aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/video
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/Kconfig321
-rw-r--r--drivers/video/Makefile10
-rw-r--r--drivers/video/acornfb.c26
-rw-r--r--drivers/video/amba-clcd.c107
-rw-r--r--drivers/video/amifb.c27
-rw-r--r--drivers/video/arcfb.c6
-rw-r--r--drivers/video/arkfb.c172
-rw-r--r--drivers/video/atafb.c4
-rw-r--r--drivers/video/atmel_lcdfb.c36
-rw-r--r--drivers/video/aty/aty128fb.c15
-rw-r--r--drivers/video/aty/atyfb_base.c53
-rw-r--r--drivers/video/aty/mach64_cursor.c2
-rw-r--r--drivers/video/aty/radeon_backlight.c3
-rw-r--r--drivers/video/aty/radeon_base.c2
-rw-r--r--drivers/video/aty/radeon_i2c.c4
-rw-r--r--drivers/video/aty/radeon_pm.c10
-rw-r--r--drivers/video/au1200fb.c4
-rw-r--r--drivers/video/backlight/88pm860x_bl.c36
-rw-r--r--drivers/video/backlight/Kconfig30
-rw-r--r--drivers/video/backlight/Makefile4
-rw-r--r--drivers/video/backlight/adp5520_bl.c7
-rw-r--r--drivers/video/backlight/adp8860_bl.c9
-rw-r--r--drivers/video/backlight/adp8870_bl.c1012
-rw-r--r--drivers/video/backlight/adx_bl.c1
-rw-r--r--drivers/video/backlight/apple_bl.c241
-rw-r--r--drivers/video/backlight/atmel-pwm-bl.c1
-rw-r--r--drivers/video/backlight/backlight.c36
-rw-r--r--drivers/video/backlight/corgi_lcd.c3
-rw-r--r--drivers/video/backlight/cr_bllcd.c2
-rw-r--r--drivers/video/backlight/da903x_bl.c1
-rw-r--r--drivers/video/backlight/ep93xx_bl.c1
-rw-r--r--drivers/video/backlight/generic_bl.c1
-rw-r--r--drivers/video/backlight/hp680_bl.c1
-rw-r--r--drivers/video/backlight/jornada720_bl.c5
-rw-r--r--drivers/video/backlight/jornada720_lcd.c4
-rw-r--r--drivers/video/backlight/kb3886_bl.c1
-rw-r--r--drivers/video/backlight/l4f00242t03.c108
-rw-r--r--drivers/video/backlight/ld9040.c819
-rw-r--r--drivers/video/backlight/ld9040_gamma.h200
-rw-r--r--drivers/video/backlight/lms283gf05.c2
-rw-r--r--drivers/video/backlight/locomolcd.c3
-rw-r--r--drivers/video/backlight/ltv350qv.c11
-rw-r--r--drivers/video/backlight/max8925_bl.c3
-rw-r--r--drivers/video/backlight/mbp_nvidia_bl.c382
-rw-r--r--drivers/video/backlight/omap1_bl.c1
-rw-r--r--drivers/video/backlight/pcf50633-backlight.c1
-rw-r--r--drivers/video/backlight/progear_bl.c1
-rw-r--r--drivers/video/backlight/pwm_bl.c19
-rw-r--r--drivers/video/backlight/s6e63m0.c8
-rw-r--r--drivers/video/backlight/tosa_bl.c1
-rw-r--r--drivers/video/backlight/wm831x_bl.c1
-rw-r--r--drivers/video/bf537-lq035.c923
-rw-r--r--drivers/video/bf54x-lq043fb.c7
-rw-r--r--drivers/video/bfin-lq035q1-fb.c4
-rw-r--r--drivers/video/bfin-t350mcqb-fb.c3
-rw-r--r--drivers/video/bfin_adv7393fb.c832
-rw-r--r--drivers/video/bfin_adv7393fb.h321
-rw-r--r--drivers/video/broadsheetfb.c4
-rw-r--r--drivers/video/bw2.c8
-rw-r--r--drivers/video/carminefb.c6
-rw-r--r--drivers/video/cg14.c9
-rw-r--r--drivers/video/cg3.c9
-rw-r--r--drivers/video/cg6.c10
-rw-r--r--drivers/video/chipsfb.c8
-rw-r--r--drivers/video/console/Kconfig2
-rw-r--r--drivers/video/console/fbcon.c48
-rw-r--r--drivers/video/console/font_mini_4x6.c2
-rw-r--r--drivers/video/console/newport_con.c2
-rw-r--r--drivers/video/console/tileblit.c2
-rw-r--r--drivers/video/console/vgacon.c10
-rw-r--r--drivers/video/cyber2000fb.c263
-rw-r--r--drivers/video/cyber2000fb.h16
-rw-r--r--drivers/video/da8xx-fb.c31
-rw-r--r--drivers/video/display/display-sysfs.c2
-rw-r--r--drivers/video/edid.h4
-rw-r--r--drivers/video/efifb.c188
-rw-r--r--drivers/video/ep93xx-fb.c8
-rw-r--r--drivers/video/epson1355fb.c2
-rw-r--r--drivers/video/fb-puv3.c852
-rw-r--r--drivers/video/fb_defio.c2
-rw-r--r--drivers/video/fbcmap.c69
-rw-r--r--drivers/video/fbcvt.c2
-rw-r--r--drivers/video/fbmem.c300
-rw-r--r--drivers/video/fbmon.c88
-rw-r--r--drivers/video/fbsysfs.c22
-rw-r--r--drivers/video/ffb.c11
-rw-r--r--drivers/video/fm2fb.c2
-rw-r--r--drivers/video/fsl-diu-fb.c27
-rw-r--r--drivers/video/gbefb.c8
-rw-r--r--drivers/video/geode/gx1fb_core.c14
-rw-r--r--drivers/video/geode/gxfb_core.c8
-rw-r--r--drivers/video/geode/lxfb.h6
-rw-r--r--drivers/video/geode/lxfb_core.c8
-rw-r--r--drivers/video/geode/lxfb_ops.c24
-rw-r--r--drivers/video/hecubafb.c10
-rw-r--r--drivers/video/hgafb.c22
-rw-r--r--drivers/video/hpfb.c6
-rw-r--r--drivers/video/i810/i810-i2c.c12
-rw-r--r--drivers/video/i810/i810.h1
-rw-r--r--drivers/video/i810/i810_accel.c2
-rw-r--r--drivers/video/i810/i810_main.c8
-rw-r--r--drivers/video/imxfb.c44
-rw-r--r--drivers/video/intelfb/Makefile5
-rw-r--r--drivers/video/intelfb/intelfb_i2c.c1
-rw-r--r--drivers/video/jz4740_fb.c8
-rw-r--r--drivers/video/kyro/STG4000OverlayDevice.c2
-rw-r--r--drivers/video/kyro/STG4000Reg.h2
-rw-r--r--drivers/video/leo.c9
-rw-r--r--drivers/video/matrox/matroxfb_DAC1064.c5
-rw-r--r--drivers/video/matrox/matroxfb_DAC1064.h2
-rw-r--r--drivers/video/matrox/matroxfb_Ti3026.c4
-rw-r--r--drivers/video/matrox/matroxfb_base.c84
-rw-r--r--drivers/video/matrox/matroxfb_base.h2
-rw-r--r--drivers/video/matrox/matroxfb_maven.c2
-rw-r--r--drivers/video/mb862xx/Makefile5
-rw-r--r--drivers/video/mb862xx/mb862xx-i2c.c178
-rw-r--r--drivers/video/mb862xx/mb862xx_reg.h58
-rw-r--r--drivers/video/mb862xx/mb862xxfb.h36
-rw-r--r--drivers/video/mb862xx/mb862xxfbdrv.c (renamed from drivers/video/mb862xx/mb862xxfb.c)162
-rw-r--r--drivers/video/mbx/mbxdebugfs.c6
-rw-r--r--drivers/video/metronomefb.c8
-rw-r--r--drivers/video/modedb.c447
-rw-r--r--drivers/video/msm/mddi.c7
-rw-r--r--drivers/video/msm/mdp.c3
-rw-r--r--drivers/video/msm/mdp_hw.h11
-rw-r--r--drivers/video/msm/mdp_ppp.c1
-rw-r--r--drivers/video/msm/msm_fb.c27
-rw-r--r--drivers/video/mx3fb.c15
-rw-r--r--drivers/video/mxsfb.c919
-rw-r--r--drivers/video/nuc900fb.c11
-rw-r--r--drivers/video/nuc900fb.h2
-rw-r--r--drivers/video/nvidia/nv_backlight.c3
-rw-r--r--drivers/video/nvidia/nvidia.c8
-rw-r--r--drivers/video/omap/Kconfig13
-rw-r--r--drivers/video/omap/Makefile1
-rw-r--r--drivers/video/omap/blizzard.c5
-rw-r--r--drivers/video/omap/dispc.c4
-rw-r--r--drivers/video/omap/hwa742.c3
-rw-r--r--drivers/video/omap/lcd_mipid.c2
-rw-r--r--drivers/video/omap/lcd_omap2evm.c192
-rw-r--r--drivers/video/omap/lcd_omap3beagle.c2
-rw-r--r--drivers/video/omap/omapfb_main.c2
-rw-r--r--drivers/video/omap/rfbi.c2
-rw-r--r--drivers/video/omap2/Makefile4
-rw-r--r--drivers/video/omap2/displays/Kconfig40
-rw-r--r--drivers/video/omap2/displays/Makefile6
-rw-r--r--drivers/video/omap2/displays/panel-acx565akm.c9
-rw-r--r--drivers/video/omap2/displays/panel-generic-dpi.c441
-rw-r--r--drivers/video/omap2/displays/panel-generic.c168
-rw-r--r--drivers/video/omap2/displays/panel-lgphilips-lb035q02.c279
-rw-r--r--drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c325
-rw-r--r--drivers/video/omap2/displays/panel-sharp-lq043t1dg01.c159
-rw-r--r--drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c13
-rw-r--r--drivers/video/omap2/displays/panel-taal.c631
-rw-r--r--drivers/video/omap2/displays/panel-toppoly-tdo35s.c158
-rw-r--r--drivers/video/omap2/displays/panel-tpo-td043mtea1.c16
-rw-r--r--drivers/video/omap2/dss/Kconfig47
-rw-r--r--drivers/video/omap2/dss/Makefile4
-rw-r--r--drivers/video/omap2/dss/core.c496
-rw-r--r--drivers/video/omap2/dss/dispc.c2467
-rw-r--r--drivers/video/omap2/dss/dispc.h691
-rw-r--r--drivers/video/omap2/dss/display.c81
-rw-r--r--drivers/video/omap2/dss/dpi.c180
-rw-r--r--drivers/video/omap2/dss/dsi.c2938
-rw-r--r--drivers/video/omap2/dss/dss.c831
-rw-r--r--drivers/video/omap2/dss/dss.h246
-rw-r--r--drivers/video/omap2/dss/dss_features.c433
-rw-r--r--drivers/video/omap2/dss/dss_features.h96
-rw-r--r--drivers/video/omap2/dss/hdmi.c1763
-rw-r--r--drivers/video/omap2/dss/hdmi.h631
-rw-r--r--drivers/video/omap2/dss/hdmi_omap4_panel.c222
-rw-r--r--drivers/video/omap2/dss/manager.c138
-rw-r--r--drivers/video/omap2/dss/overlay.c128
-rw-r--r--drivers/video/omap2/dss/rfbi.c310
-rw-r--r--drivers/video/omap2/dss/sdi.c86
-rw-r--r--drivers/video/omap2/dss/venc.c151
-rw-r--r--drivers/video/omap2/omapfb/Kconfig8
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c14
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c277
-rw-r--r--drivers/video/omap2/omapfb/omapfb-sysfs.c23
-rw-r--r--drivers/video/omap2/omapfb/omapfb.h8
-rw-r--r--drivers/video/omap2/vram.c21
-rw-r--r--drivers/video/p9100.c8
-rw-r--r--drivers/video/platinumfb.c9
-rw-r--r--drivers/video/ps3fb.c16
-rw-r--r--drivers/video/pxa168fb.c70
-rw-r--r--drivers/video/pxa3xx-gcu.c772
-rw-r--r--drivers/video/pxa3xx-gcu.h38
-rw-r--r--drivers/video/pxafb.c138
-rw-r--r--drivers/video/pxafb.h3
-rw-r--r--drivers/video/q40fb.c4
-rw-r--r--drivers/video/riva/fbdev.c3
-rw-r--r--drivers/video/riva/rivafb-i2c.c1
-rw-r--r--drivers/video/s1d13xxxfb.c50
-rw-r--r--drivers/video/s3c-fb.c255
-rw-r--r--drivers/video/s3c2410fb.c13
-rw-r--r--drivers/video/s3fb.c610
-rw-r--r--drivers/video/savage/savagefb-i2c.c25
-rw-r--r--drivers/video/savage/savagefb.h11
-rw-r--r--drivers/video/savage/savagefb_driver.c43
-rw-r--r--drivers/video/sh7760fb.c10
-rw-r--r--drivers/video/sh_mipi_dsi.c161
-rw-r--r--drivers/video/sh_mobile_hdmi.c849
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c754
-rw-r--r--drivers/video/sh_mobile_lcdcfb.h45
-rw-r--r--drivers/video/sh_mobile_meram.c567
-rw-r--r--drivers/video/sh_mobile_meram.h41
-rw-r--r--drivers/video/sis/init.c719
-rw-r--r--drivers/video/sis/init.h76
-rw-r--r--drivers/video/sis/init301.c475
-rw-r--r--drivers/video/sis/init301.h54
-rw-r--r--drivers/video/sis/initextlfb.c7
-rw-r--r--drivers/video/sis/osdef.h133
-rw-r--r--drivers/video/sis/sis.h67
-rw-r--r--drivers/video/sis/sis_main.c1463
-rw-r--r--drivers/video/sis/vgatypes.h12
-rw-r--r--drivers/video/sis/vstruct.h12
-rw-r--r--drivers/video/sm501fb.c313
-rw-r--r--drivers/video/sstfb.c10
-rw-r--r--drivers/video/sticore.h2
-rw-r--r--drivers/video/sunxvr1000.c9
-rw-r--r--drivers/video/svgalib.c175
-rw-r--r--drivers/video/tcx.c10
-rw-r--r--drivers/video/tdfxfb.c18
-rw-r--r--drivers/video/tmiofb.c38
-rw-r--r--drivers/video/udlfb.c1897
-rw-r--r--drivers/video/uvesafb.c51
-rw-r--r--drivers/video/vermilion/vermilion.c3
-rw-r--r--drivers/video/vesafb.c47
-rw-r--r--drivers/video/vga16fb.c4
-rw-r--r--drivers/video/via/Makefile4
-rw-r--r--drivers/video/via/accel.c55
-rw-r--r--drivers/video/via/accel.h3
-rw-r--r--drivers/video/via/chip.h19
-rw-r--r--drivers/video/via/dvi.c329
-rw-r--r--drivers/video/via/dvi.h4
-rw-r--r--drivers/video/via/global.c4
-rw-r--r--drivers/video/via/global.h3
-rw-r--r--drivers/video/via/hw.c1463
-rw-r--r--drivers/video/via/hw.h73
-rw-r--r--drivers/video/via/ioctl.c2
-rw-r--r--drivers/video/via/lcd.c182
-rw-r--r--drivers/video/via/lcd.h6
-rw-r--r--drivers/video/via/lcdtbl.h591
-rw-r--r--drivers/video/via/share.h158
-rw-r--r--drivers/video/via/tbl1636.c71
-rw-r--r--drivers/video/via/tbl1636.h34
-rw-r--r--drivers/video/via/tblDPASetting.c23
-rw-r--r--drivers/video/via/tblDPASetting.h2
-rw-r--r--drivers/video/via/via-core.c133
-rw-r--r--drivers/video/via/via-gpio.c74
-rw-r--r--drivers/video/via/via_clock.c349
-rw-r--r--drivers/video/via/via_clock.h76
-rw-r--r--drivers/video/via/via_i2c.c34
-rw-r--r--drivers/video/via/via_utility.c2
-rw-r--r--drivers/video/via/via_utility.h2
-rw-r--r--drivers/video/via/viafbdev.c434
-rw-r--r--drivers/video/via/viafbdev.h12
-rw-r--r--drivers/video/via/viamode.c547
-rw-r--r--drivers/video/via/viamode.h18
-rw-r--r--drivers/video/via/vt1636.c164
-rw-r--r--drivers/video/vt8500lcdfb.c475
-rw-r--r--drivers/video/vt8500lcdfb.h34
-rw-r--r--drivers/video/vt8623fb.c169
-rw-r--r--drivers/video/w100fb.c2
-rw-r--r--drivers/video/wm8505fb.c422
-rw-r--r--drivers/video/wm8505fb_regs.h76
-rw-r--r--drivers/video/wmt_ge_rops.c186
-rw-r--r--drivers/video/wmt_ge_rops.h5
-rw-r--r--drivers/video/xen-fbfront.c30
-rw-r--r--drivers/video/xilinxfb.c35
271 files changed, 29819 insertions, 11405 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 8b31fdfefc98..549b960667c8 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -8,7 +8,11 @@ menu "Graphics support"
8config HAVE_FB_ATMEL 8config HAVE_FB_ATMEL
9 bool 9 bool
10 10
11config HAVE_FB_IMX 11config SH_MIPI_DSI
12 tristate
13 depends on (SUPERH || ARCH_SHMOBILE) && HAVE_CLK
14
15config SH_LCD_MIPI_DSI
12 bool 16 bool
13 17
14source "drivers/char/agp/Kconfig" 18source "drivers/char/agp/Kconfig"
@@ -17,6 +21,8 @@ source "drivers/gpu/vga/Kconfig"
17 21
18source "drivers/gpu/drm/Kconfig" 22source "drivers/gpu/drm/Kconfig"
19 23
24source "drivers/gpu/stub/Kconfig"
25
20config VGASTATE 26config VGASTATE
21 tristate 27 tristate
22 default n 28 default n
@@ -49,7 +55,7 @@ menuconfig FB
49 You need an utility program called fbset to make full use of frame 55 You need an utility program called fbset to make full use of frame
50 buffer devices. Please read <file:Documentation/fb/framebuffer.txt> 56 buffer devices. Please read <file:Documentation/fb/framebuffer.txt>
51 and the Framebuffer-HOWTO at 57 and the Framebuffer-HOWTO at
52 <http://www.munted.org.uk/programming/Framebuffer-HOWTO-1.2.html> for more 58 <http://www.munted.org.uk/programming/Framebuffer-HOWTO-1.3.html> for more
53 information. 59 information.
54 60
55 Say Y here and to the driver for your graphics board below if you 61 Say Y here and to the driver for your graphics board below if you
@@ -184,6 +190,14 @@ config FB_SYS_FOPS
184 depends on FB 190 depends on FB
185 default n 191 default n
186 192
193config FB_WMT_GE_ROPS
194 tristate
195 depends on FB
196 default n
197 ---help---
198 Include functions for accelerated rectangle filling and area
199 copying using WonderMedia Graphics Engine operations.
200
187config FB_DEFERRED_IO 201config FB_DEFERRED_IO
188 bool 202 bool
189 depends on FB 203 depends on FB
@@ -305,69 +319,6 @@ config FB_ARMCLCD
305 here and read <file:Documentation/kbuild/modules.txt>. The module 319 here and read <file:Documentation/kbuild/modules.txt>. The module
306 will be called amba-clcd. 320 will be called amba-clcd.
307 321
308choice
309
310 depends on FB_ARMCLCD && (ARCH_LH7A40X || ARCH_LH7952X)
311 prompt "LCD Panel"
312 default FB_ARMCLCD_SHARP_LQ035Q7DB02
313
314config FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT
315 bool "LogicPD LCD 3.5\" QVGA w/HRTFT IC"
316 help
317 This is an implementation of the Sharp LQ035Q7DB02, a 3.5"
318 color QVGA, HRTFT panel. The LogicPD device includes
319 an integrated HRTFT controller IC.
320 The native resolution is 240x320.
321
322config FB_ARMCLCD_SHARP_LQ057Q3DC02
323 bool "LogicPD LCD 5.7\" QVGA"
324 help
325 This is an implementation of the Sharp LQ057Q3DC02, a 5.7"
326 color QVGA, TFT panel. The LogicPD device includes an
327 The native resolution is 320x240.
328
329config FB_ARMCLCD_SHARP_LQ64D343
330 bool "LogicPD LCD 6.4\" VGA"
331 help
332 This is an implementation of the Sharp LQ64D343, a 6.4"
333 color VGA, TFT panel. The LogicPD device includes an
334 The native resolution is 640x480.
335
336config FB_ARMCLCD_SHARP_LQ10D368
337 bool "LogicPD LCD 10.4\" VGA"
338 help
339 This is an implementation of the Sharp LQ10D368, a 10.4"
340 color VGA, TFT panel. The LogicPD device includes an
341 The native resolution is 640x480.
342
343
344config FB_ARMCLCD_SHARP_LQ121S1DG41
345 bool "LogicPD LCD 12.1\" SVGA"
346 help
347 This is an implementation of the Sharp LQ121S1DG41, a 12.1"
348 color SVGA, TFT panel. The LogicPD device includes an
349 The native resolution is 800x600.
350
351 This panel requires a clock rate may be an integer fraction
352 of the base LCDCLK frequency. The driver will select the
353 highest frequency available that is lower than the maximum
354 allowed. The panel may flicker if the clock rate is
355 slower than the recommended minimum.
356
357config FB_ARMCLCD_AUO_A070VW01_WIDE
358 bool "AU Optronics A070VW01 LCD 7.0\" WIDE"
359 help
360 This is an implementation of the AU Optronics, a 7.0"
361 WIDE Color. The native resolution is 234x480.
362
363config FB_ARMCLCD_HITACHI
364 bool "Hitachi Wide Screen 800x480"
365 help
366 This is an implementation of the Hitachi 800x480.
367
368endchoice
369
370
371config FB_ACORN 322config FB_ACORN
372 bool "Acorn VIDC support" 323 bool "Acorn VIDC support"
373 depends on (FB = y) && ARM && ARCH_ACORN 324 depends on (FB = y) && ARM && ARCH_ACORN
@@ -404,8 +355,8 @@ config FB_SA1100
404 Y here. 355 Y here.
405 356
406config FB_IMX 357config FB_IMX
407 tristate "Motorola i.MX LCD support" 358 tristate "Freescale i.MX LCD support"
408 depends on FB && (HAVE_FB_IMX || ARCH_MX1 || ARCH_MX2) 359 depends on FB && IMX_HAVE_PLATFORM_IMX_FB
409 select FB_CFB_FILLRECT 360 select FB_CFB_FILLRECT
410 select FB_CFB_COPYAREA 361 select FB_CFB_COPYAREA
411 select FB_CFB_IMAGEBLIT 362 select FB_CFB_IMAGEBLIT
@@ -422,6 +373,24 @@ config FB_CYBER2000
422 Say Y if you have a NetWinder or a graphics card containing this 373 Say Y if you have a NetWinder or a graphics card containing this
423 device, otherwise say N. 374 device, otherwise say N.
424 375
376config FB_CYBER2000_DDC
377 bool "DDC for CyberPro support"
378 depends on FB_CYBER2000
379 select FB_DDC
380 default y
381 help
382 Say Y here if you want DDC support for your CyberPro graphics
383 card. This is only I2C bus support, driver does not use EDID.
384
385config FB_CYBER2000_I2C
386 bool "CyberPro 2000/2010/5000 I2C support"
387 depends on FB_CYBER2000 && I2C && ARCH_NETWINDER
388 select I2C_ALGOBIT
389 help
390 Enable support for the I2C video decoder interface on the
391 Integraphics CyberPro 20x0 and 5000 VGA chips. This is used
392 on the Netwinder machines for the SAA7111 video capture.
393
425config FB_APOLLO 394config FB_APOLLO
426 bool 395 bool
427 depends on (FB = y) && APOLLO 396 depends on (FB = y) && APOLLO
@@ -633,6 +602,72 @@ config FB_BFIN_LQ035Q1
633 To compile this driver as a module, choose M here: the 602 To compile this driver as a module, choose M here: the
634 module will be called bfin-lq035q1-fb. 603 module will be called bfin-lq035q1-fb.
635 604
605config FB_BF537_LQ035
606 tristate "SHARP LQ035 TFT LCD (BF537 STAMP)"
607 depends on FB && (BF534 || BF536 || BF537) && I2C_BLACKFIN_TWI
608 select FB_CFB_FILLRECT
609 select FB_CFB_COPYAREA
610 select FB_CFB_IMAGEBLIT
611 select BFIN_GPTIMERS
612 help
613 This is the framebuffer device for a SHARP LQ035Q7DB03 TFT LCD
614 attached to a BF537.
615
616 To compile this driver as a module, choose M here: the
617 module will be called bf537-lq035.
618
619config FB_BFIN_7393
620 tristate "Blackfin ADV7393 Video encoder"
621 depends on FB && BLACKFIN
622 select I2C
623 select FB_CFB_FILLRECT
624 select FB_CFB_COPYAREA
625 select FB_CFB_IMAGEBLIT
626 help
627 This is the framebuffer device for a ADV7393 video encoder
628 attached to a Blackfin on the PPI port.
629 If your Blackfin board has a ADV7393 select Y.
630
631 To compile this driver as a module, choose M here: the
632 module will be called bfin_adv7393fb.
633
634choice
635 prompt "Video mode support"
636 depends on FB_BFIN_7393
637 default NTSC
638
639config NTSC
640 bool 'NTSC 720x480'
641
642config PAL
643 bool 'PAL 720x576'
644
645config NTSC_640x480
646 bool 'NTSC 640x480 (Experimental)'
647
648config PAL_640x480
649 bool 'PAL 640x480 (Experimental)'
650
651config NTSC_YCBCR
652 bool 'NTSC 720x480 YCbCR input'
653
654config PAL_YCBCR
655 bool 'PAL 720x576 YCbCR input'
656
657endchoice
658
659choice
660 prompt "Size of ADV7393 frame buffer memory Single/Double Size"
661 depends on (FB_BFIN_7393)
662 default ADV7393_1XMEM
663
664config ADV7393_1XMEM
665 bool 'Single'
666
667config ADV7393_2XMEM
668 bool 'Double'
669endchoice
670
636config FB_STI 671config FB_STI
637 tristate "HP STI frame buffer device support" 672 tristate "HP STI frame buffer device support"
638 depends on FB && PARISC 673 depends on FB && PARISC
@@ -748,24 +783,14 @@ config FB_N411
748config FB_HGA 783config FB_HGA
749 tristate "Hercules mono graphics support" 784 tristate "Hercules mono graphics support"
750 depends on FB && X86 785 depends on FB && X86
751 select FB_CFB_FILLRECT
752 select FB_CFB_COPYAREA
753 select FB_CFB_IMAGEBLIT
754 help 786 help
755 Say Y here if you have a Hercules mono graphics card. 787 Say Y here if you have a Hercules mono graphics card.
756 788
757 To compile this driver as a module, choose M here: the 789 To compile this driver as a module, choose M here: the
758 module will be called hgafb. 790 module will be called hgafb.
759 791
760 As this card technology is 15 years old, most people will answer N 792 As this card technology is at least 25 years old,
761 here. 793 most people will answer N here.
762
763config FB_HGA_ACCEL
764 bool "Hercules mono Acceleration functions (EXPERIMENTAL)"
765 depends on FB_HGA && EXPERIMENTAL
766 ---help---
767 This will compile the Hercules mono graphics with
768 acceleration functions.
769 794
770config FB_SGIVW 795config FB_SGIVW
771 tristate "SGI Visual Workstation framebuffer support" 796 tristate "SGI Visual Workstation framebuffer support"
@@ -955,7 +980,7 @@ config FB_EPSON1355
955 Build in support for the SED1355 Epson Research Embedded RAMDAC 980 Build in support for the SED1355 Epson Research Embedded RAMDAC
956 LCD/CRT Controller (since redesignated as the S1D13505) as a 981 LCD/CRT Controller (since redesignated as the S1D13505) as a
957 framebuffer. Product specs at 982 framebuffer. Product specs at
958 <http://www.erd.epson.com/vdc/html/products.htm>. 983 <http://vdc.epson.com/>.
959 984
960config FB_S1D13XXX 985config FB_S1D13XXX
961 tristate "Epson S1D13XXX framebuffer support" 986 tristate "Epson S1D13XXX framebuffer support"
@@ -966,7 +991,7 @@ config FB_S1D13XXX
966 help 991 help
967 Support for S1D13XXX framebuffer device family (currently only 992 Support for S1D13XXX framebuffer device family (currently only
968 working with S1D13806). Product specs at 993 working with S1D13806). Product specs at
969 <http://www.erd.epson.com/vdc/html/legacy_13xxx.htm> 994 <http://vdc.epson.com/>
970 995
971config FB_ATMEL 996config FB_ATMEL
972 tristate "AT91/AT32 LCD Controller support" 997 tristate "AT91/AT32 LCD Controller support"
@@ -1154,7 +1179,7 @@ config FB_CARILLO_RANCH
1154 1179
1155config FB_INTEL 1180config FB_INTEL
1156 tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G/945GM/965G/965GM support (EXPERIMENTAL)" 1181 tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G/945GM/965G/965GM support (EXPERIMENTAL)"
1157 depends on EXPERIMENTAL && FB && PCI && X86 && AGP_INTEL && EMBEDDED 1182 depends on EXPERIMENTAL && FB && PCI && X86 && AGP_INTEL && EXPERT
1158 select FB_MODE_HELPERS 1183 select FB_MODE_HELPERS
1159 select FB_CFB_FILLRECT 1184 select FB_CFB_FILLRECT
1160 select FB_CFB_COPYAREA 1185 select FB_CFB_COPYAREA
@@ -1207,7 +1232,7 @@ config FB_MATROX
1207 module will be called matroxfb. 1232 module will be called matroxfb.
1208 1233
1209 You can pass several parameters to the driver at boot time or at 1234 You can pass several parameters to the driver at boot time or at
1210 module load time. The parameters look like "video=matrox:XXX", and 1235 module load time. The parameters look like "video=matroxfb:XXX", and
1211 are described in <file:Documentation/fb/matroxfb.txt>. 1236 are described in <file:Documentation/fb/matroxfb.txt>.
1212 1237
1213config FB_MATROX_MILLENIUM 1238config FB_MATROX_MILLENIUM
@@ -1323,7 +1348,7 @@ config FB_RADEON
1323 don't need to choose this to run the Radeon in plain VGA mode. 1348 don't need to choose this to run the Radeon in plain VGA mode.
1324 1349
1325 There is a product page at 1350 There is a product page at
1326 http://apps.ati.com/ATIcompare/ 1351 http://products.amd.com/en-us/GraphicCardResult.aspx
1327 1352
1328config FB_RADEON_I2C 1353config FB_RADEON_I2C
1329 bool "DDC/I2C for ATI Radeon support" 1354 bool "DDC/I2C for ATI Radeon support"
@@ -1395,7 +1420,7 @@ config FB_ATY_CT
1395 Say Y here to support use of ATI's 64-bit Rage boards (or other 1420 Say Y here to support use of ATI's 64-bit Rage boards (or other
1396 boards based on the Mach64 CT, VT, GT, and LT chipsets) as a 1421 boards based on the Mach64 CT, VT, GT, and LT chipsets) as a
1397 framebuffer device. The ATI product support page for these boards 1422 framebuffer device. The ATI product support page for these boards
1398 is at <http://support.ati.com/products/pc/mach64/>. 1423 is at <http://support.ati.com/products/pc/mach64/mach64.html>.
1399 1424
1400config FB_ATY_GENERIC_LCD 1425config FB_ATY_GENERIC_LCD
1401 bool "Mach64 generic LCD support (EXPERIMENTAL)" 1426 bool "Mach64 generic LCD support (EXPERIMENTAL)"
@@ -1435,6 +1460,14 @@ config FB_S3
1435 ---help--- 1460 ---help---
1436 Driver for graphics boards with S3 Trio / S3 Virge chip. 1461 Driver for graphics boards with S3 Trio / S3 Virge chip.
1437 1462
1463config FB_S3_DDC
1464 bool "DDC for S3 support"
1465 depends on FB_S3
1466 select FB_DDC
1467 default y
1468 help
1469 Say Y here if you want DDC support for your S3 graphics card.
1470
1438config FB_SAVAGE 1471config FB_SAVAGE
1439 tristate "S3 Savage support" 1472 tristate "S3 Savage support"
1440 depends on FB && PCI && EXPERIMENTAL 1473 depends on FB && PCI && EXPERIMENTAL
@@ -1534,6 +1567,17 @@ config FB_VIA_DIRECT_PROCFS
1534 correct output device configuration. 1567 correct output device configuration.
1535 Its use is strongly discouraged. 1568 Its use is strongly discouraged.
1536 1569
1570config FB_VIA_X_COMPATIBILITY
1571 bool "X server compatibility"
1572 depends on FB_VIA
1573 default n
1574 help
1575 This option reduces the functionality (power saving, ...) of the
1576 framebuffer to avoid negative impact on the OpenChrome X server.
1577 If you use any X server other than fbdev you should enable this
1578 otherwise it should be safe to disable it and allow using all
1579 features.
1580
1537endif 1581endif
1538 1582
1539config FB_NEOMAGIC 1583config FB_NEOMAGIC
@@ -1720,6 +1764,24 @@ config FB_AU1200
1720 various panels and CRTs by passing in kernel cmd line option 1764 various panels and CRTs by passing in kernel cmd line option
1721 au1200fb:panel=<name>. 1765 au1200fb:panel=<name>.
1722 1766
1767config FB_VT8500
1768 bool "VT8500 LCD Driver"
1769 depends on (FB = y) && ARM && ARCH_VT8500 && VTWM_VERSION_VT8500
1770 select FB_WMT_GE_ROPS
1771 select FB_SYS_IMAGEBLIT
1772 help
1773 This is the framebuffer driver for VIA VT8500 integrated LCD
1774 controller.
1775
1776config FB_WM8505
1777 bool "WM8505 frame buffer support"
1778 depends on (FB = y) && ARM && ARCH_VT8500 && VTWM_VERSION_WM8505
1779 select FB_WMT_GE_ROPS
1780 select FB_SYS_IMAGEBLIT
1781 help
1782 This is the framebuffer driver for WonderMedia WM8505
1783 integrated LCD controller.
1784
1723source "drivers/video/geode/Kconfig" 1785source "drivers/video/geode/Kconfig"
1724 1786
1725config FB_HIT 1787config FB_HIT
@@ -1848,6 +1910,16 @@ config FB_PXA_PARAMETERS
1848 1910
1849 <file:Documentation/fb/pxafb.txt> describes the available parameters. 1911 <file:Documentation/fb/pxafb.txt> describes the available parameters.
1850 1912
1913config PXA3XX_GCU
1914 tristate "PXA3xx 2D graphics accelerator driver"
1915 depends on FB_PXA
1916 help
1917 Kernelspace driver for the 2D graphics controller unit (GCU)
1918 found on PXA3xx processors. There is a counterpart driver in the
1919 DirectFB suite, see http://www.directfb.org/
1920
1921 If you compile this as a module, it will be called pxa3xx_gcu.
1922
1851config FB_MBX 1923config FB_MBX
1852 tristate "2700G LCD framebuffer support" 1924 tristate "2700G LCD framebuffer support"
1853 depends on FB && ARCH_PXA 1925 depends on FB && ARCH_PXA
@@ -1896,13 +1968,6 @@ config FB_W100
1896 1968
1897 If unsure, say N. 1969 If unsure, say N.
1898 1970
1899config SH_MIPI_DSI
1900 tristate
1901 depends on (SUPERH || ARCH_SHMOBILE) && HAVE_CLK
1902
1903config SH_LCD_MIPI_DSI
1904 bool
1905
1906config FB_SH_MOBILE_LCDC 1971config FB_SH_MOBILE_LCDC
1907 tristate "SuperH Mobile LCDC framebuffer support" 1972 tristate "SuperH Mobile LCDC framebuffer support"
1908 depends on FB && (SUPERH || ARCH_SHMOBILE) && HAVE_CLK 1973 depends on FB && (SUPERH || ARCH_SHMOBILE) && HAVE_CLK
@@ -1911,6 +1976,7 @@ config FB_SH_MOBILE_LCDC
1911 select FB_SYS_IMAGEBLIT 1976 select FB_SYS_IMAGEBLIT
1912 select FB_SYS_FOPS 1977 select FB_SYS_FOPS
1913 select FB_DEFERRED_IO 1978 select FB_DEFERRED_IO
1979 select FB_BACKLIGHT
1914 select SH_MIPI_DSI if SH_LCD_MIPI_DSI 1980 select SH_MIPI_DSI if SH_LCD_MIPI_DSI
1915 ---help--- 1981 ---help---
1916 Frame buffer driver for the on-chip SH-Mobile LCD controller. 1982 Frame buffer driver for the on-chip SH-Mobile LCD controller.
@@ -1919,9 +1985,24 @@ config FB_SH_MOBILE_HDMI
1919 tristate "SuperH Mobile HDMI controller support" 1985 tristate "SuperH Mobile HDMI controller support"
1920 depends on FB_SH_MOBILE_LCDC 1986 depends on FB_SH_MOBILE_LCDC
1921 select FB_MODE_HELPERS 1987 select FB_MODE_HELPERS
1988 select SOUND
1989 select SND
1990 select SND_SOC
1922 ---help--- 1991 ---help---
1923 Driver for the on-chip SH-Mobile HDMI controller. 1992 Driver for the on-chip SH-Mobile HDMI controller.
1924 1993
1994config FB_SH_MOBILE_MERAM
1995 tristate "SuperH Mobile MERAM read ahead support for LCDC"
1996 depends on FB_SH_MOBILE_LCDC
1997 default y
1998 ---help---
1999 Enable MERAM support for the SH-Mobile LCD controller.
2000
2001 This will allow for caching of the framebuffer to provide more
2002 reliable access under heavy main memory bus traffic situations.
2003 Up to 4 memory channels can be configured, allowing 4 RGB or
2004 2 YCbCr framebuffers to be configured.
2005
1925config FB_TMIO 2006config FB_TMIO
1926 tristate "Toshiba Mobile IO FrameBuffer support" 2007 tristate "Toshiba Mobile IO FrameBuffer support"
1927 depends on FB && MFD_CORE 2008 depends on FB && MFD_CORE
@@ -2029,6 +2110,20 @@ config FB_SM501
2029 2110
2030 If unsure, say N. 2111 If unsure, say N.
2031 2112
2113config FB_UDL
2114 tristate "Displaylink USB Framebuffer support"
2115 depends on FB && USB
2116 select FB_MODE_HELPERS
2117 select FB_SYS_FILLRECT
2118 select FB_SYS_COPYAREA
2119 select FB_SYS_IMAGEBLIT
2120 select FB_SYS_FOPS
2121 select FB_DEFERRED_IO
2122 ---help---
2123 This is a kernel framebuffer driver for DisplayLink USB devices.
2124 Supports fbdev clients like xf86-video-fbdev, kdrive, fbi, and
2125 mplayer -vo fbdev. Supports all USB 2.0 era DisplayLink devices.
2126 To compile as a module, choose M here: the module name is udlfb.
2032 2127
2033config FB_PNX4008_DUM 2128config FB_PNX4008_DUM
2034 tristate "Display Update Module support on Philips PNX4008 board" 2129 tristate "Display Update Module support on Philips PNX4008 board"
@@ -2171,29 +2266,43 @@ config FB_METRONOME
2171config FB_MB862XX 2266config FB_MB862XX
2172 tristate "Fujitsu MB862xx GDC support" 2267 tristate "Fujitsu MB862xx GDC support"
2173 depends on FB 2268 depends on FB
2269 depends on PCI || (OF && PPC)
2174 select FB_CFB_FILLRECT 2270 select FB_CFB_FILLRECT
2175 select FB_CFB_COPYAREA 2271 select FB_CFB_COPYAREA
2176 select FB_CFB_IMAGEBLIT 2272 select FB_CFB_IMAGEBLIT
2177 ---help--- 2273 ---help---
2178 Frame buffer driver for Fujitsu Carmine/Coral-P(A)/Lime controllers. 2274 Frame buffer driver for Fujitsu Carmine/Coral-P(A)/Lime controllers.
2179 2275
2276choice
2277 prompt "GDC variant"
2278 depends on FB_MB862XX
2279
2180config FB_MB862XX_PCI_GDC 2280config FB_MB862XX_PCI_GDC
2181 bool "Carmine/Coral-P(A) GDC" 2281 bool "Carmine/Coral-P(A) GDC"
2182 depends on PCI && FB_MB862XX 2282 depends on PCI
2183 ---help--- 2283 ---help---
2184 This enables framebuffer support for Fujitsu Carmine/Coral-P(A) 2284 This enables framebuffer support for Fujitsu Carmine/Coral-P(A)
2185 PCI graphics controller devices. 2285 PCI graphics controller devices.
2186 2286
2187config FB_MB862XX_LIME 2287config FB_MB862XX_LIME
2188 bool "Lime GDC" 2288 bool "Lime GDC"
2189 depends on FB_MB862XX 2289 depends on OF && PPC
2190 depends on OF && !FB_MB862XX_PCI_GDC
2191 depends on PPC
2192 select FB_FOREIGN_ENDIAN 2290 select FB_FOREIGN_ENDIAN
2193 select FB_LITTLE_ENDIAN 2291 select FB_LITTLE_ENDIAN
2194 ---help--- 2292 ---help---
2195 Framebuffer support for Fujitsu Lime GDC on host CPU bus. 2293 Framebuffer support for Fujitsu Lime GDC on host CPU bus.
2196 2294
2295endchoice
2296
2297config FB_MB862XX_I2C
2298 bool "Support I2C bus on MB862XX GDC"
2299 depends on FB_MB862XX && I2C
2300 default y
2301 help
2302 Selecting this option adds Coral-P(A)/Lime GDC I2C bus adapter
2303 driver to support accessing I2C devices on controller's I2C bus.
2304 These are usually some video decoder chips.
2305
2197config FB_EP93XX 2306config FB_EP93XX
2198 tristate "EP93XX frame buffer support" 2307 tristate "EP93XX frame buffer support"
2199 depends on FB && ARCH_EP93XX 2308 depends on FB && ARCH_EP93XX
@@ -2254,6 +2363,26 @@ config FB_JZ4740
2254 help 2363 help
2255 Framebuffer support for the JZ4740 SoC. 2364 Framebuffer support for the JZ4740 SoC.
2256 2365
2366config FB_MXS
2367 tristate "MXS LCD framebuffer support"
2368 depends on FB && ARCH_MXS
2369 select FB_CFB_FILLRECT
2370 select FB_CFB_COPYAREA
2371 select FB_CFB_IMAGEBLIT
2372 help
2373 Framebuffer support for the MXS SoC.
2374
2375config FB_PUV3_UNIGFX
2376 tristate "PKUnity v3 Unigfx framebuffer support"
2377 depends on FB && UNICORE32 && ARCH_PUV3
2378 select FB_SYS_FILLRECT
2379 select FB_SYS_COPYAREA
2380 select FB_SYS_IMAGEBLIT
2381 select FB_SYS_FOPS
2382 help
2383 Choose this option if you want to use the Unigfx device as a
2384 framebuffer device. Without the support of PCI & AGP.
2385
2257source "drivers/video/omap/Kconfig" 2386source "drivers/video/omap/Kconfig"
2258source "drivers/video/omap2/Kconfig" 2387source "drivers/video/omap2/Kconfig"
2259 2388
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 485e8ed1318c..8b83129e209c 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_FB_SVGALIB) += svgalib.o
26obj-$(CONFIG_FB_MACMODES) += macmodes.o 26obj-$(CONFIG_FB_MACMODES) += macmodes.o
27obj-$(CONFIG_FB_DDC) += fb_ddc.o 27obj-$(CONFIG_FB_DDC) += fb_ddc.o
28obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o 28obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o
29obj-$(CONFIG_FB_WMT_GE_ROPS) += wmt_ge_rops.o
29 30
30# Hardware specific drivers go first 31# Hardware specific drivers go first
31obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o 32obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o
@@ -100,10 +101,13 @@ obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o
100obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o 101obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o
101obj-$(CONFIG_FB_PXA) += pxafb.o 102obj-$(CONFIG_FB_PXA) += pxafb.o
102obj-$(CONFIG_FB_PXA168) += pxa168fb.o 103obj-$(CONFIG_FB_PXA168) += pxa168fb.o
104obj-$(CONFIG_PXA3XX_GCU) += pxa3xx-gcu.o
103obj-$(CONFIG_FB_W100) += w100fb.o 105obj-$(CONFIG_FB_W100) += w100fb.o
104obj-$(CONFIG_FB_TMIO) += tmiofb.o 106obj-$(CONFIG_FB_TMIO) += tmiofb.o
105obj-$(CONFIG_FB_AU1100) += au1100fb.o 107obj-$(CONFIG_FB_AU1100) += au1100fb.o
106obj-$(CONFIG_FB_AU1200) += au1200fb.o 108obj-$(CONFIG_FB_AU1200) += au1200fb.o
109obj-$(CONFIG_FB_VT8500) += vt8500lcdfb.o
110obj-$(CONFIG_FB_WM8505) += wm8505fb.o
107obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o 111obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o
108obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o 112obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o
109obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o 113obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o
@@ -122,9 +126,11 @@ obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx4008/
122obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o 126obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
123obj-$(CONFIG_FB_PS3) += ps3fb.o 127obj-$(CONFIG_FB_PS3) += ps3fb.o
124obj-$(CONFIG_FB_SM501) += sm501fb.o 128obj-$(CONFIG_FB_SM501) += sm501fb.o
129obj-$(CONFIG_FB_UDL) += udlfb.o
125obj-$(CONFIG_FB_XILINX) += xilinxfb.o 130obj-$(CONFIG_FB_XILINX) += xilinxfb.o
126obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o 131obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o
127obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o 132obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o
133obj-$(CONFIG_FB_SH_MOBILE_MERAM) += sh_mobile_meram.o
128obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o 134obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o
129obj-$(CONFIG_FB_OMAP) += omap/ 135obj-$(CONFIG_FB_OMAP) += omap/
130obj-y += omap2/ 136obj-y += omap2/
@@ -134,6 +140,7 @@ obj-$(CONFIG_FB_MB862XX) += mb862xx/
134obj-$(CONFIG_FB_MSM) += msm/ 140obj-$(CONFIG_FB_MSM) += msm/
135obj-$(CONFIG_FB_NUC900) += nuc900fb.o 141obj-$(CONFIG_FB_NUC900) += nuc900fb.o
136obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o 142obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o
143obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o
137 144
138# Platform or fallback drivers go here 145# Platform or fallback drivers go here
139obj-$(CONFIG_FB_UVESA) += uvesafb.o 146obj-$(CONFIG_FB_UVESA) += uvesafb.o
@@ -141,11 +148,14 @@ obj-$(CONFIG_FB_VESA) += vesafb.o
141obj-$(CONFIG_FB_EFI) += efifb.o 148obj-$(CONFIG_FB_EFI) += efifb.o
142obj-$(CONFIG_FB_VGA16) += vga16fb.o 149obj-$(CONFIG_FB_VGA16) += vga16fb.o
143obj-$(CONFIG_FB_OF) += offb.o 150obj-$(CONFIG_FB_OF) += offb.o
151obj-$(CONFIG_FB_BF537_LQ035) += bf537-lq035.o
144obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o 152obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o
145obj-$(CONFIG_FB_BFIN_LQ035Q1) += bfin-lq035q1-fb.o 153obj-$(CONFIG_FB_BFIN_LQ035Q1) += bfin-lq035q1-fb.o
146obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o 154obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o
155obj-$(CONFIG_FB_BFIN_7393) += bfin_adv7393fb.o
147obj-$(CONFIG_FB_MX3) += mx3fb.o 156obj-$(CONFIG_FB_MX3) += mx3fb.o
148obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o 157obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o
158obj-$(CONFIG_FB_MXS) += mxsfb.o
149 159
150# the test framebuffer is last 160# the test framebuffer is last
151obj-$(CONFIG_FB_VIRTUAL) += vfb.o 161obj-$(CONFIG_FB_VIRTUAL) += vfb.o
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
index 82acb8dc4aa1..6183a57eb69d 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/acornfb.c
@@ -66,7 +66,7 @@
66 * have. Allow 1% either way on the nominal for TVs. 66 * have. Allow 1% either way on the nominal for TVs.
67 */ 67 */
68#define NR_MONTYPES 6 68#define NR_MONTYPES 6
69static struct fb_monspecs monspecs[NR_MONTYPES] __initdata = { 69static struct fb_monspecs monspecs[NR_MONTYPES] __devinitdata = {
70 { /* TV */ 70 { /* TV */
71 .hfmin = 15469, 71 .hfmin = 15469,
72 .hfmax = 15781, 72 .hfmax = 15781,
@@ -873,7 +873,7 @@ static struct fb_ops acornfb_ops = {
873/* 873/*
874 * Everything after here is initialisation!!! 874 * Everything after here is initialisation!!!
875 */ 875 */
876static struct fb_videomode modedb[] __initdata = { 876static struct fb_videomode modedb[] __devinitdata = {
877 { /* 320x256 @ 50Hz */ 877 { /* 320x256 @ 50Hz */
878 NULL, 50, 320, 256, 125000, 92, 62, 35, 19, 38, 2, 878 NULL, 50, 320, 256, 125000, 92, 62, 35, 19, 38, 2,
879 FB_SYNC_COMP_HIGH_ACT, 879 FB_SYNC_COMP_HIGH_ACT,
@@ -925,8 +925,7 @@ static struct fb_videomode modedb[] __initdata = {
925 } 925 }
926}; 926};
927 927
928static struct fb_videomode __initdata 928static struct fb_videomode acornfb_default_mode __devinitdata = {
929acornfb_default_mode = {
930 .name = NULL, 929 .name = NULL,
931 .refresh = 60, 930 .refresh = 60,
932 .xres = 640, 931 .xres = 640,
@@ -942,7 +941,7 @@ acornfb_default_mode = {
942 .vmode = FB_VMODE_NONINTERLACED 941 .vmode = FB_VMODE_NONINTERLACED
943}; 942};
944 943
945static void __init acornfb_init_fbinfo(void) 944static void __devinit acornfb_init_fbinfo(void)
946{ 945{
947 static int first = 1; 946 static int first = 1;
948 947
@@ -1018,8 +1017,7 @@ static void __init acornfb_init_fbinfo(void)
1018 * size can optionally be followed by 'M' or 'K' for 1017 * size can optionally be followed by 'M' or 'K' for
1019 * MB or KB respectively. 1018 * MB or KB respectively.
1020 */ 1019 */
1021static void __init 1020static void __devinit acornfb_parse_mon(char *opt)
1022acornfb_parse_mon(char *opt)
1023{ 1021{
1024 char *p = opt; 1022 char *p = opt;
1025 1023
@@ -1066,8 +1064,7 @@ bad:
1066 current_par.montype = -1; 1064 current_par.montype = -1;
1067} 1065}
1068 1066
1069static void __init 1067static void __devinit acornfb_parse_montype(char *opt)
1070acornfb_parse_montype(char *opt)
1071{ 1068{
1072 current_par.montype = -2; 1069 current_par.montype = -2;
1073 1070
@@ -1108,8 +1105,7 @@ acornfb_parse_montype(char *opt)
1108 } 1105 }
1109} 1106}
1110 1107
1111static void __init 1108static void __devinit acornfb_parse_dram(char *opt)
1112acornfb_parse_dram(char *opt)
1113{ 1109{
1114 unsigned int size; 1110 unsigned int size;
1115 1111
@@ -1134,15 +1130,14 @@ acornfb_parse_dram(char *opt)
1134static struct options { 1130static struct options {
1135 char *name; 1131 char *name;
1136 void (*parse)(char *opt); 1132 void (*parse)(char *opt);
1137} opt_table[] __initdata = { 1133} opt_table[] __devinitdata = {
1138 { "mon", acornfb_parse_mon }, 1134 { "mon", acornfb_parse_mon },
1139 { "montype", acornfb_parse_montype }, 1135 { "montype", acornfb_parse_montype },
1140 { "dram", acornfb_parse_dram }, 1136 { "dram", acornfb_parse_dram },
1141 { NULL, NULL } 1137 { NULL, NULL }
1142}; 1138};
1143 1139
1144int __init 1140static int __devinit acornfb_setup(char *options)
1145acornfb_setup(char *options)
1146{ 1141{
1147 struct options *optp; 1142 struct options *optp;
1148 char *opt; 1143 char *opt;
@@ -1179,8 +1174,7 @@ acornfb_setup(char *options)
1179 * Detect type of monitor connected 1174 * Detect type of monitor connected
1180 * For now, we just assume SVGA 1175 * For now, we just assume SVGA
1181 */ 1176 */
1182static int __init 1177static int __devinit acornfb_detect_monitortype(void)
1183acornfb_detect_monitortype(void)
1184{ 1178{
1185 return 4; 1179 return 4;
1186} 1180}
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
index 1c2c68356ea7..cf03ad067147 100644
--- a/drivers/video/amba-clcd.c
+++ b/drivers/video/amba-clcd.c
@@ -120,8 +120,23 @@ static void clcdfb_enable(struct clcd_fb *fb, u32 cntl)
120static int 120static int
121clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var) 121clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var)
122{ 122{
123 u32 caps;
123 int ret = 0; 124 int ret = 0;
124 125
126 if (fb->panel->caps && fb->board->caps)
127 caps = fb->panel->caps & fb->board->caps;
128 else {
129 /* Old way of specifying what can be used */
130 caps = fb->panel->cntl & CNTL_BGR ?
131 CLCD_CAP_BGR : CLCD_CAP_RGB;
132 /* But mask out 444 modes as they weren't supported */
133 caps &= ~CLCD_CAP_444;
134 }
135
136 /* Only TFT panels can do RGB888/BGR888 */
137 if (!(fb->panel->cntl & CNTL_LCDTFT))
138 caps &= ~CLCD_CAP_888;
139
125 memset(&var->transp, 0, sizeof(var->transp)); 140 memset(&var->transp, 0, sizeof(var->transp));
126 141
127 var->red.msb_right = 0; 142 var->red.msb_right = 0;
@@ -133,6 +148,13 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var)
133 case 2: 148 case 2:
134 case 4: 149 case 4:
135 case 8: 150 case 8:
151 /* If we can't do 5551, reject */
152 caps &= CLCD_CAP_5551;
153 if (!caps) {
154 ret = -EINVAL;
155 break;
156 }
157
136 var->red.length = var->bits_per_pixel; 158 var->red.length = var->bits_per_pixel;
137 var->red.offset = 0; 159 var->red.offset = 0;
138 var->green.length = var->bits_per_pixel; 160 var->green.length = var->bits_per_pixel;
@@ -140,23 +162,61 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var)
140 var->blue.length = var->bits_per_pixel; 162 var->blue.length = var->bits_per_pixel;
141 var->blue.offset = 0; 163 var->blue.offset = 0;
142 break; 164 break;
165
143 case 16: 166 case 16:
144 var->red.length = 5; 167 /* If we can't do 444, 5551 or 565, reject */
145 var->blue.length = 5; 168 if (!(caps & (CLCD_CAP_444 | CLCD_CAP_5551 | CLCD_CAP_565))) {
169 ret = -EINVAL;
170 break;
171 }
172
146 /* 173 /*
147 * Green length can be 5 or 6 depending whether 174 * Green length can be 4, 5 or 6 depending whether
148 * we're operating in RGB555 or RGB565 mode. 175 * we're operating in 444, 5551 or 565 mode.
149 */ 176 */
150 if (var->green.length != 5 && var->green.length != 6) 177 if (var->green.length == 4 && caps & CLCD_CAP_444)
151 var->green.length = 6; 178 caps &= CLCD_CAP_444;
179 if (var->green.length == 5 && caps & CLCD_CAP_5551)
180 caps &= CLCD_CAP_5551;
181 else if (var->green.length == 6 && caps & CLCD_CAP_565)
182 caps &= CLCD_CAP_565;
183 else {
184 /*
185 * PL110 officially only supports RGB555,
186 * but may be wired up to allow RGB565.
187 */
188 if (caps & CLCD_CAP_565) {
189 var->green.length = 6;
190 caps &= CLCD_CAP_565;
191 } else if (caps & CLCD_CAP_5551) {
192 var->green.length = 5;
193 caps &= CLCD_CAP_5551;
194 } else {
195 var->green.length = 4;
196 caps &= CLCD_CAP_444;
197 }
198 }
199
200 if (var->green.length >= 5) {
201 var->red.length = 5;
202 var->blue.length = 5;
203 } else {
204 var->red.length = 4;
205 var->blue.length = 4;
206 }
152 break; 207 break;
153 case 32: 208 case 32:
154 if (fb->panel->cntl & CNTL_LCDTFT) { 209 /* If we can't do 888, reject */
155 var->red.length = 8; 210 caps &= CLCD_CAP_888;
156 var->green.length = 8; 211 if (!caps) {
157 var->blue.length = 8; 212 ret = -EINVAL;
158 break; 213 break;
159 } 214 }
215
216 var->red.length = 8;
217 var->green.length = 8;
218 var->blue.length = 8;
219 break;
160 default: 220 default:
161 ret = -EINVAL; 221 ret = -EINVAL;
162 break; 222 break;
@@ -168,7 +228,20 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var)
168 * the bitfield length defined above. 228 * the bitfield length defined above.
169 */ 229 */
170 if (ret == 0 && var->bits_per_pixel >= 16) { 230 if (ret == 0 && var->bits_per_pixel >= 16) {
171 if (fb->panel->cntl & CNTL_BGR) { 231 bool bgr, rgb;
232
233 bgr = caps & CLCD_CAP_BGR && var->blue.offset == 0;
234 rgb = caps & CLCD_CAP_RGB && var->red.offset == 0;
235
236 if (!bgr && !rgb)
237 /*
238 * The requested format was not possible, try just
239 * our capabilities. One of BGR or RGB must be
240 * supported.
241 */
242 bgr = caps & CLCD_CAP_BGR;
243
244 if (bgr) {
172 var->blue.offset = 0; 245 var->blue.offset = 0;
173 var->green.offset = var->blue.offset + var->blue.length; 246 var->green.offset = var->blue.offset + var->blue.length;
174 var->red.offset = var->green.offset + var->green.length; 247 var->red.offset = var->green.offset + var->green.length;
@@ -374,6 +447,8 @@ static int clcdfb_register(struct clcd_fb *fb)
374 goto out; 447 goto out;
375 } 448 }
376 449
450 fb->fb.device = &fb->dev->dev;
451
377 fb->fb.fix.mmio_start = fb->dev->res.start; 452 fb->fb.fix.mmio_start = fb->dev->res.start;
378 fb->fb.fix.mmio_len = resource_size(&fb->dev->res); 453 fb->fb.fix.mmio_len = resource_size(&fb->dev->res);
379 454
@@ -443,8 +518,8 @@ static int clcdfb_register(struct clcd_fb *fb)
443 518
444 fb_set_var(&fb->fb, &fb->fb.var); 519 fb_set_var(&fb->fb, &fb->fb.var);
445 520
446 printk(KERN_INFO "CLCD: %s hardware, %s display\n", 521 dev_info(&fb->dev->dev, "%s hardware, %s display\n",
447 fb->board->name, fb->panel->mode.name); 522 fb->board->name, fb->panel->mode.name);
448 523
449 ret = register_framebuffer(&fb->fb); 524 ret = register_framebuffer(&fb->fb);
450 if (ret == 0) 525 if (ret == 0)
@@ -461,7 +536,7 @@ static int clcdfb_register(struct clcd_fb *fb)
461 return ret; 536 return ret;
462} 537}
463 538
464static int clcdfb_probe(struct amba_device *dev, struct amba_id *id) 539static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
465{ 540{
466 struct clcd_board *board = dev->dev.platform_data; 541 struct clcd_board *board = dev->dev.platform_data;
467 struct clcd_fb *fb; 542 struct clcd_fb *fb;
@@ -486,6 +561,10 @@ static int clcdfb_probe(struct amba_device *dev, struct amba_id *id)
486 fb->dev = dev; 561 fb->dev = dev;
487 fb->board = board; 562 fb->board = board;
488 563
564 dev_info(&fb->dev->dev, "PL%03x rev%u at 0x%08llx\n",
565 amba_part(dev), amba_rev(dev),
566 (unsigned long long)dev->res.start);
567
489 ret = fb->board->setup(fb); 568 ret = fb->board->setup(fb);
490 if (ret) 569 if (ret)
491 goto free_fb; 570 goto free_fb;
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index e5d6b56d4447..5ea6596dd824 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -2224,22 +2224,23 @@ static int amifb_ioctl(struct fb_info *info,
2224 * Allocate, Clear and Align a Block of Chip Memory 2224 * Allocate, Clear and Align a Block of Chip Memory
2225 */ 2225 */
2226 2226
2227static u_long unaligned_chipptr = 0; 2227static void *aligned_chipptr;
2228 2228
2229static inline u_long __init chipalloc(u_long size) 2229static inline u_long __init chipalloc(u_long size)
2230{ 2230{
2231 size += PAGE_SIZE-1; 2231 aligned_chipptr = amiga_chip_alloc(size, "amifb [RAM]");
2232 if (!(unaligned_chipptr = (u_long)amiga_chip_alloc(size, 2232 if (!aligned_chipptr) {
2233 "amifb [RAM]"))) 2233 pr_err("amifb: No Chip RAM for frame buffer");
2234 panic("No Chip RAM for frame buffer"); 2234 return 0;
2235 memset((void *)unaligned_chipptr, 0, size); 2235 }
2236 return PAGE_ALIGN(unaligned_chipptr); 2236 memset(aligned_chipptr, 0, size);
2237 return (u_long)aligned_chipptr;
2237} 2238}
2238 2239
2239static inline void chipfree(void) 2240static inline void chipfree(void)
2240{ 2241{
2241 if (unaligned_chipptr) 2242 if (aligned_chipptr)
2242 amiga_chip_free((void *)unaligned_chipptr); 2243 amiga_chip_free(aligned_chipptr);
2243} 2244}
2244 2245
2245 2246
@@ -2295,7 +2296,7 @@ default_chipset:
2295 defmode = amiga_vblank == 50 ? DEFMODE_PAL 2296 defmode = amiga_vblank == 50 ? DEFMODE_PAL
2296 : DEFMODE_NTSC; 2297 : DEFMODE_NTSC;
2297 if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT > 2298 if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT >
2298 VIDEOMEMSIZE_ECS_1M) 2299 VIDEOMEMSIZE_ECS_2M)
2299 fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_2M; 2300 fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_2M;
2300 else 2301 else
2301 fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_1M; 2302 fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_1M;
@@ -2312,7 +2313,7 @@ default_chipset:
2312 maxfmode = TAG_FMODE_4; 2313 maxfmode = TAG_FMODE_4;
2313 defmode = DEFMODE_AGA; 2314 defmode = DEFMODE_AGA;
2314 if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT > 2315 if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT >
2315 VIDEOMEMSIZE_AGA_1M) 2316 VIDEOMEMSIZE_AGA_2M)
2316 fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_2M; 2317 fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_2M;
2317 else 2318 else
2318 fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_1M; 2319 fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_1M;
@@ -2385,6 +2386,10 @@ default_chipset:
2385 DUMMYSPRITEMEMSIZE+ 2386 DUMMYSPRITEMEMSIZE+
2386 COPINITSIZE+ 2387 COPINITSIZE+
2387 4*COPLISTSIZE); 2388 4*COPLISTSIZE);
2389 if (!chipptr) {
2390 err = -ENOMEM;
2391 goto amifb_error;
2392 }
2388 2393
2389 assignchunk(videomemory, u_long, chipptr, fb_info.fix.smem_len); 2394 assignchunk(videomemory, u_long, chipptr, fb_info.fix.smem_len);
2390 assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE); 2395 assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE);
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c
index f3d7440f0072..c22e8d39a2cb 100644
--- a/drivers/video/arcfb.c
+++ b/drivers/video/arcfb.c
@@ -2,7 +2,6 @@
2 * linux/drivers/video/arcfb.c -- FB driver for Arc monochrome LCD board 2 * linux/drivers/video/arcfb.c -- FB driver for Arc monochrome LCD board
3 * 3 *
4 * Copyright (C) 2005, Jaya Kumar <jayalk@intworks.biz> 4 * Copyright (C) 2005, Jaya Kumar <jayalk@intworks.biz>
5 * http://www.intworks.biz/arclcd
6 * 5 *
7 * This file is subject to the terms and conditions of the GNU General Public 6 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file COPYING in the main directory of this archive for 7 * License. See the file COPYING in the main directory of this archive for
@@ -516,11 +515,10 @@ static int __devinit arcfb_probe(struct platform_device *dev)
516 515
517 /* We need a flat backing store for the Arc's 516 /* We need a flat backing store for the Arc's
518 less-flat actual paged framebuffer */ 517 less-flat actual paged framebuffer */
519 if (!(videomemory = vmalloc(videomemorysize))) 518 videomemory = vzalloc(videomemorysize);
519 if (!videomemory)
520 return retval; 520 return retval;
521 521
522 memset(videomemory, 0, videomemorysize);
523
524 info = framebuffer_alloc(sizeof(struct arcfb_par), &dev->dev); 522 info = framebuffer_alloc(sizeof(struct arcfb_par), &dev->dev);
525 if (!info) 523 if (!info)
526 goto err; 524 goto err;
diff --git a/drivers/video/arkfb.c b/drivers/video/arkfb.c
index d583bea608fd..8686429cbdf0 100644
--- a/drivers/video/arkfb.c
+++ b/drivers/video/arkfb.c
@@ -23,7 +23,7 @@
23#include <linux/svga.h> 23#include <linux/svga.h>
24#include <linux/init.h> 24#include <linux/init.h>
25#include <linux/pci.h> 25#include <linux/pci.h>
26#include <linux/console.h> /* Why should fb driver call console functions? because acquire_console_sem() */ 26#include <linux/console.h> /* Why should fb driver call console functions? because console_lock() */
27#include <video/vga.h> 27#include <video/vga.h>
28 28
29#ifdef CONFIG_MTRR 29#ifdef CONFIG_MTRR
@@ -158,12 +158,19 @@ static void arkfb_settile(struct fb_info *info, struct fb_tilemap *map)
158 } 158 }
159} 159}
160 160
161static void arkfb_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor)
162{
163 struct arkfb_info *par = info->par;
164
165 svga_tilecursor(par->state.vgabase, info, cursor);
166}
167
161static struct fb_tile_ops arkfb_tile_ops = { 168static struct fb_tile_ops arkfb_tile_ops = {
162 .fb_settile = arkfb_settile, 169 .fb_settile = arkfb_settile,
163 .fb_tilecopy = svga_tilecopy, 170 .fb_tilecopy = svga_tilecopy,
164 .fb_tilefill = svga_tilefill, 171 .fb_tilefill = svga_tilefill,
165 .fb_tileblit = svga_tileblit, 172 .fb_tileblit = svga_tileblit,
166 .fb_tilecursor = svga_tilecursor, 173 .fb_tilecursor = arkfb_tilecursor,
167 .fb_get_tilemax = svga_get_tilemax, 174 .fb_get_tilemax = svga_get_tilemax,
168}; 175};
169 176
@@ -466,32 +473,40 @@ static unsigned short dac_regs[4] = {0x3c8, 0x3c9, 0x3c6, 0x3c7};
466 473
467static void ark_dac_read_regs(void *data, u8 *code, int count) 474static void ark_dac_read_regs(void *data, u8 *code, int count)
468{ 475{
469 u8 regval = vga_rseq(NULL, 0x1C); 476 struct fb_info *info = data;
477 struct arkfb_info *par;
478 u8 regval;
470 479
480 par = info->par;
481 regval = vga_rseq(par->state.vgabase, 0x1C);
471 while (count != 0) 482 while (count != 0)
472 { 483 {
473 vga_wseq(NULL, 0x1C, regval | (code[0] & 4 ? 0x80 : 0)); 484 vga_wseq(par->state.vgabase, 0x1C, regval | (code[0] & 4 ? 0x80 : 0));
474 code[1] = vga_r(NULL, dac_regs[code[0] & 3]); 485 code[1] = vga_r(par->state.vgabase, dac_regs[code[0] & 3]);
475 count--; 486 count--;
476 code += 2; 487 code += 2;
477 } 488 }
478 489
479 vga_wseq(NULL, 0x1C, regval); 490 vga_wseq(par->state.vgabase, 0x1C, regval);
480} 491}
481 492
482static void ark_dac_write_regs(void *data, u8 *code, int count) 493static void ark_dac_write_regs(void *data, u8 *code, int count)
483{ 494{
484 u8 regval = vga_rseq(NULL, 0x1C); 495 struct fb_info *info = data;
496 struct arkfb_info *par;
497 u8 regval;
485 498
499 par = info->par;
500 regval = vga_rseq(par->state.vgabase, 0x1C);
486 while (count != 0) 501 while (count != 0)
487 { 502 {
488 vga_wseq(NULL, 0x1C, regval | (code[0] & 4 ? 0x80 : 0)); 503 vga_wseq(par->state.vgabase, 0x1C, regval | (code[0] & 4 ? 0x80 : 0));
489 vga_w(NULL, dac_regs[code[0] & 3], code[1]); 504 vga_w(par->state.vgabase, dac_regs[code[0] & 3], code[1]);
490 count--; 505 count--;
491 code += 2; 506 code += 2;
492 } 507 }
493 508
494 vga_wseq(NULL, 0x1C, regval); 509 vga_wseq(par->state.vgabase, 0x1C, regval);
495} 510}
496 511
497 512
@@ -507,8 +522,8 @@ static void ark_set_pixclock(struct fb_info *info, u32 pixclock)
507 } 522 }
508 523
509 /* Set VGA misc register */ 524 /* Set VGA misc register */
510 regval = vga_r(NULL, VGA_MIS_R); 525 regval = vga_r(par->state.vgabase, VGA_MIS_R);
511 vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); 526 vga_w(par->state.vgabase, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD);
512} 527}
513 528
514 529
@@ -520,7 +535,10 @@ static int arkfb_open(struct fb_info *info, int user)
520 535
521 mutex_lock(&(par->open_lock)); 536 mutex_lock(&(par->open_lock));
522 if (par->ref_count == 0) { 537 if (par->ref_count == 0) {
538 void __iomem *vgabase = par->state.vgabase;
539
523 memset(&(par->state), 0, sizeof(struct vgastate)); 540 memset(&(par->state), 0, sizeof(struct vgastate));
541 par->state.vgabase = vgabase;
524 par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP; 542 par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP;
525 par->state.num_crtc = 0x60; 543 par->state.num_crtc = 0x60;
526 par->state.num_seq = 0x30; 544 par->state.num_seq = 0x30;
@@ -646,50 +664,50 @@ static int arkfb_set_par(struct fb_info *info)
646 info->var.activate = FB_ACTIVATE_NOW; 664 info->var.activate = FB_ACTIVATE_NOW;
647 665
648 /* Unlock registers */ 666 /* Unlock registers */
649 svga_wcrt_mask(0x11, 0x00, 0x80); 667 svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x80);
650 668
651 /* Blank screen and turn off sync */ 669 /* Blank screen and turn off sync */
652 svga_wseq_mask(0x01, 0x20, 0x20); 670 svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
653 svga_wcrt_mask(0x17, 0x00, 0x80); 671 svga_wcrt_mask(par->state.vgabase, 0x17, 0x00, 0x80);
654 672
655 /* Set default values */ 673 /* Set default values */
656 svga_set_default_gfx_regs(); 674 svga_set_default_gfx_regs(par->state.vgabase);
657 svga_set_default_atc_regs(); 675 svga_set_default_atc_regs(par->state.vgabase);
658 svga_set_default_seq_regs(); 676 svga_set_default_seq_regs(par->state.vgabase);
659 svga_set_default_crt_regs(); 677 svga_set_default_crt_regs(par->state.vgabase);
660 svga_wcrt_multi(ark_line_compare_regs, 0xFFFFFFFF); 678 svga_wcrt_multi(par->state.vgabase, ark_line_compare_regs, 0xFFFFFFFF);
661 svga_wcrt_multi(ark_start_address_regs, 0); 679 svga_wcrt_multi(par->state.vgabase, ark_start_address_regs, 0);
662 680
663 /* ARK specific initialization */ 681 /* ARK specific initialization */
664 svga_wseq_mask(0x10, 0x1F, 0x1F); /* enable linear framebuffer and full memory access */ 682 svga_wseq_mask(par->state.vgabase, 0x10, 0x1F, 0x1F); /* enable linear framebuffer and full memory access */
665 svga_wseq_mask(0x12, 0x03, 0x03); /* 4 MB linear framebuffer size */ 683 svga_wseq_mask(par->state.vgabase, 0x12, 0x03, 0x03); /* 4 MB linear framebuffer size */
666 684
667 vga_wseq(NULL, 0x13, info->fix.smem_start >> 16); 685 vga_wseq(par->state.vgabase, 0x13, info->fix.smem_start >> 16);
668 vga_wseq(NULL, 0x14, info->fix.smem_start >> 24); 686 vga_wseq(par->state.vgabase, 0x14, info->fix.smem_start >> 24);
669 vga_wseq(NULL, 0x15, 0); 687 vga_wseq(par->state.vgabase, 0x15, 0);
670 vga_wseq(NULL, 0x16, 0); 688 vga_wseq(par->state.vgabase, 0x16, 0);
671 689
672 /* Set the FIFO threshold register */ 690 /* Set the FIFO threshold register */
673 /* It is fascinating way to store 5-bit value in 8-bit register */ 691 /* It is fascinating way to store 5-bit value in 8-bit register */
674 regval = 0x10 | ((threshold & 0x0E) >> 1) | (threshold & 0x01) << 7 | (threshold & 0x10) << 1; 692 regval = 0x10 | ((threshold & 0x0E) >> 1) | (threshold & 0x01) << 7 | (threshold & 0x10) << 1;
675 vga_wseq(NULL, 0x18, regval); 693 vga_wseq(par->state.vgabase, 0x18, regval);
676 694
677 /* Set the offset register */ 695 /* Set the offset register */
678 pr_debug("fb%d: offset register : %d\n", info->node, offset_value); 696 pr_debug("fb%d: offset register : %d\n", info->node, offset_value);
679 svga_wcrt_multi(ark_offset_regs, offset_value); 697 svga_wcrt_multi(par->state.vgabase, ark_offset_regs, offset_value);
680 698
681 /* fix for hi-res textmode */ 699 /* fix for hi-res textmode */
682 svga_wcrt_mask(0x40, 0x08, 0x08); 700 svga_wcrt_mask(par->state.vgabase, 0x40, 0x08, 0x08);
683 701
684 if (info->var.vmode & FB_VMODE_DOUBLE) 702 if (info->var.vmode & FB_VMODE_DOUBLE)
685 svga_wcrt_mask(0x09, 0x80, 0x80); 703 svga_wcrt_mask(par->state.vgabase, 0x09, 0x80, 0x80);
686 else 704 else
687 svga_wcrt_mask(0x09, 0x00, 0x80); 705 svga_wcrt_mask(par->state.vgabase, 0x09, 0x00, 0x80);
688 706
689 if (info->var.vmode & FB_VMODE_INTERLACED) 707 if (info->var.vmode & FB_VMODE_INTERLACED)
690 svga_wcrt_mask(0x44, 0x04, 0x04); 708 svga_wcrt_mask(par->state.vgabase, 0x44, 0x04, 0x04);
691 else 709 else
692 svga_wcrt_mask(0x44, 0x00, 0x04); 710 svga_wcrt_mask(par->state.vgabase, 0x44, 0x00, 0x04);
693 711
694 hmul = 1; 712 hmul = 1;
695 hdiv = 1; 713 hdiv = 1;
@@ -699,40 +717,40 @@ static int arkfb_set_par(struct fb_info *info)
699 switch (mode) { 717 switch (mode) {
700 case 0: 718 case 0:
701 pr_debug("fb%d: text mode\n", info->node); 719 pr_debug("fb%d: text mode\n", info->node);
702 svga_set_textmode_vga_regs(); 720 svga_set_textmode_vga_regs(par->state.vgabase);
703 721
704 vga_wseq(NULL, 0x11, 0x10); /* basic VGA mode */ 722 vga_wseq(par->state.vgabase, 0x11, 0x10); /* basic VGA mode */
705 svga_wcrt_mask(0x46, 0x00, 0x04); /* 8bit pixel path */ 723 svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */
706 dac_set_mode(par->dac, DAC_PSEUDO8_8); 724 dac_set_mode(par->dac, DAC_PSEUDO8_8);
707 725
708 break; 726 break;
709 case 1: 727 case 1:
710 pr_debug("fb%d: 4 bit pseudocolor\n", info->node); 728 pr_debug("fb%d: 4 bit pseudocolor\n", info->node);
711 vga_wgfx(NULL, VGA_GFX_MODE, 0x40); 729 vga_wgfx(par->state.vgabase, VGA_GFX_MODE, 0x40);
712 730
713 vga_wseq(NULL, 0x11, 0x10); /* basic VGA mode */ 731 vga_wseq(par->state.vgabase, 0x11, 0x10); /* basic VGA mode */
714 svga_wcrt_mask(0x46, 0x00, 0x04); /* 8bit pixel path */ 732 svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */
715 dac_set_mode(par->dac, DAC_PSEUDO8_8); 733 dac_set_mode(par->dac, DAC_PSEUDO8_8);
716 break; 734 break;
717 case 2: 735 case 2:
718 pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node); 736 pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node);
719 737
720 vga_wseq(NULL, 0x11, 0x10); /* basic VGA mode */ 738 vga_wseq(par->state.vgabase, 0x11, 0x10); /* basic VGA mode */
721 svga_wcrt_mask(0x46, 0x00, 0x04); /* 8bit pixel path */ 739 svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */
722 dac_set_mode(par->dac, DAC_PSEUDO8_8); 740 dac_set_mode(par->dac, DAC_PSEUDO8_8);
723 break; 741 break;
724 case 3: 742 case 3:
725 pr_debug("fb%d: 8 bit pseudocolor\n", info->node); 743 pr_debug("fb%d: 8 bit pseudocolor\n", info->node);
726 744
727 vga_wseq(NULL, 0x11, 0x16); /* 8bpp accel mode */ 745 vga_wseq(par->state.vgabase, 0x11, 0x16); /* 8bpp accel mode */
728 746
729 if (info->var.pixclock > 20000) { 747 if (info->var.pixclock > 20000) {
730 pr_debug("fb%d: not using multiplex\n", info->node); 748 pr_debug("fb%d: not using multiplex\n", info->node);
731 svga_wcrt_mask(0x46, 0x00, 0x04); /* 8bit pixel path */ 749 svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */
732 dac_set_mode(par->dac, DAC_PSEUDO8_8); 750 dac_set_mode(par->dac, DAC_PSEUDO8_8);
733 } else { 751 } else {
734 pr_debug("fb%d: using multiplex\n", info->node); 752 pr_debug("fb%d: using multiplex\n", info->node);
735 svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */ 753 svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */
736 dac_set_mode(par->dac, DAC_PSEUDO8_16); 754 dac_set_mode(par->dac, DAC_PSEUDO8_16);
737 hdiv = 2; 755 hdiv = 2;
738 } 756 }
@@ -740,22 +758,22 @@ static int arkfb_set_par(struct fb_info *info)
740 case 4: 758 case 4:
741 pr_debug("fb%d: 5/5/5 truecolor\n", info->node); 759 pr_debug("fb%d: 5/5/5 truecolor\n", info->node);
742 760
743 vga_wseq(NULL, 0x11, 0x1A); /* 16bpp accel mode */ 761 vga_wseq(par->state.vgabase, 0x11, 0x1A); /* 16bpp accel mode */
744 svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */ 762 svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */
745 dac_set_mode(par->dac, DAC_RGB1555_16); 763 dac_set_mode(par->dac, DAC_RGB1555_16);
746 break; 764 break;
747 case 5: 765 case 5:
748 pr_debug("fb%d: 5/6/5 truecolor\n", info->node); 766 pr_debug("fb%d: 5/6/5 truecolor\n", info->node);
749 767
750 vga_wseq(NULL, 0x11, 0x1A); /* 16bpp accel mode */ 768 vga_wseq(par->state.vgabase, 0x11, 0x1A); /* 16bpp accel mode */
751 svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */ 769 svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */
752 dac_set_mode(par->dac, DAC_RGB0565_16); 770 dac_set_mode(par->dac, DAC_RGB0565_16);
753 break; 771 break;
754 case 6: 772 case 6:
755 pr_debug("fb%d: 8/8/8 truecolor\n", info->node); 773 pr_debug("fb%d: 8/8/8 truecolor\n", info->node);
756 774
757 vga_wseq(NULL, 0x11, 0x16); /* 8bpp accel mode ??? */ 775 vga_wseq(par->state.vgabase, 0x11, 0x16); /* 8bpp accel mode ??? */
758 svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */ 776 svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */
759 dac_set_mode(par->dac, DAC_RGB0888_16); 777 dac_set_mode(par->dac, DAC_RGB0888_16);
760 hmul = 3; 778 hmul = 3;
761 hdiv = 2; 779 hdiv = 2;
@@ -763,8 +781,8 @@ static int arkfb_set_par(struct fb_info *info)
763 case 7: 781 case 7:
764 pr_debug("fb%d: 8/8/8/8 truecolor\n", info->node); 782 pr_debug("fb%d: 8/8/8/8 truecolor\n", info->node);
765 783
766 vga_wseq(NULL, 0x11, 0x1E); /* 32bpp accel mode */ 784 vga_wseq(par->state.vgabase, 0x11, 0x1E); /* 32bpp accel mode */
767 svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */ 785 svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */
768 dac_set_mode(par->dac, DAC_RGB8888_16); 786 dac_set_mode(par->dac, DAC_RGB8888_16);
769 hmul = 2; 787 hmul = 2;
770 break; 788 break;
@@ -774,7 +792,7 @@ static int arkfb_set_par(struct fb_info *info)
774 } 792 }
775 793
776 ark_set_pixclock(info, (hdiv * info->var.pixclock) / hmul); 794 ark_set_pixclock(info, (hdiv * info->var.pixclock) / hmul);
777 svga_set_timings(&ark_timing_regs, &(info->var), hmul, hdiv, 795 svga_set_timings(par->state.vgabase, &ark_timing_regs, &(info->var), hmul, hdiv,
778 (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1, 796 (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1,
779 (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1, 797 (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1,
780 hmul, info->node); 798 hmul, info->node);
@@ -782,12 +800,12 @@ static int arkfb_set_par(struct fb_info *info)
782 /* Set interlaced mode start/end register */ 800 /* Set interlaced mode start/end register */
783 value = info->var.xres + info->var.left_margin + info->var.right_margin + info->var.hsync_len; 801 value = info->var.xres + info->var.left_margin + info->var.right_margin + info->var.hsync_len;
784 value = ((value * hmul / hdiv) / 8) - 5; 802 value = ((value * hmul / hdiv) / 8) - 5;
785 vga_wcrt(NULL, 0x42, (value + 1) / 2); 803 vga_wcrt(par->state.vgabase, 0x42, (value + 1) / 2);
786 804
787 memset_io(info->screen_base, 0x00, screen_size); 805 memset_io(info->screen_base, 0x00, screen_size);
788 /* Device and screen back on */ 806 /* Device and screen back on */
789 svga_wcrt_mask(0x17, 0x80, 0x80); 807 svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80);
790 svga_wseq_mask(0x01, 0x00, 0x20); 808 svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
791 809
792 return 0; 810 return 0;
793} 811}
@@ -857,23 +875,25 @@ static int arkfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
857 875
858static int arkfb_blank(int blank_mode, struct fb_info *info) 876static int arkfb_blank(int blank_mode, struct fb_info *info)
859{ 877{
878 struct arkfb_info *par = info->par;
879
860 switch (blank_mode) { 880 switch (blank_mode) {
861 case FB_BLANK_UNBLANK: 881 case FB_BLANK_UNBLANK:
862 pr_debug("fb%d: unblank\n", info->node); 882 pr_debug("fb%d: unblank\n", info->node);
863 svga_wseq_mask(0x01, 0x00, 0x20); 883 svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
864 svga_wcrt_mask(0x17, 0x80, 0x80); 884 svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80);
865 break; 885 break;
866 case FB_BLANK_NORMAL: 886 case FB_BLANK_NORMAL:
867 pr_debug("fb%d: blank\n", info->node); 887 pr_debug("fb%d: blank\n", info->node);
868 svga_wseq_mask(0x01, 0x20, 0x20); 888 svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
869 svga_wcrt_mask(0x17, 0x80, 0x80); 889 svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80);
870 break; 890 break;
871 case FB_BLANK_POWERDOWN: 891 case FB_BLANK_POWERDOWN:
872 case FB_BLANK_HSYNC_SUSPEND: 892 case FB_BLANK_HSYNC_SUSPEND:
873 case FB_BLANK_VSYNC_SUSPEND: 893 case FB_BLANK_VSYNC_SUSPEND:
874 pr_debug("fb%d: sync down\n", info->node); 894 pr_debug("fb%d: sync down\n", info->node);
875 svga_wseq_mask(0x01, 0x20, 0x20); 895 svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
876 svga_wcrt_mask(0x17, 0x00, 0x80); 896 svga_wcrt_mask(par->state.vgabase, 0x17, 0x00, 0x80);
877 break; 897 break;
878 } 898 }
879 return 0; 899 return 0;
@@ -884,6 +904,7 @@ static int arkfb_blank(int blank_mode, struct fb_info *info)
884 904
885static int arkfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) 905static int arkfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
886{ 906{
907 struct arkfb_info *par = info->par;
887 unsigned int offset; 908 unsigned int offset;
888 909
889 /* Calculate the offset */ 910 /* Calculate the offset */
@@ -897,7 +918,7 @@ static int arkfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info
897 } 918 }
898 919
899 /* Set the offset */ 920 /* Set the offset */
900 svga_wcrt_multi(ark_start_address_regs, offset); 921 svga_wcrt_multi(par->state.vgabase, ark_start_address_regs, offset);
901 922
902 return 0; 923 return 0;
903} 924}
@@ -930,6 +951,8 @@ static struct fb_ops arkfb_ops = {
930/* PCI probe */ 951/* PCI probe */
931static int __devinit ark_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) 952static int __devinit ark_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
932{ 953{
954 struct pci_bus_region bus_reg;
955 struct resource vga_res;
933 struct fb_info *info; 956 struct fb_info *info;
934 struct arkfb_info *par; 957 struct arkfb_info *par;
935 int rc; 958 int rc;
@@ -985,8 +1008,17 @@ static int __devinit ark_pci_probe(struct pci_dev *dev, const struct pci_device_
985 goto err_iomap; 1008 goto err_iomap;
986 } 1009 }
987 1010
1011 bus_reg.start = 0;
1012 bus_reg.end = 64 * 1024;
1013
1014 vga_res.flags = IORESOURCE_IO;
1015
1016 pcibios_bus_to_resource(dev, &vga_res, &bus_reg);
1017
1018 par->state.vgabase = (void __iomem *) vga_res.start;
1019
988 /* FIXME get memsize */ 1020 /* FIXME get memsize */
989 regval = vga_rseq(NULL, 0x10); 1021 regval = vga_rseq(par->state.vgabase, 0x10);
990 info->screen_size = (1 << (regval >> 6)) << 20; 1022 info->screen_size = (1 << (regval >> 6)) << 20;
991 info->fix.smem_len = info->screen_size; 1023 info->fix.smem_len = info->screen_size;
992 1024
@@ -1091,12 +1123,12 @@ static int ark_pci_suspend (struct pci_dev* dev, pm_message_t state)
1091 1123
1092 dev_info(info->device, "suspend\n"); 1124 dev_info(info->device, "suspend\n");
1093 1125
1094 acquire_console_sem(); 1126 console_lock();
1095 mutex_lock(&(par->open_lock)); 1127 mutex_lock(&(par->open_lock));
1096 1128
1097 if ((state.event == PM_EVENT_FREEZE) || (par->ref_count == 0)) { 1129 if ((state.event == PM_EVENT_FREEZE) || (par->ref_count == 0)) {
1098 mutex_unlock(&(par->open_lock)); 1130 mutex_unlock(&(par->open_lock));
1099 release_console_sem(); 1131 console_unlock();
1100 return 0; 1132 return 0;
1101 } 1133 }
1102 1134
@@ -1107,7 +1139,7 @@ static int ark_pci_suspend (struct pci_dev* dev, pm_message_t state)
1107 pci_set_power_state(dev, pci_choose_state(dev, state)); 1139 pci_set_power_state(dev, pci_choose_state(dev, state));
1108 1140
1109 mutex_unlock(&(par->open_lock)); 1141 mutex_unlock(&(par->open_lock));
1110 release_console_sem(); 1142 console_unlock();
1111 1143
1112 return 0; 1144 return 0;
1113} 1145}
@@ -1122,7 +1154,7 @@ static int ark_pci_resume (struct pci_dev* dev)
1122 1154
1123 dev_info(info->device, "resume\n"); 1155 dev_info(info->device, "resume\n");
1124 1156
1125 acquire_console_sem(); 1157 console_lock();
1126 mutex_lock(&(par->open_lock)); 1158 mutex_lock(&(par->open_lock));
1127 1159
1128 if (par->ref_count == 0) 1160 if (par->ref_count == 0)
@@ -1141,7 +1173,7 @@ static int ark_pci_resume (struct pci_dev* dev)
1141 1173
1142fail: 1174fail:
1143 mutex_unlock(&(par->open_lock)); 1175 mutex_unlock(&(par->open_lock));
1144 release_console_sem(); 1176 console_unlock();
1145 return 0; 1177 return 0;
1146} 1178}
1147#else 1179#else
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index f3aada20fa02..64e41f5448c4 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -1718,11 +1718,9 @@ static int falcon_setcolreg(unsigned int regno, unsigned int red,
1718 (((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) | 1718 (((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) |
1719 (((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) | 1719 (((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) |
1720 ((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12); 1720 ((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
1721#ifdef ATAFB_FALCON
1722 ((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) | 1721 ((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) |
1723 ((green & 0xfc00) >> 5) | 1722 ((green & 0xfc00) >> 5) |
1724 ((blue & 0xf800) >> 11)); 1723 ((blue & 0xf800) >> 11));
1725#endif
1726 } 1724 }
1727 return 0; 1725 return 0;
1728} 1726}
@@ -3119,7 +3117,7 @@ int __init atafb_init(void)
3119 atafb_ops.fb_setcolreg = &falcon_setcolreg; 3117 atafb_ops.fb_setcolreg = &falcon_setcolreg;
3120 error = request_irq(IRQ_AUTO_4, falcon_vbl_switcher, 3118 error = request_irq(IRQ_AUTO_4, falcon_vbl_switcher,
3121 IRQ_TYPE_PRIO, 3119 IRQ_TYPE_PRIO,
3122 "framebuffer/modeswitch", 3120 "framebuffer:modeswitch",
3123 falcon_vbl_switcher); 3121 falcon_vbl_switcher);
3124 if (error) 3122 if (error)
3125 return error; 3123 return error;
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index 8dce25126330..4484c721f0f9 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -68,7 +68,7 @@ static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
68} 68}
69#endif 69#endif
70 70
71static const u32 contrast_ctr = ATMEL_LCDC_PS_DIV8 71static u32 contrast_ctr = ATMEL_LCDC_PS_DIV8
72 | ATMEL_LCDC_POL_POSITIVE 72 | ATMEL_LCDC_POL_POSITIVE
73 | ATMEL_LCDC_ENA_PWMENABLE; 73 | ATMEL_LCDC_ENA_PWMENABLE;
74 74
@@ -111,7 +111,7 @@ static int atmel_bl_get_brightness(struct backlight_device *bl)
111 return lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL); 111 return lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
112} 112}
113 113
114static struct backlight_ops atmel_lcdc_bl_ops = { 114static const struct backlight_ops atmel_lcdc_bl_ops = {
115 .update_status = atmel_bl_update_status, 115 .update_status = atmel_bl_update_status,
116 .get_brightness = atmel_bl_get_brightness, 116 .get_brightness = atmel_bl_get_brightness,
117}; 117};
@@ -127,6 +127,7 @@ static void init_backlight(struct atmel_lcdfb_info *sinfo)
127 return; 127 return;
128 128
129 memset(&props, 0, sizeof(struct backlight_properties)); 129 memset(&props, 0, sizeof(struct backlight_properties));
130 props.type = BACKLIGHT_RAW;
130 props.max_brightness = 0xff; 131 props.max_brightness = 0xff;
131 bl = backlight_device_register("backlight", &sinfo->pdev->dev, sinfo, 132 bl = backlight_device_register("backlight", &sinfo->pdev->dev, sinfo,
132 &atmel_lcdc_bl_ops, &props); 133 &atmel_lcdc_bl_ops, &props);
@@ -163,6 +164,10 @@ static void exit_backlight(struct atmel_lcdfb_info *sinfo)
163 164
164static void init_contrast(struct atmel_lcdfb_info *sinfo) 165static void init_contrast(struct atmel_lcdfb_info *sinfo)
165{ 166{
167 /* contrast pwm can be 'inverted' */
168 if (sinfo->lcdcon_pol_negative)
169 contrast_ctr &= ~(ATMEL_LCDC_POL_POSITIVE);
170
166 /* have some default contrast/backlight settings */ 171 /* have some default contrast/backlight settings */
167 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr); 172 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr);
168 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT); 173 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT);
@@ -632,7 +637,7 @@ static inline unsigned int chan_to_field(unsigned int chan, const struct fb_bitf
632 * magnitude which needs to be scaled in this function for the hardware. 637 * magnitude which needs to be scaled in this function for the hardware.
633 * Things to take into consideration are how many color registers, if 638 * Things to take into consideration are how many color registers, if
634 * any, are supported with the current color visual. With truecolor mode 639 * any, are supported with the current color visual. With truecolor mode
635 * no color palettes are supported. Here a psuedo palette is created 640 * no color palettes are supported. Here a pseudo palette is created
636 * which we store the value in pseudo_palette in struct fb_info. For 641 * which we store the value in pseudo_palette in struct fb_info. For
637 * pseudocolor mode we have a limited color palette. To deal with this 642 * pseudocolor mode we have a limited color palette. To deal with this
638 * we can program what color is displayed for a particular pixel value. 643 * we can program what color is displayed for a particular pixel value.
@@ -710,11 +715,35 @@ static int atmel_lcdfb_pan_display(struct fb_var_screeninfo *var,
710 return 0; 715 return 0;
711} 716}
712 717
718static int atmel_lcdfb_blank(int blank_mode, struct fb_info *info)
719{
720 struct atmel_lcdfb_info *sinfo = info->par;
721
722 switch (blank_mode) {
723 case FB_BLANK_UNBLANK:
724 case FB_BLANK_NORMAL:
725 atmel_lcdfb_start(sinfo);
726 break;
727 case FB_BLANK_VSYNC_SUSPEND:
728 case FB_BLANK_HSYNC_SUSPEND:
729 break;
730 case FB_BLANK_POWERDOWN:
731 atmel_lcdfb_stop(sinfo);
732 break;
733 default:
734 return -EINVAL;
735 }
736
737 /* let fbcon do a soft blank for us */
738 return ((blank_mode == FB_BLANK_NORMAL) ? 1 : 0);
739}
740
713static struct fb_ops atmel_lcdfb_ops = { 741static struct fb_ops atmel_lcdfb_ops = {
714 .owner = THIS_MODULE, 742 .owner = THIS_MODULE,
715 .fb_check_var = atmel_lcdfb_check_var, 743 .fb_check_var = atmel_lcdfb_check_var,
716 .fb_set_par = atmel_lcdfb_set_par, 744 .fb_set_par = atmel_lcdfb_set_par,
717 .fb_setcolreg = atmel_lcdfb_setcolreg, 745 .fb_setcolreg = atmel_lcdfb_setcolreg,
746 .fb_blank = atmel_lcdfb_blank,
718 .fb_pan_display = atmel_lcdfb_pan_display, 747 .fb_pan_display = atmel_lcdfb_pan_display,
719 .fb_fillrect = cfb_fillrect, 748 .fb_fillrect = cfb_fillrect,
720 .fb_copyarea = cfb_copyarea, 749 .fb_copyarea = cfb_copyarea,
@@ -816,6 +845,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
816 sinfo->guard_time = pdata_sinfo->guard_time; 845 sinfo->guard_time = pdata_sinfo->guard_time;
817 sinfo->smem_len = pdata_sinfo->smem_len; 846 sinfo->smem_len = pdata_sinfo->smem_len;
818 sinfo->lcdcon_is_backlight = pdata_sinfo->lcdcon_is_backlight; 847 sinfo->lcdcon_is_backlight = pdata_sinfo->lcdcon_is_backlight;
848 sinfo->lcdcon_pol_negative = pdata_sinfo->lcdcon_pol_negative;
819 sinfo->lcd_wiring_mode = pdata_sinfo->lcd_wiring_mode; 849 sinfo->lcd_wiring_mode = pdata_sinfo->lcd_wiring_mode;
820 } else { 850 } else {
821 dev_err(dev, "cannot get default configuration\n"); 851 dev_err(dev, "cannot get default configuration\n");
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index 34a0851bcbfa..b0b2ac335347 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -1786,7 +1786,7 @@ static int aty128_bl_get_brightness(struct backlight_device *bd)
1786 return bd->props.brightness; 1786 return bd->props.brightness;
1787} 1787}
1788 1788
1789static struct backlight_ops aty128_bl_data = { 1789static const struct backlight_ops aty128_bl_data = {
1790 .get_brightness = aty128_bl_get_brightness, 1790 .get_brightness = aty128_bl_get_brightness,
1791 .update_status = aty128_bl_update_status, 1791 .update_status = aty128_bl_update_status,
1792}; 1792};
@@ -1818,6 +1818,7 @@ static void aty128_bl_init(struct aty128fb_par *par)
1818 snprintf(name, sizeof(name), "aty128bl%d", info->node); 1818 snprintf(name, sizeof(name), "aty128bl%d", info->node);
1819 1819
1820 memset(&props, 0, sizeof(struct backlight_properties)); 1820 memset(&props, 0, sizeof(struct backlight_properties));
1821 props.type = BACKLIGHT_RAW;
1821 props.max_brightness = FB_BACKLIGHT_LEVELS - 1; 1822 props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
1822 bd = backlight_device_register(name, info->dev, par, &aty128_bl_data, 1823 bd = backlight_device_register(name, info->dev, par, &aty128_bl_data,
1823 &props); 1824 &props);
@@ -1860,11 +1861,11 @@ static void aty128_early_resume(void *data)
1860{ 1861{
1861 struct aty128fb_par *par = data; 1862 struct aty128fb_par *par = data;
1862 1863
1863 if (try_acquire_console_sem()) 1864 if (!console_trylock())
1864 return; 1865 return;
1865 pci_restore_state(par->pdev); 1866 pci_restore_state(par->pdev);
1866 aty128_do_resume(par->pdev); 1867 aty128_do_resume(par->pdev);
1867 release_console_sem(); 1868 console_unlock();
1868} 1869}
1869#endif /* CONFIG_PPC_PMAC */ 1870#endif /* CONFIG_PPC_PMAC */
1870 1871
@@ -2438,7 +2439,7 @@ static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state)
2438 2439
2439 printk(KERN_DEBUG "aty128fb: suspending...\n"); 2440 printk(KERN_DEBUG "aty128fb: suspending...\n");
2440 2441
2441 acquire_console_sem(); 2442 console_lock();
2442 2443
2443 fb_set_suspend(info, 1); 2444 fb_set_suspend(info, 1);
2444 2445
@@ -2470,7 +2471,7 @@ static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state)
2470 if (state.event != PM_EVENT_ON) 2471 if (state.event != PM_EVENT_ON)
2471 aty128_set_suspend(par, 1); 2472 aty128_set_suspend(par, 1);
2472 2473
2473 release_console_sem(); 2474 console_unlock();
2474 2475
2475 pdev->dev.power.power_state = state; 2476 pdev->dev.power.power_state = state;
2476 2477
@@ -2527,9 +2528,9 @@ static int aty128_pci_resume(struct pci_dev *pdev)
2527{ 2528{
2528 int rc; 2529 int rc;
2529 2530
2530 acquire_console_sem(); 2531 console_lock();
2531 rc = aty128_do_resume(pdev); 2532 rc = aty128_do_resume(pdev);
2532 release_console_sem(); 2533 console_unlock();
2533 2534
2534 return rc; 2535 return rc;
2535} 2536}
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index f8d69ad36830..d7aaec5667bf 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -248,10 +248,6 @@ static int atyfb_sync(struct fb_info *info);
248 248
249static int aty_init(struct fb_info *info); 249static int aty_init(struct fb_info *info);
250 250
251#ifdef CONFIG_ATARI
252static int store_video_par(char *videopar, unsigned char m64_num);
253#endif
254
255static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc); 251static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc);
256 252
257static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc); 253static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc);
@@ -2069,7 +2065,7 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
2069 if (state.event == pdev->dev.power.power_state.event) 2065 if (state.event == pdev->dev.power.power_state.event)
2070 return 0; 2066 return 0;
2071 2067
2072 acquire_console_sem(); 2068 console_lock();
2073 2069
2074 fb_set_suspend(info, 1); 2070 fb_set_suspend(info, 1);
2075 2071
@@ -2097,14 +2093,14 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
2097 par->lock_blank = 0; 2093 par->lock_blank = 0;
2098 atyfb_blank(FB_BLANK_UNBLANK, info); 2094 atyfb_blank(FB_BLANK_UNBLANK, info);
2099 fb_set_suspend(info, 0); 2095 fb_set_suspend(info, 0);
2100 release_console_sem(); 2096 console_unlock();
2101 return -EIO; 2097 return -EIO;
2102 } 2098 }
2103#else 2099#else
2104 pci_set_power_state(pdev, pci_choose_state(pdev, state)); 2100 pci_set_power_state(pdev, pci_choose_state(pdev, state));
2105#endif 2101#endif
2106 2102
2107 release_console_sem(); 2103 console_unlock();
2108 2104
2109 pdev->dev.power.power_state = state; 2105 pdev->dev.power.power_state = state;
2110 2106
@@ -2133,7 +2129,7 @@ static int atyfb_pci_resume(struct pci_dev *pdev)
2133 if (pdev->dev.power.power_state.event == PM_EVENT_ON) 2129 if (pdev->dev.power.power_state.event == PM_EVENT_ON)
2134 return 0; 2130 return 0;
2135 2131
2136 acquire_console_sem(); 2132 console_lock();
2137 2133
2138 /* 2134 /*
2139 * PCI state will have been restored by the core, so 2135 * PCI state will have been restored by the core, so
@@ -2161,7 +2157,7 @@ static int atyfb_pci_resume(struct pci_dev *pdev)
2161 par->lock_blank = 0; 2157 par->lock_blank = 0;
2162 atyfb_blank(FB_BLANK_UNBLANK, info); 2158 atyfb_blank(FB_BLANK_UNBLANK, info);
2163 2159
2164 release_console_sem(); 2160 console_unlock();
2165 2161
2166 pdev->dev.power.power_state = PMSG_ON; 2162 pdev->dev.power.power_state = PMSG_ON;
2167 2163
@@ -2221,7 +2217,7 @@ static int aty_bl_get_brightness(struct backlight_device *bd)
2221 return bd->props.brightness; 2217 return bd->props.brightness;
2222} 2218}
2223 2219
2224static struct backlight_ops aty_bl_data = { 2220static const struct backlight_ops aty_bl_data = {
2225 .get_brightness = aty_bl_get_brightness, 2221 .get_brightness = aty_bl_get_brightness,
2226 .update_status = aty_bl_update_status, 2222 .update_status = aty_bl_update_status,
2227}; 2223};
@@ -2241,6 +2237,7 @@ static void aty_bl_init(struct atyfb_par *par)
2241 snprintf(name, sizeof(name), "atybl%d", info->node); 2237 snprintf(name, sizeof(name), "atybl%d", info->node);
2242 2238
2243 memset(&props, 0, sizeof(struct backlight_properties)); 2239 memset(&props, 0, sizeof(struct backlight_properties));
2240 props.type = BACKLIGHT_RAW;
2244 props.max_brightness = FB_BACKLIGHT_LEVELS - 1; 2241 props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
2245 bd = backlight_device_register(name, info->dev, par, &aty_bl_data, 2242 bd = backlight_device_register(name, info->dev, par, &aty_bl_data,
2246 &props); 2243 &props);
@@ -2267,11 +2264,13 @@ error:
2267 return; 2264 return;
2268} 2265}
2269 2266
2267#ifdef CONFIG_PCI
2270static void aty_bl_exit(struct backlight_device *bd) 2268static void aty_bl_exit(struct backlight_device *bd)
2271{ 2269{
2272 backlight_device_unregister(bd); 2270 backlight_device_unregister(bd);
2273 printk("aty: Backlight unloaded\n"); 2271 printk("aty: Backlight unloaded\n");
2274} 2272}
2273#endif /* CONFIG_PCI */
2275 2274
2276#endif /* CONFIG_FB_ATY_BACKLIGHT */ 2275#endif /* CONFIG_FB_ATY_BACKLIGHT */
2277 2276
@@ -2788,7 +2787,7 @@ aty_init_exit:
2788 return ret; 2787 return ret;
2789} 2788}
2790 2789
2791#ifdef CONFIG_ATARI 2790#if defined(CONFIG_ATARI) && !defined(MODULE)
2792static int __devinit store_video_par(char *video_str, unsigned char m64_num) 2791static int __devinit store_video_par(char *video_str, unsigned char m64_num)
2793{ 2792{
2794 char *p; 2793 char *p;
@@ -2817,7 +2816,7 @@ static int __devinit store_video_par(char *video_str, unsigned char m64_num)
2817 phys_vmembase[m64_num] = 0; 2816 phys_vmembase[m64_num] = 0;
2818 return -1; 2817 return -1;
2819} 2818}
2820#endif /* CONFIG_ATARI */ 2819#endif /* CONFIG_ATARI && !MODULE */
2821 2820
2822/* 2821/*
2823 * Blank the display. 2822 * Blank the display.
@@ -2969,9 +2968,8 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
2969{ 2968{
2970 struct atyfb_par *par = info->par; 2969 struct atyfb_par *par = info->par;
2971 struct device_node *dp; 2970 struct device_node *dp;
2972 char prop[128];
2973 int node, len, i, j, ret;
2974 u32 mem, chip_id; 2971 u32 mem, chip_id;
2972 int i, j, ret;
2975 2973
2976 /* 2974 /*
2977 * Map memory-mapped registers. 2975 * Map memory-mapped registers.
@@ -3087,23 +3085,8 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
3087 aty_st_le32(MEM_CNTL, mem, par); 3085 aty_st_le32(MEM_CNTL, mem, par);
3088 } 3086 }
3089 3087
3090 /*
3091 * If this is the console device, we will set default video
3092 * settings to what the PROM left us with.
3093 */
3094 node = prom_getchild(prom_root_node);
3095 node = prom_searchsiblings(node, "aliases");
3096 if (node) {
3097 len = prom_getproperty(node, "screen", prop, sizeof(prop));
3098 if (len > 0) {
3099 prop[len] = '\0';
3100 node = prom_finddevice(prop);
3101 } else
3102 node = 0;
3103 }
3104
3105 dp = pci_device_to_OF_node(pdev); 3088 dp = pci_device_to_OF_node(pdev);
3106 if (node == dp->phandle) { 3089 if (dp == of_console_device) {
3107 struct fb_var_screeninfo *var = &default_var; 3090 struct fb_var_screeninfo *var = &default_var;
3108 unsigned int N, P, Q, M, T, R; 3091 unsigned int N, P, Q, M, T, R;
3109 u32 v_total, h_total; 3092 u32 v_total, h_total;
@@ -3111,9 +3094,9 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
3111 u8 pll_regs[16]; 3094 u8 pll_regs[16];
3112 u8 clock_cntl; 3095 u8 clock_cntl;
3113 3096
3114 crtc.vxres = prom_getintdefault(node, "width", 1024); 3097 crtc.vxres = of_getintprop_default(dp, "width", 1024);
3115 crtc.vyres = prom_getintdefault(node, "height", 768); 3098 crtc.vyres = of_getintprop_default(dp, "height", 768);
3116 var->bits_per_pixel = prom_getintdefault(node, "depth", 8); 3099 var->bits_per_pixel = of_getintprop_default(dp, "depth", 8);
3117 var->xoffset = var->yoffset = 0; 3100 var->xoffset = var->yoffset = 0;
3118 crtc.h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par); 3101 crtc.h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
3119 crtc.h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par); 3102 crtc.h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
@@ -3139,12 +3122,12 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
3139 M = pll_regs[2]; 3122 M = pll_regs[2];
3140 3123
3141 /* 3124 /*
3142 * PLL Feedback Divider N (Dependant on CLOCK_CNTL): 3125 * PLL Feedback Divider N (Dependent on CLOCK_CNTL):
3143 */ 3126 */
3144 N = pll_regs[7 + (clock_cntl & 3)]; 3127 N = pll_regs[7 + (clock_cntl & 3)];
3145 3128
3146 /* 3129 /*
3147 * PLL Post Divider P (Dependant on CLOCK_CNTL): 3130 * PLL Post Divider P (Dependent on CLOCK_CNTL):
3148 */ 3131 */
3149 P = 1 << (pll_regs[6] >> ((clock_cntl & 3) << 1)); 3132 P = 1 << (pll_regs[6] >> ((clock_cntl & 3) << 1));
3150 3133
diff --git a/drivers/video/aty/mach64_cursor.c b/drivers/video/aty/mach64_cursor.c
index 2ba8b3c421a1..46f72ed53510 100644
--- a/drivers/video/aty/mach64_cursor.c
+++ b/drivers/video/aty/mach64_cursor.c
@@ -51,7 +51,7 @@
51 * to a larger number and saturate CUR_HORZ_POSN to zero. 51 * to a larger number and saturate CUR_HORZ_POSN to zero.
52 * 52 *
53 * if Y becomes negative, CUR_VERT_OFFSET must be adjusted to a larger number, 53 * if Y becomes negative, CUR_VERT_OFFSET must be adjusted to a larger number,
54 * CUR_OFFSET must be adjusted to a point to the appropraite line in the cursor 54 * CUR_OFFSET must be adjusted to a point to the appropriate line in the cursor
55 * definitation and CUR_VERT_POSN must be saturated to zero. 55 * definitation and CUR_VERT_POSN must be saturated to zero.
56 */ 56 */
57 57
diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c
index 256966e9667d..db572df7e1ef 100644
--- a/drivers/video/aty/radeon_backlight.c
+++ b/drivers/video/aty/radeon_backlight.c
@@ -128,7 +128,7 @@ static int radeon_bl_get_brightness(struct backlight_device *bd)
128 return bd->props.brightness; 128 return bd->props.brightness;
129} 129}
130 130
131static struct backlight_ops radeon_bl_data = { 131static const struct backlight_ops radeon_bl_data = {
132 .get_brightness = radeon_bl_get_brightness, 132 .get_brightness = radeon_bl_get_brightness,
133 .update_status = radeon_bl_update_status, 133 .update_status = radeon_bl_update_status,
134}; 134};
@@ -158,6 +158,7 @@ void radeonfb_bl_init(struct radeonfb_info *rinfo)
158 snprintf(name, sizeof(name), "radeonbl%d", rinfo->info->node); 158 snprintf(name, sizeof(name), "radeonbl%d", rinfo->info->node);
159 159
160 memset(&props, 0, sizeof(struct backlight_properties)); 160 memset(&props, 0, sizeof(struct backlight_properties));
161 props.type = BACKLIGHT_RAW;
161 props.max_brightness = FB_BACKLIGHT_LEVELS - 1; 162 props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
162 bd = backlight_device_register(name, rinfo->info->dev, pdata, 163 bd = backlight_device_register(name, rinfo->info->dev, pdata,
163 &radeon_bl_data, &props); 164 &radeon_bl_data, &props);
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 3c1e13ed1cba..32f8cf6200a7 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -1248,7 +1248,7 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg
1248 1248
1249 /* Workaround from XFree */ 1249 /* Workaround from XFree */
1250 if (rinfo->is_mobility) { 1250 if (rinfo->is_mobility) {
1251 /* A temporal workaround for the occational blanking on certain laptop 1251 /* A temporal workaround for the occasional blanking on certain laptop
1252 * panels. This appears to related to the PLL divider registers 1252 * panels. This appears to related to the PLL divider registers
1253 * (fail to lock?). It occurs even when all dividers are the same 1253 * (fail to lock?). It occurs even when all dividers are the same
1254 * with their old settings. In this case we really don't need to 1254 * with their old settings. In this case we really don't need to
diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c
index 359fc64e761a..ab1d0fd76316 100644
--- a/drivers/video/aty/radeon_i2c.c
+++ b/drivers/video/aty/radeon_i2c.c
@@ -7,7 +7,6 @@
7 7
8 8
9#include <linux/i2c.h> 9#include <linux/i2c.h>
10#include <linux/i2c-id.h>
11#include <linux/i2c-algo-bit.h> 10#include <linux/i2c-algo-bit.h>
12 11
13#include <asm/io.h> 12#include <asm/io.h>
@@ -101,6 +100,9 @@ void radeon_create_i2c_busses(struct radeonfb_info *rinfo)
101{ 100{
102 rinfo->i2c[0].rinfo = rinfo; 101 rinfo->i2c[0].rinfo = rinfo;
103 rinfo->i2c[0].ddc_reg = GPIO_MONID; 102 rinfo->i2c[0].ddc_reg = GPIO_MONID;
103#ifndef CONFIG_PPC
104 rinfo->i2c[0].adapter.class = I2C_CLASS_HWMON;
105#endif
104 radeon_setup_i2c_bus(&rinfo->i2c[0], "monid"); 106 radeon_setup_i2c_bus(&rinfo->i2c[0], "monid");
105 107
106 rinfo->i2c[1].rinfo = rinfo; 108 rinfo->i2c[1].rinfo = rinfo;
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index c4e17642d9c5..92bda5848516 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -2626,7 +2626,7 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
2626 goto done; 2626 goto done;
2627 } 2627 }
2628 2628
2629 acquire_console_sem(); 2629 console_lock();
2630 2630
2631 fb_set_suspend(info, 1); 2631 fb_set_suspend(info, 1);
2632 2632
@@ -2690,7 +2690,7 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
2690 if (rinfo->pm_mode & radeon_pm_d2) 2690 if (rinfo->pm_mode & radeon_pm_d2)
2691 radeon_set_suspend(rinfo, 1); 2691 radeon_set_suspend(rinfo, 1);
2692 2692
2693 release_console_sem(); 2693 console_unlock();
2694 2694
2695 done: 2695 done:
2696 pdev->dev.power.power_state = mesg; 2696 pdev->dev.power.power_state = mesg;
@@ -2715,10 +2715,10 @@ int radeonfb_pci_resume(struct pci_dev *pdev)
2715 return 0; 2715 return 0;
2716 2716
2717 if (rinfo->no_schedule) { 2717 if (rinfo->no_schedule) {
2718 if (try_acquire_console_sem()) 2718 if (!console_trylock())
2719 return 0; 2719 return 0;
2720 } else 2720 } else
2721 acquire_console_sem(); 2721 console_lock();
2722 2722
2723 printk(KERN_DEBUG "radeonfb (%s): resuming from state: %d...\n", 2723 printk(KERN_DEBUG "radeonfb (%s): resuming from state: %d...\n",
2724 pci_name(pdev), pdev->dev.power.power_state.event); 2724 pci_name(pdev), pdev->dev.power.power_state.event);
@@ -2783,7 +2783,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev)
2783 pdev->dev.power.power_state = PMSG_ON; 2783 pdev->dev.power.power_state = PMSG_ON;
2784 2784
2785 bail: 2785 bail:
2786 release_console_sem(); 2786 console_unlock();
2787 2787
2788 return rc; 2788 return rc;
2789} 2789}
diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c
index e77e8e4280fb..5dff32ac8044 100644
--- a/drivers/video/au1200fb.c
+++ b/drivers/video/au1200fb.c
@@ -1079,7 +1079,7 @@ static int au1200fb_fb_check_var(struct fb_var_screeninfo *var,
1079 * clock can only be obtain by dividing this value by an even integer. 1079 * clock can only be obtain by dividing this value by an even integer.
1080 * Fallback to a slower pixel clock if necessary. */ 1080 * Fallback to a slower pixel clock if necessary. */
1081 pixclock = max((u32)(PICOS2KHZ(var->pixclock) * 1000), fbi->monspecs.dclkmin); 1081 pixclock = max((u32)(PICOS2KHZ(var->pixclock) * 1000), fbi->monspecs.dclkmin);
1082 pixclock = min(pixclock, min(fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2)); 1082 pixclock = min3(pixclock, fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2);
1083 1083
1084 if (AU1200_LCD_MAX_CLK % pixclock) { 1084 if (AU1200_LCD_MAX_CLK % pixclock) {
1085 int diff = AU1200_LCD_MAX_CLK % pixclock; 1085 int diff = AU1200_LCD_MAX_CLK % pixclock;
@@ -1572,7 +1572,7 @@ static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev)
1572 /* Copy monitor specs from panel data */ 1572 /* Copy monitor specs from panel data */
1573 /* fixme: we're setting up LCD controller windows, so these dont give a 1573 /* fixme: we're setting up LCD controller windows, so these dont give a
1574 damn as to what the monitor specs are (the panel itself does, but that 1574 damn as to what the monitor specs are (the panel itself does, but that
1575 isnt done here...so maybe need a generic catchall monitor setting??? */ 1575 isn't done here...so maybe need a generic catchall monitor setting??? */
1576 memcpy(&fbi->monspecs, &panel->monspecs, sizeof(struct fb_monspecs)); 1576 memcpy(&fbi->monspecs, &panel->monspecs, sizeof(struct fb_monspecs));
1577 1577
1578 /* We first try the user mode passed in argument. If that failed, 1578 /* We first try the user mode passed in argument. If that failed,
diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c
index 38ffc3fbcbe4..c04b94da81f7 100644
--- a/drivers/video/backlight/88pm860x_bl.c
+++ b/drivers/video/backlight/88pm860x_bl.c
@@ -12,16 +12,16 @@
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/kernel.h> 13#include <linux/kernel.h>
14#include <linux/platform_device.h> 14#include <linux/platform_device.h>
15#include <linux/slab.h>
15#include <linux/fb.h> 16#include <linux/fb.h>
16#include <linux/i2c.h> 17#include <linux/i2c.h>
17#include <linux/backlight.h> 18#include <linux/backlight.h>
18#include <linux/mfd/88pm860x.h> 19#include <linux/mfd/88pm860x.h>
19#include <linux/slab.h>
20 20
21#define MAX_BRIGHTNESS (0xFF) 21#define MAX_BRIGHTNESS (0xFF)
22#define MIN_BRIGHTNESS (0) 22#define MIN_BRIGHTNESS (0)
23 23
24#define CURRENT_MASK (0x1F << 1) 24#define CURRENT_BITMASK (0x1F << 1)
25 25
26struct pm860x_backlight_data { 26struct pm860x_backlight_data {
27 struct pm860x_chip *chip; 27 struct pm860x_chip *chip;
@@ -85,7 +85,7 @@ static int pm860x_backlight_set(struct backlight_device *bl, int brightness)
85 if ((data->current_brightness == 0) && brightness) { 85 if ((data->current_brightness == 0) && brightness) {
86 if (data->iset) { 86 if (data->iset) {
87 ret = pm860x_set_bits(data->i2c, wled_idc(data->port), 87 ret = pm860x_set_bits(data->i2c, wled_idc(data->port),
88 CURRENT_MASK, data->iset); 88 CURRENT_BITMASK, data->iset);
89 if (ret < 0) 89 if (ret < 0)
90 goto out; 90 goto out;
91 } 91 }
@@ -155,35 +155,15 @@ out:
155 return -EINVAL; 155 return -EINVAL;
156} 156}
157 157
158static struct backlight_ops pm860x_backlight_ops = { 158static const struct backlight_ops pm860x_backlight_ops = {
159 .options = BL_CORE_SUSPENDRESUME, 159 .options = BL_CORE_SUSPENDRESUME,
160 .update_status = pm860x_backlight_update_status, 160 .update_status = pm860x_backlight_update_status,
161 .get_brightness = pm860x_backlight_get_brightness, 161 .get_brightness = pm860x_backlight_get_brightness,
162}; 162};
163 163
164static int __check_device(struct pm860x_backlight_pdata *pdata, char *name)
165{
166 struct pm860x_backlight_pdata *p = pdata;
167 int ret = -EINVAL;
168
169 while (p && p->id) {
170 if ((p->id != PM8606_ID_BACKLIGHT) || (p->flags < 0))
171 break;
172
173 if (!strncmp(name, pm860x_backlight_name[p->flags],
174 MFD_NAME_SIZE)) {
175 ret = (int)p->flags;
176 break;
177 }
178 p++;
179 }
180 return ret;
181}
182
183static int pm860x_backlight_probe(struct platform_device *pdev) 164static int pm860x_backlight_probe(struct platform_device *pdev)
184{ 165{
185 struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); 166 struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
186 struct pm860x_platform_data *pm860x_pdata;
187 struct pm860x_backlight_pdata *pdata = NULL; 167 struct pm860x_backlight_pdata *pdata = NULL;
188 struct pm860x_backlight_data *data; 168 struct pm860x_backlight_data *data;
189 struct backlight_device *bl; 169 struct backlight_device *bl;
@@ -199,10 +179,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
199 return -EINVAL; 179 return -EINVAL;
200 } 180 }
201 181
202 if (pdev->dev.parent->platform_data) { 182 pdata = pdev->dev.platform_data;
203 pm860x_pdata = pdev->dev.parent->platform_data;
204 pdata = pm860x_pdata->backlight;
205 }
206 if (pdata == NULL) { 183 if (pdata == NULL) {
207 dev_err(&pdev->dev, "platform data isn't assigned to " 184 dev_err(&pdev->dev, "platform data isn't assigned to "
208 "backlight\n"); 185 "backlight\n");
@@ -219,7 +196,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
219 data->current_brightness = MAX_BRIGHTNESS; 196 data->current_brightness = MAX_BRIGHTNESS;
220 data->pwm = pdata->pwm; 197 data->pwm = pdata->pwm;
221 data->iset = pdata->iset; 198 data->iset = pdata->iset;
222 data->port = __check_device(pdata, name); 199 data->port = pdata->flags;
223 if (data->port < 0) { 200 if (data->port < 0) {
224 dev_err(&pdev->dev, "wrong platform data is assigned"); 201 dev_err(&pdev->dev, "wrong platform data is assigned");
225 kfree(data); 202 kfree(data);
@@ -227,6 +204,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
227 } 204 }
228 205
229 memset(&props, 0, sizeof(struct backlight_properties)); 206 memset(&props, 0, sizeof(struct backlight_properties));
207 props.type = BACKLIGHT_RAW;
230 props.max_brightness = MAX_BRIGHTNESS; 208 props.max_brightness = MAX_BRIGHTNESS;
231 bl = backlight_device_register(name, &pdev->dev, data, 209 bl = backlight_device_register(name, &pdev->dev, data,
232 &pm860x_backlight_ops, &props); 210 &pm860x_backlight_ops, &props);
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index e54a337227ea..2d93c8d61ad5 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -109,6 +109,14 @@ config LCD_S6E63M0
109 If you have an S6E63M0 LCD Panel, say Y to enable its 109 If you have an S6E63M0 LCD Panel, say Y to enable its
110 LCD control driver. 110 LCD control driver.
111 111
112config LCD_LD9040
113 tristate "LD9040 AMOLED LCD Driver"
114 depends on SPI && BACKLIGHT_CLASS_DEVICE
115 default n
116 help
117 If you have an LD9040 Panel, say Y to enable its
118 control driver.
119
112endif # LCD_CLASS_DEVICE 120endif # LCD_CLASS_DEVICE
113 121
114# 122#
@@ -236,12 +244,12 @@ config BACKLIGHT_MAX8925
236 If you have a LCD backlight connected to the WLED output of MAX8925 244 If you have a LCD backlight connected to the WLED output of MAX8925
237 WLED output, say Y here to enable this driver. 245 WLED output, say Y here to enable this driver.
238 246
239config BACKLIGHT_MBP_NVIDIA 247config BACKLIGHT_APPLE
240 tristate "MacBook Pro Nvidia Backlight Driver" 248 tristate "Apple Backlight Driver"
241 depends on X86 249 depends on X86 && ACPI
242 help 250 help
243 If you have an Apple Macbook Pro with Nvidia graphics hardware say Y 251 If you have an Intel-based Apple say Y to enable a driver for its
244 to enable a driver for its backlight 252 backlight.
245 253
246config BACKLIGHT_TOSA 254config BACKLIGHT_TOSA
247 tristate "Sharp SL-6000 Backlight Driver" 255 tristate "Sharp SL-6000 Backlight Driver"
@@ -294,6 +302,18 @@ config BACKLIGHT_ADP8860
294 To compile this driver as a module, choose M here: the module will 302 To compile this driver as a module, choose M here: the module will
295 be called adp8860_bl. 303 be called adp8860_bl.
296 304
305config BACKLIGHT_ADP8870
306 tristate "Backlight Driver for ADP8870 using WLED"
307 depends on BACKLIGHT_CLASS_DEVICE && I2C
308 select NEW_LEDS
309 select LEDS_CLASS
310 help
311 If you have a LCD backlight connected to the ADP8870,
312 say Y here to enable this driver.
313
314 To compile this driver as a module, choose M here: the module will
315 be called adp8870_bl.
316
297config BACKLIGHT_88PM860X 317config BACKLIGHT_88PM860X
298 tristate "Backlight Driver for 88PM8606 using WLED" 318 tristate "Backlight Driver for 88PM8606 using WLED"
299 depends on MFD_88PM860X 319 depends on MFD_88PM860X
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 44c0f81ad85d..ee72adb8786e 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o
12obj-$(CONFIG_LCD_TDO24M) += tdo24m.o 12obj-$(CONFIG_LCD_TDO24M) += tdo24m.o
13obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o 13obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o
14obj-$(CONFIG_LCD_S6E63M0) += s6e63m0.o 14obj-$(CONFIG_LCD_S6E63M0) += s6e63m0.o
15obj-$(CONFIG_LCD_LD9040) += ld9040.o
15 16
16obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o 17obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
17obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o 18obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o
@@ -26,13 +27,14 @@ obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o
26obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o 27obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o
27obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o 28obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o
28obj-$(CONFIG_BACKLIGHT_MAX8925) += max8925_bl.o 29obj-$(CONFIG_BACKLIGHT_MAX8925) += max8925_bl.o
29obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o 30obj-$(CONFIG_BACKLIGHT_APPLE) += apple_bl.o
30obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o 31obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o
31obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o 32obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
32obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o 33obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o
33obj-$(CONFIG_BACKLIGHT_ADX) += adx_bl.o 34obj-$(CONFIG_BACKLIGHT_ADX) += adx_bl.o
34obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o 35obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o
35obj-$(CONFIG_BACKLIGHT_ADP8860) += adp8860_bl.o 36obj-$(CONFIG_BACKLIGHT_ADP8860) += adp8860_bl.o
37obj-$(CONFIG_BACKLIGHT_ADP8870) += adp8870_bl.o
36obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o 38obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o
37obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o 39obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o
38 40
diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c
index 9f436e014f85..d1aee730d7d8 100644
--- a/drivers/video/backlight/adp5520_bl.c
+++ b/drivers/video/backlight/adp5520_bl.c
@@ -211,8 +211,12 @@ static ssize_t adp5520_bl_daylight_max_store(struct device *dev,
211 const char *buf, size_t count) 211 const char *buf, size_t count)
212{ 212{
213 struct adp5520_bl *data = dev_get_drvdata(dev); 213 struct adp5520_bl *data = dev_get_drvdata(dev);
214 int ret;
215
216 ret = strict_strtoul(buf, 10, &data->cached_daylight_max);
217 if (ret < 0)
218 return ret;
214 219
215 strict_strtoul(buf, 10, &data->cached_daylight_max);
216 return adp5520_store(dev, buf, count, ADP5520_DAYLIGHT_MAX); 220 return adp5520_store(dev, buf, count, ADP5520_DAYLIGHT_MAX);
217} 221}
218static DEVICE_ATTR(daylight_max, 0664, adp5520_bl_daylight_max_show, 222static DEVICE_ATTR(daylight_max, 0664, adp5520_bl_daylight_max_show,
@@ -303,6 +307,7 @@ static int __devinit adp5520_bl_probe(struct platform_device *pdev)
303 mutex_init(&data->lock); 307 mutex_init(&data->lock);
304 308
305 memset(&props, 0, sizeof(struct backlight_properties)); 309 memset(&props, 0, sizeof(struct backlight_properties));
310 props.type = BACKLIGHT_RAW;
306 props.max_brightness = ADP5020_MAX_BRIGHTNESS; 311 props.max_brightness = ADP5020_MAX_BRIGHTNESS;
307 bl = backlight_device_register(pdev->name, data->master, data, 312 bl = backlight_device_register(pdev->name, data->master, data,
308 &adp5520_bl_ops, &props); 313 &adp5520_bl_ops, &props);
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
index 3ec24609151e..d2a96a421ffd 100644
--- a/drivers/video/backlight/adp8860_bl.c
+++ b/drivers/video/backlight/adp8860_bl.c
@@ -502,8 +502,10 @@ static ssize_t adp8860_bl_l1_daylight_max_store(struct device *dev,
502 struct device_attribute *attr, const char *buf, size_t count) 502 struct device_attribute *attr, const char *buf, size_t count)
503{ 503{
504 struct adp8860_bl *data = dev_get_drvdata(dev); 504 struct adp8860_bl *data = dev_get_drvdata(dev);
505 int ret = strict_strtoul(buf, 10, &data->cached_daylight_max);
506 if (ret)
507 return ret;
505 508
506 strict_strtoul(buf, 10, &data->cached_daylight_max);
507 return adp8860_store(dev, buf, count, ADP8860_BLMX1); 509 return adp8860_store(dev, buf, count, ADP8860_BLMX1);
508} 510}
509static DEVICE_ATTR(l1_daylight_max, 0664, adp8860_bl_l1_daylight_max_show, 511static DEVICE_ATTR(l1_daylight_max, 0664, adp8860_bl_l1_daylight_max_show,
@@ -614,7 +616,7 @@ static ssize_t adp8860_bl_ambient_light_zone_store(struct device *dev,
614 if (val == 0) { 616 if (val == 0) {
615 /* Enable automatic ambient light sensing */ 617 /* Enable automatic ambient light sensing */
616 adp8860_set_bits(data->client, ADP8860_MDCR, CMP_AUTOEN); 618 adp8860_set_bits(data->client, ADP8860_MDCR, CMP_AUTOEN);
617 } else if ((val > 0) && (val < 6)) { 619 } else if ((val > 0) && (val <= 3)) {
618 /* Disable automatic ambient light sensing */ 620 /* Disable automatic ambient light sensing */
619 adp8860_clr_bits(data->client, ADP8860_MDCR, CMP_AUTOEN); 621 adp8860_clr_bits(data->client, ADP8860_MDCR, CMP_AUTOEN);
620 622
@@ -622,7 +624,7 @@ static ssize_t adp8860_bl_ambient_light_zone_store(struct device *dev,
622 mutex_lock(&data->lock); 624 mutex_lock(&data->lock);
623 adp8860_read(data->client, ADP8860_CFGR, &reg_val); 625 adp8860_read(data->client, ADP8860_CFGR, &reg_val);
624 reg_val &= ~(CFGR_BLV_MASK << CFGR_BLV_SHIFT); 626 reg_val &= ~(CFGR_BLV_MASK << CFGR_BLV_SHIFT);
625 reg_val |= val << CFGR_BLV_SHIFT; 627 reg_val |= (val - 1) << CFGR_BLV_SHIFT;
626 adp8860_write(data->client, ADP8860_CFGR, reg_val); 628 adp8860_write(data->client, ADP8860_CFGR, reg_val);
627 mutex_unlock(&data->lock); 629 mutex_unlock(&data->lock);
628 } 630 }
@@ -707,6 +709,7 @@ static int __devinit adp8860_probe(struct i2c_client *client,
707 i2c_set_clientdata(client, data); 709 i2c_set_clientdata(client, data);
708 710
709 memset(&props, 0, sizeof(props)); 711 memset(&props, 0, sizeof(props));
712 props.type = BACKLIGHT_RAW;
710 props.max_brightness = ADP8860_MAX_BRIGHTNESS; 713 props.max_brightness = ADP8860_MAX_BRIGHTNESS;
711 714
712 mutex_init(&data->lock); 715 mutex_init(&data->lock);
diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c
new file mode 100644
index 000000000000..05a8832bb3eb
--- /dev/null
+++ b/drivers/video/backlight/adp8870_bl.c
@@ -0,0 +1,1012 @@
1/*
2 * Backlight driver for Analog Devices ADP8870 Backlight Devices
3 *
4 * Copyright 2009-2011 Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#include <linux/module.h>
10#include <linux/version.h>
11#include <linux/init.h>
12#include <linux/errno.h>
13#include <linux/pm.h>
14#include <linux/platform_device.h>
15#include <linux/i2c.h>
16#include <linux/fb.h>
17#include <linux/backlight.h>
18#include <linux/leds.h>
19#include <linux/workqueue.h>
20#include <linux/slab.h>
21
22#include <linux/i2c/adp8870.h>
23#define ADP8870_EXT_FEATURES
24#define ADP8870_USE_LEDS
25
26
27#define ADP8870_MFDVID 0x00 /* Manufacturer and device ID */
28#define ADP8870_MDCR 0x01 /* Device mode and status */
29#define ADP8870_INT_STAT 0x02 /* Interrupts status */
30#define ADP8870_INT_EN 0x03 /* Interrupts enable */
31#define ADP8870_CFGR 0x04 /* Configuration register */
32#define ADP8870_BLSEL 0x05 /* Sink enable backlight or independent */
33#define ADP8870_PWMLED 0x06 /* PWM Enable Selection Register */
34#define ADP8870_BLOFF 0x07 /* Backlight off timeout */
35#define ADP8870_BLDIM 0x08 /* Backlight dim timeout */
36#define ADP8870_BLFR 0x09 /* Backlight fade in and out rates */
37#define ADP8870_BLMX1 0x0A /* Backlight (Brightness Level 1-daylight) maximum current */
38#define ADP8870_BLDM1 0x0B /* Backlight (Brightness Level 1-daylight) dim current */
39#define ADP8870_BLMX2 0x0C /* Backlight (Brightness Level 2-bright) maximum current */
40#define ADP8870_BLDM2 0x0D /* Backlight (Brightness Level 2-bright) dim current */
41#define ADP8870_BLMX3 0x0E /* Backlight (Brightness Level 3-office) maximum current */
42#define ADP8870_BLDM3 0x0F /* Backlight (Brightness Level 3-office) dim current */
43#define ADP8870_BLMX4 0x10 /* Backlight (Brightness Level 4-indoor) maximum current */
44#define ADP8870_BLDM4 0x11 /* Backlight (Brightness Level 4-indoor) dim current */
45#define ADP8870_BLMX5 0x12 /* Backlight (Brightness Level 5-dark) maximum current */
46#define ADP8870_BLDM5 0x13 /* Backlight (Brightness Level 5-dark) dim current */
47#define ADP8870_ISCLAW 0x1A /* Independent sink current fade law register */
48#define ADP8870_ISCC 0x1B /* Independent sink current control register */
49#define ADP8870_ISCT1 0x1C /* Independent Sink Current Timer Register LED[7:5] */
50#define ADP8870_ISCT2 0x1D /* Independent Sink Current Timer Register LED[4:1] */
51#define ADP8870_ISCF 0x1E /* Independent sink current fade register */
52#define ADP8870_ISC1 0x1F /* Independent Sink Current LED1 */
53#define ADP8870_ISC2 0x20 /* Independent Sink Current LED2 */
54#define ADP8870_ISC3 0x21 /* Independent Sink Current LED3 */
55#define ADP8870_ISC4 0x22 /* Independent Sink Current LED4 */
56#define ADP8870_ISC5 0x23 /* Independent Sink Current LED5 */
57#define ADP8870_ISC6 0x24 /* Independent Sink Current LED6 */
58#define ADP8870_ISC7 0x25 /* Independent Sink Current LED7 (Brightness Level 1-daylight) */
59#define ADP8870_ISC7_L2 0x26 /* Independent Sink Current LED7 (Brightness Level 2-bright) */
60#define ADP8870_ISC7_L3 0x27 /* Independent Sink Current LED7 (Brightness Level 3-office) */
61#define ADP8870_ISC7_L4 0x28 /* Independent Sink Current LED7 (Brightness Level 4-indoor) */
62#define ADP8870_ISC7_L5 0x29 /* Independent Sink Current LED7 (Brightness Level 5-dark) */
63#define ADP8870_CMP_CTL 0x2D /* ALS Comparator Control Register */
64#define ADP8870_ALS1_EN 0x2E /* Main ALS comparator level enable */
65#define ADP8870_ALS2_EN 0x2F /* Second ALS comparator level enable */
66#define ADP8870_ALS1_STAT 0x30 /* Main ALS Comparator Status Register */
67#define ADP8870_ALS2_STAT 0x31 /* Second ALS Comparator Status Register */
68#define ADP8870_L2TRP 0x32 /* L2 comparator reference */
69#define ADP8870_L2HYS 0x33 /* L2 hysteresis */
70#define ADP8870_L3TRP 0x34 /* L3 comparator reference */
71#define ADP8870_L3HYS 0x35 /* L3 hysteresis */
72#define ADP8870_L4TRP 0x36 /* L4 comparator reference */
73#define ADP8870_L4HYS 0x37 /* L4 hysteresis */
74#define ADP8870_L5TRP 0x38 /* L5 comparator reference */
75#define ADP8870_L5HYS 0x39 /* L5 hysteresis */
76#define ADP8870_PH1LEVL 0x40 /* First phototransistor ambient light level-low byte register */
77#define ADP8870_PH1LEVH 0x41 /* First phototransistor ambient light level-high byte register */
78#define ADP8870_PH2LEVL 0x42 /* Second phototransistor ambient light level-low byte register */
79#define ADP8870_PH2LEVH 0x43 /* Second phototransistor ambient light level-high byte register */
80
81#define ADP8870_MANUFID 0x3 /* Analog Devices AD8870 Manufacturer and device ID */
82#define ADP8870_DEVID(x) ((x) & 0xF)
83#define ADP8870_MANID(x) ((x) >> 4)
84
85/* MDCR Device mode and status */
86#define D7ALSEN (1 << 7)
87#define INT_CFG (1 << 6)
88#define NSTBY (1 << 5)
89#define DIM_EN (1 << 4)
90#define GDWN_DIS (1 << 3)
91#define SIS_EN (1 << 2)
92#define CMP_AUTOEN (1 << 1)
93#define BLEN (1 << 0)
94
95/* ADP8870_ALS1_EN Main ALS comparator level enable */
96#define L5_EN (1 << 3)
97#define L4_EN (1 << 2)
98#define L3_EN (1 << 1)
99#define L2_EN (1 << 0)
100
101#define CFGR_BLV_SHIFT 3
102#define CFGR_BLV_MASK 0x7
103#define ADP8870_FLAG_LED_MASK 0xFF
104
105#define FADE_VAL(in, out) ((0xF & (in)) | ((0xF & (out)) << 4))
106#define BL_CFGR_VAL(law, blv) ((((blv) & CFGR_BLV_MASK) << CFGR_BLV_SHIFT) | ((0x3 & (law)) << 1))
107#define ALS_CMPR_CFG_VAL(filt) ((0x7 & (filt)) << 1)
108
109struct adp8870_bl {
110 struct i2c_client *client;
111 struct backlight_device *bl;
112 struct adp8870_led *led;
113 struct adp8870_backlight_platform_data *pdata;
114 struct mutex lock;
115 unsigned long cached_daylight_max;
116 int id;
117 int revid;
118 int current_brightness;
119};
120
121struct adp8870_led {
122 struct led_classdev cdev;
123 struct work_struct work;
124 struct i2c_client *client;
125 enum led_brightness new_brightness;
126 int id;
127 int flags;
128};
129
130static int adp8870_read(struct i2c_client *client, int reg, uint8_t *val)
131{
132 int ret;
133
134 ret = i2c_smbus_read_byte_data(client, reg);
135 if (ret < 0) {
136 dev_err(&client->dev, "failed reading at 0x%02x\n", reg);
137 return ret;
138 }
139
140 *val = ret;
141 return 0;
142}
143
144
145static int adp8870_write(struct i2c_client *client, u8 reg, u8 val)
146{
147 int ret = i2c_smbus_write_byte_data(client, reg, val);
148 if (ret)
149 dev_err(&client->dev, "failed to write\n");
150
151 return ret;
152}
153
154static int adp8870_set_bits(struct i2c_client *client, int reg, uint8_t bit_mask)
155{
156 struct adp8870_bl *data = i2c_get_clientdata(client);
157 uint8_t reg_val;
158 int ret;
159
160 mutex_lock(&data->lock);
161
162 ret = adp8870_read(client, reg, &reg_val);
163
164 if (!ret && ((reg_val & bit_mask) == 0)) {
165 reg_val |= bit_mask;
166 ret = adp8870_write(client, reg, reg_val);
167 }
168
169 mutex_unlock(&data->lock);
170 return ret;
171}
172
173static int adp8870_clr_bits(struct i2c_client *client, int reg, uint8_t bit_mask)
174{
175 struct adp8870_bl *data = i2c_get_clientdata(client);
176 uint8_t reg_val;
177 int ret;
178
179 mutex_lock(&data->lock);
180
181 ret = adp8870_read(client, reg, &reg_val);
182
183 if (!ret && (reg_val & bit_mask)) {
184 reg_val &= ~bit_mask;
185 ret = adp8870_write(client, reg, reg_val);
186 }
187
188 mutex_unlock(&data->lock);
189 return ret;
190}
191
192/*
193 * Independent sink / LED
194 */
195#if defined(ADP8870_USE_LEDS)
196static void adp8870_led_work(struct work_struct *work)
197{
198 struct adp8870_led *led = container_of(work, struct adp8870_led, work);
199 adp8870_write(led->client, ADP8870_ISC1 + led->id - 1,
200 led->new_brightness >> 1);
201}
202
203static void adp8870_led_set(struct led_classdev *led_cdev,
204 enum led_brightness value)
205{
206 struct adp8870_led *led;
207
208 led = container_of(led_cdev, struct adp8870_led, cdev);
209 led->new_brightness = value;
210 /*
211 * Use workqueue for IO since I2C operations can sleep.
212 */
213 schedule_work(&led->work);
214}
215
216static int adp8870_led_setup(struct adp8870_led *led)
217{
218 struct i2c_client *client = led->client;
219 int ret = 0;
220
221 ret = adp8870_write(client, ADP8870_ISC1 + led->id - 1, 0);
222 if (ret)
223 return ret;
224
225 ret = adp8870_set_bits(client, ADP8870_ISCC, 1 << (led->id - 1));
226 if (ret)
227 return ret;
228
229 if (led->id > 4)
230 ret = adp8870_set_bits(client, ADP8870_ISCT1,
231 (led->flags & 0x3) << ((led->id - 5) * 2));
232 else
233 ret = adp8870_set_bits(client, ADP8870_ISCT2,
234 (led->flags & 0x3) << ((led->id - 1) * 2));
235
236 return ret;
237}
238
239static int __devinit adp8870_led_probe(struct i2c_client *client)
240{
241 struct adp8870_backlight_platform_data *pdata =
242 client->dev.platform_data;
243 struct adp8870_bl *data = i2c_get_clientdata(client);
244 struct adp8870_led *led, *led_dat;
245 struct led_info *cur_led;
246 int ret, i;
247
248
249 led = kcalloc(pdata->num_leds, sizeof(*led), GFP_KERNEL);
250 if (led == NULL) {
251 dev_err(&client->dev, "failed to alloc memory\n");
252 return -ENOMEM;
253 }
254
255 ret = adp8870_write(client, ADP8870_ISCLAW, pdata->led_fade_law);
256 if (ret)
257 goto err_free;
258
259 ret = adp8870_write(client, ADP8870_ISCT1,
260 (pdata->led_on_time & 0x3) << 6);
261 if (ret)
262 goto err_free;
263
264 ret = adp8870_write(client, ADP8870_ISCF,
265 FADE_VAL(pdata->led_fade_in, pdata->led_fade_out));
266 if (ret)
267 goto err_free;
268
269 for (i = 0; i < pdata->num_leds; ++i) {
270 cur_led = &pdata->leds[i];
271 led_dat = &led[i];
272
273 led_dat->id = cur_led->flags & ADP8870_FLAG_LED_MASK;
274
275 if (led_dat->id > 7 || led_dat->id < 1) {
276 dev_err(&client->dev, "Invalid LED ID %d\n",
277 led_dat->id);
278 goto err;
279 }
280
281 if (pdata->bl_led_assign & (1 << (led_dat->id - 1))) {
282 dev_err(&client->dev, "LED %d used by Backlight\n",
283 led_dat->id);
284 goto err;
285 }
286
287 led_dat->cdev.name = cur_led->name;
288 led_dat->cdev.default_trigger = cur_led->default_trigger;
289 led_dat->cdev.brightness_set = adp8870_led_set;
290 led_dat->cdev.brightness = LED_OFF;
291 led_dat->flags = cur_led->flags >> FLAG_OFFT_SHIFT;
292 led_dat->client = client;
293 led_dat->new_brightness = LED_OFF;
294 INIT_WORK(&led_dat->work, adp8870_led_work);
295
296 ret = led_classdev_register(&client->dev, &led_dat->cdev);
297 if (ret) {
298 dev_err(&client->dev, "failed to register LED %d\n",
299 led_dat->id);
300 goto err;
301 }
302
303 ret = adp8870_led_setup(led_dat);
304 if (ret) {
305 dev_err(&client->dev, "failed to write\n");
306 i++;
307 goto err;
308 }
309 }
310
311 data->led = led;
312
313 return 0;
314
315 err:
316 for (i = i - 1; i >= 0; --i) {
317 led_classdev_unregister(&led[i].cdev);
318 cancel_work_sync(&led[i].work);
319 }
320
321 err_free:
322 kfree(led);
323
324 return ret;
325}
326
327static int __devexit adp8870_led_remove(struct i2c_client *client)
328{
329 struct adp8870_backlight_platform_data *pdata =
330 client->dev.platform_data;
331 struct adp8870_bl *data = i2c_get_clientdata(client);
332 int i;
333
334 for (i = 0; i < pdata->num_leds; i++) {
335 led_classdev_unregister(&data->led[i].cdev);
336 cancel_work_sync(&data->led[i].work);
337 }
338
339 kfree(data->led);
340 return 0;
341}
342#else
343static int __devinit adp8870_led_probe(struct i2c_client *client)
344{
345 return 0;
346}
347
348static int __devexit adp8870_led_remove(struct i2c_client *client)
349{
350 return 0;
351}
352#endif
353
354static int adp8870_bl_set(struct backlight_device *bl, int brightness)
355{
356 struct adp8870_bl *data = bl_get_data(bl);
357 struct i2c_client *client = data->client;
358 int ret = 0;
359
360 if (data->pdata->en_ambl_sens) {
361 if ((brightness > 0) && (brightness < ADP8870_MAX_BRIGHTNESS)) {
362 /* Disable Ambient Light auto adjust */
363 ret = adp8870_clr_bits(client, ADP8870_MDCR,
364 CMP_AUTOEN);
365 if (ret)
366 return ret;
367 ret = adp8870_write(client, ADP8870_BLMX1, brightness);
368 if (ret)
369 return ret;
370 } else {
371 /*
372 * MAX_BRIGHTNESS -> Enable Ambient Light auto adjust
373 * restore daylight l1 sysfs brightness
374 */
375 ret = adp8870_write(client, ADP8870_BLMX1,
376 data->cached_daylight_max);
377 if (ret)
378 return ret;
379
380 ret = adp8870_set_bits(client, ADP8870_MDCR,
381 CMP_AUTOEN);
382 if (ret)
383 return ret;
384 }
385 } else {
386 ret = adp8870_write(client, ADP8870_BLMX1, brightness);
387 if (ret)
388 return ret;
389 }
390
391 if (data->current_brightness && brightness == 0)
392 ret = adp8870_set_bits(client,
393 ADP8870_MDCR, DIM_EN);
394 else if (data->current_brightness == 0 && brightness)
395 ret = adp8870_clr_bits(client,
396 ADP8870_MDCR, DIM_EN);
397
398 if (!ret)
399 data->current_brightness = brightness;
400
401 return ret;
402}
403
404static int adp8870_bl_update_status(struct backlight_device *bl)
405{
406 int brightness = bl->props.brightness;
407 if (bl->props.power != FB_BLANK_UNBLANK)
408 brightness = 0;
409
410 if (bl->props.fb_blank != FB_BLANK_UNBLANK)
411 brightness = 0;
412
413 return adp8870_bl_set(bl, brightness);
414}
415
416static int adp8870_bl_get_brightness(struct backlight_device *bl)
417{
418 struct adp8870_bl *data = bl_get_data(bl);
419
420 return data->current_brightness;
421}
422
423static const struct backlight_ops adp8870_bl_ops = {
424 .update_status = adp8870_bl_update_status,
425 .get_brightness = adp8870_bl_get_brightness,
426};
427
428static int adp8870_bl_setup(struct backlight_device *bl)
429{
430 struct adp8870_bl *data = bl_get_data(bl);
431 struct i2c_client *client = data->client;
432 struct adp8870_backlight_platform_data *pdata = data->pdata;
433 int ret = 0;
434
435 ret = adp8870_write(client, ADP8870_BLSEL, ~pdata->bl_led_assign);
436 if (ret)
437 return ret;
438
439 ret = adp8870_write(client, ADP8870_PWMLED, pdata->pwm_assign);
440 if (ret)
441 return ret;
442
443 ret = adp8870_write(client, ADP8870_BLMX1, pdata->l1_daylight_max);
444 if (ret)
445 return ret;
446
447 ret = adp8870_write(client, ADP8870_BLDM1, pdata->l1_daylight_dim);
448 if (ret)
449 return ret;
450
451 if (pdata->en_ambl_sens) {
452 data->cached_daylight_max = pdata->l1_daylight_max;
453 ret = adp8870_write(client, ADP8870_BLMX2,
454 pdata->l2_bright_max);
455 if (ret)
456 return ret;
457 ret = adp8870_write(client, ADP8870_BLDM2,
458 pdata->l2_bright_dim);
459 if (ret)
460 return ret;
461
462 ret = adp8870_write(client, ADP8870_BLMX3,
463 pdata->l3_office_max);
464 if (ret)
465 return ret;
466 ret = adp8870_write(client, ADP8870_BLDM3,
467 pdata->l3_office_dim);
468 if (ret)
469 return ret;
470
471 ret = adp8870_write(client, ADP8870_BLMX4,
472 pdata->l4_indoor_max);
473 if (ret)
474 return ret;
475
476 ret = adp8870_write(client, ADP8870_BLDM4,
477 pdata->l4_indor_dim);
478 if (ret)
479 return ret;
480
481 ret = adp8870_write(client, ADP8870_BLMX5,
482 pdata->l5_dark_max);
483 if (ret)
484 return ret;
485
486 ret = adp8870_write(client, ADP8870_BLDM5,
487 pdata->l5_dark_dim);
488 if (ret)
489 return ret;
490
491 ret = adp8870_write(client, ADP8870_L2TRP, pdata->l2_trip);
492 if (ret)
493 return ret;
494
495 ret = adp8870_write(client, ADP8870_L2HYS, pdata->l2_hyst);
496 if (ret)
497 return ret;
498
499 ret = adp8870_write(client, ADP8870_L3TRP, pdata->l3_trip);
500 if (ret)
501 return ret;
502
503 ret = adp8870_write(client, ADP8870_L3HYS, pdata->l3_hyst);
504 if (ret)
505 return ret;
506
507 ret = adp8870_write(client, ADP8870_L4TRP, pdata->l4_trip);
508 if (ret)
509 return ret;
510
511 ret = adp8870_write(client, ADP8870_L4HYS, pdata->l4_hyst);
512 if (ret)
513 return ret;
514
515 ret = adp8870_write(client, ADP8870_L5TRP, pdata->l5_trip);
516 if (ret)
517 return ret;
518
519 ret = adp8870_write(client, ADP8870_L5HYS, pdata->l5_hyst);
520 if (ret)
521 return ret;
522
523 ret = adp8870_write(client, ADP8870_ALS1_EN, L5_EN | L4_EN |
524 L3_EN | L2_EN);
525 if (ret)
526 return ret;
527
528 ret = adp8870_write(client, ADP8870_CMP_CTL,
529 ALS_CMPR_CFG_VAL(pdata->abml_filt));
530 if (ret)
531 return ret;
532 }
533
534 ret = adp8870_write(client, ADP8870_CFGR,
535 BL_CFGR_VAL(pdata->bl_fade_law, 0));
536 if (ret)
537 return ret;
538
539 ret = adp8870_write(client, ADP8870_BLFR, FADE_VAL(pdata->bl_fade_in,
540 pdata->bl_fade_out));
541 if (ret)
542 return ret;
543 /*
544 * ADP8870 Rev0 requires GDWN_DIS bit set
545 */
546
547 ret = adp8870_set_bits(client, ADP8870_MDCR, BLEN | DIM_EN | NSTBY |
548 (data->revid == 0 ? GDWN_DIS : 0));
549
550 return ret;
551}
552
553static ssize_t adp8870_show(struct device *dev, char *buf, int reg)
554{
555 struct adp8870_bl *data = dev_get_drvdata(dev);
556 int error;
557 uint8_t reg_val;
558
559 mutex_lock(&data->lock);
560 error = adp8870_read(data->client, reg, &reg_val);
561 mutex_unlock(&data->lock);
562
563 if (error < 0)
564 return error;
565
566 return sprintf(buf, "%u\n", reg_val);
567}
568
569static ssize_t adp8870_store(struct device *dev, const char *buf,
570 size_t count, int reg)
571{
572 struct adp8870_bl *data = dev_get_drvdata(dev);
573 unsigned long val;
574 int ret;
575
576 ret = strict_strtoul(buf, 10, &val);
577 if (ret)
578 return ret;
579
580 mutex_lock(&data->lock);
581 adp8870_write(data->client, reg, val);
582 mutex_unlock(&data->lock);
583
584 return count;
585}
586
587static ssize_t adp8870_bl_l5_dark_max_show(struct device *dev,
588 struct device_attribute *attr, char *buf)
589{
590 return adp8870_show(dev, buf, ADP8870_BLMX5);
591}
592
593static ssize_t adp8870_bl_l5_dark_max_store(struct device *dev,
594 struct device_attribute *attr, const char *buf, size_t count)
595{
596 return adp8870_store(dev, buf, count, ADP8870_BLMX5);
597}
598static DEVICE_ATTR(l5_dark_max, 0664, adp8870_bl_l5_dark_max_show,
599 adp8870_bl_l5_dark_max_store);
600
601
602static ssize_t adp8870_bl_l4_indoor_max_show(struct device *dev,
603 struct device_attribute *attr, char *buf)
604{
605 return adp8870_show(dev, buf, ADP8870_BLMX4);
606}
607
608static ssize_t adp8870_bl_l4_indoor_max_store(struct device *dev,
609 struct device_attribute *attr, const char *buf, size_t count)
610{
611 return adp8870_store(dev, buf, count, ADP8870_BLMX4);
612}
613static DEVICE_ATTR(l4_indoor_max, 0664, adp8870_bl_l4_indoor_max_show,
614 adp8870_bl_l4_indoor_max_store);
615
616
617static ssize_t adp8870_bl_l3_office_max_show(struct device *dev,
618 struct device_attribute *attr, char *buf)
619{
620 return adp8870_show(dev, buf, ADP8870_BLMX3);
621}
622
623static ssize_t adp8870_bl_l3_office_max_store(struct device *dev,
624 struct device_attribute *attr, const char *buf, size_t count)
625{
626 return adp8870_store(dev, buf, count, ADP8870_BLMX3);
627}
628
629static DEVICE_ATTR(l3_office_max, 0664, adp8870_bl_l3_office_max_show,
630 adp8870_bl_l3_office_max_store);
631
632static ssize_t adp8870_bl_l2_bright_max_show(struct device *dev,
633 struct device_attribute *attr, char *buf)
634{
635 return adp8870_show(dev, buf, ADP8870_BLMX2);
636}
637
638static ssize_t adp8870_bl_l2_bright_max_store(struct device *dev,
639 struct device_attribute *attr, const char *buf, size_t count)
640{
641 return adp8870_store(dev, buf, count, ADP8870_BLMX2);
642}
643static DEVICE_ATTR(l2_bright_max, 0664, adp8870_bl_l2_bright_max_show,
644 adp8870_bl_l2_bright_max_store);
645
646static ssize_t adp8870_bl_l1_daylight_max_show(struct device *dev,
647 struct device_attribute *attr, char *buf)
648{
649 return adp8870_show(dev, buf, ADP8870_BLMX1);
650}
651
652static ssize_t adp8870_bl_l1_daylight_max_store(struct device *dev,
653 struct device_attribute *attr, const char *buf, size_t count)
654{
655 struct adp8870_bl *data = dev_get_drvdata(dev);
656 int ret = strict_strtoul(buf, 10, &data->cached_daylight_max);
657 if (ret)
658 return ret;
659
660 return adp8870_store(dev, buf, count, ADP8870_BLMX1);
661}
662static DEVICE_ATTR(l1_daylight_max, 0664, adp8870_bl_l1_daylight_max_show,
663 adp8870_bl_l1_daylight_max_store);
664
665static ssize_t adp8870_bl_l5_dark_dim_show(struct device *dev,
666 struct device_attribute *attr, char *buf)
667{
668 return adp8870_show(dev, buf, ADP8870_BLDM5);
669}
670
671static ssize_t adp8870_bl_l5_dark_dim_store(struct device *dev,
672 struct device_attribute *attr,
673 const char *buf, size_t count)
674{
675 return adp8870_store(dev, buf, count, ADP8870_BLDM5);
676}
677static DEVICE_ATTR(l5_dark_dim, 0664, adp8870_bl_l5_dark_dim_show,
678 adp8870_bl_l5_dark_dim_store);
679
680static ssize_t adp8870_bl_l4_indoor_dim_show(struct device *dev,
681 struct device_attribute *attr, char *buf)
682{
683 return adp8870_show(dev, buf, ADP8870_BLDM4);
684}
685
686static ssize_t adp8870_bl_l4_indoor_dim_store(struct device *dev,
687 struct device_attribute *attr,
688 const char *buf, size_t count)
689{
690 return adp8870_store(dev, buf, count, ADP8870_BLDM4);
691}
692static DEVICE_ATTR(l4_indoor_dim, 0664, adp8870_bl_l4_indoor_dim_show,
693 adp8870_bl_l4_indoor_dim_store);
694
695
696static ssize_t adp8870_bl_l3_office_dim_show(struct device *dev,
697 struct device_attribute *attr, char *buf)
698{
699 return adp8870_show(dev, buf, ADP8870_BLDM3);
700}
701
702static ssize_t adp8870_bl_l3_office_dim_store(struct device *dev,
703 struct device_attribute *attr,
704 const char *buf, size_t count)
705{
706 return adp8870_store(dev, buf, count, ADP8870_BLDM3);
707}
708static DEVICE_ATTR(l3_office_dim, 0664, adp8870_bl_l3_office_dim_show,
709 adp8870_bl_l3_office_dim_store);
710
711static ssize_t adp8870_bl_l2_bright_dim_show(struct device *dev,
712 struct device_attribute *attr, char *buf)
713{
714 return adp8870_show(dev, buf, ADP8870_BLDM2);
715}
716
717static ssize_t adp8870_bl_l2_bright_dim_store(struct device *dev,
718 struct device_attribute *attr,
719 const char *buf, size_t count)
720{
721 return adp8870_store(dev, buf, count, ADP8870_BLDM2);
722}
723static DEVICE_ATTR(l2_bright_dim, 0664, adp8870_bl_l2_bright_dim_show,
724 adp8870_bl_l2_bright_dim_store);
725
726static ssize_t adp8870_bl_l1_daylight_dim_show(struct device *dev,
727 struct device_attribute *attr, char *buf)
728{
729 return adp8870_show(dev, buf, ADP8870_BLDM1);
730}
731
732static ssize_t adp8870_bl_l1_daylight_dim_store(struct device *dev,
733 struct device_attribute *attr,
734 const char *buf, size_t count)
735{
736 return adp8870_store(dev, buf, count, ADP8870_BLDM1);
737}
738static DEVICE_ATTR(l1_daylight_dim, 0664, adp8870_bl_l1_daylight_dim_show,
739 adp8870_bl_l1_daylight_dim_store);
740
741#ifdef ADP8870_EXT_FEATURES
742static ssize_t adp8870_bl_ambient_light_level_show(struct device *dev,
743 struct device_attribute *attr, char *buf)
744{
745 struct adp8870_bl *data = dev_get_drvdata(dev);
746 int error;
747 uint8_t reg_val;
748 uint16_t ret_val;
749
750 mutex_lock(&data->lock);
751 error = adp8870_read(data->client, ADP8870_PH1LEVL, &reg_val);
752 if (error < 0) {
753 mutex_unlock(&data->lock);
754 return error;
755 }
756 ret_val = reg_val;
757 error = adp8870_read(data->client, ADP8870_PH1LEVH, &reg_val);
758 mutex_unlock(&data->lock);
759
760 if (error < 0)
761 return error;
762
763 /* Return 13-bit conversion value for the first light sensor */
764 ret_val += (reg_val & 0x1F) << 8;
765
766 return sprintf(buf, "%u\n", ret_val);
767}
768static DEVICE_ATTR(ambient_light_level, 0444,
769 adp8870_bl_ambient_light_level_show, NULL);
770
771static ssize_t adp8870_bl_ambient_light_zone_show(struct device *dev,
772 struct device_attribute *attr, char *buf)
773{
774 struct adp8870_bl *data = dev_get_drvdata(dev);
775 int error;
776 uint8_t reg_val;
777
778 mutex_lock(&data->lock);
779 error = adp8870_read(data->client, ADP8870_CFGR, &reg_val);
780 mutex_unlock(&data->lock);
781
782 if (error < 0)
783 return error;
784
785 return sprintf(buf, "%u\n",
786 ((reg_val >> CFGR_BLV_SHIFT) & CFGR_BLV_MASK) + 1);
787}
788
789static ssize_t adp8870_bl_ambient_light_zone_store(struct device *dev,
790 struct device_attribute *attr,
791 const char *buf, size_t count)
792{
793 struct adp8870_bl *data = dev_get_drvdata(dev);
794 unsigned long val;
795 uint8_t reg_val;
796 int ret;
797
798 ret = strict_strtoul(buf, 10, &val);
799 if (ret)
800 return ret;
801
802 if (val == 0) {
803 /* Enable automatic ambient light sensing */
804 adp8870_set_bits(data->client, ADP8870_MDCR, CMP_AUTOEN);
805 } else if ((val > 0) && (val < 6)) {
806 /* Disable automatic ambient light sensing */
807 adp8870_clr_bits(data->client, ADP8870_MDCR, CMP_AUTOEN);
808
809 /* Set user supplied ambient light zone */
810 mutex_lock(&data->lock);
811 adp8870_read(data->client, ADP8870_CFGR, &reg_val);
812 reg_val &= ~(CFGR_BLV_MASK << CFGR_BLV_SHIFT);
813 reg_val |= (val - 1) << CFGR_BLV_SHIFT;
814 adp8870_write(data->client, ADP8870_CFGR, reg_val);
815 mutex_unlock(&data->lock);
816 }
817
818 return count;
819}
820static DEVICE_ATTR(ambient_light_zone, 0664,
821 adp8870_bl_ambient_light_zone_show,
822 adp8870_bl_ambient_light_zone_store);
823#endif
824
825static struct attribute *adp8870_bl_attributes[] = {
826 &dev_attr_l5_dark_max.attr,
827 &dev_attr_l5_dark_dim.attr,
828 &dev_attr_l4_indoor_max.attr,
829 &dev_attr_l4_indoor_dim.attr,
830 &dev_attr_l3_office_max.attr,
831 &dev_attr_l3_office_dim.attr,
832 &dev_attr_l2_bright_max.attr,
833 &dev_attr_l2_bright_dim.attr,
834 &dev_attr_l1_daylight_max.attr,
835 &dev_attr_l1_daylight_dim.attr,
836#ifdef ADP8870_EXT_FEATURES
837 &dev_attr_ambient_light_level.attr,
838 &dev_attr_ambient_light_zone.attr,
839#endif
840 NULL
841};
842
843static const struct attribute_group adp8870_bl_attr_group = {
844 .attrs = adp8870_bl_attributes,
845};
846
847static int __devinit adp8870_probe(struct i2c_client *client,
848 const struct i2c_device_id *id)
849{
850 struct backlight_properties props;
851 struct backlight_device *bl;
852 struct adp8870_bl *data;
853 struct adp8870_backlight_platform_data *pdata =
854 client->dev.platform_data;
855 uint8_t reg_val;
856 int ret;
857
858 if (!i2c_check_functionality(client->adapter,
859 I2C_FUNC_SMBUS_BYTE_DATA)) {
860 dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
861 return -EIO;
862 }
863
864 if (!pdata) {
865 dev_err(&client->dev, "no platform data?\n");
866 return -EINVAL;
867 }
868
869 ret = adp8870_read(client, ADP8870_MFDVID, &reg_val);
870 if (ret < 0)
871 return -EIO;
872
873 if (ADP8870_MANID(reg_val) != ADP8870_MANUFID) {
874 dev_err(&client->dev, "failed to probe\n");
875 return -ENODEV;
876 }
877
878 data = kzalloc(sizeof(*data), GFP_KERNEL);
879 if (data == NULL)
880 return -ENOMEM;
881
882 data->revid = ADP8870_DEVID(reg_val);
883 data->client = client;
884 data->pdata = pdata;
885 data->id = id->driver_data;
886 data->current_brightness = 0;
887 i2c_set_clientdata(client, data);
888
889 mutex_init(&data->lock);
890
891 memset(&props, 0, sizeof(props));
892 props.type = BACKLIGHT_RAW;
893 props.max_brightness = props.brightness = ADP8870_MAX_BRIGHTNESS;
894 bl = backlight_device_register(dev_driver_string(&client->dev),
895 &client->dev, data, &adp8870_bl_ops, &props);
896 if (IS_ERR(bl)) {
897 dev_err(&client->dev, "failed to register backlight\n");
898 ret = PTR_ERR(bl);
899 goto out2;
900 }
901
902 data->bl = bl;
903
904 if (pdata->en_ambl_sens)
905 ret = sysfs_create_group(&bl->dev.kobj,
906 &adp8870_bl_attr_group);
907
908 if (ret) {
909 dev_err(&client->dev, "failed to register sysfs\n");
910 goto out1;
911 }
912
913 ret = adp8870_bl_setup(bl);
914 if (ret) {
915 ret = -EIO;
916 goto out;
917 }
918
919 backlight_update_status(bl);
920
921 dev_info(&client->dev, "Rev.%d Backlight\n", data->revid);
922
923 if (pdata->num_leds)
924 adp8870_led_probe(client);
925
926 return 0;
927
928out:
929 if (data->pdata->en_ambl_sens)
930 sysfs_remove_group(&data->bl->dev.kobj,
931 &adp8870_bl_attr_group);
932out1:
933 backlight_device_unregister(bl);
934out2:
935 i2c_set_clientdata(client, NULL);
936 kfree(data);
937
938 return ret;
939}
940
941static int __devexit adp8870_remove(struct i2c_client *client)
942{
943 struct adp8870_bl *data = i2c_get_clientdata(client);
944
945 adp8870_clr_bits(client, ADP8870_MDCR, NSTBY);
946
947 if (data->led)
948 adp8870_led_remove(client);
949
950 if (data->pdata->en_ambl_sens)
951 sysfs_remove_group(&data->bl->dev.kobj,
952 &adp8870_bl_attr_group);
953
954 backlight_device_unregister(data->bl);
955 i2c_set_clientdata(client, NULL);
956 kfree(data);
957
958 return 0;
959}
960
961#ifdef CONFIG_PM
962static int adp8870_i2c_suspend(struct i2c_client *client, pm_message_t message)
963{
964 adp8870_clr_bits(client, ADP8870_MDCR, NSTBY);
965
966 return 0;
967}
968
969static int adp8870_i2c_resume(struct i2c_client *client)
970{
971 adp8870_set_bits(client, ADP8870_MDCR, NSTBY);
972
973 return 0;
974}
975#else
976#define adp8870_i2c_suspend NULL
977#define adp8870_i2c_resume NULL
978#endif
979
980static const struct i2c_device_id adp8870_id[] = {
981 { "adp8870", 0 },
982 { }
983};
984MODULE_DEVICE_TABLE(i2c, adp8870_id);
985
986static struct i2c_driver adp8870_driver = {
987 .driver = {
988 .name = KBUILD_MODNAME,
989 },
990 .probe = adp8870_probe,
991 .remove = __devexit_p(adp8870_remove),
992 .suspend = adp8870_i2c_suspend,
993 .resume = adp8870_i2c_resume,
994 .id_table = adp8870_id,
995};
996
997static int __init adp8870_init(void)
998{
999 return i2c_add_driver(&adp8870_driver);
1000}
1001module_init(adp8870_init);
1002
1003static void __exit adp8870_exit(void)
1004{
1005 i2c_del_driver(&adp8870_driver);
1006}
1007module_exit(adp8870_exit);
1008
1009MODULE_LICENSE("GPL v2");
1010MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
1011MODULE_DESCRIPTION("ADP8870 Backlight driver");
1012MODULE_ALIAS("platform:adp8870-backlight");
diff --git a/drivers/video/backlight/adx_bl.c b/drivers/video/backlight/adx_bl.c
index fe9af129c5dd..c861c41af442 100644
--- a/drivers/video/backlight/adx_bl.c
+++ b/drivers/video/backlight/adx_bl.c
@@ -104,6 +104,7 @@ static int __devinit adx_backlight_probe(struct platform_device *pdev)
104 } 104 }
105 105
106 memset(&props, 0, sizeof(struct backlight_properties)); 106 memset(&props, 0, sizeof(struct backlight_properties));
107 props.type = BACKLIGHT_RAW;
107 props.max_brightness = 0xff; 108 props.max_brightness = 0xff;
108 bldev = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, 109 bldev = backlight_device_register(dev_name(&pdev->dev), &pdev->dev,
109 bl, &adx_backlight_ops, &props); 110 bl, &adx_backlight_ops, &props);
diff --git a/drivers/video/backlight/apple_bl.c b/drivers/video/backlight/apple_bl.c
new file mode 100644
index 000000000000..be98d152b7fd
--- /dev/null
+++ b/drivers/video/backlight/apple_bl.c
@@ -0,0 +1,241 @@
1/*
2 * Backlight Driver for Intel-based Apples
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/backlight.h>
23#include <linux/err.h>
24#include <linux/io.h>
25#include <linux/pci.h>
26#include <linux/acpi.h>
27
28static struct backlight_device *apple_backlight_device;
29
30struct hw_data {
31 /* I/O resource to allocate. */
32 unsigned long iostart;
33 unsigned long iolen;
34 /* Backlight operations structure. */
35 const struct backlight_ops backlight_ops;
36 void (*set_brightness)(int);
37};
38
39static const struct hw_data *hw_data;
40
41#define DRIVER "apple_backlight: "
42
43/* Module parameters. */
44static int debug;
45module_param_named(debug, debug, int, 0644);
46MODULE_PARM_DESC(debug, "Set to one to enable debugging messages.");
47
48/*
49 * Implementation for machines with Intel chipset.
50 */
51static void intel_chipset_set_brightness(int intensity)
52{
53 outb(0x04 | (intensity << 4), 0xb3);
54 outb(0xbf, 0xb2);
55}
56
57static int intel_chipset_send_intensity(struct backlight_device *bd)
58{
59 int intensity = bd->props.brightness;
60
61 if (debug)
62 printk(KERN_DEBUG DRIVER "setting brightness to %d\n",
63 intensity);
64
65 intel_chipset_set_brightness(intensity);
66 return 0;
67}
68
69static int intel_chipset_get_intensity(struct backlight_device *bd)
70{
71 int intensity;
72
73 outb(0x03, 0xb3);
74 outb(0xbf, 0xb2);
75 intensity = inb(0xb3) >> 4;
76
77 if (debug)
78 printk(KERN_DEBUG DRIVER "read brightness of %d\n",
79 intensity);
80
81 return intensity;
82}
83
84static const struct hw_data intel_chipset_data = {
85 .iostart = 0xb2,
86 .iolen = 2,
87 .backlight_ops = {
88 .options = BL_CORE_SUSPENDRESUME,
89 .get_brightness = intel_chipset_get_intensity,
90 .update_status = intel_chipset_send_intensity,
91 },
92 .set_brightness = intel_chipset_set_brightness,
93};
94
95/*
96 * Implementation for machines with Nvidia chipset.
97 */
98static void nvidia_chipset_set_brightness(int intensity)
99{
100 outb(0x04 | (intensity << 4), 0x52f);
101 outb(0xbf, 0x52e);
102}
103
104static int nvidia_chipset_send_intensity(struct backlight_device *bd)
105{
106 int intensity = bd->props.brightness;
107
108 if (debug)
109 printk(KERN_DEBUG DRIVER "setting brightness to %d\n",
110 intensity);
111
112 nvidia_chipset_set_brightness(intensity);
113 return 0;
114}
115
116static int nvidia_chipset_get_intensity(struct backlight_device *bd)
117{
118 int intensity;
119
120 outb(0x03, 0x52f);
121 outb(0xbf, 0x52e);
122 intensity = inb(0x52f) >> 4;
123
124 if (debug)
125 printk(KERN_DEBUG DRIVER "read brightness of %d\n",
126 intensity);
127
128 return intensity;
129}
130
131static const struct hw_data nvidia_chipset_data = {
132 .iostart = 0x52e,
133 .iolen = 2,
134 .backlight_ops = {
135 .options = BL_CORE_SUSPENDRESUME,
136 .get_brightness = nvidia_chipset_get_intensity,
137 .update_status = nvidia_chipset_send_intensity
138 },
139 .set_brightness = nvidia_chipset_set_brightness,
140};
141
142static int __devinit apple_bl_add(struct acpi_device *dev)
143{
144 struct backlight_properties props;
145 struct pci_dev *host;
146 int intensity;
147
148 host = pci_get_bus_and_slot(0, 0);
149
150 if (!host) {
151 printk(KERN_ERR DRIVER "unable to find PCI host\n");
152 return -ENODEV;
153 }
154
155 if (host->vendor == PCI_VENDOR_ID_INTEL)
156 hw_data = &intel_chipset_data;
157 else if (host->vendor == PCI_VENDOR_ID_NVIDIA)
158 hw_data = &nvidia_chipset_data;
159
160 pci_dev_put(host);
161
162 if (!hw_data) {
163 printk(KERN_ERR DRIVER "unknown hardware\n");
164 return -ENODEV;
165 }
166
167 /* Check that the hardware responds - this may not work under EFI */
168
169 intensity = hw_data->backlight_ops.get_brightness(NULL);
170
171 if (!intensity) {
172 hw_data->set_brightness(1);
173 if (!hw_data->backlight_ops.get_brightness(NULL))
174 return -ENODEV;
175
176 hw_data->set_brightness(0);
177 }
178
179 if (!request_region(hw_data->iostart, hw_data->iolen,
180 "Apple backlight"))
181 return -ENXIO;
182
183 memset(&props, 0, sizeof(struct backlight_properties));
184 props.type = BACKLIGHT_PLATFORM;
185 props.max_brightness = 15;
186 apple_backlight_device = backlight_device_register("apple_backlight",
187 NULL, NULL, &hw_data->backlight_ops, &props);
188
189 if (IS_ERR(apple_backlight_device)) {
190 release_region(hw_data->iostart, hw_data->iolen);
191 return PTR_ERR(apple_backlight_device);
192 }
193
194 apple_backlight_device->props.brightness =
195 hw_data->backlight_ops.get_brightness(apple_backlight_device);
196 backlight_update_status(apple_backlight_device);
197
198 return 0;
199}
200
201static int __devexit apple_bl_remove(struct acpi_device *dev, int type)
202{
203 backlight_device_unregister(apple_backlight_device);
204
205 release_region(hw_data->iostart, hw_data->iolen);
206 hw_data = NULL;
207 return 0;
208}
209
210static const struct acpi_device_id apple_bl_ids[] = {
211 {"APP0002", 0},
212 {"", 0},
213};
214
215static struct acpi_driver apple_bl_driver = {
216 .name = "Apple backlight",
217 .ids = apple_bl_ids,
218 .ops = {
219 .add = apple_bl_add,
220 .remove = apple_bl_remove,
221 },
222};
223
224static int __init apple_bl_init(void)
225{
226 return acpi_bus_register_driver(&apple_bl_driver);
227}
228
229static void __exit apple_bl_exit(void)
230{
231 acpi_bus_unregister_driver(&apple_bl_driver);
232}
233
234module_init(apple_bl_init);
235module_exit(apple_bl_exit);
236
237MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
238MODULE_DESCRIPTION("Apple Backlight Driver");
239MODULE_LICENSE("GPL");
240MODULE_DEVICE_TABLE(acpi, apple_bl_ids);
241MODULE_ALIAS("mbp_nvidia_bl");
diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c
index e6a66dab088c..0443a4f71858 100644
--- a/drivers/video/backlight/atmel-pwm-bl.c
+++ b/drivers/video/backlight/atmel-pwm-bl.c
@@ -168,6 +168,7 @@ static int atmel_pwm_bl_probe(struct platform_device *pdev)
168 } 168 }
169 169
170 memset(&props, 0, sizeof(struct backlight_properties)); 170 memset(&props, 0, sizeof(struct backlight_properties));
171 props.type = BACKLIGHT_RAW;
171 props.max_brightness = pdata->pwm_duty_max - pdata->pwm_duty_min; 172 props.max_brightness = pdata->pwm_duty_max - pdata->pwm_duty_min;
172 bldev = backlight_device_register("atmel-pwm-bl", &pdev->dev, pwmbl, 173 bldev = backlight_device_register("atmel-pwm-bl", &pdev->dev, pwmbl,
173 &atmel_pwm_bl_ops, &props); 174 &atmel_pwm_bl_ops, &props);
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index e207810bba3c..80d292fb92d8 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -19,6 +19,12 @@
19#include <asm/backlight.h> 19#include <asm/backlight.h>
20#endif 20#endif
21 21
22static const char const *backlight_types[] = {
23 [BACKLIGHT_RAW] = "raw",
24 [BACKLIGHT_PLATFORM] = "platform",
25 [BACKLIGHT_FIRMWARE] = "firmware",
26};
27
22#if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \ 28#if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \
23 defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)) 29 defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE))
24/* This callback gets called when something important happens inside a 30/* This callback gets called when something important happens inside a
@@ -169,6 +175,14 @@ static ssize_t backlight_store_brightness(struct device *dev,
169 return rc; 175 return rc;
170} 176}
171 177
178static ssize_t backlight_show_type(struct device *dev,
179 struct device_attribute *attr, char *buf)
180{
181 struct backlight_device *bd = to_backlight_device(dev);
182
183 return sprintf(buf, "%s\n", backlight_types[bd->props.type]);
184}
185
172static ssize_t backlight_show_max_brightness(struct device *dev, 186static ssize_t backlight_show_max_brightness(struct device *dev,
173 struct device_attribute *attr, char *buf) 187 struct device_attribute *attr, char *buf)
174{ 188{
@@ -197,12 +211,12 @@ static int backlight_suspend(struct device *dev, pm_message_t state)
197{ 211{
198 struct backlight_device *bd = to_backlight_device(dev); 212 struct backlight_device *bd = to_backlight_device(dev);
199 213
200 if (bd->ops->options & BL_CORE_SUSPENDRESUME) { 214 mutex_lock(&bd->ops_lock);
201 mutex_lock(&bd->ops_lock); 215 if (bd->ops && bd->ops->options & BL_CORE_SUSPENDRESUME) {
202 bd->props.state |= BL_CORE_SUSPENDED; 216 bd->props.state |= BL_CORE_SUSPENDED;
203 backlight_update_status(bd); 217 backlight_update_status(bd);
204 mutex_unlock(&bd->ops_lock);
205 } 218 }
219 mutex_unlock(&bd->ops_lock);
206 220
207 return 0; 221 return 0;
208} 222}
@@ -211,12 +225,12 @@ static int backlight_resume(struct device *dev)
211{ 225{
212 struct backlight_device *bd = to_backlight_device(dev); 226 struct backlight_device *bd = to_backlight_device(dev);
213 227
214 if (bd->ops->options & BL_CORE_SUSPENDRESUME) { 228 mutex_lock(&bd->ops_lock);
215 mutex_lock(&bd->ops_lock); 229 if (bd->ops && bd->ops->options & BL_CORE_SUSPENDRESUME) {
216 bd->props.state &= ~BL_CORE_SUSPENDED; 230 bd->props.state &= ~BL_CORE_SUSPENDED;
217 backlight_update_status(bd); 231 backlight_update_status(bd);
218 mutex_unlock(&bd->ops_lock);
219 } 232 }
233 mutex_unlock(&bd->ops_lock);
220 234
221 return 0; 235 return 0;
222} 236}
@@ -234,6 +248,7 @@ static struct device_attribute bl_device_attributes[] = {
234 __ATTR(actual_brightness, 0444, backlight_show_actual_brightness, 248 __ATTR(actual_brightness, 0444, backlight_show_actual_brightness,
235 NULL), 249 NULL),
236 __ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL), 250 __ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL),
251 __ATTR(type, 0444, backlight_show_type, NULL),
237 __ATTR_NULL, 252 __ATTR_NULL,
238}; 253};
239 254
@@ -292,9 +307,16 @@ struct backlight_device *backlight_device_register(const char *name,
292 dev_set_drvdata(&new_bd->dev, devdata); 307 dev_set_drvdata(&new_bd->dev, devdata);
293 308
294 /* Set default properties */ 309 /* Set default properties */
295 if (props) 310 if (props) {
296 memcpy(&new_bd->props, props, 311 memcpy(&new_bd->props, props,
297 sizeof(struct backlight_properties)); 312 sizeof(struct backlight_properties));
313 if (props->type <= 0 || props->type >= BACKLIGHT_TYPE_MAX) {
314 WARN(1, "%s: invalid backlight type", name);
315 new_bd->props.type = BACKLIGHT_RAW;
316 }
317 } else {
318 new_bd->props.type = BACKLIGHT_RAW;
319 }
298 320
299 rc = device_register(&new_bd->dev); 321 rc = device_register(&new_bd->dev);
300 if (rc) { 322 if (rc) {
diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c
index 1e71c35083bb..c6533bad26f8 100644
--- a/drivers/video/backlight/corgi_lcd.c
+++ b/drivers/video/backlight/corgi_lcd.c
@@ -109,7 +109,7 @@ static unsigned long corgibl_flags;
109#define CORGIBL_BATTLOW 0x02 109#define CORGIBL_BATTLOW 0x02
110 110
111/* 111/*
112 * This is only a psuedo I2C interface. We can't use the standard kernel 112 * This is only a pseudo I2C interface. We can't use the standard kernel
113 * routines as the interface is write only. We just assume the data is acked... 113 * routines as the interface is write only. We just assume the data is acked...
114 */ 114 */
115static void lcdtg_ssp_i2c_send(struct corgi_lcd *lcd, uint8_t data) 115static void lcdtg_ssp_i2c_send(struct corgi_lcd *lcd, uint8_t data)
@@ -562,6 +562,7 @@ static int __devinit corgi_lcd_probe(struct spi_device *spi)
562 lcd->mode = (pdata) ? pdata->init_mode : CORGI_LCD_MODE_VGA; 562 lcd->mode = (pdata) ? pdata->init_mode : CORGI_LCD_MODE_VGA;
563 563
564 memset(&props, 0, sizeof(struct backlight_properties)); 564 memset(&props, 0, sizeof(struct backlight_properties));
565 props.type = BACKLIGHT_RAW;
565 props.max_brightness = pdata->max_intensity; 566 props.max_brightness = pdata->max_intensity;
566 lcd->bl_dev = backlight_device_register("corgi_bl", &spi->dev, lcd, 567 lcd->bl_dev = backlight_device_register("corgi_bl", &spi->dev, lcd,
567 &corgi_bl_ops, &props); 568 &corgi_bl_ops, &props);
diff --git a/drivers/video/backlight/cr_bllcd.c b/drivers/video/backlight/cr_bllcd.c
index a4f4546f0be0..6c8c54041fae 100644
--- a/drivers/video/backlight/cr_bllcd.c
+++ b/drivers/video/backlight/cr_bllcd.c
@@ -193,6 +193,7 @@ static int cr_backlight_probe(struct platform_device *pdev)
193 } 193 }
194 194
195 memset(&props, 0, sizeof(struct backlight_properties)); 195 memset(&props, 0, sizeof(struct backlight_properties));
196 props.type = BACKLIGHT_RAW;
196 bdp = backlight_device_register("cr-backlight", &pdev->dev, NULL, 197 bdp = backlight_device_register("cr-backlight", &pdev->dev, NULL,
197 &cr_backlight_ops, &props); 198 &cr_backlight_ops, &props);
198 if (IS_ERR(bdp)) { 199 if (IS_ERR(bdp)) {
@@ -242,6 +243,7 @@ static int cr_backlight_remove(struct platform_device *pdev)
242 backlight_device_unregister(crp->cr_backlight_device); 243 backlight_device_unregister(crp->cr_backlight_device);
243 lcd_device_unregister(crp->cr_lcd_device); 244 lcd_device_unregister(crp->cr_lcd_device);
244 pci_dev_put(lpc_dev); 245 pci_dev_put(lpc_dev);
246 kfree(crp);
245 247
246 return 0; 248 return 0;
247} 249}
diff --git a/drivers/video/backlight/da903x_bl.c b/drivers/video/backlight/da903x_bl.c
index 87659ed79bd7..62043f12a5a4 100644
--- a/drivers/video/backlight/da903x_bl.c
+++ b/drivers/video/backlight/da903x_bl.c
@@ -136,6 +136,7 @@ static int da903x_backlight_probe(struct platform_device *pdev)
136 da903x_write(data->da903x_dev, DA9034_WLED_CONTROL2, 136 da903x_write(data->da903x_dev, DA9034_WLED_CONTROL2,
137 DA9034_WLED_ISET(pdata->output_current)); 137 DA9034_WLED_ISET(pdata->output_current));
138 138
139 props.type = BACKLIGHT_RAW;
139 props.max_brightness = max_brightness; 140 props.max_brightness = max_brightness;
140 bl = backlight_device_register(pdev->name, data->da903x_dev, data, 141 bl = backlight_device_register(pdev->name, data->da903x_dev, data,
141 &da903x_backlight_ops, &props); 142 &da903x_backlight_ops, &props);
diff --git a/drivers/video/backlight/ep93xx_bl.c b/drivers/video/backlight/ep93xx_bl.c
index b0cc49184803..9f1e389d51d2 100644
--- a/drivers/video/backlight/ep93xx_bl.c
+++ b/drivers/video/backlight/ep93xx_bl.c
@@ -87,6 +87,7 @@ static int __init ep93xxbl_probe(struct platform_device *dev)
87 ep93xxbl->mmio = EP93XX_RASTER_BRIGHTNESS; 87 ep93xxbl->mmio = EP93XX_RASTER_BRIGHTNESS;
88 88
89 memset(&props, 0, sizeof(struct backlight_properties)); 89 memset(&props, 0, sizeof(struct backlight_properties));
90 props.type = BACKLIGHT_RAW;
90 props.max_brightness = EP93XX_MAX_BRIGHT; 91 props.max_brightness = EP93XX_MAX_BRIGHT;
91 bl = backlight_device_register(dev->name, &dev->dev, ep93xxbl, 92 bl = backlight_device_register(dev->name, &dev->dev, ep93xxbl,
92 &ep93xxbl_ops, &props); 93 &ep93xxbl_ops, &props);
diff --git a/drivers/video/backlight/generic_bl.c b/drivers/video/backlight/generic_bl.c
index 312ca619735d..8c6befd65a33 100644
--- a/drivers/video/backlight/generic_bl.c
+++ b/drivers/video/backlight/generic_bl.c
@@ -91,6 +91,7 @@ static int genericbl_probe(struct platform_device *pdev)
91 name = machinfo->name; 91 name = machinfo->name;
92 92
93 memset(&props, 0, sizeof(struct backlight_properties)); 93 memset(&props, 0, sizeof(struct backlight_properties));
94 props.type = BACKLIGHT_RAW;
94 props.max_brightness = machinfo->max_intensity; 95 props.max_brightness = machinfo->max_intensity;
95 bd = backlight_device_register(name, &pdev->dev, NULL, &genericbl_ops, 96 bd = backlight_device_register(name, &pdev->dev, NULL, &genericbl_ops,
96 &props); 97 &props);
diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c
index 267d23f8d645..38aa00272141 100644
--- a/drivers/video/backlight/hp680_bl.c
+++ b/drivers/video/backlight/hp680_bl.c
@@ -109,6 +109,7 @@ static int __devinit hp680bl_probe(struct platform_device *pdev)
109 struct backlight_device *bd; 109 struct backlight_device *bd;
110 110
111 memset(&props, 0, sizeof(struct backlight_properties)); 111 memset(&props, 0, sizeof(struct backlight_properties));
112 props.type = BACKLIGHT_RAW;
112 props.max_brightness = HP680_MAX_INTENSITY; 113 props.max_brightness = HP680_MAX_INTENSITY;
113 bd = backlight_device_register("hp680-bl", &pdev->dev, NULL, 114 bd = backlight_device_register("hp680-bl", &pdev->dev, NULL,
114 &hp680bl_ops, &props); 115 &hp680bl_ops, &props);
diff --git a/drivers/video/backlight/jornada720_bl.c b/drivers/video/backlight/jornada720_bl.c
index 2f177b3a4885..de65d80159be 100644
--- a/drivers/video/backlight/jornada720_bl.c
+++ b/drivers/video/backlight/jornada720_bl.c
@@ -106,6 +106,7 @@ static int jornada_bl_probe(struct platform_device *pdev)
106 struct backlight_device *bd; 106 struct backlight_device *bd;
107 107
108 memset(&props, 0, sizeof(struct backlight_properties)); 108 memset(&props, 0, sizeof(struct backlight_properties));
109 props.type = BACKLIGHT_RAW;
109 props.max_brightness = BL_MAX_BRIGHT; 110 props.max_brightness = BL_MAX_BRIGHT;
110 bd = backlight_device_register(S1D_DEVICENAME, &pdev->dev, NULL, 111 bd = backlight_device_register(S1D_DEVICENAME, &pdev->dev, NULL,
111 &jornada_bl_ops, &props); 112 &jornada_bl_ops, &props);
@@ -146,12 +147,12 @@ static struct platform_driver jornada_bl_driver = {
146 }, 147 },
147}; 148};
148 149
149int __init jornada_bl_init(void) 150static int __init jornada_bl_init(void)
150{ 151{
151 return platform_driver_register(&jornada_bl_driver); 152 return platform_driver_register(&jornada_bl_driver);
152} 153}
153 154
154void __exit jornada_bl_exit(void) 155static void __exit jornada_bl_exit(void)
155{ 156{
156 platform_driver_unregister(&jornada_bl_driver); 157 platform_driver_unregister(&jornada_bl_driver);
157} 158}
diff --git a/drivers/video/backlight/jornada720_lcd.c b/drivers/video/backlight/jornada720_lcd.c
index cbbb167fd268..d2ff658b4144 100644
--- a/drivers/video/backlight/jornada720_lcd.c
+++ b/drivers/video/backlight/jornada720_lcd.c
@@ -135,12 +135,12 @@ static struct platform_driver jornada_lcd_driver = {
135 }, 135 },
136}; 136};
137 137
138int __init jornada_lcd_init(void) 138static int __init jornada_lcd_init(void)
139{ 139{
140 return platform_driver_register(&jornada_lcd_driver); 140 return platform_driver_register(&jornada_lcd_driver);
141} 141}
142 142
143void __exit jornada_lcd_exit(void) 143static void __exit jornada_lcd_exit(void)
144{ 144{
145 platform_driver_unregister(&jornada_lcd_driver); 145 platform_driver_unregister(&jornada_lcd_driver);
146} 146}
diff --git a/drivers/video/backlight/kb3886_bl.c b/drivers/video/backlight/kb3886_bl.c
index f439a8632287..72dd5556a35b 100644
--- a/drivers/video/backlight/kb3886_bl.c
+++ b/drivers/video/backlight/kb3886_bl.c
@@ -149,6 +149,7 @@ static int kb3886bl_probe(struct platform_device *pdev)
149 machinfo->limit_mask = -1; 149 machinfo->limit_mask = -1;
150 150
151 memset(&props, 0, sizeof(struct backlight_properties)); 151 memset(&props, 0, sizeof(struct backlight_properties));
152 props.type = BACKLIGHT_RAW;
152 props.max_brightness = machinfo->max_intensity; 153 props.max_brightness = machinfo->max_intensity;
153 kb3886_backlight_device = backlight_device_register("kb3886-bl", 154 kb3886_backlight_device = backlight_device_register("kb3886-bl",
154 &pdev->dev, NULL, 155 &pdev->dev, NULL,
diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c
index 9093ef0fa869..98ad3e5f7c85 100644
--- a/drivers/video/backlight/l4f00242t03.c
+++ b/drivers/video/backlight/l4f00242t03.c
@@ -25,7 +25,7 @@
25struct l4f00242t03_priv { 25struct l4f00242t03_priv {
26 struct spi_device *spi; 26 struct spi_device *spi;
27 struct lcd_device *ld; 27 struct lcd_device *ld;
28 int lcd_on:1; 28 int lcd_state;
29 struct regulator *io_reg; 29 struct regulator *io_reg;
30 struct regulator *core_reg; 30 struct regulator *core_reg;
31}; 31};
@@ -62,11 +62,36 @@ static void l4f00242t03_lcd_init(struct spi_device *spi)
62 regulator_enable(priv->core_reg); 62 regulator_enable(priv->core_reg);
63 } 63 }
64 64
65 l4f00242t03_reset(pdata->reset_gpio);
66
65 gpio_set_value(pdata->data_enable_gpio, 1); 67 gpio_set_value(pdata->data_enable_gpio, 1);
66 msleep(60); 68 msleep(60);
67 spi_write(spi, (const u8 *)cmd, ARRAY_SIZE(cmd) * sizeof(u16)); 69 spi_write(spi, (const u8 *)cmd, ARRAY_SIZE(cmd) * sizeof(u16));
68} 70}
69 71
72static void l4f00242t03_lcd_powerdown(struct spi_device *spi)
73{
74 struct l4f00242t03_pdata *pdata = spi->dev.platform_data;
75 struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev);
76
77 dev_dbg(&spi->dev, "Powering down LCD\n");
78
79 gpio_set_value(pdata->data_enable_gpio, 0);
80
81 if (priv->io_reg)
82 regulator_disable(priv->io_reg);
83
84 if (priv->core_reg)
85 regulator_disable(priv->core_reg);
86}
87
88static int l4f00242t03_lcd_power_get(struct lcd_device *ld)
89{
90 struct l4f00242t03_priv *priv = lcd_get_data(ld);
91
92 return priv->lcd_state;
93}
94
70static int l4f00242t03_lcd_power_set(struct lcd_device *ld, int power) 95static int l4f00242t03_lcd_power_set(struct lcd_device *ld, int power)
71{ 96{
72 struct l4f00242t03_priv *priv = lcd_get_data(ld); 97 struct l4f00242t03_priv *priv = lcd_get_data(ld);
@@ -78,36 +103,55 @@ static int l4f00242t03_lcd_power_set(struct lcd_device *ld, int power)
78 const u16 slpin = 0x10; 103 const u16 slpin = 0x10;
79 const u16 disoff = 0x28; 104 const u16 disoff = 0x28;
80 105
81 if (power) { 106 if (power <= FB_BLANK_NORMAL) {
82 if (priv->lcd_on) 107 if (priv->lcd_state <= FB_BLANK_NORMAL) {
83 return 0; 108 /* Do nothing, the LCD is running */
84 109 } else if (priv->lcd_state < FB_BLANK_POWERDOWN) {
85 dev_dbg(&spi->dev, "turning on LCD\n"); 110 dev_dbg(&spi->dev, "Resuming LCD\n");
86 111
87 spi_write(spi, (const u8 *)&slpout, sizeof(u16)); 112 spi_write(spi, (const u8 *)&slpout, sizeof(u16));
88 msleep(60); 113 msleep(60);
89 spi_write(spi, (const u8 *)&dison, sizeof(u16)); 114 spi_write(spi, (const u8 *)&dison, sizeof(u16));
90 115 } else {
91 priv->lcd_on = 1; 116 /* priv->lcd_state == FB_BLANK_POWERDOWN */
117 l4f00242t03_lcd_init(spi);
118 priv->lcd_state = FB_BLANK_VSYNC_SUSPEND;
119 l4f00242t03_lcd_power_set(priv->ld, power);
120 }
121 } else if (power < FB_BLANK_POWERDOWN) {
122 if (priv->lcd_state <= FB_BLANK_NORMAL) {
123 /* Send the display in standby */
124 dev_dbg(&spi->dev, "Standby the LCD\n");
125
126 spi_write(spi, (const u8 *)&disoff, sizeof(u16));
127 msleep(60);
128 spi_write(spi, (const u8 *)&slpin, sizeof(u16));
129 } else if (priv->lcd_state < FB_BLANK_POWERDOWN) {
130 /* Do nothing, the LCD is already in standby */
131 } else {
132 /* priv->lcd_state == FB_BLANK_POWERDOWN */
133 l4f00242t03_lcd_init(spi);
134 priv->lcd_state = FB_BLANK_UNBLANK;
135 l4f00242t03_lcd_power_set(ld, power);
136 }
92 } else { 137 } else {
93 if (!priv->lcd_on) 138 /* power == FB_BLANK_POWERDOWN */
94 return 0; 139 if (priv->lcd_state != FB_BLANK_POWERDOWN) {
95 140 /* Clear the screen before shutting down */
96 dev_dbg(&spi->dev, "turning off LCD\n"); 141 spi_write(spi, (const u8 *)&disoff, sizeof(u16));
97 142 msleep(60);
98 spi_write(spi, (const u8 *)&disoff, sizeof(u16)); 143 l4f00242t03_lcd_powerdown(spi);
99 msleep(60); 144 }
100 spi_write(spi, (const u8 *)&slpin, sizeof(u16));
101
102 priv->lcd_on = 0;
103 } 145 }
104 146
147 priv->lcd_state = power;
148
105 return 0; 149 return 0;
106} 150}
107 151
108static struct lcd_ops l4f_ops = { 152static struct lcd_ops l4f_ops = {
109 .set_power = l4f00242t03_lcd_power_set, 153 .set_power = l4f00242t03_lcd_power_set,
110 .get_power = NULL, 154 .get_power = l4f00242t03_lcd_power_get,
111}; 155};
112 156
113static int __devinit l4f00242t03_probe(struct spi_device *spi) 157static int __devinit l4f00242t03_probe(struct spi_device *spi)
@@ -185,9 +229,9 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
185 } 229 }
186 230
187 /* Init the LCD */ 231 /* Init the LCD */
188 l4f00242t03_reset(pdata->reset_gpio);
189 l4f00242t03_lcd_init(spi); 232 l4f00242t03_lcd_init(spi);
190 l4f00242t03_lcd_power_set(priv->ld, 1); 233 priv->lcd_state = FB_BLANK_VSYNC_SUSPEND;
234 l4f00242t03_lcd_power_set(priv->ld, FB_BLANK_UNBLANK);
191 235
192 dev_info(&spi->dev, "Epson l4f00242t03 lcd probed.\n"); 236 dev_info(&spi->dev, "Epson l4f00242t03 lcd probed.\n");
193 237
@@ -214,9 +258,11 @@ static int __devexit l4f00242t03_remove(struct spi_device *spi)
214 struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev); 258 struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev);
215 struct l4f00242t03_pdata *pdata = priv->spi->dev.platform_data; 259 struct l4f00242t03_pdata *pdata = priv->spi->dev.platform_data;
216 260
217 l4f00242t03_lcd_power_set(priv->ld, 0); 261 l4f00242t03_lcd_power_set(priv->ld, FB_BLANK_POWERDOWN);
218 lcd_device_unregister(priv->ld); 262 lcd_device_unregister(priv->ld);
219 263
264 dev_set_drvdata(&spi->dev, NULL);
265
220 gpio_free(pdata->data_enable_gpio); 266 gpio_free(pdata->data_enable_gpio);
221 gpio_free(pdata->reset_gpio); 267 gpio_free(pdata->reset_gpio);
222 268
@@ -230,6 +276,15 @@ static int __devexit l4f00242t03_remove(struct spi_device *spi)
230 return 0; 276 return 0;
231} 277}
232 278
279static void l4f00242t03_shutdown(struct spi_device *spi)
280{
281 struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev);
282
283 if (priv)
284 l4f00242t03_lcd_power_set(priv->ld, FB_BLANK_POWERDOWN);
285
286}
287
233static struct spi_driver l4f00242t03_driver = { 288static struct spi_driver l4f00242t03_driver = {
234 .driver = { 289 .driver = {
235 .name = "l4f00242t03", 290 .name = "l4f00242t03",
@@ -237,6 +292,7 @@ static struct spi_driver l4f00242t03_driver = {
237 }, 292 },
238 .probe = l4f00242t03_probe, 293 .probe = l4f00242t03_probe,
239 .remove = __devexit_p(l4f00242t03_remove), 294 .remove = __devexit_p(l4f00242t03_remove),
295 .shutdown = l4f00242t03_shutdown,
240}; 296};
241 297
242static __init int l4f00242t03_init(void) 298static __init int l4f00242t03_init(void)
diff --git a/drivers/video/backlight/ld9040.c b/drivers/video/backlight/ld9040.c
new file mode 100644
index 000000000000..7281b2506a67
--- /dev/null
+++ b/drivers/video/backlight/ld9040.c
@@ -0,0 +1,819 @@
1/*
2 * ld9040 AMOLED LCD panel driver.
3 *
4 * Copyright (c) 2011 Samsung Electronics
5 * Author: Donghwa Lee <dh09.lee@samsung.com>
6 * Derived from drivers/video/backlight/s6e63m0.c
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22
23#include <linux/wait.h>
24#include <linux/fb.h>
25#include <linux/delay.h>
26#include <linux/gpio.h>
27#include <linux/spi/spi.h>
28#include <linux/irq.h>
29#include <linux/interrupt.h>
30#include <linux/kernel.h>
31#include <linux/lcd.h>
32#include <linux/backlight.h>
33
34#include "ld9040_gamma.h"
35
36#define SLEEPMSEC 0x1000
37#define ENDDEF 0x2000
38#define DEFMASK 0xFF00
39#define COMMAND_ONLY 0xFE
40#define DATA_ONLY 0xFF
41
42#define MIN_BRIGHTNESS 0
43#define MAX_BRIGHTNESS 24
44#define power_is_on(pwr) ((pwr) <= FB_BLANK_NORMAL)
45
46struct ld9040 {
47 struct device *dev;
48 struct spi_device *spi;
49 unsigned int power;
50 unsigned int current_brightness;
51
52 struct lcd_device *ld;
53 struct backlight_device *bd;
54 struct lcd_platform_data *lcd_pd;
55};
56
57static const unsigned short seq_swreset[] = {
58 0x01, COMMAND_ONLY,
59 ENDDEF, 0x00
60};
61
62static const unsigned short seq_user_setting[] = {
63 0xF0, 0x5A,
64
65 DATA_ONLY, 0x5A,
66 ENDDEF, 0x00
67};
68
69static const unsigned short seq_elvss_on[] = {
70 0xB1, 0x0D,
71
72 DATA_ONLY, 0x00,
73 DATA_ONLY, 0x16,
74 ENDDEF, 0x00
75};
76
77static const unsigned short seq_gtcon[] = {
78 0xF7, 0x09,
79
80 DATA_ONLY, 0x00,
81 DATA_ONLY, 0x00,
82 ENDDEF, 0x00
83};
84
85static const unsigned short seq_panel_condition[] = {
86 0xF8, 0x05,
87
88 DATA_ONLY, 0x65,
89 DATA_ONLY, 0x96,
90 DATA_ONLY, 0x71,
91 DATA_ONLY, 0x7D,
92 DATA_ONLY, 0x19,
93 DATA_ONLY, 0x3B,
94 DATA_ONLY, 0x0D,
95 DATA_ONLY, 0x19,
96 DATA_ONLY, 0x7E,
97 DATA_ONLY, 0x0D,
98 DATA_ONLY, 0xE2,
99 DATA_ONLY, 0x00,
100 DATA_ONLY, 0x00,
101 DATA_ONLY, 0x7E,
102 DATA_ONLY, 0x7D,
103 DATA_ONLY, 0x07,
104 DATA_ONLY, 0x07,
105 DATA_ONLY, 0x20,
106 DATA_ONLY, 0x20,
107 DATA_ONLY, 0x20,
108 DATA_ONLY, 0x02,
109 DATA_ONLY, 0x02,
110 ENDDEF, 0x00
111};
112
113static const unsigned short seq_gamma_set1[] = {
114 0xF9, 0x00,
115
116 DATA_ONLY, 0xA7,
117 DATA_ONLY, 0xB4,
118 DATA_ONLY, 0xAE,
119 DATA_ONLY, 0xBF,
120 DATA_ONLY, 0x00,
121 DATA_ONLY, 0x91,
122 DATA_ONLY, 0x00,
123 DATA_ONLY, 0xB2,
124 DATA_ONLY, 0xB4,
125 DATA_ONLY, 0xAA,
126 DATA_ONLY, 0xBB,
127 DATA_ONLY, 0x00,
128 DATA_ONLY, 0xAC,
129 DATA_ONLY, 0x00,
130 DATA_ONLY, 0xB3,
131 DATA_ONLY, 0xB1,
132 DATA_ONLY, 0xAA,
133 DATA_ONLY, 0xBC,
134 DATA_ONLY, 0x00,
135 DATA_ONLY, 0xB3,
136 ENDDEF, 0x00
137};
138
139static const unsigned short seq_gamma_ctrl[] = {
140 0xFB, 0x02,
141
142 DATA_ONLY, 0x5A,
143 ENDDEF, 0x00
144};
145
146static const unsigned short seq_gamma_start[] = {
147 0xF9, COMMAND_ONLY,
148
149 ENDDEF, 0x00
150};
151
152static const unsigned short seq_apon[] = {
153 0xF3, 0x00,
154
155 DATA_ONLY, 0x00,
156 DATA_ONLY, 0x00,
157 DATA_ONLY, 0x0A,
158 DATA_ONLY, 0x02,
159 ENDDEF, 0x00
160};
161
162static const unsigned short seq_display_ctrl[] = {
163 0xF2, 0x02,
164
165 DATA_ONLY, 0x08,
166 DATA_ONLY, 0x08,
167 DATA_ONLY, 0x10,
168 DATA_ONLY, 0x10,
169 ENDDEF, 0x00
170};
171
172static const unsigned short seq_manual_pwr[] = {
173 0xB0, 0x04,
174 ENDDEF, 0x00
175};
176
177static const unsigned short seq_pwr_ctrl[] = {
178 0xF4, 0x0A,
179
180 DATA_ONLY, 0x87,
181 DATA_ONLY, 0x25,
182 DATA_ONLY, 0x6A,
183 DATA_ONLY, 0x44,
184 DATA_ONLY, 0x02,
185 DATA_ONLY, 0x88,
186 ENDDEF, 0x00
187};
188
189static const unsigned short seq_sleep_out[] = {
190 0x11, COMMAND_ONLY,
191 ENDDEF, 0x00
192};
193
194static const unsigned short seq_sleep_in[] = {
195 0x10, COMMAND_ONLY,
196 ENDDEF, 0x00
197};
198
199static const unsigned short seq_display_on[] = {
200 0x29, COMMAND_ONLY,
201 ENDDEF, 0x00
202};
203
204static const unsigned short seq_display_off[] = {
205 0x28, COMMAND_ONLY,
206 ENDDEF, 0x00
207};
208
209static const unsigned short seq_vci1_1st_en[] = {
210 0xF3, 0x10,
211
212 DATA_ONLY, 0x00,
213 DATA_ONLY, 0x00,
214 DATA_ONLY, 0x00,
215 DATA_ONLY, 0x02,
216 ENDDEF, 0x00
217};
218
219static const unsigned short seq_vl1_en[] = {
220 0xF3, 0x11,
221
222 DATA_ONLY, 0x00,
223 DATA_ONLY, 0x00,
224 DATA_ONLY, 0x00,
225 DATA_ONLY, 0x02,
226 ENDDEF, 0x00
227};
228
229static const unsigned short seq_vl2_en[] = {
230 0xF3, 0x13,
231
232 DATA_ONLY, 0x00,
233 DATA_ONLY, 0x00,
234 DATA_ONLY, 0x00,
235 DATA_ONLY, 0x02,
236 ENDDEF, 0x00
237};
238
239static const unsigned short seq_vci1_2nd_en[] = {
240 0xF3, 0x33,
241
242 DATA_ONLY, 0x00,
243 DATA_ONLY, 0x00,
244 DATA_ONLY, 0x00,
245 DATA_ONLY, 0x02,
246 ENDDEF, 0x00
247};
248
249static const unsigned short seq_vl3_en[] = {
250 0xF3, 0x37,
251
252 DATA_ONLY, 0x00,
253 DATA_ONLY, 0x00,
254 DATA_ONLY, 0x00,
255 DATA_ONLY, 0x02,
256 ENDDEF, 0x00
257};
258
259static const unsigned short seq_vreg1_amp_en[] = {
260 0xF3, 0x37,
261
262 DATA_ONLY, 0x01,
263 DATA_ONLY, 0x00,
264 DATA_ONLY, 0x00,
265 DATA_ONLY, 0x02,
266 ENDDEF, 0x00
267};
268
269static const unsigned short seq_vgh_amp_en[] = {
270 0xF3, 0x37,
271
272 DATA_ONLY, 0x11,
273 DATA_ONLY, 0x00,
274 DATA_ONLY, 0x00,
275 DATA_ONLY, 0x02,
276 ENDDEF, 0x00
277};
278
279static const unsigned short seq_vgl_amp_en[] = {
280 0xF3, 0x37,
281
282 DATA_ONLY, 0x31,
283 DATA_ONLY, 0x00,
284 DATA_ONLY, 0x00,
285 DATA_ONLY, 0x02,
286 ENDDEF, 0x00
287};
288
289static const unsigned short seq_vmos_amp_en[] = {
290 0xF3, 0x37,
291
292 DATA_ONLY, 0xB1,
293 DATA_ONLY, 0x00,
294 DATA_ONLY, 0x00,
295 DATA_ONLY, 0x03,
296 ENDDEF, 0x00
297};
298
299static const unsigned short seq_vint_amp_en[] = {
300 0xF3, 0x37,
301
302 DATA_ONLY, 0xF1,
303 /* DATA_ONLY, 0x71, VMOS/VBL/VBH not used */
304 DATA_ONLY, 0x00,
305 DATA_ONLY, 0x00,
306 DATA_ONLY, 0x03,
307 /* DATA_ONLY, 0x02, VMOS/VBL/VBH not used */
308 ENDDEF, 0x00
309};
310
311static const unsigned short seq_vbh_amp_en[] = {
312 0xF3, 0x37,
313
314 DATA_ONLY, 0xF9,
315 DATA_ONLY, 0x00,
316 DATA_ONLY, 0x00,
317 DATA_ONLY, 0x03,
318 ENDDEF, 0x00
319};
320
321static const unsigned short seq_vbl_amp_en[] = {
322 0xF3, 0x37,
323
324 DATA_ONLY, 0xFD,
325 DATA_ONLY, 0x00,
326 DATA_ONLY, 0x00,
327 DATA_ONLY, 0x03,
328 ENDDEF, 0x00
329};
330
331static const unsigned short seq_gam_amp_en[] = {
332 0xF3, 0x37,
333
334 DATA_ONLY, 0xFF,
335 /* DATA_ONLY, 0x73, VMOS/VBL/VBH not used */
336 DATA_ONLY, 0x00,
337 DATA_ONLY, 0x00,
338 DATA_ONLY, 0x03,
339 /* DATA_ONLY, 0x02, VMOS/VBL/VBH not used */
340 ENDDEF, 0x00
341};
342
343static const unsigned short seq_sd_amp_en[] = {
344 0xF3, 0x37,
345
346 DATA_ONLY, 0xFF,
347 /* DATA_ONLY, 0x73, VMOS/VBL/VBH not used */
348 DATA_ONLY, 0x80,
349 DATA_ONLY, 0x00,
350 DATA_ONLY, 0x03,
351 /* DATA_ONLY, 0x02, VMOS/VBL/VBH not used */
352 ENDDEF, 0x00
353};
354
355static const unsigned short seq_gls_en[] = {
356 0xF3, 0x37,
357
358 DATA_ONLY, 0xFF,
359 /* DATA_ONLY, 0x73, VMOS/VBL/VBH not used */
360 DATA_ONLY, 0x81,
361 DATA_ONLY, 0x00,
362 DATA_ONLY, 0x03,
363 /* DATA_ONLY, 0x02, VMOS/VBL/VBH not used */
364 ENDDEF, 0x00
365};
366
367static const unsigned short seq_els_en[] = {
368 0xF3, 0x37,
369
370 DATA_ONLY, 0xFF,
371 /* DATA_ONLY, 0x73, VMOS/VBL/VBH not used */
372 DATA_ONLY, 0x83,
373 DATA_ONLY, 0x00,
374 DATA_ONLY, 0x03,
375 /* DATA_ONLY, 0x02, VMOS/VBL/VBH not used */
376 ENDDEF, 0x00
377};
378
379static const unsigned short seq_el_on[] = {
380 0xF3, 0x37,
381
382 DATA_ONLY, 0xFF,
383 /* DATA_ONLY, 0x73, VMOS/VBL/VBH not used */
384 DATA_ONLY, 0x87,
385 DATA_ONLY, 0x00,
386 DATA_ONLY, 0x03,
387 /* DATA_ONLY, 0x02, VMOS/VBL/VBH not used */
388 ENDDEF, 0x00
389};
390
391static int ld9040_spi_write_byte(struct ld9040 *lcd, int addr, int data)
392{
393 u16 buf[1];
394 struct spi_message msg;
395
396 struct spi_transfer xfer = {
397 .len = 2,
398 .tx_buf = buf,
399 };
400
401 buf[0] = (addr << 8) | data;
402
403 spi_message_init(&msg);
404 spi_message_add_tail(&xfer, &msg);
405
406 return spi_sync(lcd->spi, &msg);
407}
408
409static int ld9040_spi_write(struct ld9040 *lcd, unsigned char address,
410 unsigned char command)
411{
412 int ret = 0;
413
414 if (address != DATA_ONLY)
415 ret = ld9040_spi_write_byte(lcd, 0x0, address);
416 if (command != COMMAND_ONLY)
417 ret = ld9040_spi_write_byte(lcd, 0x1, command);
418
419 return ret;
420}
421
422static int ld9040_panel_send_sequence(struct ld9040 *lcd,
423 const unsigned short *wbuf)
424{
425 int ret = 0, i = 0;
426
427 while ((wbuf[i] & DEFMASK) != ENDDEF) {
428 if ((wbuf[i] & DEFMASK) != SLEEPMSEC) {
429 ret = ld9040_spi_write(lcd, wbuf[i], wbuf[i+1]);
430 if (ret)
431 break;
432 } else
433 udelay(wbuf[i+1]*1000);
434 i += 2;
435 }
436
437 return ret;
438}
439
440static int _ld9040_gamma_ctl(struct ld9040 *lcd, const unsigned int *gamma)
441{
442 unsigned int i = 0;
443 int ret = 0;
444
445 /* start gamma table updating. */
446 ret = ld9040_panel_send_sequence(lcd, seq_gamma_start);
447 if (ret) {
448 dev_err(lcd->dev, "failed to disable gamma table updating.\n");
449 goto gamma_err;
450 }
451
452 for (i = 0 ; i < GAMMA_TABLE_COUNT; i++) {
453 ret = ld9040_spi_write(lcd, DATA_ONLY, gamma[i]);
454 if (ret) {
455 dev_err(lcd->dev, "failed to set gamma table.\n");
456 goto gamma_err;
457 }
458 }
459
460 /* update gamma table. */
461 ret = ld9040_panel_send_sequence(lcd, seq_gamma_ctrl);
462 if (ret)
463 dev_err(lcd->dev, "failed to update gamma table.\n");
464
465gamma_err:
466 return ret;
467}
468
469static int ld9040_gamma_ctl(struct ld9040 *lcd, int gamma)
470{
471 int ret = 0;
472
473 ret = _ld9040_gamma_ctl(lcd, gamma_table.gamma_22_table[gamma]);
474
475 return ret;
476}
477
478
479static int ld9040_ldi_init(struct ld9040 *lcd)
480{
481 int ret, i;
482 static const unsigned short *init_seq[] = {
483 seq_user_setting,
484 seq_panel_condition,
485 seq_display_ctrl,
486 seq_manual_pwr,
487 seq_elvss_on,
488 seq_gtcon,
489 seq_gamma_set1,
490 seq_gamma_ctrl,
491 seq_sleep_out,
492 };
493
494 for (i = 0; i < ARRAY_SIZE(init_seq); i++) {
495 ret = ld9040_panel_send_sequence(lcd, init_seq[i]);
496 /* workaround: minimum delay time for transferring CMD */
497 udelay(300);
498 if (ret)
499 break;
500 }
501
502 return ret;
503}
504
505static int ld9040_ldi_enable(struct ld9040 *lcd)
506{
507 int ret = 0;
508
509 ret = ld9040_panel_send_sequence(lcd, seq_display_on);
510
511 return ret;
512}
513
514static int ld9040_ldi_disable(struct ld9040 *lcd)
515{
516 int ret;
517
518 ret = ld9040_panel_send_sequence(lcd, seq_display_off);
519 ret = ld9040_panel_send_sequence(lcd, seq_sleep_in);
520
521 return ret;
522}
523
524static int ld9040_power_on(struct ld9040 *lcd)
525{
526 int ret = 0;
527 struct lcd_platform_data *pd = NULL;
528 pd = lcd->lcd_pd;
529 if (!pd) {
530 dev_err(lcd->dev, "platform data is NULL.\n");
531 return -EFAULT;
532 }
533
534 if (!pd->power_on) {
535 dev_err(lcd->dev, "power_on is NULL.\n");
536 return -EFAULT;
537 } else {
538 pd->power_on(lcd->ld, 1);
539 mdelay(pd->power_on_delay);
540 }
541
542 if (!pd->reset) {
543 dev_err(lcd->dev, "reset is NULL.\n");
544 return -EFAULT;
545 } else {
546 pd->reset(lcd->ld);
547 mdelay(pd->reset_delay);
548 }
549
550 ret = ld9040_ldi_init(lcd);
551 if (ret) {
552 dev_err(lcd->dev, "failed to initialize ldi.\n");
553 return ret;
554 }
555
556 ret = ld9040_ldi_enable(lcd);
557 if (ret) {
558 dev_err(lcd->dev, "failed to enable ldi.\n");
559 return ret;
560 }
561
562 return 0;
563}
564
565static int ld9040_power_off(struct ld9040 *lcd)
566{
567 int ret = 0;
568 struct lcd_platform_data *pd = NULL;
569
570 pd = lcd->lcd_pd;
571 if (!pd) {
572 dev_err(lcd->dev, "platform data is NULL.\n");
573 return -EFAULT;
574 }
575
576 ret = ld9040_ldi_disable(lcd);
577 if (ret) {
578 dev_err(lcd->dev, "lcd setting failed.\n");
579 return -EIO;
580 }
581
582 mdelay(pd->power_off_delay);
583
584 if (!pd->power_on) {
585 dev_err(lcd->dev, "power_on is NULL.\n");
586 return -EFAULT;
587 } else
588 pd->power_on(lcd->ld, 0);
589
590 return 0;
591}
592
593static int ld9040_power(struct ld9040 *lcd, int power)
594{
595 int ret = 0;
596
597 if (power_is_on(power) && !power_is_on(lcd->power))
598 ret = ld9040_power_on(lcd);
599 else if (!power_is_on(power) && power_is_on(lcd->power))
600 ret = ld9040_power_off(lcd);
601
602 if (!ret)
603 lcd->power = power;
604
605 return ret;
606}
607
608static int ld9040_set_power(struct lcd_device *ld, int power)
609{
610 struct ld9040 *lcd = lcd_get_data(ld);
611
612 if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN &&
613 power != FB_BLANK_NORMAL) {
614 dev_err(lcd->dev, "power value should be 0, 1 or 4.\n");
615 return -EINVAL;
616 }
617
618 return ld9040_power(lcd, power);
619}
620
621static int ld9040_get_power(struct lcd_device *ld)
622{
623 struct ld9040 *lcd = lcd_get_data(ld);
624
625 return lcd->power;
626}
627
628static int ld9040_get_brightness(struct backlight_device *bd)
629{
630 return bd->props.brightness;
631}
632
633static int ld9040_set_brightness(struct backlight_device *bd)
634{
635 int ret = 0, brightness = bd->props.brightness;
636 struct ld9040 *lcd = bl_get_data(bd);
637
638 if (brightness < MIN_BRIGHTNESS ||
639 brightness > bd->props.max_brightness) {
640 dev_err(&bd->dev, "lcd brightness should be %d to %d.\n",
641 MIN_BRIGHTNESS, MAX_BRIGHTNESS);
642 return -EINVAL;
643 }
644
645 ret = ld9040_gamma_ctl(lcd, bd->props.brightness);
646 if (ret) {
647 dev_err(&bd->dev, "lcd brightness setting failed.\n");
648 return -EIO;
649 }
650
651 return ret;
652}
653
654static struct lcd_ops ld9040_lcd_ops = {
655 .set_power = ld9040_set_power,
656 .get_power = ld9040_get_power,
657};
658
659static const struct backlight_ops ld9040_backlight_ops = {
660 .get_brightness = ld9040_get_brightness,
661 .update_status = ld9040_set_brightness,
662};
663
664
665static int ld9040_probe(struct spi_device *spi)
666{
667 int ret = 0;
668 struct ld9040 *lcd = NULL;
669 struct lcd_device *ld = NULL;
670 struct backlight_device *bd = NULL;
671
672 lcd = kzalloc(sizeof(struct ld9040), GFP_KERNEL);
673 if (!lcd)
674 return -ENOMEM;
675
676 /* ld9040 lcd panel uses 3-wire 9bits SPI Mode. */
677 spi->bits_per_word = 9;
678
679 ret = spi_setup(spi);
680 if (ret < 0) {
681 dev_err(&spi->dev, "spi setup failed.\n");
682 goto out_free_lcd;
683 }
684
685 lcd->spi = spi;
686 lcd->dev = &spi->dev;
687
688 lcd->lcd_pd = spi->dev.platform_data;
689 if (!lcd->lcd_pd) {
690 dev_err(&spi->dev, "platform data is NULL.\n");
691 goto out_free_lcd;
692 }
693
694 ld = lcd_device_register("ld9040", &spi->dev, lcd, &ld9040_lcd_ops);
695 if (IS_ERR(ld)) {
696 ret = PTR_ERR(ld);
697 goto out_free_lcd;
698 }
699
700 lcd->ld = ld;
701
702 bd = backlight_device_register("ld9040-bl", &spi->dev,
703 lcd, &ld9040_backlight_ops, NULL);
704 if (IS_ERR(ld)) {
705 ret = PTR_ERR(ld);
706 goto out_free_lcd;
707 }
708
709 bd->props.max_brightness = MAX_BRIGHTNESS;
710 bd->props.brightness = MAX_BRIGHTNESS;
711 lcd->bd = bd;
712
713 /*
714 * if lcd panel was on from bootloader like u-boot then
715 * do not lcd on.
716 */
717 if (!lcd->lcd_pd->lcd_enabled) {
718 /*
719 * if lcd panel was off from bootloader then
720 * current lcd status is powerdown and then
721 * it enables lcd panel.
722 */
723 lcd->power = FB_BLANK_POWERDOWN;
724
725 ld9040_power(lcd, FB_BLANK_UNBLANK);
726 } else
727 lcd->power = FB_BLANK_UNBLANK;
728
729 dev_set_drvdata(&spi->dev, lcd);
730
731 dev_info(&spi->dev, "ld9040 panel driver has been probed.\n");
732 return 0;
733
734out_free_lcd:
735 kfree(lcd);
736 return ret;
737}
738
739static int __devexit ld9040_remove(struct spi_device *spi)
740{
741 struct ld9040 *lcd = dev_get_drvdata(&spi->dev);
742
743 ld9040_power(lcd, FB_BLANK_POWERDOWN);
744 lcd_device_unregister(lcd->ld);
745 kfree(lcd);
746
747 return 0;
748}
749
750#if defined(CONFIG_PM)
751static int ld9040_suspend(struct spi_device *spi, pm_message_t mesg)
752{
753 int ret = 0;
754 struct ld9040 *lcd = dev_get_drvdata(&spi->dev);
755
756 dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power);
757
758 /*
759 * when lcd panel is suspend, lcd panel becomes off
760 * regardless of status.
761 */
762 ret = ld9040_power(lcd, FB_BLANK_POWERDOWN);
763
764 return ret;
765}
766
767static int ld9040_resume(struct spi_device *spi)
768{
769 int ret = 0;
770 struct ld9040 *lcd = dev_get_drvdata(&spi->dev);
771
772 lcd->power = FB_BLANK_POWERDOWN;
773
774 ret = ld9040_power(lcd, FB_BLANK_UNBLANK);
775
776 return ret;
777}
778#else
779#define ld9040_suspend NULL
780#define ld9040_resume NULL
781#endif
782
783/* Power down all displays on reboot, poweroff or halt. */
784static void ld9040_shutdown(struct spi_device *spi)
785{
786 struct ld9040 *lcd = dev_get_drvdata(&spi->dev);
787
788 ld9040_power(lcd, FB_BLANK_POWERDOWN);
789}
790
791static struct spi_driver ld9040_driver = {
792 .driver = {
793 .name = "ld9040",
794 .bus = &spi_bus_type,
795 .owner = THIS_MODULE,
796 },
797 .probe = ld9040_probe,
798 .remove = __devexit_p(ld9040_remove),
799 .shutdown = ld9040_shutdown,
800 .suspend = ld9040_suspend,
801 .resume = ld9040_resume,
802};
803
804static int __init ld9040_init(void)
805{
806 return spi_register_driver(&ld9040_driver);
807}
808
809static void __exit ld9040_exit(void)
810{
811 spi_unregister_driver(&ld9040_driver);
812}
813
814module_init(ld9040_init);
815module_exit(ld9040_exit);
816
817MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
818MODULE_DESCRIPTION("ld9040 LCD Driver");
819MODULE_LICENSE("GPL");
diff --git a/drivers/video/backlight/ld9040_gamma.h b/drivers/video/backlight/ld9040_gamma.h
new file mode 100644
index 000000000000..038d9c86ec03
--- /dev/null
+++ b/drivers/video/backlight/ld9040_gamma.h
@@ -0,0 +1,200 @@
1/*
2 * Gamma level definitions.
3 *
4 * Copyright (c) 2011 Samsung Electronics
5 * InKi Dae <inki.dae@samsung.com>
6 * Donghwa Lee <dh09.lee@samsung.com>
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#ifndef _LD9040_BRIGHTNESS_H
14#define _LD9040_BRIGHTNESS_H
15
16#define MAX_GAMMA_LEVEL 25
17#define GAMMA_TABLE_COUNT 21
18
19/* gamma value: 2.2 */
20static const unsigned int ld9040_22_300[] = {
21 0x00, 0xa7, 0xb4, 0xae, 0xbf, 0x00, 0x91,
22 0x00, 0xb2, 0xb4, 0xaa, 0xbb, 0x00, 0xac,
23 0x00, 0xb3, 0xb1, 0xaa, 0xbc, 0x00, 0xb3
24};
25
26static const unsigned int ld9040_22_290[] = {
27 0x00, 0xa9, 0xb7, 0xae, 0xbd, 0x00, 0x89,
28 0x00, 0xb7, 0xb6, 0xa8, 0xba, 0x00, 0xa4,
29 0x00, 0xb1, 0xb4, 0xaa, 0xbb, 0x00, 0xaa
30};
31
32static const unsigned int ld9040_22_280[] = {
33 0x00, 0xa9, 0xb6, 0xad, 0xbf, 0x00, 0x86,
34 0x00, 0xb8, 0xb5, 0xa8, 0xbc, 0x00, 0xa0,
35 0x00, 0xb3, 0xb3, 0xa9, 0xbc, 0x00, 0xa7
36};
37
38static const unsigned int ld9040_22_270[] = {
39 0x00, 0xa8, 0xb8, 0xae, 0xbe, 0x00, 0x84,
40 0x00, 0xb9, 0xb7, 0xa8, 0xbc, 0x00, 0x9d,
41 0x00, 0xb2, 0xb5, 0xaa, 0xbc, 0x00, 0xa4
42
43};
44static const unsigned int ld9040_22_260[] = {
45 0x00, 0xa4, 0xb8, 0xb0, 0xbf, 0x00, 0x80,
46 0x00, 0xb8, 0xb6, 0xaa, 0xbc, 0x00, 0x9a,
47 0x00, 0xb0, 0xb5, 0xab, 0xbd, 0x00, 0xa0
48};
49
50static const unsigned int ld9040_22_250[] = {
51 0x00, 0xa4, 0xb9, 0xaf, 0xc1, 0x00, 0x7d,
52 0x00, 0xb9, 0xb6, 0xaa, 0xbb, 0x00, 0x97,
53 0x00, 0xb1, 0xb5, 0xaa, 0xbf, 0x00, 0x9d
54};
55
56static const unsigned int ld9040_22_240[] = {
57 0x00, 0xa2, 0xb9, 0xaf, 0xc2, 0x00, 0x7a,
58 0x00, 0xb9, 0xb7, 0xaa, 0xbd, 0x00, 0x94,
59 0x00, 0xb0, 0xb5, 0xab, 0xbf, 0x00, 0x9a
60};
61
62static const unsigned int ld9040_22_230[] = {
63 0x00, 0xa0, 0xb9, 0xaf, 0xc3, 0x00, 0x77,
64 0x00, 0xb9, 0xb7, 0xab, 0xbe, 0x00, 0x90,
65 0x00, 0xb0, 0xb6, 0xab, 0xbf, 0x00, 0x97
66};
67
68static const unsigned int ld9040_22_220[] = {
69 0x00, 0x9e, 0xba, 0xb0, 0xc2, 0x00, 0x75,
70 0x00, 0xb9, 0xb8, 0xab, 0xbe, 0x00, 0x8e,
71 0x00, 0xb0, 0xb6, 0xac, 0xbf, 0x00, 0x94
72};
73
74static const unsigned int ld9040_22_210[] = {
75 0x00, 0x9c, 0xb9, 0xb0, 0xc4, 0x00, 0x72,
76 0x00, 0xb8, 0xb8, 0xac, 0xbf, 0x00, 0x8a,
77 0x00, 0xb0, 0xb6, 0xac, 0xc0, 0x00, 0x91
78};
79
80static const unsigned int ld9040_22_200[] = {
81 0x00, 0x9a, 0xba, 0xb1, 0xc4, 0x00, 0x6f,
82 0x00, 0xb8, 0xb8, 0xad, 0xc0, 0x00, 0x86,
83 0x00, 0xb0, 0xb7, 0xad, 0xc0, 0x00, 0x8d
84};
85
86static const unsigned int ld9040_22_190[] = {
87 0x00, 0x97, 0xba, 0xb2, 0xc5, 0x00, 0x6c,
88 0x00, 0xb8, 0xb8, 0xae, 0xc1, 0x00, 0x82,
89 0x00, 0xb0, 0xb6, 0xae, 0xc2, 0x00, 0x89
90};
91
92static const unsigned int ld9040_22_180[] = {
93 0x00, 0x93, 0xba, 0xb3, 0xc5, 0x00, 0x69,
94 0x00, 0xb8, 0xb9, 0xae, 0xc1, 0x00, 0x7f,
95 0x00, 0xb0, 0xb6, 0xae, 0xc3, 0x00, 0x85
96};
97
98static const unsigned int ld9040_22_170[] = {
99 0x00, 0x8b, 0xb9, 0xb3, 0xc7, 0x00, 0x65,
100 0x00, 0xb7, 0xb8, 0xaf, 0xc3, 0x00, 0x7a,
101 0x00, 0x80, 0xb6, 0xae, 0xc4, 0x00, 0x81
102};
103
104static const unsigned int ld9040_22_160[] = {
105 0x00, 0x89, 0xba, 0xb3, 0xc8, 0x00, 0x62,
106 0x00, 0xb6, 0xba, 0xaf, 0xc3, 0x00, 0x76,
107 0x00, 0xaf, 0xb7, 0xae, 0xc4, 0x00, 0x7e
108};
109
110static const unsigned int ld9040_22_150[] = {
111 0x00, 0x82, 0xba, 0xb4, 0xc7, 0x00, 0x5f,
112 0x00, 0xb5, 0xba, 0xb0, 0xc3, 0x00, 0x72,
113 0x00, 0xae, 0xb8, 0xb0, 0xc3, 0x00, 0x7a
114};
115
116static const unsigned int ld9040_22_140[] = {
117 0x00, 0x7b, 0xbb, 0xb4, 0xc8, 0x00, 0x5b,
118 0x00, 0xb5, 0xba, 0xb1, 0xc4, 0x00, 0x6e,
119 0x00, 0xae, 0xb9, 0xb0, 0xc5, 0x00, 0x75
120};
121
122static const unsigned int ld9040_22_130[] = {
123 0x00, 0x71, 0xbb, 0xb5, 0xc8, 0x00, 0x57,
124 0x00, 0xb5, 0xbb, 0xb0, 0xc5, 0x00, 0x6a,
125 0x00, 0xae, 0xb9, 0xb1, 0xc6, 0x00, 0x70
126};
127
128static const unsigned int ld9040_22_120[] = {
129 0x00, 0x47, 0xba, 0xb6, 0xca, 0x00, 0x53,
130 0x00, 0xb5, 0xbb, 0xb3, 0xc6, 0x00, 0x65,
131 0x00, 0xae, 0xb8, 0xb3, 0xc7, 0x00, 0x6c
132};
133
134static const unsigned int ld9040_22_110[] = {
135 0x00, 0x13, 0xbb, 0xb7, 0xca, 0x00, 0x4f,
136 0x00, 0xb4, 0xbb, 0xb3, 0xc7, 0x00, 0x60,
137 0x00, 0xad, 0xb8, 0xb4, 0xc7, 0x00, 0x67
138};
139
140static const unsigned int ld9040_22_100[] = {
141 0x00, 0x13, 0xba, 0xb8, 0xcb, 0x00, 0x4b,
142 0x00, 0xb3, 0xbc, 0xb4, 0xc7, 0x00, 0x5c,
143 0x00, 0xac, 0xb8, 0xb4, 0xc8, 0x00, 0x62
144};
145
146static const unsigned int ld9040_22_90[] = {
147 0x00, 0x13, 0xb9, 0xb8, 0xcd, 0x00, 0x46,
148 0x00, 0xb1, 0xbc, 0xb5, 0xc8, 0x00, 0x56,
149 0x00, 0xaa, 0xb8, 0xb4, 0xc9, 0x00, 0x5d
150};
151
152static const unsigned int ld9040_22_80[] = {
153 0x00, 0x13, 0xba, 0xb9, 0xcd, 0x00, 0x41,
154 0x00, 0xb0, 0xbe, 0xb5, 0xc9, 0x00, 0x51,
155 0x00, 0xa9, 0xb9, 0xb5, 0xca, 0x00, 0x57
156};
157
158static const unsigned int ld9040_22_70[] = {
159 0x00, 0x13, 0xb9, 0xb9, 0xd0, 0x00, 0x3c,
160 0x00, 0xaf, 0xbf, 0xb6, 0xcb, 0x00, 0x4b,
161 0x00, 0xa8, 0xb9, 0xb5, 0xcc, 0x00, 0x52
162};
163
164static const unsigned int ld9040_22_50[] = {
165 0x00, 0x13, 0xb2, 0xba, 0xd2, 0x00, 0x30,
166 0x00, 0xaf, 0xc0, 0xb8, 0xcd, 0x00, 0x3d,
167 0x00, 0xa8, 0xb8, 0xb7, 0xcd, 0x00, 0x44
168};
169
170struct ld9040_gamma {
171 unsigned int *gamma_22_table[MAX_GAMMA_LEVEL];
172} gamma_table = {
173 .gamma_22_table[0] = (unsigned int *)&ld9040_22_50,
174 .gamma_22_table[1] = (unsigned int *)&ld9040_22_70,
175 .gamma_22_table[2] = (unsigned int *)&ld9040_22_80,
176 .gamma_22_table[3] = (unsigned int *)&ld9040_22_90,
177 .gamma_22_table[4] = (unsigned int *)&ld9040_22_100,
178 .gamma_22_table[5] = (unsigned int *)&ld9040_22_110,
179 .gamma_22_table[6] = (unsigned int *)&ld9040_22_120,
180 .gamma_22_table[7] = (unsigned int *)&ld9040_22_130,
181 .gamma_22_table[8] = (unsigned int *)&ld9040_22_140,
182 .gamma_22_table[9] = (unsigned int *)&ld9040_22_150,
183 .gamma_22_table[10] = (unsigned int *)&ld9040_22_160,
184 .gamma_22_table[11] = (unsigned int *)&ld9040_22_170,
185 .gamma_22_table[12] = (unsigned int *)&ld9040_22_180,
186 .gamma_22_table[13] = (unsigned int *)&ld9040_22_190,
187 .gamma_22_table[14] = (unsigned int *)&ld9040_22_200,
188 .gamma_22_table[15] = (unsigned int *)&ld9040_22_210,
189 .gamma_22_table[16] = (unsigned int *)&ld9040_22_220,
190 .gamma_22_table[17] = (unsigned int *)&ld9040_22_230,
191 .gamma_22_table[18] = (unsigned int *)&ld9040_22_240,
192 .gamma_22_table[19] = (unsigned int *)&ld9040_22_250,
193 .gamma_22_table[20] = (unsigned int *)&ld9040_22_260,
194 .gamma_22_table[21] = (unsigned int *)&ld9040_22_270,
195 .gamma_22_table[22] = (unsigned int *)&ld9040_22_280,
196 .gamma_22_table[23] = (unsigned int *)&ld9040_22_290,
197 .gamma_22_table[24] = (unsigned int *)&ld9040_22_300,
198};
199
200#endif
diff --git a/drivers/video/backlight/lms283gf05.c b/drivers/video/backlight/lms283gf05.c
index abc43a0eb97d..5d3cf33953ac 100644
--- a/drivers/video/backlight/lms283gf05.c
+++ b/drivers/video/backlight/lms283gf05.c
@@ -129,7 +129,7 @@ static int lms283gf05_power_set(struct lcd_device *ld, int power)
129 struct spi_device *spi = st->spi; 129 struct spi_device *spi = st->spi;
130 struct lms283gf05_pdata *pdata = spi->dev.platform_data; 130 struct lms283gf05_pdata *pdata = spi->dev.platform_data;
131 131
132 if (power) { 132 if (power <= FB_BLANK_NORMAL) {
133 if (pdata) 133 if (pdata)
134 lms283gf05_reset(pdata->reset_gpio, 134 lms283gf05_reset(pdata->reset_gpio,
135 pdata->reset_inverted); 135 pdata->reset_inverted);
diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c
index d2f59015d517..be20b5cbe26c 100644
--- a/drivers/video/backlight/locomolcd.c
+++ b/drivers/video/backlight/locomolcd.c
@@ -6,7 +6,7 @@
6 * GPL v2 6 * GPL v2
7 * 7 *
8 * This driver assumes single CPU. That's okay, because collie is 8 * This driver assumes single CPU. That's okay, because collie is
9 * slightly old hardware, and noone is going to retrofit second CPU to 9 * slightly old hardware, and no one is going to retrofit second CPU to
10 * old PDA. 10 * old PDA.
11 */ 11 */
12 12
@@ -184,6 +184,7 @@ static int locomolcd_probe(struct locomo_dev *ldev)
184 local_irq_restore(flags); 184 local_irq_restore(flags);
185 185
186 memset(&props, 0, sizeof(struct backlight_properties)); 186 memset(&props, 0, sizeof(struct backlight_properties));
187 props.type = BACKLIGHT_RAW;
187 props.max_brightness = 4; 188 props.max_brightness = 4;
188 locomolcd_bl_device = backlight_device_register("locomo-bl", 189 locomolcd_bl_device = backlight_device_register("locomo-bl",
189 &ldev->dev, NULL, 190 &ldev->dev, NULL,
diff --git a/drivers/video/backlight/ltv350qv.c b/drivers/video/backlight/ltv350qv.c
index 8010aaeb5adb..cca43c06d3c8 100644
--- a/drivers/video/backlight/ltv350qv.c
+++ b/drivers/video/backlight/ltv350qv.c
@@ -239,11 +239,15 @@ static int __devinit ltv350qv_probe(struct spi_device *spi)
239 lcd->spi = spi; 239 lcd->spi = spi;
240 lcd->power = FB_BLANK_POWERDOWN; 240 lcd->power = FB_BLANK_POWERDOWN;
241 lcd->buffer = kzalloc(8, GFP_KERNEL); 241 lcd->buffer = kzalloc(8, GFP_KERNEL);
242 if (!lcd->buffer) {
243 ret = -ENOMEM;
244 goto out_free_lcd;
245 }
242 246
243 ld = lcd_device_register("ltv350qv", &spi->dev, lcd, &ltv_ops); 247 ld = lcd_device_register("ltv350qv", &spi->dev, lcd, &ltv_ops);
244 if (IS_ERR(ld)) { 248 if (IS_ERR(ld)) {
245 ret = PTR_ERR(ld); 249 ret = PTR_ERR(ld);
246 goto out_free_lcd; 250 goto out_free_buffer;
247 } 251 }
248 lcd->ld = ld; 252 lcd->ld = ld;
249 253
@@ -257,6 +261,8 @@ static int __devinit ltv350qv_probe(struct spi_device *spi)
257 261
258out_unregister: 262out_unregister:
259 lcd_device_unregister(ld); 263 lcd_device_unregister(ld);
264out_free_buffer:
265 kfree(lcd->buffer);
260out_free_lcd: 266out_free_lcd:
261 kfree(lcd); 267 kfree(lcd);
262 return ret; 268 return ret;
@@ -268,6 +274,7 @@ static int __devexit ltv350qv_remove(struct spi_device *spi)
268 274
269 ltv350qv_power(lcd, FB_BLANK_POWERDOWN); 275 ltv350qv_power(lcd, FB_BLANK_POWERDOWN);
270 lcd_device_unregister(lcd->ld); 276 lcd_device_unregister(lcd->ld);
277 kfree(lcd->buffer);
271 kfree(lcd); 278 kfree(lcd);
272 279
273 return 0; 280 return 0;
@@ -326,7 +333,7 @@ static void __exit ltv350qv_exit(void)
326module_init(ltv350qv_init); 333module_init(ltv350qv_init);
327module_exit(ltv350qv_exit); 334module_exit(ltv350qv_exit);
328 335
329MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>"); 336MODULE_AUTHOR("Haavard Skinnemoen (Atmel)");
330MODULE_DESCRIPTION("Samsung LTV350QV LCD Driver"); 337MODULE_DESCRIPTION("Samsung LTV350QV LCD Driver");
331MODULE_LICENSE("GPL"); 338MODULE_LICENSE("GPL");
332MODULE_ALIAS("spi:ltv350qv"); 339MODULE_ALIAS("spi:ltv350qv");
diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c
index b2b2c7ba1f63..07e8e273ced0 100644
--- a/drivers/video/backlight/max8925_bl.c
+++ b/drivers/video/backlight/max8925_bl.c
@@ -92,7 +92,7 @@ static int max8925_backlight_get_brightness(struct backlight_device *bl)
92 return ret; 92 return ret;
93} 93}
94 94
95static struct backlight_ops max8925_backlight_ops = { 95static const struct backlight_ops max8925_backlight_ops = {
96 .options = BL_CORE_SUSPENDRESUME, 96 .options = BL_CORE_SUSPENDRESUME,
97 .update_status = max8925_backlight_update_status, 97 .update_status = max8925_backlight_update_status,
98 .get_brightness = max8925_backlight_get_brightness, 98 .get_brightness = max8925_backlight_get_brightness,
@@ -136,6 +136,7 @@ static int __devinit max8925_backlight_probe(struct platform_device *pdev)
136 data->current_brightness = 0; 136 data->current_brightness = 0;
137 137
138 memset(&props, 0, sizeof(struct backlight_properties)); 138 memset(&props, 0, sizeof(struct backlight_properties));
139 props.type = BACKLIGHT_RAW;
139 props.max_brightness = MAX_BRIGHTNESS; 140 props.max_brightness = MAX_BRIGHTNESS;
140 bl = backlight_device_register(name, &pdev->dev, data, 141 bl = backlight_device_register(name, &pdev->dev, data,
141 &max8925_backlight_ops, &props); 142 &max8925_backlight_ops, &props);
diff --git a/drivers/video/backlight/mbp_nvidia_bl.c b/drivers/video/backlight/mbp_nvidia_bl.c
deleted file mode 100644
index 9fb533f6373e..000000000000
--- a/drivers/video/backlight/mbp_nvidia_bl.c
+++ /dev/null
@@ -1,382 +0,0 @@
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
30/* Structure to be passed to the DMI_MATCH function. */
31struct dmi_match_data {
32 /* I/O resource to allocate. */
33 unsigned long iostart;
34 unsigned long iolen;
35 /* Backlight operations structure. */
36 const struct backlight_ops backlight_ops;
37};
38
39/* Module parameters. */
40static int debug;
41module_param_named(debug, debug, int, 0644);
42MODULE_PARM_DESC(debug, "Set to one to enable debugging messages.");
43
44/*
45 * Implementation for MacBooks with Intel chipset.
46 */
47static int intel_chipset_send_intensity(struct backlight_device *bd)
48{
49 int intensity = bd->props.brightness;
50
51 if (debug)
52 printk(KERN_DEBUG "mbp_nvidia_bl: setting brightness to %d\n",
53 intensity);
54
55 outb(0x04 | (intensity << 4), 0xb3);
56 outb(0xbf, 0xb2);
57 return 0;
58}
59
60static int intel_chipset_get_intensity(struct backlight_device *bd)
61{
62 int intensity;
63
64 outb(0x03, 0xb3);
65 outb(0xbf, 0xb2);
66 intensity = inb(0xb3) >> 4;
67
68 if (debug)
69 printk(KERN_DEBUG "mbp_nvidia_bl: read brightness of %d\n",
70 intensity);
71
72 return intensity;
73}
74
75static const struct dmi_match_data intel_chipset_data = {
76 .iostart = 0xb2,
77 .iolen = 2,
78 .backlight_ops = {
79 .options = BL_CORE_SUSPENDRESUME,
80 .get_brightness = intel_chipset_get_intensity,
81 .update_status = intel_chipset_send_intensity,
82 }
83};
84
85/*
86 * Implementation for MacBooks with Nvidia chipset.
87 */
88static int nvidia_chipset_send_intensity(struct backlight_device *bd)
89{
90 int intensity = bd->props.brightness;
91
92 if (debug)
93 printk(KERN_DEBUG "mbp_nvidia_bl: setting brightness to %d\n",
94 intensity);
95
96 outb(0x04 | (intensity << 4), 0x52f);
97 outb(0xbf, 0x52e);
98 return 0;
99}
100
101static int nvidia_chipset_get_intensity(struct backlight_device *bd)
102{
103 int intensity;
104
105 outb(0x03, 0x52f);
106 outb(0xbf, 0x52e);
107 intensity = inb(0x52f) >> 4;
108
109 if (debug)
110 printk(KERN_DEBUG "mbp_nvidia_bl: read brightness of %d\n",
111 intensity);
112
113 return intensity;
114}
115
116static const struct dmi_match_data nvidia_chipset_data = {
117 .iostart = 0x52e,
118 .iolen = 2,
119 .backlight_ops = {
120 .options = BL_CORE_SUSPENDRESUME,
121 .get_brightness = nvidia_chipset_get_intensity,
122 .update_status = nvidia_chipset_send_intensity
123 }
124};
125
126/*
127 * DMI matching.
128 */
129static /* const */ struct dmi_match_data *driver_data;
130
131static int mbp_dmi_match(const struct dmi_system_id *id)
132{
133 driver_data = id->driver_data;
134
135 printk(KERN_INFO "mbp_nvidia_bl: %s detected\n", id->ident);
136 return 1;
137}
138
139static const struct dmi_system_id __initdata mbp_device_table[] = {
140 {
141 .callback = mbp_dmi_match,
142 .ident = "MacBook 1,1",
143 .matches = {
144 DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."),
145 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"),
146 },
147 .driver_data = (void *)&intel_chipset_data,
148 },
149 {
150 .callback = mbp_dmi_match,
151 .ident = "MacBook 2,1",
152 .matches = {
153 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
154 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook2,1"),
155 },
156 .driver_data = (void *)&intel_chipset_data,
157 },
158 {
159 .callback = mbp_dmi_match,
160 .ident = "MacBook 3,1",
161 .matches = {
162 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
163 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook3,1"),
164 },
165 .driver_data = (void *)&intel_chipset_data,
166 },
167 {
168 .callback = mbp_dmi_match,
169 .ident = "MacBook 4,1",
170 .matches = {
171 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
172 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook4,1"),
173 },
174 .driver_data = (void *)&intel_chipset_data,
175 },
176 {
177 .callback = mbp_dmi_match,
178 .ident = "MacBook 4,2",
179 .matches = {
180 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
181 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook4,2"),
182 },
183 .driver_data = (void *)&intel_chipset_data,
184 },
185 {
186 .callback = mbp_dmi_match,
187 .ident = "MacBookPro 1,1",
188 .matches = {
189 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
190 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,1"),
191 },
192 .driver_data = (void *)&intel_chipset_data,
193 },
194 {
195 .callback = mbp_dmi_match,
196 .ident = "MacBookPro 1,2",
197 .matches = {
198 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
199 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,2"),
200 },
201 .driver_data = (void *)&intel_chipset_data,
202 },
203 {
204 .callback = mbp_dmi_match,
205 .ident = "MacBookPro 2,1",
206 .matches = {
207 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
208 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,1"),
209 },
210 .driver_data = (void *)&intel_chipset_data,
211 },
212 {
213 .callback = mbp_dmi_match,
214 .ident = "MacBookPro 2,2",
215 .matches = {
216 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
217 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,2"),
218 },
219 .driver_data = (void *)&intel_chipset_data,
220 },
221 {
222 .callback = mbp_dmi_match,
223 .ident = "MacBookPro 3,1",
224 .matches = {
225 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
226 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"),
227 },
228 .driver_data = (void *)&intel_chipset_data,
229 },
230 {
231 .callback = mbp_dmi_match,
232 .ident = "MacBookPro 3,2",
233 .matches = {
234 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
235 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,2"),
236 },
237 .driver_data = (void *)&intel_chipset_data,
238 },
239 {
240 .callback = mbp_dmi_match,
241 .ident = "MacBookPro 4,1",
242 .matches = {
243 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
244 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro4,1"),
245 },
246 .driver_data = (void *)&intel_chipset_data,
247 },
248 {
249 .callback = mbp_dmi_match,
250 .ident = "MacBookAir 1,1",
251 .matches = {
252 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
253 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir1,1"),
254 },
255 .driver_data = (void *)&intel_chipset_data,
256 },
257 {
258 .callback = mbp_dmi_match,
259 .ident = "MacBook 5,1",
260 .matches = {
261 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
262 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5,1"),
263 },
264 .driver_data = (void *)&nvidia_chipset_data,
265 },
266 {
267 .callback = mbp_dmi_match,
268 .ident = "MacBook 5,2",
269 .matches = {
270 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
271 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5,2"),
272 },
273 .driver_data = (void *)&nvidia_chipset_data,
274 },
275 {
276 .callback = mbp_dmi_match,
277 .ident = "MacBook 6,1",
278 .matches = {
279 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
280 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook6,1"),
281 },
282 .driver_data = (void *)&nvidia_chipset_data,
283 },
284 {
285 .callback = mbp_dmi_match,
286 .ident = "MacBookAir 2,1",
287 .matches = {
288 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
289 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir2,1"),
290 },
291 .driver_data = (void *)&nvidia_chipset_data,
292 },
293 {
294 .callback = mbp_dmi_match,
295 .ident = "MacBookPro 5,1",
296 .matches = {
297 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
298 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,1"),
299 },
300 .driver_data = (void *)&nvidia_chipset_data,
301 },
302 {
303 .callback = mbp_dmi_match,
304 .ident = "MacBookPro 5,2",
305 .matches = {
306 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
307 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,2"),
308 },
309 .driver_data = (void *)&nvidia_chipset_data,
310 },
311 {
312 .callback = mbp_dmi_match,
313 .ident = "MacBookPro 5,3",
314 .matches = {
315 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
316 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,3"),
317 },
318 .driver_data = (void *)&nvidia_chipset_data,
319 },
320 {
321 .callback = mbp_dmi_match,
322 .ident = "MacBookPro 5,4",
323 .matches = {
324 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
325 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,4"),
326 },
327 .driver_data = (void *)&nvidia_chipset_data,
328 },
329 {
330 .callback = mbp_dmi_match,
331 .ident = "MacBookPro 5,5",
332 .matches = {
333 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
334 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,5"),
335 },
336 .driver_data = (void *)&nvidia_chipset_data,
337 },
338 { }
339};
340
341static int __init mbp_init(void)
342{
343 struct backlight_properties props;
344 if (!dmi_check_system(mbp_device_table))
345 return -ENODEV;
346
347 if (!request_region(driver_data->iostart, driver_data->iolen,
348 "Macbook Pro backlight"))
349 return -ENXIO;
350
351 memset(&props, 0, sizeof(struct backlight_properties));
352 props.max_brightness = 15;
353 mbp_backlight_device = backlight_device_register("mbp_backlight", NULL,
354 NULL,
355 &driver_data->backlight_ops,
356 &props);
357 if (IS_ERR(mbp_backlight_device)) {
358 release_region(driver_data->iostart, driver_data->iolen);
359 return PTR_ERR(mbp_backlight_device);
360 }
361
362 mbp_backlight_device->props.brightness =
363 driver_data->backlight_ops.get_brightness(mbp_backlight_device);
364 backlight_update_status(mbp_backlight_device);
365
366 return 0;
367}
368
369static void __exit mbp_exit(void)
370{
371 backlight_device_unregister(mbp_backlight_device);
372
373 release_region(driver_data->iostart, driver_data->iolen);
374}
375
376module_init(mbp_init);
377module_exit(mbp_exit);
378
379MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
380MODULE_DESCRIPTION("Nvidia-based Macbook Pro Backlight Driver");
381MODULE_LICENSE("GPL");
382MODULE_DEVICE_TABLE(dmi, mbp_device_table);
diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c
index d3bc56296c8d..08d26a72394c 100644
--- a/drivers/video/backlight/omap1_bl.c
+++ b/drivers/video/backlight/omap1_bl.c
@@ -146,6 +146,7 @@ static int omapbl_probe(struct platform_device *pdev)
146 return -ENOMEM; 146 return -ENOMEM;
147 147
148 memset(&props, 0, sizeof(struct backlight_properties)); 148 memset(&props, 0, sizeof(struct backlight_properties));
149 props.type = BACKLIGHT_RAW;
149 props.max_brightness = OMAPBL_MAX_INTENSITY; 150 props.max_brightness = OMAPBL_MAX_INTENSITY;
150 dev = backlight_device_register("omap-bl", &pdev->dev, bl, &omapbl_ops, 151 dev = backlight_device_register("omap-bl", &pdev->dev, bl, &omapbl_ops,
151 &props); 152 &props);
diff --git a/drivers/video/backlight/pcf50633-backlight.c b/drivers/video/backlight/pcf50633-backlight.c
index 3c424f7efdcc..ef5628d60563 100644
--- a/drivers/video/backlight/pcf50633-backlight.c
+++ b/drivers/video/backlight/pcf50633-backlight.c
@@ -112,6 +112,7 @@ static int __devinit pcf50633_bl_probe(struct platform_device *pdev)
112 if (!pcf_bl) 112 if (!pcf_bl)
113 return -ENOMEM; 113 return -ENOMEM;
114 114
115 bl_props.type = BACKLIGHT_RAW;
115 bl_props.max_brightness = 0x3f; 116 bl_props.max_brightness = 0x3f;
116 bl_props.power = FB_BLANK_UNBLANK; 117 bl_props.power = FB_BLANK_UNBLANK;
117 118
diff --git a/drivers/video/backlight/progear_bl.c b/drivers/video/backlight/progear_bl.c
index 809278c90738..6af183d6465e 100644
--- a/drivers/video/backlight/progear_bl.c
+++ b/drivers/video/backlight/progear_bl.c
@@ -84,6 +84,7 @@ static int progearbl_probe(struct platform_device *pdev)
84 pci_write_config_byte(sb_dev, SB_MPS1, temp | 0x20); 84 pci_write_config_byte(sb_dev, SB_MPS1, temp | 0x20);
85 85
86 memset(&props, 0, sizeof(struct backlight_properties)); 86 memset(&props, 0, sizeof(struct backlight_properties));
87 props.type = BACKLIGHT_RAW;
87 props.max_brightness = HW_LEVEL_MAX - HW_LEVEL_MIN; 88 props.max_brightness = HW_LEVEL_MAX - HW_LEVEL_MIN;
88 progear_backlight_device = backlight_device_register("progear-bl", 89 progear_backlight_device = backlight_device_register("progear-bl",
89 &pdev->dev, NULL, 90 &pdev->dev, NULL,
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index 550443518891..b8f38ec6eb18 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -25,8 +25,10 @@ struct pwm_bl_data {
25 struct pwm_device *pwm; 25 struct pwm_device *pwm;
26 struct device *dev; 26 struct device *dev;
27 unsigned int period; 27 unsigned int period;
28 unsigned int lth_brightness;
28 int (*notify)(struct device *, 29 int (*notify)(struct device *,
29 int brightness); 30 int brightness);
31 int (*check_fb)(struct device *, struct fb_info *);
30}; 32};
31 33
32static int pwm_backlight_update_status(struct backlight_device *bl) 34static int pwm_backlight_update_status(struct backlight_device *bl)
@@ -48,7 +50,9 @@ static int pwm_backlight_update_status(struct backlight_device *bl)
48 pwm_config(pb->pwm, 0, pb->period); 50 pwm_config(pb->pwm, 0, pb->period);
49 pwm_disable(pb->pwm); 51 pwm_disable(pb->pwm);
50 } else { 52 } else {
51 pwm_config(pb->pwm, brightness * pb->period / max, pb->period); 53 brightness = pb->lth_brightness +
54 (brightness * (pb->period - pb->lth_brightness) / max);
55 pwm_config(pb->pwm, brightness, pb->period);
52 pwm_enable(pb->pwm); 56 pwm_enable(pb->pwm);
53 } 57 }
54 return 0; 58 return 0;
@@ -59,9 +63,18 @@ static int pwm_backlight_get_brightness(struct backlight_device *bl)
59 return bl->props.brightness; 63 return bl->props.brightness;
60} 64}
61 65
66static int pwm_backlight_check_fb(struct backlight_device *bl,
67 struct fb_info *info)
68{
69 struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev);
70
71 return !pb->check_fb || pb->check_fb(pb->dev, info);
72}
73
62static const struct backlight_ops pwm_backlight_ops = { 74static const struct backlight_ops pwm_backlight_ops = {
63 .update_status = pwm_backlight_update_status, 75 .update_status = pwm_backlight_update_status,
64 .get_brightness = pwm_backlight_get_brightness, 76 .get_brightness = pwm_backlight_get_brightness,
77 .check_fb = pwm_backlight_check_fb,
65}; 78};
66 79
67static int pwm_backlight_probe(struct platform_device *pdev) 80static int pwm_backlight_probe(struct platform_device *pdev)
@@ -92,6 +105,9 @@ static int pwm_backlight_probe(struct platform_device *pdev)
92 105
93 pb->period = data->pwm_period_ns; 106 pb->period = data->pwm_period_ns;
94 pb->notify = data->notify; 107 pb->notify = data->notify;
108 pb->check_fb = data->check_fb;
109 pb->lth_brightness = data->lth_brightness *
110 (data->pwm_period_ns / data->max_brightness);
95 pb->dev = &pdev->dev; 111 pb->dev = &pdev->dev;
96 112
97 pb->pwm = pwm_request(data->pwm_id, "backlight"); 113 pb->pwm = pwm_request(data->pwm_id, "backlight");
@@ -103,6 +119,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
103 dev_dbg(&pdev->dev, "got pwm for backlight\n"); 119 dev_dbg(&pdev->dev, "got pwm for backlight\n");
104 120
105 memset(&props, 0, sizeof(struct backlight_properties)); 121 memset(&props, 0, sizeof(struct backlight_properties));
122 props.type = BACKLIGHT_RAW;
106 props.max_brightness = data->max_brightness; 123 props.max_brightness = data->max_brightness;
107 bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, pb, 124 bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, pb,
108 &pwm_backlight_ops, &props); 125 &pwm_backlight_ops, &props);
diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c
index a3128c9cb7ad..322040f686c2 100644
--- a/drivers/video/backlight/s6e63m0.c
+++ b/drivers/video/backlight/s6e63m0.c
@@ -729,10 +729,10 @@ static ssize_t s6e63m0_sysfs_show_gamma_table(struct device *dev,
729 729
730 return strlen(buf); 730 return strlen(buf);
731} 731}
732static DEVICE_ATTR(gamma_table, 0644, 732static DEVICE_ATTR(gamma_table, 0444,
733 s6e63m0_sysfs_show_gamma_table, NULL); 733 s6e63m0_sysfs_show_gamma_table, NULL);
734 734
735static int __init s6e63m0_probe(struct spi_device *spi) 735static int __devinit s6e63m0_probe(struct spi_device *spi)
736{ 736{
737 int ret = 0; 737 int ret = 0;
738 struct s6e63m0 *lcd = NULL; 738 struct s6e63m0 *lcd = NULL;
@@ -778,6 +778,7 @@ static int __init s6e63m0_probe(struct spi_device *spi)
778 778
779 bd->props.max_brightness = MAX_BRIGHTNESS; 779 bd->props.max_brightness = MAX_BRIGHTNESS;
780 bd->props.brightness = MAX_BRIGHTNESS; 780 bd->props.brightness = MAX_BRIGHTNESS;
781 bd->props.type = BACKLIGHT_RAW;
781 lcd->bd = bd; 782 lcd->bd = bd;
782 783
783 /* 784 /*
@@ -829,6 +830,9 @@ static int __devexit s6e63m0_remove(struct spi_device *spi)
829 struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev); 830 struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev);
830 831
831 s6e63m0_power(lcd, FB_BLANK_POWERDOWN); 832 s6e63m0_power(lcd, FB_BLANK_POWERDOWN);
833 device_remove_file(&spi->dev, &dev_attr_gamma_table);
834 device_remove_file(&spi->dev, &dev_attr_gamma_mode);
835 backlight_device_unregister(lcd->bd);
832 lcd_device_unregister(lcd->ld); 836 lcd_device_unregister(lcd->ld);
833 kfree(lcd); 837 kfree(lcd);
834 838
diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c
index 2a04b382ec48..425a7365470b 100644
--- a/drivers/video/backlight/tosa_bl.c
+++ b/drivers/video/backlight/tosa_bl.c
@@ -102,6 +102,7 @@ static int __devinit tosa_bl_probe(struct i2c_client *client,
102 data->i2c = client; 102 data->i2c = client;
103 103
104 memset(&props, 0, sizeof(struct backlight_properties)); 104 memset(&props, 0, sizeof(struct backlight_properties));
105 props.type = BACKLIGHT_RAW;
105 props.max_brightness = 512 - 1; 106 props.max_brightness = 512 - 1;
106 data->bl = backlight_device_register("tosa-bl", &client->dev, data, 107 data->bl = backlight_device_register("tosa-bl", &client->dev, data,
107 &bl_ops, &props); 108 &bl_ops, &props);
diff --git a/drivers/video/backlight/wm831x_bl.c b/drivers/video/backlight/wm831x_bl.c
index 08fd87f3aecc..d4c6eb248ff9 100644
--- a/drivers/video/backlight/wm831x_bl.c
+++ b/drivers/video/backlight/wm831x_bl.c
@@ -193,6 +193,7 @@ static int wm831x_backlight_probe(struct platform_device *pdev)
193 data->current_brightness = 0; 193 data->current_brightness = 0;
194 data->isink_reg = isink_reg; 194 data->isink_reg = isink_reg;
195 195
196 props.type = BACKLIGHT_RAW;
196 props.max_brightness = max_isel; 197 props.max_brightness = max_isel;
197 bl = backlight_device_register("wm831x", &pdev->dev, data, 198 bl = backlight_device_register("wm831x", &pdev->dev, data,
198 &wm831x_backlight_ops, &props); 199 &wm831x_backlight_ops, &props);
diff --git a/drivers/video/bf537-lq035.c b/drivers/video/bf537-lq035.c
new file mode 100644
index 000000000000..bea53c1a4950
--- /dev/null
+++ b/drivers/video/bf537-lq035.c
@@ -0,0 +1,923 @@
1/*
2 * Analog Devices Blackfin(BF537 STAMP) + SHARP TFT LCD.
3 * http://docs.blackfin.uclinux.org/doku.php?id=hw:cards:tft-lcd
4 *
5 * Copyright 2006-2010 Analog Devices Inc.
6 * Licensed under the GPL-2.
7 */
8
9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10
11#include <linux/module.h>
12#include <linux/kernel.h>
13#include <linux/errno.h>
14#include <linux/string.h>
15#include <linux/mm.h>
16#include <linux/delay.h>
17#include <linux/fb.h>
18#include <linux/ioport.h>
19#include <linux/init.h>
20#include <linux/types.h>
21#include <linux/gpio.h>
22#include <linux/interrupt.h>
23#include <linux/sched.h>
24#include <linux/timer.h>
25#include <linux/device.h>
26#include <linux/backlight.h>
27#include <linux/lcd.h>
28#include <linux/i2c.h>
29#include <linux/spinlock.h>
30#include <linux/dma-mapping.h>
31#include <linux/slab.h>
32#include <linux/platform_device.h>
33
34#include <asm/blackfin.h>
35#include <asm/irq.h>
36#include <asm/dpmc.h>
37#include <asm/dma.h>
38#include <asm/portmux.h>
39
40#define NO_BL 1
41
42#define MAX_BRIGHENESS 95
43#define MIN_BRIGHENESS 5
44#define NBR_PALETTE 256
45
46static const unsigned short ppi_pins[] = {
47 P_PPI0_CLK, P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
48 P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
49 P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
50 P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15, 0
51};
52
53static unsigned char *fb_buffer; /* RGB Buffer */
54static unsigned long *dma_desc_table;
55static int t_conf_done, lq035_open_cnt;
56static DEFINE_SPINLOCK(bfin_lq035_lock);
57
58static int landscape;
59module_param(landscape, int, 0);
60MODULE_PARM_DESC(landscape,
61 "LANDSCAPE use 320x240 instead of Native 240x320 Resolution");
62
63static int bgr;
64module_param(bgr, int, 0);
65MODULE_PARM_DESC(bgr,
66 "BGR use 16-bit BGR-565 instead of RGB-565");
67
68static int nocursor = 1;
69module_param(nocursor, int, 0644);
70MODULE_PARM_DESC(nocursor, "cursor enable/disable");
71
72static unsigned long current_brightness; /* backlight */
73
74/* AD5280 vcomm */
75static unsigned char vcomm_value = 150;
76static struct i2c_client *ad5280_client;
77
78static void set_vcomm(void)
79{
80 int nr;
81
82 if (!ad5280_client)
83 return;
84
85 nr = i2c_smbus_write_byte_data(ad5280_client, 0x00, vcomm_value);
86 if (nr)
87 pr_err("i2c_smbus_write_byte_data fail: %d\n", nr);
88}
89
90static int __devinit ad5280_probe(struct i2c_client *client,
91 const struct i2c_device_id *id)
92{
93 int ret;
94 if (!i2c_check_functionality(client->adapter,
95 I2C_FUNC_SMBUS_BYTE_DATA)) {
96 dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
97 return -EIO;
98 }
99
100 ret = i2c_smbus_write_byte_data(client, 0x00, vcomm_value);
101 if (ret) {
102 dev_err(&client->dev, "write fail: %d\n", ret);
103 return ret;
104 }
105
106 ad5280_client = client;
107
108 return 0;
109}
110
111static int __devexit ad5280_remove(struct i2c_client *client)
112{
113 ad5280_client = NULL;
114 return 0;
115}
116
117static const struct i2c_device_id ad5280_id[] = {
118 {"bf537-lq035-ad5280", 0},
119 {}
120};
121
122MODULE_DEVICE_TABLE(i2c, ad5280_id);
123
124static struct i2c_driver ad5280_driver = {
125 .driver = {
126 .name = "bf537-lq035-ad5280",
127 },
128 .probe = ad5280_probe,
129 .remove = __devexit_p(ad5280_remove),
130 .id_table = ad5280_id,
131};
132
133#ifdef CONFIG_PNAV10
134#define MOD GPIO_PH13
135
136#define bfin_write_TIMER_LP_CONFIG bfin_write_TIMER0_CONFIG
137#define bfin_write_TIMER_LP_WIDTH bfin_write_TIMER0_WIDTH
138#define bfin_write_TIMER_LP_PERIOD bfin_write_TIMER0_PERIOD
139#define bfin_read_TIMER_LP_COUNTER bfin_read_TIMER0_COUNTER
140#define TIMDIS_LP TIMDIS0
141#define TIMEN_LP TIMEN0
142
143#define bfin_write_TIMER_SPS_CONFIG bfin_write_TIMER1_CONFIG
144#define bfin_write_TIMER_SPS_WIDTH bfin_write_TIMER1_WIDTH
145#define bfin_write_TIMER_SPS_PERIOD bfin_write_TIMER1_PERIOD
146#define TIMDIS_SPS TIMDIS1
147#define TIMEN_SPS TIMEN1
148
149#define bfin_write_TIMER_SP_CONFIG bfin_write_TIMER5_CONFIG
150#define bfin_write_TIMER_SP_WIDTH bfin_write_TIMER5_WIDTH
151#define bfin_write_TIMER_SP_PERIOD bfin_write_TIMER5_PERIOD
152#define TIMDIS_SP TIMDIS5
153#define TIMEN_SP TIMEN5
154
155#define bfin_write_TIMER_PS_CLS_CONFIG bfin_write_TIMER2_CONFIG
156#define bfin_write_TIMER_PS_CLS_WIDTH bfin_write_TIMER2_WIDTH
157#define bfin_write_TIMER_PS_CLS_PERIOD bfin_write_TIMER2_PERIOD
158#define TIMDIS_PS_CLS TIMDIS2
159#define TIMEN_PS_CLS TIMEN2
160
161#define bfin_write_TIMER_REV_CONFIG bfin_write_TIMER3_CONFIG
162#define bfin_write_TIMER_REV_WIDTH bfin_write_TIMER3_WIDTH
163#define bfin_write_TIMER_REV_PERIOD bfin_write_TIMER3_PERIOD
164#define TIMDIS_REV TIMDIS3
165#define TIMEN_REV TIMEN3
166#define bfin_read_TIMER_REV_COUNTER bfin_read_TIMER3_COUNTER
167
168#define FREQ_PPI_CLK (5*1024*1024) /* PPI_CLK 5MHz */
169
170#define TIMERS {P_TMR0, P_TMR1, P_TMR2, P_TMR3, P_TMR5, 0}
171
172#else
173
174#define UD GPIO_PF13 /* Up / Down */
175#define MOD GPIO_PF10
176#define LBR GPIO_PF14 /* Left Right */
177
178#define bfin_write_TIMER_LP_CONFIG bfin_write_TIMER6_CONFIG
179#define bfin_write_TIMER_LP_WIDTH bfin_write_TIMER6_WIDTH
180#define bfin_write_TIMER_LP_PERIOD bfin_write_TIMER6_PERIOD
181#define bfin_read_TIMER_LP_COUNTER bfin_read_TIMER6_COUNTER
182#define TIMDIS_LP TIMDIS6
183#define TIMEN_LP TIMEN6
184
185#define bfin_write_TIMER_SPS_CONFIG bfin_write_TIMER1_CONFIG
186#define bfin_write_TIMER_SPS_WIDTH bfin_write_TIMER1_WIDTH
187#define bfin_write_TIMER_SPS_PERIOD bfin_write_TIMER1_PERIOD
188#define TIMDIS_SPS TIMDIS1
189#define TIMEN_SPS TIMEN1
190
191#define bfin_write_TIMER_SP_CONFIG bfin_write_TIMER0_CONFIG
192#define bfin_write_TIMER_SP_WIDTH bfin_write_TIMER0_WIDTH
193#define bfin_write_TIMER_SP_PERIOD bfin_write_TIMER0_PERIOD
194#define TIMDIS_SP TIMDIS0
195#define TIMEN_SP TIMEN0
196
197#define bfin_write_TIMER_PS_CLS_CONFIG bfin_write_TIMER7_CONFIG
198#define bfin_write_TIMER_PS_CLS_WIDTH bfin_write_TIMER7_WIDTH
199#define bfin_write_TIMER_PS_CLS_PERIOD bfin_write_TIMER7_PERIOD
200#define TIMDIS_PS_CLS TIMDIS7
201#define TIMEN_PS_CLS TIMEN7
202
203#define bfin_write_TIMER_REV_CONFIG bfin_write_TIMER5_CONFIG
204#define bfin_write_TIMER_REV_WIDTH bfin_write_TIMER5_WIDTH
205#define bfin_write_TIMER_REV_PERIOD bfin_write_TIMER5_PERIOD
206#define TIMDIS_REV TIMDIS5
207#define TIMEN_REV TIMEN5
208#define bfin_read_TIMER_REV_COUNTER bfin_read_TIMER5_COUNTER
209
210#define FREQ_PPI_CLK (6*1000*1000) /* PPI_CLK 6MHz */
211#define TIMERS {P_TMR0, P_TMR1, P_TMR5, P_TMR6, P_TMR7, 0}
212
213#endif
214
215#define LCD_X_RES 240 /* Horizontal Resolution */
216#define LCD_Y_RES 320 /* Vertical Resolution */
217
218#define LCD_BBP 16 /* Bit Per Pixel */
219
220/* the LCD and the DMA start counting differently;
221 * since one starts at 0 and the other starts at 1,
222 * we have a difference of 1 between START_LINES
223 * and U_LINES.
224 */
225#define START_LINES 8 /* lines for field flyback or field blanking signal */
226#define U_LINES 9 /* number of undisplayed blanking lines */
227
228#define FRAMES_PER_SEC (60)
229
230#define DCLKS_PER_FRAME (FREQ_PPI_CLK/FRAMES_PER_SEC)
231#define DCLKS_PER_LINE (DCLKS_PER_FRAME/(LCD_Y_RES+U_LINES))
232
233#define PPI_CONFIG_VALUE (PORT_DIR|XFR_TYPE|DLEN_16|POLS)
234#define PPI_DELAY_VALUE (0)
235#define TIMER_CONFIG (PWM_OUT|PERIOD_CNT|TIN_SEL|CLK_SEL)
236
237#define ACTIVE_VIDEO_MEM_OFFSET (LCD_X_RES*START_LINES*(LCD_BBP/8))
238#define ACTIVE_VIDEO_MEM_SIZE (LCD_Y_RES*LCD_X_RES*(LCD_BBP/8))
239#define TOTAL_VIDEO_MEM_SIZE ((LCD_Y_RES+U_LINES)*LCD_X_RES*(LCD_BBP/8))
240#define TOTAL_DMA_DESC_SIZE (2 * sizeof(u32) * (LCD_Y_RES + U_LINES))
241
242static void start_timers(void) /* CHECK with HW */
243{
244 unsigned long flags;
245
246 local_irq_save(flags);
247
248 bfin_write_TIMER_ENABLE(TIMEN_REV);
249 SSYNC();
250
251 while (bfin_read_TIMER_REV_COUNTER() <= 11)
252 continue;
253 bfin_write_TIMER_ENABLE(TIMEN_LP);
254 SSYNC();
255
256 while (bfin_read_TIMER_LP_COUNTER() < 3)
257 continue;
258 bfin_write_TIMER_ENABLE(TIMEN_SP|TIMEN_SPS|TIMEN_PS_CLS);
259 SSYNC();
260 t_conf_done = 1;
261 local_irq_restore(flags);
262}
263
264static void config_timers(void)
265{
266 /* Stop timers */
267 bfin_write_TIMER_DISABLE(TIMDIS_SP|TIMDIS_SPS|TIMDIS_REV|
268 TIMDIS_LP|TIMDIS_PS_CLS);
269 SSYNC();
270
271 /* LP, timer 6 */
272 bfin_write_TIMER_LP_CONFIG(TIMER_CONFIG|PULSE_HI);
273 bfin_write_TIMER_LP_WIDTH(1);
274
275 bfin_write_TIMER_LP_PERIOD(DCLKS_PER_LINE);
276 SSYNC();
277
278 /* SPS, timer 1 */
279 bfin_write_TIMER_SPS_CONFIG(TIMER_CONFIG|PULSE_HI);
280 bfin_write_TIMER_SPS_WIDTH(DCLKS_PER_LINE*2);
281 bfin_write_TIMER_SPS_PERIOD((DCLKS_PER_LINE * (LCD_Y_RES+U_LINES)));
282 SSYNC();
283
284 /* SP, timer 0 */
285 bfin_write_TIMER_SP_CONFIG(TIMER_CONFIG|PULSE_HI);
286 bfin_write_TIMER_SP_WIDTH(1);
287 bfin_write_TIMER_SP_PERIOD(DCLKS_PER_LINE);
288 SSYNC();
289
290 /* PS & CLS, timer 7 */
291 bfin_write_TIMER_PS_CLS_CONFIG(TIMER_CONFIG);
292 bfin_write_TIMER_PS_CLS_WIDTH(LCD_X_RES + START_LINES);
293 bfin_write_TIMER_PS_CLS_PERIOD(DCLKS_PER_LINE);
294
295 SSYNC();
296
297#ifdef NO_BL
298 /* REV, timer 5 */
299 bfin_write_TIMER_REV_CONFIG(TIMER_CONFIG|PULSE_HI);
300
301 bfin_write_TIMER_REV_WIDTH(DCLKS_PER_LINE);
302 bfin_write_TIMER_REV_PERIOD(DCLKS_PER_LINE*2);
303
304 SSYNC();
305#endif
306}
307
308static void config_ppi(void)
309{
310 bfin_write_PPI_DELAY(PPI_DELAY_VALUE);
311 bfin_write_PPI_COUNT(LCD_X_RES-1);
312 /* 0x10 -> PORT_CFG -> 2 or 3 frame syncs */
313 bfin_write_PPI_CONTROL((PPI_CONFIG_VALUE|0x10) & (~POLS));
314}
315
316static int config_dma(void)
317{
318 u32 i;
319
320 if (landscape) {
321
322 for (i = 0; i < U_LINES; ++i) {
323 /* blanking lines point to first line of fb_buffer */
324 dma_desc_table[2*i] = (unsigned long)&dma_desc_table[2*i+2];
325 dma_desc_table[2*i+1] = (unsigned long)fb_buffer;
326 }
327
328 for (i = U_LINES; i < U_LINES + LCD_Y_RES; ++i) {
329 /* visible lines */
330 dma_desc_table[2*i] = (unsigned long)&dma_desc_table[2*i+2];
331 dma_desc_table[2*i+1] = (unsigned long)fb_buffer +
332 (LCD_Y_RES+U_LINES-1-i)*2;
333 }
334
335 /* last descriptor points to first */
336 dma_desc_table[2*(LCD_Y_RES+U_LINES-1)] = (unsigned long)&dma_desc_table[0];
337
338 set_dma_x_count(CH_PPI, LCD_X_RES);
339 set_dma_x_modify(CH_PPI, LCD_Y_RES * (LCD_BBP / 8));
340 set_dma_y_count(CH_PPI, 0);
341 set_dma_y_modify(CH_PPI, 0);
342 set_dma_next_desc_addr(CH_PPI, (void *)dma_desc_table[0]);
343 set_dma_config(CH_PPI, DMAFLOW_LARGE | NDSIZE_4 | WDSIZE_16);
344
345 } else {
346
347 set_dma_config(CH_PPI, set_bfin_dma_config(DIR_READ,
348 DMA_FLOW_AUTO,
349 INTR_DISABLE,
350 DIMENSION_2D,
351 DATA_SIZE_16,
352 DMA_NOSYNC_KEEP_DMA_BUF));
353 set_dma_x_count(CH_PPI, LCD_X_RES);
354 set_dma_x_modify(CH_PPI, LCD_BBP / 8);
355 set_dma_y_count(CH_PPI, LCD_Y_RES+U_LINES);
356 set_dma_y_modify(CH_PPI, LCD_BBP / 8);
357 set_dma_start_addr(CH_PPI, (unsigned long) fb_buffer);
358 }
359
360 return 0;
361}
362
363static int __devinit request_ports(void)
364{
365 u16 tmr_req[] = TIMERS;
366
367 /*
368 UD: PF13
369 MOD: PF10
370 LBR: PF14
371 PPI_CLK: PF15
372 */
373
374 if (peripheral_request_list(ppi_pins, KBUILD_MODNAME)) {
375 pr_err("requesting PPI peripheral failed\n");
376 return -EBUSY;
377 }
378
379 if (peripheral_request_list(tmr_req, KBUILD_MODNAME)) {
380 peripheral_free_list(ppi_pins);
381 pr_err("requesting timer peripheral failed\n");
382 return -EBUSY;
383 }
384
385#if (defined(UD) && defined(LBR))
386 if (gpio_request(UD, KBUILD_MODNAME)) {
387 pr_err("requesting GPIO %d failed\n", UD);
388 return -EBUSY;
389 }
390
391 if (gpio_request(LBR, KBUILD_MODNAME)) {
392 pr_err("requesting GPIO %d failed\n", LBR);
393 gpio_free(UD);
394 return -EBUSY;
395 }
396
397 gpio_direction_output(UD, 0);
398 gpio_direction_output(LBR, 1);
399
400#endif
401
402 if (gpio_request(MOD, KBUILD_MODNAME)) {
403 pr_err("requesting GPIO %d failed\n", MOD);
404#if (defined(UD) && defined(LBR))
405 gpio_free(LBR);
406 gpio_free(UD);
407#endif
408 return -EBUSY;
409 }
410
411 gpio_direction_output(MOD, 1);
412
413 SSYNC();
414 return 0;
415}
416
417static void free_ports(void)
418{
419 u16 tmr_req[] = TIMERS;
420
421 peripheral_free_list(ppi_pins);
422 peripheral_free_list(tmr_req);
423
424#if defined(UD) && defined(LBR)
425 gpio_free(LBR);
426 gpio_free(UD);
427#endif
428 gpio_free(MOD);
429}
430
431static struct fb_info bfin_lq035_fb;
432
433static struct fb_var_screeninfo bfin_lq035_fb_defined = {
434 .bits_per_pixel = LCD_BBP,
435 .activate = FB_ACTIVATE_TEST,
436 .xres = LCD_X_RES, /*default portrait mode RGB*/
437 .yres = LCD_Y_RES,
438 .xres_virtual = LCD_X_RES,
439 .yres_virtual = LCD_Y_RES,
440 .height = -1,
441 .width = -1,
442 .left_margin = 0,
443 .right_margin = 0,
444 .upper_margin = 0,
445 .lower_margin = 0,
446 .red = {11, 5, 0},
447 .green = {5, 6, 0},
448 .blue = {0, 5, 0},
449 .transp = {0, 0, 0},
450};
451
452static struct fb_fix_screeninfo bfin_lq035_fb_fix __devinitdata = {
453 .id = KBUILD_MODNAME,
454 .smem_len = ACTIVE_VIDEO_MEM_SIZE,
455 .type = FB_TYPE_PACKED_PIXELS,
456 .visual = FB_VISUAL_TRUECOLOR,
457 .xpanstep = 0,
458 .ypanstep = 0,
459 .line_length = LCD_X_RES*(LCD_BBP/8),
460 .accel = FB_ACCEL_NONE,
461};
462
463
464static int bfin_lq035_fb_open(struct fb_info *info, int user)
465{
466 unsigned long flags;
467
468 spin_lock_irqsave(&bfin_lq035_lock, flags);
469 lq035_open_cnt++;
470 spin_unlock_irqrestore(&bfin_lq035_lock, flags);
471
472 if (lq035_open_cnt <= 1) {
473 bfin_write_PPI_CONTROL(0);
474 SSYNC();
475
476 set_vcomm();
477 config_dma();
478 config_ppi();
479
480 /* start dma */
481 enable_dma(CH_PPI);
482 SSYNC();
483 bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
484 SSYNC();
485
486 if (!t_conf_done) {
487 config_timers();
488 start_timers();
489 }
490 /* gpio_set_value(MOD,1); */
491 }
492
493 return 0;
494}
495
496static int bfin_lq035_fb_release(struct fb_info *info, int user)
497{
498 unsigned long flags;
499
500 spin_lock_irqsave(&bfin_lq035_lock, flags);
501 lq035_open_cnt--;
502 spin_unlock_irqrestore(&bfin_lq035_lock, flags);
503
504
505 if (lq035_open_cnt <= 0) {
506
507 bfin_write_PPI_CONTROL(0);
508 SSYNC();
509
510 disable_dma(CH_PPI);
511 }
512
513 return 0;
514}
515
516
517static int bfin_lq035_fb_check_var(struct fb_var_screeninfo *var,
518 struct fb_info *info)
519{
520 switch (var->bits_per_pixel) {
521 case 16:/* DIRECTCOLOUR, 64k */
522 var->red.offset = info->var.red.offset;
523 var->green.offset = info->var.green.offset;
524 var->blue.offset = info->var.blue.offset;
525 var->red.length = info->var.red.length;
526 var->green.length = info->var.green.length;
527 var->blue.length = info->var.blue.length;
528 var->transp.offset = 0;
529 var->transp.length = 0;
530 var->transp.msb_right = 0;
531 var->red.msb_right = 0;
532 var->green.msb_right = 0;
533 var->blue.msb_right = 0;
534 break;
535 default:
536 pr_debug("%s: depth not supported: %u BPP\n", __func__,
537 var->bits_per_pixel);
538 return -EINVAL;
539 }
540
541 if (info->var.xres != var->xres ||
542 info->var.yres != var->yres ||
543 info->var.xres_virtual != var->xres_virtual ||
544 info->var.yres_virtual != var->yres_virtual) {
545 pr_debug("%s: Resolution not supported: X%u x Y%u\n",
546 __func__, var->xres, var->yres);
547 return -EINVAL;
548 }
549
550 /*
551 * Memory limit
552 */
553
554 if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
555 pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
556 __func__, var->yres_virtual);
557 return -ENOMEM;
558 }
559
560 return 0;
561}
562
563/* fb_rotate
564 * Rotate the display of this angle. This doesn't seems to be used by the core,
565 * but as our hardware supports it, so why not implementing it...
566 */
567static void bfin_lq035_fb_rotate(struct fb_info *fbi, int angle)
568{
569 pr_debug("%s: %p %d", __func__, fbi, angle);
570#if (defined(UD) && defined(LBR))
571 switch (angle) {
572
573 case 180:
574 gpio_set_value(LBR, 0);
575 gpio_set_value(UD, 1);
576 break;
577 default:
578 gpio_set_value(LBR, 1);
579 gpio_set_value(UD, 0);
580 break;
581 }
582#endif
583}
584
585static int bfin_lq035_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
586{
587 if (nocursor)
588 return 0;
589 else
590 return -EINVAL; /* just to force soft_cursor() call */
591}
592
593static int bfin_lq035_fb_setcolreg(u_int regno, u_int red, u_int green,
594 u_int blue, u_int transp,
595 struct fb_info *info)
596{
597 if (regno >= NBR_PALETTE)
598 return -EINVAL;
599
600 if (info->var.grayscale)
601 /* grayscale = 0.30*R + 0.59*G + 0.11*B */
602 red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
603
604 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
605
606 u32 value;
607 /* Place color in the pseudopalette */
608 if (regno > 16)
609 return -EINVAL;
610
611 red >>= (16 - info->var.red.length);
612 green >>= (16 - info->var.green.length);
613 blue >>= (16 - info->var.blue.length);
614
615 value = (red << info->var.red.offset) |
616 (green << info->var.green.offset)|
617 (blue << info->var.blue.offset);
618 value &= 0xFFFF;
619
620 ((u32 *) (info->pseudo_palette))[regno] = value;
621
622 }
623
624 return 0;
625}
626
627static struct fb_ops bfin_lq035_fb_ops = {
628 .owner = THIS_MODULE,
629 .fb_open = bfin_lq035_fb_open,
630 .fb_release = bfin_lq035_fb_release,
631 .fb_check_var = bfin_lq035_fb_check_var,
632 .fb_rotate = bfin_lq035_fb_rotate,
633 .fb_fillrect = cfb_fillrect,
634 .fb_copyarea = cfb_copyarea,
635 .fb_imageblit = cfb_imageblit,
636 .fb_cursor = bfin_lq035_fb_cursor,
637 .fb_setcolreg = bfin_lq035_fb_setcolreg,
638};
639
640static int bl_get_brightness(struct backlight_device *bd)
641{
642 return current_brightness;
643}
644
645static const struct backlight_ops bfin_lq035fb_bl_ops = {
646 .get_brightness = bl_get_brightness,
647};
648
649static struct backlight_device *bl_dev;
650
651static int bfin_lcd_get_power(struct lcd_device *dev)
652{
653 return 0;
654}
655
656static int bfin_lcd_set_power(struct lcd_device *dev, int power)
657{
658 return 0;
659}
660
661static int bfin_lcd_get_contrast(struct lcd_device *dev)
662{
663 return (int)vcomm_value;
664}
665
666static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast)
667{
668 if (contrast > 255)
669 contrast = 255;
670 if (contrast < 0)
671 contrast = 0;
672
673 vcomm_value = (unsigned char)contrast;
674 set_vcomm();
675 return 0;
676}
677
678static int bfin_lcd_check_fb(struct lcd_device *lcd, struct fb_info *fi)
679{
680 if (!fi || (fi == &bfin_lq035_fb))
681 return 1;
682 return 0;
683}
684
685static struct lcd_ops bfin_lcd_ops = {
686 .get_power = bfin_lcd_get_power,
687 .set_power = bfin_lcd_set_power,
688 .get_contrast = bfin_lcd_get_contrast,
689 .set_contrast = bfin_lcd_set_contrast,
690 .check_fb = bfin_lcd_check_fb,
691};
692
693static struct lcd_device *lcd_dev;
694
695static int __devinit bfin_lq035_probe(struct platform_device *pdev)
696{
697 struct backlight_properties props;
698 dma_addr_t dma_handle;
699 int ret;
700
701 if (request_dma(CH_PPI, KBUILD_MODNAME)) {
702 pr_err("couldn't request PPI DMA\n");
703 return -EFAULT;
704 }
705
706 if (request_ports()) {
707 pr_err("couldn't request gpio port\n");
708 ret = -EFAULT;
709 goto out_ports;
710 }
711
712 fb_buffer = dma_alloc_coherent(NULL, TOTAL_VIDEO_MEM_SIZE,
713 &dma_handle, GFP_KERNEL);
714 if (fb_buffer == NULL) {
715 pr_err("couldn't allocate dma buffer\n");
716 ret = -ENOMEM;
717 goto out_dma_coherent;
718 }
719
720 if (L1_DATA_A_LENGTH)
721 dma_desc_table = l1_data_sram_zalloc(TOTAL_DMA_DESC_SIZE);
722 else
723 dma_desc_table = dma_alloc_coherent(NULL, TOTAL_DMA_DESC_SIZE,
724 &dma_handle, 0);
725
726 if (dma_desc_table == NULL) {
727 pr_err("couldn't allocate dma descriptor\n");
728 ret = -ENOMEM;
729 goto out_table;
730 }
731
732 bfin_lq035_fb.screen_base = (void *)fb_buffer;
733 bfin_lq035_fb_fix.smem_start = (int)fb_buffer;
734 if (landscape) {
735 bfin_lq035_fb_defined.xres = LCD_Y_RES;
736 bfin_lq035_fb_defined.yres = LCD_X_RES;
737 bfin_lq035_fb_defined.xres_virtual = LCD_Y_RES;
738 bfin_lq035_fb_defined.yres_virtual = LCD_X_RES;
739
740 bfin_lq035_fb_fix.line_length = LCD_Y_RES*(LCD_BBP/8);
741 } else {
742 bfin_lq035_fb.screen_base += ACTIVE_VIDEO_MEM_OFFSET;
743 bfin_lq035_fb_fix.smem_start += ACTIVE_VIDEO_MEM_OFFSET;
744 }
745
746 bfin_lq035_fb_defined.green.msb_right = 0;
747 bfin_lq035_fb_defined.red.msb_right = 0;
748 bfin_lq035_fb_defined.blue.msb_right = 0;
749 bfin_lq035_fb_defined.green.offset = 5;
750 bfin_lq035_fb_defined.green.length = 6;
751 bfin_lq035_fb_defined.red.length = 5;
752 bfin_lq035_fb_defined.blue.length = 5;
753
754 if (bgr) {
755 bfin_lq035_fb_defined.red.offset = 0;
756 bfin_lq035_fb_defined.blue.offset = 11;
757 } else {
758 bfin_lq035_fb_defined.red.offset = 11;
759 bfin_lq035_fb_defined.blue.offset = 0;
760 }
761
762 bfin_lq035_fb.fbops = &bfin_lq035_fb_ops;
763 bfin_lq035_fb.var = bfin_lq035_fb_defined;
764
765 bfin_lq035_fb.fix = bfin_lq035_fb_fix;
766 bfin_lq035_fb.flags = FBINFO_DEFAULT;
767
768
769 bfin_lq035_fb.pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL);
770 if (bfin_lq035_fb.pseudo_palette == NULL) {
771 pr_err("failed to allocate pseudo_palette\n");
772 ret = -ENOMEM;
773 goto out_palette;
774 }
775
776 if (fb_alloc_cmap(&bfin_lq035_fb.cmap, NBR_PALETTE, 0) < 0) {
777 pr_err("failed to allocate colormap (%d entries)\n",
778 NBR_PALETTE);
779 ret = -EFAULT;
780 goto out_cmap;
781 }
782
783 if (register_framebuffer(&bfin_lq035_fb) < 0) {
784 pr_err("unable to register framebuffer\n");
785 ret = -EINVAL;
786 goto out_reg;
787 }
788
789 i2c_add_driver(&ad5280_driver);
790
791 memset(&props, 0, sizeof(props));
792 props.type = BACKLIGHT_RAW;
793 props.max_brightness = MAX_BRIGHENESS;
794 bl_dev = backlight_device_register("bf537-bl", NULL, NULL,
795 &bfin_lq035fb_bl_ops, &props);
796
797 lcd_dev = lcd_device_register(KBUILD_MODNAME, &pdev->dev, NULL,
798 &bfin_lcd_ops);
799 if (IS_ERR(lcd_dev)) {
800 pr_err("unable to register lcd\n");
801 ret = PTR_ERR(lcd_dev);
802 goto out_lcd;
803 }
804 lcd_dev->props.max_contrast = 255,
805
806 pr_info("initialized");
807
808 return 0;
809out_lcd:
810 unregister_framebuffer(&bfin_lq035_fb);
811out_reg:
812 fb_dealloc_cmap(&bfin_lq035_fb.cmap);
813out_cmap:
814 kfree(bfin_lq035_fb.pseudo_palette);
815out_palette:
816out_table:
817 dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
818 fb_buffer = NULL;
819out_dma_coherent:
820 free_ports();
821out_ports:
822 free_dma(CH_PPI);
823 return ret;
824}
825
826static int __devexit bfin_lq035_remove(struct platform_device *pdev)
827{
828 if (fb_buffer != NULL)
829 dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
830
831 if (L1_DATA_A_LENGTH)
832 l1_data_sram_free(dma_desc_table);
833 else
834 dma_free_coherent(NULL, TOTAL_DMA_DESC_SIZE, NULL, 0);
835
836 bfin_write_TIMER_DISABLE(TIMEN_SP|TIMEN_SPS|TIMEN_PS_CLS|
837 TIMEN_LP|TIMEN_REV);
838 t_conf_done = 0;
839
840 free_dma(CH_PPI);
841
842
843 kfree(bfin_lq035_fb.pseudo_palette);
844 fb_dealloc_cmap(&bfin_lq035_fb.cmap);
845
846
847 lcd_device_unregister(lcd_dev);
848 backlight_device_unregister(bl_dev);
849
850 unregister_framebuffer(&bfin_lq035_fb);
851 i2c_del_driver(&ad5280_driver);
852
853 free_ports();
854
855 pr_info("unregistered LCD driver\n");
856
857 return 0;
858}
859
860#ifdef CONFIG_PM
861static int bfin_lq035_suspend(struct platform_device *pdev, pm_message_t state)
862{
863 if (lq035_open_cnt > 0) {
864 bfin_write_PPI_CONTROL(0);
865 SSYNC();
866 disable_dma(CH_PPI);
867 }
868
869 return 0;
870}
871
872static int bfin_lq035_resume(struct platform_device *pdev)
873{
874 if (lq035_open_cnt > 0) {
875 bfin_write_PPI_CONTROL(0);
876 SSYNC();
877
878 config_dma();
879 config_ppi();
880
881 enable_dma(CH_PPI);
882 bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
883 SSYNC();
884
885 config_timers();
886 start_timers();
887 } else {
888 t_conf_done = 0;
889 }
890
891 return 0;
892}
893#else
894# define bfin_lq035_suspend NULL
895# define bfin_lq035_resume NULL
896#endif
897
898static struct platform_driver bfin_lq035_driver = {
899 .probe = bfin_lq035_probe,
900 .remove = __devexit_p(bfin_lq035_remove),
901 .suspend = bfin_lq035_suspend,
902 .resume = bfin_lq035_resume,
903 .driver = {
904 .name = KBUILD_MODNAME,
905 .owner = THIS_MODULE,
906 },
907};
908
909static int __init bfin_lq035_driver_init(void)
910{
911 request_module("i2c-bfin-twi");
912 return platform_driver_register(&bfin_lq035_driver);
913}
914module_init(bfin_lq035_driver_init);
915
916static void __exit bfin_lq035_driver_cleanup(void)
917{
918 platform_driver_unregister(&bfin_lq035_driver);
919}
920module_exit(bfin_lq035_driver_cleanup);
921
922MODULE_DESCRIPTION("SHARP LQ035Q7DB03 TFT LCD Driver");
923MODULE_LICENSE("GPL");
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c
index b020ba7f1cf2..2464b910b590 100644
--- a/drivers/video/bf54x-lq043fb.c
+++ b/drivers/video/bf54x-lq043fb.c
@@ -241,12 +241,12 @@ static int request_ports(struct bfin_bf54xfb_info *fbi)
241 u16 disp = fbi->mach_info->disp; 241 u16 disp = fbi->mach_info->disp;
242 242
243 if (gpio_request(disp, DRIVER_NAME)) { 243 if (gpio_request(disp, DRIVER_NAME)) {
244 printk(KERN_ERR "Requesting GPIO %d faild\n", disp); 244 printk(KERN_ERR "Requesting GPIO %d failed\n", disp);
245 return -EFAULT; 245 return -EFAULT;
246 } 246 }
247 247
248 if (peripheral_request_list(eppi_req_18, DRIVER_NAME)) { 248 if (peripheral_request_list(eppi_req_18, DRIVER_NAME)) {
249 printk(KERN_ERR "Requesting Peripherals faild\n"); 249 printk(KERN_ERR "Requesting Peripherals failed\n");
250 gpio_free(disp); 250 gpio_free(disp);
251 return -EFAULT; 251 return -EFAULT;
252 } 252 }
@@ -256,7 +256,7 @@ static int request_ports(struct bfin_bf54xfb_info *fbi)
256 u16 eppi_req_24[] = EPPI0_24; 256 u16 eppi_req_24[] = EPPI0_24;
257 257
258 if (peripheral_request_list(eppi_req_24, DRIVER_NAME)) { 258 if (peripheral_request_list(eppi_req_24, DRIVER_NAME)) {
259 printk(KERN_ERR "Requesting Peripherals faild\n"); 259 printk(KERN_ERR "Requesting Peripherals failed\n");
260 peripheral_free_list(eppi_req_18); 260 peripheral_free_list(eppi_req_18);
261 gpio_free(disp); 261 gpio_free(disp);
262 return -EFAULT; 262 return -EFAULT;
@@ -649,6 +649,7 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
649 } 649 }
650#ifndef NO_BL_SUPPORT 650#ifndef NO_BL_SUPPORT
651 memset(&props, 0, sizeof(struct backlight_properties)); 651 memset(&props, 0, sizeof(struct backlight_properties));
652 props.type = BACKLIGHT_RAW;
652 props.max_brightness = 255; 653 props.max_brightness = 255;
653 bl_dev = backlight_device_register("bf54x-bl", NULL, NULL, 654 bl_dev = backlight_device_register("bf54x-bl", NULL, NULL,
654 &bfin_lq043fb_bl_ops, &props); 655 &bfin_lq043fb_bl_ops, &props);
diff --git a/drivers/video/bfin-lq035q1-fb.c b/drivers/video/bfin-lq035q1-fb.c
index c8e1f04941bd..23b6c4b62c78 100644
--- a/drivers/video/bfin-lq035q1-fb.c
+++ b/drivers/video/bfin-lq035q1-fb.c
@@ -154,8 +154,10 @@ static int __devinit lq035q1_spidev_probe(struct spi_device *spi)
154 154
155 ret = lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_ON); 155 ret = lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_ON);
156 ret |= lq035q1_control(spi, LQ035_DRIVER_OUTPUT_CTL, ctl->mode); 156 ret |= lq035q1_control(spi, LQ035_DRIVER_OUTPUT_CTL, ctl->mode);
157 if (ret) 157 if (ret) {
158 kfree(ctl);
158 return ret; 159 return ret;
160 }
159 161
160 spi_set_drvdata(spi, ctl); 162 spi_set_drvdata(spi, ctl);
161 163
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c
index 7a50272eaab9..d8de29f0dd8d 100644
--- a/drivers/video/bfin-t350mcqb-fb.c
+++ b/drivers/video/bfin-t350mcqb-fb.c
@@ -192,7 +192,7 @@ static int bfin_t350mcqb_request_ports(int action)
192{ 192{
193 if (action) { 193 if (action) {
194 if (peripheral_request_list(ppi0_req_8, DRIVER_NAME)) { 194 if (peripheral_request_list(ppi0_req_8, DRIVER_NAME)) {
195 printk(KERN_ERR "Requesting Peripherals faild\n"); 195 printk(KERN_ERR "Requesting Peripherals failed\n");
196 return -EFAULT; 196 return -EFAULT;
197 } 197 }
198 } else 198 } else
@@ -545,6 +545,7 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev)
545 } 545 }
546#ifndef NO_BL_SUPPORT 546#ifndef NO_BL_SUPPORT
547 memset(&props, 0, sizeof(struct backlight_properties)); 547 memset(&props, 0, sizeof(struct backlight_properties));
548 props.type = BACKLIGHT_RAW;
548 props.max_brightness = 255; 549 props.max_brightness = 255;
549 bl_dev = backlight_device_register("bf52x-bl", NULL, NULL, 550 bl_dev = backlight_device_register("bf52x-bl", NULL, NULL,
550 &bfin_lq043fb_bl_ops, &props); 551 &bfin_lq043fb_bl_ops, &props);
diff --git a/drivers/video/bfin_adv7393fb.c b/drivers/video/bfin_adv7393fb.c
new file mode 100644
index 000000000000..8486f541156b
--- /dev/null
+++ b/drivers/video/bfin_adv7393fb.c
@@ -0,0 +1,832 @@
1/*
2 * Frame buffer driver for ADV7393/2 video encoder
3 *
4 * Copyright 2006-2009 Analog Devices Inc.
5 * Licensed under the GPL-2 or late.
6 */
7
8/*
9 * TODO: Remove Globals
10 * TODO: Code Cleanup
11 */
12
13#define pr_fmt(fmt) DRIVER_NAME ": " fmt
14
15#include <linux/module.h>
16#include <linux/kernel.h>
17#include <linux/errno.h>
18#include <linux/string.h>
19#include <linux/mm.h>
20#include <linux/tty.h>
21#include <linux/slab.h>
22#include <linux/delay.h>
23#include <linux/fb.h>
24#include <linux/ioport.h>
25#include <linux/init.h>
26#include <linux/types.h>
27#include <linux/interrupt.h>
28#include <linux/sched.h>
29#include <asm/blackfin.h>
30#include <asm/irq.h>
31#include <asm/dma.h>
32#include <linux/uaccess.h>
33#include <linux/gpio.h>
34#include <asm/portmux.h>
35
36#include <linux/dma-mapping.h>
37#include <linux/proc_fs.h>
38#include <linux/platform_device.h>
39
40#include <linux/i2c.h>
41#include <linux/i2c-dev.h>
42
43#include "bfin_adv7393fb.h"
44
45static int mode = VMODE;
46static int mem = VMEM;
47static int nocursor = 1;
48
49static const unsigned short ppi_pins[] = {
50 P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
51 P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
52 P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
53 P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
54 P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15,
55 0
56};
57
58/*
59 * card parameters
60 */
61
62static struct bfin_adv7393_fb_par {
63 /* structure holding blackfin / adv7393 paramters when
64 screen is blanked */
65 struct {
66 u8 Mode; /* ntsc/pal/? */
67 } vga_state;
68 atomic_t ref_count;
69} bfin_par;
70
71/* --------------------------------------------------------------------- */
72
73static struct fb_var_screeninfo bfin_adv7393_fb_defined = {
74 .xres = 720,
75 .yres = 480,
76 .xres_virtual = 720,
77 .yres_virtual = 480,
78 .bits_per_pixel = 16,
79 .activate = FB_ACTIVATE_TEST,
80 .height = -1,
81 .width = -1,
82 .left_margin = 0,
83 .right_margin = 0,
84 .upper_margin = 0,
85 .lower_margin = 0,
86 .vmode = FB_VMODE_INTERLACED,
87 .red = {11, 5, 0},
88 .green = {5, 6, 0},
89 .blue = {0, 5, 0},
90 .transp = {0, 0, 0},
91};
92
93static struct fb_fix_screeninfo bfin_adv7393_fb_fix __devinitdata = {
94 .id = "BFIN ADV7393",
95 .smem_len = 720 * 480 * 2,
96 .type = FB_TYPE_PACKED_PIXELS,
97 .visual = FB_VISUAL_TRUECOLOR,
98 .xpanstep = 0,
99 .ypanstep = 0,
100 .line_length = 720 * 2,
101 .accel = FB_ACCEL_NONE
102};
103
104static struct fb_ops bfin_adv7393_fb_ops = {
105 .owner = THIS_MODULE,
106 .fb_open = bfin_adv7393_fb_open,
107 .fb_release = bfin_adv7393_fb_release,
108 .fb_check_var = bfin_adv7393_fb_check_var,
109 .fb_pan_display = bfin_adv7393_fb_pan_display,
110 .fb_blank = bfin_adv7393_fb_blank,
111 .fb_fillrect = cfb_fillrect,
112 .fb_copyarea = cfb_copyarea,
113 .fb_imageblit = cfb_imageblit,
114 .fb_cursor = bfin_adv7393_fb_cursor,
115 .fb_setcolreg = bfin_adv7393_fb_setcolreg,
116};
117
118static int dma_desc_list(struct adv7393fb_device *fbdev, u16 arg)
119{
120 if (arg == BUILD) { /* Build */
121 fbdev->vb1 = l1_data_sram_zalloc(sizeof(struct dmasg));
122 if (fbdev->vb1 == NULL)
123 goto error;
124
125 fbdev->av1 = l1_data_sram_zalloc(sizeof(struct dmasg));
126 if (fbdev->av1 == NULL)
127 goto error;
128
129 fbdev->vb2 = l1_data_sram_zalloc(sizeof(struct dmasg));
130 if (fbdev->vb2 == NULL)
131 goto error;
132
133 fbdev->av2 = l1_data_sram_zalloc(sizeof(struct dmasg));
134 if (fbdev->av2 == NULL)
135 goto error;
136
137 /* Build linked DMA descriptor list */
138 fbdev->vb1->next_desc_addr = fbdev->av1;
139 fbdev->av1->next_desc_addr = fbdev->vb2;
140 fbdev->vb2->next_desc_addr = fbdev->av2;
141 fbdev->av2->next_desc_addr = fbdev->vb1;
142
143 /* Save list head */
144 fbdev->descriptor_list_head = fbdev->av2;
145
146 /* Vertical Blanking Field 1 */
147 fbdev->vb1->start_addr = VB_DUMMY_MEMORY_SOURCE;
148 fbdev->vb1->cfg = DMA_CFG_VAL;
149
150 fbdev->vb1->x_count =
151 fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank;
152
153 fbdev->vb1->x_modify = 0;
154 fbdev->vb1->y_count = fbdev->modes[mode].vb1_lines;
155 fbdev->vb1->y_modify = 0;
156
157 /* Active Video Field 1 */
158
159 fbdev->av1->start_addr = (unsigned long)fbdev->fb_mem;
160 fbdev->av1->cfg = DMA_CFG_VAL;
161 fbdev->av1->x_count =
162 fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank;
163 fbdev->av1->x_modify = fbdev->modes[mode].bpp / 8;
164 fbdev->av1->y_count = fbdev->modes[mode].a_lines;
165 fbdev->av1->y_modify =
166 (fbdev->modes[mode].xres - fbdev->modes[mode].boeft_blank +
167 1) * (fbdev->modes[mode].bpp / 8);
168
169 /* Vertical Blanking Field 2 */
170
171 fbdev->vb2->start_addr = VB_DUMMY_MEMORY_SOURCE;
172 fbdev->vb2->cfg = DMA_CFG_VAL;
173 fbdev->vb2->x_count =
174 fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank;
175
176 fbdev->vb2->x_modify = 0;
177 fbdev->vb2->y_count = fbdev->modes[mode].vb2_lines;
178 fbdev->vb2->y_modify = 0;
179
180 /* Active Video Field 2 */
181
182 fbdev->av2->start_addr =
183 (unsigned long)fbdev->fb_mem + fbdev->line_len;
184
185 fbdev->av2->cfg = DMA_CFG_VAL;
186
187 fbdev->av2->x_count =
188 fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank;
189
190 fbdev->av2->x_modify = (fbdev->modes[mode].bpp / 8);
191 fbdev->av2->y_count = fbdev->modes[mode].a_lines;
192
193 fbdev->av2->y_modify =
194 (fbdev->modes[mode].xres - fbdev->modes[mode].boeft_blank +
195 1) * (fbdev->modes[mode].bpp / 8);
196
197 return 1;
198 }
199
200error:
201 l1_data_sram_free(fbdev->vb1);
202 l1_data_sram_free(fbdev->av1);
203 l1_data_sram_free(fbdev->vb2);
204 l1_data_sram_free(fbdev->av2);
205
206 return 0;
207}
208
209static int bfin_config_dma(struct adv7393fb_device *fbdev)
210{
211 BUG_ON(!(fbdev->fb_mem));
212
213 set_dma_x_count(CH_PPI, fbdev->descriptor_list_head->x_count);
214 set_dma_x_modify(CH_PPI, fbdev->descriptor_list_head->x_modify);
215 set_dma_y_count(CH_PPI, fbdev->descriptor_list_head->y_count);
216 set_dma_y_modify(CH_PPI, fbdev->descriptor_list_head->y_modify);
217 set_dma_start_addr(CH_PPI, fbdev->descriptor_list_head->start_addr);
218 set_dma_next_desc_addr(CH_PPI,
219 fbdev->descriptor_list_head->next_desc_addr);
220 set_dma_config(CH_PPI, fbdev->descriptor_list_head->cfg);
221
222 return 1;
223}
224
225static void bfin_disable_dma(void)
226{
227 bfin_write_DMA0_CONFIG(bfin_read_DMA0_CONFIG() & ~DMAEN);
228}
229
230static void bfin_config_ppi(struct adv7393fb_device *fbdev)
231{
232 if (ANOMALY_05000183) {
233 bfin_write_TIMER2_CONFIG(WDTH_CAP);
234 bfin_write_TIMER_ENABLE(TIMEN2);
235 }
236
237 bfin_write_PPI_CONTROL(0x381E);
238 bfin_write_PPI_FRAME(fbdev->modes[mode].tot_lines);
239 bfin_write_PPI_COUNT(fbdev->modes[mode].xres +
240 fbdev->modes[mode].boeft_blank - 1);
241 bfin_write_PPI_DELAY(fbdev->modes[mode].aoeft_blank - 1);
242}
243
244static void bfin_enable_ppi(void)
245{
246 bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
247}
248
249static void bfin_disable_ppi(void)
250{
251 bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() & ~PORT_EN);
252}
253
254static inline int adv7393_write(struct i2c_client *client, u8 reg, u8 value)
255{
256 return i2c_smbus_write_byte_data(client, reg, value);
257}
258
259static inline int adv7393_read(struct i2c_client *client, u8 reg)
260{
261 return i2c_smbus_read_byte_data(client, reg);
262}
263
264static int
265adv7393_write_block(struct i2c_client *client,
266 const u8 *data, unsigned int len)
267{
268 int ret = -1;
269 u8 reg;
270
271 while (len >= 2) {
272 reg = *data++;
273 ret = adv7393_write(client, reg, *data++);
274 if (ret < 0)
275 break;
276 len -= 2;
277 }
278
279 return ret;
280}
281
282static int adv7393_mode(struct i2c_client *client, u16 mode)
283{
284 switch (mode) {
285 case POWER_ON: /* ADV7393 Sleep mode OFF */
286 adv7393_write(client, 0x00, 0x1E);
287 break;
288 case POWER_DOWN: /* ADV7393 Sleep mode ON */
289 adv7393_write(client, 0x00, 0x1F);
290 break;
291 case BLANK_OFF: /* Pixel Data Valid */
292 adv7393_write(client, 0x82, 0xCB);
293 break;
294 case BLANK_ON: /* Pixel Data Invalid */
295 adv7393_write(client, 0x82, 0x8B);
296 break;
297 default:
298 return -EINVAL;
299 break;
300 }
301 return 0;
302}
303
304static irqreturn_t ppi_irq_error(int irq, void *dev_id)
305{
306
307 struct adv7393fb_device *fbdev = (struct adv7393fb_device *)dev_id;
308
309 u16 status = bfin_read_PPI_STATUS();
310
311 pr_debug("%s: PPI Status = 0x%X\n", __func__, status);
312
313 if (status) {
314 bfin_disable_dma(); /* TODO: Check Sequence */
315 bfin_disable_ppi();
316 bfin_clear_PPI_STATUS();
317 bfin_config_dma(fbdev);
318 bfin_enable_ppi();
319 }
320
321 return IRQ_HANDLED;
322
323}
324
325static int proc_output(char *buf)
326{
327 char *p = buf;
328
329 p += sprintf(p,
330 "Usage:\n"
331 "echo 0x[REG][Value] > adv7393\n"
332 "example: echo 0x1234 >adv7393\n"
333 "writes 0x34 into Register 0x12\n");
334
335 return p - buf;
336}
337
338static int
339adv7393_read_proc(char *page, char **start, off_t off,
340 int count, int *eof, void *data)
341{
342 int len;
343
344 len = proc_output(page);
345 if (len <= off + count)
346 *eof = 1;
347 *start = page + off;
348 len -= off;
349 if (len > count)
350 len = count;
351 if (len < 0)
352 len = 0;
353 return len;
354}
355
356static int
357adv7393_write_proc(struct file *file, const char __user * buffer,
358 unsigned long count, void *data)
359{
360 struct adv7393fb_device *fbdev = data;
361 char line[8];
362 unsigned int val;
363 int ret;
364
365 ret = copy_from_user(line, buffer, count);
366 if (ret)
367 return -EFAULT;
368
369 val = simple_strtoul(line, NULL, 0);
370 adv7393_write(fbdev->client, val >> 8, val & 0xff);
371
372 return count;
373}
374
375static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client,
376 const struct i2c_device_id *id)
377{
378 int ret = 0;
379 struct proc_dir_entry *entry;
380 int num_modes = ARRAY_SIZE(known_modes);
381
382 struct adv7393fb_device *fbdev = NULL;
383
384 if (mem > 2) {
385 dev_err(&client->dev, "mem out of allowed range [1;2]\n");
386 return -EINVAL;
387 }
388
389 if (mode > num_modes) {
390 dev_err(&client->dev, "mode %d: not supported", mode);
391 return -EFAULT;
392 }
393
394 fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
395 if (!fbdev) {
396 dev_err(&client->dev, "failed to allocate device private record");
397 return -ENOMEM;
398 }
399
400 i2c_set_clientdata(client, fbdev);
401
402 fbdev->modes = known_modes;
403 fbdev->client = client;
404
405 fbdev->fb_len =
406 mem * fbdev->modes[mode].xres * fbdev->modes[mode].xres *
407 (fbdev->modes[mode].bpp / 8);
408
409 fbdev->line_len =
410 fbdev->modes[mode].xres * (fbdev->modes[mode].bpp / 8);
411
412 /* Workaround "PPI Does Not Start Properly In Specific Mode" */
413 if (ANOMALY_05000400) {
414 if (gpio_request(P_IDENT(P_PPI0_FS3), "PPI0_FS3")) {
415 dev_err(&client->dev, "PPI0_FS3 GPIO request failed\n");
416 ret = -EBUSY;
417 goto out_8;
418 }
419 gpio_direction_output(P_IDENT(P_PPI0_FS3), 0);
420 }
421
422 if (peripheral_request_list(ppi_pins, DRIVER_NAME)) {
423 dev_err(&client->dev, "requesting PPI peripheral failed\n");
424 ret = -EFAULT;
425 goto out_8;
426 }
427
428 fbdev->fb_mem =
429 dma_alloc_coherent(NULL, fbdev->fb_len, &fbdev->dma_handle,
430 GFP_KERNEL);
431
432 if (NULL == fbdev->fb_mem) {
433 dev_err(&client->dev, "couldn't allocate dma buffer (%d bytes)\n",
434 (u32) fbdev->fb_len);
435 ret = -ENOMEM;
436 goto out_7;
437 }
438
439 fbdev->info.screen_base = (void *)fbdev->fb_mem;
440 bfin_adv7393_fb_fix.smem_start = (int)fbdev->fb_mem;
441
442 bfin_adv7393_fb_fix.smem_len = fbdev->fb_len;
443 bfin_adv7393_fb_fix.line_length = fbdev->line_len;
444
445 if (mem > 1)
446 bfin_adv7393_fb_fix.ypanstep = 1;
447
448 bfin_adv7393_fb_defined.red.length = 5;
449 bfin_adv7393_fb_defined.green.length = 6;
450 bfin_adv7393_fb_defined.blue.length = 5;
451
452 bfin_adv7393_fb_defined.xres = fbdev->modes[mode].xres;
453 bfin_adv7393_fb_defined.yres = fbdev->modes[mode].yres;
454 bfin_adv7393_fb_defined.xres_virtual = fbdev->modes[mode].xres;
455 bfin_adv7393_fb_defined.yres_virtual = mem * fbdev->modes[mode].yres;
456 bfin_adv7393_fb_defined.bits_per_pixel = fbdev->modes[mode].bpp;
457
458 fbdev->info.fbops = &bfin_adv7393_fb_ops;
459 fbdev->info.var = bfin_adv7393_fb_defined;
460 fbdev->info.fix = bfin_adv7393_fb_fix;
461 fbdev->info.par = &bfin_par;
462 fbdev->info.flags = FBINFO_DEFAULT;
463
464 fbdev->info.pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL);
465 if (!fbdev->info.pseudo_palette) {
466 dev_err(&client->dev, "failed to allocate pseudo_palette\n");
467 ret = -ENOMEM;
468 goto out_6;
469 }
470
471 if (fb_alloc_cmap(&fbdev->info.cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0) < 0) {
472 dev_err(&client->dev, "failed to allocate colormap (%d entries)\n",
473 BFIN_LCD_NBR_PALETTE_ENTRIES);
474 ret = -EFAULT;
475 goto out_5;
476 }
477
478 if (request_dma(CH_PPI, "BF5xx_PPI_DMA") < 0) {
479 dev_err(&client->dev, "unable to request PPI DMA\n");
480 ret = -EFAULT;
481 goto out_4;
482 }
483
484 if (request_irq(IRQ_PPI_ERROR, ppi_irq_error, IRQF_DISABLED,
485 "PPI ERROR", fbdev) < 0) {
486 dev_err(&client->dev, "unable to request PPI ERROR IRQ\n");
487 ret = -EFAULT;
488 goto out_3;
489 }
490
491 fbdev->open = 0;
492
493 ret = adv7393_write_block(client, fbdev->modes[mode].adv7393_i2c_initd,
494 fbdev->modes[mode].adv7393_i2c_initd_len);
495
496 if (ret) {
497 dev_err(&client->dev, "i2c attach: init error\n");
498 goto out_1;
499 }
500
501
502 if (register_framebuffer(&fbdev->info) < 0) {
503 dev_err(&client->dev, "unable to register framebuffer\n");
504 ret = -EFAULT;
505 goto out_1;
506 }
507
508 dev_info(&client->dev, "fb%d: %s frame buffer device\n",
509 fbdev->info.node, fbdev->info.fix.id);
510 dev_info(&client->dev, "fb memory address : 0x%p\n", fbdev->fb_mem);
511
512 entry = create_proc_entry("driver/adv7393", 0, NULL);
513 if (!entry) {
514 dev_err(&client->dev, "unable to create /proc entry\n");
515 ret = -EFAULT;
516 goto out_0;
517 }
518
519 entry->read_proc = adv7393_read_proc;
520 entry->write_proc = adv7393_write_proc;
521 entry->data = fbdev;
522
523 return 0;
524
525 out_0:
526 unregister_framebuffer(&fbdev->info);
527 out_1:
528 free_irq(IRQ_PPI_ERROR, fbdev);
529 out_3:
530 free_dma(CH_PPI);
531 out_4:
532 dma_free_coherent(NULL, fbdev->fb_len, fbdev->fb_mem,
533 fbdev->dma_handle);
534 out_5:
535 fb_dealloc_cmap(&fbdev->info.cmap);
536 out_6:
537 kfree(fbdev->info.pseudo_palette);
538 out_7:
539 peripheral_free_list(ppi_pins);
540 out_8:
541 kfree(fbdev);
542
543 return ret;
544}
545
546static int bfin_adv7393_fb_open(struct fb_info *info, int user)
547{
548 struct adv7393fb_device *fbdev = to_adv7393fb_device(info);
549
550 fbdev->info.screen_base = (void *)fbdev->fb_mem;
551 if (!fbdev->info.screen_base) {
552 dev_err(&fbdev->client->dev, "unable to map device\n");
553 return -ENOMEM;
554 }
555
556 fbdev->open = 1;
557 dma_desc_list(fbdev, BUILD);
558 adv7393_mode(fbdev->client, BLANK_OFF);
559 bfin_config_ppi(fbdev);
560 bfin_config_dma(fbdev);
561 bfin_enable_ppi();
562
563 return 0;
564}
565
566static int bfin_adv7393_fb_release(struct fb_info *info, int user)
567{
568 struct adv7393fb_device *fbdev = to_adv7393fb_device(info);
569
570 adv7393_mode(fbdev->client, BLANK_ON);
571 bfin_disable_dma();
572 bfin_disable_ppi();
573 dma_desc_list(fbdev, DESTRUCT);
574 fbdev->open = 0;
575 return 0;
576}
577
578static int
579bfin_adv7393_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
580{
581
582 switch (var->bits_per_pixel) {
583 case 16:/* DIRECTCOLOUR, 64k */
584 var->red.offset = info->var.red.offset;
585 var->green.offset = info->var.green.offset;
586 var->blue.offset = info->var.blue.offset;
587 var->red.length = info->var.red.length;
588 var->green.length = info->var.green.length;
589 var->blue.length = info->var.blue.length;
590 var->transp.offset = 0;
591 var->transp.length = 0;
592 var->transp.msb_right = 0;
593 var->red.msb_right = 0;
594 var->green.msb_right = 0;
595 var->blue.msb_right = 0;
596 break;
597 default:
598 pr_debug("%s: depth not supported: %u BPP\n", __func__,
599 var->bits_per_pixel);
600 return -EINVAL;
601 }
602
603 if (info->var.xres != var->xres ||
604 info->var.yres != var->yres ||
605 info->var.xres_virtual != var->xres_virtual ||
606 info->var.yres_virtual != var->yres_virtual) {
607 pr_debug("%s: Resolution not supported: X%u x Y%u\n",
608 __func__, var->xres, var->yres);
609 return -EINVAL;
610 }
611
612 /*
613 * Memory limit
614 */
615
616 if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
617 pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
618 __func__, var->yres_virtual);
619 return -ENOMEM;
620 }
621
622 return 0;
623}
624
625static int
626bfin_adv7393_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
627{
628 int dy;
629 u32 dmaaddr;
630 struct adv7393fb_device *fbdev = to_adv7393fb_device(info);
631
632 if (!var || !info)
633 return -EINVAL;
634
635 if (var->xoffset - info->var.xoffset) {
636 /* No support for X panning for now! */
637 return -EINVAL;
638 }
639 dy = var->yoffset - info->var.yoffset;
640
641 if (dy) {
642 pr_debug("%s: Panning screen of %d lines\n", __func__, dy);
643
644 dmaaddr = fbdev->av1->start_addr;
645 dmaaddr += (info->fix.line_length * dy);
646 /* TODO: Wait for current frame to finished */
647
648 fbdev->av1->start_addr = (unsigned long)dmaaddr;
649 fbdev->av2->start_addr = (unsigned long)dmaaddr + fbdev->line_len;
650 }
651
652 return 0;
653
654}
655
656/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
657static int bfin_adv7393_fb_blank(int blank, struct fb_info *info)
658{
659 struct adv7393fb_device *fbdev = to_adv7393fb_device(info);
660
661 switch (blank) {
662
663 case VESA_NO_BLANKING:
664 /* Turn on panel */
665 adv7393_mode(fbdev->client, BLANK_OFF);
666 break;
667
668 case VESA_VSYNC_SUSPEND:
669 case VESA_HSYNC_SUSPEND:
670 case VESA_POWERDOWN:
671 /* Turn off panel */
672 adv7393_mode(fbdev->client, BLANK_ON);
673 break;
674
675 default:
676 return -EINVAL;
677 break;
678 }
679 return 0;
680}
681
682int bfin_adv7393_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
683{
684 if (nocursor)
685 return 0;
686 else
687 return -EINVAL; /* just to force soft_cursor() call */
688}
689
690static int bfin_adv7393_fb_setcolreg(u_int regno, u_int red, u_int green,
691 u_int blue, u_int transp,
692 struct fb_info *info)
693{
694 if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES)
695 return -EINVAL;
696
697 if (info->var.grayscale)
698 /* grayscale = 0.30*R + 0.59*G + 0.11*B */
699 red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
700
701 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
702 u32 value;
703 /* Place color in the pseudopalette */
704 if (regno > 16)
705 return -EINVAL;
706
707 red >>= (16 - info->var.red.length);
708 green >>= (16 - info->var.green.length);
709 blue >>= (16 - info->var.blue.length);
710
711 value = (red << info->var.red.offset) |
712 (green << info->var.green.offset)|
713 (blue << info->var.blue.offset);
714 value &= 0xFFFF;
715
716 ((u32 *) (info->pseudo_palette))[regno] = value;
717 }
718
719 return 0;
720}
721
722static int __devexit bfin_adv7393_fb_remove(struct i2c_client *client)
723{
724 struct adv7393fb_device *fbdev = i2c_get_clientdata(client);
725
726 adv7393_mode(client, POWER_DOWN);
727
728 if (fbdev->fb_mem)
729 dma_free_coherent(NULL, fbdev->fb_len, fbdev->fb_mem, fbdev->dma_handle);
730 free_dma(CH_PPI);
731 free_irq(IRQ_PPI_ERROR, fbdev);
732 unregister_framebuffer(&fbdev->info);
733 remove_proc_entry("driver/adv7393", NULL);
734 fb_dealloc_cmap(&fbdev->info.cmap);
735 kfree(fbdev->info.pseudo_palette);
736
737 if (ANOMALY_05000400)
738 gpio_free(P_IDENT(P_PPI0_FS3)); /* FS3 */
739 peripheral_free_list(ppi_pins);
740 kfree(fbdev);
741
742 return 0;
743}
744
745#ifdef CONFIG_PM
746static int bfin_adv7393_fb_suspend(struct device *dev)
747{
748 struct adv7393fb_device *fbdev = dev_get_drvdata(dev);
749
750 if (fbdev->open) {
751 bfin_disable_dma();
752 bfin_disable_ppi();
753 dma_desc_list(fbdev, DESTRUCT);
754 }
755 adv7393_mode(fbdev->client, POWER_DOWN);
756
757 return 0;
758}
759
760static int bfin_adv7393_fb_resume(struct device *dev)
761{
762 struct adv7393fb_device *fbdev = dev_get_drvdata(dev);
763
764 adv7393_mode(fbdev->client, POWER_ON);
765
766 if (fbdev->open) {
767 dma_desc_list(fbdev, BUILD);
768 bfin_config_ppi(fbdev);
769 bfin_config_dma(fbdev);
770 bfin_enable_ppi();
771 }
772
773 return 0;
774}
775
776static const struct dev_pm_ops bfin_adv7393_dev_pm_ops = {
777 .suspend = bfin_adv7393_fb_suspend,
778 .resume = bfin_adv7393_fb_resume,
779};
780#endif
781
782static const struct i2c_device_id bfin_adv7393_id[] = {
783 {DRIVER_NAME, 0},
784 {}
785};
786
787MODULE_DEVICE_TABLE(i2c, bfin_adv7393_id);
788
789static struct i2c_driver bfin_adv7393_fb_driver = {
790 .driver = {
791 .name = DRIVER_NAME,
792#ifdef CONFIG_PM
793 .pm = &bfin_adv7393_dev_pm_ops,
794#endif
795 },
796 .probe = bfin_adv7393_fb_probe,
797 .remove = __devexit_p(bfin_adv7393_fb_remove),
798 .id_table = bfin_adv7393_id,
799};
800
801static int __init bfin_adv7393_fb_driver_init(void)
802{
803#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
804 request_module("i2c-bfin-twi");
805#else
806 request_module("i2c-gpio");
807#endif
808
809 return i2c_add_driver(&bfin_adv7393_fb_driver);
810}
811module_init(bfin_adv7393_fb_driver_init);
812
813static void __exit bfin_adv7393_fb_driver_cleanup(void)
814{
815 i2c_del_driver(&bfin_adv7393_fb_driver);
816}
817module_exit(bfin_adv7393_fb_driver_cleanup);
818
819MODULE_LICENSE("GPL");
820MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
821MODULE_DESCRIPTION("Frame buffer driver for ADV7393/2 Video Encoder");
822
823module_param(mode, int, 0);
824MODULE_PARM_DESC(mode,
825 "Video Mode (0=NTSC,1=PAL,2=NTSC 640x480,3=PAL 640x480,4=NTSC YCbCr input,5=PAL YCbCr input)");
826
827module_param(mem, int, 0);
828MODULE_PARM_DESC(mem,
829 "Size of frame buffer memory 1=Single 2=Double Size (allows y-panning / frame stacking)");
830
831module_param(nocursor, int, 0644);
832MODULE_PARM_DESC(nocursor, "cursor enable/disable");
diff --git a/drivers/video/bfin_adv7393fb.h b/drivers/video/bfin_adv7393fb.h
new file mode 100644
index 000000000000..cd591b5152a5
--- /dev/null
+++ b/drivers/video/bfin_adv7393fb.h
@@ -0,0 +1,321 @@
1/*
2 * Frame buffer driver for ADV7393/2 video encoder
3 *
4 * Copyright 2006-2009 Analog Devices Inc.
5 * Licensed under the GPL-2 or late.
6 */
7
8#ifndef __BFIN_ADV7393FB_H__
9#define __BFIN_ADV7393FB_H__
10
11#define BFIN_LCD_NBR_PALETTE_ENTRIES 256
12
13#ifdef CONFIG_NTSC
14# define VMODE 0
15#endif
16#ifdef CONFIG_PAL
17# define VMODE 1
18#endif
19#ifdef CONFIG_NTSC_640x480
20# define VMODE 2
21#endif
22#ifdef CONFIG_PAL_640x480
23# define VMODE 3
24#endif
25#ifdef CONFIG_NTSC_YCBCR
26# define VMODE 4
27#endif
28#ifdef CONFIG_PAL_YCBCR
29# define VMODE 5
30#endif
31
32#ifndef VMODE
33# define VMODE 1
34#endif
35
36#ifdef CONFIG_ADV7393_2XMEM
37# define VMEM 2
38#else
39# define VMEM 1
40#endif
41
42#if defined(CONFIG_BF537) || defined(CONFIG_BF536) || defined(CONFIG_BF534)
43# define DMA_CFG_VAL 0x7935 /* Set Sync Bit */
44# define VB_DUMMY_MEMORY_SOURCE L1_DATA_B_START
45#else
46# define DMA_CFG_VAL 0x7915
47# define VB_DUMMY_MEMORY_SOURCE BOOT_ROM_START
48#endif
49
50enum {
51 DESTRUCT,
52 BUILD,
53};
54
55enum {
56 POWER_ON,
57 POWER_DOWN,
58 BLANK_ON,
59 BLANK_OFF,
60};
61
62#define DRIVER_NAME "bfin-adv7393"
63
64struct adv7393fb_modes {
65 const s8 name[25]; /* Full name */
66 u16 xres; /* Active Horizonzal Pixels */
67 u16 yres; /* Active Vertical Pixels */
68 u16 bpp;
69 u16 vmode;
70 u16 a_lines; /* Active Lines per Field */
71 u16 vb1_lines; /* Vertical Blanking Field 1 Lines */
72 u16 vb2_lines; /* Vertical Blanking Field 2 Lines */
73 u16 tot_lines; /* Total Lines per Frame */
74 u16 boeft_blank; /* Before Odd/Even Field Transition No. of Blank Pixels */
75 u16 aoeft_blank; /* After Odd/Even Field Transition No. of Blank Pixels */
76 const s8 *adv7393_i2c_initd;
77 u16 adv7393_i2c_initd_len;
78};
79
80static const u8 init_NTSC_TESTPATTERN[] = {
81 0x00, 0x1E, /* Power up all DACs and PLL */
82 0x01, 0x00, /* SD-Only Mode */
83 0x80, 0x10, /* SSAF Luma Filter Enabled, NTSC Mode */
84 0x82, 0xCB, /* Step control on, pixel data valid, pedestal on, PrPb SSAF on, CVBS/YC output */
85 0x84, 0x40, /* SD Color Bar Test Pattern Enabled, DAC 2 = Luma, DAC 3 = Chroma */
86};
87
88static const u8 init_NTSC[] = {
89 0x00, 0x1E, /* Power up all DACs and PLL */
90 0xC3, 0x26, /* Program RGB->YCrCb Color Space conversion matrix */
91 0xC5, 0x12, /* Program RGB->YCrCb Color Space conversion matrix */
92 0xC2, 0x4A, /* Program RGB->YCrCb Color Space conversion matrix */
93 0xC6, 0x5E, /* Program RGB->YCrCb Color Space conversion matrix */
94 0xBD, 0x19, /* Program RGB->YCrCb Color Space conversion matrix */
95 0xBF, 0x42, /* Program RGB->YCrCb Color Space conversion matrix */
96 0x8C, 0x1F, /* NTSC Subcarrier Frequency */
97 0x8D, 0x7C, /* NTSC Subcarrier Frequency */
98 0x8E, 0xF0, /* NTSC Subcarrier Frequency */
99 0x8F, 0x21, /* NTSC Subcarrier Frequency */
100 0x01, 0x00, /* SD-Only Mode */
101 0x80, 0x30, /* SSAF Luma Filter Enabled, NTSC Mode */
102 0x82, 0x8B, /* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
103 0x87, 0x80, /* SD Color Bar Test Pattern Enabled, DAC 2 = Luma, DAC 3 = Chroma */
104 0x86, 0x82,
105 0x8B, 0x11,
106 0x88, 0x20,
107 0x8A, 0x0d,
108};
109
110static const u8 init_PAL[] = {
111 0x00, 0x1E, /* Power up all DACs and PLL */
112 0xC3, 0x26, /* Program RGB->YCrCb Color Space conversion matrix */
113 0xC5, 0x12, /* Program RGB->YCrCb Color Space conversion matrix */
114 0xC2, 0x4A, /* Program RGB->YCrCb Color Space conversion matrix */
115 0xC6, 0x5E, /* Program RGB->YCrCb Color Space conversion matrix */
116 0xBD, 0x19, /* Program RGB->YCrCb Color Space conversion matrix */
117 0xBF, 0x42, /* Program RGB->YCrCb Color Space conversion matrix */
118 0x8C, 0xCB, /* PAL Subcarrier Frequency */
119 0x8D, 0x8A, /* PAL Subcarrier Frequency */
120 0x8E, 0x09, /* PAL Subcarrier Frequency */
121 0x8F, 0x2A, /* PAL Subcarrier Frequency */
122 0x01, 0x00, /* SD-Only Mode */
123 0x80, 0x11, /* SSAF Luma Filter Enabled, PAL Mode */
124 0x82, 0x8B, /* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
125 0x87, 0x80, /* SD Color Bar Test Pattern Enabled, DAC 2 = Luma, DAC 3 = Chroma */
126 0x86, 0x82,
127 0x8B, 0x11,
128 0x88, 0x20,
129 0x8A, 0x0d,
130};
131
132static const u8 init_NTSC_YCbCr[] = {
133 0x00, 0x1E, /* Power up all DACs and PLL */
134 0x8C, 0x1F, /* NTSC Subcarrier Frequency */
135 0x8D, 0x7C, /* NTSC Subcarrier Frequency */
136 0x8E, 0xF0, /* NTSC Subcarrier Frequency */
137 0x8F, 0x21, /* NTSC Subcarrier Frequency */
138 0x01, 0x00, /* SD-Only Mode */
139 0x80, 0x30, /* SSAF Luma Filter Enabled, NTSC Mode */
140 0x82, 0x8B, /* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
141 0x87, 0x00, /* DAC 2 = Luma, DAC 3 = Chroma */
142 0x86, 0x82,
143 0x8B, 0x11,
144 0x88, 0x08,
145 0x8A, 0x0d,
146};
147
148static const u8 init_PAL_YCbCr[] = {
149 0x00, 0x1E, /* Power up all DACs and PLL */
150 0x8C, 0xCB, /* PAL Subcarrier Frequency */
151 0x8D, 0x8A, /* PAL Subcarrier Frequency */
152 0x8E, 0x09, /* PAL Subcarrier Frequency */
153 0x8F, 0x2A, /* PAL Subcarrier Frequency */
154 0x01, 0x00, /* SD-Only Mode */
155 0x80, 0x11, /* SSAF Luma Filter Enabled, PAL Mode */
156 0x82, 0x8B, /* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
157 0x87, 0x00, /* DAC 2 = Luma, DAC 3 = Chroma */
158 0x86, 0x82,
159 0x8B, 0x11,
160 0x88, 0x08,
161 0x8A, 0x0d,
162};
163
164static struct adv7393fb_modes known_modes[] = {
165 /* NTSC 720x480 CRT */
166 {
167 .name = "NTSC 720x480",
168 .xres = 720,
169 .yres = 480,
170 .bpp = 16,
171 .vmode = FB_VMODE_INTERLACED,
172 .a_lines = 240,
173 .vb1_lines = 22,
174 .vb2_lines = 23,
175 .tot_lines = 525,
176 .boeft_blank = 16,
177 .aoeft_blank = 122,
178 .adv7393_i2c_initd = init_NTSC,
179 .adv7393_i2c_initd_len = sizeof(init_NTSC)
180 },
181 /* PAL 720x480 CRT */
182 {
183 .name = "PAL 720x576",
184 .xres = 720,
185 .yres = 576,
186 .bpp = 16,
187 .vmode = FB_VMODE_INTERLACED,
188 .a_lines = 288,
189 .vb1_lines = 24,
190 .vb2_lines = 25,
191 .tot_lines = 625,
192 .boeft_blank = 12,
193 .aoeft_blank = 132,
194 .adv7393_i2c_initd = init_PAL,
195 .adv7393_i2c_initd_len = sizeof(init_PAL)
196 },
197 /* NTSC 640x480 CRT Experimental */
198 {
199 .name = "NTSC 640x480",
200 .xres = 640,
201 .yres = 480,
202 .bpp = 16,
203 .vmode = FB_VMODE_INTERLACED,
204 .a_lines = 240,
205 .vb1_lines = 22,
206 .vb2_lines = 23,
207 .tot_lines = 525,
208 .boeft_blank = 16 + 40,
209 .aoeft_blank = 122 + 40,
210 .adv7393_i2c_initd = init_NTSC,
211 .adv7393_i2c_initd_len = sizeof(init_NTSC)
212 },
213 /* PAL 640x480 CRT Experimental */
214 {
215 .name = "PAL 640x480",
216 .xres = 640,
217 .yres = 480,
218 .bpp = 16,
219 .vmode = FB_VMODE_INTERLACED,
220 .a_lines = 288 - 20,
221 .vb1_lines = 24 + 20,
222 .vb2_lines = 25 + 20,
223 .tot_lines = 625,
224 .boeft_blank = 12 + 40,
225 .aoeft_blank = 132 + 40,
226 .adv7393_i2c_initd = init_PAL,
227 .adv7393_i2c_initd_len = sizeof(init_PAL)
228 },
229 /* NTSC 720x480 YCbCR */
230 {
231 .name = "NTSC 720x480 YCbCR",
232 .xres = 720,
233 .yres = 480,
234 .bpp = 16,
235 .vmode = FB_VMODE_INTERLACED,
236 .a_lines = 240,
237 .vb1_lines = 22,
238 .vb2_lines = 23,
239 .tot_lines = 525,
240 .boeft_blank = 16,
241 .aoeft_blank = 122,
242 .adv7393_i2c_initd = init_NTSC_YCbCr,
243 .adv7393_i2c_initd_len = sizeof(init_NTSC_YCbCr)
244 },
245 /* PAL 720x480 CRT */
246 {
247 .name = "PAL 720x576 YCbCR",
248 .xres = 720,
249 .yres = 576,
250 .bpp = 16,
251 .vmode = FB_VMODE_INTERLACED,
252 .a_lines = 288,
253 .vb1_lines = 24,
254 .vb2_lines = 25,
255 .tot_lines = 625,
256 .boeft_blank = 12,
257 .aoeft_blank = 132,
258 .adv7393_i2c_initd = init_PAL_YCbCr,
259 .adv7393_i2c_initd_len = sizeof(init_PAL_YCbCr)
260 }
261};
262
263struct adv7393fb_regs {
264
265};
266
267struct adv7393fb_device {
268 struct fb_info info; /* FB driver info record */
269
270 struct i2c_client *client;
271
272 struct dmasg *descriptor_list_head;
273 struct dmasg *vb1;
274 struct dmasg *av1;
275 struct dmasg *vb2;
276 struct dmasg *av2;
277
278 dma_addr_t dma_handle;
279
280 struct fb_info bfin_adv7393_fb;
281
282 struct adv7393fb_modes *modes;
283
284 struct adv7393fb_regs *regs; /* Registers memory map */
285 size_t regs_len;
286 size_t fb_len;
287 size_t line_len;
288 u16 open;
289 u16 *fb_mem; /* RGB Buffer */
290
291};
292
293#define to_adv7393fb_device(_info) \
294 (_info ? container_of(_info, struct adv7393fb_device, info) : NULL);
295
296static int bfin_adv7393_fb_open(struct fb_info *info, int user);
297static int bfin_adv7393_fb_release(struct fb_info *info, int user);
298static int bfin_adv7393_fb_check_var(struct fb_var_screeninfo *var,
299 struct fb_info *info);
300
301static int bfin_adv7393_fb_pan_display(struct fb_var_screeninfo *var,
302 struct fb_info *info);
303
304static int bfin_adv7393_fb_blank(int blank, struct fb_info *info);
305
306static void bfin_config_ppi(struct adv7393fb_device *fbdev);
307static int bfin_config_dma(struct adv7393fb_device *fbdev);
308static void bfin_disable_dma(void);
309static void bfin_enable_ppi(void);
310static void bfin_disable_ppi(void);
311
312static inline int adv7393_write(struct i2c_client *client, u8 reg, u8 value);
313static inline int adv7393_read(struct i2c_client *client, u8 reg);
314static int adv7393_write_block(struct i2c_client *client, const u8 *data,
315 unsigned int len);
316
317int bfin_adv7393_fb_cursor(struct fb_info *info, struct fb_cursor *cursor);
318static int bfin_adv7393_fb_setcolreg(u_int, u_int, u_int, u_int,
319 u_int, struct fb_info *info);
320
321#endif
diff --git a/drivers/video/broadsheetfb.c b/drivers/video/broadsheetfb.c
index ebda6876d3a9..377dde3d5bfc 100644
--- a/drivers/video/broadsheetfb.c
+++ b/drivers/video/broadsheetfb.c
@@ -1101,12 +1101,10 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev)
1101 1101
1102 videomemorysize = roundup((dpyw*dpyh), PAGE_SIZE); 1102 videomemorysize = roundup((dpyw*dpyh), PAGE_SIZE);
1103 1103
1104 videomemory = vmalloc(videomemorysize); 1104 videomemory = vzalloc(videomemorysize);
1105 if (!videomemory) 1105 if (!videomemory)
1106 goto err_fb_rel; 1106 goto err_fb_rel;
1107 1107
1108 memset(videomemory, 0, videomemorysize);
1109
1110 info->screen_base = (char *)videomemory; 1108 info->screen_base = (char *)videomemory;
1111 info->fbops = &broadsheetfb_ops; 1109 info->fbops = &broadsheetfb_ops;
1112 1110
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
index 4dc13467281d..7ba74cd4be61 100644
--- a/drivers/video/bw2.c
+++ b/drivers/video/bw2.c
@@ -273,7 +273,7 @@ static int __devinit bw2_do_default_mode(struct bw2_par *par,
273 return 0; 273 return 0;
274} 274}
275 275
276static int __devinit bw2_probe(struct platform_device *op, const struct of_device_id *match) 276static int __devinit bw2_probe(struct platform_device *op)
277{ 277{
278 struct device_node *dp = op->dev.of_node; 278 struct device_node *dp = op->dev.of_node;
279 struct fb_info *info; 279 struct fb_info *info;
@@ -375,7 +375,7 @@ static const struct of_device_id bw2_match[] = {
375}; 375};
376MODULE_DEVICE_TABLE(of, bw2_match); 376MODULE_DEVICE_TABLE(of, bw2_match);
377 377
378static struct of_platform_driver bw2_driver = { 378static struct platform_driver bw2_driver = {
379 .driver = { 379 .driver = {
380 .name = "bw2", 380 .name = "bw2",
381 .owner = THIS_MODULE, 381 .owner = THIS_MODULE,
@@ -390,12 +390,12 @@ static int __init bw2_init(void)
390 if (fb_get_options("bw2fb", NULL)) 390 if (fb_get_options("bw2fb", NULL))
391 return -ENODEV; 391 return -ENODEV;
392 392
393 return of_register_platform_driver(&bw2_driver); 393 return platform_driver_register(&bw2_driver);
394} 394}
395 395
396static void __exit bw2_exit(void) 396static void __exit bw2_exit(void)
397{ 397{
398 of_unregister_platform_driver(&bw2_driver); 398 platform_driver_unregister(&bw2_driver);
399} 399}
400 400
401module_init(bw2_init); 401module_init(bw2_init);
diff --git a/drivers/video/carminefb.c b/drivers/video/carminefb.c
index 6b19136aa181..caaa27d4a46a 100644
--- a/drivers/video/carminefb.c
+++ b/drivers/video/carminefb.c
@@ -654,7 +654,7 @@ static int __devinit carminefb_probe(struct pci_dev *dev,
654 printk(KERN_ERR "carminefb: Memory bar is only %d bytes, %d " 654 printk(KERN_ERR "carminefb: Memory bar is only %d bytes, %d "
655 "are required.", carminefb_fix.smem_len, 655 "are required.", carminefb_fix.smem_len,
656 CARMINE_TOTAL_DIPLAY_MEM); 656 CARMINE_TOTAL_DIPLAY_MEM);
657 goto err_free_reg_mmio; 657 goto err_unmap_vregs;
658 } 658 }
659 659
660 if (!request_mem_region(carminefb_fix.smem_start, 660 if (!request_mem_region(carminefb_fix.smem_start,
@@ -667,8 +667,6 @@ static int __devinit carminefb_probe(struct pci_dev *dev,
667 carminefb_fix.smem_len); 667 carminefb_fix.smem_len);
668 if (!hw->screen_mem) { 668 if (!hw->screen_mem) {
669 printk(KERN_ERR "carmine: Can't ioremap smem area.\n"); 669 printk(KERN_ERR "carmine: Can't ioremap smem area.\n");
670 release_mem_region(carminefb_fix.smem_start,
671 carminefb_fix.smem_len);
672 goto err_reg_smem; 670 goto err_reg_smem;
673 } 671 }
674 672
@@ -710,7 +708,7 @@ err_deinit_hw:
710err_unmap_screen: 708err_unmap_screen:
711 iounmap(hw->screen_mem); 709 iounmap(hw->screen_mem);
712err_reg_smem: 710err_reg_smem:
713 release_mem_region(carminefb_fix.mmio_start, carminefb_fix.mmio_len); 711 release_mem_region(carminefb_fix.smem_start, carminefb_fix.smem_len);
714err_unmap_vregs: 712err_unmap_vregs:
715 iounmap(hw->v_regs); 713 iounmap(hw->v_regs);
716err_free_reg_mmio: 714err_free_reg_mmio:
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c
index 24249535ac86..f18895006627 100644
--- a/drivers/video/cg14.c
+++ b/drivers/video/cg14.c
@@ -463,7 +463,7 @@ static void cg14_unmap_regs(struct platform_device *op, struct fb_info *info,
463 info->screen_base, info->fix.smem_len); 463 info->screen_base, info->fix.smem_len);
464} 464}
465 465
466static int __devinit cg14_probe(struct platform_device *op, const struct of_device_id *match) 466static int __devinit cg14_probe(struct platform_device *op)
467{ 467{
468 struct device_node *dp = op->dev.of_node; 468 struct device_node *dp = op->dev.of_node;
469 struct fb_info *info; 469 struct fb_info *info;
@@ -565,6 +565,7 @@ out_dealloc_cmap:
565 565
566out_unmap_regs: 566out_unmap_regs:
567 cg14_unmap_regs(op, info, par); 567 cg14_unmap_regs(op, info, par);
568 framebuffer_release(info);
568 569
569out_err: 570out_err:
570 return err; 571 return err;
@@ -595,7 +596,7 @@ static const struct of_device_id cg14_match[] = {
595}; 596};
596MODULE_DEVICE_TABLE(of, cg14_match); 597MODULE_DEVICE_TABLE(of, cg14_match);
597 598
598static struct of_platform_driver cg14_driver = { 599static struct platform_driver cg14_driver = {
599 .driver = { 600 .driver = {
600 .name = "cg14", 601 .name = "cg14",
601 .owner = THIS_MODULE, 602 .owner = THIS_MODULE,
@@ -610,12 +611,12 @@ static int __init cg14_init(void)
610 if (fb_get_options("cg14fb", NULL)) 611 if (fb_get_options("cg14fb", NULL))
611 return -ENODEV; 612 return -ENODEV;
612 613
613 return of_register_platform_driver(&cg14_driver); 614 return platform_driver_register(&cg14_driver);
614} 615}
615 616
616static void __exit cg14_exit(void) 617static void __exit cg14_exit(void)
617{ 618{
618 of_unregister_platform_driver(&cg14_driver); 619 platform_driver_unregister(&cg14_driver);
619} 620}
620 621
621module_init(cg14_init); 622module_init(cg14_init);
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c
index 09c0c3c42482..f927a7b1a8d4 100644
--- a/drivers/video/cg3.c
+++ b/drivers/video/cg3.c
@@ -346,8 +346,7 @@ static int __devinit cg3_do_default_mode(struct cg3_par *par)
346 return 0; 346 return 0;
347} 347}
348 348
349static int __devinit cg3_probe(struct platform_device *op, 349static int __devinit cg3_probe(struct platform_device *op)
350 const struct of_device_id *match)
351{ 350{
352 struct device_node *dp = op->dev.of_node; 351 struct device_node *dp = op->dev.of_node;
353 struct fb_info *info; 352 struct fb_info *info;
@@ -462,7 +461,7 @@ static const struct of_device_id cg3_match[] = {
462}; 461};
463MODULE_DEVICE_TABLE(of, cg3_match); 462MODULE_DEVICE_TABLE(of, cg3_match);
464 463
465static struct of_platform_driver cg3_driver = { 464static struct platform_driver cg3_driver = {
466 .driver = { 465 .driver = {
467 .name = "cg3", 466 .name = "cg3",
468 .owner = THIS_MODULE, 467 .owner = THIS_MODULE,
@@ -477,12 +476,12 @@ static int __init cg3_init(void)
477 if (fb_get_options("cg3fb", NULL)) 476 if (fb_get_options("cg3fb", NULL))
478 return -ENODEV; 477 return -ENODEV;
479 478
480 return of_register_platform_driver(&cg3_driver); 479 return platform_driver_register(&cg3_driver);
481} 480}
482 481
483static void __exit cg3_exit(void) 482static void __exit cg3_exit(void)
484{ 483{
485 of_unregister_platform_driver(&cg3_driver); 484 platform_driver_unregister(&cg3_driver);
486} 485}
487 486
488module_init(cg3_init); 487module_init(cg3_init);
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c
index 2b5a97058b08..179e96cdb323 100644
--- a/drivers/video/cg6.c
+++ b/drivers/video/cg6.c
@@ -737,8 +737,7 @@ static void cg6_unmap_regs(struct platform_device *op, struct fb_info *info,
737 info->fix.smem_len); 737 info->fix.smem_len);
738} 738}
739 739
740static int __devinit cg6_probe(struct platform_device *op, 740static int __devinit cg6_probe(struct platform_device *op)
741 const struct of_device_id *match)
742{ 741{
743 struct device_node *dp = op->dev.of_node; 742 struct device_node *dp = op->dev.of_node;
744 struct fb_info *info; 743 struct fb_info *info;
@@ -822,6 +821,7 @@ out_dealloc_cmap:
822 821
823out_unmap_regs: 822out_unmap_regs:
824 cg6_unmap_regs(op, info, par); 823 cg6_unmap_regs(op, info, par);
824 framebuffer_release(info);
825 825
826out_err: 826out_err:
827 return err; 827 return err;
@@ -855,7 +855,7 @@ static const struct of_device_id cg6_match[] = {
855}; 855};
856MODULE_DEVICE_TABLE(of, cg6_match); 856MODULE_DEVICE_TABLE(of, cg6_match);
857 857
858static struct of_platform_driver cg6_driver = { 858static struct platform_driver cg6_driver = {
859 .driver = { 859 .driver = {
860 .name = "cg6", 860 .name = "cg6",
861 .owner = THIS_MODULE, 861 .owner = THIS_MODULE,
@@ -870,12 +870,12 @@ static int __init cg6_init(void)
870 if (fb_get_options("cg6fb", NULL)) 870 if (fb_get_options("cg6fb", NULL))
871 return -ENODEV; 871 return -ENODEV;
872 872
873 return of_register_platform_driver(&cg6_driver); 873 return platform_driver_register(&cg6_driver);
874} 874}
875 875
876static void __exit cg6_exit(void) 876static void __exit cg6_exit(void)
877{ 877{
878 of_unregister_platform_driver(&cg6_driver); 878 platform_driver_unregister(&cg6_driver);
879} 879}
880 880
881module_init(cg6_init); 881module_init(cg6_init);
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index d637e1f53172..cff742abdc5d 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -460,10 +460,10 @@ static int chipsfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
460 if (!(state.event & PM_EVENT_SLEEP)) 460 if (!(state.event & PM_EVENT_SLEEP))
461 goto done; 461 goto done;
462 462
463 acquire_console_sem(); 463 console_lock();
464 chipsfb_blank(1, p); 464 chipsfb_blank(1, p);
465 fb_set_suspend(p, 1); 465 fb_set_suspend(p, 1);
466 release_console_sem(); 466 console_unlock();
467 done: 467 done:
468 pdev->dev.power.power_state = state; 468 pdev->dev.power.power_state = state;
469 return 0; 469 return 0;
@@ -473,10 +473,10 @@ static int chipsfb_pci_resume(struct pci_dev *pdev)
473{ 473{
474 struct fb_info *p = pci_get_drvdata(pdev); 474 struct fb_info *p = pci_get_drvdata(pdev);
475 475
476 acquire_console_sem(); 476 console_lock();
477 fb_set_suspend(p, 0); 477 fb_set_suspend(p, 0);
478 chipsfb_blank(0, p); 478 chipsfb_blank(0, p);
479 release_console_sem(); 479 console_unlock();
480 480
481 pdev->dev.power.power_state = PMSG_ON; 481 pdev->dev.power.power_state = PMSG_ON;
482 return 0; 482 return 0;
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 5a35f22372b9..2209e354f531 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -5,7 +5,7 @@
5menu "Console display driver support" 5menu "Console display driver support"
6 6
7config VGA_CONSOLE 7config VGA_CONSOLE
8 bool "VGA text console" if EMBEDDED || !X86 8 bool "VGA text console" if EXPERT || !X86
9 depends on !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !SUPERH && !BLACKFIN && !AVR32 && !MN10300 && (!ARM || ARCH_FOOTBRIDGE || ARCH_INTEGRATOR || ARCH_NETWINDER) 9 depends on !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !SUPERH && !BLACKFIN && !AVR32 && !MN10300 && (!ARM || ARCH_FOOTBRIDGE || ARCH_INTEGRATOR || ARCH_NETWINDER)
10 default y 10 default y
11 help 11 help
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 7ccc967831f0..8745637e4b7e 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -370,29 +370,27 @@ static void fb_flashcursor(struct work_struct *work)
370{ 370{
371 struct fb_info *info = container_of(work, struct fb_info, queue); 371 struct fb_info *info = container_of(work, struct fb_info, queue);
372 struct fbcon_ops *ops = info->fbcon_par; 372 struct fbcon_ops *ops = info->fbcon_par;
373 struct display *p;
374 struct vc_data *vc = NULL; 373 struct vc_data *vc = NULL;
375 int c; 374 int c;
376 int mode; 375 int mode;
377 376
378 acquire_console_sem(); 377 console_lock();
379 if (ops && ops->currcon != -1) 378 if (ops && ops->currcon != -1)
380 vc = vc_cons[ops->currcon].d; 379 vc = vc_cons[ops->currcon].d;
381 380
382 if (!vc || !CON_IS_VISIBLE(vc) || 381 if (!vc || !CON_IS_VISIBLE(vc) ||
383 registered_fb[con2fb_map[vc->vc_num]] != info || 382 registered_fb[con2fb_map[vc->vc_num]] != info ||
384 vc->vc_deccm != 1) { 383 vc->vc_deccm != 1) {
385 release_console_sem(); 384 console_unlock();
386 return; 385 return;
387 } 386 }
388 387
389 p = &fb_display[vc->vc_num];
390 c = scr_readw((u16 *) vc->vc_pos); 388 c = scr_readw((u16 *) vc->vc_pos);
391 mode = (!ops->cursor_flash || ops->cursor_state.enable) ? 389 mode = (!ops->cursor_flash || ops->cursor_state.enable) ?
392 CM_ERASE : CM_DRAW; 390 CM_ERASE : CM_DRAW;
393 ops->cursor(vc, info, mode, softback_lines, get_color(vc, info, c, 1), 391 ops->cursor(vc, info, mode, softback_lines, get_color(vc, info, c, 1),
394 get_color(vc, info, c, 0)); 392 get_color(vc, info, c, 0));
395 release_console_sem(); 393 console_unlock();
396} 394}
397 395
398static void cursor_timer_handler(unsigned long dev_addr) 396static void cursor_timer_handler(unsigned long dev_addr)
@@ -823,10 +821,10 @@ static int set_con2fb_map(int unit, int newidx, int user)
823 if (oldidx == newidx) 821 if (oldidx == newidx)
824 return 0; 822 return 0;
825 823
826 if (!info || fbcon_has_exited) 824 if (!info)
827 return -EINVAL; 825 return -EINVAL;
828 826
829 if (!err && !search_for_mapped_con()) { 827 if (!search_for_mapped_con() || !con_is_bound(&fb_con)) {
830 info_idx = newidx; 828 info_idx = newidx;
831 return fbcon_takeover(0); 829 return fbcon_takeover(0);
832 } 830 }
@@ -836,7 +834,7 @@ static int set_con2fb_map(int unit, int newidx, int user)
836 834
837 found = search_fb_in_map(newidx); 835 found = search_fb_in_map(newidx);
838 836
839 acquire_console_sem(); 837 console_lock();
840 con2fb_map[unit] = newidx; 838 con2fb_map[unit] = newidx;
841 if (!err && !found) 839 if (!err && !found)
842 err = con2fb_acquire_newinfo(vc, info, unit, oldidx); 840 err = con2fb_acquire_newinfo(vc, info, unit, oldidx);
@@ -863,7 +861,7 @@ static int set_con2fb_map(int unit, int newidx, int user)
863 if (!search_fb_in_map(info_idx)) 861 if (!search_fb_in_map(info_idx))
864 info_idx = newidx; 862 info_idx = newidx;
865 863
866 release_console_sem(); 864 console_unlock();
867 return err; 865 return err;
868} 866}
869 867
@@ -3321,7 +3319,7 @@ static ssize_t store_rotate(struct device *device,
3321 if (fbcon_has_exited) 3319 if (fbcon_has_exited)
3322 return count; 3320 return count;
3323 3321
3324 acquire_console_sem(); 3322 console_lock();
3325 idx = con2fb_map[fg_console]; 3323 idx = con2fb_map[fg_console];
3326 3324
3327 if (idx == -1 || registered_fb[idx] == NULL) 3325 if (idx == -1 || registered_fb[idx] == NULL)
@@ -3331,7 +3329,7 @@ static ssize_t store_rotate(struct device *device,
3331 rotate = simple_strtoul(buf, last, 0); 3329 rotate = simple_strtoul(buf, last, 0);
3332 fbcon_rotate(info, rotate); 3330 fbcon_rotate(info, rotate);
3333err: 3331err:
3334 release_console_sem(); 3332 console_unlock();
3335 return count; 3333 return count;
3336} 3334}
3337 3335
@@ -3346,7 +3344,7 @@ static ssize_t store_rotate_all(struct device *device,
3346 if (fbcon_has_exited) 3344 if (fbcon_has_exited)
3347 return count; 3345 return count;
3348 3346
3349 acquire_console_sem(); 3347 console_lock();
3350 idx = con2fb_map[fg_console]; 3348 idx = con2fb_map[fg_console];
3351 3349
3352 if (idx == -1 || registered_fb[idx] == NULL) 3350 if (idx == -1 || registered_fb[idx] == NULL)
@@ -3356,7 +3354,7 @@ static ssize_t store_rotate_all(struct device *device,
3356 rotate = simple_strtoul(buf, last, 0); 3354 rotate = simple_strtoul(buf, last, 0);
3357 fbcon_rotate_all(info, rotate); 3355 fbcon_rotate_all(info, rotate);
3358err: 3356err:
3359 release_console_sem(); 3357 console_unlock();
3360 return count; 3358 return count;
3361} 3359}
3362 3360
@@ -3369,7 +3367,7 @@ static ssize_t show_rotate(struct device *device,
3369 if (fbcon_has_exited) 3367 if (fbcon_has_exited)
3370 return 0; 3368 return 0;
3371 3369
3372 acquire_console_sem(); 3370 console_lock();
3373 idx = con2fb_map[fg_console]; 3371 idx = con2fb_map[fg_console];
3374 3372
3375 if (idx == -1 || registered_fb[idx] == NULL) 3373 if (idx == -1 || registered_fb[idx] == NULL)
@@ -3378,7 +3376,7 @@ static ssize_t show_rotate(struct device *device,
3378 info = registered_fb[idx]; 3376 info = registered_fb[idx];
3379 rotate = fbcon_get_rotate(info); 3377 rotate = fbcon_get_rotate(info);
3380err: 3378err:
3381 release_console_sem(); 3379 console_unlock();
3382 return snprintf(buf, PAGE_SIZE, "%d\n", rotate); 3380 return snprintf(buf, PAGE_SIZE, "%d\n", rotate);
3383} 3381}
3384 3382
@@ -3392,7 +3390,7 @@ static ssize_t show_cursor_blink(struct device *device,
3392 if (fbcon_has_exited) 3390 if (fbcon_has_exited)
3393 return 0; 3391 return 0;
3394 3392
3395 acquire_console_sem(); 3393 console_lock();
3396 idx = con2fb_map[fg_console]; 3394 idx = con2fb_map[fg_console];
3397 3395
3398 if (idx == -1 || registered_fb[idx] == NULL) 3396 if (idx == -1 || registered_fb[idx] == NULL)
@@ -3406,7 +3404,7 @@ static ssize_t show_cursor_blink(struct device *device,
3406 3404
3407 blink = (ops->flags & FBCON_FLAGS_CURSOR_TIMER) ? 1 : 0; 3405 blink = (ops->flags & FBCON_FLAGS_CURSOR_TIMER) ? 1 : 0;
3408err: 3406err:
3409 release_console_sem(); 3407 console_unlock();
3410 return snprintf(buf, PAGE_SIZE, "%d\n", blink); 3408 return snprintf(buf, PAGE_SIZE, "%d\n", blink);
3411} 3409}
3412 3410
@@ -3421,7 +3419,7 @@ static ssize_t store_cursor_blink(struct device *device,
3421 if (fbcon_has_exited) 3419 if (fbcon_has_exited)
3422 return count; 3420 return count;
3423 3421
3424 acquire_console_sem(); 3422 console_lock();
3425 idx = con2fb_map[fg_console]; 3423 idx = con2fb_map[fg_console];
3426 3424
3427 if (idx == -1 || registered_fb[idx] == NULL) 3425 if (idx == -1 || registered_fb[idx] == NULL)
@@ -3443,7 +3441,7 @@ static ssize_t store_cursor_blink(struct device *device,
3443 } 3441 }
3444 3442
3445err: 3443err:
3446 release_console_sem(); 3444 console_unlock();
3447 return count; 3445 return count;
3448} 3446}
3449 3447
@@ -3482,7 +3480,7 @@ static void fbcon_start(void)
3482 if (num_registered_fb) { 3480 if (num_registered_fb) {
3483 int i; 3481 int i;
3484 3482
3485 acquire_console_sem(); 3483 console_lock();
3486 3484
3487 for (i = 0; i < FB_MAX; i++) { 3485 for (i = 0; i < FB_MAX; i++) {
3488 if (registered_fb[i] != NULL) { 3486 if (registered_fb[i] != NULL) {
@@ -3491,7 +3489,7 @@ static void fbcon_start(void)
3491 } 3489 }
3492 } 3490 }
3493 3491
3494 release_console_sem(); 3492 console_unlock();
3495 fbcon_takeover(0); 3493 fbcon_takeover(0);
3496 } 3494 }
3497} 3495}
@@ -3552,7 +3550,7 @@ static int __init fb_console_init(void)
3552{ 3550{
3553 int i; 3551 int i;
3554 3552
3555 acquire_console_sem(); 3553 console_lock();
3556 fb_register_client(&fbcon_event_notifier); 3554 fb_register_client(&fbcon_event_notifier);
3557 fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), NULL, 3555 fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), NULL,
3558 "fbcon"); 3556 "fbcon");
@@ -3568,7 +3566,7 @@ static int __init fb_console_init(void)
3568 for (i = 0; i < MAX_NR_CONSOLES; i++) 3566 for (i = 0; i < MAX_NR_CONSOLES; i++)
3569 con2fb_map[i] = -1; 3567 con2fb_map[i] = -1;
3570 3568
3571 release_console_sem(); 3569 console_unlock();
3572 fbcon_start(); 3570 fbcon_start();
3573 return 0; 3571 return 0;
3574} 3572}
@@ -3591,12 +3589,12 @@ static void __exit fbcon_deinit_device(void)
3591 3589
3592static void __exit fb_console_exit(void) 3590static void __exit fb_console_exit(void)
3593{ 3591{
3594 acquire_console_sem(); 3592 console_lock();
3595 fb_unregister_client(&fbcon_event_notifier); 3593 fb_unregister_client(&fbcon_event_notifier);
3596 fbcon_deinit_device(); 3594 fbcon_deinit_device();
3597 device_destroy(fb_class, MKDEV(0, 0)); 3595 device_destroy(fb_class, MKDEV(0, 0));
3598 fbcon_exit(); 3596 fbcon_exit();
3599 release_console_sem(); 3597 console_unlock();
3600 unregister_con_driver(&fb_con); 3598 unregister_con_driver(&fb_con);
3601} 3599}
3602 3600
diff --git a/drivers/video/console/font_mini_4x6.c b/drivers/video/console/font_mini_4x6.c
index a19a7f33133e..fa6e698e63c4 100644
--- a/drivers/video/console/font_mini_4x6.c
+++ b/drivers/video/console/font_mini_4x6.c
@@ -1,5 +1,5 @@
1 1
2/* Hand composed "Miniscule" 4x6 font, with binary data generated using 2/* Hand composed "Minuscule" 4x6 font, with binary data generated using
3 * Perl stub. 3 * Perl stub.
4 * 4 *
5 * Use 'perl -x mini_4x6.c < mini_4x6.c > new_version.c' to regenerate 5 * Use 'perl -x mini_4x6.c < mini_4x6.c > new_version.c' to regenerate
diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
index 3772433c49d1..93317b5b8740 100644
--- a/drivers/video/console/newport_con.c
+++ b/drivers/video/console/newport_con.c
@@ -6,7 +6,7 @@
6 * 6 *
7 * This driver is based on sgicons.c and cons_newport. 7 * This driver is based on sgicons.c and cons_newport.
8 * 8 *
9 * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) 9 * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
10 * Copyright (C) 1997 Miguel de Icaza (miguel@nuclecu.unam.mx) 10 * Copyright (C) 1997 Miguel de Icaza (miguel@nuclecu.unam.mx)
11 */ 11 */
12#include <linux/init.h> 12#include <linux/init.h>
diff --git a/drivers/video/console/tileblit.c b/drivers/video/console/tileblit.c
index 0056a41e5c35..15e8e1a89c45 100644
--- a/drivers/video/console/tileblit.c
+++ b/drivers/video/console/tileblit.c
@@ -83,7 +83,7 @@ static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode,
83 int softback_lines, int fg, int bg) 83 int softback_lines, int fg, int bg)
84{ 84{
85 struct fb_tilecursor cursor; 85 struct fb_tilecursor cursor;
86 int use_sw = (vc->vc_cursor_type & 0x01); 86 int use_sw = (vc->vc_cursor_type & 0x10);
87 87
88 cursor.sx = vc->vc_x; 88 cursor.sx = vc->vc_x;
89 cursor.sy = vc->vc_y; 89 cursor.sy = vc->vc_y;
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 54e32c513610..915fd74da7a2 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -47,7 +47,6 @@
47#include <linux/ioport.h> 47#include <linux/ioport.h>
48#include <linux/init.h> 48#include <linux/init.h>
49#include <linux/screen_info.h> 49#include <linux/screen_info.h>
50#include <linux/smp_lock.h>
51#include <video/vga.h> 50#include <video/vga.h>
52#include <asm/io.h> 51#include <asm/io.h>
53 52
@@ -203,11 +202,7 @@ static void vgacon_scrollback_init(int pitch)
203 } 202 }
204} 203}
205 204
206/* 205static void vgacon_scrollback_startup(void)
207 * Called only duing init so call of alloc_bootmen is ok.
208 * Marked __init_refok to silence modpost.
209 */
210static void __init_refok vgacon_scrollback_startup(void)
211{ 206{
212 vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, GFP_NOWAIT); 207 vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, GFP_NOWAIT);
213 vgacon_scrollback_init(vga_video_num_columns * 2); 208 vgacon_scrollback_init(vga_video_num_columns * 2);
@@ -376,7 +371,8 @@ static const char *vgacon_startup(void)
376 u16 saved1, saved2; 371 u16 saved1, saved2;
377 volatile u16 *p; 372 volatile u16 *p;
378 373
379 if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB) { 374 if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB ||
375 screen_info.orig_video_isVGA == VIDEO_TYPE_EFI) {
380 no_vga: 376 no_vga:
381#ifdef CONFIG_DUMMY_CONSOLE 377#ifdef CONFIG_DUMMY_CONSOLE
382 conswitchp = &dummy_con; 378 conswitchp = &dummy_con;
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index 0c1afd13ddd3..850380795b05 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -47,6 +47,8 @@
47#include <linux/pci.h> 47#include <linux/pci.h>
48#include <linux/init.h> 48#include <linux/init.h>
49#include <linux/io.h> 49#include <linux/io.h>
50#include <linux/i2c.h>
51#include <linux/i2c-algo-bit.h>
50 52
51#include <asm/pgtable.h> 53#include <asm/pgtable.h>
52#include <asm/system.h> 54#include <asm/system.h>
@@ -61,10 +63,10 @@ struct cfb_info {
61 struct fb_info fb; 63 struct fb_info fb;
62 struct display_switch *dispsw; 64 struct display_switch *dispsw;
63 struct display *display; 65 struct display *display;
64 struct pci_dev *dev;
65 unsigned char __iomem *region; 66 unsigned char __iomem *region;
66 unsigned char __iomem *regs; 67 unsigned char __iomem *regs;
67 u_int id; 68 u_int id;
69 u_int irq;
68 int func_use_count; 70 int func_use_count;
69 u_long ref_ps; 71 u_long ref_ps;
70 72
@@ -88,6 +90,19 @@ struct cfb_info {
88 u_char ramdac_powerdown; 90 u_char ramdac_powerdown;
89 91
90 u32 pseudo_palette[16]; 92 u32 pseudo_palette[16];
93
94 spinlock_t reg_b0_lock;
95
96#ifdef CONFIG_FB_CYBER2000_DDC
97 bool ddc_registered;
98 struct i2c_adapter ddc_adapter;
99 struct i2c_algo_bit_data ddc_algo;
100#endif
101
102#ifdef CONFIG_FB_CYBER2000_I2C
103 struct i2c_adapter i2c_adapter;
104 struct i2c_algo_bit_data i2c_algo;
105#endif
91}; 106};
92 107
93static char *default_font = "Acorn8x8"; 108static char *default_font = "Acorn8x8";
@@ -494,6 +509,7 @@ static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
494 cyber2000_attrw(0x14, 0x00, cfb); 509 cyber2000_attrw(0x14, 0x00, cfb);
495 510
496 /* PLL registers */ 511 /* PLL registers */
512 spin_lock(&cfb->reg_b0_lock);
497 cyber2000_grphw(EXT_DCLK_MULT, hw->clock_mult, cfb); 513 cyber2000_grphw(EXT_DCLK_MULT, hw->clock_mult, cfb);
498 cyber2000_grphw(EXT_DCLK_DIV, hw->clock_div, cfb); 514 cyber2000_grphw(EXT_DCLK_DIV, hw->clock_div, cfb);
499 cyber2000_grphw(EXT_MCLK_MULT, cfb->mclk_mult, cfb); 515 cyber2000_grphw(EXT_MCLK_MULT, cfb->mclk_mult, cfb);
@@ -501,6 +517,7 @@ static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
501 cyber2000_grphw(0x90, 0x01, cfb); 517 cyber2000_grphw(0x90, 0x01, cfb);
502 cyber2000_grphw(0xb9, 0x80, cfb); 518 cyber2000_grphw(0xb9, 0x80, cfb);
503 cyber2000_grphw(0xb9, 0x00, cfb); 519 cyber2000_grphw(0xb9, 0x00, cfb);
520 spin_unlock(&cfb->reg_b0_lock);
504 521
505 cfb->ramdac_ctrl = hw->ramdac; 522 cfb->ramdac_ctrl = hw->ramdac;
506 cyber2000fb_write_ramdac_ctrl(cfb); 523 cyber2000fb_write_ramdac_ctrl(cfb);
@@ -681,9 +698,9 @@ cyber2000fb_decode_clock(struct par_info *hw, struct cfb_info *cfb,
681 * pll_ps_calc = best_div1 / (ref_ps * best_mult) 698 * pll_ps_calc = best_div1 / (ref_ps * best_mult)
682 */ 699 */
683 best_diff = 0x7fffffff; 700 best_diff = 0x7fffffff;
684 best_mult = 32; 701 best_mult = 2;
685 best_div1 = 255; 702 best_div1 = 32;
686 for (t_div1 = 32; t_div1 > 1; t_div1 -= 1) { 703 for (t_div1 = 2; t_div1 < 32; t_div1 += 1) {
687 u_int rr, t_mult, t_pll_ps; 704 u_int rr, t_mult, t_pll_ps;
688 int diff; 705 int diff;
689 706
@@ -1105,24 +1122,22 @@ void cyber2000fb_disable_extregs(struct cfb_info *cfb)
1105} 1122}
1106EXPORT_SYMBOL(cyber2000fb_disable_extregs); 1123EXPORT_SYMBOL(cyber2000fb_disable_extregs);
1107 1124
1108void cyber2000fb_get_fb_var(struct cfb_info *cfb, struct fb_var_screeninfo *var)
1109{
1110 memcpy(var, &cfb->fb.var, sizeof(struct fb_var_screeninfo));
1111}
1112EXPORT_SYMBOL(cyber2000fb_get_fb_var);
1113
1114/* 1125/*
1115 * Attach a capture/tv driver to the core CyberX0X0 driver. 1126 * Attach a capture/tv driver to the core CyberX0X0 driver.
1116 */ 1127 */
1117int cyber2000fb_attach(struct cyberpro_info *info, int idx) 1128int cyber2000fb_attach(struct cyberpro_info *info, int idx)
1118{ 1129{
1119 if (int_cfb_info != NULL) { 1130 if (int_cfb_info != NULL) {
1120 info->dev = int_cfb_info->dev; 1131 info->dev = int_cfb_info->fb.device;
1132#ifdef CONFIG_FB_CYBER2000_I2C
1133 info->i2c = &int_cfb_info->i2c_adapter;
1134#else
1135 info->i2c = NULL;
1136#endif
1121 info->regs = int_cfb_info->regs; 1137 info->regs = int_cfb_info->regs;
1138 info->irq = int_cfb_info->irq;
1122 info->fb = int_cfb_info->fb.screen_base; 1139 info->fb = int_cfb_info->fb.screen_base;
1123 info->fb_size = int_cfb_info->fb.fix.smem_len; 1140 info->fb_size = int_cfb_info->fb.fix.smem_len;
1124 info->enable_extregs = cyber2000fb_enable_extregs;
1125 info->disable_extregs = cyber2000fb_disable_extregs;
1126 info->info = int_cfb_info; 1141 info->info = int_cfb_info;
1127 1142
1128 strlcpy(info->dev_name, int_cfb_info->fb.fix.id, 1143 strlcpy(info->dev_name, int_cfb_info->fb.fix.id,
@@ -1141,6 +1156,183 @@ void cyber2000fb_detach(int idx)
1141} 1156}
1142EXPORT_SYMBOL(cyber2000fb_detach); 1157EXPORT_SYMBOL(cyber2000fb_detach);
1143 1158
1159#ifdef CONFIG_FB_CYBER2000_DDC
1160
1161#define DDC_REG 0xb0
1162#define DDC_SCL_OUT (1 << 0)
1163#define DDC_SDA_OUT (1 << 4)
1164#define DDC_SCL_IN (1 << 2)
1165#define DDC_SDA_IN (1 << 6)
1166
1167static void cyber2000fb_enable_ddc(struct cfb_info *cfb)
1168{
1169 spin_lock(&cfb->reg_b0_lock);
1170 cyber2000fb_writew(0x1bf, 0x3ce, cfb);
1171}
1172
1173static void cyber2000fb_disable_ddc(struct cfb_info *cfb)
1174{
1175 cyber2000fb_writew(0x0bf, 0x3ce, cfb);
1176 spin_unlock(&cfb->reg_b0_lock);
1177}
1178
1179
1180static void cyber2000fb_ddc_setscl(void *data, int val)
1181{
1182 struct cfb_info *cfb = data;
1183 unsigned char reg;
1184
1185 cyber2000fb_enable_ddc(cfb);
1186 reg = cyber2000_grphr(DDC_REG, cfb);
1187 if (!val) /* bit is inverted */
1188 reg |= DDC_SCL_OUT;
1189 else
1190 reg &= ~DDC_SCL_OUT;
1191 cyber2000_grphw(DDC_REG, reg, cfb);
1192 cyber2000fb_disable_ddc(cfb);
1193}
1194
1195static void cyber2000fb_ddc_setsda(void *data, int val)
1196{
1197 struct cfb_info *cfb = data;
1198 unsigned char reg;
1199
1200 cyber2000fb_enable_ddc(cfb);
1201 reg = cyber2000_grphr(DDC_REG, cfb);
1202 if (!val) /* bit is inverted */
1203 reg |= DDC_SDA_OUT;
1204 else
1205 reg &= ~DDC_SDA_OUT;
1206 cyber2000_grphw(DDC_REG, reg, cfb);
1207 cyber2000fb_disable_ddc(cfb);
1208}
1209
1210static int cyber2000fb_ddc_getscl(void *data)
1211{
1212 struct cfb_info *cfb = data;
1213 int retval;
1214
1215 cyber2000fb_enable_ddc(cfb);
1216 retval = !!(cyber2000_grphr(DDC_REG, cfb) & DDC_SCL_IN);
1217 cyber2000fb_disable_ddc(cfb);
1218
1219 return retval;
1220}
1221
1222static int cyber2000fb_ddc_getsda(void *data)
1223{
1224 struct cfb_info *cfb = data;
1225 int retval;
1226
1227 cyber2000fb_enable_ddc(cfb);
1228 retval = !!(cyber2000_grphr(DDC_REG, cfb) & DDC_SDA_IN);
1229 cyber2000fb_disable_ddc(cfb);
1230
1231 return retval;
1232}
1233
1234static int __devinit cyber2000fb_setup_ddc_bus(struct cfb_info *cfb)
1235{
1236 strlcpy(cfb->ddc_adapter.name, cfb->fb.fix.id,
1237 sizeof(cfb->ddc_adapter.name));
1238 cfb->ddc_adapter.owner = THIS_MODULE;
1239 cfb->ddc_adapter.class = I2C_CLASS_DDC;
1240 cfb->ddc_adapter.algo_data = &cfb->ddc_algo;
1241 cfb->ddc_adapter.dev.parent = cfb->fb.device;
1242 cfb->ddc_algo.setsda = cyber2000fb_ddc_setsda;
1243 cfb->ddc_algo.setscl = cyber2000fb_ddc_setscl;
1244 cfb->ddc_algo.getsda = cyber2000fb_ddc_getsda;
1245 cfb->ddc_algo.getscl = cyber2000fb_ddc_getscl;
1246 cfb->ddc_algo.udelay = 10;
1247 cfb->ddc_algo.timeout = 20;
1248 cfb->ddc_algo.data = cfb;
1249
1250 i2c_set_adapdata(&cfb->ddc_adapter, cfb);
1251
1252 return i2c_bit_add_bus(&cfb->ddc_adapter);
1253}
1254#endif /* CONFIG_FB_CYBER2000_DDC */
1255
1256#ifdef CONFIG_FB_CYBER2000_I2C
1257static void cyber2000fb_i2c_setsda(void *data, int state)
1258{
1259 struct cfb_info *cfb = data;
1260 unsigned int latch2;
1261
1262 spin_lock(&cfb->reg_b0_lock);
1263 latch2 = cyber2000_grphr(EXT_LATCH2, cfb);
1264 latch2 &= EXT_LATCH2_I2C_CLKEN;
1265 if (state)
1266 latch2 |= EXT_LATCH2_I2C_DATEN;
1267 cyber2000_grphw(EXT_LATCH2, latch2, cfb);
1268 spin_unlock(&cfb->reg_b0_lock);
1269}
1270
1271static void cyber2000fb_i2c_setscl(void *data, int state)
1272{
1273 struct cfb_info *cfb = data;
1274 unsigned int latch2;
1275
1276 spin_lock(&cfb->reg_b0_lock);
1277 latch2 = cyber2000_grphr(EXT_LATCH2, cfb);
1278 latch2 &= EXT_LATCH2_I2C_DATEN;
1279 if (state)
1280 latch2 |= EXT_LATCH2_I2C_CLKEN;
1281 cyber2000_grphw(EXT_LATCH2, latch2, cfb);
1282 spin_unlock(&cfb->reg_b0_lock);
1283}
1284
1285static int cyber2000fb_i2c_getsda(void *data)
1286{
1287 struct cfb_info *cfb = data;
1288 int ret;
1289
1290 spin_lock(&cfb->reg_b0_lock);
1291 ret = !!(cyber2000_grphr(EXT_LATCH2, cfb) & EXT_LATCH2_I2C_DAT);
1292 spin_unlock(&cfb->reg_b0_lock);
1293
1294 return ret;
1295}
1296
1297static int cyber2000fb_i2c_getscl(void *data)
1298{
1299 struct cfb_info *cfb = data;
1300 int ret;
1301
1302 spin_lock(&cfb->reg_b0_lock);
1303 ret = !!(cyber2000_grphr(EXT_LATCH2, cfb) & EXT_LATCH2_I2C_CLK);
1304 spin_unlock(&cfb->reg_b0_lock);
1305
1306 return ret;
1307}
1308
1309static int __devinit cyber2000fb_i2c_register(struct cfb_info *cfb)
1310{
1311 strlcpy(cfb->i2c_adapter.name, cfb->fb.fix.id,
1312 sizeof(cfb->i2c_adapter.name));
1313 cfb->i2c_adapter.owner = THIS_MODULE;
1314 cfb->i2c_adapter.algo_data = &cfb->i2c_algo;
1315 cfb->i2c_adapter.dev.parent = cfb->fb.device;
1316 cfb->i2c_algo.setsda = cyber2000fb_i2c_setsda;
1317 cfb->i2c_algo.setscl = cyber2000fb_i2c_setscl;
1318 cfb->i2c_algo.getsda = cyber2000fb_i2c_getsda;
1319 cfb->i2c_algo.getscl = cyber2000fb_i2c_getscl;
1320 cfb->i2c_algo.udelay = 5;
1321 cfb->i2c_algo.timeout = msecs_to_jiffies(100);
1322 cfb->i2c_algo.data = cfb;
1323
1324 return i2c_bit_add_bus(&cfb->i2c_adapter);
1325}
1326
1327static void cyber2000fb_i2c_unregister(struct cfb_info *cfb)
1328{
1329 i2c_del_adapter(&cfb->i2c_adapter);
1330}
1331#else
1332#define cyber2000fb_i2c_register(cfb) (0)
1333#define cyber2000fb_i2c_unregister(cfb) do { } while (0)
1334#endif
1335
1144/* 1336/*
1145 * These parameters give 1337 * These parameters give
1146 * 640x480, hsync 31.5kHz, vsync 60Hz 1338 * 640x480, hsync 31.5kHz, vsync 60Hz
@@ -1275,6 +1467,8 @@ static struct cfb_info __devinit *cyberpro_alloc_fb_info(unsigned int id,
1275 cfb->fb.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; 1467 cfb->fb.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1276 cfb->fb.pseudo_palette = cfb->pseudo_palette; 1468 cfb->fb.pseudo_palette = cfb->pseudo_palette;
1277 1469
1470 spin_lock_init(&cfb->reg_b0_lock);
1471
1278 fb_alloc_cmap(&cfb->fb.cmap, NR_PALETTE, 0); 1472 fb_alloc_cmap(&cfb->fb.cmap, NR_PALETTE, 0);
1279 1473
1280 return cfb; 1474 return cfb;
@@ -1369,6 +1563,11 @@ static int __devinit cyberpro_common_probe(struct cfb_info *cfb)
1369 cfb->fb.fix.mmio_len = MMIO_SIZE; 1563 cfb->fb.fix.mmio_len = MMIO_SIZE;
1370 cfb->fb.screen_base = cfb->region; 1564 cfb->fb.screen_base = cfb->region;
1371 1565
1566#ifdef CONFIG_FB_CYBER2000_DDC
1567 if (cyber2000fb_setup_ddc_bus(cfb) == 0)
1568 cfb->ddc_registered = true;
1569#endif
1570
1372 err = -EINVAL; 1571 err = -EINVAL;
1373 if (!fb_find_mode(&cfb->fb.var, &cfb->fb, NULL, NULL, 0, 1572 if (!fb_find_mode(&cfb->fb.var, &cfb->fb, NULL, NULL, 0,
1374 &cyber2000fb_default_mode, 8)) { 1573 &cyber2000fb_default_mode, 8)) {
@@ -1401,14 +1600,32 @@ static int __devinit cyberpro_common_probe(struct cfb_info *cfb)
1401 cfb->fb.var.xres, cfb->fb.var.yres, 1600 cfb->fb.var.xres, cfb->fb.var.yres,
1402 h_sync / 1000, h_sync % 1000, v_sync); 1601 h_sync / 1000, h_sync % 1000, v_sync);
1403 1602
1404 if (cfb->dev) 1603 err = cyber2000fb_i2c_register(cfb);
1405 cfb->fb.device = &cfb->dev->dev; 1604 if (err)
1605 goto failed;
1606
1406 err = register_framebuffer(&cfb->fb); 1607 err = register_framebuffer(&cfb->fb);
1608 if (err)
1609 cyber2000fb_i2c_unregister(cfb);
1407 1610
1408failed: 1611failed:
1612#ifdef CONFIG_FB_CYBER2000_DDC
1613 if (err && cfb->ddc_registered)
1614 i2c_del_adapter(&cfb->ddc_adapter);
1615#endif
1409 return err; 1616 return err;
1410} 1617}
1411 1618
1619static void __devexit cyberpro_common_remove(struct cfb_info *cfb)
1620{
1621 unregister_framebuffer(&cfb->fb);
1622#ifdef CONFIG_FB_CYBER2000_DDC
1623 if (cfb->ddc_registered)
1624 i2c_del_adapter(&cfb->ddc_adapter);
1625#endif
1626 cyber2000fb_i2c_unregister(cfb);
1627}
1628
1412static void cyberpro_common_resume(struct cfb_info *cfb) 1629static void cyberpro_common_resume(struct cfb_info *cfb)
1413{ 1630{
1414 cyberpro_init_hw(cfb); 1631 cyberpro_init_hw(cfb);
@@ -1442,12 +1659,13 @@ static int __devinit cyberpro_vl_probe(void)
1442 if (!cfb) 1659 if (!cfb)
1443 goto failed_release; 1660 goto failed_release;
1444 1661
1445 cfb->dev = NULL; 1662 cfb->irq = -1;
1446 cfb->region = ioremap(FB_START, FB_SIZE); 1663 cfb->region = ioremap(FB_START, FB_SIZE);
1447 if (!cfb->region) 1664 if (!cfb->region)
1448 goto failed_ioremap; 1665 goto failed_ioremap;
1449 1666
1450 cfb->regs = cfb->region + MMIO_OFFSET; 1667 cfb->regs = cfb->region + MMIO_OFFSET;
1668 cfb->fb.device = NULL;
1451 cfb->fb.fix.mmio_start = FB_START + MMIO_OFFSET; 1669 cfb->fb.fix.mmio_start = FB_START + MMIO_OFFSET;
1452 cfb->fb.fix.smem_start = FB_START; 1670 cfb->fb.fix.smem_start = FB_START;
1453 1671
@@ -1585,12 +1803,13 @@ cyberpro_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
1585 if (err) 1803 if (err)
1586 goto failed_regions; 1804 goto failed_regions;
1587 1805
1588 cfb->dev = dev; 1806 cfb->irq = dev->irq;
1589 cfb->region = pci_ioremap_bar(dev, 0); 1807 cfb->region = pci_ioremap_bar(dev, 0);
1590 if (!cfb->region) 1808 if (!cfb->region)
1591 goto failed_ioremap; 1809 goto failed_ioremap;
1592 1810
1593 cfb->regs = cfb->region + MMIO_OFFSET; 1811 cfb->regs = cfb->region + MMIO_OFFSET;
1812 cfb->fb.device = &dev->dev;
1594 cfb->fb.fix.mmio_start = pci_resource_start(dev, 0) + MMIO_OFFSET; 1813 cfb->fb.fix.mmio_start = pci_resource_start(dev, 0) + MMIO_OFFSET;
1595 cfb->fb.fix.smem_start = pci_resource_start(dev, 0); 1814 cfb->fb.fix.smem_start = pci_resource_start(dev, 0);
1596 1815
@@ -1648,15 +1867,7 @@ static void __devexit cyberpro_pci_remove(struct pci_dev *dev)
1648 struct cfb_info *cfb = pci_get_drvdata(dev); 1867 struct cfb_info *cfb = pci_get_drvdata(dev);
1649 1868
1650 if (cfb) { 1869 if (cfb) {
1651 /* 1870 cyberpro_common_remove(cfb);
1652 * If unregister_framebuffer fails, then
1653 * we will be leaving hooks that could cause
1654 * oopsen laying around.
1655 */
1656 if (unregister_framebuffer(&cfb->fb))
1657 printk(KERN_WARNING "%s: danger Will Robinson, "
1658 "danger danger! Oopsen imminent!\n",
1659 cfb->fb.fix.id);
1660 iounmap(cfb->region); 1871 iounmap(cfb->region);
1661 cyberpro_free_fb_info(cfb); 1872 cyberpro_free_fb_info(cfb);
1662 1873
diff --git a/drivers/video/cyber2000fb.h b/drivers/video/cyber2000fb.h
index de4fc43e51c1..bad69102e774 100644
--- a/drivers/video/cyber2000fb.h
+++ b/drivers/video/cyber2000fb.h
@@ -464,12 +464,14 @@ static void debug_printf(char *fmt, ...)
464struct cfb_info; 464struct cfb_info;
465 465
466struct cyberpro_info { 466struct cyberpro_info {
467 struct pci_dev *dev; 467 struct device *dev;
468 struct i2c_adapter *i2c;
468 unsigned char __iomem *regs; 469 unsigned char __iomem *regs;
469 char __iomem *fb; 470 char __iomem *fb;
470 char dev_name[32]; 471 char dev_name[32];
471 unsigned int fb_size; 472 unsigned int fb_size;
472 unsigned int chip_id; 473 unsigned int chip_id;
474 unsigned int irq;
473 475
474 /* 476 /*
475 * The following is a pointer to be passed into the 477 * The following is a pointer to be passed into the
@@ -478,15 +480,6 @@ struct cyberpro_info {
478 * is within this structure. 480 * is within this structure.
479 */ 481 */
480 struct cfb_info *info; 482 struct cfb_info *info;
481
482 /*
483 * Use these to enable the BM or TV registers. In an SMP
484 * environment, these two function pointers should only be
485 * called from the module_init() or module_exit()
486 * functions.
487 */
488 void (*enable_extregs)(struct cfb_info *);
489 void (*disable_extregs)(struct cfb_info *);
490}; 483};
491 484
492#define ID_IGA_1682 0 485#define ID_IGA_1682 0
@@ -494,8 +487,6 @@ struct cyberpro_info {
494#define ID_CYBERPRO_2010 2 487#define ID_CYBERPRO_2010 2
495#define ID_CYBERPRO_5000 3 488#define ID_CYBERPRO_5000 3
496 489
497struct fb_var_screeninfo;
498
499/* 490/*
500 * Note! Writing to the Cyber20x0 registers from an interrupt 491 * Note! Writing to the Cyber20x0 registers from an interrupt
501 * routine is definitely a bad idea atm. 492 * routine is definitely a bad idea atm.
@@ -504,4 +495,3 @@ int cyber2000fb_attach(struct cyberpro_info *info, int idx);
504void cyber2000fb_detach(int idx); 495void cyber2000fb_detach(int idx);
505void cyber2000fb_enable_extregs(struct cfb_info *cfb); 496void cyber2000fb_enable_extregs(struct cfb_info *cfb);
506void cyber2000fb_disable_extregs(struct cfb_info *cfb); 497void cyber2000fb_disable_extregs(struct cfb_info *cfb);
507void cyber2000fb_get_fb_var(struct cfb_info *cfb, struct fb_var_screeninfo *var);
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index cad7d45c8bac..fcdac872522d 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -763,7 +763,7 @@ static int fb_wait_for_vsync(struct fb_info *info)
763 763
764 /* 764 /*
765 * Set flag to 0 and wait for isr to set to 1. It would seem there is a 765 * Set flag to 0 and wait for isr to set to 1. It would seem there is a
766 * race condition here where the ISR could have occured just before or 766 * race condition here where the ISR could have occurred just before or
767 * just after this set. But since we are just coarsely waiting for 767 * just after this set. But since we are just coarsely waiting for
768 * a frame to complete then that's OK. i.e. if the frame completed 768 * a frame to complete then that's OK. i.e. if the frame completed
769 * just before this code executed then we have to wait another full 769 * just before this code executed then we have to wait another full
@@ -899,7 +899,7 @@ static struct fb_ops da8xx_fb_ops = {
899 .fb_blank = cfb_blank, 899 .fb_blank = cfb_blank,
900}; 900};
901 901
902static int __init fb_probe(struct platform_device *device) 902static int __devinit fb_probe(struct platform_device *device)
903{ 903{
904 struct da8xx_lcdc_platform_data *fb_pdata = 904 struct da8xx_lcdc_platform_data *fb_pdata =
905 device->dev.platform_data; 905 device->dev.platform_data;
@@ -1029,10 +1029,6 @@ static int __init fb_probe(struct platform_device *device)
1029 goto err_release_pl_mem; 1029 goto err_release_pl_mem;
1030 } 1030 }
1031 1031
1032 ret = request_irq(par->irq, lcdc_irq_handler, 0, DRIVER_NAME, par);
1033 if (ret)
1034 goto err_release_pl_mem;
1035
1036 /* Initialize par */ 1032 /* Initialize par */
1037 da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp; 1033 da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp;
1038 1034
@@ -1060,7 +1056,7 @@ static int __init fb_probe(struct platform_device *device)
1060 1056
1061 ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0); 1057 ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0);
1062 if (ret) 1058 if (ret)
1063 goto err_free_irq; 1059 goto err_release_pl_mem;
1064 da8xx_fb_info->cmap.len = par->palette_sz; 1060 da8xx_fb_info->cmap.len = par->palette_sz;
1065 1061
1066 /* initialize var_screeninfo */ 1062 /* initialize var_screeninfo */
@@ -1088,19 +1084,22 @@ static int __init fb_probe(struct platform_device *device)
1088 goto err_cpu_freq; 1084 goto err_cpu_freq;
1089 } 1085 }
1090#endif 1086#endif
1087
1088 ret = request_irq(par->irq, lcdc_irq_handler, 0, DRIVER_NAME, par);
1089 if (ret)
1090 goto irq_freq;
1091 return 0; 1091 return 0;
1092 1092
1093irq_freq:
1093#ifdef CONFIG_CPU_FREQ 1094#ifdef CONFIG_CPU_FREQ
1095 lcd_da8xx_cpufreq_deregister(par);
1096#endif
1094err_cpu_freq: 1097err_cpu_freq:
1095 unregister_framebuffer(da8xx_fb_info); 1098 unregister_framebuffer(da8xx_fb_info);
1096#endif
1097 1099
1098err_dealloc_cmap: 1100err_dealloc_cmap:
1099 fb_dealloc_cmap(&da8xx_fb_info->cmap); 1101 fb_dealloc_cmap(&da8xx_fb_info->cmap);
1100 1102
1101err_free_irq:
1102 free_irq(par->irq, par);
1103
1104err_release_pl_mem: 1103err_release_pl_mem:
1105 dma_free_coherent(NULL, PALETTE_SIZE, par->v_palette_base, 1104 dma_free_coherent(NULL, PALETTE_SIZE, par->v_palette_base,
1106 par->p_palette_base); 1105 par->p_palette_base);
@@ -1132,14 +1131,14 @@ static int fb_suspend(struct platform_device *dev, pm_message_t state)
1132 struct fb_info *info = platform_get_drvdata(dev); 1131 struct fb_info *info = platform_get_drvdata(dev);
1133 struct da8xx_fb_par *par = info->par; 1132 struct da8xx_fb_par *par = info->par;
1134 1133
1135 acquire_console_sem(); 1134 console_lock();
1136 if (par->panel_power_ctrl) 1135 if (par->panel_power_ctrl)
1137 par->panel_power_ctrl(0); 1136 par->panel_power_ctrl(0);
1138 1137
1139 fb_set_suspend(info, 1); 1138 fb_set_suspend(info, 1);
1140 lcd_disable_raster(); 1139 lcd_disable_raster();
1141 clk_disable(par->lcdc_clk); 1140 clk_disable(par->lcdc_clk);
1142 release_console_sem(); 1141 console_unlock();
1143 1142
1144 return 0; 1143 return 0;
1145} 1144}
@@ -1148,14 +1147,14 @@ static int fb_resume(struct platform_device *dev)
1148 struct fb_info *info = platform_get_drvdata(dev); 1147 struct fb_info *info = platform_get_drvdata(dev);
1149 struct da8xx_fb_par *par = info->par; 1148 struct da8xx_fb_par *par = info->par;
1150 1149
1151 acquire_console_sem(); 1150 console_lock();
1152 if (par->panel_power_ctrl) 1151 if (par->panel_power_ctrl)
1153 par->panel_power_ctrl(1); 1152 par->panel_power_ctrl(1);
1154 1153
1155 clk_enable(par->lcdc_clk); 1154 clk_enable(par->lcdc_clk);
1156 lcd_enable_raster(); 1155 lcd_enable_raster();
1157 fb_set_suspend(info, 0); 1156 fb_set_suspend(info, 0);
1158 release_console_sem(); 1157 console_unlock();
1159 1158
1160 return 0; 1159 return 0;
1161} 1160}
@@ -1166,7 +1165,7 @@ static int fb_resume(struct platform_device *dev)
1166 1165
1167static struct platform_driver da8xx_fb_driver = { 1166static struct platform_driver da8xx_fb_driver = {
1168 .probe = fb_probe, 1167 .probe = fb_probe,
1169 .remove = fb_remove, 1168 .remove = __devexit_p(fb_remove),
1170 .suspend = fb_suspend, 1169 .suspend = fb_suspend,
1171 .resume = fb_resume, 1170 .resume = fb_resume,
1172 .driver = { 1171 .driver = {
diff --git a/drivers/video/display/display-sysfs.c b/drivers/video/display/display-sysfs.c
index f6a09ab0dac6..0c647d7af0ee 100644
--- a/drivers/video/display/display-sysfs.c
+++ b/drivers/video/display/display-sysfs.c
@@ -182,7 +182,7 @@ void display_device_unregister(struct display_device *ddev)
182 mutex_lock(&ddev->lock); 182 mutex_lock(&ddev->lock);
183 device_unregister(ddev->dev); 183 device_unregister(ddev->dev);
184 mutex_unlock(&ddev->lock); 184 mutex_unlock(&ddev->lock);
185 // Mark device index as avaliable 185 // Mark device index as available
186 mutex_lock(&allocated_dsp_lock); 186 mutex_lock(&allocated_dsp_lock);
187 idr_remove(&allocated_dsp, ddev->idx); 187 idr_remove(&allocated_dsp, ddev->idx);
188 mutex_unlock(&allocated_dsp_lock); 188 mutex_unlock(&allocated_dsp_lock);
diff --git a/drivers/video/edid.h b/drivers/video/edid.h
index bd89fb3be8c2..d03a232d90b2 100644
--- a/drivers/video/edid.h
+++ b/drivers/video/edid.h
@@ -101,8 +101,8 @@
101#define V_SYNC_WIDTH COMBINE_HI_4LO( V_SYNC_WIDTH_HI, V_SYNC_WIDTH_LO ) 101#define V_SYNC_WIDTH COMBINE_HI_4LO( V_SYNC_WIDTH_HI, V_SYNC_WIDTH_LO )
102#define V_SYNC_OFFSET COMBINE_HI_4LO( V_SYNC_OFFSET_HI, V_SYNC_OFFSET_LO ) 102#define V_SYNC_OFFSET COMBINE_HI_4LO( V_SYNC_OFFSET_HI, V_SYNC_OFFSET_LO )
103 103
104#define H_SYNC_WIDTH COMBINE_HI_4LO( H_SYNC_WIDTH_HI, H_SYNC_WIDTH_LO ) 104#define H_SYNC_WIDTH COMBINE_HI_8LO( H_SYNC_WIDTH_HI, H_SYNC_WIDTH_LO )
105#define H_SYNC_OFFSET COMBINE_HI_4LO( H_SYNC_OFFSET_HI, H_SYNC_OFFSET_LO ) 105#define H_SYNC_OFFSET COMBINE_HI_8LO( H_SYNC_OFFSET_HI, H_SYNC_OFFSET_LO )
106 106
107#define H_SIZE_LO (unsigned)block[ 12 ] 107#define H_SIZE_LO (unsigned)block[ 12 ]
108#define V_SIZE_LO (unsigned)block[ 13 ] 108#define V_SIZE_LO (unsigned)block[ 13 ]
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c
index 70477c2e4b61..784139aed079 100644
--- a/drivers/video/efifb.c
+++ b/drivers/video/efifb.c
@@ -16,6 +16,8 @@
16#include <linux/pci.h> 16#include <linux/pci.h>
17#include <video/vga.h> 17#include <video/vga.h>
18 18
19static bool request_mem_succeeded = false;
20
19static struct fb_var_screeninfo efifb_defined __devinitdata = { 21static struct fb_var_screeninfo efifb_defined __devinitdata = {
20 .activate = FB_ACTIVATE_NOW, 22 .activate = FB_ACTIVATE_NOW,
21 .height = -1, 23 .height = -1,
@@ -53,6 +55,7 @@ enum {
53 M_MB_7_1, /* MacBook, 7th rev. */ 55 M_MB_7_1, /* MacBook, 7th rev. */
54 M_MB_SR, /* MacBook, 2nd gen, (Santa Rosa) */ 56 M_MB_SR, /* MacBook, 2nd gen, (Santa Rosa) */
55 M_MBA, /* MacBook Air */ 57 M_MBA, /* MacBook Air */
58 M_MBA_3, /* Macbook Air, 3rd rev */
56 M_MBP, /* MacBook Pro */ 59 M_MBP, /* MacBook Pro */
57 M_MBP_2, /* MacBook Pro 2nd gen */ 60 M_MBP_2, /* MacBook Pro 2nd gen */
58 M_MBP_2_2, /* MacBook Pro 2,2nd gen */ 61 M_MBP_2_2, /* MacBook Pro 2,2nd gen */
@@ -64,43 +67,54 @@ enum {
64 M_MBP_6_1, /* MacBook Pro, 6,1th gen */ 67 M_MBP_6_1, /* MacBook Pro, 6,1th gen */
65 M_MBP_6_2, /* MacBook Pro, 6,2th gen */ 68 M_MBP_6_2, /* MacBook Pro, 6,2th gen */
66 M_MBP_7_1, /* MacBook Pro, 7,1th gen */ 69 M_MBP_7_1, /* MacBook Pro, 7,1th gen */
70 M_MBP_8_2, /* MacBook Pro, 8,2nd gen */
67 M_UNKNOWN /* placeholder */ 71 M_UNKNOWN /* placeholder */
68}; 72};
69 73
74#define OVERRIDE_NONE 0x0
75#define OVERRIDE_BASE 0x1
76#define OVERRIDE_STRIDE 0x2
77#define OVERRIDE_HEIGHT 0x4
78#define OVERRIDE_WIDTH 0x8
79
70static struct efifb_dmi_info { 80static struct efifb_dmi_info {
71 char *optname; 81 char *optname;
72 unsigned long base; 82 unsigned long base;
73 int stride; 83 int stride;
74 int width; 84 int width;
75 int height; 85 int height;
86 int flags;
76} dmi_list[] __initdata = { 87} dmi_list[] __initdata = {
77 [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900 }, 88 [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
78 [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050 }, /* guess */ 89 [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050, OVERRIDE_NONE }, /* guess */
79 [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050 }, 90 [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050, OVERRIDE_NONE },
80 [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200 }, /* guess */ 91 [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, /* guess */
81 [M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200 }, 92 [M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
82 [M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080 }, 93 [M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080, OVERRIDE_NONE },
83 [M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440 }, 94 [M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440, OVERRIDE_NONE },
84 [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768 }, 95 [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768, OVERRIDE_NONE },
85 [M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768 }, 96 [M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768, OVERRIDE_NONE },
86 [M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200 }, 97 [M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
87 [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800 }, 98 [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
88 [M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800 }, 99 [M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
89 [M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800 }, 100 [M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
90 [M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800 }, 101 [M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
91 [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800 }, 102 [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
92 [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900 }, 103 /* 11" Macbook Air 3,1 passes the wrong stride */
93 [M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */ 104 [M_MBA_3] = { "mba3", 0, 2048 * 4, 0, 0, OVERRIDE_STRIDE },
94 [M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900 }, 105 [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
95 [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 }, 106 [M_MBP_2] = { "mbp2", 0, 0, 0, 0, OVERRIDE_NONE }, /* placeholder */
96 [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 }, 107 [M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
97 [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900 }, 108 [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900, OVERRIDE_NONE },
98 [M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200 }, 109 [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
99 [M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900 }, 110 [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900, OVERRIDE_NONE },
100 [M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200 }, 111 [M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
101 [M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050 }, 112 [M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900, OVERRIDE_NONE },
102 [M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800 }, 113 [M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
103 [M_UNKNOWN] = { NULL, 0, 0, 0, 0 } 114 [M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050, OVERRIDE_NONE },
115 [M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
116 [M_MBP_8_2] = { "mbp82", 0x90010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
117 [M_UNKNOWN] = { NULL, 0, 0, 0, 0, OVERRIDE_NONE }
104}; 118};
105 119
106static int set_system(const struct dmi_system_id *id); 120static int set_system(const struct dmi_system_id *id);
@@ -138,6 +152,7 @@ static const struct dmi_system_id dmi_system_table[] __initconst = {
138 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook6,1", M_MB_6_1), 152 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook6,1", M_MB_6_1),
139 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook7,1", M_MB_7_1), 153 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook7,1", M_MB_7_1),
140 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA), 154 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA),
155 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir3,1", M_MBA_3),
141 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP), 156 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP),
142 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2), 157 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2),
143 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,2", M_MBP_2_2), 158 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,2", M_MBP_2_2),
@@ -151,19 +166,26 @@ static const struct dmi_system_id dmi_system_table[] __initconst = {
151 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,1", M_MBP_6_1), 166 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,1", M_MBP_6_1),
152 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,2", M_MBP_6_2), 167 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,2", M_MBP_6_2),
153 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro7,1", M_MBP_7_1), 168 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro7,1", M_MBP_7_1),
169 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro8,2", M_MBP_8_2),
154 {}, 170 {},
155}; 171};
156 172
173#define choose_value(dmivalue, fwvalue, field, flags) ({ \
174 typeof(fwvalue) _ret_ = fwvalue; \
175 if ((flags) & (field)) \
176 _ret_ = dmivalue; \
177 else if ((fwvalue) == 0) \
178 _ret_ = dmivalue; \
179 _ret_; \
180 })
181
157static int set_system(const struct dmi_system_id *id) 182static int set_system(const struct dmi_system_id *id)
158{ 183{
159 struct efifb_dmi_info *info = id->driver_data; 184 struct efifb_dmi_info *info = id->driver_data;
160 if (info->base == 0)
161 return 0;
162 185
163 printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p " 186 if (info->base == 0 && info->height == 0 && info->width == 0
164 "(%dx%d, stride %d)\n", id->ident, 187 && info->stride == 0)
165 (void *)info->base, info->width, info->height, 188 return 0;
166 info->stride);
167 189
168 /* Trust the bootloader over the DMI tables */ 190 /* Trust the bootloader over the DMI tables */
169 if (screen_info.lfb_base == 0) { 191 if (screen_info.lfb_base == 0) {
@@ -171,40 +193,47 @@ static int set_system(const struct dmi_system_id *id)
171 struct pci_dev *dev = NULL; 193 struct pci_dev *dev = NULL;
172 int found_bar = 0; 194 int found_bar = 0;
173#endif 195#endif
174 screen_info.lfb_base = info->base; 196 if (info->base) {
197 screen_info.lfb_base = choose_value(info->base,
198 screen_info.lfb_base, OVERRIDE_BASE,
199 info->flags);
175 200
176#if defined(CONFIG_PCI) 201#if defined(CONFIG_PCI)
177 /* make sure that the address in the table is actually on a 202 /* make sure that the address in the table is actually
178 * VGA device's PCI BAR */ 203 * on a VGA device's PCI BAR */
179 204
180 for_each_pci_dev(dev) { 205 for_each_pci_dev(dev) {
181 int i; 206 int i;
182 if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) 207 if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
183 continue; 208 continue;
184 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { 209 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
185 resource_size_t start, end; 210 resource_size_t start, end;
186 211
187 start = pci_resource_start(dev, i); 212 start = pci_resource_start(dev, i);
188 if (start == 0) 213 if (start == 0)
189 break; 214 break;
190 end = pci_resource_end(dev, i); 215 end = pci_resource_end(dev, i);
191 if (screen_info.lfb_base >= start && 216 if (screen_info.lfb_base >= start &&
192 screen_info.lfb_base < end) { 217 screen_info.lfb_base < end) {
193 found_bar = 1; 218 found_bar = 1;
219 }
194 } 220 }
195 } 221 }
196 } 222 if (!found_bar)
197 if (!found_bar) 223 screen_info.lfb_base = 0;
198 screen_info.lfb_base = 0;
199#endif 224#endif
225 }
200 } 226 }
201 if (screen_info.lfb_base) { 227 if (screen_info.lfb_base) {
202 if (screen_info.lfb_linelength == 0) 228 screen_info.lfb_linelength = choose_value(info->stride,
203 screen_info.lfb_linelength = info->stride; 229 screen_info.lfb_linelength, OVERRIDE_STRIDE,
204 if (screen_info.lfb_width == 0) 230 info->flags);
205 screen_info.lfb_width = info->width; 231 screen_info.lfb_width = choose_value(info->width,
206 if (screen_info.lfb_height == 0) 232 screen_info.lfb_width, OVERRIDE_WIDTH,
207 screen_info.lfb_height = info->height; 233 info->flags);
234 screen_info.lfb_height = choose_value(info->height,
235 screen_info.lfb_height, OVERRIDE_HEIGHT,
236 info->flags);
208 if (screen_info.orig_video_isVGA == 0) 237 if (screen_info.orig_video_isVGA == 0)
209 screen_info.orig_video_isVGA = VIDEO_TYPE_EFI; 238 screen_info.orig_video_isVGA = VIDEO_TYPE_EFI;
210 } else { 239 } else {
@@ -214,6 +243,13 @@ static int set_system(const struct dmi_system_id *id)
214 screen_info.orig_video_isVGA = 0; 243 screen_info.orig_video_isVGA = 0;
215 return 0; 244 return 0;
216 } 245 }
246
247 printk(KERN_INFO "efifb: dmi detected %s - framebuffer at 0x%08x "
248 "(%dx%d, stride %d)\n", id->ident,
249 screen_info.lfb_base, screen_info.lfb_width,
250 screen_info.lfb_height, screen_info.lfb_linelength);
251
252
217 return 1; 253 return 1;
218} 254}
219 255
@@ -247,7 +283,9 @@ static void efifb_destroy(struct fb_info *info)
247{ 283{
248 if (info->screen_base) 284 if (info->screen_base)
249 iounmap(info->screen_base); 285 iounmap(info->screen_base);
250 release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size); 286 if (request_mem_succeeded)
287 release_mem_region(info->apertures->ranges[0].base,
288 info->apertures->ranges[0].size);
251 framebuffer_release(info); 289 framebuffer_release(info);
252} 290}
253 291
@@ -292,14 +330,13 @@ static int __init efifb_setup(char *options)
292 return 0; 330 return 0;
293} 331}
294 332
295static int __devinit efifb_probe(struct platform_device *dev) 333static int __init efifb_probe(struct platform_device *dev)
296{ 334{
297 struct fb_info *info; 335 struct fb_info *info;
298 int err; 336 int err;
299 unsigned int size_vmode; 337 unsigned int size_vmode;
300 unsigned int size_remap; 338 unsigned int size_remap;
301 unsigned int size_total; 339 unsigned int size_total;
302 int request_succeeded = 0;
303 340
304 if (!screen_info.lfb_depth) 341 if (!screen_info.lfb_depth)
305 screen_info.lfb_depth = 32; 342 screen_info.lfb_depth = 32;
@@ -353,7 +390,7 @@ static int __devinit efifb_probe(struct platform_device *dev)
353 efifb_fix.smem_len = size_remap; 390 efifb_fix.smem_len = size_remap;
354 391
355 if (request_mem_region(efifb_fix.smem_start, size_remap, "efifb")) { 392 if (request_mem_region(efifb_fix.smem_start, size_remap, "efifb")) {
356 request_succeeded = 1; 393 request_mem_succeeded = true;
357 } else { 394 } else {
358 /* We cannot make this fatal. Sometimes this comes from magic 395 /* We cannot make this fatal. Sometimes this comes from magic
359 spaces our resource handlers simply don't know about */ 396 spaces our resource handlers simply don't know about */
@@ -379,7 +416,7 @@ static int __devinit efifb_probe(struct platform_device *dev)
379 info->apertures->ranges[0].base = efifb_fix.smem_start; 416 info->apertures->ranges[0].base = efifb_fix.smem_start;
380 info->apertures->ranges[0].size = size_remap; 417 info->apertures->ranges[0].size = size_remap;
381 418
382 info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len); 419 info->screen_base = ioremap_wc(efifb_fix.smem_start, efifb_fix.smem_len);
383 if (!info->screen_base) { 420 if (!info->screen_base) {
384 printk(KERN_ERR "efifb: abort, cannot ioremap video memory " 421 printk(KERN_ERR "efifb: abort, cannot ioremap video memory "
385 "0x%x @ 0x%lx\n", 422 "0x%x @ 0x%lx\n",
@@ -457,13 +494,12 @@ err_unmap:
457err_release_fb: 494err_release_fb:
458 framebuffer_release(info); 495 framebuffer_release(info);
459err_release_mem: 496err_release_mem:
460 if (request_succeeded) 497 if (request_mem_succeeded)
461 release_mem_region(efifb_fix.smem_start, size_total); 498 release_mem_region(efifb_fix.smem_start, size_total);
462 return err; 499 return err;
463} 500}
464 501
465static struct platform_driver efifb_driver = { 502static struct platform_driver efifb_driver = {
466 .probe = efifb_probe,
467 .driver = { 503 .driver = {
468 .name = "efifb", 504 .name = "efifb",
469 }, 505 },
@@ -494,13 +530,21 @@ static int __init efifb_init(void)
494 if (!screen_info.lfb_linelength) 530 if (!screen_info.lfb_linelength)
495 return -ENODEV; 531 return -ENODEV;
496 532
497 ret = platform_driver_register(&efifb_driver); 533 ret = platform_device_register(&efifb_device);
534 if (ret)
535 return ret;
498 536
499 if (!ret) { 537 /*
500 ret = platform_device_register(&efifb_device); 538 * This is not just an optimization. We will interfere
501 if (ret) 539 * with a real driver if we get reprobed, so don't allow
502 platform_driver_unregister(&efifb_driver); 540 * it.
541 */
542 ret = platform_driver_probe(&efifb_driver, efifb_probe);
543 if (ret) {
544 platform_device_unregister(&efifb_device);
545 return ret;
503 } 546 }
547
504 return ret; 548 return ret;
505} 549}
506module_init(efifb_init); 550module_init(efifb_init);
diff --git a/drivers/video/ep93xx-fb.c b/drivers/video/ep93xx-fb.c
index 0c99de0562ca..cbdb1bd77c21 100644
--- a/drivers/video/ep93xx-fb.c
+++ b/drivers/video/ep93xx-fb.c
@@ -456,7 +456,7 @@ static int __init ep93xxfb_alloc_videomem(struct fb_info *info)
456 * There is a bug in the ep93xx framebuffer which causes problems 456 * There is a bug in the ep93xx framebuffer which causes problems
457 * if bit 27 of the physical address is set. 457 * if bit 27 of the physical address is set.
458 * See: http://marc.info/?l=linux-arm-kernel&m=110061245502000&w=2 458 * See: http://marc.info/?l=linux-arm-kernel&m=110061245502000&w=2
459 * There does not seem to be any offical errata for this, but I 459 * There does not seem to be any official errata for this, but I
460 * have confirmed the problem exists on my hardware (ep9315) at 460 * have confirmed the problem exists on my hardware (ep9315) at
461 * least. 461 * least.
462 */ 462 */
@@ -483,7 +483,7 @@ static void ep93xxfb_dealloc_videomem(struct fb_info *info)
483 info->screen_base, info->fix.smem_start); 483 info->screen_base, info->fix.smem_start);
484} 484}
485 485
486static int __init ep93xxfb_probe(struct platform_device *pdev) 486static int __devinit ep93xxfb_probe(struct platform_device *pdev)
487{ 487{
488 struct ep93xxfb_mach_info *mach_info = pdev->dev.platform_data; 488 struct ep93xxfb_mach_info *mach_info = pdev->dev.platform_data;
489 struct fb_info *info; 489 struct fb_info *info;
@@ -598,7 +598,7 @@ failed:
598 return err; 598 return err;
599} 599}
600 600
601static int ep93xxfb_remove(struct platform_device *pdev) 601static int __devexit ep93xxfb_remove(struct platform_device *pdev)
602{ 602{
603 struct fb_info *info = platform_get_drvdata(pdev); 603 struct fb_info *info = platform_get_drvdata(pdev);
604 struct ep93xx_fbi *fbi = info->par; 604 struct ep93xx_fbi *fbi = info->par;
@@ -622,7 +622,7 @@ static int ep93xxfb_remove(struct platform_device *pdev)
622 622
623static struct platform_driver ep93xxfb_driver = { 623static struct platform_driver ep93xxfb_driver = {
624 .probe = ep93xxfb_probe, 624 .probe = ep93xxfb_probe,
625 .remove = ep93xxfb_remove, 625 .remove = __devexit_p(ep93xxfb_remove),
626 .driver = { 626 .driver = {
627 .name = "ep93xx-fb", 627 .name = "ep93xx-fb",
628 .owner = THIS_MODULE, 628 .owner = THIS_MODULE,
diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c
index db9713b49ce9..a268cbf1cbea 100644
--- a/drivers/video/epson1355fb.c
+++ b/drivers/video/epson1355fb.c
@@ -4,7 +4,7 @@
4 * Epson Research S1D13505 Embedded RAMDAC LCD/CRT Controller 4 * Epson Research S1D13505 Embedded RAMDAC LCD/CRT Controller
5 * (previously known as SED1355) 5 * (previously known as SED1355)
6 * 6 *
7 * Cf. http://www.erd.epson.com/vdc/html/S1D13505.html 7 * Cf. http://vdc.epson.com/
8 * 8 *
9 * 9 *
10 * Copyright (C) Hewlett-Packard Company. All rights reserved. 10 * Copyright (C) Hewlett-Packard Company. All rights reserved.
diff --git a/drivers/video/fb-puv3.c b/drivers/video/fb-puv3.c
new file mode 100644
index 000000000000..27f2c57e06e9
--- /dev/null
+++ b/drivers/video/fb-puv3.c
@@ -0,0 +1,852 @@
1/*
2 * Frame Buffer Driver for PKUnity-v3 Unigfx
3 * Code specific to PKUnity SoC and UniCore ISA
4 *
5 * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
6 * Copyright (C) 2001-2010 Guan Xuetao
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/module.h>
14#include <linux/kernel.h>
15#include <linux/errno.h>
16#include <linux/platform_device.h>
17#include <linux/clk.h>
18#include <linux/fb.h>
19#include <linux/init.h>
20#include <linux/console.h>
21
22#include <asm/sizes.h>
23#include <mach/hardware.h>
24
25/* Platform_data reserved for unifb registers. */
26#define UNIFB_REGS_NUM 10
27/* RAM reserved for the frame buffer. */
28#define UNIFB_MEMSIZE (SZ_4M) /* 4 MB for 1024*768*32b */
29
30/*
31 * cause UNIGFX don not have EDID
32 * all the modes are organized as follow
33 */
34static const struct fb_videomode unifb_modes[] = {
35 /* 0 640x480-60 VESA */
36 { "640x480@60", 60, 640, 480, 25175000, 48, 16, 34, 10, 96, 1,
37 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
38 /* 1 640x480-75 VESA */
39 { "640x480@75", 75, 640, 480, 31500000, 120, 16, 18, 1, 64, 1,
40 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
41 /* 2 800x600-60 VESA */
42 { "800x600@60", 60, 800, 600, 40000000, 88, 40, 26, 1, 128, 1,
43 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
44 /* 3 800x600-75 VESA */
45 { "800x600@75", 75, 800, 600, 49500000, 160, 16, 23, 1, 80, 1,
46 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
47 /* 4 1024x768-60 VESA */
48 { "1024x768@60", 60, 1024, 768, 65000000, 160, 24, 34, 3, 136, 1,
49 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
50 /* 5 1024x768-75 VESA */
51 { "1024x768@75", 75, 1024, 768, 78750000, 176, 16, 30, 1, 96, 1,
52 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
53 /* 6 1280x960-60 VESA */
54 { "1280x960@60", 60, 1280, 960, 108000000, 312, 96, 38, 1, 112, 1,
55 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
56 /* 7 1440x900-60 VESA */
57 { "1440x900@60", 60, 1440, 900, 106500000, 232, 80, 30, 3, 152, 1,
58 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
59 /* 8 FIXME 9 1024x600-60 VESA UNTESTED */
60 { "1024x600@60", 60, 1024, 600, 50650000, 160, 24, 26, 1, 136, 1,
61 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
62 /* 9 FIXME 10 1024x600-75 VESA UNTESTED */
63 { "1024x600@75", 75, 1024, 600, 61500000, 176, 16, 23, 1, 96, 1,
64 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
65 /* 10 FIXME 11 1366x768-60 VESA UNTESTED */
66 { "1366x768@60", 60, 1366, 768, 85500000, 256, 58, 18, 1, 112, 3,
67 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
68};
69
70static struct fb_var_screeninfo unifb_default = {
71 .xres = 640,
72 .yres = 480,
73 .xres_virtual = 640,
74 .yres_virtual = 480,
75 .bits_per_pixel = 16,
76 .red = { 11, 5, 0 },
77 .green = { 5, 6, 0 },
78 .blue = { 0, 5, 0 },
79 .activate = FB_ACTIVATE_NOW,
80 .height = -1,
81 .width = -1,
82 .pixclock = 25175000,
83 .left_margin = 48,
84 .right_margin = 16,
85 .upper_margin = 33,
86 .lower_margin = 10,
87 .hsync_len = 96,
88 .vsync_len = 2,
89 .vmode = FB_VMODE_NONINTERLACED,
90};
91
92static struct fb_fix_screeninfo unifb_fix = {
93 .id = "UNIGFX FB",
94 .type = FB_TYPE_PACKED_PIXELS,
95 .visual = FB_VISUAL_TRUECOLOR,
96 .xpanstep = 1,
97 .ypanstep = 1,
98 .ywrapstep = 1,
99 .accel = FB_ACCEL_NONE,
100};
101
102static void unifb_sync(struct fb_info *info)
103{
104 /* TODO: may, this can be replaced by interrupt */
105 int cnt;
106
107 for (cnt = 0; cnt < 0x10000000; cnt++) {
108 if (readl(UGE_COMMAND) & 0x1000000)
109 return;
110 }
111
112 if (cnt > 0x8000000)
113 dev_warn(info->device, "Warning: UniGFX GE time out ...\n");
114}
115
116static void unifb_prim_fillrect(struct fb_info *info,
117 const struct fb_fillrect *region)
118{
119 int awidth = region->width;
120 int aheight = region->height;
121 int m_iBpp = info->var.bits_per_pixel;
122 int screen_width = info->var.xres;
123 int src_sel = 1; /* from fg_color */
124 int pat_sel = 1;
125 int src_x0 = 0;
126 int dst_x0 = region->dx;
127 int src_y0 = 0;
128 int dst_y0 = region->dy;
129 int rop_alpha_sel = 0;
130 int rop_alpha_code = 0xCC;
131 int x_dir = 1;
132 int y_dir = 1;
133 int alpha_r = 0;
134 int alpha_sel = 0;
135 int dst_pitch = screen_width * (m_iBpp / 8);
136 int dst_offset = dst_y0 * dst_pitch + dst_x0 * (m_iBpp / 8);
137 int src_pitch = screen_width * (m_iBpp / 8);
138 int src_offset = src_y0 * src_pitch + src_x0 * (m_iBpp / 8);
139 unsigned int command = 0;
140 int clip_region = 0;
141 int clip_en = 0;
142 int tp_en = 0;
143 int fg_color = 0;
144 int bottom = info->var.yres - 1;
145 int right = info->var.xres - 1;
146 int top = 0;
147
148 bottom = (bottom << 16) | right;
149 command = (rop_alpha_sel << 26) | (pat_sel << 18) | (src_sel << 16)
150 | (x_dir << 20) | (y_dir << 21) | (command << 24)
151 | (clip_region << 23) | (clip_en << 22) | (tp_en << 27);
152 src_pitch = (dst_pitch << 16) | src_pitch;
153 awidth = awidth | (aheight << 16);
154 alpha_r = ((rop_alpha_code & 0xff) << 8) | (alpha_r & 0xff)
155 | (alpha_sel << 16);
156 src_x0 = (src_x0 & 0x1fff) | ((src_y0 & 0x1fff) << 16);
157 dst_x0 = (dst_x0 & 0x1fff) | ((dst_y0 & 0x1fff) << 16);
158 fg_color = region->color;
159
160 unifb_sync(info);
161
162 writel(((u32 *)(info->pseudo_palette))[fg_color], UGE_FCOLOR);
163 writel(0, UGE_BCOLOR);
164 writel(src_pitch, UGE_PITCH);
165 writel(src_offset, UGE_SRCSTART);
166 writel(dst_offset, UGE_DSTSTART);
167 writel(awidth, UGE_WIDHEIGHT);
168 writel(top, UGE_CLIP0);
169 writel(bottom, UGE_CLIP1);
170 writel(alpha_r, UGE_ROPALPHA);
171 writel(src_x0, UGE_SRCXY);
172 writel(dst_x0, UGE_DSTXY);
173 writel(command, UGE_COMMAND);
174}
175
176static void unifb_fillrect(struct fb_info *info,
177 const struct fb_fillrect *region)
178{
179 struct fb_fillrect modded;
180 int vxres, vyres;
181
182 if (info->flags & FBINFO_HWACCEL_DISABLED) {
183 sys_fillrect(info, region);
184 return;
185 }
186
187 vxres = info->var.xres_virtual;
188 vyres = info->var.yres_virtual;
189
190 memcpy(&modded, region, sizeof(struct fb_fillrect));
191
192 if (!modded.width || !modded.height ||
193 modded.dx >= vxres || modded.dy >= vyres)
194 return;
195
196 if (modded.dx + modded.width > vxres)
197 modded.width = vxres - modded.dx;
198 if (modded.dy + modded.height > vyres)
199 modded.height = vyres - modded.dy;
200
201 unifb_prim_fillrect(info, &modded);
202}
203
204static void unifb_prim_copyarea(struct fb_info *info,
205 const struct fb_copyarea *area)
206{
207 int awidth = area->width;
208 int aheight = area->height;
209 int m_iBpp = info->var.bits_per_pixel;
210 int screen_width = info->var.xres;
211 int src_sel = 2; /* from mem */
212 int pat_sel = 0;
213 int src_x0 = area->sx;
214 int dst_x0 = area->dx;
215 int src_y0 = area->sy;
216 int dst_y0 = area->dy;
217
218 int rop_alpha_sel = 0;
219 int rop_alpha_code = 0xCC;
220 int x_dir = 1;
221 int y_dir = 1;
222
223 int alpha_r = 0;
224 int alpha_sel = 0;
225 int dst_pitch = screen_width * (m_iBpp / 8);
226 int dst_offset = dst_y0 * dst_pitch + dst_x0 * (m_iBpp / 8);
227 int src_pitch = screen_width * (m_iBpp / 8);
228 int src_offset = src_y0 * src_pitch + src_x0 * (m_iBpp / 8);
229 unsigned int command = 0;
230 int clip_region = 0;
231 int clip_en = 1;
232 int tp_en = 0;
233 int top = 0;
234 int bottom = info->var.yres;
235 int right = info->var.xres;
236 int fg_color = 0;
237 int bg_color = 0;
238
239 if (src_x0 < 0)
240 src_x0 = 0;
241 if (src_y0 < 0)
242 src_y0 = 0;
243
244 if (src_y0 - dst_y0 > 0) {
245 y_dir = 1;
246 } else {
247 y_dir = 0;
248 src_offset = (src_y0 + aheight) * src_pitch +
249 src_x0 * (m_iBpp / 8);
250 dst_offset = (dst_y0 + aheight) * dst_pitch +
251 dst_x0 * (m_iBpp / 8);
252 src_y0 += aheight;
253 dst_y0 += aheight;
254 }
255
256 command = (rop_alpha_sel << 26) | (pat_sel << 18) | (src_sel << 16) |
257 (x_dir << 20) | (y_dir << 21) | (command << 24) |
258 (clip_region << 23) | (clip_en << 22) | (tp_en << 27);
259 src_pitch = (dst_pitch << 16) | src_pitch;
260 awidth = awidth | (aheight << 16);
261 alpha_r = ((rop_alpha_code & 0xff) << 8) | (alpha_r & 0xff) |
262 (alpha_sel << 16);
263 src_x0 = (src_x0 & 0x1fff) | ((src_y0 & 0x1fff) << 16);
264 dst_x0 = (dst_x0 & 0x1fff) | ((dst_y0 & 0x1fff) << 16);
265 bottom = (bottom << 16) | right;
266
267 unifb_sync(info);
268
269 writel(src_pitch, UGE_PITCH);
270 writel(src_offset, UGE_SRCSTART);
271 writel(dst_offset, UGE_DSTSTART);
272 writel(awidth, UGE_WIDHEIGHT);
273 writel(top, UGE_CLIP0);
274 writel(bottom, UGE_CLIP1);
275 writel(bg_color, UGE_BCOLOR);
276 writel(fg_color, UGE_FCOLOR);
277 writel(alpha_r, UGE_ROPALPHA);
278 writel(src_x0, UGE_SRCXY);
279 writel(dst_x0, UGE_DSTXY);
280 writel(command, UGE_COMMAND);
281}
282
283static void unifb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
284{
285 struct fb_copyarea modded;
286 u32 vxres, vyres;
287 modded.sx = area->sx;
288 modded.sy = area->sy;
289 modded.dx = area->dx;
290 modded.dy = area->dy;
291 modded.width = area->width;
292 modded.height = area->height;
293
294 if (info->flags & FBINFO_HWACCEL_DISABLED) {
295 sys_copyarea(info, area);
296 return;
297 }
298
299 vxres = info->var.xres_virtual;
300 vyres = info->var.yres_virtual;
301
302 if (!modded.width || !modded.height ||
303 modded.sx >= vxres || modded.sy >= vyres ||
304 modded.dx >= vxres || modded.dy >= vyres)
305 return;
306
307 if (modded.sx + modded.width > vxres)
308 modded.width = vxres - modded.sx;
309 if (modded.dx + modded.width > vxres)
310 modded.width = vxres - modded.dx;
311 if (modded.sy + modded.height > vyres)
312 modded.height = vyres - modded.sy;
313 if (modded.dy + modded.height > vyres)
314 modded.height = vyres - modded.dy;
315
316 unifb_prim_copyarea(info, &modded);
317}
318
319static void unifb_imageblit(struct fb_info *info, const struct fb_image *image)
320{
321 sys_imageblit(info, image);
322}
323
324static u_long get_line_length(int xres_virtual, int bpp)
325{
326 u_long length;
327
328 length = xres_virtual * bpp;
329 length = (length + 31) & ~31;
330 length >>= 3;
331 return length;
332}
333
334/*
335 * Setting the video mode has been split into two parts.
336 * First part, xxxfb_check_var, must not write anything
337 * to hardware, it should only verify and adjust var.
338 * This means it doesn't alter par but it does use hardware
339 * data from it to check this var.
340 */
341static int unifb_check_var(struct fb_var_screeninfo *var,
342 struct fb_info *info)
343{
344 u_long line_length;
345
346 /*
347 * FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
348 * as FB_VMODE_SMOOTH_XPAN is only used internally
349 */
350
351 if (var->vmode & FB_VMODE_CONUPDATE) {
352 var->vmode |= FB_VMODE_YWRAP;
353 var->xoffset = info->var.xoffset;
354 var->yoffset = info->var.yoffset;
355 }
356
357 /*
358 * Some very basic checks
359 */
360 if (!var->xres)
361 var->xres = 1;
362 if (!var->yres)
363 var->yres = 1;
364 if (var->xres > var->xres_virtual)
365 var->xres_virtual = var->xres;
366 if (var->yres > var->yres_virtual)
367 var->yres_virtual = var->yres;
368 if (var->bits_per_pixel <= 1)
369 var->bits_per_pixel = 1;
370 else if (var->bits_per_pixel <= 8)
371 var->bits_per_pixel = 8;
372 else if (var->bits_per_pixel <= 16)
373 var->bits_per_pixel = 16;
374 else if (var->bits_per_pixel <= 24)
375 var->bits_per_pixel = 24;
376 else if (var->bits_per_pixel <= 32)
377 var->bits_per_pixel = 32;
378 else
379 return -EINVAL;
380
381 if (var->xres_virtual < var->xoffset + var->xres)
382 var->xres_virtual = var->xoffset + var->xres;
383 if (var->yres_virtual < var->yoffset + var->yres)
384 var->yres_virtual = var->yoffset + var->yres;
385
386 /*
387 * Memory limit
388 */
389 line_length =
390 get_line_length(var->xres_virtual, var->bits_per_pixel);
391 if (line_length * var->yres_virtual > UNIFB_MEMSIZE)
392 return -ENOMEM;
393
394 /*
395 * Now that we checked it we alter var. The reason being is that the
396 * video mode passed in might not work but slight changes to it might
397 * make it work. This way we let the user know what is acceptable.
398 */
399 switch (var->bits_per_pixel) {
400 case 1:
401 case 8:
402 var->red.offset = 0;
403 var->red.length = 8;
404 var->green.offset = 0;
405 var->green.length = 8;
406 var->blue.offset = 0;
407 var->blue.length = 8;
408 var->transp.offset = 0;
409 var->transp.length = 0;
410 break;
411 case 16: /* RGBA 5551 */
412 if (var->transp.length) {
413 var->red.offset = 0;
414 var->red.length = 5;
415 var->green.offset = 5;
416 var->green.length = 5;
417 var->blue.offset = 10;
418 var->blue.length = 5;
419 var->transp.offset = 15;
420 var->transp.length = 1;
421 } else { /* RGB 565 */
422 var->red.offset = 11;
423 var->red.length = 5;
424 var->green.offset = 5;
425 var->green.length = 6;
426 var->blue.offset = 0;
427 var->blue.length = 5;
428 var->transp.offset = 0;
429 var->transp.length = 0;
430 }
431 break;
432 case 24: /* RGB 888 */
433 var->red.offset = 0;
434 var->red.length = 8;
435 var->green.offset = 8;
436 var->green.length = 8;
437 var->blue.offset = 16;
438 var->blue.length = 8;
439 var->transp.offset = 0;
440 var->transp.length = 0;
441 break;
442 case 32: /* RGBA 8888 */
443 var->red.offset = 16;
444 var->red.length = 8;
445 var->green.offset = 8;
446 var->green.length = 8;
447 var->blue.offset = 0;
448 var->blue.length = 8;
449 var->transp.offset = 24;
450 var->transp.length = 8;
451 break;
452 }
453 var->red.msb_right = 0;
454 var->green.msb_right = 0;
455 var->blue.msb_right = 0;
456 var->transp.msb_right = 0;
457
458 return 0;
459}
460
461/*
462 * This routine actually sets the video mode. It's in here where we
463 * the hardware state info->par and fix which can be affected by the
464 * change in par. For this driver it doesn't do much.
465 */
466static int unifb_set_par(struct fb_info *info)
467{
468 int hTotal, vTotal, hSyncStart, hSyncEnd, vSyncStart, vSyncEnd;
469 int format;
470
471#ifdef CONFIG_PUV3_PM
472 struct clk *clk_vga;
473 u32 pixclk = 0;
474 int i;
475
476 for (i = 0; i <= 10; i++) {
477 if (info->var.xres == unifb_modes[i].xres
478 && info->var.yres == unifb_modes[i].yres
479 && info->var.upper_margin == unifb_modes[i].upper_margin
480 && info->var.lower_margin == unifb_modes[i].lower_margin
481 && info->var.left_margin == unifb_modes[i].left_margin
482 && info->var.right_margin == unifb_modes[i].right_margin
483 && info->var.hsync_len == unifb_modes[i].hsync_len
484 && info->var.vsync_len == unifb_modes[i].vsync_len) {
485 pixclk = unifb_modes[i].pixclock;
486 break;
487 }
488 }
489
490 /* set clock rate */
491 clk_vga = clk_get(info->device, "VGA_CLK");
492 if (clk_vga == ERR_PTR(-ENOENT))
493 return -ENOENT;
494
495 if (pixclk != 0) {
496 if (clk_set_rate(clk_vga, pixclk)) { /* set clock failed */
497 info->fix = unifb_fix;
498 info->var = unifb_default;
499 if (clk_set_rate(clk_vga, unifb_default.pixclock))
500 return -EINVAL;
501 }
502 }
503#endif
504
505 info->fix.line_length = get_line_length(info->var.xres_virtual,
506 info->var.bits_per_pixel);
507
508 hSyncStart = info->var.xres + info->var.right_margin;
509 hSyncEnd = hSyncStart + info->var.hsync_len;
510 hTotal = hSyncEnd + info->var.left_margin;
511
512 vSyncStart = info->var.yres + info->var.lower_margin;
513 vSyncEnd = vSyncStart + info->var.vsync_len;
514 vTotal = vSyncEnd + info->var.upper_margin;
515
516 switch (info->var.bits_per_pixel) {
517 case 8:
518 format = UDE_CFG_DST8;
519 break;
520 case 16:
521 format = UDE_CFG_DST16;
522 break;
523 case 24:
524 format = UDE_CFG_DST24;
525 break;
526 case 32:
527 format = UDE_CFG_DST32;
528 break;
529 default:
530 return -EINVAL;
531 }
532
533 writel(info->fix.smem_start, UDE_FSA);
534 writel(info->var.yres, UDE_LS);
535 writel(get_line_length(info->var.xres,
536 info->var.bits_per_pixel) >> 3, UDE_PS);
537 /* >> 3 for hardware required. */
538 writel((hTotal << 16) | (info->var.xres), UDE_HAT);
539 writel(((hTotal - 1) << 16) | (info->var.xres - 1), UDE_HBT);
540 writel(((hSyncEnd - 1) << 16) | (hSyncStart - 1), UDE_HST);
541 writel((vTotal << 16) | (info->var.yres), UDE_VAT);
542 writel(((vTotal - 1) << 16) | (info->var.yres - 1), UDE_VBT);
543 writel(((vSyncEnd - 1) << 16) | (vSyncStart - 1), UDE_VST);
544 writel(UDE_CFG_GDEN_ENABLE | UDE_CFG_TIMEUP_ENABLE
545 | format | 0xC0000001, UDE_CFG);
546
547 return 0;
548}
549
550/*
551 * Set a single color register. The values supplied are already
552 * rounded down to the hardware's capabilities (according to the
553 * entries in the var structure). Return != 0 for invalid regno.
554 */
555static int unifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
556 u_int transp, struct fb_info *info)
557{
558 if (regno >= 256) /* no. of hw registers */
559 return 1;
560
561 /* grayscale works only partially under directcolor */
562 if (info->var.grayscale) {
563 /* grayscale = 0.30*R + 0.59*G + 0.11*B */
564 red = green = blue =
565 (red * 77 + green * 151 + blue * 28) >> 8;
566 }
567
568#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
569 switch (info->fix.visual) {
570 case FB_VISUAL_TRUECOLOR:
571 case FB_VISUAL_PSEUDOCOLOR:
572 red = CNVT_TOHW(red, info->var.red.length);
573 green = CNVT_TOHW(green, info->var.green.length);
574 blue = CNVT_TOHW(blue, info->var.blue.length);
575 transp = CNVT_TOHW(transp, info->var.transp.length);
576 break;
577 case FB_VISUAL_DIRECTCOLOR:
578 red = CNVT_TOHW(red, 8); /* expect 8 bit DAC */
579 green = CNVT_TOHW(green, 8);
580 blue = CNVT_TOHW(blue, 8);
581 /* hey, there is bug in transp handling... */
582 transp = CNVT_TOHW(transp, 8);
583 break;
584 }
585#undef CNVT_TOHW
586 /* Truecolor has hardware independent palette */
587 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
588 u32 v;
589
590 if (regno >= 16)
591 return 1;
592
593 v = (red << info->var.red.offset) |
594 (green << info->var.green.offset) |
595 (blue << info->var.blue.offset) |
596 (transp << info->var.transp.offset);
597 switch (info->var.bits_per_pixel) {
598 case 8:
599 break;
600 case 16:
601 case 24:
602 case 32:
603 ((u32 *) (info->pseudo_palette))[regno] = v;
604 break;
605 default:
606 return 1;
607 }
608 return 0;
609 }
610 return 0;
611}
612
613/*
614 * Pan or Wrap the Display
615 *
616 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
617 */
618static int unifb_pan_display(struct fb_var_screeninfo *var,
619 struct fb_info *info)
620{
621 if (var->vmode & FB_VMODE_YWRAP) {
622 if (var->yoffset < 0
623 || var->yoffset >= info->var.yres_virtual
624 || var->xoffset)
625 return -EINVAL;
626 } else {
627 if (var->xoffset + var->xres > info->var.xres_virtual ||
628 var->yoffset + var->yres > info->var.yres_virtual)
629 return -EINVAL;
630 }
631 info->var.xoffset = var->xoffset;
632 info->var.yoffset = var->yoffset;
633 if (var->vmode & FB_VMODE_YWRAP)
634 info->var.vmode |= FB_VMODE_YWRAP;
635 else
636 info->var.vmode &= ~FB_VMODE_YWRAP;
637 return 0;
638}
639
640int unifb_mmap(struct fb_info *info,
641 struct vm_area_struct *vma)
642{
643 unsigned long size = vma->vm_end - vma->vm_start;
644 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
645 unsigned long pos = info->fix.smem_start + offset;
646
647 if (offset + size > info->fix.smem_len)
648 return -EINVAL;
649
650 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
651
652 if (io_remap_pfn_range(vma, vma->vm_start, pos >> PAGE_SHIFT, size,
653 vma->vm_page_prot))
654 return -EAGAIN;
655
656 vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */
657 return 0;
658
659}
660
661static struct fb_ops unifb_ops = {
662 .fb_read = fb_sys_read,
663 .fb_write = fb_sys_write,
664 .fb_check_var = unifb_check_var,
665 .fb_set_par = unifb_set_par,
666 .fb_setcolreg = unifb_setcolreg,
667 .fb_pan_display = unifb_pan_display,
668 .fb_fillrect = unifb_fillrect,
669 .fb_copyarea = unifb_copyarea,
670 .fb_imageblit = unifb_imageblit,
671 .fb_mmap = unifb_mmap,
672};
673
674/*
675 * Initialisation
676 */
677static int unifb_probe(struct platform_device *dev)
678{
679 struct fb_info *info;
680 u32 unifb_regs[UNIFB_REGS_NUM];
681 int retval = -ENOMEM;
682 struct resource *iomem;
683 void *videomemory;
684
685 videomemory = (void *)__get_free_pages(GFP_KERNEL | __GFP_COMP,
686 get_order(UNIFB_MEMSIZE));
687 if (!videomemory)
688 goto err;
689
690 memset(videomemory, 0, UNIFB_MEMSIZE);
691
692 unifb_fix.smem_start = virt_to_phys(videomemory);
693 unifb_fix.smem_len = UNIFB_MEMSIZE;
694
695 iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
696 unifb_fix.mmio_start = iomem->start;
697
698 info = framebuffer_alloc(sizeof(u32)*256, &dev->dev);
699 if (!info)
700 goto err;
701
702 info->screen_base = (char __iomem *)videomemory;
703 info->fbops = &unifb_ops;
704
705 retval = fb_find_mode(&info->var, info, NULL,
706 unifb_modes, 10, &unifb_modes[0], 16);
707
708 if (!retval || (retval == 4))
709 info->var = unifb_default;
710
711 info->fix = unifb_fix;
712 info->pseudo_palette = info->par;
713 info->par = NULL;
714 info->flags = FBINFO_FLAG_DEFAULT;
715#ifdef FB_ACCEL_PUV3_UNIGFX
716 info->fix.accel = FB_ACCEL_PUV3_UNIGFX;
717#endif
718
719 retval = fb_alloc_cmap(&info->cmap, 256, 0);
720 if (retval < 0)
721 goto err1;
722
723 retval = register_framebuffer(info);
724 if (retval < 0)
725 goto err2;
726 platform_set_drvdata(dev, info);
727 platform_device_add_data(dev, unifb_regs, sizeof(u32) * UNIFB_REGS_NUM);
728
729 printk(KERN_INFO
730 "fb%d: Virtual frame buffer device, using %dM of video memory\n",
731 info->node, UNIFB_MEMSIZE >> 20);
732 return 0;
733err2:
734 fb_dealloc_cmap(&info->cmap);
735err1:
736 framebuffer_release(info);
737err:
738 return retval;
739}
740
741static int unifb_remove(struct platform_device *dev)
742{
743 struct fb_info *info = platform_get_drvdata(dev);
744
745 if (info) {
746 unregister_framebuffer(info);
747 fb_dealloc_cmap(&info->cmap);
748 framebuffer_release(info);
749 }
750 return 0;
751}
752
753#ifdef CONFIG_PM
754static int unifb_resume(struct platform_device *dev)
755{
756 int rc = 0;
757 u32 *unifb_regs = dev->dev.platform_data;
758
759 if (dev->dev.power.power_state.event == PM_EVENT_ON)
760 return 0;
761
762 console_lock();
763
764 if (dev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
765 writel(unifb_regs[0], UDE_FSA);
766 writel(unifb_regs[1], UDE_LS);
767 writel(unifb_regs[2], UDE_PS);
768 writel(unifb_regs[3], UDE_HAT);
769 writel(unifb_regs[4], UDE_HBT);
770 writel(unifb_regs[5], UDE_HST);
771 writel(unifb_regs[6], UDE_VAT);
772 writel(unifb_regs[7], UDE_VBT);
773 writel(unifb_regs[8], UDE_VST);
774 writel(unifb_regs[9], UDE_CFG);
775 }
776 dev->dev.power.power_state = PMSG_ON;
777
778 console_unlock();
779
780 return rc;
781}
782
783static int unifb_suspend(struct platform_device *dev, pm_message_t mesg)
784{
785 u32 *unifb_regs = dev->dev.platform_data;
786
787 unifb_regs[0] = readl(UDE_FSA);
788 unifb_regs[1] = readl(UDE_LS);
789 unifb_regs[2] = readl(UDE_PS);
790 unifb_regs[3] = readl(UDE_HAT);
791 unifb_regs[4] = readl(UDE_HBT);
792 unifb_regs[5] = readl(UDE_HST);
793 unifb_regs[6] = readl(UDE_VAT);
794 unifb_regs[7] = readl(UDE_VBT);
795 unifb_regs[8] = readl(UDE_VST);
796 unifb_regs[9] = readl(UDE_CFG);
797
798 if (mesg.event == dev->dev.power.power_state.event)
799 return 0;
800
801 switch (mesg.event) {
802 case PM_EVENT_FREEZE: /* about to take snapshot */
803 case PM_EVENT_PRETHAW: /* before restoring snapshot */
804 goto done;
805 }
806
807 console_lock();
808
809 /* do nothing... */
810
811 console_unlock();
812
813done:
814 dev->dev.power.power_state = mesg;
815
816 return 0;
817}
818#else
819#define unifb_resume NULL
820#define unifb_suspend NULL
821#endif
822
823static struct platform_driver unifb_driver = {
824 .probe = unifb_probe,
825 .remove = unifb_remove,
826 .resume = unifb_resume,
827 .suspend = unifb_suspend,
828 .driver = {
829 .name = "PKUnity-v3-UNIGFX",
830 },
831};
832
833static int __init unifb_init(void)
834{
835#ifndef MODULE
836 if (fb_get_options("unifb", NULL))
837 return -ENODEV;
838#endif
839
840 return platform_driver_register(&unifb_driver);
841}
842
843module_init(unifb_init);
844
845static void __exit unifb_exit(void)
846{
847 platform_driver_unregister(&unifb_driver);
848}
849
850module_exit(unifb_exit);
851
852MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c
index 6b93ef93cb12..804000183c5e 100644
--- a/drivers/video/fb_defio.c
+++ b/drivers/video/fb_defio.c
@@ -75,7 +75,7 @@ int fb_deferred_io_fsync(struct file *file, int datasync)
75 return 0; 75 return 0;
76 76
77 /* Kill off the delayed work */ 77 /* Kill off the delayed work */
78 cancel_rearming_delayed_work(&info->deferred_work); 78 cancel_delayed_work_sync(&info->deferred_work);
79 79
80 /* Run it immediately */ 80 /* Run it immediately */
81 return schedule_delayed_work(&info->deferred_work, 0); 81 return schedule_delayed_work(&info->deferred_work, 0);
diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c
index f53b9f1d6aba..5c3960da755a 100644
--- a/drivers/video/fbcmap.c
+++ b/drivers/video/fbcmap.c
@@ -80,6 +80,7 @@ static const struct fb_cmap default_16_colors = {
80 * @cmap: frame buffer colormap structure 80 * @cmap: frame buffer colormap structure
81 * @len: length of @cmap 81 * @len: length of @cmap
82 * @transp: boolean, 1 if there is transparency, 0 otherwise 82 * @transp: boolean, 1 if there is transparency, 0 otherwise
83 * @flags: flags for kmalloc memory allocation
83 * 84 *
84 * Allocates memory for a colormap @cmap. @len is the 85 * Allocates memory for a colormap @cmap. @len is the
85 * number of entries in the palette. 86 * number of entries in the palette.
@@ -88,34 +89,48 @@ static const struct fb_cmap default_16_colors = {
88 * 89 *
89 */ 90 */
90 91
91int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp) 92int fb_alloc_cmap_gfp(struct fb_cmap *cmap, int len, int transp, gfp_t flags)
92{ 93{
93 int size = len*sizeof(u16); 94 int size = len * sizeof(u16);
94 95 int ret = -ENOMEM;
95 if (cmap->len != len) { 96
96 fb_dealloc_cmap(cmap); 97 if (cmap->len != len) {
97 if (!len) 98 fb_dealloc_cmap(cmap);
98 return 0; 99 if (!len)
99 if (!(cmap->red = kmalloc(size, GFP_ATOMIC))) 100 return 0;
100 goto fail; 101
101 if (!(cmap->green = kmalloc(size, GFP_ATOMIC))) 102 cmap->red = kmalloc(size, flags);
102 goto fail; 103 if (!cmap->red)
103 if (!(cmap->blue = kmalloc(size, GFP_ATOMIC))) 104 goto fail;
104 goto fail; 105 cmap->green = kmalloc(size, flags);
105 if (transp) { 106 if (!cmap->green)
106 if (!(cmap->transp = kmalloc(size, GFP_ATOMIC))) 107 goto fail;
108 cmap->blue = kmalloc(size, flags);
109 if (!cmap->blue)
110 goto fail;
111 if (transp) {
112 cmap->transp = kmalloc(size, flags);
113 if (!cmap->transp)
114 goto fail;
115 } else {
116 cmap->transp = NULL;
117 }
118 }
119 cmap->start = 0;
120 cmap->len = len;
121 ret = fb_copy_cmap(fb_default_cmap(len), cmap);
122 if (ret)
107 goto fail; 123 goto fail;
108 } else 124 return 0;
109 cmap->transp = NULL;
110 }
111 cmap->start = 0;
112 cmap->len = len;
113 fb_copy_cmap(fb_default_cmap(len), cmap);
114 return 0;
115 125
116fail: 126fail:
117 fb_dealloc_cmap(cmap); 127 fb_dealloc_cmap(cmap);
118 return -ENOMEM; 128 return ret;
129}
130
131int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp)
132{
133 return fb_alloc_cmap_gfp(cmap, len, transp, GFP_ATOMIC);
119} 134}
120 135
121/** 136/**
@@ -250,8 +265,12 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info)
250 int rc, size = cmap->len * sizeof(u16); 265 int rc, size = cmap->len * sizeof(u16);
251 struct fb_cmap umap; 266 struct fb_cmap umap;
252 267
268 if (size < 0 || size < cmap->len)
269 return -E2BIG;
270
253 memset(&umap, 0, sizeof(struct fb_cmap)); 271 memset(&umap, 0, sizeof(struct fb_cmap));
254 rc = fb_alloc_cmap(&umap, cmap->len, cmap->transp != NULL); 272 rc = fb_alloc_cmap_gfp(&umap, cmap->len, cmap->transp != NULL,
273 GFP_KERNEL);
255 if (rc) 274 if (rc)
256 return rc; 275 return rc;
257 if (copy_from_user(umap.red, cmap->red, size) || 276 if (copy_from_user(umap.red, cmap->red, size) ||
diff --git a/drivers/video/fbcvt.c b/drivers/video/fbcvt.c
index 7293eaccd81b..7cb715dfc0e1 100644
--- a/drivers/video/fbcvt.c
+++ b/drivers/video/fbcvt.c
@@ -5,7 +5,7 @@
5 * 5 *
6 * Based from the VESA(TM) Coordinated Video Timing Generator by 6 * Based from the VESA(TM) Coordinated Video Timing Generator by
7 * Graham Loveridge April 9, 2003 available at 7 * Graham Loveridge April 9, 2003 available at
8 * http://www.vesa.org/public/CVT/CVTd6r1.xls 8 * http://www.elo.utfsm.cl/~elo212/docs/CVTd6r1.xls
9 * 9 *
10 * This file is subject to the terms and conditions of the GNU General Public 10 * This file is subject to the terms and conditions of the GNU General Public
11 * License. See the file COPYING in the main directory of this archive 11 * License. See the file COPYING in the main directory of this archive
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index b06647517c0e..5aac00eb1830 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -42,9 +42,34 @@
42 42
43#define FBPIXMAPSIZE (1024 * 8) 43#define FBPIXMAPSIZE (1024 * 8)
44 44
45static DEFINE_MUTEX(registration_lock);
45struct fb_info *registered_fb[FB_MAX] __read_mostly; 46struct fb_info *registered_fb[FB_MAX] __read_mostly;
46int num_registered_fb __read_mostly; 47int num_registered_fb __read_mostly;
47 48
49static struct fb_info *get_fb_info(unsigned int idx)
50{
51 struct fb_info *fb_info;
52
53 if (idx >= FB_MAX)
54 return ERR_PTR(-ENODEV);
55
56 mutex_lock(&registration_lock);
57 fb_info = registered_fb[idx];
58 if (fb_info)
59 atomic_inc(&fb_info->count);
60 mutex_unlock(&registration_lock);
61
62 return fb_info;
63}
64
65static void put_fb_info(struct fb_info *fb_info)
66{
67 if (!atomic_dec_and_test(&fb_info->count))
68 return;
69 if (fb_info->fbops->fb_destroy)
70 fb_info->fbops->fb_destroy(fb_info);
71}
72
48int lock_fb_info(struct fb_info *info) 73int lock_fb_info(struct fb_info *info)
49{ 74{
50 mutex_lock(&info->lock); 75 mutex_lock(&info->lock);
@@ -647,6 +672,7 @@ int fb_show_logo(struct fb_info *info, int rotate) { return 0; }
647 672
648static void *fb_seq_start(struct seq_file *m, loff_t *pos) 673static void *fb_seq_start(struct seq_file *m, loff_t *pos)
649{ 674{
675 mutex_lock(&registration_lock);
650 return (*pos < FB_MAX) ? pos : NULL; 676 return (*pos < FB_MAX) ? pos : NULL;
651} 677}
652 678
@@ -658,6 +684,7 @@ static void *fb_seq_next(struct seq_file *m, void *v, loff_t *pos)
658 684
659static void fb_seq_stop(struct seq_file *m, void *v) 685static void fb_seq_stop(struct seq_file *m, void *v)
660{ 686{
687 mutex_unlock(&registration_lock);
661} 688}
662 689
663static int fb_seq_show(struct seq_file *m, void *v) 690static int fb_seq_show(struct seq_file *m, void *v)
@@ -690,16 +717,33 @@ static const struct file_operations fb_proc_fops = {
690 .release = seq_release, 717 .release = seq_release,
691}; 718};
692 719
693static ssize_t 720/*
694fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) 721 * We hold a reference to the fb_info in file->private_data,
722 * but if the current registered fb has changed, we don't
723 * actually want to use it.
724 *
725 * So look up the fb_info using the inode minor number,
726 * and just verify it against the reference we have.
727 */
728static struct fb_info *file_fb_info(struct file *file)
695{ 729{
696 unsigned long p = *ppos;
697 struct inode *inode = file->f_path.dentry->d_inode; 730 struct inode *inode = file->f_path.dentry->d_inode;
698 int fbidx = iminor(inode); 731 int fbidx = iminor(inode);
699 struct fb_info *info = registered_fb[fbidx]; 732 struct fb_info *info = registered_fb[fbidx];
700 u32 *buffer, *dst; 733
701 u32 __iomem *src; 734 if (info != file->private_data)
702 int c, i, cnt = 0, err = 0; 735 info = NULL;
736 return info;
737}
738
739static ssize_t
740fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
741{
742 unsigned long p = *ppos;
743 struct fb_info *info = file_fb_info(file);
744 u8 *buffer, *dst;
745 u8 __iomem *src;
746 int c, cnt = 0, err = 0;
703 unsigned long total_size; 747 unsigned long total_size;
704 748
705 if (!info || ! info->screen_base) 749 if (!info || ! info->screen_base)
@@ -730,7 +774,7 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
730 if (!buffer) 774 if (!buffer)
731 return -ENOMEM; 775 return -ENOMEM;
732 776
733 src = (u32 __iomem *) (info->screen_base + p); 777 src = (u8 __iomem *) (info->screen_base + p);
734 778
735 if (info->fbops->fb_sync) 779 if (info->fbops->fb_sync)
736 info->fbops->fb_sync(info); 780 info->fbops->fb_sync(info);
@@ -738,17 +782,9 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
738 while (count) { 782 while (count) {
739 c = (count > PAGE_SIZE) ? PAGE_SIZE : count; 783 c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
740 dst = buffer; 784 dst = buffer;
741 for (i = c >> 2; i--; ) 785 fb_memcpy_fromfb(dst, src, c);
742 *dst++ = fb_readl(src++); 786 dst += c;
743 if (c & 3) { 787 src += c;
744 u8 *dst8 = (u8 *) dst;
745 u8 __iomem *src8 = (u8 __iomem *) src;
746
747 for (i = c & 3; i--;)
748 *dst8++ = fb_readb(src8++);
749
750 src = (u32 __iomem *) src8;
751 }
752 788
753 if (copy_to_user(buf, buffer, c)) { 789 if (copy_to_user(buf, buffer, c)) {
754 err = -EFAULT; 790 err = -EFAULT;
@@ -769,12 +805,10 @@ static ssize_t
769fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) 805fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
770{ 806{
771 unsigned long p = *ppos; 807 unsigned long p = *ppos;
772 struct inode *inode = file->f_path.dentry->d_inode; 808 struct fb_info *info = file_fb_info(file);
773 int fbidx = iminor(inode); 809 u8 *buffer, *src;
774 struct fb_info *info = registered_fb[fbidx]; 810 u8 __iomem *dst;
775 u32 *buffer, *src; 811 int c, cnt = 0, err = 0;
776 u32 __iomem *dst;
777 int c, i, cnt = 0, err = 0;
778 unsigned long total_size; 812 unsigned long total_size;
779 813
780 if (!info || !info->screen_base) 814 if (!info || !info->screen_base)
@@ -811,7 +845,7 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
811 if (!buffer) 845 if (!buffer)
812 return -ENOMEM; 846 return -ENOMEM;
813 847
814 dst = (u32 __iomem *) (info->screen_base + p); 848 dst = (u8 __iomem *) (info->screen_base + p);
815 849
816 if (info->fbops->fb_sync) 850 if (info->fbops->fb_sync)
817 info->fbops->fb_sync(info); 851 info->fbops->fb_sync(info);
@@ -825,19 +859,9 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
825 break; 859 break;
826 } 860 }
827 861
828 for (i = c >> 2; i--; ) 862 fb_memcpy_tofb(dst, src, c);
829 fb_writel(*src++, dst++); 863 dst += c;
830 864 src += c;
831 if (c & 3) {
832 u8 *src8 = (u8 *) src;
833 u8 __iomem *dst8 = (u8 __iomem *) dst;
834
835 for (i = c & 3; i--; )
836 fb_writeb(*src8++, dst8++);
837
838 dst = (u32 __iomem *) dst8;
839 }
840
841 *ppos += c; 865 *ppos += c;
842 buf += c; 866 buf += c;
843 cnt += c; 867 cnt += c;
@@ -877,13 +901,13 @@ fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
877 901
878 if ((err = info->fbops->fb_pan_display(var, info))) 902 if ((err = info->fbops->fb_pan_display(var, info)))
879 return err; 903 return err;
880 info->var.xoffset = var->xoffset; 904 info->var.xoffset = var->xoffset;
881 info->var.yoffset = var->yoffset; 905 info->var.yoffset = var->yoffset;
882 if (var->vmode & FB_VMODE_YWRAP) 906 if (var->vmode & FB_VMODE_YWRAP)
883 info->var.vmode |= FB_VMODE_YWRAP; 907 info->var.vmode |= FB_VMODE_YWRAP;
884 else 908 else
885 info->var.vmode &= ~FB_VMODE_YWRAP; 909 info->var.vmode &= ~FB_VMODE_YWRAP;
886 return 0; 910 return 0;
887} 911}
888 912
889static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var, 913static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var,
@@ -1054,11 +1078,11 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
1054 return -EFAULT; 1078 return -EFAULT;
1055 if (!lock_fb_info(info)) 1079 if (!lock_fb_info(info))
1056 return -ENODEV; 1080 return -ENODEV;
1057 acquire_console_sem(); 1081 console_lock();
1058 info->flags |= FBINFO_MISC_USEREVENT; 1082 info->flags |= FBINFO_MISC_USEREVENT;
1059 ret = fb_set_var(info, &var); 1083 ret = fb_set_var(info, &var);
1060 info->flags &= ~FBINFO_MISC_USEREVENT; 1084 info->flags &= ~FBINFO_MISC_USEREVENT;
1061 release_console_sem(); 1085 console_unlock();
1062 unlock_fb_info(info); 1086 unlock_fb_info(info);
1063 if (!ret && copy_to_user(argp, &var, sizeof(var))) 1087 if (!ret && copy_to_user(argp, &var, sizeof(var)))
1064 ret = -EFAULT; 1088 ret = -EFAULT;
@@ -1090,9 +1114,9 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
1090 return -EFAULT; 1114 return -EFAULT;
1091 if (!lock_fb_info(info)) 1115 if (!lock_fb_info(info))
1092 return -ENODEV; 1116 return -ENODEV;
1093 acquire_console_sem(); 1117 console_lock();
1094 ret = fb_pan_display(info, &var); 1118 ret = fb_pan_display(info, &var);
1095 release_console_sem(); 1119 console_unlock();
1096 unlock_fb_info(info); 1120 unlock_fb_info(info);
1097 if (ret == 0 && copy_to_user(argp, &var, sizeof(var))) 1121 if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))
1098 return -EFAULT; 1122 return -EFAULT;
@@ -1137,11 +1161,11 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
1137 case FBIOBLANK: 1161 case FBIOBLANK:
1138 if (!lock_fb_info(info)) 1162 if (!lock_fb_info(info))
1139 return -ENODEV; 1163 return -ENODEV;
1140 acquire_console_sem(); 1164 console_lock();
1141 info->flags |= FBINFO_MISC_USEREVENT; 1165 info->flags |= FBINFO_MISC_USEREVENT;
1142 ret = fb_blank(info, arg); 1166 ret = fb_blank(info, arg);
1143 info->flags &= ~FBINFO_MISC_USEREVENT; 1167 info->flags &= ~FBINFO_MISC_USEREVENT;
1144 release_console_sem(); 1168 console_unlock();
1145 unlock_fb_info(info); 1169 unlock_fb_info(info);
1146 break; 1170 break;
1147 default: 1171 default:
@@ -1159,10 +1183,10 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
1159 1183
1160static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 1184static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1161{ 1185{
1162 struct inode *inode = file->f_path.dentry->d_inode; 1186 struct fb_info *info = file_fb_info(file);
1163 int fbidx = iminor(inode);
1164 struct fb_info *info = registered_fb[fbidx];
1165 1187
1188 if (!info)
1189 return -ENODEV;
1166 return do_fb_ioctl(info, cmd, arg); 1190 return do_fb_ioctl(info, cmd, arg);
1167} 1191}
1168 1192
@@ -1283,12 +1307,13 @@ static int fb_get_fscreeninfo(struct fb_info *info, unsigned int cmd,
1283static long fb_compat_ioctl(struct file *file, unsigned int cmd, 1307static long fb_compat_ioctl(struct file *file, unsigned int cmd,
1284 unsigned long arg) 1308 unsigned long arg)
1285{ 1309{
1286 struct inode *inode = file->f_path.dentry->d_inode; 1310 struct fb_info *info = file_fb_info(file);
1287 int fbidx = iminor(inode); 1311 struct fb_ops *fb;
1288 struct fb_info *info = registered_fb[fbidx];
1289 struct fb_ops *fb = info->fbops;
1290 long ret = -ENOIOCTLCMD; 1312 long ret = -ENOIOCTLCMD;
1291 1313
1314 if (!info)
1315 return -ENODEV;
1316 fb = info->fbops;
1292 switch(cmd) { 1317 switch(cmd) {
1293 case FBIOGET_VSCREENINFO: 1318 case FBIOGET_VSCREENINFO:
1294 case FBIOPUT_VSCREENINFO: 1319 case FBIOPUT_VSCREENINFO:
@@ -1321,16 +1346,18 @@ static long fb_compat_ioctl(struct file *file, unsigned int cmd,
1321static int 1346static int
1322fb_mmap(struct file *file, struct vm_area_struct * vma) 1347fb_mmap(struct file *file, struct vm_area_struct * vma)
1323{ 1348{
1324 int fbidx = iminor(file->f_path.dentry->d_inode); 1349 struct fb_info *info = file_fb_info(file);
1325 struct fb_info *info = registered_fb[fbidx]; 1350 struct fb_ops *fb;
1326 struct fb_ops *fb = info->fbops;
1327 unsigned long off; 1351 unsigned long off;
1328 unsigned long start; 1352 unsigned long start;
1329 u32 len; 1353 u32 len;
1330 1354
1355 if (!info)
1356 return -ENODEV;
1331 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) 1357 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
1332 return -EINVAL; 1358 return -EINVAL;
1333 off = vma->vm_pgoff << PAGE_SHIFT; 1359 off = vma->vm_pgoff << PAGE_SHIFT;
1360 fb = info->fbops;
1334 if (!fb) 1361 if (!fb)
1335 return -ENODEV; 1362 return -ENODEV;
1336 mutex_lock(&info->mm_lock); 1363 mutex_lock(&info->mm_lock);
@@ -1379,14 +1406,16 @@ __releases(&info->lock)
1379 struct fb_info *info; 1406 struct fb_info *info;
1380 int res = 0; 1407 int res = 0;
1381 1408
1382 if (fbidx >= FB_MAX) 1409 info = get_fb_info(fbidx);
1383 return -ENODEV; 1410 if (!info) {
1384 info = registered_fb[fbidx];
1385 if (!info)
1386 request_module("fb%d", fbidx); 1411 request_module("fb%d", fbidx);
1387 info = registered_fb[fbidx]; 1412 info = get_fb_info(fbidx);
1388 if (!info) 1413 if (!info)
1389 return -ENODEV; 1414 return -ENODEV;
1415 }
1416 if (IS_ERR(info))
1417 return PTR_ERR(info);
1418
1390 mutex_lock(&info->lock); 1419 mutex_lock(&info->lock);
1391 if (!try_module_get(info->fbops->owner)) { 1420 if (!try_module_get(info->fbops->owner)) {
1392 res = -ENODEV; 1421 res = -ENODEV;
@@ -1404,6 +1433,8 @@ __releases(&info->lock)
1404#endif 1433#endif
1405out: 1434out:
1406 mutex_unlock(&info->lock); 1435 mutex_unlock(&info->lock);
1436 if (res)
1437 put_fb_info(info);
1407 return res; 1438 return res;
1408} 1439}
1409 1440
@@ -1419,6 +1450,7 @@ __releases(&info->lock)
1419 info->fbops->fb_release(info,1); 1450 info->fbops->fb_release(info,1);
1420 module_put(info->fbops->owner); 1451 module_put(info->fbops->owner);
1421 mutex_unlock(&info->lock); 1452 mutex_unlock(&info->lock);
1453 put_fb_info(info);
1422 return 0; 1454 return 0;
1423} 1455}
1424 1456
@@ -1439,6 +1471,7 @@ static const struct file_operations fb_fops = {
1439#ifdef CONFIG_FB_DEFERRED_IO 1471#ifdef CONFIG_FB_DEFERRED_IO
1440 .fsync = fb_deferred_io_fsync, 1472 .fsync = fb_deferred_io_fsync,
1441#endif 1473#endif
1474 .llseek = default_llseek,
1442}; 1475};
1443 1476
1444struct class *fb_class; 1477struct class *fb_class;
@@ -1475,7 +1508,7 @@ static bool apertures_overlap(struct aperture *gen, struct aperture *hw)
1475 if (gen->base == hw->base) 1508 if (gen->base == hw->base)
1476 return true; 1509 return true;
1477 /* is the generic aperture base inside the hw base->hw base+size */ 1510 /* is the generic aperture base inside the hw base->hw base+size */
1478 if (gen->base > hw->base && gen->base <= hw->base + hw->size) 1511 if (gen->base > hw->base && gen->base < hw->base + hw->size)
1479 return true; 1512 return true;
1480 return false; 1513 return false;
1481} 1514}
@@ -1504,8 +1537,10 @@ static bool fb_do_apertures_overlap(struct apertures_struct *gena,
1504 return false; 1537 return false;
1505} 1538}
1506 1539
1540static int do_unregister_framebuffer(struct fb_info *fb_info);
1541
1507#define VGA_FB_PHYS 0xA0000 1542#define VGA_FB_PHYS 0xA0000
1508void remove_conflicting_framebuffers(struct apertures_struct *a, 1543static void do_remove_conflicting_framebuffers(struct apertures_struct *a,
1509 const char *name, bool primary) 1544 const char *name, bool primary)
1510{ 1545{
1511 int i; 1546 int i;
@@ -1524,46 +1559,35 @@ void remove_conflicting_framebuffers(struct apertures_struct *a,
1524 (primary && gen_aper && gen_aper->count && 1559 (primary && gen_aper && gen_aper->count &&
1525 gen_aper->ranges[0].base == VGA_FB_PHYS)) { 1560 gen_aper->ranges[0].base == VGA_FB_PHYS)) {
1526 1561
1527 printk(KERN_ERR "fb: conflicting fb hw usage " 1562 printk(KERN_INFO "fb: conflicting fb hw usage "
1528 "%s vs %s - removing generic driver\n", 1563 "%s vs %s - removing generic driver\n",
1529 name, registered_fb[i]->fix.id); 1564 name, registered_fb[i]->fix.id);
1530 unregister_framebuffer(registered_fb[i]); 1565 do_unregister_framebuffer(registered_fb[i]);
1531 } 1566 }
1532 } 1567 }
1533} 1568}
1534EXPORT_SYMBOL(remove_conflicting_framebuffers);
1535
1536/**
1537 * register_framebuffer - registers a frame buffer device
1538 * @fb_info: frame buffer info structure
1539 *
1540 * Registers a frame buffer device @fb_info.
1541 *
1542 * Returns negative errno on error, or zero for success.
1543 *
1544 */
1545 1569
1546int 1570static int do_register_framebuffer(struct fb_info *fb_info)
1547register_framebuffer(struct fb_info *fb_info)
1548{ 1571{
1549 int i; 1572 int i;
1550 struct fb_event event; 1573 struct fb_event event;
1551 struct fb_videomode mode; 1574 struct fb_videomode mode;
1552 1575
1553 if (num_registered_fb == FB_MAX)
1554 return -ENXIO;
1555
1556 if (fb_check_foreignness(fb_info)) 1576 if (fb_check_foreignness(fb_info))
1557 return -ENOSYS; 1577 return -ENOSYS;
1558 1578
1559 remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id, 1579 do_remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id,
1560 fb_is_primary_device(fb_info)); 1580 fb_is_primary_device(fb_info));
1561 1581
1582 if (num_registered_fb == FB_MAX)
1583 return -ENXIO;
1584
1562 num_registered_fb++; 1585 num_registered_fb++;
1563 for (i = 0 ; i < FB_MAX; i++) 1586 for (i = 0 ; i < FB_MAX; i++)
1564 if (!registered_fb[i]) 1587 if (!registered_fb[i])
1565 break; 1588 break;
1566 fb_info->node = i; 1589 fb_info->node = i;
1590 atomic_set(&fb_info->count, 1);
1567 mutex_init(&fb_info->lock); 1591 mutex_init(&fb_info->lock);
1568 mutex_init(&fb_info->mm_lock); 1592 mutex_init(&fb_info->mm_lock);
1569 1593
@@ -1609,36 +1633,14 @@ register_framebuffer(struct fb_info *fb_info)
1609 return 0; 1633 return 0;
1610} 1634}
1611 1635
1612 1636static int do_unregister_framebuffer(struct fb_info *fb_info)
1613/**
1614 * unregister_framebuffer - releases a frame buffer device
1615 * @fb_info: frame buffer info structure
1616 *
1617 * Unregisters a frame buffer device @fb_info.
1618 *
1619 * Returns negative errno on error, or zero for success.
1620 *
1621 * This function will also notify the framebuffer console
1622 * to release the driver.
1623 *
1624 * This is meant to be called within a driver's module_exit()
1625 * function. If this is called outside module_exit(), ensure
1626 * that the driver implements fb_open() and fb_release() to
1627 * check that no processes are using the device.
1628 */
1629
1630int
1631unregister_framebuffer(struct fb_info *fb_info)
1632{ 1637{
1633 struct fb_event event; 1638 struct fb_event event;
1634 int i, ret = 0; 1639 int i, ret = 0;
1635 1640
1636 i = fb_info->node; 1641 i = fb_info->node;
1637 if (!registered_fb[i]) { 1642 if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)
1638 ret = -EINVAL; 1643 return -EINVAL;
1639 goto done;
1640 }
1641
1642 1644
1643 if (!lock_fb_info(fb_info)) 1645 if (!lock_fb_info(fb_info))
1644 return -ENODEV; 1646 return -ENODEV;
@@ -1646,16 +1648,14 @@ unregister_framebuffer(struct fb_info *fb_info)
1646 ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event); 1648 ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event);
1647 unlock_fb_info(fb_info); 1649 unlock_fb_info(fb_info);
1648 1650
1649 if (ret) { 1651 if (ret)
1650 ret = -EINVAL; 1652 return -EINVAL;
1651 goto done;
1652 }
1653 1653
1654 if (fb_info->pixmap.addr && 1654 if (fb_info->pixmap.addr &&
1655 (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) 1655 (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
1656 kfree(fb_info->pixmap.addr); 1656 kfree(fb_info->pixmap.addr);
1657 fb_destroy_modelist(&fb_info->modelist); 1657 fb_destroy_modelist(&fb_info->modelist);
1658 registered_fb[i]=NULL; 1658 registered_fb[i] = NULL;
1659 num_registered_fb--; 1659 num_registered_fb--;
1660 fb_cleanup_device(fb_info); 1660 fb_cleanup_device(fb_info);
1661 device_destroy(fb_class, MKDEV(FB_MAJOR, i)); 1661 device_destroy(fb_class, MKDEV(FB_MAJOR, i));
@@ -1663,9 +1663,65 @@ unregister_framebuffer(struct fb_info *fb_info)
1663 fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); 1663 fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
1664 1664
1665 /* this may free fb info */ 1665 /* this may free fb info */
1666 if (fb_info->fbops->fb_destroy) 1666 put_fb_info(fb_info);
1667 fb_info->fbops->fb_destroy(fb_info); 1667 return 0;
1668done: 1668}
1669
1670void remove_conflicting_framebuffers(struct apertures_struct *a,
1671 const char *name, bool primary)
1672{
1673 mutex_lock(&registration_lock);
1674 do_remove_conflicting_framebuffers(a, name, primary);
1675 mutex_unlock(&registration_lock);
1676}
1677EXPORT_SYMBOL(remove_conflicting_framebuffers);
1678
1679/**
1680 * register_framebuffer - registers a frame buffer device
1681 * @fb_info: frame buffer info structure
1682 *
1683 * Registers a frame buffer device @fb_info.
1684 *
1685 * Returns negative errno on error, or zero for success.
1686 *
1687 */
1688int
1689register_framebuffer(struct fb_info *fb_info)
1690{
1691 int ret;
1692
1693 mutex_lock(&registration_lock);
1694 ret = do_register_framebuffer(fb_info);
1695 mutex_unlock(&registration_lock);
1696
1697 return ret;
1698}
1699
1700/**
1701 * unregister_framebuffer - releases a frame buffer device
1702 * @fb_info: frame buffer info structure
1703 *
1704 * Unregisters a frame buffer device @fb_info.
1705 *
1706 * Returns negative errno on error, or zero for success.
1707 *
1708 * This function will also notify the framebuffer console
1709 * to release the driver.
1710 *
1711 * This is meant to be called within a driver's module_exit()
1712 * function. If this is called outside module_exit(), ensure
1713 * that the driver implements fb_open() and fb_release() to
1714 * check that no processes are using the device.
1715 */
1716int
1717unregister_framebuffer(struct fb_info *fb_info)
1718{
1719 int ret;
1720
1721 mutex_lock(&registration_lock);
1722 ret = do_unregister_framebuffer(fb_info);
1723 mutex_unlock(&registration_lock);
1724
1669 return ret; 1725 return ret;
1670} 1726}
1671 1727
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 563a98b88e9b..4f57485f8c54 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -973,6 +973,90 @@ void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
973 DPRINTK("========================================\n"); 973 DPRINTK("========================================\n");
974} 974}
975 975
976/**
977 * fb_edid_add_monspecs() - add monitor video modes from E-EDID data
978 * @edid: 128 byte array with an E-EDID block
979 * @spacs: monitor specs to be extended
980 */
981void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs)
982{
983 unsigned char *block;
984 struct fb_videomode *m;
985 int num = 0, i;
986 u8 svd[64], edt[(128 - 4) / DETAILED_TIMING_DESCRIPTION_SIZE];
987 u8 pos = 4, svd_n = 0;
988
989 if (!edid)
990 return;
991
992 if (!edid_checksum(edid))
993 return;
994
995 if (edid[0] != 0x2 ||
996 edid[2] < 4 || edid[2] > 128 - DETAILED_TIMING_DESCRIPTION_SIZE)
997 return;
998
999 DPRINTK(" Short Video Descriptors\n");
1000
1001 while (pos < edid[2]) {
1002 u8 len = edid[pos] & 0x1f, type = (edid[pos] >> 5) & 7;
1003 pr_debug("Data block %u of %u bytes\n", type, len);
1004 if (type == 2)
1005 for (i = pos; i < pos + len; i++) {
1006 u8 idx = edid[pos + i] & 0x7f;
1007 svd[svd_n++] = idx;
1008 pr_debug("N%sative mode #%d\n",
1009 edid[pos + i] & 0x80 ? "" : "on-n", idx);
1010 }
1011 pos += len + 1;
1012 }
1013
1014 block = edid + edid[2];
1015
1016 DPRINTK(" Extended Detailed Timings\n");
1017
1018 for (i = 0; i < (128 - edid[2]) / DETAILED_TIMING_DESCRIPTION_SIZE;
1019 i++, block += DETAILED_TIMING_DESCRIPTION_SIZE)
1020 if (PIXEL_CLOCK)
1021 edt[num++] = block - edid;
1022
1023 /* Yikes, EDID data is totally useless */
1024 if (!(num + svd_n))
1025 return;
1026
1027 m = kzalloc((specs->modedb_len + num + svd_n) *
1028 sizeof(struct fb_videomode), GFP_KERNEL);
1029
1030 if (!m)
1031 return;
1032
1033 memcpy(m, specs->modedb, specs->modedb_len * sizeof(struct fb_videomode));
1034
1035 for (i = specs->modedb_len; i < specs->modedb_len + num; i++) {
1036 get_detailed_timing(edid + edt[i - specs->modedb_len], &m[i]);
1037 if (i == specs->modedb_len)
1038 m[i].flag |= FB_MODE_IS_FIRST;
1039 pr_debug("Adding %ux%u@%u\n", m[i].xres, m[i].yres, m[i].refresh);
1040 }
1041
1042 for (i = specs->modedb_len + num; i < specs->modedb_len + num + svd_n; i++) {
1043 int idx = svd[i - specs->modedb_len - num];
1044 if (!idx || idx > 63) {
1045 pr_warning("Reserved SVD code %d\n", idx);
1046 } else if (idx > ARRAY_SIZE(cea_modes) || !cea_modes[idx].xres) {
1047 pr_warning("Unimplemented SVD code %d\n", idx);
1048 } else {
1049 memcpy(&m[i], cea_modes + idx, sizeof(m[i]));
1050 pr_debug("Adding SVD #%d: %ux%u@%u\n", idx,
1051 m[i].xres, m[i].yres, m[i].refresh);
1052 }
1053 }
1054
1055 kfree(specs->modedb);
1056 specs->modedb = m;
1057 specs->modedb_len = specs->modedb_len + num + svd_n;
1058}
1059
976/* 1060/*
977 * VESA Generalized Timing Formula (GTF) 1061 * VESA Generalized Timing Formula (GTF)
978 */ 1062 */
@@ -1289,6 +1373,9 @@ void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
1289{ 1373{
1290 specs = NULL; 1374 specs = NULL;
1291} 1375}
1376void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs)
1377{
1378}
1292void fb_destroy_modedb(struct fb_videomode *modedb) 1379void fb_destroy_modedb(struct fb_videomode *modedb)
1293{ 1380{
1294} 1381}
@@ -1396,6 +1483,7 @@ EXPORT_SYMBOL(fb_firmware_edid);
1396 1483
1397EXPORT_SYMBOL(fb_parse_edid); 1484EXPORT_SYMBOL(fb_parse_edid);
1398EXPORT_SYMBOL(fb_edid_to_monspecs); 1485EXPORT_SYMBOL(fb_edid_to_monspecs);
1486EXPORT_SYMBOL(fb_edid_add_monspecs);
1399EXPORT_SYMBOL(fb_get_mode); 1487EXPORT_SYMBOL(fb_get_mode);
1400EXPORT_SYMBOL(fb_validate_mode); 1488EXPORT_SYMBOL(fb_validate_mode);
1401EXPORT_SYMBOL(fb_destroy_modedb); 1489EXPORT_SYMBOL(fb_destroy_modedb);
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index 0a08f1341227..04251ce89184 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -33,7 +33,7 @@
33 * for driver private data (info->par). info->par (if any) will be 33 * for driver private data (info->par). info->par (if any) will be
34 * aligned to sizeof(long). 34 * aligned to sizeof(long).
35 * 35 *
36 * Returns the new structure, or NULL if an error occured. 36 * Returns the new structure, or NULL if an error occurred.
37 * 37 *
38 */ 38 */
39struct fb_info *framebuffer_alloc(size_t size, struct device *dev) 39struct fb_info *framebuffer_alloc(size_t size, struct device *dev)
@@ -90,11 +90,11 @@ static int activate(struct fb_info *fb_info, struct fb_var_screeninfo *var)
90 int err; 90 int err;
91 91
92 var->activate |= FB_ACTIVATE_FORCE; 92 var->activate |= FB_ACTIVATE_FORCE;
93 acquire_console_sem(); 93 console_lock();
94 fb_info->flags |= FBINFO_MISC_USEREVENT; 94 fb_info->flags |= FBINFO_MISC_USEREVENT;
95 err = fb_set_var(fb_info, var); 95 err = fb_set_var(fb_info, var);
96 fb_info->flags &= ~FBINFO_MISC_USEREVENT; 96 fb_info->flags &= ~FBINFO_MISC_USEREVENT;
97 release_console_sem(); 97 console_unlock();
98 if (err) 98 if (err)
99 return err; 99 return err;
100 return 0; 100 return 0;
@@ -175,7 +175,7 @@ static ssize_t store_modes(struct device *device,
175 if (i * sizeof(struct fb_videomode) != count) 175 if (i * sizeof(struct fb_videomode) != count)
176 return -EINVAL; 176 return -EINVAL;
177 177
178 acquire_console_sem(); 178 console_lock();
179 list_splice(&fb_info->modelist, &old_list); 179 list_splice(&fb_info->modelist, &old_list);
180 fb_videomode_to_modelist((const struct fb_videomode *)buf, i, 180 fb_videomode_to_modelist((const struct fb_videomode *)buf, i,
181 &fb_info->modelist); 181 &fb_info->modelist);
@@ -185,7 +185,7 @@ static ssize_t store_modes(struct device *device,
185 } else 185 } else
186 fb_destroy_modelist(&old_list); 186 fb_destroy_modelist(&old_list);
187 187
188 release_console_sem(); 188 console_unlock();
189 189
190 return 0; 190 return 0;
191} 191}
@@ -301,11 +301,11 @@ static ssize_t store_blank(struct device *device,
301 char *last = NULL; 301 char *last = NULL;
302 int err; 302 int err;
303 303
304 acquire_console_sem(); 304 console_lock();
305 fb_info->flags |= FBINFO_MISC_USEREVENT; 305 fb_info->flags |= FBINFO_MISC_USEREVENT;
306 err = fb_blank(fb_info, simple_strtoul(buf, &last, 0)); 306 err = fb_blank(fb_info, simple_strtoul(buf, &last, 0));
307 fb_info->flags &= ~FBINFO_MISC_USEREVENT; 307 fb_info->flags &= ~FBINFO_MISC_USEREVENT;
308 release_console_sem(); 308 console_unlock();
309 if (err < 0) 309 if (err < 0)
310 return err; 310 return err;
311 return count; 311 return count;
@@ -364,9 +364,9 @@ static ssize_t store_pan(struct device *device,
364 return -EINVAL; 364 return -EINVAL;
365 var.yoffset = simple_strtoul(last, &last, 0); 365 var.yoffset = simple_strtoul(last, &last, 0);
366 366
367 acquire_console_sem(); 367 console_lock();
368 err = fb_pan_display(fb_info, &var); 368 err = fb_pan_display(fb_info, &var);
369 release_console_sem(); 369 console_unlock();
370 370
371 if (err < 0) 371 if (err < 0)
372 return err; 372 return err;
@@ -399,9 +399,9 @@ static ssize_t store_fbstate(struct device *device,
399 399
400 state = simple_strtoul(buf, &last, 0); 400 state = simple_strtoul(buf, &last, 0);
401 401
402 acquire_console_sem(); 402 console_lock();
403 fb_set_suspend(fb_info, (int)state); 403 fb_set_suspend(fb_info, (int)state);
404 release_console_sem(); 404 console_unlock();
405 405
406 return count; 406 return count;
407} 407}
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c
index 6739b2af3bc0..14102a3f70f5 100644
--- a/drivers/video/ffb.c
+++ b/drivers/video/ffb.c
@@ -893,8 +893,7 @@ static void ffb_init_fix(struct fb_info *info)
893 info->fix.accel = FB_ACCEL_SUN_CREATOR; 893 info->fix.accel = FB_ACCEL_SUN_CREATOR;
894} 894}
895 895
896static int __devinit ffb_probe(struct platform_device *op, 896static int __devinit ffb_probe(struct platform_device *op)
897 const struct of_device_id *match)
898{ 897{
899 struct device_node *dp = op->dev.of_node; 898 struct device_node *dp = op->dev.of_node;
900 struct ffb_fbc __iomem *fbc; 899 struct ffb_fbc __iomem *fbc;
@@ -1011,7 +1010,7 @@ out_dealloc_cmap:
1011 fb_dealloc_cmap(&info->cmap); 1010 fb_dealloc_cmap(&info->cmap);
1012 1011
1013out_unmap_dac: 1012out_unmap_dac:
1014 of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc)); 1013 of_iounmap(&op->resource[1], par->dac, sizeof(struct ffb_dac));
1015 1014
1016out_unmap_fbc: 1015out_unmap_fbc:
1017 of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc)); 1016 of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc));
@@ -1052,7 +1051,7 @@ static const struct of_device_id ffb_match[] = {
1052}; 1051};
1053MODULE_DEVICE_TABLE(of, ffb_match); 1052MODULE_DEVICE_TABLE(of, ffb_match);
1054 1053
1055static struct of_platform_driver ffb_driver = { 1054static struct platform_driver ffb_driver = {
1056 .driver = { 1055 .driver = {
1057 .name = "ffb", 1056 .name = "ffb",
1058 .owner = THIS_MODULE, 1057 .owner = THIS_MODULE,
@@ -1067,12 +1066,12 @@ static int __init ffb_init(void)
1067 if (fb_get_options("ffb", NULL)) 1066 if (fb_get_options("ffb", NULL))
1068 return -ENODEV; 1067 return -ENODEV;
1069 1068
1070 return of_register_platform_driver(&ffb_driver); 1069 return platform_driver_register(&ffb_driver);
1071} 1070}
1072 1071
1073static void __exit ffb_exit(void) 1072static void __exit ffb_exit(void)
1074{ 1073{
1075 of_unregister_platform_driver(&ffb_driver); 1074 platform_driver_unregister(&ffb_driver);
1076} 1075}
1077 1076
1078module_init(ffb_init); 1077module_init(ffb_init);
diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c
index 1b0feb8e7244..d0533b7aad79 100644
--- a/drivers/video/fm2fb.c
+++ b/drivers/video/fm2fb.c
@@ -45,7 +45,7 @@
45 * buffer needs an amount of memory of 1.769.472 bytes which 45 * buffer needs an amount of memory of 1.769.472 bytes which
46 * is near to 2 MByte (the allocated address space of Zorro2). 46 * is near to 2 MByte (the allocated address space of Zorro2).
47 * The memory is channel interleaved. That means every channel 47 * The memory is channel interleaved. That means every channel
48 * owns four VRAMs. Unfortunatly most FrameMasters II are 48 * owns four VRAMs. Unfortunately most FrameMasters II are
49 * not assembled with memory for the alpha channel. In this 49 * not assembled with memory for the alpha channel. In this
50 * case it could be possible to add the frame buffer into the 50 * case it could be possible to add the frame buffer into the
51 * normal memory pool. 51 * normal memory pool.
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index 8bbbf08fa3ce..0acc7d65aeaa 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -555,8 +555,6 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
555static int fsl_diu_check_var(struct fb_var_screeninfo *var, 555static int fsl_diu_check_var(struct fb_var_screeninfo *var,
556 struct fb_info *info) 556 struct fb_info *info)
557{ 557{
558 unsigned long htotal, vtotal;
559
560 pr_debug("check_var xres: %d\n", var->xres); 558 pr_debug("check_var xres: %d\n", var->xres);
561 pr_debug("check_var yres: %d\n", var->yres); 559 pr_debug("check_var yres: %d\n", var->yres);
562 560
@@ -635,20 +633,6 @@ static int fsl_diu_check_var(struct fb_var_screeninfo *var,
635 633
636 break; 634 break;
637 } 635 }
638 /* If the pixclock is below the minimum spec'd value then set to
639 * refresh rate for 60Hz since this is supported by most monitors.
640 * Refer to Documentation/fb/ for calculations.
641 */
642 if ((var->pixclock < MIN_PIX_CLK) || (var->pixclock > MAX_PIX_CLK)) {
643 htotal = var->xres + var->right_margin + var->hsync_len +
644 var->left_margin;
645 vtotal = var->yres + var->lower_margin + var->vsync_len +
646 var->upper_margin;
647 var->pixclock = (vtotal * htotal * 6UL) / 100UL;
648 var->pixclock = KHZ2PICOS(var->pixclock);
649 pr_debug("pixclock set for 60Hz refresh = %u ps\n",
650 var->pixclock);
651 }
652 636
653 var->height = -1; 637 var->height = -1;
654 var->width = -1; 638 var->width = -1;
@@ -882,7 +866,7 @@ static inline __u32 CNVT_TOHW(__u32 val, __u32 width)
882 * which needs to be scaled in this function for the hardware. Things to take 866 * which needs to be scaled in this function for the hardware. Things to take
883 * into consideration are how many color registers, if any, are supported with 867 * into consideration are how many color registers, if any, are supported with
884 * the current color visual. With truecolor mode no color palettes are 868 * the current color visual. With truecolor mode no color palettes are
885 * supported. Here a psuedo palette is created which we store the value in 869 * supported. Here a pseudo palette is created which we store the value in
886 * pseudo_palette in struct fb_info. For pseudocolor mode we have a limited 870 * pseudo_palette in struct fb_info. For pseudocolor mode we have a limited
887 * color palette. 871 * color palette.
888 */ 872 */
@@ -1487,8 +1471,7 @@ static ssize_t show_monitor(struct device *device,
1487 return diu_ops.show_monitor_port(machine_data->monitor_port, buf); 1471 return diu_ops.show_monitor_port(machine_data->monitor_port, buf);
1488} 1472}
1489 1473
1490static int __devinit fsl_diu_probe(struct platform_device *ofdev, 1474static int __devinit fsl_diu_probe(struct platform_device *ofdev)
1491 const struct of_device_id *match)
1492{ 1475{
1493 struct device_node *np = ofdev->dev.of_node; 1476 struct device_node *np = ofdev->dev.of_node;
1494 struct mfb_info *mfbi; 1477 struct mfb_info *mfbi;
@@ -1735,7 +1718,7 @@ static struct of_device_id fsl_diu_match[] = {
1735}; 1718};
1736MODULE_DEVICE_TABLE(of, fsl_diu_match); 1719MODULE_DEVICE_TABLE(of, fsl_diu_match);
1737 1720
1738static struct of_platform_driver fsl_diu_driver = { 1721static struct platform_driver fsl_diu_driver = {
1739 .driver = { 1722 .driver = {
1740 .name = "fsl_diu", 1723 .name = "fsl_diu",
1741 .owner = THIS_MODULE, 1724 .owner = THIS_MODULE,
@@ -1797,7 +1780,7 @@ static int __init fsl_diu_init(void)
1797 if (!coherence_data) 1780 if (!coherence_data)
1798 return -ENOMEM; 1781 return -ENOMEM;
1799#endif 1782#endif
1800 ret = of_register_platform_driver(&fsl_diu_driver); 1783 ret = platform_driver_register(&fsl_diu_driver);
1801 if (ret) { 1784 if (ret) {
1802 printk(KERN_ERR 1785 printk(KERN_ERR
1803 "fsl-diu: failed to register platform driver\n"); 1786 "fsl-diu: failed to register platform driver\n");
@@ -1811,7 +1794,7 @@ static int __init fsl_diu_init(void)
1811 1794
1812static void __exit fsl_diu_exit(void) 1795static void __exit fsl_diu_exit(void)
1813{ 1796{
1814 of_unregister_platform_driver(&fsl_diu_driver); 1797 platform_driver_unregister(&fsl_diu_driver);
1815#if defined(CONFIG_NOT_COHERENT_CACHE) 1798#if defined(CONFIG_NOT_COHERENT_CACHE)
1816 vfree(coherence_data); 1799 vfree(coherence_data);
1817#endif 1800#endif
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index ca3355e430bf..7e7b7a9ba274 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -721,7 +721,7 @@ static int gbefb_set_par(struct fb_info *info)
721 721
722 Tiles have the advantage that they can be allocated individually in 722 Tiles have the advantage that they can be allocated individually in
723 memory. However, this mapping is not linear at all, which is not 723 memory. However, this mapping is not linear at all, which is not
724 really convienient. In order to support linear addressing, the GBE 724 really convenient. In order to support linear addressing, the GBE
725 DMA hardware is fooled into thinking the screen is only one tile 725 DMA hardware is fooled into thinking the screen is only one tile
726 large and but has a greater height, so that the DMA transfer covers 726 large and but has a greater height, so that the DMA transfer covers
727 the same region. 727 the same region.
@@ -1143,8 +1143,10 @@ static int __devinit gbefb_probe(struct platform_device *p_dev)
1143 return -ENOMEM; 1143 return -ENOMEM;
1144 1144
1145#ifndef MODULE 1145#ifndef MODULE
1146 if (fb_get_options("gbefb", &options)) 1146 if (fb_get_options("gbefb", &options)) {
1147 return -ENODEV; 1147 ret = -ENODEV;
1148 goto out_release_framebuffer;
1149 }
1148 gbefb_setup(options); 1150 gbefb_setup(options);
1149#endif 1151#endif
1150 1152
diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/geode/gx1fb_core.c
index c6b554f72c6d..5a5d0928df33 100644
--- a/drivers/video/geode/gx1fb_core.c
+++ b/drivers/video/geode/gx1fb_core.c
@@ -29,7 +29,7 @@ static int crt_option = 1;
29static char panel_option[32] = ""; 29static char panel_option[32] = "";
30 30
31/* Modes relevant to the GX1 (taken from modedb.c) */ 31/* Modes relevant to the GX1 (taken from modedb.c) */
32static const struct fb_videomode __initdata gx1_modedb[] = { 32static const struct fb_videomode __devinitdata gx1_modedb[] = {
33 /* 640x480-60 VESA */ 33 /* 640x480-60 VESA */
34 { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, 34 { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2,
35 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, 35 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
@@ -195,7 +195,7 @@ static int gx1fb_blank(int blank_mode, struct fb_info *info)
195 return par->vid_ops->blank_display(info, blank_mode); 195 return par->vid_ops->blank_display(info, blank_mode);
196} 196}
197 197
198static int __init gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *dev) 198static int __devinit gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
199{ 199{
200 struct geodefb_par *par = info->par; 200 struct geodefb_par *par = info->par;
201 unsigned gx_base; 201 unsigned gx_base;
@@ -268,7 +268,7 @@ static struct fb_ops gx1fb_ops = {
268 .fb_imageblit = cfb_imageblit, 268 .fb_imageblit = cfb_imageblit,
269}; 269};
270 270
271static struct fb_info * __init gx1fb_init_fbinfo(struct device *dev) 271static struct fb_info * __devinit gx1fb_init_fbinfo(struct device *dev)
272{ 272{
273 struct geodefb_par *par; 273 struct geodefb_par *par;
274 struct fb_info *info; 274 struct fb_info *info;
@@ -318,7 +318,7 @@ static struct fb_info * __init gx1fb_init_fbinfo(struct device *dev)
318 return info; 318 return info;
319} 319}
320 320
321static int __init gx1fb_probe(struct pci_dev *pdev, const struct pci_device_id *id) 321static int __devinit gx1fb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
322{ 322{
323 struct geodefb_par *par; 323 struct geodefb_par *par;
324 struct fb_info *info; 324 struct fb_info *info;
@@ -382,7 +382,7 @@ static int __init gx1fb_probe(struct pci_dev *pdev, const struct pci_device_id *
382 return ret; 382 return ret;
383} 383}
384 384
385static void gx1fb_remove(struct pci_dev *pdev) 385static void __devexit gx1fb_remove(struct pci_dev *pdev)
386{ 386{
387 struct fb_info *info = pci_get_drvdata(pdev); 387 struct fb_info *info = pci_get_drvdata(pdev);
388 struct geodefb_par *par = info->par; 388 struct geodefb_par *par = info->par;
@@ -441,7 +441,7 @@ static struct pci_driver gx1fb_driver = {
441 .name = "gx1fb", 441 .name = "gx1fb",
442 .id_table = gx1fb_id_table, 442 .id_table = gx1fb_id_table,
443 .probe = gx1fb_probe, 443 .probe = gx1fb_probe,
444 .remove = gx1fb_remove, 444 .remove = __devexit_p(gx1fb_remove),
445}; 445};
446 446
447static int __init gx1fb_init(void) 447static int __init gx1fb_init(void)
@@ -456,7 +456,7 @@ static int __init gx1fb_init(void)
456 return pci_register_driver(&gx1fb_driver); 456 return pci_register_driver(&gx1fb_driver);
457} 457}
458 458
459static void __exit gx1fb_cleanup(void) 459static void __devexit gx1fb_cleanup(void)
460{ 460{
461 pci_unregister_driver(&gx1fb_driver); 461 pci_unregister_driver(&gx1fb_driver);
462} 462}
diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c
index 70b1d9d51c96..b4f19db9bb54 100644
--- a/drivers/video/geode/gxfb_core.c
+++ b/drivers/video/geode/gxfb_core.c
@@ -344,10 +344,10 @@ static int gxfb_suspend(struct pci_dev *pdev, pm_message_t state)
344 struct fb_info *info = pci_get_drvdata(pdev); 344 struct fb_info *info = pci_get_drvdata(pdev);
345 345
346 if (state.event == PM_EVENT_SUSPEND) { 346 if (state.event == PM_EVENT_SUSPEND) {
347 acquire_console_sem(); 347 console_lock();
348 gx_powerdown(info); 348 gx_powerdown(info);
349 fb_set_suspend(info, 1); 349 fb_set_suspend(info, 1);
350 release_console_sem(); 350 console_unlock();
351 } 351 }
352 352
353 /* there's no point in setting PCI states; we emulate PCI, so 353 /* there's no point in setting PCI states; we emulate PCI, so
@@ -361,7 +361,7 @@ static int gxfb_resume(struct pci_dev *pdev)
361 struct fb_info *info = pci_get_drvdata(pdev); 361 struct fb_info *info = pci_get_drvdata(pdev);
362 int ret; 362 int ret;
363 363
364 acquire_console_sem(); 364 console_lock();
365 ret = gx_powerup(info); 365 ret = gx_powerup(info);
366 if (ret) { 366 if (ret) {
367 printk(KERN_ERR "gxfb: power up failed!\n"); 367 printk(KERN_ERR "gxfb: power up failed!\n");
@@ -369,7 +369,7 @@ static int gxfb_resume(struct pci_dev *pdev)
369 } 369 }
370 370
371 fb_set_suspend(info, 0); 371 fb_set_suspend(info, 0);
372 release_console_sem(); 372 console_unlock();
373 return 0; 373 return 0;
374} 374}
375#endif 375#endif
diff --git a/drivers/video/geode/lxfb.h b/drivers/video/geode/lxfb.h
index e4c4d89b7860..cfcd8090f313 100644
--- a/drivers/video/geode/lxfb.h
+++ b/drivers/video/geode/lxfb.h
@@ -22,6 +22,7 @@
22#define DC_HFILT_COUNT 0x100 22#define DC_HFILT_COUNT 0x100
23#define DC_VFILT_COUNT 0x100 23#define DC_VFILT_COUNT 0x100
24#define VP_COEFF_SIZE 0x1000 24#define VP_COEFF_SIZE 0x1000
25#define VP_PAL_COUNT 0x100
25 26
26#define OUTPUT_CRT 0x01 27#define OUTPUT_CRT 0x01
27#define OUTPUT_PANEL 0x02 28#define OUTPUT_PANEL 0x02
@@ -48,7 +49,8 @@ struct lxfb_par {
48 uint64_t vp[VP_REG_COUNT]; 49 uint64_t vp[VP_REG_COUNT];
49 uint64_t fp[FP_REG_COUNT]; 50 uint64_t fp[FP_REG_COUNT];
50 51
51 uint32_t pal[DC_PAL_COUNT]; 52 uint32_t dc_pal[DC_PAL_COUNT];
53 uint32_t vp_pal[VP_PAL_COUNT];
52 uint32_t hcoeff[DC_HFILT_COUNT * 2]; 54 uint32_t hcoeff[DC_HFILT_COUNT * 2];
53 uint32_t vcoeff[DC_VFILT_COUNT]; 55 uint32_t vcoeff[DC_VFILT_COUNT];
54 uint32_t vp_coeff[VP_COEFF_SIZE / 4]; 56 uint32_t vp_coeff[VP_COEFF_SIZE / 4];
@@ -115,7 +117,7 @@ enum gp_registers {
115}; 117};
116 118
117#define GP_BLT_STATUS_CE (1 << 4) /* cmd buf empty */ 119#define GP_BLT_STATUS_CE (1 << 4) /* cmd buf empty */
118#define GP_BLT_STATUS_PB (1 << 0) /* primative busy */ 120#define GP_BLT_STATUS_PB (1 << 0) /* primitive busy */
119 121
120 122
121/* Display Controller registers (table 6-47 from the data book) */ 123/* Display Controller registers (table 6-47 from the data book) */
diff --git a/drivers/video/geode/lxfb_core.c b/drivers/video/geode/lxfb_core.c
index 39bdbedf43b4..416851ca8754 100644
--- a/drivers/video/geode/lxfb_core.c
+++ b/drivers/video/geode/lxfb_core.c
@@ -465,10 +465,10 @@ static int lxfb_suspend(struct pci_dev *pdev, pm_message_t state)
465 struct fb_info *info = pci_get_drvdata(pdev); 465 struct fb_info *info = pci_get_drvdata(pdev);
466 466
467 if (state.event == PM_EVENT_SUSPEND) { 467 if (state.event == PM_EVENT_SUSPEND) {
468 acquire_console_sem(); 468 console_lock();
469 lx_powerdown(info); 469 lx_powerdown(info);
470 fb_set_suspend(info, 1); 470 fb_set_suspend(info, 1);
471 release_console_sem(); 471 console_unlock();
472 } 472 }
473 473
474 /* there's no point in setting PCI states; we emulate PCI, so 474 /* there's no point in setting PCI states; we emulate PCI, so
@@ -482,7 +482,7 @@ static int lxfb_resume(struct pci_dev *pdev)
482 struct fb_info *info = pci_get_drvdata(pdev); 482 struct fb_info *info = pci_get_drvdata(pdev);
483 int ret; 483 int ret;
484 484
485 acquire_console_sem(); 485 console_lock();
486 ret = lx_powerup(info); 486 ret = lx_powerup(info);
487 if (ret) { 487 if (ret) {
488 printk(KERN_ERR "lxfb: power up failed!\n"); 488 printk(KERN_ERR "lxfb: power up failed!\n");
@@ -490,7 +490,7 @@ static int lxfb_resume(struct pci_dev *pdev)
490 } 490 }
491 491
492 fb_set_suspend(info, 0); 492 fb_set_suspend(info, 0);
493 release_console_sem(); 493 console_unlock();
494 return 0; 494 return 0;
495} 495}
496#else 496#else
diff --git a/drivers/video/geode/lxfb_ops.c b/drivers/video/geode/lxfb_ops.c
index bc35a95e59d4..79e9abc72b83 100644
--- a/drivers/video/geode/lxfb_ops.c
+++ b/drivers/video/geode/lxfb_ops.c
@@ -276,10 +276,10 @@ static void lx_graphics_enable(struct fb_info *info)
276 write_fp(par, FP_PT1, 0); 276 write_fp(par, FP_PT1, 0);
277 temp = FP_PT2_SCRC; 277 temp = FP_PT2_SCRC;
278 278
279 if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) 279 if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
280 temp |= FP_PT2_HSP; 280 temp |= FP_PT2_HSP;
281 281
282 if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) 282 if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
283 temp |= FP_PT2_VSP; 283 temp |= FP_PT2_VSP;
284 284
285 write_fp(par, FP_PT2, temp); 285 write_fp(par, FP_PT2, temp);
@@ -610,10 +610,15 @@ static void lx_save_regs(struct lxfb_par *par)
610 memcpy(par->vp, par->vp_regs, sizeof(par->vp)); 610 memcpy(par->vp, par->vp_regs, sizeof(par->vp));
611 memcpy(par->fp, par->vp_regs + VP_FP_START, sizeof(par->fp)); 611 memcpy(par->fp, par->vp_regs + VP_FP_START, sizeof(par->fp));
612 612
613 /* save the palette */ 613 /* save the display controller palette */
614 write_dc(par, DC_PAL_ADDRESS, 0); 614 write_dc(par, DC_PAL_ADDRESS, 0);
615 for (i = 0; i < ARRAY_SIZE(par->pal); i++) 615 for (i = 0; i < ARRAY_SIZE(par->dc_pal); i++)
616 par->pal[i] = read_dc(par, DC_PAL_DATA); 616 par->dc_pal[i] = read_dc(par, DC_PAL_DATA);
617
618 /* save the video processor palette */
619 write_vp(par, VP_PAR, 0);
620 for (i = 0; i < ARRAY_SIZE(par->vp_pal); i++)
621 par->vp_pal[i] = read_vp(par, VP_PDR);
617 622
618 /* save the horizontal filter coefficients */ 623 /* save the horizontal filter coefficients */
619 filt = par->dc[DC_IRQ_FILT_CTL] | DC_IRQ_FILT_CTL_H_FILT_SEL; 624 filt = par->dc[DC_IRQ_FILT_CTL] | DC_IRQ_FILT_CTL_H_FILT_SEL;
@@ -706,8 +711,8 @@ static void lx_restore_display_ctlr(struct lxfb_par *par)
706 711
707 /* restore the palette */ 712 /* restore the palette */
708 write_dc(par, DC_PAL_ADDRESS, 0); 713 write_dc(par, DC_PAL_ADDRESS, 0);
709 for (i = 0; i < ARRAY_SIZE(par->pal); i++) 714 for (i = 0; i < ARRAY_SIZE(par->dc_pal); i++)
710 write_dc(par, DC_PAL_DATA, par->pal[i]); 715 write_dc(par, DC_PAL_DATA, par->dc_pal[i]);
711 716
712 /* restore the horizontal filter coefficients */ 717 /* restore the horizontal filter coefficients */
713 filt = par->dc[DC_IRQ_FILT_CTL] | DC_IRQ_FILT_CTL_H_FILT_SEL; 718 filt = par->dc[DC_IRQ_FILT_CTL] | DC_IRQ_FILT_CTL_H_FILT_SEL;
@@ -751,6 +756,11 @@ static void lx_restore_video_proc(struct lxfb_par *par)
751 } 756 }
752 } 757 }
753 758
759 /* restore video processor palette */
760 write_vp(par, VP_PAR, 0);
761 for (i = 0; i < ARRAY_SIZE(par->vp_pal); i++)
762 write_vp(par, VP_PDR, par->vp_pal[i]);
763
754 /* restore video coeff ram */ 764 /* restore video coeff ram */
755 memcpy(par->vp_regs + VP_VCR, par->vp_coeff, sizeof(par->vp_coeff)); 765 memcpy(par->vp_regs + VP_VCR, par->vp_coeff, sizeof(par->vp_coeff));
756} 766}
diff --git a/drivers/video/hecubafb.c b/drivers/video/hecubafb.c
index c77bcc6ab463..614251a9af91 100644
--- a/drivers/video/hecubafb.c
+++ b/drivers/video/hecubafb.c
@@ -231,10 +231,9 @@ static int __devinit hecubafb_probe(struct platform_device *dev)
231 231
232 videomemorysize = (DPY_W*DPY_H)/8; 232 videomemorysize = (DPY_W*DPY_H)/8;
233 233
234 if (!(videomemory = vmalloc(videomemorysize))) 234 videomemory = vzalloc(videomemorysize);
235 return retval; 235 if (!videomemory)
236 236 goto err_videomem_alloc;
237 memset(videomemory, 0, videomemorysize);
238 237
239 info = framebuffer_alloc(sizeof(struct hecubafb_par), &dev->dev); 238 info = framebuffer_alloc(sizeof(struct hecubafb_par), &dev->dev);
240 if (!info) 239 if (!info)
@@ -276,6 +275,7 @@ err_fbreg:
276 framebuffer_release(info); 275 framebuffer_release(info);
277err_fballoc: 276err_fballoc:
278 vfree(videomemory); 277 vfree(videomemory);
278err_videomem_alloc:
279 module_put(board->owner); 279 module_put(board->owner);
280 return retval; 280 return retval;
281} 281}
@@ -299,7 +299,7 @@ static int __devexit hecubafb_remove(struct platform_device *dev)
299 299
300static struct platform_driver hecubafb_driver = { 300static struct platform_driver hecubafb_driver = {
301 .probe = hecubafb_probe, 301 .probe = hecubafb_probe,
302 .remove = hecubafb_remove, 302 .remove = __devexit_p(hecubafb_remove),
303 .driver = { 303 .driver = {
304 .owner = THIS_MODULE, 304 .owner = THIS_MODULE,
305 .name = "hecubafb", 305 .name = "hecubafb",
diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c
index af8f0f2cc782..4052718eefaa 100644
--- a/drivers/video/hgafb.c
+++ b/drivers/video/hgafb.c
@@ -454,7 +454,6 @@ static int hgafb_blank(int blank_mode, struct fb_info *info)
454/* 454/*
455 * Accel functions 455 * Accel functions
456 */ 456 */
457#ifdef CONFIG_FB_HGA_ACCEL
458static void hgafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 457static void hgafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
459{ 458{
460 u_int rows, y; 459 u_int rows, y;
@@ -466,7 +465,7 @@ static void hgafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
466 dest = rowaddr(info, y) + (rect->dx >> 3); 465 dest = rowaddr(info, y) + (rect->dx >> 3);
467 switch (rect->rop) { 466 switch (rect->rop) {
468 case ROP_COPY: 467 case ROP_COPY:
469 //fb_memset(dest, rect->color, (rect->width >> 3)); 468 memset_io(dest, rect->color, (rect->width >> 3));
470 break; 469 break;
471 case ROP_XOR: 470 case ROP_XOR:
472 fb_writeb(~(fb_readb(dest)), dest); 471 fb_writeb(~(fb_readb(dest)), dest);
@@ -488,7 +487,7 @@ static void hgafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
488 for (rows = area->height; rows--; ) { 487 for (rows = area->height; rows--; ) {
489 src = rowaddr(info, y1) + (area->sx >> 3); 488 src = rowaddr(info, y1) + (area->sx >> 3);
490 dest = rowaddr(info, y2) + (area->dx >> 3); 489 dest = rowaddr(info, y2) + (area->dx >> 3);
491 //fb_memmove(dest, src, (area->width >> 3)); 490 memmove(dest, src, (area->width >> 3));
492 y1++; 491 y1++;
493 y2++; 492 y2++;
494 } 493 }
@@ -499,7 +498,7 @@ static void hgafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
499 for (rows = area->height; rows--;) { 498 for (rows = area->height; rows--;) {
500 src = rowaddr(info, y1) + (area->sx >> 3); 499 src = rowaddr(info, y1) + (area->sx >> 3);
501 dest = rowaddr(info, y2) + (area->dx >> 3); 500 dest = rowaddr(info, y2) + (area->dx >> 3);
502 //fb_memmove(dest, src, (area->width >> 3)); 501 memmove(dest, src, (area->width >> 3));
503 y1--; 502 y1--;
504 y2--; 503 y2--;
505 } 504 }
@@ -511,20 +510,17 @@ static void hgafb_imageblit(struct fb_info *info, const struct fb_image *image)
511 u8 __iomem *dest; 510 u8 __iomem *dest;
512 u8 *cdat = (u8 *) image->data; 511 u8 *cdat = (u8 *) image->data;
513 u_int rows, y = image->dy; 512 u_int rows, y = image->dy;
513 u_int x;
514 u8 d; 514 u8 d;
515 515
516 for (rows = image->height; rows--; y++) { 516 for (rows = image->height; rows--; y++) {
517 d = *cdat++; 517 for (x = 0; x < image->width; x+= 8) {
518 dest = rowaddr(info, y) + (image->dx >> 3); 518 d = *cdat++;
519 fb_writeb(d, dest); 519 dest = rowaddr(info, y) + ((image->dx + x)>> 3);
520 fb_writeb(d, dest);
521 }
520 } 522 }
521} 523}
522#else /* !CONFIG_FB_HGA_ACCEL */
523#define hgafb_fillrect cfb_fillrect
524#define hgafb_copyarea cfb_copyarea
525#define hgafb_imageblit cfb_imageblit
526#endif /* CONFIG_FB_HGA_ACCEL */
527
528 524
529static struct fb_ops hgafb_ops = { 525static struct fb_ops hgafb_ops = {
530 .owner = THIS_MODULE, 526 .owner = THIS_MODULE,
diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c
index c8e280f1bb0b..ebf8495ff198 100644
--- a/drivers/video/hpfb.c
+++ b/drivers/video/hpfb.c
@@ -321,11 +321,11 @@ static int __devinit hpfb_dio_probe(struct dio_dev * d, const struct dio_device_
321 unsigned long paddr, vaddr; 321 unsigned long paddr, vaddr;
322 322
323 paddr = d->resource.start; 323 paddr = d->resource.start;
324 if (!request_mem_region(d->resource.start, d->resource.end - d->resource.start, d->name)) 324 if (!request_mem_region(d->resource.start, resource_size(&d->resource), d->name))
325 return -EBUSY; 325 return -EBUSY;
326 326
327 if (d->scode >= DIOII_SCBASE) { 327 if (d->scode >= DIOII_SCBASE) {
328 vaddr = (unsigned long)ioremap(paddr, d->resource.end - d->resource.start); 328 vaddr = (unsigned long)ioremap(paddr, resource_size(&d->resource));
329 } else { 329 } else {
330 vaddr = paddr + DIO_VIRADDRBASE; 330 vaddr = paddr + DIO_VIRADDRBASE;
331 } 331 }
@@ -344,7 +344,7 @@ static void __devexit hpfb_remove_one(struct dio_dev *d)
344 unregister_framebuffer(&fb_info); 344 unregister_framebuffer(&fb_info);
345 if (d->scode >= DIOII_SCBASE) 345 if (d->scode >= DIOII_SCBASE)
346 iounmap((void *)fb_regs); 346 iounmap((void *)fb_regs);
347 release_mem_region(d->resource.start, d->resource.end - d->resource.start); 347 release_mem_region(d->resource.start, resource_size(&d->resource));
348} 348}
349 349
350static struct dio_device_id hpfb_dio_tbl[] = { 350static struct dio_device_id hpfb_dio_tbl[] = {
diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c
index cd2c728a809b..7db17d0d8a8c 100644
--- a/drivers/video/i810/i810-i2c.c
+++ b/drivers/video/i810/i810-i2c.c
@@ -45,8 +45,10 @@ static void i810i2c_setscl(void *data, int state)
45 struct i810fb_par *par = chan->par; 45 struct i810fb_par *par = chan->par;
46 u8 __iomem *mmio = par->mmio_start_virtual; 46 u8 __iomem *mmio = par->mmio_start_virtual;
47 47
48 i810_writel(mmio, chan->ddc_base, (state ? SCL_VAL_OUT : 0) | SCL_DIR | 48 if (state)
49 SCL_DIR_MASK | SCL_VAL_MASK); 49 i810_writel(mmio, chan->ddc_base, SCL_DIR_MASK | SCL_VAL_MASK);
50 else
51 i810_writel(mmio, chan->ddc_base, SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK);
50 i810_readl(mmio, chan->ddc_base); /* flush posted write */ 52 i810_readl(mmio, chan->ddc_base); /* flush posted write */
51} 53}
52 54
@@ -56,8 +58,10 @@ static void i810i2c_setsda(void *data, int state)
56 struct i810fb_par *par = chan->par; 58 struct i810fb_par *par = chan->par;
57 u8 __iomem *mmio = par->mmio_start_virtual; 59 u8 __iomem *mmio = par->mmio_start_virtual;
58 60
59 i810_writel(mmio, chan->ddc_base, (state ? SDA_VAL_OUT : 0) | SDA_DIR | 61 if (state)
60 SDA_DIR_MASK | SDA_VAL_MASK); 62 i810_writel(mmio, chan->ddc_base, SDA_DIR_MASK | SDA_VAL_MASK);
63 else
64 i810_writel(mmio, chan->ddc_base, SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK);
61 i810_readl(mmio, chan->ddc_base); /* flush posted write */ 65 i810_readl(mmio, chan->ddc_base); /* flush posted write */
62} 66}
63 67
diff --git a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h
index 328ae6c673ec..f37de60ecc59 100644
--- a/drivers/video/i810/i810.h
+++ b/drivers/video/i810/i810.h
@@ -17,7 +17,6 @@
17#include <linux/agp_backend.h> 17#include <linux/agp_backend.h>
18#include <linux/fb.h> 18#include <linux/fb.h>
19#include <linux/i2c.h> 19#include <linux/i2c.h>
20#include <linux/i2c-id.h>
21#include <linux/i2c-algo-bit.h> 20#include <linux/i2c-algo-bit.h>
22#include <video/vga.h> 21#include <video/vga.h>
23 22
diff --git a/drivers/video/i810/i810_accel.c b/drivers/video/i810/i810_accel.c
index f5bedee4310a..7672d2ea9b35 100644
--- a/drivers/video/i810/i810_accel.c
+++ b/drivers/video/i810/i810_accel.c
@@ -112,7 +112,7 @@ static inline int wait_for_engine_idle(struct fb_info *info)
112 * @par: pointer to i810fb_par structure 112 * @par: pointer to i810fb_par structure
113 * 113 *
114 * DESCRIPTION: 114 * DESCRIPTION:
115 * Checks/waits for sufficent space in ringbuffer of size 115 * Checks/waits for sufficient space in ringbuffer of size
116 * space. Returns the tail of the buffer 116 * space. Returns the tail of the buffer
117 */ 117 */
118static inline u32 begin_iring(struct fb_info *info, u32 space) 118static inline u32 begin_iring(struct fb_info *info, u32 space)
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index 5743ea25e818..318f6fb895b2 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -1574,7 +1574,7 @@ static int i810fb_suspend(struct pci_dev *dev, pm_message_t mesg)
1574 return 0; 1574 return 0;
1575 } 1575 }
1576 1576
1577 acquire_console_sem(); 1577 console_lock();
1578 fb_set_suspend(info, 1); 1578 fb_set_suspend(info, 1);
1579 1579
1580 if (info->fbops->fb_sync) 1580 if (info->fbops->fb_sync)
@@ -1587,7 +1587,7 @@ static int i810fb_suspend(struct pci_dev *dev, pm_message_t mesg)
1587 pci_save_state(dev); 1587 pci_save_state(dev);
1588 pci_disable_device(dev); 1588 pci_disable_device(dev);
1589 pci_set_power_state(dev, pci_choose_state(dev, mesg)); 1589 pci_set_power_state(dev, pci_choose_state(dev, mesg));
1590 release_console_sem(); 1590 console_unlock();
1591 1591
1592 return 0; 1592 return 0;
1593} 1593}
@@ -1605,7 +1605,7 @@ static int i810fb_resume(struct pci_dev *dev)
1605 return 0; 1605 return 0;
1606 } 1606 }
1607 1607
1608 acquire_console_sem(); 1608 console_lock();
1609 pci_set_power_state(dev, PCI_D0); 1609 pci_set_power_state(dev, PCI_D0);
1610 pci_restore_state(dev); 1610 pci_restore_state(dev);
1611 1611
@@ -1621,7 +1621,7 @@ static int i810fb_resume(struct pci_dev *dev)
1621 fb_set_suspend (info, 0); 1621 fb_set_suspend (info, 0);
1622 info->fbops->fb_blank(VESA_NO_BLANKING, info); 1622 info->fbops->fb_blank(VESA_NO_BLANKING, info);
1623fail: 1623fail:
1624 release_console_sem(); 1624 console_unlock();
1625 return 0; 1625 return 0;
1626} 1626}
1627/*********************************************************************** 1627/***********************************************************************
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index 5c363d026f64..f135dbead07d 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -53,11 +53,8 @@
53#define LCDC_SIZE 0x04 53#define LCDC_SIZE 0x04
54#define SIZE_XMAX(x) ((((x) >> 4) & 0x3f) << 20) 54#define SIZE_XMAX(x) ((((x) >> 4) & 0x3f) << 20)
55 55
56#ifdef CONFIG_ARCH_MX1 56#define YMAX_MASK (cpu_is_mx1() ? 0x1ff : 0x3ff)
57#define SIZE_YMAX(y) ((y) & 0x1ff) 57#define SIZE_YMAX(y) ((y) & YMAX_MASK)
58#else
59#define SIZE_YMAX(y) ((y) & 0x3ff)
60#endif
61 58
62#define LCDC_VPW 0x08 59#define LCDC_VPW 0x08
63#define VPW_VPW(x) ((x) & 0x3ff) 60#define VPW_VPW(x) ((x) & 0x3ff)
@@ -68,12 +65,6 @@
68#define CPOS_OP (1<<28) 65#define CPOS_OP (1<<28)
69#define CPOS_CXP(x) (((x) & 3ff) << 16) 66#define CPOS_CXP(x) (((x) & 3ff) << 16)
70 67
71#ifdef CONFIG_ARCH_MX1
72#define CPOS_CYP(y) ((y) & 0x1ff)
73#else
74#define CPOS_CYP(y) ((y) & 0x3ff)
75#endif
76
77#define LCDC_LCWHB 0x10 68#define LCDC_LCWHB 0x10
78#define LCWHB_BK_EN (1<<31) 69#define LCWHB_BK_EN (1<<31)
79#define LCWHB_CW(w) (((w) & 0x1f) << 24) 70#define LCWHB_CW(w) (((w) & 0x1f) << 24)
@@ -82,16 +73,6 @@
82 73
83#define LCDC_LCHCC 0x14 74#define LCDC_LCHCC 0x14
84 75
85#ifdef CONFIG_ARCH_MX1
86#define LCHCC_CUR_COL_R(r) (((r) & 0x1f) << 11)
87#define LCHCC_CUR_COL_G(g) (((g) & 0x3f) << 5)
88#define LCHCC_CUR_COL_B(b) ((b) & 0x1f)
89#else
90#define LCHCC_CUR_COL_R(r) (((r) & 0x3f) << 12)
91#define LCHCC_CUR_COL_G(g) (((g) & 0x3f) << 6)
92#define LCHCC_CUR_COL_B(b) ((b) & 0x3f)
93#endif
94
95#define LCDC_PCR 0x18 76#define LCDC_PCR 0x18
96 77
97#define LCDC_HCR 0x1C 78#define LCDC_HCR 0x1C
@@ -118,11 +99,7 @@
118 99
119#define LCDC_RMCR 0x34 100#define LCDC_RMCR 0x34
120 101
121#ifdef CONFIG_ARCH_MX1 102#define RMCR_LCDC_EN_MX1 (1<<1)
122#define RMCR_LCDC_EN (1<<1)
123#else
124#define RMCR_LCDC_EN 0
125#endif
126 103
127#define RMCR_SELF_REF (1<<0) 104#define RMCR_SELF_REF (1<<0)
128 105
@@ -502,6 +479,7 @@ static void imxfb_init_backlight(struct imxfb_info *fbi)
502 479
503 memset(&props, 0, sizeof(struct backlight_properties)); 480 memset(&props, 0, sizeof(struct backlight_properties));
504 props.max_brightness = 0xff; 481 props.max_brightness = 0xff;
482 props.type = BACKLIGHT_RAW;
505 writel(fbi->pwmr, fbi->regs + LCDC_PWMR); 483 writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
506 484
507 bl = backlight_device_register("imxfb-bl", &fbi->pdev->dev, fbi, 485 bl = backlight_device_register("imxfb-bl", &fbi->pdev->dev, fbi,
@@ -538,7 +516,11 @@ static void imxfb_enable_controller(struct imxfb_info *fbi)
538 writel(readl(fbi->regs + LCDC_CPOS) & ~(CPOS_CC0 | CPOS_CC1), 516 writel(readl(fbi->regs + LCDC_CPOS) & ~(CPOS_CC0 | CPOS_CC1),
539 fbi->regs + LCDC_CPOS); 517 fbi->regs + LCDC_CPOS);
540 518
541 writel(RMCR_LCDC_EN, fbi->regs + LCDC_RMCR); 519 /*
520 * RMCR_LCDC_EN_MX1 is present on i.MX1 only, but doesn't hurt
521 * on other SoCs
522 */
523 writel(RMCR_LCDC_EN_MX1, fbi->regs + LCDC_RMCR);
542 524
543 clk_enable(fbi->clk); 525 clk_enable(fbi->clk);
544 526
@@ -623,7 +605,7 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
623 if (var->right_margin > 255) 605 if (var->right_margin > 255)
624 printk(KERN_ERR "%s: invalid right_margin %d\n", 606 printk(KERN_ERR "%s: invalid right_margin %d\n",
625 info->fix.id, var->right_margin); 607 info->fix.id, var->right_margin);
626 if (var->yres < 1 || var->yres > 511) 608 if (var->yres < 1 || var->yres > YMAX_MASK)
627 printk(KERN_ERR "%s: invalid yres %d\n", 609 printk(KERN_ERR "%s: invalid yres %d\n",
628 info->fix.id, var->yres); 610 info->fix.id, var->yres);
629 if (var->vsync_len > 100) 611 if (var->vsync_len > 100)
@@ -874,10 +856,10 @@ failed_platform_init:
874 dma_free_writecombine(&pdev->dev,fbi->map_size,fbi->map_cpu, 856 dma_free_writecombine(&pdev->dev,fbi->map_size,fbi->map_cpu,
875 fbi->map_dma); 857 fbi->map_dma);
876failed_map: 858failed_map:
877 clk_put(fbi->clk);
878failed_getclock:
879 iounmap(fbi->regs); 859 iounmap(fbi->regs);
880failed_ioremap: 860failed_ioremap:
861 clk_put(fbi->clk);
862failed_getclock:
881 release_mem_region(res->start, resource_size(res)); 863 release_mem_region(res->start, resource_size(res));
882failed_req: 864failed_req:
883 kfree(info->pseudo_palette); 865 kfree(info->pseudo_palette);
@@ -977,6 +959,6 @@ static void __exit imxfb_cleanup(void)
977module_init(imxfb_init); 959module_init(imxfb_init);
978module_exit(imxfb_cleanup); 960module_exit(imxfb_cleanup);
979 961
980MODULE_DESCRIPTION("Motorola i.MX framebuffer driver"); 962MODULE_DESCRIPTION("Freescale i.MX framebuffer driver");
981MODULE_AUTHOR("Sascha Hauer, Pengutronix"); 963MODULE_AUTHOR("Sascha Hauer, Pengutronix");
982MODULE_LICENSE("GPL"); 964MODULE_LICENSE("GPL");
diff --git a/drivers/video/intelfb/Makefile b/drivers/video/intelfb/Makefile
index 6c782d3ae1be..f7d631ebee8e 100644
--- a/drivers/video/intelfb/Makefile
+++ b/drivers/video/intelfb/Makefile
@@ -4,7 +4,4 @@ intelfb-y := intelfbdrv.o intelfbhw.o
4intelfb-$(CONFIG_FB_INTEL_I2C) += intelfb_i2c.o 4intelfb-$(CONFIG_FB_INTEL_I2C) += intelfb_i2c.o
5intelfb-objs := $(intelfb-y) 5intelfb-objs := $(intelfb-y)
6 6
7ifdef CONFIG_FB_INTEL_DEBUG 7ccflags-$(CONFIG_FB_INTEL_DEBUG) := -DDEBUG -DREGDUMP
8#EXTRA_CFLAGS += -DDEBUG -DVERBOSE -DREGDUMP
9EXTRA_CFLAGS += -DDEBUG -DREGDUMP
10endif
diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/intelfb/intelfb_i2c.c
index 487f2be47460..3300bd31d9d7 100644
--- a/drivers/video/intelfb/intelfb_i2c.c
+++ b/drivers/video/intelfb/intelfb_i2c.c
@@ -32,7 +32,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
32#include <linux/fb.h> 32#include <linux/fb.h>
33 33
34#include <linux/i2c.h> 34#include <linux/i2c.h>
35#include <linux/i2c-id.h>
36#include <linux/i2c-algo-bit.h> 35#include <linux/i2c-algo-bit.h>
37 36
38#include <asm/io.h> 37#include <asm/io.h>
diff --git a/drivers/video/jz4740_fb.c b/drivers/video/jz4740_fb.c
index 670ecaa0385a..de366937c933 100644
--- a/drivers/video/jz4740_fb.c
+++ b/drivers/video/jz4740_fb.c
@@ -778,9 +778,9 @@ static int jzfb_suspend(struct device *dev)
778{ 778{
779 struct jzfb *jzfb = dev_get_drvdata(dev); 779 struct jzfb *jzfb = dev_get_drvdata(dev);
780 780
781 acquire_console_sem(); 781 console_lock();
782 fb_set_suspend(jzfb->fb, 1); 782 fb_set_suspend(jzfb->fb, 1);
783 release_console_sem(); 783 console_unlock();
784 784
785 mutex_lock(&jzfb->lock); 785 mutex_lock(&jzfb->lock);
786 if (jzfb->is_enabled) 786 if (jzfb->is_enabled)
@@ -800,9 +800,9 @@ static int jzfb_resume(struct device *dev)
800 jzfb_enable(jzfb); 800 jzfb_enable(jzfb);
801 mutex_unlock(&jzfb->lock); 801 mutex_unlock(&jzfb->lock);
802 802
803 acquire_console_sem(); 803 console_lock();
804 fb_set_suspend(jzfb->fb, 0); 804 fb_set_suspend(jzfb->fb, 0);
805 release_console_sem(); 805 console_unlock();
806 806
807 return 0; 807 return 0;
808} 808}
diff --git a/drivers/video/kyro/STG4000OverlayDevice.c b/drivers/video/kyro/STG4000OverlayDevice.c
index a8c9713413e6..0aeeaa10708b 100644
--- a/drivers/video/kyro/STG4000OverlayDevice.c
+++ b/drivers/video/kyro/STG4000OverlayDevice.c
@@ -417,7 +417,7 @@ int SetOverlayViewPort(volatile STG4000REG __iomem *pSTGReg,
417 /***************** Horizontal decimation/scaling ***************************/ 417 /***************** Horizontal decimation/scaling ***************************/
418 418
419 /* 419 /*
420 * Now we handle the horizontal case, this is a simplified verison of 420 * Now we handle the horizontal case, this is a simplified version of
421 * the vertical case in that we decimate by factors of 2. as we are 421 * the vertical case in that we decimate by factors of 2. as we are
422 * working in words we should always be able to decimate by these 422 * working in words we should always be able to decimate by these
423 * factors. as we always have to have a buffer which is aligned to a 423 * factors. as we always have to have a buffer which is aligned to a
diff --git a/drivers/video/kyro/STG4000Reg.h b/drivers/video/kyro/STG4000Reg.h
index 244549e61368..5d6269882589 100644
--- a/drivers/video/kyro/STG4000Reg.h
+++ b/drivers/video/kyro/STG4000Reg.h
@@ -16,7 +16,7 @@
16 16
17/* 17/*
18 * Macros that access memory mapped card registers in PCI space 18 * Macros that access memory mapped card registers in PCI space
19 * Add an appropraite section for your OS or processor architecture. 19 * Add an appropriate section for your OS or processor architecture.
20 */ 20 */
21#if defined(__KERNEL__) 21#if defined(__KERNEL__)
22#include <asm/page.h> 22#include <asm/page.h>
diff --git a/drivers/video/leo.c b/drivers/video/leo.c
index b599e5e36ced..9e946e2c1da9 100644
--- a/drivers/video/leo.c
+++ b/drivers/video/leo.c
@@ -547,8 +547,7 @@ static void leo_unmap_regs(struct platform_device *op, struct fb_info *info,
547 of_iounmap(&op->resource[0], info->screen_base, 0x800000); 547 of_iounmap(&op->resource[0], info->screen_base, 0x800000);
548} 548}
549 549
550static int __devinit leo_probe(struct platform_device *op, 550static int __devinit leo_probe(struct platform_device *op)
551 const struct of_device_id *match)
552{ 551{
553 struct device_node *dp = op->dev.of_node; 552 struct device_node *dp = op->dev.of_node;
554 struct fb_info *info; 553 struct fb_info *info;
@@ -662,7 +661,7 @@ static const struct of_device_id leo_match[] = {
662}; 661};
663MODULE_DEVICE_TABLE(of, leo_match); 662MODULE_DEVICE_TABLE(of, leo_match);
664 663
665static struct of_platform_driver leo_driver = { 664static struct platform_driver leo_driver = {
666 .driver = { 665 .driver = {
667 .name = "leo", 666 .name = "leo",
668 .owner = THIS_MODULE, 667 .owner = THIS_MODULE,
@@ -677,12 +676,12 @@ static int __init leo_init(void)
677 if (fb_get_options("leofb", NULL)) 676 if (fb_get_options("leofb", NULL))
678 return -ENODEV; 677 return -ENODEV;
679 678
680 return of_register_platform_driver(&leo_driver); 679 return platform_driver_register(&leo_driver);
681} 680}
682 681
683static void __exit leo_exit(void) 682static void __exit leo_exit(void)
684{ 683{
685 of_unregister_platform_driver(&leo_driver); 684 platform_driver_unregister(&leo_driver);
686} 685}
687 686
688module_init(leo_init); 687module_init(leo_init);
diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/matrox/matroxfb_DAC1064.c
index f9fa0fd00292..1717623aabc0 100644
--- a/drivers/video/matrox/matroxfb_DAC1064.c
+++ b/drivers/video/matrox/matroxfb_DAC1064.c
@@ -869,12 +869,9 @@ static int MGAG100_preinit(struct matrox_fb_info *minfo)
869 minfo->capable.plnwt = minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG100 869 minfo->capable.plnwt = minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG100
870 ? minfo->devflags.sgram : 1; 870 ? minfo->devflags.sgram : 1;
871 871
872#ifdef CONFIG_FB_MATROX_G
873 if (minfo->devflags.g450dac) { 872 if (minfo->devflags.g450dac) {
874 minfo->outputs[0].output = &g450out; 873 minfo->outputs[0].output = &g450out;
875 } else 874 } else {
876#endif
877 {
878 minfo->outputs[0].output = &m1064; 875 minfo->outputs[0].output = &m1064;
879 } 876 }
880 minfo->outputs[0].src = minfo->outputs[0].default_src; 877 minfo->outputs[0].src = minfo->outputs[0].default_src;
diff --git a/drivers/video/matrox/matroxfb_DAC1064.h b/drivers/video/matrox/matroxfb_DAC1064.h
index c6ed7801efe2..1e6e45b57b78 100644
--- a/drivers/video/matrox/matroxfb_DAC1064.h
+++ b/drivers/video/matrox/matroxfb_DAC1064.h
@@ -46,7 +46,7 @@ void DAC1064_global_restore(struct matrox_fb_info *minfo);
46#define M1064_XDVICLKCTRL_DVILOOPCTL 0x30 46#define M1064_XDVICLKCTRL_DVILOOPCTL 0x30
47 /* CRTC2 pixel clock allowed to(0)/blocked from(1) driving CRTC2 */ 47 /* CRTC2 pixel clock allowed to(0)/blocked from(1) driving CRTC2 */
48#define M1064_XDVICLKCTRL_C2DVICLKEN 0x40 48#define M1064_XDVICLKCTRL_C2DVICLKEN 0x40
49 /* P1PLL loop filter bandwith selection */ 49 /* P1PLL loop filter bandwidth selection */
50#define M1064_XDVICLKCTRL_P1LOOPBWDTCTL 0x80 50#define M1064_XDVICLKCTRL_P1LOOPBWDTCTL 0x80
51#define M1064_XCURCOL0RED 0x08 51#define M1064_XCURCOL0RED 0x08
52#define M1064_XCURCOL0GREEN 0x09 52#define M1064_XCURCOL0GREEN 0x09
diff --git a/drivers/video/matrox/matroxfb_Ti3026.c b/drivers/video/matrox/matroxfb_Ti3026.c
index 835aaaae6b96..9a44cec394b5 100644
--- a/drivers/video/matrox/matroxfb_Ti3026.c
+++ b/drivers/video/matrox/matroxfb_Ti3026.c
@@ -387,7 +387,7 @@ static int Ti3026_init(struct matrox_fb_info *minfo, struct my_timming *m)
387 hw->DACreg[POS3026_XMISCCTRL] = TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_LOW; 387 hw->DACreg[POS3026_XMISCCTRL] = TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_LOW;
388 break; 388 break;
389 case 16: 389 case 16:
390 /* XLATCHCTRL should be _4_1 / _2_1... Why is not? (_2_1 is used everytime) */ 390 /* XLATCHCTRL should be _4_1 / _2_1... Why is not? (_2_1 is used every time) */
391 hw->DACreg[POS3026_XTRUECOLORCTRL] = (minfo->fbcon.var.green.length == 5) ? (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_1555) : (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_565); 391 hw->DACreg[POS3026_XTRUECOLORCTRL] = (minfo->fbcon.var.green.length == 5) ? (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_1555) : (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_565);
392 hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_16BIT; 392 hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_16BIT;
393 hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV2; 393 hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV2;
@@ -399,7 +399,7 @@ static int Ti3026_init(struct matrox_fb_info *minfo, struct my_timming *m)
399 hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV4; 399 hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV4;
400 break; 400 break;
401 case 32: 401 case 32:
402 /* XLATCHCTRL should be _2_1 / _1_1... Why is not? (_2_1 is used everytime) */ 402 /* XLATCHCTRL should be _2_1 / _1_1... Why is not? (_2_1 is used every time) */
403 hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_32BIT; 403 hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_32BIT;
404 break; 404 break;
405 default: 405 default:
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 052dd9f0b760..44bf8d4a216b 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -101,8 +101,6 @@
101 101
102#include <linux/version.h> 102#include <linux/version.h>
103 103
104#define __OLD_VIDIOC_
105
106#include "matroxfb_base.h" 104#include "matroxfb_base.h"
107#include "matroxfb_misc.h" 105#include "matroxfb_misc.h"
108#include "matroxfb_accel.h" 106#include "matroxfb_accel.h"
@@ -623,7 +621,7 @@ static int matroxfb_decode_var(const struct matrox_fb_info *minfo,
623 var->yoffset = var->yres_virtual - var->yres; 621 var->yoffset = var->yres_virtual - var->yres;
624 622
625 if (bpp == 16 && var->green.length == 5) { 623 if (bpp == 16 && var->green.length == 5) {
626 bpp--; /* an artifical value - 15 */ 624 bpp--; /* an artificial value - 15 */
627 } 625 }
628 626
629 for (rgbt = table; rgbt->bpp < bpp; rgbt++); 627 for (rgbt = table; rgbt->bpp < bpp; rgbt++);
@@ -1152,7 +1150,6 @@ static int matroxfb_ioctl(struct fb_info *info,
1152 return -EFAULT; 1150 return -EFAULT;
1153 return err; 1151 return err;
1154 } 1152 }
1155 case VIDIOC_S_CTRL_OLD:
1156 case VIDIOC_S_CTRL: 1153 case VIDIOC_S_CTRL:
1157 { 1154 {
1158 struct v4l2_control ctrl; 1155 struct v4l2_control ctrl;
@@ -1247,46 +1244,46 @@ static struct { struct fb_bitfield red, green, blue, transp; int bits_per_pixel;
1247}; 1244};
1248 1245
1249/* initialized by setup, see explanation at end of file (search for MODULE_PARM_DESC) */ 1246/* initialized by setup, see explanation at end of file (search for MODULE_PARM_DESC) */
1250static unsigned int mem; /* "matrox:mem:xxxxxM" */ 1247static unsigned int mem; /* "matroxfb:mem:xxxxxM" */
1251static int option_precise_width = 1; /* cannot be changed, option_precise_width==0 must imply noaccel */ 1248static int option_precise_width = 1; /* cannot be changed, option_precise_width==0 must imply noaccel */
1252static int inv24; /* "matrox:inv24" */ 1249static int inv24; /* "matroxfb:inv24" */
1253static int cross4MB = -1; /* "matrox:cross4MB" */ 1250static int cross4MB = -1; /* "matroxfb:cross4MB" */
1254static int disabled; /* "matrox:disabled" */ 1251static int disabled; /* "matroxfb:disabled" */
1255static int noaccel; /* "matrox:noaccel" */ 1252static int noaccel; /* "matroxfb:noaccel" */
1256static int nopan; /* "matrox:nopan" */ 1253static int nopan; /* "matroxfb:nopan" */
1257static int no_pci_retry; /* "matrox:nopciretry" */ 1254static int no_pci_retry; /* "matroxfb:nopciretry" */
1258static int novga; /* "matrox:novga" */ 1255static int novga; /* "matroxfb:novga" */
1259static int nobios; /* "matrox:nobios" */ 1256static int nobios; /* "matroxfb:nobios" */
1260static int noinit = 1; /* "matrox:init" */ 1257static int noinit = 1; /* "matroxfb:init" */
1261static int inverse; /* "matrox:inverse" */ 1258static int inverse; /* "matroxfb:inverse" */
1262static int sgram; /* "matrox:sgram" */ 1259static int sgram; /* "matroxfb:sgram" */
1263#ifdef CONFIG_MTRR 1260#ifdef CONFIG_MTRR
1264static int mtrr = 1; /* "matrox:nomtrr" */ 1261static int mtrr = 1; /* "matroxfb:nomtrr" */
1265#endif 1262#endif
1266static int grayscale; /* "matrox:grayscale" */ 1263static int grayscale; /* "matroxfb:grayscale" */
1267static int dev = -1; /* "matrox:dev:xxxxx" */ 1264static int dev = -1; /* "matroxfb:dev:xxxxx" */
1268static unsigned int vesa = ~0; /* "matrox:vesa:xxxxx" */ 1265static unsigned int vesa = ~0; /* "matroxfb:vesa:xxxxx" */
1269static int depth = -1; /* "matrox:depth:xxxxx" */ 1266static int depth = -1; /* "matroxfb:depth:xxxxx" */
1270static unsigned int xres; /* "matrox:xres:xxxxx" */ 1267static unsigned int xres; /* "matroxfb:xres:xxxxx" */
1271static unsigned int yres; /* "matrox:yres:xxxxx" */ 1268static unsigned int yres; /* "matroxfb:yres:xxxxx" */
1272static unsigned int upper = ~0; /* "matrox:upper:xxxxx" */ 1269static unsigned int upper = ~0; /* "matroxfb:upper:xxxxx" */
1273static unsigned int lower = ~0; /* "matrox:lower:xxxxx" */ 1270static unsigned int lower = ~0; /* "matroxfb:lower:xxxxx" */
1274static unsigned int vslen; /* "matrox:vslen:xxxxx" */ 1271static unsigned int vslen; /* "matroxfb:vslen:xxxxx" */
1275static unsigned int left = ~0; /* "matrox:left:xxxxx" */ 1272static unsigned int left = ~0; /* "matroxfb:left:xxxxx" */
1276static unsigned int right = ~0; /* "matrox:right:xxxxx" */ 1273static unsigned int right = ~0; /* "matroxfb:right:xxxxx" */
1277static unsigned int hslen; /* "matrox:hslen:xxxxx" */ 1274static unsigned int hslen; /* "matroxfb:hslen:xxxxx" */
1278static unsigned int pixclock; /* "matrox:pixclock:xxxxx" */ 1275static unsigned int pixclock; /* "matroxfb:pixclock:xxxxx" */
1279static int sync = -1; /* "matrox:sync:xxxxx" */ 1276static int sync = -1; /* "matroxfb:sync:xxxxx" */
1280static unsigned int fv; /* "matrox:fv:xxxxx" */ 1277static unsigned int fv; /* "matroxfb:fv:xxxxx" */
1281static unsigned int fh; /* "matrox:fh:xxxxxk" */ 1278static unsigned int fh; /* "matroxfb:fh:xxxxxk" */
1282static unsigned int maxclk; /* "matrox:maxclk:xxxxM" */ 1279static unsigned int maxclk; /* "matroxfb:maxclk:xxxxM" */
1283static int dfp; /* "matrox:dfp */ 1280static int dfp; /* "matroxfb:dfp */
1284static int dfp_type = -1; /* "matrox:dfp:xxx */ 1281static int dfp_type = -1; /* "matroxfb:dfp:xxx */
1285static int memtype = -1; /* "matrox:memtype:xxx" */ 1282static int memtype = -1; /* "matroxfb:memtype:xxx" */
1286static char outputs[8]; /* "matrox:outputs:xxx" */ 1283static char outputs[8]; /* "matroxfb:outputs:xxx" */
1287 1284
1288#ifndef MODULE 1285#ifndef MODULE
1289static char videomode[64]; /* "matrox:mode:xxxxx" or "matrox:xxxxx" */ 1286static char videomode[64]; /* "matroxfb:mode:xxxxx" or "matroxfb:xxxxx" */
1290#endif 1287#endif
1291 1288
1292static int matroxfb_getmemory(struct matrox_fb_info *minfo, 1289static int matroxfb_getmemory(struct matrox_fb_info *minfo,
@@ -1461,13 +1458,6 @@ static struct board {
1461 MGA_G100, 1458 MGA_G100,
1462 &vbG100, 1459 &vbG100,
1463 "MGA-G100 (AGP)"}, 1460 "MGA-G100 (AGP)"},
1464 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200EV_PCI, 0xFF,
1465 0, 0,
1466 DEVF_G200,
1467 230000,
1468 MGA_G200,
1469 &vbG200,
1470 "MGA-G200eV (PCI)"},
1471 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_PCI, 0xFF, 1461 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_PCI, 0xFF,
1472 0, 0, 1462 0, 0,
1473 DEVF_G200, 1463 DEVF_G200,
@@ -2119,8 +2109,6 @@ static struct pci_device_id matroxfb_devices[] = {
2119 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 2109 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2120 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 2110 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP,
2121 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 2111 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2122 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200EV_PCI,
2123 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2124 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_PCI, 2112 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_PCI,
2125 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 2113 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2126 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 2114 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP,
diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h
index f96a471cb1a8..11ed57bb704e 100644
--- a/drivers/video/matrox/matroxfb_base.h
+++ b/drivers/video/matrox/matroxfb_base.h
@@ -12,7 +12,7 @@
12#undef MATROXFB_DEBUG 12#undef MATROXFB_DEBUG
13 13
14/* heavy debugging: */ 14/* heavy debugging: */
15/* -- logs putc[s], so everytime a char is displayed, it's logged */ 15/* -- logs putc[s], so every time a char is displayed, it's logged */
16#undef MATROXFB_DEBUG_HEAVY 16#undef MATROXFB_DEBUG_HEAVY
17 17
18/* This one _could_ cause infinite loops */ 18/* This one _could_ cause infinite loops */
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index 1e3e8f19783e..31b8f67477b7 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -280,7 +280,7 @@ static int matroxfb_PLL_mavenclock(const struct matrox_pll_features2* pll,
280 return fxtal * (*feed) / (*in) * ctl->den; 280 return fxtal * (*feed) / (*in) * ctl->den;
281} 281}
282 282
283static unsigned int matroxfb_mavenclock(const struct matrox_pll_ctl* ctl, 283static int matroxfb_mavenclock(const struct matrox_pll_ctl *ctl,
284 unsigned int htotal, unsigned int vtotal, 284 unsigned int htotal, unsigned int vtotal,
285 unsigned int* in, unsigned int* feed, unsigned int* post, 285 unsigned int* in, unsigned int* feed, unsigned int* post,
286 unsigned int* htotal2) { 286 unsigned int* htotal2) {
diff --git a/drivers/video/mb862xx/Makefile b/drivers/video/mb862xx/Makefile
index d7777714166b..5707ed0e31a7 100644
--- a/drivers/video/mb862xx/Makefile
+++ b/drivers/video/mb862xx/Makefile
@@ -2,4 +2,7 @@
2# Makefile for the MB862xx framebuffer driver 2# Makefile for the MB862xx framebuffer driver
3# 3#
4 4
5obj-$(CONFIG_FB_MB862XX) := mb862xxfb.o mb862xxfb_accel.o 5obj-$(CONFIG_FB_MB862XX) += mb862xxfb.o
6
7mb862xxfb-y := mb862xxfbdrv.o mb862xxfb_accel.o
8mb862xxfb-$(CONFIG_FB_MB862XX_I2C) += mb862xx-i2c.o
diff --git a/drivers/video/mb862xx/mb862xx-i2c.c b/drivers/video/mb862xx/mb862xx-i2c.c
new file mode 100644
index 000000000000..b953099edd8e
--- /dev/null
+++ b/drivers/video/mb862xx/mb862xx-i2c.c
@@ -0,0 +1,178 @@
1/*
2 * Coral-P(A)/Lime I2C adapter driver
3 *
4 * (C) 2011 DENX Software Engineering, Anatolij Gustschin <agust@denx.de>
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 version 2 as
8 * published by the Free Software Foundation.
9 *
10 */
11
12#include <linux/fb.h>
13#include <linux/i2c.h>
14#include <linux/io.h>
15#include <linux/delay.h>
16
17#include "mb862xxfb.h"
18#include "mb862xx_reg.h"
19
20static int mb862xx_i2c_wait_event(struct i2c_adapter *adap)
21{
22 struct mb862xxfb_par *par = adap->algo_data;
23 u32 reg;
24
25 do {
26 udelay(1);
27 reg = inreg(i2c, GC_I2C_BCR);
28 if (reg & (I2C_INT | I2C_BER))
29 break;
30 } while (1);
31
32 return (reg & I2C_BER) ? 0 : 1;
33}
34
35static int mb862xx_i2c_do_address(struct i2c_adapter *adap, int addr)
36{
37 struct mb862xxfb_par *par = adap->algo_data;
38
39 outreg(i2c, GC_I2C_DAR, addr);
40 outreg(i2c, GC_I2C_CCR, I2C_CLOCK_AND_ENABLE);
41 outreg(i2c, GC_I2C_BCR, par->i2c_rs ? I2C_REPEATED_START : I2C_START);
42 if (!mb862xx_i2c_wait_event(adap))
43 return -EIO;
44 par->i2c_rs = !(inreg(i2c, GC_I2C_BSR) & I2C_LRB);
45 return par->i2c_rs;
46}
47
48static int mb862xx_i2c_write_byte(struct i2c_adapter *adap, u8 byte)
49{
50 struct mb862xxfb_par *par = adap->algo_data;
51
52 outreg(i2c, GC_I2C_DAR, byte);
53 outreg(i2c, GC_I2C_BCR, I2C_START);
54 if (!mb862xx_i2c_wait_event(adap))
55 return -EIO;
56 return !(inreg(i2c, GC_I2C_BSR) & I2C_LRB);
57}
58
59static int mb862xx_i2c_read_byte(struct i2c_adapter *adap, u8 *byte, int last)
60{
61 struct mb862xxfb_par *par = adap->algo_data;
62
63 outreg(i2c, GC_I2C_BCR, I2C_START | (last ? 0 : I2C_ACK));
64 if (!mb862xx_i2c_wait_event(adap))
65 return 0;
66 *byte = inreg(i2c, GC_I2C_DAR);
67 return 1;
68}
69
70void mb862xx_i2c_stop(struct i2c_adapter *adap)
71{
72 struct mb862xxfb_par *par = adap->algo_data;
73
74 outreg(i2c, GC_I2C_BCR, I2C_STOP);
75 outreg(i2c, GC_I2C_CCR, I2C_DISABLE);
76 par->i2c_rs = 0;
77}
78
79static int mb862xx_i2c_read(struct i2c_adapter *adap, struct i2c_msg *m)
80{
81 int i, ret = 0;
82 int last = m->len - 1;
83
84 for (i = 0; i < m->len; i++) {
85 if (!mb862xx_i2c_read_byte(adap, &m->buf[i], i == last)) {
86 ret = -EIO;
87 break;
88 }
89 }
90 return ret;
91}
92
93static int mb862xx_i2c_write(struct i2c_adapter *adap, struct i2c_msg *m)
94{
95 int i, ret = 0;
96
97 for (i = 0; i < m->len; i++) {
98 if (!mb862xx_i2c_write_byte(adap, m->buf[i])) {
99 ret = -EIO;
100 break;
101 }
102 }
103 return ret;
104}
105
106static int mb862xx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
107 int num)
108{
109 struct mb862xxfb_par *par = adap->algo_data;
110 struct i2c_msg *m;
111 int addr;
112 int i = 0, err = 0;
113
114 dev_dbg(par->dev, "%s: %d msgs\n", __func__, num);
115
116 for (i = 0; i < num; i++) {
117 m = &msgs[i];
118 if (!m->len) {
119 dev_dbg(par->dev, "%s: null msgs\n", __func__);
120 continue;
121 }
122 addr = m->addr;
123 if (m->flags & I2C_M_RD)
124 addr |= 1;
125
126 err = mb862xx_i2c_do_address(adap, addr);
127 if (err < 0)
128 break;
129 if (m->flags & I2C_M_RD)
130 err = mb862xx_i2c_read(adap, m);
131 else
132 err = mb862xx_i2c_write(adap, m);
133 }
134
135 if (i)
136 mb862xx_i2c_stop(adap);
137
138 return (err < 0) ? err : i;
139}
140
141static u32 mb862xx_func(struct i2c_adapter *adap)
142{
143 return I2C_FUNC_SMBUS_BYTE_DATA;
144}
145
146static const struct i2c_algorithm mb862xx_algo = {
147 .master_xfer = mb862xx_xfer,
148 .functionality = mb862xx_func,
149};
150
151static struct i2c_adapter mb862xx_i2c_adapter = {
152 .name = "MB862xx I2C adapter",
153 .algo = &mb862xx_algo,
154 .owner = THIS_MODULE,
155};
156
157int mb862xx_i2c_init(struct mb862xxfb_par *par)
158{
159 int ret;
160
161 mb862xx_i2c_adapter.algo_data = par;
162 par->adap = &mb862xx_i2c_adapter;
163
164 ret = i2c_add_adapter(par->adap);
165 if (ret < 0) {
166 dev_err(par->dev, "failed to add %s\n",
167 mb862xx_i2c_adapter.name);
168 }
169 return ret;
170}
171
172void mb862xx_i2c_exit(struct mb862xxfb_par *par)
173{
174 if (par->adap) {
175 i2c_del_adapter(par->adap);
176 par->adap = NULL;
177 }
178}
diff --git a/drivers/video/mb862xx/mb862xx_reg.h b/drivers/video/mb862xx/mb862xx_reg.h
index 2ba65e118500..9df48b8edc94 100644
--- a/drivers/video/mb862xx/mb862xx_reg.h
+++ b/drivers/video/mb862xx/mb862xx_reg.h
@@ -5,11 +5,8 @@
5#ifndef _MB862XX_REG_H 5#ifndef _MB862XX_REG_H
6#define _MB862XX_REG_H 6#define _MB862XX_REG_H
7 7
8#ifdef MB862XX_MMIO_BOTTOM
9#define MB862XX_MMIO_BASE 0x03fc0000
10#else
11#define MB862XX_MMIO_BASE 0x01fc0000 8#define MB862XX_MMIO_BASE 0x01fc0000
12#endif 9#define MB862XX_MMIO_HIGH_BASE 0x03fc0000
13#define MB862XX_I2C_BASE 0x0000c000 10#define MB862XX_I2C_BASE 0x0000c000
14#define MB862XX_DISP_BASE 0x00010000 11#define MB862XX_DISP_BASE 0x00010000
15#define MB862XX_CAP_BASE 0x00018000 12#define MB862XX_CAP_BASE 0x00018000
@@ -23,6 +20,7 @@
23#define GC_IMASK 0x00000024 20#define GC_IMASK 0x00000024
24#define GC_SRST 0x0000002c 21#define GC_SRST 0x0000002c
25#define GC_CCF 0x00000038 22#define GC_CCF 0x00000038
23#define GC_RSW 0x0000005c
26#define GC_CID 0x000000f0 24#define GC_CID 0x000000f0
27#define GC_REVISION 0x00000084 25#define GC_REVISION 0x00000084
28 26
@@ -53,10 +51,16 @@
53#define GC_L0OA0 0x00000024 51#define GC_L0OA0 0x00000024
54#define GC_L0DA0 0x00000028 52#define GC_L0DA0 0x00000028
55#define GC_L0DY_L0DX 0x0000002c 53#define GC_L0DY_L0DX 0x0000002c
54#define GC_L1M 0x00000030
55#define GC_L1DA 0x00000034
56#define GC_DCM1 0x00000100 56#define GC_DCM1 0x00000100
57#define GC_L0EM 0x00000110 57#define GC_L0EM 0x00000110
58#define GC_L0WY_L0WX 0x00000114 58#define GC_L0WY_L0WX 0x00000114
59#define GC_L0WH_L0WW 0x00000118 59#define GC_L0WH_L0WW 0x00000118
60#define GC_L1EM 0x00000120
61#define GC_L1WY_L1WX 0x00000124
62#define GC_L1WH_L1WW 0x00000128
63#define GC_DLS 0x00000180
60#define GC_DCM2 0x00000104 64#define GC_DCM2 0x00000104
61#define GC_DCM3 0x00000108 65#define GC_DCM3 0x00000108
62#define GC_CPM_CUTC 0x000000a0 66#define GC_CPM_CUTC 0x000000a0
@@ -68,6 +72,11 @@
68 72
69#define GC_CPM_CEN0 0x00100000 73#define GC_CPM_CEN0 0x00100000
70#define GC_CPM_CEN1 0x00200000 74#define GC_CPM_CEN1 0x00200000
75#define GC_DCM1_DEN 0x80000000
76#define GC_DCM1_L1E 0x00020000
77#define GC_L1M_16 0x80000000
78#define GC_L1M_YC 0x40000000
79#define GC_L1M_CS 0x20000000
71 80
72#define GC_DCM01_ESY 0x00000004 81#define GC_DCM01_ESY 0x00000004
73#define GC_DCM01_SC 0x00003f00 82#define GC_DCM01_SC 0x00003f00
@@ -79,9 +88,50 @@
79#define GC_L0M_L0C_16 0x80000000 88#define GC_L0M_L0C_16 0x80000000
80#define GC_L0EM_L0EC_24 0x40000000 89#define GC_L0EM_L0EC_24 0x40000000
81#define GC_L0M_L0W_UNIT 64 90#define GC_L0M_L0W_UNIT 64
91#define GC_L1EM_DM 0x02000000
82 92
83#define GC_DISP_REFCLK_400 400 93#define GC_DISP_REFCLK_400 400
84 94
95/* I2C */
96#define GC_I2C_BSR 0x00000000 /* BSR */
97#define GC_I2C_BCR 0x00000004 /* BCR */
98#define GC_I2C_CCR 0x00000008 /* CCR */
99#define GC_I2C_ADR 0x0000000C /* ADR */
100#define GC_I2C_DAR 0x00000010 /* DAR */
101
102#define I2C_DISABLE 0x00000000
103#define I2C_STOP 0x00000000
104#define I2C_START 0x00000010
105#define I2C_REPEATED_START 0x00000030
106#define I2C_CLOCK_AND_ENABLE 0x0000003f
107#define I2C_READY 0x01
108#define I2C_INT 0x01
109#define I2C_INTE 0x02
110#define I2C_ACK 0x08
111#define I2C_BER 0x80
112#define I2C_BEIE 0x40
113#define I2C_TRX 0x80
114#define I2C_LRB 0x10
115
116/* Capture registers and bits */
117#define GC_CAP_VCM 0x00000000
118#define GC_CAP_CSC 0x00000004
119#define GC_CAP_VCS 0x00000008
120#define GC_CAP_CBM 0x00000010
121#define GC_CAP_CBOA 0x00000014
122#define GC_CAP_CBLA 0x00000018
123#define GC_CAP_IMG_START 0x0000001C
124#define GC_CAP_IMG_END 0x00000020
125#define GC_CAP_CMSS 0x00000048
126#define GC_CAP_CMDS 0x0000004C
127
128#define GC_VCM_VIE 0x80000000
129#define GC_VCM_CM 0x03000000
130#define GC_VCM_VS_PAL 0x00000002
131#define GC_CBM_OO 0x80000000
132#define GC_CBM_HRV 0x00000010
133#define GC_CBM_CBST 0x00000001
134
85/* Carmine specific */ 135/* Carmine specific */
86#define MB86297_DRAW_BASE 0x00020000 136#define MB86297_DRAW_BASE 0x00020000
87#define MB86297_DISP0_BASE 0x00100000 137#define MB86297_DISP0_BASE 0x00100000
diff --git a/drivers/video/mb862xx/mb862xxfb.h b/drivers/video/mb862xx/mb862xxfb.h
index d7e7cb76bbf2..8550630c1e01 100644
--- a/drivers/video/mb862xx/mb862xxfb.h
+++ b/drivers/video/mb862xx/mb862xxfb.h
@@ -1,6 +1,26 @@
1#ifndef __MB862XX_H__ 1#ifndef __MB862XX_H__
2#define __MB862XX_H__ 2#define __MB862XX_H__
3 3
4struct mb862xx_l1_cfg {
5 unsigned short sx;
6 unsigned short sy;
7 unsigned short sw;
8 unsigned short sh;
9 unsigned short dx;
10 unsigned short dy;
11 unsigned short dw;
12 unsigned short dh;
13 int mirror;
14};
15
16#define MB862XX_BASE 'M'
17#define MB862XX_L1_GET_CFG _IOR(MB862XX_BASE, 0, struct mb862xx_l1_cfg*)
18#define MB862XX_L1_SET_CFG _IOW(MB862XX_BASE, 1, struct mb862xx_l1_cfg*)
19#define MB862XX_L1_ENABLE _IOW(MB862XX_BASE, 2, int)
20#define MB862XX_L1_CAP_CTL _IOW(MB862XX_BASE, 3, int)
21
22#ifdef __KERNEL__
23
4#define PCI_VENDOR_ID_FUJITSU_LIMITED 0x10cf 24#define PCI_VENDOR_ID_FUJITSU_LIMITED 0x10cf
5#define PCI_DEVICE_ID_FUJITSU_CORALP 0x2019 25#define PCI_DEVICE_ID_FUJITSU_CORALP 0x2019
6#define PCI_DEVICE_ID_FUJITSU_CORALPA 0x201e 26#define PCI_DEVICE_ID_FUJITSU_CORALPA 0x201e
@@ -38,6 +58,8 @@ struct mb862xxfb_par {
38 void __iomem *mmio_base; /* remapped registers */ 58 void __iomem *mmio_base; /* remapped registers */
39 size_t mapped_vram; /* length of remapped vram */ 59 size_t mapped_vram; /* length of remapped vram */
40 size_t mmio_len; /* length of register region */ 60 size_t mmio_len; /* length of register region */
61 unsigned long cap_buf; /* capture buffers offset */
62 size_t cap_len; /* length of capture buffers */
41 63
42 void __iomem *host; /* relocatable reg. bases */ 64 void __iomem *host; /* relocatable reg. bases */
43 void __iomem *i2c; 65 void __iomem *i2c;
@@ -57,11 +79,23 @@ struct mb862xxfb_par {
57 unsigned int refclk; /* disp. reference clock */ 79 unsigned int refclk; /* disp. reference clock */
58 struct mb862xx_gc_mode *gc_mode; /* GDC mode init data */ 80 struct mb862xx_gc_mode *gc_mode; /* GDC mode init data */
59 int pre_init; /* don't init display if 1 */ 81 int pre_init; /* don't init display if 1 */
82 struct i2c_adapter *adap; /* GDC I2C bus adapter */
83 int i2c_rs;
84
85 struct mb862xx_l1_cfg l1_cfg;
86 int l1_stride;
60 87
61 u32 pseudo_palette[16]; 88 u32 pseudo_palette[16];
62}; 89};
63 90
64extern void mb862xxfb_init_accel(struct fb_info *info, int xres); 91extern void mb862xxfb_init_accel(struct fb_info *info, int xres);
92#ifdef CONFIG_FB_MB862XX_I2C
93extern int mb862xx_i2c_init(struct mb862xxfb_par *par);
94extern void mb862xx_i2c_exit(struct mb862xxfb_par *par);
95#else
96static inline int mb862xx_i2c_init(struct mb862xxfb_par *par) { return 0; }
97static inline void mb862xx_i2c_exit(struct mb862xxfb_par *par) { }
98#endif
65 99
66#if defined(CONFIG_FB_MB862XX_LIME) && defined(CONFIG_FB_MB862XX_PCI_GDC) 100#if defined(CONFIG_FB_MB862XX_LIME) && defined(CONFIG_FB_MB862XX_PCI_GDC)
67#error "Select Lime GDC or CoralP/Carmine support, but not both together" 101#error "Select Lime GDC or CoralP/Carmine support, but not both together"
@@ -82,4 +116,6 @@ extern void mb862xxfb_init_accel(struct fb_info *info, int xres);
82 116
83#define pack(a, b) (((a) << 16) | (b)) 117#define pack(a, b) (((a) << 16) | (b))
84 118
119#endif /* __KERNEL__ */
120
85#endif 121#endif
diff --git a/drivers/video/mb862xx/mb862xxfb.c b/drivers/video/mb862xx/mb862xxfbdrv.c
index b1c4374cf940..f70bd63b0187 100644
--- a/drivers/video/mb862xx/mb862xxfb.c
+++ b/drivers/video/mb862xx/mb862xxfbdrv.c
@@ -16,6 +16,7 @@
16 16
17#include <linux/fb.h> 17#include <linux/fb.h>
18#include <linux/delay.h> 18#include <linux/delay.h>
19#include <linux/uaccess.h>
19#include <linux/init.h> 20#include <linux/init.h>
20#include <linux/interrupt.h> 21#include <linux/interrupt.h>
21#include <linux/pci.h> 22#include <linux/pci.h>
@@ -27,7 +28,7 @@
27 28
28#define NR_PALETTE 256 29#define NR_PALETTE 256
29#define MB862XX_MEM_SIZE 0x1000000 30#define MB862XX_MEM_SIZE 0x1000000
30#define CORALP_MEM_SIZE 0x4000000 31#define CORALP_MEM_SIZE 0x2000000
31#define CARMINE_MEM_SIZE 0x8000000 32#define CARMINE_MEM_SIZE 0x8000000
32#define DRV_NAME "mb862xxfb" 33#define DRV_NAME "mb862xxfb"
33 34
@@ -309,6 +310,97 @@ static int mb862xxfb_blank(int mode, struct fb_info *fbi)
309 return 0; 310 return 0;
310} 311}
311 312
313static int mb862xxfb_ioctl(struct fb_info *fbi, unsigned int cmd,
314 unsigned long arg)
315{
316 struct mb862xxfb_par *par = fbi->par;
317 struct mb862xx_l1_cfg *l1_cfg = &par->l1_cfg;
318 void __user *argp = (void __user *)arg;
319 int *enable;
320 u32 l1em = 0;
321
322 switch (cmd) {
323 case MB862XX_L1_GET_CFG:
324 if (copy_to_user(argp, l1_cfg, sizeof(*l1_cfg)))
325 return -EFAULT;
326 break;
327 case MB862XX_L1_SET_CFG:
328 if (copy_from_user(l1_cfg, argp, sizeof(*l1_cfg)))
329 return -EFAULT;
330 if ((l1_cfg->sw >= l1_cfg->dw) && (l1_cfg->sh >= l1_cfg->dh)) {
331 /* downscaling */
332 outreg(cap, GC_CAP_CSC,
333 pack((l1_cfg->sh << 11) / l1_cfg->dh,
334 (l1_cfg->sw << 11) / l1_cfg->dw));
335 l1em = inreg(disp, GC_L1EM);
336 l1em &= ~GC_L1EM_DM;
337 } else if ((l1_cfg->sw <= l1_cfg->dw) &&
338 (l1_cfg->sh <= l1_cfg->dh)) {
339 /* upscaling */
340 outreg(cap, GC_CAP_CSC,
341 pack((l1_cfg->sh << 11) / l1_cfg->dh,
342 (l1_cfg->sw << 11) / l1_cfg->dw));
343 outreg(cap, GC_CAP_CMSS,
344 pack(l1_cfg->sw >> 1, l1_cfg->sh));
345 outreg(cap, GC_CAP_CMDS,
346 pack(l1_cfg->dw >> 1, l1_cfg->dh));
347 l1em = inreg(disp, GC_L1EM);
348 l1em |= GC_L1EM_DM;
349 }
350
351 if (l1_cfg->mirror) {
352 outreg(cap, GC_CAP_CBM,
353 inreg(cap, GC_CAP_CBM) | GC_CBM_HRV);
354 l1em |= l1_cfg->dw * 2 - 8;
355 } else {
356 outreg(cap, GC_CAP_CBM,
357 inreg(cap, GC_CAP_CBM) & ~GC_CBM_HRV);
358 l1em &= 0xffff0000;
359 }
360 outreg(disp, GC_L1EM, l1em);
361 break;
362 case MB862XX_L1_ENABLE:
363 enable = (int *)arg;
364 if (*enable) {
365 outreg(disp, GC_L1DA, par->cap_buf);
366 outreg(cap, GC_CAP_IMG_START,
367 pack(l1_cfg->sy >> 1, l1_cfg->sx));
368 outreg(cap, GC_CAP_IMG_END,
369 pack(l1_cfg->sh, l1_cfg->sw));
370 outreg(disp, GC_L1M, GC_L1M_16 | GC_L1M_YC | GC_L1M_CS |
371 (par->l1_stride << 16));
372 outreg(disp, GC_L1WY_L1WX,
373 pack(l1_cfg->dy, l1_cfg->dx));
374 outreg(disp, GC_L1WH_L1WW,
375 pack(l1_cfg->dh - 1, l1_cfg->dw));
376 outreg(disp, GC_DLS, 1);
377 outreg(cap, GC_CAP_VCM,
378 GC_VCM_VIE | GC_VCM_CM | GC_VCM_VS_PAL);
379 outreg(disp, GC_DCM1, inreg(disp, GC_DCM1) |
380 GC_DCM1_DEN | GC_DCM1_L1E);
381 } else {
382 outreg(cap, GC_CAP_VCM,
383 inreg(cap, GC_CAP_VCM) & ~GC_VCM_VIE);
384 outreg(disp, GC_DCM1,
385 inreg(disp, GC_DCM1) & ~GC_DCM1_L1E);
386 }
387 break;
388 case MB862XX_L1_CAP_CTL:
389 enable = (int *)arg;
390 if (*enable) {
391 outreg(cap, GC_CAP_VCM,
392 inreg(cap, GC_CAP_VCM) | GC_VCM_VIE);
393 } else {
394 outreg(cap, GC_CAP_VCM,
395 inreg(cap, GC_CAP_VCM) & ~GC_VCM_VIE);
396 }
397 break;
398 default:
399 return -EINVAL;
400 }
401 return 0;
402}
403
312/* framebuffer ops */ 404/* framebuffer ops */
313static struct fb_ops mb862xxfb_ops = { 405static struct fb_ops mb862xxfb_ops = {
314 .owner = THIS_MODULE, 406 .owner = THIS_MODULE,
@@ -320,6 +412,7 @@ static struct fb_ops mb862xxfb_ops = {
320 .fb_fillrect = cfb_fillrect, 412 .fb_fillrect = cfb_fillrect,
321 .fb_copyarea = cfb_copyarea, 413 .fb_copyarea = cfb_copyarea,
322 .fb_imageblit = cfb_imageblit, 414 .fb_imageblit = cfb_imageblit,
415 .fb_ioctl = mb862xxfb_ioctl,
323}; 416};
324 417
325/* initialize fb_info data */ 418/* initialize fb_info data */
@@ -328,6 +421,7 @@ static int mb862xxfb_init_fbinfo(struct fb_info *fbi)
328 struct mb862xxfb_par *par = fbi->par; 421 struct mb862xxfb_par *par = fbi->par;
329 struct mb862xx_gc_mode *mode = par->gc_mode; 422 struct mb862xx_gc_mode *mode = par->gc_mode;
330 unsigned long reg; 423 unsigned long reg;
424 int stride;
331 425
332 fbi->fbops = &mb862xxfb_ops; 426 fbi->fbops = &mb862xxfb_ops;
333 fbi->pseudo_palette = par->pseudo_palette; 427 fbi->pseudo_palette = par->pseudo_palette;
@@ -336,7 +430,6 @@ static int mb862xxfb_init_fbinfo(struct fb_info *fbi)
336 430
337 strcpy(fbi->fix.id, DRV_NAME); 431 strcpy(fbi->fix.id, DRV_NAME);
338 fbi->fix.smem_start = (unsigned long)par->fb_base_phys; 432 fbi->fix.smem_start = (unsigned long)par->fb_base_phys;
339 fbi->fix.smem_len = par->mapped_vram;
340 fbi->fix.mmio_start = (unsigned long)par->mmio_base_phys; 433 fbi->fix.mmio_start = (unsigned long)par->mmio_base_phys;
341 fbi->fix.mmio_len = par->mmio_len; 434 fbi->fix.mmio_len = par->mmio_len;
342 fbi->fix.accel = FB_ACCEL_NONE; 435 fbi->fix.accel = FB_ACCEL_NONE;
@@ -420,6 +513,28 @@ static int mb862xxfb_init_fbinfo(struct fb_info *fbi)
420 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; 513 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
421 fbi->fix.line_length = (fbi->var.xres_virtual * 514 fbi->fix.line_length = (fbi->var.xres_virtual *
422 fbi->var.bits_per_pixel) / 8; 515 fbi->var.bits_per_pixel) / 8;
516 fbi->fix.smem_len = fbi->fix.line_length * fbi->var.yres_virtual;
517
518 /*
519 * reserve space for capture buffers and two cursors
520 * at the end of vram: 720x576 * 2 * 2.2 + 64x64 * 16.
521 */
522 par->cap_buf = par->mapped_vram - 0x1bd800 - 0x10000;
523 par->cap_len = 0x1bd800;
524 par->l1_cfg.sx = 0;
525 par->l1_cfg.sy = 0;
526 par->l1_cfg.sw = 720;
527 par->l1_cfg.sh = 576;
528 par->l1_cfg.dx = 0;
529 par->l1_cfg.dy = 0;
530 par->l1_cfg.dw = 720;
531 par->l1_cfg.dh = 576;
532 stride = par->l1_cfg.sw * (fbi->var.bits_per_pixel / 8);
533 par->l1_stride = stride / 64 + ((stride % 64) ? 1 : 0);
534 outreg(cap, GC_CAP_CBM, GC_CBM_OO | GC_CBM_CBST |
535 (par->l1_stride << 16));
536 outreg(cap, GC_CAP_CBOA, par->cap_buf);
537 outreg(cap, GC_CAP_CBLA, par->cap_buf + par->cap_len);
423 return 0; 538 return 0;
424} 539}
425 540
@@ -550,8 +665,7 @@ static int mb862xx_gdc_init(struct mb862xxfb_par *par)
550 return 0; 665 return 0;
551} 666}
552 667
553static int __devinit of_platform_mb862xx_probe(struct platform_device *ofdev, 668static int __devinit of_platform_mb862xx_probe(struct platform_device *ofdev)
554 const struct of_device_id *id)
555{ 669{
556 struct device_node *np = ofdev->dev.of_node; 670 struct device_node *np = ofdev->dev.of_node;
557 struct device *dev = &ofdev->dev; 671 struct device *dev = &ofdev->dev;
@@ -717,7 +831,7 @@ static struct of_device_id __devinitdata of_platform_mb862xx_tbl[] = {
717 { /* end */ } 831 { /* end */ }
718}; 832};
719 833
720static struct of_platform_driver of_platform_mb862xxfb_driver = { 834static struct platform_driver of_platform_mb862xxfb_driver = {
721 .driver = { 835 .driver = {
722 .name = DRV_NAME, 836 .name = DRV_NAME,
723 .owner = THIS_MODULE, 837 .owner = THIS_MODULE,
@@ -743,22 +857,38 @@ static int coralp_init(struct mb862xxfb_par *par)
743 857
744 par->refclk = GC_DISP_REFCLK_400; 858 par->refclk = GC_DISP_REFCLK_400;
745 859
860 if (par->mapped_vram >= 0x2000000) {
861 /* relocate gdc registers space */
862 writel(1, par->fb_base + MB862XX_MMIO_BASE + GC_RSW);
863 udelay(1); /* wait at least 20 bus cycles */
864 }
865
746 ver = inreg(host, GC_CID); 866 ver = inreg(host, GC_CID);
747 cn = (ver & GC_CID_CNAME_MSK) >> 8; 867 cn = (ver & GC_CID_CNAME_MSK) >> 8;
748 ver = ver & GC_CID_VERSION_MSK; 868 ver = ver & GC_CID_VERSION_MSK;
749 if (cn == 3) { 869 if (cn == 3) {
870 unsigned long reg;
871
750 dev_info(par->dev, "Fujitsu Coral-%s GDC Rev.%d found\n",\ 872 dev_info(par->dev, "Fujitsu Coral-%s GDC Rev.%d found\n",\
751 (ver == 6) ? "P" : (ver == 8) ? "PA" : "?", 873 (ver == 6) ? "P" : (ver == 8) ? "PA" : "?",
752 par->pdev->revision); 874 par->pdev->revision);
753 outreg(host, GC_CCF, GC_CCF_CGE_166 | GC_CCF_COT_133); 875 reg = inreg(disp, GC_DCM1);
754 udelay(200); 876 if (reg & GC_DCM01_DEN && reg & GC_DCM01_L0E)
755 outreg(host, GC_MMR, GC_MMR_CORALP_EVB_VAL); 877 par->pre_init = 1;
756 udelay(10); 878
879 if (!par->pre_init) {
880 outreg(host, GC_CCF, GC_CCF_CGE_166 | GC_CCF_COT_133);
881 udelay(200);
882 outreg(host, GC_MMR, GC_MMR_CORALP_EVB_VAL);
883 udelay(10);
884 }
757 /* Clear interrupt status */ 885 /* Clear interrupt status */
758 outreg(host, GC_IST, 0); 886 outreg(host, GC_IST, 0);
759 } else { 887 } else {
760 return -ENODEV; 888 return -ENODEV;
761 } 889 }
890
891 mb862xx_i2c_init(par);
762 return 0; 892 return 0;
763} 893}
764 894
@@ -900,7 +1030,13 @@ static int __devinit mb862xx_pci_probe(struct pci_dev *pdev,
900 case PCI_DEVICE_ID_FUJITSU_CORALPA: 1030 case PCI_DEVICE_ID_FUJITSU_CORALPA:
901 par->fb_base_phys = pci_resource_start(par->pdev, 0); 1031 par->fb_base_phys = pci_resource_start(par->pdev, 0);
902 par->mapped_vram = CORALP_MEM_SIZE; 1032 par->mapped_vram = CORALP_MEM_SIZE;
903 par->mmio_base_phys = par->fb_base_phys + MB862XX_MMIO_BASE; 1033 if (par->mapped_vram >= 0x2000000) {
1034 par->mmio_base_phys = par->fb_base_phys +
1035 MB862XX_MMIO_HIGH_BASE;
1036 } else {
1037 par->mmio_base_phys = par->fb_base_phys +
1038 MB862XX_MMIO_BASE;
1039 }
904 par->mmio_len = MB862XX_MMIO_SIZE; 1040 par->mmio_len = MB862XX_MMIO_SIZE;
905 par->type = BT_CORALP; 1041 par->type = BT_CORALP;
906 break; 1042 break;
@@ -1010,6 +1146,8 @@ static void __devexit mb862xx_pci_remove(struct pci_dev *pdev)
1010 outreg(host, GC_IMASK, 0); 1146 outreg(host, GC_IMASK, 0);
1011 } 1147 }
1012 1148
1149 mb862xx_i2c_exit(par);
1150
1013 device_remove_file(&pdev->dev, &dev_attr_dispregs); 1151 device_remove_file(&pdev->dev, &dev_attr_dispregs);
1014 1152
1015 pci_set_drvdata(pdev, NULL); 1153 pci_set_drvdata(pdev, NULL);
@@ -1038,7 +1176,7 @@ static int __devinit mb862xxfb_init(void)
1038 int ret = -ENODEV; 1176 int ret = -ENODEV;
1039 1177
1040#if defined(CONFIG_FB_MB862XX_LIME) 1178#if defined(CONFIG_FB_MB862XX_LIME)
1041 ret = of_register_platform_driver(&of_platform_mb862xxfb_driver); 1179 ret = platform_driver_register(&of_platform_mb862xxfb_driver);
1042#endif 1180#endif
1043#if defined(CONFIG_FB_MB862XX_PCI_GDC) 1181#if defined(CONFIG_FB_MB862XX_PCI_GDC)
1044 ret = pci_register_driver(&mb862xxfb_pci_driver); 1182 ret = pci_register_driver(&mb862xxfb_pci_driver);
@@ -1049,7 +1187,7 @@ static int __devinit mb862xxfb_init(void)
1049static void __exit mb862xxfb_exit(void) 1187static void __exit mb862xxfb_exit(void)
1050{ 1188{
1051#if defined(CONFIG_FB_MB862XX_LIME) 1189#if defined(CONFIG_FB_MB862XX_LIME)
1052 of_unregister_platform_driver(&of_platform_mb862xxfb_driver); 1190 platform_driver_unregister(&of_platform_mb862xxfb_driver);
1053#endif 1191#endif
1054#if defined(CONFIG_FB_MB862XX_PCI_GDC) 1192#if defined(CONFIG_FB_MB862XX_PCI_GDC)
1055 pci_unregister_driver(&mb862xxfb_pci_driver); 1193 pci_unregister_driver(&mb862xxfb_pci_driver);
diff --git a/drivers/video/mbx/mbxdebugfs.c b/drivers/video/mbx/mbxdebugfs.c
index ecad96524570..12dec7634c55 100644
--- a/drivers/video/mbx/mbxdebugfs.c
+++ b/drivers/video/mbx/mbxdebugfs.c
@@ -175,36 +175,42 @@ static const struct file_operations sysconf_fops = {
175 .read = sysconf_read_file, 175 .read = sysconf_read_file,
176 .write = write_file_dummy, 176 .write = write_file_dummy,
177 .open = open_file_generic, 177 .open = open_file_generic,
178 .llseek = default_llseek,
178}; 179};
179 180
180static const struct file_operations clock_fops = { 181static const struct file_operations clock_fops = {
181 .read = clock_read_file, 182 .read = clock_read_file,
182 .write = write_file_dummy, 183 .write = write_file_dummy,
183 .open = open_file_generic, 184 .open = open_file_generic,
185 .llseek = default_llseek,
184}; 186};
185 187
186static const struct file_operations display_fops = { 188static const struct file_operations display_fops = {
187 .read = display_read_file, 189 .read = display_read_file,
188 .write = write_file_dummy, 190 .write = write_file_dummy,
189 .open = open_file_generic, 191 .open = open_file_generic,
192 .llseek = default_llseek,
190}; 193};
191 194
192static const struct file_operations gsctl_fops = { 195static const struct file_operations gsctl_fops = {
193 .read = gsctl_read_file, 196 .read = gsctl_read_file,
194 .write = write_file_dummy, 197 .write = write_file_dummy,
195 .open = open_file_generic, 198 .open = open_file_generic,
199 .llseek = default_llseek,
196}; 200};
197 201
198static const struct file_operations sdram_fops = { 202static const struct file_operations sdram_fops = {
199 .read = sdram_read_file, 203 .read = sdram_read_file,
200 .write = write_file_dummy, 204 .write = write_file_dummy,
201 .open = open_file_generic, 205 .open = open_file_generic,
206 .llseek = default_llseek,
202}; 207};
203 208
204static const struct file_operations misc_fops = { 209static const struct file_operations misc_fops = {
205 .read = misc_read_file, 210 .read = misc_read_file,
206 .write = write_file_dummy, 211 .write = write_file_dummy,
207 .open = open_file_generic, 212 .open = open_file_generic,
213 .llseek = default_llseek,
208}; 214};
209 215
210static void __devinit mbxfb_debugfs_init(struct fb_info *fbi) 216static void __devinit mbxfb_debugfs_init(struct fb_info *fbi)
diff --git a/drivers/video/metronomefb.c b/drivers/video/metronomefb.c
index 9b3d6e4584cc..97d45e5115e2 100644
--- a/drivers/video/metronomefb.c
+++ b/drivers/video/metronomefb.c
@@ -10,7 +10,7 @@
10 * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven. 10 * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
11 * 11 *
12 * This work was made possible by help and equipment support from E-Ink 12 * This work was made possible by help and equipment support from E-Ink
13 * Corporation. http://support.eink.com/community 13 * Corporation. http://www.eink.com/
14 * 14 *
15 * This driver is written to be used with the Metronome display controller. 15 * This driver is written to be used with the Metronome display controller.
16 * It is intended to be architecture independent. A board specific driver 16 * It is intended to be architecture independent. A board specific driver
@@ -628,12 +628,10 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
628 /* we need to add a spare page because our csum caching scheme walks 628 /* we need to add a spare page because our csum caching scheme walks
629 * to the end of the page */ 629 * to the end of the page */
630 videomemorysize = PAGE_SIZE + (fw * fh); 630 videomemorysize = PAGE_SIZE + (fw * fh);
631 videomemory = vmalloc(videomemorysize); 631 videomemory = vzalloc(videomemorysize);
632 if (!videomemory) 632 if (!videomemory)
633 goto err_fb_rel; 633 goto err_fb_rel;
634 634
635 memset(videomemory, 0, videomemorysize);
636
637 info->screen_base = (char __force __iomem *)videomemory; 635 info->screen_base = (char __force __iomem *)videomemory;
638 info->fbops = &metronomefb_ops; 636 info->fbops = &metronomefb_ops;
639 637
@@ -765,7 +763,7 @@ static int __devexit metronomefb_remove(struct platform_device *dev)
765 763
766static struct platform_driver metronomefb_driver = { 764static struct platform_driver metronomefb_driver = {
767 .probe = metronomefb_probe, 765 .probe = metronomefb_probe,
768 .remove = metronomefb_remove, 766 .remove = __devexit_p(metronomefb_remove),
769 .driver = { 767 .driver = {
770 .owner = THIS_MODULE, 768 .owner = THIS_MODULE,
771 .name = "metronomefb", 769 .name = "metronomefb",
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index 0a4dbdc1693a..cb175fe7abc0 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -32,252 +32,323 @@
32const char *fb_mode_option; 32const char *fb_mode_option;
33EXPORT_SYMBOL_GPL(fb_mode_option); 33EXPORT_SYMBOL_GPL(fb_mode_option);
34 34
35 /* 35/*
36 * Standard video mode definitions (taken from XFree86) 36 * Standard video mode definitions (taken from XFree86)
37 */ 37 */
38 38
39static const struct fb_videomode modedb[] = { 39static const struct fb_videomode modedb[] = {
40 { 40
41 /* 640x400 @ 70 Hz, 31.5 kHz hsync */ 41 /* 640x400 @ 70 Hz, 31.5 kHz hsync */
42 NULL, 70, 640, 400, 39721, 40, 24, 39, 9, 96, 2, 42 { NULL, 70, 640, 400, 39721, 40, 24, 39, 9, 96, 2, 0,
43 0, FB_VMODE_NONINTERLACED 43 FB_VMODE_NONINTERLACED },
44 }, { 44
45 /* 640x480 @ 60 Hz, 31.5 kHz hsync */ 45 /* 640x480 @ 60 Hz, 31.5 kHz hsync */
46 NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2, 46 { NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2, 0,
47 0, FB_VMODE_NONINTERLACED 47 FB_VMODE_NONINTERLACED },
48 }, { 48
49 /* 800x600 @ 56 Hz, 35.15 kHz hsync */ 49 /* 800x600 @ 56 Hz, 35.15 kHz hsync */
50 NULL, 56, 800, 600, 27777, 128, 24, 22, 1, 72, 2, 50 { NULL, 56, 800, 600, 27777, 128, 24, 22, 1, 72, 2, 0,
51 0, FB_VMODE_NONINTERLACED 51 FB_VMODE_NONINTERLACED },
52 }, { 52
53 /* 1024x768 @ 87 Hz interlaced, 35.5 kHz hsync */ 53 /* 1024x768 @ 87 Hz interlaced, 35.5 kHz hsync */
54 NULL, 87, 1024, 768, 22271, 56, 24, 33, 8, 160, 8, 54 { NULL, 87, 1024, 768, 22271, 56, 24, 33, 8, 160, 8, 0,
55 0, FB_VMODE_INTERLACED 55 FB_VMODE_INTERLACED },
56 }, { 56
57 /* 640x400 @ 85 Hz, 37.86 kHz hsync */ 57 /* 640x400 @ 85 Hz, 37.86 kHz hsync */
58 NULL, 85, 640, 400, 31746, 96, 32, 41, 1, 64, 3, 58 { NULL, 85, 640, 400, 31746, 96, 32, 41, 1, 64, 3,
59 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED 59 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
60 }, { 60
61 /* 640x480 @ 72 Hz, 36.5 kHz hsync */ 61 /* 640x480 @ 72 Hz, 36.5 kHz hsync */
62 NULL, 72, 640, 480, 31746, 144, 40, 30, 8, 40, 3, 62 { NULL, 72, 640, 480, 31746, 144, 40, 30, 8, 40, 3, 0,
63 0, FB_VMODE_NONINTERLACED 63 FB_VMODE_NONINTERLACED },
64 }, { 64
65 /* 640x480 @ 75 Hz, 37.50 kHz hsync */ 65 /* 640x480 @ 75 Hz, 37.50 kHz hsync */
66 NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3, 66 { NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3, 0,
67 0, FB_VMODE_NONINTERLACED 67 FB_VMODE_NONINTERLACED },
68 }, { 68
69 /* 800x600 @ 60 Hz, 37.8 kHz hsync */ 69 /* 800x600 @ 60 Hz, 37.8 kHz hsync */
70 NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4, 70 { NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4,
71 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED 71 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
72 }, { 72 FB_VMODE_NONINTERLACED },
73
73 /* 640x480 @ 85 Hz, 43.27 kHz hsync */ 74 /* 640x480 @ 85 Hz, 43.27 kHz hsync */
74 NULL, 85, 640, 480, 27777, 80, 56, 25, 1, 56, 3, 75 { NULL, 85, 640, 480, 27777, 80, 56, 25, 1, 56, 3, 0,
75 0, FB_VMODE_NONINTERLACED 76 FB_VMODE_NONINTERLACED },
76 }, { 77
77 /* 1152x864 @ 89 Hz interlaced, 44 kHz hsync */ 78 /* 1152x864 @ 89 Hz interlaced, 44 kHz hsync */
78 NULL, 89, 1152, 864, 15384, 96, 16, 110, 1, 216, 10, 79 { NULL, 89, 1152, 864, 15384, 96, 16, 110, 1, 216, 10, 0,
79 0, FB_VMODE_INTERLACED 80 FB_VMODE_INTERLACED },
80 }, {
81 /* 800x600 @ 72 Hz, 48.0 kHz hsync */ 81 /* 800x600 @ 72 Hz, 48.0 kHz hsync */
82 NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6, 82 { NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
83 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED 83 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
84 }, { 84 FB_VMODE_NONINTERLACED },
85
85 /* 1024x768 @ 60 Hz, 48.4 kHz hsync */ 86 /* 1024x768 @ 60 Hz, 48.4 kHz hsync */
86 NULL, 60, 1024, 768, 15384, 168, 8, 29, 3, 144, 6, 87 { NULL, 60, 1024, 768, 15384, 168, 8, 29, 3, 144, 6, 0,
87 0, FB_VMODE_NONINTERLACED 88 FB_VMODE_NONINTERLACED },
88 }, { 89
89 /* 640x480 @ 100 Hz, 53.01 kHz hsync */ 90 /* 640x480 @ 100 Hz, 53.01 kHz hsync */
90 NULL, 100, 640, 480, 21834, 96, 32, 36, 8, 96, 6, 91 { NULL, 100, 640, 480, 21834, 96, 32, 36, 8, 96, 6, 0,
91 0, FB_VMODE_NONINTERLACED 92 FB_VMODE_NONINTERLACED },
92 }, { 93
93 /* 1152x864 @ 60 Hz, 53.5 kHz hsync */ 94 /* 1152x864 @ 60 Hz, 53.5 kHz hsync */
94 NULL, 60, 1152, 864, 11123, 208, 64, 16, 4, 256, 8, 95 { NULL, 60, 1152, 864, 11123, 208, 64, 16, 4, 256, 8, 0,
95 0, FB_VMODE_NONINTERLACED 96 FB_VMODE_NONINTERLACED },
96 }, { 97
97 /* 800x600 @ 85 Hz, 55.84 kHz hsync */ 98 /* 800x600 @ 85 Hz, 55.84 kHz hsync */
98 NULL, 85, 800, 600, 16460, 160, 64, 36, 16, 64, 5, 99 { NULL, 85, 800, 600, 16460, 160, 64, 36, 16, 64, 5, 0,
99 0, FB_VMODE_NONINTERLACED 100 FB_VMODE_NONINTERLACED },
100 }, { 101
101 /* 1024x768 @ 70 Hz, 56.5 kHz hsync */ 102 /* 1024x768 @ 70 Hz, 56.5 kHz hsync */
102 NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6, 103 { NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6, 0,
103 0, FB_VMODE_NONINTERLACED 104 FB_VMODE_NONINTERLACED },
104 }, { 105
105 /* 1280x1024 @ 87 Hz interlaced, 51 kHz hsync */ 106 /* 1280x1024 @ 87 Hz interlaced, 51 kHz hsync */
106 NULL, 87, 1280, 1024, 12500, 56, 16, 128, 1, 216, 12, 107 { NULL, 87, 1280, 1024, 12500, 56, 16, 128, 1, 216, 12, 0,
107 0, FB_VMODE_INTERLACED 108 FB_VMODE_INTERLACED },
108 }, { 109
109 /* 800x600 @ 100 Hz, 64.02 kHz hsync */ 110 /* 800x600 @ 100 Hz, 64.02 kHz hsync */
110 NULL, 100, 800, 600, 14357, 160, 64, 30, 4, 64, 6, 111 { NULL, 100, 800, 600, 14357, 160, 64, 30, 4, 64, 6, 0,
111 0, FB_VMODE_NONINTERLACED 112 FB_VMODE_NONINTERLACED },
112 }, { 113
113 /* 1024x768 @ 76 Hz, 62.5 kHz hsync */ 114 /* 1024x768 @ 76 Hz, 62.5 kHz hsync */
114 NULL, 76, 1024, 768, 11764, 208, 8, 36, 16, 120, 3, 115 { NULL, 76, 1024, 768, 11764, 208, 8, 36, 16, 120, 3, 0,
115 0, FB_VMODE_NONINTERLACED 116 FB_VMODE_NONINTERLACED },
116 }, { 117
117 /* 1152x864 @ 70 Hz, 62.4 kHz hsync */ 118 /* 1152x864 @ 70 Hz, 62.4 kHz hsync */
118 NULL, 70, 1152, 864, 10869, 106, 56, 20, 1, 160, 10, 119 { NULL, 70, 1152, 864, 10869, 106, 56, 20, 1, 160, 10, 0,
119 0, FB_VMODE_NONINTERLACED 120 FB_VMODE_NONINTERLACED },
120 }, { 121
121 /* 1280x1024 @ 61 Hz, 64.2 kHz hsync */ 122 /* 1280x1024 @ 61 Hz, 64.2 kHz hsync */
122 NULL, 61, 1280, 1024, 9090, 200, 48, 26, 1, 184, 3, 123 { NULL, 61, 1280, 1024, 9090, 200, 48, 26, 1, 184, 3, 0,
123 0, FB_VMODE_NONINTERLACED 124 FB_VMODE_NONINTERLACED },
124 }, { 125
125 /* 1400x1050 @ 60Hz, 63.9 kHz hsync */ 126 /* 1400x1050 @ 60Hz, 63.9 kHz hsync */
126 NULL, 60, 1400, 1050, 9259, 136, 40, 13, 1, 112, 3, 127 { NULL, 60, 1400, 1050, 9259, 136, 40, 13, 1, 112, 3, 0,
127 0, FB_VMODE_NONINTERLACED 128 FB_VMODE_NONINTERLACED },
128 }, { 129
129 /* 1400x1050 @ 75,107 Hz, 82,392 kHz +hsync +vsync*/ 130 /* 1400x1050 @ 75,107 Hz, 82,392 kHz +hsync +vsync*/
130 NULL, 75, 1400, 1050, 7190, 120, 56, 23, 10, 112, 13, 131 { NULL, 75, 1400, 1050, 7190, 120, 56, 23, 10, 112, 13,
131 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED 132 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
132 }, { 133 FB_VMODE_NONINTERLACED },
134
133 /* 1400x1050 @ 60 Hz, ? kHz +hsync +vsync*/ 135 /* 1400x1050 @ 60 Hz, ? kHz +hsync +vsync*/
134 NULL, 60, 1400, 1050, 9259, 128, 40, 12, 0, 112, 3, 136 { NULL, 60, 1400, 1050, 9259, 128, 40, 12, 0, 112, 3,
135 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED 137 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
136 }, { 138 FB_VMODE_NONINTERLACED },
139
137 /* 1024x768 @ 85 Hz, 70.24 kHz hsync */ 140 /* 1024x768 @ 85 Hz, 70.24 kHz hsync */
138 NULL, 85, 1024, 768, 10111, 192, 32, 34, 14, 160, 6, 141 { NULL, 85, 1024, 768, 10111, 192, 32, 34, 14, 160, 6, 0,
139 0, FB_VMODE_NONINTERLACED 142 FB_VMODE_NONINTERLACED },
140 }, { 143
141 /* 1152x864 @ 78 Hz, 70.8 kHz hsync */ 144 /* 1152x864 @ 78 Hz, 70.8 kHz hsync */
142 NULL, 78, 1152, 864, 9090, 228, 88, 32, 0, 84, 12, 145 { NULL, 78, 1152, 864, 9090, 228, 88, 32, 0, 84, 12, 0,
143 0, FB_VMODE_NONINTERLACED 146 FB_VMODE_NONINTERLACED },
144 }, { 147
145 /* 1280x1024 @ 70 Hz, 74.59 kHz hsync */ 148 /* 1280x1024 @ 70 Hz, 74.59 kHz hsync */
146 NULL, 70, 1280, 1024, 7905, 224, 32, 28, 8, 160, 8, 149 { NULL, 70, 1280, 1024, 7905, 224, 32, 28, 8, 160, 8, 0,
147 0, FB_VMODE_NONINTERLACED 150 FB_VMODE_NONINTERLACED },
148 }, { 151
149 /* 1600x1200 @ 60Hz, 75.00 kHz hsync */ 152 /* 1600x1200 @ 60Hz, 75.00 kHz hsync */
150 NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3, 153 { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
151 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED 154 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
152 }, { 155 FB_VMODE_NONINTERLACED },
156
153 /* 1152x864 @ 84 Hz, 76.0 kHz hsync */ 157 /* 1152x864 @ 84 Hz, 76.0 kHz hsync */
154 NULL, 84, 1152, 864, 7407, 184, 312, 32, 0, 128, 12, 158 { NULL, 84, 1152, 864, 7407, 184, 312, 32, 0, 128, 12, 0,
155 0, FB_VMODE_NONINTERLACED 159 FB_VMODE_NONINTERLACED },
156 }, { 160
157 /* 1280x1024 @ 74 Hz, 78.85 kHz hsync */ 161 /* 1280x1024 @ 74 Hz, 78.85 kHz hsync */
158 NULL, 74, 1280, 1024, 7407, 256, 32, 34, 3, 144, 3, 162 { NULL, 74, 1280, 1024, 7407, 256, 32, 34, 3, 144, 3, 0,
159 0, FB_VMODE_NONINTERLACED 163 FB_VMODE_NONINTERLACED },
160 }, { 164
161 /* 1024x768 @ 100Hz, 80.21 kHz hsync */ 165 /* 1024x768 @ 100Hz, 80.21 kHz hsync */
162 NULL, 100, 1024, 768, 8658, 192, 32, 21, 3, 192, 10, 166 { NULL, 100, 1024, 768, 8658, 192, 32, 21, 3, 192, 10, 0,
163 0, FB_VMODE_NONINTERLACED 167 FB_VMODE_NONINTERLACED },
164 }, { 168
165 /* 1280x1024 @ 76 Hz, 81.13 kHz hsync */ 169 /* 1280x1024 @ 76 Hz, 81.13 kHz hsync */
166 NULL, 76, 1280, 1024, 7407, 248, 32, 34, 3, 104, 3, 170 { NULL, 76, 1280, 1024, 7407, 248, 32, 34, 3, 104, 3, 0,
167 0, FB_VMODE_NONINTERLACED 171 FB_VMODE_NONINTERLACED },
168 }, { 172
169 /* 1600x1200 @ 70 Hz, 87.50 kHz hsync */ 173 /* 1600x1200 @ 70 Hz, 87.50 kHz hsync */
170 NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3, 174 { NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3, 0,
171 0, FB_VMODE_NONINTERLACED 175 FB_VMODE_NONINTERLACED },
172 }, { 176
173 /* 1152x864 @ 100 Hz, 89.62 kHz hsync */ 177 /* 1152x864 @ 100 Hz, 89.62 kHz hsync */
174 NULL, 100, 1152, 864, 7264, 224, 32, 17, 2, 128, 19, 178 { NULL, 100, 1152, 864, 7264, 224, 32, 17, 2, 128, 19, 0,
175 0, FB_VMODE_NONINTERLACED 179 FB_VMODE_NONINTERLACED },
176 }, { 180
177 /* 1280x1024 @ 85 Hz, 91.15 kHz hsync */ 181 /* 1280x1024 @ 85 Hz, 91.15 kHz hsync */
178 NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3, 182 { NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
179 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED 183 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
180 }, { 184 FB_VMODE_NONINTERLACED },
185
181 /* 1600x1200 @ 75 Hz, 93.75 kHz hsync */ 186 /* 1600x1200 @ 75 Hz, 93.75 kHz hsync */
182 NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3, 187 { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
183 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED 188 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
184 }, { 189 FB_VMODE_NONINTERLACED },
190
185 /* 1680x1050 @ 60 Hz, 65.191 kHz hsync */ 191 /* 1680x1050 @ 60 Hz, 65.191 kHz hsync */
186 NULL, 60, 1680, 1050, 6848, 280, 104, 30, 3, 176, 6, 192 { NULL, 60, 1680, 1050, 6848, 280, 104, 30, 3, 176, 6,
187 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED 193 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
188 }, { 194 FB_VMODE_NONINTERLACED },
195
189 /* 1600x1200 @ 85 Hz, 105.77 kHz hsync */ 196 /* 1600x1200 @ 85 Hz, 105.77 kHz hsync */
190 NULL, 85, 1600, 1200, 4545, 272, 16, 37, 4, 192, 3, 197 { NULL, 85, 1600, 1200, 4545, 272, 16, 37, 4, 192, 3,
191 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED 198 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
192 }, { 199 FB_VMODE_NONINTERLACED },
200
193 /* 1280x1024 @ 100 Hz, 107.16 kHz hsync */ 201 /* 1280x1024 @ 100 Hz, 107.16 kHz hsync */
194 NULL, 100, 1280, 1024, 5502, 256, 32, 26, 7, 128, 15, 202 { NULL, 100, 1280, 1024, 5502, 256, 32, 26, 7, 128, 15, 0,
195 0, FB_VMODE_NONINTERLACED 203 FB_VMODE_NONINTERLACED },
196 }, { 204
197 /* 1800x1440 @ 64Hz, 96.15 kHz hsync */ 205 /* 1800x1440 @ 64Hz, 96.15 kHz hsync */
198 NULL, 64, 1800, 1440, 4347, 304, 96, 46, 1, 192, 3, 206 { NULL, 64, 1800, 1440, 4347, 304, 96, 46, 1, 192, 3,
199 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED 207 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
200 }, { 208 FB_VMODE_NONINTERLACED },
209
201 /* 1800x1440 @ 70Hz, 104.52 kHz hsync */ 210 /* 1800x1440 @ 70Hz, 104.52 kHz hsync */
202 NULL, 70, 1800, 1440, 4000, 304, 96, 46, 1, 192, 3, 211 { NULL, 70, 1800, 1440, 4000, 304, 96, 46, 1, 192, 3,
203 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED 212 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
204 }, { 213 FB_VMODE_NONINTERLACED },
214
205 /* 512x384 @ 78 Hz, 31.50 kHz hsync */ 215 /* 512x384 @ 78 Hz, 31.50 kHz hsync */
206 NULL, 78, 512, 384, 49603, 48, 16, 16, 1, 64, 3, 216 { NULL, 78, 512, 384, 49603, 48, 16, 16, 1, 64, 3, 0,
207 0, FB_VMODE_NONINTERLACED 217 FB_VMODE_NONINTERLACED },
208 }, { 218
209 /* 512x384 @ 85 Hz, 34.38 kHz hsync */ 219 /* 512x384 @ 85 Hz, 34.38 kHz hsync */
210 NULL, 85, 512, 384, 45454, 48, 16, 16, 1, 64, 3, 220 { NULL, 85, 512, 384, 45454, 48, 16, 16, 1, 64, 3, 0,
211 0, FB_VMODE_NONINTERLACED 221 FB_VMODE_NONINTERLACED },
212 }, { 222
213 /* 320x200 @ 70 Hz, 31.5 kHz hsync, 8:5 aspect ratio */ 223 /* 320x200 @ 70 Hz, 31.5 kHz hsync, 8:5 aspect ratio */
214 NULL, 70, 320, 200, 79440, 16, 16, 20, 4, 48, 1, 224 { NULL, 70, 320, 200, 79440, 16, 16, 20, 4, 48, 1, 0,
215 0, FB_VMODE_DOUBLE 225 FB_VMODE_DOUBLE },
216 }, { 226
217 /* 320x240 @ 60 Hz, 31.5 kHz hsync, 4:3 aspect ratio */ 227 /* 320x240 @ 60 Hz, 31.5 kHz hsync, 4:3 aspect ratio */
218 NULL, 60, 320, 240, 79440, 16, 16, 16, 5, 48, 1, 228 { NULL, 60, 320, 240, 79440, 16, 16, 16, 5, 48, 1, 0,
219 0, FB_VMODE_DOUBLE 229 FB_VMODE_DOUBLE },
220 }, { 230
221 /* 320x240 @ 72 Hz, 36.5 kHz hsync */ 231 /* 320x240 @ 72 Hz, 36.5 kHz hsync */
222 NULL, 72, 320, 240, 63492, 16, 16, 16, 4, 48, 2, 232 { NULL, 72, 320, 240, 63492, 16, 16, 16, 4, 48, 2, 0,
223 0, FB_VMODE_DOUBLE 233 FB_VMODE_DOUBLE },
224 }, { 234
225 /* 400x300 @ 56 Hz, 35.2 kHz hsync, 4:3 aspect ratio */ 235 /* 400x300 @ 56 Hz, 35.2 kHz hsync, 4:3 aspect ratio */
226 NULL, 56, 400, 300, 55555, 64, 16, 10, 1, 32, 1, 236 { NULL, 56, 400, 300, 55555, 64, 16, 10, 1, 32, 1, 0,
227 0, FB_VMODE_DOUBLE 237 FB_VMODE_DOUBLE },
228 }, { 238
229 /* 400x300 @ 60 Hz, 37.8 kHz hsync */ 239 /* 400x300 @ 60 Hz, 37.8 kHz hsync */
230 NULL, 60, 400, 300, 50000, 48, 16, 11, 1, 64, 2, 240 { NULL, 60, 400, 300, 50000, 48, 16, 11, 1, 64, 2, 0,
231 0, FB_VMODE_DOUBLE 241 FB_VMODE_DOUBLE },
232 }, { 242
233 /* 400x300 @ 72 Hz, 48.0 kHz hsync */ 243 /* 400x300 @ 72 Hz, 48.0 kHz hsync */
234 NULL, 72, 400, 300, 40000, 32, 24, 11, 19, 64, 3, 244 { NULL, 72, 400, 300, 40000, 32, 24, 11, 19, 64, 3, 0,
235 0, FB_VMODE_DOUBLE 245 FB_VMODE_DOUBLE },
236 }, { 246
237 /* 480x300 @ 56 Hz, 35.2 kHz hsync, 8:5 aspect ratio */ 247 /* 480x300 @ 56 Hz, 35.2 kHz hsync, 8:5 aspect ratio */
238 NULL, 56, 480, 300, 46176, 80, 16, 10, 1, 40, 1, 248 { NULL, 56, 480, 300, 46176, 80, 16, 10, 1, 40, 1, 0,
239 0, FB_VMODE_DOUBLE 249 FB_VMODE_DOUBLE },
240 }, { 250
241 /* 480x300 @ 60 Hz, 37.8 kHz hsync */ 251 /* 480x300 @ 60 Hz, 37.8 kHz hsync */
242 NULL, 60, 480, 300, 41858, 56, 16, 11, 1, 80, 2, 252 { NULL, 60, 480, 300, 41858, 56, 16, 11, 1, 80, 2, 0,
243 0, FB_VMODE_DOUBLE 253 FB_VMODE_DOUBLE },
244 }, { 254
245 /* 480x300 @ 63 Hz, 39.6 kHz hsync */ 255 /* 480x300 @ 63 Hz, 39.6 kHz hsync */
246 NULL, 63, 480, 300, 40000, 56, 16, 11, 1, 80, 2, 256 { NULL, 63, 480, 300, 40000, 56, 16, 11, 1, 80, 2, 0,
247 0, FB_VMODE_DOUBLE 257 FB_VMODE_DOUBLE },
248 }, { 258
249 /* 480x300 @ 72 Hz, 48.0 kHz hsync */ 259 /* 480x300 @ 72 Hz, 48.0 kHz hsync */
250 NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3, 260 { NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3, 0,
251 0, FB_VMODE_DOUBLE 261 FB_VMODE_DOUBLE },
252 }, { 262
253 /* 1920x1200 @ 60 Hz, 74.5 Khz hsync */ 263 /* 1920x1200 @ 60 Hz, 74.5 Khz hsync */
254 NULL, 60, 1920, 1200, 5177, 128, 336, 1, 38, 208, 3, 264 { NULL, 60, 1920, 1200, 5177, 128, 336, 1, 38, 208, 3,
255 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 265 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
256 FB_VMODE_NONINTERLACED 266 FB_VMODE_NONINTERLACED },
257 }, { 267
258 /* 1152x768, 60 Hz, PowerBook G4 Titanium I and II */ 268 /* 1152x768, 60 Hz, PowerBook G4 Titanium I and II */
259 NULL, 60, 1152, 768, 14047, 158, 26, 29, 3, 136, 6, 269 { NULL, 60, 1152, 768, 14047, 158, 26, 29, 3, 136, 6,
260 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED 270 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
261 }, { 271 FB_VMODE_NONINTERLACED },
272
262 /* 1366x768, 60 Hz, 47.403 kHz hsync, WXGA 16:9 aspect ratio */ 273 /* 1366x768, 60 Hz, 47.403 kHz hsync, WXGA 16:9 aspect ratio */
263 NULL, 60, 1366, 768, 13806, 120, 10, 14, 3, 32, 5, 274 { NULL, 60, 1366, 768, 13806, 120, 10, 14, 3, 32, 5, 0,
264 0, FB_VMODE_NONINTERLACED 275 FB_VMODE_NONINTERLACED },
265 }, { 276
266 /* 1280x800, 60 Hz, 47.403 kHz hsync, WXGA 16:10 aspect ratio */ 277 /* 1280x800, 60 Hz, 47.403 kHz hsync, WXGA 16:10 aspect ratio */
267 NULL, 60, 1280, 800, 12048, 200, 64, 24, 1, 136, 3, 278 { NULL, 60, 1280, 800, 12048, 200, 64, 24, 1, 136, 3, 0,
268 0, FB_VMODE_NONINTERLACED 279 FB_VMODE_NONINTERLACED },
269 }, { 280
270 /* 720x576i @ 50 Hz, 15.625 kHz hsync (PAL RGB) */ 281 /* 720x576i @ 50 Hz, 15.625 kHz hsync (PAL RGB) */
271 NULL, 50, 720, 576, 74074, 64, 16, 39, 5, 64, 5, 282 { NULL, 50, 720, 576, 74074, 64, 16, 39, 5, 64, 5, 0,
272 0, FB_VMODE_INTERLACED 283 FB_VMODE_INTERLACED },
273 }, { 284
274 /* 800x520i @ 50 Hz, 15.625 kHz hsync (PAL RGB) */ 285 /* 800x520i @ 50 Hz, 15.625 kHz hsync (PAL RGB) */
275 NULL, 50, 800, 520, 58823, 144, 64, 72, 28, 80, 5, 286 { NULL, 50, 800, 520, 58823, 144, 64, 72, 28, 80, 5, 0,
276 0, FB_VMODE_INTERLACED 287 FB_VMODE_INTERLACED },
277 }, 288
289 /* 864x480 @ 60 Hz, 35.15 kHz hsync */
290 { NULL, 60, 864, 480, 27777, 1, 1, 1, 1, 0, 0,
291 0, FB_VMODE_NONINTERLACED },
278}; 292};
279 293
280#ifdef CONFIG_FB_MODE_HELPERS 294#ifdef CONFIG_FB_MODE_HELPERS
295const struct fb_videomode cea_modes[64] = {
296 /* #1: 640x480p@59.94/60Hz */
297 [1] = {
298 NULL, 60, 640, 480, 39722, 48, 16, 33, 10, 96, 2, 0,
299 FB_VMODE_NONINTERLACED, 0,
300 },
301 /* #3: 720x480p@59.94/60Hz */
302 [3] = {
303 NULL, 60, 720, 480, 37037, 60, 16, 30, 9, 62, 6, 0,
304 FB_VMODE_NONINTERLACED, 0,
305 },
306 /* #5: 1920x1080i@59.94/60Hz */
307 [5] = {
308 NULL, 60, 1920, 1080, 13763, 148, 88, 15, 2, 44, 5,
309 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
310 FB_VMODE_INTERLACED, 0,
311 },
312 /* #7: 720(1440)x480iH@59.94/60Hz */
313 [7] = {
314 NULL, 60, 1440, 480, 18554/*37108*/, 114, 38, 15, 4, 124, 3, 0,
315 FB_VMODE_INTERLACED, 0,
316 },
317 /* #9: 720(1440)x240pH@59.94/60Hz */
318 [9] = {
319 NULL, 60, 1440, 240, 18554, 114, 38, 16, 4, 124, 3, 0,
320 FB_VMODE_NONINTERLACED, 0,
321 },
322 /* #18: 720x576pH@50Hz */
323 [18] = {
324 NULL, 50, 720, 576, 37037, 68, 12, 39, 5, 64, 5, 0,
325 FB_VMODE_NONINTERLACED, 0,
326 },
327 /* #19: 1280x720p@50Hz */
328 [19] = {
329 NULL, 50, 1280, 720, 13468, 220, 440, 20, 5, 40, 5,
330 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
331 FB_VMODE_NONINTERLACED, 0,
332 },
333 /* #20: 1920x1080i@50Hz */
334 [20] = {
335 NULL, 50, 1920, 1080, 13480, 148, 528, 15, 5, 528, 5,
336 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
337 FB_VMODE_INTERLACED, 0,
338 },
339 /* #32: 1920x1080p@23.98/24Hz */
340 [32] = {
341 NULL, 24, 1920, 1080, 13468, 148, 638, 36, 4, 44, 5,
342 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
343 FB_VMODE_NONINTERLACED, 0,
344 },
345 /* #35: (2880)x480p4x@59.94/60Hz */
346 [35] = {
347 NULL, 60, 2880, 480, 9250, 240, 64, 30, 9, 248, 6, 0,
348 FB_VMODE_NONINTERLACED, 0,
349 },
350};
351
281const struct fb_videomode vesa_modes[] = { 352const struct fb_videomode vesa_modes[] = {
282 /* 0 640x350-85 VESA */ 353 /* 0 640x350-85 VESA */
283 { NULL, 85, 640, 350, 31746, 96, 32, 60, 32, 64, 3, 354 { NULL, 85, 640, 350, 31746, 96, 32, 60, 32, 64, 3,
@@ -289,10 +360,10 @@ const struct fb_videomode vesa_modes[] = {
289 { NULL, 85, 721, 400, 28169, 108, 36, 42, 01, 72, 3, 360 { NULL, 85, 721, 400, 28169, 108, 36, 42, 01, 72, 3,
290 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, 361 FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
291 /* 3 640x480-60 VESA */ 362 /* 3 640x480-60 VESA */
292 { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, 363 { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2,
293 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, 364 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
294 /* 4 640x480-72 VESA */ 365 /* 4 640x480-72 VESA */
295 { NULL, 72, 640, 480, 31746, 128, 24, 29, 9, 40, 2, 366 { NULL, 72, 640, 480, 31746, 128, 24, 29, 9, 40, 2,
296 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, 367 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
297 /* 5 640x480-75 VESA */ 368 /* 5 640x480-75 VESA */
298 { NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3, 369 { NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3,
@@ -375,7 +446,7 @@ const struct fb_videomode vesa_modes[] = {
375 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 446 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
376 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, 447 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
377 /* 26 1600x1200-75 VESA */ 448 /* 26 1600x1200-75 VESA */
378 { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3, 449 { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
379 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 450 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
380 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, 451 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
381 /* 27 1600x1200-85 VESA */ 452 /* 27 1600x1200-85 VESA */
@@ -855,6 +926,7 @@ const struct fb_videomode *fb_find_nearest_mode(const struct fb_videomode *mode,
855 abs(cmode->yres - mode->yres); 926 abs(cmode->yres - mode->yres);
856 if (diff > d) { 927 if (diff > d) {
857 diff = d; 928 diff = d;
929 diff_refresh = abs(cmode->refresh - mode->refresh);
858 best = cmode; 930 best = cmode;
859 } else if (diff == d) { 931 } else if (diff == d) {
860 d = abs(cmode->refresh - mode->refresh); 932 d = abs(cmode->refresh - mode->refresh);
@@ -1056,3 +1128,4 @@ EXPORT_SYMBOL(fb_find_best_mode);
1056EXPORT_SYMBOL(fb_find_nearest_mode); 1128EXPORT_SYMBOL(fb_find_nearest_mode);
1057EXPORT_SYMBOL(fb_videomode_to_modelist); 1129EXPORT_SYMBOL(fb_videomode_to_modelist);
1058EXPORT_SYMBOL(fb_find_mode); 1130EXPORT_SYMBOL(fb_find_mode);
1131EXPORT_SYMBOL(fb_find_mode_cvt);
diff --git a/drivers/video/msm/mddi.c b/drivers/video/msm/mddi.c
index 7c316c34dfca..178b0720bd79 100644
--- a/drivers/video/msm/mddi.c
+++ b/drivers/video/msm/mddi.c
@@ -318,7 +318,7 @@ static long mddi_wait_interrupt_timeout(struct mddi_info *mddi,
318static void mddi_wait_interrupt(struct mddi_info *mddi, uint32_t intmask) 318static void mddi_wait_interrupt(struct mddi_info *mddi, uint32_t intmask)
319{ 319{
320 if (mddi_wait_interrupt_timeout(mddi, intmask, HZ/10) == 0) 320 if (mddi_wait_interrupt_timeout(mddi, intmask, HZ/10) == 0)
321 printk(KERN_INFO KERN_ERR "mddi_wait_interrupt %d, timeout " 321 printk(KERN_INFO "mddi_wait_interrupt %d, timeout "
322 "waiting for %x, INT = %x, STAT = %x gotint = %x\n", 322 "waiting for %x, INT = %x, STAT = %x gotint = %x\n",
323 current->pid, intmask, mddi_readl(INT), mddi_readl(STAT), 323 current->pid, intmask, mddi_readl(INT), mddi_readl(STAT),
324 mddi->got_int); 324 mddi->got_int);
@@ -465,8 +465,7 @@ static int __init mddi_get_client_caps(struct mddi_info *mddi)
465 465
466 if (mddi->flags & FLAG_HAVE_CAPS) 466 if (mddi->flags & FLAG_HAVE_CAPS)
467 break; 467 break;
468 printk(KERN_INFO KERN_ERR "mddi_init, timeout waiting for " 468 printk(KERN_INFO "mddi_init, timeout waiting for caps\n");
469 "caps\n");
470 } 469 }
471 return mddi->flags & FLAG_HAVE_CAPS; 470 return mddi->flags & FLAG_HAVE_CAPS;
472} 471}
@@ -680,7 +679,7 @@ static int __devinit mddi_probe(struct platform_device *pdev)
680 printk(KERN_ERR "mddi: no associated mem resource!\n"); 679 printk(KERN_ERR "mddi: no associated mem resource!\n");
681 return -ENOMEM; 680 return -ENOMEM;
682 } 681 }
683 mddi->base = ioremap(resource->start, resource->end - resource->start); 682 mddi->base = ioremap(resource->start, resource_size(resource));
684 if (!mddi->base) { 683 if (!mddi->base) {
685 printk(KERN_ERR "mddi: failed to remap base!\n"); 684 printk(KERN_ERR "mddi: failed to remap base!\n");
686 ret = -EINVAL; 685 ret = -EINVAL;
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 3c28db03ad39..c3636d55a3c5 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -90,7 +90,7 @@ static int locked_disable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
90 mdp_irq_mask &= ~(mask); 90 mdp_irq_mask &= ~(mask);
91 /* if no one is waiting on the interrupt, disable it */ 91 /* if no one is waiting on the interrupt, disable it */
92 if (!mdp_irq_mask) { 92 if (!mdp_irq_mask) {
93 disable_irq(mdp->irq); 93 disable_irq_nosync(mdp->irq);
94 if (clk) 94 if (clk)
95 clk_disable(clk); 95 clk_disable(clk);
96 } 96 }
@@ -482,6 +482,7 @@ int mdp_probe(struct platform_device *pdev)
482 /* register mdp device */ 482 /* register mdp device */
483 mdp->mdp_dev.dev.parent = &pdev->dev; 483 mdp->mdp_dev.dev.parent = &pdev->dev;
484 mdp->mdp_dev.dev.class = mdp_class; 484 mdp->mdp_dev.dev.class = mdp_class;
485 dev_set_name(&mdp->mdp_dev.dev, "mdp%d", pdev->id);
485 486
486 /* if you can remove the platform device you'd have to implement 487 /* if you can remove the platform device you'd have to implement
487 * this: 488 * this:
diff --git a/drivers/video/msm/mdp_hw.h b/drivers/video/msm/mdp_hw.h
index 4e3deb4e592b..d80477415caa 100644
--- a/drivers/video/msm/mdp_hw.h
+++ b/drivers/video/msm/mdp_hw.h
@@ -449,6 +449,7 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
449#define PPP_CFG_MDP_XRGB_8888(dir) PPP_CFG_MDP_ARGB_8888(dir) 449#define PPP_CFG_MDP_XRGB_8888(dir) PPP_CFG_MDP_ARGB_8888(dir)
450#define PPP_CFG_MDP_RGBA_8888(dir) PPP_CFG_MDP_ARGB_8888(dir) 450#define PPP_CFG_MDP_RGBA_8888(dir) PPP_CFG_MDP_ARGB_8888(dir)
451#define PPP_CFG_MDP_BGRA_8888(dir) PPP_CFG_MDP_ARGB_8888(dir) 451#define PPP_CFG_MDP_BGRA_8888(dir) PPP_CFG_MDP_ARGB_8888(dir)
452#define PPP_CFG_MDP_RGBX_8888(dir) PPP_CFG_MDP_ARGB_8888(dir)
452 453
453#define PPP_CFG_MDP_Y_CBCR_H2V2(dir) (PPP_##dir##_C2R_8BIT | \ 454#define PPP_CFG_MDP_Y_CBCR_H2V2(dir) (PPP_##dir##_C2R_8BIT | \
454 PPP_##dir##_C0G_8BIT | \ 455 PPP_##dir##_C0G_8BIT | \
@@ -488,12 +489,14 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
488 MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8) 489 MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8)
489#define PPP_PACK_PATTERN_MDP_RGB_888 PPP_PACK_PATTERN_MDP_RGB_565 490#define PPP_PACK_PATTERN_MDP_RGB_888 PPP_PACK_PATTERN_MDP_RGB_565
490#define PPP_PACK_PATTERN_MDP_XRGB_8888 \ 491#define PPP_PACK_PATTERN_MDP_XRGB_8888 \
491 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, 8) 492 MDP_GET_PACK_PATTERN(CLR_B, CLR_G, CLR_R, CLR_ALPHA, 8)
492#define PPP_PACK_PATTERN_MDP_ARGB_8888 PPP_PACK_PATTERN_MDP_XRGB_8888 493#define PPP_PACK_PATTERN_MDP_ARGB_8888 PPP_PACK_PATTERN_MDP_XRGB_8888
493#define PPP_PACK_PATTERN_MDP_RGBA_8888 \ 494#define PPP_PACK_PATTERN_MDP_RGBA_8888 \
494 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R, 8) 495 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R, 8)
495#define PPP_PACK_PATTERN_MDP_BGRA_8888 \ 496#define PPP_PACK_PATTERN_MDP_BGRA_8888 \
496 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, 8) 497 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, 8)
498#define PPP_PACK_PATTERN_MDP_RGBX_8888 \
499 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R, 8)
497#define PPP_PACK_PATTERN_MDP_Y_CBCR_H2V1 \ 500#define PPP_PACK_PATTERN_MDP_Y_CBCR_H2V1 \
498 MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8) 501 MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8)
499#define PPP_PACK_PATTERN_MDP_Y_CBCR_H2V2 PPP_PACK_PATTERN_MDP_Y_CBCR_H2V1 502#define PPP_PACK_PATTERN_MDP_Y_CBCR_H2V2 PPP_PACK_PATTERN_MDP_Y_CBCR_H2V1
@@ -509,6 +512,7 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
509#define PPP_CHROMA_SAMP_MDP_ARGB_8888(dir) PPP_OP_##dir##_CHROMA_RGB 512#define PPP_CHROMA_SAMP_MDP_ARGB_8888(dir) PPP_OP_##dir##_CHROMA_RGB
510#define PPP_CHROMA_SAMP_MDP_RGBA_8888(dir) PPP_OP_##dir##_CHROMA_RGB 513#define PPP_CHROMA_SAMP_MDP_RGBA_8888(dir) PPP_OP_##dir##_CHROMA_RGB
511#define PPP_CHROMA_SAMP_MDP_BGRA_8888(dir) PPP_OP_##dir##_CHROMA_RGB 514#define PPP_CHROMA_SAMP_MDP_BGRA_8888(dir) PPP_OP_##dir##_CHROMA_RGB
515#define PPP_CHROMA_SAMP_MDP_RGBX_8888(dir) PPP_OP_##dir##_CHROMA_RGB
512#define PPP_CHROMA_SAMP_MDP_Y_CBCR_H2V1(dir) PPP_OP_##dir##_CHROMA_H2V1 516#define PPP_CHROMA_SAMP_MDP_Y_CBCR_H2V1(dir) PPP_OP_##dir##_CHROMA_H2V1
513#define PPP_CHROMA_SAMP_MDP_Y_CBCR_H2V2(dir) PPP_OP_##dir##_CHROMA_420 517#define PPP_CHROMA_SAMP_MDP_Y_CBCR_H2V2(dir) PPP_OP_##dir##_CHROMA_420
514#define PPP_CHROMA_SAMP_MDP_Y_CRCB_H2V1(dir) PPP_OP_##dir##_CHROMA_H2V1 518#define PPP_CHROMA_SAMP_MDP_Y_CRCB_H2V1(dir) PPP_OP_##dir##_CHROMA_H2V1
@@ -523,6 +527,7 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
523 [MDP_ARGB_8888] = PPP_##name##_MDP_ARGB_8888,\ 527 [MDP_ARGB_8888] = PPP_##name##_MDP_ARGB_8888,\
524 [MDP_RGBA_8888] = PPP_##name##_MDP_RGBA_8888,\ 528 [MDP_RGBA_8888] = PPP_##name##_MDP_RGBA_8888,\
525 [MDP_BGRA_8888] = PPP_##name##_MDP_BGRA_8888,\ 529 [MDP_BGRA_8888] = PPP_##name##_MDP_BGRA_8888,\
530 [MDP_RGBX_8888] = PPP_##name##_MDP_RGBX_8888,\
526 [MDP_Y_CBCR_H2V1] = PPP_##name##_MDP_Y_CBCR_H2V1,\ 531 [MDP_Y_CBCR_H2V1] = PPP_##name##_MDP_Y_CBCR_H2V1,\
527 [MDP_Y_CBCR_H2V2] = PPP_##name##_MDP_Y_CBCR_H2V2,\ 532 [MDP_Y_CBCR_H2V2] = PPP_##name##_MDP_Y_CBCR_H2V2,\
528 [MDP_Y_CRCB_H2V1] = PPP_##name##_MDP_Y_CRCB_H2V1,\ 533 [MDP_Y_CRCB_H2V1] = PPP_##name##_MDP_Y_CRCB_H2V1,\
@@ -536,6 +541,7 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
536 [MDP_ARGB_8888] = PPP_##name##_MDP_ARGB_8888(dir),\ 541 [MDP_ARGB_8888] = PPP_##name##_MDP_ARGB_8888(dir),\
537 [MDP_RGBA_8888] = PPP_##name##_MDP_RGBA_8888(dir),\ 542 [MDP_RGBA_8888] = PPP_##name##_MDP_RGBA_8888(dir),\
538 [MDP_BGRA_8888] = PPP_##name##_MDP_BGRA_8888(dir),\ 543 [MDP_BGRA_8888] = PPP_##name##_MDP_BGRA_8888(dir),\
544 [MDP_RGBX_8888] = PPP_##name##_MDP_RGBX_8888(dir),\
539 [MDP_Y_CBCR_H2V1] = PPP_##name##_MDP_Y_CBCR_H2V1(dir),\ 545 [MDP_Y_CBCR_H2V1] = PPP_##name##_MDP_Y_CBCR_H2V1(dir),\
540 [MDP_Y_CBCR_H2V2] = PPP_##name##_MDP_Y_CBCR_H2V2(dir),\ 546 [MDP_Y_CBCR_H2V2] = PPP_##name##_MDP_Y_CBCR_H2V2(dir),\
541 [MDP_Y_CRCB_H2V1] = PPP_##name##_MDP_Y_CRCB_H2V1(dir),\ 547 [MDP_Y_CRCB_H2V1] = PPP_##name##_MDP_Y_CRCB_H2V1(dir),\
@@ -547,7 +553,8 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
547 (img == MDP_YCRYCB_H2V1)) 553 (img == MDP_YCRYCB_H2V1))
548#define IS_RGB(img) ((img == MDP_RGB_565) | (img == MDP_RGB_888) | \ 554#define IS_RGB(img) ((img == MDP_RGB_565) | (img == MDP_RGB_888) | \
549 (img == MDP_ARGB_8888) | (img == MDP_RGBA_8888) | \ 555 (img == MDP_ARGB_8888) | (img == MDP_RGBA_8888) | \
550 (img == MDP_XRGB_8888) | (img == MDP_BGRA_8888)) 556 (img == MDP_XRGB_8888) | (img == MDP_BGRA_8888) | \
557 (img == MDP_RGBX_8888))
551#define HAS_ALPHA(img) ((img == MDP_ARGB_8888) | (img == MDP_RGBA_8888) | \ 558#define HAS_ALPHA(img) ((img == MDP_ARGB_8888) | (img == MDP_RGBA_8888) | \
552 (img == MDP_BGRA_8888)) 559 (img == MDP_BGRA_8888))
553 560
diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/msm/mdp_ppp.c
index 4ff001f4cbbd..2b6564e8bfea 100644
--- a/drivers/video/msm/mdp_ppp.c
+++ b/drivers/video/msm/mdp_ppp.c
@@ -69,6 +69,7 @@ static uint32_t bytes_per_pixel[] = {
69 [MDP_ARGB_8888] = 4, 69 [MDP_ARGB_8888] = 4,
70 [MDP_RGBA_8888] = 4, 70 [MDP_RGBA_8888] = 4,
71 [MDP_BGRA_8888] = 4, 71 [MDP_BGRA_8888] = 4,
72 [MDP_RGBX_8888] = 4,
72 [MDP_Y_CBCR_H2V1] = 1, 73 [MDP_Y_CBCR_H2V1] = 1,
73 [MDP_Y_CBCR_H2V2] = 1, 74 [MDP_Y_CBCR_H2V2] = 1,
74 [MDP_Y_CRCB_H2V1] = 1, 75 [MDP_Y_CRCB_H2V1] = 1,
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index debe5933fd2e..ec351309e607 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -81,7 +81,6 @@ struct msmfb_info {
81 spinlock_t update_lock; 81 spinlock_t update_lock;
82 struct mutex panel_init_lock; 82 struct mutex panel_init_lock;
83 wait_queue_head_t frame_wq; 83 wait_queue_head_t frame_wq;
84 struct workqueue_struct *resume_workqueue;
85 struct work_struct resume_work; 84 struct work_struct resume_work;
86 struct msmfb_callback dma_callback; 85 struct msmfb_callback dma_callback;
87 struct msmfb_callback vsync_callback; 86 struct msmfb_callback vsync_callback;
@@ -111,7 +110,7 @@ static void msmfb_handle_dma_interrupt(struct msmfb_callback *callback)
111 if (msmfb->sleeping == UPDATING && 110 if (msmfb->sleeping == UPDATING &&
112 msmfb->frame_done == msmfb->update_frame) { 111 msmfb->frame_done == msmfb->update_frame) {
113 DLOG(SUSPEND_RESUME, "full update completed\n"); 112 DLOG(SUSPEND_RESUME, "full update completed\n");
114 queue_work(msmfb->resume_workqueue, &msmfb->resume_work); 113 schedule_work(&msmfb->resume_work);
115 } 114 }
116 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags); 115 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
117 wake_up(&msmfb->frame_wq); 116 wake_up(&msmfb->frame_wq);
@@ -220,8 +219,8 @@ restart:
220 219
221 sleeping = msmfb->sleeping; 220 sleeping = msmfb->sleeping;
222 /* on a full update, if the last frame has not completed, wait for it */ 221 /* on a full update, if the last frame has not completed, wait for it */
223 if (pan_display && (msmfb->frame_requested != msmfb->frame_done || 222 if ((pan_display && msmfb->frame_requested != msmfb->frame_done) ||
224 sleeping == UPDATING)) { 223 sleeping == UPDATING) {
225 int ret; 224 int ret;
226 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags); 225 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
227 ret = wait_event_interruptible_timeout(msmfb->frame_wq, 226 ret = wait_event_interruptible_timeout(msmfb->frame_wq,
@@ -470,6 +469,18 @@ static void setup_fb_info(struct msmfb_info *msmfb)
470 fb_info->var.yoffset = 0; 469 fb_info->var.yoffset = 0;
471 470
472 if (msmfb->panel->caps & MSMFB_CAP_PARTIAL_UPDATES) { 471 if (msmfb->panel->caps & MSMFB_CAP_PARTIAL_UPDATES) {
472 /*
473 * Set the param in the fixed screen, so userspace can't
474 * change it. This will be used to check for the
475 * capability.
476 */
477 fb_info->fix.reserved[0] = 0x5444;
478 fb_info->fix.reserved[1] = 0x5055;
479
480 /*
481 * This preloads the value so that if userspace doesn't
482 * change it, it will be a full update
483 */
473 fb_info->var.reserved[0] = 0x54445055; 484 fb_info->var.reserved[0] = 0x54445055;
474 fb_info->var.reserved[1] = 0; 485 fb_info->var.reserved[1] = 0;
475 fb_info->var.reserved[2] = (uint16_t)msmfb->xres | 486 fb_info->var.reserved[2] = (uint16_t)msmfb->xres |
@@ -559,12 +570,6 @@ static int msmfb_probe(struct platform_device *pdev)
559 spin_lock_init(&msmfb->update_lock); 570 spin_lock_init(&msmfb->update_lock);
560 mutex_init(&msmfb->panel_init_lock); 571 mutex_init(&msmfb->panel_init_lock);
561 init_waitqueue_head(&msmfb->frame_wq); 572 init_waitqueue_head(&msmfb->frame_wq);
562 msmfb->resume_workqueue = create_workqueue("panel_on");
563 if (msmfb->resume_workqueue == NULL) {
564 printk(KERN_ERR "failed to create panel_on workqueue\n");
565 ret = -ENOMEM;
566 goto error_create_workqueue;
567 }
568 INIT_WORK(&msmfb->resume_work, power_on_panel); 573 INIT_WORK(&msmfb->resume_work, power_on_panel);
569 msmfb->black = kzalloc(msmfb->fb->var.bits_per_pixel*msmfb->xres, 574 msmfb->black = kzalloc(msmfb->fb->var.bits_per_pixel*msmfb->xres,
570 GFP_KERNEL); 575 GFP_KERNEL);
@@ -589,8 +594,6 @@ static int msmfb_probe(struct platform_device *pdev)
589 return 0; 594 return 0;
590 595
591error_register_framebuffer: 596error_register_framebuffer:
592 destroy_workqueue(msmfb->resume_workqueue);
593error_create_workqueue:
594 iounmap(fb->screen_base); 597 iounmap(fb->screen_base);
595error_setup_fbmem: 598error_setup_fbmem:
596 framebuffer_release(msmfb->fb); 599 framebuffer_release(msmfb->fb);
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c
index 7cfc170bce19..7e3a490e8d76 100644
--- a/drivers/video/mx3fb.c
+++ b/drivers/video/mx3fb.c
@@ -27,6 +27,7 @@
27#include <linux/clk.h> 27#include <linux/clk.h>
28#include <linux/mutex.h> 28#include <linux/mutex.h>
29 29
30#include <mach/dma.h>
30#include <mach/hardware.h> 31#include <mach/hardware.h>
31#include <mach/ipu.h> 32#include <mach/ipu.h>
32#include <mach/mx3fb.h> 33#include <mach/mx3fb.h>
@@ -1176,9 +1177,9 @@ static int mx3fb_suspend(struct platform_device *pdev, pm_message_t state)
1176 struct mx3fb_data *mx3fb = platform_get_drvdata(pdev); 1177 struct mx3fb_data *mx3fb = platform_get_drvdata(pdev);
1177 struct mx3fb_info *mx3_fbi = mx3fb->fbi->par; 1178 struct mx3fb_info *mx3_fbi = mx3fb->fbi->par;
1178 1179
1179 acquire_console_sem(); 1180 console_lock();
1180 fb_set_suspend(mx3fb->fbi, 1); 1181 fb_set_suspend(mx3fb->fbi, 1);
1181 release_console_sem(); 1182 console_unlock();
1182 1183
1183 if (mx3_fbi->blank == FB_BLANK_UNBLANK) { 1184 if (mx3_fbi->blank == FB_BLANK_UNBLANK) {
1184 sdc_disable_channel(mx3_fbi); 1185 sdc_disable_channel(mx3_fbi);
@@ -1201,9 +1202,9 @@ static int mx3fb_resume(struct platform_device *pdev)
1201 sdc_set_brightness(mx3fb, mx3fb->backlight_level); 1202 sdc_set_brightness(mx3fb, mx3fb->backlight_level);
1202 } 1203 }
1203 1204
1204 acquire_console_sem(); 1205 console_lock();
1205 fb_set_suspend(mx3fb->fbi, 0); 1206 fb_set_suspend(mx3fb->fbi, 0);
1206 release_console_sem(); 1207 console_unlock();
1207 1208
1208 return 0; 1209 return 0;
1209} 1210}
@@ -1420,6 +1421,9 @@ static bool chan_filter(struct dma_chan *chan, void *arg)
1420 struct device *dev; 1421 struct device *dev;
1421 struct mx3fb_platform_data *mx3fb_pdata; 1422 struct mx3fb_platform_data *mx3fb_pdata;
1422 1423
1424 if (!imx_dma_is_ipu(chan))
1425 return false;
1426
1423 if (!rq) 1427 if (!rq)
1424 return false; 1428 return false;
1425 1429
@@ -1470,8 +1474,7 @@ static int mx3fb_probe(struct platform_device *pdev)
1470 goto eremap; 1474 goto eremap;
1471 } 1475 }
1472 1476
1473 pr_debug("Remapped %x to %x at %p\n", sdc_reg->start, sdc_reg->end, 1477 pr_debug("Remapped %pR at %p\n", sdc_reg, mx3fb->reg_base);
1474 mx3fb->reg_base);
1475 1478
1476 /* IDMAC interface */ 1479 /* IDMAC interface */
1477 dmaengine_get(); 1480 dmaengine_get();
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
new file mode 100644
index 000000000000..0b2f2dd41416
--- /dev/null
+++ b/drivers/video/mxsfb.c
@@ -0,0 +1,919 @@
1/*
2 * Copyright (C) 2010 Juergen Beisert, Pengutronix
3 *
4 * This code is based on:
5 * Author: Vitaly Wool <vital@embeddedalley.com>
6 *
7 * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
8 * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
19
20#define DRIVER_NAME "mxsfb"
21
22/**
23 * @file
24 * @brief LCDIF driver for i.MX23 and i.MX28
25 *
26 * The LCDIF support four modes of operation
27 * - MPU interface (to drive smart displays) -> not supported yet
28 * - VSYNC interface (like MPU interface plus Vsync) -> not supported yet
29 * - Dotclock interface (to drive LC displays with RGB data and sync signals)
30 * - DVI (to drive ITU-R BT656) -> not supported yet
31 *
32 * This driver depends on a correct setup of the pins used for this purpose
33 * (platform specific).
34 *
35 * For the developer: Don't forget to set the data bus width to the display
36 * in the imx_fb_videomode structure. You will else end up with ugly colours.
37 * If you fight against jitter you can vary the clock delay. This is a feature
38 * of the i.MX28 and you can vary it between 2 ns ... 8 ns in 2 ns steps. Give
39 * the required value in the imx_fb_videomode structure.
40 */
41
42#include <linux/kernel.h>
43#include <linux/platform_device.h>
44#include <linux/clk.h>
45#include <linux/dma-mapping.h>
46#include <linux/io.h>
47#include <mach/mxsfb.h>
48
49#define REG_SET 4
50#define REG_CLR 8
51
52#define LCDC_CTRL 0x00
53#define LCDC_CTRL1 0x10
54#define LCDC_V4_CTRL2 0x20
55#define LCDC_V3_TRANSFER_COUNT 0x20
56#define LCDC_V4_TRANSFER_COUNT 0x30
57#define LCDC_V4_CUR_BUF 0x40
58#define LCDC_V4_NEXT_BUF 0x50
59#define LCDC_V3_CUR_BUF 0x30
60#define LCDC_V3_NEXT_BUF 0x40
61#define LCDC_TIMING 0x60
62#define LCDC_VDCTRL0 0x70
63#define LCDC_VDCTRL1 0x80
64#define LCDC_VDCTRL2 0x90
65#define LCDC_VDCTRL3 0xa0
66#define LCDC_VDCTRL4 0xb0
67#define LCDC_DVICTRL0 0xc0
68#define LCDC_DVICTRL1 0xd0
69#define LCDC_DVICTRL2 0xe0
70#define LCDC_DVICTRL3 0xf0
71#define LCDC_DVICTRL4 0x100
72#define LCDC_V4_DATA 0x180
73#define LCDC_V3_DATA 0x1b0
74#define LCDC_V4_DEBUG0 0x1d0
75#define LCDC_V3_DEBUG0 0x1f0
76
77#define CTRL_SFTRST (1 << 31)
78#define CTRL_CLKGATE (1 << 30)
79#define CTRL_BYPASS_COUNT (1 << 19)
80#define CTRL_VSYNC_MODE (1 << 18)
81#define CTRL_DOTCLK_MODE (1 << 17)
82#define CTRL_DATA_SELECT (1 << 16)
83#define CTRL_SET_BUS_WIDTH(x) (((x) & 0x3) << 10)
84#define CTRL_GET_BUS_WIDTH(x) (((x) >> 10) & 0x3)
85#define CTRL_SET_WORD_LENGTH(x) (((x) & 0x3) << 8)
86#define CTRL_GET_WORD_LENGTH(x) (((x) >> 8) & 0x3)
87#define CTRL_MASTER (1 << 5)
88#define CTRL_DF16 (1 << 3)
89#define CTRL_DF18 (1 << 2)
90#define CTRL_DF24 (1 << 1)
91#define CTRL_RUN (1 << 0)
92
93#define CTRL1_FIFO_CLEAR (1 << 21)
94#define CTRL1_SET_BYTE_PACKAGING(x) (((x) & 0xf) << 16)
95#define CTRL1_GET_BYTE_PACKAGING(x) (((x) >> 16) & 0xf)
96
97#define TRANSFER_COUNT_SET_VCOUNT(x) (((x) & 0xffff) << 16)
98#define TRANSFER_COUNT_GET_VCOUNT(x) (((x) >> 16) & 0xffff)
99#define TRANSFER_COUNT_SET_HCOUNT(x) ((x) & 0xffff)
100#define TRANSFER_COUNT_GET_HCOUNT(x) ((x) & 0xffff)
101
102
103#define VDCTRL0_ENABLE_PRESENT (1 << 28)
104#define VDCTRL0_VSYNC_ACT_HIGH (1 << 27)
105#define VDCTRL0_HSYNC_ACT_HIGH (1 << 26)
106#define VDCTRL0_DOTCLK_ACT_FAILING (1 << 25)
107#define VDCTRL0_ENABLE_ACT_HIGH (1 << 24)
108#define VDCTRL0_VSYNC_PERIOD_UNIT (1 << 21)
109#define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT (1 << 20)
110#define VDCTRL0_HALF_LINE (1 << 19)
111#define VDCTRL0_HALF_LINE_MODE (1 << 18)
112#define VDCTRL0_SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
113#define VDCTRL0_GET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
114
115#define VDCTRL2_SET_HSYNC_PERIOD(x) ((x) & 0x3ffff)
116#define VDCTRL2_GET_HSYNC_PERIOD(x) ((x) & 0x3ffff)
117
118#define VDCTRL3_MUX_SYNC_SIGNALS (1 << 29)
119#define VDCTRL3_VSYNC_ONLY (1 << 28)
120#define SET_HOR_WAIT_CNT(x) (((x) & 0xfff) << 16)
121#define GET_HOR_WAIT_CNT(x) (((x) >> 16) & 0xfff)
122#define SET_VERT_WAIT_CNT(x) ((x) & 0xffff)
123#define GET_VERT_WAIT_CNT(x) ((x) & 0xffff)
124
125#define VDCTRL4_SET_DOTCLK_DLY(x) (((x) & 0x7) << 29) /* v4 only */
126#define VDCTRL4_GET_DOTCLK_DLY(x) (((x) >> 29) & 0x7) /* v4 only */
127#define VDCTRL4_SYNC_SIGNALS_ON (1 << 18)
128#define SET_DOTCLK_H_VALID_DATA_CNT(x) ((x) & 0x3ffff)
129
130#define DEBUG0_HSYNC (1 < 26)
131#define DEBUG0_VSYNC (1 < 25)
132
133#define MIN_XRES 120
134#define MIN_YRES 120
135
136#define RED 0
137#define GREEN 1
138#define BLUE 2
139#define TRANSP 3
140
141enum mxsfb_devtype {
142 MXSFB_V3,
143 MXSFB_V4,
144};
145
146/* CPU dependent register offsets */
147struct mxsfb_devdata {
148 unsigned transfer_count;
149 unsigned cur_buf;
150 unsigned next_buf;
151 unsigned debug0;
152 unsigned hs_wdth_mask;
153 unsigned hs_wdth_shift;
154 unsigned ipversion;
155};
156
157struct mxsfb_info {
158 struct fb_info fb_info;
159 struct platform_device *pdev;
160 struct clk *clk;
161 void __iomem *base; /* registers */
162 unsigned allocated_size;
163 int enabled;
164 unsigned ld_intf_width;
165 unsigned dotclk_delay;
166 const struct mxsfb_devdata *devdata;
167 int mapped;
168};
169
170#define mxsfb_is_v3(host) (host->devdata->ipversion == 3)
171#define mxsfb_is_v4(host) (host->devdata->ipversion == 4)
172
173static const struct mxsfb_devdata mxsfb_devdata[] = {
174 [MXSFB_V3] = {
175 .transfer_count = LCDC_V3_TRANSFER_COUNT,
176 .cur_buf = LCDC_V3_CUR_BUF,
177 .next_buf = LCDC_V3_NEXT_BUF,
178 .debug0 = LCDC_V3_DEBUG0,
179 .hs_wdth_mask = 0xff,
180 .hs_wdth_shift = 24,
181 .ipversion = 3,
182 },
183 [MXSFB_V4] = {
184 .transfer_count = LCDC_V4_TRANSFER_COUNT,
185 .cur_buf = LCDC_V4_CUR_BUF,
186 .next_buf = LCDC_V4_NEXT_BUF,
187 .debug0 = LCDC_V4_DEBUG0,
188 .hs_wdth_mask = 0x3fff,
189 .hs_wdth_shift = 18,
190 .ipversion = 4,
191 },
192};
193
194#define to_imxfb_host(x) (container_of(x, struct mxsfb_info, fb_info))
195
196/* mask and shift depends on architecture */
197static inline u32 set_hsync_pulse_width(struct mxsfb_info *host, unsigned val)
198{
199 return (val & host->devdata->hs_wdth_mask) <<
200 host->devdata->hs_wdth_shift;
201}
202
203static inline u32 get_hsync_pulse_width(struct mxsfb_info *host, unsigned val)
204{
205 return (val >> host->devdata->hs_wdth_shift) &
206 host->devdata->hs_wdth_mask;
207}
208
209static const struct fb_bitfield def_rgb565[] = {
210 [RED] = {
211 .offset = 11,
212 .length = 5,
213 },
214 [GREEN] = {
215 .offset = 5,
216 .length = 6,
217 },
218 [BLUE] = {
219 .offset = 0,
220 .length = 5,
221 },
222 [TRANSP] = { /* no support for transparency */
223 .length = 0,
224 }
225};
226
227static const struct fb_bitfield def_rgb666[] = {
228 [RED] = {
229 .offset = 16,
230 .length = 6,
231 },
232 [GREEN] = {
233 .offset = 8,
234 .length = 6,
235 },
236 [BLUE] = {
237 .offset = 0,
238 .length = 6,
239 },
240 [TRANSP] = { /* no support for transparency */
241 .length = 0,
242 }
243};
244
245static const struct fb_bitfield def_rgb888[] = {
246 [RED] = {
247 .offset = 16,
248 .length = 8,
249 },
250 [GREEN] = {
251 .offset = 8,
252 .length = 8,
253 },
254 [BLUE] = {
255 .offset = 0,
256 .length = 8,
257 },
258 [TRANSP] = { /* no support for transparency */
259 .length = 0,
260 }
261};
262
263static inline unsigned chan_to_field(unsigned chan, struct fb_bitfield *bf)
264{
265 chan &= 0xffff;
266 chan >>= 16 - bf->length;
267 return chan << bf->offset;
268}
269
270static int mxsfb_check_var(struct fb_var_screeninfo *var,
271 struct fb_info *fb_info)
272{
273 struct mxsfb_info *host = to_imxfb_host(fb_info);
274 const struct fb_bitfield *rgb = NULL;
275
276 if (var->xres < MIN_XRES)
277 var->xres = MIN_XRES;
278 if (var->yres < MIN_YRES)
279 var->yres = MIN_YRES;
280
281 var->xres_virtual = var->xres;
282
283 var->yres_virtual = var->yres;
284
285 switch (var->bits_per_pixel) {
286 case 16:
287 /* always expect RGB 565 */
288 rgb = def_rgb565;
289 break;
290 case 32:
291 switch (host->ld_intf_width) {
292 case STMLCDIF_8BIT:
293 pr_debug("Unsupported LCD bus width mapping\n");
294 break;
295 case STMLCDIF_16BIT:
296 case STMLCDIF_18BIT:
297 /* 24 bit to 18 bit mapping */
298 rgb = def_rgb666;
299 break;
300 case STMLCDIF_24BIT:
301 /* real 24 bit */
302 rgb = def_rgb888;
303 break;
304 }
305 break;
306 default:
307 pr_debug("Unsupported colour depth: %u\n", var->bits_per_pixel);
308 return -EINVAL;
309 }
310
311 /*
312 * Copy the RGB parameters for this display
313 * from the machine specific parameters.
314 */
315 var->red = rgb[RED];
316 var->green = rgb[GREEN];
317 var->blue = rgb[BLUE];
318 var->transp = rgb[TRANSP];
319
320 return 0;
321}
322
323static void mxsfb_enable_controller(struct fb_info *fb_info)
324{
325 struct mxsfb_info *host = to_imxfb_host(fb_info);
326 u32 reg;
327
328 dev_dbg(&host->pdev->dev, "%s\n", __func__);
329
330 clk_enable(host->clk);
331 clk_set_rate(host->clk, PICOS2KHZ(fb_info->var.pixclock) * 1000U);
332
333 /* if it was disabled, re-enable the mode again */
334 writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_SET);
335
336 /* enable the SYNC signals first, then the DMA engine */
337 reg = readl(host->base + LCDC_VDCTRL4);
338 reg |= VDCTRL4_SYNC_SIGNALS_ON;
339 writel(reg, host->base + LCDC_VDCTRL4);
340
341 writel(CTRL_RUN, host->base + LCDC_CTRL + REG_SET);
342
343 host->enabled = 1;
344}
345
346static void mxsfb_disable_controller(struct fb_info *fb_info)
347{
348 struct mxsfb_info *host = to_imxfb_host(fb_info);
349 unsigned loop;
350 u32 reg;
351
352 dev_dbg(&host->pdev->dev, "%s\n", __func__);
353
354 /*
355 * Even if we disable the controller here, it will still continue
356 * until its FIFOs are running out of data
357 */
358 writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_CLR);
359
360 loop = 1000;
361 while (loop) {
362 reg = readl(host->base + LCDC_CTRL);
363 if (!(reg & CTRL_RUN))
364 break;
365 loop--;
366 }
367
368 writel(VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4 + REG_CLR);
369
370 clk_disable(host->clk);
371
372 host->enabled = 0;
373}
374
375static int mxsfb_set_par(struct fb_info *fb_info)
376{
377 struct mxsfb_info *host = to_imxfb_host(fb_info);
378 u32 ctrl, vdctrl0, vdctrl4;
379 int line_size, fb_size;
380 int reenable = 0;
381
382 line_size = fb_info->var.xres * (fb_info->var.bits_per_pixel >> 3);
383 fb_size = fb_info->var.yres_virtual * line_size;
384
385 if (fb_size > fb_info->fix.smem_len)
386 return -ENOMEM;
387
388 fb_info->fix.line_length = line_size;
389
390 /*
391 * It seems, you can't re-program the controller if it is still running.
392 * This may lead into shifted pictures (FIFO issue?).
393 * So, first stop the controller and drain its FIFOs
394 */
395 if (host->enabled) {
396 reenable = 1;
397 mxsfb_disable_controller(fb_info);
398 }
399
400 /* clear the FIFOs */
401 writel(CTRL1_FIFO_CLEAR, host->base + LCDC_CTRL1 + REG_SET);
402
403 ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER |
404 CTRL_SET_BUS_WIDTH(host->ld_intf_width);
405
406 switch (fb_info->var.bits_per_pixel) {
407 case 16:
408 dev_dbg(&host->pdev->dev, "Setting up RGB565 mode\n");
409 ctrl |= CTRL_SET_WORD_LENGTH(0);
410 writel(CTRL1_SET_BYTE_PACKAGING(0xf), host->base + LCDC_CTRL1);
411 break;
412 case 32:
413 dev_dbg(&host->pdev->dev, "Setting up RGB888/666 mode\n");
414 ctrl |= CTRL_SET_WORD_LENGTH(3);
415 switch (host->ld_intf_width) {
416 case STMLCDIF_8BIT:
417 dev_dbg(&host->pdev->dev,
418 "Unsupported LCD bus width mapping\n");
419 return -EINVAL;
420 case STMLCDIF_16BIT:
421 case STMLCDIF_18BIT:
422 /* 24 bit to 18 bit mapping */
423 ctrl |= CTRL_DF24; /* ignore the upper 2 bits in
424 * each colour component
425 */
426 break;
427 case STMLCDIF_24BIT:
428 /* real 24 bit */
429 break;
430 }
431 /* do not use packed pixels = one pixel per word instead */
432 writel(CTRL1_SET_BYTE_PACKAGING(0x7), host->base + LCDC_CTRL1);
433 break;
434 default:
435 dev_dbg(&host->pdev->dev, "Unhandled color depth of %u\n",
436 fb_info->var.bits_per_pixel);
437 return -EINVAL;
438 }
439
440 writel(ctrl, host->base + LCDC_CTRL);
441
442 writel(TRANSFER_COUNT_SET_VCOUNT(fb_info->var.yres) |
443 TRANSFER_COUNT_SET_HCOUNT(fb_info->var.xres),
444 host->base + host->devdata->transfer_count);
445
446 vdctrl0 = VDCTRL0_ENABLE_PRESENT | /* always in DOTCLOCK mode */
447 VDCTRL0_VSYNC_PERIOD_UNIT |
448 VDCTRL0_VSYNC_PULSE_WIDTH_UNIT |
449 VDCTRL0_SET_VSYNC_PULSE_WIDTH(fb_info->var.vsync_len);
450 if (fb_info->var.sync & FB_SYNC_HOR_HIGH_ACT)
451 vdctrl0 |= VDCTRL0_HSYNC_ACT_HIGH;
452 if (fb_info->var.sync & FB_SYNC_VERT_HIGH_ACT)
453 vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH;
454 if (fb_info->var.sync & FB_SYNC_DATA_ENABLE_HIGH_ACT)
455 vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH;
456 if (fb_info->var.sync & FB_SYNC_DOTCLK_FAILING_ACT)
457 vdctrl0 |= VDCTRL0_DOTCLK_ACT_FAILING;
458
459 writel(vdctrl0, host->base + LCDC_VDCTRL0);
460
461 /* frame length in lines */
462 writel(fb_info->var.upper_margin + fb_info->var.vsync_len +
463 fb_info->var.lower_margin + fb_info->var.yres,
464 host->base + LCDC_VDCTRL1);
465
466 /* line length in units of clocks or pixels */
467 writel(set_hsync_pulse_width(host, fb_info->var.hsync_len) |
468 VDCTRL2_SET_HSYNC_PERIOD(fb_info->var.left_margin +
469 fb_info->var.hsync_len + fb_info->var.right_margin +
470 fb_info->var.xres),
471 host->base + LCDC_VDCTRL2);
472
473 writel(SET_HOR_WAIT_CNT(fb_info->var.left_margin +
474 fb_info->var.hsync_len) |
475 SET_VERT_WAIT_CNT(fb_info->var.upper_margin +
476 fb_info->var.vsync_len),
477 host->base + LCDC_VDCTRL3);
478
479 vdctrl4 = SET_DOTCLK_H_VALID_DATA_CNT(fb_info->var.xres);
480 if (mxsfb_is_v4(host))
481 vdctrl4 |= VDCTRL4_SET_DOTCLK_DLY(host->dotclk_delay);
482 writel(vdctrl4, host->base + LCDC_VDCTRL4);
483
484 writel(fb_info->fix.smem_start +
485 fb_info->fix.line_length * fb_info->var.yoffset,
486 host->base + host->devdata->next_buf);
487
488 if (reenable)
489 mxsfb_enable_controller(fb_info);
490
491 return 0;
492}
493
494static int mxsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
495 u_int transp, struct fb_info *fb_info)
496{
497 unsigned int val;
498 int ret = -EINVAL;
499
500 /*
501 * If greyscale is true, then we convert the RGB value
502 * to greyscale no matter what visual we are using.
503 */
504 if (fb_info->var.grayscale)
505 red = green = blue = (19595 * red + 38470 * green +
506 7471 * blue) >> 16;
507
508 switch (fb_info->fix.visual) {
509 case FB_VISUAL_TRUECOLOR:
510 /*
511 * 12 or 16-bit True Colour. We encode the RGB value
512 * according to the RGB bitfield information.
513 */
514 if (regno < 16) {
515 u32 *pal = fb_info->pseudo_palette;
516
517 val = chan_to_field(red, &fb_info->var.red);
518 val |= chan_to_field(green, &fb_info->var.green);
519 val |= chan_to_field(blue, &fb_info->var.blue);
520
521 pal[regno] = val;
522 ret = 0;
523 }
524 break;
525
526 case FB_VISUAL_STATIC_PSEUDOCOLOR:
527 case FB_VISUAL_PSEUDOCOLOR:
528 break;
529 }
530
531 return ret;
532}
533
534static int mxsfb_blank(int blank, struct fb_info *fb_info)
535{
536 struct mxsfb_info *host = to_imxfb_host(fb_info);
537
538 switch (blank) {
539 case FB_BLANK_POWERDOWN:
540 case FB_BLANK_VSYNC_SUSPEND:
541 case FB_BLANK_HSYNC_SUSPEND:
542 case FB_BLANK_NORMAL:
543 if (host->enabled)
544 mxsfb_disable_controller(fb_info);
545 break;
546
547 case FB_BLANK_UNBLANK:
548 if (!host->enabled)
549 mxsfb_enable_controller(fb_info);
550 break;
551 }
552 return 0;
553}
554
555static int mxsfb_pan_display(struct fb_var_screeninfo *var,
556 struct fb_info *fb_info)
557{
558 struct mxsfb_info *host = to_imxfb_host(fb_info);
559 unsigned offset;
560
561 if (var->xoffset != 0)
562 return -EINVAL;
563
564 offset = fb_info->fix.line_length * var->yoffset;
565
566 /* update on next VSYNC */
567 writel(fb_info->fix.smem_start + offset,
568 host->base + host->devdata->next_buf);
569
570 return 0;
571}
572
573static struct fb_ops mxsfb_ops = {
574 .owner = THIS_MODULE,
575 .fb_check_var = mxsfb_check_var,
576 .fb_set_par = mxsfb_set_par,
577 .fb_setcolreg = mxsfb_setcolreg,
578 .fb_blank = mxsfb_blank,
579 .fb_pan_display = mxsfb_pan_display,
580 .fb_fillrect = cfb_fillrect,
581 .fb_copyarea = cfb_copyarea,
582 .fb_imageblit = cfb_imageblit,
583};
584
585static int __devinit mxsfb_restore_mode(struct mxsfb_info *host)
586{
587 struct fb_info *fb_info = &host->fb_info;
588 unsigned line_count;
589 unsigned period;
590 unsigned long pa, fbsize;
591 int bits_per_pixel, ofs;
592 u32 transfer_count, vdctrl0, vdctrl2, vdctrl3, vdctrl4, ctrl;
593 struct fb_videomode vmode;
594
595 /* Only restore the mode when the controller is running */
596 ctrl = readl(host->base + LCDC_CTRL);
597 if (!(ctrl & CTRL_RUN))
598 return -EINVAL;
599
600 vdctrl0 = readl(host->base + LCDC_VDCTRL0);
601 vdctrl2 = readl(host->base + LCDC_VDCTRL2);
602 vdctrl3 = readl(host->base + LCDC_VDCTRL3);
603 vdctrl4 = readl(host->base + LCDC_VDCTRL4);
604
605 transfer_count = readl(host->base + host->devdata->transfer_count);
606
607 vmode.xres = TRANSFER_COUNT_GET_HCOUNT(transfer_count);
608 vmode.yres = TRANSFER_COUNT_GET_VCOUNT(transfer_count);
609
610 switch (CTRL_GET_WORD_LENGTH(ctrl)) {
611 case 0:
612 bits_per_pixel = 16;
613 break;
614 case 3:
615 bits_per_pixel = 32;
616 case 1:
617 default:
618 return -EINVAL;
619 }
620
621 fb_info->var.bits_per_pixel = bits_per_pixel;
622
623 vmode.pixclock = KHZ2PICOS(clk_get_rate(host->clk) / 1000U);
624 vmode.hsync_len = get_hsync_pulse_width(host, vdctrl2);
625 vmode.left_margin = GET_HOR_WAIT_CNT(vdctrl3) - vmode.hsync_len;
626 vmode.right_margin = VDCTRL2_GET_HSYNC_PERIOD(vdctrl2) - vmode.hsync_len -
627 vmode.left_margin - vmode.xres;
628 vmode.vsync_len = VDCTRL0_GET_VSYNC_PULSE_WIDTH(vdctrl0);
629 period = readl(host->base + LCDC_VDCTRL1);
630 vmode.upper_margin = GET_VERT_WAIT_CNT(vdctrl3) - vmode.vsync_len;
631 vmode.lower_margin = period - vmode.vsync_len - vmode.upper_margin - vmode.yres;
632
633 vmode.vmode = FB_VMODE_NONINTERLACED;
634
635 vmode.sync = 0;
636 if (vdctrl0 & VDCTRL0_HSYNC_ACT_HIGH)
637 vmode.sync |= FB_SYNC_HOR_HIGH_ACT;
638 if (vdctrl0 & VDCTRL0_VSYNC_ACT_HIGH)
639 vmode.sync |= FB_SYNC_VERT_HIGH_ACT;
640
641 pr_debug("Reconstructed video mode:\n");
642 pr_debug("%dx%d, hsync: %u left: %u, right: %u, vsync: %u, upper: %u, lower: %u\n",
643 vmode.xres, vmode.yres,
644 vmode.hsync_len, vmode.left_margin, vmode.right_margin,
645 vmode.vsync_len, vmode.upper_margin, vmode.lower_margin);
646 pr_debug("pixclk: %ldkHz\n", PICOS2KHZ(vmode.pixclock));
647
648 fb_add_videomode(&vmode, &fb_info->modelist);
649
650 host->ld_intf_width = CTRL_GET_BUS_WIDTH(ctrl);
651 host->dotclk_delay = VDCTRL4_GET_DOTCLK_DLY(vdctrl4);
652
653 fb_info->fix.line_length = vmode.xres * (bits_per_pixel >> 3);
654
655 pa = readl(host->base + host->devdata->cur_buf);
656 fbsize = fb_info->fix.line_length * vmode.yres;
657 if (pa < fb_info->fix.smem_start)
658 return -EINVAL;
659 if (pa + fbsize > fb_info->fix.smem_start + fb_info->fix.smem_len)
660 return -EINVAL;
661 ofs = pa - fb_info->fix.smem_start;
662 if (ofs) {
663 memmove(fb_info->screen_base, fb_info->screen_base + ofs, fbsize);
664 writel(fb_info->fix.smem_start, host->base + host->devdata->next_buf);
665 }
666
667 line_count = fb_info->fix.smem_len / fb_info->fix.line_length;
668 fb_info->fix.ypanstep = 1;
669
670 clk_enable(host->clk);
671 host->enabled = 1;
672
673 return 0;
674}
675
676static int __devinit mxsfb_init_fbinfo(struct mxsfb_info *host)
677{
678 struct fb_info *fb_info = &host->fb_info;
679 struct fb_var_screeninfo *var = &fb_info->var;
680 struct mxsfb_platform_data *pdata = host->pdev->dev.platform_data;
681 dma_addr_t fb_phys;
682 void *fb_virt;
683 unsigned fb_size = pdata->fb_size;
684
685 fb_info->fbops = &mxsfb_ops;
686 fb_info->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST;
687 strlcpy(fb_info->fix.id, "mxs", sizeof(fb_info->fix.id));
688 fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
689 fb_info->fix.ypanstep = 1;
690 fb_info->fix.visual = FB_VISUAL_TRUECOLOR,
691 fb_info->fix.accel = FB_ACCEL_NONE;
692
693 var->bits_per_pixel = pdata->default_bpp ? pdata->default_bpp : 16;
694 var->nonstd = 0;
695 var->activate = FB_ACTIVATE_NOW;
696 var->accel_flags = 0;
697 var->vmode = FB_VMODE_NONINTERLACED;
698
699 host->dotclk_delay = pdata->dotclk_delay;
700 host->ld_intf_width = pdata->ld_intf_width;
701
702 /* Memory allocation for framebuffer */
703 if (pdata->fb_phys) {
704 if (!fb_size)
705 return -EINVAL;
706
707 fb_phys = pdata->fb_phys;
708
709 if (!request_mem_region(fb_phys, fb_size, host->pdev->name))
710 return -ENOMEM;
711
712 fb_virt = ioremap(fb_phys, fb_size);
713 if (!fb_virt) {
714 release_mem_region(fb_phys, fb_size);
715 return -ENOMEM;
716 }
717 host->mapped = 1;
718 } else {
719 if (!fb_size)
720 fb_size = SZ_2M; /* default */
721 fb_virt = alloc_pages_exact(fb_size, GFP_DMA);
722 if (!fb_virt)
723 return -ENOMEM;
724
725 fb_phys = virt_to_phys(fb_virt);
726 }
727
728 fb_info->fix.smem_start = fb_phys;
729 fb_info->screen_base = fb_virt;
730 fb_info->screen_size = fb_info->fix.smem_len = fb_size;
731
732 if (mxsfb_restore_mode(host))
733 memset(fb_virt, 0, fb_size);
734
735 return 0;
736}
737
738static void __devexit mxsfb_free_videomem(struct mxsfb_info *host)
739{
740 struct fb_info *fb_info = &host->fb_info;
741
742 if (host->mapped) {
743 iounmap(fb_info->screen_base);
744 release_mem_region(fb_info->fix.smem_start,
745 fb_info->screen_size);
746 } else {
747 free_pages_exact(fb_info->screen_base, fb_info->fix.smem_len);
748 }
749}
750
751static int __devinit mxsfb_probe(struct platform_device *pdev)
752{
753 struct mxsfb_platform_data *pdata = pdev->dev.platform_data;
754 struct resource *res;
755 struct mxsfb_info *host;
756 struct fb_info *fb_info;
757 struct fb_modelist *modelist;
758 int i, ret;
759
760 if (!pdata) {
761 dev_err(&pdev->dev, "No platformdata. Giving up\n");
762 return -ENODEV;
763 }
764
765 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
766 if (!res) {
767 dev_err(&pdev->dev, "Cannot get memory IO resource\n");
768 return -ENODEV;
769 }
770
771 if (!request_mem_region(res->start, resource_size(res), pdev->name))
772 return -EBUSY;
773
774 fb_info = framebuffer_alloc(sizeof(struct mxsfb_info), &pdev->dev);
775 if (!fb_info) {
776 dev_err(&pdev->dev, "Failed to allocate fbdev\n");
777 ret = -ENOMEM;
778 goto error_alloc_info;
779 }
780
781 host = to_imxfb_host(fb_info);
782
783 host->base = ioremap(res->start, resource_size(res));
784 if (!host->base) {
785 dev_err(&pdev->dev, "ioremap failed\n");
786 ret = -ENOMEM;
787 goto error_ioremap;
788 }
789
790 host->pdev = pdev;
791 platform_set_drvdata(pdev, host);
792
793 host->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
794
795 host->clk = clk_get(&host->pdev->dev, NULL);
796 if (IS_ERR(host->clk)) {
797 ret = PTR_ERR(host->clk);
798 goto error_getclock;
799 }
800
801 fb_info->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
802 if (!fb_info->pseudo_palette) {
803 ret = -ENOMEM;
804 goto error_pseudo_pallette;
805 }
806
807 INIT_LIST_HEAD(&fb_info->modelist);
808
809 ret = mxsfb_init_fbinfo(host);
810 if (ret != 0)
811 goto error_init_fb;
812
813 for (i = 0; i < pdata->mode_count; i++)
814 fb_add_videomode(&pdata->mode_list[i], &fb_info->modelist);
815
816 modelist = list_first_entry(&fb_info->modelist,
817 struct fb_modelist, list);
818 fb_videomode_to_var(&fb_info->var, &modelist->mode);
819
820 /* init the color fields */
821 mxsfb_check_var(&fb_info->var, fb_info);
822
823 platform_set_drvdata(pdev, fb_info);
824
825 ret = register_framebuffer(fb_info);
826 if (ret != 0) {
827 dev_err(&pdev->dev,"Failed to register framebuffer\n");
828 goto error_register;
829 }
830
831 if (!host->enabled) {
832 writel(0, host->base + LCDC_CTRL);
833 mxsfb_set_par(fb_info);
834 mxsfb_enable_controller(fb_info);
835 }
836
837 dev_info(&pdev->dev, "initialized\n");
838
839 return 0;
840
841error_register:
842 if (host->enabled)
843 clk_disable(host->clk);
844 fb_destroy_modelist(&fb_info->modelist);
845error_init_fb:
846 kfree(fb_info->pseudo_palette);
847error_pseudo_pallette:
848 clk_put(host->clk);
849error_getclock:
850 iounmap(host->base);
851error_ioremap:
852 framebuffer_release(fb_info);
853error_alloc_info:
854 release_mem_region(res->start, resource_size(res));
855
856 return ret;
857}
858
859static int __devexit mxsfb_remove(struct platform_device *pdev)
860{
861 struct fb_info *fb_info = platform_get_drvdata(pdev);
862 struct mxsfb_info *host = to_imxfb_host(fb_info);
863 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
864
865 if (host->enabled)
866 mxsfb_disable_controller(fb_info);
867
868 unregister_framebuffer(fb_info);
869 kfree(fb_info->pseudo_palette);
870 mxsfb_free_videomem(host);
871 iounmap(host->base);
872 clk_put(host->clk);
873
874 framebuffer_release(fb_info);
875 release_mem_region(res->start, resource_size(res));
876
877 platform_set_drvdata(pdev, NULL);
878
879 return 0;
880}
881
882static struct platform_device_id mxsfb_devtype[] = {
883 {
884 .name = "imx23-fb",
885 .driver_data = MXSFB_V3,
886 }, {
887 .name = "imx28-fb",
888 .driver_data = MXSFB_V4,
889 }, {
890 /* sentinel */
891 }
892};
893MODULE_DEVICE_TABLE(platform, mxsfb_devtype);
894
895static struct platform_driver mxsfb_driver = {
896 .probe = mxsfb_probe,
897 .remove = __devexit_p(mxsfb_remove),
898 .id_table = mxsfb_devtype,
899 .driver = {
900 .name = DRIVER_NAME,
901 },
902};
903
904static int __init mxsfb_init(void)
905{
906 return platform_driver_register(&mxsfb_driver);
907}
908
909static void __exit mxsfb_exit(void)
910{
911 platform_driver_unregister(&mxsfb_driver);
912}
913
914module_init(mxsfb_init);
915module_exit(mxsfb_exit);
916
917MODULE_DESCRIPTION("Freescale mxs framebuffer driver");
918MODULE_AUTHOR("Sascha Hauer, Pengutronix");
919MODULE_LICENSE("GPL");
diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
index 81687ed26ba9..f838d9e277f0 100644
--- a/drivers/video/nuc900fb.c
+++ b/drivers/video/nuc900fb.c
@@ -15,6 +15,7 @@
15 */ 15 */
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/err.h>
18#include <linux/errno.h> 19#include <linux/errno.h>
19#include <linux/string.h> 20#include <linux/string.h>
20#include <linux/mm.h> 21#include <linux/mm.h>
@@ -597,9 +598,9 @@ static int __devinit nuc900fb_probe(struct platform_device *pdev)
597 } 598 }
598 599
599 fbi->clk = clk_get(&pdev->dev, NULL); 600 fbi->clk = clk_get(&pdev->dev, NULL);
600 if (!fbi->clk || IS_ERR(fbi->clk)) { 601 if (IS_ERR(fbi->clk)) {
601 printk(KERN_ERR "nuc900-lcd:failed to get lcd clock source\n"); 602 printk(KERN_ERR "nuc900-lcd:failed to get lcd clock source\n");
602 ret = -ENOENT; 603 ret = PTR_ERR(fbi->clk);
603 goto release_irq; 604 goto release_irq;
604 } 605 }
605 606
@@ -695,6 +696,8 @@ static int nuc900fb_remove(struct platform_device *pdev)
695 nuc900fb_stop_lcd(fbinfo); 696 nuc900fb_stop_lcd(fbinfo);
696 msleep(1); 697 msleep(1);
697 698
699 unregister_framebuffer(fbinfo);
700 nuc900fb_cpufreq_deregister(fbi);
698 nuc900fb_unmap_video_memory(fbinfo); 701 nuc900fb_unmap_video_memory(fbinfo);
699 702
700 iounmap(fbi->io); 703 iounmap(fbi->io);
@@ -722,7 +725,7 @@ static int nuc900fb_suspend(struct platform_device *dev, pm_message_t state)
722 struct fb_info *fbinfo = platform_get_drvdata(dev); 725 struct fb_info *fbinfo = platform_get_drvdata(dev);
723 struct nuc900fb_info *info = fbinfo->par; 726 struct nuc900fb_info *info = fbinfo->par;
724 727
725 nuc900fb_stop_lcd(); 728 nuc900fb_stop_lcd(fbinfo);
726 msleep(1); 729 msleep(1);
727 clk_disable(info->clk); 730 clk_disable(info->clk);
728 return 0; 731 return 0;
@@ -739,7 +742,7 @@ static int nuc900fb_resume(struct platform_device *dev)
739 msleep(1); 742 msleep(1);
740 743
741 nuc900fb_init_registers(fbinfo); 744 nuc900fb_init_registers(fbinfo);
742 nuc900fb_activate_var(bfinfo); 745 nuc900fb_activate_var(fbinfo);
743 746
744 return 0; 747 return 0;
745} 748}
diff --git a/drivers/video/nuc900fb.h b/drivers/video/nuc900fb.h
index 6c23aa3d3b89..bc7c9300f276 100644
--- a/drivers/video/nuc900fb.h
+++ b/drivers/video/nuc900fb.h
@@ -8,7 +8,7 @@
8 * the Free Software Foundation; either version 2 of the License, or 8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version. 9 * (at your option) any later version.
10 * 10 *
11 * Auther: 11 * Author:
12 * Wang Qiang(rurality.linux@gmail.com) 2009/12/16 12 * Wang Qiang(rurality.linux@gmail.com) 2009/12/16
13 */ 13 */
14 14
diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/nvidia/nv_backlight.c
index 2fb552a6f32c..8471008aa6ff 100644
--- a/drivers/video/nvidia/nv_backlight.c
+++ b/drivers/video/nvidia/nv_backlight.c
@@ -87,7 +87,7 @@ static int nvidia_bl_get_brightness(struct backlight_device *bd)
87 return bd->props.brightness; 87 return bd->props.brightness;
88} 88}
89 89
90static struct backlight_ops nvidia_bl_ops = { 90static const struct backlight_ops nvidia_bl_ops = {
91 .get_brightness = nvidia_bl_get_brightness, 91 .get_brightness = nvidia_bl_get_brightness,
92 .update_status = nvidia_bl_update_status, 92 .update_status = nvidia_bl_update_status,
93}; 93};
@@ -111,6 +111,7 @@ void nvidia_bl_init(struct nvidia_par *par)
111 snprintf(name, sizeof(name), "nvidiabl%d", info->node); 111 snprintf(name, sizeof(name), "nvidiabl%d", info->node);
112 112
113 memset(&props, 0, sizeof(struct backlight_properties)); 113 memset(&props, 0, sizeof(struct backlight_properties));
114 props.type = BACKLIGHT_RAW;
114 props.max_brightness = FB_BACKLIGHT_LEVELS - 1; 115 props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
115 bd = backlight_device_register(name, info->dev, par, &nvidia_bl_ops, 116 bd = backlight_device_register(name, info->dev, par, &nvidia_bl_ops,
116 &props); 117 &props);
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index efe10ff86d63..081dc4745274 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -1057,7 +1057,7 @@ static int nvidiafb_suspend(struct pci_dev *dev, pm_message_t mesg)
1057 1057
1058 if (mesg.event == PM_EVENT_PRETHAW) 1058 if (mesg.event == PM_EVENT_PRETHAW)
1059 mesg.event = PM_EVENT_FREEZE; 1059 mesg.event = PM_EVENT_FREEZE;
1060 acquire_console_sem(); 1060 console_lock();
1061 par->pm_state = mesg.event; 1061 par->pm_state = mesg.event;
1062 1062
1063 if (mesg.event & PM_EVENT_SLEEP) { 1063 if (mesg.event & PM_EVENT_SLEEP) {
@@ -1070,7 +1070,7 @@ static int nvidiafb_suspend(struct pci_dev *dev, pm_message_t mesg)
1070 } 1070 }
1071 dev->dev.power.power_state = mesg; 1071 dev->dev.power.power_state = mesg;
1072 1072
1073 release_console_sem(); 1073 console_unlock();
1074 return 0; 1074 return 0;
1075} 1075}
1076 1076
@@ -1079,7 +1079,7 @@ static int nvidiafb_resume(struct pci_dev *dev)
1079 struct fb_info *info = pci_get_drvdata(dev); 1079 struct fb_info *info = pci_get_drvdata(dev);
1080 struct nvidia_par *par = info->par; 1080 struct nvidia_par *par = info->par;
1081 1081
1082 acquire_console_sem(); 1082 console_lock();
1083 pci_set_power_state(dev, PCI_D0); 1083 pci_set_power_state(dev, PCI_D0);
1084 1084
1085 if (par->pm_state != PM_EVENT_FREEZE) { 1085 if (par->pm_state != PM_EVENT_FREEZE) {
@@ -1097,7 +1097,7 @@ static int nvidiafb_resume(struct pci_dev *dev)
1097 nvidiafb_blank(FB_BLANK_UNBLANK, info); 1097 nvidiafb_blank(FB_BLANK_UNBLANK, info);
1098 1098
1099fail: 1099fail:
1100 release_console_sem(); 1100 console_unlock();
1101 return 0; 1101 return 0;
1102} 1102}
1103#else 1103#else
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig
index 455c6055325d..196fa2e7f438 100644
--- a/drivers/video/omap/Kconfig
+++ b/drivers/video/omap/Kconfig
@@ -1,17 +1,22 @@
1config FB_OMAP 1config FB_OMAP
2 tristate "OMAP frame buffer support (EXPERIMENTAL)" 2 tristate "OMAP frame buffer support (EXPERIMENTAL)"
3 depends on FB && ARCH_OMAP && (OMAP2_DSS = "n") 3 depends on FB && (OMAP2_DSS = "n")
4 4 depends on ARCH_OMAP1 || ARCH_OMAP2 || ARCH_OMAP3
5 select FB_CFB_FILLRECT 5 select FB_CFB_FILLRECT
6 select FB_CFB_COPYAREA 6 select FB_CFB_COPYAREA
7 select FB_CFB_IMAGEBLIT 7 select FB_CFB_IMAGEBLIT
8 select TWL4030_CORE if MACH_OMAP_2430SDP
8 help 9 help
9 Frame buffer driver for OMAP based boards. 10 Frame buffer driver for OMAP based boards.
10 11
11config FB_OMAP_LCD_VGA 12config FB_OMAP_LCD_VGA
12 bool "Use LCD in VGA mode" 13 bool "Use LCD in VGA mode"
13 depends on MACH_OMAP_3430SDP || MACH_OMAP_LDP 14 depends on MACH_OMAP_3430SDP || MACH_OMAP_LDP
14 15 help
16 Set LCD resolution as VGA (640 X 480).
17 Default resolution without this option is QVGA(320 X 240).
18 Please take a look at drivers/video/omap/lcd_ldp.c file
19 for lcd driver code.
15choice 20choice
16 depends on FB_OMAP && MACH_OVERO 21 depends on FB_OMAP && MACH_OVERO
17 prompt "Screen resolution" 22 prompt "Screen resolution"
@@ -59,7 +64,7 @@ config FB_OMAP_MANUAL_UPDATE
59 depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL 64 depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL
60 help 65 help
61 Say Y here, if your user-space applications are capable of 66 Say Y here, if your user-space applications are capable of
62 notifying the frame buffer driver when a change has occured in 67 notifying the frame buffer driver when a change has occurred in
63 the frame buffer content and thus a reload of the image data to 68 the frame buffer content and thus a reload of the image data to
64 the external frame buffer is required. If unsure, say N. 69 the external frame buffer is required. If unsure, say N.
65 70
diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile
index 49226a1b909e..25db55696e14 100644
--- a/drivers/video/omap/Makefile
+++ b/drivers/video/omap/Makefile
@@ -30,7 +30,6 @@ objs-y$(CONFIG_MACH_OMAP_APOLLON) += lcd_apollon.o
30objs-y$(CONFIG_MACH_OMAP_2430SDP) += lcd_2430sdp.o 30objs-y$(CONFIG_MACH_OMAP_2430SDP) += lcd_2430sdp.o
31objs-y$(CONFIG_MACH_OMAP_3430SDP) += lcd_2430sdp.o 31objs-y$(CONFIG_MACH_OMAP_3430SDP) += lcd_2430sdp.o
32objs-y$(CONFIG_MACH_OMAP_LDP) += lcd_ldp.o 32objs-y$(CONFIG_MACH_OMAP_LDP) += lcd_ldp.o
33objs-y$(CONFIG_MACH_OMAP2EVM) += lcd_omap2evm.o
34objs-y$(CONFIG_MACH_OMAP3EVM) += lcd_omap3evm.o 33objs-y$(CONFIG_MACH_OMAP3EVM) += lcd_omap3evm.o
35objs-y$(CONFIG_MACH_OMAP3_BEAGLE) += lcd_omap3beagle.o 34objs-y$(CONFIG_MACH_OMAP3_BEAGLE) += lcd_omap3beagle.o
36objs-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o 35objs-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o
diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c
index 2ffb34af4c59..c0504a8a5079 100644
--- a/drivers/video/omap/blizzard.c
+++ b/drivers/video/omap/blizzard.c
@@ -397,8 +397,7 @@ static inline void free_req(struct blizzard_request *req)
397 397
398 spin_lock_irqsave(&blizzard.req_lock, flags); 398 spin_lock_irqsave(&blizzard.req_lock, flags);
399 399
400 list_del(&req->entry); 400 list_move(&req->entry, &blizzard.free_req_list);
401 list_add(&req->entry, &blizzard.free_req_list);
402 if (!(req->flags & REQ_FROM_IRQ_POOL)) 401 if (!(req->flags & REQ_FROM_IRQ_POOL))
403 up(&blizzard.req_sema); 402 up(&blizzard.req_sema);
404 403
@@ -1590,7 +1589,7 @@ static int blizzard_init(struct omapfb_device *fbdev, int ext_mode,
1590 blizzard.auto_update_window.width = fbdev->panel->x_res; 1589 blizzard.auto_update_window.width = fbdev->panel->x_res;
1591 blizzard.auto_update_window.height = fbdev->panel->y_res; 1590 blizzard.auto_update_window.height = fbdev->panel->y_res;
1592 blizzard.auto_update_window.out_x = 0; 1591 blizzard.auto_update_window.out_x = 0;
1593 blizzard.auto_update_window.out_x = 0; 1592 blizzard.auto_update_window.out_y = 0;
1594 blizzard.auto_update_window.out_width = fbdev->panel->x_res; 1593 blizzard.auto_update_window.out_width = fbdev->panel->x_res;
1595 blizzard.auto_update_window.out_height = fbdev->panel->y_res; 1594 blizzard.auto_update_window.out_height = fbdev->panel->y_res;
1596 blizzard.auto_update_window.format = 0; 1595 blizzard.auto_update_window.format = 0;
diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c
index 529483467abf..0ccd7adf47bb 100644
--- a/drivers/video/omap/dispc.c
+++ b/drivers/video/omap/dispc.c
@@ -922,14 +922,14 @@ static int get_dss_clocks(void)
922 return PTR_ERR(dispc.dss_ick); 922 return PTR_ERR(dispc.dss_ick);
923 } 923 }
924 924
925 dispc.dss1_fck = clk_get(&dispc.fbdev->dssdev->dev, "dss1_fck"); 925 dispc.dss1_fck = clk_get(&dispc.fbdev->dssdev->dev, "fck");
926 if (IS_ERR(dispc.dss1_fck)) { 926 if (IS_ERR(dispc.dss1_fck)) {
927 dev_err(dispc.fbdev->dev, "can't get dss1_fck\n"); 927 dev_err(dispc.fbdev->dev, "can't get dss1_fck\n");
928 clk_put(dispc.dss_ick); 928 clk_put(dispc.dss_ick);
929 return PTR_ERR(dispc.dss1_fck); 929 return PTR_ERR(dispc.dss1_fck);
930 } 930 }
931 931
932 dispc.dss_54m_fck = clk_get(&dispc.fbdev->dssdev->dev, "tv_fck"); 932 dispc.dss_54m_fck = clk_get(&dispc.fbdev->dssdev->dev, "tv_clk");
933 if (IS_ERR(dispc.dss_54m_fck)) { 933 if (IS_ERR(dispc.dss_54m_fck)) {
934 dev_err(dispc.fbdev->dev, "can't get tv_fck\n"); 934 dev_err(dispc.fbdev->dev, "can't get tv_fck\n");
935 clk_put(dispc.dss_ick); 935 clk_put(dispc.dss_ick);
diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c
index 0016f77cd13f..084aa0ac562b 100644
--- a/drivers/video/omap/hwa742.c
+++ b/drivers/video/omap/hwa742.c
@@ -269,8 +269,7 @@ static inline void free_req(struct hwa742_request *req)
269 269
270 spin_lock_irqsave(&hwa742.req_lock, flags); 270 spin_lock_irqsave(&hwa742.req_lock, flags);
271 271
272 list_del(&req->entry); 272 list_move(&req->entry, &hwa742.free_req_list);
273 list_add(&req->entry, &hwa742.free_req_list);
274 if (!(req->flags & REQ_FROM_IRQ_POOL)) 273 if (!(req->flags & REQ_FROM_IRQ_POOL))
275 up(&hwa742.req_sema); 274 up(&hwa742.req_sema);
276 275
diff --git a/drivers/video/omap/lcd_mipid.c b/drivers/video/omap/lcd_mipid.c
index 64dcc7439c99..90e3bdd1b7ab 100644
--- a/drivers/video/omap/lcd_mipid.c
+++ b/drivers/video/omap/lcd_mipid.c
@@ -396,7 +396,7 @@ static void mipid_esd_start_check(struct mipid_device *md)
396static void mipid_esd_stop_check(struct mipid_device *md) 396static void mipid_esd_stop_check(struct mipid_device *md)
397{ 397{
398 if (md->esd_check != NULL) 398 if (md->esd_check != NULL)
399 cancel_rearming_delayed_workqueue(md->esd_wq, &md->esd_work); 399 cancel_delayed_work_sync(&md->esd_work);
400} 400}
401 401
402static void mipid_esd_work(struct work_struct *work) 402static void mipid_esd_work(struct work_struct *work)
diff --git a/drivers/video/omap/lcd_omap2evm.c b/drivers/video/omap/lcd_omap2evm.c
deleted file mode 100644
index 7e7a65c08452..000000000000
--- a/drivers/video/omap/lcd_omap2evm.c
+++ /dev/null
@@ -1,192 +0,0 @@
1/*
2 * LCD panel support for the MISTRAL OMAP2EVM board
3 *
4 * Author: Arun C <arunedarath@mistralsolutions.com>
5 *
6 * Derived from drivers/video/omap/lcd_omap3evm.c
7 * Derived from drivers/video/omap/lcd-apollon.c
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24#include <linux/module.h>
25#include <linux/platform_device.h>
26#include <linux/gpio.h>
27#include <linux/i2c/twl.h>
28
29#include <plat/mux.h>
30#include <asm/mach-types.h>
31
32#include "omapfb.h"
33
34#define LCD_PANEL_ENABLE_GPIO 154
35#define LCD_PANEL_LR 128
36#define LCD_PANEL_UD 129
37#define LCD_PANEL_INI 152
38#define LCD_PANEL_QVGA 148
39#define LCD_PANEL_RESB 153
40
41#define TWL_LED_LEDEN 0x00
42#define TWL_PWMA_PWMAON 0x00
43#define TWL_PWMA_PWMAOFF 0x01
44
45static unsigned int bklight_level;
46
47static int omap2evm_panel_init(struct lcd_panel *panel,
48 struct omapfb_device *fbdev)
49{
50 gpio_request(LCD_PANEL_ENABLE_GPIO, "LCD enable");
51 gpio_request(LCD_PANEL_LR, "LCD lr");
52 gpio_request(LCD_PANEL_UD, "LCD ud");
53 gpio_request(LCD_PANEL_INI, "LCD ini");
54 gpio_request(LCD_PANEL_QVGA, "LCD qvga");
55 gpio_request(LCD_PANEL_RESB, "LCD resb");
56
57 gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 1);
58 gpio_direction_output(LCD_PANEL_RESB, 1);
59 gpio_direction_output(LCD_PANEL_INI, 1);
60 gpio_direction_output(LCD_PANEL_QVGA, 0);
61 gpio_direction_output(LCD_PANEL_LR, 1);
62 gpio_direction_output(LCD_PANEL_UD, 1);
63
64 twl_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN);
65 twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON);
66 twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF);
67 bklight_level = 100;
68
69 return 0;
70}
71
72static void omap2evm_panel_cleanup(struct lcd_panel *panel)
73{
74 gpio_free(LCD_PANEL_RESB);
75 gpio_free(LCD_PANEL_QVGA);
76 gpio_free(LCD_PANEL_INI);
77 gpio_free(LCD_PANEL_UD);
78 gpio_free(LCD_PANEL_LR);
79 gpio_free(LCD_PANEL_ENABLE_GPIO);
80}
81
82static int omap2evm_panel_enable(struct lcd_panel *panel)
83{
84 gpio_set_value(LCD_PANEL_ENABLE_GPIO, 0);
85 return 0;
86}
87
88static void omap2evm_panel_disable(struct lcd_panel *panel)
89{
90 gpio_set_value(LCD_PANEL_ENABLE_GPIO, 1);
91}
92
93static unsigned long omap2evm_panel_get_caps(struct lcd_panel *panel)
94{
95 return 0;
96}
97
98static int omap2evm_bklight_setlevel(struct lcd_panel *panel,
99 unsigned int level)
100{
101 u8 c;
102 if ((level >= 0) && (level <= 100)) {
103 c = (125 * (100 - level)) / 100 + 2;
104 twl_i2c_write_u8(TWL4030_MODULE_PWMA, c, TWL_PWMA_PWMAOFF);
105 bklight_level = level;
106 }
107 return 0;
108}
109
110static unsigned int omap2evm_bklight_getlevel(struct lcd_panel *panel)
111{
112 return bklight_level;
113}
114
115static unsigned int omap2evm_bklight_getmaxlevel(struct lcd_panel *panel)
116{
117 return 100;
118}
119
120struct lcd_panel omap2evm_panel = {
121 .name = "omap2evm",
122 .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
123 OMAP_LCDC_INV_HSYNC,
124
125 .bpp = 16,
126 .data_lines = 18,
127 .x_res = 480,
128 .y_res = 640,
129 .hsw = 3,
130 .hfp = 0,
131 .hbp = 28,
132 .vsw = 2,
133 .vfp = 1,
134 .vbp = 0,
135
136 .pixel_clock = 20000,
137
138 .init = omap2evm_panel_init,
139 .cleanup = omap2evm_panel_cleanup,
140 .enable = omap2evm_panel_enable,
141 .disable = omap2evm_panel_disable,
142 .get_caps = omap2evm_panel_get_caps,
143 .set_bklight_level = omap2evm_bklight_setlevel,
144 .get_bklight_level = omap2evm_bklight_getlevel,
145 .get_bklight_max = omap2evm_bklight_getmaxlevel,
146};
147
148static int omap2evm_panel_probe(struct platform_device *pdev)
149{
150 omapfb_register_panel(&omap2evm_panel);
151 return 0;
152}
153
154static int omap2evm_panel_remove(struct platform_device *pdev)
155{
156 return 0;
157}
158
159static int omap2evm_panel_suspend(struct platform_device *pdev,
160 pm_message_t mesg)
161{
162 return 0;
163}
164
165static int omap2evm_panel_resume(struct platform_device *pdev)
166{
167 return 0;
168}
169
170struct platform_driver omap2evm_panel_driver = {
171 .probe = omap2evm_panel_probe,
172 .remove = omap2evm_panel_remove,
173 .suspend = omap2evm_panel_suspend,
174 .resume = omap2evm_panel_resume,
175 .driver = {
176 .name = "omap2evm_lcd",
177 .owner = THIS_MODULE,
178 },
179};
180
181static int __init omap2evm_panel_drv_init(void)
182{
183 return platform_driver_register(&omap2evm_panel_driver);
184}
185
186static void __exit omap2evm_panel_drv_exit(void)
187{
188 platform_driver_unregister(&omap2evm_panel_driver);
189}
190
191module_init(omap2evm_panel_drv_init);
192module_exit(omap2evm_panel_drv_exit);
diff --git a/drivers/video/omap/lcd_omap3beagle.c b/drivers/video/omap/lcd_omap3beagle.c
index ca75cc2a87a5..d7c6c3e0afc6 100644
--- a/drivers/video/omap/lcd_omap3beagle.c
+++ b/drivers/video/omap/lcd_omap3beagle.c
@@ -25,8 +25,6 @@
25#include <linux/gpio.h> 25#include <linux/gpio.h>
26#include <linux/i2c/twl.h> 26#include <linux/i2c/twl.h>
27 27
28#include <plat/mux.h>
29#include <plat/mux.h>
30#include <asm/mach-types.h> 28#include <asm/mach-types.h>
31 29
32#include "omapfb.h" 30#include "omapfb.h"
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
index e264efd0278f..b3ddd743d8a6 100644
--- a/drivers/video/omap/omapfb_main.c
+++ b/drivers/video/omap/omapfb_main.c
@@ -90,7 +90,7 @@ static void omapdss_release(struct device *dev)
90 90
91/* dummy device for clocks */ 91/* dummy device for clocks */
92static struct platform_device omapdss_device = { 92static struct platform_device omapdss_device = {
93 .name = "omapdss", 93 .name = "omapdss_dss",
94 .id = -1, 94 .id = -1,
95 .dev = { 95 .dev = {
96 .release = omapdss_release, 96 .release = omapdss_release,
diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c
index eada9f12efc7..0c6981f1a4a3 100644
--- a/drivers/video/omap/rfbi.c
+++ b/drivers/video/omap/rfbi.c
@@ -90,7 +90,7 @@ static int rfbi_get_clocks(void)
90 return PTR_ERR(rfbi.dss_ick); 90 return PTR_ERR(rfbi.dss_ick);
91 } 91 }
92 92
93 rfbi.dss1_fck = clk_get(&rfbi.fbdev->dssdev->dev, "dss1_fck"); 93 rfbi.dss1_fck = clk_get(&rfbi.fbdev->dssdev->dev, "fck");
94 if (IS_ERR(rfbi.dss1_fck)) { 94 if (IS_ERR(rfbi.dss1_fck)) {
95 dev_err(rfbi.fbdev->dev, "can't get dss1_fck\n"); 95 dev_err(rfbi.fbdev->dev, "can't get dss1_fck\n");
96 clk_put(rfbi.dss_ick); 96 clk_put(rfbi.dss_ick);
diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
index d853d05dad31..5ddef129f798 100644
--- a/drivers/video/omap2/Makefile
+++ b/drivers/video/omap2/Makefile
@@ -1,6 +1,6 @@
1obj-$(CONFIG_OMAP2_VRAM) += vram.o 1obj-$(CONFIG_OMAP2_VRAM) += vram.o
2obj-$(CONFIG_OMAP2_VRFB) += vrfb.o 2obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
3 3
4obj-y += dss/ 4obj-$(CONFIG_OMAP2_DSS) += dss/
5obj-y += omapfb/ 5obj-$(CONFIG_FB_OMAP2) += omapfb/
6obj-y += displays/ 6obj-y += displays/
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
index 881c9f77c75a..609a28073178 100644
--- a/drivers/video/omap2/displays/Kconfig
+++ b/drivers/video/omap2/displays/Kconfig
@@ -1,24 +1,34 @@
1menu "OMAP2/3 Display Device Drivers" 1menu "OMAP2/3 Display Device Drivers"
2 depends on OMAP2_DSS 2 depends on OMAP2_DSS
3 3
4config PANEL_GENERIC 4config PANEL_GENERIC_DPI
5 tristate "Generic Panel" 5 tristate "Generic DPI Panel"
6 depends on OMAP2_DSS_DPI
6 help 7 help
7 Generic panel driver. 8 Generic DPI panel driver.
8 Used for DVI output for Beagle and OMAP3 SDP. 9 Supports DVI output for Beagle and OMAP3 SDP.
10 Supports LCD Panel used in TI SDP3430 and EVM boards,
11 OMAP3517 EVM boards and CM-T35.
12
13config PANEL_LGPHILIPS_LB035Q02
14 tristate "LG.Philips LB035Q02 LCD Panel"
15 depends on OMAP2_DSS_DPI && SPI
16 help
17 LCD Panel used on the Gumstix Overo Palo35
9 18
10config PANEL_SHARP_LS037V7DW01 19config PANEL_SHARP_LS037V7DW01
11 tristate "Sharp LS037V7DW01 LCD Panel" 20 tristate "Sharp LS037V7DW01 LCD Panel"
12 depends on OMAP2_DSS 21 depends on OMAP2_DSS_DPI
13 select BACKLIGHT_CLASS_DEVICE 22 select BACKLIGHT_CLASS_DEVICE
14 help 23 help
15 LCD Panel used in TI's SDP3430 and EVM boards 24 LCD Panel used in TI's SDP3430 and EVM boards
16 25
17config PANEL_SHARP_LQ043T1DG01 26config PANEL_NEC_NL8048HL11_01B
18 tristate "Sharp LQ043T1DG01 LCD Panel" 27 tristate "NEC NL8048HL11-01B Panel"
19 depends on OMAP2_DSS 28 depends on OMAP2_DSS_DPI
20 help 29 help
21 LCD Panel used in TI's OMAP3517 EVM boards 30 This NEC NL8048HL11-01B panel is TFT LCD
31 used in the Zoom2/3/3630 sdp boards.
22 32
23config PANEL_TAAL 33config PANEL_TAAL
24 tristate "Taal DSI Panel" 34 tristate "Taal DSI Panel"
@@ -26,21 +36,15 @@ config PANEL_TAAL
26 help 36 help
27 Taal DSI command mode panel from TPO. 37 Taal DSI command mode panel from TPO.
28 38
29config PANEL_TOPPOLY_TDO35S
30 tristate "Toppoly TDO35S LCD Panel support"
31 depends on OMAP2_DSS
32 help
33 LCD Panel used in CM-T35
34
35config PANEL_TPO_TD043MTEA1 39config PANEL_TPO_TD043MTEA1
36 tristate "TPO TD043MTEA1 LCD Panel" 40 tristate "TPO TD043MTEA1 LCD Panel"
37 depends on OMAP2_DSS && SPI 41 depends on OMAP2_DSS_DPI && SPI
38 help 42 help
39 LCD Panel used in OMAP3 Pandora 43 LCD Panel used in OMAP3 Pandora
40 44
41config PANEL_ACX565AKM 45config PANEL_ACX565AKM
42 tristate "ACX565AKM Panel" 46 tristate "ACX565AKM Panel"
43 depends on OMAP2_DSS_SDI 47 depends on OMAP2_DSS_SDI && SPI
44 select BACKLIGHT_CLASS_DEVICE 48 select BACKLIGHT_CLASS_DEVICE
45 help 49 help
46 This is the LCD panel used on Nokia N900 50 This is the LCD panel used on Nokia N900
diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
index aa386095d7c4..0f601ab3abf4 100644
--- a/drivers/video/omap2/displays/Makefile
+++ b/drivers/video/omap2/displays/Makefile
@@ -1,8 +1,8 @@
1obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o 1obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o
2obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o
2obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o 3obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
3obj-$(CONFIG_PANEL_SHARP_LQ043T1DG01) += panel-sharp-lq043t1dg01.o 4obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o
4 5
5obj-$(CONFIG_PANEL_TAAL) += panel-taal.o 6obj-$(CONFIG_PANEL_TAAL) += panel-taal.o
6obj-$(CONFIG_PANEL_TOPPOLY_TDO35S) += panel-toppoly-tdo35s.o
7obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o 7obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
8obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o 8obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
index 07fbb8a733bb..dbd59b8e5b36 100644
--- a/drivers/video/omap2/displays/panel-acx565akm.c
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -30,7 +30,7 @@
30#include <linux/backlight.h> 30#include <linux/backlight.h>
31#include <linux/fb.h> 31#include <linux/fb.h>
32 32
33#include <plat/display.h> 33#include <video/omapdss.h>
34 34
35#define MIPID_CMD_READ_DISP_ID 0x04 35#define MIPID_CMD_READ_DISP_ID 0x04
36#define MIPID_CMD_READ_RED 0x06 36#define MIPID_CMD_READ_RED 0x06
@@ -534,6 +534,7 @@ static int acx_panel_probe(struct omap_dss_device *dssdev)
534 534
535 props.fb_blank = FB_BLANK_UNBLANK; 535 props.fb_blank = FB_BLANK_UNBLANK;
536 props.power = FB_BLANK_UNBLANK; 536 props.power = FB_BLANK_UNBLANK;
537 props.type = BACKLIGHT_RAW;
537 538
538 bldev = backlight_device_register("acx565akm", &md->spi->dev, 539 bldev = backlight_device_register("acx565akm", &md->spi->dev,
539 md, &acx565akm_bl_ops, &props); 540 md, &acx565akm_bl_ops, &props);
@@ -587,6 +588,9 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev)
587 588
588 dev_dbg(&dssdev->dev, "%s\n", __func__); 589 dev_dbg(&dssdev->dev, "%s\n", __func__);
589 590
591 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
592 return 0;
593
590 mutex_lock(&md->mutex); 594 mutex_lock(&md->mutex);
591 595
592 r = omapdss_sdi_display_enable(dssdev); 596 r = omapdss_sdi_display_enable(dssdev);
@@ -644,6 +648,9 @@ static void acx_panel_power_off(struct omap_dss_device *dssdev)
644 648
645 dev_dbg(&dssdev->dev, "%s\n", __func__); 649 dev_dbg(&dssdev->dev, "%s\n", __func__);
646 650
651 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
652 return;
653
647 mutex_lock(&md->mutex); 654 mutex_lock(&md->mutex);
648 655
649 if (!md->enabled) { 656 if (!md->enabled) {
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
new file mode 100644
index 000000000000..9c90f75653fb
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -0,0 +1,441 @@
1/*
2 * Generic DPI Panels support
3 *
4 * Copyright (C) 2010 Canonical Ltd.
5 * Author: Bryan Wu <bryan.wu@canonical.com>
6 *
7 * LCD panel driver for Sharp LQ043T1DG01
8 *
9 * Copyright (C) 2009 Texas Instruments Inc
10 * Author: Vaibhav Hiremath <hvaibhav@ti.com>
11 *
12 * LCD panel driver for Toppoly TDO35S
13 *
14 * Copyright (C) 2009 CompuLab, Ltd.
15 * Author: Mike Rapoport <mike@compulab.co.il>
16 *
17 * Copyright (C) 2008 Nokia Corporation
18 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
19 *
20 * This program is free software; you can redistribute it and/or modify it
21 * under the terms of the GNU General Public License version 2 as published by
22 * the Free Software Foundation.
23 *
24 * This program is distributed in the hope that it will be useful, but WITHOUT
25 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
26 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
27 * more details.
28 *
29 * You should have received a copy of the GNU General Public License along with
30 * this program. If not, see <http://www.gnu.org/licenses/>.
31 */
32
33#include <linux/module.h>
34#include <linux/delay.h>
35#include <linux/slab.h>
36#include <video/omapdss.h>
37
38#include <video/omap-panel-generic-dpi.h>
39
40struct panel_config {
41 struct omap_video_timings timings;
42
43 int acbi; /* ac-bias pin transitions per interrupt */
44 /* Unit: line clocks */
45 int acb; /* ac-bias pin frequency */
46
47 enum omap_panel_config config;
48
49 int power_on_delay;
50 int power_off_delay;
51
52 /*
53 * Used to match device to panel configuration
54 * when use generic panel driver
55 */
56 const char *name;
57};
58
59/* Panel configurations */
60static struct panel_config generic_dpi_panels[] = {
61 /* Generic Panel */
62 {
63 {
64 .x_res = 640,
65 .y_res = 480,
66
67 .pixel_clock = 23500,
68
69 .hfp = 48,
70 .hsw = 32,
71 .hbp = 80,
72
73 .vfp = 3,
74 .vsw = 4,
75 .vbp = 7,
76 },
77 .acbi = 0x0,
78 .acb = 0x0,
79 .config = OMAP_DSS_LCD_TFT,
80 .power_on_delay = 0,
81 .power_off_delay = 0,
82 .name = "generic",
83 },
84
85 /* Sharp LQ043T1DG01 */
86 {
87 {
88 .x_res = 480,
89 .y_res = 272,
90
91 .pixel_clock = 9000,
92
93 .hsw = 42,
94 .hfp = 3,
95 .hbp = 2,
96
97 .vsw = 11,
98 .vfp = 3,
99 .vbp = 2,
100 },
101 .acbi = 0x0,
102 .acb = 0x0,
103 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
104 OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IEO,
105 .power_on_delay = 50,
106 .power_off_delay = 100,
107 .name = "sharp_lq",
108 },
109
110 /* Sharp LS037V7DW01 */
111 {
112 {
113 .x_res = 480,
114 .y_res = 640,
115
116 .pixel_clock = 19200,
117
118 .hsw = 2,
119 .hfp = 1,
120 .hbp = 28,
121
122 .vsw = 1,
123 .vfp = 1,
124 .vbp = 1,
125 },
126 .acbi = 0x0,
127 .acb = 0x28,
128 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
129 OMAP_DSS_LCD_IHS,
130 .power_on_delay = 50,
131 .power_off_delay = 100,
132 .name = "sharp_ls",
133 },
134
135 /* Toppoly TDO35S */
136 {
137 {
138 .x_res = 480,
139 .y_res = 640,
140
141 .pixel_clock = 26000,
142
143 .hfp = 104,
144 .hsw = 8,
145 .hbp = 8,
146
147 .vfp = 4,
148 .vsw = 2,
149 .vbp = 2,
150 },
151 .acbi = 0x0,
152 .acb = 0x0,
153 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
154 OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC |
155 OMAP_DSS_LCD_ONOFF,
156 .power_on_delay = 0,
157 .power_off_delay = 0,
158 .name = "toppoly_tdo35s",
159 },
160
161 /* Samsung LTE430WQ-F0C */
162 {
163 {
164 .x_res = 480,
165 .y_res = 272,
166
167 .pixel_clock = 9200,
168
169 .hfp = 8,
170 .hsw = 41,
171 .hbp = 45 - 41,
172
173 .vfp = 4,
174 .vsw = 10,
175 .vbp = 12 - 10,
176 },
177 .acbi = 0x0,
178 .acb = 0x0,
179 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
180 OMAP_DSS_LCD_IHS,
181 .power_on_delay = 0,
182 .power_off_delay = 0,
183 .name = "samsung_lte430wq_f0c",
184 },
185
186 /* Seiko 70WVW1TZ3Z3 */
187 {
188 {
189 .x_res = 800,
190 .y_res = 480,
191
192 .pixel_clock = 33000,
193
194 .hsw = 128,
195 .hfp = 10,
196 .hbp = 10,
197
198 .vsw = 2,
199 .vfp = 4,
200 .vbp = 11,
201 },
202 .acbi = 0x0,
203 .acb = 0x0,
204 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
205 OMAP_DSS_LCD_IHS,
206 .power_on_delay = 0,
207 .power_off_delay = 0,
208 .name = "seiko_70wvw1tz3",
209 },
210
211 /* Powertip PH480272T */
212 {
213 {
214 .x_res = 480,
215 .y_res = 272,
216
217 .pixel_clock = 9000,
218
219 .hsw = 40,
220 .hfp = 2,
221 .hbp = 2,
222
223 .vsw = 10,
224 .vfp = 2,
225 .vbp = 2,
226 },
227 .acbi = 0x0,
228 .acb = 0x0,
229 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
230 OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IEO,
231 .power_on_delay = 0,
232 .power_off_delay = 0,
233 .name = "powertip_ph480272t",
234 },
235};
236
237struct panel_drv_data {
238
239 struct omap_dss_device *dssdev;
240
241 struct panel_config *panel_config;
242};
243
244static inline struct panel_generic_dpi_data
245*get_panel_data(const struct omap_dss_device *dssdev)
246{
247 return (struct panel_generic_dpi_data *) dssdev->data;
248}
249
250static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev)
251{
252 int r;
253 struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
254 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
255 struct panel_config *panel_config = drv_data->panel_config;
256
257 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
258 return 0;
259
260 r = omapdss_dpi_display_enable(dssdev);
261 if (r)
262 goto err0;
263
264 /* wait couple of vsyncs until enabling the LCD */
265 if (panel_config->power_on_delay)
266 msleep(panel_config->power_on_delay);
267
268 if (panel_data->platform_enable) {
269 r = panel_data->platform_enable(dssdev);
270 if (r)
271 goto err1;
272 }
273
274 return 0;
275err1:
276 omapdss_dpi_display_disable(dssdev);
277err0:
278 return r;
279}
280
281static void generic_dpi_panel_power_off(struct omap_dss_device *dssdev)
282{
283 struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
284 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
285 struct panel_config *panel_config = drv_data->panel_config;
286
287 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
288 return;
289
290 if (panel_data->platform_disable)
291 panel_data->platform_disable(dssdev);
292
293 /* wait couple of vsyncs after disabling the LCD */
294 if (panel_config->power_off_delay)
295 msleep(panel_config->power_off_delay);
296
297 omapdss_dpi_display_disable(dssdev);
298}
299
300static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
301{
302 struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev);
303 struct panel_config *panel_config = NULL;
304 struct panel_drv_data *drv_data = NULL;
305 int i;
306
307 dev_dbg(&dssdev->dev, "probe\n");
308
309 if (!panel_data || !panel_data->name)
310 return -EINVAL;
311
312 for (i = 0; i < ARRAY_SIZE(generic_dpi_panels); i++) {
313 if (strcmp(panel_data->name, generic_dpi_panels[i].name) == 0) {
314 panel_config = &generic_dpi_panels[i];
315 break;
316 }
317 }
318
319 if (!panel_config)
320 return -EINVAL;
321
322 dssdev->panel.config = panel_config->config;
323 dssdev->panel.timings = panel_config->timings;
324 dssdev->panel.acb = panel_config->acb;
325 dssdev->panel.acbi = panel_config->acbi;
326
327 drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
328 if (!drv_data)
329 return -ENOMEM;
330
331 drv_data->dssdev = dssdev;
332 drv_data->panel_config = panel_config;
333
334 dev_set_drvdata(&dssdev->dev, drv_data);
335
336 return 0;
337}
338
339static void __exit generic_dpi_panel_remove(struct omap_dss_device *dssdev)
340{
341 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
342
343 dev_dbg(&dssdev->dev, "remove\n");
344
345 kfree(drv_data);
346
347 dev_set_drvdata(&dssdev->dev, NULL);
348}
349
350static int generic_dpi_panel_enable(struct omap_dss_device *dssdev)
351{
352 int r = 0;
353
354 r = generic_dpi_panel_power_on(dssdev);
355 if (r)
356 return r;
357
358 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
359
360 return 0;
361}
362
363static void generic_dpi_panel_disable(struct omap_dss_device *dssdev)
364{
365 generic_dpi_panel_power_off(dssdev);
366
367 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
368}
369
370static int generic_dpi_panel_suspend(struct omap_dss_device *dssdev)
371{
372 generic_dpi_panel_power_off(dssdev);
373
374 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
375
376 return 0;
377}
378
379static int generic_dpi_panel_resume(struct omap_dss_device *dssdev)
380{
381 int r = 0;
382
383 r = generic_dpi_panel_power_on(dssdev);
384 if (r)
385 return r;
386
387 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
388
389 return 0;
390}
391
392static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev,
393 struct omap_video_timings *timings)
394{
395 dpi_set_timings(dssdev, timings);
396}
397
398static void generic_dpi_panel_get_timings(struct omap_dss_device *dssdev,
399 struct omap_video_timings *timings)
400{
401 *timings = dssdev->panel.timings;
402}
403
404static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev,
405 struct omap_video_timings *timings)
406{
407 return dpi_check_timings(dssdev, timings);
408}
409
410static struct omap_dss_driver dpi_driver = {
411 .probe = generic_dpi_panel_probe,
412 .remove = __exit_p(generic_dpi_panel_remove),
413
414 .enable = generic_dpi_panel_enable,
415 .disable = generic_dpi_panel_disable,
416 .suspend = generic_dpi_panel_suspend,
417 .resume = generic_dpi_panel_resume,
418
419 .set_timings = generic_dpi_panel_set_timings,
420 .get_timings = generic_dpi_panel_get_timings,
421 .check_timings = generic_dpi_panel_check_timings,
422
423 .driver = {
424 .name = "generic_dpi_panel",
425 .owner = THIS_MODULE,
426 },
427};
428
429static int __init generic_dpi_panel_drv_init(void)
430{
431 return omap_dss_register_driver(&dpi_driver);
432}
433
434static void __exit generic_dpi_panel_drv_exit(void)
435{
436 omap_dss_unregister_driver(&dpi_driver);
437}
438
439module_init(generic_dpi_panel_drv_init);
440module_exit(generic_dpi_panel_drv_exit);
441MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-generic.c b/drivers/video/omap2/displays/panel-generic.c
deleted file mode 100644
index 300eff5de1b4..000000000000
--- a/drivers/video/omap2/displays/panel-generic.c
+++ /dev/null
@@ -1,168 +0,0 @@
1/*
2 * Generic panel support
3 *
4 * Copyright (C) 2008 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <linux/module.h>
21#include <linux/delay.h>
22
23#include <plat/display.h>
24
25static struct omap_video_timings generic_panel_timings = {
26 /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */
27 .x_res = 640,
28 .y_res = 480,
29 .pixel_clock = 23500,
30 .hfp = 48,
31 .hsw = 32,
32 .hbp = 80,
33 .vfp = 3,
34 .vsw = 4,
35 .vbp = 7,
36};
37
38static int generic_panel_power_on(struct omap_dss_device *dssdev)
39{
40 int r;
41
42 r = omapdss_dpi_display_enable(dssdev);
43 if (r)
44 goto err0;
45
46 if (dssdev->platform_enable) {
47 r = dssdev->platform_enable(dssdev);
48 if (r)
49 goto err1;
50 }
51
52 return 0;
53err1:
54 omapdss_dpi_display_disable(dssdev);
55err0:
56 return r;
57}
58
59static void generic_panel_power_off(struct omap_dss_device *dssdev)
60{
61 if (dssdev->platform_disable)
62 dssdev->platform_disable(dssdev);
63
64 omapdss_dpi_display_disable(dssdev);
65}
66
67static int generic_panel_probe(struct omap_dss_device *dssdev)
68{
69 dssdev->panel.config = OMAP_DSS_LCD_TFT;
70 dssdev->panel.timings = generic_panel_timings;
71
72 return 0;
73}
74
75static void generic_panel_remove(struct omap_dss_device *dssdev)
76{
77}
78
79static int generic_panel_enable(struct omap_dss_device *dssdev)
80{
81 int r = 0;
82
83 r = generic_panel_power_on(dssdev);
84 if (r)
85 return r;
86
87 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
88
89 return 0;
90}
91
92static void generic_panel_disable(struct omap_dss_device *dssdev)
93{
94 generic_panel_power_off(dssdev);
95
96 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
97}
98
99static int generic_panel_suspend(struct omap_dss_device *dssdev)
100{
101 generic_panel_power_off(dssdev);
102 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
103 return 0;
104}
105
106static int generic_panel_resume(struct omap_dss_device *dssdev)
107{
108 int r = 0;
109
110 r = generic_panel_power_on(dssdev);
111 if (r)
112 return r;
113
114 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
115
116 return 0;
117}
118
119static void generic_panel_set_timings(struct omap_dss_device *dssdev,
120 struct omap_video_timings *timings)
121{
122 dpi_set_timings(dssdev, timings);
123}
124
125static void generic_panel_get_timings(struct omap_dss_device *dssdev,
126 struct omap_video_timings *timings)
127{
128 *timings = dssdev->panel.timings;
129}
130
131static int generic_panel_check_timings(struct omap_dss_device *dssdev,
132 struct omap_video_timings *timings)
133{
134 return dpi_check_timings(dssdev, timings);
135}
136
137static struct omap_dss_driver generic_driver = {
138 .probe = generic_panel_probe,
139 .remove = generic_panel_remove,
140
141 .enable = generic_panel_enable,
142 .disable = generic_panel_disable,
143 .suspend = generic_panel_suspend,
144 .resume = generic_panel_resume,
145
146 .set_timings = generic_panel_set_timings,
147 .get_timings = generic_panel_get_timings,
148 .check_timings = generic_panel_check_timings,
149
150 .driver = {
151 .name = "generic_panel",
152 .owner = THIS_MODULE,
153 },
154};
155
156static int __init generic_panel_drv_init(void)
157{
158 return omap_dss_register_driver(&generic_driver);
159}
160
161static void __exit generic_panel_drv_exit(void)
162{
163 omap_dss_unregister_driver(&generic_driver);
164}
165
166module_init(generic_panel_drv_init);
167module_exit(generic_panel_drv_exit);
168MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
new file mode 100644
index 000000000000..e0eb35be303e
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
@@ -0,0 +1,279 @@
1/*
2 * LCD panel driver for LG.Philips LB035Q02
3 *
4 * Author: Steve Sakoman <steve@sakoman.com>
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 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/module.h>
20#include <linux/delay.h>
21#include <linux/spi/spi.h>
22#include <linux/mutex.h>
23
24#include <video/omapdss.h>
25
26struct lb035q02_data {
27 struct mutex lock;
28};
29
30static struct omap_video_timings lb035q02_timings = {
31 .x_res = 320,
32 .y_res = 240,
33
34 .pixel_clock = 6500,
35
36 .hsw = 2,
37 .hfp = 20,
38 .hbp = 68,
39
40 .vsw = 2,
41 .vfp = 4,
42 .vbp = 18,
43};
44
45static int lb035q02_panel_power_on(struct omap_dss_device *dssdev)
46{
47 int r;
48
49 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
50 return 0;
51
52 r = omapdss_dpi_display_enable(dssdev);
53 if (r)
54 goto err0;
55
56 if (dssdev->platform_enable) {
57 r = dssdev->platform_enable(dssdev);
58 if (r)
59 goto err1;
60 }
61
62 return 0;
63err1:
64 omapdss_dpi_display_disable(dssdev);
65err0:
66 return r;
67}
68
69static void lb035q02_panel_power_off(struct omap_dss_device *dssdev)
70{
71 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
72 return;
73
74 if (dssdev->platform_disable)
75 dssdev->platform_disable(dssdev);
76
77 omapdss_dpi_display_disable(dssdev);
78}
79
80static int lb035q02_panel_probe(struct omap_dss_device *dssdev)
81{
82 struct lb035q02_data *ld;
83 int r;
84
85 dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
86 OMAP_DSS_LCD_IHS;
87 dssdev->panel.timings = lb035q02_timings;
88
89 ld = kzalloc(sizeof(*ld), GFP_KERNEL);
90 if (!ld) {
91 r = -ENOMEM;
92 goto err;
93 }
94 mutex_init(&ld->lock);
95 dev_set_drvdata(&dssdev->dev, ld);
96 return 0;
97err:
98 return r;
99}
100
101static void lb035q02_panel_remove(struct omap_dss_device *dssdev)
102{
103 struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
104
105 kfree(ld);
106}
107
108static int lb035q02_panel_enable(struct omap_dss_device *dssdev)
109{
110 struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
111 int r;
112
113 mutex_lock(&ld->lock);
114
115 r = lb035q02_panel_power_on(dssdev);
116 if (r)
117 goto err;
118 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
119
120 mutex_unlock(&ld->lock);
121 return 0;
122err:
123 mutex_unlock(&ld->lock);
124 return r;
125}
126
127static void lb035q02_panel_disable(struct omap_dss_device *dssdev)
128{
129 struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
130
131 mutex_lock(&ld->lock);
132
133 lb035q02_panel_power_off(dssdev);
134 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
135
136 mutex_unlock(&ld->lock);
137}
138
139static int lb035q02_panel_suspend(struct omap_dss_device *dssdev)
140{
141 struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
142
143 mutex_lock(&ld->lock);
144
145 lb035q02_panel_power_off(dssdev);
146 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
147
148 mutex_unlock(&ld->lock);
149 return 0;
150}
151
152static int lb035q02_panel_resume(struct omap_dss_device *dssdev)
153{
154 struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
155 int r;
156
157 mutex_lock(&ld->lock);
158
159 r = lb035q02_panel_power_on(dssdev);
160 if (r)
161 goto err;
162 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
163
164 mutex_unlock(&ld->lock);
165 return 0;
166err:
167 mutex_unlock(&ld->lock);
168 return r;
169}
170
171static struct omap_dss_driver lb035q02_driver = {
172 .probe = lb035q02_panel_probe,
173 .remove = lb035q02_panel_remove,
174
175 .enable = lb035q02_panel_enable,
176 .disable = lb035q02_panel_disable,
177 .suspend = lb035q02_panel_suspend,
178 .resume = lb035q02_panel_resume,
179
180 .driver = {
181 .name = "lgphilips_lb035q02_panel",
182 .owner = THIS_MODULE,
183 },
184};
185
186static int lb035q02_write_reg(struct spi_device *spi, u8 reg, u16 val)
187{
188 struct spi_message msg;
189 struct spi_transfer index_xfer = {
190 .len = 3,
191 .cs_change = 1,
192 };
193 struct spi_transfer value_xfer = {
194 .len = 3,
195 };
196 u8 buffer[16];
197
198 spi_message_init(&msg);
199
200 /* register index */
201 buffer[0] = 0x70;
202 buffer[1] = 0x00;
203 buffer[2] = reg & 0x7f;
204 index_xfer.tx_buf = buffer;
205 spi_message_add_tail(&index_xfer, &msg);
206
207 /* register value */
208 buffer[4] = 0x72;
209 buffer[5] = val >> 8;
210 buffer[6] = val;
211 value_xfer.tx_buf = buffer + 4;
212 spi_message_add_tail(&value_xfer, &msg);
213
214 return spi_sync(spi, &msg);
215}
216
217static void init_lb035q02_panel(struct spi_device *spi)
218{
219 /* Init sequence from page 28 of the lb035q02 spec */
220 lb035q02_write_reg(spi, 0x01, 0x6300);
221 lb035q02_write_reg(spi, 0x02, 0x0200);
222 lb035q02_write_reg(spi, 0x03, 0x0177);
223 lb035q02_write_reg(spi, 0x04, 0x04c7);
224 lb035q02_write_reg(spi, 0x05, 0xffc0);
225 lb035q02_write_reg(spi, 0x06, 0xe806);
226 lb035q02_write_reg(spi, 0x0a, 0x4008);
227 lb035q02_write_reg(spi, 0x0b, 0x0000);
228 lb035q02_write_reg(spi, 0x0d, 0x0030);
229 lb035q02_write_reg(spi, 0x0e, 0x2800);
230 lb035q02_write_reg(spi, 0x0f, 0x0000);
231 lb035q02_write_reg(spi, 0x16, 0x9f80);
232 lb035q02_write_reg(spi, 0x17, 0x0a0f);
233 lb035q02_write_reg(spi, 0x1e, 0x00c1);
234 lb035q02_write_reg(spi, 0x30, 0x0300);
235 lb035q02_write_reg(spi, 0x31, 0x0007);
236 lb035q02_write_reg(spi, 0x32, 0x0000);
237 lb035q02_write_reg(spi, 0x33, 0x0000);
238 lb035q02_write_reg(spi, 0x34, 0x0707);
239 lb035q02_write_reg(spi, 0x35, 0x0004);
240 lb035q02_write_reg(spi, 0x36, 0x0302);
241 lb035q02_write_reg(spi, 0x37, 0x0202);
242 lb035q02_write_reg(spi, 0x3a, 0x0a0d);
243 lb035q02_write_reg(spi, 0x3b, 0x0806);
244}
245
246static int __devinit lb035q02_panel_spi_probe(struct spi_device *spi)
247{
248 init_lb035q02_panel(spi);
249 return omap_dss_register_driver(&lb035q02_driver);
250}
251
252static int __devexit lb035q02_panel_spi_remove(struct spi_device *spi)
253{
254 omap_dss_unregister_driver(&lb035q02_driver);
255 return 0;
256}
257
258static struct spi_driver lb035q02_spi_driver = {
259 .driver = {
260 .name = "lgphilips_lb035q02_panel-spi",
261 .owner = THIS_MODULE,
262 },
263 .probe = lb035q02_panel_spi_probe,
264 .remove = __devexit_p(lb035q02_panel_spi_remove),
265};
266
267static int __init lb035q02_panel_drv_init(void)
268{
269 return spi_register_driver(&lb035q02_spi_driver);
270}
271
272static void __exit lb035q02_panel_drv_exit(void)
273{
274 spi_unregister_driver(&lb035q02_spi_driver);
275}
276
277module_init(lb035q02_panel_drv_init);
278module_exit(lb035q02_panel_drv_exit);
279MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
new file mode 100644
index 000000000000..2ba9d0ca187c
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
@@ -0,0 +1,325 @@
1/*
2 * Support for NEC-nl8048hl11-01b panel driver
3 *
4 * Copyright (C) 2010 Texas Instruments Inc.
5 * Author: Erik Gilling <konkers@android.com>
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 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/module.h>
20#include <linux/delay.h>
21#include <linux/spi/spi.h>
22#include <linux/backlight.h>
23#include <linux/fb.h>
24
25#include <video/omapdss.h>
26
27#define LCD_XRES 800
28#define LCD_YRES 480
29/*
30 * NEC PIX Clock Ratings
31 * MIN:21.8MHz TYP:23.8MHz MAX:25.7MHz
32 */
33#define LCD_PIXEL_CLOCK 23800
34
35struct nec_8048_data {
36 struct backlight_device *bl;
37};
38
39static const struct {
40 unsigned char addr;
41 unsigned char dat;
42} nec_8048_init_seq[] = {
43 { 3, 0x01 }, { 0, 0x00 }, { 1, 0x01 }, { 4, 0x00 }, { 5, 0x14 },
44 { 6, 0x24 }, { 16, 0xD7 }, { 17, 0x00 }, { 18, 0x00 }, { 19, 0x55 },
45 { 20, 0x01 }, { 21, 0x70 }, { 22, 0x1E }, { 23, 0x25 }, { 24, 0x25 },
46 { 25, 0x02 }, { 26, 0x02 }, { 27, 0xA0 }, { 32, 0x2F }, { 33, 0x0F },
47 { 34, 0x0F }, { 35, 0x0F }, { 36, 0x0F }, { 37, 0x0F }, { 38, 0x0F },
48 { 39, 0x00 }, { 40, 0x02 }, { 41, 0x02 }, { 42, 0x02 }, { 43, 0x0F },
49 { 44, 0x0F }, { 45, 0x0F }, { 46, 0x0F }, { 47, 0x0F }, { 48, 0x0F },
50 { 49, 0x0F }, { 50, 0x00 }, { 51, 0x02 }, { 52, 0x02 }, { 53, 0x02 },
51 { 80, 0x0C }, { 83, 0x42 }, { 84, 0x42 }, { 85, 0x41 }, { 86, 0x14 },
52 { 89, 0x88 }, { 90, 0x01 }, { 91, 0x00 }, { 92, 0x02 }, { 93, 0x0C },
53 { 94, 0x1C }, { 95, 0x27 }, { 98, 0x49 }, { 99, 0x27 }, { 102, 0x76 },
54 { 103, 0x27 }, { 112, 0x01 }, { 113, 0x0E }, { 114, 0x02 },
55 { 115, 0x0C }, { 118, 0x0C }, { 121, 0x30 }, { 130, 0x00 },
56 { 131, 0x00 }, { 132, 0xFC }, { 134, 0x00 }, { 136, 0x00 },
57 { 138, 0x00 }, { 139, 0x00 }, { 140, 0x00 }, { 141, 0xFC },
58 { 143, 0x00 }, { 145, 0x00 }, { 147, 0x00 }, { 148, 0x00 },
59 { 149, 0x00 }, { 150, 0xFC }, { 152, 0x00 }, { 154, 0x00 },
60 { 156, 0x00 }, { 157, 0x00 }, { 2, 0x00 },
61};
62
63/*
64 * NEC NL8048HL11-01B Manual
65 * defines HFB, HSW, HBP, VFP, VSW, VBP as shown below
66 */
67
68static struct omap_video_timings nec_8048_panel_timings = {
69 /* 800 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */
70 .x_res = LCD_XRES,
71 .y_res = LCD_YRES,
72 .pixel_clock = LCD_PIXEL_CLOCK,
73 .hfp = 6,
74 .hsw = 1,
75 .hbp = 4,
76 .vfp = 3,
77 .vsw = 1,
78 .vbp = 4,
79};
80
81static int nec_8048_bl_update_status(struct backlight_device *bl)
82{
83 struct omap_dss_device *dssdev = dev_get_drvdata(&bl->dev);
84 int level;
85
86 if (!dssdev->set_backlight)
87 return -EINVAL;
88
89 if (bl->props.fb_blank == FB_BLANK_UNBLANK &&
90 bl->props.power == FB_BLANK_UNBLANK)
91 level = bl->props.brightness;
92 else
93 level = 0;
94
95 return dssdev->set_backlight(dssdev, level);
96}
97
98static int nec_8048_bl_get_brightness(struct backlight_device *bl)
99{
100 if (bl->props.fb_blank == FB_BLANK_UNBLANK &&
101 bl->props.power == FB_BLANK_UNBLANK)
102 return bl->props.brightness;
103
104 return 0;
105}
106
107static const struct backlight_ops nec_8048_bl_ops = {
108 .get_brightness = nec_8048_bl_get_brightness,
109 .update_status = nec_8048_bl_update_status,
110};
111
112static int nec_8048_panel_probe(struct omap_dss_device *dssdev)
113{
114 struct backlight_device *bl;
115 struct nec_8048_data *necd;
116 struct backlight_properties props;
117 int r;
118
119 dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
120 OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_RF |
121 OMAP_DSS_LCD_ONOFF;
122 dssdev->panel.timings = nec_8048_panel_timings;
123
124 necd = kzalloc(sizeof(*necd), GFP_KERNEL);
125 if (!necd)
126 return -ENOMEM;
127
128 dev_set_drvdata(&dssdev->dev, necd);
129
130 memset(&props, 0, sizeof(struct backlight_properties));
131 props.max_brightness = 255;
132
133 bl = backlight_device_register("nec-8048", &dssdev->dev, dssdev,
134 &nec_8048_bl_ops, &props);
135 if (IS_ERR(bl)) {
136 r = PTR_ERR(bl);
137 kfree(necd);
138 return r;
139 }
140 necd->bl = bl;
141
142 bl->props.fb_blank = FB_BLANK_UNBLANK;
143 bl->props.power = FB_BLANK_UNBLANK;
144 bl->props.max_brightness = dssdev->max_backlight_level;
145 bl->props.brightness = dssdev->max_backlight_level;
146
147 r = nec_8048_bl_update_status(bl);
148 if (r < 0)
149 dev_err(&dssdev->dev, "failed to set lcd brightness\n");
150
151 return 0;
152}
153
154static void nec_8048_panel_remove(struct omap_dss_device *dssdev)
155{
156 struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev);
157 struct backlight_device *bl = necd->bl;
158
159 bl->props.power = FB_BLANK_POWERDOWN;
160 nec_8048_bl_update_status(bl);
161 backlight_device_unregister(bl);
162
163 kfree(necd);
164}
165
166static int nec_8048_panel_enable(struct omap_dss_device *dssdev)
167{
168 int r = 0;
169 struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev);
170 struct backlight_device *bl = necd->bl;
171
172 if (dssdev->platform_enable) {
173 r = dssdev->platform_enable(dssdev);
174 if (r)
175 return r;
176 }
177
178 r = nec_8048_bl_update_status(bl);
179 if (r < 0)
180 dev_err(&dssdev->dev, "failed to set lcd brightness\n");
181
182 r = omapdss_dpi_display_enable(dssdev);
183
184 return r;
185}
186
187static void nec_8048_panel_disable(struct omap_dss_device *dssdev)
188{
189 struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev);
190 struct backlight_device *bl = necd->bl;
191
192 omapdss_dpi_display_disable(dssdev);
193
194 bl->props.brightness = 0;
195 nec_8048_bl_update_status(bl);
196
197 if (dssdev->platform_disable)
198 dssdev->platform_disable(dssdev);
199}
200
201static int nec_8048_panel_suspend(struct omap_dss_device *dssdev)
202{
203 nec_8048_panel_disable(dssdev);
204 return 0;
205}
206
207static int nec_8048_panel_resume(struct omap_dss_device *dssdev)
208{
209 return nec_8048_panel_enable(dssdev);
210}
211
212static int nec_8048_recommended_bpp(struct omap_dss_device *dssdev)
213{
214 return 16;
215}
216
217static struct omap_dss_driver nec_8048_driver = {
218 .probe = nec_8048_panel_probe,
219 .remove = nec_8048_panel_remove,
220 .enable = nec_8048_panel_enable,
221 .disable = nec_8048_panel_disable,
222 .suspend = nec_8048_panel_suspend,
223 .resume = nec_8048_panel_resume,
224 .get_recommended_bpp = nec_8048_recommended_bpp,
225
226 .driver = {
227 .name = "NEC_8048_panel",
228 .owner = THIS_MODULE,
229 },
230};
231
232static int nec_8048_spi_send(struct spi_device *spi, unsigned char reg_addr,
233 unsigned char reg_data)
234{
235 int ret = 0;
236 unsigned int cmd = 0, data = 0;
237
238 cmd = 0x0000 | reg_addr; /* register address write */
239 data = 0x0100 | reg_data ; /* register data write */
240 data = (cmd << 16) | data;
241
242 ret = spi_write(spi, (unsigned char *)&data, 4);
243 if (ret)
244 pr_err("error in spi_write %x\n", data);
245
246 return ret;
247}
248
249static int init_nec_8048_wvga_lcd(struct spi_device *spi)
250{
251 unsigned int i;
252 /* Initialization Sequence */
253 /* nec_8048_spi_send(spi, REG, VAL) */
254 for (i = 0; i < (ARRAY_SIZE(nec_8048_init_seq) - 1); i++)
255 nec_8048_spi_send(spi, nec_8048_init_seq[i].addr,
256 nec_8048_init_seq[i].dat);
257 udelay(20);
258 nec_8048_spi_send(spi, nec_8048_init_seq[i].addr,
259 nec_8048_init_seq[i].dat);
260 return 0;
261}
262
263static int nec_8048_spi_probe(struct spi_device *spi)
264{
265 spi->mode = SPI_MODE_0;
266 spi->bits_per_word = 32;
267 spi_setup(spi);
268
269 init_nec_8048_wvga_lcd(spi);
270
271 return omap_dss_register_driver(&nec_8048_driver);
272}
273
274static int nec_8048_spi_remove(struct spi_device *spi)
275{
276 omap_dss_unregister_driver(&nec_8048_driver);
277
278 return 0;
279}
280
281static int nec_8048_spi_suspend(struct spi_device *spi, pm_message_t mesg)
282{
283 nec_8048_spi_send(spi, 2, 0x01);
284 mdelay(40);
285
286 return 0;
287}
288
289static int nec_8048_spi_resume(struct spi_device *spi)
290{
291 /* reinitialize the panel */
292 spi_setup(spi);
293 nec_8048_spi_send(spi, 2, 0x00);
294 init_nec_8048_wvga_lcd(spi);
295
296 return 0;
297}
298
299static struct spi_driver nec_8048_spi_driver = {
300 .probe = nec_8048_spi_probe,
301 .remove = __devexit_p(nec_8048_spi_remove),
302 .suspend = nec_8048_spi_suspend,
303 .resume = nec_8048_spi_resume,
304 .driver = {
305 .name = "nec_8048_spi",
306 .bus = &spi_bus_type,
307 .owner = THIS_MODULE,
308 },
309};
310
311static int __init nec_8048_lcd_init(void)
312{
313 return spi_register_driver(&nec_8048_spi_driver);
314}
315
316static void __exit nec_8048_lcd_exit(void)
317{
318 return spi_unregister_driver(&nec_8048_spi_driver);
319}
320
321module_init(nec_8048_lcd_init);
322module_exit(nec_8048_lcd_exit);
323MODULE_AUTHOR("Erik Gilling <konkers@android.com>");
324MODULE_DESCRIPTION("NEC-nl8048hl11-01b Driver");
325MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-sharp-lq043t1dg01.c b/drivers/video/omap2/displays/panel-sharp-lq043t1dg01.c
deleted file mode 100644
index 10267461991c..000000000000
--- a/drivers/video/omap2/displays/panel-sharp-lq043t1dg01.c
+++ /dev/null
@@ -1,159 +0,0 @@
1/*
2 * LCD panel driver for Sharp LQ043T1DG01
3 *
4 * Copyright (C) 2009 Texas Instruments Inc
5 * Author: Vaibhav Hiremath <hvaibhav@ti.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <linux/module.h>
21#include <linux/delay.h>
22#include <linux/device.h>
23#include <linux/err.h>
24
25#include <plat/display.h>
26
27static struct omap_video_timings sharp_lq_timings = {
28 .x_res = 480,
29 .y_res = 272,
30
31 .pixel_clock = 9000,
32
33 .hsw = 42,
34 .hfp = 3,
35 .hbp = 2,
36
37 .vsw = 11,
38 .vfp = 3,
39 .vbp = 2,
40};
41
42static int sharp_lq_panel_power_on(struct omap_dss_device *dssdev)
43{
44 int r;
45
46 r = omapdss_dpi_display_enable(dssdev);
47 if (r)
48 goto err0;
49
50 /* wait couple of vsyncs until enabling the LCD */
51 msleep(50);
52
53 if (dssdev->platform_enable) {
54 r = dssdev->platform_enable(dssdev);
55 if (r)
56 goto err1;
57 }
58
59 return 0;
60err1:
61 omapdss_dpi_display_disable(dssdev);
62err0:
63 return r;
64}
65
66static void sharp_lq_panel_power_off(struct omap_dss_device *dssdev)
67{
68 if (dssdev->platform_disable)
69 dssdev->platform_disable(dssdev);
70
71 /* wait at least 5 vsyncs after disabling the LCD */
72 msleep(100);
73
74 omapdss_dpi_display_disable(dssdev);
75}
76
77static int sharp_lq_panel_probe(struct omap_dss_device *dssdev)
78{
79
80 dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
81 OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IEO;
82 dssdev->panel.acb = 0x0;
83 dssdev->panel.timings = sharp_lq_timings;
84
85 return 0;
86}
87
88static void sharp_lq_panel_remove(struct omap_dss_device *dssdev)
89{
90}
91
92static int sharp_lq_panel_enable(struct omap_dss_device *dssdev)
93{
94 int r = 0;
95
96 r = sharp_lq_panel_power_on(dssdev);
97 if (r)
98 return r;
99
100 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
101
102 return 0;
103}
104
105static void sharp_lq_panel_disable(struct omap_dss_device *dssdev)
106{
107 sharp_lq_panel_power_off(dssdev);
108
109 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
110}
111
112static int sharp_lq_panel_suspend(struct omap_dss_device *dssdev)
113{
114 sharp_lq_panel_power_off(dssdev);
115 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
116 return 0;
117}
118
119static int sharp_lq_panel_resume(struct omap_dss_device *dssdev)
120{
121 int r = 0;
122
123 r = sharp_lq_panel_power_on(dssdev);
124 if (r)
125 return r;
126
127 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
128
129 return 0;
130}
131
132static struct omap_dss_driver sharp_lq_driver = {
133 .probe = sharp_lq_panel_probe,
134 .remove = sharp_lq_panel_remove,
135
136 .enable = sharp_lq_panel_enable,
137 .disable = sharp_lq_panel_disable,
138 .suspend = sharp_lq_panel_suspend,
139 .resume = sharp_lq_panel_resume,
140
141 .driver = {
142 .name = "sharp_lq_panel",
143 .owner = THIS_MODULE,
144 },
145};
146
147static int __init sharp_lq_panel_drv_init(void)
148{
149 return omap_dss_register_driver(&sharp_lq_driver);
150}
151
152static void __exit sharp_lq_panel_drv_exit(void)
153{
154 omap_dss_unregister_driver(&sharp_lq_driver);
155}
156
157module_init(sharp_lq_panel_drv_init);
158module_exit(sharp_lq_panel_drv_exit);
159MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
index 7d9eb2b1f5af..ba38b3ad17d6 100644
--- a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
@@ -25,7 +25,7 @@
25#include <linux/err.h> 25#include <linux/err.h>
26#include <linux/slab.h> 26#include <linux/slab.h>
27 27
28#include <plat/display.h> 28#include <video/omapdss.h>
29 29
30struct sharp_data { 30struct sharp_data {
31 struct backlight_device *bl; 31 struct backlight_device *bl;
@@ -99,6 +99,7 @@ static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
99 99
100 memset(&props, 0, sizeof(struct backlight_properties)); 100 memset(&props, 0, sizeof(struct backlight_properties));
101 props.max_brightness = dssdev->max_backlight_level; 101 props.max_brightness = dssdev->max_backlight_level;
102 props.type = BACKLIGHT_RAW;
102 103
103 bl = backlight_device_register("sharp-ls", &dssdev->dev, dssdev, 104 bl = backlight_device_register("sharp-ls", &dssdev->dev, dssdev,
104 &sharp_ls_bl_ops, &props); 105 &sharp_ls_bl_ops, &props);
@@ -119,7 +120,7 @@ static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
119 return 0; 120 return 0;
120} 121}
121 122
122static void sharp_ls_panel_remove(struct omap_dss_device *dssdev) 123static void __exit sharp_ls_panel_remove(struct omap_dss_device *dssdev)
123{ 124{
124 struct sharp_data *sd = dev_get_drvdata(&dssdev->dev); 125 struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
125 struct backlight_device *bl = sd->bl; 126 struct backlight_device *bl = sd->bl;
@@ -135,6 +136,9 @@ static int sharp_ls_power_on(struct omap_dss_device *dssdev)
135{ 136{
136 int r = 0; 137 int r = 0;
137 138
139 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
140 return 0;
141
138 r = omapdss_dpi_display_enable(dssdev); 142 r = omapdss_dpi_display_enable(dssdev);
139 if (r) 143 if (r)
140 goto err0; 144 goto err0;
@@ -157,6 +161,9 @@ err0:
157 161
158static void sharp_ls_power_off(struct omap_dss_device *dssdev) 162static void sharp_ls_power_off(struct omap_dss_device *dssdev)
159{ 163{
164 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
165 return;
166
160 if (dssdev->platform_disable) 167 if (dssdev->platform_disable)
161 dssdev->platform_disable(dssdev); 168 dssdev->platform_disable(dssdev);
162 169
@@ -198,7 +205,7 @@ static int sharp_ls_panel_resume(struct omap_dss_device *dssdev)
198 205
199static struct omap_dss_driver sharp_ls_driver = { 206static struct omap_dss_driver sharp_ls_driver = {
200 .probe = sharp_ls_panel_probe, 207 .probe = sharp_ls_panel_probe,
201 .remove = sharp_ls_panel_remove, 208 .remove = __exit_p(sharp_ls_panel_remove),
202 209
203 .enable = sharp_ls_panel_enable, 210 .enable = sharp_ls_panel_enable,
204 .disable = sharp_ls_panel_disable, 211 .disable = sharp_ls_panel_disable,
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index e1c765d11419..fdd5d4ae437d 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -33,8 +33,8 @@
33#include <linux/regulator/consumer.h> 33#include <linux/regulator/consumer.h>
34#include <linux/mutex.h> 34#include <linux/mutex.h>
35 35
36#include <plat/display.h> 36#include <video/omapdss.h>
37#include <plat/nokia-dsi-panel.h> 37#include <video/omap-panel-nokia-dsi.h>
38 38
39/* DSI Virtual channel. Hardcoded for now. */ 39/* DSI Virtual channel. Hardcoded for now. */
40#define TCH 0 40#define TCH 0
@@ -63,12 +63,12 @@
63#define DCS_GET_ID2 0xdb 63#define DCS_GET_ID2 0xdb
64#define DCS_GET_ID3 0xdc 64#define DCS_GET_ID3 0xdc
65 65
66#define TAAL_ESD_CHECK_PERIOD msecs_to_jiffies(5000)
67
68static irqreturn_t taal_te_isr(int irq, void *data); 66static irqreturn_t taal_te_isr(int irq, void *data);
69static void taal_te_timeout_work_callback(struct work_struct *work); 67static void taal_te_timeout_work_callback(struct work_struct *work);
70static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable); 68static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable);
71 69
70static int taal_panel_reset(struct omap_dss_device *dssdev);
71
72struct panel_regulator { 72struct panel_regulator {
73 struct regulator *regulator; 73 struct regulator *regulator;
74 const char *name; 74 const char *name;
@@ -218,6 +218,8 @@ struct taal_data {
218 u16 w; 218 u16 w;
219 u16 h; 219 u16 h;
220 } update_region; 220 } update_region;
221 int channel;
222
221 struct delayed_work te_timeout_work; 223 struct delayed_work te_timeout_work;
222 224
223 bool use_dsi_bl; 225 bool use_dsi_bl;
@@ -227,8 +229,14 @@ struct taal_data {
227 229
228 bool intro_printed; 230 bool intro_printed;
229 231
230 struct workqueue_struct *esd_wq; 232 struct workqueue_struct *workqueue;
233
231 struct delayed_work esd_work; 234 struct delayed_work esd_work;
235 unsigned esd_interval;
236
237 bool ulps_enabled;
238 unsigned ulps_timeout;
239 struct delayed_work ulps_work;
232 240
233 struct panel_config *panel_config; 241 struct panel_config *panel_config;
234}; 242};
@@ -240,6 +248,7 @@ static inline struct nokia_dsi_panel_data
240} 248}
241 249
242static void taal_esd_work(struct work_struct *work); 250static void taal_esd_work(struct work_struct *work);
251static void taal_ulps_work(struct work_struct *work);
243 252
244static void hw_guard_start(struct taal_data *td, int guard_msec) 253static void hw_guard_start(struct taal_data *td, int guard_msec)
245{ 254{
@@ -257,12 +266,12 @@ static void hw_guard_wait(struct taal_data *td)
257 } 266 }
258} 267}
259 268
260static int taal_dcs_read_1(u8 dcs_cmd, u8 *data) 269static int taal_dcs_read_1(struct taal_data *td, u8 dcs_cmd, u8 *data)
261{ 270{
262 int r; 271 int r;
263 u8 buf[1]; 272 u8 buf[1];
264 273
265 r = dsi_vc_dcs_read(TCH, dcs_cmd, buf, 1); 274 r = dsi_vc_dcs_read(td->dssdev, td->channel, dcs_cmd, buf, 1);
266 275
267 if (r < 0) 276 if (r < 0)
268 return r; 277 return r;
@@ -272,17 +281,17 @@ static int taal_dcs_read_1(u8 dcs_cmd, u8 *data)
272 return 0; 281 return 0;
273} 282}
274 283
275static int taal_dcs_write_0(u8 dcs_cmd) 284static int taal_dcs_write_0(struct taal_data *td, u8 dcs_cmd)
276{ 285{
277 return dsi_vc_dcs_write(TCH, &dcs_cmd, 1); 286 return dsi_vc_dcs_write(td->dssdev, td->channel, &dcs_cmd, 1);
278} 287}
279 288
280static int taal_dcs_write_1(u8 dcs_cmd, u8 param) 289static int taal_dcs_write_1(struct taal_data *td, u8 dcs_cmd, u8 param)
281{ 290{
282 u8 buf[2]; 291 u8 buf[2];
283 buf[0] = dcs_cmd; 292 buf[0] = dcs_cmd;
284 buf[1] = param; 293 buf[1] = param;
285 return dsi_vc_dcs_write(TCH, buf, 2); 294 return dsi_vc_dcs_write(td->dssdev, td->channel, buf, 2);
286} 295}
287 296
288static int taal_sleep_in(struct taal_data *td) 297static int taal_sleep_in(struct taal_data *td)
@@ -294,7 +303,7 @@ static int taal_sleep_in(struct taal_data *td)
294 hw_guard_wait(td); 303 hw_guard_wait(td);
295 304
296 cmd = DCS_SLEEP_IN; 305 cmd = DCS_SLEEP_IN;
297 r = dsi_vc_dcs_write_nosync(TCH, &cmd, 1); 306 r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, &cmd, 1);
298 if (r) 307 if (r)
299 return r; 308 return r;
300 309
@@ -312,7 +321,7 @@ static int taal_sleep_out(struct taal_data *td)
312 321
313 hw_guard_wait(td); 322 hw_guard_wait(td);
314 323
315 r = taal_dcs_write_0(DCS_SLEEP_OUT); 324 r = taal_dcs_write_0(td, DCS_SLEEP_OUT);
316 if (r) 325 if (r)
317 return r; 326 return r;
318 327
@@ -324,30 +333,30 @@ static int taal_sleep_out(struct taal_data *td)
324 return 0; 333 return 0;
325} 334}
326 335
327static int taal_get_id(u8 *id1, u8 *id2, u8 *id3) 336static int taal_get_id(struct taal_data *td, u8 *id1, u8 *id2, u8 *id3)
328{ 337{
329 int r; 338 int r;
330 339
331 r = taal_dcs_read_1(DCS_GET_ID1, id1); 340 r = taal_dcs_read_1(td, DCS_GET_ID1, id1);
332 if (r) 341 if (r)
333 return r; 342 return r;
334 r = taal_dcs_read_1(DCS_GET_ID2, id2); 343 r = taal_dcs_read_1(td, DCS_GET_ID2, id2);
335 if (r) 344 if (r)
336 return r; 345 return r;
337 r = taal_dcs_read_1(DCS_GET_ID3, id3); 346 r = taal_dcs_read_1(td, DCS_GET_ID3, id3);
338 if (r) 347 if (r)
339 return r; 348 return r;
340 349
341 return 0; 350 return 0;
342} 351}
343 352
344static int taal_set_addr_mode(u8 rotate, bool mirror) 353static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror)
345{ 354{
346 int r; 355 int r;
347 u8 mode; 356 u8 mode;
348 int b5, b6, b7; 357 int b5, b6, b7;
349 358
350 r = taal_dcs_read_1(DCS_READ_MADCTL, &mode); 359 r = taal_dcs_read_1(td, DCS_READ_MADCTL, &mode);
351 if (r) 360 if (r)
352 return r; 361 return r;
353 362
@@ -381,10 +390,11 @@ static int taal_set_addr_mode(u8 rotate, bool mirror)
381 mode &= ~((1<<7) | (1<<6) | (1<<5)); 390 mode &= ~((1<<7) | (1<<6) | (1<<5));
382 mode |= (b7 << 7) | (b6 << 6) | (b5 << 5); 391 mode |= (b7 << 7) | (b6 << 6) | (b5 << 5);
383 392
384 return taal_dcs_write_1(DCS_MEM_ACC_CTRL, mode); 393 return taal_dcs_write_1(td, DCS_MEM_ACC_CTRL, mode);
385} 394}
386 395
387static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h) 396static int taal_set_update_window(struct taal_data *td,
397 u16 x, u16 y, u16 w, u16 h)
388{ 398{
389 int r; 399 int r;
390 u16 x1 = x; 400 u16 x1 = x;
@@ -399,7 +409,7 @@ static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h)
399 buf[3] = (x2 >> 8) & 0xff; 409 buf[3] = (x2 >> 8) & 0xff;
400 buf[4] = (x2 >> 0) & 0xff; 410 buf[4] = (x2 >> 0) & 0xff;
401 411
402 r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf)); 412 r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, buf, sizeof(buf));
403 if (r) 413 if (r)
404 return r; 414 return r;
405 415
@@ -409,15 +419,132 @@ static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h)
409 buf[3] = (y2 >> 8) & 0xff; 419 buf[3] = (y2 >> 8) & 0xff;
410 buf[4] = (y2 >> 0) & 0xff; 420 buf[4] = (y2 >> 0) & 0xff;
411 421
412 r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf)); 422 r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, buf, sizeof(buf));
413 if (r) 423 if (r)
414 return r; 424 return r;
415 425
416 dsi_vc_send_bta_sync(TCH); 426 dsi_vc_send_bta_sync(td->dssdev, td->channel);
427
428 return r;
429}
430
431static void taal_queue_esd_work(struct omap_dss_device *dssdev)
432{
433 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
434
435 if (td->esd_interval > 0)
436 queue_delayed_work(td->workqueue, &td->esd_work,
437 msecs_to_jiffies(td->esd_interval));
438}
439
440static void taal_cancel_esd_work(struct omap_dss_device *dssdev)
441{
442 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
443
444 cancel_delayed_work(&td->esd_work);
445}
446
447static void taal_queue_ulps_work(struct omap_dss_device *dssdev)
448{
449 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
450
451 if (td->ulps_timeout > 0)
452 queue_delayed_work(td->workqueue, &td->ulps_work,
453 msecs_to_jiffies(td->ulps_timeout));
454}
455
456static void taal_cancel_ulps_work(struct omap_dss_device *dssdev)
457{
458 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
459
460 cancel_delayed_work(&td->ulps_work);
461}
462
463static int taal_enter_ulps(struct omap_dss_device *dssdev)
464{
465 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
466 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
467 int r;
468
469 if (td->ulps_enabled)
470 return 0;
471
472 taal_cancel_ulps_work(dssdev);
473
474 r = _taal_enable_te(dssdev, false);
475 if (r)
476 goto err;
477
478 disable_irq(gpio_to_irq(panel_data->ext_te_gpio));
479
480 omapdss_dsi_display_disable(dssdev, false, true);
481
482 td->ulps_enabled = true;
483
484 return 0;
485
486err:
487 dev_err(&dssdev->dev, "enter ULPS failed");
488 taal_panel_reset(dssdev);
489
490 td->ulps_enabled = false;
491
492 taal_queue_ulps_work(dssdev);
493
494 return r;
495}
496
497static int taal_exit_ulps(struct omap_dss_device *dssdev)
498{
499 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
500 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
501 int r;
502
503 if (!td->ulps_enabled)
504 return 0;
505
506 r = omapdss_dsi_display_enable(dssdev);
507 if (r)
508 goto err;
509
510 omapdss_dsi_vc_enable_hs(dssdev, td->channel, true);
511
512 r = _taal_enable_te(dssdev, true);
513 if (r)
514 goto err;
515
516 enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
517
518 taal_queue_ulps_work(dssdev);
519
520 td->ulps_enabled = false;
521
522 return 0;
523
524err:
525 dev_err(&dssdev->dev, "exit ULPS failed");
526 r = taal_panel_reset(dssdev);
527
528 enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
529 td->ulps_enabled = false;
530
531 taal_queue_ulps_work(dssdev);
417 532
418 return r; 533 return r;
419} 534}
420 535
536static int taal_wake_up(struct omap_dss_device *dssdev)
537{
538 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
539
540 if (td->ulps_enabled)
541 return taal_exit_ulps(dssdev);
542
543 taal_cancel_ulps_work(dssdev);
544 taal_queue_ulps_work(dssdev);
545 return 0;
546}
547
421static int taal_bl_update_status(struct backlight_device *dev) 548static int taal_bl_update_status(struct backlight_device *dev)
422{ 549{
423 struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); 550 struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
@@ -438,9 +565,13 @@ static int taal_bl_update_status(struct backlight_device *dev)
438 565
439 if (td->use_dsi_bl) { 566 if (td->use_dsi_bl) {
440 if (td->enabled) { 567 if (td->enabled) {
441 dsi_bus_lock(); 568 dsi_bus_lock(dssdev);
442 r = taal_dcs_write_1(DCS_BRIGHTNESS, level); 569
443 dsi_bus_unlock(); 570 r = taal_wake_up(dssdev);
571 if (!r)
572 r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level);
573
574 dsi_bus_unlock(dssdev);
444 } else { 575 } else {
445 r = 0; 576 r = 0;
446 } 577 }
@@ -465,7 +596,7 @@ static int taal_bl_get_intensity(struct backlight_device *dev)
465 return 0; 596 return 0;
466} 597}
467 598
468static struct backlight_ops taal_bl_ops = { 599static const struct backlight_ops taal_bl_ops = {
469 .get_brightness = taal_bl_get_intensity, 600 .get_brightness = taal_bl_get_intensity,
470 .update_status = taal_bl_update_status, 601 .update_status = taal_bl_update_status,
471}; 602};
@@ -501,9 +632,13 @@ static ssize_t taal_num_errors_show(struct device *dev,
501 mutex_lock(&td->lock); 632 mutex_lock(&td->lock);
502 633
503 if (td->enabled) { 634 if (td->enabled) {
504 dsi_bus_lock(); 635 dsi_bus_lock(dssdev);
505 r = taal_dcs_read_1(DCS_READ_NUM_ERRORS, &errors); 636
506 dsi_bus_unlock(); 637 r = taal_wake_up(dssdev);
638 if (!r)
639 r = taal_dcs_read_1(td, DCS_READ_NUM_ERRORS, &errors);
640
641 dsi_bus_unlock(dssdev);
507 } else { 642 } else {
508 r = -ENODEV; 643 r = -ENODEV;
509 } 644 }
@@ -527,9 +662,13 @@ static ssize_t taal_hw_revision_show(struct device *dev,
527 mutex_lock(&td->lock); 662 mutex_lock(&td->lock);
528 663
529 if (td->enabled) { 664 if (td->enabled) {
530 dsi_bus_lock(); 665 dsi_bus_lock(dssdev);
531 r = taal_get_id(&id1, &id2, &id3); 666
532 dsi_bus_unlock(); 667 r = taal_wake_up(dssdev);
668 if (!r)
669 r = taal_get_id(td, &id1, &id2, &id3);
670
671 dsi_bus_unlock(dssdev);
533 } else { 672 } else {
534 r = -ENODEV; 673 r = -ENODEV;
535 } 674 }
@@ -576,6 +715,7 @@ static ssize_t store_cabc_mode(struct device *dev,
576 struct omap_dss_device *dssdev = to_dss_device(dev); 715 struct omap_dss_device *dssdev = to_dss_device(dev);
577 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 716 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
578 int i; 717 int i;
718 int r;
579 719
580 for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) { 720 for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) {
581 if (sysfs_streq(cabc_modes[i], buf)) 721 if (sysfs_streq(cabc_modes[i], buf))
@@ -588,10 +728,19 @@ static ssize_t store_cabc_mode(struct device *dev,
588 mutex_lock(&td->lock); 728 mutex_lock(&td->lock);
589 729
590 if (td->enabled) { 730 if (td->enabled) {
591 dsi_bus_lock(); 731 dsi_bus_lock(dssdev);
592 if (!td->cabc_broken) 732
593 taal_dcs_write_1(DCS_WRITE_CABC, i); 733 if (!td->cabc_broken) {
594 dsi_bus_unlock(); 734 r = taal_wake_up(dssdev);
735 if (r)
736 goto err;
737
738 r = taal_dcs_write_1(td, DCS_WRITE_CABC, i);
739 if (r)
740 goto err;
741 }
742
743 dsi_bus_unlock(dssdev);
595 } 744 }
596 745
597 td->cabc_mode = i; 746 td->cabc_mode = i;
@@ -599,6 +748,10 @@ static ssize_t store_cabc_mode(struct device *dev,
599 mutex_unlock(&td->lock); 748 mutex_unlock(&td->lock);
600 749
601 return count; 750 return count;
751err:
752 dsi_bus_unlock(dssdev);
753 mutex_unlock(&td->lock);
754 return r;
602} 755}
603 756
604static ssize_t show_cabc_available_modes(struct device *dev, 757static ssize_t show_cabc_available_modes(struct device *dev,
@@ -617,18 +770,161 @@ static ssize_t show_cabc_available_modes(struct device *dev,
617 return len < PAGE_SIZE ? len : PAGE_SIZE - 1; 770 return len < PAGE_SIZE ? len : PAGE_SIZE - 1;
618} 771}
619 772
773static ssize_t taal_store_esd_interval(struct device *dev,
774 struct device_attribute *attr,
775 const char *buf, size_t count)
776{
777 struct omap_dss_device *dssdev = to_dss_device(dev);
778 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
779
780 unsigned long t;
781 int r;
782
783 r = strict_strtoul(buf, 10, &t);
784 if (r)
785 return r;
786
787 mutex_lock(&td->lock);
788 taal_cancel_esd_work(dssdev);
789 td->esd_interval = t;
790 if (td->enabled)
791 taal_queue_esd_work(dssdev);
792 mutex_unlock(&td->lock);
793
794 return count;
795}
796
797static ssize_t taal_show_esd_interval(struct device *dev,
798 struct device_attribute *attr,
799 char *buf)
800{
801 struct omap_dss_device *dssdev = to_dss_device(dev);
802 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
803 unsigned t;
804
805 mutex_lock(&td->lock);
806 t = td->esd_interval;
807 mutex_unlock(&td->lock);
808
809 return snprintf(buf, PAGE_SIZE, "%u\n", t);
810}
811
812static ssize_t taal_store_ulps(struct device *dev,
813 struct device_attribute *attr,
814 const char *buf, size_t count)
815{
816 struct omap_dss_device *dssdev = to_dss_device(dev);
817 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
818 unsigned long t;
819 int r;
820
821 r = strict_strtoul(buf, 10, &t);
822 if (r)
823 return r;
824
825 mutex_lock(&td->lock);
826
827 if (td->enabled) {
828 dsi_bus_lock(dssdev);
829
830 if (t)
831 r = taal_enter_ulps(dssdev);
832 else
833 r = taal_wake_up(dssdev);
834
835 dsi_bus_unlock(dssdev);
836 }
837
838 mutex_unlock(&td->lock);
839
840 if (r)
841 return r;
842
843 return count;
844}
845
846static ssize_t taal_show_ulps(struct device *dev,
847 struct device_attribute *attr,
848 char *buf)
849{
850 struct omap_dss_device *dssdev = to_dss_device(dev);
851 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
852 unsigned t;
853
854 mutex_lock(&td->lock);
855 t = td->ulps_enabled;
856 mutex_unlock(&td->lock);
857
858 return snprintf(buf, PAGE_SIZE, "%u\n", t);
859}
860
861static ssize_t taal_store_ulps_timeout(struct device *dev,
862 struct device_attribute *attr,
863 const char *buf, size_t count)
864{
865 struct omap_dss_device *dssdev = to_dss_device(dev);
866 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
867 unsigned long t;
868 int r;
869
870 r = strict_strtoul(buf, 10, &t);
871 if (r)
872 return r;
873
874 mutex_lock(&td->lock);
875 td->ulps_timeout = t;
876
877 if (td->enabled) {
878 /* taal_wake_up will restart the timer */
879 dsi_bus_lock(dssdev);
880 r = taal_wake_up(dssdev);
881 dsi_bus_unlock(dssdev);
882 }
883
884 mutex_unlock(&td->lock);
885
886 if (r)
887 return r;
888
889 return count;
890}
891
892static ssize_t taal_show_ulps_timeout(struct device *dev,
893 struct device_attribute *attr,
894 char *buf)
895{
896 struct omap_dss_device *dssdev = to_dss_device(dev);
897 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
898 unsigned t;
899
900 mutex_lock(&td->lock);
901 t = td->ulps_timeout;
902 mutex_unlock(&td->lock);
903
904 return snprintf(buf, PAGE_SIZE, "%u\n", t);
905}
906
620static DEVICE_ATTR(num_dsi_errors, S_IRUGO, taal_num_errors_show, NULL); 907static DEVICE_ATTR(num_dsi_errors, S_IRUGO, taal_num_errors_show, NULL);
621static DEVICE_ATTR(hw_revision, S_IRUGO, taal_hw_revision_show, NULL); 908static DEVICE_ATTR(hw_revision, S_IRUGO, taal_hw_revision_show, NULL);
622static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR, 909static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR,
623 show_cabc_mode, store_cabc_mode); 910 show_cabc_mode, store_cabc_mode);
624static DEVICE_ATTR(cabc_available_modes, S_IRUGO, 911static DEVICE_ATTR(cabc_available_modes, S_IRUGO,
625 show_cabc_available_modes, NULL); 912 show_cabc_available_modes, NULL);
913static DEVICE_ATTR(esd_interval, S_IRUGO | S_IWUSR,
914 taal_show_esd_interval, taal_store_esd_interval);
915static DEVICE_ATTR(ulps, S_IRUGO | S_IWUSR,
916 taal_show_ulps, taal_store_ulps);
917static DEVICE_ATTR(ulps_timeout, S_IRUGO | S_IWUSR,
918 taal_show_ulps_timeout, taal_store_ulps_timeout);
626 919
627static struct attribute *taal_attrs[] = { 920static struct attribute *taal_attrs[] = {
628 &dev_attr_num_dsi_errors.attr, 921 &dev_attr_num_dsi_errors.attr,
629 &dev_attr_hw_revision.attr, 922 &dev_attr_hw_revision.attr,
630 &dev_attr_cabc_mode.attr, 923 &dev_attr_cabc_mode.attr,
631 &dev_attr_cabc_available_modes.attr, 924 &dev_attr_cabc_available_modes.attr,
925 &dev_attr_esd_interval.attr,
926 &dev_attr_ulps.attr,
927 &dev_attr_ulps_timeout.attr,
632 NULL, 928 NULL,
633}; 929};
634 930
@@ -697,6 +993,9 @@ static int taal_probe(struct omap_dss_device *dssdev)
697 } 993 }
698 td->dssdev = dssdev; 994 td->dssdev = dssdev;
699 td->panel_config = panel_config; 995 td->panel_config = panel_config;
996 td->esd_interval = panel_data->esd_interval;
997 td->ulps_enabled = false;
998 td->ulps_timeout = panel_data->ulps_timeout;
700 999
701 mutex_init(&td->lock); 1000 mutex_init(&td->lock);
702 1001
@@ -707,13 +1006,14 @@ static int taal_probe(struct omap_dss_device *dssdev)
707 if (r) 1006 if (r)
708 goto err_reg; 1007 goto err_reg;
709 1008
710 td->esd_wq = create_singlethread_workqueue("taal_esd"); 1009 td->workqueue = create_singlethread_workqueue("taal_esd");
711 if (td->esd_wq == NULL) { 1010 if (td->workqueue == NULL) {
712 dev_err(&dssdev->dev, "can't create ESD workqueue\n"); 1011 dev_err(&dssdev->dev, "can't create ESD workqueue\n");
713 r = -ENOMEM; 1012 r = -ENOMEM;
714 goto err_wq; 1013 goto err_wq;
715 } 1014 }
716 INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work); 1015 INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work);
1016 INIT_DELAYED_WORK(&td->ulps_work, taal_ulps_work);
717 1017
718 dev_set_drvdata(&dssdev->dev, td); 1018 dev_set_drvdata(&dssdev->dev, td);
719 1019
@@ -729,8 +1029,10 @@ static int taal_probe(struct omap_dss_device *dssdev)
729 props.max_brightness = 255; 1029 props.max_brightness = 255;
730 else 1030 else
731 props.max_brightness = 127; 1031 props.max_brightness = 127;
732 bldev = backlight_device_register("taal", &dssdev->dev, dssdev, 1032
733 &taal_bl_ops, &props); 1033 props.type = BACKLIGHT_RAW;
1034 bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev,
1035 dssdev, &taal_bl_ops, &props);
734 if (IS_ERR(bldev)) { 1036 if (IS_ERR(bldev)) {
735 r = PTR_ERR(bldev); 1037 r = PTR_ERR(bldev);
736 goto err_bl; 1038 goto err_bl;
@@ -774,14 +1076,29 @@ static int taal_probe(struct omap_dss_device *dssdev)
774 dev_dbg(&dssdev->dev, "Using GPIO TE\n"); 1076 dev_dbg(&dssdev->dev, "Using GPIO TE\n");
775 } 1077 }
776 1078
1079 r = omap_dsi_request_vc(dssdev, &td->channel);
1080 if (r) {
1081 dev_err(&dssdev->dev, "failed to get virtual channel\n");
1082 goto err_req_vc;
1083 }
1084
1085 r = omap_dsi_set_vc_id(dssdev, td->channel, TCH);
1086 if (r) {
1087 dev_err(&dssdev->dev, "failed to set VC_ID\n");
1088 goto err_vc_id;
1089 }
1090
777 r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group); 1091 r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group);
778 if (r) { 1092 if (r) {
779 dev_err(&dssdev->dev, "failed to create sysfs files\n"); 1093 dev_err(&dssdev->dev, "failed to create sysfs files\n");
780 goto err_sysfs; 1094 goto err_vc_id;
781 } 1095 }
782 1096
783 return 0; 1097 return 0;
784err_sysfs: 1098
1099err_vc_id:
1100 omap_dsi_release_vc(dssdev, td->channel);
1101err_req_vc:
785 if (panel_data->use_ext_te) 1102 if (panel_data->use_ext_te)
786 free_irq(gpio_to_irq(panel_data->ext_te_gpio), dssdev); 1103 free_irq(gpio_to_irq(panel_data->ext_te_gpio), dssdev);
787err_irq: 1104err_irq:
@@ -790,7 +1107,7 @@ err_irq:
790err_gpio: 1107err_gpio:
791 backlight_device_unregister(bldev); 1108 backlight_device_unregister(bldev);
792err_bl: 1109err_bl:
793 destroy_workqueue(td->esd_wq); 1110 destroy_workqueue(td->workqueue);
794err_wq: 1111err_wq:
795 free_regulators(panel_config->regulators, panel_config->num_regulators); 1112 free_regulators(panel_config->regulators, panel_config->num_regulators);
796err_reg: 1113err_reg:
@@ -799,7 +1116,7 @@ err:
799 return r; 1116 return r;
800} 1117}
801 1118
802static void taal_remove(struct omap_dss_device *dssdev) 1119static void __exit taal_remove(struct omap_dss_device *dssdev)
803{ 1120{
804 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1121 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
805 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); 1122 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
@@ -808,6 +1125,7 @@ static void taal_remove(struct omap_dss_device *dssdev)
808 dev_dbg(&dssdev->dev, "remove\n"); 1125 dev_dbg(&dssdev->dev, "remove\n");
809 1126
810 sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group); 1127 sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group);
1128 omap_dsi_release_vc(dssdev, td->channel);
811 1129
812 if (panel_data->use_ext_te) { 1130 if (panel_data->use_ext_te) {
813 int gpio = panel_data->ext_te_gpio; 1131 int gpio = panel_data->ext_te_gpio;
@@ -820,8 +1138,9 @@ static void taal_remove(struct omap_dss_device *dssdev)
820 taal_bl_update_status(bldev); 1138 taal_bl_update_status(bldev);
821 backlight_device_unregister(bldev); 1139 backlight_device_unregister(bldev);
822 1140
823 cancel_delayed_work(&td->esd_work); 1141 taal_cancel_ulps_work(dssdev);
824 destroy_workqueue(td->esd_wq); 1142 taal_cancel_esd_work(dssdev);
1143 destroy_workqueue(td->workqueue);
825 1144
826 /* reset, to be sure that the panel is in a valid state */ 1145 /* reset, to be sure that the panel is in a valid state */
827 taal_hw_reset(dssdev); 1146 taal_hw_reset(dssdev);
@@ -846,13 +1165,13 @@ static int taal_power_on(struct omap_dss_device *dssdev)
846 1165
847 taal_hw_reset(dssdev); 1166 taal_hw_reset(dssdev);
848 1167
849 omapdss_dsi_vc_enable_hs(TCH, false); 1168 omapdss_dsi_vc_enable_hs(dssdev, td->channel, false);
850 1169
851 r = taal_sleep_out(td); 1170 r = taal_sleep_out(td);
852 if (r) 1171 if (r)
853 goto err; 1172 goto err;
854 1173
855 r = taal_get_id(&id1, &id2, &id3); 1174 r = taal_get_id(td, &id1, &id2, &id3);
856 if (r) 1175 if (r)
857 goto err; 1176 goto err;
858 1177
@@ -861,30 +1180,30 @@ static int taal_power_on(struct omap_dss_device *dssdev)
861 (id2 == 0x00 || id2 == 0xff || id2 == 0x81)) 1180 (id2 == 0x00 || id2 == 0xff || id2 == 0x81))
862 td->cabc_broken = true; 1181 td->cabc_broken = true;
863 1182
864 r = taal_dcs_write_1(DCS_BRIGHTNESS, 0xff); 1183 r = taal_dcs_write_1(td, DCS_BRIGHTNESS, 0xff);
865 if (r) 1184 if (r)
866 goto err; 1185 goto err;
867 1186
868 r = taal_dcs_write_1(DCS_CTRL_DISPLAY, 1187 r = taal_dcs_write_1(td, DCS_CTRL_DISPLAY,
869 (1<<2) | (1<<5)); /* BL | BCTRL */ 1188 (1<<2) | (1<<5)); /* BL | BCTRL */
870 if (r) 1189 if (r)
871 goto err; 1190 goto err;
872 1191
873 r = taal_dcs_write_1(DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */ 1192 r = taal_dcs_write_1(td, DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */
874 if (r) 1193 if (r)
875 goto err; 1194 goto err;
876 1195
877 r = taal_set_addr_mode(td->rotate, td->mirror); 1196 r = taal_set_addr_mode(td, td->rotate, td->mirror);
878 if (r) 1197 if (r)
879 goto err; 1198 goto err;
880 1199
881 if (!td->cabc_broken) { 1200 if (!td->cabc_broken) {
882 r = taal_dcs_write_1(DCS_WRITE_CABC, td->cabc_mode); 1201 r = taal_dcs_write_1(td, DCS_WRITE_CABC, td->cabc_mode);
883 if (r) 1202 if (r)
884 goto err; 1203 goto err;
885 } 1204 }
886 1205
887 r = taal_dcs_write_0(DCS_DISPLAY_ON); 1206 r = taal_dcs_write_0(td, DCS_DISPLAY_ON);
888 if (r) 1207 if (r)
889 goto err; 1208 goto err;
890 1209
@@ -903,7 +1222,7 @@ static int taal_power_on(struct omap_dss_device *dssdev)
903 td->intro_printed = true; 1222 td->intro_printed = true;
904 } 1223 }
905 1224
906 omapdss_dsi_vc_enable_hs(TCH, true); 1225 omapdss_dsi_vc_enable_hs(dssdev, td->channel, true);
907 1226
908 return 0; 1227 return 0;
909err: 1228err:
@@ -911,7 +1230,7 @@ err:
911 1230
912 taal_hw_reset(dssdev); 1231 taal_hw_reset(dssdev);
913 1232
914 omapdss_dsi_display_disable(dssdev); 1233 omapdss_dsi_display_disable(dssdev, true, false);
915err0: 1234err0:
916 return r; 1235 return r;
917} 1236}
@@ -921,7 +1240,7 @@ static void taal_power_off(struct omap_dss_device *dssdev)
921 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1240 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
922 int r; 1241 int r;
923 1242
924 r = taal_dcs_write_0(DCS_DISPLAY_OFF); 1243 r = taal_dcs_write_0(td, DCS_DISPLAY_OFF);
925 if (!r) { 1244 if (!r) {
926 r = taal_sleep_in(td); 1245 r = taal_sleep_in(td);
927 /* HACK: wait a bit so that the message goes through */ 1246 /* HACK: wait a bit so that the message goes through */
@@ -934,15 +1253,23 @@ static void taal_power_off(struct omap_dss_device *dssdev)
934 taal_hw_reset(dssdev); 1253 taal_hw_reset(dssdev);
935 } 1254 }
936 1255
937 omapdss_dsi_display_disable(dssdev); 1256 omapdss_dsi_display_disable(dssdev, true, false);
938 1257
939 td->enabled = 0; 1258 td->enabled = 0;
940} 1259}
941 1260
1261static int taal_panel_reset(struct omap_dss_device *dssdev)
1262{
1263 dev_err(&dssdev->dev, "performing LCD reset\n");
1264
1265 taal_power_off(dssdev);
1266 taal_hw_reset(dssdev);
1267 return taal_power_on(dssdev);
1268}
1269
942static int taal_enable(struct omap_dss_device *dssdev) 1270static int taal_enable(struct omap_dss_device *dssdev)
943{ 1271{
944 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1272 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
945 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
946 int r; 1273 int r;
947 1274
948 dev_dbg(&dssdev->dev, "enable\n"); 1275 dev_dbg(&dssdev->dev, "enable\n");
@@ -954,18 +1281,16 @@ static int taal_enable(struct omap_dss_device *dssdev)
954 goto err; 1281 goto err;
955 } 1282 }
956 1283
957 dsi_bus_lock(); 1284 dsi_bus_lock(dssdev);
958 1285
959 r = taal_power_on(dssdev); 1286 r = taal_power_on(dssdev);
960 1287
961 dsi_bus_unlock(); 1288 dsi_bus_unlock(dssdev);
962 1289
963 if (r) 1290 if (r)
964 goto err; 1291 goto err;
965 1292
966 if (panel_data->use_esd_check) 1293 taal_queue_esd_work(dssdev);
967 queue_delayed_work(td->esd_wq, &td->esd_work,
968 TAAL_ESD_CHECK_PERIOD);
969 1294
970 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 1295 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
971 1296
@@ -986,14 +1311,17 @@ static void taal_disable(struct omap_dss_device *dssdev)
986 1311
987 mutex_lock(&td->lock); 1312 mutex_lock(&td->lock);
988 1313
989 cancel_delayed_work(&td->esd_work); 1314 taal_cancel_ulps_work(dssdev);
1315 taal_cancel_esd_work(dssdev);
990 1316
991 dsi_bus_lock(); 1317 dsi_bus_lock(dssdev);
992 1318
993 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 1319 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
1320 taal_wake_up(dssdev);
994 taal_power_off(dssdev); 1321 taal_power_off(dssdev);
1322 }
995 1323
996 dsi_bus_unlock(); 1324 dsi_bus_unlock(dssdev);
997 1325
998 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 1326 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
999 1327
@@ -1014,13 +1342,16 @@ static int taal_suspend(struct omap_dss_device *dssdev)
1014 goto err; 1342 goto err;
1015 } 1343 }
1016 1344
1017 cancel_delayed_work(&td->esd_work); 1345 taal_cancel_ulps_work(dssdev);
1346 taal_cancel_esd_work(dssdev);
1018 1347
1019 dsi_bus_lock(); 1348 dsi_bus_lock(dssdev);
1020 1349
1021 taal_power_off(dssdev); 1350 r = taal_wake_up(dssdev);
1351 if (!r)
1352 taal_power_off(dssdev);
1022 1353
1023 dsi_bus_unlock(); 1354 dsi_bus_unlock(dssdev);
1024 1355
1025 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; 1356 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
1026 1357
@@ -1035,7 +1366,6 @@ err:
1035static int taal_resume(struct omap_dss_device *dssdev) 1366static int taal_resume(struct omap_dss_device *dssdev)
1036{ 1367{
1037 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1368 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1038 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
1039 int r; 1369 int r;
1040 1370
1041 dev_dbg(&dssdev->dev, "resume\n"); 1371 dev_dbg(&dssdev->dev, "resume\n");
@@ -1047,19 +1377,17 @@ static int taal_resume(struct omap_dss_device *dssdev)
1047 goto err; 1377 goto err;
1048 } 1378 }
1049 1379
1050 dsi_bus_lock(); 1380 dsi_bus_lock(dssdev);
1051 1381
1052 r = taal_power_on(dssdev); 1382 r = taal_power_on(dssdev);
1053 1383
1054 dsi_bus_unlock(); 1384 dsi_bus_unlock(dssdev);
1055 1385
1056 if (r) { 1386 if (r) {
1057 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 1387 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
1058 } else { 1388 } else {
1059 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 1389 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
1060 if (panel_data->use_esd_check) 1390 taal_queue_esd_work(dssdev);
1061 queue_delayed_work(td->esd_wq, &td->esd_work,
1062 TAAL_ESD_CHECK_PERIOD);
1063 } 1391 }
1064 1392
1065 mutex_unlock(&td->lock); 1393 mutex_unlock(&td->lock);
@@ -1074,7 +1402,7 @@ static void taal_framedone_cb(int err, void *data)
1074{ 1402{
1075 struct omap_dss_device *dssdev = data; 1403 struct omap_dss_device *dssdev = data;
1076 dev_dbg(&dssdev->dev, "framedone, err %d\n", err); 1404 dev_dbg(&dssdev->dev, "framedone, err %d\n", err);
1077 dsi_bus_unlock(); 1405 dsi_bus_unlock(dssdev);
1078} 1406}
1079 1407
1080static irqreturn_t taal_te_isr(int irq, void *data) 1408static irqreturn_t taal_te_isr(int irq, void *data)
@@ -1089,7 +1417,7 @@ static irqreturn_t taal_te_isr(int irq, void *data)
1089 if (old) { 1417 if (old) {
1090 cancel_delayed_work(&td->te_timeout_work); 1418 cancel_delayed_work(&td->te_timeout_work);
1091 1419
1092 r = omap_dsi_update(dssdev, TCH, 1420 r = omap_dsi_update(dssdev, td->channel,
1093 td->update_region.x, 1421 td->update_region.x,
1094 td->update_region.y, 1422 td->update_region.y,
1095 td->update_region.w, 1423 td->update_region.w,
@@ -1102,7 +1430,7 @@ static irqreturn_t taal_te_isr(int irq, void *data)
1102 return IRQ_HANDLED; 1430 return IRQ_HANDLED;
1103err: 1431err:
1104 dev_err(&dssdev->dev, "start update failed\n"); 1432 dev_err(&dssdev->dev, "start update failed\n");
1105 dsi_bus_unlock(); 1433 dsi_bus_unlock(dssdev);
1106 return IRQ_HANDLED; 1434 return IRQ_HANDLED;
1107} 1435}
1108 1436
@@ -1115,7 +1443,7 @@ static void taal_te_timeout_work_callback(struct work_struct *work)
1115 dev_err(&dssdev->dev, "TE not received for 250ms!\n"); 1443 dev_err(&dssdev->dev, "TE not received for 250ms!\n");
1116 1444
1117 atomic_set(&td->do_update, 0); 1445 atomic_set(&td->do_update, 0);
1118 dsi_bus_unlock(); 1446 dsi_bus_unlock(dssdev);
1119} 1447}
1120 1448
1121static int taal_update(struct omap_dss_device *dssdev, 1449static int taal_update(struct omap_dss_device *dssdev,
@@ -1128,7 +1456,11 @@ static int taal_update(struct omap_dss_device *dssdev,
1128 dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h); 1456 dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h);
1129 1457
1130 mutex_lock(&td->lock); 1458 mutex_lock(&td->lock);
1131 dsi_bus_lock(); 1459 dsi_bus_lock(dssdev);
1460
1461 r = taal_wake_up(dssdev);
1462 if (r)
1463 goto err;
1132 1464
1133 if (!td->enabled) { 1465 if (!td->enabled) {
1134 r = 0; 1466 r = 0;
@@ -1139,7 +1471,7 @@ static int taal_update(struct omap_dss_device *dssdev,
1139 if (r) 1471 if (r)
1140 goto err; 1472 goto err;
1141 1473
1142 r = taal_set_update_window(x, y, w, h); 1474 r = taal_set_update_window(td, x, y, w, h);
1143 if (r) 1475 if (r)
1144 goto err; 1476 goto err;
1145 1477
@@ -1153,7 +1485,7 @@ static int taal_update(struct omap_dss_device *dssdev,
1153 msecs_to_jiffies(250)); 1485 msecs_to_jiffies(250));
1154 atomic_set(&td->do_update, 1); 1486 atomic_set(&td->do_update, 1);
1155 } else { 1487 } else {
1156 r = omap_dsi_update(dssdev, TCH, x, y, w, h, 1488 r = omap_dsi_update(dssdev, td->channel, x, y, w, h,
1157 taal_framedone_cb, dssdev); 1489 taal_framedone_cb, dssdev);
1158 if (r) 1490 if (r)
1159 goto err; 1491 goto err;
@@ -1163,7 +1495,7 @@ static int taal_update(struct omap_dss_device *dssdev,
1163 mutex_unlock(&td->lock); 1495 mutex_unlock(&td->lock);
1164 return 0; 1496 return 0;
1165err: 1497err:
1166 dsi_bus_unlock(); 1498 dsi_bus_unlock(dssdev);
1167 mutex_unlock(&td->lock); 1499 mutex_unlock(&td->lock);
1168 return r; 1500 return r;
1169} 1501}
@@ -1175,8 +1507,8 @@ static int taal_sync(struct omap_dss_device *dssdev)
1175 dev_dbg(&dssdev->dev, "sync\n"); 1507 dev_dbg(&dssdev->dev, "sync\n");
1176 1508
1177 mutex_lock(&td->lock); 1509 mutex_lock(&td->lock);
1178 dsi_bus_lock(); 1510 dsi_bus_lock(dssdev);
1179 dsi_bus_unlock(); 1511 dsi_bus_unlock(dssdev);
1180 mutex_unlock(&td->lock); 1512 mutex_unlock(&td->lock);
1181 1513
1182 dev_dbg(&dssdev->dev, "sync done\n"); 1514 dev_dbg(&dssdev->dev, "sync done\n");
@@ -1191,9 +1523,9 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
1191 int r; 1523 int r;
1192 1524
1193 if (enable) 1525 if (enable)
1194 r = taal_dcs_write_1(DCS_TEAR_ON, 0); 1526 r = taal_dcs_write_1(td, DCS_TEAR_ON, 0);
1195 else 1527 else
1196 r = taal_dcs_write_0(DCS_TEAR_OFF); 1528 r = taal_dcs_write_0(td, DCS_TEAR_OFF);
1197 1529
1198 if (!panel_data->use_ext_te) 1530 if (!panel_data->use_ext_te)
1199 omapdss_dsi_enable_te(dssdev, enable); 1531 omapdss_dsi_enable_te(dssdev, enable);
@@ -1214,9 +1546,13 @@ static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
1214 if (td->te_enabled == enable) 1546 if (td->te_enabled == enable)
1215 goto end; 1547 goto end;
1216 1548
1217 dsi_bus_lock(); 1549 dsi_bus_lock(dssdev);
1218 1550
1219 if (td->enabled) { 1551 if (td->enabled) {
1552 r = taal_wake_up(dssdev);
1553 if (r)
1554 goto err;
1555
1220 r = _taal_enable_te(dssdev, enable); 1556 r = _taal_enable_te(dssdev, enable);
1221 if (r) 1557 if (r)
1222 goto err; 1558 goto err;
@@ -1224,13 +1560,13 @@ static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
1224 1560
1225 td->te_enabled = enable; 1561 td->te_enabled = enable;
1226 1562
1227 dsi_bus_unlock(); 1563 dsi_bus_unlock(dssdev);
1228end: 1564end:
1229 mutex_unlock(&td->lock); 1565 mutex_unlock(&td->lock);
1230 1566
1231 return 0; 1567 return 0;
1232err: 1568err:
1233 dsi_bus_unlock(); 1569 dsi_bus_unlock(dssdev);
1234 mutex_unlock(&td->lock); 1570 mutex_unlock(&td->lock);
1235 1571
1236 return r; 1572 return r;
@@ -1260,22 +1596,26 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
1260 if (td->rotate == rotate) 1596 if (td->rotate == rotate)
1261 goto end; 1597 goto end;
1262 1598
1263 dsi_bus_lock(); 1599 dsi_bus_lock(dssdev);
1264 1600
1265 if (td->enabled) { 1601 if (td->enabled) {
1266 r = taal_set_addr_mode(rotate, td->mirror); 1602 r = taal_wake_up(dssdev);
1603 if (r)
1604 goto err;
1605
1606 r = taal_set_addr_mode(td, rotate, td->mirror);
1267 if (r) 1607 if (r)
1268 goto err; 1608 goto err;
1269 } 1609 }
1270 1610
1271 td->rotate = rotate; 1611 td->rotate = rotate;
1272 1612
1273 dsi_bus_unlock(); 1613 dsi_bus_unlock(dssdev);
1274end: 1614end:
1275 mutex_unlock(&td->lock); 1615 mutex_unlock(&td->lock);
1276 return 0; 1616 return 0;
1277err: 1617err:
1278 dsi_bus_unlock(); 1618 dsi_bus_unlock(dssdev);
1279 mutex_unlock(&td->lock); 1619 mutex_unlock(&td->lock);
1280 return r; 1620 return r;
1281} 1621}
@@ -1304,21 +1644,25 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
1304 if (td->mirror == enable) 1644 if (td->mirror == enable)
1305 goto end; 1645 goto end;
1306 1646
1307 dsi_bus_lock(); 1647 dsi_bus_lock(dssdev);
1308 if (td->enabled) { 1648 if (td->enabled) {
1309 r = taal_set_addr_mode(td->rotate, enable); 1649 r = taal_wake_up(dssdev);
1650 if (r)
1651 goto err;
1652
1653 r = taal_set_addr_mode(td, td->rotate, enable);
1310 if (r) 1654 if (r)
1311 goto err; 1655 goto err;
1312 } 1656 }
1313 1657
1314 td->mirror = enable; 1658 td->mirror = enable;
1315 1659
1316 dsi_bus_unlock(); 1660 dsi_bus_unlock(dssdev);
1317end: 1661end:
1318 mutex_unlock(&td->lock); 1662 mutex_unlock(&td->lock);
1319 return 0; 1663 return 0;
1320err: 1664err:
1321 dsi_bus_unlock(); 1665 dsi_bus_unlock(dssdev);
1322 mutex_unlock(&td->lock); 1666 mutex_unlock(&td->lock);
1323 return r; 1667 return r;
1324} 1668}
@@ -1348,23 +1692,27 @@ static int taal_run_test(struct omap_dss_device *dssdev, int test_num)
1348 goto err1; 1692 goto err1;
1349 } 1693 }
1350 1694
1351 dsi_bus_lock(); 1695 dsi_bus_lock(dssdev);
1696
1697 r = taal_wake_up(dssdev);
1698 if (r)
1699 goto err2;
1352 1700
1353 r = taal_dcs_read_1(DCS_GET_ID1, &id1); 1701 r = taal_dcs_read_1(td, DCS_GET_ID1, &id1);
1354 if (r) 1702 if (r)
1355 goto err2; 1703 goto err2;
1356 r = taal_dcs_read_1(DCS_GET_ID2, &id2); 1704 r = taal_dcs_read_1(td, DCS_GET_ID2, &id2);
1357 if (r) 1705 if (r)
1358 goto err2; 1706 goto err2;
1359 r = taal_dcs_read_1(DCS_GET_ID3, &id3); 1707 r = taal_dcs_read_1(td, DCS_GET_ID3, &id3);
1360 if (r) 1708 if (r)
1361 goto err2; 1709 goto err2;
1362 1710
1363 dsi_bus_unlock(); 1711 dsi_bus_unlock(dssdev);
1364 mutex_unlock(&td->lock); 1712 mutex_unlock(&td->lock);
1365 return 0; 1713 return 0;
1366err2: 1714err2:
1367 dsi_bus_unlock(); 1715 dsi_bus_unlock(dssdev);
1368err1: 1716err1:
1369 mutex_unlock(&td->lock); 1717 mutex_unlock(&td->lock);
1370 return r; 1718 return r;
@@ -1394,7 +1742,11 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
1394 dssdev->panel.timings.x_res * 1742 dssdev->panel.timings.x_res *
1395 dssdev->panel.timings.y_res * 3); 1743 dssdev->panel.timings.y_res * 3);
1396 1744
1397 dsi_bus_lock(); 1745 dsi_bus_lock(dssdev);
1746
1747 r = taal_wake_up(dssdev);
1748 if (r)
1749 goto err2;
1398 1750
1399 /* plen 1 or 2 goes into short packet. until checksum error is fixed, 1751 /* plen 1 or 2 goes into short packet. until checksum error is fixed,
1400 * use short packets. plen 32 works, but bigger packets seem to cause 1752 * use short packets. plen 32 works, but bigger packets seem to cause
@@ -1404,9 +1756,9 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
1404 else 1756 else
1405 plen = 2; 1757 plen = 2;
1406 1758
1407 taal_set_update_window(x, y, w, h); 1759 taal_set_update_window(td, x, y, w, h);
1408 1760
1409 r = dsi_vc_set_max_rx_packet_size(TCH, plen); 1761 r = dsi_vc_set_max_rx_packet_size(dssdev, td->channel, plen);
1410 if (r) 1762 if (r)
1411 goto err2; 1763 goto err2;
1412 1764
@@ -1414,7 +1766,7 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
1414 u8 dcs_cmd = first ? 0x2e : 0x3e; 1766 u8 dcs_cmd = first ? 0x2e : 0x3e;
1415 first = 0; 1767 first = 0;
1416 1768
1417 r = dsi_vc_dcs_read(TCH, dcs_cmd, 1769 r = dsi_vc_dcs_read(dssdev, td->channel, dcs_cmd,
1418 buf + buf_used, size - buf_used); 1770 buf + buf_used, size - buf_used);
1419 1771
1420 if (r < 0) { 1772 if (r < 0) {
@@ -1440,14 +1792,35 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
1440 r = buf_used; 1792 r = buf_used;
1441 1793
1442err3: 1794err3:
1443 dsi_vc_set_max_rx_packet_size(TCH, 1); 1795 dsi_vc_set_max_rx_packet_size(dssdev, td->channel, 1);
1444err2: 1796err2:
1445 dsi_bus_unlock(); 1797 dsi_bus_unlock(dssdev);
1446err1: 1798err1:
1447 mutex_unlock(&td->lock); 1799 mutex_unlock(&td->lock);
1448 return r; 1800 return r;
1449} 1801}
1450 1802
1803static void taal_ulps_work(struct work_struct *work)
1804{
1805 struct taal_data *td = container_of(work, struct taal_data,
1806 ulps_work.work);
1807 struct omap_dss_device *dssdev = td->dssdev;
1808
1809 mutex_lock(&td->lock);
1810
1811 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE || !td->enabled) {
1812 mutex_unlock(&td->lock);
1813 return;
1814 }
1815
1816 dsi_bus_lock(dssdev);
1817
1818 taal_enter_ulps(dssdev);
1819
1820 dsi_bus_unlock(dssdev);
1821 mutex_unlock(&td->lock);
1822}
1823
1451static void taal_esd_work(struct work_struct *work) 1824static void taal_esd_work(struct work_struct *work)
1452{ 1825{
1453 struct taal_data *td = container_of(work, struct taal_data, 1826 struct taal_data *td = container_of(work, struct taal_data,
@@ -1464,9 +1837,15 @@ static void taal_esd_work(struct work_struct *work)
1464 return; 1837 return;
1465 } 1838 }
1466 1839
1467 dsi_bus_lock(); 1840 dsi_bus_lock(dssdev);
1841
1842 r = taal_wake_up(dssdev);
1843 if (r) {
1844 dev_err(&dssdev->dev, "failed to exit ULPS\n");
1845 goto err;
1846 }
1468 1847
1469 r = taal_dcs_read_1(DCS_RDDSDR, &state1); 1848 r = taal_dcs_read_1(td, DCS_RDDSDR, &state1);
1470 if (r) { 1849 if (r) {
1471 dev_err(&dssdev->dev, "failed to read Taal status\n"); 1850 dev_err(&dssdev->dev, "failed to read Taal status\n");
1472 goto err; 1851 goto err;
@@ -1479,7 +1858,7 @@ static void taal_esd_work(struct work_struct *work)
1479 goto err; 1858 goto err;
1480 } 1859 }
1481 1860
1482 r = taal_dcs_read_1(DCS_RDDSDR, &state2); 1861 r = taal_dcs_read_1(td, DCS_RDDSDR, &state2);
1483 if (r) { 1862 if (r) {
1484 dev_err(&dssdev->dev, "failed to read Taal status\n"); 1863 dev_err(&dssdev->dev, "failed to read Taal status\n");
1485 goto err; 1864 goto err;
@@ -1495,27 +1874,25 @@ static void taal_esd_work(struct work_struct *work)
1495 /* Self-diagnostics result is also shown on TE GPIO line. We need 1874 /* Self-diagnostics result is also shown on TE GPIO line. We need
1496 * to re-enable TE after self diagnostics */ 1875 * to re-enable TE after self diagnostics */
1497 if (td->te_enabled && panel_data->use_ext_te) { 1876 if (td->te_enabled && panel_data->use_ext_te) {
1498 r = taal_dcs_write_1(DCS_TEAR_ON, 0); 1877 r = taal_dcs_write_1(td, DCS_TEAR_ON, 0);
1499 if (r) 1878 if (r)
1500 goto err; 1879 goto err;
1501 } 1880 }
1502 1881
1503 dsi_bus_unlock(); 1882 dsi_bus_unlock(dssdev);
1504 1883
1505 queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD); 1884 taal_queue_esd_work(dssdev);
1506 1885
1507 mutex_unlock(&td->lock); 1886 mutex_unlock(&td->lock);
1508 return; 1887 return;
1509err: 1888err:
1510 dev_err(&dssdev->dev, "performing LCD reset\n"); 1889 dev_err(&dssdev->dev, "performing LCD reset\n");
1511 1890
1512 taal_power_off(dssdev); 1891 taal_panel_reset(dssdev);
1513 taal_hw_reset(dssdev);
1514 taal_power_on(dssdev);
1515 1892
1516 dsi_bus_unlock(); 1893 dsi_bus_unlock(dssdev);
1517 1894
1518 queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD); 1895 taal_queue_esd_work(dssdev);
1519 1896
1520 mutex_unlock(&td->lock); 1897 mutex_unlock(&td->lock);
1521} 1898}
@@ -1536,7 +1913,7 @@ static enum omap_dss_update_mode taal_get_update_mode(
1536 1913
1537static struct omap_dss_driver taal_driver = { 1914static struct omap_dss_driver taal_driver = {
1538 .probe = taal_probe, 1915 .probe = taal_probe,
1539 .remove = taal_remove, 1916 .remove = __exit_p(taal_remove),
1540 1917
1541 .enable = taal_enable, 1918 .enable = taal_enable,
1542 .disable = taal_disable, 1919 .disable = taal_disable,
diff --git a/drivers/video/omap2/displays/panel-toppoly-tdo35s.c b/drivers/video/omap2/displays/panel-toppoly-tdo35s.c
deleted file mode 100644
index e320e67d06f3..000000000000
--- a/drivers/video/omap2/displays/panel-toppoly-tdo35s.c
+++ /dev/null
@@ -1,158 +0,0 @@
1/*
2 * LCD panel driver for Toppoly TDO35S
3 *
4 * Copyright (C) 2009 CompuLab, Ltd.
5 * Author: Mike Rapoport <mike@compulab.co.il>
6 *
7 * Based on generic panel support
8 * Copyright (C) 2008 Nokia Corporation
9 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License version 2 as published by
13 * the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 * more details.
19 *
20 * You should have received a copy of the GNU General Public License along with
21 * this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24#include <linux/module.h>
25#include <linux/delay.h>
26
27#include <plat/display.h>
28
29static struct omap_video_timings toppoly_tdo_panel_timings = {
30 /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */
31 .x_res = 480,
32 .y_res = 640,
33
34 .pixel_clock = 26000,
35
36 .hfp = 104,
37 .hsw = 8,
38 .hbp = 8,
39
40 .vfp = 4,
41 .vsw = 2,
42 .vbp = 2,
43};
44
45static int toppoly_tdo_panel_power_on(struct omap_dss_device *dssdev)
46{
47 int r;
48
49 r = omapdss_dpi_display_enable(dssdev);
50 if (r)
51 goto err0;
52
53 if (dssdev->platform_enable) {
54 r = dssdev->platform_enable(dssdev);
55 if (r)
56 goto err1;
57 }
58
59 return 0;
60err1:
61 omapdss_dpi_display_disable(dssdev);
62err0:
63 return r;
64}
65
66static void toppoly_tdo_panel_power_off(struct omap_dss_device *dssdev)
67{
68 if (dssdev->platform_disable)
69 dssdev->platform_disable(dssdev);
70
71 omapdss_dpi_display_disable(dssdev);
72}
73
74static int toppoly_tdo_panel_probe(struct omap_dss_device *dssdev)
75{
76 dssdev->panel.config = OMAP_DSS_LCD_TFT |
77 OMAP_DSS_LCD_IVS |
78 OMAP_DSS_LCD_IHS |
79 OMAP_DSS_LCD_IPC |
80 OMAP_DSS_LCD_ONOFF;
81
82 dssdev->panel.timings = toppoly_tdo_panel_timings;
83
84 return 0;
85}
86
87static void toppoly_tdo_panel_remove(struct omap_dss_device *dssdev)
88{
89}
90
91static int toppoly_tdo_panel_enable(struct omap_dss_device *dssdev)
92{
93 int r = 0;
94
95 r = toppoly_tdo_panel_power_on(dssdev);
96 if (r)
97 return r;
98
99 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
100
101 return 0;
102}
103
104static void toppoly_tdo_panel_disable(struct omap_dss_device *dssdev)
105{
106 toppoly_tdo_panel_power_off(dssdev);
107
108 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
109}
110
111static int toppoly_tdo_panel_suspend(struct omap_dss_device *dssdev)
112{
113 toppoly_tdo_panel_power_off(dssdev);
114 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
115 return 0;
116}
117
118static int toppoly_tdo_panel_resume(struct omap_dss_device *dssdev)
119{
120 int r = 0;
121
122 r = toppoly_tdo_panel_power_on(dssdev);
123 if (r)
124 return r;
125
126 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
127
128 return 0;
129}
130
131static struct omap_dss_driver generic_driver = {
132 .probe = toppoly_tdo_panel_probe,
133 .remove = toppoly_tdo_panel_remove,
134
135 .enable = toppoly_tdo_panel_enable,
136 .disable = toppoly_tdo_panel_disable,
137 .suspend = toppoly_tdo_panel_suspend,
138 .resume = toppoly_tdo_panel_resume,
139
140 .driver = {
141 .name = "toppoly_tdo35s_panel",
142 .owner = THIS_MODULE,
143 },
144};
145
146static int __init toppoly_tdo_panel_drv_init(void)
147{
148 return omap_dss_register_driver(&generic_driver);
149}
150
151static void __exit toppoly_tdo_panel_drv_exit(void)
152{
153 omap_dss_unregister_driver(&generic_driver);
154}
155
156module_init(toppoly_tdo_panel_drv_init);
157module_exit(toppoly_tdo_panel_drv_exit);
158MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
index e866e76b13d0..2462b9ec6662 100644
--- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
+++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
@@ -17,7 +17,7 @@
17#include <linux/err.h> 17#include <linux/err.h>
18#include <linux/slab.h> 18#include <linux/slab.h>
19 19
20#include <plat/display.h> 20#include <video/omapdss.h>
21 21
22#define TPO_R02_MODE(x) ((x) & 7) 22#define TPO_R02_MODE(x) ((x) & 7)
23#define TPO_R02_MODE_800x480 7 23#define TPO_R02_MODE_800x480 7
@@ -144,13 +144,15 @@ static ssize_t tpo_td043_vmirror_store(struct device *dev,
144 struct device_attribute *attr, const char *buf, size_t count) 144 struct device_attribute *attr, const char *buf, size_t count)
145{ 145{
146 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev); 146 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
147 long val; 147 int val;
148 int ret; 148 int ret;
149 149
150 ret = strict_strtol(buf, 0, &val); 150 ret = kstrtoint(buf, 0, &val);
151 if (ret < 0) 151 if (ret < 0)
152 return ret; 152 return ret;
153 153
154 val = !!val;
155
154 ret = tpo_td043_write_mirror(tpo_td043->spi, tpo_td043->hmirror, val); 156 ret = tpo_td043_write_mirror(tpo_td043->spi, tpo_td043->hmirror, val);
155 if (ret < 0) 157 if (ret < 0)
156 return ret; 158 return ret;
@@ -175,7 +177,7 @@ static ssize_t tpo_td043_mode_store(struct device *dev,
175 long val; 177 long val;
176 int ret; 178 int ret;
177 179
178 ret = strict_strtol(buf, 0, &val); 180 ret = kstrtol(buf, 0, &val);
179 if (ret != 0 || val & ~7) 181 if (ret != 0 || val & ~7)
180 return -EINVAL; 182 return -EINVAL;
181 183
@@ -269,6 +271,9 @@ static int tpo_td043_power_on(struct omap_dss_device *dssdev)
269 int nreset_gpio = dssdev->reset_gpio; 271 int nreset_gpio = dssdev->reset_gpio;
270 int r; 272 int r;
271 273
274 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
275 return 0;
276
272 r = omapdss_dpi_display_enable(dssdev); 277 r = omapdss_dpi_display_enable(dssdev);
273 if (r) 278 if (r)
274 goto err0; 279 goto err0;
@@ -308,6 +313,9 @@ static void tpo_td043_power_off(struct omap_dss_device *dssdev)
308 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev); 313 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
309 int nreset_gpio = dssdev->reset_gpio; 314 int nreset_gpio = dssdev->reset_gpio;
310 315
316 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
317 return;
318
311 tpo_td043_write(tpo_td043->spi, 3, 319 tpo_td043_write(tpo_td043->spi, 3,
312 TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM); 320 TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM);
313 321
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index 43b64403eaa4..6b3e2da11419 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -1,8 +1,8 @@
1menuconfig OMAP2_DSS 1menuconfig OMAP2_DSS
2 tristate "OMAP2/3 Display Subsystem support (EXPERIMENTAL)" 2 tristate "OMAP2+ Display Subsystem support (EXPERIMENTAL)"
3 depends on ARCH_OMAP2 || ARCH_OMAP3 3 depends on ARCH_OMAP2PLUS
4 help 4 help
5 OMAP2/3 Display Subsystem support. 5 OMAP2+ Display Subsystem support.
6 6
7if OMAP2_DSS 7if OMAP2_DSS
8 8
@@ -60,6 +60,14 @@ config OMAP2_DSS_VENC
60 help 60 help
61 OMAP Video Encoder support for S-Video and composite TV-out. 61 OMAP Video Encoder support for S-Video and composite TV-out.
62 62
63config OMAP4_DSS_HDMI
64 bool "HDMI support"
65 depends on ARCH_OMAP4
66 default y
67 help
68 HDMI Interface. This adds the High Definition Multimedia Interface.
69 See http://www.hdmi.org/ for HDMI specification.
70
63config OMAP2_DSS_SDI 71config OMAP2_DSS_SDI
64 bool "SDI support" 72 bool "SDI support"
65 depends on ARCH_OMAP3 73 depends on ARCH_OMAP3
@@ -72,7 +80,7 @@ config OMAP2_DSS_SDI
72 80
73config OMAP2_DSS_DSI 81config OMAP2_DSS_DSI
74 bool "DSI support" 82 bool "DSI support"
75 depends on ARCH_OMAP3 83 depends on ARCH_OMAP3 || ARCH_OMAP4
76 default n 84 default n
77 help 85 help
78 MIPI DSI (Display Serial Interface) support. 86 MIPI DSI (Display Serial Interface) support.
@@ -82,14 +90,6 @@ config OMAP2_DSS_DSI
82 90
83 See http://www.mipi.org/ for DSI spesifications. 91 See http://www.mipi.org/ for DSI spesifications.
84 92
85config OMAP2_DSS_USE_DSI_PLL
86 bool "Use DSI PLL for PCLK (EXPERIMENTAL)"
87 default n
88 depends on OMAP2_DSS_DSI
89 help
90 Use DSI PLL to generate pixel clock. Currently only for DPI output.
91 DSI PLL can be used to generate higher and more precise pixel clocks.
92
93config OMAP2_DSS_FAKE_VSYNC 93config OMAP2_DSS_FAKE_VSYNC
94 bool "Fake VSYNC irq from manual update displays" 94 bool "Fake VSYNC irq from manual update displays"
95 default n 95 default n
@@ -117,4 +117,27 @@ config OMAP2_DSS_MIN_FCK_PER_PCK
117 Max FCK is 173MHz, so this doesn't work if your PCK 117 Max FCK is 173MHz, so this doesn't work if your PCK
118 is very high. 118 is very high.
119 119
120config OMAP2_DSS_SLEEP_BEFORE_RESET
121 bool "Sleep 50ms before DSS reset"
122 default y
123 help
124 For some unknown reason we may get SYNC_LOST errors from the display
125 subsystem at initialization time if we don't sleep before resetting
126 the DSS. See the source (dss.c) for more comments.
127
128 However, 50ms is quite long time to sleep, and with some
129 configurations the SYNC_LOST may never happen, so the sleep can
130 be disabled here.
131
132config OMAP2_DSS_SLEEP_AFTER_VENC_RESET
133 bool "Sleep 20ms after VENC reset"
134 default y
135 help
136 There is a 20ms sleep after VENC reset which seemed to fix the
137 reset. The reason for the bug is unclear, and it's also unclear
138 on what platforms this happens.
139
140 This option enables the sleep, and is enabled by default. You can
141 disable the sleep if it doesn't cause problems on your platform.
142
120endif 143endif
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
index d71b5d9d71b1..10d9d3bb3e24 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/omap2/dss/Makefile
@@ -1,7 +1,9 @@
1obj-$(CONFIG_OMAP2_DSS) += omapdss.o 1obj-$(CONFIG_OMAP2_DSS) += omapdss.o
2omapdss-y := core.o dss.o dispc.o display.o manager.o overlay.o 2omapdss-y := core.o dss.o dss_features.o dispc.o display.o manager.o overlay.o
3omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o 3omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
4omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o 4omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
5omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o 5omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
6omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o 6omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
7omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o 7omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
8omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \
9 hdmi_omap4_panel.o
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index b3a498f22d36..3da426719dd6 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -33,331 +33,29 @@
33#include <linux/device.h> 33#include <linux/device.h>
34#include <linux/regulator/consumer.h> 34#include <linux/regulator/consumer.h>
35 35
36#include <plat/display.h> 36#include <video/omapdss.h>
37#include <plat/clock.h>
38 37
39#include "dss.h" 38#include "dss.h"
39#include "dss_features.h"
40 40
41static struct { 41static struct {
42 struct platform_device *pdev; 42 struct platform_device *pdev;
43 int ctx_id;
44
45 struct clk *dss_ick;
46 struct clk *dss1_fck;
47 struct clk *dss2_fck;
48 struct clk *dss_54m_fck;
49 struct clk *dss_96m_fck;
50 unsigned num_clks_enabled;
51 43
52 struct regulator *vdds_dsi_reg; 44 struct regulator *vdds_dsi_reg;
53 struct regulator *vdds_sdi_reg; 45 struct regulator *vdds_sdi_reg;
54 struct regulator *vdda_dac_reg;
55} core; 46} core;
56 47
57static void dss_clk_enable_all_no_ctx(void);
58static void dss_clk_disable_all_no_ctx(void);
59static void dss_clk_enable_no_ctx(enum dss_clock clks);
60static void dss_clk_disable_no_ctx(enum dss_clock clks);
61
62static char *def_disp_name; 48static char *def_disp_name;
63module_param_named(def_disp, def_disp_name, charp, 0); 49module_param_named(def_disp, def_disp_name, charp, 0);
64MODULE_PARM_DESC(def_disp_name, "default display name"); 50MODULE_PARM_DESC(def_disp, "default display name");
65 51
66#ifdef DEBUG 52#ifdef DEBUG
67unsigned int dss_debug; 53unsigned int dss_debug;
68module_param_named(debug, dss_debug, bool, 0644); 54module_param_named(debug, dss_debug, bool, 0644);
69#endif 55#endif
70 56
71/* CONTEXT */ 57static int omap_dss_register_device(struct omap_dss_device *);
72static int dss_get_ctx_id(void) 58static void omap_dss_unregister_device(struct omap_dss_device *);
73{
74 struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
75 int r;
76
77 if (!pdata->get_last_off_on_transaction_id)
78 return 0;
79 r = pdata->get_last_off_on_transaction_id(&core.pdev->dev);
80 if (r < 0) {
81 dev_err(&core.pdev->dev, "getting transaction ID failed, "
82 "will force context restore\n");
83 r = -1;
84 }
85 return r;
86}
87
88int dss_need_ctx_restore(void)
89{
90 int id = dss_get_ctx_id();
91
92 if (id < 0 || id != core.ctx_id) {
93 DSSDBG("ctx id %d -> id %d\n",
94 core.ctx_id, id);
95 core.ctx_id = id;
96 return 1;
97 } else {
98 return 0;
99 }
100}
101
102static void save_all_ctx(void)
103{
104 DSSDBG("save context\n");
105
106 dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
107
108 dss_save_context();
109 dispc_save_context();
110#ifdef CONFIG_OMAP2_DSS_DSI
111 dsi_save_context();
112#endif
113
114 dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
115}
116
117static void restore_all_ctx(void)
118{
119 DSSDBG("restore context\n");
120
121 dss_clk_enable_all_no_ctx();
122
123 dss_restore_context();
124 dispc_restore_context();
125#ifdef CONFIG_OMAP2_DSS_DSI
126 dsi_restore_context();
127#endif
128
129 dss_clk_disable_all_no_ctx();
130}
131
132#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
133/* CLOCKS */
134static void core_dump_clocks(struct seq_file *s)
135{
136 int i;
137 struct clk *clocks[5] = {
138 core.dss_ick,
139 core.dss1_fck,
140 core.dss2_fck,
141 core.dss_54m_fck,
142 core.dss_96m_fck
143 };
144
145 seq_printf(s, "- CORE -\n");
146
147 seq_printf(s, "internal clk count\t\t%u\n", core.num_clks_enabled);
148
149 for (i = 0; i < 5; i++) {
150 if (!clocks[i])
151 continue;
152 seq_printf(s, "%-15s\t%lu\t%d\n",
153 clocks[i]->name,
154 clk_get_rate(clocks[i]),
155 clocks[i]->usecount);
156 }
157}
158#endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */
159
160static int dss_get_clock(struct clk **clock, const char *clk_name)
161{
162 struct clk *clk;
163
164 clk = clk_get(&core.pdev->dev, clk_name);
165
166 if (IS_ERR(clk)) {
167 DSSERR("can't get clock %s", clk_name);
168 return PTR_ERR(clk);
169 }
170
171 *clock = clk;
172
173 DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
174
175 return 0;
176}
177
178static int dss_get_clocks(void)
179{
180 int r;
181
182 core.dss_ick = NULL;
183 core.dss1_fck = NULL;
184 core.dss2_fck = NULL;
185 core.dss_54m_fck = NULL;
186 core.dss_96m_fck = NULL;
187
188 r = dss_get_clock(&core.dss_ick, "ick");
189 if (r)
190 goto err;
191
192 r = dss_get_clock(&core.dss1_fck, "dss1_fck");
193 if (r)
194 goto err;
195
196 r = dss_get_clock(&core.dss2_fck, "dss2_fck");
197 if (r)
198 goto err;
199
200 r = dss_get_clock(&core.dss_54m_fck, "tv_fck");
201 if (r)
202 goto err;
203
204 r = dss_get_clock(&core.dss_96m_fck, "video_fck");
205 if (r)
206 goto err;
207
208 return 0;
209
210err:
211 if (core.dss_ick)
212 clk_put(core.dss_ick);
213 if (core.dss1_fck)
214 clk_put(core.dss1_fck);
215 if (core.dss2_fck)
216 clk_put(core.dss2_fck);
217 if (core.dss_54m_fck)
218 clk_put(core.dss_54m_fck);
219 if (core.dss_96m_fck)
220 clk_put(core.dss_96m_fck);
221
222 return r;
223}
224
225static void dss_put_clocks(void)
226{
227 if (core.dss_96m_fck)
228 clk_put(core.dss_96m_fck);
229 clk_put(core.dss_54m_fck);
230 clk_put(core.dss1_fck);
231 clk_put(core.dss2_fck);
232 clk_put(core.dss_ick);
233}
234
235unsigned long dss_clk_get_rate(enum dss_clock clk)
236{
237 switch (clk) {
238 case DSS_CLK_ICK:
239 return clk_get_rate(core.dss_ick);
240 case DSS_CLK_FCK1:
241 return clk_get_rate(core.dss1_fck);
242 case DSS_CLK_FCK2:
243 return clk_get_rate(core.dss2_fck);
244 case DSS_CLK_54M:
245 return clk_get_rate(core.dss_54m_fck);
246 case DSS_CLK_96M:
247 return clk_get_rate(core.dss_96m_fck);
248 }
249
250 BUG();
251 return 0;
252}
253
254static unsigned count_clk_bits(enum dss_clock clks)
255{
256 unsigned num_clks = 0;
257
258 if (clks & DSS_CLK_ICK)
259 ++num_clks;
260 if (clks & DSS_CLK_FCK1)
261 ++num_clks;
262 if (clks & DSS_CLK_FCK2)
263 ++num_clks;
264 if (clks & DSS_CLK_54M)
265 ++num_clks;
266 if (clks & DSS_CLK_96M)
267 ++num_clks;
268
269 return num_clks;
270}
271
272static void dss_clk_enable_no_ctx(enum dss_clock clks)
273{
274 unsigned num_clks = count_clk_bits(clks);
275
276 if (clks & DSS_CLK_ICK)
277 clk_enable(core.dss_ick);
278 if (clks & DSS_CLK_FCK1)
279 clk_enable(core.dss1_fck);
280 if (clks & DSS_CLK_FCK2)
281 clk_enable(core.dss2_fck);
282 if (clks & DSS_CLK_54M)
283 clk_enable(core.dss_54m_fck);
284 if (clks & DSS_CLK_96M)
285 clk_enable(core.dss_96m_fck);
286
287 core.num_clks_enabled += num_clks;
288}
289
290void dss_clk_enable(enum dss_clock clks)
291{
292 bool check_ctx = core.num_clks_enabled == 0;
293
294 dss_clk_enable_no_ctx(clks);
295
296 if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore())
297 restore_all_ctx();
298}
299
300static void dss_clk_disable_no_ctx(enum dss_clock clks)
301{
302 unsigned num_clks = count_clk_bits(clks);
303
304 if (clks & DSS_CLK_ICK)
305 clk_disable(core.dss_ick);
306 if (clks & DSS_CLK_FCK1)
307 clk_disable(core.dss1_fck);
308 if (clks & DSS_CLK_FCK2)
309 clk_disable(core.dss2_fck);
310 if (clks & DSS_CLK_54M)
311 clk_disable(core.dss_54m_fck);
312 if (clks & DSS_CLK_96M)
313 clk_disable(core.dss_96m_fck);
314
315 core.num_clks_enabled -= num_clks;
316}
317
318void dss_clk_disable(enum dss_clock clks)
319{
320 if (cpu_is_omap34xx()) {
321 unsigned num_clks = count_clk_bits(clks);
322
323 BUG_ON(core.num_clks_enabled < num_clks);
324
325 if (core.num_clks_enabled == num_clks)
326 save_all_ctx();
327 }
328
329 dss_clk_disable_no_ctx(clks);
330}
331
332static void dss_clk_enable_all_no_ctx(void)
333{
334 enum dss_clock clks;
335
336 clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
337 if (cpu_is_omap34xx())
338 clks |= DSS_CLK_96M;
339 dss_clk_enable_no_ctx(clks);
340}
341
342static void dss_clk_disable_all_no_ctx(void)
343{
344 enum dss_clock clks;
345
346 clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
347 if (cpu_is_omap34xx())
348 clks |= DSS_CLK_96M;
349 dss_clk_disable_no_ctx(clks);
350}
351
352static void dss_clk_disable_all(void)
353{
354 enum dss_clock clks;
355
356 clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
357 if (cpu_is_omap34xx())
358 clks |= DSS_CLK_96M;
359 dss_clk_disable(clks);
360}
361 59
362/* REGULATORS */ 60/* REGULATORS */
363 61
@@ -389,32 +87,7 @@ struct regulator *dss_get_vdds_sdi(void)
389 return reg; 87 return reg;
390} 88}
391 89
392struct regulator *dss_get_vdda_dac(void)
393{
394 struct regulator *reg;
395
396 if (core.vdda_dac_reg != NULL)
397 return core.vdda_dac_reg;
398
399 reg = regulator_get(&core.pdev->dev, "vdda_dac");
400 if (!IS_ERR(reg))
401 core.vdda_dac_reg = reg;
402
403 return reg;
404}
405
406/* DEBUGFS */
407#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) 90#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
408static void dss_debug_dump_clocks(struct seq_file *s)
409{
410 core_dump_clocks(s);
411 dss_dump_clocks(s);
412 dispc_dump_clocks(s);
413#ifdef CONFIG_OMAP2_DSS_DSI
414 dsi_dump_clocks(s);
415#endif
416}
417
418static int dss_debug_show(struct seq_file *s, void *unused) 91static int dss_debug_show(struct seq_file *s, void *unused)
419{ 92{
420 void (*func)(struct seq_file *) = s->private; 93 void (*func)(struct seq_file *) = s->private;
@@ -454,8 +127,7 @@ static int dss_initialize_debugfs(void)
454#endif 127#endif
455 128
456#if defined(CONFIG_OMAP2_DSS_DSI) && defined(CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS) 129#if defined(CONFIG_OMAP2_DSS_DSI) && defined(CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS)
457 debugfs_create_file("dsi_irq", S_IRUGO, dss_debugfs_dir, 130 dsi_create_debugfs_files_irq(dss_debugfs_dir, &dss_debug_fops);
458 &dsi_dump_irqs, &dss_debug_fops);
459#endif 131#endif
460 132
461 debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir, 133 debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir,
@@ -467,8 +139,7 @@ static int dss_initialize_debugfs(void)
467 &rfbi_dump_regs, &dss_debug_fops); 139 &rfbi_dump_regs, &dss_debug_fops);
468#endif 140#endif
469#ifdef CONFIG_OMAP2_DSS_DSI 141#ifdef CONFIG_OMAP2_DSS_DSI
470 debugfs_create_file("dsi", S_IRUGO, dss_debugfs_dir, 142 dsi_create_debugfs_files_reg(dss_debugfs_dir, &dss_debug_fops);
471 &dsi_dump_regs, &dss_debug_fops);
472#endif 143#endif
473#ifdef CONFIG_OMAP2_DSS_VENC 144#ifdef CONFIG_OMAP2_DSS_VENC
474 debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir, 145 debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir,
@@ -496,72 +167,53 @@ static inline void dss_uninitialize_debugfs(void)
496static int omap_dss_probe(struct platform_device *pdev) 167static int omap_dss_probe(struct platform_device *pdev)
497{ 168{
498 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 169 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
499 int skip_init = 0;
500 int r; 170 int r;
501 int i; 171 int i;
502 172
503 core.pdev = pdev; 173 core.pdev = pdev;
504 174
175 dss_features_init();
176
505 dss_init_overlay_managers(pdev); 177 dss_init_overlay_managers(pdev);
506 dss_init_overlays(pdev); 178 dss_init_overlays(pdev);
507 179
508 r = dss_get_clocks(); 180 r = dss_init_platform_driver();
509 if (r)
510 goto err_clocks;
511
512 dss_clk_enable_all_no_ctx();
513
514 core.ctx_id = dss_get_ctx_id();
515 DSSDBG("initial ctx id %u\n", core.ctx_id);
516
517#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
518 /* DISPC_CONTROL */
519 if (omap_readl(0x48050440) & 1) /* LCD enabled? */
520 skip_init = 1;
521#endif
522
523 r = dss_init(skip_init);
524 if (r) { 181 if (r) {
525 DSSERR("Failed to initialize DSS\n"); 182 DSSERR("Failed to initialize DSS platform driver\n");
526 goto err_dss; 183 goto err_dss;
527 } 184 }
528 185
529 r = rfbi_init(); 186 /* keep clocks enabled to prevent context saves/restores during init */
530 if (r) { 187 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
531 DSSERR("Failed to initialize rfbi\n");
532 goto err_rfbi;
533 }
534 188
535 r = dpi_init(pdev); 189 r = rfbi_init_platform_driver();
536 if (r) { 190 if (r) {
537 DSSERR("Failed to initialize dpi\n"); 191 DSSERR("Failed to initialize rfbi platform driver\n");
538 goto err_dpi; 192 goto err_rfbi;
539 } 193 }
540 194
541 r = dispc_init(); 195 r = dispc_init_platform_driver();
542 if (r) { 196 if (r) {
543 DSSERR("Failed to initialize dispc\n"); 197 DSSERR("Failed to initialize dispc platform driver\n");
544 goto err_dispc; 198 goto err_dispc;
545 } 199 }
546 200
547 r = venc_init(pdev); 201 r = venc_init_platform_driver();
548 if (r) { 202 if (r) {
549 DSSERR("Failed to initialize venc\n"); 203 DSSERR("Failed to initialize venc platform driver\n");
550 goto err_venc; 204 goto err_venc;
551 } 205 }
552 206
553 if (cpu_is_omap34xx()) { 207 r = dsi_init_platform_driver();
554 r = sdi_init(skip_init); 208 if (r) {
555 if (r) { 209 DSSERR("Failed to initialize DSI platform driver\n");
556 DSSERR("Failed to initialize SDI\n"); 210 goto err_dsi;
557 goto err_sdi; 211 }
558 }
559 212
560 r = dsi_init(pdev); 213 r = hdmi_init_platform_driver();
561 if (r) { 214 if (r) {
562 DSSERR("Failed to initialize DSI\n"); 215 DSSERR("Failed to initialize hdmi\n");
563 goto err_dsi; 216 goto err_hdmi;
564 }
565 } 217 }
566 218
567 r = dss_initialize_debugfs(); 219 r = dss_initialize_debugfs();
@@ -586,32 +238,25 @@ static int omap_dss_probe(struct platform_device *pdev)
586 pdata->default_device = dssdev; 238 pdata->default_device = dssdev;
587 } 239 }
588 240
589 dss_clk_disable_all(); 241 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
590 242
591 return 0; 243 return 0;
592 244
593err_register: 245err_register:
594 dss_uninitialize_debugfs(); 246 dss_uninitialize_debugfs();
595err_debugfs: 247err_debugfs:
596 if (cpu_is_omap34xx()) 248 hdmi_uninit_platform_driver();
597 dsi_exit(); 249err_hdmi:
250 dsi_uninit_platform_driver();
598err_dsi: 251err_dsi:
599 if (cpu_is_omap34xx()) 252 venc_uninit_platform_driver();
600 sdi_exit();
601err_sdi:
602 venc_exit();
603err_venc: 253err_venc:
604 dispc_exit(); 254 dispc_uninit_platform_driver();
605err_dispc: 255err_dispc:
606 dpi_exit(); 256 rfbi_uninit_platform_driver();
607err_dpi:
608 rfbi_exit();
609err_rfbi: 257err_rfbi:
610 dss_exit(); 258 dss_uninit_platform_driver();
611err_dss: 259err_dss:
612 dss_clk_disable_all_no_ctx();
613 dss_put_clocks();
614err_clocks:
615 260
616 return r; 261 return r;
617} 262}
@@ -620,61 +265,15 @@ static int omap_dss_remove(struct platform_device *pdev)
620{ 265{
621 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 266 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
622 int i; 267 int i;
623 int c;
624 268
625 dss_uninitialize_debugfs(); 269 dss_uninitialize_debugfs();
626 270
627 venc_exit(); 271 venc_uninit_platform_driver();
628 dispc_exit(); 272 dispc_uninit_platform_driver();
629 dpi_exit(); 273 rfbi_uninit_platform_driver();
630 rfbi_exit(); 274 dsi_uninit_platform_driver();
631 if (cpu_is_omap34xx()) { 275 hdmi_uninit_platform_driver();
632 dsi_exit(); 276 dss_uninit_platform_driver();
633 sdi_exit();
634 }
635
636 dss_exit();
637
638 /* these should be removed at some point */
639 c = core.dss_ick->usecount;
640 if (c > 0) {
641 DSSERR("warning: dss_ick usecount %d, disabling\n", c);
642 while (c-- > 0)
643 clk_disable(core.dss_ick);
644 }
645
646 c = core.dss1_fck->usecount;
647 if (c > 0) {
648 DSSERR("warning: dss1_fck usecount %d, disabling\n", c);
649 while (c-- > 0)
650 clk_disable(core.dss1_fck);
651 }
652
653 c = core.dss2_fck->usecount;
654 if (c > 0) {
655 DSSERR("warning: dss2_fck usecount %d, disabling\n", c);
656 while (c-- > 0)
657 clk_disable(core.dss2_fck);
658 }
659
660 c = core.dss_54m_fck->usecount;
661 if (c > 0) {
662 DSSERR("warning: dss_54m_fck usecount %d, disabling\n", c);
663 while (c-- > 0)
664 clk_disable(core.dss_54m_fck);
665 }
666
667 if (core.dss_96m_fck) {
668 c = core.dss_96m_fck->usecount;
669 if (c > 0) {
670 DSSERR("warning: dss_96m_fck usecount %d, disabling\n",
671 c);
672 while (c-- > 0)
673 clk_disable(core.dss_96m_fck);
674 }
675 }
676
677 dss_put_clocks();
678 277
679 dss_uninit_overlays(pdev); 278 dss_uninit_overlays(pdev);
680 dss_uninit_overlay_managers(pdev); 279 dss_uninit_overlay_managers(pdev);
@@ -882,7 +481,7 @@ static void omap_dss_dev_release(struct device *dev)
882 reset_device(dev, 0); 481 reset_device(dev, 0);
883} 482}
884 483
885int omap_dss_register_device(struct omap_dss_device *dssdev) 484static int omap_dss_register_device(struct omap_dss_device *dssdev)
886{ 485{
887 static int dev_num; 486 static int dev_num;
888 487
@@ -896,7 +495,7 @@ int omap_dss_register_device(struct omap_dss_device *dssdev)
896 return device_register(&dssdev->dev); 495 return device_register(&dssdev->dev);
897} 496}
898 497
899void omap_dss_unregister_device(struct omap_dss_device *dssdev) 498static void omap_dss_unregister_device(struct omap_dss_device *dssdev)
900{ 499{
901 device_unregister(&dssdev->dev); 500 device_unregister(&dssdev->dev);
902} 501}
@@ -962,11 +561,6 @@ static void __exit omap_dss_exit(void)
962 core.vdds_sdi_reg = NULL; 561 core.vdds_sdi_reg = NULL;
963 } 562 }
964 563
965 if (core.vdda_dac_reg != NULL) {
966 regulator_put(core.vdda_dac_reg);
967 core.vdda_dac_reg = NULL;
968 }
969
970 platform_driver_unregister(&omap_dss_driver); 564 platform_driver_unregister(&omap_dss_driver);
971 565
972 omap_dss_bus_unregister(); 566 omap_dss_bus_unregister();
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 5ecdc0004094..7a9a2e7d9685 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -32,97 +32,19 @@
32#include <linux/delay.h> 32#include <linux/delay.h>
33#include <linux/workqueue.h> 33#include <linux/workqueue.h>
34#include <linux/hardirq.h> 34#include <linux/hardirq.h>
35#include <linux/interrupt.h>
35 36
36#include <plat/sram.h> 37#include <plat/sram.h>
37#include <plat/clock.h> 38#include <plat/clock.h>
38 39
39#include <plat/display.h> 40#include <video/omapdss.h>
40 41
41#include "dss.h" 42#include "dss.h"
43#include "dss_features.h"
44#include "dispc.h"
42 45
43/* DISPC */ 46/* DISPC */
44#define DISPC_BASE 0x48050400 47#define DISPC_SZ_REGS SZ_4K
45
46#define DISPC_SZ_REGS SZ_1K
47
48struct dispc_reg { u16 idx; };
49
50#define DISPC_REG(idx) ((const struct dispc_reg) { idx })
51
52/* DISPC common */
53#define DISPC_REVISION DISPC_REG(0x0000)
54#define DISPC_SYSCONFIG DISPC_REG(0x0010)
55#define DISPC_SYSSTATUS DISPC_REG(0x0014)
56#define DISPC_IRQSTATUS DISPC_REG(0x0018)
57#define DISPC_IRQENABLE DISPC_REG(0x001C)
58#define DISPC_CONTROL DISPC_REG(0x0040)
59#define DISPC_CONFIG DISPC_REG(0x0044)
60#define DISPC_CAPABLE DISPC_REG(0x0048)
61#define DISPC_DEFAULT_COLOR0 DISPC_REG(0x004C)
62#define DISPC_DEFAULT_COLOR1 DISPC_REG(0x0050)
63#define DISPC_TRANS_COLOR0 DISPC_REG(0x0054)
64#define DISPC_TRANS_COLOR1 DISPC_REG(0x0058)
65#define DISPC_LINE_STATUS DISPC_REG(0x005C)
66#define DISPC_LINE_NUMBER DISPC_REG(0x0060)
67#define DISPC_TIMING_H DISPC_REG(0x0064)
68#define DISPC_TIMING_V DISPC_REG(0x0068)
69#define DISPC_POL_FREQ DISPC_REG(0x006C)
70#define DISPC_DIVISOR DISPC_REG(0x0070)
71#define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074)
72#define DISPC_SIZE_DIG DISPC_REG(0x0078)
73#define DISPC_SIZE_LCD DISPC_REG(0x007C)
74
75/* DISPC GFX plane */
76#define DISPC_GFX_BA0 DISPC_REG(0x0080)
77#define DISPC_GFX_BA1 DISPC_REG(0x0084)
78#define DISPC_GFX_POSITION DISPC_REG(0x0088)
79#define DISPC_GFX_SIZE DISPC_REG(0x008C)
80#define DISPC_GFX_ATTRIBUTES DISPC_REG(0x00A0)
81#define DISPC_GFX_FIFO_THRESHOLD DISPC_REG(0x00A4)
82#define DISPC_GFX_FIFO_SIZE_STATUS DISPC_REG(0x00A8)
83#define DISPC_GFX_ROW_INC DISPC_REG(0x00AC)
84#define DISPC_GFX_PIXEL_INC DISPC_REG(0x00B0)
85#define DISPC_GFX_WINDOW_SKIP DISPC_REG(0x00B4)
86#define DISPC_GFX_TABLE_BA DISPC_REG(0x00B8)
87
88#define DISPC_DATA_CYCLE1 DISPC_REG(0x01D4)
89#define DISPC_DATA_CYCLE2 DISPC_REG(0x01D8)
90#define DISPC_DATA_CYCLE3 DISPC_REG(0x01DC)
91
92#define DISPC_CPR_COEF_R DISPC_REG(0x0220)
93#define DISPC_CPR_COEF_G DISPC_REG(0x0224)
94#define DISPC_CPR_COEF_B DISPC_REG(0x0228)
95
96#define DISPC_GFX_PRELOAD DISPC_REG(0x022C)
97
98/* DISPC Video plane, n = 0 for VID1 and n = 1 for VID2 */
99#define DISPC_VID_REG(n, idx) DISPC_REG(0x00BC + (n)*0x90 + idx)
100
101#define DISPC_VID_BA0(n) DISPC_VID_REG(n, 0x0000)
102#define DISPC_VID_BA1(n) DISPC_VID_REG(n, 0x0004)
103#define DISPC_VID_POSITION(n) DISPC_VID_REG(n, 0x0008)
104#define DISPC_VID_SIZE(n) DISPC_VID_REG(n, 0x000C)
105#define DISPC_VID_ATTRIBUTES(n) DISPC_VID_REG(n, 0x0010)
106#define DISPC_VID_FIFO_THRESHOLD(n) DISPC_VID_REG(n, 0x0014)
107#define DISPC_VID_FIFO_SIZE_STATUS(n) DISPC_VID_REG(n, 0x0018)
108#define DISPC_VID_ROW_INC(n) DISPC_VID_REG(n, 0x001C)
109#define DISPC_VID_PIXEL_INC(n) DISPC_VID_REG(n, 0x0020)
110#define DISPC_VID_FIR(n) DISPC_VID_REG(n, 0x0024)
111#define DISPC_VID_PICTURE_SIZE(n) DISPC_VID_REG(n, 0x0028)
112#define DISPC_VID_ACCU0(n) DISPC_VID_REG(n, 0x002C)
113#define DISPC_VID_ACCU1(n) DISPC_VID_REG(n, 0x0030)
114
115/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
116#define DISPC_VID_FIR_COEF_H(n, i) DISPC_REG(0x00F0 + (n)*0x90 + (i)*0x8)
117/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
118#define DISPC_VID_FIR_COEF_HV(n, i) DISPC_REG(0x00F4 + (n)*0x90 + (i)*0x8)
119/* coef index i = {0, 1, 2, 3, 4} */
120#define DISPC_VID_CONV_COEF(n, i) DISPC_REG(0x0130 + (n)*0x90 + (i)*0x4)
121/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
122#define DISPC_VID_FIR_COEF_V(n, i) DISPC_REG(0x01E0 + (n)*0x20 + (i)*0x4)
123
124#define DISPC_VID_PRELOAD(n) DISPC_REG(0x230 + (n)*0x04)
125
126 48
127#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \ 49#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
128 DISPC_IRQ_OCP_ERR | \ 50 DISPC_IRQ_OCP_ERR | \
@@ -139,16 +61,28 @@ struct omap_dispc_isr_data {
139 u32 mask; 61 u32 mask;
140}; 62};
141 63
64struct dispc_h_coef {
65 s8 hc4;
66 s8 hc3;
67 u8 hc2;
68 s8 hc1;
69 s8 hc0;
70};
71
72struct dispc_v_coef {
73 s8 vc22;
74 s8 vc2;
75 u8 vc1;
76 s8 vc0;
77 s8 vc00;
78};
79
142#define REG_GET(idx, start, end) \ 80#define REG_GET(idx, start, end) \
143 FLD_GET(dispc_read_reg(idx), start, end) 81 FLD_GET(dispc_read_reg(idx), start, end)
144 82
145#define REG_FLD_MOD(idx, val, start, end) \ 83#define REG_FLD_MOD(idx, val, start, end) \
146 dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end)) 84 dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
147 85
148static const struct dispc_reg dispc_reg_att[] = { DISPC_GFX_ATTRIBUTES,
149 DISPC_VID_ATTRIBUTES(0),
150 DISPC_VID_ATTRIBUTES(1) };
151
152struct dispc_irq_stats { 86struct dispc_irq_stats {
153 unsigned long last_reset; 87 unsigned long last_reset;
154 unsigned irq_count; 88 unsigned irq_count;
@@ -156,7 +90,9 @@ struct dispc_irq_stats {
156}; 90};
157 91
158static struct { 92static struct {
93 struct platform_device *pdev;
159 void __iomem *base; 94 void __iomem *base;
95 int irq;
160 96
161 u32 fifo_size[3]; 97 u32 fifo_size[3];
162 98
@@ -174,25 +110,38 @@ static struct {
174#endif 110#endif
175} dispc; 111} dispc;
176 112
113enum omap_color_component {
114 /* used for all color formats for OMAP3 and earlier
115 * and for RGB and Y color component on OMAP4
116 */
117 DISPC_COLOR_COMPONENT_RGB_Y = 1 << 0,
118 /* used for UV component for
119 * OMAP_DSS_COLOR_YUV2, OMAP_DSS_COLOR_UYVY, OMAP_DSS_COLOR_NV12
120 * color formats on OMAP4
121 */
122 DISPC_COLOR_COMPONENT_UV = 1 << 1,
123};
124
177static void _omap_dispc_set_irqs(void); 125static void _omap_dispc_set_irqs(void);
178 126
179static inline void dispc_write_reg(const struct dispc_reg idx, u32 val) 127static inline void dispc_write_reg(const u16 idx, u32 val)
180{ 128{
181 __raw_writel(val, dispc.base + idx.idx); 129 __raw_writel(val, dispc.base + idx);
182} 130}
183 131
184static inline u32 dispc_read_reg(const struct dispc_reg idx) 132static inline u32 dispc_read_reg(const u16 idx)
185{ 133{
186 return __raw_readl(dispc.base + idx.idx); 134 return __raw_readl(dispc.base + idx);
187} 135}
188 136
189#define SR(reg) \ 137#define SR(reg) \
190 dispc.ctx[(DISPC_##reg).idx / sizeof(u32)] = dispc_read_reg(DISPC_##reg) 138 dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
191#define RR(reg) \ 139#define RR(reg) \
192 dispc_write_reg(DISPC_##reg, dispc.ctx[(DISPC_##reg).idx / sizeof(u32)]) 140 dispc_write_reg(DISPC_##reg, dispc.ctx[DISPC_##reg / sizeof(u32)])
193 141
194void dispc_save_context(void) 142void dispc_save_context(void)
195{ 143{
144 int i;
196 if (cpu_is_omap24xx()) 145 if (cpu_is_omap24xx())
197 return; 146 return;
198 147
@@ -200,280 +149,320 @@ void dispc_save_context(void)
200 SR(IRQENABLE); 149 SR(IRQENABLE);
201 SR(CONTROL); 150 SR(CONTROL);
202 SR(CONFIG); 151 SR(CONFIG);
203 SR(DEFAULT_COLOR0); 152 SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD));
204 SR(DEFAULT_COLOR1); 153 SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT));
205 SR(TRANS_COLOR0); 154 SR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD));
206 SR(TRANS_COLOR1); 155 SR(TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT));
207 SR(LINE_NUMBER); 156 SR(LINE_NUMBER);
208 SR(TIMING_H); 157 SR(TIMING_H(OMAP_DSS_CHANNEL_LCD));
209 SR(TIMING_V); 158 SR(TIMING_V(OMAP_DSS_CHANNEL_LCD));
210 SR(POL_FREQ); 159 SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
211 SR(DIVISOR); 160 SR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
212 SR(GLOBAL_ALPHA); 161 SR(GLOBAL_ALPHA);
213 SR(SIZE_DIG); 162 SR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
214 SR(SIZE_LCD); 163 SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
215 164 if (dss_has_feature(FEAT_MGR_LCD2)) {
216 SR(GFX_BA0); 165 SR(CONTROL2);
217 SR(GFX_BA1); 166 SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2));
218 SR(GFX_POSITION); 167 SR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2));
219 SR(GFX_SIZE); 168 SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD2));
220 SR(GFX_ATTRIBUTES); 169 SR(TIMING_H(OMAP_DSS_CHANNEL_LCD2));
221 SR(GFX_FIFO_THRESHOLD); 170 SR(TIMING_V(OMAP_DSS_CHANNEL_LCD2));
222 SR(GFX_ROW_INC); 171 SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD2));
223 SR(GFX_PIXEL_INC); 172 SR(DIVISORo(OMAP_DSS_CHANNEL_LCD2));
224 SR(GFX_WINDOW_SKIP); 173 SR(CONFIG2);
225 SR(GFX_TABLE_BA); 174 }
226 175
227 SR(DATA_CYCLE1); 176 SR(OVL_BA0(OMAP_DSS_GFX));
228 SR(DATA_CYCLE2); 177 SR(OVL_BA1(OMAP_DSS_GFX));
229 SR(DATA_CYCLE3); 178 SR(OVL_POSITION(OMAP_DSS_GFX));
230 179 SR(OVL_SIZE(OMAP_DSS_GFX));
231 SR(CPR_COEF_R); 180 SR(OVL_ATTRIBUTES(OMAP_DSS_GFX));
232 SR(CPR_COEF_G); 181 SR(OVL_FIFO_THRESHOLD(OMAP_DSS_GFX));
233 SR(CPR_COEF_B); 182 SR(OVL_ROW_INC(OMAP_DSS_GFX));
234 183 SR(OVL_PIXEL_INC(OMAP_DSS_GFX));
235 SR(GFX_PRELOAD); 184 SR(OVL_WINDOW_SKIP(OMAP_DSS_GFX));
185 SR(OVL_TABLE_BA(OMAP_DSS_GFX));
186
187 SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD));
188 SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
189 SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
190
191 SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
192 SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
193 SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
194 if (dss_has_feature(FEAT_MGR_LCD2)) {
195 SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
196 SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
197 SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
198
199 SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
200 SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
201 SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
202 }
203
204 SR(OVL_PRELOAD(OMAP_DSS_GFX));
236 205
237 /* VID1 */ 206 /* VID1 */
238 SR(VID_BA0(0)); 207 SR(OVL_BA0(OMAP_DSS_VIDEO1));
239 SR(VID_BA1(0)); 208 SR(OVL_BA1(OMAP_DSS_VIDEO1));
240 SR(VID_POSITION(0)); 209 SR(OVL_POSITION(OMAP_DSS_VIDEO1));
241 SR(VID_SIZE(0)); 210 SR(OVL_SIZE(OMAP_DSS_VIDEO1));
242 SR(VID_ATTRIBUTES(0)); 211 SR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO1));
243 SR(VID_FIFO_THRESHOLD(0)); 212 SR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1));
244 SR(VID_ROW_INC(0)); 213 SR(OVL_ROW_INC(OMAP_DSS_VIDEO1));
245 SR(VID_PIXEL_INC(0)); 214 SR(OVL_PIXEL_INC(OMAP_DSS_VIDEO1));
246 SR(VID_FIR(0)); 215 SR(OVL_FIR(OMAP_DSS_VIDEO1));
247 SR(VID_PICTURE_SIZE(0)); 216 SR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1));
248 SR(VID_ACCU0(0)); 217 SR(OVL_ACCU0(OMAP_DSS_VIDEO1));
249 SR(VID_ACCU1(0)); 218 SR(OVL_ACCU1(OMAP_DSS_VIDEO1));
250 219
251 SR(VID_FIR_COEF_H(0, 0)); 220 for (i = 0; i < 8; i++)
252 SR(VID_FIR_COEF_H(0, 1)); 221 SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, i));
253 SR(VID_FIR_COEF_H(0, 2)); 222
254 SR(VID_FIR_COEF_H(0, 3)); 223 for (i = 0; i < 8; i++)
255 SR(VID_FIR_COEF_H(0, 4)); 224 SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, i));
256 SR(VID_FIR_COEF_H(0, 5)); 225
257 SR(VID_FIR_COEF_H(0, 6)); 226 for (i = 0; i < 5; i++)
258 SR(VID_FIR_COEF_H(0, 7)); 227 SR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i));
259 228
260 SR(VID_FIR_COEF_HV(0, 0)); 229 for (i = 0; i < 8; i++)
261 SR(VID_FIR_COEF_HV(0, 1)); 230 SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
262 SR(VID_FIR_COEF_HV(0, 2)); 231
263 SR(VID_FIR_COEF_HV(0, 3)); 232 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
264 SR(VID_FIR_COEF_HV(0, 4)); 233 SR(OVL_BA0_UV(OMAP_DSS_VIDEO1));
265 SR(VID_FIR_COEF_HV(0, 5)); 234 SR(OVL_BA1_UV(OMAP_DSS_VIDEO1));
266 SR(VID_FIR_COEF_HV(0, 6)); 235 SR(OVL_FIR2(OMAP_DSS_VIDEO1));
267 SR(VID_FIR_COEF_HV(0, 7)); 236 SR(OVL_ACCU2_0(OMAP_DSS_VIDEO1));
268 237 SR(OVL_ACCU2_1(OMAP_DSS_VIDEO1));
269 SR(VID_CONV_COEF(0, 0)); 238
270 SR(VID_CONV_COEF(0, 1)); 239 for (i = 0; i < 8; i++)
271 SR(VID_CONV_COEF(0, 2)); 240 SR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, i));
272 SR(VID_CONV_COEF(0, 3)); 241
273 SR(VID_CONV_COEF(0, 4)); 242 for (i = 0; i < 8; i++)
274 243 SR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, i));
275 SR(VID_FIR_COEF_V(0, 0)); 244
276 SR(VID_FIR_COEF_V(0, 1)); 245 for (i = 0; i < 8; i++)
277 SR(VID_FIR_COEF_V(0, 2)); 246 SR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, i));
278 SR(VID_FIR_COEF_V(0, 3)); 247 }
279 SR(VID_FIR_COEF_V(0, 4)); 248 if (dss_has_feature(FEAT_ATTR2))
280 SR(VID_FIR_COEF_V(0, 5)); 249 SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
281 SR(VID_FIR_COEF_V(0, 6)); 250
282 SR(VID_FIR_COEF_V(0, 7)); 251 SR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
283
284 SR(VID_PRELOAD(0));
285 252
286 /* VID2 */ 253 /* VID2 */
287 SR(VID_BA0(1)); 254 SR(OVL_BA0(OMAP_DSS_VIDEO2));
288 SR(VID_BA1(1)); 255 SR(OVL_BA1(OMAP_DSS_VIDEO2));
289 SR(VID_POSITION(1)); 256 SR(OVL_POSITION(OMAP_DSS_VIDEO2));
290 SR(VID_SIZE(1)); 257 SR(OVL_SIZE(OMAP_DSS_VIDEO2));
291 SR(VID_ATTRIBUTES(1)); 258 SR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO2));
292 SR(VID_FIFO_THRESHOLD(1)); 259 SR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2));
293 SR(VID_ROW_INC(1)); 260 SR(OVL_ROW_INC(OMAP_DSS_VIDEO2));
294 SR(VID_PIXEL_INC(1)); 261 SR(OVL_PIXEL_INC(OMAP_DSS_VIDEO2));
295 SR(VID_FIR(1)); 262 SR(OVL_FIR(OMAP_DSS_VIDEO2));
296 SR(VID_PICTURE_SIZE(1)); 263 SR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2));
297 SR(VID_ACCU0(1)); 264 SR(OVL_ACCU0(OMAP_DSS_VIDEO2));
298 SR(VID_ACCU1(1)); 265 SR(OVL_ACCU1(OMAP_DSS_VIDEO2));
299 266
300 SR(VID_FIR_COEF_H(1, 0)); 267 for (i = 0; i < 8; i++)
301 SR(VID_FIR_COEF_H(1, 1)); 268 SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, i));
302 SR(VID_FIR_COEF_H(1, 2)); 269
303 SR(VID_FIR_COEF_H(1, 3)); 270 for (i = 0; i < 8; i++)
304 SR(VID_FIR_COEF_H(1, 4)); 271 SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, i));
305 SR(VID_FIR_COEF_H(1, 5)); 272
306 SR(VID_FIR_COEF_H(1, 6)); 273 for (i = 0; i < 5; i++)
307 SR(VID_FIR_COEF_H(1, 7)); 274 SR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i));
308 275
309 SR(VID_FIR_COEF_HV(1, 0)); 276 for (i = 0; i < 8; i++)
310 SR(VID_FIR_COEF_HV(1, 1)); 277 SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
311 SR(VID_FIR_COEF_HV(1, 2)); 278
312 SR(VID_FIR_COEF_HV(1, 3)); 279 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
313 SR(VID_FIR_COEF_HV(1, 4)); 280 SR(OVL_BA0_UV(OMAP_DSS_VIDEO2));
314 SR(VID_FIR_COEF_HV(1, 5)); 281 SR(OVL_BA1_UV(OMAP_DSS_VIDEO2));
315 SR(VID_FIR_COEF_HV(1, 6)); 282 SR(OVL_FIR2(OMAP_DSS_VIDEO2));
316 SR(VID_FIR_COEF_HV(1, 7)); 283 SR(OVL_ACCU2_0(OMAP_DSS_VIDEO2));
317 284 SR(OVL_ACCU2_1(OMAP_DSS_VIDEO2));
318 SR(VID_CONV_COEF(1, 0)); 285
319 SR(VID_CONV_COEF(1, 1)); 286 for (i = 0; i < 8; i++)
320 SR(VID_CONV_COEF(1, 2)); 287 SR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, i));
321 SR(VID_CONV_COEF(1, 3)); 288
322 SR(VID_CONV_COEF(1, 4)); 289 for (i = 0; i < 8; i++)
323 290 SR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, i));
324 SR(VID_FIR_COEF_V(1, 0)); 291
325 SR(VID_FIR_COEF_V(1, 1)); 292 for (i = 0; i < 8; i++)
326 SR(VID_FIR_COEF_V(1, 2)); 293 SR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, i));
327 SR(VID_FIR_COEF_V(1, 3)); 294 }
328 SR(VID_FIR_COEF_V(1, 4)); 295 if (dss_has_feature(FEAT_ATTR2))
329 SR(VID_FIR_COEF_V(1, 5)); 296 SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
330 SR(VID_FIR_COEF_V(1, 6)); 297
331 SR(VID_FIR_COEF_V(1, 7)); 298 SR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
332 299
333 SR(VID_PRELOAD(1)); 300 if (dss_has_feature(FEAT_CORE_CLK_DIV))
301 SR(DIVISOR);
334} 302}
335 303
336void dispc_restore_context(void) 304void dispc_restore_context(void)
337{ 305{
306 int i;
338 RR(SYSCONFIG); 307 RR(SYSCONFIG);
339 /*RR(IRQENABLE);*/ 308 /*RR(IRQENABLE);*/
340 /*RR(CONTROL);*/ 309 /*RR(CONTROL);*/
341 RR(CONFIG); 310 RR(CONFIG);
342 RR(DEFAULT_COLOR0); 311 RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD));
343 RR(DEFAULT_COLOR1); 312 RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT));
344 RR(TRANS_COLOR0); 313 RR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD));
345 RR(TRANS_COLOR1); 314 RR(TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT));
346 RR(LINE_NUMBER); 315 RR(LINE_NUMBER);
347 RR(TIMING_H); 316 RR(TIMING_H(OMAP_DSS_CHANNEL_LCD));
348 RR(TIMING_V); 317 RR(TIMING_V(OMAP_DSS_CHANNEL_LCD));
349 RR(POL_FREQ); 318 RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
350 RR(DIVISOR); 319 RR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
351 RR(GLOBAL_ALPHA); 320 RR(GLOBAL_ALPHA);
352 RR(SIZE_DIG); 321 RR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
353 RR(SIZE_LCD); 322 RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
354 323 if (dss_has_feature(FEAT_MGR_LCD2)) {
355 RR(GFX_BA0); 324 RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2));
356 RR(GFX_BA1); 325 RR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2));
357 RR(GFX_POSITION); 326 RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD2));
358 RR(GFX_SIZE); 327 RR(TIMING_H(OMAP_DSS_CHANNEL_LCD2));
359 RR(GFX_ATTRIBUTES); 328 RR(TIMING_V(OMAP_DSS_CHANNEL_LCD2));
360 RR(GFX_FIFO_THRESHOLD); 329 RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD2));
361 RR(GFX_ROW_INC); 330 RR(DIVISORo(OMAP_DSS_CHANNEL_LCD2));
362 RR(GFX_PIXEL_INC); 331 RR(CONFIG2);
363 RR(GFX_WINDOW_SKIP); 332 }
364 RR(GFX_TABLE_BA); 333
365 334 RR(OVL_BA0(OMAP_DSS_GFX));
366 RR(DATA_CYCLE1); 335 RR(OVL_BA1(OMAP_DSS_GFX));
367 RR(DATA_CYCLE2); 336 RR(OVL_POSITION(OMAP_DSS_GFX));
368 RR(DATA_CYCLE3); 337 RR(OVL_SIZE(OMAP_DSS_GFX));
369 338 RR(OVL_ATTRIBUTES(OMAP_DSS_GFX));
370 RR(CPR_COEF_R); 339 RR(OVL_FIFO_THRESHOLD(OMAP_DSS_GFX));
371 RR(CPR_COEF_G); 340 RR(OVL_ROW_INC(OMAP_DSS_GFX));
372 RR(CPR_COEF_B); 341 RR(OVL_PIXEL_INC(OMAP_DSS_GFX));
373 342 RR(OVL_WINDOW_SKIP(OMAP_DSS_GFX));
374 RR(GFX_PRELOAD); 343 RR(OVL_TABLE_BA(OMAP_DSS_GFX));
344
345
346 RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD));
347 RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
348 RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
349
350 RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
351 RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
352 RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
353 if (dss_has_feature(FEAT_MGR_LCD2)) {
354 RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
355 RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
356 RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
357
358 RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
359 RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
360 RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
361 }
362
363 RR(OVL_PRELOAD(OMAP_DSS_GFX));
375 364
376 /* VID1 */ 365 /* VID1 */
377 RR(VID_BA0(0)); 366 RR(OVL_BA0(OMAP_DSS_VIDEO1));
378 RR(VID_BA1(0)); 367 RR(OVL_BA1(OMAP_DSS_VIDEO1));
379 RR(VID_POSITION(0)); 368 RR(OVL_POSITION(OMAP_DSS_VIDEO1));
380 RR(VID_SIZE(0)); 369 RR(OVL_SIZE(OMAP_DSS_VIDEO1));
381 RR(VID_ATTRIBUTES(0)); 370 RR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO1));
382 RR(VID_FIFO_THRESHOLD(0)); 371 RR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1));
383 RR(VID_ROW_INC(0)); 372 RR(OVL_ROW_INC(OMAP_DSS_VIDEO1));
384 RR(VID_PIXEL_INC(0)); 373 RR(OVL_PIXEL_INC(OMAP_DSS_VIDEO1));
385 RR(VID_FIR(0)); 374 RR(OVL_FIR(OMAP_DSS_VIDEO1));
386 RR(VID_PICTURE_SIZE(0)); 375 RR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1));
387 RR(VID_ACCU0(0)); 376 RR(OVL_ACCU0(OMAP_DSS_VIDEO1));
388 RR(VID_ACCU1(0)); 377 RR(OVL_ACCU1(OMAP_DSS_VIDEO1));
389 378
390 RR(VID_FIR_COEF_H(0, 0)); 379 for (i = 0; i < 8; i++)
391 RR(VID_FIR_COEF_H(0, 1)); 380 RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, i));
392 RR(VID_FIR_COEF_H(0, 2)); 381
393 RR(VID_FIR_COEF_H(0, 3)); 382 for (i = 0; i < 8; i++)
394 RR(VID_FIR_COEF_H(0, 4)); 383 RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, i));
395 RR(VID_FIR_COEF_H(0, 5)); 384
396 RR(VID_FIR_COEF_H(0, 6)); 385 for (i = 0; i < 5; i++)
397 RR(VID_FIR_COEF_H(0, 7)); 386 RR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i));
398 387
399 RR(VID_FIR_COEF_HV(0, 0)); 388 for (i = 0; i < 8; i++)
400 RR(VID_FIR_COEF_HV(0, 1)); 389 RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
401 RR(VID_FIR_COEF_HV(0, 2)); 390
402 RR(VID_FIR_COEF_HV(0, 3)); 391 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
403 RR(VID_FIR_COEF_HV(0, 4)); 392 RR(OVL_BA0_UV(OMAP_DSS_VIDEO1));
404 RR(VID_FIR_COEF_HV(0, 5)); 393 RR(OVL_BA1_UV(OMAP_DSS_VIDEO1));
405 RR(VID_FIR_COEF_HV(0, 6)); 394 RR(OVL_FIR2(OMAP_DSS_VIDEO1));
406 RR(VID_FIR_COEF_HV(0, 7)); 395 RR(OVL_ACCU2_0(OMAP_DSS_VIDEO1));
407 396 RR(OVL_ACCU2_1(OMAP_DSS_VIDEO1));
408 RR(VID_CONV_COEF(0, 0)); 397
409 RR(VID_CONV_COEF(0, 1)); 398 for (i = 0; i < 8; i++)
410 RR(VID_CONV_COEF(0, 2)); 399 RR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, i));
411 RR(VID_CONV_COEF(0, 3)); 400
412 RR(VID_CONV_COEF(0, 4)); 401 for (i = 0; i < 8; i++)
413 402 RR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, i));
414 RR(VID_FIR_COEF_V(0, 0)); 403
415 RR(VID_FIR_COEF_V(0, 1)); 404 for (i = 0; i < 8; i++)
416 RR(VID_FIR_COEF_V(0, 2)); 405 RR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, i));
417 RR(VID_FIR_COEF_V(0, 3)); 406 }
418 RR(VID_FIR_COEF_V(0, 4)); 407 if (dss_has_feature(FEAT_ATTR2))
419 RR(VID_FIR_COEF_V(0, 5)); 408 RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
420 RR(VID_FIR_COEF_V(0, 6)); 409
421 RR(VID_FIR_COEF_V(0, 7)); 410 RR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
422
423 RR(VID_PRELOAD(0));
424 411
425 /* VID2 */ 412 /* VID2 */
426 RR(VID_BA0(1)); 413 RR(OVL_BA0(OMAP_DSS_VIDEO2));
427 RR(VID_BA1(1)); 414 RR(OVL_BA1(OMAP_DSS_VIDEO2));
428 RR(VID_POSITION(1)); 415 RR(OVL_POSITION(OMAP_DSS_VIDEO2));
429 RR(VID_SIZE(1)); 416 RR(OVL_SIZE(OMAP_DSS_VIDEO2));
430 RR(VID_ATTRIBUTES(1)); 417 RR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO2));
431 RR(VID_FIFO_THRESHOLD(1)); 418 RR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2));
432 RR(VID_ROW_INC(1)); 419 RR(OVL_ROW_INC(OMAP_DSS_VIDEO2));
433 RR(VID_PIXEL_INC(1)); 420 RR(OVL_PIXEL_INC(OMAP_DSS_VIDEO2));
434 RR(VID_FIR(1)); 421 RR(OVL_FIR(OMAP_DSS_VIDEO2));
435 RR(VID_PICTURE_SIZE(1)); 422 RR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2));
436 RR(VID_ACCU0(1)); 423 RR(OVL_ACCU0(OMAP_DSS_VIDEO2));
437 RR(VID_ACCU1(1)); 424 RR(OVL_ACCU1(OMAP_DSS_VIDEO2));
438 425
439 RR(VID_FIR_COEF_H(1, 0)); 426 for (i = 0; i < 8; i++)
440 RR(VID_FIR_COEF_H(1, 1)); 427 RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, i));
441 RR(VID_FIR_COEF_H(1, 2)); 428
442 RR(VID_FIR_COEF_H(1, 3)); 429 for (i = 0; i < 8; i++)
443 RR(VID_FIR_COEF_H(1, 4)); 430 RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, i));
444 RR(VID_FIR_COEF_H(1, 5)); 431
445 RR(VID_FIR_COEF_H(1, 6)); 432 for (i = 0; i < 5; i++)
446 RR(VID_FIR_COEF_H(1, 7)); 433 RR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i));
447 434
448 RR(VID_FIR_COEF_HV(1, 0)); 435 for (i = 0; i < 8; i++)
449 RR(VID_FIR_COEF_HV(1, 1)); 436 RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
450 RR(VID_FIR_COEF_HV(1, 2)); 437
451 RR(VID_FIR_COEF_HV(1, 3)); 438 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
452 RR(VID_FIR_COEF_HV(1, 4)); 439 RR(OVL_BA0_UV(OMAP_DSS_VIDEO2));
453 RR(VID_FIR_COEF_HV(1, 5)); 440 RR(OVL_BA1_UV(OMAP_DSS_VIDEO2));
454 RR(VID_FIR_COEF_HV(1, 6)); 441 RR(OVL_FIR2(OMAP_DSS_VIDEO2));
455 RR(VID_FIR_COEF_HV(1, 7)); 442 RR(OVL_ACCU2_0(OMAP_DSS_VIDEO2));
456 443 RR(OVL_ACCU2_1(OMAP_DSS_VIDEO2));
457 RR(VID_CONV_COEF(1, 0)); 444
458 RR(VID_CONV_COEF(1, 1)); 445 for (i = 0; i < 8; i++)
459 RR(VID_CONV_COEF(1, 2)); 446 RR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, i));
460 RR(VID_CONV_COEF(1, 3)); 447
461 RR(VID_CONV_COEF(1, 4)); 448 for (i = 0; i < 8; i++)
462 449 RR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, i));
463 RR(VID_FIR_COEF_V(1, 0)); 450
464 RR(VID_FIR_COEF_V(1, 1)); 451 for (i = 0; i < 8; i++)
465 RR(VID_FIR_COEF_V(1, 2)); 452 RR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, i));
466 RR(VID_FIR_COEF_V(1, 3)); 453 }
467 RR(VID_FIR_COEF_V(1, 4)); 454 if (dss_has_feature(FEAT_ATTR2))
468 RR(VID_FIR_COEF_V(1, 5)); 455 RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
469 RR(VID_FIR_COEF_V(1, 6)); 456
470 RR(VID_FIR_COEF_V(1, 7)); 457 RR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
471 458
472 RR(VID_PRELOAD(1)); 459 if (dss_has_feature(FEAT_CORE_CLK_DIV))
460 RR(DIVISOR);
473 461
474 /* enable last, because LCD & DIGIT enable are here */ 462 /* enable last, because LCD & DIGIT enable are here */
475 RR(CONTROL); 463 RR(CONTROL);
476 464 if (dss_has_feature(FEAT_MGR_LCD2))
465 RR(CONTROL2);
477 /* clear spurious SYNC_LOST_DIGIT interrupts */ 466 /* clear spurious SYNC_LOST_DIGIT interrupts */
478 dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); 467 dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
479 468
@@ -490,180 +479,188 @@ void dispc_restore_context(void)
490static inline void enable_clocks(bool enable) 479static inline void enable_clocks(bool enable)
491{ 480{
492 if (enable) 481 if (enable)
493 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); 482 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
494 else 483 else
495 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); 484 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
496} 485}
497 486
498bool dispc_go_busy(enum omap_channel channel) 487bool dispc_go_busy(enum omap_channel channel)
499{ 488{
500 int bit; 489 int bit;
501 490
502 if (channel == OMAP_DSS_CHANNEL_LCD) 491 if (channel == OMAP_DSS_CHANNEL_LCD ||
492 channel == OMAP_DSS_CHANNEL_LCD2)
503 bit = 5; /* GOLCD */ 493 bit = 5; /* GOLCD */
504 else 494 else
505 bit = 6; /* GODIGIT */ 495 bit = 6; /* GODIGIT */
506 496
507 return REG_GET(DISPC_CONTROL, bit, bit) == 1; 497 if (channel == OMAP_DSS_CHANNEL_LCD2)
498 return REG_GET(DISPC_CONTROL2, bit, bit) == 1;
499 else
500 return REG_GET(DISPC_CONTROL, bit, bit) == 1;
508} 501}
509 502
510void dispc_go(enum omap_channel channel) 503void dispc_go(enum omap_channel channel)
511{ 504{
512 int bit; 505 int bit;
506 bool enable_bit, go_bit;
513 507
514 enable_clocks(1); 508 enable_clocks(1);
515 509
516 if (channel == OMAP_DSS_CHANNEL_LCD) 510 if (channel == OMAP_DSS_CHANNEL_LCD ||
511 channel == OMAP_DSS_CHANNEL_LCD2)
517 bit = 0; /* LCDENABLE */ 512 bit = 0; /* LCDENABLE */
518 else 513 else
519 bit = 1; /* DIGITALENABLE */ 514 bit = 1; /* DIGITALENABLE */
520 515
521 /* if the channel is not enabled, we don't need GO */ 516 /* if the channel is not enabled, we don't need GO */
522 if (REG_GET(DISPC_CONTROL, bit, bit) == 0) 517 if (channel == OMAP_DSS_CHANNEL_LCD2)
518 enable_bit = REG_GET(DISPC_CONTROL2, bit, bit) == 1;
519 else
520 enable_bit = REG_GET(DISPC_CONTROL, bit, bit) == 1;
521
522 if (!enable_bit)
523 goto end; 523 goto end;
524 524
525 if (channel == OMAP_DSS_CHANNEL_LCD) 525 if (channel == OMAP_DSS_CHANNEL_LCD ||
526 channel == OMAP_DSS_CHANNEL_LCD2)
526 bit = 5; /* GOLCD */ 527 bit = 5; /* GOLCD */
527 else 528 else
528 bit = 6; /* GODIGIT */ 529 bit = 6; /* GODIGIT */
529 530
530 if (REG_GET(DISPC_CONTROL, bit, bit) == 1) { 531 if (channel == OMAP_DSS_CHANNEL_LCD2)
532 go_bit = REG_GET(DISPC_CONTROL2, bit, bit) == 1;
533 else
534 go_bit = REG_GET(DISPC_CONTROL, bit, bit) == 1;
535
536 if (go_bit) {
531 DSSERR("GO bit not down for channel %d\n", channel); 537 DSSERR("GO bit not down for channel %d\n", channel);
532 goto end; 538 goto end;
533 } 539 }
534 540
535 DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" : "DIGIT"); 541 DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" :
542 (channel == OMAP_DSS_CHANNEL_LCD2 ? "LCD2" : "DIGIT"));
536 543
537 REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit); 544 if (channel == OMAP_DSS_CHANNEL_LCD2)
545 REG_FLD_MOD(DISPC_CONTROL2, 1, bit, bit);
546 else
547 REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
538end: 548end:
539 enable_clocks(0); 549 enable_clocks(0);
540} 550}
541 551
542static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value) 552static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value)
543{ 553{
554 dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value);
555}
556
557static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value)
558{
559 dispc_write_reg(DISPC_OVL_FIR_COEF_HV(plane, reg), value);
560}
561
562static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value)
563{
564 dispc_write_reg(DISPC_OVL_FIR_COEF_V(plane, reg), value);
565}
566
567static void _dispc_write_firh2_reg(enum omap_plane plane, int reg, u32 value)
568{
544 BUG_ON(plane == OMAP_DSS_GFX); 569 BUG_ON(plane == OMAP_DSS_GFX);
545 570
546 dispc_write_reg(DISPC_VID_FIR_COEF_H(plane-1, reg), value); 571 dispc_write_reg(DISPC_OVL_FIR_COEF_H2(plane, reg), value);
547} 572}
548 573
549static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value) 574static void _dispc_write_firhv2_reg(enum omap_plane plane, int reg, u32 value)
550{ 575{
551 BUG_ON(plane == OMAP_DSS_GFX); 576 BUG_ON(plane == OMAP_DSS_GFX);
552 577
553 dispc_write_reg(DISPC_VID_FIR_COEF_HV(plane-1, reg), value); 578 dispc_write_reg(DISPC_OVL_FIR_COEF_HV2(plane, reg), value);
554} 579}
555 580
556static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value) 581static void _dispc_write_firv2_reg(enum omap_plane plane, int reg, u32 value)
557{ 582{
558 BUG_ON(plane == OMAP_DSS_GFX); 583 BUG_ON(plane == OMAP_DSS_GFX);
559 584
560 dispc_write_reg(DISPC_VID_FIR_COEF_V(plane-1, reg), value); 585 dispc_write_reg(DISPC_OVL_FIR_COEF_V2(plane, reg), value);
561} 586}
562 587
563static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup, 588static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
564 int vscaleup, int five_taps) 589 int vscaleup, int five_taps,
590 enum omap_color_component color_comp)
565{ 591{
566 /* Coefficients for horizontal up-sampling */ 592 /* Coefficients for horizontal up-sampling */
567 static const u32 coef_hup[8] = { 593 static const struct dispc_h_coef coef_hup[8] = {
568 0x00800000, 594 { 0, 0, 128, 0, 0 },
569 0x0D7CF800, 595 { -1, 13, 124, -8, 0 },
570 0x1E70F5FF, 596 { -2, 30, 112, -11, -1 },
571 0x335FF5FE, 597 { -5, 51, 95, -11, -2 },
572 0xF74949F7, 598 { 0, -9, 73, 73, -9 },
573 0xF55F33FB, 599 { -2, -11, 95, 51, -5 },
574 0xF5701EFE, 600 { -1, -11, 112, 30, -2 },
575 0xF87C0DFF, 601 { 0, -8, 124, 13, -1 },
576 }; 602 };
577 603
578 /* Coefficients for horizontal down-sampling */ 604 /* Coefficients for vertical up-sampling */
579 static const u32 coef_hdown[8] = { 605 static const struct dispc_v_coef coef_vup_3tap[8] = {
580 0x24382400, 606 { 0, 0, 128, 0, 0 },
581 0x28371FFE, 607 { 0, 3, 123, 2, 0 },
582 0x2C361BFB, 608 { 0, 12, 111, 5, 0 },
583 0x303516F9, 609 { 0, 32, 89, 7, 0 },
584 0x11343311, 610 { 0, 0, 64, 64, 0 },
585 0x1635300C, 611 { 0, 7, 89, 32, 0 },
586 0x1B362C08, 612 { 0, 5, 111, 12, 0 },
587 0x1F372804, 613 { 0, 2, 123, 3, 0 },
588 }; 614 };
589 615
590 /* Coefficients for horizontal and vertical up-sampling */ 616 static const struct dispc_v_coef coef_vup_5tap[8] = {
591 static const u32 coef_hvup[2][8] = { 617 { 0, 0, 128, 0, 0 },
592 { 618 { -1, 13, 124, -8, 0 },
593 0x00800000, 619 { -2, 30, 112, -11, -1 },
594 0x037B02FF, 620 { -5, 51, 95, -11, -2 },
595 0x0C6F05FE, 621 { 0, -9, 73, 73, -9 },
596 0x205907FB, 622 { -2, -11, 95, 51, -5 },
597 0x00404000, 623 { -1, -11, 112, 30, -2 },
598 0x075920FE, 624 { 0, -8, 124, 13, -1 },
599 0x056F0CFF,
600 0x027B0300,
601 },
602 {
603 0x00800000,
604 0x0D7CF8FF,
605 0x1E70F5FE,
606 0x335FF5FB,
607 0xF7404000,
608 0xF55F33FE,
609 0xF5701EFF,
610 0xF87C0D00,
611 },
612 }; 625 };
613 626
614 /* Coefficients for horizontal and vertical down-sampling */ 627 /* Coefficients for horizontal down-sampling */
615 static const u32 coef_hvdown[2][8] = { 628 static const struct dispc_h_coef coef_hdown[8] = {
616 { 629 { 0, 36, 56, 36, 0 },
617 0x24382400, 630 { 4, 40, 55, 31, -2 },
618 0x28391F04, 631 { 8, 44, 54, 27, -5 },
619 0x2D381B08, 632 { 12, 48, 53, 22, -7 },
620 0x3237170C, 633 { -9, 17, 52, 51, 17 },
621 0x123737F7, 634 { -7, 22, 53, 48, 12 },
622 0x173732F9, 635 { -5, 27, 54, 44, 8 },
623 0x1B382DFB, 636 { -2, 31, 55, 40, 4 },
624 0x1F3928FE,
625 },
626 {
627 0x24382400,
628 0x28371F04,
629 0x2C361B08,
630 0x3035160C,
631 0x113433F7,
632 0x163530F9,
633 0x1B362CFB,
634 0x1F3728FE,
635 },
636 }; 637 };
637 638
638 /* Coefficients for vertical up-sampling */ 639 /* Coefficients for vertical down-sampling */
639 static const u32 coef_vup[8] = { 640 static const struct dispc_v_coef coef_vdown_3tap[8] = {
640 0x00000000, 641 { 0, 36, 56, 36, 0 },
641 0x0000FF00, 642 { 0, 40, 57, 31, 0 },
642 0x0000FEFF, 643 { 0, 45, 56, 27, 0 },
643 0x0000FBFE, 644 { 0, 50, 55, 23, 0 },
644 0x000000F7, 645 { 0, 18, 55, 55, 0 },
645 0x0000FEFB, 646 { 0, 23, 55, 50, 0 },
646 0x0000FFFE, 647 { 0, 27, 56, 45, 0 },
647 0x000000FF, 648 { 0, 31, 57, 40, 0 },
648 }; 649 };
649 650
650 651 static const struct dispc_v_coef coef_vdown_5tap[8] = {
651 /* Coefficients for vertical down-sampling */ 652 { 0, 36, 56, 36, 0 },
652 static const u32 coef_vdown[8] = { 653 { 4, 40, 55, 31, -2 },
653 0x00000000, 654 { 8, 44, 54, 27, -5 },
654 0x000004FE, 655 { 12, 48, 53, 22, -7 },
655 0x000008FB, 656 { -9, 17, 52, 51, 17 },
656 0x00000CF9, 657 { -7, 22, 53, 48, 12 },
657 0x0000F711, 658 { -5, 27, 54, 44, 8 },
658 0x0000F90C, 659 { -2, 31, 55, 40, 4 },
659 0x0000FB08,
660 0x0000FE04,
661 }; 660 };
662 661
663 const u32 *h_coef; 662 const struct dispc_h_coef *h_coef;
664 const u32 *hv_coef; 663 const struct dispc_v_coef *v_coef;
665 const u32 *hv_coef_mod;
666 const u32 *v_coef;
667 int i; 664 int i;
668 665
669 if (hscaleup) 666 if (hscaleup)
@@ -671,47 +668,43 @@ static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
671 else 668 else
672 h_coef = coef_hdown; 669 h_coef = coef_hdown;
673 670
674 if (vscaleup) { 671 if (vscaleup)
675 hv_coef = coef_hvup[five_taps]; 672 v_coef = five_taps ? coef_vup_5tap : coef_vup_3tap;
676 v_coef = coef_vup; 673 else
677 674 v_coef = five_taps ? coef_vdown_5tap : coef_vdown_3tap;
678 if (hscaleup)
679 hv_coef_mod = NULL;
680 else
681 hv_coef_mod = coef_hvdown[five_taps];
682 } else {
683 hv_coef = coef_hvdown[five_taps];
684 v_coef = coef_vdown;
685
686 if (hscaleup)
687 hv_coef_mod = coef_hvup[five_taps];
688 else
689 hv_coef_mod = NULL;
690 }
691 675
692 for (i = 0; i < 8; i++) { 676 for (i = 0; i < 8; i++) {
693 u32 h, hv; 677 u32 h, hv;
694 678
695 h = h_coef[i]; 679 h = FLD_VAL(h_coef[i].hc0, 7, 0)
696 680 | FLD_VAL(h_coef[i].hc1, 15, 8)
697 hv = hv_coef[i]; 681 | FLD_VAL(h_coef[i].hc2, 23, 16)
698 682 | FLD_VAL(h_coef[i].hc3, 31, 24);
699 if (hv_coef_mod) { 683 hv = FLD_VAL(h_coef[i].hc4, 7, 0)
700 hv &= 0xffffff00; 684 | FLD_VAL(v_coef[i].vc0, 15, 8)
701 hv |= (hv_coef_mod[i] & 0xff); 685 | FLD_VAL(v_coef[i].vc1, 23, 16)
686 | FLD_VAL(v_coef[i].vc2, 31, 24);
687
688 if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) {
689 _dispc_write_firh_reg(plane, i, h);
690 _dispc_write_firhv_reg(plane, i, hv);
691 } else {
692 _dispc_write_firh2_reg(plane, i, h);
693 _dispc_write_firhv2_reg(plane, i, hv);
702 } 694 }
703 695
704 _dispc_write_firh_reg(plane, i, h);
705 _dispc_write_firhv_reg(plane, i, hv);
706 } 696 }
707 697
708 if (!five_taps) 698 if (five_taps) {
709 return; 699 for (i = 0; i < 8; i++) {
710 700 u32 v;
711 for (i = 0; i < 8; i++) { 701 v = FLD_VAL(v_coef[i].vc00, 7, 0)
712 u32 v; 702 | FLD_VAL(v_coef[i].vc22, 15, 8);
713 v = v_coef[i]; 703 if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y)
714 _dispc_write_firv_reg(plane, i, v); 704 _dispc_write_firv_reg(plane, i, v);
705 else
706 _dispc_write_firv2_reg(plane, i, v);
707 }
715 } 708 }
716} 709}
717 710
@@ -730,80 +723,104 @@ static void _dispc_setup_color_conv_coef(void)
730 723
731 ct = &ctbl_bt601_5; 724 ct = &ctbl_bt601_5;
732 725
733 dispc_write_reg(DISPC_VID_CONV_COEF(0, 0), CVAL(ct->rcr, ct->ry)); 726 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0),
734 dispc_write_reg(DISPC_VID_CONV_COEF(0, 1), CVAL(ct->gy, ct->rcb)); 727 CVAL(ct->rcr, ct->ry));
735 dispc_write_reg(DISPC_VID_CONV_COEF(0, 2), CVAL(ct->gcb, ct->gcr)); 728 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1),
736 dispc_write_reg(DISPC_VID_CONV_COEF(0, 3), CVAL(ct->bcr, ct->by)); 729 CVAL(ct->gy, ct->rcb));
737 dispc_write_reg(DISPC_VID_CONV_COEF(0, 4), CVAL(0, ct->bcb)); 730 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2),
738 731 CVAL(ct->gcb, ct->gcr));
739 dispc_write_reg(DISPC_VID_CONV_COEF(1, 0), CVAL(ct->rcr, ct->ry)); 732 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3),
740 dispc_write_reg(DISPC_VID_CONV_COEF(1, 1), CVAL(ct->gy, ct->rcb)); 733 CVAL(ct->bcr, ct->by));
741 dispc_write_reg(DISPC_VID_CONV_COEF(1, 2), CVAL(ct->gcb, ct->gcr)); 734 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4),
742 dispc_write_reg(DISPC_VID_CONV_COEF(1, 3), CVAL(ct->bcr, ct->by)); 735 CVAL(0, ct->bcb));
743 dispc_write_reg(DISPC_VID_CONV_COEF(1, 4), CVAL(0, ct->bcb)); 736
737 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0),
738 CVAL(ct->rcr, ct->ry));
739 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1),
740 CVAL(ct->gy, ct->rcb));
741 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2),
742 CVAL(ct->gcb, ct->gcr));
743 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3),
744 CVAL(ct->bcr, ct->by));
745 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4),
746 CVAL(0, ct->bcb));
744 747
745#undef CVAL 748#undef CVAL
746 749
747 REG_FLD_MOD(DISPC_VID_ATTRIBUTES(0), ct->full_range, 11, 11); 750 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO1),
748 REG_FLD_MOD(DISPC_VID_ATTRIBUTES(1), ct->full_range, 11, 11); 751 ct->full_range, 11, 11);
752 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO2),
753 ct->full_range, 11, 11);
749} 754}
750 755
751 756
752static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr) 757static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr)
753{ 758{
754 const struct dispc_reg ba0_reg[] = { DISPC_GFX_BA0, 759 dispc_write_reg(DISPC_OVL_BA0(plane), paddr);
755 DISPC_VID_BA0(0),
756 DISPC_VID_BA0(1) };
757
758 dispc_write_reg(ba0_reg[plane], paddr);
759} 760}
760 761
761static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr) 762static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr)
762{ 763{
763 const struct dispc_reg ba1_reg[] = { DISPC_GFX_BA1, 764 dispc_write_reg(DISPC_OVL_BA1(plane), paddr);
764 DISPC_VID_BA1(0), 765}
765 DISPC_VID_BA1(1) };
766 766
767 dispc_write_reg(ba1_reg[plane], paddr); 767static void _dispc_set_plane_ba0_uv(enum omap_plane plane, u32 paddr)
768{
769 dispc_write_reg(DISPC_OVL_BA0_UV(plane), paddr);
768} 770}
769 771
770static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y) 772static void _dispc_set_plane_ba1_uv(enum omap_plane plane, u32 paddr)
771{ 773{
772 const struct dispc_reg pos_reg[] = { DISPC_GFX_POSITION, 774 dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr);
773 DISPC_VID_POSITION(0), 775}
774 DISPC_VID_POSITION(1) };
775 776
777static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y)
778{
776 u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0); 779 u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
777 dispc_write_reg(pos_reg[plane], val); 780
781 dispc_write_reg(DISPC_OVL_POSITION(plane), val);
778} 782}
779 783
780static void _dispc_set_pic_size(enum omap_plane plane, int width, int height) 784static void _dispc_set_pic_size(enum omap_plane plane, int width, int height)
781{ 785{
782 const struct dispc_reg siz_reg[] = { DISPC_GFX_SIZE,
783 DISPC_VID_PICTURE_SIZE(0),
784 DISPC_VID_PICTURE_SIZE(1) };
785 u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); 786 u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
786 dispc_write_reg(siz_reg[plane], val); 787
788 if (plane == OMAP_DSS_GFX)
789 dispc_write_reg(DISPC_OVL_SIZE(plane), val);
790 else
791 dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);
787} 792}
788 793
789static void _dispc_set_vid_size(enum omap_plane plane, int width, int height) 794static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)
790{ 795{
791 u32 val; 796 u32 val;
792 const struct dispc_reg vsi_reg[] = { DISPC_VID_SIZE(0),
793 DISPC_VID_SIZE(1) };
794 797
795 BUG_ON(plane == OMAP_DSS_GFX); 798 BUG_ON(plane == OMAP_DSS_GFX);
796 799
797 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); 800 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
798 dispc_write_reg(vsi_reg[plane-1], val); 801
802 dispc_write_reg(DISPC_OVL_SIZE(plane), val);
799} 803}
800 804
801static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha) 805static void _dispc_set_pre_mult_alpha(enum omap_plane plane, bool enable)
802{ 806{
807 if (!dss_has_feature(FEAT_PRE_MULT_ALPHA))
808 return;
803 809
804 BUG_ON(plane == OMAP_DSS_VIDEO1); 810 if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
811 plane == OMAP_DSS_VIDEO1)
812 return;
805 813
806 if (cpu_is_omap24xx()) 814 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28);
815}
816
817static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha)
818{
819 if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
820 return;
821
822 if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
823 plane == OMAP_DSS_VIDEO1)
807 return; 824 return;
808 825
809 if (plane == OMAP_DSS_GFX) 826 if (plane == OMAP_DSS_GFX)
@@ -814,61 +831,93 @@ static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha)
814 831
815static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc) 832static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc)
816{ 833{
817 const struct dispc_reg ri_reg[] = { DISPC_GFX_PIXEL_INC, 834 dispc_write_reg(DISPC_OVL_PIXEL_INC(plane), inc);
818 DISPC_VID_PIXEL_INC(0),
819 DISPC_VID_PIXEL_INC(1) };
820
821 dispc_write_reg(ri_reg[plane], inc);
822} 835}
823 836
824static void _dispc_set_row_inc(enum omap_plane plane, s32 inc) 837static void _dispc_set_row_inc(enum omap_plane plane, s32 inc)
825{ 838{
826 const struct dispc_reg ri_reg[] = { DISPC_GFX_ROW_INC, 839 dispc_write_reg(DISPC_OVL_ROW_INC(plane), inc);
827 DISPC_VID_ROW_INC(0),
828 DISPC_VID_ROW_INC(1) };
829
830 dispc_write_reg(ri_reg[plane], inc);
831} 840}
832 841
833static void _dispc_set_color_mode(enum omap_plane plane, 842static void _dispc_set_color_mode(enum omap_plane plane,
834 enum omap_color_mode color_mode) 843 enum omap_color_mode color_mode)
835{ 844{
836 u32 m = 0; 845 u32 m = 0;
837 846 if (plane != OMAP_DSS_GFX) {
838 switch (color_mode) { 847 switch (color_mode) {
839 case OMAP_DSS_COLOR_CLUT1: 848 case OMAP_DSS_COLOR_NV12:
840 m = 0x0; break; 849 m = 0x0; break;
841 case OMAP_DSS_COLOR_CLUT2: 850 case OMAP_DSS_COLOR_RGB12U:
842 m = 0x1; break; 851 m = 0x1; break;
843 case OMAP_DSS_COLOR_CLUT4: 852 case OMAP_DSS_COLOR_RGBA16:
844 m = 0x2; break; 853 m = 0x2; break;
845 case OMAP_DSS_COLOR_CLUT8: 854 case OMAP_DSS_COLOR_RGBX16:
846 m = 0x3; break; 855 m = 0x4; break;
847 case OMAP_DSS_COLOR_RGB12U: 856 case OMAP_DSS_COLOR_ARGB16:
848 m = 0x4; break; 857 m = 0x5; break;
849 case OMAP_DSS_COLOR_ARGB16: 858 case OMAP_DSS_COLOR_RGB16:
850 m = 0x5; break; 859 m = 0x6; break;
851 case OMAP_DSS_COLOR_RGB16: 860 case OMAP_DSS_COLOR_ARGB16_1555:
852 m = 0x6; break; 861 m = 0x7; break;
853 case OMAP_DSS_COLOR_RGB24U: 862 case OMAP_DSS_COLOR_RGB24U:
854 m = 0x8; break; 863 m = 0x8; break;
855 case OMAP_DSS_COLOR_RGB24P: 864 case OMAP_DSS_COLOR_RGB24P:
856 m = 0x9; break; 865 m = 0x9; break;
857 case OMAP_DSS_COLOR_YUV2: 866 case OMAP_DSS_COLOR_YUV2:
858 m = 0xa; break; 867 m = 0xa; break;
859 case OMAP_DSS_COLOR_UYVY: 868 case OMAP_DSS_COLOR_UYVY:
860 m = 0xb; break; 869 m = 0xb; break;
861 case OMAP_DSS_COLOR_ARGB32: 870 case OMAP_DSS_COLOR_ARGB32:
862 m = 0xc; break; 871 m = 0xc; break;
863 case OMAP_DSS_COLOR_RGBA32: 872 case OMAP_DSS_COLOR_RGBA32:
864 m = 0xd; break; 873 m = 0xd; break;
865 case OMAP_DSS_COLOR_RGBX32: 874 case OMAP_DSS_COLOR_RGBX32:
866 m = 0xe; break; 875 m = 0xe; break;
867 default: 876 case OMAP_DSS_COLOR_XRGB16_1555:
868 BUG(); break; 877 m = 0xf; break;
878 default:
879 BUG(); break;
880 }
881 } else {
882 switch (color_mode) {
883 case OMAP_DSS_COLOR_CLUT1:
884 m = 0x0; break;
885 case OMAP_DSS_COLOR_CLUT2:
886 m = 0x1; break;
887 case OMAP_DSS_COLOR_CLUT4:
888 m = 0x2; break;
889 case OMAP_DSS_COLOR_CLUT8:
890 m = 0x3; break;
891 case OMAP_DSS_COLOR_RGB12U:
892 m = 0x4; break;
893 case OMAP_DSS_COLOR_ARGB16:
894 m = 0x5; break;
895 case OMAP_DSS_COLOR_RGB16:
896 m = 0x6; break;
897 case OMAP_DSS_COLOR_ARGB16_1555:
898 m = 0x7; break;
899 case OMAP_DSS_COLOR_RGB24U:
900 m = 0x8; break;
901 case OMAP_DSS_COLOR_RGB24P:
902 m = 0x9; break;
903 case OMAP_DSS_COLOR_YUV2:
904 m = 0xa; break;
905 case OMAP_DSS_COLOR_UYVY:
906 m = 0xb; break;
907 case OMAP_DSS_COLOR_ARGB32:
908 m = 0xc; break;
909 case OMAP_DSS_COLOR_RGBA32:
910 m = 0xd; break;
911 case OMAP_DSS_COLOR_RGBX32:
912 m = 0xe; break;
913 case OMAP_DSS_COLOR_XRGB16_1555:
914 m = 0xf; break;
915 default:
916 BUG(); break;
917 }
869 } 918 }
870 919
871 REG_FLD_MOD(dispc_reg_att[plane], m, 4, 1); 920 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
872} 921}
873 922
874static void _dispc_set_channel_out(enum omap_plane plane, 923static void _dispc_set_channel_out(enum omap_plane plane,
@@ -876,6 +925,7 @@ static void _dispc_set_channel_out(enum omap_plane plane,
876{ 925{
877 int shift; 926 int shift;
878 u32 val; 927 u32 val;
928 int chan = 0, chan2 = 0;
879 929
880 switch (plane) { 930 switch (plane) {
881 case OMAP_DSS_GFX: 931 case OMAP_DSS_GFX:
@@ -890,9 +940,31 @@ static void _dispc_set_channel_out(enum omap_plane plane,
890 return; 940 return;
891 } 941 }
892 942
893 val = dispc_read_reg(dispc_reg_att[plane]); 943 val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
894 val = FLD_MOD(val, channel, shift, shift); 944 if (dss_has_feature(FEAT_MGR_LCD2)) {
895 dispc_write_reg(dispc_reg_att[plane], val); 945 switch (channel) {
946 case OMAP_DSS_CHANNEL_LCD:
947 chan = 0;
948 chan2 = 0;
949 break;
950 case OMAP_DSS_CHANNEL_DIGIT:
951 chan = 1;
952 chan2 = 0;
953 break;
954 case OMAP_DSS_CHANNEL_LCD2:
955 chan = 0;
956 chan2 = 1;
957 break;
958 default:
959 BUG();
960 }
961
962 val = FLD_MOD(val, chan, shift, shift);
963 val = FLD_MOD(val, chan2, 31, 30);
964 } else {
965 val = FLD_MOD(val, channel, shift, shift);
966 }
967 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
896} 968}
897 969
898void dispc_set_burst_size(enum omap_plane plane, 970void dispc_set_burst_size(enum omap_plane plane,
@@ -916,22 +988,36 @@ void dispc_set_burst_size(enum omap_plane plane,
916 return; 988 return;
917 } 989 }
918 990
919 val = dispc_read_reg(dispc_reg_att[plane]); 991 val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
920 val = FLD_MOD(val, burst_size, shift+1, shift); 992 val = FLD_MOD(val, burst_size, shift+1, shift);
921 dispc_write_reg(dispc_reg_att[plane], val); 993 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
922 994
923 enable_clocks(0); 995 enable_clocks(0);
924} 996}
925 997
998void dispc_enable_gamma_table(bool enable)
999{
1000 /*
1001 * This is partially implemented to support only disabling of
1002 * the gamma table.
1003 */
1004 if (enable) {
1005 DSSWARN("Gamma table enabling for TV not yet supported");
1006 return;
1007 }
1008
1009 REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9);
1010}
1011
926static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable) 1012static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
927{ 1013{
928 u32 val; 1014 u32 val;
929 1015
930 BUG_ON(plane == OMAP_DSS_GFX); 1016 BUG_ON(plane == OMAP_DSS_GFX);
931 1017
932 val = dispc_read_reg(dispc_reg_att[plane]); 1018 val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
933 val = FLD_MOD(val, enable, 9, 9); 1019 val = FLD_MOD(val, enable, 9, 9);
934 dispc_write_reg(dispc_reg_att[plane], val); 1020 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
935} 1021}
936 1022
937void dispc_enable_replication(enum omap_plane plane, bool enable) 1023void dispc_enable_replication(enum omap_plane plane, bool enable)
@@ -944,17 +1030,17 @@ void dispc_enable_replication(enum omap_plane plane, bool enable)
944 bit = 10; 1030 bit = 10;
945 1031
946 enable_clocks(1); 1032 enable_clocks(1);
947 REG_FLD_MOD(dispc_reg_att[plane], enable, bit, bit); 1033 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit);
948 enable_clocks(0); 1034 enable_clocks(0);
949} 1035}
950 1036
951void dispc_set_lcd_size(u16 width, u16 height) 1037void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
952{ 1038{
953 u32 val; 1039 u32 val;
954 BUG_ON((width > (1 << 11)) || (height > (1 << 11))); 1040 BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
955 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); 1041 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
956 enable_clocks(1); 1042 enable_clocks(1);
957 dispc_write_reg(DISPC_SIZE_LCD, val); 1043 dispc_write_reg(DISPC_SIZE_MGR(channel), val);
958 enable_clocks(0); 1044 enable_clocks(0);
959} 1045}
960 1046
@@ -964,28 +1050,23 @@ void dispc_set_digit_size(u16 width, u16 height)
964 BUG_ON((width > (1 << 11)) || (height > (1 << 11))); 1050 BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
965 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); 1051 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
966 enable_clocks(1); 1052 enable_clocks(1);
967 dispc_write_reg(DISPC_SIZE_DIG, val); 1053 dispc_write_reg(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT), val);
968 enable_clocks(0); 1054 enable_clocks(0);
969} 1055}
970 1056
971static void dispc_read_plane_fifo_sizes(void) 1057static void dispc_read_plane_fifo_sizes(void)
972{ 1058{
973 const struct dispc_reg fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS,
974 DISPC_VID_FIFO_SIZE_STATUS(0),
975 DISPC_VID_FIFO_SIZE_STATUS(1) };
976 u32 size; 1059 u32 size;
977 int plane; 1060 int plane;
1061 u8 start, end;
978 1062
979 enable_clocks(1); 1063 enable_clocks(1);
980 1064
981 for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) { 1065 dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
982 if (cpu_is_omap24xx())
983 size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 8, 0);
984 else if (cpu_is_omap34xx())
985 size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 10, 0);
986 else
987 BUG();
988 1066
1067 for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
1068 size = FLD_GET(dispc_read_reg(DISPC_OVL_FIFO_SIZE_STATUS(plane)),
1069 start, end);
989 dispc.fifo_size[plane] = size; 1070 dispc.fifo_size[plane] = size;
990 } 1071 }
991 1072
@@ -999,23 +1080,24 @@ u32 dispc_get_plane_fifo_size(enum omap_plane plane)
999 1080
1000void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high) 1081void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
1001{ 1082{
1002 const struct dispc_reg ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD, 1083 u8 hi_start, hi_end, lo_start, lo_end;
1003 DISPC_VID_FIFO_THRESHOLD(0), 1084
1004 DISPC_VID_FIFO_THRESHOLD(1) }; 1085 dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end);
1086 dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end);
1087
1005 enable_clocks(1); 1088 enable_clocks(1);
1006 1089
1007 DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n", 1090 DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
1008 plane, 1091 plane,
1009 REG_GET(ftrs_reg[plane], 11, 0), 1092 REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
1010 REG_GET(ftrs_reg[plane], 27, 16), 1093 lo_start, lo_end),
1094 REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
1095 hi_start, hi_end),
1011 low, high); 1096 low, high);
1012 1097
1013 if (cpu_is_omap24xx()) 1098 dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane),
1014 dispc_write_reg(ftrs_reg[plane], 1099 FLD_VAL(high, hi_start, hi_end) |
1015 FLD_VAL(high, 24, 16) | FLD_VAL(low, 8, 0)); 1100 FLD_VAL(low, lo_start, lo_end));
1016 else
1017 dispc_write_reg(ftrs_reg[plane],
1018 FLD_VAL(high, 27, 16) | FLD_VAL(low, 11, 0));
1019 1101
1020 enable_clocks(0); 1102 enable_clocks(0);
1021} 1103}
@@ -1030,91 +1112,129 @@ void dispc_enable_fifomerge(bool enable)
1030 enable_clocks(0); 1112 enable_clocks(0);
1031} 1113}
1032 1114
1033static void _dispc_set_fir(enum omap_plane plane, int hinc, int vinc) 1115static void _dispc_set_fir(enum omap_plane plane,
1116 int hinc, int vinc,
1117 enum omap_color_component color_comp)
1034{ 1118{
1035 u32 val; 1119 u32 val;
1036 const struct dispc_reg fir_reg[] = { DISPC_VID_FIR(0),
1037 DISPC_VID_FIR(1) };
1038 1120
1039 BUG_ON(plane == OMAP_DSS_GFX); 1121 if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) {
1122 u8 hinc_start, hinc_end, vinc_start, vinc_end;
1040 1123
1041 if (cpu_is_omap24xx()) 1124 dss_feat_get_reg_field(FEAT_REG_FIRHINC,
1042 val = FLD_VAL(vinc, 27, 16) | FLD_VAL(hinc, 11, 0); 1125 &hinc_start, &hinc_end);
1043 else 1126 dss_feat_get_reg_field(FEAT_REG_FIRVINC,
1127 &vinc_start, &vinc_end);
1128 val = FLD_VAL(vinc, vinc_start, vinc_end) |
1129 FLD_VAL(hinc, hinc_start, hinc_end);
1130
1131 dispc_write_reg(DISPC_OVL_FIR(plane), val);
1132 } else {
1044 val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0); 1133 val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0);
1045 dispc_write_reg(fir_reg[plane-1], val); 1134 dispc_write_reg(DISPC_OVL_FIR2(plane), val);
1135 }
1046} 1136}
1047 1137
1048static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) 1138static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
1049{ 1139{
1050 u32 val; 1140 u32 val;
1051 const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0), 1141 u8 hor_start, hor_end, vert_start, vert_end;
1052 DISPC_VID_ACCU0(1) };
1053 1142
1054 BUG_ON(plane == OMAP_DSS_GFX); 1143 dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end);
1144 dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end);
1145
1146 val = FLD_VAL(vaccu, vert_start, vert_end) |
1147 FLD_VAL(haccu, hor_start, hor_end);
1055 1148
1056 val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0); 1149 dispc_write_reg(DISPC_OVL_ACCU0(plane), val);
1057 dispc_write_reg(ac0_reg[plane-1], val);
1058} 1150}
1059 1151
1060static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu) 1152static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
1061{ 1153{
1062 u32 val; 1154 u32 val;
1063 const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0), 1155 u8 hor_start, hor_end, vert_start, vert_end;
1064 DISPC_VID_ACCU1(1) };
1065 1156
1066 BUG_ON(plane == OMAP_DSS_GFX); 1157 dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end);
1158 dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end);
1159
1160 val = FLD_VAL(vaccu, vert_start, vert_end) |
1161 FLD_VAL(haccu, hor_start, hor_end);
1067 1162
1068 val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0); 1163 dispc_write_reg(DISPC_OVL_ACCU1(plane), val);
1069 dispc_write_reg(ac1_reg[plane-1], val);
1070} 1164}
1071 1165
1166static void _dispc_set_vid_accu2_0(enum omap_plane plane, int haccu, int vaccu)
1167{
1168 u32 val;
1072 1169
1073static void _dispc_set_scaling(enum omap_plane plane, 1170 val = FLD_VAL(vaccu, 26, 16) | FLD_VAL(haccu, 10, 0);
1171 dispc_write_reg(DISPC_OVL_ACCU2_0(plane), val);
1172}
1173
1174static void _dispc_set_vid_accu2_1(enum omap_plane plane, int haccu, int vaccu)
1175{
1176 u32 val;
1177
1178 val = FLD_VAL(vaccu, 26, 16) | FLD_VAL(haccu, 10, 0);
1179 dispc_write_reg(DISPC_OVL_ACCU2_1(plane), val);
1180}
1181
1182static void _dispc_set_scale_param(enum omap_plane plane,
1074 u16 orig_width, u16 orig_height, 1183 u16 orig_width, u16 orig_height,
1075 u16 out_width, u16 out_height, 1184 u16 out_width, u16 out_height,
1076 bool ilace, bool five_taps, 1185 bool five_taps, u8 rotation,
1077 bool fieldmode) 1186 enum omap_color_component color_comp)
1078{ 1187{
1079 int fir_hinc; 1188 int fir_hinc, fir_vinc;
1080 int fir_vinc;
1081 int hscaleup, vscaleup; 1189 int hscaleup, vscaleup;
1082 int accu0 = 0;
1083 int accu1 = 0;
1084 u32 l;
1085
1086 BUG_ON(plane == OMAP_DSS_GFX);
1087 1190
1088 hscaleup = orig_width <= out_width; 1191 hscaleup = orig_width <= out_width;
1089 vscaleup = orig_height <= out_height; 1192 vscaleup = orig_height <= out_height;
1090 1193
1091 _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps); 1194 _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps, color_comp);
1092 1195
1093 if (!orig_width || orig_width == out_width) 1196 fir_hinc = 1024 * orig_width / out_width;
1094 fir_hinc = 0; 1197 fir_vinc = 1024 * orig_height / out_height;
1095 else
1096 fir_hinc = 1024 * orig_width / out_width;
1097 1198
1098 if (!orig_height || orig_height == out_height) 1199 _dispc_set_fir(plane, fir_hinc, fir_vinc, color_comp);
1099 fir_vinc = 0; 1200}
1100 else
1101 fir_vinc = 1024 * orig_height / out_height;
1102 1201
1103 _dispc_set_fir(plane, fir_hinc, fir_vinc); 1202static void _dispc_set_scaling_common(enum omap_plane plane,
1203 u16 orig_width, u16 orig_height,
1204 u16 out_width, u16 out_height,
1205 bool ilace, bool five_taps,
1206 bool fieldmode, enum omap_color_mode color_mode,
1207 u8 rotation)
1208{
1209 int accu0 = 0;
1210 int accu1 = 0;
1211 u32 l;
1104 1212
1105 l = dispc_read_reg(dispc_reg_att[plane]); 1213 _dispc_set_scale_param(plane, orig_width, orig_height,
1106 l &= ~((0x0f << 5) | (0x3 << 21)); 1214 out_width, out_height, five_taps,
1215 rotation, DISPC_COLOR_COMPONENT_RGB_Y);
1216 l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
1107 1217
1108 l |= fir_hinc ? (1 << 5) : 0; 1218 /* RESIZEENABLE and VERTICALTAPS */
1109 l |= fir_vinc ? (1 << 6) : 0; 1219 l &= ~((0x3 << 5) | (0x1 << 21));
1220 l |= (orig_width != out_width) ? (1 << 5) : 0;
1221 l |= (orig_height != out_height) ? (1 << 6) : 0;
1222 l |= five_taps ? (1 << 21) : 0;
1110 1223
1111 l |= hscaleup ? 0 : (1 << 7); 1224 /* VRESIZECONF and HRESIZECONF */
1112 l |= vscaleup ? 0 : (1 << 8); 1225 if (dss_has_feature(FEAT_RESIZECONF)) {
1226 l &= ~(0x3 << 7);
1227 l |= (orig_width <= out_width) ? 0 : (1 << 7);
1228 l |= (orig_height <= out_height) ? 0 : (1 << 8);
1229 }
1113 1230
1114 l |= five_taps ? (1 << 21) : 0; 1231 /* LINEBUFFERSPLIT */
1115 l |= five_taps ? (1 << 22) : 0; 1232 if (dss_has_feature(FEAT_LINEBUFFERSPLIT)) {
1233 l &= ~(0x1 << 22);
1234 l |= five_taps ? (1 << 22) : 0;
1235 }
1116 1236
1117 dispc_write_reg(dispc_reg_att[plane], l); 1237 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), l);
1118 1238
1119 /* 1239 /*
1120 * field 0 = even field = bottom field 1240 * field 0 = even field = bottom field
@@ -1122,7 +1242,7 @@ static void _dispc_set_scaling(enum omap_plane plane,
1122 */ 1242 */
1123 if (ilace && !fieldmode) { 1243 if (ilace && !fieldmode) {
1124 accu1 = 0; 1244 accu1 = 0;
1125 accu0 = (fir_vinc / 2) & 0x3ff; 1245 accu0 = ((1024 * orig_height / out_height) / 2) & 0x3ff;
1126 if (accu0 >= 1024/2) { 1246 if (accu0 >= 1024/2) {
1127 accu1 = 1024/2; 1247 accu1 = 1024/2;
1128 accu0 -= accu1; 1248 accu0 -= accu1;
@@ -1133,12 +1253,101 @@ static void _dispc_set_scaling(enum omap_plane plane,
1133 _dispc_set_vid_accu1(plane, 0, accu1); 1253 _dispc_set_vid_accu1(plane, 0, accu1);
1134} 1254}
1135 1255
1256static void _dispc_set_scaling_uv(enum omap_plane plane,
1257 u16 orig_width, u16 orig_height,
1258 u16 out_width, u16 out_height,
1259 bool ilace, bool five_taps,
1260 bool fieldmode, enum omap_color_mode color_mode,
1261 u8 rotation)
1262{
1263 int scale_x = out_width != orig_width;
1264 int scale_y = out_height != orig_height;
1265
1266 if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE))
1267 return;
1268 if ((color_mode != OMAP_DSS_COLOR_YUV2 &&
1269 color_mode != OMAP_DSS_COLOR_UYVY &&
1270 color_mode != OMAP_DSS_COLOR_NV12)) {
1271 /* reset chroma resampling for RGB formats */
1272 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8);
1273 return;
1274 }
1275 switch (color_mode) {
1276 case OMAP_DSS_COLOR_NV12:
1277 /* UV is subsampled by 2 vertically*/
1278 orig_height >>= 1;
1279 /* UV is subsampled by 2 horz.*/
1280 orig_width >>= 1;
1281 break;
1282 case OMAP_DSS_COLOR_YUV2:
1283 case OMAP_DSS_COLOR_UYVY:
1284 /*For YUV422 with 90/270 rotation,
1285 *we don't upsample chroma
1286 */
1287 if (rotation == OMAP_DSS_ROT_0 ||
1288 rotation == OMAP_DSS_ROT_180)
1289 /* UV is subsampled by 2 hrz*/
1290 orig_width >>= 1;
1291 /* must use FIR for YUV422 if rotated */
1292 if (rotation != OMAP_DSS_ROT_0)
1293 scale_x = scale_y = true;
1294 break;
1295 default:
1296 BUG();
1297 }
1298
1299 if (out_width != orig_width)
1300 scale_x = true;
1301 if (out_height != orig_height)
1302 scale_y = true;
1303
1304 _dispc_set_scale_param(plane, orig_width, orig_height,
1305 out_width, out_height, five_taps,
1306 rotation, DISPC_COLOR_COMPONENT_UV);
1307
1308 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane),
1309 (scale_x || scale_y) ? 1 : 0, 8, 8);
1310 /* set H scaling */
1311 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5);
1312 /* set V scaling */
1313 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6);
1314
1315 _dispc_set_vid_accu2_0(plane, 0x80, 0);
1316 _dispc_set_vid_accu2_1(plane, 0x80, 0);
1317}
1318
1319static void _dispc_set_scaling(enum omap_plane plane,
1320 u16 orig_width, u16 orig_height,
1321 u16 out_width, u16 out_height,
1322 bool ilace, bool five_taps,
1323 bool fieldmode, enum omap_color_mode color_mode,
1324 u8 rotation)
1325{
1326 BUG_ON(plane == OMAP_DSS_GFX);
1327
1328 _dispc_set_scaling_common(plane,
1329 orig_width, orig_height,
1330 out_width, out_height,
1331 ilace, five_taps,
1332 fieldmode, color_mode,
1333 rotation);
1334
1335 _dispc_set_scaling_uv(plane,
1336 orig_width, orig_height,
1337 out_width, out_height,
1338 ilace, five_taps,
1339 fieldmode, color_mode,
1340 rotation);
1341}
1342
1136static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, 1343static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
1137 bool mirroring, enum omap_color_mode color_mode) 1344 bool mirroring, enum omap_color_mode color_mode)
1138{ 1345{
1346 bool row_repeat = false;
1347 int vidrot = 0;
1348
1139 if (color_mode == OMAP_DSS_COLOR_YUV2 || 1349 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1140 color_mode == OMAP_DSS_COLOR_UYVY) { 1350 color_mode == OMAP_DSS_COLOR_UYVY) {
1141 int vidrot = 0;
1142 1351
1143 if (mirroring) { 1352 if (mirroring) {
1144 switch (rotation) { 1353 switch (rotation) {
@@ -1172,16 +1381,16 @@ static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
1172 } 1381 }
1173 } 1382 }
1174 1383
1175 REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12);
1176
1177 if (rotation == OMAP_DSS_ROT_90 || rotation == OMAP_DSS_ROT_270) 1384 if (rotation == OMAP_DSS_ROT_90 || rotation == OMAP_DSS_ROT_270)
1178 REG_FLD_MOD(dispc_reg_att[plane], 0x1, 18, 18); 1385 row_repeat = true;
1179 else 1386 else
1180 REG_FLD_MOD(dispc_reg_att[plane], 0x0, 18, 18); 1387 row_repeat = false;
1181 } else {
1182 REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12);
1183 REG_FLD_MOD(dispc_reg_att[plane], 0, 18, 18);
1184 } 1388 }
1389
1390 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), vidrot, 13, 12);
1391 if (dss_has_feature(FEAT_ROWREPEATENABLE))
1392 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane),
1393 row_repeat ? 1 : 0, 18, 18);
1185} 1394}
1186 1395
1187static int color_mode_to_bpp(enum omap_color_mode color_mode) 1396static int color_mode_to_bpp(enum omap_color_mode color_mode)
@@ -1194,12 +1403,17 @@ static int color_mode_to_bpp(enum omap_color_mode color_mode)
1194 case OMAP_DSS_COLOR_CLUT4: 1403 case OMAP_DSS_COLOR_CLUT4:
1195 return 4; 1404 return 4;
1196 case OMAP_DSS_COLOR_CLUT8: 1405 case OMAP_DSS_COLOR_CLUT8:
1406 case OMAP_DSS_COLOR_NV12:
1197 return 8; 1407 return 8;
1198 case OMAP_DSS_COLOR_RGB12U: 1408 case OMAP_DSS_COLOR_RGB12U:
1199 case OMAP_DSS_COLOR_RGB16: 1409 case OMAP_DSS_COLOR_RGB16:
1200 case OMAP_DSS_COLOR_ARGB16: 1410 case OMAP_DSS_COLOR_ARGB16:
1201 case OMAP_DSS_COLOR_YUV2: 1411 case OMAP_DSS_COLOR_YUV2:
1202 case OMAP_DSS_COLOR_UYVY: 1412 case OMAP_DSS_COLOR_UYVY:
1413 case OMAP_DSS_COLOR_RGBA16:
1414 case OMAP_DSS_COLOR_RGBX16:
1415 case OMAP_DSS_COLOR_ARGB16_1555:
1416 case OMAP_DSS_COLOR_XRGB16_1555:
1203 return 16; 1417 return 16;
1204 case OMAP_DSS_COLOR_RGB24P: 1418 case OMAP_DSS_COLOR_RGB24P:
1205 return 24; 1419 return 24;
@@ -1449,12 +1663,13 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1449 } 1663 }
1450} 1664}
1451 1665
1452static unsigned long calc_fclk_five_taps(u16 width, u16 height, 1666static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width,
1453 u16 out_width, u16 out_height, enum omap_color_mode color_mode) 1667 u16 height, u16 out_width, u16 out_height,
1668 enum omap_color_mode color_mode)
1454{ 1669{
1455 u32 fclk = 0; 1670 u32 fclk = 0;
1456 /* FIXME venc pclk? */ 1671 /* FIXME venc pclk? */
1457 u64 tmp, pclk = dispc_pclk_rate(); 1672 u64 tmp, pclk = dispc_pclk_rate(channel);
1458 1673
1459 if (height > out_height) { 1674 if (height > out_height) {
1460 /* FIXME get real display PPL */ 1675 /* FIXME get real display PPL */
@@ -1486,8 +1701,8 @@ static unsigned long calc_fclk_five_taps(u16 width, u16 height,
1486 return fclk; 1701 return fclk;
1487} 1702}
1488 1703
1489static unsigned long calc_fclk(u16 width, u16 height, 1704static unsigned long calc_fclk(enum omap_channel channel, u16 width,
1490 u16 out_width, u16 out_height) 1705 u16 height, u16 out_width, u16 out_height)
1491{ 1706{
1492 unsigned int hf, vf; 1707 unsigned int hf, vf;
1493 1708
@@ -1511,7 +1726,7 @@ static unsigned long calc_fclk(u16 width, u16 height,
1511 vf = 1; 1726 vf = 1;
1512 1727
1513 /* FIXME venc pclk? */ 1728 /* FIXME venc pclk? */
1514 return dispc_pclk_rate() * vf * hf; 1729 return dispc_pclk_rate(channel) * vf * hf;
1515} 1730}
1516 1731
1517void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out) 1732void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out)
@@ -1530,7 +1745,8 @@ static int _dispc_setup_plane(enum omap_plane plane,
1530 bool ilace, 1745 bool ilace,
1531 enum omap_dss_rotation_type rotation_type, 1746 enum omap_dss_rotation_type rotation_type,
1532 u8 rotation, int mirror, 1747 u8 rotation, int mirror,
1533 u8 global_alpha) 1748 u8 global_alpha, u8 pre_mult_alpha,
1749 enum omap_channel channel, u32 puv_addr)
1534{ 1750{
1535 const int maxdownscale = cpu_is_omap34xx() ? 4 : 2; 1751 const int maxdownscale = cpu_is_omap34xx() ? 4 : 2;
1536 bool five_taps = 0; 1752 bool five_taps = 0;
@@ -1559,27 +1775,12 @@ static int _dispc_setup_plane(enum omap_plane plane,
1559 height, pos_y, out_height); 1775 height, pos_y, out_height);
1560 } 1776 }
1561 1777
1778 if (!dss_feat_color_mode_supported(plane, color_mode))
1779 return -EINVAL;
1780
1562 if (plane == OMAP_DSS_GFX) { 1781 if (plane == OMAP_DSS_GFX) {
1563 if (width != out_width || height != out_height) 1782 if (width != out_width || height != out_height)
1564 return -EINVAL; 1783 return -EINVAL;
1565
1566 switch (color_mode) {
1567 case OMAP_DSS_COLOR_ARGB16:
1568 case OMAP_DSS_COLOR_ARGB32:
1569 case OMAP_DSS_COLOR_RGBA32:
1570 case OMAP_DSS_COLOR_RGBX32:
1571 if (cpu_is_omap24xx())
1572 return -EINVAL;
1573 /* fall through */
1574 case OMAP_DSS_COLOR_RGB12U:
1575 case OMAP_DSS_COLOR_RGB16:
1576 case OMAP_DSS_COLOR_RGB24P:
1577 case OMAP_DSS_COLOR_RGB24U:
1578 break;
1579
1580 default:
1581 return -EINVAL;
1582 }
1583 } else { 1784 } else {
1584 /* video plane */ 1785 /* video plane */
1585 1786
@@ -1593,41 +1794,17 @@ static int _dispc_setup_plane(enum omap_plane plane,
1593 out_height > height * 8) 1794 out_height > height * 8)
1594 return -EINVAL; 1795 return -EINVAL;
1595 1796
1596 switch (color_mode) { 1797 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1597 case OMAP_DSS_COLOR_RGBX32: 1798 color_mode == OMAP_DSS_COLOR_UYVY ||
1598 case OMAP_DSS_COLOR_RGB12U: 1799 color_mode == OMAP_DSS_COLOR_NV12)
1599 if (cpu_is_omap24xx())
1600 return -EINVAL;
1601 /* fall through */
1602 case OMAP_DSS_COLOR_RGB16:
1603 case OMAP_DSS_COLOR_RGB24P:
1604 case OMAP_DSS_COLOR_RGB24U:
1605 break;
1606
1607 case OMAP_DSS_COLOR_ARGB16:
1608 case OMAP_DSS_COLOR_ARGB32:
1609 case OMAP_DSS_COLOR_RGBA32:
1610 if (cpu_is_omap24xx())
1611 return -EINVAL;
1612 if (plane == OMAP_DSS_VIDEO1)
1613 return -EINVAL;
1614 break;
1615
1616 case OMAP_DSS_COLOR_YUV2:
1617 case OMAP_DSS_COLOR_UYVY:
1618 cconv = 1; 1800 cconv = 1;
1619 break;
1620
1621 default:
1622 return -EINVAL;
1623 }
1624 1801
1625 /* Must use 5-tap filter? */ 1802 /* Must use 5-tap filter? */
1626 five_taps = height > out_height * 2; 1803 five_taps = height > out_height * 2;
1627 1804
1628 if (!five_taps) { 1805 if (!five_taps) {
1629 fclk = calc_fclk(width, height, 1806 fclk = calc_fclk(channel, width, height, out_width,
1630 out_width, out_height); 1807 out_height);
1631 1808
1632 /* Try 5-tap filter if 3-tap fclk is too high */ 1809 /* Try 5-tap filter if 3-tap fclk is too high */
1633 if (cpu_is_omap34xx() && height > out_height && 1810 if (cpu_is_omap34xx() && height > out_height &&
@@ -1641,7 +1818,7 @@ static int _dispc_setup_plane(enum omap_plane plane,
1641 } 1818 }
1642 1819
1643 if (five_taps) 1820 if (five_taps)
1644 fclk = calc_fclk_five_taps(width, height, 1821 fclk = calc_fclk_five_taps(channel, width, height,
1645 out_width, out_height, color_mode); 1822 out_width, out_height, color_mode);
1646 1823
1647 DSSDBG("required fclk rate = %lu Hz\n", fclk); 1824 DSSDBG("required fclk rate = %lu Hz\n", fclk);
@@ -1693,6 +1870,12 @@ static int _dispc_setup_plane(enum omap_plane plane,
1693 _dispc_set_plane_ba0(plane, paddr + offset0); 1870 _dispc_set_plane_ba0(plane, paddr + offset0);
1694 _dispc_set_plane_ba1(plane, paddr + offset1); 1871 _dispc_set_plane_ba1(plane, paddr + offset1);
1695 1872
1873 if (OMAP_DSS_COLOR_NV12 == color_mode) {
1874 _dispc_set_plane_ba0_uv(plane, puv_addr + offset0);
1875 _dispc_set_plane_ba1_uv(plane, puv_addr + offset1);
1876 }
1877
1878
1696 _dispc_set_row_inc(plane, row_inc); 1879 _dispc_set_row_inc(plane, row_inc);
1697 _dispc_set_pix_inc(plane, pix_inc); 1880 _dispc_set_pix_inc(plane, pix_inc);
1698 1881
@@ -1706,22 +1889,23 @@ static int _dispc_setup_plane(enum omap_plane plane,
1706 if (plane != OMAP_DSS_GFX) { 1889 if (plane != OMAP_DSS_GFX) {
1707 _dispc_set_scaling(plane, width, height, 1890 _dispc_set_scaling(plane, width, height,
1708 out_width, out_height, 1891 out_width, out_height,
1709 ilace, five_taps, fieldmode); 1892 ilace, five_taps, fieldmode,
1893 color_mode, rotation);
1710 _dispc_set_vid_size(plane, out_width, out_height); 1894 _dispc_set_vid_size(plane, out_width, out_height);
1711 _dispc_set_vid_color_conv(plane, cconv); 1895 _dispc_set_vid_color_conv(plane, cconv);
1712 } 1896 }
1713 1897
1714 _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode); 1898 _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode);
1715 1899
1716 if (plane != OMAP_DSS_VIDEO1) 1900 _dispc_set_pre_mult_alpha(plane, pre_mult_alpha);
1717 _dispc_setup_global_alpha(plane, global_alpha); 1901 _dispc_setup_global_alpha(plane, global_alpha);
1718 1902
1719 return 0; 1903 return 0;
1720} 1904}
1721 1905
1722static void _dispc_enable_plane(enum omap_plane plane, bool enable) 1906static void _dispc_enable_plane(enum omap_plane plane, bool enable)
1723{ 1907{
1724 REG_FLD_MOD(dispc_reg_att[plane], enable ? 1 : 0, 0, 0); 1908 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
1725} 1909}
1726 1910
1727static void dispc_disable_isr(void *data, u32 mask) 1911static void dispc_disable_isr(void *data, u32 mask)
@@ -1730,36 +1914,44 @@ static void dispc_disable_isr(void *data, u32 mask)
1730 complete(compl); 1914 complete(compl);
1731} 1915}
1732 1916
1733static void _enable_lcd_out(bool enable) 1917static void _enable_lcd_out(enum omap_channel channel, bool enable)
1734{ 1918{
1735 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0); 1919 if (channel == OMAP_DSS_CHANNEL_LCD2)
1920 REG_FLD_MOD(DISPC_CONTROL2, enable ? 1 : 0, 0, 0);
1921 else
1922 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0);
1736} 1923}
1737 1924
1738static void dispc_enable_lcd_out(bool enable) 1925static void dispc_enable_lcd_out(enum omap_channel channel, bool enable)
1739{ 1926{
1740 struct completion frame_done_completion; 1927 struct completion frame_done_completion;
1741 bool is_on; 1928 bool is_on;
1742 int r; 1929 int r;
1930 u32 irq;
1743 1931
1744 enable_clocks(1); 1932 enable_clocks(1);
1745 1933
1746 /* When we disable LCD output, we need to wait until frame is done. 1934 /* When we disable LCD output, we need to wait until frame is done.
1747 * Otherwise the DSS is still working, and turning off the clocks 1935 * Otherwise the DSS is still working, and turning off the clocks
1748 * prevents DSS from going to OFF mode */ 1936 * prevents DSS from going to OFF mode */
1749 is_on = REG_GET(DISPC_CONTROL, 0, 0); 1937 is_on = channel == OMAP_DSS_CHANNEL_LCD2 ?
1938 REG_GET(DISPC_CONTROL2, 0, 0) :
1939 REG_GET(DISPC_CONTROL, 0, 0);
1940
1941 irq = channel == OMAP_DSS_CHANNEL_LCD2 ? DISPC_IRQ_FRAMEDONE2 :
1942 DISPC_IRQ_FRAMEDONE;
1750 1943
1751 if (!enable && is_on) { 1944 if (!enable && is_on) {
1752 init_completion(&frame_done_completion); 1945 init_completion(&frame_done_completion);
1753 1946
1754 r = omap_dispc_register_isr(dispc_disable_isr, 1947 r = omap_dispc_register_isr(dispc_disable_isr,
1755 &frame_done_completion, 1948 &frame_done_completion, irq);
1756 DISPC_IRQ_FRAMEDONE);
1757 1949
1758 if (r) 1950 if (r)
1759 DSSERR("failed to register FRAMEDONE isr\n"); 1951 DSSERR("failed to register FRAMEDONE isr\n");
1760 } 1952 }
1761 1953
1762 _enable_lcd_out(enable); 1954 _enable_lcd_out(channel, enable);
1763 1955
1764 if (!enable && is_on) { 1956 if (!enable && is_on) {
1765 if (!wait_for_completion_timeout(&frame_done_completion, 1957 if (!wait_for_completion_timeout(&frame_done_completion,
@@ -1767,8 +1959,7 @@ static void dispc_enable_lcd_out(bool enable)
1767 DSSERR("timeout waiting for FRAME DONE\n"); 1959 DSSERR("timeout waiting for FRAME DONE\n");
1768 1960
1769 r = omap_dispc_unregister_isr(dispc_disable_isr, 1961 r = omap_dispc_unregister_isr(dispc_disable_isr,
1770 &frame_done_completion, 1962 &frame_done_completion, irq);
1771 DISPC_IRQ_FRAMEDONE);
1772 1963
1773 if (r) 1964 if (r)
1774 DSSERR("failed to unregister FRAMEDONE isr\n"); 1965 DSSERR("failed to unregister FRAMEDONE isr\n");
@@ -1838,6 +2029,8 @@ static void dispc_enable_digit_out(bool enable)
1838 unsigned long flags; 2029 unsigned long flags;
1839 spin_lock_irqsave(&dispc.irq_lock, flags); 2030 spin_lock_irqsave(&dispc.irq_lock, flags);
1840 dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; 2031 dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
2032 if (dss_has_feature(FEAT_MGR_LCD2))
2033 dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
1841 dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); 2034 dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
1842 _omap_dispc_set_irqs(); 2035 _omap_dispc_set_irqs();
1843 spin_unlock_irqrestore(&dispc.irq_lock, flags); 2036 spin_unlock_irqrestore(&dispc.irq_lock, flags);
@@ -1852,14 +2045,17 @@ bool dispc_is_channel_enabled(enum omap_channel channel)
1852 return !!REG_GET(DISPC_CONTROL, 0, 0); 2045 return !!REG_GET(DISPC_CONTROL, 0, 0);
1853 else if (channel == OMAP_DSS_CHANNEL_DIGIT) 2046 else if (channel == OMAP_DSS_CHANNEL_DIGIT)
1854 return !!REG_GET(DISPC_CONTROL, 1, 1); 2047 return !!REG_GET(DISPC_CONTROL, 1, 1);
2048 else if (channel == OMAP_DSS_CHANNEL_LCD2)
2049 return !!REG_GET(DISPC_CONTROL2, 0, 0);
1855 else 2050 else
1856 BUG(); 2051 BUG();
1857} 2052}
1858 2053
1859void dispc_enable_channel(enum omap_channel channel, bool enable) 2054void dispc_enable_channel(enum omap_channel channel, bool enable)
1860{ 2055{
1861 if (channel == OMAP_DSS_CHANNEL_LCD) 2056 if (channel == OMAP_DSS_CHANNEL_LCD ||
1862 dispc_enable_lcd_out(enable); 2057 channel == OMAP_DSS_CHANNEL_LCD2)
2058 dispc_enable_lcd_out(channel, enable);
1863 else if (channel == OMAP_DSS_CHANNEL_DIGIT) 2059 else if (channel == OMAP_DSS_CHANNEL_DIGIT)
1864 dispc_enable_digit_out(enable); 2060 dispc_enable_digit_out(enable);
1865 else 2061 else
@@ -1868,6 +2064,9 @@ void dispc_enable_channel(enum omap_channel channel, bool enable)
1868 2064
1869void dispc_lcd_enable_signal_polarity(bool act_high) 2065void dispc_lcd_enable_signal_polarity(bool act_high)
1870{ 2066{
2067 if (!dss_has_feature(FEAT_LCDENABLEPOL))
2068 return;
2069
1871 enable_clocks(1); 2070 enable_clocks(1);
1872 REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29); 2071 REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
1873 enable_clocks(0); 2072 enable_clocks(0);
@@ -1875,6 +2074,9 @@ void dispc_lcd_enable_signal_polarity(bool act_high)
1875 2074
1876void dispc_lcd_enable_signal(bool enable) 2075void dispc_lcd_enable_signal(bool enable)
1877{ 2076{
2077 if (!dss_has_feature(FEAT_LCDENABLESIGNAL))
2078 return;
2079
1878 enable_clocks(1); 2080 enable_clocks(1);
1879 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28); 2081 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
1880 enable_clocks(0); 2082 enable_clocks(0);
@@ -1882,20 +2084,27 @@ void dispc_lcd_enable_signal(bool enable)
1882 2084
1883void dispc_pck_free_enable(bool enable) 2085void dispc_pck_free_enable(bool enable)
1884{ 2086{
2087 if (!dss_has_feature(FEAT_PCKFREEENABLE))
2088 return;
2089
1885 enable_clocks(1); 2090 enable_clocks(1);
1886 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); 2091 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
1887 enable_clocks(0); 2092 enable_clocks(0);
1888} 2093}
1889 2094
1890void dispc_enable_fifohandcheck(bool enable) 2095void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable)
1891{ 2096{
1892 enable_clocks(1); 2097 enable_clocks(1);
1893 REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16); 2098 if (channel == OMAP_DSS_CHANNEL_LCD2)
2099 REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16);
2100 else
2101 REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16);
1894 enable_clocks(0); 2102 enable_clocks(0);
1895} 2103}
1896 2104
1897 2105
1898void dispc_set_lcd_display_type(enum omap_lcd_display_type type) 2106void dispc_set_lcd_display_type(enum omap_channel channel,
2107 enum omap_lcd_display_type type)
1899{ 2108{
1900 int mode; 2109 int mode;
1901 2110
@@ -1914,7 +2123,10 @@ void dispc_set_lcd_display_type(enum omap_lcd_display_type type)
1914 } 2123 }
1915 2124
1916 enable_clocks(1); 2125 enable_clocks(1);
1917 REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3); 2126 if (channel == OMAP_DSS_CHANNEL_LCD2)
2127 REG_FLD_MOD(DISPC_CONTROL2, mode, 3, 3);
2128 else
2129 REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3);
1918 enable_clocks(0); 2130 enable_clocks(0);
1919} 2131}
1920 2132
@@ -1928,25 +2140,21 @@ void dispc_set_loadmode(enum omap_dss_load_mode mode)
1928 2140
1929void dispc_set_default_color(enum omap_channel channel, u32 color) 2141void dispc_set_default_color(enum omap_channel channel, u32 color)
1930{ 2142{
1931 const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0,
1932 DISPC_DEFAULT_COLOR1 };
1933
1934 enable_clocks(1); 2143 enable_clocks(1);
1935 dispc_write_reg(def_reg[channel], color); 2144 dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color);
1936 enable_clocks(0); 2145 enable_clocks(0);
1937} 2146}
1938 2147
1939u32 dispc_get_default_color(enum omap_channel channel) 2148u32 dispc_get_default_color(enum omap_channel channel)
1940{ 2149{
1941 const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0,
1942 DISPC_DEFAULT_COLOR1 };
1943 u32 l; 2150 u32 l;
1944 2151
1945 BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT && 2152 BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT &&
1946 channel != OMAP_DSS_CHANNEL_LCD); 2153 channel != OMAP_DSS_CHANNEL_LCD &&
2154 channel != OMAP_DSS_CHANNEL_LCD2);
1947 2155
1948 enable_clocks(1); 2156 enable_clocks(1);
1949 l = dispc_read_reg(def_reg[channel]); 2157 l = dispc_read_reg(DISPC_DEFAULT_COLOR(channel));
1950 enable_clocks(0); 2158 enable_clocks(0);
1951 2159
1952 return l; 2160 return l;
@@ -1956,16 +2164,15 @@ void dispc_set_trans_key(enum omap_channel ch,
1956 enum omap_dss_trans_key_type type, 2164 enum omap_dss_trans_key_type type,
1957 u32 trans_key) 2165 u32 trans_key)
1958{ 2166{
1959 const struct dispc_reg tr_reg[] = {
1960 DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 };
1961
1962 enable_clocks(1); 2167 enable_clocks(1);
1963 if (ch == OMAP_DSS_CHANNEL_LCD) 2168 if (ch == OMAP_DSS_CHANNEL_LCD)
1964 REG_FLD_MOD(DISPC_CONFIG, type, 11, 11); 2169 REG_FLD_MOD(DISPC_CONFIG, type, 11, 11);
1965 else /* OMAP_DSS_CHANNEL_DIGIT */ 2170 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
1966 REG_FLD_MOD(DISPC_CONFIG, type, 13, 13); 2171 REG_FLD_MOD(DISPC_CONFIG, type, 13, 13);
2172 else /* OMAP_DSS_CHANNEL_LCD2 */
2173 REG_FLD_MOD(DISPC_CONFIG2, type, 11, 11);
1967 2174
1968 dispc_write_reg(tr_reg[ch], trans_key); 2175 dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key);
1969 enable_clocks(0); 2176 enable_clocks(0);
1970} 2177}
1971 2178
@@ -1973,21 +2180,20 @@ void dispc_get_trans_key(enum omap_channel ch,
1973 enum omap_dss_trans_key_type *type, 2180 enum omap_dss_trans_key_type *type,
1974 u32 *trans_key) 2181 u32 *trans_key)
1975{ 2182{
1976 const struct dispc_reg tr_reg[] = {
1977 DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 };
1978
1979 enable_clocks(1); 2183 enable_clocks(1);
1980 if (type) { 2184 if (type) {
1981 if (ch == OMAP_DSS_CHANNEL_LCD) 2185 if (ch == OMAP_DSS_CHANNEL_LCD)
1982 *type = REG_GET(DISPC_CONFIG, 11, 11); 2186 *type = REG_GET(DISPC_CONFIG, 11, 11);
1983 else if (ch == OMAP_DSS_CHANNEL_DIGIT) 2187 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
1984 *type = REG_GET(DISPC_CONFIG, 13, 13); 2188 *type = REG_GET(DISPC_CONFIG, 13, 13);
2189 else if (ch == OMAP_DSS_CHANNEL_LCD2)
2190 *type = REG_GET(DISPC_CONFIG2, 11, 11);
1985 else 2191 else
1986 BUG(); 2192 BUG();
1987 } 2193 }
1988 2194
1989 if (trans_key) 2195 if (trans_key)
1990 *trans_key = dispc_read_reg(tr_reg[ch]); 2196 *trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch));
1991 enable_clocks(0); 2197 enable_clocks(0);
1992} 2198}
1993 2199
@@ -1996,40 +2202,45 @@ void dispc_enable_trans_key(enum omap_channel ch, bool enable)
1996 enable_clocks(1); 2202 enable_clocks(1);
1997 if (ch == OMAP_DSS_CHANNEL_LCD) 2203 if (ch == OMAP_DSS_CHANNEL_LCD)
1998 REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10); 2204 REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
1999 else /* OMAP_DSS_CHANNEL_DIGIT */ 2205 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
2000 REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12); 2206 REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12);
2207 else /* OMAP_DSS_CHANNEL_LCD2 */
2208 REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10);
2001 enable_clocks(0); 2209 enable_clocks(0);
2002} 2210}
2003void dispc_enable_alpha_blending(enum omap_channel ch, bool enable) 2211void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
2004{ 2212{
2005 if (cpu_is_omap24xx()) 2213 if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
2006 return; 2214 return;
2007 2215
2008 enable_clocks(1); 2216 enable_clocks(1);
2009 if (ch == OMAP_DSS_CHANNEL_LCD) 2217 if (ch == OMAP_DSS_CHANNEL_LCD)
2010 REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18); 2218 REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
2011 else /* OMAP_DSS_CHANNEL_DIGIT */ 2219 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
2012 REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19); 2220 REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
2221 else /* OMAP_DSS_CHANNEL_LCD2 */
2222 REG_FLD_MOD(DISPC_CONFIG2, enable, 18, 18);
2013 enable_clocks(0); 2223 enable_clocks(0);
2014} 2224}
2015bool dispc_alpha_blending_enabled(enum omap_channel ch) 2225bool dispc_alpha_blending_enabled(enum omap_channel ch)
2016{ 2226{
2017 bool enabled; 2227 bool enabled;
2018 2228
2019 if (cpu_is_omap24xx()) 2229 if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
2020 return false; 2230 return false;
2021 2231
2022 enable_clocks(1); 2232 enable_clocks(1);
2023 if (ch == OMAP_DSS_CHANNEL_LCD) 2233 if (ch == OMAP_DSS_CHANNEL_LCD)
2024 enabled = REG_GET(DISPC_CONFIG, 18, 18); 2234 enabled = REG_GET(DISPC_CONFIG, 18, 18);
2025 else if (ch == OMAP_DSS_CHANNEL_DIGIT) 2235 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
2026 enabled = REG_GET(DISPC_CONFIG, 18, 18); 2236 enabled = REG_GET(DISPC_CONFIG, 19, 19);
2237 else if (ch == OMAP_DSS_CHANNEL_LCD2)
2238 enabled = REG_GET(DISPC_CONFIG2, 18, 18);
2027 else 2239 else
2028 BUG(); 2240 BUG();
2029 enable_clocks(0); 2241 enable_clocks(0);
2030 2242
2031 return enabled; 2243 return enabled;
2032
2033} 2244}
2034 2245
2035 2246
@@ -2042,6 +2253,8 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
2042 enabled = REG_GET(DISPC_CONFIG, 10, 10); 2253 enabled = REG_GET(DISPC_CONFIG, 10, 10);
2043 else if (ch == OMAP_DSS_CHANNEL_DIGIT) 2254 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
2044 enabled = REG_GET(DISPC_CONFIG, 12, 12); 2255 enabled = REG_GET(DISPC_CONFIG, 12, 12);
2256 else if (ch == OMAP_DSS_CHANNEL_LCD2)
2257 enabled = REG_GET(DISPC_CONFIG2, 10, 10);
2045 else 2258 else
2046 BUG(); 2259 BUG();
2047 enable_clocks(0); 2260 enable_clocks(0);
@@ -2050,7 +2263,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
2050} 2263}
2051 2264
2052 2265
2053void dispc_set_tft_data_lines(u8 data_lines) 2266void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
2054{ 2267{
2055 int code; 2268 int code;
2056 2269
@@ -2073,11 +2286,15 @@ void dispc_set_tft_data_lines(u8 data_lines)
2073 } 2286 }
2074 2287
2075 enable_clocks(1); 2288 enable_clocks(1);
2076 REG_FLD_MOD(DISPC_CONTROL, code, 9, 8); 2289 if (channel == OMAP_DSS_CHANNEL_LCD2)
2290 REG_FLD_MOD(DISPC_CONTROL2, code, 9, 8);
2291 else
2292 REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
2077 enable_clocks(0); 2293 enable_clocks(0);
2078} 2294}
2079 2295
2080void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode) 2296void dispc_set_parallel_interface_mode(enum omap_channel channel,
2297 enum omap_parallel_interface_mode mode)
2081{ 2298{
2082 u32 l; 2299 u32 l;
2083 int stallmode; 2300 int stallmode;
@@ -2107,13 +2324,17 @@ void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode)
2107 2324
2108 enable_clocks(1); 2325 enable_clocks(1);
2109 2326
2110 l = dispc_read_reg(DISPC_CONTROL); 2327 if (channel == OMAP_DSS_CHANNEL_LCD2) {
2111 2328 l = dispc_read_reg(DISPC_CONTROL2);
2112 l = FLD_MOD(l, stallmode, 11, 11); 2329 l = FLD_MOD(l, stallmode, 11, 11);
2113 l = FLD_MOD(l, gpout0, 15, 15); 2330 dispc_write_reg(DISPC_CONTROL2, l);
2114 l = FLD_MOD(l, gpout1, 16, 16); 2331 } else {
2115 2332 l = dispc_read_reg(DISPC_CONTROL);
2116 dispc_write_reg(DISPC_CONTROL, l); 2333 l = FLD_MOD(l, stallmode, 11, 11);
2334 l = FLD_MOD(l, gpout0, 15, 15);
2335 l = FLD_MOD(l, gpout1, 16, 16);
2336 dispc_write_reg(DISPC_CONTROL, l);
2337 }
2117 2338
2118 enable_clocks(0); 2339 enable_clocks(0);
2119} 2340}
@@ -2149,8 +2370,8 @@ bool dispc_lcd_timings_ok(struct omap_video_timings *timings)
2149 timings->vfp, timings->vbp); 2370 timings->vfp, timings->vbp);
2150} 2371}
2151 2372
2152static void _dispc_set_lcd_timings(int hsw, int hfp, int hbp, 2373static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw,
2153 int vsw, int vfp, int vbp) 2374 int hfp, int hbp, int vsw, int vfp, int vbp)
2154{ 2375{
2155 u32 timing_h, timing_v; 2376 u32 timing_h, timing_v;
2156 2377
@@ -2169,13 +2390,14 @@ static void _dispc_set_lcd_timings(int hsw, int hfp, int hbp,
2169 } 2390 }
2170 2391
2171 enable_clocks(1); 2392 enable_clocks(1);
2172 dispc_write_reg(DISPC_TIMING_H, timing_h); 2393 dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
2173 dispc_write_reg(DISPC_TIMING_V, timing_v); 2394 dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
2174 enable_clocks(0); 2395 enable_clocks(0);
2175} 2396}
2176 2397
2177/* change name to mode? */ 2398/* change name to mode? */
2178void dispc_set_lcd_timings(struct omap_video_timings *timings) 2399void dispc_set_lcd_timings(enum omap_channel channel,
2400 struct omap_video_timings *timings)
2179{ 2401{
2180 unsigned xtot, ytot; 2402 unsigned xtot, ytot;
2181 unsigned long ht, vt; 2403 unsigned long ht, vt;
@@ -2185,10 +2407,11 @@ void dispc_set_lcd_timings(struct omap_video_timings *timings)
2185 timings->vfp, timings->vbp)) 2407 timings->vfp, timings->vbp))
2186 BUG(); 2408 BUG();
2187 2409
2188 _dispc_set_lcd_timings(timings->hsw, timings->hfp, timings->hbp, 2410 _dispc_set_lcd_timings(channel, timings->hsw, timings->hfp,
2189 timings->vsw, timings->vfp, timings->vbp); 2411 timings->hbp, timings->vsw, timings->vfp,
2412 timings->vbp);
2190 2413
2191 dispc_set_lcd_size(timings->x_res, timings->y_res); 2414 dispc_set_lcd_size(channel, timings->x_res, timings->y_res);
2192 2415
2193 xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp; 2416 xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp;
2194 ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp; 2417 ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp;
@@ -2196,7 +2419,8 @@ void dispc_set_lcd_timings(struct omap_video_timings *timings)
2196 ht = (timings->pixel_clock * 1000) / xtot; 2419 ht = (timings->pixel_clock * 1000) / xtot;
2197 vt = (timings->pixel_clock * 1000) / xtot / ytot; 2420 vt = (timings->pixel_clock * 1000) / xtot / ytot;
2198 2421
2199 DSSDBG("xres %u yres %u\n", timings->x_res, timings->y_res); 2422 DSSDBG("channel %d xres %u yres %u\n", channel, timings->x_res,
2423 timings->y_res);
2200 DSSDBG("pck %u\n", timings->pixel_clock); 2424 DSSDBG("pck %u\n", timings->pixel_clock);
2201 DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", 2425 DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n",
2202 timings->hsw, timings->hfp, timings->hbp, 2426 timings->hsw, timings->hfp, timings->hbp,
@@ -2205,89 +2429,151 @@ void dispc_set_lcd_timings(struct omap_video_timings *timings)
2205 DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); 2429 DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt);
2206} 2430}
2207 2431
2208static void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div) 2432static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
2433 u16 pck_div)
2209{ 2434{
2210 BUG_ON(lck_div < 1); 2435 BUG_ON(lck_div < 1);
2211 BUG_ON(pck_div < 2); 2436 BUG_ON(pck_div < 2);
2212 2437
2213 enable_clocks(1); 2438 enable_clocks(1);
2214 dispc_write_reg(DISPC_DIVISOR, 2439 dispc_write_reg(DISPC_DIVISORo(channel),
2215 FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); 2440 FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
2216 enable_clocks(0); 2441 enable_clocks(0);
2217} 2442}
2218 2443
2219static void dispc_get_lcd_divisor(int *lck_div, int *pck_div) 2444static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div,
2445 int *pck_div)
2220{ 2446{
2221 u32 l; 2447 u32 l;
2222 l = dispc_read_reg(DISPC_DIVISOR); 2448 l = dispc_read_reg(DISPC_DIVISORo(channel));
2223 *lck_div = FLD_GET(l, 23, 16); 2449 *lck_div = FLD_GET(l, 23, 16);
2224 *pck_div = FLD_GET(l, 7, 0); 2450 *pck_div = FLD_GET(l, 7, 0);
2225} 2451}
2226 2452
2227unsigned long dispc_fclk_rate(void) 2453unsigned long dispc_fclk_rate(void)
2228{ 2454{
2455 struct platform_device *dsidev;
2229 unsigned long r = 0; 2456 unsigned long r = 0;
2230 2457
2231 if (dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK) 2458 switch (dss_get_dispc_clk_source()) {
2232 r = dss_clk_get_rate(DSS_CLK_FCK1); 2459 case OMAP_DSS_CLK_SRC_FCK:
2233 else 2460 r = dss_clk_get_rate(DSS_CLK_FCK);
2234#ifdef CONFIG_OMAP2_DSS_DSI 2461 break;
2235 r = dsi_get_dsi1_pll_rate(); 2462 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
2236#else 2463 dsidev = dsi_get_dsidev_from_id(0);
2237 BUG(); 2464 r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
2238#endif 2465 break;
2466 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
2467 dsidev = dsi_get_dsidev_from_id(1);
2468 r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
2469 break;
2470 default:
2471 BUG();
2472 }
2473
2239 return r; 2474 return r;
2240} 2475}
2241 2476
2242unsigned long dispc_lclk_rate(void) 2477unsigned long dispc_lclk_rate(enum omap_channel channel)
2243{ 2478{
2479 struct platform_device *dsidev;
2244 int lcd; 2480 int lcd;
2245 unsigned long r; 2481 unsigned long r;
2246 u32 l; 2482 u32 l;
2247 2483
2248 l = dispc_read_reg(DISPC_DIVISOR); 2484 l = dispc_read_reg(DISPC_DIVISORo(channel));
2249 2485
2250 lcd = FLD_GET(l, 23, 16); 2486 lcd = FLD_GET(l, 23, 16);
2251 2487
2252 r = dispc_fclk_rate(); 2488 switch (dss_get_lcd_clk_source(channel)) {
2489 case OMAP_DSS_CLK_SRC_FCK:
2490 r = dss_clk_get_rate(DSS_CLK_FCK);
2491 break;
2492 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
2493 dsidev = dsi_get_dsidev_from_id(0);
2494 r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
2495 break;
2496 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
2497 dsidev = dsi_get_dsidev_from_id(1);
2498 r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
2499 break;
2500 default:
2501 BUG();
2502 }
2253 2503
2254 return r / lcd; 2504 return r / lcd;
2255} 2505}
2256 2506
2257unsigned long dispc_pclk_rate(void) 2507unsigned long dispc_pclk_rate(enum omap_channel channel)
2258{ 2508{
2259 int lcd, pcd; 2509 int pcd;
2260 unsigned long r; 2510 unsigned long r;
2261 u32 l; 2511 u32 l;
2262 2512
2263 l = dispc_read_reg(DISPC_DIVISOR); 2513 l = dispc_read_reg(DISPC_DIVISORo(channel));
2264 2514
2265 lcd = FLD_GET(l, 23, 16);
2266 pcd = FLD_GET(l, 7, 0); 2515 pcd = FLD_GET(l, 7, 0);
2267 2516
2268 r = dispc_fclk_rate(); 2517 r = dispc_lclk_rate(channel);
2269 2518
2270 return r / lcd / pcd; 2519 return r / pcd;
2271} 2520}
2272 2521
2273void dispc_dump_clocks(struct seq_file *s) 2522void dispc_dump_clocks(struct seq_file *s)
2274{ 2523{
2275 int lcd, pcd; 2524 int lcd, pcd;
2525 u32 l;
2526 enum omap_dss_clk_source dispc_clk_src = dss_get_dispc_clk_source();
2527 enum omap_dss_clk_source lcd_clk_src;
2276 2528
2277 enable_clocks(1); 2529 enable_clocks(1);
2278 2530
2279 dispc_get_lcd_divisor(&lcd, &pcd);
2280
2281 seq_printf(s, "- DISPC -\n"); 2531 seq_printf(s, "- DISPC -\n");
2282 2532
2283 seq_printf(s, "dispc fclk source = %s\n", 2533 seq_printf(s, "dispc fclk source = %s (%s)\n",
2284 dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ? 2534 dss_get_generic_clk_source_name(dispc_clk_src),
2285 "dss1_alwon_fclk" : "dsi1_pll_fclk"); 2535 dss_feat_get_clk_source_name(dispc_clk_src));
2286 2536
2287 seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate()); 2537 seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate());
2288 seq_printf(s, "lck\t\t%-16lulck div\t%u\n", dispc_lclk_rate(), lcd);
2289 seq_printf(s, "pck\t\t%-16lupck div\t%u\n", dispc_pclk_rate(), pcd);
2290 2538
2539 if (dss_has_feature(FEAT_CORE_CLK_DIV)) {
2540 seq_printf(s, "- DISPC-CORE-CLK -\n");
2541 l = dispc_read_reg(DISPC_DIVISOR);
2542 lcd = FLD_GET(l, 23, 16);
2543
2544 seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
2545 (dispc_fclk_rate()/lcd), lcd);
2546 }
2547 seq_printf(s, "- LCD1 -\n");
2548
2549 lcd_clk_src = dss_get_lcd_clk_source(OMAP_DSS_CHANNEL_LCD);
2550
2551 seq_printf(s, "lcd1_clk source = %s (%s)\n",
2552 dss_get_generic_clk_source_name(lcd_clk_src),
2553 dss_feat_get_clk_source_name(lcd_clk_src));
2554
2555 dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd);
2556
2557 seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
2558 dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD), lcd);
2559 seq_printf(s, "pck\t\t%-16lupck div\t%u\n",
2560 dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD), pcd);
2561 if (dss_has_feature(FEAT_MGR_LCD2)) {
2562 seq_printf(s, "- LCD2 -\n");
2563
2564 lcd_clk_src = dss_get_lcd_clk_source(OMAP_DSS_CHANNEL_LCD2);
2565
2566 seq_printf(s, "lcd2_clk source = %s (%s)\n",
2567 dss_get_generic_clk_source_name(lcd_clk_src),
2568 dss_feat_get_clk_source_name(lcd_clk_src));
2569
2570 dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd);
2571
2572 seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
2573 dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD2), lcd);
2574 seq_printf(s, "pck\t\t%-16lupck div\t%u\n",
2575 dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd);
2576 }
2291 enable_clocks(0); 2577 enable_clocks(0);
2292} 2578}
2293 2579
@@ -2329,15 +2615,21 @@ void dispc_dump_irqs(struct seq_file *s)
2329 PIS(SYNC_LOST); 2615 PIS(SYNC_LOST);
2330 PIS(SYNC_LOST_DIGIT); 2616 PIS(SYNC_LOST_DIGIT);
2331 PIS(WAKEUP); 2617 PIS(WAKEUP);
2618 if (dss_has_feature(FEAT_MGR_LCD2)) {
2619 PIS(FRAMEDONE2);
2620 PIS(VSYNC2);
2621 PIS(ACBIAS_COUNT_STAT2);
2622 PIS(SYNC_LOST2);
2623 }
2332#undef PIS 2624#undef PIS
2333} 2625}
2334#endif 2626#endif
2335 2627
2336void dispc_dump_regs(struct seq_file *s) 2628void dispc_dump_regs(struct seq_file *s)
2337{ 2629{
2338#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r)) 2630#define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r))
2339 2631
2340 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); 2632 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
2341 2633
2342 DUMPREG(DISPC_REVISION); 2634 DUMPREG(DISPC_REVISION);
2343 DUMPREG(DISPC_SYSCONFIG); 2635 DUMPREG(DISPC_SYSCONFIG);
@@ -2347,139 +2639,234 @@ void dispc_dump_regs(struct seq_file *s)
2347 DUMPREG(DISPC_CONTROL); 2639 DUMPREG(DISPC_CONTROL);
2348 DUMPREG(DISPC_CONFIG); 2640 DUMPREG(DISPC_CONFIG);
2349 DUMPREG(DISPC_CAPABLE); 2641 DUMPREG(DISPC_CAPABLE);
2350 DUMPREG(DISPC_DEFAULT_COLOR0); 2642 DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD));
2351 DUMPREG(DISPC_DEFAULT_COLOR1); 2643 DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT));
2352 DUMPREG(DISPC_TRANS_COLOR0); 2644 DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_LCD));
2353 DUMPREG(DISPC_TRANS_COLOR1); 2645 DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT));
2354 DUMPREG(DISPC_LINE_STATUS); 2646 DUMPREG(DISPC_LINE_STATUS);
2355 DUMPREG(DISPC_LINE_NUMBER); 2647 DUMPREG(DISPC_LINE_NUMBER);
2356 DUMPREG(DISPC_TIMING_H); 2648 DUMPREG(DISPC_TIMING_H(OMAP_DSS_CHANNEL_LCD));
2357 DUMPREG(DISPC_TIMING_V); 2649 DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD));
2358 DUMPREG(DISPC_POL_FREQ); 2650 DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD));
2359 DUMPREG(DISPC_DIVISOR); 2651 DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD));
2360 DUMPREG(DISPC_GLOBAL_ALPHA); 2652 DUMPREG(DISPC_GLOBAL_ALPHA);
2361 DUMPREG(DISPC_SIZE_DIG); 2653 DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
2362 DUMPREG(DISPC_SIZE_LCD); 2654 DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
2363 2655 if (dss_has_feature(FEAT_MGR_LCD2)) {
2364 DUMPREG(DISPC_GFX_BA0); 2656 DUMPREG(DISPC_CONTROL2);
2365 DUMPREG(DISPC_GFX_BA1); 2657 DUMPREG(DISPC_CONFIG2);
2366 DUMPREG(DISPC_GFX_POSITION); 2658 DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2));
2367 DUMPREG(DISPC_GFX_SIZE); 2659 DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2));
2368 DUMPREG(DISPC_GFX_ATTRIBUTES); 2660 DUMPREG(DISPC_TIMING_H(OMAP_DSS_CHANNEL_LCD2));
2369 DUMPREG(DISPC_GFX_FIFO_THRESHOLD); 2661 DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD2));
2370 DUMPREG(DISPC_GFX_FIFO_SIZE_STATUS); 2662 DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD2));
2371 DUMPREG(DISPC_GFX_ROW_INC); 2663 DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD2));
2372 DUMPREG(DISPC_GFX_PIXEL_INC); 2664 DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD2));
2373 DUMPREG(DISPC_GFX_WINDOW_SKIP); 2665 }
2374 DUMPREG(DISPC_GFX_TABLE_BA); 2666
2375 2667 DUMPREG(DISPC_OVL_BA0(OMAP_DSS_GFX));
2376 DUMPREG(DISPC_DATA_CYCLE1); 2668 DUMPREG(DISPC_OVL_BA1(OMAP_DSS_GFX));
2377 DUMPREG(DISPC_DATA_CYCLE2); 2669 DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_GFX));
2378 DUMPREG(DISPC_DATA_CYCLE3); 2670 DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_GFX));
2379 2671 DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_GFX));
2380 DUMPREG(DISPC_CPR_COEF_R); 2672 DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_GFX));
2381 DUMPREG(DISPC_CPR_COEF_G); 2673 DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_GFX));
2382 DUMPREG(DISPC_CPR_COEF_B); 2674 DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_GFX));
2383 2675 DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_GFX));
2384 DUMPREG(DISPC_GFX_PRELOAD); 2676 DUMPREG(DISPC_OVL_WINDOW_SKIP(OMAP_DSS_GFX));
2385 2677 DUMPREG(DISPC_OVL_TABLE_BA(OMAP_DSS_GFX));
2386 DUMPREG(DISPC_VID_BA0(0)); 2678
2387 DUMPREG(DISPC_VID_BA1(0)); 2679 DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD));
2388 DUMPREG(DISPC_VID_POSITION(0)); 2680 DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
2389 DUMPREG(DISPC_VID_SIZE(0)); 2681 DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
2390 DUMPREG(DISPC_VID_ATTRIBUTES(0)); 2682
2391 DUMPREG(DISPC_VID_FIFO_THRESHOLD(0)); 2683 DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
2392 DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(0)); 2684 DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
2393 DUMPREG(DISPC_VID_ROW_INC(0)); 2685 DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
2394 DUMPREG(DISPC_VID_PIXEL_INC(0)); 2686 if (dss_has_feature(FEAT_MGR_LCD2)) {
2395 DUMPREG(DISPC_VID_FIR(0)); 2687 DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
2396 DUMPREG(DISPC_VID_PICTURE_SIZE(0)); 2688 DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
2397 DUMPREG(DISPC_VID_ACCU0(0)); 2689 DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
2398 DUMPREG(DISPC_VID_ACCU1(0)); 2690
2399 2691 DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
2400 DUMPREG(DISPC_VID_BA0(1)); 2692 DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
2401 DUMPREG(DISPC_VID_BA1(1)); 2693 DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
2402 DUMPREG(DISPC_VID_POSITION(1)); 2694 }
2403 DUMPREG(DISPC_VID_SIZE(1)); 2695
2404 DUMPREG(DISPC_VID_ATTRIBUTES(1)); 2696 DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX));
2405 DUMPREG(DISPC_VID_FIFO_THRESHOLD(1)); 2697
2406 DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(1)); 2698 DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO1));
2407 DUMPREG(DISPC_VID_ROW_INC(1)); 2699 DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO1));
2408 DUMPREG(DISPC_VID_PIXEL_INC(1)); 2700 DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_VIDEO1));
2409 DUMPREG(DISPC_VID_FIR(1)); 2701 DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_VIDEO1));
2410 DUMPREG(DISPC_VID_PICTURE_SIZE(1)); 2702 DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO1));
2411 DUMPREG(DISPC_VID_ACCU0(1)); 2703 DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1));
2412 DUMPREG(DISPC_VID_ACCU1(1)); 2704 DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_VIDEO1));
2413 2705 DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_VIDEO1));
2414 DUMPREG(DISPC_VID_FIR_COEF_H(0, 0)); 2706 DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_VIDEO1));
2415 DUMPREG(DISPC_VID_FIR_COEF_H(0, 1)); 2707 DUMPREG(DISPC_OVL_FIR(OMAP_DSS_VIDEO1));
2416 DUMPREG(DISPC_VID_FIR_COEF_H(0, 2)); 2708 DUMPREG(DISPC_OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1));
2417 DUMPREG(DISPC_VID_FIR_COEF_H(0, 3)); 2709 DUMPREG(DISPC_OVL_ACCU0(OMAP_DSS_VIDEO1));
2418 DUMPREG(DISPC_VID_FIR_COEF_H(0, 4)); 2710 DUMPREG(DISPC_OVL_ACCU1(OMAP_DSS_VIDEO1));
2419 DUMPREG(DISPC_VID_FIR_COEF_H(0, 5)); 2711
2420 DUMPREG(DISPC_VID_FIR_COEF_H(0, 6)); 2712 DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO2));
2421 DUMPREG(DISPC_VID_FIR_COEF_H(0, 7)); 2713 DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO2));
2422 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 0)); 2714 DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_VIDEO2));
2423 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 1)); 2715 DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_VIDEO2));
2424 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 2)); 2716 DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO2));
2425 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 3)); 2717 DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2));
2426 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 4)); 2718 DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_VIDEO2));
2427 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 5)); 2719 DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_VIDEO2));
2428 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 6)); 2720 DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_VIDEO2));
2429 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 7)); 2721 DUMPREG(DISPC_OVL_FIR(OMAP_DSS_VIDEO2));
2430 DUMPREG(DISPC_VID_CONV_COEF(0, 0)); 2722 DUMPREG(DISPC_OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2));
2431 DUMPREG(DISPC_VID_CONV_COEF(0, 1)); 2723 DUMPREG(DISPC_OVL_ACCU0(OMAP_DSS_VIDEO2));
2432 DUMPREG(DISPC_VID_CONV_COEF(0, 2)); 2724 DUMPREG(DISPC_OVL_ACCU1(OMAP_DSS_VIDEO2));
2433 DUMPREG(DISPC_VID_CONV_COEF(0, 3)); 2725
2434 DUMPREG(DISPC_VID_CONV_COEF(0, 4)); 2726 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 0));
2435 DUMPREG(DISPC_VID_FIR_COEF_V(0, 0)); 2727 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 1));
2436 DUMPREG(DISPC_VID_FIR_COEF_V(0, 1)); 2728 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 2));
2437 DUMPREG(DISPC_VID_FIR_COEF_V(0, 2)); 2729 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 3));
2438 DUMPREG(DISPC_VID_FIR_COEF_V(0, 3)); 2730 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 4));
2439 DUMPREG(DISPC_VID_FIR_COEF_V(0, 4)); 2731 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 5));
2440 DUMPREG(DISPC_VID_FIR_COEF_V(0, 5)); 2732 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 6));
2441 DUMPREG(DISPC_VID_FIR_COEF_V(0, 6)); 2733 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 7));
2442 DUMPREG(DISPC_VID_FIR_COEF_V(0, 7)); 2734 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 0));
2443 2735 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 1));
2444 DUMPREG(DISPC_VID_FIR_COEF_H(1, 0)); 2736 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 2));
2445 DUMPREG(DISPC_VID_FIR_COEF_H(1, 1)); 2737 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 3));
2446 DUMPREG(DISPC_VID_FIR_COEF_H(1, 2)); 2738 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 4));
2447 DUMPREG(DISPC_VID_FIR_COEF_H(1, 3)); 2739 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 5));
2448 DUMPREG(DISPC_VID_FIR_COEF_H(1, 4)); 2740 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 6));
2449 DUMPREG(DISPC_VID_FIR_COEF_H(1, 5)); 2741 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 7));
2450 DUMPREG(DISPC_VID_FIR_COEF_H(1, 6)); 2742 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0));
2451 DUMPREG(DISPC_VID_FIR_COEF_H(1, 7)); 2743 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1));
2452 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 0)); 2744 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2));
2453 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 1)); 2745 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3));
2454 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 2)); 2746 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4));
2455 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 3)); 2747 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0));
2456 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 4)); 2748 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1));
2457 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 5)); 2749 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2));
2458 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 6)); 2750 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3));
2459 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 7)); 2751 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4));
2460 DUMPREG(DISPC_VID_CONV_COEF(1, 0)); 2752 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5));
2461 DUMPREG(DISPC_VID_CONV_COEF(1, 1)); 2753 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6));
2462 DUMPREG(DISPC_VID_CONV_COEF(1, 2)); 2754 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7));
2463 DUMPREG(DISPC_VID_CONV_COEF(1, 3)); 2755
2464 DUMPREG(DISPC_VID_CONV_COEF(1, 4)); 2756 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
2465 DUMPREG(DISPC_VID_FIR_COEF_V(1, 0)); 2757 DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO1));
2466 DUMPREG(DISPC_VID_FIR_COEF_V(1, 1)); 2758 DUMPREG(DISPC_OVL_BA1_UV(OMAP_DSS_VIDEO1));
2467 DUMPREG(DISPC_VID_FIR_COEF_V(1, 2)); 2759 DUMPREG(DISPC_OVL_FIR2(OMAP_DSS_VIDEO1));
2468 DUMPREG(DISPC_VID_FIR_COEF_V(1, 3)); 2760 DUMPREG(DISPC_OVL_ACCU2_0(OMAP_DSS_VIDEO1));
2469 DUMPREG(DISPC_VID_FIR_COEF_V(1, 4)); 2761 DUMPREG(DISPC_OVL_ACCU2_1(OMAP_DSS_VIDEO1));
2470 DUMPREG(DISPC_VID_FIR_COEF_V(1, 5)); 2762
2471 DUMPREG(DISPC_VID_FIR_COEF_V(1, 6)); 2763 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 0));
2472 DUMPREG(DISPC_VID_FIR_COEF_V(1, 7)); 2764 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 1));
2473 2765 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 2));
2474 DUMPREG(DISPC_VID_PRELOAD(0)); 2766 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 3));
2475 DUMPREG(DISPC_VID_PRELOAD(1)); 2767 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 4));
2476 2768 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 5));
2477 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); 2769 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 6));
2770 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 7));
2771
2772 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 0));
2773 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 1));
2774 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 2));
2775 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 3));
2776 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 4));
2777 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 5));
2778 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 6));
2779 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 7));
2780
2781 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 0));
2782 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 1));
2783 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 2));
2784 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 3));
2785 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 4));
2786 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 5));
2787 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 6));
2788 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 7));
2789 }
2790 if (dss_has_feature(FEAT_ATTR2))
2791 DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
2792
2793
2794 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 0));
2795 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 1));
2796 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 2));
2797 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 3));
2798 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 4));
2799 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 5));
2800 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 6));
2801 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 7));
2802 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 0));
2803 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 1));
2804 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 2));
2805 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 3));
2806 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 4));
2807 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 5));
2808 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 6));
2809 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 7));
2810 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0));
2811 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1));
2812 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2));
2813 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3));
2814 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4));
2815 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0));
2816 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1));
2817 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2));
2818 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3));
2819 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4));
2820 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5));
2821 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6));
2822 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7));
2823
2824 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
2825 DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO2));
2826 DUMPREG(DISPC_OVL_BA1_UV(OMAP_DSS_VIDEO2));
2827 DUMPREG(DISPC_OVL_FIR2(OMAP_DSS_VIDEO2));
2828 DUMPREG(DISPC_OVL_ACCU2_0(OMAP_DSS_VIDEO2));
2829 DUMPREG(DISPC_OVL_ACCU2_1(OMAP_DSS_VIDEO2));
2830
2831 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 0));
2832 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 1));
2833 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 2));
2834 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 3));
2835 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 4));
2836 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 5));
2837 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 6));
2838 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 7));
2839
2840 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 0));
2841 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 1));
2842 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 2));
2843 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 3));
2844 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 4));
2845 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 5));
2846 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 6));
2847 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 7));
2848
2849 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 0));
2850 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 1));
2851 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 2));
2852 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 3));
2853 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 4));
2854 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 5));
2855 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 6));
2856 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 7));
2857 }
2858 if (dss_has_feature(FEAT_ATTR2))
2859 DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
2860
2861 DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1));
2862 DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2));
2863
2864 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
2478#undef DUMPREG 2865#undef DUMPREG
2479} 2866}
2480 2867
2481static void _dispc_set_pol_freq(bool onoff, bool rf, bool ieo, bool ipc, 2868static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf,
2482 bool ihs, bool ivs, u8 acbi, u8 acb) 2869 bool ieo, bool ipc, bool ihs, bool ivs, u8 acbi, u8 acb)
2483{ 2870{
2484 u32 l = 0; 2871 u32 l = 0;
2485 2872
@@ -2496,13 +2883,14 @@ static void _dispc_set_pol_freq(bool onoff, bool rf, bool ieo, bool ipc,
2496 l |= FLD_VAL(acb, 7, 0); 2883 l |= FLD_VAL(acb, 7, 0);
2497 2884
2498 enable_clocks(1); 2885 enable_clocks(1);
2499 dispc_write_reg(DISPC_POL_FREQ, l); 2886 dispc_write_reg(DISPC_POL_FREQ(channel), l);
2500 enable_clocks(0); 2887 enable_clocks(0);
2501} 2888}
2502 2889
2503void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb) 2890void dispc_set_pol_freq(enum omap_channel channel,
2891 enum omap_panel_config config, u8 acbi, u8 acb)
2504{ 2892{
2505 _dispc_set_pol_freq((config & OMAP_DSS_LCD_ONOFF) != 0, 2893 _dispc_set_pol_freq(channel, (config & OMAP_DSS_LCD_ONOFF) != 0,
2506 (config & OMAP_DSS_LCD_RF) != 0, 2894 (config & OMAP_DSS_LCD_RF) != 0,
2507 (config & OMAP_DSS_LCD_IEO) != 0, 2895 (config & OMAP_DSS_LCD_IEO) != 0,
2508 (config & OMAP_DSS_LCD_IPC) != 0, 2896 (config & OMAP_DSS_LCD_IPC) != 0,
@@ -2571,24 +2959,26 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
2571 return 0; 2959 return 0;
2572} 2960}
2573 2961
2574int dispc_set_clock_div(struct dispc_clock_info *cinfo) 2962int dispc_set_clock_div(enum omap_channel channel,
2963 struct dispc_clock_info *cinfo)
2575{ 2964{
2576 DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div); 2965 DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div);
2577 DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div); 2966 DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div);
2578 2967
2579 dispc_set_lcd_divisor(cinfo->lck_div, cinfo->pck_div); 2968 dispc_set_lcd_divisor(channel, cinfo->lck_div, cinfo->pck_div);
2580 2969
2581 return 0; 2970 return 0;
2582} 2971}
2583 2972
2584int dispc_get_clock_div(struct dispc_clock_info *cinfo) 2973int dispc_get_clock_div(enum omap_channel channel,
2974 struct dispc_clock_info *cinfo)
2585{ 2975{
2586 unsigned long fck; 2976 unsigned long fck;
2587 2977
2588 fck = dispc_fclk_rate(); 2978 fck = dispc_fclk_rate();
2589 2979
2590 cinfo->lck_div = REG_GET(DISPC_DIVISOR, 23, 16); 2980 cinfo->lck_div = REG_GET(DISPC_DIVISORo(channel), 23, 16);
2591 cinfo->pck_div = REG_GET(DISPC_DIVISOR, 7, 0); 2981 cinfo->pck_div = REG_GET(DISPC_DIVISORo(channel), 7, 0);
2592 2982
2593 cinfo->lck = fck / cinfo->lck_div; 2983 cinfo->lck = fck / cinfo->lck_div;
2594 cinfo->pck = cinfo->lck / cinfo->pck_div; 2984 cinfo->pck = cinfo->lck / cinfo->pck_div;
@@ -2665,6 +3055,9 @@ int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
2665 break; 3055 break;
2666 } 3056 }
2667 3057
3058 if (ret)
3059 goto err;
3060
2668 _omap_dispc_set_irqs(); 3061 _omap_dispc_set_irqs();
2669 3062
2670 spin_unlock_irqrestore(&dispc.irq_lock, flags); 3063 spin_unlock_irqrestore(&dispc.irq_lock, flags);
@@ -2728,6 +3121,8 @@ static void print_irq_status(u32 status)
2728 PIS(VID2_FIFO_UNDERFLOW); 3121 PIS(VID2_FIFO_UNDERFLOW);
2729 PIS(SYNC_LOST); 3122 PIS(SYNC_LOST);
2730 PIS(SYNC_LOST_DIGIT); 3123 PIS(SYNC_LOST_DIGIT);
3124 if (dss_has_feature(FEAT_MGR_LCD2))
3125 PIS(SYNC_LOST2);
2731#undef PIS 3126#undef PIS
2732 3127
2733 printk("\n"); 3128 printk("\n");
@@ -2738,10 +3133,10 @@ static void print_irq_status(u32 status)
2738 * but we presume they are on because we got an IRQ. However, 3133 * but we presume they are on because we got an IRQ. However,
2739 * an irq handler may turn the clocks off, so we may not have 3134 * an irq handler may turn the clocks off, so we may not have
2740 * clock later in the function. */ 3135 * clock later in the function. */
2741void dispc_irq_handler(void) 3136static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
2742{ 3137{
2743 int i; 3138 int i;
2744 u32 irqstatus; 3139 u32 irqstatus, irqenable;
2745 u32 handledirqs = 0; 3140 u32 handledirqs = 0;
2746 u32 unhandled_errors; 3141 u32 unhandled_errors;
2747 struct omap_dispc_isr_data *isr_data; 3142 struct omap_dispc_isr_data *isr_data;
@@ -2750,6 +3145,13 @@ void dispc_irq_handler(void)
2750 spin_lock(&dispc.irq_lock); 3145 spin_lock(&dispc.irq_lock);
2751 3146
2752 irqstatus = dispc_read_reg(DISPC_IRQSTATUS); 3147 irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
3148 irqenable = dispc_read_reg(DISPC_IRQENABLE);
3149
3150 /* IRQ is not for us */
3151 if (!(irqstatus & irqenable)) {
3152 spin_unlock(&dispc.irq_lock);
3153 return IRQ_NONE;
3154 }
2753 3155
2754#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 3156#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
2755 spin_lock(&dispc.irq_stats_lock); 3157 spin_lock(&dispc.irq_stats_lock);
@@ -2801,6 +3203,8 @@ void dispc_irq_handler(void)
2801 } 3203 }
2802 3204
2803 spin_unlock(&dispc.irq_lock); 3205 spin_unlock(&dispc.irq_lock);
3206
3207 return IRQ_HANDLED;
2804} 3208}
2805 3209
2806static void dispc_error_worker(struct work_struct *work) 3210static void dispc_error_worker(struct work_struct *work)
@@ -2946,6 +3350,45 @@ static void dispc_error_worker(struct work_struct *work)
2946 } 3350 }
2947 } 3351 }
2948 3352
3353 if (errors & DISPC_IRQ_SYNC_LOST2) {
3354 struct omap_overlay_manager *manager = NULL;
3355 bool enable = false;
3356
3357 DSSERR("SYNC_LOST for LCD2, disabling LCD2\n");
3358
3359 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
3360 struct omap_overlay_manager *mgr;
3361 mgr = omap_dss_get_overlay_manager(i);
3362
3363 if (mgr->id == OMAP_DSS_CHANNEL_LCD2) {
3364 manager = mgr;
3365 enable = mgr->device->state ==
3366 OMAP_DSS_DISPLAY_ACTIVE;
3367 mgr->device->driver->disable(mgr->device);
3368 break;
3369 }
3370 }
3371
3372 if (manager) {
3373 struct omap_dss_device *dssdev = manager->device;
3374 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
3375 struct omap_overlay *ovl;
3376 ovl = omap_dss_get_overlay(i);
3377
3378 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
3379 continue;
3380
3381 if (ovl->id != 0 && ovl->manager == manager)
3382 dispc_enable_plane(ovl->id, 0);
3383 }
3384
3385 dispc_go(manager->id);
3386 mdelay(50);
3387 if (enable)
3388 dssdev->driver->enable(dssdev);
3389 }
3390 }
3391
2949 if (errors & DISPC_IRQ_OCP_ERR) { 3392 if (errors & DISPC_IRQ_OCP_ERR) {
2950 DSSERR("OCP_ERR\n"); 3393 DSSERR("OCP_ERR\n");
2951 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { 3394 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
@@ -3053,6 +3496,8 @@ static void _omap_dispc_initialize_irq(void)
3053 memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr)); 3496 memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr));
3054 3497
3055 dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; 3498 dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
3499 if (dss_has_feature(FEAT_MGR_LCD2))
3500 dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
3056 3501
3057 /* there's SYNC_LOST_DIGIT waiting after enabling the DSS, 3502 /* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
3058 * so clear it */ 3503 * so clear it */
@@ -3084,8 +3529,18 @@ static void _omap_dispc_initial_config(void)
3084 l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */ 3529 l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */
3085 dispc_write_reg(DISPC_SYSCONFIG, l); 3530 dispc_write_reg(DISPC_SYSCONFIG, l);
3086 3531
3532 /* Exclusively enable DISPC_CORE_CLK and set divider to 1 */
3533 if (dss_has_feature(FEAT_CORE_CLK_DIV)) {
3534 l = dispc_read_reg(DISPC_DIVISOR);
3535 /* Use DISPC_DIVISOR.LCD, instead of DISPC_DIVISOR1.LCD */
3536 l = FLD_MOD(l, 1, 0, 0);
3537 l = FLD_MOD(l, 1, 23, 16);
3538 dispc_write_reg(DISPC_DIVISOR, l);
3539 }
3540
3087 /* FUNCGATED */ 3541 /* FUNCGATED */
3088 REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); 3542 if (dss_has_feature(FEAT_FUNCGATED))
3543 REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
3089 3544
3090 /* L3 firewall setting: enable access to OCM RAM */ 3545 /* L3 firewall setting: enable access to OCM RAM */
3091 /* XXX this should be somewhere in plat-omap */ 3546 /* XXX this should be somewhere in plat-omap */
@@ -3099,47 +3554,6 @@ static void _omap_dispc_initial_config(void)
3099 dispc_read_plane_fifo_sizes(); 3554 dispc_read_plane_fifo_sizes();
3100} 3555}
3101 3556
3102int dispc_init(void)
3103{
3104 u32 rev;
3105
3106 spin_lock_init(&dispc.irq_lock);
3107
3108#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
3109 spin_lock_init(&dispc.irq_stats_lock);
3110 dispc.irq_stats.last_reset = jiffies;
3111#endif
3112
3113 INIT_WORK(&dispc.error_work, dispc_error_worker);
3114
3115 dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS);
3116 if (!dispc.base) {
3117 DSSERR("can't ioremap DISPC\n");
3118 return -ENOMEM;
3119 }
3120
3121 enable_clocks(1);
3122
3123 _omap_dispc_initial_config();
3124
3125 _omap_dispc_initialize_irq();
3126
3127 dispc_save_context();
3128
3129 rev = dispc_read_reg(DISPC_REVISION);
3130 printk(KERN_INFO "OMAP DISPC rev %d.%d\n",
3131 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
3132
3133 enable_clocks(0);
3134
3135 return 0;
3136}
3137
3138void dispc_exit(void)
3139{
3140 iounmap(dispc.base);
3141}
3142
3143int dispc_enable_plane(enum omap_plane plane, bool enable) 3557int dispc_enable_plane(enum omap_plane plane, bool enable)
3144{ 3558{
3145 DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); 3559 DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
@@ -3159,17 +3573,19 @@ int dispc_setup_plane(enum omap_plane plane,
3159 enum omap_color_mode color_mode, 3573 enum omap_color_mode color_mode,
3160 bool ilace, 3574 bool ilace,
3161 enum omap_dss_rotation_type rotation_type, 3575 enum omap_dss_rotation_type rotation_type,
3162 u8 rotation, bool mirror, u8 global_alpha) 3576 u8 rotation, bool mirror, u8 global_alpha,
3577 u8 pre_mult_alpha, enum omap_channel channel,
3578 u32 puv_addr)
3163{ 3579{
3164 int r = 0; 3580 int r = 0;
3165 3581
3166 DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> " 3582 DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d, %d, %dx%d -> "
3167 "%dx%d, ilace %d, cmode %x, rot %d, mir %d\n", 3583 "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n",
3168 plane, paddr, screen_width, pos_x, pos_y, 3584 plane, paddr, screen_width, pos_x, pos_y,
3169 width, height, 3585 width, height,
3170 out_width, out_height, 3586 out_width, out_height,
3171 ilace, color_mode, 3587 ilace, color_mode,
3172 rotation, mirror); 3588 rotation, mirror, channel);
3173 3589
3174 enable_clocks(1); 3590 enable_clocks(1);
3175 3591
@@ -3181,9 +3597,102 @@ int dispc_setup_plane(enum omap_plane plane,
3181 color_mode, ilace, 3597 color_mode, ilace,
3182 rotation_type, 3598 rotation_type,
3183 rotation, mirror, 3599 rotation, mirror,
3184 global_alpha); 3600 global_alpha,
3601 pre_mult_alpha,
3602 channel, puv_addr);
3185 3603
3186 enable_clocks(0); 3604 enable_clocks(0);
3187 3605
3188 return r; 3606 return r;
3189} 3607}
3608
3609/* DISPC HW IP initialisation */
3610static int omap_dispchw_probe(struct platform_device *pdev)
3611{
3612 u32 rev;
3613 int r = 0;
3614 struct resource *dispc_mem;
3615
3616 dispc.pdev = pdev;
3617
3618 spin_lock_init(&dispc.irq_lock);
3619
3620#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
3621 spin_lock_init(&dispc.irq_stats_lock);
3622 dispc.irq_stats.last_reset = jiffies;
3623#endif
3624
3625 INIT_WORK(&dispc.error_work, dispc_error_worker);
3626
3627 dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0);
3628 if (!dispc_mem) {
3629 DSSERR("can't get IORESOURCE_MEM DISPC\n");
3630 r = -EINVAL;
3631 goto fail0;
3632 }
3633 dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem));
3634 if (!dispc.base) {
3635 DSSERR("can't ioremap DISPC\n");
3636 r = -ENOMEM;
3637 goto fail0;
3638 }
3639 dispc.irq = platform_get_irq(dispc.pdev, 0);
3640 if (dispc.irq < 0) {
3641 DSSERR("platform_get_irq failed\n");
3642 r = -ENODEV;
3643 goto fail1;
3644 }
3645
3646 r = request_irq(dispc.irq, omap_dispc_irq_handler, IRQF_SHARED,
3647 "OMAP DISPC", dispc.pdev);
3648 if (r < 0) {
3649 DSSERR("request_irq failed\n");
3650 goto fail1;
3651 }
3652
3653 enable_clocks(1);
3654
3655 _omap_dispc_initial_config();
3656
3657 _omap_dispc_initialize_irq();
3658
3659 dispc_save_context();
3660
3661 rev = dispc_read_reg(DISPC_REVISION);
3662 dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n",
3663 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
3664
3665 enable_clocks(0);
3666
3667 return 0;
3668fail1:
3669 iounmap(dispc.base);
3670fail0:
3671 return r;
3672}
3673
3674static int omap_dispchw_remove(struct platform_device *pdev)
3675{
3676 free_irq(dispc.irq, dispc.pdev);
3677 iounmap(dispc.base);
3678 return 0;
3679}
3680
3681static struct platform_driver omap_dispchw_driver = {
3682 .probe = omap_dispchw_probe,
3683 .remove = omap_dispchw_remove,
3684 .driver = {
3685 .name = "omapdss_dispc",
3686 .owner = THIS_MODULE,
3687 },
3688};
3689
3690int dispc_init_platform_driver(void)
3691{
3692 return platform_driver_register(&omap_dispchw_driver);
3693}
3694
3695void dispc_uninit_platform_driver(void)
3696{
3697 return platform_driver_unregister(&omap_dispchw_driver);
3698}
diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h
new file mode 100644
index 000000000000..6c9ee0a0efb3
--- /dev/null
+++ b/drivers/video/omap2/dss/dispc.h
@@ -0,0 +1,691 @@
1/*
2 * linux/drivers/video/omap2/dss/dispc.h
3 *
4 * Copyright (C) 2011 Texas Instruments
5 * Author: Archit Taneja <archit@ti.com>
6 *
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#ifndef __OMAP2_DISPC_REG_H
22#define __OMAP2_DISPC_REG_H
23
24/* DISPC common registers */
25#define DISPC_REVISION 0x0000
26#define DISPC_SYSCONFIG 0x0010
27#define DISPC_SYSSTATUS 0x0014
28#define DISPC_IRQSTATUS 0x0018
29#define DISPC_IRQENABLE 0x001C
30#define DISPC_CONTROL 0x0040
31#define DISPC_CONFIG 0x0044
32#define DISPC_CAPABLE 0x0048
33#define DISPC_LINE_STATUS 0x005C
34#define DISPC_LINE_NUMBER 0x0060
35#define DISPC_GLOBAL_ALPHA 0x0074
36#define DISPC_CONTROL2 0x0238
37#define DISPC_CONFIG2 0x0620
38#define DISPC_DIVISOR 0x0804
39
40/* DISPC overlay registers */
41#define DISPC_OVL_BA0(n) (DISPC_OVL_BASE(n) + \
42 DISPC_BA0_OFFSET(n))
43#define DISPC_OVL_BA1(n) (DISPC_OVL_BASE(n) + \
44 DISPC_BA1_OFFSET(n))
45#define DISPC_OVL_BA0_UV(n) (DISPC_OVL_BASE(n) + \
46 DISPC_BA0_UV_OFFSET(n))
47#define DISPC_OVL_BA1_UV(n) (DISPC_OVL_BASE(n) + \
48 DISPC_BA1_UV_OFFSET(n))
49#define DISPC_OVL_POSITION(n) (DISPC_OVL_BASE(n) + \
50 DISPC_POS_OFFSET(n))
51#define DISPC_OVL_SIZE(n) (DISPC_OVL_BASE(n) + \
52 DISPC_SIZE_OFFSET(n))
53#define DISPC_OVL_ATTRIBUTES(n) (DISPC_OVL_BASE(n) + \
54 DISPC_ATTR_OFFSET(n))
55#define DISPC_OVL_ATTRIBUTES2(n) (DISPC_OVL_BASE(n) + \
56 DISPC_ATTR2_OFFSET(n))
57#define DISPC_OVL_FIFO_THRESHOLD(n) (DISPC_OVL_BASE(n) + \
58 DISPC_FIFO_THRESH_OFFSET(n))
59#define DISPC_OVL_FIFO_SIZE_STATUS(n) (DISPC_OVL_BASE(n) + \
60 DISPC_FIFO_SIZE_STATUS_OFFSET(n))
61#define DISPC_OVL_ROW_INC(n) (DISPC_OVL_BASE(n) + \
62 DISPC_ROW_INC_OFFSET(n))
63#define DISPC_OVL_PIXEL_INC(n) (DISPC_OVL_BASE(n) + \
64 DISPC_PIX_INC_OFFSET(n))
65#define DISPC_OVL_WINDOW_SKIP(n) (DISPC_OVL_BASE(n) + \
66 DISPC_WINDOW_SKIP_OFFSET(n))
67#define DISPC_OVL_TABLE_BA(n) (DISPC_OVL_BASE(n) + \
68 DISPC_TABLE_BA_OFFSET(n))
69#define DISPC_OVL_FIR(n) (DISPC_OVL_BASE(n) + \
70 DISPC_FIR_OFFSET(n))
71#define DISPC_OVL_FIR2(n) (DISPC_OVL_BASE(n) + \
72 DISPC_FIR2_OFFSET(n))
73#define DISPC_OVL_PICTURE_SIZE(n) (DISPC_OVL_BASE(n) + \
74 DISPC_PIC_SIZE_OFFSET(n))
75#define DISPC_OVL_ACCU0(n) (DISPC_OVL_BASE(n) + \
76 DISPC_ACCU0_OFFSET(n))
77#define DISPC_OVL_ACCU1(n) (DISPC_OVL_BASE(n) + \
78 DISPC_ACCU1_OFFSET(n))
79#define DISPC_OVL_ACCU2_0(n) (DISPC_OVL_BASE(n) + \
80 DISPC_ACCU2_0_OFFSET(n))
81#define DISPC_OVL_ACCU2_1(n) (DISPC_OVL_BASE(n) + \
82 DISPC_ACCU2_1_OFFSET(n))
83#define DISPC_OVL_FIR_COEF_H(n, i) (DISPC_OVL_BASE(n) + \
84 DISPC_FIR_COEF_H_OFFSET(n, i))
85#define DISPC_OVL_FIR_COEF_HV(n, i) (DISPC_OVL_BASE(n) + \
86 DISPC_FIR_COEF_HV_OFFSET(n, i))
87#define DISPC_OVL_FIR_COEF_H2(n, i) (DISPC_OVL_BASE(n) + \
88 DISPC_FIR_COEF_H2_OFFSET(n, i))
89#define DISPC_OVL_FIR_COEF_HV2(n, i) (DISPC_OVL_BASE(n) + \
90 DISPC_FIR_COEF_HV2_OFFSET(n, i))
91#define DISPC_OVL_CONV_COEF(n, i) (DISPC_OVL_BASE(n) + \
92 DISPC_CONV_COEF_OFFSET(n, i))
93#define DISPC_OVL_FIR_COEF_V(n, i) (DISPC_OVL_BASE(n) + \
94 DISPC_FIR_COEF_V_OFFSET(n, i))
95#define DISPC_OVL_FIR_COEF_V2(n, i) (DISPC_OVL_BASE(n) + \
96 DISPC_FIR_COEF_V2_OFFSET(n, i))
97#define DISPC_OVL_PRELOAD(n) (DISPC_OVL_BASE(n) + \
98 DISPC_PRELOAD_OFFSET(n))
99
100/* DISPC manager/channel specific registers */
101static inline u16 DISPC_DEFAULT_COLOR(enum omap_channel channel)
102{
103 switch (channel) {
104 case OMAP_DSS_CHANNEL_LCD:
105 return 0x004C;
106 case OMAP_DSS_CHANNEL_DIGIT:
107 return 0x0050;
108 case OMAP_DSS_CHANNEL_LCD2:
109 return 0x03AC;
110 default:
111 BUG();
112 }
113}
114
115static inline u16 DISPC_TRANS_COLOR(enum omap_channel channel)
116{
117 switch (channel) {
118 case OMAP_DSS_CHANNEL_LCD:
119 return 0x0054;
120 case OMAP_DSS_CHANNEL_DIGIT:
121 return 0x0058;
122 case OMAP_DSS_CHANNEL_LCD2:
123 return 0x03B0;
124 default:
125 BUG();
126 }
127}
128
129static inline u16 DISPC_TIMING_H(enum omap_channel channel)
130{
131 switch (channel) {
132 case OMAP_DSS_CHANNEL_LCD:
133 return 0x0064;
134 case OMAP_DSS_CHANNEL_DIGIT:
135 BUG();
136 case OMAP_DSS_CHANNEL_LCD2:
137 return 0x0400;
138 default:
139 BUG();
140 }
141}
142
143static inline u16 DISPC_TIMING_V(enum omap_channel channel)
144{
145 switch (channel) {
146 case OMAP_DSS_CHANNEL_LCD:
147 return 0x0068;
148 case OMAP_DSS_CHANNEL_DIGIT:
149 BUG();
150 case OMAP_DSS_CHANNEL_LCD2:
151 return 0x0404;
152 default:
153 BUG();
154 }
155}
156
157static inline u16 DISPC_POL_FREQ(enum omap_channel channel)
158{
159 switch (channel) {
160 case OMAP_DSS_CHANNEL_LCD:
161 return 0x006C;
162 case OMAP_DSS_CHANNEL_DIGIT:
163 BUG();
164 case OMAP_DSS_CHANNEL_LCD2:
165 return 0x0408;
166 default:
167 BUG();
168 }
169}
170
171static inline u16 DISPC_DIVISORo(enum omap_channel channel)
172{
173 switch (channel) {
174 case OMAP_DSS_CHANNEL_LCD:
175 return 0x0070;
176 case OMAP_DSS_CHANNEL_DIGIT:
177 BUG();
178 case OMAP_DSS_CHANNEL_LCD2:
179 return 0x040C;
180 default:
181 BUG();
182 }
183}
184
185/* Named as DISPC_SIZE_LCD, DISPC_SIZE_DIGIT and DISPC_SIZE_LCD2 in TRM */
186static inline u16 DISPC_SIZE_MGR(enum omap_channel channel)
187{
188 switch (channel) {
189 case OMAP_DSS_CHANNEL_LCD:
190 return 0x007C;
191 case OMAP_DSS_CHANNEL_DIGIT:
192 return 0x0078;
193 case OMAP_DSS_CHANNEL_LCD2:
194 return 0x03CC;
195 default:
196 BUG();
197 }
198}
199
200static inline u16 DISPC_DATA_CYCLE1(enum omap_channel channel)
201{
202 switch (channel) {
203 case OMAP_DSS_CHANNEL_LCD:
204 return 0x01D4;
205 case OMAP_DSS_CHANNEL_DIGIT:
206 BUG();
207 case OMAP_DSS_CHANNEL_LCD2:
208 return 0x03C0;
209 default:
210 BUG();
211 }
212}
213
214static inline u16 DISPC_DATA_CYCLE2(enum omap_channel channel)
215{
216 switch (channel) {
217 case OMAP_DSS_CHANNEL_LCD:
218 return 0x01D8;
219 case OMAP_DSS_CHANNEL_DIGIT:
220 BUG();
221 case OMAP_DSS_CHANNEL_LCD2:
222 return 0x03C4;
223 default:
224 BUG();
225 }
226}
227
228static inline u16 DISPC_DATA_CYCLE3(enum omap_channel channel)
229{
230 switch (channel) {
231 case OMAP_DSS_CHANNEL_LCD:
232 return 0x01DC;
233 case OMAP_DSS_CHANNEL_DIGIT:
234 BUG();
235 case OMAP_DSS_CHANNEL_LCD2:
236 return 0x03C8;
237 default:
238 BUG();
239 }
240}
241
242static inline u16 DISPC_CPR_COEF_R(enum omap_channel channel)
243{
244 switch (channel) {
245 case OMAP_DSS_CHANNEL_LCD:
246 return 0x0220;
247 case OMAP_DSS_CHANNEL_DIGIT:
248 BUG();
249 case OMAP_DSS_CHANNEL_LCD2:
250 return 0x03BC;
251 default:
252 BUG();
253 }
254}
255
256static inline u16 DISPC_CPR_COEF_G(enum omap_channel channel)
257{
258 switch (channel) {
259 case OMAP_DSS_CHANNEL_LCD:
260 return 0x0224;
261 case OMAP_DSS_CHANNEL_DIGIT:
262 BUG();
263 case OMAP_DSS_CHANNEL_LCD2:
264 return 0x03B8;
265 default:
266 BUG();
267 }
268}
269
270static inline u16 DISPC_CPR_COEF_B(enum omap_channel channel)
271{
272 switch (channel) {
273 case OMAP_DSS_CHANNEL_LCD:
274 return 0x0228;
275 case OMAP_DSS_CHANNEL_DIGIT:
276 BUG();
277 case OMAP_DSS_CHANNEL_LCD2:
278 return 0x03B4;
279 default:
280 BUG();
281 }
282}
283
284/* DISPC overlay register base addresses */
285static inline u16 DISPC_OVL_BASE(enum omap_plane plane)
286{
287 switch (plane) {
288 case OMAP_DSS_GFX:
289 return 0x0080;
290 case OMAP_DSS_VIDEO1:
291 return 0x00BC;
292 case OMAP_DSS_VIDEO2:
293 return 0x014C;
294 default:
295 BUG();
296 }
297}
298
299/* DISPC overlay register offsets */
300static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane)
301{
302 switch (plane) {
303 case OMAP_DSS_GFX:
304 case OMAP_DSS_VIDEO1:
305 case OMAP_DSS_VIDEO2:
306 return 0x0000;
307 default:
308 BUG();
309 }
310}
311
312static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane)
313{
314 switch (plane) {
315 case OMAP_DSS_GFX:
316 case OMAP_DSS_VIDEO1:
317 case OMAP_DSS_VIDEO2:
318 return 0x0004;
319 default:
320 BUG();
321 }
322}
323
324static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane)
325{
326 switch (plane) {
327 case OMAP_DSS_GFX:
328 BUG();
329 case OMAP_DSS_VIDEO1:
330 return 0x0544;
331 case OMAP_DSS_VIDEO2:
332 return 0x04BC;
333 default:
334 BUG();
335 }
336}
337
338static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane)
339{
340 switch (plane) {
341 case OMAP_DSS_GFX:
342 BUG();
343 case OMAP_DSS_VIDEO1:
344 return 0x0548;
345 case OMAP_DSS_VIDEO2:
346 return 0x04C0;
347 default:
348 BUG();
349 }
350}
351
352static inline u16 DISPC_POS_OFFSET(enum omap_plane plane)
353{
354 switch (plane) {
355 case OMAP_DSS_GFX:
356 case OMAP_DSS_VIDEO1:
357 case OMAP_DSS_VIDEO2:
358 return 0x0008;
359 default:
360 BUG();
361 }
362}
363
364static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane)
365{
366 switch (plane) {
367 case OMAP_DSS_GFX:
368 case OMAP_DSS_VIDEO1:
369 case OMAP_DSS_VIDEO2:
370 return 0x000C;
371 default:
372 BUG();
373 }
374}
375
376static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane)
377{
378 switch (plane) {
379 case OMAP_DSS_GFX:
380 return 0x0020;
381 case OMAP_DSS_VIDEO1:
382 case OMAP_DSS_VIDEO2:
383 return 0x0010;
384 default:
385 BUG();
386 }
387}
388
389static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane)
390{
391 switch (plane) {
392 case OMAP_DSS_GFX:
393 BUG();
394 case OMAP_DSS_VIDEO1:
395 return 0x0568;
396 case OMAP_DSS_VIDEO2:
397 return 0x04DC;
398 default:
399 BUG();
400 }
401}
402
403static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane)
404{
405 switch (plane) {
406 case OMAP_DSS_GFX:
407 return 0x0024;
408 case OMAP_DSS_VIDEO1:
409 case OMAP_DSS_VIDEO2:
410 return 0x0014;
411 default:
412 BUG();
413 }
414}
415
416static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane)
417{
418 switch (plane) {
419 case OMAP_DSS_GFX:
420 return 0x0028;
421 case OMAP_DSS_VIDEO1:
422 case OMAP_DSS_VIDEO2:
423 return 0x0018;
424 default:
425 BUG();
426 }
427}
428
429static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane)
430{
431 switch (plane) {
432 case OMAP_DSS_GFX:
433 return 0x002C;
434 case OMAP_DSS_VIDEO1:
435 case OMAP_DSS_VIDEO2:
436 return 0x001C;
437 default:
438 BUG();
439 }
440}
441
442static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane)
443{
444 switch (plane) {
445 case OMAP_DSS_GFX:
446 return 0x0030;
447 case OMAP_DSS_VIDEO1:
448 case OMAP_DSS_VIDEO2:
449 return 0x0020;
450 default:
451 BUG();
452 }
453}
454
455static inline u16 DISPC_WINDOW_SKIP_OFFSET(enum omap_plane plane)
456{
457 switch (plane) {
458 case OMAP_DSS_GFX:
459 return 0x0034;
460 case OMAP_DSS_VIDEO1:
461 case OMAP_DSS_VIDEO2:
462 BUG();
463 default:
464 BUG();
465 }
466}
467
468static inline u16 DISPC_TABLE_BA_OFFSET(enum omap_plane plane)
469{
470 switch (plane) {
471 case OMAP_DSS_GFX:
472 return 0x0038;
473 case OMAP_DSS_VIDEO1:
474 case OMAP_DSS_VIDEO2:
475 BUG();
476 default:
477 BUG();
478 }
479}
480
481static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane)
482{
483 switch (plane) {
484 case OMAP_DSS_GFX:
485 BUG();
486 case OMAP_DSS_VIDEO1:
487 case OMAP_DSS_VIDEO2:
488 return 0x0024;
489 default:
490 BUG();
491 }
492}
493
494static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane)
495{
496 switch (plane) {
497 case OMAP_DSS_GFX:
498 BUG();
499 case OMAP_DSS_VIDEO1:
500 return 0x0580;
501 case OMAP_DSS_VIDEO2:
502 return 0x055C;
503 default:
504 BUG();
505 }
506}
507
508static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane)
509{
510 switch (plane) {
511 case OMAP_DSS_GFX:
512 BUG();
513 case OMAP_DSS_VIDEO1:
514 case OMAP_DSS_VIDEO2:
515 return 0x0028;
516 default:
517 BUG();
518 }
519}
520
521
522static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane)
523{
524 switch (plane) {
525 case OMAP_DSS_GFX:
526 BUG();
527 case OMAP_DSS_VIDEO1:
528 case OMAP_DSS_VIDEO2:
529 return 0x002C;
530 default:
531 BUG();
532 }
533}
534
535static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane)
536{
537 switch (plane) {
538 case OMAP_DSS_GFX:
539 BUG();
540 case OMAP_DSS_VIDEO1:
541 return 0x0584;
542 case OMAP_DSS_VIDEO2:
543 return 0x0560;
544 default:
545 BUG();
546 }
547}
548
549static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane)
550{
551 switch (plane) {
552 case OMAP_DSS_GFX:
553 BUG();
554 case OMAP_DSS_VIDEO1:
555 case OMAP_DSS_VIDEO2:
556 return 0x0030;
557 default:
558 BUG();
559 }
560}
561
562static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane)
563{
564 switch (plane) {
565 case OMAP_DSS_GFX:
566 BUG();
567 case OMAP_DSS_VIDEO1:
568 return 0x0588;
569 case OMAP_DSS_VIDEO2:
570 return 0x0564;
571 default:
572 BUG();
573 }
574}
575
576/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
577static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i)
578{
579 switch (plane) {
580 case OMAP_DSS_GFX:
581 BUG();
582 case OMAP_DSS_VIDEO1:
583 case OMAP_DSS_VIDEO2:
584 return 0x0034 + i * 0x8;
585 default:
586 BUG();
587 }
588}
589
590/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
591static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i)
592{
593 switch (plane) {
594 case OMAP_DSS_GFX:
595 BUG();
596 case OMAP_DSS_VIDEO1:
597 return 0x058C + i * 0x8;
598 case OMAP_DSS_VIDEO2:
599 return 0x0568 + i * 0x8;
600 default:
601 BUG();
602 }
603}
604
605/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
606static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i)
607{
608 switch (plane) {
609 case OMAP_DSS_GFX:
610 BUG();
611 case OMAP_DSS_VIDEO1:
612 case OMAP_DSS_VIDEO2:
613 return 0x0038 + i * 0x8;
614 default:
615 BUG();
616 }
617}
618
619/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
620static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i)
621{
622 switch (plane) {
623 case OMAP_DSS_GFX:
624 BUG();
625 case OMAP_DSS_VIDEO1:
626 return 0x0590 + i * 8;
627 case OMAP_DSS_VIDEO2:
628 return 0x056C + i * 0x8;
629 default:
630 BUG();
631 }
632}
633
634/* coef index i = {0, 1, 2, 3, 4,} */
635static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i)
636{
637 switch (plane) {
638 case OMAP_DSS_GFX:
639 BUG();
640 case OMAP_DSS_VIDEO1:
641 case OMAP_DSS_VIDEO2:
642 return 0x0074 + i * 0x4;
643 default:
644 BUG();
645 }
646}
647
648/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
649static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i)
650{
651 switch (plane) {
652 case OMAP_DSS_GFX:
653 BUG();
654 case OMAP_DSS_VIDEO1:
655 return 0x0124 + i * 0x4;
656 case OMAP_DSS_VIDEO2:
657 return 0x00B4 + i * 0x4;
658 default:
659 BUG();
660 }
661}
662
663/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
664static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i)
665{
666 switch (plane) {
667 case OMAP_DSS_GFX:
668 BUG();
669 case OMAP_DSS_VIDEO1:
670 return 0x05CC + i * 0x4;
671 case OMAP_DSS_VIDEO2:
672 return 0x05A8 + i * 0x4;
673 default:
674 BUG();
675 }
676}
677
678static inline u16 DISPC_PRELOAD_OFFSET(enum omap_plane plane)
679{
680 switch (plane) {
681 case OMAP_DSS_GFX:
682 return 0x01AC;
683 case OMAP_DSS_VIDEO1:
684 return 0x0174;
685 case OMAP_DSS_VIDEO2:
686 return 0x00E8;
687 default:
688 BUG();
689 }
690}
691#endif
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index 22dd7a474f79..c2dfc8c50057 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -25,14 +25,11 @@
25#include <linux/kernel.h> 25#include <linux/kernel.h>
26#include <linux/module.h> 26#include <linux/module.h>
27#include <linux/jiffies.h> 27#include <linux/jiffies.h>
28#include <linux/list.h>
29#include <linux/platform_device.h> 28#include <linux/platform_device.h>
30 29
31#include <plat/display.h> 30#include <video/omapdss.h>
32#include "dss.h" 31#include "dss.h"
33 32
34static LIST_HEAD(display_list);
35
36static ssize_t display_enabled_show(struct device *dev, 33static ssize_t display_enabled_show(struct device *dev,
37 struct device_attribute *attr, char *buf) 34 struct device_attribute *attr, char *buf)
38{ 35{
@@ -47,9 +44,13 @@ static ssize_t display_enabled_store(struct device *dev,
47 const char *buf, size_t size) 44 const char *buf, size_t size)
48{ 45{
49 struct omap_dss_device *dssdev = to_dss_device(dev); 46 struct omap_dss_device *dssdev = to_dss_device(dev);
50 bool enabled, r; 47 int r, enabled;
48
49 r = kstrtoint(buf, 0, &enabled);
50 if (r)
51 return r;
51 52
52 enabled = simple_strtoul(buf, NULL, 10); 53 enabled = !!enabled;
53 54
54 if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) { 55 if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
55 if (enabled) { 56 if (enabled) {
@@ -85,7 +86,9 @@ static ssize_t display_upd_mode_store(struct device *dev,
85 if (!dssdev->driver->set_update_mode) 86 if (!dssdev->driver->set_update_mode)
86 return -EINVAL; 87 return -EINVAL;
87 88
88 val = simple_strtoul(buf, NULL, 10); 89 r = kstrtoint(buf, 0, &val);
90 if (r)
91 return r;
89 92
90 switch (val) { 93 switch (val) {
91 case OMAP_DSS_UPDATE_DISABLED: 94 case OMAP_DSS_UPDATE_DISABLED:
@@ -117,13 +120,16 @@ static ssize_t display_tear_store(struct device *dev,
117 struct device_attribute *attr, const char *buf, size_t size) 120 struct device_attribute *attr, const char *buf, size_t size)
118{ 121{
119 struct omap_dss_device *dssdev = to_dss_device(dev); 122 struct omap_dss_device *dssdev = to_dss_device(dev);
120 unsigned long te; 123 int te, r;
121 int r;
122 124
123 if (!dssdev->driver->enable_te || !dssdev->driver->get_te) 125 if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
124 return -ENOENT; 126 return -ENOENT;
125 127
126 te = simple_strtoul(buf, NULL, 0); 128 r = kstrtoint(buf, 0, &te);
129 if (r)
130 return r;
131
132 te = !!te;
127 133
128 r = dssdev->driver->enable_te(dssdev, te); 134 r = dssdev->driver->enable_te(dssdev, te);
129 if (r) 135 if (r)
@@ -199,13 +205,14 @@ static ssize_t display_rotate_store(struct device *dev,
199 struct device_attribute *attr, const char *buf, size_t size) 205 struct device_attribute *attr, const char *buf, size_t size)
200{ 206{
201 struct omap_dss_device *dssdev = to_dss_device(dev); 207 struct omap_dss_device *dssdev = to_dss_device(dev);
202 unsigned long rot; 208 int rot, r;
203 int r;
204 209
205 if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate) 210 if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
206 return -ENOENT; 211 return -ENOENT;
207 212
208 rot = simple_strtoul(buf, NULL, 0); 213 r = kstrtoint(buf, 0, &rot);
214 if (r)
215 return r;
209 216
210 r = dssdev->driver->set_rotate(dssdev, rot); 217 r = dssdev->driver->set_rotate(dssdev, rot);
211 if (r) 218 if (r)
@@ -229,13 +236,16 @@ static ssize_t display_mirror_store(struct device *dev,
229 struct device_attribute *attr, const char *buf, size_t size) 236 struct device_attribute *attr, const char *buf, size_t size)
230{ 237{
231 struct omap_dss_device *dssdev = to_dss_device(dev); 238 struct omap_dss_device *dssdev = to_dss_device(dev);
232 unsigned long mirror; 239 int mirror, r;
233 int r;
234 240
235 if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror) 241 if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
236 return -ENOENT; 242 return -ENOENT;
237 243
238 mirror = simple_strtoul(buf, NULL, 0); 244 r = kstrtoint(buf, 0, &mirror);
245 if (r)
246 return r;
247
248 mirror = !!mirror;
239 249
240 r = dssdev->driver->set_mirror(dssdev, mirror); 250 r = dssdev->driver->set_mirror(dssdev, mirror);
241 if (r) 251 if (r)
@@ -262,14 +272,15 @@ static ssize_t display_wss_store(struct device *dev,
262 struct device_attribute *attr, const char *buf, size_t size) 272 struct device_attribute *attr, const char *buf, size_t size)
263{ 273{
264 struct omap_dss_device *dssdev = to_dss_device(dev); 274 struct omap_dss_device *dssdev = to_dss_device(dev);
265 unsigned long wss; 275 u32 wss;
266 int r; 276 int r;
267 277
268 if (!dssdev->driver->get_wss || !dssdev->driver->set_wss) 278 if (!dssdev->driver->get_wss || !dssdev->driver->set_wss)
269 return -ENOENT; 279 return -ENOENT;
270 280
271 if (strict_strtoul(buf, 0, &wss)) 281 r = kstrtou32(buf, 0, &wss);
272 return -EINVAL; 282 if (r)
283 return r;
273 284
274 if (wss > 0xfffff) 285 if (wss > 0xfffff)
275 return -EINVAL; 286 return -EINVAL;
@@ -345,6 +356,7 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
345 return 16; 356 return 16;
346 case OMAP_DISPLAY_TYPE_VENC: 357 case OMAP_DISPLAY_TYPE_VENC:
347 case OMAP_DISPLAY_TYPE_SDI: 358 case OMAP_DISPLAY_TYPE_SDI:
359 case OMAP_DISPLAY_TYPE_HDMI:
348 return 24; 360 return 24;
349 default: 361 default:
350 BUG(); 362 BUG();
@@ -371,6 +383,7 @@ bool dss_use_replication(struct omap_dss_device *dssdev,
371 case OMAP_DISPLAY_TYPE_DPI: 383 case OMAP_DISPLAY_TYPE_DPI:
372 bpp = dssdev->phy.dpi.data_lines; 384 bpp = dssdev->phy.dpi.data_lines;
373 break; 385 break;
386 case OMAP_DISPLAY_TYPE_HDMI:
374 case OMAP_DISPLAY_TYPE_VENC: 387 case OMAP_DISPLAY_TYPE_VENC:
375 case OMAP_DISPLAY_TYPE_SDI: 388 case OMAP_DISPLAY_TYPE_SDI:
376 bpp = 24; 389 bpp = 24;
@@ -396,29 +409,6 @@ void dss_init_device(struct platform_device *pdev,
396 switch (dssdev->type) { 409 switch (dssdev->type) {
397#ifdef CONFIG_OMAP2_DSS_DPI 410#ifdef CONFIG_OMAP2_DSS_DPI
398 case OMAP_DISPLAY_TYPE_DPI: 411 case OMAP_DISPLAY_TYPE_DPI:
399#endif
400#ifdef CONFIG_OMAP2_DSS_RFBI
401 case OMAP_DISPLAY_TYPE_DBI:
402#endif
403#ifdef CONFIG_OMAP2_DSS_SDI
404 case OMAP_DISPLAY_TYPE_SDI:
405#endif
406#ifdef CONFIG_OMAP2_DSS_DSI
407 case OMAP_DISPLAY_TYPE_DSI:
408#endif
409#ifdef CONFIG_OMAP2_DSS_VENC
410 case OMAP_DISPLAY_TYPE_VENC:
411#endif
412 break;
413 default:
414 DSSERR("Support for display '%s' not compiled in.\n",
415 dssdev->name);
416 return;
417 }
418
419 switch (dssdev->type) {
420#ifdef CONFIG_OMAP2_DSS_DPI
421 case OMAP_DISPLAY_TYPE_DPI:
422 r = dpi_init_display(dssdev); 412 r = dpi_init_display(dssdev);
423 break; 413 break;
424#endif 414#endif
@@ -442,8 +432,13 @@ void dss_init_device(struct platform_device *pdev,
442 r = dsi_init_display(dssdev); 432 r = dsi_init_display(dssdev);
443 break; 433 break;
444#endif 434#endif
435 case OMAP_DISPLAY_TYPE_HDMI:
436 r = hdmi_init_display(dssdev);
437 break;
445 default: 438 default:
446 BUG(); 439 DSSERR("Support for display '%s' not compiled in.\n",
440 dssdev->name);
441 return;
447 } 442 }
448 443
449 if (r) { 444 if (r) {
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 960e977a8bf0..ff6bd30132df 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -30,47 +30,73 @@
30#include <linux/platform_device.h> 30#include <linux/platform_device.h>
31#include <linux/regulator/consumer.h> 31#include <linux/regulator/consumer.h>
32 32
33#include <plat/display.h> 33#include <video/omapdss.h>
34#include <plat/cpu.h> 34#include <plat/cpu.h>
35 35
36#include "dss.h" 36#include "dss.h"
37 37
38static struct { 38static struct {
39 struct regulator *vdds_dsi_reg; 39 struct regulator *vdds_dsi_reg;
40 struct platform_device *dsidev;
40} dpi; 41} dpi;
41 42
42#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL 43static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk)
43static int dpi_set_dsi_clk(bool is_tft, unsigned long pck_req, 44{
44 unsigned long *fck, int *lck_div, int *pck_div) 45 int dsi_module;
46
47 dsi_module = clk == OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ? 0 : 1;
48
49 return dsi_get_dsidev_from_id(dsi_module);
50}
51
52static bool dpi_use_dsi_pll(struct omap_dss_device *dssdev)
53{
54 if (dssdev->clocks.dispc.dispc_fclk_src ==
55 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ||
56 dssdev->clocks.dispc.dispc_fclk_src ==
57 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC ||
58 dssdev->clocks.dispc.channel.lcd_clk_src ==
59 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ||
60 dssdev->clocks.dispc.channel.lcd_clk_src ==
61 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC)
62 return true;
63 else
64 return false;
65}
66
67static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft,
68 unsigned long pck_req, unsigned long *fck, int *lck_div,
69 int *pck_div)
45{ 70{
46 struct dsi_clock_info dsi_cinfo; 71 struct dsi_clock_info dsi_cinfo;
47 struct dispc_clock_info dispc_cinfo; 72 struct dispc_clock_info dispc_cinfo;
48 int r; 73 int r;
49 74
50 r = dsi_pll_calc_clock_div_pck(is_tft, pck_req, &dsi_cinfo, 75 r = dsi_pll_calc_clock_div_pck(dpi.dsidev, is_tft, pck_req,
51 &dispc_cinfo); 76 &dsi_cinfo, &dispc_cinfo);
52 if (r) 77 if (r)
53 return r; 78 return r;
54 79
55 r = dsi_pll_set_clock_div(&dsi_cinfo); 80 r = dsi_pll_set_clock_div(dpi.dsidev, &dsi_cinfo);
56 if (r) 81 if (r)
57 return r; 82 return r;
58 83
59 dss_select_dispc_clk_source(DSS_SRC_DSI1_PLL_FCLK); 84 dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
60 85
61 r = dispc_set_clock_div(&dispc_cinfo); 86 r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
62 if (r) 87 if (r)
63 return r; 88 return r;
64 89
65 *fck = dsi_cinfo.dsi1_pll_fclk; 90 *fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
66 *lck_div = dispc_cinfo.lck_div; 91 *lck_div = dispc_cinfo.lck_div;
67 *pck_div = dispc_cinfo.pck_div; 92 *pck_div = dispc_cinfo.pck_div;
68 93
69 return 0; 94 return 0;
70} 95}
71#else 96
72static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req, 97static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, bool is_tft,
73 unsigned long *fck, int *lck_div, int *pck_div) 98 unsigned long pck_req, unsigned long *fck, int *lck_div,
99 int *pck_div)
74{ 100{
75 struct dss_clock_info dss_cinfo; 101 struct dss_clock_info dss_cinfo;
76 struct dispc_clock_info dispc_cinfo; 102 struct dispc_clock_info dispc_cinfo;
@@ -84,7 +110,7 @@ static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req,
84 if (r) 110 if (r)
85 return r; 111 return r;
86 112
87 r = dispc_set_clock_div(&dispc_cinfo); 113 r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
88 if (r) 114 if (r)
89 return r; 115 return r;
90 116
@@ -94,31 +120,29 @@ static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req,
94 120
95 return 0; 121 return 0;
96} 122}
97#endif
98 123
99static int dpi_set_mode(struct omap_dss_device *dssdev) 124static int dpi_set_mode(struct omap_dss_device *dssdev)
100{ 125{
101 struct omap_video_timings *t = &dssdev->panel.timings; 126 struct omap_video_timings *t = &dssdev->panel.timings;
102 int lck_div, pck_div; 127 int lck_div = 0, pck_div = 0;
103 unsigned long fck; 128 unsigned long fck = 0;
104 unsigned long pck; 129 unsigned long pck;
105 bool is_tft; 130 bool is_tft;
106 int r = 0; 131 int r = 0;
107 132
108 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); 133 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
109 134
110 dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi, 135 dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
111 dssdev->panel.acb); 136 dssdev->panel.acbi, dssdev->panel.acb);
112 137
113 is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; 138 is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
114 139
115#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL 140 if (dpi_use_dsi_pll(dssdev))
116 r = dpi_set_dsi_clk(is_tft, t->pixel_clock * 1000, 141 r = dpi_set_dsi_clk(dssdev, is_tft, t->pixel_clock * 1000,
117 &fck, &lck_div, &pck_div); 142 &fck, &lck_div, &pck_div);
118#else 143 else
119 r = dpi_set_dispc_clk(is_tft, t->pixel_clock * 1000, 144 r = dpi_set_dispc_clk(dssdev, is_tft, t->pixel_clock * 1000,
120 &fck, &lck_div, &pck_div); 145 &fck, &lck_div, &pck_div);
121#endif
122 if (r) 146 if (r)
123 goto err0; 147 goto err0;
124 148
@@ -132,10 +156,10 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
132 t->pixel_clock = pck; 156 t->pixel_clock = pck;
133 } 157 }
134 158
135 dispc_set_lcd_timings(t); 159 dispc_set_lcd_timings(dssdev->manager->id, t);
136 160
137err0: 161err0:
138 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); 162 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
139 return r; 163 return r;
140} 164}
141 165
@@ -145,10 +169,12 @@ static int dpi_basic_init(struct omap_dss_device *dssdev)
145 169
146 is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; 170 is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
147 171
148 dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS); 172 dispc_set_parallel_interface_mode(dssdev->manager->id,
149 dispc_set_lcd_display_type(is_tft ? OMAP_DSS_LCD_DISPLAY_TFT : 173 OMAP_DSS_PARALLELMODE_BYPASS);
150 OMAP_DSS_LCD_DISPLAY_STN); 174 dispc_set_lcd_display_type(dssdev->manager->id, is_tft ?
151 dispc_set_tft_data_lines(dssdev->phy.dpi.data_lines); 175 OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN);
176 dispc_set_tft_data_lines(dssdev->manager->id,
177 dssdev->phy.dpi.data_lines);
152 178
153 return 0; 179 return 0;
154} 180}
@@ -169,18 +195,19 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
169 goto err1; 195 goto err1;
170 } 196 }
171 197
172 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); 198 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
173 199
174 r = dpi_basic_init(dssdev); 200 r = dpi_basic_init(dssdev);
175 if (r) 201 if (r)
176 goto err2; 202 goto err2;
177 203
178#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL 204 if (dpi_use_dsi_pll(dssdev)) {
179 dss_clk_enable(DSS_CLK_FCK2); 205 dss_clk_enable(DSS_CLK_SYSCK);
180 r = dsi_pll_init(dssdev, 0, 1); 206 r = dsi_pll_init(dpi.dsidev, 0, 1);
181 if (r) 207 if (r)
182 goto err3; 208 goto err3;
183#endif 209 }
210
184 r = dpi_set_mode(dssdev); 211 r = dpi_set_mode(dssdev);
185 if (r) 212 if (r)
186 goto err4; 213 goto err4;
@@ -192,13 +219,13 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
192 return 0; 219 return 0;
193 220
194err4: 221err4:
195#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL 222 if (dpi_use_dsi_pll(dssdev))
196 dsi_pll_uninit(); 223 dsi_pll_uninit(dpi.dsidev, true);
197err3: 224err3:
198 dss_clk_disable(DSS_CLK_FCK2); 225 if (dpi_use_dsi_pll(dssdev))
199#endif 226 dss_clk_disable(DSS_CLK_SYSCK);
200err2: 227err2:
201 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); 228 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
202 if (cpu_is_omap34xx()) 229 if (cpu_is_omap34xx())
203 regulator_disable(dpi.vdds_dsi_reg); 230 regulator_disable(dpi.vdds_dsi_reg);
204err1: 231err1:
@@ -212,13 +239,13 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
212{ 239{
213 dssdev->manager->disable(dssdev->manager); 240 dssdev->manager->disable(dssdev->manager);
214 241
215#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL 242 if (dpi_use_dsi_pll(dssdev)) {
216 dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK); 243 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
217 dsi_pll_uninit(); 244 dsi_pll_uninit(dpi.dsidev, true);
218 dss_clk_disable(DSS_CLK_FCK2); 245 dss_clk_disable(DSS_CLK_SYSCK);
219#endif 246 }
220 247
221 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); 248 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
222 249
223 if (cpu_is_omap34xx()) 250 if (cpu_is_omap34xx())
224 regulator_disable(dpi.vdds_dsi_reg); 251 regulator_disable(dpi.vdds_dsi_reg);
@@ -234,7 +261,7 @@ void dpi_set_timings(struct omap_dss_device *dssdev,
234 dssdev->panel.timings = *timings; 261 dssdev->panel.timings = *timings;
235 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { 262 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
236 dpi_set_mode(dssdev); 263 dpi_set_mode(dssdev);
237 dispc_go(OMAP_DSS_CHANNEL_LCD); 264 dispc_go(dssdev->manager->id);
238 } 265 }
239} 266}
240EXPORT_SYMBOL(dpi_set_timings); 267EXPORT_SYMBOL(dpi_set_timings);
@@ -247,6 +274,7 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
247 int lck_div, pck_div; 274 int lck_div, pck_div;
248 unsigned long fck; 275 unsigned long fck;
249 unsigned long pck; 276 unsigned long pck;
277 struct dispc_clock_info dispc_cinfo;
250 278
251 if (!dispc_lcd_timings_ok(timings)) 279 if (!dispc_lcd_timings_ok(timings))
252 return -EINVAL; 280 return -EINVAL;
@@ -256,25 +284,18 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
256 284
257 is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; 285 is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
258 286
259#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL 287 if (dpi_use_dsi_pll(dssdev)) {
260 {
261 struct dsi_clock_info dsi_cinfo; 288 struct dsi_clock_info dsi_cinfo;
262 struct dispc_clock_info dispc_cinfo; 289 r = dsi_pll_calc_clock_div_pck(dpi.dsidev, is_tft,
263 r = dsi_pll_calc_clock_div_pck(is_tft,
264 timings->pixel_clock * 1000, 290 timings->pixel_clock * 1000,
265 &dsi_cinfo, &dispc_cinfo); 291 &dsi_cinfo, &dispc_cinfo);
266 292
267 if (r) 293 if (r)
268 return r; 294 return r;
269 295
270 fck = dsi_cinfo.dsi1_pll_fclk; 296 fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
271 lck_div = dispc_cinfo.lck_div; 297 } else {
272 pck_div = dispc_cinfo.pck_div;
273 }
274#else
275 {
276 struct dss_clock_info dss_cinfo; 298 struct dss_clock_info dss_cinfo;
277 struct dispc_clock_info dispc_cinfo;
278 r = dss_calc_clock_div(is_tft, timings->pixel_clock * 1000, 299 r = dss_calc_clock_div(is_tft, timings->pixel_clock * 1000,
279 &dss_cinfo, &dispc_cinfo); 300 &dss_cinfo, &dispc_cinfo);
280 301
@@ -282,10 +303,10 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
282 return r; 303 return r;
283 304
284 fck = dss_cinfo.fck; 305 fck = dss_cinfo.fck;
285 lck_div = dispc_cinfo.lck_div;
286 pck_div = dispc_cinfo.pck_div;
287 } 306 }
288#endif 307
308 lck_div = dispc_cinfo.lck_div;
309 pck_div = dispc_cinfo.pck_div;
289 310
290 pck = fck / lck_div / pck_div / 1000; 311 pck = fck / lck_div / pck_div / 1000;
291 312
@@ -299,22 +320,33 @@ int dpi_init_display(struct omap_dss_device *dssdev)
299{ 320{
300 DSSDBG("init_display\n"); 321 DSSDBG("init_display\n");
301 322
302 return 0; 323 if (cpu_is_omap34xx() && dpi.vdds_dsi_reg == NULL) {
303} 324 struct regulator *vdds_dsi;
304 325
305int dpi_init(struct platform_device *pdev) 326 vdds_dsi = dss_get_vdds_dsi();
306{ 327
307 if (cpu_is_omap34xx()) { 328 if (IS_ERR(vdds_dsi)) {
308 dpi.vdds_dsi_reg = dss_get_vdds_dsi();
309 if (IS_ERR(dpi.vdds_dsi_reg)) {
310 DSSERR("can't get VDDS_DSI regulator\n"); 329 DSSERR("can't get VDDS_DSI regulator\n");
311 return PTR_ERR(dpi.vdds_dsi_reg); 330 return PTR_ERR(vdds_dsi);
312 } 331 }
332
333 dpi.vdds_dsi_reg = vdds_dsi;
334 }
335
336 if (dpi_use_dsi_pll(dssdev)) {
337 enum omap_dss_clk_source dispc_fclk_src =
338 dssdev->clocks.dispc.dispc_fclk_src;
339 dpi.dsidev = dpi_get_dsidev(dispc_fclk_src);
313 } 340 }
314 341
315 return 0; 342 return 0;
316} 343}
317 344
345int dpi_init(void)
346{
347 return 0;
348}
349
318void dpi_exit(void) 350void dpi_exit(void)
319{ 351{
320} 352}
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index b3fa3a7db911..345757cfcbee 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -33,17 +33,19 @@
33#include <linux/regulator/consumer.h> 33#include <linux/regulator/consumer.h>
34#include <linux/wait.h> 34#include <linux/wait.h>
35#include <linux/workqueue.h> 35#include <linux/workqueue.h>
36#include <linux/sched.h>
37#include <linux/slab.h>
38#include <linux/debugfs.h>
36 39
37#include <plat/display.h> 40#include <video/omapdss.h>
38#include <plat/clock.h> 41#include <plat/clock.h>
39 42
40#include "dss.h" 43#include "dss.h"
44#include "dss_features.h"
41 45
42/*#define VERBOSE_IRQ*/ 46/*#define VERBOSE_IRQ*/
43#define DSI_CATCH_MISSING_TE 47#define DSI_CATCH_MISSING_TE
44 48
45#define DSI_BASE 0x4804FC00
46
47struct dsi_reg { u16 idx; }; 49struct dsi_reg { u16 idx; };
48 50
49#define DSI_REG(idx) ((const struct dsi_reg) { idx }) 51#define DSI_REG(idx) ((const struct dsi_reg) { idx })
@@ -57,6 +59,7 @@ struct dsi_reg { u16 idx; };
57#define DSI_IRQSTATUS DSI_REG(0x0018) 59#define DSI_IRQSTATUS DSI_REG(0x0018)
58#define DSI_IRQENABLE DSI_REG(0x001C) 60#define DSI_IRQENABLE DSI_REG(0x001C)
59#define DSI_CTRL DSI_REG(0x0040) 61#define DSI_CTRL DSI_REG(0x0040)
62#define DSI_GNQ DSI_REG(0x0044)
60#define DSI_COMPLEXIO_CFG1 DSI_REG(0x0048) 63#define DSI_COMPLEXIO_CFG1 DSI_REG(0x0048)
61#define DSI_COMPLEXIO_IRQ_STATUS DSI_REG(0x004C) 64#define DSI_COMPLEXIO_IRQ_STATUS DSI_REG(0x004C)
62#define DSI_COMPLEXIO_IRQ_ENABLE DSI_REG(0x0050) 65#define DSI_COMPLEXIO_IRQ_ENABLE DSI_REG(0x0050)
@@ -91,6 +94,7 @@ struct dsi_reg { u16 idx; };
91#define DSI_DSIPHY_CFG1 DSI_REG(0x200 + 0x0004) 94#define DSI_DSIPHY_CFG1 DSI_REG(0x200 + 0x0004)
92#define DSI_DSIPHY_CFG2 DSI_REG(0x200 + 0x0008) 95#define DSI_DSIPHY_CFG2 DSI_REG(0x200 + 0x0008)
93#define DSI_DSIPHY_CFG5 DSI_REG(0x200 + 0x0014) 96#define DSI_DSIPHY_CFG5 DSI_REG(0x200 + 0x0014)
97#define DSI_DSIPHY_CFG10 DSI_REG(0x200 + 0x0028)
94 98
95/* DSI_PLL_CTRL_SCP */ 99/* DSI_PLL_CTRL_SCP */
96 100
@@ -100,11 +104,11 @@ struct dsi_reg { u16 idx; };
100#define DSI_PLL_CONFIGURATION1 DSI_REG(0x300 + 0x000C) 104#define DSI_PLL_CONFIGURATION1 DSI_REG(0x300 + 0x000C)
101#define DSI_PLL_CONFIGURATION2 DSI_REG(0x300 + 0x0010) 105#define DSI_PLL_CONFIGURATION2 DSI_REG(0x300 + 0x0010)
102 106
103#define REG_GET(idx, start, end) \ 107#define REG_GET(dsidev, idx, start, end) \
104 FLD_GET(dsi_read_reg(idx), start, end) 108 FLD_GET(dsi_read_reg(dsidev, idx), start, end)
105 109
106#define REG_FLD_MOD(idx, val, start, end) \ 110#define REG_FLD_MOD(dsidev, idx, val, start, end) \
107 dsi_write_reg(idx, FLD_MOD(dsi_read_reg(idx), val, start, end)) 111 dsi_write_reg(dsidev, idx, FLD_MOD(dsi_read_reg(dsidev, idx), val, start, end))
108 112
109/* Global interrupts */ 113/* Global interrupts */
110#define DSI_IRQ_VC0 (1 << 0) 114#define DSI_IRQ_VC0 (1 << 0)
@@ -148,31 +152,50 @@ struct dsi_reg { u16 idx; };
148#define DSI_CIO_IRQ_ERRSYNCESC1 (1 << 0) 152#define DSI_CIO_IRQ_ERRSYNCESC1 (1 << 0)
149#define DSI_CIO_IRQ_ERRSYNCESC2 (1 << 1) 153#define DSI_CIO_IRQ_ERRSYNCESC2 (1 << 1)
150#define DSI_CIO_IRQ_ERRSYNCESC3 (1 << 2) 154#define DSI_CIO_IRQ_ERRSYNCESC3 (1 << 2)
155#define DSI_CIO_IRQ_ERRSYNCESC4 (1 << 3)
156#define DSI_CIO_IRQ_ERRSYNCESC5 (1 << 4)
151#define DSI_CIO_IRQ_ERRESC1 (1 << 5) 157#define DSI_CIO_IRQ_ERRESC1 (1 << 5)
152#define DSI_CIO_IRQ_ERRESC2 (1 << 6) 158#define DSI_CIO_IRQ_ERRESC2 (1 << 6)
153#define DSI_CIO_IRQ_ERRESC3 (1 << 7) 159#define DSI_CIO_IRQ_ERRESC3 (1 << 7)
160#define DSI_CIO_IRQ_ERRESC4 (1 << 8)
161#define DSI_CIO_IRQ_ERRESC5 (1 << 9)
154#define DSI_CIO_IRQ_ERRCONTROL1 (1 << 10) 162#define DSI_CIO_IRQ_ERRCONTROL1 (1 << 10)
155#define DSI_CIO_IRQ_ERRCONTROL2 (1 << 11) 163#define DSI_CIO_IRQ_ERRCONTROL2 (1 << 11)
156#define DSI_CIO_IRQ_ERRCONTROL3 (1 << 12) 164#define DSI_CIO_IRQ_ERRCONTROL3 (1 << 12)
165#define DSI_CIO_IRQ_ERRCONTROL4 (1 << 13)
166#define DSI_CIO_IRQ_ERRCONTROL5 (1 << 14)
157#define DSI_CIO_IRQ_STATEULPS1 (1 << 15) 167#define DSI_CIO_IRQ_STATEULPS1 (1 << 15)
158#define DSI_CIO_IRQ_STATEULPS2 (1 << 16) 168#define DSI_CIO_IRQ_STATEULPS2 (1 << 16)
159#define DSI_CIO_IRQ_STATEULPS3 (1 << 17) 169#define DSI_CIO_IRQ_STATEULPS3 (1 << 17)
170#define DSI_CIO_IRQ_STATEULPS4 (1 << 18)
171#define DSI_CIO_IRQ_STATEULPS5 (1 << 19)
160#define DSI_CIO_IRQ_ERRCONTENTIONLP0_1 (1 << 20) 172#define DSI_CIO_IRQ_ERRCONTENTIONLP0_1 (1 << 20)
161#define DSI_CIO_IRQ_ERRCONTENTIONLP1_1 (1 << 21) 173#define DSI_CIO_IRQ_ERRCONTENTIONLP1_1 (1 << 21)
162#define DSI_CIO_IRQ_ERRCONTENTIONLP0_2 (1 << 22) 174#define DSI_CIO_IRQ_ERRCONTENTIONLP0_2 (1 << 22)
163#define DSI_CIO_IRQ_ERRCONTENTIONLP1_2 (1 << 23) 175#define DSI_CIO_IRQ_ERRCONTENTIONLP1_2 (1 << 23)
164#define DSI_CIO_IRQ_ERRCONTENTIONLP0_3 (1 << 24) 176#define DSI_CIO_IRQ_ERRCONTENTIONLP0_3 (1 << 24)
165#define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25) 177#define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25)
178#define DSI_CIO_IRQ_ERRCONTENTIONLP0_4 (1 << 26)
179#define DSI_CIO_IRQ_ERRCONTENTIONLP1_4 (1 << 27)
180#define DSI_CIO_IRQ_ERRCONTENTIONLP0_5 (1 << 28)
181#define DSI_CIO_IRQ_ERRCONTENTIONLP1_5 (1 << 29)
166#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30) 182#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30)
167#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31) 183#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31)
168#define DSI_CIO_IRQ_ERROR_MASK \ 184#define DSI_CIO_IRQ_ERROR_MASK \
169 (DSI_CIO_IRQ_ERRSYNCESC1 | DSI_CIO_IRQ_ERRSYNCESC2 | \ 185 (DSI_CIO_IRQ_ERRSYNCESC1 | DSI_CIO_IRQ_ERRSYNCESC2 | \
170 DSI_CIO_IRQ_ERRSYNCESC3 | DSI_CIO_IRQ_ERRESC1 | DSI_CIO_IRQ_ERRESC2 | \ 186 DSI_CIO_IRQ_ERRSYNCESC3 | DSI_CIO_IRQ_ERRSYNCESC4 | \
171 DSI_CIO_IRQ_ERRESC3 | DSI_CIO_IRQ_ERRCONTROL1 | \ 187 DSI_CIO_IRQ_ERRSYNCESC5 | \
172 DSI_CIO_IRQ_ERRCONTROL2 | DSI_CIO_IRQ_ERRCONTROL3 | \ 188 DSI_CIO_IRQ_ERRESC1 | DSI_CIO_IRQ_ERRESC2 | \
189 DSI_CIO_IRQ_ERRESC3 | DSI_CIO_IRQ_ERRESC4 | \
190 DSI_CIO_IRQ_ERRESC5 | \
191 DSI_CIO_IRQ_ERRCONTROL1 | DSI_CIO_IRQ_ERRCONTROL2 | \
192 DSI_CIO_IRQ_ERRCONTROL3 | DSI_CIO_IRQ_ERRCONTROL4 | \
193 DSI_CIO_IRQ_ERRCONTROL5 | \
173 DSI_CIO_IRQ_ERRCONTENTIONLP0_1 | DSI_CIO_IRQ_ERRCONTENTIONLP1_1 | \ 194 DSI_CIO_IRQ_ERRCONTENTIONLP0_1 | DSI_CIO_IRQ_ERRCONTENTIONLP1_1 | \
174 DSI_CIO_IRQ_ERRCONTENTIONLP0_2 | DSI_CIO_IRQ_ERRCONTENTIONLP1_2 | \ 195 DSI_CIO_IRQ_ERRCONTENTIONLP0_2 | DSI_CIO_IRQ_ERRCONTENTIONLP1_2 | \
175 DSI_CIO_IRQ_ERRCONTENTIONLP0_3 | DSI_CIO_IRQ_ERRCONTENTIONLP1_3) 196 DSI_CIO_IRQ_ERRCONTENTIONLP0_3 | DSI_CIO_IRQ_ERRCONTENTIONLP1_3 | \
197 DSI_CIO_IRQ_ERRCONTENTIONLP0_4 | DSI_CIO_IRQ_ERRCONTENTIONLP1_4 | \
198 DSI_CIO_IRQ_ERRCONTENTIONLP0_5 | DSI_CIO_IRQ_ERRCONTENTIONLP1_5)
176 199
177#define DSI_DT_DCS_SHORT_WRITE_0 0x05 200#define DSI_DT_DCS_SHORT_WRITE_0 0x05
178#define DSI_DT_DCS_SHORT_WRITE_1 0x15 201#define DSI_DT_DCS_SHORT_WRITE_1 0x15
@@ -186,13 +209,15 @@ struct dsi_reg { u16 idx; };
186#define DSI_DT_RX_SHORT_READ_1 0x21 209#define DSI_DT_RX_SHORT_READ_1 0x21
187#define DSI_DT_RX_SHORT_READ_2 0x22 210#define DSI_DT_RX_SHORT_READ_2 0x22
188 211
189#define FINT_MAX 2100000 212typedef void (*omap_dsi_isr_t) (void *arg, u32 mask);
190#define FINT_MIN 750000 213
191#define REGN_MAX (1 << 7) 214#define DSI_MAX_NR_ISRS 2
192#define REGM_MAX ((1 << 11) - 1) 215
193#define REGM3_MAX (1 << 4) 216struct dsi_isr_data {
194#define REGM4_MAX (1 << 4) 217 omap_dsi_isr_t isr;
195#define LP_DIV_MAX ((1 << 13) - 1) 218 void *arg;
219 u32 mask;
220};
196 221
197enum fifo_size { 222enum fifo_size {
198 DSI_FIFO_SIZE_0 = 0, 223 DSI_FIFO_SIZE_0 = 0,
@@ -207,6 +232,19 @@ enum dsi_vc_mode {
207 DSI_VC_MODE_VP, 232 DSI_VC_MODE_VP,
208}; 233};
209 234
235enum dsi_lane {
236 DSI_CLK_P = 1 << 0,
237 DSI_CLK_N = 1 << 1,
238 DSI_DATA1_P = 1 << 2,
239 DSI_DATA1_N = 1 << 3,
240 DSI_DATA2_P = 1 << 4,
241 DSI_DATA2_N = 1 << 5,
242 DSI_DATA3_P = 1 << 6,
243 DSI_DATA3_N = 1 << 7,
244 DSI_DATA4_P = 1 << 8,
245 DSI_DATA4_N = 1 << 9,
246};
247
210struct dsi_update_region { 248struct dsi_update_region {
211 u16 x, y, w, h; 249 u16 x, y, w, h;
212 struct omap_dss_device *device; 250 struct omap_dss_device *device;
@@ -220,18 +258,29 @@ struct dsi_irq_stats {
220 unsigned cio_irqs[32]; 258 unsigned cio_irqs[32];
221}; 259};
222 260
223static struct 261struct dsi_isr_tables {
224{ 262 struct dsi_isr_data isr_table[DSI_MAX_NR_ISRS];
263 struct dsi_isr_data isr_table_vc[4][DSI_MAX_NR_ISRS];
264 struct dsi_isr_data isr_table_cio[DSI_MAX_NR_ISRS];
265};
266
267struct dsi_data {
268 struct platform_device *pdev;
225 void __iomem *base; 269 void __iomem *base;
270 int irq;
271
272 void (*dsi_mux_pads)(bool enable);
226 273
227 struct dsi_clock_info current_cinfo; 274 struct dsi_clock_info current_cinfo;
228 275
276 bool vdds_dsi_enabled;
229 struct regulator *vdds_dsi_reg; 277 struct regulator *vdds_dsi_reg;
230 278
231 struct { 279 struct {
232 enum dsi_vc_mode mode; 280 enum dsi_vc_mode mode;
233 struct omap_dss_device *dssdev; 281 struct omap_dss_device *dssdev;
234 enum fifo_size fifo_size; 282 enum fifo_size fifo_size;
283 int vc_id;
235 } vc[4]; 284 } vc[4];
236 285
237 struct mutex lock; 286 struct mutex lock;
@@ -239,15 +288,16 @@ static struct
239 288
240 unsigned pll_locked; 289 unsigned pll_locked;
241 290
242 struct completion bta_completion; 291 spinlock_t irq_lock;
243 void (*bta_callback)(void); 292 struct dsi_isr_tables isr_tables;
293 /* space for a copy used by the interrupt handler */
294 struct dsi_isr_tables isr_tables_copy;
244 295
245 int update_channel; 296 int update_channel;
246 struct dsi_update_region update_region; 297 struct dsi_update_region update_region;
247 298
248 bool te_enabled; 299 bool te_enabled;
249 300 bool ulps_enabled;
250 struct workqueue_struct *workqueue;
251 301
252 void (*framedone_callback)(int, void *); 302 void (*framedone_callback)(int, void *);
253 void *framedone_data; 303 void *framedone_data;
@@ -275,21 +325,68 @@ static struct
275 spinlock_t irq_stats_lock; 325 spinlock_t irq_stats_lock;
276 struct dsi_irq_stats irq_stats; 326 struct dsi_irq_stats irq_stats;
277#endif 327#endif
278} dsi; 328 /* DSI PLL Parameter Ranges */
329 unsigned long regm_max, regn_max;
330 unsigned long regm_dispc_max, regm_dsi_max;
331 unsigned long fint_min, fint_max;
332 unsigned long lpdiv_max;
333
334 int num_data_lanes;
335
336 unsigned scp_clk_refcount;
337};
338
339struct dsi_packet_sent_handler_data {
340 struct platform_device *dsidev;
341 struct completion *completion;
342};
343
344static struct platform_device *dsi_pdev_map[MAX_NUM_DSI];
279 345
280#ifdef DEBUG 346#ifdef DEBUG
281static unsigned int dsi_perf; 347static unsigned int dsi_perf;
282module_param_named(dsi_perf, dsi_perf, bool, 0644); 348module_param_named(dsi_perf, dsi_perf, bool, 0644);
283#endif 349#endif
284 350
285static inline void dsi_write_reg(const struct dsi_reg idx, u32 val) 351static inline struct dsi_data *dsi_get_dsidrv_data(struct platform_device *dsidev)
352{
353 return dev_get_drvdata(&dsidev->dev);
354}
355
356static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss_device *dssdev)
286{ 357{
287 __raw_writel(val, dsi.base + idx.idx); 358 return dsi_pdev_map[dssdev->phy.dsi.module];
288} 359}
289 360
290static inline u32 dsi_read_reg(const struct dsi_reg idx) 361struct platform_device *dsi_get_dsidev_from_id(int module)
291{ 362{
292 return __raw_readl(dsi.base + idx.idx); 363 return dsi_pdev_map[module];
364}
365
366static int dsi_get_dsidev_id(struct platform_device *dsidev)
367{
368 /* TEMP: Pass 0 as the dsi module index till the time the dsi platform
369 * device names aren't changed to the form "omapdss_dsi.0",
370 * "omapdss_dsi.1" and so on */
371 BUG_ON(dsidev->id != -1);
372
373 return 0;
374}
375
376static inline void dsi_write_reg(struct platform_device *dsidev,
377 const struct dsi_reg idx, u32 val)
378{
379 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
380
381 __raw_writel(val, dsi->base + idx.idx);
382}
383
384static inline u32 dsi_read_reg(struct platform_device *dsidev,
385 const struct dsi_reg idx)
386{
387 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
388
389 return __raw_readl(dsi->base + idx.idx);
293} 390}
294 391
295 392
@@ -301,29 +398,42 @@ void dsi_restore_context(void)
301{ 398{
302} 399}
303 400
304void dsi_bus_lock(void) 401void dsi_bus_lock(struct omap_dss_device *dssdev)
305{ 402{
306 down(&dsi.bus_lock); 403 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
404 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
405
406 down(&dsi->bus_lock);
307} 407}
308EXPORT_SYMBOL(dsi_bus_lock); 408EXPORT_SYMBOL(dsi_bus_lock);
309 409
310void dsi_bus_unlock(void) 410void dsi_bus_unlock(struct omap_dss_device *dssdev)
311{ 411{
312 up(&dsi.bus_lock); 412 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
413 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
414
415 up(&dsi->bus_lock);
313} 416}
314EXPORT_SYMBOL(dsi_bus_unlock); 417EXPORT_SYMBOL(dsi_bus_unlock);
315 418
316static bool dsi_bus_is_locked(void) 419static bool dsi_bus_is_locked(struct platform_device *dsidev)
317{ 420{
318 return dsi.bus_lock.count == 0; 421 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
422
423 return dsi->bus_lock.count == 0;
319} 424}
320 425
321static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum, 426static void dsi_completion_handler(void *data, u32 mask)
322 int value) 427{
428 complete((struct completion *)data);
429}
430
431static inline int wait_for_bit_change(struct platform_device *dsidev,
432 const struct dsi_reg idx, int bitnum, int value)
323{ 433{
324 int t = 100000; 434 int t = 100000;
325 435
326 while (REG_GET(idx, bitnum, bitnum) != value) { 436 while (REG_GET(dsidev, idx, bitnum, bitnum) != value) {
327 if (--t == 0) 437 if (--t == 0)
328 return !value; 438 return !value;
329 } 439 }
@@ -332,18 +442,21 @@ static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum,
332} 442}
333 443
334#ifdef DEBUG 444#ifdef DEBUG
335static void dsi_perf_mark_setup(void) 445static void dsi_perf_mark_setup(struct platform_device *dsidev)
336{ 446{
337 dsi.perf_setup_time = ktime_get(); 447 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
448 dsi->perf_setup_time = ktime_get();
338} 449}
339 450
340static void dsi_perf_mark_start(void) 451static void dsi_perf_mark_start(struct platform_device *dsidev)
341{ 452{
342 dsi.perf_start_time = ktime_get(); 453 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
454 dsi->perf_start_time = ktime_get();
343} 455}
344 456
345static void dsi_perf_show(const char *name) 457static void dsi_perf_show(struct platform_device *dsidev, const char *name)
346{ 458{
459 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
347 ktime_t t, setup_time, trans_time; 460 ktime_t t, setup_time, trans_time;
348 u32 total_bytes; 461 u32 total_bytes;
349 u32 setup_us, trans_us, total_us; 462 u32 setup_us, trans_us, total_us;
@@ -353,21 +466,21 @@ static void dsi_perf_show(const char *name)
353 466
354 t = ktime_get(); 467 t = ktime_get();
355 468
356 setup_time = ktime_sub(dsi.perf_start_time, dsi.perf_setup_time); 469 setup_time = ktime_sub(dsi->perf_start_time, dsi->perf_setup_time);
357 setup_us = (u32)ktime_to_us(setup_time); 470 setup_us = (u32)ktime_to_us(setup_time);
358 if (setup_us == 0) 471 if (setup_us == 0)
359 setup_us = 1; 472 setup_us = 1;
360 473
361 trans_time = ktime_sub(t, dsi.perf_start_time); 474 trans_time = ktime_sub(t, dsi->perf_start_time);
362 trans_us = (u32)ktime_to_us(trans_time); 475 trans_us = (u32)ktime_to_us(trans_time);
363 if (trans_us == 0) 476 if (trans_us == 0)
364 trans_us = 1; 477 trans_us = 1;
365 478
366 total_us = setup_us + trans_us; 479 total_us = setup_us + trans_us;
367 480
368 total_bytes = dsi.update_region.w * 481 total_bytes = dsi->update_region.w *
369 dsi.update_region.h * 482 dsi->update_region.h *
370 dsi.update_region.device->ctrl.pixel_size / 8; 483 dsi->update_region.device->ctrl.pixel_size / 8;
371 484
372 printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), " 485 printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), "
373 "%u bytes, %u kbytes/sec\n", 486 "%u bytes, %u kbytes/sec\n",
@@ -380,13 +493,16 @@ static void dsi_perf_show(const char *name)
380 total_bytes * 1000 / total_us); 493 total_bytes * 1000 / total_us);
381} 494}
382#else 495#else
383#define dsi_perf_mark_setup() 496#define dsi_perf_mark_setup(x)
384#define dsi_perf_mark_start() 497#define dsi_perf_mark_start(x)
385#define dsi_perf_show(x) 498#define dsi_perf_show(x, y)
386#endif 499#endif
387 500
388static void print_irq_status(u32 status) 501static void print_irq_status(u32 status)
389{ 502{
503 if (status == 0)
504 return;
505
390#ifndef VERBOSE_IRQ 506#ifndef VERBOSE_IRQ
391 if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0) 507 if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0)
392 return; 508 return;
@@ -422,6 +538,9 @@ static void print_irq_status(u32 status)
422 538
423static void print_irq_status_vc(int channel, u32 status) 539static void print_irq_status_vc(int channel, u32 status)
424{ 540{
541 if (status == 0)
542 return;
543
425#ifndef VERBOSE_IRQ 544#ifndef VERBOSE_IRQ
426 if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0) 545 if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
427 return; 546 return;
@@ -448,6 +567,9 @@ static void print_irq_status_vc(int channel, u32 status)
448 567
449static void print_irq_status_cio(u32 status) 568static void print_irq_status_cio(u32 status)
450{ 569{
570 if (status == 0)
571 return;
572
451 printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status); 573 printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status);
452 574
453#define PIS(x) \ 575#define PIS(x) \
@@ -478,192 +600,476 @@ static void print_irq_status_cio(u32 status)
478 printk("\n"); 600 printk("\n");
479} 601}
480 602
481static int debug_irq; 603#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
482 604static void dsi_collect_irq_stats(struct platform_device *dsidev, u32 irqstatus,
483/* called from dss */ 605 u32 *vcstatus, u32 ciostatus)
484void dsi_irq_handler(void)
485{ 606{
486 u32 irqstatus, vcstatus, ciostatus; 607 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
487 int i; 608 int i;
488 609
489 irqstatus = dsi_read_reg(DSI_IRQSTATUS); 610 spin_lock(&dsi->irq_stats_lock);
490 611
491#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 612 dsi->irq_stats.irq_count++;
492 spin_lock(&dsi.irq_stats_lock); 613 dss_collect_irq_stats(irqstatus, dsi->irq_stats.dsi_irqs);
493 dsi.irq_stats.irq_count++; 614
494 dss_collect_irq_stats(irqstatus, dsi.irq_stats.dsi_irqs); 615 for (i = 0; i < 4; ++i)
616 dss_collect_irq_stats(vcstatus[i], dsi->irq_stats.vc_irqs[i]);
617
618 dss_collect_irq_stats(ciostatus, dsi->irq_stats.cio_irqs);
619
620 spin_unlock(&dsi->irq_stats_lock);
621}
622#else
623#define dsi_collect_irq_stats(dsidev, irqstatus, vcstatus, ciostatus)
495#endif 624#endif
496 625
626static int debug_irq;
627
628static void dsi_handle_irq_errors(struct platform_device *dsidev, u32 irqstatus,
629 u32 *vcstatus, u32 ciostatus)
630{
631 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
632 int i;
633
497 if (irqstatus & DSI_IRQ_ERROR_MASK) { 634 if (irqstatus & DSI_IRQ_ERROR_MASK) {
498 DSSERR("DSI error, irqstatus %x\n", irqstatus); 635 DSSERR("DSI error, irqstatus %x\n", irqstatus);
499 print_irq_status(irqstatus); 636 print_irq_status(irqstatus);
500 spin_lock(&dsi.errors_lock); 637 spin_lock(&dsi->errors_lock);
501 dsi.errors |= irqstatus & DSI_IRQ_ERROR_MASK; 638 dsi->errors |= irqstatus & DSI_IRQ_ERROR_MASK;
502 spin_unlock(&dsi.errors_lock); 639 spin_unlock(&dsi->errors_lock);
503 } else if (debug_irq) { 640 } else if (debug_irq) {
504 print_irq_status(irqstatus); 641 print_irq_status(irqstatus);
505 } 642 }
506 643
507#ifdef DSI_CATCH_MISSING_TE 644 for (i = 0; i < 4; ++i) {
508 if (irqstatus & DSI_IRQ_TE_TRIGGER) 645 if (vcstatus[i] & DSI_VC_IRQ_ERROR_MASK) {
509 del_timer(&dsi.te_timer); 646 DSSERR("DSI VC(%d) error, vc irqstatus %x\n",
510#endif 647 i, vcstatus[i]);
648 print_irq_status_vc(i, vcstatus[i]);
649 } else if (debug_irq) {
650 print_irq_status_vc(i, vcstatus[i]);
651 }
652 }
653
654 if (ciostatus & DSI_CIO_IRQ_ERROR_MASK) {
655 DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus);
656 print_irq_status_cio(ciostatus);
657 } else if (debug_irq) {
658 print_irq_status_cio(ciostatus);
659 }
660}
661
662static void dsi_call_isrs(struct dsi_isr_data *isr_array,
663 unsigned isr_array_size, u32 irqstatus)
664{
665 struct dsi_isr_data *isr_data;
666 int i;
667
668 for (i = 0; i < isr_array_size; i++) {
669 isr_data = &isr_array[i];
670 if (isr_data->isr && isr_data->mask & irqstatus)
671 isr_data->isr(isr_data->arg, irqstatus);
672 }
673}
674
675static void dsi_handle_isrs(struct dsi_isr_tables *isr_tables,
676 u32 irqstatus, u32 *vcstatus, u32 ciostatus)
677{
678 int i;
679
680 dsi_call_isrs(isr_tables->isr_table,
681 ARRAY_SIZE(isr_tables->isr_table),
682 irqstatus);
511 683
512 for (i = 0; i < 4; ++i) { 684 for (i = 0; i < 4; ++i) {
513 if ((irqstatus & (1<<i)) == 0) 685 if (vcstatus[i] == 0)
514 continue; 686 continue;
687 dsi_call_isrs(isr_tables->isr_table_vc[i],
688 ARRAY_SIZE(isr_tables->isr_table_vc[i]),
689 vcstatus[i]);
690 }
515 691
516 vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i)); 692 if (ciostatus != 0)
693 dsi_call_isrs(isr_tables->isr_table_cio,
694 ARRAY_SIZE(isr_tables->isr_table_cio),
695 ciostatus);
696}
517 697
518#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 698static irqreturn_t omap_dsi_irq_handler(int irq, void *arg)
519 dss_collect_irq_stats(vcstatus, dsi.irq_stats.vc_irqs[i]); 699{
520#endif 700 struct platform_device *dsidev;
701 struct dsi_data *dsi;
702 u32 irqstatus, vcstatus[4], ciostatus;
703 int i;
521 704
522 if (vcstatus & DSI_VC_IRQ_BTA) { 705 dsidev = (struct platform_device *) arg;
523 complete(&dsi.bta_completion); 706 dsi = dsi_get_dsidrv_data(dsidev);
524 707
525 if (dsi.bta_callback) 708 spin_lock(&dsi->irq_lock);
526 dsi.bta_callback();
527 }
528 709
529 if (vcstatus & DSI_VC_IRQ_ERROR_MASK) { 710 irqstatus = dsi_read_reg(dsidev, DSI_IRQSTATUS);
530 DSSERR("DSI VC(%d) error, vc irqstatus %x\n", 711
531 i, vcstatus); 712 /* IRQ is not for us */
532 print_irq_status_vc(i, vcstatus); 713 if (!irqstatus) {
533 } else if (debug_irq) { 714 spin_unlock(&dsi->irq_lock);
534 print_irq_status_vc(i, vcstatus); 715 return IRQ_NONE;
716 }
717
718 dsi_write_reg(dsidev, DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
719 /* flush posted write */
720 dsi_read_reg(dsidev, DSI_IRQSTATUS);
721
722 for (i = 0; i < 4; ++i) {
723 if ((irqstatus & (1 << i)) == 0) {
724 vcstatus[i] = 0;
725 continue;
535 } 726 }
536 727
537 dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus); 728 vcstatus[i] = dsi_read_reg(dsidev, DSI_VC_IRQSTATUS(i));
729
730 dsi_write_reg(dsidev, DSI_VC_IRQSTATUS(i), vcstatus[i]);
538 /* flush posted write */ 731 /* flush posted write */
539 dsi_read_reg(DSI_VC_IRQSTATUS(i)); 732 dsi_read_reg(dsidev, DSI_VC_IRQSTATUS(i));
540 } 733 }
541 734
542 if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) { 735 if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) {
543 ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); 736 ciostatus = dsi_read_reg(dsidev, DSI_COMPLEXIO_IRQ_STATUS);
544 737
545#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 738 dsi_write_reg(dsidev, DSI_COMPLEXIO_IRQ_STATUS, ciostatus);
546 dss_collect_irq_stats(ciostatus, dsi.irq_stats.cio_irqs); 739 /* flush posted write */
740 dsi_read_reg(dsidev, DSI_COMPLEXIO_IRQ_STATUS);
741 } else {
742 ciostatus = 0;
743 }
744
745#ifdef DSI_CATCH_MISSING_TE
746 if (irqstatus & DSI_IRQ_TE_TRIGGER)
747 del_timer(&dsi->te_timer);
547#endif 748#endif
548 749
549 dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus); 750 /* make a copy and unlock, so that isrs can unregister
550 /* flush posted write */ 751 * themselves */
551 dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); 752 memcpy(&dsi->isr_tables_copy, &dsi->isr_tables,
753 sizeof(dsi->isr_tables));
552 754
553 if (ciostatus & DSI_CIO_IRQ_ERROR_MASK) { 755 spin_unlock(&dsi->irq_lock);
554 DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus); 756
555 print_irq_status_cio(ciostatus); 757 dsi_handle_isrs(&dsi->isr_tables_copy, irqstatus, vcstatus, ciostatus);
556 } else if (debug_irq) { 758
557 print_irq_status_cio(ciostatus); 759 dsi_handle_irq_errors(dsidev, irqstatus, vcstatus, ciostatus);
558 } 760
761 dsi_collect_irq_stats(dsidev, irqstatus, vcstatus, ciostatus);
762
763 return IRQ_HANDLED;
764}
765
766/* dsi->irq_lock has to be locked by the caller */
767static void _omap_dsi_configure_irqs(struct platform_device *dsidev,
768 struct dsi_isr_data *isr_array,
769 unsigned isr_array_size, u32 default_mask,
770 const struct dsi_reg enable_reg,
771 const struct dsi_reg status_reg)
772{
773 struct dsi_isr_data *isr_data;
774 u32 mask;
775 u32 old_mask;
776 int i;
777
778 mask = default_mask;
779
780 for (i = 0; i < isr_array_size; i++) {
781 isr_data = &isr_array[i];
782
783 if (isr_data->isr == NULL)
784 continue;
785
786 mask |= isr_data->mask;
559 } 787 }
560 788
561 dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK); 789 old_mask = dsi_read_reg(dsidev, enable_reg);
562 /* flush posted write */ 790 /* clear the irqstatus for newly enabled irqs */
563 dsi_read_reg(DSI_IRQSTATUS); 791 dsi_write_reg(dsidev, status_reg, (mask ^ old_mask) & mask);
792 dsi_write_reg(dsidev, enable_reg, mask);
564 793
565#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 794 /* flush posted writes */
566 spin_unlock(&dsi.irq_stats_lock); 795 dsi_read_reg(dsidev, enable_reg);
796 dsi_read_reg(dsidev, status_reg);
797}
798
799/* dsi->irq_lock has to be locked by the caller */
800static void _omap_dsi_set_irqs(struct platform_device *dsidev)
801{
802 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
803 u32 mask = DSI_IRQ_ERROR_MASK;
804#ifdef DSI_CATCH_MISSING_TE
805 mask |= DSI_IRQ_TE_TRIGGER;
567#endif 806#endif
807 _omap_dsi_configure_irqs(dsidev, dsi->isr_tables.isr_table,
808 ARRAY_SIZE(dsi->isr_tables.isr_table), mask,
809 DSI_IRQENABLE, DSI_IRQSTATUS);
810}
811
812/* dsi->irq_lock has to be locked by the caller */
813static void _omap_dsi_set_irqs_vc(struct platform_device *dsidev, int vc)
814{
815 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
816
817 _omap_dsi_configure_irqs(dsidev, dsi->isr_tables.isr_table_vc[vc],
818 ARRAY_SIZE(dsi->isr_tables.isr_table_vc[vc]),
819 DSI_VC_IRQ_ERROR_MASK,
820 DSI_VC_IRQENABLE(vc), DSI_VC_IRQSTATUS(vc));
568} 821}
569 822
823/* dsi->irq_lock has to be locked by the caller */
824static void _omap_dsi_set_irqs_cio(struct platform_device *dsidev)
825{
826 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
827
828 _omap_dsi_configure_irqs(dsidev, dsi->isr_tables.isr_table_cio,
829 ARRAY_SIZE(dsi->isr_tables.isr_table_cio),
830 DSI_CIO_IRQ_ERROR_MASK,
831 DSI_COMPLEXIO_IRQ_ENABLE, DSI_COMPLEXIO_IRQ_STATUS);
832}
570 833
571static void _dsi_initialize_irq(void) 834static void _dsi_initialize_irq(struct platform_device *dsidev)
572{ 835{
573 u32 l; 836 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
837 unsigned long flags;
838 int vc;
839
840 spin_lock_irqsave(&dsi->irq_lock, flags);
841
842 memset(&dsi->isr_tables, 0, sizeof(dsi->isr_tables));
843
844 _omap_dsi_set_irqs(dsidev);
845 for (vc = 0; vc < 4; ++vc)
846 _omap_dsi_set_irqs_vc(dsidev, vc);
847 _omap_dsi_set_irqs_cio(dsidev);
848
849 spin_unlock_irqrestore(&dsi->irq_lock, flags);
850}
851
852static int _dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask,
853 struct dsi_isr_data *isr_array, unsigned isr_array_size)
854{
855 struct dsi_isr_data *isr_data;
856 int free_idx;
574 int i; 857 int i;
575 858
576 /* disable all interrupts */ 859 BUG_ON(isr == NULL);
577 dsi_write_reg(DSI_IRQENABLE, 0);
578 for (i = 0; i < 4; ++i)
579 dsi_write_reg(DSI_VC_IRQENABLE(i), 0);
580 dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, 0);
581 860
582 /* clear interrupt status */ 861 /* check for duplicate entry and find a free slot */
583 l = dsi_read_reg(DSI_IRQSTATUS); 862 free_idx = -1;
584 dsi_write_reg(DSI_IRQSTATUS, l & ~DSI_IRQ_CHANNEL_MASK); 863 for (i = 0; i < isr_array_size; i++) {
864 isr_data = &isr_array[i];
585 865
586 for (i = 0; i < 4; ++i) { 866 if (isr_data->isr == isr && isr_data->arg == arg &&
587 l = dsi_read_reg(DSI_VC_IRQSTATUS(i)); 867 isr_data->mask == mask) {
588 dsi_write_reg(DSI_VC_IRQSTATUS(i), l); 868 return -EINVAL;
869 }
870
871 if (isr_data->isr == NULL && free_idx == -1)
872 free_idx = i;
589 } 873 }
590 874
591 l = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); 875 if (free_idx == -1)
592 dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, l); 876 return -EBUSY;
593 877
594 /* enable error irqs */ 878 isr_data = &isr_array[free_idx];
595 l = DSI_IRQ_ERROR_MASK; 879 isr_data->isr = isr;
596#ifdef DSI_CATCH_MISSING_TE 880 isr_data->arg = arg;
597 l |= DSI_IRQ_TE_TRIGGER; 881 isr_data->mask = mask;
598#endif
599 dsi_write_reg(DSI_IRQENABLE, l);
600 882
601 l = DSI_VC_IRQ_ERROR_MASK; 883 return 0;
602 for (i = 0; i < 4; ++i) 884}
603 dsi_write_reg(DSI_VC_IRQENABLE(i), l); 885
886static int _dsi_unregister_isr(omap_dsi_isr_t isr, void *arg, u32 mask,
887 struct dsi_isr_data *isr_array, unsigned isr_array_size)
888{
889 struct dsi_isr_data *isr_data;
890 int i;
891
892 for (i = 0; i < isr_array_size; i++) {
893 isr_data = &isr_array[i];
894 if (isr_data->isr != isr || isr_data->arg != arg ||
895 isr_data->mask != mask)
896 continue;
897
898 isr_data->isr = NULL;
899 isr_data->arg = NULL;
900 isr_data->mask = 0;
604 901
605 l = DSI_CIO_IRQ_ERROR_MASK; 902 return 0;
606 dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, l); 903 }
904
905 return -EINVAL;
607} 906}
608 907
609static u32 dsi_get_errors(void) 908static int dsi_register_isr(struct platform_device *dsidev, omap_dsi_isr_t isr,
909 void *arg, u32 mask)
610{ 910{
911 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
611 unsigned long flags; 912 unsigned long flags;
612 u32 e; 913 int r;
613 spin_lock_irqsave(&dsi.errors_lock, flags); 914
614 e = dsi.errors; 915 spin_lock_irqsave(&dsi->irq_lock, flags);
615 dsi.errors = 0; 916
616 spin_unlock_irqrestore(&dsi.errors_lock, flags); 917 r = _dsi_register_isr(isr, arg, mask, dsi->isr_tables.isr_table,
617 return e; 918 ARRAY_SIZE(dsi->isr_tables.isr_table));
919
920 if (r == 0)
921 _omap_dsi_set_irqs(dsidev);
922
923 spin_unlock_irqrestore(&dsi->irq_lock, flags);
924
925 return r;
618} 926}
619 927
620static void dsi_vc_enable_bta_irq(int channel) 928static int dsi_unregister_isr(struct platform_device *dsidev,
929 omap_dsi_isr_t isr, void *arg, u32 mask)
621{ 930{
622 u32 l; 931 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
932 unsigned long flags;
933 int r;
623 934
624 dsi_write_reg(DSI_VC_IRQSTATUS(channel), DSI_VC_IRQ_BTA); 935 spin_lock_irqsave(&dsi->irq_lock, flags);
625 936
626 l = dsi_read_reg(DSI_VC_IRQENABLE(channel)); 937 r = _dsi_unregister_isr(isr, arg, mask, dsi->isr_tables.isr_table,
627 l |= DSI_VC_IRQ_BTA; 938 ARRAY_SIZE(dsi->isr_tables.isr_table));
628 dsi_write_reg(DSI_VC_IRQENABLE(channel), l); 939
940 if (r == 0)
941 _omap_dsi_set_irqs(dsidev);
942
943 spin_unlock_irqrestore(&dsi->irq_lock, flags);
944
945 return r;
629} 946}
630 947
631static void dsi_vc_disable_bta_irq(int channel) 948static int dsi_register_isr_vc(struct platform_device *dsidev, int channel,
949 omap_dsi_isr_t isr, void *arg, u32 mask)
632{ 950{
633 u32 l; 951 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
952 unsigned long flags;
953 int r;
954
955 spin_lock_irqsave(&dsi->irq_lock, flags);
956
957 r = _dsi_register_isr(isr, arg, mask,
958 dsi->isr_tables.isr_table_vc[channel],
959 ARRAY_SIZE(dsi->isr_tables.isr_table_vc[channel]));
960
961 if (r == 0)
962 _omap_dsi_set_irqs_vc(dsidev, channel);
963
964 spin_unlock_irqrestore(&dsi->irq_lock, flags);
965
966 return r;
967}
968
969static int dsi_unregister_isr_vc(struct platform_device *dsidev, int channel,
970 omap_dsi_isr_t isr, void *arg, u32 mask)
971{
972 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
973 unsigned long flags;
974 int r;
975
976 spin_lock_irqsave(&dsi->irq_lock, flags);
977
978 r = _dsi_unregister_isr(isr, arg, mask,
979 dsi->isr_tables.isr_table_vc[channel],
980 ARRAY_SIZE(dsi->isr_tables.isr_table_vc[channel]));
981
982 if (r == 0)
983 _omap_dsi_set_irqs_vc(dsidev, channel);
984
985 spin_unlock_irqrestore(&dsi->irq_lock, flags);
986
987 return r;
988}
634 989
635 l = dsi_read_reg(DSI_VC_IRQENABLE(channel)); 990static int dsi_register_isr_cio(struct platform_device *dsidev,
636 l &= ~DSI_VC_IRQ_BTA; 991 omap_dsi_isr_t isr, void *arg, u32 mask)
637 dsi_write_reg(DSI_VC_IRQENABLE(channel), l); 992{
993 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
994 unsigned long flags;
995 int r;
996
997 spin_lock_irqsave(&dsi->irq_lock, flags);
998
999 r = _dsi_register_isr(isr, arg, mask, dsi->isr_tables.isr_table_cio,
1000 ARRAY_SIZE(dsi->isr_tables.isr_table_cio));
1001
1002 if (r == 0)
1003 _omap_dsi_set_irqs_cio(dsidev);
1004
1005 spin_unlock_irqrestore(&dsi->irq_lock, flags);
1006
1007 return r;
1008}
1009
1010static int dsi_unregister_isr_cio(struct platform_device *dsidev,
1011 omap_dsi_isr_t isr, void *arg, u32 mask)
1012{
1013 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1014 unsigned long flags;
1015 int r;
1016
1017 spin_lock_irqsave(&dsi->irq_lock, flags);
1018
1019 r = _dsi_unregister_isr(isr, arg, mask, dsi->isr_tables.isr_table_cio,
1020 ARRAY_SIZE(dsi->isr_tables.isr_table_cio));
1021
1022 if (r == 0)
1023 _omap_dsi_set_irqs_cio(dsidev);
1024
1025 spin_unlock_irqrestore(&dsi->irq_lock, flags);
1026
1027 return r;
638} 1028}
639 1029
640/* DSI func clock. this could also be DSI2_PLL_FCLK */ 1030static u32 dsi_get_errors(struct platform_device *dsidev)
1031{
1032 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1033 unsigned long flags;
1034 u32 e;
1035 spin_lock_irqsave(&dsi->errors_lock, flags);
1036 e = dsi->errors;
1037 dsi->errors = 0;
1038 spin_unlock_irqrestore(&dsi->errors_lock, flags);
1039 return e;
1040}
1041
1042/* DSI func clock. this could also be dsi_pll_hsdiv_dsi_clk */
641static inline void enable_clocks(bool enable) 1043static inline void enable_clocks(bool enable)
642{ 1044{
643 if (enable) 1045 if (enable)
644 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); 1046 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
645 else 1047 else
646 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); 1048 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
647} 1049}
648 1050
649/* source clock for DSI PLL. this could also be PCLKFREE */ 1051/* source clock for DSI PLL. this could also be PCLKFREE */
650static inline void dsi_enable_pll_clock(bool enable) 1052static inline void dsi_enable_pll_clock(struct platform_device *dsidev,
1053 bool enable)
651{ 1054{
1055 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1056
652 if (enable) 1057 if (enable)
653 dss_clk_enable(DSS_CLK_FCK2); 1058 dss_clk_enable(DSS_CLK_SYSCK);
654 else 1059 else
655 dss_clk_disable(DSS_CLK_FCK2); 1060 dss_clk_disable(DSS_CLK_SYSCK);
656 1061
657 if (enable && dsi.pll_locked) { 1062 if (enable && dsi->pll_locked) {
658 if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) 1063 if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1)
659 DSSERR("cannot lock PLL when enabling clocks\n"); 1064 DSSERR("cannot lock PLL when enabling clocks\n");
660 } 1065 }
661} 1066}
662 1067
663#ifdef DEBUG 1068#ifdef DEBUG
664static void _dsi_print_reset_status(void) 1069static void _dsi_print_reset_status(struct platform_device *dsidev)
665{ 1070{
666 u32 l; 1071 u32 l;
1072 int b0, b1, b2;
667 1073
668 if (!dss_debug) 1074 if (!dss_debug)
669 return; 1075 return;
@@ -671,35 +1077,47 @@ static void _dsi_print_reset_status(void)
671 /* A dummy read using the SCP interface to any DSIPHY register is 1077 /* A dummy read using the SCP interface to any DSIPHY register is
672 * required after DSIPHY reset to complete the reset of the DSI complex 1078 * required after DSIPHY reset to complete the reset of the DSI complex
673 * I/O. */ 1079 * I/O. */
674 l = dsi_read_reg(DSI_DSIPHY_CFG5); 1080 l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
675 1081
676 printk(KERN_DEBUG "DSI resets: "); 1082 printk(KERN_DEBUG "DSI resets: ");
677 1083
678 l = dsi_read_reg(DSI_PLL_STATUS); 1084 l = dsi_read_reg(dsidev, DSI_PLL_STATUS);
679 printk("PLL (%d) ", FLD_GET(l, 0, 0)); 1085 printk("PLL (%d) ", FLD_GET(l, 0, 0));
680 1086
681 l = dsi_read_reg(DSI_COMPLEXIO_CFG1); 1087 l = dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1);
682 printk("CIO (%d) ", FLD_GET(l, 29, 29)); 1088 printk("CIO (%d) ", FLD_GET(l, 29, 29));
683 1089
684 l = dsi_read_reg(DSI_DSIPHY_CFG5); 1090 if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) {
685 printk("PHY (%x, %d, %d, %d)\n", 1091 b0 = 28;
686 FLD_GET(l, 28, 26), 1092 b1 = 27;
1093 b2 = 26;
1094 } else {
1095 b0 = 24;
1096 b1 = 25;
1097 b2 = 26;
1098 }
1099
1100 l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
1101 printk("PHY (%x%x%x, %d, %d, %d)\n",
1102 FLD_GET(l, b0, b0),
1103 FLD_GET(l, b1, b1),
1104 FLD_GET(l, b2, b2),
687 FLD_GET(l, 29, 29), 1105 FLD_GET(l, 29, 29),
688 FLD_GET(l, 30, 30), 1106 FLD_GET(l, 30, 30),
689 FLD_GET(l, 31, 31)); 1107 FLD_GET(l, 31, 31));
690} 1108}
691#else 1109#else
692#define _dsi_print_reset_status() 1110#define _dsi_print_reset_status(x)
693#endif 1111#endif
694 1112
695static inline int dsi_if_enable(bool enable) 1113static inline int dsi_if_enable(struct platform_device *dsidev, bool enable)
696{ 1114{
697 DSSDBG("dsi_if_enable(%d)\n", enable); 1115 DSSDBG("dsi_if_enable(%d)\n", enable);
698 1116
699 enable = enable ? 1 : 0; 1117 enable = enable ? 1 : 0;
700 REG_FLD_MOD(DSI_CTRL, enable, 0, 0); /* IF_EN */ 1118 REG_FLD_MOD(dsidev, DSI_CTRL, enable, 0, 0); /* IF_EN */
701 1119
702 if (wait_for_bit_change(DSI_CTRL, 0, enable) != enable) { 1120 if (wait_for_bit_change(dsidev, DSI_CTRL, 0, enable) != enable) {
703 DSSERR("Failed to set dsi_if_enable to %d\n", enable); 1121 DSSERR("Failed to set dsi_if_enable to %d\n", enable);
704 return -EIO; 1122 return -EIO;
705 } 1123 }
@@ -707,31 +1125,38 @@ static inline int dsi_if_enable(bool enable)
707 return 0; 1125 return 0;
708} 1126}
709 1127
710unsigned long dsi_get_dsi1_pll_rate(void) 1128unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
711{ 1129{
712 return dsi.current_cinfo.dsi1_pll_fclk; 1130 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1131
1132 return dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk;
713} 1133}
714 1134
715static unsigned long dsi_get_dsi2_pll_rate(void) 1135static unsigned long dsi_get_pll_hsdiv_dsi_rate(struct platform_device *dsidev)
716{ 1136{
717 return dsi.current_cinfo.dsi2_pll_fclk; 1137 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1138
1139 return dsi->current_cinfo.dsi_pll_hsdiv_dsi_clk;
718} 1140}
719 1141
720static unsigned long dsi_get_txbyteclkhs(void) 1142static unsigned long dsi_get_txbyteclkhs(struct platform_device *dsidev)
721{ 1143{
722 return dsi.current_cinfo.clkin4ddr / 16; 1144 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1145
1146 return dsi->current_cinfo.clkin4ddr / 16;
723} 1147}
724 1148
725static unsigned long dsi_fclk_rate(void) 1149static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
726{ 1150{
727 unsigned long r; 1151 unsigned long r;
1152 int dsi_module = dsi_get_dsidev_id(dsidev);
728 1153
729 if (dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK) { 1154 if (dss_get_dsi_clk_source(dsi_module) == OMAP_DSS_CLK_SRC_FCK) {
730 /* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */ 1155 /* DSI FCLK source is DSS_CLK_FCK */
731 r = dss_clk_get_rate(DSS_CLK_FCK1); 1156 r = dss_clk_get_rate(DSS_CLK_FCK);
732 } else { 1157 } else {
733 /* DSI FCLK source is DSI2_PLL_FCLK */ 1158 /* DSI FCLK source is dsi_pll_hsdiv_dsi_clk */
734 r = dsi_get_dsi2_pll_rate(); 1159 r = dsi_get_pll_hsdiv_dsi_rate(dsidev);
735 } 1160 }
736 1161
737 return r; 1162 return r;
@@ -739,31 +1164,50 @@ static unsigned long dsi_fclk_rate(void)
739 1164
740static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev) 1165static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev)
741{ 1166{
1167 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
1168 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
742 unsigned long dsi_fclk; 1169 unsigned long dsi_fclk;
743 unsigned lp_clk_div; 1170 unsigned lp_clk_div;
744 unsigned long lp_clk; 1171 unsigned long lp_clk;
745 1172
746 lp_clk_div = dssdev->phy.dsi.div.lp_clk_div; 1173 lp_clk_div = dssdev->clocks.dsi.lp_clk_div;
747 1174
748 if (lp_clk_div == 0 || lp_clk_div > LP_DIV_MAX) 1175 if (lp_clk_div == 0 || lp_clk_div > dsi->lpdiv_max)
749 return -EINVAL; 1176 return -EINVAL;
750 1177
751 dsi_fclk = dsi_fclk_rate(); 1178 dsi_fclk = dsi_fclk_rate(dsidev);
752 1179
753 lp_clk = dsi_fclk / 2 / lp_clk_div; 1180 lp_clk = dsi_fclk / 2 / lp_clk_div;
754 1181
755 DSSDBG("LP_CLK_DIV %u, LP_CLK %lu\n", lp_clk_div, lp_clk); 1182 DSSDBG("LP_CLK_DIV %u, LP_CLK %lu\n", lp_clk_div, lp_clk);
756 dsi.current_cinfo.lp_clk = lp_clk; 1183 dsi->current_cinfo.lp_clk = lp_clk;
757 dsi.current_cinfo.lp_clk_div = lp_clk_div; 1184 dsi->current_cinfo.lp_clk_div = lp_clk_div;
758 1185
759 REG_FLD_MOD(DSI_CLK_CTRL, lp_clk_div, 12, 0); /* LP_CLK_DIVISOR */ 1186 /* LP_CLK_DIVISOR */
1187 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, lp_clk_div, 12, 0);
760 1188
761 REG_FLD_MOD(DSI_CLK_CTRL, dsi_fclk > 30000000 ? 1 : 0, 1189 /* LP_RX_SYNCHRO_ENABLE */
762 21, 21); /* LP_RX_SYNCHRO_ENABLE */ 1190 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, dsi_fclk > 30000000 ? 1 : 0, 21, 21);
763 1191
764 return 0; 1192 return 0;
765} 1193}
766 1194
1195static void dsi_enable_scp_clk(struct platform_device *dsidev)
1196{
1197 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1198
1199 if (dsi->scp_clk_refcount++ == 0)
1200 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 14, 14); /* CIO_CLK_ICG */
1201}
1202
1203static void dsi_disable_scp_clk(struct platform_device *dsidev)
1204{
1205 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1206
1207 WARN_ON(dsi->scp_clk_refcount == 0);
1208 if (--dsi->scp_clk_refcount == 0)
1209 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 14, 14); /* CIO_CLK_ICG */
1210}
767 1211
768enum dsi_pll_power_state { 1212enum dsi_pll_power_state {
769 DSI_PLL_POWER_OFF = 0x0, 1213 DSI_PLL_POWER_OFF = 0x0,
@@ -772,14 +1216,21 @@ enum dsi_pll_power_state {
772 DSI_PLL_POWER_ON_DIV = 0x3, 1216 DSI_PLL_POWER_ON_DIV = 0x3,
773}; 1217};
774 1218
775static int dsi_pll_power(enum dsi_pll_power_state state) 1219static int dsi_pll_power(struct platform_device *dsidev,
1220 enum dsi_pll_power_state state)
776{ 1221{
777 int t = 0; 1222 int t = 0;
778 1223
779 REG_FLD_MOD(DSI_CLK_CTRL, state, 31, 30); /* PLL_PWR_CMD */ 1224 /* DSI-PLL power command 0x3 is not working */
1225 if (dss_has_feature(FEAT_DSI_PLL_PWR_BUG) &&
1226 state == DSI_PLL_POWER_ON_DIV)
1227 state = DSI_PLL_POWER_ON_ALL;
1228
1229 /* PLL_PWR_CMD */
1230 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, state, 31, 30);
780 1231
781 /* PLL_PWR_STATUS */ 1232 /* PLL_PWR_STATUS */
782 while (FLD_GET(dsi_read_reg(DSI_CLK_CTRL), 29, 28) != state) { 1233 while (FLD_GET(dsi_read_reg(dsidev, DSI_CLK_CTRL), 29, 28) != state) {
783 if (++t > 1000) { 1234 if (++t > 1000) {
784 DSSERR("Failed to set DSI PLL power mode to %d\n", 1235 DSSERR("Failed to set DSI PLL power mode to %d\n",
785 state); 1236 state);
@@ -792,27 +1243,31 @@ static int dsi_pll_power(enum dsi_pll_power_state state)
792} 1243}
793 1244
794/* calculate clock rates using dividers in cinfo */ 1245/* calculate clock rates using dividers in cinfo */
795static int dsi_calc_clock_rates(struct dsi_clock_info *cinfo) 1246static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,
1247 struct dsi_clock_info *cinfo)
796{ 1248{
797 if (cinfo->regn == 0 || cinfo->regn > REGN_MAX) 1249 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
1250 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1251
1252 if (cinfo->regn == 0 || cinfo->regn > dsi->regn_max)
798 return -EINVAL; 1253 return -EINVAL;
799 1254
800 if (cinfo->regm == 0 || cinfo->regm > REGM_MAX) 1255 if (cinfo->regm == 0 || cinfo->regm > dsi->regm_max)
801 return -EINVAL; 1256 return -EINVAL;
802 1257
803 if (cinfo->regm3 > REGM3_MAX) 1258 if (cinfo->regm_dispc > dsi->regm_dispc_max)
804 return -EINVAL; 1259 return -EINVAL;
805 1260
806 if (cinfo->regm4 > REGM4_MAX) 1261 if (cinfo->regm_dsi > dsi->regm_dsi_max)
807 return -EINVAL; 1262 return -EINVAL;
808 1263
809 if (cinfo->use_dss2_fck) { 1264 if (cinfo->use_sys_clk) {
810 cinfo->clkin = dss_clk_get_rate(DSS_CLK_FCK2); 1265 cinfo->clkin = dss_clk_get_rate(DSS_CLK_SYSCK);
811 /* XXX it is unclear if highfreq should be used 1266 /* XXX it is unclear if highfreq should be used
812 * with DSS2_FCK source also */ 1267 * with DSS_SYS_CLK source also */
813 cinfo->highfreq = 0; 1268 cinfo->highfreq = 0;
814 } else { 1269 } else {
815 cinfo->clkin = dispc_pclk_rate(); 1270 cinfo->clkin = dispc_pclk_rate(dssdev->manager->id);
816 1271
817 if (cinfo->clkin < 32000000) 1272 if (cinfo->clkin < 32000000)
818 cinfo->highfreq = 0; 1273 cinfo->highfreq = 0;
@@ -822,7 +1277,7 @@ static int dsi_calc_clock_rates(struct dsi_clock_info *cinfo)
822 1277
823 cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1)); 1278 cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1));
824 1279
825 if (cinfo->fint > FINT_MAX || cinfo->fint < FINT_MIN) 1280 if (cinfo->fint > dsi->fint_max || cinfo->fint < dsi->fint_min)
826 return -EINVAL; 1281 return -EINVAL;
827 1282
828 cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint; 1283 cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint;
@@ -830,44 +1285,49 @@ static int dsi_calc_clock_rates(struct dsi_clock_info *cinfo)
830 if (cinfo->clkin4ddr > 1800 * 1000 * 1000) 1285 if (cinfo->clkin4ddr > 1800 * 1000 * 1000)
831 return -EINVAL; 1286 return -EINVAL;
832 1287
833 if (cinfo->regm3 > 0) 1288 if (cinfo->regm_dispc > 0)
834 cinfo->dsi1_pll_fclk = cinfo->clkin4ddr / cinfo->regm3; 1289 cinfo->dsi_pll_hsdiv_dispc_clk =
1290 cinfo->clkin4ddr / cinfo->regm_dispc;
835 else 1291 else
836 cinfo->dsi1_pll_fclk = 0; 1292 cinfo->dsi_pll_hsdiv_dispc_clk = 0;
837 1293
838 if (cinfo->regm4 > 0) 1294 if (cinfo->regm_dsi > 0)
839 cinfo->dsi2_pll_fclk = cinfo->clkin4ddr / cinfo->regm4; 1295 cinfo->dsi_pll_hsdiv_dsi_clk =
1296 cinfo->clkin4ddr / cinfo->regm_dsi;
840 else 1297 else
841 cinfo->dsi2_pll_fclk = 0; 1298 cinfo->dsi_pll_hsdiv_dsi_clk = 0;
842 1299
843 return 0; 1300 return 0;
844} 1301}
845 1302
846int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck, 1303int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, bool is_tft,
847 struct dsi_clock_info *dsi_cinfo, 1304 unsigned long req_pck, struct dsi_clock_info *dsi_cinfo,
848 struct dispc_clock_info *dispc_cinfo) 1305 struct dispc_clock_info *dispc_cinfo)
849{ 1306{
1307 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
850 struct dsi_clock_info cur, best; 1308 struct dsi_clock_info cur, best;
851 struct dispc_clock_info best_dispc; 1309 struct dispc_clock_info best_dispc;
852 int min_fck_per_pck; 1310 int min_fck_per_pck;
853 int match = 0; 1311 int match = 0;
854 unsigned long dss_clk_fck2; 1312 unsigned long dss_sys_clk, max_dss_fck;
1313
1314 dss_sys_clk = dss_clk_get_rate(DSS_CLK_SYSCK);
855 1315
856 dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2); 1316 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
857 1317
858 if (req_pck == dsi.cache_req_pck && 1318 if (req_pck == dsi->cache_req_pck &&
859 dsi.cache_cinfo.clkin == dss_clk_fck2) { 1319 dsi->cache_cinfo.clkin == dss_sys_clk) {
860 DSSDBG("DSI clock info found from cache\n"); 1320 DSSDBG("DSI clock info found from cache\n");
861 *dsi_cinfo = dsi.cache_cinfo; 1321 *dsi_cinfo = dsi->cache_cinfo;
862 dispc_find_clk_divs(is_tft, req_pck, dsi_cinfo->dsi1_pll_fclk, 1322 dispc_find_clk_divs(is_tft, req_pck,
863 dispc_cinfo); 1323 dsi_cinfo->dsi_pll_hsdiv_dispc_clk, dispc_cinfo);
864 return 0; 1324 return 0;
865 } 1325 }
866 1326
867 min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; 1327 min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
868 1328
869 if (min_fck_per_pck && 1329 if (min_fck_per_pck &&
870 req_pck * min_fck_per_pck > DISPC_MAX_FCK) { 1330 req_pck * min_fck_per_pck > max_dss_fck) {
871 DSSERR("Requested pixel clock not possible with the current " 1331 DSSERR("Requested pixel clock not possible with the current "
872 "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " 1332 "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
873 "the constraint off.\n"); 1333 "the constraint off.\n");
@@ -881,24 +1341,24 @@ retry:
881 memset(&best_dispc, 0, sizeof(best_dispc)); 1341 memset(&best_dispc, 0, sizeof(best_dispc));
882 1342
883 memset(&cur, 0, sizeof(cur)); 1343 memset(&cur, 0, sizeof(cur));
884 cur.clkin = dss_clk_fck2; 1344 cur.clkin = dss_sys_clk;
885 cur.use_dss2_fck = 1; 1345 cur.use_sys_clk = 1;
886 cur.highfreq = 0; 1346 cur.highfreq = 0;
887 1347
888 /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ 1348 /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */
889 /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ 1349 /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
890 /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ 1350 /* To reduce PLL lock time, keep Fint high (around 2 MHz) */
891 for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) { 1351 for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) {
892 if (cur.highfreq == 0) 1352 if (cur.highfreq == 0)
893 cur.fint = cur.clkin / cur.regn; 1353 cur.fint = cur.clkin / cur.regn;
894 else 1354 else
895 cur.fint = cur.clkin / (2 * cur.regn); 1355 cur.fint = cur.clkin / (2 * cur.regn);
896 1356
897 if (cur.fint > FINT_MAX || cur.fint < FINT_MIN) 1357 if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min)
898 continue; 1358 continue;
899 1359
900 /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ 1360 /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */
901 for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) { 1361 for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) {
902 unsigned long a, b; 1362 unsigned long a, b;
903 1363
904 a = 2 * cur.regm * (cur.clkin/1000); 1364 a = 2 * cur.regm * (cur.clkin/1000);
@@ -908,30 +1368,32 @@ retry:
908 if (cur.clkin4ddr > 1800 * 1000 * 1000) 1368 if (cur.clkin4ddr > 1800 * 1000 * 1000)
909 break; 1369 break;
910 1370
911 /* DSI1_PLL_FCLK(MHz) = DSIPHY(MHz) / regm3 < 173MHz */ 1371 /* dsi_pll_hsdiv_dispc_clk(MHz) =
912 for (cur.regm3 = 1; cur.regm3 < REGM3_MAX; 1372 * DSIPHY(MHz) / regm_dispc < 173MHz/186Mhz */
913 ++cur.regm3) { 1373 for (cur.regm_dispc = 1; cur.regm_dispc <
1374 dsi->regm_dispc_max; ++cur.regm_dispc) {
914 struct dispc_clock_info cur_dispc; 1375 struct dispc_clock_info cur_dispc;
915 cur.dsi1_pll_fclk = cur.clkin4ddr / cur.regm3; 1376 cur.dsi_pll_hsdiv_dispc_clk =
1377 cur.clkin4ddr / cur.regm_dispc;
916 1378
917 /* this will narrow down the search a bit, 1379 /* this will narrow down the search a bit,
918 * but still give pixclocks below what was 1380 * but still give pixclocks below what was
919 * requested */ 1381 * requested */
920 if (cur.dsi1_pll_fclk < req_pck) 1382 if (cur.dsi_pll_hsdiv_dispc_clk < req_pck)
921 break; 1383 break;
922 1384
923 if (cur.dsi1_pll_fclk > DISPC_MAX_FCK) 1385 if (cur.dsi_pll_hsdiv_dispc_clk > max_dss_fck)
924 continue; 1386 continue;
925 1387
926 if (min_fck_per_pck && 1388 if (min_fck_per_pck &&
927 cur.dsi1_pll_fclk < 1389 cur.dsi_pll_hsdiv_dispc_clk <
928 req_pck * min_fck_per_pck) 1390 req_pck * min_fck_per_pck)
929 continue; 1391 continue;
930 1392
931 match = 1; 1393 match = 1;
932 1394
933 dispc_find_clk_divs(is_tft, req_pck, 1395 dispc_find_clk_divs(is_tft, req_pck,
934 cur.dsi1_pll_fclk, 1396 cur.dsi_pll_hsdiv_dispc_clk,
935 &cur_dispc); 1397 &cur_dispc);
936 1398
937 if (abs(cur_dispc.pck - req_pck) < 1399 if (abs(cur_dispc.pck - req_pck) <
@@ -960,44 +1422,53 @@ found:
960 return -EINVAL; 1422 return -EINVAL;
961 } 1423 }
962 1424
963 /* DSI2_PLL_FCLK (regm4) is not used */ 1425 /* dsi_pll_hsdiv_dsi_clk (regm_dsi) is not used */
964 best.regm4 = 0; 1426 best.regm_dsi = 0;
965 best.dsi2_pll_fclk = 0; 1427 best.dsi_pll_hsdiv_dsi_clk = 0;
966 1428
967 if (dsi_cinfo) 1429 if (dsi_cinfo)
968 *dsi_cinfo = best; 1430 *dsi_cinfo = best;
969 if (dispc_cinfo) 1431 if (dispc_cinfo)
970 *dispc_cinfo = best_dispc; 1432 *dispc_cinfo = best_dispc;
971 1433
972 dsi.cache_req_pck = req_pck; 1434 dsi->cache_req_pck = req_pck;
973 dsi.cache_clk_freq = 0; 1435 dsi->cache_clk_freq = 0;
974 dsi.cache_cinfo = best; 1436 dsi->cache_cinfo = best;
975 1437
976 return 0; 1438 return 0;
977} 1439}
978 1440
979int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) 1441int dsi_pll_set_clock_div(struct platform_device *dsidev,
1442 struct dsi_clock_info *cinfo)
980{ 1443{
1444 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
981 int r = 0; 1445 int r = 0;
982 u32 l; 1446 u32 l;
983 int f; 1447 int f = 0;
1448 u8 regn_start, regn_end, regm_start, regm_end;
1449 u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end;
984 1450
985 DSSDBGF(); 1451 DSSDBGF();
986 1452
987 dsi.current_cinfo.fint = cinfo->fint; 1453 dsi->current_cinfo.use_sys_clk = cinfo->use_sys_clk;
988 dsi.current_cinfo.clkin4ddr = cinfo->clkin4ddr; 1454 dsi->current_cinfo.highfreq = cinfo->highfreq;
989 dsi.current_cinfo.dsi1_pll_fclk = cinfo->dsi1_pll_fclk;
990 dsi.current_cinfo.dsi2_pll_fclk = cinfo->dsi2_pll_fclk;
991 1455
992 dsi.current_cinfo.regn = cinfo->regn; 1456 dsi->current_cinfo.fint = cinfo->fint;
993 dsi.current_cinfo.regm = cinfo->regm; 1457 dsi->current_cinfo.clkin4ddr = cinfo->clkin4ddr;
994 dsi.current_cinfo.regm3 = cinfo->regm3; 1458 dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk =
995 dsi.current_cinfo.regm4 = cinfo->regm4; 1459 cinfo->dsi_pll_hsdiv_dispc_clk;
1460 dsi->current_cinfo.dsi_pll_hsdiv_dsi_clk =
1461 cinfo->dsi_pll_hsdiv_dsi_clk;
1462
1463 dsi->current_cinfo.regn = cinfo->regn;
1464 dsi->current_cinfo.regm = cinfo->regm;
1465 dsi->current_cinfo.regm_dispc = cinfo->regm_dispc;
1466 dsi->current_cinfo.regm_dsi = cinfo->regm_dsi;
996 1467
997 DSSDBG("DSI Fint %ld\n", cinfo->fint); 1468 DSSDBG("DSI Fint %ld\n", cinfo->fint);
998 1469
999 DSSDBG("clkin (%s) rate %ld, highfreq %d\n", 1470 DSSDBG("clkin (%s) rate %ld, highfreq %d\n",
1000 cinfo->use_dss2_fck ? "dss2_fck" : "pclkfree", 1471 cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree",
1001 cinfo->clkin, 1472 cinfo->clkin,
1002 cinfo->highfreq); 1473 cinfo->highfreq);
1003 1474
@@ -1014,63 +1485,79 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo)
1014 1485
1015 DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4); 1486 DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4);
1016 1487
1017 DSSDBG("regm3 = %d, dsi1_pll_fclk = %lu\n", 1488 DSSDBG("regm_dispc = %d, %s (%s) = %lu\n", cinfo->regm_dispc,
1018 cinfo->regm3, cinfo->dsi1_pll_fclk); 1489 dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
1019 DSSDBG("regm4 = %d, dsi2_pll_fclk = %lu\n", 1490 dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
1020 cinfo->regm4, cinfo->dsi2_pll_fclk); 1491 cinfo->dsi_pll_hsdiv_dispc_clk);
1021 1492 DSSDBG("regm_dsi = %d, %s (%s) = %lu\n", cinfo->regm_dsi,
1022 REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */ 1493 dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
1023 1494 dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
1024 l = dsi_read_reg(DSI_PLL_CONFIGURATION1); 1495 cinfo->dsi_pll_hsdiv_dsi_clk);
1496
1497 dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGN, &regn_start, &regn_end);
1498 dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM, &regm_start, &regm_end);
1499 dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DISPC, &regm_dispc_start,
1500 &regm_dispc_end);
1501 dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DSI, &regm_dsi_start,
1502 &regm_dsi_end);
1503
1504 /* DSI_PLL_AUTOMODE = manual */
1505 REG_FLD_MOD(dsidev, DSI_PLL_CONTROL, 0, 0, 0);
1506
1507 l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION1);
1025 l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */ 1508 l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */
1026 l = FLD_MOD(l, cinfo->regn - 1, 7, 1); /* DSI_PLL_REGN */ 1509 /* DSI_PLL_REGN */
1027 l = FLD_MOD(l, cinfo->regm, 18, 8); /* DSI_PLL_REGM */ 1510 l = FLD_MOD(l, cinfo->regn - 1, regn_start, regn_end);
1028 l = FLD_MOD(l, cinfo->regm3 > 0 ? cinfo->regm3 - 1 : 0, 1511 /* DSI_PLL_REGM */
1029 22, 19); /* DSI_CLOCK_DIV */ 1512 l = FLD_MOD(l, cinfo->regm, regm_start, regm_end);
1030 l = FLD_MOD(l, cinfo->regm4 > 0 ? cinfo->regm4 - 1 : 0, 1513 /* DSI_CLOCK_DIV */
1031 26, 23); /* DSIPROTO_CLOCK_DIV */ 1514 l = FLD_MOD(l, cinfo->regm_dispc > 0 ? cinfo->regm_dispc - 1 : 0,
1032 dsi_write_reg(DSI_PLL_CONFIGURATION1, l); 1515 regm_dispc_start, regm_dispc_end);
1033 1516 /* DSIPROTO_CLOCK_DIV */
1034 BUG_ON(cinfo->fint < 750000 || cinfo->fint > 2100000); 1517 l = FLD_MOD(l, cinfo->regm_dsi > 0 ? cinfo->regm_dsi - 1 : 0,
1035 if (cinfo->fint < 1000000) 1518 regm_dsi_start, regm_dsi_end);
1036 f = 0x3; 1519 dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION1, l);
1037 else if (cinfo->fint < 1250000) 1520
1038 f = 0x4; 1521 BUG_ON(cinfo->fint < dsi->fint_min || cinfo->fint > dsi->fint_max);
1039 else if (cinfo->fint < 1500000) 1522
1040 f = 0x5; 1523 if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) {
1041 else if (cinfo->fint < 1750000) 1524 f = cinfo->fint < 1000000 ? 0x3 :
1042 f = 0x6; 1525 cinfo->fint < 1250000 ? 0x4 :
1043 else 1526 cinfo->fint < 1500000 ? 0x5 :
1044 f = 0x7; 1527 cinfo->fint < 1750000 ? 0x6 :
1528 0x7;
1529 }
1045 1530
1046 l = dsi_read_reg(DSI_PLL_CONFIGURATION2); 1531 l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);
1047 l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ 1532
1048 l = FLD_MOD(l, cinfo->use_dss2_fck ? 0 : 1, 1533 if (dss_has_feature(FEAT_DSI_PLL_FREQSEL))
1534 l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */
1535 l = FLD_MOD(l, cinfo->use_sys_clk ? 0 : 1,
1049 11, 11); /* DSI_PLL_CLKSEL */ 1536 11, 11); /* DSI_PLL_CLKSEL */
1050 l = FLD_MOD(l, cinfo->highfreq, 1537 l = FLD_MOD(l, cinfo->highfreq,
1051 12, 12); /* DSI_PLL_HIGHFREQ */ 1538 12, 12); /* DSI_PLL_HIGHFREQ */
1052 l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */ 1539 l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
1053 l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */ 1540 l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */
1054 l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */ 1541 l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */
1055 dsi_write_reg(DSI_PLL_CONFIGURATION2, l); 1542 dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l);
1056 1543
1057 REG_FLD_MOD(DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */ 1544 REG_FLD_MOD(dsidev, DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */
1058 1545
1059 if (wait_for_bit_change(DSI_PLL_GO, 0, 0) != 0) { 1546 if (wait_for_bit_change(dsidev, DSI_PLL_GO, 0, 0) != 0) {
1060 DSSERR("dsi pll go bit not going down.\n"); 1547 DSSERR("dsi pll go bit not going down.\n");
1061 r = -EIO; 1548 r = -EIO;
1062 goto err; 1549 goto err;
1063 } 1550 }
1064 1551
1065 if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) { 1552 if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1) {
1066 DSSERR("cannot lock PLL\n"); 1553 DSSERR("cannot lock PLL\n");
1067 r = -EIO; 1554 r = -EIO;
1068 goto err; 1555 goto err;
1069 } 1556 }
1070 1557
1071 dsi.pll_locked = 1; 1558 dsi->pll_locked = 1;
1072 1559
1073 l = dsi_read_reg(DSI_PLL_CONFIGURATION2); 1560 l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);
1074 l = FLD_MOD(l, 0, 0, 0); /* DSI_PLL_IDLE */ 1561 l = FLD_MOD(l, 0, 0, 0); /* DSI_PLL_IDLE */
1075 l = FLD_MOD(l, 0, 5, 5); /* DSI_PLL_PLLLPMODE */ 1562 l = FLD_MOD(l, 0, 5, 5); /* DSI_PLL_PLLLPMODE */
1076 l = FLD_MOD(l, 0, 6, 6); /* DSI_PLL_LOWCURRSTBY */ 1563 l = FLD_MOD(l, 0, 6, 6); /* DSI_PLL_LOWCURRSTBY */
@@ -1085,32 +1572,53 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo)
1085 l = FLD_MOD(l, 1, 18, 18); /* DSI_PROTO_CLOCK_EN */ 1572 l = FLD_MOD(l, 1, 18, 18); /* DSI_PROTO_CLOCK_EN */
1086 l = FLD_MOD(l, 0, 19, 19); /* DSI_PROTO_CLOCK_PWDN */ 1573 l = FLD_MOD(l, 0, 19, 19); /* DSI_PROTO_CLOCK_PWDN */
1087 l = FLD_MOD(l, 0, 20, 20); /* DSI_HSDIVBYPASS */ 1574 l = FLD_MOD(l, 0, 20, 20); /* DSI_HSDIVBYPASS */
1088 dsi_write_reg(DSI_PLL_CONFIGURATION2, l); 1575 dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l);
1089 1576
1090 DSSDBG("PLL config done\n"); 1577 DSSDBG("PLL config done\n");
1091err: 1578err:
1092 return r; 1579 return r;
1093} 1580}
1094 1581
1095int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk, 1582int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
1096 bool enable_hsdiv) 1583 bool enable_hsdiv)
1097{ 1584{
1585 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1098 int r = 0; 1586 int r = 0;
1099 enum dsi_pll_power_state pwstate; 1587 enum dsi_pll_power_state pwstate;
1100 1588
1101 DSSDBG("PLL init\n"); 1589 DSSDBG("PLL init\n");
1102 1590
1591 if (dsi->vdds_dsi_reg == NULL) {
1592 struct regulator *vdds_dsi;
1593
1594 vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi");
1595
1596 if (IS_ERR(vdds_dsi)) {
1597 DSSERR("can't get VDDS_DSI regulator\n");
1598 return PTR_ERR(vdds_dsi);
1599 }
1600
1601 dsi->vdds_dsi_reg = vdds_dsi;
1602 }
1603
1103 enable_clocks(1); 1604 enable_clocks(1);
1104 dsi_enable_pll_clock(1); 1605 dsi_enable_pll_clock(dsidev, 1);
1606 /*
1607 * Note: SCP CLK is not required on OMAP3, but it is required on OMAP4.
1608 */
1609 dsi_enable_scp_clk(dsidev);
1105 1610
1106 r = regulator_enable(dsi.vdds_dsi_reg); 1611 if (!dsi->vdds_dsi_enabled) {
1107 if (r) 1612 r = regulator_enable(dsi->vdds_dsi_reg);
1108 goto err0; 1613 if (r)
1614 goto err0;
1615 dsi->vdds_dsi_enabled = true;
1616 }
1109 1617
1110 /* XXX PLL does not come out of reset without this... */ 1618 /* XXX PLL does not come out of reset without this... */
1111 dispc_pck_free_enable(1); 1619 dispc_pck_free_enable(1);
1112 1620
1113 if (wait_for_bit_change(DSI_PLL_STATUS, 0, 1) != 1) { 1621 if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 0, 1) != 1) {
1114 DSSERR("PLL not coming out of reset.\n"); 1622 DSSERR("PLL not coming out of reset.\n");
1115 r = -ENODEV; 1623 r = -ENODEV;
1116 dispc_pck_free_enable(0); 1624 dispc_pck_free_enable(0);
@@ -1130,7 +1638,7 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk,
1130 else 1638 else
1131 pwstate = DSI_PLL_POWER_OFF; 1639 pwstate = DSI_PLL_POWER_OFF;
1132 1640
1133 r = dsi_pll_power(pwstate); 1641 r = dsi_pll_power(dsidev, pwstate);
1134 1642
1135 if (r) 1643 if (r)
1136 goto err1; 1644 goto err1;
@@ -1139,92 +1647,121 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk,
1139 1647
1140 return 0; 1648 return 0;
1141err1: 1649err1:
1142 regulator_disable(dsi.vdds_dsi_reg); 1650 if (dsi->vdds_dsi_enabled) {
1651 regulator_disable(dsi->vdds_dsi_reg);
1652 dsi->vdds_dsi_enabled = false;
1653 }
1143err0: 1654err0:
1655 dsi_disable_scp_clk(dsidev);
1144 enable_clocks(0); 1656 enable_clocks(0);
1145 dsi_enable_pll_clock(0); 1657 dsi_enable_pll_clock(dsidev, 0);
1146 return r; 1658 return r;
1147} 1659}
1148 1660
1149void dsi_pll_uninit(void) 1661void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes)
1150{ 1662{
1663 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1664
1665 dsi->pll_locked = 0;
1666 dsi_pll_power(dsidev, DSI_PLL_POWER_OFF);
1667 if (disconnect_lanes) {
1668 WARN_ON(!dsi->vdds_dsi_enabled);
1669 regulator_disable(dsi->vdds_dsi_reg);
1670 dsi->vdds_dsi_enabled = false;
1671 }
1672
1673 dsi_disable_scp_clk(dsidev);
1151 enable_clocks(0); 1674 enable_clocks(0);
1152 dsi_enable_pll_clock(0); 1675 dsi_enable_pll_clock(dsidev, 0);
1153 1676
1154 dsi.pll_locked = 0;
1155 dsi_pll_power(DSI_PLL_POWER_OFF);
1156 regulator_disable(dsi.vdds_dsi_reg);
1157 DSSDBG("PLL uninit done\n"); 1677 DSSDBG("PLL uninit done\n");
1158} 1678}
1159 1679
1160void dsi_dump_clocks(struct seq_file *s) 1680static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
1681 struct seq_file *s)
1161{ 1682{
1162 int clksel; 1683 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1163 struct dsi_clock_info *cinfo = &dsi.current_cinfo; 1684 struct dsi_clock_info *cinfo = &dsi->current_cinfo;
1685 enum omap_dss_clk_source dispc_clk_src, dsi_clk_src;
1686 int dsi_module = dsi_get_dsidev_id(dsidev);
1164 1687
1165 enable_clocks(1); 1688 dispc_clk_src = dss_get_dispc_clk_source();
1689 dsi_clk_src = dss_get_dsi_clk_source(dsi_module);
1166 1690
1167 clksel = REG_GET(DSI_PLL_CONFIGURATION2, 11, 11); 1691 enable_clocks(1);
1168 1692
1169 seq_printf(s, "- DSI PLL -\n"); 1693 seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1);
1170 1694
1171 seq_printf(s, "dsi pll source = %s\n", 1695 seq_printf(s, "dsi pll source = %s\n",
1172 clksel == 0 ? 1696 cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree");
1173 "dss2_alwon_fclk" : "pclkfree");
1174 1697
1175 seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn); 1698 seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn);
1176 1699
1177 seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n", 1700 seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n",
1178 cinfo->clkin4ddr, cinfo->regm); 1701 cinfo->clkin4ddr, cinfo->regm);
1179 1702
1180 seq_printf(s, "dsi1_pll_fck\t%-16luregm3 %u\t(%s)\n", 1703 seq_printf(s, "%s (%s)\t%-16luregm_dispc %u\t(%s)\n",
1181 cinfo->dsi1_pll_fclk, 1704 dss_get_generic_clk_source_name(dispc_clk_src),
1182 cinfo->regm3, 1705 dss_feat_get_clk_source_name(dispc_clk_src),
1183 dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ? 1706 cinfo->dsi_pll_hsdiv_dispc_clk,
1707 cinfo->regm_dispc,
1708 dispc_clk_src == OMAP_DSS_CLK_SRC_FCK ?
1184 "off" : "on"); 1709 "off" : "on");
1185 1710
1186 seq_printf(s, "dsi2_pll_fck\t%-16luregm4 %u\t(%s)\n", 1711 seq_printf(s, "%s (%s)\t%-16luregm_dsi %u\t(%s)\n",
1187 cinfo->dsi2_pll_fclk, 1712 dss_get_generic_clk_source_name(dsi_clk_src),
1188 cinfo->regm4, 1713 dss_feat_get_clk_source_name(dsi_clk_src),
1189 dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ? 1714 cinfo->dsi_pll_hsdiv_dsi_clk,
1715 cinfo->regm_dsi,
1716 dsi_clk_src == OMAP_DSS_CLK_SRC_FCK ?
1190 "off" : "on"); 1717 "off" : "on");
1191 1718
1192 seq_printf(s, "- DSI -\n"); 1719 seq_printf(s, "- DSI%d -\n", dsi_module + 1);
1193 1720
1194 seq_printf(s, "dsi fclk source = %s\n", 1721 seq_printf(s, "dsi fclk source = %s (%s)\n",
1195 dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ? 1722 dss_get_generic_clk_source_name(dsi_clk_src),
1196 "dss1_alwon_fclk" : "dsi2_pll_fclk"); 1723 dss_feat_get_clk_source_name(dsi_clk_src));
1197 1724
1198 seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate()); 1725 seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate(dsidev));
1199 1726
1200 seq_printf(s, "DDR_CLK\t\t%lu\n", 1727 seq_printf(s, "DDR_CLK\t\t%lu\n",
1201 cinfo->clkin4ddr / 4); 1728 cinfo->clkin4ddr / 4);
1202 1729
1203 seq_printf(s, "TxByteClkHS\t%lu\n", dsi_get_txbyteclkhs()); 1730 seq_printf(s, "TxByteClkHS\t%lu\n", dsi_get_txbyteclkhs(dsidev));
1204 1731
1205 seq_printf(s, "LP_CLK\t\t%lu\n", cinfo->lp_clk); 1732 seq_printf(s, "LP_CLK\t\t%lu\n", cinfo->lp_clk);
1206 1733
1207 seq_printf(s, "VP_CLK\t\t%lu\n"
1208 "VP_PCLK\t\t%lu\n",
1209 dispc_lclk_rate(),
1210 dispc_pclk_rate());
1211
1212 enable_clocks(0); 1734 enable_clocks(0);
1213} 1735}
1214 1736
1737void dsi_dump_clocks(struct seq_file *s)
1738{
1739 struct platform_device *dsidev;
1740 int i;
1741
1742 for (i = 0; i < MAX_NUM_DSI; i++) {
1743 dsidev = dsi_get_dsidev_from_id(i);
1744 if (dsidev)
1745 dsi_dump_dsidev_clocks(dsidev, s);
1746 }
1747}
1748
1215#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 1749#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
1216void dsi_dump_irqs(struct seq_file *s) 1750static void dsi_dump_dsidev_irqs(struct platform_device *dsidev,
1751 struct seq_file *s)
1217{ 1752{
1753 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1218 unsigned long flags; 1754 unsigned long flags;
1219 struct dsi_irq_stats stats; 1755 struct dsi_irq_stats stats;
1756 int dsi_module = dsi_get_dsidev_id(dsidev);
1220 1757
1221 spin_lock_irqsave(&dsi.irq_stats_lock, flags); 1758 spin_lock_irqsave(&dsi->irq_stats_lock, flags);
1222 1759
1223 stats = dsi.irq_stats; 1760 stats = dsi->irq_stats;
1224 memset(&dsi.irq_stats, 0, sizeof(dsi.irq_stats)); 1761 memset(&dsi->irq_stats, 0, sizeof(dsi->irq_stats));
1225 dsi.irq_stats.last_reset = jiffies; 1762 dsi->irq_stats.last_reset = jiffies;
1226 1763
1227 spin_unlock_irqrestore(&dsi.irq_stats_lock, flags); 1764 spin_unlock_irqrestore(&dsi->irq_stats_lock, flags);
1228 1765
1229 seq_printf(s, "period %u ms\n", 1766 seq_printf(s, "period %u ms\n",
1230 jiffies_to_msecs(jiffies - stats.last_reset)); 1767 jiffies_to_msecs(jiffies - stats.last_reset));
@@ -1233,7 +1770,7 @@ void dsi_dump_irqs(struct seq_file *s)
1233#define PIS(x) \ 1770#define PIS(x) \
1234 seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]); 1771 seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]);
1235 1772
1236 seq_printf(s, "-- DSI interrupts --\n"); 1773 seq_printf(s, "-- DSI%d interrupts --\n", dsi_module + 1);
1237 PIS(VC0); 1774 PIS(VC0);
1238 PIS(VC1); 1775 PIS(VC1);
1239 PIS(VC2); 1776 PIS(VC2);
@@ -1299,13 +1836,45 @@ void dsi_dump_irqs(struct seq_file *s)
1299 PIS(ULPSACTIVENOT_ALL1); 1836 PIS(ULPSACTIVENOT_ALL1);
1300#undef PIS 1837#undef PIS
1301} 1838}
1839
1840static void dsi1_dump_irqs(struct seq_file *s)
1841{
1842 struct platform_device *dsidev = dsi_get_dsidev_from_id(0);
1843
1844 dsi_dump_dsidev_irqs(dsidev, s);
1845}
1846
1847static void dsi2_dump_irqs(struct seq_file *s)
1848{
1849 struct platform_device *dsidev = dsi_get_dsidev_from_id(1);
1850
1851 dsi_dump_dsidev_irqs(dsidev, s);
1852}
1853
1854void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir,
1855 const struct file_operations *debug_fops)
1856{
1857 struct platform_device *dsidev;
1858
1859 dsidev = dsi_get_dsidev_from_id(0);
1860 if (dsidev)
1861 debugfs_create_file("dsi1_irqs", S_IRUGO, debugfs_dir,
1862 &dsi1_dump_irqs, debug_fops);
1863
1864 dsidev = dsi_get_dsidev_from_id(1);
1865 if (dsidev)
1866 debugfs_create_file("dsi2_irqs", S_IRUGO, debugfs_dir,
1867 &dsi2_dump_irqs, debug_fops);
1868}
1302#endif 1869#endif
1303 1870
1304void dsi_dump_regs(struct seq_file *s) 1871static void dsi_dump_dsidev_regs(struct platform_device *dsidev,
1872 struct seq_file *s)
1305{ 1873{
1306#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r)) 1874#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsidev, r))
1307 1875
1308 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); 1876 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
1877 dsi_enable_scp_clk(dsidev);
1309 1878
1310 DUMPREG(DSI_REVISION); 1879 DUMPREG(DSI_REVISION);
1311 DUMPREG(DSI_SYSCONFIG); 1880 DUMPREG(DSI_SYSCONFIG);
@@ -1377,25 +1946,57 @@ void dsi_dump_regs(struct seq_file *s)
1377 DUMPREG(DSI_PLL_CONFIGURATION1); 1946 DUMPREG(DSI_PLL_CONFIGURATION1);
1378 DUMPREG(DSI_PLL_CONFIGURATION2); 1947 DUMPREG(DSI_PLL_CONFIGURATION2);
1379 1948
1380 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); 1949 dsi_disable_scp_clk(dsidev);
1950 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
1381#undef DUMPREG 1951#undef DUMPREG
1382} 1952}
1383 1953
1384enum dsi_complexio_power_state { 1954static void dsi1_dump_regs(struct seq_file *s)
1955{
1956 struct platform_device *dsidev = dsi_get_dsidev_from_id(0);
1957
1958 dsi_dump_dsidev_regs(dsidev, s);
1959}
1960
1961static void dsi2_dump_regs(struct seq_file *s)
1962{
1963 struct platform_device *dsidev = dsi_get_dsidev_from_id(1);
1964
1965 dsi_dump_dsidev_regs(dsidev, s);
1966}
1967
1968void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir,
1969 const struct file_operations *debug_fops)
1970{
1971 struct platform_device *dsidev;
1972
1973 dsidev = dsi_get_dsidev_from_id(0);
1974 if (dsidev)
1975 debugfs_create_file("dsi1_regs", S_IRUGO, debugfs_dir,
1976 &dsi1_dump_regs, debug_fops);
1977
1978 dsidev = dsi_get_dsidev_from_id(1);
1979 if (dsidev)
1980 debugfs_create_file("dsi2_regs", S_IRUGO, debugfs_dir,
1981 &dsi2_dump_regs, debug_fops);
1982}
1983enum dsi_cio_power_state {
1385 DSI_COMPLEXIO_POWER_OFF = 0x0, 1984 DSI_COMPLEXIO_POWER_OFF = 0x0,
1386 DSI_COMPLEXIO_POWER_ON = 0x1, 1985 DSI_COMPLEXIO_POWER_ON = 0x1,
1387 DSI_COMPLEXIO_POWER_ULPS = 0x2, 1986 DSI_COMPLEXIO_POWER_ULPS = 0x2,
1388}; 1987};
1389 1988
1390static int dsi_complexio_power(enum dsi_complexio_power_state state) 1989static int dsi_cio_power(struct platform_device *dsidev,
1990 enum dsi_cio_power_state state)
1391{ 1991{
1392 int t = 0; 1992 int t = 0;
1393 1993
1394 /* PWR_CMD */ 1994 /* PWR_CMD */
1395 REG_FLD_MOD(DSI_COMPLEXIO_CFG1, state, 28, 27); 1995 REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG1, state, 28, 27);
1396 1996
1397 /* PWR_STATUS */ 1997 /* PWR_STATUS */
1398 while (FLD_GET(dsi_read_reg(DSI_COMPLEXIO_CFG1), 26, 25) != state) { 1998 while (FLD_GET(dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1),
1999 26, 25) != state) {
1399 if (++t > 1000) { 2000 if (++t > 1000) {
1400 DSSERR("failed to set complexio power state to " 2001 DSSERR("failed to set complexio power state to "
1401 "%d\n", state); 2002 "%d\n", state);
@@ -1407,9 +2008,70 @@ static int dsi_complexio_power(enum dsi_complexio_power_state state)
1407 return 0; 2008 return 0;
1408} 2009}
1409 2010
1410static void dsi_complexio_config(struct omap_dss_device *dssdev) 2011/* Number of data lanes present on DSI interface */
2012static inline int dsi_get_num_data_lanes(struct platform_device *dsidev)
1411{ 2013{
2014 /* DSI on OMAP3 doesn't have register DSI_GNQ, set number
2015 * of data lanes as 2 by default */
2016 if (dss_has_feature(FEAT_DSI_GNQ))
2017 return REG_GET(dsidev, DSI_GNQ, 11, 9); /* NB_DATA_LANES */
2018 else
2019 return 2;
2020}
2021
2022/* Number of data lanes used by the dss device */
2023static inline int dsi_get_num_data_lanes_dssdev(struct omap_dss_device *dssdev)
2024{
2025 int num_data_lanes = 0;
2026
2027 if (dssdev->phy.dsi.data1_lane != 0)
2028 num_data_lanes++;
2029 if (dssdev->phy.dsi.data2_lane != 0)
2030 num_data_lanes++;
2031 if (dssdev->phy.dsi.data3_lane != 0)
2032 num_data_lanes++;
2033 if (dssdev->phy.dsi.data4_lane != 0)
2034 num_data_lanes++;
2035
2036 return num_data_lanes;
2037}
2038
2039static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
2040{
2041 int val;
2042
2043 /* line buffer on OMAP3 is 1024 x 24bits */
2044 /* XXX: for some reason using full buffer size causes
2045 * considerable TX slowdown with update sizes that fill the
2046 * whole buffer */
2047 if (!dss_has_feature(FEAT_DSI_GNQ))
2048 return 1023 * 3;
2049
2050 val = REG_GET(dsidev, DSI_GNQ, 14, 12); /* VP1_LINE_BUFFER_SIZE */
2051
2052 switch (val) {
2053 case 1:
2054 return 512 * 3; /* 512x24 bits */
2055 case 2:
2056 return 682 * 3; /* 682x24 bits */
2057 case 3:
2058 return 853 * 3; /* 853x24 bits */
2059 case 4:
2060 return 1024 * 3; /* 1024x24 bits */
2061 case 5:
2062 return 1194 * 3; /* 1194x24 bits */
2063 case 6:
2064 return 1365 * 3; /* 1365x24 bits */
2065 default:
2066 BUG();
2067 }
2068}
2069
2070static void dsi_set_lane_config(struct omap_dss_device *dssdev)
2071{
2072 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
1412 u32 r; 2073 u32 r;
2074 int num_data_lanes_dssdev = dsi_get_num_data_lanes_dssdev(dssdev);
1413 2075
1414 int clk_lane = dssdev->phy.dsi.clk_lane; 2076 int clk_lane = dssdev->phy.dsi.clk_lane;
1415 int data1_lane = dssdev->phy.dsi.data1_lane; 2077 int data1_lane = dssdev->phy.dsi.data1_lane;
@@ -1418,14 +2080,28 @@ static void dsi_complexio_config(struct omap_dss_device *dssdev)
1418 int data1_pol = dssdev->phy.dsi.data1_pol; 2080 int data1_pol = dssdev->phy.dsi.data1_pol;
1419 int data2_pol = dssdev->phy.dsi.data2_pol; 2081 int data2_pol = dssdev->phy.dsi.data2_pol;
1420 2082
1421 r = dsi_read_reg(DSI_COMPLEXIO_CFG1); 2083 r = dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1);
1422 r = FLD_MOD(r, clk_lane, 2, 0); 2084 r = FLD_MOD(r, clk_lane, 2, 0);
1423 r = FLD_MOD(r, clk_pol, 3, 3); 2085 r = FLD_MOD(r, clk_pol, 3, 3);
1424 r = FLD_MOD(r, data1_lane, 6, 4); 2086 r = FLD_MOD(r, data1_lane, 6, 4);
1425 r = FLD_MOD(r, data1_pol, 7, 7); 2087 r = FLD_MOD(r, data1_pol, 7, 7);
1426 r = FLD_MOD(r, data2_lane, 10, 8); 2088 r = FLD_MOD(r, data2_lane, 10, 8);
1427 r = FLD_MOD(r, data2_pol, 11, 11); 2089 r = FLD_MOD(r, data2_pol, 11, 11);
1428 dsi_write_reg(DSI_COMPLEXIO_CFG1, r); 2090 if (num_data_lanes_dssdev > 2) {
2091 int data3_lane = dssdev->phy.dsi.data3_lane;
2092 int data3_pol = dssdev->phy.dsi.data3_pol;
2093
2094 r = FLD_MOD(r, data3_lane, 14, 12);
2095 r = FLD_MOD(r, data3_pol, 15, 15);
2096 }
2097 if (num_data_lanes_dssdev > 3) {
2098 int data4_lane = dssdev->phy.dsi.data4_lane;
2099 int data4_pol = dssdev->phy.dsi.data4_pol;
2100
2101 r = FLD_MOD(r, data4_lane, 18, 16);
2102 r = FLD_MOD(r, data4_pol, 19, 19);
2103 }
2104 dsi_write_reg(dsidev, DSI_COMPLEXIO_CFG1, r);
1429 2105
1430 /* The configuration of the DSI complex I/O (number of data lanes, 2106 /* The configuration of the DSI complex I/O (number of data lanes,
1431 position, differential order) should not be changed while 2107 position, differential order) should not be changed while
@@ -1439,27 +2115,31 @@ static void dsi_complexio_config(struct omap_dss_device *dssdev)
1439 DSI complex I/O configuration is unknown. */ 2115 DSI complex I/O configuration is unknown. */
1440 2116
1441 /* 2117 /*
1442 REG_FLD_MOD(DSI_CTRL, 1, 0, 0); 2118 REG_FLD_MOD(dsidev, DSI_CTRL, 1, 0, 0);
1443 REG_FLD_MOD(DSI_CTRL, 0, 0, 0); 2119 REG_FLD_MOD(dsidev, DSI_CTRL, 0, 0, 0);
1444 REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); 2120 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20);
1445 REG_FLD_MOD(DSI_CTRL, 1, 0, 0); 2121 REG_FLD_MOD(dsidev, DSI_CTRL, 1, 0, 0);
1446 */ 2122 */
1447} 2123}
1448 2124
1449static inline unsigned ns2ddr(unsigned ns) 2125static inline unsigned ns2ddr(struct platform_device *dsidev, unsigned ns)
1450{ 2126{
2127 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2128
1451 /* convert time in ns to ddr ticks, rounding up */ 2129 /* convert time in ns to ddr ticks, rounding up */
1452 unsigned long ddr_clk = dsi.current_cinfo.clkin4ddr / 4; 2130 unsigned long ddr_clk = dsi->current_cinfo.clkin4ddr / 4;
1453 return (ns * (ddr_clk / 1000 / 1000) + 999) / 1000; 2131 return (ns * (ddr_clk / 1000 / 1000) + 999) / 1000;
1454} 2132}
1455 2133
1456static inline unsigned ddr2ns(unsigned ddr) 2134static inline unsigned ddr2ns(struct platform_device *dsidev, unsigned ddr)
1457{ 2135{
1458 unsigned long ddr_clk = dsi.current_cinfo.clkin4ddr / 4; 2136 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2137
2138 unsigned long ddr_clk = dsi->current_cinfo.clkin4ddr / 4;
1459 return ddr * 1000 * 1000 / (ddr_clk / 1000); 2139 return ddr * 1000 * 1000 / (ddr_clk / 1000);
1460} 2140}
1461 2141
1462static void dsi_complexio_timings(void) 2142static void dsi_cio_timings(struct platform_device *dsidev)
1463{ 2143{
1464 u32 r; 2144 u32 r;
1465 u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit; 2145 u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit;
@@ -1471,139 +2151,323 @@ static void dsi_complexio_timings(void)
1471 /* 1 * DDR_CLK = 2 * UI */ 2151 /* 1 * DDR_CLK = 2 * UI */
1472 2152
1473 /* min 40ns + 4*UI max 85ns + 6*UI */ 2153 /* min 40ns + 4*UI max 85ns + 6*UI */
1474 ths_prepare = ns2ddr(70) + 2; 2154 ths_prepare = ns2ddr(dsidev, 70) + 2;
1475 2155
1476 /* min 145ns + 10*UI */ 2156 /* min 145ns + 10*UI */
1477 ths_prepare_ths_zero = ns2ddr(175) + 2; 2157 ths_prepare_ths_zero = ns2ddr(dsidev, 175) + 2;
1478 2158
1479 /* min max(8*UI, 60ns+4*UI) */ 2159 /* min max(8*UI, 60ns+4*UI) */
1480 ths_trail = ns2ddr(60) + 5; 2160 ths_trail = ns2ddr(dsidev, 60) + 5;
1481 2161
1482 /* min 100ns */ 2162 /* min 100ns */
1483 ths_exit = ns2ddr(145); 2163 ths_exit = ns2ddr(dsidev, 145);
1484 2164
1485 /* tlpx min 50n */ 2165 /* tlpx min 50n */
1486 tlpx_half = ns2ddr(25); 2166 tlpx_half = ns2ddr(dsidev, 25);
1487 2167
1488 /* min 60ns */ 2168 /* min 60ns */
1489 tclk_trail = ns2ddr(60) + 2; 2169 tclk_trail = ns2ddr(dsidev, 60) + 2;
1490 2170
1491 /* min 38ns, max 95ns */ 2171 /* min 38ns, max 95ns */
1492 tclk_prepare = ns2ddr(65); 2172 tclk_prepare = ns2ddr(dsidev, 65);
1493 2173
1494 /* min tclk-prepare + tclk-zero = 300ns */ 2174 /* min tclk-prepare + tclk-zero = 300ns */
1495 tclk_zero = ns2ddr(260); 2175 tclk_zero = ns2ddr(dsidev, 260);
1496 2176
1497 DSSDBG("ths_prepare %u (%uns), ths_prepare_ths_zero %u (%uns)\n", 2177 DSSDBG("ths_prepare %u (%uns), ths_prepare_ths_zero %u (%uns)\n",
1498 ths_prepare, ddr2ns(ths_prepare), 2178 ths_prepare, ddr2ns(dsidev, ths_prepare),
1499 ths_prepare_ths_zero, ddr2ns(ths_prepare_ths_zero)); 2179 ths_prepare_ths_zero, ddr2ns(dsidev, ths_prepare_ths_zero));
1500 DSSDBG("ths_trail %u (%uns), ths_exit %u (%uns)\n", 2180 DSSDBG("ths_trail %u (%uns), ths_exit %u (%uns)\n",
1501 ths_trail, ddr2ns(ths_trail), 2181 ths_trail, ddr2ns(dsidev, ths_trail),
1502 ths_exit, ddr2ns(ths_exit)); 2182 ths_exit, ddr2ns(dsidev, ths_exit));
1503 2183
1504 DSSDBG("tlpx_half %u (%uns), tclk_trail %u (%uns), " 2184 DSSDBG("tlpx_half %u (%uns), tclk_trail %u (%uns), "
1505 "tclk_zero %u (%uns)\n", 2185 "tclk_zero %u (%uns)\n",
1506 tlpx_half, ddr2ns(tlpx_half), 2186 tlpx_half, ddr2ns(dsidev, tlpx_half),
1507 tclk_trail, ddr2ns(tclk_trail), 2187 tclk_trail, ddr2ns(dsidev, tclk_trail),
1508 tclk_zero, ddr2ns(tclk_zero)); 2188 tclk_zero, ddr2ns(dsidev, tclk_zero));
1509 DSSDBG("tclk_prepare %u (%uns)\n", 2189 DSSDBG("tclk_prepare %u (%uns)\n",
1510 tclk_prepare, ddr2ns(tclk_prepare)); 2190 tclk_prepare, ddr2ns(dsidev, tclk_prepare));
1511 2191
1512 /* program timings */ 2192 /* program timings */
1513 2193
1514 r = dsi_read_reg(DSI_DSIPHY_CFG0); 2194 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0);
1515 r = FLD_MOD(r, ths_prepare, 31, 24); 2195 r = FLD_MOD(r, ths_prepare, 31, 24);
1516 r = FLD_MOD(r, ths_prepare_ths_zero, 23, 16); 2196 r = FLD_MOD(r, ths_prepare_ths_zero, 23, 16);
1517 r = FLD_MOD(r, ths_trail, 15, 8); 2197 r = FLD_MOD(r, ths_trail, 15, 8);
1518 r = FLD_MOD(r, ths_exit, 7, 0); 2198 r = FLD_MOD(r, ths_exit, 7, 0);
1519 dsi_write_reg(DSI_DSIPHY_CFG0, r); 2199 dsi_write_reg(dsidev, DSI_DSIPHY_CFG0, r);
1520 2200
1521 r = dsi_read_reg(DSI_DSIPHY_CFG1); 2201 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1);
1522 r = FLD_MOD(r, tlpx_half, 22, 16); 2202 r = FLD_MOD(r, tlpx_half, 22, 16);
1523 r = FLD_MOD(r, tclk_trail, 15, 8); 2203 r = FLD_MOD(r, tclk_trail, 15, 8);
1524 r = FLD_MOD(r, tclk_zero, 7, 0); 2204 r = FLD_MOD(r, tclk_zero, 7, 0);
1525 dsi_write_reg(DSI_DSIPHY_CFG1, r); 2205 dsi_write_reg(dsidev, DSI_DSIPHY_CFG1, r);
1526 2206
1527 r = dsi_read_reg(DSI_DSIPHY_CFG2); 2207 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2);
1528 r = FLD_MOD(r, tclk_prepare, 7, 0); 2208 r = FLD_MOD(r, tclk_prepare, 7, 0);
1529 dsi_write_reg(DSI_DSIPHY_CFG2, r); 2209 dsi_write_reg(dsidev, DSI_DSIPHY_CFG2, r);
2210}
2211
2212static void dsi_cio_enable_lane_override(struct omap_dss_device *dssdev,
2213 enum dsi_lane lanes)
2214{
2215 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2216 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2217 int clk_lane = dssdev->phy.dsi.clk_lane;
2218 int data1_lane = dssdev->phy.dsi.data1_lane;
2219 int data2_lane = dssdev->phy.dsi.data2_lane;
2220 int data3_lane = dssdev->phy.dsi.data3_lane;
2221 int data4_lane = dssdev->phy.dsi.data4_lane;
2222 int clk_pol = dssdev->phy.dsi.clk_pol;
2223 int data1_pol = dssdev->phy.dsi.data1_pol;
2224 int data2_pol = dssdev->phy.dsi.data2_pol;
2225 int data3_pol = dssdev->phy.dsi.data3_pol;
2226 int data4_pol = dssdev->phy.dsi.data4_pol;
2227
2228 u32 l = 0;
2229 u8 lptxscp_start = dsi->num_data_lanes == 2 ? 22 : 26;
2230
2231 if (lanes & DSI_CLK_P)
2232 l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 0 : 1));
2233 if (lanes & DSI_CLK_N)
2234 l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 1 : 0));
2235
2236 if (lanes & DSI_DATA1_P)
2237 l |= 1 << ((data1_lane - 1) * 2 + (data1_pol ? 0 : 1));
2238 if (lanes & DSI_DATA1_N)
2239 l |= 1 << ((data1_lane - 1) * 2 + (data1_pol ? 1 : 0));
2240
2241 if (lanes & DSI_DATA2_P)
2242 l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 0 : 1));
2243 if (lanes & DSI_DATA2_N)
2244 l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 1 : 0));
2245
2246 if (lanes & DSI_DATA3_P)
2247 l |= 1 << ((data3_lane - 1) * 2 + (data3_pol ? 0 : 1));
2248 if (lanes & DSI_DATA3_N)
2249 l |= 1 << ((data3_lane - 1) * 2 + (data3_pol ? 1 : 0));
2250
2251 if (lanes & DSI_DATA4_P)
2252 l |= 1 << ((data4_lane - 1) * 2 + (data4_pol ? 0 : 1));
2253 if (lanes & DSI_DATA4_N)
2254 l |= 1 << ((data4_lane - 1) * 2 + (data4_pol ? 1 : 0));
2255 /*
2256 * Bits in REGLPTXSCPDAT4TO0DXDY:
2257 * 17: DY0 18: DX0
2258 * 19: DY1 20: DX1
2259 * 21: DY2 22: DX2
2260 * 23: DY3 24: DX3
2261 * 25: DY4 26: DX4
2262 */
2263
2264 /* Set the lane override configuration */
2265
2266 /* REGLPTXSCPDAT4TO0DXDY */
2267 REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, l, lptxscp_start, 17);
2268
2269 /* Enable lane override */
2270
2271 /* ENLPTXSCPDAT */
2272 REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 1, 27, 27);
1530} 2273}
1531 2274
2275static void dsi_cio_disable_lane_override(struct platform_device *dsidev)
2276{
2277 /* Disable lane override */
2278 REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 0, 27, 27); /* ENLPTXSCPDAT */
2279 /* Reset the lane override configuration */
2280 /* REGLPTXSCPDAT4TO0DXDY */
2281 REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 0, 22, 17);
2282}
1532 2283
1533static int dsi_complexio_init(struct omap_dss_device *dssdev) 2284static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev)
1534{ 2285{
1535 int r = 0; 2286 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2287 int t;
2288 int bits[3];
2289 bool in_use[3];
2290
2291 if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) {
2292 bits[0] = 28;
2293 bits[1] = 27;
2294 bits[2] = 26;
2295 } else {
2296 bits[0] = 24;
2297 bits[1] = 25;
2298 bits[2] = 26;
2299 }
2300
2301 in_use[0] = false;
2302 in_use[1] = false;
2303 in_use[2] = false;
2304
2305 if (dssdev->phy.dsi.clk_lane != 0)
2306 in_use[dssdev->phy.dsi.clk_lane - 1] = true;
2307 if (dssdev->phy.dsi.data1_lane != 0)
2308 in_use[dssdev->phy.dsi.data1_lane - 1] = true;
2309 if (dssdev->phy.dsi.data2_lane != 0)
2310 in_use[dssdev->phy.dsi.data2_lane - 1] = true;
2311
2312 t = 100000;
2313 while (true) {
2314 u32 l;
2315 int i;
2316 int ok;
2317
2318 l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
2319
2320 ok = 0;
2321 for (i = 0; i < 3; ++i) {
2322 if (!in_use[i] || (l & (1 << bits[i])))
2323 ok++;
2324 }
2325
2326 if (ok == 3)
2327 break;
2328
2329 if (--t == 0) {
2330 for (i = 0; i < 3; ++i) {
2331 if (!in_use[i] || (l & (1 << bits[i])))
2332 continue;
2333
2334 DSSERR("CIO TXCLKESC%d domain not coming " \
2335 "out of reset\n", i);
2336 }
2337 return -EIO;
2338 }
2339 }
2340
2341 return 0;
2342}
2343
2344static int dsi_cio_init(struct omap_dss_device *dssdev)
2345{
2346 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2347 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2348 int r;
2349 int num_data_lanes_dssdev = dsi_get_num_data_lanes_dssdev(dssdev);
2350 u32 l;
2351
2352 DSSDBGF();
1536 2353
1537 DSSDBG("dsi_complexio_init\n"); 2354 if (dsi->dsi_mux_pads)
2355 dsi->dsi_mux_pads(true);
1538 2356
1539 /* CIO_CLK_ICG, enable L3 clk to CIO */ 2357 dsi_enable_scp_clk(dsidev);
1540 REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14);
1541 2358
1542 /* A dummy read using the SCP interface to any DSIPHY register is 2359 /* A dummy read using the SCP interface to any DSIPHY register is
1543 * required after DSIPHY reset to complete the reset of the DSI complex 2360 * required after DSIPHY reset to complete the reset of the DSI complex
1544 * I/O. */ 2361 * I/O. */
1545 dsi_read_reg(DSI_DSIPHY_CFG5); 2362 dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
1546 2363
1547 if (wait_for_bit_change(DSI_DSIPHY_CFG5, 30, 1) != 1) { 2364 if (wait_for_bit_change(dsidev, DSI_DSIPHY_CFG5, 30, 1) != 1) {
1548 DSSERR("ComplexIO PHY not coming out of reset.\n"); 2365 DSSERR("CIO SCP Clock domain not coming out of reset.\n");
1549 r = -ENODEV; 2366 r = -EIO;
1550 goto err; 2367 goto err_scp_clk_dom;
1551 } 2368 }
1552 2369
1553 dsi_complexio_config(dssdev); 2370 dsi_set_lane_config(dssdev);
2371
2372 /* set TX STOP MODE timer to maximum for this operation */
2373 l = dsi_read_reg(dsidev, DSI_TIMING1);
2374 l = FLD_MOD(l, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
2375 l = FLD_MOD(l, 1, 14, 14); /* STOP_STATE_X16_IO */
2376 l = FLD_MOD(l, 1, 13, 13); /* STOP_STATE_X4_IO */
2377 l = FLD_MOD(l, 0x1fff, 12, 0); /* STOP_STATE_COUNTER_IO */
2378 dsi_write_reg(dsidev, DSI_TIMING1, l);
2379
2380 if (dsi->ulps_enabled) {
2381 u32 lane_mask = DSI_CLK_P | DSI_DATA1_P | DSI_DATA2_P;
2382
2383 DSSDBG("manual ulps exit\n");
2384
2385 /* ULPS is exited by Mark-1 state for 1ms, followed by
2386 * stop state. DSS HW cannot do this via the normal
2387 * ULPS exit sequence, as after reset the DSS HW thinks
2388 * that we are not in ULPS mode, and refuses to send the
2389 * sequence. So we need to send the ULPS exit sequence
2390 * manually.
2391 */
2392
2393 if (num_data_lanes_dssdev > 2)
2394 lane_mask |= DSI_DATA3_P;
2395
2396 if (num_data_lanes_dssdev > 3)
2397 lane_mask |= DSI_DATA4_P;
1554 2398
1555 r = dsi_complexio_power(DSI_COMPLEXIO_POWER_ON); 2399 dsi_cio_enable_lane_override(dssdev, lane_mask);
2400 }
1556 2401
2402 r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON);
1557 if (r) 2403 if (r)
1558 goto err; 2404 goto err_cio_pwr;
1559 2405
1560 if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 29, 1) != 1) { 2406 if (wait_for_bit_change(dsidev, DSI_COMPLEXIO_CFG1, 29, 1) != 1) {
1561 DSSERR("ComplexIO not coming out of reset.\n"); 2407 DSSERR("CIO PWR clock domain not coming out of reset.\n");
1562 r = -ENODEV; 2408 r = -ENODEV;
1563 goto err; 2409 goto err_cio_pwr_dom;
1564 } 2410 }
1565 2411
1566 if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) { 2412 dsi_if_enable(dsidev, true);
1567 DSSERR("ComplexIO LDO power down.\n"); 2413 dsi_if_enable(dsidev, false);
1568 r = -ENODEV; 2414 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */
1569 goto err; 2415
2416 r = dsi_cio_wait_tx_clk_esc_reset(dssdev);
2417 if (r)
2418 goto err_tx_clk_esc_rst;
2419
2420 if (dsi->ulps_enabled) {
2421 /* Keep Mark-1 state for 1ms (as per DSI spec) */
2422 ktime_t wait = ns_to_ktime(1000 * 1000);
2423 set_current_state(TASK_UNINTERRUPTIBLE);
2424 schedule_hrtimeout(&wait, HRTIMER_MODE_REL);
2425
2426 /* Disable the override. The lanes should be set to Mark-11
2427 * state by the HW */
2428 dsi_cio_disable_lane_override(dsidev);
1570 } 2429 }
1571 2430
1572 dsi_complexio_timings(); 2431 /* FORCE_TX_STOP_MODE_IO */
2432 REG_FLD_MOD(dsidev, DSI_TIMING1, 0, 15, 15);
1573 2433
1574 /* 2434 dsi_cio_timings(dsidev);
1575 The configuration of the DSI complex I/O (number of data lanes, 2435
1576 position, differential order) should not be changed while 2436 dsi->ulps_enabled = false;
1577 DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. For the
1578 hardware to recognize a new configuration of the complex I/O (done
1579 in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to follow
1580 this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1, next
1581 reset the DSS.DSI_CTRL[0] IF_EN to 0, then set DSS.DSI_CLK_CTRL[20]
1582 LP_CLK_ENABLE to 1, and finally, set again the DSS.DSI_CTRL[0] IF_EN
1583 bit to 1. If the sequence is not followed, the DSi complex I/O
1584 configuration is undetermined.
1585 */
1586 dsi_if_enable(1);
1587 dsi_if_enable(0);
1588 REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */
1589 dsi_if_enable(1);
1590 dsi_if_enable(0);
1591 2437
1592 DSSDBG("CIO init done\n"); 2438 DSSDBG("CIO init done\n");
1593err: 2439
2440 return 0;
2441
2442err_tx_clk_esc_rst:
2443 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 20, 20); /* LP_CLK_ENABLE */
2444err_cio_pwr_dom:
2445 dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF);
2446err_cio_pwr:
2447 if (dsi->ulps_enabled)
2448 dsi_cio_disable_lane_override(dsidev);
2449err_scp_clk_dom:
2450 dsi_disable_scp_clk(dsidev);
2451 if (dsi->dsi_mux_pads)
2452 dsi->dsi_mux_pads(false);
1594 return r; 2453 return r;
1595} 2454}
1596 2455
1597static void dsi_complexio_uninit(void) 2456static void dsi_cio_uninit(struct platform_device *dsidev)
1598{ 2457{
1599 dsi_complexio_power(DSI_COMPLEXIO_POWER_OFF); 2458 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2459
2460 dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF);
2461 dsi_disable_scp_clk(dsidev);
2462 if (dsi->dsi_mux_pads)
2463 dsi->dsi_mux_pads(false);
1600} 2464}
1601 2465
1602static int _dsi_wait_reset(void) 2466static int _dsi_wait_reset(struct platform_device *dsidev)
1603{ 2467{
1604 int t = 0; 2468 int t = 0;
1605 2469
1606 while (REG_GET(DSI_SYSSTATUS, 0, 0) == 0) { 2470 while (REG_GET(dsidev, DSI_SYSSTATUS, 0, 0) == 0) {
1607 if (++t > 5) { 2471 if (++t > 5) {
1608 DSSERR("soft reset failed\n"); 2472 DSSERR("soft reset failed\n");
1609 return -ENODEV; 2473 return -ENODEV;
@@ -1614,42 +2478,30 @@ static int _dsi_wait_reset(void)
1614 return 0; 2478 return 0;
1615} 2479}
1616 2480
1617static int _dsi_reset(void) 2481static int _dsi_reset(struct platform_device *dsidev)
1618{ 2482{
1619 /* Soft reset */ 2483 /* Soft reset */
1620 REG_FLD_MOD(DSI_SYSCONFIG, 1, 1, 1); 2484 REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 1, 1);
1621 return _dsi_wait_reset(); 2485 return _dsi_wait_reset(dsidev);
1622}
1623
1624static void dsi_reset_tx_fifo(int channel)
1625{
1626 u32 mask;
1627 u32 l;
1628
1629 /* set fifosize of the channel to 0, then return the old size */
1630 l = dsi_read_reg(DSI_TX_FIFO_VC_SIZE);
1631
1632 mask = FLD_MASK((8 * channel) + 7, (8 * channel) + 4);
1633 dsi_write_reg(DSI_TX_FIFO_VC_SIZE, l & ~mask);
1634
1635 dsi_write_reg(DSI_TX_FIFO_VC_SIZE, l);
1636} 2486}
1637 2487
1638static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2, 2488static void dsi_config_tx_fifo(struct platform_device *dsidev,
2489 enum fifo_size size1, enum fifo_size size2,
1639 enum fifo_size size3, enum fifo_size size4) 2490 enum fifo_size size3, enum fifo_size size4)
1640{ 2491{
2492 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1641 u32 r = 0; 2493 u32 r = 0;
1642 int add = 0; 2494 int add = 0;
1643 int i; 2495 int i;
1644 2496
1645 dsi.vc[0].fifo_size = size1; 2497 dsi->vc[0].fifo_size = size1;
1646 dsi.vc[1].fifo_size = size2; 2498 dsi->vc[1].fifo_size = size2;
1647 dsi.vc[2].fifo_size = size3; 2499 dsi->vc[2].fifo_size = size3;
1648 dsi.vc[3].fifo_size = size4; 2500 dsi->vc[3].fifo_size = size4;
1649 2501
1650 for (i = 0; i < 4; i++) { 2502 for (i = 0; i < 4; i++) {
1651 u8 v; 2503 u8 v;
1652 int size = dsi.vc[i].fifo_size; 2504 int size = dsi->vc[i].fifo_size;
1653 2505
1654 if (add + size > 4) { 2506 if (add + size > 4) {
1655 DSSERR("Illegal FIFO configuration\n"); 2507 DSSERR("Illegal FIFO configuration\n");
@@ -1662,24 +2514,26 @@ static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2,
1662 add += size; 2514 add += size;
1663 } 2515 }
1664 2516
1665 dsi_write_reg(DSI_TX_FIFO_VC_SIZE, r); 2517 dsi_write_reg(dsidev, DSI_TX_FIFO_VC_SIZE, r);
1666} 2518}
1667 2519
1668static void dsi_config_rx_fifo(enum fifo_size size1, enum fifo_size size2, 2520static void dsi_config_rx_fifo(struct platform_device *dsidev,
2521 enum fifo_size size1, enum fifo_size size2,
1669 enum fifo_size size3, enum fifo_size size4) 2522 enum fifo_size size3, enum fifo_size size4)
1670{ 2523{
2524 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1671 u32 r = 0; 2525 u32 r = 0;
1672 int add = 0; 2526 int add = 0;
1673 int i; 2527 int i;
1674 2528
1675 dsi.vc[0].fifo_size = size1; 2529 dsi->vc[0].fifo_size = size1;
1676 dsi.vc[1].fifo_size = size2; 2530 dsi->vc[1].fifo_size = size2;
1677 dsi.vc[2].fifo_size = size3; 2531 dsi->vc[2].fifo_size = size3;
1678 dsi.vc[3].fifo_size = size4; 2532 dsi->vc[3].fifo_size = size4;
1679 2533
1680 for (i = 0; i < 4; i++) { 2534 for (i = 0; i < 4; i++) {
1681 u8 v; 2535 u8 v;
1682 int size = dsi.vc[i].fifo_size; 2536 int size = dsi->vc[i].fifo_size;
1683 2537
1684 if (add + size > 4) { 2538 if (add + size > 4) {
1685 DSSERR("Illegal FIFO configuration\n"); 2539 DSSERR("Illegal FIFO configuration\n");
@@ -1692,18 +2546,18 @@ static void dsi_config_rx_fifo(enum fifo_size size1, enum fifo_size size2,
1692 add += size; 2546 add += size;
1693 } 2547 }
1694 2548
1695 dsi_write_reg(DSI_RX_FIFO_VC_SIZE, r); 2549 dsi_write_reg(dsidev, DSI_RX_FIFO_VC_SIZE, r);
1696} 2550}
1697 2551
1698static int dsi_force_tx_stop_mode_io(void) 2552static int dsi_force_tx_stop_mode_io(struct platform_device *dsidev)
1699{ 2553{
1700 u32 r; 2554 u32 r;
1701 2555
1702 r = dsi_read_reg(DSI_TIMING1); 2556 r = dsi_read_reg(dsidev, DSI_TIMING1);
1703 r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */ 2557 r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
1704 dsi_write_reg(DSI_TIMING1, r); 2558 dsi_write_reg(dsidev, DSI_TIMING1, r);
1705 2559
1706 if (wait_for_bit_change(DSI_TIMING1, 15, 0) != 0) { 2560 if (wait_for_bit_change(dsidev, DSI_TIMING1, 15, 0) != 0) {
1707 DSSERR("TX_STOP bit not going down\n"); 2561 DSSERR("TX_STOP bit not going down\n");
1708 return -EIO; 2562 return -EIO;
1709 } 2563 }
@@ -1711,16 +2565,135 @@ static int dsi_force_tx_stop_mode_io(void)
1711 return 0; 2565 return 0;
1712} 2566}
1713 2567
1714static int dsi_vc_enable(int channel, bool enable) 2568static bool dsi_vc_is_enabled(struct platform_device *dsidev, int channel)
2569{
2570 return REG_GET(dsidev, DSI_VC_CTRL(channel), 0, 0);
2571}
2572
2573static void dsi_packet_sent_handler_vp(void *data, u32 mask)
2574{
2575 struct dsi_packet_sent_handler_data *vp_data =
2576 (struct dsi_packet_sent_handler_data *) data;
2577 struct dsi_data *dsi = dsi_get_dsidrv_data(vp_data->dsidev);
2578 const int channel = dsi->update_channel;
2579 u8 bit = dsi->te_enabled ? 30 : 31;
2580
2581 if (REG_GET(vp_data->dsidev, DSI_VC_TE(channel), bit, bit) == 0)
2582 complete(vp_data->completion);
2583}
2584
2585static int dsi_sync_vc_vp(struct platform_device *dsidev, int channel)
2586{
2587 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2588 DECLARE_COMPLETION_ONSTACK(completion);
2589 struct dsi_packet_sent_handler_data vp_data = { dsidev, &completion };
2590 int r = 0;
2591 u8 bit;
2592
2593 bit = dsi->te_enabled ? 30 : 31;
2594
2595 r = dsi_register_isr_vc(dsidev, channel, dsi_packet_sent_handler_vp,
2596 &vp_data, DSI_VC_IRQ_PACKET_SENT);
2597 if (r)
2598 goto err0;
2599
2600 /* Wait for completion only if TE_EN/TE_START is still set */
2601 if (REG_GET(dsidev, DSI_VC_TE(channel), bit, bit)) {
2602 if (wait_for_completion_timeout(&completion,
2603 msecs_to_jiffies(10)) == 0) {
2604 DSSERR("Failed to complete previous frame transfer\n");
2605 r = -EIO;
2606 goto err1;
2607 }
2608 }
2609
2610 dsi_unregister_isr_vc(dsidev, channel, dsi_packet_sent_handler_vp,
2611 &vp_data, DSI_VC_IRQ_PACKET_SENT);
2612
2613 return 0;
2614err1:
2615 dsi_unregister_isr_vc(dsidev, channel, dsi_packet_sent_handler_vp,
2616 &vp_data, DSI_VC_IRQ_PACKET_SENT);
2617err0:
2618 return r;
2619}
2620
2621static void dsi_packet_sent_handler_l4(void *data, u32 mask)
2622{
2623 struct dsi_packet_sent_handler_data *l4_data =
2624 (struct dsi_packet_sent_handler_data *) data;
2625 struct dsi_data *dsi = dsi_get_dsidrv_data(l4_data->dsidev);
2626 const int channel = dsi->update_channel;
2627
2628 if (REG_GET(l4_data->dsidev, DSI_VC_CTRL(channel), 5, 5) == 0)
2629 complete(l4_data->completion);
2630}
2631
2632static int dsi_sync_vc_l4(struct platform_device *dsidev, int channel)
2633{
2634 DECLARE_COMPLETION_ONSTACK(completion);
2635 struct dsi_packet_sent_handler_data l4_data = { dsidev, &completion };
2636 int r = 0;
2637
2638 r = dsi_register_isr_vc(dsidev, channel, dsi_packet_sent_handler_l4,
2639 &l4_data, DSI_VC_IRQ_PACKET_SENT);
2640 if (r)
2641 goto err0;
2642
2643 /* Wait for completion only if TX_FIFO_NOT_EMPTY is still set */
2644 if (REG_GET(dsidev, DSI_VC_CTRL(channel), 5, 5)) {
2645 if (wait_for_completion_timeout(&completion,
2646 msecs_to_jiffies(10)) == 0) {
2647 DSSERR("Failed to complete previous l4 transfer\n");
2648 r = -EIO;
2649 goto err1;
2650 }
2651 }
2652
2653 dsi_unregister_isr_vc(dsidev, channel, dsi_packet_sent_handler_l4,
2654 &l4_data, DSI_VC_IRQ_PACKET_SENT);
2655
2656 return 0;
2657err1:
2658 dsi_unregister_isr_vc(dsidev, channel, dsi_packet_sent_handler_l4,
2659 &l4_data, DSI_VC_IRQ_PACKET_SENT);
2660err0:
2661 return r;
2662}
2663
2664static int dsi_sync_vc(struct platform_device *dsidev, int channel)
2665{
2666 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2667
2668 WARN_ON(!dsi_bus_is_locked(dsidev));
2669
2670 WARN_ON(in_interrupt());
2671
2672 if (!dsi_vc_is_enabled(dsidev, channel))
2673 return 0;
2674
2675 switch (dsi->vc[channel].mode) {
2676 case DSI_VC_MODE_VP:
2677 return dsi_sync_vc_vp(dsidev, channel);
2678 case DSI_VC_MODE_L4:
2679 return dsi_sync_vc_l4(dsidev, channel);
2680 default:
2681 BUG();
2682 }
2683}
2684
2685static int dsi_vc_enable(struct platform_device *dsidev, int channel,
2686 bool enable)
1715{ 2687{
1716 DSSDBG("dsi_vc_enable channel %d, enable %d\n", 2688 DSSDBG("dsi_vc_enable channel %d, enable %d\n",
1717 channel, enable); 2689 channel, enable);
1718 2690
1719 enable = enable ? 1 : 0; 2691 enable = enable ? 1 : 0;
1720 2692
1721 REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 0, 0); 2693 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 0, 0);
1722 2694
1723 if (wait_for_bit_change(DSI_VC_CTRL(channel), 0, enable) != enable) { 2695 if (wait_for_bit_change(dsidev, DSI_VC_CTRL(channel),
2696 0, enable) != enable) {
1724 DSSERR("Failed to set dsi_vc_enable to %d\n", enable); 2697 DSSERR("Failed to set dsi_vc_enable to %d\n", enable);
1725 return -EIO; 2698 return -EIO;
1726 } 2699 }
@@ -1728,13 +2701,13 @@ static int dsi_vc_enable(int channel, bool enable)
1728 return 0; 2701 return 0;
1729} 2702}
1730 2703
1731static void dsi_vc_initial_config(int channel) 2704static void dsi_vc_initial_config(struct platform_device *dsidev, int channel)
1732{ 2705{
1733 u32 r; 2706 u32 r;
1734 2707
1735 DSSDBGF("%d", channel); 2708 DSSDBGF("%d", channel);
1736 2709
1737 r = dsi_read_reg(DSI_VC_CTRL(channel)); 2710 r = dsi_read_reg(dsidev, DSI_VC_CTRL(channel));
1738 2711
1739 if (FLD_GET(r, 15, 15)) /* VC_BUSY */ 2712 if (FLD_GET(r, 15, 15)) /* VC_BUSY */
1740 DSSERR("VC(%d) busy when trying to configure it!\n", 2713 DSSERR("VC(%d) busy when trying to configure it!\n",
@@ -1747,87 +2720,107 @@ static void dsi_vc_initial_config(int channel)
1747 r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */ 2720 r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */
1748 r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */ 2721 r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */
1749 r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */ 2722 r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */
2723 if (dss_has_feature(FEAT_DSI_VC_OCP_WIDTH))
2724 r = FLD_MOD(r, 3, 11, 10); /* OCP_WIDTH = 32 bit */
1750 2725
1751 r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */ 2726 r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */
1752 r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */ 2727 r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
1753 2728
1754 dsi_write_reg(DSI_VC_CTRL(channel), r); 2729 dsi_write_reg(dsidev, DSI_VC_CTRL(channel), r);
1755
1756 dsi.vc[channel].mode = DSI_VC_MODE_L4;
1757} 2730}
1758 2731
1759static int dsi_vc_config_l4(int channel) 2732static int dsi_vc_config_l4(struct platform_device *dsidev, int channel)
1760{ 2733{
1761 if (dsi.vc[channel].mode == DSI_VC_MODE_L4) 2734 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2735
2736 if (dsi->vc[channel].mode == DSI_VC_MODE_L4)
1762 return 0; 2737 return 0;
1763 2738
1764 DSSDBGF("%d", channel); 2739 DSSDBGF("%d", channel);
1765 2740
1766 dsi_vc_enable(channel, 0); 2741 dsi_sync_vc(dsidev, channel);
2742
2743 dsi_vc_enable(dsidev, channel, 0);
1767 2744
1768 /* VC_BUSY */ 2745 /* VC_BUSY */
1769 if (wait_for_bit_change(DSI_VC_CTRL(channel), 15, 0) != 0) { 2746 if (wait_for_bit_change(dsidev, DSI_VC_CTRL(channel), 15, 0) != 0) {
1770 DSSERR("vc(%d) busy when trying to config for L4\n", channel); 2747 DSSERR("vc(%d) busy when trying to config for L4\n", channel);
1771 return -EIO; 2748 return -EIO;
1772 } 2749 }
1773 2750
1774 REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */ 2751 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */
2752
2753 /* DCS_CMD_ENABLE */
2754 if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC))
2755 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 30, 30);
1775 2756
1776 dsi_vc_enable(channel, 1); 2757 dsi_vc_enable(dsidev, channel, 1);
1777 2758
1778 dsi.vc[channel].mode = DSI_VC_MODE_L4; 2759 dsi->vc[channel].mode = DSI_VC_MODE_L4;
1779 2760
1780 return 0; 2761 return 0;
1781} 2762}
1782 2763
1783static int dsi_vc_config_vp(int channel) 2764static int dsi_vc_config_vp(struct platform_device *dsidev, int channel)
1784{ 2765{
1785 if (dsi.vc[channel].mode == DSI_VC_MODE_VP) 2766 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2767
2768 if (dsi->vc[channel].mode == DSI_VC_MODE_VP)
1786 return 0; 2769 return 0;
1787 2770
1788 DSSDBGF("%d", channel); 2771 DSSDBGF("%d", channel);
1789 2772
1790 dsi_vc_enable(channel, 0); 2773 dsi_sync_vc(dsidev, channel);
2774
2775 dsi_vc_enable(dsidev, channel, 0);
1791 2776
1792 /* VC_BUSY */ 2777 /* VC_BUSY */
1793 if (wait_for_bit_change(DSI_VC_CTRL(channel), 15, 0) != 0) { 2778 if (wait_for_bit_change(dsidev, DSI_VC_CTRL(channel), 15, 0) != 0) {
1794 DSSERR("vc(%d) busy when trying to config for VP\n", channel); 2779 DSSERR("vc(%d) busy when trying to config for VP\n", channel);
1795 return -EIO; 2780 return -EIO;
1796 } 2781 }
1797 2782
1798 REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */ 2783 /* SOURCE, 1 = video port */
2784 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 1, 1);
2785
2786 /* DCS_CMD_ENABLE */
2787 if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC))
2788 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 30, 30);
1799 2789
1800 dsi_vc_enable(channel, 1); 2790 dsi_vc_enable(dsidev, channel, 1);
1801 2791
1802 dsi.vc[channel].mode = DSI_VC_MODE_VP; 2792 dsi->vc[channel].mode = DSI_VC_MODE_VP;
1803 2793
1804 return 0; 2794 return 0;
1805} 2795}
1806 2796
1807 2797
1808void omapdss_dsi_vc_enable_hs(int channel, bool enable) 2798void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
2799 bool enable)
1809{ 2800{
2801 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2802
1810 DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable); 2803 DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable);
1811 2804
1812 WARN_ON(!dsi_bus_is_locked()); 2805 WARN_ON(!dsi_bus_is_locked(dsidev));
1813 2806
1814 dsi_vc_enable(channel, 0); 2807 dsi_vc_enable(dsidev, channel, 0);
1815 dsi_if_enable(0); 2808 dsi_if_enable(dsidev, 0);
1816 2809
1817 REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 9, 9); 2810 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 9, 9);
1818 2811
1819 dsi_vc_enable(channel, 1); 2812 dsi_vc_enable(dsidev, channel, 1);
1820 dsi_if_enable(1); 2813 dsi_if_enable(dsidev, 1);
1821 2814
1822 dsi_force_tx_stop_mode_io(); 2815 dsi_force_tx_stop_mode_io(dsidev);
1823} 2816}
1824EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs); 2817EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs);
1825 2818
1826static void dsi_vc_flush_long_data(int channel) 2819static void dsi_vc_flush_long_data(struct platform_device *dsidev, int channel)
1827{ 2820{
1828 while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { 2821 while (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20)) {
1829 u32 val; 2822 u32 val;
1830 val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); 2823 val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel));
1831 DSSDBG("\t\tb1 %#02x b2 %#02x b3 %#02x b4 %#02x\n", 2824 DSSDBG("\t\tb1 %#02x b2 %#02x b3 %#02x b4 %#02x\n",
1832 (val >> 0) & 0xff, 2825 (val >> 0) & 0xff,
1833 (val >> 8) & 0xff, 2826 (val >> 8) & 0xff,
@@ -1873,13 +2866,14 @@ static void dsi_show_rx_ack_with_err(u16 err)
1873 DSSERR("\t\tDSI Protocol Violation\n"); 2866 DSSERR("\t\tDSI Protocol Violation\n");
1874} 2867}
1875 2868
1876static u16 dsi_vc_flush_receive_data(int channel) 2869static u16 dsi_vc_flush_receive_data(struct platform_device *dsidev,
2870 int channel)
1877{ 2871{
1878 /* RX_FIFO_NOT_EMPTY */ 2872 /* RX_FIFO_NOT_EMPTY */
1879 while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { 2873 while (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20)) {
1880 u32 val; 2874 u32 val;
1881 u8 dt; 2875 u8 dt;
1882 val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); 2876 val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel));
1883 DSSERR("\trawval %#08x\n", val); 2877 DSSERR("\trawval %#08x\n", val);
1884 dt = FLD_GET(val, 5, 0); 2878 dt = FLD_GET(val, 5, 0);
1885 if (dt == DSI_DT_RX_ACK_WITH_ERR) { 2879 if (dt == DSI_DT_RX_ACK_WITH_ERR) {
@@ -1894,7 +2888,7 @@ static u16 dsi_vc_flush_receive_data(int channel)
1894 } else if (dt == DSI_DT_RX_DCS_LONG_READ) { 2888 } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
1895 DSSERR("\tDCS long response, len %d\n", 2889 DSSERR("\tDCS long response, len %d\n",
1896 FLD_GET(val, 23, 8)); 2890 FLD_GET(val, 23, 8));
1897 dsi_vc_flush_long_data(channel); 2891 dsi_vc_flush_long_data(dsidev, channel);
1898 } else { 2892 } else {
1899 DSSERR("\tunknown datatype 0x%02x\n", dt); 2893 DSSERR("\tunknown datatype 0x%02x\n", dt);
1900 } 2894 }
@@ -1902,74 +2896,90 @@ static u16 dsi_vc_flush_receive_data(int channel)
1902 return 0; 2896 return 0;
1903} 2897}
1904 2898
1905static int dsi_vc_send_bta(int channel) 2899static int dsi_vc_send_bta(struct platform_device *dsidev, int channel)
1906{ 2900{
1907 if (dsi.debug_write || dsi.debug_read) 2901 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2902
2903 if (dsi->debug_write || dsi->debug_read)
1908 DSSDBG("dsi_vc_send_bta %d\n", channel); 2904 DSSDBG("dsi_vc_send_bta %d\n", channel);
1909 2905
1910 WARN_ON(!dsi_bus_is_locked()); 2906 WARN_ON(!dsi_bus_is_locked(dsidev));
1911 2907
1912 if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { /* RX_FIFO_NOT_EMPTY */ 2908 /* RX_FIFO_NOT_EMPTY */
2909 if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20)) {
1913 DSSERR("rx fifo not empty when sending BTA, dumping data:\n"); 2910 DSSERR("rx fifo not empty when sending BTA, dumping data:\n");
1914 dsi_vc_flush_receive_data(channel); 2911 dsi_vc_flush_receive_data(dsidev, channel);
1915 } 2912 }
1916 2913
1917 REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */ 2914 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */
1918 2915
1919 return 0; 2916 return 0;
1920} 2917}
1921 2918
1922int dsi_vc_send_bta_sync(int channel) 2919int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel)
1923{ 2920{
2921 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2922 DECLARE_COMPLETION_ONSTACK(completion);
1924 int r = 0; 2923 int r = 0;
1925 u32 err; 2924 u32 err;
1926 2925
1927 INIT_COMPLETION(dsi.bta_completion); 2926 r = dsi_register_isr_vc(dsidev, channel, dsi_completion_handler,
2927 &completion, DSI_VC_IRQ_BTA);
2928 if (r)
2929 goto err0;
1928 2930
1929 dsi_vc_enable_bta_irq(channel); 2931 r = dsi_register_isr(dsidev, dsi_completion_handler, &completion,
2932 DSI_IRQ_ERROR_MASK);
2933 if (r)
2934 goto err1;
1930 2935
1931 r = dsi_vc_send_bta(channel); 2936 r = dsi_vc_send_bta(dsidev, channel);
1932 if (r) 2937 if (r)
1933 goto err; 2938 goto err2;
1934 2939
1935 if (wait_for_completion_timeout(&dsi.bta_completion, 2940 if (wait_for_completion_timeout(&completion,
1936 msecs_to_jiffies(500)) == 0) { 2941 msecs_to_jiffies(500)) == 0) {
1937 DSSERR("Failed to receive BTA\n"); 2942 DSSERR("Failed to receive BTA\n");
1938 r = -EIO; 2943 r = -EIO;
1939 goto err; 2944 goto err2;
1940 } 2945 }
1941 2946
1942 err = dsi_get_errors(); 2947 err = dsi_get_errors(dsidev);
1943 if (err) { 2948 if (err) {
1944 DSSERR("Error while sending BTA: %x\n", err); 2949 DSSERR("Error while sending BTA: %x\n", err);
1945 r = -EIO; 2950 r = -EIO;
1946 goto err; 2951 goto err2;
1947 } 2952 }
1948err: 2953err2:
1949 dsi_vc_disable_bta_irq(channel); 2954 dsi_unregister_isr(dsidev, dsi_completion_handler, &completion,
1950 2955 DSI_IRQ_ERROR_MASK);
2956err1:
2957 dsi_unregister_isr_vc(dsidev, channel, dsi_completion_handler,
2958 &completion, DSI_VC_IRQ_BTA);
2959err0:
1951 return r; 2960 return r;
1952} 2961}
1953EXPORT_SYMBOL(dsi_vc_send_bta_sync); 2962EXPORT_SYMBOL(dsi_vc_send_bta_sync);
1954 2963
1955static inline void dsi_vc_write_long_header(int channel, u8 data_type, 2964static inline void dsi_vc_write_long_header(struct platform_device *dsidev,
1956 u16 len, u8 ecc) 2965 int channel, u8 data_type, u16 len, u8 ecc)
1957{ 2966{
2967 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1958 u32 val; 2968 u32 val;
1959 u8 data_id; 2969 u8 data_id;
1960 2970
1961 WARN_ON(!dsi_bus_is_locked()); 2971 WARN_ON(!dsi_bus_is_locked(dsidev));
1962 2972
1963 data_id = data_type | channel << 6; 2973 data_id = data_type | dsi->vc[channel].vc_id << 6;
1964 2974
1965 val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) | 2975 val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) |
1966 FLD_VAL(ecc, 31, 24); 2976 FLD_VAL(ecc, 31, 24);
1967 2977
1968 dsi_write_reg(DSI_VC_LONG_PACKET_HEADER(channel), val); 2978 dsi_write_reg(dsidev, DSI_VC_LONG_PACKET_HEADER(channel), val);
1969} 2979}
1970 2980
1971static inline void dsi_vc_write_long_payload(int channel, 2981static inline void dsi_vc_write_long_payload(struct platform_device *dsidev,
1972 u8 b1, u8 b2, u8 b3, u8 b4) 2982 int channel, u8 b1, u8 b2, u8 b3, u8 b4)
1973{ 2983{
1974 u32 val; 2984 u32 val;
1975 2985
@@ -1978,34 +2988,35 @@ static inline void dsi_vc_write_long_payload(int channel,
1978/* DSSDBG("\twriting %02x, %02x, %02x, %02x (%#010x)\n", 2988/* DSSDBG("\twriting %02x, %02x, %02x, %02x (%#010x)\n",
1979 b1, b2, b3, b4, val); */ 2989 b1, b2, b3, b4, val); */
1980 2990
1981 dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(channel), val); 2991 dsi_write_reg(dsidev, DSI_VC_LONG_PACKET_PAYLOAD(channel), val);
1982} 2992}
1983 2993
1984static int dsi_vc_send_long(int channel, u8 data_type, u8 *data, u16 len, 2994static int dsi_vc_send_long(struct platform_device *dsidev, int channel,
1985 u8 ecc) 2995 u8 data_type, u8 *data, u16 len, u8 ecc)
1986{ 2996{
1987 /*u32 val; */ 2997 /*u32 val; */
2998 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1988 int i; 2999 int i;
1989 u8 *p; 3000 u8 *p;
1990 int r = 0; 3001 int r = 0;
1991 u8 b1, b2, b3, b4; 3002 u8 b1, b2, b3, b4;
1992 3003
1993 if (dsi.debug_write) 3004 if (dsi->debug_write)
1994 DSSDBG("dsi_vc_send_long, %d bytes\n", len); 3005 DSSDBG("dsi_vc_send_long, %d bytes\n", len);
1995 3006
1996 /* len + header */ 3007 /* len + header */
1997 if (dsi.vc[channel].fifo_size * 32 * 4 < len + 4) { 3008 if (dsi->vc[channel].fifo_size * 32 * 4 < len + 4) {
1998 DSSERR("unable to send long packet: packet too long.\n"); 3009 DSSERR("unable to send long packet: packet too long.\n");
1999 return -EINVAL; 3010 return -EINVAL;
2000 } 3011 }
2001 3012
2002 dsi_vc_config_l4(channel); 3013 dsi_vc_config_l4(dsidev, channel);
2003 3014
2004 dsi_vc_write_long_header(channel, data_type, len, ecc); 3015 dsi_vc_write_long_header(dsidev, channel, data_type, len, ecc);
2005 3016
2006 p = data; 3017 p = data;
2007 for (i = 0; i < len >> 2; i++) { 3018 for (i = 0; i < len >> 2; i++) {
2008 if (dsi.debug_write) 3019 if (dsi->debug_write)
2009 DSSDBG("\tsending full packet %d\n", i); 3020 DSSDBG("\tsending full packet %d\n", i);
2010 3021
2011 b1 = *p++; 3022 b1 = *p++;
@@ -2013,14 +3024,14 @@ static int dsi_vc_send_long(int channel, u8 data_type, u8 *data, u16 len,
2013 b3 = *p++; 3024 b3 = *p++;
2014 b4 = *p++; 3025 b4 = *p++;
2015 3026
2016 dsi_vc_write_long_payload(channel, b1, b2, b3, b4); 3027 dsi_vc_write_long_payload(dsidev, channel, b1, b2, b3, b4);
2017 } 3028 }
2018 3029
2019 i = len % 4; 3030 i = len % 4;
2020 if (i) { 3031 if (i) {
2021 b1 = 0; b2 = 0; b3 = 0; 3032 b1 = 0; b2 = 0; b3 = 0;
2022 3033
2023 if (dsi.debug_write) 3034 if (dsi->debug_write)
2024 DSSDBG("\tsending remainder bytes %d\n", i); 3035 DSSDBG("\tsending remainder bytes %d\n", i);
2025 3036
2026 switch (i) { 3037 switch (i) {
@@ -2038,62 +3049,69 @@ static int dsi_vc_send_long(int channel, u8 data_type, u8 *data, u16 len,
2038 break; 3049 break;
2039 } 3050 }
2040 3051
2041 dsi_vc_write_long_payload(channel, b1, b2, b3, 0); 3052 dsi_vc_write_long_payload(dsidev, channel, b1, b2, b3, 0);
2042 } 3053 }
2043 3054
2044 return r; 3055 return r;
2045} 3056}
2046 3057
2047static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc) 3058static int dsi_vc_send_short(struct platform_device *dsidev, int channel,
3059 u8 data_type, u16 data, u8 ecc)
2048{ 3060{
3061 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2049 u32 r; 3062 u32 r;
2050 u8 data_id; 3063 u8 data_id;
2051 3064
2052 WARN_ON(!dsi_bus_is_locked()); 3065 WARN_ON(!dsi_bus_is_locked(dsidev));
2053 3066
2054 if (dsi.debug_write) 3067 if (dsi->debug_write)
2055 DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n", 3068 DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n",
2056 channel, 3069 channel,
2057 data_type, data & 0xff, (data >> 8) & 0xff); 3070 data_type, data & 0xff, (data >> 8) & 0xff);
2058 3071
2059 dsi_vc_config_l4(channel); 3072 dsi_vc_config_l4(dsidev, channel);
2060 3073
2061 if (FLD_GET(dsi_read_reg(DSI_VC_CTRL(channel)), 16, 16)) { 3074 if (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(channel)), 16, 16)) {
2062 DSSERR("ERROR FIFO FULL, aborting transfer\n"); 3075 DSSERR("ERROR FIFO FULL, aborting transfer\n");
2063 return -EINVAL; 3076 return -EINVAL;
2064 } 3077 }
2065 3078
2066 data_id = data_type | channel << 6; 3079 data_id = data_type | dsi->vc[channel].vc_id << 6;
2067 3080
2068 r = (data_id << 0) | (data << 8) | (ecc << 24); 3081 r = (data_id << 0) | (data << 8) | (ecc << 24);
2069 3082
2070 dsi_write_reg(DSI_VC_SHORT_PACKET_HEADER(channel), r); 3083 dsi_write_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel), r);
2071 3084
2072 return 0; 3085 return 0;
2073} 3086}
2074 3087
2075int dsi_vc_send_null(int channel) 3088int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel)
2076{ 3089{
3090 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2077 u8 nullpkg[] = {0, 0, 0, 0}; 3091 u8 nullpkg[] = {0, 0, 0, 0};
2078 return dsi_vc_send_long(channel, DSI_DT_NULL_PACKET, nullpkg, 4, 0); 3092
3093 return dsi_vc_send_long(dsidev, channel, DSI_DT_NULL_PACKET, nullpkg,
3094 4, 0);
2079} 3095}
2080EXPORT_SYMBOL(dsi_vc_send_null); 3096EXPORT_SYMBOL(dsi_vc_send_null);
2081 3097
2082int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len) 3098int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel,
3099 u8 *data, int len)
2083{ 3100{
3101 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2084 int r; 3102 int r;
2085 3103
2086 BUG_ON(len == 0); 3104 BUG_ON(len == 0);
2087 3105
2088 if (len == 1) { 3106 if (len == 1) {
2089 r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_0, 3107 r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_SHORT_WRITE_0,
2090 data[0], 0); 3108 data[0], 0);
2091 } else if (len == 2) { 3109 } else if (len == 2) {
2092 r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_1, 3110 r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_SHORT_WRITE_1,
2093 data[0] | (data[1] << 8), 0); 3111 data[0] | (data[1] << 8), 0);
2094 } else { 3112 } else {
2095 /* 0x39 = DCS Long Write */ 3113 /* 0x39 = DCS Long Write */
2096 r = dsi_vc_send_long(channel, DSI_DT_DCS_LONG_WRITE, 3114 r = dsi_vc_send_long(dsidev, channel, DSI_DT_DCS_LONG_WRITE,
2097 data, len, 0); 3115 data, len, 0);
2098 } 3116 }
2099 3117
@@ -2101,21 +3119,24 @@ int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len)
2101} 3119}
2102EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); 3120EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);
2103 3121
2104int dsi_vc_dcs_write(int channel, u8 *data, int len) 3122int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
3123 int len)
2105{ 3124{
3125 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2106 int r; 3126 int r;
2107 3127
2108 r = dsi_vc_dcs_write_nosync(channel, data, len); 3128 r = dsi_vc_dcs_write_nosync(dssdev, channel, data, len);
2109 if (r) 3129 if (r)
2110 goto err; 3130 goto err;
2111 3131
2112 r = dsi_vc_send_bta_sync(channel); 3132 r = dsi_vc_send_bta_sync(dssdev, channel);
2113 if (r) 3133 if (r)
2114 goto err; 3134 goto err;
2115 3135
2116 if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { /* RX_FIFO_NOT_EMPTY */ 3136 /* RX_FIFO_NOT_EMPTY */
3137 if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20)) {
2117 DSSERR("rx fifo not empty after write, dumping data:\n"); 3138 DSSERR("rx fifo not empty after write, dumping data:\n");
2118 dsi_vc_flush_receive_data(channel); 3139 dsi_vc_flush_receive_data(dsidev, channel);
2119 r = -EIO; 3140 r = -EIO;
2120 goto err; 3141 goto err;
2121 } 3142 }
@@ -2128,47 +3149,51 @@ err:
2128} 3149}
2129EXPORT_SYMBOL(dsi_vc_dcs_write); 3150EXPORT_SYMBOL(dsi_vc_dcs_write);
2130 3151
2131int dsi_vc_dcs_write_0(int channel, u8 dcs_cmd) 3152int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd)
2132{ 3153{
2133 return dsi_vc_dcs_write(channel, &dcs_cmd, 1); 3154 return dsi_vc_dcs_write(dssdev, channel, &dcs_cmd, 1);
2134} 3155}
2135EXPORT_SYMBOL(dsi_vc_dcs_write_0); 3156EXPORT_SYMBOL(dsi_vc_dcs_write_0);
2136 3157
2137int dsi_vc_dcs_write_1(int channel, u8 dcs_cmd, u8 param) 3158int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
3159 u8 param)
2138{ 3160{
2139 u8 buf[2]; 3161 u8 buf[2];
2140 buf[0] = dcs_cmd; 3162 buf[0] = dcs_cmd;
2141 buf[1] = param; 3163 buf[1] = param;
2142 return dsi_vc_dcs_write(channel, buf, 2); 3164 return dsi_vc_dcs_write(dssdev, channel, buf, 2);
2143} 3165}
2144EXPORT_SYMBOL(dsi_vc_dcs_write_1); 3166EXPORT_SYMBOL(dsi_vc_dcs_write_1);
2145 3167
2146int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen) 3168int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
3169 u8 *buf, int buflen)
2147{ 3170{
3171 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3172 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2148 u32 val; 3173 u32 val;
2149 u8 dt; 3174 u8 dt;
2150 int r; 3175 int r;
2151 3176
2152 if (dsi.debug_read) 3177 if (dsi->debug_read)
2153 DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %x)\n", channel, dcs_cmd); 3178 DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %x)\n", channel, dcs_cmd);
2154 3179
2155 r = dsi_vc_send_short(channel, DSI_DT_DCS_READ, dcs_cmd, 0); 3180 r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_READ, dcs_cmd, 0);
2156 if (r) 3181 if (r)
2157 goto err; 3182 goto err;
2158 3183
2159 r = dsi_vc_send_bta_sync(channel); 3184 r = dsi_vc_send_bta_sync(dssdev, channel);
2160 if (r) 3185 if (r)
2161 goto err; 3186 goto err;
2162 3187
2163 /* RX_FIFO_NOT_EMPTY */ 3188 /* RX_FIFO_NOT_EMPTY */
2164 if (REG_GET(DSI_VC_CTRL(channel), 20, 20) == 0) { 3189 if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20) == 0) {
2165 DSSERR("RX fifo empty when trying to read.\n"); 3190 DSSERR("RX fifo empty when trying to read.\n");
2166 r = -EIO; 3191 r = -EIO;
2167 goto err; 3192 goto err;
2168 } 3193 }
2169 3194
2170 val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); 3195 val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel));
2171 if (dsi.debug_read) 3196 if (dsi->debug_read)
2172 DSSDBG("\theader: %08x\n", val); 3197 DSSDBG("\theader: %08x\n", val);
2173 dt = FLD_GET(val, 5, 0); 3198 dt = FLD_GET(val, 5, 0);
2174 if (dt == DSI_DT_RX_ACK_WITH_ERR) { 3199 if (dt == DSI_DT_RX_ACK_WITH_ERR) {
@@ -2179,7 +3204,7 @@ int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen)
2179 3204
2180 } else if (dt == DSI_DT_RX_SHORT_READ_1) { 3205 } else if (dt == DSI_DT_RX_SHORT_READ_1) {
2181 u8 data = FLD_GET(val, 15, 8); 3206 u8 data = FLD_GET(val, 15, 8);
2182 if (dsi.debug_read) 3207 if (dsi->debug_read)
2183 DSSDBG("\tDCS short response, 1 byte: %02x\n", data); 3208 DSSDBG("\tDCS short response, 1 byte: %02x\n", data);
2184 3209
2185 if (buflen < 1) { 3210 if (buflen < 1) {
@@ -2192,7 +3217,7 @@ int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen)
2192 return 1; 3217 return 1;
2193 } else if (dt == DSI_DT_RX_SHORT_READ_2) { 3218 } else if (dt == DSI_DT_RX_SHORT_READ_2) {
2194 u16 data = FLD_GET(val, 23, 8); 3219 u16 data = FLD_GET(val, 23, 8);
2195 if (dsi.debug_read) 3220 if (dsi->debug_read)
2196 DSSDBG("\tDCS short response, 2 byte: %04x\n", data); 3221 DSSDBG("\tDCS short response, 2 byte: %04x\n", data);
2197 3222
2198 if (buflen < 2) { 3223 if (buflen < 2) {
@@ -2207,7 +3232,7 @@ int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen)
2207 } else if (dt == DSI_DT_RX_DCS_LONG_READ) { 3232 } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
2208 int w; 3233 int w;
2209 int len = FLD_GET(val, 23, 8); 3234 int len = FLD_GET(val, 23, 8);
2210 if (dsi.debug_read) 3235 if (dsi->debug_read)
2211 DSSDBG("\tDCS long response, len %d\n", len); 3236 DSSDBG("\tDCS long response, len %d\n", len);
2212 3237
2213 if (len > buflen) { 3238 if (len > buflen) {
@@ -2218,8 +3243,9 @@ int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen)
2218 /* two byte checksum ends the packet, not included in len */ 3243 /* two byte checksum ends the packet, not included in len */
2219 for (w = 0; w < len + 2;) { 3244 for (w = 0; w < len + 2;) {
2220 int b; 3245 int b;
2221 val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); 3246 val = dsi_read_reg(dsidev,
2222 if (dsi.debug_read) 3247 DSI_VC_SHORT_PACKET_HEADER(channel));
3248 if (dsi->debug_read)
2223 DSSDBG("\t\t%02x %02x %02x %02x\n", 3249 DSSDBG("\t\t%02x %02x %02x %02x\n",
2224 (val >> 0) & 0xff, 3250 (val >> 0) & 0xff,
2225 (val >> 8) & 0xff, 3251 (val >> 8) & 0xff,
@@ -2250,11 +3276,12 @@ err:
2250} 3276}
2251EXPORT_SYMBOL(dsi_vc_dcs_read); 3277EXPORT_SYMBOL(dsi_vc_dcs_read);
2252 3278
2253int dsi_vc_dcs_read_1(int channel, u8 dcs_cmd, u8 *data) 3279int dsi_vc_dcs_read_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
3280 u8 *data)
2254{ 3281{
2255 int r; 3282 int r;
2256 3283
2257 r = dsi_vc_dcs_read(channel, dcs_cmd, data, 1); 3284 r = dsi_vc_dcs_read(dssdev, channel, dcs_cmd, data, 1);
2258 3285
2259 if (r < 0) 3286 if (r < 0)
2260 return r; 3287 return r;
@@ -2266,12 +3293,13 @@ int dsi_vc_dcs_read_1(int channel, u8 dcs_cmd, u8 *data)
2266} 3293}
2267EXPORT_SYMBOL(dsi_vc_dcs_read_1); 3294EXPORT_SYMBOL(dsi_vc_dcs_read_1);
2268 3295
2269int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u8 *data1, u8 *data2) 3296int dsi_vc_dcs_read_2(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
3297 u8 *data1, u8 *data2)
2270{ 3298{
2271 u8 buf[2]; 3299 u8 buf[2];
2272 int r; 3300 int r;
2273 3301
2274 r = dsi_vc_dcs_read(channel, dcs_cmd, buf, 2); 3302 r = dsi_vc_dcs_read(dssdev, channel, dcs_cmd, buf, 2);
2275 3303
2276 if (r < 0) 3304 if (r < 0)
2277 return r; 3305 return r;
@@ -2286,14 +3314,94 @@ int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u8 *data1, u8 *data2)
2286} 3314}
2287EXPORT_SYMBOL(dsi_vc_dcs_read_2); 3315EXPORT_SYMBOL(dsi_vc_dcs_read_2);
2288 3316
2289int dsi_vc_set_max_rx_packet_size(int channel, u16 len) 3317int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel,
3318 u16 len)
2290{ 3319{
2291 return dsi_vc_send_short(channel, DSI_DT_SET_MAX_RET_PKG_SIZE, 3320 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3321
3322 return dsi_vc_send_short(dsidev, channel, DSI_DT_SET_MAX_RET_PKG_SIZE,
2292 len, 0); 3323 len, 0);
2293} 3324}
2294EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size); 3325EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size);
2295 3326
2296static void dsi_set_lp_rx_timeout(unsigned ticks, bool x4, bool x16) 3327static int dsi_enter_ulps(struct platform_device *dsidev)
3328{
3329 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3330 DECLARE_COMPLETION_ONSTACK(completion);
3331 int r;
3332
3333 DSSDBGF();
3334
3335 WARN_ON(!dsi_bus_is_locked(dsidev));
3336
3337 WARN_ON(dsi->ulps_enabled);
3338
3339 if (dsi->ulps_enabled)
3340 return 0;
3341
3342 if (REG_GET(dsidev, DSI_CLK_CTRL, 13, 13)) {
3343 DSSERR("DDR_CLK_ALWAYS_ON enabled when entering ULPS\n");
3344 return -EIO;
3345 }
3346
3347 dsi_sync_vc(dsidev, 0);
3348 dsi_sync_vc(dsidev, 1);
3349 dsi_sync_vc(dsidev, 2);
3350 dsi_sync_vc(dsidev, 3);
3351
3352 dsi_force_tx_stop_mode_io(dsidev);
3353
3354 dsi_vc_enable(dsidev, 0, false);
3355 dsi_vc_enable(dsidev, 1, false);
3356 dsi_vc_enable(dsidev, 2, false);
3357 dsi_vc_enable(dsidev, 3, false);
3358
3359 if (REG_GET(dsidev, DSI_COMPLEXIO_CFG2, 16, 16)) { /* HS_BUSY */
3360 DSSERR("HS busy when enabling ULPS\n");
3361 return -EIO;
3362 }
3363
3364 if (REG_GET(dsidev, DSI_COMPLEXIO_CFG2, 17, 17)) { /* LP_BUSY */
3365 DSSERR("LP busy when enabling ULPS\n");
3366 return -EIO;
3367 }
3368
3369 r = dsi_register_isr_cio(dsidev, dsi_completion_handler, &completion,
3370 DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
3371 if (r)
3372 return r;
3373
3374 /* Assert TxRequestEsc for data lanes and TxUlpsClk for clk lane */
3375 /* LANEx_ULPS_SIG2 */
3376 REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (1 << 0) | (1 << 1) | (1 << 2),
3377 7, 5);
3378
3379 if (wait_for_completion_timeout(&completion,
3380 msecs_to_jiffies(1000)) == 0) {
3381 DSSERR("ULPS enable timeout\n");
3382 r = -EIO;
3383 goto err;
3384 }
3385
3386 dsi_unregister_isr_cio(dsidev, dsi_completion_handler, &completion,
3387 DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
3388
3389 dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS);
3390
3391 dsi_if_enable(dsidev, false);
3392
3393 dsi->ulps_enabled = true;
3394
3395 return 0;
3396
3397err:
3398 dsi_unregister_isr_cio(dsidev, dsi_completion_handler, &completion,
3399 DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
3400 return r;
3401}
3402
3403static void dsi_set_lp_rx_timeout(struct platform_device *dsidev,
3404 unsigned ticks, bool x4, bool x16)
2297{ 3405{
2298 unsigned long fck; 3406 unsigned long fck;
2299 unsigned long total_ticks; 3407 unsigned long total_ticks;
@@ -2302,14 +3410,14 @@ static void dsi_set_lp_rx_timeout(unsigned ticks, bool x4, bool x16)
2302 BUG_ON(ticks > 0x1fff); 3410 BUG_ON(ticks > 0x1fff);
2303 3411
2304 /* ticks in DSI_FCK */ 3412 /* ticks in DSI_FCK */
2305 fck = dsi_fclk_rate(); 3413 fck = dsi_fclk_rate(dsidev);
2306 3414
2307 r = dsi_read_reg(DSI_TIMING2); 3415 r = dsi_read_reg(dsidev, DSI_TIMING2);
2308 r = FLD_MOD(r, 1, 15, 15); /* LP_RX_TO */ 3416 r = FLD_MOD(r, 1, 15, 15); /* LP_RX_TO */
2309 r = FLD_MOD(r, x16 ? 1 : 0, 14, 14); /* LP_RX_TO_X16 */ 3417 r = FLD_MOD(r, x16 ? 1 : 0, 14, 14); /* LP_RX_TO_X16 */
2310 r = FLD_MOD(r, x4 ? 1 : 0, 13, 13); /* LP_RX_TO_X4 */ 3418 r = FLD_MOD(r, x4 ? 1 : 0, 13, 13); /* LP_RX_TO_X4 */
2311 r = FLD_MOD(r, ticks, 12, 0); /* LP_RX_COUNTER */ 3419 r = FLD_MOD(r, ticks, 12, 0); /* LP_RX_COUNTER */
2312 dsi_write_reg(DSI_TIMING2, r); 3420 dsi_write_reg(dsidev, DSI_TIMING2, r);
2313 3421
2314 total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1); 3422 total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1);
2315 3423
@@ -2319,7 +3427,8 @@ static void dsi_set_lp_rx_timeout(unsigned ticks, bool x4, bool x16)
2319 (total_ticks * 1000) / (fck / 1000 / 1000)); 3427 (total_ticks * 1000) / (fck / 1000 / 1000));
2320} 3428}
2321 3429
2322static void dsi_set_ta_timeout(unsigned ticks, bool x8, bool x16) 3430static void dsi_set_ta_timeout(struct platform_device *dsidev, unsigned ticks,
3431 bool x8, bool x16)
2323{ 3432{
2324 unsigned long fck; 3433 unsigned long fck;
2325 unsigned long total_ticks; 3434 unsigned long total_ticks;
@@ -2328,14 +3437,14 @@ static void dsi_set_ta_timeout(unsigned ticks, bool x8, bool x16)
2328 BUG_ON(ticks > 0x1fff); 3437 BUG_ON(ticks > 0x1fff);
2329 3438
2330 /* ticks in DSI_FCK */ 3439 /* ticks in DSI_FCK */
2331 fck = dsi_fclk_rate(); 3440 fck = dsi_fclk_rate(dsidev);
2332 3441
2333 r = dsi_read_reg(DSI_TIMING1); 3442 r = dsi_read_reg(dsidev, DSI_TIMING1);
2334 r = FLD_MOD(r, 1, 31, 31); /* TA_TO */ 3443 r = FLD_MOD(r, 1, 31, 31); /* TA_TO */
2335 r = FLD_MOD(r, x16 ? 1 : 0, 30, 30); /* TA_TO_X16 */ 3444 r = FLD_MOD(r, x16 ? 1 : 0, 30, 30); /* TA_TO_X16 */
2336 r = FLD_MOD(r, x8 ? 1 : 0, 29, 29); /* TA_TO_X8 */ 3445 r = FLD_MOD(r, x8 ? 1 : 0, 29, 29); /* TA_TO_X8 */
2337 r = FLD_MOD(r, ticks, 28, 16); /* TA_TO_COUNTER */ 3446 r = FLD_MOD(r, ticks, 28, 16); /* TA_TO_COUNTER */
2338 dsi_write_reg(DSI_TIMING1, r); 3447 dsi_write_reg(dsidev, DSI_TIMING1, r);
2339 3448
2340 total_ticks = ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1); 3449 total_ticks = ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1);
2341 3450
@@ -2345,7 +3454,8 @@ static void dsi_set_ta_timeout(unsigned ticks, bool x8, bool x16)
2345 (total_ticks * 1000) / (fck / 1000 / 1000)); 3454 (total_ticks * 1000) / (fck / 1000 / 1000));
2346} 3455}
2347 3456
2348static void dsi_set_stop_state_counter(unsigned ticks, bool x4, bool x16) 3457static void dsi_set_stop_state_counter(struct platform_device *dsidev,
3458 unsigned ticks, bool x4, bool x16)
2349{ 3459{
2350 unsigned long fck; 3460 unsigned long fck;
2351 unsigned long total_ticks; 3461 unsigned long total_ticks;
@@ -2354,14 +3464,14 @@ static void dsi_set_stop_state_counter(unsigned ticks, bool x4, bool x16)
2354 BUG_ON(ticks > 0x1fff); 3464 BUG_ON(ticks > 0x1fff);
2355 3465
2356 /* ticks in DSI_FCK */ 3466 /* ticks in DSI_FCK */
2357 fck = dsi_fclk_rate(); 3467 fck = dsi_fclk_rate(dsidev);
2358 3468
2359 r = dsi_read_reg(DSI_TIMING1); 3469 r = dsi_read_reg(dsidev, DSI_TIMING1);
2360 r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */ 3470 r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
2361 r = FLD_MOD(r, x16 ? 1 : 0, 14, 14); /* STOP_STATE_X16_IO */ 3471 r = FLD_MOD(r, x16 ? 1 : 0, 14, 14); /* STOP_STATE_X16_IO */
2362 r = FLD_MOD(r, x4 ? 1 : 0, 13, 13); /* STOP_STATE_X4_IO */ 3472 r = FLD_MOD(r, x4 ? 1 : 0, 13, 13); /* STOP_STATE_X4_IO */
2363 r = FLD_MOD(r, ticks, 12, 0); /* STOP_STATE_COUNTER_IO */ 3473 r = FLD_MOD(r, ticks, 12, 0); /* STOP_STATE_COUNTER_IO */
2364 dsi_write_reg(DSI_TIMING1, r); 3474 dsi_write_reg(dsidev, DSI_TIMING1, r);
2365 3475
2366 total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1); 3476 total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1);
2367 3477
@@ -2371,7 +3481,8 @@ static void dsi_set_stop_state_counter(unsigned ticks, bool x4, bool x16)
2371 (total_ticks * 1000) / (fck / 1000 / 1000)); 3481 (total_ticks * 1000) / (fck / 1000 / 1000));
2372} 3482}
2373 3483
2374static void dsi_set_hs_tx_timeout(unsigned ticks, bool x4, bool x16) 3484static void dsi_set_hs_tx_timeout(struct platform_device *dsidev,
3485 unsigned ticks, bool x4, bool x16)
2375{ 3486{
2376 unsigned long fck; 3487 unsigned long fck;
2377 unsigned long total_ticks; 3488 unsigned long total_ticks;
@@ -2380,14 +3491,14 @@ static void dsi_set_hs_tx_timeout(unsigned ticks, bool x4, bool x16)
2380 BUG_ON(ticks > 0x1fff); 3491 BUG_ON(ticks > 0x1fff);
2381 3492
2382 /* ticks in TxByteClkHS */ 3493 /* ticks in TxByteClkHS */
2383 fck = dsi_get_txbyteclkhs(); 3494 fck = dsi_get_txbyteclkhs(dsidev);
2384 3495
2385 r = dsi_read_reg(DSI_TIMING2); 3496 r = dsi_read_reg(dsidev, DSI_TIMING2);
2386 r = FLD_MOD(r, 1, 31, 31); /* HS_TX_TO */ 3497 r = FLD_MOD(r, 1, 31, 31); /* HS_TX_TO */
2387 r = FLD_MOD(r, x16 ? 1 : 0, 30, 30); /* HS_TX_TO_X16 */ 3498 r = FLD_MOD(r, x16 ? 1 : 0, 30, 30); /* HS_TX_TO_X16 */
2388 r = FLD_MOD(r, x4 ? 1 : 0, 29, 29); /* HS_TX_TO_X8 (4 really) */ 3499 r = FLD_MOD(r, x4 ? 1 : 0, 29, 29); /* HS_TX_TO_X8 (4 really) */
2389 r = FLD_MOD(r, ticks, 28, 16); /* HS_TX_TO_COUNTER */ 3500 r = FLD_MOD(r, ticks, 28, 16); /* HS_TX_TO_COUNTER */
2390 dsi_write_reg(DSI_TIMING2, r); 3501 dsi_write_reg(dsidev, DSI_TIMING2, r);
2391 3502
2392 total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1); 3503 total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1);
2393 3504
@@ -2398,24 +3509,25 @@ static void dsi_set_hs_tx_timeout(unsigned ticks, bool x4, bool x16)
2398} 3509}
2399static int dsi_proto_config(struct omap_dss_device *dssdev) 3510static int dsi_proto_config(struct omap_dss_device *dssdev)
2400{ 3511{
3512 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2401 u32 r; 3513 u32 r;
2402 int buswidth = 0; 3514 int buswidth = 0;
2403 3515
2404 dsi_config_tx_fifo(DSI_FIFO_SIZE_32, 3516 dsi_config_tx_fifo(dsidev, DSI_FIFO_SIZE_32,
2405 DSI_FIFO_SIZE_32, 3517 DSI_FIFO_SIZE_32,
2406 DSI_FIFO_SIZE_32, 3518 DSI_FIFO_SIZE_32,
2407 DSI_FIFO_SIZE_32); 3519 DSI_FIFO_SIZE_32);
2408 3520
2409 dsi_config_rx_fifo(DSI_FIFO_SIZE_32, 3521 dsi_config_rx_fifo(dsidev, DSI_FIFO_SIZE_32,
2410 DSI_FIFO_SIZE_32, 3522 DSI_FIFO_SIZE_32,
2411 DSI_FIFO_SIZE_32, 3523 DSI_FIFO_SIZE_32,
2412 DSI_FIFO_SIZE_32); 3524 DSI_FIFO_SIZE_32);
2413 3525
2414 /* XXX what values for the timeouts? */ 3526 /* XXX what values for the timeouts? */
2415 dsi_set_stop_state_counter(0x1000, false, false); 3527 dsi_set_stop_state_counter(dsidev, 0x1000, false, false);
2416 dsi_set_ta_timeout(0x1fff, true, true); 3528 dsi_set_ta_timeout(dsidev, 0x1fff, true, true);
2417 dsi_set_lp_rx_timeout(0x1fff, true, true); 3529 dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true);
2418 dsi_set_hs_tx_timeout(0x1fff, true, true); 3530 dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true);
2419 3531
2420 switch (dssdev->ctrl.pixel_size) { 3532 switch (dssdev->ctrl.pixel_size) {
2421 case 16: 3533 case 16:
@@ -2431,7 +3543,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
2431 BUG(); 3543 BUG();
2432 } 3544 }
2433 3545
2434 r = dsi_read_reg(DSI_CTRL); 3546 r = dsi_read_reg(dsidev, DSI_CTRL);
2435 r = FLD_MOD(r, 1, 1, 1); /* CS_RX_EN */ 3547 r = FLD_MOD(r, 1, 1, 1); /* CS_RX_EN */
2436 r = FLD_MOD(r, 1, 2, 2); /* ECC_RX_EN */ 3548 r = FLD_MOD(r, 1, 2, 2); /* ECC_RX_EN */
2437 r = FLD_MOD(r, 1, 3, 3); /* TX_FIFO_ARBITRATION */ 3549 r = FLD_MOD(r, 1, 3, 3); /* TX_FIFO_ARBITRATION */
@@ -2441,21 +3553,25 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
2441 r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */ 3553 r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */
2442 r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */ 3554 r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */
2443 r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */ 3555 r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */
2444 r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */ 3556 if (!dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) {
2445 r = FLD_MOD(r, 0, 25, 25); /* DCS_CMD_CODE, 1=start, 0=continue */ 3557 r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */
3558 /* DCS_CMD_CODE, 1=start, 0=continue */
3559 r = FLD_MOD(r, 0, 25, 25);
3560 }
2446 3561
2447 dsi_write_reg(DSI_CTRL, r); 3562 dsi_write_reg(dsidev, DSI_CTRL, r);
2448 3563
2449 dsi_vc_initial_config(0); 3564 dsi_vc_initial_config(dsidev, 0);
2450 dsi_vc_initial_config(1); 3565 dsi_vc_initial_config(dsidev, 1);
2451 dsi_vc_initial_config(2); 3566 dsi_vc_initial_config(dsidev, 2);
2452 dsi_vc_initial_config(3); 3567 dsi_vc_initial_config(dsidev, 3);
2453 3568
2454 return 0; 3569 return 0;
2455} 3570}
2456 3571
2457static void dsi_proto_timings(struct omap_dss_device *dssdev) 3572static void dsi_proto_timings(struct omap_dss_device *dssdev)
2458{ 3573{
3574 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2459 unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail; 3575 unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail;
2460 unsigned tclk_pre, tclk_post; 3576 unsigned tclk_pre, tclk_post;
2461 unsigned ths_prepare, ths_prepare_ths_zero, ths_zero; 3577 unsigned ths_prepare, ths_prepare_ths_zero, ths_zero;
@@ -2465,32 +3581,27 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
2465 unsigned ths_eot; 3581 unsigned ths_eot;
2466 u32 r; 3582 u32 r;
2467 3583
2468 r = dsi_read_reg(DSI_DSIPHY_CFG0); 3584 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0);
2469 ths_prepare = FLD_GET(r, 31, 24); 3585 ths_prepare = FLD_GET(r, 31, 24);
2470 ths_prepare_ths_zero = FLD_GET(r, 23, 16); 3586 ths_prepare_ths_zero = FLD_GET(r, 23, 16);
2471 ths_zero = ths_prepare_ths_zero - ths_prepare; 3587 ths_zero = ths_prepare_ths_zero - ths_prepare;
2472 ths_trail = FLD_GET(r, 15, 8); 3588 ths_trail = FLD_GET(r, 15, 8);
2473 ths_exit = FLD_GET(r, 7, 0); 3589 ths_exit = FLD_GET(r, 7, 0);
2474 3590
2475 r = dsi_read_reg(DSI_DSIPHY_CFG1); 3591 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1);
2476 tlpx = FLD_GET(r, 22, 16) * 2; 3592 tlpx = FLD_GET(r, 22, 16) * 2;
2477 tclk_trail = FLD_GET(r, 15, 8); 3593 tclk_trail = FLD_GET(r, 15, 8);
2478 tclk_zero = FLD_GET(r, 7, 0); 3594 tclk_zero = FLD_GET(r, 7, 0);
2479 3595
2480 r = dsi_read_reg(DSI_DSIPHY_CFG2); 3596 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2);
2481 tclk_prepare = FLD_GET(r, 7, 0); 3597 tclk_prepare = FLD_GET(r, 7, 0);
2482 3598
2483 /* min 8*UI */ 3599 /* min 8*UI */
2484 tclk_pre = 20; 3600 tclk_pre = 20;
2485 /* min 60ns + 52*UI */ 3601 /* min 60ns + 52*UI */
2486 tclk_post = ns2ddr(60) + 26; 3602 tclk_post = ns2ddr(dsidev, 60) + 26;
2487 3603
2488 /* ths_eot is 2 for 2 datalanes and 4 for 1 datalane */ 3604 ths_eot = DIV_ROUND_UP(4, dsi_get_num_data_lanes_dssdev(dssdev));
2489 if (dssdev->phy.dsi.data1_lane != 0 &&
2490 dssdev->phy.dsi.data2_lane != 0)
2491 ths_eot = 2;
2492 else
2493 ths_eot = 4;
2494 3605
2495 ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare, 3606 ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare,
2496 4); 3607 4);
@@ -2499,10 +3610,10 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
2499 BUG_ON(ddr_clk_pre == 0 || ddr_clk_pre > 255); 3610 BUG_ON(ddr_clk_pre == 0 || ddr_clk_pre > 255);
2500 BUG_ON(ddr_clk_post == 0 || ddr_clk_post > 255); 3611 BUG_ON(ddr_clk_post == 0 || ddr_clk_post > 255);
2501 3612
2502 r = dsi_read_reg(DSI_CLK_TIMING); 3613 r = dsi_read_reg(dsidev, DSI_CLK_TIMING);
2503 r = FLD_MOD(r, ddr_clk_pre, 15, 8); 3614 r = FLD_MOD(r, ddr_clk_pre, 15, 8);
2504 r = FLD_MOD(r, ddr_clk_post, 7, 0); 3615 r = FLD_MOD(r, ddr_clk_post, 7, 0);
2505 dsi_write_reg(DSI_CLK_TIMING, r); 3616 dsi_write_reg(dsidev, DSI_CLK_TIMING, r);
2506 3617
2507 DSSDBG("ddr_clk_pre %u, ddr_clk_post %u\n", 3618 DSSDBG("ddr_clk_pre %u, ddr_clk_post %u\n",
2508 ddr_clk_pre, 3619 ddr_clk_pre,
@@ -2516,7 +3627,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
2516 3627
2517 r = FLD_VAL(enter_hs_mode_lat, 31, 16) | 3628 r = FLD_VAL(enter_hs_mode_lat, 31, 16) |
2518 FLD_VAL(exit_hs_mode_lat, 15, 0); 3629 FLD_VAL(exit_hs_mode_lat, 15, 0);
2519 dsi_write_reg(DSI_VM_TIMING7, r); 3630 dsi_write_reg(dsidev, DSI_VM_TIMING7, r);
2520 3631
2521 DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n", 3632 DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",
2522 enter_hs_mode_lat, exit_hs_mode_lat); 3633 enter_hs_mode_lat, exit_hs_mode_lat);
@@ -2526,25 +3637,27 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
2526#define DSI_DECL_VARS \ 3637#define DSI_DECL_VARS \
2527 int __dsi_cb = 0; u32 __dsi_cv = 0; 3638 int __dsi_cb = 0; u32 __dsi_cv = 0;
2528 3639
2529#define DSI_FLUSH(ch) \ 3640#define DSI_FLUSH(dsidev, ch) \
2530 if (__dsi_cb > 0) { \ 3641 if (__dsi_cb > 0) { \
2531 /*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \ 3642 /*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \
2532 dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \ 3643 dsi_write_reg(dsidev, DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \
2533 __dsi_cb = __dsi_cv = 0; \ 3644 __dsi_cb = __dsi_cv = 0; \
2534 } 3645 }
2535 3646
2536#define DSI_PUSH(ch, data) \ 3647#define DSI_PUSH(dsidev, ch, data) \
2537 do { \ 3648 do { \
2538 __dsi_cv |= (data) << (__dsi_cb * 8); \ 3649 __dsi_cv |= (data) << (__dsi_cb * 8); \
2539 /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \ 3650 /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \
2540 if (++__dsi_cb > 3) \ 3651 if (++__dsi_cb > 3) \
2541 DSI_FLUSH(ch); \ 3652 DSI_FLUSH(dsidev, ch); \
2542 } while (0) 3653 } while (0)
2543 3654
2544static int dsi_update_screen_l4(struct omap_dss_device *dssdev, 3655static int dsi_update_screen_l4(struct omap_dss_device *dssdev,
2545 int x, int y, int w, int h) 3656 int x, int y, int w, int h)
2546{ 3657{
2547 /* Note: supports only 24bit colors in 32bit container */ 3658 /* Note: supports only 24bit colors in 32bit container */
3659 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3660 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2548 int first = 1; 3661 int first = 1;
2549 int fifo_stalls = 0; 3662 int fifo_stalls = 0;
2550 int max_dsi_packet_size; 3663 int max_dsi_packet_size;
@@ -2583,7 +3696,7 @@ static int dsi_update_screen_l4(struct omap_dss_device *dssdev,
2583 * in fifo */ 3696 * in fifo */
2584 3697
2585 /* When using CPU, max long packet size is TX buffer size */ 3698 /* When using CPU, max long packet size is TX buffer size */
2586 max_dsi_packet_size = dsi.vc[0].fifo_size * 32 * 4; 3699 max_dsi_packet_size = dsi->vc[0].fifo_size * 32 * 4;
2587 3700
2588 /* we seem to get better perf if we divide the tx fifo to half, 3701 /* we seem to get better perf if we divide the tx fifo to half,
2589 and while the other half is being sent, we fill the other half 3702 and while the other half is being sent, we fill the other half
@@ -2612,35 +3725,36 @@ static int dsi_update_screen_l4(struct omap_dss_device *dssdev,
2612#if 1 3725#if 1
2613 /* using fifo not empty */ 3726 /* using fifo not empty */
2614 /* TX_FIFO_NOT_EMPTY */ 3727 /* TX_FIFO_NOT_EMPTY */
2615 while (FLD_GET(dsi_read_reg(DSI_VC_CTRL(0)), 5, 5)) { 3728 while (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(0)), 5, 5)) {
2616 fifo_stalls++; 3729 fifo_stalls++;
2617 if (fifo_stalls > 0xfffff) { 3730 if (fifo_stalls > 0xfffff) {
2618 DSSERR("fifo stalls overflow, pixels left %d\n", 3731 DSSERR("fifo stalls overflow, pixels left %d\n",
2619 pixels_left); 3732 pixels_left);
2620 dsi_if_enable(0); 3733 dsi_if_enable(dsidev, 0);
2621 return -EIO; 3734 return -EIO;
2622 } 3735 }
2623 udelay(1); 3736 udelay(1);
2624 } 3737 }
2625#elif 1 3738#elif 1
2626 /* using fifo emptiness */ 3739 /* using fifo emptiness */
2627 while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 < 3740 while ((REG_GET(dsidev, DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 <
2628 max_dsi_packet_size) { 3741 max_dsi_packet_size) {
2629 fifo_stalls++; 3742 fifo_stalls++;
2630 if (fifo_stalls > 0xfffff) { 3743 if (fifo_stalls > 0xfffff) {
2631 DSSERR("fifo stalls overflow, pixels left %d\n", 3744 DSSERR("fifo stalls overflow, pixels left %d\n",
2632 pixels_left); 3745 pixels_left);
2633 dsi_if_enable(0); 3746 dsi_if_enable(dsidev, 0);
2634 return -EIO; 3747 return -EIO;
2635 } 3748 }
2636 } 3749 }
2637#else 3750#else
2638 while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 == 0) { 3751 while ((REG_GET(dsidev, DSI_TX_FIFO_VC_EMPTINESS,
3752 7, 0) + 1) * 4 == 0) {
2639 fifo_stalls++; 3753 fifo_stalls++;
2640 if (fifo_stalls > 0xfffff) { 3754 if (fifo_stalls > 0xfffff) {
2641 DSSERR("fifo stalls overflow, pixels left %d\n", 3755 DSSERR("fifo stalls overflow, pixels left %d\n",
2642 pixels_left); 3756 pixels_left);
2643 dsi_if_enable(0); 3757 dsi_if_enable(dsidev, 0);
2644 return -EIO; 3758 return -EIO;
2645 } 3759 }
2646 } 3760 }
@@ -2649,17 +3763,17 @@ static int dsi_update_screen_l4(struct omap_dss_device *dssdev,
2649 3763
2650 pixels_left -= pixels; 3764 pixels_left -= pixels;
2651 3765
2652 dsi_vc_write_long_header(0, DSI_DT_DCS_LONG_WRITE, 3766 dsi_vc_write_long_header(dsidev, 0, DSI_DT_DCS_LONG_WRITE,
2653 1 + pixels * bytespp, 0); 3767 1 + pixels * bytespp, 0);
2654 3768
2655 DSI_PUSH(0, dcs_cmd); 3769 DSI_PUSH(dsidev, 0, dcs_cmd);
2656 3770
2657 while (pixels-- > 0) { 3771 while (pixels-- > 0) {
2658 u32 pix = __raw_readl(data++); 3772 u32 pix = __raw_readl(data++);
2659 3773
2660 DSI_PUSH(0, (pix >> 16) & 0xff); 3774 DSI_PUSH(dsidev, 0, (pix >> 16) & 0xff);
2661 DSI_PUSH(0, (pix >> 8) & 0xff); 3775 DSI_PUSH(dsidev, 0, (pix >> 8) & 0xff);
2662 DSI_PUSH(0, (pix >> 0) & 0xff); 3776 DSI_PUSH(dsidev, 0, (pix >> 0) & 0xff);
2663 3777
2664 current_x++; 3778 current_x++;
2665 if (current_x == x+w) { 3779 if (current_x == x+w) {
@@ -2668,7 +3782,7 @@ static int dsi_update_screen_l4(struct omap_dss_device *dssdev,
2668 } 3782 }
2669 } 3783 }
2670 3784
2671 DSI_FLUSH(0); 3785 DSI_FLUSH(dsidev, 0);
2672 } 3786 }
2673 3787
2674 return 0; 3788 return 0;
@@ -2677,6 +3791,8 @@ static int dsi_update_screen_l4(struct omap_dss_device *dssdev,
2677static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, 3791static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
2678 u16 x, u16 y, u16 w, u16 h) 3792 u16 x, u16 y, u16 w, u16 h)
2679{ 3793{
3794 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3795 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2680 unsigned bytespp; 3796 unsigned bytespp;
2681 unsigned bytespl; 3797 unsigned bytespl;
2682 unsigned bytespf; 3798 unsigned bytespf;
@@ -2685,16 +3801,13 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
2685 unsigned packet_len; 3801 unsigned packet_len;
2686 u32 l; 3802 u32 l;
2687 int r; 3803 int r;
2688 const unsigned channel = dsi.update_channel; 3804 const unsigned channel = dsi->update_channel;
2689 /* line buffer is 1024 x 24bits */ 3805 const unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
2690 /* XXX: for some reason using full buffer size causes considerable TX
2691 * slowdown with update sizes that fill the whole buffer */
2692 const unsigned line_buf_size = 1023 * 3;
2693 3806
2694 DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n", 3807 DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",
2695 x, y, w, h); 3808 x, y, w, h);
2696 3809
2697 dsi_vc_config_vp(channel); 3810 dsi_vc_config_vp(dsidev, channel);
2698 3811
2699 bytespp = dssdev->ctrl.pixel_size / 8; 3812 bytespp = dssdev->ctrl.pixel_size / 8;
2700 bytespl = w * bytespp; 3813 bytespl = w * bytespp;
@@ -2715,15 +3828,16 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
2715 total_len += (bytespf % packet_payload) + 1; 3828 total_len += (bytespf % packet_payload) + 1;
2716 3829
2717 l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */ 3830 l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */
2718 dsi_write_reg(DSI_VC_TE(channel), l); 3831 dsi_write_reg(dsidev, DSI_VC_TE(channel), l);
2719 3832
2720 dsi_vc_write_long_header(channel, DSI_DT_DCS_LONG_WRITE, packet_len, 0); 3833 dsi_vc_write_long_header(dsidev, channel, DSI_DT_DCS_LONG_WRITE,
3834 packet_len, 0);
2721 3835
2722 if (dsi.te_enabled) 3836 if (dsi->te_enabled)
2723 l = FLD_MOD(l, 1, 30, 30); /* TE_EN */ 3837 l = FLD_MOD(l, 1, 30, 30); /* TE_EN */
2724 else 3838 else
2725 l = FLD_MOD(l, 1, 31, 31); /* TE_START */ 3839 l = FLD_MOD(l, 1, 31, 31); /* TE_START */
2726 dsi_write_reg(DSI_VC_TE(channel), l); 3840 dsi_write_reg(dsidev, DSI_VC_TE(channel), l);
2727 3841
2728 /* We put SIDLEMODE to no-idle for the duration of the transfer, 3842 /* We put SIDLEMODE to no-idle for the duration of the transfer,
2729 * because DSS interrupts are not capable of waking up the CPU and the 3843 * because DSS interrupts are not capable of waking up the CPU and the
@@ -2733,23 +3847,23 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
2733 */ 3847 */
2734 dispc_disable_sidle(); 3848 dispc_disable_sidle();
2735 3849
2736 dsi_perf_mark_start(); 3850 dsi_perf_mark_start(dsidev);
2737 3851
2738 r = queue_delayed_work(dsi.workqueue, &dsi.framedone_timeout_work, 3852 r = schedule_delayed_work(&dsi->framedone_timeout_work,
2739 msecs_to_jiffies(250)); 3853 msecs_to_jiffies(250));
2740 BUG_ON(r == 0); 3854 BUG_ON(r == 0);
2741 3855
2742 dss_start_update(dssdev); 3856 dss_start_update(dssdev);
2743 3857
2744 if (dsi.te_enabled) { 3858 if (dsi->te_enabled) {
2745 /* disable LP_RX_TO, so that we can receive TE. Time to wait 3859 /* disable LP_RX_TO, so that we can receive TE. Time to wait
2746 * for TE is longer than the timer allows */ 3860 * for TE is longer than the timer allows */
2747 REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */ 3861 REG_FLD_MOD(dsidev, DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */
2748 3862
2749 dsi_vc_send_bta(channel); 3863 dsi_vc_send_bta(dsidev, channel);
2750 3864
2751#ifdef DSI_CATCH_MISSING_TE 3865#ifdef DSI_CATCH_MISSING_TE
2752 mod_timer(&dsi.te_timer, jiffies + msecs_to_jiffies(250)); 3866 mod_timer(&dsi->te_timer, jiffies + msecs_to_jiffies(250));
2753#endif 3867#endif
2754 } 3868 }
2755} 3869}
@@ -2761,40 +3875,28 @@ static void dsi_te_timeout(unsigned long arg)
2761} 3875}
2762#endif 3876#endif
2763 3877
2764static void dsi_handle_framedone(int error) 3878static void dsi_handle_framedone(struct platform_device *dsidev, int error)
2765{ 3879{
2766 const int channel = dsi.update_channel; 3880 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2767
2768 cancel_delayed_work(&dsi.framedone_timeout_work);
2769
2770 dsi_vc_disable_bta_irq(channel);
2771 3881
2772 /* SIDLEMODE back to smart-idle */ 3882 /* SIDLEMODE back to smart-idle */
2773 dispc_enable_sidle(); 3883 dispc_enable_sidle();
2774 3884
2775 dsi.bta_callback = NULL; 3885 if (dsi->te_enabled) {
2776
2777 if (dsi.te_enabled) {
2778 /* enable LP_RX_TO again after the TE */ 3886 /* enable LP_RX_TO again after the TE */
2779 REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ 3887 REG_FLD_MOD(dsidev, DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
2780 }
2781
2782 /* RX_FIFO_NOT_EMPTY */
2783 if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
2784 DSSERR("Received error during frame transfer:\n");
2785 dsi_vc_flush_receive_data(channel);
2786 if (!error)
2787 error = -EIO;
2788 } 3888 }
2789 3889
2790 dsi.framedone_callback(error, dsi.framedone_data); 3890 dsi->framedone_callback(error, dsi->framedone_data);
2791 3891
2792 if (!error) 3892 if (!error)
2793 dsi_perf_show("DISPC"); 3893 dsi_perf_show(dsidev, "DISPC");
2794} 3894}
2795 3895
2796static void dsi_framedone_timeout_work_callback(struct work_struct *work) 3896static void dsi_framedone_timeout_work_callback(struct work_struct *work)
2797{ 3897{
3898 struct dsi_data *dsi = container_of(work, struct dsi_data,
3899 framedone_timeout_work.work);
2798 /* XXX While extremely unlikely, we could get FRAMEDONE interrupt after 3900 /* XXX While extremely unlikely, we could get FRAMEDONE interrupt after
2799 * 250ms which would conflict with this timeout work. What should be 3901 * 250ms which would conflict with this timeout work. What should be
2800 * done is first cancel the transfer on the HW, and then cancel the 3902 * done is first cancel the transfer on the HW, and then cancel the
@@ -2804,66 +3906,34 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work)
2804 3906
2805 DSSERR("Framedone not received for 250ms!\n"); 3907 DSSERR("Framedone not received for 250ms!\n");
2806 3908
2807 dsi_handle_framedone(-ETIMEDOUT); 3909 dsi_handle_framedone(dsi->pdev, -ETIMEDOUT);
2808}
2809
2810static void dsi_framedone_bta_callback(void)
2811{
2812 dsi_handle_framedone(0);
2813
2814#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
2815 dispc_fake_vsync_irq();
2816#endif
2817} 3910}
2818 3911
2819static void dsi_framedone_irq_callback(void *data, u32 mask) 3912static void dsi_framedone_irq_callback(void *data, u32 mask)
2820{ 3913{
2821 const int channel = dsi.update_channel; 3914 struct omap_dss_device *dssdev = (struct omap_dss_device *) data;
2822 int r; 3915 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3916 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2823 3917
2824 /* Note: We get FRAMEDONE when DISPC has finished sending pixels and 3918 /* Note: We get FRAMEDONE when DISPC has finished sending pixels and
2825 * turns itself off. However, DSI still has the pixels in its buffers, 3919 * turns itself off. However, DSI still has the pixels in its buffers,
2826 * and is sending the data. 3920 * and is sending the data.
2827 */ 3921 */
2828 3922
2829 if (dsi.te_enabled) { 3923 __cancel_delayed_work(&dsi->framedone_timeout_work);
2830 /* enable LP_RX_TO again after the TE */
2831 REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
2832 }
2833
2834 /* Send BTA after the frame. We need this for the TE to work, as TE
2835 * trigger is only sent for BTAs without preceding packet. Thus we need
2836 * to BTA after the pixel packets so that next BTA will cause TE
2837 * trigger.
2838 *
2839 * This is not needed when TE is not in use, but we do it anyway to
2840 * make sure that the transfer has been completed. It would be more
2841 * optimal, but more complex, to wait only just before starting next
2842 * transfer.
2843 *
2844 * Also, as there's no interrupt telling when the transfer has been
2845 * done and the channel could be reconfigured, the only way is to
2846 * busyloop until TE_SIZE is zero. With BTA we can do this
2847 * asynchronously.
2848 * */
2849
2850 dsi.bta_callback = dsi_framedone_bta_callback;
2851
2852 barrier();
2853 3924
2854 dsi_vc_enable_bta_irq(channel); 3925 dsi_handle_framedone(dsidev, 0);
2855 3926
2856 r = dsi_vc_send_bta(channel); 3927#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
2857 if (r) { 3928 dispc_fake_vsync_irq();
2858 DSSERR("BTA after framedone failed\n"); 3929#endif
2859 dsi_handle_framedone(-EIO);
2860 }
2861} 3930}
2862 3931
2863int omap_dsi_prepare_update(struct omap_dss_device *dssdev, 3932int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
2864 u16 *x, u16 *y, u16 *w, u16 *h, 3933 u16 *x, u16 *y, u16 *w, u16 *h,
2865 bool enlarge_update_area) 3934 bool enlarge_update_area)
2866{ 3935{
3936 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2867 u16 dw, dh; 3937 u16 dw, dh;
2868 3938
2869 dssdev->driver->get_resolution(dssdev, &dw, &dh); 3939 dssdev->driver->get_resolution(dssdev, &dw, &dh);
@@ -2883,12 +3953,12 @@ int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
2883 if (*w == 0 || *h == 0) 3953 if (*w == 0 || *h == 0)
2884 return -EINVAL; 3954 return -EINVAL;
2885 3955
2886 dsi_perf_mark_setup(); 3956 dsi_perf_mark_setup(dsidev);
2887 3957
2888 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { 3958 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
2889 dss_setup_partial_planes(dssdev, x, y, w, h, 3959 dss_setup_partial_planes(dssdev, x, y, w, h,
2890 enlarge_update_area); 3960 enlarge_update_area);
2891 dispc_set_lcd_size(*w, *h); 3961 dispc_set_lcd_size(dssdev->manager->id, *w, *h);
2892 } 3962 }
2893 3963
2894 return 0; 3964 return 0;
@@ -2900,7 +3970,10 @@ int omap_dsi_update(struct omap_dss_device *dssdev,
2900 u16 x, u16 y, u16 w, u16 h, 3970 u16 x, u16 y, u16 w, u16 h,
2901 void (*callback)(int, void *), void *data) 3971 void (*callback)(int, void *), void *data)
2902{ 3972{
2903 dsi.update_channel = channel; 3973 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3974 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3975
3976 dsi->update_channel = channel;
2904 3977
2905 /* OMAP DSS cannot send updates of odd widths. 3978 /* OMAP DSS cannot send updates of odd widths.
2906 * omap_dsi_prepare_update() makes the widths even, but add a BUG_ON 3979 * omap_dsi_prepare_update() makes the widths even, but add a BUG_ON
@@ -2909,14 +3982,14 @@ int omap_dsi_update(struct omap_dss_device *dssdev,
2909 BUG_ON(x % 2 == 1); 3982 BUG_ON(x % 2 == 1);
2910 3983
2911 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { 3984 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
2912 dsi.framedone_callback = callback; 3985 dsi->framedone_callback = callback;
2913 dsi.framedone_data = data; 3986 dsi->framedone_data = data;
2914 3987
2915 dsi.update_region.x = x; 3988 dsi->update_region.x = x;
2916 dsi.update_region.y = y; 3989 dsi->update_region.y = y;
2917 dsi.update_region.w = w; 3990 dsi->update_region.w = w;
2918 dsi.update_region.h = h; 3991 dsi->update_region.h = h;
2919 dsi.update_region.device = dssdev; 3992 dsi->update_region.device = dssdev;
2920 3993
2921 dsi_update_screen_dispc(dssdev, x, y, w, h); 3994 dsi_update_screen_dispc(dssdev, x, y, w, h);
2922 } else { 3995 } else {
@@ -2926,7 +3999,7 @@ int omap_dsi_update(struct omap_dss_device *dssdev,
2926 if (r) 3999 if (r)
2927 return r; 4000 return r;
2928 4001
2929 dsi_perf_show("L4"); 4002 dsi_perf_show(dsidev, "L4");
2930 callback(0, data); 4003 callback(0, data);
2931 } 4004 }
2932 4005
@@ -2939,20 +4012,26 @@ EXPORT_SYMBOL(omap_dsi_update);
2939static int dsi_display_init_dispc(struct omap_dss_device *dssdev) 4012static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
2940{ 4013{
2941 int r; 4014 int r;
4015 u32 irq;
4016
4017 irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ?
4018 DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2;
2942 4019
2943 r = omap_dispc_register_isr(dsi_framedone_irq_callback, NULL, 4020 r = omap_dispc_register_isr(dsi_framedone_irq_callback, (void *) dssdev,
2944 DISPC_IRQ_FRAMEDONE); 4021 irq);
2945 if (r) { 4022 if (r) {
2946 DSSERR("can't get FRAMEDONE irq\n"); 4023 DSSERR("can't get FRAMEDONE irq\n");
2947 return r; 4024 return r;
2948 } 4025 }
2949 4026
2950 dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT); 4027 dispc_set_lcd_display_type(dssdev->manager->id,
4028 OMAP_DSS_LCD_DISPLAY_TFT);
2951 4029
2952 dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_DSI); 4030 dispc_set_parallel_interface_mode(dssdev->manager->id,
2953 dispc_enable_fifohandcheck(1); 4031 OMAP_DSS_PARALLELMODE_DSI);
4032 dispc_enable_fifohandcheck(dssdev->manager->id, 1);
2954 4033
2955 dispc_set_tft_data_lines(dssdev->ctrl.pixel_size); 4034 dispc_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size);
2956 4035
2957 { 4036 {
2958 struct omap_video_timings timings = { 4037 struct omap_video_timings timings = {
@@ -2964,7 +4043,7 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
2964 .vbp = 0, 4043 .vbp = 0,
2965 }; 4044 };
2966 4045
2967 dispc_set_lcd_timings(&timings); 4046 dispc_set_lcd_timings(dssdev->manager->id, &timings);
2968 } 4047 }
2969 4048
2970 return 0; 4049 return 0;
@@ -2972,28 +4051,34 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
2972 4051
2973static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) 4052static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
2974{ 4053{
2975 omap_dispc_unregister_isr(dsi_framedone_irq_callback, NULL, 4054 u32 irq;
2976 DISPC_IRQ_FRAMEDONE); 4055
4056 irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ?
4057 DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2;
4058
4059 omap_dispc_unregister_isr(dsi_framedone_irq_callback, (void *) dssdev,
4060 irq);
2977} 4061}
2978 4062
2979static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) 4063static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
2980{ 4064{
4065 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2981 struct dsi_clock_info cinfo; 4066 struct dsi_clock_info cinfo;
2982 int r; 4067 int r;
2983 4068
2984 /* we always use DSS2_FCK as input clock */ 4069 /* we always use DSS_CLK_SYSCK as input clock */
2985 cinfo.use_dss2_fck = true; 4070 cinfo.use_sys_clk = true;
2986 cinfo.regn = dssdev->phy.dsi.div.regn; 4071 cinfo.regn = dssdev->clocks.dsi.regn;
2987 cinfo.regm = dssdev->phy.dsi.div.regm; 4072 cinfo.regm = dssdev->clocks.dsi.regm;
2988 cinfo.regm3 = dssdev->phy.dsi.div.regm3; 4073 cinfo.regm_dispc = dssdev->clocks.dsi.regm_dispc;
2989 cinfo.regm4 = dssdev->phy.dsi.div.regm4; 4074 cinfo.regm_dsi = dssdev->clocks.dsi.regm_dsi;
2990 r = dsi_calc_clock_rates(&cinfo); 4075 r = dsi_calc_clock_rates(dssdev, &cinfo);
2991 if (r) { 4076 if (r) {
2992 DSSERR("Failed to calc dsi clocks\n"); 4077 DSSERR("Failed to calc dsi clocks\n");
2993 return r; 4078 return r;
2994 } 4079 }
2995 4080
2996 r = dsi_pll_set_clock_div(&cinfo); 4081 r = dsi_pll_set_clock_div(dsidev, &cinfo);
2997 if (r) { 4082 if (r) {
2998 DSSERR("Failed to set dsi clocks\n"); 4083 DSSERR("Failed to set dsi clocks\n");
2999 return r; 4084 return r;
@@ -3004,14 +4089,15 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
3004 4089
3005static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) 4090static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev)
3006{ 4091{
4092 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3007 struct dispc_clock_info dispc_cinfo; 4093 struct dispc_clock_info dispc_cinfo;
3008 int r; 4094 int r;
3009 unsigned long long fck; 4095 unsigned long long fck;
3010 4096
3011 fck = dsi_get_dsi1_pll_rate(); 4097 fck = dsi_get_pll_hsdiv_dispc_rate(dsidev);
3012 4098
3013 dispc_cinfo.lck_div = dssdev->phy.dsi.div.lck_div; 4099 dispc_cinfo.lck_div = dssdev->clocks.dispc.channel.lck_div;
3014 dispc_cinfo.pck_div = dssdev->phy.dsi.div.pck_div; 4100 dispc_cinfo.pck_div = dssdev->clocks.dispc.channel.pck_div;
3015 4101
3016 r = dispc_calc_clock_rates(fck, &dispc_cinfo); 4102 r = dispc_calc_clock_rates(fck, &dispc_cinfo);
3017 if (r) { 4103 if (r) {
@@ -3019,7 +4105,7 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev)
3019 return r; 4105 return r;
3020 } 4106 }
3021 4107
3022 r = dispc_set_clock_div(&dispc_cinfo); 4108 r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
3023 if (r) { 4109 if (r) {
3024 DSSERR("Failed to set dispc clocks\n"); 4110 DSSERR("Failed to set dispc clocks\n");
3025 return r; 4111 return r;
@@ -3030,11 +4116,11 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev)
3030 4116
3031static int dsi_display_init_dsi(struct omap_dss_device *dssdev) 4117static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
3032{ 4118{
4119 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4120 int dsi_module = dsi_get_dsidev_id(dsidev);
3033 int r; 4121 int r;
3034 4122
3035 _dsi_print_reset_status(); 4123 r = dsi_pll_init(dsidev, true, true);
3036
3037 r = dsi_pll_init(dssdev, true, true);
3038 if (r) 4124 if (r)
3039 goto err0; 4125 goto err0;
3040 4126
@@ -3042,8 +4128,10 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
3042 if (r) 4128 if (r)
3043 goto err1; 4129 goto err1;
3044 4130
3045 dss_select_dispc_clk_source(DSS_SRC_DSI1_PLL_FCLK); 4131 dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
3046 dss_select_dsi_clk_source(DSS_SRC_DSI2_PLL_FCLK); 4132 dss_select_dsi_clk_source(dsi_module, dssdev->clocks.dsi.dsi_fclk_src);
4133 dss_select_lcd_clk_source(dssdev->manager->id,
4134 dssdev->clocks.dispc.channel.lcd_clk_src);
3047 4135
3048 DSSDBG("PLL OK\n"); 4136 DSSDBG("PLL OK\n");
3049 4137
@@ -3051,82 +4139,92 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
3051 if (r) 4139 if (r)
3052 goto err2; 4140 goto err2;
3053 4141
3054 r = dsi_complexio_init(dssdev); 4142 r = dsi_cio_init(dssdev);
3055 if (r) 4143 if (r)
3056 goto err2; 4144 goto err2;
3057 4145
3058 _dsi_print_reset_status(); 4146 _dsi_print_reset_status(dsidev);
3059 4147
3060 dsi_proto_timings(dssdev); 4148 dsi_proto_timings(dssdev);
3061 dsi_set_lp_clk_divisor(dssdev); 4149 dsi_set_lp_clk_divisor(dssdev);
3062 4150
3063 if (1) 4151 if (1)
3064 _dsi_print_reset_status(); 4152 _dsi_print_reset_status(dsidev);
3065 4153
3066 r = dsi_proto_config(dssdev); 4154 r = dsi_proto_config(dssdev);
3067 if (r) 4155 if (r)
3068 goto err3; 4156 goto err3;
3069 4157
3070 /* enable interface */ 4158 /* enable interface */
3071 dsi_vc_enable(0, 1); 4159 dsi_vc_enable(dsidev, 0, 1);
3072 dsi_vc_enable(1, 1); 4160 dsi_vc_enable(dsidev, 1, 1);
3073 dsi_vc_enable(2, 1); 4161 dsi_vc_enable(dsidev, 2, 1);
3074 dsi_vc_enable(3, 1); 4162 dsi_vc_enable(dsidev, 3, 1);
3075 dsi_if_enable(1); 4163 dsi_if_enable(dsidev, 1);
3076 dsi_force_tx_stop_mode_io(); 4164 dsi_force_tx_stop_mode_io(dsidev);
3077 4165
3078 return 0; 4166 return 0;
3079err3: 4167err3:
3080 dsi_complexio_uninit(); 4168 dsi_cio_uninit(dsidev);
3081err2: 4169err2:
3082 dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK); 4170 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
3083 dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK); 4171 dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK);
3084err1: 4172err1:
3085 dsi_pll_uninit(); 4173 dsi_pll_uninit(dsidev, true);
3086err0: 4174err0:
3087 return r; 4175 return r;
3088} 4176}
3089 4177
3090static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev) 4178static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
4179 bool disconnect_lanes, bool enter_ulps)
3091{ 4180{
3092 /* disable interface */ 4181 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3093 dsi_if_enable(0); 4182 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3094 dsi_vc_enable(0, 0); 4183 int dsi_module = dsi_get_dsidev_id(dsidev);
3095 dsi_vc_enable(1, 0); 4184
3096 dsi_vc_enable(2, 0); 4185 if (enter_ulps && !dsi->ulps_enabled)
3097 dsi_vc_enable(3, 0); 4186 dsi_enter_ulps(dsidev);
3098 4187
3099 dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK); 4188 /* disable interface */
3100 dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK); 4189 dsi_if_enable(dsidev, 0);
3101 dsi_complexio_uninit(); 4190 dsi_vc_enable(dsidev, 0, 0);
3102 dsi_pll_uninit(); 4191 dsi_vc_enable(dsidev, 1, 0);
4192 dsi_vc_enable(dsidev, 2, 0);
4193 dsi_vc_enable(dsidev, 3, 0);
4194
4195 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
4196 dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK);
4197 dsi_cio_uninit(dsidev);
4198 dsi_pll_uninit(dsidev, disconnect_lanes);
3103} 4199}
3104 4200
3105static int dsi_core_init(void) 4201static int dsi_core_init(struct platform_device *dsidev)
3106{ 4202{
3107 /* Autoidle */ 4203 /* Autoidle */
3108 REG_FLD_MOD(DSI_SYSCONFIG, 1, 0, 0); 4204 REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 0, 0);
3109 4205
3110 /* ENWAKEUP */ 4206 /* ENWAKEUP */
3111 REG_FLD_MOD(DSI_SYSCONFIG, 1, 2, 2); 4207 REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 2, 2);
3112 4208
3113 /* SIDLEMODE smart-idle */ 4209 /* SIDLEMODE smart-idle */
3114 REG_FLD_MOD(DSI_SYSCONFIG, 2, 4, 3); 4210 REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 2, 4, 3);
3115 4211
3116 _dsi_initialize_irq(); 4212 _dsi_initialize_irq(dsidev);
3117 4213
3118 return 0; 4214 return 0;
3119} 4215}
3120 4216
3121int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) 4217int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
3122{ 4218{
4219 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4220 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3123 int r = 0; 4221 int r = 0;
3124 4222
3125 DSSDBG("dsi_display_enable\n"); 4223 DSSDBG("dsi_display_enable\n");
3126 4224
3127 WARN_ON(!dsi_bus_is_locked()); 4225 WARN_ON(!dsi_bus_is_locked(dsidev));
3128 4226
3129 mutex_lock(&dsi.lock); 4227 mutex_lock(&dsi->lock);
3130 4228
3131 r = omap_dss_start_device(dssdev); 4229 r = omap_dss_start_device(dssdev);
3132 if (r) { 4230 if (r) {
@@ -3135,13 +4233,13 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
3135 } 4233 }
3136 4234
3137 enable_clocks(1); 4235 enable_clocks(1);
3138 dsi_enable_pll_clock(1); 4236 dsi_enable_pll_clock(dsidev, 1);
3139 4237
3140 r = _dsi_reset(); 4238 r = _dsi_reset(dsidev);
3141 if (r) 4239 if (r)
3142 goto err1; 4240 goto err1;
3143 4241
3144 dsi_core_init(); 4242 dsi_core_init(dsidev);
3145 4243
3146 r = dsi_display_init_dispc(dssdev); 4244 r = dsi_display_init_dispc(dssdev);
3147 if (r) 4245 if (r)
@@ -3151,7 +4249,7 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
3151 if (r) 4249 if (r)
3152 goto err2; 4250 goto err2;
3153 4251
3154 mutex_unlock(&dsi.lock); 4252 mutex_unlock(&dsi->lock);
3155 4253
3156 return 0; 4254 return 0;
3157 4255
@@ -3159,39 +4257,46 @@ err2:
3159 dsi_display_uninit_dispc(dssdev); 4257 dsi_display_uninit_dispc(dssdev);
3160err1: 4258err1:
3161 enable_clocks(0); 4259 enable_clocks(0);
3162 dsi_enable_pll_clock(0); 4260 dsi_enable_pll_clock(dsidev, 0);
3163 omap_dss_stop_device(dssdev); 4261 omap_dss_stop_device(dssdev);
3164err0: 4262err0:
3165 mutex_unlock(&dsi.lock); 4263 mutex_unlock(&dsi->lock);
3166 DSSDBG("dsi_display_enable FAILED\n"); 4264 DSSDBG("dsi_display_enable FAILED\n");
3167 return r; 4265 return r;
3168} 4266}
3169EXPORT_SYMBOL(omapdss_dsi_display_enable); 4267EXPORT_SYMBOL(omapdss_dsi_display_enable);
3170 4268
3171void omapdss_dsi_display_disable(struct omap_dss_device *dssdev) 4269void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
4270 bool disconnect_lanes, bool enter_ulps)
3172{ 4271{
4272 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4273 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4274
3173 DSSDBG("dsi_display_disable\n"); 4275 DSSDBG("dsi_display_disable\n");
3174 4276
3175 WARN_ON(!dsi_bus_is_locked()); 4277 WARN_ON(!dsi_bus_is_locked(dsidev));
3176 4278
3177 mutex_lock(&dsi.lock); 4279 mutex_lock(&dsi->lock);
3178 4280
3179 dsi_display_uninit_dispc(dssdev); 4281 dsi_display_uninit_dispc(dssdev);
3180 4282
3181 dsi_display_uninit_dsi(dssdev); 4283 dsi_display_uninit_dsi(dssdev, disconnect_lanes, enter_ulps);
3182 4284
3183 enable_clocks(0); 4285 enable_clocks(0);
3184 dsi_enable_pll_clock(0); 4286 dsi_enable_pll_clock(dsidev, 0);
3185 4287
3186 omap_dss_stop_device(dssdev); 4288 omap_dss_stop_device(dssdev);
3187 4289
3188 mutex_unlock(&dsi.lock); 4290 mutex_unlock(&dsi->lock);
3189} 4291}
3190EXPORT_SYMBOL(omapdss_dsi_display_disable); 4292EXPORT_SYMBOL(omapdss_dsi_display_disable);
3191 4293
3192int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable) 4294int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
3193{ 4295{
3194 dsi.te_enabled = enable; 4296 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4297 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4298
4299 dsi->te_enabled = enable;
3195 return 0; 4300 return 0;
3196} 4301}
3197EXPORT_SYMBOL(omapdss_dsi_enable_te); 4302EXPORT_SYMBOL(omapdss_dsi_enable_te);
@@ -3211,97 +4316,284 @@ void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
3211 4316
3212int dsi_init_display(struct omap_dss_device *dssdev) 4317int dsi_init_display(struct omap_dss_device *dssdev)
3213{ 4318{
4319 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4320 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4321 int dsi_module = dsi_get_dsidev_id(dsidev);
4322
3214 DSSDBG("DSI init\n"); 4323 DSSDBG("DSI init\n");
3215 4324
3216 /* XXX these should be figured out dynamically */ 4325 /* XXX these should be figured out dynamically */
3217 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | 4326 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
3218 OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; 4327 OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
3219 4328
3220 dsi.vc[0].dssdev = dssdev; 4329 if (dsi->vdds_dsi_reg == NULL) {
3221 dsi.vc[1].dssdev = dssdev; 4330 struct regulator *vdds_dsi;
4331
4332 vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi");
4333
4334 if (IS_ERR(vdds_dsi)) {
4335 DSSERR("can't get VDDS_DSI regulator\n");
4336 return PTR_ERR(vdds_dsi);
4337 }
4338
4339 dsi->vdds_dsi_reg = vdds_dsi;
4340 }
4341
4342 if (dsi_get_num_data_lanes_dssdev(dssdev) > dsi->num_data_lanes) {
4343 DSSERR("DSI%d can't support more than %d data lanes\n",
4344 dsi_module + 1, dsi->num_data_lanes);
4345 return -EINVAL;
4346 }
4347
4348 return 0;
4349}
4350
4351int omap_dsi_request_vc(struct omap_dss_device *dssdev, int *channel)
4352{
4353 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4354 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4355 int i;
4356
4357 for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) {
4358 if (!dsi->vc[i].dssdev) {
4359 dsi->vc[i].dssdev = dssdev;
4360 *channel = i;
4361 return 0;
4362 }
4363 }
4364
4365 DSSERR("cannot get VC for display %s", dssdev->name);
4366 return -ENOSPC;
4367}
4368EXPORT_SYMBOL(omap_dsi_request_vc);
4369
4370int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id)
4371{
4372 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4373 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4374
4375 if (vc_id < 0 || vc_id > 3) {
4376 DSSERR("VC ID out of range\n");
4377 return -EINVAL;
4378 }
4379
4380 if (channel < 0 || channel > 3) {
4381 DSSERR("Virtual Channel out of range\n");
4382 return -EINVAL;
4383 }
4384
4385 if (dsi->vc[channel].dssdev != dssdev) {
4386 DSSERR("Virtual Channel not allocated to display %s\n",
4387 dssdev->name);
4388 return -EINVAL;
4389 }
4390
4391 dsi->vc[channel].vc_id = vc_id;
3222 4392
3223 return 0; 4393 return 0;
3224} 4394}
4395EXPORT_SYMBOL(omap_dsi_set_vc_id);
4396
4397void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel)
4398{
4399 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4400 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4401
4402 if ((channel >= 0 && channel <= 3) &&
4403 dsi->vc[channel].dssdev == dssdev) {
4404 dsi->vc[channel].dssdev = NULL;
4405 dsi->vc[channel].vc_id = 0;
4406 }
4407}
4408EXPORT_SYMBOL(omap_dsi_release_vc);
4409
4410void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev)
4411{
4412 if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 7, 1) != 1)
4413 DSSERR("%s (%s) not active\n",
4414 dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
4415 dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC));
4416}
3225 4417
3226void dsi_wait_dsi1_pll_active(void) 4418void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev)
3227{ 4419{
3228 if (wait_for_bit_change(DSI_PLL_STATUS, 7, 1) != 1) 4420 if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 8, 1) != 1)
3229 DSSERR("DSI1 PLL clock not active\n"); 4421 DSSERR("%s (%s) not active\n",
4422 dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
4423 dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI));
3230} 4424}
3231 4425
3232void dsi_wait_dsi2_pll_active(void) 4426static void dsi_calc_clock_param_ranges(struct platform_device *dsidev)
3233{ 4427{
3234 if (wait_for_bit_change(DSI_PLL_STATUS, 8, 1) != 1) 4428 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3235 DSSERR("DSI2 PLL clock not active\n"); 4429
4430 dsi->regn_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGN);
4431 dsi->regm_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM);
4432 dsi->regm_dispc_max =
4433 dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DISPC);
4434 dsi->regm_dsi_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DSI);
4435 dsi->fint_min = dss_feat_get_param_min(FEAT_PARAM_DSIPLL_FINT);
4436 dsi->fint_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_FINT);
4437 dsi->lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV);
3236} 4438}
3237 4439
3238int dsi_init(struct platform_device *pdev) 4440static int dsi_init(struct platform_device *dsidev)
3239{ 4441{
4442 struct omap_display_platform_data *dss_plat_data;
4443 struct omap_dss_board_info *board_info;
3240 u32 rev; 4444 u32 rev;
3241 int r; 4445 int r, i, dsi_module = dsi_get_dsidev_id(dsidev);
4446 struct resource *dsi_mem;
4447 struct dsi_data *dsi;
3242 4448
3243 spin_lock_init(&dsi.errors_lock); 4449 dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
3244 dsi.errors = 0; 4450 if (!dsi) {
4451 r = -ENOMEM;
4452 goto err0;
4453 }
3245 4454
3246#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 4455 dsi->pdev = dsidev;
3247 spin_lock_init(&dsi.irq_stats_lock); 4456 dsi_pdev_map[dsi_module] = dsidev;
3248 dsi.irq_stats.last_reset = jiffies; 4457 dev_set_drvdata(&dsidev->dev, dsi);
3249#endif
3250 4458
3251 init_completion(&dsi.bta_completion); 4459 dss_plat_data = dsidev->dev.platform_data;
4460 board_info = dss_plat_data->board_data;
4461 dsi->dsi_mux_pads = board_info->dsi_mux_pads;
3252 4462
3253 mutex_init(&dsi.lock); 4463 spin_lock_init(&dsi->irq_lock);
3254 sema_init(&dsi.bus_lock, 1); 4464 spin_lock_init(&dsi->errors_lock);
4465 dsi->errors = 0;
3255 4466
3256 dsi.workqueue = create_singlethread_workqueue("dsi"); 4467#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
3257 if (dsi.workqueue == NULL) 4468 spin_lock_init(&dsi->irq_stats_lock);
3258 return -ENOMEM; 4469 dsi->irq_stats.last_reset = jiffies;
4470#endif
3259 4471
3260 INIT_DELAYED_WORK_DEFERRABLE(&dsi.framedone_timeout_work, 4472 mutex_init(&dsi->lock);
4473 sema_init(&dsi->bus_lock, 1);
4474
4475 INIT_DELAYED_WORK_DEFERRABLE(&dsi->framedone_timeout_work,
3261 dsi_framedone_timeout_work_callback); 4476 dsi_framedone_timeout_work_callback);
3262 4477
3263#ifdef DSI_CATCH_MISSING_TE 4478#ifdef DSI_CATCH_MISSING_TE
3264 init_timer(&dsi.te_timer); 4479 init_timer(&dsi->te_timer);
3265 dsi.te_timer.function = dsi_te_timeout; 4480 dsi->te_timer.function = dsi_te_timeout;
3266 dsi.te_timer.data = 0; 4481 dsi->te_timer.data = 0;
3267#endif 4482#endif
3268 dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS); 4483 dsi_mem = platform_get_resource(dsi->pdev, IORESOURCE_MEM, 0);
3269 if (!dsi.base) { 4484 if (!dsi_mem) {
4485 DSSERR("can't get IORESOURCE_MEM DSI\n");
4486 r = -EINVAL;
4487 goto err1;
4488 }
4489 dsi->base = ioremap(dsi_mem->start, resource_size(dsi_mem));
4490 if (!dsi->base) {
3270 DSSERR("can't ioremap DSI\n"); 4491 DSSERR("can't ioremap DSI\n");
3271 r = -ENOMEM; 4492 r = -ENOMEM;
3272 goto err1; 4493 goto err1;
3273 } 4494 }
4495 dsi->irq = platform_get_irq(dsi->pdev, 0);
4496 if (dsi->irq < 0) {
4497 DSSERR("platform_get_irq failed\n");
4498 r = -ENODEV;
4499 goto err2;
4500 }
3274 4501
3275 dsi.vdds_dsi_reg = dss_get_vdds_dsi(); 4502 r = request_irq(dsi->irq, omap_dsi_irq_handler, IRQF_SHARED,
3276 if (IS_ERR(dsi.vdds_dsi_reg)) { 4503 dev_name(&dsidev->dev), dsi->pdev);
3277 iounmap(dsi.base); 4504 if (r < 0) {
3278 DSSERR("can't get VDDS_DSI regulator\n"); 4505 DSSERR("request_irq failed\n");
3279 r = PTR_ERR(dsi.vdds_dsi_reg);
3280 goto err2; 4506 goto err2;
3281 } 4507 }
3282 4508
4509 /* DSI VCs initialization */
4510 for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) {
4511 dsi->vc[i].mode = DSI_VC_MODE_L4;
4512 dsi->vc[i].dssdev = NULL;
4513 dsi->vc[i].vc_id = 0;
4514 }
4515
4516 dsi_calc_clock_param_ranges(dsidev);
4517
3283 enable_clocks(1); 4518 enable_clocks(1);
3284 4519
3285 rev = dsi_read_reg(DSI_REVISION); 4520 rev = dsi_read_reg(dsidev, DSI_REVISION);
3286 printk(KERN_INFO "OMAP DSI rev %d.%d\n", 4521 dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n",
3287 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); 4522 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
3288 4523
4524 dsi->num_data_lanes = dsi_get_num_data_lanes(dsidev);
4525
3289 enable_clocks(0); 4526 enable_clocks(0);
3290 4527
3291 return 0; 4528 return 0;
3292err2: 4529err2:
3293 iounmap(dsi.base); 4530 iounmap(dsi->base);
3294err1: 4531err1:
3295 destroy_workqueue(dsi.workqueue); 4532 kfree(dsi);
4533err0:
3296 return r; 4534 return r;
3297} 4535}
3298 4536
3299void dsi_exit(void) 4537static void dsi_exit(struct platform_device *dsidev)
3300{ 4538{
3301 iounmap(dsi.base); 4539 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4540
4541 if (dsi->vdds_dsi_reg != NULL) {
4542 if (dsi->vdds_dsi_enabled) {
4543 regulator_disable(dsi->vdds_dsi_reg);
4544 dsi->vdds_dsi_enabled = false;
4545 }
4546
4547 regulator_put(dsi->vdds_dsi_reg);
4548 dsi->vdds_dsi_reg = NULL;
4549 }
3302 4550
3303 destroy_workqueue(dsi.workqueue); 4551 free_irq(dsi->irq, dsi->pdev);
4552 iounmap(dsi->base);
4553
4554 kfree(dsi);
3304 4555
3305 DSSDBG("omap_dsi_exit\n"); 4556 DSSDBG("omap_dsi_exit\n");
3306} 4557}
3307 4558
4559/* DSI1 HW IP initialisation */
4560static int omap_dsi1hw_probe(struct platform_device *dsidev)
4561{
4562 int r;
4563
4564 r = dsi_init(dsidev);
4565 if (r) {
4566 DSSERR("Failed to initialize DSI\n");
4567 goto err_dsi;
4568 }
4569err_dsi:
4570 return r;
4571}
4572
4573static int omap_dsi1hw_remove(struct platform_device *dsidev)
4574{
4575 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4576
4577 dsi_exit(dsidev);
4578 WARN_ON(dsi->scp_clk_refcount > 0);
4579 return 0;
4580}
4581
4582static struct platform_driver omap_dsi1hw_driver = {
4583 .probe = omap_dsi1hw_probe,
4584 .remove = omap_dsi1hw_remove,
4585 .driver = {
4586 .name = "omapdss_dsi1",
4587 .owner = THIS_MODULE,
4588 },
4589};
4590
4591int dsi_init_platform_driver(void)
4592{
4593 return platform_driver_register(&omap_dsi1hw_driver);
4594}
4595
4596void dsi_uninit_platform_driver(void)
4597{
4598 return platform_driver_unregister(&omap_dsi1hw_driver);
4599}
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 77c3621c9171..d9489d5c4f08 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -26,14 +26,13 @@
26#include <linux/io.h> 26#include <linux/io.h>
27#include <linux/err.h> 27#include <linux/err.h>
28#include <linux/delay.h> 28#include <linux/delay.h>
29#include <linux/interrupt.h>
30#include <linux/seq_file.h> 29#include <linux/seq_file.h>
31#include <linux/clk.h> 30#include <linux/clk.h>
32 31
33#include <plat/display.h> 32#include <video/omapdss.h>
33#include <plat/clock.h>
34#include "dss.h" 34#include "dss.h"
35 35#include "dss_features.h"
36#define DSS_BASE 0x48050000
37 36
38#define DSS_SZ_REGS SZ_512 37#define DSS_SZ_REGS SZ_512
39 38
@@ -46,7 +45,6 @@ struct dss_reg {
46#define DSS_REVISION DSS_REG(0x0000) 45#define DSS_REVISION DSS_REG(0x0000)
47#define DSS_SYSCONFIG DSS_REG(0x0010) 46#define DSS_SYSCONFIG DSS_REG(0x0010)
48#define DSS_SYSSTATUS DSS_REG(0x0014) 47#define DSS_SYSSTATUS DSS_REG(0x0014)
49#define DSS_IRQSTATUS DSS_REG(0x0018)
50#define DSS_CONTROL DSS_REG(0x0040) 48#define DSS_CONTROL DSS_REG(0x0040)
51#define DSS_SDI_CONTROL DSS_REG(0x0044) 49#define DSS_SDI_CONTROL DSS_REG(0x0044)
52#define DSS_PLL_CONTROL DSS_REG(0x0048) 50#define DSS_PLL_CONTROL DSS_REG(0x0048)
@@ -59,21 +57,41 @@ struct dss_reg {
59 dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end)) 57 dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
60 58
61static struct { 59static struct {
60 struct platform_device *pdev;
62 void __iomem *base; 61 void __iomem *base;
62 int ctx_id;
63 63
64 struct clk *dpll4_m4_ck; 64 struct clk *dpll4_m4_ck;
65 struct clk *dss_ick;
66 struct clk *dss_fck;
67 struct clk *dss_sys_clk;
68 struct clk *dss_tv_fck;
69 struct clk *dss_video_fck;
70 unsigned num_clks_enabled;
65 71
66 unsigned long cache_req_pck; 72 unsigned long cache_req_pck;
67 unsigned long cache_prate; 73 unsigned long cache_prate;
68 struct dss_clock_info cache_dss_cinfo; 74 struct dss_clock_info cache_dss_cinfo;
69 struct dispc_clock_info cache_dispc_cinfo; 75 struct dispc_clock_info cache_dispc_cinfo;
70 76
71 enum dss_clk_source dsi_clk_source; 77 enum omap_dss_clk_source dsi_clk_source[MAX_NUM_DSI];
72 enum dss_clk_source dispc_clk_source; 78 enum omap_dss_clk_source dispc_clk_source;
79 enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
73 80
74 u32 ctx[DSS_SZ_REGS / sizeof(u32)]; 81 u32 ctx[DSS_SZ_REGS / sizeof(u32)];
75} dss; 82} dss;
76 83
84static const char * const dss_generic_clk_source_names[] = {
85 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC",
86 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI",
87 [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK",
88};
89
90static void dss_clk_enable_all_no_ctx(void);
91static void dss_clk_disable_all_no_ctx(void);
92static void dss_clk_enable_no_ctx(enum dss_clock clks);
93static void dss_clk_disable_no_ctx(enum dss_clock clks);
94
77static int _omap_dss_wait_reset(void); 95static int _omap_dss_wait_reset(void);
78 96
79static inline void dss_write_reg(const struct dss_reg idx, u32 val) 97static inline void dss_write_reg(const struct dss_reg idx, u32 val)
@@ -99,10 +117,11 @@ void dss_save_context(void)
99 SR(SYSCONFIG); 117 SR(SYSCONFIG);
100 SR(CONTROL); 118 SR(CONTROL);
101 119
102#ifdef CONFIG_OMAP2_DSS_SDI 120 if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
103 SR(SDI_CONTROL); 121 OMAP_DISPLAY_TYPE_SDI) {
104 SR(PLL_CONTROL); 122 SR(SDI_CONTROL);
105#endif 123 SR(PLL_CONTROL);
124 }
106} 125}
107 126
108void dss_restore_context(void) 127void dss_restore_context(void)
@@ -113,10 +132,11 @@ void dss_restore_context(void)
113 RR(SYSCONFIG); 132 RR(SYSCONFIG);
114 RR(CONTROL); 133 RR(CONTROL);
115 134
116#ifdef CONFIG_OMAP2_DSS_SDI 135 if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
117 RR(SDI_CONTROL); 136 OMAP_DISPLAY_TYPE_SDI) {
118 RR(PLL_CONTROL); 137 RR(SDI_CONTROL);
119#endif 138 RR(PLL_CONTROL);
139 }
120} 140}
121 141
122#undef SR 142#undef SR
@@ -209,125 +229,235 @@ void dss_sdi_disable(void)
209 REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */ 229 REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
210} 230}
211 231
232const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
233{
234 return dss_generic_clk_source_names[clk_src];
235}
236
212void dss_dump_clocks(struct seq_file *s) 237void dss_dump_clocks(struct seq_file *s)
213{ 238{
214 unsigned long dpll4_ck_rate; 239 unsigned long dpll4_ck_rate;
215 unsigned long dpll4_m4_ck_rate; 240 unsigned long dpll4_m4_ck_rate;
241 const char *fclk_name, *fclk_real_name;
242 unsigned long fclk_rate;
216 243
217 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); 244 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
218
219 dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
220 dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck);
221 245
222 seq_printf(s, "- DSS -\n"); 246 seq_printf(s, "- DSS -\n");
223 247
224 seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate); 248 fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
249 fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
250 fclk_rate = dss_clk_get_rate(DSS_CLK_FCK);
225 251
226 if (cpu_is_omap3630()) 252 if (dss.dpll4_m4_ck) {
227 seq_printf(s, "dss1_alwon_fclk = %lu / %lu = %lu\n", 253 dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
228 dpll4_ck_rate, 254 dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck);
229 dpll4_ck_rate / dpll4_m4_ck_rate, 255
230 dss_clk_get_rate(DSS_CLK_FCK1)); 256 seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
231 else
232 seq_printf(s, "dss1_alwon_fclk = %lu / %lu * 2 = %lu\n",
233 dpll4_ck_rate,
234 dpll4_ck_rate / dpll4_m4_ck_rate,
235 dss_clk_get_rate(DSS_CLK_FCK1));
236 257
237 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); 258 if (cpu_is_omap3630() || cpu_is_omap44xx())
259 seq_printf(s, "%s (%s) = %lu / %lu = %lu\n",
260 fclk_name, fclk_real_name,
261 dpll4_ck_rate,
262 dpll4_ck_rate / dpll4_m4_ck_rate,
263 fclk_rate);
264 else
265 seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n",
266 fclk_name, fclk_real_name,
267 dpll4_ck_rate,
268 dpll4_ck_rate / dpll4_m4_ck_rate,
269 fclk_rate);
270 } else {
271 seq_printf(s, "%s (%s) = %lu\n",
272 fclk_name, fclk_real_name,
273 fclk_rate);
274 }
275
276 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
238} 277}
239 278
240void dss_dump_regs(struct seq_file *s) 279void dss_dump_regs(struct seq_file *s)
241{ 280{
242#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r)) 281#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
243 282
244 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); 283 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
245 284
246 DUMPREG(DSS_REVISION); 285 DUMPREG(DSS_REVISION);
247 DUMPREG(DSS_SYSCONFIG); 286 DUMPREG(DSS_SYSCONFIG);
248 DUMPREG(DSS_SYSSTATUS); 287 DUMPREG(DSS_SYSSTATUS);
249 DUMPREG(DSS_IRQSTATUS);
250 DUMPREG(DSS_CONTROL); 288 DUMPREG(DSS_CONTROL);
251 DUMPREG(DSS_SDI_CONTROL);
252 DUMPREG(DSS_PLL_CONTROL);
253 DUMPREG(DSS_SDI_STATUS);
254 289
255 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); 290 if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
291 OMAP_DISPLAY_TYPE_SDI) {
292 DUMPREG(DSS_SDI_CONTROL);
293 DUMPREG(DSS_PLL_CONTROL);
294 DUMPREG(DSS_SDI_STATUS);
295 }
296
297 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
256#undef DUMPREG 298#undef DUMPREG
257} 299}
258 300
259void dss_select_dispc_clk_source(enum dss_clk_source clk_src) 301void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
260{ 302{
303 struct platform_device *dsidev;
261 int b; 304 int b;
305 u8 start, end;
306
307 switch (clk_src) {
308 case OMAP_DSS_CLK_SRC_FCK:
309 b = 0;
310 break;
311 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
312 b = 1;
313 dsidev = dsi_get_dsidev_from_id(0);
314 dsi_wait_pll_hsdiv_dispc_active(dsidev);
315 break;
316 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
317 b = 2;
318 dsidev = dsi_get_dsidev_from_id(1);
319 dsi_wait_pll_hsdiv_dispc_active(dsidev);
320 break;
321 default:
322 BUG();
323 }
262 324
263 BUG_ON(clk_src != DSS_SRC_DSI1_PLL_FCLK && 325 dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH, &start, &end);
264 clk_src != DSS_SRC_DSS1_ALWON_FCLK);
265
266 b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1;
267
268 if (clk_src == DSS_SRC_DSI1_PLL_FCLK)
269 dsi_wait_dsi1_pll_active();
270 326
271 REG_FLD_MOD(DSS_CONTROL, b, 0, 0); /* DISPC_CLK_SWITCH */ 327 REG_FLD_MOD(DSS_CONTROL, b, start, end); /* DISPC_CLK_SWITCH */
272 328
273 dss.dispc_clk_source = clk_src; 329 dss.dispc_clk_source = clk_src;
274} 330}
275 331
276void dss_select_dsi_clk_source(enum dss_clk_source clk_src) 332void dss_select_dsi_clk_source(int dsi_module,
333 enum omap_dss_clk_source clk_src)
277{ 334{
335 struct platform_device *dsidev;
278 int b; 336 int b;
279 337
280 BUG_ON(clk_src != DSS_SRC_DSI2_PLL_FCLK && 338 switch (clk_src) {
281 clk_src != DSS_SRC_DSS1_ALWON_FCLK); 339 case OMAP_DSS_CLK_SRC_FCK:
340 b = 0;
341 break;
342 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI:
343 BUG_ON(dsi_module != 0);
344 b = 1;
345 dsidev = dsi_get_dsidev_from_id(0);
346 dsi_wait_pll_hsdiv_dsi_active(dsidev);
347 break;
348 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI:
349 BUG_ON(dsi_module != 1);
350 b = 1;
351 dsidev = dsi_get_dsidev_from_id(1);
352 dsi_wait_pll_hsdiv_dsi_active(dsidev);
353 break;
354 default:
355 BUG();
356 }
282 357
283 b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1; 358 REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */
284 359
285 if (clk_src == DSS_SRC_DSI2_PLL_FCLK) 360 dss.dsi_clk_source[dsi_module] = clk_src;
286 dsi_wait_dsi2_pll_active(); 361}
287 362
288 REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */ 363void dss_select_lcd_clk_source(enum omap_channel channel,
364 enum omap_dss_clk_source clk_src)
365{
366 struct platform_device *dsidev;
367 int b, ix, pos;
289 368
290 dss.dsi_clk_source = clk_src; 369 if (!dss_has_feature(FEAT_LCD_CLK_SRC))
370 return;
371
372 switch (clk_src) {
373 case OMAP_DSS_CLK_SRC_FCK:
374 b = 0;
375 break;
376 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
377 BUG_ON(channel != OMAP_DSS_CHANNEL_LCD);
378 b = 1;
379 dsidev = dsi_get_dsidev_from_id(0);
380 dsi_wait_pll_hsdiv_dispc_active(dsidev);
381 break;
382 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
383 BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2);
384 b = 1;
385 dsidev = dsi_get_dsidev_from_id(1);
386 dsi_wait_pll_hsdiv_dispc_active(dsidev);
387 break;
388 default:
389 BUG();
390 }
391
392 pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 12;
393 REG_FLD_MOD(DSS_CONTROL, b, pos, pos); /* LCDx_CLK_SWITCH */
394
395 ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1;
396 dss.lcd_clk_source[ix] = clk_src;
291} 397}
292 398
293enum dss_clk_source dss_get_dispc_clk_source(void) 399enum omap_dss_clk_source dss_get_dispc_clk_source(void)
294{ 400{
295 return dss.dispc_clk_source; 401 return dss.dispc_clk_source;
296} 402}
297 403
298enum dss_clk_source dss_get_dsi_clk_source(void) 404enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module)
299{ 405{
300 return dss.dsi_clk_source; 406 return dss.dsi_clk_source[dsi_module];
407}
408
409enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
410{
411 if (dss_has_feature(FEAT_LCD_CLK_SRC)) {
412 int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1;
413 return dss.lcd_clk_source[ix];
414 } else {
415 /* LCD_CLK source is the same as DISPC_FCLK source for
416 * OMAP2 and OMAP3 */
417 return dss.dispc_clk_source;
418 }
301} 419}
302 420
303/* calculate clock rates using dividers in cinfo */ 421/* calculate clock rates using dividers in cinfo */
304int dss_calc_clock_rates(struct dss_clock_info *cinfo) 422int dss_calc_clock_rates(struct dss_clock_info *cinfo)
305{ 423{
306 unsigned long prate; 424 if (dss.dpll4_m4_ck) {
425 unsigned long prate;
426 u16 fck_div_max = 16;
307 427
308 if (cinfo->fck_div > (cpu_is_omap3630() ? 32 : 16) || 428 if (cpu_is_omap3630() || cpu_is_omap44xx())
309 cinfo->fck_div == 0) 429 fck_div_max = 32;
310 return -EINVAL; 430
431 if (cinfo->fck_div > fck_div_max || cinfo->fck_div == 0)
432 return -EINVAL;
311 433
312 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); 434 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
313 435
314 cinfo->fck = prate / cinfo->fck_div; 436 cinfo->fck = prate / cinfo->fck_div;
437 } else {
438 if (cinfo->fck_div != 0)
439 return -EINVAL;
440 cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
441 }
315 442
316 return 0; 443 return 0;
317} 444}
318 445
319int dss_set_clock_div(struct dss_clock_info *cinfo) 446int dss_set_clock_div(struct dss_clock_info *cinfo)
320{ 447{
321 unsigned long prate; 448 if (dss.dpll4_m4_ck) {
322 int r; 449 unsigned long prate;
450 int r;
323 451
324 if (cpu_is_omap34xx()) {
325 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); 452 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
326 DSSDBG("dpll4_m4 = %ld\n", prate); 453 DSSDBG("dpll4_m4 = %ld\n", prate);
327 454
328 r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div); 455 r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div);
329 if (r) 456 if (r)
330 return r; 457 return r;
458 } else {
459 if (cinfo->fck_div != 0)
460 return -EINVAL;
331 } 461 }
332 462
333 DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div); 463 DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
@@ -337,12 +467,14 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
337 467
338int dss_get_clock_div(struct dss_clock_info *cinfo) 468int dss_get_clock_div(struct dss_clock_info *cinfo)
339{ 469{
340 cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK1); 470 cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
341 471
342 if (cpu_is_omap34xx()) { 472 if (dss.dpll4_m4_ck) {
343 unsigned long prate; 473 unsigned long prate;
474
344 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); 475 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
345 if (cpu_is_omap3630()) 476
477 if (cpu_is_omap3630() || cpu_is_omap44xx())
346 cinfo->fck_div = prate / (cinfo->fck); 478 cinfo->fck_div = prate / (cinfo->fck);
347 else 479 else
348 cinfo->fck_div = prate / (cinfo->fck / 2); 480 cinfo->fck_div = prate / (cinfo->fck / 2);
@@ -355,7 +487,7 @@ int dss_get_clock_div(struct dss_clock_info *cinfo)
355 487
356unsigned long dss_get_dpll4_rate(void) 488unsigned long dss_get_dpll4_rate(void)
357{ 489{
358 if (cpu_is_omap34xx()) 490 if (dss.dpll4_m4_ck)
359 return clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); 491 return clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
360 else 492 else
361 return 0; 493 return 0;
@@ -369,16 +501,18 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
369 struct dss_clock_info best_dss; 501 struct dss_clock_info best_dss;
370 struct dispc_clock_info best_dispc; 502 struct dispc_clock_info best_dispc;
371 503
372 unsigned long fck; 504 unsigned long fck, max_dss_fck;
373 505
374 u16 fck_div; 506 u16 fck_div, fck_div_max = 16;
375 507
376 int match = 0; 508 int match = 0;
377 int min_fck_per_pck; 509 int min_fck_per_pck;
378 510
379 prate = dss_get_dpll4_rate(); 511 prate = dss_get_dpll4_rate();
380 512
381 fck = dss_clk_get_rate(DSS_CLK_FCK1); 513 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
514
515 fck = dss_clk_get_rate(DSS_CLK_FCK);
382 if (req_pck == dss.cache_req_pck && 516 if (req_pck == dss.cache_req_pck &&
383 ((cpu_is_omap34xx() && prate == dss.cache_prate) || 517 ((cpu_is_omap34xx() && prate == dss.cache_prate) ||
384 dss.cache_dss_cinfo.fck == fck)) { 518 dss.cache_dss_cinfo.fck == fck)) {
@@ -391,7 +525,7 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
391 min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; 525 min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
392 526
393 if (min_fck_per_pck && 527 if (min_fck_per_pck &&
394 req_pck * min_fck_per_pck > DISPC_MAX_FCK) { 528 req_pck * min_fck_per_pck > max_dss_fck) {
395 DSSERR("Requested pixel clock not possible with the current " 529 DSSERR("Requested pixel clock not possible with the current "
396 "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " 530 "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
397 "the constraint off.\n"); 531 "the constraint off.\n");
@@ -402,10 +536,10 @@ retry:
402 memset(&best_dss, 0, sizeof(best_dss)); 536 memset(&best_dss, 0, sizeof(best_dss));
403 memset(&best_dispc, 0, sizeof(best_dispc)); 537 memset(&best_dispc, 0, sizeof(best_dispc));
404 538
405 if (cpu_is_omap24xx()) { 539 if (dss.dpll4_m4_ck == NULL) {
406 struct dispc_clock_info cur_dispc; 540 struct dispc_clock_info cur_dispc;
407 /* XXX can we change the clock on omap2? */ 541 /* XXX can we change the clock on omap2? */
408 fck = dss_clk_get_rate(DSS_CLK_FCK1); 542 fck = dss_clk_get_rate(DSS_CLK_FCK);
409 fck_div = 1; 543 fck_div = 1;
410 544
411 dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc); 545 dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
@@ -417,17 +551,19 @@ retry:
417 best_dispc = cur_dispc; 551 best_dispc = cur_dispc;
418 552
419 goto found; 553 goto found;
420 } else if (cpu_is_omap34xx()) { 554 } else {
421 for (fck_div = (cpu_is_omap3630() ? 32 : 16); 555 if (cpu_is_omap3630() || cpu_is_omap44xx())
422 fck_div > 0; --fck_div) { 556 fck_div_max = 32;
557
558 for (fck_div = fck_div_max; fck_div > 0; --fck_div) {
423 struct dispc_clock_info cur_dispc; 559 struct dispc_clock_info cur_dispc;
424 560
425 if (cpu_is_omap3630()) 561 if (fck_div_max == 32)
426 fck = prate / fck_div; 562 fck = prate / fck_div;
427 else 563 else
428 fck = prate / fck_div * 2; 564 fck = prate / fck_div * 2;
429 565
430 if (fck > DISPC_MAX_FCK) 566 if (fck > max_dss_fck)
431 continue; 567 continue;
432 568
433 if (min_fck_per_pck && 569 if (min_fck_per_pck &&
@@ -450,8 +586,6 @@ retry:
450 goto found; 586 goto found;
451 } 587 }
452 } 588 }
453 } else {
454 BUG();
455 } 589 }
456 590
457found: 591found:
@@ -482,31 +616,6 @@ found:
482 return 0; 616 return 0;
483} 617}
484 618
485
486
487static irqreturn_t dss_irq_handler_omap2(int irq, void *arg)
488{
489 dispc_irq_handler();
490
491 return IRQ_HANDLED;
492}
493
494static irqreturn_t dss_irq_handler_omap3(int irq, void *arg)
495{
496 u32 irqstatus;
497
498 irqstatus = dss_read_reg(DSS_IRQSTATUS);
499
500 if (irqstatus & (1<<0)) /* DISPC_IRQ */
501 dispc_irq_handler();
502#ifdef CONFIG_OMAP2_DSS_DSI
503 if (irqstatus & (1<<1)) /* DSI_IRQ */
504 dsi_irq_handler();
505#endif
506
507 return IRQ_HANDLED;
508}
509
510static int _omap_dss_wait_reset(void) 619static int _omap_dss_wait_reset(void)
511{ 620{
512 int t = 0; 621 int t = 0;
@@ -549,34 +658,50 @@ void dss_set_dac_pwrdn_bgz(bool enable)
549 REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */ 658 REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
550} 659}
551 660
552int dss_init(bool skip_init) 661void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi)
662{
663 REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */
664}
665
666static int dss_init(void)
553{ 667{
554 int r; 668 int r;
555 u32 rev; 669 u32 rev;
670 struct resource *dss_mem;
671 struct clk *dpll4_m4_ck;
556 672
557 dss.base = ioremap(DSS_BASE, DSS_SZ_REGS); 673 dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
674 if (!dss_mem) {
675 DSSERR("can't get IORESOURCE_MEM DSS\n");
676 r = -EINVAL;
677 goto fail0;
678 }
679 dss.base = ioremap(dss_mem->start, resource_size(dss_mem));
558 if (!dss.base) { 680 if (!dss.base) {
559 DSSERR("can't ioremap DSS\n"); 681 DSSERR("can't ioremap DSS\n");
560 r = -ENOMEM; 682 r = -ENOMEM;
561 goto fail0; 683 goto fail0;
562 } 684 }
563 685
564 if (!skip_init) { 686 /* disable LCD and DIGIT output. This seems to fix the synclost
565 /* disable LCD and DIGIT output. This seems to fix the synclost 687 * problem that we get, if the bootloader starts the DSS and
566 * problem that we get, if the bootloader starts the DSS and 688 * the kernel resets it */
567 * the kernel resets it */ 689 omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
568 omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440); 690
569 691#ifdef CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET
570 /* We need to wait here a bit, otherwise we sometimes start to 692 /* We need to wait here a bit, otherwise we sometimes start to
571 * get synclost errors, and after that only power cycle will 693 * get synclost errors, and after that only power cycle will
572 * restore DSS functionality. I have no idea why this happens. 694 * restore DSS functionality. I have no idea why this happens.
573 * And we have to wait _before_ resetting the DSS, but after 695 * And we have to wait _before_ resetting the DSS, but after
574 * enabling clocks. 696 * enabling clocks.
575 */ 697 *
576 msleep(50); 698 * This bug was at least present on OMAP3430. It's unknown
699 * if it happens on OMAP2 or OMAP3630.
700 */
701 msleep(50);
702#endif
577 703
578 _omap_dss_reset(); 704 _omap_dss_reset();
579 }
580 705
581 /* autoidle */ 706 /* autoidle */
582 REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0); 707 REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
@@ -589,29 +714,31 @@ int dss_init(bool skip_init)
589 REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ 714 REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */
590 REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ 715 REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */
591#endif 716#endif
592
593 r = request_irq(INT_24XX_DSS_IRQ,
594 cpu_is_omap24xx()
595 ? dss_irq_handler_omap2
596 : dss_irq_handler_omap3,
597 0, "OMAP DSS", NULL);
598
599 if (r < 0) {
600 DSSERR("omap2 dss: request_irq failed\n");
601 goto fail1;
602 }
603
604 if (cpu_is_omap34xx()) { 717 if (cpu_is_omap34xx()) {
605 dss.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck"); 718 dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
606 if (IS_ERR(dss.dpll4_m4_ck)) { 719 if (IS_ERR(dpll4_m4_ck)) {
607 DSSERR("Failed to get dpll4_m4_ck\n"); 720 DSSERR("Failed to get dpll4_m4_ck\n");
608 r = PTR_ERR(dss.dpll4_m4_ck); 721 r = PTR_ERR(dpll4_m4_ck);
609 goto fail2; 722 goto fail1;
610 } 723 }
724 } else if (cpu_is_omap44xx()) {
725 dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck");
726 if (IS_ERR(dpll4_m4_ck)) {
727 DSSERR("Failed to get dpll4_m4_ck\n");
728 r = PTR_ERR(dpll4_m4_ck);
729 goto fail1;
730 }
731 } else { /* omap24xx */
732 dpll4_m4_ck = NULL;
611 } 733 }
612 734
613 dss.dsi_clk_source = DSS_SRC_DSS1_ALWON_FCLK; 735 dss.dpll4_m4_ck = dpll4_m4_ck;
614 dss.dispc_clk_source = DSS_SRC_DSS1_ALWON_FCLK; 736
737 dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
738 dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
739 dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
740 dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
741 dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
615 742
616 dss_save_context(); 743 dss_save_context();
617 744
@@ -621,21 +748,427 @@ int dss_init(bool skip_init)
621 748
622 return 0; 749 return 0;
623 750
624fail2:
625 free_irq(INT_24XX_DSS_IRQ, NULL);
626fail1: 751fail1:
627 iounmap(dss.base); 752 iounmap(dss.base);
628fail0: 753fail0:
629 return r; 754 return r;
630} 755}
631 756
632void dss_exit(void) 757static void dss_exit(void)
633{ 758{
634 if (cpu_is_omap34xx()) 759 if (dss.dpll4_m4_ck)
635 clk_put(dss.dpll4_m4_ck); 760 clk_put(dss.dpll4_m4_ck);
636 761
637 free_irq(INT_24XX_DSS_IRQ, NULL);
638
639 iounmap(dss.base); 762 iounmap(dss.base);
640} 763}
641 764
765/* CONTEXT */
766static int dss_get_ctx_id(void)
767{
768 struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
769 int r;
770
771 if (!pdata->board_data->get_last_off_on_transaction_id)
772 return 0;
773 r = pdata->board_data->get_last_off_on_transaction_id(&dss.pdev->dev);
774 if (r < 0) {
775 dev_err(&dss.pdev->dev, "getting transaction ID failed, "
776 "will force context restore\n");
777 r = -1;
778 }
779 return r;
780}
781
782int dss_need_ctx_restore(void)
783{
784 int id = dss_get_ctx_id();
785
786 if (id < 0 || id != dss.ctx_id) {
787 DSSDBG("ctx id %d -> id %d\n",
788 dss.ctx_id, id);
789 dss.ctx_id = id;
790 return 1;
791 } else {
792 return 0;
793 }
794}
795
796static void save_all_ctx(void)
797{
798 DSSDBG("save context\n");
799
800 dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
801
802 dss_save_context();
803 dispc_save_context();
804#ifdef CONFIG_OMAP2_DSS_DSI
805 dsi_save_context();
806#endif
807
808 dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
809}
810
811static void restore_all_ctx(void)
812{
813 DSSDBG("restore context\n");
814
815 dss_clk_enable_all_no_ctx();
816
817 dss_restore_context();
818 dispc_restore_context();
819#ifdef CONFIG_OMAP2_DSS_DSI
820 dsi_restore_context();
821#endif
822
823 dss_clk_disable_all_no_ctx();
824}
825
826static int dss_get_clock(struct clk **clock, const char *clk_name)
827{
828 struct clk *clk;
829
830 clk = clk_get(&dss.pdev->dev, clk_name);
831
832 if (IS_ERR(clk)) {
833 DSSERR("can't get clock %s", clk_name);
834 return PTR_ERR(clk);
835 }
836
837 *clock = clk;
838
839 DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
840
841 return 0;
842}
843
844static int dss_get_clocks(void)
845{
846 int r;
847 struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
848
849 dss.dss_ick = NULL;
850 dss.dss_fck = NULL;
851 dss.dss_sys_clk = NULL;
852 dss.dss_tv_fck = NULL;
853 dss.dss_video_fck = NULL;
854
855 r = dss_get_clock(&dss.dss_ick, "ick");
856 if (r)
857 goto err;
858
859 r = dss_get_clock(&dss.dss_fck, "fck");
860 if (r)
861 goto err;
862
863 if (!pdata->opt_clock_available) {
864 r = -ENODEV;
865 goto err;
866 }
867
868 if (pdata->opt_clock_available("sys_clk")) {
869 r = dss_get_clock(&dss.dss_sys_clk, "sys_clk");
870 if (r)
871 goto err;
872 }
873
874 if (pdata->opt_clock_available("tv_clk")) {
875 r = dss_get_clock(&dss.dss_tv_fck, "tv_clk");
876 if (r)
877 goto err;
878 }
879
880 if (pdata->opt_clock_available("video_clk")) {
881 r = dss_get_clock(&dss.dss_video_fck, "video_clk");
882 if (r)
883 goto err;
884 }
885
886 return 0;
887
888err:
889 if (dss.dss_ick)
890 clk_put(dss.dss_ick);
891 if (dss.dss_fck)
892 clk_put(dss.dss_fck);
893 if (dss.dss_sys_clk)
894 clk_put(dss.dss_sys_clk);
895 if (dss.dss_tv_fck)
896 clk_put(dss.dss_tv_fck);
897 if (dss.dss_video_fck)
898 clk_put(dss.dss_video_fck);
899
900 return r;
901}
902
903static void dss_put_clocks(void)
904{
905 if (dss.dss_video_fck)
906 clk_put(dss.dss_video_fck);
907 if (dss.dss_tv_fck)
908 clk_put(dss.dss_tv_fck);
909 if (dss.dss_sys_clk)
910 clk_put(dss.dss_sys_clk);
911 clk_put(dss.dss_fck);
912 clk_put(dss.dss_ick);
913}
914
915unsigned long dss_clk_get_rate(enum dss_clock clk)
916{
917 switch (clk) {
918 case DSS_CLK_ICK:
919 return clk_get_rate(dss.dss_ick);
920 case DSS_CLK_FCK:
921 return clk_get_rate(dss.dss_fck);
922 case DSS_CLK_SYSCK:
923 return clk_get_rate(dss.dss_sys_clk);
924 case DSS_CLK_TVFCK:
925 return clk_get_rate(dss.dss_tv_fck);
926 case DSS_CLK_VIDFCK:
927 return clk_get_rate(dss.dss_video_fck);
928 }
929
930 BUG();
931 return 0;
932}
933
934static unsigned count_clk_bits(enum dss_clock clks)
935{
936 unsigned num_clks = 0;
937
938 if (clks & DSS_CLK_ICK)
939 ++num_clks;
940 if (clks & DSS_CLK_FCK)
941 ++num_clks;
942 if (clks & DSS_CLK_SYSCK)
943 ++num_clks;
944 if (clks & DSS_CLK_TVFCK)
945 ++num_clks;
946 if (clks & DSS_CLK_VIDFCK)
947 ++num_clks;
948
949 return num_clks;
950}
951
952static void dss_clk_enable_no_ctx(enum dss_clock clks)
953{
954 unsigned num_clks = count_clk_bits(clks);
955
956 if (clks & DSS_CLK_ICK)
957 clk_enable(dss.dss_ick);
958 if (clks & DSS_CLK_FCK)
959 clk_enable(dss.dss_fck);
960 if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
961 clk_enable(dss.dss_sys_clk);
962 if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
963 clk_enable(dss.dss_tv_fck);
964 if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
965 clk_enable(dss.dss_video_fck);
966
967 dss.num_clks_enabled += num_clks;
968}
969
970void dss_clk_enable(enum dss_clock clks)
971{
972 bool check_ctx = dss.num_clks_enabled == 0;
973
974 dss_clk_enable_no_ctx(clks);
975
976 /*
977 * HACK: On omap4 the registers may not be accessible right after
978 * enabling the clocks. At some point this will be handled by
979 * pm_runtime, but for the time begin this should make things work.
980 */
981 if (cpu_is_omap44xx() && check_ctx)
982 udelay(10);
983
984 if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore())
985 restore_all_ctx();
986}
987
988static void dss_clk_disable_no_ctx(enum dss_clock clks)
989{
990 unsigned num_clks = count_clk_bits(clks);
991
992 if (clks & DSS_CLK_ICK)
993 clk_disable(dss.dss_ick);
994 if (clks & DSS_CLK_FCK)
995 clk_disable(dss.dss_fck);
996 if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
997 clk_disable(dss.dss_sys_clk);
998 if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
999 clk_disable(dss.dss_tv_fck);
1000 if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
1001 clk_disable(dss.dss_video_fck);
1002
1003 dss.num_clks_enabled -= num_clks;
1004}
1005
1006void dss_clk_disable(enum dss_clock clks)
1007{
1008 if (cpu_is_omap34xx()) {
1009 unsigned num_clks = count_clk_bits(clks);
1010
1011 BUG_ON(dss.num_clks_enabled < num_clks);
1012
1013 if (dss.num_clks_enabled == num_clks)
1014 save_all_ctx();
1015 }
1016
1017 dss_clk_disable_no_ctx(clks);
1018}
1019
1020static void dss_clk_enable_all_no_ctx(void)
1021{
1022 enum dss_clock clks;
1023
1024 clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK;
1025 if (cpu_is_omap34xx())
1026 clks |= DSS_CLK_VIDFCK;
1027 dss_clk_enable_no_ctx(clks);
1028}
1029
1030static void dss_clk_disable_all_no_ctx(void)
1031{
1032 enum dss_clock clks;
1033
1034 clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK;
1035 if (cpu_is_omap34xx())
1036 clks |= DSS_CLK_VIDFCK;
1037 dss_clk_disable_no_ctx(clks);
1038}
1039
1040#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
1041/* CLOCKS */
1042static void core_dump_clocks(struct seq_file *s)
1043{
1044 int i;
1045 struct clk *clocks[5] = {
1046 dss.dss_ick,
1047 dss.dss_fck,
1048 dss.dss_sys_clk,
1049 dss.dss_tv_fck,
1050 dss.dss_video_fck
1051 };
1052
1053 const char *names[5] = {
1054 "ick",
1055 "fck",
1056 "sys_clk",
1057 "tv_fck",
1058 "video_fck"
1059 };
1060
1061 seq_printf(s, "- CORE -\n");
1062
1063 seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled);
1064
1065 for (i = 0; i < 5; i++) {
1066 if (!clocks[i])
1067 continue;
1068 seq_printf(s, "%s (%s)%*s\t%lu\t%d\n",
1069 names[i],
1070 clocks[i]->name,
1071 24 - strlen(names[i]) - strlen(clocks[i]->name),
1072 "",
1073 clk_get_rate(clocks[i]),
1074 clocks[i]->usecount);
1075 }
1076}
1077#endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */
1078
1079/* DEBUGFS */
1080#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
1081void dss_debug_dump_clocks(struct seq_file *s)
1082{
1083 core_dump_clocks(s);
1084 dss_dump_clocks(s);
1085 dispc_dump_clocks(s);
1086#ifdef CONFIG_OMAP2_DSS_DSI
1087 dsi_dump_clocks(s);
1088#endif
1089}
1090#endif
1091
1092
1093/* DSS HW IP initialisation */
1094static int omap_dsshw_probe(struct platform_device *pdev)
1095{
1096 int r;
1097
1098 dss.pdev = pdev;
1099
1100 r = dss_get_clocks();
1101 if (r)
1102 goto err_clocks;
1103
1104 dss_clk_enable_all_no_ctx();
1105
1106 dss.ctx_id = dss_get_ctx_id();
1107 DSSDBG("initial ctx id %u\n", dss.ctx_id);
1108
1109 r = dss_init();
1110 if (r) {
1111 DSSERR("Failed to initialize DSS\n");
1112 goto err_dss;
1113 }
1114
1115 r = dpi_init();
1116 if (r) {
1117 DSSERR("Failed to initialize DPI\n");
1118 goto err_dpi;
1119 }
1120
1121 r = sdi_init();
1122 if (r) {
1123 DSSERR("Failed to initialize SDI\n");
1124 goto err_sdi;
1125 }
1126
1127 dss_clk_disable_all_no_ctx();
1128 return 0;
1129err_sdi:
1130 dpi_exit();
1131err_dpi:
1132 dss_exit();
1133err_dss:
1134 dss_clk_disable_all_no_ctx();
1135 dss_put_clocks();
1136err_clocks:
1137 return r;
1138}
1139
1140static int omap_dsshw_remove(struct platform_device *pdev)
1141{
1142
1143 dss_exit();
1144
1145 /*
1146 * As part of hwmod changes, DSS is not the only controller of dss
1147 * clocks; hwmod framework itself will also enable clocks during hwmod
1148 * init for dss, and autoidle is set in h/w for DSS. Hence, there's no
1149 * need to disable clocks if their usecounts > 1.
1150 */
1151 WARN_ON(dss.num_clks_enabled > 0);
1152
1153 dss_put_clocks();
1154 return 0;
1155}
1156
1157static struct platform_driver omap_dsshw_driver = {
1158 .probe = omap_dsshw_probe,
1159 .remove = omap_dsshw_remove,
1160 .driver = {
1161 .name = "omapdss_dss",
1162 .owner = THIS_MODULE,
1163 },
1164};
1165
1166int dss_init_platform_driver(void)
1167{
1168 return platform_driver_register(&omap_dsshw_driver);
1169}
1170
1171void dss_uninit_platform_driver(void)
1172{
1173 return platform_driver_unregister(&omap_dsshw_driver);
1174}
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 5c7940d5f282..8ab6d43329bb 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -97,8 +97,6 @@ extern unsigned int dss_debug;
97#define FLD_MOD(orig, val, start, end) \ 97#define FLD_MOD(orig, val, start, end) \
98 (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end)) 98 (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
99 99
100#define DISPC_MAX_FCK 173000000
101
102enum omap_burst_size { 100enum omap_burst_size {
103 OMAP_DSS_BURST_4x32 = 0, 101 OMAP_DSS_BURST_4x32 = 0,
104 OMAP_DSS_BURST_8x32 = 1, 102 OMAP_DSS_BURST_8x32 = 1,
@@ -112,17 +110,16 @@ enum omap_parallel_interface_mode {
112}; 110};
113 111
114enum dss_clock { 112enum dss_clock {
115 DSS_CLK_ICK = 1 << 0, 113 DSS_CLK_ICK = 1 << 0, /* DSS_L3_ICLK and DSS_L4_ICLK */
116 DSS_CLK_FCK1 = 1 << 1, 114 DSS_CLK_FCK = 1 << 1, /* DSS1_ALWON_FCLK */
117 DSS_CLK_FCK2 = 1 << 2, 115 DSS_CLK_SYSCK = 1 << 2, /* DSS2_ALWON_FCLK */
118 DSS_CLK_54M = 1 << 3, 116 DSS_CLK_TVFCK = 1 << 3, /* DSS_TV_FCLK */
119 DSS_CLK_96M = 1 << 4, 117 DSS_CLK_VIDFCK = 1 << 4, /* DSS_96M_FCLK*/
120}; 118};
121 119
122enum dss_clk_source { 120enum dss_hdmi_venc_clk_source_select {
123 DSS_SRC_DSI1_PLL_FCLK, 121 DSS_VENC_TV_CLK = 0,
124 DSS_SRC_DSI2_PLL_FCLK, 122 DSS_HDMI_M_PCLK = 1,
125 DSS_SRC_DSS1_ALWON_FCLK,
126}; 123};
127 124
128struct dss_clock_info { 125struct dss_clock_info {
@@ -148,36 +145,42 @@ struct dsi_clock_info {
148 unsigned long fint; 145 unsigned long fint;
149 unsigned long clkin4ddr; 146 unsigned long clkin4ddr;
150 unsigned long clkin; 147 unsigned long clkin;
151 unsigned long dsi1_pll_fclk; 148 unsigned long dsi_pll_hsdiv_dispc_clk; /* OMAP3: DSI1_PLL_CLK
152 unsigned long dsi2_pll_fclk; 149 * OMAP4: PLLx_CLK1 */
153 150 unsigned long dsi_pll_hsdiv_dsi_clk; /* OMAP3: DSI2_PLL_CLK
151 * OMAP4: PLLx_CLK2 */
154 unsigned long lp_clk; 152 unsigned long lp_clk;
155 153
156 /* dividers */ 154 /* dividers */
157 u16 regn; 155 u16 regn;
158 u16 regm; 156 u16 regm;
159 u16 regm3; 157 u16 regm_dispc; /* OMAP3: REGM3
160 u16 regm4; 158 * OMAP4: REGM4 */
161 159 u16 regm_dsi; /* OMAP3: REGM4
160 * OMAP4: REGM5 */
162 u16 lp_clk_div; 161 u16 lp_clk_div;
163 162
164 u8 highfreq; 163 u8 highfreq;
165 bool use_dss2_fck; 164 bool use_sys_clk;
165};
166
167/* HDMI PLL structure */
168struct hdmi_pll_info {
169 u16 regn;
170 u16 regm;
171 u32 regmf;
172 u16 regm2;
173 u16 regsd;
174 u16 dcofreq;
166}; 175};
167 176
168struct seq_file; 177struct seq_file;
169struct platform_device; 178struct platform_device;
170 179
171/* core */ 180/* core */
172void dss_clk_enable(enum dss_clock clks);
173void dss_clk_disable(enum dss_clock clks);
174unsigned long dss_clk_get_rate(enum dss_clock clk);
175int dss_need_ctx_restore(void);
176void dss_dump_clocks(struct seq_file *s);
177struct bus_type *dss_get_bus(void); 181struct bus_type *dss_get_bus(void);
178struct regulator *dss_get_vdds_dsi(void); 182struct regulator *dss_get_vdds_dsi(void);
179struct regulator *dss_get_vdds_sdi(void); 183struct regulator *dss_get_vdds_sdi(void);
180struct regulator *dss_get_vdda_dac(void);
181 184
182/* display */ 185/* display */
183int dss_suspend_all_devices(void); 186int dss_suspend_all_devices(void);
@@ -214,22 +217,36 @@ void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr);
214void dss_recheck_connections(struct omap_dss_device *dssdev, bool force); 217void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
215 218
216/* DSS */ 219/* DSS */
217int dss_init(bool skip_init); 220int dss_init_platform_driver(void);
218void dss_exit(void); 221void dss_uninit_platform_driver(void);
219 222
223void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
220void dss_save_context(void); 224void dss_save_context(void);
221void dss_restore_context(void); 225void dss_restore_context(void);
226void dss_clk_enable(enum dss_clock clks);
227void dss_clk_disable(enum dss_clock clks);
228unsigned long dss_clk_get_rate(enum dss_clock clk);
229int dss_need_ctx_restore(void);
230const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
231void dss_dump_clocks(struct seq_file *s);
222 232
223void dss_dump_regs(struct seq_file *s); 233void dss_dump_regs(struct seq_file *s);
234#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
235void dss_debug_dump_clocks(struct seq_file *s);
236#endif
224 237
225void dss_sdi_init(u8 datapairs); 238void dss_sdi_init(u8 datapairs);
226int dss_sdi_enable(void); 239int dss_sdi_enable(void);
227void dss_sdi_disable(void); 240void dss_sdi_disable(void);
228 241
229void dss_select_dispc_clk_source(enum dss_clk_source clk_src); 242void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src);
230void dss_select_dsi_clk_source(enum dss_clk_source clk_src); 243void dss_select_dsi_clk_source(int dsi_module,
231enum dss_clk_source dss_get_dispc_clk_source(void); 244 enum omap_dss_clk_source clk_src);
232enum dss_clk_source dss_get_dsi_clk_source(void); 245void dss_select_lcd_clk_source(enum omap_channel channel,
246 enum omap_dss_clk_source clk_src);
247enum omap_dss_clk_source dss_get_dispc_clk_source(void);
248enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module);
249enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel);
233 250
234void dss_set_venc_output(enum omap_dss_venc_type type); 251void dss_set_venc_output(enum omap_dss_venc_type type);
235void dss_set_dac_pwrdn_bgz(bool enable); 252void dss_set_dac_pwrdn_bgz(bool enable);
@@ -244,11 +261,11 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
244 261
245/* SDI */ 262/* SDI */
246#ifdef CONFIG_OMAP2_DSS_SDI 263#ifdef CONFIG_OMAP2_DSS_SDI
247int sdi_init(bool skip_init); 264int sdi_init(void);
248void sdi_exit(void); 265void sdi_exit(void);
249int sdi_init_display(struct omap_dss_device *display); 266int sdi_init_display(struct omap_dss_device *display);
250#else 267#else
251static inline int sdi_init(bool skip_init) 268static inline int sdi_init(void)
252{ 269{
253 return 0; 270 return 0;
254} 271}
@@ -259,54 +276,97 @@ static inline void sdi_exit(void)
259 276
260/* DSI */ 277/* DSI */
261#ifdef CONFIG_OMAP2_DSS_DSI 278#ifdef CONFIG_OMAP2_DSS_DSI
262int dsi_init(struct platform_device *pdev); 279
263void dsi_exit(void); 280struct dentry;
281struct file_operations;
282
283int dsi_init_platform_driver(void);
284void dsi_uninit_platform_driver(void);
264 285
265void dsi_dump_clocks(struct seq_file *s); 286void dsi_dump_clocks(struct seq_file *s);
266void dsi_dump_irqs(struct seq_file *s); 287void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir,
267void dsi_dump_regs(struct seq_file *s); 288 const struct file_operations *debug_fops);
289void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir,
290 const struct file_operations *debug_fops);
268 291
269void dsi_save_context(void); 292void dsi_save_context(void);
270void dsi_restore_context(void); 293void dsi_restore_context(void);
271 294
272int dsi_init_display(struct omap_dss_device *display); 295int dsi_init_display(struct omap_dss_device *display);
273void dsi_irq_handler(void); 296void dsi_irq_handler(void);
274unsigned long dsi_get_dsi1_pll_rate(void); 297unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
275int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo); 298int dsi_pll_set_clock_div(struct platform_device *dsidev,
276int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck, 299 struct dsi_clock_info *cinfo);
277 struct dsi_clock_info *cinfo, 300int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, bool is_tft,
301 unsigned long req_pck, struct dsi_clock_info *cinfo,
278 struct dispc_clock_info *dispc_cinfo); 302 struct dispc_clock_info *dispc_cinfo);
279int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk, 303int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
280 bool enable_hsdiv); 304 bool enable_hsdiv);
281void dsi_pll_uninit(void); 305void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes);
282void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, 306void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
283 u32 fifo_size, enum omap_burst_size *burst_size, 307 u32 fifo_size, enum omap_burst_size *burst_size,
284 u32 *fifo_low, u32 *fifo_high); 308 u32 *fifo_low, u32 *fifo_high);
285void dsi_wait_dsi1_pll_active(void); 309void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev);
286void dsi_wait_dsi2_pll_active(void); 310void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev);
311struct platform_device *dsi_get_dsidev_from_id(int module);
287#else 312#else
288static inline int dsi_init(struct platform_device *pdev) 313static inline int dsi_init_platform_driver(void)
289{ 314{
290 return 0; 315 return 0;
291} 316}
292static inline void dsi_exit(void) 317static inline void dsi_uninit_platform_driver(void)
318{
319}
320static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
293{ 321{
322 WARN("%s: DSI not compiled in, returning rate as 0\n", __func__);
323 return 0;
294} 324}
295static inline void dsi_wait_dsi1_pll_active(void) 325static inline int dsi_pll_set_clock_div(struct platform_device *dsidev,
326 struct dsi_clock_info *cinfo)
296{ 327{
328 WARN("%s: DSI not compiled in\n", __func__);
329 return -ENODEV;
297} 330}
298static inline void dsi_wait_dsi2_pll_active(void) 331static inline int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev,
332 bool is_tft, unsigned long req_pck,
333 struct dsi_clock_info *dsi_cinfo,
334 struct dispc_clock_info *dispc_cinfo)
299{ 335{
336 WARN("%s: DSI not compiled in\n", __func__);
337 return -ENODEV;
338}
339static inline int dsi_pll_init(struct platform_device *dsidev,
340 bool enable_hsclk, bool enable_hsdiv)
341{
342 WARN("%s: DSI not compiled in\n", __func__);
343 return -ENODEV;
344}
345static inline void dsi_pll_uninit(struct platform_device *dsidev,
346 bool disconnect_lanes)
347{
348}
349static inline void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev)
350{
351}
352static inline void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev)
353{
354}
355static inline struct platform_device *dsi_get_dsidev_from_id(int module)
356{
357 WARN("%s: DSI not compiled in, returning platform device as NULL\n",
358 __func__);
359 return NULL;
300} 360}
301#endif 361#endif
302 362
303/* DPI */ 363/* DPI */
304#ifdef CONFIG_OMAP2_DSS_DPI 364#ifdef CONFIG_OMAP2_DSS_DPI
305int dpi_init(struct platform_device *pdev); 365int dpi_init(void);
306void dpi_exit(void); 366void dpi_exit(void);
307int dpi_init_display(struct omap_dss_device *dssdev); 367int dpi_init_display(struct omap_dss_device *dssdev);
308#else 368#else
309static inline int dpi_init(struct platform_device *pdev) 369static inline int dpi_init(void)
310{ 370{
311 return 0; 371 return 0;
312} 372}
@@ -316,8 +376,8 @@ static inline void dpi_exit(void)
316#endif 376#endif
317 377
318/* DISPC */ 378/* DISPC */
319int dispc_init(void); 379int dispc_init_platform_driver(void);
320void dispc_exit(void); 380void dispc_uninit_platform_driver(void);
321void dispc_dump_clocks(struct seq_file *s); 381void dispc_dump_clocks(struct seq_file *s);
322void dispc_dump_irqs(struct seq_file *s); 382void dispc_dump_irqs(struct seq_file *s);
323void dispc_dump_regs(struct seq_file *s); 383void dispc_dump_regs(struct seq_file *s);
@@ -333,9 +393,9 @@ void dispc_disable_sidle(void);
333void dispc_lcd_enable_signal_polarity(bool act_high); 393void dispc_lcd_enable_signal_polarity(bool act_high);
334void dispc_lcd_enable_signal(bool enable); 394void dispc_lcd_enable_signal(bool enable);
335void dispc_pck_free_enable(bool enable); 395void dispc_pck_free_enable(bool enable);
336void dispc_enable_fifohandcheck(bool enable); 396void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable);
337 397
338void dispc_set_lcd_size(u16 width, u16 height); 398void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height);
339void dispc_set_digit_size(u16 width, u16 height); 399void dispc_set_digit_size(u16 width, u16 height);
340u32 dispc_get_plane_fifo_size(enum omap_plane plane); 400u32 dispc_get_plane_fifo_size(enum omap_plane plane);
341void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high); 401void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high);
@@ -350,6 +410,7 @@ void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height);
350void dispc_set_channel_out(enum omap_plane plane, 410void dispc_set_channel_out(enum omap_plane plane,
351 enum omap_channel channel_out); 411 enum omap_channel channel_out);
352 412
413void dispc_enable_gamma_table(bool enable);
353int dispc_setup_plane(enum omap_plane plane, 414int dispc_setup_plane(enum omap_plane plane,
354 u32 paddr, u16 screen_width, 415 u32 paddr, u16 screen_width,
355 u16 pos_x, u16 pos_y, 416 u16 pos_x, u16 pos_y,
@@ -359,7 +420,9 @@ int dispc_setup_plane(enum omap_plane plane,
359 bool ilace, 420 bool ilace,
360 enum omap_dss_rotation_type rotation_type, 421 enum omap_dss_rotation_type rotation_type,
361 u8 rotation, bool mirror, 422 u8 rotation, bool mirror,
362 u8 global_alpha); 423 u8 global_alpha, u8 pre_mult_alpha,
424 enum omap_channel channel,
425 u32 puv_addr);
363 426
364bool dispc_go_busy(enum omap_channel channel); 427bool dispc_go_busy(enum omap_channel channel);
365void dispc_go(enum omap_channel channel); 428void dispc_go(enum omap_channel channel);
@@ -368,9 +431,11 @@ bool dispc_is_channel_enabled(enum omap_channel channel);
368int dispc_enable_plane(enum omap_plane plane, bool enable); 431int dispc_enable_plane(enum omap_plane plane, bool enable);
369void dispc_enable_replication(enum omap_plane plane, bool enable); 432void dispc_enable_replication(enum omap_plane plane, bool enable);
370 433
371void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode); 434void dispc_set_parallel_interface_mode(enum omap_channel channel,
372void dispc_set_tft_data_lines(u8 data_lines); 435 enum omap_parallel_interface_mode mode);
373void dispc_set_lcd_display_type(enum omap_lcd_display_type type); 436void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines);
437void dispc_set_lcd_display_type(enum omap_channel channel,
438 enum omap_lcd_display_type type);
374void dispc_set_loadmode(enum omap_dss_load_mode mode); 439void dispc_set_loadmode(enum omap_dss_load_mode mode);
375 440
376void dispc_set_default_color(enum omap_channel channel, u32 color); 441void dispc_set_default_color(enum omap_channel channel, u32 color);
@@ -387,54 +452,77 @@ bool dispc_trans_key_enabled(enum omap_channel ch);
387bool dispc_alpha_blending_enabled(enum omap_channel ch); 452bool dispc_alpha_blending_enabled(enum omap_channel ch);
388 453
389bool dispc_lcd_timings_ok(struct omap_video_timings *timings); 454bool dispc_lcd_timings_ok(struct omap_video_timings *timings);
390void dispc_set_lcd_timings(struct omap_video_timings *timings); 455void dispc_set_lcd_timings(enum omap_channel channel,
456 struct omap_video_timings *timings);
391unsigned long dispc_fclk_rate(void); 457unsigned long dispc_fclk_rate(void);
392unsigned long dispc_lclk_rate(void); 458unsigned long dispc_lclk_rate(enum omap_channel channel);
393unsigned long dispc_pclk_rate(void); 459unsigned long dispc_pclk_rate(enum omap_channel channel);
394void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb); 460void dispc_set_pol_freq(enum omap_channel channel,
461 enum omap_panel_config config, u8 acbi, u8 acb);
395void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, 462void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
396 struct dispc_clock_info *cinfo); 463 struct dispc_clock_info *cinfo);
397int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, 464int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
398 struct dispc_clock_info *cinfo); 465 struct dispc_clock_info *cinfo);
399int dispc_set_clock_div(struct dispc_clock_info *cinfo); 466int dispc_set_clock_div(enum omap_channel channel,
400int dispc_get_clock_div(struct dispc_clock_info *cinfo); 467 struct dispc_clock_info *cinfo);
468int dispc_get_clock_div(enum omap_channel channel,
469 struct dispc_clock_info *cinfo);
401 470
402 471
403/* VENC */ 472/* VENC */
404#ifdef CONFIG_OMAP2_DSS_VENC 473#ifdef CONFIG_OMAP2_DSS_VENC
405int venc_init(struct platform_device *pdev); 474int venc_init_platform_driver(void);
406void venc_exit(void); 475void venc_uninit_platform_driver(void);
407void venc_dump_regs(struct seq_file *s); 476void venc_dump_regs(struct seq_file *s);
408int venc_init_display(struct omap_dss_device *display); 477int venc_init_display(struct omap_dss_device *display);
409#else 478#else
410static inline int venc_init(struct platform_device *pdev) 479static inline int venc_init_platform_driver(void)
411{ 480{
412 return 0; 481 return 0;
413} 482}
414static inline void venc_exit(void) 483static inline void venc_uninit_platform_driver(void)
415{ 484{
416} 485}
417#endif 486#endif
418 487
488/* HDMI */
489#ifdef CONFIG_OMAP4_DSS_HDMI
490int hdmi_init_platform_driver(void);
491void hdmi_uninit_platform_driver(void);
492int hdmi_init_display(struct omap_dss_device *dssdev);
493#else
494static inline int hdmi_init_display(struct omap_dss_device *dssdev)
495{
496 return 0;
497}
498static inline int hdmi_init_platform_driver(void)
499{
500 return 0;
501}
502static inline void hdmi_uninit_platform_driver(void)
503{
504}
505#endif
506int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev);
507void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);
508void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev);
509int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
510 struct omap_video_timings *timings);
511int hdmi_panel_init(void);
512void hdmi_panel_exit(void);
513
419/* RFBI */ 514/* RFBI */
420#ifdef CONFIG_OMAP2_DSS_RFBI 515#ifdef CONFIG_OMAP2_DSS_RFBI
421int rfbi_init(void); 516int rfbi_init_platform_driver(void);
422void rfbi_exit(void); 517void rfbi_uninit_platform_driver(void);
423void rfbi_dump_regs(struct seq_file *s); 518void rfbi_dump_regs(struct seq_file *s);
424
425int rfbi_configure(int rfbi_module, int bpp, int lines);
426void rfbi_enable_rfbi(bool enable);
427void rfbi_transfer_area(u16 width, u16 height,
428 void (callback)(void *data), void *data);
429void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t);
430unsigned long rfbi_get_max_tx_rate(void);
431int rfbi_init_display(struct omap_dss_device *display); 519int rfbi_init_display(struct omap_dss_device *display);
432#else 520#else
433static inline int rfbi_init(void) 521static inline int rfbi_init_platform_driver(void)
434{ 522{
435 return 0; 523 return 0;
436} 524}
437static inline void rfbi_exit(void) 525static inline void rfbi_uninit_platform_driver(void)
438{ 526{
439} 527}
440#endif 528#endif
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
new file mode 100644
index 000000000000..1c18888e5df3
--- /dev/null
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -0,0 +1,433 @@
1/*
2 * linux/drivers/video/omap2/dss/dss_features.c
3 *
4 * Copyright (C) 2010 Texas Instruments
5 * Author: Archit Taneja <archit@ti.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <linux/kernel.h>
21#include <linux/types.h>
22#include <linux/err.h>
23#include <linux/slab.h>
24
25#include <video/omapdss.h>
26#include <plat/cpu.h>
27
28#include "dss.h"
29#include "dss_features.h"
30
31/* Defines a generic omap register field */
32struct dss_reg_field {
33 u8 start, end;
34};
35
36struct dss_param_range {
37 int min, max;
38};
39
40struct omap_dss_features {
41 const struct dss_reg_field *reg_fields;
42 const int num_reg_fields;
43
44 const u32 has_feature;
45
46 const int num_mgrs;
47 const int num_ovls;
48 const enum omap_display_type *supported_displays;
49 const enum omap_color_mode *supported_color_modes;
50 const char * const *clksrc_names;
51 const struct dss_param_range *dss_params;
52};
53
54/* This struct is assigned to one of the below during initialization */
55static const struct omap_dss_features *omap_current_dss_features;
56
57static const struct dss_reg_field omap2_dss_reg_fields[] = {
58 [FEAT_REG_FIRHINC] = { 11, 0 },
59 [FEAT_REG_FIRVINC] = { 27, 16 },
60 [FEAT_REG_FIFOLOWTHRESHOLD] = { 8, 0 },
61 [FEAT_REG_FIFOHIGHTHRESHOLD] = { 24, 16 },
62 [FEAT_REG_FIFOSIZE] = { 8, 0 },
63 [FEAT_REG_HORIZONTALACCU] = { 9, 0 },
64 [FEAT_REG_VERTICALACCU] = { 25, 16 },
65 [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 },
66 [FEAT_REG_DSIPLL_REGN] = { 0, 0 },
67 [FEAT_REG_DSIPLL_REGM] = { 0, 0 },
68 [FEAT_REG_DSIPLL_REGM_DISPC] = { 0, 0 },
69 [FEAT_REG_DSIPLL_REGM_DSI] = { 0, 0 },
70};
71
72static const struct dss_reg_field omap3_dss_reg_fields[] = {
73 [FEAT_REG_FIRHINC] = { 12, 0 },
74 [FEAT_REG_FIRVINC] = { 28, 16 },
75 [FEAT_REG_FIFOLOWTHRESHOLD] = { 11, 0 },
76 [FEAT_REG_FIFOHIGHTHRESHOLD] = { 27, 16 },
77 [FEAT_REG_FIFOSIZE] = { 10, 0 },
78 [FEAT_REG_HORIZONTALACCU] = { 9, 0 },
79 [FEAT_REG_VERTICALACCU] = { 25, 16 },
80 [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 },
81 [FEAT_REG_DSIPLL_REGN] = { 7, 1 },
82 [FEAT_REG_DSIPLL_REGM] = { 18, 8 },
83 [FEAT_REG_DSIPLL_REGM_DISPC] = { 22, 19 },
84 [FEAT_REG_DSIPLL_REGM_DSI] = { 26, 23 },
85};
86
87static const struct dss_reg_field omap4_dss_reg_fields[] = {
88 [FEAT_REG_FIRHINC] = { 12, 0 },
89 [FEAT_REG_FIRVINC] = { 28, 16 },
90 [FEAT_REG_FIFOLOWTHRESHOLD] = { 15, 0 },
91 [FEAT_REG_FIFOHIGHTHRESHOLD] = { 31, 16 },
92 [FEAT_REG_FIFOSIZE] = { 15, 0 },
93 [FEAT_REG_HORIZONTALACCU] = { 10, 0 },
94 [FEAT_REG_VERTICALACCU] = { 26, 16 },
95 [FEAT_REG_DISPC_CLK_SWITCH] = { 9, 8 },
96 [FEAT_REG_DSIPLL_REGN] = { 8, 1 },
97 [FEAT_REG_DSIPLL_REGM] = { 20, 9 },
98 [FEAT_REG_DSIPLL_REGM_DISPC] = { 25, 21 },
99 [FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 },
100};
101
102static const enum omap_display_type omap2_dss_supported_displays[] = {
103 /* OMAP_DSS_CHANNEL_LCD */
104 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI,
105
106 /* OMAP_DSS_CHANNEL_DIGIT */
107 OMAP_DISPLAY_TYPE_VENC,
108};
109
110static const enum omap_display_type omap3430_dss_supported_displays[] = {
111 /* OMAP_DSS_CHANNEL_LCD */
112 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
113 OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI,
114
115 /* OMAP_DSS_CHANNEL_DIGIT */
116 OMAP_DISPLAY_TYPE_VENC,
117};
118
119static const enum omap_display_type omap3630_dss_supported_displays[] = {
120 /* OMAP_DSS_CHANNEL_LCD */
121 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
122 OMAP_DISPLAY_TYPE_DSI,
123
124 /* OMAP_DSS_CHANNEL_DIGIT */
125 OMAP_DISPLAY_TYPE_VENC,
126};
127
128static const enum omap_display_type omap4_dss_supported_displays[] = {
129 /* OMAP_DSS_CHANNEL_LCD */
130 OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI,
131
132 /* OMAP_DSS_CHANNEL_DIGIT */
133 OMAP_DISPLAY_TYPE_VENC | OMAP_DISPLAY_TYPE_HDMI,
134
135 /* OMAP_DSS_CHANNEL_LCD2 */
136 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
137 OMAP_DISPLAY_TYPE_DSI,
138};
139
140static const enum omap_color_mode omap2_dss_supported_color_modes[] = {
141 /* OMAP_DSS_GFX */
142 OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
143 OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
144 OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 |
145 OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P,
146
147 /* OMAP_DSS_VIDEO1 */
148 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
149 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
150 OMAP_DSS_COLOR_UYVY,
151
152 /* OMAP_DSS_VIDEO2 */
153 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
154 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
155 OMAP_DSS_COLOR_UYVY,
156};
157
158static const enum omap_color_mode omap3_dss_supported_color_modes[] = {
159 /* OMAP_DSS_GFX */
160 OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
161 OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
162 OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
163 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
164 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
165 OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
166
167 /* OMAP_DSS_VIDEO1 */
168 OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P |
169 OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 |
170 OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY,
171
172 /* OMAP_DSS_VIDEO2 */
173 OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
174 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
175 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
176 OMAP_DSS_COLOR_UYVY | OMAP_DSS_COLOR_ARGB32 |
177 OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
178};
179
180static const enum omap_color_mode omap4_dss_supported_color_modes[] = {
181 /* OMAP_DSS_GFX */
182 OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
183 OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
184 OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
185 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
186 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
187 OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32 |
188 OMAP_DSS_COLOR_ARGB16_1555,
189
190 /* OMAP_DSS_VIDEO1 */
191 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
192 OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
193 OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
194 OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
195 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
196 OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
197 OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
198 OMAP_DSS_COLOR_RGBX32,
199
200 /* OMAP_DSS_VIDEO2 */
201 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
202 OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
203 OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
204 OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
205 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
206 OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
207 OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
208 OMAP_DSS_COLOR_RGBX32,
209};
210
211static const char * const omap2_dss_clk_source_names[] = {
212 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "N/A",
213 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "N/A",
214 [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCLK1",
215};
216
217static const char * const omap3_dss_clk_source_names[] = {
218 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI1_PLL_FCLK",
219 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI2_PLL_FCLK",
220 [OMAP_DSS_CLK_SRC_FCK] = "DSS1_ALWON_FCLK",
221};
222
223static const char * const omap4_dss_clk_source_names[] = {
224 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "PLL1_CLK1",
225 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "PLL1_CLK2",
226 [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCLK",
227 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "PLL2_CLK1",
228 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "PLL2_CLK2",
229};
230
231static const struct dss_param_range omap2_dss_param_range[] = {
232 [FEAT_PARAM_DSS_FCK] = { 0, 173000000 },
233 [FEAT_PARAM_DSIPLL_REGN] = { 0, 0 },
234 [FEAT_PARAM_DSIPLL_REGM] = { 0, 0 },
235 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, 0 },
236 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, 0 },
237 [FEAT_PARAM_DSIPLL_FINT] = { 0, 0 },
238 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 },
239};
240
241static const struct dss_param_range omap3_dss_param_range[] = {
242 [FEAT_PARAM_DSS_FCK] = { 0, 173000000 },
243 [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 7) - 1 },
244 [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 11) - 1 },
245 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 4) - 1 },
246 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 4) - 1 },
247 [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 },
248 [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1},
249};
250
251static const struct dss_param_range omap4_dss_param_range[] = {
252 [FEAT_PARAM_DSS_FCK] = { 0, 186000000 },
253 [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 },
254 [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 },
255 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 },
256 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 },
257 [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 },
258 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
259};
260
261/* OMAP2 DSS Features */
262static const struct omap_dss_features omap2_dss_features = {
263 .reg_fields = omap2_dss_reg_fields,
264 .num_reg_fields = ARRAY_SIZE(omap2_dss_reg_fields),
265
266 .has_feature =
267 FEAT_LCDENABLEPOL | FEAT_LCDENABLESIGNAL |
268 FEAT_PCKFREEENABLE | FEAT_FUNCGATED |
269 FEAT_ROWREPEATENABLE | FEAT_RESIZECONF,
270
271 .num_mgrs = 2,
272 .num_ovls = 3,
273 .supported_displays = omap2_dss_supported_displays,
274 .supported_color_modes = omap2_dss_supported_color_modes,
275 .clksrc_names = omap2_dss_clk_source_names,
276 .dss_params = omap2_dss_param_range,
277};
278
279/* OMAP3 DSS Features */
280static const struct omap_dss_features omap3430_dss_features = {
281 .reg_fields = omap3_dss_reg_fields,
282 .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
283
284 .has_feature =
285 FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL |
286 FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
287 FEAT_FUNCGATED | FEAT_ROWREPEATENABLE |
288 FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF |
289 FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC,
290
291 .num_mgrs = 2,
292 .num_ovls = 3,
293 .supported_displays = omap3430_dss_supported_displays,
294 .supported_color_modes = omap3_dss_supported_color_modes,
295 .clksrc_names = omap3_dss_clk_source_names,
296 .dss_params = omap3_dss_param_range,
297};
298
299static const struct omap_dss_features omap3630_dss_features = {
300 .reg_fields = omap3_dss_reg_fields,
301 .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
302
303 .has_feature =
304 FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL |
305 FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
306 FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED |
307 FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT |
308 FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG |
309 FEAT_DSI_PLL_FREQSEL,
310
311 .num_mgrs = 2,
312 .num_ovls = 3,
313 .supported_displays = omap3630_dss_supported_displays,
314 .supported_color_modes = omap3_dss_supported_color_modes,
315 .clksrc_names = omap3_dss_clk_source_names,
316 .dss_params = omap3_dss_param_range,
317};
318
319/* OMAP4 DSS Features */
320/* For OMAP4430 ES 1.0 revision */
321static const struct omap_dss_features omap4430_es1_0_dss_features = {
322 .reg_fields = omap4_dss_reg_fields,
323 .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
324
325 .has_feature =
326 FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA |
327 FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 |
328 FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
329 FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
330 FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2,
331
332 .num_mgrs = 3,
333 .num_ovls = 3,
334 .supported_displays = omap4_dss_supported_displays,
335 .supported_color_modes = omap4_dss_supported_color_modes,
336 .clksrc_names = omap4_dss_clk_source_names,
337 .dss_params = omap4_dss_param_range,
338};
339
340/* For all the other OMAP4 versions */
341static const struct omap_dss_features omap4_dss_features = {
342 .reg_fields = omap4_dss_reg_fields,
343 .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
344
345 .has_feature =
346 FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA |
347 FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 |
348 FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
349 FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
350 FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE |
351 FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2,
352
353 .num_mgrs = 3,
354 .num_ovls = 3,
355 .supported_displays = omap4_dss_supported_displays,
356 .supported_color_modes = omap4_dss_supported_color_modes,
357 .clksrc_names = omap4_dss_clk_source_names,
358 .dss_params = omap4_dss_param_range,
359};
360
361/* Functions returning values related to a DSS feature */
362int dss_feat_get_num_mgrs(void)
363{
364 return omap_current_dss_features->num_mgrs;
365}
366
367int dss_feat_get_num_ovls(void)
368{
369 return omap_current_dss_features->num_ovls;
370}
371
372unsigned long dss_feat_get_param_min(enum dss_range_param param)
373{
374 return omap_current_dss_features->dss_params[param].min;
375}
376
377unsigned long dss_feat_get_param_max(enum dss_range_param param)
378{
379 return omap_current_dss_features->dss_params[param].max;
380}
381
382enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel)
383{
384 return omap_current_dss_features->supported_displays[channel];
385}
386
387enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)
388{
389 return omap_current_dss_features->supported_color_modes[plane];
390}
391
392bool dss_feat_color_mode_supported(enum omap_plane plane,
393 enum omap_color_mode color_mode)
394{
395 return omap_current_dss_features->supported_color_modes[plane] &
396 color_mode;
397}
398
399const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id)
400{
401 return omap_current_dss_features->clksrc_names[id];
402}
403
404/* DSS has_feature check */
405bool dss_has_feature(enum dss_feat_id id)
406{
407 return omap_current_dss_features->has_feature & id;
408}
409
410void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end)
411{
412 if (id >= omap_current_dss_features->num_reg_fields)
413 BUG();
414
415 *start = omap_current_dss_features->reg_fields[id].start;
416 *end = omap_current_dss_features->reg_fields[id].end;
417}
418
419void dss_features_init(void)
420{
421 if (cpu_is_omap24xx())
422 omap_current_dss_features = &omap2_dss_features;
423 else if (cpu_is_omap3630())
424 omap_current_dss_features = &omap3630_dss_features;
425 else if (cpu_is_omap34xx())
426 omap_current_dss_features = &omap3430_dss_features;
427 else if (omap_rev() == OMAP4430_REV_ES1_0)
428 omap_current_dss_features = &omap4430_es1_0_dss_features;
429 else if (cpu_is_omap44xx())
430 omap_current_dss_features = &omap4_dss_features;
431 else
432 DSSWARN("Unsupported OMAP version");
433}
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
new file mode 100644
index 000000000000..07b346f7d916
--- /dev/null
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -0,0 +1,96 @@
1/*
2 * linux/drivers/video/omap2/dss/dss_features.h
3 *
4 * Copyright (C) 2010 Texas Instruments
5 * Author: Archit Taneja <archit@ti.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#ifndef __OMAP2_DSS_FEATURES_H
21#define __OMAP2_DSS_FEATURES_H
22
23#define MAX_DSS_MANAGERS 3
24#define MAX_DSS_OVERLAYS 3
25#define MAX_DSS_LCD_MANAGERS 2
26#define MAX_NUM_DSI 2
27
28/* DSS has feature id */
29enum dss_feat_id {
30 FEAT_GLOBAL_ALPHA = 1 << 0,
31 FEAT_GLOBAL_ALPHA_VID1 = 1 << 1,
32 FEAT_PRE_MULT_ALPHA = 1 << 2,
33 FEAT_LCDENABLEPOL = 1 << 3,
34 FEAT_LCDENABLESIGNAL = 1 << 4,
35 FEAT_PCKFREEENABLE = 1 << 5,
36 FEAT_FUNCGATED = 1 << 6,
37 FEAT_MGR_LCD2 = 1 << 7,
38 FEAT_LINEBUFFERSPLIT = 1 << 8,
39 FEAT_ROWREPEATENABLE = 1 << 9,
40 FEAT_RESIZECONF = 1 << 10,
41 /* Independent core clk divider */
42 FEAT_CORE_CLK_DIV = 1 << 11,
43 FEAT_LCD_CLK_SRC = 1 << 12,
44 /* DSI-PLL power command 0x3 is not working */
45 FEAT_DSI_PLL_PWR_BUG = 1 << 13,
46 FEAT_DSI_PLL_FREQSEL = 1 << 14,
47 FEAT_DSI_DCS_CMD_CONFIG_VC = 1 << 15,
48 FEAT_DSI_VC_OCP_WIDTH = 1 << 16,
49 FEAT_DSI_REVERSE_TXCLKESC = 1 << 17,
50 FEAT_DSI_GNQ = 1 << 18,
51 FEAT_HDMI_CTS_SWMODE = 1 << 19,
52 FEAT_HANDLE_UV_SEPARATE = 1 << 20,
53 FEAT_ATTR2 = 1 << 21,
54};
55
56/* DSS register field id */
57enum dss_feat_reg_field {
58 FEAT_REG_FIRHINC,
59 FEAT_REG_FIRVINC,
60 FEAT_REG_FIFOHIGHTHRESHOLD,
61 FEAT_REG_FIFOLOWTHRESHOLD,
62 FEAT_REG_FIFOSIZE,
63 FEAT_REG_HORIZONTALACCU,
64 FEAT_REG_VERTICALACCU,
65 FEAT_REG_DISPC_CLK_SWITCH,
66 FEAT_REG_DSIPLL_REGN,
67 FEAT_REG_DSIPLL_REGM,
68 FEAT_REG_DSIPLL_REGM_DISPC,
69 FEAT_REG_DSIPLL_REGM_DSI,
70};
71
72enum dss_range_param {
73 FEAT_PARAM_DSS_FCK,
74 FEAT_PARAM_DSIPLL_REGN,
75 FEAT_PARAM_DSIPLL_REGM,
76 FEAT_PARAM_DSIPLL_REGM_DISPC,
77 FEAT_PARAM_DSIPLL_REGM_DSI,
78 FEAT_PARAM_DSIPLL_FINT,
79 FEAT_PARAM_DSIPLL_LPDIV,
80};
81
82/* DSS Feature Functions */
83int dss_feat_get_num_mgrs(void);
84int dss_feat_get_num_ovls(void);
85unsigned long dss_feat_get_param_min(enum dss_range_param param);
86unsigned long dss_feat_get_param_max(enum dss_range_param param);
87enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);
88enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
89bool dss_feat_color_mode_supported(enum omap_plane plane,
90 enum omap_color_mode color_mode);
91const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id);
92
93bool dss_has_feature(enum dss_feat_id id);
94void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
95void dss_features_init(void);
96#endif
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
new file mode 100644
index 000000000000..b0555f4f0a78
--- /dev/null
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -0,0 +1,1763 @@
1/*
2 * hdmi.c
3 *
4 * HDMI interface DSS driver setting for TI's OMAP4 family of processor.
5 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
6 * Authors: Yong Zhi
7 * Mythri pk <mythripk@ti.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as published by
11 * the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#define DSS_SUBSYS_NAME "HDMI"
23
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <linux/err.h>
27#include <linux/io.h>
28#include <linux/interrupt.h>
29#include <linux/mutex.h>
30#include <linux/delay.h>
31#include <linux/string.h>
32#include <video/omapdss.h>
33#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
34 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
35#include <sound/soc.h>
36#include <sound/pcm_params.h>
37#endif
38
39#include "dss.h"
40#include "hdmi.h"
41#include "dss_features.h"
42
43static struct {
44 struct mutex lock;
45 struct omap_display_platform_data *pdata;
46 struct platform_device *pdev;
47 void __iomem *base_wp; /* HDMI wrapper */
48 int code;
49 int mode;
50 u8 edid[HDMI_EDID_MAX_LENGTH];
51 u8 edid_set;
52 bool custom_set;
53 struct hdmi_config cfg;
54} hdmi;
55
56/*
57 * Logic for the below structure :
58 * user enters the CEA or VESA timings by specifying the HDMI/DVI code.
59 * There is a correspondence between CEA/VESA timing and code, please
60 * refer to section 6.3 in HDMI 1.3 specification for timing code.
61 *
62 * In the below structure, cea_vesa_timings corresponds to all OMAP4
63 * supported CEA and VESA timing values.code_cea corresponds to the CEA
64 * code, It is used to get the timing from cea_vesa_timing array.Similarly
65 * with code_vesa. Code_index is used for back mapping, that is once EDID
66 * is read from the TV, EDID is parsed to find the timing values and then
67 * map it to corresponding CEA or VESA index.
68 */
69
70static const struct hdmi_timings cea_vesa_timings[OMAP_HDMI_TIMINGS_NB] = {
71 { {640, 480, 25200, 96, 16, 48, 2, 10, 33} , 0 , 0},
72 { {1280, 720, 74250, 40, 440, 220, 5, 5, 20}, 1, 1},
73 { {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, 1, 1},
74 { {720, 480, 27027, 62, 16, 60, 6, 9, 30}, 0, 0},
75 { {2880, 576, 108000, 256, 48, 272, 5, 5, 39}, 0, 0},
76 { {1440, 240, 27027, 124, 38, 114, 3, 4, 15}, 0, 0},
77 { {1440, 288, 27000, 126, 24, 138, 3, 2, 19}, 0, 0},
78 { {1920, 540, 74250, 44, 528, 148, 5, 2, 15}, 1, 1},
79 { {1920, 540, 74250, 44, 88, 148, 5, 2, 15}, 1, 1},
80 { {1920, 1080, 148500, 44, 88, 148, 5, 4, 36}, 1, 1},
81 { {720, 576, 27000, 64, 12, 68, 5, 5, 39}, 0, 0},
82 { {1440, 576, 54000, 128, 24, 136, 5, 5, 39}, 0, 0},
83 { {1920, 1080, 148500, 44, 528, 148, 5, 4, 36}, 1, 1},
84 { {2880, 480, 108108, 248, 64, 240, 6, 9, 30}, 0, 0},
85 { {1920, 1080, 74250, 44, 638, 148, 5, 4, 36}, 1, 1},
86 /* VESA From Here */
87 { {640, 480, 25175, 96, 16, 48, 2 , 11, 31}, 0, 0},
88 { {800, 600, 40000, 128, 40, 88, 4 , 1, 23}, 1, 1},
89 { {848, 480, 33750, 112, 16, 112, 8 , 6, 23}, 1, 1},
90 { {1280, 768, 79500, 128, 64, 192, 7 , 3, 20}, 1, 0},
91 { {1280, 800, 83500, 128, 72, 200, 6 , 3, 22}, 1, 0},
92 { {1360, 768, 85500, 112, 64, 256, 6 , 3, 18}, 1, 1},
93 { {1280, 960, 108000, 112, 96, 312, 3 , 1, 36}, 1, 1},
94 { {1280, 1024, 108000, 112, 48, 248, 3 , 1, 38}, 1, 1},
95 { {1024, 768, 65000, 136, 24, 160, 6, 3, 29}, 0, 0},
96 { {1400, 1050, 121750, 144, 88, 232, 4, 3, 32}, 1, 0},
97 { {1440, 900, 106500, 152, 80, 232, 6, 3, 25}, 1, 0},
98 { {1680, 1050, 146250, 176 , 104, 280, 6, 3, 30}, 1, 0},
99 { {1366, 768, 85500, 143, 70, 213, 3, 3, 24}, 1, 1},
100 { {1920, 1080, 148500, 44, 148, 80, 5, 4, 36}, 1, 1},
101 { {1280, 768, 68250, 32, 48, 80, 7, 3, 12}, 0, 1},
102 { {1400, 1050, 101000, 32, 48, 80, 4, 3, 23}, 0, 1},
103 { {1680, 1050, 119000, 32, 48, 80, 6, 3, 21}, 0, 1},
104 { {1280, 800, 79500, 32, 48, 80, 6, 3, 14}, 0, 1},
105 { {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, 1, 1}
106};
107
108/*
109 * This is a static mapping array which maps the timing values
110 * with corresponding CEA / VESA code
111 */
112static const int code_index[OMAP_HDMI_TIMINGS_NB] = {
113 1, 19, 4, 2, 37, 6, 21, 20, 5, 16, 17, 29, 31, 35, 32,
114 /* <--15 CEA 17--> vesa*/
115 4, 9, 0xE, 0x17, 0x1C, 0x27, 0x20, 0x23, 0x10, 0x2A,
116 0X2F, 0x3A, 0X51, 0X52, 0x16, 0x29, 0x39, 0x1B
117};
118
119/*
120 * This is reverse static mapping which maps the CEA / VESA code
121 * to the corresponding timing values
122 */
123static const int code_cea[39] = {
124 -1, 0, 3, 3, 2, 8, 5, 5, -1, -1,
125 -1, -1, -1, -1, -1, -1, 9, 10, 10, 1,
126 7, 6, 6, -1, -1, -1, -1, -1, -1, 11,
127 11, 12, 14, -1, -1, 13, 13, 4, 4
128};
129
130static const int code_vesa[85] = {
131 -1, -1, -1, -1, 15, -1, -1, -1, -1, 16,
132 -1, -1, -1, -1, 17, -1, 23, -1, -1, -1,
133 -1, -1, 29, 18, -1, -1, -1, 32, 19, -1,
134 -1, -1, 21, -1, -1, 22, -1, -1, -1, 20,
135 -1, 30, 24, -1, -1, -1, -1, 25, -1, -1,
136 -1, -1, -1, -1, -1, -1, -1, 31, 26, -1,
137 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
138 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
139 -1, 27, 28, -1, 33};
140
141static const u8 edid_header[8] = {0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0};
142
143static inline void hdmi_write_reg(const struct hdmi_reg idx, u32 val)
144{
145 __raw_writel(val, hdmi.base_wp + idx.idx);
146}
147
148static inline u32 hdmi_read_reg(const struct hdmi_reg idx)
149{
150 return __raw_readl(hdmi.base_wp + idx.idx);
151}
152
153static inline int hdmi_wait_for_bit_change(const struct hdmi_reg idx,
154 int b2, int b1, u32 val)
155{
156 u32 t = 0;
157 while (val != REG_GET(idx, b2, b1)) {
158 udelay(1);
159 if (t++ > 10000)
160 return !val;
161 }
162 return val;
163}
164
165int hdmi_init_display(struct omap_dss_device *dssdev)
166{
167 DSSDBG("init_display\n");
168
169 return 0;
170}
171
172static int hdmi_pll_init(enum hdmi_clk_refsel refsel, int dcofreq,
173 struct hdmi_pll_info *fmt, u16 sd)
174{
175 u32 r;
176
177 /* PLL start always use manual mode */
178 REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 0, 0);
179
180 r = hdmi_read_reg(PLLCTRL_CFG1);
181 r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */
182 r = FLD_MOD(r, fmt->regn, 8, 1); /* CFG1_PLL_REGN */
183
184 hdmi_write_reg(PLLCTRL_CFG1, r);
185
186 r = hdmi_read_reg(PLLCTRL_CFG2);
187
188 r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */
189 r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */
190 r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */
191
192 if (dcofreq) {
193 /* divider programming for frequency beyond 1000Mhz */
194 REG_FLD_MOD(PLLCTRL_CFG3, sd, 17, 10);
195 r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */
196 } else {
197 r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */
198 }
199
200 hdmi_write_reg(PLLCTRL_CFG2, r);
201
202 r = hdmi_read_reg(PLLCTRL_CFG4);
203 r = FLD_MOD(r, fmt->regm2, 24, 18);
204 r = FLD_MOD(r, fmt->regmf, 17, 0);
205
206 hdmi_write_reg(PLLCTRL_CFG4, r);
207
208 /* go now */
209 REG_FLD_MOD(PLLCTRL_PLL_GO, 0x1, 0, 0);
210
211 /* wait for bit change */
212 if (hdmi_wait_for_bit_change(PLLCTRL_PLL_GO, 0, 0, 1) != 1) {
213 DSSERR("PLL GO bit not set\n");
214 return -ETIMEDOUT;
215 }
216
217 /* Wait till the lock bit is set in PLL status */
218 if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) {
219 DSSWARN("cannot lock PLL\n");
220 DSSWARN("CFG1 0x%x\n",
221 hdmi_read_reg(PLLCTRL_CFG1));
222 DSSWARN("CFG2 0x%x\n",
223 hdmi_read_reg(PLLCTRL_CFG2));
224 DSSWARN("CFG4 0x%x\n",
225 hdmi_read_reg(PLLCTRL_CFG4));
226 return -ETIMEDOUT;
227 }
228
229 DSSDBG("PLL locked!\n");
230
231 return 0;
232}
233
234/* PHY_PWR_CMD */
235static int hdmi_set_phy_pwr(enum hdmi_phy_pwr val)
236{
237 /* Command for power control of HDMI PHY */
238 REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 7, 6);
239
240 /* Status of the power control of HDMI PHY */
241 if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 5, 4, val) != val) {
242 DSSERR("Failed to set PHY power mode to %d\n", val);
243 return -ETIMEDOUT;
244 }
245
246 return 0;
247}
248
249/* PLL_PWR_CMD */
250static int hdmi_set_pll_pwr(enum hdmi_pll_pwr val)
251{
252 /* Command for power control of HDMI PLL */
253 REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 3, 2);
254
255 /* wait till PHY_PWR_STATUS is set */
256 if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 1, 0, val) != val) {
257 DSSERR("Failed to set PHY_PWR_STATUS\n");
258 return -ETIMEDOUT;
259 }
260
261 return 0;
262}
263
264static int hdmi_pll_reset(void)
265{
266 /* SYSRESET controlled by power FSM */
267 REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 3, 3);
268
269 /* READ 0x0 reset is in progress */
270 if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) {
271 DSSERR("Failed to sysreset PLL\n");
272 return -ETIMEDOUT;
273 }
274
275 return 0;
276}
277
278static int hdmi_phy_init(void)
279{
280 u16 r = 0;
281
282 r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_LDOON);
283 if (r)
284 return r;
285
286 r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_TXON);
287 if (r)
288 return r;
289
290 /*
291 * Read address 0 in order to get the SCP reset done completed
292 * Dummy access performed to make sure reset is done
293 */
294 hdmi_read_reg(HDMI_TXPHY_TX_CTRL);
295
296 /*
297 * Write to phy address 0 to configure the clock
298 * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field
299 */
300 REG_FLD_MOD(HDMI_TXPHY_TX_CTRL, 0x1, 31, 30);
301
302 /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */
303 hdmi_write_reg(HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000);
304
305 /* Setup max LDO voltage */
306 REG_FLD_MOD(HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0);
307
308 /* Write to phy address 3 to change the polarity control */
309 REG_FLD_MOD(HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27);
310
311 return 0;
312}
313
314static int hdmi_wait_softreset(void)
315{
316 /* reset W1 */
317 REG_FLD_MOD(HDMI_WP_SYSCONFIG, 0x1, 0, 0);
318
319 /* wait till SOFTRESET == 0 */
320 if (hdmi_wait_for_bit_change(HDMI_WP_SYSCONFIG, 0, 0, 0) != 0) {
321 DSSERR("sysconfig reset failed\n");
322 return -ETIMEDOUT;
323 }
324
325 return 0;
326}
327
328static int hdmi_pll_program(struct hdmi_pll_info *fmt)
329{
330 u16 r = 0;
331 enum hdmi_clk_refsel refsel;
332
333 /* wait for wrapper reset */
334 r = hdmi_wait_softreset();
335 if (r)
336 return r;
337
338 r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
339 if (r)
340 return r;
341
342 r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
343 if (r)
344 return r;
345
346 r = hdmi_pll_reset();
347 if (r)
348 return r;
349
350 refsel = HDMI_REFSEL_SYSCLK;
351
352 r = hdmi_pll_init(refsel, fmt->dcofreq, fmt, fmt->regsd);
353 if (r)
354 return r;
355
356 return 0;
357}
358
359static void hdmi_phy_off(void)
360{
361 hdmi_set_phy_pwr(HDMI_PHYPWRCMD_OFF);
362}
363
364static int hdmi_core_ddc_edid(u8 *pedid, int ext)
365{
366 u32 i, j;
367 char checksum = 0;
368 u32 offset = 0;
369
370 /* Turn on CLK for DDC */
371 REG_FLD_MOD(HDMI_CORE_AV_DPD, 0x7, 2, 0);
372
373 /*
374 * SW HACK : Without the Delay DDC(i2c bus) reads 0 values /
375 * right shifted values( The behavior is not consistent and seen only
376 * with some TV's)
377 */
378 usleep_range(800, 1000);
379
380 if (!ext) {
381 /* Clk SCL Devices */
382 REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0xA, 3, 0);
383
384 /* HDMI_CORE_DDC_STATUS_IN_PROG */
385 if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS,
386 4, 4, 0) != 0) {
387 DSSERR("Failed to program DDC\n");
388 return -ETIMEDOUT;
389 }
390
391 /* Clear FIFO */
392 REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x9, 3, 0);
393
394 /* HDMI_CORE_DDC_STATUS_IN_PROG */
395 if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS,
396 4, 4, 0) != 0) {
397 DSSERR("Failed to program DDC\n");
398 return -ETIMEDOUT;
399 }
400
401 } else {
402 if (ext % 2 != 0)
403 offset = 0x80;
404 }
405
406 /* Load Segment Address Register */
407 REG_FLD_MOD(HDMI_CORE_DDC_SEGM, ext/2, 7, 0);
408
409 /* Load Slave Address Register */
410 REG_FLD_MOD(HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1);
411
412 /* Load Offset Address Register */
413 REG_FLD_MOD(HDMI_CORE_DDC_OFFSET, offset, 7, 0);
414
415 /* Load Byte Count */
416 REG_FLD_MOD(HDMI_CORE_DDC_COUNT1, 0x80, 7, 0);
417 REG_FLD_MOD(HDMI_CORE_DDC_COUNT2, 0x0, 1, 0);
418
419 /* Set DDC_CMD */
420 if (ext)
421 REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x4, 3, 0);
422 else
423 REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x2, 3, 0);
424
425 /* HDMI_CORE_DDC_STATUS_BUS_LOW */
426 if (REG_GET(HDMI_CORE_DDC_STATUS, 6, 6) == 1) {
427 DSSWARN("I2C Bus Low?\n");
428 return -EIO;
429 }
430 /* HDMI_CORE_DDC_STATUS_NO_ACK */
431 if (REG_GET(HDMI_CORE_DDC_STATUS, 5, 5) == 1) {
432 DSSWARN("I2C No Ack\n");
433 return -EIO;
434 }
435
436 i = ext * 128;
437 j = 0;
438 while (((REG_GET(HDMI_CORE_DDC_STATUS, 4, 4) == 1) ||
439 (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0)) &&
440 j < 128) {
441
442 if (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0) {
443 /* FIFO not empty */
444 pedid[i++] = REG_GET(HDMI_CORE_DDC_DATA, 7, 0);
445 j++;
446 }
447 }
448
449 for (j = 0; j < 128; j++)
450 checksum += pedid[j];
451
452 if (checksum != 0) {
453 DSSERR("E-EDID checksum failed!!\n");
454 return -EIO;
455 }
456
457 return 0;
458}
459
460static int read_edid(u8 *pedid, u16 max_length)
461{
462 int r = 0, n = 0, i = 0;
463 int max_ext_blocks = (max_length / 128) - 1;
464
465 r = hdmi_core_ddc_edid(pedid, 0);
466 if (r) {
467 return r;
468 } else {
469 n = pedid[0x7e];
470
471 /*
472 * README: need to comply with max_length set by the caller.
473 * Better implementation should be to allocate necessary
474 * memory to store EDID according to nb_block field found
475 * in first block
476 */
477 if (n > max_ext_blocks)
478 n = max_ext_blocks;
479
480 for (i = 1; i <= n; i++) {
481 r = hdmi_core_ddc_edid(pedid, i);
482 if (r)
483 return r;
484 }
485 }
486 return 0;
487}
488
489static int get_timings_index(void)
490{
491 int code;
492
493 if (hdmi.mode == 0)
494 code = code_vesa[hdmi.code];
495 else
496 code = code_cea[hdmi.code];
497
498 if (code == -1) {
499 /* HDMI code 4 corresponds to 640 * 480 VGA */
500 hdmi.code = 4;
501 /* DVI mode 1 corresponds to HDMI 0 to DVI */
502 hdmi.mode = HDMI_DVI;
503
504 code = code_vesa[hdmi.code];
505 }
506 return code;
507}
508
509static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
510{
511 int i = 0, code = -1, temp_vsync = 0, temp_hsync = 0;
512 int timing_vsync = 0, timing_hsync = 0;
513 struct omap_video_timings temp;
514 struct hdmi_cm cm = {-1};
515 DSSDBG("hdmi_get_code\n");
516
517 for (i = 0; i < OMAP_HDMI_TIMINGS_NB; i++) {
518 temp = cea_vesa_timings[i].timings;
519 if ((temp.pixel_clock == timing->pixel_clock) &&
520 (temp.x_res == timing->x_res) &&
521 (temp.y_res == timing->y_res)) {
522
523 temp_hsync = temp.hfp + temp.hsw + temp.hbp;
524 timing_hsync = timing->hfp + timing->hsw + timing->hbp;
525 temp_vsync = temp.vfp + temp.vsw + temp.vbp;
526 timing_vsync = timing->vfp + timing->vsw + timing->vbp;
527
528 DSSDBG("temp_hsync = %d , temp_vsync = %d"
529 "timing_hsync = %d, timing_vsync = %d\n",
530 temp_hsync, temp_hsync,
531 timing_hsync, timing_vsync);
532
533 if ((temp_hsync == timing_hsync) &&
534 (temp_vsync == timing_vsync)) {
535 code = i;
536 cm.code = code_index[i];
537 if (code < 14)
538 cm.mode = HDMI_HDMI;
539 else
540 cm.mode = HDMI_DVI;
541 DSSDBG("Hdmi_code = %d mode = %d\n",
542 cm.code, cm.mode);
543 break;
544 }
545 }
546 }
547
548 return cm;
549}
550
551static void get_horz_vert_timing_info(int current_descriptor_addrs, u8 *edid ,
552 struct omap_video_timings *timings)
553{
554 /* X and Y resolution */
555 timings->x_res = (((edid[current_descriptor_addrs + 4] & 0xF0) << 4) |
556 edid[current_descriptor_addrs + 2]);
557 timings->y_res = (((edid[current_descriptor_addrs + 7] & 0xF0) << 4) |
558 edid[current_descriptor_addrs + 5]);
559
560 timings->pixel_clock = ((edid[current_descriptor_addrs + 1] << 8) |
561 edid[current_descriptor_addrs]);
562
563 timings->pixel_clock = 10 * timings->pixel_clock;
564
565 /* HORIZONTAL FRONT PORCH */
566 timings->hfp = edid[current_descriptor_addrs + 8] |
567 ((edid[current_descriptor_addrs + 11] & 0xc0) << 2);
568 /* HORIZONTAL SYNC WIDTH */
569 timings->hsw = edid[current_descriptor_addrs + 9] |
570 ((edid[current_descriptor_addrs + 11] & 0x30) << 4);
571 /* HORIZONTAL BACK PORCH */
572 timings->hbp = (((edid[current_descriptor_addrs + 4] & 0x0F) << 8) |
573 edid[current_descriptor_addrs + 3]) -
574 (timings->hfp + timings->hsw);
575 /* VERTICAL FRONT PORCH */
576 timings->vfp = ((edid[current_descriptor_addrs + 10] & 0xF0) >> 4) |
577 ((edid[current_descriptor_addrs + 11] & 0x0f) << 2);
578 /* VERTICAL SYNC WIDTH */
579 timings->vsw = (edid[current_descriptor_addrs + 10] & 0x0F) |
580 ((edid[current_descriptor_addrs + 11] & 0x03) << 4);
581 /* VERTICAL BACK PORCH */
582 timings->vbp = (((edid[current_descriptor_addrs + 7] & 0x0F) << 8) |
583 edid[current_descriptor_addrs + 6]) -
584 (timings->vfp + timings->vsw);
585
586}
587
588/* Description : This function gets the resolution information from EDID */
589static void get_edid_timing_data(u8 *edid)
590{
591 u8 count;
592 u16 current_descriptor_addrs;
593 struct hdmi_cm cm;
594 struct omap_video_timings edid_timings;
595
596 /* search block 0, there are 4 DTDs arranged in priority order */
597 for (count = 0; count < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; count++) {
598 current_descriptor_addrs =
599 EDID_DESCRIPTOR_BLOCK0_ADDRESS +
600 count * EDID_TIMING_DESCRIPTOR_SIZE;
601 get_horz_vert_timing_info(current_descriptor_addrs,
602 edid, &edid_timings);
603 cm = hdmi_get_code(&edid_timings);
604 DSSDBG("Block0[%d] value matches code = %d , mode = %d\n",
605 count, cm.code, cm.mode);
606 if (cm.code == -1) {
607 continue;
608 } else {
609 hdmi.code = cm.code;
610 hdmi.mode = cm.mode;
611 DSSDBG("code = %d , mode = %d\n",
612 hdmi.code, hdmi.mode);
613 return;
614 }
615 }
616 if (edid[0x7e] != 0x00) {
617 for (count = 0; count < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR;
618 count++) {
619 current_descriptor_addrs =
620 EDID_DESCRIPTOR_BLOCK1_ADDRESS +
621 count * EDID_TIMING_DESCRIPTOR_SIZE;
622 get_horz_vert_timing_info(current_descriptor_addrs,
623 edid, &edid_timings);
624 cm = hdmi_get_code(&edid_timings);
625 DSSDBG("Block1[%d] value matches code = %d, mode = %d",
626 count, cm.code, cm.mode);
627 if (cm.code == -1) {
628 continue;
629 } else {
630 hdmi.code = cm.code;
631 hdmi.mode = cm.mode;
632 DSSDBG("code = %d , mode = %d\n",
633 hdmi.code, hdmi.mode);
634 return;
635 }
636 }
637 }
638
639 DSSINFO("no valid timing found , falling back to VGA\n");
640 hdmi.code = 4; /* setting default value of 640 480 VGA */
641 hdmi.mode = HDMI_DVI;
642}
643
644static void hdmi_read_edid(struct omap_video_timings *dp)
645{
646 int ret = 0, code;
647
648 memset(hdmi.edid, 0, HDMI_EDID_MAX_LENGTH);
649
650 if (!hdmi.edid_set)
651 ret = read_edid(hdmi.edid, HDMI_EDID_MAX_LENGTH);
652
653 if (!ret) {
654 if (!memcmp(hdmi.edid, edid_header, sizeof(edid_header))) {
655 /* search for timings of default resolution */
656 get_edid_timing_data(hdmi.edid);
657 hdmi.edid_set = true;
658 }
659 } else {
660 DSSWARN("failed to read E-EDID\n");
661 }
662
663 if (!hdmi.edid_set) {
664 DSSINFO("fallback to VGA\n");
665 hdmi.code = 4; /* setting default value of 640 480 VGA */
666 hdmi.mode = HDMI_DVI;
667 }
668
669 code = get_timings_index();
670
671 *dp = cea_vesa_timings[code].timings;
672}
673
674static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,
675 struct hdmi_core_infoframe_avi *avi_cfg,
676 struct hdmi_core_packet_enable_repeat *repeat_cfg)
677{
678 DSSDBG("Enter hdmi_core_init\n");
679
680 /* video core */
681 video_cfg->ip_bus_width = HDMI_INPUT_8BIT;
682 video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT;
683 video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE;
684 video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE;
685 video_cfg->hdmi_dvi = HDMI_DVI;
686 video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK;
687
688 /* info frame */
689 avi_cfg->db1_format = 0;
690 avi_cfg->db1_active_info = 0;
691 avi_cfg->db1_bar_info_dv = 0;
692 avi_cfg->db1_scan_info = 0;
693 avi_cfg->db2_colorimetry = 0;
694 avi_cfg->db2_aspect_ratio = 0;
695 avi_cfg->db2_active_fmt_ar = 0;
696 avi_cfg->db3_itc = 0;
697 avi_cfg->db3_ec = 0;
698 avi_cfg->db3_q_range = 0;
699 avi_cfg->db3_nup_scaling = 0;
700 avi_cfg->db4_videocode = 0;
701 avi_cfg->db5_pixel_repeat = 0;
702 avi_cfg->db6_7_line_eoftop = 0 ;
703 avi_cfg->db8_9_line_sofbottom = 0;
704 avi_cfg->db10_11_pixel_eofleft = 0;
705 avi_cfg->db12_13_pixel_sofright = 0;
706
707 /* packet enable and repeat */
708 repeat_cfg->audio_pkt = 0;
709 repeat_cfg->audio_pkt_repeat = 0;
710 repeat_cfg->avi_infoframe = 0;
711 repeat_cfg->avi_infoframe_repeat = 0;
712 repeat_cfg->gen_cntrl_pkt = 0;
713 repeat_cfg->gen_cntrl_pkt_repeat = 0;
714 repeat_cfg->generic_pkt = 0;
715 repeat_cfg->generic_pkt_repeat = 0;
716}
717
718static void hdmi_core_powerdown_disable(void)
719{
720 DSSDBG("Enter hdmi_core_powerdown_disable\n");
721 REG_FLD_MOD(HDMI_CORE_CTRL1, 0x0, 0, 0);
722}
723
724static void hdmi_core_swreset_release(void)
725{
726 DSSDBG("Enter hdmi_core_swreset_release\n");
727 REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x0, 0, 0);
728}
729
730static void hdmi_core_swreset_assert(void)
731{
732 DSSDBG("Enter hdmi_core_swreset_assert\n");
733 REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x1, 0, 0);
734}
735
736/* DSS_HDMI_CORE_VIDEO_CONFIG */
737static void hdmi_core_video_config(struct hdmi_core_video_config *cfg)
738{
739 u32 r = 0;
740
741 /* sys_ctrl1 default configuration not tunable */
742 r = hdmi_read_reg(HDMI_CORE_CTRL1);
743 r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5);
744 r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4);
745 r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2);
746 r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1);
747 hdmi_write_reg(HDMI_CORE_CTRL1, r);
748
749 REG_FLD_MOD(HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6);
750
751 /* Vid_Mode */
752 r = hdmi_read_reg(HDMI_CORE_SYS_VID_MODE);
753
754 /* dither truncation configuration */
755 if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) {
756 r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6);
757 r = FLD_MOD(r, 1, 5, 5);
758 } else {
759 r = FLD_MOD(r, cfg->op_dither_truc, 7, 6);
760 r = FLD_MOD(r, 0, 5, 5);
761 }
762 hdmi_write_reg(HDMI_CORE_SYS_VID_MODE, r);
763
764 /* HDMI_Ctrl */
765 r = hdmi_read_reg(HDMI_CORE_AV_HDMI_CTRL);
766 r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6);
767 r = FLD_MOD(r, cfg->pkt_mode, 5, 3);
768 r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0);
769 hdmi_write_reg(HDMI_CORE_AV_HDMI_CTRL, r);
770
771 /* TMDS_CTRL */
772 REG_FLD_MOD(HDMI_CORE_SYS_TMDS_CTRL,
773 cfg->tclk_sel_clkmult, 6, 5);
774}
775
776static void hdmi_core_aux_infoframe_avi_config(
777 struct hdmi_core_infoframe_avi info_avi)
778{
779 u32 val;
780 char sum = 0, checksum = 0;
781
782 sum += 0x82 + 0x002 + 0x00D;
783 hdmi_write_reg(HDMI_CORE_AV_AVI_TYPE, 0x082);
784 hdmi_write_reg(HDMI_CORE_AV_AVI_VERS, 0x002);
785 hdmi_write_reg(HDMI_CORE_AV_AVI_LEN, 0x00D);
786
787 val = (info_avi.db1_format << 5) |
788 (info_avi.db1_active_info << 4) |
789 (info_avi.db1_bar_info_dv << 2) |
790 (info_avi.db1_scan_info);
791 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(0), val);
792 sum += val;
793
794 val = (info_avi.db2_colorimetry << 6) |
795 (info_avi.db2_aspect_ratio << 4) |
796 (info_avi.db2_active_fmt_ar);
797 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(1), val);
798 sum += val;
799
800 val = (info_avi.db3_itc << 7) |
801 (info_avi.db3_ec << 4) |
802 (info_avi.db3_q_range << 2) |
803 (info_avi.db3_nup_scaling);
804 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(2), val);
805 sum += val;
806
807 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(3), info_avi.db4_videocode);
808 sum += info_avi.db4_videocode;
809
810 val = info_avi.db5_pixel_repeat;
811 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(4), val);
812 sum += val;
813
814 val = info_avi.db6_7_line_eoftop & 0x00FF;
815 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(5), val);
816 sum += val;
817
818 val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF);
819 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(6), val);
820 sum += val;
821
822 val = info_avi.db8_9_line_sofbottom & 0x00FF;
823 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(7), val);
824 sum += val;
825
826 val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF);
827 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(8), val);
828 sum += val;
829
830 val = info_avi.db10_11_pixel_eofleft & 0x00FF;
831 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(9), val);
832 sum += val;
833
834 val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF);
835 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(10), val);
836 sum += val;
837
838 val = info_avi.db12_13_pixel_sofright & 0x00FF;
839 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(11), val);
840 sum += val;
841
842 val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF);
843 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(12), val);
844 sum += val;
845
846 checksum = 0x100 - sum;
847 hdmi_write_reg(HDMI_CORE_AV_AVI_CHSUM, checksum);
848}
849
850static void hdmi_core_av_packet_config(
851 struct hdmi_core_packet_enable_repeat repeat_cfg)
852{
853 /* enable/repeat the infoframe */
854 hdmi_write_reg(HDMI_CORE_AV_PB_CTRL1,
855 (repeat_cfg.audio_pkt << 5) |
856 (repeat_cfg.audio_pkt_repeat << 4) |
857 (repeat_cfg.avi_infoframe << 1) |
858 (repeat_cfg.avi_infoframe_repeat));
859
860 /* enable/repeat the packet */
861 hdmi_write_reg(HDMI_CORE_AV_PB_CTRL2,
862 (repeat_cfg.gen_cntrl_pkt << 3) |
863 (repeat_cfg.gen_cntrl_pkt_repeat << 2) |
864 (repeat_cfg.generic_pkt << 1) |
865 (repeat_cfg.generic_pkt_repeat));
866}
867
868static void hdmi_wp_init(struct omap_video_timings *timings,
869 struct hdmi_video_format *video_fmt,
870 struct hdmi_video_interface *video_int)
871{
872 DSSDBG("Enter hdmi_wp_init\n");
873
874 timings->hbp = 0;
875 timings->hfp = 0;
876 timings->hsw = 0;
877 timings->vbp = 0;
878 timings->vfp = 0;
879 timings->vsw = 0;
880
881 video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444;
882 video_fmt->y_res = 0;
883 video_fmt->x_res = 0;
884
885 video_int->vsp = 0;
886 video_int->hsp = 0;
887
888 video_int->interlacing = 0;
889 video_int->tm = 0; /* HDMI_TIMING_SLAVE */
890
891}
892
893static void hdmi_wp_video_start(bool start)
894{
895 REG_FLD_MOD(HDMI_WP_VIDEO_CFG, start, 31, 31);
896}
897
898static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt,
899 struct omap_video_timings *timings, struct hdmi_config *param)
900{
901 DSSDBG("Enter hdmi_wp_video_init_format\n");
902
903 video_fmt->y_res = param->timings.timings.y_res;
904 video_fmt->x_res = param->timings.timings.x_res;
905
906 timings->hbp = param->timings.timings.hbp;
907 timings->hfp = param->timings.timings.hfp;
908 timings->hsw = param->timings.timings.hsw;
909 timings->vbp = param->timings.timings.vbp;
910 timings->vfp = param->timings.timings.vfp;
911 timings->vsw = param->timings.timings.vsw;
912}
913
914static void hdmi_wp_video_config_format(
915 struct hdmi_video_format *video_fmt)
916{
917 u32 l = 0;
918
919 REG_FLD_MOD(HDMI_WP_VIDEO_CFG, video_fmt->packing_mode, 10, 8);
920
921 l |= FLD_VAL(video_fmt->y_res, 31, 16);
922 l |= FLD_VAL(video_fmt->x_res, 15, 0);
923 hdmi_write_reg(HDMI_WP_VIDEO_SIZE, l);
924}
925
926static void hdmi_wp_video_config_interface(
927 struct hdmi_video_interface *video_int)
928{
929 u32 r;
930 DSSDBG("Enter hdmi_wp_video_config_interface\n");
931
932 r = hdmi_read_reg(HDMI_WP_VIDEO_CFG);
933 r = FLD_MOD(r, video_int->vsp, 7, 7);
934 r = FLD_MOD(r, video_int->hsp, 6, 6);
935 r = FLD_MOD(r, video_int->interlacing, 3, 3);
936 r = FLD_MOD(r, video_int->tm, 1, 0);
937 hdmi_write_reg(HDMI_WP_VIDEO_CFG, r);
938}
939
940static void hdmi_wp_video_config_timing(
941 struct omap_video_timings *timings)
942{
943 u32 timing_h = 0;
944 u32 timing_v = 0;
945
946 DSSDBG("Enter hdmi_wp_video_config_timing\n");
947
948 timing_h |= FLD_VAL(timings->hbp, 31, 20);
949 timing_h |= FLD_VAL(timings->hfp, 19, 8);
950 timing_h |= FLD_VAL(timings->hsw, 7, 0);
951 hdmi_write_reg(HDMI_WP_VIDEO_TIMING_H, timing_h);
952
953 timing_v |= FLD_VAL(timings->vbp, 31, 20);
954 timing_v |= FLD_VAL(timings->vfp, 19, 8);
955 timing_v |= FLD_VAL(timings->vsw, 7, 0);
956 hdmi_write_reg(HDMI_WP_VIDEO_TIMING_V, timing_v);
957}
958
959static void hdmi_basic_configure(struct hdmi_config *cfg)
960{
961 /* HDMI */
962 struct omap_video_timings video_timing;
963 struct hdmi_video_format video_format;
964 struct hdmi_video_interface video_interface;
965 /* HDMI core */
966 struct hdmi_core_infoframe_avi avi_cfg;
967 struct hdmi_core_video_config v_core_cfg;
968 struct hdmi_core_packet_enable_repeat repeat_cfg;
969
970 hdmi_wp_init(&video_timing, &video_format,
971 &video_interface);
972
973 hdmi_core_init(&v_core_cfg,
974 &avi_cfg,
975 &repeat_cfg);
976
977 hdmi_wp_video_init_format(&video_format,
978 &video_timing, cfg);
979
980 hdmi_wp_video_config_timing(&video_timing);
981
982 /* video config */
983 video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422;
984
985 hdmi_wp_video_config_format(&video_format);
986
987 video_interface.vsp = cfg->timings.vsync_pol;
988 video_interface.hsp = cfg->timings.hsync_pol;
989 video_interface.interlacing = cfg->interlace;
990 video_interface.tm = 1 ; /* HDMI_TIMING_MASTER_24BIT */
991
992 hdmi_wp_video_config_interface(&video_interface);
993
994 /*
995 * configure core video part
996 * set software reset in the core
997 */
998 hdmi_core_swreset_assert();
999
1000 /* power down off */
1001 hdmi_core_powerdown_disable();
1002
1003 v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL;
1004 v_core_cfg.hdmi_dvi = cfg->cm.mode;
1005
1006 hdmi_core_video_config(&v_core_cfg);
1007
1008 /* release software reset in the core */
1009 hdmi_core_swreset_release();
1010
1011 /*
1012 * configure packet
1013 * info frame video see doc CEA861-D page 65
1014 */
1015 avi_cfg.db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB;
1016 avi_cfg.db1_active_info =
1017 HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF;
1018 avi_cfg.db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO;
1019 avi_cfg.db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0;
1020 avi_cfg.db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO;
1021 avi_cfg.db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO;
1022 avi_cfg.db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME;
1023 avi_cfg.db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO;
1024 avi_cfg.db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601;
1025 avi_cfg.db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT;
1026 avi_cfg.db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO;
1027 avi_cfg.db4_videocode = cfg->cm.code;
1028 avi_cfg.db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO;
1029 avi_cfg.db6_7_line_eoftop = 0;
1030 avi_cfg.db8_9_line_sofbottom = 0;
1031 avi_cfg.db10_11_pixel_eofleft = 0;
1032 avi_cfg.db12_13_pixel_sofright = 0;
1033
1034 hdmi_core_aux_infoframe_avi_config(avi_cfg);
1035
1036 /* enable/repeat the infoframe */
1037 repeat_cfg.avi_infoframe = HDMI_PACKETENABLE;
1038 repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON;
1039 /* wakeup */
1040 repeat_cfg.audio_pkt = HDMI_PACKETENABLE;
1041 repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON;
1042 hdmi_core_av_packet_config(repeat_cfg);
1043}
1044
1045static void update_hdmi_timings(struct hdmi_config *cfg,
1046 struct omap_video_timings *timings, int code)
1047{
1048 cfg->timings.timings.x_res = timings->x_res;
1049 cfg->timings.timings.y_res = timings->y_res;
1050 cfg->timings.timings.hbp = timings->hbp;
1051 cfg->timings.timings.hfp = timings->hfp;
1052 cfg->timings.timings.hsw = timings->hsw;
1053 cfg->timings.timings.vbp = timings->vbp;
1054 cfg->timings.timings.vfp = timings->vfp;
1055 cfg->timings.timings.vsw = timings->vsw;
1056 cfg->timings.timings.pixel_clock = timings->pixel_clock;
1057 cfg->timings.vsync_pol = cea_vesa_timings[code].vsync_pol;
1058 cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol;
1059}
1060
1061static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
1062 struct hdmi_pll_info *pi)
1063{
1064 unsigned long clkin, refclk;
1065 u32 mf;
1066
1067 clkin = dss_clk_get_rate(DSS_CLK_SYSCK) / 10000;
1068 /*
1069 * Input clock is predivided by N + 1
1070 * out put of which is reference clk
1071 */
1072 pi->regn = dssdev->clocks.hdmi.regn;
1073 refclk = clkin / (pi->regn + 1);
1074
1075 /*
1076 * multiplier is pixel_clk/ref_clk
1077 * Multiplying by 100 to avoid fractional part removal
1078 */
1079 pi->regm = (phy * 100 / (refclk)) / 100;
1080 pi->regm2 = dssdev->clocks.hdmi.regm2;
1081
1082 /*
1083 * fractional multiplier is remainder of the difference between
1084 * multiplier and actual phy(required pixel clock thus should be
1085 * multiplied by 2^18(262144) divided by the reference clock
1086 */
1087 mf = (phy - pi->regm * refclk) * 262144;
1088 pi->regmf = mf / (refclk);
1089
1090 /*
1091 * Dcofreq should be set to 1 if required pixel clock
1092 * is greater than 1000MHz
1093 */
1094 pi->dcofreq = phy > 1000 * 100;
1095 pi->regsd = ((pi->regm * clkin / 10) / ((pi->regn + 1) * 250) + 5) / 10;
1096
1097 DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf);
1098 DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
1099}
1100
1101static void hdmi_enable_clocks(int enable)
1102{
1103 if (enable)
1104 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK |
1105 DSS_CLK_SYSCK | DSS_CLK_VIDFCK);
1106 else
1107 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK |
1108 DSS_CLK_SYSCK | DSS_CLK_VIDFCK);
1109}
1110
1111static int hdmi_power_on(struct omap_dss_device *dssdev)
1112{
1113 int r, code = 0;
1114 struct hdmi_pll_info pll_data;
1115 struct omap_video_timings *p;
1116 unsigned long phy;
1117
1118 hdmi_enable_clocks(1);
1119
1120 dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0);
1121
1122 p = &dssdev->panel.timings;
1123
1124 DSSDBG("hdmi_power_on x_res= %d y_res = %d\n",
1125 dssdev->panel.timings.x_res,
1126 dssdev->panel.timings.y_res);
1127
1128 if (!hdmi.custom_set) {
1129 DSSDBG("Read EDID as no EDID is not set on poweron\n");
1130 hdmi_read_edid(p);
1131 }
1132 code = get_timings_index();
1133 dssdev->panel.timings = cea_vesa_timings[code].timings;
1134 update_hdmi_timings(&hdmi.cfg, p, code);
1135
1136 phy = p->pixel_clock;
1137
1138 hdmi_compute_pll(dssdev, phy, &pll_data);
1139
1140 hdmi_wp_video_start(0);
1141
1142 /* config the PLL and PHY first */
1143 r = hdmi_pll_program(&pll_data);
1144 if (r) {
1145 DSSDBG("Failed to lock PLL\n");
1146 goto err;
1147 }
1148
1149 r = hdmi_phy_init();
1150 if (r) {
1151 DSSDBG("Failed to start PHY\n");
1152 goto err;
1153 }
1154
1155 hdmi.cfg.cm.mode = hdmi.mode;
1156 hdmi.cfg.cm.code = hdmi.code;
1157 hdmi_basic_configure(&hdmi.cfg);
1158
1159 /* Make selection of HDMI in DSS */
1160 dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
1161
1162 /* Select the dispc clock source as PRCM clock, to ensure that it is not
1163 * DSI PLL source as the clock selected by DSI PLL might not be
1164 * sufficient for the resolution selected / that can be changed
1165 * dynamically by user. This can be moved to single location , say
1166 * Boardfile.
1167 */
1168 dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
1169
1170 /* bypass TV gamma table */
1171 dispc_enable_gamma_table(0);
1172
1173 /* tv size */
1174 dispc_set_digit_size(dssdev->panel.timings.x_res,
1175 dssdev->panel.timings.y_res);
1176
1177 dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 1);
1178
1179 hdmi_wp_video_start(1);
1180
1181 return 0;
1182err:
1183 hdmi_enable_clocks(0);
1184 return -EIO;
1185}
1186
1187static void hdmi_power_off(struct omap_dss_device *dssdev)
1188{
1189 dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0);
1190
1191 hdmi_wp_video_start(0);
1192 hdmi_phy_off();
1193 hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
1194 hdmi_enable_clocks(0);
1195
1196 hdmi.edid_set = 0;
1197}
1198
1199int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
1200 struct omap_video_timings *timings)
1201{
1202 struct hdmi_cm cm;
1203
1204 cm = hdmi_get_code(timings);
1205 if (cm.code == -1) {
1206 DSSERR("Invalid timing entered\n");
1207 return -EINVAL;
1208 }
1209
1210 return 0;
1211
1212}
1213
1214void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
1215{
1216 struct hdmi_cm cm;
1217
1218 hdmi.custom_set = 1;
1219 cm = hdmi_get_code(&dssdev->panel.timings);
1220 hdmi.code = cm.code;
1221 hdmi.mode = cm.mode;
1222 omapdss_hdmi_display_enable(dssdev);
1223 hdmi.custom_set = 0;
1224}
1225
1226int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
1227{
1228 int r = 0;
1229
1230 DSSDBG("ENTER hdmi_display_enable\n");
1231
1232 mutex_lock(&hdmi.lock);
1233
1234 r = omap_dss_start_device(dssdev);
1235 if (r) {
1236 DSSERR("failed to start device\n");
1237 goto err0;
1238 }
1239
1240 if (dssdev->platform_enable) {
1241 r = dssdev->platform_enable(dssdev);
1242 if (r) {
1243 DSSERR("failed to enable GPIO's\n");
1244 goto err1;
1245 }
1246 }
1247
1248 r = hdmi_power_on(dssdev);
1249 if (r) {
1250 DSSERR("failed to power on device\n");
1251 goto err2;
1252 }
1253
1254 mutex_unlock(&hdmi.lock);
1255 return 0;
1256
1257err2:
1258 if (dssdev->platform_disable)
1259 dssdev->platform_disable(dssdev);
1260err1:
1261 omap_dss_stop_device(dssdev);
1262err0:
1263 mutex_unlock(&hdmi.lock);
1264 return r;
1265}
1266
1267void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
1268{
1269 DSSDBG("Enter hdmi_display_disable\n");
1270
1271 mutex_lock(&hdmi.lock);
1272
1273 hdmi_power_off(dssdev);
1274
1275 if (dssdev->platform_disable)
1276 dssdev->platform_disable(dssdev);
1277
1278 omap_dss_stop_device(dssdev);
1279
1280 mutex_unlock(&hdmi.lock);
1281}
1282
1283#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
1284 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
1285static void hdmi_wp_audio_config_format(
1286 struct hdmi_audio_format *aud_fmt)
1287{
1288 u32 r;
1289
1290 DSSDBG("Enter hdmi_wp_audio_config_format\n");
1291
1292 r = hdmi_read_reg(HDMI_WP_AUDIO_CFG);
1293 r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24);
1294 r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16);
1295 r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5);
1296 r = FLD_MOD(r, aud_fmt->type, 4, 4);
1297 r = FLD_MOD(r, aud_fmt->justification, 3, 3);
1298 r = FLD_MOD(r, aud_fmt->sample_order, 2, 2);
1299 r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1);
1300 r = FLD_MOD(r, aud_fmt->sample_size, 0, 0);
1301 hdmi_write_reg(HDMI_WP_AUDIO_CFG, r);
1302}
1303
1304static void hdmi_wp_audio_config_dma(struct hdmi_audio_dma *aud_dma)
1305{
1306 u32 r;
1307
1308 DSSDBG("Enter hdmi_wp_audio_config_dma\n");
1309
1310 r = hdmi_read_reg(HDMI_WP_AUDIO_CFG2);
1311 r = FLD_MOD(r, aud_dma->transfer_size, 15, 8);
1312 r = FLD_MOD(r, aud_dma->block_size, 7, 0);
1313 hdmi_write_reg(HDMI_WP_AUDIO_CFG2, r);
1314
1315 r = hdmi_read_reg(HDMI_WP_AUDIO_CTRL);
1316 r = FLD_MOD(r, aud_dma->mode, 9, 9);
1317 r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0);
1318 hdmi_write_reg(HDMI_WP_AUDIO_CTRL, r);
1319}
1320
1321static void hdmi_core_audio_config(struct hdmi_core_audio_config *cfg)
1322{
1323 u32 r;
1324
1325 /* audio clock recovery parameters */
1326 r = hdmi_read_reg(HDMI_CORE_AV_ACR_CTRL);
1327 r = FLD_MOD(r, cfg->use_mclk, 2, 2);
1328 r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1);
1329 r = FLD_MOD(r, cfg->cts_mode, 0, 0);
1330 hdmi_write_reg(HDMI_CORE_AV_ACR_CTRL, r);
1331
1332 REG_FLD_MOD(HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0);
1333 REG_FLD_MOD(HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0);
1334 REG_FLD_MOD(HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0);
1335
1336 if (cfg->cts_mode == HDMI_AUDIO_CTS_MODE_SW) {
1337 REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0);
1338 REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0);
1339 REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0);
1340 } else {
1341 /*
1342 * HDMI IP uses this configuration to divide the MCLK to
1343 * update CTS value.
1344 */
1345 REG_FLD_MOD(HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0);
1346
1347 /* Configure clock for audio packets */
1348 REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_1,
1349 cfg->aud_par_busclk, 7, 0);
1350 REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_2,
1351 (cfg->aud_par_busclk >> 8), 7, 0);
1352 REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_3,
1353 (cfg->aud_par_busclk >> 16), 7, 0);
1354 }
1355
1356 /* Override of SPDIF sample frequency with value in I2S_CHST4 */
1357 REG_FLD_MOD(HDMI_CORE_AV_SPDIF_CTRL, cfg->fs_override, 1, 1);
1358
1359 /* I2S parameters */
1360 REG_FLD_MOD(HDMI_CORE_AV_I2S_CHST4, cfg->freq_sample, 3, 0);
1361
1362 r = hdmi_read_reg(HDMI_CORE_AV_I2S_IN_CTRL);
1363 r = FLD_MOD(r, cfg->i2s_cfg.en_high_bitrate_aud, 7, 7);
1364 r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6);
1365 r = FLD_MOD(r, cfg->i2s_cfg.cbit_order, 5, 5);
1366 r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4);
1367 r = FLD_MOD(r, cfg->i2s_cfg.ws_polarity, 3, 3);
1368 r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2);
1369 r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1);
1370 r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0);
1371 hdmi_write_reg(HDMI_CORE_AV_I2S_IN_CTRL, r);
1372
1373 r = hdmi_read_reg(HDMI_CORE_AV_I2S_CHST5);
1374 r = FLD_MOD(r, cfg->freq_sample, 7, 4);
1375 r = FLD_MOD(r, cfg->i2s_cfg.word_length, 3, 1);
1376 r = FLD_MOD(r, cfg->i2s_cfg.word_max_length, 0, 0);
1377 hdmi_write_reg(HDMI_CORE_AV_I2S_CHST5, r);
1378
1379 REG_FLD_MOD(HDMI_CORE_AV_I2S_IN_LEN, cfg->i2s_cfg.in_length_bits, 3, 0);
1380
1381 /* Audio channels and mode parameters */
1382 REG_FLD_MOD(HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1);
1383 r = hdmi_read_reg(HDMI_CORE_AV_AUD_MODE);
1384 r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4);
1385 r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3);
1386 r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2);
1387 r = FLD_MOD(r, cfg->en_spdif, 1, 1);
1388 hdmi_write_reg(HDMI_CORE_AV_AUD_MODE, r);
1389}
1390
1391static void hdmi_core_audio_infoframe_config(
1392 struct hdmi_core_infoframe_audio *info_aud)
1393{
1394 u8 val;
1395 u8 sum = 0, checksum = 0;
1396
1397 /*
1398 * Set audio info frame type, version and length as
1399 * described in HDMI 1.4a Section 8.2.2 specification.
1400 * Checksum calculation is defined in Section 5.3.5.
1401 */
1402 hdmi_write_reg(HDMI_CORE_AV_AUDIO_TYPE, 0x84);
1403 hdmi_write_reg(HDMI_CORE_AV_AUDIO_VERS, 0x01);
1404 hdmi_write_reg(HDMI_CORE_AV_AUDIO_LEN, 0x0a);
1405 sum += 0x84 + 0x001 + 0x00a;
1406
1407 val = (info_aud->db1_coding_type << 4)
1408 | (info_aud->db1_channel_count - 1);
1409 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(0), val);
1410 sum += val;
1411
1412 val = (info_aud->db2_sample_freq << 2) | info_aud->db2_sample_size;
1413 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(1), val);
1414 sum += val;
1415
1416 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(2), 0x00);
1417
1418 val = info_aud->db4_channel_alloc;
1419 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(3), val);
1420 sum += val;
1421
1422 val = (info_aud->db5_downmix_inh << 7) | (info_aud->db5_lsv << 3);
1423 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(4), val);
1424 sum += val;
1425
1426 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(5), 0x00);
1427 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(6), 0x00);
1428 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(7), 0x00);
1429 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(8), 0x00);
1430 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(9), 0x00);
1431
1432 checksum = 0x100 - sum;
1433 hdmi_write_reg(HDMI_CORE_AV_AUDIO_CHSUM, checksum);
1434
1435 /*
1436 * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing
1437 * is available.
1438 */
1439}
1440
1441static int hdmi_config_audio_acr(u32 sample_freq, u32 *n, u32 *cts)
1442{
1443 u32 r;
1444 u32 deep_color = 0;
1445 u32 pclk = hdmi.cfg.timings.timings.pixel_clock;
1446
1447 if (n == NULL || cts == NULL)
1448 return -EINVAL;
1449 /*
1450 * Obtain current deep color configuration. This needed
1451 * to calculate the TMDS clock based on the pixel clock.
1452 */
1453 r = REG_GET(HDMI_WP_VIDEO_CFG, 1, 0);
1454 switch (r) {
1455 case 1: /* No deep color selected */
1456 deep_color = 100;
1457 break;
1458 case 2: /* 10-bit deep color selected */
1459 deep_color = 125;
1460 break;
1461 case 3: /* 12-bit deep color selected */
1462 deep_color = 150;
1463 break;
1464 default:
1465 return -EINVAL;
1466 }
1467
1468 switch (sample_freq) {
1469 case 32000:
1470 if ((deep_color == 125) && ((pclk == 54054)
1471 || (pclk == 74250)))
1472 *n = 8192;
1473 else
1474 *n = 4096;
1475 break;
1476 case 44100:
1477 *n = 6272;
1478 break;
1479 case 48000:
1480 if ((deep_color == 125) && ((pclk == 54054)
1481 || (pclk == 74250)))
1482 *n = 8192;
1483 else
1484 *n = 6144;
1485 break;
1486 default:
1487 *n = 0;
1488 return -EINVAL;
1489 }
1490
1491 /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
1492 *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10);
1493
1494 return 0;
1495}
1496
1497static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
1498 struct snd_pcm_hw_params *params,
1499 struct snd_soc_dai *dai)
1500{
1501 struct hdmi_audio_format audio_format;
1502 struct hdmi_audio_dma audio_dma;
1503 struct hdmi_core_audio_config core_cfg;
1504 struct hdmi_core_infoframe_audio aud_if_cfg;
1505 int err, n, cts;
1506 enum hdmi_core_audio_sample_freq sample_freq;
1507
1508 switch (params_format(params)) {
1509 case SNDRV_PCM_FORMAT_S16_LE:
1510 core_cfg.i2s_cfg.word_max_length =
1511 HDMI_AUDIO_I2S_MAX_WORD_20BITS;
1512 core_cfg.i2s_cfg.word_length = HDMI_AUDIO_I2S_CHST_WORD_16_BITS;
1513 core_cfg.i2s_cfg.in_length_bits =
1514 HDMI_AUDIO_I2S_INPUT_LENGTH_16;
1515 core_cfg.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_LEFT;
1516 audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES;
1517 audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS;
1518 audio_format.justification = HDMI_AUDIO_JUSTIFY_LEFT;
1519 audio_dma.transfer_size = 0x10;
1520 break;
1521 case SNDRV_PCM_FORMAT_S24_LE:
1522 core_cfg.i2s_cfg.word_max_length =
1523 HDMI_AUDIO_I2S_MAX_WORD_24BITS;
1524 core_cfg.i2s_cfg.word_length = HDMI_AUDIO_I2S_CHST_WORD_24_BITS;
1525 core_cfg.i2s_cfg.in_length_bits =
1526 HDMI_AUDIO_I2S_INPUT_LENGTH_24;
1527 audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_ONESAMPLE;
1528 audio_format.sample_size = HDMI_AUDIO_SAMPLE_24BITS;
1529 audio_format.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
1530 core_cfg.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
1531 audio_dma.transfer_size = 0x20;
1532 break;
1533 default:
1534 return -EINVAL;
1535 }
1536
1537 switch (params_rate(params)) {
1538 case 32000:
1539 sample_freq = HDMI_AUDIO_FS_32000;
1540 break;
1541 case 44100:
1542 sample_freq = HDMI_AUDIO_FS_44100;
1543 break;
1544 case 48000:
1545 sample_freq = HDMI_AUDIO_FS_48000;
1546 break;
1547 default:
1548 return -EINVAL;
1549 }
1550
1551 err = hdmi_config_audio_acr(params_rate(params), &n, &cts);
1552 if (err < 0)
1553 return err;
1554
1555 /* Audio wrapper config */
1556 audio_format.stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL;
1557 audio_format.active_chnnls_msk = 0x03;
1558 audio_format.type = HDMI_AUDIO_TYPE_LPCM;
1559 audio_format.sample_order = HDMI_AUDIO_SAMPLE_LEFT_FIRST;
1560 /* Disable start/stop signals of IEC 60958 blocks */
1561 audio_format.en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_OFF;
1562
1563 audio_dma.block_size = 0xC0;
1564 audio_dma.mode = HDMI_AUDIO_TRANSF_DMA;
1565 audio_dma.fifo_threshold = 0x20; /* in number of samples */
1566
1567 hdmi_wp_audio_config_dma(&audio_dma);
1568 hdmi_wp_audio_config_format(&audio_format);
1569
1570 /*
1571 * I2S config
1572 */
1573 core_cfg.i2s_cfg.en_high_bitrate_aud = false;
1574 /* Only used with high bitrate audio */
1575 core_cfg.i2s_cfg.cbit_order = false;
1576 /* Serial data and word select should change on sck rising edge */
1577 core_cfg.i2s_cfg.sck_edge_mode = HDMI_AUDIO_I2S_SCK_EDGE_RISING;
1578 core_cfg.i2s_cfg.vbit = HDMI_AUDIO_I2S_VBIT_FOR_PCM;
1579 /* Set I2S word select polarity */
1580 core_cfg.i2s_cfg.ws_polarity = HDMI_AUDIO_I2S_WS_POLARITY_LOW_IS_LEFT;
1581 core_cfg.i2s_cfg.direction = HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST;
1582 /* Set serial data to word select shift. See Phillips spec. */
1583 core_cfg.i2s_cfg.shift = HDMI_AUDIO_I2S_FIRST_BIT_SHIFT;
1584 /* Enable one of the four available serial data channels */
1585 core_cfg.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN;
1586
1587 /* Core audio config */
1588 core_cfg.freq_sample = sample_freq;
1589 core_cfg.n = n;
1590 core_cfg.cts = cts;
1591 if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) {
1592 core_cfg.aud_par_busclk = 0;
1593 core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_SW;
1594 core_cfg.use_mclk = false;
1595 } else {
1596 core_cfg.aud_par_busclk = (((128 * 31) - 1) << 8);
1597 core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_HW;
1598 core_cfg.use_mclk = true;
1599 core_cfg.mclk_mode = HDMI_AUDIO_MCLK_128FS;
1600 }
1601 core_cfg.layout = HDMI_AUDIO_LAYOUT_2CH;
1602 core_cfg.en_spdif = false;
1603 /* Use sample frequency from channel status word */
1604 core_cfg.fs_override = true;
1605 /* Enable ACR packets */
1606 core_cfg.en_acr_pkt = true;
1607 /* Disable direct streaming digital audio */
1608 core_cfg.en_dsd_audio = false;
1609 /* Use parallel audio interface */
1610 core_cfg.en_parallel_aud_input = true;
1611
1612 hdmi_core_audio_config(&core_cfg);
1613
1614 /*
1615 * Configure packet
1616 * info frame audio see doc CEA861-D page 74
1617 */
1618 aud_if_cfg.db1_coding_type = HDMI_INFOFRAME_AUDIO_DB1CT_FROM_STREAM;
1619 aud_if_cfg.db1_channel_count = 2;
1620 aud_if_cfg.db2_sample_freq = HDMI_INFOFRAME_AUDIO_DB2SF_FROM_STREAM;
1621 aud_if_cfg.db2_sample_size = HDMI_INFOFRAME_AUDIO_DB2SS_FROM_STREAM;
1622 aud_if_cfg.db4_channel_alloc = 0x00;
1623 aud_if_cfg.db5_downmix_inh = false;
1624 aud_if_cfg.db5_lsv = 0;
1625
1626 hdmi_core_audio_infoframe_config(&aud_if_cfg);
1627 return 0;
1628}
1629
1630static int hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
1631 struct snd_soc_dai *dai)
1632{
1633 int err = 0;
1634 switch (cmd) {
1635 case SNDRV_PCM_TRIGGER_START:
1636 case SNDRV_PCM_TRIGGER_RESUME:
1637 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1638 REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 1, 0, 0);
1639 REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 31, 31);
1640 REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 30, 30);
1641 break;
1642
1643 case SNDRV_PCM_TRIGGER_STOP:
1644 case SNDRV_PCM_TRIGGER_SUSPEND:
1645 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1646 REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 0, 0, 0);
1647 REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 30, 30);
1648 REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 31, 31);
1649 break;
1650 default:
1651 err = -EINVAL;
1652 }
1653 return err;
1654}
1655
1656static int hdmi_audio_startup(struct snd_pcm_substream *substream,
1657 struct snd_soc_dai *dai)
1658{
1659 if (!hdmi.mode) {
1660 pr_err("Current video settings do not support audio.\n");
1661 return -EIO;
1662 }
1663 return 0;
1664}
1665
1666static struct snd_soc_codec_driver hdmi_audio_codec_drv = {
1667};
1668
1669static struct snd_soc_dai_ops hdmi_audio_codec_ops = {
1670 .hw_params = hdmi_audio_hw_params,
1671 .trigger = hdmi_audio_trigger,
1672 .startup = hdmi_audio_startup,
1673};
1674
1675static struct snd_soc_dai_driver hdmi_codec_dai_drv = {
1676 .name = "hdmi-audio-codec",
1677 .playback = {
1678 .channels_min = 2,
1679 .channels_max = 2,
1680 .rates = SNDRV_PCM_RATE_32000 |
1681 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
1682 .formats = SNDRV_PCM_FMTBIT_S16_LE |
1683 SNDRV_PCM_FMTBIT_S24_LE,
1684 },
1685 .ops = &hdmi_audio_codec_ops,
1686};
1687#endif
1688
1689/* HDMI HW IP initialisation */
1690static int omapdss_hdmihw_probe(struct platform_device *pdev)
1691{
1692 struct resource *hdmi_mem;
1693#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
1694 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
1695 int ret;
1696#endif
1697
1698 hdmi.pdata = pdev->dev.platform_data;
1699 hdmi.pdev = pdev;
1700
1701 mutex_init(&hdmi.lock);
1702
1703 hdmi_mem = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0);
1704 if (!hdmi_mem) {
1705 DSSERR("can't get IORESOURCE_MEM HDMI\n");
1706 return -EINVAL;
1707 }
1708
1709 /* Base address taken from platform */
1710 hdmi.base_wp = ioremap(hdmi_mem->start, resource_size(hdmi_mem));
1711 if (!hdmi.base_wp) {
1712 DSSERR("can't ioremap WP\n");
1713 return -ENOMEM;
1714 }
1715
1716 hdmi_panel_init();
1717
1718#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
1719 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
1720
1721 /* Register ASoC codec DAI */
1722 ret = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv,
1723 &hdmi_codec_dai_drv, 1);
1724 if (ret) {
1725 DSSERR("can't register ASoC HDMI audio codec\n");
1726 return ret;
1727 }
1728#endif
1729 return 0;
1730}
1731
1732static int omapdss_hdmihw_remove(struct platform_device *pdev)
1733{
1734 hdmi_panel_exit();
1735
1736#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
1737 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
1738 snd_soc_unregister_codec(&pdev->dev);
1739#endif
1740
1741 iounmap(hdmi.base_wp);
1742
1743 return 0;
1744}
1745
1746static struct platform_driver omapdss_hdmihw_driver = {
1747 .probe = omapdss_hdmihw_probe,
1748 .remove = omapdss_hdmihw_remove,
1749 .driver = {
1750 .name = "omapdss_hdmi",
1751 .owner = THIS_MODULE,
1752 },
1753};
1754
1755int hdmi_init_platform_driver(void)
1756{
1757 return platform_driver_register(&omapdss_hdmihw_driver);
1758}
1759
1760void hdmi_uninit_platform_driver(void)
1761{
1762 return platform_driver_unregister(&omapdss_hdmihw_driver);
1763}
diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/omap2/dss/hdmi.h
new file mode 100644
index 000000000000..c885f9cb0659
--- /dev/null
+++ b/drivers/video/omap2/dss/hdmi.h
@@ -0,0 +1,631 @@
1/*
2 * hdmi.h
3 *
4 * HDMI driver definition for TI OMAP4 processors.
5 *
6 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#ifndef _OMAP4_DSS_HDMI_H_
22#define _OMAP4_DSS_HDMI_H_
23
24#include <linux/string.h>
25#include <video/omapdss.h>
26
27#define HDMI_WP 0x0
28#define HDMI_CORE_SYS 0x400
29#define HDMI_CORE_AV 0x900
30#define HDMI_PLLCTRL 0x200
31#define HDMI_PHY 0x300
32
33struct hdmi_reg { u16 idx; };
34
35#define HDMI_REG(idx) ((const struct hdmi_reg) { idx })
36
37/* HDMI Wrapper */
38#define HDMI_WP_REG(idx) HDMI_REG(HDMI_WP + idx)
39
40#define HDMI_WP_REVISION HDMI_WP_REG(0x0)
41#define HDMI_WP_SYSCONFIG HDMI_WP_REG(0x10)
42#define HDMI_WP_IRQSTATUS_RAW HDMI_WP_REG(0x24)
43#define HDMI_WP_IRQSTATUS HDMI_WP_REG(0x28)
44#define HDMI_WP_PWR_CTRL HDMI_WP_REG(0x40)
45#define HDMI_WP_IRQENABLE_SET HDMI_WP_REG(0x2C)
46#define HDMI_WP_VIDEO_CFG HDMI_WP_REG(0x50)
47#define HDMI_WP_VIDEO_SIZE HDMI_WP_REG(0x60)
48#define HDMI_WP_VIDEO_TIMING_H HDMI_WP_REG(0x68)
49#define HDMI_WP_VIDEO_TIMING_V HDMI_WP_REG(0x6C)
50#define HDMI_WP_WP_CLK HDMI_WP_REG(0x70)
51#define HDMI_WP_AUDIO_CFG HDMI_WP_REG(0x80)
52#define HDMI_WP_AUDIO_CFG2 HDMI_WP_REG(0x84)
53#define HDMI_WP_AUDIO_CTRL HDMI_WP_REG(0x88)
54#define HDMI_WP_AUDIO_DATA HDMI_WP_REG(0x8C)
55
56/* HDMI IP Core System */
57#define HDMI_CORE_SYS_REG(idx) HDMI_REG(HDMI_CORE_SYS + idx)
58
59#define HDMI_CORE_SYS_VND_IDL HDMI_CORE_SYS_REG(0x0)
60#define HDMI_CORE_SYS_DEV_IDL HDMI_CORE_SYS_REG(0x8)
61#define HDMI_CORE_SYS_DEV_IDH HDMI_CORE_SYS_REG(0xC)
62#define HDMI_CORE_SYS_DEV_REV HDMI_CORE_SYS_REG(0x10)
63#define HDMI_CORE_SYS_SRST HDMI_CORE_SYS_REG(0x14)
64#define HDMI_CORE_CTRL1 HDMI_CORE_SYS_REG(0x20)
65#define HDMI_CORE_SYS_SYS_STAT HDMI_CORE_SYS_REG(0x24)
66#define HDMI_CORE_SYS_VID_ACEN HDMI_CORE_SYS_REG(0x124)
67#define HDMI_CORE_SYS_VID_MODE HDMI_CORE_SYS_REG(0x128)
68#define HDMI_CORE_SYS_INTR_STATE HDMI_CORE_SYS_REG(0x1C0)
69#define HDMI_CORE_SYS_INTR1 HDMI_CORE_SYS_REG(0x1C4)
70#define HDMI_CORE_SYS_INTR2 HDMI_CORE_SYS_REG(0x1C8)
71#define HDMI_CORE_SYS_INTR3 HDMI_CORE_SYS_REG(0x1CC)
72#define HDMI_CORE_SYS_INTR4 HDMI_CORE_SYS_REG(0x1D0)
73#define HDMI_CORE_SYS_UMASK1 HDMI_CORE_SYS_REG(0x1D4)
74#define HDMI_CORE_SYS_TMDS_CTRL HDMI_CORE_SYS_REG(0x208)
75#define HDMI_CORE_SYS_DE_DLY HDMI_CORE_SYS_REG(0xC8)
76#define HDMI_CORE_SYS_DE_CTRL HDMI_CORE_SYS_REG(0xCC)
77#define HDMI_CORE_SYS_DE_TOP HDMI_CORE_SYS_REG(0xD0)
78#define HDMI_CORE_SYS_DE_CNTL HDMI_CORE_SYS_REG(0xD8)
79#define HDMI_CORE_SYS_DE_CNTH HDMI_CORE_SYS_REG(0xDC)
80#define HDMI_CORE_SYS_DE_LINL HDMI_CORE_SYS_REG(0xE0)
81#define HDMI_CORE_SYS_DE_LINH_1 HDMI_CORE_SYS_REG(0xE4)
82#define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC 0x1
83#define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC 0x1
84#define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1
85#define HDMI_CORE_CTRL1_EDGE_RISINGEDGE 0x1
86
87/* HDMI DDC E-DID */
88#define HDMI_CORE_DDC_CMD HDMI_CORE_SYS_REG(0x3CC)
89#define HDMI_CORE_DDC_STATUS HDMI_CORE_SYS_REG(0x3C8)
90#define HDMI_CORE_DDC_ADDR HDMI_CORE_SYS_REG(0x3B4)
91#define HDMI_CORE_DDC_OFFSET HDMI_CORE_SYS_REG(0x3BC)
92#define HDMI_CORE_DDC_COUNT1 HDMI_CORE_SYS_REG(0x3C0)
93#define HDMI_CORE_DDC_COUNT2 HDMI_CORE_SYS_REG(0x3C4)
94#define HDMI_CORE_DDC_DATA HDMI_CORE_SYS_REG(0x3D0)
95#define HDMI_CORE_DDC_SEGM HDMI_CORE_SYS_REG(0x3B8)
96
97/* HDMI IP Core Audio Video */
98#define HDMI_CORE_AV_REG(idx) HDMI_REG(HDMI_CORE_AV + idx)
99
100#define HDMI_CORE_AV_HDMI_CTRL HDMI_CORE_AV_REG(0xBC)
101#define HDMI_CORE_AV_DPD HDMI_CORE_AV_REG(0xF4)
102#define HDMI_CORE_AV_PB_CTRL1 HDMI_CORE_AV_REG(0xF8)
103#define HDMI_CORE_AV_PB_CTRL2 HDMI_CORE_AV_REG(0xFC)
104#define HDMI_CORE_AV_AVI_TYPE HDMI_CORE_AV_REG(0x100)
105#define HDMI_CORE_AV_AVI_VERS HDMI_CORE_AV_REG(0x104)
106#define HDMI_CORE_AV_AVI_LEN HDMI_CORE_AV_REG(0x108)
107#define HDMI_CORE_AV_AVI_CHSUM HDMI_CORE_AV_REG(0x10C)
108#define HDMI_CORE_AV_AVI_DBYTE(n) HDMI_CORE_AV_REG(n * 4 + 0x110)
109#define HDMI_CORE_AV_AVI_DBYTE_NELEMS HDMI_CORE_AV_REG(15)
110#define HDMI_CORE_AV_SPD_DBYTE HDMI_CORE_AV_REG(0x190)
111#define HDMI_CORE_AV_SPD_DBYTE_NELEMS HDMI_CORE_AV_REG(27)
112#define HDMI_CORE_AV_AUD_DBYTE(n) HDMI_CORE_AV_REG(n * 4 + 0x210)
113#define HDMI_CORE_AV_AUD_DBYTE_NELEMS HDMI_CORE_AV_REG(10)
114#define HDMI_CORE_AV_MPEG_DBYTE HDMI_CORE_AV_REG(0x290)
115#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS HDMI_CORE_AV_REG(27)
116#define HDMI_CORE_AV_GEN_DBYTE HDMI_CORE_AV_REG(0x300)
117#define HDMI_CORE_AV_GEN_DBYTE_NELEMS HDMI_CORE_AV_REG(31)
118#define HDMI_CORE_AV_GEN2_DBYTE HDMI_CORE_AV_REG(0x380)
119#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS HDMI_CORE_AV_REG(31)
120#define HDMI_CORE_AV_ACR_CTRL HDMI_CORE_AV_REG(0x4)
121#define HDMI_CORE_AV_FREQ_SVAL HDMI_CORE_AV_REG(0x8)
122#define HDMI_CORE_AV_N_SVAL1 HDMI_CORE_AV_REG(0xC)
123#define HDMI_CORE_AV_N_SVAL2 HDMI_CORE_AV_REG(0x10)
124#define HDMI_CORE_AV_N_SVAL3 HDMI_CORE_AV_REG(0x14)
125#define HDMI_CORE_AV_CTS_SVAL1 HDMI_CORE_AV_REG(0x18)
126#define HDMI_CORE_AV_CTS_SVAL2 HDMI_CORE_AV_REG(0x1C)
127#define HDMI_CORE_AV_CTS_SVAL3 HDMI_CORE_AV_REG(0x20)
128#define HDMI_CORE_AV_CTS_HVAL1 HDMI_CORE_AV_REG(0x24)
129#define HDMI_CORE_AV_CTS_HVAL2 HDMI_CORE_AV_REG(0x28)
130#define HDMI_CORE_AV_CTS_HVAL3 HDMI_CORE_AV_REG(0x2C)
131#define HDMI_CORE_AV_AUD_MODE HDMI_CORE_AV_REG(0x50)
132#define HDMI_CORE_AV_SPDIF_CTRL HDMI_CORE_AV_REG(0x54)
133#define HDMI_CORE_AV_HW_SPDIF_FS HDMI_CORE_AV_REG(0x60)
134#define HDMI_CORE_AV_SWAP_I2S HDMI_CORE_AV_REG(0x64)
135#define HDMI_CORE_AV_SPDIF_ERTH HDMI_CORE_AV_REG(0x6C)
136#define HDMI_CORE_AV_I2S_IN_MAP HDMI_CORE_AV_REG(0x70)
137#define HDMI_CORE_AV_I2S_IN_CTRL HDMI_CORE_AV_REG(0x74)
138#define HDMI_CORE_AV_I2S_CHST0 HDMI_CORE_AV_REG(0x78)
139#define HDMI_CORE_AV_I2S_CHST1 HDMI_CORE_AV_REG(0x7C)
140#define HDMI_CORE_AV_I2S_CHST2 HDMI_CORE_AV_REG(0x80)
141#define HDMI_CORE_AV_I2S_CHST4 HDMI_CORE_AV_REG(0x84)
142#define HDMI_CORE_AV_I2S_CHST5 HDMI_CORE_AV_REG(0x88)
143#define HDMI_CORE_AV_ASRC HDMI_CORE_AV_REG(0x8C)
144#define HDMI_CORE_AV_I2S_IN_LEN HDMI_CORE_AV_REG(0x90)
145#define HDMI_CORE_AV_HDMI_CTRL HDMI_CORE_AV_REG(0xBC)
146#define HDMI_CORE_AV_AUDO_TXSTAT HDMI_CORE_AV_REG(0xC0)
147#define HDMI_CORE_AV_AUD_PAR_BUSCLK_1 HDMI_CORE_AV_REG(0xCC)
148#define HDMI_CORE_AV_AUD_PAR_BUSCLK_2 HDMI_CORE_AV_REG(0xD0)
149#define HDMI_CORE_AV_AUD_PAR_BUSCLK_3 HDMI_CORE_AV_REG(0xD4)
150#define HDMI_CORE_AV_TEST_TXCTRL HDMI_CORE_AV_REG(0xF0)
151#define HDMI_CORE_AV_DPD HDMI_CORE_AV_REG(0xF4)
152#define HDMI_CORE_AV_PB_CTRL1 HDMI_CORE_AV_REG(0xF8)
153#define HDMI_CORE_AV_PB_CTRL2 HDMI_CORE_AV_REG(0xFC)
154#define HDMI_CORE_AV_AVI_TYPE HDMI_CORE_AV_REG(0x100)
155#define HDMI_CORE_AV_AVI_VERS HDMI_CORE_AV_REG(0x104)
156#define HDMI_CORE_AV_AVI_LEN HDMI_CORE_AV_REG(0x108)
157#define HDMI_CORE_AV_AVI_CHSUM HDMI_CORE_AV_REG(0x10C)
158#define HDMI_CORE_AV_SPD_TYPE HDMI_CORE_AV_REG(0x180)
159#define HDMI_CORE_AV_SPD_VERS HDMI_CORE_AV_REG(0x184)
160#define HDMI_CORE_AV_SPD_LEN HDMI_CORE_AV_REG(0x188)
161#define HDMI_CORE_AV_SPD_CHSUM HDMI_CORE_AV_REG(0x18C)
162#define HDMI_CORE_AV_AUDIO_TYPE HDMI_CORE_AV_REG(0x200)
163#define HDMI_CORE_AV_AUDIO_VERS HDMI_CORE_AV_REG(0x204)
164#define HDMI_CORE_AV_AUDIO_LEN HDMI_CORE_AV_REG(0x208)
165#define HDMI_CORE_AV_AUDIO_CHSUM HDMI_CORE_AV_REG(0x20C)
166#define HDMI_CORE_AV_MPEG_TYPE HDMI_CORE_AV_REG(0x280)
167#define HDMI_CORE_AV_MPEG_VERS HDMI_CORE_AV_REG(0x284)
168#define HDMI_CORE_AV_MPEG_LEN HDMI_CORE_AV_REG(0x288)
169#define HDMI_CORE_AV_MPEG_CHSUM HDMI_CORE_AV_REG(0x28C)
170#define HDMI_CORE_AV_CP_BYTE1 HDMI_CORE_AV_REG(0x37C)
171#define HDMI_CORE_AV_CEC_ADDR_ID HDMI_CORE_AV_REG(0x3FC)
172#define HDMI_CORE_AV_SPD_DBYTE_ELSIZE 0x4
173#define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE 0x4
174#define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE 0x4
175#define HDMI_CORE_AV_GEN_DBYTE_ELSIZE 0x4
176
177/* PLL */
178#define HDMI_PLL_REG(idx) HDMI_REG(HDMI_PLLCTRL + idx)
179
180#define PLLCTRL_PLL_CONTROL HDMI_PLL_REG(0x0)
181#define PLLCTRL_PLL_STATUS HDMI_PLL_REG(0x4)
182#define PLLCTRL_PLL_GO HDMI_PLL_REG(0x8)
183#define PLLCTRL_CFG1 HDMI_PLL_REG(0xC)
184#define PLLCTRL_CFG2 HDMI_PLL_REG(0x10)
185#define PLLCTRL_CFG3 HDMI_PLL_REG(0x14)
186#define PLLCTRL_CFG4 HDMI_PLL_REG(0x20)
187
188/* HDMI PHY */
189#define HDMI_PHY_REG(idx) HDMI_REG(HDMI_PHY + idx)
190
191#define HDMI_TXPHY_TX_CTRL HDMI_PHY_REG(0x0)
192#define HDMI_TXPHY_DIGITAL_CTRL HDMI_PHY_REG(0x4)
193#define HDMI_TXPHY_POWER_CTRL HDMI_PHY_REG(0x8)
194#define HDMI_TXPHY_PAD_CFG_CTRL HDMI_PHY_REG(0xC)
195
196/* HDMI EDID Length */
197#define HDMI_EDID_MAX_LENGTH 256
198#define EDID_TIMING_DESCRIPTOR_SIZE 0x12
199#define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36
200#define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80
201#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4
202#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4
203
204#define OMAP_HDMI_TIMINGS_NB 34
205
206#define REG_FLD_MOD(idx, val, start, end) \
207 hdmi_write_reg(idx, FLD_MOD(hdmi_read_reg(idx), val, start, end))
208#define REG_GET(idx, start, end) \
209 FLD_GET(hdmi_read_reg(idx), start, end)
210
211/* HDMI timing structure */
212struct hdmi_timings {
213 struct omap_video_timings timings;
214 int vsync_pol;
215 int hsync_pol;
216};
217
218enum hdmi_phy_pwr {
219 HDMI_PHYPWRCMD_OFF = 0,
220 HDMI_PHYPWRCMD_LDOON = 1,
221 HDMI_PHYPWRCMD_TXON = 2
222};
223
224enum hdmi_pll_pwr {
225 HDMI_PLLPWRCMD_ALLOFF = 0,
226 HDMI_PLLPWRCMD_PLLONLY = 1,
227 HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2,
228 HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3
229};
230
231enum hdmi_clk_refsel {
232 HDMI_REFSEL_PCLK = 0,
233 HDMI_REFSEL_REF1 = 1,
234 HDMI_REFSEL_REF2 = 2,
235 HDMI_REFSEL_SYSCLK = 3
236};
237
238enum hdmi_core_inputbus_width {
239 HDMI_INPUT_8BIT = 0,
240 HDMI_INPUT_10BIT = 1,
241 HDMI_INPUT_12BIT = 2
242};
243
244enum hdmi_core_dither_trunc {
245 HDMI_OUTPUTTRUNCATION_8BIT = 0,
246 HDMI_OUTPUTTRUNCATION_10BIT = 1,
247 HDMI_OUTPUTTRUNCATION_12BIT = 2,
248 HDMI_OUTPUTDITHER_8BIT = 3,
249 HDMI_OUTPUTDITHER_10BIT = 4,
250 HDMI_OUTPUTDITHER_12BIT = 5
251};
252
253enum hdmi_core_deepcolor_ed {
254 HDMI_DEEPCOLORPACKECTDISABLE = 0,
255 HDMI_DEEPCOLORPACKECTENABLE = 1
256};
257
258enum hdmi_core_packet_mode {
259 HDMI_PACKETMODERESERVEDVALUE = 0,
260 HDMI_PACKETMODE24BITPERPIXEL = 4,
261 HDMI_PACKETMODE30BITPERPIXEL = 5,
262 HDMI_PACKETMODE36BITPERPIXEL = 6,
263 HDMI_PACKETMODE48BITPERPIXEL = 7
264};
265
266enum hdmi_core_hdmi_dvi {
267 HDMI_DVI = 0,
268 HDMI_HDMI = 1
269};
270
271enum hdmi_core_tclkselclkmult {
272 HDMI_FPLL05IDCK = 0,
273 HDMI_FPLL10IDCK = 1,
274 HDMI_FPLL20IDCK = 2,
275 HDMI_FPLL40IDCK = 3
276};
277
278enum hdmi_core_packet_ctrl {
279 HDMI_PACKETENABLE = 1,
280 HDMI_PACKETDISABLE = 0,
281 HDMI_PACKETREPEATON = 1,
282 HDMI_PACKETREPEATOFF = 0
283};
284
285/* INFOFRAME_AVI_ and INFOFRAME_AUDIO_ definitions */
286enum hdmi_core_infoframe {
287 HDMI_INFOFRAME_AVI_DB1Y_RGB = 0,
288 HDMI_INFOFRAME_AVI_DB1Y_YUV422 = 1,
289 HDMI_INFOFRAME_AVI_DB1Y_YUV444 = 2,
290 HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF = 0,
291 HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_ON = 1,
292 HDMI_INFOFRAME_AVI_DB1B_NO = 0,
293 HDMI_INFOFRAME_AVI_DB1B_VERT = 1,
294 HDMI_INFOFRAME_AVI_DB1B_HORI = 2,
295 HDMI_INFOFRAME_AVI_DB1B_VERTHORI = 3,
296 HDMI_INFOFRAME_AVI_DB1S_0 = 0,
297 HDMI_INFOFRAME_AVI_DB1S_1 = 1,
298 HDMI_INFOFRAME_AVI_DB1S_2 = 2,
299 HDMI_INFOFRAME_AVI_DB2C_NO = 0,
300 HDMI_INFOFRAME_AVI_DB2C_ITU601 = 1,
301 HDMI_INFOFRAME_AVI_DB2C_ITU709 = 2,
302 HDMI_INFOFRAME_AVI_DB2C_EC_EXTENDED = 3,
303 HDMI_INFOFRAME_AVI_DB2M_NO = 0,
304 HDMI_INFOFRAME_AVI_DB2M_43 = 1,
305 HDMI_INFOFRAME_AVI_DB2M_169 = 2,
306 HDMI_INFOFRAME_AVI_DB2R_SAME = 8,
307 HDMI_INFOFRAME_AVI_DB2R_43 = 9,
308 HDMI_INFOFRAME_AVI_DB2R_169 = 10,
309 HDMI_INFOFRAME_AVI_DB2R_149 = 11,
310 HDMI_INFOFRAME_AVI_DB3ITC_NO = 0,
311 HDMI_INFOFRAME_AVI_DB3ITC_YES = 1,
312 HDMI_INFOFRAME_AVI_DB3EC_XVYUV601 = 0,
313 HDMI_INFOFRAME_AVI_DB3EC_XVYUV709 = 1,
314 HDMI_INFOFRAME_AVI_DB3Q_DEFAULT = 0,
315 HDMI_INFOFRAME_AVI_DB3Q_LR = 1,
316 HDMI_INFOFRAME_AVI_DB3Q_FR = 2,
317 HDMI_INFOFRAME_AVI_DB3SC_NO = 0,
318 HDMI_INFOFRAME_AVI_DB3SC_HORI = 1,
319 HDMI_INFOFRAME_AVI_DB3SC_VERT = 2,
320 HDMI_INFOFRAME_AVI_DB3SC_HORIVERT = 3,
321 HDMI_INFOFRAME_AVI_DB5PR_NO = 0,
322 HDMI_INFOFRAME_AVI_DB5PR_2 = 1,
323 HDMI_INFOFRAME_AVI_DB5PR_3 = 2,
324 HDMI_INFOFRAME_AVI_DB5PR_4 = 3,
325 HDMI_INFOFRAME_AVI_DB5PR_5 = 4,
326 HDMI_INFOFRAME_AVI_DB5PR_6 = 5,
327 HDMI_INFOFRAME_AVI_DB5PR_7 = 6,
328 HDMI_INFOFRAME_AVI_DB5PR_8 = 7,
329 HDMI_INFOFRAME_AVI_DB5PR_9 = 8,
330 HDMI_INFOFRAME_AVI_DB5PR_10 = 9,
331 HDMI_INFOFRAME_AUDIO_DB1CT_FROM_STREAM = 0,
332 HDMI_INFOFRAME_AUDIO_DB1CT_IEC60958 = 1,
333 HDMI_INFOFRAME_AUDIO_DB1CT_AC3 = 2,
334 HDMI_INFOFRAME_AUDIO_DB1CT_MPEG1 = 3,
335 HDMI_INFOFRAME_AUDIO_DB1CT_MP3 = 4,
336 HDMI_INFOFRAME_AUDIO_DB1CT_MPEG2_MULTICH = 5,
337 HDMI_INFOFRAME_AUDIO_DB1CT_AAC = 6,
338 HDMI_INFOFRAME_AUDIO_DB1CT_DTS = 7,
339 HDMI_INFOFRAME_AUDIO_DB1CT_ATRAC = 8,
340 HDMI_INFOFRAME_AUDIO_DB1CT_ONEBIT = 9,
341 HDMI_INFOFRAME_AUDIO_DB1CT_DOLBY_DIGITAL_PLUS = 10,
342 HDMI_INFOFRAME_AUDIO_DB1CT_DTS_HD = 11,
343 HDMI_INFOFRAME_AUDIO_DB1CT_MAT = 12,
344 HDMI_INFOFRAME_AUDIO_DB1CT_DST = 13,
345 HDMI_INFOFRAME_AUDIO_DB1CT_WMA_PRO = 14,
346 HDMI_INFOFRAME_AUDIO_DB2SF_FROM_STREAM = 0,
347 HDMI_INFOFRAME_AUDIO_DB2SF_32000 = 1,
348 HDMI_INFOFRAME_AUDIO_DB2SF_44100 = 2,
349 HDMI_INFOFRAME_AUDIO_DB2SF_48000 = 3,
350 HDMI_INFOFRAME_AUDIO_DB2SF_88200 = 4,
351 HDMI_INFOFRAME_AUDIO_DB2SF_96000 = 5,
352 HDMI_INFOFRAME_AUDIO_DB2SF_176400 = 6,
353 HDMI_INFOFRAME_AUDIO_DB2SF_192000 = 7,
354 HDMI_INFOFRAME_AUDIO_DB2SS_FROM_STREAM = 0,
355 HDMI_INFOFRAME_AUDIO_DB2SS_16BIT = 1,
356 HDMI_INFOFRAME_AUDIO_DB2SS_20BIT = 2,
357 HDMI_INFOFRAME_AUDIO_DB2SS_24BIT = 3,
358 HDMI_INFOFRAME_AUDIO_DB5_DM_INH_PERMITTED = 0,
359 HDMI_INFOFRAME_AUDIO_DB5_DM_INH_PROHIBITED = 1
360};
361
362enum hdmi_packing_mode {
363 HDMI_PACK_10b_RGB_YUV444 = 0,
364 HDMI_PACK_24b_RGB_YUV444_YUV422 = 1,
365 HDMI_PACK_20b_YUV422 = 2,
366 HDMI_PACK_ALREADYPACKED = 7
367};
368
369enum hdmi_core_audio_sample_freq {
370 HDMI_AUDIO_FS_32000 = 0x3,
371 HDMI_AUDIO_FS_44100 = 0x0,
372 HDMI_AUDIO_FS_48000 = 0x2,
373 HDMI_AUDIO_FS_88200 = 0x8,
374 HDMI_AUDIO_FS_96000 = 0xA,
375 HDMI_AUDIO_FS_176400 = 0xC,
376 HDMI_AUDIO_FS_192000 = 0xE,
377 HDMI_AUDIO_FS_NOT_INDICATED = 0x1
378};
379
380enum hdmi_core_audio_layout {
381 HDMI_AUDIO_LAYOUT_2CH = 0,
382 HDMI_AUDIO_LAYOUT_8CH = 1
383};
384
385enum hdmi_core_cts_mode {
386 HDMI_AUDIO_CTS_MODE_HW = 0,
387 HDMI_AUDIO_CTS_MODE_SW = 1
388};
389
390enum hdmi_stereo_channels {
391 HDMI_AUDIO_STEREO_NOCHANNELS = 0,
392 HDMI_AUDIO_STEREO_ONECHANNEL = 1,
393 HDMI_AUDIO_STEREO_TWOCHANNELS = 2,
394 HDMI_AUDIO_STEREO_THREECHANNELS = 3,
395 HDMI_AUDIO_STEREO_FOURCHANNELS = 4
396};
397
398enum hdmi_audio_type {
399 HDMI_AUDIO_TYPE_LPCM = 0,
400 HDMI_AUDIO_TYPE_IEC = 1
401};
402
403enum hdmi_audio_justify {
404 HDMI_AUDIO_JUSTIFY_LEFT = 0,
405 HDMI_AUDIO_JUSTIFY_RIGHT = 1
406};
407
408enum hdmi_audio_sample_order {
409 HDMI_AUDIO_SAMPLE_RIGHT_FIRST = 0,
410 HDMI_AUDIO_SAMPLE_LEFT_FIRST = 1
411};
412
413enum hdmi_audio_samples_perword {
414 HDMI_AUDIO_ONEWORD_ONESAMPLE = 0,
415 HDMI_AUDIO_ONEWORD_TWOSAMPLES = 1
416};
417
418enum hdmi_audio_sample_size {
419 HDMI_AUDIO_SAMPLE_16BITS = 0,
420 HDMI_AUDIO_SAMPLE_24BITS = 1
421};
422
423enum hdmi_audio_transf_mode {
424 HDMI_AUDIO_TRANSF_DMA = 0,
425 HDMI_AUDIO_TRANSF_IRQ = 1
426};
427
428enum hdmi_audio_blk_strt_end_sig {
429 HDMI_AUDIO_BLOCK_SIG_STARTEND_ON = 0,
430 HDMI_AUDIO_BLOCK_SIG_STARTEND_OFF = 1
431};
432
433enum hdmi_audio_i2s_config {
434 HDMI_AUDIO_I2S_WS_POLARITY_LOW_IS_LEFT = 0,
435 HDMI_AUDIO_I2S_WS_POLARIT_YLOW_IS_RIGHT = 1,
436 HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST = 0,
437 HDMI_AUDIO_I2S_LSB_SHIFTED_FIRST = 1,
438 HDMI_AUDIO_I2S_MAX_WORD_20BITS = 0,
439 HDMI_AUDIO_I2S_MAX_WORD_24BITS = 1,
440 HDMI_AUDIO_I2S_CHST_WORD_NOT_SPECIFIED = 0,
441 HDMI_AUDIO_I2S_CHST_WORD_16_BITS = 1,
442 HDMI_AUDIO_I2S_CHST_WORD_17_BITS = 6,
443 HDMI_AUDIO_I2S_CHST_WORD_18_BITS = 2,
444 HDMI_AUDIO_I2S_CHST_WORD_19_BITS = 4,
445 HDMI_AUDIO_I2S_CHST_WORD_20_BITS_20MAX = 5,
446 HDMI_AUDIO_I2S_CHST_WORD_20_BITS_24MAX = 1,
447 HDMI_AUDIO_I2S_CHST_WORD_21_BITS = 6,
448 HDMI_AUDIO_I2S_CHST_WORD_22_BITS = 2,
449 HDMI_AUDIO_I2S_CHST_WORD_23_BITS = 4,
450 HDMI_AUDIO_I2S_CHST_WORD_24_BITS = 5,
451 HDMI_AUDIO_I2S_SCK_EDGE_FALLING = 0,
452 HDMI_AUDIO_I2S_SCK_EDGE_RISING = 1,
453 HDMI_AUDIO_I2S_VBIT_FOR_PCM = 0,
454 HDMI_AUDIO_I2S_VBIT_FOR_COMPRESSED = 1,
455 HDMI_AUDIO_I2S_INPUT_LENGTH_NA = 0,
456 HDMI_AUDIO_I2S_INPUT_LENGTH_16 = 2,
457 HDMI_AUDIO_I2S_INPUT_LENGTH_17 = 12,
458 HDMI_AUDIO_I2S_INPUT_LENGTH_18 = 4,
459 HDMI_AUDIO_I2S_INPUT_LENGTH_19 = 8,
460 HDMI_AUDIO_I2S_INPUT_LENGTH_20 = 10,
461 HDMI_AUDIO_I2S_INPUT_LENGTH_21 = 13,
462 HDMI_AUDIO_I2S_INPUT_LENGTH_22 = 5,
463 HDMI_AUDIO_I2S_INPUT_LENGTH_23 = 9,
464 HDMI_AUDIO_I2S_INPUT_LENGTH_24 = 11,
465 HDMI_AUDIO_I2S_FIRST_BIT_SHIFT = 0,
466 HDMI_AUDIO_I2S_FIRST_BIT_NO_SHIFT = 1,
467 HDMI_AUDIO_I2S_SD0_EN = 1,
468 HDMI_AUDIO_I2S_SD1_EN = 1 << 1,
469 HDMI_AUDIO_I2S_SD2_EN = 1 << 2,
470 HDMI_AUDIO_I2S_SD3_EN = 1 << 3,
471};
472
473enum hdmi_audio_mclk_mode {
474 HDMI_AUDIO_MCLK_128FS = 0,
475 HDMI_AUDIO_MCLK_256FS = 1,
476 HDMI_AUDIO_MCLK_384FS = 2,
477 HDMI_AUDIO_MCLK_512FS = 3,
478 HDMI_AUDIO_MCLK_768FS = 4,
479 HDMI_AUDIO_MCLK_1024FS = 5,
480 HDMI_AUDIO_MCLK_1152FS = 6,
481 HDMI_AUDIO_MCLK_192FS = 7
482};
483
484struct hdmi_core_video_config {
485 enum hdmi_core_inputbus_width ip_bus_width;
486 enum hdmi_core_dither_trunc op_dither_truc;
487 enum hdmi_core_deepcolor_ed deep_color_pkt;
488 enum hdmi_core_packet_mode pkt_mode;
489 enum hdmi_core_hdmi_dvi hdmi_dvi;
490 enum hdmi_core_tclkselclkmult tclk_sel_clkmult;
491};
492
493/*
494 * Refer to section 8.2 in HDMI 1.3 specification for
495 * details about infoframe databytes
496 */
497struct hdmi_core_infoframe_avi {
498 u8 db1_format;
499 /* Y0, Y1 rgb,yCbCr */
500 u8 db1_active_info;
501 /* A0 Active information Present */
502 u8 db1_bar_info_dv;
503 /* B0, B1 Bar info data valid */
504 u8 db1_scan_info;
505 /* S0, S1 scan information */
506 u8 db2_colorimetry;
507 /* C0, C1 colorimetry */
508 u8 db2_aspect_ratio;
509 /* M0, M1 Aspect ratio (4:3, 16:9) */
510 u8 db2_active_fmt_ar;
511 /* R0...R3 Active format aspect ratio */
512 u8 db3_itc;
513 /* ITC IT content. */
514 u8 db3_ec;
515 /* EC0, EC1, EC2 Extended colorimetry */
516 u8 db3_q_range;
517 /* Q1, Q0 Quantization range */
518 u8 db3_nup_scaling;
519 /* SC1, SC0 Non-uniform picture scaling */
520 u8 db4_videocode;
521 /* VIC0..6 Video format identification */
522 u8 db5_pixel_repeat;
523 /* PR0..PR3 Pixel repetition factor */
524 u16 db6_7_line_eoftop;
525 /* Line number end of top bar */
526 u16 db8_9_line_sofbottom;
527 /* Line number start of bottom bar */
528 u16 db10_11_pixel_eofleft;
529 /* Pixel number end of left bar */
530 u16 db12_13_pixel_sofright;
531 /* Pixel number start of right bar */
532};
533/*
534 * Refer to section 8.2 in HDMI 1.3 specification for
535 * details about infoframe databytes
536 */
537struct hdmi_core_infoframe_audio {
538 u8 db1_coding_type;
539 u8 db1_channel_count;
540 u8 db2_sample_freq;
541 u8 db2_sample_size;
542 u8 db4_channel_alloc;
543 bool db5_downmix_inh;
544 u8 db5_lsv; /* Level shift values for downmix */
545};
546
547struct hdmi_core_packet_enable_repeat {
548 u32 audio_pkt;
549 u32 audio_pkt_repeat;
550 u32 avi_infoframe;
551 u32 avi_infoframe_repeat;
552 u32 gen_cntrl_pkt;
553 u32 gen_cntrl_pkt_repeat;
554 u32 generic_pkt;
555 u32 generic_pkt_repeat;
556};
557
558struct hdmi_video_format {
559 enum hdmi_packing_mode packing_mode;
560 u32 y_res; /* Line per panel */
561 u32 x_res; /* pixel per line */
562};
563
564struct hdmi_video_interface {
565 int vsp; /* Vsync polarity */
566 int hsp; /* Hsync polarity */
567 int interlacing;
568 int tm; /* Timing mode */
569};
570
571struct hdmi_cm {
572 int code;
573 int mode;
574};
575
576struct hdmi_config {
577 struct hdmi_timings timings;
578 u16 interlace;
579 struct hdmi_cm cm;
580};
581
582struct hdmi_audio_format {
583 enum hdmi_stereo_channels stereo_channels;
584 u8 active_chnnls_msk;
585 enum hdmi_audio_type type;
586 enum hdmi_audio_justify justification;
587 enum hdmi_audio_sample_order sample_order;
588 enum hdmi_audio_samples_perword samples_per_word;
589 enum hdmi_audio_sample_size sample_size;
590 enum hdmi_audio_blk_strt_end_sig en_sig_blk_strt_end;
591};
592
593struct hdmi_audio_dma {
594 u8 transfer_size;
595 u8 block_size;
596 enum hdmi_audio_transf_mode mode;
597 u16 fifo_threshold;
598};
599
600struct hdmi_core_audio_i2s_config {
601 u8 word_max_length;
602 u8 word_length;
603 u8 in_length_bits;
604 u8 justification;
605 u8 en_high_bitrate_aud;
606 u8 sck_edge_mode;
607 u8 cbit_order;
608 u8 vbit;
609 u8 ws_polarity;
610 u8 direction;
611 u8 shift;
612 u8 active_sds;
613};
614
615struct hdmi_core_audio_config {
616 struct hdmi_core_audio_i2s_config i2s_cfg;
617 enum hdmi_core_audio_sample_freq freq_sample;
618 bool fs_override;
619 u32 n;
620 u32 cts;
621 u32 aud_par_busclk;
622 enum hdmi_core_audio_layout layout;
623 enum hdmi_core_cts_mode cts_mode;
624 bool use_mclk;
625 enum hdmi_audio_mclk_mode mclk_mode;
626 bool en_acr_pkt;
627 bool en_dsd_audio;
628 bool en_parallel_aud_input;
629 bool en_spdif;
630};
631#endif
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_omap4_panel.c
new file mode 100644
index 000000000000..7d4f2bd7c506
--- /dev/null
+++ b/drivers/video/omap2/dss/hdmi_omap4_panel.c
@@ -0,0 +1,222 @@
1/*
2 * hdmi_omap4_panel.c
3 *
4 * HDMI library support functions for TI OMAP4 processors.
5 *
6 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
7 * Authors: Mythri P k <mythripk@ti.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as published by
11 * the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include <linux/kernel.h>
23#include <linux/err.h>
24#include <linux/io.h>
25#include <linux/mutex.h>
26#include <linux/module.h>
27#include <video/omapdss.h>
28
29#include "dss.h"
30
31static struct {
32 struct mutex hdmi_lock;
33} hdmi;
34
35
36static int hdmi_panel_probe(struct omap_dss_device *dssdev)
37{
38 DSSDBG("ENTER hdmi_panel_probe\n");
39
40 dssdev->panel.config = OMAP_DSS_LCD_TFT |
41 OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS;
42
43 /*
44 * Initialize the timings to 640 * 480
45 * This is only for framebuffer update not for TV timing setting
46 * Setting TV timing will be done only on enable
47 */
48 dssdev->panel.timings.x_res = 640;
49 dssdev->panel.timings.y_res = 480;
50
51 DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n",
52 dssdev->panel.timings.x_res,
53 dssdev->panel.timings.y_res);
54 return 0;
55}
56
57static void hdmi_panel_remove(struct omap_dss_device *dssdev)
58{
59
60}
61
62static int hdmi_panel_enable(struct omap_dss_device *dssdev)
63{
64 int r = 0;
65 DSSDBG("ENTER hdmi_panel_enable\n");
66
67 mutex_lock(&hdmi.hdmi_lock);
68
69 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
70 r = -EINVAL;
71 goto err;
72 }
73
74 r = omapdss_hdmi_display_enable(dssdev);
75 if (r) {
76 DSSERR("failed to power on\n");
77 goto err;
78 }
79
80 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
81
82err:
83 mutex_unlock(&hdmi.hdmi_lock);
84
85 return r;
86}
87
88static void hdmi_panel_disable(struct omap_dss_device *dssdev)
89{
90 mutex_lock(&hdmi.hdmi_lock);
91
92 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
93 omapdss_hdmi_display_disable(dssdev);
94
95 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
96
97 mutex_unlock(&hdmi.hdmi_lock);
98}
99
100static int hdmi_panel_suspend(struct omap_dss_device *dssdev)
101{
102 int r = 0;
103
104 mutex_lock(&hdmi.hdmi_lock);
105
106 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
107 r = -EINVAL;
108 goto err;
109 }
110
111 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
112
113 omapdss_hdmi_display_disable(dssdev);
114
115err:
116 mutex_unlock(&hdmi.hdmi_lock);
117
118 return r;
119}
120
121static int hdmi_panel_resume(struct omap_dss_device *dssdev)
122{
123 int r = 0;
124
125 mutex_lock(&hdmi.hdmi_lock);
126
127 if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
128 r = -EINVAL;
129 goto err;
130 }
131
132 r = omapdss_hdmi_display_enable(dssdev);
133 if (r) {
134 DSSERR("failed to power on\n");
135 goto err;
136 }
137
138 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
139
140err:
141 mutex_unlock(&hdmi.hdmi_lock);
142
143 return r;
144}
145
146static void hdmi_get_timings(struct omap_dss_device *dssdev,
147 struct omap_video_timings *timings)
148{
149 mutex_lock(&hdmi.hdmi_lock);
150
151 *timings = dssdev->panel.timings;
152
153 mutex_unlock(&hdmi.hdmi_lock);
154}
155
156static void hdmi_set_timings(struct omap_dss_device *dssdev,
157 struct omap_video_timings *timings)
158{
159 DSSDBG("hdmi_set_timings\n");
160
161 mutex_lock(&hdmi.hdmi_lock);
162
163 dssdev->panel.timings = *timings;
164
165 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
166 /* turn the hdmi off and on to get new timings to use */
167 omapdss_hdmi_display_disable(dssdev);
168 omapdss_hdmi_display_set_timing(dssdev);
169 }
170
171 mutex_unlock(&hdmi.hdmi_lock);
172}
173
174static int hdmi_check_timings(struct omap_dss_device *dssdev,
175 struct omap_video_timings *timings)
176{
177 int r = 0;
178
179 DSSDBG("hdmi_check_timings\n");
180
181 mutex_lock(&hdmi.hdmi_lock);
182
183 r = omapdss_hdmi_display_check_timing(dssdev, timings);
184 if (r) {
185 DSSERR("Timing cannot be applied\n");
186 goto err;
187 }
188err:
189 mutex_unlock(&hdmi.hdmi_lock);
190 return r;
191}
192
193static struct omap_dss_driver hdmi_driver = {
194 .probe = hdmi_panel_probe,
195 .remove = hdmi_panel_remove,
196 .enable = hdmi_panel_enable,
197 .disable = hdmi_panel_disable,
198 .suspend = hdmi_panel_suspend,
199 .resume = hdmi_panel_resume,
200 .get_timings = hdmi_get_timings,
201 .set_timings = hdmi_set_timings,
202 .check_timings = hdmi_check_timings,
203 .driver = {
204 .name = "hdmi_panel",
205 .owner = THIS_MODULE,
206 },
207};
208
209int hdmi_panel_init(void)
210{
211 mutex_init(&hdmi.hdmi_lock);
212
213 omap_dss_register_driver(&hdmi_driver);
214
215 return 0;
216}
217
218void hdmi_panel_exit(void)
219{
220 omap_dss_unregister_driver(&hdmi_driver);
221
222}
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index 6a649ab5539e..9aeea50e33ff 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -29,10 +29,11 @@
29#include <linux/spinlock.h> 29#include <linux/spinlock.h>
30#include <linux/jiffies.h> 30#include <linux/jiffies.h>
31 31
32#include <plat/display.h> 32#include <video/omapdss.h>
33#include <plat/cpu.h> 33#include <plat/cpu.h>
34 34
35#include "dss.h" 35#include "dss.h"
36#include "dss_features.h"
36 37
37static int num_managers; 38static int num_managers;
38static struct list_head manager_list; 39static struct list_head manager_list;
@@ -392,6 +393,7 @@ struct overlay_cache_data {
392 393
393 u32 paddr; 394 u32 paddr;
394 void __iomem *vaddr; 395 void __iomem *vaddr;
396 u32 p_uv_addr; /* relevant for NV12 format only */
395 u16 screen_width; 397 u16 screen_width;
396 u16 width; 398 u16 width;
397 u16 height; 399 u16 height;
@@ -405,6 +407,7 @@ struct overlay_cache_data {
405 u16 out_width; /* if 0, out_width == width */ 407 u16 out_width; /* if 0, out_width == width */
406 u16 out_height; /* if 0, out_height == height */ 408 u16 out_height; /* if 0, out_height == height */
407 u8 global_alpha; 409 u8 global_alpha;
410 u8 pre_mult_alpha;
408 411
409 enum omap_channel channel; 412 enum omap_channel channel;
410 bool replication; 413 bool replication;
@@ -448,8 +451,8 @@ struct manager_cache_data {
448 451
449static struct { 452static struct {
450 spinlock_t lock; 453 spinlock_t lock;
451 struct overlay_cache_data overlay_cache[3]; 454 struct overlay_cache_data overlay_cache[MAX_DSS_OVERLAYS];
452 struct manager_cache_data manager_cache[2]; 455 struct manager_cache_data manager_cache[MAX_DSS_MANAGERS];
453 456
454 bool irq_enabled; 457 bool irq_enabled;
455} dss_cache; 458} dss_cache;
@@ -511,11 +514,16 @@ static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
511 unsigned long timeout = msecs_to_jiffies(500); 514 unsigned long timeout = msecs_to_jiffies(500);
512 u32 irq; 515 u32 irq;
513 516
514 if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) 517 if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) {
515 irq = DISPC_IRQ_EVSYNC_ODD; 518 irq = DISPC_IRQ_EVSYNC_ODD;
516 else 519 } else if (mgr->device->type == OMAP_DISPLAY_TYPE_HDMI) {
517 irq = DISPC_IRQ_VSYNC; 520 irq = DISPC_IRQ_EVSYNC_EVEN;
518 521 } else {
522 if (mgr->id == OMAP_DSS_CHANNEL_LCD)
523 irq = DISPC_IRQ_VSYNC;
524 else
525 irq = DISPC_IRQ_VSYNC2;
526 }
519 return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); 527 return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
520} 528}
521 529
@@ -523,7 +531,6 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
523{ 531{
524 unsigned long timeout = msecs_to_jiffies(500); 532 unsigned long timeout = msecs_to_jiffies(500);
525 struct manager_cache_data *mc; 533 struct manager_cache_data *mc;
526 enum omap_channel channel;
527 u32 irq; 534 u32 irq;
528 int r; 535 int r;
529 int i; 536 int i;
@@ -532,9 +539,9 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
532 if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) 539 if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
533 return 0; 540 return 0;
534 541
535 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { 542 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
543 || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
536 irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; 544 irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
537 channel = OMAP_DSS_CHANNEL_DIGIT;
538 } else { 545 } else {
539 if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { 546 if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
540 enum omap_dss_update_mode mode; 547 enum omap_dss_update_mode mode;
@@ -542,11 +549,14 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
542 if (mode != OMAP_DSS_UPDATE_AUTO) 549 if (mode != OMAP_DSS_UPDATE_AUTO)
543 return 0; 550 return 0;
544 551
545 irq = DISPC_IRQ_FRAMEDONE; 552 irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
553 DISPC_IRQ_FRAMEDONE
554 : DISPC_IRQ_FRAMEDONE2;
546 } else { 555 } else {
547 irq = DISPC_IRQ_VSYNC; 556 irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
557 DISPC_IRQ_VSYNC
558 : DISPC_IRQ_VSYNC2;
548 } 559 }
549 channel = OMAP_DSS_CHANNEL_LCD;
550 } 560 }
551 561
552 mc = &dss_cache.manager_cache[mgr->id]; 562 mc = &dss_cache.manager_cache[mgr->id];
@@ -593,7 +603,6 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
593int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) 603int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
594{ 604{
595 unsigned long timeout = msecs_to_jiffies(500); 605 unsigned long timeout = msecs_to_jiffies(500);
596 enum omap_channel channel;
597 struct overlay_cache_data *oc; 606 struct overlay_cache_data *oc;
598 struct omap_dss_device *dssdev; 607 struct omap_dss_device *dssdev;
599 u32 irq; 608 u32 irq;
@@ -608,9 +617,9 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
608 if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) 617 if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
609 return 0; 618 return 0;
610 619
611 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { 620 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
621 || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
612 irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; 622 irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
613 channel = OMAP_DSS_CHANNEL_DIGIT;
614 } else { 623 } else {
615 if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { 624 if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
616 enum omap_dss_update_mode mode; 625 enum omap_dss_update_mode mode;
@@ -618,11 +627,14 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
618 if (mode != OMAP_DSS_UPDATE_AUTO) 627 if (mode != OMAP_DSS_UPDATE_AUTO)
619 return 0; 628 return 0;
620 629
621 irq = DISPC_IRQ_FRAMEDONE; 630 irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
631 DISPC_IRQ_FRAMEDONE
632 : DISPC_IRQ_FRAMEDONE2;
622 } else { 633 } else {
623 irq = DISPC_IRQ_VSYNC; 634 irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
635 DISPC_IRQ_VSYNC
636 : DISPC_IRQ_VSYNC2;
624 } 637 }
625 channel = OMAP_DSS_CHANNEL_LCD;
626 } 638 }
627 639
628 oc = &dss_cache.overlay_cache[ovl->id]; 640 oc = &dss_cache.overlay_cache[ovl->id];
@@ -764,10 +776,17 @@ static int configure_overlay(enum omap_plane plane)
764 } 776 }
765 777
766 switch (c->color_mode) { 778 switch (c->color_mode) {
779 case OMAP_DSS_COLOR_NV12:
780 bpp = 8;
781 break;
767 case OMAP_DSS_COLOR_RGB16: 782 case OMAP_DSS_COLOR_RGB16:
768 case OMAP_DSS_COLOR_ARGB16: 783 case OMAP_DSS_COLOR_ARGB16:
769 case OMAP_DSS_COLOR_YUV2: 784 case OMAP_DSS_COLOR_YUV2:
770 case OMAP_DSS_COLOR_UYVY: 785 case OMAP_DSS_COLOR_UYVY:
786 case OMAP_DSS_COLOR_RGBA16:
787 case OMAP_DSS_COLOR_RGBX16:
788 case OMAP_DSS_COLOR_ARGB16_1555:
789 case OMAP_DSS_COLOR_XRGB16_1555:
771 bpp = 16; 790 bpp = 16;
772 break; 791 break;
773 792
@@ -841,7 +860,10 @@ static int configure_overlay(enum omap_plane plane)
841 c->rotation_type, 860 c->rotation_type,
842 c->rotation, 861 c->rotation,
843 c->mirror, 862 c->mirror,
844 c->global_alpha); 863 c->global_alpha,
864 c->pre_mult_alpha,
865 c->channel,
866 c->p_uv_addr);
845 867
846 if (r) { 868 if (r) {
847 /* this shouldn't happen */ 869 /* this shouldn't happen */
@@ -882,21 +904,21 @@ static int configure_dispc(void)
882{ 904{
883 struct overlay_cache_data *oc; 905 struct overlay_cache_data *oc;
884 struct manager_cache_data *mc; 906 struct manager_cache_data *mc;
885 const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); 907 const int num_ovls = dss_feat_get_num_ovls();
886 const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache); 908 const int num_mgrs = dss_feat_get_num_mgrs();
887 int i; 909 int i;
888 int r; 910 int r;
889 bool mgr_busy[2]; 911 bool mgr_busy[MAX_DSS_MANAGERS];
890 bool mgr_go[2]; 912 bool mgr_go[MAX_DSS_MANAGERS];
891 bool busy; 913 bool busy;
892 914
893 r = 0; 915 r = 0;
894 busy = false; 916 busy = false;
895 917
896 mgr_busy[0] = dispc_go_busy(0); 918 for (i = 0; i < num_mgrs; i++) {
897 mgr_busy[1] = dispc_go_busy(1); 919 mgr_busy[i] = dispc_go_busy(i);
898 mgr_go[0] = false; 920 mgr_go[i] = false;
899 mgr_go[1] = false; 921 }
900 922
901 /* Commit overlay settings */ 923 /* Commit overlay settings */
902 for (i = 0; i < num_ovls; ++i) { 924 for (i = 0; i < num_ovls; ++i) {
@@ -989,7 +1011,7 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev,
989{ 1011{
990 struct overlay_cache_data *oc; 1012 struct overlay_cache_data *oc;
991 struct manager_cache_data *mc; 1013 struct manager_cache_data *mc;
992 const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); 1014 const int num_ovls = dss_feat_get_num_ovls();
993 struct omap_overlay_manager *mgr; 1015 struct omap_overlay_manager *mgr;
994 int i; 1016 int i;
995 u16 x, y, w, h; 1017 u16 x, y, w, h;
@@ -1121,8 +1143,8 @@ void dss_start_update(struct omap_dss_device *dssdev)
1121{ 1143{
1122 struct manager_cache_data *mc; 1144 struct manager_cache_data *mc;
1123 struct overlay_cache_data *oc; 1145 struct overlay_cache_data *oc;
1124 const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); 1146 const int num_ovls = dss_feat_get_num_ovls();
1125 const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache); 1147 const int num_mgrs = dss_feat_get_num_mgrs();
1126 struct omap_overlay_manager *mgr; 1148 struct omap_overlay_manager *mgr;
1127 int i; 1149 int i;
1128 1150
@@ -1151,13 +1173,14 @@ static void dss_apply_irq_handler(void *data, u32 mask)
1151{ 1173{
1152 struct manager_cache_data *mc; 1174 struct manager_cache_data *mc;
1153 struct overlay_cache_data *oc; 1175 struct overlay_cache_data *oc;
1154 const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); 1176 const int num_ovls = dss_feat_get_num_ovls();
1155 const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache); 1177 const int num_mgrs = dss_feat_get_num_mgrs();
1156 int i, r; 1178 int i, r;
1157 bool mgr_busy[2]; 1179 bool mgr_busy[MAX_DSS_MANAGERS];
1180 u32 irq_mask;
1158 1181
1159 mgr_busy[0] = dispc_go_busy(0); 1182 for (i = 0; i < num_mgrs; i++)
1160 mgr_busy[1] = dispc_go_busy(1); 1183 mgr_busy[i] = dispc_go_busy(i);
1161 1184
1162 spin_lock(&dss_cache.lock); 1185 spin_lock(&dss_cache.lock);
1163 1186
@@ -1178,8 +1201,8 @@ static void dss_apply_irq_handler(void *data, u32 mask)
1178 goto end; 1201 goto end;
1179 1202
1180 /* re-read busy flags */ 1203 /* re-read busy flags */
1181 mgr_busy[0] = dispc_go_busy(0); 1204 for (i = 0; i < num_mgrs; i++)
1182 mgr_busy[1] = dispc_go_busy(1); 1205 mgr_busy[i] = dispc_go_busy(i);
1183 1206
1184 /* keep running as long as there are busy managers, so that 1207 /* keep running as long as there are busy managers, so that
1185 * we can collect overlay-applied information */ 1208 * we can collect overlay-applied information */
@@ -1188,9 +1211,12 @@ static void dss_apply_irq_handler(void *data, u32 mask)
1188 goto end; 1211 goto end;
1189 } 1212 }
1190 1213
1191 omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, 1214 irq_mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD |
1192 DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD | 1215 DISPC_IRQ_EVSYNC_EVEN;
1193 DISPC_IRQ_EVSYNC_EVEN); 1216 if (dss_has_feature(FEAT_MGR_LCD2))
1217 irq_mask |= DISPC_IRQ_VSYNC2;
1218
1219 omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, irq_mask);
1194 dss_cache.irq_enabled = false; 1220 dss_cache.irq_enabled = false;
1195 1221
1196end: 1222end:
@@ -1252,6 +1278,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
1252 1278
1253 oc->paddr = ovl->info.paddr; 1279 oc->paddr = ovl->info.paddr;
1254 oc->vaddr = ovl->info.vaddr; 1280 oc->vaddr = ovl->info.vaddr;
1281 oc->p_uv_addr = ovl->info.p_uv_addr;
1255 oc->screen_width = ovl->info.screen_width; 1282 oc->screen_width = ovl->info.screen_width;
1256 oc->width = ovl->info.width; 1283 oc->width = ovl->info.width;
1257 oc->height = ovl->info.height; 1284 oc->height = ovl->info.height;
@@ -1264,6 +1291,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
1264 oc->out_width = ovl->info.out_width; 1291 oc->out_width = ovl->info.out_width;
1265 oc->out_height = ovl->info.out_height; 1292 oc->out_height = ovl->info.out_height;
1266 oc->global_alpha = ovl->info.global_alpha; 1293 oc->global_alpha = ovl->info.global_alpha;
1294 oc->pre_mult_alpha = ovl->info.pre_mult_alpha;
1267 1295
1268 oc->replication = 1296 oc->replication =
1269 dss_use_replication(dssdev, ovl->info.color_mode); 1297 dss_use_replication(dssdev, ovl->info.color_mode);
@@ -1363,6 +1391,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
1363 case OMAP_DISPLAY_TYPE_DBI: 1391 case OMAP_DISPLAY_TYPE_DBI:
1364 case OMAP_DISPLAY_TYPE_SDI: 1392 case OMAP_DISPLAY_TYPE_SDI:
1365 case OMAP_DISPLAY_TYPE_VENC: 1393 case OMAP_DISPLAY_TYPE_VENC:
1394 case OMAP_DISPLAY_TYPE_HDMI:
1366 default_get_overlay_fifo_thresholds(ovl->id, size, 1395 default_get_overlay_fifo_thresholds(ovl->id, size,
1367 &oc->burst_size, &oc->fifo_low, 1396 &oc->burst_size, &oc->fifo_low,
1368 &oc->fifo_high); 1397 &oc->fifo_high);
@@ -1380,15 +1409,20 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
1380 } 1409 }
1381 1410
1382 r = 0; 1411 r = 0;
1383 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); 1412 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
1384 if (!dss_cache.irq_enabled) { 1413 if (!dss_cache.irq_enabled) {
1385 r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, 1414 u32 mask;
1386 DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD | 1415
1387 DISPC_IRQ_EVSYNC_EVEN); 1416 mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD |
1417 DISPC_IRQ_EVSYNC_EVEN;
1418 if (dss_has_feature(FEAT_MGR_LCD2))
1419 mask |= DISPC_IRQ_VSYNC2;
1420
1421 r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask);
1388 dss_cache.irq_enabled = true; 1422 dss_cache.irq_enabled = true;
1389 } 1423 }
1390 configure_dispc(); 1424 configure_dispc();
1391 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); 1425 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
1392 1426
1393 spin_unlock_irqrestore(&dss_cache.lock, flags); 1427 spin_unlock_irqrestore(&dss_cache.lock, flags);
1394 1428
@@ -1461,7 +1495,7 @@ int dss_init_overlay_managers(struct platform_device *pdev)
1461 1495
1462 num_managers = 0; 1496 num_managers = 0;
1463 1497
1464 for (i = 0; i < 2; ++i) { 1498 for (i = 0; i < dss_feat_get_num_mgrs(); ++i) {
1465 struct omap_overlay_manager *mgr; 1499 struct omap_overlay_manager *mgr;
1466 mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); 1500 mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
1467 1501
@@ -1471,14 +1505,14 @@ int dss_init_overlay_managers(struct platform_device *pdev)
1471 case 0: 1505 case 0:
1472 mgr->name = "lcd"; 1506 mgr->name = "lcd";
1473 mgr->id = OMAP_DSS_CHANNEL_LCD; 1507 mgr->id = OMAP_DSS_CHANNEL_LCD;
1474 mgr->supported_displays =
1475 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
1476 OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI;
1477 break; 1508 break;
1478 case 1: 1509 case 1:
1479 mgr->name = "tv"; 1510 mgr->name = "tv";
1480 mgr->id = OMAP_DSS_CHANNEL_DIGIT; 1511 mgr->id = OMAP_DSS_CHANNEL_DIGIT;
1481 mgr->supported_displays = OMAP_DISPLAY_TYPE_VENC; 1512 break;
1513 case 2:
1514 mgr->name = "lcd2";
1515 mgr->id = OMAP_DSS_CHANNEL_LCD2;
1482 break; 1516 break;
1483 } 1517 }
1484 1518
@@ -1494,6 +1528,8 @@ int dss_init_overlay_managers(struct platform_device *pdev)
1494 mgr->disable = &dss_mgr_disable; 1528 mgr->disable = &dss_mgr_disable;
1495 1529
1496 mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC; 1530 mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC;
1531 mgr->supported_displays =
1532 dss_feat_get_supported_displays(mgr->id);
1497 1533
1498 dss_overlay_setup_dispc_manager(mgr); 1534 dss_overlay_setup_dispc_manager(mgr);
1499 1535
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index 244dca81a399..0f08025b1f0e 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -31,10 +31,11 @@
31#include <linux/delay.h> 31#include <linux/delay.h>
32#include <linux/slab.h> 32#include <linux/slab.h>
33 33
34#include <plat/display.h> 34#include <video/omapdss.h>
35#include <plat/cpu.h> 35#include <plat/cpu.h>
36 36
37#include "dss.h" 37#include "dss.h"
38#include "dss_features.h"
38 39
39static int num_overlays; 40static int num_overlays;
40static struct list_head overlay_list; 41static struct list_head overlay_list;
@@ -200,12 +201,16 @@ static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
200static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf, 201static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
201 size_t size) 202 size_t size)
202{ 203{
203 int r; 204 int r, enable;
204 struct omap_overlay_info info; 205 struct omap_overlay_info info;
205 206
206 ovl->get_overlay_info(ovl, &info); 207 ovl->get_overlay_info(ovl, &info);
207 208
208 info.enabled = simple_strtoul(buf, NULL, 10); 209 r = kstrtoint(buf, 0, &enable);
210 if (r)
211 return r;
212
213 info.enabled = !!enable;
209 214
210 r = ovl->set_overlay_info(ovl, &info); 215 r = ovl->set_overlay_info(ovl, &info);
211 if (r) 216 if (r)
@@ -230,17 +235,65 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
230 const char *buf, size_t size) 235 const char *buf, size_t size)
231{ 236{
232 int r; 237 int r;
238 u8 alpha;
233 struct omap_overlay_info info; 239 struct omap_overlay_info info;
234 240
241 r = kstrtou8(buf, 0, &alpha);
242 if (r)
243 return r;
244
235 ovl->get_overlay_info(ovl, &info); 245 ovl->get_overlay_info(ovl, &info);
236 246
237 /* Video1 plane does not support global alpha 247 /* Video1 plane does not support global alpha
238 * to always make it 255 completely opaque 248 * to always make it 255 completely opaque
239 */ 249 */
240 if (ovl->id == OMAP_DSS_VIDEO1) 250 if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
251 ovl->id == OMAP_DSS_VIDEO1)
241 info.global_alpha = 255; 252 info.global_alpha = 255;
242 else 253 else
243 info.global_alpha = simple_strtoul(buf, NULL, 10); 254 info.global_alpha = alpha;
255
256 r = ovl->set_overlay_info(ovl, &info);
257 if (r)
258 return r;
259
260 if (ovl->manager) {
261 r = ovl->manager->apply(ovl->manager);
262 if (r)
263 return r;
264 }
265
266 return size;
267}
268
269static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
270 char *buf)
271{
272 return snprintf(buf, PAGE_SIZE, "%d\n",
273 ovl->info.pre_mult_alpha);
274}
275
276static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
277 const char *buf, size_t size)
278{
279 int r;
280 u8 alpha;
281 struct omap_overlay_info info;
282
283 r = kstrtou8(buf, 0, &alpha);
284 if (r)
285 return r;
286
287 ovl->get_overlay_info(ovl, &info);
288
289 /* only GFX and Video2 plane support pre alpha multiplied
290 * set zero for Video1 plane
291 */
292 if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
293 ovl->id == OMAP_DSS_VIDEO1)
294 info.pre_mult_alpha = 0;
295 else
296 info.pre_mult_alpha = alpha;
244 297
245 r = ovl->set_overlay_info(ovl, &info); 298 r = ovl->set_overlay_info(ovl, &info);
246 if (r) 299 if (r)
@@ -278,6 +331,9 @@ static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
278 overlay_enabled_show, overlay_enabled_store); 331 overlay_enabled_show, overlay_enabled_store);
279static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR, 332static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
280 overlay_global_alpha_show, overlay_global_alpha_store); 333 overlay_global_alpha_show, overlay_global_alpha_store);
334static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
335 overlay_pre_mult_alpha_show,
336 overlay_pre_mult_alpha_store);
281 337
282static struct attribute *overlay_sysfs_attrs[] = { 338static struct attribute *overlay_sysfs_attrs[] = {
283 &overlay_attr_name.attr, 339 &overlay_attr_name.attr,
@@ -288,6 +344,7 @@ static struct attribute *overlay_sysfs_attrs[] = {
288 &overlay_attr_output_size.attr, 344 &overlay_attr_output_size.attr,
289 &overlay_attr_enabled.attr, 345 &overlay_attr_enabled.attr,
290 &overlay_attr_global_alpha.attr, 346 &overlay_attr_global_alpha.attr,
347 &overlay_attr_pre_mult_alpha.attr,
291 NULL 348 NULL
292}; 349};
293 350
@@ -447,16 +504,21 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
447 504
448 ovl->manager = mgr; 505 ovl->manager = mgr;
449 506
450 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); 507 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
451 /* XXX: on manual update display, in auto update mode, a bug happens 508 /* XXX: When there is an overlay on a DSI manual update display, and
452 * here. When an overlay is first enabled on LCD, then it's disabled, 509 * the overlay is first disabled, then moved to tv, and enabled, we
453 * and the manager is changed to TV, we sometimes get SYNC_LOST_DIGIT 510 * seem to get SYNC_LOST_DIGIT error.
454 * errors. Waiting before changing the channel_out fixes it. I'm 511 *
455 * guessing that the overlay is still somehow being used for the LCD, 512 * Waiting doesn't seem to help, but updating the manual update display
456 * but I don't understand how or why. */ 513 * after disabling the overlay seems to fix this. This hints that the
457 msleep(40); 514 * overlay is perhaps somehow tied to the LCD output until the output
515 * is updated.
516 *
517 * Userspace workaround for this is to update the LCD after disabling
518 * the overlay, but before moving the overlay to TV.
519 */
458 dispc_set_channel_out(ovl->id, mgr->id); 520 dispc_set_channel_out(ovl->id, mgr->id);
459 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); 521 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
460 522
461 return 0; 523 return 0;
462} 524}
@@ -510,11 +572,11 @@ static void omap_dss_add_overlay(struct omap_overlay *overlay)
510 list_add_tail(&overlay->list, &overlay_list); 572 list_add_tail(&overlay->list, &overlay_list);
511} 573}
512 574
513static struct omap_overlay *dispc_overlays[3]; 575static struct omap_overlay *dispc_overlays[MAX_DSS_OVERLAYS];
514 576
515void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr) 577void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr)
516{ 578{
517 mgr->num_overlays = 3; 579 mgr->num_overlays = dss_feat_get_num_ovls();
518 mgr->overlays = dispc_overlays; 580 mgr->overlays = dispc_overlays;
519} 581}
520 582
@@ -535,7 +597,7 @@ void dss_init_overlays(struct platform_device *pdev)
535 597
536 num_overlays = 0; 598 num_overlays = 0;
537 599
538 for (i = 0; i < 3; ++i) { 600 for (i = 0; i < dss_feat_get_num_ovls(); ++i) {
539 struct omap_overlay *ovl; 601 struct omap_overlay *ovl;
540 ovl = kzalloc(sizeof(*ovl), GFP_KERNEL); 602 ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
541 603
@@ -545,18 +607,12 @@ void dss_init_overlays(struct platform_device *pdev)
545 case 0: 607 case 0:
546 ovl->name = "gfx"; 608 ovl->name = "gfx";
547 ovl->id = OMAP_DSS_GFX; 609 ovl->id = OMAP_DSS_GFX;
548 ovl->supported_modes = cpu_is_omap34xx() ?
549 OMAP_DSS_COLOR_GFX_OMAP3 :
550 OMAP_DSS_COLOR_GFX_OMAP2;
551 ovl->caps = OMAP_DSS_OVL_CAP_DISPC; 610 ovl->caps = OMAP_DSS_OVL_CAP_DISPC;
552 ovl->info.global_alpha = 255; 611 ovl->info.global_alpha = 255;
553 break; 612 break;
554 case 1: 613 case 1:
555 ovl->name = "vid1"; 614 ovl->name = "vid1";
556 ovl->id = OMAP_DSS_VIDEO1; 615 ovl->id = OMAP_DSS_VIDEO1;
557 ovl->supported_modes = cpu_is_omap34xx() ?
558 OMAP_DSS_COLOR_VID1_OMAP3 :
559 OMAP_DSS_COLOR_VID_OMAP2;
560 ovl->caps = OMAP_DSS_OVL_CAP_SCALE | 616 ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
561 OMAP_DSS_OVL_CAP_DISPC; 617 OMAP_DSS_OVL_CAP_DISPC;
562 ovl->info.global_alpha = 255; 618 ovl->info.global_alpha = 255;
@@ -564,9 +620,6 @@ void dss_init_overlays(struct platform_device *pdev)
564 case 2: 620 case 2:
565 ovl->name = "vid2"; 621 ovl->name = "vid2";
566 ovl->id = OMAP_DSS_VIDEO2; 622 ovl->id = OMAP_DSS_VIDEO2;
567 ovl->supported_modes = cpu_is_omap34xx() ?
568 OMAP_DSS_COLOR_VID2_OMAP3 :
569 OMAP_DSS_COLOR_VID_OMAP2;
570 ovl->caps = OMAP_DSS_OVL_CAP_SCALE | 623 ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
571 OMAP_DSS_OVL_CAP_DISPC; 624 OMAP_DSS_OVL_CAP_DISPC;
572 ovl->info.global_alpha = 255; 625 ovl->info.global_alpha = 255;
@@ -579,6 +632,9 @@ void dss_init_overlays(struct platform_device *pdev)
579 ovl->get_overlay_info = &dss_ovl_get_overlay_info; 632 ovl->get_overlay_info = &dss_ovl_get_overlay_info;
580 ovl->wait_for_go = &dss_ovl_wait_for_go; 633 ovl->wait_for_go = &dss_ovl_wait_for_go;
581 634
635 ovl->supported_modes =
636 dss_feat_get_supported_color_modes(ovl->id);
637
582 omap_dss_add_overlay(ovl); 638 omap_dss_add_overlay(ovl);
583 639
584 r = kobject_init_and_add(&ovl->kobj, &overlay_ktype, 640 r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
@@ -627,12 +683,23 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
627 int i; 683 int i;
628 struct omap_overlay_manager *lcd_mgr; 684 struct omap_overlay_manager *lcd_mgr;
629 struct omap_overlay_manager *tv_mgr; 685 struct omap_overlay_manager *tv_mgr;
686 struct omap_overlay_manager *lcd2_mgr = NULL;
630 struct omap_overlay_manager *mgr = NULL; 687 struct omap_overlay_manager *mgr = NULL;
631 688
632 lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD); 689 lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD);
633 tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_TV); 690 tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_TV);
634 691 if (dss_has_feature(FEAT_MGR_LCD2))
635 if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) { 692 lcd2_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD2);
693
694 if (dssdev->channel == OMAP_DSS_CHANNEL_LCD2) {
695 if (!lcd2_mgr->device || force) {
696 if (lcd2_mgr->device)
697 lcd2_mgr->unset_device(lcd2_mgr);
698 lcd2_mgr->set_device(lcd2_mgr, dssdev);
699 mgr = lcd2_mgr;
700 }
701 } else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC
702 && dssdev->type != OMAP_DISPLAY_TYPE_HDMI) {
636 if (!lcd_mgr->device || force) { 703 if (!lcd_mgr->device || force) {
637 if (lcd_mgr->device) 704 if (lcd_mgr->device)
638 lcd_mgr->unset_device(lcd_mgr); 705 lcd_mgr->unset_device(lcd_mgr);
@@ -641,7 +708,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
641 } 708 }
642 } 709 }
643 710
644 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { 711 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
712 || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
645 if (!tv_mgr->device || force) { 713 if (!tv_mgr->device || force) {
646 if (tv_mgr->device) 714 if (tv_mgr->device)
647 tv_mgr->unset_device(tv_mgr); 715 tv_mgr->unset_device(tv_mgr);
@@ -651,7 +719,7 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
651 } 719 }
652 720
653 if (mgr) { 721 if (mgr) {
654 for (i = 0; i < 3; i++) { 722 for (i = 0; i < dss_feat_get_num_ovls(); i++) {
655 struct omap_overlay *ovl; 723 struct omap_overlay *ovl;
656 ovl = omap_dss_get_overlay(i); 724 ovl = omap_dss_get_overlay(i);
657 if (!ovl->manager || force) { 725 if (!ovl->manager || force) {
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index bbe62464e92d..c06fbe0bc678 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -32,12 +32,11 @@
32#include <linux/ktime.h> 32#include <linux/ktime.h>
33#include <linux/hrtimer.h> 33#include <linux/hrtimer.h>
34#include <linux/seq_file.h> 34#include <linux/seq_file.h>
35#include <linux/semaphore.h>
35 36
36#include <plat/display.h> 37#include <video/omapdss.h>
37#include "dss.h" 38#include "dss.h"
38 39
39#define RFBI_BASE 0x48050800
40
41struct rfbi_reg { u16 idx; }; 40struct rfbi_reg { u16 idx; };
42 41
43#define RFBI_REG(idx) ((const struct rfbi_reg) { idx }) 42#define RFBI_REG(idx) ((const struct rfbi_reg) { idx })
@@ -67,9 +66,6 @@ struct rfbi_reg { u16 idx; };
67#define REG_FLD_MOD(idx, val, start, end) \ 66#define REG_FLD_MOD(idx, val, start, end) \
68 rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end)) 67 rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end))
69 68
70/* To work around an RFBI transfer rate limitation */
71#define OMAP_RFBI_RATE_LIMIT 1
72
73enum omap_rfbi_cycleformat { 69enum omap_rfbi_cycleformat {
74 OMAP_DSS_RFBI_CYCLEFORMAT_1_1 = 0, 70 OMAP_DSS_RFBI_CYCLEFORMAT_1_1 = 0,
75 OMAP_DSS_RFBI_CYCLEFORMAT_2_1 = 1, 71 OMAP_DSS_RFBI_CYCLEFORMAT_2_1 = 1,
@@ -91,15 +87,11 @@ enum omap_rfbi_parallelmode {
91 OMAP_DSS_RFBI_PARALLELMODE_16 = 3, 87 OMAP_DSS_RFBI_PARALLELMODE_16 = 3,
92}; 88};
93 89
94enum update_cmd {
95 RFBI_CMD_UPDATE = 0,
96 RFBI_CMD_SYNC = 1,
97};
98
99static int rfbi_convert_timings(struct rfbi_timings *t); 90static int rfbi_convert_timings(struct rfbi_timings *t);
100static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div); 91static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div);
101 92
102static struct { 93static struct {
94 struct platform_device *pdev;
103 void __iomem *base; 95 void __iomem *base;
104 96
105 unsigned long l4_khz; 97 unsigned long l4_khz;
@@ -115,20 +107,9 @@ static struct {
115 107
116 struct omap_dss_device *dssdev[2]; 108 struct omap_dss_device *dssdev[2];
117 109
118 struct kfifo cmd_fifo; 110 struct semaphore bus_lock;
119 spinlock_t cmd_lock;
120 struct completion cmd_done;
121 atomic_t cmd_fifo_full;
122 atomic_t cmd_pending;
123} rfbi; 111} rfbi;
124 112
125struct update_region {
126 u16 x;
127 u16 y;
128 u16 w;
129 u16 h;
130};
131
132static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val) 113static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
133{ 114{
134 __raw_writel(val, rfbi.base + idx.idx); 115 __raw_writel(val, rfbi.base + idx.idx);
@@ -142,14 +123,25 @@ static inline u32 rfbi_read_reg(const struct rfbi_reg idx)
142static void rfbi_enable_clocks(bool enable) 123static void rfbi_enable_clocks(bool enable)
143{ 124{
144 if (enable) 125 if (enable)
145 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); 126 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
146 else 127 else
147 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); 128 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
129}
130
131void rfbi_bus_lock(void)
132{
133 down(&rfbi.bus_lock);
134}
135EXPORT_SYMBOL(rfbi_bus_lock);
136
137void rfbi_bus_unlock(void)
138{
139 up(&rfbi.bus_lock);
148} 140}
141EXPORT_SYMBOL(rfbi_bus_unlock);
149 142
150void omap_rfbi_write_command(const void *buf, u32 len) 143void omap_rfbi_write_command(const void *buf, u32 len)
151{ 144{
152 rfbi_enable_clocks(1);
153 switch (rfbi.parallelmode) { 145 switch (rfbi.parallelmode) {
154 case OMAP_DSS_RFBI_PARALLELMODE_8: 146 case OMAP_DSS_RFBI_PARALLELMODE_8:
155 { 147 {
@@ -173,13 +165,11 @@ void omap_rfbi_write_command(const void *buf, u32 len)
173 default: 165 default:
174 BUG(); 166 BUG();
175 } 167 }
176 rfbi_enable_clocks(0);
177} 168}
178EXPORT_SYMBOL(omap_rfbi_write_command); 169EXPORT_SYMBOL(omap_rfbi_write_command);
179 170
180void omap_rfbi_read_data(void *buf, u32 len) 171void omap_rfbi_read_data(void *buf, u32 len)
181{ 172{
182 rfbi_enable_clocks(1);
183 switch (rfbi.parallelmode) { 173 switch (rfbi.parallelmode) {
184 case OMAP_DSS_RFBI_PARALLELMODE_8: 174 case OMAP_DSS_RFBI_PARALLELMODE_8:
185 { 175 {
@@ -207,13 +197,11 @@ void omap_rfbi_read_data(void *buf, u32 len)
207 default: 197 default:
208 BUG(); 198 BUG();
209 } 199 }
210 rfbi_enable_clocks(0);
211} 200}
212EXPORT_SYMBOL(omap_rfbi_read_data); 201EXPORT_SYMBOL(omap_rfbi_read_data);
213 202
214void omap_rfbi_write_data(const void *buf, u32 len) 203void omap_rfbi_write_data(const void *buf, u32 len)
215{ 204{
216 rfbi_enable_clocks(1);
217 switch (rfbi.parallelmode) { 205 switch (rfbi.parallelmode) {
218 case OMAP_DSS_RFBI_PARALLELMODE_8: 206 case OMAP_DSS_RFBI_PARALLELMODE_8:
219 { 207 {
@@ -238,7 +226,6 @@ void omap_rfbi_write_data(const void *buf, u32 len)
238 BUG(); 226 BUG();
239 227
240 } 228 }
241 rfbi_enable_clocks(0);
242} 229}
243EXPORT_SYMBOL(omap_rfbi_write_data); 230EXPORT_SYMBOL(omap_rfbi_write_data);
244 231
@@ -250,8 +237,6 @@ void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
250 int horiz_offset = scr_width - w; 237 int horiz_offset = scr_width - w;
251 int i; 238 int i;
252 239
253 rfbi_enable_clocks(1);
254
255 if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 && 240 if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
256 rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) { 241 rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
257 const u16 __iomem *pd = buf; 242 const u16 __iomem *pd = buf;
@@ -296,13 +281,11 @@ void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
296 } else { 281 } else {
297 BUG(); 282 BUG();
298 } 283 }
299
300 rfbi_enable_clocks(0);
301} 284}
302EXPORT_SYMBOL(omap_rfbi_write_pixels); 285EXPORT_SYMBOL(omap_rfbi_write_pixels);
303 286
304void rfbi_transfer_area(u16 width, u16 height, 287static void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width,
305 void (callback)(void *data), void *data) 288 u16 height, void (*callback)(void *data), void *data)
306{ 289{
307 u32 l; 290 u32 l;
308 291
@@ -311,15 +294,13 @@ void rfbi_transfer_area(u16 width, u16 height,
311 294
312 DSSDBG("rfbi_transfer_area %dx%d\n", width, height); 295 DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
313 296
314 dispc_set_lcd_size(width, height); 297 dispc_set_lcd_size(dssdev->manager->id, width, height);
315 298
316 dispc_enable_channel(OMAP_DSS_CHANNEL_LCD, true); 299 dispc_enable_channel(dssdev->manager->id, true);
317 300
318 rfbi.framedone_callback = callback; 301 rfbi.framedone_callback = callback;
319 rfbi.framedone_callback_data = data; 302 rfbi.framedone_callback_data = data;
320 303
321 rfbi_enable_clocks(1);
322
323 rfbi_write_reg(RFBI_PIXEL_CNT, width * height); 304 rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
324 305
325 l = rfbi_read_reg(RFBI_CONTROL); 306 l = rfbi_read_reg(RFBI_CONTROL);
@@ -338,15 +319,11 @@ static void framedone_callback(void *data, u32 mask)
338 319
339 REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0); 320 REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0);
340 321
341 rfbi_enable_clocks(0);
342
343 callback = rfbi.framedone_callback; 322 callback = rfbi.framedone_callback;
344 rfbi.framedone_callback = NULL; 323 rfbi.framedone_callback = NULL;
345 324
346 if (callback != NULL) 325 if (callback != NULL)
347 callback(rfbi.framedone_callback_data); 326 callback(rfbi.framedone_callback_data);
348
349 atomic_set(&rfbi.cmd_pending, 0);
350} 327}
351 328
352#if 1 /* VERBOSE */ 329#if 1 /* VERBOSE */
@@ -436,7 +413,7 @@ static int calc_extif_timings(struct rfbi_timings *t)
436} 413}
437 414
438 415
439void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t) 416static void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t)
440{ 417{
441 int r; 418 int r;
442 419
@@ -448,7 +425,6 @@ void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t)
448 425
449 BUG_ON(!t->converted); 426 BUG_ON(!t->converted);
450 427
451 rfbi_enable_clocks(1);
452 rfbi_write_reg(RFBI_ONOFF_TIME(rfbi_module), t->tim[0]); 428 rfbi_write_reg(RFBI_ONOFF_TIME(rfbi_module), t->tim[0]);
453 rfbi_write_reg(RFBI_CYCLE_TIME(rfbi_module), t->tim[1]); 429 rfbi_write_reg(RFBI_CYCLE_TIME(rfbi_module), t->tim[1]);
454 430
@@ -457,7 +433,6 @@ void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t)
457 (t->tim[2] ? 1 : 0), 4, 4); 433 (t->tim[2] ? 1 : 0), 4, 4);
458 434
459 rfbi_print_timings(); 435 rfbi_print_timings();
460 rfbi_enable_clocks(0);
461} 436}
462 437
463static int ps_to_rfbi_ticks(int time, int div) 438static int ps_to_rfbi_ticks(int time, int div)
@@ -473,59 +448,6 @@ static int ps_to_rfbi_ticks(int time, int div)
473 return ret; 448 return ret;
474} 449}
475 450
476#ifdef OMAP_RFBI_RATE_LIMIT
477unsigned long rfbi_get_max_tx_rate(void)
478{
479 unsigned long l4_rate, dss1_rate;
480 int min_l4_ticks = 0;
481 int i;
482
483 /* According to TI this can't be calculated so make the
484 * adjustments for a couple of known frequencies and warn for
485 * others.
486 */
487 static const struct {
488 unsigned long l4_clk; /* HZ */
489 unsigned long dss1_clk; /* HZ */
490 unsigned long min_l4_ticks;
491 } ftab[] = {
492 { 55, 132, 7, }, /* 7.86 MPix/s */
493 { 110, 110, 12, }, /* 9.16 MPix/s */
494 { 110, 132, 10, }, /* 11 Mpix/s */
495 { 120, 120, 10, }, /* 12 Mpix/s */
496 { 133, 133, 10, }, /* 13.3 Mpix/s */
497 };
498
499 l4_rate = rfbi.l4_khz / 1000;
500 dss1_rate = dss_clk_get_rate(DSS_CLK_FCK1) / 1000000;
501
502 for (i = 0; i < ARRAY_SIZE(ftab); i++) {
503 /* Use a window instead of an exact match, to account
504 * for different DPLL multiplier / divider pairs.
505 */
506 if (abs(ftab[i].l4_clk - l4_rate) < 3 &&
507 abs(ftab[i].dss1_clk - dss1_rate) < 3) {
508 min_l4_ticks = ftab[i].min_l4_ticks;
509 break;
510 }
511 }
512 if (i == ARRAY_SIZE(ftab)) {
513 /* Can't be sure, return anyway the maximum not
514 * rate-limited. This might cause a problem only for the
515 * tearing synchronisation.
516 */
517 DSSERR("can't determine maximum RFBI transfer rate\n");
518 return rfbi.l4_khz * 1000;
519 }
520 return rfbi.l4_khz * 1000 / min_l4_ticks;
521}
522#else
523int rfbi_get_max_tx_rate(void)
524{
525 return rfbi.l4_khz * 1000;
526}
527#endif
528
529static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div) 451static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
530{ 452{
531 *clk_period = 1000000000 / rfbi.l4_khz; 453 *clk_period = 1000000000 / rfbi.l4_khz;
@@ -645,7 +567,6 @@ int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
645 DSSDBG("setup_te: mode %d hs %d vs %d hs_inv %d vs_inv %d\n", 567 DSSDBG("setup_te: mode %d hs %d vs %d hs_inv %d vs_inv %d\n",
646 mode, hs, vs, hs_pol_inv, vs_pol_inv); 568 mode, hs, vs, hs_pol_inv, vs_pol_inv);
647 569
648 rfbi_enable_clocks(1);
649 rfbi_write_reg(RFBI_HSYNC_WIDTH, hs); 570 rfbi_write_reg(RFBI_HSYNC_WIDTH, hs);
650 rfbi_write_reg(RFBI_VSYNC_WIDTH, vs); 571 rfbi_write_reg(RFBI_VSYNC_WIDTH, vs);
651 572
@@ -658,7 +579,6 @@ int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
658 l &= ~(1 << 20); 579 l &= ~(1 << 20);
659 else 580 else
660 l |= 1 << 20; 581 l |= 1 << 20;
661 rfbi_enable_clocks(0);
662 582
663 return 0; 583 return 0;
664} 584}
@@ -673,7 +593,6 @@ int omap_rfbi_enable_te(bool enable, unsigned line)
673 if (line > (1 << 11) - 1) 593 if (line > (1 << 11) - 1)
674 return -EINVAL; 594 return -EINVAL;
675 595
676 rfbi_enable_clocks(1);
677 l = rfbi_read_reg(RFBI_CONFIG(0)); 596 l = rfbi_read_reg(RFBI_CONFIG(0));
678 l &= ~(0x3 << 2); 597 l &= ~(0x3 << 2);
679 if (enable) { 598 if (enable) {
@@ -683,50 +602,12 @@ int omap_rfbi_enable_te(bool enable, unsigned line)
683 rfbi.te_enabled = 0; 602 rfbi.te_enabled = 0;
684 rfbi_write_reg(RFBI_CONFIG(0), l); 603 rfbi_write_reg(RFBI_CONFIG(0), l);
685 rfbi_write_reg(RFBI_LINE_NUMBER, line); 604 rfbi_write_reg(RFBI_LINE_NUMBER, line);
686 rfbi_enable_clocks(0);
687 605
688 return 0; 606 return 0;
689} 607}
690EXPORT_SYMBOL(omap_rfbi_enable_te); 608EXPORT_SYMBOL(omap_rfbi_enable_te);
691 609
692#if 0 610static int rfbi_configure(int rfbi_module, int bpp, int lines)
693static void rfbi_enable_config(int enable1, int enable2)
694{
695 u32 l;
696 int cs = 0;
697
698 if (enable1)
699 cs |= 1<<0;
700 if (enable2)
701 cs |= 1<<1;
702
703 rfbi_enable_clocks(1);
704
705 l = rfbi_read_reg(RFBI_CONTROL);
706
707 l = FLD_MOD(l, cs, 3, 2);
708 l = FLD_MOD(l, 0, 1, 1);
709
710 rfbi_write_reg(RFBI_CONTROL, l);
711
712
713 l = rfbi_read_reg(RFBI_CONFIG(0));
714 l = FLD_MOD(l, 0, 3, 2); /* TRIGGERMODE: ITE */
715 /*l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */
716 /*l |= FLD_VAL(0, 8, 7); */ /* L4FORMAT, 1pix/L4 */
717
718 l = FLD_MOD(l, 0, 16, 16); /* A0POLARITY */
719 l = FLD_MOD(l, 1, 20, 20); /* TE_VSYNC_POLARITY */
720 l = FLD_MOD(l, 1, 21, 21); /* HSYNCPOLARITY */
721
722 l = FLD_MOD(l, OMAP_DSS_RFBI_PARALLELMODE_8, 1, 0);
723 rfbi_write_reg(RFBI_CONFIG(0), l);
724
725 rfbi_enable_clocks(0);
726}
727#endif
728
729int rfbi_configure(int rfbi_module, int bpp, int lines)
730{ 611{
731 u32 l; 612 u32 l;
732 int cycle1 = 0, cycle2 = 0, cycle3 = 0; 613 int cycle1 = 0, cycle2 = 0, cycle3 = 0;
@@ -822,8 +703,6 @@ int rfbi_configure(int rfbi_module, int bpp, int lines)
822 break; 703 break;
823 } 704 }
824 705
825 rfbi_enable_clocks(1);
826
827 REG_FLD_MOD(RFBI_CONTROL, 0, 3, 2); /* clear CS */ 706 REG_FLD_MOD(RFBI_CONTROL, 0, 3, 2); /* clear CS */
828 707
829 l = 0; 708 l = 0;
@@ -857,11 +736,15 @@ int rfbi_configure(int rfbi_module, int bpp, int lines)
857 DSSDBG("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n", 736 DSSDBG("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n",
858 bpp, lines, cycle1, cycle2, cycle3); 737 bpp, lines, cycle1, cycle2, cycle3);
859 738
860 rfbi_enable_clocks(0);
861
862 return 0; 739 return 0;
863} 740}
864EXPORT_SYMBOL(rfbi_configure); 741
742int omap_rfbi_configure(struct omap_dss_device *dssdev, int pixel_size,
743 int data_lines)
744{
745 return rfbi_configure(dssdev->phy.rfbi.channel, pixel_size, data_lines);
746}
747EXPORT_SYMBOL(omap_rfbi_configure);
865 748
866int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, 749int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
867 u16 *x, u16 *y, u16 *w, u16 *h) 750 u16 *x, u16 *y, u16 *w, u16 *h)
@@ -887,7 +770,7 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
887 770
888 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { 771 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
889 dss_setup_partial_planes(dssdev, x, y, w, h, true); 772 dss_setup_partial_planes(dssdev, x, y, w, h, true);
890 dispc_set_lcd_size(*w, *h); 773 dispc_set_lcd_size(dssdev->manager->id, *w, *h);
891 } 774 }
892 775
893 return 0; 776 return 0;
@@ -899,7 +782,7 @@ int omap_rfbi_update(struct omap_dss_device *dssdev,
899 void (*callback)(void *), void *data) 782 void (*callback)(void *), void *data)
900{ 783{
901 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { 784 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
902 rfbi_transfer_area(w, h, callback, data); 785 rfbi_transfer_area(dssdev, w, h, callback, data);
903 } else { 786 } else {
904 struct omap_overlay *ovl; 787 struct omap_overlay *ovl;
905 void __iomem *addr; 788 void __iomem *addr;
@@ -922,7 +805,7 @@ void rfbi_dump_regs(struct seq_file *s)
922{ 805{
923#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r)) 806#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
924 807
925 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); 808 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
926 809
927 DUMPREG(RFBI_REVISION); 810 DUMPREG(RFBI_REVISION);
928 DUMPREG(RFBI_SYSCONFIG); 811 DUMPREG(RFBI_SYSCONFIG);
@@ -953,58 +836,16 @@ void rfbi_dump_regs(struct seq_file *s)
953 DUMPREG(RFBI_VSYNC_WIDTH); 836 DUMPREG(RFBI_VSYNC_WIDTH);
954 DUMPREG(RFBI_HSYNC_WIDTH); 837 DUMPREG(RFBI_HSYNC_WIDTH);
955 838
956 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); 839 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
957#undef DUMPREG 840#undef DUMPREG
958} 841}
959 842
960int rfbi_init(void)
961{
962 u32 rev;
963 u32 l;
964
965 spin_lock_init(&rfbi.cmd_lock);
966
967 init_completion(&rfbi.cmd_done);
968 atomic_set(&rfbi.cmd_fifo_full, 0);
969 atomic_set(&rfbi.cmd_pending, 0);
970
971 rfbi.base = ioremap(RFBI_BASE, SZ_256);
972 if (!rfbi.base) {
973 DSSERR("can't ioremap RFBI\n");
974 return -ENOMEM;
975 }
976
977 rfbi_enable_clocks(1);
978
979 msleep(10);
980
981 rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000;
982
983 /* Enable autoidle and smart-idle */
984 l = rfbi_read_reg(RFBI_SYSCONFIG);
985 l |= (1 << 0) | (2 << 3);
986 rfbi_write_reg(RFBI_SYSCONFIG, l);
987
988 rev = rfbi_read_reg(RFBI_REVISION);
989 printk(KERN_INFO "OMAP RFBI rev %d.%d\n",
990 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
991
992 rfbi_enable_clocks(0);
993
994 return 0;
995}
996
997void rfbi_exit(void)
998{
999 DSSDBG("rfbi_exit\n");
1000
1001 iounmap(rfbi.base);
1002}
1003
1004int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) 843int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
1005{ 844{
1006 int r; 845 int r;
1007 846
847 rfbi_enable_clocks(1);
848
1008 r = omap_dss_start_device(dssdev); 849 r = omap_dss_start_device(dssdev);
1009 if (r) { 850 if (r) {
1010 DSSERR("failed to start device\n"); 851 DSSERR("failed to start device\n");
@@ -1018,11 +859,13 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
1018 goto err1; 859 goto err1;
1019 } 860 }
1020 861
1021 dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT); 862 dispc_set_lcd_display_type(dssdev->manager->id,
863 OMAP_DSS_LCD_DISPLAY_TFT);
1022 864
1023 dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_RFBI); 865 dispc_set_parallel_interface_mode(dssdev->manager->id,
866 OMAP_DSS_PARALLELMODE_RFBI);
1024 867
1025 dispc_set_tft_data_lines(dssdev->ctrl.pixel_size); 868 dispc_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size);
1026 869
1027 rfbi_configure(dssdev->phy.rfbi.channel, 870 rfbi_configure(dssdev->phy.rfbi.channel,
1028 dssdev->ctrl.pixel_size, 871 dssdev->ctrl.pixel_size,
@@ -1045,6 +888,8 @@ void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
1045 omap_dispc_unregister_isr(framedone_callback, NULL, 888 omap_dispc_unregister_isr(framedone_callback, NULL,
1046 DISPC_IRQ_FRAMEDONE); 889 DISPC_IRQ_FRAMEDONE);
1047 omap_dss_stop_device(dssdev); 890 omap_dss_stop_device(dssdev);
891
892 rfbi_enable_clocks(0);
1048} 893}
1049EXPORT_SYMBOL(omapdss_rfbi_display_disable); 894EXPORT_SYMBOL(omapdss_rfbi_display_disable);
1050 895
@@ -1054,3 +899,70 @@ int rfbi_init_display(struct omap_dss_device *dssdev)
1054 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; 899 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
1055 return 0; 900 return 0;
1056} 901}
902
903/* RFBI HW IP initialisation */
904static int omap_rfbihw_probe(struct platform_device *pdev)
905{
906 u32 rev;
907 u32 l;
908 struct resource *rfbi_mem;
909
910 rfbi.pdev = pdev;
911
912 sema_init(&rfbi.bus_lock, 1);
913
914 rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0);
915 if (!rfbi_mem) {
916 DSSERR("can't get IORESOURCE_MEM RFBI\n");
917 return -EINVAL;
918 }
919 rfbi.base = ioremap(rfbi_mem->start, resource_size(rfbi_mem));
920 if (!rfbi.base) {
921 DSSERR("can't ioremap RFBI\n");
922 return -ENOMEM;
923 }
924
925 rfbi_enable_clocks(1);
926
927 msleep(10);
928
929 rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000;
930
931 /* Enable autoidle and smart-idle */
932 l = rfbi_read_reg(RFBI_SYSCONFIG);
933 l |= (1 << 0) | (2 << 3);
934 rfbi_write_reg(RFBI_SYSCONFIG, l);
935
936 rev = rfbi_read_reg(RFBI_REVISION);
937 dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n",
938 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
939
940 rfbi_enable_clocks(0);
941
942 return 0;
943}
944
945static int omap_rfbihw_remove(struct platform_device *pdev)
946{
947 iounmap(rfbi.base);
948 return 0;
949}
950
951static struct platform_driver omap_rfbihw_driver = {
952 .probe = omap_rfbihw_probe,
953 .remove = omap_rfbihw_remove,
954 .driver = {
955 .name = "omapdss_rfbi",
956 .owner = THIS_MODULE,
957 },
958};
959
960int rfbi_init_platform_driver(void)
961{
962 return platform_driver_register(&omap_rfbihw_driver);
963}
964
965void rfbi_uninit_platform_driver(void)
966{
967 return platform_driver_unregister(&omap_rfbihw_driver);
968}
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index ee07a3cc22ef..0bd4b0350f80 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -25,22 +25,25 @@
25#include <linux/err.h> 25#include <linux/err.h>
26#include <linux/regulator/consumer.h> 26#include <linux/regulator/consumer.h>
27 27
28#include <plat/display.h> 28#include <video/omapdss.h>
29#include <plat/cpu.h> 29#include <plat/cpu.h>
30#include "dss.h" 30#include "dss.h"
31 31
32static struct { 32static struct {
33 bool skip_init;
34 bool update_enabled; 33 bool update_enabled;
35 struct regulator *vdds_sdi_reg; 34 struct regulator *vdds_sdi_reg;
36} sdi; 35} sdi;
37 36
38static void sdi_basic_init(void) 37static void sdi_basic_init(struct omap_dss_device *dssdev)
38
39{ 39{
40 dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS); 40 dispc_set_parallel_interface_mode(dssdev->manager->id,
41 OMAP_DSS_PARALLELMODE_BYPASS);
42
43 dispc_set_lcd_display_type(dssdev->manager->id,
44 OMAP_DSS_LCD_DISPLAY_TFT);
41 45
42 dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT); 46 dispc_set_tft_data_lines(dssdev->manager->id, 24);
43 dispc_set_tft_data_lines(24);
44 dispc_lcd_enable_signal_polarity(1); 47 dispc_lcd_enable_signal_polarity(1);
45} 48}
46 49
@@ -64,26 +67,18 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
64 if (r) 67 if (r)
65 goto err1; 68 goto err1;
66 69
67 /* In case of skip_init sdi_init has already enabled the clocks */ 70 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
68 if (!sdi.skip_init)
69 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
70 71
71 sdi_basic_init(); 72 sdi_basic_init(dssdev);
72 73
73 /* 15.5.9.1.2 */ 74 /* 15.5.9.1.2 */
74 dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF; 75 dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF;
75 76
76 dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi, 77 dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
77 dssdev->panel.acb); 78 dssdev->panel.acbi, dssdev->panel.acb);
78
79 if (!sdi.skip_init) {
80 r = dss_calc_clock_div(1, t->pixel_clock * 1000,
81 &dss_cinfo, &dispc_cinfo);
82 } else {
83 r = dss_get_clock_div(&dss_cinfo);
84 r = dispc_get_clock_div(&dispc_cinfo);
85 }
86 79
80 r = dss_calc_clock_div(1, t->pixel_clock * 1000,
81 &dss_cinfo, &dispc_cinfo);
87 if (r) 82 if (r)
88 goto err2; 83 goto err2;
89 84
@@ -102,31 +97,27 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
102 } 97 }
103 98
104 99
105 dispc_set_lcd_timings(t); 100 dispc_set_lcd_timings(dssdev->manager->id, t);
106 101
107 r = dss_set_clock_div(&dss_cinfo); 102 r = dss_set_clock_div(&dss_cinfo);
108 if (r) 103 if (r)
109 goto err2; 104 goto err2;
110 105
111 r = dispc_set_clock_div(&dispc_cinfo); 106 r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
112 if (r) 107 if (r)
113 goto err2; 108 goto err2;
114 109
115 if (!sdi.skip_init) { 110 dss_sdi_init(dssdev->phy.sdi.datapairs);
116 dss_sdi_init(dssdev->phy.sdi.datapairs); 111 r = dss_sdi_enable();
117 r = dss_sdi_enable(); 112 if (r)
118 if (r) 113 goto err1;
119 goto err1; 114 mdelay(2);
120 mdelay(2);
121 }
122 115
123 dssdev->manager->enable(dssdev->manager); 116 dssdev->manager->enable(dssdev->manager);
124 117
125 sdi.skip_init = 0;
126
127 return 0; 118 return 0;
128err2: 119err2:
129 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); 120 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
130 regulator_disable(sdi.vdds_sdi_reg); 121 regulator_disable(sdi.vdds_sdi_reg);
131err1: 122err1:
132 omap_dss_stop_device(dssdev); 123 omap_dss_stop_device(dssdev);
@@ -141,7 +132,7 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
141 132
142 dss_sdi_disable(); 133 dss_sdi_disable();
143 134
144 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); 135 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
145 136
146 regulator_disable(sdi.vdds_sdi_reg); 137 regulator_disable(sdi.vdds_sdi_reg);
147 138
@@ -153,25 +144,24 @@ int sdi_init_display(struct omap_dss_device *dssdev)
153{ 144{
154 DSSDBG("SDI init\n"); 145 DSSDBG("SDI init\n");
155 146
147 if (sdi.vdds_sdi_reg == NULL) {
148 struct regulator *vdds_sdi;
149
150 vdds_sdi = dss_get_vdds_sdi();
151
152 if (IS_ERR(vdds_sdi)) {
153 DSSERR("can't get VDDS_SDI regulator\n");
154 return PTR_ERR(vdds_sdi);
155 }
156
157 sdi.vdds_sdi_reg = vdds_sdi;
158 }
159
156 return 0; 160 return 0;
157} 161}
158 162
159int sdi_init(bool skip_init) 163int sdi_init(void)
160{ 164{
161 /* we store this for first display enable, then clear it */
162 sdi.skip_init = skip_init;
163
164 sdi.vdds_sdi_reg = dss_get_vdds_sdi();
165 if (IS_ERR(sdi.vdds_sdi_reg)) {
166 DSSERR("can't get VDDS_SDI regulator\n");
167 return PTR_ERR(sdi.vdds_sdi_reg);
168 }
169 /*
170 * Enable clocks already here, otherwise there would be a toggle
171 * of them until sdi_display_enable is called.
172 */
173 if (skip_init)
174 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
175 return 0; 165 return 0;
176} 166}
177 167
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index eff35050e28a..980f919ed987 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -34,13 +34,11 @@
34#include <linux/platform_device.h> 34#include <linux/platform_device.h>
35#include <linux/regulator/consumer.h> 35#include <linux/regulator/consumer.h>
36 36
37#include <plat/display.h> 37#include <video/omapdss.h>
38#include <plat/cpu.h> 38#include <plat/cpu.h>
39 39
40#include "dss.h" 40#include "dss.h"
41 41
42#define VENC_BASE 0x48050C00
43
44/* Venc registers */ 42/* Venc registers */
45#define VENC_REV_ID 0x00 43#define VENC_REV_ID 0x00
46#define VENC_STATUS 0x04 44#define VENC_STATUS 0x04
@@ -289,6 +287,7 @@ const struct omap_video_timings omap_dss_ntsc_timings = {
289EXPORT_SYMBOL(omap_dss_ntsc_timings); 287EXPORT_SYMBOL(omap_dss_ntsc_timings);
290 288
291static struct { 289static struct {
290 struct platform_device *pdev;
292 void __iomem *base; 291 void __iomem *base;
293 struct mutex venc_lock; 292 struct mutex venc_lock;
294 u32 wss_data; 293 u32 wss_data;
@@ -374,18 +373,21 @@ static void venc_reset(void)
374 } 373 }
375 } 374 }
376 375
376#ifdef CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET
377 /* the magical sleep that makes things work */ 377 /* the magical sleep that makes things work */
378 /* XXX more info? What bug this circumvents? */
378 msleep(20); 379 msleep(20);
380#endif
379} 381}
380 382
381static void venc_enable_clocks(int enable) 383static void venc_enable_clocks(int enable)
382{ 384{
383 if (enable) 385 if (enable)
384 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M | 386 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK |
385 DSS_CLK_96M); 387 DSS_CLK_VIDFCK);
386 else 388 else
387 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M | 389 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK |
388 DSS_CLK_96M); 390 DSS_CLK_VIDFCK);
389} 391}
390 392
391static const struct venc_config *venc_timings_to_config( 393static const struct venc_config *venc_timings_to_config(
@@ -474,6 +476,12 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
474 476
475 mutex_lock(&venc.venc_lock); 477 mutex_lock(&venc.venc_lock);
476 478
479 r = omap_dss_start_device(dssdev);
480 if (r) {
481 DSSERR("failed to start device\n");
482 goto err0;
483 }
484
477 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { 485 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
478 r = -EINVAL; 486 r = -EINVAL;
479 goto err1; 487 goto err1;
@@ -485,10 +493,11 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
485 493
486 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 494 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
487 495
488 /* wait couple of vsyncs until enabling the LCD */ 496 mutex_unlock(&venc.venc_lock);
489 msleep(50); 497 return 0;
490
491err1: 498err1:
499 omap_dss_stop_device(dssdev);
500err0:
492 mutex_unlock(&venc.venc_lock); 501 mutex_unlock(&venc.venc_lock);
493 502
494 return r; 503 return r;
@@ -511,10 +520,9 @@ static void venc_panel_disable(struct omap_dss_device *dssdev)
511 520
512 venc_power_off(dssdev); 521 venc_power_off(dssdev);
513 522
514 /* wait at least 5 vsyncs after disabling the LCD */
515 msleep(100);
516
517 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 523 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
524
525 omap_dss_stop_device(dssdev);
518end: 526end:
519 mutex_unlock(&venc.venc_lock); 527 mutex_unlock(&venc.venc_lock);
520} 528}
@@ -641,50 +649,23 @@ static struct omap_dss_driver venc_driver = {
641}; 649};
642/* driver end */ 650/* driver end */
643 651
644 652int venc_init_display(struct omap_dss_device *dssdev)
645
646int venc_init(struct platform_device *pdev)
647{ 653{
648 u8 rev_id; 654 DSSDBG("init_display\n");
649 655
650 mutex_init(&venc.venc_lock); 656 if (venc.vdda_dac_reg == NULL) {
657 struct regulator *vdda_dac;
651 658
652 venc.wss_data = 0; 659 vdda_dac = regulator_get(&venc.pdev->dev, "vdda_dac");
653 660
654 venc.base = ioremap(VENC_BASE, SZ_1K); 661 if (IS_ERR(vdda_dac)) {
655 if (!venc.base) { 662 DSSERR("can't get VDDA_DAC regulator\n");
656 DSSERR("can't ioremap VENC\n"); 663 return PTR_ERR(vdda_dac);
657 return -ENOMEM; 664 }
658 }
659 665
660 venc.vdda_dac_reg = dss_get_vdda_dac(); 666 venc.vdda_dac_reg = vdda_dac;
661 if (IS_ERR(venc.vdda_dac_reg)) {
662 iounmap(venc.base);
663 DSSERR("can't get VDDA_DAC regulator\n");
664 return PTR_ERR(venc.vdda_dac_reg);
665 } 667 }
666 668
667 venc_enable_clocks(1);
668
669 rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
670 printk(KERN_INFO "OMAP VENC rev %d\n", rev_id);
671
672 venc_enable_clocks(0);
673
674 return omap_dss_register_driver(&venc_driver);
675}
676
677void venc_exit(void)
678{
679 omap_dss_unregister_driver(&venc_driver);
680
681 iounmap(venc.base);
682}
683
684int venc_init_display(struct omap_dss_device *dssdev)
685{
686 DSSDBG("init_display\n");
687
688 return 0; 669 return 0;
689} 670}
690 671
@@ -740,3 +721,73 @@ void venc_dump_regs(struct seq_file *s)
740 721
741#undef DUMPREG 722#undef DUMPREG
742} 723}
724
725/* VENC HW IP initialisation */
726static int omap_venchw_probe(struct platform_device *pdev)
727{
728 u8 rev_id;
729 struct resource *venc_mem;
730
731 venc.pdev = pdev;
732
733 mutex_init(&venc.venc_lock);
734
735 venc.wss_data = 0;
736
737 venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0);
738 if (!venc_mem) {
739 DSSERR("can't get IORESOURCE_MEM VENC\n");
740 return -EINVAL;
741 }
742 venc.base = ioremap(venc_mem->start, resource_size(venc_mem));
743 if (!venc.base) {
744 DSSERR("can't ioremap VENC\n");
745 return -ENOMEM;
746 }
747
748 venc_enable_clocks(1);
749
750 rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
751 dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id);
752
753 venc_enable_clocks(0);
754
755 return omap_dss_register_driver(&venc_driver);
756}
757
758static int omap_venchw_remove(struct platform_device *pdev)
759{
760 if (venc.vdda_dac_reg != NULL) {
761 regulator_put(venc.vdda_dac_reg);
762 venc.vdda_dac_reg = NULL;
763 }
764 omap_dss_unregister_driver(&venc_driver);
765
766 iounmap(venc.base);
767 return 0;
768}
769
770static struct platform_driver omap_venchw_driver = {
771 .probe = omap_venchw_probe,
772 .remove = omap_venchw_remove,
773 .driver = {
774 .name = "omapdss_venc",
775 .owner = THIS_MODULE,
776 },
777};
778
779int venc_init_platform_driver(void)
780{
781 if (cpu_is_omap44xx())
782 return 0;
783
784 return platform_driver_register(&omap_venchw_driver);
785}
786
787void venc_uninit_platform_driver(void)
788{
789 if (cpu_is_omap44xx())
790 return;
791
792 return platform_driver_unregister(&omap_venchw_driver);
793}
diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig
index 43496d6c377f..aa33386c81ff 100644
--- a/drivers/video/omap2/omapfb/Kconfig
+++ b/drivers/video/omap2/omapfb/Kconfig
@@ -1,17 +1,17 @@
1menuconfig FB_OMAP2 1menuconfig FB_OMAP2
2 tristate "OMAP2/3 frame buffer support (EXPERIMENTAL)" 2 tristate "OMAP2+ frame buffer support (EXPERIMENTAL)"
3 depends on FB && OMAP2_DSS 3 depends on FB && OMAP2_DSS
4 4
5 select OMAP2_VRAM 5 select OMAP2_VRAM
6 select OMAP2_VRFB 6 select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3
7 select FB_CFB_FILLRECT 7 select FB_CFB_FILLRECT
8 select FB_CFB_COPYAREA 8 select FB_CFB_COPYAREA
9 select FB_CFB_IMAGEBLIT 9 select FB_CFB_IMAGEBLIT
10 help 10 help
11 Frame buffer driver for OMAP2/3 based boards. 11 Frame buffer driver for OMAP2+ based boards.
12 12
13config FB_OMAP2_DEBUG_SUPPORT 13config FB_OMAP2_DEBUG_SUPPORT
14 bool "Debug support for OMAP2/3 FB" 14 bool "Debug support for OMAP2+ FB"
15 default y 15 default y
16 depends on FB_OMAP2 16 depends on FB_OMAP2
17 help 17 help
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index 6f435450987e..cff450392b79 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -28,7 +28,7 @@
28#include <linux/omapfb.h> 28#include <linux/omapfb.h>
29#include <linux/vmalloc.h> 29#include <linux/vmalloc.h>
30 30
31#include <plat/display.h> 31#include <video/omapdss.h>
32#include <plat/vrfb.h> 32#include <plat/vrfb.h>
33#include <plat/vram.h> 33#include <plat/vram.h>
34 34
@@ -895,8 +895,16 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
895 895
896 p.display_info.xres = xres; 896 p.display_info.xres = xres;
897 p.display_info.yres = yres; 897 p.display_info.yres = yres;
898 p.display_info.width = 0; 898
899 p.display_info.height = 0; 899 if (display->driver->get_dimensions) {
900 u32 w, h;
901 display->driver->get_dimensions(display, &w, &h);
902 p.display_info.width = w;
903 p.display_info.height = h;
904 } else {
905 p.display_info.width = 0;
906 p.display_info.height = 0;
907 }
900 908
901 if (copy_to_user((void __user *)arg, &p.display_info, 909 if (copy_to_user((void __user *)arg, &p.display_info,
902 sizeof(p.display_info))) 910 sizeof(p.display_info)))
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 04034d410d6d..505bc12a3031 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -30,7 +30,7 @@
30#include <linux/platform_device.h> 30#include <linux/platform_device.h>
31#include <linux/omapfb.h> 31#include <linux/omapfb.h>
32 32
33#include <plat/display.h> 33#include <video/omapdss.h>
34#include <plat/vram.h> 34#include <plat/vram.h>
35#include <plat/vrfb.h> 35#include <plat/vrfb.h>
36 36
@@ -702,8 +702,16 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
702 var->xres, var->yres, 702 var->xres, var->yres,
703 var->xres_virtual, var->yres_virtual); 703 var->xres_virtual, var->yres_virtual);
704 704
705 var->height = -1; 705 if (display && display->driver->get_dimensions) {
706 var->width = -1; 706 u32 w, h;
707 display->driver->get_dimensions(display, &w, &h);
708 var->width = DIV_ROUND_CLOSEST(w, 1000);
709 var->height = DIV_ROUND_CLOSEST(h, 1000);
710 } else {
711 var->height = -1;
712 var->width = -1;
713 }
714
707 var->grayscale = 0; 715 var->grayscale = 0;
708 716
709 if (display && display->driver->get_timings) { 717 if (display && display->driver->get_timings) {
@@ -714,10 +722,10 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
714 var->pixclock = timings.pixel_clock != 0 ? 722 var->pixclock = timings.pixel_clock != 0 ?
715 KHZ2PICOS(timings.pixel_clock) : 723 KHZ2PICOS(timings.pixel_clock) :
716 0; 724 0;
717 var->left_margin = timings.hfp; 725 var->left_margin = timings.hbp;
718 var->right_margin = timings.hbp; 726 var->right_margin = timings.hfp;
719 var->upper_margin = timings.vfp; 727 var->upper_margin = timings.vbp;
720 var->lower_margin = timings.vbp; 728 var->lower_margin = timings.vfp;
721 var->hsync_len = timings.hsw; 729 var->hsync_len = timings.hsw;
722 var->vsync_len = timings.vsw; 730 var->vsync_len = timings.vsw;
723 } else { 731 } else {
@@ -749,35 +757,6 @@ static int omapfb_open(struct fb_info *fbi, int user)
749 757
750static int omapfb_release(struct fb_info *fbi, int user) 758static int omapfb_release(struct fb_info *fbi, int user)
751{ 759{
752#if 0
753 struct omapfb_info *ofbi = FB2OFB(fbi);
754 struct omapfb2_device *fbdev = ofbi->fbdev;
755 struct omap_dss_device *display = fb2display(fbi);
756
757 DBG("Closing fb with plane index %d\n", ofbi->id);
758
759 omapfb_lock(fbdev);
760
761 if (display && display->get_update_mode && display->update) {
762 /* XXX this update should be removed, I think. But it's
763 * good for debugging */
764 if (display->get_update_mode(display) ==
765 OMAP_DSS_UPDATE_MANUAL) {
766 u16 w, h;
767
768 if (display->sync)
769 display->sync(display);
770
771 display->get_resolution(display, &w, &h);
772 display->update(display, 0, 0, w, h);
773 }
774 }
775
776 if (display && display->sync)
777 display->sync(display);
778
779 omapfb_unlock(fbdev);
780#endif
781 return 0; 760 return 0;
782} 761}
783 762
@@ -1263,7 +1242,6 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
1263 struct omapfb_info *ofbi = FB2OFB(fbi); 1242 struct omapfb_info *ofbi = FB2OFB(fbi);
1264 struct omapfb2_device *fbdev = ofbi->fbdev; 1243 struct omapfb2_device *fbdev = ofbi->fbdev;
1265 struct omap_dss_device *display = fb2display(fbi); 1244 struct omap_dss_device *display = fb2display(fbi);
1266 int do_update = 0;
1267 int r = 0; 1245 int r = 0;
1268 1246
1269 if (!display) 1247 if (!display)
@@ -1279,11 +1257,6 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
1279 if (display->driver->resume) 1257 if (display->driver->resume)
1280 r = display->driver->resume(display); 1258 r = display->driver->resume(display);
1281 1259
1282 if (r == 0 && display->driver->get_update_mode &&
1283 display->driver->get_update_mode(display) ==
1284 OMAP_DSS_UPDATE_MANUAL)
1285 do_update = 1;
1286
1287 break; 1260 break;
1288 1261
1289 case FB_BLANK_NORMAL: 1262 case FB_BLANK_NORMAL:
@@ -1307,13 +1280,6 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
1307exit: 1280exit:
1308 omapfb_unlock(fbdev); 1281 omapfb_unlock(fbdev);
1309 1282
1310 if (r == 0 && do_update && display->driver->update) {
1311 u16 w, h;
1312 display->driver->get_resolution(display, &w, &h);
1313
1314 r = display->driver->update(display, 0, 0, w, h);
1315 }
1316
1317 return r; 1283 return r;
1318} 1284}
1319 1285
@@ -2030,9 +1996,9 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
2030static int omapfb_mode_to_timings(const char *mode_str, 1996static int omapfb_mode_to_timings(const char *mode_str,
2031 struct omap_video_timings *timings, u8 *bpp) 1997 struct omap_video_timings *timings, u8 *bpp)
2032{ 1998{
2033 struct fb_info fbi; 1999 struct fb_info *fbi;
2034 struct fb_var_screeninfo var; 2000 struct fb_var_screeninfo *var;
2035 struct fb_ops fbops; 2001 struct fb_ops *fbops;
2036 int r; 2002 int r;
2037 2003
2038#ifdef CONFIG_OMAP2_DSS_VENC 2004#ifdef CONFIG_OMAP2_DSS_VENC
@@ -2050,39 +2016,66 @@ static int omapfb_mode_to_timings(const char *mode_str,
2050 /* this is quite a hack, but I wanted to use the modedb and for 2016 /* this is quite a hack, but I wanted to use the modedb and for
2051 * that we need fb_info and var, so we create dummy ones */ 2017 * that we need fb_info and var, so we create dummy ones */
2052 2018
2053 memset(&fbi, 0, sizeof(fbi)); 2019 *bpp = 0;
2054 memset(&var, 0, sizeof(var)); 2020 fbi = NULL;
2055 memset(&fbops, 0, sizeof(fbops)); 2021 var = NULL;
2056 fbi.fbops = &fbops; 2022 fbops = NULL;
2057
2058 r = fb_find_mode(&var, &fbi, mode_str, NULL, 0, NULL, 24);
2059
2060 if (r != 0) {
2061 timings->pixel_clock = PICOS2KHZ(var.pixclock);
2062 timings->hfp = var.left_margin;
2063 timings->hbp = var.right_margin;
2064 timings->vfp = var.upper_margin;
2065 timings->vbp = var.lower_margin;
2066 timings->hsw = var.hsync_len;
2067 timings->vsw = var.vsync_len;
2068 timings->x_res = var.xres;
2069 timings->y_res = var.yres;
2070
2071 switch (var.bits_per_pixel) {
2072 case 16:
2073 *bpp = 16;
2074 break;
2075 case 24:
2076 case 32:
2077 default:
2078 *bpp = 24;
2079 break;
2080 }
2081 2023
2082 return 0; 2024 fbi = kzalloc(sizeof(*fbi), GFP_KERNEL);
2083 } else { 2025 if (fbi == NULL) {
2084 return -EINVAL; 2026 r = -ENOMEM;
2027 goto err;
2028 }
2029
2030 var = kzalloc(sizeof(*var), GFP_KERNEL);
2031 if (var == NULL) {
2032 r = -ENOMEM;
2033 goto err;
2034 }
2035
2036 fbops = kzalloc(sizeof(*fbops), GFP_KERNEL);
2037 if (fbops == NULL) {
2038 r = -ENOMEM;
2039 goto err;
2040 }
2041
2042 fbi->fbops = fbops;
2043
2044 r = fb_find_mode(var, fbi, mode_str, NULL, 0, NULL, 24);
2045 if (r == 0) {
2046 r = -EINVAL;
2047 goto err;
2048 }
2049
2050 timings->pixel_clock = PICOS2KHZ(var->pixclock);
2051 timings->hbp = var->left_margin;
2052 timings->hfp = var->right_margin;
2053 timings->vbp = var->upper_margin;
2054 timings->vfp = var->lower_margin;
2055 timings->hsw = var->hsync_len;
2056 timings->vsw = var->vsync_len;
2057 timings->x_res = var->xres;
2058 timings->y_res = var->yres;
2059
2060 switch (var->bits_per_pixel) {
2061 case 16:
2062 *bpp = 16;
2063 break;
2064 case 24:
2065 case 32:
2066 default:
2067 *bpp = 24;
2068 break;
2085 } 2069 }
2070
2071 r = 0;
2072
2073err:
2074 kfree(fbi);
2075 kfree(var);
2076 kfree(fbops);
2077
2078 return r;
2086} 2079}
2087 2080
2088static int omapfb_set_def_mode(struct omapfb2_device *fbdev, 2081static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
@@ -2090,7 +2083,7 @@ static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
2090{ 2083{
2091 int r; 2084 int r;
2092 u8 bpp; 2085 u8 bpp;
2093 struct omap_video_timings timings; 2086 struct omap_video_timings timings, temp_timings;
2094 2087
2095 r = omapfb_mode_to_timings(mode_str, &timings, &bpp); 2088 r = omapfb_mode_to_timings(mode_str, &timings, &bpp);
2096 if (r) 2089 if (r)
@@ -2100,14 +2093,23 @@ static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
2100 fbdev->bpp_overrides[fbdev->num_bpp_overrides].bpp = bpp; 2093 fbdev->bpp_overrides[fbdev->num_bpp_overrides].bpp = bpp;
2101 ++fbdev->num_bpp_overrides; 2094 ++fbdev->num_bpp_overrides;
2102 2095
2103 if (!display->driver->check_timings || !display->driver->set_timings) 2096 if (display->driver->check_timings) {
2104 return -EINVAL; 2097 r = display->driver->check_timings(display, &timings);
2098 if (r)
2099 return r;
2100 } else {
2101 /* If check_timings is not present compare xres and yres */
2102 if (display->driver->get_timings) {
2103 display->driver->get_timings(display, &temp_timings);
2105 2104
2106 r = display->driver->check_timings(display, &timings); 2105 if (temp_timings.x_res != timings.x_res ||
2107 if (r) 2106 temp_timings.y_res != timings.y_res)
2108 return r; 2107 return -EINVAL;
2108 }
2109 }
2109 2110
2110 display->driver->set_timings(display, &timings); 2111 if (display->driver->set_timings)
2112 display->driver->set_timings(display, &timings);
2111 2113
2112 return 0; 2114 return 0;
2113} 2115}
@@ -2132,8 +2134,9 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
2132 char *str, *options, *this_opt; 2134 char *str, *options, *this_opt;
2133 int r = 0; 2135 int r = 0;
2134 2136
2135 str = kmalloc(strlen(def_mode) + 1, GFP_KERNEL); 2137 str = kstrdup(def_mode, GFP_KERNEL);
2136 strcpy(str, def_mode); 2138 if (!str)
2139 return -ENOMEM;
2137 options = str; 2140 options = str;
2138 2141
2139 while (!r && (this_opt = strsep(&options, ",")) != NULL) { 2142 while (!r && (this_opt = strsep(&options, ",")) != NULL) {
@@ -2175,6 +2178,61 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
2175 return r; 2178 return r;
2176} 2179}
2177 2180
2181static int omapfb_init_display(struct omapfb2_device *fbdev,
2182 struct omap_dss_device *dssdev)
2183{
2184 struct omap_dss_driver *dssdrv = dssdev->driver;
2185 int r;
2186
2187 r = dssdrv->enable(dssdev);
2188 if (r) {
2189 dev_warn(fbdev->dev, "Failed to enable display '%s'\n",
2190 dssdev->name);
2191 return r;
2192 }
2193
2194 if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
2195 u16 w, h;
2196 if (dssdrv->enable_te) {
2197 r = dssdrv->enable_te(dssdev, 1);
2198 if (r) {
2199 dev_err(fbdev->dev, "Failed to set TE\n");
2200 return r;
2201 }
2202 }
2203
2204 if (dssdrv->set_update_mode) {
2205 r = dssdrv->set_update_mode(dssdev,
2206 OMAP_DSS_UPDATE_MANUAL);
2207 if (r) {
2208 dev_err(fbdev->dev,
2209 "Failed to set update mode\n");
2210 return r;
2211 }
2212 }
2213
2214 dssdrv->get_resolution(dssdev, &w, &h);
2215 r = dssdrv->update(dssdev, 0, 0, w, h);
2216 if (r) {
2217 dev_err(fbdev->dev,
2218 "Failed to update display\n");
2219 return r;
2220 }
2221 } else {
2222 if (dssdrv->set_update_mode) {
2223 r = dssdrv->set_update_mode(dssdev,
2224 OMAP_DSS_UPDATE_AUTO);
2225 if (r) {
2226 dev_err(fbdev->dev,
2227 "Failed to set update mode\n");
2228 return r;
2229 }
2230 }
2231 }
2232
2233 return 0;
2234}
2235
2178static int omapfb_probe(struct platform_device *pdev) 2236static int omapfb_probe(struct platform_device *pdev)
2179{ 2237{
2180 struct omapfb2_device *fbdev = NULL; 2238 struct omapfb2_device *fbdev = NULL;
@@ -2198,6 +2256,16 @@ static int omapfb_probe(struct platform_device *pdev)
2198 goto err0; 2256 goto err0;
2199 } 2257 }
2200 2258
2259 /* TODO : Replace cpu check with omap_has_vrfb once HAS_FEATURE
2260 * available for OMAP2 and OMAP3
2261 */
2262 if (def_vrfb && !cpu_is_omap24xx() && !cpu_is_omap34xx()) {
2263 def_vrfb = 0;
2264 dev_warn(&pdev->dev, "VRFB is not supported on this hardware, "
2265 "ignoring the module parameter vrfb=y\n");
2266 }
2267
2268
2201 mutex_init(&fbdev->mtx); 2269 mutex_init(&fbdev->mtx);
2202 2270
2203 fbdev->dev = &pdev->dev; 2271 fbdev->dev = &pdev->dev;
@@ -2264,30 +2332,13 @@ static int omapfb_probe(struct platform_device *pdev)
2264 } 2332 }
2265 2333
2266 if (def_display) { 2334 if (def_display) {
2267 struct omap_dss_driver *dssdrv = def_display->driver; 2335 r = omapfb_init_display(fbdev, def_display);
2268
2269 r = def_display->driver->enable(def_display);
2270 if (r) { 2336 if (r) {
2271 dev_warn(fbdev->dev, "Failed to enable display '%s'\n", 2337 dev_err(fbdev->dev,
2272 def_display->name); 2338 "failed to initialize default "
2339 "display\n");
2273 goto cleanup; 2340 goto cleanup;
2274 } 2341 }
2275
2276 if (def_display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
2277 u16 w, h;
2278 if (dssdrv->enable_te)
2279 dssdrv->enable_te(def_display, 1);
2280 if (dssdrv->set_update_mode)
2281 dssdrv->set_update_mode(def_display,
2282 OMAP_DSS_UPDATE_MANUAL);
2283
2284 dssdrv->get_resolution(def_display, &w, &h);
2285 def_display->driver->update(def_display, 0, 0, w, h);
2286 } else {
2287 if (dssdrv->set_update_mode)
2288 dssdrv->set_update_mode(def_display,
2289 OMAP_DSS_UPDATE_AUTO);
2290 }
2291 } 2342 }
2292 2343
2293 DBG("create sysfs for fbs\n"); 2344 DBG("create sysfs for fbs\n");
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
index 6f9c72cd6bb0..2f5e817b2a9a 100644
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -29,7 +29,7 @@
29#include <linux/mm.h> 29#include <linux/mm.h>
30#include <linux/omapfb.h> 30#include <linux/omapfb.h>
31 31
32#include <plat/display.h> 32#include <video/omapdss.h>
33#include <plat/vrfb.h> 33#include <plat/vrfb.h>
34 34
35#include "omapfb.h" 35#include "omapfb.h"
@@ -50,10 +50,12 @@ static ssize_t store_rotate_type(struct device *dev,
50 struct fb_info *fbi = dev_get_drvdata(dev); 50 struct fb_info *fbi = dev_get_drvdata(dev);
51 struct omapfb_info *ofbi = FB2OFB(fbi); 51 struct omapfb_info *ofbi = FB2OFB(fbi);
52 struct omapfb2_mem_region *rg; 52 struct omapfb2_mem_region *rg;
53 enum omap_dss_rotation_type rot_type; 53 int rot_type;
54 int r; 54 int r;
55 55
56 rot_type = simple_strtoul(buf, NULL, 0); 56 r = kstrtoint(buf, 0, &rot_type);
57 if (r)
58 return r;
57 59
58 if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB) 60 if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB)
59 return -EINVAL; 61 return -EINVAL;
@@ -102,14 +104,15 @@ static ssize_t store_mirror(struct device *dev,
102{ 104{
103 struct fb_info *fbi = dev_get_drvdata(dev); 105 struct fb_info *fbi = dev_get_drvdata(dev);
104 struct omapfb_info *ofbi = FB2OFB(fbi); 106 struct omapfb_info *ofbi = FB2OFB(fbi);
105 unsigned long mirror; 107 int mirror;
106 int r; 108 int r;
107 struct fb_var_screeninfo new_var; 109 struct fb_var_screeninfo new_var;
108 110
109 mirror = simple_strtoul(buf, NULL, 0); 111 r = kstrtoint(buf, 0, &mirror);
112 if (r)
113 return r;
110 114
111 if (mirror != 0 && mirror != 1) 115 mirror = !!mirror;
112 return -EINVAL;
113 116
114 if (!lock_fb_info(fbi)) 117 if (!lock_fb_info(fbi))
115 return -ENODEV; 118 return -ENODEV;
@@ -445,7 +448,11 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
445 int r; 448 int r;
446 int i; 449 int i;
447 450
448 size = PAGE_ALIGN(simple_strtoul(buf, NULL, 0)); 451 r = kstrtoul(buf, 0, &size);
452 if (r)
453 return r;
454
455 size = PAGE_ALIGN(size);
449 456
450 if (!lock_fb_info(fbi)) 457 if (!lock_fb_info(fbi))
451 return -ENODEV; 458 return -ENODEV;
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
index 1305fc9880ba..aa1b1d974276 100644
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ b/drivers/video/omap2/omapfb/omapfb.h
@@ -29,13 +29,15 @@
29 29
30#include <linux/rwsem.h> 30#include <linux/rwsem.h>
31 31
32#include <plat/display.h> 32#include <video/omapdss.h>
33 33
34#ifdef DEBUG 34#ifdef DEBUG
35extern unsigned int omapfb_debug; 35extern unsigned int omapfb_debug;
36#define DBG(format, ...) \ 36#define DBG(format, ...) \
37 if (omapfb_debug) \ 37 do { \
38 printk(KERN_DEBUG "OMAPFB: " format, ## __VA_ARGS__) 38 if (omapfb_debug) \
39 printk(KERN_DEBUG "OMAPFB: " format, ## __VA_ARGS__); \
40 } while (0)
39#else 41#else
40#define DBG(format, ...) 42#define DBG(format, ...)
41#endif 43#endif
diff --git a/drivers/video/omap2/vram.c b/drivers/video/omap2/vram.c
index f6fdc2085f3e..9441e2eb3dee 100644
--- a/drivers/video/omap2/vram.c
+++ b/drivers/video/omap2/vram.c
@@ -551,16 +551,18 @@ void __init omap_vram_reserve_sdram_memblock(void)
551 if (!size) 551 if (!size)
552 return; 552 return;
553 553
554 size = PAGE_ALIGN(size); 554 size = ALIGN(size, SZ_2M);
555 555
556 if (paddr) { 556 if (paddr) {
557 struct memblock_property res; 557 if (paddr & ~PAGE_MASK) {
558 pr_err("VRAM start address 0x%08x not page aligned\n",
559 paddr);
560 return;
561 }
558 562
559 res.base = paddr; 563 if (!memblock_is_region_memory(paddr, size)) {
560 res.size = size; 564 pr_err("Illegal SDRAM region 0x%08x..0x%08x for VRAM\n",
561 if ((paddr & ~PAGE_MASK) || memblock_find(&res) || 565 paddr, paddr + size - 1);
562 res.base != paddr || res.size != size) {
563 pr_err("Illegal SDRAM region for VRAM\n");
564 return; 566 return;
565 } 567 }
566 568
@@ -574,9 +576,12 @@ void __init omap_vram_reserve_sdram_memblock(void)
574 return; 576 return;
575 } 577 }
576 } else { 578 } else {
577 paddr = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_REAL_LIMIT); 579 paddr = memblock_alloc(size, SZ_2M);
578 } 580 }
579 581
582 memblock_free(paddr, size);
583 memblock_remove(paddr, size);
584
580 omap_vram_add_region(paddr, size); 585 omap_vram_add_region(paddr, size);
581 586
582 pr_info("Reserving %u bytes SDRAM for VRAM\n", size); 587 pr_info("Reserving %u bytes SDRAM for VRAM\n", size);
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c
index b6c3fc2db632..d57cc58c5168 100644
--- a/drivers/video/p9100.c
+++ b/drivers/video/p9100.c
@@ -249,7 +249,7 @@ static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_no
249 info->fix.accel = FB_ACCEL_SUN_CGTHREE; 249 info->fix.accel = FB_ACCEL_SUN_CGTHREE;
250} 250}
251 251
252static int __devinit p9100_probe(struct platform_device *op, const struct of_device_id *match) 252static int __devinit p9100_probe(struct platform_device *op)
253{ 253{
254 struct device_node *dp = op->dev.of_node; 254 struct device_node *dp = op->dev.of_node;
255 struct fb_info *info; 255 struct fb_info *info;
@@ -352,7 +352,7 @@ static const struct of_device_id p9100_match[] = {
352}; 352};
353MODULE_DEVICE_TABLE(of, p9100_match); 353MODULE_DEVICE_TABLE(of, p9100_match);
354 354
355static struct of_platform_driver p9100_driver = { 355static struct platform_driver p9100_driver = {
356 .driver = { 356 .driver = {
357 .name = "p9100", 357 .name = "p9100",
358 .owner = THIS_MODULE, 358 .owner = THIS_MODULE,
@@ -367,12 +367,12 @@ static int __init p9100_init(void)
367 if (fb_get_options("p9100fb", NULL)) 367 if (fb_get_options("p9100fb", NULL))
368 return -ENODEV; 368 return -ENODEV;
369 369
370 return of_register_platform_driver(&p9100_driver); 370 return platform_driver_register(&p9100_driver);
371} 371}
372 372
373static void __exit p9100_exit(void) 373static void __exit p9100_exit(void)
374{ 374{
375 of_unregister_platform_driver(&p9100_driver); 375 platform_driver_unregister(&p9100_driver);
376} 376}
377 377
378module_init(p9100_init); 378module_init(p9100_init);
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index a50e1977b316..ef532d9d3c99 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -533,8 +533,7 @@ static int __init platinumfb_setup(char *options)
533#define invalidate_cache(addr) 533#define invalidate_cache(addr)
534#endif 534#endif
535 535
536static int __devinit platinumfb_probe(struct platform_device* odev, 536static int __devinit platinumfb_probe(struct platform_device* odev)
537 const struct of_device_id *match)
538{ 537{
539 struct device_node *dp = odev->dev.of_node; 538 struct device_node *dp = odev->dev.of_node;
540 struct fb_info *info; 539 struct fb_info *info;
@@ -677,7 +676,7 @@ static struct of_device_id platinumfb_match[] =
677 {}, 676 {},
678}; 677};
679 678
680static struct of_platform_driver platinum_driver = 679static struct platform_driver platinum_driver =
681{ 680{
682 .driver = { 681 .driver = {
683 .name = "platinumfb", 682 .name = "platinumfb",
@@ -697,14 +696,14 @@ static int __init platinumfb_init(void)
697 return -ENODEV; 696 return -ENODEV;
698 platinumfb_setup(option); 697 platinumfb_setup(option);
699#endif 698#endif
700 of_register_platform_driver(&platinum_driver); 699 platform_driver_register(&platinum_driver);
701 700
702 return 0; 701 return 0;
703} 702}
704 703
705static void __exit platinumfb_exit(void) 704static void __exit platinumfb_exit(void)
706{ 705{
707 of_unregister_platform_driver(&platinum_driver); 706 platform_driver_unregister(&platinum_driver);
708} 707}
709 708
710MODULE_LICENSE("GPL"); 709MODULE_LICENSE("GPL");
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
index 9c0144ee7ae5..65560a1a0439 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -513,9 +513,9 @@ static int ps3fb_release(struct fb_info *info, int user)
513 if (atomic_dec_and_test(&ps3fb.f_count)) { 513 if (atomic_dec_and_test(&ps3fb.f_count)) {
514 if (atomic_read(&ps3fb.ext_flip)) { 514 if (atomic_read(&ps3fb.ext_flip)) {
515 atomic_set(&ps3fb.ext_flip, 0); 515 atomic_set(&ps3fb.ext_flip, 0);
516 if (!try_acquire_console_sem()) { 516 if (console_trylock()) {
517 ps3fb_sync(info, 0); /* single buffer */ 517 ps3fb_sync(info, 0); /* single buffer */
518 release_console_sem(); 518 console_unlock();
519 } 519 }
520 } 520 }
521 } 521 }
@@ -830,14 +830,14 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
830 if (vmode) { 830 if (vmode) {
831 var = info->var; 831 var = info->var;
832 fb_videomode_to_var(&var, vmode); 832 fb_videomode_to_var(&var, vmode);
833 acquire_console_sem(); 833 console_lock();
834 info->flags |= FBINFO_MISC_USEREVENT; 834 info->flags |= FBINFO_MISC_USEREVENT;
835 /* Force, in case only special bits changed */ 835 /* Force, in case only special bits changed */
836 var.activate |= FB_ACTIVATE_FORCE; 836 var.activate |= FB_ACTIVATE_FORCE;
837 par->new_mode_id = val; 837 par->new_mode_id = val;
838 retval = fb_set_var(info, &var); 838 retval = fb_set_var(info, &var);
839 info->flags &= ~FBINFO_MISC_USEREVENT; 839 info->flags &= ~FBINFO_MISC_USEREVENT;
840 release_console_sem(); 840 console_unlock();
841 } 841 }
842 break; 842 break;
843 } 843 }
@@ -881,9 +881,9 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
881 break; 881 break;
882 882
883 dev_dbg(info->device, "PS3FB_IOCTL_FSEL:%d\n", val); 883 dev_dbg(info->device, "PS3FB_IOCTL_FSEL:%d\n", val);
884 acquire_console_sem(); 884 console_lock();
885 retval = ps3fb_sync(info, val); 885 retval = ps3fb_sync(info, val);
886 release_console_sem(); 886 console_unlock();
887 break; 887 break;
888 888
889 default: 889 default:
@@ -903,9 +903,9 @@ static int ps3fbd(void *arg)
903 set_current_state(TASK_INTERRUPTIBLE); 903 set_current_state(TASK_INTERRUPTIBLE);
904 if (ps3fb.is_kicked) { 904 if (ps3fb.is_kicked) {
905 ps3fb.is_kicked = 0; 905 ps3fb.is_kicked = 0;
906 acquire_console_sem(); 906 console_lock();
907 ps3fb_sync(info, 0); /* single buffer */ 907 ps3fb_sync(info, 0); /* single buffer */
908 release_console_sem(); 908 console_unlock();
909 } 909 }
910 schedule(); 910 schedule();
911 } 911 }
diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c
index a31a77ff6f3d..bb95ec56d25d 100644
--- a/drivers/video/pxa168fb.c
+++ b/drivers/video/pxa168fb.c
@@ -623,19 +623,21 @@ static int __devinit pxa168fb_probe(struct platform_device *pdev)
623 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 623 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
624 if (res == NULL) { 624 if (res == NULL) {
625 dev_err(&pdev->dev, "no IO memory defined\n"); 625 dev_err(&pdev->dev, "no IO memory defined\n");
626 return -ENOENT; 626 ret = -ENOENT;
627 goto failed_put_clk;
627 } 628 }
628 629
629 irq = platform_get_irq(pdev, 0); 630 irq = platform_get_irq(pdev, 0);
630 if (irq < 0) { 631 if (irq < 0) {
631 dev_err(&pdev->dev, "no IRQ defined\n"); 632 dev_err(&pdev->dev, "no IRQ defined\n");
632 return -ENOENT; 633 ret = -ENOENT;
634 goto failed_put_clk;
633 } 635 }
634 636
635 info = framebuffer_alloc(sizeof(struct pxa168fb_info), &pdev->dev); 637 info = framebuffer_alloc(sizeof(struct pxa168fb_info), &pdev->dev);
636 if (info == NULL) { 638 if (info == NULL) {
637 clk_put(clk); 639 ret = -ENOMEM;
638 return -ENOMEM; 640 goto failed_put_clk;
639 } 641 }
640 642
641 /* Initialize private data */ 643 /* Initialize private data */
@@ -671,7 +673,7 @@ static int __devinit pxa168fb_probe(struct platform_device *pdev)
671 fbi->reg_base = ioremap_nocache(res->start, resource_size(res)); 673 fbi->reg_base = ioremap_nocache(res->start, resource_size(res));
672 if (fbi->reg_base == NULL) { 674 if (fbi->reg_base == NULL) {
673 ret = -ENOMEM; 675 ret = -ENOMEM;
674 goto failed; 676 goto failed_free_info;
675 } 677 }
676 678
677 /* 679 /*
@@ -683,7 +685,7 @@ static int __devinit pxa168fb_probe(struct platform_device *pdev)
683 &fbi->fb_start_dma, GFP_KERNEL); 685 &fbi->fb_start_dma, GFP_KERNEL);
684 if (info->screen_base == NULL) { 686 if (info->screen_base == NULL) {
685 ret = -ENOMEM; 687 ret = -ENOMEM;
686 goto failed; 688 goto failed_free_info;
687 } 689 }
688 690
689 info->fix.smem_start = (unsigned long)fbi->fb_start_dma; 691 info->fix.smem_start = (unsigned long)fbi->fb_start_dma;
@@ -701,16 +703,12 @@ static int __devinit pxa168fb_probe(struct platform_device *pdev)
701 */ 703 */
702 pxa168fb_init_mode(info, mi); 704 pxa168fb_init_mode(info, mi);
703 705
704 ret = pxa168fb_check_var(&info->var, info);
705 if (ret)
706 goto failed_free_fbmem;
707
708 /* 706 /*
709 * Fill in sane defaults. 707 * Fill in sane defaults.
710 */ 708 */
711 ret = pxa168fb_check_var(&info->var, info); 709 ret = pxa168fb_check_var(&info->var, info);
712 if (ret) 710 if (ret)
713 goto failed; 711 goto failed_free_fbmem;
714 712
715 /* 713 /*
716 * enable controller clock 714 * enable controller clock
@@ -776,20 +774,62 @@ failed_free_clk:
776failed_free_fbmem: 774failed_free_fbmem:
777 dma_free_coherent(fbi->dev, info->fix.smem_len, 775 dma_free_coherent(fbi->dev, info->fix.smem_len,
778 info->screen_base, fbi->fb_start_dma); 776 info->screen_base, fbi->fb_start_dma);
779failed: 777failed_free_info:
780 kfree(info); 778 kfree(info);
779failed_put_clk:
781 clk_put(clk); 780 clk_put(clk);
782 781
783 dev_err(&pdev->dev, "frame buffer device init failed with %d\n", ret); 782 dev_err(&pdev->dev, "frame buffer device init failed with %d\n", ret);
784 return ret; 783 return ret;
785} 784}
786 785
786static int __devexit pxa168fb_remove(struct platform_device *pdev)
787{
788 struct pxa168fb_info *fbi = platform_get_drvdata(pdev);
789 struct fb_info *info;
790 int irq;
791 unsigned int data;
792
793 if (!fbi)
794 return 0;
795
796 /* disable DMA transfer */
797 data = readl(fbi->reg_base + LCD_SPU_DMA_CTRL0);
798 data &= ~CFG_GRA_ENA_MASK;
799 writel(data, fbi->reg_base + LCD_SPU_DMA_CTRL0);
800
801 info = fbi->info;
802
803 unregister_framebuffer(info);
804
805 writel(GRA_FRAME_IRQ0_ENA(0x0), fbi->reg_base + SPU_IRQ_ENA);
806
807 if (info->cmap.len)
808 fb_dealloc_cmap(&info->cmap);
809
810 irq = platform_get_irq(pdev, 0);
811 free_irq(irq, fbi);
812
813 dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
814 info->screen_base, info->fix.smem_start);
815
816 iounmap(fbi->reg_base);
817
818 clk_disable(fbi->clk);
819 clk_put(fbi->clk);
820
821 framebuffer_release(info);
822
823 return 0;
824}
825
787static struct platform_driver pxa168fb_driver = { 826static struct platform_driver pxa168fb_driver = {
788 .driver = { 827 .driver = {
789 .name = "pxa168-fb", 828 .name = "pxa168-fb",
790 .owner = THIS_MODULE, 829 .owner = THIS_MODULE,
791 }, 830 },
792 .probe = pxa168fb_probe, 831 .probe = pxa168fb_probe,
832 .remove = __devexit_p(pxa168fb_remove),
793}; 833};
794 834
795static int __init pxa168fb_init(void) 835static int __init pxa168fb_init(void)
@@ -798,6 +838,12 @@ static int __init pxa168fb_init(void)
798} 838}
799module_init(pxa168fb_init); 839module_init(pxa168fb_init);
800 840
841static void __exit pxa168fb_exit(void)
842{
843 platform_driver_unregister(&pxa168fb_driver);
844}
845module_exit(pxa168fb_exit);
846
801MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com> " 847MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com> "
802 "Green Wan <gwan@marvell.com>"); 848 "Green Wan <gwan@marvell.com>");
803MODULE_DESCRIPTION("Framebuffer driver for PXA168/910"); 849MODULE_DESCRIPTION("Framebuffer driver for PXA168/910");
diff --git a/drivers/video/pxa3xx-gcu.c b/drivers/video/pxa3xx-gcu.c
new file mode 100644
index 000000000000..0283c7021090
--- /dev/null
+++ b/drivers/video/pxa3xx-gcu.c
@@ -0,0 +1,772 @@
1/*
2 * pxa3xx-gcu.c - Linux kernel module for PXA3xx graphics controllers
3 *
4 * This driver needs a DirectFB counterpart in user space, communication
5 * is handled via mmap()ed memory areas and an ioctl.
6 *
7 * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
8 * Copyright (c) 2009 Janine Kropp <nin@directfb.org>
9 * Copyright (c) 2009 Denis Oliver Kropp <dok@directfb.org>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
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 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26/*
27 * WARNING: This controller is attached to System Bus 2 of the PXA which
28 * needs its arbiter to be enabled explicitly (CKENB & 1<<9).
29 * There is currently no way to do this from Linux, so you need to teach
30 * your bootloader for now.
31 */
32
33#include <linux/module.h>
34#include <linux/version.h>
35
36#include <linux/platform_device.h>
37#include <linux/dma-mapping.h>
38#include <linux/miscdevice.h>
39#include <linux/interrupt.h>
40#include <linux/spinlock.h>
41#include <linux/uaccess.h>
42#include <linux/ioctl.h>
43#include <linux/delay.h>
44#include <linux/sched.h>
45#include <linux/slab.h>
46#include <linux/clk.h>
47#include <linux/fs.h>
48#include <linux/io.h>
49
50#include "pxa3xx-gcu.h"
51
52#define DRV_NAME "pxa3xx-gcu"
53#define MISCDEV_MINOR 197
54
55#define REG_GCCR 0x00
56#define GCCR_SYNC_CLR (1 << 9)
57#define GCCR_BP_RST (1 << 8)
58#define GCCR_ABORT (1 << 6)
59#define GCCR_STOP (1 << 4)
60
61#define REG_GCISCR 0x04
62#define REG_GCIECR 0x08
63#define REG_GCRBBR 0x20
64#define REG_GCRBLR 0x24
65#define REG_GCRBHR 0x28
66#define REG_GCRBTR 0x2C
67#define REG_GCRBEXHR 0x30
68
69#define IE_EOB (1 << 0)
70#define IE_EEOB (1 << 5)
71#define IE_ALL 0xff
72
73#define SHARED_SIZE PAGE_ALIGN(sizeof(struct pxa3xx_gcu_shared))
74
75/* #define PXA3XX_GCU_DEBUG */
76/* #define PXA3XX_GCU_DEBUG_TIMER */
77
78#ifdef PXA3XX_GCU_DEBUG
79#define QDUMP(msg) \
80 do { \
81 QPRINT(priv, KERN_DEBUG, msg); \
82 } while (0)
83#else
84#define QDUMP(msg) do {} while (0)
85#endif
86
87#define QERROR(msg) \
88 do { \
89 QPRINT(priv, KERN_ERR, msg); \
90 } while (0)
91
92struct pxa3xx_gcu_batch {
93 struct pxa3xx_gcu_batch *next;
94 u32 *ptr;
95 dma_addr_t phys;
96 unsigned long length;
97};
98
99struct pxa3xx_gcu_priv {
100 void __iomem *mmio_base;
101 struct clk *clk;
102 struct pxa3xx_gcu_shared *shared;
103 dma_addr_t shared_phys;
104 struct resource *resource_mem;
105 struct miscdevice misc_dev;
106 struct file_operations misc_fops;
107 wait_queue_head_t wait_idle;
108 wait_queue_head_t wait_free;
109 spinlock_t spinlock;
110 struct timeval base_time;
111
112 struct pxa3xx_gcu_batch *free;
113
114 struct pxa3xx_gcu_batch *ready;
115 struct pxa3xx_gcu_batch *ready_last;
116 struct pxa3xx_gcu_batch *running;
117};
118
119static inline unsigned long
120gc_readl(struct pxa3xx_gcu_priv *priv, unsigned int off)
121{
122 return __raw_readl(priv->mmio_base + off);
123}
124
125static inline void
126gc_writel(struct pxa3xx_gcu_priv *priv, unsigned int off, unsigned long val)
127{
128 __raw_writel(val, priv->mmio_base + off);
129}
130
131#define QPRINT(priv, level, msg) \
132 do { \
133 struct timeval tv; \
134 struct pxa3xx_gcu_shared *shared = priv->shared; \
135 u32 base = gc_readl(priv, REG_GCRBBR); \
136 \
137 do_gettimeofday(&tv); \
138 \
139 printk(level "%ld.%03ld.%03ld - %-17s: %-21s (%s, " \
140 "STATUS " \
141 "0x%02lx, B 0x%08lx [%ld], E %5ld, H %5ld, " \
142 "T %5ld)\n", \
143 tv.tv_sec - priv->base_time.tv_sec, \
144 tv.tv_usec / 1000, tv.tv_usec % 1000, \
145 __func__, msg, \
146 shared->hw_running ? "running" : " idle", \
147 gc_readl(priv, REG_GCISCR), \
148 gc_readl(priv, REG_GCRBBR), \
149 gc_readl(priv, REG_GCRBLR), \
150 (gc_readl(priv, REG_GCRBEXHR) - base) / 4, \
151 (gc_readl(priv, REG_GCRBHR) - base) / 4, \
152 (gc_readl(priv, REG_GCRBTR) - base) / 4); \
153 } while (0)
154
155static void
156pxa3xx_gcu_reset(struct pxa3xx_gcu_priv *priv)
157{
158 QDUMP("RESET");
159
160 /* disable interrupts */
161 gc_writel(priv, REG_GCIECR, 0);
162
163 /* reset hardware */
164 gc_writel(priv, REG_GCCR, GCCR_ABORT);
165 gc_writel(priv, REG_GCCR, 0);
166
167 memset(priv->shared, 0, SHARED_SIZE);
168 priv->shared->buffer_phys = priv->shared_phys;
169 priv->shared->magic = PXA3XX_GCU_SHARED_MAGIC;
170
171 do_gettimeofday(&priv->base_time);
172
173 /* set up the ring buffer pointers */
174 gc_writel(priv, REG_GCRBLR, 0);
175 gc_writel(priv, REG_GCRBBR, priv->shared_phys);
176 gc_writel(priv, REG_GCRBTR, priv->shared_phys);
177
178 /* enable all IRQs except EOB */
179 gc_writel(priv, REG_GCIECR, IE_ALL & ~IE_EOB);
180}
181
182static void
183dump_whole_state(struct pxa3xx_gcu_priv *priv)
184{
185 struct pxa3xx_gcu_shared *sh = priv->shared;
186 u32 base = gc_readl(priv, REG_GCRBBR);
187
188 QDUMP("DUMP");
189
190 printk(KERN_DEBUG "== PXA3XX-GCU DUMP ==\n"
191 "%s, STATUS 0x%02lx, B 0x%08lx [%ld], E %5ld, H %5ld, T %5ld\n",
192 sh->hw_running ? "running" : "idle ",
193 gc_readl(priv, REG_GCISCR),
194 gc_readl(priv, REG_GCRBBR),
195 gc_readl(priv, REG_GCRBLR),
196 (gc_readl(priv, REG_GCRBEXHR) - base) / 4,
197 (gc_readl(priv, REG_GCRBHR) - base) / 4,
198 (gc_readl(priv, REG_GCRBTR) - base) / 4);
199}
200
201static void
202flush_running(struct pxa3xx_gcu_priv *priv)
203{
204 struct pxa3xx_gcu_batch *running = priv->running;
205 struct pxa3xx_gcu_batch *next;
206
207 while (running) {
208 next = running->next;
209 running->next = priv->free;
210 priv->free = running;
211 running = next;
212 }
213
214 priv->running = NULL;
215}
216
217static void
218run_ready(struct pxa3xx_gcu_priv *priv)
219{
220 unsigned int num = 0;
221 struct pxa3xx_gcu_shared *shared = priv->shared;
222 struct pxa3xx_gcu_batch *ready = priv->ready;
223
224 QDUMP("Start");
225
226 BUG_ON(!ready);
227
228 shared->buffer[num++] = 0x05000000;
229
230 while (ready) {
231 shared->buffer[num++] = 0x00000001;
232 shared->buffer[num++] = ready->phys;
233 ready = ready->next;
234 }
235
236 shared->buffer[num++] = 0x05000000;
237 priv->running = priv->ready;
238 priv->ready = priv->ready_last = NULL;
239 gc_writel(priv, REG_GCRBLR, 0);
240 shared->hw_running = 1;
241
242 /* ring base address */
243 gc_writel(priv, REG_GCRBBR, shared->buffer_phys);
244
245 /* ring tail address */
246 gc_writel(priv, REG_GCRBTR, shared->buffer_phys + num * 4);
247
248 /* ring length */
249 gc_writel(priv, REG_GCRBLR, ((num + 63) & ~63) * 4);
250}
251
252static irqreturn_t
253pxa3xx_gcu_handle_irq(int irq, void *ctx)
254{
255 struct pxa3xx_gcu_priv *priv = ctx;
256 struct pxa3xx_gcu_shared *shared = priv->shared;
257 u32 status = gc_readl(priv, REG_GCISCR) & IE_ALL;
258
259 QDUMP("-Interrupt");
260
261 if (!status)
262 return IRQ_NONE;
263
264 spin_lock(&priv->spinlock);
265 shared->num_interrupts++;
266
267 if (status & IE_EEOB) {
268 QDUMP(" [EEOB]");
269
270 flush_running(priv);
271 wake_up_all(&priv->wait_free);
272
273 if (priv->ready) {
274 run_ready(priv);
275 } else {
276 /* There is no more data prepared by the userspace.
277 * Set hw_running = 0 and wait for the next userspace
278 * kick-off */
279 shared->num_idle++;
280 shared->hw_running = 0;
281
282 QDUMP(" '-> Idle.");
283
284 /* set ring buffer length to zero */
285 gc_writel(priv, REG_GCRBLR, 0);
286
287 wake_up_all(&priv->wait_idle);
288 }
289
290 shared->num_done++;
291 } else {
292 QERROR(" [???]");
293 dump_whole_state(priv);
294 }
295
296 /* Clear the interrupt */
297 gc_writel(priv, REG_GCISCR, status);
298 spin_unlock(&priv->spinlock);
299
300 return IRQ_HANDLED;
301}
302
303static int
304pxa3xx_gcu_wait_idle(struct pxa3xx_gcu_priv *priv)
305{
306 int ret = 0;
307
308 QDUMP("Waiting for idle...");
309
310 /* Does not need to be atomic. There's a lock in user space,
311 * but anyhow, this is just for statistics. */
312 priv->shared->num_wait_idle++;
313
314 while (priv->shared->hw_running) {
315 int num = priv->shared->num_interrupts;
316 u32 rbexhr = gc_readl(priv, REG_GCRBEXHR);
317
318 ret = wait_event_interruptible_timeout(priv->wait_idle,
319 !priv->shared->hw_running, HZ*4);
320
321 if (ret < 0)
322 break;
323
324 if (ret > 0)
325 continue;
326
327 if (gc_readl(priv, REG_GCRBEXHR) == rbexhr &&
328 priv->shared->num_interrupts == num) {
329 QERROR("TIMEOUT");
330 ret = -ETIMEDOUT;
331 break;
332 }
333 }
334
335 QDUMP("done");
336
337 return ret;
338}
339
340static int
341pxa3xx_gcu_wait_free(struct pxa3xx_gcu_priv *priv)
342{
343 int ret = 0;
344
345 QDUMP("Waiting for free...");
346
347 /* Does not need to be atomic. There's a lock in user space,
348 * but anyhow, this is just for statistics. */
349 priv->shared->num_wait_free++;
350
351 while (!priv->free) {
352 u32 rbexhr = gc_readl(priv, REG_GCRBEXHR);
353
354 ret = wait_event_interruptible_timeout(priv->wait_free,
355 priv->free, HZ*4);
356
357 if (ret < 0)
358 break;
359
360 if (ret > 0)
361 continue;
362
363 if (gc_readl(priv, REG_GCRBEXHR) == rbexhr) {
364 QERROR("TIMEOUT");
365 ret = -ETIMEDOUT;
366 break;
367 }
368 }
369
370 QDUMP("done");
371
372 return ret;
373}
374
375/* Misc device layer */
376
377static ssize_t
378pxa3xx_gcu_misc_write(struct file *filp, const char *buff,
379 size_t count, loff_t *offp)
380{
381 int ret;
382 unsigned long flags;
383 struct pxa3xx_gcu_batch *buffer;
384 struct pxa3xx_gcu_priv *priv =
385 container_of(filp->f_op, struct pxa3xx_gcu_priv, misc_fops);
386
387 int words = count / 4;
388
389 /* Does not need to be atomic. There's a lock in user space,
390 * but anyhow, this is just for statistics. */
391 priv->shared->num_writes++;
392
393 priv->shared->num_words += words;
394
395 /* Last word reserved for batch buffer end command */
396 if (words >= PXA3XX_GCU_BATCH_WORDS)
397 return -E2BIG;
398
399 /* Wait for a free buffer */
400 if (!priv->free) {
401 ret = pxa3xx_gcu_wait_free(priv);
402 if (ret < 0)
403 return ret;
404 }
405
406 /*
407 * Get buffer from free list
408 */
409 spin_lock_irqsave(&priv->spinlock, flags);
410
411 buffer = priv->free;
412 priv->free = buffer->next;
413
414 spin_unlock_irqrestore(&priv->spinlock, flags);
415
416
417 /* Copy data from user into buffer */
418 ret = copy_from_user(buffer->ptr, buff, words * 4);
419 if (ret) {
420 spin_lock_irqsave(&priv->spinlock, flags);
421 buffer->next = priv->free;
422 priv->free = buffer;
423 spin_unlock_irqrestore(&priv->spinlock, flags);
424 return -EFAULT;
425 }
426
427 buffer->length = words;
428
429 /* Append batch buffer end command */
430 buffer->ptr[words] = 0x01000000;
431
432 /*
433 * Add buffer to ready list
434 */
435 spin_lock_irqsave(&priv->spinlock, flags);
436
437 buffer->next = NULL;
438
439 if (priv->ready) {
440 BUG_ON(priv->ready_last == NULL);
441
442 priv->ready_last->next = buffer;
443 } else
444 priv->ready = buffer;
445
446 priv->ready_last = buffer;
447
448 if (!priv->shared->hw_running)
449 run_ready(priv);
450
451 spin_unlock_irqrestore(&priv->spinlock, flags);
452
453 return words * 4;
454}
455
456
457static long
458pxa3xx_gcu_misc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
459{
460 unsigned long flags;
461 struct pxa3xx_gcu_priv *priv =
462 container_of(filp->f_op, struct pxa3xx_gcu_priv, misc_fops);
463
464 switch (cmd) {
465 case PXA3XX_GCU_IOCTL_RESET:
466 spin_lock_irqsave(&priv->spinlock, flags);
467 pxa3xx_gcu_reset(priv);
468 spin_unlock_irqrestore(&priv->spinlock, flags);
469 return 0;
470
471 case PXA3XX_GCU_IOCTL_WAIT_IDLE:
472 return pxa3xx_gcu_wait_idle(priv);
473 }
474
475 return -ENOSYS;
476}
477
478static int
479pxa3xx_gcu_misc_mmap(struct file *filp, struct vm_area_struct *vma)
480{
481 unsigned int size = vma->vm_end - vma->vm_start;
482 struct pxa3xx_gcu_priv *priv =
483 container_of(filp->f_op, struct pxa3xx_gcu_priv, misc_fops);
484
485 switch (vma->vm_pgoff) {
486 case 0:
487 /* hand out the shared data area */
488 if (size != SHARED_SIZE)
489 return -EINVAL;
490
491 return dma_mmap_coherent(NULL, vma,
492 priv->shared, priv->shared_phys, size);
493
494 case SHARED_SIZE >> PAGE_SHIFT:
495 /* hand out the MMIO base for direct register access
496 * from userspace */
497 if (size != resource_size(priv->resource_mem))
498 return -EINVAL;
499
500 vma->vm_flags |= VM_IO;
501 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
502
503 return io_remap_pfn_range(vma, vma->vm_start,
504 priv->resource_mem->start >> PAGE_SHIFT,
505 size, vma->vm_page_prot);
506 }
507
508 return -EINVAL;
509}
510
511
512#ifdef PXA3XX_GCU_DEBUG_TIMER
513static struct timer_list pxa3xx_gcu_debug_timer;
514
515static void pxa3xx_gcu_debug_timedout(unsigned long ptr)
516{
517 struct pxa3xx_gcu_priv *priv = (struct pxa3xx_gcu_priv *) ptr;
518
519 QERROR("Timer DUMP");
520
521 /* init the timer structure */
522 init_timer(&pxa3xx_gcu_debug_timer);
523 pxa3xx_gcu_debug_timer.function = pxa3xx_gcu_debug_timedout;
524 pxa3xx_gcu_debug_timer.data = ptr;
525 pxa3xx_gcu_debug_timer.expires = jiffies + 5*HZ; /* one second */
526
527 add_timer(&pxa3xx_gcu_debug_timer);
528}
529
530static void pxa3xx_gcu_init_debug_timer(void)
531{
532 pxa3xx_gcu_debug_timedout((unsigned long) &pxa3xx_gcu_debug_timer);
533}
534#else
535static inline void pxa3xx_gcu_init_debug_timer(void) {}
536#endif
537
538static int
539add_buffer(struct platform_device *dev,
540 struct pxa3xx_gcu_priv *priv)
541{
542 struct pxa3xx_gcu_batch *buffer;
543
544 buffer = kzalloc(sizeof(struct pxa3xx_gcu_batch), GFP_KERNEL);
545 if (!buffer)
546 return -ENOMEM;
547
548 buffer->ptr = dma_alloc_coherent(&dev->dev, PXA3XX_GCU_BATCH_WORDS * 4,
549 &buffer->phys, GFP_KERNEL);
550 if (!buffer->ptr) {
551 kfree(buffer);
552 return -ENOMEM;
553 }
554
555 buffer->next = priv->free;
556
557 priv->free = buffer;
558
559 return 0;
560}
561
562static void
563free_buffers(struct platform_device *dev,
564 struct pxa3xx_gcu_priv *priv)
565{
566 struct pxa3xx_gcu_batch *next, *buffer = priv->free;
567
568 while (buffer) {
569 next = buffer->next;
570
571 dma_free_coherent(&dev->dev, PXA3XX_GCU_BATCH_WORDS * 4,
572 buffer->ptr, buffer->phys);
573
574 kfree(buffer);
575
576 buffer = next;
577 }
578
579 priv->free = NULL;
580}
581
582static int __devinit
583pxa3xx_gcu_probe(struct platform_device *dev)
584{
585 int i, ret, irq;
586 struct resource *r;
587 struct pxa3xx_gcu_priv *priv;
588
589 priv = kzalloc(sizeof(struct pxa3xx_gcu_priv), GFP_KERNEL);
590 if (!priv)
591 return -ENOMEM;
592
593 for (i = 0; i < 8; i++) {
594 ret = add_buffer(dev, priv);
595 if (ret) {
596 dev_err(&dev->dev, "failed to allocate DMA memory\n");
597 goto err_free_priv;
598 }
599 }
600
601 init_waitqueue_head(&priv->wait_idle);
602 init_waitqueue_head(&priv->wait_free);
603 spin_lock_init(&priv->spinlock);
604
605 /* we allocate the misc device structure as part of our own allocation,
606 * so we can get a pointer to our priv structure later on with
607 * container_of(). This isn't really necessary as we have a fixed minor
608 * number anyway, but this is to avoid statics. */
609
610 priv->misc_fops.owner = THIS_MODULE;
611 priv->misc_fops.write = pxa3xx_gcu_misc_write;
612 priv->misc_fops.unlocked_ioctl = pxa3xx_gcu_misc_ioctl;
613 priv->misc_fops.mmap = pxa3xx_gcu_misc_mmap;
614
615 priv->misc_dev.minor = MISCDEV_MINOR,
616 priv->misc_dev.name = DRV_NAME,
617 priv->misc_dev.fops = &priv->misc_fops,
618
619 /* register misc device */
620 ret = misc_register(&priv->misc_dev);
621 if (ret < 0) {
622 dev_err(&dev->dev, "misc_register() for minor %d failed\n",
623 MISCDEV_MINOR);
624 goto err_free_priv;
625 }
626
627 /* handle IO resources */
628 r = platform_get_resource(dev, IORESOURCE_MEM, 0);
629 if (r == NULL) {
630 dev_err(&dev->dev, "no I/O memory resource defined\n");
631 ret = -ENODEV;
632 goto err_misc_deregister;
633 }
634
635 if (!request_mem_region(r->start, resource_size(r), dev->name)) {
636 dev_err(&dev->dev, "failed to request I/O memory\n");
637 ret = -EBUSY;
638 goto err_misc_deregister;
639 }
640
641 priv->mmio_base = ioremap_nocache(r->start, resource_size(r));
642 if (!priv->mmio_base) {
643 dev_err(&dev->dev, "failed to map I/O memory\n");
644 ret = -EBUSY;
645 goto err_free_mem_region;
646 }
647
648 /* allocate dma memory */
649 priv->shared = dma_alloc_coherent(&dev->dev, SHARED_SIZE,
650 &priv->shared_phys, GFP_KERNEL);
651
652 if (!priv->shared) {
653 dev_err(&dev->dev, "failed to allocate DMA memory\n");
654 ret = -ENOMEM;
655 goto err_free_io;
656 }
657
658 /* enable the clock */
659 priv->clk = clk_get(&dev->dev, NULL);
660 if (IS_ERR(priv->clk)) {
661 dev_err(&dev->dev, "failed to get clock\n");
662 ret = -ENODEV;
663 goto err_free_dma;
664 }
665
666 ret = clk_enable(priv->clk);
667 if (ret < 0) {
668 dev_err(&dev->dev, "failed to enable clock\n");
669 goto err_put_clk;
670 }
671
672 /* request the IRQ */
673 irq = platform_get_irq(dev, 0);
674 if (irq < 0) {
675 dev_err(&dev->dev, "no IRQ defined\n");
676 ret = -ENODEV;
677 goto err_put_clk;
678 }
679
680 ret = request_irq(irq, pxa3xx_gcu_handle_irq,
681 IRQF_DISABLED, DRV_NAME, priv);
682 if (ret) {
683 dev_err(&dev->dev, "request_irq failed\n");
684 ret = -EBUSY;
685 goto err_put_clk;
686 }
687
688 platform_set_drvdata(dev, priv);
689 priv->resource_mem = r;
690 pxa3xx_gcu_reset(priv);
691 pxa3xx_gcu_init_debug_timer();
692
693 dev_info(&dev->dev, "registered @0x%p, DMA 0x%p (%d bytes), IRQ %d\n",
694 (void *) r->start, (void *) priv->shared_phys,
695 SHARED_SIZE, irq);
696 return 0;
697
698err_put_clk:
699 clk_disable(priv->clk);
700 clk_put(priv->clk);
701
702err_free_dma:
703 dma_free_coherent(&dev->dev, SHARED_SIZE,
704 priv->shared, priv->shared_phys);
705
706err_free_io:
707 iounmap(priv->mmio_base);
708
709err_free_mem_region:
710 release_mem_region(r->start, resource_size(r));
711
712err_misc_deregister:
713 misc_deregister(&priv->misc_dev);
714
715err_free_priv:
716 platform_set_drvdata(dev, NULL);
717 free_buffers(dev, priv);
718 kfree(priv);
719 return ret;
720}
721
722static int __devexit
723pxa3xx_gcu_remove(struct platform_device *dev)
724{
725 struct pxa3xx_gcu_priv *priv = platform_get_drvdata(dev);
726 struct resource *r = priv->resource_mem;
727
728 pxa3xx_gcu_wait_idle(priv);
729
730 misc_deregister(&priv->misc_dev);
731 dma_free_coherent(&dev->dev, SHARED_SIZE,
732 priv->shared, priv->shared_phys);
733 iounmap(priv->mmio_base);
734 release_mem_region(r->start, resource_size(r));
735 platform_set_drvdata(dev, NULL);
736 clk_disable(priv->clk);
737 free_buffers(dev, priv);
738 kfree(priv);
739
740 return 0;
741}
742
743static struct platform_driver pxa3xx_gcu_driver = {
744 .probe = pxa3xx_gcu_probe,
745 .remove = __devexit_p(pxa3xx_gcu_remove),
746 .driver = {
747 .owner = THIS_MODULE,
748 .name = DRV_NAME,
749 },
750};
751
752static int __init
753pxa3xx_gcu_init(void)
754{
755 return platform_driver_register(&pxa3xx_gcu_driver);
756}
757
758static void __exit
759pxa3xx_gcu_exit(void)
760{
761 platform_driver_unregister(&pxa3xx_gcu_driver);
762}
763
764module_init(pxa3xx_gcu_init);
765module_exit(pxa3xx_gcu_exit);
766
767MODULE_DESCRIPTION("PXA3xx graphics controller unit driver");
768MODULE_LICENSE("GPL");
769MODULE_ALIAS_MISCDEV(MISCDEV_MINOR);
770MODULE_AUTHOR("Janine Kropp <nin@directfb.org>, "
771 "Denis Oliver Kropp <dok@directfb.org>, "
772 "Daniel Mack <daniel@caiaq.de>");
diff --git a/drivers/video/pxa3xx-gcu.h b/drivers/video/pxa3xx-gcu.h
new file mode 100644
index 000000000000..0428ed03dc49
--- /dev/null
+++ b/drivers/video/pxa3xx-gcu.h
@@ -0,0 +1,38 @@
1#ifndef __PXA3XX_GCU_H__
2#define __PXA3XX_GCU_H__
3
4#include <linux/types.h>
5
6/* Number of 32bit words in display list (ring buffer). */
7#define PXA3XX_GCU_BUFFER_WORDS ((256 * 1024 - 256) / 4)
8
9/* To be increased when breaking the ABI */
10#define PXA3XX_GCU_SHARED_MAGIC 0x30000001
11
12#define PXA3XX_GCU_BATCH_WORDS 8192
13
14struct pxa3xx_gcu_shared {
15 u32 buffer[PXA3XX_GCU_BUFFER_WORDS];
16
17 bool hw_running;
18
19 unsigned long buffer_phys;
20
21 unsigned int num_words;
22 unsigned int num_writes;
23 unsigned int num_done;
24 unsigned int num_interrupts;
25 unsigned int num_wait_idle;
26 unsigned int num_wait_free;
27 unsigned int num_idle;
28
29 u32 magic;
30};
31
32/* Initialization and synchronization.
33 * Hardware is started upon write(). */
34#define PXA3XX_GCU_IOCTL_RESET _IO('G', 0)
35#define PXA3XX_GCU_IOCTL_WAIT_IDLE _IO('G', 2)
36
37#endif /* __PXA3XX_GCU_H__ */
38
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 825b665245bb..0f4e8c942f9e 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -627,7 +627,12 @@ static void overlay1fb_enable(struct pxafb_layer *ofb)
627 627
628static void overlay1fb_disable(struct pxafb_layer *ofb) 628static void overlay1fb_disable(struct pxafb_layer *ofb)
629{ 629{
630 uint32_t lccr5 = lcd_readl(ofb->fbi, LCCR5); 630 uint32_t lccr5;
631
632 if (!(lcd_readl(ofb->fbi, OVL1C1) & OVLxC1_OEN))
633 return;
634
635 lccr5 = lcd_readl(ofb->fbi, LCCR5);
631 636
632 lcd_writel(ofb->fbi, OVL1C1, ofb->control[0] & ~OVLxC1_OEN); 637 lcd_writel(ofb->fbi, OVL1C1, ofb->control[0] & ~OVLxC1_OEN);
633 638
@@ -685,7 +690,12 @@ static void overlay2fb_enable(struct pxafb_layer *ofb)
685 690
686static void overlay2fb_disable(struct pxafb_layer *ofb) 691static void overlay2fb_disable(struct pxafb_layer *ofb)
687{ 692{
688 uint32_t lccr5 = lcd_readl(ofb->fbi, LCCR5); 693 uint32_t lccr5;
694
695 if (!(lcd_readl(ofb->fbi, OVL2C1) & OVLxC1_OEN))
696 return;
697
698 lccr5 = lcd_readl(ofb->fbi, LCCR5);
689 699
690 lcd_writel(ofb->fbi, OVL2C1, ofb->control[0] & ~OVLxC1_OEN); 700 lcd_writel(ofb->fbi, OVL2C1, ofb->control[0] & ~OVLxC1_OEN);
691 701
@@ -720,12 +730,10 @@ static int overlayfb_open(struct fb_info *info, int user)
720 if (user == 0) 730 if (user == 0)
721 return -ENODEV; 731 return -ENODEV;
722 732
723 /* allow only one user at a time */ 733 if (ofb->usage++ == 0)
724 if (atomic_inc_and_test(&ofb->usage)) 734 /* unblank the base framebuffer */
725 return -EBUSY; 735 fb_blank(&ofb->fbi->fb, FB_BLANK_UNBLANK);
726 736
727 /* unblank the base framebuffer */
728 fb_blank(&ofb->fbi->fb, FB_BLANK_UNBLANK);
729 return 0; 737 return 0;
730} 738}
731 739
@@ -733,12 +741,15 @@ static int overlayfb_release(struct fb_info *info, int user)
733{ 741{
734 struct pxafb_layer *ofb = (struct pxafb_layer*) info; 742 struct pxafb_layer *ofb = (struct pxafb_layer*) info;
735 743
736 atomic_dec(&ofb->usage); 744 if (ofb->usage == 1) {
737 ofb->ops->disable(ofb); 745 ofb->ops->disable(ofb);
746 ofb->fb.var.height = -1;
747 ofb->fb.var.width = -1;
748 ofb->fb.var.xres = ofb->fb.var.xres_virtual = 0;
749 ofb->fb.var.yres = ofb->fb.var.yres_virtual = 0;
738 750
739 free_pages_exact(ofb->video_mem, ofb->video_mem_size); 751 ofb->usage--;
740 ofb->video_mem = NULL; 752 }
741 ofb->video_mem_size = 0;
742 return 0; 753 return 0;
743} 754}
744 755
@@ -750,7 +761,7 @@ static int overlayfb_check_var(struct fb_var_screeninfo *var,
750 int xpos, ypos, pfor, bpp; 761 int xpos, ypos, pfor, bpp;
751 762
752 xpos = NONSTD_TO_XPOS(var->nonstd); 763 xpos = NONSTD_TO_XPOS(var->nonstd);
753 ypos = NONSTD_TO_XPOS(var->nonstd); 764 ypos = NONSTD_TO_YPOS(var->nonstd);
754 pfor = NONSTD_TO_PFOR(var->nonstd); 765 pfor = NONSTD_TO_PFOR(var->nonstd);
755 766
756 bpp = pxafb_var_to_bpp(var); 767 bpp = pxafb_var_to_bpp(var);
@@ -794,7 +805,7 @@ static int overlayfb_check_var(struct fb_var_screeninfo *var,
794 return 0; 805 return 0;
795} 806}
796 807
797static int overlayfb_map_video_memory(struct pxafb_layer *ofb) 808static int overlayfb_check_video_memory(struct pxafb_layer *ofb)
798{ 809{
799 struct fb_var_screeninfo *var = &ofb->fb.var; 810 struct fb_var_screeninfo *var = &ofb->fb.var;
800 int pfor = NONSTD_TO_PFOR(var->nonstd); 811 int pfor = NONSTD_TO_PFOR(var->nonstd);
@@ -812,27 +823,11 @@ static int overlayfb_map_video_memory(struct pxafb_layer *ofb)
812 823
813 size = PAGE_ALIGN(ofb->fb.fix.line_length * var->yres_virtual); 824 size = PAGE_ALIGN(ofb->fb.fix.line_length * var->yres_virtual);
814 825
815 /* don't re-allocate if the original video memory is enough */
816 if (ofb->video_mem) { 826 if (ofb->video_mem) {
817 if (ofb->video_mem_size >= size) 827 if (ofb->video_mem_size >= size)
818 return 0; 828 return 0;
819
820 free_pages_exact(ofb->video_mem, ofb->video_mem_size);
821 } 829 }
822 830 return -EINVAL;
823 ofb->video_mem = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO);
824 if (ofb->video_mem == NULL)
825 return -ENOMEM;
826
827 ofb->video_mem_phys = virt_to_phys(ofb->video_mem);
828 ofb->video_mem_size = size;
829
830 mutex_lock(&ofb->fb.mm_lock);
831 ofb->fb.fix.smem_start = ofb->video_mem_phys;
832 ofb->fb.fix.smem_len = ofb->fb.fix.line_length * var->yres_virtual;
833 mutex_unlock(&ofb->fb.mm_lock);
834 ofb->fb.screen_base = ofb->video_mem;
835 return 0;
836} 831}
837 832
838static int overlayfb_set_par(struct fb_info *info) 833static int overlayfb_set_par(struct fb_info *info)
@@ -841,13 +836,13 @@ static int overlayfb_set_par(struct fb_info *info)
841 struct fb_var_screeninfo *var = &info->var; 836 struct fb_var_screeninfo *var = &info->var;
842 int xpos, ypos, pfor, bpp, ret; 837 int xpos, ypos, pfor, bpp, ret;
843 838
844 ret = overlayfb_map_video_memory(ofb); 839 ret = overlayfb_check_video_memory(ofb);
845 if (ret) 840 if (ret)
846 return ret; 841 return ret;
847 842
848 bpp = pxafb_var_to_bpp(var); 843 bpp = pxafb_var_to_bpp(var);
849 xpos = NONSTD_TO_XPOS(var->nonstd); 844 xpos = NONSTD_TO_XPOS(var->nonstd);
850 ypos = NONSTD_TO_XPOS(var->nonstd); 845 ypos = NONSTD_TO_YPOS(var->nonstd);
851 pfor = NONSTD_TO_PFOR(var->nonstd); 846 pfor = NONSTD_TO_PFOR(var->nonstd);
852 847
853 ofb->control[0] = OVLxC1_PPL(var->xres) | OVLxC1_LPO(var->yres) | 848 ofb->control[0] = OVLxC1_PPL(var->xres) | OVLxC1_LPO(var->yres) |
@@ -891,7 +886,7 @@ static void __devinit init_pxafb_overlay(struct pxafb_info *fbi,
891 886
892 ofb->id = id; 887 ofb->id = id;
893 ofb->ops = &ofb_ops[id]; 888 ofb->ops = &ofb_ops[id];
894 atomic_set(&ofb->usage, 0); 889 ofb->usage = 0;
895 ofb->fbi = fbi; 890 ofb->fbi = fbi;
896 init_completion(&ofb->branch_done); 891 init_completion(&ofb->branch_done);
897} 892}
@@ -904,29 +899,60 @@ static inline int pxafb_overlay_supported(void)
904 return 0; 899 return 0;
905} 900}
906 901
907static int __devinit pxafb_overlay_init(struct pxafb_info *fbi) 902static int __devinit pxafb_overlay_map_video_memory(struct pxafb_info *pxafb,
903 struct pxafb_layer *ofb)
904{
905 /* We assume that user will use at most video_mem_size for overlay fb,
906 * anyway, it's useless to use 16bpp main plane and 24bpp overlay
907 */
908 ofb->video_mem = alloc_pages_exact(PAGE_ALIGN(pxafb->video_mem_size),
909 GFP_KERNEL | __GFP_ZERO);
910 if (ofb->video_mem == NULL)
911 return -ENOMEM;
912
913 ofb->video_mem_phys = virt_to_phys(ofb->video_mem);
914 ofb->video_mem_size = PAGE_ALIGN(pxafb->video_mem_size);
915
916 mutex_lock(&ofb->fb.mm_lock);
917 ofb->fb.fix.smem_start = ofb->video_mem_phys;
918 ofb->fb.fix.smem_len = pxafb->video_mem_size;
919 mutex_unlock(&ofb->fb.mm_lock);
920
921 ofb->fb.screen_base = ofb->video_mem;
922
923 return 0;
924}
925
926static void __devinit pxafb_overlay_init(struct pxafb_info *fbi)
908{ 927{
909 int i, ret; 928 int i, ret;
910 929
911 if (!pxafb_overlay_supported()) 930 if (!pxafb_overlay_supported())
912 return 0; 931 return;
913 932
914 for (i = 0; i < 2; i++) { 933 for (i = 0; i < 2; i++) {
915 init_pxafb_overlay(fbi, &fbi->overlay[i], i); 934 struct pxafb_layer *ofb = &fbi->overlay[i];
916 ret = register_framebuffer(&fbi->overlay[i].fb); 935 init_pxafb_overlay(fbi, ofb, i);
936 ret = register_framebuffer(&ofb->fb);
917 if (ret) { 937 if (ret) {
918 dev_err(fbi->dev, "failed to register overlay %d\n", i); 938 dev_err(fbi->dev, "failed to register overlay %d\n", i);
919 return ret; 939 continue;
920 } 940 }
941 ret = pxafb_overlay_map_video_memory(fbi, ofb);
942 if (ret) {
943 dev_err(fbi->dev,
944 "failed to map video memory for overlay %d\n",
945 i);
946 unregister_framebuffer(&ofb->fb);
947 continue;
948 }
949 ofb->registered = 1;
921 } 950 }
922 951
923 /* mask all IU/BS/EOF/SOF interrupts */ 952 /* mask all IU/BS/EOF/SOF interrupts */
924 lcd_writel(fbi, LCCR5, ~0); 953 lcd_writel(fbi, LCCR5, ~0);
925 954
926 /* place overlay(s) on top of base */
927 fbi->lccr0 |= LCCR0_OUC;
928 pr_info("PXA Overlay driver loaded successfully!\n"); 955 pr_info("PXA Overlay driver loaded successfully!\n");
929 return 0;
930} 956}
931 957
932static void __devexit pxafb_overlay_exit(struct pxafb_info *fbi) 958static void __devexit pxafb_overlay_exit(struct pxafb_info *fbi)
@@ -936,8 +962,15 @@ static void __devexit pxafb_overlay_exit(struct pxafb_info *fbi)
936 if (!pxafb_overlay_supported()) 962 if (!pxafb_overlay_supported())
937 return; 963 return;
938 964
939 for (i = 0; i < 2; i++) 965 for (i = 0; i < 2; i++) {
940 unregister_framebuffer(&fbi->overlay[i].fb); 966 struct pxafb_layer *ofb = &fbi->overlay[i];
967 if (ofb->registered) {
968 if (ofb->video_mem)
969 free_pages_exact(ofb->video_mem,
970 ofb->video_mem_size);
971 unregister_framebuffer(&ofb->fb);
972 }
973 }
941} 974}
942#else 975#else
943static inline void pxafb_overlay_init(struct pxafb_info *fbi) {} 976static inline void pxafb_overlay_init(struct pxafb_info *fbi) {}
@@ -1368,7 +1401,8 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var,
1368 (lcd_readl(fbi, LCCR3) != fbi->reg_lccr3) || 1401 (lcd_readl(fbi, LCCR3) != fbi->reg_lccr3) ||
1369 (lcd_readl(fbi, LCCR4) != fbi->reg_lccr4) || 1402 (lcd_readl(fbi, LCCR4) != fbi->reg_lccr4) ||
1370 (lcd_readl(fbi, FDADR0) != fbi->fdadr[0]) || 1403 (lcd_readl(fbi, FDADR0) != fbi->fdadr[0]) ||
1371 (lcd_readl(fbi, FDADR1) != fbi->fdadr[1])) 1404 ((fbi->lccr0 & LCCR0_SDS) &&
1405 (lcd_readl(fbi, FDADR1) != fbi->fdadr[1])))
1372 pxafb_schedule_work(fbi, C_REENABLE); 1406 pxafb_schedule_work(fbi, C_REENABLE);
1373 1407
1374 return 0; 1408 return 0;
@@ -1420,7 +1454,8 @@ static void pxafb_enable_controller(struct pxafb_info *fbi)
1420 lcd_writel(fbi, LCCR0, fbi->reg_lccr0 & ~LCCR0_ENB); 1454 lcd_writel(fbi, LCCR0, fbi->reg_lccr0 & ~LCCR0_ENB);
1421 1455
1422 lcd_writel(fbi, FDADR0, fbi->fdadr[0]); 1456 lcd_writel(fbi, FDADR0, fbi->fdadr[0]);
1423 lcd_writel(fbi, FDADR1, fbi->fdadr[1]); 1457 if (fbi->lccr0 & LCCR0_SDS)
1458 lcd_writel(fbi, FDADR1, fbi->fdadr[1]);
1424 lcd_writel(fbi, LCCR0, fbi->reg_lccr0 | LCCR0_ENB); 1459 lcd_writel(fbi, LCCR0, fbi->reg_lccr0 | LCCR0_ENB);
1425} 1460}
1426 1461
@@ -1613,7 +1648,10 @@ pxafb_freq_transition(struct notifier_block *nb, unsigned long val, void *data)
1613 1648
1614 switch (val) { 1649 switch (val) {
1615 case CPUFREQ_PRECHANGE: 1650 case CPUFREQ_PRECHANGE:
1616 set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE); 1651#ifdef CONFIG_FB_PXA_OVERLAY
1652 if (!(fbi->overlay[0].usage || fbi->overlay[1].usage))
1653#endif
1654 set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE);
1617 break; 1655 break;
1618 1656
1619 case CPUFREQ_POSTCHANGE: 1657 case CPUFREQ_POSTCHANGE:
@@ -1806,6 +1844,12 @@ static struct pxafb_info * __devinit pxafb_init_fbinfo(struct device *dev)
1806 1844
1807 pxafb_decode_mach_info(fbi, inf); 1845 pxafb_decode_mach_info(fbi, inf);
1808 1846
1847#ifdef CONFIG_FB_PXA_OVERLAY
1848 /* place overlay(s) on top of base */
1849 if (pxafb_overlay_supported())
1850 fbi->lccr0 |= LCCR0_OUC;
1851#endif
1852
1809 init_waitqueue_head(&fbi->ctrlr_wait); 1853 init_waitqueue_head(&fbi->ctrlr_wait);
1810 INIT_WORK(&fbi->task, pxafb_task); 1854 INIT_WORK(&fbi->task, pxafb_task);
1811 mutex_init(&fbi->ctrlr_lock); 1855 mutex_init(&fbi->ctrlr_lock);
diff --git a/drivers/video/pxafb.h b/drivers/video/pxafb.h
index 2353521c5c8c..26ba9fa3f737 100644
--- a/drivers/video/pxafb.h
+++ b/drivers/video/pxafb.h
@@ -92,7 +92,8 @@ struct pxafb_layer_ops {
92struct pxafb_layer { 92struct pxafb_layer {
93 struct fb_info fb; 93 struct fb_info fb;
94 int id; 94 int id;
95 atomic_t usage; 95 int registered;
96 uint32_t usage;
96 uint32_t control[2]; 97 uint32_t control[2];
97 98
98 struct pxafb_layer_ops *ops; 99 struct pxafb_layer_ops *ops;
diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c
index fc32c323a381..f5a39f5aa900 100644
--- a/drivers/video/q40fb.c
+++ b/drivers/video/q40fb.c
@@ -28,7 +28,7 @@
28 28
29#define Q40_PHYS_SCREEN_ADDR 0xFE800000 29#define Q40_PHYS_SCREEN_ADDR 0xFE800000
30 30
31static struct fb_fix_screeninfo q40fb_fix __initdata = { 31static struct fb_fix_screeninfo q40fb_fix __devinitdata = {
32 .id = "Q40", 32 .id = "Q40",
33 .smem_len = 1024*1024, 33 .smem_len = 1024*1024,
34 .type = FB_TYPE_PACKED_PIXELS, 34 .type = FB_TYPE_PACKED_PIXELS,
@@ -37,7 +37,7 @@ static struct fb_fix_screeninfo q40fb_fix __initdata = {
37 .accel = FB_ACCEL_NONE, 37 .accel = FB_ACCEL_NONE,
38}; 38};
39 39
40static struct fb_var_screeninfo q40fb_var __initdata = { 40static struct fb_var_screeninfo q40fb_var __devinitdata = {
41 .xres = 1024, 41 .xres = 1024,
42 .yres = 512, 42 .yres = 512,
43 .xres_virtual = 1024, 43 .xres_virtual = 1024,
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 618f36bec10d..d8ab7be4fd6b 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -331,7 +331,7 @@ static int riva_bl_get_brightness(struct backlight_device *bd)
331 return bd->props.brightness; 331 return bd->props.brightness;
332} 332}
333 333
334static struct backlight_ops riva_bl_ops = { 334static const struct backlight_ops riva_bl_ops = {
335 .get_brightness = riva_bl_get_brightness, 335 .get_brightness = riva_bl_get_brightness,
336 .update_status = riva_bl_update_status, 336 .update_status = riva_bl_update_status,
337}; 337};
@@ -355,6 +355,7 @@ static void riva_bl_init(struct riva_par *par)
355 snprintf(name, sizeof(name), "rivabl%d", info->node); 355 snprintf(name, sizeof(name), "rivabl%d", info->node);
356 356
357 memset(&props, 0, sizeof(struct backlight_properties)); 357 memset(&props, 0, sizeof(struct backlight_properties));
358 props.type = BACKLIGHT_RAW;
358 props.max_brightness = FB_BACKLIGHT_LEVELS - 1; 359 props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
359 bd = backlight_device_register(name, info->dev, par, &riva_bl_ops, 360 bd = backlight_device_register(name, info->dev, par, &riva_bl_ops,
360 &props); 361 &props);
diff --git a/drivers/video/riva/rivafb-i2c.c b/drivers/video/riva/rivafb-i2c.c
index a0e22ac483a3..167400e2a182 100644
--- a/drivers/video/riva/rivafb-i2c.c
+++ b/drivers/video/riva/rivafb-i2c.c
@@ -94,7 +94,6 @@ static int __devinit riva_setup_i2c_bus(struct riva_i2c_chan *chan,
94 94
95 strcpy(chan->adapter.name, name); 95 strcpy(chan->adapter.name, name);
96 chan->adapter.owner = THIS_MODULE; 96 chan->adapter.owner = THIS_MODULE;
97 chan->adapter.id = I2C_HW_B_RIVA;
98 chan->adapter.class = i2c_class; 97 chan->adapter.class = i2c_class;
99 chan->adapter.algo_data = &chan->algo; 98 chan->adapter.algo_data = &chan->algo;
100 chan->adapter.dev.parent = &chan->par->pdev->dev; 99 chan->adapter.dev.parent = &chan->par->pdev->dev;
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c
index a6247fc081ab..28b1c6c3d8ac 100644
--- a/drivers/video/s1d13xxxfb.c
+++ b/drivers/video/s1d13xxxfb.c
@@ -410,28 +410,6 @@ s1d13xxxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
410 ************************************************************/ 410 ************************************************************/
411 411
412/** 412/**
413 * bltbit_wait_bitset - waits for change in register value
414 * @info : framebuffer structure
415 * @bit : value expected in register
416 * @timeout : ...
417 *
418 * waits until value changes INTO bit
419 */
420static u8
421bltbit_wait_bitset(struct fb_info *info, u8 bit, int timeout)
422{
423 while (!(s1d13xxxfb_readreg(info->par, S1DREG_BBLT_CTL0) & bit)) {
424 udelay(10);
425 if (!--timeout) {
426 dbg_blit("wait_bitset timeout\n");
427 break;
428 }
429 }
430
431 return timeout;
432}
433
434/**
435 * bltbit_wait_bitclear - waits for change in register value 413 * bltbit_wait_bitclear - waits for change in register value
436 * @info : frambuffer structure 414 * @info : frambuffer structure
437 * @bit : value currently in register 415 * @bit : value currently in register
@@ -454,34 +432,6 @@ bltbit_wait_bitclear(struct fb_info *info, u8 bit, int timeout)
454 return timeout; 432 return timeout;
455} 433}
456 434
457/**
458 * bltbit_fifo_status - checks the current status of the fifo
459 * @info : framebuffer structure
460 *
461 * returns number of free words in buffer
462 */
463static u8
464bltbit_fifo_status(struct fb_info *info)
465{
466 u8 status;
467
468 status = s1d13xxxfb_readreg(info->par, S1DREG_BBLT_CTL0);
469
470 /* its empty so room for 16 words */
471 if (status & BBLT_FIFO_EMPTY)
472 return 16;
473
474 /* its full so we dont want to add */
475 if (status & BBLT_FIFO_FULL)
476 return 0;
477
478 /* its atleast half full but we can add one atleast */
479 if (status & BBLT_FIFO_NOT_FULL)
480 return 1;
481
482 return 0;
483}
484
485/* 435/*
486 * s1d13xxxfb_bitblt_copyarea - accelerated copyarea function 436 * s1d13xxxfb_bitblt_copyarea - accelerated copyarea function
487 * @info : framebuffer structure 437 * @info : framebuffer structure
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index f9aca9d13d1b..4aecf213c9be 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -23,6 +23,7 @@
23#include <linux/io.h> 23#include <linux/io.h>
24#include <linux/uaccess.h> 24#include <linux/uaccess.h>
25#include <linux/interrupt.h> 25#include <linux/interrupt.h>
26#include <linux/pm_runtime.h>
26 27
27#include <mach/map.h> 28#include <mach/map.h>
28#include <plat/regs-fb-v4.h> 29#include <plat/regs-fb-v4.h>
@@ -47,7 +48,7 @@
47#undef writel 48#undef writel
48#define writel(v, r) do { \ 49#define writel(v, r) do { \
49 printk(KERN_DEBUG "%s: %08x => %p\n", __func__, (unsigned int)v, r); \ 50 printk(KERN_DEBUG "%s: %08x => %p\n", __func__, (unsigned int)v, r); \
50 __raw_writel(v, r); } while(0) 51 __raw_writel(v, r); } while (0)
51#endif /* FB_S3C_DEBUG_REGWRITE */ 52#endif /* FB_S3C_DEBUG_REGWRITE */
52 53
53/* irq_flags bits */ 54/* irq_flags bits */
@@ -181,6 +182,7 @@ struct s3c_fb_vsync {
181 182
182/** 183/**
183 * struct s3c_fb - overall hardware state of the hardware 184 * struct s3c_fb - overall hardware state of the hardware
185 * @slock: The spinlock protection for this data sturcture.
184 * @dev: The device that we bound to, for printing, etc. 186 * @dev: The device that we bound to, for printing, etc.
185 * @regs_res: The resource we claimed for the IO registers. 187 * @regs_res: The resource we claimed for the IO registers.
186 * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk. 188 * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk.
@@ -194,6 +196,7 @@ struct s3c_fb_vsync {
194 * @vsync_info: VSYNC-related information (count, queues...) 196 * @vsync_info: VSYNC-related information (count, queues...)
195 */ 197 */
196struct s3c_fb { 198struct s3c_fb {
199 spinlock_t slock;
197 struct device *dev; 200 struct device *dev;
198 struct resource *regs_res; 201 struct resource *regs_res;
199 struct clk *bus_clk; 202 struct clk *bus_clk;
@@ -232,13 +235,12 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
232 struct fb_info *info) 235 struct fb_info *info)
233{ 236{
234 struct s3c_fb_win *win = info->par; 237 struct s3c_fb_win *win = info->par;
235 struct s3c_fb_pd_win *windata = win->windata;
236 struct s3c_fb *sfb = win->parent; 238 struct s3c_fb *sfb = win->parent;
237 239
238 dev_dbg(sfb->dev, "checking parameters\n"); 240 dev_dbg(sfb->dev, "checking parameters\n");
239 241
240 var->xres_virtual = max((unsigned int)windata->virtual_x, var->xres); 242 var->xres_virtual = max(var->xres_virtual, var->xres);
241 var->yres_virtual = max((unsigned int)windata->virtual_y, var->yres); 243 var->yres_virtual = max(var->yres_virtual, var->yres);
242 244
243 if (!s3c_fb_validate_win_bpp(win, var->bits_per_pixel)) { 245 if (!s3c_fb_validate_win_bpp(win, var->bits_per_pixel)) {
244 dev_dbg(sfb->dev, "win %d: unsupported bpp %d\n", 246 dev_dbg(sfb->dev, "win %d: unsupported bpp %d\n",
@@ -299,6 +301,7 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
299 var->blue.length = 5; 301 var->blue.length = 5;
300 break; 302 break;
301 303
304 case 32:
302 case 28: 305 case 28:
303 case 25: 306 case 25:
304 var->transp.length = var->bits_per_pixel - 24; 307 var->transp.length = var->bits_per_pixel - 24;
@@ -307,7 +310,6 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
307 case 24: 310 case 24:
308 /* our 24bpp is unpacked, so 32bpp */ 311 /* our 24bpp is unpacked, so 32bpp */
309 var->bits_per_pixel = 32; 312 var->bits_per_pixel = 32;
310 case 32:
311 var->red.offset = 16; 313 var->red.offset = 16;
312 var->red.length = 8; 314 var->red.length = 8;
313 var->green.offset = 8; 315 var->green.offset = 8;
@@ -517,7 +519,7 @@ static int s3c_fb_set_par(struct fb_info *info)
517 519
518 data = VIDTCON2_LINEVAL(var->yres - 1) | 520 data = VIDTCON2_LINEVAL(var->yres - 1) |
519 VIDTCON2_HOZVAL(var->xres - 1); 521 VIDTCON2_HOZVAL(var->xres - 1);
520 writel(data, regs +sfb->variant.vidtcon + 8 ); 522 writel(data, regs + sfb->variant.vidtcon + 8);
521 } 523 }
522 524
523 /* write the buffer address */ 525 /* write the buffer address */
@@ -555,6 +557,13 @@ static int s3c_fb_set_par(struct fb_info *info)
555 vidosd_set_alpha(win, alpha); 557 vidosd_set_alpha(win, alpha);
556 vidosd_set_size(win, data); 558 vidosd_set_size(win, data);
557 559
560 /* Enable DMA channel for this window */
561 if (sfb->variant.has_shadowcon) {
562 data = readl(sfb->regs + SHADOWCON);
563 data |= SHADOWCON_CHx_ENABLE(win_no);
564 writel(data, sfb->regs + SHADOWCON);
565 }
566
558 data = WINCONx_ENWIN; 567 data = WINCONx_ENWIN;
559 568
560 /* note, since we have to round up the bits-per-pixel, we end up 569 /* note, since we have to round up the bits-per-pixel, we end up
@@ -634,13 +643,6 @@ static int s3c_fb_set_par(struct fb_info *info)
634 writel(data, regs + sfb->variant.wincon + (win_no * 4)); 643 writel(data, regs + sfb->variant.wincon + (win_no * 4));
635 writel(0x0, regs + sfb->variant.winmap + (win_no * 4)); 644 writel(0x0, regs + sfb->variant.winmap + (win_no * 4));
636 645
637 /* Enable DMA channel for this window */
638 if (sfb->variant.has_shadowcon) {
639 data = readl(sfb->regs + SHADOWCON);
640 data |= SHADOWCON_CHx_ENABLE(win_no);
641 writel(data, sfb->regs + SHADOWCON);
642 }
643
644 shadow_protect_win(win, 0); 646 shadow_protect_win(win, 0);
645 647
646 return 0; 648 return 0;
@@ -946,6 +948,8 @@ static irqreturn_t s3c_fb_irq(int irq, void *dev_id)
946 void __iomem *regs = sfb->regs; 948 void __iomem *regs = sfb->regs;
947 u32 irq_sts_reg; 949 u32 irq_sts_reg;
948 950
951 spin_lock(&sfb->slock);
952
949 irq_sts_reg = readl(regs + VIDINTCON1); 953 irq_sts_reg = readl(regs + VIDINTCON1);
950 954
951 if (irq_sts_reg & VIDINTCON1_INT_FRAME) { 955 if (irq_sts_reg & VIDINTCON1_INT_FRAME) {
@@ -962,6 +966,7 @@ static irqreturn_t s3c_fb_irq(int irq, void *dev_id)
962 */ 966 */
963 s3c_fb_disable_irq(sfb); 967 s3c_fb_disable_irq(sfb);
964 968
969 spin_unlock(&sfb->slock);
965 return IRQ_HANDLED; 970 return IRQ_HANDLED;
966} 971}
967 972
@@ -1013,8 +1018,30 @@ static int s3c_fb_ioctl(struct fb_info *info, unsigned int cmd,
1013 return ret; 1018 return ret;
1014} 1019}
1015 1020
1021static int s3c_fb_open(struct fb_info *info, int user)
1022{
1023 struct s3c_fb_win *win = info->par;
1024 struct s3c_fb *sfb = win->parent;
1025
1026 pm_runtime_get_sync(sfb->dev);
1027
1028 return 0;
1029}
1030
1031static int s3c_fb_release(struct fb_info *info, int user)
1032{
1033 struct s3c_fb_win *win = info->par;
1034 struct s3c_fb *sfb = win->parent;
1035
1036 pm_runtime_put_sync(sfb->dev);
1037
1038 return 0;
1039}
1040
1016static struct fb_ops s3c_fb_ops = { 1041static struct fb_ops s3c_fb_ops = {
1017 .owner = THIS_MODULE, 1042 .owner = THIS_MODULE,
1043 .fb_open = s3c_fb_open,
1044 .fb_release = s3c_fb_release,
1018 .fb_check_var = s3c_fb_check_var, 1045 .fb_check_var = s3c_fb_check_var,
1019 .fb_set_par = s3c_fb_set_par, 1046 .fb_set_par = s3c_fb_set_par,
1020 .fb_blank = s3c_fb_blank, 1047 .fb_blank = s3c_fb_blank,
@@ -1281,6 +1308,7 @@ static void s3c_fb_clear_win(struct s3c_fb *sfb, int win)
1281 1308
1282static int __devinit s3c_fb_probe(struct platform_device *pdev) 1309static int __devinit s3c_fb_probe(struct platform_device *pdev)
1283{ 1310{
1311 const struct platform_device_id *platid;
1284 struct s3c_fb_driverdata *fbdrv; 1312 struct s3c_fb_driverdata *fbdrv;
1285 struct device *dev = &pdev->dev; 1313 struct device *dev = &pdev->dev;
1286 struct s3c_fb_platdata *pd; 1314 struct s3c_fb_platdata *pd;
@@ -1289,7 +1317,8 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
1289 int win; 1317 int win;
1290 int ret = 0; 1318 int ret = 0;
1291 1319
1292 fbdrv = (struct s3c_fb_driverdata *)platform_get_device_id(pdev)->driver_data; 1320 platid = platform_get_device_id(pdev);
1321 fbdrv = (struct s3c_fb_driverdata *)platid->driver_data;
1293 1322
1294 if (fbdrv->variant.nr_windows > S3C_FB_MAX_WIN) { 1323 if (fbdrv->variant.nr_windows > S3C_FB_MAX_WIN) {
1295 dev_err(dev, "too many windows, cannot attach\n"); 1324 dev_err(dev, "too many windows, cannot attach\n");
@@ -1314,14 +1343,19 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
1314 sfb->pdata = pd; 1343 sfb->pdata = pd;
1315 sfb->variant = fbdrv->variant; 1344 sfb->variant = fbdrv->variant;
1316 1345
1346 spin_lock_init(&sfb->slock);
1347
1317 sfb->bus_clk = clk_get(dev, "lcd"); 1348 sfb->bus_clk = clk_get(dev, "lcd");
1318 if (IS_ERR(sfb->bus_clk)) { 1349 if (IS_ERR(sfb->bus_clk)) {
1319 dev_err(dev, "failed to get bus clock\n"); 1350 dev_err(dev, "failed to get bus clock\n");
1351 ret = PTR_ERR(sfb->bus_clk);
1320 goto err_sfb; 1352 goto err_sfb;
1321 } 1353 }
1322 1354
1323 clk_enable(sfb->bus_clk); 1355 clk_enable(sfb->bus_clk);
1324 1356
1357 pm_runtime_enable(sfb->dev);
1358
1325 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1359 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1326 if (!res) { 1360 if (!res) {
1327 dev_err(dev, "failed to find registers\n"); 1361 dev_err(dev, "failed to find registers\n");
@@ -1360,6 +1394,9 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
1360 1394
1361 dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs); 1395 dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs);
1362 1396
1397 platform_set_drvdata(pdev, sfb);
1398 pm_runtime_get_sync(sfb->dev);
1399
1363 /* setup gpio and output polarity controls */ 1400 /* setup gpio and output polarity controls */
1364 1401
1365 pd->setup_gpio(); 1402 pd->setup_gpio();
@@ -1400,6 +1437,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
1400 } 1437 }
1401 1438
1402 platform_set_drvdata(pdev, sfb); 1439 platform_set_drvdata(pdev, sfb);
1440 pm_runtime_put_sync(sfb->dev);
1403 1441
1404 return 0; 1442 return 0;
1405 1443
@@ -1410,8 +1448,7 @@ err_ioremap:
1410 iounmap(sfb->regs); 1448 iounmap(sfb->regs);
1411 1449
1412err_req_region: 1450err_req_region:
1413 release_resource(sfb->regs_res); 1451 release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res));
1414 kfree(sfb->regs_res);
1415 1452
1416err_clk: 1453err_clk:
1417 clk_disable(sfb->bus_clk); 1454 clk_disable(sfb->bus_clk);
@@ -1434,6 +1471,8 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
1434 struct s3c_fb *sfb = platform_get_drvdata(pdev); 1471 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1435 int win; 1472 int win;
1436 1473
1474 pm_runtime_get_sync(sfb->dev);
1475
1437 for (win = 0; win < S3C_FB_MAX_WIN; win++) 1476 for (win = 0; win < S3C_FB_MAX_WIN; win++)
1438 if (sfb->windows[win]) 1477 if (sfb->windows[win])
1439 s3c_fb_release_win(sfb, sfb->windows[win]); 1478 s3c_fb_release_win(sfb, sfb->windows[win]);
@@ -1445,17 +1484,78 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
1445 clk_disable(sfb->bus_clk); 1484 clk_disable(sfb->bus_clk);
1446 clk_put(sfb->bus_clk); 1485 clk_put(sfb->bus_clk);
1447 1486
1448 release_resource(sfb->regs_res); 1487 release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res));
1449 kfree(sfb->regs_res);
1450 1488
1451 kfree(sfb); 1489 pm_runtime_put_sync(sfb->dev);
1490 pm_runtime_disable(sfb->dev);
1452 1491
1492 kfree(sfb);
1453 return 0; 1493 return 0;
1454} 1494}
1455 1495
1456#ifdef CONFIG_PM 1496#ifdef CONFIG_PM
1457static int s3c_fb_suspend(struct platform_device *pdev, pm_message_t state) 1497static int s3c_fb_suspend(struct device *dev)
1498{
1499 struct platform_device *pdev = to_platform_device(dev);
1500 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1501 struct s3c_fb_win *win;
1502 int win_no;
1503
1504 for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) {
1505 win = sfb->windows[win_no];
1506 if (!win)
1507 continue;
1508
1509 /* use the blank function to push into power-down */
1510 s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
1511 }
1512
1513 clk_disable(sfb->bus_clk);
1514 return 0;
1515}
1516
1517static int s3c_fb_resume(struct device *dev)
1518{
1519 struct platform_device *pdev = to_platform_device(dev);
1520 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1521 struct s3c_fb_platdata *pd = sfb->pdata;
1522 struct s3c_fb_win *win;
1523 int win_no;
1524
1525 clk_enable(sfb->bus_clk);
1526
1527 /* setup gpio and output polarity controls */
1528 pd->setup_gpio();
1529 writel(pd->vidcon1, sfb->regs + VIDCON1);
1530
1531 /* zero all windows before we do anything */
1532 for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++)
1533 s3c_fb_clear_win(sfb, win_no);
1534
1535 for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) {
1536 void __iomem *regs = sfb->regs + sfb->variant.keycon;
1537
1538 regs += (win_no * 8);
1539 writel(0xffffff, regs + WKEYCON0);
1540 writel(0xffffff, regs + WKEYCON1);
1541 }
1542
1543 /* restore framebuffers */
1544 for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) {
1545 win = sfb->windows[win_no];
1546 if (!win)
1547 continue;
1548
1549 dev_dbg(&pdev->dev, "resuming window %d\n", win_no);
1550 s3c_fb_set_par(win->fbinfo);
1551 }
1552
1553 return 0;
1554}
1555
1556static int s3c_fb_runtime_suspend(struct device *dev)
1458{ 1557{
1558 struct platform_device *pdev = to_platform_device(dev);
1459 struct s3c_fb *sfb = platform_get_drvdata(pdev); 1559 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1460 struct s3c_fb_win *win; 1560 struct s3c_fb_win *win;
1461 int win_no; 1561 int win_no;
@@ -1473,8 +1573,9 @@ static int s3c_fb_suspend(struct platform_device *pdev, pm_message_t state)
1473 return 0; 1573 return 0;
1474} 1574}
1475 1575
1476static int s3c_fb_resume(struct platform_device *pdev) 1576static int s3c_fb_runtime_resume(struct device *dev)
1477{ 1577{
1578 struct platform_device *pdev = to_platform_device(dev);
1478 struct s3c_fb *sfb = platform_get_drvdata(pdev); 1579 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1479 struct s3c_fb_platdata *pd = sfb->pdata; 1580 struct s3c_fb_platdata *pd = sfb->pdata;
1480 struct s3c_fb_win *win; 1581 struct s3c_fb_win *win;
@@ -1482,7 +1583,8 @@ static int s3c_fb_resume(struct platform_device *pdev)
1482 1583
1483 clk_enable(sfb->bus_clk); 1584 clk_enable(sfb->bus_clk);
1484 1585
1485 /* setup registers */ 1586 /* setup gpio and output polarity controls */
1587 pd->setup_gpio();
1486 writel(pd->vidcon1, sfb->regs + VIDCON1); 1588 writel(pd->vidcon1, sfb->regs + VIDCON1);
1487 1589
1488 /* zero all windows before we do anything */ 1590 /* zero all windows before we do anything */
@@ -1509,9 +1611,12 @@ static int s3c_fb_resume(struct platform_device *pdev)
1509 1611
1510 return 0; 1612 return 0;
1511} 1613}
1614
1512#else 1615#else
1513#define s3c_fb_suspend NULL 1616#define s3c_fb_suspend NULL
1514#define s3c_fb_resume NULL 1617#define s3c_fb_resume NULL
1618#define s3c_fb_runtime_suspend NULL
1619#define s3c_fb_runtime_resume NULL
1515#endif 1620#endif
1516 1621
1517 1622
@@ -1523,28 +1628,31 @@ static struct s3c_fb_win_variant s3c_fb_data_64xx_wins[] = {
1523 .has_osd_c = 1, 1628 .has_osd_c = 1,
1524 .osd_size_off = 0x8, 1629 .osd_size_off = 0x8,
1525 .palette_sz = 256, 1630 .palette_sz = 256,
1526 .valid_bpp = VALID_BPP1248 | VALID_BPP(16) | VALID_BPP(24), 1631 .valid_bpp = (VALID_BPP1248 | VALID_BPP(16) |
1632 VALID_BPP(18) | VALID_BPP(24)),
1527 }, 1633 },
1528 [1] = { 1634 [1] = {
1529 .has_osd_c = 1, 1635 .has_osd_c = 1,
1530 .has_osd_d = 1, 1636 .has_osd_d = 1,
1531 .osd_size_off = 0x12, 1637 .osd_size_off = 0xc,
1532 .has_osd_alpha = 1, 1638 .has_osd_alpha = 1,
1533 .palette_sz = 256, 1639 .palette_sz = 256,
1534 .valid_bpp = (VALID_BPP1248 | VALID_BPP(16) | 1640 .valid_bpp = (VALID_BPP1248 | VALID_BPP(16) |
1535 VALID_BPP(18) | VALID_BPP(19) | 1641 VALID_BPP(18) | VALID_BPP(19) |
1536 VALID_BPP(24) | VALID_BPP(25)), 1642 VALID_BPP(24) | VALID_BPP(25) |
1643 VALID_BPP(28)),
1537 }, 1644 },
1538 [2] = { 1645 [2] = {
1539 .has_osd_c = 1, 1646 .has_osd_c = 1,
1540 .has_osd_d = 1, 1647 .has_osd_d = 1,
1541 .osd_size_off = 0x12, 1648 .osd_size_off = 0xc,
1542 .has_osd_alpha = 1, 1649 .has_osd_alpha = 1,
1543 .palette_sz = 16, 1650 .palette_sz = 16,
1544 .palette_16bpp = 1, 1651 .palette_16bpp = 1,
1545 .valid_bpp = (VALID_BPP1248 | VALID_BPP(16) | 1652 .valid_bpp = (VALID_BPP1248 | VALID_BPP(16) |
1546 VALID_BPP(18) | VALID_BPP(19) | 1653 VALID_BPP(18) | VALID_BPP(19) |
1547 VALID_BPP(24) | VALID_BPP(25)), 1654 VALID_BPP(24) | VALID_BPP(25) |
1655 VALID_BPP(28)),
1548 }, 1656 },
1549 [3] = { 1657 [3] = {
1550 .has_osd_c = 1, 1658 .has_osd_c = 1,
@@ -1553,7 +1661,8 @@ static struct s3c_fb_win_variant s3c_fb_data_64xx_wins[] = {
1553 .palette_16bpp = 1, 1661 .palette_16bpp = 1,
1554 .valid_bpp = (VALID_BPP124 | VALID_BPP(16) | 1662 .valid_bpp = (VALID_BPP124 | VALID_BPP(16) |
1555 VALID_BPP(18) | VALID_BPP(19) | 1663 VALID_BPP(18) | VALID_BPP(19) |
1556 VALID_BPP(24) | VALID_BPP(25)), 1664 VALID_BPP(24) | VALID_BPP(25) |
1665 VALID_BPP(28)),
1557 }, 1666 },
1558 [4] = { 1667 [4] = {
1559 .has_osd_c = 1, 1668 .has_osd_c = 1,
@@ -1562,7 +1671,65 @@ static struct s3c_fb_win_variant s3c_fb_data_64xx_wins[] = {
1562 .palette_16bpp = 1, 1671 .palette_16bpp = 1,
1563 .valid_bpp = (VALID_BPP(1) | VALID_BPP(2) | 1672 .valid_bpp = (VALID_BPP(1) | VALID_BPP(2) |
1564 VALID_BPP(16) | VALID_BPP(18) | 1673 VALID_BPP(16) | VALID_BPP(18) |
1565 VALID_BPP(24) | VALID_BPP(25)), 1674 VALID_BPP(19) | VALID_BPP(24) |
1675 VALID_BPP(25) | VALID_BPP(28)),
1676 },
1677};
1678
1679static struct s3c_fb_win_variant s3c_fb_data_s5p_wins[] = {
1680 [0] = {
1681 .has_osd_c = 1,
1682 .osd_size_off = 0x8,
1683 .palette_sz = 256,
1684 .valid_bpp = (VALID_BPP1248 | VALID_BPP(13) |
1685 VALID_BPP(15) | VALID_BPP(16) |
1686 VALID_BPP(18) | VALID_BPP(19) |
1687 VALID_BPP(24) | VALID_BPP(25) |
1688 VALID_BPP(32)),
1689 },
1690 [1] = {
1691 .has_osd_c = 1,
1692 .has_osd_d = 1,
1693 .osd_size_off = 0xc,
1694 .has_osd_alpha = 1,
1695 .palette_sz = 256,
1696 .valid_bpp = (VALID_BPP1248 | VALID_BPP(13) |
1697 VALID_BPP(15) | VALID_BPP(16) |
1698 VALID_BPP(18) | VALID_BPP(19) |
1699 VALID_BPP(24) | VALID_BPP(25) |
1700 VALID_BPP(32)),
1701 },
1702 [2] = {
1703 .has_osd_c = 1,
1704 .has_osd_d = 1,
1705 .osd_size_off = 0xc,
1706 .has_osd_alpha = 1,
1707 .palette_sz = 256,
1708 .valid_bpp = (VALID_BPP1248 | VALID_BPP(13) |
1709 VALID_BPP(15) | VALID_BPP(16) |
1710 VALID_BPP(18) | VALID_BPP(19) |
1711 VALID_BPP(24) | VALID_BPP(25) |
1712 VALID_BPP(32)),
1713 },
1714 [3] = {
1715 .has_osd_c = 1,
1716 .has_osd_alpha = 1,
1717 .palette_sz = 256,
1718 .valid_bpp = (VALID_BPP1248 | VALID_BPP(13) |
1719 VALID_BPP(15) | VALID_BPP(16) |
1720 VALID_BPP(18) | VALID_BPP(19) |
1721 VALID_BPP(24) | VALID_BPP(25) |
1722 VALID_BPP(32)),
1723 },
1724 [4] = {
1725 .has_osd_c = 1,
1726 .has_osd_alpha = 1,
1727 .palette_sz = 256,
1728 .valid_bpp = (VALID_BPP1248 | VALID_BPP(13) |
1729 VALID_BPP(15) | VALID_BPP(16) |
1730 VALID_BPP(18) | VALID_BPP(19) |
1731 VALID_BPP(24) | VALID_BPP(25) |
1732 VALID_BPP(32)),
1566 }, 1733 },
1567}; 1734};
1568 1735
@@ -1619,11 +1786,11 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pc100 = {
1619 1786
1620 .has_prtcon = 1, 1787 .has_prtcon = 1,
1621 }, 1788 },
1622 .win[0] = &s3c_fb_data_64xx_wins[0], 1789 .win[0] = &s3c_fb_data_s5p_wins[0],
1623 .win[1] = &s3c_fb_data_64xx_wins[1], 1790 .win[1] = &s3c_fb_data_s5p_wins[1],
1624 .win[2] = &s3c_fb_data_64xx_wins[2], 1791 .win[2] = &s3c_fb_data_s5p_wins[2],
1625 .win[3] = &s3c_fb_data_64xx_wins[3], 1792 .win[3] = &s3c_fb_data_s5p_wins[3],
1626 .win[4] = &s3c_fb_data_64xx_wins[4], 1793 .win[4] = &s3c_fb_data_s5p_wins[4],
1627}; 1794};
1628 1795
1629static struct s3c_fb_driverdata s3c_fb_data_s5pv210 = { 1796static struct s3c_fb_driverdata s3c_fb_data_s5pv210 = {
@@ -1649,11 +1816,11 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pv210 = {
1649 1816
1650 .has_shadowcon = 1, 1817 .has_shadowcon = 1,
1651 }, 1818 },
1652 .win[0] = &s3c_fb_data_64xx_wins[0], 1819 .win[0] = &s3c_fb_data_s5p_wins[0],
1653 .win[1] = &s3c_fb_data_64xx_wins[1], 1820 .win[1] = &s3c_fb_data_s5p_wins[1],
1654 .win[2] = &s3c_fb_data_64xx_wins[2], 1821 .win[2] = &s3c_fb_data_s5p_wins[2],
1655 .win[3] = &s3c_fb_data_64xx_wins[3], 1822 .win[3] = &s3c_fb_data_s5p_wins[3],
1656 .win[4] = &s3c_fb_data_64xx_wins[4], 1823 .win[4] = &s3c_fb_data_s5p_wins[4],
1657}; 1824};
1658 1825
1659/* S3C2443/S3C2416 style hardware */ 1826/* S3C2443/S3C2416 style hardware */
@@ -1710,15 +1877,21 @@ static struct platform_device_id s3c_fb_driver_ids[] = {
1710}; 1877};
1711MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids); 1878MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids);
1712 1879
1880static const struct dev_pm_ops s3cfb_pm_ops = {
1881 .suspend = s3c_fb_suspend,
1882 .resume = s3c_fb_resume,
1883 .runtime_suspend = s3c_fb_runtime_suspend,
1884 .runtime_resume = s3c_fb_runtime_resume,
1885};
1886
1713static struct platform_driver s3c_fb_driver = { 1887static struct platform_driver s3c_fb_driver = {
1714 .probe = s3c_fb_probe, 1888 .probe = s3c_fb_probe,
1715 .remove = __devexit_p(s3c_fb_remove), 1889 .remove = __devexit_p(s3c_fb_remove),
1716 .suspend = s3c_fb_suspend,
1717 .resume = s3c_fb_resume,
1718 .id_table = s3c_fb_driver_ids, 1890 .id_table = s3c_fb_driver_ids,
1719 .driver = { 1891 .driver = {
1720 .name = "s3c-fb", 1892 .name = "s3c-fb",
1721 .owner = THIS_MODULE, 1893 .owner = THIS_MODULE,
1894 .pm = &s3cfb_pm_ops,
1722 }, 1895 },
1723}; 1896};
1724 1897
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index 46b430978bcc..0aa13761de6e 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -13,6 +13,7 @@
13 13
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/kernel.h> 15#include <linux/kernel.h>
16#include <linux/err.h>
16#include <linux/errno.h> 17#include <linux/errno.h>
17#include <linux/string.h> 18#include <linux/string.h>
18#include <linux/mm.h> 19#include <linux/mm.h>
@@ -866,7 +867,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
866 goto dealloc_fb; 867 goto dealloc_fb;
867 } 868 }
868 869
869 size = (res->end - res->start) + 1; 870 size = resource_size(res);
870 info->mem = request_mem_region(res->start, size, pdev->name); 871 info->mem = request_mem_region(res->start, size, pdev->name);
871 if (info->mem == NULL) { 872 if (info->mem == NULL) {
872 dev_err(&pdev->dev, "failed to get memory region\n"); 873 dev_err(&pdev->dev, "failed to get memory region\n");
@@ -918,9 +919,9 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
918 } 919 }
919 920
920 info->clk = clk_get(NULL, "lcd"); 921 info->clk = clk_get(NULL, "lcd");
921 if (!info->clk || IS_ERR(info->clk)) { 922 if (IS_ERR(info->clk)) {
922 printk(KERN_ERR "failed to get lcd clock source\n"); 923 printk(KERN_ERR "failed to get lcd clock source\n");
923 ret = -ENOENT; 924 ret = PTR_ERR(info->clk);
924 goto release_irq; 925 goto release_irq;
925 } 926 }
926 927
@@ -996,8 +997,7 @@ release_irq:
996release_regs: 997release_regs:
997 iounmap(info->io); 998 iounmap(info->io);
998release_mem: 999release_mem:
999 release_resource(info->mem); 1000 release_mem_region(res->start, size);
1000 kfree(info->mem);
1001dealloc_fb: 1001dealloc_fb:
1002 platform_set_drvdata(pdev, NULL); 1002 platform_set_drvdata(pdev, NULL);
1003 framebuffer_release(fbinfo); 1003 framebuffer_release(fbinfo);
@@ -1043,8 +1043,7 @@ static int __devexit s3c2410fb_remove(struct platform_device *pdev)
1043 1043
1044 iounmap(info->io); 1044 iounmap(info->io);
1045 1045
1046 release_resource(info->mem); 1046 release_mem_region(info->mem->start, resource_size(info->mem));
1047 kfree(info->mem);
1048 1047
1049 platform_set_drvdata(pdev, NULL); 1048 platform_set_drvdata(pdev, NULL);
1050 framebuffer_release(fbinfo); 1049 framebuffer_release(fbinfo);
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c
index dce8c97b4333..4ca5d0c8fe84 100644
--- a/drivers/video/s3fb.c
+++ b/drivers/video/s3fb.c
@@ -22,9 +22,12 @@
22#include <linux/svga.h> 22#include <linux/svga.h>
23#include <linux/init.h> 23#include <linux/init.h>
24#include <linux/pci.h> 24#include <linux/pci.h>
25#include <linux/console.h> /* Why should fb driver call console functions? because acquire_console_sem() */ 25#include <linux/console.h> /* Why should fb driver call console functions? because console_lock() */
26#include <video/vga.h> 26#include <video/vga.h>
27 27
28#include <linux/i2c.h>
29#include <linux/i2c-algo-bit.h>
30
28#ifdef CONFIG_MTRR 31#ifdef CONFIG_MTRR
29#include <asm/mtrr.h> 32#include <asm/mtrr.h>
30#endif 33#endif
@@ -36,6 +39,12 @@ struct s3fb_info {
36 struct mutex open_lock; 39 struct mutex open_lock;
37 unsigned int ref_count; 40 unsigned int ref_count;
38 u32 pseudo_palette[16]; 41 u32 pseudo_palette[16];
42#ifdef CONFIG_FB_S3_DDC
43 u8 __iomem *mmio;
44 bool ddc_registered;
45 struct i2c_adapter ddc_adapter;
46 struct i2c_algo_bit_data ddc_algo;
47#endif
39}; 48};
40 49
41 50
@@ -64,15 +73,18 @@ static const struct svga_fb_format s3fb_formats[] = {
64 73
65static const struct svga_pll s3_pll = {3, 129, 3, 33, 0, 3, 74static const struct svga_pll s3_pll = {3, 129, 3, 33, 0, 3,
66 35000, 240000, 14318}; 75 35000, 240000, 14318};
76static const struct svga_pll s3_trio3d_pll = {3, 129, 3, 31, 0, 4,
77 230000, 460000, 14318};
67 78
68static const int s3_memsizes[] = {4096, 0, 3072, 8192, 2048, 6144, 1024, 512}; 79static const int s3_memsizes[] = {4096, 0, 3072, 8192, 2048, 6144, 1024, 512};
69 80
70static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", "S3 Trio64V+", 81static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", "S3 Trio64V+",
71 "S3 Trio64UV+", "S3 Trio64V2/DX", "S3 Trio64V2/GX", 82 "S3 Trio64UV+", "S3 Trio64V2/DX", "S3 Trio64V2/GX",
72 "S3 Plato/PX", "S3 Aurora64VP", "S3 Virge", 83 "S3 Plato/PX", "S3 Aurora64V+", "S3 Virge",
73 "S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX", 84 "S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX",
74 "S3 Virge/GX2", "S3 Virge/GX2P", "S3 Virge/GX2P", 85 "S3 Virge/GX2", "S3 Virge/GX2+", "",
75 "S3 Trio3D/1X", "S3 Trio3D/2X", "S3 Trio3D/2X"}; 86 "S3 Trio3D/1X", "S3 Trio3D/2X", "S3 Trio3D/2X",
87 "S3 Trio3D"};
76 88
77#define CHIP_UNKNOWN 0x00 89#define CHIP_UNKNOWN 0x00
78#define CHIP_732_TRIO32 0x01 90#define CHIP_732_TRIO32 0x01
@@ -87,12 +99,12 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64",
87#define CHIP_988_VIRGE_VX 0x0A 99#define CHIP_988_VIRGE_VX 0x0A
88#define CHIP_375_VIRGE_DX 0x0B 100#define CHIP_375_VIRGE_DX 0x0B
89#define CHIP_385_VIRGE_GX 0x0C 101#define CHIP_385_VIRGE_GX 0x0C
90#define CHIP_356_VIRGE_GX2 0x0D 102#define CHIP_357_VIRGE_GX2 0x0D
91#define CHIP_357_VIRGE_GX2P 0x0E 103#define CHIP_359_VIRGE_GX2P 0x0E
92#define CHIP_359_VIRGE_GX2P 0x0F
93#define CHIP_360_TRIO3D_1X 0x10 104#define CHIP_360_TRIO3D_1X 0x10
94#define CHIP_362_TRIO3D_2X 0x11 105#define CHIP_362_TRIO3D_2X 0x11
95#define CHIP_368_TRIO3D_2X 0x12 106#define CHIP_368_TRIO3D_2X 0x12
107#define CHIP_365_TRIO3D 0x13
96 108
97#define CHIP_XXX_TRIO 0x80 109#define CHIP_XXX_TRIO 0x80
98#define CHIP_XXX_TRIO64V2_DXGX 0x81 110#define CHIP_XXX_TRIO64V2_DXGX 0x81
@@ -102,6 +114,9 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64",
102#define CHIP_UNDECIDED_FLAG 0x80 114#define CHIP_UNDECIDED_FLAG 0x80
103#define CHIP_MASK 0xFF 115#define CHIP_MASK 0xFF
104 116
117#define MMIO_OFFSET 0x1000000
118#define MMIO_SIZE 0x10000
119
105/* CRT timing register sets */ 120/* CRT timing register sets */
106 121
107static const struct vga_regset s3_h_total_regs[] = {{0x00, 0, 7}, {0x5D, 0, 0}, VGA_REGSET_END}; 122static const struct vga_regset s3_h_total_regs[] = {{0x00, 0, 7}, {0x5D, 0, 0}, VGA_REGSET_END};
@@ -119,9 +134,11 @@ static const struct vga_regset s3_v_sync_start_regs[] = {{0x10, 0, 7}, {0x07,
119static const struct vga_regset s3_v_sync_end_regs[] = {{0x11, 0, 3}, VGA_REGSET_END}; 134static const struct vga_regset s3_v_sync_end_regs[] = {{0x11, 0, 3}, VGA_REGSET_END};
120 135
121static const struct vga_regset s3_line_compare_regs[] = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x5E, 6, 6}, VGA_REGSET_END}; 136static const struct vga_regset s3_line_compare_regs[] = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x5E, 6, 6}, VGA_REGSET_END};
122static const struct vga_regset s3_start_address_regs[] = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x31, 4, 5}, {0x51, 0, 1}, VGA_REGSET_END}; 137static const struct vga_regset s3_start_address_regs[] = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x69, 0, 4}, VGA_REGSET_END};
123static const struct vga_regset s3_offset_regs[] = {{0x13, 0, 7}, {0x51, 4, 5}, VGA_REGSET_END}; /* set 0x43 bit 2 to 0 */ 138static const struct vga_regset s3_offset_regs[] = {{0x13, 0, 7}, {0x51, 4, 5}, VGA_REGSET_END}; /* set 0x43 bit 2 to 0 */
124 139
140static const struct vga_regset s3_dtpc_regs[] = {{0x3B, 0, 7}, {0x5D, 6, 6}, VGA_REGSET_END};
141
125static const struct svga_timing_regs s3_timing_regs = { 142static const struct svga_timing_regs s3_timing_regs = {
126 s3_h_total_regs, s3_h_display_regs, s3_h_blank_start_regs, 143 s3_h_total_regs, s3_h_display_regs, s3_h_blank_start_regs,
127 s3_h_blank_end_regs, s3_h_sync_start_regs, s3_h_sync_end_regs, 144 s3_h_blank_end_regs, s3_h_sync_start_regs, s3_h_sync_end_regs,
@@ -135,7 +152,7 @@ static const struct svga_timing_regs s3_timing_regs = {
135/* Module parameters */ 152/* Module parameters */
136 153
137 154
138static char *mode_option __devinitdata = "640x480-8@60"; 155static char *mode_option __devinitdata;
139 156
140#ifdef CONFIG_MTRR 157#ifdef CONFIG_MTRR
141static int mtrr __devinitdata = 1; 158static int mtrr __devinitdata = 1;
@@ -164,6 +181,119 @@ MODULE_PARM_DESC(fasttext, "Enable S3 fast text mode (1=enable, 0=disable, defau
164 181
165/* ------------------------------------------------------------------------- */ 182/* ------------------------------------------------------------------------- */
166 183
184#ifdef CONFIG_FB_S3_DDC
185
186#define DDC_REG 0xaa /* Trio 3D/1X/2X */
187#define DDC_MMIO_REG 0xff20 /* all other chips */
188#define DDC_SCL_OUT (1 << 0)
189#define DDC_SDA_OUT (1 << 1)
190#define DDC_SCL_IN (1 << 2)
191#define DDC_SDA_IN (1 << 3)
192#define DDC_DRIVE_EN (1 << 4)
193
194static bool s3fb_ddc_needs_mmio(int chip)
195{
196 return !(chip == CHIP_360_TRIO3D_1X ||
197 chip == CHIP_362_TRIO3D_2X ||
198 chip == CHIP_368_TRIO3D_2X);
199}
200
201static u8 s3fb_ddc_read(struct s3fb_info *par)
202{
203 if (s3fb_ddc_needs_mmio(par->chip))
204 return readb(par->mmio + DDC_MMIO_REG);
205 else
206 return vga_rcrt(par->state.vgabase, DDC_REG);
207}
208
209static void s3fb_ddc_write(struct s3fb_info *par, u8 val)
210{
211 if (s3fb_ddc_needs_mmio(par->chip))
212 writeb(val, par->mmio + DDC_MMIO_REG);
213 else
214 vga_wcrt(par->state.vgabase, DDC_REG, val);
215}
216
217static void s3fb_ddc_setscl(void *data, int val)
218{
219 struct s3fb_info *par = data;
220 unsigned char reg;
221
222 reg = s3fb_ddc_read(par) | DDC_DRIVE_EN;
223 if (val)
224 reg |= DDC_SCL_OUT;
225 else
226 reg &= ~DDC_SCL_OUT;
227 s3fb_ddc_write(par, reg);
228}
229
230static void s3fb_ddc_setsda(void *data, int val)
231{
232 struct s3fb_info *par = data;
233 unsigned char reg;
234
235 reg = s3fb_ddc_read(par) | DDC_DRIVE_EN;
236 if (val)
237 reg |= DDC_SDA_OUT;
238 else
239 reg &= ~DDC_SDA_OUT;
240 s3fb_ddc_write(par, reg);
241}
242
243static int s3fb_ddc_getscl(void *data)
244{
245 struct s3fb_info *par = data;
246
247 return !!(s3fb_ddc_read(par) & DDC_SCL_IN);
248}
249
250static int s3fb_ddc_getsda(void *data)
251{
252 struct s3fb_info *par = data;
253
254 return !!(s3fb_ddc_read(par) & DDC_SDA_IN);
255}
256
257static int __devinit s3fb_setup_ddc_bus(struct fb_info *info)
258{
259 struct s3fb_info *par = info->par;
260
261 strlcpy(par->ddc_adapter.name, info->fix.id,
262 sizeof(par->ddc_adapter.name));
263 par->ddc_adapter.owner = THIS_MODULE;
264 par->ddc_adapter.class = I2C_CLASS_DDC;
265 par->ddc_adapter.algo_data = &par->ddc_algo;
266 par->ddc_adapter.dev.parent = info->device;
267 par->ddc_algo.setsda = s3fb_ddc_setsda;
268 par->ddc_algo.setscl = s3fb_ddc_setscl;
269 par->ddc_algo.getsda = s3fb_ddc_getsda;
270 par->ddc_algo.getscl = s3fb_ddc_getscl;
271 par->ddc_algo.udelay = 10;
272 par->ddc_algo.timeout = 20;
273 par->ddc_algo.data = par;
274
275 i2c_set_adapdata(&par->ddc_adapter, par);
276
277 /*
278 * some Virge cards have external MUX to switch chip I2C bus between
279 * DDC and extension pins - switch it do DDC
280 */
281/* vga_wseq(par->state.vgabase, 0x08, 0x06); - not needed, already unlocked */
282 if (par->chip == CHIP_357_VIRGE_GX2 ||
283 par->chip == CHIP_359_VIRGE_GX2P)
284 svga_wseq_mask(par->state.vgabase, 0x0d, 0x01, 0x03);
285 else
286 svga_wseq_mask(par->state.vgabase, 0x0d, 0x00, 0x03);
287 /* some Virge need this or the DDC is ignored */
288 svga_wcrt_mask(par->state.vgabase, 0x5c, 0x03, 0x03);
289
290 return i2c_bit_add_bus(&par->ddc_adapter);
291}
292#endif /* CONFIG_FB_S3_DDC */
293
294
295/* ------------------------------------------------------------------------- */
296
167/* Set font in S3 fast text mode */ 297/* Set font in S3 fast text mode */
168 298
169static void s3fb_settile_fast(struct fb_info *info, struct fb_tilemap *map) 299static void s3fb_settile_fast(struct fb_info *info, struct fb_tilemap *map)
@@ -188,12 +318,19 @@ static void s3fb_settile_fast(struct fb_info *info, struct fb_tilemap *map)
188 } 318 }
189} 319}
190 320
321static void s3fb_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor)
322{
323 struct s3fb_info *par = info->par;
324
325 svga_tilecursor(par->state.vgabase, info, cursor);
326}
327
191static struct fb_tile_ops s3fb_tile_ops = { 328static struct fb_tile_ops s3fb_tile_ops = {
192 .fb_settile = svga_settile, 329 .fb_settile = svga_settile,
193 .fb_tilecopy = svga_tilecopy, 330 .fb_tilecopy = svga_tilecopy,
194 .fb_tilefill = svga_tilefill, 331 .fb_tilefill = svga_tilefill,
195 .fb_tileblit = svga_tileblit, 332 .fb_tileblit = svga_tileblit,
196 .fb_tilecursor = svga_tilecursor, 333 .fb_tilecursor = s3fb_tilecursor,
197 .fb_get_tilemax = svga_get_tilemax, 334 .fb_get_tilemax = svga_get_tilemax,
198}; 335};
199 336
@@ -202,7 +339,7 @@ static struct fb_tile_ops s3fb_fast_tile_ops = {
202 .fb_tilecopy = svga_tilecopy, 339 .fb_tilecopy = svga_tilecopy,
203 .fb_tilefill = svga_tilefill, 340 .fb_tilefill = svga_tilefill,
204 .fb_tileblit = svga_tileblit, 341 .fb_tileblit = svga_tileblit,
205 .fb_tilecursor = svga_tilecursor, 342 .fb_tilecursor = s3fb_tilecursor,
206 .fb_get_tilemax = svga_get_tilemax, 343 .fb_get_tilemax = svga_get_tilemax,
207}; 344};
208 345
@@ -334,33 +471,36 @@ static void s3_set_pixclock(struct fb_info *info, u32 pixclock)
334 u8 regval; 471 u8 regval;
335 int rv; 472 int rv;
336 473
337 rv = svga_compute_pll(&s3_pll, 1000000000 / pixclock, &m, &n, &r, info->node); 474 rv = svga_compute_pll((par->chip == CHIP_365_TRIO3D) ? &s3_trio3d_pll : &s3_pll,
475 1000000000 / pixclock, &m, &n, &r, info->node);
338 if (rv < 0) { 476 if (rv < 0) {
339 printk(KERN_ERR "fb%d: cannot set requested pixclock, keeping old value\n", info->node); 477 printk(KERN_ERR "fb%d: cannot set requested pixclock, keeping old value\n", info->node);
340 return; 478 return;
341 } 479 }
342 480
343 /* Set VGA misc register */ 481 /* Set VGA misc register */
344 regval = vga_r(NULL, VGA_MIS_R); 482 regval = vga_r(par->state.vgabase, VGA_MIS_R);
345 vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); 483 vga_w(par->state.vgabase, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD);
346 484
347 /* Set S3 clock registers */ 485 /* Set S3 clock registers */
348 if (par->chip == CHIP_360_TRIO3D_1X || 486 if (par->chip == CHIP_357_VIRGE_GX2 ||
487 par->chip == CHIP_359_VIRGE_GX2P ||
488 par->chip == CHIP_360_TRIO3D_1X ||
349 par->chip == CHIP_362_TRIO3D_2X || 489 par->chip == CHIP_362_TRIO3D_2X ||
350 par->chip == CHIP_368_TRIO3D_2X) { 490 par->chip == CHIP_368_TRIO3D_2X) {
351 vga_wseq(NULL, 0x12, (n - 2) | ((r & 3) << 6)); /* n and two bits of r */ 491 vga_wseq(par->state.vgabase, 0x12, (n - 2) | ((r & 3) << 6)); /* n and two bits of r */
352 vga_wseq(NULL, 0x29, r >> 2); /* remaining highest bit of r */ 492 vga_wseq(par->state.vgabase, 0x29, r >> 2); /* remaining highest bit of r */
353 } else 493 } else
354 vga_wseq(NULL, 0x12, (n - 2) | (r << 5)); 494 vga_wseq(par->state.vgabase, 0x12, (n - 2) | (r << 5));
355 vga_wseq(NULL, 0x13, m - 2); 495 vga_wseq(par->state.vgabase, 0x13, m - 2);
356 496
357 udelay(1000); 497 udelay(1000);
358 498
359 /* Activate clock - write 0, 1, 0 to seq/15 bit 5 */ 499 /* Activate clock - write 0, 1, 0 to seq/15 bit 5 */
360 regval = vga_rseq (NULL, 0x15); /* | 0x80; */ 500 regval = vga_rseq (par->state.vgabase, 0x15); /* | 0x80; */
361 vga_wseq(NULL, 0x15, regval & ~(1<<5)); 501 vga_wseq(par->state.vgabase, 0x15, regval & ~(1<<5));
362 vga_wseq(NULL, 0x15, regval | (1<<5)); 502 vga_wseq(par->state.vgabase, 0x15, regval | (1<<5));
363 vga_wseq(NULL, 0x15, regval & ~(1<<5)); 503 vga_wseq(par->state.vgabase, 0x15, regval & ~(1<<5));
364} 504}
365 505
366 506
@@ -372,7 +512,10 @@ static int s3fb_open(struct fb_info *info, int user)
372 512
373 mutex_lock(&(par->open_lock)); 513 mutex_lock(&(par->open_lock));
374 if (par->ref_count == 0) { 514 if (par->ref_count == 0) {
515 void __iomem *vgabase = par->state.vgabase;
516
375 memset(&(par->state), 0, sizeof(struct vgastate)); 517 memset(&(par->state), 0, sizeof(struct vgastate));
518 par->state.vgabase = vgabase;
376 par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP; 519 par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP;
377 par->state.num_crtc = 0x70; 520 par->state.num_crtc = 0x70;
378 par->state.num_seq = 0x20; 521 par->state.num_seq = 0x20;
@@ -470,6 +613,7 @@ static int s3fb_set_par(struct fb_info *info)
470 struct s3fb_info *par = info->par; 613 struct s3fb_info *par = info->par;
471 u32 value, mode, hmul, offset_value, screen_size, multiplex, dbytes; 614 u32 value, mode, hmul, offset_value, screen_size, multiplex, dbytes;
472 u32 bpp = info->var.bits_per_pixel; 615 u32 bpp = info->var.bits_per_pixel;
616 u32 htotal, hsstart;
473 617
474 if (bpp != 0) { 618 if (bpp != 0) {
475 info->fix.ypanstep = 1; 619 info->fix.ypanstep = 1;
@@ -504,99 +648,115 @@ static int s3fb_set_par(struct fb_info *info)
504 info->var.activate = FB_ACTIVATE_NOW; 648 info->var.activate = FB_ACTIVATE_NOW;
505 649
506 /* Unlock registers */ 650 /* Unlock registers */
507 vga_wcrt(NULL, 0x38, 0x48); 651 vga_wcrt(par->state.vgabase, 0x38, 0x48);
508 vga_wcrt(NULL, 0x39, 0xA5); 652 vga_wcrt(par->state.vgabase, 0x39, 0xA5);
509 vga_wseq(NULL, 0x08, 0x06); 653 vga_wseq(par->state.vgabase, 0x08, 0x06);
510 svga_wcrt_mask(0x11, 0x00, 0x80); 654 svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x80);
511 655
512 /* Blank screen and turn off sync */ 656 /* Blank screen and turn off sync */
513 svga_wseq_mask(0x01, 0x20, 0x20); 657 svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
514 svga_wcrt_mask(0x17, 0x00, 0x80); 658 svga_wcrt_mask(par->state.vgabase, 0x17, 0x00, 0x80);
515 659
516 /* Set default values */ 660 /* Set default values */
517 svga_set_default_gfx_regs(); 661 svga_set_default_gfx_regs(par->state.vgabase);
518 svga_set_default_atc_regs(); 662 svga_set_default_atc_regs(par->state.vgabase);
519 svga_set_default_seq_regs(); 663 svga_set_default_seq_regs(par->state.vgabase);
520 svga_set_default_crt_regs(); 664 svga_set_default_crt_regs(par->state.vgabase);
521 svga_wcrt_multi(s3_line_compare_regs, 0xFFFFFFFF); 665 svga_wcrt_multi(par->state.vgabase, s3_line_compare_regs, 0xFFFFFFFF);
522 svga_wcrt_multi(s3_start_address_regs, 0); 666 svga_wcrt_multi(par->state.vgabase, s3_start_address_regs, 0);
523 667
524 /* S3 specific initialization */ 668 /* S3 specific initialization */
525 svga_wcrt_mask(0x58, 0x10, 0x10); /* enable linear framebuffer */ 669 svga_wcrt_mask(par->state.vgabase, 0x58, 0x10, 0x10); /* enable linear framebuffer */
526 svga_wcrt_mask(0x31, 0x08, 0x08); /* enable sequencer access to framebuffer above 256 kB */ 670 svga_wcrt_mask(par->state.vgabase, 0x31, 0x08, 0x08); /* enable sequencer access to framebuffer above 256 kB */
527 671
528/* svga_wcrt_mask(0x33, 0x08, 0x08); */ /* DDR ? */ 672/* svga_wcrt_mask(par->state.vgabase, 0x33, 0x08, 0x08); */ /* DDR ? */
529/* svga_wcrt_mask(0x43, 0x01, 0x01); */ /* DDR ? */ 673/* svga_wcrt_mask(par->state.vgabase, 0x43, 0x01, 0x01); */ /* DDR ? */
530 svga_wcrt_mask(0x33, 0x00, 0x08); /* no DDR ? */ 674 svga_wcrt_mask(par->state.vgabase, 0x33, 0x00, 0x08); /* no DDR ? */
531 svga_wcrt_mask(0x43, 0x00, 0x01); /* no DDR ? */ 675 svga_wcrt_mask(par->state.vgabase, 0x43, 0x00, 0x01); /* no DDR ? */
532 676
533 svga_wcrt_mask(0x5D, 0x00, 0x28); /* Clear strange HSlen bits */ 677 svga_wcrt_mask(par->state.vgabase, 0x5D, 0x00, 0x28); /* Clear strange HSlen bits */
534 678
535/* svga_wcrt_mask(0x58, 0x03, 0x03); */ 679/* svga_wcrt_mask(par->state.vgabase, 0x58, 0x03, 0x03); */
536 680
537/* svga_wcrt_mask(0x53, 0x12, 0x13); */ /* enable MMIO */ 681/* svga_wcrt_mask(par->state.vgabase, 0x53, 0x12, 0x13); */ /* enable MMIO */
538/* svga_wcrt_mask(0x40, 0x08, 0x08); */ /* enable write buffer */ 682/* svga_wcrt_mask(par->state.vgabase, 0x40, 0x08, 0x08); */ /* enable write buffer */
539 683
540 684
541 /* Set the offset register */ 685 /* Set the offset register */
542 pr_debug("fb%d: offset register : %d\n", info->node, offset_value); 686 pr_debug("fb%d: offset register : %d\n", info->node, offset_value);
543 svga_wcrt_multi(s3_offset_regs, offset_value); 687 svga_wcrt_multi(par->state.vgabase, s3_offset_regs, offset_value);
544 688
545 if (par->chip != CHIP_360_TRIO3D_1X && 689 if (par->chip != CHIP_357_VIRGE_GX2 &&
690 par->chip != CHIP_359_VIRGE_GX2P &&
691 par->chip != CHIP_360_TRIO3D_1X &&
546 par->chip != CHIP_362_TRIO3D_2X && 692 par->chip != CHIP_362_TRIO3D_2X &&
547 par->chip != CHIP_368_TRIO3D_2X) { 693 par->chip != CHIP_368_TRIO3D_2X) {
548 vga_wcrt(NULL, 0x54, 0x18); /* M parameter */ 694 vga_wcrt(par->state.vgabase, 0x54, 0x18); /* M parameter */
549 vga_wcrt(NULL, 0x60, 0xff); /* N parameter */ 695 vga_wcrt(par->state.vgabase, 0x60, 0xff); /* N parameter */
550 vga_wcrt(NULL, 0x61, 0xff); /* L parameter */ 696 vga_wcrt(par->state.vgabase, 0x61, 0xff); /* L parameter */
551 vga_wcrt(NULL, 0x62, 0xff); /* L parameter */ 697 vga_wcrt(par->state.vgabase, 0x62, 0xff); /* L parameter */
552 } 698 }
553 699
554 vga_wcrt(NULL, 0x3A, 0x35); 700 vga_wcrt(par->state.vgabase, 0x3A, 0x35);
555 svga_wattr(0x33, 0x00); 701 svga_wattr(par->state.vgabase, 0x33, 0x00);
556 702
557 if (info->var.vmode & FB_VMODE_DOUBLE) 703 if (info->var.vmode & FB_VMODE_DOUBLE)
558 svga_wcrt_mask(0x09, 0x80, 0x80); 704 svga_wcrt_mask(par->state.vgabase, 0x09, 0x80, 0x80);
559 else 705 else
560 svga_wcrt_mask(0x09, 0x00, 0x80); 706 svga_wcrt_mask(par->state.vgabase, 0x09, 0x00, 0x80);
561 707
562 if (info->var.vmode & FB_VMODE_INTERLACED) 708 if (info->var.vmode & FB_VMODE_INTERLACED)
563 svga_wcrt_mask(0x42, 0x20, 0x20); 709 svga_wcrt_mask(par->state.vgabase, 0x42, 0x20, 0x20);
564 else 710 else
565 svga_wcrt_mask(0x42, 0x00, 0x20); 711 svga_wcrt_mask(par->state.vgabase, 0x42, 0x00, 0x20);
566 712
567 /* Disable hardware graphics cursor */ 713 /* Disable hardware graphics cursor */
568 svga_wcrt_mask(0x45, 0x00, 0x01); 714 svga_wcrt_mask(par->state.vgabase, 0x45, 0x00, 0x01);
569 /* Disable Streams engine */ 715 /* Disable Streams engine */
570 svga_wcrt_mask(0x67, 0x00, 0x0C); 716 svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0x0C);
571 717
572 mode = svga_match_format(s3fb_formats, &(info->var), &(info->fix)); 718 mode = svga_match_format(s3fb_formats, &(info->var), &(info->fix));
573 719
574 /* S3 virge DX hack */ 720 /* S3 virge DX hack */
575 if (par->chip == CHIP_375_VIRGE_DX) { 721 if (par->chip == CHIP_375_VIRGE_DX) {
576 vga_wcrt(NULL, 0x86, 0x80); 722 vga_wcrt(par->state.vgabase, 0x86, 0x80);
577 vga_wcrt(NULL, 0x90, 0x00); 723 vga_wcrt(par->state.vgabase, 0x90, 0x00);
578 } 724 }
579 725
580 /* S3 virge VX hack */ 726 /* S3 virge VX hack */
581 if (par->chip == CHIP_988_VIRGE_VX) { 727 if (par->chip == CHIP_988_VIRGE_VX) {
582 vga_wcrt(NULL, 0x50, 0x00); 728 vga_wcrt(par->state.vgabase, 0x50, 0x00);
583 vga_wcrt(NULL, 0x67, 0x50); 729 vga_wcrt(par->state.vgabase, 0x67, 0x50);
584 730
585 vga_wcrt(NULL, 0x63, (mode <= 2) ? 0x90 : 0x09); 731 vga_wcrt(par->state.vgabase, 0x63, (mode <= 2) ? 0x90 : 0x09);
586 vga_wcrt(NULL, 0x66, 0x90); 732 vga_wcrt(par->state.vgabase, 0x66, 0x90);
587 } 733 }
588 734
589 if (par->chip == CHIP_360_TRIO3D_1X || 735 if (par->chip == CHIP_357_VIRGE_GX2 ||
736 par->chip == CHIP_359_VIRGE_GX2P ||
737 par->chip == CHIP_360_TRIO3D_1X ||
590 par->chip == CHIP_362_TRIO3D_2X || 738 par->chip == CHIP_362_TRIO3D_2X ||
591 par->chip == CHIP_368_TRIO3D_2X) { 739 par->chip == CHIP_368_TRIO3D_2X ||
740 par->chip == CHIP_365_TRIO3D ||
741 par->chip == CHIP_375_VIRGE_DX ||
742 par->chip == CHIP_385_VIRGE_GX) {
592 dbytes = info->var.xres * ((bpp+7)/8); 743 dbytes = info->var.xres * ((bpp+7)/8);
593 vga_wcrt(NULL, 0x91, (dbytes + 7) / 8); 744 vga_wcrt(par->state.vgabase, 0x91, (dbytes + 7) / 8);
594 vga_wcrt(NULL, 0x90, (((dbytes + 7) / 8) >> 8) | 0x80); 745 vga_wcrt(par->state.vgabase, 0x90, (((dbytes + 7) / 8) >> 8) | 0x80);
595 746
596 vga_wcrt(NULL, 0x66, 0x81); 747 vga_wcrt(par->state.vgabase, 0x66, 0x81);
597 } 748 }
598 749
599 svga_wcrt_mask(0x31, 0x00, 0x40); 750 if (par->chip == CHIP_357_VIRGE_GX2 ||
751 par->chip == CHIP_359_VIRGE_GX2P ||
752 par->chip == CHIP_360_TRIO3D_1X ||
753 par->chip == CHIP_362_TRIO3D_2X ||
754 par->chip == CHIP_368_TRIO3D_2X)
755 vga_wcrt(par->state.vgabase, 0x34, 0x00);
756 else /* enable Data Transfer Position Control (DTPC) */
757 vga_wcrt(par->state.vgabase, 0x34, 0x10);
758
759 svga_wcrt_mask(par->state.vgabase, 0x31, 0x00, 0x40);
600 multiplex = 0; 760 multiplex = 0;
601 hmul = 1; 761 hmul = 1;
602 762
@@ -604,51 +764,53 @@ static int s3fb_set_par(struct fb_info *info)
604 switch (mode) { 764 switch (mode) {
605 case 0: 765 case 0:
606 pr_debug("fb%d: text mode\n", info->node); 766 pr_debug("fb%d: text mode\n", info->node);
607 svga_set_textmode_vga_regs(); 767 svga_set_textmode_vga_regs(par->state.vgabase);
608 768
609 /* Set additional registers like in 8-bit mode */ 769 /* Set additional registers like in 8-bit mode */
610 svga_wcrt_mask(0x50, 0x00, 0x30); 770 svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30);
611 svga_wcrt_mask(0x67, 0x00, 0xF0); 771 svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0);
612 772
613 /* Disable enhanced mode */ 773 /* Disable enhanced mode */
614 svga_wcrt_mask(0x3A, 0x00, 0x30); 774 svga_wcrt_mask(par->state.vgabase, 0x3A, 0x00, 0x30);
615 775
616 if (fasttext) { 776 if (fasttext) {
617 pr_debug("fb%d: high speed text mode set\n", info->node); 777 pr_debug("fb%d: high speed text mode set\n", info->node);
618 svga_wcrt_mask(0x31, 0x40, 0x40); 778 svga_wcrt_mask(par->state.vgabase, 0x31, 0x40, 0x40);
619 } 779 }
620 break; 780 break;
621 case 1: 781 case 1:
622 pr_debug("fb%d: 4 bit pseudocolor\n", info->node); 782 pr_debug("fb%d: 4 bit pseudocolor\n", info->node);
623 vga_wgfx(NULL, VGA_GFX_MODE, 0x40); 783 vga_wgfx(par->state.vgabase, VGA_GFX_MODE, 0x40);
624 784
625 /* Set additional registers like in 8-bit mode */ 785 /* Set additional registers like in 8-bit mode */
626 svga_wcrt_mask(0x50, 0x00, 0x30); 786 svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30);
627 svga_wcrt_mask(0x67, 0x00, 0xF0); 787 svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0);
628 788
629 /* disable enhanced mode */ 789 /* disable enhanced mode */
630 svga_wcrt_mask(0x3A, 0x00, 0x30); 790 svga_wcrt_mask(par->state.vgabase, 0x3A, 0x00, 0x30);
631 break; 791 break;
632 case 2: 792 case 2:
633 pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node); 793 pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node);
634 794
635 /* Set additional registers like in 8-bit mode */ 795 /* Set additional registers like in 8-bit mode */
636 svga_wcrt_mask(0x50, 0x00, 0x30); 796 svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30);
637 svga_wcrt_mask(0x67, 0x00, 0xF0); 797 svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0);
638 798
639 /* disable enhanced mode */ 799 /* disable enhanced mode */
640 svga_wcrt_mask(0x3A, 0x00, 0x30); 800 svga_wcrt_mask(par->state.vgabase, 0x3A, 0x00, 0x30);
641 break; 801 break;
642 case 3: 802 case 3:
643 pr_debug("fb%d: 8 bit pseudocolor\n", info->node); 803 pr_debug("fb%d: 8 bit pseudocolor\n", info->node);
644 svga_wcrt_mask(0x50, 0x00, 0x30); 804 svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30);
645 if (info->var.pixclock > 20000 || 805 if (info->var.pixclock > 20000 ||
806 par->chip == CHIP_357_VIRGE_GX2 ||
807 par->chip == CHIP_359_VIRGE_GX2P ||
646 par->chip == CHIP_360_TRIO3D_1X || 808 par->chip == CHIP_360_TRIO3D_1X ||
647 par->chip == CHIP_362_TRIO3D_2X || 809 par->chip == CHIP_362_TRIO3D_2X ||
648 par->chip == CHIP_368_TRIO3D_2X) 810 par->chip == CHIP_368_TRIO3D_2X)
649 svga_wcrt_mask(0x67, 0x00, 0xF0); 811 svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0);
650 else { 812 else {
651 svga_wcrt_mask(0x67, 0x10, 0xF0); 813 svga_wcrt_mask(par->state.vgabase, 0x67, 0x10, 0xF0);
652 multiplex = 1; 814 multiplex = 1;
653 } 815 }
654 break; 816 break;
@@ -656,13 +818,24 @@ static int s3fb_set_par(struct fb_info *info)
656 pr_debug("fb%d: 5/5/5 truecolor\n", info->node); 818 pr_debug("fb%d: 5/5/5 truecolor\n", info->node);
657 if (par->chip == CHIP_988_VIRGE_VX) { 819 if (par->chip == CHIP_988_VIRGE_VX) {
658 if (info->var.pixclock > 20000) 820 if (info->var.pixclock > 20000)
659 svga_wcrt_mask(0x67, 0x20, 0xF0); 821 svga_wcrt_mask(par->state.vgabase, 0x67, 0x20, 0xF0);
660 else 822 else
661 svga_wcrt_mask(0x67, 0x30, 0xF0); 823 svga_wcrt_mask(par->state.vgabase, 0x67, 0x30, 0xF0);
824 } else if (par->chip == CHIP_365_TRIO3D) {
825 svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30);
826 if (info->var.pixclock > 8695) {
827 svga_wcrt_mask(par->state.vgabase, 0x67, 0x30, 0xF0);
828 hmul = 2;
829 } else {
830 svga_wcrt_mask(par->state.vgabase, 0x67, 0x20, 0xF0);
831 multiplex = 1;
832 }
662 } else { 833 } else {
663 svga_wcrt_mask(0x50, 0x10, 0x30); 834 svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30);
664 svga_wcrt_mask(0x67, 0x30, 0xF0); 835 svga_wcrt_mask(par->state.vgabase, 0x67, 0x30, 0xF0);
665 if (par->chip != CHIP_360_TRIO3D_1X && 836 if (par->chip != CHIP_357_VIRGE_GX2 &&
837 par->chip != CHIP_359_VIRGE_GX2P &&
838 par->chip != CHIP_360_TRIO3D_1X &&
666 par->chip != CHIP_362_TRIO3D_2X && 839 par->chip != CHIP_362_TRIO3D_2X &&
667 par->chip != CHIP_368_TRIO3D_2X) 840 par->chip != CHIP_368_TRIO3D_2X)
668 hmul = 2; 841 hmul = 2;
@@ -672,13 +845,24 @@ static int s3fb_set_par(struct fb_info *info)
672 pr_debug("fb%d: 5/6/5 truecolor\n", info->node); 845 pr_debug("fb%d: 5/6/5 truecolor\n", info->node);
673 if (par->chip == CHIP_988_VIRGE_VX) { 846 if (par->chip == CHIP_988_VIRGE_VX) {
674 if (info->var.pixclock > 20000) 847 if (info->var.pixclock > 20000)
675 svga_wcrt_mask(0x67, 0x40, 0xF0); 848 svga_wcrt_mask(par->state.vgabase, 0x67, 0x40, 0xF0);
676 else 849 else
677 svga_wcrt_mask(0x67, 0x50, 0xF0); 850 svga_wcrt_mask(par->state.vgabase, 0x67, 0x50, 0xF0);
851 } else if (par->chip == CHIP_365_TRIO3D) {
852 svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30);
853 if (info->var.pixclock > 8695) {
854 svga_wcrt_mask(par->state.vgabase, 0x67, 0x50, 0xF0);
855 hmul = 2;
856 } else {
857 svga_wcrt_mask(par->state.vgabase, 0x67, 0x40, 0xF0);
858 multiplex = 1;
859 }
678 } else { 860 } else {
679 svga_wcrt_mask(0x50, 0x10, 0x30); 861 svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30);
680 svga_wcrt_mask(0x67, 0x50, 0xF0); 862 svga_wcrt_mask(par->state.vgabase, 0x67, 0x50, 0xF0);
681 if (par->chip != CHIP_360_TRIO3D_1X && 863 if (par->chip != CHIP_357_VIRGE_GX2 &&
864 par->chip != CHIP_359_VIRGE_GX2P &&
865 par->chip != CHIP_360_TRIO3D_1X &&
682 par->chip != CHIP_362_TRIO3D_2X && 866 par->chip != CHIP_362_TRIO3D_2X &&
683 par->chip != CHIP_368_TRIO3D_2X) 867 par->chip != CHIP_368_TRIO3D_2X)
684 hmul = 2; 868 hmul = 2;
@@ -687,12 +871,12 @@ static int s3fb_set_par(struct fb_info *info)
687 case 6: 871 case 6:
688 /* VIRGE VX case */ 872 /* VIRGE VX case */
689 pr_debug("fb%d: 8/8/8 truecolor\n", info->node); 873 pr_debug("fb%d: 8/8/8 truecolor\n", info->node);
690 svga_wcrt_mask(0x67, 0xD0, 0xF0); 874 svga_wcrt_mask(par->state.vgabase, 0x67, 0xD0, 0xF0);
691 break; 875 break;
692 case 7: 876 case 7:
693 pr_debug("fb%d: 8/8/8/8 truecolor\n", info->node); 877 pr_debug("fb%d: 8/8/8/8 truecolor\n", info->node);
694 svga_wcrt_mask(0x50, 0x30, 0x30); 878 svga_wcrt_mask(par->state.vgabase, 0x50, 0x30, 0x30);
695 svga_wcrt_mask(0x67, 0xD0, 0xF0); 879 svga_wcrt_mask(par->state.vgabase, 0x67, 0xD0, 0xF0);
696 break; 880 break;
697 default: 881 default:
698 printk(KERN_ERR "fb%d: unsupported mode - bug\n", info->node); 882 printk(KERN_ERR "fb%d: unsupported mode - bug\n", info->node);
@@ -700,25 +884,30 @@ static int s3fb_set_par(struct fb_info *info)
700 } 884 }
701 885
702 if (par->chip != CHIP_988_VIRGE_VX) { 886 if (par->chip != CHIP_988_VIRGE_VX) {
703 svga_wseq_mask(0x15, multiplex ? 0x10 : 0x00, 0x10); 887 svga_wseq_mask(par->state.vgabase, 0x15, multiplex ? 0x10 : 0x00, 0x10);
704 svga_wseq_mask(0x18, multiplex ? 0x80 : 0x00, 0x80); 888 svga_wseq_mask(par->state.vgabase, 0x18, multiplex ? 0x80 : 0x00, 0x80);
705 } 889 }
706 890
707 s3_set_pixclock(info, info->var.pixclock); 891 s3_set_pixclock(info, info->var.pixclock);
708 svga_set_timings(&s3_timing_regs, &(info->var), hmul, 1, 892 svga_set_timings(par->state.vgabase, &s3_timing_regs, &(info->var), hmul, 1,
709 (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1, 893 (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1,
710 (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1, 894 (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1,
711 hmul, info->node); 895 hmul, info->node);
712 896
713 /* Set interlaced mode start/end register */ 897 /* Set interlaced mode start/end register */
714 value = info->var.xres + info->var.left_margin + info->var.right_margin + info->var.hsync_len; 898 htotal = info->var.xres + info->var.left_margin + info->var.right_margin + info->var.hsync_len;
715 value = ((value * hmul) / 8) - 5; 899 htotal = ((htotal * hmul) / 8) - 5;
716 vga_wcrt(NULL, 0x3C, (value + 1) / 2); 900 vga_wcrt(par->state.vgabase, 0x3C, (htotal + 1) / 2);
901
902 /* Set Data Transfer Position */
903 hsstart = ((info->var.xres + info->var.right_margin) * hmul) / 8;
904 value = clamp((htotal + hsstart + 1) / 2, hsstart + 4, htotal + 1);
905 svga_wcrt_multi(par->state.vgabase, s3_dtpc_regs, value);
717 906
718 memset_io(info->screen_base, 0x00, screen_size); 907 memset_io(info->screen_base, 0x00, screen_size);
719 /* Device and screen back on */ 908 /* Device and screen back on */
720 svga_wcrt_mask(0x17, 0x80, 0x80); 909 svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80);
721 svga_wseq_mask(0x01, 0x00, 0x20); 910 svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
722 911
723 return 0; 912 return 0;
724} 913}
@@ -788,31 +977,33 @@ static int s3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
788 977
789static int s3fb_blank(int blank_mode, struct fb_info *info) 978static int s3fb_blank(int blank_mode, struct fb_info *info)
790{ 979{
980 struct s3fb_info *par = info->par;
981
791 switch (blank_mode) { 982 switch (blank_mode) {
792 case FB_BLANK_UNBLANK: 983 case FB_BLANK_UNBLANK:
793 pr_debug("fb%d: unblank\n", info->node); 984 pr_debug("fb%d: unblank\n", info->node);
794 svga_wcrt_mask(0x56, 0x00, 0x06); 985 svga_wcrt_mask(par->state.vgabase, 0x56, 0x00, 0x06);
795 svga_wseq_mask(0x01, 0x00, 0x20); 986 svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
796 break; 987 break;
797 case FB_BLANK_NORMAL: 988 case FB_BLANK_NORMAL:
798 pr_debug("fb%d: blank\n", info->node); 989 pr_debug("fb%d: blank\n", info->node);
799 svga_wcrt_mask(0x56, 0x00, 0x06); 990 svga_wcrt_mask(par->state.vgabase, 0x56, 0x00, 0x06);
800 svga_wseq_mask(0x01, 0x20, 0x20); 991 svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
801 break; 992 break;
802 case FB_BLANK_HSYNC_SUSPEND: 993 case FB_BLANK_HSYNC_SUSPEND:
803 pr_debug("fb%d: hsync\n", info->node); 994 pr_debug("fb%d: hsync\n", info->node);
804 svga_wcrt_mask(0x56, 0x02, 0x06); 995 svga_wcrt_mask(par->state.vgabase, 0x56, 0x02, 0x06);
805 svga_wseq_mask(0x01, 0x20, 0x20); 996 svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
806 break; 997 break;
807 case FB_BLANK_VSYNC_SUSPEND: 998 case FB_BLANK_VSYNC_SUSPEND:
808 pr_debug("fb%d: vsync\n", info->node); 999 pr_debug("fb%d: vsync\n", info->node);
809 svga_wcrt_mask(0x56, 0x04, 0x06); 1000 svga_wcrt_mask(par->state.vgabase, 0x56, 0x04, 0x06);
810 svga_wseq_mask(0x01, 0x20, 0x20); 1001 svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
811 break; 1002 break;
812 case FB_BLANK_POWERDOWN: 1003 case FB_BLANK_POWERDOWN:
813 pr_debug("fb%d: sync down\n", info->node); 1004 pr_debug("fb%d: sync down\n", info->node);
814 svga_wcrt_mask(0x56, 0x06, 0x06); 1005 svga_wcrt_mask(par->state.vgabase, 0x56, 0x06, 0x06);
815 svga_wseq_mask(0x01, 0x20, 0x20); 1006 svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
816 break; 1007 break;
817 } 1008 }
818 1009
@@ -822,8 +1013,9 @@ static int s3fb_blank(int blank_mode, struct fb_info *info)
822 1013
823/* Pan the display */ 1014/* Pan the display */
824 1015
825static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { 1016static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
826 1017{
1018 struct s3fb_info *par = info->par;
827 unsigned int offset; 1019 unsigned int offset;
828 1020
829 /* Calculate the offset */ 1021 /* Calculate the offset */
@@ -837,7 +1029,7 @@ static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
837 } 1029 }
838 1030
839 /* Set the offset */ 1031 /* Set the offset */
840 svga_wcrt_multi(s3_start_address_regs, offset); 1032 svga_wcrt_multi(par->state.vgabase, s3_start_address_regs, offset);
841 1033
842 return 0; 1034 return 0;
843} 1035}
@@ -863,12 +1055,14 @@ static struct fb_ops s3fb_ops = {
863 1055
864/* ------------------------------------------------------------------------- */ 1056/* ------------------------------------------------------------------------- */
865 1057
866static int __devinit s3_identification(int chip) 1058static int __devinit s3_identification(struct s3fb_info *par)
867{ 1059{
1060 int chip = par->chip;
1061
868 if (chip == CHIP_XXX_TRIO) { 1062 if (chip == CHIP_XXX_TRIO) {
869 u8 cr30 = vga_rcrt(NULL, 0x30); 1063 u8 cr30 = vga_rcrt(par->state.vgabase, 0x30);
870 u8 cr2e = vga_rcrt(NULL, 0x2e); 1064 u8 cr2e = vga_rcrt(par->state.vgabase, 0x2e);
871 u8 cr2f = vga_rcrt(NULL, 0x2f); 1065 u8 cr2f = vga_rcrt(par->state.vgabase, 0x2f);
872 1066
873 if ((cr30 == 0xE0) || (cr30 == 0xE1)) { 1067 if ((cr30 == 0xE0) || (cr30 == 0xE1)) {
874 if (cr2e == 0x10) 1068 if (cr2e == 0x10)
@@ -883,7 +1077,7 @@ static int __devinit s3_identification(int chip)
883 } 1077 }
884 1078
885 if (chip == CHIP_XXX_TRIO64V2_DXGX) { 1079 if (chip == CHIP_XXX_TRIO64V2_DXGX) {
886 u8 cr6f = vga_rcrt(NULL, 0x6f); 1080 u8 cr6f = vga_rcrt(par->state.vgabase, 0x6f);
887 1081
888 if (! (cr6f & 0x01)) 1082 if (! (cr6f & 0x01))
889 return CHIP_775_TRIO64V2_DX; 1083 return CHIP_775_TRIO64V2_DX;
@@ -892,7 +1086,7 @@ static int __devinit s3_identification(int chip)
892 } 1086 }
893 1087
894 if (chip == CHIP_XXX_VIRGE_DXGX) { 1088 if (chip == CHIP_XXX_VIRGE_DXGX) {
895 u8 cr6f = vga_rcrt(NULL, 0x6f); 1089 u8 cr6f = vga_rcrt(par->state.vgabase, 0x6f);
896 1090
897 if (! (cr6f & 0x01)) 1091 if (! (cr6f & 0x01))
898 return CHIP_375_VIRGE_DX; 1092 return CHIP_375_VIRGE_DX;
@@ -901,7 +1095,7 @@ static int __devinit s3_identification(int chip)
901 } 1095 }
902 1096
903 if (chip == CHIP_36X_TRIO3D_1X_2X) { 1097 if (chip == CHIP_36X_TRIO3D_1X_2X) {
904 switch (vga_rcrt(NULL, 0x2f)) { 1098 switch (vga_rcrt(par->state.vgabase, 0x2f)) {
905 case 0x00: 1099 case 0x00:
906 return CHIP_360_TRIO3D_1X; 1100 return CHIP_360_TRIO3D_1X;
907 case 0x01: 1101 case 0x01:
@@ -919,10 +1113,13 @@ static int __devinit s3_identification(int chip)
919 1113
920static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) 1114static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
921{ 1115{
1116 struct pci_bus_region bus_reg;
1117 struct resource vga_res;
922 struct fb_info *info; 1118 struct fb_info *info;
923 struct s3fb_info *par; 1119 struct s3fb_info *par;
924 int rc; 1120 int rc;
925 u8 regval, cr38, cr39; 1121 u8 regval, cr38, cr39;
1122 bool found = false;
926 1123
927 /* Ignore secondary VGA device because there is no VGA arbitration */ 1124 /* Ignore secondary VGA device because there is no VGA arbitration */
928 if (! svga_primary_device(dev)) { 1125 if (! svga_primary_device(dev)) {
@@ -968,47 +1165,68 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i
968 goto err_iomap; 1165 goto err_iomap;
969 } 1166 }
970 1167
1168 bus_reg.start = 0;
1169 bus_reg.end = 64 * 1024;
1170
1171 vga_res.flags = IORESOURCE_IO;
1172
1173 pcibios_bus_to_resource(dev, &vga_res, &bus_reg);
1174
1175 par->state.vgabase = (void __iomem *) vga_res.start;
1176
971 /* Unlock regs */ 1177 /* Unlock regs */
972 cr38 = vga_rcrt(NULL, 0x38); 1178 cr38 = vga_rcrt(par->state.vgabase, 0x38);
973 cr39 = vga_rcrt(NULL, 0x39); 1179 cr39 = vga_rcrt(par->state.vgabase, 0x39);
974 vga_wseq(NULL, 0x08, 0x06); 1180 vga_wseq(par->state.vgabase, 0x08, 0x06);
975 vga_wcrt(NULL, 0x38, 0x48); 1181 vga_wcrt(par->state.vgabase, 0x38, 0x48);
976 vga_wcrt(NULL, 0x39, 0xA5); 1182 vga_wcrt(par->state.vgabase, 0x39, 0xA5);
977 1183
978 /* Identify chip type */ 1184 /* Identify chip type */
979 par->chip = id->driver_data & CHIP_MASK; 1185 par->chip = id->driver_data & CHIP_MASK;
980 par->rev = vga_rcrt(NULL, 0x2f); 1186 par->rev = vga_rcrt(par->state.vgabase, 0x2f);
981 if (par->chip & CHIP_UNDECIDED_FLAG) 1187 if (par->chip & CHIP_UNDECIDED_FLAG)
982 par->chip = s3_identification(par->chip); 1188 par->chip = s3_identification(par);
983 1189
984 /* Find how many physical memory there is on card */ 1190 /* Find how many physical memory there is on card */
985 /* 0x36 register is accessible even if other registers are locked */ 1191 /* 0x36 register is accessible even if other registers are locked */
986 regval = vga_rcrt(NULL, 0x36); 1192 regval = vga_rcrt(par->state.vgabase, 0x36);
987 if (par->chip == CHIP_360_TRIO3D_1X || 1193 if (par->chip == CHIP_360_TRIO3D_1X ||
988 par->chip == CHIP_362_TRIO3D_2X || 1194 par->chip == CHIP_362_TRIO3D_2X ||
989 par->chip == CHIP_368_TRIO3D_2X) { 1195 par->chip == CHIP_368_TRIO3D_2X ||
1196 par->chip == CHIP_365_TRIO3D) {
990 switch ((regval & 0xE0) >> 5) { 1197 switch ((regval & 0xE0) >> 5) {
991 case 0: /* 8MB -- only 4MB usable for display */ 1198 case 0: /* 8MB -- only 4MB usable for display */
992 case 1: /* 4MB with 32-bit bus */ 1199 case 1: /* 4MB with 32-bit bus */
993 case 2: /* 4MB */ 1200 case 2: /* 4MB */
994 info->screen_size = 4 << 20; 1201 info->screen_size = 4 << 20;
995 break; 1202 break;
1203 case 4: /* 2MB on 365 Trio3D */
996 case 6: /* 2MB */ 1204 case 6: /* 2MB */
997 info->screen_size = 2 << 20; 1205 info->screen_size = 2 << 20;
998 break; 1206 break;
999 } 1207 }
1208 } else if (par->chip == CHIP_357_VIRGE_GX2 ||
1209 par->chip == CHIP_359_VIRGE_GX2P) {
1210 switch ((regval & 0xC0) >> 6) {
1211 case 1: /* 4MB */
1212 info->screen_size = 4 << 20;
1213 break;
1214 case 3: /* 2MB */
1215 info->screen_size = 2 << 20;
1216 break;
1217 }
1000 } else 1218 } else
1001 info->screen_size = s3_memsizes[regval >> 5] << 10; 1219 info->screen_size = s3_memsizes[regval >> 5] << 10;
1002 info->fix.smem_len = info->screen_size; 1220 info->fix.smem_len = info->screen_size;
1003 1221
1004 /* Find MCLK frequency */ 1222 /* Find MCLK frequency */
1005 regval = vga_rseq(NULL, 0x10); 1223 regval = vga_rseq(par->state.vgabase, 0x10);
1006 par->mclk_freq = ((vga_rseq(NULL, 0x11) + 2) * 14318) / ((regval & 0x1F) + 2); 1224 par->mclk_freq = ((vga_rseq(par->state.vgabase, 0x11) + 2) * 14318) / ((regval & 0x1F) + 2);
1007 par->mclk_freq = par->mclk_freq >> (regval >> 5); 1225 par->mclk_freq = par->mclk_freq >> (regval >> 5);
1008 1226
1009 /* Restore locks */ 1227 /* Restore locks */
1010 vga_wcrt(NULL, 0x38, cr38); 1228 vga_wcrt(par->state.vgabase, 0x38, cr38);
1011 vga_wcrt(NULL, 0x39, cr39); 1229 vga_wcrt(par->state.vgabase, 0x39, cr39);
1012 1230
1013 strcpy(info->fix.id, s3_names [par->chip]); 1231 strcpy(info->fix.id, s3_names [par->chip]);
1014 info->fix.mmio_start = 0; 1232 info->fix.mmio_start = 0;
@@ -1018,12 +1236,77 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i
1018 info->fix.ypanstep = 0; 1236 info->fix.ypanstep = 0;
1019 info->fix.accel = FB_ACCEL_NONE; 1237 info->fix.accel = FB_ACCEL_NONE;
1020 info->pseudo_palette = (void*) (par->pseudo_palette); 1238 info->pseudo_palette = (void*) (par->pseudo_palette);
1239 info->var.bits_per_pixel = 8;
1240
1241#ifdef CONFIG_FB_S3_DDC
1242 /* Enable MMIO if needed */
1243 if (s3fb_ddc_needs_mmio(par->chip)) {
1244 par->mmio = ioremap(info->fix.smem_start + MMIO_OFFSET, MMIO_SIZE);
1245 if (par->mmio)
1246 svga_wcrt_mask(par->state.vgabase, 0x53, 0x08, 0x08); /* enable MMIO */
1247 else
1248 dev_err(info->device, "unable to map MMIO at 0x%lx, disabling DDC",
1249 info->fix.smem_start + MMIO_OFFSET);
1250 }
1251 if (!s3fb_ddc_needs_mmio(par->chip) || par->mmio)
1252 if (s3fb_setup_ddc_bus(info) == 0) {
1253 u8 *edid = fb_ddc_read(&par->ddc_adapter);
1254 par->ddc_registered = true;
1255 if (edid) {
1256 fb_edid_to_monspecs(edid, &info->monspecs);
1257 kfree(edid);
1258 if (!info->monspecs.modedb)
1259 dev_err(info->device, "error getting mode database\n");
1260 else {
1261 const struct fb_videomode *m;
1262
1263 fb_videomode_to_modelist(info->monspecs.modedb,
1264 info->monspecs.modedb_len,
1265 &info->modelist);
1266 m = fb_find_best_display(&info->monspecs, &info->modelist);
1267 if (m) {
1268 fb_videomode_to_var(&info->var, m);
1269 /* fill all other info->var's fields */
1270 if (s3fb_check_var(&info->var, info) == 0)
1271 found = true;
1272 }
1273 }
1274 }
1275 }
1276#endif
1277 if (!mode_option && !found)
1278 mode_option = "640x480-8@60";
1021 1279
1022 /* Prepare startup mode */ 1280 /* Prepare startup mode */
1023 rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8); 1281 if (mode_option) {
1024 if (! ((rc == 1) || (rc == 2))) { 1282 rc = fb_find_mode(&info->var, info, mode_option,
1025 rc = -EINVAL; 1283 info->monspecs.modedb, info->monspecs.modedb_len,
1026 dev_err(info->device, "mode %s not found\n", mode_option); 1284 NULL, info->var.bits_per_pixel);
1285 if (!rc || rc == 4) {
1286 rc = -EINVAL;
1287 dev_err(info->device, "mode %s not found\n", mode_option);
1288 fb_destroy_modedb(info->monspecs.modedb);
1289 info->monspecs.modedb = NULL;
1290 goto err_find_mode;
1291 }
1292 }
1293
1294 fb_destroy_modedb(info->monspecs.modedb);
1295 info->monspecs.modedb = NULL;
1296
1297 /* maximize virtual vertical size for fast scrolling */
1298 info->var.yres_virtual = info->fix.smem_len * 8 /
1299 (info->var.bits_per_pixel * info->var.xres_virtual);
1300 if (info->var.yres_virtual < info->var.yres) {
1301 dev_err(info->device, "virtual vertical size smaller than real\n");
1302 goto err_find_mode;
1303 }
1304
1305 /* maximize virtual vertical size for fast scrolling */
1306 info->var.yres_virtual = info->fix.smem_len * 8 /
1307 (info->var.bits_per_pixel * info->var.xres_virtual);
1308 if (info->var.yres_virtual < info->var.yres) {
1309 dev_err(info->device, "virtual vertical size smaller than real\n");
1027 goto err_find_mode; 1310 goto err_find_mode;
1028 } 1311 }
1029 1312
@@ -1044,8 +1327,8 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i
1044 1327
1045 if (par->chip == CHIP_UNKNOWN) 1328 if (par->chip == CHIP_UNKNOWN)
1046 printk(KERN_INFO "fb%d: unknown chip, CR2D=%x, CR2E=%x, CRT2F=%x, CRT30=%x\n", 1329 printk(KERN_INFO "fb%d: unknown chip, CR2D=%x, CR2E=%x, CRT2F=%x, CRT30=%x\n",
1047 info->node, vga_rcrt(NULL, 0x2d), vga_rcrt(NULL, 0x2e), 1330 info->node, vga_rcrt(par->state.vgabase, 0x2d), vga_rcrt(par->state.vgabase, 0x2e),
1048 vga_rcrt(NULL, 0x2f), vga_rcrt(NULL, 0x30)); 1331 vga_rcrt(par->state.vgabase, 0x2f), vga_rcrt(par->state.vgabase, 0x30));
1049 1332
1050 /* Record a reference to the driver data */ 1333 /* Record a reference to the driver data */
1051 pci_set_drvdata(dev, info); 1334 pci_set_drvdata(dev, info);
@@ -1064,6 +1347,12 @@ err_reg_fb:
1064 fb_dealloc_cmap(&info->cmap); 1347 fb_dealloc_cmap(&info->cmap);
1065err_alloc_cmap: 1348err_alloc_cmap:
1066err_find_mode: 1349err_find_mode:
1350#ifdef CONFIG_FB_S3_DDC
1351 if (par->ddc_registered)
1352 i2c_del_adapter(&par->ddc_adapter);
1353 if (par->mmio)
1354 iounmap(par->mmio);
1355#endif
1067 pci_iounmap(dev, info->screen_base); 1356 pci_iounmap(dev, info->screen_base);
1068err_iomap: 1357err_iomap:
1069 pci_release_regions(dev); 1358 pci_release_regions(dev);
@@ -1080,12 +1369,11 @@ err_enable_device:
1080static void __devexit s3_pci_remove(struct pci_dev *dev) 1369static void __devexit s3_pci_remove(struct pci_dev *dev)
1081{ 1370{
1082 struct fb_info *info = pci_get_drvdata(dev); 1371 struct fb_info *info = pci_get_drvdata(dev);
1372 struct s3fb_info __maybe_unused *par = info->par;
1083 1373
1084 if (info) { 1374 if (info) {
1085 1375
1086#ifdef CONFIG_MTRR 1376#ifdef CONFIG_MTRR
1087 struct s3fb_info *par = info->par;
1088
1089 if (par->mtrr_reg >= 0) { 1377 if (par->mtrr_reg >= 0) {
1090 mtrr_del(par->mtrr_reg, 0, 0); 1378 mtrr_del(par->mtrr_reg, 0, 0);
1091 par->mtrr_reg = -1; 1379 par->mtrr_reg = -1;
@@ -1095,6 +1383,13 @@ static void __devexit s3_pci_remove(struct pci_dev *dev)
1095 unregister_framebuffer(info); 1383 unregister_framebuffer(info);
1096 fb_dealloc_cmap(&info->cmap); 1384 fb_dealloc_cmap(&info->cmap);
1097 1385
1386#ifdef CONFIG_FB_S3_DDC
1387 if (par->ddc_registered)
1388 i2c_del_adapter(&par->ddc_adapter);
1389 if (par->mmio)
1390 iounmap(par->mmio);
1391#endif
1392
1098 pci_iounmap(dev, info->screen_base); 1393 pci_iounmap(dev, info->screen_base);
1099 pci_release_regions(dev); 1394 pci_release_regions(dev);
1100/* pci_disable_device(dev); */ 1395/* pci_disable_device(dev); */
@@ -1113,12 +1408,12 @@ static int s3_pci_suspend(struct pci_dev* dev, pm_message_t state)
1113 1408
1114 dev_info(info->device, "suspend\n"); 1409 dev_info(info->device, "suspend\n");
1115 1410
1116 acquire_console_sem(); 1411 console_lock();
1117 mutex_lock(&(par->open_lock)); 1412 mutex_lock(&(par->open_lock));
1118 1413
1119 if ((state.event == PM_EVENT_FREEZE) || (par->ref_count == 0)) { 1414 if ((state.event == PM_EVENT_FREEZE) || (par->ref_count == 0)) {
1120 mutex_unlock(&(par->open_lock)); 1415 mutex_unlock(&(par->open_lock));
1121 release_console_sem(); 1416 console_unlock();
1122 return 0; 1417 return 0;
1123 } 1418 }
1124 1419
@@ -1129,7 +1424,7 @@ static int s3_pci_suspend(struct pci_dev* dev, pm_message_t state)
1129 pci_set_power_state(dev, pci_choose_state(dev, state)); 1424 pci_set_power_state(dev, pci_choose_state(dev, state));
1130 1425
1131 mutex_unlock(&(par->open_lock)); 1426 mutex_unlock(&(par->open_lock));
1132 release_console_sem(); 1427 console_unlock();
1133 1428
1134 return 0; 1429 return 0;
1135} 1430}
@@ -1145,12 +1440,12 @@ static int s3_pci_resume(struct pci_dev* dev)
1145 1440
1146 dev_info(info->device, "resume\n"); 1441 dev_info(info->device, "resume\n");
1147 1442
1148 acquire_console_sem(); 1443 console_lock();
1149 mutex_lock(&(par->open_lock)); 1444 mutex_lock(&(par->open_lock));
1150 1445
1151 if (par->ref_count == 0) { 1446 if (par->ref_count == 0) {
1152 mutex_unlock(&(par->open_lock)); 1447 mutex_unlock(&(par->open_lock));
1153 release_console_sem(); 1448 console_unlock();
1154 return 0; 1449 return 0;
1155 } 1450 }
1156 1451
@@ -1159,7 +1454,7 @@ static int s3_pci_resume(struct pci_dev* dev)
1159 err = pci_enable_device(dev); 1454 err = pci_enable_device(dev);
1160 if (err) { 1455 if (err) {
1161 mutex_unlock(&(par->open_lock)); 1456 mutex_unlock(&(par->open_lock));
1162 release_console_sem(); 1457 console_unlock();
1163 dev_err(info->device, "error %d enabling device for resume\n", err); 1458 dev_err(info->device, "error %d enabling device for resume\n", err);
1164 return err; 1459 return err;
1165 } 1460 }
@@ -1169,7 +1464,7 @@ static int s3_pci_resume(struct pci_dev* dev)
1169 fb_set_suspend(info, 0); 1464 fb_set_suspend(info, 0);
1170 1465
1171 mutex_unlock(&(par->open_lock)); 1466 mutex_unlock(&(par->open_lock));
1172 release_console_sem(); 1467 console_unlock();
1173 1468
1174 return 0; 1469 return 0;
1175} 1470}
@@ -1188,10 +1483,11 @@ static struct pci_device_id s3_devices[] __devinitdata = {
1188 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x5631), .driver_data = CHIP_325_VIRGE}, 1483 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x5631), .driver_data = CHIP_325_VIRGE},
1189 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x883D), .driver_data = CHIP_988_VIRGE_VX}, 1484 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x883D), .driver_data = CHIP_988_VIRGE_VX},
1190 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A01), .driver_data = CHIP_XXX_VIRGE_DXGX}, 1485 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A01), .driver_data = CHIP_XXX_VIRGE_DXGX},
1191 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_356_VIRGE_GX2}, 1486 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_357_VIRGE_GX2},
1192 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_357_VIRGE_GX2P}, 1487 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_359_VIRGE_GX2P},
1193 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P}, 1488 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P},
1194 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A13), .driver_data = CHIP_36X_TRIO3D_1X_2X}, 1489 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A13), .driver_data = CHIP_36X_TRIO3D_1X_2X},
1490 {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8904), .driver_data = CHIP_365_TRIO3D},
1195 1491
1196 {0, 0, 0, 0, 0, 0, 0} 1492 {0, 0, 0, 0, 0, 0, 0}
1197}; 1493};
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c
index ed371c868b3a..80fa87e2ae2f 100644
--- a/drivers/video/savage/savagefb-i2c.c
+++ b/drivers/video/savage/savagefb-i2c.c
@@ -159,8 +159,7 @@ static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
159 else 159 else
160 dev_warn(&chan->par->pcidev->dev, 160 dev_warn(&chan->par->pcidev->dev,
161 "Failed to register I2C bus %s.\n", name); 161 "Failed to register I2C bus %s.\n", name);
162 } else 162 }
163 chan->par = NULL;
164 163
165 return rc; 164 return rc;
166} 165}
@@ -170,9 +169,10 @@ void savagefb_create_i2c_busses(struct fb_info *info)
170 struct savagefb_par *par = info->par; 169 struct savagefb_par *par = info->par;
171 par->chan.par = par; 170 par->chan.par = par;
172 171
173 switch(info->fix.accel) { 172 switch (par->chip) {
174 case FB_ACCEL_PROSAVAGE_DDRK: 173 case S3_PROSAVAGE:
175 case FB_ACCEL_PROSAVAGE_PM: 174 case S3_PROSAVAGEDDR:
175 case S3_TWISTER:
176 par->chan.reg = CR_SERIAL2; 176 par->chan.reg = CR_SERIAL2;
177 par->chan.ioaddr = par->mmio.vbase; 177 par->chan.ioaddr = par->mmio.vbase;
178 par->chan.algo.setsda = prosavage_gpio_setsda; 178 par->chan.algo.setsda = prosavage_gpio_setsda;
@@ -180,9 +180,18 @@ void savagefb_create_i2c_busses(struct fb_info *info)
180 par->chan.algo.getsda = prosavage_gpio_getsda; 180 par->chan.algo.getsda = prosavage_gpio_getsda;
181 par->chan.algo.getscl = prosavage_gpio_getscl; 181 par->chan.algo.getscl = prosavage_gpio_getscl;
182 break; 182 break;
183 case FB_ACCEL_SAVAGE4: 183 case S3_SAVAGE4:
184 case FB_ACCEL_SAVAGE2000: 184 par->chan.reg = CR_SERIAL1;
185 par->chan.reg = 0xff20; 185 if (par->pcidev->revision > 1 && !(VGArCR(0xa6, par) & 0x40))
186 par->chan.reg = CR_SERIAL2;
187 par->chan.ioaddr = par->mmio.vbase;
188 par->chan.algo.setsda = prosavage_gpio_setsda;
189 par->chan.algo.setscl = prosavage_gpio_setscl;
190 par->chan.algo.getsda = prosavage_gpio_getsda;
191 par->chan.algo.getscl = prosavage_gpio_getscl;
192 break;
193 case S3_SAVAGE2000:
194 par->chan.reg = MM_SERIAL1;
186 par->chan.ioaddr = par->mmio.vbase; 195 par->chan.ioaddr = par->mmio.vbase;
187 par->chan.algo.setsda = savage4_gpio_setsda; 196 par->chan.algo.setsda = savage4_gpio_setsda;
188 par->chan.algo.setscl = savage4_gpio_setscl; 197 par->chan.algo.setscl = savage4_gpio_setscl;
diff --git a/drivers/video/savage/savagefb.h b/drivers/video/savage/savagefb.h
index 8bfdfc3c5234..32549d177b19 100644
--- a/drivers/video/savage/savagefb.h
+++ b/drivers/video/savage/savagefb.h
@@ -13,7 +13,6 @@
13#define __SAVAGEFB_H__ 13#define __SAVAGEFB_H__
14 14
15#include <linux/i2c.h> 15#include <linux/i2c.h>
16#include <linux/i2c-id.h>
17#include <linux/i2c-algo-bit.h> 16#include <linux/i2c-algo-bit.h>
18#include <linux/mutex.h> 17#include <linux/mutex.h>
19#include <video/vga.h> 18#include <video/vga.h>
@@ -37,7 +36,6 @@
37#define PCI_CHIP_SAVAGE_IX 0x8c13 36#define PCI_CHIP_SAVAGE_IX 0x8c13
38#define PCI_CHIP_PROSAVAGE_PM 0x8a25 37#define PCI_CHIP_PROSAVAGE_PM 0x8a25
39#define PCI_CHIP_PROSAVAGE_KM 0x8a26 38#define PCI_CHIP_PROSAVAGE_KM 0x8a26
40 /* Twister is a code name; hope I get the real name soon. */
41#define PCI_CHIP_S3TWISTER_P 0x8d01 39#define PCI_CHIP_S3TWISTER_P 0x8d01
42#define PCI_CHIP_S3TWISTER_K 0x8d02 40#define PCI_CHIP_S3TWISTER_K 0x8d02
43#define PCI_CHIP_PROSAVAGE_DDR 0x8d03 41#define PCI_CHIP_PROSAVAGE_DDR 0x8d03
@@ -53,14 +51,15 @@
53#define PCI_CHIP_SUPSAV_IXCDDR 0x8c2f 51#define PCI_CHIP_SUPSAV_IXCDDR 0x8c2f
54 52
55 53
54#define S3_SAVAGE_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000))
56 55
57#define S3_SAVAGE3D_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX)) 56#define S3_SAVAGE3D_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX))
58 57
59#define S3_SAVAGE4_SERIES(chip) ((chip==S3_SAVAGE4) || (chip==S3_PROSAVAGE)) 58#define S3_SAVAGE4_SERIES(chip) ((chip>=S3_SAVAGE4) || (chip<=S3_PROSAVAGEDDR))
60 59
61#define S3_SAVAGE_MOBILE_SERIES(chip) ((chip==S3_SAVAGE_MX) || (chip==S3_SUPERSAVAGE)) 60#define S3_SAVAGE_MOBILE_SERIES(chip) ((chip==S3_SAVAGE_MX) || (chip==S3_SUPERSAVAGE))
62 61
63#define S3_SAVAGE_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000)) 62#define S3_MOBILE_TWISTER_SERIES(chip) ((chip==S3_TWISTER) || (chip==S3_PROSAVAGEDDR))
64 63
65/* Chip tags. These are used to group the adapters into 64/* Chip tags. These are used to group the adapters into
66 * related families. 65 * related families.
@@ -72,6 +71,8 @@ typedef enum {
72 S3_SAVAGE_MX, 71 S3_SAVAGE_MX,
73 S3_SAVAGE4, 72 S3_SAVAGE4,
74 S3_PROSAVAGE, 73 S3_PROSAVAGE,
74 S3_TWISTER,
75 S3_PROSAVAGEDDR,
75 S3_SUPERSAVAGE, 76 S3_SUPERSAVAGE,
76 S3_SAVAGE2000, 77 S3_SAVAGE2000,
77 S3_LAST 78 S3_LAST
@@ -154,7 +155,7 @@ struct savage_reg {
154 unsigned char CRTC[25]; /* Crtc Controller */ 155 unsigned char CRTC[25]; /* Crtc Controller */
155 unsigned char Sequencer[5]; /* Video Sequencer */ 156 unsigned char Sequencer[5]; /* Video Sequencer */
156 unsigned char Graphics[9]; /* Video Graphics */ 157 unsigned char Graphics[9]; /* Video Graphics */
157 unsigned char Attribute[21]; /* Video Atribute */ 158 unsigned char Attribute[21]; /* Video Attribute */
158 159
159 unsigned int mode, refresh; 160 unsigned int mode, refresh;
160 unsigned char SR08, SR0E, SR0F; 161 unsigned char SR08, SR0E, SR0F;
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 842d157e1025..4de541ca9c52 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -328,7 +328,9 @@ SavageSetup2DEngine(struct savagefb_par *par)
328 savage_out32(0x48C18, savage_in32(0x48C18, par) | 0x0C, par); 328 savage_out32(0x48C18, savage_in32(0x48C18, par) | 0x0C, par);
329 break; 329 break;
330 case S3_SAVAGE4: 330 case S3_SAVAGE4:
331 case S3_TWISTER:
331 case S3_PROSAVAGE: 332 case S3_PROSAVAGE:
333 case S3_PROSAVAGEDDR:
332 case S3_SUPERSAVAGE: 334 case S3_SUPERSAVAGE:
333 /* Disable BCI */ 335 /* Disable BCI */
334 savage_out32(0x48C18, savage_in32(0x48C18, par) & 0x3FF0, par); 336 savage_out32(0x48C18, savage_in32(0x48C18, par) & 0x3FF0, par);
@@ -385,7 +387,7 @@ SavageSetup2DEngine(struct savagefb_par *par)
385 BCI_SEND(GlobalBitmapDescriptor); 387 BCI_SEND(GlobalBitmapDescriptor);
386 388
387 /* 389 /*
388 * I don't know why, sending this twice fixes the intial black screen, 390 * I don't know why, sending this twice fixes the initial black screen,
389 * prevents X from crashing at least in Toshiba laptops with SavageIX. 391 * prevents X from crashing at least in Toshiba laptops with SavageIX.
390 * --Tony 392 * --Tony
391 */ 393 */
@@ -1886,6 +1888,8 @@ static int savage_init_hw(struct savagefb_par *par)
1886 break; 1888 break;
1887 1889
1888 case S3_PROSAVAGE: 1890 case S3_PROSAVAGE:
1891 case S3_PROSAVAGEDDR:
1892 case S3_TWISTER:
1889 videoRam = RamSavageNB[(config1 & 0xE0) >> 5] * 1024; 1893 videoRam = RamSavageNB[(config1 & 0xE0) >> 5] * 1024;
1890 break; 1894 break;
1891 1895
@@ -1963,7 +1967,8 @@ static int savage_init_hw(struct savagefb_par *par)
1963 } 1967 }
1964 } 1968 }
1965 1969
1966 if (S3_SAVAGE_MOBILE_SERIES(par->chip) && !par->crtonly) 1970 if ((S3_SAVAGE_MOBILE_SERIES(par->chip) ||
1971 S3_MOBILE_TWISTER_SERIES(par->chip)) && !par->crtonly)
1967 par->display_type = DISP_LCD; 1972 par->display_type = DISP_LCD;
1968 else if (dvi || (par->chip == S3_SAVAGE4 && par->dvi)) 1973 else if (dvi || (par->chip == S3_SAVAGE4 && par->dvi))
1969 par->display_type = DISP_DFP; 1974 par->display_type = DISP_DFP;
@@ -2111,19 +2116,19 @@ static int __devinit savage_init_fb_info(struct fb_info *info,
2111 snprintf(info->fix.id, 16, "ProSavageKM"); 2116 snprintf(info->fix.id, 16, "ProSavageKM");
2112 break; 2117 break;
2113 case FB_ACCEL_S3TWISTER_P: 2118 case FB_ACCEL_S3TWISTER_P:
2114 par->chip = S3_PROSAVAGE; 2119 par->chip = S3_TWISTER;
2115 snprintf(info->fix.id, 16, "TwisterP"); 2120 snprintf(info->fix.id, 16, "TwisterP");
2116 break; 2121 break;
2117 case FB_ACCEL_S3TWISTER_K: 2122 case FB_ACCEL_S3TWISTER_K:
2118 par->chip = S3_PROSAVAGE; 2123 par->chip = S3_TWISTER;
2119 snprintf(info->fix.id, 16, "TwisterK"); 2124 snprintf(info->fix.id, 16, "TwisterK");
2120 break; 2125 break;
2121 case FB_ACCEL_PROSAVAGE_DDR: 2126 case FB_ACCEL_PROSAVAGE_DDR:
2122 par->chip = S3_PROSAVAGE; 2127 par->chip = S3_PROSAVAGEDDR;
2123 snprintf(info->fix.id, 16, "ProSavageDDR"); 2128 snprintf(info->fix.id, 16, "ProSavageDDR");
2124 break; 2129 break;
2125 case FB_ACCEL_PROSAVAGE_DDRK: 2130 case FB_ACCEL_PROSAVAGE_DDRK:
2126 par->chip = S3_PROSAVAGE; 2131 par->chip = S3_PROSAVAGEDDR;
2127 snprintf(info->fix.id, 16, "ProSavage8"); 2132 snprintf(info->fix.id, 16, "ProSavage8");
2128 break; 2133 break;
2129 } 2134 }
@@ -2211,7 +2216,7 @@ static int __devinit savagefb_probe(struct pci_dev* dev,
2211 goto failed_mmio; 2216 goto failed_mmio;
2212 2217
2213 video_len = savage_init_hw(par); 2218 video_len = savage_init_hw(par);
2214 /* FIXME: cant be negative */ 2219 /* FIXME: can't be negative */
2215 if (video_len < 0) { 2220 if (video_len < 0) {
2216 err = video_len; 2221 err = video_len;
2217 goto failed_mmio; 2222 goto failed_mmio;
@@ -2232,6 +2237,22 @@ static int __devinit savagefb_probe(struct pci_dev* dev,
2232 &info->modelist); 2237 &info->modelist);
2233#endif 2238#endif
2234 info->var = savagefb_var800x600x8; 2239 info->var = savagefb_var800x600x8;
2240 /* if a panel was detected, default to a CVT mode instead */
2241 if (par->SavagePanelWidth) {
2242 struct fb_videomode cvt_mode;
2243
2244 memset(&cvt_mode, 0, sizeof(cvt_mode));
2245 cvt_mode.xres = par->SavagePanelWidth;
2246 cvt_mode.yres = par->SavagePanelHeight;
2247 cvt_mode.refresh = 60;
2248 /* FIXME: if we know there is only the panel
2249 * we can enable reduced blanking as well */
2250 if (fb_find_mode_cvt(&cvt_mode, 0, 0))
2251 printk(KERN_WARNING "No CVT mode found for panel\n");
2252 else if (fb_find_mode(&info->var, info, NULL, NULL, 0,
2253 &cvt_mode, 0) != 3)
2254 info->var = savagefb_var800x600x8;
2255 }
2235 2256
2236 if (mode_option) { 2257 if (mode_option) {
2237 fb_find_mode(&info->var, info, mode_option, 2258 fb_find_mode(&info->var, info, mode_option,
@@ -2373,7 +2394,7 @@ static int savagefb_suspend(struct pci_dev *dev, pm_message_t mesg)
2373 if (mesg.event == PM_EVENT_FREEZE) 2394 if (mesg.event == PM_EVENT_FREEZE)
2374 return 0; 2395 return 0;
2375 2396
2376 acquire_console_sem(); 2397 console_lock();
2377 fb_set_suspend(info, 1); 2398 fb_set_suspend(info, 1);
2378 2399
2379 if (info->fbops->fb_sync) 2400 if (info->fbops->fb_sync)
@@ -2385,7 +2406,7 @@ static int savagefb_suspend(struct pci_dev *dev, pm_message_t mesg)
2385 pci_save_state(dev); 2406 pci_save_state(dev);
2386 pci_disable_device(dev); 2407 pci_disable_device(dev);
2387 pci_set_power_state(dev, pci_choose_state(dev, mesg)); 2408 pci_set_power_state(dev, pci_choose_state(dev, mesg));
2388 release_console_sem(); 2409 console_unlock();
2389 2410
2390 return 0; 2411 return 0;
2391} 2412}
@@ -2409,7 +2430,7 @@ static int savagefb_resume(struct pci_dev* dev)
2409 return 0; 2430 return 0;
2410 } 2431 }
2411 2432
2412 acquire_console_sem(); 2433 console_lock();
2413 2434
2414 pci_set_power_state(dev, PCI_D0); 2435 pci_set_power_state(dev, PCI_D0);
2415 pci_restore_state(dev); 2436 pci_restore_state(dev);
@@ -2423,7 +2444,7 @@ static int savagefb_resume(struct pci_dev* dev)
2423 savagefb_set_par(info); 2444 savagefb_set_par(info);
2424 fb_set_suspend(info, 0); 2445 fb_set_suspend(info, 0);
2425 savagefb_blank(FB_BLANK_UNBLANK, info); 2446 savagefb_blank(FB_BLANK_UNBLANK, info);
2426 release_console_sem(); 2447 console_unlock();
2427 2448
2428 return 0; 2449 return 0;
2429} 2450}
diff --git a/drivers/video/sh7760fb.c b/drivers/video/sh7760fb.c
index bea38fce2470..45e47d847163 100644
--- a/drivers/video/sh7760fb.c
+++ b/drivers/video/sh7760fb.c
@@ -459,14 +459,14 @@ static int __devinit sh7760fb_probe(struct platform_device *pdev)
459 } 459 }
460 460
461 par->ioarea = request_mem_region(res->start, 461 par->ioarea = request_mem_region(res->start,
462 (res->end - res->start), pdev->name); 462 resource_size(res), pdev->name);
463 if (!par->ioarea) { 463 if (!par->ioarea) {
464 dev_err(&pdev->dev, "mmio area busy\n"); 464 dev_err(&pdev->dev, "mmio area busy\n");
465 ret = -EBUSY; 465 ret = -EBUSY;
466 goto out_fb; 466 goto out_fb;
467 } 467 }
468 468
469 par->base = ioremap_nocache(res->start, res->end - res->start + 1); 469 par->base = ioremap_nocache(res->start, resource_size(res));
470 if (!par->base) { 470 if (!par->base) {
471 dev_err(&pdev->dev, "cannot remap\n"); 471 dev_err(&pdev->dev, "cannot remap\n");
472 ret = -ENODEV; 472 ret = -ENODEV;
@@ -551,8 +551,7 @@ out_unmap:
551 free_irq(par->irq, &par->vsync); 551 free_irq(par->irq, &par->vsync);
552 iounmap(par->base); 552 iounmap(par->base);
553out_res: 553out_res:
554 release_resource(par->ioarea); 554 release_mem_region(res->start, resource_size(res));
555 kfree(par->ioarea);
556out_fb: 555out_fb:
557 framebuffer_release(info); 556 framebuffer_release(info);
558 return ret; 557 return ret;
@@ -570,8 +569,7 @@ static int __devexit sh7760fb_remove(struct platform_device *dev)
570 if (par->irq >= 0) 569 if (par->irq >= 0)
571 free_irq(par->irq, par); 570 free_irq(par->irq, par);
572 iounmap(par->base); 571 iounmap(par->base);
573 release_resource(par->ioarea); 572 release_mem_region(par->ioarea->start, resource_size(par->ioarea));
574 kfree(par->ioarea);
575 framebuffer_release(info); 573 framebuffer_release(info);
576 platform_set_drvdata(dev, NULL); 574 platform_set_drvdata(dev, NULL);
577 575
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c
index 5699ce0c1780..24640c8458ab 100644
--- a/drivers/video/sh_mipi_dsi.c
+++ b/drivers/video/sh_mipi_dsi.c
@@ -13,6 +13,7 @@
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/io.h> 14#include <linux/io.h>
15#include <linux/platform_device.h> 15#include <linux/platform_device.h>
16#include <linux/pm_runtime.h>
16#include <linux/slab.h> 17#include <linux/slab.h>
17#include <linux/string.h> 18#include <linux/string.h>
18#include <linux/types.h> 19#include <linux/types.h>
@@ -21,18 +22,40 @@
21#include <video/sh_mipi_dsi.h> 22#include <video/sh_mipi_dsi.h>
22#include <video/sh_mobile_lcdc.h> 23#include <video/sh_mobile_lcdc.h>
23 24
24#define CMTSRTCTR 0x80d0 25#define SYSCTRL 0x0000
25#define CMTSRTREQ 0x8070 26#define SYSCONF 0x0004
26 27#define TIMSET 0x0008
28#define RESREQSET0 0x0018
29#define RESREQSET1 0x001c
30#define HSTTOVSET 0x0020
31#define LPRTOVSET 0x0024
32#define TATOVSET 0x0028
33#define PRTOVSET 0x002c
34#define DSICTRL 0x0030
27#define DSIINTE 0x0060 35#define DSIINTE 0x0060
36#define PHYCTRL 0x0070
37
38/* relative to linkbase */
39#define DTCTR 0x0000
40#define VMCTR1 0x0020
41#define VMCTR2 0x0024
42#define VMLEN1 0x0028
43#define CMTSRTREQ 0x0070
44#define CMTSRTCTR 0x00d0
28 45
29/* E.g., sh7372 has 2 MIPI-DSIs - one for each LCDC */ 46/* E.g., sh7372 has 2 MIPI-DSIs - one for each LCDC */
30#define MAX_SH_MIPI_DSI 2 47#define MAX_SH_MIPI_DSI 2
31 48
32struct sh_mipi { 49struct sh_mipi {
33 void __iomem *base; 50 void __iomem *base;
51 void __iomem *linkbase;
34 struct clk *dsit_clk; 52 struct clk *dsit_clk;
35 struct clk *dsip_clk; 53 struct clk *dsip_clk;
54 struct device *dev;
55
56 void *next_board_data;
57 void (*next_display_on)(void *board_data, struct fb_info *info);
58 void (*next_display_off)(void *board_data);
36}; 59};
37 60
38static struct sh_mipi *mipi_dsi[MAX_SH_MIPI_DSI]; 61static struct sh_mipi *mipi_dsi[MAX_SH_MIPI_DSI];
@@ -55,10 +78,10 @@ static int sh_mipi_send_short(struct sh_mipi *mipi, u8 dsi_cmd,
55 int cnt = 100; 78 int cnt = 100;
56 79
57 /* transmit a short packet to LCD panel */ 80 /* transmit a short packet to LCD panel */
58 iowrite32(1 | data, mipi->base + 0x80d0); /* CMTSRTCTR */ 81 iowrite32(1 | data, mipi->linkbase + CMTSRTCTR);
59 iowrite32(1, mipi->base + 0x8070); /* CMTSRTREQ */ 82 iowrite32(1, mipi->linkbase + CMTSRTREQ);
60 83
61 while ((ioread32(mipi->base + 0x8070) & 1) && --cnt) 84 while ((ioread32(mipi->linkbase + CMTSRTREQ) & 1) && --cnt)
62 udelay(1); 85 udelay(1);
63 86
64 return cnt ? 0 : -ETIMEDOUT; 87 return cnt ? 0 : -ETIMEDOUT;
@@ -90,7 +113,7 @@ static void sh_mipi_dsi_enable(struct sh_mipi *mipi, bool enable)
90 * enable LCDC data tx, transition to LPS after completion of each HS 113 * enable LCDC data tx, transition to LPS after completion of each HS
91 * packet 114 * packet
92 */ 115 */
93 iowrite32(0x00000002 | enable, mipi->base + 0x8000); /* DTCTR */ 116 iowrite32(0x00000002 | enable, mipi->linkbase + DTCTR);
94} 117}
95 118
96static void sh_mipi_shutdown(struct platform_device *pdev) 119static void sh_mipi_shutdown(struct platform_device *pdev)
@@ -104,14 +127,22 @@ static void mipi_display_on(void *arg, struct fb_info *info)
104{ 127{
105 struct sh_mipi *mipi = arg; 128 struct sh_mipi *mipi = arg;
106 129
130 pm_runtime_get_sync(mipi->dev);
107 sh_mipi_dsi_enable(mipi, true); 131 sh_mipi_dsi_enable(mipi, true);
132
133 if (mipi->next_display_on)
134 mipi->next_display_on(mipi->next_board_data, info);
108} 135}
109 136
110static void mipi_display_off(void *arg) 137static void mipi_display_off(void *arg)
111{ 138{
112 struct sh_mipi *mipi = arg; 139 struct sh_mipi *mipi = arg;
113 140
141 if (mipi->next_display_off)
142 mipi->next_display_off(mipi->next_board_data);
143
114 sh_mipi_dsi_enable(mipi, false); 144 sh_mipi_dsi_enable(mipi, false);
145 pm_runtime_put(mipi->dev);
115} 146}
116 147
117static int __init sh_mipi_setup(struct sh_mipi *mipi, 148static int __init sh_mipi_setup(struct sh_mipi *mipi,
@@ -119,87 +150,90 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
119{ 150{
120 void __iomem *base = mipi->base; 151 void __iomem *base = mipi->base;
121 struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan; 152 struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan;
122 u32 pctype, datatype, pixfmt; 153 u32 pctype, datatype, pixfmt, linelength, vmctr2 = 0x00e00000;
123 u32 linelength;
124 bool yuv; 154 bool yuv;
125 155
126 /* Select data format */ 156 /*
157 * Select data format. MIPI DSI is not hot-pluggable, so, we just use
158 * the default videomode. If this ever becomes a problem, We'll have to
159 * move this to mipi_display_on() above and use info->var.xres
160 */
127 switch (pdata->data_format) { 161 switch (pdata->data_format) {
128 case MIPI_RGB888: 162 case MIPI_RGB888:
129 pctype = 0; 163 pctype = 0;
130 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; 164 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
131 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; 165 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
132 linelength = ch->lcd_cfg.xres * 3; 166 linelength = ch->lcd_cfg[0].xres * 3;
133 yuv = false; 167 yuv = false;
134 break; 168 break;
135 case MIPI_RGB565: 169 case MIPI_RGB565:
136 pctype = 1; 170 pctype = 1;
137 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; 171 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
138 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; 172 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
139 linelength = ch->lcd_cfg.xres * 2; 173 linelength = ch->lcd_cfg[0].xres * 2;
140 yuv = false; 174 yuv = false;
141 break; 175 break;
142 case MIPI_RGB666_LP: 176 case MIPI_RGB666_LP:
143 pctype = 2; 177 pctype = 2;
144 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; 178 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
145 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; 179 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
146 linelength = ch->lcd_cfg.xres * 3; 180 linelength = ch->lcd_cfg[0].xres * 3;
147 yuv = false; 181 yuv = false;
148 break; 182 break;
149 case MIPI_RGB666: 183 case MIPI_RGB666:
150 pctype = 3; 184 pctype = 3;
151 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; 185 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
152 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; 186 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
153 linelength = (ch->lcd_cfg.xres * 18 + 7) / 8; 187 linelength = (ch->lcd_cfg[0].xres * 18 + 7) / 8;
154 yuv = false; 188 yuv = false;
155 break; 189 break;
156 case MIPI_BGR888: 190 case MIPI_BGR888:
157 pctype = 8; 191 pctype = 8;
158 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; 192 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
159 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; 193 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
160 linelength = ch->lcd_cfg.xres * 3; 194 linelength = ch->lcd_cfg[0].xres * 3;
161 yuv = false; 195 yuv = false;
162 break; 196 break;
163 case MIPI_BGR565: 197 case MIPI_BGR565:
164 pctype = 9; 198 pctype = 9;
165 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; 199 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
166 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; 200 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
167 linelength = ch->lcd_cfg.xres * 2; 201 linelength = ch->lcd_cfg[0].xres * 2;
168 yuv = false; 202 yuv = false;
169 break; 203 break;
170 case MIPI_BGR666_LP: 204 case MIPI_BGR666_LP:
171 pctype = 0xa; 205 pctype = 0xa;
172 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; 206 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
173 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; 207 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
174 linelength = ch->lcd_cfg.xres * 3; 208 linelength = ch->lcd_cfg[0].xres * 3;
175 yuv = false; 209 yuv = false;
176 break; 210 break;
177 case MIPI_BGR666: 211 case MIPI_BGR666:
178 pctype = 0xb; 212 pctype = 0xb;
179 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; 213 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
180 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; 214 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
181 linelength = (ch->lcd_cfg.xres * 18 + 7) / 8; 215 linelength = (ch->lcd_cfg[0].xres * 18 + 7) / 8;
182 yuv = false; 216 yuv = false;
183 break; 217 break;
184 case MIPI_YUYV: 218 case MIPI_YUYV:
185 pctype = 4; 219 pctype = 4;
186 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; 220 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
187 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; 221 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
188 linelength = ch->lcd_cfg.xres * 2; 222 linelength = ch->lcd_cfg[0].xres * 2;
189 yuv = true; 223 yuv = true;
190 break; 224 break;
191 case MIPI_UYVY: 225 case MIPI_UYVY:
192 pctype = 5; 226 pctype = 5;
193 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; 227 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
194 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; 228 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
195 linelength = ch->lcd_cfg.xres * 2; 229 linelength = ch->lcd_cfg[0].xres * 2;
196 yuv = true; 230 yuv = true;
197 break; 231 break;
198 case MIPI_YUV420_L: 232 case MIPI_YUV420_L:
199 pctype = 6; 233 pctype = 6;
200 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; 234 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
201 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; 235 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
202 linelength = (ch->lcd_cfg.xres * 12 + 7) / 8; 236 linelength = (ch->lcd_cfg[0].xres * 12 + 7) / 8;
203 yuv = true; 237 yuv = true;
204 break; 238 break;
205 case MIPI_YUV420: 239 case MIPI_YUV420:
@@ -207,7 +241,7 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
207 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; 241 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
208 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; 242 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
209 /* Length of U/V line */ 243 /* Length of U/V line */
210 linelength = (ch->lcd_cfg.xres + 1) / 2; 244 linelength = (ch->lcd_cfg[0].xres + 1) / 2;
211 yuv = true; 245 yuv = true;
212 break; 246 break;
213 default: 247 default:
@@ -219,10 +253,10 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
219 return -EINVAL; 253 return -EINVAL;
220 254
221 /* reset DSI link */ 255 /* reset DSI link */
222 iowrite32(0x00000001, base); /* SYSCTRL */ 256 iowrite32(0x00000001, base + SYSCTRL);
223 /* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */ 257 /* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */
224 udelay(50); 258 udelay(50);
225 iowrite32(0x00000000, base); /* SYSCTRL */ 259 iowrite32(0x00000000, base + SYSCTRL);
226 260
227 /* setup DSI link */ 261 /* setup DSI link */
228 262
@@ -234,7 +268,7 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
234 * ECC check enable 268 * ECC check enable
235 * additionally enable first two lanes 269 * additionally enable first two lanes
236 */ 270 */
237 iowrite32(0x00003703, base + 0x04); /* SYSCONF */ 271 iowrite32(0x00003703, base + SYSCONF);
238 /* 272 /*
239 * T_wakeup = 0x7000 273 * T_wakeup = 0x7000
240 * T_hs-trail = 3 274 * T_hs-trail = 3
@@ -242,28 +276,28 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
242 * T_clk-trail = 3 276 * T_clk-trail = 3
243 * T_clk-prepare = 2 277 * T_clk-prepare = 2
244 */ 278 */
245 iowrite32(0x70003332, base + 0x08); /* TIMSET */ 279 iowrite32(0x70003332, base + TIMSET);
246 /* no responses requested */ 280 /* no responses requested */
247 iowrite32(0x00000000, base + 0x18); /* RESREQSET0 */ 281 iowrite32(0x00000000, base + RESREQSET0);
248 /* request response to packets of type 0x28 */ 282 /* request response to packets of type 0x28 */
249 iowrite32(0x00000100, base + 0x1c); /* RESREQSET1 */ 283 iowrite32(0x00000100, base + RESREQSET1);
250 /* High-speed transmission timeout, default 0xffffffff */ 284 /* High-speed transmission timeout, default 0xffffffff */
251 iowrite32(0x0fffffff, base + 0x20); /* HSTTOVSET */ 285 iowrite32(0x0fffffff, base + HSTTOVSET);
252 /* LP reception timeout, default 0xffffffff */ 286 /* LP reception timeout, default 0xffffffff */
253 iowrite32(0x0fffffff, base + 0x24); /* LPRTOVSET */ 287 iowrite32(0x0fffffff, base + LPRTOVSET);
254 /* Turn-around timeout, default 0xffffffff */ 288 /* Turn-around timeout, default 0xffffffff */
255 iowrite32(0x0fffffff, base + 0x28); /* TATOVSET */ 289 iowrite32(0x0fffffff, base + TATOVSET);
256 /* Peripheral reset timeout, default 0xffffffff */ 290 /* Peripheral reset timeout, default 0xffffffff */
257 iowrite32(0x0fffffff, base + 0x2c); /* PRTOVSET */ 291 iowrite32(0x0fffffff, base + PRTOVSET);
258 /* Enable timeout counters */ 292 /* Enable timeout counters */
259 iowrite32(0x00000f00, base + 0x30); /* DSICTRL */ 293 iowrite32(0x00000f00, base + DSICTRL);
260 /* Interrupts not used, disable all */ 294 /* Interrupts not used, disable all */
261 iowrite32(0, base + DSIINTE); 295 iowrite32(0, base + DSIINTE);
262 /* DSI-Tx bias on */ 296 /* DSI-Tx bias on */
263 iowrite32(0x00000001, base + 0x70); /* PHYCTRL */ 297 iowrite32(0x00000001, base + PHYCTRL);
264 udelay(200); 298 udelay(200);
265 /* Deassert resets, power on, set multiplier */ 299 /* Deassert resets, power on, set multiplier */
266 iowrite32(0x03070b01, base + 0x70); /* PHYCTRL */ 300 iowrite32(0x03070b01, base + PHYCTRL);
267 301
268 /* setup l-bridge */ 302 /* setup l-bridge */
269 303
@@ -271,20 +305,28 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
271 * Enable transmission of all packets, 305 * Enable transmission of all packets,
272 * transmit LPS after each HS packet completion 306 * transmit LPS after each HS packet completion
273 */ 307 */
274 iowrite32(0x00000006, base + 0x8000); /* DTCTR */ 308 iowrite32(0x00000006, mipi->linkbase + DTCTR);
275 /* VSYNC width = 2 (<< 17) */ 309 /* VSYNC width = 2 (<< 17) */
276 iowrite32(0x00040000 | (pctype << 12) | datatype, base + 0x8020); /* VMCTR1 */ 310 iowrite32((ch->lcd_cfg[0].vsync_len << pdata->vsynw_offset) |
311 (pdata->clksrc << 16) | (pctype << 12) | datatype,
312 mipi->linkbase + VMCTR1);
313
277 /* 314 /*
278 * Non-burst mode with sync pulses: VSE and HSE are output, 315 * Non-burst mode with sync pulses: VSE and HSE are output,
279 * HSA period allowed, no commands in LP 316 * HSA period allowed, no commands in LP
280 */ 317 */
281 iowrite32(0x00e00000, base + 0x8024); /* VMCTR2 */ 318 if (pdata->flags & SH_MIPI_DSI_HSABM)
319 vmctr2 |= 0x20;
320 if (pdata->flags & SH_MIPI_DSI_HSPBM)
321 vmctr2 |= 0x10;
322 iowrite32(vmctr2, mipi->linkbase + VMCTR2);
323
282 /* 324 /*
283 * 0x660 = 1632 bytes per line (RGB24, 544 pixels: see 325 * 0x660 = 1632 bytes per line (RGB24, 544 pixels: see
284 * sh_mobile_lcdc_info.ch[0].lcd_cfg.xres), HSALEN = 1 - default 326 * sh_mobile_lcdc_info.ch[0].lcd_cfg[0].xres), HSALEN = 1 - default
285 * (unused, since VMCTR2[HSABM] = 0) 327 * (unused if VMCTR2[HSABM] = 0)
286 */ 328 */
287 iowrite32(1 | (linelength << 16), base + 0x8028); /* VMLEN1 */ 329 iowrite32(1 | (linelength << 16), mipi->linkbase + VMLEN1);
288 330
289 msleep(5); 331 msleep(5);
290 332
@@ -317,11 +359,12 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
317 struct sh_mipi *mipi; 359 struct sh_mipi *mipi;
318 struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data; 360 struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data;
319 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 361 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
362 struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
320 unsigned long rate, f_current; 363 unsigned long rate, f_current;
321 int idx = pdev->id, ret; 364 int idx = pdev->id, ret;
322 char dsip_clk[] = "dsi.p_clk"; 365 char dsip_clk[] = "dsi.p_clk";
323 366
324 if (!res || idx >= ARRAY_SIZE(mipi_dsi) || !pdata) 367 if (!res || !res2 || idx >= ARRAY_SIZE(mipi_dsi) || !pdata)
325 return -ENODEV; 368 return -ENODEV;
326 369
327 mutex_lock(&array_lock); 370 mutex_lock(&array_lock);
@@ -352,6 +395,20 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
352 goto emap; 395 goto emap;
353 } 396 }
354 397
398 if (!request_mem_region(res2->start, resource_size(res2), pdev->name)) {
399 dev_err(&pdev->dev, "MIPI register region 2 already claimed\n");
400 ret = -EBUSY;
401 goto ereqreg2;
402 }
403
404 mipi->linkbase = ioremap(res2->start, resource_size(res2));
405 if (!mipi->linkbase) {
406 ret = -ENOMEM;
407 goto emap2;
408 }
409
410 mipi->dev = &pdev->dev;
411
355 mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk"); 412 mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk");
356 if (IS_ERR(mipi->dsit_clk)) { 413 if (IS_ERR(mipi->dsit_clk)) {
357 ret = PTR_ERR(mipi->dsit_clk); 414 ret = PTR_ERR(mipi->dsit_clk);
@@ -401,6 +458,9 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
401 458
402 mipi_dsi[idx] = mipi; 459 mipi_dsi[idx] = mipi;
403 460
461 pm_runtime_enable(&pdev->dev);
462 pm_runtime_resume(&pdev->dev);
463
404 ret = sh_mipi_setup(mipi, pdata); 464 ret = sh_mipi_setup(mipi, pdata);
405 if (ret < 0) 465 if (ret < 0)
406 goto emipisetup; 466 goto emipisetup;
@@ -408,15 +468,22 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
408 mutex_unlock(&array_lock); 468 mutex_unlock(&array_lock);
409 platform_set_drvdata(pdev, mipi); 469 platform_set_drvdata(pdev, mipi);
410 470
471 /* Save original LCDC callbacks */
472 mipi->next_board_data = pdata->lcd_chan->board_cfg.board_data;
473 mipi->next_display_on = pdata->lcd_chan->board_cfg.display_on;
474 mipi->next_display_off = pdata->lcd_chan->board_cfg.display_off;
475
411 /* Set up LCDC callbacks */ 476 /* Set up LCDC callbacks */
412 pdata->lcd_chan->board_cfg.board_data = mipi; 477 pdata->lcd_chan->board_cfg.board_data = mipi;
413 pdata->lcd_chan->board_cfg.display_on = mipi_display_on; 478 pdata->lcd_chan->board_cfg.display_on = mipi_display_on;
414 pdata->lcd_chan->board_cfg.display_off = mipi_display_off; 479 pdata->lcd_chan->board_cfg.display_off = mipi_display_off;
480 pdata->lcd_chan->board_cfg.owner = THIS_MODULE;
415 481
416 return 0; 482 return 0;
417 483
418emipisetup: 484emipisetup:
419 mipi_dsi[idx] = NULL; 485 mipi_dsi[idx] = NULL;
486 pm_runtime_disable(&pdev->dev);
420 clk_disable(mipi->dsip_clk); 487 clk_disable(mipi->dsip_clk);
421eclkpon: 488eclkpon:
422 clk_disable(mipi->dsit_clk); 489 clk_disable(mipi->dsit_clk);
@@ -427,6 +494,10 @@ eclkpget:
427esettrate: 494esettrate:
428 clk_put(mipi->dsit_clk); 495 clk_put(mipi->dsit_clk);
429eclktget: 496eclktget:
497 iounmap(mipi->linkbase);
498emap2:
499 release_mem_region(res2->start, resource_size(res2));
500ereqreg2:
430 iounmap(mipi->base); 501 iounmap(mipi->base);
431emap: 502emap:
432 release_mem_region(res->start, resource_size(res)); 503 release_mem_region(res->start, resource_size(res));
@@ -443,6 +514,7 @@ static int __exit sh_mipi_remove(struct platform_device *pdev)
443{ 514{
444 struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data; 515 struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data;
445 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 516 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
517 struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
446 struct sh_mipi *mipi = platform_get_drvdata(pdev); 518 struct sh_mipi *mipi = platform_get_drvdata(pdev);
447 int i, ret; 519 int i, ret;
448 520
@@ -463,14 +535,19 @@ static int __exit sh_mipi_remove(struct platform_device *pdev)
463 if (ret < 0) 535 if (ret < 0)
464 return ret; 536 return ret;
465 537
538 pdata->lcd_chan->board_cfg.owner = NULL;
466 pdata->lcd_chan->board_cfg.display_on = NULL; 539 pdata->lcd_chan->board_cfg.display_on = NULL;
467 pdata->lcd_chan->board_cfg.display_off = NULL; 540 pdata->lcd_chan->board_cfg.display_off = NULL;
468 pdata->lcd_chan->board_cfg.board_data = NULL; 541 pdata->lcd_chan->board_cfg.board_data = NULL;
469 542
543 pm_runtime_disable(&pdev->dev);
470 clk_disable(mipi->dsip_clk); 544 clk_disable(mipi->dsip_clk);
471 clk_disable(mipi->dsit_clk); 545 clk_disable(mipi->dsit_clk);
472 clk_put(mipi->dsit_clk); 546 clk_put(mipi->dsit_clk);
473 clk_put(mipi->dsip_clk); 547 clk_put(mipi->dsip_clk);
548 iounmap(mipi->linkbase);
549 if (res2)
550 release_mem_region(res2->start, resource_size(res2));
474 iounmap(mipi->base); 551 iounmap(mipi->base);
475 if (res) 552 if (res)
476 release_mem_region(res->start, resource_size(res)); 553 release_mem_region(res->start, resource_size(res));
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
index 2fde08cc66bf..7d54e2c612f7 100644
--- a/drivers/video/sh_mobile_hdmi.c
+++ b/drivers/video/sh_mobile_hdmi.c
@@ -22,10 +22,15 @@
22#include <linux/slab.h> 22#include <linux/slab.h>
23#include <linux/types.h> 23#include <linux/types.h>
24#include <linux/workqueue.h> 24#include <linux/workqueue.h>
25#include <sound/soc.h>
26#include <sound/soc-dapm.h>
27#include <sound/initval.h>
25 28
26#include <video/sh_mobile_hdmi.h> 29#include <video/sh_mobile_hdmi.h>
27#include <video/sh_mobile_lcdc.h> 30#include <video/sh_mobile_lcdc.h>
28 31
32#include "sh_mobile_lcdcfb.h"
33
29#define HDMI_SYSTEM_CTRL 0x00 /* System control */ 34#define HDMI_SYSTEM_CTRL 0x00 /* System control */
30#define HDMI_L_R_DATA_SWAP_CTRL_RPKT 0x01 /* L/R data swap control, 35#define HDMI_L_R_DATA_SWAP_CTRL_RPKT 0x01 /* L/R data swap control,
31 bits 19..16 of 20-bit N for Audio Clock Regeneration packet */ 36 bits 19..16 of 20-bit N for Audio Clock Regeneration packet */
@@ -204,12 +209,20 @@ enum hotplug_state {
204 209
205struct sh_hdmi { 210struct sh_hdmi {
206 void __iomem *base; 211 void __iomem *base;
207 enum hotplug_state hp_state; 212 enum hotplug_state hp_state; /* hot-plug status */
213 u8 preprogrammed_vic; /* use a pre-programmed VIC or
214 the external mode */
215 u8 edid_block_addr;
216 u8 edid_segment_nr;
217 u8 edid_blocks;
208 struct clk *hdmi_clk; 218 struct clk *hdmi_clk;
209 struct device *dev; 219 struct device *dev;
210 struct fb_info *info; 220 struct fb_info *info;
221 struct mutex mutex; /* Protect the info pointer */
211 struct delayed_work edid_work; 222 struct delayed_work edid_work;
212 struct fb_var_screeninfo var; 223 struct fb_var_screeninfo var;
224 struct fb_monspecs monspec;
225 struct notifier_block notifier;
213}; 226};
214 227
215static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg) 228static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg)
@@ -222,8 +235,60 @@ static u8 hdmi_read(struct sh_hdmi *hdmi, u8 reg)
222 return ioread8(hdmi->base + reg); 235 return ioread8(hdmi->base + reg);
223} 236}
224 237
238/*
239 * HDMI sound
240 */
241static unsigned int sh_hdmi_snd_read(struct snd_soc_codec *codec,
242 unsigned int reg)
243{
244 struct sh_hdmi *hdmi = snd_soc_codec_get_drvdata(codec);
245
246 return hdmi_read(hdmi, reg);
247}
248
249static int sh_hdmi_snd_write(struct snd_soc_codec *codec,
250 unsigned int reg,
251 unsigned int value)
252{
253 struct sh_hdmi *hdmi = snd_soc_codec_get_drvdata(codec);
254
255 hdmi_write(hdmi, value, reg);
256 return 0;
257}
258
259static struct snd_soc_dai_driver sh_hdmi_dai = {
260 .name = "sh_mobile_hdmi-hifi",
261 .playback = {
262 .stream_name = "Playback",
263 .channels_min = 2,
264 .channels_max = 8,
265 .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
266 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
267 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
268 SNDRV_PCM_RATE_192000,
269 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
270 },
271};
272
273static int sh_hdmi_snd_probe(struct snd_soc_codec *codec)
274{
275 dev_info(codec->dev, "SH Mobile HDMI Audio Codec");
276
277 return 0;
278}
279
280static struct snd_soc_codec_driver soc_codec_dev_sh_hdmi = {
281 .probe = sh_hdmi_snd_probe,
282 .read = sh_hdmi_snd_read,
283 .write = sh_hdmi_snd_write,
284};
285
286/*
287 * HDMI video
288 */
289
225/* External video parameter settings */ 290/* External video parameter settings */
226static void hdmi_external_video_param(struct sh_hdmi *hdmi) 291static void sh_hdmi_external_video_param(struct sh_hdmi *hdmi)
227{ 292{
228 struct fb_var_screeninfo *var = &hdmi->var; 293 struct fb_var_screeninfo *var = &hdmi->var;
229 u16 htotal, hblank, hdelay, vtotal, vblank, vdelay, voffset; 294 u16 htotal, hblank, hdelay, vtotal, vblank, vdelay, voffset;
@@ -255,9 +320,9 @@ static void hdmi_external_video_param(struct sh_hdmi *hdmi)
255 if (var->sync & FB_SYNC_VERT_HIGH_ACT) 320 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
256 sync |= 8; 321 sync |= 8;
257 322
258 pr_debug("H: %u, %u, %u, %u; V: %u, %u, %u, %u; sync 0x%x\n", 323 dev_dbg(hdmi->dev, "H: %u, %u, %u, %u; V: %u, %u, %u, %u; sync 0x%x\n",
259 htotal, hblank, hdelay, var->hsync_len, 324 htotal, hblank, hdelay, var->hsync_len,
260 vtotal, vblank, vdelay, var->vsync_len, sync); 325 vtotal, vblank, vdelay, var->vsync_len, sync);
261 326
262 hdmi_write(hdmi, sync | (voffset << 4), HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS); 327 hdmi_write(hdmi, sync | (voffset << 4), HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS);
263 328
@@ -282,7 +347,10 @@ static void hdmi_external_video_param(struct sh_hdmi *hdmi)
282 347
283 hdmi_write(hdmi, var->vsync_len, HDMI_EXTERNAL_V_DURATION); 348 hdmi_write(hdmi, var->vsync_len, HDMI_EXTERNAL_V_DURATION);
284 349
285 /* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for manual mode */ 350 /* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for external mode */
351 if (!hdmi->preprogrammed_vic)
352 hdmi_write(hdmi, sync | 1 | (voffset << 4),
353 HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS);
286} 354}
287 355
288/** 356/**
@@ -318,6 +386,9 @@ static void sh_hdmi_video_config(struct sh_hdmi *hdmi)
318 */ 386 */
319static void sh_hdmi_audio_config(struct sh_hdmi *hdmi) 387static void sh_hdmi_audio_config(struct sh_hdmi *hdmi)
320{ 388{
389 u8 data;
390 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
391
321 /* 392 /*
322 * [7:4] L/R data swap control 393 * [7:4] L/R data swap control
323 * [3:0] appropriate N[19:16] 394 * [3:0] appropriate N[19:16]
@@ -335,7 +406,23 @@ static void sh_hdmi_audio_config(struct sh_hdmi *hdmi)
335 * [6:5] set required down sampling rate if required 406 * [6:5] set required down sampling rate if required
336 * [4:3] set required audio source 407 * [4:3] set required audio source
337 */ 408 */
338 hdmi_write(hdmi, 0x00, HDMI_AUDIO_SETTING_1); 409 switch (pdata->flags & HDMI_SND_SRC_MASK) {
410 default:
411 /* fall through */
412 case HDMI_SND_SRC_I2S:
413 data = 0x0 << 3;
414 break;
415 case HDMI_SND_SRC_SPDIF:
416 data = 0x1 << 3;
417 break;
418 case HDMI_SND_SRC_DSD:
419 data = 0x2 << 3;
420 break;
421 case HDMI_SND_SRC_HBR:
422 data = 0x3 << 3;
423 break;
424 }
425 hdmi_write(hdmi, data, HDMI_AUDIO_SETTING_1);
339 426
340 /* [3:0] set sending channel number for channel status */ 427 /* [3:0] set sending channel number for channel status */
341 hdmi_write(hdmi, 0x40, HDMI_AUDIO_SETTING_2); 428 hdmi_write(hdmi, 0x40, HDMI_AUDIO_SETTING_2);
@@ -381,21 +468,72 @@ static void sh_hdmi_audio_config(struct sh_hdmi *hdmi)
381} 468}
382 469
383/** 470/**
384 * sh_hdmi_phy_config() 471 * sh_hdmi_phy_config() - configure the HDMI PHY for the used video mode
385 */ 472 */
386static void sh_hdmi_phy_config(struct sh_hdmi *hdmi) 473static void sh_hdmi_phy_config(struct sh_hdmi *hdmi)
387{ 474{
388 /* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */ 475 if (hdmi->var.pixclock < 10000) {
389 hdmi_write(hdmi, 0x19, HDMI_SLIPHDMIT_PARAM_SETTINGS_1); 476 /* for 1080p8bit 148MHz */
390 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2); 477 hdmi_write(hdmi, 0x1d, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
391 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3); 478 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
392 /* PLLA_CONFIG[7:0]: VCO gain, VCO offset, LPF resistance[0] */ 479 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3);
393 hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5); 480 hdmi_write(hdmi, 0x4c, HDMI_SLIPHDMIT_PARAM_SETTINGS_5);
394 hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6); 481 hdmi_write(hdmi, 0x1e, HDMI_SLIPHDMIT_PARAM_SETTINGS_6);
395 hdmi_write(hdmi, 0x4A, HDMI_SLIPHDMIT_PARAM_SETTINGS_7); 482 hdmi_write(hdmi, 0x48, HDMI_SLIPHDMIT_PARAM_SETTINGS_7);
396 hdmi_write(hdmi, 0x0E, HDMI_SLIPHDMIT_PARAM_SETTINGS_8); 483 hdmi_write(hdmi, 0x0e, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
397 hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9); 484 hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
398 hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10); 485 hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
486 } else if (hdmi->var.pixclock < 30000) {
487 /* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */
488 /*
489 * [1:0] Speed_A
490 * [3:2] Speed_B
491 * [4] PLLA_Bypass
492 * [6] DRV_TEST_EN
493 * [7] DRV_TEST_IN
494 */
495 hdmi_write(hdmi, 0x0f, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
496 /* PLLB_CONFIG[17], PLLA_CONFIG[17] - not in PHY datasheet */
497 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
498 /*
499 * [2:0] BGR_I_OFFSET
500 * [6:4] BGR_V_OFFSET
501 */
502 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3);
503 /* PLLA_CONFIG[7:0]: VCO gain, VCO offset, LPF resistance[0] */
504 hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5);
505 /*
506 * PLLA_CONFIG[15:8]: regulator voltage[0], CP current,
507 * LPF capacitance, LPF resistance[1]
508 */
509 hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6);
510 /* PLLB_CONFIG[7:0]: LPF resistance[0], VCO offset, VCO gain */
511 hdmi_write(hdmi, 0x4A, HDMI_SLIPHDMIT_PARAM_SETTINGS_7);
512 /*
513 * PLLB_CONFIG[15:8]: regulator voltage[0], CP current,
514 * LPF capacitance, LPF resistance[1]
515 */
516 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
517 /* DRV_CONFIG, PE_CONFIG */
518 hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
519 /*
520 * [2:0] AMON_SEL (4 == LPF voltage)
521 * [4] PLLA_CONFIG[16]
522 * [5] PLLB_CONFIG[16]
523 */
524 hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
525 } else {
526 /* for 480p8bit 27MHz */
527 hdmi_write(hdmi, 0x19, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
528 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
529 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3);
530 hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5);
531 hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6);
532 hdmi_write(hdmi, 0x48, HDMI_SLIPHDMIT_PARAM_SETTINGS_7);
533 hdmi_write(hdmi, 0x0F, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
534 hdmi_write(hdmi, 0x20, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
535 hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
536 }
399} 537}
400 538
401/** 539/**
@@ -403,6 +541,8 @@ static void sh_hdmi_phy_config(struct sh_hdmi *hdmi)
403 */ 541 */
404static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi) 542static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi)
405{ 543{
544 u8 vic;
545
406 /* AVI InfoFrame */ 546 /* AVI InfoFrame */
407 hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_INDEX); 547 hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_INDEX);
408 548
@@ -427,9 +567,9 @@ static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi)
427 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1); 567 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1);
428 568
429 /* 569 /*
430 * C = No Data 570 * [7:6] C = Colorimetry: no data
431 * M = 16:9 Picture Aspect Ratio 571 * [5:4] M = 2: 16:9, 1: 4:3 Picture Aspect Ratio
432 * R = Same as picture aspect ratio 572 * [3:0] R = 8: Active Frame Aspect Ratio: same as picture aspect ratio
433 */ 573 */
434 hdmi_write(hdmi, 0x28, HDMI_CTRL_PKT_BUF_ACCESS_PB2); 574 hdmi_write(hdmi, 0x28, HDMI_CTRL_PKT_BUF_ACCESS_PB2);
435 575
@@ -442,10 +582,14 @@ static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi)
442 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB3); 582 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB3);
443 583
444 /* 584 /*
445 * VIC = 1280 x 720p: ignored if external config is used 585 * VIC should be ignored if external config is used, so, we could just use 0,
446 * Send 2 for 720 x 480p, 16 for 1080p 586 * but play safe and use a valid value in any case just in case
447 */ 587 */
448 hdmi_write(hdmi, 4, HDMI_CTRL_PKT_BUF_ACCESS_PB4); 588 if (hdmi->preprogrammed_vic)
589 vic = hdmi->preprogrammed_vic;
590 else
591 vic = 4;
592 hdmi_write(hdmi, vic, HDMI_CTRL_PKT_BUF_ACCESS_PB4);
449 593
450 /* PR = No Repetition */ 594 /* PR = No Repetition */
451 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5); 595 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5);
@@ -519,100 +663,6 @@ static void sh_hdmi_audio_infoframe_setup(struct sh_hdmi *hdmi)
519} 663}
520 664
521/** 665/**
522 * sh_hdmi_gamut_metadata_setup() - Gamut Metadata Packet of CONTROL PACKET
523 */
524static void sh_hdmi_gamut_metadata_setup(struct sh_hdmi *hdmi)
525{
526 int i;
527
528 /* Gamut Metadata Packet */
529 hdmi_write(hdmi, 0x04, HDMI_CTRL_PKT_BUF_INDEX);
530
531 /* Packet Type = 0x0A */
532 hdmi_write(hdmi, 0x0A, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
533 /* Gamut Packet is not used, so default value */
534 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
535 /* Gamut Packet is not used, so default value */
536 hdmi_write(hdmi, 0x10, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
537
538 /* GBD bytes 0 through 27 */
539 for (i = 0; i <= 27; i++)
540 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0_63H - PB27_7EH */
541 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
542}
543
544/**
545 * sh_hdmi_acp_setup() - Audio Content Protection Packet (ACP)
546 */
547static void sh_hdmi_acp_setup(struct sh_hdmi *hdmi)
548{
549 int i;
550
551 /* Audio Content Protection Packet (ACP) */
552 hdmi_write(hdmi, 0x01, HDMI_CTRL_PKT_BUF_INDEX);
553
554 /* Packet Type = 0x04 */
555 hdmi_write(hdmi, 0x04, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
556 /* ACP_Type */
557 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
558 /* Reserved (0) */
559 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
560
561 /* GBD bytes 0 through 27 */
562 for (i = 0; i <= 27; i++)
563 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */
564 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
565}
566
567/**
568 * sh_hdmi_isrc1_setup() - ISRC1 Packet
569 */
570static void sh_hdmi_isrc1_setup(struct sh_hdmi *hdmi)
571{
572 int i;
573
574 /* ISRC1 Packet */
575 hdmi_write(hdmi, 0x02, HDMI_CTRL_PKT_BUF_INDEX);
576
577 /* Packet Type = 0x05 */
578 hdmi_write(hdmi, 0x05, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
579 /* ISRC_Cont, ISRC_Valid, Reserved (0), ISRC_Status */
580 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
581 /* Reserved (0) */
582 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
583
584 /* PB0 UPC_EAN_ISRC_0-15 */
585 /* Bytes PB16-PB27 shall be set to a value of 0. */
586 for (i = 0; i <= 27; i++)
587 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */
588 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
589}
590
591/**
592 * sh_hdmi_isrc2_setup() - ISRC2 Packet
593 */
594static void sh_hdmi_isrc2_setup(struct sh_hdmi *hdmi)
595{
596 int i;
597
598 /* ISRC2 Packet */
599 hdmi_write(hdmi, 0x03, HDMI_CTRL_PKT_BUF_INDEX);
600
601 /* HB0 Packet Type = 0x06 */
602 hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
603 /* Reserved (0) */
604 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
605 /* Reserved (0) */
606 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
607
608 /* PB0 UPC_EAN_ISRC_16-31 */
609 /* Bytes PB16-PB27 shall be set to a value of 0. */
610 for (i = 0; i <= 27; i++)
611 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */
612 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
613}
614
615/**
616 * sh_hdmi_configure() - Initialise HDMI for output 666 * sh_hdmi_configure() - Initialise HDMI for output
617 */ 667 */
618static void sh_hdmi_configure(struct sh_hdmi *hdmi) 668static void sh_hdmi_configure(struct sh_hdmi *hdmi)
@@ -632,18 +682,6 @@ static void sh_hdmi_configure(struct sh_hdmi *hdmi)
632 /* Audio InfoFrame */ 682 /* Audio InfoFrame */
633 sh_hdmi_audio_infoframe_setup(hdmi); 683 sh_hdmi_audio_infoframe_setup(hdmi);
634 684
635 /* Gamut Metadata packet */
636 sh_hdmi_gamut_metadata_setup(hdmi);
637
638 /* Audio Content Protection (ACP) Packet */
639 sh_hdmi_acp_setup(hdmi);
640
641 /* ISRC1 Packet */
642 sh_hdmi_isrc1_setup(hdmi);
643
644 /* ISRC2 Packet */
645 sh_hdmi_isrc2_setup(hdmi);
646
647 /* 685 /*
648 * Control packet auto send with VSYNC control: auto send 686 * Control packet auto send with VSYNC control: auto send
649 * General control, Gamut metadata, ISRC, and ACP packets 687 * General control, Gamut metadata, ISRC, and ACP packets
@@ -661,17 +699,53 @@ static void sh_hdmi_configure(struct sh_hdmi *hdmi)
661 hdmi_write(hdmi, 0x40, HDMI_SYSTEM_CTRL); 699 hdmi_write(hdmi, 0x40, HDMI_SYSTEM_CTRL);
662} 700}
663 701
664static void sh_hdmi_read_edid(struct sh_hdmi *hdmi) 702static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi,
703 const struct fb_videomode *mode,
704 unsigned long *hdmi_rate, unsigned long *parent_rate)
665{ 705{
666 struct fb_var_screeninfo *var = &hdmi->var; 706 unsigned long target = PICOS2KHZ(mode->pixclock) * 1000, rate_error;
667 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; 707 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
668 struct fb_videomode *lcd_cfg = &pdata->lcd_chan->lcd_cfg; 708
669 unsigned long height = var->height, width = var->width; 709 *hdmi_rate = clk_round_rate(hdmi->hdmi_clk, target);
670 int i; 710 if ((long)*hdmi_rate < 0)
711 *hdmi_rate = clk_get_rate(hdmi->hdmi_clk);
712
713 rate_error = (long)*hdmi_rate > 0 ? abs(*hdmi_rate - target) : ULONG_MAX;
714 if (rate_error && pdata->clk_optimize_parent)
715 rate_error = pdata->clk_optimize_parent(target, hdmi_rate, parent_rate);
716 else if (clk_get_parent(hdmi->hdmi_clk))
717 *parent_rate = clk_get_rate(clk_get_parent(hdmi->hdmi_clk));
718
719 dev_dbg(hdmi->dev, "%u-%u-%u-%u x %u-%u-%u-%u\n",
720 mode->left_margin, mode->xres,
721 mode->right_margin, mode->hsync_len,
722 mode->upper_margin, mode->yres,
723 mode->lower_margin, mode->vsync_len);
724
725 dev_dbg(hdmi->dev, "\t@%lu(+/-%lu)Hz, e=%lu / 1000, r=%uHz, p=%luHz\n", target,
726 rate_error, rate_error ? 10000 / (10 * target / rate_error) : 0,
727 mode->refresh, *parent_rate);
728
729 return rate_error;
730}
731
732static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
733 unsigned long *parent_rate)
734{
735 struct fb_var_screeninfo tmpvar;
736 struct fb_var_screeninfo *var = &tmpvar;
737 const struct fb_videomode *mode, *found = NULL;
738 struct fb_info *info = hdmi->info;
739 struct fb_modelist *modelist = NULL;
740 unsigned int f_width = 0, f_height = 0, f_refresh = 0;
741 unsigned long found_rate_error = ULONG_MAX; /* silly compiler... */
742 bool scanning = false, preferred_bad = false;
671 u8 edid[128]; 743 u8 edid[128];
744 char *forced;
745 int i;
672 746
673 /* Read EDID */ 747 /* Read EDID */
674 pr_debug("Read back EDID code:"); 748 dev_dbg(hdmi->dev, "Read back EDID code:");
675 for (i = 0; i < 128; i++) { 749 for (i = 0; i < 128; i++) {
676 edid[i] = hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW); 750 edid[i] = hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW);
677#ifdef DEBUG 751#ifdef DEBUG
@@ -686,29 +760,167 @@ static void sh_hdmi_read_edid(struct sh_hdmi *hdmi)
686#ifdef DEBUG 760#ifdef DEBUG
687 printk(KERN_CONT "\n"); 761 printk(KERN_CONT "\n");
688#endif 762#endif
689 fb_parse_edid(edid, var); 763
690 pr_debug("%u-%u-%u-%u x %u-%u-%u-%u @ %lu kHz monitor detected\n", 764 if (!hdmi->edid_blocks) {
691 var->left_margin, var->xres, var->right_margin, var->hsync_len, 765 fb_edid_to_monspecs(edid, &hdmi->monspec);
692 var->upper_margin, var->yres, var->lower_margin, var->vsync_len, 766 hdmi->edid_blocks = edid[126] + 1;
693 PICOS2KHZ(var->pixclock)); 767
694 768 dev_dbg(hdmi->dev, "%d main modes, %d extension blocks\n",
695 /* FIXME: Use user-provided configuration instead of EDID */ 769 hdmi->monspec.modedb_len, hdmi->edid_blocks - 1);
696 var->width = width; 770 } else {
697 var->xres = lcd_cfg->xres; 771 dev_dbg(hdmi->dev, "Extension %u detected, DTD start %u\n",
698 var->xres_virtual = lcd_cfg->xres; 772 edid[0], edid[2]);
699 var->left_margin = lcd_cfg->left_margin; 773 fb_edid_add_monspecs(edid, &hdmi->monspec);
700 var->right_margin = lcd_cfg->right_margin; 774 }
701 var->hsync_len = lcd_cfg->hsync_len; 775
702 var->height = height; 776 if (hdmi->edid_blocks > hdmi->edid_segment_nr * 2 +
703 var->yres = lcd_cfg->yres; 777 (hdmi->edid_block_addr >> 7) + 1) {
704 var->yres_virtual = lcd_cfg->yres * 2; 778 /* More blocks to read */
705 var->upper_margin = lcd_cfg->upper_margin; 779 if (hdmi->edid_block_addr) {
706 var->lower_margin = lcd_cfg->lower_margin; 780 hdmi->edid_block_addr = 0;
707 var->vsync_len = lcd_cfg->vsync_len; 781 hdmi->edid_segment_nr++;
708 var->sync = lcd_cfg->sync; 782 } else {
709 var->pixclock = lcd_cfg->pixclock; 783 hdmi->edid_block_addr = 0x80;
710 784 }
711 hdmi_external_video_param(hdmi); 785 /* Set EDID word address */
786 hdmi_write(hdmi, hdmi->edid_block_addr, HDMI_EDID_WORD_ADDRESS);
787 /* Enable EDID interrupt */
788 hdmi_write(hdmi, 0xC6, HDMI_INTERRUPT_MASK_1);
789 /* Set EDID segment pointer - starts reading EDID */
790 hdmi_write(hdmi, hdmi->edid_segment_nr, HDMI_EDID_SEGMENT_POINTER);
791 return -EAGAIN;
792 }
793
794 /* All E-EDID blocks ready */
795 dev_dbg(hdmi->dev, "%d main and extended modes\n", hdmi->monspec.modedb_len);
796
797 fb_get_options("sh_mobile_lcdc", &forced);
798 if (forced && *forced) {
799 /* Only primitive parsing so far */
800 i = sscanf(forced, "%ux%u@%u",
801 &f_width, &f_height, &f_refresh);
802 if (i < 2) {
803 f_width = 0;
804 f_height = 0;
805 } else {
806 /* The user wants us to use the EDID data */
807 scanning = true;
808 }
809 dev_dbg(hdmi->dev, "Forced mode %ux%u@%uHz\n",
810 f_width, f_height, f_refresh);
811 }
812
813 /* Walk monitor modes to find the best or the exact match */
814 for (i = 0, mode = hdmi->monspec.modedb;
815 i < hdmi->monspec.modedb_len && scanning;
816 i++, mode++) {
817 unsigned long rate_error;
818
819 if (!f_width && !f_height) {
820 /*
821 * A parameter string "video=sh_mobile_lcdc:0x0" means
822 * use the preferred EDID mode. If it is rejected by
823 * .fb_check_var(), keep looking, until an acceptable
824 * one is found.
825 */
826 if ((mode->flag & FB_MODE_IS_FIRST) || preferred_bad)
827 scanning = false;
828 else
829 continue;
830 } else if (f_width != mode->xres || f_height != mode->yres) {
831 /* No interest in unmatching modes */
832 continue;
833 }
834
835 rate_error = sh_hdmi_rate_error(hdmi, mode, hdmi_rate, parent_rate);
836
837 if (scanning) {
838 if (f_refresh == mode->refresh || (!f_refresh && !rate_error))
839 /*
840 * Exact match if either the refresh rate
841 * matches or it hasn't been specified and we've
842 * found a mode, for which we can configure the
843 * clock precisely
844 */
845 scanning = false;
846 else if (found && found_rate_error <= rate_error)
847 /*
848 * We otherwise search for the closest matching
849 * clock rate - either if no refresh rate has
850 * been specified or we cannot find an exactly
851 * matching one
852 */
853 continue;
854 }
855
856 /* Check if supported: sufficient fb memory, supported clock-rate */
857 fb_videomode_to_var(var, mode);
858
859 var->bits_per_pixel = info->var.bits_per_pixel;
860
861 if (info && info->fbops->fb_check_var &&
862 info->fbops->fb_check_var(var, info)) {
863 scanning = true;
864 preferred_bad = true;
865 continue;
866 }
867
868 found = mode;
869 found_rate_error = rate_error;
870 }
871
872 hdmi->var.width = hdmi->monspec.max_x * 10;
873 hdmi->var.height = hdmi->monspec.max_y * 10;
874
875 /*
876 * TODO 1: if no ->info is present, postpone running the config until
877 * after ->info first gets registered.
878 * TODO 2: consider registering the HDMI platform device from the LCDC
879 * driver, and passing ->info with HDMI platform data.
880 */
881 if (info && !found) {
882 modelist = info->modelist.next &&
883 !list_empty(&info->modelist) ?
884 list_entry(info->modelist.next,
885 struct fb_modelist, list) :
886 NULL;
887
888 if (modelist) {
889 found = &modelist->mode;
890 found_rate_error = sh_hdmi_rate_error(hdmi, found, hdmi_rate, parent_rate);
891 }
892 }
893
894 /* No cookie today */
895 if (!found)
896 return -ENXIO;
897
898 if (found->xres == 640 && found->yres == 480 && found->refresh == 60)
899 hdmi->preprogrammed_vic = 1;
900 else if (found->xres == 720 && found->yres == 480 && found->refresh == 60)
901 hdmi->preprogrammed_vic = 2;
902 else if (found->xres == 720 && found->yres == 576 && found->refresh == 50)
903 hdmi->preprogrammed_vic = 17;
904 else if (found->xres == 1280 && found->yres == 720 && found->refresh == 60)
905 hdmi->preprogrammed_vic = 4;
906 else if (found->xres == 1920 && found->yres == 1080 && found->refresh == 24)
907 hdmi->preprogrammed_vic = 32;
908 else if (found->xres == 1920 && found->yres == 1080 && found->refresh == 50)
909 hdmi->preprogrammed_vic = 31;
910 else if (found->xres == 1920 && found->yres == 1080 && found->refresh == 60)
911 hdmi->preprogrammed_vic = 16;
912 else
913 hdmi->preprogrammed_vic = 0;
914
915 dev_dbg(hdmi->dev, "Using %s %s mode %ux%u@%uHz (%luHz), clock error %luHz\n",
916 modelist ? "default" : "EDID", hdmi->preprogrammed_vic ? "VIC" : "external",
917 found->xres, found->yres, found->refresh,
918 PICOS2KHZ(found->pixclock) * 1000, found_rate_error);
919
920 fb_videomode_to_var(&hdmi->var, found);
921 sh_hdmi_external_video_param(hdmi);
922
923 return 0;
712} 924}
713 925
714static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id) 926static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
@@ -736,8 +948,8 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
736 hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_2); 948 hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_2);
737 949
738 if (printk_ratelimit()) 950 if (printk_ratelimit())
739 pr_debug("IRQ #%d: Status #1: 0x%x & 0x%x, #2: 0x%x & 0x%x\n", 951 dev_dbg(hdmi->dev, "IRQ #%d: Status #1: 0x%x & 0x%x, #2: 0x%x & 0x%x\n",
740 irq, status1, mask1, status2, mask2); 952 irq, status1, mask1, status2, mask2);
741 953
742 if (!((status1 & mask1) | (status2 & mask2))) { 954 if (!((status1 & mask1) | (status2 & mask2))) {
743 return IRQ_NONE; 955 return IRQ_NONE;
@@ -748,136 +960,283 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
748 udelay(500); 960 udelay(500);
749 961
750 msens = hdmi_read(hdmi, HDMI_HOT_PLUG_MSENS_STATUS); 962 msens = hdmi_read(hdmi, HDMI_HOT_PLUG_MSENS_STATUS);
751 pr_debug("MSENS 0x%x\n", msens); 963 dev_dbg(hdmi->dev, "MSENS 0x%x\n", msens);
752 /* Check, if hot plug & MSENS pin status are both high */ 964 /* Check, if hot plug & MSENS pin status are both high */
753 if ((msens & 0xC0) == 0xC0) { 965 if ((msens & 0xC0) == 0xC0) {
754 /* Display plug in */ 966 /* Display plug in */
967 hdmi->edid_segment_nr = 0;
968 hdmi->edid_block_addr = 0;
969 hdmi->edid_blocks = 0;
755 hdmi->hp_state = HDMI_HOTPLUG_CONNECTED; 970 hdmi->hp_state = HDMI_HOTPLUG_CONNECTED;
756 971
757 /* Set EDID word address */ 972 /* Set EDID word address */
758 hdmi_write(hdmi, 0x00, HDMI_EDID_WORD_ADDRESS); 973 hdmi_write(hdmi, 0x00, HDMI_EDID_WORD_ADDRESS);
759 /* Set EDID segment pointer */
760 hdmi_write(hdmi, 0x00, HDMI_EDID_SEGMENT_POINTER);
761 /* Enable EDID interrupt */ 974 /* Enable EDID interrupt */
762 hdmi_write(hdmi, 0xC6, HDMI_INTERRUPT_MASK_1); 975 hdmi_write(hdmi, 0xC6, HDMI_INTERRUPT_MASK_1);
976 /* Set EDID segment pointer - starts reading EDID */
977 hdmi_write(hdmi, 0x00, HDMI_EDID_SEGMENT_POINTER);
763 } else if (!(status1 & 0x80)) { 978 } else if (!(status1 & 0x80)) {
764 /* Display unplug, beware multiple interrupts */ 979 /* Display unplug, beware multiple interrupts */
765 if (hdmi->hp_state != HDMI_HOTPLUG_DISCONNECTED) 980 if (hdmi->hp_state != HDMI_HOTPLUG_DISCONNECTED) {
981 hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
766 schedule_delayed_work(&hdmi->edid_work, 0); 982 schedule_delayed_work(&hdmi->edid_work, 0);
767 983 }
768 hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
769 /* display_off will switch back to mode_a */ 984 /* display_off will switch back to mode_a */
770 } 985 }
771 } else if (status1 & 2) { 986 } else if (status1 & 2) {
772 /* EDID error interrupt: retry */ 987 /* EDID error interrupt: retry */
773 /* Set EDID word address */ 988 /* Set EDID word address */
774 hdmi_write(hdmi, 0x00, HDMI_EDID_WORD_ADDRESS); 989 hdmi_write(hdmi, hdmi->edid_block_addr, HDMI_EDID_WORD_ADDRESS);
775 /* Set EDID segment pointer */ 990 /* Set EDID segment pointer */
776 hdmi_write(hdmi, 0x00, HDMI_EDID_SEGMENT_POINTER); 991 hdmi_write(hdmi, hdmi->edid_segment_nr, HDMI_EDID_SEGMENT_POINTER);
777 } else if (status1 & 4) { 992 } else if (status1 & 4) {
778 /* Disable EDID interrupt */ 993 /* Disable EDID interrupt */
779 hdmi_write(hdmi, 0xC0, HDMI_INTERRUPT_MASK_1); 994 hdmi_write(hdmi, 0xC0, HDMI_INTERRUPT_MASK_1);
780 hdmi->hp_state = HDMI_HOTPLUG_EDID_DONE;
781 schedule_delayed_work(&hdmi->edid_work, msecs_to_jiffies(10)); 995 schedule_delayed_work(&hdmi->edid_work, msecs_to_jiffies(10));
782 } 996 }
783 997
784 return IRQ_HANDLED; 998 return IRQ_HANDLED;
785} 999}
786 1000
787static void hdmi_display_on(void *arg, struct fb_info *info) 1001/* locking: called with info->lock held, or before register_framebuffer() */
1002static void sh_hdmi_display_on(void *arg, struct fb_info *info)
788{ 1003{
1004 /*
1005 * info is guaranteed to be valid, when we are called, because our
1006 * FB_EVENT_FB_UNBIND notify is also called with info->lock held
1007 */
789 struct sh_hdmi *hdmi = arg; 1008 struct sh_hdmi *hdmi = arg;
790 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; 1009 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
1010 struct sh_mobile_lcdc_chan *ch = info->par;
791 1011
792 if (info->var.xres != 1280 || info->var.yres != 720) { 1012 dev_dbg(hdmi->dev, "%s(%p): state %x\n", __func__,
793 dev_warn(info->device, "Unsupported framebuffer geometry %ux%u\n", 1013 pdata->lcd_dev, info->state);
794 info->var.xres, info->var.yres); 1014
795 return; 1015 /* No need to lock */
796 } 1016 hdmi->info = info;
797 1017
798 pr_debug("%s(%p): state %x\n", __func__, pdata->lcd_dev, info->state);
799 /* 1018 /*
800 * FIXME: not a good place to store fb_info. And we cannot nullify it 1019 * hp_state can be set to
801 * even on monitor disconnect. What should the lifecycle be? 1020 * HDMI_HOTPLUG_DISCONNECTED: on monitor unplug
1021 * HDMI_HOTPLUG_CONNECTED: on monitor plug-in
1022 * HDMI_HOTPLUG_EDID_DONE: on EDID read completion
802 */ 1023 */
803 hdmi->info = info;
804 switch (hdmi->hp_state) { 1024 switch (hdmi->hp_state) {
805 case HDMI_HOTPLUG_EDID_DONE: 1025 case HDMI_HOTPLUG_EDID_DONE:
806 /* PS mode d->e. All functions are active */ 1026 /* PS mode d->e. All functions are active */
807 hdmi_write(hdmi, 0x80, HDMI_SYSTEM_CTRL); 1027 hdmi_write(hdmi, 0x80, HDMI_SYSTEM_CTRL);
808 pr_debug("HDMI running\n"); 1028 dev_dbg(hdmi->dev, "HDMI running\n");
809 break; 1029 break;
810 case HDMI_HOTPLUG_DISCONNECTED: 1030 case HDMI_HOTPLUG_DISCONNECTED:
811 info->state = FBINFO_STATE_SUSPENDED; 1031 info->state = FBINFO_STATE_SUSPENDED;
812 default: 1032 default:
813 hdmi->var = info->var; 1033 hdmi->var = ch->display_var;
814 } 1034 }
815} 1035}
816 1036
817static void hdmi_display_off(void *arg) 1037/* locking: called with info->lock held */
1038static void sh_hdmi_display_off(void *arg)
818{ 1039{
819 struct sh_hdmi *hdmi = arg; 1040 struct sh_hdmi *hdmi = arg;
820 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; 1041 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
821 1042
822 pr_debug("%s(%p)\n", __func__, pdata->lcd_dev); 1043 dev_dbg(hdmi->dev, "%s(%p)\n", __func__, pdata->lcd_dev);
823 /* PS mode e->a */ 1044 /* PS mode e->a */
824 hdmi_write(hdmi, 0x10, HDMI_SYSTEM_CTRL); 1045 hdmi_write(hdmi, 0x10, HDMI_SYSTEM_CTRL);
825} 1046}
826 1047
1048static bool sh_hdmi_must_reconfigure(struct sh_hdmi *hdmi)
1049{
1050 struct fb_info *info = hdmi->info;
1051 struct sh_mobile_lcdc_chan *ch = info->par;
1052 struct fb_var_screeninfo *new_var = &hdmi->var, *old_var = &ch->display_var;
1053 struct fb_videomode mode1, mode2;
1054
1055 fb_var_to_videomode(&mode1, old_var);
1056 fb_var_to_videomode(&mode2, new_var);
1057
1058 dev_dbg(info->dev, "Old %ux%u, new %ux%u\n",
1059 mode1.xres, mode1.yres, mode2.xres, mode2.yres);
1060
1061 if (fb_mode_is_equal(&mode1, &mode2)) {
1062 /* It can be a different monitor with an equal video-mode */
1063 old_var->width = new_var->width;
1064 old_var->height = new_var->height;
1065 return false;
1066 }
1067
1068 dev_dbg(info->dev, "Switching %u -> %u lines\n",
1069 mode1.yres, mode2.yres);
1070 *old_var = *new_var;
1071
1072 return true;
1073}
1074
1075/**
1076 * sh_hdmi_clk_configure() - set HDMI clock frequency and enable the clock
1077 * @hdmi: driver context
1078 * @hdmi_rate: HDMI clock frequency in Hz
1079 * @parent_rate: if != 0 - set parent clock rate for optimal precision
1080 * return: configured positive rate if successful
1081 * 0 if couldn't set the rate, but managed to enable the
1082 * clock, negative error, if couldn't enable the clock
1083 */
1084static long sh_hdmi_clk_configure(struct sh_hdmi *hdmi, unsigned long hdmi_rate,
1085 unsigned long parent_rate)
1086{
1087 int ret;
1088
1089 if (parent_rate && clk_get_parent(hdmi->hdmi_clk)) {
1090 ret = clk_set_rate(clk_get_parent(hdmi->hdmi_clk), parent_rate);
1091 if (ret < 0) {
1092 dev_warn(hdmi->dev, "Cannot set parent rate %ld: %d\n", parent_rate, ret);
1093 hdmi_rate = clk_round_rate(hdmi->hdmi_clk, hdmi_rate);
1094 } else {
1095 dev_dbg(hdmi->dev, "HDMI set parent frequency %lu\n", parent_rate);
1096 }
1097 }
1098
1099 ret = clk_set_rate(hdmi->hdmi_clk, hdmi_rate);
1100 if (ret < 0) {
1101 dev_warn(hdmi->dev, "Cannot set rate %ld: %d\n", hdmi_rate, ret);
1102 hdmi_rate = 0;
1103 } else {
1104 dev_dbg(hdmi->dev, "HDMI set frequency %lu\n", hdmi_rate);
1105 }
1106
1107 return hdmi_rate;
1108}
1109
827/* Hotplug interrupt occurred, read EDID */ 1110/* Hotplug interrupt occurred, read EDID */
828static void edid_work_fn(struct work_struct *work) 1111static void sh_hdmi_edid_work_fn(struct work_struct *work)
829{ 1112{
830 struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work); 1113 struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work);
831 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; 1114 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
1115 struct sh_mobile_lcdc_chan *ch;
1116 int ret;
832 1117
833 pr_debug("%s(%p): begin, hotplug status %d\n", __func__, 1118 dev_dbg(hdmi->dev, "%s(%p): begin, hotplug status %d\n", __func__,
834 pdata->lcd_dev, hdmi->hp_state); 1119 pdata->lcd_dev, hdmi->hp_state);
835 1120
836 if (!pdata->lcd_dev) 1121 if (!pdata->lcd_dev)
837 return; 1122 return;
838 1123
839 if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) { 1124 mutex_lock(&hdmi->mutex);
840 pm_runtime_get_sync(hdmi->dev); 1125
841 /* A device has been plugged in */ 1126 if (hdmi->hp_state == HDMI_HOTPLUG_CONNECTED) {
842 sh_hdmi_read_edid(hdmi); 1127 struct fb_info *info = hdmi->info;
1128 unsigned long parent_rate = 0, hdmi_rate;
1129
1130 ret = sh_hdmi_read_edid(hdmi, &hdmi_rate, &parent_rate);
1131 if (ret < 0)
1132 goto out;
1133
1134 hdmi->hp_state = HDMI_HOTPLUG_EDID_DONE;
1135
1136 /* Reconfigure the clock */
1137 ret = sh_hdmi_clk_configure(hdmi, hdmi_rate, parent_rate);
1138 if (ret < 0)
1139 goto out;
1140
843 msleep(10); 1141 msleep(10);
844 sh_hdmi_configure(hdmi); 1142 sh_hdmi_configure(hdmi);
845 /* Switched to another (d) power-save mode */ 1143 /* Switched to another (d) power-save mode */
846 msleep(10); 1144 msleep(10);
847 1145
848 if (!hdmi->info) 1146 if (!info)
849 return; 1147 goto out;
1148
1149 ch = info->par;
850 1150
851 acquire_console_sem(); 1151 console_lock();
852 1152
853 /* HDMI plug in */ 1153 /* HDMI plug in */
854 hdmi->info->var = hdmi->var; 1154 if (!sh_hdmi_must_reconfigure(hdmi) &&
855 if (hdmi->info->state != FBINFO_STATE_RUNNING) 1155 info->state == FBINFO_STATE_RUNNING) {
856 fb_set_suspend(hdmi->info, 0); 1156 /*
857 else 1157 * First activation with the default monitor - just turn
858 hdmi_display_on(hdmi, hdmi->info); 1158 * on, if we run a resume here, the logo disappears
1159 */
1160 if (lock_fb_info(info)) {
1161 info->var.width = hdmi->var.width;
1162 info->var.height = hdmi->var.height;
1163 sh_hdmi_display_on(hdmi, info);
1164 unlock_fb_info(info);
1165 }
1166 } else {
1167 /* New monitor or have to wake up */
1168 fb_set_suspend(info, 0);
1169 }
859 1170
860 release_console_sem(); 1171 console_unlock();
861 } else { 1172 } else {
1173 ret = 0;
862 if (!hdmi->info) 1174 if (!hdmi->info)
863 return; 1175 goto out;
1176
1177 hdmi->monspec.modedb_len = 0;
1178 fb_destroy_modedb(hdmi->monspec.modedb);
1179 hdmi->monspec.modedb = NULL;
864 1180
865 acquire_console_sem(); 1181 console_lock();
866 1182
867 /* HDMI disconnect */ 1183 /* HDMI disconnect */
868 fb_set_suspend(hdmi->info, 1); 1184 fb_set_suspend(hdmi->info, 1);
869 1185
870 release_console_sem(); 1186 console_unlock();
871 pm_runtime_put(hdmi->dev);
872 } 1187 }
873 1188
874 pr_debug("%s(%p): end\n", __func__, pdata->lcd_dev); 1189out:
1190 if (ret < 0 && ret != -EAGAIN)
1191 hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
1192 mutex_unlock(&hdmi->mutex);
1193
1194 dev_dbg(hdmi->dev, "%s(%p): end\n", __func__, pdata->lcd_dev);
1195}
1196
1197static int sh_hdmi_notify(struct notifier_block *nb,
1198 unsigned long action, void *data)
1199{
1200 struct fb_event *event = data;
1201 struct fb_info *info = event->info;
1202 struct sh_mobile_lcdc_chan *ch = info->par;
1203 struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg;
1204 struct sh_hdmi *hdmi = board_cfg->board_data;
1205
1206 if (!hdmi || nb != &hdmi->notifier || hdmi->info != info)
1207 return NOTIFY_DONE;
1208
1209 switch(action) {
1210 case FB_EVENT_FB_REGISTERED:
1211 /* Unneeded, activation taken care by sh_hdmi_display_on() */
1212 break;
1213 case FB_EVENT_FB_UNREGISTERED:
1214 /*
1215 * We are called from unregister_framebuffer() with the
1216 * info->lock held. This is bad for us, because we can race with
1217 * the scheduled work, which has to call fb_set_suspend(), which
1218 * takes info->lock internally, so, sh_hdmi_edid_work_fn()
1219 * cannot take and hold info->lock for the whole function
1220 * duration. Using an additional lock creates a classical AB-BA
1221 * lock up. Therefore, we have to release the info->lock
1222 * temporarily, synchronise with the work queue and re-acquire
1223 * the info->lock.
1224 */
1225 unlock_fb_info(info);
1226 mutex_lock(&hdmi->mutex);
1227 hdmi->info = NULL;
1228 mutex_unlock(&hdmi->mutex);
1229 lock_fb_info(info);
1230 return NOTIFY_OK;
1231 }
1232 return NOTIFY_DONE;
875} 1233}
876 1234
877static int __init sh_hdmi_probe(struct platform_device *pdev) 1235static int __init sh_hdmi_probe(struct platform_device *pdev)
878{ 1236{
879 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data; 1237 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data;
880 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1238 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1239 struct sh_mobile_lcdc_board_cfg *board_cfg;
881 int irq = platform_get_irq(pdev, 0), ret; 1240 int irq = platform_get_irq(pdev, 0), ret;
882 struct sh_hdmi *hdmi; 1241 struct sh_hdmi *hdmi;
883 long rate; 1242 long rate;
@@ -891,6 +1250,8 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
891 return -ENOMEM; 1250 return -ENOMEM;
892 } 1251 }
893 1252
1253 mutex_init(&hdmi->mutex);
1254
894 hdmi->dev = &pdev->dev; 1255 hdmi->dev = &pdev->dev;
895 1256
896 hdmi->hdmi_clk = clk_get(&pdev->dev, "ick"); 1257 hdmi->hdmi_clk = clk_get(&pdev->dev, "ick");
@@ -900,30 +1261,23 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
900 goto egetclk; 1261 goto egetclk;
901 } 1262 }
902 1263
903 rate = PICOS2KHZ(pdata->lcd_chan->lcd_cfg.pixclock) * 1000; 1264 /* An arbitrary relaxed pixclock just to get things started: from standard 480p */
1265 rate = clk_round_rate(hdmi->hdmi_clk, PICOS2KHZ(37037));
1266 if (rate > 0)
1267 rate = sh_hdmi_clk_configure(hdmi, rate, 0);
904 1268
905 rate = clk_round_rate(hdmi->hdmi_clk, rate);
906 if (rate < 0) { 1269 if (rate < 0) {
907 ret = rate; 1270 ret = rate;
908 dev_err(&pdev->dev, "Cannot get suitable rate: %ld\n", rate);
909 goto erate; 1271 goto erate;
910 } 1272 }
911 1273
912 ret = clk_set_rate(hdmi->hdmi_clk, rate);
913 if (ret < 0) {
914 dev_err(&pdev->dev, "Cannot set rate %ld: %d\n", rate, ret);
915 goto erate;
916 }
917
918 pr_debug("HDMI set frequency %lu\n", rate);
919
920 ret = clk_enable(hdmi->hdmi_clk); 1274 ret = clk_enable(hdmi->hdmi_clk);
921 if (ret < 0) { 1275 if (ret < 0) {
922 dev_err(&pdev->dev, "Cannot enable clock: %d\n", ret); 1276 dev_err(hdmi->dev, "Cannot enable clock: %d\n", ret);
923 goto eclkenable; 1277 goto erate;
924 } 1278 }
925 1279
926 dev_info(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate); 1280 dev_dbg(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate);
927 1281
928 if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) { 1282 if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) {
929 dev_err(&pdev->dev, "HDMI register region already claimed\n"); 1283 dev_err(&pdev->dev, "HDMI register region already claimed\n");
@@ -940,21 +1294,21 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
940 1294
941 platform_set_drvdata(pdev, hdmi); 1295 platform_set_drvdata(pdev, hdmi);
942 1296
943#if 1
944 /* Product and revision IDs are 0 in sh-mobile version */
945 dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n",
946 hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID));
947#endif
948
949 /* Set up LCDC callbacks */ 1297 /* Set up LCDC callbacks */
950 pdata->lcd_chan->board_cfg.board_data = hdmi; 1298 board_cfg = &pdata->lcd_chan->board_cfg;
951 pdata->lcd_chan->board_cfg.display_on = hdmi_display_on; 1299 board_cfg->owner = THIS_MODULE;
952 pdata->lcd_chan->board_cfg.display_off = hdmi_display_off; 1300 board_cfg->board_data = hdmi;
1301 board_cfg->display_on = sh_hdmi_display_on;
1302 board_cfg->display_off = sh_hdmi_display_off;
953 1303
954 INIT_DELAYED_WORK(&hdmi->edid_work, edid_work_fn); 1304 INIT_DELAYED_WORK(&hdmi->edid_work, sh_hdmi_edid_work_fn);
955 1305
956 pm_runtime_enable(&pdev->dev); 1306 pm_runtime_enable(&pdev->dev);
957 pm_runtime_resume(&pdev->dev); 1307 pm_runtime_get_sync(&pdev->dev);
1308
1309 /* Product and revision IDs are 0 in sh-mobile version */
1310 dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n",
1311 hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID));
958 1312
959 ret = request_irq(irq, sh_hdmi_hotplug, 0, 1313 ret = request_irq(irq, sh_hdmi_hotplug, 0,
960 dev_name(&pdev->dev), hdmi); 1314 dev_name(&pdev->dev), hdmi);
@@ -963,19 +1317,32 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
963 goto ereqirq; 1317 goto ereqirq;
964 } 1318 }
965 1319
1320 ret = snd_soc_register_codec(&pdev->dev,
1321 &soc_codec_dev_sh_hdmi, &sh_hdmi_dai, 1);
1322 if (ret < 0) {
1323 dev_err(&pdev->dev, "codec registration failed\n");
1324 goto ecodec;
1325 }
1326
1327 hdmi->notifier.notifier_call = sh_hdmi_notify;
1328 fb_register_client(&hdmi->notifier);
1329
966 return 0; 1330 return 0;
967 1331
1332ecodec:
1333 free_irq(irq, hdmi);
968ereqirq: 1334ereqirq:
1335 pm_runtime_put(&pdev->dev);
969 pm_runtime_disable(&pdev->dev); 1336 pm_runtime_disable(&pdev->dev);
970 iounmap(hdmi->base); 1337 iounmap(hdmi->base);
971emap: 1338emap:
972 release_mem_region(res->start, resource_size(res)); 1339 release_mem_region(res->start, resource_size(res));
973ereqreg: 1340ereqreg:
974 clk_disable(hdmi->hdmi_clk); 1341 clk_disable(hdmi->hdmi_clk);
975eclkenable:
976erate: 1342erate:
977 clk_put(hdmi->hdmi_clk); 1343 clk_put(hdmi->hdmi_clk);
978egetclk: 1344egetclk:
1345 mutex_destroy(&hdmi->mutex);
979 kfree(hdmi); 1346 kfree(hdmi);
980 1347
981 return ret; 1348 return ret;
@@ -986,19 +1353,29 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev)
986 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data; 1353 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data;
987 struct sh_hdmi *hdmi = platform_get_drvdata(pdev); 1354 struct sh_hdmi *hdmi = platform_get_drvdata(pdev);
988 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1355 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1356 struct sh_mobile_lcdc_board_cfg *board_cfg = &pdata->lcd_chan->board_cfg;
989 int irq = platform_get_irq(pdev, 0); 1357 int irq = platform_get_irq(pdev, 0);
990 1358
991 pdata->lcd_chan->board_cfg.display_on = NULL; 1359 snd_soc_unregister_codec(&pdev->dev);
992 pdata->lcd_chan->board_cfg.display_off = NULL; 1360
993 pdata->lcd_chan->board_cfg.board_data = NULL; 1361 fb_unregister_client(&hdmi->notifier);
994 1362
1363 board_cfg->display_on = NULL;
1364 board_cfg->display_off = NULL;
1365 board_cfg->board_data = NULL;
1366 board_cfg->owner = NULL;
1367
1368 /* No new work will be scheduled, wait for running ISR */
995 free_irq(irq, hdmi); 1369 free_irq(irq, hdmi);
996 pm_runtime_disable(&pdev->dev); 1370 /* Wait for already scheduled work */
997 cancel_delayed_work_sync(&hdmi->edid_work); 1371 cancel_delayed_work_sync(&hdmi->edid_work);
1372 pm_runtime_put(&pdev->dev);
1373 pm_runtime_disable(&pdev->dev);
998 clk_disable(hdmi->hdmi_clk); 1374 clk_disable(hdmi->hdmi_clk);
999 clk_put(hdmi->hdmi_clk); 1375 clk_put(hdmi->hdmi_clk);
1000 iounmap(hdmi->base); 1376 iounmap(hdmi->base);
1001 release_mem_region(res->start, resource_size(res)); 1377 release_mem_region(res->start, resource_size(res));
1378 mutex_destroy(&hdmi->mutex);
1002 kfree(hdmi); 1379 kfree(hdmi);
1003 1380
1004 return 0; 1381 return 0;
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index d72075a9f01c..019dbd3f12b2 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -12,7 +12,6 @@
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/delay.h> 13#include <linux/delay.h>
14#include <linux/mm.h> 14#include <linux/mm.h>
15#include <linux/fb.h>
16#include <linux/clk.h> 15#include <linux/clk.h>
17#include <linux/pm_runtime.h> 16#include <linux/pm_runtime.h>
18#include <linux/platform_device.h> 17#include <linux/platform_device.h>
@@ -21,10 +20,15 @@
21#include <linux/vmalloc.h> 20#include <linux/vmalloc.h>
22#include <linux/ioctl.h> 21#include <linux/ioctl.h>
23#include <linux/slab.h> 22#include <linux/slab.h>
23#include <linux/console.h>
24#include <linux/backlight.h>
25#include <linux/gpio.h>
24#include <video/sh_mobile_lcdc.h> 26#include <video/sh_mobile_lcdc.h>
25#include <asm/atomic.h> 27#include <asm/atomic.h>
26 28
27#define PALETTE_NR 16 29#include "sh_mobile_lcdcfb.h"
30#include "sh_mobile_meram.h"
31
28#define SIDE_B_OFFSET 0x1000 32#define SIDE_B_OFFSET 0x1000
29#define MIRROR_OFFSET 0x2000 33#define MIRROR_OFFSET 0x2000
30 34
@@ -53,11 +57,8 @@ static int lcdc_shared_regs[] = {
53}; 57};
54#define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs) 58#define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs)
55 59
56/* per-channel registers */ 60#define MAX_XRES 1920
57enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R, 61#define MAX_YRES 1080
58 LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR,
59 LDHAJR,
60 NR_CH_REGS };
61 62
62static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = { 63static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
63 [LDDCKPAT1R] = 0x400, 64 [LDDCKPAT1R] = 0x400,
@@ -69,6 +70,7 @@ static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
69 [LDSM1R] = 0x428, 70 [LDSM1R] = 0x428,
70 [LDSM2R] = 0x42c, 71 [LDSM2R] = 0x42c,
71 [LDSA1R] = 0x430, 72 [LDSA1R] = 0x430,
73 [LDSA2R] = 0x434,
72 [LDMLSR] = 0x438, 74 [LDMLSR] = 0x438,
73 [LDHCNR] = 0x448, 75 [LDHCNR] = 0x448,
74 [LDHSYNR] = 0x44c, 76 [LDHSYNR] = 0x44c,
@@ -112,23 +114,22 @@ static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = {
112#define LDRCNTR_MRC 0x00000001 114#define LDRCNTR_MRC 0x00000001
113#define LDSR_MRS 0x00000100 115#define LDSR_MRS 0x00000100
114 116
115struct sh_mobile_lcdc_priv; 117static const struct fb_videomode default_720p = {
116struct sh_mobile_lcdc_chan { 118 .name = "HDMI 720p",
117 struct sh_mobile_lcdc_priv *lcdc; 119 .xres = 1280,
118 unsigned long *reg_offs; 120 .yres = 720,
119 unsigned long ldmt1r_value; 121
120 unsigned long enabled; /* ME and SE in LDCNT2R */ 122 .left_margin = 220,
121 struct sh_mobile_lcdc_chan_cfg cfg; 123 .right_margin = 110,
122 u32 pseudo_palette[PALETTE_NR]; 124 .hsync_len = 40,
123 unsigned long saved_ch_regs[NR_CH_REGS]; 125
124 struct fb_info *info; 126 .upper_margin = 20,
125 dma_addr_t dma_handle; 127 .lower_margin = 5,
126 struct fb_deferred_io defio; 128 .vsync_len = 5,
127 struct scatterlist *sglist; 129
128 unsigned long frame_end; 130 .pixclock = 13468,
129 unsigned long pan_offset; 131 .refresh = 60,
130 wait_queue_head_t frame_end_wait; 132 .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
131 struct completion vsync_completion;
132}; 133};
133 134
134struct sh_mobile_lcdc_priv { 135struct sh_mobile_lcdc_priv {
@@ -142,6 +143,8 @@ struct sh_mobile_lcdc_priv {
142 struct notifier_block notifier; 143 struct notifier_block notifier;
143 unsigned long saved_shared_regs[NR_SHARED_REGS]; 144 unsigned long saved_shared_regs[NR_SHARED_REGS];
144 int started; 145 int started;
146 int forced_bpp; /* 2 channel LCDC must share bpp setting */
147 struct sh_mobile_meram_info *meram_dev;
145}; 148};
146 149
147static bool banked(int reg_nr) 150static bool banked(int reg_nr)
@@ -153,6 +156,7 @@ static bool banked(int reg_nr)
153 case LDDFR: 156 case LDDFR:
154 case LDSM1R: 157 case LDSM1R:
155 case LDSA1R: 158 case LDSA1R:
159 case LDSA2R:
156 case LDMLSR: 160 case LDMLSR:
157 case LDHCNR: 161 case LDHCNR:
158 case LDHSYNR: 162 case LDHSYNR:
@@ -409,8 +413,8 @@ static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
409 413
410static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch) 414static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
411{ 415{
412 struct fb_var_screeninfo *var = &ch->info->var; 416 struct fb_var_screeninfo *var = &ch->info->var, *display_var = &ch->display_var;
413 unsigned long h_total, hsync_pos; 417 unsigned long h_total, hsync_pos, display_h_total;
414 u32 tmp; 418 u32 tmp;
415 419
416 tmp = ch->ldmt1r_value; 420 tmp = ch->ldmt1r_value;
@@ -428,31 +432,33 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
428 lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r); 432 lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r);
429 433
430 /* horizontal configuration */ 434 /* horizontal configuration */
431 h_total = var->xres + var->hsync_len + 435 h_total = display_var->xres + display_var->hsync_len +
432 var->left_margin + var->right_margin; 436 display_var->left_margin + display_var->right_margin;
433 tmp = h_total / 8; /* HTCN */ 437 tmp = h_total / 8; /* HTCN */
434 tmp |= (var->xres / 8) << 16; /* HDCN */ 438 tmp |= (min(display_var->xres, var->xres) / 8) << 16; /* HDCN */
435 lcdc_write_chan(ch, LDHCNR, tmp); 439 lcdc_write_chan(ch, LDHCNR, tmp);
436 440
437 hsync_pos = var->xres + var->right_margin; 441 hsync_pos = display_var->xres + display_var->right_margin;
438 tmp = hsync_pos / 8; /* HSYNP */ 442 tmp = hsync_pos / 8; /* HSYNP */
439 tmp |= (var->hsync_len / 8) << 16; /* HSYNW */ 443 tmp |= (display_var->hsync_len / 8) << 16; /* HSYNW */
440 lcdc_write_chan(ch, LDHSYNR, tmp); 444 lcdc_write_chan(ch, LDHSYNR, tmp);
441 445
442 /* vertical configuration */ 446 /* vertical configuration */
443 tmp = var->yres + var->vsync_len + 447 tmp = display_var->yres + display_var->vsync_len +
444 var->upper_margin + var->lower_margin; /* VTLN */ 448 display_var->upper_margin + display_var->lower_margin; /* VTLN */
445 tmp |= var->yres << 16; /* VDLN */ 449 tmp |= min(display_var->yres, var->yres) << 16; /* VDLN */
446 lcdc_write_chan(ch, LDVLNR, tmp); 450 lcdc_write_chan(ch, LDVLNR, tmp);
447 451
448 tmp = var->yres + var->lower_margin; /* VSYNP */ 452 tmp = display_var->yres + display_var->lower_margin; /* VSYNP */
449 tmp |= var->vsync_len << 16; /* VSYNW */ 453 tmp |= display_var->vsync_len << 16; /* VSYNW */
450 lcdc_write_chan(ch, LDVSYNR, tmp); 454 lcdc_write_chan(ch, LDVSYNR, tmp);
451 455
452 /* Adjust horizontal synchronisation for HDMI */ 456 /* Adjust horizontal synchronisation for HDMI */
453 tmp = ((var->xres & 7) << 24) | 457 display_h_total = display_var->xres + display_var->hsync_len +
454 ((h_total & 7) << 16) | 458 display_var->left_margin + display_var->right_margin;
455 ((var->hsync_len & 7) << 8) | 459 tmp = ((display_var->xres & 7) << 24) |
460 ((display_h_total & 7) << 16) |
461 ((display_var->hsync_len & 7) << 8) |
456 hsync_pos; 462 hsync_pos;
457 lcdc_write_chan(ch, LDHAJR, tmp); 463 lcdc_write_chan(ch, LDHAJR, tmp);
458} 464}
@@ -460,16 +466,20 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
460static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) 466static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
461{ 467{
462 struct sh_mobile_lcdc_chan *ch; 468 struct sh_mobile_lcdc_chan *ch;
463 struct fb_videomode *lcd_cfg;
464 struct sh_mobile_lcdc_board_cfg *board_cfg; 469 struct sh_mobile_lcdc_board_cfg *board_cfg;
465 unsigned long tmp; 470 unsigned long tmp;
466 int k, m; 471 int bpp = 0;
467 int ret = 0; 472 unsigned long ldddsr;
473 int k, m, ret;
468 474
469 /* enable clocks before accessing the hardware */ 475 /* enable clocks before accessing the hardware */
470 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) 476 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
471 if (priv->ch[k].enabled) 477 if (priv->ch[k].enabled) {
472 sh_mobile_lcdc_clk_on(priv); 478 sh_mobile_lcdc_clk_on(priv);
479 if (!bpp)
480 bpp = priv->ch[k].info->var.bits_per_pixel;
481 }
482 }
473 483
474 /* reset */ 484 /* reset */
475 lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LCDC_RESET); 485 lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LCDC_RESET);
@@ -503,7 +513,8 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
503 m = 1 << 6; 513 m = 1 << 6;
504 tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0); 514 tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0);
505 515
506 lcdc_write_chan(ch, LDDCKPAT1R, 0x00000000); 516 /* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider denominator */
517 lcdc_write_chan(ch, LDDCKPAT1R, 0);
507 lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1); 518 lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1);
508 } 519 }
509 520
@@ -518,7 +529,6 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
518 529
519 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 530 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
520 ch = &priv->ch[k]; 531 ch = &priv->ch[k];
521 lcd_cfg = &ch->cfg.lcd_cfg;
522 532
523 if (!ch->enabled) 533 if (!ch->enabled)
524 continue; 534 continue;
@@ -529,17 +539,36 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
529 lcdc_write_chan(ch, LDPMR, 0); 539 lcdc_write_chan(ch, LDPMR, 0);
530 540
531 board_cfg = &ch->cfg.board_cfg; 541 board_cfg = &ch->cfg.board_cfg;
532 if (board_cfg->setup_sys) 542 if (board_cfg->setup_sys) {
533 ret = board_cfg->setup_sys(board_cfg->board_data, ch, 543 ret = board_cfg->setup_sys(board_cfg->board_data,
534 &sh_mobile_lcdc_sys_bus_ops); 544 ch, &sh_mobile_lcdc_sys_bus_ops);
535 if (ret) 545 if (ret)
536 return ret; 546 return ret;
547 }
537 } 548 }
538 549
539 /* word and long word swap */ 550 /* word and long word swap */
540 lcdc_write(priv, _LDDDSR, lcdc_read(priv, _LDDDSR) | 6); 551 ldddsr = lcdc_read(priv, _LDDDSR);
552 if (priv->ch[0].info->var.nonstd)
553 lcdc_write(priv, _LDDDSR, ldddsr | 7);
554 else {
555 switch (bpp) {
556 case 16:
557 lcdc_write(priv, _LDDDSR, ldddsr | 6);
558 break;
559 case 24:
560 lcdc_write(priv, _LDDDSR, ldddsr | 7);
561 break;
562 case 32:
563 lcdc_write(priv, _LDDDSR, ldddsr | 4);
564 break;
565 }
566 }
541 567
542 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 568 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
569 unsigned long base_addr_y;
570 unsigned long base_addr_c = 0;
571 int pitch;
543 ch = &priv->ch[k]; 572 ch = &priv->ch[k];
544 573
545 if (!priv->ch[k].enabled) 574 if (!priv->ch[k].enabled)
@@ -547,15 +576,95 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
547 576
548 /* set bpp format in PKF[4:0] */ 577 /* set bpp format in PKF[4:0] */
549 tmp = lcdc_read_chan(ch, LDDFR); 578 tmp = lcdc_read_chan(ch, LDDFR);
550 tmp &= ~(0x0001001f); 579 tmp &= ~0x0003031f;
551 tmp |= (ch->info->var.bits_per_pixel == 16) ? 3 : 0; 580 if (ch->info->var.nonstd) {
581 tmp |= (ch->info->var.nonstd << 16);
582 switch (ch->info->var.bits_per_pixel) {
583 case 12:
584 break;
585 case 16:
586 tmp |= (0x1 << 8);
587 break;
588 case 24:
589 tmp |= (0x2 << 8);
590 break;
591 }
592 } else {
593 switch (ch->info->var.bits_per_pixel) {
594 case 16:
595 tmp |= 0x03;
596 break;
597 case 24:
598 tmp |= 0x0b;
599 break;
600 case 32:
601 break;
602 }
603 }
552 lcdc_write_chan(ch, LDDFR, tmp); 604 lcdc_write_chan(ch, LDDFR, tmp);
553 605
606 base_addr_y = ch->info->fix.smem_start;
607 base_addr_c = base_addr_y +
608 ch->info->var.xres *
609 ch->info->var.yres_virtual;
610 pitch = ch->info->fix.line_length;
611
612 /* test if we can enable meram */
613 if (ch->cfg.meram_cfg && priv->meram_dev &&
614 priv->meram_dev->ops) {
615 struct sh_mobile_meram_cfg *cfg;
616 struct sh_mobile_meram_info *mdev;
617 unsigned long icb_addr_y, icb_addr_c;
618 int icb_pitch;
619 int pf;
620
621 cfg = ch->cfg.meram_cfg;
622 mdev = priv->meram_dev;
623 /* we need to de-init configured ICBs before we
624 * we can re-initialize them.
625 */
626 if (ch->meram_enabled)
627 mdev->ops->meram_unregister(mdev, cfg);
628
629 ch->meram_enabled = 0;
630
631 if (ch->info->var.nonstd) {
632 if (ch->info->var.bits_per_pixel == 24)
633 pf = SH_MOBILE_MERAM_PF_NV24;
634 else
635 pf = SH_MOBILE_MERAM_PF_NV;
636 } else {
637 pf = SH_MOBILE_MERAM_PF_RGB;
638 }
639
640 ret = mdev->ops->meram_register(mdev, cfg, pitch,
641 ch->info->var.yres,
642 pf,
643 base_addr_y,
644 base_addr_c,
645 &icb_addr_y,
646 &icb_addr_c,
647 &icb_pitch);
648 if (!ret) {
649 /* set LDSA1R value */
650 base_addr_y = icb_addr_y;
651 pitch = icb_pitch;
652
653 /* set LDSA2R value if required */
654 if (base_addr_c)
655 base_addr_c = icb_addr_c;
656
657 ch->meram_enabled = 1;
658 }
659 }
660
554 /* point out our frame buffer */ 661 /* point out our frame buffer */
555 lcdc_write_chan(ch, LDSA1R, ch->info->fix.smem_start); 662 lcdc_write_chan(ch, LDSA1R, base_addr_y);
663 if (ch->info->var.nonstd)
664 lcdc_write_chan(ch, LDSA2R, base_addr_c);
556 665
557 /* set line size */ 666 /* set line size */
558 lcdc_write_chan(ch, LDMLSR, ch->info->fix.line_length); 667 lcdc_write_chan(ch, LDMLSR, pitch);
559 668
560 /* setup deferred io if SYS bus */ 669 /* setup deferred io if SYS bus */
561 tmp = ch->cfg.sys_bus_cfg.deferred_io_msec; 670 tmp = ch->cfg.sys_bus_cfg.deferred_io_msec;
@@ -591,8 +700,15 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
591 continue; 700 continue;
592 701
593 board_cfg = &ch->cfg.board_cfg; 702 board_cfg = &ch->cfg.board_cfg;
594 if (board_cfg->display_on) 703 if (board_cfg->display_on && try_module_get(board_cfg->owner)) {
595 board_cfg->display_on(board_cfg->board_data, ch->info); 704 board_cfg->display_on(board_cfg->board_data, ch->info);
705 module_put(board_cfg->owner);
706 }
707
708 if (ch->bl) {
709 ch->bl->props.power = FB_BLANK_UNBLANK;
710 backlight_update_status(ch->bl);
711 }
596 } 712 }
597 713
598 return 0; 714 return 0;
@@ -614,7 +730,7 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
614 * flush frame, and wait for frame end interrupt 730 * flush frame, and wait for frame end interrupt
615 * clean up deferred io and enable clock 731 * clean up deferred io and enable clock
616 */ 732 */
617 if (ch->info->fbdefio) { 733 if (ch->info && ch->info->fbdefio) {
618 ch->frame_end = 0; 734 ch->frame_end = 0;
619 schedule_delayed_work(&ch->info->deferred_work, 0); 735 schedule_delayed_work(&ch->info->deferred_work, 0);
620 wait_event(ch->frame_end_wait, ch->frame_end); 736 wait_event(ch->frame_end_wait, ch->frame_end);
@@ -623,9 +739,27 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
623 sh_mobile_lcdc_clk_on(priv); 739 sh_mobile_lcdc_clk_on(priv);
624 } 740 }
625 741
742 if (ch->bl) {
743 ch->bl->props.power = FB_BLANK_POWERDOWN;
744 backlight_update_status(ch->bl);
745 }
746
626 board_cfg = &ch->cfg.board_cfg; 747 board_cfg = &ch->cfg.board_cfg;
627 if (board_cfg->display_off) 748 if (board_cfg->display_off && try_module_get(board_cfg->owner)) {
628 board_cfg->display_off(board_cfg->board_data); 749 board_cfg->display_off(board_cfg->board_data);
750 module_put(board_cfg->owner);
751 }
752
753 /* disable the meram */
754 if (ch->meram_enabled) {
755 struct sh_mobile_meram_cfg *cfg;
756 struct sh_mobile_meram_info *mdev;
757 cfg = ch->cfg.meram_cfg;
758 mdev = priv->meram_dev;
759 mdev->ops->meram_unregister(mdev, cfg);
760 ch->meram_enabled = 0;
761 }
762
629 } 763 }
630 764
631 /* stop the lcdc */ 765 /* stop the lcdc */
@@ -704,7 +838,6 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
704 return PTR_ERR(priv->dot_clk); 838 return PTR_ERR(priv->dot_clk);
705 } 839 }
706 } 840 }
707 atomic_set(&priv->hw_usecnt, -1);
708 841
709 /* Runtime PM support involves two step for this driver: 842 /* Runtime PM support involves two step for this driver:
710 * 1) Enable Runtime PM 843 * 1) Enable Runtime PM
@@ -778,9 +911,15 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
778 struct sh_mobile_lcdc_priv *priv = ch->lcdc; 911 struct sh_mobile_lcdc_priv *priv = ch->lcdc;
779 unsigned long ldrcntr; 912 unsigned long ldrcntr;
780 unsigned long new_pan_offset; 913 unsigned long new_pan_offset;
914 unsigned long base_addr_y, base_addr_c;
915 unsigned long c_offset;
781 916
782 new_pan_offset = (var->yoffset * info->fix.line_length) + 917 if (!var->nonstd)
783 (var->xoffset * (info->var.bits_per_pixel / 8)); 918 new_pan_offset = (var->yoffset * info->fix.line_length) +
919 (var->xoffset * (info->var.bits_per_pixel / 8));
920 else
921 new_pan_offset = (var->yoffset * info->fix.line_length) +
922 (var->xoffset);
784 923
785 if (new_pan_offset == ch->pan_offset) 924 if (new_pan_offset == ch->pan_offset)
786 return 0; /* No change, do nothing */ 925 return 0; /* No change, do nothing */
@@ -788,7 +927,46 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
788 ldrcntr = lcdc_read(priv, _LDRCNTR); 927 ldrcntr = lcdc_read(priv, _LDRCNTR);
789 928
790 /* Set the source address for the next refresh */ 929 /* Set the source address for the next refresh */
791 lcdc_write_chan_mirror(ch, LDSA1R, ch->dma_handle + new_pan_offset); 930 base_addr_y = ch->dma_handle + new_pan_offset;
931 if (var->nonstd) {
932 /* Set y offset */
933 c_offset = (var->yoffset *
934 info->fix.line_length *
935 (info->var.bits_per_pixel - 8)) / 8;
936 base_addr_c = ch->dma_handle + var->xres * var->yres_virtual +
937 c_offset;
938 /* Set x offset */
939 if (info->var.bits_per_pixel == 24)
940 base_addr_c += 2 * var->xoffset;
941 else
942 base_addr_c += var->xoffset;
943 } else
944 base_addr_c = 0;
945
946 if (!ch->meram_enabled) {
947 lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
948 if (base_addr_c)
949 lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
950 } else {
951 struct sh_mobile_meram_cfg *cfg;
952 struct sh_mobile_meram_info *mdev;
953 unsigned long icb_addr_y, icb_addr_c;
954 int ret;
955
956 cfg = ch->cfg.meram_cfg;
957 mdev = priv->meram_dev;
958 ret = mdev->ops->meram_update(mdev, cfg,
959 base_addr_y, base_addr_c,
960 &icb_addr_y, &icb_addr_c);
961 if (ret)
962 return ret;
963
964 lcdc_write_chan_mirror(ch, LDSA1R, icb_addr_y);
965 if (icb_addr_c)
966 lcdc_write_chan_mirror(ch, LDSA2R, icb_addr_c);
967
968 }
969
792 if (lcdc_chan_is_sublcd(ch)) 970 if (lcdc_chan_is_sublcd(ch))
793 lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS); 971 lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS);
794 else 972 else
@@ -837,6 +1015,153 @@ static int sh_mobile_ioctl(struct fb_info *info, unsigned int cmd,
837 return retval; 1015 return retval;
838} 1016}
839 1017
1018static void sh_mobile_fb_reconfig(struct fb_info *info)
1019{
1020 struct sh_mobile_lcdc_chan *ch = info->par;
1021 struct fb_videomode mode1, mode2;
1022 struct fb_event event;
1023 int evnt = FB_EVENT_MODE_CHANGE_ALL;
1024
1025 if (ch->use_count > 1 || (ch->use_count == 1 && !info->fbcon_par))
1026 /* More framebuffer users are active */
1027 return;
1028
1029 fb_var_to_videomode(&mode1, &ch->display_var);
1030 fb_var_to_videomode(&mode2, &info->var);
1031
1032 if (fb_mode_is_equal(&mode1, &mode2))
1033 return;
1034
1035 /* Display has been re-plugged, framebuffer is free now, reconfigure */
1036 if (fb_set_var(info, &ch->display_var) < 0)
1037 /* Couldn't reconfigure, hopefully, can continue as before */
1038 return;
1039
1040 if (info->var.nonstd)
1041 info->fix.line_length = mode1.xres;
1042 else
1043 info->fix.line_length = mode1.xres * (ch->cfg.bpp / 8);
1044
1045 /*
1046 * fb_set_var() calls the notifier change internally, only if
1047 * FBINFO_MISC_USEREVENT flag is set. Since we do not want to fake a
1048 * user event, we have to call the chain ourselves.
1049 */
1050 event.info = info;
1051 event.data = &mode1;
1052 fb_notifier_call_chain(evnt, &event);
1053}
1054
1055/*
1056 * Locking: both .fb_release() and .fb_open() are called with info->lock held if
1057 * user == 1, or with console sem held, if user == 0.
1058 */
1059static int sh_mobile_release(struct fb_info *info, int user)
1060{
1061 struct sh_mobile_lcdc_chan *ch = info->par;
1062
1063 mutex_lock(&ch->open_lock);
1064 dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count);
1065
1066 ch->use_count--;
1067
1068 /* Nothing to reconfigure, when called from fbcon */
1069 if (user) {
1070 console_lock();
1071 sh_mobile_fb_reconfig(info);
1072 console_unlock();
1073 }
1074
1075 mutex_unlock(&ch->open_lock);
1076
1077 return 0;
1078}
1079
1080static int sh_mobile_open(struct fb_info *info, int user)
1081{
1082 struct sh_mobile_lcdc_chan *ch = info->par;
1083
1084 mutex_lock(&ch->open_lock);
1085 ch->use_count++;
1086
1087 dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count);
1088 mutex_unlock(&ch->open_lock);
1089
1090 return 0;
1091}
1092
1093static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1094{
1095 struct sh_mobile_lcdc_chan *ch = info->par;
1096 struct sh_mobile_lcdc_priv *p = ch->lcdc;
1097
1098 if (var->xres > MAX_XRES || var->yres > MAX_YRES ||
1099 var->xres * var->yres * (ch->cfg.bpp / 8) * 2 > info->fix.smem_len) {
1100 dev_warn(info->dev, "Invalid info: %u-%u-%u-%u x %u-%u-%u-%u @ %lukHz!\n",
1101 var->left_margin, var->xres, var->right_margin, var->hsync_len,
1102 var->upper_margin, var->yres, var->lower_margin, var->vsync_len,
1103 PICOS2KHZ(var->pixclock));
1104 return -EINVAL;
1105 }
1106
1107 /* only accept the forced_bpp for dual channel configurations */
1108 if (p->forced_bpp && p->forced_bpp != var->bits_per_pixel)
1109 return -EINVAL;
1110
1111 switch (var->bits_per_pixel) {
1112 case 16: /* PKF[4:0] = 00011 - RGB 565 */
1113 case 24: /* PKF[4:0] = 01011 - RGB 888 */
1114 case 32: /* PKF[4:0] = 00000 - RGBA 888 */
1115 break;
1116 default:
1117 return -EINVAL;
1118 }
1119
1120 return 0;
1121}
1122
1123/*
1124 * Screen blanking. Behavior is as follows:
1125 * FB_BLANK_UNBLANK: screen unblanked, clocks enabled
1126 * FB_BLANK_NORMAL: screen blanked, clocks enabled
1127 * FB_BLANK_VSYNC,
1128 * FB_BLANK_HSYNC,
1129 * FB_BLANK_POWEROFF: screen blanked, clocks disabled
1130 */
1131static int sh_mobile_lcdc_blank(int blank, struct fb_info *info)
1132{
1133 struct sh_mobile_lcdc_chan *ch = info->par;
1134 struct sh_mobile_lcdc_priv *p = ch->lcdc;
1135
1136 /* blank the screen? */
1137 if (blank > FB_BLANK_UNBLANK && ch->blank_status == FB_BLANK_UNBLANK) {
1138 struct fb_fillrect rect = {
1139 .width = info->var.xres,
1140 .height = info->var.yres,
1141 };
1142 sh_mobile_lcdc_fillrect(info, &rect);
1143 }
1144 /* turn clocks on? */
1145 if (blank <= FB_BLANK_NORMAL && ch->blank_status > FB_BLANK_NORMAL) {
1146 sh_mobile_lcdc_clk_on(p);
1147 }
1148 /* turn clocks off? */
1149 if (blank > FB_BLANK_NORMAL && ch->blank_status <= FB_BLANK_NORMAL) {
1150 /* make sure the screen is updated with the black fill before
1151 * switching the clocks off. one vsync is not enough since
1152 * blanking may occur in the middle of a refresh. deferred io
1153 * mode will reenable the clocks and update the screen in time,
1154 * so it does not need this. */
1155 if (!info->fbdefio) {
1156 sh_mobile_wait_for_vsync(info);
1157 sh_mobile_wait_for_vsync(info);
1158 }
1159 sh_mobile_lcdc_clk_off(p);
1160 }
1161
1162 ch->blank_status = blank;
1163 return 0;
1164}
840 1165
841static struct fb_ops sh_mobile_lcdc_ops = { 1166static struct fb_ops sh_mobile_lcdc_ops = {
842 .owner = THIS_MODULE, 1167 .owner = THIS_MODULE,
@@ -846,12 +1171,89 @@ static struct fb_ops sh_mobile_lcdc_ops = {
846 .fb_fillrect = sh_mobile_lcdc_fillrect, 1171 .fb_fillrect = sh_mobile_lcdc_fillrect,
847 .fb_copyarea = sh_mobile_lcdc_copyarea, 1172 .fb_copyarea = sh_mobile_lcdc_copyarea,
848 .fb_imageblit = sh_mobile_lcdc_imageblit, 1173 .fb_imageblit = sh_mobile_lcdc_imageblit,
1174 .fb_blank = sh_mobile_lcdc_blank,
849 .fb_pan_display = sh_mobile_fb_pan_display, 1175 .fb_pan_display = sh_mobile_fb_pan_display,
850 .fb_ioctl = sh_mobile_ioctl, 1176 .fb_ioctl = sh_mobile_ioctl,
1177 .fb_open = sh_mobile_open,
1178 .fb_release = sh_mobile_release,
1179 .fb_check_var = sh_mobile_check_var,
851}; 1180};
852 1181
853static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp) 1182static int sh_mobile_lcdc_update_bl(struct backlight_device *bdev)
1183{
1184 struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev);
1185 struct sh_mobile_lcdc_board_cfg *cfg = &ch->cfg.board_cfg;
1186 int brightness = bdev->props.brightness;
1187
1188 if (bdev->props.power != FB_BLANK_UNBLANK ||
1189 bdev->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
1190 brightness = 0;
1191
1192 return cfg->set_brightness(cfg->board_data, brightness);
1193}
1194
1195static int sh_mobile_lcdc_get_brightness(struct backlight_device *bdev)
1196{
1197 struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev);
1198 struct sh_mobile_lcdc_board_cfg *cfg = &ch->cfg.board_cfg;
1199
1200 return cfg->get_brightness(cfg->board_data);
1201}
1202
1203static int sh_mobile_lcdc_check_fb(struct backlight_device *bdev,
1204 struct fb_info *info)
854{ 1205{
1206 return (info->bl_dev == bdev);
1207}
1208
1209static struct backlight_ops sh_mobile_lcdc_bl_ops = {
1210 .options = BL_CORE_SUSPENDRESUME,
1211 .update_status = sh_mobile_lcdc_update_bl,
1212 .get_brightness = sh_mobile_lcdc_get_brightness,
1213 .check_fb = sh_mobile_lcdc_check_fb,
1214};
1215
1216static struct backlight_device *sh_mobile_lcdc_bl_probe(struct device *parent,
1217 struct sh_mobile_lcdc_chan *ch)
1218{
1219 struct backlight_device *bl;
1220
1221 bl = backlight_device_register(ch->cfg.bl_info.name, parent, ch,
1222 &sh_mobile_lcdc_bl_ops, NULL);
1223 if (IS_ERR(bl)) {
1224 dev_err(parent, "unable to register backlight device: %ld\n",
1225 PTR_ERR(bl));
1226 return NULL;
1227 }
1228
1229 bl->props.max_brightness = ch->cfg.bl_info.max_brightness;
1230 bl->props.brightness = bl->props.max_brightness;
1231 backlight_update_status(bl);
1232
1233 return bl;
1234}
1235
1236static void sh_mobile_lcdc_bl_remove(struct backlight_device *bdev)
1237{
1238 backlight_device_unregister(bdev);
1239}
1240
1241static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp,
1242 int nonstd)
1243{
1244 if (nonstd) {
1245 switch (bpp) {
1246 case 12:
1247 case 16:
1248 case 24:
1249 var->bits_per_pixel = bpp;
1250 var->nonstd = nonstd;
1251 return 0;
1252 default:
1253 return -EINVAL;
1254 }
1255 }
1256
855 switch (bpp) { 1257 switch (bpp) {
856 case 16: /* PKF[4:0] = 00011 - RGB 565 */ 1258 case 16: /* PKF[4:0] = 00011 - RGB 565 */
857 var->red.offset = 11; 1259 var->red.offset = 11;
@@ -864,19 +1266,27 @@ static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp)
864 var->transp.length = 0; 1266 var->transp.length = 0;
865 break; 1267 break;
866 1268
867 case 32: /* PKF[4:0] = 00000 - RGB 888 1269 case 24: /* PKF[4:0] = 01011 - RGB 888 */
868 * sh7722 pdf says 00RRGGBB but reality is GGBB00RR 1270 var->red.offset = 16;
869 * this may be because LDDDSR has word swap enabled..
870 */
871 var->red.offset = 0;
872 var->red.length = 8; 1271 var->red.length = 8;
873 var->green.offset = 24; 1272 var->green.offset = 8;
874 var->green.length = 8; 1273 var->green.length = 8;
875 var->blue.offset = 16; 1274 var->blue.offset = 0;
876 var->blue.length = 8; 1275 var->blue.length = 8;
877 var->transp.offset = 0; 1276 var->transp.offset = 0;
878 var->transp.length = 0; 1277 var->transp.length = 0;
879 break; 1278 break;
1279
1280 case 32: /* PKF[4:0] = 00000 - RGBA 888 */
1281 var->red.offset = 16;
1282 var->red.length = 8;
1283 var->green.offset = 8;
1284 var->green.length = 8;
1285 var->blue.offset = 0;
1286 var->blue.length = 8;
1287 var->transp.offset = 24;
1288 var->transp.length = 8;
1289 break;
880 default: 1290 default:
881 return -EINVAL; 1291 return -EINVAL;
882 } 1292 }
@@ -958,6 +1368,7 @@ static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = {
958 .runtime_resume = sh_mobile_lcdc_runtime_resume, 1368 .runtime_resume = sh_mobile_lcdc_runtime_resume,
959}; 1369};
960 1370
1371/* locking: called with info->lock held */
961static int sh_mobile_lcdc_notify(struct notifier_block *nb, 1372static int sh_mobile_lcdc_notify(struct notifier_block *nb,
962 unsigned long action, void *data) 1373 unsigned long action, void *data)
963{ 1374{
@@ -965,53 +1376,36 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb,
965 struct fb_info *info = event->info; 1376 struct fb_info *info = event->info;
966 struct sh_mobile_lcdc_chan *ch = info->par; 1377 struct sh_mobile_lcdc_chan *ch = info->par;
967 struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg; 1378 struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg;
968 struct fb_var_screeninfo *var;
969 1379
970 if (&ch->lcdc->notifier != nb) 1380 if (&ch->lcdc->notifier != nb)
971 return 0; 1381 return NOTIFY_DONE;
972 1382
973 dev_dbg(info->dev, "%s(): action = %lu, data = %p\n", 1383 dev_dbg(info->dev, "%s(): action = %lu, data = %p\n",
974 __func__, action, event->data); 1384 __func__, action, event->data);
975 1385
976 switch(action) { 1386 switch(action) {
977 case FB_EVENT_SUSPEND: 1387 case FB_EVENT_SUSPEND:
978 if (board_cfg->display_off) 1388 if (board_cfg->display_off && try_module_get(board_cfg->owner)) {
979 board_cfg->display_off(board_cfg->board_data); 1389 board_cfg->display_off(board_cfg->board_data);
980 pm_runtime_put(info->device); 1390 module_put(board_cfg->owner);
1391 }
1392 sh_mobile_lcdc_stop(ch->lcdc);
981 break; 1393 break;
982 case FB_EVENT_RESUME: 1394 case FB_EVENT_RESUME:
983 var = &info->var; 1395 mutex_lock(&ch->open_lock);
1396 sh_mobile_fb_reconfig(info);
1397 mutex_unlock(&ch->open_lock);
984 1398
985 /* HDMI must be enabled before LCDC configuration */ 1399 /* HDMI must be enabled before LCDC configuration */
986 if (board_cfg->display_on) 1400 if (board_cfg->display_on && try_module_get(board_cfg->owner)) {
987 board_cfg->display_on(board_cfg->board_data, ch->info); 1401 board_cfg->display_on(board_cfg->board_data, info);
988 1402 module_put(board_cfg->owner);
989 /* Check if the new display is not in our modelist */
990 if (ch->info->modelist.next &&
991 !fb_match_mode(var, &ch->info->modelist)) {
992 struct fb_videomode mode;
993 int ret;
994
995 /* Can we handle this display? */
996 if (var->xres > ch->cfg.lcd_cfg.xres ||
997 var->yres > ch->cfg.lcd_cfg.yres)
998 return -ENOMEM;
999
1000 /* Add to the modelist */
1001 fb_var_to_videomode(&mode, var);
1002 ret = fb_add_videomode(&mode, &ch->info->modelist);
1003 if (ret < 0)
1004 return ret;
1005 } 1403 }
1006 1404
1007 pm_runtime_get_sync(info->device); 1405 sh_mobile_lcdc_start(ch->lcdc);
1008
1009 sh_mobile_lcdc_geometry(ch);
1010
1011 break;
1012 } 1406 }
1013 1407
1014 return 0; 1408 return NOTIFY_OK;
1015} 1409}
1016 1410
1017static int sh_mobile_lcdc_remove(struct platform_device *pdev); 1411static int sh_mobile_lcdc_remove(struct platform_device *pdev);
@@ -1020,14 +1414,13 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1020{ 1414{
1021 struct fb_info *info; 1415 struct fb_info *info;
1022 struct sh_mobile_lcdc_priv *priv; 1416 struct sh_mobile_lcdc_priv *priv;
1023 struct sh_mobile_lcdc_info *pdata; 1417 struct sh_mobile_lcdc_info *pdata = pdev->dev.platform_data;
1024 struct sh_mobile_lcdc_chan_cfg *cfg;
1025 struct resource *res; 1418 struct resource *res;
1026 int error; 1419 int error;
1027 void *buf; 1420 void *buf;
1028 int i, j; 1421 int i, j;
1029 1422
1030 if (!pdev->dev.platform_data) { 1423 if (!pdata) {
1031 dev_err(&pdev->dev, "no platform data defined\n"); 1424 dev_err(&pdev->dev, "no platform data defined\n");
1032 return -EINVAL; 1425 return -EINVAL;
1033 } 1426 }
@@ -1055,31 +1448,37 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1055 } 1448 }
1056 1449
1057 priv->irq = i; 1450 priv->irq = i;
1058 pdata = pdev->dev.platform_data; 1451 atomic_set(&priv->hw_usecnt, -1);
1059 1452
1060 j = 0; 1453 j = 0;
1061 for (i = 0; i < ARRAY_SIZE(pdata->ch); i++) { 1454 for (i = 0; i < ARRAY_SIZE(pdata->ch); i++) {
1062 priv->ch[j].lcdc = priv; 1455 struct sh_mobile_lcdc_chan *ch = priv->ch + j;
1063 memcpy(&priv->ch[j].cfg, &pdata->ch[i], sizeof(pdata->ch[i])); 1456
1457 ch->lcdc = priv;
1458 memcpy(&ch->cfg, &pdata->ch[i], sizeof(pdata->ch[i]));
1064 1459
1065 error = sh_mobile_lcdc_check_interface(&priv->ch[j]); 1460 error = sh_mobile_lcdc_check_interface(ch);
1066 if (error) { 1461 if (error) {
1067 dev_err(&pdev->dev, "unsupported interface type\n"); 1462 dev_err(&pdev->dev, "unsupported interface type\n");
1068 goto err1; 1463 goto err1;
1069 } 1464 }
1070 init_waitqueue_head(&priv->ch[j].frame_end_wait); 1465 init_waitqueue_head(&ch->frame_end_wait);
1071 init_completion(&priv->ch[j].vsync_completion); 1466 init_completion(&ch->vsync_completion);
1072 priv->ch[j].pan_offset = 0; 1467 ch->pan_offset = 0;
1468
1469 /* probe the backlight is there is one defined */
1470 if (ch->cfg.bl_info.max_brightness)
1471 ch->bl = sh_mobile_lcdc_bl_probe(&pdev->dev, ch);
1073 1472
1074 switch (pdata->ch[i].chan) { 1473 switch (pdata->ch[i].chan) {
1075 case LCDC_CHAN_MAINLCD: 1474 case LCDC_CHAN_MAINLCD:
1076 priv->ch[j].enabled = 1 << 1; 1475 ch->enabled = 1 << 1;
1077 priv->ch[j].reg_offs = lcdc_offs_mainlcd; 1476 ch->reg_offs = lcdc_offs_mainlcd;
1078 j++; 1477 j++;
1079 break; 1478 break;
1080 case LCDC_CHAN_SUBLCD: 1479 case LCDC_CHAN_SUBLCD:
1081 priv->ch[j].enabled = 1 << 2; 1480 ch->enabled = 1 << 2;
1082 priv->ch[j].reg_offs = lcdc_offs_sublcd; 1481 ch->reg_offs = lcdc_offs_sublcd;
1083 j++; 1482 j++;
1084 break; 1483 break;
1085 } 1484 }
@@ -1091,6 +1490,10 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1091 goto err1; 1490 goto err1;
1092 } 1491 }
1093 1492
1493 /* for dual channel LCDC (MAIN + SUB) force shared bpp setting */
1494 if (j == 2)
1495 priv->forced_bpp = pdata->ch[0].bpp;
1496
1094 priv->base = ioremap_nocache(res->start, resource_size(res)); 1497 priv->base = ioremap_nocache(res->start, resource_size(res));
1095 if (!priv->base) 1498 if (!priv->base)
1096 goto err1; 1499 goto err1;
@@ -1101,71 +1504,112 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1101 goto err1; 1504 goto err1;
1102 } 1505 }
1103 1506
1507 priv->meram_dev = pdata->meram_dev;
1508
1104 for (i = 0; i < j; i++) { 1509 for (i = 0; i < j; i++) {
1105 struct fb_var_screeninfo *var; 1510 struct fb_var_screeninfo *var;
1106 struct fb_videomode *lcd_cfg; 1511 const struct fb_videomode *lcd_cfg, *max_cfg = NULL;
1107 cfg = &priv->ch[i].cfg; 1512 struct sh_mobile_lcdc_chan *ch = priv->ch + i;
1108 1513 struct sh_mobile_lcdc_chan_cfg *cfg = &ch->cfg;
1109 priv->ch[i].info = framebuffer_alloc(0, &pdev->dev); 1514 const struct fb_videomode *mode = cfg->lcd_cfg;
1110 if (!priv->ch[i].info) { 1515 unsigned long max_size = 0;
1516 int k;
1517 int num_cfg;
1518
1519 ch->info = framebuffer_alloc(0, &pdev->dev);
1520 if (!ch->info) {
1111 dev_err(&pdev->dev, "unable to allocate fb_info\n"); 1521 dev_err(&pdev->dev, "unable to allocate fb_info\n");
1112 error = -ENOMEM; 1522 error = -ENOMEM;
1113 break; 1523 break;
1114 } 1524 }
1115 1525
1116 info = priv->ch[i].info; 1526 info = ch->info;
1117 var = &info->var; 1527 var = &info->var;
1118 lcd_cfg = &cfg->lcd_cfg;
1119 info->fbops = &sh_mobile_lcdc_ops; 1528 info->fbops = &sh_mobile_lcdc_ops;
1120 var->xres = var->xres_virtual = lcd_cfg->xres; 1529 info->par = ch;
1121 var->yres = lcd_cfg->yres; 1530
1122 /* Default Y virtual resolution is 2x panel size */ 1531 mutex_init(&ch->open_lock);
1123 var->yres_virtual = var->yres * 2; 1532
1533 for (k = 0, lcd_cfg = mode;
1534 k < cfg->num_cfg && lcd_cfg;
1535 k++, lcd_cfg++) {
1536 unsigned long size = lcd_cfg->yres * lcd_cfg->xres;
1537 /* NV12 buffers must have even number of lines */
1538 if ((cfg->nonstd) && cfg->bpp == 12 &&
1539 (lcd_cfg->yres & 0x1)) {
1540 dev_err(&pdev->dev, "yres must be multiple of 2"
1541 " for YCbCr420 mode.\n");
1542 error = -EINVAL;
1543 goto err1;
1544 }
1545
1546 if (size > max_size) {
1547 max_cfg = lcd_cfg;
1548 max_size = size;
1549 }
1550 }
1551
1552 if (!mode)
1553 max_size = MAX_XRES * MAX_YRES;
1554 else if (max_cfg)
1555 dev_dbg(&pdev->dev, "Found largest videomode %ux%u\n",
1556 max_cfg->xres, max_cfg->yres);
1557
1558 info->fix = sh_mobile_lcdc_fix;
1559 info->fix.smem_len = max_size * 2 * cfg->bpp / 8;
1560
1561 /* Only pan in 2 line steps for NV12 */
1562 if (cfg->nonstd && cfg->bpp == 12)
1563 info->fix.ypanstep = 2;
1564
1565 if (!mode) {
1566 mode = &default_720p;
1567 num_cfg = 1;
1568 } else {
1569 num_cfg = cfg->num_cfg;
1570 }
1571
1572 fb_videomode_to_modelist(mode, num_cfg, &info->modelist);
1573
1574 fb_videomode_to_var(var, mode);
1124 var->width = cfg->lcd_size_cfg.width; 1575 var->width = cfg->lcd_size_cfg.width;
1125 var->height = cfg->lcd_size_cfg.height; 1576 var->height = cfg->lcd_size_cfg.height;
1577 /* Default Y virtual resolution is 2x panel size */
1578 var->yres_virtual = var->yres * 2;
1126 var->activate = FB_ACTIVATE_NOW; 1579 var->activate = FB_ACTIVATE_NOW;
1127 var->left_margin = lcd_cfg->left_margin; 1580
1128 var->right_margin = lcd_cfg->right_margin; 1581 error = sh_mobile_lcdc_set_bpp(var, cfg->bpp, cfg->nonstd);
1129 var->upper_margin = lcd_cfg->upper_margin;
1130 var->lower_margin = lcd_cfg->lower_margin;
1131 var->hsync_len = lcd_cfg->hsync_len;
1132 var->vsync_len = lcd_cfg->vsync_len;
1133 var->sync = lcd_cfg->sync;
1134 var->pixclock = lcd_cfg->pixclock;
1135
1136 error = sh_mobile_lcdc_set_bpp(var, cfg->bpp);
1137 if (error) 1582 if (error)
1138 break; 1583 break;
1139 1584
1140 info->fix = sh_mobile_lcdc_fix;
1141 info->fix.line_length = lcd_cfg->xres * (cfg->bpp / 8);
1142 info->fix.smem_len = info->fix.line_length *
1143 var->yres_virtual;
1144
1145 buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len, 1585 buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len,
1146 &priv->ch[i].dma_handle, GFP_KERNEL); 1586 &ch->dma_handle, GFP_KERNEL);
1147 if (!buf) { 1587 if (!buf) {
1148 dev_err(&pdev->dev, "unable to allocate buffer\n"); 1588 dev_err(&pdev->dev, "unable to allocate buffer\n");
1149 error = -ENOMEM; 1589 error = -ENOMEM;
1150 break; 1590 break;
1151 } 1591 }
1152 1592
1153 info->pseudo_palette = &priv->ch[i].pseudo_palette; 1593 info->pseudo_palette = &ch->pseudo_palette;
1154 info->flags = FBINFO_FLAG_DEFAULT; 1594 info->flags = FBINFO_FLAG_DEFAULT;
1155 1595
1156 error = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0); 1596 error = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
1157 if (error < 0) { 1597 if (error < 0) {
1158 dev_err(&pdev->dev, "unable to allocate cmap\n"); 1598 dev_err(&pdev->dev, "unable to allocate cmap\n");
1159 dma_free_coherent(&pdev->dev, info->fix.smem_len, 1599 dma_free_coherent(&pdev->dev, info->fix.smem_len,
1160 buf, priv->ch[i].dma_handle); 1600 buf, ch->dma_handle);
1161 break; 1601 break;
1162 } 1602 }
1163 1603
1164 memset(buf, 0, info->fix.smem_len); 1604 info->fix.smem_start = ch->dma_handle;
1165 info->fix.smem_start = priv->ch[i].dma_handle; 1605 if (var->nonstd)
1606 info->fix.line_length = var->xres;
1607 else
1608 info->fix.line_length = var->xres * (cfg->bpp / 8);
1609
1166 info->screen_base = buf; 1610 info->screen_base = buf;
1167 info->device = &pdev->dev; 1611 info->device = &pdev->dev;
1168 info->par = &priv->ch[i]; 1612 ch->display_var = *var;
1169 } 1613 }
1170 1614
1171 if (error) 1615 if (error)
@@ -1191,6 +1635,8 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1191 } 1635 }
1192 } 1636 }
1193 1637
1638 info->bl_dev = ch->bl;
1639
1194 error = register_framebuffer(info); 1640 error = register_framebuffer(info);
1195 if (error < 0) 1641 if (error < 0)
1196 goto err1; 1642 goto err1;
@@ -1200,8 +1646,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1200 pdev->name, 1646 pdev->name,
1201 (ch->cfg.chan == LCDC_CHAN_MAINLCD) ? 1647 (ch->cfg.chan == LCDC_CHAN_MAINLCD) ?
1202 "mainlcd" : "sublcd", 1648 "mainlcd" : "sublcd",
1203 (int) ch->cfg.lcd_cfg.xres, 1649 info->var.xres, info->var.yres,
1204 (int) ch->cfg.lcd_cfg.yres,
1205 ch->cfg.bpp); 1650 ch->cfg.bpp);
1206 1651
1207 /* deferred io mode: disable clock to save power */ 1652 /* deferred io mode: disable clock to save power */
@@ -1243,12 +1688,19 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
1243 if (priv->ch[i].sglist) 1688 if (priv->ch[i].sglist)
1244 vfree(priv->ch[i].sglist); 1689 vfree(priv->ch[i].sglist);
1245 1690
1246 dma_free_coherent(&pdev->dev, info->fix.smem_len, 1691 if (info->screen_base)
1247 info->screen_base, priv->ch[i].dma_handle); 1692 dma_free_coherent(&pdev->dev, info->fix.smem_len,
1693 info->screen_base,
1694 priv->ch[i].dma_handle);
1248 fb_dealloc_cmap(&info->cmap); 1695 fb_dealloc_cmap(&info->cmap);
1249 framebuffer_release(info); 1696 framebuffer_release(info);
1250 } 1697 }
1251 1698
1699 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
1700 if (priv->ch[i].bl)
1701 sh_mobile_lcdc_bl_remove(priv->ch[i].bl);
1702 }
1703
1252 if (priv->dot_clk) 1704 if (priv->dot_clk)
1253 clk_put(priv->dot_clk); 1705 clk_put(priv->dot_clk);
1254 1706
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
new file mode 100644
index 000000000000..aeed6687e6a7
--- /dev/null
+++ b/drivers/video/sh_mobile_lcdcfb.h
@@ -0,0 +1,45 @@
1#ifndef SH_MOBILE_LCDCFB_H
2#define SH_MOBILE_LCDCFB_H
3
4#include <linux/completion.h>
5#include <linux/fb.h>
6#include <linux/mutex.h>
7#include <linux/wait.h>
8
9/* per-channel registers */
10enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R,
11 LDSM2R, LDSA1R, LDSA2R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR,
12 LDHAJR,
13 NR_CH_REGS };
14
15#define PALETTE_NR 16
16
17struct sh_mobile_lcdc_priv;
18struct fb_info;
19struct backlight_device;
20
21struct sh_mobile_lcdc_chan {
22 struct sh_mobile_lcdc_priv *lcdc;
23 unsigned long *reg_offs;
24 unsigned long ldmt1r_value;
25 unsigned long enabled; /* ME and SE in LDCNT2R */
26 struct sh_mobile_lcdc_chan_cfg cfg;
27 u32 pseudo_palette[PALETTE_NR];
28 unsigned long saved_ch_regs[NR_CH_REGS];
29 struct fb_info *info;
30 struct backlight_device *bl;
31 dma_addr_t dma_handle;
32 struct fb_deferred_io defio;
33 struct scatterlist *sglist;
34 unsigned long frame_end;
35 unsigned long pan_offset;
36 wait_queue_head_t frame_end_wait;
37 struct completion vsync_completion;
38 struct fb_var_screeninfo display_var;
39 int use_count;
40 int blank_status;
41 struct mutex open_lock; /* protects the use counter */
42 int meram_enabled;
43};
44
45#endif
diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
new file mode 100644
index 000000000000..cc7d7329dc15
--- /dev/null
+++ b/drivers/video/sh_mobile_meram.c
@@ -0,0 +1,567 @@
1/*
2 * SuperH Mobile MERAM Driver for SuperH Mobile LCDC Driver
3 *
4 * Copyright (c) 2011 Damian Hobson-Garcia <dhobsong@igel.co.jp>
5 * Takanari Hayama <taki@igel.co.jp>
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
9 * for more details.
10 */
11
12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <linux/device.h>
15#include <linux/io.h>
16#include <linux/slab.h>
17#include <linux/platform_device.h>
18
19#include "sh_mobile_meram.h"
20
21/* meram registers */
22#define MExxCTL 0x0
23#define MExxBSIZE 0x4
24#define MExxMNCF 0x8
25#define MExxSARA 0x10
26#define MExxSARB 0x14
27#define MExxSBSIZE 0x18
28
29#define MERAM_MExxCTL_VAL(ctl, next_icb, addr) \
30 ((ctl) | (((next_icb) & 0x1f) << 11) | (((addr) & 0x7ff) << 16))
31#define MERAM_MExxBSIZE_VAL(a, b, c) \
32 (((a) << 28) | ((b) << 16) | (c))
33
34#define MEVCR1 0x4
35#define MEACTS 0x10
36#define MEQSEL1 0x40
37#define MEQSEL2 0x44
38
39/* settings */
40#define MERAM_SEC_LINE 15
41#define MERAM_LINE_WIDTH 2048
42
43/*
44 * MERAM/ICB access functions
45 */
46
47#define MERAM_ICB_OFFSET(base, idx, off) \
48 ((base) + (0x400 + ((idx) * 0x20) + (off)))
49
50static inline void meram_write_icb(void __iomem *base, int idx, int off,
51 unsigned long val)
52{
53 iowrite32(val, MERAM_ICB_OFFSET(base, idx, off));
54}
55
56static inline unsigned long meram_read_icb(void __iomem *base, int idx, int off)
57{
58 return ioread32(MERAM_ICB_OFFSET(base, idx, off));
59}
60
61static inline void meram_write_reg(void __iomem *base, int off,
62 unsigned long val)
63{
64 iowrite32(val, base + off);
65}
66
67static inline unsigned long meram_read_reg(void __iomem *base, int off)
68{
69 return ioread32(base + off);
70}
71
72/*
73 * register ICB
74 */
75
76#define MERAM_CACHE_START(p) ((p) >> 16)
77#define MERAM_CACHE_END(p) ((p) & 0xffff)
78#define MERAM_CACHE_SET(o, s) ((((o) & 0xffff) << 16) | \
79 (((o) + (s) - 1) & 0xffff))
80
81/*
82 * check if there's no overlaps in MERAM allocation.
83 */
84
85static inline int meram_check_overlap(struct sh_mobile_meram_priv *priv,
86 struct sh_mobile_meram_icb *new)
87{
88 int i;
89 int used_start, used_end, meram_start, meram_end;
90
91 /* valid ICB? */
92 if (new->marker_icb & ~0x1f || new->cache_icb & ~0x1f)
93 return 1;
94
95 if (test_bit(new->marker_icb, &priv->used_icb) ||
96 test_bit(new->cache_icb, &priv->used_icb))
97 return 1;
98
99 for (i = 0; i < priv->used_meram_cache_regions; i++) {
100 used_start = MERAM_CACHE_START(priv->used_meram_cache[i]);
101 used_end = MERAM_CACHE_END(priv->used_meram_cache[i]);
102 meram_start = new->meram_offset;
103 meram_end = new->meram_offset + new->meram_size;
104
105 if ((meram_start >= used_start && meram_start < used_end) ||
106 (meram_end > used_start && meram_end < used_end))
107 return 1;
108 }
109
110 return 0;
111}
112
113/*
114 * mark the specified ICB as used
115 */
116
117static inline void meram_mark(struct sh_mobile_meram_priv *priv,
118 struct sh_mobile_meram_icb *new)
119{
120 int n;
121
122 if (new->marker_icb < 0 || new->cache_icb < 0)
123 return;
124
125 __set_bit(new->marker_icb, &priv->used_icb);
126 __set_bit(new->cache_icb, &priv->used_icb);
127
128 n = priv->used_meram_cache_regions;
129
130 priv->used_meram_cache[n] = MERAM_CACHE_SET(new->meram_offset,
131 new->meram_size);
132
133 priv->used_meram_cache_regions++;
134}
135
136/*
137 * unmark the specified ICB as used
138 */
139
140static inline void meram_unmark(struct sh_mobile_meram_priv *priv,
141 struct sh_mobile_meram_icb *icb)
142{
143 int i;
144 unsigned long pattern;
145
146 if (icb->marker_icb < 0 || icb->cache_icb < 0)
147 return;
148
149 __clear_bit(icb->marker_icb, &priv->used_icb);
150 __clear_bit(icb->cache_icb, &priv->used_icb);
151
152 pattern = MERAM_CACHE_SET(icb->meram_offset, icb->meram_size);
153 for (i = 0; i < priv->used_meram_cache_regions; i++) {
154 if (priv->used_meram_cache[i] == pattern) {
155 while (i < priv->used_meram_cache_regions - 1) {
156 priv->used_meram_cache[i] =
157 priv->used_meram_cache[i + 1] ;
158 i++;
159 }
160 priv->used_meram_cache[i] = 0;
161 priv->used_meram_cache_regions--;
162 break;
163 }
164 }
165}
166
167/*
168 * is this a YCbCr(NV12, NV16 or NV24) colorspace
169 */
170static inline int is_nvcolor(int cspace)
171{
172 if (cspace == SH_MOBILE_MERAM_PF_NV ||
173 cspace == SH_MOBILE_MERAM_PF_NV24)
174 return 1;
175 return 0;
176}
177
178/*
179 * set the next address to fetch
180 */
181static inline void meram_set_next_addr(struct sh_mobile_meram_priv *priv,
182 struct sh_mobile_meram_cfg *cfg,
183 unsigned long base_addr_y,
184 unsigned long base_addr_c)
185{
186 unsigned long target;
187
188 target = (cfg->current_reg) ? MExxSARA : MExxSARB;
189 cfg->current_reg ^= 1;
190
191 /* set the next address to fetch */
192 meram_write_icb(priv->base, cfg->icb[0].cache_icb, target,
193 base_addr_y);
194 meram_write_icb(priv->base, cfg->icb[0].marker_icb, target,
195 base_addr_y + cfg->icb[0].cache_unit);
196
197 if (is_nvcolor(cfg->pixelformat)) {
198 meram_write_icb(priv->base, cfg->icb[1].cache_icb, target,
199 base_addr_c);
200 meram_write_icb(priv->base, cfg->icb[1].marker_icb, target,
201 base_addr_c + cfg->icb[1].cache_unit);
202 }
203}
204
205/*
206 * get the next ICB address
207 */
208static inline void meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata,
209 struct sh_mobile_meram_cfg *cfg,
210 unsigned long *icb_addr_y,
211 unsigned long *icb_addr_c)
212{
213 unsigned long icb_offset;
214
215 if (pdata->addr_mode == SH_MOBILE_MERAM_MODE0)
216 icb_offset = 0x80000000 | (cfg->current_reg << 29);
217 else
218 icb_offset = 0xc0000000 | (cfg->current_reg << 23);
219
220 *icb_addr_y = icb_offset | (cfg->icb[0].marker_icb << 24);
221 if (is_nvcolor(cfg->pixelformat))
222 *icb_addr_c = icb_offset | (cfg->icb[1].marker_icb << 24);
223}
224
225#define MERAM_CALC_BYTECOUNT(x, y) \
226 (((x) * (y) + (MERAM_LINE_WIDTH - 1)) & ~(MERAM_LINE_WIDTH - 1))
227
228/*
229 * initialize MERAM
230 */
231
232static int meram_init(struct sh_mobile_meram_priv *priv,
233 struct sh_mobile_meram_icb *icb,
234 int xres, int yres, int *out_pitch)
235{
236 unsigned long total_byte_count = MERAM_CALC_BYTECOUNT(xres, yres);
237 unsigned long bnm;
238 int lcdc_pitch, xpitch, line_cnt;
239 int save_lines;
240
241 /* adjust pitch to 1024, 2048, 4096 or 8192 */
242 lcdc_pitch = (xres - 1) | 1023;
243 lcdc_pitch = lcdc_pitch | (lcdc_pitch >> 1);
244 lcdc_pitch = lcdc_pitch | (lcdc_pitch >> 2);
245 lcdc_pitch += 1;
246
247 /* derive settings */
248 if (lcdc_pitch == 8192 && yres >= 1024) {
249 lcdc_pitch = xpitch = MERAM_LINE_WIDTH;
250 line_cnt = total_byte_count >> 11;
251 *out_pitch = xres;
252 save_lines = (icb->meram_size / 16 / MERAM_SEC_LINE);
253 save_lines *= MERAM_SEC_LINE;
254 } else {
255 xpitch = xres;
256 line_cnt = yres;
257 *out_pitch = lcdc_pitch;
258 save_lines = icb->meram_size / (lcdc_pitch >> 10) / 2;
259 save_lines &= 0xff;
260 }
261 bnm = (save_lines - 1) << 16;
262
263 /* TODO: we better to check if we have enough MERAM buffer size */
264
265 /* set up ICB */
266 meram_write_icb(priv->base, icb->cache_icb, MExxBSIZE,
267 MERAM_MExxBSIZE_VAL(0x0, line_cnt - 1, xpitch - 1));
268 meram_write_icb(priv->base, icb->marker_icb, MExxBSIZE,
269 MERAM_MExxBSIZE_VAL(0xf, line_cnt - 1, xpitch - 1));
270
271 meram_write_icb(priv->base, icb->cache_icb, MExxMNCF, bnm);
272 meram_write_icb(priv->base, icb->marker_icb, MExxMNCF, bnm);
273
274 meram_write_icb(priv->base, icb->cache_icb, MExxSBSIZE, xpitch);
275 meram_write_icb(priv->base, icb->marker_icb, MExxSBSIZE, xpitch);
276
277 /* save a cache unit size */
278 icb->cache_unit = xres * save_lines;
279
280 /*
281 * Set MERAM for framebuffer
282 *
283 * 0x70f: WD = 0x3, WS=0x1, CM=0x1, MD=FB mode
284 * we also chain the cache_icb and the marker_icb.
285 * we also split the allocated MERAM buffer between two ICBs.
286 */
287 meram_write_icb(priv->base, icb->cache_icb, MExxCTL,
288 MERAM_MExxCTL_VAL(0x70f, icb->marker_icb,
289 icb->meram_offset));
290 meram_write_icb(priv->base, icb->marker_icb, MExxCTL,
291 MERAM_MExxCTL_VAL(0x70f, icb->cache_icb,
292 icb->meram_offset +
293 icb->meram_size / 2));
294
295 return 0;
296}
297
298static void meram_deinit(struct sh_mobile_meram_priv *priv,
299 struct sh_mobile_meram_icb *icb)
300{
301 /* disable ICB */
302 meram_write_icb(priv->base, icb->cache_icb, MExxCTL, 0);
303 meram_write_icb(priv->base, icb->marker_icb, MExxCTL, 0);
304 icb->cache_unit = 0;
305}
306
307/*
308 * register the ICB
309 */
310
311static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
312 struct sh_mobile_meram_cfg *cfg,
313 int xres, int yres, int pixelformat,
314 unsigned long base_addr_y,
315 unsigned long base_addr_c,
316 unsigned long *icb_addr_y,
317 unsigned long *icb_addr_c,
318 int *pitch)
319{
320 struct platform_device *pdev;
321 struct sh_mobile_meram_priv *priv;
322 int n, out_pitch;
323 int error = 0;
324
325 if (!pdata || !pdata->priv || !pdata->pdev || !cfg)
326 return -EINVAL;
327
328 if (pixelformat != SH_MOBILE_MERAM_PF_NV &&
329 pixelformat != SH_MOBILE_MERAM_PF_NV24 &&
330 pixelformat != SH_MOBILE_MERAM_PF_RGB)
331 return -EINVAL;
332
333 priv = pdata->priv;
334 pdev = pdata->pdev;
335
336 dev_dbg(&pdev->dev, "registering %dx%d (%s) (y=%08lx, c=%08lx)",
337 xres, yres, (!pixelformat) ? "yuv" : "rgb",
338 base_addr_y, base_addr_c);
339
340 mutex_lock(&priv->lock);
341
342 /* we can't handle wider than 8192px */
343 if (xres > 8192) {
344 dev_err(&pdev->dev, "width exceeding the limit (> 8192).");
345 error = -EINVAL;
346 goto err;
347 }
348
349 if (priv->used_meram_cache_regions + 2 > SH_MOBILE_MERAM_ICB_NUM) {
350 dev_err(&pdev->dev, "no more ICB available.");
351 error = -EINVAL;
352 goto err;
353 }
354
355 /* do we have at least one ICB config? */
356 if (cfg->icb[0].marker_icb < 0 || cfg->icb[0].cache_icb < 0) {
357 dev_err(&pdev->dev, "at least one ICB is required.");
358 error = -EINVAL;
359 goto err;
360 }
361
362 /* make sure that there's no overlaps */
363 if (meram_check_overlap(priv, &cfg->icb[0])) {
364 dev_err(&pdev->dev, "conflicting config detected.");
365 error = -EINVAL;
366 goto err;
367 }
368 n = 1;
369
370 /* do the same if we have the second ICB set */
371 if (cfg->icb[1].marker_icb >= 0 && cfg->icb[1].cache_icb >= 0) {
372 if (meram_check_overlap(priv, &cfg->icb[1])) {
373 dev_err(&pdev->dev, "conflicting config detected.");
374 error = -EINVAL;
375 goto err;
376 }
377 n = 2;
378 }
379
380 if (is_nvcolor(pixelformat) && n != 2) {
381 dev_err(&pdev->dev, "requires two ICB sets for planar Y/C.");
382 error = -EINVAL;
383 goto err;
384 }
385
386 /* we now register the ICB */
387 cfg->pixelformat = pixelformat;
388 meram_mark(priv, &cfg->icb[0]);
389 if (is_nvcolor(pixelformat))
390 meram_mark(priv, &cfg->icb[1]);
391
392 /* initialize MERAM */
393 meram_init(priv, &cfg->icb[0], xres, yres, &out_pitch);
394 *pitch = out_pitch;
395 if (pixelformat == SH_MOBILE_MERAM_PF_NV)
396 meram_init(priv, &cfg->icb[1], xres, (yres + 1) / 2,
397 &out_pitch);
398 else if (pixelformat == SH_MOBILE_MERAM_PF_NV24)
399 meram_init(priv, &cfg->icb[1], 2 * xres, (yres + 1) / 2,
400 &out_pitch);
401
402 cfg->current_reg = 1;
403 meram_set_next_addr(priv, cfg, base_addr_y, base_addr_c);
404 meram_get_next_icb_addr(pdata, cfg, icb_addr_y, icb_addr_c);
405
406 dev_dbg(&pdev->dev, "registered - can access via y=%08lx, c=%08lx",
407 *icb_addr_y, *icb_addr_c);
408
409err:
410 mutex_unlock(&priv->lock);
411 return error;
412}
413
414static int sh_mobile_meram_unregister(struct sh_mobile_meram_info *pdata,
415 struct sh_mobile_meram_cfg *cfg)
416{
417 struct sh_mobile_meram_priv *priv;
418
419 if (!pdata || !pdata->priv || !cfg)
420 return -EINVAL;
421
422 priv = pdata->priv;
423
424 mutex_lock(&priv->lock);
425
426 /* deinit & unmark */
427 if (is_nvcolor(cfg->pixelformat)) {
428 meram_deinit(priv, &cfg->icb[1]);
429 meram_unmark(priv, &cfg->icb[1]);
430 }
431 meram_deinit(priv, &cfg->icb[0]);
432 meram_unmark(priv, &cfg->icb[0]);
433
434 mutex_unlock(&priv->lock);
435
436 return 0;
437}
438
439static int sh_mobile_meram_update(struct sh_mobile_meram_info *pdata,
440 struct sh_mobile_meram_cfg *cfg,
441 unsigned long base_addr_y,
442 unsigned long base_addr_c,
443 unsigned long *icb_addr_y,
444 unsigned long *icb_addr_c)
445{
446 struct sh_mobile_meram_priv *priv;
447
448 if (!pdata || !pdata->priv || !cfg)
449 return -EINVAL;
450
451 priv = pdata->priv;
452
453 mutex_lock(&priv->lock);
454
455 meram_set_next_addr(priv, cfg, base_addr_y, base_addr_c);
456 meram_get_next_icb_addr(pdata, cfg, icb_addr_y, icb_addr_c);
457
458 mutex_unlock(&priv->lock);
459
460 return 0;
461}
462
463static struct sh_mobile_meram_ops sh_mobile_meram_ops = {
464 .module = THIS_MODULE,
465 .meram_register = sh_mobile_meram_register,
466 .meram_unregister = sh_mobile_meram_unregister,
467 .meram_update = sh_mobile_meram_update,
468};
469
470/*
471 * initialize MERAM
472 */
473
474static int sh_mobile_meram_remove(struct platform_device *pdev);
475
476static int __devinit sh_mobile_meram_probe(struct platform_device *pdev)
477{
478 struct sh_mobile_meram_priv *priv;
479 struct sh_mobile_meram_info *pdata = pdev->dev.platform_data;
480 struct resource *res;
481 int error;
482
483 if (!pdata) {
484 dev_err(&pdev->dev, "no platform data defined\n");
485 return -EINVAL;
486 }
487
488 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
489 if (!res) {
490 dev_err(&pdev->dev, "cannot get platform resources\n");
491 return -ENOENT;
492 }
493
494 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
495 if (!priv) {
496 dev_err(&pdev->dev, "cannot allocate device data\n");
497 return -ENOMEM;
498 }
499
500 platform_set_drvdata(pdev, priv);
501
502 /* initialize private data */
503 mutex_init(&priv->lock);
504 priv->base = ioremap_nocache(res->start, resource_size(res));
505 if (!priv->base) {
506 dev_err(&pdev->dev, "ioremap failed\n");
507 error = -EFAULT;
508 goto err;
509 }
510 pdata->ops = &sh_mobile_meram_ops;
511 pdata->priv = priv;
512 pdata->pdev = pdev;
513
514 /* initialize ICB addressing mode */
515 if (pdata->addr_mode == SH_MOBILE_MERAM_MODE1)
516 meram_write_reg(priv->base, MEVCR1, 1 << 29);
517
518 dev_info(&pdev->dev, "sh_mobile_meram initialized.");
519
520 return 0;
521
522err:
523 sh_mobile_meram_remove(pdev);
524
525 return error;
526}
527
528
529static int sh_mobile_meram_remove(struct platform_device *pdev)
530{
531 struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
532
533 if (priv->base)
534 iounmap(priv->base);
535
536 mutex_destroy(&priv->lock);
537
538 kfree(priv);
539
540 return 0;
541}
542
543static struct platform_driver sh_mobile_meram_driver = {
544 .driver = {
545 .name = "sh_mobile_meram",
546 .owner = THIS_MODULE,
547 },
548 .probe = sh_mobile_meram_probe,
549 .remove = sh_mobile_meram_remove,
550};
551
552static int __init sh_mobile_meram_init(void)
553{
554 return platform_driver_register(&sh_mobile_meram_driver);
555}
556
557static void __exit sh_mobile_meram_exit(void)
558{
559 platform_driver_unregister(&sh_mobile_meram_driver);
560}
561
562module_init(sh_mobile_meram_init);
563module_exit(sh_mobile_meram_exit);
564
565MODULE_DESCRIPTION("SuperH Mobile MERAM driver");
566MODULE_AUTHOR("Damian Hobson-Garcia / Takanari Hayama");
567MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/sh_mobile_meram.h b/drivers/video/sh_mobile_meram.h
new file mode 100644
index 000000000000..82c54fbce8bd
--- /dev/null
+++ b/drivers/video/sh_mobile_meram.h
@@ -0,0 +1,41 @@
1#ifndef __sh_mobile_meram_h__
2#define __sh_mobile_meram_h__
3
4#include <linux/mutex.h>
5#include <video/sh_mobile_meram.h>
6
7/*
8 * MERAM private
9 */
10
11#define MERAM_ICB_Y 0x1
12#define MERAM_ICB_C 0x2
13
14/* MERAM cache size */
15#define SH_MOBILE_MERAM_ICB_NUM 32
16
17#define SH_MOBILE_MERAM_CACHE_OFFSET(p) ((p) >> 16)
18#define SH_MOBILE_MERAM_CACHE_SIZE(p) ((p) & 0xffff)
19
20struct sh_mobile_meram_priv {
21 void __iomem *base;
22 struct mutex lock;
23 unsigned long used_icb;
24 int used_meram_cache_regions;
25 unsigned long used_meram_cache[SH_MOBILE_MERAM_ICB_NUM];
26};
27
28int sh_mobile_meram_alloc_icb(const struct sh_mobile_meram_cfg *cfg,
29 int xres,
30 int yres,
31 unsigned int base_addr,
32 int yuv_mode,
33 int *marker_icb,
34 int *out_pitch);
35
36void sh_mobile_meram_free_icb(int marker_icb);
37
38#define SH_MOBILE_MERAM_START(ind, ab) \
39 (0xC0000000 | ((ab & 0x1) << 23) | ((ind & 0x1F) << 24))
40
41#endif /* !__sh_mobile_meram_h__ */
diff --git a/drivers/video/sis/init.c b/drivers/video/sis/init.c
index c311ad3c3687..66de832361cc 100644
--- a/drivers/video/sis/init.c
+++ b/drivers/video/sis/init.c
@@ -56,17 +56,13 @@
56 * Used by permission. 56 * Used by permission.
57 */ 57 */
58 58
59#ifdef HAVE_CONFIG_H
60#include "config.h"
61#endif
62
63#include "init.h" 59#include "init.h"
64 60
65#ifdef SIS300 61#ifdef CONFIG_FB_SIS_300
66#include "300vtbl.h" 62#include "300vtbl.h"
67#endif 63#endif
68 64
69#ifdef SIS315H 65#ifdef CONFIG_FB_SIS_315
70#include "310vtbl.h" 66#include "310vtbl.h"
71#endif 67#endif
72 68
@@ -78,7 +74,7 @@
78/* POINTER INITIALIZATION */ 74/* POINTER INITIALIZATION */
79/*********************************************/ 75/*********************************************/
80 76
81#if defined(SIS300) || defined(SIS315H) 77#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
82static void 78static void
83InitCommonPointer(struct SiS_Private *SiS_Pr) 79InitCommonPointer(struct SiS_Private *SiS_Pr)
84{ 80{
@@ -160,7 +156,7 @@ InitCommonPointer(struct SiS_Private *SiS_Pr)
160} 156}
161#endif 157#endif
162 158
163#ifdef SIS300 159#ifdef CONFIG_FB_SIS_300
164static void 160static void
165InitTo300Pointer(struct SiS_Private *SiS_Pr) 161InitTo300Pointer(struct SiS_Private *SiS_Pr)
166{ 162{
@@ -237,7 +233,7 @@ InitTo300Pointer(struct SiS_Private *SiS_Pr)
237} 233}
238#endif 234#endif
239 235
240#ifdef SIS315H 236#ifdef CONFIG_FB_SIS_315
241static void 237static void
242InitTo310Pointer(struct SiS_Private *SiS_Pr) 238InitTo310Pointer(struct SiS_Private *SiS_Pr)
243{ 239{
@@ -321,13 +317,13 @@ bool
321SiSInitPtr(struct SiS_Private *SiS_Pr) 317SiSInitPtr(struct SiS_Private *SiS_Pr)
322{ 318{
323 if(SiS_Pr->ChipType < SIS_315H) { 319 if(SiS_Pr->ChipType < SIS_315H) {
324#ifdef SIS300 320#ifdef CONFIG_FB_SIS_300
325 InitTo300Pointer(SiS_Pr); 321 InitTo300Pointer(SiS_Pr);
326#else 322#else
327 return false; 323 return false;
328#endif 324#endif
329 } else { 325 } else {
330#ifdef SIS315H 326#ifdef CONFIG_FB_SIS_315
331 InitTo310Pointer(SiS_Pr); 327 InitTo310Pointer(SiS_Pr);
332#else 328#else
333 return false; 329 return false;
@@ -340,9 +336,7 @@ SiSInitPtr(struct SiS_Private *SiS_Pr)
340/* HELPER: Get ModeID */ 336/* HELPER: Get ModeID */
341/*********************************************/ 337/*********************************************/
342 338
343#ifndef SIS_XORG_XF86
344static 339static
345#endif
346unsigned short 340unsigned short
347SiS_GetModeID(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay, 341SiS_GetModeID(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
348 int Depth, bool FSTN, int LCDwidth, int LCDheight) 342 int Depth, bool FSTN, int LCDwidth, int LCDheight)
@@ -882,59 +876,59 @@ SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDispl
882/*********************************************/ 876/*********************************************/
883 877
884void 878void
885SiS_SetReg(SISIOADDRESS port, unsigned short index, unsigned short data) 879SiS_SetReg(SISIOADDRESS port, u8 index, u8 data)
886{ 880{
887 OutPortByte(port, index); 881 outb(index, port);
888 OutPortByte(port + 1, data); 882 outb(data, port + 1);
889} 883}
890 884
891void 885void
892SiS_SetRegByte(SISIOADDRESS port, unsigned short data) 886SiS_SetRegByte(SISIOADDRESS port, u8 data)
893{ 887{
894 OutPortByte(port, data); 888 outb(data, port);
895} 889}
896 890
897void 891void
898SiS_SetRegShort(SISIOADDRESS port, unsigned short data) 892SiS_SetRegShort(SISIOADDRESS port, u16 data)
899{ 893{
900 OutPortWord(port, data); 894 outw(data, port);
901} 895}
902 896
903void 897void
904SiS_SetRegLong(SISIOADDRESS port, unsigned int data) 898SiS_SetRegLong(SISIOADDRESS port, u32 data)
905{ 899{
906 OutPortLong(port, data); 900 outl(data, port);
907} 901}
908 902
909unsigned char 903u8
910SiS_GetReg(SISIOADDRESS port, unsigned short index) 904SiS_GetReg(SISIOADDRESS port, u8 index)
911{ 905{
912 OutPortByte(port, index); 906 outb(index, port);
913 return(InPortByte(port + 1)); 907 return inb(port + 1);
914} 908}
915 909
916unsigned char 910u8
917SiS_GetRegByte(SISIOADDRESS port) 911SiS_GetRegByte(SISIOADDRESS port)
918{ 912{
919 return(InPortByte(port)); 913 return inb(port);
920} 914}
921 915
922unsigned short 916u16
923SiS_GetRegShort(SISIOADDRESS port) 917SiS_GetRegShort(SISIOADDRESS port)
924{ 918{
925 return(InPortWord(port)); 919 return inw(port);
926} 920}
927 921
928unsigned int 922u32
929SiS_GetRegLong(SISIOADDRESS port) 923SiS_GetRegLong(SISIOADDRESS port)
930{ 924{
931 return(InPortLong(port)); 925 return inl(port);
932} 926}
933 927
934void 928void
935SiS_SetRegANDOR(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND, unsigned short DataOR) 929SiS_SetRegANDOR(SISIOADDRESS Port, u8 Index, u8 DataAND, u8 DataOR)
936{ 930{
937 unsigned short temp; 931 u8 temp;
938 932
939 temp = SiS_GetReg(Port, Index); 933 temp = SiS_GetReg(Port, Index);
940 temp = (temp & (DataAND)) | DataOR; 934 temp = (temp & (DataAND)) | DataOR;
@@ -942,9 +936,9 @@ SiS_SetRegANDOR(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND,
942} 936}
943 937
944void 938void
945SiS_SetRegAND(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND) 939SiS_SetRegAND(SISIOADDRESS Port, u8 Index, u8 DataAND)
946{ 940{
947 unsigned short temp; 941 u8 temp;
948 942
949 temp = SiS_GetReg(Port, Index); 943 temp = SiS_GetReg(Port, Index);
950 temp &= DataAND; 944 temp &= DataAND;
@@ -952,9 +946,9 @@ SiS_SetRegAND(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND)
952} 946}
953 947
954void 948void
955SiS_SetRegOR(SISIOADDRESS Port, unsigned short Index, unsigned short DataOR) 949SiS_SetRegOR(SISIOADDRESS Port, u8 Index, u8 DataOR)
956{ 950{
957 unsigned short temp; 951 u8 temp;
958 952
959 temp = SiS_GetReg(Port, Index); 953 temp = SiS_GetReg(Port, Index);
960 temp |= DataOR; 954 temp |= DataOR;
@@ -1089,7 +1083,7 @@ static void
1089SiSInitPCIetc(struct SiS_Private *SiS_Pr) 1083SiSInitPCIetc(struct SiS_Private *SiS_Pr)
1090{ 1084{
1091 switch(SiS_Pr->ChipType) { 1085 switch(SiS_Pr->ChipType) {
1092#ifdef SIS300 1086#ifdef CONFIG_FB_SIS_300
1093 case SIS_300: 1087 case SIS_300:
1094 case SIS_540: 1088 case SIS_540:
1095 case SIS_630: 1089 case SIS_630:
@@ -1108,7 +1102,7 @@ SiSInitPCIetc(struct SiS_Private *SiS_Pr)
1108 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x5A); 1102 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x5A);
1109 break; 1103 break;
1110#endif 1104#endif
1111#ifdef SIS315H 1105#ifdef CONFIG_FB_SIS_315
1112 case SIS_315H: 1106 case SIS_315H:
1113 case SIS_315: 1107 case SIS_315:
1114 case SIS_315PRO: 1108 case SIS_315PRO:
@@ -1152,9 +1146,7 @@ SiSInitPCIetc(struct SiS_Private *SiS_Pr)
1152/* HELPER: SetLVDSetc */ 1146/* HELPER: SetLVDSetc */
1153/*********************************************/ 1147/*********************************************/
1154 1148
1155#ifdef SIS_LINUX_KERNEL
1156static 1149static
1157#endif
1158void 1150void
1159SiSSetLVDSetc(struct SiS_Private *SiS_Pr) 1151SiSSetLVDSetc(struct SiS_Private *SiS_Pr)
1160{ 1152{
@@ -1174,7 +1166,7 @@ SiSSetLVDSetc(struct SiS_Private *SiS_Pr)
1174 if((temp == 1) || (temp == 2)) return; 1166 if((temp == 1) || (temp == 2)) return;
1175 1167
1176 switch(SiS_Pr->ChipType) { 1168 switch(SiS_Pr->ChipType) {
1177#ifdef SIS300 1169#ifdef CONFIG_FB_SIS_300
1178 case SIS_540: 1170 case SIS_540:
1179 case SIS_630: 1171 case SIS_630:
1180 case SIS_730: 1172 case SIS_730:
@@ -1188,7 +1180,7 @@ SiSSetLVDSetc(struct SiS_Private *SiS_Pr)
1188 } 1180 }
1189 break; 1181 break;
1190#endif 1182#endif
1191#ifdef SIS315H 1183#ifdef CONFIG_FB_SIS_315
1192 case SIS_550: 1184 case SIS_550:
1193 case SIS_650: 1185 case SIS_650:
1194 case SIS_740: 1186 case SIS_740:
@@ -1420,9 +1412,7 @@ SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr)
1420/* HELPER: GetVBType */ 1412/* HELPER: GetVBType */
1421/*********************************************/ 1413/*********************************************/
1422 1414
1423#ifdef SIS_LINUX_KERNEL
1424static 1415static
1425#endif
1426void 1416void
1427SiS_GetVBType(struct SiS_Private *SiS_Pr) 1417SiS_GetVBType(struct SiS_Private *SiS_Pr)
1428{ 1418{
@@ -1487,7 +1477,6 @@ SiS_GetVBType(struct SiS_Private *SiS_Pr)
1487/* HELPER: Check RAM size */ 1477/* HELPER: Check RAM size */
1488/*********************************************/ 1478/*********************************************/
1489 1479
1490#ifdef SIS_LINUX_KERNEL
1491static bool 1480static bool
1492SiS_CheckMemorySize(struct SiS_Private *SiS_Pr, unsigned short ModeNo, 1481SiS_CheckMemorySize(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
1493 unsigned short ModeIdIndex) 1482 unsigned short ModeIdIndex)
@@ -1501,13 +1490,12 @@ SiS_CheckMemorySize(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
1501 if(AdapterMemSize < memorysize) return false; 1490 if(AdapterMemSize < memorysize) return false;
1502 return true; 1491 return true;
1503} 1492}
1504#endif
1505 1493
1506/*********************************************/ 1494/*********************************************/
1507/* HELPER: Get DRAM type */ 1495/* HELPER: Get DRAM type */
1508/*********************************************/ 1496/*********************************************/
1509 1497
1510#ifdef SIS315H 1498#ifdef CONFIG_FB_SIS_315
1511static unsigned char 1499static unsigned char
1512SiS_Get310DRAMType(struct SiS_Private *SiS_Pr) 1500SiS_Get310DRAMType(struct SiS_Private *SiS_Pr)
1513{ 1501{
@@ -1574,7 +1562,6 @@ SiS_GetMCLK(struct SiS_Private *SiS_Pr)
1574/* HELPER: ClearBuffer */ 1562/* HELPER: ClearBuffer */
1575/*********************************************/ 1563/*********************************************/
1576 1564
1577#ifdef SIS_LINUX_KERNEL
1578static void 1565static void
1579SiS_ClearBuffer(struct SiS_Private *SiS_Pr, unsigned short ModeNo) 1566SiS_ClearBuffer(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
1580{ 1567{
@@ -1587,7 +1574,7 @@ SiS_ClearBuffer(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
1587 1574
1588 if(SiS_Pr->SiS_ModeType >= ModeEGA) { 1575 if(SiS_Pr->SiS_ModeType >= ModeEGA) {
1589 if(ModeNo > 0x13) { 1576 if(ModeNo > 0x13) {
1590 SiS_SetMemory(memaddr, memsize, 0); 1577 memset_io(memaddr, 0, memsize);
1591 } else { 1578 } else {
1592 pBuffer = (unsigned short SISIOMEMTYPE *)memaddr; 1579 pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;
1593 for(i = 0; i < 0x4000; i++) writew(0x0000, &pBuffer[i]); 1580 for(i = 0; i < 0x4000; i++) writew(0x0000, &pBuffer[i]);
@@ -1596,10 +1583,9 @@ SiS_ClearBuffer(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
1596 pBuffer = (unsigned short SISIOMEMTYPE *)memaddr; 1583 pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;
1597 for(i = 0; i < 0x4000; i++) writew(0x0720, &pBuffer[i]); 1584 for(i = 0; i < 0x4000; i++) writew(0x0720, &pBuffer[i]);
1598 } else { 1585 } else {
1599 SiS_SetMemory(memaddr, 0x8000, 0); 1586 memset_io(memaddr, 0, 0x8000);
1600 } 1587 }
1601} 1588}
1602#endif
1603 1589
1604/*********************************************/ 1590/*********************************************/
1605/* HELPER: SearchModeID */ 1591/* HELPER: SearchModeID */
@@ -2132,7 +2118,7 @@ SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2132 SiS_SetReg(SiS_Pr->SiS_P3d4,0x14,0x4F); 2118 SiS_SetReg(SiS_Pr->SiS_P3d4,0x14,0x4F);
2133 } 2119 }
2134 2120
2135#ifdef SIS315H 2121#ifdef CONFIG_FB_SIS_315
2136 if(SiS_Pr->ChipType == XGI_20) { 2122 if(SiS_Pr->ChipType == XGI_20) {
2137 SiS_SetReg(SiS_Pr->SiS_P3d4,0x04,crt1data[4] - 1); 2123 SiS_SetReg(SiS_Pr->SiS_P3d4,0x04,crt1data[4] - 1);
2138 if(!(temp = crt1data[5] & 0x1f)) { 2124 if(!(temp = crt1data[5] & 0x1f)) {
@@ -2215,7 +2201,7 @@ SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2215 SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,clkb); 2201 SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,clkb);
2216 2202
2217 if(SiS_Pr->ChipType >= SIS_315H) { 2203 if(SiS_Pr->ChipType >= SIS_315H) {
2218#ifdef SIS315H 2204#ifdef CONFIG_FB_SIS_315
2219 SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x01); 2205 SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x01);
2220 if(SiS_Pr->ChipType == XGI_20) { 2206 if(SiS_Pr->ChipType == XGI_20) {
2221 unsigned short mf = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex); 2207 unsigned short mf = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
@@ -2236,7 +2222,7 @@ SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2236/* FIFO */ 2222/* FIFO */
2237/*********************************************/ 2223/*********************************************/
2238 2224
2239#ifdef SIS300 2225#ifdef CONFIG_FB_SIS_300
2240void 2226void
2241SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *idx1, 2227SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *idx1,
2242 unsigned short *idx2) 2228 unsigned short *idx2)
@@ -2506,11 +2492,7 @@ SiS_SetCRT1FIFO_630(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2506 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x09,0x80,data); 2492 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x09,0x80,data);
2507 2493
2508 /* Write foreground and background queue */ 2494 /* Write foreground and background queue */
2509#ifdef SIS_LINUX_KERNEL
2510 templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50); 2495 templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
2511#else
2512 templ = pciReadLong(0x00000000, 0x50);
2513#endif
2514 2496
2515 if(SiS_Pr->ChipType == SIS_730) { 2497 if(SiS_Pr->ChipType == SIS_730) {
2516 2498
@@ -2530,13 +2512,8 @@ SiS_SetCRT1FIFO_630(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2530 2512
2531 } 2513 }
2532 2514
2533#ifdef SIS_LINUX_KERNEL
2534 sisfb_write_nbridge_pci_dword(SiS_Pr, 0x50, templ); 2515 sisfb_write_nbridge_pci_dword(SiS_Pr, 0x50, templ);
2535 templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xA0); 2516 templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xA0);
2536#else
2537 pciWriteLong(0x00000000, 0x50, templ);
2538 templ = pciReadLong(0x00000000, 0xA0);
2539#endif
2540 2517
2541 /* GUI grant timer (PCI config 0xA3) */ 2518 /* GUI grant timer (PCI config 0xA3) */
2542 if(SiS_Pr->ChipType == SIS_730) { 2519 if(SiS_Pr->ChipType == SIS_730) {
@@ -2552,15 +2529,11 @@ SiS_SetCRT1FIFO_630(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2552 2529
2553 } 2530 }
2554 2531
2555#ifdef SIS_LINUX_KERNEL
2556 sisfb_write_nbridge_pci_dword(SiS_Pr, 0xA0, templ); 2532 sisfb_write_nbridge_pci_dword(SiS_Pr, 0xA0, templ);
2557#else
2558 pciWriteLong(0x00000000, 0xA0, templ);
2559#endif
2560} 2533}
2561#endif /* SIS300 */ 2534#endif /* CONFIG_FB_SIS_300 */
2562 2535
2563#ifdef SIS315H 2536#ifdef CONFIG_FB_SIS_315
2564static void 2537static void
2565SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex) 2538SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
2566{ 2539{
@@ -2612,7 +2585,7 @@ SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2612 } 2585 }
2613 2586
2614 if(SiS_Pr->ChipType < SIS_315H) { 2587 if(SiS_Pr->ChipType < SIS_315H) {
2615#ifdef SIS300 2588#ifdef CONFIG_FB_SIS_300
2616 if(VCLK > 150) data |= 0x80; 2589 if(VCLK > 150) data |= 0x80;
2617 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data); 2590 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data);
2618 2591
@@ -2621,7 +2594,7 @@ SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2621 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data); 2594 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data);
2622#endif 2595#endif
2623 } else if(SiS_Pr->ChipType < XGI_20) { 2596 } else if(SiS_Pr->ChipType < XGI_20) {
2624#ifdef SIS315H 2597#ifdef CONFIG_FB_SIS_315
2625 if(VCLK >= 166) data |= 0x0c; 2598 if(VCLK >= 166) data |= 0x0c;
2626 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data); 2599 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
2627 2600
@@ -2630,7 +2603,7 @@ SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2630 } 2603 }
2631#endif 2604#endif
2632 } else { 2605 } else {
2633#ifdef SIS315H 2606#ifdef CONFIG_FB_SIS_315
2634 if(VCLK >= 200) data |= 0x0c; 2607 if(VCLK >= 200) data |= 0x0c;
2635 if(SiS_Pr->ChipType == XGI_20) data &= ~0x04; 2608 if(SiS_Pr->ChipType == XGI_20) data &= ~0x04;
2636 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data); 2609 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
@@ -2675,7 +2648,7 @@ SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2675 unsigned short ModeIdIndex, unsigned short RRTI) 2648 unsigned short ModeIdIndex, unsigned short RRTI)
2676{ 2649{
2677 unsigned short data, infoflag = 0, modeflag, resindex; 2650 unsigned short data, infoflag = 0, modeflag, resindex;
2678#ifdef SIS315H 2651#ifdef CONFIG_FB_SIS_315
2679 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase; 2652 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
2680 unsigned short data2, data3; 2653 unsigned short data2, data3;
2681#endif 2654#endif
@@ -2736,7 +2709,7 @@ SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2736 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,data); 2709 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,data);
2737 } 2710 }
2738 2711
2739#ifdef SIS315H 2712#ifdef CONFIG_FB_SIS_315
2740 if(SiS_Pr->ChipType >= SIS_315H) { 2713 if(SiS_Pr->ChipType >= SIS_315H) {
2741 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xfb); 2714 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xfb);
2742 } 2715 }
@@ -2826,7 +2799,7 @@ SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2826 2799
2827 SiS_SetVCLKState(SiS_Pr, ModeNo, RRTI, ModeIdIndex); 2800 SiS_SetVCLKState(SiS_Pr, ModeNo, RRTI, ModeIdIndex);
2828 2801
2829#ifdef SIS315H 2802#ifdef CONFIG_FB_SIS_315
2830 if(((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) || 2803 if(((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) ||
2831 (SiS_Pr->ChipType == XGI_40)) { 2804 (SiS_Pr->ChipType == XGI_40)) {
2832 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) { 2805 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
@@ -2845,7 +2818,7 @@ SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2845#endif 2818#endif
2846} 2819}
2847 2820
2848#ifdef SIS315H 2821#ifdef CONFIG_FB_SIS_315
2849static void 2822static void
2850SiS_SetupDualChip(struct SiS_Private *SiS_Pr) 2823SiS_SetupDualChip(struct SiS_Private *SiS_Pr)
2851{ 2824{
@@ -2999,11 +2972,6 @@ SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned sho
2999 SiS_Pr->SiS_SelectCRT2Rate = 0; 2972 SiS_Pr->SiS_SelectCRT2Rate = 0;
3000 SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2); 2973 SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
3001 2974
3002#ifdef SIS_XORG_XF86
3003 xf86DrvMsgVerb(0, X_PROBED, 4, "(init: VBType=0x%04x, VBInfo=0x%04x)\n",
3004 SiS_Pr->SiS_VBType, SiS_Pr->SiS_VBInfo);
3005#endif
3006
3007 if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) { 2975 if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
3008 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) { 2976 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
3009 SiS_Pr->SiS_SetFlag |= ProgrammingCRT2; 2977 SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
@@ -3028,7 +2996,7 @@ SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned sho
3028 } 2996 }
3029 2997
3030 switch(SiS_Pr->ChipType) { 2998 switch(SiS_Pr->ChipType) {
3031#ifdef SIS300 2999#ifdef CONFIG_FB_SIS_300
3032 case SIS_300: 3000 case SIS_300:
3033 SiS_SetCRT1FIFO_300(SiS_Pr, ModeNo, RefreshRateTableIndex); 3001 SiS_SetCRT1FIFO_300(SiS_Pr, ModeNo, RefreshRateTableIndex);
3034 break; 3002 break;
@@ -3039,7 +3007,7 @@ SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned sho
3039 break; 3007 break;
3040#endif 3008#endif
3041 default: 3009 default:
3042#ifdef SIS315H 3010#ifdef CONFIG_FB_SIS_315
3043 if(SiS_Pr->ChipType == XGI_20) { 3011 if(SiS_Pr->ChipType == XGI_20) {
3044 unsigned char sr2b = 0, sr2c = 0; 3012 unsigned char sr2b = 0, sr2c = 0;
3045 switch(ModeNo) { 3013 switch(ModeNo) {
@@ -3062,7 +3030,7 @@ SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned sho
3062 3030
3063 SiS_SetCRT1ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex); 3031 SiS_SetCRT1ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3064 3032
3065#ifdef SIS315H 3033#ifdef CONFIG_FB_SIS_315
3066 if(SiS_Pr->ChipType == XGI_40) { 3034 if(SiS_Pr->ChipType == XGI_40) {
3067 SiS_SetupDualChip(SiS_Pr); 3035 SiS_SetupDualChip(SiS_Pr);
3068 } 3036 }
@@ -3070,11 +3038,9 @@ SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned sho
3070 3038
3071 SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex); 3039 SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
3072 3040
3073#ifdef SIS_LINUX_KERNEL
3074 if(SiS_Pr->SiS_flag_clearbuffer) { 3041 if(SiS_Pr->SiS_flag_clearbuffer) {
3075 SiS_ClearBuffer(SiS_Pr, ModeNo); 3042 SiS_ClearBuffer(SiS_Pr, ModeNo);
3076 } 3043 }
3077#endif
3078 3044
3079 if(!(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA))) { 3045 if(!(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA))) {
3080 SiS_WaitRetrace1(SiS_Pr); 3046 SiS_WaitRetrace1(SiS_Pr);
@@ -3104,7 +3070,7 @@ SiS_InitVB(struct SiS_Private *SiS_Pr)
3104static void 3070static void
3105SiS_ResetVB(struct SiS_Private *SiS_Pr) 3071SiS_ResetVB(struct SiS_Private *SiS_Pr)
3106{ 3072{
3107#ifdef SIS315H 3073#ifdef CONFIG_FB_SIS_315
3108 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase; 3074 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
3109 unsigned short temp; 3075 unsigned short temp;
3110 3076
@@ -3139,7 +3105,7 @@ SiS_StrangeStuff(struct SiS_Private *SiS_Pr)
3139 * which locks CRT2 in some way to CRT1 timing. Disable 3105 * which locks CRT2 in some way to CRT1 timing. Disable
3140 * this here. 3106 * this here.
3141 */ 3107 */
3142#ifdef SIS315H 3108#ifdef CONFIG_FB_SIS_315
3143 if((IS_SIS651) || (IS_SISM650) || 3109 if((IS_SIS651) || (IS_SISM650) ||
3144 SiS_Pr->ChipType == SIS_340 || 3110 SiS_Pr->ChipType == SIS_340 ||
3145 SiS_Pr->ChipType == XGI_40) { 3111 SiS_Pr->ChipType == XGI_40) {
@@ -3160,7 +3126,7 @@ SiS_StrangeStuff(struct SiS_Private *SiS_Pr)
3160static void 3126static void
3161SiS_Handle760(struct SiS_Private *SiS_Pr) 3127SiS_Handle760(struct SiS_Private *SiS_Pr)
3162{ 3128{
3163#ifdef SIS315H 3129#ifdef CONFIG_FB_SIS_315
3164 unsigned int somebase; 3130 unsigned int somebase;
3165 unsigned char temp1, temp2, temp3; 3131 unsigned char temp1, temp2, temp3;
3166 3132
@@ -3170,11 +3136,7 @@ SiS_Handle760(struct SiS_Private *SiS_Pr)
3170 (!(SiS_Pr->SiS_SysFlags & SF_760UMA)) ) 3136 (!(SiS_Pr->SiS_SysFlags & SF_760UMA)) )
3171 return; 3137 return;
3172 3138
3173#ifdef SIS_LINUX_KERNEL
3174 somebase = sisfb_read_mio_pci_word(SiS_Pr, 0x74); 3139 somebase = sisfb_read_mio_pci_word(SiS_Pr, 0x74);
3175#else
3176 somebase = pciReadWord(0x00001000, 0x74);
3177#endif
3178 somebase &= 0xffff; 3140 somebase &= 0xffff;
3179 3141
3180 if(somebase == 0) return; 3142 if(somebase == 0) return;
@@ -3190,105 +3152,34 @@ SiS_Handle760(struct SiS_Private *SiS_Pr)
3190 temp2 = 0x0b; 3152 temp2 = 0x0b;
3191 } 3153 }
3192 3154
3193#ifdef SIS_LINUX_KERNEL
3194 sisfb_write_nbridge_pci_byte(SiS_Pr, 0x7e, temp1); 3155 sisfb_write_nbridge_pci_byte(SiS_Pr, 0x7e, temp1);
3195 sisfb_write_nbridge_pci_byte(SiS_Pr, 0x8d, temp2); 3156 sisfb_write_nbridge_pci_byte(SiS_Pr, 0x8d, temp2);
3196#else
3197 pciWriteByte(0x00000000, 0x7e, temp1);
3198 pciWriteByte(0x00000000, 0x8d, temp2);
3199#endif
3200 3157
3201 SiS_SetRegByte((somebase + 0x85), temp3); 3158 SiS_SetRegByte((somebase + 0x85), temp3);
3202#endif 3159#endif
3203} 3160}
3204 3161
3205/*********************************************/ 3162/*********************************************/
3206/* X.org/XFree86: SET SCREEN PITCH */
3207/*********************************************/
3208
3209#ifdef SIS_XORG_XF86
3210static void
3211SiS_SetPitchCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
3212{
3213 SISPtr pSiS = SISPTR(pScrn);
3214 unsigned short HDisplay = pSiS->scrnPitch >> 3;
3215
3216 SiS_SetReg(SiS_Pr->SiS_P3d4,0x13,(HDisplay & 0xFF));
3217 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,(HDisplay >> 8));
3218}
3219
3220static void
3221SiS_SetPitchCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
3222{
3223 SISPtr pSiS = SISPTR(pScrn);
3224 unsigned short HDisplay = pSiS->scrnPitch2 >> 3;
3225
3226 /* Unlock CRT2 */
3227 if(pSiS->VGAEngine == SIS_315_VGA)
3228 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2F, 0x01);
3229 else
3230 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24, 0x01);
3231
3232 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(HDisplay & 0xFF));
3233 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0xF0,(HDisplay >> 8));
3234}
3235
3236static void
3237SiS_SetPitch(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
3238{
3239 SISPtr pSiS = SISPTR(pScrn);
3240 bool isslavemode = false;
3241
3242 if( (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) &&
3243 ( ((pSiS->VGAEngine == SIS_300_VGA) &&
3244 (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0xa0) == 0x20) ||
3245 ((pSiS->VGAEngine == SIS_315_VGA) &&
3246 (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x50) == 0x10) ) ) {
3247 isslavemode = true;
3248 }
3249
3250 /* We need to set pitch for CRT1 if bridge is in slave mode, too */
3251 if((pSiS->VBFlags & DISPTYPE_DISP1) || (isslavemode)) {
3252 SiS_SetPitchCRT1(SiS_Pr, pScrn);
3253 }
3254 /* We must not set the pitch for CRT2 if bridge is in slave mode */
3255 if((pSiS->VBFlags & DISPTYPE_DISP2) && (!isslavemode)) {
3256 SiS_SetPitchCRT2(SiS_Pr, pScrn);
3257 }
3258}
3259#endif
3260
3261/*********************************************/
3262/* SiSSetMode() */ 3163/* SiSSetMode() */
3263/*********************************************/ 3164/*********************************************/
3264 3165
3265#ifdef SIS_XORG_XF86
3266/* We need pScrn for setting the pitch correctly */
3267bool
3268SiSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, unsigned short ModeNo, bool dosetpitch)
3269#else
3270bool 3166bool
3271SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo) 3167SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
3272#endif
3273{ 3168{
3274 SISIOADDRESS BaseAddr = SiS_Pr->IOAddress; 3169 SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
3275 unsigned short RealModeNo, ModeIdIndex; 3170 unsigned short RealModeNo, ModeIdIndex;
3276 unsigned char backupreg = 0; 3171 unsigned char backupreg = 0;
3277#ifdef SIS_LINUX_KERNEL
3278 unsigned short KeepLockReg; 3172 unsigned short KeepLockReg;
3279 3173
3280 SiS_Pr->UseCustomMode = false; 3174 SiS_Pr->UseCustomMode = false;
3281 SiS_Pr->CRT1UsesCustomMode = false; 3175 SiS_Pr->CRT1UsesCustomMode = false;
3282#endif
3283 3176
3284 SiS_Pr->SiS_flag_clearbuffer = 0; 3177 SiS_Pr->SiS_flag_clearbuffer = 0;
3285 3178
3286 if(SiS_Pr->UseCustomMode) { 3179 if(SiS_Pr->UseCustomMode) {
3287 ModeNo = 0xfe; 3180 ModeNo = 0xfe;
3288 } else { 3181 } else {
3289#ifdef SIS_LINUX_KERNEL
3290 if(!(ModeNo & 0x80)) SiS_Pr->SiS_flag_clearbuffer = 1; 3182 if(!(ModeNo & 0x80)) SiS_Pr->SiS_flag_clearbuffer = 1;
3291#endif
3292 ModeNo &= 0x7f; 3183 ModeNo &= 0x7f;
3293 } 3184 }
3294 3185
@@ -3301,13 +3192,8 @@ SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
3301 SiS_GetSysFlags(SiS_Pr); 3192 SiS_GetSysFlags(SiS_Pr);
3302 3193
3303 SiS_Pr->SiS_VGAINFO = 0x11; 3194 SiS_Pr->SiS_VGAINFO = 0x11;
3304#if defined(SIS_XORG_XF86) && (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__) || defined(__amd64__) || defined(__x86_64__))
3305 if(pScrn) SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
3306#endif
3307 3195
3308#ifdef SIS_LINUX_KERNEL
3309 KeepLockReg = SiS_GetReg(SiS_Pr->SiS_P3c4,0x05); 3196 KeepLockReg = SiS_GetReg(SiS_Pr->SiS_P3c4,0x05);
3310#endif
3311 SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86); 3197 SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
3312 3198
3313 SiSInitPCIetc(SiS_Pr); 3199 SiSInitPCIetc(SiS_Pr);
@@ -3344,12 +3230,10 @@ SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
3344 SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex); 3230 SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
3345 SiS_SetLowModeTest(SiS_Pr, ModeNo); 3231 SiS_SetLowModeTest(SiS_Pr, ModeNo);
3346 3232
3347#ifdef SIS_LINUX_KERNEL
3348 /* Check memory size (kernel framebuffer driver only) */ 3233 /* Check memory size (kernel framebuffer driver only) */
3349 if(!SiS_CheckMemorySize(SiS_Pr, ModeNo, ModeIdIndex)) { 3234 if(!SiS_CheckMemorySize(SiS_Pr, ModeNo, ModeIdIndex)) {
3350 return false; 3235 return false;
3351 } 3236 }
3352#endif
3353 3237
3354 SiS_OpenCRTC(SiS_Pr); 3238 SiS_OpenCRTC(SiS_Pr);
3355 3239
@@ -3384,7 +3268,7 @@ SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
3384 SiS_DisplayOn(SiS_Pr); 3268 SiS_DisplayOn(SiS_Pr);
3385 SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF); 3269 SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
3386 3270
3387#ifdef SIS315H 3271#ifdef CONFIG_FB_SIS_315
3388 if(SiS_Pr->ChipType >= SIS_315H) { 3272 if(SiS_Pr->ChipType >= SIS_315H) {
3389 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { 3273 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
3390 if(!(SiS_IsDualEdge(SiS_Pr))) { 3274 if(!(SiS_IsDualEdge(SiS_Pr))) {
@@ -3396,7 +3280,7 @@ SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
3396 3280
3397 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { 3281 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
3398 if(SiS_Pr->ChipType >= SIS_315H) { 3282 if(SiS_Pr->ChipType >= SIS_315H) {
3399#ifdef SIS315H 3283#ifdef CONFIG_FB_SIS_315
3400 if(!SiS_Pr->SiS_ROMNew) { 3284 if(!SiS_Pr->SiS_ROMNew) {
3401 if(SiS_IsVAMode(SiS_Pr)) { 3285 if(SiS_IsVAMode(SiS_Pr)) {
3402 SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01); 3286 SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
@@ -3424,424 +3308,16 @@ SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
3424 } 3308 }
3425 } 3309 }
3426 3310
3427#ifdef SIS_XORG_XF86
3428 if(pScrn) {
3429 /* SetPitch: Adapt to virtual size & position */
3430 if((ModeNo > 0x13) && (dosetpitch)) {
3431 SiS_SetPitch(SiS_Pr, pScrn);
3432 }
3433
3434 /* Backup/Set ModeNo in BIOS scratch area */
3435 SiS_GetSetModeID(pScrn, ModeNo);
3436 }
3437#endif
3438
3439 SiS_CloseCRTC(SiS_Pr); 3311 SiS_CloseCRTC(SiS_Pr);
3440 3312
3441 SiS_Handle760(SiS_Pr); 3313 SiS_Handle760(SiS_Pr);
3442 3314
3443#ifdef SIS_LINUX_KERNEL
3444 /* We never lock registers in XF86 */ 3315 /* We never lock registers in XF86 */
3445 if(KeepLockReg != 0xA1) SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x00); 3316 if(KeepLockReg != 0xA1) SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x00);
3446#endif
3447 3317
3448 return true; 3318 return true;
3449} 3319}
3450 3320
3451/*********************************************/
3452/* X.org/XFree86: SiSBIOSSetMode() */
3453/* for non-Dual-Head mode */
3454/*********************************************/
3455
3456#ifdef SIS_XORG_XF86
3457bool
3458SiSBIOSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
3459 DisplayModePtr mode, bool IsCustom)
3460{
3461 SISPtr pSiS = SISPTR(pScrn);
3462 unsigned short ModeNo = 0;
3463
3464 SiS_Pr->UseCustomMode = false;
3465
3466 if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
3467
3468 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting custom mode %dx%d\n",
3469 SiS_Pr->CHDisplay,
3470 (mode->Flags & V_INTERLACE ? SiS_Pr->CVDisplay * 2 :
3471 (mode->Flags & V_DBLSCAN ? SiS_Pr->CVDisplay / 2 :
3472 SiS_Pr->CVDisplay)));
3473
3474 } else {
3475
3476 /* Don't need vbflags here; checks done earlier */
3477 ModeNo = SiS_GetModeNumber(pScrn, mode, pSiS->VBFlags);
3478 if(!ModeNo) return false;
3479
3480 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting standard mode 0x%x\n", ModeNo);
3481
3482 }
3483
3484 return(SiSSetMode(SiS_Pr, pScrn, ModeNo, true));
3485}
3486
3487/*********************************************/
3488/* X.org/XFree86: SiSBIOSSetModeCRT2() */
3489/* for Dual-Head modes */
3490/*********************************************/
3491
3492bool
3493SiSBIOSSetModeCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
3494 DisplayModePtr mode, bool IsCustom)
3495{
3496 SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
3497 SISPtr pSiS = SISPTR(pScrn);
3498#ifdef SISDUALHEAD
3499 SISEntPtr pSiSEnt = pSiS->entityPrivate;
3500#endif
3501 unsigned short ModeIdIndex;
3502 unsigned short ModeNo = 0;
3503 unsigned char backupreg = 0;
3504
3505 SiS_Pr->UseCustomMode = false;
3506
3507 /* Remember: Custom modes for CRT2 are ONLY supported
3508 * -) on the 30x/B/C, and
3509 * -) if CRT2 is LCD or VGA, or CRT1 is LCDA
3510 */
3511
3512 if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
3513
3514 ModeNo = 0xfe;
3515
3516 } else {
3517
3518 ModeNo = SiS_GetModeNumber(pScrn, mode, pSiS->VBFlags);
3519 if(!ModeNo) return false;
3520
3521 }
3522
3523 SiSRegInit(SiS_Pr, BaseAddr);
3524 SiSInitPtr(SiS_Pr);
3525 SiS_GetSysFlags(SiS_Pr);
3526#if defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__) || defined(__amd64__) || defined(__x86_64__)
3527 SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
3528#else
3529 SiS_Pr->SiS_VGAINFO = 0x11;
3530#endif
3531
3532 SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
3533
3534 SiSInitPCIetc(SiS_Pr);
3535 SiSSetLVDSetc(SiS_Pr);
3536 SiSDetermineROMUsage(SiS_Pr);
3537
3538 /* Save mode info so we can set it from within SetMode for CRT1 */
3539#ifdef SISDUALHEAD
3540 if(pSiS->DualHeadMode) {
3541 pSiSEnt->CRT2ModeNo = ModeNo;
3542 pSiSEnt->CRT2DMode = mode;
3543 pSiSEnt->CRT2IsCustom = IsCustom;
3544 pSiSEnt->CRT2CR30 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
3545 pSiSEnt->CRT2CR31 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
3546 pSiSEnt->CRT2CR35 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
3547 pSiSEnt->CRT2CR38 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
3548#if 0
3549 /* We can't set CRT2 mode before CRT1 mode is set - says who...? */
3550 if(pSiSEnt->CRT1ModeNo == -1) {
3551 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
3552 "Setting CRT2 mode delayed until after setting CRT1 mode\n");
3553 return true;
3554 }
3555#endif
3556 pSiSEnt->CRT2ModeSet = true;
3557 }
3558#endif
3559
3560 if(SiS_Pr->UseCustomMode) {
3561
3562 unsigned short temptemp = SiS_Pr->CVDisplay;
3563
3564 if(SiS_Pr->CModeFlag & DoubleScanMode) temptemp >>= 1;
3565 else if(SiS_Pr->CInfoFlag & InterlaceMode) temptemp <<= 1;
3566
3567 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
3568 "Setting custom mode %dx%d on CRT2\n",
3569 SiS_Pr->CHDisplay, temptemp);
3570
3571 } else {
3572
3573 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
3574 "Setting standard mode 0x%x on CRT2\n", ModeNo);
3575
3576 }
3577
3578 SiS_UnLockCRT2(SiS_Pr);
3579
3580 if(!SiS_Pr->UseCustomMode) {
3581 if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return false;
3582 } else {
3583 ModeIdIndex = 0;
3584 }
3585
3586 SiS_GetVBType(SiS_Pr);
3587
3588 SiS_InitVB(SiS_Pr);
3589 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
3590 if(SiS_Pr->ChipType >= SIS_315H) {
3591 SiS_ResetVB(SiS_Pr);
3592 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10);
3593 SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c);
3594 backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
3595 } else {
3596 backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
3597 }
3598 }
3599
3600 /* Get VB information (connectors, connected devices) */
3601 if(!SiS_Pr->UseCustomMode) {
3602 SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, 1);
3603 } else {
3604 /* If this is a custom mode, we don't check the modeflag for CRT2Mode */
3605 SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, 0);
3606 }
3607 SiS_SetYPbPr(SiS_Pr);
3608 SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex);
3609 SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
3610 SiS_SetLowModeTest(SiS_Pr, ModeNo);
3611
3612 SiS_ResetSegmentRegisters(SiS_Pr);
3613
3614 /* Set mode on CRT2 */
3615 if( (SiS_Pr->SiS_VBType & VB_SISVB) ||
3616 (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
3617 (SiS_Pr->SiS_IF_DEF_CH70xx != 0) ||
3618 (SiS_Pr->SiS_IF_DEF_TRUMPION != 0) ) {
3619 SiS_SetCRT2Group(SiS_Pr, ModeNo);
3620 }
3621
3622 SiS_StrangeStuff(SiS_Pr);
3623
3624 SiS_DisplayOn(SiS_Pr);
3625 SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
3626
3627 if(SiS_Pr->ChipType >= SIS_315H) {
3628 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
3629 if(!(SiS_IsDualEdge(SiS_Pr))) {
3630 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
3631 }
3632 }
3633 }
3634
3635 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
3636 if(SiS_Pr->ChipType >= SIS_315H) {
3637 if(!SiS_Pr->SiS_ROMNew) {
3638 if(SiS_IsVAMode(SiS_Pr)) {
3639 SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
3640 } else {
3641 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x35,0xFE);
3642 }
3643 }
3644
3645 SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg);
3646
3647 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) {
3648 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
3649 }
3650 } else if((SiS_Pr->ChipType == SIS_630) ||
3651 (SiS_Pr->ChipType == SIS_730)) {
3652 SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
3653 }
3654 }
3655
3656 /* SetPitch: Adapt to virtual size & position */
3657 SiS_SetPitchCRT2(SiS_Pr, pScrn);
3658
3659 SiS_Handle760(SiS_Pr);
3660
3661 return true;
3662}
3663
3664/*********************************************/
3665/* X.org/XFree86: SiSBIOSSetModeCRT1() */
3666/* for Dual-Head modes */
3667/*********************************************/
3668
3669bool
3670SiSBIOSSetModeCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
3671 DisplayModePtr mode, bool IsCustom)
3672{
3673 SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
3674 SISPtr pSiS = SISPTR(pScrn);
3675 unsigned short ModeIdIndex, ModeNo = 0;
3676 unsigned char backupreg = 0;
3677#ifdef SISDUALHEAD
3678 SISEntPtr pSiSEnt = pSiS->entityPrivate;
3679 unsigned char backupcr30, backupcr31, backupcr38, backupcr35, backupp40d=0;
3680 bool backupcustom;
3681#endif
3682
3683 SiS_Pr->UseCustomMode = false;
3684
3685 if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
3686
3687 unsigned short temptemp = SiS_Pr->CVDisplay;
3688
3689 if(SiS_Pr->CModeFlag & DoubleScanMode) temptemp >>= 1;
3690 else if(SiS_Pr->CInfoFlag & InterlaceMode) temptemp <<= 1;
3691
3692 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
3693 "Setting custom mode %dx%d on CRT1\n",
3694 SiS_Pr->CHDisplay, temptemp);
3695 ModeNo = 0xfe;
3696
3697 } else {
3698
3699 ModeNo = SiS_GetModeNumber(pScrn, mode, 0); /* don't give VBFlags */
3700 if(!ModeNo) return false;
3701
3702 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
3703 "Setting standard mode 0x%x on CRT1\n", ModeNo);
3704 }
3705
3706 SiSInitPtr(SiS_Pr);
3707 SiSRegInit(SiS_Pr, BaseAddr);
3708 SiS_GetSysFlags(SiS_Pr);
3709#if defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__) || defined(__amd64__) || defined(__x86_64__)
3710 SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
3711#else
3712 SiS_Pr->SiS_VGAINFO = 0x11;
3713#endif
3714
3715 SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
3716
3717 SiSInitPCIetc(SiS_Pr);
3718 SiSSetLVDSetc(SiS_Pr);
3719 SiSDetermineROMUsage(SiS_Pr);
3720
3721 SiS_UnLockCRT2(SiS_Pr);
3722
3723 if(!SiS_Pr->UseCustomMode) {
3724 if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return false;
3725 } else {
3726 ModeIdIndex = 0;
3727 }
3728
3729 /* Determine VBType */
3730 SiS_GetVBType(SiS_Pr);
3731
3732 SiS_InitVB(SiS_Pr);
3733 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
3734 if(SiS_Pr->ChipType >= SIS_315H) {
3735 backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
3736 } else {
3737 backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
3738 }
3739 }
3740
3741 /* Get VB information (connectors, connected devices) */
3742 /* (We don't care if the current mode is a CRT2 mode) */
3743 SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, 0);
3744 SiS_SetYPbPr(SiS_Pr);
3745 SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex);
3746 SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
3747 SiS_SetLowModeTest(SiS_Pr, ModeNo);
3748
3749 SiS_OpenCRTC(SiS_Pr);
3750
3751 /* Set mode on CRT1 */
3752 SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);
3753 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
3754 SiS_SetCRT2Group(SiS_Pr, ModeNo);
3755 }
3756
3757 /* SetPitch: Adapt to virtual size & position */
3758 SiS_SetPitchCRT1(SiS_Pr, pScrn);
3759
3760 SiS_HandleCRT1(SiS_Pr);
3761
3762 SiS_StrangeStuff(SiS_Pr);
3763
3764 SiS_CloseCRTC(SiS_Pr);
3765
3766#ifdef SISDUALHEAD
3767 if(pSiS->DualHeadMode) {
3768 pSiSEnt->CRT1ModeNo = ModeNo;
3769 pSiSEnt->CRT1DMode = mode;
3770 }
3771#endif
3772
3773 if(SiS_Pr->UseCustomMode) {
3774 SiS_Pr->CRT1UsesCustomMode = true;
3775 SiS_Pr->CSRClock_CRT1 = SiS_Pr->CSRClock;
3776 SiS_Pr->CModeFlag_CRT1 = SiS_Pr->CModeFlag;
3777 } else {
3778 SiS_Pr->CRT1UsesCustomMode = false;
3779 }
3780
3781 /* Reset CRT2 if changing mode on CRT1 */
3782#ifdef SISDUALHEAD
3783 if(pSiS->DualHeadMode) {
3784 if(pSiSEnt->CRT2ModeNo != -1) {
3785 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
3786 "(Re-)Setting mode for CRT2\n");
3787 backupcustom = SiS_Pr->UseCustomMode;
3788 backupcr30 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
3789 backupcr31 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
3790 backupcr35 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
3791 backupcr38 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
3792 if(SiS_Pr->SiS_VBType & VB_SISVB) {
3793 /* Backup LUT-enable */
3794 if(pSiSEnt->CRT2ModeSet) {
3795 backupp40d = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x0d) & 0x08;
3796 }
3797 }
3798 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
3799 SiS_SetReg(SiS_Pr->SiS_P3d4,0x30,pSiSEnt->CRT2CR30);
3800 SiS_SetReg(SiS_Pr->SiS_P3d4,0x31,pSiSEnt->CRT2CR31);
3801 SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,pSiSEnt->CRT2CR35);
3802 SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,pSiSEnt->CRT2CR38);
3803 }
3804
3805 SiSBIOSSetModeCRT2(SiS_Pr, pSiSEnt->pScrn_1,
3806 pSiSEnt->CRT2DMode, pSiSEnt->CRT2IsCustom);
3807
3808 SiS_SetReg(SiS_Pr->SiS_P3d4,0x30,backupcr30);
3809 SiS_SetReg(SiS_Pr->SiS_P3d4,0x31,backupcr31);
3810 SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupcr35);
3811 SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupcr38);
3812 if(SiS_Pr->SiS_VBType & VB_SISVB) {
3813 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d, ~0x08, backupp40d);
3814 }
3815 SiS_Pr->UseCustomMode = backupcustom;
3816 }
3817 }
3818#endif
3819
3820 /* Warning: From here, the custom mode entries in SiS_Pr are
3821 * possibly overwritten
3822 */
3823
3824 SiS_DisplayOn(SiS_Pr);
3825 SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
3826
3827 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
3828 if(SiS_Pr->ChipType >= SIS_315H) {
3829 SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg);
3830 } else if((SiS_Pr->ChipType == SIS_630) ||
3831 (SiS_Pr->ChipType == SIS_730)) {
3832 SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
3833 }
3834 }
3835
3836 SiS_Handle760(SiS_Pr);
3837
3838 /* Backup/Set ModeNo in BIOS scratch area */
3839 SiS_GetSetModeID(pScrn,ModeNo);
3840
3841 return true;
3842}
3843#endif /* Linux_XF86 */
3844
3845#ifndef GETBITSTR 3321#ifndef GETBITSTR
3846#define BITMASK(h,l) (((unsigned)(1U << ((h)-(l)+1))-1)<<(l)) 3322#define BITMASK(h,l) (((unsigned)(1U << ((h)-(l)+1))-1)<<(l))
3847#define GENMASK(mask) BITMASK(1?mask,0?mask) 3323#define GENMASK(mask) BITMASK(1?mask,0?mask)
@@ -3927,7 +3403,7 @@ SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
3927 SiS_Pr->CVBlankStart = SiS_Pr->SiS_VGAVDE; 3403 SiS_Pr->CVBlankStart = SiS_Pr->SiS_VGAVDE;
3928 3404
3929 if(SiS_Pr->ChipType < SIS_315H) { 3405 if(SiS_Pr->ChipType < SIS_315H) {
3930#ifdef SIS300 3406#ifdef CONFIG_FB_SIS_300
3931 tempbx = SiS_Pr->SiS_VGAHT; 3407 tempbx = SiS_Pr->SiS_VGAHT;
3932 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) { 3408 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3933 tempbx = SiS_Pr->PanelHT; 3409 tempbx = SiS_Pr->PanelHT;
@@ -3936,7 +3412,7 @@ SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
3936 remaining = tempbx % 8; 3412 remaining = tempbx % 8;
3937#endif 3413#endif
3938 } else { 3414 } else {
3939#ifdef SIS315H 3415#ifdef CONFIG_FB_SIS_315
3940 /* OK for LCDA, LVDS */ 3416 /* OK for LCDA, LVDS */
3941 tempbx = SiS_Pr->PanelHT - SiS_Pr->PanelXRes; 3417 tempbx = SiS_Pr->PanelHT - SiS_Pr->PanelXRes;
3942 tempax = SiS_Pr->SiS_VGAHDE; /* not /2 ! */ 3418 tempax = SiS_Pr->SiS_VGAHDE; /* not /2 ! */
@@ -3950,7 +3426,7 @@ SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
3950 SiS_Pr->CHTotal = SiS_Pr->CHBlankEnd = tempbx; 3426 SiS_Pr->CHTotal = SiS_Pr->CHBlankEnd = tempbx;
3951 3427
3952 if(SiS_Pr->ChipType < SIS_315H) { 3428 if(SiS_Pr->ChipType < SIS_315H) {
3953#ifdef SIS300 3429#ifdef CONFIG_FB_SIS_300
3954 if(SiS_Pr->SiS_VGAHDE == SiS_Pr->PanelXRes) { 3430 if(SiS_Pr->SiS_VGAHDE == SiS_Pr->PanelXRes) {
3955 SiS_Pr->CHSyncStart = SiS_Pr->SiS_VGAHDE + ((SiS_Pr->PanelHRS + 1) & ~1); 3431 SiS_Pr->CHSyncStart = SiS_Pr->SiS_VGAHDE + ((SiS_Pr->PanelHRS + 1) & ~1);
3956 SiS_Pr->CHSyncEnd = SiS_Pr->CHSyncStart + SiS_Pr->PanelHRE; 3432 SiS_Pr->CHSyncEnd = SiS_Pr->CHSyncStart + SiS_Pr->PanelHRE;
@@ -3982,7 +3458,7 @@ SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
3982 } 3458 }
3983#endif 3459#endif
3984 } else { 3460 } else {
3985#ifdef SIS315H 3461#ifdef CONFIG_FB_SIS_315
3986 tempax = VGAHDE; 3462 tempax = VGAHDE;
3987 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) { 3463 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3988 tempbx = SiS_Pr->PanelXRes; 3464 tempbx = SiS_Pr->PanelXRes;
@@ -4001,7 +3477,7 @@ SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
4001 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) { 3477 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
4002 tempax = SiS_Pr->PanelYRes; 3478 tempax = SiS_Pr->PanelYRes;
4003 } else if(SiS_Pr->ChipType < SIS_315H) { 3479 } else if(SiS_Pr->ChipType < SIS_315H) {
4004#ifdef SIS300 3480#ifdef CONFIG_FB_SIS_300
4005 /* Stupid hack for 640x400/320x200 */ 3481 /* Stupid hack for 640x400/320x200 */
4006 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) { 3482 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
4007 if((tempax + tempbx) == 438) tempbx += 16; 3483 if((tempax + tempbx) == 438) tempbx += 16;
@@ -4054,36 +3530,12 @@ SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
4054 if(modeflag & DoubleScanMode) tempax |= 0x80; 3530 if(modeflag & DoubleScanMode) tempax |= 0x80;
4055 SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,tempax); 3531 SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,tempax);
4056 3532
4057#ifdef SIS_XORG_XF86
4058#ifdef TWDEBUG
4059 xf86DrvMsg(0, X_INFO, "%d %d %d %d %d %d %d %d (%d %d %d %d)\n",
4060 SiS_Pr->CHDisplay, SiS_Pr->CHSyncStart, SiS_Pr->CHSyncEnd, SiS_Pr->CHTotal,
4061 SiS_Pr->CVDisplay, SiS_Pr->CVSyncStart, SiS_Pr->CVSyncEnd, SiS_Pr->CVTotal,
4062 SiS_Pr->CHBlankStart, SiS_Pr->CHBlankEnd, SiS_Pr->CVBlankStart, SiS_Pr->CVBlankEnd);
4063 xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
4064 SiS_Pr->CCRT1CRTC[0], SiS_Pr->CCRT1CRTC[1],
4065 SiS_Pr->CCRT1CRTC[2], SiS_Pr->CCRT1CRTC[3],
4066 SiS_Pr->CCRT1CRTC[4], SiS_Pr->CCRT1CRTC[5],
4067 SiS_Pr->CCRT1CRTC[6], SiS_Pr->CCRT1CRTC[7]);
4068 xf86DrvMsg(0, X_INFO, " 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
4069 SiS_Pr->CCRT1CRTC[8], SiS_Pr->CCRT1CRTC[9],
4070 SiS_Pr->CCRT1CRTC[10], SiS_Pr->CCRT1CRTC[11],
4071 SiS_Pr->CCRT1CRTC[12], SiS_Pr->CCRT1CRTC[13],
4072 SiS_Pr->CCRT1CRTC[14], SiS_Pr->CCRT1CRTC[15]);
4073 xf86DrvMsg(0, X_INFO, " 0x%02x}},\n", SiS_Pr->CCRT1CRTC[16]);
4074#endif
4075#endif
4076} 3533}
4077 3534
4078void 3535void
4079SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata, 3536SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
4080 int xres, int yres, 3537 int xres, int yres,
4081#ifdef SIS_XORG_XF86
4082 DisplayModePtr current
4083#endif
4084#ifdef SIS_LINUX_KERNEL
4085 struct fb_var_screeninfo *var, bool writeres 3538 struct fb_var_screeninfo *var, bool writeres
4086#endif
4087) 3539)
4088{ 3540{
4089 unsigned short HRE, HBE, HRS, HBS, HDE, HT; 3541 unsigned short HRE, HBE, HRS, HBS, HDE, HT;
@@ -4127,25 +3579,10 @@ SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
4127 3579
4128 D = B - F - C; 3580 D = B - F - C;
4129 3581
4130#ifdef SIS_XORG_XF86
4131 current->HDisplay = (E * 8);
4132 current->HSyncStart = (E * 8) + (F * 8);
4133 current->HSyncEnd = (E * 8) + (F * 8) + (C * 8);
4134 current->HTotal = (E * 8) + (F * 8) + (C * 8) + (D * 8);
4135#ifdef TWDEBUG
4136 xf86DrvMsg(0, X_INFO,
4137 "H: A %d B %d C %d D %d E %d F %d HT %d HDE %d HRS %d HBS %d HBE %d HRE %d\n",
4138 A, B, C, D, E, F, HT, HDE, HRS, HBS, HBE, HRE);
4139#else
4140 (void)VBS; (void)HBS; (void)A;
4141#endif
4142#endif
4143#ifdef SIS_LINUX_KERNEL
4144 if(writeres) var->xres = xres = E * 8; 3582 if(writeres) var->xres = xres = E * 8;
4145 var->left_margin = D * 8; 3583 var->left_margin = D * 8;
4146 var->right_margin = F * 8; 3584 var->right_margin = F * 8;
4147 var->hsync_len = C * 8; 3585 var->hsync_len = C * 8;
4148#endif
4149 3586
4150 /* Vertical */ 3587 /* Vertical */
4151 sr_data = crdata[13]; 3588 sr_data = crdata[13];
@@ -4192,30 +3629,10 @@ SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
4192 3629
4193 D = B - F - C; 3630 D = B - F - C;
4194 3631
4195#ifdef SIS_XORG_XF86
4196 current->VDisplay = VDE + 1;
4197 current->VSyncStart = VRS + 1;
4198 current->VSyncEnd = ((VRS & ~0x1f) | VRE) + 1;
4199 if(VRE <= (VRS & 0x1f)) current->VSyncEnd += 32;
4200 current->VTotal = E + D + C + F;
4201#if 0
4202 current->VDisplay = E;
4203 current->VSyncStart = E + D;
4204 current->VSyncEnd = E + D + C;
4205 current->VTotal = E + D + C + F;
4206#endif
4207#ifdef TWDEBUG
4208 xf86DrvMsg(0, X_INFO,
4209 "V: A %d B %d C %d D %d E %d F %d VT %d VDE %d VRS %d VBS %d VBE %d VRE %d\n",
4210 A, B, C, D, E, F, VT, VDE, VRS, VBS, VBE, VRE);
4211#endif
4212#endif
4213#ifdef SIS_LINUX_KERNEL
4214 if(writeres) var->yres = yres = E; 3632 if(writeres) var->yres = yres = E;
4215 var->upper_margin = D; 3633 var->upper_margin = D;
4216 var->lower_margin = F; 3634 var->lower_margin = F;
4217 var->vsync_len = C; 3635 var->vsync_len = C;
4218#endif
4219 3636
4220 if((xres == 320) && ((yres == 200) || (yres == 240))) { 3637 if((xres == 320) && ((yres == 200) || (yres == 240))) {
4221 /* Terrible hack, but correct CRTC data for 3638 /* Terrible hack, but correct CRTC data for
@@ -4224,17 +3641,9 @@ SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
4224 * a negative D. The CRT controller does not 3641 * a negative D. The CRT controller does not
4225 * seem to like correcting HRE to 50) 3642 * seem to like correcting HRE to 50)
4226 */ 3643 */
4227#ifdef SIS_XORG_XF86
4228 current->HDisplay = 320;
4229 current->HSyncStart = 328;
4230 current->HSyncEnd = 376;
4231 current->HTotal = 400;
4232#endif
4233#ifdef SIS_LINUX_KERNEL
4234 var->left_margin = (400 - 376); 3644 var->left_margin = (400 - 376);
4235 var->right_margin = (328 - 320); 3645 var->right_margin = (328 - 320);
4236 var->hsync_len = (376 - 328); 3646 var->hsync_len = (376 - 328);
4237#endif
4238 3647
4239 } 3648 }
4240 3649
diff --git a/drivers/video/sis/init.h b/drivers/video/sis/init.h
index b96005c39c67..aff73842d877 100644
--- a/drivers/video/sis/init.h
+++ b/drivers/video/sis/init.h
@@ -53,21 +53,8 @@
53#ifndef _INIT_H_ 53#ifndef _INIT_H_
54#define _INIT_H_ 54#define _INIT_H_
55 55
56#include "osdef.h"
57#include "initdef.h" 56#include "initdef.h"
58 57
59#ifdef SIS_XORG_XF86
60#include "sis.h"
61#define SIS_NEED_inSISREG
62#define SIS_NEED_inSISREGW
63#define SIS_NEED_inSISREGL
64#define SIS_NEED_outSISREG
65#define SIS_NEED_outSISREGW
66#define SIS_NEED_outSISREGL
67#include "sis_regs.h"
68#endif
69
70#ifdef SIS_LINUX_KERNEL
71#include "vgatypes.h" 58#include "vgatypes.h"
72#include "vstruct.h" 59#include "vstruct.h"
73#ifdef SIS_CP 60#ifdef SIS_CP
@@ -78,7 +65,6 @@
78#include <linux/fb.h> 65#include <linux/fb.h>
79#include "sis.h" 66#include "sis.h"
80#include <video/sisfb.h> 67#include <video/sisfb.h>
81#endif
82 68
83/* Mode numbers */ 69/* Mode numbers */
84static const unsigned short ModeIndex_320x200[] = {0x59, 0x41, 0x00, 0x4f}; 70static const unsigned short ModeIndex_320x200[] = {0x59, 0x41, 0x00, 0x4f};
@@ -286,7 +272,7 @@ static const struct SiS_ModeResInfo_S SiS_ModeResInfo[] =
286 { 1280, 854, 8,16} /* 0x22 */ 272 { 1280, 854, 8,16} /* 0x22 */
287}; 273};
288 274
289#if defined(SIS300) || defined(SIS315H) 275#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
290static const struct SiS_StandTable_S SiS_StandTable[]= 276static const struct SiS_StandTable_S SiS_StandTable[]=
291{ 277{
292/* 0x00: MD_0_200 */ 278/* 0x00: MD_0_200 */
@@ -1521,10 +1507,6 @@ static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1640x480_1_H[] =
1521}; 1507};
1522 1508
1523bool SiSInitPtr(struct SiS_Private *SiS_Pr); 1509bool SiSInitPtr(struct SiS_Private *SiS_Pr);
1524#ifdef SIS_XORG_XF86
1525unsigned short SiS_GetModeID(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
1526 int Depth, bool FSTN, int LCDwith, int LCDheight);
1527#endif
1528unsigned short SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay, 1510unsigned short SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay,
1529 int VDisplay, int Depth, bool FSTN, 1511 int VDisplay, int Depth, bool FSTN,
1530 unsigned short CustomT, int LCDwith, int LCDheight, 1512 unsigned short CustomT, int LCDwith, int LCDheight,
@@ -1534,33 +1516,14 @@ unsigned short SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDispla
1534unsigned short SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay, 1516unsigned short SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay,
1535 int VDisplay, int Depth, unsigned int VBFlags2); 1517 int VDisplay, int Depth, unsigned int VBFlags2);
1536 1518
1537void SiS_SetReg(SISIOADDRESS port, unsigned short index, unsigned short data);
1538void SiS_SetRegByte(SISIOADDRESS port, unsigned short data);
1539void SiS_SetRegShort(SISIOADDRESS port, unsigned short data);
1540void SiS_SetRegLong(SISIOADDRESS port, unsigned int data);
1541unsigned char SiS_GetReg(SISIOADDRESS port, unsigned short index);
1542unsigned char SiS_GetRegByte(SISIOADDRESS port);
1543unsigned short SiS_GetRegShort(SISIOADDRESS port);
1544unsigned int SiS_GetRegLong(SISIOADDRESS port);
1545void SiS_SetRegANDOR(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND,
1546 unsigned short DataOR);
1547void SiS_SetRegAND(SISIOADDRESS Port,unsigned short Index, unsigned short DataAND);
1548void SiS_SetRegOR(SISIOADDRESS Port,unsigned short Index, unsigned short DataOR);
1549
1550void SiS_DisplayOn(struct SiS_Private *SiS_Pr); 1519void SiS_DisplayOn(struct SiS_Private *SiS_Pr);
1551void SiS_DisplayOff(struct SiS_Private *SiS_Pr); 1520void SiS_DisplayOff(struct SiS_Private *SiS_Pr);
1552void SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr); 1521void SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
1553#ifndef SIS_LINUX_KERNEL
1554void SiSSetLVDSetc(struct SiS_Private *SiS_Pr);
1555#endif
1556void SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable); 1522void SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable);
1557void SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable); 1523void SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable);
1558unsigned short SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo, 1524unsigned short SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
1559 unsigned short ModeIdIndex); 1525 unsigned short ModeIdIndex);
1560bool SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr); 1526bool SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr);
1561#ifndef SIS_LINUX_KERNEL
1562void SiS_GetVBType(struct SiS_Private *SiS_Pr);
1563#endif
1564 1527
1565bool SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo, 1528bool SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
1566 unsigned short *ModeIdIndex); 1529 unsigned short *ModeIdIndex);
@@ -1572,37 +1535,19 @@ unsigned short SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short Mode
1572 unsigned short ModeIdIndex); 1535 unsigned short ModeIdIndex);
1573unsigned short SiS_GetOffset(struct SiS_Private *SiS_Pr,unsigned short ModeNo, 1536unsigned short SiS_GetOffset(struct SiS_Private *SiS_Pr,unsigned short ModeNo,
1574 unsigned short ModeIdIndex, unsigned short RRTI); 1537 unsigned short ModeIdIndex, unsigned short RRTI);
1575#ifdef SIS300 1538#ifdef CONFIG_FB_SIS_300
1576void SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *idx1, 1539void SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *idx1,
1577 unsigned short *idx2); 1540 unsigned short *idx2);
1578unsigned short SiS_GetFIFOThresholdB300(unsigned short idx1, unsigned short idx2); 1541unsigned short SiS_GetFIFOThresholdB300(unsigned short idx1, unsigned short idx2);
1579unsigned short SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index); 1542unsigned short SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index);
1580#endif 1543#endif
1581void SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex); 1544void SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
1582#ifdef SIS_XORG_XF86
1583bool SiSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, unsigned short ModeNo,
1584 bool dosetpitch);
1585bool SiSBIOSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
1586 DisplayModePtr mode, bool IsCustom);
1587bool SiSBIOSSetModeCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
1588 DisplayModePtr mode, bool IsCustom);
1589bool SiSBIOSSetModeCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
1590 DisplayModePtr mode, bool IsCustom);
1591#endif
1592#ifdef SIS_LINUX_KERNEL
1593bool SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo); 1545bool SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
1594#endif
1595void SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth); 1546void SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth);
1596void SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo, 1547void SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
1597 unsigned short ModeIdIndex); 1548 unsigned short ModeIdIndex);
1598#ifdef SIS_XORG_XF86
1599void SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata, int xres,
1600 int yres, DisplayModePtr current);
1601#endif
1602#ifdef SIS_LINUX_KERNEL
1603void SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata, int xres, 1549void SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata, int xres,
1604 int yres, struct fb_var_screeninfo *var, bool writeres); 1550 int yres, struct fb_var_screeninfo *var, bool writeres);
1605#endif
1606 1551
1607/* From init301.c: */ 1552/* From init301.c: */
1608extern void SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, 1553extern void SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
@@ -1626,29 +1571,16 @@ extern unsigned short SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short
1626extern bool SiS_IsVAMode(struct SiS_Private *); 1571extern bool SiS_IsVAMode(struct SiS_Private *);
1627extern bool SiS_IsDualEdge(struct SiS_Private *); 1572extern bool SiS_IsDualEdge(struct SiS_Private *);
1628 1573
1629#ifdef SIS_XORG_XF86 1574#ifdef CONFIG_FB_SIS_300
1630/* From other modules: */
1631extern unsigned short SiS_CheckBuildCustomMode(ScrnInfoPtr pScrn, DisplayModePtr mode,
1632 unsigned int VBFlags);
1633extern unsigned char SiS_GetSetBIOSScratch(ScrnInfoPtr pScrn, unsigned short offset,
1634 unsigned char value);
1635extern unsigned char SiS_GetSetModeID(ScrnInfoPtr pScrn, unsigned char id);
1636extern unsigned short SiS_GetModeNumber(ScrnInfoPtr pScrn, DisplayModePtr mode,
1637 unsigned int VBFlags);
1638#endif
1639
1640#ifdef SIS_LINUX_KERNEL
1641#ifdef SIS300
1642extern unsigned int sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg); 1575extern unsigned int sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg);
1643extern void sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, 1576extern void sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg,
1644 unsigned int val); 1577 unsigned int val);
1645#endif 1578#endif
1646#ifdef SIS315H 1579#ifdef CONFIG_FB_SIS_315
1647extern void sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, 1580extern void sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg,
1648 unsigned char val); 1581 unsigned char val);
1649extern unsigned int sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg); 1582extern unsigned int sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg);
1650#endif 1583#endif
1651#endif
1652 1584
1653#endif 1585#endif
1654 1586
diff --git a/drivers/video/sis/init301.c b/drivers/video/sis/init301.c
index da33d801c22e..a89e3cafd5ad 100644
--- a/drivers/video/sis/init301.c
+++ b/drivers/video/sis/init301.c
@@ -57,10 +57,6 @@
57 * 57 *
58 */ 58 */
59 59
60#ifdef HAVE_CONFIG_H
61#include "config.h"
62#endif
63
64#if 1 60#if 1
65#define SET_EMI /* 302LV/ELV: Set EMI values */ 61#define SET_EMI /* 302LV/ELV: Set EMI values */
66#endif 62#endif
@@ -75,11 +71,11 @@
75 71
76#include "init301.h" 72#include "init301.h"
77 73
78#ifdef SIS300 74#ifdef CONFIG_FB_SIS_300
79#include "oem300.h" 75#include "oem300.h"
80#endif 76#endif
81 77
82#ifdef SIS315H 78#ifdef CONFIG_FB_SIS_315
83#include "oem310.h" 79#include "oem310.h"
84#endif 80#endif
85 81
@@ -87,9 +83,7 @@
87#define SiS_I2CDELAYSHORT 150 83#define SiS_I2CDELAYSHORT 150
88 84
89static unsigned short SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr); 85static unsigned short SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr);
90#ifdef SIS_LINUX_KERNEL
91static void SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val); 86static void SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
92#endif
93 87
94/*********************************************/ 88/*********************************************/
95/* HELPER: Lock/Unlock CRT2 */ 89/* HELPER: Lock/Unlock CRT2 */
@@ -106,9 +100,7 @@ SiS_UnLockCRT2(struct SiS_Private *SiS_Pr)
106 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01); 100 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01);
107} 101}
108 102
109#ifdef SIS_LINUX_KERNEL
110static 103static
111#endif
112void 104void
113SiS_LockCRT2(struct SiS_Private *SiS_Pr) 105SiS_LockCRT2(struct SiS_Private *SiS_Pr)
114{ 106{
@@ -138,7 +130,7 @@ SiS_SetRegSR11ANDOR(struct SiS_Private *SiS_Pr, unsigned short DataAND, unsigned
138/* HELPER: Get Pointer to LCD structure */ 130/* HELPER: Get Pointer to LCD structure */
139/*********************************************/ 131/*********************************************/
140 132
141#ifdef SIS315H 133#ifdef CONFIG_FB_SIS_315
142static unsigned char * 134static unsigned char *
143GetLCDStructPtr661(struct SiS_Private *SiS_Pr) 135GetLCDStructPtr661(struct SiS_Private *SiS_Pr)
144{ 136{
@@ -404,7 +396,7 @@ SiS_SaveCRT2Info(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
404/* HELPER: GET SOME DATA FROM BIOS ROM */ 396/* HELPER: GET SOME DATA FROM BIOS ROM */
405/*********************************************/ 397/*********************************************/
406 398
407#ifdef SIS300 399#ifdef CONFIG_FB_SIS_300
408static bool 400static bool
409SiS_CR36BIOSWord23b(struct SiS_Private *SiS_Pr) 401SiS_CR36BIOSWord23b(struct SiS_Private *SiS_Pr)
410{ 402{
@@ -449,7 +441,7 @@ SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime)
449 SiS_GetReg(SiS_Pr->SiS_P3c4, 0x05); 441 SiS_GetReg(SiS_Pr->SiS_P3c4, 0x05);
450} 442}
451 443
452#if defined(SIS300) || defined(SIS315H) 444#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
453static void 445static void
454SiS_GenericDelay(struct SiS_Private *SiS_Pr, unsigned short delay) 446SiS_GenericDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
455{ 447{
@@ -457,7 +449,7 @@ SiS_GenericDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
457} 449}
458#endif 450#endif
459 451
460#ifdef SIS315H 452#ifdef CONFIG_FB_SIS_315
461static void 453static void
462SiS_LongDelay(struct SiS_Private *SiS_Pr, unsigned short delay) 454SiS_LongDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
463{ 455{
@@ -467,7 +459,7 @@ SiS_LongDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
467} 459}
468#endif 460#endif
469 461
470#if defined(SIS300) || defined(SIS315H) 462#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
471static void 463static void
472SiS_ShortDelay(struct SiS_Private *SiS_Pr, unsigned short delay) 464SiS_ShortDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
473{ 465{
@@ -480,14 +472,14 @@ SiS_ShortDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
480static void 472static void
481SiS_PanelDelay(struct SiS_Private *SiS_Pr, unsigned short DelayTime) 473SiS_PanelDelay(struct SiS_Private *SiS_Pr, unsigned short DelayTime)
482{ 474{
483#if defined(SIS300) || defined(SIS315H) 475#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
484 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase; 476 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
485 unsigned short PanelID, DelayIndex, Delay=0; 477 unsigned short PanelID, DelayIndex, Delay=0;
486#endif 478#endif
487 479
488 if(SiS_Pr->ChipType < SIS_315H) { 480 if(SiS_Pr->ChipType < SIS_315H) {
489 481
490#ifdef SIS300 482#ifdef CONFIG_FB_SIS_300
491 483
492 PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36); 484 PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
493 if(SiS_Pr->SiS_VBType & VB_SISVB) { 485 if(SiS_Pr->SiS_VBType & VB_SISVB) {
@@ -513,11 +505,11 @@ SiS_PanelDelay(struct SiS_Private *SiS_Pr, unsigned short DelayTime)
513 } 505 }
514 SiS_ShortDelay(SiS_Pr, Delay); 506 SiS_ShortDelay(SiS_Pr, Delay);
515 507
516#endif /* SIS300 */ 508#endif /* CONFIG_FB_SIS_300 */
517 509
518 } else { 510 } else {
519 511
520#ifdef SIS315H 512#ifdef CONFIG_FB_SIS_315
521 513
522 if((SiS_Pr->ChipType >= SIS_661) || 514 if((SiS_Pr->ChipType >= SIS_661) ||
523 (SiS_Pr->ChipType <= SIS_315PRO) || 515 (SiS_Pr->ChipType <= SIS_315PRO) ||
@@ -579,12 +571,12 @@ SiS_PanelDelay(struct SiS_Private *SiS_Pr, unsigned short DelayTime)
579 571
580 } 572 }
581 573
582#endif /* SIS315H */ 574#endif /* CONFIG_FB_SIS_315 */
583 575
584 } 576 }
585} 577}
586 578
587#ifdef SIS315H 579#ifdef CONFIG_FB_SIS_315
588static void 580static void
589SiS_PanelDelayLoop(struct SiS_Private *SiS_Pr, unsigned short DelayTime, unsigned short DelayLoop) 581SiS_PanelDelayLoop(struct SiS_Private *SiS_Pr, unsigned short DelayTime, unsigned short DelayLoop)
590{ 582{
@@ -613,7 +605,7 @@ SiS_WaitRetrace1(struct SiS_Private *SiS_Pr)
613 while((!(SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08)) && --watchdog); 605 while((!(SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08)) && --watchdog);
614} 606}
615 607
616#if defined(SIS300) || defined(SIS315H) 608#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
617static void 609static void
618SiS_WaitRetrace2(struct SiS_Private *SiS_Pr, unsigned short reg) 610SiS_WaitRetrace2(struct SiS_Private *SiS_Pr, unsigned short reg)
619{ 611{
@@ -630,7 +622,7 @@ static void
630SiS_WaitVBRetrace(struct SiS_Private *SiS_Pr) 622SiS_WaitVBRetrace(struct SiS_Private *SiS_Pr)
631{ 623{
632 if(SiS_Pr->ChipType < SIS_315H) { 624 if(SiS_Pr->ChipType < SIS_315H) {
633#ifdef SIS300 625#ifdef CONFIG_FB_SIS_300
634 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { 626 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
635 if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x20)) return; 627 if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x20)) return;
636 } 628 }
@@ -641,7 +633,7 @@ SiS_WaitVBRetrace(struct SiS_Private *SiS_Pr)
641 } 633 }
642#endif 634#endif
643 } else { 635 } else {
644#ifdef SIS315H 636#ifdef CONFIG_FB_SIS_315
645 if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x40)) { 637 if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x40)) {
646 SiS_WaitRetrace1(SiS_Pr); 638 SiS_WaitRetrace1(SiS_Pr);
647 } else { 639 } else {
@@ -686,7 +678,7 @@ SiS_VBLongWait(struct SiS_Private *SiS_Pr)
686/* HELPER: MISC */ 678/* HELPER: MISC */
687/*********************************************/ 679/*********************************************/
688 680
689#ifdef SIS300 681#ifdef CONFIG_FB_SIS_300
690static bool 682static bool
691SiS_Is301B(struct SiS_Private *SiS_Pr) 683SiS_Is301B(struct SiS_Private *SiS_Pr)
692{ 684{
@@ -708,7 +700,7 @@ SiS_CRT2IsLCD(struct SiS_Private *SiS_Pr)
708bool 700bool
709SiS_IsDualEdge(struct SiS_Private *SiS_Pr) 701SiS_IsDualEdge(struct SiS_Private *SiS_Pr)
710{ 702{
711#ifdef SIS315H 703#ifdef CONFIG_FB_SIS_315
712 if(SiS_Pr->ChipType >= SIS_315H) { 704 if(SiS_Pr->ChipType >= SIS_315H) {
713 if((SiS_Pr->ChipType != SIS_650) || (SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0)) { 705 if((SiS_Pr->ChipType != SIS_650) || (SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0)) {
714 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableDualEdge) return true; 706 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableDualEdge) return true;
@@ -721,7 +713,7 @@ SiS_IsDualEdge(struct SiS_Private *SiS_Pr)
721bool 713bool
722SiS_IsVAMode(struct SiS_Private *SiS_Pr) 714SiS_IsVAMode(struct SiS_Private *SiS_Pr)
723{ 715{
724#ifdef SIS315H 716#ifdef CONFIG_FB_SIS_315
725 unsigned short flag; 717 unsigned short flag;
726 718
727 if(SiS_Pr->ChipType >= SIS_315H) { 719 if(SiS_Pr->ChipType >= SIS_315H) {
@@ -732,7 +724,7 @@ SiS_IsVAMode(struct SiS_Private *SiS_Pr)
732 return false; 724 return false;
733} 725}
734 726
735#ifdef SIS315H 727#ifdef CONFIG_FB_SIS_315
736static bool 728static bool
737SiS_IsVAorLCD(struct SiS_Private *SiS_Pr) 729SiS_IsVAorLCD(struct SiS_Private *SiS_Pr)
738{ 730{
@@ -745,7 +737,7 @@ SiS_IsVAorLCD(struct SiS_Private *SiS_Pr)
745static bool 737static bool
746SiS_IsDualLink(struct SiS_Private *SiS_Pr) 738SiS_IsDualLink(struct SiS_Private *SiS_Pr)
747{ 739{
748#ifdef SIS315H 740#ifdef CONFIG_FB_SIS_315
749 if(SiS_Pr->ChipType >= SIS_315H) { 741 if(SiS_Pr->ChipType >= SIS_315H) {
750 if((SiS_CRT2IsLCD(SiS_Pr)) || 742 if((SiS_CRT2IsLCD(SiS_Pr)) ||
751 (SiS_IsVAMode(SiS_Pr))) { 743 (SiS_IsVAMode(SiS_Pr))) {
@@ -756,7 +748,7 @@ SiS_IsDualLink(struct SiS_Private *SiS_Pr)
756 return false; 748 return false;
757} 749}
758 750
759#ifdef SIS315H 751#ifdef CONFIG_FB_SIS_315
760static bool 752static bool
761SiS_TVEnabled(struct SiS_Private *SiS_Pr) 753SiS_TVEnabled(struct SiS_Private *SiS_Pr)
762{ 754{
@@ -768,7 +760,7 @@ SiS_TVEnabled(struct SiS_Private *SiS_Pr)
768} 760}
769#endif 761#endif
770 762
771#ifdef SIS315H 763#ifdef CONFIG_FB_SIS_315
772static bool 764static bool
773SiS_LCDAEnabled(struct SiS_Private *SiS_Pr) 765SiS_LCDAEnabled(struct SiS_Private *SiS_Pr)
774{ 766{
@@ -777,7 +769,7 @@ SiS_LCDAEnabled(struct SiS_Private *SiS_Pr)
777} 769}
778#endif 770#endif
779 771
780#ifdef SIS315H 772#ifdef CONFIG_FB_SIS_315
781static bool 773static bool
782SiS_WeHaveBacklightCtrl(struct SiS_Private *SiS_Pr) 774SiS_WeHaveBacklightCtrl(struct SiS_Private *SiS_Pr)
783{ 775{
@@ -788,7 +780,7 @@ SiS_WeHaveBacklightCtrl(struct SiS_Private *SiS_Pr)
788} 780}
789#endif 781#endif
790 782
791#ifdef SIS315H 783#ifdef CONFIG_FB_SIS_315
792static bool 784static bool
793SiS_IsNotM650orLater(struct SiS_Private *SiS_Pr) 785SiS_IsNotM650orLater(struct SiS_Private *SiS_Pr)
794{ 786{
@@ -804,7 +796,7 @@ SiS_IsNotM650orLater(struct SiS_Private *SiS_Pr)
804} 796}
805#endif 797#endif
806 798
807#ifdef SIS315H 799#ifdef CONFIG_FB_SIS_315
808static bool 800static bool
809SiS_IsYPbPr(struct SiS_Private *SiS_Pr) 801SiS_IsYPbPr(struct SiS_Private *SiS_Pr)
810{ 802{
@@ -816,7 +808,7 @@ SiS_IsYPbPr(struct SiS_Private *SiS_Pr)
816} 808}
817#endif 809#endif
818 810
819#ifdef SIS315H 811#ifdef CONFIG_FB_SIS_315
820static bool 812static bool
821SiS_IsChScart(struct SiS_Private *SiS_Pr) 813SiS_IsChScart(struct SiS_Private *SiS_Pr)
822{ 814{
@@ -828,7 +820,7 @@ SiS_IsChScart(struct SiS_Private *SiS_Pr)
828} 820}
829#endif 821#endif
830 822
831#ifdef SIS315H 823#ifdef CONFIG_FB_SIS_315
832static bool 824static bool
833SiS_IsTVOrYPbPrOrScart(struct SiS_Private *SiS_Pr) 825SiS_IsTVOrYPbPrOrScart(struct SiS_Private *SiS_Pr)
834{ 826{
@@ -848,7 +840,7 @@ SiS_IsTVOrYPbPrOrScart(struct SiS_Private *SiS_Pr)
848} 840}
849#endif 841#endif
850 842
851#ifdef SIS315H 843#ifdef CONFIG_FB_SIS_315
852static bool 844static bool
853SiS_IsLCDOrLCDA(struct SiS_Private *SiS_Pr) 845SiS_IsLCDOrLCDA(struct SiS_Private *SiS_Pr)
854{ 846{
@@ -914,7 +906,7 @@ SiS_BridgeInSlavemode(struct SiS_Private *SiS_Pr)
914/*********************************************/ 906/*********************************************/
915 907
916/* Setup general purpose IO for Chrontel communication */ 908/* Setup general purpose IO for Chrontel communication */
917#ifdef SIS300 909#ifdef CONFIG_FB_SIS_300
918void 910void
919SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo) 911SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo)
920{ 912{
@@ -923,11 +915,7 @@ SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo)
923 915
924 if(!(SiS_Pr->SiS_ChSW)) return; 916 if(!(SiS_Pr->SiS_ChSW)) return;
925 917
926#ifdef SIS_LINUX_KERNEL
927 acpibase = sisfb_read_lpc_pci_dword(SiS_Pr, 0x74); 918 acpibase = sisfb_read_lpc_pci_dword(SiS_Pr, 0x74);
928#else
929 acpibase = pciReadLong(0x00000800, 0x74);
930#endif
931 acpibase &= 0xFFFF; 919 acpibase &= 0xFFFF;
932 if(!acpibase) return; 920 if(!acpibase) return;
933 temp = SiS_GetRegShort((acpibase + 0x3c)); /* ACPI register 0x3c: GP Event 1 I/O mode select */ 921 temp = SiS_GetRegShort((acpibase + 0x3c)); /* ACPI register 0x3c: GP Event 1 I/O mode select */
@@ -969,7 +957,7 @@ SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
969 tempax &= (DriverMode | LoadDACFlag | SetNotSimuMode | SetPALTV); 957 tempax &= (DriverMode | LoadDACFlag | SetNotSimuMode | SetPALTV);
970 tempbx |= tempax; 958 tempbx |= tempax;
971 959
972#ifdef SIS315H 960#ifdef CONFIG_FB_SIS_315
973 if(SiS_Pr->ChipType >= SIS_315H) { 961 if(SiS_Pr->ChipType >= SIS_315H) {
974 if(SiS_Pr->SiS_VBType & VB_SISLCDA) { 962 if(SiS_Pr->SiS_VBType & VB_SISLCDA) {
975 if(ModeNo == 0x03) { 963 if(ModeNo == 0x03) {
@@ -1019,7 +1007,7 @@ SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
1019 } 1007 }
1020 } 1008 }
1021 1009
1022#endif /* SIS315H */ 1010#endif /* CONFIG_FB_SIS_315 */
1023 1011
1024 if(!(SiS_Pr->SiS_VBType & VB_SISVGA2)) { 1012 if(!(SiS_Pr->SiS_VBType & VB_SISVGA2)) {
1025 tempbx &= ~(SetCRT2ToRAMDAC); 1013 tempbx &= ~(SetCRT2ToRAMDAC);
@@ -1154,24 +1142,16 @@ SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
1154 1142
1155 SiS_Pr->SiS_VBInfo = tempbx; 1143 SiS_Pr->SiS_VBInfo = tempbx;
1156 1144
1157#ifdef SIS300 1145#ifdef CONFIG_FB_SIS_300
1158 if(SiS_Pr->ChipType == SIS_630) { 1146 if(SiS_Pr->ChipType == SIS_630) {
1159 SiS_SetChrontelGPIO(SiS_Pr, SiS_Pr->SiS_VBInfo); 1147 SiS_SetChrontelGPIO(SiS_Pr, SiS_Pr->SiS_VBInfo);
1160 } 1148 }
1161#endif 1149#endif
1162 1150
1163#ifdef SIS_LINUX_KERNEL
1164#if 0 1151#if 0
1165 printk(KERN_DEBUG "sisfb: (init301: VBInfo= 0x%04x, SetFlag=0x%04x)\n", 1152 printk(KERN_DEBUG "sisfb: (init301: VBInfo= 0x%04x, SetFlag=0x%04x)\n",
1166 SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag); 1153 SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag);
1167#endif 1154#endif
1168#endif
1169#ifdef SIS_XORG_XF86
1170#ifdef TWDEBUG
1171 xf86DrvMsg(0, X_PROBED, "(init301: VBInfo=0x%04x, SetFlag=0x%04x)\n",
1172 SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag);
1173#endif
1174#endif
1175} 1155}
1176 1156
1177/*********************************************/ 1157/*********************************************/
@@ -1415,12 +1395,6 @@ SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
1415 } 1395 }
1416 1396
1417 SiS_Pr->SiS_VBInfo &= ~SetPALTV; 1397 SiS_Pr->SiS_VBInfo &= ~SetPALTV;
1418
1419#ifdef SIS_XORG_XF86
1420#ifdef TWDEBUG
1421 xf86DrvMsg(0, X_INFO, "(init301: TVMode %x, VBInfo %x)\n", SiS_Pr->SiS_TVMode, SiS_Pr->SiS_VBInfo);
1422#endif
1423#endif
1424} 1398}
1425 1399
1426/*********************************************/ 1400/*********************************************/
@@ -1443,22 +1417,10 @@ SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr)
1443static void 1417static void
1444SiS_GetLCDInfoBIOS(struct SiS_Private *SiS_Pr) 1418SiS_GetLCDInfoBIOS(struct SiS_Private *SiS_Pr)
1445{ 1419{
1446#ifdef SIS315H 1420#ifdef CONFIG_FB_SIS_315
1447 unsigned char *ROMAddr; 1421 unsigned char *ROMAddr;
1448 unsigned short temp; 1422 unsigned short temp;
1449 1423
1450#ifdef SIS_XORG_XF86
1451#ifdef TWDEBUG
1452 xf86DrvMsg(0, X_INFO, "Paneldata driver: [%d %d] [H %d %d] [V %d %d] [C %d 0x%02x 0x%02x]\n",
1453 SiS_Pr->PanelHT, SiS_Pr->PanelVT,
1454 SiS_Pr->PanelHRS, SiS_Pr->PanelHRE,
1455 SiS_Pr->PanelVRS, SiS_Pr->PanelVRE,
1456 SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK,
1457 SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A,
1458 SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B);
1459#endif
1460#endif
1461
1462 if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) { 1424 if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
1463 if((temp = SISGETROMW(6)) != SiS_Pr->PanelHT) { 1425 if((temp = SISGETROMW(6)) != SiS_Pr->PanelHT) {
1464 SiS_Pr->SiS_NeedRomModeData = true; 1426 SiS_Pr->SiS_NeedRomModeData = true;
@@ -1480,18 +1442,6 @@ SiS_GetLCDInfoBIOS(struct SiS_Private *SiS_Pr)
1480 SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2C = 1442 SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2C =
1481 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_B = ROMAddr[20]; 1443 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_B = ROMAddr[20];
1482 1444
1483#ifdef SIS_XORG_XF86
1484#ifdef TWDEBUG
1485 xf86DrvMsg(0, X_INFO, "Paneldata BIOS: [%d %d] [H %d %d] [V %d %d] [C %d 0x%02x 0x%02x]\n",
1486 SiS_Pr->PanelHT, SiS_Pr->PanelVT,
1487 SiS_Pr->PanelHRS, SiS_Pr->PanelHRE,
1488 SiS_Pr->PanelVRS, SiS_Pr->PanelVRE,
1489 SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK,
1490 SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A,
1491 SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B);
1492#endif
1493#endif
1494
1495 } 1445 }
1496#endif 1446#endif
1497} 1447}
@@ -1517,13 +1467,13 @@ SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned sh
1517{ 1467{
1518 unsigned short temp,modeflag,resinfo=0,modexres=0,modeyres=0; 1468 unsigned short temp,modeflag,resinfo=0,modexres=0,modeyres=0;
1519 bool panelcanscale = false; 1469 bool panelcanscale = false;
1520#ifdef SIS300 1470#ifdef CONFIG_FB_SIS_300
1521 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase; 1471 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
1522 static const unsigned char SiS300SeriesLCDRes[] = 1472 static const unsigned char SiS300SeriesLCDRes[] =
1523 { 0, 1, 2, 3, 7, 4, 5, 8, 1473 { 0, 1, 2, 3, 7, 4, 5, 8,
1524 0, 0, 10, 0, 0, 0, 0, 15 }; 1474 0, 0, 10, 0, 0, 0, 0, 15 };
1525#endif 1475#endif
1526#ifdef SIS315H 1476#ifdef CONFIG_FB_SIS_315
1527 unsigned char *myptr = NULL; 1477 unsigned char *myptr = NULL;
1528#endif 1478#endif
1529 1479
@@ -1562,7 +1512,7 @@ SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned sh
1562 SiS_Pr->SiS_LCDTypeInfo = (temp & 0x0F) - 1; 1512 SiS_Pr->SiS_LCDTypeInfo = (temp & 0x0F) - 1;
1563 } 1513 }
1564 temp &= 0x0f; 1514 temp &= 0x0f;
1565#ifdef SIS300 1515#ifdef CONFIG_FB_SIS_300
1566 if(SiS_Pr->ChipType < SIS_315H) { 1516 if(SiS_Pr->ChipType < SIS_315H) {
1567 /* Very old BIOSes only know 7 sizes (NetVista 2179, 1.01g) */ 1517 /* Very old BIOSes only know 7 sizes (NetVista 2179, 1.01g) */
1568 if(SiS_Pr->SiS_VBType & VB_SIS301) { 1518 if(SiS_Pr->SiS_VBType & VB_SIS301) {
@@ -1574,7 +1524,7 @@ SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned sh
1574#endif 1524#endif
1575 1525
1576 /* Translate to our internal types */ 1526 /* Translate to our internal types */
1577#ifdef SIS315H 1527#ifdef CONFIG_FB_SIS_315
1578 if(SiS_Pr->ChipType == SIS_550) { 1528 if(SiS_Pr->ChipType == SIS_550) {
1579 if (temp == Panel310_1152x768) temp = Panel_320x240_2; /* Verified working */ 1529 if (temp == Panel310_1152x768) temp = Panel_320x240_2; /* Verified working */
1580 else if(temp == Panel310_320x240_2) temp = Panel_320x240_2; 1530 else if(temp == Panel310_320x240_2) temp = Panel_320x240_2;
@@ -1597,7 +1547,7 @@ SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned sh
1597 1547
1598 SiS_Pr->SiS_LCDResInfo = temp; 1548 SiS_Pr->SiS_LCDResInfo = temp;
1599 1549
1600#ifdef SIS300 1550#ifdef CONFIG_FB_SIS_300
1601 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { 1551 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
1602 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) { 1552 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
1603 SiS_Pr->SiS_LCDResInfo = Panel_Barco1366; 1553 SiS_Pr->SiS_LCDResInfo = Panel_Barco1366;
@@ -1639,7 +1589,7 @@ SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned sh
1639 else if(SiS_Pr->UsePanelScaler == 1) SiS_Pr->SiS_LCDInfo |= DontExpandLCD; 1589 else if(SiS_Pr->UsePanelScaler == 1) SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1640 1590
1641 /* Dual link, Pass 1:1 BIOS default, etc. */ 1591 /* Dual link, Pass 1:1 BIOS default, etc. */
1642#ifdef SIS315H 1592#ifdef CONFIG_FB_SIS_315
1643 if(SiS_Pr->ChipType >= SIS_661) { 1593 if(SiS_Pr->ChipType >= SIS_661) {
1644 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) { 1594 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
1645 if(temp & 0x08) SiS_Pr->SiS_LCDInfo |= LCDPass11; 1595 if(temp & 0x08) SiS_Pr->SiS_LCDInfo |= LCDPass11;
@@ -2076,7 +2026,7 @@ SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned sh
2076 } 2026 }
2077 } 2027 }
2078 2028
2079#ifdef SIS300 2029#ifdef CONFIG_FB_SIS_300
2080 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { 2030 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
2081 if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) { 2031 if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
2082 SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20; /* neg h/v sync, RGB24(D0 = 0) */ 2032 SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20; /* neg h/v sync, RGB24(D0 = 0) */
@@ -2186,17 +2136,10 @@ SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned sh
2186 SiS_Pr->SiS_SetFlag |= LCDVESATiming; 2136 SiS_Pr->SiS_SetFlag |= LCDVESATiming;
2187 } 2137 }
2188 2138
2189#ifdef SIS_LINUX_KERNEL
2190#if 0 2139#if 0
2191 printk(KERN_DEBUG "sisfb: (LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x)\n", 2140 printk(KERN_DEBUG "sisfb: (LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x)\n",
2192 SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo); 2141 SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo);
2193#endif 2142#endif
2194#endif
2195#ifdef SIS_XORG_XF86
2196 xf86DrvMsgVerb(0, X_PROBED, 4,
2197 "(init301: LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x SetFlag=0x%04x)\n",
2198 SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo, SiS_Pr->SiS_SetFlag);
2199#endif
2200} 2143}
2201 2144
2202/*********************************************/ 2145/*********************************************/
@@ -2359,7 +2302,7 @@ SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned shor
2359 VCLKIndex = SiS_Pr->PanelVCLKIdx315; 2302 VCLKIndex = SiS_Pr->PanelVCLKIdx315;
2360 } 2303 }
2361 2304
2362#ifdef SIS300 2305#ifdef CONFIG_FB_SIS_300
2363 /* Special Timing: Barco iQ Pro R series */ 2306 /* Special Timing: Barco iQ Pro R series */
2364 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) VCLKIndex = 0x44; 2307 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) VCLKIndex = 0x44;
2365 2308
@@ -2410,12 +2353,6 @@ SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned shor
2410 2353
2411 } 2354 }
2412 2355
2413#ifdef SIS_XORG_XF86
2414#ifdef TWDEBUG
2415 xf86DrvMsg(0, X_INFO, "VCLKIndex %d (0x%x)\n", VCLKIndex, VCLKIndex);
2416#endif
2417#endif
2418
2419 return VCLKIndex; 2356 return VCLKIndex;
2420} 2357}
2421 2358
@@ -2428,10 +2365,10 @@ SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
2428{ 2365{
2429 unsigned short i, j, modeflag, tempah=0; 2366 unsigned short i, j, modeflag, tempah=0;
2430 short tempcl; 2367 short tempcl;
2431#if defined(SIS300) || defined(SIS315H) 2368#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2432 unsigned short tempbl; 2369 unsigned short tempbl;
2433#endif 2370#endif
2434#ifdef SIS315H 2371#ifdef CONFIG_FB_SIS_315
2435 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase; 2372 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
2436 unsigned short tempah2, tempbl2; 2373 unsigned short tempah2, tempbl2;
2437#endif 2374#endif
@@ -2454,7 +2391,7 @@ SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
2454 2391
2455 if(SiS_Pr->ChipType < SIS_315H) { 2392 if(SiS_Pr->ChipType < SIS_315H) {
2456 2393
2457#ifdef SIS300 /* ---- 300 series ---- */ 2394#ifdef CONFIG_FB_SIS_300 /* ---- 300 series ---- */
2458 2395
2459 /* For 301BDH: (with LCD via LVDS) */ 2396 /* For 301BDH: (with LCD via LVDS) */
2460 if(SiS_Pr->SiS_VBType & VB_NoLCD) { 2397 if(SiS_Pr->SiS_VBType & VB_NoLCD) {
@@ -2477,11 +2414,11 @@ SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
2477 2414
2478 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0xA0; 2415 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0xA0;
2479 2416
2480#endif /* SIS300 */ 2417#endif /* CONFIG_FB_SIS_300 */
2481 2418
2482 } else { 2419 } else {
2483 2420
2484#ifdef SIS315H /* ------- 315/330 series ------ */ 2421#ifdef CONFIG_FB_SIS_315 /* ------- 315/330 series ------ */
2485 2422
2486 if(ModeNo > 0x13) { 2423 if(ModeNo > 0x13) {
2487 tempcl -= ModeVGA; 2424 tempcl -= ModeVGA;
@@ -2494,7 +2431,7 @@ SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
2494 2431
2495 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0x50; 2432 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0x50;
2496 2433
2497#endif /* SIS315H */ 2434#endif /* CONFIG_FB_SIS_315 */
2498 2435
2499 } 2436 }
2500 2437
@@ -2503,7 +2440,7 @@ SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
2503 if(SiS_Pr->ChipType < SIS_315H) { 2440 if(SiS_Pr->ChipType < SIS_315H) {
2504 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah); 2441 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
2505 } else { 2442 } else {
2506#ifdef SIS315H 2443#ifdef CONFIG_FB_SIS_315
2507 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { 2444 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
2508 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah); 2445 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
2509 } else if(SiS_Pr->SiS_VBType & VB_SISVB) { 2446 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
@@ -2584,7 +2521,7 @@ SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
2584 2521
2585 if(SiS_Pr->ChipType >= SIS_315H) { 2522 if(SiS_Pr->ChipType >= SIS_315H) {
2586 2523
2587#ifdef SIS315H 2524#ifdef CONFIG_FB_SIS_315
2588 /* LVDS can only be slave in 8bpp modes */ 2525 /* LVDS can only be slave in 8bpp modes */
2589 tempah = 0x80; 2526 tempah = 0x80;
2590 if((modeflag & CRT2Mode) && (SiS_Pr->SiS_ModeType > ModeVGA)) { 2527 if((modeflag & CRT2Mode) && (SiS_Pr->SiS_ModeType > ModeVGA)) {
@@ -2604,7 +2541,7 @@ SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
2604 2541
2605 } else { 2542 } else {
2606 2543
2607#ifdef SIS300 2544#ifdef CONFIG_FB_SIS_300
2608 tempah = 0; 2545 tempah = 0;
2609 if( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) && (SiS_Pr->SiS_ModeType > ModeVGA) ) { 2546 if( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) && (SiS_Pr->SiS_ModeType > ModeVGA) ) {
2610 tempah |= 0x02; 2547 tempah |= 0x02;
@@ -2626,7 +2563,7 @@ SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
2626 2563
2627 if(SiS_Pr->ChipType >= SIS_315H) { 2564 if(SiS_Pr->ChipType >= SIS_315H) {
2628 2565
2629#ifdef SIS315H 2566#ifdef CONFIG_FB_SIS_315
2630 /* unsigned char bridgerev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01); */ 2567 /* unsigned char bridgerev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01); */
2631 2568
2632 /* The following is nearly unpreditable and varies from machine 2569 /* The following is nearly unpreditable and varies from machine
@@ -2718,11 +2655,11 @@ SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
2718 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah); 2655 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah);
2719 } 2656 }
2720 2657
2721#endif /* SIS315H */ 2658#endif /* CONFIG_FB_SIS_315 */
2722 2659
2723 } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { 2660 } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
2724 2661
2725#ifdef SIS300 2662#ifdef CONFIG_FB_SIS_300
2726 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f); 2663 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
2727 2664
2728 if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) || 2665 if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
@@ -2745,7 +2682,7 @@ SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
2745 2682
2746 } else { /* LVDS */ 2683 } else { /* LVDS */
2747 2684
2748#ifdef SIS315H 2685#ifdef CONFIG_FB_SIS_315
2749 if(SiS_Pr->ChipType >= SIS_315H) { 2686 if(SiS_Pr->ChipType >= SIS_315H) {
2750 2687
2751 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { 2688 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
@@ -2931,7 +2868,7 @@ SiS_GetCRT2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
2931 } 2868 }
2932 } 2869 }
2933 2870
2934#ifdef SIS315H 2871#ifdef CONFIG_FB_SIS_315
2935 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) { 2872 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
2936 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) { 2873 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
2937 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) { 2874 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
@@ -3036,7 +2973,7 @@ SiS_GetCRT2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
3036 case Panel_1280x1024: tempbx = 24; break; 2973 case Panel_1280x1024: tempbx = 24; break;
3037 case Panel_1400x1050: tempbx = 26; break; 2974 case Panel_1400x1050: tempbx = 26; break;
3038 case Panel_1600x1200: tempbx = 28; break; 2975 case Panel_1600x1200: tempbx = 28; break;
3039#ifdef SIS300 2976#ifdef CONFIG_FB_SIS_300
3040 case Panel_Barco1366: tempbx = 80; break; 2977 case Panel_Barco1366: tempbx = 80; break;
3041#endif 2978#endif
3042 } 2979 }
@@ -3053,7 +2990,7 @@ SiS_GetCRT2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
3053 2990
3054 if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempbx = 30; 2991 if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempbx = 30;
3055 2992
3056#ifdef SIS300 2993#ifdef CONFIG_FB_SIS_300
3057 if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) { 2994 if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
3058 tempbx = 82; 2995 tempbx = 82;
3059 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++; 2996 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
@@ -3189,7 +3126,7 @@ SiS_GetCRT2DataLVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
3189 3126
3190 if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { 3127 if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
3191 3128
3192#ifdef SIS315H 3129#ifdef CONFIG_FB_SIS_315
3193 SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex); 3130 SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3194 SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex); 3131 SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
3195#endif 3132#endif
@@ -3214,7 +3151,7 @@ SiS_GetCRT2DataLVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
3214 case 16: LVDSData = SiS_Pr->SiS_LVDS800x600Data_1; break; 3151 case 16: LVDSData = SiS_Pr->SiS_LVDS800x600Data_1; break;
3215 case 18: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1; break; 3152 case 18: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1; break;
3216 case 20: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1; break; 3153 case 20: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1; break;
3217#ifdef SIS300 3154#ifdef CONFIG_FB_SIS_300
3218 case 80: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_1; break; 3155 case 80: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_1; break;
3219 case 81: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_2; break; 3156 case 81: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_2; break;
3220 case 82: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_1; break; 3157 case 82: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_1; break;
@@ -3248,7 +3185,7 @@ SiS_GetCRT2DataLVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned
3248 (SiS_Pr->SiS_SetFlag & SetDOSMode) ) { 3185 (SiS_Pr->SiS_SetFlag & SetDOSMode) ) {
3249 SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes; 3186 SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
3250 SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes; 3187 SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
3251#ifdef SIS300 3188#ifdef CONFIG_FB_SIS_300
3252 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) { 3189 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
3253 if(ResIndex < 0x08) { 3190 if(ResIndex < 0x08) {
3254 SiS_Pr->SiS_HDE = 1280; 3191 SiS_Pr->SiS_HDE = 1280;
@@ -3270,7 +3207,7 @@ SiS_GetCRT2Data301(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
3270 unsigned short resinfo, CRT2Index, ResIndex; 3207 unsigned short resinfo, CRT2Index, ResIndex;
3271 const struct SiS_LCDData *LCDPtr = NULL; 3208 const struct SiS_LCDData *LCDPtr = NULL;
3272 const struct SiS_TVData *TVPtr = NULL; 3209 const struct SiS_TVData *TVPtr = NULL;
3273#ifdef SIS315H 3210#ifdef CONFIG_FB_SIS_315
3274 short resinfo661; 3211 short resinfo661;
3275#endif 3212#endif
3276 3213
@@ -3283,7 +3220,7 @@ SiS_GetCRT2Data301(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
3283 } else { 3220 } else {
3284 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; 3221 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
3285 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; 3222 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
3286#ifdef SIS315H 3223#ifdef CONFIG_FB_SIS_315
3287 resinfo661 = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].ROMMODEIDX661; 3224 resinfo661 = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].ROMMODEIDX661;
3288 if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && 3225 if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
3289 (SiS_Pr->SiS_SetFlag & LCDVESATiming) && 3226 (SiS_Pr->SiS_SetFlag & LCDVESATiming) &&
@@ -3460,7 +3397,7 @@ SiS_GetCRT2Data301(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
3460 3397
3461 } else if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) && (romptr) && (ROMAddr) ) { 3398 } else if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) && (romptr) && (ROMAddr) ) {
3462 3399
3463#ifdef SIS315H 3400#ifdef CONFIG_FB_SIS_315
3464 SiS_Pr->SiS_RVBHCMAX = ROMAddr[romptr]; 3401 SiS_Pr->SiS_RVBHCMAX = ROMAddr[romptr];
3465 SiS_Pr->SiS_RVBHCFACT = ROMAddr[romptr+1]; 3402 SiS_Pr->SiS_RVBHCFACT = ROMAddr[romptr+1];
3466 SiS_Pr->SiS_VGAHT = ROMAddr[romptr+2] | ((ROMAddr[romptr+3] & 0x0f) << 8); 3403 SiS_Pr->SiS_VGAHT = ROMAddr[romptr+2] | ((ROMAddr[romptr+3] & 0x0f) << 8);
@@ -3520,19 +3457,13 @@ SiS_GetCRT2Data301(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
3520 case Panel_1680x1050 : 3457 case Panel_1680x1050 :
3521 case Panel_1680x1050 + 32: LCDPtr = SiS_Pr->SiS_LCD1680x1050Data; break; 3458 case Panel_1680x1050 + 32: LCDPtr = SiS_Pr->SiS_LCD1680x1050Data; break;
3522 case 100 : LCDPtr = SiS_Pr->SiS_NoScaleData; break; 3459 case 100 : LCDPtr = SiS_Pr->SiS_NoScaleData; break;
3523#ifdef SIS315H 3460#ifdef CONFIG_FB_SIS_315
3524 case 200 : LCDPtr = SiS310_ExtCompaq1280x1024Data; break; 3461 case 200 : LCDPtr = SiS310_ExtCompaq1280x1024Data; break;
3525 case 201 : LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data; break; 3462 case 201 : LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data; break;
3526#endif 3463#endif
3527 default : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break; 3464 default : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break;
3528 } 3465 }
3529 3466
3530#ifdef SIS_XORG_XF86
3531#ifdef TWDEBUG
3532 xf86DrvMsg(0, X_INFO, "GetCRT2Data: Index %d ResIndex %d\n", CRT2Index, ResIndex);
3533#endif
3534#endif
3535
3536 SiS_Pr->SiS_RVBHCMAX = (LCDPtr+ResIndex)->RVBHCMAX; 3467 SiS_Pr->SiS_RVBHCMAX = (LCDPtr+ResIndex)->RVBHCMAX;
3537 SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT; 3468 SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
3538 SiS_Pr->SiS_VGAHT = (LCDPtr+ResIndex)->VGAHT; 3469 SiS_Pr->SiS_VGAHT = (LCDPtr+ResIndex)->VGAHT;
@@ -3624,7 +3555,7 @@ SiS_GetLVDSDesPtr(struct SiS_Private *SiS_Pr)
3624{ 3555{
3625 const struct SiS_LVDSDes *PanelDesPtr = NULL; 3556 const struct SiS_LVDSDes *PanelDesPtr = NULL;
3626 3557
3627#ifdef SIS300 3558#ifdef CONFIG_FB_SIS_300
3628 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { 3559 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
3629 3560
3630 if(SiS_Pr->ChipType < SIS_315H) { 3561 if(SiS_Pr->ChipType < SIS_315H) {
@@ -3696,7 +3627,7 @@ SiS_GetLVDSDesData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
3696 3627
3697 if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { 3628 if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
3698 3629
3699#ifdef SIS315H 3630#ifdef CONFIG_FB_SIS_315
3700 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) { 3631 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3701 /* non-pass 1:1 only, see above */ 3632 /* non-pass 1:1 only, see above */
3702 if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) { 3633 if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
@@ -3771,7 +3702,7 @@ SiS_GetLVDSDesData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
3771 } else { 3702 } else {
3772 3703
3773 if(SiS_Pr->ChipType < SIS_315H) { 3704 if(SiS_Pr->ChipType < SIS_315H) {
3774#ifdef SIS300 3705#ifdef CONFIG_FB_SIS_300
3775 switch(SiS_Pr->SiS_LCDResInfo) { 3706 switch(SiS_Pr->SiS_LCDResInfo) {
3776 case Panel_800x600: 3707 case Panel_800x600:
3777 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) { 3708 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
@@ -3816,7 +3747,7 @@ SiS_GetLVDSDesData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
3816 } 3747 }
3817#endif 3748#endif
3818 } else { 3749 } else {
3819#ifdef SIS315H 3750#ifdef CONFIG_FB_SIS_315
3820 switch(SiS_Pr->SiS_LCDResInfo) { 3751 switch(SiS_Pr->SiS_LCDResInfo) {
3821 case Panel_1024x768: 3752 case Panel_1024x768:
3822 case Panel_1280x1024: 3753 case Panel_1280x1024:
@@ -3844,7 +3775,7 @@ SiS_GetLVDSDesData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
3844 if(SiS_Pr->ChipType < SIS_315H) { 3775 if(SiS_Pr->ChipType < SIS_315H) {
3845 if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 320; 3776 if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 320;
3846 } else { 3777 } else {
3847#ifdef SIS315H 3778#ifdef CONFIG_FB_SIS_315
3848 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) SiS_Pr->SiS_LCDHDES = 480; 3779 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) SiS_Pr->SiS_LCDHDES = 480;
3849 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 804; 3780 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 804;
3850 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 704; 3781 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 704;
@@ -3866,7 +3797,7 @@ SiS_GetLVDSDesData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
3866/* DISABLE VIDEO BRIDGE */ 3797/* DISABLE VIDEO BRIDGE */
3867/*********************************************/ 3798/*********************************************/
3868 3799
3869#ifdef SIS315H 3800#ifdef CONFIG_FB_SIS_315
3870static int 3801static int
3871SiS_HandlePWD(struct SiS_Private *SiS_Pr) 3802SiS_HandlePWD(struct SiS_Private *SiS_Pr)
3872{ 3803{
@@ -3891,11 +3822,6 @@ SiS_HandlePWD(struct SiS_Private *SiS_Pr)
3891 ret = 1; 3822 ret = 1;
3892 } 3823 }
3893 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x27,0x7f,temp); 3824 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x27,0x7f,temp);
3894#ifdef SIS_XORG_XF86
3895#ifdef TWDEBUG
3896 xf86DrvMsg(0, 0, "Setting PWD %x\n", temp);
3897#endif
3898#endif
3899 } 3825 }
3900#endif 3826#endif
3901 return ret; 3827 return ret;
@@ -3909,7 +3835,7 @@ SiS_HandlePWD(struct SiS_Private *SiS_Pr)
3909void 3835void
3910SiS_DisableBridge(struct SiS_Private *SiS_Pr) 3836SiS_DisableBridge(struct SiS_Private *SiS_Pr)
3911{ 3837{
3912#ifdef SIS315H 3838#ifdef CONFIG_FB_SIS_315
3913 unsigned short tempah, pushax=0, modenum; 3839 unsigned short tempah, pushax=0, modenum;
3914#endif 3840#endif
3915 unsigned short temp=0; 3841 unsigned short temp=0;
@@ -3920,7 +3846,7 @@ SiS_DisableBridge(struct SiS_Private *SiS_Pr)
3920 3846
3921 if(SiS_Pr->ChipType < SIS_315H) { 3847 if(SiS_Pr->ChipType < SIS_315H) {
3922 3848
3923#ifdef SIS300 /* 300 series */ 3849#ifdef CONFIG_FB_SIS_300 /* 300 series */
3924 3850
3925 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) { 3851 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
3926 if(SiS_Pr->SiS_VBType & VB_SISLVDS) { 3852 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
@@ -3953,11 +3879,11 @@ SiS_DisableBridge(struct SiS_Private *SiS_Pr)
3953 } 3879 }
3954 } 3880 }
3955 3881
3956#endif /* SIS300 */ 3882#endif /* CONFIG_FB_SIS_300 */
3957 3883
3958 } else { 3884 } else {
3959 3885
3960#ifdef SIS315H /* 315 series */ 3886#ifdef CONFIG_FB_SIS_315 /* 315 series */
3961 3887
3962 int didpwd = 0; 3888 int didpwd = 0;
3963 bool custom1 = (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) || 3889 bool custom1 = (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
@@ -4081,14 +4007,14 @@ SiS_DisableBridge(struct SiS_Private *SiS_Pr)
4081 4007
4082 } 4008 }
4083 4009
4084#endif /* SIS315H */ 4010#endif /* CONFIG_FB_SIS_315 */
4085 4011
4086 } 4012 }
4087 4013
4088 } else { /* ============ For 301 ================ */ 4014 } else { /* ============ For 301 ================ */
4089 4015
4090 if(SiS_Pr->ChipType < SIS_315H) { 4016 if(SiS_Pr->ChipType < SIS_315H) {
4091#ifdef SIS300 4017#ifdef CONFIG_FB_SIS_300
4092 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) { 4018 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4093 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08); 4019 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4094 SiS_PanelDelay(SiS_Pr, 3); 4020 SiS_PanelDelay(SiS_Pr, 3);
@@ -4111,7 +4037,7 @@ SiS_DisableBridge(struct SiS_Private *SiS_Pr)
4111 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); 4037 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4112 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp); 4038 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
4113 } else { 4039 } else {
4114#ifdef SIS300 4040#ifdef CONFIG_FB_SIS_300
4115 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF); /* disable CRT2 */ 4041 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF); /* disable CRT2 */
4116 if( (!(SiS_CRT2IsLCD(SiS_Pr))) || 4042 if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
4117 (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) { 4043 (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
@@ -4127,7 +4053,7 @@ SiS_DisableBridge(struct SiS_Private *SiS_Pr)
4127 4053
4128 if(SiS_Pr->ChipType < SIS_315H) { 4054 if(SiS_Pr->ChipType < SIS_315H) {
4129 4055
4130#ifdef SIS300 /* 300 series */ 4056#ifdef CONFIG_FB_SIS_300 /* 300 series */
4131 4057
4132 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) { 4058 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
4133 SiS_SetCH700x(SiS_Pr,0x0E,0x09); 4059 SiS_SetCH700x(SiS_Pr,0x0E,0x09);
@@ -4171,11 +4097,11 @@ SiS_DisableBridge(struct SiS_Private *SiS_Pr)
4171 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04); 4097 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
4172 } 4098 }
4173 4099
4174#endif /* SIS300 */ 4100#endif /* CONFIG_FB_SIS_300 */
4175 4101
4176 } else { 4102 } else {
4177 4103
4178#ifdef SIS315H /* 315 series */ 4104#ifdef CONFIG_FB_SIS_315 /* 315 series */
4179 4105
4180 if(!(SiS_IsNotM650orLater(SiS_Pr))) { 4106 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
4181 /*if(SiS_Pr->ChipType < SIS_340) { */ /* XGI needs this */ 4107 /*if(SiS_Pr->ChipType < SIS_340) { */ /* XGI needs this */
@@ -4288,7 +4214,7 @@ SiS_DisableBridge(struct SiS_Private *SiS_Pr)
4288 } 4214 }
4289 } 4215 }
4290 4216
4291#endif /* SIS315H */ 4217#endif /* CONFIG_FB_SIS_315 */
4292 4218
4293 } /* 315 series */ 4219 } /* 315 series */
4294 4220
@@ -4304,14 +4230,12 @@ SiS_DisableBridge(struct SiS_Private *SiS_Pr)
4304 * from outside the context of a mode switch! 4230 * from outside the context of a mode switch!
4305 * MUST call getVBType before calling this 4231 * MUST call getVBType before calling this
4306 */ 4232 */
4307#ifdef SIS_LINUX_KERNEL
4308static 4233static
4309#endif
4310void 4234void
4311SiS_EnableBridge(struct SiS_Private *SiS_Pr) 4235SiS_EnableBridge(struct SiS_Private *SiS_Pr)
4312{ 4236{
4313 unsigned short temp=0, tempah; 4237 unsigned short temp=0, tempah;
4314#ifdef SIS315H 4238#ifdef CONFIG_FB_SIS_315
4315 unsigned short temp1, pushax=0; 4239 unsigned short temp1, pushax=0;
4316 bool delaylong = false; 4240 bool delaylong = false;
4317#endif 4241#endif
@@ -4322,7 +4246,7 @@ SiS_EnableBridge(struct SiS_Private *SiS_Pr)
4322 4246
4323 if(SiS_Pr->ChipType < SIS_315H) { 4247 if(SiS_Pr->ChipType < SIS_315H) {
4324 4248
4325#ifdef SIS300 /* 300 series */ 4249#ifdef CONFIG_FB_SIS_300 /* 300 series */
4326 4250
4327 if(SiS_CRT2IsLCD(SiS_Pr)) { 4251 if(SiS_CRT2IsLCD(SiS_Pr)) {
4328 if(SiS_Pr->SiS_VBType & VB_SISLVDS) { 4252 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
@@ -4385,11 +4309,11 @@ SiS_EnableBridge(struct SiS_Private *SiS_Pr)
4385 } 4309 }
4386 4310
4387 4311
4388#endif /* SIS300 */ 4312#endif /* CONFIG_FB_SIS_300 */
4389 4313
4390 } else { 4314 } else {
4391 4315
4392#ifdef SIS315H /* 315 series */ 4316#ifdef CONFIG_FB_SIS_315 /* 315 series */
4393 4317
4394#ifdef SET_EMI 4318#ifdef SET_EMI
4395 unsigned char r30=0, r31=0, r32=0, r33=0, cr36=0; 4319 unsigned char r30=0, r31=0, r32=0, r33=0, cr36=0;
@@ -4688,7 +4612,7 @@ SiS_EnableBridge(struct SiS_Private *SiS_Pr)
4688 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f); 4612 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
4689 } 4613 }
4690 4614
4691#endif /* SIS315H */ 4615#endif /* CONFIG_FB_SIS_315 */
4692 4616
4693 } 4617 }
4694 4618
@@ -4739,7 +4663,7 @@ SiS_EnableBridge(struct SiS_Private *SiS_Pr)
4739 4663
4740 if(SiS_Pr->ChipType < SIS_315H) { 4664 if(SiS_Pr->ChipType < SIS_315H) {
4741 4665
4742#ifdef SIS300 /* 300 series */ 4666#ifdef CONFIG_FB_SIS_300 /* 300 series */
4743 4667
4744 if(SiS_CRT2IsLCD(SiS_Pr)) { 4668 if(SiS_CRT2IsLCD(SiS_Pr)) {
4745 if(SiS_Pr->ChipType == SIS_730) { 4669 if(SiS_Pr->ChipType == SIS_730) {
@@ -4783,11 +4707,11 @@ SiS_EnableBridge(struct SiS_Private *SiS_Pr)
4783 } 4707 }
4784 } 4708 }
4785 4709
4786#endif /* SIS300 */ 4710#endif /* CONFIG_FB_SIS_300 */
4787 4711
4788 } else { 4712 } else {
4789 4713
4790#ifdef SIS315H /* 315 series */ 4714#ifdef CONFIG_FB_SIS_315 /* 315 series */
4791 4715
4792 if(!(SiS_IsNotM650orLater(SiS_Pr))) { 4716 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
4793 /*if(SiS_Pr->ChipType < SIS_340) {*/ /* XGI needs this */ 4717 /*if(SiS_Pr->ChipType < SIS_340) {*/ /* XGI needs this */
@@ -4881,7 +4805,7 @@ SiS_EnableBridge(struct SiS_Private *SiS_Pr)
4881 } 4805 }
4882 } 4806 }
4883 4807
4884#endif /* SIS315H */ 4808#endif /* CONFIG_FB_SIS_315 */
4885 4809
4886 } /* 310 series */ 4810 } /* 310 series */
4887 4811
@@ -4971,7 +4895,7 @@ SiS_SetCRT2Sync(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned shor
4971 4895
4972 if(SiS_Pr->ChipType < SIS_315H) { 4896 if(SiS_Pr->ChipType < SIS_315H) {
4973 4897
4974#ifdef SIS300 /* ---- 300 series --- */ 4898#ifdef CONFIG_FB_SIS_300 /* ---- 300 series --- */
4975 4899
4976 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { /* 630 - 301B(-DH) */ 4900 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { /* 630 - 301B(-DH) */
4977 4901
@@ -5000,11 +4924,11 @@ SiS_SetCRT2Sync(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned shor
5000 4924
5001 } 4925 }
5002 4926
5003#endif /* SIS300 */ 4927#endif /* CONFIG_FB_SIS_300 */
5004 4928
5005 } else { 4929 } else {
5006 4930
5007#ifdef SIS315H /* ------- 315 series ------ */ 4931#ifdef CONFIG_FB_SIS_315 /* ------- 315 series ------ */
5008 4932
5009 if(SiS_Pr->SiS_VBType & VB_SISLVDS) { /* 315 - LVDS */ 4933 if(SiS_Pr->SiS_VBType & VB_SISLVDS) { /* 315 - LVDS */
5010 4934
@@ -5076,13 +5000,13 @@ SiS_SetCRT2Sync(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned shor
5076 } 5000 }
5077 5001
5078 } 5002 }
5079#endif /* SIS315H */ 5003#endif /* CONFIG_FB_SIS_315 */
5080 } 5004 }
5081 } 5005 }
5082} 5006}
5083 5007
5084/* Set CRT2 FIFO on 300/540/630/730 */ 5008/* Set CRT2 FIFO on 300/540/630/730 */
5085#ifdef SIS300 5009#ifdef CONFIG_FB_SIS_300
5086static void 5010static void
5087SiS_SetCRT2FIFO_300(struct SiS_Private *SiS_Pr,unsigned short ModeNo) 5011SiS_SetCRT2FIFO_300(struct SiS_Private *SiS_Pr,unsigned short ModeNo)
5088{ 5012{
@@ -5154,13 +5078,8 @@ SiS_SetCRT2FIFO_300(struct SiS_Private *SiS_Pr,unsigned short ModeNo)
5154 5078
5155 } else { 5079 } else {
5156 5080
5157#ifdef SIS_LINUX_KERNEL
5158 pci50 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50); 5081 pci50 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
5159 pciA0 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xa0); 5082 pciA0 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xa0);
5160#else
5161 pci50 = pciReadLong(0x00000000, 0x50);
5162 pciA0 = pciReadLong(0x00000000, 0xA0);
5163#endif
5164 5083
5165 if(SiS_Pr->ChipType == SIS_730) { 5084 if(SiS_Pr->ChipType == SIS_730) {
5166 5085
@@ -5262,7 +5181,7 @@ SiS_SetCRT2FIFO_300(struct SiS_Private *SiS_Pr,unsigned short ModeNo)
5262#endif 5181#endif
5263 5182
5264/* Set CRT2 FIFO on 315/330 series */ 5183/* Set CRT2 FIFO on 315/330 series */
5265#ifdef SIS315H 5184#ifdef CONFIG_FB_SIS_315
5266static void 5185static void
5267SiS_SetCRT2FIFO_310(struct SiS_Private *SiS_Pr) 5186SiS_SetCRT2FIFO_310(struct SiS_Private *SiS_Pr)
5268{ 5187{
@@ -5420,27 +5339,6 @@ SiS_SetGroup1_301(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned sho
5420 5339
5421 temp = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02)); 5340 temp = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
5422 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp); /* ? */ 5341 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp); /* ? */
5423
5424#ifdef SIS_XORG_XF86
5425#ifdef TWDEBUG
5426 xf86DrvMsg(0, X_INFO, "%d %d %d %d %d %d %d %d (%d %d %d %d)\n",
5427 SiS_Pr->CHDisplay, SiS_Pr->CHSyncStart, SiS_Pr->CHSyncEnd, SiS_Pr->CHTotal,
5428 SiS_Pr->CVDisplay, SiS_Pr->CVSyncStart, SiS_Pr->CVSyncEnd, SiS_Pr->CVTotal,
5429 SiS_Pr->CHBlankStart, SiS_Pr->CHBlankEnd, SiS_Pr->CVBlankStart, SiS_Pr->CVBlankEnd);
5430
5431 xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
5432 SiS_Pr->CCRT1CRTC[0], SiS_Pr->CCRT1CRTC[1],
5433 SiS_Pr->CCRT1CRTC[2], SiS_Pr->CCRT1CRTC[3],
5434 SiS_Pr->CCRT1CRTC[4], SiS_Pr->CCRT1CRTC[5],
5435 SiS_Pr->CCRT1CRTC[6], SiS_Pr->CCRT1CRTC[7]);
5436 xf86DrvMsg(0, X_INFO, " 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
5437 SiS_Pr->CCRT1CRTC[8], SiS_Pr->CCRT1CRTC[9],
5438 SiS_Pr->CCRT1CRTC[10], SiS_Pr->CCRT1CRTC[11],
5439 SiS_Pr->CCRT1CRTC[12], SiS_Pr->CCRT1CRTC[13],
5440 SiS_Pr->CCRT1CRTC[14], SiS_Pr->CCRT1CRTC[15]);
5441 xf86DrvMsg(0, X_INFO, " 0x%02x}},\n", SiS_Pr->CCRT1CRTC[16]);
5442#endif
5443#endif
5444} 5342}
5445 5343
5446/* Setup panel link 5344/* Setup panel link
@@ -5455,17 +5353,17 @@ SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
5455 unsigned short push2, tempax, tempbx, tempcx, temp; 5353 unsigned short push2, tempax, tempbx, tempcx, temp;
5456 unsigned int tempeax = 0, tempebx, tempecx, tempvcfact = 0; 5354 unsigned int tempeax = 0, tempebx, tempecx, tempvcfact = 0;
5457 bool islvds = false, issis = false, chkdclkfirst = false; 5355 bool islvds = false, issis = false, chkdclkfirst = false;
5458#ifdef SIS300 5356#ifdef CONFIG_FB_SIS_300
5459 unsigned short crt2crtc = 0; 5357 unsigned short crt2crtc = 0;
5460#endif 5358#endif
5461#ifdef SIS315H 5359#ifdef CONFIG_FB_SIS_315
5462 unsigned short pushcx; 5360 unsigned short pushcx;
5463#endif 5361#endif
5464 5362
5465 if(ModeNo <= 0x13) { 5363 if(ModeNo <= 0x13) {
5466 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; 5364 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
5467 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo; 5365 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
5468#ifdef SIS300 5366#ifdef CONFIG_FB_SIS_300
5469 crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC; 5367 crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
5470#endif 5368#endif
5471 } else if(SiS_Pr->UseCustomMode) { 5369 } else if(SiS_Pr->UseCustomMode) {
@@ -5473,7 +5371,7 @@ SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
5473 } else { 5371 } else {
5474 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; 5372 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
5475 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO; 5373 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
5476#ifdef SIS300 5374#ifdef CONFIG_FB_SIS_300
5477 crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC; 5375 crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
5478#endif 5376#endif
5479 } 5377 }
@@ -5494,7 +5392,7 @@ SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
5494 } 5392 }
5495 } 5393 }
5496 5394
5497#ifdef SIS315H 5395#ifdef CONFIG_FB_SIS_315
5498 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) { 5396 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
5499 if(IS_SIS330) { 5397 if(IS_SIS330) {
5500 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10); 5398 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
@@ -5744,7 +5642,7 @@ SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
5744 5642
5745 if(SiS_Pr->ChipType < SIS_315H) { 5643 if(SiS_Pr->ChipType < SIS_315H) {
5746 5644
5747#ifdef SIS300 /* 300 series */ 5645#ifdef CONFIG_FB_SIS_300 /* 300 series */
5748 tempeax = SiS_Pr->SiS_VGAVDE << 6; 5646 tempeax = SiS_Pr->SiS_VGAVDE << 6;
5749 temp = (tempeax % (unsigned int)SiS_Pr->SiS_VDE); 5647 temp = (tempeax % (unsigned int)SiS_Pr->SiS_VDE);
5750 tempeax = tempeax / (unsigned int)SiS_Pr->SiS_VDE; 5648 tempeax = tempeax / (unsigned int)SiS_Pr->SiS_VDE;
@@ -5755,11 +5653,11 @@ SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
5755 temp = (unsigned short)(tempeax & 0x00FF); 5653 temp = (unsigned short)(tempeax & 0x00FF);
5756 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,temp); /* BPLVCFACT */ 5654 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,temp); /* BPLVCFACT */
5757 tempvcfact = temp; 5655 tempvcfact = temp;
5758#endif /* SIS300 */ 5656#endif /* CONFIG_FB_SIS_300 */
5759 5657
5760 } else { 5658 } else {
5761 5659
5762#ifdef SIS315H /* 315 series */ 5660#ifdef CONFIG_FB_SIS_315 /* 315 series */
5763 tempeax = SiS_Pr->SiS_VGAVDE << 18; 5661 tempeax = SiS_Pr->SiS_VGAVDE << 18;
5764 tempebx = SiS_Pr->SiS_VDE; 5662 tempebx = SiS_Pr->SiS_VDE;
5765 temp = (tempeax % tempebx); 5663 temp = (tempeax % tempebx);
@@ -5845,7 +5743,7 @@ SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
5845 temp = (unsigned short)(tempecx & 0x00FF); 5743 temp = (unsigned short)(tempecx & 0x00FF);
5846 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp); 5744 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp);
5847 5745
5848#ifdef SIS315H 5746#ifdef CONFIG_FB_SIS_315
5849 if(SiS_Pr->ChipType >= SIS_315H) { 5747 if(SiS_Pr->ChipType >= SIS_315H) {
5850 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) { 5748 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
5851 if((islvds) || (SiS_Pr->SiS_VBInfo & VB_SISLVDS)) { 5749 if((islvds) || (SiS_Pr->SiS_VBInfo & VB_SISLVDS)) {
@@ -5863,7 +5761,7 @@ SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
5863 } 5761 }
5864#endif 5762#endif
5865 5763
5866#ifdef SIS300 5764#ifdef CONFIG_FB_SIS_300
5867 if(SiS_Pr->SiS_IF_DEF_TRUMPION) { 5765 if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
5868 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase; 5766 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
5869 unsigned char *trumpdata; 5767 unsigned char *trumpdata;
@@ -5899,7 +5797,7 @@ SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
5899 } 5797 }
5900#endif 5798#endif
5901 5799
5902#ifdef SIS315H 5800#ifdef CONFIG_FB_SIS_315
5903 if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) { 5801 if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
5904 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x25,0x00); 5802 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x25,0x00);
5905 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x26,0x00); 5803 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x26,0x00);
@@ -5954,7 +5852,7 @@ SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
5954 temp = tempax & 0x00FF; 5852 temp = tempax & 0x00FF;
5955 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,temp); 5853 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,temp);
5956 temp = ((tempax & 0xFF00) >> 8) << 3; 5854 temp = ((tempax & 0xFF00) >> 8) << 3;
5957 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x0F8,temp); 5855 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port, 0x44, 0x07, temp);
5958 5856
5959 tempax = SiS_Pr->SiS_VDE; /* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */ 5857 tempax = SiS_Pr->SiS_VDE; /* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */
5960 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 || 5858 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
@@ -5968,7 +5866,7 @@ SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
5968 temp = ((tempeax & 0xFF0000) >> 16) | 0x10; 5866 temp = ((tempeax & 0xFF0000) >> 16) | 0x10;
5969 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,temp); 5867 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,temp);
5970 temp = ((tempeax & 0x01000000) >> 24) << 7; 5868 temp = ((tempeax & 0x01000000) >> 24) << 7;
5971 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x080,temp); 5869 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port, 0x3C, 0x7F, temp);
5972 5870
5973 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x03); 5871 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x03);
5974 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,0x50); 5872 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,0x50);
@@ -5999,7 +5897,7 @@ SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
5999 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,0x0a); 5897 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,0x0a);
6000 } 5898 }
6001 } 5899 }
6002#endif /* SIS315H */ 5900#endif /* CONFIG_FB_SIS_315 */
6003} 5901}
6004 5902
6005/* Set Part 1 */ 5903/* Set Part 1 */
@@ -6007,12 +5905,12 @@ static void
6007SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex, 5905SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
6008 unsigned short RefreshRateTableIndex) 5906 unsigned short RefreshRateTableIndex)
6009{ 5907{
6010#if defined(SIS300) || defined(SIS315H) 5908#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
6011 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase; 5909 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
6012#endif 5910#endif
6013 unsigned short temp=0, tempax=0, tempbx=0, tempcx=0, bridgeadd=0; 5911 unsigned short temp=0, tempax=0, tempbx=0, tempcx=0, bridgeadd=0;
6014 unsigned short pushbx=0, CRT1Index=0, modeflag, resinfo=0; 5912 unsigned short pushbx=0, CRT1Index=0, modeflag, resinfo=0;
6015#ifdef SIS315H 5913#ifdef CONFIG_FB_SIS_315
6016 unsigned short tempbl=0; 5914 unsigned short tempbl=0;
6017#endif 5915#endif
6018 5916
@@ -6038,11 +5936,11 @@ SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
6038 (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) { 5936 (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) {
6039 5937
6040 if(SiS_Pr->ChipType < SIS_315H ) { 5938 if(SiS_Pr->ChipType < SIS_315H ) {
6041#ifdef SIS300 5939#ifdef CONFIG_FB_SIS_300
6042 SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo); 5940 SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo);
6043#endif 5941#endif
6044 } else { 5942 } else {
6045#ifdef SIS315H 5943#ifdef CONFIG_FB_SIS_315
6046 SiS_SetCRT2FIFO_310(SiS_Pr); 5944 SiS_SetCRT2FIFO_310(SiS_Pr);
6047#endif 5945#endif
6048 } 5946 }
@@ -6051,7 +5949,7 @@ SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
6051 5949
6052 if(SiS_Pr->ChipType < SIS_315H ) { 5950 if(SiS_Pr->ChipType < SIS_315H ) {
6053 5951
6054#ifdef SIS300 /* ------------- 300 series --------------*/ 5952#ifdef CONFIG_FB_SIS_300 /* ------------- 300 series --------------*/
6055 5953
6056 temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF; /* BTVGA2HT 0x08,0x09 */ 5954 temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF; /* BTVGA2HT 0x08,0x09 */
6057 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp); /* CRT2 Horizontal Total */ 5955 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp); /* CRT2 Horizontal Total */
@@ -6070,11 +5968,11 @@ SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
6070 5968
6071 bridgeadd = 12; 5969 bridgeadd = 12;
6072 5970
6073#endif /* SIS300 */ 5971#endif /* CONFIG_FB_SIS_300 */
6074 5972
6075 } else { 5973 } else {
6076 5974
6077#ifdef SIS315H /* ------------------- 315/330 series --------------- */ 5975#ifdef CONFIG_FB_SIS_315 /* ------------------- 315/330 series --------------- */
6078 5976
6079 tempcx = SiS_Pr->SiS_VGAHT; /* BTVGA2HT 0x08,0x09 */ 5977 tempcx = SiS_Pr->SiS_VGAHT; /* BTVGA2HT 0x08,0x09 */
6080 if(modeflag & HalfDCLK) { 5978 if(modeflag & HalfDCLK) {
@@ -6125,7 +6023,7 @@ SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
6125 } 6023 }
6126 } 6024 }
6127 6025
6128#endif /* SIS315H */ 6026#endif /* CONFIG_FB_SIS_315 */
6129 6027
6130 } /* 315/330 series */ 6028 } /* 315/330 series */
6131 6029
@@ -6256,7 +6154,7 @@ SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
6256 6154
6257 if(SiS_Pr->ChipType < SIS_315H) { 6155 if(SiS_Pr->ChipType < SIS_315H) {
6258 6156
6259#ifdef SIS300 /* ---------- 300 series -------------- */ 6157#ifdef CONFIG_FB_SIS_300 /* ---------- 300 series -------------- */
6260 6158
6261 if(SiS_Pr->SiS_VBType & VB_SISVB) { 6159 if(SiS_Pr->SiS_VBType & VB_SISVB) {
6262 temp = 0x20; 6160 temp = 0x20;
@@ -6310,11 +6208,11 @@ SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
6310 6208
6311 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp); /* Panel Link Delay Compensation; (Software Command Reset; Power Saving) */ 6209 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp); /* Panel Link Delay Compensation; (Software Command Reset; Power Saving) */
6312 6210
6313#endif /* SIS300 */ 6211#endif /* CONFIG_FB_SIS_300 */
6314 6212
6315 } else { 6213 } else {
6316 6214
6317#ifdef SIS315H /* --------------- 315/330 series ---------------*/ 6215#ifdef CONFIG_FB_SIS_315 /* --------------- 315/330 series ---------------*/
6318 6216
6319 if(SiS_Pr->ChipType < SIS_661) { 6217 if(SiS_Pr->ChipType < SIS_661) {
6320 6218
@@ -6349,7 +6247,7 @@ SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
6349 if(modeflag & HalfDCLK) tempax |= 0x40; 6247 if(modeflag & HalfDCLK) tempax |= 0x40;
6350 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax); 6248 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
6351 6249
6352#endif /* SIS315H */ 6250#endif /* CONFIG_FB_SIS_315 */
6353 6251
6354 } 6252 }
6355 6253
@@ -6381,7 +6279,7 @@ SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
6381/* SET PART 2 REGISTER GROUP */ 6279/* SET PART 2 REGISTER GROUP */
6382/*********************************************/ 6280/*********************************************/
6383 6281
6384#ifdef SIS315H 6282#ifdef CONFIG_FB_SIS_315
6385static unsigned char * 6283static unsigned char *
6386SiS_GetGroup2CLVXPtr(struct SiS_Private *SiS_Pr, int tabletype) 6284SiS_GetGroup2CLVXPtr(struct SiS_Private *SiS_Pr, int tabletype)
6387{ 6285{
@@ -6478,7 +6376,7 @@ SiS_GetCRT2Part2Ptr(struct SiS_Private *SiS_Pr,unsigned short ModeNo,unsigned sh
6478} 6376}
6479#endif 6377#endif
6480 6378
6481#ifdef SIS300 6379#ifdef CONFIG_FB_SIS_300
6482static void 6380static void
6483SiS_Group2LCDSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short crt2crtc) 6381SiS_Group2LCDSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short crt2crtc)
6484{ 6382{
@@ -6690,7 +6588,7 @@ SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
6690 unsigned int longtemp, PhaseIndex; 6588 unsigned int longtemp, PhaseIndex;
6691 bool newtvphase; 6589 bool newtvphase;
6692 const unsigned char *TimingPoint; 6590 const unsigned char *TimingPoint;
6693#ifdef SIS315H 6591#ifdef CONFIG_FB_SIS_315
6694 unsigned short resindex, CRT2Index; 6592 unsigned short resindex, CRT2Index;
6695 const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL; 6593 const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
6696 6594
@@ -7069,7 +6967,7 @@ SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
7069 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x17,0xFB); 6967 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x17,0xFB);
7070 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x18,0xDF); 6968 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x18,0xDF);
7071 6969
7072#ifdef SIS315H 6970#ifdef CONFIG_FB_SIS_315
7073 if(SiS_GetCRT2Part2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, 6971 if(SiS_GetCRT2Part2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
7074 &CRT2Index, &resindex)) { 6972 &CRT2Index, &resindex)) {
7075 switch(CRT2Index) { 6973 switch(CRT2Index) {
@@ -7130,12 +7028,6 @@ SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
7130 7028
7131 /* Non-expanding: lcdvdes = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */ 7029 /* Non-expanding: lcdvdes = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */
7132 7030
7133#ifdef SIS_XORG_XF86
7134#ifdef TWDEBUG
7135 xf86DrvMsg(0, X_INFO, "lcdvdes 0x%x lcdvdee 0x%x\n", tempcx, tempbx);
7136#endif
7137#endif
7138
7139 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempcx); /* lcdvdes */ 7031 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempcx); /* lcdvdes */
7140 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,tempbx); /* lcdvdee */ 7032 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,tempbx); /* lcdvdee */
7141 7033
@@ -7184,12 +7076,6 @@ SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
7184 tempbx = SiS_Pr->CVSyncStart; 7076 tempbx = SiS_Pr->CVSyncStart;
7185 } 7077 }
7186 7078
7187#ifdef SIS_XORG_XF86
7188#ifdef TWDEBUG
7189 xf86DrvMsg(0, X_INFO, "lcdvrs 0x%x\n", tempbx);
7190#endif
7191#endif
7192
7193 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx); /* lcdvrs */ 7079 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx); /* lcdvrs */
7194 7080
7195 temp = (tempbx >> 4) & 0xF0; 7081 temp = (tempbx >> 4) & 0xF0;
@@ -7201,15 +7087,9 @@ SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
7201 temp |= (SiS_Pr->CVSyncEnd & 0x0f); 7087 temp |= (SiS_Pr->CVSyncEnd & 0x0f);
7202 } 7088 }
7203 7089
7204#ifdef SIS_XORG_XF86
7205#ifdef TWDEBUG
7206 xf86DrvMsg(0, X_INFO, "lcdvre[3:0] 0x%x\n", (temp & 0x0f));
7207#endif
7208#endif
7209
7210 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp); 7090 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
7211 7091
7212#ifdef SIS300 7092#ifdef CONFIG_FB_SIS_300
7213 SiS_Group2LCDSpecial(SiS_Pr, ModeNo, crt2crtc); 7093 SiS_Group2LCDSpecial(SiS_Pr, ModeNo, crt2crtc);
7214#endif 7094#endif
7215 7095
@@ -7245,12 +7125,6 @@ SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
7245 tempax >>= 1; 7125 tempax >>= 1;
7246 } 7126 }
7247 7127
7248#ifdef SIS_XORG_XF86
7249#ifdef TWDEBUG
7250 xf86DrvMsg(0, X_INFO, "lcdhdee 0x%x\n", tempbx);
7251#endif
7252#endif
7253
7254 tempbx += bridgeoffset; 7128 tempbx += bridgeoffset;
7255 7129
7256 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,tempbx); /* lcdhdee */ 7130 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,tempbx); /* lcdhdee */
@@ -7276,12 +7150,6 @@ SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
7276 tempbx += bridgeoffset; 7150 tempbx += bridgeoffset;
7277 } 7151 }
7278 7152
7279#ifdef SIS_XORG_XF86
7280#ifdef TWDEBUG
7281 xf86DrvMsg(0, X_INFO, "lcdhrs 0x%x\n", tempbx);
7282#endif
7283#endif
7284
7285 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,tempbx); /* lcdhrs */ 7153 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,tempbx); /* lcdhrs */
7286 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,((tempbx >> 4) & 0xf0)); 7154 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,((tempbx >> 4) & 0xf0));
7287 7155
@@ -7300,20 +7168,14 @@ SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
7300 tempbx += bridgeoffset; 7168 tempbx += bridgeoffset;
7301 } 7169 }
7302 7170
7303#ifdef SIS_XORG_XF86
7304#ifdef TWDEBUG
7305 xf86DrvMsg(0, X_INFO, "lcdhre 0x%x\n", tempbx);
7306#endif
7307#endif
7308
7309 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,tempbx); /* lcdhre */ 7171 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,tempbx); /* lcdhre */
7310 7172
7311 SiS_SetGroup2_Tail(SiS_Pr, ModeNo); 7173 SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
7312 7174
7313#ifdef SIS300 7175#ifdef CONFIG_FB_SIS_300
7314 SiS_Set300Part2Regs(SiS_Pr, ModeIdIndex, RefreshRateTableIndex, ModeNo); 7176 SiS_Set300Part2Regs(SiS_Pr, ModeIdIndex, RefreshRateTableIndex, ModeNo);
7315#endif 7177#endif
7316#ifdef SIS315H 7178#ifdef CONFIG_FB_SIS_315
7317 } /* CRT2-LCD from table */ 7179 } /* CRT2-LCD from table */
7318#endif 7180#endif
7319} 7181}
@@ -7382,7 +7244,7 @@ SiS_SetGroup3(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
7382/* SET PART 4 REGISTER GROUP */ 7244/* SET PART 4 REGISTER GROUP */
7383/*********************************************/ 7245/*********************************************/
7384 7246
7385#ifdef SIS315H 7247#ifdef CONFIG_FB_SIS_315
7386#if 0 7248#if 0
7387static void 7249static void
7388SiS_ShiftXPos(struct SiS_Private *SiS_Pr, int shift) 7250SiS_ShiftXPos(struct SiS_Private *SiS_Pr, int shift)
@@ -8011,7 +7873,7 @@ SiS_SetCHTVReg(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
8011 7873
8012 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) { 7874 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
8013 7875
8014#ifdef SIS300 7876#ifdef CONFIG_FB_SIS_300
8015 7877
8016 /* Chrontel 7005 - I assume that it does not come with a 315 series chip */ 7878 /* Chrontel 7005 - I assume that it does not come with a 315 series chip */
8017 7879
@@ -8124,7 +7986,7 @@ SiS_SetCHTVReg(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
8124 7986
8125 /* Chrontel 7019 - assumed that it does not come with a 300 series chip */ 7987 /* Chrontel 7019 - assumed that it does not come with a 300 series chip */
8126 7988
8127#ifdef SIS315H 7989#ifdef CONFIG_FB_SIS_315
8128 7990
8129 unsigned short temp; 7991 unsigned short temp;
8130 7992
@@ -8175,7 +8037,7 @@ SiS_SetCHTVReg(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short
8175 8037
8176} 8038}
8177 8039
8178#ifdef SIS315H /* ----------- 315 series only ---------- */ 8040#ifdef CONFIG_FB_SIS_315 /* ----------- 315 series only ---------- */
8179 8041
8180void 8042void
8181SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr) 8043SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr)
@@ -8657,7 +8519,7 @@ SiS_ChrontelDoSomething1(struct SiS_Private *SiS_Pr)
8657bool 8519bool
8658SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo) 8520SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
8659{ 8521{
8660#ifdef SIS300 8522#ifdef CONFIG_FB_SIS_300
8661 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase; 8523 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
8662#endif 8524#endif
8663 unsigned short ModeIdIndex, RefreshRateTableIndex; 8525 unsigned short ModeIdIndex, RefreshRateTableIndex;
@@ -8703,16 +8565,6 @@ SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
8703 SiS_GetLVDSDesData(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex); 8565 SiS_GetLVDSDesData(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8704 } 8566 }
8705 8567
8706#ifdef SIS_XORG_XF86
8707#ifdef TWDEBUG
8708 xf86DrvMsg(0, X_INFO, "(init301: LCDHDES 0x%03x LCDVDES 0x%03x)\n", SiS_Pr->SiS_LCDHDES, SiS_Pr->SiS_LCDVDES);
8709 xf86DrvMsg(0, X_INFO, "(init301: HDE 0x%03x VDE 0x%03x)\n", SiS_Pr->SiS_HDE, SiS_Pr->SiS_VDE);
8710 xf86DrvMsg(0, X_INFO, "(init301: VGAHDE 0x%03x VGAVDE 0x%03x)\n", SiS_Pr->SiS_VGAHDE, SiS_Pr->SiS_VGAVDE);
8711 xf86DrvMsg(0, X_INFO, "(init301: HT 0x%03x VT 0x%03x)\n", SiS_Pr->SiS_HT, SiS_Pr->SiS_VT);
8712 xf86DrvMsg(0, X_INFO, "(init301: VGAHT 0x%03x VGAVT 0x%03x)\n", SiS_Pr->SiS_VGAHT, SiS_Pr->SiS_VGAVT);
8713#endif
8714#endif
8715
8716 if(SiS_Pr->SiS_SetFlag & LowModeTests) { 8568 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8717 SiS_SetGroup1(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex); 8569 SiS_SetGroup1(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8718 } 8570 }
@@ -8722,12 +8574,12 @@ SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
8722 if(SiS_Pr->SiS_SetFlag & LowModeTests) { 8574 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8723 8575
8724 SiS_SetGroup2(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex); 8576 SiS_SetGroup2(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8725#ifdef SIS315H 8577#ifdef CONFIG_FB_SIS_315
8726 SiS_SetGroup2_C_ELV(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex); 8578 SiS_SetGroup2_C_ELV(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8727#endif 8579#endif
8728 SiS_SetGroup3(SiS_Pr, ModeNo, ModeIdIndex); 8580 SiS_SetGroup3(SiS_Pr, ModeNo, ModeIdIndex);
8729 SiS_SetGroup4(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex); 8581 SiS_SetGroup4(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8730#ifdef SIS315H 8582#ifdef CONFIG_FB_SIS_315
8731 SiS_SetGroup4_C_ELV(SiS_Pr, ModeNo, ModeIdIndex); 8583 SiS_SetGroup4_C_ELV(SiS_Pr, ModeNo, ModeIdIndex);
8732#endif 8584#endif
8733 SiS_SetGroup5(SiS_Pr, ModeNo, ModeIdIndex); 8585 SiS_SetGroup5(SiS_Pr, ModeNo, ModeIdIndex);
@@ -8758,7 +8610,7 @@ SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
8758 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) { 8610 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
8759 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { 8611 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
8760 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) { 8612 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8761#ifdef SIS315H 8613#ifdef CONFIG_FB_SIS_315
8762 SiS_SetCH701xForLCD(SiS_Pr); 8614 SiS_SetCH701xForLCD(SiS_Pr);
8763#endif 8615#endif
8764 } 8616 }
@@ -8771,7 +8623,7 @@ SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
8771 8623
8772 } 8624 }
8773 8625
8774#ifdef SIS300 8626#ifdef CONFIG_FB_SIS_300
8775 if(SiS_Pr->ChipType < SIS_315H) { 8627 if(SiS_Pr->ChipType < SIS_315H) {
8776 if(SiS_Pr->SiS_SetFlag & LowModeTests) { 8628 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8777 if(SiS_Pr->SiS_UseOEM) { 8629 if(SiS_Pr->SiS_UseOEM) {
@@ -8794,7 +8646,7 @@ SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
8794 } 8646 }
8795#endif 8647#endif
8796 8648
8797#ifdef SIS315H 8649#ifdef CONFIG_FB_SIS_315
8798 if(SiS_Pr->ChipType >= SIS_315H) { 8650 if(SiS_Pr->ChipType >= SIS_315H) {
8799 if(SiS_Pr->SiS_SetFlag & LowModeTests) { 8651 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8800 if(SiS_Pr->ChipType < SIS_661) { 8652 if(SiS_Pr->ChipType < SIS_661) {
@@ -8873,7 +8725,7 @@ SiS_SetupDDCN(struct SiS_Private *SiS_Pr)
8873 } 8725 }
8874} 8726}
8875 8727
8876#ifdef SIS300 8728#ifdef CONFIG_FB_SIS_300
8877static unsigned char * 8729static unsigned char *
8878SiS_SetTrumpBlockLoop(struct SiS_Private *SiS_Pr, unsigned char *dataptr) 8730SiS_SetTrumpBlockLoop(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
8879{ 8731{
@@ -8923,11 +8775,6 @@ SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
8923 dataptr = SiS_SetTrumpBlockLoop(SiS_Pr, dataptr); 8775 dataptr = SiS_SetTrumpBlockLoop(SiS_Pr, dataptr);
8924 if(!dataptr) return false; 8776 if(!dataptr) return false;
8925 } 8777 }
8926#ifdef SIS_XORG_XF86
8927#ifdef TWDEBUG
8928 xf86DrvMsg(0, X_INFO, "Trumpion block success\n");
8929#endif
8930#endif
8931 return true; 8778 return true;
8932} 8779}
8933#endif 8780#endif
@@ -9002,9 +8849,7 @@ SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
9002 SiS_SetChReg(SiS_Pr, reg, val, 0); 8849 SiS_SetChReg(SiS_Pr, reg, val, 0);
9003} 8850}
9004 8851
9005#ifdef SIS_LINUX_KERNEL
9006static 8852static
9007#endif
9008void 8853void
9009SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val) 8854SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
9010{ 8855{
@@ -9091,9 +8936,7 @@ SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
9091 8936
9092/* Read from Chrontel 70xx */ 8937/* Read from Chrontel 70xx */
9093/* Parameter is [Register no (S7-S0)] */ 8938/* Parameter is [Register no (S7-S0)] */
9094#ifdef SIS_LINUX_KERNEL
9095static 8939static
9096#endif
9097unsigned short 8940unsigned short
9098SiS_GetCH70xx(struct SiS_Private *SiS_Pr, unsigned short tempbx) 8941SiS_GetCH70xx(struct SiS_Private *SiS_Pr, unsigned short tempbx)
9099{ 8942{
@@ -9114,9 +8957,7 @@ SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
9114} 8957}
9115 8958
9116/* Our own DDC functions */ 8959/* Our own DDC functions */
9117#ifndef SIS_XORG_XF86
9118static 8960static
9119#endif
9120unsigned short 8961unsigned short
9121SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine, 8962SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
9122 unsigned short adaptnum, unsigned short DDCdatatype, bool checkcr32, 8963 unsigned short adaptnum, unsigned short DDCdatatype, bool checkcr32,
@@ -9224,12 +9065,6 @@ SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
9224 9065
9225 SiS_SetupDDCN(SiS_Pr); 9066 SiS_SetupDDCN(SiS_Pr);
9226 9067
9227#ifdef SIS_XORG_XF86
9228#ifdef TWDEBUG
9229 xf86DrvMsg(0, X_INFO, "DDC Port %x Index %x Shift %d\n",
9230 SiS_Pr->SiS_DDC_Port, SiS_Pr->SiS_DDC_Index, temp);
9231#endif
9232#endif
9233 return 0; 9068 return 0;
9234} 9069}
9235 9070
@@ -9292,11 +9127,6 @@ SiS_DoProbeDDC(struct SiS_Private *SiS_Pr)
9292 SiS_SetSwitchDDC2(SiS_Pr); 9127 SiS_SetSwitchDDC2(SiS_Pr);
9293 if(SiS_PrepareDDC(SiS_Pr)) { 9128 if(SiS_PrepareDDC(SiS_Pr)) {
9294 SiS_SetStop(SiS_Pr); 9129 SiS_SetStop(SiS_Pr);
9295#ifdef SIS_XORG_XF86
9296#ifdef TWDEBUG
9297 xf86DrvMsg(0, X_INFO, "Probe: Prepare failed\n");
9298#endif
9299#endif
9300 return 0xFFFF; 9130 return 0xFFFF;
9301 } 9131 }
9302 mask = 0xf0; 9132 mask = 0xf0;
@@ -9310,11 +9140,6 @@ SiS_DoProbeDDC(struct SiS_Private *SiS_Pr)
9310 } else { 9140 } else {
9311 failed = true; 9141 failed = true;
9312 ret = 0xFFFF; 9142 ret = 0xFFFF;
9313#ifdef SIS_XORG_XF86
9314#ifdef TWDEBUG
9315 xf86DrvMsg(0, X_INFO, "Probe: Read 1 failed\n");
9316#endif
9317#endif
9318 } 9143 }
9319 } 9144 }
9320 if(!failed) { 9145 if(!failed) {
@@ -9324,11 +9149,6 @@ SiS_DoProbeDDC(struct SiS_Private *SiS_Pr)
9324 if(temp == value) ret = 0; 9149 if(temp == value) ret = 0;
9325 else { 9150 else {
9326 ret = 0xFFFF; 9151 ret = 0xFFFF;
9327#ifdef SIS_XORG_XF86
9328#ifdef TWDEBUG
9329 xf86DrvMsg(0, X_INFO, "Probe: Read 2 failed\n");
9330#endif
9331#endif
9332 if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) { 9152 if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
9333 if(temp == 0x30) ret = 0; 9153 if(temp == 0x30) ret = 0;
9334 } 9154 }
@@ -9338,9 +9158,7 @@ SiS_DoProbeDDC(struct SiS_Private *SiS_Pr)
9338 return ret; 9158 return ret;
9339} 9159}
9340 9160
9341#ifndef SIS_XORG_XF86
9342static 9161static
9343#endif
9344unsigned short 9162unsigned short
9345SiS_ProbeDDC(struct SiS_Private *SiS_Pr) 9163SiS_ProbeDDC(struct SiS_Private *SiS_Pr)
9346{ 9164{
@@ -9357,9 +9175,7 @@ SiS_ProbeDDC(struct SiS_Private *SiS_Pr)
9357 return flag; 9175 return flag;
9358} 9176}
9359 9177
9360#ifndef SIS_XORG_XF86
9361static 9178static
9362#endif
9363unsigned short 9179unsigned short
9364SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype, unsigned char *buffer) 9180SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype, unsigned char *buffer)
9365{ 9181{
@@ -9606,11 +9422,6 @@ SiS_SetSCLKHigh(struct SiS_Private *SiS_Pr)
9606 temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index); 9422 temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
9607 } while((!(temp & SiS_Pr->SiS_DDC_Clk)) && --watchdog); 9423 } while((!(temp & SiS_Pr->SiS_DDC_Clk)) && --watchdog);
9608 if (!watchdog) { 9424 if (!watchdog) {
9609#ifdef SIS_XORG_XF86
9610#ifdef TWDEBUG
9611 xf86DrvMsg(0, X_INFO, "SetClkHigh failed\n");
9612#endif
9613#endif
9614 return 0xFFFF; 9425 return 0xFFFF;
9615 } 9426 }
9616 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT); 9427 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
@@ -9641,7 +9452,7 @@ SiS_CheckACK(struct SiS_Private *SiS_Pr)
9641 9452
9642/* =============== SiS 315/330 O.E.M. ================= */ 9453/* =============== SiS 315/330 O.E.M. ================= */
9643 9454
9644#ifdef SIS315H 9455#ifdef CONFIG_FB_SIS_315
9645 9456
9646static unsigned short 9457static unsigned short
9647GetRAMDACromptr(struct SiS_Private *SiS_Pr) 9458GetRAMDACromptr(struct SiS_Private *SiS_Pr)
@@ -10829,7 +10640,7 @@ SiS_FinalizeLCD(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned shor
10829 10640
10830/* ================= SiS 300 O.E.M. ================== */ 10641/* ================= SiS 300 O.E.M. ================== */
10831 10642
10832#ifdef SIS300 10643#ifdef CONFIG_FB_SIS_300
10833 10644
10834static void 10645static void
10835SetOEMLCDData2(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex, 10646SetOEMLCDData2(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
diff --git a/drivers/video/sis/init301.h b/drivers/video/sis/init301.h
index 51d99222375d..2112d6d7feda 100644
--- a/drivers/video/sis/init301.h
+++ b/drivers/video/sis/init301.h
@@ -53,15 +53,8 @@
53#ifndef _INIT301_H_ 53#ifndef _INIT301_H_
54#define _INIT301_H_ 54#define _INIT301_H_
55 55
56#include "osdef.h"
57#include "initdef.h" 56#include "initdef.h"
58 57
59#ifdef SIS_XORG_XF86
60#include "sis.h"
61#include "sis_regs.h"
62#endif
63
64#ifdef SIS_LINUX_KERNEL
65#include "vgatypes.h" 58#include "vgatypes.h"
66#include "vstruct.h" 59#include "vstruct.h"
67#ifdef SIS_CP 60#ifdef SIS_CP
@@ -72,7 +65,6 @@
72#include <linux/fb.h> 65#include <linux/fb.h>
73#include "sis.h" 66#include "sis.h"
74#include <video/sisfb.h> 67#include <video/sisfb.h>
75#endif
76 68
77static const unsigned char SiS_YPbPrTable[3][64] = { 69static const unsigned char SiS_YPbPrTable[3][64] = {
78 { 70 {
@@ -237,7 +229,7 @@ static const unsigned char SiS_Part2CLVX_6[] = { /* 1080i */
237 0xFF,0xFF, 229 0xFF,0xFF,
238}; 230};
239 231
240#ifdef SIS315H 232#ifdef CONFIG_FB_SIS_315
241/* 661 et al LCD data structure (2.03.00) */ 233/* 661 et al LCD data structure (2.03.00) */
242static const unsigned char SiS_LCDStruct661[] = { 234static const unsigned char SiS_LCDStruct661[] = {
243 /* 1024x768 */ 235 /* 1024x768 */
@@ -279,7 +271,7 @@ static const unsigned char SiS_LCDStruct661[] = {
279}; 271};
280#endif 272#endif
281 273
282#ifdef SIS300 274#ifdef CONFIG_FB_SIS_300
283static unsigned char SiS300_TrumpionData[14][80] = { 275static unsigned char SiS300_TrumpionData[14][80] = {
284 { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02, 276 { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
285 0x20,0x03,0x0B,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x10,0x00,0x00,0x04,0x23, 277 0x20,0x03,0x0B,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x10,0x00,0x00,0x04,0x23,
@@ -356,9 +348,6 @@ static unsigned char SiS300_TrumpionData[14][80] = {
356#endif 348#endif
357 349
358void SiS_UnLockCRT2(struct SiS_Private *SiS_Pr); 350void SiS_UnLockCRT2(struct SiS_Private *SiS_Pr);
359#ifndef SIS_LINUX_KERNEL
360void SiS_LockCRT2(struct SiS_Private *SiS_Pr);
361#endif
362void SiS_EnableCRT2(struct SiS_Private *SiS_Pr); 351void SiS_EnableCRT2(struct SiS_Private *SiS_Pr);
363unsigned short SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex); 352unsigned short SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
364void SiS_WaitRetrace1(struct SiS_Private *SiS_Pr); 353void SiS_WaitRetrace1(struct SiS_Private *SiS_Pr);
@@ -375,9 +364,6 @@ unsigned short SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo
375 unsigned short RefreshRateTableIndex); 364 unsigned short RefreshRateTableIndex);
376unsigned short SiS_GetResInfo(struct SiS_Private *SiS_Pr,unsigned short ModeNo,unsigned short ModeIdIndex); 365unsigned short SiS_GetResInfo(struct SiS_Private *SiS_Pr,unsigned short ModeNo,unsigned short ModeIdIndex);
377void SiS_DisableBridge(struct SiS_Private *SiS_Pr); 366void SiS_DisableBridge(struct SiS_Private *SiS_Pr);
378#ifndef SIS_LINUX_KERNEL
379void SiS_EnableBridge(struct SiS_Private *SiS_Pr);
380#endif
381bool SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo); 367bool SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
382void SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr); 368void SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr);
383void SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr); 369void SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr);
@@ -386,13 +372,9 @@ void SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned cha
386unsigned short SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempax); 372unsigned short SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempax);
387void SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val); 373void SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
388unsigned short SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short tempax); 374unsigned short SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short tempax);
389#ifndef SIS_LINUX_KERNEL
390void SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
391unsigned short SiS_GetCH70xx(struct SiS_Private *SiS_Pr, unsigned short tempax);
392#endif
393void SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg, 375void SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
394 unsigned char orval,unsigned short andval); 376 unsigned char orval,unsigned short andval);
395#ifdef SIS315H 377#ifdef CONFIG_FB_SIS_315
396static void SiS_Chrontel701xOn(struct SiS_Private *SiS_Pr); 378static void SiS_Chrontel701xOn(struct SiS_Private *SiS_Pr);
397static void SiS_Chrontel701xOff(struct SiS_Private *SiS_Pr); 379static void SiS_Chrontel701xOff(struct SiS_Private *SiS_Pr);
398static void SiS_ChrontelInitTVVSync(struct SiS_Private *SiS_Pr); 380static void SiS_ChrontelInitTVVSync(struct SiS_Private *SiS_Pr);
@@ -401,7 +383,7 @@ void SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr);
401void SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr); 383void SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr);
402#endif /* 315 */ 384#endif /* 315 */
403 385
404#ifdef SIS300 386#ifdef CONFIG_FB_SIS_300
405static bool SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr); 387static bool SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr);
406void SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo); 388void SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo);
407#endif 389#endif
@@ -412,21 +394,12 @@ unsigned short SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, i
412 unsigned short adaptnum, unsigned short DDCdatatype, 394 unsigned short adaptnum, unsigned short DDCdatatype,
413 unsigned char *buffer, unsigned int VBFlags2); 395 unsigned char *buffer, unsigned int VBFlags2);
414 396
415#ifdef SIS_XORG_XF86
416unsigned short SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags,
417 int VGAEngine, unsigned short adaptnum, unsigned short DDCdatatype,
418 bool checkcr32, unsigned int VBFlags2);
419unsigned short SiS_ProbeDDC(struct SiS_Private *SiS_Pr);
420unsigned short SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype,
421 unsigned char *buffer);
422#else
423static unsigned short SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags, 397static unsigned short SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags,
424 int VGAEngine, unsigned short adaptnum, unsigned short DDCdatatype, 398 int VGAEngine, unsigned short adaptnum, unsigned short DDCdatatype,
425 bool checkcr32, unsigned int VBFlags2); 399 bool checkcr32, unsigned int VBFlags2);
426static unsigned short SiS_ProbeDDC(struct SiS_Private *SiS_Pr); 400static unsigned short SiS_ProbeDDC(struct SiS_Private *SiS_Pr);
427static unsigned short SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype, 401static unsigned short SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype,
428 unsigned char *buffer); 402 unsigned char *buffer);
429#endif
430static void SiS_SetSwitchDDC2(struct SiS_Private *SiS_Pr); 403static void SiS_SetSwitchDDC2(struct SiS_Private *SiS_Pr);
431static unsigned short SiS_SetStart(struct SiS_Private *SiS_Pr); 404static unsigned short SiS_SetStart(struct SiS_Private *SiS_Pr);
432static unsigned short SiS_SetStop(struct SiS_Private *SiS_Pr); 405static unsigned short SiS_SetStop(struct SiS_Private *SiS_Pr);
@@ -441,13 +414,13 @@ static unsigned short SiS_PrepareDDC(struct SiS_Private *SiS_Pr);
441static void SiS_SendACK(struct SiS_Private *SiS_Pr, unsigned short yesno); 414static void SiS_SendACK(struct SiS_Private *SiS_Pr, unsigned short yesno);
442static unsigned short SiS_DoProbeDDC(struct SiS_Private *SiS_Pr); 415static unsigned short SiS_DoProbeDDC(struct SiS_Private *SiS_Pr);
443 416
444#ifdef SIS300 417#ifdef CONFIG_FB_SIS_300
445static void SiS_OEM300Setting(struct SiS_Private *SiS_Pr, 418static void SiS_OEM300Setting(struct SiS_Private *SiS_Pr,
446 unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefTabindex); 419 unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefTabindex);
447static void SetOEMLCDData2(struct SiS_Private *SiS_Pr, 420static void SetOEMLCDData2(struct SiS_Private *SiS_Pr,
448 unsigned short ModeNo, unsigned short ModeIdIndex,unsigned short RefTableIndex); 421 unsigned short ModeNo, unsigned short ModeIdIndex,unsigned short RefTableIndex);
449#endif 422#endif
450#ifdef SIS315H 423#ifdef CONFIG_FB_SIS_315
451static void SiS_OEM310Setting(struct SiS_Private *SiS_Pr, 424static void SiS_OEM310Setting(struct SiS_Private *SiS_Pr,
452 unsigned short ModeNo,unsigned short ModeIdIndex, unsigned short RRTI); 425 unsigned short ModeNo,unsigned short ModeIdIndex, unsigned short RRTI);
453static void SiS_OEM661Setting(struct SiS_Private *SiS_Pr, 426static void SiS_OEM661Setting(struct SiS_Private *SiS_Pr,
@@ -455,17 +428,6 @@ static void SiS_OEM661Setting(struct SiS_Private *SiS_Pr,
455static void SiS_FinalizeLCD(struct SiS_Private *, unsigned short, unsigned short); 428static void SiS_FinalizeLCD(struct SiS_Private *, unsigned short, unsigned short);
456#endif 429#endif
457 430
458extern void SiS_SetReg(SISIOADDRESS, unsigned short, unsigned short);
459extern void SiS_SetRegByte(SISIOADDRESS, unsigned short);
460extern void SiS_SetRegShort(SISIOADDRESS, unsigned short);
461extern void SiS_SetRegLong(SISIOADDRESS, unsigned int);
462extern unsigned char SiS_GetReg(SISIOADDRESS, unsigned short);
463extern unsigned char SiS_GetRegByte(SISIOADDRESS);
464extern unsigned short SiS_GetRegShort(SISIOADDRESS);
465extern unsigned int SiS_GetRegLong(SISIOADDRESS);
466extern void SiS_SetRegANDOR(SISIOADDRESS, unsigned short, unsigned short, unsigned short);
467extern void SiS_SetRegOR(SISIOADDRESS, unsigned short, unsigned short);
468extern void SiS_SetRegAND(SISIOADDRESS, unsigned short, unsigned short);
469extern void SiS_DisplayOff(struct SiS_Private *SiS_Pr); 431extern void SiS_DisplayOff(struct SiS_Private *SiS_Pr);
470extern void SiS_DisplayOn(struct SiS_Private *SiS_Pr); 432extern void SiS_DisplayOn(struct SiS_Private *SiS_Pr);
471extern bool SiS_SearchModeID(struct SiS_Private *, unsigned short *, unsigned short *); 433extern bool SiS_SearchModeID(struct SiS_Private *, unsigned short *, unsigned short *);
@@ -482,15 +444,13 @@ extern void SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short M
482extern void SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth); 444extern void SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth);
483extern unsigned short SiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide); 445extern unsigned short SiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
484extern unsigned short SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide); 446extern unsigned short SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
485#ifdef SIS300 447#ifdef CONFIG_FB_SIS_300
486extern void SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *tempbx, 448extern void SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *tempbx,
487 unsigned short *tempcl); 449 unsigned short *tempcl);
488extern unsigned short SiS_GetFIFOThresholdB300(unsigned short tempbx, unsigned short tempcl); 450extern unsigned short SiS_GetFIFOThresholdB300(unsigned short tempbx, unsigned short tempcl);
489extern unsigned short SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index); 451extern unsigned short SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index);
490#ifdef SIS_LINUX_KERNEL
491extern unsigned int sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg); 452extern unsigned int sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg);
492extern unsigned int sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg); 453extern unsigned int sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg);
493#endif 454#endif
494#endif
495 455
496#endif 456#endif
diff --git a/drivers/video/sis/initextlfb.c b/drivers/video/sis/initextlfb.c
index 99c04a4855d1..9dec64da4015 100644
--- a/drivers/video/sis/initextlfb.c
+++ b/drivers/video/sis/initextlfb.c
@@ -25,7 +25,6 @@
25 * Author: Thomas Winischhofer <thomas@winischhofer.net> 25 * Author: Thomas Winischhofer <thomas@winischhofer.net>
26 */ 26 */
27 27
28#include "osdef.h"
29#include "initdef.h" 28#include "initdef.h"
30#include "vgatypes.h" 29#include "vgatypes.h"
31#include "vstruct.h" 30#include "vstruct.h"
@@ -59,7 +58,7 @@ sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr, unsigned char modeno,
59 58
60 if(rateindex > 0) rateindex--; 59 if(rateindex > 0) rateindex--;
61 60
62#ifdef SIS315H 61#ifdef CONFIG_FB_SIS_315
63 switch(ModeNo) { 62 switch(ModeNo) {
64 case 0x5a: ModeNo = 0x50; break; 63 case 0x5a: ModeNo = 0x50; break;
65 case 0x5b: ModeNo = 0x56; 64 case 0x5b: ModeNo = 0x56;
@@ -103,7 +102,7 @@ sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno,
103 102
104 if(rateindex > 0) rateindex--; 103 if(rateindex > 0) rateindex--;
105 104
106#ifdef SIS315H 105#ifdef CONFIG_FB_SIS_315
107 switch(ModeNo) { 106 switch(ModeNo) {
108 case 0x5a: ModeNo = 0x50; break; 107 case 0x5a: ModeNo = 0x50; break;
109 case 0x5b: ModeNo = 0x56; 108 case 0x5b: ModeNo = 0x56;
@@ -187,7 +186,7 @@ sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno, int *ht
187 186
188 if(rateindex > 0) rateindex--; 187 if(rateindex > 0) rateindex--;
189 188
190#ifdef SIS315H 189#ifdef CONFIG_FB_SIS_315
191 switch(ModeNo) { 190 switch(ModeNo) {
192 case 0x5a: ModeNo = 0x50; break; 191 case 0x5a: ModeNo = 0x50; break;
193 case 0x5b: ModeNo = 0x56; 192 case 0x5b: ModeNo = 0x56;
diff --git a/drivers/video/sis/osdef.h b/drivers/video/sis/osdef.h
deleted file mode 100644
index 6ff8f988a1a7..000000000000
--- a/drivers/video/sis/osdef.h
+++ /dev/null
@@ -1,133 +0,0 @@
1/* $XFree86$ */
2/* $XdotOrg$ */
3/*
4 * OS depending defines
5 *
6 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
7 *
8 * If distributed as part of the Linux kernel, the following license terms
9 * apply:
10 *
11 * * This program is free software; you can redistribute it and/or modify
12 * * it under the terms of the GNU General Public License as published by
13 * * the Free Software Foundation; either version 2 of the named License,
14 * * or any later version.
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 * * You should have received a copy of the GNU General Public License
22 * * along with this program; if not, write to the Free Software
23 * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
24 *
25 * Otherwise, the following license terms apply:
26 *
27 * * Redistribution and use in source and binary forms, with or without
28 * * modification, are permitted provided that the following conditions
29 * * are met:
30 * * 1) Redistributions of source code must retain the above copyright
31 * * notice, this list of conditions and the following disclaimer.
32 * * 2) Redistributions in binary form must reproduce the above copyright
33 * * notice, this list of conditions and the following disclaimer in the
34 * * documentation and/or other materials provided with the distribution.
35 * * 3) The name of the author may not be used to endorse or promote products
36 * * derived from this software without specific prior written permission.
37 * *
38 * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
39 * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
40 * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
41 * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
42 * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
43 * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
44 * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
45 * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46 * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
47 * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48 *
49 * Author: Thomas Winischhofer <thomas@winischhofer.net>
50 * Silicon Integrated Systems, Inc. (used by permission)
51 *
52 */
53
54#ifndef _SIS_OSDEF_H_
55#define _SIS_OSDEF_H_
56
57/* The choices are: */
58#define SIS_LINUX_KERNEL /* Linux kernel framebuffer */
59#undef SIS_XORG_XF86 /* XFree86/X.org */
60
61#ifdef OutPortByte
62#undef OutPortByte
63#endif
64
65#ifdef OutPortWord
66#undef OutPortWord
67#endif
68
69#ifdef OutPortLong
70#undef OutPortLong
71#endif
72
73#ifdef InPortByte
74#undef InPortByte
75#endif
76
77#ifdef InPortWord
78#undef InPortWord
79#endif
80
81#ifdef InPortLong
82#undef InPortLong
83#endif
84
85/**********************************************************************/
86/* LINUX KERNEL */
87/**********************************************************************/
88
89#ifdef SIS_LINUX_KERNEL
90
91#ifdef CONFIG_FB_SIS_300
92#define SIS300
93#endif
94
95#ifdef CONFIG_FB_SIS_315
96#define SIS315H
97#endif
98
99#if !defined(SIS300) && !defined(SIS315H)
100#warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
101#warning sisfb will not work!
102#endif
103
104#define OutPortByte(p,v) outb((u8)(v),(SISIOADDRESS)(p))
105#define OutPortWord(p,v) outw((u16)(v),(SISIOADDRESS)(p))
106#define OutPortLong(p,v) outl((u32)(v),(SISIOADDRESS)(p))
107#define InPortByte(p) inb((SISIOADDRESS)(p))
108#define InPortWord(p) inw((SISIOADDRESS)(p))
109#define InPortLong(p) inl((SISIOADDRESS)(p))
110#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset_io(MemoryAddress, value, MemorySize)
111
112#endif /* LINUX_KERNEL */
113
114/**********************************************************************/
115/* XFree86/X.org */
116/**********************************************************************/
117
118#ifdef SIS_XORG_XF86
119
120#define SIS300
121#define SIS315H
122
123#define OutPortByte(p,v) outSISREG((IOADDRESS)(p),(CARD8)(v))
124#define OutPortWord(p,v) outSISREGW((IOADDRESS)(p),(CARD16)(v))
125#define OutPortLong(p,v) outSISREGL((IOADDRESS)(p),(CARD32)(v))
126#define InPortByte(p) inSISREG((IOADDRESS)(p))
127#define InPortWord(p) inSISREGW((IOADDRESS)(p))
128#define InPortLong(p) inSISREGL((IOADDRESS)(p))
129#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
130
131#endif /* XF86 */
132
133#endif /* _OSDEF_H_ */
diff --git a/drivers/video/sis/sis.h b/drivers/video/sis/sis.h
index 7c5710e3fb56..1987f1b7212f 100644
--- a/drivers/video/sis/sis.h
+++ b/drivers/video/sis/sis.h
@@ -24,7 +24,6 @@
24#ifndef _SIS_H_ 24#ifndef _SIS_H_
25#define _SIS_H_ 25#define _SIS_H_
26 26
27#include "osdef.h"
28#include <video/sisfb.h> 27#include <video/sisfb.h>
29 28
30#include "vgatypes.h" 29#include "vgatypes.h"
@@ -308,58 +307,19 @@
308#define VB2_LCDOVER1600BRIDGE (VB2_307T | VB2_307LV) 307#define VB2_LCDOVER1600BRIDGE (VB2_307T | VB2_307LV)
309#define VB2_RAMDAC202MHZBRIDGE (VB2_301C | VB2_307T) 308#define VB2_RAMDAC202MHZBRIDGE (VB2_301C | VB2_307T)
310 309
311/* I/O port access macros */ 310/* I/O port access functions */
312#define inSISREG(base) inb(base) 311
313 312void SiS_SetReg(SISIOADDRESS, u8, u8);
314#define outSISREG(base,val) outb(val,base) 313void SiS_SetRegByte(SISIOADDRESS, u8);
315 314void SiS_SetRegShort(SISIOADDRESS, u16);
316#define orSISREG(base,val) \ 315void SiS_SetRegLong(SISIOADDRESS, u32);
317 do { \ 316void SiS_SetRegANDOR(SISIOADDRESS, u8, u8, u8);
318 u8 __Temp = inSISREG(base); \ 317void SiS_SetRegAND(SISIOADDRESS, u8, u8);
319 outSISREG(base, __Temp | (val));\ 318void SiS_SetRegOR(SISIOADDRESS, u8, u8);
320 } while (0) 319u8 SiS_GetReg(SISIOADDRESS, u8);
321 320u8 SiS_GetRegByte(SISIOADDRESS);
322#define andSISREG(base,val) \ 321u16 SiS_GetRegShort(SISIOADDRESS);
323 do { \ 322u32 SiS_GetRegLong(SISIOADDRESS);
324 u8 __Temp = inSISREG(base); \
325 outSISREG(base, __Temp & (val));\
326 } while (0)
327
328#define inSISIDXREG(base,idx,var) \
329 do { \
330 outSISREG(base, idx); \
331 var = inSISREG((base)+1); \
332 } while (0)
333
334#define outSISIDXREG(base,idx,val) \
335 do { \
336 outSISREG(base, idx); \
337 outSISREG((base)+1, val); \
338 } while (0)
339
340#define orSISIDXREG(base,idx,val) \
341 do { \
342 u8 __Temp; \
343 outSISREG(base, idx); \
344 __Temp = inSISREG((base)+1) | (val); \
345 outSISREG((base)+1, __Temp); \
346 } while (0)
347
348#define andSISIDXREG(base,idx,and) \
349 do { \
350 u8 __Temp; \
351 outSISREG(base, idx); \
352 __Temp = inSISREG((base)+1) & (and); \
353 outSISREG((base)+1, __Temp); \
354 } while (0)
355
356#define setSISIDXREG(base,idx,and,or) \
357 do { \
358 u8 __Temp; \
359 outSISREG(base, idx); \
360 __Temp = (inSISREG((base)+1) & (and)) | (or); \
361 outSISREG((base)+1, __Temp); \
362 } while (0)
363 323
364/* MMIO access macros */ 324/* MMIO access macros */
365#define MMIO_IN8(base, offset) readb((base+offset)) 325#define MMIO_IN8(base, offset) readb((base+offset))
@@ -535,6 +495,7 @@ struct sis_video_info {
535 unsigned int refresh_rate; 495 unsigned int refresh_rate;
536 496
537 unsigned int chip; 497 unsigned int chip;
498 unsigned int chip_real_id;
538 u8 revision_id; 499 u8 revision_id;
539 int sisvga_enabled; /* PCI device was enabled */ 500 int sisvga_enabled; /* PCI device was enabled */
540 501
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index b52f8e4ef1fd..75259845933d 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -60,6 +60,11 @@
60#include "sis.h" 60#include "sis.h"
61#include "sis_main.h" 61#include "sis_main.h"
62 62
63#if !defined(CONFIG_FB_SIS_300) && !defined(CONFIG_FB_SIS_315)
64#warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
65#warning sisfb will not work!
66#endif
67
63static void sisfb_handle_command(struct sis_video_info *ivideo, 68static void sisfb_handle_command(struct sis_video_info *ivideo,
64 struct sisfb_cmd *sisfb_command); 69 struct sisfb_cmd *sisfb_command);
65 70
@@ -732,7 +737,7 @@ sisfb_bridgeisslave(struct sis_video_info *ivideo)
732 if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) 737 if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
733 return false; 738 return false;
734 739
735 inSISIDXREG(SISPART1,0x00,P1_00); 740 P1_00 = SiS_GetReg(SISPART1, 0x00);
736 if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) || 741 if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
737 ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) { 742 ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
738 return true; 743 return true;
@@ -746,11 +751,11 @@ sisfballowretracecrt1(struct sis_video_info *ivideo)
746{ 751{
747 u8 temp; 752 u8 temp;
748 753
749 inSISIDXREG(SISCR,0x17,temp); 754 temp = SiS_GetReg(SISCR, 0x17);
750 if(!(temp & 0x80)) 755 if(!(temp & 0x80))
751 return false; 756 return false;
752 757
753 inSISIDXREG(SISSR,0x1f,temp); 758 temp = SiS_GetReg(SISSR, 0x1f);
754 if(temp & 0xc0) 759 if(temp & 0xc0)
755 return false; 760 return false;
756 761
@@ -763,7 +768,7 @@ sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
763 if(!sisfballowretracecrt1(ivideo)) 768 if(!sisfballowretracecrt1(ivideo))
764 return false; 769 return false;
765 770
766 if(inSISREG(SISINPSTAT) & 0x08) 771 if (SiS_GetRegByte(SISINPSTAT) & 0x08)
767 return true; 772 return true;
768 else 773 else
769 return false; 774 return false;
@@ -778,9 +783,9 @@ sisfbwaitretracecrt1(struct sis_video_info *ivideo)
778 return; 783 return;
779 784
780 watchdog = 65536; 785 watchdog = 65536;
781 while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog); 786 while ((!(SiS_GetRegByte(SISINPSTAT) & 0x08)) && --watchdog);
782 watchdog = 65536; 787 watchdog = 65536;
783 while((inSISREG(SISINPSTAT) & 0x08) && --watchdog); 788 while ((SiS_GetRegByte(SISINPSTAT) & 0x08) && --watchdog);
784} 789}
785 790
786static bool 791static bool
@@ -794,7 +799,7 @@ sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
794 default: return false; 799 default: return false;
795 } 800 }
796 801
797 inSISIDXREG(SISPART1, reg, temp); 802 temp = SiS_GetReg(SISPART1, reg);
798 if(temp & 0x02) 803 if(temp & 0x02)
799 return true; 804 return true;
800 else 805 else
@@ -832,10 +837,10 @@ sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
832 default: 837 default:
833 case SIS_315_VGA: idx = 0x30; break; 838 case SIS_315_VGA: idx = 0x30; break;
834 } 839 }
835 inSISIDXREG(SISPART1,(idx+0),reg1); /* 30 */ 840 reg1 = SiS_GetReg(SISPART1, (idx+0)); /* 30 */
836 inSISIDXREG(SISPART1,(idx+1),reg2); /* 31 */ 841 reg2 = SiS_GetReg(SISPART1, (idx+1)); /* 31 */
837 inSISIDXREG(SISPART1,(idx+2),reg3); /* 32 */ 842 reg3 = SiS_GetReg(SISPART1, (idx+2)); /* 32 */
838 inSISIDXREG(SISPART1,(idx+3),reg4); /* 33 */ 843 reg4 = SiS_GetReg(SISPART1, (idx+3)); /* 33 */
839 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING; 844 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
840 if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING; 845 if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
841 if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING; 846 if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
@@ -848,13 +853,13 @@ sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
848 FB_VBLANK_HAVE_VBLANK | 853 FB_VBLANK_HAVE_VBLANK |
849 FB_VBLANK_HAVE_VCOUNT | 854 FB_VBLANK_HAVE_VCOUNT |
850 FB_VBLANK_HAVE_HCOUNT); 855 FB_VBLANK_HAVE_HCOUNT);
851 reg1 = inSISREG(SISINPSTAT); 856 reg1 = SiS_GetRegByte(SISINPSTAT);
852 if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING; 857 if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
853 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING; 858 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
854 inSISIDXREG(SISCR,0x20,reg1); 859 reg1 = SiS_GetReg(SISCR, 0x20);
855 inSISIDXREG(SISCR,0x1b,reg1); 860 reg1 = SiS_GetReg(SISCR, 0x1b);
856 inSISIDXREG(SISCR,0x1c,reg2); 861 reg2 = SiS_GetReg(SISCR, 0x1c);
857 inSISIDXREG(SISCR,0x1d,reg3); 862 reg3 = SiS_GetReg(SISCR, 0x1d);
858 (*vcount) = reg2 | ((reg3 & 0x07) << 8); 863 (*vcount) = reg2 | ((reg3 & 0x07) << 8);
859 (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3; 864 (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
860 } 865 }
@@ -925,12 +930,12 @@ sisfb_myblank(struct sis_video_info *ivideo, int blank)
925 (ivideo->sisfb_thismonitor.feature & 0xe0))) { 930 (ivideo->sisfb_thismonitor.feature & 0xe0))) {
926 931
927 if(ivideo->sisvga_engine == SIS_315_VGA) { 932 if(ivideo->sisvga_engine == SIS_315_VGA) {
928 setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63); 933 SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
929 } 934 }
930 935
931 if(!(sisfb_bridgeisslave(ivideo))) { 936 if(!(sisfb_bridgeisslave(ivideo))) {
932 setSISIDXREG(SISSR, 0x01, ~0x20, sr01); 937 SiS_SetRegANDOR(SISSR, 0x01, ~0x20, sr01);
933 setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f); 938 SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, sr1f);
934 } 939 }
935 } 940 }
936 941
@@ -960,25 +965,25 @@ sisfb_myblank(struct sis_video_info *ivideo, int blank)
960 (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) || 965 (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) ||
961 ((ivideo->sisvga_engine == SIS_315_VGA) && 966 ((ivideo->sisvga_engine == SIS_315_VGA) &&
962 ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) { 967 ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) {
963 setSISIDXREG(SISSR, 0x11, ~0x0c, sr11); 968 SiS_SetRegANDOR(SISSR, 0x11, ~0x0c, sr11);
964 } 969 }
965 970
966 if(ivideo->sisvga_engine == SIS_300_VGA) { 971 if(ivideo->sisvga_engine == SIS_300_VGA) {
967 if((ivideo->vbflags2 & VB2_30xB) && 972 if((ivideo->vbflags2 & VB2_30xB) &&
968 (!(ivideo->vbflags2 & VB2_30xBDH))) { 973 (!(ivideo->vbflags2 & VB2_30xBDH))) {
969 setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13); 974 SiS_SetRegANDOR(SISPART1, 0x13, 0x3f, p1_13);
970 } 975 }
971 } else if(ivideo->sisvga_engine == SIS_315_VGA) { 976 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
972 if((ivideo->vbflags2 & VB2_30xB) && 977 if((ivideo->vbflags2 & VB2_30xB) &&
973 (!(ivideo->vbflags2 & VB2_30xBDH))) { 978 (!(ivideo->vbflags2 & VB2_30xBDH))) {
974 setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); 979 SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
975 } 980 }
976 } 981 }
977 982
978 } else if(ivideo->currentvbflags & CRT2_VGA) { 983 } else if(ivideo->currentvbflags & CRT2_VGA) {
979 984
980 if(ivideo->vbflags2 & VB2_30xB) { 985 if(ivideo->vbflags2 & VB2_30xB) {
981 setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); 986 SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
982 } 987 }
983 988
984 } 989 }
@@ -1109,15 +1114,15 @@ sisfb_set_pitch(struct sis_video_info *ivideo)
1109 1114
1110 /* We need to set pitch for CRT1 if bridge is in slave mode, too */ 1115 /* We need to set pitch for CRT1 if bridge is in slave mode, too */
1111 if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) { 1116 if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
1112 outSISIDXREG(SISCR,0x13,(HDisplay1 & 0xFF)); 1117 SiS_SetReg(SISCR, 0x13, (HDisplay1 & 0xFF));
1113 setSISIDXREG(SISSR,0x0E,0xF0,(HDisplay1 >> 8)); 1118 SiS_SetRegANDOR(SISSR, 0x0E, 0xF0, (HDisplay1 >> 8));
1114 } 1119 }
1115 1120
1116 /* We must not set the pitch for CRT2 if bridge is in slave mode */ 1121 /* We must not set the pitch for CRT2 if bridge is in slave mode */
1117 if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) { 1122 if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
1118 orSISIDXREG(SISPART1,ivideo->CRT2_write_enable,0x01); 1123 SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
1119 outSISIDXREG(SISPART1,0x07,(HDisplay2 & 0xFF)); 1124 SiS_SetReg(SISPART1, 0x07, (HDisplay2 & 0xFF));
1120 setSISIDXREG(SISPART1,0x09,0xF0,(HDisplay2 >> 8)); 1125 SiS_SetRegANDOR(SISPART1, 0x09, 0xF0, (HDisplay2 >> 8));
1121 } 1126 }
1122} 1127}
1123 1128
@@ -1162,7 +1167,7 @@ sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
1162 /* >=2.6.12's fbcon clears the screen anyway */ 1167 /* >=2.6.12's fbcon clears the screen anyway */
1163 modeno |= 0x80; 1168 modeno |= 0x80;
1164 1169
1165 outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD); 1170 SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1166 1171
1167 sisfb_pre_setmode(ivideo); 1172 sisfb_pre_setmode(ivideo);
1168 1173
@@ -1171,7 +1176,7 @@ sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
1171 return -EINVAL; 1176 return -EINVAL;
1172 } 1177 }
1173 1178
1174 outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD); 1179 SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1175 1180
1176 sisfb_post_setmode(ivideo); 1181 sisfb_post_setmode(ivideo);
1177 1182
@@ -1303,13 +1308,13 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
1303static void 1308static void
1304sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base) 1309sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base)
1305{ 1310{
1306 outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD); 1311 SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1307 1312
1308 outSISIDXREG(SISCR, 0x0D, base & 0xFF); 1313 SiS_SetReg(SISCR, 0x0D, base & 0xFF);
1309 outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); 1314 SiS_SetReg(SISCR, 0x0C, (base >> 8) & 0xFF);
1310 outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF); 1315 SiS_SetReg(SISSR, 0x0D, (base >> 16) & 0xFF);
1311 if(ivideo->sisvga_engine == SIS_315_VGA) { 1316 if(ivideo->sisvga_engine == SIS_315_VGA) {
1312 setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01); 1317 SiS_SetRegANDOR(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
1313 } 1318 }
1314} 1319}
1315 1320
@@ -1317,12 +1322,12 @@ static void
1317sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base) 1322sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
1318{ 1323{
1319 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { 1324 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1320 orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01); 1325 SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
1321 outSISIDXREG(SISPART1, 0x06, (base & 0xFF)); 1326 SiS_SetReg(SISPART1, 0x06, (base & 0xFF));
1322 outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF)); 1327 SiS_SetReg(SISPART1, 0x05, ((base >> 8) & 0xFF));
1323 outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF)); 1328 SiS_SetReg(SISPART1, 0x04, ((base >> 16) & 0xFF));
1324 if(ivideo->sisvga_engine == SIS_315_VGA) { 1329 if(ivideo->sisvga_engine == SIS_315_VGA) {
1325 setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7); 1330 SiS_SetRegANDOR(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1326 } 1331 }
1327 } 1332 }
1328} 1333}
@@ -1383,15 +1388,15 @@ sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
1383 1388
1384 switch(info->var.bits_per_pixel) { 1389 switch(info->var.bits_per_pixel) {
1385 case 8: 1390 case 8:
1386 outSISREG(SISDACA, regno); 1391 SiS_SetRegByte(SISDACA, regno);
1387 outSISREG(SISDACD, (red >> 10)); 1392 SiS_SetRegByte(SISDACD, (red >> 10));
1388 outSISREG(SISDACD, (green >> 10)); 1393 SiS_SetRegByte(SISDACD, (green >> 10));
1389 outSISREG(SISDACD, (blue >> 10)); 1394 SiS_SetRegByte(SISDACD, (blue >> 10));
1390 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { 1395 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1391 outSISREG(SISDAC2A, regno); 1396 SiS_SetRegByte(SISDAC2A, regno);
1392 outSISREG(SISDAC2D, (red >> 8)); 1397 SiS_SetRegByte(SISDAC2D, (red >> 8));
1393 outSISREG(SISDAC2D, (green >> 8)); 1398 SiS_SetRegByte(SISDAC2D, (green >> 8));
1394 outSISREG(SISDAC2D, (blue >> 8)); 1399 SiS_SetRegByte(SISDAC2D, (blue >> 8));
1395 } 1400 }
1396 break; 1401 break;
1397 case 16: 1402 case 16:
@@ -1956,7 +1961,7 @@ sisfb_get_dram_size(struct sis_video_info *ivideo)
1956 switch(ivideo->chip) { 1961 switch(ivideo->chip) {
1957#ifdef CONFIG_FB_SIS_300 1962#ifdef CONFIG_FB_SIS_300
1958 case SIS_300: 1963 case SIS_300:
1959 inSISIDXREG(SISSR, 0x14, reg); 1964 reg = SiS_GetReg(SISSR, 0x14);
1960 ivideo->video_size = ((reg & 0x3F) + 1) << 20; 1965 ivideo->video_size = ((reg & 0x3F) + 1) << 20;
1961 break; 1966 break;
1962 case SIS_540: 1967 case SIS_540:
@@ -1972,7 +1977,7 @@ sisfb_get_dram_size(struct sis_video_info *ivideo)
1972 case SIS_315H: 1977 case SIS_315H:
1973 case SIS_315PRO: 1978 case SIS_315PRO:
1974 case SIS_315: 1979 case SIS_315:
1975 inSISIDXREG(SISSR, 0x14, reg); 1980 reg = SiS_GetReg(SISSR, 0x14);
1976 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20; 1981 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
1977 switch((reg >> 2) & 0x03) { 1982 switch((reg >> 2) & 0x03) {
1978 case 0x01: 1983 case 0x01:
@@ -1984,31 +1989,31 @@ sisfb_get_dram_size(struct sis_video_info *ivideo)
1984 } 1989 }
1985 break; 1990 break;
1986 case SIS_330: 1991 case SIS_330:
1987 inSISIDXREG(SISSR, 0x14, reg); 1992 reg = SiS_GetReg(SISSR, 0x14);
1988 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20; 1993 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
1989 if(reg & 0x0c) ivideo->video_size <<= 1; 1994 if(reg & 0x0c) ivideo->video_size <<= 1;
1990 break; 1995 break;
1991 case SIS_550: 1996 case SIS_550:
1992 case SIS_650: 1997 case SIS_650:
1993 case SIS_740: 1998 case SIS_740:
1994 inSISIDXREG(SISSR, 0x14, reg); 1999 reg = SiS_GetReg(SISSR, 0x14);
1995 ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20; 2000 ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
1996 break; 2001 break;
1997 case SIS_661: 2002 case SIS_661:
1998 case SIS_741: 2003 case SIS_741:
1999 inSISIDXREG(SISCR, 0x79, reg); 2004 reg = SiS_GetReg(SISCR, 0x79);
2000 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20; 2005 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2001 break; 2006 break;
2002 case SIS_660: 2007 case SIS_660:
2003 case SIS_760: 2008 case SIS_760:
2004 case SIS_761: 2009 case SIS_761:
2005 inSISIDXREG(SISCR, 0x79, reg); 2010 reg = SiS_GetReg(SISCR, 0x79);
2006 reg = (reg & 0xf0) >> 4; 2011 reg = (reg & 0xf0) >> 4;
2007 if(reg) { 2012 if(reg) {
2008 ivideo->video_size = (1 << reg) << 20; 2013 ivideo->video_size = (1 << reg) << 20;
2009 ivideo->UMAsize = ivideo->video_size; 2014 ivideo->UMAsize = ivideo->video_size;
2010 } 2015 }
2011 inSISIDXREG(SISCR, 0x78, reg); 2016 reg = SiS_GetReg(SISCR, 0x78);
2012 reg &= 0x30; 2017 reg &= 0x30;
2013 if(reg) { 2018 if(reg) {
2014 if(reg == 0x10) { 2019 if(reg == 0x10) {
@@ -2022,7 +2027,7 @@ sisfb_get_dram_size(struct sis_video_info *ivideo)
2022 case SIS_340: 2027 case SIS_340:
2023 case XGI_20: 2028 case XGI_20:
2024 case XGI_40: 2029 case XGI_40:
2025 inSISIDXREG(SISSR, 0x14, reg); 2030 reg = SiS_GetReg(SISSR, 0x14);
2026 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20; 2031 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2027 if(ivideo->chip != XGI_20) { 2032 if(ivideo->chip != XGI_20) {
2028 reg = (reg & 0x0c) >> 2; 2033 reg = (reg & 0x0c) >> 2;
@@ -2056,11 +2061,11 @@ sisfb_detect_VB_connect(struct sis_video_info *ivideo)
2056 2061
2057#ifdef CONFIG_FB_SIS_300 2062#ifdef CONFIG_FB_SIS_300
2058 if(ivideo->sisvga_engine == SIS_300_VGA) { 2063 if(ivideo->sisvga_engine == SIS_300_VGA) {
2059 inSISIDXREG(SISSR, 0x17, temp); 2064 temp = SiS_GetReg(SISSR, 0x17);
2060 if((temp & 0x0F) && (ivideo->chip != SIS_300)) { 2065 if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
2061 /* PAL/NTSC is stored on SR16 on such machines */ 2066 /* PAL/NTSC is stored on SR16 on such machines */
2062 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) { 2067 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
2063 inSISIDXREG(SISSR, 0x16, temp); 2068 temp = SiS_GetReg(SISSR, 0x16);
2064 if(temp & 0x20) 2069 if(temp & 0x20)
2065 ivideo->vbflags |= TV_PAL; 2070 ivideo->vbflags |= TV_PAL;
2066 else 2071 else
@@ -2070,7 +2075,7 @@ sisfb_detect_VB_connect(struct sis_video_info *ivideo)
2070 } 2075 }
2071#endif 2076#endif
2072 2077
2073 inSISIDXREG(SISCR, 0x32, cr32); 2078 cr32 = SiS_GetReg(SISCR, 0x32);
2074 2079
2075 if(cr32 & SIS_CRT1) { 2080 if(cr32 & SIS_CRT1) {
2076 ivideo->sisfb_crt1off = 0; 2081 ivideo->sisfb_crt1off = 0;
@@ -2146,15 +2151,15 @@ sisfb_detect_VB_connect(struct sis_video_info *ivideo)
2146 } 2151 }
2147 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) { 2152 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
2148 if(ivideo->sisvga_engine == SIS_300_VGA) { 2153 if(ivideo->sisvga_engine == SIS_300_VGA) {
2149 inSISIDXREG(SISSR, 0x38, temp); 2154 temp = SiS_GetReg(SISSR, 0x38);
2150 if(temp & 0x01) ivideo->vbflags |= TV_PAL; 2155 if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2151 else ivideo->vbflags |= TV_NTSC; 2156 else ivideo->vbflags |= TV_NTSC;
2152 } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) { 2157 } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
2153 inSISIDXREG(SISSR, 0x38, temp); 2158 temp = SiS_GetReg(SISSR, 0x38);
2154 if(temp & 0x01) ivideo->vbflags |= TV_PAL; 2159 if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2155 else ivideo->vbflags |= TV_NTSC; 2160 else ivideo->vbflags |= TV_NTSC;
2156 } else { 2161 } else {
2157 inSISIDXREG(SISCR, 0x79, temp); 2162 temp = SiS_GetReg(SISCR, 0x79);
2158 if(temp & 0x20) ivideo->vbflags |= TV_PAL; 2163 if(temp & 0x20) ivideo->vbflags |= TV_PAL;
2159 else ivideo->vbflags |= TV_NTSC; 2164 else ivideo->vbflags |= TV_NTSC;
2160 } 2165 }
@@ -2193,26 +2198,26 @@ sisfb_sense_crt1(struct sis_video_info *ivideo)
2193 u16 temp = 0xffff; 2198 u16 temp = 0xffff;
2194 int i; 2199 int i;
2195 2200
2196 inSISIDXREG(SISSR,0x1F,sr1F); 2201 sr1F = SiS_GetReg(SISSR, 0x1F);
2197 orSISIDXREG(SISSR,0x1F,0x04); 2202 SiS_SetRegOR(SISSR, 0x1F, 0x04);
2198 andSISIDXREG(SISSR,0x1F,0x3F); 2203 SiS_SetRegAND(SISSR, 0x1F, 0x3F);
2199 if(sr1F & 0xc0) mustwait = true; 2204 if(sr1F & 0xc0) mustwait = true;
2200 2205
2201#ifdef CONFIG_FB_SIS_315 2206#ifdef CONFIG_FB_SIS_315
2202 if(ivideo->sisvga_engine == SIS_315_VGA) { 2207 if(ivideo->sisvga_engine == SIS_315_VGA) {
2203 inSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,cr63); 2208 cr63 = SiS_GetReg(SISCR, ivideo->SiS_Pr.SiS_MyCR63);
2204 cr63 &= 0x40; 2209 cr63 &= 0x40;
2205 andSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF); 2210 SiS_SetRegAND(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF);
2206 } 2211 }
2207#endif 2212#endif
2208 2213
2209 inSISIDXREG(SISCR,0x17,cr17); 2214 cr17 = SiS_GetReg(SISCR, 0x17);
2210 cr17 &= 0x80; 2215 cr17 &= 0x80;
2211 if(!cr17) { 2216 if(!cr17) {
2212 orSISIDXREG(SISCR,0x17,0x80); 2217 SiS_SetRegOR(SISCR, 0x17, 0x80);
2213 mustwait = true; 2218 mustwait = true;
2214 outSISIDXREG(SISSR, 0x00, 0x01); 2219 SiS_SetReg(SISSR, 0x00, 0x01);
2215 outSISIDXREG(SISSR, 0x00, 0x03); 2220 SiS_SetReg(SISSR, 0x00, 0x03);
2216 } 2221 }
2217 2222
2218 if(mustwait) { 2223 if(mustwait) {
@@ -2221,18 +2226,18 @@ sisfb_sense_crt1(struct sis_video_info *ivideo)
2221 2226
2222#ifdef CONFIG_FB_SIS_315 2227#ifdef CONFIG_FB_SIS_315
2223 if(ivideo->chip >= SIS_330) { 2228 if(ivideo->chip >= SIS_330) {
2224 andSISIDXREG(SISCR,0x32,~0x20); 2229 SiS_SetRegAND(SISCR, 0x32, ~0x20);
2225 if(ivideo->chip >= SIS_340) { 2230 if(ivideo->chip >= SIS_340) {
2226 outSISIDXREG(SISCR, 0x57, 0x4a); 2231 SiS_SetReg(SISCR, 0x57, 0x4a);
2227 } else { 2232 } else {
2228 outSISIDXREG(SISCR, 0x57, 0x5f); 2233 SiS_SetReg(SISCR, 0x57, 0x5f);
2229 } 2234 }
2230 orSISIDXREG(SISCR, 0x53, 0x02); 2235 SiS_SetRegOR(SISCR, 0x53, 0x02);
2231 while((inSISREG(SISINPSTAT)) & 0x01) break; 2236 while ((SiS_GetRegByte(SISINPSTAT)) & 0x01) break;
2232 while(!((inSISREG(SISINPSTAT)) & 0x01)) break; 2237 while (!((SiS_GetRegByte(SISINPSTAT)) & 0x01)) break;
2233 if((inSISREG(SISMISCW)) & 0x10) temp = 1; 2238 if ((SiS_GetRegByte(SISMISCW)) & 0x10) temp = 1;
2234 andSISIDXREG(SISCR, 0x53, 0xfd); 2239 SiS_SetRegAND(SISCR, 0x53, 0xfd);
2235 andSISIDXREG(SISCR, 0x57, 0x00); 2240 SiS_SetRegAND(SISCR, 0x57, 0x00);
2236 } 2241 }
2237#endif 2242#endif
2238 2243
@@ -2249,18 +2254,18 @@ sisfb_sense_crt1(struct sis_video_info *ivideo)
2249 } 2254 }
2250 2255
2251 if((temp) && (temp != 0xffff)) { 2256 if((temp) && (temp != 0xffff)) {
2252 orSISIDXREG(SISCR,0x32,0x20); 2257 SiS_SetRegOR(SISCR, 0x32, 0x20);
2253 } 2258 }
2254 2259
2255#ifdef CONFIG_FB_SIS_315 2260#ifdef CONFIG_FB_SIS_315
2256 if(ivideo->sisvga_engine == SIS_315_VGA) { 2261 if(ivideo->sisvga_engine == SIS_315_VGA) {
2257 setSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF,cr63); 2262 SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF, cr63);
2258 } 2263 }
2259#endif 2264#endif
2260 2265
2261 setSISIDXREG(SISCR,0x17,0x7F,cr17); 2266 SiS_SetRegANDOR(SISCR, 0x17, 0x7F, cr17);
2262 2267
2263 outSISIDXREG(SISSR,0x1F,sr1F); 2268 SiS_SetReg(SISSR, 0x1F, sr1F);
2264} 2269}
2265 2270
2266/* Determine and detect attached devices on SiS30x */ 2271/* Determine and detect attached devices on SiS30x */
@@ -2281,7 +2286,7 @@ SiS_SenseLCD(struct sis_video_info *ivideo)
2281 return; 2286 return;
2282 2287
2283 /* If LCD already set up by BIOS, skip it */ 2288 /* If LCD already set up by BIOS, skip it */
2284 inSISIDXREG(SISCR, 0x32, reg); 2289 reg = SiS_GetReg(SISCR, 0x32);
2285 if(reg & 0x08) 2290 if(reg & 0x08)
2286 return; 2291 return;
2287 2292
@@ -2344,10 +2349,10 @@ SiS_SenseLCD(struct sis_video_info *ivideo)
2344 else 2349 else
2345 cr37 |= 0xc0; 2350 cr37 |= 0xc0;
2346 2351
2347 outSISIDXREG(SISCR, 0x36, paneltype); 2352 SiS_SetReg(SISCR, 0x36, paneltype);
2348 cr37 &= 0xf1; 2353 cr37 &= 0xf1;
2349 setSISIDXREG(SISCR, 0x37, 0x0c, cr37); 2354 SiS_SetRegANDOR(SISCR, 0x37, 0x0c, cr37);
2350 orSISIDXREG(SISCR, 0x32, 0x08); 2355 SiS_SetRegOR(SISCR, 0x32, 0x08);
2351 2356
2352 ivideo->SiS_Pr.PanelSelfDetected = true; 2357 ivideo->SiS_Pr.PanelSelfDetected = true;
2353} 2358}
@@ -2361,19 +2366,19 @@ SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
2361 result = 0; 2366 result = 0;
2362 for(i = 0; i < 3; i++) { 2367 for(i = 0; i < 3; i++) {
2363 mytest = test; 2368 mytest = test;
2364 outSISIDXREG(SISPART4,0x11,(type & 0x00ff)); 2369 SiS_SetReg(SISPART4, 0x11, (type & 0x00ff));
2365 temp = (type >> 8) | (mytest & 0x00ff); 2370 temp = (type >> 8) | (mytest & 0x00ff);
2366 setSISIDXREG(SISPART4,0x10,0xe0,temp); 2371 SiS_SetRegANDOR(SISPART4, 0x10, 0xe0, temp);
2367 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500); 2372 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
2368 mytest >>= 8; 2373 mytest >>= 8;
2369 mytest &= 0x7f; 2374 mytest &= 0x7f;
2370 inSISIDXREG(SISPART4,0x03,temp); 2375 temp = SiS_GetReg(SISPART4, 0x03);
2371 temp ^= 0x0e; 2376 temp ^= 0x0e;
2372 temp &= mytest; 2377 temp &= mytest;
2373 if(temp == mytest) result++; 2378 if(temp == mytest) result++;
2374#if 1 2379#if 1
2375 outSISIDXREG(SISPART4,0x11,0x00); 2380 SiS_SetReg(SISPART4, 0x11, 0x00);
2376 andSISIDXREG(SISPART4,0x10,0xe0); 2381 SiS_SetRegAND(SISPART4, 0x10, 0xe0);
2377 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000); 2382 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
2378#endif 2383#endif
2379 } 2384 }
@@ -2395,7 +2400,7 @@ SiS_Sense30x(struct sis_video_info *ivideo)
2395 2400
2396 if(ivideo->vbflags2 & VB2_301) { 2401 if(ivideo->vbflags2 & VB2_301) {
2397 svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1; 2402 svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
2398 inSISIDXREG(SISPART4,0x01,myflag); 2403 myflag = SiS_GetReg(SISPART4, 0x01);
2399 if(myflag & 0x04) { 2404 if(myflag & 0x04) {
2400 svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd; 2405 svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
2401 } 2406 }
@@ -2425,7 +2430,7 @@ SiS_Sense30x(struct sis_video_info *ivideo)
2425 } 2430 }
2426 2431
2427 if(ivideo->chip == SIS_300) { 2432 if(ivideo->chip == SIS_300) {
2428 inSISIDXREG(SISSR,0x3b,myflag); 2433 myflag = SiS_GetReg(SISSR, 0x3b);
2429 if(!(myflag & 0x01)) vga2 = vga2_c = 0; 2434 if(!(myflag & 0x01)) vga2 = vga2_c = 0;
2430 } 2435 }
2431 2436
@@ -2433,93 +2438,93 @@ SiS_Sense30x(struct sis_video_info *ivideo)
2433 vga2 = vga2_c = 0; 2438 vga2 = vga2_c = 0;
2434 } 2439 }
2435 2440
2436 inSISIDXREG(SISSR,0x1e,backupSR_1e); 2441 backupSR_1e = SiS_GetReg(SISSR, 0x1e);
2437 orSISIDXREG(SISSR,0x1e,0x20); 2442 SiS_SetRegOR(SISSR, 0x1e, 0x20);
2438 2443
2439 inSISIDXREG(SISPART4,0x0d,backupP4_0d); 2444 backupP4_0d = SiS_GetReg(SISPART4, 0x0d);
2440 if(ivideo->vbflags2 & VB2_30xC) { 2445 if(ivideo->vbflags2 & VB2_30xC) {
2441 setSISIDXREG(SISPART4,0x0d,~0x07,0x01); 2446 SiS_SetRegANDOR(SISPART4, 0x0d, ~0x07, 0x01);
2442 } else { 2447 } else {
2443 orSISIDXREG(SISPART4,0x0d,0x04); 2448 SiS_SetRegOR(SISPART4, 0x0d, 0x04);
2444 } 2449 }
2445 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000); 2450 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2446 2451
2447 inSISIDXREG(SISPART2,0x00,backupP2_00); 2452 backupP2_00 = SiS_GetReg(SISPART2, 0x00);
2448 outSISIDXREG(SISPART2,0x00,((backupP2_00 | 0x1c) & 0xfc)); 2453 SiS_SetReg(SISPART2, 0x00, ((backupP2_00 | 0x1c) & 0xfc));
2449 2454
2450 inSISIDXREG(SISPART2,0x4d,backupP2_4d); 2455 backupP2_4d = SiS_GetReg(SISPART2, 0x4d);
2451 if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) { 2456 if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) {
2452 outSISIDXREG(SISPART2,0x4d,(backupP2_4d & ~0x10)); 2457 SiS_SetReg(SISPART2, 0x4d, (backupP2_4d & ~0x10));
2453 } 2458 }
2454 2459
2455 if(!(ivideo->vbflags2 & VB2_30xCLV)) { 2460 if(!(ivideo->vbflags2 & VB2_30xCLV)) {
2456 SISDoSense(ivideo, 0, 0); 2461 SISDoSense(ivideo, 0, 0);
2457 } 2462 }
2458 2463
2459 andSISIDXREG(SISCR, 0x32, ~0x14); 2464 SiS_SetRegAND(SISCR, 0x32, ~0x14);
2460 2465
2461 if(vga2_c || vga2) { 2466 if(vga2_c || vga2) {
2462 if(SISDoSense(ivideo, vga2, vga2_c)) { 2467 if(SISDoSense(ivideo, vga2, vga2_c)) {
2463 if(biosflag & 0x01) { 2468 if(biosflag & 0x01) {
2464 printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr); 2469 printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr);
2465 orSISIDXREG(SISCR, 0x32, 0x04); 2470 SiS_SetRegOR(SISCR, 0x32, 0x04);
2466 } else { 2471 } else {
2467 printk(KERN_INFO "%s secondary VGA connection\n", stdstr); 2472 printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
2468 orSISIDXREG(SISCR, 0x32, 0x10); 2473 SiS_SetRegOR(SISCR, 0x32, 0x10);
2469 } 2474 }
2470 } 2475 }
2471 } 2476 }
2472 2477
2473 andSISIDXREG(SISCR, 0x32, 0x3f); 2478 SiS_SetRegAND(SISCR, 0x32, 0x3f);
2474 2479
2475 if(ivideo->vbflags2 & VB2_30xCLV) { 2480 if(ivideo->vbflags2 & VB2_30xCLV) {
2476 orSISIDXREG(SISPART4,0x0d,0x04); 2481 SiS_SetRegOR(SISPART4, 0x0d, 0x04);
2477 } 2482 }
2478 2483
2479 if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) { 2484 if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
2480 outSISIDXREG(SISPART2,0x4d,(backupP2_4d | 0x10)); 2485 SiS_SetReg(SISPART2, 0x4d, (backupP2_4d | 0x10));
2481 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000); 2486 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2482 if((result = SISDoSense(ivideo, svhs, 0x0604))) { 2487 if((result = SISDoSense(ivideo, svhs, 0x0604))) {
2483 if((result = SISDoSense(ivideo, cvbs, 0x0804))) { 2488 if((result = SISDoSense(ivideo, cvbs, 0x0804))) {
2484 printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr); 2489 printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr);
2485 orSISIDXREG(SISCR,0x32,0x80); 2490 SiS_SetRegOR(SISCR, 0x32, 0x80);
2486 } 2491 }
2487 } 2492 }
2488 outSISIDXREG(SISPART2,0x4d,backupP2_4d); 2493 SiS_SetReg(SISPART2, 0x4d, backupP2_4d);
2489 } 2494 }
2490 2495
2491 andSISIDXREG(SISCR, 0x32, ~0x03); 2496 SiS_SetRegAND(SISCR, 0x32, ~0x03);
2492 2497
2493 if(!(ivideo->vbflags & TV_YPBPR)) { 2498 if(!(ivideo->vbflags & TV_YPBPR)) {
2494 if((result = SISDoSense(ivideo, svhs, svhs_c))) { 2499 if((result = SISDoSense(ivideo, svhs, svhs_c))) {
2495 printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr); 2500 printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
2496 orSISIDXREG(SISCR, 0x32, 0x02); 2501 SiS_SetRegOR(SISCR, 0x32, 0x02);
2497 } 2502 }
2498 if((biosflag & 0x02) || (!result)) { 2503 if((biosflag & 0x02) || (!result)) {
2499 if(SISDoSense(ivideo, cvbs, cvbs_c)) { 2504 if(SISDoSense(ivideo, cvbs, cvbs_c)) {
2500 printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr); 2505 printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
2501 orSISIDXREG(SISCR, 0x32, 0x01); 2506 SiS_SetRegOR(SISCR, 0x32, 0x01);
2502 } 2507 }
2503 } 2508 }
2504 } 2509 }
2505 2510
2506 SISDoSense(ivideo, 0, 0); 2511 SISDoSense(ivideo, 0, 0);
2507 2512
2508 outSISIDXREG(SISPART2,0x00,backupP2_00); 2513 SiS_SetReg(SISPART2, 0x00, backupP2_00);
2509 outSISIDXREG(SISPART4,0x0d,backupP4_0d); 2514 SiS_SetReg(SISPART4, 0x0d, backupP4_0d);
2510 outSISIDXREG(SISSR,0x1e,backupSR_1e); 2515 SiS_SetReg(SISSR, 0x1e, backupSR_1e);
2511 2516
2512 if(ivideo->vbflags2 & VB2_30xCLV) { 2517 if(ivideo->vbflags2 & VB2_30xCLV) {
2513 inSISIDXREG(SISPART2,0x00,biosflag); 2518 biosflag = SiS_GetReg(SISPART2, 0x00);
2514 if(biosflag & 0x20) { 2519 if(biosflag & 0x20) {
2515 for(myflag = 2; myflag > 0; myflag--) { 2520 for(myflag = 2; myflag > 0; myflag--) {
2516 biosflag ^= 0x20; 2521 biosflag ^= 0x20;
2517 outSISIDXREG(SISPART2,0x00,biosflag); 2522 SiS_SetReg(SISPART2, 0x00, biosflag);
2518 } 2523 }
2519 } 2524 }
2520 } 2525 }
2521 2526
2522 outSISIDXREG(SISPART2,0x00,backupP2_00); 2527 SiS_SetReg(SISPART2, 0x00, backupP2_00);
2523} 2528}
2524 2529
2525/* Determine and detect attached TV's on Chrontel */ 2530/* Determine and detect attached TV's on Chrontel */
@@ -2583,20 +2588,20 @@ SiS_SenseCh(struct sis_video_info *ivideo)
2583 if(temp1 == 0x02) { 2588 if(temp1 == 0x02) {
2584 printk(KERN_INFO "%s SVIDEO output\n", stdstr); 2589 printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2585 ivideo->vbflags |= TV_SVIDEO; 2590 ivideo->vbflags |= TV_SVIDEO;
2586 orSISIDXREG(SISCR, 0x32, 0x02); 2591 SiS_SetRegOR(SISCR, 0x32, 0x02);
2587 andSISIDXREG(SISCR, 0x32, ~0x05); 2592 SiS_SetRegAND(SISCR, 0x32, ~0x05);
2588 } else if (temp1 == 0x01) { 2593 } else if (temp1 == 0x01) {
2589 printk(KERN_INFO "%s CVBS output\n", stdstr); 2594 printk(KERN_INFO "%s CVBS output\n", stdstr);
2590 ivideo->vbflags |= TV_AVIDEO; 2595 ivideo->vbflags |= TV_AVIDEO;
2591 orSISIDXREG(SISCR, 0x32, 0x01); 2596 SiS_SetRegOR(SISCR, 0x32, 0x01);
2592 andSISIDXREG(SISCR, 0x32, ~0x06); 2597 SiS_SetRegAND(SISCR, 0x32, ~0x06);
2593 } else { 2598 } else {
2594 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8); 2599 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2595 andSISIDXREG(SISCR, 0x32, ~0x07); 2600 SiS_SetRegAND(SISCR, 0x32, ~0x07);
2596 } 2601 }
2597 } else if(temp1 == 0) { 2602 } else if(temp1 == 0) {
2598 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8); 2603 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2599 andSISIDXREG(SISCR, 0x32, ~0x07); 2604 SiS_SetRegAND(SISCR, 0x32, ~0x07);
2600 } 2605 }
2601 /* Set general purpose IO for Chrontel communication */ 2606 /* Set general purpose IO for Chrontel communication */
2602 SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00); 2607 SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00);
@@ -2627,22 +2632,22 @@ SiS_SenseCh(struct sis_video_info *ivideo)
2627 case 0x01: 2632 case 0x01:
2628 printk(KERN_INFO "%s CVBS output\n", stdstr); 2633 printk(KERN_INFO "%s CVBS output\n", stdstr);
2629 ivideo->vbflags |= TV_AVIDEO; 2634 ivideo->vbflags |= TV_AVIDEO;
2630 orSISIDXREG(SISCR, 0x32, 0x01); 2635 SiS_SetRegOR(SISCR, 0x32, 0x01);
2631 andSISIDXREG(SISCR, 0x32, ~0x06); 2636 SiS_SetRegAND(SISCR, 0x32, ~0x06);
2632 break; 2637 break;
2633 case 0x02: 2638 case 0x02:
2634 printk(KERN_INFO "%s SVIDEO output\n", stdstr); 2639 printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2635 ivideo->vbflags |= TV_SVIDEO; 2640 ivideo->vbflags |= TV_SVIDEO;
2636 orSISIDXREG(SISCR, 0x32, 0x02); 2641 SiS_SetRegOR(SISCR, 0x32, 0x02);
2637 andSISIDXREG(SISCR, 0x32, ~0x05); 2642 SiS_SetRegAND(SISCR, 0x32, ~0x05);
2638 break; 2643 break;
2639 case 0x04: 2644 case 0x04:
2640 printk(KERN_INFO "%s SCART output\n", stdstr); 2645 printk(KERN_INFO "%s SCART output\n", stdstr);
2641 orSISIDXREG(SISCR, 0x32, 0x04); 2646 SiS_SetRegOR(SISCR, 0x32, 0x04);
2642 andSISIDXREG(SISCR, 0x32, ~0x03); 2647 SiS_SetRegAND(SISCR, 0x32, ~0x03);
2643 break; 2648 break;
2644 default: 2649 default:
2645 andSISIDXREG(SISCR, 0x32, ~0x07); 2650 SiS_SetRegAND(SISCR, 0x32, ~0x07);
2646 } 2651 }
2647#endif 2652#endif
2648 } 2653 }
@@ -2660,10 +2665,10 @@ sisfb_get_VB_type(struct sis_video_info *ivideo)
2660 if(ivideo->chip == XGI_20) 2665 if(ivideo->chip == XGI_20)
2661 return; 2666 return;
2662 2667
2663 inSISIDXREG(SISPART4, 0x00, vb_chipid); 2668 vb_chipid = SiS_GetReg(SISPART4, 0x00);
2664 switch(vb_chipid) { 2669 switch(vb_chipid) {
2665 case 0x01: 2670 case 0x01:
2666 inSISIDXREG(SISPART4, 0x01, reg); 2671 reg = SiS_GetReg(SISPART4, 0x01);
2667 if(reg < 0xb0) { 2672 if(reg < 0xb0) {
2668 ivideo->vbflags |= VB_301; /* Deprecated */ 2673 ivideo->vbflags |= VB_301; /* Deprecated */
2669 ivideo->vbflags2 |= VB2_301; 2674 ivideo->vbflags2 |= VB2_301;
@@ -2671,7 +2676,7 @@ sisfb_get_VB_type(struct sis_video_info *ivideo)
2671 } else if(reg < 0xc0) { 2676 } else if(reg < 0xc0) {
2672 ivideo->vbflags |= VB_301B; /* Deprecated */ 2677 ivideo->vbflags |= VB_301B; /* Deprecated */
2673 ivideo->vbflags2 |= VB2_301B; 2678 ivideo->vbflags2 |= VB2_301B;
2674 inSISIDXREG(SISPART4,0x23,reg); 2679 reg = SiS_GetReg(SISPART4, 0x23);
2675 if(!(reg & 0x02)) { 2680 if(!(reg & 0x02)) {
2676 ivideo->vbflags |= VB_30xBDH; /* Deprecated */ 2681 ivideo->vbflags |= VB_30xBDH; /* Deprecated */
2677 ivideo->vbflags2 |= VB2_30xBDH; 2682 ivideo->vbflags2 |= VB2_30xBDH;
@@ -2688,7 +2693,7 @@ sisfb_get_VB_type(struct sis_video_info *ivideo)
2688 ivideo->vbflags2 |= VB2_301LV; 2693 ivideo->vbflags2 |= VB2_301LV;
2689 printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr); 2694 printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
2690 } else if(reg <= 0xe1) { 2695 } else if(reg <= 0xe1) {
2691 inSISIDXREG(SISPART4,0x39,reg); 2696 reg = SiS_GetReg(SISPART4, 0x39);
2692 if(reg == 0xff) { 2697 if(reg == 0xff) {
2693 ivideo->vbflags |= VB_302LV; /* Deprecated */ 2698 ivideo->vbflags |= VB_302LV; /* Deprecated */
2694 ivideo->vbflags2 |= VB2_302LV; 2699 ivideo->vbflags2 |= VB2_302LV;
@@ -2713,7 +2718,7 @@ sisfb_get_VB_type(struct sis_video_info *ivideo)
2713 } 2718 }
2714 2719
2715 if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) { 2720 if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
2716 inSISIDXREG(SISCR, 0x37, reg); 2721 reg = SiS_GetReg(SISCR, 0x37);
2717 reg &= SIS_EXTERNAL_CHIP_MASK; 2722 reg &= SIS_EXTERNAL_CHIP_MASK;
2718 reg >>= 1; 2723 reg >>= 1;
2719 if(ivideo->sisvga_engine == SIS_300_VGA) { 2724 if(ivideo->sisvga_engine == SIS_300_VGA) {
@@ -2754,7 +2759,7 @@ sisfb_get_VB_type(struct sis_video_info *ivideo)
2754#endif 2759#endif
2755 } else if(ivideo->chip >= SIS_661) { 2760 } else if(ivideo->chip >= SIS_661) {
2756#ifdef CONFIG_FB_SIS_315 2761#ifdef CONFIG_FB_SIS_315
2757 inSISIDXREG(SISCR, 0x38, reg); 2762 reg = SiS_GetReg(SISCR, 0x38);
2758 reg >>= 5; 2763 reg >>= 5;
2759 switch(reg) { 2764 switch(reg) {
2760 case 0x02: 2765 case 0x02:
@@ -2817,13 +2822,13 @@ sisfb_engine_init(struct sis_video_info *ivideo)
2817 2822
2818 tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024); 2823 tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024);
2819 2824
2820 inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state); 2825 tq_state = SiS_GetReg(SISSR, IND_SIS_TURBOQUEUE_SET);
2821 tq_state |= 0xf0; 2826 tq_state |= 0xf0;
2822 tq_state &= 0xfc; 2827 tq_state &= 0xfc;
2823 tq_state |= (u8)(tqueue_pos >> 8); 2828 tq_state |= (u8)(tqueue_pos >> 8);
2824 outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state); 2829 SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
2825 2830
2826 outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff)); 2831 SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
2827 2832
2828 ivideo->caps |= TURBO_QUEUE_CAP; 2833 ivideo->caps |= TURBO_QUEUE_CAP;
2829 } 2834 }
@@ -2860,8 +2865,8 @@ sisfb_engine_init(struct sis_video_info *ivideo)
2860 } 2865 }
2861 } 2866 }
2862 2867
2863 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD); 2868 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2864 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET); 2869 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
2865 2870
2866 if((ivideo->chip >= XGI_40) && ivideo->modechanged) { 2871 if((ivideo->chip >= XGI_40) && ivideo->modechanged) {
2867 /* Must disable dual pipe on XGI_40. Can't do 2872 /* Must disable dual pipe on XGI_40. Can't do
@@ -2873,7 +2878,7 @@ sisfb_engine_init(struct sis_video_info *ivideo)
2873 2878
2874 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0); 2879 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0);
2875 2880
2876 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE)); 2881 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
2877 2882
2878 tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR); 2883 tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR);
2879 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq); 2884 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq);
@@ -2890,7 +2895,7 @@ sisfb_engine_init(struct sis_video_info *ivideo)
2890 2895
2891 sisfb_syncaccel(ivideo); 2896 sisfb_syncaccel(ivideo);
2892 2897
2893 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET); 2898 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
2894 2899
2895 } 2900 }
2896 } 2901 }
@@ -2899,7 +2904,7 @@ sisfb_engine_init(struct sis_video_info *ivideo)
2899 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq); 2904 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
2900 2905
2901 temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR); 2906 temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
2902 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp); 2907 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, temp);
2903 2908
2904 tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize); 2909 tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2905 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq); 2910 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
@@ -2917,7 +2922,7 @@ sisfb_detect_lcd_type(struct sis_video_info *ivideo)
2917 u8 reg; 2922 u8 reg;
2918 int i; 2923 int i;
2919 2924
2920 inSISIDXREG(SISCR, 0x36, reg); 2925 reg = SiS_GetReg(SISCR, 0x36);
2921 reg &= 0x0f; 2926 reg &= 0x0f;
2922 if(ivideo->sisvga_engine == SIS_300_VGA) { 2927 if(ivideo->sisvga_engine == SIS_300_VGA) {
2923 ivideo->CRT2LCDType = sis300paneltype[reg]; 2928 ivideo->CRT2LCDType = sis300paneltype[reg];
@@ -2936,8 +2941,8 @@ sisfb_detect_lcd_type(struct sis_video_info *ivideo)
2936 if(ivideo->CRT2LCDType == LCD_UNKNOWN) { 2941 if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
2937 /* For broken BIOSes: Assume 1024x768, RGB18 */ 2942 /* For broken BIOSes: Assume 1024x768, RGB18 */
2938 ivideo->CRT2LCDType = LCD_1024x768; 2943 ivideo->CRT2LCDType = LCD_1024x768;
2939 setSISIDXREG(SISCR,0x36,0xf0,0x02); 2944 SiS_SetRegANDOR(SISCR, 0x36, 0xf0, 0x02);
2940 setSISIDXREG(SISCR,0x37,0xee,0x01); 2945 SiS_SetRegANDOR(SISCR, 0x37, 0xee, 0x01);
2941 printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg); 2946 printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
2942 } 2947 }
2943 2948
@@ -2975,10 +2980,10 @@ sisfb_save_pdc_emi(struct sis_video_info *ivideo)
2975 if(ivideo->sisvga_engine == SIS_300_VGA) { 2980 if(ivideo->sisvga_engine == SIS_300_VGA) {
2976 if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) { 2981 if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) {
2977 int tmp; 2982 int tmp;
2978 inSISIDXREG(SISCR,0x30,tmp); 2983 tmp = SiS_GetReg(SISCR, 0x30);
2979 if(tmp & 0x20) { 2984 if(tmp & 0x20) {
2980 /* Currently on LCD? If yes, read current pdc */ 2985 /* Currently on LCD? If yes, read current pdc */
2981 inSISIDXREG(SISPART1,0x13,ivideo->detectedpdc); 2986 ivideo->detectedpdc = SiS_GetReg(SISPART1, 0x13);
2982 ivideo->detectedpdc &= 0x3c; 2987 ivideo->detectedpdc &= 0x3c;
2983 if(ivideo->SiS_Pr.PDC == -1) { 2988 if(ivideo->SiS_Pr.PDC == -1) {
2984 /* Let option override detection */ 2989 /* Let option override detection */
@@ -3002,7 +3007,7 @@ sisfb_save_pdc_emi(struct sis_video_info *ivideo)
3002 /* Try to find about LCDA */ 3007 /* Try to find about LCDA */
3003 if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) { 3008 if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) {
3004 int tmp; 3009 int tmp;
3005 inSISIDXREG(SISPART1,0x13,tmp); 3010 tmp = SiS_GetReg(SISPART1, 0x13);
3006 if(tmp & 0x04) { 3011 if(tmp & 0x04) {
3007 ivideo->SiS_Pr.SiS_UseLCDA = true; 3012 ivideo->SiS_Pr.SiS_UseLCDA = true;
3008 ivideo->detectedlcda = 0x03; 3013 ivideo->detectedlcda = 0x03;
@@ -3012,16 +3017,16 @@ sisfb_save_pdc_emi(struct sis_video_info *ivideo)
3012 /* Save PDC */ 3017 /* Save PDC */
3013 if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) { 3018 if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
3014 int tmp; 3019 int tmp;
3015 inSISIDXREG(SISCR,0x30,tmp); 3020 tmp = SiS_GetReg(SISCR, 0x30);
3016 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) { 3021 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
3017 /* Currently on LCD? If yes, read current pdc */ 3022 /* Currently on LCD? If yes, read current pdc */
3018 u8 pdc; 3023 u8 pdc;
3019 inSISIDXREG(SISPART1,0x2D,pdc); 3024 pdc = SiS_GetReg(SISPART1, 0x2D);
3020 ivideo->detectedpdc = (pdc & 0x0f) << 1; 3025 ivideo->detectedpdc = (pdc & 0x0f) << 1;
3021 ivideo->detectedpdca = (pdc & 0xf0) >> 3; 3026 ivideo->detectedpdca = (pdc & 0xf0) >> 3;
3022 inSISIDXREG(SISPART1,0x35,pdc); 3027 pdc = SiS_GetReg(SISPART1, 0x35);
3023 ivideo->detectedpdc |= ((pdc >> 7) & 0x01); 3028 ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
3024 inSISIDXREG(SISPART1,0x20,pdc); 3029 pdc = SiS_GetReg(SISPART1, 0x20);
3025 ivideo->detectedpdca |= ((pdc >> 6) & 0x01); 3030 ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
3026 if(ivideo->newrom) { 3031 if(ivideo->newrom) {
3027 /* New ROM invalidates other PDC resp. */ 3032 /* New ROM invalidates other PDC resp. */
@@ -3055,10 +3060,10 @@ sisfb_save_pdc_emi(struct sis_video_info *ivideo)
3055 3060
3056 /* Save EMI */ 3061 /* Save EMI */
3057 if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) { 3062 if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) {
3058 inSISIDXREG(SISPART4,0x30,ivideo->SiS_Pr.EMI_30); 3063 ivideo->SiS_Pr.EMI_30 = SiS_GetReg(SISPART4, 0x30);
3059 inSISIDXREG(SISPART4,0x31,ivideo->SiS_Pr.EMI_31); 3064 ivideo->SiS_Pr.EMI_31 = SiS_GetReg(SISPART4, 0x31);
3060 inSISIDXREG(SISPART4,0x32,ivideo->SiS_Pr.EMI_32); 3065 ivideo->SiS_Pr.EMI_32 = SiS_GetReg(SISPART4, 0x32);
3061 inSISIDXREG(SISPART4,0x33,ivideo->SiS_Pr.EMI_33); 3066 ivideo->SiS_Pr.EMI_33 = SiS_GetReg(SISPART4, 0x33);
3062 ivideo->SiS_Pr.HaveEMI = true; 3067 ivideo->SiS_Pr.HaveEMI = true;
3063 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) { 3068 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
3064 ivideo->SiS_Pr.HaveEMILCD = true; 3069 ivideo->SiS_Pr.HaveEMILCD = true;
@@ -3483,8 +3488,8 @@ sisfb_check_engine_and_sync(struct sis_video_info *ivideo)
3483 * ivideo->accel here, as this might have 3488 * ivideo->accel here, as this might have
3484 * been changed before this is called. 3489 * been changed before this is called.
3485 */ 3490 */
3486 inSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, cr30); 3491 cr30 = SiS_GetReg(SISSR, IND_SIS_PCI_ADDRESS_SET);
3487 inSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, cr31); 3492 cr31 = SiS_GetReg(SISSR, IND_SIS_MODULE_ENABLE);
3488 /* MMIO and 2D/3D engine enabled? */ 3493 /* MMIO and 2D/3D engine enabled? */
3489 if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) { 3494 if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) {
3490#ifdef CONFIG_FB_SIS_300 3495#ifdef CONFIG_FB_SIS_300
@@ -3502,7 +3507,7 @@ sisfb_check_engine_and_sync(struct sis_video_info *ivideo)
3502 * enabled, and that the queue 3507 * enabled, and that the queue
3503 * is not in the state of "reset" 3508 * is not in the state of "reset"
3504 */ 3509 */
3505 inSISIDXREG(SISSR, 0x26, cr30); 3510 cr30 = SiS_GetReg(SISSR, 0x26);
3506 if((cr30 & 0xe0) && (!(cr30 & 0x01))) { 3511 if((cr30 & 0xe0) && (!(cr30 & 0x01))) {
3507 sisfb_syncaccel(ivideo); 3512 sisfb_syncaccel(ivideo);
3508 } 3513 }
@@ -3519,9 +3524,9 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
3519 3524
3520 ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2); 3525 ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
3521 3526
3522 outSISIDXREG(SISSR, 0x05, 0x86); 3527 SiS_SetReg(SISSR, 0x05, 0x86);
3523 3528
3524 inSISIDXREG(SISCR, 0x31, cr31); 3529 cr31 = SiS_GetReg(SISCR, 0x31);
3525 cr31 &= ~0x60; 3530 cr31 &= ~0x60;
3526 cr31 |= 0x04; 3531 cr31 |= 0x04;
3527 3532
@@ -3530,11 +3535,11 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
3530#ifdef CONFIG_FB_SIS_315 3535#ifdef CONFIG_FB_SIS_315
3531 if(ivideo->sisvga_engine == SIS_315_VGA) { 3536 if(ivideo->sisvga_engine == SIS_315_VGA) {
3532 if(ivideo->chip >= SIS_661) { 3537 if(ivideo->chip >= SIS_661) {
3533 inSISIDXREG(SISCR, 0x38, cr38); 3538 cr38 = SiS_GetReg(SISCR, 0x38);
3534 cr38 &= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */ 3539 cr38 &= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */
3535 } else { 3540 } else {
3536 tvregnum = 0x38; 3541 tvregnum = 0x38;
3537 inSISIDXREG(SISCR, tvregnum, cr38); 3542 cr38 = SiS_GetReg(SISCR, tvregnum);
3538 cr38 &= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */ 3543 cr38 &= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */
3539 } 3544 }
3540 } 3545 }
@@ -3542,7 +3547,7 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
3542#ifdef CONFIG_FB_SIS_300 3547#ifdef CONFIG_FB_SIS_300
3543 if(ivideo->sisvga_engine == SIS_300_VGA) { 3548 if(ivideo->sisvga_engine == SIS_300_VGA) {
3544 tvregnum = 0x35; 3549 tvregnum = 0x35;
3545 inSISIDXREG(SISCR, tvregnum, cr38); 3550 cr38 = SiS_GetReg(SISCR, tvregnum);
3546 } 3551 }
3547#endif 3552#endif
3548 3553
@@ -3649,20 +3654,20 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
3649 cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE); 3654 cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
3650 } 3655 }
3651 3656
3652 outSISIDXREG(SISCR, 0x30, cr30); 3657 SiS_SetReg(SISCR, 0x30, cr30);
3653 outSISIDXREG(SISCR, 0x33, cr33); 3658 SiS_SetReg(SISCR, 0x33, cr33);
3654 3659
3655 if(ivideo->chip >= SIS_661) { 3660 if(ivideo->chip >= SIS_661) {
3656#ifdef CONFIG_FB_SIS_315 3661#ifdef CONFIG_FB_SIS_315
3657 cr31 &= ~0x01; /* Clear PAL flag (now in CR35) */ 3662 cr31 &= ~0x01; /* Clear PAL flag (now in CR35) */
3658 setSISIDXREG(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */ 3663 SiS_SetRegANDOR(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
3659 cr38 &= 0x07; /* Use only LCDA and HiVision/YPbPr bits */ 3664 cr38 &= 0x07; /* Use only LCDA and HiVision/YPbPr bits */
3660 setSISIDXREG(SISCR, 0x38, 0xf8, cr38); 3665 SiS_SetRegANDOR(SISCR, 0x38, 0xf8, cr38);
3661#endif 3666#endif
3662 } else if(ivideo->chip != SIS_300) { 3667 } else if(ivideo->chip != SIS_300) {
3663 outSISIDXREG(SISCR, tvregnum, cr38); 3668 SiS_SetReg(SISCR, tvregnum, cr38);
3664 } 3669 }
3665 outSISIDXREG(SISCR, 0x31, cr31); 3670 SiS_SetReg(SISCR, 0x31, cr31);
3666 3671
3667 ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem; 3672 ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
3668 3673
@@ -3677,15 +3682,15 @@ sisfb_fixup_SR11(struct sis_video_info *ivideo)
3677 u8 tmpreg; 3682 u8 tmpreg;
3678 3683
3679 if(ivideo->chip >= SIS_661) { 3684 if(ivideo->chip >= SIS_661) {
3680 inSISIDXREG(SISSR,0x11,tmpreg); 3685 tmpreg = SiS_GetReg(SISSR, 0x11);
3681 if(tmpreg & 0x20) { 3686 if(tmpreg & 0x20) {
3682 inSISIDXREG(SISSR,0x3e,tmpreg); 3687 tmpreg = SiS_GetReg(SISSR, 0x3e);
3683 tmpreg = (tmpreg + 1) & 0xff; 3688 tmpreg = (tmpreg + 1) & 0xff;
3684 outSISIDXREG(SISSR,0x3e,tmpreg); 3689 SiS_SetReg(SISSR, 0x3e, tmpreg);
3685 inSISIDXREG(SISSR,0x11,tmpreg); 3690 tmpreg = SiS_GetReg(SISSR, 0x11);
3686 } 3691 }
3687 if(tmpreg & 0xf0) { 3692 if(tmpreg & 0xf0) {
3688 andSISIDXREG(SISSR,0x11,0x0f); 3693 SiS_SetRegAND(SISSR, 0x11, 0x0f);
3689 } 3694 }
3690 } 3695 }
3691} 3696}
@@ -3711,7 +3716,7 @@ sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
3711 case 1: 3716 case 1:
3712 x += val; 3717 x += val;
3713 if(x < 0) x = 0; 3718 if(x < 0) x = 0;
3714 outSISIDXREG(SISSR,0x05,0x86); 3719 SiS_SetReg(SISSR, 0x05, 0x86);
3715 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff)); 3720 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff));
3716 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD); 3721 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD);
3717 break; 3722 break;
@@ -3740,11 +3745,11 @@ sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
3740 temp += (val * 2); 3745 temp += (val * 2);
3741 p2_43 = temp & 0xff; 3746 p2_43 = temp & 0xff;
3742 p2_42 = (temp & 0xf00) >> 4; 3747 p2_42 = (temp & 0xf00) >> 4;
3743 outSISIDXREG(SISPART2,0x1f,p2_1f); 3748 SiS_SetReg(SISPART2, 0x1f, p2_1f);
3744 setSISIDXREG(SISPART2,0x20,0x0F,p2_20); 3749 SiS_SetRegANDOR(SISPART2, 0x20, 0x0F, p2_20);
3745 setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b); 3750 SiS_SetRegANDOR(SISPART2, 0x2b, 0xF0, p2_2b);
3746 setSISIDXREG(SISPART2,0x42,0x0F,p2_42); 3751 SiS_SetRegANDOR(SISPART2, 0x42, 0x0F, p2_42);
3747 outSISIDXREG(SISPART2,0x43,p2_43); 3752 SiS_SetReg(SISPART2, 0x43, p2_43);
3748 } 3753 }
3749 } 3754 }
3750} 3755}
@@ -3769,7 +3774,7 @@ sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
3769 case 1: 3774 case 1:
3770 y -= val; 3775 y -= val;
3771 if(y < 0) y = 0; 3776 if(y < 0) y = 0;
3772 outSISIDXREG(SISSR,0x05,0x86); 3777 SiS_SetReg(SISSR, 0x05, 0x86);
3773 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff)); 3778 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff));
3774 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE); 3779 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE);
3775 break; 3780 break;
@@ -3793,8 +3798,8 @@ sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
3793 p2_02 += 2; 3798 p2_02 += 2;
3794 } 3799 }
3795 } 3800 }
3796 outSISIDXREG(SISPART2,0x01,p2_01); 3801 SiS_SetReg(SISPART2, 0x01, p2_01);
3797 outSISIDXREG(SISPART2,0x02,p2_02); 3802 SiS_SetReg(SISPART2, 0x02, p2_02);
3798 } 3803 }
3799 } 3804 }
3800} 3805}
@@ -3811,7 +3816,7 @@ sisfb_post_setmode(struct sis_video_info *ivideo)
3811 u8 reg1; 3816 u8 reg1;
3812#endif 3817#endif
3813 3818
3814 outSISIDXREG(SISSR, 0x05, 0x86); 3819 SiS_SetReg(SISSR, 0x05, 0x86);
3815 3820
3816#ifdef CONFIG_FB_SIS_315 3821#ifdef CONFIG_FB_SIS_315
3817 sisfb_fixup_SR11(ivideo); 3822 sisfb_fixup_SR11(ivideo);
@@ -3835,7 +3840,7 @@ sisfb_post_setmode(struct sis_video_info *ivideo)
3835 crt1isoff = false; 3840 crt1isoff = false;
3836 reg = 0x80; 3841 reg = 0x80;
3837 } 3842 }
3838 setSISIDXREG(SISCR, 0x17, 0x7f, reg); 3843 SiS_SetRegANDOR(SISCR, 0x17, 0x7f, reg);
3839 } 3844 }
3840#endif 3845#endif
3841#ifdef CONFIG_FB_SIS_315 3846#ifdef CONFIG_FB_SIS_315
@@ -3849,8 +3854,8 @@ sisfb_post_setmode(struct sis_video_info *ivideo)
3849 reg = 0x00; 3854 reg = 0x00;
3850 reg1 = 0x00; 3855 reg1 = 0x00;
3851 } 3856 }
3852 setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg); 3857 SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
3853 setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1); 3858 SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, reg1);
3854 } 3859 }
3855#endif 3860#endif
3856 3861
@@ -3866,17 +3871,17 @@ sisfb_post_setmode(struct sis_video_info *ivideo)
3866 } 3871 }
3867 } 3872 }
3868 3873
3869 andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04); 3874 SiS_SetRegAND(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
3870 3875
3871 if(ivideo->currentvbflags & CRT2_TV) { 3876 if(ivideo->currentvbflags & CRT2_TV) {
3872 if(ivideo->vbflags2 & VB2_SISBRIDGE) { 3877 if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3873 inSISIDXREG(SISPART2,0x1f,ivideo->p2_1f); 3878 ivideo->p2_1f = SiS_GetReg(SISPART2, 0x1f);
3874 inSISIDXREG(SISPART2,0x20,ivideo->p2_20); 3879 ivideo->p2_20 = SiS_GetReg(SISPART2, 0x20);
3875 inSISIDXREG(SISPART2,0x2b,ivideo->p2_2b); 3880 ivideo->p2_2b = SiS_GetReg(SISPART2, 0x2b);
3876 inSISIDXREG(SISPART2,0x42,ivideo->p2_42); 3881 ivideo->p2_42 = SiS_GetReg(SISPART2, 0x42);
3877 inSISIDXREG(SISPART2,0x43,ivideo->p2_43); 3882 ivideo->p2_43 = SiS_GetReg(SISPART2, 0x43);
3878 inSISIDXREG(SISPART2,0x01,ivideo->p2_01); 3883 ivideo->p2_01 = SiS_GetReg(SISPART2, 0x01);
3879 inSISIDXREG(SISPART2,0x02,ivideo->p2_02); 3884 ivideo->p2_02 = SiS_GetReg(SISPART2, 0x02);
3880 } else if(ivideo->vbflags2 & VB2_CHRONTEL) { 3885 } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
3881 if(ivideo->chronteltype == 1) { 3886 if(ivideo->chronteltype == 1) {
3882 ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a); 3887 ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
@@ -4100,7 +4105,6 @@ sisfb_find_rom(struct pci_dev *pdev)
4100 struct sis_video_info *ivideo = pci_get_drvdata(pdev); 4105 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4101 void __iomem *rom_base; 4106 void __iomem *rom_base;
4102 unsigned char *myrombase = NULL; 4107 unsigned char *myrombase = NULL;
4103 u32 temp;
4104 size_t romsize; 4108 size_t romsize;
4105 4109
4106 /* First, try the official pci ROM functions (except 4110 /* First, try the official pci ROM functions (except
@@ -4114,14 +4118,6 @@ sisfb_find_rom(struct pci_dev *pdev)
4114 if(sisfb_check_rom(rom_base, ivideo)) { 4118 if(sisfb_check_rom(rom_base, ivideo)) {
4115 4119
4116 if((myrombase = vmalloc(65536))) { 4120 if((myrombase = vmalloc(65536))) {
4117
4118 /* Work around bug in pci/rom.c: Folks forgot to check
4119 * whether the size retrieved from the BIOS image eventually
4120 * is larger than the mapped size
4121 */
4122 if(pci_resource_len(pdev, PCI_ROM_RESOURCE) < romsize)
4123 romsize = pci_resource_len(pdev, PCI_ROM_RESOURCE);
4124
4125 memcpy_fromio(myrombase, rom_base, 4121 memcpy_fromio(myrombase, rom_base,
4126 (romsize > 65536) ? 65536 : romsize); 4122 (romsize > 65536) ? 65536 : romsize);
4127 } 4123 }
@@ -4135,43 +4131,29 @@ sisfb_find_rom(struct pci_dev *pdev)
4135 /* Otherwise do it the conventional way. */ 4131 /* Otherwise do it the conventional way. */
4136 4132
4137#if defined(__i386__) || defined(__x86_64__) 4133#if defined(__i386__) || defined(__x86_64__)
4134 {
4135 u32 temp;
4138 4136
4139 for(temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) { 4137 for (temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
4140 4138
4141 rom_base = ioremap(temp, 65536); 4139 rom_base = ioremap(temp, 65536);
4142 if(!rom_base) 4140 if (!rom_base)
4143 continue; 4141 continue;
4144
4145 if(!sisfb_check_rom(rom_base, ivideo)) {
4146 iounmap(rom_base);
4147 continue;
4148 }
4149 4142
4150 if((myrombase = vmalloc(65536))) 4143 if (!sisfb_check_rom(rom_base, ivideo)) {
4151 memcpy_fromio(myrombase, rom_base, 65536); 4144 iounmap(rom_base);
4152 4145 continue;
4153 iounmap(rom_base); 4146 }
4154 break;
4155
4156 }
4157 4147
4158#else 4148 if ((myrombase = vmalloc(65536)))
4149 memcpy_fromio(myrombase, rom_base, 65536);
4159 4150
4160 pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &temp); 4151 iounmap(rom_base);
4161 pci_write_config_dword(pdev, PCI_ROM_ADDRESS, 4152 break;
4162 (ivideo->video_base & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE);
4163 4153
4164 rom_base = ioremap(ivideo->video_base, 65536);
4165 if(rom_base) {
4166 if(sisfb_check_rom(rom_base, ivideo)) {
4167 if((myrombase = vmalloc(65536)))
4168 memcpy_fromio(myrombase, rom_base, 65536);
4169 } 4154 }
4170 iounmap(rom_base);
4171 }
4172
4173 pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp);
4174 4155
4156 }
4175#endif 4157#endif
4176 4158
4177 return myrombase; 4159 return myrombase;
@@ -4181,6 +4163,9 @@ static void __devinit
4181sisfb_post_map_vram(struct sis_video_info *ivideo, unsigned int *mapsize, 4163sisfb_post_map_vram(struct sis_video_info *ivideo, unsigned int *mapsize,
4182 unsigned int min) 4164 unsigned int min)
4183{ 4165{
4166 if (*mapsize < (min << 20))
4167 return;
4168
4184 ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize)); 4169 ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize));
4185 4170
4186 if(!ivideo->video_vbase) { 4171 if(!ivideo->video_vbase) {
@@ -4209,10 +4194,10 @@ sisfb_post_300_buswidth(struct sis_video_info *ivideo)
4209 unsigned char reg; 4194 unsigned char reg;
4210 int i, j; 4195 int i, j;
4211 4196
4212 andSISIDXREG(SISSR, 0x15, 0xFB); 4197 SiS_SetRegAND(SISSR, 0x15, 0xFB);
4213 orSISIDXREG(SISSR, 0x15, 0x04); 4198 SiS_SetRegOR(SISSR, 0x15, 0x04);
4214 outSISIDXREG(SISSR, 0x13, 0x00); 4199 SiS_SetReg(SISSR, 0x13, 0x00);
4215 outSISIDXREG(SISSR, 0x14, 0xBF); 4200 SiS_SetReg(SISSR, 0x14, 0xBF);
4216 4201
4217 for(i = 0; i < 2; i++) { 4202 for(i = 0; i < 2; i++) {
4218 temp = 0x1234; 4203 temp = 0x1234;
@@ -4220,12 +4205,12 @@ sisfb_post_300_buswidth(struct sis_video_info *ivideo)
4220 writew(temp, FBAddress); 4205 writew(temp, FBAddress);
4221 if(readw(FBAddress) == temp) 4206 if(readw(FBAddress) == temp)
4222 break; 4207 break;
4223 orSISIDXREG(SISSR, 0x3c, 0x01); 4208 SiS_SetRegOR(SISSR, 0x3c, 0x01);
4224 inSISIDXREG(SISSR, 0x05, reg); 4209 reg = SiS_GetReg(SISSR, 0x05);
4225 inSISIDXREG(SISSR, 0x05, reg); 4210 reg = SiS_GetReg(SISSR, 0x05);
4226 andSISIDXREG(SISSR, 0x3c, 0xfe); 4211 SiS_SetRegAND(SISSR, 0x3c, 0xfe);
4227 inSISIDXREG(SISSR, 0x05, reg); 4212 reg = SiS_GetReg(SISSR, 0x05);
4228 inSISIDXREG(SISSR, 0x05, reg); 4213 reg = SiS_GetReg(SISSR, 0x05);
4229 temp++; 4214 temp++;
4230 } 4215 }
4231 } 4216 }
@@ -4235,7 +4220,7 @@ sisfb_post_300_buswidth(struct sis_video_info *ivideo)
4235 writel(0x89ABCDEFL, (FBAddress + 8)); 4220 writel(0x89ABCDEFL, (FBAddress + 8));
4236 writel(0xCDEF0123L, (FBAddress + 12)); 4221 writel(0xCDEF0123L, (FBAddress + 12));
4237 4222
4238 inSISIDXREG(SISSR, 0x3b, reg); 4223 reg = SiS_GetReg(SISSR, 0x3b);
4239 if(reg & 0x01) { 4224 if(reg & 0x01) {
4240 if(readl((FBAddress + 12)) == 0xCDEF0123L) 4225 if(readl((FBAddress + 12)) == 0xCDEF0123L)
4241 return 4; /* Channel A 128bit */ 4226 return 4; /* Channel A 128bit */
@@ -4298,13 +4283,13 @@ sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth
4298 PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity; 4283 PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
4299 PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh; 4284 PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
4300 4285
4301 andSISIDXREG(SISSR, 0x15, 0xFB); /* Test */ 4286 SiS_SetRegAND(SISSR, 0x15, 0xFB); /* Test */
4302 orSISIDXREG(SISSR, 0x15, 0x04); /* Test */ 4287 SiS_SetRegOR(SISSR, 0x15, 0x04); /* Test */
4303 sr14 = (SiS_DRAMType[k][3] * buswidth) - 1; 4288 sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
4304 if(buswidth == 4) sr14 |= 0x80; 4289 if(buswidth == 4) sr14 |= 0x80;
4305 else if(buswidth == 2) sr14 |= 0x40; 4290 else if(buswidth == 2) sr14 |= 0x40;
4306 outSISIDXREG(SISSR, 0x13, SiS_DRAMType[k][4]); 4291 SiS_SetReg(SISSR, 0x13, SiS_DRAMType[k][4]);
4307 outSISIDXREG(SISSR, 0x14, sr14); 4292 SiS_SetReg(SISSR, 0x14, sr14);
4308 4293
4309 BankNumHigh <<= 16; 4294 BankNumHigh <<= 16;
4310 BankNumMid <<= 16; 4295 BankNumMid <<= 16;
@@ -4371,13 +4356,13 @@ sisfb_post_sis300(struct pci_dev *pdev)
4371 if(!ivideo->SiS_Pr.UseROM) 4356 if(!ivideo->SiS_Pr.UseROM)
4372 bios = NULL; 4357 bios = NULL;
4373 4358
4374 outSISIDXREG(SISSR, 0x05, 0x86); 4359 SiS_SetReg(SISSR, 0x05, 0x86);
4375 4360
4376 if(bios) { 4361 if(bios) {
4377 if(bios[0x52] & 0x80) { 4362 if(bios[0x52] & 0x80) {
4378 memtype = bios[0x52]; 4363 memtype = bios[0x52];
4379 } else { 4364 } else {
4380 inSISIDXREG(SISSR, 0x3a, memtype); 4365 memtype = SiS_GetReg(SISSR, 0x3a);
4381 } 4366 }
4382 memtype &= 0x07; 4367 memtype &= 0x07;
4383 } 4368 }
@@ -4401,19 +4386,19 @@ sisfb_post_sis300(struct pci_dev *pdev)
4401 v6 = bios[rindex++]; 4386 v6 = bios[rindex++];
4402 } 4387 }
4403 } 4388 }
4404 outSISIDXREG(SISSR, 0x28, v1); 4389 SiS_SetReg(SISSR, 0x28, v1);
4405 outSISIDXREG(SISSR, 0x29, v2); 4390 SiS_SetReg(SISSR, 0x29, v2);
4406 outSISIDXREG(SISSR, 0x2a, v3); 4391 SiS_SetReg(SISSR, 0x2a, v3);
4407 outSISIDXREG(SISSR, 0x2e, v4); 4392 SiS_SetReg(SISSR, 0x2e, v4);
4408 outSISIDXREG(SISSR, 0x2f, v5); 4393 SiS_SetReg(SISSR, 0x2f, v5);
4409 outSISIDXREG(SISSR, 0x30, v6); 4394 SiS_SetReg(SISSR, 0x30, v6);
4410 4395
4411 v1 = 0x10; 4396 v1 = 0x10;
4412 if(bios) 4397 if(bios)
4413 v1 = bios[0xa4]; 4398 v1 = bios[0xa4];
4414 outSISIDXREG(SISSR, 0x07, v1); /* DAC speed */ 4399 SiS_SetReg(SISSR, 0x07, v1); /* DAC speed */
4415 4400
4416 outSISIDXREG(SISSR, 0x11, 0x0f); /* DDC, power save */ 4401 SiS_SetReg(SISSR, 0x11, 0x0f); /* DDC, power save */
4417 4402
4418 v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a; 4403 v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
4419 v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00; 4404 v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
@@ -4430,91 +4415,91 @@ sisfb_post_sis300(struct pci_dev *pdev)
4430 } 4415 }
4431 if(ivideo->revision_id >= 0x80) 4416 if(ivideo->revision_id >= 0x80)
4432 v3 &= 0xfd; 4417 v3 &= 0xfd;
4433 outSISIDXREG(SISSR, 0x15, v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */ 4418 SiS_SetReg(SISSR, 0x15, v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
4434 outSISIDXREG(SISSR, 0x16, v2); 4419 SiS_SetReg(SISSR, 0x16, v2);
4435 outSISIDXREG(SISSR, 0x17, v3); 4420 SiS_SetReg(SISSR, 0x17, v3);
4436 outSISIDXREG(SISSR, 0x18, v4); 4421 SiS_SetReg(SISSR, 0x18, v4);
4437 outSISIDXREG(SISSR, 0x19, v5); 4422 SiS_SetReg(SISSR, 0x19, v5);
4438 outSISIDXREG(SISSR, 0x1a, v6); 4423 SiS_SetReg(SISSR, 0x1a, v6);
4439 outSISIDXREG(SISSR, 0x1b, v7); 4424 SiS_SetReg(SISSR, 0x1b, v7);
4440 outSISIDXREG(SISSR, 0x1c, v8); /* ---- */ 4425 SiS_SetReg(SISSR, 0x1c, v8); /* ---- */
4441 andSISIDXREG(SISSR, 0x15 ,0xfb); 4426 SiS_SetRegAND(SISSR, 0x15, 0xfb);
4442 orSISIDXREG(SISSR, 0x15, 0x04); 4427 SiS_SetRegOR(SISSR, 0x15, 0x04);
4443 if(bios) { 4428 if(bios) {
4444 if(bios[0x53] & 0x02) { 4429 if(bios[0x53] & 0x02) {
4445 orSISIDXREG(SISSR, 0x19, 0x20); 4430 SiS_SetRegOR(SISSR, 0x19, 0x20);
4446 } 4431 }
4447 } 4432 }
4448 v1 = 0x04; /* DAC pedestal (BIOS 0xe5) */ 4433 v1 = 0x04; /* DAC pedestal (BIOS 0xe5) */
4449 if(ivideo->revision_id >= 0x80) 4434 if(ivideo->revision_id >= 0x80)
4450 v1 |= 0x01; 4435 v1 |= 0x01;
4451 outSISIDXREG(SISSR, 0x1f, v1); 4436 SiS_SetReg(SISSR, 0x1f, v1);
4452 outSISIDXREG(SISSR, 0x20, 0xa4); /* linear & relocated io & disable a0000 */ 4437 SiS_SetReg(SISSR, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
4453 v1 = 0xf6; v2 = 0x0d; v3 = 0x00; 4438 v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
4454 if(bios) { 4439 if(bios) {
4455 v1 = bios[0xe8]; 4440 v1 = bios[0xe8];
4456 v2 = bios[0xe9]; 4441 v2 = bios[0xe9];
4457 v3 = bios[0xea]; 4442 v3 = bios[0xea];
4458 } 4443 }
4459 outSISIDXREG(SISSR, 0x23, v1); 4444 SiS_SetReg(SISSR, 0x23, v1);
4460 outSISIDXREG(SISSR, 0x24, v2); 4445 SiS_SetReg(SISSR, 0x24, v2);
4461 outSISIDXREG(SISSR, 0x25, v3); 4446 SiS_SetReg(SISSR, 0x25, v3);
4462 outSISIDXREG(SISSR, 0x21, 0x84); 4447 SiS_SetReg(SISSR, 0x21, 0x84);
4463 outSISIDXREG(SISSR, 0x22, 0x00); 4448 SiS_SetReg(SISSR, 0x22, 0x00);
4464 outSISIDXREG(SISCR, 0x37, 0x00); 4449 SiS_SetReg(SISCR, 0x37, 0x00);
4465 orSISIDXREG(SISPART1, 0x24, 0x01); /* unlock crt2 */ 4450 SiS_SetRegOR(SISPART1, 0x24, 0x01); /* unlock crt2 */
4466 outSISIDXREG(SISPART1, 0x00, 0x00); 4451 SiS_SetReg(SISPART1, 0x00, 0x00);
4467 v1 = 0x40; v2 = 0x11; 4452 v1 = 0x40; v2 = 0x11;
4468 if(bios) { 4453 if(bios) {
4469 v1 = bios[0xec]; 4454 v1 = bios[0xec];
4470 v2 = bios[0xeb]; 4455 v2 = bios[0xeb];
4471 } 4456 }
4472 outSISIDXREG(SISPART1, 0x02, v1); 4457 SiS_SetReg(SISPART1, 0x02, v1);
4473 4458
4474 if(ivideo->revision_id >= 0x80) 4459 if(ivideo->revision_id >= 0x80)
4475 v2 &= ~0x01; 4460 v2 &= ~0x01;
4476 4461
4477 inSISIDXREG(SISPART4, 0x00, reg); 4462 reg = SiS_GetReg(SISPART4, 0x00);
4478 if((reg == 1) || (reg == 2)) { 4463 if((reg == 1) || (reg == 2)) {
4479 outSISIDXREG(SISCR, 0x37, 0x02); 4464 SiS_SetReg(SISCR, 0x37, 0x02);
4480 outSISIDXREG(SISPART2, 0x00, 0x1c); 4465 SiS_SetReg(SISPART2, 0x00, 0x1c);
4481 v4 = 0x00; v5 = 0x00; v6 = 0x10; 4466 v4 = 0x00; v5 = 0x00; v6 = 0x10;
4482 if(ivideo->SiS_Pr.UseROM) { 4467 if(ivideo->SiS_Pr.UseROM) {
4483 v4 = bios[0xf5]; 4468 v4 = bios[0xf5];
4484 v5 = bios[0xf6]; 4469 v5 = bios[0xf6];
4485 v6 = bios[0xf7]; 4470 v6 = bios[0xf7];
4486 } 4471 }
4487 outSISIDXREG(SISPART4, 0x0d, v4); 4472 SiS_SetReg(SISPART4, 0x0d, v4);
4488 outSISIDXREG(SISPART4, 0x0e, v5); 4473 SiS_SetReg(SISPART4, 0x0e, v5);
4489 outSISIDXREG(SISPART4, 0x10, v6); 4474 SiS_SetReg(SISPART4, 0x10, v6);
4490 outSISIDXREG(SISPART4, 0x0f, 0x3f); 4475 SiS_SetReg(SISPART4, 0x0f, 0x3f);
4491 inSISIDXREG(SISPART4, 0x01, reg); 4476 reg = SiS_GetReg(SISPART4, 0x01);
4492 if(reg >= 0xb0) { 4477 if(reg >= 0xb0) {
4493 inSISIDXREG(SISPART4, 0x23, reg); 4478 reg = SiS_GetReg(SISPART4, 0x23);
4494 reg &= 0x20; 4479 reg &= 0x20;
4495 reg <<= 1; 4480 reg <<= 1;
4496 outSISIDXREG(SISPART4, 0x23, reg); 4481 SiS_SetReg(SISPART4, 0x23, reg);
4497 } 4482 }
4498 } else { 4483 } else {
4499 v2 &= ~0x10; 4484 v2 &= ~0x10;
4500 } 4485 }
4501 outSISIDXREG(SISSR, 0x32, v2); 4486 SiS_SetReg(SISSR, 0x32, v2);
4502 4487
4503 andSISIDXREG(SISPART1, 0x24, 0xfe); /* Lock CRT2 */ 4488 SiS_SetRegAND(SISPART1, 0x24, 0xfe); /* Lock CRT2 */
4504 4489
4505 inSISIDXREG(SISSR, 0x16, reg); 4490 reg = SiS_GetReg(SISSR, 0x16);
4506 reg &= 0xc3; 4491 reg &= 0xc3;
4507 outSISIDXREG(SISCR, 0x35, reg); 4492 SiS_SetReg(SISCR, 0x35, reg);
4508 outSISIDXREG(SISCR, 0x83, 0x00); 4493 SiS_SetReg(SISCR, 0x83, 0x00);
4509#if !defined(__i386__) && !defined(__x86_64__) 4494#if !defined(__i386__) && !defined(__x86_64__)
4510 if(sisfb_videoram) { 4495 if(sisfb_videoram) {
4511 outSISIDXREG(SISSR, 0x13, 0x28); /* ? */ 4496 SiS_SetReg(SISSR, 0x13, 0x28); /* ? */
4512 reg = ((sisfb_videoram >> 10) - 1) | 0x40; 4497 reg = ((sisfb_videoram >> 10) - 1) | 0x40;
4513 outSISIDXREG(SISSR, 0x14, reg); 4498 SiS_SetReg(SISSR, 0x14, reg);
4514 } else { 4499 } else {
4515#endif 4500#endif
4516 /* Need to map max FB size for finding out about RAM size */ 4501 /* Need to map max FB size for finding out about RAM size */
4517 mapsize = 64 << 20; 4502 mapsize = ivideo->video_size;
4518 sisfb_post_map_vram(ivideo, &mapsize, 4); 4503 sisfb_post_map_vram(ivideo, &mapsize, 4);
4519 4504
4520 if(ivideo->video_vbase) { 4505 if(ivideo->video_vbase) {
@@ -4523,8 +4508,8 @@ sisfb_post_sis300(struct pci_dev *pdev)
4523 } else { 4508 } else {
4524 printk(KERN_DEBUG 4509 printk(KERN_DEBUG
4525 "sisfb: Failed to map memory for size detection, assuming 8MB\n"); 4510 "sisfb: Failed to map memory for size detection, assuming 8MB\n");
4526 outSISIDXREG(SISSR, 0x13, 0x28); /* ? */ 4511 SiS_SetReg(SISSR, 0x13, 0x28); /* ? */
4527 outSISIDXREG(SISSR, 0x14, 0x47); /* 8MB, 64bit default */ 4512 SiS_SetReg(SISSR, 0x14, 0x47); /* 8MB, 64bit default */
4528 } 4513 }
4529#if !defined(__i386__) && !defined(__x86_64__) 4514#if !defined(__i386__) && !defined(__x86_64__)
4530 } 4515 }
@@ -4533,7 +4518,7 @@ sisfb_post_sis300(struct pci_dev *pdev)
4533 v1 = bios[0xe6]; 4518 v1 = bios[0xe6];
4534 v2 = bios[0xe7]; 4519 v2 = bios[0xe7];
4535 } else { 4520 } else {
4536 inSISIDXREG(SISSR, 0x3a, reg); 4521 reg = SiS_GetReg(SISSR, 0x3a);
4537 if((reg & 0x30) == 0x30) { 4522 if((reg & 0x30) == 0x30) {
4538 v1 = 0x04; /* PCI */ 4523 v1 = 0x04; /* PCI */
4539 v2 = 0x92; 4524 v2 = 0x92;
@@ -4542,8 +4527,8 @@ sisfb_post_sis300(struct pci_dev *pdev)
4542 v2 = 0xb2; 4527 v2 = 0xb2;
4543 } 4528 }
4544 } 4529 }
4545 outSISIDXREG(SISSR, 0x21, v1); 4530 SiS_SetReg(SISSR, 0x21, v1);
4546 outSISIDXREG(SISSR, 0x22, v2); 4531 SiS_SetReg(SISSR, 0x22, v2);
4547 4532
4548 /* Sense CRT1 */ 4533 /* Sense CRT1 */
4549 sisfb_sense_crt1(ivideo); 4534 sisfb_sense_crt1(ivideo);
@@ -4556,13 +4541,13 @@ sisfb_post_sis300(struct pci_dev *pdev)
4556 ivideo->SiS_Pr.VideoMemorySize = 8 << 20; 4541 ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
4557 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80); 4542 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
4558 4543
4559 outSISIDXREG(SISSR, 0x05, 0x86); 4544 SiS_SetReg(SISSR, 0x05, 0x86);
4560 4545
4561 /* Display off */ 4546 /* Display off */
4562 orSISIDXREG(SISSR, 0x01, 0x20); 4547 SiS_SetRegOR(SISSR, 0x01, 0x20);
4563 4548
4564 /* Save mode number in CR34 */ 4549 /* Save mode number in CR34 */
4565 outSISIDXREG(SISCR, 0x34, 0x2e); 4550 SiS_SetReg(SISCR, 0x34, 0x2e);
4566 4551
4567 /* Let everyone know what the current mode is */ 4552 /* Let everyone know what the current mode is */
4568 ivideo->modeprechange = 0x2e; 4553 ivideo->modeprechange = 0x2e;
@@ -4578,6 +4563,11 @@ sisfb_post_sis315330(struct pci_dev *pdev)
4578} 4563}
4579#endif 4564#endif
4580 4565
4566static inline int sisfb_xgi_is21(struct sis_video_info *ivideo)
4567{
4568 return ivideo->chip_real_id == XGI_21;
4569}
4570
4581static void __devinit 4571static void __devinit
4582sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay) 4572sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
4583{ 4573{
@@ -4585,7 +4575,7 @@ sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
4585 u8 reg; 4575 u8 reg;
4586 4576
4587 for(i = 0; i <= (delay * 10 * 36); i++) { 4577 for(i = 0; i <= (delay * 10 * 36); i++) {
4588 inSISIDXREG(SISSR, 0x05, reg); 4578 reg = SiS_GetReg(SISSR, 0x05);
4589 reg++; 4579 reg++;
4590 } 4580 }
4591} 4581}
@@ -4642,11 +4632,11 @@ sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
4642 return 1; 4632 return 1;
4643} 4633}
4644 4634
4645static void __devinit 4635static int __devinit
4646sisfb_post_xgi_ramsize(struct sis_video_info *ivideo) 4636sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
4647{ 4637{
4648 unsigned int buswidth, ranksize, channelab, mapsize; 4638 unsigned int buswidth, ranksize, channelab, mapsize;
4649 int i, j, k, l; 4639 int i, j, k, l, status;
4650 u8 reg, sr14; 4640 u8 reg, sr14;
4651 static const u8 dramsr13[12 * 5] = { 4641 static const u8 dramsr13[12 * 5] = {
4652 0x02, 0x0e, 0x0b, 0x80, 0x5d, 4642 0x02, 0x0e, 0x0b, 0x80, 0x5d,
@@ -4677,84 +4667,84 @@ sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
4677 * - if running on non-x86, there usually is no VGA window 4667 * - if running on non-x86, there usually is no VGA window
4678 * at a0000. 4668 * at a0000.
4679 */ 4669 */
4680 orSISIDXREG(SISSR, 0x20, (0x80 | 0x04)); 4670 SiS_SetRegOR(SISSR, 0x20, (0x80 | 0x04));
4681 4671
4682 /* Need to map max FB size for finding out about RAM size */ 4672 /* Need to map max FB size for finding out about RAM size */
4683 mapsize = 256 << 20; 4673 mapsize = ivideo->video_size;
4684 sisfb_post_map_vram(ivideo, &mapsize, 32); 4674 sisfb_post_map_vram(ivideo, &mapsize, 32);
4685 4675
4686 if(!ivideo->video_vbase) { 4676 if(!ivideo->video_vbase) {
4687 printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n"); 4677 printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n");
4688 outSISIDXREG(SISSR, 0x13, 0x35); 4678 SiS_SetReg(SISSR, 0x13, 0x35);
4689 outSISIDXREG(SISSR, 0x14, 0x41); 4679 SiS_SetReg(SISSR, 0x14, 0x41);
4690 /* TODO */ 4680 /* TODO */
4691 return; 4681 return -ENOMEM;
4692 } 4682 }
4693 4683
4694 /* Non-interleaving */ 4684 /* Non-interleaving */
4695 outSISIDXREG(SISSR, 0x15, 0x00); 4685 SiS_SetReg(SISSR, 0x15, 0x00);
4696 /* No tiling */ 4686 /* No tiling */
4697 outSISIDXREG(SISSR, 0x1c, 0x00); 4687 SiS_SetReg(SISSR, 0x1c, 0x00);
4698 4688
4699 if(ivideo->chip == XGI_20) { 4689 if(ivideo->chip == XGI_20) {
4700 4690
4701 channelab = 1; 4691 channelab = 1;
4702 inSISIDXREG(SISCR, 0x97, reg); 4692 reg = SiS_GetReg(SISCR, 0x97);
4703 if(!(reg & 0x01)) { /* Single 32/16 */ 4693 if(!(reg & 0x01)) { /* Single 32/16 */
4704 buswidth = 32; 4694 buswidth = 32;
4705 outSISIDXREG(SISSR, 0x13, 0xb1); 4695 SiS_SetReg(SISSR, 0x13, 0xb1);
4706 outSISIDXREG(SISSR, 0x14, 0x52); 4696 SiS_SetReg(SISSR, 0x14, 0x52);
4707 sisfb_post_xgi_delay(ivideo, 1); 4697 sisfb_post_xgi_delay(ivideo, 1);
4708 sr14 = 0x02; 4698 sr14 = 0x02;
4709 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) 4699 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4710 goto bail_out; 4700 goto bail_out;
4711 4701
4712 outSISIDXREG(SISSR, 0x13, 0x31); 4702 SiS_SetReg(SISSR, 0x13, 0x31);
4713 outSISIDXREG(SISSR, 0x14, 0x42); 4703 SiS_SetReg(SISSR, 0x14, 0x42);
4714 sisfb_post_xgi_delay(ivideo, 1); 4704 sisfb_post_xgi_delay(ivideo, 1);
4715 if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize)) 4705 if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize))
4716 goto bail_out; 4706 goto bail_out;
4717 4707
4718 buswidth = 16; 4708 buswidth = 16;
4719 outSISIDXREG(SISSR, 0x13, 0xb1); 4709 SiS_SetReg(SISSR, 0x13, 0xb1);
4720 outSISIDXREG(SISSR, 0x14, 0x41); 4710 SiS_SetReg(SISSR, 0x14, 0x41);
4721 sisfb_post_xgi_delay(ivideo, 1); 4711 sisfb_post_xgi_delay(ivideo, 1);
4722 sr14 = 0x01; 4712 sr14 = 0x01;
4723 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize)) 4713 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4724 goto bail_out; 4714 goto bail_out;
4725 else 4715 else
4726 outSISIDXREG(SISSR, 0x13, 0x31); 4716 SiS_SetReg(SISSR, 0x13, 0x31);
4727 } else { /* Dual 16/8 */ 4717 } else { /* Dual 16/8 */
4728 buswidth = 16; 4718 buswidth = 16;
4729 outSISIDXREG(SISSR, 0x13, 0xb1); 4719 SiS_SetReg(SISSR, 0x13, 0xb1);
4730 outSISIDXREG(SISSR, 0x14, 0x41); 4720 SiS_SetReg(SISSR, 0x14, 0x41);
4731 sisfb_post_xgi_delay(ivideo, 1); 4721 sisfb_post_xgi_delay(ivideo, 1);
4732 sr14 = 0x01; 4722 sr14 = 0x01;
4733 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize)) 4723 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4734 goto bail_out; 4724 goto bail_out;
4735 4725
4736 outSISIDXREG(SISSR, 0x13, 0x31); 4726 SiS_SetReg(SISSR, 0x13, 0x31);
4737 outSISIDXREG(SISSR, 0x14, 0x31); 4727 SiS_SetReg(SISSR, 0x14, 0x31);
4738 sisfb_post_xgi_delay(ivideo, 1); 4728 sisfb_post_xgi_delay(ivideo, 1);
4739 if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize)) 4729 if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize))
4740 goto bail_out; 4730 goto bail_out;
4741 4731
4742 buswidth = 8; 4732 buswidth = 8;
4743 outSISIDXREG(SISSR, 0x13, 0xb1); 4733 SiS_SetReg(SISSR, 0x13, 0xb1);
4744 outSISIDXREG(SISSR, 0x14, 0x30); 4734 SiS_SetReg(SISSR, 0x14, 0x30);
4745 sisfb_post_xgi_delay(ivideo, 1); 4735 sisfb_post_xgi_delay(ivideo, 1);
4746 sr14 = 0x00; 4736 sr14 = 0x00;
4747 if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize)) 4737 if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize))
4748 goto bail_out; 4738 goto bail_out;
4749 else 4739 else
4750 outSISIDXREG(SISSR, 0x13, 0x31); 4740 SiS_SetReg(SISSR, 0x13, 0x31);
4751 } 4741 }
4752 4742
4753 } else { /* XGI_40 */ 4743 } else { /* XGI_40 */
4754 4744
4755 inSISIDXREG(SISCR, 0x97, reg); 4745 reg = SiS_GetReg(SISCR, 0x97);
4756 if(!(reg & 0x10)) { 4746 if(!(reg & 0x10)) {
4757 inSISIDXREG(SISSR, 0x39, reg); 4747 reg = SiS_GetReg(SISSR, 0x39);
4758 reg >>= 1; 4748 reg >>= 1;
4759 } 4749 }
4760 4750
@@ -4762,52 +4752,52 @@ sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
4762 buswidth = 32; 4752 buswidth = 32;
4763 if(ivideo->revision_id == 2) { 4753 if(ivideo->revision_id == 2) {
4764 channelab = 2; 4754 channelab = 2;
4765 outSISIDXREG(SISSR, 0x13, 0xa1); 4755 SiS_SetReg(SISSR, 0x13, 0xa1);
4766 outSISIDXREG(SISSR, 0x14, 0x44); 4756 SiS_SetReg(SISSR, 0x14, 0x44);
4767 sr14 = 0x04; 4757 sr14 = 0x04;
4768 sisfb_post_xgi_delay(ivideo, 1); 4758 sisfb_post_xgi_delay(ivideo, 1);
4769 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) 4759 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4770 goto bail_out; 4760 goto bail_out;
4771 4761
4772 outSISIDXREG(SISSR, 0x13, 0x21); 4762 SiS_SetReg(SISSR, 0x13, 0x21);
4773 outSISIDXREG(SISSR, 0x14, 0x34); 4763 SiS_SetReg(SISSR, 0x14, 0x34);
4774 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize)) 4764 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4775 goto bail_out; 4765 goto bail_out;
4776 4766
4777 channelab = 1; 4767 channelab = 1;
4778 outSISIDXREG(SISSR, 0x13, 0xa1); 4768 SiS_SetReg(SISSR, 0x13, 0xa1);
4779 outSISIDXREG(SISSR, 0x14, 0x40); 4769 SiS_SetReg(SISSR, 0x14, 0x40);
4780 sr14 = 0x00; 4770 sr14 = 0x00;
4781 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize)) 4771 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4782 goto bail_out; 4772 goto bail_out;
4783 4773
4784 outSISIDXREG(SISSR, 0x13, 0x21); 4774 SiS_SetReg(SISSR, 0x13, 0x21);
4785 outSISIDXREG(SISSR, 0x14, 0x30); 4775 SiS_SetReg(SISSR, 0x14, 0x30);
4786 } else { 4776 } else {
4787 channelab = 3; 4777 channelab = 3;
4788 outSISIDXREG(SISSR, 0x13, 0xa1); 4778 SiS_SetReg(SISSR, 0x13, 0xa1);
4789 outSISIDXREG(SISSR, 0x14, 0x4c); 4779 SiS_SetReg(SISSR, 0x14, 0x4c);
4790 sr14 = 0x0c; 4780 sr14 = 0x0c;
4791 sisfb_post_xgi_delay(ivideo, 1); 4781 sisfb_post_xgi_delay(ivideo, 1);
4792 if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize)) 4782 if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize))
4793 goto bail_out; 4783 goto bail_out;
4794 4784
4795 channelab = 2; 4785 channelab = 2;
4796 outSISIDXREG(SISSR, 0x14, 0x48); 4786 SiS_SetReg(SISSR, 0x14, 0x48);
4797 sisfb_post_xgi_delay(ivideo, 1); 4787 sisfb_post_xgi_delay(ivideo, 1);
4798 sr14 = 0x08; 4788 sr14 = 0x08;
4799 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) 4789 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4800 goto bail_out; 4790 goto bail_out;
4801 4791
4802 outSISIDXREG(SISSR, 0x13, 0x21); 4792 SiS_SetReg(SISSR, 0x13, 0x21);
4803 outSISIDXREG(SISSR, 0x14, 0x3c); 4793 SiS_SetReg(SISSR, 0x14, 0x3c);
4804 sr14 = 0x0c; 4794 sr14 = 0x0c;
4805 4795
4806 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) { 4796 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) {
4807 channelab = 3; 4797 channelab = 3;
4808 } else { 4798 } else {
4809 channelab = 2; 4799 channelab = 2;
4810 outSISIDXREG(SISSR, 0x14, 0x38); 4800 SiS_SetReg(SISSR, 0x14, 0x38);
4811 sr14 = 0x08; 4801 sr14 = 0x08;
4812 } 4802 }
4813 } 4803 }
@@ -4818,26 +4808,26 @@ sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
4818 buswidth = 64; 4808 buswidth = 64;
4819 if(ivideo->revision_id == 2) { 4809 if(ivideo->revision_id == 2) {
4820 channelab = 1; 4810 channelab = 1;
4821 outSISIDXREG(SISSR, 0x13, 0xa1); 4811 SiS_SetReg(SISSR, 0x13, 0xa1);
4822 outSISIDXREG(SISSR, 0x14, 0x52); 4812 SiS_SetReg(SISSR, 0x14, 0x52);
4823 sisfb_post_xgi_delay(ivideo, 1); 4813 sisfb_post_xgi_delay(ivideo, 1);
4824 sr14 = 0x02; 4814 sr14 = 0x02;
4825 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) 4815 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4826 goto bail_out; 4816 goto bail_out;
4827 4817
4828 outSISIDXREG(SISSR, 0x13, 0x21); 4818 SiS_SetReg(SISSR, 0x13, 0x21);
4829 outSISIDXREG(SISSR, 0x14, 0x42); 4819 SiS_SetReg(SISSR, 0x14, 0x42);
4830 } else { 4820 } else {
4831 channelab = 2; 4821 channelab = 2;
4832 outSISIDXREG(SISSR, 0x13, 0xa1); 4822 SiS_SetReg(SISSR, 0x13, 0xa1);
4833 outSISIDXREG(SISSR, 0x14, 0x5a); 4823 SiS_SetReg(SISSR, 0x14, 0x5a);
4834 sisfb_post_xgi_delay(ivideo, 1); 4824 sisfb_post_xgi_delay(ivideo, 1);
4835 sr14 = 0x0a; 4825 sr14 = 0x0a;
4836 if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize)) 4826 if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize))
4837 goto bail_out; 4827 goto bail_out;
4838 4828
4839 outSISIDXREG(SISSR, 0x13, 0x21); 4829 SiS_SetReg(SISSR, 0x13, 0x21);
4840 outSISIDXREG(SISSR, 0x14, 0x4a); 4830 SiS_SetReg(SISSR, 0x14, 0x4a);
4841 } 4831 }
4842 sisfb_post_xgi_delay(ivideo, 1); 4832 sisfb_post_xgi_delay(ivideo, 1);
4843 4833
@@ -4845,23 +4835,24 @@ sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
4845 } 4835 }
4846 4836
4847bail_out: 4837bail_out:
4848 setSISIDXREG(SISSR, 0x14, 0xf0, sr14); 4838 SiS_SetRegANDOR(SISSR, 0x14, 0xf0, sr14);
4849 sisfb_post_xgi_delay(ivideo, 1); 4839 sisfb_post_xgi_delay(ivideo, 1);
4850 4840
4851 j = (ivideo->chip == XGI_20) ? 5 : 9; 4841 j = (ivideo->chip == XGI_20) ? 5 : 9;
4852 k = (ivideo->chip == XGI_20) ? 12 : 4; 4842 k = (ivideo->chip == XGI_20) ? 12 : 4;
4843 status = -EIO;
4853 4844
4854 for(i = 0; i < k; i++) { 4845 for(i = 0; i < k; i++) {
4855 4846
4856 reg = (ivideo->chip == XGI_20) ? 4847 reg = (ivideo->chip == XGI_20) ?
4857 dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4]; 4848 dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4];
4858 setSISIDXREG(SISSR, 0x13, 0x80, reg); 4849 SiS_SetRegANDOR(SISSR, 0x13, 0x80, reg);
4859 sisfb_post_xgi_delay(ivideo, 50); 4850 sisfb_post_xgi_delay(ivideo, 50);
4860 4851
4861 ranksize = (ivideo->chip == XGI_20) ? 4852 ranksize = (ivideo->chip == XGI_20) ?
4862 dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3]; 4853 dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3];
4863 4854
4864 inSISIDXREG(SISSR, 0x13, reg); 4855 reg = SiS_GetReg(SISSR, 0x13);
4865 if(reg & 0x80) ranksize <<= 1; 4856 if(reg & 0x80) ranksize <<= 1;
4866 4857
4867 if(ivideo->chip == XGI_20) { 4858 if(ivideo->chip == XGI_20) {
@@ -4880,14 +4871,18 @@ bail_out:
4880 4871
4881 if(!reg) continue; 4872 if(!reg) continue;
4882 4873
4883 setSISIDXREG(SISSR, 0x14, 0x0f, (reg & 0xf0)); 4874 SiS_SetRegANDOR(SISSR, 0x14, 0x0f, (reg & 0xf0));
4884 sisfb_post_xgi_delay(ivideo, 1); 4875 sisfb_post_xgi_delay(ivideo, 1);
4885 4876
4886 if(sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize)) 4877 if (sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize)) {
4878 status = 0;
4887 break; 4879 break;
4880 }
4888 } 4881 }
4889 4882
4890 iounmap(ivideo->video_vbase); 4883 iounmap(ivideo->video_vbase);
4884
4885 return status;
4891} 4886}
4892 4887
4893static void __devinit 4888static void __devinit
@@ -4925,9 +4920,9 @@ sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
4925 v2 = ivideo->bios_abase[0x90 + index + 1]; 4920 v2 = ivideo->bios_abase[0x90 + index + 1];
4926 v3 = ivideo->bios_abase[0x90 + index + 2]; 4921 v3 = ivideo->bios_abase[0x90 + index + 2];
4927 } 4922 }
4928 outSISIDXREG(SISSR, 0x28, v1); 4923 SiS_SetReg(SISSR, 0x28, v1);
4929 outSISIDXREG(SISSR, 0x29, v2); 4924 SiS_SetReg(SISSR, 0x29, v2);
4930 outSISIDXREG(SISSR, 0x2a, v3); 4925 SiS_SetReg(SISSR, 0x2a, v3);
4931 sisfb_post_xgi_delay(ivideo, 0x43); 4926 sisfb_post_xgi_delay(ivideo, 0x43);
4932 sisfb_post_xgi_delay(ivideo, 0x43); 4927 sisfb_post_xgi_delay(ivideo, 0x43);
4933 sisfb_post_xgi_delay(ivideo, 0x43); 4928 sisfb_post_xgi_delay(ivideo, 0x43);
@@ -4938,14 +4933,183 @@ sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
4938 v2 = ivideo->bios_abase[0xb8 + index + 1]; 4933 v2 = ivideo->bios_abase[0xb8 + index + 1];
4939 v3 = ivideo->bios_abase[0xb8 + index + 2]; 4934 v3 = ivideo->bios_abase[0xb8 + index + 2];
4940 } 4935 }
4941 outSISIDXREG(SISSR, 0x2e, v1); 4936 SiS_SetReg(SISSR, 0x2e, v1);
4942 outSISIDXREG(SISSR, 0x2f, v2); 4937 SiS_SetReg(SISSR, 0x2f, v2);
4943 outSISIDXREG(SISSR, 0x30, v3); 4938 SiS_SetReg(SISSR, 0x30, v3);
4944 sisfb_post_xgi_delay(ivideo, 0x43); 4939 sisfb_post_xgi_delay(ivideo, 0x43);
4945 sisfb_post_xgi_delay(ivideo, 0x43); 4940 sisfb_post_xgi_delay(ivideo, 0x43);
4946 sisfb_post_xgi_delay(ivideo, 0x43); 4941 sisfb_post_xgi_delay(ivideo, 0x43);
4947} 4942}
4948 4943
4944static void __devinit
4945sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info *ivideo, u8 regb)
4946{
4947 unsigned char *bios = ivideo->bios_abase;
4948 u8 v1;
4949
4950 SiS_SetReg(SISSR, 0x28, 0x64);
4951 SiS_SetReg(SISSR, 0x29, 0x63);
4952 sisfb_post_xgi_delay(ivideo, 15);
4953 SiS_SetReg(SISSR, 0x18, 0x00);
4954 SiS_SetReg(SISSR, 0x19, 0x20);
4955 SiS_SetReg(SISSR, 0x16, 0x00);
4956 SiS_SetReg(SISSR, 0x16, 0x80);
4957 SiS_SetReg(SISSR, 0x18, 0xc5);
4958 SiS_SetReg(SISSR, 0x19, 0x23);
4959 SiS_SetReg(SISSR, 0x16, 0x00);
4960 SiS_SetReg(SISSR, 0x16, 0x80);
4961 sisfb_post_xgi_delay(ivideo, 1);
4962 SiS_SetReg(SISCR, 0x97, 0x11);
4963 sisfb_post_xgi_setclocks(ivideo, regb);
4964 sisfb_post_xgi_delay(ivideo, 0x46);
4965 SiS_SetReg(SISSR, 0x18, 0xc5);
4966 SiS_SetReg(SISSR, 0x19, 0x23);
4967 SiS_SetReg(SISSR, 0x16, 0x00);
4968 SiS_SetReg(SISSR, 0x16, 0x80);
4969 sisfb_post_xgi_delay(ivideo, 1);
4970 SiS_SetReg(SISSR, 0x1b, 0x04);
4971 sisfb_post_xgi_delay(ivideo, 1);
4972 SiS_SetReg(SISSR, 0x1b, 0x00);
4973 sisfb_post_xgi_delay(ivideo, 1);
4974 v1 = 0x31;
4975 if (ivideo->haveXGIROM) {
4976 v1 = bios[0xf0];
4977 }
4978 SiS_SetReg(SISSR, 0x18, v1);
4979 SiS_SetReg(SISSR, 0x19, 0x06);
4980 SiS_SetReg(SISSR, 0x16, 0x04);
4981 SiS_SetReg(SISSR, 0x16, 0x84);
4982 sisfb_post_xgi_delay(ivideo, 1);
4983}
4984
4985static void __devinit
4986sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info *ivideo)
4987{
4988 sisfb_post_xgi_setclocks(ivideo, 1);
4989
4990 SiS_SetReg(SISCR, 0x97, 0x11);
4991 sisfb_post_xgi_delay(ivideo, 0x46);
4992
4993 SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS2 */
4994 SiS_SetReg(SISSR, 0x19, 0x80);
4995 SiS_SetReg(SISSR, 0x16, 0x05);
4996 SiS_SetReg(SISSR, 0x16, 0x85);
4997
4998 SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS3 */
4999 SiS_SetReg(SISSR, 0x19, 0xc0);
5000 SiS_SetReg(SISSR, 0x16, 0x05);
5001 SiS_SetReg(SISSR, 0x16, 0x85);
5002
5003 SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS1 */
5004 SiS_SetReg(SISSR, 0x19, 0x40);
5005 SiS_SetReg(SISSR, 0x16, 0x05);
5006 SiS_SetReg(SISSR, 0x16, 0x85);
5007
5008 SiS_SetReg(SISSR, 0x18, 0x42); /* MRS1 */
5009 SiS_SetReg(SISSR, 0x19, 0x02);
5010 SiS_SetReg(SISSR, 0x16, 0x05);
5011 SiS_SetReg(SISSR, 0x16, 0x85);
5012 sisfb_post_xgi_delay(ivideo, 1);
5013
5014 SiS_SetReg(SISSR, 0x1b, 0x04);
5015 sisfb_post_xgi_delay(ivideo, 1);
5016
5017 SiS_SetReg(SISSR, 0x1b, 0x00);
5018 sisfb_post_xgi_delay(ivideo, 1);
5019
5020 SiS_SetReg(SISSR, 0x18, 0x42); /* MRS1 */
5021 SiS_SetReg(SISSR, 0x19, 0x00);
5022 SiS_SetReg(SISSR, 0x16, 0x05);
5023 SiS_SetReg(SISSR, 0x16, 0x85);
5024 sisfb_post_xgi_delay(ivideo, 1);
5025}
5026
5027static void __devinit
5028sisfb_post_xgi_ddr2(struct sis_video_info *ivideo, u8 regb)
5029{
5030 unsigned char *bios = ivideo->bios_abase;
5031 static const u8 cs158[8] = {
5032 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5033 };
5034 static const u8 cs160[8] = {
5035 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5036 };
5037 static const u8 cs168[8] = {
5038 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5039 };
5040 u8 reg;
5041 u8 v1;
5042 u8 v2;
5043 u8 v3;
5044
5045 SiS_SetReg(SISCR, 0xb0, 0x80); /* DDR2 dual frequency mode */
5046 SiS_SetReg(SISCR, 0x82, 0x77);
5047 SiS_SetReg(SISCR, 0x86, 0x00);
5048 reg = SiS_GetReg(SISCR, 0x86);
5049 SiS_SetReg(SISCR, 0x86, 0x88);
5050 reg = SiS_GetReg(SISCR, 0x86);
5051 v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
5052 if (ivideo->haveXGIROM) {
5053 v1 = bios[regb + 0x168];
5054 v2 = bios[regb + 0x160];
5055 v3 = bios[regb + 0x158];
5056 }
5057 SiS_SetReg(SISCR, 0x86, v1);
5058 SiS_SetReg(SISCR, 0x82, 0x77);
5059 SiS_SetReg(SISCR, 0x85, 0x00);
5060 reg = SiS_GetReg(SISCR, 0x85);
5061 SiS_SetReg(SISCR, 0x85, 0x88);
5062 reg = SiS_GetReg(SISCR, 0x85);
5063 SiS_SetReg(SISCR, 0x85, v2);
5064 SiS_SetReg(SISCR, 0x82, v3);
5065 SiS_SetReg(SISCR, 0x98, 0x01);
5066 SiS_SetReg(SISCR, 0x9a, 0x02);
5067 if (sisfb_xgi_is21(ivideo))
5068 sisfb_post_xgi_ddr2_mrs_xg21(ivideo);
5069 else
5070 sisfb_post_xgi_ddr2_mrs_default(ivideo, regb);
5071}
5072
5073static u8 __devinit
5074sisfb_post_xgi_ramtype(struct sis_video_info *ivideo)
5075{
5076 unsigned char *bios = ivideo->bios_abase;
5077 u8 ramtype;
5078 u8 reg;
5079 u8 v1;
5080
5081 ramtype = 0x00; v1 = 0x10;
5082 if (ivideo->haveXGIROM) {
5083 ramtype = bios[0x62];
5084 v1 = bios[0x1d2];
5085 }
5086 if (!(ramtype & 0x80)) {
5087 if (sisfb_xgi_is21(ivideo)) {
5088 SiS_SetRegAND(SISCR, 0xb4, 0xfd); /* GPIO control */
5089 SiS_SetRegOR(SISCR, 0x4a, 0x80); /* GPIOH EN */
5090 reg = SiS_GetReg(SISCR, 0x48);
5091 SiS_SetRegOR(SISCR, 0xb4, 0x02);
5092 ramtype = reg & 0x01; /* GPIOH */
5093 } else if (ivideo->chip == XGI_20) {
5094 SiS_SetReg(SISCR, 0x97, v1);
5095 reg = SiS_GetReg(SISCR, 0x97);
5096 if (reg & 0x10) {
5097 ramtype = (reg & 0x01) << 1;
5098 }
5099 } else {
5100 reg = SiS_GetReg(SISSR, 0x39);
5101 ramtype = reg & 0x02;
5102 if (!(ramtype)) {
5103 reg = SiS_GetReg(SISSR, 0x3a);
5104 ramtype = (reg >> 1) & 0x01;
5105 }
5106 }
5107 }
5108 ramtype &= 0x07;
5109
5110 return ramtype;
5111}
5112
4949static int __devinit 5113static int __devinit
4950sisfb_post_xgi(struct pci_dev *pdev) 5114sisfb_post_xgi(struct pci_dev *pdev)
4951{ 5115{
@@ -5013,29 +5177,29 @@ sisfb_post_xgi(struct pci_dev *pdev)
5013 }; 5177 };
5014 5178
5015 /* VGA enable */ 5179 /* VGA enable */
5016 reg = inSISREG(SISVGAENABLE) | 0x01; 5180 reg = SiS_GetRegByte(SISVGAENABLE) | 0x01;
5017 outSISREG(SISVGAENABLE, reg); 5181 SiS_SetRegByte(SISVGAENABLE, reg);
5018 5182
5019 /* Misc */ 5183 /* Misc */
5020 reg = inSISREG(SISMISCR) | 0x01; 5184 reg = SiS_GetRegByte(SISMISCR) | 0x01;
5021 outSISREG(SISMISCW, reg); 5185 SiS_SetRegByte(SISMISCW, reg);
5022 5186
5023 /* Unlock SR */ 5187 /* Unlock SR */
5024 outSISIDXREG(SISSR, 0x05, 0x86); 5188 SiS_SetReg(SISSR, 0x05, 0x86);
5025 inSISIDXREG(SISSR, 0x05, reg); 5189 reg = SiS_GetReg(SISSR, 0x05);
5026 if(reg != 0xa1) 5190 if(reg != 0xa1)
5027 return 0; 5191 return 0;
5028 5192
5029 /* Clear some regs */ 5193 /* Clear some regs */
5030 for(i = 0; i < 0x22; i++) { 5194 for(i = 0; i < 0x22; i++) {
5031 if(0x06 + i == 0x20) continue; 5195 if(0x06 + i == 0x20) continue;
5032 outSISIDXREG(SISSR, 0x06 + i, 0x00); 5196 SiS_SetReg(SISSR, 0x06 + i, 0x00);
5033 } 5197 }
5034 for(i = 0; i < 0x0b; i++) { 5198 for(i = 0; i < 0x0b; i++) {
5035 outSISIDXREG(SISSR, 0x31 + i, 0x00); 5199 SiS_SetReg(SISSR, 0x31 + i, 0x00);
5036 } 5200 }
5037 for(i = 0; i < 0x10; i++) { 5201 for(i = 0; i < 0x10; i++) {
5038 outSISIDXREG(SISCR, 0x30 + i, 0x00); 5202 SiS_SetReg(SISCR, 0x30 + i, 0x00);
5039 } 5203 }
5040 5204
5041 ptr = cs78; 5205 ptr = cs78;
@@ -5043,7 +5207,7 @@ sisfb_post_xgi(struct pci_dev *pdev)
5043 ptr = (const u8 *)&bios[0x78]; 5207 ptr = (const u8 *)&bios[0x78];
5044 } 5208 }
5045 for(i = 0; i < 3; i++) { 5209 for(i = 0; i < 3; i++) {
5046 outSISIDXREG(SISSR, 0x23 + i, ptr[i]); 5210 SiS_SetReg(SISSR, 0x23 + i, ptr[i]);
5047 } 5211 }
5048 5212
5049 ptr = cs76; 5213 ptr = cs76;
@@ -5051,7 +5215,7 @@ sisfb_post_xgi(struct pci_dev *pdev)
5051 ptr = (const u8 *)&bios[0x76]; 5215 ptr = (const u8 *)&bios[0x76];
5052 } 5216 }
5053 for(i = 0; i < 2; i++) { 5217 for(i = 0; i < 2; i++) {
5054 outSISIDXREG(SISSR, 0x21 + i, ptr[i]); 5218 SiS_SetReg(SISSR, 0x21 + i, ptr[i]);
5055 } 5219 }
5056 5220
5057 v1 = 0x18; v2 = 0x00; 5221 v1 = 0x18; v2 = 0x00;
@@ -5059,83 +5223,83 @@ sisfb_post_xgi(struct pci_dev *pdev)
5059 v1 = bios[0x74]; 5223 v1 = bios[0x74];
5060 v2 = bios[0x75]; 5224 v2 = bios[0x75];
5061 } 5225 }
5062 outSISIDXREG(SISSR, 0x07, v1); 5226 SiS_SetReg(SISSR, 0x07, v1);
5063 outSISIDXREG(SISSR, 0x11, 0x0f); 5227 SiS_SetReg(SISSR, 0x11, 0x0f);
5064 outSISIDXREG(SISSR, 0x1f, v2); 5228 SiS_SetReg(SISSR, 0x1f, v2);
5065 /* PCI linear mode, RelIO enabled, A0000 decoding disabled */ 5229 /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
5066 outSISIDXREG(SISSR, 0x20, 0x80 | 0x20 | 0x04); 5230 SiS_SetReg(SISSR, 0x20, 0x80 | 0x20 | 0x04);
5067 outSISIDXREG(SISSR, 0x27, 0x74); 5231 SiS_SetReg(SISSR, 0x27, 0x74);
5068 5232
5069 ptr = cs7b; 5233 ptr = cs7b;
5070 if(ivideo->haveXGIROM) { 5234 if(ivideo->haveXGIROM) {
5071 ptr = (const u8 *)&bios[0x7b]; 5235 ptr = (const u8 *)&bios[0x7b];
5072 } 5236 }
5073 for(i = 0; i < 3; i++) { 5237 for(i = 0; i < 3; i++) {
5074 outSISIDXREG(SISSR, 0x31 + i, ptr[i]); 5238 SiS_SetReg(SISSR, 0x31 + i, ptr[i]);
5075 } 5239 }
5076 5240
5077 if(ivideo->chip == XGI_40) { 5241 if(ivideo->chip == XGI_40) {
5078 if(ivideo->revision_id == 2) { 5242 if(ivideo->revision_id == 2) {
5079 setSISIDXREG(SISSR, 0x3b, 0x3f, 0xc0); 5243 SiS_SetRegANDOR(SISSR, 0x3b, 0x3f, 0xc0);
5080 } 5244 }
5081 outSISIDXREG(SISCR, 0x7d, 0xfe); 5245 SiS_SetReg(SISCR, 0x7d, 0xfe);
5082 outSISIDXREG(SISCR, 0x7e, 0x0f); 5246 SiS_SetReg(SISCR, 0x7e, 0x0f);
5083 } 5247 }
5084 if(ivideo->revision_id == 0) { /* 40 *and* 20? */ 5248 if(ivideo->revision_id == 0) { /* 40 *and* 20? */
5085 andSISIDXREG(SISCR, 0x58, 0xd7); 5249 SiS_SetRegAND(SISCR, 0x58, 0xd7);
5086 inSISIDXREG(SISCR, 0xcb, reg); 5250 reg = SiS_GetReg(SISCR, 0xcb);
5087 if(reg & 0x20) { 5251 if(reg & 0x20) {
5088 setSISIDXREG(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */ 5252 SiS_SetRegANDOR(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
5089 } 5253 }
5090 } 5254 }
5091 5255
5092 reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00; 5256 reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00;
5093 setSISIDXREG(SISCR, 0x38, 0x1f, reg); 5257 SiS_SetRegANDOR(SISCR, 0x38, 0x1f, reg);
5094 5258
5095 if(ivideo->chip == XGI_20) { 5259 if(ivideo->chip == XGI_20) {
5096 outSISIDXREG(SISSR, 0x36, 0x70); 5260 SiS_SetReg(SISSR, 0x36, 0x70);
5097 } else { 5261 } else {
5098 outSISIDXREG(SISVID, 0x00, 0x86); 5262 SiS_SetReg(SISVID, 0x00, 0x86);
5099 outSISIDXREG(SISVID, 0x32, 0x00); 5263 SiS_SetReg(SISVID, 0x32, 0x00);
5100 outSISIDXREG(SISVID, 0x30, 0x00); 5264 SiS_SetReg(SISVID, 0x30, 0x00);
5101 outSISIDXREG(SISVID, 0x32, 0x01); 5265 SiS_SetReg(SISVID, 0x32, 0x01);
5102 outSISIDXREG(SISVID, 0x30, 0x00); 5266 SiS_SetReg(SISVID, 0x30, 0x00);
5103 andSISIDXREG(SISVID, 0x2f, 0xdf); 5267 SiS_SetRegAND(SISVID, 0x2f, 0xdf);
5104 andSISIDXREG(SISCAP, 0x00, 0x3f); 5268 SiS_SetRegAND(SISCAP, 0x00, 0x3f);
5105 5269
5106 outSISIDXREG(SISPART1, 0x2f, 0x01); 5270 SiS_SetReg(SISPART1, 0x2f, 0x01);
5107 outSISIDXREG(SISPART1, 0x00, 0x00); 5271 SiS_SetReg(SISPART1, 0x00, 0x00);
5108 outSISIDXREG(SISPART1, 0x02, bios[0x7e]); 5272 SiS_SetReg(SISPART1, 0x02, bios[0x7e]);
5109 outSISIDXREG(SISPART1, 0x2e, 0x08); 5273 SiS_SetReg(SISPART1, 0x2e, 0x08);
5110 andSISIDXREG(SISPART1, 0x35, 0x7f); 5274 SiS_SetRegAND(SISPART1, 0x35, 0x7f);
5111 andSISIDXREG(SISPART1, 0x50, 0xfe); 5275 SiS_SetRegAND(SISPART1, 0x50, 0xfe);
5112 5276
5113 inSISIDXREG(SISPART4, 0x00, reg); 5277 reg = SiS_GetReg(SISPART4, 0x00);
5114 if(reg == 1 || reg == 2) { 5278 if(reg == 1 || reg == 2) {
5115 outSISIDXREG(SISPART2, 0x00, 0x1c); 5279 SiS_SetReg(SISPART2, 0x00, 0x1c);
5116 outSISIDXREG(SISPART4, 0x0d, bios[0x7f]); 5280 SiS_SetReg(SISPART4, 0x0d, bios[0x7f]);
5117 outSISIDXREG(SISPART4, 0x0e, bios[0x80]); 5281 SiS_SetReg(SISPART4, 0x0e, bios[0x80]);
5118 outSISIDXREG(SISPART4, 0x10, bios[0x81]); 5282 SiS_SetReg(SISPART4, 0x10, bios[0x81]);
5119 andSISIDXREG(SISPART4, 0x0f, 0x3f); 5283 SiS_SetRegAND(SISPART4, 0x0f, 0x3f);
5120 5284
5121 inSISIDXREG(SISPART4, 0x01, reg); 5285 reg = SiS_GetReg(SISPART4, 0x01);
5122 if((reg & 0xf0) >= 0xb0) { 5286 if((reg & 0xf0) >= 0xb0) {
5123 inSISIDXREG(SISPART4, 0x23, reg); 5287 reg = SiS_GetReg(SISPART4, 0x23);
5124 if(reg & 0x20) reg |= 0x40; 5288 if(reg & 0x20) reg |= 0x40;
5125 outSISIDXREG(SISPART4, 0x23, reg); 5289 SiS_SetReg(SISPART4, 0x23, reg);
5126 reg = (reg & 0x20) ? 0x02 : 0x00; 5290 reg = (reg & 0x20) ? 0x02 : 0x00;
5127 setSISIDXREG(SISPART1, 0x1e, 0xfd, reg); 5291 SiS_SetRegANDOR(SISPART1, 0x1e, 0xfd, reg);
5128 } 5292 }
5129 } 5293 }
5130 5294
5131 v1 = bios[0x77]; 5295 v1 = bios[0x77];
5132 5296
5133 inSISIDXREG(SISSR, 0x3b, reg); 5297 reg = SiS_GetReg(SISSR, 0x3b);
5134 if(reg & 0x02) { 5298 if(reg & 0x02) {
5135 inSISIDXREG(SISSR, 0x3a, reg); 5299 reg = SiS_GetReg(SISSR, 0x3a);
5136 v2 = (reg & 0x30) >> 3; 5300 v2 = (reg & 0x30) >> 3;
5137 if(!(v2 & 0x04)) v2 ^= 0x02; 5301 if(!(v2 & 0x04)) v2 ^= 0x02;
5138 inSISIDXREG(SISSR, 0x39, reg); 5302 reg = SiS_GetReg(SISSR, 0x39);
5139 if(reg & 0x80) v2 |= 0x80; 5303 if(reg & 0x80) v2 |= 0x80;
5140 v2 |= 0x01; 5304 v2 |= 0x01;
5141 5305
@@ -5168,36 +5332,36 @@ sisfb_post_xgi(struct pci_dev *pdev)
5168 v2 |= 0x08; 5332 v2 |= 0x08;
5169 } 5333 }
5170 } 5334 }
5171 setSISIDXREG(SISCR, 0x5f, 0xf0, v2); 5335 SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, v2);
5172 } 5336 }
5173 outSISIDXREG(SISSR, 0x22, v1); 5337 SiS_SetReg(SISSR, 0x22, v1);
5174 5338
5175 if(ivideo->revision_id == 2) { 5339 if(ivideo->revision_id == 2) {
5176 inSISIDXREG(SISSR, 0x3b, v1); 5340 v1 = SiS_GetReg(SISSR, 0x3b);
5177 inSISIDXREG(SISSR, 0x3a, v2); 5341 v2 = SiS_GetReg(SISSR, 0x3a);
5178 regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8); 5342 regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8);
5179 if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) ) 5343 if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) )
5180 setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01); 5344 SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
5181 5345
5182 if((mypdev = pci_get_device(0x10de, 0x01e0, NULL))) { 5346 if((mypdev = pci_get_device(0x10de, 0x01e0, NULL))) {
5183 /* TODO: set CR5f &0xf1 | 0x01 for version 6570 5347 /* TODO: set CR5f &0xf1 | 0x01 for version 6570
5184 * of nforce 2 ROM 5348 * of nforce 2 ROM
5185 */ 5349 */
5186 if(0) 5350 if(0)
5187 setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01); 5351 SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
5188 pci_dev_put(mypdev); 5352 pci_dev_put(mypdev);
5189 } 5353 }
5190 } 5354 }
5191 5355
5192 v1 = 0x30; 5356 v1 = 0x30;
5193 inSISIDXREG(SISSR, 0x3b, reg); 5357 reg = SiS_GetReg(SISSR, 0x3b);
5194 inSISIDXREG(SISCR, 0x5f, v2); 5358 v2 = SiS_GetReg(SISCR, 0x5f);
5195 if((!(reg & 0x02)) && (v2 & 0x0e)) 5359 if((!(reg & 0x02)) && (v2 & 0x0e))
5196 v1 |= 0x08; 5360 v1 |= 0x08;
5197 outSISIDXREG(SISSR, 0x27, v1); 5361 SiS_SetReg(SISSR, 0x27, v1);
5198 5362
5199 if(bios[0x64] & 0x01) { 5363 if(bios[0x64] & 0x01) {
5200 setSISIDXREG(SISCR, 0x5f, 0xf0, bios[0x64]); 5364 SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, bios[0x64]);
5201 } 5365 }
5202 5366
5203 v1 = bios[0x4f7]; 5367 v1 = bios[0x4f7];
@@ -5205,45 +5369,59 @@ sisfb_post_xgi(struct pci_dev *pdev)
5205 regd = (regd >> 20) & 0x0f; 5369 regd = (regd >> 20) & 0x0f;
5206 if(regd == 1) { 5370 if(regd == 1) {
5207 v1 &= 0xfc; 5371 v1 &= 0xfc;
5208 orSISIDXREG(SISCR, 0x5f, 0x08); 5372 SiS_SetRegOR(SISCR, 0x5f, 0x08);
5209 } 5373 }
5210 outSISIDXREG(SISCR, 0x48, v1); 5374 SiS_SetReg(SISCR, 0x48, v1);
5211 5375
5212 setSISIDXREG(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb); 5376 SiS_SetRegANDOR(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
5213 setSISIDXREG(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f); 5377 SiS_SetRegANDOR(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
5214 setSISIDXREG(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f); 5378 SiS_SetRegANDOR(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
5215 setSISIDXREG(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7); 5379 SiS_SetRegANDOR(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
5216 setSISIDXREG(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f); 5380 SiS_SetRegANDOR(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
5217 outSISIDXREG(SISCR, 0x70, bios[0x4fc]); 5381 SiS_SetReg(SISCR, 0x70, bios[0x4fc]);
5218 setSISIDXREG(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f); 5382 SiS_SetRegANDOR(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
5219 outSISIDXREG(SISCR, 0x74, 0xd0); 5383 SiS_SetReg(SISCR, 0x74, 0xd0);
5220 setSISIDXREG(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30); 5384 SiS_SetRegANDOR(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
5221 setSISIDXREG(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f); 5385 SiS_SetRegANDOR(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
5222 setSISIDXREG(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f); 5386 SiS_SetRegANDOR(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
5223 v1 = bios[0x501]; 5387 v1 = bios[0x501];
5224 if((mypdev = pci_get_device(0x8086, 0x2530, NULL))) { 5388 if((mypdev = pci_get_device(0x8086, 0x2530, NULL))) {
5225 v1 = 0xf0; 5389 v1 = 0xf0;
5226 pci_dev_put(mypdev); 5390 pci_dev_put(mypdev);
5227 } 5391 }
5228 outSISIDXREG(SISCR, 0x77, v1); 5392 SiS_SetReg(SISCR, 0x77, v1);
5229 } 5393 }
5230 5394
5231 /* RAM type */ 5395 /* RAM type:
5232 5396 *
5233 regb = 0; /* ! */ 5397 * 0 == DDR1, 1 == DDR2, 2..7 == reserved?
5398 *
5399 * The code seems to written so that regb should equal ramtype,
5400 * however, so far it has been hardcoded to 0. Enable other values only
5401 * on XGI Z9, as it passes the POST, and add a warning for others.
5402 */
5403 ramtype = sisfb_post_xgi_ramtype(ivideo);
5404 if (!sisfb_xgi_is21(ivideo) && ramtype) {
5405 dev_warn(&pdev->dev,
5406 "RAM type something else than expected: %d\n",
5407 ramtype);
5408 regb = 0;
5409 } else {
5410 regb = ramtype;
5411 }
5234 5412
5235 v1 = 0xff; 5413 v1 = 0xff;
5236 if(ivideo->haveXGIROM) { 5414 if(ivideo->haveXGIROM) {
5237 v1 = bios[0x140 + regb]; 5415 v1 = bios[0x140 + regb];
5238 } 5416 }
5239 outSISIDXREG(SISCR, 0x6d, v1); 5417 SiS_SetReg(SISCR, 0x6d, v1);
5240 5418
5241 ptr = cs128; 5419 ptr = cs128;
5242 if(ivideo->haveXGIROM) { 5420 if(ivideo->haveXGIROM) {
5243 ptr = (const u8 *)&bios[0x128]; 5421 ptr = (const u8 *)&bios[0x128];
5244 } 5422 }
5245 for(i = 0, j = 0; i < 3; i++, j += 8) { 5423 for(i = 0, j = 0; i < 3; i++, j += 8) {
5246 outSISIDXREG(SISCR, 0x68 + i, ptr[j + regb]); 5424 SiS_SetReg(SISCR, 0x68 + i, ptr[j + regb]);
5247 } 5425 }
5248 5426
5249 ptr = cs31a; 5427 ptr = cs31a;
@@ -5267,14 +5445,14 @@ sisfb_post_xgi(struct pci_dev *pdev)
5267 if(regd & 0x01) reg |= 0x04; 5445 if(regd & 0x01) reg |= 0x04;
5268 if(regd & 0x02) reg |= 0x08; 5446 if(regd & 0x02) reg |= 0x08;
5269 regd >>= 2; 5447 regd >>= 2;
5270 outSISIDXREG(SISCR, rega, reg); 5448 SiS_SetReg(SISCR, rega, reg);
5271 inSISIDXREG(SISCR, rega, reg); 5449 reg = SiS_GetReg(SISCR, rega);
5272 inSISIDXREG(SISCR, rega, reg); 5450 reg = SiS_GetReg(SISCR, rega);
5273 reg += 0x10; 5451 reg += 0x10;
5274 } 5452 }
5275 } 5453 }
5276 5454
5277 andSISIDXREG(SISCR, 0x6e, 0xfc); 5455 SiS_SetRegAND(SISCR, 0x6e, 0xfc);
5278 5456
5279 ptr = NULL; 5457 ptr = NULL;
5280 if(ivideo->haveXGIROM) { 5458 if(ivideo->haveXGIROM) {
@@ -5282,7 +5460,7 @@ sisfb_post_xgi(struct pci_dev *pdev)
5282 ptr = (const u8 *)&bios[index]; 5460 ptr = (const u8 *)&bios[index];
5283 } 5461 }
5284 for(i = 0; i < 4; i++) { 5462 for(i = 0; i < 4; i++) {
5285 setSISIDXREG(SISCR, 0x6e, 0xfc, i); 5463 SiS_SetRegANDOR(SISCR, 0x6e, 0xfc, i);
5286 reg = 0x00; 5464 reg = 0x00;
5287 for(j = 0; j < 2; j++) { 5465 for(j = 0; j < 2; j++) {
5288 regd = 0; 5466 regd = 0;
@@ -5296,9 +5474,9 @@ sisfb_post_xgi(struct pci_dev *pdev)
5296 if(regd & 0x01) reg |= 0x01; 5474 if(regd & 0x01) reg |= 0x01;
5297 if(regd & 0x02) reg |= 0x02; 5475 if(regd & 0x02) reg |= 0x02;
5298 regd >>= 2; 5476 regd >>= 2;
5299 outSISIDXREG(SISCR, 0x6f, reg); 5477 SiS_SetReg(SISCR, 0x6f, reg);
5300 inSISIDXREG(SISCR, 0x6f, reg); 5478 reg = SiS_GetReg(SISCR, 0x6f);
5301 inSISIDXREG(SISCR, 0x6f, reg); 5479 reg = SiS_GetReg(SISCR, 0x6f);
5302 reg += 0x08; 5480 reg += 0x08;
5303 } 5481 }
5304 } 5482 }
@@ -5309,10 +5487,10 @@ sisfb_post_xgi(struct pci_dev *pdev)
5309 ptr = (const u8 *)&bios[0x148]; 5487 ptr = (const u8 *)&bios[0x148];
5310 } 5488 }
5311 for(i = 0, j = 0; i < 2; i++, j += 8) { 5489 for(i = 0, j = 0; i < 2; i++, j += 8) {
5312 outSISIDXREG(SISCR, 0x80 + i, ptr[j + regb]); 5490 SiS_SetReg(SISCR, 0x80 + i, ptr[j + regb]);
5313 } 5491 }
5314 5492
5315 andSISIDXREG(SISCR, 0x89, 0x8f); 5493 SiS_SetRegAND(SISCR, 0x89, 0x8f);
5316 5494
5317 ptr = cs45a; 5495 ptr = cs45a;
5318 if(ivideo->haveXGIROM) { 5496 if(ivideo->haveXGIROM) {
@@ -5326,9 +5504,9 @@ sisfb_post_xgi(struct pci_dev *pdev)
5326 if(regd & 0x01) reg |= 0x01; 5504 if(regd & 0x01) reg |= 0x01;
5327 if(regd & 0x02) reg |= 0x02; 5505 if(regd & 0x02) reg |= 0x02;
5328 regd >>= 2; 5506 regd >>= 2;
5329 outSISIDXREG(SISCR, 0x89, reg); 5507 SiS_SetReg(SISCR, 0x89, reg);
5330 inSISIDXREG(SISCR, 0x89, reg); 5508 reg = SiS_GetReg(SISCR, 0x89);
5331 inSISIDXREG(SISCR, 0x89, reg); 5509 reg = SiS_GetReg(SISCR, 0x89);
5332 reg += 0x10; 5510 reg += 0x10;
5333 } 5511 }
5334 5512
@@ -5339,27 +5517,27 @@ sisfb_post_xgi(struct pci_dev *pdev)
5339 v3 = bios[0x120 + regb]; 5517 v3 = bios[0x120 + regb];
5340 v4 = bios[0x1ca]; 5518 v4 = bios[0x1ca];
5341 } 5519 }
5342 outSISIDXREG(SISCR, 0x45, v1 & 0x0f); 5520 SiS_SetReg(SISCR, 0x45, v1 & 0x0f);
5343 outSISIDXREG(SISCR, 0x99, (v1 >> 4) & 0x07); 5521 SiS_SetReg(SISCR, 0x99, (v1 >> 4) & 0x07);
5344 orSISIDXREG(SISCR, 0x40, v1 & 0x80); 5522 SiS_SetRegOR(SISCR, 0x40, v1 & 0x80);
5345 outSISIDXREG(SISCR, 0x41, v2); 5523 SiS_SetReg(SISCR, 0x41, v2);
5346 5524
5347 ptr = cs170; 5525 ptr = cs170;
5348 if(ivideo->haveXGIROM) { 5526 if(ivideo->haveXGIROM) {
5349 ptr = (const u8 *)&bios[0x170]; 5527 ptr = (const u8 *)&bios[0x170];
5350 } 5528 }
5351 for(i = 0, j = 0; i < 7; i++, j += 8) { 5529 for(i = 0, j = 0; i < 7; i++, j += 8) {
5352 outSISIDXREG(SISCR, 0x90 + i, ptr[j + regb]); 5530 SiS_SetReg(SISCR, 0x90 + i, ptr[j + regb]);
5353 } 5531 }
5354 5532
5355 outSISIDXREG(SISCR, 0x59, v3); 5533 SiS_SetReg(SISCR, 0x59, v3);
5356 5534
5357 ptr = cs1a8; 5535 ptr = cs1a8;
5358 if(ivideo->haveXGIROM) { 5536 if(ivideo->haveXGIROM) {
5359 ptr = (const u8 *)&bios[0x1a8]; 5537 ptr = (const u8 *)&bios[0x1a8];
5360 } 5538 }
5361 for(i = 0, j = 0; i < 3; i++, j += 8) { 5539 for(i = 0, j = 0; i < 3; i++, j += 8) {
5362 outSISIDXREG(SISCR, 0xc3 + i, ptr[j + regb]); 5540 SiS_SetReg(SISCR, 0xc3 + i, ptr[j + regb]);
5363 } 5541 }
5364 5542
5365 ptr = cs100; 5543 ptr = cs100;
@@ -5367,53 +5545,31 @@ sisfb_post_xgi(struct pci_dev *pdev)
5367 ptr = (const u8 *)&bios[0x100]; 5545 ptr = (const u8 *)&bios[0x100];
5368 } 5546 }
5369 for(i = 0, j = 0; i < 2; i++, j += 8) { 5547 for(i = 0, j = 0; i < 2; i++, j += 8) {
5370 outSISIDXREG(SISCR, 0x8a + i, ptr[j + regb]); 5548 SiS_SetReg(SISCR, 0x8a + i, ptr[j + regb]);
5371 } 5549 }
5372 5550
5373 outSISIDXREG(SISCR, 0xcf, v4); 5551 SiS_SetReg(SISCR, 0xcf, v4);
5374 5552
5375 outSISIDXREG(SISCR, 0x83, 0x09); 5553 SiS_SetReg(SISCR, 0x83, 0x09);
5376 outSISIDXREG(SISCR, 0x87, 0x00); 5554 SiS_SetReg(SISCR, 0x87, 0x00);
5377 5555
5378 if(ivideo->chip == XGI_40) { 5556 if(ivideo->chip == XGI_40) {
5379 if( (ivideo->revision_id == 1) || 5557 if( (ivideo->revision_id == 1) ||
5380 (ivideo->revision_id == 2) ) { 5558 (ivideo->revision_id == 2) ) {
5381 outSISIDXREG(SISCR, 0x8c, 0x87); 5559 SiS_SetReg(SISCR, 0x8c, 0x87);
5382 } 5560 }
5383 } 5561 }
5384 5562
5385 outSISIDXREG(SISSR, 0x17, 0x00); 5563 if (regb == 1)
5386 outSISIDXREG(SISSR, 0x1a, 0x87); 5564 SiS_SetReg(SISSR, 0x17, 0x80); /* DDR2 */
5565 else
5566 SiS_SetReg(SISSR, 0x17, 0x00); /* DDR1 */
5567 SiS_SetReg(SISSR, 0x1a, 0x87);
5387 5568
5388 if(ivideo->chip == XGI_20) { 5569 if(ivideo->chip == XGI_20) {
5389 outSISIDXREG(SISSR, 0x15, 0x00); 5570 SiS_SetReg(SISSR, 0x15, 0x00);
5390 outSISIDXREG(SISSR, 0x1c, 0x00); 5571 SiS_SetReg(SISSR, 0x1c, 0x00);
5391 }
5392
5393 ramtype = 0x00; v1 = 0x10;
5394 if(ivideo->haveXGIROM) {
5395 ramtype = bios[0x62];
5396 v1 = bios[0x1d2];
5397 } 5572 }
5398 if(!(ramtype & 0x80)) {
5399 if(ivideo->chip == XGI_20) {
5400 outSISIDXREG(SISCR, 0x97, v1);
5401 inSISIDXREG(SISCR, 0x97, reg);
5402 if(reg & 0x10) {
5403 ramtype = (reg & 0x01) << 1;
5404 }
5405 } else {
5406 inSISIDXREG(SISSR, 0x39, reg);
5407 ramtype = reg & 0x02;
5408 if(!(ramtype)) {
5409 inSISIDXREG(SISSR, 0x3a, reg);
5410 ramtype = (reg >> 1) & 0x01;
5411 }
5412 }
5413 }
5414 ramtype &= 0x07;
5415
5416 regb = 0; /* ! */
5417 5573
5418 switch(ramtype) { 5574 switch(ramtype) {
5419 case 0: 5575 case 0:
@@ -5427,55 +5583,55 @@ sisfb_post_xgi(struct pci_dev *pdev)
5427 v2 = bios[regb + 0x160]; 5583 v2 = bios[regb + 0x160];
5428 v3 = bios[regb + 0x168]; 5584 v3 = bios[regb + 0x168];
5429 } 5585 }
5430 outSISIDXREG(SISCR, 0x82, v1); 5586 SiS_SetReg(SISCR, 0x82, v1);
5431 outSISIDXREG(SISCR, 0x85, v2); 5587 SiS_SetReg(SISCR, 0x85, v2);
5432 outSISIDXREG(SISCR, 0x86, v3); 5588 SiS_SetReg(SISCR, 0x86, v3);
5433 } else { 5589 } else {
5434 outSISIDXREG(SISCR, 0x82, 0x88); 5590 SiS_SetReg(SISCR, 0x82, 0x88);
5435 outSISIDXREG(SISCR, 0x86, 0x00); 5591 SiS_SetReg(SISCR, 0x86, 0x00);
5436 inSISIDXREG(SISCR, 0x86, reg); 5592 reg = SiS_GetReg(SISCR, 0x86);
5437 outSISIDXREG(SISCR, 0x86, 0x88); 5593 SiS_SetReg(SISCR, 0x86, 0x88);
5438 inSISIDXREG(SISCR, 0x86, reg); 5594 reg = SiS_GetReg(SISCR, 0x86);
5439 outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]); 5595 SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
5440 outSISIDXREG(SISCR, 0x82, 0x77); 5596 SiS_SetReg(SISCR, 0x82, 0x77);
5441 outSISIDXREG(SISCR, 0x85, 0x00); 5597 SiS_SetReg(SISCR, 0x85, 0x00);
5442 inSISIDXREG(SISCR, 0x85, reg); 5598 reg = SiS_GetReg(SISCR, 0x85);
5443 outSISIDXREG(SISCR, 0x85, 0x88); 5599 SiS_SetReg(SISCR, 0x85, 0x88);
5444 inSISIDXREG(SISCR, 0x85, reg); 5600 reg = SiS_GetReg(SISCR, 0x85);
5445 outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]); 5601 SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
5446 outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]); 5602 SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
5447 } 5603 }
5448 if(ivideo->chip == XGI_40) { 5604 if(ivideo->chip == XGI_40) {
5449 outSISIDXREG(SISCR, 0x97, 0x00); 5605 SiS_SetReg(SISCR, 0x97, 0x00);
5450 } 5606 }
5451 outSISIDXREG(SISCR, 0x98, 0x01); 5607 SiS_SetReg(SISCR, 0x98, 0x01);
5452 outSISIDXREG(SISCR, 0x9a, 0x02); 5608 SiS_SetReg(SISCR, 0x9a, 0x02);
5453 5609
5454 outSISIDXREG(SISSR, 0x18, 0x01); 5610 SiS_SetReg(SISSR, 0x18, 0x01);
5455 if((ivideo->chip == XGI_20) || 5611 if((ivideo->chip == XGI_20) ||
5456 (ivideo->revision_id == 2)) { 5612 (ivideo->revision_id == 2)) {
5457 outSISIDXREG(SISSR, 0x19, 0x40); 5613 SiS_SetReg(SISSR, 0x19, 0x40);
5458 } else { 5614 } else {
5459 outSISIDXREG(SISSR, 0x19, 0x20); 5615 SiS_SetReg(SISSR, 0x19, 0x20);
5460 } 5616 }
5461 outSISIDXREG(SISSR, 0x16, 0x00); 5617 SiS_SetReg(SISSR, 0x16, 0x00);
5462 outSISIDXREG(SISSR, 0x16, 0x80); 5618 SiS_SetReg(SISSR, 0x16, 0x80);
5463 if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) { 5619 if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) {
5464 sisfb_post_xgi_delay(ivideo, 0x43); 5620 sisfb_post_xgi_delay(ivideo, 0x43);
5465 sisfb_post_xgi_delay(ivideo, 0x43); 5621 sisfb_post_xgi_delay(ivideo, 0x43);
5466 sisfb_post_xgi_delay(ivideo, 0x43); 5622 sisfb_post_xgi_delay(ivideo, 0x43);
5467 outSISIDXREG(SISSR, 0x18, 0x00); 5623 SiS_SetReg(SISSR, 0x18, 0x00);
5468 if((ivideo->chip == XGI_20) || 5624 if((ivideo->chip == XGI_20) ||
5469 (ivideo->revision_id == 2)) { 5625 (ivideo->revision_id == 2)) {
5470 outSISIDXREG(SISSR, 0x19, 0x40); 5626 SiS_SetReg(SISSR, 0x19, 0x40);
5471 } else { 5627 } else {
5472 outSISIDXREG(SISSR, 0x19, 0x20); 5628 SiS_SetReg(SISSR, 0x19, 0x20);
5473 } 5629 }
5474 } else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) { 5630 } else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) {
5475 /* outSISIDXREG(SISSR, 0x16, 0x0c); */ /* ? */ 5631 /* SiS_SetReg(SISSR, 0x16, 0x0c); */ /* ? */
5476 } 5632 }
5477 outSISIDXREG(SISSR, 0x16, 0x00); 5633 SiS_SetReg(SISSR, 0x16, 0x00);
5478 outSISIDXREG(SISSR, 0x16, 0x80); 5634 SiS_SetReg(SISSR, 0x16, 0x80);
5479 sisfb_post_xgi_delay(ivideo, 4); 5635 sisfb_post_xgi_delay(ivideo, 4);
5480 v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83; 5636 v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83;
5481 if(ivideo->haveXGIROM) { 5637 if(ivideo->haveXGIROM) {
@@ -5486,160 +5642,106 @@ sisfb_post_xgi(struct pci_dev *pdev)
5486 v4 = bios[index + 2]; 5642 v4 = bios[index + 2];
5487 v5 = bios[index + 3]; 5643 v5 = bios[index + 3];
5488 } 5644 }
5489 outSISIDXREG(SISSR, 0x18, v1); 5645 SiS_SetReg(SISSR, 0x18, v1);
5490 outSISIDXREG(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01)); 5646 SiS_SetReg(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
5491 outSISIDXREG(SISSR, 0x16, v2); 5647 SiS_SetReg(SISSR, 0x16, v2);
5492 outSISIDXREG(SISSR, 0x16, v3); 5648 SiS_SetReg(SISSR, 0x16, v3);
5493 sisfb_post_xgi_delay(ivideo, 0x43); 5649 sisfb_post_xgi_delay(ivideo, 0x43);
5494 outSISIDXREG(SISSR, 0x1b, 0x03); 5650 SiS_SetReg(SISSR, 0x1b, 0x03);
5495 sisfb_post_xgi_delay(ivideo, 0x22); 5651 sisfb_post_xgi_delay(ivideo, 0x22);
5496 outSISIDXREG(SISSR, 0x18, v1); 5652 SiS_SetReg(SISSR, 0x18, v1);
5497 outSISIDXREG(SISSR, 0x19, 0x00); 5653 SiS_SetReg(SISSR, 0x19, 0x00);
5498 outSISIDXREG(SISSR, 0x16, v4); 5654 SiS_SetReg(SISSR, 0x16, v4);
5499 outSISIDXREG(SISSR, 0x16, v5); 5655 SiS_SetReg(SISSR, 0x16, v5);
5500 outSISIDXREG(SISSR, 0x1b, 0x00); 5656 SiS_SetReg(SISSR, 0x1b, 0x00);
5501 break; 5657 break;
5502 case 1: 5658 case 1:
5503 outSISIDXREG(SISCR, 0x82, 0x77); 5659 sisfb_post_xgi_ddr2(ivideo, regb);
5504 outSISIDXREG(SISCR, 0x86, 0x00);
5505 inSISIDXREG(SISCR, 0x86, reg);
5506 outSISIDXREG(SISCR, 0x86, 0x88);
5507 inSISIDXREG(SISCR, 0x86, reg);
5508 v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
5509 if(ivideo->haveXGIROM) {
5510 v1 = bios[regb + 0x168];
5511 v2 = bios[regb + 0x160];
5512 v3 = bios[regb + 0x158];
5513 }
5514 outSISIDXREG(SISCR, 0x86, v1);
5515 outSISIDXREG(SISCR, 0x82, 0x77);
5516 outSISIDXREG(SISCR, 0x85, 0x00);
5517 inSISIDXREG(SISCR, 0x85, reg);
5518 outSISIDXREG(SISCR, 0x85, 0x88);
5519 inSISIDXREG(SISCR, 0x85, reg);
5520 outSISIDXREG(SISCR, 0x85, v2);
5521 outSISIDXREG(SISCR, 0x82, v3);
5522 outSISIDXREG(SISCR, 0x98, 0x01);
5523 outSISIDXREG(SISCR, 0x9a, 0x02);
5524
5525 outSISIDXREG(SISSR, 0x28, 0x64);
5526 outSISIDXREG(SISSR, 0x29, 0x63);
5527 sisfb_post_xgi_delay(ivideo, 15);
5528 outSISIDXREG(SISSR, 0x18, 0x00);
5529 outSISIDXREG(SISSR, 0x19, 0x20);
5530 outSISIDXREG(SISSR, 0x16, 0x00);
5531 outSISIDXREG(SISSR, 0x16, 0x80);
5532 outSISIDXREG(SISSR, 0x18, 0xc5);
5533 outSISIDXREG(SISSR, 0x19, 0x23);
5534 outSISIDXREG(SISSR, 0x16, 0x00);
5535 outSISIDXREG(SISSR, 0x16, 0x80);
5536 sisfb_post_xgi_delay(ivideo, 1);
5537 outSISIDXREG(SISCR, 0x97,0x11);
5538 sisfb_post_xgi_setclocks(ivideo, regb);
5539 sisfb_post_xgi_delay(ivideo, 0x46);
5540 outSISIDXREG(SISSR, 0x18, 0xc5);
5541 outSISIDXREG(SISSR, 0x19, 0x23);
5542 outSISIDXREG(SISSR, 0x16, 0x00);
5543 outSISIDXREG(SISSR, 0x16, 0x80);
5544 sisfb_post_xgi_delay(ivideo, 1);
5545 outSISIDXREG(SISSR, 0x1b, 0x04);
5546 sisfb_post_xgi_delay(ivideo, 1);
5547 outSISIDXREG(SISSR, 0x1b, 0x00);
5548 sisfb_post_xgi_delay(ivideo, 1);
5549 v1 = 0x31;
5550 if(ivideo->haveXGIROM) {
5551 v1 = bios[0xf0];
5552 }
5553 outSISIDXREG(SISSR, 0x18, v1);
5554 outSISIDXREG(SISSR, 0x19, 0x06);
5555 outSISIDXREG(SISSR, 0x16, 0x04);
5556 outSISIDXREG(SISSR, 0x16, 0x84);
5557 sisfb_post_xgi_delay(ivideo, 1);
5558 break; 5660 break;
5559 default: 5661 default:
5560 sisfb_post_xgi_setclocks(ivideo, regb); 5662 sisfb_post_xgi_setclocks(ivideo, regb);
5561 if((ivideo->chip == XGI_40) && 5663 if((ivideo->chip == XGI_40) &&
5562 ((ivideo->revision_id == 1) || 5664 ((ivideo->revision_id == 1) ||
5563 (ivideo->revision_id == 2))) { 5665 (ivideo->revision_id == 2))) {
5564 outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]); 5666 SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
5565 outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]); 5667 SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
5566 outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]); 5668 SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
5567 } else { 5669 } else {
5568 outSISIDXREG(SISCR, 0x82, 0x88); 5670 SiS_SetReg(SISCR, 0x82, 0x88);
5569 outSISIDXREG(SISCR, 0x86, 0x00); 5671 SiS_SetReg(SISCR, 0x86, 0x00);
5570 inSISIDXREG(SISCR, 0x86, reg); 5672 reg = SiS_GetReg(SISCR, 0x86);
5571 outSISIDXREG(SISCR, 0x86, 0x88); 5673 SiS_SetReg(SISCR, 0x86, 0x88);
5572 outSISIDXREG(SISCR, 0x82, 0x77); 5674 SiS_SetReg(SISCR, 0x82, 0x77);
5573 outSISIDXREG(SISCR, 0x85, 0x00); 5675 SiS_SetReg(SISCR, 0x85, 0x00);
5574 inSISIDXREG(SISCR, 0x85, reg); 5676 reg = SiS_GetReg(SISCR, 0x85);
5575 outSISIDXREG(SISCR, 0x85, 0x88); 5677 SiS_SetReg(SISCR, 0x85, 0x88);
5576 inSISIDXREG(SISCR, 0x85, reg); 5678 reg = SiS_GetReg(SISCR, 0x85);
5577 v1 = cs160[regb]; v2 = cs158[regb]; 5679 v1 = cs160[regb]; v2 = cs158[regb];
5578 if(ivideo->haveXGIROM) { 5680 if(ivideo->haveXGIROM) {
5579 v1 = bios[regb + 0x160]; 5681 v1 = bios[regb + 0x160];
5580 v2 = bios[regb + 0x158]; 5682 v2 = bios[regb + 0x158];
5581 } 5683 }
5582 outSISIDXREG(SISCR, 0x85, v1); 5684 SiS_SetReg(SISCR, 0x85, v1);
5583 outSISIDXREG(SISCR, 0x82, v2); 5685 SiS_SetReg(SISCR, 0x82, v2);
5584 } 5686 }
5585 if(ivideo->chip == XGI_40) { 5687 if(ivideo->chip == XGI_40) {
5586 outSISIDXREG(SISCR, 0x97, 0x11); 5688 SiS_SetReg(SISCR, 0x97, 0x11);
5587 } 5689 }
5588 if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) { 5690 if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) {
5589 outSISIDXREG(SISCR, 0x98, 0x01); 5691 SiS_SetReg(SISCR, 0x98, 0x01);
5590 } else { 5692 } else {
5591 outSISIDXREG(SISCR, 0x98, 0x03); 5693 SiS_SetReg(SISCR, 0x98, 0x03);
5592 } 5694 }
5593 outSISIDXREG(SISCR, 0x9a, 0x02); 5695 SiS_SetReg(SISCR, 0x9a, 0x02);
5594 5696
5595 if(ivideo->chip == XGI_40) { 5697 if(ivideo->chip == XGI_40) {
5596 outSISIDXREG(SISSR, 0x18, 0x01); 5698 SiS_SetReg(SISSR, 0x18, 0x01);
5597 } else { 5699 } else {
5598 outSISIDXREG(SISSR, 0x18, 0x00); 5700 SiS_SetReg(SISSR, 0x18, 0x00);
5599 } 5701 }
5600 outSISIDXREG(SISSR, 0x19, 0x40); 5702 SiS_SetReg(SISSR, 0x19, 0x40);
5601 outSISIDXREG(SISSR, 0x16, 0x00); 5703 SiS_SetReg(SISSR, 0x16, 0x00);
5602 outSISIDXREG(SISSR, 0x16, 0x80); 5704 SiS_SetReg(SISSR, 0x16, 0x80);
5603 if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) { 5705 if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) {
5604 sisfb_post_xgi_delay(ivideo, 0x43); 5706 sisfb_post_xgi_delay(ivideo, 0x43);
5605 sisfb_post_xgi_delay(ivideo, 0x43); 5707 sisfb_post_xgi_delay(ivideo, 0x43);
5606 sisfb_post_xgi_delay(ivideo, 0x43); 5708 sisfb_post_xgi_delay(ivideo, 0x43);
5607 outSISIDXREG(SISSR, 0x18, 0x00); 5709 SiS_SetReg(SISSR, 0x18, 0x00);
5608 outSISIDXREG(SISSR, 0x19, 0x40); 5710 SiS_SetReg(SISSR, 0x19, 0x40);
5609 outSISIDXREG(SISSR, 0x16, 0x00); 5711 SiS_SetReg(SISSR, 0x16, 0x00);
5610 outSISIDXREG(SISSR, 0x16, 0x80); 5712 SiS_SetReg(SISSR, 0x16, 0x80);
5611 } 5713 }
5612 sisfb_post_xgi_delay(ivideo, 4); 5714 sisfb_post_xgi_delay(ivideo, 4);
5613 v1 = 0x31; 5715 v1 = 0x31;
5614 if(ivideo->haveXGIROM) { 5716 if(ivideo->haveXGIROM) {
5615 v1 = bios[0xf0]; 5717 v1 = bios[0xf0];
5616 } 5718 }
5617 outSISIDXREG(SISSR, 0x18, v1); 5719 SiS_SetReg(SISSR, 0x18, v1);
5618 outSISIDXREG(SISSR, 0x19, 0x01); 5720 SiS_SetReg(SISSR, 0x19, 0x01);
5619 if(ivideo->chip == XGI_40) { 5721 if(ivideo->chip == XGI_40) {
5620 outSISIDXREG(SISSR, 0x16, bios[0x53e]); 5722 SiS_SetReg(SISSR, 0x16, bios[0x53e]);
5621 outSISIDXREG(SISSR, 0x16, bios[0x53f]); 5723 SiS_SetReg(SISSR, 0x16, bios[0x53f]);
5622 } else { 5724 } else {
5623 outSISIDXREG(SISSR, 0x16, 0x05); 5725 SiS_SetReg(SISSR, 0x16, 0x05);
5624 outSISIDXREG(SISSR, 0x16, 0x85); 5726 SiS_SetReg(SISSR, 0x16, 0x85);
5625 } 5727 }
5626 sisfb_post_xgi_delay(ivideo, 0x43); 5728 sisfb_post_xgi_delay(ivideo, 0x43);
5627 if(ivideo->chip == XGI_40) { 5729 if(ivideo->chip == XGI_40) {
5628 outSISIDXREG(SISSR, 0x1b, 0x01); 5730 SiS_SetReg(SISSR, 0x1b, 0x01);
5629 } else { 5731 } else {
5630 outSISIDXREG(SISSR, 0x1b, 0x03); 5732 SiS_SetReg(SISSR, 0x1b, 0x03);
5631 } 5733 }
5632 sisfb_post_xgi_delay(ivideo, 0x22); 5734 sisfb_post_xgi_delay(ivideo, 0x22);
5633 outSISIDXREG(SISSR, 0x18, v1); 5735 SiS_SetReg(SISSR, 0x18, v1);
5634 outSISIDXREG(SISSR, 0x19, 0x00); 5736 SiS_SetReg(SISSR, 0x19, 0x00);
5635 if(ivideo->chip == XGI_40) { 5737 if(ivideo->chip == XGI_40) {
5636 outSISIDXREG(SISSR, 0x16, bios[0x540]); 5738 SiS_SetReg(SISSR, 0x16, bios[0x540]);
5637 outSISIDXREG(SISSR, 0x16, bios[0x541]); 5739 SiS_SetReg(SISSR, 0x16, bios[0x541]);
5638 } else { 5740 } else {
5639 outSISIDXREG(SISSR, 0x16, 0x05); 5741 SiS_SetReg(SISSR, 0x16, 0x05);
5640 outSISIDXREG(SISSR, 0x16, 0x85); 5742 SiS_SetReg(SISSR, 0x16, 0x85);
5641 } 5743 }
5642 outSISIDXREG(SISSR, 0x1b, 0x00); 5744 SiS_SetReg(SISSR, 0x1b, 0x00);
5643 } 5745 }
5644 5746
5645 regb = 0; /* ! */ 5747 regb = 0; /* ! */
@@ -5647,7 +5749,7 @@ sisfb_post_xgi(struct pci_dev *pdev)
5647 if(ivideo->haveXGIROM) { 5749 if(ivideo->haveXGIROM) {
5648 v1 = bios[0x110 + regb]; 5750 v1 = bios[0x110 + regb];
5649 } 5751 }
5650 outSISIDXREG(SISSR, 0x1b, v1); 5752 SiS_SetReg(SISSR, 0x1b, v1);
5651 5753
5652 /* RAM size */ 5754 /* RAM size */
5653 v1 = 0x00; v2 = 0x00; 5755 v1 = 0x00; v2 = 0x00;
@@ -5659,10 +5761,11 @@ sisfb_post_xgi(struct pci_dev *pdev)
5659 regd = 1 << regb; 5761 regd = 1 << regb;
5660 if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) { 5762 if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) {
5661 5763
5662 outSISIDXREG(SISSR, 0x13, bios[regb + 0xe0]); 5764 SiS_SetReg(SISSR, 0x13, bios[regb + 0xe0]);
5663 outSISIDXREG(SISSR, 0x14, bios[regb + 0xe0 + 8]); 5765 SiS_SetReg(SISSR, 0x14, bios[regb + 0xe0 + 8]);
5664 5766
5665 } else { 5767 } else {
5768 int err;
5666 5769
5667 /* Set default mode, don't clear screen */ 5770 /* Set default mode, don't clear screen */
5668 ivideo->SiS_Pr.SiS_UseOEM = false; 5771 ivideo->SiS_Pr.SiS_UseOEM = false;
@@ -5672,24 +5775,30 @@ sisfb_post_xgi(struct pci_dev *pdev)
5672 ivideo->SiS_Pr.VideoMemorySize = 8 << 20; 5775 ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
5673 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80); 5776 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5674 5777
5675 outSISIDXREG(SISSR, 0x05, 0x86); 5778 SiS_SetReg(SISSR, 0x05, 0x86);
5676 5779
5677 /* Disable read-cache */ 5780 /* Disable read-cache */
5678 andSISIDXREG(SISSR, 0x21, 0xdf); 5781 SiS_SetRegAND(SISSR, 0x21, 0xdf);
5679 sisfb_post_xgi_ramsize(ivideo); 5782 err = sisfb_post_xgi_ramsize(ivideo);
5680 /* Enable read-cache */ 5783 /* Enable read-cache */
5681 orSISIDXREG(SISSR, 0x21, 0x20); 5784 SiS_SetRegOR(SISSR, 0x21, 0x20);
5682 5785
5786 if (err) {
5787 dev_err(&pdev->dev,
5788 "%s: RAM size detection failed: %d\n",
5789 __func__, err);
5790 return 0;
5791 }
5683 } 5792 }
5684 5793
5685#if 0 5794#if 0
5686 printk(KERN_DEBUG "-----------------\n"); 5795 printk(KERN_DEBUG "-----------------\n");
5687 for(i = 0; i < 0xff; i++) { 5796 for(i = 0; i < 0xff; i++) {
5688 inSISIDXREG(SISCR, i, reg); 5797 reg = SiS_GetReg(SISCR, i);
5689 printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg); 5798 printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg);
5690 } 5799 }
5691 for(i = 0; i < 0x40; i++) { 5800 for(i = 0; i < 0x40; i++) {
5692 inSISIDXREG(SISSR, i, reg); 5801 reg = SiS_GetReg(SISSR, i);
5693 printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg); 5802 printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg);
5694 } 5803 }
5695 printk(KERN_DEBUG "-----------------\n"); 5804 printk(KERN_DEBUG "-----------------\n");
@@ -5697,13 +5806,13 @@ sisfb_post_xgi(struct pci_dev *pdev)
5697 5806
5698 /* Sense CRT1 */ 5807 /* Sense CRT1 */
5699 if(ivideo->chip == XGI_20) { 5808 if(ivideo->chip == XGI_20) {
5700 orSISIDXREG(SISCR, 0x32, 0x20); 5809 SiS_SetRegOR(SISCR, 0x32, 0x20);
5701 } else { 5810 } else {
5702 inSISIDXREG(SISPART4, 0x00, reg); 5811 reg = SiS_GetReg(SISPART4, 0x00);
5703 if((reg == 1) || (reg == 2)) { 5812 if((reg == 1) || (reg == 2)) {
5704 sisfb_sense_crt1(ivideo); 5813 sisfb_sense_crt1(ivideo);
5705 } else { 5814 } else {
5706 orSISIDXREG(SISCR, 0x32, 0x20); 5815 SiS_SetRegOR(SISCR, 0x32, 0x20);
5707 } 5816 }
5708 } 5817 }
5709 5818
@@ -5714,20 +5823,20 @@ sisfb_post_xgi(struct pci_dev *pdev)
5714 ivideo->curFSTN = ivideo->curDSTN = 0; 5823 ivideo->curFSTN = ivideo->curDSTN = 0;
5715 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80); 5824 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5716 5825
5717 outSISIDXREG(SISSR, 0x05, 0x86); 5826 SiS_SetReg(SISSR, 0x05, 0x86);
5718 5827
5719 /* Display off */ 5828 /* Display off */
5720 orSISIDXREG(SISSR, 0x01, 0x20); 5829 SiS_SetRegOR(SISSR, 0x01, 0x20);
5721 5830
5722 /* Save mode number in CR34 */ 5831 /* Save mode number in CR34 */
5723 outSISIDXREG(SISCR, 0x34, 0x2e); 5832 SiS_SetReg(SISCR, 0x34, 0x2e);
5724 5833
5725 /* Let everyone know what the current mode is */ 5834 /* Let everyone know what the current mode is */
5726 ivideo->modeprechange = 0x2e; 5835 ivideo->modeprechange = 0x2e;
5727 5836
5728 if(ivideo->chip == XGI_40) { 5837 if(ivideo->chip == XGI_40) {
5729 inSISIDXREG(SISCR, 0xca, reg); 5838 reg = SiS_GetReg(SISCR, 0xca);
5730 inSISIDXREG(SISCR, 0xcc, v1); 5839 v1 = SiS_GetReg(SISCR, 0xcc);
5731 if((reg & 0x10) && (!(v1 & 0x04))) { 5840 if((reg & 0x10) && (!(v1 & 0x04))) {
5732 printk(KERN_ERR 5841 printk(KERN_ERR
5733 "sisfb: Please connect power to the card.\n"); 5842 "sisfb: Please connect power to the card.\n");
@@ -5792,6 +5901,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
5792#endif 5901#endif
5793 5902
5794 ivideo->chip = chipinfo->chip; 5903 ivideo->chip = chipinfo->chip;
5904 ivideo->chip_real_id = chipinfo->chip;
5795 ivideo->sisvga_engine = chipinfo->vgaengine; 5905 ivideo->sisvga_engine = chipinfo->vgaengine;
5796 ivideo->hwcursor_size = chipinfo->hwcursor_size; 5906 ivideo->hwcursor_size = chipinfo->hwcursor_size;
5797 ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable; 5907 ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable;
@@ -5936,6 +6046,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
5936 } 6046 }
5937 6047
5938 ivideo->video_base = pci_resource_start(pdev, 0); 6048 ivideo->video_base = pci_resource_start(pdev, 0);
6049 ivideo->video_size = pci_resource_len(pdev, 0);
5939 ivideo->mmio_base = pci_resource_start(pdev, 1); 6050 ivideo->mmio_base = pci_resource_start(pdev, 1);
5940 ivideo->mmio_size = pci_resource_len(pdev, 1); 6051 ivideo->mmio_size = pci_resource_len(pdev, 1);
5941 ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30; 6052 ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
@@ -5969,7 +6080,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
5969 } 6080 }
5970#endif 6081#endif
5971 6082
5972 outSISIDXREG(SISSR, 0x05, 0x86); 6083 SiS_SetReg(SISSR, 0x05, 0x86);
5973 6084
5974 if( (!ivideo->sisvga_enabled) 6085 if( (!ivideo->sisvga_enabled)
5975#if !defined(__i386__) && !defined(__x86_64__) 6086#if !defined(__i386__) && !defined(__x86_64__)
@@ -5977,13 +6088,13 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
5977#endif 6088#endif
5978 ) { 6089 ) {
5979 for(i = 0x30; i <= 0x3f; i++) { 6090 for(i = 0x30; i <= 0x3f; i++) {
5980 outSISIDXREG(SISCR, i, 0x00); 6091 SiS_SetReg(SISCR, i, 0x00);
5981 } 6092 }
5982 } 6093 }
5983 6094
5984 /* Find out about current video mode */ 6095 /* Find out about current video mode */
5985 ivideo->modeprechange = 0x03; 6096 ivideo->modeprechange = 0x03;
5986 inSISIDXREG(SISCR, 0x34, reg); 6097 reg = SiS_GetReg(SISCR, 0x34);
5987 if(reg & 0x7f) { 6098 if(reg & 0x7f) {
5988 ivideo->modeprechange = reg & 0x7f; 6099 ivideo->modeprechange = reg & 0x7f;
5989 } else if(ivideo->sisvga_enabled) { 6100 } else if(ivideo->sisvga_enabled) {
@@ -6024,6 +6135,18 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
6024 sisfb_detect_custom_timing(ivideo); 6135 sisfb_detect_custom_timing(ivideo);
6025 } 6136 }
6026 6137
6138#ifdef CONFIG_FB_SIS_315
6139 if (ivideo->chip == XGI_20) {
6140 /* Check if our Z7 chip is actually Z9 */
6141 SiS_SetRegOR(SISCR, 0x4a, 0x40); /* GPIOG EN */
6142 reg = SiS_GetReg(SISCR, 0x48);
6143 if (reg & 0x02) { /* GPIOG */
6144 ivideo->chip_real_id = XGI_21;
6145 dev_info(&pdev->dev, "Z9 detected\n");
6146 }
6147 }
6148#endif
6149
6027 /* POST card in case this has not been done by the BIOS */ 6150 /* POST card in case this has not been done by the BIOS */
6028 if( (!ivideo->sisvga_enabled) 6151 if( (!ivideo->sisvga_enabled)
6029#if !defined(__i386__) && !defined(__x86_64__) 6152#if !defined(__i386__) && !defined(__x86_64__)
@@ -6080,9 +6203,9 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
6080 if((ivideo->sisfb_mode_idx < 0) || 6203 if((ivideo->sisfb_mode_idx < 0) ||
6081 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) { 6204 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
6082 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */ 6205 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
6083 orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE)); 6206 SiS_SetRegOR(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
6084 /* Enable 2D accelerator engine */ 6207 /* Enable 2D accelerator engine */
6085 orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D); 6208 SiS_SetRegOR(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
6086 } 6209 }
6087 6210
6088 if(sisfb_pdc != 0xff) { 6211 if(sisfb_pdc != 0xff) {
diff --git a/drivers/video/sis/vgatypes.h b/drivers/video/sis/vgatypes.h
index 81a22eaabfde..e3f9976cfef0 100644
--- a/drivers/video/sis/vgatypes.h
+++ b/drivers/video/sis/vgatypes.h
@@ -55,21 +55,10 @@
55 55
56#define SISIOMEMTYPE 56#define SISIOMEMTYPE
57 57
58#ifdef SIS_LINUX_KERNEL
59typedef unsigned long SISIOADDRESS; 58typedef unsigned long SISIOADDRESS;
60#include <linux/types.h> /* Need __iomem */ 59#include <linux/types.h> /* Need __iomem */
61#undef SISIOMEMTYPE 60#undef SISIOMEMTYPE
62#define SISIOMEMTYPE __iomem 61#define SISIOMEMTYPE __iomem
63#endif
64
65#ifdef SIS_XORG_XF86
66#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,0,0,0)
67typedef unsigned long IOADDRESS;
68typedef unsigned long SISIOADDRESS;
69#else
70typedef IOADDRESS SISIOADDRESS;
71#endif
72#endif
73 62
74typedef enum _SIS_CHIP_TYPE { 63typedef enum _SIS_CHIP_TYPE {
75 SIS_VGALegacy = 0, 64 SIS_VGALegacy = 0,
@@ -98,6 +87,7 @@ typedef enum _SIS_CHIP_TYPE {
98 SIS_341, 87 SIS_341,
99 SIS_342, 88 SIS_342,
100 XGI_20 = 75, 89 XGI_20 = 75,
90 XGI_21,
101 XGI_40, 91 XGI_40,
102 MAX_SIS_CHIP 92 MAX_SIS_CHIP
103} SIS_CHIP_TYPE; 93} SIS_CHIP_TYPE;
diff --git a/drivers/video/sis/vstruct.h b/drivers/video/sis/vstruct.h
index bef4aae388d0..ea94d214dcff 100644
--- a/drivers/video/sis/vstruct.h
+++ b/drivers/video/sis/vstruct.h
@@ -233,24 +233,15 @@ struct SiS_Private
233{ 233{
234 unsigned char ChipType; 234 unsigned char ChipType;
235 unsigned char ChipRevision; 235 unsigned char ChipRevision;
236#ifdef SIS_XORG_XF86
237 PCITAG PciTag;
238#endif
239#ifdef SIS_LINUX_KERNEL
240 void *ivideo; 236 void *ivideo;
241#endif
242 unsigned char *VirtualRomBase; 237 unsigned char *VirtualRomBase;
243 bool UseROM; 238 bool UseROM;
244#ifdef SIS_LINUX_KERNEL
245 unsigned char SISIOMEMTYPE *VideoMemoryAddress; 239 unsigned char SISIOMEMTYPE *VideoMemoryAddress;
246 unsigned int VideoMemorySize; 240 unsigned int VideoMemorySize;
247#endif
248 SISIOADDRESS IOAddress; 241 SISIOADDRESS IOAddress;
249 SISIOADDRESS IOAddress2; /* For dual chip XGI volari */ 242 SISIOADDRESS IOAddress2; /* For dual chip XGI volari */
250 243
251#ifdef SIS_LINUX_KERNEL
252 SISIOADDRESS RelIO; 244 SISIOADDRESS RelIO;
253#endif
254 SISIOADDRESS SiS_P3c4; 245 SISIOADDRESS SiS_P3c4;
255 SISIOADDRESS SiS_P3d4; 246 SISIOADDRESS SiS_P3d4;
256 SISIOADDRESS SiS_P3c0; 247 SISIOADDRESS SiS_P3c0;
@@ -280,9 +271,6 @@ struct SiS_Private
280 unsigned short SiS_IF_DEF_FSTN; 271 unsigned short SiS_IF_DEF_FSTN;
281 unsigned short SiS_SysFlags; 272 unsigned short SiS_SysFlags;
282 unsigned char SiS_VGAINFO; 273 unsigned char SiS_VGAINFO;
283#ifdef SIS_XORG_XF86
284 unsigned short SiS_CP1, SiS_CP2, SiS_CP3, SiS_CP4;
285#endif
286 bool SiS_UseROM; 274 bool SiS_UseROM;
287 bool SiS_ROMNew; 275 bool SiS_ROMNew;
288 bool SiS_XGIROM; 276 bool SiS_XGIROM;
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index b7dc1800efa9..6294dca95500 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -41,6 +41,26 @@
41#include <linux/sm501.h> 41#include <linux/sm501.h>
42#include <linux/sm501-regs.h> 42#include <linux/sm501-regs.h>
43 43
44#include "edid.h"
45
46static char *fb_mode = "640x480-16@60";
47static unsigned long default_bpp = 16;
48
49static struct fb_videomode __devinitdata sm501_default_mode = {
50 .refresh = 60,
51 .xres = 640,
52 .yres = 480,
53 .pixclock = 20833,
54 .left_margin = 142,
55 .right_margin = 13,
56 .upper_margin = 21,
57 .lower_margin = 1,
58 .hsync_len = 69,
59 .vsync_len = 3,
60 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
61 .vmode = FB_VMODE_NONINTERLACED
62};
63
44#define NR_PALETTE 256 64#define NR_PALETTE 256
45 65
46enum sm501_controller { 66enum sm501_controller {
@@ -77,6 +97,7 @@ struct sm501fb_info {
77 void __iomem *regs2d; /* 2d remapped registers */ 97 void __iomem *regs2d; /* 2d remapped registers */
78 void __iomem *fbmem; /* remapped framebuffer */ 98 void __iomem *fbmem; /* remapped framebuffer */
79 size_t fbmem_len; /* length of remapped region */ 99 size_t fbmem_len; /* length of remapped region */
100 u8 *edid_data;
80}; 101};
81 102
82/* per-framebuffer private data */ 103/* per-framebuffer private data */
@@ -117,7 +138,7 @@ static inline int v_total(struct fb_var_screeninfo *var)
117 138
118static inline void sm501fb_sync_regs(struct sm501fb_info *info) 139static inline void sm501fb_sync_regs(struct sm501fb_info *info)
119{ 140{
120 readl(info->regs); 141 smc501_readl(info->regs);
121} 142}
122 143
123/* sm501_alloc_mem 144/* sm501_alloc_mem
@@ -244,7 +265,7 @@ static unsigned long sm501fb_ps_to_hz(unsigned long psvalue)
244 return (unsigned long)numerator; 265 return (unsigned long)numerator;
245} 266}
246 267
247/* sm501fb_hz_to_ps is identical to the oposite transform */ 268/* sm501fb_hz_to_ps is identical to the opposite transform */
248 269
249#define sm501fb_hz_to_ps(x) sm501fb_ps_to_hz(x) 270#define sm501fb_hz_to_ps(x) sm501fb_ps_to_hz(x)
250 271
@@ -262,7 +283,7 @@ static void sm501fb_setup_gamma(struct sm501fb_info *fbi,
262 283
263 /* set gamma values */ 284 /* set gamma values */
264 for (offset = 0; offset < 256 * 4; offset += 4) { 285 for (offset = 0; offset < 256 * 4; offset += 4) {
265 writel(value, fbi->regs + palette + offset); 286 smc501_writel(value, fbi->regs + palette + offset);
266 value += 0x010101; /* Advance RGB by 1,1,1.*/ 287 value += 0x010101; /* Advance RGB by 1,1,1.*/
267 } 288 }
268} 289}
@@ -476,7 +497,8 @@ static int sm501fb_set_par_common(struct fb_info *info,
476 497
477 /* set start of framebuffer to the screen */ 498 /* set start of framebuffer to the screen */
478 499
479 writel(par->screen.sm_addr | SM501_ADDR_FLIP, fbi->regs + head_addr); 500 smc501_writel(par->screen.sm_addr | SM501_ADDR_FLIP,
501 fbi->regs + head_addr);
480 502
481 /* program CRT clock */ 503 /* program CRT clock */
482 504
@@ -519,7 +541,7 @@ static void sm501fb_set_par_geometry(struct fb_info *info,
519 reg = info->fix.line_length; 541 reg = info->fix.line_length;
520 reg |= ((var->xres * var->bits_per_pixel)/8) << 16; 542 reg |= ((var->xres * var->bits_per_pixel)/8) << 16;
521 543
522 writel(reg, fbi->regs + (par->head == HEAD_CRT ? 544 smc501_writel(reg, fbi->regs + (par->head == HEAD_CRT ?
523 SM501_DC_CRT_FB_OFFSET : SM501_DC_PANEL_FB_OFFSET)); 545 SM501_DC_CRT_FB_OFFSET : SM501_DC_PANEL_FB_OFFSET));
524 546
525 /* program horizontal total */ 547 /* program horizontal total */
@@ -527,27 +549,27 @@ static void sm501fb_set_par_geometry(struct fb_info *info,
527 reg = (h_total(var) - 1) << 16; 549 reg = (h_total(var) - 1) << 16;
528 reg |= (var->xres - 1); 550 reg |= (var->xres - 1);
529 551
530 writel(reg, base + SM501_OFF_DC_H_TOT); 552 smc501_writel(reg, base + SM501_OFF_DC_H_TOT);
531 553
532 /* program horizontal sync */ 554 /* program horizontal sync */
533 555
534 reg = var->hsync_len << 16; 556 reg = var->hsync_len << 16;
535 reg |= var->xres + var->right_margin - 1; 557 reg |= var->xres + var->right_margin - 1;
536 558
537 writel(reg, base + SM501_OFF_DC_H_SYNC); 559 smc501_writel(reg, base + SM501_OFF_DC_H_SYNC);
538 560
539 /* program vertical total */ 561 /* program vertical total */
540 562
541 reg = (v_total(var) - 1) << 16; 563 reg = (v_total(var) - 1) << 16;
542 reg |= (var->yres - 1); 564 reg |= (var->yres - 1);
543 565
544 writel(reg, base + SM501_OFF_DC_V_TOT); 566 smc501_writel(reg, base + SM501_OFF_DC_V_TOT);
545 567
546 /* program vertical sync */ 568 /* program vertical sync */
547 reg = var->vsync_len << 16; 569 reg = var->vsync_len << 16;
548 reg |= var->yres + var->lower_margin - 1; 570 reg |= var->yres + var->lower_margin - 1;
549 571
550 writel(reg, base + SM501_OFF_DC_V_SYNC); 572 smc501_writel(reg, base + SM501_OFF_DC_V_SYNC);
551} 573}
552 574
553/* sm501fb_pan_crt 575/* sm501fb_pan_crt
@@ -566,15 +588,15 @@ static int sm501fb_pan_crt(struct fb_var_screeninfo *var,
566 588
567 xoffs = var->xoffset * bytes_pixel; 589 xoffs = var->xoffset * bytes_pixel;
568 590
569 reg = readl(fbi->regs + SM501_DC_CRT_CONTROL); 591 reg = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL);
570 592
571 reg &= ~SM501_DC_CRT_CONTROL_PIXEL_MASK; 593 reg &= ~SM501_DC_CRT_CONTROL_PIXEL_MASK;
572 reg |= ((xoffs & 15) / bytes_pixel) << 4; 594 reg |= ((xoffs & 15) / bytes_pixel) << 4;
573 writel(reg, fbi->regs + SM501_DC_CRT_CONTROL); 595 smc501_writel(reg, fbi->regs + SM501_DC_CRT_CONTROL);
574 596
575 reg = (par->screen.sm_addr + xoffs + 597 reg = (par->screen.sm_addr + xoffs +
576 var->yoffset * info->fix.line_length); 598 var->yoffset * info->fix.line_length);
577 writel(reg | SM501_ADDR_FLIP, fbi->regs + SM501_DC_CRT_FB_ADDR); 599 smc501_writel(reg | SM501_ADDR_FLIP, fbi->regs + SM501_DC_CRT_FB_ADDR);
578 600
579 sm501fb_sync_regs(fbi); 601 sm501fb_sync_regs(fbi);
580 return 0; 602 return 0;
@@ -593,10 +615,10 @@ static int sm501fb_pan_pnl(struct fb_var_screeninfo *var,
593 unsigned long reg; 615 unsigned long reg;
594 616
595 reg = var->xoffset | (var->xres_virtual << 16); 617 reg = var->xoffset | (var->xres_virtual << 16);
596 writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH); 618 smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH);
597 619
598 reg = var->yoffset | (var->yres_virtual << 16); 620 reg = var->yoffset | (var->yres_virtual << 16);
599 writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT); 621 smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT);
600 622
601 sm501fb_sync_regs(fbi); 623 sm501fb_sync_regs(fbi);
602 return 0; 624 return 0;
@@ -622,7 +644,7 @@ static int sm501fb_set_par_crt(struct fb_info *info)
622 /* enable CRT DAC - note 0 is on!*/ 644 /* enable CRT DAC - note 0 is on!*/
623 sm501_misc_control(fbi->dev->parent, 0, SM501_MISC_DAC_POWER); 645 sm501_misc_control(fbi->dev->parent, 0, SM501_MISC_DAC_POWER);
624 646
625 control = readl(fbi->regs + SM501_DC_CRT_CONTROL); 647 control = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL);
626 648
627 control &= (SM501_DC_CRT_CONTROL_PIXEL_MASK | 649 control &= (SM501_DC_CRT_CONTROL_PIXEL_MASK |
628 SM501_DC_CRT_CONTROL_GAMMA | 650 SM501_DC_CRT_CONTROL_GAMMA |
@@ -684,7 +706,7 @@ static int sm501fb_set_par_crt(struct fb_info *info)
684 out_update: 706 out_update:
685 dev_dbg(fbi->dev, "new control is %08lx\n", control); 707 dev_dbg(fbi->dev, "new control is %08lx\n", control);
686 708
687 writel(control, fbi->regs + SM501_DC_CRT_CONTROL); 709 smc501_writel(control, fbi->regs + SM501_DC_CRT_CONTROL);
688 sm501fb_sync_regs(fbi); 710 sm501fb_sync_regs(fbi);
689 711
690 return 0; 712 return 0;
@@ -696,18 +718,18 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
696 void __iomem *ctrl_reg = fbi->regs + SM501_DC_PANEL_CONTROL; 718 void __iomem *ctrl_reg = fbi->regs + SM501_DC_PANEL_CONTROL;
697 struct sm501_platdata_fbsub *pd = fbi->pdata->fb_pnl; 719 struct sm501_platdata_fbsub *pd = fbi->pdata->fb_pnl;
698 720
699 control = readl(ctrl_reg); 721 control = smc501_readl(ctrl_reg);
700 722
701 if (to && (control & SM501_DC_PANEL_CONTROL_VDD) == 0) { 723 if (to && (control & SM501_DC_PANEL_CONTROL_VDD) == 0) {
702 /* enable panel power */ 724 /* enable panel power */
703 725
704 control |= SM501_DC_PANEL_CONTROL_VDD; /* FPVDDEN */ 726 control |= SM501_DC_PANEL_CONTROL_VDD; /* FPVDDEN */
705 writel(control, ctrl_reg); 727 smc501_writel(control, ctrl_reg);
706 sm501fb_sync_regs(fbi); 728 sm501fb_sync_regs(fbi);
707 mdelay(10); 729 mdelay(10);
708 730
709 control |= SM501_DC_PANEL_CONTROL_DATA; /* DATA */ 731 control |= SM501_DC_PANEL_CONTROL_DATA; /* DATA */
710 writel(control, ctrl_reg); 732 smc501_writel(control, ctrl_reg);
711 sm501fb_sync_regs(fbi); 733 sm501fb_sync_regs(fbi);
712 mdelay(10); 734 mdelay(10);
713 735
@@ -719,7 +741,7 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
719 else 741 else
720 control |= SM501_DC_PANEL_CONTROL_BIAS; 742 control |= SM501_DC_PANEL_CONTROL_BIAS;
721 743
722 writel(control, ctrl_reg); 744 smc501_writel(control, ctrl_reg);
723 sm501fb_sync_regs(fbi); 745 sm501fb_sync_regs(fbi);
724 mdelay(10); 746 mdelay(10);
725 } 747 }
@@ -730,7 +752,7 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
730 else 752 else
731 control |= SM501_DC_PANEL_CONTROL_FPEN; 753 control |= SM501_DC_PANEL_CONTROL_FPEN;
732 754
733 writel(control, ctrl_reg); 755 smc501_writel(control, ctrl_reg);
734 sm501fb_sync_regs(fbi); 756 sm501fb_sync_regs(fbi);
735 mdelay(10); 757 mdelay(10);
736 } 758 }
@@ -742,7 +764,7 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
742 else 764 else
743 control &= ~SM501_DC_PANEL_CONTROL_FPEN; 765 control &= ~SM501_DC_PANEL_CONTROL_FPEN;
744 766
745 writel(control, ctrl_reg); 767 smc501_writel(control, ctrl_reg);
746 sm501fb_sync_regs(fbi); 768 sm501fb_sync_regs(fbi);
747 mdelay(10); 769 mdelay(10);
748 } 770 }
@@ -753,18 +775,18 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
753 else 775 else
754 control &= ~SM501_DC_PANEL_CONTROL_BIAS; 776 control &= ~SM501_DC_PANEL_CONTROL_BIAS;
755 777
756 writel(control, ctrl_reg); 778 smc501_writel(control, ctrl_reg);
757 sm501fb_sync_regs(fbi); 779 sm501fb_sync_regs(fbi);
758 mdelay(10); 780 mdelay(10);
759 } 781 }
760 782
761 control &= ~SM501_DC_PANEL_CONTROL_DATA; 783 control &= ~SM501_DC_PANEL_CONTROL_DATA;
762 writel(control, ctrl_reg); 784 smc501_writel(control, ctrl_reg);
763 sm501fb_sync_regs(fbi); 785 sm501fb_sync_regs(fbi);
764 mdelay(10); 786 mdelay(10);
765 787
766 control &= ~SM501_DC_PANEL_CONTROL_VDD; 788 control &= ~SM501_DC_PANEL_CONTROL_VDD;
767 writel(control, ctrl_reg); 789 smc501_writel(control, ctrl_reg);
768 sm501fb_sync_regs(fbi); 790 sm501fb_sync_regs(fbi);
769 mdelay(10); 791 mdelay(10);
770 } 792 }
@@ -799,7 +821,7 @@ static int sm501fb_set_par_pnl(struct fb_info *info)
799 821
800 /* update control register */ 822 /* update control register */
801 823
802 control = readl(fbi->regs + SM501_DC_PANEL_CONTROL); 824 control = smc501_readl(fbi->regs + SM501_DC_PANEL_CONTROL);
803 control &= (SM501_DC_PANEL_CONTROL_GAMMA | 825 control &= (SM501_DC_PANEL_CONTROL_GAMMA |
804 SM501_DC_PANEL_CONTROL_VDD | 826 SM501_DC_PANEL_CONTROL_VDD |
805 SM501_DC_PANEL_CONTROL_DATA | 827 SM501_DC_PANEL_CONTROL_DATA |
@@ -833,16 +855,16 @@ static int sm501fb_set_par_pnl(struct fb_info *info)
833 BUG(); 855 BUG();
834 } 856 }
835 857
836 writel(0x0, fbi->regs + SM501_DC_PANEL_PANNING_CONTROL); 858 smc501_writel(0x0, fbi->regs + SM501_DC_PANEL_PANNING_CONTROL);
837 859
838 /* panel plane top left and bottom right location */ 860 /* panel plane top left and bottom right location */
839 861
840 writel(0x00, fbi->regs + SM501_DC_PANEL_TL_LOC); 862 smc501_writel(0x00, fbi->regs + SM501_DC_PANEL_TL_LOC);
841 863
842 reg = var->xres - 1; 864 reg = var->xres - 1;
843 reg |= (var->yres - 1) << 16; 865 reg |= (var->yres - 1) << 16;
844 866
845 writel(reg, fbi->regs + SM501_DC_PANEL_BR_LOC); 867 smc501_writel(reg, fbi->regs + SM501_DC_PANEL_BR_LOC);
846 868
847 /* program panel control register */ 869 /* program panel control register */
848 870
@@ -855,7 +877,7 @@ static int sm501fb_set_par_pnl(struct fb_info *info)
855 if ((var->sync & FB_SYNC_VERT_HIGH_ACT) == 0) 877 if ((var->sync & FB_SYNC_VERT_HIGH_ACT) == 0)
856 control |= SM501_DC_PANEL_CONTROL_VSP; 878 control |= SM501_DC_PANEL_CONTROL_VSP;
857 879
858 writel(control, fbi->regs + SM501_DC_PANEL_CONTROL); 880 smc501_writel(control, fbi->regs + SM501_DC_PANEL_CONTROL);
859 sm501fb_sync_regs(fbi); 881 sm501fb_sync_regs(fbi);
860 882
861 /* ensure the panel interface is not tristated at this point */ 883 /* ensure the panel interface is not tristated at this point */
@@ -924,7 +946,7 @@ static int sm501fb_setcolreg(unsigned regno,
924 val |= (green >> 8) << 8; 946 val |= (green >> 8) << 8;
925 val |= blue >> 8; 947 val |= blue >> 8;
926 948
927 writel(val, base + (regno * 4)); 949 smc501_writel(val, base + (regno * 4));
928 } 950 }
929 951
930 break; 952 break;
@@ -980,7 +1002,7 @@ static int sm501fb_blank_crt(int blank_mode, struct fb_info *info)
980 1002
981 dev_dbg(fbi->dev, "%s(mode=%d, %p)\n", __func__, blank_mode, info); 1003 dev_dbg(fbi->dev, "%s(mode=%d, %p)\n", __func__, blank_mode, info);
982 1004
983 ctrl = readl(fbi->regs + SM501_DC_CRT_CONTROL); 1005 ctrl = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL);
984 1006
985 switch (blank_mode) { 1007 switch (blank_mode) {
986 case FB_BLANK_POWERDOWN: 1008 case FB_BLANK_POWERDOWN:
@@ -1004,7 +1026,7 @@ static int sm501fb_blank_crt(int blank_mode, struct fb_info *info)
1004 1026
1005 } 1027 }
1006 1028
1007 writel(ctrl, fbi->regs + SM501_DC_CRT_CONTROL); 1029 smc501_writel(ctrl, fbi->regs + SM501_DC_CRT_CONTROL);
1008 sm501fb_sync_regs(fbi); 1030 sm501fb_sync_regs(fbi);
1009 1031
1010 return 0; 1032 return 0;
@@ -1041,12 +1063,14 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
1041 if (cursor->image.depth > 1) 1063 if (cursor->image.depth > 1)
1042 return -EINVAL; 1064 return -EINVAL;
1043 1065
1044 hwc_addr = readl(base + SM501_OFF_HWC_ADDR); 1066 hwc_addr = smc501_readl(base + SM501_OFF_HWC_ADDR);
1045 1067
1046 if (cursor->enable) 1068 if (cursor->enable)
1047 writel(hwc_addr | SM501_HWC_EN, base + SM501_OFF_HWC_ADDR); 1069 smc501_writel(hwc_addr | SM501_HWC_EN,
1070 base + SM501_OFF_HWC_ADDR);
1048 else 1071 else
1049 writel(hwc_addr & ~SM501_HWC_EN, base + SM501_OFF_HWC_ADDR); 1072 smc501_writel(hwc_addr & ~SM501_HWC_EN,
1073 base + SM501_OFF_HWC_ADDR);
1050 1074
1051 /* set data */ 1075 /* set data */
1052 if (cursor->set & FB_CUR_SETPOS) { 1076 if (cursor->set & FB_CUR_SETPOS) {
@@ -1060,7 +1084,7 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
1060 1084
1061 //y += cursor->image.height; 1085 //y += cursor->image.height;
1062 1086
1063 writel(x | (y << 16), base + SM501_OFF_HWC_LOC); 1087 smc501_writel(x | (y << 16), base + SM501_OFF_HWC_LOC);
1064 } 1088 }
1065 1089
1066 if (cursor->set & FB_CUR_SETCMAP) { 1090 if (cursor->set & FB_CUR_SETCMAP) {
@@ -1080,8 +1104,8 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
1080 1104
1081 dev_dbg(fbi->dev, "fgcol %08lx, bgcol %08lx\n", fg, bg); 1105 dev_dbg(fbi->dev, "fgcol %08lx, bgcol %08lx\n", fg, bg);
1082 1106
1083 writel(bg, base + SM501_OFF_HWC_COLOR_1_2); 1107 smc501_writel(bg, base + SM501_OFF_HWC_COLOR_1_2);
1084 writel(fg, base + SM501_OFF_HWC_COLOR_3); 1108 smc501_writel(fg, base + SM501_OFF_HWC_COLOR_3);
1085 } 1109 }
1086 1110
1087 if (cursor->set & FB_CUR_SETSIZE || 1111 if (cursor->set & FB_CUR_SETSIZE ||
@@ -1102,7 +1126,7 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
1102 __func__, cursor->image.width, cursor->image.height); 1126 __func__, cursor->image.width, cursor->image.height);
1103 1127
1104 for (op = 0; op < (64*64*2)/8; op+=4) 1128 for (op = 0; op < (64*64*2)/8; op+=4)
1105 writel(0x0, dst + op); 1129 smc501_writel(0x0, dst + op);
1106 1130
1107 for (y = 0; y < cursor->image.height; y++) { 1131 for (y = 0; y < cursor->image.height; y++) {
1108 for (x = 0; x < cursor->image.width; x++) { 1132 for (x = 0; x < cursor->image.width; x++) {
@@ -1141,7 +1165,7 @@ static ssize_t sm501fb_crtsrc_show(struct device *dev,
1141 struct sm501fb_info *info = dev_get_drvdata(dev); 1165 struct sm501fb_info *info = dev_get_drvdata(dev);
1142 unsigned long ctrl; 1166 unsigned long ctrl;
1143 1167
1144 ctrl = readl(info->regs + SM501_DC_CRT_CONTROL); 1168 ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
1145 ctrl &= SM501_DC_CRT_CONTROL_SEL; 1169 ctrl &= SM501_DC_CRT_CONTROL_SEL;
1146 1170
1147 return snprintf(buf, PAGE_SIZE, "%s\n", ctrl ? "crt" : "panel"); 1171 return snprintf(buf, PAGE_SIZE, "%s\n", ctrl ? "crt" : "panel");
@@ -1172,7 +1196,7 @@ static ssize_t sm501fb_crtsrc_store(struct device *dev,
1172 1196
1173 dev_info(dev, "setting crt source to head %d\n", head); 1197 dev_info(dev, "setting crt source to head %d\n", head);
1174 1198
1175 ctrl = readl(info->regs + SM501_DC_CRT_CONTROL); 1199 ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
1176 1200
1177 if (head == HEAD_CRT) { 1201 if (head == HEAD_CRT) {
1178 ctrl |= SM501_DC_CRT_CONTROL_SEL; 1202 ctrl |= SM501_DC_CRT_CONTROL_SEL;
@@ -1184,7 +1208,7 @@ static ssize_t sm501fb_crtsrc_store(struct device *dev,
1184 ctrl &= ~SM501_DC_CRT_CONTROL_TE; 1208 ctrl &= ~SM501_DC_CRT_CONTROL_TE;
1185 } 1209 }
1186 1210
1187 writel(ctrl, info->regs + SM501_DC_CRT_CONTROL); 1211 smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
1188 sm501fb_sync_regs(info); 1212 sm501fb_sync_regs(info);
1189 1213
1190 return len; 1214 return len;
@@ -1205,7 +1229,8 @@ static int sm501fb_show_regs(struct sm501fb_info *info, char *ptr,
1205 unsigned int reg; 1229 unsigned int reg;
1206 1230
1207 for (reg = start; reg < (len + start); reg += 4) 1231 for (reg = start; reg < (len + start); reg += 4)
1208 ptr += sprintf(ptr, "%08x = %08x\n", reg, readl(mem + reg)); 1232 ptr += sprintf(ptr, "%08x = %08x\n", reg,
1233 smc501_readl(mem + reg));
1209 1234
1210 return ptr - buf; 1235 return ptr - buf;
1211} 1236}
@@ -1257,7 +1282,7 @@ static int sm501fb_sync(struct fb_info *info)
1257 1282
1258 /* wait for the 2d engine to be ready */ 1283 /* wait for the 2d engine to be ready */
1259 while ((count > 0) && 1284 while ((count > 0) &&
1260 (readl(fbi->regs + SM501_SYSTEM_CONTROL) & 1285 (smc501_readl(fbi->regs + SM501_SYSTEM_CONTROL) &
1261 SM501_SYSCTRL_2D_ENGINE_STATUS) != 0) 1286 SM501_SYSCTRL_2D_ENGINE_STATUS) != 0)
1262 count--; 1287 count--;
1263 1288
@@ -1312,45 +1337,46 @@ static void sm501fb_copyarea(struct fb_info *info, const struct fb_copyarea *are
1312 return; 1337 return;
1313 1338
1314 /* set the base addresses */ 1339 /* set the base addresses */
1315 writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE); 1340 smc501_writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
1316 writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_DESTINATION_BASE); 1341 smc501_writel(par->screen.sm_addr,
1342 fbi->regs2d + SM501_2D_DESTINATION_BASE);
1317 1343
1318 /* set the window width */ 1344 /* set the window width */
1319 writel((info->var.xres << 16) | info->var.xres, 1345 smc501_writel((info->var.xres << 16) | info->var.xres,
1320 fbi->regs2d + SM501_2D_WINDOW_WIDTH); 1346 fbi->regs2d + SM501_2D_WINDOW_WIDTH);
1321 1347
1322 /* set window stride */ 1348 /* set window stride */
1323 writel((info->var.xres_virtual << 16) | info->var.xres_virtual, 1349 smc501_writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
1324 fbi->regs2d + SM501_2D_PITCH); 1350 fbi->regs2d + SM501_2D_PITCH);
1325 1351
1326 /* set data format */ 1352 /* set data format */
1327 switch (info->var.bits_per_pixel) { 1353 switch (info->var.bits_per_pixel) {
1328 case 8: 1354 case 8:
1329 writel(0, fbi->regs2d + SM501_2D_STRETCH); 1355 smc501_writel(0, fbi->regs2d + SM501_2D_STRETCH);
1330 break; 1356 break;
1331 case 16: 1357 case 16:
1332 writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH); 1358 smc501_writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
1333 break; 1359 break;
1334 case 32: 1360 case 32:
1335 writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH); 1361 smc501_writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
1336 break; 1362 break;
1337 } 1363 }
1338 1364
1339 /* 2d compare mask */ 1365 /* 2d compare mask */
1340 writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK); 1366 smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
1341 1367
1342 /* 2d mask */ 1368 /* 2d mask */
1343 writel(0xffffffff, fbi->regs2d + SM501_2D_MASK); 1369 smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
1344 1370
1345 /* source and destination x y */ 1371 /* source and destination x y */
1346 writel((sx << 16) | sy, fbi->regs2d + SM501_2D_SOURCE); 1372 smc501_writel((sx << 16) | sy, fbi->regs2d + SM501_2D_SOURCE);
1347 writel((dx << 16) | dy, fbi->regs2d + SM501_2D_DESTINATION); 1373 smc501_writel((dx << 16) | dy, fbi->regs2d + SM501_2D_DESTINATION);
1348 1374
1349 /* w/h */ 1375 /* w/h */
1350 writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION); 1376 smc501_writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
1351 1377
1352 /* do area move */ 1378 /* do area move */
1353 writel(0x800000cc | rtl, fbi->regs2d + SM501_2D_CONTROL); 1379 smc501_writel(0x800000cc | rtl, fbi->regs2d + SM501_2D_CONTROL);
1354} 1380}
1355 1381
1356static void sm501fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 1382static void sm501fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
@@ -1372,47 +1398,49 @@ static void sm501fb_fillrect(struct fb_info *info, const struct fb_fillrect *rec
1372 return; 1398 return;
1373 1399
1374 /* set the base addresses */ 1400 /* set the base addresses */
1375 writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE); 1401 smc501_writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
1376 writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_DESTINATION_BASE); 1402 smc501_writel(par->screen.sm_addr,
1403 fbi->regs2d + SM501_2D_DESTINATION_BASE);
1377 1404
1378 /* set the window width */ 1405 /* set the window width */
1379 writel((info->var.xres << 16) | info->var.xres, 1406 smc501_writel((info->var.xres << 16) | info->var.xres,
1380 fbi->regs2d + SM501_2D_WINDOW_WIDTH); 1407 fbi->regs2d + SM501_2D_WINDOW_WIDTH);
1381 1408
1382 /* set window stride */ 1409 /* set window stride */
1383 writel((info->var.xres_virtual << 16) | info->var.xres_virtual, 1410 smc501_writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
1384 fbi->regs2d + SM501_2D_PITCH); 1411 fbi->regs2d + SM501_2D_PITCH);
1385 1412
1386 /* set data format */ 1413 /* set data format */
1387 switch (info->var.bits_per_pixel) { 1414 switch (info->var.bits_per_pixel) {
1388 case 8: 1415 case 8:
1389 writel(0, fbi->regs2d + SM501_2D_STRETCH); 1416 smc501_writel(0, fbi->regs2d + SM501_2D_STRETCH);
1390 break; 1417 break;
1391 case 16: 1418 case 16:
1392 writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH); 1419 smc501_writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
1393 break; 1420 break;
1394 case 32: 1421 case 32:
1395 writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH); 1422 smc501_writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
1396 break; 1423 break;
1397 } 1424 }
1398 1425
1399 /* 2d compare mask */ 1426 /* 2d compare mask */
1400 writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK); 1427 smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
1401 1428
1402 /* 2d mask */ 1429 /* 2d mask */
1403 writel(0xffffffff, fbi->regs2d + SM501_2D_MASK); 1430 smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
1404 1431
1405 /* colour */ 1432 /* colour */
1406 writel(rect->color, fbi->regs2d + SM501_2D_FOREGROUND); 1433 smc501_writel(rect->color, fbi->regs2d + SM501_2D_FOREGROUND);
1407 1434
1408 /* x y */ 1435 /* x y */
1409 writel((rect->dx << 16) | rect->dy, fbi->regs2d + SM501_2D_DESTINATION); 1436 smc501_writel((rect->dx << 16) | rect->dy,
1437 fbi->regs2d + SM501_2D_DESTINATION);
1410 1438
1411 /* w/h */ 1439 /* w/h */
1412 writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION); 1440 smc501_writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
1413 1441
1414 /* do rectangle fill */ 1442 /* do rectangle fill */
1415 writel(0x800100cc, fbi->regs2d + SM501_2D_CONTROL); 1443 smc501_writel(0x800100cc, fbi->regs2d + SM501_2D_CONTROL);
1416} 1444}
1417 1445
1418 1446
@@ -1470,11 +1498,12 @@ static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base)
1470 1498
1471 /* initialise the colour registers */ 1499 /* initialise the colour registers */
1472 1500
1473 writel(par->cursor.sm_addr, par->cursor_regs + SM501_OFF_HWC_ADDR); 1501 smc501_writel(par->cursor.sm_addr,
1502 par->cursor_regs + SM501_OFF_HWC_ADDR);
1474 1503
1475 writel(0x00, par->cursor_regs + SM501_OFF_HWC_LOC); 1504 smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_LOC);
1476 writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_1_2); 1505 smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_1_2);
1477 writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_3); 1506 smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_3);
1478 sm501fb_sync_regs(info); 1507 sm501fb_sync_regs(info);
1479 1508
1480 return 0; 1509 return 0;
@@ -1581,7 +1610,7 @@ static int sm501fb_start(struct sm501fb_info *info,
1581 1610
1582 /* clear palette ram - undefined at power on */ 1611 /* clear palette ram - undefined at power on */
1583 for (k = 0; k < (256 * 3); k++) 1612 for (k = 0; k < (256 * 3); k++)
1584 writel(0, info->regs + SM501_DC_PANEL_PALETTE + (k * 4)); 1613 smc501_writel(0, info->regs + SM501_DC_PANEL_PALETTE + (k * 4));
1585 1614
1586 /* enable display controller */ 1615 /* enable display controller */
1587 sm501_unit_power(dev->parent, SM501_GATE_DISPLAY, 1); 1616 sm501_unit_power(dev->parent, SM501_GATE_DISPLAY, 1);
@@ -1596,22 +1625,22 @@ static int sm501fb_start(struct sm501fb_info *info,
1596 return 0; /* everything is setup */ 1625 return 0; /* everything is setup */
1597 1626
1598 err_mem_res: 1627 err_mem_res:
1599 release_resource(info->fbmem_res); 1628 release_mem_region(info->fbmem_res->start,
1600 kfree(info->fbmem_res); 1629 resource_size(info->fbmem_res));
1601 1630
1602 err_regs2d_map: 1631 err_regs2d_map:
1603 iounmap(info->regs2d); 1632 iounmap(info->regs2d);
1604 1633
1605 err_regs2d_res: 1634 err_regs2d_res:
1606 release_resource(info->regs2d_res); 1635 release_mem_region(info->regs2d_res->start,
1607 kfree(info->regs2d_res); 1636 resource_size(info->regs2d_res));
1608 1637
1609 err_regs_map: 1638 err_regs_map:
1610 iounmap(info->regs); 1639 iounmap(info->regs);
1611 1640
1612 err_regs_res: 1641 err_regs_res:
1613 release_resource(info->regs_res); 1642 release_mem_region(info->regs_res->start,
1614 kfree(info->regs_res); 1643 resource_size(info->regs_res));
1615 1644
1616 err_release: 1645 err_release:
1617 return ret; 1646 return ret;
@@ -1623,19 +1652,19 @@ static void sm501fb_stop(struct sm501fb_info *info)
1623 sm501_unit_power(info->dev->parent, SM501_GATE_DISPLAY, 0); 1652 sm501_unit_power(info->dev->parent, SM501_GATE_DISPLAY, 0);
1624 1653
1625 iounmap(info->fbmem); 1654 iounmap(info->fbmem);
1626 release_resource(info->fbmem_res); 1655 release_mem_region(info->fbmem_res->start,
1627 kfree(info->fbmem_res); 1656 resource_size(info->fbmem_res));
1628 1657
1629 iounmap(info->regs2d); 1658 iounmap(info->regs2d);
1630 release_resource(info->regs2d_res); 1659 release_mem_region(info->regs2d_res->start,
1631 kfree(info->regs2d_res); 1660 resource_size(info->regs2d_res));
1632 1661
1633 iounmap(info->regs); 1662 iounmap(info->regs);
1634 release_resource(info->regs_res); 1663 release_mem_region(info->regs_res->start,
1635 kfree(info->regs_res); 1664 resource_size(info->regs_res));
1636} 1665}
1637 1666
1638static int sm501fb_init_fb(struct fb_info *fb, 1667static int __devinit sm501fb_init_fb(struct fb_info *fb,
1639 enum sm501_controller head, 1668 enum sm501_controller head,
1640 const char *fbname) 1669 const char *fbname)
1641{ 1670{
@@ -1649,20 +1678,20 @@ static int sm501fb_init_fb(struct fb_info *fb,
1649 switch (head) { 1678 switch (head) {
1650 case HEAD_CRT: 1679 case HEAD_CRT:
1651 pd = info->pdata->fb_crt; 1680 pd = info->pdata->fb_crt;
1652 ctrl = readl(info->regs + SM501_DC_CRT_CONTROL); 1681 ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
1653 enable = (ctrl & SM501_DC_CRT_CONTROL_ENABLE) ? 1 : 0; 1682 enable = (ctrl & SM501_DC_CRT_CONTROL_ENABLE) ? 1 : 0;
1654 1683
1655 /* ensure we set the correct source register */ 1684 /* ensure we set the correct source register */
1656 if (info->pdata->fb_route != SM501_FB_CRT_PANEL) { 1685 if (info->pdata->fb_route != SM501_FB_CRT_PANEL) {
1657 ctrl |= SM501_DC_CRT_CONTROL_SEL; 1686 ctrl |= SM501_DC_CRT_CONTROL_SEL;
1658 writel(ctrl, info->regs + SM501_DC_CRT_CONTROL); 1687 smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
1659 } 1688 }
1660 1689
1661 break; 1690 break;
1662 1691
1663 case HEAD_PANEL: 1692 case HEAD_PANEL:
1664 pd = info->pdata->fb_pnl; 1693 pd = info->pdata->fb_pnl;
1665 ctrl = readl(info->regs + SM501_DC_PANEL_CONTROL); 1694 ctrl = smc501_readl(info->regs + SM501_DC_PANEL_CONTROL);
1666 enable = (ctrl & SM501_DC_PANEL_CONTROL_EN) ? 1 : 0; 1695 enable = (ctrl & SM501_DC_PANEL_CONTROL_EN) ? 1 : 0;
1667 break; 1696 break;
1668 1697
@@ -1680,7 +1709,7 @@ static int sm501fb_init_fb(struct fb_info *fb,
1680 1709
1681 if (head == HEAD_CRT && info->pdata->fb_route == SM501_FB_CRT_PANEL) { 1710 if (head == HEAD_CRT && info->pdata->fb_route == SM501_FB_CRT_PANEL) {
1682 ctrl &= ~SM501_DC_CRT_CONTROL_SEL; 1711 ctrl &= ~SM501_DC_CRT_CONTROL_SEL;
1683 writel(ctrl, info->regs + SM501_DC_CRT_CONTROL); 1712 smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
1684 enable = 0; 1713 enable = 0;
1685 } 1714 }
1686 1715
@@ -1690,7 +1719,7 @@ static int sm501fb_init_fb(struct fb_info *fb,
1690 (head == HEAD_CRT) ? &sm501fb_ops_crt : &sm501fb_ops_pnl, 1719 (head == HEAD_CRT) ? &sm501fb_ops_crt : &sm501fb_ops_pnl,
1691 sizeof(struct fb_ops)); 1720 sizeof(struct fb_ops));
1692 1721
1693 /* update ops dependant on what we've been passed */ 1722 /* update ops dependent on what we've been passed */
1694 1723
1695 if ((pd->flags & SM501FB_FLAG_USE_HWCURSOR) == 0) 1724 if ((pd->flags & SM501FB_FLAG_USE_HWCURSOR) == 0)
1696 par->ops.fb_cursor = NULL; 1725 par->ops.fb_cursor = NULL;
@@ -1700,6 +1729,15 @@ static int sm501fb_init_fb(struct fb_info *fb,
1700 FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT | 1729 FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
1701 FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN; 1730 FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
1702 1731
1732#if defined(CONFIG_OF)
1733#ifdef __BIG_ENDIAN
1734 if (of_get_property(info->dev->parent->of_node, "little-endian", NULL))
1735 fb->flags |= FBINFO_FOREIGN_ENDIAN;
1736#else
1737 if (of_get_property(info->dev->parent->of_node, "big-endian", NULL))
1738 fb->flags |= FBINFO_FOREIGN_ENDIAN;
1739#endif
1740#endif
1703 /* fixed data */ 1741 /* fixed data */
1704 1742
1705 fb->fix.type = FB_TYPE_PACKED_PIXELS; 1743 fb->fix.type = FB_TYPE_PACKED_PIXELS;
@@ -1717,9 +1755,16 @@ static int sm501fb_init_fb(struct fb_info *fb,
1717 fb->var.vmode = FB_VMODE_NONINTERLACED; 1755 fb->var.vmode = FB_VMODE_NONINTERLACED;
1718 fb->var.bits_per_pixel = 16; 1756 fb->var.bits_per_pixel = 16;
1719 1757
1758 if (info->edid_data) {
1759 /* Now build modedb from EDID */
1760 fb_edid_to_monspecs(info->edid_data, &fb->monspecs);
1761 fb_videomode_to_modelist(fb->monspecs.modedb,
1762 fb->monspecs.modedb_len,
1763 &fb->modelist);
1764 }
1765
1720 if (enable && (pd->flags & SM501FB_FLAG_USE_INIT_MODE) && 0) { 1766 if (enable && (pd->flags & SM501FB_FLAG_USE_INIT_MODE) && 0) {
1721 /* TODO read the mode from the current display */ 1767 /* TODO read the mode from the current display */
1722
1723 } else { 1768 } else {
1724 if (pd->def_mode) { 1769 if (pd->def_mode) {
1725 dev_info(info->dev, "using supplied mode\n"); 1770 dev_info(info->dev, "using supplied mode\n");
@@ -1729,12 +1774,37 @@ static int sm501fb_init_fb(struct fb_info *fb,
1729 fb->var.xres_virtual = fb->var.xres; 1774 fb->var.xres_virtual = fb->var.xres;
1730 fb->var.yres_virtual = fb->var.yres; 1775 fb->var.yres_virtual = fb->var.yres;
1731 } else { 1776 } else {
1732 ret = fb_find_mode(&fb->var, fb, 1777 if (info->edid_data) {
1778 ret = fb_find_mode(&fb->var, fb, fb_mode,
1779 fb->monspecs.modedb,
1780 fb->monspecs.modedb_len,
1781 &sm501_default_mode, default_bpp);
1782 /* edid_data is no longer needed, free it */
1783 kfree(info->edid_data);
1784 } else {
1785 ret = fb_find_mode(&fb->var, fb,
1733 NULL, NULL, 0, NULL, 8); 1786 NULL, NULL, 0, NULL, 8);
1787 }
1734 1788
1735 if (ret == 0 || ret == 4) { 1789 switch (ret) {
1736 dev_err(info->dev, 1790 case 1:
1737 "failed to get initial mode\n"); 1791 dev_info(info->dev, "using mode specified in "
1792 "@mode\n");
1793 break;
1794 case 2:
1795 dev_info(info->dev, "using mode specified in "
1796 "@mode with ignored refresh rate\n");
1797 break;
1798 case 3:
1799 dev_info(info->dev, "using mode default "
1800 "mode\n");
1801 break;
1802 case 4:
1803 dev_info(info->dev, "using mode from list\n");
1804 break;
1805 default:
1806 dev_info(info->dev, "ret = %d\n", ret);
1807 dev_info(info->dev, "failed to find mode\n");
1738 return -EINVAL; 1808 return -EINVAL;
1739 } 1809 }
1740 } 1810 }
@@ -1875,8 +1945,32 @@ static int __devinit sm501fb_probe(struct platform_device *pdev)
1875 } 1945 }
1876 1946
1877 if (info->pdata == NULL) { 1947 if (info->pdata == NULL) {
1878 dev_info(dev, "using default configuration data\n"); 1948 int found = 0;
1949#if defined(CONFIG_OF)
1950 struct device_node *np = pdev->dev.parent->of_node;
1951 const u8 *prop;
1952 const char *cp;
1953 int len;
1954
1879 info->pdata = &sm501fb_def_pdata; 1955 info->pdata = &sm501fb_def_pdata;
1956 if (np) {
1957 /* Get EDID */
1958 cp = of_get_property(np, "mode", &len);
1959 if (cp)
1960 strcpy(fb_mode, cp);
1961 prop = of_get_property(np, "edid", &len);
1962 if (prop && len == EDID_LENGTH) {
1963 info->edid_data = kmemdup(prop, EDID_LENGTH,
1964 GFP_KERNEL);
1965 if (info->edid_data)
1966 found = 1;
1967 }
1968 }
1969#endif
1970 if (!found) {
1971 dev_info(dev, "using default configuration data\n");
1972 info->pdata = &sm501fb_def_pdata;
1973 }
1880 } 1974 }
1881 1975
1882 /* probe for the presence of each panel */ 1976 /* probe for the presence of each panel */
@@ -2010,9 +2104,9 @@ static int sm501fb_suspend_fb(struct sm501fb_info *info,
2010 2104
2011 /* tell console/fb driver we are suspending */ 2105 /* tell console/fb driver we are suspending */
2012 2106
2013 acquire_console_sem(); 2107 console_lock();
2014 fb_set_suspend(fbi, 1); 2108 fb_set_suspend(fbi, 1);
2015 release_console_sem(); 2109 console_unlock();
2016 2110
2017 /* backup copies in case chip is powered down over suspend */ 2111 /* backup copies in case chip is powered down over suspend */
2018 2112
@@ -2069,9 +2163,9 @@ static void sm501fb_resume_fb(struct sm501fb_info *info,
2069 memcpy_toio(par->cursor.k_addr, par->store_cursor, 2163 memcpy_toio(par->cursor.k_addr, par->store_cursor,
2070 par->cursor.size); 2164 par->cursor.size);
2071 2165
2072 acquire_console_sem(); 2166 console_lock();
2073 fb_set_suspend(fbi, 0); 2167 fb_set_suspend(fbi, 0);
2074 release_console_sem(); 2168 console_unlock();
2075 2169
2076 vfree(par->store_fb); 2170 vfree(par->store_fb);
2077 vfree(par->store_cursor); 2171 vfree(par->store_cursor);
@@ -2085,7 +2179,7 @@ static int sm501fb_suspend(struct platform_device *pdev, pm_message_t state)
2085 struct sm501fb_info *info = platform_get_drvdata(pdev); 2179 struct sm501fb_info *info = platform_get_drvdata(pdev);
2086 2180
2087 /* store crt control to resume with */ 2181 /* store crt control to resume with */
2088 info->pm_crt_ctrl = readl(info->regs + SM501_DC_CRT_CONTROL); 2182 info->pm_crt_ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
2089 2183
2090 sm501fb_suspend_fb(info, HEAD_CRT); 2184 sm501fb_suspend_fb(info, HEAD_CRT);
2091 sm501fb_suspend_fb(info, HEAD_PANEL); 2185 sm501fb_suspend_fb(info, HEAD_PANEL);
@@ -2109,10 +2203,10 @@ static int sm501fb_resume(struct platform_device *pdev)
2109 2203
2110 /* restore the items we want to be saved for crt control */ 2204 /* restore the items we want to be saved for crt control */
2111 2205
2112 crt_ctrl = readl(info->regs + SM501_DC_CRT_CONTROL); 2206 crt_ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
2113 crt_ctrl &= ~SM501_CRT_CTRL_SAVE; 2207 crt_ctrl &= ~SM501_CRT_CTRL_SAVE;
2114 crt_ctrl |= info->pm_crt_ctrl & SM501_CRT_CTRL_SAVE; 2208 crt_ctrl |= info->pm_crt_ctrl & SM501_CRT_CTRL_SAVE;
2115 writel(crt_ctrl, info->regs + SM501_DC_CRT_CONTROL); 2209 smc501_writel(crt_ctrl, info->regs + SM501_DC_CRT_CONTROL);
2116 2210
2117 sm501fb_resume_fb(info, HEAD_CRT); 2211 sm501fb_resume_fb(info, HEAD_CRT);
2118 sm501fb_resume_fb(info, HEAD_PANEL); 2212 sm501fb_resume_fb(info, HEAD_PANEL);
@@ -2149,6 +2243,11 @@ static void __exit sm501fb_cleanup(void)
2149module_init(sm501fb_init); 2243module_init(sm501fb_init);
2150module_exit(sm501fb_cleanup); 2244module_exit(sm501fb_cleanup);
2151 2245
2246module_param_named(mode, fb_mode, charp, 0);
2247MODULE_PARM_DESC(mode,
2248 "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
2249module_param_named(bpp, default_bpp, ulong, 0);
2250MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified mode");
2152MODULE_AUTHOR("Ben Dooks, Vincent Sanders"); 2251MODULE_AUTHOR("Ben Dooks, Vincent Sanders");
2153MODULE_DESCRIPTION("SM501 Framebuffer driver"); 2252MODULE_DESCRIPTION("SM501 Framebuffer driver");
2154MODULE_LICENSE("GPL v2"); 2253MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c
index dee64c3b1e67..2301c275d63a 100644
--- a/drivers/video/sstfb.c
+++ b/drivers/video/sstfb.c
@@ -221,7 +221,7 @@ static int __sst_wait_idle(u8 __iomem *vbase)
221 while(1) { 221 while(1) {
222 if (__sst_read(vbase, STATUS) & STATUS_FBI_BUSY) { 222 if (__sst_read(vbase, STATUS) & STATUS_FBI_BUSY) {
223 f_dddprintk("status: busy\n"); 223 f_dddprintk("status: busy\n");
224/* FIXME basicaly, this is a busy wait. maybe not that good. oh well; 224/* FIXME basically, this is a busy wait. maybe not that good. oh well;
225 * this is a small loop after all. 225 * this is a small loop after all.
226 * Or maybe we should use mdelay() or udelay() here instead ? */ 226 * Or maybe we should use mdelay() or udelay() here instead ? */
227 count = 0; 227 count = 0;
@@ -501,7 +501,7 @@ static int sstfb_set_par(struct fb_info *info)
501 } 501 }
502 502
503 if (IS_VOODOO2(par)) { 503 if (IS_VOODOO2(par)) {
504 /* voodoo2 has 32 pixel wide tiles , BUT stange things 504 /* voodoo2 has 32 pixel wide tiles , BUT strange things
505 happen with odd number of tiles */ 505 happen with odd number of tiles */
506 par->tiles_in_X = (info->var.xres + 63 ) / 64 * 2; 506 par->tiles_in_X = (info->var.xres + 63 ) / 64 * 2;
507 } else { 507 } else {
@@ -536,7 +536,7 @@ static int sstfb_set_par(struct fb_info *info)
536 fbiinit2 = sst_read(FBIINIT2); 536 fbiinit2 = sst_read(FBIINIT2);
537 fbiinit3 = sst_read(FBIINIT3); 537 fbiinit3 = sst_read(FBIINIT3);
538 538
539 /* everything is reset. we enable fbiinit2/3 remap : dac acces ok */ 539 /* everything is reset. we enable fbiinit2/3 remap : dac access ok */
540 pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, 540 pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
541 PCI_EN_INIT_WR | PCI_REMAP_DAC ); 541 PCI_EN_INIT_WR | PCI_REMAP_DAC );
542 542
@@ -920,11 +920,11 @@ static int __devinit sst_detect_ti(struct fb_info *info)
920 * we get the 1st byte (M value) of preset f1,f7 and fB 920 * we get the 1st byte (M value) of preset f1,f7 and fB
921 * why those 3 ? mmmh... for now, i'll do it the glide way... 921 * why those 3 ? mmmh... for now, i'll do it the glide way...
922 * and ask questions later. anyway, it seems that all the freq registers are 922 * and ask questions later. anyway, it seems that all the freq registers are
923 * realy at their default state (cf specs) so i ask again, why those 3 regs ? 923 * really at their default state (cf specs) so i ask again, why those 3 regs ?
924 * mmmmh.. it seems that's much more ugly than i thought. we use f0 and fA for 924 * mmmmh.. it seems that's much more ugly than i thought. we use f0 and fA for
925 * pll programming, so in fact, we *hope* that the f1, f7 & fB won't be 925 * pll programming, so in fact, we *hope* that the f1, f7 & fB won't be
926 * touched... 926 * touched...
927 * is it realy safe ? how can i reset this ramdac ? geee... 927 * is it really safe ? how can i reset this ramdac ? geee...
928 */ 928 */
929static int __devinit sst_detect_ics(struct fb_info *info) 929static int __devinit sst_detect_ics(struct fb_info *info)
930{ 930{
diff --git a/drivers/video/sticore.h b/drivers/video/sticore.h
index 7fe5be4bc70e..addf7b615ef8 100644
--- a/drivers/video/sticore.h
+++ b/drivers/video/sticore.h
@@ -79,7 +79,7 @@ struct sti_glob_cfg_ext {
79 u8 curr_mon; /* current monitor configured */ 79 u8 curr_mon; /* current monitor configured */
80 u8 friendly_boot; /* in friendly boot mode */ 80 u8 friendly_boot; /* in friendly boot mode */
81 s16 power; /* power calculation (in Watts) */ 81 s16 power; /* power calculation (in Watts) */
82 s32 freq_ref; /* frequency refrence */ 82 s32 freq_ref; /* frequency reference */
83 u32 sti_mem_addr; /* pointer to global sti memory (size=sti_mem_request) */ 83 u32 sti_mem_addr; /* pointer to global sti memory (size=sti_mem_request) */
84 u32 future_ptr; /* pointer to future data */ 84 u32 future_ptr; /* pointer to future data */
85}; 85};
diff --git a/drivers/video/sunxvr1000.c b/drivers/video/sunxvr1000.c
index 5dbe06af2226..b7f27acaf817 100644
--- a/drivers/video/sunxvr1000.c
+++ b/drivers/video/sunxvr1000.c
@@ -111,8 +111,7 @@ static int __devinit gfb_set_fbinfo(struct gfb_info *gp)
111 return 0; 111 return 0;
112} 112}
113 113
114static int __devinit gfb_probe(struct platform_device *op, 114static int __devinit gfb_probe(struct platform_device *op)
115 const struct of_device_id *match)
116{ 115{
117 struct device_node *dp = op->dev.of_node; 116 struct device_node *dp = op->dev.of_node;
118 struct fb_info *info; 117 struct fb_info *info;
@@ -198,7 +197,7 @@ static const struct of_device_id gfb_match[] = {
198}; 197};
199MODULE_DEVICE_TABLE(of, ffb_match); 198MODULE_DEVICE_TABLE(of, ffb_match);
200 199
201static struct of_platform_driver gfb_driver = { 200static struct platform_driver gfb_driver = {
202 .probe = gfb_probe, 201 .probe = gfb_probe,
203 .remove = __devexit_p(gfb_remove), 202 .remove = __devexit_p(gfb_remove),
204 .driver = { 203 .driver = {
@@ -213,12 +212,12 @@ static int __init gfb_init(void)
213 if (fb_get_options("gfb", NULL)) 212 if (fb_get_options("gfb", NULL))
214 return -ENODEV; 213 return -ENODEV;
215 214
216 return of_register_platform_driver(&gfb_driver); 215 return platform_driver_register(&gfb_driver);
217} 216}
218 217
219static void __exit gfb_exit(void) 218static void __exit gfb_exit(void)
220{ 219{
221 of_unregister_platform_driver(&gfb_driver); 220 platform_driver_unregister(&gfb_driver);
222} 221}
223 222
224module_init(gfb_init); 223module_init(gfb_init);
diff --git a/drivers/video/svgalib.c b/drivers/video/svgalib.c
index fdb45674e2f6..33df9ec91795 100644
--- a/drivers/video/svgalib.c
+++ b/drivers/video/svgalib.c
@@ -20,12 +20,12 @@
20 20
21 21
22/* Write a CRT register value spread across multiple registers */ 22/* Write a CRT register value spread across multiple registers */
23void svga_wcrt_multi(const struct vga_regset *regset, u32 value) { 23void svga_wcrt_multi(void __iomem *regbase, const struct vga_regset *regset, u32 value)
24 24{
25 u8 regval, bitval, bitnum; 25 u8 regval, bitval, bitnum;
26 26
27 while (regset->regnum != VGA_REGSET_END_VAL) { 27 while (regset->regnum != VGA_REGSET_END_VAL) {
28 regval = vga_rcrt(NULL, regset->regnum); 28 regval = vga_rcrt(regbase, regset->regnum);
29 bitnum = regset->lowbit; 29 bitnum = regset->lowbit;
30 while (bitnum <= regset->highbit) { 30 while (bitnum <= regset->highbit) {
31 bitval = 1 << bitnum; 31 bitval = 1 << bitnum;
@@ -34,18 +34,18 @@ void svga_wcrt_multi(const struct vga_regset *regset, u32 value) {
34 bitnum ++; 34 bitnum ++;
35 value = value >> 1; 35 value = value >> 1;
36 } 36 }
37 vga_wcrt(NULL, regset->regnum, regval); 37 vga_wcrt(regbase, regset->regnum, regval);
38 regset ++; 38 regset ++;
39 } 39 }
40} 40}
41 41
42/* Write a sequencer register value spread across multiple registers */ 42/* Write a sequencer register value spread across multiple registers */
43void svga_wseq_multi(const struct vga_regset *regset, u32 value) { 43void svga_wseq_multi(void __iomem *regbase, const struct vga_regset *regset, u32 value)
44 44{
45 u8 regval, bitval, bitnum; 45 u8 regval, bitval, bitnum;
46 46
47 while (regset->regnum != VGA_REGSET_END_VAL) { 47 while (regset->regnum != VGA_REGSET_END_VAL) {
48 regval = vga_rseq(NULL, regset->regnum); 48 regval = vga_rseq(regbase, regset->regnum);
49 bitnum = regset->lowbit; 49 bitnum = regset->lowbit;
50 while (bitnum <= regset->highbit) { 50 while (bitnum <= regset->highbit) {
51 bitval = 1 << bitnum; 51 bitval = 1 << bitnum;
@@ -54,7 +54,7 @@ void svga_wseq_multi(const struct vga_regset *regset, u32 value) {
54 bitnum ++; 54 bitnum ++;
55 value = value >> 1; 55 value = value >> 1;
56 } 56 }
57 vga_wseq(NULL, regset->regnum, regval); 57 vga_wseq(regbase, regset->regnum, regval);
58 regset ++; 58 regset ++;
59 } 59 }
60} 60}
@@ -75,95 +75,95 @@ static unsigned int svga_regset_size(const struct vga_regset *regset)
75 75
76 76
77/* Set graphics controller registers to sane values */ 77/* Set graphics controller registers to sane values */
78void svga_set_default_gfx_regs(void) 78void svga_set_default_gfx_regs(void __iomem *regbase)
79{ 79{
80 /* All standard GFX registers (GR00 - GR08) */ 80 /* All standard GFX registers (GR00 - GR08) */
81 vga_wgfx(NULL, VGA_GFX_SR_VALUE, 0x00); 81 vga_wgfx(regbase, VGA_GFX_SR_VALUE, 0x00);
82 vga_wgfx(NULL, VGA_GFX_SR_ENABLE, 0x00); 82 vga_wgfx(regbase, VGA_GFX_SR_ENABLE, 0x00);
83 vga_wgfx(NULL, VGA_GFX_COMPARE_VALUE, 0x00); 83 vga_wgfx(regbase, VGA_GFX_COMPARE_VALUE, 0x00);
84 vga_wgfx(NULL, VGA_GFX_DATA_ROTATE, 0x00); 84 vga_wgfx(regbase, VGA_GFX_DATA_ROTATE, 0x00);
85 vga_wgfx(NULL, VGA_GFX_PLANE_READ, 0x00); 85 vga_wgfx(regbase, VGA_GFX_PLANE_READ, 0x00);
86 vga_wgfx(NULL, VGA_GFX_MODE, 0x00); 86 vga_wgfx(regbase, VGA_GFX_MODE, 0x00);
87/* vga_wgfx(NULL, VGA_GFX_MODE, 0x20); */ 87/* vga_wgfx(regbase, VGA_GFX_MODE, 0x20); */
88/* vga_wgfx(NULL, VGA_GFX_MODE, 0x40); */ 88/* vga_wgfx(regbase, VGA_GFX_MODE, 0x40); */
89 vga_wgfx(NULL, VGA_GFX_MISC, 0x05); 89 vga_wgfx(regbase, VGA_GFX_MISC, 0x05);
90/* vga_wgfx(NULL, VGA_GFX_MISC, 0x01); */ 90/* vga_wgfx(regbase, VGA_GFX_MISC, 0x01); */
91 vga_wgfx(NULL, VGA_GFX_COMPARE_MASK, 0x0F); 91 vga_wgfx(regbase, VGA_GFX_COMPARE_MASK, 0x0F);
92 vga_wgfx(NULL, VGA_GFX_BIT_MASK, 0xFF); 92 vga_wgfx(regbase, VGA_GFX_BIT_MASK, 0xFF);
93} 93}
94 94
95/* Set attribute controller registers to sane values */ 95/* Set attribute controller registers to sane values */
96void svga_set_default_atc_regs(void) 96void svga_set_default_atc_regs(void __iomem *regbase)
97{ 97{
98 u8 count; 98 u8 count;
99 99
100 vga_r(NULL, 0x3DA); 100 vga_r(regbase, 0x3DA);
101 vga_w(NULL, VGA_ATT_W, 0x00); 101 vga_w(regbase, VGA_ATT_W, 0x00);
102 102
103 /* All standard ATC registers (AR00 - AR14) */ 103 /* All standard ATC registers (AR00 - AR14) */
104 for (count = 0; count <= 0xF; count ++) 104 for (count = 0; count <= 0xF; count ++)
105 svga_wattr(count, count); 105 svga_wattr(regbase, count, count);
106 106
107 svga_wattr(VGA_ATC_MODE, 0x01); 107 svga_wattr(regbase, VGA_ATC_MODE, 0x01);
108/* svga_wattr(VGA_ATC_MODE, 0x41); */ 108/* svga_wattr(regbase, VGA_ATC_MODE, 0x41); */
109 svga_wattr(VGA_ATC_OVERSCAN, 0x00); 109 svga_wattr(regbase, VGA_ATC_OVERSCAN, 0x00);
110 svga_wattr(VGA_ATC_PLANE_ENABLE, 0x0F); 110 svga_wattr(regbase, VGA_ATC_PLANE_ENABLE, 0x0F);
111 svga_wattr(VGA_ATC_PEL, 0x00); 111 svga_wattr(regbase, VGA_ATC_PEL, 0x00);
112 svga_wattr(VGA_ATC_COLOR_PAGE, 0x00); 112 svga_wattr(regbase, VGA_ATC_COLOR_PAGE, 0x00);
113 113
114 vga_r(NULL, 0x3DA); 114 vga_r(regbase, 0x3DA);
115 vga_w(NULL, VGA_ATT_W, 0x20); 115 vga_w(regbase, VGA_ATT_W, 0x20);
116} 116}
117 117
118/* Set sequencer registers to sane values */ 118/* Set sequencer registers to sane values */
119void svga_set_default_seq_regs(void) 119void svga_set_default_seq_regs(void __iomem *regbase)
120{ 120{
121 /* Standard sequencer registers (SR01 - SR04), SR00 is not set */ 121 /* Standard sequencer registers (SR01 - SR04), SR00 is not set */
122 vga_wseq(NULL, VGA_SEQ_CLOCK_MODE, VGA_SR01_CHAR_CLK_8DOTS); 122 vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, VGA_SR01_CHAR_CLK_8DOTS);
123 vga_wseq(NULL, VGA_SEQ_PLANE_WRITE, VGA_SR02_ALL_PLANES); 123 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, VGA_SR02_ALL_PLANES);
124 vga_wseq(NULL, VGA_SEQ_CHARACTER_MAP, 0x00); 124 vga_wseq(regbase, VGA_SEQ_CHARACTER_MAP, 0x00);
125/* vga_wseq(NULL, VGA_SEQ_MEMORY_MODE, VGA_SR04_EXT_MEM | VGA_SR04_SEQ_MODE | VGA_SR04_CHN_4M); */ 125/* vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, VGA_SR04_EXT_MEM | VGA_SR04_SEQ_MODE | VGA_SR04_CHN_4M); */
126 vga_wseq(NULL, VGA_SEQ_MEMORY_MODE, VGA_SR04_EXT_MEM | VGA_SR04_SEQ_MODE); 126 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, VGA_SR04_EXT_MEM | VGA_SR04_SEQ_MODE);
127} 127}
128 128
129/* Set CRTC registers to sane values */ 129/* Set CRTC registers to sane values */
130void svga_set_default_crt_regs(void) 130void svga_set_default_crt_regs(void __iomem *regbase)
131{ 131{
132 /* Standard CRT registers CR03 CR08 CR09 CR14 CR17 */ 132 /* Standard CRT registers CR03 CR08 CR09 CR14 CR17 */
133 svga_wcrt_mask(0x03, 0x80, 0x80); /* Enable vertical retrace EVRA */ 133 svga_wcrt_mask(regbase, 0x03, 0x80, 0x80); /* Enable vertical retrace EVRA */
134 vga_wcrt(NULL, VGA_CRTC_PRESET_ROW, 0); 134 vga_wcrt(regbase, VGA_CRTC_PRESET_ROW, 0);
135 svga_wcrt_mask(VGA_CRTC_MAX_SCAN, 0, 0x1F); 135 svga_wcrt_mask(regbase, VGA_CRTC_MAX_SCAN, 0, 0x1F);
136 vga_wcrt(NULL, VGA_CRTC_UNDERLINE, 0); 136 vga_wcrt(regbase, VGA_CRTC_UNDERLINE, 0);
137 vga_wcrt(NULL, VGA_CRTC_MODE, 0xE3); 137 vga_wcrt(regbase, VGA_CRTC_MODE, 0xE3);
138} 138}
139 139
140void svga_set_textmode_vga_regs(void) 140void svga_set_textmode_vga_regs(void __iomem *regbase)
141{ 141{
142 /* svga_wseq_mask(0x1, 0x00, 0x01); */ /* Switch 8/9 pixel per char */ 142 /* svga_wseq_mask(regbase, 0x1, 0x00, 0x01); */ /* Switch 8/9 pixel per char */
143 vga_wseq(NULL, VGA_SEQ_MEMORY_MODE, VGA_SR04_EXT_MEM); 143 vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, VGA_SR04_EXT_MEM);
144 vga_wseq(NULL, VGA_SEQ_PLANE_WRITE, 0x03); 144 vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0x03);
145 145
146 vga_wcrt(NULL, VGA_CRTC_MAX_SCAN, 0x0f); /* 0x4f */ 146 vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, 0x0f); /* 0x4f */
147 vga_wcrt(NULL, VGA_CRTC_UNDERLINE, 0x1f); 147 vga_wcrt(regbase, VGA_CRTC_UNDERLINE, 0x1f);
148 svga_wcrt_mask(VGA_CRTC_MODE, 0x23, 0x7f); 148 svga_wcrt_mask(regbase, VGA_CRTC_MODE, 0x23, 0x7f);
149 149
150 vga_wcrt(NULL, VGA_CRTC_CURSOR_START, 0x0d); 150 vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0x0d);
151 vga_wcrt(NULL, VGA_CRTC_CURSOR_END, 0x0e); 151 vga_wcrt(regbase, VGA_CRTC_CURSOR_END, 0x0e);
152 vga_wcrt(NULL, VGA_CRTC_CURSOR_HI, 0x00); 152 vga_wcrt(regbase, VGA_CRTC_CURSOR_HI, 0x00);
153 vga_wcrt(NULL, VGA_CRTC_CURSOR_LO, 0x00); 153 vga_wcrt(regbase, VGA_CRTC_CURSOR_LO, 0x00);
154 154
155 vga_wgfx(NULL, VGA_GFX_MODE, 0x10); /* Odd/even memory mode */ 155 vga_wgfx(regbase, VGA_GFX_MODE, 0x10); /* Odd/even memory mode */
156 vga_wgfx(NULL, VGA_GFX_MISC, 0x0E); /* Misc graphics register - text mode enable */ 156 vga_wgfx(regbase, VGA_GFX_MISC, 0x0E); /* Misc graphics register - text mode enable */
157 vga_wgfx(NULL, VGA_GFX_COMPARE_MASK, 0x00); 157 vga_wgfx(regbase, VGA_GFX_COMPARE_MASK, 0x00);
158 158
159 vga_r(NULL, 0x3DA); 159 vga_r(regbase, 0x3DA);
160 vga_w(NULL, VGA_ATT_W, 0x00); 160 vga_w(regbase, VGA_ATT_W, 0x00);
161 161
162 svga_wattr(0x10, 0x0C); /* Attribute Mode Control Register - text mode, blinking and line graphics */ 162 svga_wattr(regbase, 0x10, 0x0C); /* Attribute Mode Control Register - text mode, blinking and line graphics */
163 svga_wattr(0x13, 0x08); /* Horizontal Pixel Panning Register */ 163 svga_wattr(regbase, 0x13, 0x08); /* Horizontal Pixel Panning Register */
164 164
165 vga_r(NULL, 0x3DA); 165 vga_r(regbase, 0x3DA);
166 vga_w(NULL, VGA_ATT_W, 0x20); 166 vga_w(regbase, VGA_ATT_W, 0x20);
167} 167}
168 168
169#if 0 169#if 0
@@ -299,7 +299,7 @@ void svga_tileblit(struct fb_info *info, struct fb_tileblit *blit)
299} 299}
300 300
301/* Set cursor in text (tileblit) mode */ 301/* Set cursor in text (tileblit) mode */
302void svga_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor) 302void svga_tilecursor(void __iomem *regbase, struct fb_info *info, struct fb_tilecursor *cursor)
303{ 303{
304 u8 cs = 0x0d; 304 u8 cs = 0x0d;
305 u8 ce = 0x0e; 305 u8 ce = 0x0e;
@@ -310,7 +310,7 @@ void svga_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor)
310 if (! cursor -> mode) 310 if (! cursor -> mode)
311 return; 311 return;
312 312
313 svga_wcrt_mask(0x0A, 0x20, 0x20); /* disable cursor */ 313 svga_wcrt_mask(regbase, 0x0A, 0x20, 0x20); /* disable cursor */
314 314
315 if (cursor -> shape == FB_TILE_CURSOR_NONE) 315 if (cursor -> shape == FB_TILE_CURSOR_NONE)
316 return; 316 return;
@@ -334,11 +334,11 @@ void svga_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor)
334 } 334 }
335 335
336 /* set cursor position */ 336 /* set cursor position */
337 vga_wcrt(NULL, 0x0E, pos >> 8); 337 vga_wcrt(regbase, 0x0E, pos >> 8);
338 vga_wcrt(NULL, 0x0F, pos & 0xFF); 338 vga_wcrt(regbase, 0x0F, pos & 0xFF);
339 339
340 vga_wcrt(NULL, 0x0B, ce); /* set cursor end */ 340 vga_wcrt(regbase, 0x0B, ce); /* set cursor end */
341 vga_wcrt(NULL, 0x0A, cs); /* set cursor start and enable it */ 341 vga_wcrt(regbase, 0x0A, cs); /* set cursor start and enable it */
342} 342}
343 343
344int svga_get_tilemax(struct fb_info *info) 344int svga_get_tilemax(struct fb_info *info)
@@ -507,8 +507,9 @@ int svga_check_timings(const struct svga_timing_regs *tm, struct fb_var_screenin
507} 507}
508 508
509/* Set CRT timing registers */ 509/* Set CRT timing registers */
510void svga_set_timings(const struct svga_timing_regs *tm, struct fb_var_screeninfo *var, 510void svga_set_timings(void __iomem *regbase, const struct svga_timing_regs *tm,
511 u32 hmul, u32 hdiv, u32 vmul, u32 vdiv, u32 hborder, int node) 511 struct fb_var_screeninfo *var,
512 u32 hmul, u32 hdiv, u32 vmul, u32 vdiv, u32 hborder, int node)
512{ 513{
513 u8 regval; 514 u8 regval;
514 u32 value; 515 u32 value;
@@ -516,66 +517,66 @@ void svga_set_timings(const struct svga_timing_regs *tm, struct fb_var_screeninf
516 value = var->xres + var->left_margin + var->right_margin + var->hsync_len; 517 value = var->xres + var->left_margin + var->right_margin + var->hsync_len;
517 value = (value * hmul) / hdiv; 518 value = (value * hmul) / hdiv;
518 pr_debug("fb%d: horizontal total : %d\n", node, value); 519 pr_debug("fb%d: horizontal total : %d\n", node, value);
519 svga_wcrt_multi(tm->h_total_regs, (value / 8) - 5); 520 svga_wcrt_multi(regbase, tm->h_total_regs, (value / 8) - 5);
520 521
521 value = var->xres; 522 value = var->xres;
522 value = (value * hmul) / hdiv; 523 value = (value * hmul) / hdiv;
523 pr_debug("fb%d: horizontal display : %d\n", node, value); 524 pr_debug("fb%d: horizontal display : %d\n", node, value);
524 svga_wcrt_multi(tm->h_display_regs, (value / 8) - 1); 525 svga_wcrt_multi(regbase, tm->h_display_regs, (value / 8) - 1);
525 526
526 value = var->xres; 527 value = var->xres;
527 value = (value * hmul) / hdiv; 528 value = (value * hmul) / hdiv;
528 pr_debug("fb%d: horizontal blank start: %d\n", node, value); 529 pr_debug("fb%d: horizontal blank start: %d\n", node, value);
529 svga_wcrt_multi(tm->h_blank_start_regs, (value / 8) - 1 + hborder); 530 svga_wcrt_multi(regbase, tm->h_blank_start_regs, (value / 8) - 1 + hborder);
530 531
531 value = var->xres + var->left_margin + var->right_margin + var->hsync_len; 532 value = var->xres + var->left_margin + var->right_margin + var->hsync_len;
532 value = (value * hmul) / hdiv; 533 value = (value * hmul) / hdiv;
533 pr_debug("fb%d: horizontal blank end : %d\n", node, value); 534 pr_debug("fb%d: horizontal blank end : %d\n", node, value);
534 svga_wcrt_multi(tm->h_blank_end_regs, (value / 8) - 1 - hborder); 535 svga_wcrt_multi(regbase, tm->h_blank_end_regs, (value / 8) - 1 - hborder);
535 536
536 value = var->xres + var->right_margin; 537 value = var->xres + var->right_margin;
537 value = (value * hmul) / hdiv; 538 value = (value * hmul) / hdiv;
538 pr_debug("fb%d: horizontal sync start : %d\n", node, value); 539 pr_debug("fb%d: horizontal sync start : %d\n", node, value);
539 svga_wcrt_multi(tm->h_sync_start_regs, (value / 8)); 540 svga_wcrt_multi(regbase, tm->h_sync_start_regs, (value / 8));
540 541
541 value = var->xres + var->right_margin + var->hsync_len; 542 value = var->xres + var->right_margin + var->hsync_len;
542 value = (value * hmul) / hdiv; 543 value = (value * hmul) / hdiv;
543 pr_debug("fb%d: horizontal sync end : %d\n", node, value); 544 pr_debug("fb%d: horizontal sync end : %d\n", node, value);
544 svga_wcrt_multi(tm->h_sync_end_regs, (value / 8)); 545 svga_wcrt_multi(regbase, tm->h_sync_end_regs, (value / 8));
545 546
546 value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len; 547 value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
547 value = (value * vmul) / vdiv; 548 value = (value * vmul) / vdiv;
548 pr_debug("fb%d: vertical total : %d\n", node, value); 549 pr_debug("fb%d: vertical total : %d\n", node, value);
549 svga_wcrt_multi(tm->v_total_regs, value - 2); 550 svga_wcrt_multi(regbase, tm->v_total_regs, value - 2);
550 551
551 value = var->yres; 552 value = var->yres;
552 value = (value * vmul) / vdiv; 553 value = (value * vmul) / vdiv;
553 pr_debug("fb%d: vertical display : %d\n", node, value); 554 pr_debug("fb%d: vertical display : %d\n", node, value);
554 svga_wcrt_multi(tm->v_display_regs, value - 1); 555 svga_wcrt_multi(regbase, tm->v_display_regs, value - 1);
555 556
556 value = var->yres; 557 value = var->yres;
557 value = (value * vmul) / vdiv; 558 value = (value * vmul) / vdiv;
558 pr_debug("fb%d: vertical blank start : %d\n", node, value); 559 pr_debug("fb%d: vertical blank start : %d\n", node, value);
559 svga_wcrt_multi(tm->v_blank_start_regs, value); 560 svga_wcrt_multi(regbase, tm->v_blank_start_regs, value);
560 561
561 value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len; 562 value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
562 value = (value * vmul) / vdiv; 563 value = (value * vmul) / vdiv;
563 pr_debug("fb%d: vertical blank end : %d\n", node, value); 564 pr_debug("fb%d: vertical blank end : %d\n", node, value);
564 svga_wcrt_multi(tm->v_blank_end_regs, value - 2); 565 svga_wcrt_multi(regbase, tm->v_blank_end_regs, value - 2);
565 566
566 value = var->yres + var->lower_margin; 567 value = var->yres + var->lower_margin;
567 value = (value * vmul) / vdiv; 568 value = (value * vmul) / vdiv;
568 pr_debug("fb%d: vertical sync start : %d\n", node, value); 569 pr_debug("fb%d: vertical sync start : %d\n", node, value);
569 svga_wcrt_multi(tm->v_sync_start_regs, value); 570 svga_wcrt_multi(regbase, tm->v_sync_start_regs, value);
570 571
571 value = var->yres + var->lower_margin + var->vsync_len; 572 value = var->yres + var->lower_margin + var->vsync_len;
572 value = (value * vmul) / vdiv; 573 value = (value * vmul) / vdiv;
573 pr_debug("fb%d: vertical sync end : %d\n", node, value); 574 pr_debug("fb%d: vertical sync end : %d\n", node, value);
574 svga_wcrt_multi(tm->v_sync_end_regs, value); 575 svga_wcrt_multi(regbase, tm->v_sync_end_regs, value);
575 576
576 /* Set horizontal and vertical sync pulse polarity in misc register */ 577 /* Set horizontal and vertical sync pulse polarity in misc register */
577 578
578 regval = vga_r(NULL, VGA_MIS_R); 579 regval = vga_r(regbase, VGA_MIS_R);
579 if (var->sync & FB_SYNC_HOR_HIGH_ACT) { 580 if (var->sync & FB_SYNC_HOR_HIGH_ACT) {
580 pr_debug("fb%d: positive horizontal sync\n", node); 581 pr_debug("fb%d: positive horizontal sync\n", node);
581 regval = regval & ~0x80; 582 regval = regval & ~0x80;
@@ -590,7 +591,7 @@ void svga_set_timings(const struct svga_timing_regs *tm, struct fb_var_screeninf
590 pr_debug("fb%d: negative vertical sync\n\n", node); 591 pr_debug("fb%d: negative vertical sync\n\n", node);
591 regval = regval | 0x40; 592 regval = regval | 0x40;
592 } 593 }
593 vga_w(NULL, VGA_MIS_W, regval); 594 vga_w(regbase, VGA_MIS_W, regval);
594} 595}
595 596
596 597
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c
index 77ad27955cf0..07c66e946634 100644
--- a/drivers/video/tcx.c
+++ b/drivers/video/tcx.c
@@ -362,8 +362,7 @@ static void tcx_unmap_regs(struct platform_device *op, struct fb_info *info,
362 info->screen_base, info->fix.smem_len); 362 info->screen_base, info->fix.smem_len);
363} 363}
364 364
365static int __devinit tcx_probe(struct platform_device *op, 365static int __devinit tcx_probe(struct platform_device *op)
366 const struct of_device_id *match)
367{ 366{
368 struct device_node *dp = op->dev.of_node; 367 struct device_node *dp = op->dev.of_node;
369 struct fb_info *info; 368 struct fb_info *info;
@@ -481,6 +480,7 @@ out_dealloc_cmap:
481 480
482out_unmap_regs: 481out_unmap_regs:
483 tcx_unmap_regs(op, info, par); 482 tcx_unmap_regs(op, info, par);
483 framebuffer_release(info);
484 484
485out_err: 485out_err:
486 return err; 486 return err;
@@ -511,7 +511,7 @@ static const struct of_device_id tcx_match[] = {
511}; 511};
512MODULE_DEVICE_TABLE(of, tcx_match); 512MODULE_DEVICE_TABLE(of, tcx_match);
513 513
514static struct of_platform_driver tcx_driver = { 514static struct platform_driver tcx_driver = {
515 .driver = { 515 .driver = {
516 .name = "tcx", 516 .name = "tcx",
517 .owner = THIS_MODULE, 517 .owner = THIS_MODULE,
@@ -526,12 +526,12 @@ static int __init tcx_init(void)
526 if (fb_get_options("tcxfb", NULL)) 526 if (fb_get_options("tcxfb", NULL))
527 return -ENODEV; 527 return -ENODEV;
528 528
529 return of_register_platform_driver(&tcx_driver); 529 return platform_driver_register(&tcx_driver);
530} 530}
531 531
532static void __exit tcx_exit(void) 532static void __exit tcx_exit(void)
533{ 533{
534 of_unregister_platform_driver(&tcx_driver); 534 platform_driver_unregister(&tcx_driver);
535} 535}
536 536
537module_init(tcx_init); 537module_init(tcx_init);
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index 3ee5e63cfa4f..a99b994c9b6b 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -877,12 +877,12 @@ static void tdfxfb_fillrect(struct fb_info *info,
877 else 877 else
878 tdfx_rop = TDFX_ROP_XOR; 878 tdfx_rop = TDFX_ROP_XOR;
879 879
880 /* asume always rect->height < 4096 */ 880 /* assume always rect->height < 4096 */
881 if (dy + rect->height > 4095) { 881 if (dy + rect->height > 4095) {
882 dstbase = stride * dy; 882 dstbase = stride * dy;
883 dy = 0; 883 dy = 0;
884 } 884 }
885 /* asume always rect->width < 4096 */ 885 /* assume always rect->width < 4096 */
886 if (dx + rect->width > 4095) { 886 if (dx + rect->width > 4095) {
887 dstbase += dx * bpp >> 3; 887 dstbase += dx * bpp >> 3;
888 dx = 0; 888 dx = 0;
@@ -915,22 +915,22 @@ static void tdfxfb_copyarea(struct fb_info *info,
915 u32 dstbase = 0; 915 u32 dstbase = 0;
916 u32 srcbase = 0; 916 u32 srcbase = 0;
917 917
918 /* asume always area->height < 4096 */ 918 /* assume always area->height < 4096 */
919 if (sy + area->height > 4095) { 919 if (sy + area->height > 4095) {
920 srcbase = stride * sy; 920 srcbase = stride * sy;
921 sy = 0; 921 sy = 0;
922 } 922 }
923 /* asume always area->width < 4096 */ 923 /* assume always area->width < 4096 */
924 if (sx + area->width > 4095) { 924 if (sx + area->width > 4095) {
925 srcbase += sx * bpp >> 3; 925 srcbase += sx * bpp >> 3;
926 sx = 0; 926 sx = 0;
927 } 927 }
928 /* asume always area->height < 4096 */ 928 /* assume always area->height < 4096 */
929 if (dy + area->height > 4095) { 929 if (dy + area->height > 4095) {
930 dstbase = stride * dy; 930 dstbase = stride * dy;
931 dy = 0; 931 dy = 0;
932 } 932 }
933 /* asume always area->width < 4096 */ 933 /* assume always area->width < 4096 */
934 if (dx + area->width > 4095) { 934 if (dx + area->width > 4095) {
935 dstbase += dx * bpp >> 3; 935 dstbase += dx * bpp >> 3;
936 dx = 0; 936 dx = 0;
@@ -1003,12 +1003,12 @@ static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image)
1003#else 1003#else
1004 srcfmt = 0x400000; 1004 srcfmt = 0x400000;
1005#endif 1005#endif
1006 /* asume always image->height < 4096 */ 1006 /* assume always image->height < 4096 */
1007 if (dy + image->height > 4095) { 1007 if (dy + image->height > 4095) {
1008 dstbase = stride * dy; 1008 dstbase = stride * dy;
1009 dy = 0; 1009 dy = 0;
1010 } 1010 }
1011 /* asume always image->width < 4096 */ 1011 /* assume always image->width < 4096 */
1012 if (dx + image->width > 4095) { 1012 if (dx + image->width > 4095) {
1013 dstbase += dx * bpp >> 3; 1013 dstbase += dx * bpp >> 3;
1014 dx = 0; 1014 dx = 0;
@@ -1124,7 +1124,7 @@ static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
1124 * lower half (least significant 64 bits) of a 128 bit word 1124 * lower half (least significant 64 bits) of a 128 bit word
1125 * and pattern 1 the upper half. If you examine the data of 1125 * and pattern 1 the upper half. If you examine the data of
1126 * the cursor image the graphics card uses then from the 1126 * the cursor image the graphics card uses then from the
1127 * begining you see line one of pattern 0, line one of 1127 * beginning you see line one of pattern 0, line one of
1128 * pattern 1, line two of pattern 0, line two of pattern 1, 1128 * pattern 1, line two of pattern 0, line two of pattern 1,
1129 * etc etc. The linear stride for the cursor is always 16 bytes 1129 * etc etc. The linear stride for the cursor is always 16 bytes
1130 * (128 bits) which is the maximum cursor width times two for 1130 * (128 bits) which is the maximum cursor width times two for
diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c
index 6913fe168c25..cd1c4dcef8fd 100644
--- a/drivers/video/tmiofb.c
+++ b/drivers/video/tmiofb.c
@@ -25,7 +25,7 @@
25#include <linux/fb.h> 25#include <linux/fb.h>
26#include <linux/interrupt.h> 26#include <linux/interrupt.h>
27#include <linux/delay.h> 27#include <linux/delay.h>
28/* Why should fb driver call console functions? because acquire_console_sem() */ 28/* Why should fb driver call console functions? because console_lock() */
29#include <linux/console.h> 29#include <linux/console.h>
30#include <linux/mfd/core.h> 30#include <linux/mfd/core.h>
31#include <linux/mfd/tmio.h> 31#include <linux/mfd/tmio.h>
@@ -250,8 +250,7 @@ static irqreturn_t tmiofb_irq(int irq, void *__info)
250 */ 250 */
251static int tmiofb_hw_stop(struct platform_device *dev) 251static int tmiofb_hw_stop(struct platform_device *dev)
252{ 252{
253 struct mfd_cell *cell = dev->dev.platform_data; 253 struct tmio_fb_data *data = dev->dev.platform_data;
254 struct tmio_fb_data *data = cell->driver_data;
255 struct fb_info *info = platform_get_drvdata(dev); 254 struct fb_info *info = platform_get_drvdata(dev);
256 struct tmiofb_par *par = info->par; 255 struct tmiofb_par *par = info->par;
257 256
@@ -268,7 +267,7 @@ static int tmiofb_hw_stop(struct platform_device *dev)
268 */ 267 */
269static int tmiofb_hw_init(struct platform_device *dev) 268static int tmiofb_hw_init(struct platform_device *dev)
270{ 269{
271 struct mfd_cell *cell = dev->dev.platform_data; 270 const struct mfd_cell *cell = mfd_get_cell(dev);
272 struct fb_info *info = platform_get_drvdata(dev); 271 struct fb_info *info = platform_get_drvdata(dev);
273 struct tmiofb_par *par = info->par; 272 struct tmiofb_par *par = info->par;
274 const struct resource *nlcr = &cell->resources[0]; 273 const struct resource *nlcr = &cell->resources[0];
@@ -312,8 +311,7 @@ static int tmiofb_hw_init(struct platform_device *dev)
312 */ 311 */
313static void tmiofb_hw_mode(struct platform_device *dev) 312static void tmiofb_hw_mode(struct platform_device *dev)
314{ 313{
315 struct mfd_cell *cell = dev->dev.platform_data; 314 struct tmio_fb_data *data = dev->dev.platform_data;
316 struct tmio_fb_data *data = cell->driver_data;
317 struct fb_info *info = platform_get_drvdata(dev); 315 struct fb_info *info = platform_get_drvdata(dev);
318 struct fb_videomode *mode = info->mode; 316 struct fb_videomode *mode = info->mode;
319 struct tmiofb_par *par = info->par; 317 struct tmiofb_par *par = info->par;
@@ -361,7 +359,7 @@ tmiofb_acc_wait(struct fb_info *info, unsigned int ccs)
361{ 359{
362 struct tmiofb_par *par = info->par; 360 struct tmiofb_par *par = info->par;
363 /* 361 /*
364 * This code can be called whith interrupts disabled. 362 * This code can be called with interrupts disabled.
365 * So instead of relaying on irq to trigger the event, 363 * So instead of relaying on irq to trigger the event,
366 * poll the state till the necessary command is executed. 364 * poll the state till the necessary command is executed.
367 */ 365 */
@@ -559,9 +557,7 @@ static int tmiofb_ioctl(struct fb_info *fbi,
559static struct fb_videomode * 557static struct fb_videomode *
560tmiofb_find_mode(struct fb_info *info, struct fb_var_screeninfo *var) 558tmiofb_find_mode(struct fb_info *info, struct fb_var_screeninfo *var)
561{ 559{
562 struct mfd_cell *cell = 560 struct tmio_fb_data *data = info->device->platform_data;
563 info->device->platform_data;
564 struct tmio_fb_data *data = cell->driver_data;
565 struct fb_videomode *best = NULL; 561 struct fb_videomode *best = NULL;
566 int i; 562 int i;
567 563
@@ -581,9 +577,7 @@ static int tmiofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
581{ 577{
582 578
583 struct fb_videomode *mode; 579 struct fb_videomode *mode;
584 struct mfd_cell *cell = 580 struct tmio_fb_data *data = info->device->platform_data;
585 info->device->platform_data;
586 struct tmio_fb_data *data = cell->driver_data;
587 581
588 mode = tmiofb_find_mode(info, var); 582 mode = tmiofb_find_mode(info, var);
589 if (!mode || var->bits_per_pixel > 16) 583 if (!mode || var->bits_per_pixel > 16)
@@ -683,8 +677,8 @@ static struct fb_ops tmiofb_ops = {
683 677
684static int __devinit tmiofb_probe(struct platform_device *dev) 678static int __devinit tmiofb_probe(struct platform_device *dev)
685{ 679{
686 struct mfd_cell *cell = dev->dev.platform_data; 680 const struct mfd_cell *cell = mfd_get_cell(dev);
687 struct tmio_fb_data *data = cell->driver_data; 681 struct tmio_fb_data *data = dev->dev.platform_data;
688 struct resource *ccr = platform_get_resource(dev, IORESOURCE_MEM, 1); 682 struct resource *ccr = platform_get_resource(dev, IORESOURCE_MEM, 1);
689 struct resource *lcr = platform_get_resource(dev, IORESOURCE_MEM, 0); 683 struct resource *lcr = platform_get_resource(dev, IORESOURCE_MEM, 0);
690 struct resource *vram = platform_get_resource(dev, IORESOURCE_MEM, 2); 684 struct resource *vram = platform_get_resource(dev, IORESOURCE_MEM, 2);
@@ -811,7 +805,7 @@ err_ioremap_ccr:
811 805
812static int __devexit tmiofb_remove(struct platform_device *dev) 806static int __devexit tmiofb_remove(struct platform_device *dev)
813{ 807{
814 struct mfd_cell *cell = dev->dev.platform_data; 808 const struct mfd_cell *cell = mfd_get_cell(dev);
815 struct fb_info *info = platform_get_drvdata(dev); 809 struct fb_info *info = platform_get_drvdata(dev);
816 int irq = platform_get_irq(dev, 0); 810 int irq = platform_get_irq(dev, 0);
817 struct tmiofb_par *par; 811 struct tmiofb_par *par;
@@ -941,10 +935,10 @@ static int tmiofb_suspend(struct platform_device *dev, pm_message_t state)
941#ifdef CONFIG_FB_TMIO_ACCELL 935#ifdef CONFIG_FB_TMIO_ACCELL
942 struct tmiofb_par *par = info->par; 936 struct tmiofb_par *par = info->par;
943#endif 937#endif
944 struct mfd_cell *cell = dev->dev.platform_data; 938 const struct mfd_cell *cell = mfd_get_cell(dev);
945 int retval = 0; 939 int retval = 0;
946 940
947 acquire_console_sem(); 941 console_lock();
948 942
949 fb_set_suspend(info, 1); 943 fb_set_suspend(info, 1);
950 944
@@ -965,7 +959,7 @@ static int tmiofb_suspend(struct platform_device *dev, pm_message_t state)
965 if (cell->suspend) 959 if (cell->suspend)
966 retval = cell->suspend(dev); 960 retval = cell->suspend(dev);
967 961
968 release_console_sem(); 962 console_unlock();
969 963
970 return retval; 964 return retval;
971} 965}
@@ -973,10 +967,10 @@ static int tmiofb_suspend(struct platform_device *dev, pm_message_t state)
973static int tmiofb_resume(struct platform_device *dev) 967static int tmiofb_resume(struct platform_device *dev)
974{ 968{
975 struct fb_info *info = platform_get_drvdata(dev); 969 struct fb_info *info = platform_get_drvdata(dev);
976 struct mfd_cell *cell = dev->dev.platform_data; 970 const struct mfd_cell *cell = mfd_get_cell(dev);
977 int retval = 0; 971 int retval = 0;
978 972
979 acquire_console_sem(); 973 console_lock();
980 974
981 if (cell->resume) { 975 if (cell->resume) {
982 retval = cell->resume(dev); 976 retval = cell->resume(dev);
@@ -992,7 +986,7 @@ static int tmiofb_resume(struct platform_device *dev)
992 986
993 fb_set_suspend(info, 0); 987 fb_set_suspend(info, 0);
994out: 988out:
995 release_console_sem(); 989 console_unlock();
996 return retval; 990 return retval;
997} 991}
998#else 992#else
diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c
new file mode 100644
index 000000000000..816a4fda04f5
--- /dev/null
+++ b/drivers/video/udlfb.c
@@ -0,0 +1,1897 @@
1/*
2 * udlfb.c -- Framebuffer driver for DisplayLink USB controller
3 *
4 * Copyright (C) 2009 Roberto De Ioris <roberto@unbit.it>
5 * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com>
6 * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License v2. See the file COPYING in the main directory of this archive for
10 * more details.
11 *
12 * Layout is based on skeletonfb by James Simmons and Geert Uytterhoeven,
13 * usb-skeleton by GregKH.
14 *
15 * Device-specific portions based on information from Displaylink, with work
16 * from Florian Echtler, Henrik Bjerregaard Pedersen, and others.
17 */
18
19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
21#include <linux/module.h>
22#include <linux/kernel.h>
23#include <linux/init.h>
24#include <linux/usb.h>
25#include <linux/uaccess.h>
26#include <linux/mm.h>
27#include <linux/fb.h>
28#include <linux/vmalloc.h>
29#include <linux/slab.h>
30#include <linux/prefetch.h>
31#include <linux/delay.h>
32#include <linux/prefetch.h>
33#include <video/udlfb.h>
34#include "edid.h"
35
36static struct fb_fix_screeninfo dlfb_fix = {
37 .id = "udlfb",
38 .type = FB_TYPE_PACKED_PIXELS,
39 .visual = FB_VISUAL_TRUECOLOR,
40 .xpanstep = 0,
41 .ypanstep = 0,
42 .ywrapstep = 0,
43 .accel = FB_ACCEL_NONE,
44};
45
46static const u32 udlfb_info_flags = FBINFO_DEFAULT | FBINFO_READS_FAST |
47 FBINFO_VIRTFB |
48 FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT |
49 FBINFO_HWACCEL_COPYAREA | FBINFO_MISC_ALWAYS_SETPAR;
50
51/*
52 * There are many DisplayLink-based products, all with unique PIDs. We are able
53 * to support all volume ones (circa 2009) with a single driver, so we match
54 * globally on VID. TODO: Probe() needs to detect when we might be running
55 * "future" chips, and bail on those, so a compatible driver can match.
56 */
57static struct usb_device_id id_table[] = {
58 {.idVendor = 0x17e9, .match_flags = USB_DEVICE_ID_MATCH_VENDOR,},
59 {},
60};
61MODULE_DEVICE_TABLE(usb, id_table);
62
63/* module options */
64static int console; /* Optionally allow fbcon to consume first framebuffer */
65static int fb_defio; /* Optionally enable experimental fb_defio mmap support */
66
67/* dlfb keeps a list of urbs for efficient bulk transfers */
68static void dlfb_urb_completion(struct urb *urb);
69static struct urb *dlfb_get_urb(struct dlfb_data *dev);
70static int dlfb_submit_urb(struct dlfb_data *dev, struct urb * urb, size_t len);
71static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size);
72static void dlfb_free_urb_list(struct dlfb_data *dev);
73
74/*
75 * All DisplayLink bulk operations start with 0xAF, followed by specific code
76 * All operations are written to buffers which then later get sent to device
77 */
78static char *dlfb_set_register(char *buf, u8 reg, u8 val)
79{
80 *buf++ = 0xAF;
81 *buf++ = 0x20;
82 *buf++ = reg;
83 *buf++ = val;
84 return buf;
85}
86
87static char *dlfb_vidreg_lock(char *buf)
88{
89 return dlfb_set_register(buf, 0xFF, 0x00);
90}
91
92static char *dlfb_vidreg_unlock(char *buf)
93{
94 return dlfb_set_register(buf, 0xFF, 0xFF);
95}
96
97/*
98 * On/Off for driving the DisplayLink framebuffer to the display
99 * 0x00 H and V sync on
100 * 0x01 H and V sync off (screen blank but powered)
101 * 0x07 DPMS powerdown (requires modeset to come back)
102 */
103static char *dlfb_enable_hvsync(char *buf, bool enable)
104{
105 if (enable)
106 return dlfb_set_register(buf, 0x1F, 0x00);
107 else
108 return dlfb_set_register(buf, 0x1F, 0x07);
109}
110
111static char *dlfb_set_color_depth(char *buf, u8 selection)
112{
113 return dlfb_set_register(buf, 0x00, selection);
114}
115
116static char *dlfb_set_base16bpp(char *wrptr, u32 base)
117{
118 /* the base pointer is 16 bits wide, 0x20 is hi byte. */
119 wrptr = dlfb_set_register(wrptr, 0x20, base >> 16);
120 wrptr = dlfb_set_register(wrptr, 0x21, base >> 8);
121 return dlfb_set_register(wrptr, 0x22, base);
122}
123
124/*
125 * DisplayLink HW has separate 16bpp and 8bpp framebuffers.
126 * In 24bpp modes, the low 323 RGB bits go in the 8bpp framebuffer
127 */
128static char *dlfb_set_base8bpp(char *wrptr, u32 base)
129{
130 wrptr = dlfb_set_register(wrptr, 0x26, base >> 16);
131 wrptr = dlfb_set_register(wrptr, 0x27, base >> 8);
132 return dlfb_set_register(wrptr, 0x28, base);
133}
134
135static char *dlfb_set_register_16(char *wrptr, u8 reg, u16 value)
136{
137 wrptr = dlfb_set_register(wrptr, reg, value >> 8);
138 return dlfb_set_register(wrptr, reg+1, value);
139}
140
141/*
142 * This is kind of weird because the controller takes some
143 * register values in a different byte order than other registers.
144 */
145static char *dlfb_set_register_16be(char *wrptr, u8 reg, u16 value)
146{
147 wrptr = dlfb_set_register(wrptr, reg, value);
148 return dlfb_set_register(wrptr, reg+1, value >> 8);
149}
150
151/*
152 * LFSR is linear feedback shift register. The reason we have this is
153 * because the display controller needs to minimize the clock depth of
154 * various counters used in the display path. So this code reverses the
155 * provided value into the lfsr16 value by counting backwards to get
156 * the value that needs to be set in the hardware comparator to get the
157 * same actual count. This makes sense once you read above a couple of
158 * times and think about it from a hardware perspective.
159 */
160static u16 dlfb_lfsr16(u16 actual_count)
161{
162 u32 lv = 0xFFFF; /* This is the lfsr value that the hw starts with */
163
164 while (actual_count--) {
165 lv = ((lv << 1) |
166 (((lv >> 15) ^ (lv >> 4) ^ (lv >> 2) ^ (lv >> 1)) & 1))
167 & 0xFFFF;
168 }
169
170 return (u16) lv;
171}
172
173/*
174 * This does LFSR conversion on the value that is to be written.
175 * See LFSR explanation above for more detail.
176 */
177static char *dlfb_set_register_lfsr16(char *wrptr, u8 reg, u16 value)
178{
179 return dlfb_set_register_16(wrptr, reg, dlfb_lfsr16(value));
180}
181
182/*
183 * This takes a standard fbdev screeninfo struct and all of its monitor mode
184 * details and converts them into the DisplayLink equivalent register commands.
185 */
186static char *dlfb_set_vid_cmds(char *wrptr, struct fb_var_screeninfo *var)
187{
188 u16 xds, yds;
189 u16 xde, yde;
190 u16 yec;
191
192 /* x display start */
193 xds = var->left_margin + var->hsync_len;
194 wrptr = dlfb_set_register_lfsr16(wrptr, 0x01, xds);
195 /* x display end */
196 xde = xds + var->xres;
197 wrptr = dlfb_set_register_lfsr16(wrptr, 0x03, xde);
198
199 /* y display start */
200 yds = var->upper_margin + var->vsync_len;
201 wrptr = dlfb_set_register_lfsr16(wrptr, 0x05, yds);
202 /* y display end */
203 yde = yds + var->yres;
204 wrptr = dlfb_set_register_lfsr16(wrptr, 0x07, yde);
205
206 /* x end count is active + blanking - 1 */
207 wrptr = dlfb_set_register_lfsr16(wrptr, 0x09,
208 xde + var->right_margin - 1);
209
210 /* libdlo hardcodes hsync start to 1 */
211 wrptr = dlfb_set_register_lfsr16(wrptr, 0x0B, 1);
212
213 /* hsync end is width of sync pulse + 1 */
214 wrptr = dlfb_set_register_lfsr16(wrptr, 0x0D, var->hsync_len + 1);
215
216 /* hpixels is active pixels */
217 wrptr = dlfb_set_register_16(wrptr, 0x0F, var->xres);
218
219 /* yendcount is vertical active + vertical blanking */
220 yec = var->yres + var->upper_margin + var->lower_margin +
221 var->vsync_len;
222 wrptr = dlfb_set_register_lfsr16(wrptr, 0x11, yec);
223
224 /* libdlo hardcodes vsync start to 0 */
225 wrptr = dlfb_set_register_lfsr16(wrptr, 0x13, 0);
226
227 /* vsync end is width of vsync pulse */
228 wrptr = dlfb_set_register_lfsr16(wrptr, 0x15, var->vsync_len);
229
230 /* vpixels is active pixels */
231 wrptr = dlfb_set_register_16(wrptr, 0x17, var->yres);
232
233 /* convert picoseconds to 5kHz multiple for pclk5k = x * 1E12/5k */
234 wrptr = dlfb_set_register_16be(wrptr, 0x1B,
235 200*1000*1000/var->pixclock);
236
237 return wrptr;
238}
239
240/*
241 * This takes a standard fbdev screeninfo struct that was fetched or prepared
242 * and then generates the appropriate command sequence that then drives the
243 * display controller.
244 */
245static int dlfb_set_video_mode(struct dlfb_data *dev,
246 struct fb_var_screeninfo *var)
247{
248 char *buf;
249 char *wrptr;
250 int retval = 0;
251 int writesize;
252 struct urb *urb;
253
254 if (!atomic_read(&dev->usb_active))
255 return -EPERM;
256
257 urb = dlfb_get_urb(dev);
258 if (!urb)
259 return -ENOMEM;
260
261 buf = (char *) urb->transfer_buffer;
262
263 /*
264 * This first section has to do with setting the base address on the
265 * controller * associated with the display. There are 2 base
266 * pointers, currently, we only * use the 16 bpp segment.
267 */
268 wrptr = dlfb_vidreg_lock(buf);
269 wrptr = dlfb_set_color_depth(wrptr, 0x00);
270 /* set base for 16bpp segment to 0 */
271 wrptr = dlfb_set_base16bpp(wrptr, 0);
272 /* set base for 8bpp segment to end of fb */
273 wrptr = dlfb_set_base8bpp(wrptr, dev->info->fix.smem_len);
274
275 wrptr = dlfb_set_vid_cmds(wrptr, var);
276 wrptr = dlfb_enable_hvsync(wrptr, true);
277 wrptr = dlfb_vidreg_unlock(wrptr);
278
279 writesize = wrptr - buf;
280
281 retval = dlfb_submit_urb(dev, urb, writesize);
282
283 return retval;
284}
285
286static int dlfb_ops_mmap(struct fb_info *info, struct vm_area_struct *vma)
287{
288 unsigned long start = vma->vm_start;
289 unsigned long size = vma->vm_end - vma->vm_start;
290 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
291 unsigned long page, pos;
292
293 if (offset + size > info->fix.smem_len)
294 return -EINVAL;
295
296 pos = (unsigned long)info->fix.smem_start + offset;
297
298 pr_notice("mmap() framebuffer addr:%lu size:%lu\n",
299 pos, size);
300
301 while (size > 0) {
302 page = vmalloc_to_pfn((void *)pos);
303 if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
304 return -EAGAIN;
305
306 start += PAGE_SIZE;
307 pos += PAGE_SIZE;
308 if (size > PAGE_SIZE)
309 size -= PAGE_SIZE;
310 else
311 size = 0;
312 }
313
314 vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */
315 return 0;
316}
317
318/*
319 * Trims identical data from front and back of line
320 * Sets new front buffer address and width
321 * And returns byte count of identical pixels
322 * Assumes CPU natural alignment (unsigned long)
323 * for back and front buffer ptrs and width
324 */
325static int dlfb_trim_hline(const u8 *bback, const u8 **bfront, int *width_bytes)
326{
327 int j, k;
328 const unsigned long *back = (const unsigned long *) bback;
329 const unsigned long *front = (const unsigned long *) *bfront;
330 const int width = *width_bytes / sizeof(unsigned long);
331 int identical = width;
332 int start = width;
333 int end = width;
334
335 prefetch((void *) front);
336 prefetch((void *) back);
337
338 for (j = 0; j < width; j++) {
339 if (back[j] != front[j]) {
340 start = j;
341 break;
342 }
343 }
344
345 for (k = width - 1; k > j; k--) {
346 if (back[k] != front[k]) {
347 end = k+1;
348 break;
349 }
350 }
351
352 identical = start + (width - end);
353 *bfront = (u8 *) &front[start];
354 *width_bytes = (end - start) * sizeof(unsigned long);
355
356 return identical * sizeof(unsigned long);
357}
358
359/*
360 * Render a command stream for an encoded horizontal line segment of pixels.
361 *
362 * A command buffer holds several commands.
363 * It always begins with a fresh command header
364 * (the protocol doesn't require this, but we enforce it to allow
365 * multiple buffers to be potentially encoded and sent in parallel).
366 * A single command encodes one contiguous horizontal line of pixels
367 *
368 * The function relies on the client to do all allocation, so that
369 * rendering can be done directly to output buffers (e.g. USB URBs).
370 * The function fills the supplied command buffer, providing information
371 * on where it left off, so the client may call in again with additional
372 * buffers if the line will take several buffers to complete.
373 *
374 * A single command can transmit a maximum of 256 pixels,
375 * regardless of the compression ratio (protocol design limit).
376 * To the hardware, 0 for a size byte means 256
377 *
378 * Rather than 256 pixel commands which are either rl or raw encoded,
379 * the rlx command simply assumes alternating raw and rl spans within one cmd.
380 * This has a slightly larger header overhead, but produces more even results.
381 * It also processes all data (read and write) in a single pass.
382 * Performance benchmarks of common cases show it having just slightly better
383 * compression than 256 pixel raw or rle commands, with similar CPU consumpion.
384 * But for very rl friendly data, will compress not quite as well.
385 */
386static void dlfb_compress_hline(
387 const uint16_t **pixel_start_ptr,
388 const uint16_t *const pixel_end,
389 uint32_t *device_address_ptr,
390 uint8_t **command_buffer_ptr,
391 const uint8_t *const cmd_buffer_end)
392{
393 const uint16_t *pixel = *pixel_start_ptr;
394 uint32_t dev_addr = *device_address_ptr;
395 uint8_t *cmd = *command_buffer_ptr;
396 const int bpp = 2;
397
398 while ((pixel_end > pixel) &&
399 (cmd_buffer_end - MIN_RLX_CMD_BYTES > cmd)) {
400 uint8_t *raw_pixels_count_byte = 0;
401 uint8_t *cmd_pixels_count_byte = 0;
402 const uint16_t *raw_pixel_start = 0;
403 const uint16_t *cmd_pixel_start, *cmd_pixel_end = 0;
404
405 prefetchw((void *) cmd); /* pull in one cache line at least */
406
407 *cmd++ = 0xAF;
408 *cmd++ = 0x6B;
409 *cmd++ = (uint8_t) ((dev_addr >> 16) & 0xFF);
410 *cmd++ = (uint8_t) ((dev_addr >> 8) & 0xFF);
411 *cmd++ = (uint8_t) ((dev_addr) & 0xFF);
412
413 cmd_pixels_count_byte = cmd++; /* we'll know this later */
414 cmd_pixel_start = pixel;
415
416 raw_pixels_count_byte = cmd++; /* we'll know this later */
417 raw_pixel_start = pixel;
418
419 cmd_pixel_end = pixel + min(MAX_CMD_PIXELS + 1,
420 min((int)(pixel_end - pixel),
421 (int)(cmd_buffer_end - cmd) / bpp));
422
423 prefetch_range((void *) pixel, (cmd_pixel_end - pixel) * bpp);
424
425 while (pixel < cmd_pixel_end) {
426 const uint16_t * const repeating_pixel = pixel;
427
428 *(uint16_t *)cmd = cpu_to_be16p(pixel);
429 cmd += 2;
430 pixel++;
431
432 if (unlikely((pixel < cmd_pixel_end) &&
433 (*pixel == *repeating_pixel))) {
434 /* go back and fill in raw pixel count */
435 *raw_pixels_count_byte = ((repeating_pixel -
436 raw_pixel_start) + 1) & 0xFF;
437
438 while ((pixel < cmd_pixel_end)
439 && (*pixel == *repeating_pixel)) {
440 pixel++;
441 }
442
443 /* immediately after raw data is repeat byte */
444 *cmd++ = ((pixel - repeating_pixel) - 1) & 0xFF;
445
446 /* Then start another raw pixel span */
447 raw_pixel_start = pixel;
448 raw_pixels_count_byte = cmd++;
449 }
450 }
451
452 if (pixel > raw_pixel_start) {
453 /* finalize last RAW span */
454 *raw_pixels_count_byte = (pixel-raw_pixel_start) & 0xFF;
455 }
456
457 *cmd_pixels_count_byte = (pixel - cmd_pixel_start) & 0xFF;
458 dev_addr += (pixel - cmd_pixel_start) * bpp;
459 }
460
461 if (cmd_buffer_end <= MIN_RLX_CMD_BYTES + cmd) {
462 /* Fill leftover bytes with no-ops */
463 if (cmd_buffer_end > cmd)
464 memset(cmd, 0xAF, cmd_buffer_end - cmd);
465 cmd = (uint8_t *) cmd_buffer_end;
466 }
467
468 *command_buffer_ptr = cmd;
469 *pixel_start_ptr = pixel;
470 *device_address_ptr = dev_addr;
471
472 return;
473}
474
475/*
476 * There are 3 copies of every pixel: The front buffer that the fbdev
477 * client renders to, the actual framebuffer across the USB bus in hardware
478 * (that we can only write to, slowly, and can never read), and (optionally)
479 * our shadow copy that tracks what's been sent to that hardware buffer.
480 */
481static int dlfb_render_hline(struct dlfb_data *dev, struct urb **urb_ptr,
482 const char *front, char **urb_buf_ptr,
483 u32 byte_offset, u32 byte_width,
484 int *ident_ptr, int *sent_ptr)
485{
486 const u8 *line_start, *line_end, *next_pixel;
487 u32 dev_addr = dev->base16 + byte_offset;
488 struct urb *urb = *urb_ptr;
489 u8 *cmd = *urb_buf_ptr;
490 u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length;
491
492 line_start = (u8 *) (front + byte_offset);
493 next_pixel = line_start;
494 line_end = next_pixel + byte_width;
495
496 if (dev->backing_buffer) {
497 int offset;
498 const u8 *back_start = (u8 *) (dev->backing_buffer
499 + byte_offset);
500
501 *ident_ptr += dlfb_trim_hline(back_start, &next_pixel,
502 &byte_width);
503
504 offset = next_pixel - line_start;
505 line_end = next_pixel + byte_width;
506 dev_addr += offset;
507 back_start += offset;
508 line_start += offset;
509
510 memcpy((char *)back_start, (char *) line_start,
511 byte_width);
512 }
513
514 while (next_pixel < line_end) {
515
516 dlfb_compress_hline((const uint16_t **) &next_pixel,
517 (const uint16_t *) line_end, &dev_addr,
518 (u8 **) &cmd, (u8 *) cmd_end);
519
520 if (cmd >= cmd_end) {
521 int len = cmd - (u8 *) urb->transfer_buffer;
522 if (dlfb_submit_urb(dev, urb, len))
523 return 1; /* lost pixels is set */
524 *sent_ptr += len;
525 urb = dlfb_get_urb(dev);
526 if (!urb)
527 return 1; /* lost_pixels is set */
528 *urb_ptr = urb;
529 cmd = urb->transfer_buffer;
530 cmd_end = &cmd[urb->transfer_buffer_length];
531 }
532 }
533
534 *urb_buf_ptr = cmd;
535
536 return 0;
537}
538
539int dlfb_handle_damage(struct dlfb_data *dev, int x, int y,
540 int width, int height, char *data)
541{
542 int i, ret;
543 char *cmd;
544 cycles_t start_cycles, end_cycles;
545 int bytes_sent = 0;
546 int bytes_identical = 0;
547 struct urb *urb;
548 int aligned_x;
549
550 start_cycles = get_cycles();
551
552 aligned_x = DL_ALIGN_DOWN(x, sizeof(unsigned long));
553 width = DL_ALIGN_UP(width + (x-aligned_x), sizeof(unsigned long));
554 x = aligned_x;
555
556 if ((width <= 0) ||
557 (x + width > dev->info->var.xres) ||
558 (y + height > dev->info->var.yres))
559 return -EINVAL;
560
561 if (!atomic_read(&dev->usb_active))
562 return 0;
563
564 urb = dlfb_get_urb(dev);
565 if (!urb)
566 return 0;
567 cmd = urb->transfer_buffer;
568
569 for (i = y; i < y + height ; i++) {
570 const int line_offset = dev->info->fix.line_length * i;
571 const int byte_offset = line_offset + (x * BPP);
572
573 if (dlfb_render_hline(dev, &urb,
574 (char *) dev->info->fix.smem_start,
575 &cmd, byte_offset, width * BPP,
576 &bytes_identical, &bytes_sent))
577 goto error;
578 }
579
580 if (cmd > (char *) urb->transfer_buffer) {
581 /* Send partial buffer remaining before exiting */
582 int len = cmd - (char *) urb->transfer_buffer;
583 ret = dlfb_submit_urb(dev, urb, len);
584 bytes_sent += len;
585 } else
586 dlfb_urb_completion(urb);
587
588error:
589 atomic_add(bytes_sent, &dev->bytes_sent);
590 atomic_add(bytes_identical, &dev->bytes_identical);
591 atomic_add(width*height*2, &dev->bytes_rendered);
592 end_cycles = get_cycles();
593 atomic_add(((unsigned int) ((end_cycles - start_cycles)
594 >> 10)), /* Kcycles */
595 &dev->cpu_kcycles_used);
596
597 return 0;
598}
599
600/*
601 * Path triggered by usermode clients who write to filesystem
602 * e.g. cat filename > /dev/fb1
603 * Not used by X Windows or text-mode console. But useful for testing.
604 * Slow because of extra copy and we must assume all pixels dirty.
605 */
606static ssize_t dlfb_ops_write(struct fb_info *info, const char __user *buf,
607 size_t count, loff_t *ppos)
608{
609 ssize_t result;
610 struct dlfb_data *dev = info->par;
611 u32 offset = (u32) *ppos;
612
613 result = fb_sys_write(info, buf, count, ppos);
614
615 if (result > 0) {
616 int start = max((int)(offset / info->fix.line_length) - 1, 0);
617 int lines = min((u32)((result / info->fix.line_length) + 1),
618 (u32)info->var.yres);
619
620 dlfb_handle_damage(dev, 0, start, info->var.xres,
621 lines, info->screen_base);
622 }
623
624 return result;
625}
626
627/* hardware has native COPY command (see libdlo), but not worth it for fbcon */
628static void dlfb_ops_copyarea(struct fb_info *info,
629 const struct fb_copyarea *area)
630{
631
632 struct dlfb_data *dev = info->par;
633
634 sys_copyarea(info, area);
635
636 dlfb_handle_damage(dev, area->dx, area->dy,
637 area->width, area->height, info->screen_base);
638}
639
640static void dlfb_ops_imageblit(struct fb_info *info,
641 const struct fb_image *image)
642{
643 struct dlfb_data *dev = info->par;
644
645 sys_imageblit(info, image);
646
647 dlfb_handle_damage(dev, image->dx, image->dy,
648 image->width, image->height, info->screen_base);
649}
650
651static void dlfb_ops_fillrect(struct fb_info *info,
652 const struct fb_fillrect *rect)
653{
654 struct dlfb_data *dev = info->par;
655
656 sys_fillrect(info, rect);
657
658 dlfb_handle_damage(dev, rect->dx, rect->dy, rect->width,
659 rect->height, info->screen_base);
660}
661
662/*
663 * NOTE: fb_defio.c is holding info->fbdefio.mutex
664 * Touching ANY framebuffer memory that triggers a page fault
665 * in fb_defio will cause a deadlock, when it also tries to
666 * grab the same mutex.
667 */
668static void dlfb_dpy_deferred_io(struct fb_info *info,
669 struct list_head *pagelist)
670{
671 struct page *cur;
672 struct fb_deferred_io *fbdefio = info->fbdefio;
673 struct dlfb_data *dev = info->par;
674 struct urb *urb;
675 char *cmd;
676 cycles_t start_cycles, end_cycles;
677 int bytes_sent = 0;
678 int bytes_identical = 0;
679 int bytes_rendered = 0;
680
681 if (!fb_defio)
682 return;
683
684 if (!atomic_read(&dev->usb_active))
685 return;
686
687 start_cycles = get_cycles();
688
689 urb = dlfb_get_urb(dev);
690 if (!urb)
691 return;
692
693 cmd = urb->transfer_buffer;
694
695 /* walk the written page list and render each to device */
696 list_for_each_entry(cur, &fbdefio->pagelist, lru) {
697
698 if (dlfb_render_hline(dev, &urb, (char *) info->fix.smem_start,
699 &cmd, cur->index << PAGE_SHIFT,
700 PAGE_SIZE, &bytes_identical, &bytes_sent))
701 goto error;
702 bytes_rendered += PAGE_SIZE;
703 }
704
705 if (cmd > (char *) urb->transfer_buffer) {
706 /* Send partial buffer remaining before exiting */
707 int len = cmd - (char *) urb->transfer_buffer;
708 dlfb_submit_urb(dev, urb, len);
709 bytes_sent += len;
710 } else
711 dlfb_urb_completion(urb);
712
713error:
714 atomic_add(bytes_sent, &dev->bytes_sent);
715 atomic_add(bytes_identical, &dev->bytes_identical);
716 atomic_add(bytes_rendered, &dev->bytes_rendered);
717 end_cycles = get_cycles();
718 atomic_add(((unsigned int) ((end_cycles - start_cycles)
719 >> 10)), /* Kcycles */
720 &dev->cpu_kcycles_used);
721}
722
723static int dlfb_get_edid(struct dlfb_data *dev, char *edid, int len)
724{
725 int i;
726 int ret;
727 char *rbuf;
728
729 rbuf = kmalloc(2, GFP_KERNEL);
730 if (!rbuf)
731 return 0;
732
733 for (i = 0; i < len; i++) {
734 ret = usb_control_msg(dev->udev,
735 usb_rcvctrlpipe(dev->udev, 0), (0x02),
736 (0x80 | (0x02 << 5)), i << 8, 0xA1, rbuf, 2,
737 HZ);
738 if (ret < 1) {
739 pr_err("Read EDID byte %d failed err %x\n", i, ret);
740 i--;
741 break;
742 }
743 edid[i] = rbuf[1];
744 }
745
746 kfree(rbuf);
747
748 return i;
749}
750
751static int dlfb_ops_ioctl(struct fb_info *info, unsigned int cmd,
752 unsigned long arg)
753{
754
755 struct dlfb_data *dev = info->par;
756 struct dloarea *area = NULL;
757
758 if (!atomic_read(&dev->usb_active))
759 return 0;
760
761 /* TODO: Update X server to get this from sysfs instead */
762 if (cmd == DLFB_IOCTL_RETURN_EDID) {
763 char *edid = (char *)arg;
764 if (copy_to_user(edid, dev->edid, dev->edid_size))
765 return -EFAULT;
766 return 0;
767 }
768
769 /* TODO: Help propose a standard fb.h ioctl to report mmap damage */
770 if (cmd == DLFB_IOCTL_REPORT_DAMAGE) {
771
772 /*
773 * If we have a damage-aware client, turn fb_defio "off"
774 * To avoid perf imact of unnecessary page fault handling.
775 * Done by resetting the delay for this fb_info to a very
776 * long period. Pages will become writable and stay that way.
777 * Reset to normal value when all clients have closed this fb.
778 */
779 if (info->fbdefio)
780 info->fbdefio->delay = DL_DEFIO_WRITE_DISABLE;
781
782 area = (struct dloarea *)arg;
783
784 if (area->x < 0)
785 area->x = 0;
786
787 if (area->x > info->var.xres)
788 area->x = info->var.xres;
789
790 if (area->y < 0)
791 area->y = 0;
792
793 if (area->y > info->var.yres)
794 area->y = info->var.yres;
795
796 dlfb_handle_damage(dev, area->x, area->y, area->w, area->h,
797 info->screen_base);
798 }
799
800 return 0;
801}
802
803/* taken from vesafb */
804static int
805dlfb_ops_setcolreg(unsigned regno, unsigned red, unsigned green,
806 unsigned blue, unsigned transp, struct fb_info *info)
807{
808 int err = 0;
809
810 if (regno >= info->cmap.len)
811 return 1;
812
813 if (regno < 16) {
814 if (info->var.red.offset == 10) {
815 /* 1:5:5:5 */
816 ((u32 *) (info->pseudo_palette))[regno] =
817 ((red & 0xf800) >> 1) |
818 ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
819 } else {
820 /* 0:5:6:5 */
821 ((u32 *) (info->pseudo_palette))[regno] =
822 ((red & 0xf800)) |
823 ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
824 }
825 }
826
827 return err;
828}
829
830/*
831 * It's common for several clients to have framebuffer open simultaneously.
832 * e.g. both fbcon and X. Makes things interesting.
833 * Assumes caller is holding info->lock (for open and release at least)
834 */
835static int dlfb_ops_open(struct fb_info *info, int user)
836{
837 struct dlfb_data *dev = info->par;
838
839 /*
840 * fbcon aggressively connects to first framebuffer it finds,
841 * preventing other clients (X) from working properly. Usually
842 * not what the user wants. Fail by default with option to enable.
843 */
844 if ((user == 0) & (!console))
845 return -EBUSY;
846
847 /* If the USB device is gone, we don't accept new opens */
848 if (dev->virtualized)
849 return -ENODEV;
850
851 dev->fb_count++;
852
853 kref_get(&dev->kref);
854
855 if (fb_defio && (info->fbdefio == NULL)) {
856 /* enable defio at last moment if not disabled by client */
857
858 struct fb_deferred_io *fbdefio;
859
860 fbdefio = kmalloc(sizeof(struct fb_deferred_io), GFP_KERNEL);
861
862 if (fbdefio) {
863 fbdefio->delay = DL_DEFIO_WRITE_DELAY;
864 fbdefio->deferred_io = dlfb_dpy_deferred_io;
865 }
866
867 info->fbdefio = fbdefio;
868 fb_deferred_io_init(info);
869 }
870
871 pr_notice("open /dev/fb%d user=%d fb_info=%p count=%d\n",
872 info->node, user, info, dev->fb_count);
873
874 return 0;
875}
876
877/*
878 * Called when all client interfaces to start transactions have been disabled,
879 * and all references to our device instance (dlfb_data) are released.
880 * Every transaction must have a reference, so we know are fully spun down
881 */
882static void dlfb_free(struct kref *kref)
883{
884 struct dlfb_data *dev = container_of(kref, struct dlfb_data, kref);
885
886 /* this function will wait for all in-flight urbs to complete */
887 if (dev->urbs.count > 0)
888 dlfb_free_urb_list(dev);
889
890 if (dev->backing_buffer)
891 vfree(dev->backing_buffer);
892
893 kfree(dev->edid);
894
895 pr_warn("freeing dlfb_data %p\n", dev);
896
897 kfree(dev);
898}
899
900static void dlfb_release_urb_work(struct work_struct *work)
901{
902 struct urb_node *unode = container_of(work, struct urb_node,
903 release_urb_work.work);
904
905 up(&unode->dev->urbs.limit_sem);
906}
907
908static void dlfb_free_framebuffer_work(struct work_struct *work)
909{
910 struct dlfb_data *dev = container_of(work, struct dlfb_data,
911 free_framebuffer_work.work);
912 struct fb_info *info = dev->info;
913 int node = info->node;
914
915 unregister_framebuffer(info);
916
917 if (info->cmap.len != 0)
918 fb_dealloc_cmap(&info->cmap);
919 if (info->monspecs.modedb)
920 fb_destroy_modedb(info->monspecs.modedb);
921 if (info->screen_base)
922 vfree(info->screen_base);
923
924 fb_destroy_modelist(&info->modelist);
925
926 dev->info = 0;
927
928 /* Assume info structure is freed after this point */
929 framebuffer_release(info);
930
931 pr_warn("fb_info for /dev/fb%d has been freed\n", node);
932
933 /* ref taken in probe() as part of registering framebfufer */
934 kref_put(&dev->kref, dlfb_free);
935}
936
937/*
938 * Assumes caller is holding info->lock mutex (for open and release at least)
939 */
940static int dlfb_ops_release(struct fb_info *info, int user)
941{
942 struct dlfb_data *dev = info->par;
943
944 dev->fb_count--;
945
946 /* We can't free fb_info here - fbmem will touch it when we return */
947 if (dev->virtualized && (dev->fb_count == 0))
948 schedule_delayed_work(&dev->free_framebuffer_work, HZ);
949
950 if ((dev->fb_count == 0) && (info->fbdefio)) {
951 fb_deferred_io_cleanup(info);
952 kfree(info->fbdefio);
953 info->fbdefio = NULL;
954 info->fbops->fb_mmap = dlfb_ops_mmap;
955 }
956
957 pr_warn("released /dev/fb%d user=%d count=%d\n",
958 info->node, user, dev->fb_count);
959
960 kref_put(&dev->kref, dlfb_free);
961
962 return 0;
963}
964
965/*
966 * Check whether a video mode is supported by the DisplayLink chip
967 * We start from monitor's modes, so don't need to filter that here
968 */
969static int dlfb_is_valid_mode(struct fb_videomode *mode,
970 struct fb_info *info)
971{
972 struct dlfb_data *dev = info->par;
973
974 if (mode->xres * mode->yres > dev->sku_pixel_limit) {
975 pr_warn("%dx%d beyond chip capabilities\n",
976 mode->xres, mode->yres);
977 return 0;
978 }
979
980 pr_info("%dx%d valid mode\n", mode->xres, mode->yres);
981
982 return 1;
983}
984
985static void dlfb_var_color_format(struct fb_var_screeninfo *var)
986{
987 const struct fb_bitfield red = { 11, 5, 0 };
988 const struct fb_bitfield green = { 5, 6, 0 };
989 const struct fb_bitfield blue = { 0, 5, 0 };
990
991 var->bits_per_pixel = 16;
992 var->red = red;
993 var->green = green;
994 var->blue = blue;
995}
996
997static int dlfb_ops_check_var(struct fb_var_screeninfo *var,
998 struct fb_info *info)
999{
1000 struct fb_videomode mode;
1001
1002 /* TODO: support dynamically changing framebuffer size */
1003 if ((var->xres * var->yres * 2) > info->fix.smem_len)
1004 return -EINVAL;
1005
1006 /* set device-specific elements of var unrelated to mode */
1007 dlfb_var_color_format(var);
1008
1009 fb_var_to_videomode(&mode, var);
1010
1011 if (!dlfb_is_valid_mode(&mode, info))
1012 return -EINVAL;
1013
1014 return 0;
1015}
1016
1017static int dlfb_ops_set_par(struct fb_info *info)
1018{
1019 struct dlfb_data *dev = info->par;
1020 int result;
1021 u16 *pix_framebuffer;
1022 int i;
1023
1024 pr_notice("set_par mode %dx%d\n", info->var.xres, info->var.yres);
1025
1026 result = dlfb_set_video_mode(dev, &info->var);
1027
1028 if ((result == 0) && (dev->fb_count == 0)) {
1029
1030 /* paint greenscreen */
1031
1032 pix_framebuffer = (u16 *) info->screen_base;
1033 for (i = 0; i < info->fix.smem_len / 2; i++)
1034 pix_framebuffer[i] = 0x37e6;
1035
1036 dlfb_handle_damage(dev, 0, 0, info->var.xres, info->var.yres,
1037 info->screen_base);
1038 }
1039
1040 return result;
1041}
1042
1043/*
1044 * In order to come back from full DPMS off, we need to set the mode again
1045 */
1046static int dlfb_ops_blank(int blank_mode, struct fb_info *info)
1047{
1048 struct dlfb_data *dev = info->par;
1049
1050 if (blank_mode != FB_BLANK_UNBLANK) {
1051 char *bufptr;
1052 struct urb *urb;
1053
1054 urb = dlfb_get_urb(dev);
1055 if (!urb)
1056 return 0;
1057
1058 bufptr = (char *) urb->transfer_buffer;
1059 bufptr = dlfb_vidreg_lock(bufptr);
1060 bufptr = dlfb_enable_hvsync(bufptr, false);
1061 bufptr = dlfb_vidreg_unlock(bufptr);
1062
1063 dlfb_submit_urb(dev, urb, bufptr -
1064 (char *) urb->transfer_buffer);
1065 } else {
1066 dlfb_set_video_mode(dev, &info->var);
1067 }
1068
1069 return 0;
1070}
1071
1072static struct fb_ops dlfb_ops = {
1073 .owner = THIS_MODULE,
1074 .fb_read = fb_sys_read,
1075 .fb_write = dlfb_ops_write,
1076 .fb_setcolreg = dlfb_ops_setcolreg,
1077 .fb_fillrect = dlfb_ops_fillrect,
1078 .fb_copyarea = dlfb_ops_copyarea,
1079 .fb_imageblit = dlfb_ops_imageblit,
1080 .fb_mmap = dlfb_ops_mmap,
1081 .fb_ioctl = dlfb_ops_ioctl,
1082 .fb_open = dlfb_ops_open,
1083 .fb_release = dlfb_ops_release,
1084 .fb_blank = dlfb_ops_blank,
1085 .fb_check_var = dlfb_ops_check_var,
1086 .fb_set_par = dlfb_ops_set_par,
1087};
1088
1089
1090/*
1091 * Assumes &info->lock held by caller
1092 * Assumes no active clients have framebuffer open
1093 */
1094static int dlfb_realloc_framebuffer(struct dlfb_data *dev, struct fb_info *info)
1095{
1096 int retval = -ENOMEM;
1097 int old_len = info->fix.smem_len;
1098 int new_len;
1099 unsigned char *old_fb = info->screen_base;
1100 unsigned char *new_fb;
1101 unsigned char *new_back;
1102
1103 pr_warn("Reallocating framebuffer. Addresses will change!\n");
1104
1105 new_len = info->fix.line_length * info->var.yres;
1106
1107 if (PAGE_ALIGN(new_len) > old_len) {
1108 /*
1109 * Alloc system memory for virtual framebuffer
1110 */
1111 new_fb = vmalloc(new_len);
1112 if (!new_fb) {
1113 pr_err("Virtual framebuffer alloc failed\n");
1114 goto error;
1115 }
1116
1117 if (info->screen_base) {
1118 memcpy(new_fb, old_fb, old_len);
1119 vfree(info->screen_base);
1120 }
1121
1122 info->screen_base = new_fb;
1123 info->fix.smem_len = PAGE_ALIGN(new_len);
1124 info->fix.smem_start = (unsigned long) new_fb;
1125 info->flags = udlfb_info_flags;
1126
1127 /*
1128 * Second framebuffer copy to mirror the framebuffer state
1129 * on the physical USB device. We can function without this.
1130 * But with imperfect damage info we may send pixels over USB
1131 * that were, in fact, unchanged - wasting limited USB bandwidth
1132 */
1133 new_back = vzalloc(new_len);
1134 if (!new_back)
1135 pr_info("No shadow/backing buffer allocated\n");
1136 else {
1137 if (dev->backing_buffer)
1138 vfree(dev->backing_buffer);
1139 dev->backing_buffer = new_back;
1140 }
1141 }
1142
1143 retval = 0;
1144
1145error:
1146 return retval;
1147}
1148
1149/*
1150 * 1) Get EDID from hw, or use sw default
1151 * 2) Parse into various fb_info structs
1152 * 3) Allocate virtual framebuffer memory to back highest res mode
1153 *
1154 * Parses EDID into three places used by various parts of fbdev:
1155 * fb_var_screeninfo contains the timing of the monitor's preferred mode
1156 * fb_info.monspecs is full parsed EDID info, including monspecs.modedb
1157 * fb_info.modelist is a linked list of all monitor & VESA modes which work
1158 *
1159 * If EDID is not readable/valid, then modelist is all VESA modes,
1160 * monspecs is NULL, and fb_var_screeninfo is set to safe VESA mode
1161 * Returns 0 if successful
1162 */
1163static int dlfb_setup_modes(struct dlfb_data *dev,
1164 struct fb_info *info,
1165 char *default_edid, size_t default_edid_size)
1166{
1167 int i;
1168 const struct fb_videomode *default_vmode = NULL;
1169 int result = 0;
1170 char *edid;
1171 int tries = 3;
1172
1173 if (info->dev) /* only use mutex if info has been registered */
1174 mutex_lock(&info->lock);
1175
1176 edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
1177 if (!edid) {
1178 result = -ENOMEM;
1179 goto error;
1180 }
1181
1182 fb_destroy_modelist(&info->modelist);
1183 memset(&info->monspecs, 0, sizeof(info->monspecs));
1184
1185 /*
1186 * Try to (re)read EDID from hardware first
1187 * EDID data may return, but not parse as valid
1188 * Try again a few times, in case of e.g. analog cable noise
1189 */
1190 while (tries--) {
1191
1192 i = dlfb_get_edid(dev, edid, EDID_LENGTH);
1193
1194 if (i >= EDID_LENGTH)
1195 fb_edid_to_monspecs(edid, &info->monspecs);
1196
1197 if (info->monspecs.modedb_len > 0) {
1198 dev->edid = edid;
1199 dev->edid_size = i;
1200 break;
1201 }
1202 }
1203
1204 /* If that fails, use a previously returned EDID if available */
1205 if (info->monspecs.modedb_len == 0) {
1206
1207 pr_err("Unable to get valid EDID from device/display\n");
1208
1209 if (dev->edid) {
1210 fb_edid_to_monspecs(dev->edid, &info->monspecs);
1211 if (info->monspecs.modedb_len > 0)
1212 pr_err("Using previously queried EDID\n");
1213 }
1214 }
1215
1216 /* If that fails, use the default EDID we were handed */
1217 if (info->monspecs.modedb_len == 0) {
1218 if (default_edid_size >= EDID_LENGTH) {
1219 fb_edid_to_monspecs(default_edid, &info->monspecs);
1220 if (info->monspecs.modedb_len > 0) {
1221 memcpy(edid, default_edid, default_edid_size);
1222 dev->edid = edid;
1223 dev->edid_size = default_edid_size;
1224 pr_err("Using default/backup EDID\n");
1225 }
1226 }
1227 }
1228
1229 /* If we've got modes, let's pick a best default mode */
1230 if (info->monspecs.modedb_len > 0) {
1231
1232 for (i = 0; i < info->monspecs.modedb_len; i++) {
1233 if (dlfb_is_valid_mode(&info->monspecs.modedb[i], info))
1234 fb_add_videomode(&info->monspecs.modedb[i],
1235 &info->modelist);
1236 else {
1237 if (i == 0)
1238 /* if we've removed top/best mode */
1239 info->monspecs.misc
1240 &= ~FB_MISC_1ST_DETAIL;
1241 }
1242 }
1243
1244 default_vmode = fb_find_best_display(&info->monspecs,
1245 &info->modelist);
1246 }
1247
1248 /* If everything else has failed, fall back to safe default mode */
1249 if (default_vmode == NULL) {
1250
1251 struct fb_videomode fb_vmode = {0};
1252
1253 /*
1254 * Add the standard VESA modes to our modelist
1255 * Since we don't have EDID, there may be modes that
1256 * overspec monitor and/or are incorrect aspect ratio, etc.
1257 * But at least the user has a chance to choose
1258 */
1259 for (i = 0; i < VESA_MODEDB_SIZE; i++) {
1260 if (dlfb_is_valid_mode((struct fb_videomode *)
1261 &vesa_modes[i], info))
1262 fb_add_videomode(&vesa_modes[i],
1263 &info->modelist);
1264 }
1265
1266 /*
1267 * default to resolution safe for projectors
1268 * (since they are most common case without EDID)
1269 */
1270 fb_vmode.xres = 800;
1271 fb_vmode.yres = 600;
1272 fb_vmode.refresh = 60;
1273 default_vmode = fb_find_nearest_mode(&fb_vmode,
1274 &info->modelist);
1275 }
1276
1277 /* If we have good mode and no active clients*/
1278 if ((default_vmode != NULL) && (dev->fb_count == 0)) {
1279
1280 fb_videomode_to_var(&info->var, default_vmode);
1281 dlfb_var_color_format(&info->var);
1282
1283 /*
1284 * with mode size info, we can now alloc our framebuffer.
1285 */
1286 memcpy(&info->fix, &dlfb_fix, sizeof(dlfb_fix));
1287 info->fix.line_length = info->var.xres *
1288 (info->var.bits_per_pixel / 8);
1289
1290 result = dlfb_realloc_framebuffer(dev, info);
1291
1292 } else
1293 result = -EINVAL;
1294
1295error:
1296 if (edid && (dev->edid != edid))
1297 kfree(edid);
1298
1299 if (info->dev)
1300 mutex_unlock(&info->lock);
1301
1302 return result;
1303}
1304
1305static ssize_t metrics_bytes_rendered_show(struct device *fbdev,
1306 struct device_attribute *a, char *buf) {
1307 struct fb_info *fb_info = dev_get_drvdata(fbdev);
1308 struct dlfb_data *dev = fb_info->par;
1309 return snprintf(buf, PAGE_SIZE, "%u\n",
1310 atomic_read(&dev->bytes_rendered));
1311}
1312
1313static ssize_t metrics_bytes_identical_show(struct device *fbdev,
1314 struct device_attribute *a, char *buf) {
1315 struct fb_info *fb_info = dev_get_drvdata(fbdev);
1316 struct dlfb_data *dev = fb_info->par;
1317 return snprintf(buf, PAGE_SIZE, "%u\n",
1318 atomic_read(&dev->bytes_identical));
1319}
1320
1321static ssize_t metrics_bytes_sent_show(struct device *fbdev,
1322 struct device_attribute *a, char *buf) {
1323 struct fb_info *fb_info = dev_get_drvdata(fbdev);
1324 struct dlfb_data *dev = fb_info->par;
1325 return snprintf(buf, PAGE_SIZE, "%u\n",
1326 atomic_read(&dev->bytes_sent));
1327}
1328
1329static ssize_t metrics_cpu_kcycles_used_show(struct device *fbdev,
1330 struct device_attribute *a, char *buf) {
1331 struct fb_info *fb_info = dev_get_drvdata(fbdev);
1332 struct dlfb_data *dev = fb_info->par;
1333 return snprintf(buf, PAGE_SIZE, "%u\n",
1334 atomic_read(&dev->cpu_kcycles_used));
1335}
1336
1337static ssize_t edid_show(
1338 struct file *filp,
1339 struct kobject *kobj, struct bin_attribute *a,
1340 char *buf, loff_t off, size_t count) {
1341 struct device *fbdev = container_of(kobj, struct device, kobj);
1342 struct fb_info *fb_info = dev_get_drvdata(fbdev);
1343 struct dlfb_data *dev = fb_info->par;
1344
1345 if (dev->edid == NULL)
1346 return 0;
1347
1348 if ((off >= dev->edid_size) || (count > dev->edid_size))
1349 return 0;
1350
1351 if (off + count > dev->edid_size)
1352 count = dev->edid_size - off;
1353
1354 pr_info("sysfs edid copy %p to %p, %d bytes\n",
1355 dev->edid, buf, (int) count);
1356
1357 memcpy(buf, dev->edid, count);
1358
1359 return count;
1360}
1361
1362static ssize_t edid_store(
1363 struct file *filp,
1364 struct kobject *kobj, struct bin_attribute *a,
1365 char *src, loff_t src_off, size_t src_size) {
1366 struct device *fbdev = container_of(kobj, struct device, kobj);
1367 struct fb_info *fb_info = dev_get_drvdata(fbdev);
1368 struct dlfb_data *dev = fb_info->par;
1369
1370 /* We only support write of entire EDID at once, no offset*/
1371 if ((src_size != EDID_LENGTH) || (src_off != 0))
1372 return 0;
1373
1374 dlfb_setup_modes(dev, fb_info, src, src_size);
1375
1376 if (dev->edid && (memcmp(src, dev->edid, src_size) == 0)) {
1377 pr_info("sysfs written EDID is new default\n");
1378 dlfb_ops_set_par(fb_info);
1379 return src_size;
1380 } else
1381 return 0;
1382}
1383
1384static ssize_t metrics_reset_store(struct device *fbdev,
1385 struct device_attribute *attr,
1386 const char *buf, size_t count)
1387{
1388 struct fb_info *fb_info = dev_get_drvdata(fbdev);
1389 struct dlfb_data *dev = fb_info->par;
1390
1391 atomic_set(&dev->bytes_rendered, 0);
1392 atomic_set(&dev->bytes_identical, 0);
1393 atomic_set(&dev->bytes_sent, 0);
1394 atomic_set(&dev->cpu_kcycles_used, 0);
1395
1396 return count;
1397}
1398
1399static struct bin_attribute edid_attr = {
1400 .attr.name = "edid",
1401 .attr.mode = 0666,
1402 .size = EDID_LENGTH,
1403 .read = edid_show,
1404 .write = edid_store
1405};
1406
1407static struct device_attribute fb_device_attrs[] = {
1408 __ATTR_RO(metrics_bytes_rendered),
1409 __ATTR_RO(metrics_bytes_identical),
1410 __ATTR_RO(metrics_bytes_sent),
1411 __ATTR_RO(metrics_cpu_kcycles_used),
1412 __ATTR(metrics_reset, S_IWUSR, NULL, metrics_reset_store),
1413};
1414
1415/*
1416 * This is necessary before we can communicate with the display controller.
1417 */
1418static int dlfb_select_std_channel(struct dlfb_data *dev)
1419{
1420 int ret;
1421 u8 set_def_chn[] = { 0x57, 0xCD, 0xDC, 0xA7,
1422 0x1C, 0x88, 0x5E, 0x15,
1423 0x60, 0xFE, 0xC6, 0x97,
1424 0x16, 0x3D, 0x47, 0xF2 };
1425
1426 ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
1427 NR_USB_REQUEST_CHANNEL,
1428 (USB_DIR_OUT | USB_TYPE_VENDOR), 0, 0,
1429 set_def_chn, sizeof(set_def_chn), USB_CTRL_SET_TIMEOUT);
1430 return ret;
1431}
1432
1433static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev,
1434 struct usb_device *usbdev)
1435{
1436 char *desc;
1437 char *buf;
1438 char *desc_end;
1439
1440 u8 total_len = 0;
1441
1442 buf = kzalloc(MAX_VENDOR_DESCRIPTOR_SIZE, GFP_KERNEL);
1443 if (!buf)
1444 return false;
1445 desc = buf;
1446
1447 total_len = usb_get_descriptor(usbdev, 0x5f, /* vendor specific */
1448 0, desc, MAX_VENDOR_DESCRIPTOR_SIZE);
1449 if (total_len > 5) {
1450 pr_info("vendor descriptor length:%x data:%02x %02x %02x %02x" \
1451 "%02x %02x %02x %02x %02x %02x %02x\n",
1452 total_len, desc[0],
1453 desc[1], desc[2], desc[3], desc[4], desc[5], desc[6],
1454 desc[7], desc[8], desc[9], desc[10]);
1455
1456 if ((desc[0] != total_len) || /* descriptor length */
1457 (desc[1] != 0x5f) || /* vendor descriptor type */
1458 (desc[2] != 0x01) || /* version (2 bytes) */
1459 (desc[3] != 0x00) ||
1460 (desc[4] != total_len - 2)) /* length after type */
1461 goto unrecognized;
1462
1463 desc_end = desc + total_len;
1464 desc += 5; /* the fixed header we've already parsed */
1465
1466 while (desc < desc_end) {
1467 u8 length;
1468 u16 key;
1469
1470 key = *((u16 *) desc);
1471 desc += sizeof(u16);
1472 length = *desc;
1473 desc++;
1474
1475 switch (key) {
1476 case 0x0200: { /* max_area */
1477 u32 max_area;
1478 max_area = le32_to_cpu(*((u32 *)desc));
1479 pr_warn("DL chip limited to %d pixel modes\n",
1480 max_area);
1481 dev->sku_pixel_limit = max_area;
1482 break;
1483 }
1484 default:
1485 break;
1486 }
1487 desc += length;
1488 }
1489 }
1490
1491 goto success;
1492
1493unrecognized:
1494 /* allow udlfb to load for now even if firmware unrecognized */
1495 pr_err("Unrecognized vendor firmware descriptor\n");
1496
1497success:
1498 kfree(buf);
1499 return true;
1500}
1501static int dlfb_usb_probe(struct usb_interface *interface,
1502 const struct usb_device_id *id)
1503{
1504 struct usb_device *usbdev;
1505 struct dlfb_data *dev = 0;
1506 struct fb_info *info = 0;
1507 int retval = -ENOMEM;
1508 int i;
1509
1510 /* usb initialization */
1511
1512 usbdev = interface_to_usbdev(interface);
1513
1514 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1515 if (dev == NULL) {
1516 err("dlfb_usb_probe: failed alloc of dev struct\n");
1517 goto error;
1518 }
1519
1520 /* we need to wait for both usb and fbdev to spin down on disconnect */
1521 kref_init(&dev->kref); /* matching kref_put in usb .disconnect fn */
1522 kref_get(&dev->kref); /* matching kref_put in free_framebuffer_work */
1523
1524 dev->udev = usbdev;
1525 dev->gdev = &usbdev->dev; /* our generic struct device * */
1526 usb_set_intfdata(interface, dev);
1527
1528 pr_info("%s %s - serial #%s\n",
1529 usbdev->manufacturer, usbdev->product, usbdev->serial);
1530 pr_info("vid_%04x&pid_%04x&rev_%04x driver's dlfb_data struct at %p\n",
1531 usbdev->descriptor.idVendor, usbdev->descriptor.idProduct,
1532 usbdev->descriptor.bcdDevice, dev);
1533 pr_info("console enable=%d\n", console);
1534 pr_info("fb_defio enable=%d\n", fb_defio);
1535
1536 dev->sku_pixel_limit = 2048 * 1152; /* default to maximum */
1537
1538 if (!dlfb_parse_vendor_descriptor(dev, usbdev)) {
1539 pr_err("firmware not recognized. Assume incompatible device\n");
1540 goto error;
1541 }
1542
1543 if (!dlfb_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) {
1544 retval = -ENOMEM;
1545 pr_err("dlfb_alloc_urb_list failed\n");
1546 goto error;
1547 }
1548
1549 /* We don't register a new USB class. Our client interface is fbdev */
1550
1551 /* allocates framebuffer driver structure, not framebuffer memory */
1552 info = framebuffer_alloc(0, &usbdev->dev);
1553 if (!info) {
1554 retval = -ENOMEM;
1555 pr_err("framebuffer_alloc failed\n");
1556 goto error;
1557 }
1558
1559 dev->info = info;
1560 info->par = dev;
1561 info->pseudo_palette = dev->pseudo_palette;
1562 info->fbops = &dlfb_ops;
1563
1564 retval = fb_alloc_cmap(&info->cmap, 256, 0);
1565 if (retval < 0) {
1566 pr_err("fb_alloc_cmap failed %x\n", retval);
1567 goto error;
1568 }
1569
1570 INIT_DELAYED_WORK(&dev->free_framebuffer_work,
1571 dlfb_free_framebuffer_work);
1572
1573 INIT_LIST_HEAD(&info->modelist);
1574
1575 retval = dlfb_setup_modes(dev, info, NULL, 0);
1576 if (retval != 0) {
1577 pr_err("unable to find common mode for display and adapter\n");
1578 goto error;
1579 }
1580
1581 /* ready to begin using device */
1582
1583 atomic_set(&dev->usb_active, 1);
1584 dlfb_select_std_channel(dev);
1585
1586 dlfb_ops_check_var(&info->var, info);
1587 dlfb_ops_set_par(info);
1588
1589 retval = register_framebuffer(info);
1590 if (retval < 0) {
1591 pr_err("register_framebuffer failed %d\n", retval);
1592 goto error;
1593 }
1594
1595 for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++) {
1596 retval = device_create_file(info->dev, &fb_device_attrs[i]);
1597 if (retval) {
1598 pr_err("device_create_file failed %d\n", retval);
1599 goto err_del_attrs;
1600 }
1601 }
1602
1603 retval = device_create_bin_file(info->dev, &edid_attr);
1604 if (retval) {
1605 pr_err("device_create_bin_file failed %d\n", retval);
1606 goto err_del_attrs;
1607 }
1608
1609 pr_info("DisplayLink USB device /dev/fb%d attached. %dx%d resolution."
1610 " Using %dK framebuffer memory\n", info->node,
1611 info->var.xres, info->var.yres,
1612 ((dev->backing_buffer) ?
1613 info->fix.smem_len * 2 : info->fix.smem_len) >> 10);
1614 return 0;
1615
1616err_del_attrs:
1617 for (i -= 1; i >= 0; i--)
1618 device_remove_file(info->dev, &fb_device_attrs[i]);
1619
1620error:
1621 if (dev) {
1622
1623 if (info) {
1624 if (info->cmap.len != 0)
1625 fb_dealloc_cmap(&info->cmap);
1626 if (info->monspecs.modedb)
1627 fb_destroy_modedb(info->monspecs.modedb);
1628 if (info->screen_base)
1629 vfree(info->screen_base);
1630
1631 fb_destroy_modelist(&info->modelist);
1632
1633 framebuffer_release(info);
1634 }
1635
1636 if (dev->backing_buffer)
1637 vfree(dev->backing_buffer);
1638
1639 kref_put(&dev->kref, dlfb_free); /* ref for framebuffer */
1640 kref_put(&dev->kref, dlfb_free); /* last ref from kref_init */
1641
1642 /* dev has been deallocated. Do not dereference */
1643 }
1644
1645 return retval;
1646}
1647
1648static void dlfb_usb_disconnect(struct usb_interface *interface)
1649{
1650 struct dlfb_data *dev;
1651 struct fb_info *info;
1652 int i;
1653
1654 dev = usb_get_intfdata(interface);
1655 info = dev->info;
1656
1657 pr_info("USB disconnect starting\n");
1658
1659 /* we virtualize until all fb clients release. Then we free */
1660 dev->virtualized = true;
1661
1662 /* When non-active we'll update virtual framebuffer, but no new urbs */
1663 atomic_set(&dev->usb_active, 0);
1664
1665 /* remove udlfb's sysfs interfaces */
1666 for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++)
1667 device_remove_file(info->dev, &fb_device_attrs[i]);
1668 device_remove_bin_file(info->dev, &edid_attr);
1669
1670 usb_set_intfdata(interface, NULL);
1671
1672 /* if clients still have us open, will be freed on last close */
1673 if (dev->fb_count == 0)
1674 schedule_delayed_work(&dev->free_framebuffer_work, 0);
1675
1676 /* release reference taken by kref_init in probe() */
1677 kref_put(&dev->kref, dlfb_free);
1678
1679 /* consider dlfb_data freed */
1680
1681 return;
1682}
1683
1684static struct usb_driver dlfb_driver = {
1685 .name = "udlfb",
1686 .probe = dlfb_usb_probe,
1687 .disconnect = dlfb_usb_disconnect,
1688 .id_table = id_table,
1689};
1690
1691static int __init dlfb_module_init(void)
1692{
1693 int res;
1694
1695 res = usb_register(&dlfb_driver);
1696 if (res)
1697 err("usb_register failed. Error number %d", res);
1698
1699 return res;
1700}
1701
1702static void __exit dlfb_module_exit(void)
1703{
1704 usb_deregister(&dlfb_driver);
1705}
1706
1707module_init(dlfb_module_init);
1708module_exit(dlfb_module_exit);
1709
1710static void dlfb_urb_completion(struct urb *urb)
1711{
1712 struct urb_node *unode = urb->context;
1713 struct dlfb_data *dev = unode->dev;
1714 unsigned long flags;
1715
1716 /* sync/async unlink faults aren't errors */
1717 if (urb->status) {
1718 if (!(urb->status == -ENOENT ||
1719 urb->status == -ECONNRESET ||
1720 urb->status == -ESHUTDOWN)) {
1721 pr_err("%s - nonzero write bulk status received: %d\n",
1722 __func__, urb->status);
1723 atomic_set(&dev->lost_pixels, 1);
1724 }
1725 }
1726
1727 urb->transfer_buffer_length = dev->urbs.size; /* reset to actual */
1728
1729 spin_lock_irqsave(&dev->urbs.lock, flags);
1730 list_add_tail(&unode->entry, &dev->urbs.list);
1731 dev->urbs.available++;
1732 spin_unlock_irqrestore(&dev->urbs.lock, flags);
1733
1734 /*
1735 * When using fb_defio, we deadlock if up() is called
1736 * while another is waiting. So queue to another process.
1737 */
1738 if (fb_defio)
1739 schedule_delayed_work(&unode->release_urb_work, 0);
1740 else
1741 up(&dev->urbs.limit_sem);
1742}
1743
1744static void dlfb_free_urb_list(struct dlfb_data *dev)
1745{
1746 int count = dev->urbs.count;
1747 struct list_head *node;
1748 struct urb_node *unode;
1749 struct urb *urb;
1750 int ret;
1751 unsigned long flags;
1752
1753 pr_notice("Waiting for completes and freeing all render urbs\n");
1754
1755 /* keep waiting and freeing, until we've got 'em all */
1756 while (count--) {
1757
1758 /* Getting interrupted means a leak, but ok at shutdown*/
1759 ret = down_interruptible(&dev->urbs.limit_sem);
1760 if (ret)
1761 break;
1762
1763 spin_lock_irqsave(&dev->urbs.lock, flags);
1764
1765 node = dev->urbs.list.next; /* have reserved one with sem */
1766 list_del_init(node);
1767
1768 spin_unlock_irqrestore(&dev->urbs.lock, flags);
1769
1770 unode = list_entry(node, struct urb_node, entry);
1771 urb = unode->urb;
1772
1773 /* Free each separately allocated piece */
1774 usb_free_coherent(urb->dev, dev->urbs.size,
1775 urb->transfer_buffer, urb->transfer_dma);
1776 usb_free_urb(urb);
1777 kfree(node);
1778 }
1779
1780}
1781
1782static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size)
1783{
1784 int i = 0;
1785 struct urb *urb;
1786 struct urb_node *unode;
1787 char *buf;
1788
1789 spin_lock_init(&dev->urbs.lock);
1790
1791 dev->urbs.size = size;
1792 INIT_LIST_HEAD(&dev->urbs.list);
1793
1794 while (i < count) {
1795 unode = kzalloc(sizeof(struct urb_node), GFP_KERNEL);
1796 if (!unode)
1797 break;
1798 unode->dev = dev;
1799
1800 INIT_DELAYED_WORK(&unode->release_urb_work,
1801 dlfb_release_urb_work);
1802
1803 urb = usb_alloc_urb(0, GFP_KERNEL);
1804 if (!urb) {
1805 kfree(unode);
1806 break;
1807 }
1808 unode->urb = urb;
1809
1810 buf = usb_alloc_coherent(dev->udev, MAX_TRANSFER, GFP_KERNEL,
1811 &urb->transfer_dma);
1812 if (!buf) {
1813 kfree(unode);
1814 usb_free_urb(urb);
1815 break;
1816 }
1817
1818 /* urb->transfer_buffer_length set to actual before submit */
1819 usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 1),
1820 buf, size, dlfb_urb_completion, unode);
1821 urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
1822
1823 list_add_tail(&unode->entry, &dev->urbs.list);
1824
1825 i++;
1826 }
1827
1828 sema_init(&dev->urbs.limit_sem, i);
1829 dev->urbs.count = i;
1830 dev->urbs.available = i;
1831
1832 pr_notice("allocated %d %d byte urbs\n", i, (int) size);
1833
1834 return i;
1835}
1836
1837static struct urb *dlfb_get_urb(struct dlfb_data *dev)
1838{
1839 int ret = 0;
1840 struct list_head *entry;
1841 struct urb_node *unode;
1842 struct urb *urb = NULL;
1843 unsigned long flags;
1844
1845 /* Wait for an in-flight buffer to complete and get re-queued */
1846 ret = down_timeout(&dev->urbs.limit_sem, GET_URB_TIMEOUT);
1847 if (ret) {
1848 atomic_set(&dev->lost_pixels, 1);
1849 pr_warn("wait for urb interrupted: %x available: %d\n",
1850 ret, dev->urbs.available);
1851 goto error;
1852 }
1853
1854 spin_lock_irqsave(&dev->urbs.lock, flags);
1855
1856 BUG_ON(list_empty(&dev->urbs.list)); /* reserved one with limit_sem */
1857 entry = dev->urbs.list.next;
1858 list_del_init(entry);
1859 dev->urbs.available--;
1860
1861 spin_unlock_irqrestore(&dev->urbs.lock, flags);
1862
1863 unode = list_entry(entry, struct urb_node, entry);
1864 urb = unode->urb;
1865
1866error:
1867 return urb;
1868}
1869
1870static int dlfb_submit_urb(struct dlfb_data *dev, struct urb *urb, size_t len)
1871{
1872 int ret;
1873
1874 BUG_ON(len > dev->urbs.size);
1875
1876 urb->transfer_buffer_length = len; /* set to actual payload len */
1877 ret = usb_submit_urb(urb, GFP_KERNEL);
1878 if (ret) {
1879 dlfb_urb_completion(urb); /* because no one else will */
1880 atomic_set(&dev->lost_pixels, 1);
1881 pr_err("usb_submit_urb error %x\n", ret);
1882 }
1883 return ret;
1884}
1885
1886module_param(console, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
1887MODULE_PARM_DESC(console, "Allow fbcon to consume first framebuffer found");
1888
1889module_param(fb_defio, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
1890MODULE_PARM_DESC(fb_defio, "Enable fb_defio mmap support. *Experimental*");
1891
1892MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, "
1893 "Jaya Kumar <jayakumar.lkml@gmail.com>, "
1894 "Bernie Thompson <bernie@plugable.com>");
1895MODULE_DESCRIPTION("DisplayLink kernel framebuffer driver");
1896MODULE_LICENSE("GPL");
1897
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index 52ec0959d462..7f8472cc993b 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -73,7 +73,7 @@ static void uvesafb_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *ns
73 struct uvesafb_task *utask; 73 struct uvesafb_task *utask;
74 struct uvesafb_ktask *task; 74 struct uvesafb_ktask *task;
75 75
76 if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN)) 76 if (!cap_raised(current_cap(), CAP_SYS_ADMIN))
77 return; 77 return;
78 78
79 if (msg->seq >= UVESAFB_TASKS_MAX) 79 if (msg->seq >= UVESAFB_TASKS_MAX)
@@ -1552,8 +1552,7 @@ static void __devinit uvesafb_init_mtrr(struct fb_info *info)
1552 int rc; 1552 int rc;
1553 1553
1554 /* Find the largest power-of-two */ 1554 /* Find the largest power-of-two */
1555 while (temp_size & (temp_size - 1)) 1555 temp_size = roundup_pow_of_two(temp_size);
1556 temp_size &= (temp_size - 1);
1557 1556
1558 /* Try and find a power of two to add */ 1557 /* Try and find a power of two to add */
1559 do { 1558 do {
@@ -1566,6 +1565,28 @@ static void __devinit uvesafb_init_mtrr(struct fb_info *info)
1566#endif /* CONFIG_MTRR */ 1565#endif /* CONFIG_MTRR */
1567} 1566}
1568 1567
1568static void __devinit uvesafb_ioremap(struct fb_info *info)
1569{
1570#ifdef CONFIG_X86
1571 switch (mtrr) {
1572 case 1: /* uncachable */
1573 info->screen_base = ioremap_nocache(info->fix.smem_start, info->fix.smem_len);
1574 break;
1575 case 2: /* write-back */
1576 info->screen_base = ioremap_cache(info->fix.smem_start, info->fix.smem_len);
1577 break;
1578 case 3: /* write-combining */
1579 info->screen_base = ioremap_wc(info->fix.smem_start, info->fix.smem_len);
1580 break;
1581 case 4: /* write-through */
1582 default:
1583 info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
1584 break;
1585 }
1586#else
1587 info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
1588#endif /* CONFIG_X86 */
1589}
1569 1590
1570static ssize_t uvesafb_show_vbe_ver(struct device *dev, 1591static ssize_t uvesafb_show_vbe_ver(struct device *dev,
1571 struct device_attribute *attr, char *buf) 1592 struct device_attribute *attr, char *buf)
@@ -1736,15 +1757,22 @@ static int __devinit uvesafb_probe(struct platform_device *dev)
1736 1757
1737 uvesafb_init_info(info, mode); 1758 uvesafb_init_info(info, mode);
1738 1759
1760 if (!request_region(0x3c0, 32, "uvesafb")) {
1761 printk(KERN_ERR "uvesafb: request region 0x3c0-0x3e0 failed\n");
1762 err = -EIO;
1763 goto out_mode;
1764 }
1765
1739 if (!request_mem_region(info->fix.smem_start, info->fix.smem_len, 1766 if (!request_mem_region(info->fix.smem_start, info->fix.smem_len,
1740 "uvesafb")) { 1767 "uvesafb")) {
1741 printk(KERN_ERR "uvesafb: cannot reserve video memory at " 1768 printk(KERN_ERR "uvesafb: cannot reserve video memory at "
1742 "0x%lx\n", info->fix.smem_start); 1769 "0x%lx\n", info->fix.smem_start);
1743 err = -EIO; 1770 err = -EIO;
1744 goto out_mode; 1771 goto out_reg;
1745 } 1772 }
1746 1773
1747 info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); 1774 uvesafb_init_mtrr(info);
1775 uvesafb_ioremap(info);
1748 1776
1749 if (!info->screen_base) { 1777 if (!info->screen_base) {
1750 printk(KERN_ERR 1778 printk(KERN_ERR
@@ -1755,20 +1783,13 @@ static int __devinit uvesafb_probe(struct platform_device *dev)
1755 goto out_mem; 1783 goto out_mem;
1756 } 1784 }
1757 1785
1758 if (!request_region(0x3c0, 32, "uvesafb")) {
1759 printk(KERN_ERR "uvesafb: request region 0x3c0-0x3e0 failed\n");
1760 err = -EIO;
1761 goto out_unmap;
1762 }
1763
1764 uvesafb_init_mtrr(info);
1765 platform_set_drvdata(dev, info); 1786 platform_set_drvdata(dev, info);
1766 1787
1767 if (register_framebuffer(info) < 0) { 1788 if (register_framebuffer(info) < 0) {
1768 printk(KERN_ERR 1789 printk(KERN_ERR
1769 "uvesafb: failed to register framebuffer device\n"); 1790 "uvesafb: failed to register framebuffer device\n");
1770 err = -EINVAL; 1791 err = -EINVAL;
1771 goto out_reg; 1792 goto out_unmap;
1772 } 1793 }
1773 1794
1774 printk(KERN_INFO "uvesafb: framebuffer at 0x%lx, mapped to 0x%p, " 1795 printk(KERN_INFO "uvesafb: framebuffer at 0x%lx, mapped to 0x%p, "
@@ -1785,12 +1806,12 @@ static int __devinit uvesafb_probe(struct platform_device *dev)
1785 1806
1786 return 0; 1807 return 0;
1787 1808
1788out_reg:
1789 release_region(0x3c0, 32);
1790out_unmap: 1809out_unmap:
1791 iounmap(info->screen_base); 1810 iounmap(info->screen_base);
1792out_mem: 1811out_mem:
1793 release_mem_region(info->fix.smem_start, info->fix.smem_len); 1812 release_mem_region(info->fix.smem_start, info->fix.smem_len);
1813out_reg:
1814 release_region(0x3c0, 32);
1794out_mode: 1815out_mode:
1795 if (!list_empty(&info->modelist)) 1816 if (!list_empty(&info->modelist))
1796 fb_destroy_modelist(&info->modelist); 1817 fb_destroy_modelist(&info->modelist);
diff --git a/drivers/video/vermilion/vermilion.c b/drivers/video/vermilion/vermilion.c
index 931a567f9aff..970e43d13f52 100644
--- a/drivers/video/vermilion/vermilion.c
+++ b/drivers/video/vermilion/vermilion.c
@@ -891,8 +891,7 @@ static int vmlfb_set_par(struct fb_info *info)
891 int ret; 891 int ret;
892 892
893 mutex_lock(&vml_mutex); 893 mutex_lock(&vml_mutex);
894 list_del(&vinfo->head); 894 list_move(&vinfo->head, (subsys) ? &global_has_mode : &global_no_mode);
895 list_add(&vinfo->head, (subsys) ? &global_has_mode : &global_no_mode);
896 ret = vmlfb_set_par_locked(vinfo); 895 ret = vmlfb_set_par_locked(vinfo);
897 896
898 mutex_unlock(&vml_mutex); 897 mutex_unlock(&vml_mutex);
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index 090aa1a9be6e..501b3406c6d5 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -175,6 +175,7 @@ static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
175 175
176static void vesafb_destroy(struct fb_info *info) 176static void vesafb_destroy(struct fb_info *info)
177{ 177{
178 fb_dealloc_cmap(&info->cmap);
178 if (info->screen_base) 179 if (info->screen_base)
179 iounmap(info->screen_base); 180 iounmap(info->screen_base);
180 release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size); 181 release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size);
@@ -253,7 +254,7 @@ static int __init vesafb_probe(struct platform_device *dev)
253 size_vmode = vesafb_defined.yres * vesafb_fix.line_length; 254 size_vmode = vesafb_defined.yres * vesafb_fix.line_length;
254 255
255 /* size_total -- all video memory we have. Used for mtrr 256 /* size_total -- all video memory we have. Used for mtrr
256 * entries, ressource allocation and bounds 257 * entries, resource allocation and bounds
257 * checking. */ 258 * checking. */
258 size_total = screen_info.lfb_size * 65536; 259 size_total = screen_info.lfb_size * 65536;
259 if (vram_total) 260 if (vram_total)
@@ -303,19 +304,6 @@ static int __init vesafb_probe(struct platform_device *dev)
303 info->apertures->ranges[0].base = screen_info.lfb_base; 304 info->apertures->ranges[0].base = screen_info.lfb_base;
304 info->apertures->ranges[0].size = size_total; 305 info->apertures->ranges[0].size = size_total;
305 306
306 info->screen_base = ioremap(vesafb_fix.smem_start, vesafb_fix.smem_len);
307 if (!info->screen_base) {
308 printk(KERN_ERR
309 "vesafb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n",
310 vesafb_fix.smem_len, vesafb_fix.smem_start);
311 err = -EIO;
312 goto err;
313 }
314
315 printk(KERN_INFO "vesafb: framebuffer at 0x%lx, mapped to 0x%p, "
316 "using %dk, total %dk\n",
317 vesafb_fix.smem_start, info->screen_base,
318 size_remap/1024, size_total/1024);
319 printk(KERN_INFO "vesafb: mode is %dx%dx%d, linelength=%d, pages=%d\n", 307 printk(KERN_INFO "vesafb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
320 vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel, vesafb_fix.line_length, screen_info.pages); 308 vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel, vesafb_fix.line_length, screen_info.pages);
321 309
@@ -438,8 +426,7 @@ static int __init vesafb_probe(struct platform_device *dev)
438 int rc; 426 int rc;
439 427
440 /* Find the largest power-of-two */ 428 /* Find the largest power-of-two */
441 while (temp_size & (temp_size - 1)) 429 temp_size = roundup_pow_of_two(temp_size);
442 temp_size &= (temp_size - 1);
443 430
444 /* Try and find a power of two to add */ 431 /* Try and find a power of two to add */
445 do { 432 do {
@@ -451,6 +438,34 @@ static int __init vesafb_probe(struct platform_device *dev)
451 } 438 }
452#endif 439#endif
453 440
441 switch (mtrr) {
442 case 1: /* uncachable */
443 info->screen_base = ioremap_nocache(vesafb_fix.smem_start, vesafb_fix.smem_len);
444 break;
445 case 2: /* write-back */
446 info->screen_base = ioremap_cache(vesafb_fix.smem_start, vesafb_fix.smem_len);
447 break;
448 case 3: /* write-combining */
449 info->screen_base = ioremap_wc(vesafb_fix.smem_start, vesafb_fix.smem_len);
450 break;
451 case 4: /* write-through */
452 default:
453 info->screen_base = ioremap(vesafb_fix.smem_start, vesafb_fix.smem_len);
454 break;
455 }
456 if (!info->screen_base) {
457 printk(KERN_ERR
458 "vesafb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n",
459 vesafb_fix.smem_len, vesafb_fix.smem_start);
460 err = -EIO;
461 goto err;
462 }
463
464 printk(KERN_INFO "vesafb: framebuffer at 0x%lx, mapped to 0x%p, "
465 "using %dk, total %dk\n",
466 vesafb_fix.smem_start, info->screen_base,
467 size_remap/1024, size_total/1024);
468
454 info->fbops = &vesafb_ops; 469 info->fbops = &vesafb_ops;
455 info->var = vesafb_defined; 470 info->var = vesafb_defined;
456 info->fix = vesafb_fix; 471 info->fix = vesafb_fix;
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 28ccab44a391..305c975b1787 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -152,7 +152,7 @@ static inline int setop(int op)
152} 152}
153 153
154/* Set the Enable Set/Reset Register and return its old value. 154/* Set the Enable Set/Reset Register and return its old value.
155 The code here always uses value 0xf for thsi register. */ 155 The code here always uses value 0xf for this register. */
156static inline int setsr(int sr) 156static inline int setsr(int sr)
157{ 157{
158 int oldsr; 158 int oldsr;
@@ -1265,9 +1265,11 @@ static void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image
1265 1265
1266static void vga16fb_destroy(struct fb_info *info) 1266static void vga16fb_destroy(struct fb_info *info)
1267{ 1267{
1268 struct platform_device *dev = container_of(info->device, struct platform_device, dev);
1268 iounmap(info->screen_base); 1269 iounmap(info->screen_base);
1269 fb_dealloc_cmap(&info->cmap); 1270 fb_dealloc_cmap(&info->cmap);
1270 /* XXX unshare VGA regions */ 1271 /* XXX unshare VGA regions */
1272 platform_set_drvdata(dev, NULL);
1271 framebuffer_release(info); 1273 framebuffer_release(info);
1272} 1274}
1273 1275
diff --git a/drivers/video/via/Makefile b/drivers/video/via/Makefile
index d496adb0f832..5108136e8776 100644
--- a/drivers/video/via/Makefile
+++ b/drivers/video/via/Makefile
@@ -5,5 +5,5 @@
5obj-$(CONFIG_FB_VIA) += viafb.o 5obj-$(CONFIG_FB_VIA) += viafb.o
6 6
7viafb-y :=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o \ 7viafb-y :=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o \
8 via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o \ 8 via_utility.o vt1636.o global.o tblDPASetting.o viamode.o \
9 via-core.o via-gpio.o via_modesetting.o 9 via-core.o via-gpio.o via_modesetting.o via_clock.o
diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c
index e44893ea590d..4b67b8e6030a 100644
--- a/drivers/video/via/accel.c
+++ b/drivers/video/via/accel.c
@@ -283,11 +283,12 @@ static int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height,
283 writel(tmp, engine + 0x1C); 283 writel(tmp, engine + 0x1C);
284 } 284 }
285 285
286 if (op != VIA_BITBLT_COLOR) 286 if (op == VIA_BITBLT_FILL) {
287 writel(fg_color, engine + 0x58);
288 } else if (op == VIA_BITBLT_MONO) {
287 writel(fg_color, engine + 0x4C); 289 writel(fg_color, engine + 0x4C);
288
289 if (op == VIA_BITBLT_MONO)
290 writel(bg_color, engine + 0x50); 290 writel(bg_color, engine + 0x50);
291 }
291 292
292 if (op == VIA_BITBLT_FILL) 293 if (op == VIA_BITBLT_FILL)
293 ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001; 294 ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001;
@@ -314,13 +315,11 @@ static int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height,
314 return 0; 315 return 0;
315} 316}
316 317
317int viafb_init_engine(struct fb_info *info) 318int viafb_setup_engine(struct fb_info *info)
318{ 319{
319 struct viafb_par *viapar = info->par; 320 struct viafb_par *viapar = info->par;
320 void __iomem *engine; 321 void __iomem *engine;
321 int highest_reg, i; 322 u32 chip_name = viapar->shared->chip_info.gfx_chip_name;
322 u32 vq_start_addr, vq_end_addr, vq_start_low, vq_end_low, vq_high,
323 vq_len, chip_name = viapar->shared->chip_info.gfx_chip_name;
324 323
325 engine = viapar->shared->vdev->engine_mmio; 324 engine = viapar->shared->vdev->engine_mmio;
326 if (!engine) { 325 if (!engine) {
@@ -329,18 +328,6 @@ int viafb_init_engine(struct fb_info *info)
329 return -ENOMEM; 328 return -ENOMEM;
330 } 329 }
331 330
332 /* Initialize registers to reset the 2D engine */
333 switch (viapar->shared->chip_info.twod_engine) {
334 case VIA_2D_ENG_M1:
335 highest_reg = 0x5c;
336 break;
337 default:
338 highest_reg = 0x40;
339 break;
340 }
341 for (i = 0; i <= highest_reg; i += 4)
342 writel(0x0, engine + i);
343
344 switch (chip_name) { 331 switch (chip_name) {
345 case UNICHROME_CLE266: 332 case UNICHROME_CLE266:
346 case UNICHROME_K400: 333 case UNICHROME_K400:
@@ -356,6 +343,7 @@ int viafb_init_engine(struct fb_info *info)
356 break; 343 break;
357 case UNICHROME_VX800: 344 case UNICHROME_VX800:
358 case UNICHROME_VX855: 345 case UNICHROME_VX855:
346 case UNICHROME_VX900:
359 viapar->shared->hw_bitblt = hw_bitblt_2; 347 viapar->shared->hw_bitblt = hw_bitblt_2;
360 break; 348 break;
361 default: 349 default:
@@ -370,7 +358,7 @@ int viafb_init_engine(struct fb_info *info)
370 viapar->shared->vq_vram_addr = viapar->fbmem_free; 358 viapar->shared->vq_vram_addr = viapar->fbmem_free;
371 viapar->fbmem_used += VQ_SIZE; 359 viapar->fbmem_used += VQ_SIZE;
372 360
373#if defined(CONFIG_FB_VIA_CAMERA) || defined(CONFIG_FB_VIA_CAMERA_MODULE) 361#if defined(CONFIG_VIDEO_VIA_CAMERA) || defined(CONFIG_VIDEO_VIA_CAMERA_MODULE)
374 /* 362 /*
375 * Set aside a chunk of framebuffer memory for the camera 363 * Set aside a chunk of framebuffer memory for the camera
376 * driver. Someday this driver probably needs a proper allocator 364 * driver. Someday this driver probably needs a proper allocator
@@ -386,12 +374,36 @@ int viafb_init_engine(struct fb_info *info)
386 viapar->shared->vdev->camera_fbmem_offset = viapar->fbmem_free; 374 viapar->shared->vdev->camera_fbmem_offset = viapar->fbmem_free;
387#endif 375#endif
388 376
377 viafb_reset_engine(viapar);
378 return 0;
379}
380
381void viafb_reset_engine(struct viafb_par *viapar)
382{
383 void __iomem *engine = viapar->shared->vdev->engine_mmio;
384 int highest_reg, i;
385 u32 vq_start_addr, vq_end_addr, vq_start_low, vq_end_low, vq_high,
386 vq_len, chip_name = viapar->shared->chip_info.gfx_chip_name;
387
388 /* Initialize registers to reset the 2D engine */
389 switch (viapar->shared->chip_info.twod_engine) {
390 case VIA_2D_ENG_M1:
391 highest_reg = 0x5c;
392 break;
393 default:
394 highest_reg = 0x40;
395 break;
396 }
397 for (i = 0; i <= highest_reg; i += 4)
398 writel(0x0, engine + i);
399
389 /* Init AGP and VQ regs */ 400 /* Init AGP and VQ regs */
390 switch (chip_name) { 401 switch (chip_name) {
391 case UNICHROME_K8M890: 402 case UNICHROME_K8M890:
392 case UNICHROME_P4M900: 403 case UNICHROME_P4M900:
393 case UNICHROME_VX800: 404 case UNICHROME_VX800:
394 case UNICHROME_VX855: 405 case UNICHROME_VX855:
406 case UNICHROME_VX900:
395 writel(0x00100000, engine + VIA_REG_CR_TRANSET); 407 writel(0x00100000, engine + VIA_REG_CR_TRANSET);
396 writel(0x680A0000, engine + VIA_REG_CR_TRANSPACE); 408 writel(0x680A0000, engine + VIA_REG_CR_TRANSPACE);
397 writel(0x02000000, engine + VIA_REG_CR_TRANSPACE); 409 writel(0x02000000, engine + VIA_REG_CR_TRANSPACE);
@@ -428,6 +440,7 @@ int viafb_init_engine(struct fb_info *info)
428 case UNICHROME_P4M900: 440 case UNICHROME_P4M900:
429 case UNICHROME_VX800: 441 case UNICHROME_VX800:
430 case UNICHROME_VX855: 442 case UNICHROME_VX855:
443 case UNICHROME_VX900:
431 vq_start_low |= 0x20000000; 444 vq_start_low |= 0x20000000;
432 vq_end_low |= 0x20000000; 445 vq_end_low |= 0x20000000;
433 vq_high |= 0x20000000; 446 vq_high |= 0x20000000;
@@ -473,7 +486,7 @@ int viafb_init_engine(struct fb_info *info)
473 writel(0x0, engine + VIA_REG_CURSOR_ORG); 486 writel(0x0, engine + VIA_REG_CURSOR_ORG);
474 writel(0x0, engine + VIA_REG_CURSOR_BG); 487 writel(0x0, engine + VIA_REG_CURSOR_BG);
475 writel(0x0, engine + VIA_REG_CURSOR_FG); 488 writel(0x0, engine + VIA_REG_CURSOR_FG);
476 return 0; 489 return;
477} 490}
478 491
479void viafb_show_hw_cursor(struct fb_info *info, int Status) 492void viafb_show_hw_cursor(struct fb_info *info, int Status)
diff --git a/drivers/video/via/accel.h b/drivers/video/via/accel.h
index 2c122d292365..79d5e10cc835 100644
--- a/drivers/video/via/accel.h
+++ b/drivers/video/via/accel.h
@@ -203,7 +203,8 @@
203#define VIA_BITBLT_MONO 2 203#define VIA_BITBLT_MONO 2
204#define VIA_BITBLT_FILL 3 204#define VIA_BITBLT_FILL 3
205 205
206int viafb_init_engine(struct fb_info *info); 206int viafb_setup_engine(struct fb_info *info);
207void viafb_reset_engine(struct viafb_par *viapar);
207void viafb_show_hw_cursor(struct fb_info *info, int Status); 208void viafb_show_hw_cursor(struct fb_info *info, int Status);
208void viafb_wait_engine_idle(struct fb_info *info); 209void viafb_wait_engine_idle(struct fb_info *info);
209 210
diff --git a/drivers/video/via/chip.h b/drivers/video/via/chip.h
index ef1f3de2e052..3ebf20c06eef 100644
--- a/drivers/video/via/chip.h
+++ b/drivers/video/via/chip.h
@@ -71,6 +71,9 @@
71#define UNICHROME_VX855 12 71#define UNICHROME_VX855 12
72#define UNICHROME_VX855_DID 0x5122 72#define UNICHROME_VX855_DID 0x5122
73 73
74#define UNICHROME_VX900 13
75#define UNICHROME_VX900_DID 0x7122
76
74/**************************************************/ 77/**************************************************/
75/* Definition TMDS Trasmitter Information */ 78/* Definition TMDS Trasmitter Information */
76/**************************************************/ 79/**************************************************/
@@ -107,16 +110,13 @@
107struct tmds_chip_information { 110struct tmds_chip_information {
108 int tmds_chip_name; 111 int tmds_chip_name;
109 int tmds_chip_slave_addr; 112 int tmds_chip_slave_addr;
110 int data_mode;
111 int output_interface; 113 int output_interface;
112 int i2c_port; 114 int i2c_port;
113 int device_type;
114}; 115};
115 116
116struct lvds_chip_information { 117struct lvds_chip_information {
117 int lvds_chip_name; 118 int lvds_chip_name;
118 int lvds_chip_slave_addr; 119 int lvds_chip_slave_addr;
119 int data_mode;
120 int output_interface; 120 int output_interface;
121 int i2c_port; 121 int i2c_port;
122}; 122};
@@ -137,21 +137,11 @@ struct chip_information {
137 struct lvds_chip_information lvds_chip_info2; 137 struct lvds_chip_information lvds_chip_info2;
138}; 138};
139 139
140struct crt_setting_information {
141 int iga_path;
142 int h_active;
143 int v_active;
144 int bpp;
145 int refresh_rate;
146};
147
148struct tmds_setting_information { 140struct tmds_setting_information {
149 int iga_path; 141 int iga_path;
150 int h_active; 142 int h_active;
151 int v_active; 143 int v_active;
152 int max_pixel_clock; 144 int max_pixel_clock;
153 int max_hres;
154 int max_vres;
155}; 145};
156 146
157struct lvds_setting_information { 147struct lvds_setting_information {
@@ -159,8 +149,6 @@ struct lvds_setting_information {
159 int h_active; 149 int h_active;
160 int v_active; 150 int v_active;
161 int bpp; 151 int bpp;
162 int refresh_rate;
163 int lcd_panel_id;
164 int lcd_panel_hres; 152 int lcd_panel_hres;
165 int lcd_panel_vres; 153 int lcd_panel_vres;
166 int display_method; 154 int display_method;
@@ -185,7 +173,6 @@ struct GFX_DPA_SETTING {
185}; 173};
186 174
187struct VT1636_DPA_SETTING { 175struct VT1636_DPA_SETTING {
188 int PanelSizeID;
189 u8 CLK_SEL_ST1; 176 u8 CLK_SEL_ST1;
190 u8 CLK_SEL_ST2; 177 u8 CLK_SEL_ST2;
191}; 178};
diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c
index 39b040bb3817..b1f364745ca0 100644
--- a/drivers/video/via/dvi.c
+++ b/drivers/video/via/dvi.c
@@ -25,42 +25,29 @@
25static void tmds_register_write(int index, u8 data); 25static void tmds_register_write(int index, u8 data);
26static int tmds_register_read(int index); 26static int tmds_register_read(int index);
27static int tmds_register_read_bytes(int index, u8 *buff, int buff_len); 27static int tmds_register_read_bytes(int index, u8 *buff, int buff_len);
28static void dvi_get_panel_size_from_DDCv1(struct tmds_chip_information 28static void __devinit dvi_get_panel_size_from_DDCv1(
29 *tmds_chip, struct tmds_setting_information *tmds_setting); 29 struct tmds_chip_information *tmds_chip,
30static void dvi_get_panel_size_from_DDCv2(struct tmds_chip_information 30 struct tmds_setting_information *tmds_setting);
31 *tmds_chip, struct tmds_setting_information *tmds_setting);
32static int viafb_dvi_query_EDID(void); 31static int viafb_dvi_query_EDID(void);
33 32
34static int check_tmds_chip(int device_id_subaddr, int device_id) 33static inline bool check_tmds_chip(int device_id_subaddr, int device_id)
35{ 34{
36 if (tmds_register_read(device_id_subaddr) == device_id) 35 return tmds_register_read(device_id_subaddr) == device_id;
37 return OK;
38 else
39 return FAIL;
40} 36}
41 37
42void viafb_init_dvi_size(struct tmds_chip_information *tmds_chip, 38void __devinit viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
43 struct tmds_setting_information *tmds_setting) 39 struct tmds_setting_information *tmds_setting)
44{ 40{
45 DEBUG_MSG(KERN_INFO "viafb_init_dvi_size()\n"); 41 DEBUG_MSG(KERN_INFO "viafb_init_dvi_size()\n");
46 42
47 viafb_dvi_sense(); 43 viafb_dvi_sense();
48 switch (viafb_dvi_query_EDID()) { 44 if (viafb_dvi_query_EDID() == 1)
49 case 1:
50 dvi_get_panel_size_from_DDCv1(tmds_chip, tmds_setting); 45 dvi_get_panel_size_from_DDCv1(tmds_chip, tmds_setting);
51 break;
52 case 2:
53 dvi_get_panel_size_from_DDCv2(tmds_chip, tmds_setting);
54 break;
55 default:
56 printk(KERN_WARNING "viafb_init_dvi_size: DVI panel size undetected!\n");
57 break;
58 }
59 46
60 return; 47 return;
61} 48}
62 49
63int viafb_tmds_trasmitter_identify(void) 50bool __devinit viafb_tmds_trasmitter_identify(void)
64{ 51{
65 unsigned char sr2a = 0, sr1e = 0, sr3e = 0; 52 unsigned char sr2a = 0, sr1e = 0, sr3e = 0;
66 53
@@ -99,7 +86,7 @@ int viafb_tmds_trasmitter_identify(void)
99 viaparinfo->chip_info-> 86 viaparinfo->chip_info->
100 tmds_chip_info.tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR; 87 tmds_chip_info.tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR;
101 viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_31; 88 viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_31;
102 if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID) != FAIL) { 89 if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID)) {
103 /* 90 /*
104 * Currently only support 12bits,dual edge,add 24bits mode later 91 * Currently only support 12bits,dual edge,add 24bits mode later
105 */ 92 */
@@ -110,11 +97,10 @@ int viafb_tmds_trasmitter_identify(void)
110 viaparinfo->chip_info->tmds_chip_info.tmds_chip_name); 97 viaparinfo->chip_info->tmds_chip_info.tmds_chip_name);
111 DEBUG_MSG(KERN_INFO "\n %2d", 98 DEBUG_MSG(KERN_INFO "\n %2d",
112 viaparinfo->chip_info->tmds_chip_info.i2c_port); 99 viaparinfo->chip_info->tmds_chip_info.i2c_port);
113 return OK; 100 return true;
114 } else { 101 } else {
115 viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_2C; 102 viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_2C;
116 if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID) 103 if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID)) {
117 != FAIL) {
118 tmds_register_write(0x08, 0x3b); 104 tmds_register_write(0x08, 0x3b);
119 DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n"); 105 DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n");
120 DEBUG_MSG(KERN_INFO "\n %2d", 106 DEBUG_MSG(KERN_INFO "\n %2d",
@@ -123,7 +109,7 @@ int viafb_tmds_trasmitter_identify(void)
123 DEBUG_MSG(KERN_INFO "\n %2d", 109 DEBUG_MSG(KERN_INFO "\n %2d",
124 viaparinfo->chip_info-> 110 viaparinfo->chip_info->
125 tmds_chip_info.i2c_port); 111 tmds_chip_info.i2c_port);
126 return OK; 112 return true;
127 } 113 }
128 } 114 }
129 115
@@ -133,7 +119,7 @@ int viafb_tmds_trasmitter_identify(void)
133 ((viafb_display_hardware_layout == HW_LAYOUT_DVI_ONLY) || 119 ((viafb_display_hardware_layout == HW_LAYOUT_DVI_ONLY) ||
134 (viafb_display_hardware_layout == HW_LAYOUT_LCD_DVI))) { 120 (viafb_display_hardware_layout == HW_LAYOUT_LCD_DVI))) {
135 DEBUG_MSG(KERN_INFO "\n Integrated TMDS ! \n"); 121 DEBUG_MSG(KERN_INFO "\n Integrated TMDS ! \n");
136 return OK; 122 return true;
137 } 123 }
138 124
139 switch (viaparinfo->chip_info->gfx_chip_name) { 125 switch (viaparinfo->chip_info->gfx_chip_name) {
@@ -157,7 +143,7 @@ int viafb_tmds_trasmitter_identify(void)
157 tmds_chip_info.tmds_chip_name = NON_TMDS_TRANSMITTER; 143 tmds_chip_info.tmds_chip_name = NON_TMDS_TRANSMITTER;
158 viaparinfo->chip_info->tmds_chip_info. 144 viaparinfo->chip_info->tmds_chip_info.
159 tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR; 145 tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR;
160 return FAIL; 146 return false;
161} 147}
162 148
163static void tmds_register_write(int index, u8 data) 149static void tmds_register_write(int index, u8 data)
@@ -193,7 +179,9 @@ void viafb_dvi_set_mode(struct VideoModeTable *mode, int mode_bpp,
193 struct crt_mode_table *pDviTiming; 179 struct crt_mode_table *pDviTiming;
194 unsigned long desirePixelClock, maxPixelClock; 180 unsigned long desirePixelClock, maxPixelClock;
195 pDviTiming = mode->crtc; 181 pDviTiming = mode->crtc;
196 desirePixelClock = pDviTiming->clk / 1000000; 182 desirePixelClock = pDviTiming->refresh_rate
183 * pDviTiming->crtc.hor_total * pDviTiming->crtc.ver_total
184 / 1000000;
197 maxPixelClock = (unsigned long)viaparinfo-> 185 maxPixelClock = (unsigned long)viaparinfo->
198 tmds_setting_info->max_pixel_clock; 186 tmds_setting_info->max_pixel_clock;
199 187
@@ -208,8 +196,6 @@ void viafb_dvi_set_mode(struct VideoModeTable *mode, int mode_bpp,
208 } 196 }
209 } 197 }
210 viafb_fill_crtc_timing(pDviTiming, mode, mode_bpp / 8, set_iga); 198 viafb_fill_crtc_timing(pDviTiming, mode, mode_bpp / 8, set_iga);
211 viafb_set_output_path(DEVICE_DVI, set_iga,
212 viaparinfo->chip_info->tmds_chip_info.output_interface);
213} 199}
214 200
215/* Sense DVI Connector */ 201/* Sense DVI Connector */
@@ -304,62 +290,23 @@ static int viafb_dvi_query_EDID(void)
304 return EDID_VERSION_1; /* Found EDID1 Table */ 290 return EDID_VERSION_1; /* Found EDID1 Table */
305 } 291 }
306 292
307 data0 = (u8) tmds_register_read(0x00); 293 return false;
308 viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore;
309 if (data0 == 0x20)
310 return EDID_VERSION_2; /* Found EDID2 Table */
311 else
312 return false;
313} 294}
314 295
315/* Get Panel Size Using EDID1 Table */ 296/* Get Panel Size Using EDID1 Table */
316static void dvi_get_panel_size_from_DDCv1(struct tmds_chip_information 297static void __devinit dvi_get_panel_size_from_DDCv1(
317 *tmds_chip, struct tmds_setting_information *tmds_setting) 298 struct tmds_chip_information *tmds_chip,
299 struct tmds_setting_information *tmds_setting)
318{ 300{
319 int i, max_h = 0, tmp, restore; 301 int i, restore;
320 unsigned char rData;
321 unsigned char EDID_DATA[18]; 302 unsigned char EDID_DATA[18];
322 303
323 DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv1 \n"); 304 DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv1 \n");
324 305
325 restore = tmds_chip->tmds_chip_slave_addr; 306 restore = tmds_chip->tmds_chip_slave_addr;
326 tmds_chip->tmds_chip_slave_addr = 0xA0; 307 tmds_chip->tmds_chip_slave_addr = 0xA0;
327
328 rData = tmds_register_read(0x23);
329 if (rData & 0x3C)
330 max_h = 640;
331 if (rData & 0xC0)
332 max_h = 720;
333 if (rData & 0x03)
334 max_h = 800;
335
336 rData = tmds_register_read(0x24);
337 if (rData & 0xC0)
338 max_h = 800;
339 if (rData & 0x1E)
340 max_h = 1024;
341 if (rData & 0x01)
342 max_h = 1280;
343
344 for (i = 0x25; i < 0x6D; i++) { 308 for (i = 0x25; i < 0x6D; i++) {
345 switch (i) { 309 switch (i) {
346 case 0x26:
347 case 0x28:
348 case 0x2A:
349 case 0x2C:
350 case 0x2E:
351 case 0x30:
352 case 0x32:
353 case 0x34:
354 rData = tmds_register_read(i);
355 if (rData == 1)
356 break;
357 /* data = (data + 31) * 8 */
358 tmp = (rData + 31) << 3;
359 if (tmp > max_h)
360 max_h = tmp;
361 break;
362
363 case 0x36: 310 case 0x36:
364 case 0x48: 311 case 0x48:
365 case 0x5A: 312 case 0x5A:
@@ -380,118 +327,85 @@ static void dvi_get_panel_size_from_DDCv1(struct tmds_chip_information
380 } 327 }
381 } 328 }
382 329
383 tmds_setting->max_hres = max_h;
384 switch (max_h) {
385 case 640:
386 tmds_setting->max_vres = 480;
387 break;
388 case 800:
389 tmds_setting->max_vres = 600;
390 break;
391 case 1024:
392 tmds_setting->max_vres = 768;
393 break;
394 case 1280:
395 tmds_setting->max_vres = 1024;
396 break;
397 case 1400:
398 tmds_setting->max_vres = 1050;
399 break;
400 case 1440:
401 tmds_setting->max_vres = 1050;
402 break;
403 case 1600:
404 tmds_setting->max_vres = 1200;
405 break;
406 case 1920:
407 tmds_setting->max_vres = 1080;
408 break;
409 default:
410 DEBUG_MSG(KERN_INFO "Unknown panel size max resolution = %d ! "
411 "set default panel size.\n", max_h);
412 break;
413 }
414
415 DEBUG_MSG(KERN_INFO "DVI max pixelclock = %d\n", 330 DEBUG_MSG(KERN_INFO "DVI max pixelclock = %d\n",
416 tmds_setting->max_pixel_clock); 331 tmds_setting->max_pixel_clock);
417 tmds_chip->tmds_chip_slave_addr = restore; 332 tmds_chip->tmds_chip_slave_addr = restore;
418} 333}
419 334
420/* Get Panel Size Using EDID2 Table */ 335/* If Disable DVI, turn off pad */
421static void dvi_get_panel_size_from_DDCv2(struct tmds_chip_information 336void viafb_dvi_disable(void)
422 *tmds_chip, struct tmds_setting_information *tmds_setting)
423{ 337{
424 int restore; 338 if (viaparinfo->chip_info->
425 unsigned char R_Buffer[2]; 339 tmds_chip_info.output_interface == INTERFACE_TMDS)
340 /* Turn off TMDS power. */
341 viafb_write_reg(CRD2, VIACR,
342 viafb_read_reg(VIACR, CRD2) | 0x08);
343}
426 344
427 DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv2 \n"); 345static void dvi_patch_skew_dvp0(void)
346{
347 /* Reset data driving first: */
348 viafb_write_reg_mask(SR1B, VIASR, 0, BIT1);
349 viafb_write_reg_mask(SR2A, VIASR, 0, BIT4);
428 350
429 restore = tmds_chip->tmds_chip_slave_addr; 351 switch (viaparinfo->chip_info->gfx_chip_name) {
430 tmds_chip->tmds_chip_slave_addr = 0xA2; 352 case UNICHROME_P4M890:
353 {
354 if ((viaparinfo->tmds_setting_info->h_active == 1600) &&
355 (viaparinfo->tmds_setting_info->v_active ==
356 1200))
357 viafb_write_reg_mask(CR96, VIACR, 0x03,
358 BIT0 + BIT1 + BIT2);
359 else
360 viafb_write_reg_mask(CR96, VIACR, 0x07,
361 BIT0 + BIT1 + BIT2);
362 break;
363 }
431 364
432 /* Horizontal: 0x76, 0x77 */ 365 case UNICHROME_P4M900:
433 tmds_register_read_bytes(0x76, R_Buffer, 2); 366 {
434 tmds_setting->max_hres = R_Buffer[0] + (R_Buffer[1] << 8); 367 viafb_write_reg_mask(CR96, VIACR, 0x07,
368 BIT0 + BIT1 + BIT2 + BIT3);
369 viafb_write_reg_mask(SR1B, VIASR, 0x02, BIT1);
370 viafb_write_reg_mask(SR2A, VIASR, 0x10, BIT4);
371 break;
372 }
435 373
436 switch (tmds_setting->max_hres) {
437 case 640:
438 tmds_setting->max_vres = 480;
439 break;
440 case 800:
441 tmds_setting->max_vres = 600;
442 break;
443 case 1024:
444 tmds_setting->max_vres = 768;
445 break;
446 case 1280:
447 tmds_setting->max_vres = 1024;
448 break;
449 case 1400:
450 tmds_setting->max_vres = 1050;
451 break;
452 case 1440:
453 tmds_setting->max_vres = 1050;
454 break;
455 case 1600:
456 tmds_setting->max_vres = 1200;
457 break;
458 default: 374 default:
459 DEBUG_MSG(KERN_INFO "Unknown panel size max resolution = %d! " 375 {
460 "set default panel size.\n", tmds_setting->max_hres); 376 break;
461 break; 377 }
462 } 378 }
463
464 tmds_chip->tmds_chip_slave_addr = restore;
465} 379}
466 380
467/* If Disable DVI, turn off pad */ 381static void dvi_patch_skew_dvp_low(void)
468void viafb_dvi_disable(void)
469{ 382{
470 if (viaparinfo->chip_info-> 383 switch (viaparinfo->chip_info->gfx_chip_name) {
471 tmds_chip_info.output_interface == INTERFACE_DVP0) 384 case UNICHROME_K8M890:
472 viafb_write_reg(SR1E, VIASR, 385 {
473 viafb_read_reg(VIASR, SR1E) & (~0xC0)); 386 viafb_write_reg_mask(CR99, VIACR, 0x03, BIT0 + BIT1);
474 387 break;
475 if (viaparinfo->chip_info-> 388 }
476 tmds_chip_info.output_interface == INTERFACE_DVP1)
477 viafb_write_reg(SR1E, VIASR,
478 viafb_read_reg(VIASR, SR1E) & (~0x30));
479 389
480 if (viaparinfo->chip_info-> 390 case UNICHROME_P4M900:
481 tmds_chip_info.output_interface == INTERFACE_DFP_HIGH) 391 {
482 viafb_write_reg(SR2A, VIASR, 392 viafb_write_reg_mask(CR99, VIACR, 0x08,
483 viafb_read_reg(VIASR, SR2A) & (~0x0C)); 393 BIT0 + BIT1 + BIT2 + BIT3);
394 break;
395 }
484 396
485 if (viaparinfo->chip_info-> 397 case UNICHROME_P4M890:
486 tmds_chip_info.output_interface == INTERFACE_DFP_LOW) 398 {
487 viafb_write_reg(SR2A, VIASR, 399 viafb_write_reg_mask(CR99, VIACR, 0x0F,
488 viafb_read_reg(VIASR, SR2A) & (~0x03)); 400 BIT0 + BIT1 + BIT2 + BIT3);
401 break;
402 }
489 403
490 if (viaparinfo->chip_info-> 404 default:
491 tmds_chip_info.output_interface == INTERFACE_TMDS) 405 {
492 /* Turn off TMDS power. */ 406 break;
493 viafb_write_reg(CRD2, VIACR, 407 }
494 viafb_read_reg(VIACR, CRD2) | 0x08); 408 }
495} 409}
496 410
497/* If Enable DVI, turn off pad */ 411/* If Enable DVI, turn off pad */
@@ -499,33 +413,30 @@ void viafb_dvi_enable(void)
499{ 413{
500 u8 data; 414 u8 data;
501 415
502 if (viaparinfo->chip_info-> 416 switch (viaparinfo->chip_info->tmds_chip_info.output_interface) {
503 tmds_chip_info.output_interface == INTERFACE_DVP0) { 417 case INTERFACE_DVP0:
504 viafb_write_reg(SR1E, VIASR, 418 viafb_write_reg_mask(CR6B, VIACR, 0x01, BIT0);
505 viafb_read_reg(VIASR, SR1E) | 0xC0); 419 viafb_write_reg_mask(CR6C, VIACR, 0x21, BIT0 + BIT5);
420 dvi_patch_skew_dvp0();
506 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) 421 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
507 tmds_register_write(0x88, 0x3b); 422 tmds_register_write(0x88, 0x3b);
508 else 423 else
509 /*clear CR91[5] to direct on display period 424 /*clear CR91[5] to direct on display period
510 in the secondary diplay path */ 425 in the secondary diplay path */
511 viafb_write_reg(CR91, VIACR, 426 via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
512 viafb_read_reg(VIACR, CR91) & 0xDF); 427 break;
513 }
514 428
515 if (viaparinfo->chip_info-> 429 case INTERFACE_DVP1:
516 tmds_chip_info.output_interface == INTERFACE_DVP1) { 430 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
517 viafb_write_reg(SR1E, VIASR, 431 viafb_write_reg_mask(CR93, VIACR, 0x21, BIT0 + BIT5);
518 viafb_read_reg(VIASR, SR1E) | 0x30);
519 432
520 /*fix dvi cann't be enabled with MB VT5718C4 - Al Zhang */ 433 /*fix dvi cann't be enabled with MB VT5718C4 - Al Zhang */
521 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) { 434 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
522 tmds_register_write(0x88, 0x3b); 435 tmds_register_write(0x88, 0x3b);
523 } else { 436 else
524 /*clear CR91[5] to direct on display period 437 /*clear CR91[5] to direct on display period
525 in the secondary diplay path */ 438 in the secondary diplay path */
526 viafb_write_reg(CR91, VIACR, 439 via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
527 viafb_read_reg(VIACR, CR91) & 0xDF);
528 }
529 440
530 /*fix DVI cannot enable on EPIA-M board */ 441 /*fix DVI cannot enable on EPIA-M board */
531 if (viafb_platform_epia_dvi == 1) { 442 if (viafb_platform_epia_dvi == 1) {
@@ -537,36 +448,40 @@ void viafb_dvi_enable(void)
537 else 448 else
538 data = 0x37; 449 data = 0x37;
539 viafb_i2c_writebyte(viaparinfo->chip_info-> 450 viafb_i2c_writebyte(viaparinfo->chip_info->
540 tmds_chip_info.i2c_port, 451 tmds_chip_info.i2c_port,
541 viaparinfo->chip_info-> 452 viaparinfo->chip_info->
542 tmds_chip_info.tmds_chip_slave_addr, 453 tmds_chip_info.tmds_chip_slave_addr,
543 0x08, data); 454 0x08, data);
544 } 455 }
545 } 456 }
546 } 457 break;
547 458
548 if (viaparinfo->chip_info-> 459 case INTERFACE_DFP_HIGH:
549 tmds_chip_info.output_interface == INTERFACE_DFP_HIGH) { 460 if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
550 viafb_write_reg(SR2A, VIASR, 461 via_write_reg_mask(VIACR, CR97, 0x03, 0x03);
551 viafb_read_reg(VIASR, SR2A) | 0x0C);
552 viafb_write_reg(CR91, VIACR,
553 viafb_read_reg(VIACR, CR91) & 0xDF);
554 }
555 462
556 if (viaparinfo->chip_info-> 463 via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
557 tmds_chip_info.output_interface == INTERFACE_DFP_LOW) { 464 break;
558 viafb_write_reg(SR2A, VIASR, 465
559 viafb_read_reg(VIASR, SR2A) | 0x03); 466 case INTERFACE_DFP_LOW:
560 viafb_write_reg(CR91, VIACR, 467 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
561 viafb_read_reg(VIACR, CR91) & 0xDF); 468 break;
562 } 469
563 if (viaparinfo->chip_info-> 470 dvi_patch_skew_dvp_low();
564 tmds_chip_info.output_interface == INTERFACE_TMDS) { 471 via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
472 break;
473
474 case INTERFACE_TMDS:
565 /* Turn on Display period in the panel path. */ 475 /* Turn on Display period in the panel path. */
566 viafb_write_reg_mask(CR91, VIACR, 0, BIT7); 476 viafb_write_reg_mask(CR91, VIACR, 0, BIT7);
567 477
568 /* Turn on TMDS power. */ 478 /* Turn on TMDS power. */
569 viafb_write_reg_mask(CRD2, VIACR, 0, BIT3); 479 viafb_write_reg_mask(CRD2, VIACR, 0, BIT3);
480 break;
570 } 481 }
571}
572 482
483 if (viaparinfo->tmds_setting_info->iga_path == IGA2) {
484 /* Disable LCD Scaling */
485 viafb_write_reg_mask(CR79, VIACR, 0x00, BIT0);
486 }
487}
diff --git a/drivers/video/via/dvi.h b/drivers/video/via/dvi.h
index 0dffcfd395f3..f473dd010977 100644
--- a/drivers/video/via/dvi.h
+++ b/drivers/video/via/dvi.h
@@ -56,8 +56,8 @@
56int viafb_dvi_sense(void); 56int viafb_dvi_sense(void);
57void viafb_dvi_disable(void); 57void viafb_dvi_disable(void);
58void viafb_dvi_enable(void); 58void viafb_dvi_enable(void);
59int viafb_tmds_trasmitter_identify(void); 59bool __devinit viafb_tmds_trasmitter_identify(void);
60void viafb_init_dvi_size(struct tmds_chip_information *tmds_chip, 60void __devinit viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
61 struct tmds_setting_information *tmds_setting); 61 struct tmds_setting_information *tmds_setting);
62void viafb_dvi_set_mode(struct VideoModeTable *videoMode, int mode_bpp, 62void viafb_dvi_set_mode(struct VideoModeTable *videoMode, int mode_bpp,
63 int set_iga); 63 int set_iga);
diff --git a/drivers/video/via/global.c b/drivers/video/via/global.c
index 1ee511b73307..e10d8249534c 100644
--- a/drivers/video/via/global.c
+++ b/drivers/video/via/global.c
@@ -40,10 +40,6 @@ int viafb_hotplug_Yres = 480;
40int viafb_hotplug_bpp = 32; 40int viafb_hotplug_bpp = 32;
41int viafb_hotplug_refresh = 60; 41int viafb_hotplug_refresh = 60;
42int viafb_primary_dev = None_Device; 42int viafb_primary_dev = None_Device;
43unsigned int viafb_second_xres = 640;
44unsigned int viafb_second_yres = 480;
45unsigned int viafb_second_virtual_xres;
46unsigned int viafb_second_virtual_yres;
47int viafb_lcd_panel_id = LCD_PANEL_ID_MAXIMUM + 1; 43int viafb_lcd_panel_id = LCD_PANEL_ID_MAXIMUM + 1;
48struct fb_info *viafbinfo; 44struct fb_info *viafbinfo;
49struct fb_info *viafbinfo1; 45struct fb_info *viafbinfo1;
diff --git a/drivers/video/via/global.h b/drivers/video/via/global.h
index 28221a062dda..ff969dc34593 100644
--- a/drivers/video/via/global.h
+++ b/drivers/video/via/global.h
@@ -48,7 +48,6 @@
48#include "via_utility.h" 48#include "via_utility.h"
49#include "vt1636.h" 49#include "vt1636.h"
50#include "tblDPASetting.h" 50#include "tblDPASetting.h"
51#include "tbl1636.h"
52 51
53/* External struct*/ 52/* External struct*/
54 53
@@ -74,8 +73,6 @@ extern int viafb_hotplug_bpp;
74extern int viafb_hotplug_refresh; 73extern int viafb_hotplug_refresh;
75extern int viafb_primary_dev; 74extern int viafb_primary_dev;
76 75
77extern unsigned int viafb_second_xres;
78extern unsigned int viafb_second_yres;
79extern int viafb_lcd_panel_id; 76extern int viafb_lcd_panel_id;
80 77
81#endif /* __GLOBAL_H__ */ 78#endif /* __GLOBAL_H__ */
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index 7dcb4d5bb9c3..47b13535ed2b 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -20,344 +20,138 @@
20 */ 20 */
21 21
22#include <linux/via-core.h> 22#include <linux/via-core.h>
23#include <asm/olpc.h>
23#include "global.h" 24#include "global.h"
25#include "via_clock.h"
26
27static struct pll_limit cle266_pll_limits[] = {
28 {19, 19, 4, 0},
29 {26, 102, 5, 0},
30 {53, 112, 6, 0},
31 {41, 100, 7, 0},
32 {83, 108, 8, 0},
33 {87, 118, 9, 0},
34 {95, 115, 12, 0},
35 {108, 108, 13, 0},
36 {83, 83, 17, 0},
37 {67, 98, 20, 0},
38 {121, 121, 24, 0},
39 {99, 99, 29, 0},
40 {33, 33, 3, 1},
41 {15, 23, 4, 1},
42 {37, 121, 5, 1},
43 {82, 82, 6, 1},
44 {31, 84, 7, 1},
45 {83, 83, 8, 1},
46 {76, 127, 9, 1},
47 {33, 121, 4, 2},
48 {91, 118, 5, 2},
49 {83, 109, 6, 2},
50 {90, 90, 7, 2},
51 {93, 93, 2, 3},
52 {53, 53, 3, 3},
53 {73, 117, 4, 3},
54 {101, 127, 5, 3},
55 {99, 99, 7, 3}
56};
57
58static struct pll_limit k800_pll_limits[] = {
59 {22, 22, 2, 0},
60 {28, 28, 3, 0},
61 {81, 112, 3, 1},
62 {86, 166, 4, 1},
63 {109, 153, 5, 1},
64 {66, 116, 3, 2},
65 {93, 137, 4, 2},
66 {117, 208, 5, 2},
67 {30, 30, 2, 3},
68 {69, 125, 3, 3},
69 {89, 161, 4, 3},
70 {121, 208, 5, 3},
71 {66, 66, 2, 4},
72 {85, 85, 3, 4},
73 {141, 161, 4, 4},
74 {177, 177, 5, 4}
75};
24 76
25static struct pll_map pll_value[] = { 77static struct pll_limit cx700_pll_limits[] = {
26 {25175000, 78 {98, 98, 3, 1},
27 {99, 7, 3}, 79 {86, 86, 4, 1},
28 {85, 3, 4}, /* ignoring bit difference: 0x00008000 */ 80 {109, 208, 5, 1},
29 {141, 5, 4}, 81 {68, 68, 2, 2},
30 {141, 5, 4} }, 82 {95, 116, 3, 2},
31 {29581000, 83 {93, 166, 4, 2},
32 {33, 4, 2}, 84 {110, 206, 5, 2},
33 {66, 2, 4}, /* ignoring bit difference: 0x00808000 */ 85 {174, 174, 7, 2},
34 {166, 5, 4}, /* ignoring bit difference: 0x00008000 */ 86 {82, 109, 3, 3},
35 {165, 5, 4} }, 87 {117, 161, 4, 3},
36 {26880000, 88 {112, 208, 5, 3},
37 {15, 4, 1}, 89 {141, 202, 5, 4}
38 {30, 2, 3}, /* ignoring bit difference: 0x00808000 */ 90};
39 {150, 5, 4}, 91
40 {150, 5, 4} }, 92static struct pll_limit vx855_pll_limits[] = {
41 {31500000, 93 {86, 86, 4, 1},
42 {53, 3, 3}, /* ignoring bit difference: 0x00008000 */ 94 {108, 208, 5, 1},
43 {141, 4, 4}, /* ignoring bit difference: 0x00008000 */ 95 {110, 208, 5, 2},
44 {176, 5, 4}, 96 {83, 112, 3, 3},
45 {176, 5, 4} }, 97 {103, 161, 4, 3},
46 {31728000, 98 {112, 209, 5, 3},
47 {31, 7, 1}, 99 {142, 161, 4, 4},
48 {177, 5, 4}, /* ignoring bit difference: 0x00008000 */ 100 {141, 176, 5, 4}
49 {177, 5, 4}, 101};
50 {142, 4, 4} }, 102
51 {32688000, 103/* according to VIA Technologies these values are based on experiment */
52 {73, 4, 3}, 104static struct io_reg scaling_parameters[] = {
53 {146, 4, 4}, /* ignoring bit difference: 0x00008000 */ 105 {VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */
54 {183, 5, 4}, 106 {VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */
55 {146, 4, 4} }, 107 {VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */
56 {36000000, 108 {VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */
57 {101, 5, 3}, /* ignoring bit difference: 0x00008000 */ 109 {VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */
58 {161, 4, 4}, /* ignoring bit difference: 0x00008000 */ 110 {VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */
59 {202, 5, 4}, 111 {VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */
60 {161, 4, 4} }, 112 {VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */
61 {40000000, 113 {VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */
62 {89, 4, 3}, 114 {VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */
63 {89, 4, 3}, /* ignoring bit difference: 0x00008000 */ 115 {VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */
64 {112, 5, 3}, 116 {VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */
65 {112, 5, 3} }, 117 {VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */
66 {41291000, 118 {VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */
67 {23, 4, 1}, 119};
68 {69, 3, 3}, /* ignoring bit difference: 0x00008000 */ 120
69 {115, 5, 3}, 121static struct io_reg common_vga[] = {
70 {115, 5, 3} }, 122 {VIACR, CR07, 0x10, 0x10}, /* [0] vertical total (bit 8)
71 {43163000, 123 [1] vertical display end (bit 8)
72 {121, 5, 3}, 124 [2] vertical retrace start (bit 8)
73 {121, 5, 3}, /* ignoring bit difference: 0x00008000 */ 125 [3] start vertical blanking (bit 8)
74 {121, 5, 3}, 126 [4] line compare (bit 8)
75 {121, 5, 3} }, 127 [5] vertical total (bit 9)
76 {45250000, 128 [6] vertical display end (bit 9)
77 {127, 5, 3}, 129 [7] vertical retrace start (bit 9) */
78 {127, 5, 3}, /* ignoring bit difference: 0x00808000 */ 130 {VIACR, CR08, 0xFF, 0x00}, /* [0-4] preset row scan
79 {127, 5, 3}, 131 [5-6] byte panning */
80 {127, 5, 3} }, 132 {VIACR, CR09, 0xDF, 0x40}, /* [0-4] max scan line
81 {46000000, 133 [5] start vertical blanking (bit 9)
82 {90, 7, 2}, 134 [6] line compare (bit 9)
83 {103, 4, 3}, /* ignoring bit difference: 0x00008000 */ 135 [7] scan doubling */
84 {129, 5, 3}, 136 {VIACR, CR0A, 0xFF, 0x1E}, /* [0-4] cursor start
85 {103, 4, 3} }, 137 [5] cursor disable */
86 {46996000, 138 {VIACR, CR0B, 0xFF, 0x00}, /* [0-4] cursor end
87 {105, 4, 3}, /* ignoring bit difference: 0x00008000 */ 139 [5-6] cursor skew */
88 {131, 5, 3}, /* ignoring bit difference: 0x00808000 */ 140 {VIACR, CR0E, 0xFF, 0x00}, /* [0-7] cursor location (high) */
89 {131, 5, 3}, /* ignoring bit difference: 0x00808000 */ 141 {VIACR, CR0F, 0xFF, 0x00}, /* [0-7] cursor location (low) */
90 {105, 4, 3} }, 142 {VIACR, CR11, 0xF0, 0x80}, /* [0-3] vertical retrace end
91 {48000000, 143 [6] memory refresh bandwidth
92 {67, 20, 0}, 144 [7] CRTC register protect enable */
93 {134, 5, 3}, /* ignoring bit difference: 0x00808000 */ 145 {VIACR, CR14, 0xFF, 0x00}, /* [0-4] underline location
94 {134, 5, 3}, 146 [5] divide memory address clock by 4
95 {134, 5, 3} }, 147 [6] double word addressing */
96 {48875000, 148 {VIACR, CR17, 0xFF, 0x63}, /* [0-1] mapping of display address 13-14
97 {99, 29, 0}, 149 [2] divide scan line clock by 2
98 {82, 3, 3}, /* ignoring bit difference: 0x00808000 */ 150 [3] divide memory address clock by 2
99 {82, 3, 3}, /* ignoring bit difference: 0x00808000 */ 151 [5] address wrap
100 {137, 5, 3} }, 152 [6] byte mode select
101 {49500000, 153 [7] sync enable */
102 {83, 6, 2}, 154 {VIACR, CR18, 0xFF, 0xFF}, /* [0-7] line compare */
103 {83, 3, 3}, /* ignoring bit difference: 0x00008000 */
104 {138, 5, 3},
105 {83, 3, 3} },
106 {52406000,
107 {117, 4, 3},
108 {117, 4, 3}, /* ignoring bit difference: 0x00008000 */
109 {117, 4, 3},
110 {88, 3, 3} },
111 {52977000,
112 {37, 5, 1},
113 {148, 5, 3}, /* ignoring bit difference: 0x00808000 */
114 {148, 5, 3},
115 {148, 5, 3} },
116 {56250000,
117 {55, 7, 1}, /* ignoring bit difference: 0x00008000 */
118 {126, 4, 3}, /* ignoring bit difference: 0x00008000 */
119 {157, 5, 3},
120 {157, 5, 3} },
121 {57275000,
122 {0, 0, 0},
123 {2, 2, 0},
124 {2, 2, 0},
125 {157, 5, 3} }, /* ignoring bit difference: 0x00808000 */
126 {60466000,
127 {76, 9, 1},
128 {169, 5, 3}, /* ignoring bit difference: 0x00808000 */
129 {169, 5, 3}, /* FIXED: old = {72, 2, 3} */
130 {169, 5, 3} },
131 {61500000,
132 {86, 20, 0},
133 {172, 5, 3}, /* ignoring bit difference: 0x00808000 */
134 {172, 5, 3},
135 {172, 5, 3} },
136 {65000000,
137 {109, 6, 2}, /* ignoring bit difference: 0x00008000 */
138 {109, 3, 3}, /* ignoring bit difference: 0x00008000 */
139 {109, 3, 3},
140 {109, 3, 3} },
141 {65178000,
142 {91, 5, 2},
143 {182, 5, 3}, /* ignoring bit difference: 0x00808000 */
144 {109, 3, 3},
145 {182, 5, 3} },
146 {66750000,
147 {75, 4, 2},
148 {150, 4, 3}, /* ignoring bit difference: 0x00808000 */
149 {150, 4, 3},
150 {112, 3, 3} },
151 {68179000,
152 {19, 4, 0},
153 {114, 3, 3}, /* ignoring bit difference: 0x00008000 */
154 {190, 5, 3},
155 {191, 5, 3} },
156 {69924000,
157 {83, 17, 0},
158 {195, 5, 3}, /* ignoring bit difference: 0x00808000 */
159 {195, 5, 3},
160 {195, 5, 3} },
161 {70159000,
162 {98, 20, 0},
163 {196, 5, 3}, /* ignoring bit difference: 0x00808000 */
164 {196, 5, 3},
165 {195, 5, 3} },
166 {72000000,
167 {121, 24, 0},
168 {161, 4, 3}, /* ignoring bit difference: 0x00808000 */
169 {161, 4, 3},
170 {161, 4, 3} },
171 {78750000,
172 {33, 3, 1},
173 {66, 3, 2}, /* ignoring bit difference: 0x00008000 */
174 {110, 5, 2},
175 {110, 5, 2} },
176 {80136000,
177 {28, 5, 0},
178 {68, 3, 2}, /* ignoring bit difference: 0x00008000 */
179 {112, 5, 2},
180 {112, 5, 2} },
181 {83375000,
182 {93, 2, 3},
183 {93, 4, 2}, /* ignoring bit difference: 0x00800000 */
184 {93, 4, 2}, /* ignoring bit difference: 0x00800000 */
185 {117, 5, 2} },
186 {83950000,
187 {41, 7, 0},
188 {117, 5, 2}, /* ignoring bit difference: 0x00008000 */
189 {117, 5, 2},
190 {117, 5, 2} },
191 {84750000,
192 {118, 5, 2},
193 {118, 5, 2}, /* ignoring bit difference: 0x00808000 */
194 {118, 5, 2},
195 {118, 5, 2} },
196 {85860000,
197 {84, 7, 1},
198 {120, 5, 2}, /* ignoring bit difference: 0x00808000 */
199 {120, 5, 2},
200 {118, 5, 2} },
201 {88750000,
202 {31, 5, 0},
203 {124, 5, 2}, /* ignoring bit difference: 0x00808000 */
204 {174, 7, 2}, /* ignoring bit difference: 0x00808000 */
205 {124, 5, 2} },
206 {94500000,
207 {33, 5, 0},
208 {132, 5, 2}, /* ignoring bit difference: 0x00008000 */
209 {132, 5, 2},
210 {132, 5, 2} },
211 {97750000,
212 {82, 6, 1},
213 {137, 5, 2}, /* ignoring bit difference: 0x00808000 */
214 {137, 5, 2},
215 {137, 5, 2} },
216 {101000000,
217 {127, 9, 1},
218 {141, 5, 2}, /* ignoring bit difference: 0x00808000 */
219 {141, 5, 2},
220 {141, 5, 2} },
221 {106500000,
222 {119, 4, 2},
223 {119, 4, 2}, /* ignoring bit difference: 0x00808000 */
224 {119, 4, 2},
225 {149, 5, 2} },
226 {108000000,
227 {121, 4, 2},
228 {121, 4, 2}, /* ignoring bit difference: 0x00808000 */
229 {151, 5, 2},
230 {151, 5, 2} },
231 {113309000,
232 {95, 12, 0},
233 {95, 3, 2}, /* ignoring bit difference: 0x00808000 */
234 {95, 3, 2},
235 {159, 5, 2} },
236 {118840000,
237 {83, 5, 1},
238 {166, 5, 2}, /* ignoring bit difference: 0x00808000 */
239 {166, 5, 2},
240 {166, 5, 2} },
241 {119000000,
242 {108, 13, 0},
243 {133, 4, 2}, /* ignoring bit difference: 0x00808000 */
244 {133, 4, 2},
245 {167, 5, 2} },
246 {121750000,
247 {85, 5, 1},
248 {170, 5, 2}, /* ignoring bit difference: 0x00808000 */
249 {68, 2, 2},
250 {0, 0, 0} },
251 {125104000,
252 {53, 6, 0}, /* ignoring bit difference: 0x00008000 */
253 {106, 3, 2}, /* ignoring bit difference: 0x00008000 */
254 {175, 5, 2},
255 {0, 0, 0} },
256 {135000000,
257 {94, 5, 1},
258 {28, 3, 0}, /* ignoring bit difference: 0x00804000 */
259 {151, 4, 2},
260 {189, 5, 2} },
261 {136700000,
262 {115, 12, 0},
263 {191, 5, 2}, /* ignoring bit difference: 0x00808000 */
264 {191, 5, 2},
265 {191, 5, 2} },
266 {138400000,
267 {87, 9, 0},
268 {116, 3, 2}, /* ignoring bit difference: 0x00808000 */
269 {116, 3, 2},
270 {194, 5, 2} },
271 {146760000,
272 {103, 5, 1},
273 {206, 5, 2}, /* ignoring bit difference: 0x00808000 */
274 {206, 5, 2},
275 {206, 5, 2} },
276 {153920000,
277 {86, 8, 0},
278 {86, 4, 1}, /* ignoring bit difference: 0x00808000 */
279 {86, 4, 1},
280 {86, 4, 1} }, /* FIXED: old = {84, 2, 1} */
281 {156000000,
282 {109, 5, 1},
283 {109, 5, 1}, /* ignoring bit difference: 0x00808000 */
284 {109, 5, 1},
285 {108, 5, 1} },
286 {157500000,
287 {55, 5, 0}, /* ignoring bit difference: 0x00008000 */
288 {22, 2, 0}, /* ignoring bit difference: 0x00802000 */
289 {110, 5, 1},
290 {110, 5, 1} },
291 {162000000,
292 {113, 5, 1},
293 {113, 5, 1}, /* ignoring bit difference: 0x00808000 */
294 {113, 5, 1},
295 {113, 5, 1} },
296 {187000000,
297 {118, 9, 0},
298 {131, 5, 1}, /* ignoring bit difference: 0x00808000 */
299 {131, 5, 1},
300 {131, 5, 1} },
301 {193295000,
302 {108, 8, 0},
303 {81, 3, 1}, /* ignoring bit difference: 0x00808000 */
304 {135, 5, 1},
305 {135, 5, 1} },
306 {202500000,
307 {99, 7, 0},
308 {85, 3, 1}, /* ignoring bit difference: 0x00808000 */
309 {142, 5, 1},
310 {142, 5, 1} },
311 {204000000,
312 {100, 7, 0},
313 {143, 5, 1}, /* ignoring bit difference: 0x00808000 */
314 {143, 5, 1},
315 {143, 5, 1} },
316 {218500000,
317 {92, 6, 0},
318 {153, 5, 1}, /* ignoring bit difference: 0x00808000 */
319 {153, 5, 1},
320 {153, 5, 1} },
321 {234000000,
322 {98, 6, 0},
323 {98, 3, 1}, /* ignoring bit difference: 0x00008000 */
324 {98, 3, 1},
325 {164, 5, 1} },
326 {267250000,
327 {112, 6, 0},
328 {112, 3, 1}, /* ignoring bit difference: 0x00808000 */
329 {187, 5, 1},
330 {187, 5, 1} },
331 {297500000,
332 {102, 5, 0}, /* ignoring bit difference: 0x00008000 */
333 {166, 4, 1}, /* ignoring bit difference: 0x00008000 */
334 {208, 5, 1},
335 {208, 5, 1} },
336 {74481000,
337 {26, 5, 0},
338 {125, 3, 3}, /* ignoring bit difference: 0x00808000 */
339 {208, 5, 3},
340 {209, 5, 3} },
341 {172798000,
342 {121, 5, 1},
343 {121, 5, 1}, /* ignoring bit difference: 0x00808000 */
344 {121, 5, 1},
345 {121, 5, 1} },
346 {122614000,
347 {60, 7, 0},
348 {137, 4, 2}, /* ignoring bit difference: 0x00808000 */
349 {137, 4, 2},
350 {172, 5, 2} },
351 {74270000,
352 {83, 8, 1},
353 {208, 5, 3},
354 {208, 5, 3},
355 {0, 0, 0} },
356 {148500000,
357 {83, 8, 0},
358 {208, 5, 2},
359 {166, 4, 2},
360 {208, 5, 2} }
361}; 155};
362 156
363static struct fifo_depth_select display_fifo_depth_reg = { 157static struct fifo_depth_select display_fifo_depth_reg = {
@@ -718,16 +512,23 @@ static struct rgbLUT palLUT_table[] = {
718 0x00} 512 0x00}
719}; 513};
720 514
721static void set_crt_output_path(int set_iga); 515static struct via_device_mapping device_mapping[] = {
722static void dvi_patch_skew_dvp0(void); 516 {VIA_LDVP0, "LDVP0"},
723static void dvi_patch_skew_dvp1(void); 517 {VIA_LDVP1, "LDVP1"},
724static void dvi_patch_skew_dvp_low(void); 518 {VIA_DVP0, "DVP0"},
725static void set_dvi_output_path(int set_iga, int output_interface); 519 {VIA_CRT, "CRT"},
726static void set_lcd_output_path(int set_iga, int output_interface); 520 {VIA_DVP1, "DVP1"},
521 {VIA_LVDS1, "LVDS1"},
522 {VIA_LVDS2, "LVDS2"}
523};
524
525/* structure with function pointers to support clock control */
526static struct via_clock clock;
527
727static void load_fix_bit_crtc_reg(void); 528static void load_fix_bit_crtc_reg(void);
728static void init_gfx_chip_info(int chip_type); 529static void __devinit init_gfx_chip_info(int chip_type);
729static void init_tmds_chip_info(void); 530static void __devinit init_tmds_chip_info(void);
730static void init_lvds_chip_info(void); 531static void __devinit init_lvds_chip_info(void);
731static void device_screen_off(void); 532static void device_screen_off(void);
732static void device_screen_on(void); 533static void device_screen_on(void);
733static void set_display_channel(void); 534static void set_display_channel(void);
@@ -747,7 +548,7 @@ void viafb_unlock_crt(void)
747 viafb_write_reg_mask(CR47, VIACR, 0, BIT0); 548 viafb_write_reg_mask(CR47, VIACR, 0, BIT0);
748} 549}
749 550
750void write_dac_reg(u8 index, u8 r, u8 g, u8 b) 551static void write_dac_reg(u8 index, u8 r, u8 g, u8 b)
751{ 552{
752 outb(index, LUT_INDEX_WRITE); 553 outb(index, LUT_INDEX_WRITE);
753 outb(r, LUT_DATA); 554 outb(r, LUT_DATA);
@@ -755,16 +556,77 @@ void write_dac_reg(u8 index, u8 r, u8 g, u8 b)
755 outb(b, LUT_DATA); 556 outb(b, LUT_DATA);
756} 557}
757 558
559static u32 get_dvi_devices(int output_interface)
560{
561 switch (output_interface) {
562 case INTERFACE_DVP0:
563 return VIA_DVP0 | VIA_LDVP0;
564
565 case INTERFACE_DVP1:
566 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
567 return VIA_LDVP1;
568 else
569 return VIA_DVP1;
570
571 case INTERFACE_DFP_HIGH:
572 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
573 return 0;
574 else
575 return VIA_LVDS2 | VIA_DVP0;
576
577 case INTERFACE_DFP_LOW:
578 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
579 return 0;
580 else
581 return VIA_DVP1 | VIA_LVDS1;
582
583 case INTERFACE_TMDS:
584 return VIA_LVDS1;
585 }
586
587 return 0;
588}
589
590static u32 get_lcd_devices(int output_interface)
591{
592 switch (output_interface) {
593 case INTERFACE_DVP0:
594 return VIA_DVP0;
595
596 case INTERFACE_DVP1:
597 return VIA_DVP1;
598
599 case INTERFACE_DFP_HIGH:
600 return VIA_LVDS2 | VIA_DVP0;
601
602 case INTERFACE_DFP_LOW:
603 return VIA_LVDS1 | VIA_DVP1;
604
605 case INTERFACE_DFP:
606 return VIA_LVDS1 | VIA_LVDS2;
607
608 case INTERFACE_LVDS0:
609 case INTERFACE_LVDS0LVDS1:
610 return VIA_LVDS1;
611
612 case INTERFACE_LVDS1:
613 return VIA_LVDS2;
614 }
615
616 return 0;
617}
618
758/*Set IGA path for each device*/ 619/*Set IGA path for each device*/
759void viafb_set_iga_path(void) 620void viafb_set_iga_path(void)
760{ 621{
622 int crt_iga_path = 0;
761 623
762 if (viafb_SAMM_ON == 1) { 624 if (viafb_SAMM_ON == 1) {
763 if (viafb_CRT_ON) { 625 if (viafb_CRT_ON) {
764 if (viafb_primary_dev == CRT_Device) 626 if (viafb_primary_dev == CRT_Device)
765 viaparinfo->crt_setting_info->iga_path = IGA1; 627 crt_iga_path = IGA1;
766 else 628 else
767 viaparinfo->crt_setting_info->iga_path = IGA2; 629 crt_iga_path = IGA2;
768 } 630 }
769 631
770 if (viafb_DVI_ON) { 632 if (viafb_DVI_ON) {
@@ -781,8 +643,7 @@ void viafb_set_iga_path(void)
781 UNICHROME_CLE266)) { 643 UNICHROME_CLE266)) {
782 viaparinfo-> 644 viaparinfo->
783 lvds_setting_info->iga_path = IGA2; 645 lvds_setting_info->iga_path = IGA2;
784 viaparinfo-> 646 crt_iga_path = IGA1;
785 crt_setting_info->iga_path = IGA1;
786 viaparinfo-> 647 viaparinfo->
787 tmds_setting_info->iga_path = IGA1; 648 tmds_setting_info->iga_path = IGA1;
788 } else 649 } else
@@ -802,10 +663,10 @@ void viafb_set_iga_path(void)
802 viafb_SAMM_ON = 0; 663 viafb_SAMM_ON = 0;
803 664
804 if (viafb_CRT_ON && viafb_LCD_ON) { 665 if (viafb_CRT_ON && viafb_LCD_ON) {
805 viaparinfo->crt_setting_info->iga_path = IGA1; 666 crt_iga_path = IGA1;
806 viaparinfo->lvds_setting_info->iga_path = IGA2; 667 viaparinfo->lvds_setting_info->iga_path = IGA2;
807 } else if (viafb_CRT_ON && viafb_DVI_ON) { 668 } else if (viafb_CRT_ON && viafb_DVI_ON) {
808 viaparinfo->crt_setting_info->iga_path = IGA1; 669 crt_iga_path = IGA1;
809 viaparinfo->tmds_setting_info->iga_path = IGA2; 670 viaparinfo->tmds_setting_info->iga_path = IGA2;
810 } else if (viafb_LCD_ON && viafb_DVI_ON) { 671 } else if (viafb_LCD_ON && viafb_DVI_ON) {
811 viaparinfo->tmds_setting_info->iga_path = IGA1; 672 viaparinfo->tmds_setting_info->iga_path = IGA1;
@@ -814,13 +675,59 @@ void viafb_set_iga_path(void)
814 viaparinfo->lvds_setting_info->iga_path = IGA2; 675 viaparinfo->lvds_setting_info->iga_path = IGA2;
815 viaparinfo->lvds_setting_info2->iga_path = IGA2; 676 viaparinfo->lvds_setting_info2->iga_path = IGA2;
816 } else if (viafb_CRT_ON) { 677 } else if (viafb_CRT_ON) {
817 viaparinfo->crt_setting_info->iga_path = IGA1; 678 crt_iga_path = IGA1;
818 } else if (viafb_LCD_ON) { 679 } else if (viafb_LCD_ON) {
819 viaparinfo->lvds_setting_info->iga_path = IGA2; 680 viaparinfo->lvds_setting_info->iga_path = IGA2;
820 } else if (viafb_DVI_ON) { 681 } else if (viafb_DVI_ON) {
821 viaparinfo->tmds_setting_info->iga_path = IGA1; 682 viaparinfo->tmds_setting_info->iga_path = IGA1;
822 } 683 }
823 } 684 }
685
686 viaparinfo->shared->iga1_devices = 0;
687 viaparinfo->shared->iga2_devices = 0;
688 if (viafb_CRT_ON) {
689 if (crt_iga_path == IGA1)
690 viaparinfo->shared->iga1_devices |= VIA_CRT;
691 else
692 viaparinfo->shared->iga2_devices |= VIA_CRT;
693 }
694
695 if (viafb_DVI_ON) {
696 if (viaparinfo->tmds_setting_info->iga_path == IGA1)
697 viaparinfo->shared->iga1_devices |= get_dvi_devices(
698 viaparinfo->chip_info->
699 tmds_chip_info.output_interface);
700 else
701 viaparinfo->shared->iga2_devices |= get_dvi_devices(
702 viaparinfo->chip_info->
703 tmds_chip_info.output_interface);
704 }
705
706 if (viafb_LCD_ON) {
707 if (viaparinfo->lvds_setting_info->iga_path == IGA1)
708 viaparinfo->shared->iga1_devices |= get_lcd_devices(
709 viaparinfo->chip_info->
710 lvds_chip_info.output_interface);
711 else
712 viaparinfo->shared->iga2_devices |= get_lcd_devices(
713 viaparinfo->chip_info->
714 lvds_chip_info.output_interface);
715 }
716
717 if (viafb_LCD2_ON) {
718 if (viaparinfo->lvds_setting_info2->iga_path == IGA1)
719 viaparinfo->shared->iga1_devices |= get_lcd_devices(
720 viaparinfo->chip_info->
721 lvds_chip_info2.output_interface);
722 else
723 viaparinfo->shared->iga2_devices |= get_lcd_devices(
724 viaparinfo->chip_info->
725 lvds_chip_info2.output_interface);
726 }
727
728 /* looks like the OLPC has its display wired to DVP1 and LVDS2 */
729 if (machine_is_olpc())
730 viaparinfo->shared->iga2_devices = VIA_DVP1 | VIA_LVDS2;
824} 731}
825 732
826static void set_color_register(u8 index, u8 red, u8 green, u8 blue) 733static void set_color_register(u8 index, u8 red, u8 green, u8 blue)
@@ -844,318 +751,281 @@ void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue)
844 set_color_register(index, red, green, blue); 751 set_color_register(index, red, green, blue);
845} 752}
846 753
847void viafb_set_output_path(int device, int set_iga, int output_interface) 754static void set_source_common(u8 index, u8 offset, u8 iga)
848{ 755{
849 switch (device) { 756 u8 value, mask = 1 << offset;
850 case DEVICE_CRT: 757
851 set_crt_output_path(set_iga); 758 switch (iga) {
852 break; 759 case IGA1:
853 case DEVICE_DVI: 760 value = 0x00;
854 set_dvi_output_path(set_iga, output_interface);
855 break; 761 break;
856 case DEVICE_LCD: 762 case IGA2:
857 set_lcd_output_path(set_iga, output_interface); 763 value = mask;
858 break; 764 break;
765 default:
766 printk(KERN_WARNING "viafb: Unsupported source: %d\n", iga);
767 return;
859 } 768 }
769
770 via_write_reg_mask(VIACR, index, value, mask);
860} 771}
861 772
862static void set_crt_output_path(int set_iga) 773static void set_crt_source(u8 iga)
863{ 774{
864 viafb_write_reg_mask(CR36, VIACR, 0x00, BIT4 + BIT5); 775 u8 value;
865 776
866 switch (set_iga) { 777 switch (iga) {
867 case IGA1: 778 case IGA1:
868 viafb_write_reg_mask(SR16, VIASR, 0x00, BIT6); 779 value = 0x00;
869 break; 780 break;
870 case IGA2: 781 case IGA2:
871 viafb_write_reg_mask(CR6A, VIACR, 0xC0, BIT6 + BIT7); 782 value = 0x40;
872 viafb_write_reg_mask(SR16, VIASR, 0x40, BIT6);
873 break; 783 break;
784 default:
785 printk(KERN_WARNING "viafb: Unsupported source: %d\n", iga);
786 return;
874 } 787 }
788
789 via_write_reg_mask(VIASR, 0x16, value, 0x40);
875} 790}
876 791
877static void dvi_patch_skew_dvp0(void) 792static inline void set_ldvp0_source(u8 iga)
878{ 793{
879 /* Reset data driving first: */ 794 set_source_common(0x6C, 7, iga);
880 viafb_write_reg_mask(SR1B, VIASR, 0, BIT1); 795}
881 viafb_write_reg_mask(SR2A, VIASR, 0, BIT4);
882
883 switch (viaparinfo->chip_info->gfx_chip_name) {
884 case UNICHROME_P4M890:
885 {
886 if ((viaparinfo->tmds_setting_info->h_active == 1600) &&
887 (viaparinfo->tmds_setting_info->v_active ==
888 1200))
889 viafb_write_reg_mask(CR96, VIACR, 0x03,
890 BIT0 + BIT1 + BIT2);
891 else
892 viafb_write_reg_mask(CR96, VIACR, 0x07,
893 BIT0 + BIT1 + BIT2);
894 break;
895 }
896 796
897 case UNICHROME_P4M900: 797static inline void set_ldvp1_source(u8 iga)
898 { 798{
899 viafb_write_reg_mask(CR96, VIACR, 0x07, 799 set_source_common(0x93, 7, iga);
900 BIT0 + BIT1 + BIT2 + BIT3); 800}
901 viafb_write_reg_mask(SR1B, VIASR, 0x02, BIT1);
902 viafb_write_reg_mask(SR2A, VIASR, 0x10, BIT4);
903 break;
904 }
905 801
906 default: 802static inline void set_dvp0_source(u8 iga)
907 { 803{
908 break; 804 set_source_common(0x96, 4, iga);
909 }
910 }
911} 805}
912 806
913static void dvi_patch_skew_dvp1(void) 807static inline void set_dvp1_source(u8 iga)
914{ 808{
915 switch (viaparinfo->chip_info->gfx_chip_name) { 809 set_source_common(0x9B, 4, iga);
916 case UNICHROME_CX700: 810}
917 {
918 break;
919 }
920 811
921 default: 812static inline void set_lvds1_source(u8 iga)
922 { 813{
923 break; 814 set_source_common(0x99, 4, iga);
924 }
925 }
926} 815}
927 816
928static void dvi_patch_skew_dvp_low(void) 817static inline void set_lvds2_source(u8 iga)
929{ 818{
930 switch (viaparinfo->chip_info->gfx_chip_name) { 819 set_source_common(0x97, 4, iga);
931 case UNICHROME_K8M890: 820}
932 {
933 viafb_write_reg_mask(CR99, VIACR, 0x03, BIT0 + BIT1);
934 break;
935 }
936 821
937 case UNICHROME_P4M900: 822void via_set_source(u32 devices, u8 iga)
938 { 823{
939 viafb_write_reg_mask(CR99, VIACR, 0x08, 824 if (devices & VIA_LDVP0)
940 BIT0 + BIT1 + BIT2 + BIT3); 825 set_ldvp0_source(iga);
941 break; 826 if (devices & VIA_LDVP1)
942 } 827 set_ldvp1_source(iga);
828 if (devices & VIA_DVP0)
829 set_dvp0_source(iga);
830 if (devices & VIA_CRT)
831 set_crt_source(iga);
832 if (devices & VIA_DVP1)
833 set_dvp1_source(iga);
834 if (devices & VIA_LVDS1)
835 set_lvds1_source(iga);
836 if (devices & VIA_LVDS2)
837 set_lvds2_source(iga);
838}
943 839
944 case UNICHROME_P4M890: 840static void set_crt_state(u8 state)
945 { 841{
946 viafb_write_reg_mask(CR99, VIACR, 0x0F, 842 u8 value;
947 BIT0 + BIT1 + BIT2 + BIT3);
948 break;
949 }
950 843
844 switch (state) {
845 case VIA_STATE_ON:
846 value = 0x00;
847 break;
848 case VIA_STATE_STANDBY:
849 value = 0x10;
850 break;
851 case VIA_STATE_SUSPEND:
852 value = 0x20;
853 break;
854 case VIA_STATE_OFF:
855 value = 0x30;
856 break;
951 default: 857 default:
952 { 858 return;
953 break;
954 }
955 } 859 }
860
861 via_write_reg_mask(VIACR, 0x36, value, 0x30);
956} 862}
957 863
958static void set_dvi_output_path(int set_iga, int output_interface) 864static void set_dvp0_state(u8 state)
959{ 865{
960 switch (output_interface) { 866 u8 value;
961 case INTERFACE_DVP0:
962 viafb_write_reg_mask(CR6B, VIACR, 0x01, BIT0);
963
964 if (set_iga == IGA1) {
965 viafb_write_reg_mask(CR96, VIACR, 0x00, BIT4);
966 viafb_write_reg_mask(CR6C, VIACR, 0x21, BIT0 +
967 BIT5 + BIT7);
968 } else {
969 viafb_write_reg_mask(CR96, VIACR, 0x10, BIT4);
970 viafb_write_reg_mask(CR6C, VIACR, 0xA1, BIT0 +
971 BIT5 + BIT7);
972 }
973
974 viafb_write_reg_mask(SR1E, VIASR, 0xC0, BIT7 + BIT6);
975 867
976 dvi_patch_skew_dvp0(); 868 switch (state) {
869 case VIA_STATE_ON:
870 value = 0xC0;
871 break;
872 case VIA_STATE_OFF:
873 value = 0x00;
977 break; 874 break;
875 default:
876 return;
877 }
978 878
979 case INTERFACE_DVP1: 879 via_write_reg_mask(VIASR, 0x1E, value, 0xC0);
980 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) { 880}
981 if (set_iga == IGA1)
982 viafb_write_reg_mask(CR93, VIACR, 0x21,
983 BIT0 + BIT5 + BIT7);
984 else
985 viafb_write_reg_mask(CR93, VIACR, 0xA1,
986 BIT0 + BIT5 + BIT7);
987 } else {
988 if (set_iga == IGA1)
989 viafb_write_reg_mask(CR9B, VIACR, 0x00, BIT4);
990 else
991 viafb_write_reg_mask(CR9B, VIACR, 0x10, BIT4);
992 }
993 881
994 viafb_write_reg_mask(SR1E, VIASR, 0x30, BIT4 + BIT5); 882static void set_dvp1_state(u8 state)
995 dvi_patch_skew_dvp1(); 883{
884 u8 value;
885
886 switch (state) {
887 case VIA_STATE_ON:
888 value = 0x30;
996 break; 889 break;
997 case INTERFACE_DFP_HIGH: 890 case VIA_STATE_OFF:
998 if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266) { 891 value = 0x00;
999 if (set_iga == IGA1) {
1000 viafb_write_reg_mask(CR96, VIACR, 0x00, BIT4);
1001 viafb_write_reg_mask(CR97, VIACR, 0x03,
1002 BIT0 + BIT1 + BIT4);
1003 } else {
1004 viafb_write_reg_mask(CR96, VIACR, 0x10, BIT4);
1005 viafb_write_reg_mask(CR97, VIACR, 0x13,
1006 BIT0 + BIT1 + BIT4);
1007 }
1008 }
1009 viafb_write_reg_mask(SR2A, VIASR, 0x0C, BIT2 + BIT3);
1010 break; 892 break;
893 default:
894 return;
895 }
1011 896
1012 case INTERFACE_DFP_LOW: 897 via_write_reg_mask(VIASR, 0x1E, value, 0x30);
1013 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) 898}
1014 break;
1015 899
1016 if (set_iga == IGA1) { 900static void set_lvds1_state(u8 state)
1017 viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4); 901{
1018 viafb_write_reg_mask(CR9B, VIACR, 0x00, BIT4); 902 u8 value;
1019 } else {
1020 viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4);
1021 viafb_write_reg_mask(CR9B, VIACR, 0x10, BIT4);
1022 }
1023 903
1024 viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1); 904 switch (state) {
1025 dvi_patch_skew_dvp_low(); 905 case VIA_STATE_ON:
906 value = 0x03;
1026 break; 907 break;
1027 908 case VIA_STATE_OFF:
1028 case INTERFACE_TMDS: 909 value = 0x00;
1029 if (set_iga == IGA1)
1030 viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4);
1031 else
1032 viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4);
1033 break; 910 break;
911 default:
912 return;
1034 } 913 }
1035 914
1036 if (set_iga == IGA2) { 915 via_write_reg_mask(VIASR, 0x2A, value, 0x03);
1037 enable_second_display_channel();
1038 /* Disable LCD Scaling */
1039 viafb_write_reg_mask(CR79, VIACR, 0x00, BIT0);
1040 }
1041} 916}
1042 917
1043static void set_lcd_output_path(int set_iga, int output_interface) 918static void set_lvds2_state(u8 state)
1044{ 919{
1045 DEBUG_MSG(KERN_INFO 920 u8 value;
1046 "set_lcd_output_path, iga:%d,out_interface:%d\n",
1047 set_iga, output_interface);
1048 switch (set_iga) {
1049 case IGA1:
1050 viafb_write_reg_mask(CR6B, VIACR, 0x00, BIT3);
1051 viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
1052 921
1053 disable_second_display_channel(); 922 switch (state) {
923 case VIA_STATE_ON:
924 value = 0x0C;
1054 break; 925 break;
1055 926 case VIA_STATE_OFF:
1056 case IGA2: 927 value = 0x00;
1057 viafb_write_reg_mask(CR6B, VIACR, 0x00, BIT3);
1058 viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
1059
1060 enable_second_display_channel();
1061 break; 928 break;
929 default:
930 return;
1062 } 931 }
1063 932
1064 switch (output_interface) { 933 via_write_reg_mask(VIASR, 0x2A, value, 0x0C);
1065 case INTERFACE_DVP0: 934}
1066 if (set_iga == IGA1) {
1067 viafb_write_reg_mask(CR96, VIACR, 0x00, BIT4);
1068 } else {
1069 viafb_write_reg(CR91, VIACR, 0x00);
1070 viafb_write_reg_mask(CR96, VIACR, 0x10, BIT4);
1071 }
1072 break;
1073
1074 case INTERFACE_DVP1:
1075 if (set_iga == IGA1)
1076 viafb_write_reg_mask(CR9B, VIACR, 0x00, BIT4);
1077 else {
1078 viafb_write_reg(CR91, VIACR, 0x00);
1079 viafb_write_reg_mask(CR9B, VIACR, 0x10, BIT4);
1080 }
1081 break;
1082 935
1083 case INTERFACE_DFP_HIGH: 936void via_set_state(u32 devices, u8 state)
1084 if (set_iga == IGA1) 937{
1085 viafb_write_reg_mask(CR97, VIACR, 0x00, BIT4); 938 /*
1086 else { 939 TODO: Can we enable/disable these devices? How?
1087 viafb_write_reg(CR91, VIACR, 0x00); 940 if (devices & VIA_LDVP0)
1088 viafb_write_reg_mask(CR97, VIACR, 0x10, BIT4); 941 if (devices & VIA_LDVP1)
1089 viafb_write_reg_mask(CR96, VIACR, 0x10, BIT4); 942 */
1090 } 943 if (devices & VIA_DVP0)
1091 break; 944 set_dvp0_state(state);
945 if (devices & VIA_CRT)
946 set_crt_state(state);
947 if (devices & VIA_DVP1)
948 set_dvp1_state(state);
949 if (devices & VIA_LVDS1)
950 set_lvds1_state(state);
951 if (devices & VIA_LVDS2)
952 set_lvds2_state(state);
953}
1092 954
1093 case INTERFACE_DFP_LOW: 955void via_set_sync_polarity(u32 devices, u8 polarity)
1094 if (set_iga == IGA1) 956{
1095 viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4); 957 if (polarity & ~(VIA_HSYNC_NEGATIVE | VIA_VSYNC_NEGATIVE)) {
1096 else { 958 printk(KERN_WARNING "viafb: Unsupported polarity: %d\n",
1097 viafb_write_reg(CR91, VIACR, 0x00); 959 polarity);
1098 viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4); 960 return;
1099 viafb_write_reg_mask(CR9B, VIACR, 0x10, BIT4); 961 }
1100 }
1101 962
1102 break; 963 if (devices & VIA_CRT)
964 via_write_misc_reg_mask(polarity << 6, 0xC0);
965 if (devices & VIA_DVP1)
966 via_write_reg_mask(VIACR, 0x9B, polarity << 5, 0x60);
967 if (devices & VIA_LVDS1)
968 via_write_reg_mask(VIACR, 0x99, polarity << 5, 0x60);
969 if (devices & VIA_LVDS2)
970 via_write_reg_mask(VIACR, 0x97, polarity << 5, 0x60);
971}
1103 972
1104 case INTERFACE_DFP: 973u32 via_parse_odev(char *input, char **end)
1105 if ((UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name) 974{
1106 || (UNICHROME_P4M890 == 975 char *ptr = input;
1107 viaparinfo->chip_info->gfx_chip_name)) 976 u32 odev = 0;
1108 viafb_write_reg_mask(CR97, VIACR, 0x84, 977 bool next = true;
1109 BIT7 + BIT2 + BIT1 + BIT0); 978 int i, len;
1110 if (set_iga == IGA1) { 979
1111 viafb_write_reg_mask(CR97, VIACR, 0x00, BIT4); 980 while (next) {
1112 viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4); 981 next = false;
1113 } else { 982 for (i = 0; i < ARRAY_SIZE(device_mapping); i++) {
1114 viafb_write_reg(CR91, VIACR, 0x00); 983 len = strlen(device_mapping[i].name);
1115 viafb_write_reg_mask(CR97, VIACR, 0x10, BIT4); 984 if (!strncmp(ptr, device_mapping[i].name, len)) {
1116 viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4); 985 odev |= device_mapping[i].device;
986 ptr += len;
987 if (*ptr == ',') {
988 ptr++;
989 next = true;
990 }
991 }
1117 } 992 }
1118 break; 993 }
1119 994
1120 case INTERFACE_LVDS0: 995 *end = ptr;
1121 case INTERFACE_LVDS0LVDS1: 996 return odev;
1122 if (set_iga == IGA1) 997}
1123 viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4);
1124 else
1125 viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4);
1126 998
1127 break; 999void via_odev_to_seq(struct seq_file *m, u32 odev)
1000{
1001 int i, count = 0;
1128 1002
1129 case INTERFACE_LVDS1: 1003 for (i = 0; i < ARRAY_SIZE(device_mapping); i++) {
1130 if (set_iga == IGA1) 1004 if (odev & device_mapping[i].device) {
1131 viafb_write_reg_mask(CR97, VIACR, 0x00, BIT4); 1005 if (count > 0)
1132 else 1006 seq_putc(m, ',');
1133 viafb_write_reg_mask(CR97, VIACR, 0x10, BIT4); 1007
1134 break; 1008 seq_puts(m, device_mapping[i].name);
1009 count++;
1010 }
1135 } 1011 }
1012
1013 seq_putc(m, '\n');
1136} 1014}
1137 1015
1138static void load_fix_bit_crtc_reg(void) 1016static void load_fix_bit_crtc_reg(void)
1139{ 1017{
1018 viafb_unlock_crt();
1019
1140 /* always set to 1 */ 1020 /* always set to 1 */
1141 viafb_write_reg_mask(CR03, VIACR, 0x80, BIT7); 1021 viafb_write_reg_mask(CR03, VIACR, 0x80, BIT7);
1142 /* line compare should set all bits = 1 (extend modes) */ 1022 /* line compare should set all bits = 1 (extend modes) */
1143 viafb_write_reg(CR18, VIACR, 0xff);
1144 /* line compare should set all bits = 1 (extend modes) */
1145 viafb_write_reg_mask(CR07, VIACR, 0x10, BIT4);
1146 /* line compare should set all bits = 1 (extend modes) */
1147 viafb_write_reg_mask(CR09, VIACR, 0x40, BIT6);
1148 /* line compare should set all bits = 1 (extend modes) */
1149 viafb_write_reg_mask(CR35, VIACR, 0x10, BIT4); 1023 viafb_write_reg_mask(CR35, VIACR, 0x10, BIT4);
1150 /* line compare should set all bits = 1 (extend modes) */ 1024 /* line compare should set all bits = 1 (extend modes) */
1151 viafb_write_reg_mask(CR33, VIACR, 0x06, BIT0 + BIT1 + BIT2); 1025 viafb_write_reg_mask(CR33, VIACR, 0x06, BIT0 + BIT1 + BIT2);
1152 /*viafb_write_reg_mask(CR32, VIACR, 0x01, BIT0); */ 1026 /*viafb_write_reg_mask(CR32, VIACR, 0x01, BIT0); */
1153 /* extend mode always set to e3h */ 1027
1154 viafb_write_reg(CR17, VIACR, 0xe3); 1028 viafb_lock_crt();
1155 /* extend mode always set to 0h */
1156 viafb_write_reg(CR08, VIACR, 0x00);
1157 /* extend mode always set to 0h */
1158 viafb_write_reg(CR14, VIACR, 0x00);
1159 1029
1160 /* If K8M800, enable Prefetch Mode. */ 1030 /* If K8M800, enable Prefetch Mode. */
1161 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) 1031 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800)
@@ -1352,6 +1222,15 @@ void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active)
1352 VX855_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; 1222 VX855_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1353 } 1223 }
1354 1224
1225 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX900) {
1226 iga1_fifo_max_depth = VX900_IGA1_FIFO_MAX_DEPTH;
1227 iga1_fifo_threshold = VX900_IGA1_FIFO_THRESHOLD;
1228 iga1_fifo_high_threshold =
1229 VX900_IGA1_FIFO_HIGH_THRESHOLD;
1230 iga1_display_queue_expire_num =
1231 VX900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1232 }
1233
1355 /* Set Display FIFO Depath Select */ 1234 /* Set Display FIFO Depath Select */
1356 reg_value = IGA1_FIFO_DEPTH_SELECT_FORMULA(iga1_fifo_max_depth); 1235 reg_value = IGA1_FIFO_DEPTH_SELECT_FORMULA(iga1_fifo_max_depth);
1357 viafb_load_reg_num = 1236 viafb_load_reg_num =
@@ -1492,6 +1371,15 @@ void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active)
1492 VX855_IGA2_DISPLAY_QUEUE_EXPIRE_NUM; 1371 VX855_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1493 } 1372 }
1494 1373
1374 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX900) {
1375 iga2_fifo_max_depth = VX900_IGA2_FIFO_MAX_DEPTH;
1376 iga2_fifo_threshold = VX900_IGA2_FIFO_THRESHOLD;
1377 iga2_fifo_high_threshold =
1378 VX900_IGA2_FIFO_HIGH_THRESHOLD;
1379 iga2_display_queue_expire_num =
1380 VX900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1381 }
1382
1495 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) { 1383 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
1496 /* Set Display FIFO Depath Select */ 1384 /* Set Display FIFO Depath Select */
1497 reg_value = 1385 reg_value =
@@ -1558,139 +1446,83 @@ void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active)
1558 1446
1559} 1447}
1560 1448
1561static u32 cle266_encode_pll(struct pll_config pll) 1449static struct via_pll_config get_pll_config(struct pll_limit *limits, int size,
1450 int clk)
1562{ 1451{
1563 return (pll.multiplier << 8) 1452 struct via_pll_config cur, up, down, best = {0, 1, 0};
1564 | (pll.rshift << 6) 1453 const u32 f0 = 14318180; /* X1 frequency */
1565 | pll.divisor; 1454 int i, f;
1566} 1455
1567 1456 for (i = 0; i < size; i++) {
1568static u32 k800_encode_pll(struct pll_config pll) 1457 cur.rshift = limits[i].rshift;
1569{ 1458 cur.divisor = limits[i].divisor;
1570 return ((pll.divisor - 2) << 16) 1459 cur.multiplier = clk / ((f0 / cur.divisor)>>cur.rshift);
1571 | (pll.rshift << 10) 1460 f = abs(get_pll_output_frequency(f0, cur) - clk);
1572 | (pll.multiplier - 2); 1461 up = down = cur;
1573} 1462 up.multiplier++;
1463 down.multiplier--;
1464 if (abs(get_pll_output_frequency(f0, up) - clk) < f)
1465 cur = up;
1466 else if (abs(get_pll_output_frequency(f0, down) - clk) < f)
1467 cur = down;
1468
1469 if (cur.multiplier < limits[i].multiplier_min)
1470 cur.multiplier = limits[i].multiplier_min;
1471 else if (cur.multiplier > limits[i].multiplier_max)
1472 cur.multiplier = limits[i].multiplier_max;
1473
1474 f = abs(get_pll_output_frequency(f0, cur) - clk);
1475 if (f < abs(get_pll_output_frequency(f0, best) - clk))
1476 best = cur;
1477 }
1574 1478
1575static u32 vx855_encode_pll(struct pll_config pll) 1479 return best;
1576{
1577 return (pll.divisor << 16)
1578 | (pll.rshift << 10)
1579 | pll.multiplier;
1580} 1480}
1581 1481
1582u32 viafb_get_clk_value(int clk) 1482static struct via_pll_config get_best_pll_config(int clk)
1583{ 1483{
1584 u32 value = 0; 1484 struct via_pll_config config;
1585 int i = 0;
1586
1587 while (i < NUM_TOTAL_PLL_TABLE && clk != pll_value[i].clk)
1588 i++;
1589
1590 if (i == NUM_TOTAL_PLL_TABLE) {
1591 printk(KERN_WARNING "viafb_get_clk_value: PLL lookup failed!");
1592 } else {
1593 switch (viaparinfo->chip_info->gfx_chip_name) {
1594 case UNICHROME_CLE266:
1595 case UNICHROME_K400:
1596 value = cle266_encode_pll(pll_value[i].cle266_pll);
1597 break;
1598 1485
1599 case UNICHROME_K800: 1486 switch (viaparinfo->chip_info->gfx_chip_name) {
1600 case UNICHROME_PM800: 1487 case UNICHROME_CLE266:
1601 case UNICHROME_CN700: 1488 case UNICHROME_K400:
1602 value = k800_encode_pll(pll_value[i].k800_pll); 1489 config = get_pll_config(cle266_pll_limits,
1603 break; 1490 ARRAY_SIZE(cle266_pll_limits), clk);
1604 1491 break;
1605 case UNICHROME_CX700: 1492 case UNICHROME_K800:
1606 case UNICHROME_CN750: 1493 case UNICHROME_PM800:
1607 case UNICHROME_K8M890: 1494 case UNICHROME_CN700:
1608 case UNICHROME_P4M890: 1495 config = get_pll_config(k800_pll_limits,
1609 case UNICHROME_P4M900: 1496 ARRAY_SIZE(k800_pll_limits), clk);
1610 case UNICHROME_VX800: 1497 break;
1611 value = k800_encode_pll(pll_value[i].cx700_pll); 1498 case UNICHROME_CX700:
1612 break; 1499 case UNICHROME_CN750:
1613 1500 case UNICHROME_K8M890:
1614 case UNICHROME_VX855: 1501 case UNICHROME_P4M890:
1615 value = vx855_encode_pll(pll_value[i].vx855_pll); 1502 case UNICHROME_P4M900:
1616 break; 1503 case UNICHROME_VX800:
1617 } 1504 config = get_pll_config(cx700_pll_limits,
1505 ARRAY_SIZE(cx700_pll_limits), clk);
1506 break;
1507 case UNICHROME_VX855:
1508 case UNICHROME_VX900:
1509 config = get_pll_config(vx855_pll_limits,
1510 ARRAY_SIZE(vx855_pll_limits), clk);
1511 break;
1618 } 1512 }
1619 1513
1620 return value; 1514 return config;
1621} 1515}
1622 1516
1623/* Set VCLK*/ 1517/* Set VCLK*/
1624void viafb_set_vclock(u32 clk, int set_iga) 1518void viafb_set_vclock(u32 clk, int set_iga)
1625{ 1519{
1626 /* H.W. Reset : ON */ 1520 struct via_pll_config config = get_best_pll_config(clk);
1627 viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
1628
1629 if (set_iga == IGA1) {
1630 /* Change D,N FOR VCLK */
1631 switch (viaparinfo->chip_info->gfx_chip_name) {
1632 case UNICHROME_CLE266:
1633 case UNICHROME_K400:
1634 via_write_reg(VIASR, SR46, (clk & 0x00FF));
1635 via_write_reg(VIASR, SR47, (clk & 0xFF00) >> 8);
1636 break;
1637
1638 case UNICHROME_K800:
1639 case UNICHROME_PM800:
1640 case UNICHROME_CN700:
1641 case UNICHROME_CX700:
1642 case UNICHROME_CN750:
1643 case UNICHROME_K8M890:
1644 case UNICHROME_P4M890:
1645 case UNICHROME_P4M900:
1646 case UNICHROME_VX800:
1647 case UNICHROME_VX855:
1648 via_write_reg(VIASR, SR44, (clk & 0x0000FF));
1649 via_write_reg(VIASR, SR45, (clk & 0x00FF00) >> 8);
1650 via_write_reg(VIASR, SR46, (clk & 0xFF0000) >> 16);
1651 break;
1652 }
1653 }
1654
1655 if (set_iga == IGA2) {
1656 /* Change D,N FOR LCK */
1657 switch (viaparinfo->chip_info->gfx_chip_name) {
1658 case UNICHROME_CLE266:
1659 case UNICHROME_K400:
1660 via_write_reg(VIASR, SR44, (clk & 0x00FF));
1661 via_write_reg(VIASR, SR45, (clk & 0xFF00) >> 8);
1662 break;
1663
1664 case UNICHROME_K800:
1665 case UNICHROME_PM800:
1666 case UNICHROME_CN700:
1667 case UNICHROME_CX700:
1668 case UNICHROME_CN750:
1669 case UNICHROME_K8M890:
1670 case UNICHROME_P4M890:
1671 case UNICHROME_P4M900:
1672 case UNICHROME_VX800:
1673 case UNICHROME_VX855:
1674 via_write_reg(VIASR, SR4A, (clk & 0x0000FF));
1675 via_write_reg(VIASR, SR4B, (clk & 0x00FF00) >> 8);
1676 via_write_reg(VIASR, SR4C, (clk & 0xFF0000) >> 16);
1677 break;
1678 }
1679 }
1680 1521
1681 /* H.W. Reset : OFF */ 1522 if (set_iga == IGA1)
1682 viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7); 1523 clock.set_primary_pll(config);
1683 1524 if (set_iga == IGA2)
1684 /* Reset PLL */ 1525 clock.set_secondary_pll(config);
1685 if (set_iga == IGA1) {
1686 viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1);
1687 viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1);
1688 }
1689
1690 if (set_iga == IGA2) {
1691 viafb_write_reg_mask(SR40, VIASR, 0x01, BIT0);
1692 viafb_write_reg_mask(SR40, VIASR, 0x00, BIT0);
1693 }
1694 1526
1695 /* Fire! */ 1527 /* Fire! */
1696 via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */ 1528 via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */
@@ -1936,14 +1768,15 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
1936 int i; 1768 int i;
1937 int index = 0; 1769 int index = 0;
1938 int h_addr, v_addr; 1770 int h_addr, v_addr;
1939 u32 pll_D_N; 1771 u32 clock, refresh = viafb_refresh;
1940 u8 polarity = 0; 1772
1773 if (viafb_SAMM_ON && set_iga == IGA2)
1774 refresh = viafb_refresh1;
1941 1775
1942 for (i = 0; i < video_mode->mode_array; i++) { 1776 for (i = 0; i < video_mode->mode_array; i++) {
1943 index = i; 1777 index = i;
1944 1778
1945 if (crt_table[i].refresh_rate == viaparinfo-> 1779 if (crt_table[i].refresh_rate == refresh)
1946 crt_setting_info->refresh_rate)
1947 break; 1780 break;
1948 } 1781 }
1949 1782
@@ -1954,7 +1787,7 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
1954 if ((viafb_LCD_ON | viafb_DVI_ON) 1787 if ((viafb_LCD_ON | viafb_DVI_ON)
1955 && video_mode->crtc[0].crtc.hor_addr == 640 1788 && video_mode->crtc[0].crtc.hor_addr == 640
1956 && video_mode->crtc[0].crtc.ver_addr == 480 1789 && video_mode->crtc[0].crtc.ver_addr == 480
1957 && viaparinfo->crt_setting_info->refresh_rate == 60) { 1790 && refresh == 60) {
1958 /* The border is 8 pixels. */ 1791 /* The border is 8 pixels. */
1959 crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8; 1792 crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8;
1960 1793
@@ -1964,18 +1797,8 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
1964 1797
1965 h_addr = crt_reg.hor_addr; 1798 h_addr = crt_reg.hor_addr;
1966 v_addr = crt_reg.ver_addr; 1799 v_addr = crt_reg.ver_addr;
1967
1968 /* update polarity for CRT timing */
1969 if (crt_table[index].h_sync_polarity == NEGATIVE)
1970 polarity |= BIT6;
1971 if (crt_table[index].v_sync_polarity == NEGATIVE)
1972 polarity |= BIT7;
1973 via_write_misc_reg_mask(polarity, BIT6 | BIT7);
1974
1975 if (set_iga == IGA1) { 1800 if (set_iga == IGA1) {
1976 viafb_unlock_crt(); 1801 viafb_unlock_crt();
1977 viafb_write_reg(CR09, VIACR, 0x00); /*initial CR09=0 */
1978 viafb_write_reg_mask(CR11, VIACR, 0x00, BIT4 + BIT5 + BIT6);
1979 viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7); 1802 viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
1980 } 1803 }
1981 1804
@@ -1988,7 +1811,6 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
1988 break; 1811 break;
1989 } 1812 }
1990 1813
1991 load_fix_bit_crtc_reg();
1992 viafb_lock_crt(); 1814 viafb_lock_crt();
1993 viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7); 1815 viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
1994 viafb_load_fetch_count_reg(h_addr, bpp_byte, set_iga); 1816 viafb_load_fetch_count_reg(h_addr, bpp_byte, set_iga);
@@ -1998,21 +1820,19 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
1998 && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)) 1820 && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
1999 viafb_load_FIFO_reg(set_iga, h_addr, v_addr); 1821 viafb_load_FIFO_reg(set_iga, h_addr, v_addr);
2000 1822
2001 pll_D_N = viafb_get_clk_value(crt_table[index].clk); 1823 clock = crt_reg.hor_total * crt_reg.ver_total
2002 DEBUG_MSG(KERN_INFO "PLL=%x", pll_D_N); 1824 * crt_table[index].refresh_rate;
2003 viafb_set_vclock(pll_D_N, set_iga); 1825 viafb_set_vclock(clock, set_iga);
2004 1826
2005} 1827}
2006 1828
2007void viafb_init_chip_info(int chip_type) 1829void __devinit viafb_init_chip_info(int chip_type)
2008{ 1830{
1831 via_clock_init(&clock, chip_type);
2009 init_gfx_chip_info(chip_type); 1832 init_gfx_chip_info(chip_type);
2010 init_tmds_chip_info(); 1833 init_tmds_chip_info();
2011 init_lvds_chip_info(); 1834 init_lvds_chip_info();
2012 1835
2013 viaparinfo->crt_setting_info->iga_path = IGA1;
2014 viaparinfo->crt_setting_info->refresh_rate = viafb_refresh;
2015
2016 /*Set IGA path for each device */ 1836 /*Set IGA path for each device */
2017 viafb_set_iga_path(); 1837 viafb_set_iga_path();
2018 1838
@@ -2024,29 +1844,18 @@ void viafb_init_chip_info(int chip_type)
2024 viaparinfo->lvds_setting_info->lcd_mode; 1844 viaparinfo->lvds_setting_info->lcd_mode;
2025} 1845}
2026 1846
2027void viafb_update_device_setting(int hres, int vres, 1847void viafb_update_device_setting(int hres, int vres, int bpp, int flag)
2028 int bpp, int vmode_refresh, int flag)
2029{ 1848{
2030 if (flag == 0) { 1849 if (flag == 0) {
2031 viaparinfo->crt_setting_info->h_active = hres;
2032 viaparinfo->crt_setting_info->v_active = vres;
2033 viaparinfo->crt_setting_info->bpp = bpp;
2034 viaparinfo->crt_setting_info->refresh_rate =
2035 vmode_refresh;
2036
2037 viaparinfo->tmds_setting_info->h_active = hres; 1850 viaparinfo->tmds_setting_info->h_active = hres;
2038 viaparinfo->tmds_setting_info->v_active = vres; 1851 viaparinfo->tmds_setting_info->v_active = vres;
2039 1852
2040 viaparinfo->lvds_setting_info->h_active = hres; 1853 viaparinfo->lvds_setting_info->h_active = hres;
2041 viaparinfo->lvds_setting_info->v_active = vres; 1854 viaparinfo->lvds_setting_info->v_active = vres;
2042 viaparinfo->lvds_setting_info->bpp = bpp; 1855 viaparinfo->lvds_setting_info->bpp = bpp;
2043 viaparinfo->lvds_setting_info->refresh_rate =
2044 vmode_refresh;
2045 viaparinfo->lvds_setting_info2->h_active = hres; 1856 viaparinfo->lvds_setting_info2->h_active = hres;
2046 viaparinfo->lvds_setting_info2->v_active = vres; 1857 viaparinfo->lvds_setting_info2->v_active = vres;
2047 viaparinfo->lvds_setting_info2->bpp = bpp; 1858 viaparinfo->lvds_setting_info2->bpp = bpp;
2048 viaparinfo->lvds_setting_info2->refresh_rate =
2049 vmode_refresh;
2050 } else { 1859 } else {
2051 1860
2052 if (viaparinfo->tmds_setting_info->iga_path == IGA2) { 1861 if (viaparinfo->tmds_setting_info->iga_path == IGA2) {
@@ -2058,20 +1867,16 @@ void viafb_update_device_setting(int hres, int vres,
2058 viaparinfo->lvds_setting_info->h_active = hres; 1867 viaparinfo->lvds_setting_info->h_active = hres;
2059 viaparinfo->lvds_setting_info->v_active = vres; 1868 viaparinfo->lvds_setting_info->v_active = vres;
2060 viaparinfo->lvds_setting_info->bpp = bpp; 1869 viaparinfo->lvds_setting_info->bpp = bpp;
2061 viaparinfo->lvds_setting_info->refresh_rate =
2062 vmode_refresh;
2063 } 1870 }
2064 if (IGA2 == viaparinfo->lvds_setting_info2->iga_path) { 1871 if (IGA2 == viaparinfo->lvds_setting_info2->iga_path) {
2065 viaparinfo->lvds_setting_info2->h_active = hres; 1872 viaparinfo->lvds_setting_info2->h_active = hres;
2066 viaparinfo->lvds_setting_info2->v_active = vres; 1873 viaparinfo->lvds_setting_info2->v_active = vres;
2067 viaparinfo->lvds_setting_info2->bpp = bpp; 1874 viaparinfo->lvds_setting_info2->bpp = bpp;
2068 viaparinfo->lvds_setting_info2->refresh_rate =
2069 vmode_refresh;
2070 } 1875 }
2071 } 1876 }
2072} 1877}
2073 1878
2074static void init_gfx_chip_info(int chip_type) 1879static void __devinit init_gfx_chip_info(int chip_type)
2075{ 1880{
2076 u8 tmp; 1881 u8 tmp;
2077 1882
@@ -2111,6 +1916,7 @@ static void init_gfx_chip_info(int chip_type)
2111 switch (viaparinfo->chip_info->gfx_chip_name) { 1916 switch (viaparinfo->chip_info->gfx_chip_name) {
2112 case UNICHROME_VX800: 1917 case UNICHROME_VX800:
2113 case UNICHROME_VX855: 1918 case UNICHROME_VX855:
1919 case UNICHROME_VX900:
2114 viaparinfo->chip_info->twod_engine = VIA_2D_ENG_M1; 1920 viaparinfo->chip_info->twod_engine = VIA_2D_ENG_M1;
2115 break; 1921 break;
2116 case UNICHROME_K8M890: 1922 case UNICHROME_K8M890:
@@ -2123,7 +1929,7 @@ static void init_gfx_chip_info(int chip_type)
2123 } 1929 }
2124} 1930}
2125 1931
2126static void init_tmds_chip_info(void) 1932static void __devinit init_tmds_chip_info(void)
2127{ 1933{
2128 viafb_tmds_trasmitter_identify(); 1934 viafb_tmds_trasmitter_identify();
2129 1935
@@ -2168,7 +1974,7 @@ static void init_tmds_chip_info(void)
2168 &viaparinfo->shared->tmds_setting_info); 1974 &viaparinfo->shared->tmds_setting_info);
2169} 1975}
2170 1976
2171static void init_lvds_chip_info(void) 1977static void __devinit init_lvds_chip_info(void)
2172{ 1978{
2173 viafb_lvds_trasmitter_identify(); 1979 viafb_lvds_trasmitter_identify();
2174 viafb_init_lcd_size(); 1980 viafb_init_lcd_size();
@@ -2202,7 +2008,7 @@ static void init_lvds_chip_info(void)
2202 viaparinfo->chip_info->lvds_chip_info.output_interface); 2008 viaparinfo->chip_info->lvds_chip_info.output_interface);
2203} 2009}
2204 2010
2205void viafb_init_dac(int set_iga) 2011void __devinit viafb_init_dac(int set_iga)
2206{ 2012{
2207 int i; 2013 int i;
2208 u8 tmp; 2014 u8 tmp;
@@ -2275,11 +2081,24 @@ static void set_display_channel(void)
2275 } 2081 }
2276} 2082}
2277 2083
2084static u8 get_sync(struct fb_info *info)
2085{
2086 u8 polarity = 0;
2087
2088 if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
2089 polarity |= VIA_HSYNC_NEGATIVE;
2090 if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
2091 polarity |= VIA_VSYNC_NEGATIVE;
2092 return polarity;
2093}
2094
2278int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, 2095int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
2279 struct VideoModeTable *vmode_tbl1, int video_bpp1) 2096 struct VideoModeTable *vmode_tbl1, int video_bpp1)
2280{ 2097{
2281 int i, j; 2098 int i, j;
2282 int port; 2099 int port;
2100 u32 devices = viaparinfo->shared->iga1_devices
2101 | viaparinfo->shared->iga2_devices;
2283 u8 value, index, mask; 2102 u8 value, index, mask;
2284 struct crt_mode_table *crt_timing; 2103 struct crt_mode_table *crt_timing;
2285 struct crt_mode_table *crt_timing1 = NULL; 2104 struct crt_mode_table *crt_timing1 = NULL;
@@ -2295,6 +2114,7 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
2295 outb(0x00, VIAAR); 2114 outb(0x00, VIAAR);
2296 2115
2297 /* Write Common Setting for Video Mode */ 2116 /* Write Common Setting for Video Mode */
2117 viafb_write_regx(common_vga, ARRAY_SIZE(common_vga));
2298 switch (viaparinfo->chip_info->gfx_chip_name) { 2118 switch (viaparinfo->chip_info->gfx_chip_name) {
2299 case UNICHROME_CLE266: 2119 case UNICHROME_CLE266:
2300 viafb_write_regx(CLE266_ModeXregs, NUM_TOTAL_CLE266_ModeXregs); 2120 viafb_write_regx(CLE266_ModeXregs, NUM_TOTAL_CLE266_ModeXregs);
@@ -2322,11 +2142,14 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
2322 break; 2142 break;
2323 2143
2324 case UNICHROME_VX855: 2144 case UNICHROME_VX855:
2145 case UNICHROME_VX900:
2325 viafb_write_regx(VX855_ModeXregs, NUM_TOTAL_VX855_ModeXregs); 2146 viafb_write_regx(VX855_ModeXregs, NUM_TOTAL_VX855_ModeXregs);
2326 break; 2147 break;
2327 } 2148 }
2328 2149
2150 viafb_write_regx(scaling_parameters, ARRAY_SIZE(scaling_parameters));
2329 device_off(); 2151 device_off();
2152 via_set_state(devices, VIA_STATE_OFF);
2330 2153
2331 /* Fill VPIT Parameters */ 2154 /* Fill VPIT Parameters */
2332 /* Write Misc Register */ 2155 /* Write Misc Register */
@@ -2337,10 +2160,6 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
2337 via_write_reg(VIASR, i, VPIT.SR[i - 1]); 2160 via_write_reg(VIASR, i, VPIT.SR[i - 1]);
2338 2161
2339 viafb_write_reg_mask(0x15, VIASR, 0xA2, 0xA2); 2162 viafb_write_reg_mask(0x15, VIASR, 0xA2, 0xA2);
2340 viafb_set_iga_path();
2341
2342 /* Write CRTC */
2343 viafb_fill_crtc_timing(crt_timing, vmode_tbl, video_bpp / 8, IGA1);
2344 2163
2345 /* Write Graphic Controller */ 2164 /* Write Graphic Controller */
2346 for (i = 0; i < StdGR; i++) 2165 for (i = 0; i < StdGR; i++)
@@ -2371,31 +2190,37 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
2371 } 2190 }
2372 } 2191 }
2373 2192
2193 load_fix_bit_crtc_reg();
2374 via_set_primary_pitch(viafbinfo->fix.line_length); 2194 via_set_primary_pitch(viafbinfo->fix.line_length);
2375 via_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length 2195 via_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length
2376 : viafbinfo->fix.line_length); 2196 : viafbinfo->fix.line_length);
2377 via_set_primary_color_depth(viaparinfo->depth); 2197 via_set_primary_color_depth(viaparinfo->depth);
2378 via_set_secondary_color_depth(viafb_dual_fb ? viaparinfo1->depth 2198 via_set_secondary_color_depth(viafb_dual_fb ? viaparinfo1->depth
2379 : viaparinfo->depth); 2199 : viaparinfo->depth);
2200 via_set_source(viaparinfo->shared->iga1_devices, IGA1);
2201 via_set_source(viaparinfo->shared->iga2_devices, IGA2);
2202 if (viaparinfo->shared->iga2_devices)
2203 enable_second_display_channel();
2204 else
2205 disable_second_display_channel();
2206
2380 /* Update Refresh Rate Setting */ 2207 /* Update Refresh Rate Setting */
2381 2208
2382 /* Clear On Screen */ 2209 /* Clear On Screen */
2383 2210
2384 /* CRT set mode */ 2211 /* CRT set mode */
2385 if (viafb_CRT_ON) { 2212 if (viafb_CRT_ON) {
2386 if (viafb_SAMM_ON && (viaparinfo->crt_setting_info->iga_path == 2213 if (viafb_SAMM_ON &&
2387 IGA2)) { 2214 viaparinfo->shared->iga2_devices & VIA_CRT) {
2388 viafb_fill_crtc_timing(crt_timing1, vmode_tbl1, 2215 viafb_fill_crtc_timing(crt_timing1, vmode_tbl1,
2389 video_bpp1 / 8, 2216 video_bpp1 / 8, IGA2);
2390 viaparinfo->crt_setting_info->iga_path);
2391 } else { 2217 } else {
2392 viafb_fill_crtc_timing(crt_timing, vmode_tbl, 2218 viafb_fill_crtc_timing(crt_timing, vmode_tbl,
2393 video_bpp / 8, 2219 video_bpp / 8,
2394 viaparinfo->crt_setting_info->iga_path); 2220 (viaparinfo->shared->iga1_devices & VIA_CRT)
2221 ? IGA1 : IGA2);
2395 } 2222 }
2396 2223
2397 set_crt_output_path(viaparinfo->crt_setting_info->iga_path);
2398
2399 /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode 2224 /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode
2400 to 8 alignment (1368),there is several pixels (2 pixels) 2225 to 8 alignment (1368),there is several pixels (2 pixels)
2401 on right side of screen. */ 2226 on right side of screen. */
@@ -2482,10 +2307,43 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
2482 viafb_DeviceStatus = CRT_Device; 2307 viafb_DeviceStatus = CRT_Device;
2483 } 2308 }
2484 device_on(); 2309 device_on();
2310 if (!viafb_dual_fb)
2311 via_set_sync_polarity(devices, get_sync(viafbinfo));
2312 else {
2313 via_set_sync_polarity(viaparinfo->shared->iga1_devices,
2314 get_sync(viafbinfo));
2315 via_set_sync_polarity(viaparinfo->shared->iga2_devices,
2316 get_sync(viafbinfo1));
2317 }
2485 2318
2486 if (viafb_SAMM_ON == 1) 2319 clock.set_engine_pll_state(VIA_STATE_ON);
2487 viafb_write_reg_mask(CR6A, VIACR, 0xC0, BIT6 + BIT7); 2320 clock.set_primary_clock_source(VIA_CLKSRC_X1, true);
2321 clock.set_secondary_clock_source(VIA_CLKSRC_X1, true);
2322
2323#ifdef CONFIG_FB_VIA_X_COMPATIBILITY
2324 clock.set_primary_pll_state(VIA_STATE_ON);
2325 clock.set_primary_clock_state(VIA_STATE_ON);
2326 clock.set_secondary_pll_state(VIA_STATE_ON);
2327 clock.set_secondary_clock_state(VIA_STATE_ON);
2328#else
2329 if (viaparinfo->shared->iga1_devices) {
2330 clock.set_primary_pll_state(VIA_STATE_ON);
2331 clock.set_primary_clock_state(VIA_STATE_ON);
2332 } else {
2333 clock.set_primary_pll_state(VIA_STATE_OFF);
2334 clock.set_primary_clock_state(VIA_STATE_OFF);
2335 }
2336
2337 if (viaparinfo->shared->iga2_devices) {
2338 clock.set_secondary_pll_state(VIA_STATE_ON);
2339 clock.set_secondary_clock_state(VIA_STATE_ON);
2340 } else {
2341 clock.set_secondary_pll_state(VIA_STATE_OFF);
2342 clock.set_secondary_clock_state(VIA_STATE_OFF);
2343 }
2344#endif /*CONFIG_FB_VIA_X_COMPATIBILITY*/
2488 2345
2346 via_set_state(devices, VIA_STATE_ON);
2489 device_screen_on(); 2347 device_screen_on();
2490 return 1; 2348 return 1;
2491} 2349}
@@ -2493,64 +2351,63 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
2493int viafb_get_pixclock(int hres, int vres, int vmode_refresh) 2351int viafb_get_pixclock(int hres, int vres, int vmode_refresh)
2494{ 2352{
2495 int i; 2353 int i;
2354 struct crt_mode_table *best;
2355 struct VideoModeTable *vmode = viafb_get_mode(hres, vres);
2356
2357 if (!vmode)
2358 return RES_640X480_60HZ_PIXCLOCK;
2496 2359
2497 for (i = 0; i < NUM_TOTAL_RES_MAP_REFRESH; i++) { 2360 best = &vmode->crtc[0];
2498 if ((hres == res_map_refresh_tbl[i].hres) 2361 for (i = 1; i < vmode->mode_array; i++) {
2499 && (vres == res_map_refresh_tbl[i].vres) 2362 if (abs(vmode->crtc[i].refresh_rate - vmode_refresh)
2500 && (vmode_refresh == res_map_refresh_tbl[i].vmode_refresh)) 2363 < abs(best->refresh_rate - vmode_refresh))
2501 return res_map_refresh_tbl[i].pixclock; 2364 best = &vmode->crtc[i];
2502 } 2365 }
2503 return RES_640X480_60HZ_PIXCLOCK;
2504 2366
2367 return 1000000000 / (best->crtc.hor_total * best->crtc.ver_total)
2368 * 1000 / best->refresh_rate;
2505} 2369}
2506 2370
2507int viafb_get_refresh(int hres, int vres, u32 long_refresh) 2371int viafb_get_refresh(int hres, int vres, u32 long_refresh)
2508{ 2372{
2509#define REFRESH_TOLERANCE 3 2373 int i;
2510 int i, nearest = -1, diff = REFRESH_TOLERANCE; 2374 struct crt_mode_table *best;
2511 for (i = 0; i < NUM_TOTAL_RES_MAP_REFRESH; i++) { 2375 struct VideoModeTable *vmode = viafb_get_mode(hres, vres);
2512 if ((hres == res_map_refresh_tbl[i].hres) 2376
2513 && (vres == res_map_refresh_tbl[i].vres) 2377 if (!vmode)
2514 && (diff > (abs(long_refresh - 2378 return 60;
2515 res_map_refresh_tbl[i].vmode_refresh)))) { 2379
2516 diff = abs(long_refresh - res_map_refresh_tbl[i]. 2380 best = &vmode->crtc[0];
2517 vmode_refresh); 2381 for (i = 1; i < vmode->mode_array; i++) {
2518 nearest = i; 2382 if (abs(vmode->crtc[i].refresh_rate - long_refresh)
2519 } 2383 < abs(best->refresh_rate - long_refresh))
2384 best = &vmode->crtc[i];
2520 } 2385 }
2521#undef REFRESH_TOLERANCE 2386
2522 if (nearest > 0) 2387 if (abs(best->refresh_rate - long_refresh) > 3) {
2523 return res_map_refresh_tbl[nearest].vmode_refresh; 2388 if (hres == 1200 && vres == 900)
2524 return 60; 2389 return 49; /* OLPC DCON only supports 50 Hz */
2390 else
2391 return 60;
2392 }
2393
2394 return best->refresh_rate;
2525} 2395}
2526 2396
2527static void device_off(void) 2397static void device_off(void)
2528{ 2398{
2529 viafb_crt_disable();
2530 viafb_dvi_disable(); 2399 viafb_dvi_disable();
2531 viafb_lcd_disable(); 2400 viafb_lcd_disable();
2532} 2401}
2533 2402
2534static void device_on(void) 2403static void device_on(void)
2535{ 2404{
2536 if (viafb_CRT_ON == 1)
2537 viafb_crt_enable();
2538 if (viafb_DVI_ON == 1) 2405 if (viafb_DVI_ON == 1)
2539 viafb_dvi_enable(); 2406 viafb_dvi_enable();
2540 if (viafb_LCD_ON == 1) 2407 if (viafb_LCD_ON == 1)
2541 viafb_lcd_enable(); 2408 viafb_lcd_enable();
2542} 2409}
2543 2410
2544void viafb_crt_disable(void)
2545{
2546 viafb_write_reg_mask(CR36, VIACR, BIT5 + BIT4, BIT5 + BIT4);
2547}
2548
2549void viafb_crt_enable(void)
2550{
2551 viafb_write_reg_mask(CR36, VIACR, 0x0, BIT5 + BIT4);
2552}
2553
2554static void enable_second_display_channel(void) 2411static void enable_second_display_channel(void)
2555{ 2412{
2556 /* to enable second display channel. */ 2413 /* to enable second display channel. */
@@ -2567,7 +2424,6 @@ static void disable_second_display_channel(void)
2567 viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6); 2424 viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6);
2568} 2425}
2569 2426
2570
2571void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ 2427void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
2572 *p_gfx_dpa_setting) 2428 *p_gfx_dpa_setting)
2573{ 2429{
@@ -2652,4 +2508,9 @@ void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
2652 crt_reg.ver_total - (crt_reg.ver_sync_start + crt_reg.ver_sync_end); 2508 crt_reg.ver_total - (crt_reg.ver_sync_start + crt_reg.ver_sync_end);
2653 var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr; 2509 var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr;
2654 var->vsync_len = crt_reg.ver_sync_end; 2510 var->vsync_len = crt_reg.ver_sync_end;
2511 var->sync = 0;
2512 if (crt_timing[index].h_sync_polarity == POSITIVE)
2513 var->sync |= FB_SYNC_HOR_HIGH_ACT;
2514 if (crt_timing[index].v_sync_polarity == POSITIVE)
2515 var->sync |= FB_SYNC_VERT_HIGH_ACT;
2655} 2516}
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index c44399895294..c7239eb83bae 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -22,6 +22,8 @@
22#ifndef __HW_H__ 22#ifndef __HW_H__
23#define __HW_H__ 23#define __HW_H__
24 24
25#include <linux/seq_file.h>
26
25#include "viamode.h" 27#include "viamode.h"
26#include "global.h" 28#include "global.h"
27#include "via_modesetting.h" 29#include "via_modesetting.h"
@@ -30,6 +32,25 @@
30#define viafb_write_reg(i, p, d) via_write_reg(p, i, d) 32#define viafb_write_reg(i, p, d) via_write_reg(p, i, d)
31#define viafb_write_reg_mask(i, p, d, m) via_write_reg_mask(p, i, d, m) 33#define viafb_write_reg_mask(i, p, d, m) via_write_reg_mask(p, i, d, m)
32 34
35/* VIA output devices */
36#define VIA_LDVP0 0x00000001
37#define VIA_LDVP1 0x00000002
38#define VIA_DVP0 0x00000004
39#define VIA_CRT 0x00000010
40#define VIA_DVP1 0x00000020
41#define VIA_LVDS1 0x00000040
42#define VIA_LVDS2 0x00000080
43
44/* VIA output device power states */
45#define VIA_STATE_ON 0
46#define VIA_STATE_STANDBY 1
47#define VIA_STATE_SUSPEND 2
48#define VIA_STATE_OFF 3
49
50/* VIA output device sync polarity */
51#define VIA_HSYNC_NEGATIVE 0x01
52#define VIA_VSYNC_NEGATIVE 0x02
53
33/*************************************************** 54/***************************************************
34* Definition IGA1 Design Method of CRTC Registers * 55* Definition IGA1 Design Method of CRTC Registers *
35****************************************************/ 56****************************************************/
@@ -341,6 +362,17 @@ is reserved, so it may have problem to set 1600x1200 on IGA2. */
341#define VX855_IGA2_FIFO_HIGH_THRESHOLD 160 362#define VX855_IGA2_FIFO_HIGH_THRESHOLD 160
342#define VX855_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 320 363#define VX855_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 320
343 364
365/* For VT3410 */
366#define VX900_IGA1_FIFO_MAX_DEPTH 400
367#define VX900_IGA1_FIFO_THRESHOLD 320
368#define VX900_IGA1_FIFO_HIGH_THRESHOLD 320
369#define VX900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 160
370
371#define VX900_IGA2_FIFO_MAX_DEPTH 192
372#define VX900_IGA2_FIFO_THRESHOLD 160
373#define VX900_IGA2_FIFO_HIGH_THRESHOLD 160
374#define VX900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 320
375
344#define IGA1_FIFO_DEPTH_SELECT_REG_NUM 1 376#define IGA1_FIFO_DEPTH_SELECT_REG_NUM 1
345#define IGA1_FIFO_THRESHOLD_REG_NUM 2 377#define IGA1_FIFO_THRESHOLD_REG_NUM 2
346#define IGA1_FIFO_HIGH_THRESHOLD_REG_NUM 2 378#define IGA1_FIFO_HIGH_THRESHOLD_REG_NUM 2
@@ -700,20 +732,13 @@ struct _lcd_scaling_factor {
700 struct _lcd_ver_scaling_factor lcd_ver_scaling_factor; 732 struct _lcd_ver_scaling_factor lcd_ver_scaling_factor;
701}; 733};
702 734
703struct pll_config { 735struct pll_limit {
704 u16 multiplier; 736 u16 multiplier_min;
737 u16 multiplier_max;
705 u8 divisor; 738 u8 divisor;
706 u8 rshift; 739 u8 rshift;
707}; 740};
708 741
709struct pll_map {
710 u32 clk;
711 struct pll_config cle266_pll;
712 struct pll_config k800_pll;
713 struct pll_config cx700_pll;
714 struct pll_config vx855_pll;
715};
716
717struct rgbLUT { 742struct rgbLUT {
718 u8 red; 743 u8 red;
719 u8 green; 744 u8 green;
@@ -858,8 +883,8 @@ struct iga2_crtc_timing {
858#define VX800_FUNCTION3 0x3353 883#define VX800_FUNCTION3 0x3353
859/* VT3409 chipset*/ 884/* VT3409 chipset*/
860#define VX855_FUNCTION3 0x3409 885#define VX855_FUNCTION3 0x3409
861 886/* VT3410 chipset*/
862#define NUM_TOTAL_PLL_TABLE ARRAY_SIZE(pll_value) 887#define VX900_FUNCTION3 0x3410
863 888
864struct IODATA { 889struct IODATA {
865 u8 Index; 890 u8 Index;
@@ -873,7 +898,11 @@ struct pci_device_id_info {
873 u32 chip_index; 898 u32 chip_index;
874}; 899};
875 900
876extern unsigned int viafb_second_virtual_xres; 901struct via_device_mapping {
902 u32 device;
903 const char *name;
904};
905
877extern int viafb_SAMM_ON; 906extern int viafb_SAMM_ON;
878extern int viafb_dual_fb; 907extern int viafb_dual_fb;
879extern int viafb_LCD2_ON; 908extern int viafb_LCD2_ON;
@@ -881,9 +910,6 @@ extern int viafb_LCD_ON;
881extern int viafb_DVI_ON; 910extern int viafb_DVI_ON;
882extern int viafb_hotplug; 911extern int viafb_hotplug;
883 912
884void viafb_set_output_path(int device, int set_iga,
885 int output_interface);
886
887void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, 913void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
888 struct VideoModeTable *video_mode, int bpp_byte, int set_iga); 914 struct VideoModeTable *video_mode, int bpp_byte, int set_iga);
889 915
@@ -891,15 +917,17 @@ void viafb_set_vclock(u32 CLK, int set_iga);
891void viafb_load_reg(int timing_value, int viafb_load_reg_num, 917void viafb_load_reg(int timing_value, int viafb_load_reg_num,
892 struct io_register *reg, 918 struct io_register *reg,
893 int io_type); 919 int io_type);
894void viafb_crt_disable(void); 920void via_set_source(u32 devices, u8 iga);
895void viafb_crt_enable(void); 921void via_set_state(u32 devices, u8 state);
922void via_set_sync_polarity(u32 devices, u8 polarity);
923u32 via_parse_odev(char *input, char **end);
924void via_odev_to_seq(struct seq_file *m, u32 odev);
896void init_ad9389(void); 925void init_ad9389(void);
897/* Access I/O Function */ 926/* Access I/O Function */
898void viafb_lock_crt(void); 927void viafb_lock_crt(void);
899void viafb_unlock_crt(void); 928void viafb_unlock_crt(void);
900void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga); 929void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga);
901void viafb_write_regx(struct io_reg RegTable[], int ItemNum); 930void viafb_write_regx(struct io_reg RegTable[], int ItemNum);
902u32 viafb_get_clk_value(int clk);
903void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active); 931void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active);
904void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ 932void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
905 *p_gfx_dpa_setting); 933 *p_gfx_dpa_setting);
@@ -908,12 +936,11 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
908 struct VideoModeTable *vmode_tbl1, int video_bpp1); 936 struct VideoModeTable *vmode_tbl1, int video_bpp1);
909void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, 937void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
910 struct VideoModeTable *vmode_tbl); 938 struct VideoModeTable *vmode_tbl);
911void viafb_init_chip_info(int chip_type); 939void __devinit viafb_init_chip_info(int chip_type);
912void viafb_init_dac(int set_iga); 940void __devinit viafb_init_dac(int set_iga);
913int viafb_get_pixclock(int hres, int vres, int vmode_refresh); 941int viafb_get_pixclock(int hres, int vres, int vmode_refresh);
914int viafb_get_refresh(int hres, int vres, u32 float_refresh); 942int viafb_get_refresh(int hres, int vres, u32 float_refresh);
915void viafb_update_device_setting(int hres, int vres, int bpp, 943void viafb_update_device_setting(int hres, int vres, int bpp, int flag);
916 int vmode_refresh, int flag);
917 944
918void viafb_set_iga_path(void); 945void viafb_set_iga_path(void);
919void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue); 946void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue);
diff --git a/drivers/video/via/ioctl.c b/drivers/video/via/ioctl.c
index 4d553d0b8d7a..ea1c51428823 100644
--- a/drivers/video/via/ioctl.c
+++ b/drivers/video/via/ioctl.c
@@ -94,6 +94,7 @@ int viafb_ioctl_hotplug(int hres, int vres, int bpp)
94 viafb_CRT_ON = 0; 94 viafb_CRT_ON = 0;
95 viafb_LCD_ON = 0; 95 viafb_LCD_ON = 0;
96 viafb_DeviceStatus = DVI_Device; 96 viafb_DeviceStatus = DVI_Device;
97 viafb_set_iga_path();
97 return viafb_DeviceStatus; 98 return viafb_DeviceStatus;
98 } 99 }
99 status = 1; 100 status = 1;
@@ -107,6 +108,7 @@ int viafb_ioctl_hotplug(int hres, int vres, int bpp)
107 viafb_LCD_ON = 0; 108 viafb_LCD_ON = 0;
108 109
109 viafb_DeviceStatus = CRT_Device; 110 viafb_DeviceStatus = CRT_Device;
111 viafb_set_iga_path();
110 return viafb_DeviceStatus; 112 return viafb_DeviceStatus;
111 } 113 }
112 114
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c
index fc25ae30c5f6..6e06981d638b 100644
--- a/drivers/video/via/lcd.c
+++ b/drivers/video/via/lcd.c
@@ -21,10 +21,18 @@
21#include <linux/via-core.h> 21#include <linux/via-core.h>
22#include <linux/via_i2c.h> 22#include <linux/via_i2c.h>
23#include "global.h" 23#include "global.h"
24#include "lcdtbl.h"
25 24
26#define viafb_compact_res(x, y) (((x)<<16)|(y)) 25#define viafb_compact_res(x, y) (((x)<<16)|(y))
27 26
27/* CLE266 Software Power Sequence */
28/* {Mask}, {Data}, {Delay} */
29static const int PowerSequenceOn[3][3] = {
30 {0x10, 0x08, 0x06}, {0x10, 0x08, 0x06}, {0x19, 0x1FE, 0x01}
31};
32static const int PowerSequenceOff[3][3] = {
33 {0x06, 0x08, 0x10}, {0x00, 0x00, 0x00}, {0xD2, 0x19, 0x01}
34};
35
28static struct _lcd_scaling_factor lcd_scaling_factor = { 36static struct _lcd_scaling_factor lcd_scaling_factor = {
29 /* LCD Horizontal Scaling Factor Register */ 37 /* LCD Horizontal Scaling Factor Register */
30 {LCD_HOR_SCALING_FACTOR_REG_NUM, 38 {LCD_HOR_SCALING_FACTOR_REG_NUM,
@@ -40,9 +48,8 @@ static struct _lcd_scaling_factor lcd_scaling_factor_CLE = {
40 {LCD_VER_SCALING_FACTOR_REG_NUM_CLE, {{CR78, 0, 7}, {CR79, 6, 7} } } 48 {LCD_VER_SCALING_FACTOR_REG_NUM_CLE, {{CR78, 0, 7}, {CR79, 6, 7} } }
41}; 49};
42 50
43static int check_lvds_chip(int device_id_subaddr, int device_id);
44static bool lvds_identify_integratedlvds(void); 51static bool lvds_identify_integratedlvds(void);
45static void fp_id_to_vindex(int panel_id); 52static void __devinit fp_id_to_vindex(int panel_id);
46static int lvds_register_read(int index); 53static int lvds_register_read(int index);
47static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres, 54static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
48 int panel_vres); 55 int panel_vres);
@@ -76,21 +83,16 @@ static struct display_timing lcd_centering_timging(struct display_timing
76 mode_crt_reg, 83 mode_crt_reg,
77 struct display_timing panel_crt_reg); 84 struct display_timing panel_crt_reg);
78 85
79static int check_lvds_chip(int device_id_subaddr, int device_id) 86static inline bool check_lvds_chip(int device_id_subaddr, int device_id)
80{ 87{
81 if (lvds_register_read(device_id_subaddr) == device_id) 88 return lvds_register_read(device_id_subaddr) == device_id;
82 return OK;
83 else
84 return FAIL;
85} 89}
86 90
87void viafb_init_lcd_size(void) 91void __devinit viafb_init_lcd_size(void)
88{ 92{
89 DEBUG_MSG(KERN_INFO "viafb_init_lcd_size()\n"); 93 DEBUG_MSG(KERN_INFO "viafb_init_lcd_size()\n");
90 94
91 fp_id_to_vindex(viafb_lcd_panel_id); 95 fp_id_to_vindex(viafb_lcd_panel_id);
92 viaparinfo->lvds_setting_info2->lcd_panel_id =
93 viaparinfo->lvds_setting_info->lcd_panel_id;
94 viaparinfo->lvds_setting_info2->lcd_panel_hres = 96 viaparinfo->lvds_setting_info2->lcd_panel_hres =
95 viaparinfo->lvds_setting_info->lcd_panel_hres; 97 viaparinfo->lvds_setting_info->lcd_panel_hres;
96 viaparinfo->lvds_setting_info2->lcd_panel_vres = 98 viaparinfo->lvds_setting_info2->lcd_panel_vres =
@@ -144,7 +146,7 @@ static bool lvds_identify_integratedlvds(void)
144 return true; 146 return true;
145} 147}
146 148
147int viafb_lvds_trasmitter_identify(void) 149bool __devinit viafb_lvds_trasmitter_identify(void)
148{ 150{
149 if (viafb_lvds_identify_vt1636(VIA_PORT_31)) { 151 if (viafb_lvds_identify_vt1636(VIA_PORT_31)) {
150 viaparinfo->chip_info->lvds_chip_info.i2c_port = VIA_PORT_31; 152 viaparinfo->chip_info->lvds_chip_info.i2c_port = VIA_PORT_31;
@@ -169,23 +171,23 @@ int viafb_lvds_trasmitter_identify(void)
169 viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr = 171 viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
170 VT1631_LVDS_I2C_ADDR; 172 VT1631_LVDS_I2C_ADDR;
171 173
172 if (check_lvds_chip(VT1631_DEVICE_ID_REG, VT1631_DEVICE_ID) != FAIL) { 174 if (check_lvds_chip(VT1631_DEVICE_ID_REG, VT1631_DEVICE_ID)) {
173 DEBUG_MSG(KERN_INFO "\n VT1631 LVDS ! \n"); 175 DEBUG_MSG(KERN_INFO "\n VT1631 LVDS ! \n");
174 DEBUG_MSG(KERN_INFO "\n %2d", 176 DEBUG_MSG(KERN_INFO "\n %2d",
175 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name); 177 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
176 DEBUG_MSG(KERN_INFO "\n %2d", 178 DEBUG_MSG(KERN_INFO "\n %2d",
177 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name); 179 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
178 return OK; 180 return true;
179 } 181 }
180 182
181 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = 183 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
182 NON_LVDS_TRANSMITTER; 184 NON_LVDS_TRANSMITTER;
183 viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr = 185 viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
184 VT1631_LVDS_I2C_ADDR; 186 VT1631_LVDS_I2C_ADDR;
185 return FAIL; 187 return false;
186} 188}
187 189
188static void fp_id_to_vindex(int panel_id) 190static void __devinit fp_id_to_vindex(int panel_id)
189{ 191{
190 DEBUG_MSG(KERN_INFO "fp_get_panel_id()\n"); 192 DEBUG_MSG(KERN_INFO "fp_get_panel_id()\n");
191 193
@@ -197,176 +199,132 @@ static void fp_id_to_vindex(int panel_id)
197 case 0x0: 199 case 0x0:
198 viaparinfo->lvds_setting_info->lcd_panel_hres = 640; 200 viaparinfo->lvds_setting_info->lcd_panel_hres = 640;
199 viaparinfo->lvds_setting_info->lcd_panel_vres = 480; 201 viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
200 viaparinfo->lvds_setting_info->lcd_panel_id =
201 LCD_PANEL_ID0_640X480;
202 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 202 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
203 viaparinfo->lvds_setting_info->LCDDithering = 1; 203 viaparinfo->lvds_setting_info->LCDDithering = 1;
204 break; 204 break;
205 case 0x1: 205 case 0x1:
206 viaparinfo->lvds_setting_info->lcd_panel_hres = 800; 206 viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
207 viaparinfo->lvds_setting_info->lcd_panel_vres = 600; 207 viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
208 viaparinfo->lvds_setting_info->lcd_panel_id =
209 LCD_PANEL_ID1_800X600;
210 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 208 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
211 viaparinfo->lvds_setting_info->LCDDithering = 1; 209 viaparinfo->lvds_setting_info->LCDDithering = 1;
212 break; 210 break;
213 case 0x2: 211 case 0x2:
214 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; 212 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
215 viaparinfo->lvds_setting_info->lcd_panel_vres = 768; 213 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
216 viaparinfo->lvds_setting_info->lcd_panel_id =
217 LCD_PANEL_ID2_1024X768;
218 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 214 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
219 viaparinfo->lvds_setting_info->LCDDithering = 1; 215 viaparinfo->lvds_setting_info->LCDDithering = 1;
220 break; 216 break;
221 case 0x3: 217 case 0x3:
222 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; 218 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
223 viaparinfo->lvds_setting_info->lcd_panel_vres = 768; 219 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
224 viaparinfo->lvds_setting_info->lcd_panel_id =
225 LCD_PANEL_ID3_1280X768;
226 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 220 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
227 viaparinfo->lvds_setting_info->LCDDithering = 1; 221 viaparinfo->lvds_setting_info->LCDDithering = 1;
228 break; 222 break;
229 case 0x4: 223 case 0x4:
230 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; 224 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
231 viaparinfo->lvds_setting_info->lcd_panel_vres = 1024; 225 viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
232 viaparinfo->lvds_setting_info->lcd_panel_id =
233 LCD_PANEL_ID4_1280X1024;
234 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; 226 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
235 viaparinfo->lvds_setting_info->LCDDithering = 1; 227 viaparinfo->lvds_setting_info->LCDDithering = 1;
236 break; 228 break;
237 case 0x5: 229 case 0x5:
238 viaparinfo->lvds_setting_info->lcd_panel_hres = 1400; 230 viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
239 viaparinfo->lvds_setting_info->lcd_panel_vres = 1050; 231 viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
240 viaparinfo->lvds_setting_info->lcd_panel_id =
241 LCD_PANEL_ID5_1400X1050;
242 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; 232 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
243 viaparinfo->lvds_setting_info->LCDDithering = 1; 233 viaparinfo->lvds_setting_info->LCDDithering = 1;
244 break; 234 break;
245 case 0x6: 235 case 0x6:
246 viaparinfo->lvds_setting_info->lcd_panel_hres = 1600; 236 viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
247 viaparinfo->lvds_setting_info->lcd_panel_vres = 1200; 237 viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
248 viaparinfo->lvds_setting_info->lcd_panel_id =
249 LCD_PANEL_ID6_1600X1200;
250 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; 238 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
251 viaparinfo->lvds_setting_info->LCDDithering = 1; 239 viaparinfo->lvds_setting_info->LCDDithering = 1;
252 break; 240 break;
253 case 0x8: 241 case 0x8:
254 viaparinfo->lvds_setting_info->lcd_panel_hres = 800; 242 viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
255 viaparinfo->lvds_setting_info->lcd_panel_vres = 480; 243 viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
256 viaparinfo->lvds_setting_info->lcd_panel_id =
257 LCD_PANEL_IDA_800X480;
258 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 244 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
259 viaparinfo->lvds_setting_info->LCDDithering = 1; 245 viaparinfo->lvds_setting_info->LCDDithering = 1;
260 break; 246 break;
261 case 0x9: 247 case 0x9:
262 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; 248 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
263 viaparinfo->lvds_setting_info->lcd_panel_vres = 768; 249 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
264 viaparinfo->lvds_setting_info->lcd_panel_id =
265 LCD_PANEL_ID2_1024X768;
266 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; 250 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
267 viaparinfo->lvds_setting_info->LCDDithering = 1; 251 viaparinfo->lvds_setting_info->LCDDithering = 1;
268 break; 252 break;
269 case 0xA: 253 case 0xA:
270 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; 254 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
271 viaparinfo->lvds_setting_info->lcd_panel_vres = 768; 255 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
272 viaparinfo->lvds_setting_info->lcd_panel_id =
273 LCD_PANEL_ID2_1024X768;
274 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 256 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
275 viaparinfo->lvds_setting_info->LCDDithering = 0; 257 viaparinfo->lvds_setting_info->LCDDithering = 0;
276 break; 258 break;
277 case 0xB: 259 case 0xB:
278 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; 260 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
279 viaparinfo->lvds_setting_info->lcd_panel_vres = 768; 261 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
280 viaparinfo->lvds_setting_info->lcd_panel_id =
281 LCD_PANEL_ID2_1024X768;
282 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; 262 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
283 viaparinfo->lvds_setting_info->LCDDithering = 0; 263 viaparinfo->lvds_setting_info->LCDDithering = 0;
284 break; 264 break;
285 case 0xC: 265 case 0xC:
286 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; 266 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
287 viaparinfo->lvds_setting_info->lcd_panel_vres = 768; 267 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
288 viaparinfo->lvds_setting_info->lcd_panel_id =
289 LCD_PANEL_ID3_1280X768;
290 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 268 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
291 viaparinfo->lvds_setting_info->LCDDithering = 0; 269 viaparinfo->lvds_setting_info->LCDDithering = 0;
292 break; 270 break;
293 case 0xD: 271 case 0xD:
294 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; 272 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
295 viaparinfo->lvds_setting_info->lcd_panel_vres = 1024; 273 viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
296 viaparinfo->lvds_setting_info->lcd_panel_id =
297 LCD_PANEL_ID4_1280X1024;
298 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; 274 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
299 viaparinfo->lvds_setting_info->LCDDithering = 0; 275 viaparinfo->lvds_setting_info->LCDDithering = 0;
300 break; 276 break;
301 case 0xE: 277 case 0xE:
302 viaparinfo->lvds_setting_info->lcd_panel_hres = 1400; 278 viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
303 viaparinfo->lvds_setting_info->lcd_panel_vres = 1050; 279 viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
304 viaparinfo->lvds_setting_info->lcd_panel_id =
305 LCD_PANEL_ID5_1400X1050;
306 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; 280 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
307 viaparinfo->lvds_setting_info->LCDDithering = 0; 281 viaparinfo->lvds_setting_info->LCDDithering = 0;
308 break; 282 break;
309 case 0xF: 283 case 0xF:
310 viaparinfo->lvds_setting_info->lcd_panel_hres = 1600; 284 viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
311 viaparinfo->lvds_setting_info->lcd_panel_vres = 1200; 285 viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
312 viaparinfo->lvds_setting_info->lcd_panel_id =
313 LCD_PANEL_ID6_1600X1200;
314 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; 286 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
315 viaparinfo->lvds_setting_info->LCDDithering = 0; 287 viaparinfo->lvds_setting_info->LCDDithering = 0;
316 break; 288 break;
317 case 0x10: 289 case 0x10:
318 viaparinfo->lvds_setting_info->lcd_panel_hres = 1366; 290 viaparinfo->lvds_setting_info->lcd_panel_hres = 1366;
319 viaparinfo->lvds_setting_info->lcd_panel_vres = 768; 291 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
320 viaparinfo->lvds_setting_info->lcd_panel_id =
321 LCD_PANEL_ID7_1366X768;
322 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 292 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
323 viaparinfo->lvds_setting_info->LCDDithering = 0; 293 viaparinfo->lvds_setting_info->LCDDithering = 0;
324 break; 294 break;
325 case 0x11: 295 case 0x11:
326 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; 296 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
327 viaparinfo->lvds_setting_info->lcd_panel_vres = 600; 297 viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
328 viaparinfo->lvds_setting_info->lcd_panel_id =
329 LCD_PANEL_ID8_1024X600;
330 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 298 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
331 viaparinfo->lvds_setting_info->LCDDithering = 1; 299 viaparinfo->lvds_setting_info->LCDDithering = 1;
332 break; 300 break;
333 case 0x12: 301 case 0x12:
334 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; 302 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
335 viaparinfo->lvds_setting_info->lcd_panel_vres = 768; 303 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
336 viaparinfo->lvds_setting_info->lcd_panel_id =
337 LCD_PANEL_ID3_1280X768;
338 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; 304 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
339 viaparinfo->lvds_setting_info->LCDDithering = 1; 305 viaparinfo->lvds_setting_info->LCDDithering = 1;
340 break; 306 break;
341 case 0x13: 307 case 0x13:
342 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; 308 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
343 viaparinfo->lvds_setting_info->lcd_panel_vres = 800; 309 viaparinfo->lvds_setting_info->lcd_panel_vres = 800;
344 viaparinfo->lvds_setting_info->lcd_panel_id =
345 LCD_PANEL_ID9_1280X800;
346 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 310 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
347 viaparinfo->lvds_setting_info->LCDDithering = 1; 311 viaparinfo->lvds_setting_info->LCDDithering = 1;
348 break; 312 break;
349 case 0x14: 313 case 0x14:
350 viaparinfo->lvds_setting_info->lcd_panel_hres = 1360; 314 viaparinfo->lvds_setting_info->lcd_panel_hres = 1360;
351 viaparinfo->lvds_setting_info->lcd_panel_vres = 768; 315 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
352 viaparinfo->lvds_setting_info->lcd_panel_id =
353 LCD_PANEL_IDB_1360X768;
354 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 316 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
355 viaparinfo->lvds_setting_info->LCDDithering = 0; 317 viaparinfo->lvds_setting_info->LCDDithering = 0;
356 break; 318 break;
357 case 0x15: 319 case 0x15:
358 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; 320 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
359 viaparinfo->lvds_setting_info->lcd_panel_vres = 768; 321 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
360 viaparinfo->lvds_setting_info->lcd_panel_id =
361 LCD_PANEL_ID3_1280X768;
362 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; 322 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
363 viaparinfo->lvds_setting_info->LCDDithering = 0; 323 viaparinfo->lvds_setting_info->LCDDithering = 0;
364 break; 324 break;
365 case 0x16: 325 case 0x16:
366 viaparinfo->lvds_setting_info->lcd_panel_hres = 480; 326 viaparinfo->lvds_setting_info->lcd_panel_hres = 480;
367 viaparinfo->lvds_setting_info->lcd_panel_vres = 640; 327 viaparinfo->lvds_setting_info->lcd_panel_vres = 640;
368 viaparinfo->lvds_setting_info->lcd_panel_id =
369 LCD_PANEL_IDC_480X640;
370 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 328 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
371 viaparinfo->lvds_setting_info->LCDDithering = 1; 329 viaparinfo->lvds_setting_info->LCDDithering = 1;
372 break; 330 break;
@@ -374,16 +332,12 @@ static void fp_id_to_vindex(int panel_id)
374 /* OLPC XO-1.5 panel */ 332 /* OLPC XO-1.5 panel */
375 viaparinfo->lvds_setting_info->lcd_panel_hres = 1200; 333 viaparinfo->lvds_setting_info->lcd_panel_hres = 1200;
376 viaparinfo->lvds_setting_info->lcd_panel_vres = 900; 334 viaparinfo->lvds_setting_info->lcd_panel_vres = 900;
377 viaparinfo->lvds_setting_info->lcd_panel_id =
378 LCD_PANEL_IDD_1200X900;
379 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 335 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
380 viaparinfo->lvds_setting_info->LCDDithering = 0; 336 viaparinfo->lvds_setting_info->LCDDithering = 0;
381 break; 337 break;
382 default: 338 default:
383 viaparinfo->lvds_setting_info->lcd_panel_hres = 800; 339 viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
384 viaparinfo->lvds_setting_info->lcd_panel_vres = 600; 340 viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
385 viaparinfo->lvds_setting_info->lcd_panel_id =
386 LCD_PANEL_ID1_800X600;
387 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 341 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
388 viaparinfo->lvds_setting_info->LCDDithering = 1; 342 viaparinfo->lvds_setting_info->LCDDithering = 1;
389 } 343 }
@@ -436,6 +390,7 @@ static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
436 case UNICHROME_CN750: 390 case UNICHROME_CN750:
437 case UNICHROME_VX800: 391 case UNICHROME_VX800:
438 case UNICHROME_VX855: 392 case UNICHROME_VX855:
393 case UNICHROME_VX900:
439 reg_value = 394 reg_value =
440 K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres); 395 K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
441 /* Horizontal scaling enabled */ 396 /* Horizontal scaling enabled */
@@ -479,6 +434,7 @@ static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
479 case UNICHROME_CN750: 434 case UNICHROME_CN750:
480 case UNICHROME_VX800: 435 case UNICHROME_VX800:
481 case UNICHROME_VX855: 436 case UNICHROME_VX855:
437 case UNICHROME_VX900:
482 reg_value = 438 reg_value =
483 K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres); 439 K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
484 /* Vertical scaling enabled */ 440 /* Vertical scaling enabled */
@@ -602,7 +558,7 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
602 int set_vres = plvds_setting_info->v_active; 558 int set_vres = plvds_setting_info->v_active;
603 int panel_hres = plvds_setting_info->lcd_panel_hres; 559 int panel_hres = plvds_setting_info->lcd_panel_hres;
604 int panel_vres = plvds_setting_info->lcd_panel_vres; 560 int panel_vres = plvds_setting_info->lcd_panel_vres;
605 u32 pll_D_N; 561 u32 clock;
606 struct display_timing mode_crt_reg, panel_crt_reg; 562 struct display_timing mode_crt_reg, panel_crt_reg;
607 struct crt_mode_table *panel_crt_table = NULL; 563 struct crt_mode_table *panel_crt_table = NULL;
608 struct VideoModeTable *vmode_tbl = viafb_get_mode(panel_hres, 564 struct VideoModeTable *vmode_tbl = viafb_get_mode(panel_hres,
@@ -617,7 +573,9 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
617 DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n"); 573 DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n");
618 if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) 574 if (VT1636_LVDS == plvds_chip_info->lvds_chip_name)
619 viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info); 575 viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info);
620 plvds_setting_info->vclk = panel_crt_table->clk; 576 clock = panel_crt_reg.hor_total * panel_crt_reg.ver_total
577 * panel_crt_table->refresh_rate;
578 plvds_setting_info->vclk = clock;
621 if (set_iga == IGA1) { 579 if (set_iga == IGA1) {
622 /* IGA1 doesn't have LCD scaling, so set it as centering. */ 580 /* IGA1 doesn't have LCD scaling, so set it as centering. */
623 viafb_load_crtc_timing(lcd_centering_timging 581 viafb_load_crtc_timing(lcd_centering_timging
@@ -651,13 +609,7 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
651 viafb_load_FIFO_reg(set_iga, set_hres, set_vres); 609 viafb_load_FIFO_reg(set_iga, set_hres, set_vres);
652 610
653 fill_lcd_format(); 611 fill_lcd_format();
654 612 viafb_set_vclock(clock, set_iga);
655 pll_D_N = viafb_get_clk_value(panel_crt_table[0].clk);
656 DEBUG_MSG(KERN_INFO "PLL=0x%x", pll_D_N);
657 viafb_set_vclock(pll_D_N, set_iga);
658
659 viafb_set_output_path(DEVICE_LCD, set_iga,
660 plvds_chip_info->output_interface);
661 lcd_patch_skew(plvds_setting_info, plvds_chip_info); 613 lcd_patch_skew(plvds_setting_info, plvds_chip_info);
662 614
663 /* If K8M800, enable LCD Prefetch Mode. */ 615 /* If K8M800, enable LCD Prefetch Mode. */
@@ -700,9 +652,6 @@ static void integrated_lvds_disable(struct lvds_setting_information
700 viafb_write_reg_mask(CR91, VIACR, 0xC0, BIT6 + BIT7); 652 viafb_write_reg_mask(CR91, VIACR, 0xC0, BIT6 + BIT7);
701 } 653 }
702 654
703 /* Turn DFP High/Low Pad off. */
704 viafb_write_reg_mask(SR2A, VIASR, 0, BIT0 + BIT1 + BIT2 + BIT3);
705
706 /* Power off LVDS channel. */ 655 /* Power off LVDS channel. */
707 switch (plvds_chip_info->output_interface) { 656 switch (plvds_chip_info->output_interface) {
708 case INTERFACE_LVDS0: 657 case INTERFACE_LVDS0:
@@ -758,9 +707,6 @@ static void integrated_lvds_enable(struct lvds_setting_information
758 break; 707 break;
759 } 708 }
760 709
761 /* Turn DFP High/Low pad on. */
762 viafb_write_reg_mask(SR2A, VIASR, 0x0F, BIT0 + BIT1 + BIT2 + BIT3);
763
764 /* Power on LVDS channel. */ 710 /* Power on LVDS channel. */
765 switch (plvds_chip_info->output_interface) { 711 switch (plvds_chip_info->output_interface) {
766 case INTERFACE_LVDS0: 712 case INTERFACE_LVDS0:
@@ -809,29 +755,48 @@ void viafb_lcd_disable(void)
809 viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info, 755 viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
810 &viaparinfo->chip_info->lvds_chip_info); 756 &viaparinfo->chip_info->lvds_chip_info);
811 } else { 757 } else {
812 /* DFP-HL pad off */
813 viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x0F);
814 /* Backlight off */ 758 /* Backlight off */
815 viafb_write_reg_mask(SR3D, VIASR, 0x00, 0x20); 759 viafb_write_reg_mask(SR3D, VIASR, 0x00, 0x20);
816 /* 24 bit DI data paht off */ 760 /* 24 bit DI data paht off */
817 viafb_write_reg_mask(CR91, VIACR, 0x80, 0x80); 761 viafb_write_reg_mask(CR91, VIACR, 0x80, 0x80);
818 /* Simultaneout disabled */
819 viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08);
820 } 762 }
821 763
822 /* Disable expansion bit */ 764 /* Disable expansion bit */
823 viafb_write_reg_mask(CR79, VIACR, 0x00, 0x01); 765 viafb_write_reg_mask(CR79, VIACR, 0x00, 0x01);
824 /* CRT path set to IGA1 */
825 viafb_write_reg_mask(SR16, VIASR, 0x00, 0x40);
826 /* Simultaneout disabled */ 766 /* Simultaneout disabled */
827 viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08); 767 viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08);
828 /* IGA2 path disabled */ 768}
829 viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x80);
830 769
770static void set_lcd_output_path(int set_iga, int output_interface)
771{
772 switch (output_interface) {
773 case INTERFACE_DFP:
774 if ((UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name)
775 || (UNICHROME_P4M890 ==
776 viaparinfo->chip_info->gfx_chip_name))
777 viafb_write_reg_mask(CR97, VIACR, 0x84,
778 BIT7 + BIT2 + BIT1 + BIT0);
779 case INTERFACE_DVP0:
780 case INTERFACE_DVP1:
781 case INTERFACE_DFP_HIGH:
782 case INTERFACE_DFP_LOW:
783 if (set_iga == IGA2)
784 viafb_write_reg(CR91, VIACR, 0x00);
785 break;
786 }
831} 787}
832 788
833void viafb_lcd_enable(void) 789void viafb_lcd_enable(void)
834{ 790{
791 viafb_write_reg_mask(CR6B, VIACR, 0x00, BIT3);
792 viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
793 set_lcd_output_path(viaparinfo->lvds_setting_info->iga_path,
794 viaparinfo->chip_info->lvds_chip_info.output_interface);
795 if (viafb_LCD2_ON)
796 set_lcd_output_path(viaparinfo->lvds_setting_info2->iga_path,
797 viaparinfo->chip_info->
798 lvds_chip_info2.output_interface);
799
835 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) { 800 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
836 /* DI1 pad on */ 801 /* DI1 pad on */
837 viafb_write_reg_mask(SR1E, VIASR, 0x30, 0x30); 802 viafb_write_reg_mask(SR1E, VIASR, 0x30, 0x30);
@@ -855,39 +820,13 @@ void viafb_lcd_enable(void)
855 viafb_enable_lvds_vt1636(viaparinfo->lvds_setting_info, 820 viafb_enable_lvds_vt1636(viaparinfo->lvds_setting_info,
856 &viaparinfo->chip_info->lvds_chip_info); 821 &viaparinfo->chip_info->lvds_chip_info);
857 } else { 822 } else {
858 /* DFP-HL pad on */
859 viafb_write_reg_mask(SR2A, VIASR, 0x0F, 0x0F);
860 /* Backlight on */ 823 /* Backlight on */
861 viafb_write_reg_mask(SR3D, VIASR, 0x20, 0x20); 824 viafb_write_reg_mask(SR3D, VIASR, 0x20, 0x20);
862 /* 24 bit DI data paht on */ 825 /* 24 bit DI data paht on */
863 viafb_write_reg_mask(CR91, VIACR, 0x00, 0x80); 826 viafb_write_reg_mask(CR91, VIACR, 0x00, 0x80);
864
865 /* Set data source selection bit by iga path */
866 if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
867 /* DFP-H set to IGA1 */
868 viafb_write_reg_mask(CR97, VIACR, 0x00, 0x10);
869 /* DFP-L set to IGA1 */
870 viafb_write_reg_mask(CR99, VIACR, 0x00, 0x10);
871 } else {
872 /* DFP-H set to IGA2 */
873 viafb_write_reg_mask(CR97, VIACR, 0x10, 0x10);
874 /* DFP-L set to IGA2 */
875 viafb_write_reg_mask(CR99, VIACR, 0x10, 0x10);
876 }
877 /* LCD enabled */ 827 /* LCD enabled */
878 viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48); 828 viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48);
879 } 829 }
880
881 if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
882 /* CRT path set to IGA2 */
883 viafb_write_reg_mask(SR16, VIASR, 0x40, 0x40);
884 /* IGA2 path disabled */
885 viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x80);
886 /* IGA2 path enabled */
887 } else { /* IGA2 */
888 viafb_write_reg_mask(CR6A, VIACR, 0x80, 0x80);
889 }
890
891} 830}
892 831
893static void lcd_powersequence_off(void) 832static void lcd_powersequence_off(void)
@@ -993,7 +932,7 @@ static void check_diport_of_integrated_lvds(
993 plvds_chip_info->output_interface); 932 plvds_chip_info->output_interface);
994} 933}
995 934
996void viafb_init_lvds_output_interface(struct lvds_chip_information 935void __devinit viafb_init_lvds_output_interface(struct lvds_chip_information
997 *plvds_chip_info, 936 *plvds_chip_info,
998 struct lvds_setting_information 937 struct lvds_setting_information
999 *plvds_setting_info) 938 *plvds_setting_info)
@@ -1072,34 +1011,33 @@ static struct display_timing lcd_centering_timging(struct display_timing
1072 1011
1073bool viafb_lcd_get_mobile_state(bool *mobile) 1012bool viafb_lcd_get_mobile_state(bool *mobile)
1074{ 1013{
1075 unsigned char *romptr, *tableptr; 1014 unsigned char __iomem *romptr, *tableptr, *biosptr;
1076 u8 core_base; 1015 u8 core_base;
1077 unsigned char *biosptr;
1078 /* Rom address */ 1016 /* Rom address */
1079 u32 romaddr = 0x000C0000; 1017 const u32 romaddr = 0x000C0000;
1080 u16 start_pattern = 0; 1018 u16 start_pattern;
1081 1019
1082 biosptr = ioremap(romaddr, 0x10000); 1020 biosptr = ioremap(romaddr, 0x10000);
1021 start_pattern = readw(biosptr);
1083 1022
1084 memcpy(&start_pattern, biosptr, 2);
1085 /* Compare pattern */ 1023 /* Compare pattern */
1086 if (start_pattern == 0xAA55) { 1024 if (start_pattern == 0xAA55) {
1087 /* Get the start of Table */ 1025 /* Get the start of Table */
1088 /* 0x1B means BIOS offset position */ 1026 /* 0x1B means BIOS offset position */
1089 romptr = biosptr + 0x1B; 1027 romptr = biosptr + 0x1B;
1090 tableptr = biosptr + *((u16 *) romptr); 1028 tableptr = biosptr + readw(romptr);
1091 1029
1092 /* Get the start of biosver structure */ 1030 /* Get the start of biosver structure */
1093 /* 18 means BIOS version position. */ 1031 /* 18 means BIOS version position. */
1094 romptr = tableptr + 18; 1032 romptr = tableptr + 18;
1095 romptr = biosptr + *((u16 *) romptr); 1033 romptr = biosptr + readw(romptr);
1096 1034
1097 /* The offset should be 44, but the 1035 /* The offset should be 44, but the
1098 actual image is less three char. */ 1036 actual image is less three char. */
1099 /* pRom += 44; */ 1037 /* pRom += 44; */
1100 romptr += 41; 1038 romptr += 41;
1101 1039
1102 core_base = *romptr++; 1040 core_base = readb(romptr);
1103 1041
1104 if (core_base & 0x8) 1042 if (core_base & 0x8)
1105 *mobile = false; 1043 *mobile = false;
diff --git a/drivers/video/via/lcd.h b/drivers/video/via/lcd.h
index b348efc360b8..75f60a655b0e 100644
--- a/drivers/video/via/lcd.h
+++ b/drivers/video/via/lcd.h
@@ -71,15 +71,15 @@ void viafb_enable_lvds_vt1636(struct lvds_setting_information
71 struct lvds_chip_information *plvds_chip_info); 71 struct lvds_chip_information *plvds_chip_info);
72void viafb_lcd_disable(void); 72void viafb_lcd_disable(void);
73void viafb_lcd_enable(void); 73void viafb_lcd_enable(void);
74void viafb_init_lcd_size(void); 74void __devinit viafb_init_lcd_size(void);
75void viafb_init_lvds_output_interface(struct lvds_chip_information 75void __devinit viafb_init_lvds_output_interface(struct lvds_chip_information
76 *plvds_chip_info, 76 *plvds_chip_info,
77 struct lvds_setting_information 77 struct lvds_setting_information
78 *plvds_setting_info); 78 *plvds_setting_info);
79void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, 79void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
80 struct lvds_setting_information *plvds_setting_info, 80 struct lvds_setting_information *plvds_setting_info,
81 struct lvds_chip_information *plvds_chip_info); 81 struct lvds_chip_information *plvds_chip_info);
82int viafb_lvds_trasmitter_identify(void); 82bool __devinit viafb_lvds_trasmitter_identify(void);
83void viafb_init_lvds_output_interface(struct lvds_chip_information 83void viafb_init_lvds_output_interface(struct lvds_chip_information
84 *plvds_chip_info, 84 *plvds_chip_info,
85 struct lvds_setting_information 85 struct lvds_setting_information
diff --git a/drivers/video/via/lcdtbl.h b/drivers/video/via/lcdtbl.h
deleted file mode 100644
index 6f3dd800be59..000000000000
--- a/drivers/video/via/lcdtbl.h
+++ /dev/null
@@ -1,591 +0,0 @@
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
index 2cbe1031b421..61b0bd596b85 100644
--- a/drivers/video/via/share.h
+++ b/drivers/video/via/share.h
@@ -22,14 +22,6 @@
22#ifndef __SHARE_H__ 22#ifndef __SHARE_H__
23#define __SHARE_H__ 23#define __SHARE_H__
24 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 */ 25/* Define Bit Field */
34#define BIT0 0x01 26#define BIT0 0x01
35#define BIT1 0x02 27#define BIT1 0x02
@@ -290,6 +282,7 @@
290#define HW_LAYOUT_LCD_EXTERNAL_LCD2 0x10 282#define HW_LAYOUT_LCD_EXTERNAL_LCD2 0x10
291 283
292/* Definition Refresh Rate */ 284/* Definition Refresh Rate */
285#define REFRESH_49 49
293#define REFRESH_50 50 286#define REFRESH_50 50
294#define REFRESH_60 60 287#define REFRESH_60 60
295#define REFRESH_75 75 288#define REFRESH_75 75
@@ -575,10 +568,6 @@
575#define M1280X720_R50_HSP NEGATIVE 568#define M1280X720_R50_HSP NEGATIVE
576#define M1280X720_R50_VSP POSITIVE 569#define M1280X720_R50_VSP POSITIVE
577 570
578/* 1280x720@60 Sync Polarity (CEA Mode) */
579#define M1280X720_CEA_R60_HSP POSITIVE
580#define M1280X720_CEA_R60_VSP POSITIVE
581
582/* 1440x900@60 Sync Polarity (CVT Mode) */ 571/* 1440x900@60 Sync Polarity (CVT Mode) */
583#define M1440X900_R60_HSP NEGATIVE 572#define M1440X900_R60_HSP NEGATIVE
584#define M1440X900_R60_VSP POSITIVE 573#define M1440X900_R60_VSP POSITIVE
@@ -619,85 +608,10 @@
619#define M1920X1200_RB_R60_HSP POSITIVE 608#define M1920X1200_RB_R60_HSP POSITIVE
620#define M1920X1200_RB_R60_VSP NEGATIVE 609#define M1920X1200_RB_R60_VSP NEGATIVE
621 610
622/* 1920x1080@60 Sync Polarity (CEA Mode) */
623#define M1920X1080_CEA_R60_HSP POSITIVE
624#define M1920X1080_CEA_R60_VSP POSITIVE
625
626/* 2048x1536@60 Sync Polarity (CVT Mode) */ 611/* 2048x1536@60 Sync Polarity (CVT Mode) */
627#define M2048x1536_R60_HSP NEGATIVE 612#define M2048x1536_R60_HSP NEGATIVE
628#define M2048x1536_R60_VSP POSITIVE 613#define M2048x1536_R60_VSP POSITIVE
629 614
630/* define PLL index: */
631#define CLK_25_175M 25175000
632#define CLK_26_880M 26880000
633#define CLK_29_581M 29581000
634#define CLK_31_500M 31500000
635#define CLK_31_728M 31728000
636#define CLK_32_668M 32688000
637#define CLK_36_000M 36000000
638#define CLK_40_000M 40000000
639#define CLK_41_291M 41291000
640#define CLK_43_163M 43163000
641#define CLK_45_250M 45250000 /* 45.46MHz */
642#define CLK_46_000M 46000000
643#define CLK_46_996M 46996000
644#define CLK_48_000M 48000000
645#define CLK_48_875M 48875000
646#define CLK_49_500M 49500000
647#define CLK_52_406M 52406000
648#define CLK_52_977M 52977000
649#define CLK_56_250M 56250000
650#define CLK_57_275M 57275000
651#define CLK_60_466M 60466000
652#define CLK_61_500M 61500000
653#define CLK_65_000M 65000000
654#define CLK_65_178M 65178000
655#define CLK_66_750M 66750000 /* 67.116MHz */
656#define CLK_68_179M 68179000
657#define CLK_69_924M 69924000
658#define CLK_70_159M 70159000
659#define CLK_72_000M 72000000
660#define CLK_74_270M 74270000
661#define CLK_78_750M 78750000
662#define CLK_80_136M 80136000
663#define CLK_83_375M 83375000
664#define CLK_83_950M 83950000
665#define CLK_84_750M 84750000 /* 84.537Mhz */
666#define CLK_85_860M 85860000
667#define CLK_88_750M 88750000
668#define CLK_94_500M 94500000
669#define CLK_97_750M 97750000
670#define CLK_101_000M 101000000
671#define CLK_106_500M 106500000
672#define CLK_108_000M 108000000
673#define CLK_113_309M 113309000
674#define CLK_118_840M 118840000
675#define CLK_119_000M 119000000
676#define CLK_121_750M 121750000 /* 121.704MHz */
677#define CLK_125_104M 125104000
678#define CLK_135_000M 135000000
679#define CLK_136_700M 136700000
680#define CLK_138_400M 138400000
681#define CLK_146_760M 146760000
682#define CLK_148_500M 148500000
683
684#define CLK_153_920M 153920000
685#define CLK_156_000M 156000000
686#define CLK_157_500M 157500000
687#define CLK_162_000M 162000000
688#define CLK_187_000M 187000000
689#define CLK_193_295M 193295000
690#define CLK_202_500M 202500000
691#define CLK_204_000M 204000000
692#define CLK_218_500M 218500000
693#define CLK_234_000M 234000000
694#define CLK_267_250M 267250000
695#define CLK_297_500M 297500000
696#define CLK_74_481M 74481000
697#define CLK_172_798M 172798000
698#define CLK_122_614M 122614000
699
700
701/* Definition CRTC Timing Index */ 615/* Definition CRTC Timing Index */
702#define H_TOTAL_INDEX 0 616#define H_TOTAL_INDEX 0
703#define H_ADDR_INDEX 1 617#define H_ADDR_INDEX 1
@@ -722,76 +636,7 @@
722 636
723/* Definition Video Mode Pixel Clock (picoseconds) 637/* Definition Video Mode Pixel Clock (picoseconds)
724*/ 638*/
725#define RES_480X640_60HZ_PIXCLOCK 39722
726#define RES_640X480_60HZ_PIXCLOCK 39722 639#define RES_640X480_60HZ_PIXCLOCK 39722
727#define RES_640X480_75HZ_PIXCLOCK 31747
728#define RES_640X480_85HZ_PIXCLOCK 27777
729#define RES_640X480_100HZ_PIXCLOCK 23168
730#define RES_640X480_120HZ_PIXCLOCK 19081
731#define RES_720X480_60HZ_PIXCLOCK 37020
732#define RES_720X576_60HZ_PIXCLOCK 30611
733#define RES_800X600_60HZ_PIXCLOCK 25000
734#define RES_800X600_75HZ_PIXCLOCK 20203
735#define RES_800X600_85HZ_PIXCLOCK 17777
736#define RES_800X600_100HZ_PIXCLOCK 14667
737#define RES_800X600_120HZ_PIXCLOCK 11912
738#define RES_800X480_60HZ_PIXCLOCK 33805
739#define RES_848X480_60HZ_PIXCLOCK 31756
740#define RES_856X480_60HZ_PIXCLOCK 31518
741#define RES_1024X512_60HZ_PIXCLOCK 24218
742#define RES_1024X600_60HZ_PIXCLOCK 20460
743#define RES_1024X768_60HZ_PIXCLOCK 15385
744#define RES_1024X768_75HZ_PIXCLOCK 12699
745#define RES_1024X768_85HZ_PIXCLOCK 10582
746#define RES_1024X768_100HZ_PIXCLOCK 8825
747#define RES_1152X864_75HZ_PIXCLOCK 9259
748#define RES_1280X768_60HZ_PIXCLOCK 12480
749#define RES_1280X800_60HZ_PIXCLOCK 11994
750#define RES_1280X960_60HZ_PIXCLOCK 9259
751#define RES_1280X1024_60HZ_PIXCLOCK 9260
752#define RES_1280X1024_75HZ_PIXCLOCK 7408
753#define RES_1280X768_85HZ_PIXCLOCK 6349
754#define RES_1440X1050_60HZ_PIXCLOCK 7993
755#define RES_1600X1200_60HZ_PIXCLOCK 6172
756#define RES_1600X1200_75HZ_PIXCLOCK 4938
757#define RES_1280X720_60HZ_PIXCLOCK 13426
758#define RES_1200X900_60HZ_PIXCLOCK 17459
759#define RES_1920X1080_60HZ_PIXCLOCK 5787
760#define RES_1400X1050_60HZ_PIXCLOCK 8214
761#define RES_1400X1050_75HZ_PIXCLOCK 6410
762#define RES_1368X768_60HZ_PIXCLOCK 11647
763#define RES_960X600_60HZ_PIXCLOCK 22099
764#define RES_1000X600_60HZ_PIXCLOCK 20834
765#define RES_1024X576_60HZ_PIXCLOCK 21278
766#define RES_1088X612_60HZ_PIXCLOCK 18877
767#define RES_1152X720_60HZ_PIXCLOCK 14981
768#define RES_1200X720_60HZ_PIXCLOCK 14253
769#define RES_1280X600_60HZ_PIXCLOCK 16260
770#define RES_1280X720_50HZ_PIXCLOCK 16538
771#define RES_1280X768_50HZ_PIXCLOCK 15342
772#define RES_1366X768_50HZ_PIXCLOCK 14301
773#define RES_1366X768_60HZ_PIXCLOCK 11646
774#define RES_1360X768_60HZ_PIXCLOCK 11799
775#define RES_1440X900_60HZ_PIXCLOCK 9390
776#define RES_1440X900_75HZ_PIXCLOCK 7315
777#define RES_1600X900_60HZ_PIXCLOCK 8415
778#define RES_1600X1024_60HZ_PIXCLOCK 7315
779#define RES_1680X1050_60HZ_PIXCLOCK 6814
780#define RES_1680X1050_75HZ_PIXCLOCK 5348
781#define RES_1792X1344_60HZ_PIXCLOCK 4902
782#define RES_1856X1392_60HZ_PIXCLOCK 4577
783#define RES_1920X1200_60HZ_PIXCLOCK 5173
784#define RES_1920X1440_60HZ_PIXCLOCK 4274
785#define RES_1920X1440_75HZ_PIXCLOCK 3367
786#define RES_2048X1536_60HZ_PIXCLOCK 3742
787
788#define RES_1360X768_RB_60HZ_PIXCLOCK 13889
789#define RES_1400X1050_RB_60HZ_PIXCLOCK 9901
790#define RES_1440X900_RB_60HZ_PIXCLOCK 11268
791#define RES_1600X900_RB_60HZ_PIXCLOCK 10230
792#define RES_1680X1050_RB_60HZ_PIXCLOCK 8403
793#define RES_1920X1080_RB_60HZ_PIXCLOCK 7225
794#define RES_1920X1200_RB_60HZ_PIXCLOCK 6497
795 640
796/* LCD display method 641/* LCD display method
797*/ 642*/
@@ -822,7 +667,6 @@ struct display_timing {
822 667
823struct crt_mode_table { 668struct crt_mode_table {
824 int refresh_rate; 669 int refresh_rate;
825 unsigned long clk;
826 int h_sync_polarity; 670 int h_sync_polarity;
827 int v_sync_polarity; 671 int v_sync_polarity;
828 struct display_timing crtc; 672 struct display_timing crtc;
diff --git a/drivers/video/via/tbl1636.c b/drivers/video/via/tbl1636.c
deleted file mode 100644
index 2d8453429d4a..000000000000
--- a/drivers/video/via/tbl1636.c
+++ /dev/null
@@ -1,71 +0,0 @@
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
deleted file mode 100644
index d906055f1511..000000000000
--- a/drivers/video/via/tbl1636.h
+++ /dev/null
@@ -1,34 +0,0 @@
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
index 0c4c8cc712f4..73bb554e7c1e 100644
--- a/drivers/video/via/tblDPASetting.c
+++ b/drivers/video/via/tblDPASetting.c
@@ -20,17 +20,6 @@
20 */ 20 */
21 21
22#include "global.h" 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 23
35struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3324[] = { 24struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3324[] = {
36/* ClkRange, DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1, 25/* ClkRange, DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1,
@@ -57,18 +46,6 @@ struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3324[] = {
57 0x00}, 46 0x00},
58}; 47};
59 48
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[] = { 49struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3327[] = {
73/* ClkRange,DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1, 50/* ClkRange,DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1,
74 DVP1Driving, DFPHigh, DFPLow */ 51 DVP1Driving, DFPHigh, DFPLow */
diff --git a/drivers/video/via/tblDPASetting.h b/drivers/video/via/tblDPASetting.h
index b065a83481d3..6db61519cb5d 100644
--- a/drivers/video/via/tblDPASetting.h
+++ b/drivers/video/via/tblDPASetting.h
@@ -38,9 +38,7 @@ enum DPA_RANGE {
38 DPA_CLK_RANGE_150M 38 DPA_CLK_RANGE_150M
39}; 39};
40 40
41extern struct VT1636_DPA_SETTING VT1636_DPA_SETTING_TBL_VT3324[7];
42extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3324[6]; 41extern 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[]; 42extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3327[];
45extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3364[6]; 43extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3364[6];
46 44
diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c
index 66f403033111..eb112b621735 100644
--- a/drivers/video/via/via-core.c
+++ b/drivers/video/via/via-core.c
@@ -15,12 +15,15 @@
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/interrupt.h> 16#include <linux/interrupt.h>
17#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/list.h>
19#include <linux/pm.h>
20#include <asm/olpc.h>
18 21
19/* 22/*
20 * The default port config. 23 * The default port config.
21 */ 24 */
22static struct via_port_cfg adap_configs[] = { 25static struct via_port_cfg adap_configs[] = {
23 [VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_OFF, VIASR, 0x26 }, 26 [VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x26 },
24 [VIA_PORT_31] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x31 }, 27 [VIA_PORT_31] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x31 },
25 [VIA_PORT_25] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 }, 28 [VIA_PORT_25] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 },
26 [VIA_PORT_2C] = { VIA_PORT_GPIO, VIA_MODE_I2C, VIASR, 0x2c }, 29 [VIA_PORT_2C] = { VIA_PORT_GPIO, VIA_MODE_I2C, VIASR, 0x2c },
@@ -29,6 +32,19 @@ static struct via_port_cfg adap_configs[] = {
29}; 32};
30 33
31/* 34/*
35 * The OLPC XO-1.5 puts the camera power and reset lines onto
36 * GPIO 2C.
37 */
38static const struct via_port_cfg olpc_adap_configs[] = {
39 [VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x26 },
40 [VIA_PORT_31] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x31 },
41 [VIA_PORT_25] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 },
42 [VIA_PORT_2C] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x2c },
43 [VIA_PORT_3D] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x3d },
44 { 0, 0, 0, 0 }
45};
46
47/*
32 * We currently only support one viafb device (will there ever be 48 * We currently only support one viafb device (will there ever be
33 * more than one?), so just declare it globally here. 49 * more than one?), so just declare it globally here.
34 */ 50 */
@@ -95,6 +111,13 @@ EXPORT_SYMBOL_GPL(viafb_irq_disable);
95 111
96/* ---------------------------------------------------------------------- */ 112/* ---------------------------------------------------------------------- */
97/* 113/*
114 * Currently, the camera driver is the only user of the DMA code, so we
115 * only compile it in if the camera driver is being built. Chances are,
116 * most viafb systems will not need to have this extra code for a while.
117 * As soon as another user comes long, the ifdef can be removed.
118 */
119#if defined(CONFIG_VIDEO_VIA_CAMERA) || defined(CONFIG_VIDEO_VIA_CAMERA_MODULE)
120/*
98 * Access to the DMA engine. This currently provides what the camera 121 * Access to the DMA engine. This currently provides what the camera
99 * driver needs (i.e. outgoing only) but is easily expandable if need 122 * driver needs (i.e. outgoing only) but is easily expandable if need
100 * be. 123 * be.
@@ -322,7 +345,7 @@ int viafb_dma_copy_out_sg(unsigned int offset, struct scatterlist *sg, int nsg)
322 return 0; 345 return 0;
323} 346}
324EXPORT_SYMBOL_GPL(viafb_dma_copy_out_sg); 347EXPORT_SYMBOL_GPL(viafb_dma_copy_out_sg);
325 348#endif /* CONFIG_VIDEO_VIA_CAMERA */
326 349
327/* ---------------------------------------------------------------------- */ 350/* ---------------------------------------------------------------------- */
328/* 351/*
@@ -333,7 +356,7 @@ EXPORT_SYMBOL_GPL(viafb_dma_copy_out_sg);
333static u16 via_function3[] = { 356static u16 via_function3[] = {
334 CLE266_FUNCTION3, KM400_FUNCTION3, CN400_FUNCTION3, CN700_FUNCTION3, 357 CLE266_FUNCTION3, KM400_FUNCTION3, CN400_FUNCTION3, CN700_FUNCTION3,
335 CX700_FUNCTION3, KM800_FUNCTION3, KM890_FUNCTION3, P4M890_FUNCTION3, 358 CX700_FUNCTION3, KM800_FUNCTION3, KM890_FUNCTION3, P4M890_FUNCTION3,
336 P4M900_FUNCTION3, VX800_FUNCTION3, VX855_FUNCTION3, 359 P4M900_FUNCTION3, VX800_FUNCTION3, VX855_FUNCTION3, VX900_FUNCTION3,
337}; 360};
338 361
339/* Get the BIOS-configured framebuffer size from PCI configuration space 362/* Get the BIOS-configured framebuffer size from PCI configuration space
@@ -370,6 +393,7 @@ static int viafb_get_fb_size_from_pci(int chip_type)
370 case P4M900_FUNCTION3: 393 case P4M900_FUNCTION3:
371 case VX800_FUNCTION3: 394 case VX800_FUNCTION3:
372 case VX855_FUNCTION3: 395 case VX855_FUNCTION3:
396 case VX900_FUNCTION3:
373 /*case CN750_FUNCTION3: */ 397 /*case CN750_FUNCTION3: */
374 offset = 0xA0; 398 offset = 0xA0;
375 break; 399 break;
@@ -474,11 +498,21 @@ static int __devinit via_pci_setup_mmio(struct viafb_dev *vdev)
474 * Eventually we want to move away from mapping this 498 * Eventually we want to move away from mapping this
475 * entire region. 499 * entire region.
476 */ 500 */
477 vdev->fbmem_start = pci_resource_start(vdev->pdev, 0); 501 if (vdev->chip_type == UNICHROME_VX900)
502 vdev->fbmem_start = pci_resource_start(vdev->pdev, 2);
503 else
504 vdev->fbmem_start = pci_resource_start(vdev->pdev, 0);
478 ret = vdev->fbmem_len = viafb_get_fb_size_from_pci(vdev->chip_type); 505 ret = vdev->fbmem_len = viafb_get_fb_size_from_pci(vdev->chip_type);
479 if (ret < 0) 506 if (ret < 0)
480 goto out_unmap; 507 goto out_unmap;
481 vdev->fbmem = ioremap_nocache(vdev->fbmem_start, vdev->fbmem_len); 508
509 /* try to map less memory on failure, 8 MB should be still enough */
510 for (; vdev->fbmem_len >= 8 << 20; vdev->fbmem_len /= 2) {
511 vdev->fbmem = ioremap_wc(vdev->fbmem_start, vdev->fbmem_len);
512 if (vdev->fbmem)
513 break;
514 }
515
482 if (vdev->fbmem == NULL) { 516 if (vdev->fbmem == NULL) {
483 ret = -ENOMEM; 517 ret = -ENOMEM;
484 goto out_unmap; 518 goto out_unmap;
@@ -507,7 +541,12 @@ static struct viafb_subdev_info {
507 }, 541 },
508 { 542 {
509 .name = "viafb-i2c", 543 .name = "viafb-i2c",
510 } 544 },
545#if defined(CONFIG_VIDEO_VIA_CAMERA) || defined(CONFIG_VIDEO_VIA_CAMERA_MODULE)
546 {
547 .name = "viafb-camera",
548 },
549#endif
511}; 550};
512#define N_SUBDEVS ARRAY_SIZE(viafb_subdevs) 551#define N_SUBDEVS ARRAY_SIZE(viafb_subdevs)
513 552
@@ -559,6 +598,78 @@ static void via_teardown_subdevs(void)
559 } 598 }
560} 599}
561 600
601/*
602 * Power management functions
603 */
604#ifdef CONFIG_PM
605static LIST_HEAD(viafb_pm_hooks);
606static DEFINE_MUTEX(viafb_pm_hooks_lock);
607
608void viafb_pm_register(struct viafb_pm_hooks *hooks)
609{
610 INIT_LIST_HEAD(&hooks->list);
611
612 mutex_lock(&viafb_pm_hooks_lock);
613 list_add_tail(&hooks->list, &viafb_pm_hooks);
614 mutex_unlock(&viafb_pm_hooks_lock);
615}
616EXPORT_SYMBOL_GPL(viafb_pm_register);
617
618void viafb_pm_unregister(struct viafb_pm_hooks *hooks)
619{
620 mutex_lock(&viafb_pm_hooks_lock);
621 list_del(&hooks->list);
622 mutex_unlock(&viafb_pm_hooks_lock);
623}
624EXPORT_SYMBOL_GPL(viafb_pm_unregister);
625
626static int via_suspend(struct pci_dev *pdev, pm_message_t state)
627{
628 struct viafb_pm_hooks *hooks;
629
630 if (state.event != PM_EVENT_SUSPEND)
631 return 0;
632 /*
633 * "I've occasionally hit a few drivers that caused suspend
634 * failures, and each and every time it was a driver bug, and
635 * the right thing to do was to just ignore the error and suspend
636 * anyway - returning an error code and trying to undo the suspend
637 * is not what anybody ever really wants, even if our model
638 *_allows_ for it."
639 * -- Linus Torvalds, Dec. 7, 2009
640 */
641 mutex_lock(&viafb_pm_hooks_lock);
642 list_for_each_entry_reverse(hooks, &viafb_pm_hooks, list)
643 hooks->suspend(hooks->private);
644 mutex_unlock(&viafb_pm_hooks_lock);
645
646 pci_save_state(pdev);
647 pci_disable_device(pdev);
648 pci_set_power_state(pdev, pci_choose_state(pdev, state));
649 return 0;
650}
651
652static int via_resume(struct pci_dev *pdev)
653{
654 struct viafb_pm_hooks *hooks;
655
656 /* Get the bus side powered up */
657 pci_set_power_state(pdev, PCI_D0);
658 pci_restore_state(pdev);
659 if (pci_enable_device(pdev))
660 return 0;
661
662 pci_set_master(pdev);
663
664 /* Now bring back any subdevs */
665 mutex_lock(&viafb_pm_hooks_lock);
666 list_for_each_entry(hooks, &viafb_pm_hooks, list)
667 hooks->resume(hooks->private);
668 mutex_unlock(&viafb_pm_hooks_lock);
669
670 return 0;
671}
672#endif /* CONFIG_PM */
562 673
563static int __devinit via_pci_probe(struct pci_dev *pdev, 674static int __devinit via_pci_probe(struct pci_dev *pdev,
564 const struct pci_device_id *ent) 675 const struct pci_device_id *ent)
@@ -568,6 +679,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
568 ret = pci_enable_device(pdev); 679 ret = pci_enable_device(pdev);
569 if (ret) 680 if (ret)
570 return ret; 681 return ret;
682
571 /* 683 /*
572 * Global device initialization. 684 * Global device initialization.
573 */ 685 */
@@ -575,6 +687,9 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
575 global_dev.pdev = pdev; 687 global_dev.pdev = pdev;
576 global_dev.chip_type = ent->driver_data; 688 global_dev.chip_type = ent->driver_data;
577 global_dev.port_cfg = adap_configs; 689 global_dev.port_cfg = adap_configs;
690 if (machine_is_olpc())
691 global_dev.port_cfg = olpc_adap_configs;
692
578 spin_lock_init(&global_dev.reg_lock); 693 spin_lock_init(&global_dev.reg_lock);
579 ret = via_pci_setup_mmio(&global_dev); 694 ret = via_pci_setup_mmio(&global_dev);
580 if (ret) 695 if (ret)
@@ -635,6 +750,8 @@ static struct pci_device_id via_pci_table[] __devinitdata = {
635 .driver_data = UNICHROME_VX800 }, 750 .driver_data = UNICHROME_VX800 },
636 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX855_DID), 751 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX855_DID),
637 .driver_data = UNICHROME_VX855 }, 752 .driver_data = UNICHROME_VX855 },
753 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX900_DID),
754 .driver_data = UNICHROME_VX900 },
638 { } 755 { }
639}; 756};
640MODULE_DEVICE_TABLE(pci, via_pci_table); 757MODULE_DEVICE_TABLE(pci, via_pci_table);
@@ -644,6 +761,10 @@ static struct pci_driver via_driver = {
644 .id_table = via_pci_table, 761 .id_table = via_pci_table,
645 .probe = via_pci_probe, 762 .probe = via_pci_probe,
646 .remove = __devexit_p(via_pci_remove), 763 .remove = __devexit_p(via_pci_remove),
764#ifdef CONFIG_PM
765 .suspend = via_suspend,
766 .resume = via_resume,
767#endif
647}; 768};
648 769
649static int __init via_core_init(void) 770static int __init via_core_init(void)
diff --git a/drivers/video/via/via-gpio.c b/drivers/video/via/via-gpio.c
index 39acb37e7a1d..ab5341814c74 100644
--- a/drivers/video/via/via-gpio.c
+++ b/drivers/video/via/via-gpio.c
@@ -145,7 +145,7 @@ static int via_gpio_get(struct gpio_chip *chip, unsigned int nr)
145} 145}
146 146
147 147
148static struct viafb_gpio_cfg gpio_config = { 148static struct viafb_gpio_cfg viafb_gpio_config = {
149 .gpio_chip = { 149 .gpio_chip = {
150 .label = "VIAFB onboard GPIO", 150 .label = "VIAFB onboard GPIO",
151 .owner = THIS_MODULE, 151 .owner = THIS_MODULE,
@@ -172,6 +172,28 @@ static void viafb_gpio_disable(struct viafb_gpio *gpio)
172 via_write_reg_mask(VIASR, gpio->vg_port_index, 0, 0x02); 172 via_write_reg_mask(VIASR, gpio->vg_port_index, 0, 0x02);
173} 173}
174 174
175#ifdef CONFIG_PM
176
177static int viafb_gpio_suspend(void *private)
178{
179 return 0;
180}
181
182static int viafb_gpio_resume(void *private)
183{
184 int i;
185
186 for (i = 0; i < viafb_gpio_config.gpio_chip.ngpio; i += 2)
187 viafb_gpio_enable(viafb_gpio_config.active_gpios[i]);
188 return 0;
189}
190
191static struct viafb_pm_hooks viafb_gpio_pm_hooks = {
192 .suspend = viafb_gpio_suspend,
193 .resume = viafb_gpio_resume
194};
195#endif /* CONFIG_PM */
196
175/* 197/*
176 * Look up a specific gpio and return the number it was assigned. 198 * Look up a specific gpio and return the number it was assigned.
177 */ 199 */
@@ -179,9 +201,9 @@ int viafb_gpio_lookup(const char *name)
179{ 201{
180 int i; 202 int i;
181 203
182 for (i = 0; i < gpio_config.gpio_chip.ngpio; i++) 204 for (i = 0; i < viafb_gpio_config.gpio_chip.ngpio; i++)
183 if (!strcmp(name, gpio_config.active_gpios[i]->vg_name)) 205 if (!strcmp(name, viafb_gpio_config.active_gpios[i]->vg_name))
184 return gpio_config.gpio_chip.base + i; 206 return viafb_gpio_config.gpio_chip.base + i;
185 return -1; 207 return -1;
186} 208}
187EXPORT_SYMBOL_GPL(viafb_gpio_lookup); 209EXPORT_SYMBOL_GPL(viafb_gpio_lookup);
@@ -207,14 +229,15 @@ static __devinit int viafb_gpio_probe(struct platform_device *platdev)
207 for (gpio = viafb_all_gpios; 229 for (gpio = viafb_all_gpios;
208 gpio < viafb_all_gpios + VIAFB_NUM_GPIOS; gpio++) 230 gpio < viafb_all_gpios + VIAFB_NUM_GPIOS; gpio++)
209 if (gpio->vg_port_index == port_cfg[i].ioport_index) { 231 if (gpio->vg_port_index == port_cfg[i].ioport_index) {
210 gpio_config.active_gpios[ngpio] = gpio; 232 viafb_gpio_config.active_gpios[ngpio] = gpio;
211 gpio_config.gpio_names[ngpio] = gpio->vg_name; 233 viafb_gpio_config.gpio_names[ngpio] =
234 gpio->vg_name;
212 ngpio++; 235 ngpio++;
213 } 236 }
214 } 237 }
215 gpio_config.gpio_chip.ngpio = ngpio; 238 viafb_gpio_config.gpio_chip.ngpio = ngpio;
216 gpio_config.gpio_chip.names = gpio_config.gpio_names; 239 viafb_gpio_config.gpio_chip.names = viafb_gpio_config.gpio_names;
217 gpio_config.vdev = vdev; 240 viafb_gpio_config.vdev = vdev;
218 if (ngpio == 0) { 241 if (ngpio == 0) {
219 printk(KERN_INFO "viafb: no GPIOs configured\n"); 242 printk(KERN_INFO "viafb: no GPIOs configured\n");
220 return 0; 243 return 0;
@@ -223,19 +246,22 @@ static __devinit int viafb_gpio_probe(struct platform_device *platdev)
223 * Enable the ports. They come in pairs, with a single 246 * Enable the ports. They come in pairs, with a single
224 * enable bit for both. 247 * enable bit for both.
225 */ 248 */
226 spin_lock_irqsave(&gpio_config.vdev->reg_lock, flags); 249 spin_lock_irqsave(&viafb_gpio_config.vdev->reg_lock, flags);
227 for (i = 0; i < ngpio; i += 2) 250 for (i = 0; i < ngpio; i += 2)
228 viafb_gpio_enable(gpio_config.active_gpios[i]); 251 viafb_gpio_enable(viafb_gpio_config.active_gpios[i]);
229 spin_unlock_irqrestore(&gpio_config.vdev->reg_lock, flags); 252 spin_unlock_irqrestore(&viafb_gpio_config.vdev->reg_lock, flags);
230 /* 253 /*
231 * Get registered. 254 * Get registered.
232 */ 255 */
233 gpio_config.gpio_chip.base = -1; /* Dynamic */ 256 viafb_gpio_config.gpio_chip.base = -1; /* Dynamic */
234 ret = gpiochip_add(&gpio_config.gpio_chip); 257 ret = gpiochip_add(&viafb_gpio_config.gpio_chip);
235 if (ret) { 258 if (ret) {
236 printk(KERN_ERR "viafb: failed to add gpios (%d)\n", ret); 259 printk(KERN_ERR "viafb: failed to add gpios (%d)\n", ret);
237 gpio_config.gpio_chip.ngpio = 0; 260 viafb_gpio_config.gpio_chip.ngpio = 0;
238 } 261 }
262#ifdef CONFIG_PM
263 viafb_pm_register(&viafb_gpio_pm_hooks);
264#endif
239 return ret; 265 return ret;
240} 266}
241 267
@@ -245,11 +271,15 @@ static int viafb_gpio_remove(struct platform_device *platdev)
245 unsigned long flags; 271 unsigned long flags;
246 int ret = 0, i; 272 int ret = 0, i;
247 273
274#ifdef CONFIG_PM
275 viafb_pm_unregister(&viafb_gpio_pm_hooks);
276#endif
277
248 /* 278 /*
249 * Get unregistered. 279 * Get unregistered.
250 */ 280 */
251 if (gpio_config.gpio_chip.ngpio > 0) { 281 if (viafb_gpio_config.gpio_chip.ngpio > 0) {
252 ret = gpiochip_remove(&gpio_config.gpio_chip); 282 ret = gpiochip_remove(&viafb_gpio_config.gpio_chip);
253 if (ret) { /* Somebody still using it? */ 283 if (ret) { /* Somebody still using it? */
254 printk(KERN_ERR "Viafb: GPIO remove failed\n"); 284 printk(KERN_ERR "Viafb: GPIO remove failed\n");
255 return ret; 285 return ret;
@@ -258,11 +288,11 @@ static int viafb_gpio_remove(struct platform_device *platdev)
258 /* 288 /*
259 * Disable the ports. 289 * Disable the ports.
260 */ 290 */
261 spin_lock_irqsave(&gpio_config.vdev->reg_lock, flags); 291 spin_lock_irqsave(&viafb_gpio_config.vdev->reg_lock, flags);
262 for (i = 0; i < gpio_config.gpio_chip.ngpio; i += 2) 292 for (i = 0; i < viafb_gpio_config.gpio_chip.ngpio; i += 2)
263 viafb_gpio_disable(gpio_config.active_gpios[i]); 293 viafb_gpio_disable(viafb_gpio_config.active_gpios[i]);
264 gpio_config.gpio_chip.ngpio = 0; 294 viafb_gpio_config.gpio_chip.ngpio = 0;
265 spin_unlock_irqrestore(&gpio_config.vdev->reg_lock, flags); 295 spin_unlock_irqrestore(&viafb_gpio_config.vdev->reg_lock, flags);
266 return ret; 296 return ret;
267} 297}
268 298
diff --git a/drivers/video/via/via_clock.c b/drivers/video/via/via_clock.c
new file mode 100644
index 000000000000..af8f26b643c1
--- /dev/null
+++ b/drivers/video/via/via_clock.c
@@ -0,0 +1,349 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public
8 * License as published by the Free Software Foundation;
9 * either version 2, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
13 * the implied warranty of MERCHANTABILITY or FITNESS FOR
14 * A PARTICULAR PURPOSE.See the GNU General Public License
15 * for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc.,
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22/*
23 * clock and PLL management functions
24 */
25
26#include <linux/kernel.h>
27#include <linux/via-core.h>
28#include "via_clock.h"
29#include "global.h"
30#include "debug.h"
31
32const char *via_slap = "Please slap VIA Technologies to motivate them "
33 "releasing full documentation for your platform!\n";
34
35static inline u32 cle266_encode_pll(struct via_pll_config pll)
36{
37 return (pll.multiplier << 8)
38 | (pll.rshift << 6)
39 | pll.divisor;
40}
41
42static inline u32 k800_encode_pll(struct via_pll_config pll)
43{
44 return ((pll.divisor - 2) << 16)
45 | (pll.rshift << 10)
46 | (pll.multiplier - 2);
47}
48
49static inline u32 vx855_encode_pll(struct via_pll_config pll)
50{
51 return (pll.divisor << 16)
52 | (pll.rshift << 10)
53 | pll.multiplier;
54}
55
56static inline void cle266_set_primary_pll_encoded(u32 data)
57{
58 via_write_reg_mask(VIASR, 0x40, 0x02, 0x02); /* enable reset */
59 via_write_reg(VIASR, 0x46, data & 0xFF);
60 via_write_reg(VIASR, 0x47, (data >> 8) & 0xFF);
61 via_write_reg_mask(VIASR, 0x40, 0x00, 0x02); /* disable reset */
62}
63
64static inline void k800_set_primary_pll_encoded(u32 data)
65{
66 via_write_reg_mask(VIASR, 0x40, 0x02, 0x02); /* enable reset */
67 via_write_reg(VIASR, 0x44, data & 0xFF);
68 via_write_reg(VIASR, 0x45, (data >> 8) & 0xFF);
69 via_write_reg(VIASR, 0x46, (data >> 16) & 0xFF);
70 via_write_reg_mask(VIASR, 0x40, 0x00, 0x02); /* disable reset */
71}
72
73static inline void cle266_set_secondary_pll_encoded(u32 data)
74{
75 via_write_reg_mask(VIASR, 0x40, 0x04, 0x04); /* enable reset */
76 via_write_reg(VIASR, 0x44, data & 0xFF);
77 via_write_reg(VIASR, 0x45, (data >> 8) & 0xFF);
78 via_write_reg_mask(VIASR, 0x40, 0x00, 0x04); /* disable reset */
79}
80
81static inline void k800_set_secondary_pll_encoded(u32 data)
82{
83 via_write_reg_mask(VIASR, 0x40, 0x04, 0x04); /* enable reset */
84 via_write_reg(VIASR, 0x4A, data & 0xFF);
85 via_write_reg(VIASR, 0x4B, (data >> 8) & 0xFF);
86 via_write_reg(VIASR, 0x4C, (data >> 16) & 0xFF);
87 via_write_reg_mask(VIASR, 0x40, 0x00, 0x04); /* disable reset */
88}
89
90static inline void set_engine_pll_encoded(u32 data)
91{
92 via_write_reg_mask(VIASR, 0x40, 0x01, 0x01); /* enable reset */
93 via_write_reg(VIASR, 0x47, data & 0xFF);
94 via_write_reg(VIASR, 0x48, (data >> 8) & 0xFF);
95 via_write_reg(VIASR, 0x49, (data >> 16) & 0xFF);
96 via_write_reg_mask(VIASR, 0x40, 0x00, 0x01); /* disable reset */
97}
98
99static void cle266_set_primary_pll(struct via_pll_config config)
100{
101 cle266_set_primary_pll_encoded(cle266_encode_pll(config));
102}
103
104static void k800_set_primary_pll(struct via_pll_config config)
105{
106 k800_set_primary_pll_encoded(k800_encode_pll(config));
107}
108
109static void vx855_set_primary_pll(struct via_pll_config config)
110{
111 k800_set_primary_pll_encoded(vx855_encode_pll(config));
112}
113
114static void cle266_set_secondary_pll(struct via_pll_config config)
115{
116 cle266_set_secondary_pll_encoded(cle266_encode_pll(config));
117}
118
119static void k800_set_secondary_pll(struct via_pll_config config)
120{
121 k800_set_secondary_pll_encoded(k800_encode_pll(config));
122}
123
124static void vx855_set_secondary_pll(struct via_pll_config config)
125{
126 k800_set_secondary_pll_encoded(vx855_encode_pll(config));
127}
128
129static void k800_set_engine_pll(struct via_pll_config config)
130{
131 set_engine_pll_encoded(k800_encode_pll(config));
132}
133
134static void vx855_set_engine_pll(struct via_pll_config config)
135{
136 set_engine_pll_encoded(vx855_encode_pll(config));
137}
138
139static void set_primary_pll_state(u8 state)
140{
141 u8 value;
142
143 switch (state) {
144 case VIA_STATE_ON:
145 value = 0x20;
146 break;
147 case VIA_STATE_OFF:
148 value = 0x00;
149 break;
150 default:
151 return;
152 }
153
154 via_write_reg_mask(VIASR, 0x2D, value, 0x30);
155}
156
157static void set_secondary_pll_state(u8 state)
158{
159 u8 value;
160
161 switch (state) {
162 case VIA_STATE_ON:
163 value = 0x08;
164 break;
165 case VIA_STATE_OFF:
166 value = 0x00;
167 break;
168 default:
169 return;
170 }
171
172 via_write_reg_mask(VIASR, 0x2D, value, 0x0C);
173}
174
175static void set_engine_pll_state(u8 state)
176{
177 u8 value;
178
179 switch (state) {
180 case VIA_STATE_ON:
181 value = 0x02;
182 break;
183 case VIA_STATE_OFF:
184 value = 0x00;
185 break;
186 default:
187 return;
188 }
189
190 via_write_reg_mask(VIASR, 0x2D, value, 0x03);
191}
192
193static void set_primary_clock_state(u8 state)
194{
195 u8 value;
196
197 switch (state) {
198 case VIA_STATE_ON:
199 value = 0x20;
200 break;
201 case VIA_STATE_OFF:
202 value = 0x00;
203 break;
204 default:
205 return;
206 }
207
208 via_write_reg_mask(VIASR, 0x1B, value, 0x30);
209}
210
211static void set_secondary_clock_state(u8 state)
212{
213 u8 value;
214
215 switch (state) {
216 case VIA_STATE_ON:
217 value = 0x80;
218 break;
219 case VIA_STATE_OFF:
220 value = 0x00;
221 break;
222 default:
223 return;
224 }
225
226 via_write_reg_mask(VIASR, 0x1B, value, 0xC0);
227}
228
229static inline u8 set_clock_source_common(enum via_clksrc source, bool use_pll)
230{
231 u8 data = 0;
232
233 switch (source) {
234 case VIA_CLKSRC_X1:
235 data = 0x00;
236 break;
237 case VIA_CLKSRC_TVX1:
238 data = 0x02;
239 break;
240 case VIA_CLKSRC_TVPLL:
241 data = 0x04; /* 0x06 should be the same */
242 break;
243 case VIA_CLKSRC_DVP1TVCLKR:
244 data = 0x0A;
245 break;
246 case VIA_CLKSRC_CAP0:
247 data = 0xC;
248 break;
249 case VIA_CLKSRC_CAP1:
250 data = 0x0E;
251 break;
252 }
253
254 if (!use_pll)
255 data |= 1;
256
257 return data;
258}
259
260static void set_primary_clock_source(enum via_clksrc source, bool use_pll)
261{
262 u8 data = set_clock_source_common(source, use_pll) << 4;
263 via_write_reg_mask(VIACR, 0x6C, data, 0xF0);
264}
265
266static void set_secondary_clock_source(enum via_clksrc source, bool use_pll)
267{
268 u8 data = set_clock_source_common(source, use_pll);
269 via_write_reg_mask(VIACR, 0x6C, data, 0x0F);
270}
271
272static void dummy_set_clock_state(u8 state)
273{
274 printk(KERN_INFO "Using undocumented set clock state.\n%s", via_slap);
275}
276
277static void dummy_set_clock_source(enum via_clksrc source, bool use_pll)
278{
279 printk(KERN_INFO "Using undocumented set clock source.\n%s", via_slap);
280}
281
282static void dummy_set_pll_state(u8 state)
283{
284 printk(KERN_INFO "Using undocumented set PLL state.\n%s", via_slap);
285}
286
287static void dummy_set_pll(struct via_pll_config config)
288{
289 printk(KERN_INFO "Using undocumented set PLL.\n%s", via_slap);
290}
291
292void via_clock_init(struct via_clock *clock, int gfx_chip)
293{
294 switch (gfx_chip) {
295 case UNICHROME_CLE266:
296 case UNICHROME_K400:
297 clock->set_primary_clock_state = dummy_set_clock_state;
298 clock->set_primary_clock_source = dummy_set_clock_source;
299 clock->set_primary_pll_state = dummy_set_pll_state;
300 clock->set_primary_pll = cle266_set_primary_pll;
301
302 clock->set_secondary_clock_state = dummy_set_clock_state;
303 clock->set_secondary_clock_source = dummy_set_clock_source;
304 clock->set_secondary_pll_state = dummy_set_pll_state;
305 clock->set_secondary_pll = cle266_set_secondary_pll;
306
307 clock->set_engine_pll_state = dummy_set_pll_state;
308 clock->set_engine_pll = dummy_set_pll;
309 break;
310 case UNICHROME_K800:
311 case UNICHROME_PM800:
312 case UNICHROME_CN700:
313 case UNICHROME_CX700:
314 case UNICHROME_CN750:
315 case UNICHROME_K8M890:
316 case UNICHROME_P4M890:
317 case UNICHROME_P4M900:
318 case UNICHROME_VX800:
319 clock->set_primary_clock_state = set_primary_clock_state;
320 clock->set_primary_clock_source = set_primary_clock_source;
321 clock->set_primary_pll_state = set_primary_pll_state;
322 clock->set_primary_pll = k800_set_primary_pll;
323
324 clock->set_secondary_clock_state = set_secondary_clock_state;
325 clock->set_secondary_clock_source = set_secondary_clock_source;
326 clock->set_secondary_pll_state = set_secondary_pll_state;
327 clock->set_secondary_pll = k800_set_secondary_pll;
328
329 clock->set_engine_pll_state = set_engine_pll_state;
330 clock->set_engine_pll = k800_set_engine_pll;
331 break;
332 case UNICHROME_VX855:
333 case UNICHROME_VX900:
334 clock->set_primary_clock_state = set_primary_clock_state;
335 clock->set_primary_clock_source = set_primary_clock_source;
336 clock->set_primary_pll_state = set_primary_pll_state;
337 clock->set_primary_pll = vx855_set_primary_pll;
338
339 clock->set_secondary_clock_state = set_secondary_clock_state;
340 clock->set_secondary_clock_source = set_secondary_clock_source;
341 clock->set_secondary_pll_state = set_secondary_pll_state;
342 clock->set_secondary_pll = vx855_set_secondary_pll;
343
344 clock->set_engine_pll_state = set_engine_pll_state;
345 clock->set_engine_pll = vx855_set_engine_pll;
346 break;
347
348 }
349}
diff --git a/drivers/video/via/via_clock.h b/drivers/video/via/via_clock.h
new file mode 100644
index 000000000000..88714ae0d157
--- /dev/null
+++ b/drivers/video/via/via_clock.h
@@ -0,0 +1,76 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public
8 * License as published by the Free Software Foundation;
9 * either version 2, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
13 * the implied warranty of MERCHANTABILITY or FITNESS FOR
14 * A PARTICULAR PURPOSE.See the GNU General Public License
15 * for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc.,
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22/*
23 * clock and PLL management functions
24 */
25
26#ifndef __VIA_CLOCK_H__
27#define __VIA_CLOCK_H__
28
29#include <linux/types.h>
30
31enum via_clksrc {
32 VIA_CLKSRC_X1 = 0,
33 VIA_CLKSRC_TVX1,
34 VIA_CLKSRC_TVPLL,
35 VIA_CLKSRC_DVP1TVCLKR,
36 VIA_CLKSRC_CAP0,
37 VIA_CLKSRC_CAP1,
38};
39
40struct via_pll_config {
41 u16 multiplier;
42 u8 divisor;
43 u8 rshift;
44};
45
46struct via_clock {
47 void (*set_primary_clock_state)(u8 state);
48 void (*set_primary_clock_source)(enum via_clksrc src, bool use_pll);
49 void (*set_primary_pll_state)(u8 state);
50 void (*set_primary_pll)(struct via_pll_config config);
51
52 void (*set_secondary_clock_state)(u8 state);
53 void (*set_secondary_clock_source)(enum via_clksrc src, bool use_pll);
54 void (*set_secondary_pll_state)(u8 state);
55 void (*set_secondary_pll)(struct via_pll_config config);
56
57 void (*set_engine_pll_state)(u8 state);
58 void (*set_engine_pll)(struct via_pll_config config);
59};
60
61
62static inline u32 get_pll_internal_frequency(u32 ref_freq,
63 struct via_pll_config pll)
64{
65 return ref_freq / pll.divisor * pll.multiplier;
66}
67
68static inline u32 get_pll_output_frequency(u32 ref_freq,
69 struct via_pll_config pll)
70{
71 return get_pll_internal_frequency(ref_freq, pll) >> pll.rshift;
72}
73
74void via_clock_init(struct via_clock *clock, int gfx_chip);
75
76#endif /* __VIA_CLOCK_H__ */
diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c
index da9e4ca94b17..78f1405dbab7 100644
--- a/drivers/video/via/via_i2c.c
+++ b/drivers/video/via/via_i2c.c
@@ -32,7 +32,7 @@
32 */ 32 */
33#define VIAFB_NUM_I2C 5 33#define VIAFB_NUM_I2C 5
34static struct via_i2c_stuff via_i2c_par[VIAFB_NUM_I2C]; 34static struct via_i2c_stuff via_i2c_par[VIAFB_NUM_I2C];
35struct viafb_dev *i2c_vdev; /* Passed in from core */ 35static struct viafb_dev *i2c_vdev; /* Passed in from core */
36 36
37static void via_i2c_setscl(void *data, int state) 37static void via_i2c_setscl(void *data, int state)
38{ 38{
@@ -114,6 +114,7 @@ static void via_i2c_setsda(void *data, int state)
114 114
115int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata) 115int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata)
116{ 116{
117 int ret;
117 u8 mm1[] = {0x00}; 118 u8 mm1[] = {0x00};
118 struct i2c_msg msgs[2]; 119 struct i2c_msg msgs[2];
119 120
@@ -126,11 +127,18 @@ int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata)
126 mm1[0] = index; 127 mm1[0] = index;
127 msgs[0].len = 1; msgs[1].len = 1; 128 msgs[0].len = 1; msgs[1].len = 1;
128 msgs[0].buf = mm1; msgs[1].buf = pdata; 129 msgs[0].buf = mm1; msgs[1].buf = pdata;
129 return i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2); 130 ret = i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2);
131 if (ret == 2)
132 ret = 0;
133 else if (ret >= 0)
134 ret = -EIO;
135
136 return ret;
130} 137}
131 138
132int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data) 139int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data)
133{ 140{
141 int ret;
134 u8 msg[2] = { index, data }; 142 u8 msg[2] = { index, data };
135 struct i2c_msg msgs; 143 struct i2c_msg msgs;
136 144
@@ -140,11 +148,18 @@ int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data)
140 msgs.addr = slave_addr / 2; 148 msgs.addr = slave_addr / 2;
141 msgs.len = 2; 149 msgs.len = 2;
142 msgs.buf = msg; 150 msgs.buf = msg;
143 return i2c_transfer(&via_i2c_par[adap].adapter, &msgs, 1); 151 ret = i2c_transfer(&via_i2c_par[adap].adapter, &msgs, 1);
152 if (ret == 1)
153 ret = 0;
154 else if (ret >= 0)
155 ret = -EIO;
156
157 return ret;
144} 158}
145 159
146int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len) 160int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len)
147{ 161{
162 int ret;
148 u8 mm1[] = {0x00}; 163 u8 mm1[] = {0x00};
149 struct i2c_msg msgs[2]; 164 struct i2c_msg msgs[2];
150 165
@@ -156,7 +171,13 @@ int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len
156 mm1[0] = index; 171 mm1[0] = index;
157 msgs[0].len = 1; msgs[1].len = buff_len; 172 msgs[0].len = 1; msgs[1].len = buff_len;
158 msgs[0].buf = mm1; msgs[1].buf = buff; 173 msgs[0].buf = mm1; msgs[1].buf = buff;
159 return i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2); 174 ret = i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2);
175 if (ret == 2)
176 ret = 0;
177 else if (ret >= 0)
178 ret = -EIO;
179
180 return ret;
160} 181}
161 182
162/* 183/*
@@ -181,14 +202,13 @@ static int create_i2c_bus(struct i2c_adapter *adapter,
181 algo->setscl = via_i2c_setscl; 202 algo->setscl = via_i2c_setscl;
182 algo->getsda = via_i2c_getsda; 203 algo->getsda = via_i2c_getsda;
183 algo->getscl = via_i2c_getscl; 204 algo->getscl = via_i2c_getscl;
184 algo->udelay = 40; 205 algo->udelay = 10;
185 algo->timeout = 20; 206 algo->timeout = 2;
186 algo->data = adap_cfg; 207 algo->data = adap_cfg;
187 208
188 sprintf(adapter->name, "viafb i2c io_port idx 0x%02x", 209 sprintf(adapter->name, "viafb i2c io_port idx 0x%02x",
189 adap_cfg->ioport_index); 210 adap_cfg->ioport_index);
190 adapter->owner = THIS_MODULE; 211 adapter->owner = THIS_MODULE;
191 adapter->id = 0x01FFFF;
192 adapter->class = I2C_CLASS_DDC; 212 adapter->class = I2C_CLASS_DDC;
193 adapter->algo_data = algo; 213 adapter->algo_data = algo;
194 if (pdev) 214 if (pdev)
diff --git a/drivers/video/via/via_utility.c b/drivers/video/via/via_utility.c
index d05ccb62b55f..35458a5eadc8 100644
--- a/drivers/video/via/via_utility.c
+++ b/drivers/video/via/via_utility.c
@@ -174,7 +174,7 @@ void viafb_set_gamma_table(int bpp, unsigned int *gamma_table)
174 } 174 }
175 175
176 /* If adjust Gamma value in SAMM, fill IGA1, 176 /* If adjust Gamma value in SAMM, fill IGA1,
177 IGA2 Gamma table simultanous. */ 177 IGA2 Gamma table simultaneous. */
178 /* Switch to IGA2 Gamma Table */ 178 /* Switch to IGA2 Gamma Table */
179 if ((active_device_amount > 1) && 179 if ((active_device_amount > 1) &&
180 !((viaparinfo->chip_info->gfx_chip_name == 180 !((viaparinfo->chip_info->gfx_chip_name ==
diff --git a/drivers/video/via/via_utility.h b/drivers/video/via/via_utility.h
index 1670ba82143f..f23be1708c14 100644
--- a/drivers/video/via/via_utility.h
+++ b/drivers/video/via/via_utility.h
@@ -21,7 +21,7 @@
21#ifndef __VIAUTILITY_H__ 21#ifndef __VIAUTILITY_H__
22#define __VIAUTILITY_H__ 22#define __VIAUTILITY_H__
23 23
24/* These functions are used to get infomation about device's state */ 24/* These functions are used to get information about device's state */
25void viafb_get_device_support_state(u32 *support_state); 25void viafb_get_device_support_state(u32 *support_state);
26void viafb_get_device_connect_state(u32 *connect_state); 26void viafb_get_device_connect_state(u32 *connect_state);
27bool viafb_lcd_get_support_expand_state(u32 xres, u32 yres); 27bool viafb_lcd_get_support_expand_state(u32 xres, u32 yres);
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index bdd0e4130f4e..cf43c80d27f6 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -24,6 +24,7 @@
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include <linux/stat.h> 25#include <linux/stat.h>
26#include <linux/via-core.h> 26#include <linux/via-core.h>
27#include <asm/olpc.h>
27 28
28#define _MASTER_FILE 29#define _MASTER_FILE
29#include "global.h" 30#include "global.h"
@@ -37,17 +38,19 @@ static char *viafb_mode1;
37static int viafb_bpp = 32; 38static int viafb_bpp = 32;
38static int viafb_bpp1 = 32; 39static int viafb_bpp1 = 32;
39 40
41static unsigned int viafb_second_xres = 640;
42static unsigned int viafb_second_yres = 480;
40static unsigned int viafb_second_offset; 43static unsigned int viafb_second_offset;
41static int viafb_second_size; 44static int viafb_second_size;
42 45
43static int viafb_accel = 1; 46static int viafb_accel = 1;
44 47
45/* Added for specifying active devices.*/ 48/* Added for specifying active devices.*/
46char *viafb_active_dev; 49static char *viafb_active_dev;
47 50
48/*Added for specify lcd output port*/ 51/*Added for specify lcd output port*/
49char *viafb_lcd_port = ""; 52static char *viafb_lcd_port = "";
50char *viafb_dvi_port = ""; 53static char *viafb_dvi_port = "";
51 54
52static void retrieve_device_setting(struct viafb_ioctl_setting 55static void retrieve_device_setting(struct viafb_ioctl_setting
53 *setting_info); 56 *setting_info);
@@ -56,6 +59,32 @@ static int viafb_pan_display(struct fb_var_screeninfo *var,
56 59
57static struct fb_ops viafb_ops; 60static struct fb_ops viafb_ops;
58 61
62/* supported output devices on each IGP
63 * only CX700, VX800, VX855, VX900 were documented
64 * VIA_CRT should be everywhere
65 * VIA_6C can be onle pre-CX700 (probably only on CLE266) as 6C is used for PLL
66 * source selection on CX700 and later
67 * K400 seems to support VIA_96, VIA_DVP1, VIA_LVDS{1,2} as in viamode.c
68 */
69static const u32 supported_odev_map[] = {
70 [UNICHROME_CLE266] = VIA_CRT | VIA_LDVP0 | VIA_LDVP1,
71 [UNICHROME_K400] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
72 | VIA_LVDS2,
73 [UNICHROME_K800] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
74 | VIA_LVDS2,
75 [UNICHROME_PM800] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
76 | VIA_LVDS2,
77 [UNICHROME_CN700] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
78 | VIA_LVDS2,
79 [UNICHROME_CX700] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
80 [UNICHROME_CN750] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
81 [UNICHROME_K8M890] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
82 [UNICHROME_P4M890] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
83 [UNICHROME_P4M900] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
84 [UNICHROME_VX800] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
85 [UNICHROME_VX855] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
86 [UNICHROME_VX900] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
87};
59 88
60static void viafb_fill_var_color_info(struct fb_var_screeninfo *var, u8 depth) 89static void viafb_fill_var_color_info(struct fb_var_screeninfo *var, u8 depth)
61{ 90{
@@ -156,13 +185,24 @@ static int viafb_release(struct fb_info *info, int user)
156 return 0; 185 return 0;
157} 186}
158 187
188static inline int get_var_refresh(struct fb_var_screeninfo *var)
189{
190 u32 htotal, vtotal;
191
192 htotal = var->left_margin + var->xres + var->right_margin
193 + var->hsync_len;
194 vtotal = var->upper_margin + var->yres + var->lower_margin
195 + var->vsync_len;
196 return PICOS2KHZ(var->pixclock) * 1000 / (htotal * vtotal);
197}
198
159static int viafb_check_var(struct fb_var_screeninfo *var, 199static int viafb_check_var(struct fb_var_screeninfo *var,
160 struct fb_info *info) 200 struct fb_info *info)
161{ 201{
162 int htotal, vtotal, depth; 202 int depth, refresh;
163 struct VideoModeTable *vmode_entry; 203 struct VideoModeTable *vmode_entry;
164 struct viafb_par *ppar = info->par; 204 struct viafb_par *ppar = info->par;
165 u32 long_refresh, line; 205 u32 line;
166 206
167 DEBUG_MSG(KERN_INFO "viafb_check_var!\n"); 207 DEBUG_MSG(KERN_INFO "viafb_check_var!\n");
168 /* Sanity check */ 208 /* Sanity check */
@@ -205,17 +245,11 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
205 /* Based on var passed in to calculate the refresh, 245 /* Based on var passed in to calculate the refresh,
206 * because our driver use some modes special. 246 * because our driver use some modes special.
207 */ 247 */
208 htotal = var->xres + var->left_margin + 248 refresh = viafb_get_refresh(var->xres, var->yres,
209 var->right_margin + var->hsync_len; 249 get_var_refresh(var));
210 vtotal = var->yres + var->upper_margin +
211 var->lower_margin + var->vsync_len;
212 long_refresh = 1000000000UL / var->pixclock * 1000;
213 long_refresh /= (htotal * vtotal);
214
215 viafb_refresh = viafb_get_refresh(var->xres, var->yres, long_refresh);
216 250
217 /* Adjust var according to our driver's own table */ 251 /* Adjust var according to our driver's own table */
218 viafb_fill_var_timing_info(var, viafb_refresh, vmode_entry); 252 viafb_fill_var_timing_info(var, refresh, vmode_entry);
219 if (var->accel_flags & FB_ACCELF_TEXT && 253 if (var->accel_flags & FB_ACCELF_TEXT &&
220 !ppar->shared->vdev->engine_mmio) 254 !ppar->shared->vdev->engine_mmio)
221 var->accel_flags = 0; 255 var->accel_flags = 0;
@@ -227,12 +261,13 @@ static int viafb_set_par(struct fb_info *info)
227{ 261{
228 struct viafb_par *viapar = info->par; 262 struct viafb_par *viapar = info->par;
229 struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL; 263 struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL;
264 int refresh;
230 DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); 265 DEBUG_MSG(KERN_INFO "viafb_set_par!\n");
231 266
232 viafb_update_fix(info); 267 viafb_update_fix(info);
233 viapar->depth = fb_get_color_depth(&info->var, &info->fix); 268 viapar->depth = fb_get_color_depth(&info->var, &info->fix);
234 viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres, 269 viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres,
235 viafbinfo->var.bits_per_pixel, viafb_refresh, 0); 270 viafbinfo->var.bits_per_pixel, 0);
236 271
237 vmode_entry = viafb_get_mode(viafbinfo->var.xres, viafbinfo->var.yres); 272 vmode_entry = viafb_get_mode(viafbinfo->var.xres, viafbinfo->var.yres);
238 if (viafb_dual_fb) { 273 if (viafb_dual_fb) {
@@ -240,7 +275,7 @@ static int viafb_set_par(struct fb_info *info)
240 viafbinfo1->var.yres); 275 viafbinfo1->var.yres);
241 viafb_update_device_setting(viafbinfo1->var.xres, 276 viafb_update_device_setting(viafbinfo1->var.xres,
242 viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel, 277 viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel,
243 viafb_refresh1, 1); 278 1);
244 } else if (viafb_SAMM_ON == 1) { 279 } else if (viafb_SAMM_ON == 1) {
245 DEBUG_MSG(KERN_INFO 280 DEBUG_MSG(KERN_INFO
246 "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n", 281 "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n",
@@ -249,14 +284,19 @@ static int viafb_set_par(struct fb_info *info)
249 viafb_second_yres); 284 viafb_second_yres);
250 285
251 viafb_update_device_setting(viafb_second_xres, 286 viafb_update_device_setting(viafb_second_xres,
252 viafb_second_yres, viafb_bpp1, viafb_refresh1, 1); 287 viafb_second_yres, viafb_bpp1, 1);
253 } 288 }
254 289
290 refresh = viafb_get_refresh(info->var.xres, info->var.yres,
291 get_var_refresh(&info->var));
255 if (vmode_entry) { 292 if (vmode_entry) {
256 if (viafb_dual_fb && viapar->iga_path == IGA2) 293 if (viafb_dual_fb && viapar->iga_path == IGA2) {
257 viafb_bpp1 = info->var.bits_per_pixel; 294 viafb_bpp1 = info->var.bits_per_pixel;
258 else 295 viafb_refresh1 = refresh;
296 } else {
259 viafb_bpp = info->var.bits_per_pixel; 297 viafb_bpp = info->var.bits_per_pixel;
298 viafb_refresh = refresh;
299 }
260 300
261 if (info->var.accel_flags & FB_ACCELF_TEXT) 301 if (info->var.accel_flags & FB_ACCELF_TEXT)
262 info->flags &= ~FBINFO_HWACCEL_DISABLED; 302 info->flags &= ~FBINFO_HWACCEL_DISABLED;
@@ -332,22 +372,22 @@ static int viafb_blank(int blank_mode, struct fb_info *info)
332 case FB_BLANK_UNBLANK: 372 case FB_BLANK_UNBLANK:
333 /* Screen: On, HSync: On, VSync: On */ 373 /* Screen: On, HSync: On, VSync: On */
334 /* control CRT monitor power management */ 374 /* control CRT monitor power management */
335 viafb_write_reg_mask(CR36, VIACR, 0x00, BIT4 + BIT5); 375 via_set_state(VIA_CRT, VIA_STATE_ON);
336 break; 376 break;
337 case FB_BLANK_HSYNC_SUSPEND: 377 case FB_BLANK_HSYNC_SUSPEND:
338 /* Screen: Off, HSync: Off, VSync: On */ 378 /* Screen: Off, HSync: Off, VSync: On */
339 /* control CRT monitor power management */ 379 /* control CRT monitor power management */
340 viafb_write_reg_mask(CR36, VIACR, 0x10, BIT4 + BIT5); 380 via_set_state(VIA_CRT, VIA_STATE_STANDBY);
341 break; 381 break;
342 case FB_BLANK_VSYNC_SUSPEND: 382 case FB_BLANK_VSYNC_SUSPEND:
343 /* Screen: Off, HSync: On, VSync: Off */ 383 /* Screen: Off, HSync: On, VSync: Off */
344 /* control CRT monitor power management */ 384 /* control CRT monitor power management */
345 viafb_write_reg_mask(CR36, VIACR, 0x20, BIT4 + BIT5); 385 via_set_state(VIA_CRT, VIA_STATE_SUSPEND);
346 break; 386 break;
347 case FB_BLANK_POWERDOWN: 387 case FB_BLANK_POWERDOWN:
348 /* Screen: Off, HSync: Off, VSync: Off */ 388 /* Screen: Off, HSync: Off, VSync: Off */
349 /* control CRT monitor power management */ 389 /* control CRT monitor power management */
350 viafb_write_reg_mask(CR36, VIACR, 0x30, BIT4 + BIT5); 390 via_set_state(VIA_CRT, VIA_STATE_OFF);
351 break; 391 break;
352 } 392 }
353 393
@@ -403,8 +443,8 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
403 if (viafb_SAMM_ON == 1) { 443 if (viafb_SAMM_ON == 1) {
404 u.viamode.xres_sec = viafb_second_xres; 444 u.viamode.xres_sec = viafb_second_xres;
405 u.viamode.yres_sec = viafb_second_yres; 445 u.viamode.yres_sec = viafb_second_yres;
406 u.viamode.virtual_xres_sec = viafb_second_virtual_xres; 446 u.viamode.virtual_xres_sec = viafb_dual_fb ? viafbinfo1->var.xres_virtual : viafbinfo->var.xres_virtual;
407 u.viamode.virtual_yres_sec = viafb_second_virtual_yres; 447 u.viamode.virtual_yres_sec = viafb_dual_fb ? viafbinfo1->var.yres_virtual : viafbinfo->var.yres_virtual;
408 u.viamode.refresh_sec = viafb_refresh1; 448 u.viamode.refresh_sec = viafb_refresh1;
409 u.viamode.bpp_sec = viafb_bpp1; 449 u.viamode.bpp_sec = viafb_bpp1;
410 } else { 450 } else {
@@ -457,7 +497,7 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
457 if (copy_from_user(&gpu32, argp, sizeof(gpu32))) 497 if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
458 return -EFAULT; 498 return -EFAULT;
459 if (gpu32 & CRT_Device) 499 if (gpu32 & CRT_Device)
460 viafb_crt_enable(); 500 via_set_state(VIA_CRT, VIA_STATE_ON);
461 if (gpu32 & DVI_Device) 501 if (gpu32 & DVI_Device)
462 viafb_dvi_enable(); 502 viafb_dvi_enable();
463 if (gpu32 & LCD_Device) 503 if (gpu32 & LCD_Device)
@@ -467,7 +507,7 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
467 if (copy_from_user(&gpu32, argp, sizeof(gpu32))) 507 if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
468 return -EFAULT; 508 return -EFAULT;
469 if (gpu32 & CRT_Device) 509 if (gpu32 & CRT_Device)
470 viafb_crt_disable(); 510 via_set_state(VIA_CRT, VIA_STATE_OFF);
471 if (gpu32 & DVI_Device) 511 if (gpu32 & DVI_Device)
472 viafb_dvi_disable(); 512 viafb_dvi_disable();
473 if (gpu32 & LCD_Device) 513 if (gpu32 & LCD_Device)
@@ -787,7 +827,8 @@ static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
787 bg_color = cursor->image.bg_color; 827 bg_color = cursor->image.bg_color;
788 if (chip_name == UNICHROME_CX700 || 828 if (chip_name == UNICHROME_CX700 ||
789 chip_name == UNICHROME_VX800 || 829 chip_name == UNICHROME_VX800 ||
790 chip_name == UNICHROME_VX855) { 830 chip_name == UNICHROME_VX855 ||
831 chip_name == UNICHROME_VX900) {
791 fg_color = 832 fg_color =
792 ((info->cmap.red[fg_color] & 0xFFC0) << 14) | 833 ((info->cmap.red[fg_color] & 0xFFC0) << 14) |
793 ((info->cmap.green[fg_color] & 0xFFC0) << 4) | 834 ((info->cmap.green[fg_color] & 0xFFC0) << 4) |
@@ -892,10 +933,8 @@ static int get_primary_device(void)
892 /* Rule: device on iga1 path are the primary device. */ 933 /* Rule: device on iga1 path are the primary device. */
893 if (viafb_SAMM_ON) { 934 if (viafb_SAMM_ON) {
894 if (viafb_CRT_ON) { 935 if (viafb_CRT_ON) {
895 if (viaparinfo->crt_setting_info->iga_path == IGA1) { 936 if (viaparinfo->shared->iga1_devices & VIA_CRT) {
896 DEBUG_MSG(KERN_INFO "CRT IGA Path:%d\n", 937 DEBUG_MSG(KERN_INFO "CRT IGA Path:%d\n", IGA1);
897 viaparinfo->
898 crt_setting_info->iga_path);
899 primary_device = CRT_Device; 938 primary_device = CRT_Device;
900 } 939 }
901 } 940 }
@@ -961,7 +1000,7 @@ static void retrieve_device_setting(struct viafb_ioctl_setting
961 setting_info->lcd_attributes.lcd_mode = viafb_lcd_mode; 1000 setting_info->lcd_attributes.lcd_mode = viafb_lcd_mode;
962} 1001}
963 1002
964static int parse_active_dev(void) 1003static int __init parse_active_dev(void)
965{ 1004{
966 viafb_CRT_ON = STATE_OFF; 1005 viafb_CRT_ON = STATE_OFF;
967 viafb_DVI_ON = STATE_OFF; 1006 viafb_DVI_ON = STATE_OFF;
@@ -973,8 +1012,13 @@ static int parse_active_dev(void)
973 /* Note: The previous of active_dev is primary device, 1012 /* Note: The previous of active_dev is primary device,
974 and the following is secondary device. */ 1013 and the following is secondary device. */
975 if (!viafb_active_dev) { 1014 if (!viafb_active_dev) {
976 viafb_CRT_ON = STATE_ON; 1015 if (machine_is_olpc()) { /* LCD only */
977 viafb_SAMM_ON = STATE_OFF; 1016 viafb_LCD_ON = STATE_ON;
1017 viafb_SAMM_ON = STATE_OFF;
1018 } else {
1019 viafb_CRT_ON = STATE_ON;
1020 viafb_SAMM_ON = STATE_OFF;
1021 }
978 } else if (!strcmp(viafb_active_dev, "CRT+DVI")) { 1022 } else if (!strcmp(viafb_active_dev, "CRT+DVI")) {
979 /* CRT+DVI */ 1023 /* CRT+DVI */
980 viafb_CRT_ON = STATE_ON; 1024 viafb_CRT_ON = STATE_ON;
@@ -1031,7 +1075,7 @@ static int parse_active_dev(void)
1031 return 0; 1075 return 0;
1032} 1076}
1033 1077
1034static int parse_port(char *opt_str, int *output_interface) 1078static int __devinit parse_port(char *opt_str, int *output_interface)
1035{ 1079{
1036 if (!strncmp(opt_str, "DVP0", 4)) 1080 if (!strncmp(opt_str, "DVP0", 4))
1037 *output_interface = INTERFACE_DVP0; 1081 *output_interface = INTERFACE_DVP0;
@@ -1048,7 +1092,7 @@ static int parse_port(char *opt_str, int *output_interface)
1048 return 0; 1092 return 0;
1049} 1093}
1050 1094
1051static void parse_lcd_port(void) 1095static void __devinit parse_lcd_port(void)
1052{ 1096{
1053 parse_port(viafb_lcd_port, &viaparinfo->chip_info->lvds_chip_info. 1097 parse_port(viafb_lcd_port, &viaparinfo->chip_info->lvds_chip_info.
1054 output_interface); 1098 output_interface);
@@ -1061,7 +1105,7 @@ static void parse_lcd_port(void)
1061 output_interface); 1105 output_interface);
1062} 1106}
1063 1107
1064static void parse_dvi_port(void) 1108static void __devinit parse_dvi_port(void)
1065{ 1109{
1066 parse_port(viafb_dvi_port, &viaparinfo->chip_info->tmds_chip_info. 1110 parse_port(viafb_dvi_port, &viaparinfo->chip_info->tmds_chip_info.
1067 output_interface); 1111 output_interface);
@@ -1431,46 +1475,209 @@ static const struct file_operations viafb_vt1636_proc_fops = {
1431 .write = viafb_vt1636_proc_write, 1475 .write = viafb_vt1636_proc_write,
1432}; 1476};
1433 1477
1434static void viafb_init_proc(struct proc_dir_entry **viafb_entry) 1478#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
1479
1480static int viafb_sup_odev_proc_show(struct seq_file *m, void *v)
1435{ 1481{
1436 *viafb_entry = proc_mkdir("viafb", NULL); 1482 via_odev_to_seq(m, supported_odev_map[
1437 if (*viafb_entry) { 1483 viaparinfo->shared->chip_info.gfx_chip_name]);
1438 proc_create("dvp0", 0, *viafb_entry, &viafb_dvp0_proc_fops); 1484 return 0;
1439 proc_create("dvp1", 0, *viafb_entry, &viafb_dvp1_proc_fops); 1485}
1440 proc_create("dfph", 0, *viafb_entry, &viafb_dfph_proc_fops); 1486
1441 proc_create("dfpl", 0, *viafb_entry, &viafb_dfpl_proc_fops); 1487static int viafb_sup_odev_proc_open(struct inode *inode, struct file *file)
1442 if (VT1636_LVDS == viaparinfo->chip_info->lvds_chip_info. 1488{
1443 lvds_chip_name || VT1636_LVDS == 1489 return single_open(file, viafb_sup_odev_proc_show, NULL);
1444 viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) { 1490}
1445 proc_create("vt1636", 0, *viafb_entry, &viafb_vt1636_proc_fops); 1491
1446 } 1492static const struct file_operations viafb_sup_odev_proc_fops = {
1493 .owner = THIS_MODULE,
1494 .open = viafb_sup_odev_proc_open,
1495 .read = seq_read,
1496 .llseek = seq_lseek,
1497 .release = single_release,
1498};
1499
1500static ssize_t odev_update(const char __user *buffer, size_t count, u32 *odev)
1501{
1502 char buf[64], *ptr = buf;
1503 u32 devices;
1504 bool add, sub;
1505
1506 if (count < 1 || count > 63)
1507 return -EINVAL;
1508 if (copy_from_user(&buf[0], buffer, count))
1509 return -EFAULT;
1510 buf[count] = '\0';
1511 add = buf[0] == '+';
1512 sub = buf[0] == '-';
1513 if (add || sub)
1514 ptr++;
1515 devices = via_parse_odev(ptr, &ptr);
1516 if (*ptr == '\n')
1517 ptr++;
1518 if (*ptr != 0)
1519 return -EINVAL;
1520 if (add)
1521 *odev |= devices;
1522 else if (sub)
1523 *odev &= ~devices;
1524 else
1525 *odev = devices;
1526 return count;
1527}
1528
1529static int viafb_iga1_odev_proc_show(struct seq_file *m, void *v)
1530{
1531 via_odev_to_seq(m, viaparinfo->shared->iga1_devices);
1532 return 0;
1533}
1534
1535static int viafb_iga1_odev_proc_open(struct inode *inode, struct file *file)
1536{
1537 return single_open(file, viafb_iga1_odev_proc_show, NULL);
1538}
1539
1540static ssize_t viafb_iga1_odev_proc_write(struct file *file,
1541 const char __user *buffer, size_t count, loff_t *pos)
1542{
1543 u32 dev_on, dev_off, dev_old, dev_new;
1544 ssize_t res;
1545
1546 dev_old = dev_new = viaparinfo->shared->iga1_devices;
1547 res = odev_update(buffer, count, &dev_new);
1548 if (res != count)
1549 return res;
1550 dev_off = dev_old & ~dev_new;
1551 dev_on = dev_new & ~dev_old;
1552 viaparinfo->shared->iga1_devices = dev_new;
1553 viaparinfo->shared->iga2_devices &= ~dev_new;
1554 via_set_state(dev_off, VIA_STATE_OFF);
1555 via_set_source(dev_new, IGA1);
1556 via_set_state(dev_on, VIA_STATE_ON);
1557 return res;
1558}
1559
1560static const struct file_operations viafb_iga1_odev_proc_fops = {
1561 .owner = THIS_MODULE,
1562 .open = viafb_iga1_odev_proc_open,
1563 .read = seq_read,
1564 .llseek = seq_lseek,
1565 .release = single_release,
1566 .write = viafb_iga1_odev_proc_write,
1567};
1568
1569static int viafb_iga2_odev_proc_show(struct seq_file *m, void *v)
1570{
1571 via_odev_to_seq(m, viaparinfo->shared->iga2_devices);
1572 return 0;
1573}
1574
1575static int viafb_iga2_odev_proc_open(struct inode *inode, struct file *file)
1576{
1577 return single_open(file, viafb_iga2_odev_proc_show, NULL);
1578}
1579
1580static ssize_t viafb_iga2_odev_proc_write(struct file *file,
1581 const char __user *buffer, size_t count, loff_t *pos)
1582{
1583 u32 dev_on, dev_off, dev_old, dev_new;
1584 ssize_t res;
1585
1586 dev_old = dev_new = viaparinfo->shared->iga2_devices;
1587 res = odev_update(buffer, count, &dev_new);
1588 if (res != count)
1589 return res;
1590 dev_off = dev_old & ~dev_new;
1591 dev_on = dev_new & ~dev_old;
1592 viaparinfo->shared->iga2_devices = dev_new;
1593 viaparinfo->shared->iga1_devices &= ~dev_new;
1594 via_set_state(dev_off, VIA_STATE_OFF);
1595 via_set_source(dev_new, IGA2);
1596 via_set_state(dev_on, VIA_STATE_ON);
1597 return res;
1598}
1447 1599
1600static const struct file_operations viafb_iga2_odev_proc_fops = {
1601 .owner = THIS_MODULE,
1602 .open = viafb_iga2_odev_proc_open,
1603 .read = seq_read,
1604 .llseek = seq_lseek,
1605 .release = single_release,
1606 .write = viafb_iga2_odev_proc_write,
1607};
1608
1609#define IS_VT1636(lvds_chip) ((lvds_chip).lvds_chip_name == VT1636_LVDS)
1610static void viafb_init_proc(struct viafb_shared *shared)
1611{
1612 struct proc_dir_entry *iga1_entry, *iga2_entry,
1613 *viafb_entry = proc_mkdir("viafb", NULL);
1614
1615 shared->proc_entry = viafb_entry;
1616 if (viafb_entry) {
1617#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
1618 proc_create("dvp0", 0, viafb_entry, &viafb_dvp0_proc_fops);
1619 proc_create("dvp1", 0, viafb_entry, &viafb_dvp1_proc_fops);
1620 proc_create("dfph", 0, viafb_entry, &viafb_dfph_proc_fops);
1621 proc_create("dfpl", 0, viafb_entry, &viafb_dfpl_proc_fops);
1622 if (IS_VT1636(shared->chip_info.lvds_chip_info)
1623 || IS_VT1636(shared->chip_info.lvds_chip_info2))
1624 proc_create("vt1636", 0, viafb_entry,
1625 &viafb_vt1636_proc_fops);
1626#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
1627
1628 proc_create("supported_output_devices", 0, viafb_entry,
1629 &viafb_sup_odev_proc_fops);
1630 iga1_entry = proc_mkdir("iga1", viafb_entry);
1631 shared->iga1_proc_entry = iga1_entry;
1632 proc_create("output_devices", 0, iga1_entry,
1633 &viafb_iga1_odev_proc_fops);
1634 iga2_entry = proc_mkdir("iga2", viafb_entry);
1635 shared->iga2_proc_entry = iga2_entry;
1636 proc_create("output_devices", 0, iga2_entry,
1637 &viafb_iga2_odev_proc_fops);
1448 } 1638 }
1449} 1639}
1450static void viafb_remove_proc(struct proc_dir_entry *viafb_entry) 1640static void viafb_remove_proc(struct viafb_shared *shared)
1451{ 1641{
1452 struct chip_information *chip_info = &viaparinfo->shared->chip_info; 1642 struct proc_dir_entry *viafb_entry = shared->proc_entry,
1643 *iga1_entry = shared->iga1_proc_entry,
1644 *iga2_entry = shared->iga2_proc_entry;
1645
1646 if (!viafb_entry)
1647 return;
1648
1649 remove_proc_entry("output_devices", iga2_entry);
1650 remove_proc_entry("iga2", viafb_entry);
1651 remove_proc_entry("output_devices", iga1_entry);
1652 remove_proc_entry("iga1", viafb_entry);
1653 remove_proc_entry("supported_output_devices", viafb_entry);
1453 1654
1655#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
1454 remove_proc_entry("dvp0", viafb_entry);/* parent dir */ 1656 remove_proc_entry("dvp0", viafb_entry);/* parent dir */
1455 remove_proc_entry("dvp1", viafb_entry); 1657 remove_proc_entry("dvp1", viafb_entry);
1456 remove_proc_entry("dfph", viafb_entry); 1658 remove_proc_entry("dfph", viafb_entry);
1457 remove_proc_entry("dfpl", viafb_entry); 1659 remove_proc_entry("dfpl", viafb_entry);
1458 if (chip_info->lvds_chip_info.lvds_chip_name == VT1636_LVDS 1660 if (IS_VT1636(shared->chip_info.lvds_chip_info)
1459 || chip_info->lvds_chip_info2.lvds_chip_name == VT1636_LVDS) 1661 || IS_VT1636(shared->chip_info.lvds_chip_info2))
1460 remove_proc_entry("vt1636", viafb_entry); 1662 remove_proc_entry("vt1636", viafb_entry);
1663#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
1461 1664
1462 remove_proc_entry("viafb", NULL); 1665 remove_proc_entry("viafb", NULL);
1463} 1666}
1464 1667#undef IS_VT1636
1465#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
1466 1668
1467static int parse_mode(const char *str, u32 *xres, u32 *yres) 1669static int parse_mode(const char *str, u32 *xres, u32 *yres)
1468{ 1670{
1469 char *ptr; 1671 char *ptr;
1470 1672
1471 if (!str) { 1673 if (!str) {
1472 *xres = 640; 1674 if (machine_is_olpc()) {
1473 *yres = 480; 1675 *xres = 1200;
1676 *yres = 900;
1677 } else {
1678 *xres = 640;
1679 *yres = 480;
1680 }
1474 return 0; 1681 return 0;
1475 } 1682 }
1476 1683
@@ -1486,6 +1693,39 @@ static int parse_mode(const char *str, u32 *xres, u32 *yres)
1486} 1693}
1487 1694
1488 1695
1696#ifdef CONFIG_PM
1697static int viafb_suspend(void *unused)
1698{
1699 console_lock();
1700 fb_set_suspend(viafbinfo, 1);
1701 viafb_sync(viafbinfo);
1702 console_unlock();
1703
1704 return 0;
1705}
1706
1707static int viafb_resume(void *unused)
1708{
1709 console_lock();
1710 if (viaparinfo->shared->vdev->engine_mmio)
1711 viafb_reset_engine(viaparinfo);
1712 viafb_set_par(viafbinfo);
1713 if (viafb_dual_fb)
1714 viafb_set_par(viafbinfo1);
1715 fb_set_suspend(viafbinfo, 0);
1716
1717 console_unlock();
1718 return 0;
1719}
1720
1721static struct viafb_pm_hooks viafb_fb_pm_hooks = {
1722 .suspend = viafb_suspend,
1723 .resume = viafb_resume
1724};
1725
1726#endif
1727
1728
1489int __devinit via_fb_pci_probe(struct viafb_dev *vdev) 1729int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
1490{ 1730{
1491 u32 default_xres, default_yres; 1731 u32 default_xres, default_yres;
@@ -1517,7 +1757,6 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
1517 viaparinfo->lvds_setting_info = &viaparinfo->shared->lvds_setting_info; 1757 viaparinfo->lvds_setting_info = &viaparinfo->shared->lvds_setting_info;
1518 viaparinfo->lvds_setting_info2 = 1758 viaparinfo->lvds_setting_info2 =
1519 &viaparinfo->shared->lvds_setting_info2; 1759 &viaparinfo->shared->lvds_setting_info2;
1520 viaparinfo->crt_setting_info = &viaparinfo->shared->crt_setting_info;
1521 viaparinfo->chip_info = &viaparinfo->shared->chip_info; 1760 viaparinfo->chip_info = &viaparinfo->shared->chip_info;
1522 1761
1523 if (viafb_dual_fb) 1762 if (viafb_dual_fb)
@@ -1544,7 +1783,7 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
1544 viafbinfo->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; 1783 viafbinfo->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1545 1784
1546 viafbinfo->pseudo_palette = pseudo_pal; 1785 viafbinfo->pseudo_palette = pseudo_pal;
1547 if (viafb_accel && !viafb_init_engine(viafbinfo)) { 1786 if (viafb_accel && !viafb_setup_engine(viafbinfo)) {
1548 viafbinfo->flags |= FBINFO_HWACCEL_COPYAREA | 1787 viafbinfo->flags |= FBINFO_HWACCEL_COPYAREA |
1549 FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_IMAGEBLIT; 1788 FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_IMAGEBLIT;
1550 default_var.accel_flags = FB_ACCELF_TEXT; 1789 default_var.accel_flags = FB_ACCELF_TEXT;
@@ -1564,27 +1803,18 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
1564 1803
1565 parse_mode(viafb_mode, &default_xres, &default_yres); 1804 parse_mode(viafb_mode, &default_xres, &default_yres);
1566 vmode_entry = viafb_get_mode(default_xres, default_yres); 1805 vmode_entry = viafb_get_mode(default_xres, default_yres);
1567 if (viafb_SAMM_ON == 1) { 1806 if (viafb_SAMM_ON == 1)
1568 parse_mode(viafb_mode1, &viafb_second_xres, 1807 parse_mode(viafb_mode1, &viafb_second_xres,
1569 &viafb_second_yres); 1808 &viafb_second_yres);
1570 1809
1571 viafb_second_virtual_xres = viafb_second_xres;
1572 viafb_second_virtual_yres = viafb_second_yres;
1573 }
1574
1575 default_var.xres = default_xres; 1810 default_var.xres = default_xres;
1576 default_var.yres = default_yres; 1811 default_var.yres = default_yres;
1577 default_var.xres_virtual = default_xres; 1812 default_var.xres_virtual = default_xres;
1578 default_var.yres_virtual = default_yres; 1813 default_var.yres_virtual = default_yres;
1579 default_var.bits_per_pixel = viafb_bpp; 1814 default_var.bits_per_pixel = viafb_bpp;
1580 default_var.pixclock = 1815 viafb_fill_var_timing_info(&default_var, viafb_get_refresh(
1581 viafb_get_pixclock(default_xres, default_yres, viafb_refresh); 1816 default_var.xres, default_var.yres, viafb_refresh),
1582 default_var.left_margin = (default_xres >> 3) & 0xf8; 1817 viafb_get_mode(default_var.xres, default_var.yres));
1583 default_var.right_margin = 32;
1584 default_var.upper_margin = 16;
1585 default_var.lower_margin = 4;
1586 default_var.hsync_len = default_var.left_margin;
1587 default_var.vsync_len = 4;
1588 viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo); 1818 viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo);
1589 viafbinfo->var = default_var; 1819 viafbinfo->var = default_var;
1590 1820
@@ -1620,18 +1850,12 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
1620 1850
1621 default_var.xres = viafb_second_xres; 1851 default_var.xres = viafb_second_xres;
1622 default_var.yres = viafb_second_yres; 1852 default_var.yres = viafb_second_yres;
1623 default_var.xres_virtual = viafb_second_virtual_xres; 1853 default_var.xres_virtual = viafb_second_xres;
1624 default_var.yres_virtual = viafb_second_virtual_yres; 1854 default_var.yres_virtual = viafb_second_yres;
1625 default_var.bits_per_pixel = viafb_bpp1; 1855 default_var.bits_per_pixel = viafb_bpp1;
1626 default_var.pixclock = 1856 viafb_fill_var_timing_info(&default_var, viafb_get_refresh(
1627 viafb_get_pixclock(viafb_second_xres, viafb_second_yres, 1857 default_var.xres, default_var.yres, viafb_refresh1),
1628 viafb_refresh); 1858 viafb_get_mode(default_var.xres, default_var.yres));
1629 default_var.left_margin = (viafb_second_xres >> 3) & 0xf8;
1630 default_var.right_margin = 32;
1631 default_var.upper_margin = 16;
1632 default_var.lower_margin = 4;
1633 default_var.hsync_len = default_var.left_margin;
1634 default_var.vsync_len = 4;
1635 1859
1636 viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1); 1860 viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1);
1637 viafb_check_var(&default_var, viafbinfo1); 1861 viafb_check_var(&default_var, viafbinfo1);
@@ -1671,10 +1895,12 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
1671 viafbinfo->node, viafbinfo->fix.id, default_var.xres, 1895 viafbinfo->node, viafbinfo->fix.id, default_var.xres,
1672 default_var.yres, default_var.bits_per_pixel); 1896 default_var.yres, default_var.bits_per_pixel);
1673 1897
1674#ifdef CONFIG_FB_VIA_DIRECT_PROCFS 1898 viafb_init_proc(viaparinfo->shared);
1675 viafb_init_proc(&viaparinfo->shared->proc_entry);
1676#endif
1677 viafb_init_dac(IGA2); 1899 viafb_init_dac(IGA2);
1900
1901#ifdef CONFIG_PM
1902 viafb_pm_register(&viafb_fb_pm_hooks);
1903#endif
1678 return 0; 1904 return 0;
1679 1905
1680out_fb_unreg: 1906out_fb_unreg:
@@ -1700,20 +1926,23 @@ void __devexit via_fb_pci_remove(struct pci_dev *pdev)
1700 unregister_framebuffer(viafbinfo); 1926 unregister_framebuffer(viafbinfo);
1701 if (viafb_dual_fb) 1927 if (viafb_dual_fb)
1702 unregister_framebuffer(viafbinfo1); 1928 unregister_framebuffer(viafbinfo1);
1703#ifdef CONFIG_FB_VIA_DIRECT_PROCFS 1929 viafb_remove_proc(viaparinfo->shared);
1704 viafb_remove_proc(viaparinfo->shared->proc_entry);
1705#endif
1706 framebuffer_release(viafbinfo); 1930 framebuffer_release(viafbinfo);
1707 if (viafb_dual_fb) 1931 if (viafb_dual_fb)
1708 framebuffer_release(viafbinfo1); 1932 framebuffer_release(viafbinfo1);
1709} 1933}
1710 1934
1711#ifndef MODULE 1935#ifndef MODULE
1712static int __init viafb_setup(char *options) 1936static int __init viafb_setup(void)
1713{ 1937{
1714 char *this_opt; 1938 char *this_opt;
1939 char *options;
1940
1715 DEBUG_MSG(KERN_INFO "viafb_setup!\n"); 1941 DEBUG_MSG(KERN_INFO "viafb_setup!\n");
1716 1942
1943 if (fb_get_options("viafb", &options))
1944 return -ENODEV;
1945
1717 if (!options || !*options) 1946 if (!options || !*options)
1718 return 0; 1947 return 0;
1719 1948
@@ -1786,22 +2015,29 @@ static int __init viafb_setup(char *options)
1786 */ 2015 */
1787int __init viafb_init(void) 2016int __init viafb_init(void)
1788{ 2017{
1789 u32 dummy; 2018 u32 dummy_x, dummy_y;
2019 int r;
2020
2021 if (machine_is_olpc())
2022 /* Apply XO-1.5-specific configuration. */
2023 viafb_lcd_panel_id = 23;
2024
1790#ifndef MODULE 2025#ifndef MODULE
1791 char *option = NULL; 2026 r = viafb_setup();
1792 if (fb_get_options("viafb", &option)) 2027 if (r < 0)
1793 return -ENODEV; 2028 return r;
1794 viafb_setup(option);
1795#endif 2029#endif
1796 if (parse_mode(viafb_mode, &dummy, &dummy) 2030 if (parse_mode(viafb_mode, &dummy_x, &dummy_y)
1797 || parse_mode(viafb_mode1, &dummy, &dummy) 2031 || !viafb_get_mode(dummy_x, dummy_y)
2032 || parse_mode(viafb_mode1, &dummy_x, &dummy_y)
2033 || !viafb_get_mode(dummy_x, dummy_y)
1798 || viafb_bpp < 0 || viafb_bpp > 32 2034 || viafb_bpp < 0 || viafb_bpp > 32
1799 || viafb_bpp1 < 0 || viafb_bpp1 > 32 2035 || viafb_bpp1 < 0 || viafb_bpp1 > 32
1800 || parse_active_dev()) 2036 || parse_active_dev())
1801 return -EINVAL; 2037 return -EINVAL;
1802 2038
1803 printk(KERN_INFO 2039 printk(KERN_INFO
1804 "VIA Graphics Intergration Chipset framebuffer %d.%d initializing\n", 2040 "VIA Graphics Integration Chipset framebuffer %d.%d initializing\n",
1805 VERSION_MAJOR, VERSION_MINOR); 2041 VERSION_MAJOR, VERSION_MINOR);
1806 return 0; 2042 return 0;
1807} 2043}
diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h
index 52a35fabba91..d9440635d1d4 100644
--- a/drivers/video/via/viafbdev.h
+++ b/drivers/video/via/viafbdev.h
@@ -40,12 +40,16 @@
40#define VIAFB_NUM_I2C 5 40#define VIAFB_NUM_I2C 5
41 41
42struct viafb_shared { 42struct viafb_shared {
43 u32 iga1_devices;
44 u32 iga2_devices;
45
43 struct proc_dir_entry *proc_entry; /*viafb proc entry */ 46 struct proc_dir_entry *proc_entry; /*viafb proc entry */
47 struct proc_dir_entry *iga1_proc_entry;
48 struct proc_dir_entry *iga2_proc_entry;
44 struct viafb_dev *vdev; /* Global dev info */ 49 struct viafb_dev *vdev; /* Global dev info */
45 50
46 /* All the information will be needed to set engine */ 51 /* All the information will be needed to set engine */
47 struct tmds_setting_information tmds_setting_info; 52 struct tmds_setting_information tmds_setting_info;
48 struct crt_setting_information crt_setting_info;
49 struct lvds_setting_information lvds_setting_info; 53 struct lvds_setting_information lvds_setting_info;
50 struct lvds_setting_information lvds_setting_info2; 54 struct lvds_setting_information lvds_setting_info2;
51 struct chip_information chip_info; 55 struct chip_information chip_info;
@@ -74,14 +78,11 @@ struct viafb_par {
74 /* All the information will be needed to set engine */ 78 /* All the information will be needed to set engine */
75 /* depreciated, use the ones in shared directly */ 79 /* depreciated, use the ones in shared directly */
76 struct tmds_setting_information *tmds_setting_info; 80 struct tmds_setting_information *tmds_setting_info;
77 struct crt_setting_information *crt_setting_info;
78 struct lvds_setting_information *lvds_setting_info; 81 struct lvds_setting_information *lvds_setting_info;
79 struct lvds_setting_information *lvds_setting_info2; 82 struct lvds_setting_information *lvds_setting_info2;
80 struct chip_information *chip_info; 83 struct chip_information *chip_info;
81}; 84};
82 85
83extern unsigned int viafb_second_virtual_yres;
84extern unsigned int viafb_second_virtual_xres;
85extern int viafb_SAMM_ON; 86extern int viafb_SAMM_ON;
86extern int viafb_dual_fb; 87extern int viafb_dual_fb;
87extern int viafb_LCD2_ON; 88extern int viafb_LCD2_ON;
@@ -89,9 +90,6 @@ extern int viafb_LCD_ON;
89extern int viafb_DVI_ON; 90extern int viafb_DVI_ON;
90extern int viafb_hotplug; 91extern int viafb_hotplug;
91 92
92extern int strict_strtoul(const char *cp, unsigned int base,
93 unsigned long *res);
94
95u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information 93u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
96 *plvds_setting_info, struct lvds_chip_information 94 *plvds_setting_info, struct lvds_chip_information
97 *plvds_chip_info, u8 index); 95 *plvds_chip_info, u8 index);
diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c
index 2dbad3c0f679..58df74e1417e 100644
--- a/drivers/video/via/viamode.c
+++ b/drivers/video/via/viamode.c
@@ -21,72 +21,6 @@
21 21
22#include <linux/via-core.h> 22#include <linux/via-core.h>
23#include "global.h" 23#include "global.h"
24struct res_map_refresh res_map_refresh_tbl[] = {
25/*hres, vres, vclock, vmode_refresh*/
26 {480, 640, RES_480X640_60HZ_PIXCLOCK, 60},
27 {640, 480, RES_640X480_60HZ_PIXCLOCK, 60},
28 {640, 480, RES_640X480_75HZ_PIXCLOCK, 75},
29 {640, 480, RES_640X480_85HZ_PIXCLOCK, 85},
30 {640, 480, RES_640X480_100HZ_PIXCLOCK, 100},
31 {640, 480, RES_640X480_120HZ_PIXCLOCK, 120},
32 {720, 480, RES_720X480_60HZ_PIXCLOCK, 60},
33 {720, 576, RES_720X576_60HZ_PIXCLOCK, 60},
34 {800, 480, RES_800X480_60HZ_PIXCLOCK, 60},
35 {800, 600, RES_800X600_60HZ_PIXCLOCK, 60},
36 {800, 600, RES_800X600_75HZ_PIXCLOCK, 75},
37 {800, 600, RES_800X600_85HZ_PIXCLOCK, 85},
38 {800, 600, RES_800X600_100HZ_PIXCLOCK, 100},
39 {800, 600, RES_800X600_120HZ_PIXCLOCK, 120},
40 {848, 480, RES_848X480_60HZ_PIXCLOCK, 60},
41 {856, 480, RES_856X480_60HZ_PIXCLOCK, 60},
42 {1024, 512, RES_1024X512_60HZ_PIXCLOCK, 60},
43 {1024, 600, RES_1024X600_60HZ_PIXCLOCK, 60},
44 {1024, 768, RES_1024X768_60HZ_PIXCLOCK, 60},
45 {1024, 768, RES_1024X768_75HZ_PIXCLOCK, 75},
46 {1024, 768, RES_1024X768_85HZ_PIXCLOCK, 85},
47 {1024, 768, RES_1024X768_100HZ_PIXCLOCK, 100},
48/* {1152,864, RES_1152X864_70HZ_PIXCLOCK, 70},*/
49 {1152, 864, RES_1152X864_75HZ_PIXCLOCK, 75},
50 {1280, 768, RES_1280X768_60HZ_PIXCLOCK, 60},
51 {1280, 800, RES_1280X800_60HZ_PIXCLOCK, 60},
52 {1280, 960, RES_1280X960_60HZ_PIXCLOCK, 60},
53 {1280, 1024, RES_1280X1024_60HZ_PIXCLOCK, 60},
54 {1280, 1024, RES_1280X1024_75HZ_PIXCLOCK, 75},
55 {1280, 1024, RES_1280X768_85HZ_PIXCLOCK, 85},
56 {1440, 1050, RES_1440X1050_60HZ_PIXCLOCK, 60},
57 {1600, 1200, RES_1600X1200_60HZ_PIXCLOCK, 60},
58 {1600, 1200, RES_1600X1200_75HZ_PIXCLOCK, 75},
59 {1280, 720, RES_1280X720_60HZ_PIXCLOCK, 60},
60 {1920, 1080, RES_1920X1080_60HZ_PIXCLOCK, 60},
61 {1400, 1050, RES_1400X1050_60HZ_PIXCLOCK, 60},
62 {1400, 1050, RES_1400X1050_75HZ_PIXCLOCK, 75},
63 {1368, 768, RES_1368X768_60HZ_PIXCLOCK, 60},
64 {960, 600, RES_960X600_60HZ_PIXCLOCK, 60},
65 {1000, 600, RES_1000X600_60HZ_PIXCLOCK, 60},
66 {1024, 576, RES_1024X576_60HZ_PIXCLOCK, 60},
67 {1088, 612, RES_1088X612_60HZ_PIXCLOCK, 60},
68 {1152, 720, RES_1152X720_60HZ_PIXCLOCK, 60},
69 {1200, 720, RES_1200X720_60HZ_PIXCLOCK, 60},
70 {1200, 900, RES_1200X900_60HZ_PIXCLOCK, 60},
71 {1280, 600, RES_1280X600_60HZ_PIXCLOCK, 60},
72 {1280, 720, RES_1280X720_50HZ_PIXCLOCK, 50},
73 {1280, 768, RES_1280X768_50HZ_PIXCLOCK, 50},
74 {1360, 768, RES_1360X768_60HZ_PIXCLOCK, 60},
75 {1366, 768, RES_1366X768_50HZ_PIXCLOCK, 50},
76 {1366, 768, RES_1366X768_60HZ_PIXCLOCK, 60},
77 {1440, 900, RES_1440X900_60HZ_PIXCLOCK, 60},
78 {1440, 900, RES_1440X900_75HZ_PIXCLOCK, 75},
79 {1600, 900, RES_1600X900_60HZ_PIXCLOCK, 60},
80 {1600, 1024, RES_1600X1024_60HZ_PIXCLOCK, 60},
81 {1680, 1050, RES_1680X1050_60HZ_PIXCLOCK, 60},
82 {1680, 1050, RES_1680X1050_75HZ_PIXCLOCK, 75},
83 {1792, 1344, RES_1792X1344_60HZ_PIXCLOCK, 60},
84 {1856, 1392, RES_1856X1392_60HZ_PIXCLOCK, 60},
85 {1920, 1200, RES_1920X1200_60HZ_PIXCLOCK, 60},
86 {1920, 1440, RES_1920X1440_60HZ_PIXCLOCK, 60},
87 {1920, 1440, RES_1920X1440_75HZ_PIXCLOCK, 75},
88 {2048, 1536, RES_2048X1536_60HZ_PIXCLOCK, 60}
89};
90 24
91struct io_reg CN400_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01}, 25struct io_reg CN400_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
92{VIASR, SR15, 0x02, 0x02}, 26{VIASR, SR15, 0x02, 0x02},
@@ -96,10 +30,6 @@ struct io_reg CN400_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
96{VIASR, SR1A, 0xFB, 0x08}, 30{VIASR, SR1A, 0xFB, 0x08},
97{VIASR, SR1E, 0x0F, 0x01}, 31{VIASR, SR1E, 0x0F, 0x01},
98{VIASR, SR2A, 0xFF, 0x00}, 32{VIASR, SR2A, 0xFF, 0x00},
99{VIACR, CR0A, 0xFF, 0x1E}, /* Cursor Start */
100{VIACR, CR0B, 0xFF, 0x00}, /* Cursor End */
101{VIACR, CR0E, 0xFF, 0x00}, /* Cursor Location High */
102{VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */
103{VIACR, CR32, 0xFF, 0x00}, 33{VIACR, CR32, 0xFF, 0x00},
104{VIACR, CR33, 0xFF, 0x00}, 34{VIACR, CR33, 0xFF, 0x00},
105{VIACR, CR35, 0xFF, 0x00}, 35{VIACR, CR35, 0xFF, 0x00},
@@ -107,21 +37,6 @@ struct io_reg CN400_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
107{VIACR, CR69, 0xFF, 0x00}, 37{VIACR, CR69, 0xFF, 0x00},
108{VIACR, CR6A, 0xFF, 0x40}, 38{VIACR, CR6A, 0xFF, 0x40},
109{VIACR, CR6B, 0xFF, 0x00}, 39{VIACR, CR6B, 0xFF, 0x00},
110{VIACR, CR6C, 0xFF, 0x00},
111{VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */
112{VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */
113{VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */
114{VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */
115{VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */
116{VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */
117{VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */
118{VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */
119{VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */
120{VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */
121{VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */
122{VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */
123{VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */
124{VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */
125{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */ 40{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
126{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */ 41{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
127{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */ 42{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
@@ -167,25 +82,10 @@ struct io_reg CN700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
167{VIACR, CR69, 0xFF, 0x00}, 82{VIACR, CR69, 0xFF, 0x00},
168{VIACR, CR6A, 0xFD, 0x40}, 83{VIACR, CR6A, 0xFD, 0x40},
169{VIACR, CR6B, 0xFF, 0x00}, 84{VIACR, CR6B, 0xFF, 0x00},
170{VIACR, CR6C, 0xFF, 0x00},
171{VIACR, CR77, 0xFF, 0x00}, /* LCD scaling Factor */ 85{VIACR, CR77, 0xFF, 0x00}, /* LCD scaling Factor */
172{VIACR, CR78, 0xFF, 0x00}, /* LCD scaling Factor */ 86{VIACR, CR78, 0xFF, 0x00}, /* LCD scaling Factor */
173{VIACR, CR79, 0xFF, 0x00}, /* LCD scaling Factor */ 87{VIACR, CR79, 0xFF, 0x00}, /* LCD scaling Factor */
174{VIACR, CR9F, 0x03, 0x00}, /* LCD scaling Factor */ 88{VIACR, CR9F, 0x03, 0x00}, /* LCD scaling Factor */
175{VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */
176{VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */
177{VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */
178{VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */
179{VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */
180{VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */
181{VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */
182{VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */
183{VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */
184{VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */
185{VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */
186{VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */
187{VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */
188{VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */
189{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */ 89{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
190{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */ 90{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
191{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */ 91{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
@@ -219,30 +119,12 @@ struct io_reg KM400_ModeXregs[] = {
219 {VIASR, SR2A, 0xFF, 0x00}, /* Power Management Control 5 */ 119 {VIASR, SR2A, 0xFF, 0x00}, /* Power Management Control 5 */
220 {VIASR, SR2D, 0xFF, 0xFF}, /* Power Management Control 1 */ 120 {VIASR, SR2D, 0xFF, 0xFF}, /* Power Management Control 1 */
221 {VIASR, SR2E, 0xFF, 0xFF}, /* Power Management Control 2 */ 121 {VIASR, SR2E, 0xFF, 0xFF}, /* Power Management Control 2 */
222 {VIACR, CR0A, 0xFF, 0x1E}, /* Cursor Start */
223 {VIACR, CR0B, 0xFF, 0x00}, /* Cursor End */
224 {VIACR, CR0E, 0xFF, 0x00}, /* Cursor Location High */
225 {VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */
226 {VIACR, CR33, 0xFF, 0x00}, 122 {VIACR, CR33, 0xFF, 0x00},
227 {VIACR, CR55, 0x80, 0x00}, 123 {VIACR, CR55, 0x80, 0x00},
228 {VIACR, CR5D, 0x80, 0x00}, 124 {VIACR, CR5D, 0x80, 0x00},
229 {VIACR, CR36, 0xFF, 0x01}, /* Power Mangement 3 */ 125 {VIACR, CR36, 0xFF, 0x01}, /* Power Mangement 3 */
230 {VIACR, CR68, 0xFF, 0x67}, /* Default FIFO For IGA2 */ 126 {VIACR, CR68, 0xFF, 0x67}, /* Default FIFO For IGA2 */
231 {VIACR, CR6A, 0x20, 0x20}, /* Extended FIFO On */ 127 {VIACR, CR6A, 0x20, 0x20}, /* Extended FIFO On */
232 {VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */
233 {VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */
234 {VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */
235 {VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */
236 {VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */
237 {VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */
238 {VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */
239 {VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */
240 {VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */
241 {VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */
242 {VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */
243 {VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */
244 {VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */
245 {VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */
246 {VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */ 128 {VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
247 {VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */ 129 {VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
248 {VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */ 130 {VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
@@ -269,11 +151,7 @@ struct io_reg CX700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
269{VIASR, SR1B, 0xFF, 0xF0}, 151{VIASR, SR1B, 0xFF, 0xF0},
270{VIASR, SR1E, 0xFF, 0x01}, 152{VIASR, SR1E, 0xFF, 0x01},
271{VIASR, SR2A, 0xFF, 0x00}, 153{VIASR, SR2A, 0xFF, 0x00},
272{VIASR, SR2D, 0xFF, 0xFF}, /* VCK and LCK PLL power on. */ 154{VIASR, SR2D, 0xC0, 0xC0}, /* delayed E3_ECK */
273{VIACR, CR0A, 0xFF, 0x1E}, /* Cursor Start */
274{VIACR, CR0B, 0xFF, 0x00}, /* Cursor End */
275{VIACR, CR0E, 0xFF, 0x00}, /* Cursor Location High */
276{VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */
277{VIACR, CR32, 0xFF, 0x00}, 155{VIACR, CR32, 0xFF, 0x00},
278{VIACR, CR33, 0xFF, 0x00}, 156{VIACR, CR33, 0xFF, 0x00},
279{VIACR, CR35, 0xFF, 0x00}, 157{VIACR, CR35, 0xFF, 0x00},
@@ -282,21 +160,6 @@ struct io_reg CX700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
282{VIACR, CR69, 0xFF, 0x00}, 160{VIACR, CR69, 0xFF, 0x00},
283{VIACR, CR6A, 0xFF, 0x40}, 161{VIACR, CR6A, 0xFF, 0x40},
284{VIACR, CR6B, 0xFF, 0x00}, 162{VIACR, CR6B, 0xFF, 0x00},
285{VIACR, CR6C, 0xFF, 0x00},
286{VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */
287{VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */
288{VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */
289{VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */
290{VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */
291{VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */
292{VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */
293{VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */
294{VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */
295{VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */
296{VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */
297{VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */
298{VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */
299{VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */
300{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */ 163{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
301{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */ 164{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
302{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */ 165{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
@@ -326,14 +189,7 @@ struct io_reg VX855_ModeXregs[] = {
326{VIASR, SR2A, 0xF0, 0x00}, 189{VIASR, SR2A, 0xF0, 0x00},
327{VIASR, SR58, 0xFF, 0x00}, 190{VIASR, SR58, 0xFF, 0x00},
328{VIASR, SR59, 0xFF, 0x00}, 191{VIASR, SR59, 0xFF, 0x00},
329{VIASR, SR2D, 0xFF, 0xFF}, /* VCK and LCK PLL power on. */ 192{VIASR, SR2D, 0xC0, 0xC0}, /* delayed E3_ECK */
330{VIACR, CR09, 0xFF, 0x00}, /* Initial CR09=0*/
331{VIACR, CR11, 0x8F, 0x00}, /* IGA1 initial Vertical end */
332{VIACR, CR17, 0x7F, 0x00}, /* IGA1 CRT Mode control init */
333{VIACR, CR0A, 0xFF, 0x1E}, /* Cursor Start */
334{VIACR, CR0B, 0xFF, 0x00}, /* Cursor End */
335{VIACR, CR0E, 0xFF, 0x00}, /* Cursor Location High */
336{VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */
337{VIACR, CR32, 0xFF, 0x00}, 193{VIACR, CR32, 0xFF, 0x00},
338{VIACR, CR33, 0x7F, 0x00}, 194{VIACR, CR33, 0x7F, 0x00},
339{VIACR, CR35, 0xFF, 0x00}, 195{VIACR, CR35, 0xFF, 0x00},
@@ -341,21 +197,6 @@ struct io_reg VX855_ModeXregs[] = {
341{VIACR, CR69, 0xFF, 0x00}, 197{VIACR, CR69, 0xFF, 0x00},
342{VIACR, CR6A, 0xFD, 0x60}, 198{VIACR, CR6A, 0xFD, 0x60},
343{VIACR, CR6B, 0xFF, 0x00}, 199{VIACR, CR6B, 0xFF, 0x00},
344{VIACR, CR6C, 0xFF, 0x00},
345{VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */
346{VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */
347{VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */
348{VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */
349{VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */
350{VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */
351{VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */
352{VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */
353{VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */
354{VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */
355{VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */
356{VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */
357{VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */
358{VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */
359{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */ 200{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
360{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */ 201{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
361{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */ 202{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
@@ -390,21 +231,6 @@ struct io_reg CLE266_ModeXregs[] = { {VIASR, SR1E, 0xF0, 0x00},
390{VIAGR, GR20, 0xFF, 0x00}, 231{VIAGR, GR20, 0xFF, 0x00},
391{VIAGR, GR21, 0xFF, 0x00}, 232{VIAGR, GR21, 0xFF, 0x00},
392{VIAGR, GR22, 0xFF, 0x00}, 233{VIAGR, GR22, 0xFF, 0x00},
393 /* LCD Parameters */
394{VIACR, CR7A, 0xFF, 0x01}, /* LCD Parameter 1 */
395{VIACR, CR7B, 0xFF, 0x02}, /* LCD Parameter 2 */
396{VIACR, CR7C, 0xFF, 0x03}, /* LCD Parameter 3 */
397{VIACR, CR7D, 0xFF, 0x04}, /* LCD Parameter 4 */
398{VIACR, CR7E, 0xFF, 0x07}, /* LCD Parameter 5 */
399{VIACR, CR7F, 0xFF, 0x0A}, /* LCD Parameter 6 */
400{VIACR, CR80, 0xFF, 0x0D}, /* LCD Parameter 7 */
401{VIACR, CR81, 0xFF, 0x13}, /* LCD Parameter 8 */
402{VIACR, CR82, 0xFF, 0x16}, /* LCD Parameter 9 */
403{VIACR, CR83, 0xFF, 0x19}, /* LCD Parameter 10 */
404{VIACR, CR84, 0xFF, 0x1C}, /* LCD Parameter 11 */
405{VIACR, CR85, 0xFF, 0x1D}, /* LCD Parameter 12 */
406{VIACR, CR86, 0xFF, 0x1E}, /* LCD Parameter 13 */
407{VIACR, CR87, 0xFF, 0x1F}, /* LCD Parameter 14 */
408 234
409}; 235};
410 236
@@ -443,328 +269,321 @@ struct VPITTable VPIT = {
443/********************/ 269/********************/
444 270
445/* 480x640 */ 271/* 480x640 */
446struct crt_mode_table CRTM480x640[] = { 272static struct crt_mode_table CRTM480x640[] = {
447 /* r_rate, vclk, hsp, vsp */ 273 /* r_rate, hsp, vsp */
448 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 274 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
449 {REFRESH_60, CLK_25_175M, M480X640_R60_HSP, M480X640_R60_VSP, 275 {REFRESH_60, M480X640_R60_HSP, M480X640_R60_VSP,
450 {624, 480, 480, 144, 504, 48, 663, 640, 640, 23, 641, 3} } /* GTF*/ 276 {624, 480, 480, 144, 504, 48, 663, 640, 640, 23, 641, 3} } /* GTF*/
451}; 277};
452 278
453/* 640x480*/ 279/* 640x480*/
454struct crt_mode_table CRTM640x480[] = { 280static struct crt_mode_table CRTM640x480[] = {
455 /*r_rate,vclk,hsp,vsp */ 281 /*r_rate,hsp,vsp */
456 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 282 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
457 {REFRESH_60, CLK_25_175M, M640X480_R60_HSP, M640X480_R60_VSP, 283 {REFRESH_60, M640X480_R60_HSP, M640X480_R60_VSP,
458 {800, 640, 648, 144, 656, 96, 525, 480, 480, 45, 490, 2} }, 284 {800, 640, 648, 144, 656, 96, 525, 480, 480, 45, 490, 2} },
459 {REFRESH_75, CLK_31_500M, M640X480_R75_HSP, M640X480_R75_VSP, 285 {REFRESH_75, M640X480_R75_HSP, M640X480_R75_VSP,
460 {840, 640, 640, 200, 656, 64, 500, 480, 480, 20, 481, 3} }, 286 {840, 640, 640, 200, 656, 64, 500, 480, 480, 20, 481, 3} },
461 {REFRESH_85, CLK_36_000M, M640X480_R85_HSP, M640X480_R85_VSP, 287 {REFRESH_85, M640X480_R85_HSP, M640X480_R85_VSP,
462 {832, 640, 640, 192, 696, 56, 509, 480, 480, 29, 481, 3} }, 288 {832, 640, 640, 192, 696, 56, 509, 480, 480, 29, 481, 3} },
463 {REFRESH_100, CLK_43_163M, M640X480_R100_HSP, M640X480_R100_VSP, 289 {REFRESH_100, M640X480_R100_HSP, M640X480_R100_VSP,
464 {848, 640, 640, 208, 680, 64, 509, 480, 480, 29, 481, 3} }, /*GTF*/ 290 {848, 640, 640, 208, 680, 64, 509, 480, 480, 29, 481, 3} }, /*GTF*/
465 {REFRESH_120, CLK_52_406M, M640X480_R120_HSP, 291 {REFRESH_120, M640X480_R120_HSP, M640X480_R120_VSP,
466 M640X480_R120_VSP, 292 {848, 640, 640, 208, 680, 64, 515, 480, 480, 35, 481, 3} } /*GTF*/
467 {848, 640, 640, 208, 680, 64, 515, 480, 480, 35, 481,
468 3} } /*GTF*/
469}; 293};
470 294
471/*720x480 (GTF)*/ 295/*720x480 (GTF)*/
472struct crt_mode_table CRTM720x480[] = { 296static struct crt_mode_table CRTM720x480[] = {
473 /*r_rate,vclk,hsp,vsp */ 297 /*r_rate,hsp,vsp */
474 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 298 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
475 {REFRESH_60, CLK_26_880M, M720X480_R60_HSP, M720X480_R60_VSP, 299 {REFRESH_60, M720X480_R60_HSP, M720X480_R60_VSP,
476 {896, 720, 720, 176, 736, 72, 497, 480, 480, 17, 481, 3} } 300 {896, 720, 720, 176, 736, 72, 497, 480, 480, 17, 481, 3} }
477 301
478}; 302};
479 303
480/*720x576 (GTF)*/ 304/*720x576 (GTF)*/
481struct crt_mode_table CRTM720x576[] = { 305static struct crt_mode_table CRTM720x576[] = {
482 /*r_rate,vclk,hsp,vsp */ 306 /*r_rate,hsp,vsp */
483 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 307 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
484 {REFRESH_60, CLK_32_668M, M720X576_R60_HSP, M720X576_R60_VSP, 308 {REFRESH_60, M720X576_R60_HSP, M720X576_R60_VSP,
485 {912, 720, 720, 192, 744, 72, 597, 576, 576, 21, 577, 3} } 309 {912, 720, 720, 192, 744, 72, 597, 576, 576, 21, 577, 3} }
486}; 310};
487 311
488/* 800x480 (CVT) */ 312/* 800x480 (CVT) */
489struct crt_mode_table CRTM800x480[] = { 313static struct crt_mode_table CRTM800x480[] = {
490 /* r_rate, vclk, hsp, vsp */ 314 /* r_rate, hsp, vsp */
491 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 315 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
492 {REFRESH_60, CLK_29_581M, M800X480_R60_HSP, M800X480_R60_VSP, 316 {REFRESH_60, M800X480_R60_HSP, M800X480_R60_VSP,
493 {992, 800, 800, 192, 824, 72, 500, 480, 480, 20, 483, 7} } 317 {992, 800, 800, 192, 824, 72, 500, 480, 480, 20, 483, 7} }
494}; 318};
495 319
496/* 800x600*/ 320/* 800x600*/
497struct crt_mode_table CRTM800x600[] = { 321static struct crt_mode_table CRTM800x600[] = {
498 /*r_rate,vclk,hsp,vsp */ 322 /*r_rate,hsp,vsp */
499 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 323 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
500 {REFRESH_60, CLK_40_000M, M800X600_R60_HSP, M800X600_R60_VSP, 324 {REFRESH_60, M800X600_R60_HSP, M800X600_R60_VSP,
501 {1056, 800, 800, 256, 840, 128, 628, 600, 600, 28, 601, 4} }, 325 {1056, 800, 800, 256, 840, 128, 628, 600, 600, 28, 601, 4} },
502 {REFRESH_75, CLK_49_500M, M800X600_R75_HSP, M800X600_R75_VSP, 326 {REFRESH_75, M800X600_R75_HSP, M800X600_R75_VSP,
503 {1056, 800, 800, 256, 816, 80, 625, 600, 600, 25, 601, 3} }, 327 {1056, 800, 800, 256, 816, 80, 625, 600, 600, 25, 601, 3} },
504 {REFRESH_85, CLK_56_250M, M800X600_R85_HSP, M800X600_R85_VSP, 328 {REFRESH_85, M800X600_R85_HSP, M800X600_R85_VSP,
505 {1048, 800, 800, 248, 832, 64, 631, 600, 600, 31, 601, 3} }, 329 {1048, 800, 800, 248, 832, 64, 631, 600, 600, 31, 601, 3} },
506 {REFRESH_100, CLK_68_179M, M800X600_R100_HSP, M800X600_R100_VSP, 330 {REFRESH_100, M800X600_R100_HSP, M800X600_R100_VSP,
507 {1072, 800, 800, 272, 848, 88, 636, 600, 600, 36, 601, 3} }, 331 {1072, 800, 800, 272, 848, 88, 636, 600, 600, 36, 601, 3} },
508 {REFRESH_120, CLK_83_950M, M800X600_R120_HSP, 332 {REFRESH_120, M800X600_R120_HSP, M800X600_R120_VSP,
509 M800X600_R120_VSP, 333 {1088, 800, 800, 288, 856, 88, 643, 600, 600, 43, 601, 3} }
510 {1088, 800, 800, 288, 856, 88, 643, 600, 600, 43, 601,
511 3} }
512}; 334};
513 335
514/* 848x480 (CVT) */ 336/* 848x480 (CVT) */
515struct crt_mode_table CRTM848x480[] = { 337static struct crt_mode_table CRTM848x480[] = {
516 /* r_rate, vclk, hsp, vsp */ 338 /* r_rate, hsp, vsp */
517 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 339 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
518 {REFRESH_60, CLK_31_500M, M848X480_R60_HSP, M848X480_R60_VSP, 340 {REFRESH_60, M848X480_R60_HSP, M848X480_R60_VSP,
519 {1056, 848, 848, 208, 872, 80, 500, 480, 480, 20, 483, 5} } 341 {1056, 848, 848, 208, 872, 80, 500, 480, 480, 20, 483, 5} }
520}; 342};
521 343
522/*856x480 (GTF) convert to 852x480*/ 344/*856x480 (GTF) convert to 852x480*/
523struct crt_mode_table CRTM852x480[] = { 345static struct crt_mode_table CRTM852x480[] = {
524 /*r_rate,vclk,hsp,vsp */ 346 /*r_rate,hsp,vsp */
525 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 347 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
526 {REFRESH_60, CLK_31_728M, M852X480_R60_HSP, M852X480_R60_VSP, 348 {REFRESH_60, M852X480_R60_HSP, M852X480_R60_VSP,
527 {1064, 856, 856, 208, 872, 88, 497, 480, 480, 17, 481, 3} } 349 {1064, 856, 856, 208, 872, 88, 497, 480, 480, 17, 481, 3} }
528}; 350};
529 351
530/*1024x512 (GTF)*/ 352/*1024x512 (GTF)*/
531struct crt_mode_table CRTM1024x512[] = { 353static struct crt_mode_table CRTM1024x512[] = {
532 /*r_rate,vclk,hsp,vsp */ 354 /*r_rate,hsp,vsp */
533 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 355 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
534 {REFRESH_60, CLK_41_291M, M1024X512_R60_HSP, M1024X512_R60_VSP, 356 {REFRESH_60, M1024X512_R60_HSP, M1024X512_R60_VSP,
535 {1296, 1024, 1024, 272, 1056, 104, 531, 512, 512, 19, 513, 3} } 357 {1296, 1024, 1024, 272, 1056, 104, 531, 512, 512, 19, 513, 3} }
536 358
537}; 359};
538 360
539/* 1024x600*/ 361/* 1024x600*/
540struct crt_mode_table CRTM1024x600[] = { 362static struct crt_mode_table CRTM1024x600[] = {
541 /*r_rate,vclk,hsp,vsp */ 363 /*r_rate,hsp,vsp */
542 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 364 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
543 {REFRESH_60, CLK_48_875M, M1024X600_R60_HSP, M1024X600_R60_VSP, 365 {REFRESH_60, M1024X600_R60_HSP, M1024X600_R60_VSP,
544 {1312, 1024, 1024, 288, 1064, 104, 622, 600, 600, 22, 601, 3} }, 366 {1312, 1024, 1024, 288, 1064, 104, 622, 600, 600, 22, 601, 3} },
545}; 367};
546 368
547/* 1024x768*/ 369/* 1024x768*/
548struct crt_mode_table CRTM1024x768[] = { 370static struct crt_mode_table CRTM1024x768[] = {
549 /*r_rate,vclk,hsp,vsp */ 371 /*r_rate,hsp,vsp */
550 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 372 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
551 {REFRESH_60, CLK_65_000M, M1024X768_R60_HSP, M1024X768_R60_VSP, 373 {REFRESH_60, M1024X768_R60_HSP, M1024X768_R60_VSP,
552 {1344, 1024, 1024, 320, 1048, 136, 806, 768, 768, 38, 771, 6} }, 374 {1344, 1024, 1024, 320, 1048, 136, 806, 768, 768, 38, 771, 6} },
553 {REFRESH_75, CLK_78_750M, M1024X768_R75_HSP, M1024X768_R75_VSP, 375 {REFRESH_75, M1024X768_R75_HSP, M1024X768_R75_VSP,
554 {1312, 1024, 1024, 288, 1040, 96, 800, 768, 768, 32, 769, 3} }, 376 {1312, 1024, 1024, 288, 1040, 96, 800, 768, 768, 32, 769, 3} },
555 {REFRESH_85, CLK_94_500M, M1024X768_R85_HSP, M1024X768_R85_VSP, 377 {REFRESH_85, M1024X768_R85_HSP, M1024X768_R85_VSP,
556 {1376, 1024, 1024, 352, 1072, 96, 808, 768, 768, 40, 769, 3} }, 378 {1376, 1024, 1024, 352, 1072, 96, 808, 768, 768, 40, 769, 3} },
557 {REFRESH_100, CLK_113_309M, M1024X768_R100_HSP, M1024X768_R100_VSP, 379 {REFRESH_100, M1024X768_R100_HSP, M1024X768_R100_VSP,
558 {1392, 1024, 1024, 368, 1096, 112, 814, 768, 768, 46, 769, 3} } 380 {1392, 1024, 1024, 368, 1096, 112, 814, 768, 768, 46, 769, 3} }
559}; 381};
560 382
561/* 1152x864*/ 383/* 1152x864*/
562struct crt_mode_table CRTM1152x864[] = { 384static struct crt_mode_table CRTM1152x864[] = {
563 /*r_rate,vclk,hsp,vsp */ 385 /*r_rate,hsp,vsp */
564 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 386 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
565 {REFRESH_75, CLK_108_000M, M1152X864_R75_HSP, M1152X864_R75_VSP, 387 {REFRESH_75, M1152X864_R75_HSP, M1152X864_R75_VSP,
566 {1600, 1152, 1152, 448, 1216, 128, 900, 864, 864, 36, 865, 3} } 388 {1600, 1152, 1152, 448, 1216, 128, 900, 864, 864, 36, 865, 3} }
567 389
568}; 390};
569 391
570/* 1280x720 (HDMI 720P)*/ 392/* 1280x720 (HDMI 720P)*/
571struct crt_mode_table CRTM1280x720[] = { 393static struct crt_mode_table CRTM1280x720[] = {
572 /*r_rate,vclk,hsp,vsp */ 394 /*r_rate,hsp,vsp */
573 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 395 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
574 {REFRESH_60, CLK_74_481M, M1280X720_R60_HSP, M1280X720_R60_VSP, 396 {REFRESH_60, M1280X720_R60_HSP, M1280X720_R60_VSP,
575 {1648, 1280, 1280, 368, 1392, 40, 750, 720, 720, 30, 725, 5} }, 397 {1648, 1280, 1280, 368, 1392, 40, 750, 720, 720, 30, 725, 5} },
576 {REFRESH_50, CLK_60_466M, M1280X720_R50_HSP, M1280X720_R50_VSP, 398 {REFRESH_50, M1280X720_R50_HSP, M1280X720_R50_VSP,
577 {1632, 1280, 1280, 352, 1328, 128, 741, 720, 720, 21, 721, 3} } 399 {1632, 1280, 1280, 352, 1328, 128, 741, 720, 720, 21, 721, 3} }
578}; 400};
579 401
580/*1280x768 (GTF)*/ 402/*1280x768 (GTF)*/
581struct crt_mode_table CRTM1280x768[] = { 403static struct crt_mode_table CRTM1280x768[] = {
582 /*r_rate,vclk,hsp,vsp */ 404 /*r_rate,hsp,vsp */
583 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 405 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
584 {REFRESH_60, CLK_80_136M, M1280X768_R60_HSP, M1280X768_R60_VSP, 406 {REFRESH_60, M1280X768_R60_HSP, M1280X768_R60_VSP,
585 {1680, 1280, 1280, 400, 1344, 136, 795, 768, 768, 27, 769, 3} }, 407 {1680, 1280, 1280, 400, 1344, 136, 795, 768, 768, 27, 769, 3} },
586 {REFRESH_50, CLK_65_178M, M1280X768_R50_HSP, M1280X768_R50_VSP, 408 {REFRESH_50, M1280X768_R50_HSP, M1280X768_R50_VSP,
587 {1648, 1280, 1280, 368, 1336, 128, 791, 768, 768, 23, 769, 3} } 409 {1648, 1280, 1280, 368, 1336, 128, 791, 768, 768, 23, 769, 3} }
588}; 410};
589 411
590/* 1280x800 (CVT) */ 412/* 1280x800 (CVT) */
591struct crt_mode_table CRTM1280x800[] = { 413static struct crt_mode_table CRTM1280x800[] = {
592 /* r_rate, vclk, hsp, vsp */ 414 /* r_rate, hsp, vsp */
593 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 415 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
594 {REFRESH_60, CLK_83_375M, M1280X800_R60_HSP, M1280X800_R60_VSP, 416 {REFRESH_60, M1280X800_R60_HSP, M1280X800_R60_VSP,
595 {1680, 1280, 1280, 400, 1352, 128, 831, 800, 800, 31, 803, 6} } 417 {1680, 1280, 1280, 400, 1352, 128, 831, 800, 800, 31, 803, 6} }
596}; 418};
597 419
598/*1280x960*/ 420/*1280x960*/
599struct crt_mode_table CRTM1280x960[] = { 421static struct crt_mode_table CRTM1280x960[] = {
600 /*r_rate,vclk,hsp,vsp */ 422 /*r_rate,hsp,vsp */
601 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 423 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
602 {REFRESH_60, CLK_108_000M, M1280X960_R60_HSP, M1280X960_R60_VSP, 424 {REFRESH_60, M1280X960_R60_HSP, M1280X960_R60_VSP,
603 {1800, 1280, 1280, 520, 1376, 112, 1000, 960, 960, 40, 961, 3} } 425 {1800, 1280, 1280, 520, 1376, 112, 1000, 960, 960, 40, 961, 3} }
604}; 426};
605 427
606/* 1280x1024*/ 428/* 1280x1024*/
607struct crt_mode_table CRTM1280x1024[] = { 429static struct crt_mode_table CRTM1280x1024[] = {
608 /*r_rate,vclk,,hsp,vsp */ 430 /*r_rate,hsp,vsp */
609 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 431 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
610 {REFRESH_60, CLK_108_000M, M1280X1024_R60_HSP, M1280X1024_R60_VSP, 432 {REFRESH_60, M1280X1024_R60_HSP, M1280X1024_R60_VSP,
611 {1688, 1280, 1280, 408, 1328, 112, 1066, 1024, 1024, 42, 1025, 433 {1688, 1280, 1280, 408, 1328, 112, 1066, 1024, 1024, 42, 1025,
612 3} }, 434 3} },
613 {REFRESH_75, CLK_135_000M, M1280X1024_R75_HSP, M1280X1024_R75_VSP, 435 {REFRESH_75, M1280X1024_R75_HSP, M1280X1024_R75_VSP,
614 {1688, 1280, 1280, 408, 1296, 144, 1066, 1024, 1024, 42, 1025, 436 {1688, 1280, 1280, 408, 1296, 144, 1066, 1024, 1024, 42, 1025,
615 3} }, 437 3} },
616 {REFRESH_85, CLK_157_500M, M1280X1024_R85_HSP, M1280X1024_R85_VSP, 438 {REFRESH_85, M1280X1024_R85_HSP, M1280X1024_R85_VSP,
617 {1728, 1280, 1280, 448, 1344, 160, 1072, 1024, 1024, 48, 1025, 3} } 439 {1728, 1280, 1280, 448, 1344, 160, 1072, 1024, 1024, 48, 1025, 3} }
618}; 440};
619 441
620/* 1368x768 (GTF) */ 442/* 1368x768 (GTF) */
621struct crt_mode_table CRTM1368x768[] = { 443static struct crt_mode_table CRTM1368x768[] = {
622 /* r_rate, vclk, hsp, vsp */ 444 /* r_rate, hsp, vsp */
623 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 445 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
624 {REFRESH_60, CLK_85_860M, M1368X768_R60_HSP, M1368X768_R60_VSP, 446 {REFRESH_60, M1368X768_R60_HSP, M1368X768_R60_VSP,
625 {1800, 1368, 1368, 432, 1440, 144, 795, 768, 768, 27, 769, 3} } 447 {1800, 1368, 1368, 432, 1440, 144, 795, 768, 768, 27, 769, 3} }
626}; 448};
627 449
628/*1440x1050 (GTF)*/ 450/*1440x1050 (GTF)*/
629struct crt_mode_table CRTM1440x1050[] = { 451static struct crt_mode_table CRTM1440x1050[] = {
630 /*r_rate,vclk,hsp,vsp */ 452 /*r_rate,hsp,vsp */
631 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 453 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
632 {REFRESH_60, CLK_125_104M, M1440X1050_R60_HSP, M1440X1050_R60_VSP, 454 {REFRESH_60, M1440X1050_R60_HSP, M1440X1050_R60_VSP,
633 {1936, 1440, 1440, 496, 1536, 152, 1077, 1040, 1040, 37, 1041, 3} } 455 {1936, 1440, 1440, 496, 1536, 152, 1077, 1040, 1040, 37, 1041, 3} }
634}; 456};
635 457
636/* 1600x1200*/ 458/* 1600x1200*/
637struct crt_mode_table CRTM1600x1200[] = { 459static struct crt_mode_table CRTM1600x1200[] = {
638 /*r_rate,vclk,hsp,vsp */ 460 /*r_rate,hsp,vsp */
639 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 461 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
640 {REFRESH_60, CLK_162_000M, M1600X1200_R60_HSP, M1600X1200_R60_VSP, 462 {REFRESH_60, M1600X1200_R60_HSP, M1600X1200_R60_VSP,
641 {2160, 1600, 1600, 560, 1664, 192, 1250, 1200, 1200, 50, 1201, 463 {2160, 1600, 1600, 560, 1664, 192, 1250, 1200, 1200, 50, 1201,
642 3} }, 464 3} },
643 {REFRESH_75, CLK_202_500M, M1600X1200_R75_HSP, M1600X1200_R75_VSP, 465 {REFRESH_75, M1600X1200_R75_HSP, M1600X1200_R75_VSP,
644 {2160, 1600, 1600, 560, 1664, 192, 1250, 1200, 1200, 50, 1201, 3} } 466 {2160, 1600, 1600, 560, 1664, 192, 1250, 1200, 1200, 50, 1201, 3} }
645 467
646}; 468};
647 469
648/* 1680x1050 (CVT) */ 470/* 1680x1050 (CVT) */
649struct crt_mode_table CRTM1680x1050[] = { 471static struct crt_mode_table CRTM1680x1050[] = {
650 /* r_rate, vclk, hsp, vsp */ 472 /* r_rate, hsp, vsp */
651 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 473 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
652 {REFRESH_60, CLK_146_760M, M1680x1050_R60_HSP, M1680x1050_R60_VSP, 474 {REFRESH_60, M1680x1050_R60_HSP, M1680x1050_R60_VSP,
653 {2240, 1680, 1680, 560, 1784, 176, 1089, 1050, 1050, 39, 1053, 475 {2240, 1680, 1680, 560, 1784, 176, 1089, 1050, 1050, 39, 1053,
654 6} }, 476 6} },
655 {REFRESH_75, CLK_187_000M, M1680x1050_R75_HSP, M1680x1050_R75_VSP, 477 {REFRESH_75, M1680x1050_R75_HSP, M1680x1050_R75_VSP,
656 {2272, 1680, 1680, 592, 1800, 176, 1099, 1050, 1050, 49, 1053, 6} } 478 {2272, 1680, 1680, 592, 1800, 176, 1099, 1050, 1050, 49, 1053, 6} }
657}; 479};
658 480
659/* 1680x1050 (CVT Reduce Blanking) */ 481/* 1680x1050 (CVT Reduce Blanking) */
660struct crt_mode_table CRTM1680x1050_RB[] = { 482static struct crt_mode_table CRTM1680x1050_RB[] = {
661 /* r_rate, vclk, hsp, vsp */ 483 /* r_rate, hsp, vsp */
662 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 484 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
663 {REFRESH_60, CLK_119_000M, M1680x1050_RB_R60_HSP, 485 {REFRESH_60, M1680x1050_RB_R60_HSP, M1680x1050_RB_R60_VSP,
664 M1680x1050_RB_R60_VSP,
665 {1840, 1680, 1680, 160, 1728, 32, 1080, 1050, 1050, 30, 1053, 6} } 486 {1840, 1680, 1680, 160, 1728, 32, 1080, 1050, 1050, 30, 1053, 6} }
666}; 487};
667 488
668/* 1920x1080 (CVT)*/ 489/* 1920x1080 (CVT)*/
669struct crt_mode_table CRTM1920x1080[] = { 490static struct crt_mode_table CRTM1920x1080[] = {
670 /*r_rate,vclk,hsp,vsp */ 491 /*r_rate,hsp,vsp */
671 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 492 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
672 {REFRESH_60, CLK_172_798M, M1920X1080_R60_HSP, M1920X1080_R60_VSP, 493 {REFRESH_60, M1920X1080_R60_HSP, M1920X1080_R60_VSP,
673 {2576, 1920, 1920, 656, 2048, 200, 1120, 1080, 1080, 40, 1083, 5} } 494 {2576, 1920, 1920, 656, 2048, 200, 1120, 1080, 1080, 40, 1083, 5} }
674}; 495};
675 496
676/* 1920x1080 (CVT with Reduce Blanking) */ 497/* 1920x1080 (CVT with Reduce Blanking) */
677struct crt_mode_table CRTM1920x1080_RB[] = { 498static struct crt_mode_table CRTM1920x1080_RB[] = {
678 /* r_rate, vclk, hsp, vsp */ 499 /* r_rate, hsp, vsp */
679 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 500 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
680 {REFRESH_60, CLK_138_400M, M1920X1080_RB_R60_HSP, 501 {REFRESH_60, M1920X1080_RB_R60_HSP, M1920X1080_RB_R60_VSP,
681 M1920X1080_RB_R60_VSP,
682 {2080, 1920, 1920, 160, 1968, 32, 1111, 1080, 1080, 31, 1083, 5} } 502 {2080, 1920, 1920, 160, 1968, 32, 1111, 1080, 1080, 31, 1083, 5} }
683}; 503};
684 504
685/* 1920x1440*/ 505/* 1920x1440*/
686struct crt_mode_table CRTM1920x1440[] = { 506static struct crt_mode_table CRTM1920x1440[] = {
687 /*r_rate,vclk,hsp,vsp */ 507 /*r_rate,hsp,vsp */
688 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 508 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
689 {REFRESH_60, CLK_234_000M, M1920X1440_R60_HSP, M1920X1440_R60_VSP, 509 {REFRESH_60, M1920X1440_R60_HSP, M1920X1440_R60_VSP,
690 {2600, 1920, 1920, 680, 2048, 208, 1500, 1440, 1440, 60, 1441, 510 {2600, 1920, 1920, 680, 2048, 208, 1500, 1440, 1440, 60, 1441,
691 3} }, 511 3} },
692 {REFRESH_75, CLK_297_500M, M1920X1440_R75_HSP, M1920X1440_R75_VSP, 512 {REFRESH_75, M1920X1440_R75_HSP, M1920X1440_R75_VSP,
693 {2640, 1920, 1920, 720, 2064, 224, 1500, 1440, 1440, 60, 1441, 3} } 513 {2640, 1920, 1920, 720, 2064, 224, 1500, 1440, 1440, 60, 1441, 3} }
694}; 514};
695 515
696/* 1400x1050 (CVT) */ 516/* 1400x1050 (CVT) */
697struct crt_mode_table CRTM1400x1050[] = { 517static struct crt_mode_table CRTM1400x1050[] = {
698 /* r_rate, vclk, hsp, vsp */ 518 /* r_rate, hsp, vsp */
699 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 519 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
700 {REFRESH_60, CLK_121_750M, M1400X1050_R60_HSP, M1400X1050_R60_VSP, 520 {REFRESH_60, M1400X1050_R60_HSP, M1400X1050_R60_VSP,
701 {1864, 1400, 1400, 464, 1488, 144, 1089, 1050, 1050, 39, 1053, 521 {1864, 1400, 1400, 464, 1488, 144, 1089, 1050, 1050, 39, 1053,
702 4} }, 522 4} },
703 {REFRESH_75, CLK_156_000M, M1400X1050_R75_HSP, M1400X1050_R75_VSP, 523 {REFRESH_75, M1400X1050_R75_HSP, M1400X1050_R75_VSP,
704 {1896, 1400, 1400, 496, 1504, 144, 1099, 1050, 1050, 49, 1053, 4} } 524 {1896, 1400, 1400, 496, 1504, 144, 1099, 1050, 1050, 49, 1053, 4} }
705}; 525};
706 526
707/* 1400x1050 (CVT Reduce Blanking) */ 527/* 1400x1050 (CVT Reduce Blanking) */
708struct crt_mode_table CRTM1400x1050_RB[] = { 528static struct crt_mode_table CRTM1400x1050_RB[] = {
709 /* r_rate, vclk, hsp, vsp */ 529 /* r_rate, hsp, vsp */
710 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 530 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
711 {REFRESH_60, CLK_101_000M, M1400X1050_RB_R60_HSP, 531 {REFRESH_60, M1400X1050_RB_R60_HSP, M1400X1050_RB_R60_VSP,
712 M1400X1050_RB_R60_VSP,
713 {1560, 1400, 1400, 160, 1448, 32, 1080, 1050, 1050, 30, 1053, 4} } 532 {1560, 1400, 1400, 160, 1448, 32, 1080, 1050, 1050, 30, 1053, 4} }
714}; 533};
715 534
716/* 960x600 (CVT) */ 535/* 960x600 (CVT) */
717struct crt_mode_table CRTM960x600[] = { 536static struct crt_mode_table CRTM960x600[] = {
718 /* r_rate, vclk, hsp, vsp */ 537 /* r_rate, hsp, vsp */
719 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 538 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
720 {REFRESH_60, CLK_45_250M, M960X600_R60_HSP, M960X600_R60_VSP, 539 {REFRESH_60, M960X600_R60_HSP, M960X600_R60_VSP,
721 {1216, 960, 960, 256, 992, 96, 624, 600, 600, 24, 603, 6} } 540 {1216, 960, 960, 256, 992, 96, 624, 600, 600, 24, 603, 6} }
722}; 541};
723 542
724/* 1000x600 (GTF) */ 543/* 1000x600 (GTF) */
725struct crt_mode_table CRTM1000x600[] = { 544static struct crt_mode_table CRTM1000x600[] = {
726 /* r_rate, vclk, hsp, vsp */ 545 /* r_rate, hsp, vsp */
727 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 546 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
728 {REFRESH_60, CLK_48_000M, M1000X600_R60_HSP, M1000X600_R60_VSP, 547 {REFRESH_60, M1000X600_R60_HSP, M1000X600_R60_VSP,
729 {1288, 1000, 1000, 288, 1040, 104, 622, 600, 600, 22, 601, 3} } 548 {1288, 1000, 1000, 288, 1040, 104, 622, 600, 600, 22, 601, 3} }
730}; 549};
731 550
732/* 1024x576 (GTF) */ 551/* 1024x576 (GTF) */
733struct crt_mode_table CRTM1024x576[] = { 552static struct crt_mode_table CRTM1024x576[] = {
734 /* r_rate, vclk, hsp, vsp */ 553 /* r_rate, hsp, vsp */
735 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 554 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
736 {REFRESH_60, CLK_46_996M, M1024X576_R60_HSP, M1024X576_R60_VSP, 555 {REFRESH_60, M1024X576_R60_HSP, M1024X576_R60_VSP,
737 {1312, 1024, 1024, 288, 1064, 104, 597, 576, 576, 21, 577, 3} } 556 {1312, 1024, 1024, 288, 1064, 104, 597, 576, 576, 21, 577, 3} }
738}; 557};
739 558
740/* 1088x612 (CVT) */ 559/* 1088x612 (CVT) */
741struct crt_mode_table CRTM1088x612[] = { 560static struct crt_mode_table CRTM1088x612[] = {
742 /* r_rate, vclk, hsp, vsp */ 561 /* r_rate, hsp, vsp */
743 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 562 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
744 {REFRESH_60, CLK_52_977M, M1088X612_R60_HSP, M1088X612_R60_VSP, 563 {REFRESH_60, M1088X612_R60_HSP, M1088X612_R60_VSP,
745 {1392, 1088, 1088, 304, 1136, 104, 636, 612, 612, 24, 615, 5} } 564 {1392, 1088, 1088, 304, 1136, 104, 636, 612, 612, 24, 615, 5} }
746}; 565};
747 566
748/* 1152x720 (CVT) */ 567/* 1152x720 (CVT) */
749struct crt_mode_table CRTM1152x720[] = { 568static struct crt_mode_table CRTM1152x720[] = {
750 /* r_rate, vclk, hsp, vsp */ 569 /* r_rate, hsp, vsp */
751 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 570 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
752 {REFRESH_60, CLK_66_750M, M1152X720_R60_HSP, M1152X720_R60_VSP, 571 {REFRESH_60, M1152X720_R60_HSP, M1152X720_R60_VSP,
753 {1488, 1152, 1152, 336, 1208, 112, 748, 720, 720, 28, 723, 6} } 572 {1488, 1152, 1152, 336, 1208, 112, 748, 720, 720, 28, 723, 6} }
754}; 573};
755 574
756/* 1200x720 (GTF) */ 575/* 1200x720 (GTF) */
757struct crt_mode_table CRTM1200x720[] = { 576static struct crt_mode_table CRTM1200x720[] = {
758 /* r_rate, vclk, hsp, vsp */ 577 /* r_rate, hsp, vsp */
759 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 578 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
760 {REFRESH_60, CLK_70_159M, M1200X720_R60_HSP, M1200X720_R60_VSP, 579 {REFRESH_60, M1200X720_R60_HSP, M1200X720_R60_VSP,
761 {1568, 1200, 1200, 368, 1256, 128, 746, 720, 720, 26, 721, 3} } 580 {1568, 1200, 1200, 368, 1256, 128, 746, 720, 720, 26, 721, 3} }
762}; 581};
763 582
764/* 1200x900 (DCON) */ 583/* 1200x900 (DCON) */
765struct crt_mode_table DCON1200x900[] = { 584static struct crt_mode_table DCON1200x900[] = {
766 /* r_rate, vclk, hsp, vsp */ 585 /* r_rate, hsp, vsp */
767 {REFRESH_60, CLK_57_275M, M1200X900_R60_HSP, M1200X900_R60_VSP, 586 {REFRESH_49, M1200X900_R60_HSP, M1200X900_R60_VSP,
768 /* The correct htotal is 1240, but this doesn't raster on VX855. */ 587 /* The correct htotal is 1240, but this doesn't raster on VX855. */
769 /* Via suggested changing to a multiple of 16, hence 1264. */ 588 /* Via suggested changing to a multiple of 16, hence 1264. */
770 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 589 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
@@ -772,126 +591,122 @@ struct crt_mode_table DCON1200x900[] = {
772}; 591};
773 592
774/* 1280x600 (GTF) */ 593/* 1280x600 (GTF) */
775struct crt_mode_table CRTM1280x600[] = { 594static struct crt_mode_table CRTM1280x600[] = {
776 /* r_rate, vclk, hsp, vsp */ 595 /* r_rate, hsp, vsp */
777 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 596 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
778 {REFRESH_60, CLK_61_500M, M1280x600_R60_HSP, M1280x600_R60_VSP, 597 {REFRESH_60, M1280x600_R60_HSP, M1280x600_R60_VSP,
779 {1648, 1280, 1280, 368, 1336, 128, 622, 600, 600, 22, 601, 3} } 598 {1648, 1280, 1280, 368, 1336, 128, 622, 600, 600, 22, 601, 3} }
780}; 599};
781 600
782/* 1360x768 (CVT) */ 601/* 1360x768 (CVT) */
783struct crt_mode_table CRTM1360x768[] = { 602static struct crt_mode_table CRTM1360x768[] = {
784 /* r_rate, vclk, hsp, vsp */ 603 /* r_rate, hsp, vsp */
785 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 604 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
786 {REFRESH_60, CLK_84_750M, M1360X768_R60_HSP, M1360X768_R60_VSP, 605 {REFRESH_60, M1360X768_R60_HSP, M1360X768_R60_VSP,
787 {1776, 1360, 1360, 416, 1432, 136, 798, 768, 768, 30, 771, 5} } 606 {1776, 1360, 1360, 416, 1432, 136, 798, 768, 768, 30, 771, 5} }
788}; 607};
789 608
790/* 1360x768 (CVT Reduce Blanking) */ 609/* 1360x768 (CVT Reduce Blanking) */
791struct crt_mode_table CRTM1360x768_RB[] = { 610static struct crt_mode_table CRTM1360x768_RB[] = {
792 /* r_rate, vclk, hsp, vsp */ 611 /* r_rate, hsp, vsp */
793 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 612 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
794 {REFRESH_60, CLK_72_000M, M1360X768_RB_R60_HSP, 613 {REFRESH_60, M1360X768_RB_R60_HSP, M1360X768_RB_R60_VSP,
795 M1360X768_RB_R60_VSP,
796 {1520, 1360, 1360, 160, 1408, 32, 790, 768, 768, 22, 771, 5} } 614 {1520, 1360, 1360, 160, 1408, 32, 790, 768, 768, 22, 771, 5} }
797}; 615};
798 616
799/* 1366x768 (GTF) */ 617/* 1366x768 (GTF) */
800struct crt_mode_table CRTM1366x768[] = { 618static struct crt_mode_table CRTM1366x768[] = {
801 /* r_rate, vclk, hsp, vsp */ 619 /* r_rate, hsp, vsp */
802 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 620 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
803 {REFRESH_60, CLK_85_860M, M1368X768_R60_HSP, M1368X768_R60_VSP, 621 {REFRESH_60, M1368X768_R60_HSP, M1368X768_R60_VSP,
804 {1800, 1368, 1368, 432, 1440, 144, 795, 768, 768, 27, 769, 3} }, 622 {1800, 1368, 1368, 432, 1440, 144, 795, 768, 768, 27, 769, 3} },
805 {REFRESH_50, CLK_69_924M, M1368X768_R50_HSP, M1368X768_R50_VSP, 623 {REFRESH_50, M1368X768_R50_HSP, M1368X768_R50_VSP,
806 {1768, 1368, 1368, 400, 1424, 144, 791, 768, 768, 23, 769, 3} } 624 {1768, 1368, 1368, 400, 1424, 144, 791, 768, 768, 23, 769, 3} }
807}; 625};
808 626
809/* 1440x900 (CVT) */ 627/* 1440x900 (CVT) */
810struct crt_mode_table CRTM1440x900[] = { 628static struct crt_mode_table CRTM1440x900[] = {
811 /* r_rate, vclk, hsp, vsp */ 629 /* r_rate, hsp, vsp */
812 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 630 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
813 {REFRESH_60, CLK_106_500M, M1440X900_R60_HSP, M1440X900_R60_VSP, 631 {REFRESH_60, M1440X900_R60_HSP, M1440X900_R60_VSP,
814 {1904, 1440, 1440, 464, 1520, 152, 934, 900, 900, 34, 903, 6} }, 632 {1904, 1440, 1440, 464, 1520, 152, 934, 900, 900, 34, 903, 6} },
815 {REFRESH_75, CLK_136_700M, M1440X900_R75_HSP, M1440X900_R75_VSP, 633 {REFRESH_75, M1440X900_R75_HSP, M1440X900_R75_VSP,
816 {1936, 1440, 1440, 496, 1536, 152, 942, 900, 900, 42, 903, 6} } 634 {1936, 1440, 1440, 496, 1536, 152, 942, 900, 900, 42, 903, 6} }
817}; 635};
818 636
819/* 1440x900 (CVT Reduce Blanking) */ 637/* 1440x900 (CVT Reduce Blanking) */
820struct crt_mode_table CRTM1440x900_RB[] = { 638static struct crt_mode_table CRTM1440x900_RB[] = {
821 /* r_rate, vclk, hsp, vsp */ 639 /* r_rate, hsp, vsp */
822 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 640 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
823 {REFRESH_60, CLK_88_750M, M1440X900_RB_R60_HSP, 641 {REFRESH_60, M1440X900_RB_R60_HSP, M1440X900_RB_R60_VSP,
824 M1440X900_RB_R60_VSP,
825 {1600, 1440, 1440, 160, 1488, 32, 926, 900, 900, 26, 903, 6} } 642 {1600, 1440, 1440, 160, 1488, 32, 926, 900, 900, 26, 903, 6} }
826}; 643};
827 644
828/* 1600x900 (CVT) */ 645/* 1600x900 (CVT) */
829struct crt_mode_table CRTM1600x900[] = { 646static struct crt_mode_table CRTM1600x900[] = {
830 /* r_rate, vclk, hsp, vsp */ 647 /* r_rate, hsp, vsp */
831 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 648 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
832 {REFRESH_60, CLK_118_840M, M1600X900_R60_HSP, M1600X900_R60_VSP, 649 {REFRESH_60, M1600X900_R60_HSP, M1600X900_R60_VSP,
833 {2112, 1600, 1600, 512, 1688, 168, 934, 900, 900, 34, 903, 5} } 650 {2112, 1600, 1600, 512, 1688, 168, 934, 900, 900, 34, 903, 5} }
834}; 651};
835 652
836/* 1600x900 (CVT Reduce Blanking) */ 653/* 1600x900 (CVT Reduce Blanking) */
837struct crt_mode_table CRTM1600x900_RB[] = { 654static struct crt_mode_table CRTM1600x900_RB[] = {
838 /* r_rate, vclk, hsp, vsp */ 655 /* r_rate, hsp, vsp */
839 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 656 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
840 {REFRESH_60, CLK_97_750M, M1600X900_RB_R60_HSP, 657 {REFRESH_60, M1600X900_RB_R60_HSP, M1600X900_RB_R60_VSP,
841 M1600X900_RB_R60_VSP,
842 {1760, 1600, 1600, 160, 1648, 32, 926, 900, 900, 26, 903, 5} } 658 {1760, 1600, 1600, 160, 1648, 32, 926, 900, 900, 26, 903, 5} }
843}; 659};
844 660
845/* 1600x1024 (GTF) */ 661/* 1600x1024 (GTF) */
846struct crt_mode_table CRTM1600x1024[] = { 662static struct crt_mode_table CRTM1600x1024[] = {
847 /* r_rate, vclk, hsp, vsp */ 663 /* r_rate, hsp, vsp */
848 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 664 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
849 {REFRESH_60, CLK_136_700M, M1600X1024_R60_HSP, M1600X1024_R60_VSP, 665 {REFRESH_60, M1600X1024_R60_HSP, M1600X1024_R60_VSP,
850 {2144, 1600, 1600, 544, 1704, 168, 1060, 1024, 1024, 36, 1025, 3} } 666 {2144, 1600, 1600, 544, 1704, 168, 1060, 1024, 1024, 36, 1025, 3} }
851}; 667};
852 668
853/* 1792x1344 (DMT) */ 669/* 1792x1344 (DMT) */
854struct crt_mode_table CRTM1792x1344[] = { 670static struct crt_mode_table CRTM1792x1344[] = {
855 /* r_rate, vclk, hsp, vsp */ 671 /* r_rate, hsp, vsp */
856 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 672 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
857 {REFRESH_60, CLK_204_000M, M1792x1344_R60_HSP, M1792x1344_R60_VSP, 673 {REFRESH_60, M1792x1344_R60_HSP, M1792x1344_R60_VSP,
858 {2448, 1792, 1792, 656, 1920, 200, 1394, 1344, 1344, 50, 1345, 3} } 674 {2448, 1792, 1792, 656, 1920, 200, 1394, 1344, 1344, 50, 1345, 3} }
859}; 675};
860 676
861/* 1856x1392 (DMT) */ 677/* 1856x1392 (DMT) */
862struct crt_mode_table CRTM1856x1392[] = { 678static struct crt_mode_table CRTM1856x1392[] = {
863 /* r_rate, vclk, hsp, vsp */ 679 /* r_rate, hsp, vsp */
864 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 680 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
865 {REFRESH_60, CLK_218_500M, M1856x1392_R60_HSP, M1856x1392_R60_VSP, 681 {REFRESH_60, M1856x1392_R60_HSP, M1856x1392_R60_VSP,
866 {2528, 1856, 1856, 672, 1952, 224, 1439, 1392, 1392, 47, 1393, 3} } 682 {2528, 1856, 1856, 672, 1952, 224, 1439, 1392, 1392, 47, 1393, 3} }
867}; 683};
868 684
869/* 1920x1200 (CVT) */ 685/* 1920x1200 (CVT) */
870struct crt_mode_table CRTM1920x1200[] = { 686static struct crt_mode_table CRTM1920x1200[] = {
871 /* r_rate, vclk, hsp, vsp */ 687 /* r_rate, hsp, vsp */
872 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 688 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
873 {REFRESH_60, CLK_193_295M, M1920X1200_R60_HSP, M1920X1200_R60_VSP, 689 {REFRESH_60, M1920X1200_R60_HSP, M1920X1200_R60_VSP,
874 {2592, 1920, 1920, 672, 2056, 200, 1245, 1200, 1200, 45, 1203, 6} } 690 {2592, 1920, 1920, 672, 2056, 200, 1245, 1200, 1200, 45, 1203, 6} }
875}; 691};
876 692
877/* 1920x1200 (CVT with Reduce Blanking) */ 693/* 1920x1200 (CVT with Reduce Blanking) */
878struct crt_mode_table CRTM1920x1200_RB[] = { 694static struct crt_mode_table CRTM1920x1200_RB[] = {
879 /* r_rate, vclk, hsp, vsp */ 695 /* r_rate, hsp, vsp */
880 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 696 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
881 {REFRESH_60, CLK_153_920M, M1920X1200_RB_R60_HSP, 697 {REFRESH_60, M1920X1200_RB_R60_HSP, M1920X1200_RB_R60_VSP,
882 M1920X1200_RB_R60_VSP,
883 {2080, 1920, 1920, 160, 1968, 32, 1235, 1200, 1200, 35, 1203, 6} } 698 {2080, 1920, 1920, 160, 1968, 32, 1235, 1200, 1200, 35, 1203, 6} }
884}; 699};
885 700
886/* 2048x1536 (CVT) */ 701/* 2048x1536 (CVT) */
887struct crt_mode_table CRTM2048x1536[] = { 702static struct crt_mode_table CRTM2048x1536[] = {
888 /* r_rate, vclk, hsp, vsp */ 703 /* r_rate, hsp, vsp */
889 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 704 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
890 {REFRESH_60, CLK_267_250M, M2048x1536_R60_HSP, M2048x1536_R60_VSP, 705 {REFRESH_60, M2048x1536_R60_HSP, M2048x1536_R60_VSP,
891 {2800, 2048, 2048, 752, 2200, 224, 1592, 1536, 1536, 56, 1539, 4} } 706 {2800, 2048, 2048, 752, 2200, 224, 1592, 1536, 1536, 56, 1539, 4} }
892}; 707};
893 708
894struct VideoModeTable viafb_modes[] = { 709static struct VideoModeTable viafb_modes[] = {
895 /* Display : 480x640 (GTF) */ 710 /* Display : 480x640 (GTF) */
896 {CRTM480x640, ARRAY_SIZE(CRTM480x640)}, 711 {CRTM480x640, ARRAY_SIZE(CRTM480x640)},
897 712
@@ -1016,7 +831,7 @@ struct VideoModeTable viafb_modes[] = {
1016 {CRTM1400x1050, ARRAY_SIZE(CRTM1400x1050)} 831 {CRTM1400x1050, ARRAY_SIZE(CRTM1400x1050)}
1017}; 832};
1018 833
1019struct VideoModeTable viafb_rb_modes[] = { 834static struct VideoModeTable viafb_rb_modes[] = {
1020 /* Display : 1360x768 (CVT Reduce Blanking) */ 835 /* Display : 1360x768 (CVT Reduce Blanking) */
1021 {CRTM1360x768_RB, ARRAY_SIZE(CRTM1360x768_RB)}, 836 {CRTM1360x768_RB, ARRAY_SIZE(CRTM1360x768_RB)},
1022 837
@@ -1039,26 +854,6 @@ struct VideoModeTable viafb_rb_modes[] = {
1039 {CRTM1920x1200_RB, ARRAY_SIZE(CRTM1920x1200_RB)} 854 {CRTM1920x1200_RB, ARRAY_SIZE(CRTM1920x1200_RB)}
1040}; 855};
1041 856
1042struct crt_mode_table CEAM1280x720[] = {
1043 {REFRESH_60, CLK_74_270M, M1280X720_CEA_R60_HSP,
1044 M1280X720_CEA_R60_VSP,
1045 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
1046 {1650, 1280, 1280, 370, 1390, 40, 750, 720, 720, 30, 725, 5} }
1047};
1048struct crt_mode_table CEAM1920x1080[] = {
1049 {REFRESH_60, CLK_148_500M, M1920X1080_CEA_R60_HSP,
1050 M1920X1080_CEA_R60_VSP,
1051 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
1052 {2200, 1920, 1920, 300, 2008, 44, 1125, 1080, 1080, 45, 1084, 5} }
1053};
1054struct VideoModeTable CEA_HDMI_Modes[] = {
1055 /* Display : 1280x720 */
1056 {CEAM1280x720, ARRAY_SIZE(CEAM1280x720)},
1057 {CEAM1920x1080, ARRAY_SIZE(CEAM1920x1080)}
1058};
1059
1060int NUM_TOTAL_RES_MAP_REFRESH = ARRAY_SIZE(res_map_refresh_tbl);
1061int NUM_TOTAL_CEA_MODES = ARRAY_SIZE(CEA_HDMI_Modes);
1062int NUM_TOTAL_CN400_ModeXregs = ARRAY_SIZE(CN400_ModeXregs); 857int NUM_TOTAL_CN400_ModeXregs = ARRAY_SIZE(CN400_ModeXregs);
1063int NUM_TOTAL_CN700_ModeXregs = ARRAY_SIZE(CN700_ModeXregs); 858int NUM_TOTAL_CN700_ModeXregs = ARRAY_SIZE(CN700_ModeXregs);
1064int NUM_TOTAL_KM400_ModeXregs = ARRAY_SIZE(KM400_ModeXregs); 859int NUM_TOTAL_KM400_ModeXregs = ARRAY_SIZE(KM400_ModeXregs);
diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h
index 5b1ced86514b..3751289eb450 100644
--- a/drivers/video/via/viamode.h
+++ b/drivers/video/via/viamode.h
@@ -41,15 +41,6 @@ struct patch_table {
41 struct io_reg *io_reg_table; 41 struct io_reg *io_reg_table;
42}; 42};
43 43
44struct res_map_refresh {
45 int hres;
46 int vres;
47 int pixclock;
48 int vmode_refresh;
49};
50
51extern int NUM_TOTAL_RES_MAP_REFRESH;
52extern int NUM_TOTAL_CEA_MODES;
53extern int NUM_TOTAL_CN400_ModeXregs; 44extern int NUM_TOTAL_CN400_ModeXregs;
54extern int NUM_TOTAL_CN700_ModeXregs; 45extern int NUM_TOTAL_CN700_ModeXregs;
55extern int NUM_TOTAL_KM400_ModeXregs; 46extern int NUM_TOTAL_KM400_ModeXregs;
@@ -58,15 +49,6 @@ extern int NUM_TOTAL_VX855_ModeXregs;
58extern int NUM_TOTAL_CLE266_ModeXregs; 49extern int NUM_TOTAL_CLE266_ModeXregs;
59extern int NUM_TOTAL_PATCH_MODE; 50extern int NUM_TOTAL_PATCH_MODE;
60 51
61/********************/
62/* Mode Table */
63/********************/
64
65extern struct crt_mode_table CEAM1280x720[];
66extern struct crt_mode_table CEAM1920x1080[];
67extern struct VideoModeTable CEA_HDMI_Modes[];
68
69extern struct res_map_refresh res_map_refresh_tbl[];
70extern struct io_reg CN400_ModeXregs[]; 52extern struct io_reg CN400_ModeXregs[];
71extern struct io_reg CN700_ModeXregs[]; 53extern struct io_reg CN700_ModeXregs[];
72extern struct io_reg KM400_ModeXregs[]; 54extern struct io_reg KM400_ModeXregs[];
diff --git a/drivers/video/via/vt1636.c b/drivers/video/via/vt1636.c
index d65bf1aee87c..ee2903b472cf 100644
--- a/drivers/video/via/vt1636.c
+++ b/drivers/video/via/vt1636.c
@@ -23,6 +23,34 @@
23#include <linux/via_i2c.h> 23#include <linux/via_i2c.h>
24#include "global.h" 24#include "global.h"
25 25
26static const struct IODATA common_init_data[] = {
27/* Index, Mask, Value */
28 /* Set panel power sequence timing */
29 {0x10, 0xC0, 0x00},
30 /* T1: VDD on - Data on. Each increment is 1 ms. (50ms = 031h) */
31 {0x0B, 0xFF, 0x40},
32 /* T2: Data on - Backlight on. Each increment is 2 ms. (210ms = 068h) */
33 {0x0C, 0xFF, 0x31},
34 /* T3: Backlight off -Data off. Each increment is 2 ms. (210ms = 068h)*/
35 {0x0D, 0xFF, 0x31},
36 /* T4: Data off - VDD off. Each increment is 1 ms. (50ms = 031h) */
37 {0x0E, 0xFF, 0x68},
38 /* T5: VDD off - VDD on. Each increment is 100 ms. (500ms = 04h) */
39 {0x0F, 0xFF, 0x68},
40 /* LVDS output power up */
41 {0x09, 0xA0, 0xA0},
42 /* turn on back light */
43 {0x10, 0x33, 0x13}
44};
45
46/* Index, Mask, Value */
47static const struct IODATA dual_channel_enable_data = {0x08, 0xF0, 0xE0};
48static const struct IODATA single_channel_enable_data = {0x08, 0xF0, 0x00};
49static const struct IODATA dithering_enable_data = {0x0A, 0x70, 0x50};
50static const struct IODATA dithering_disable_data = {0x0A, 0x70, 0x00};
51static const struct IODATA vdd_on_data = {0x10, 0x20, 0x20};
52static const struct IODATA vdd_off_data = {0x10, 0x20, 0x00};
53
26u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information 54u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
27 *plvds_setting_info, struct lvds_chip_information *plvds_chip_info, 55 *plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
28 u8 index) 56 u8 index)
@@ -55,108 +83,41 @@ void viafb_init_lvds_vt1636(struct lvds_setting_information
55 int reg_num, i; 83 int reg_num, i;
56 84
57 /* Common settings: */ 85 /* Common settings: */
58 reg_num = ARRAY_SIZE(COMMON_INIT_TBL_VT1636); 86 reg_num = ARRAY_SIZE(common_init_data);
59 87 for (i = 0; i < reg_num; i++)
60 for (i = 0; i < reg_num; i++) {
61 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, 88 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
62 plvds_chip_info, 89 plvds_chip_info, common_init_data[i]);
63 COMMON_INIT_TBL_VT1636[i]);
64 }
65 90
66 /* Input Data Mode Select */ 91 /* Input Data Mode Select */
67 if (plvds_setting_info->device_lcd_dualedge) { 92 if (plvds_setting_info->device_lcd_dualedge)
68 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, 93 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
69 plvds_chip_info, 94 plvds_chip_info, dual_channel_enable_data);
70 DUAL_CHANNEL_ENABLE_TBL_VT1636[0]); 95 else
71 } else {
72 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, 96 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
73 plvds_chip_info, 97 plvds_chip_info, single_channel_enable_data);
74 SINGLE_CHANNEL_ENABLE_TBL_VT1636[0]);
75 }
76 98
77 if (plvds_setting_info->LCDDithering) { 99 if (plvds_setting_info->LCDDithering)
78 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, 100 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
79 plvds_chip_info, 101 plvds_chip_info, dithering_enable_data);
80 DITHERING_ENABLE_TBL_VT1636[0]); 102 else
81 } else {
82 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, 103 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
83 plvds_chip_info, 104 plvds_chip_info, dithering_disable_data);
84 DITHERING_DISABLE_TBL_VT1636[0]);
85 }
86} 105}
87 106
88void viafb_enable_lvds_vt1636(struct lvds_setting_information 107void viafb_enable_lvds_vt1636(struct lvds_setting_information
89 *plvds_setting_info, 108 *plvds_setting_info,
90 struct lvds_chip_information *plvds_chip_info) 109 struct lvds_chip_information *plvds_chip_info)
91{ 110{
92
93 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info, 111 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
94 VDD_ON_TBL_VT1636[0]); 112 vdd_on_data);
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} 113}
124 114
125void viafb_disable_lvds_vt1636(struct lvds_setting_information 115void viafb_disable_lvds_vt1636(struct lvds_setting_information
126 *plvds_setting_info, 116 *plvds_setting_info,
127 struct lvds_chip_information *plvds_chip_info) 117 struct lvds_chip_information *plvds_chip_info)
128{ 118{
129
130 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info, 119 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
131 VDD_OFF_TBL_VT1636[0]); 120 vdd_off_data);
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} 121}
161 122
162bool viafb_lvds_identify_vt1636(u8 i2c_adapter) 123bool viafb_lvds_identify_vt1636(u8 i2c_adapter)
@@ -206,22 +167,6 @@ static int get_clk_range_index(u32 Clk)
206 return DPA_CLK_RANGE_150M; 167 return DPA_CLK_RANGE_150M;
207} 168}
208 169
209static int get_lvds_dpa_setting_index(int panel_size_id,
210 struct VT1636_DPA_SETTING *p_vt1636_dpasetting_tbl,
211 int tbl_size)
212{
213 int i;
214
215 for (i = 0; i < tbl_size; i++) {
216 if (panel_size_id == p_vt1636_dpasetting_tbl->PanelSizeID)
217 return i;
218
219 p_vt1636_dpasetting_tbl++;
220 }
221
222 return 0;
223}
224
225static void set_dpa_vt1636(struct lvds_setting_information 170static void set_dpa_vt1636(struct lvds_setting_information
226 *plvds_setting_info, struct lvds_chip_information *plvds_chip_info, 171 *plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
227 struct VT1636_DPA_SETTING *p_vt1636_dpa_setting) 172 struct VT1636_DPA_SETTING *p_vt1636_dpa_setting)
@@ -245,7 +190,9 @@ void viafb_vt1636_patch_skew_on_vt3324(
245 struct lvds_setting_information *plvds_setting_info, 190 struct lvds_setting_information *plvds_setting_info,
246 struct lvds_chip_information *plvds_chip_info) 191 struct lvds_chip_information *plvds_chip_info)
247{ 192{
248 int index, size; 193 struct VT1636_DPA_SETTING dpa = {0x00, 0x00}, dpa_16x12 = {0x0B, 0x03},
194 *pdpa;
195 int index;
249 196
250 DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3324.\n"); 197 DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3324.\n");
251 198
@@ -255,19 +202,21 @@ void viafb_vt1636_patch_skew_on_vt3324(
255 &GFX_DPA_SETTING_TBL_VT3324[index]); 202 &GFX_DPA_SETTING_TBL_VT3324[index]);
256 203
257 /* LVDS Transmitter DPA settings: */ 204 /* LVDS Transmitter DPA settings: */
258 size = ARRAY_SIZE(VT1636_DPA_SETTING_TBL_VT3324); 205 if (plvds_setting_info->lcd_panel_hres == 1600 &&
259 index = 206 plvds_setting_info->lcd_panel_vres == 1200)
260 get_lvds_dpa_setting_index(plvds_setting_info->lcd_panel_id, 207 pdpa = &dpa_16x12;
261 VT1636_DPA_SETTING_TBL_VT3324, size); 208 else
262 set_dpa_vt1636(plvds_setting_info, plvds_chip_info, 209 pdpa = &dpa;
263 &VT1636_DPA_SETTING_TBL_VT3324[index]); 210
211 set_dpa_vt1636(plvds_setting_info, plvds_chip_info, pdpa);
264} 212}
265 213
266void viafb_vt1636_patch_skew_on_vt3327( 214void viafb_vt1636_patch_skew_on_vt3327(
267 struct lvds_setting_information *plvds_setting_info, 215 struct lvds_setting_information *plvds_setting_info,
268 struct lvds_chip_information *plvds_chip_info) 216 struct lvds_chip_information *plvds_chip_info)
269{ 217{
270 int index, size; 218 struct VT1636_DPA_SETTING dpa = {0x00, 0x00};
219 int index;
271 220
272 DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3327.\n"); 221 DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3327.\n");
273 222
@@ -277,12 +226,7 @@ void viafb_vt1636_patch_skew_on_vt3327(
277 &GFX_DPA_SETTING_TBL_VT3327[index]); 226 &GFX_DPA_SETTING_TBL_VT3327[index]);
278 227
279 /* LVDS Transmitter DPA settings: */ 228 /* LVDS Transmitter DPA settings: */
280 size = ARRAY_SIZE(VT1636_DPA_SETTING_TBL_VT3327); 229 set_dpa_vt1636(plvds_setting_info, plvds_chip_info, &dpa);
281 index =
282 get_lvds_dpa_setting_index(plvds_setting_info->lcd_panel_id,
283 VT1636_DPA_SETTING_TBL_VT3327, size);
284 set_dpa_vt1636(plvds_setting_info, plvds_chip_info,
285 &VT1636_DPA_SETTING_TBL_VT3327[index]);
286} 230}
287 231
288void viafb_vt1636_patch_skew_on_vt3364( 232void viafb_vt1636_patch_skew_on_vt3364(
diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/vt8500lcdfb.c
new file mode 100644
index 000000000000..0e120d67eb65
--- /dev/null
+++ b/drivers/video/vt8500lcdfb.c
@@ -0,0 +1,475 @@
1/*
2 * linux/drivers/video/vt8500lcdfb.c
3 *
4 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
5 *
6 * Based on skeletonfb.c and pxafb.c
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/errno.h>
21#include <linux/string.h>
22#include <linux/mm.h>
23#include <linux/slab.h>
24#include <linux/delay.h>
25#include <linux/fb.h>
26#include <linux/init.h>
27#include <linux/interrupt.h>
28#include <linux/io.h>
29#include <linux/dma-mapping.h>
30#include <linux/platform_device.h>
31#include <linux/wait.h>
32
33#include <mach/vt8500fb.h>
34
35#include "vt8500lcdfb.h"
36#include "wmt_ge_rops.h"
37
38#define to_vt8500lcd_info(__info) container_of(__info, \
39 struct vt8500lcd_info, fb)
40
41static int vt8500lcd_set_par(struct fb_info *info)
42{
43 struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
44 int reg_bpp = 5; /* 16bpp */
45 int i;
46 unsigned long control0;
47
48 if (!fbi)
49 return -EINVAL;
50
51 if (info->var.bits_per_pixel <= 8) {
52 /* palettized */
53 info->var.red.offset = 0;
54 info->var.red.length = info->var.bits_per_pixel;
55 info->var.red.msb_right = 0;
56
57 info->var.green.offset = 0;
58 info->var.green.length = info->var.bits_per_pixel;
59 info->var.green.msb_right = 0;
60
61 info->var.blue.offset = 0;
62 info->var.blue.length = info->var.bits_per_pixel;
63 info->var.blue.msb_right = 0;
64
65 info->var.transp.offset = 0;
66 info->var.transp.length = 0;
67 info->var.transp.msb_right = 0;
68
69 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
70 info->fix.line_length = info->var.xres_virtual /
71 (8/info->var.bits_per_pixel);
72 } else {
73 /* non-palettized */
74 info->var.transp.offset = 0;
75 info->var.transp.length = 0;
76 info->var.transp.msb_right = 0;
77
78 if (info->var.bits_per_pixel == 16) {
79 /* RGB565 */
80 info->var.red.offset = 11;
81 info->var.red.length = 5;
82 info->var.red.msb_right = 0;
83 info->var.green.offset = 5;
84 info->var.green.length = 6;
85 info->var.green.msb_right = 0;
86 info->var.blue.offset = 0;
87 info->var.blue.length = 5;
88 info->var.blue.msb_right = 0;
89 } else {
90 /* Equal depths per channel */
91 info->var.red.offset = info->var.bits_per_pixel
92 * 2 / 3;
93 info->var.red.length = info->var.bits_per_pixel / 3;
94 info->var.red.msb_right = 0;
95 info->var.green.offset = info->var.bits_per_pixel / 3;
96 info->var.green.length = info->var.bits_per_pixel / 3;
97 info->var.green.msb_right = 0;
98 info->var.blue.offset = 0;
99 info->var.blue.length = info->var.bits_per_pixel / 3;
100 info->var.blue.msb_right = 0;
101 }
102
103 info->fix.visual = FB_VISUAL_TRUECOLOR;
104 info->fix.line_length = info->var.bits_per_pixel > 16 ?
105 info->var.xres_virtual << 2 :
106 info->var.xres_virtual << 1;
107 }
108
109 for (i = 0; i < 8; i++) {
110 if (bpp_values[i] == info->var.bits_per_pixel) {
111 reg_bpp = i;
112 continue;
113 }
114 }
115
116 control0 = readl(fbi->regbase) & ~0xf;
117 writel(0, fbi->regbase);
118 while (readl(fbi->regbase + 0x38) & 0x10)
119 /* wait */;
120 writel((((info->var.hsync_len - 1) & 0x3f) << 26)
121 | ((info->var.left_margin & 0xff) << 18)
122 | (((info->var.xres - 1) & 0x3ff) << 8)
123 | (info->var.right_margin & 0xff), fbi->regbase + 0x4);
124 writel((((info->var.vsync_len - 1) & 0x3f) << 26)
125 | ((info->var.upper_margin & 0xff) << 18)
126 | (((info->var.yres - 1) & 0x3ff) << 8)
127 | (info->var.lower_margin & 0xff), fbi->regbase + 0x8);
128 writel((((info->var.yres - 1) & 0x400) << 2)
129 | ((info->var.xres - 1) & 0x400), fbi->regbase + 0x10);
130 writel(0x80000000, fbi->regbase + 0x20);
131 writel(control0 | (reg_bpp << 1) | 0x100, fbi->regbase);
132
133 return 0;
134}
135
136static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
137{
138 chan &= 0xffff;
139 chan >>= 16 - bf->length;
140 return chan << bf->offset;
141}
142
143static int vt8500lcd_setcolreg(unsigned regno, unsigned red, unsigned green,
144 unsigned blue, unsigned transp,
145 struct fb_info *info) {
146 struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
147 int ret = 1;
148 unsigned int val;
149 if (regno >= 256)
150 return -EINVAL;
151
152 if (info->var.grayscale)
153 red = green = blue =
154 (19595 * red + 38470 * green + 7471 * blue) >> 16;
155
156 switch (fbi->fb.fix.visual) {
157 case FB_VISUAL_TRUECOLOR:
158 if (regno < 16) {
159 u32 *pal = fbi->fb.pseudo_palette;
160
161 val = chan_to_field(red, &fbi->fb.var.red);
162 val |= chan_to_field(green, &fbi->fb.var.green);
163 val |= chan_to_field(blue, &fbi->fb.var.blue);
164
165 pal[regno] = val;
166 ret = 0;
167 }
168 break;
169
170 case FB_VISUAL_STATIC_PSEUDOCOLOR:
171 case FB_VISUAL_PSEUDOCOLOR:
172 writew((red & 0xf800)
173 | ((green >> 5) & 0x7e0)
174 | ((blue >> 11) & 0x1f),
175 fbi->palette_cpu + sizeof(u16) * regno);
176 break;
177 }
178
179 return ret;
180}
181
182static int vt8500lcd_ioctl(struct fb_info *info, unsigned int cmd,
183 unsigned long arg)
184{
185 int ret = 0;
186 struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
187
188 if (cmd == FBIO_WAITFORVSYNC) {
189 /* Unmask End of Frame interrupt */
190 writel(0xffffffff ^ (1 << 3), fbi->regbase + 0x3c);
191 ret = wait_event_interruptible_timeout(fbi->wait,
192 readl(fbi->regbase + 0x38) & (1 << 3), HZ / 10);
193 /* Mask back to reduce unwanted interrupt traffic */
194 writel(0xffffffff, fbi->regbase + 0x3c);
195 if (ret < 0)
196 return ret;
197 if (ret == 0)
198 return -ETIMEDOUT;
199 }
200
201 return ret;
202}
203
204static int vt8500lcd_pan_display(struct fb_var_screeninfo *var,
205 struct fb_info *info)
206{
207 unsigned pixlen = info->fix.line_length / info->var.xres_virtual;
208 unsigned off = pixlen * var->xoffset
209 + info->fix.line_length * var->yoffset;
210 struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
211
212 writel((1 << 31)
213 | (((var->xres_virtual - var->xres) * pixlen / 4) << 20)
214 | (off >> 2), fbi->regbase + 0x20);
215 return 0;
216}
217
218/*
219 * vt8500lcd_blank():
220 * Blank the display by setting all palette values to zero. Note,
221 * True Color modes do not really use the palette, so this will not
222 * blank the display in all modes.
223 */
224static int vt8500lcd_blank(int blank, struct fb_info *info)
225{
226 int i;
227
228 switch (blank) {
229 case FB_BLANK_POWERDOWN:
230 case FB_BLANK_VSYNC_SUSPEND:
231 case FB_BLANK_HSYNC_SUSPEND:
232 case FB_BLANK_NORMAL:
233 if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR ||
234 info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
235 for (i = 0; i < 256; i++)
236 vt8500lcd_setcolreg(i, 0, 0, 0, 0, info);
237 case FB_BLANK_UNBLANK:
238 if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR ||
239 info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
240 fb_set_cmap(&info->cmap, info);
241 }
242 return 0;
243}
244
245static struct fb_ops vt8500lcd_ops = {
246 .owner = THIS_MODULE,
247 .fb_set_par = vt8500lcd_set_par,
248 .fb_setcolreg = vt8500lcd_setcolreg,
249 .fb_fillrect = wmt_ge_fillrect,
250 .fb_copyarea = wmt_ge_copyarea,
251 .fb_imageblit = sys_imageblit,
252 .fb_sync = wmt_ge_sync,
253 .fb_ioctl = vt8500lcd_ioctl,
254 .fb_pan_display = vt8500lcd_pan_display,
255 .fb_blank = vt8500lcd_blank,
256};
257
258static irqreturn_t vt8500lcd_handle_irq(int irq, void *dev_id)
259{
260 struct vt8500lcd_info *fbi = dev_id;
261
262 if (readl(fbi->regbase + 0x38) & (1 << 3))
263 wake_up_interruptible(&fbi->wait);
264
265 writel(0xffffffff, fbi->regbase + 0x38);
266 return IRQ_HANDLED;
267}
268
269static int __devinit vt8500lcd_probe(struct platform_device *pdev)
270{
271 struct vt8500lcd_info *fbi;
272 struct resource *res;
273 struct vt8500fb_platform_data *pdata = pdev->dev.platform_data;
274 void *addr;
275 int irq, ret;
276
277 ret = -ENOMEM;
278 fbi = NULL;
279
280 fbi = kzalloc(sizeof(struct vt8500lcd_info) + sizeof(u32) * 16,
281 GFP_KERNEL);
282 if (!fbi) {
283 dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
284 ret = -ENOMEM;
285 goto failed;
286 }
287
288 strcpy(fbi->fb.fix.id, "VT8500 LCD");
289
290 fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS;
291 fbi->fb.fix.xpanstep = 0;
292 fbi->fb.fix.ypanstep = 1;
293 fbi->fb.fix.ywrapstep = 0;
294 fbi->fb.fix.accel = FB_ACCEL_NONE;
295
296 fbi->fb.var.nonstd = 0;
297 fbi->fb.var.activate = FB_ACTIVATE_NOW;
298 fbi->fb.var.height = -1;
299 fbi->fb.var.width = -1;
300 fbi->fb.var.vmode = FB_VMODE_NONINTERLACED;
301
302 fbi->fb.fbops = &vt8500lcd_ops;
303 fbi->fb.flags = FBINFO_DEFAULT
304 | FBINFO_HWACCEL_COPYAREA
305 | FBINFO_HWACCEL_FILLRECT
306 | FBINFO_HWACCEL_YPAN
307 | FBINFO_VIRTFB
308 | FBINFO_PARTIAL_PAN_OK;
309 fbi->fb.node = -1;
310
311 addr = fbi;
312 addr = addr + sizeof(struct vt8500lcd_info);
313 fbi->fb.pseudo_palette = addr;
314
315 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
316 if (res == NULL) {
317 dev_err(&pdev->dev, "no I/O memory resource defined\n");
318 ret = -ENODEV;
319 goto failed_fbi;
320 }
321
322 res = request_mem_region(res->start, resource_size(res), "vt8500lcd");
323 if (res == NULL) {
324 dev_err(&pdev->dev, "failed to request I/O memory\n");
325 ret = -EBUSY;
326 goto failed_fbi;
327 }
328
329 fbi->regbase = ioremap(res->start, resource_size(res));
330 if (fbi->regbase == NULL) {
331 dev_err(&pdev->dev, "failed to map I/O memory\n");
332 ret = -EBUSY;
333 goto failed_free_res;
334 }
335
336 fbi->fb.fix.smem_start = pdata->video_mem_phys;
337 fbi->fb.fix.smem_len = pdata->video_mem_len;
338 fbi->fb.screen_base = pdata->video_mem_virt;
339
340 fbi->palette_size = PAGE_ALIGN(512);
341 fbi->palette_cpu = dma_alloc_coherent(&pdev->dev,
342 fbi->palette_size,
343 &fbi->palette_phys,
344 GFP_KERNEL);
345 if (fbi->palette_cpu == NULL) {
346 dev_err(&pdev->dev, "Failed to allocate palette buffer\n");
347 ret = -ENOMEM;
348 goto failed_free_io;
349 }
350
351 irq = platform_get_irq(pdev, 0);
352 if (irq < 0) {
353 dev_err(&pdev->dev, "no IRQ defined\n");
354 ret = -ENODEV;
355 goto failed_free_palette;
356 }
357
358 ret = request_irq(irq, vt8500lcd_handle_irq, IRQF_DISABLED, "LCD", fbi);
359 if (ret) {
360 dev_err(&pdev->dev, "request_irq failed: %d\n", ret);
361 ret = -EBUSY;
362 goto failed_free_palette;
363 }
364
365 init_waitqueue_head(&fbi->wait);
366
367 if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
368 dev_err(&pdev->dev, "Failed to allocate color map\n");
369 ret = -ENOMEM;
370 goto failed_free_irq;
371 }
372
373 fb_videomode_to_var(&fbi->fb.var, &pdata->mode);
374 fbi->fb.var.bits_per_pixel = pdata->bpp;
375 fbi->fb.var.xres_virtual = pdata->xres_virtual;
376 fbi->fb.var.yres_virtual = pdata->yres_virtual;
377
378 ret = vt8500lcd_set_par(&fbi->fb);
379 if (ret) {
380 dev_err(&pdev->dev, "Failed to set parameters\n");
381 goto failed_free_cmap;
382 }
383
384 writel(fbi->fb.fix.smem_start >> 22, fbi->regbase + 0x1c);
385 writel((fbi->palette_phys & 0xfffffe00) | 1, fbi->regbase + 0x18);
386
387 platform_set_drvdata(pdev, fbi);
388
389 ret = register_framebuffer(&fbi->fb);
390 if (ret < 0) {
391 dev_err(&pdev->dev,
392 "Failed to register framebuffer device: %d\n", ret);
393 goto failed_free_cmap;
394 }
395
396 /*
397 * Ok, now enable the LCD controller
398 */
399 writel(readl(fbi->regbase) | 1, fbi->regbase);
400
401 return 0;
402
403failed_free_cmap:
404 if (fbi->fb.cmap.len)
405 fb_dealloc_cmap(&fbi->fb.cmap);
406failed_free_irq:
407 free_irq(irq, fbi);
408failed_free_palette:
409 dma_free_coherent(&pdev->dev, fbi->palette_size,
410 fbi->palette_cpu, fbi->palette_phys);
411failed_free_io:
412 iounmap(fbi->regbase);
413failed_free_res:
414 release_mem_region(res->start, resource_size(res));
415failed_fbi:
416 platform_set_drvdata(pdev, NULL);
417 kfree(fbi);
418failed:
419 return ret;
420}
421
422static int __devexit vt8500lcd_remove(struct platform_device *pdev)
423{
424 struct vt8500lcd_info *fbi = platform_get_drvdata(pdev);
425 struct resource *res;
426 int irq;
427
428 unregister_framebuffer(&fbi->fb);
429
430 writel(0, fbi->regbase);
431
432 if (fbi->fb.cmap.len)
433 fb_dealloc_cmap(&fbi->fb.cmap);
434
435 irq = platform_get_irq(pdev, 0);
436 free_irq(irq, fbi);
437
438 dma_free_coherent(&pdev->dev, fbi->palette_size,
439 fbi->palette_cpu, fbi->palette_phys);
440
441 iounmap(fbi->regbase);
442
443 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
444 release_mem_region(res->start, resource_size(res));
445
446 kfree(fbi);
447
448 return 0;
449}
450
451static struct platform_driver vt8500lcd_driver = {
452 .probe = vt8500lcd_probe,
453 .remove = __devexit_p(vt8500lcd_remove),
454 .driver = {
455 .owner = THIS_MODULE,
456 .name = "vt8500-lcd",
457 },
458};
459
460static int __init vt8500lcd_init(void)
461{
462 return platform_driver_register(&vt8500lcd_driver);
463}
464
465static void __exit vt8500lcd_exit(void)
466{
467 platform_driver_unregister(&vt8500lcd_driver);
468}
469
470module_init(vt8500lcd_init);
471module_exit(vt8500lcd_exit);
472
473MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
474MODULE_DESCRIPTION("LCD controller driver for VIA VT8500");
475MODULE_LICENSE("GPL");
diff --git a/drivers/video/vt8500lcdfb.h b/drivers/video/vt8500lcdfb.h
new file mode 100644
index 000000000000..36ca3ca09d83
--- /dev/null
+++ b/drivers/video/vt8500lcdfb.h
@@ -0,0 +1,34 @@
1/*
2 * linux/drivers/video/vt8500lcdfb.h
3 *
4 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16struct vt8500lcd_info {
17 struct fb_info fb;
18 void __iomem *regbase;
19 void __iomem *palette_cpu;
20 dma_addr_t palette_phys;
21 size_t palette_size;
22 wait_queue_head_t wait;
23};
24
25static int bpp_values[] = {
26 1,
27 2,
28 4,
29 8,
30 12,
31 16,
32 18,
33 24,
34};
diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c
index 85d76ec4c63e..f9b3e3dc2421 100644
--- a/drivers/video/vt8623fb.c
+++ b/drivers/video/vt8623fb.c
@@ -23,7 +23,7 @@
23#include <linux/svga.h> 23#include <linux/svga.h>
24#include <linux/init.h> 24#include <linux/init.h>
25#include <linux/pci.h> 25#include <linux/pci.h>
26#include <linux/console.h> /* Why should fb driver call console functions? because acquire_console_sem() */ 26#include <linux/console.h> /* Why should fb driver call console functions? because console_lock() */
27#include <video/vga.h> 27#include <video/vga.h>
28 28
29#ifdef CONFIG_MTRR 29#ifdef CONFIG_MTRR
@@ -121,13 +121,19 @@ MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, d
121 121
122/* ------------------------------------------------------------------------- */ 122/* ------------------------------------------------------------------------- */
123 123
124static void vt8623fb_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor)
125{
126 struct vt8623fb_info *par = info->par;
127
128 svga_tilecursor(par->state.vgabase, info, cursor);
129}
124 130
125static struct fb_tile_ops vt8623fb_tile_ops = { 131static struct fb_tile_ops vt8623fb_tile_ops = {
126 .fb_settile = svga_settile, 132 .fb_settile = svga_settile,
127 .fb_tilecopy = svga_tilecopy, 133 .fb_tilecopy = svga_tilecopy,
128 .fb_tilefill = svga_tilefill, 134 .fb_tilefill = svga_tilefill,
129 .fb_tileblit = svga_tileblit, 135 .fb_tileblit = svga_tileblit,
130 .fb_tilecursor = svga_tilecursor, 136 .fb_tilecursor = vt8623fb_tilecursor,
131 .fb_get_tilemax = svga_get_tilemax, 137 .fb_get_tilemax = svga_get_tilemax,
132}; 138};
133 139
@@ -253,6 +259,7 @@ static void vt8623fb_fillrect(struct fb_info *info, const struct fb_fillrect *re
253 259
254static void vt8623_set_pixclock(struct fb_info *info, u32 pixclock) 260static void vt8623_set_pixclock(struct fb_info *info, u32 pixclock)
255{ 261{
262 struct vt8623fb_info *par = info->par;
256 u16 m, n, r; 263 u16 m, n, r;
257 u8 regval; 264 u8 regval;
258 int rv; 265 int rv;
@@ -264,18 +271,18 @@ static void vt8623_set_pixclock(struct fb_info *info, u32 pixclock)
264 } 271 }
265 272
266 /* Set VGA misc register */ 273 /* Set VGA misc register */
267 regval = vga_r(NULL, VGA_MIS_R); 274 regval = vga_r(par->state.vgabase, VGA_MIS_R);
268 vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); 275 vga_w(par->state.vgabase, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD);
269 276
270 /* Set clock registers */ 277 /* Set clock registers */
271 vga_wseq(NULL, 0x46, (n | (r << 6))); 278 vga_wseq(par->state.vgabase, 0x46, (n | (r << 6)));
272 vga_wseq(NULL, 0x47, m); 279 vga_wseq(par->state.vgabase, 0x47, m);
273 280
274 udelay(1000); 281 udelay(1000);
275 282
276 /* PLL reset */ 283 /* PLL reset */
277 svga_wseq_mask(0x40, 0x02, 0x02); 284 svga_wseq_mask(par->state.vgabase, 0x40, 0x02, 0x02);
278 svga_wseq_mask(0x40, 0x00, 0x02); 285 svga_wseq_mask(par->state.vgabase, 0x40, 0x00, 0x02);
279} 286}
280 287
281 288
@@ -285,7 +292,10 @@ static int vt8623fb_open(struct fb_info *info, int user)
285 292
286 mutex_lock(&(par->open_lock)); 293 mutex_lock(&(par->open_lock));
287 if (par->ref_count == 0) { 294 if (par->ref_count == 0) {
295 void __iomem *vgabase = par->state.vgabase;
296
288 memset(&(par->state), 0, sizeof(struct vgastate)); 297 memset(&(par->state), 0, sizeof(struct vgastate));
298 par->state.vgabase = vgabase;
289 par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP; 299 par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP;
290 par->state.num_crtc = 0xA2; 300 par->state.num_crtc = 0xA2;
291 par->state.num_seq = 0x50; 301 par->state.num_seq = 0x50;
@@ -373,6 +383,7 @@ static int vt8623fb_check_var(struct fb_var_screeninfo *var, struct fb_info *inf
373static int vt8623fb_set_par(struct fb_info *info) 383static int vt8623fb_set_par(struct fb_info *info)
374{ 384{
375 u32 mode, offset_value, fetch_value, screen_size; 385 u32 mode, offset_value, fetch_value, screen_size;
386 struct vt8623fb_info *par = info->par;
376 u32 bpp = info->var.bits_per_pixel; 387 u32 bpp = info->var.bits_per_pixel;
377 388
378 if (bpp != 0) { 389 if (bpp != 0) {
@@ -414,82 +425,82 @@ static int vt8623fb_set_par(struct fb_info *info)
414 info->var.activate = FB_ACTIVATE_NOW; 425 info->var.activate = FB_ACTIVATE_NOW;
415 426
416 /* Unlock registers */ 427 /* Unlock registers */
417 svga_wseq_mask(0x10, 0x01, 0x01); 428 svga_wseq_mask(par->state.vgabase, 0x10, 0x01, 0x01);
418 svga_wcrt_mask(0x11, 0x00, 0x80); 429 svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x80);
419 svga_wcrt_mask(0x47, 0x00, 0x01); 430 svga_wcrt_mask(par->state.vgabase, 0x47, 0x00, 0x01);
420 431
421 /* Device, screen and sync off */ 432 /* Device, screen and sync off */
422 svga_wseq_mask(0x01, 0x20, 0x20); 433 svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
423 svga_wcrt_mask(0x36, 0x30, 0x30); 434 svga_wcrt_mask(par->state.vgabase, 0x36, 0x30, 0x30);
424 svga_wcrt_mask(0x17, 0x00, 0x80); 435 svga_wcrt_mask(par->state.vgabase, 0x17, 0x00, 0x80);
425 436
426 /* Set default values */ 437 /* Set default values */
427 svga_set_default_gfx_regs(); 438 svga_set_default_gfx_regs(par->state.vgabase);
428 svga_set_default_atc_regs(); 439 svga_set_default_atc_regs(par->state.vgabase);
429 svga_set_default_seq_regs(); 440 svga_set_default_seq_regs(par->state.vgabase);
430 svga_set_default_crt_regs(); 441 svga_set_default_crt_regs(par->state.vgabase);
431 svga_wcrt_multi(vt8623_line_compare_regs, 0xFFFFFFFF); 442 svga_wcrt_multi(par->state.vgabase, vt8623_line_compare_regs, 0xFFFFFFFF);
432 svga_wcrt_multi(vt8623_start_address_regs, 0); 443 svga_wcrt_multi(par->state.vgabase, vt8623_start_address_regs, 0);
433 444
434 svga_wcrt_multi(vt8623_offset_regs, offset_value); 445 svga_wcrt_multi(par->state.vgabase, vt8623_offset_regs, offset_value);
435 svga_wseq_multi(vt8623_fetch_count_regs, fetch_value); 446 svga_wseq_multi(par->state.vgabase, vt8623_fetch_count_regs, fetch_value);
436 447
437 /* Clear H/V Skew */ 448 /* Clear H/V Skew */
438 svga_wcrt_mask(0x03, 0x00, 0x60); 449 svga_wcrt_mask(par->state.vgabase, 0x03, 0x00, 0x60);
439 svga_wcrt_mask(0x05, 0x00, 0x60); 450 svga_wcrt_mask(par->state.vgabase, 0x05, 0x00, 0x60);
440 451
441 if (info->var.vmode & FB_VMODE_DOUBLE) 452 if (info->var.vmode & FB_VMODE_DOUBLE)
442 svga_wcrt_mask(0x09, 0x80, 0x80); 453 svga_wcrt_mask(par->state.vgabase, 0x09, 0x80, 0x80);
443 else 454 else
444 svga_wcrt_mask(0x09, 0x00, 0x80); 455 svga_wcrt_mask(par->state.vgabase, 0x09, 0x00, 0x80);
445 456
446 svga_wseq_mask(0x1E, 0xF0, 0xF0); // DI/DVP bus 457 svga_wseq_mask(par->state.vgabase, 0x1E, 0xF0, 0xF0); // DI/DVP bus
447 svga_wseq_mask(0x2A, 0x0F, 0x0F); // DI/DVP bus 458 svga_wseq_mask(par->state.vgabase, 0x2A, 0x0F, 0x0F); // DI/DVP bus
448 svga_wseq_mask(0x16, 0x08, 0xBF); // FIFO read threshold 459 svga_wseq_mask(par->state.vgabase, 0x16, 0x08, 0xBF); // FIFO read threshold
449 vga_wseq(NULL, 0x17, 0x1F); // FIFO depth 460 vga_wseq(par->state.vgabase, 0x17, 0x1F); // FIFO depth
450 vga_wseq(NULL, 0x18, 0x4E); 461 vga_wseq(par->state.vgabase, 0x18, 0x4E);
451 svga_wseq_mask(0x1A, 0x08, 0x08); // enable MMIO ? 462 svga_wseq_mask(par->state.vgabase, 0x1A, 0x08, 0x08); // enable MMIO ?
452 463
453 vga_wcrt(NULL, 0x32, 0x00); 464 vga_wcrt(par->state.vgabase, 0x32, 0x00);
454 vga_wcrt(NULL, 0x34, 0x00); 465 vga_wcrt(par->state.vgabase, 0x34, 0x00);
455 vga_wcrt(NULL, 0x6A, 0x80); 466 vga_wcrt(par->state.vgabase, 0x6A, 0x80);
456 vga_wcrt(NULL, 0x6A, 0xC0); 467 vga_wcrt(par->state.vgabase, 0x6A, 0xC0);
457 468
458 vga_wgfx(NULL, 0x20, 0x00); 469 vga_wgfx(par->state.vgabase, 0x20, 0x00);
459 vga_wgfx(NULL, 0x21, 0x00); 470 vga_wgfx(par->state.vgabase, 0x21, 0x00);
460 vga_wgfx(NULL, 0x22, 0x00); 471 vga_wgfx(par->state.vgabase, 0x22, 0x00);
461 472
462 /* Set SR15 according to number of bits per pixel */ 473 /* Set SR15 according to number of bits per pixel */
463 mode = svga_match_format(vt8623fb_formats, &(info->var), &(info->fix)); 474 mode = svga_match_format(vt8623fb_formats, &(info->var), &(info->fix));
464 switch (mode) { 475 switch (mode) {
465 case 0: 476 case 0:
466 pr_debug("fb%d: text mode\n", info->node); 477 pr_debug("fb%d: text mode\n", info->node);
467 svga_set_textmode_vga_regs(); 478 svga_set_textmode_vga_regs(par->state.vgabase);
468 svga_wseq_mask(0x15, 0x00, 0xFE); 479 svga_wseq_mask(par->state.vgabase, 0x15, 0x00, 0xFE);
469 svga_wcrt_mask(0x11, 0x60, 0x70); 480 svga_wcrt_mask(par->state.vgabase, 0x11, 0x60, 0x70);
470 break; 481 break;
471 case 1: 482 case 1:
472 pr_debug("fb%d: 4 bit pseudocolor\n", info->node); 483 pr_debug("fb%d: 4 bit pseudocolor\n", info->node);
473 vga_wgfx(NULL, VGA_GFX_MODE, 0x40); 484 vga_wgfx(par->state.vgabase, VGA_GFX_MODE, 0x40);
474 svga_wseq_mask(0x15, 0x20, 0xFE); 485 svga_wseq_mask(par->state.vgabase, 0x15, 0x20, 0xFE);
475 svga_wcrt_mask(0x11, 0x00, 0x70); 486 svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x70);
476 break; 487 break;
477 case 2: 488 case 2:
478 pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node); 489 pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node);
479 svga_wseq_mask(0x15, 0x00, 0xFE); 490 svga_wseq_mask(par->state.vgabase, 0x15, 0x00, 0xFE);
480 svga_wcrt_mask(0x11, 0x00, 0x70); 491 svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x70);
481 break; 492 break;
482 case 3: 493 case 3:
483 pr_debug("fb%d: 8 bit pseudocolor\n", info->node); 494 pr_debug("fb%d: 8 bit pseudocolor\n", info->node);
484 svga_wseq_mask(0x15, 0x22, 0xFE); 495 svga_wseq_mask(par->state.vgabase, 0x15, 0x22, 0xFE);
485 break; 496 break;
486 case 4: 497 case 4:
487 pr_debug("fb%d: 5/6/5 truecolor\n", info->node); 498 pr_debug("fb%d: 5/6/5 truecolor\n", info->node);
488 svga_wseq_mask(0x15, 0xB6, 0xFE); 499 svga_wseq_mask(par->state.vgabase, 0x15, 0xB6, 0xFE);
489 break; 500 break;
490 case 5: 501 case 5:
491 pr_debug("fb%d: 8/8/8 truecolor\n", info->node); 502 pr_debug("fb%d: 8/8/8 truecolor\n", info->node);
492 svga_wseq_mask(0x15, 0xAE, 0xFE); 503 svga_wseq_mask(par->state.vgabase, 0x15, 0xAE, 0xFE);
493 break; 504 break;
494 default: 505 default:
495 printk(KERN_ERR "vt8623fb: unsupported mode - bug\n"); 506 printk(KERN_ERR "vt8623fb: unsupported mode - bug\n");
@@ -497,16 +508,16 @@ static int vt8623fb_set_par(struct fb_info *info)
497 } 508 }
498 509
499 vt8623_set_pixclock(info, info->var.pixclock); 510 vt8623_set_pixclock(info, info->var.pixclock);
500 svga_set_timings(&vt8623_timing_regs, &(info->var), 1, 1, 511 svga_set_timings(par->state.vgabase, &vt8623_timing_regs, &(info->var), 1, 1,
501 (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1, 1, 512 (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1, 1,
502 1, info->node); 513 1, info->node);
503 514
504 memset_io(info->screen_base, 0x00, screen_size); 515 memset_io(info->screen_base, 0x00, screen_size);
505 516
506 /* Device and screen back on */ 517 /* Device and screen back on */
507 svga_wcrt_mask(0x17, 0x80, 0x80); 518 svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80);
508 svga_wcrt_mask(0x36, 0x00, 0x30); 519 svga_wcrt_mask(par->state.vgabase, 0x36, 0x00, 0x30);
509 svga_wseq_mask(0x01, 0x00, 0x20); 520 svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
510 521
511 return 0; 522 return 0;
512} 523}
@@ -569,31 +580,33 @@ static int vt8623fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
569 580
570static int vt8623fb_blank(int blank_mode, struct fb_info *info) 581static int vt8623fb_blank(int blank_mode, struct fb_info *info)
571{ 582{
583 struct vt8623fb_info *par = info->par;
584
572 switch (blank_mode) { 585 switch (blank_mode) {
573 case FB_BLANK_UNBLANK: 586 case FB_BLANK_UNBLANK:
574 pr_debug("fb%d: unblank\n", info->node); 587 pr_debug("fb%d: unblank\n", info->node);
575 svga_wcrt_mask(0x36, 0x00, 0x30); 588 svga_wcrt_mask(par->state.vgabase, 0x36, 0x00, 0x30);
576 svga_wseq_mask(0x01, 0x00, 0x20); 589 svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
577 break; 590 break;
578 case FB_BLANK_NORMAL: 591 case FB_BLANK_NORMAL:
579 pr_debug("fb%d: blank\n", info->node); 592 pr_debug("fb%d: blank\n", info->node);
580 svga_wcrt_mask(0x36, 0x00, 0x30); 593 svga_wcrt_mask(par->state.vgabase, 0x36, 0x00, 0x30);
581 svga_wseq_mask(0x01, 0x20, 0x20); 594 svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
582 break; 595 break;
583 case FB_BLANK_HSYNC_SUSPEND: 596 case FB_BLANK_HSYNC_SUSPEND:
584 pr_debug("fb%d: DPMS standby (hsync off)\n", info->node); 597 pr_debug("fb%d: DPMS standby (hsync off)\n", info->node);
585 svga_wcrt_mask(0x36, 0x10, 0x30); 598 svga_wcrt_mask(par->state.vgabase, 0x36, 0x10, 0x30);
586 svga_wseq_mask(0x01, 0x20, 0x20); 599 svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
587 break; 600 break;
588 case FB_BLANK_VSYNC_SUSPEND: 601 case FB_BLANK_VSYNC_SUSPEND:
589 pr_debug("fb%d: DPMS suspend (vsync off)\n", info->node); 602 pr_debug("fb%d: DPMS suspend (vsync off)\n", info->node);
590 svga_wcrt_mask(0x36, 0x20, 0x30); 603 svga_wcrt_mask(par->state.vgabase, 0x36, 0x20, 0x30);
591 svga_wseq_mask(0x01, 0x20, 0x20); 604 svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
592 break; 605 break;
593 case FB_BLANK_POWERDOWN: 606 case FB_BLANK_POWERDOWN:
594 pr_debug("fb%d: DPMS off (no sync)\n", info->node); 607 pr_debug("fb%d: DPMS off (no sync)\n", info->node);
595 svga_wcrt_mask(0x36, 0x30, 0x30); 608 svga_wcrt_mask(par->state.vgabase, 0x36, 0x30, 0x30);
596 svga_wseq_mask(0x01, 0x20, 0x20); 609 svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
597 break; 610 break;
598 } 611 }
599 612
@@ -603,6 +616,7 @@ static int vt8623fb_blank(int blank_mode, struct fb_info *info)
603 616
604static int vt8623fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) 617static int vt8623fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
605{ 618{
619 struct vt8623fb_info *par = info->par;
606 unsigned int offset; 620 unsigned int offset;
607 621
608 /* Calculate the offset */ 622 /* Calculate the offset */
@@ -616,7 +630,7 @@ static int vt8623fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *i
616 } 630 }
617 631
618 /* Set the offset */ 632 /* Set the offset */
619 svga_wcrt_multi(vt8623_start_address_regs, offset); 633 svga_wcrt_multi(par->state.vgabase, vt8623_start_address_regs, offset);
620 634
621 return 0; 635 return 0;
622} 636}
@@ -647,6 +661,8 @@ static struct fb_ops vt8623fb_ops = {
647 661
648static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) 662static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
649{ 663{
664 struct pci_bus_region bus_reg;
665 struct resource vga_res;
650 struct fb_info *info; 666 struct fb_info *info;
651 struct vt8623fb_info *par; 667 struct vt8623fb_info *par;
652 unsigned int memsize1, memsize2; 668 unsigned int memsize1, memsize2;
@@ -705,9 +721,18 @@ static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_devi
705 goto err_iomap_2; 721 goto err_iomap_2;
706 } 722 }
707 723
724 bus_reg.start = 0;
725 bus_reg.end = 64 * 1024;
726
727 vga_res.flags = IORESOURCE_IO;
728
729 pcibios_bus_to_resource(dev, &vga_res, &bus_reg);
730
731 par->state.vgabase = (void __iomem *) vga_res.start;
732
708 /* Find how many physical memory there is on card */ 733 /* Find how many physical memory there is on card */
709 memsize1 = (vga_rseq(NULL, 0x34) + 1) >> 1; 734 memsize1 = (vga_rseq(par->state.vgabase, 0x34) + 1) >> 1;
710 memsize2 = vga_rseq(NULL, 0x39) << 2; 735 memsize2 = vga_rseq(par->state.vgabase, 0x39) << 2;
711 736
712 if ((16 <= memsize1) && (memsize1 <= 64) && (memsize1 == memsize2)) 737 if ((16 <= memsize1) && (memsize1 <= 64) && (memsize1 == memsize2))
713 info->screen_size = memsize1 << 20; 738 info->screen_size = memsize1 << 20;
@@ -819,12 +844,12 @@ static int vt8623_pci_suspend(struct pci_dev* dev, pm_message_t state)
819 844
820 dev_info(info->device, "suspend\n"); 845 dev_info(info->device, "suspend\n");
821 846
822 acquire_console_sem(); 847 console_lock();
823 mutex_lock(&(par->open_lock)); 848 mutex_lock(&(par->open_lock));
824 849
825 if ((state.event == PM_EVENT_FREEZE) || (par->ref_count == 0)) { 850 if ((state.event == PM_EVENT_FREEZE) || (par->ref_count == 0)) {
826 mutex_unlock(&(par->open_lock)); 851 mutex_unlock(&(par->open_lock));
827 release_console_sem(); 852 console_unlock();
828 return 0; 853 return 0;
829 } 854 }
830 855
@@ -835,7 +860,7 @@ static int vt8623_pci_suspend(struct pci_dev* dev, pm_message_t state)
835 pci_set_power_state(dev, pci_choose_state(dev, state)); 860 pci_set_power_state(dev, pci_choose_state(dev, state));
836 861
837 mutex_unlock(&(par->open_lock)); 862 mutex_unlock(&(par->open_lock));
838 release_console_sem(); 863 console_unlock();
839 864
840 return 0; 865 return 0;
841} 866}
@@ -850,7 +875,7 @@ static int vt8623_pci_resume(struct pci_dev* dev)
850 875
851 dev_info(info->device, "resume\n"); 876 dev_info(info->device, "resume\n");
852 877
853 acquire_console_sem(); 878 console_lock();
854 mutex_lock(&(par->open_lock)); 879 mutex_lock(&(par->open_lock));
855 880
856 if (par->ref_count == 0) 881 if (par->ref_count == 0)
@@ -869,7 +894,7 @@ static int vt8623_pci_resume(struct pci_dev* dev)
869 894
870fail: 895fail:
871 mutex_unlock(&(par->open_lock)); 896 mutex_unlock(&(par->open_lock));
872 release_console_sem(); 897 console_unlock();
873 898
874 return 0; 899 return 0;
875} 900}
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
index d8b12c32e3ef..c8be8af0cc6d 100644
--- a/drivers/video/w100fb.c
+++ b/drivers/video/w100fb.c
@@ -1306,7 +1306,7 @@ static void w100_init_lcd(struct w100fb_par *par)
1306 union graphic_v_disp_u graphic_v_disp; 1306 union graphic_v_disp_u graphic_v_disp;
1307 union crtc_total_u crtc_total; 1307 union crtc_total_u crtc_total;
1308 1308
1309 /* w3200 doesnt like undefined bits being set so zero register values first */ 1309 /* w3200 doesn't like undefined bits being set so zero register values first */
1310 1310
1311 active_h_disp.val = 0; 1311 active_h_disp.val = 0;
1312 active_h_disp.f.active_h_start=mode->left_margin; 1312 active_h_disp.f.active_h_start=mode->left_margin;
diff --git a/drivers/video/wm8505fb.c b/drivers/video/wm8505fb.c
new file mode 100644
index 000000000000..96e34a569169
--- /dev/null
+++ b/drivers/video/wm8505fb.c
@@ -0,0 +1,422 @@
1/*
2 * WonderMedia WM8505 Frame Buffer device driver
3 *
4 * Copyright (C) 2010 Ed Spiridonov <edo.rus@gmail.com>
5 * Based on vt8500lcdfb.c
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
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
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <linux/errno.h>
20#include <linux/string.h>
21#include <linux/mm.h>
22#include <linux/slab.h>
23#include <linux/delay.h>
24#include <linux/fb.h>
25#include <linux/init.h>
26#include <linux/interrupt.h>
27#include <linux/io.h>
28#include <linux/dma-mapping.h>
29#include <linux/platform_device.h>
30#include <linux/wait.h>
31
32#include <mach/vt8500fb.h>
33
34#include "wm8505fb_regs.h"
35#include "wmt_ge_rops.h"
36
37#define DRIVER_NAME "wm8505-fb"
38
39#define to_wm8505fb_info(__info) container_of(__info, \
40 struct wm8505fb_info, fb)
41struct wm8505fb_info {
42 struct fb_info fb;
43 void __iomem *regbase;
44 unsigned int contrast;
45};
46
47
48static int wm8505fb_init_hw(struct fb_info *info)
49{
50 struct wm8505fb_info *fbi = to_wm8505fb_info(info);
51
52 int i;
53
54 /* I know the purpose only of few registers, so clear unknown */
55 for (i = 0; i < 0x200; i += 4)
56 writel(0, fbi->regbase + i);
57
58 /* Set frame buffer address */
59 writel(fbi->fb.fix.smem_start, fbi->regbase + WMT_GOVR_FBADDR);
60 writel(fbi->fb.fix.smem_start, fbi->regbase + WMT_GOVR_FBADDR1);
61
62 /* Set in-memory picture format to RGB 32bpp */
63 writel(0x1c, fbi->regbase + WMT_GOVR_COLORSPACE);
64 writel(1, fbi->regbase + WMT_GOVR_COLORSPACE1);
65
66 /* Virtual buffer size */
67 writel(info->var.xres, fbi->regbase + WMT_GOVR_XRES);
68 writel(info->var.xres_virtual, fbi->regbase + WMT_GOVR_XRES_VIRTUAL);
69
70 /* black magic ;) */
71 writel(0xf, fbi->regbase + WMT_GOVR_FHI);
72 writel(4, fbi->regbase + WMT_GOVR_DVO_SET);
73 writel(1, fbi->regbase + WMT_GOVR_MIF_ENABLE);
74 writel(1, fbi->regbase + WMT_GOVR_REG_UPDATE);
75
76 return 0;
77}
78
79static int wm8505fb_set_timing(struct fb_info *info)
80{
81 struct wm8505fb_info *fbi = to_wm8505fb_info(info);
82
83 int h_start = info->var.left_margin;
84 int h_end = h_start + info->var.xres;
85 int h_all = h_end + info->var.right_margin;
86 int h_sync = info->var.hsync_len;
87
88 int v_start = info->var.upper_margin;
89 int v_end = v_start + info->var.yres;
90 int v_all = v_end + info->var.lower_margin;
91 int v_sync = info->var.vsync_len;
92
93 writel(0, fbi->regbase + WMT_GOVR_TG);
94
95 writel(h_start, fbi->regbase + WMT_GOVR_TIMING_H_START);
96 writel(h_end, fbi->regbase + WMT_GOVR_TIMING_H_END);
97 writel(h_all, fbi->regbase + WMT_GOVR_TIMING_H_ALL);
98 writel(h_sync, fbi->regbase + WMT_GOVR_TIMING_H_SYNC);
99
100 writel(v_start, fbi->regbase + WMT_GOVR_TIMING_V_START);
101 writel(v_end, fbi->regbase + WMT_GOVR_TIMING_V_END);
102 writel(v_all, fbi->regbase + WMT_GOVR_TIMING_V_ALL);
103 writel(v_sync, fbi->regbase + WMT_GOVR_TIMING_V_SYNC);
104
105 writel(1, fbi->regbase + WMT_GOVR_TG);
106
107 return 0;
108}
109
110
111static int wm8505fb_set_par(struct fb_info *info)
112{
113 struct wm8505fb_info *fbi = to_wm8505fb_info(info);
114
115 if (!fbi)
116 return -EINVAL;
117
118 if (info->var.bits_per_pixel == 32) {
119 info->var.red.offset = 16;
120 info->var.red.length = 8;
121 info->var.red.msb_right = 0;
122 info->var.green.offset = 8;
123 info->var.green.length = 8;
124 info->var.green.msb_right = 0;
125 info->var.blue.offset = 0;
126 info->var.blue.length = 8;
127 info->var.blue.msb_right = 0;
128 info->fix.visual = FB_VISUAL_TRUECOLOR;
129 info->fix.line_length = info->var.xres_virtual << 2;
130 }
131
132 wm8505fb_set_timing(info);
133
134 writel(fbi->contrast<<16 | fbi->contrast<<8 | fbi->contrast,
135 fbi->regbase + WMT_GOVR_CONTRAST);
136
137 return 0;
138}
139
140static ssize_t contrast_show(struct device *dev,
141 struct device_attribute *attr, char *buf)
142{
143 struct fb_info *info = dev_get_drvdata(dev);
144 struct wm8505fb_info *fbi = to_wm8505fb_info(info);
145
146 return sprintf(buf, "%d\n", fbi->contrast);
147}
148
149static ssize_t contrast_store(struct device *dev,
150 struct device_attribute *attr,
151 const char *buf, size_t count)
152{
153 struct fb_info *info = dev_get_drvdata(dev);
154 struct wm8505fb_info *fbi = to_wm8505fb_info(info);
155 unsigned long tmp;
156
157 if (strict_strtoul(buf, 10, &tmp) || (tmp > 0xff))
158 return -EINVAL;
159 fbi->contrast = tmp;
160
161 wm8505fb_set_par(info);
162
163 return count;
164}
165
166static DEVICE_ATTR(contrast, 0644, contrast_show, contrast_store);
167
168static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
169{
170 chan &= 0xffff;
171 chan >>= 16 - bf->length;
172 return chan << bf->offset;
173}
174
175static int wm8505fb_setcolreg(unsigned regno, unsigned red, unsigned green,
176 unsigned blue, unsigned transp,
177 struct fb_info *info) {
178 struct wm8505fb_info *fbi = to_wm8505fb_info(info);
179 int ret = 1;
180 unsigned int val;
181 if (regno >= 256)
182 return -EINVAL;
183
184 if (info->var.grayscale)
185 red = green = blue =
186 (19595 * red + 38470 * green + 7471 * blue) >> 16;
187
188 switch (fbi->fb.fix.visual) {
189 case FB_VISUAL_TRUECOLOR:
190 if (regno < 16) {
191 u32 *pal = info->pseudo_palette;
192
193 val = chan_to_field(red, &fbi->fb.var.red);
194 val |= chan_to_field(green, &fbi->fb.var.green);
195 val |= chan_to_field(blue, &fbi->fb.var.blue);
196
197 pal[regno] = val;
198 ret = 0;
199 }
200 break;
201 }
202
203 return ret;
204}
205
206static int wm8505fb_pan_display(struct fb_var_screeninfo *var,
207 struct fb_info *info)
208{
209 struct wm8505fb_info *fbi = to_wm8505fb_info(info);
210
211 writel(var->xoffset, fbi->regbase + WMT_GOVR_XPAN);
212 writel(var->yoffset, fbi->regbase + WMT_GOVR_YPAN);
213 return 0;
214}
215
216static int wm8505fb_blank(int blank, struct fb_info *info)
217{
218 struct wm8505fb_info *fbi = to_wm8505fb_info(info);
219
220 switch (blank) {
221 case FB_BLANK_UNBLANK:
222 wm8505fb_set_timing(info);
223 break;
224 default:
225 writel(0, fbi->regbase + WMT_GOVR_TIMING_V_SYNC);
226 break;
227 }
228
229 return 0;
230}
231
232static struct fb_ops wm8505fb_ops = {
233 .owner = THIS_MODULE,
234 .fb_set_par = wm8505fb_set_par,
235 .fb_setcolreg = wm8505fb_setcolreg,
236 .fb_fillrect = wmt_ge_fillrect,
237 .fb_copyarea = wmt_ge_copyarea,
238 .fb_imageblit = sys_imageblit,
239 .fb_sync = wmt_ge_sync,
240 .fb_pan_display = wm8505fb_pan_display,
241 .fb_blank = wm8505fb_blank,
242};
243
244static int __devinit wm8505fb_probe(struct platform_device *pdev)
245{
246 struct wm8505fb_info *fbi;
247 struct resource *res;
248 void *addr;
249 struct vt8500fb_platform_data *pdata;
250 int ret;
251
252 pdata = pdev->dev.platform_data;
253
254 ret = -ENOMEM;
255 fbi = NULL;
256
257 fbi = kzalloc(sizeof(struct wm8505fb_info) + sizeof(u32) * 16,
258 GFP_KERNEL);
259 if (!fbi) {
260 dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
261 ret = -ENOMEM;
262 goto failed;
263 }
264
265 strcpy(fbi->fb.fix.id, DRIVER_NAME);
266
267 fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS;
268 fbi->fb.fix.xpanstep = 1;
269 fbi->fb.fix.ypanstep = 1;
270 fbi->fb.fix.ywrapstep = 0;
271 fbi->fb.fix.accel = FB_ACCEL_NONE;
272
273 fbi->fb.fbops = &wm8505fb_ops;
274 fbi->fb.flags = FBINFO_DEFAULT
275 | FBINFO_HWACCEL_COPYAREA
276 | FBINFO_HWACCEL_FILLRECT
277 | FBINFO_HWACCEL_XPAN
278 | FBINFO_HWACCEL_YPAN
279 | FBINFO_VIRTFB
280 | FBINFO_PARTIAL_PAN_OK;
281 fbi->fb.node = -1;
282
283 addr = fbi;
284 addr = addr + sizeof(struct wm8505fb_info);
285 fbi->fb.pseudo_palette = addr;
286
287 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
288 if (res == NULL) {
289 dev_err(&pdev->dev, "no I/O memory resource defined\n");
290 ret = -ENODEV;
291 goto failed_fbi;
292 }
293
294 res = request_mem_region(res->start, resource_size(res), DRIVER_NAME);
295 if (res == NULL) {
296 dev_err(&pdev->dev, "failed to request I/O memory\n");
297 ret = -EBUSY;
298 goto failed_fbi;
299 }
300
301 fbi->regbase = ioremap(res->start, resource_size(res));
302 if (fbi->regbase == NULL) {
303 dev_err(&pdev->dev, "failed to map I/O memory\n");
304 ret = -EBUSY;
305 goto failed_free_res;
306 }
307
308 fb_videomode_to_var(&fbi->fb.var, &pdata->mode);
309
310 fbi->fb.var.nonstd = 0;
311 fbi->fb.var.activate = FB_ACTIVATE_NOW;
312
313 fbi->fb.var.height = -1;
314 fbi->fb.var.width = -1;
315 fbi->fb.var.xres_virtual = pdata->xres_virtual;
316 fbi->fb.var.yres_virtual = pdata->yres_virtual;
317 fbi->fb.var.bits_per_pixel = pdata->bpp;
318
319 fbi->fb.fix.smem_start = pdata->video_mem_phys;
320 fbi->fb.fix.smem_len = pdata->video_mem_len;
321 fbi->fb.screen_base = pdata->video_mem_virt;
322 fbi->fb.screen_size = pdata->video_mem_len;
323
324 if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
325 dev_err(&pdev->dev, "Failed to allocate color map\n");
326 ret = -ENOMEM;
327 goto failed_free_io;
328 }
329
330 wm8505fb_init_hw(&fbi->fb);
331
332 fbi->contrast = 0x80;
333 ret = wm8505fb_set_par(&fbi->fb);
334 if (ret) {
335 dev_err(&pdev->dev, "Failed to set parameters\n");
336 goto failed_free_cmap;
337 }
338
339 platform_set_drvdata(pdev, fbi);
340
341 ret = register_framebuffer(&fbi->fb);
342 if (ret < 0) {
343 dev_err(&pdev->dev,
344 "Failed to register framebuffer device: %d\n", ret);
345 goto failed_free_cmap;
346 }
347
348 ret = device_create_file(&pdev->dev, &dev_attr_contrast);
349 if (ret < 0) {
350 printk(KERN_WARNING "fb%d: failed to register attributes (%d)\n",
351 fbi->fb.node, ret);
352 }
353
354 printk(KERN_INFO "fb%d: %s frame buffer at 0x%lx-0x%lx\n",
355 fbi->fb.node, fbi->fb.fix.id, fbi->fb.fix.smem_start,
356 fbi->fb.fix.smem_start + fbi->fb.fix.smem_len - 1);
357
358 return 0;
359
360failed_free_cmap:
361 if (fbi->fb.cmap.len)
362 fb_dealloc_cmap(&fbi->fb.cmap);
363failed_free_io:
364 iounmap(fbi->regbase);
365failed_free_res:
366 release_mem_region(res->start, resource_size(res));
367failed_fbi:
368 platform_set_drvdata(pdev, NULL);
369 kfree(fbi);
370failed:
371 return ret;
372}
373
374static int __devexit wm8505fb_remove(struct platform_device *pdev)
375{
376 struct wm8505fb_info *fbi = platform_get_drvdata(pdev);
377 struct resource *res;
378
379 device_remove_file(&pdev->dev, &dev_attr_contrast);
380
381 unregister_framebuffer(&fbi->fb);
382
383 writel(0, fbi->regbase);
384
385 if (fbi->fb.cmap.len)
386 fb_dealloc_cmap(&fbi->fb.cmap);
387
388 iounmap(fbi->regbase);
389
390 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
391 release_mem_region(res->start, resource_size(res));
392
393 kfree(fbi);
394
395 return 0;
396}
397
398static struct platform_driver wm8505fb_driver = {
399 .probe = wm8505fb_probe,
400 .remove = __devexit_p(wm8505fb_remove),
401 .driver = {
402 .owner = THIS_MODULE,
403 .name = DRIVER_NAME,
404 },
405};
406
407static int __init wm8505fb_init(void)
408{
409 return platform_driver_register(&wm8505fb_driver);
410}
411
412static void __exit wm8505fb_exit(void)
413{
414 platform_driver_unregister(&wm8505fb_driver);
415}
416
417module_init(wm8505fb_init);
418module_exit(wm8505fb_exit);
419
420MODULE_AUTHOR("Ed Spiridonov <edo.rus@gmail.com>");
421MODULE_DESCRIPTION("Framebuffer driver for WMT WM8505");
422MODULE_LICENSE("GPL");
diff --git a/drivers/video/wm8505fb_regs.h b/drivers/video/wm8505fb_regs.h
new file mode 100644
index 000000000000..4dd41668c6d1
--- /dev/null
+++ b/drivers/video/wm8505fb_regs.h
@@ -0,0 +1,76 @@
1/*
2 * GOVR registers list for WM8505 chips
3 *
4 * Copyright (C) 2010 Ed Spiridonov <edo.rus@gmail.com>
5 * Based on VIA/WonderMedia wm8510-govrh-reg.h
6 * http://github.com/projectgus/kernel_wm8505/blob/wm8505_2.6.29/
7 * drivers/video/wmt/register/wm8510/wm8510-govrh-reg.h
8 *
9 * This software is licensed under the terms of the GNU General Public
10 * License version 2, as published by the Free Software Foundation, and
11 * may be copied, distributed, and modified under those terms.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
18
19#ifndef _WM8505FB_REGS_H
20#define _WM8505FB_REGS_H
21
22/*
23 * Color space select register, default value 0x1c
24 * BIT0 GOVRH_DVO_YUV2RGB_ENABLE
25 * BIT1 GOVRH_VGA_YUV2RGB_ENABLE
26 * BIT2 GOVRH_RGB_MODE
27 * BIT3 GOVRH_DAC_CLKINV
28 * BIT4 GOVRH_BLANK_ZERO
29 */
30#define WMT_GOVR_COLORSPACE 0x1e4
31/*
32 * Another colorspace select register, default value 1
33 * BIT0 GOVRH_DVO_RGB
34 * BIT1 GOVRH_DVO_YUV422
35 */
36#define WMT_GOVR_COLORSPACE1 0x30
37
38#define WMT_GOVR_CONTRAST 0x1b8
39#define WMT_GOVR_BRGHTNESS 0x1bc /* incompatible with RGB? */
40
41/* Framubeffer address */
42#define WMT_GOVR_FBADDR 0x90
43#define WMT_GOVR_FBADDR1 0x94 /* UV offset in YUV mode */
44
45/* Offset of visible window */
46#define WMT_GOVR_XPAN 0xa4
47#define WMT_GOVR_YPAN 0xa0
48
49#define WMT_GOVR_XRES 0x98
50#define WMT_GOVR_XRES_VIRTUAL 0x9c
51
52#define WMT_GOVR_MIF_ENABLE 0x80
53#define WMT_GOVR_FHI 0xa8
54#define WMT_GOVR_REG_UPDATE 0xe4
55
56/*
57 * BIT0 GOVRH_DVO_OUTWIDTH
58 * BIT1 GOVRH_DVO_SYNC_POLAR
59 * BIT2 GOVRH_DVO_ENABLE
60 */
61#define WMT_GOVR_DVO_SET 0x148
62
63/* Timing generator? */
64#define WMT_GOVR_TG 0x100
65
66/* Timings */
67#define WMT_GOVR_TIMING_H_ALL 0x108
68#define WMT_GOVR_TIMING_V_ALL 0x10c
69#define WMT_GOVR_TIMING_V_START 0x110
70#define WMT_GOVR_TIMING_V_END 0x114
71#define WMT_GOVR_TIMING_H_START 0x118
72#define WMT_GOVR_TIMING_H_END 0x11c
73#define WMT_GOVR_TIMING_V_SYNC 0x128
74#define WMT_GOVR_TIMING_H_SYNC 0x12c
75
76#endif /* _WM8505FB_REGS_H */
diff --git a/drivers/video/wmt_ge_rops.c b/drivers/video/wmt_ge_rops.c
new file mode 100644
index 000000000000..45832b7ef7d2
--- /dev/null
+++ b/drivers/video/wmt_ge_rops.c
@@ -0,0 +1,186 @@
1/*
2 * linux/drivers/video/wmt_ge_rops.c
3 *
4 * Accelerators for raster operations using WonderMedia Graphics Engine
5 *
6 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/module.h>
19#include <linux/fb.h>
20#include <linux/platform_device.h>
21#include "fb_draw.h"
22
23#define GE_COMMAND_OFF 0x00
24#define GE_DEPTH_OFF 0x04
25#define GE_HIGHCOLOR_OFF 0x08
26#define GE_ROPCODE_OFF 0x14
27#define GE_FIRE_OFF 0x18
28#define GE_SRCBASE_OFF 0x20
29#define GE_SRCDISPW_OFF 0x24
30#define GE_SRCDISPH_OFF 0x28
31#define GE_SRCAREAX_OFF 0x2c
32#define GE_SRCAREAY_OFF 0x30
33#define GE_SRCAREAW_OFF 0x34
34#define GE_SRCAREAH_OFF 0x38
35#define GE_DESTBASE_OFF 0x3c
36#define GE_DESTDISPW_OFF 0x40
37#define GE_DESTDISPH_OFF 0x44
38#define GE_DESTAREAX_OFF 0x48
39#define GE_DESTAREAY_OFF 0x4c
40#define GE_DESTAREAW_OFF 0x50
41#define GE_DESTAREAH_OFF 0x54
42#define GE_PAT0C_OFF 0x88 /* Pattern 0 color */
43#define GE_ENABLE_OFF 0xec
44#define GE_INTEN_OFF 0xf0
45#define GE_STATUS_OFF 0xf8
46
47static void __iomem *regbase;
48
49void wmt_ge_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
50{
51 unsigned long fg, pat;
52
53 if (p->state != FBINFO_STATE_RUNNING)
54 return;
55
56 if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
57 p->fix.visual == FB_VISUAL_DIRECTCOLOR)
58 fg = ((u32 *) (p->pseudo_palette))[rect->color];
59 else
60 fg = rect->color;
61
62 pat = pixel_to_pat(p->var.bits_per_pixel, fg);
63
64 if (p->fbops->fb_sync)
65 p->fbops->fb_sync(p);
66
67 writel(p->var.bits_per_pixel == 32 ? 3 :
68 (p->var.bits_per_pixel == 8 ? 0 : 1), regbase + GE_DEPTH_OFF);
69 writel(p->var.bits_per_pixel == 15 ? 1 : 0, regbase + GE_HIGHCOLOR_OFF);
70 writel(p->fix.smem_start, regbase + GE_DESTBASE_OFF);
71 writel(p->var.xres_virtual - 1, regbase + GE_DESTDISPW_OFF);
72 writel(p->var.yres_virtual - 1, regbase + GE_DESTDISPH_OFF);
73 writel(rect->dx, regbase + GE_DESTAREAX_OFF);
74 writel(rect->dy, regbase + GE_DESTAREAY_OFF);
75 writel(rect->width - 1, regbase + GE_DESTAREAW_OFF);
76 writel(rect->height - 1, regbase + GE_DESTAREAH_OFF);
77
78 writel(pat, regbase + GE_PAT0C_OFF);
79 writel(1, regbase + GE_COMMAND_OFF);
80 writel(rect->rop == ROP_XOR ? 0x5a : 0xf0, regbase + GE_ROPCODE_OFF);
81 writel(1, regbase + GE_FIRE_OFF);
82}
83EXPORT_SYMBOL_GPL(wmt_ge_fillrect);
84
85void wmt_ge_copyarea(struct fb_info *p, const struct fb_copyarea *area)
86{
87 if (p->state != FBINFO_STATE_RUNNING)
88 return;
89
90 if (p->fbops->fb_sync)
91 p->fbops->fb_sync(p);
92
93 writel(p->var.bits_per_pixel > 16 ? 3 :
94 (p->var.bits_per_pixel > 8 ? 1 : 0), regbase + GE_DEPTH_OFF);
95
96 writel(p->fix.smem_start, regbase + GE_SRCBASE_OFF);
97 writel(p->var.xres_virtual - 1, regbase + GE_SRCDISPW_OFF);
98 writel(p->var.yres_virtual - 1, regbase + GE_SRCDISPH_OFF);
99 writel(area->sx, regbase + GE_SRCAREAX_OFF);
100 writel(area->sy, regbase + GE_SRCAREAY_OFF);
101 writel(area->width - 1, regbase + GE_SRCAREAW_OFF);
102 writel(area->height - 1, regbase + GE_SRCAREAH_OFF);
103
104 writel(p->fix.smem_start, regbase + GE_DESTBASE_OFF);
105 writel(p->var.xres_virtual - 1, regbase + GE_DESTDISPW_OFF);
106 writel(p->var.yres_virtual - 1, regbase + GE_DESTDISPH_OFF);
107 writel(area->dx, regbase + GE_DESTAREAX_OFF);
108 writel(area->dy, regbase + GE_DESTAREAY_OFF);
109 writel(area->width - 1, regbase + GE_DESTAREAW_OFF);
110 writel(area->height - 1, regbase + GE_DESTAREAH_OFF);
111
112 writel(0xcc, regbase + GE_ROPCODE_OFF);
113 writel(1, regbase + GE_COMMAND_OFF);
114 writel(1, regbase + GE_FIRE_OFF);
115}
116EXPORT_SYMBOL_GPL(wmt_ge_copyarea);
117
118int wmt_ge_sync(struct fb_info *p)
119{
120 int loops = 5000000;
121 while ((readl(regbase + GE_STATUS_OFF) & 4) && --loops)
122 cpu_relax();
123 return loops > 0 ? 0 : -EBUSY;
124}
125EXPORT_SYMBOL_GPL(wmt_ge_sync);
126
127static int __devinit wmt_ge_rops_probe(struct platform_device *pdev)
128{
129 struct resource *res;
130
131 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
132 if (res == NULL) {
133 dev_err(&pdev->dev, "no I/O memory resource defined\n");
134 return -ENODEV;
135 }
136
137 /* Only one ROP engine is presently supported. */
138 if (unlikely(regbase)) {
139 WARN_ON(1);
140 return -EBUSY;
141 }
142
143 regbase = ioremap(res->start, resource_size(res));
144 if (regbase == NULL) {
145 dev_err(&pdev->dev, "failed to map I/O memory\n");
146 return -EBUSY;
147 }
148
149 writel(1, regbase + GE_ENABLE_OFF);
150 printk(KERN_INFO "Enabled support for WMT GE raster acceleration\n");
151
152 return 0;
153}
154
155static int __devexit wmt_ge_rops_remove(struct platform_device *pdev)
156{
157 iounmap(regbase);
158 return 0;
159}
160
161static struct platform_driver wmt_ge_rops_driver = {
162 .probe = wmt_ge_rops_probe,
163 .remove = __devexit_p(wmt_ge_rops_remove),
164 .driver = {
165 .owner = THIS_MODULE,
166 .name = "wmt_ge_rops",
167 },
168};
169
170static int __init wmt_ge_rops_init(void)
171{
172 return platform_driver_register(&wmt_ge_rops_driver);
173}
174
175static void __exit wmt_ge_rops_exit(void)
176{
177 platform_driver_unregister(&wmt_ge_rops_driver);
178}
179
180module_init(wmt_ge_rops_init);
181module_exit(wmt_ge_rops_exit);
182
183MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com");
184MODULE_DESCRIPTION("Accelerators for raster operations using "
185 "WonderMedia Graphics Engine");
186MODULE_LICENSE("GPL");
diff --git a/drivers/video/wmt_ge_rops.h b/drivers/video/wmt_ge_rops.h
new file mode 100644
index 000000000000..87380751a443
--- /dev/null
+++ b/drivers/video/wmt_ge_rops.h
@@ -0,0 +1,5 @@
1extern void wmt_ge_fillrect(struct fb_info *info,
2 const struct fb_fillrect *rect);
3extern void wmt_ge_copyarea(struct fb_info *info,
4 const struct fb_copyarea *area);
5extern int wmt_ge_sync(struct fb_info *info);
diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
index 7c7f42a12796..beac52fc1c0e 100644
--- a/drivers/video/xen-fbfront.c
+++ b/drivers/video/xen-fbfront.c
@@ -395,10 +395,9 @@ static int __devinit xenfb_probe(struct xenbus_device *dev,
395 spin_lock_init(&info->dirty_lock); 395 spin_lock_init(&info->dirty_lock);
396 spin_lock_init(&info->resize_lock); 396 spin_lock_init(&info->resize_lock);
397 397
398 info->fb = vmalloc(fb_size); 398 info->fb = vzalloc(fb_size);
399 if (info->fb == NULL) 399 if (info->fb == NULL)
400 goto error_nomem; 400 goto error_nomem;
401 memset(info->fb, 0, fb_size);
402 401
403 info->nr_pages = (fb_size + PAGE_SIZE - 1) >> PAGE_SHIFT; 402 info->nr_pages = (fb_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
404 403
@@ -491,12 +490,12 @@ xenfb_make_preferred_console(void)
491 if (console_set_on_cmdline) 490 if (console_set_on_cmdline)
492 return; 491 return;
493 492
494 acquire_console_sem(); 493 console_lock();
495 for (c = console_drivers; c; c = c->next) { 494 for_each_console(c) {
496 if (!strcmp(c->name, "tty") && c->index == 0) 495 if (!strcmp(c->name, "tty") && c->index == 0)
497 break; 496 break;
498 } 497 }
499 release_console_sem(); 498 console_unlock();
500 if (c) { 499 if (c) {
501 unregister_console(c); 500 unregister_console(c);
502 c->flags |= CON_CONSDEV; 501 c->flags |= CON_CONSDEV;
@@ -562,26 +561,24 @@ static void xenfb_init_shared_page(struct xenfb_info *info,
562static int xenfb_connect_backend(struct xenbus_device *dev, 561static int xenfb_connect_backend(struct xenbus_device *dev,
563 struct xenfb_info *info) 562 struct xenfb_info *info)
564{ 563{
565 int ret, evtchn; 564 int ret, evtchn, irq;
566 struct xenbus_transaction xbt; 565 struct xenbus_transaction xbt;
567 566
568 ret = xenbus_alloc_evtchn(dev, &evtchn); 567 ret = xenbus_alloc_evtchn(dev, &evtchn);
569 if (ret) 568 if (ret)
570 return ret; 569 return ret;
571 ret = bind_evtchn_to_irqhandler(evtchn, xenfb_event_handler, 570 irq = bind_evtchn_to_irqhandler(evtchn, xenfb_event_handler,
572 0, dev->devicetype, info); 571 0, dev->devicetype, info);
573 if (ret < 0) { 572 if (irq < 0) {
574 xenbus_free_evtchn(dev, evtchn); 573 xenbus_free_evtchn(dev, evtchn);
575 xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler"); 574 xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
576 return ret; 575 return irq;
577 } 576 }
578 info->irq = ret;
579
580 again: 577 again:
581 ret = xenbus_transaction_start(&xbt); 578 ret = xenbus_transaction_start(&xbt);
582 if (ret) { 579 if (ret) {
583 xenbus_dev_fatal(dev, ret, "starting transaction"); 580 xenbus_dev_fatal(dev, ret, "starting transaction");
584 return ret; 581 goto unbind_irq;
585 } 582 }
586 ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu", 583 ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
587 virt_to_mfn(info->page)); 584 virt_to_mfn(info->page));
@@ -603,20 +600,25 @@ static int xenfb_connect_backend(struct xenbus_device *dev,
603 if (ret == -EAGAIN) 600 if (ret == -EAGAIN)
604 goto again; 601 goto again;
605 xenbus_dev_fatal(dev, ret, "completing transaction"); 602 xenbus_dev_fatal(dev, ret, "completing transaction");
606 return ret; 603 goto unbind_irq;
607 } 604 }
608 605
609 xenbus_switch_state(dev, XenbusStateInitialised); 606 xenbus_switch_state(dev, XenbusStateInitialised);
607 info->irq = irq;
610 return 0; 608 return 0;
611 609
612 error_xenbus: 610 error_xenbus:
613 xenbus_transaction_end(xbt, 1); 611 xenbus_transaction_end(xbt, 1);
614 xenbus_dev_fatal(dev, ret, "writing xenstore"); 612 xenbus_dev_fatal(dev, ret, "writing xenstore");
613 unbind_irq:
614 unbind_from_irqhandler(irq, info);
615 return ret; 615 return ret;
616} 616}
617 617
618static void xenfb_disconnect_backend(struct xenfb_info *info) 618static void xenfb_disconnect_backend(struct xenfb_info *info)
619{ 619{
620 /* Prevent xenfb refresh */
621 info->update_wanted = 0;
620 if (info->irq >= 0) 622 if (info->irq >= 0)
621 unbind_from_irqhandler(info->irq, info); 623 unbind_from_irqhandler(info->irq, info);
622 info->irq = -1; 624 info->irq = -1;
@@ -631,6 +633,8 @@ static void xenfb_backend_changed(struct xenbus_device *dev,
631 switch (backend_state) { 633 switch (backend_state) {
632 case XenbusStateInitialising: 634 case XenbusStateInitialising:
633 case XenbusStateInitialised: 635 case XenbusStateInitialised:
636 case XenbusStateReconfiguring:
637 case XenbusStateReconfigured:
634 case XenbusStateUnknown: 638 case XenbusStateUnknown:
635 case XenbusStateClosed: 639 case XenbusStateClosed:
636 break; 640 break;
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c
index 0c9ce88e95e8..77dea015ff69 100644
--- a/drivers/video/xilinxfb.c
+++ b/drivers/video/xilinxfb.c
@@ -32,10 +32,14 @@
32#include <linux/dma-mapping.h> 32#include <linux/dma-mapping.h>
33#include <linux/of_device.h> 33#include <linux/of_device.h>
34#include <linux/of_platform.h> 34#include <linux/of_platform.h>
35#include <linux/of_address.h>
35#include <linux/io.h> 36#include <linux/io.h>
36#include <linux/xilinxfb.h> 37#include <linux/xilinxfb.h>
37#include <linux/slab.h> 38#include <linux/slab.h>
39
40#ifdef CONFIG_PPC_DCR
38#include <asm/dcr.h> 41#include <asm/dcr.h>
42#endif
39 43
40#define DRIVER_NAME "xilinxfb" 44#define DRIVER_NAME "xilinxfb"
41 45
@@ -123,10 +127,10 @@ struct xilinxfb_drvdata {
123 registers */ 127 registers */
124 void __iomem *regs; /* virt. address of the control 128 void __iomem *regs; /* virt. address of the control
125 registers */ 129 registers */
126 130#ifdef CONFIG_PPC_DCR
127 dcr_host_t dcr_host; 131 dcr_host_t dcr_host;
128 unsigned int dcr_len; 132 unsigned int dcr_len;
129 133#endif
130 void *fb_virt; /* virt. address of the frame buffer */ 134 void *fb_virt; /* virt. address of the frame buffer */
131 dma_addr_t fb_phys; /* phys. address of the frame buffer */ 135 dma_addr_t fb_phys; /* phys. address of the frame buffer */
132 int fb_alloced; /* Flag, was the fb memory alloced? */ 136 int fb_alloced; /* Flag, was the fb memory alloced? */
@@ -152,9 +156,10 @@ static void xilinx_fb_out_be32(struct xilinxfb_drvdata *drvdata, u32 offset,
152{ 156{
153 if (drvdata->flags & PLB_ACCESS_FLAG) 157 if (drvdata->flags & PLB_ACCESS_FLAG)
154 out_be32(drvdata->regs + (offset << 2), val); 158 out_be32(drvdata->regs + (offset << 2), val);
159#ifdef CONFIG_PPC_DCR
155 else 160 else
156 dcr_write(drvdata->dcr_host, offset, val); 161 dcr_write(drvdata->dcr_host, offset, val);
157 162#endif
158} 163}
159 164
160static int 165static int
@@ -383,8 +388,11 @@ static int xilinxfb_release(struct device *dev)
383 if (drvdata->flags & PLB_ACCESS_FLAG) { 388 if (drvdata->flags & PLB_ACCESS_FLAG) {
384 iounmap(drvdata->regs); 389 iounmap(drvdata->regs);
385 release_mem_region(drvdata->regs_phys, 8); 390 release_mem_region(drvdata->regs_phys, 8);
386 } else 391 }
392#ifdef CONFIG_PPC_DCR
393 else
387 dcr_unmap(drvdata->dcr_host, drvdata->dcr_len); 394 dcr_unmap(drvdata->dcr_host, drvdata->dcr_len);
395#endif
388 396
389 kfree(drvdata); 397 kfree(drvdata);
390 dev_set_drvdata(dev, NULL); 398 dev_set_drvdata(dev, NULL);
@@ -396,22 +404,19 @@ static int xilinxfb_release(struct device *dev)
396 * OF bus binding 404 * OF bus binding
397 */ 405 */
398 406
399static int __devinit 407static int __devinit xilinxfb_of_probe(struct platform_device *op)
400xilinxfb_of_probe(struct platform_device *op, const struct of_device_id *match)
401{ 408{
402 const u32 *prop; 409 const u32 *prop;
403 u32 *p; 410 u32 *p;
404 u32 tft_access; 411 u32 tft_access;
405 struct xilinxfb_platform_data pdata; 412 struct xilinxfb_platform_data pdata;
406 struct resource res; 413 struct resource res;
407 int size, rc, start; 414 int size, rc;
408 struct xilinxfb_drvdata *drvdata; 415 struct xilinxfb_drvdata *drvdata;
409 416
410 /* Copy with the default pdata (not a ptr reference!) */ 417 /* Copy with the default pdata (not a ptr reference!) */
411 pdata = xilinx_fb_default_pdata; 418 pdata = xilinx_fb_default_pdata;
412 419
413 dev_dbg(&op->dev, "xilinxfb_of_probe(%p, %p)\n", op, match);
414
415 /* Allocate the driver data region */ 420 /* Allocate the driver data region */
416 drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); 421 drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
417 if (!drvdata) { 422 if (!drvdata) {
@@ -437,7 +442,10 @@ xilinxfb_of_probe(struct platform_device *op, const struct of_device_id *match)
437 dev_err(&op->dev, "invalid address\n"); 442 dev_err(&op->dev, "invalid address\n");
438 goto err; 443 goto err;
439 } 444 }
440 } else { 445 }
446#ifdef CONFIG_PPC_DCR
447 else {
448 int start;
441 res.start = 0; 449 res.start = 0;
442 start = dcr_resource_start(op->dev.of_node, 0); 450 start = dcr_resource_start(op->dev.of_node, 0);
443 drvdata->dcr_len = dcr_resource_len(op->dev.of_node, 0); 451 drvdata->dcr_len = dcr_resource_len(op->dev.of_node, 0);
@@ -447,6 +455,7 @@ xilinxfb_of_probe(struct platform_device *op, const struct of_device_id *match)
447 goto err; 455 goto err;
448 } 456 }
449 } 457 }
458#endif
450 459
451 prop = of_get_property(op->dev.of_node, "phys-size", &size); 460 prop = of_get_property(op->dev.of_node, "phys-size", &size);
452 if ((prop) && (size >= sizeof(u32)*2)) { 461 if ((prop) && (size >= sizeof(u32)*2)) {
@@ -493,7 +502,7 @@ static struct of_device_id xilinxfb_of_match[] __devinitdata = {
493}; 502};
494MODULE_DEVICE_TABLE(of, xilinxfb_of_match); 503MODULE_DEVICE_TABLE(of, xilinxfb_of_match);
495 504
496static struct of_platform_driver xilinxfb_of_driver = { 505static struct platform_driver xilinxfb_of_driver = {
497 .probe = xilinxfb_of_probe, 506 .probe = xilinxfb_of_probe,
498 .remove = __devexit_p(xilinxfb_of_remove), 507 .remove = __devexit_p(xilinxfb_of_remove),
499 .driver = { 508 .driver = {
@@ -511,13 +520,13 @@ static struct of_platform_driver xilinxfb_of_driver = {
511static int __init 520static int __init
512xilinxfb_init(void) 521xilinxfb_init(void)
513{ 522{
514 return of_register_platform_driver(&xilinxfb_of_driver); 523 return platform_driver_register(&xilinxfb_of_driver);
515} 524}
516 525
517static void __exit 526static void __exit
518xilinxfb_cleanup(void) 527xilinxfb_cleanup(void)
519{ 528{
520 of_unregister_platform_driver(&xilinxfb_of_driver); 529 platform_driver_unregister(&xilinxfb_of_driver);
521} 530}
522 531
523module_init(xilinxfb_init); 532module_init(xilinxfb_init);