aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/68328fb.c3
-rw-r--r--drivers/video/Kconfig65
-rw-r--r--drivers/video/Makefile4
-rw-r--r--drivers/video/acornfb.c4
-rw-r--r--drivers/video/amba-clcd.c31
-rw-r--r--drivers/video/amifb.c1
-rw-r--r--drivers/video/arcfb.c3
-rw-r--r--drivers/video/asiliantfb.c5
-rw-r--r--drivers/video/atafb.c4
-rw-r--r--drivers/video/atmel_lcdfb.c11
-rw-r--r--drivers/video/aty/aty128fb.c22
-rw-r--r--drivers/video/aty/atyfb_base.c21
-rw-r--r--drivers/video/aty/mach64_cursor.c1
-rw-r--r--drivers/video/aty/radeon_backlight.c14
-rw-r--r--drivers/video/aty/radeon_monitor.c3
-rw-r--r--drivers/video/au1100fb.c1
-rw-r--r--drivers/video/au1200fb.c1
-rw-r--r--drivers/video/backlight/88pm860x_bl.c307
-rw-r--r--drivers/video/backlight/Kconfig20
-rw-r--r--drivers/video/backlight/Makefile3
-rw-r--r--drivers/video/backlight/adp5520_bl.c137
-rw-r--r--drivers/video/backlight/adx_bl.c13
-rw-r--r--drivers/video/backlight/atmel-pwm-bl.c13
-rw-r--r--drivers/video/backlight/backlight.c11
-rw-r--r--drivers/video/backlight/corgi_lcd.c11
-rw-r--r--drivers/video/backlight/cr_bllcd.c13
-rw-r--r--drivers/video/backlight/da903x_bl.c19
-rw-r--r--drivers/video/backlight/generic_bl.c10
-rw-r--r--drivers/video/backlight/hp680_bl.c10
-rw-r--r--drivers/video/backlight/ili9320.c1
-rw-r--r--drivers/video/backlight/jornada720_bl.c9
-rw-r--r--drivers/video/backlight/kb3886_bl.c10
-rw-r--r--drivers/video/backlight/l4f00242t03.c258
-rw-r--r--drivers/video/backlight/lcd.c5
-rw-r--r--drivers/video/backlight/lms283gf05.c1
-rw-r--r--drivers/video/backlight/locomolcd.c10
-rw-r--r--drivers/video/backlight/ltv350qv.c1
-rw-r--r--drivers/video/backlight/max8925_bl.c203
-rw-r--r--drivers/video/backlight/mbp_nvidia_bl.c75
-rw-r--r--drivers/video/backlight/omap1_bl.c16
-rw-r--r--drivers/video/backlight/platform_lcd.c1
-rw-r--r--drivers/video/backlight/progear_bl.c25
-rw-r--r--drivers/video/backlight/pwm_bl.c20
-rw-r--r--drivers/video/backlight/tdo24m.c2
-rw-r--r--drivers/video/backlight/tosa_bl.c11
-rw-r--r--drivers/video/backlight/tosa_lcd.c3
-rw-r--r--drivers/video/backlight/wm831x_bl.c10
-rw-r--r--drivers/video/bf54x-lq043fb.c49
-rw-r--r--drivers/video/bfin-lq035q1-fb.c826
-rw-r--r--drivers/video/bfin-t350mcqb-fb.c96
-rw-r--r--drivers/video/broadsheetfb.c740
-rw-r--r--drivers/video/bw2.c1
-rw-r--r--drivers/video/carminefb.c1
-rw-r--r--drivers/video/cfbcopyarea.c1
-rw-r--r--drivers/video/cg14.c1
-rw-r--r--drivers/video/cg3.c1
-rw-r--r--drivers/video/cg6.c1
-rw-r--r--drivers/video/chipsfb.c1
-rw-r--r--drivers/video/cirrusfb.c1
-rw-r--r--drivers/video/clps711xfb.c50
-rw-r--r--drivers/video/cobalt_lcdfb.c2
-rw-r--r--drivers/video/console/Kconfig1
-rw-r--r--drivers/video/console/bitblit.c1
-rw-r--r--drivers/video/console/fbcon.c18
-rw-r--r--drivers/video/console/fbcon_ccw.c1
-rw-r--r--drivers/video/console/fbcon_cw.c1
-rw-r--r--drivers/video/console/fbcon_rotate.c1
-rw-r--r--drivers/video/console/fbcon_ud.c1
-rw-r--r--drivers/video/console/mdacon.c1
-rw-r--r--drivers/video/console/sticore.c2
-rw-r--r--drivers/video/console/vgacon.c7
-rw-r--r--drivers/video/cyber2000fb.c12
-rw-r--r--drivers/video/da8xx-fb.c176
-rw-r--r--drivers/video/display/display-sysfs.c3
-rw-r--r--drivers/video/dnfb.c1
-rw-r--r--drivers/video/efifb.c16
-rw-r--r--drivers/video/ep93xx-fb.c3
-rw-r--r--drivers/video/epson1355fb.c3
-rw-r--r--drivers/video/fb_ddc.c1
-rw-r--r--drivers/video/fb_defio.c7
-rw-r--r--drivers/video/fbcvt.c1
-rw-r--r--drivers/video/fbmem.c1
-rw-r--r--drivers/video/fbmon.c1
-rw-r--r--drivers/video/fbsysfs.c1
-rw-r--r--drivers/video/ffb.c1
-rw-r--r--drivers/video/fsl-diu-fb.c6
-rw-r--r--drivers/video/g364fb.c1
-rw-r--r--drivers/video/gbefb.c5
-rw-r--r--drivers/video/geode/display_gx.c4
-rw-r--r--drivers/video/geode/gx1fb_core.c1
-rw-r--r--drivers/video/geode/gxfb.h2
-rw-r--r--drivers/video/geode/gxfb_core.c3
-rw-r--r--drivers/video/geode/lxfb.h14
-rw-r--r--drivers/video/geode/lxfb_core.c1
-rw-r--r--drivers/video/geode/lxfb_ops.c14
-rw-r--r--drivers/video/geode/suspend_gx.c2
-rw-r--r--drivers/video/geode/video_gx.c2
-rw-r--r--drivers/video/hecubafb.c3
-rw-r--r--drivers/video/hgafb.c3
-rw-r--r--drivers/video/hitfb.c5
-rw-r--r--drivers/video/hpfb.c1
-rw-r--r--drivers/video/i810/i810-i2c.c1
-rw-r--r--drivers/video/i810/i810_dvt.c53
-rw-r--r--drivers/video/imsttfb.c1
-rw-r--r--drivers/video/imxfb.c6
-rw-r--r--drivers/video/intelfb/intelfbdrv.c3
-rw-r--r--drivers/video/intelfb/intelfbhw.c48
-rw-r--r--drivers/video/intelfb/intelfbhw.h1
-rw-r--r--drivers/video/leo.c1
-rw-r--r--drivers/video/macfb.c736
-rw-r--r--drivers/video/macmodes.c80
-rw-r--r--drivers/video/matrox/g450_pll.c3
-rw-r--r--drivers/video/matrox/i2c-matroxfb.c1
-rw-r--r--drivers/video/matrox/matroxfb_base.c1
-rw-r--r--drivers/video/matrox/matroxfb_crtc2.c1
-rw-r--r--drivers/video/matrox/matroxfb_maven.c1
-rw-r--r--drivers/video/maxinefb.c4
-rw-r--r--drivers/video/mb862xx/Makefile2
-rw-r--r--drivers/video/mb862xx/mb862xxfb.c27
-rw-r--r--drivers/video/mb862xx/mb862xxfb.h2
-rw-r--r--drivers/video/mb862xx/mb862xxfb_accel.c335
-rw-r--r--drivers/video/mb862xx/mb862xxfb_accel.h203
-rw-r--r--drivers/video/mbx/mbxdebugfs.c1
-rw-r--r--drivers/video/mbx/mbxfb.c2
-rw-r--r--drivers/video/metronomefb.c3
-rw-r--r--drivers/video/modedb.c33
-rw-r--r--drivers/video/msm/mddi.c1
-rw-r--r--drivers/video/msm/mddi_client_dummy.c1
-rw-r--r--drivers/video/msm/mddi_client_nt35399.c1
-rw-r--r--drivers/video/msm/mddi_client_toshiba.c1
-rw-r--r--drivers/video/msm/mdp.c1
-rw-r--r--drivers/video/msm/msm_fb.c1
-rw-r--r--drivers/video/mx3fb.c12
-rw-r--r--drivers/video/nuc900fb.c779
-rw-r--r--drivers/video/nuc900fb.h55
-rw-r--r--drivers/video/nvidia/nv_backlight.c7
-rw-r--r--drivers/video/nvidia/nv_i2c.c1
-rw-r--r--drivers/video/nvidia/nv_of.c1
-rw-r--r--drivers/video/nvidia/nv_setup.c1
-rw-r--r--drivers/video/offb.c16
-rw-r--r--drivers/video/omap/Kconfig5
-rw-r--r--drivers/video/omap/Makefile1
-rw-r--r--drivers/video/omap/blizzard.c6
-rw-r--r--drivers/video/omap/dispc.c34
-rw-r--r--drivers/video/omap/hwa742.c7
-rw-r--r--drivers/video/omap/lcd_2430sdp.c9
-rw-r--r--drivers/video/omap/lcd_ams_delta.c102
-rw-r--r--drivers/video/omap/lcd_apollon.c5
-rw-r--r--drivers/video/omap/lcd_h3.c2
-rw-r--r--drivers/video/omap/lcd_h4.c2
-rw-r--r--drivers/video/omap/lcd_htcherald.c130
-rw-r--r--drivers/video/omap/lcd_inn1510.c4
-rw-r--r--drivers/video/omap/lcd_inn1610.c2
-rw-r--r--drivers/video/omap/lcd_ldp.c9
-rw-r--r--drivers/video/omap/lcd_mipid.c10
-rw-r--r--drivers/video/omap/lcd_omap2evm.c15
-rw-r--r--drivers/video/omap/lcd_omap3beagle.c8
-rw-r--r--drivers/video/omap/lcd_omap3evm.c15
-rw-r--r--drivers/video/omap/lcd_osk.c4
-rw-r--r--drivers/video/omap/lcd_overo.c7
-rw-r--r--drivers/video/omap/lcd_palmte.c4
-rw-r--r--drivers/video/omap/lcd_palmtt.c2
-rw-r--r--drivers/video/omap/lcd_palmz71.c2
-rw-r--r--drivers/video/omap/lcdc.c41
-rw-r--r--drivers/video/omap/omapfb.h229
-rw-r--r--drivers/video/omap/omapfb_main.c37
-rw-r--r--drivers/video/omap/rfbi.c7
-rw-r--r--drivers/video/omap/sossi.c5
-rw-r--r--drivers/video/omap2/Kconfig9
-rw-r--r--drivers/video/omap2/Makefile6
-rw-r--r--drivers/video/omap2/displays/Kconfig40
-rw-r--r--drivers/video/omap2/displays/Makefile7
-rw-r--r--drivers/video/omap2/displays/panel-generic.c168
-rw-r--r--drivers/video/omap2/displays/panel-sharp-lq043t1dg01.c159
-rw-r--r--drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c148
-rw-r--r--drivers/video/omap2/displays/panel-taal.c1166
-rw-r--r--drivers/video/omap2/displays/panel-toppoly-tdo35s.c154
-rw-r--r--drivers/video/omap2/displays/panel-tpo-td043mtea1.c529
-rw-r--r--drivers/video/omap2/dss/Kconfig114
-rw-r--r--drivers/video/omap2/dss/Makefile6
-rw-r--r--drivers/video/omap2/dss/core.c976
-rw-r--r--drivers/video/omap2/dss/dispc.c3181
-rw-r--r--drivers/video/omap2/dss/display.c626
-rw-r--r--drivers/video/omap2/dss/dpi.c321
-rw-r--r--drivers/video/omap2/dss/dsi.c3340
-rw-r--r--drivers/video/omap2/dss/dss.c621
-rw-r--r--drivers/video/omap2/dss/dss.h395
-rw-r--r--drivers/video/omap2/dss/manager.c1520
-rw-r--r--drivers/video/omap2/dss/overlay.c681
-rw-r--r--drivers/video/omap2/dss/rfbi.c1056
-rw-r--r--drivers/video/omap2/dss/sdi.c176
-rw-r--r--drivers/video/omap2/dss/venc.c755
-rw-r--r--drivers/video/omap2/omapfb/Kconfig28
-rw-r--r--drivers/video/omap2/omapfb/Makefile2
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c785
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c2287
-rw-r--r--drivers/video/omap2/omapfb/omapfb-sysfs.c507
-rw-r--r--drivers/video/omap2/omapfb/omapfb.h155
-rw-r--r--drivers/video/omap2/vram.c657
-rw-r--r--drivers/video/omap2/vrfb.c315
-rw-r--r--drivers/video/output.c3
-rw-r--r--drivers/video/p9100.c1
-rw-r--r--drivers/video/platinumfb.c1
-rw-r--r--drivers/video/pm2fb.c2
-rw-r--r--drivers/video/pmag-aa-fb.c1
-rw-r--r--drivers/video/pmag-ba-fb.c3
-rw-r--r--drivers/video/pmagb-b-fb.c3
-rw-r--r--drivers/video/pnx4008/pnxrgbfb.c1
-rw-r--r--drivers/video/pnx4008/sdum.c2
-rw-r--r--drivers/video/pvr2fb.c2
-rw-r--r--drivers/video/pxa168fb.c3
-rw-r--r--drivers/video/pxafb.c28
-rw-r--r--drivers/video/q40fb.c3
-rw-r--r--drivers/video/riva/fbdev.c7
-rw-r--r--drivers/video/s1d13xxxfb.c5
-rw-r--r--drivers/video/s3c-fb.c16
-rw-r--r--drivers/video/s3c2410fb.c4
-rw-r--r--drivers/video/s3fb.c1
-rw-r--r--drivers/video/sa1100fb.c2
-rw-r--r--drivers/video/savage/savagefb-i2c.c1
-rw-r--r--drivers/video/sgivwfb.c6
-rw-r--r--drivers/video/sh7760fb.c1
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c160
-rw-r--r--drivers/video/sis/sis_main.c5
-rw-r--r--drivers/video/sm501fb.c251
-rw-r--r--drivers/video/sstfb.c3
-rw-r--r--drivers/video/stifb.c4
-rw-r--r--drivers/video/sunxvr1000.c227
-rw-r--r--drivers/video/sunxvr2500.c1
-rw-r--r--drivers/video/sunxvr500.c26
-rw-r--r--drivers/video/svgalib.c1
-rw-r--r--drivers/video/syscopyarea.c1
-rw-r--r--drivers/video/tcx.c1
-rw-r--r--drivers/video/tdfxfb.c2
-rw-r--r--drivers/video/tgafb.c1
-rw-r--r--drivers/video/tridentfb.c1
-rw-r--r--drivers/video/uvesafb.c1
-rw-r--r--drivers/video/valkyriefb.c6
-rw-r--r--drivers/video/valkyriefb.h31
-rw-r--r--drivers/video/vermilion/vermilion.c1
-rw-r--r--drivers/video/vesafb.c25
-rw-r--r--drivers/video/vfb.c3
-rw-r--r--drivers/video/vga16fb.c3
-rw-r--r--drivers/video/via/Makefile2
-rw-r--r--drivers/video/via/accel.c5
-rw-r--r--drivers/video/via/chip.h11
-rw-r--r--drivers/video/via/dvi.c233
-rw-r--r--drivers/video/via/dvi.h7
-rw-r--r--drivers/video/via/global.c5
-rw-r--r--drivers/video/via/global.h3
-rw-r--r--drivers/video/via/hw.c330
-rw-r--r--drivers/video/via/hw.h17
-rw-r--r--drivers/video/via/iface.c78
-rw-r--r--drivers/video/via/iface.h38
-rw-r--r--drivers/video/via/lcd.c680
-rw-r--r--drivers/video/via/share.h56
-rw-r--r--drivers/video/via/via_utility.c12
-rw-r--r--drivers/video/via/via_utility.h1
-rw-r--r--drivers/video/via/viafbdev.c530
-rw-r--r--drivers/video/via/viafbdev.h6
-rw-r--r--drivers/video/via/viamode.c180
-rw-r--r--drivers/video/via/viamode.h8
-rw-r--r--drivers/video/vt8623fb.c3
-rw-r--r--drivers/video/w100fb.c3
-rw-r--r--drivers/video/xen-fbfront.c6
-rw-r--r--drivers/video/xilinxfb.c1
266 files changed, 27720 insertions, 2887 deletions
diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c
index 0b17824b0eb5..75a39eab70c3 100644
--- a/drivers/video/68328fb.c
+++ b/drivers/video/68328fb.c
@@ -32,7 +32,6 @@
32#include <linux/errno.h> 32#include <linux/errno.h>
33#include <linux/string.h> 33#include <linux/string.h>
34#include <linux/mm.h> 34#include <linux/mm.h>
35#include <linux/slab.h>
36#include <linux/vmalloc.h> 35#include <linux/vmalloc.h>
37#include <linux/delay.h> 36#include <linux/delay.h>
38#include <linux/interrupt.h> 37#include <linux/interrupt.h>
@@ -308,7 +307,7 @@ static int mc68x328fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
308 * Pseudocolor: 307 * Pseudocolor:
309 * uses offset = 0 && length = RAMDAC register width. 308 * uses offset = 0 && length = RAMDAC register width.
310 * var->{color}.offset is 0 309 * var->{color}.offset is 0
311 * var->{color}.length contains widht of DAC 310 * var->{color}.length contains width of DAC
312 * cmap is not used 311 * cmap is not used
313 * RAMDAC[X] is programmed to (red, green, blue) 312 * RAMDAC[X] is programmed to (red, green, blue)
314 * Truecolor: 313 * Truecolor:
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 188e1ba3b69f..6e16244f3ed1 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -5,6 +5,9 @@
5menu "Graphics support" 5menu "Graphics support"
6 depends on HAS_IOMEM 6 depends on HAS_IOMEM
7 7
8config HAVE_FB_ATMEL
9 bool
10
8source "drivers/char/agp/Kconfig" 11source "drivers/char/agp/Kconfig"
9 12
10source "drivers/gpu/vga/Kconfig" 13source "drivers/gpu/vga/Kconfig"
@@ -397,9 +400,12 @@ config FB_SA1100
397 If you plan to use the LCD display with your SA-1100 system, say 400 If you plan to use the LCD display with your SA-1100 system, say
398 Y here. 401 Y here.
399 402
403config HAVE_FB_IMX
404 bool
405
400config FB_IMX 406config FB_IMX
401 tristate "Motorola i.MX LCD support" 407 tristate "Motorola i.MX LCD support"
402 depends on FB && (ARCH_MX1 || ARCH_MX2) 408 depends on FB && (HAVE_FB_IMX || ARCH_MX1 || ARCH_MX2)
403 select FB_CFB_FILLRECT 409 select FB_CFB_FILLRECT
404 select FB_CFB_COPYAREA 410 select FB_CFB_COPYAREA
405 select FB_CFB_IMAGEBLIT 411 select FB_CFB_IMAGEBLIT
@@ -611,6 +617,21 @@ config FB_BFIN_T350MCQB
611 This display is a QVGA 320x240 24-bit RGB display interfaced by an 8-bit wide PPI 617 This display is a QVGA 320x240 24-bit RGB display interfaced by an 8-bit wide PPI
612 It uses PPI[0..7] PPI_FS1, PPI_FS2 and PPI_CLK. 618 It uses PPI[0..7] PPI_FS1, PPI_FS2 and PPI_CLK.
613 619
620config FB_BFIN_LQ035Q1
621 tristate "SHARP LQ035Q1DH02 TFT LCD"
622 depends on FB && BLACKFIN && SPI
623 select FB_CFB_FILLRECT
624 select FB_CFB_COPYAREA
625 select FB_CFB_IMAGEBLIT
626 select BFIN_GPTIMERS
627 help
628 This is the framebuffer device driver for a SHARP LQ035Q1DH02 TFT display found on
629 the Blackfin Landscape LCD EZ-Extender Card.
630 This display is a QVGA 320x240 18-bit RGB display interfaced by an 16-bit wide PPI
631 It uses PPI[0..15] PPI_FS1, PPI_FS2 and PPI_CLK.
632
633 To compile this driver as a module, choose M here: the
634 module will be called bfin-lq035q1-fb.
614 635
615config FB_STI 636config FB_STI
616 tristate "HP STI frame buffer device support" 637 tristate "HP STI frame buffer device support"
@@ -891,6 +912,18 @@ config FB_XVR2500
891 mostly initialized the card already. It is treated as a 912 mostly initialized the card already. It is treated as a
892 completely dumb framebuffer device. 913 completely dumb framebuffer device.
893 914
915config FB_XVR1000
916 bool "Sun XVR-1000 support"
917 depends on (FB = y) && SPARC64
918 select FB_CFB_FILLRECT
919 select FB_CFB_COPYAREA
920 select FB_CFB_IMAGEBLIT
921 help
922 This is the framebuffer device for the Sun XVR-1000 and similar
923 graphics cards. The driver only works on sparc64 systems where
924 the system firmware has mostly initialized the card already. It
925 is treated as a completely dumb framebuffer device.
926
894config FB_PVR2 927config FB_PVR2
895 tristate "NEC PowerVR 2 display support" 928 tristate "NEC PowerVR 2 display support"
896 depends on FB && SH_DREAMCAST 929 depends on FB && SH_DREAMCAST
@@ -937,7 +970,7 @@ config FB_S1D13XXX
937 970
938config FB_ATMEL 971config FB_ATMEL
939 tristate "AT91/AT32 LCD Controller support" 972 tristate "AT91/AT32 LCD Controller support"
940 depends on FB && (ARCH_AT91SAM9261 || ARCH_AT91SAM9G10 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91SAM9G45 || ARCH_AT91CAP9 || AVR32) 973 depends on FB && HAVE_FB_ATMEL
941 select FB_CFB_FILLRECT 974 select FB_CFB_FILLRECT
942 select FB_CFB_COPYAREA 975 select FB_CFB_COPYAREA
943 select FB_CFB_IMAGEBLIT 976 select FB_CFB_IMAGEBLIT
@@ -1476,7 +1509,6 @@ config FB_VIA
1476 select FB_CFB_FILLRECT 1509 select FB_CFB_FILLRECT
1477 select FB_CFB_COPYAREA 1510 select FB_CFB_COPYAREA
1478 select FB_CFB_IMAGEBLIT 1511 select FB_CFB_IMAGEBLIT
1479 select FB_SOFT_CURSOR
1480 select I2C_ALGOBIT 1512 select I2C_ALGOBIT
1481 select I2C 1513 select I2C
1482 help 1514 help
@@ -1849,7 +1881,7 @@ config FB_W100
1849 1881
1850config FB_SH_MOBILE_LCDC 1882config FB_SH_MOBILE_LCDC
1851 tristate "SuperH Mobile LCDC framebuffer support" 1883 tristate "SuperH Mobile LCDC framebuffer support"
1852 depends on FB && SUPERH && HAVE_CLK 1884 depends on FB && (SUPERH || ARCH_SHMOBILE) && HAVE_CLK
1853 select FB_SYS_FILLRECT 1885 select FB_SYS_FILLRECT
1854 select FB_SYS_COPYAREA 1886 select FB_SYS_COPYAREA
1855 select FB_SYS_IMAGEBLIT 1887 select FB_SYS_IMAGEBLIT
@@ -1927,6 +1959,27 @@ config FB_S3C2410_DEBUG
1927 Turn on debugging messages. Note that you can set/unset at run time 1959 Turn on debugging messages. Note that you can set/unset at run time
1928 through sysfs 1960 through sysfs
1929 1961
1962config FB_NUC900
1963 bool "NUC900 LCD framebuffer support"
1964 depends on FB && ARCH_W90X900
1965 select FB_CFB_FILLRECT
1966 select FB_CFB_COPYAREA
1967 select FB_CFB_IMAGEBLIT
1968 ---help---
1969 Frame buffer driver for the built-in LCD controller in the Nuvoton
1970 NUC900 processor
1971
1972config GPM1040A0_320X240
1973 bool "Giantplus Technology GPM1040A0 320x240 Color TFT LCD"
1974 depends on FB_NUC900
1975
1976config FB_NUC900_DEBUG
1977 bool "NUC900 lcd debug messages"
1978 depends on FB_NUC900
1979 help
1980 Turn on debugging messages. Note that you can set/unset at run time
1981 through sysfs
1982
1930config FB_SM501 1983config FB_SM501
1931 tristate "Silicon Motion SM501 framebuffer support" 1984 tristate "Silicon Motion SM501 framebuffer support"
1932 depends on FB && MFD_SM501 1985 depends on FB && MFD_SM501
@@ -2063,6 +2116,7 @@ config XEN_FBDEV_FRONTEND
2063 select FB_SYS_IMAGEBLIT 2116 select FB_SYS_IMAGEBLIT
2064 select FB_SYS_FOPS 2117 select FB_SYS_FOPS
2065 select FB_DEFERRED_IO 2118 select FB_DEFERRED_IO
2119 select XEN_XENBUS_FRONTEND
2066 default y 2120 default y
2067 help 2121 help
2068 This driver implements the front-end of the Xen virtual 2122 This driver implements the front-end of the Xen virtual
@@ -2127,7 +2181,7 @@ config FB_PRE_INIT_FB
2127 the bootloader. 2181 the bootloader.
2128 2182
2129config FB_MSM 2183config FB_MSM
2130 tristate 2184 tristate "MSM Framebuffer support"
2131 depends on FB && ARCH_MSM 2185 depends on FB && ARCH_MSM
2132 select FB_CFB_FILLRECT 2186 select FB_CFB_FILLRECT
2133 select FB_CFB_COPYAREA 2187 select FB_CFB_COPYAREA
@@ -2161,6 +2215,7 @@ config FB_BROADSHEET
2161 a bridge adapter. 2215 a bridge adapter.
2162 2216
2163source "drivers/video/omap/Kconfig" 2217source "drivers/video/omap/Kconfig"
2218source "drivers/video/omap2/Kconfig"
2164 2219
2165source "drivers/video/backlight/Kconfig" 2220source "drivers/video/backlight/Kconfig"
2166source "drivers/video/display/Kconfig" 2221source "drivers/video/display/Kconfig"
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 80232e124889..ddc2af2ba45b 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -79,6 +79,7 @@ obj-$(CONFIG_FB_N411) += n411.o
79obj-$(CONFIG_FB_HGA) += hgafb.o 79obj-$(CONFIG_FB_HGA) += hgafb.o
80obj-$(CONFIG_FB_XVR500) += sunxvr500.o 80obj-$(CONFIG_FB_XVR500) += sunxvr500.o
81obj-$(CONFIG_FB_XVR2500) += sunxvr2500.o 81obj-$(CONFIG_FB_XVR2500) += sunxvr2500.o
82obj-$(CONFIG_FB_XVR1000) += sunxvr1000.o
82obj-$(CONFIG_FB_IGA) += igafb.o 83obj-$(CONFIG_FB_IGA) += igafb.o
83obj-$(CONFIG_FB_APOLLO) += dnfb.o 84obj-$(CONFIG_FB_APOLLO) += dnfb.o
84obj-$(CONFIG_FB_Q40) += q40fb.o 85obj-$(CONFIG_FB_Q40) += q40fb.o
@@ -124,10 +125,12 @@ obj-$(CONFIG_FB_SM501) += sm501fb.o
124obj-$(CONFIG_FB_XILINX) += xilinxfb.o 125obj-$(CONFIG_FB_XILINX) += xilinxfb.o
125obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o 126obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o
126obj-$(CONFIG_FB_OMAP) += omap/ 127obj-$(CONFIG_FB_OMAP) += omap/
128obj-y += omap2/
127obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o 129obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o
128obj-$(CONFIG_FB_CARMINE) += carminefb.o 130obj-$(CONFIG_FB_CARMINE) += carminefb.o
129obj-$(CONFIG_FB_MB862XX) += mb862xx/ 131obj-$(CONFIG_FB_MB862XX) += mb862xx/
130obj-$(CONFIG_FB_MSM) += msm/ 132obj-$(CONFIG_FB_MSM) += msm/
133obj-$(CONFIG_FB_NUC900) += nuc900fb.o
131 134
132# Platform or fallback drivers go here 135# Platform or fallback drivers go here
133obj-$(CONFIG_FB_UVESA) += uvesafb.o 136obj-$(CONFIG_FB_UVESA) += uvesafb.o
@@ -136,6 +139,7 @@ obj-$(CONFIG_FB_EFI) += efifb.o
136obj-$(CONFIG_FB_VGA16) += vga16fb.o 139obj-$(CONFIG_FB_VGA16) += vga16fb.o
137obj-$(CONFIG_FB_OF) += offb.o 140obj-$(CONFIG_FB_OF) += offb.o
138obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o 141obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o
142obj-$(CONFIG_FB_BFIN_LQ035Q1) += bfin-lq035q1-fb.o
139obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o 143obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o
140obj-$(CONFIG_FB_MX3) += mx3fb.o 144obj-$(CONFIG_FB_MX3) += mx3fb.o
141obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o 145obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
index 0bcc59eb37fa..82acb8dc4aa1 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/acornfb.c
@@ -22,13 +22,13 @@
22#include <linux/errno.h> 22#include <linux/errno.h>
23#include <linux/string.h> 23#include <linux/string.h>
24#include <linux/ctype.h> 24#include <linux/ctype.h>
25#include <linux/slab.h>
26#include <linux/mm.h> 25#include <linux/mm.h>
27#include <linux/init.h> 26#include <linux/init.h>
28#include <linux/fb.h> 27#include <linux/fb.h>
29#include <linux/platform_device.h> 28#include <linux/platform_device.h>
30#include <linux/dma-mapping.h> 29#include <linux/dma-mapping.h>
31#include <linux/io.h> 30#include <linux/io.h>
31#include <linux/gfp.h>
32 32
33#include <mach/hardware.h> 33#include <mach/hardware.h>
34#include <asm/irq.h> 34#include <asm/irq.h>
@@ -1221,7 +1221,7 @@ free_unused_pages(unsigned int virtual_start, unsigned int virtual_end)
1221 printk("acornfb: freed %dK memory\n", mb_freed); 1221 printk("acornfb: freed %dK memory\n", mb_freed);
1222} 1222}
1223 1223
1224static int __init acornfb_probe(struct platform_device *dev) 1224static int __devinit acornfb_probe(struct platform_device *dev)
1225{ 1225{
1226 unsigned long size; 1226 unsigned long size;
1227 u_int h_sync, v_sync; 1227 u_int h_sync, v_sync;
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
index a21efcd10b78..afe21e6eb544 100644
--- a/drivers/video/amba-clcd.c
+++ b/drivers/video/amba-clcd.c
@@ -65,16 +65,16 @@ static void clcdfb_disable(struct clcd_fb *fb)
65 if (fb->board->disable) 65 if (fb->board->disable)
66 fb->board->disable(fb); 66 fb->board->disable(fb);
67 67
68 val = readl(fb->regs + CLCD_CNTL); 68 val = readl(fb->regs + fb->off_cntl);
69 if (val & CNTL_LCDPWR) { 69 if (val & CNTL_LCDPWR) {
70 val &= ~CNTL_LCDPWR; 70 val &= ~CNTL_LCDPWR;
71 writel(val, fb->regs + CLCD_CNTL); 71 writel(val, fb->regs + fb->off_cntl);
72 72
73 clcdfb_sleep(20); 73 clcdfb_sleep(20);
74 } 74 }
75 if (val & CNTL_LCDEN) { 75 if (val & CNTL_LCDEN) {
76 val &= ~CNTL_LCDEN; 76 val &= ~CNTL_LCDEN;
77 writel(val, fb->regs + CLCD_CNTL); 77 writel(val, fb->regs + fb->off_cntl);
78 } 78 }
79 79
80 /* 80 /*
@@ -94,7 +94,7 @@ static void clcdfb_enable(struct clcd_fb *fb, u32 cntl)
94 * Bring up by first enabling.. 94 * Bring up by first enabling..
95 */ 95 */
96 cntl |= CNTL_LCDEN; 96 cntl |= CNTL_LCDEN;
97 writel(cntl, fb->regs + CLCD_CNTL); 97 writel(cntl, fb->regs + fb->off_cntl);
98 98
99 clcdfb_sleep(20); 99 clcdfb_sleep(20);
100 100
@@ -102,7 +102,7 @@ static void clcdfb_enable(struct clcd_fb *fb, u32 cntl)
102 * and now apply power. 102 * and now apply power.
103 */ 103 */
104 cntl |= CNTL_LCDPWR; 104 cntl |= CNTL_LCDPWR;
105 writel(cntl, fb->regs + CLCD_CNTL); 105 writel(cntl, fb->regs + fb->off_cntl);
106 106
107 /* 107 /*
108 * finally, enable the interface. 108 * finally, enable the interface.
@@ -233,7 +233,7 @@ static int clcdfb_set_par(struct fb_info *info)
233 readl(fb->regs + CLCD_TIM0), readl(fb->regs + CLCD_TIM1), 233 readl(fb->regs + CLCD_TIM0), readl(fb->regs + CLCD_TIM1),
234 readl(fb->regs + CLCD_TIM2), readl(fb->regs + CLCD_TIM3), 234 readl(fb->regs + CLCD_TIM2), readl(fb->regs + CLCD_TIM3),
235 readl(fb->regs + CLCD_UBAS), readl(fb->regs + CLCD_LBAS), 235 readl(fb->regs + CLCD_UBAS), readl(fb->regs + CLCD_LBAS),
236 readl(fb->regs + CLCD_IENB), readl(fb->regs + CLCD_CNTL)); 236 readl(fb->regs + fb->off_ienb), readl(fb->regs + fb->off_cntl));
237#endif 237#endif
238 238
239 return 0; 239 return 0;
@@ -345,6 +345,23 @@ static int clcdfb_register(struct clcd_fb *fb)
345{ 345{
346 int ret; 346 int ret;
347 347
348 /*
349 * ARM PL111 always has IENB at 0x1c; it's only PL110
350 * which is reversed on some platforms.
351 */
352 if (amba_manf(fb->dev) == 0x41 && amba_part(fb->dev) == 0x111) {
353 fb->off_ienb = CLCD_PL111_IENB;
354 fb->off_cntl = CLCD_PL111_CNTL;
355 } else {
356#ifdef CONFIG_ARCH_VERSATILE
357 fb->off_ienb = CLCD_PL111_IENB;
358 fb->off_cntl = CLCD_PL111_CNTL;
359#else
360 fb->off_ienb = CLCD_PL110_IENB;
361 fb->off_cntl = CLCD_PL110_CNTL;
362#endif
363 }
364
348 fb->clk = clk_get(&fb->dev->dev, NULL); 365 fb->clk = clk_get(&fb->dev->dev, NULL);
349 if (IS_ERR(fb->clk)) { 366 if (IS_ERR(fb->clk)) {
350 ret = PTR_ERR(fb->clk); 367 ret = PTR_ERR(fb->clk);
@@ -416,7 +433,7 @@ static int clcdfb_register(struct clcd_fb *fb)
416 /* 433 /*
417 * Ensure interrupts are disabled. 434 * Ensure interrupts are disabled.
418 */ 435 */
419 writel(0, fb->regs + CLCD_IENB); 436 writel(0, fb->regs + fb->off_ienb);
420 437
421 fb_set_var(&fb->fb, &fb->fb.var); 438 fb_set_var(&fb->fb, &fb->fb.var);
422 439
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index 82bedd7f7789..dca48df98444 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -45,7 +45,6 @@
45#include <linux/errno.h> 45#include <linux/errno.h>
46#include <linux/string.h> 46#include <linux/string.h>
47#include <linux/mm.h> 47#include <linux/mm.h>
48#include <linux/slab.h>
49#include <linux/delay.h> 48#include <linux/delay.h>
50#include <linux/interrupt.h> 49#include <linux/interrupt.h>
51#include <linux/fb.h> 50#include <linux/fb.h>
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c
index c3431691c9f2..8d406fb689c1 100644
--- a/drivers/video/arcfb.c
+++ b/drivers/video/arcfb.c
@@ -39,7 +39,6 @@
39#include <linux/errno.h> 39#include <linux/errno.h>
40#include <linux/string.h> 40#include <linux/string.h>
41#include <linux/mm.h> 41#include <linux/mm.h>
42#include <linux/slab.h>
43#include <linux/vmalloc.h> 42#include <linux/vmalloc.h>
44#include <linux/delay.h> 43#include <linux/delay.h>
45#include <linux/interrupt.h> 44#include <linux/interrupt.h>
@@ -504,7 +503,7 @@ static struct fb_ops arcfb_ops = {
504 .fb_ioctl = arcfb_ioctl, 503 .fb_ioctl = arcfb_ioctl,
505}; 504};
506 505
507static int __init arcfb_probe(struct platform_device *dev) 506static int __devinit arcfb_probe(struct platform_device *dev)
508{ 507{
509 struct fb_info *info; 508 struct fb_info *info;
510 int retval = -ENOMEM; 509 int retval = -ENOMEM;
diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c
index 9fe90ce928fb..8cdf88e20b4b 100644
--- a/drivers/video/asiliantfb.c
+++ b/drivers/video/asiliantfb.c
@@ -34,7 +34,6 @@
34#include <linux/errno.h> 34#include <linux/errno.h>
35#include <linux/string.h> 35#include <linux/string.h>
36#include <linux/mm.h> 36#include <linux/mm.h>
37#include <linux/slab.h>
38#include <linux/vmalloc.h> 37#include <linux/vmalloc.h>
39#include <linux/delay.h> 38#include <linux/delay.h>
40#include <linux/interrupt.h> 39#include <linux/interrupt.h>
@@ -140,7 +139,7 @@ static void asiliant_calc_dclk2(u32 *ppixclock, u8 *dclk2_m, u8 *dclk2_n, u8 *dc
140 139
141 /* 3 <= m <= 257 */ 140 /* 3 <= m <= 257 */
142 if (m >= 3 && m <= 257) { 141 if (m >= 3 && m <= 257) {
143 unsigned new_error = ((Ftarget * n) - (Fref * m)) >= 0 ? 142 unsigned new_error = Ftarget * n >= Fref * m ?
144 ((Ftarget * n) - (Fref * m)) : ((Fref * m) - (Ftarget * n)); 143 ((Ftarget * n) - (Fref * m)) : ((Fref * m) - (Ftarget * n));
145 if (new_error < best_error) { 144 if (new_error < best_error) {
146 best_n = n; 145 best_n = n;
@@ -152,7 +151,7 @@ static void asiliant_calc_dclk2(u32 *ppixclock, u8 *dclk2_m, u8 *dclk2_n, u8 *dc
152 else if (m <= 1028) { 151 else if (m <= 1028) {
153 /* remember there are still only 8-bits of precision in m, so 152 /* remember there are still only 8-bits of precision in m, so
154 * avoid over-optimistic error calculations */ 153 * avoid over-optimistic error calculations */
155 unsigned new_error = ((Ftarget * n) - (Fref * (m & ~3))) >= 0 ? 154 unsigned new_error = Ftarget * n >= Fref * (m & ~3) ?
156 ((Ftarget * n) - (Fref * (m & ~3))) : ((Fref * (m & ~3)) - (Ftarget * n)); 155 ((Ftarget * n) - (Fref * (m & ~3))) : ((Fref * (m & ~3)) - (Ftarget * n));
157 if (new_error < best_error) { 156 if (new_error < best_error) {
158 best_n = n; 157 best_n = n;
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index 37624f74e88b..f3aada20fa02 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -52,7 +52,6 @@
52#include <linux/errno.h> 52#include <linux/errno.h>
53#include <linux/string.h> 53#include <linux/string.h>
54#include <linux/mm.h> 54#include <linux/mm.h>
55#include <linux/slab.h>
56#include <linux/delay.h> 55#include <linux/delay.h>
57#include <linux/init.h> 56#include <linux/init.h>
58#include <linux/interrupt.h> 57#include <linux/interrupt.h>
@@ -2242,6 +2241,9 @@ static int ext_setcolreg(unsigned int regno, unsigned int red,
2242 if (!external_vgaiobase) 2241 if (!external_vgaiobase)
2243 return 1; 2242 return 1;
2244 2243
2244 if (regno > 255)
2245 return 1;
2246
2245 switch (external_card_type) { 2247 switch (external_card_type) {
2246 case IS_VGA: 2248 case IS_VGA:
2247 OUTB(0x3c8, regno); 2249 OUTB(0x3c8, regno);
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index d5e801076d33..8dce25126330 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -17,6 +17,7 @@
17#include <linux/init.h> 17#include <linux/init.h>
18#include <linux/delay.h> 18#include <linux/delay.h>
19#include <linux/backlight.h> 19#include <linux/backlight.h>
20#include <linux/gfp.h>
20 21
21#include <mach/board.h> 22#include <mach/board.h>
22#include <mach/cpu.h> 23#include <mach/cpu.h>
@@ -117,6 +118,7 @@ static struct backlight_ops atmel_lcdc_bl_ops = {
117 118
118static void init_backlight(struct atmel_lcdfb_info *sinfo) 119static void init_backlight(struct atmel_lcdfb_info *sinfo)
119{ 120{
121 struct backlight_properties props;
120 struct backlight_device *bl; 122 struct backlight_device *bl;
121 123
122 sinfo->bl_power = FB_BLANK_UNBLANK; 124 sinfo->bl_power = FB_BLANK_UNBLANK;
@@ -124,8 +126,10 @@ static void init_backlight(struct atmel_lcdfb_info *sinfo)
124 if (sinfo->backlight) 126 if (sinfo->backlight)
125 return; 127 return;
126 128
127 bl = backlight_device_register("backlight", &sinfo->pdev->dev, 129 memset(&props, 0, sizeof(struct backlight_properties));
128 sinfo, &atmel_lcdc_bl_ops); 130 props.max_brightness = 0xff;
131 bl = backlight_device_register("backlight", &sinfo->pdev->dev, sinfo,
132 &atmel_lcdc_bl_ops, &props);
129 if (IS_ERR(bl)) { 133 if (IS_ERR(bl)) {
130 dev_err(&sinfo->pdev->dev, "error %ld on backlight register\n", 134 dev_err(&sinfo->pdev->dev, "error %ld on backlight register\n",
131 PTR_ERR(bl)); 135 PTR_ERR(bl));
@@ -135,7 +139,6 @@ static void init_backlight(struct atmel_lcdfb_info *sinfo)
135 139
136 bl->props.power = FB_BLANK_UNBLANK; 140 bl->props.power = FB_BLANK_UNBLANK;
137 bl->props.fb_blank = FB_BLANK_UNBLANK; 141 bl->props.fb_blank = FB_BLANK_UNBLANK;
138 bl->props.max_brightness = 0xff;
139 bl->props.brightness = atmel_bl_get_brightness(bl); 142 bl->props.brightness = atmel_bl_get_brightness(bl);
140} 143}
141 144
@@ -964,7 +967,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
964 if (sinfo->atmel_lcdfb_power_control) 967 if (sinfo->atmel_lcdfb_power_control)
965 sinfo->atmel_lcdfb_power_control(1); 968 sinfo->atmel_lcdfb_power_control(1);
966 969
967 dev_info(dev, "fb%d: Atmel LCDC at 0x%08lx (mapped at %p), irq %lu\n", 970 dev_info(dev, "fb%d: Atmel LCDC at 0x%08lx (mapped at %p), irq %d\n",
968 info->node, info->fix.mmio_start, sinfo->mmio, sinfo->irq_base); 971 info->node, info->fix.mmio_start, sinfo->mmio, sinfo->irq_base);
969 972
970 return 0; 973 return 0;
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index e4e4d433b007..34a0851bcbfa 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -52,7 +52,6 @@
52#include <linux/errno.h> 52#include <linux/errno.h>
53#include <linux/string.h> 53#include <linux/string.h>
54#include <linux/mm.h> 54#include <linux/mm.h>
55#include <linux/slab.h>
56#include <linux/vmalloc.h> 55#include <linux/vmalloc.h>
57#include <linux/delay.h> 56#include <linux/delay.h>
58#include <linux/interrupt.h> 57#include <linux/interrupt.h>
@@ -1802,6 +1801,7 @@ static void aty128_bl_set_power(struct fb_info *info, int power)
1802 1801
1803static void aty128_bl_init(struct aty128fb_par *par) 1802static void aty128_bl_init(struct aty128fb_par *par)
1804{ 1803{
1804 struct backlight_properties props;
1805 struct fb_info *info = pci_get_drvdata(par->pdev); 1805 struct fb_info *info = pci_get_drvdata(par->pdev);
1806 struct backlight_device *bd; 1806 struct backlight_device *bd;
1807 char name[12]; 1807 char name[12];
@@ -1817,7 +1817,10 @@ static void aty128_bl_init(struct aty128fb_par *par)
1817 1817
1818 snprintf(name, sizeof(name), "aty128bl%d", info->node); 1818 snprintf(name, sizeof(name), "aty128bl%d", info->node);
1819 1819
1820 bd = backlight_device_register(name, info->dev, par, &aty128_bl_data); 1820 memset(&props, 0, sizeof(struct backlight_properties));
1821 props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
1822 bd = backlight_device_register(name, info->dev, par, &aty128_bl_data,
1823 &props);
1821 if (IS_ERR(bd)) { 1824 if (IS_ERR(bd)) {
1822 info->bl_dev = NULL; 1825 info->bl_dev = NULL;
1823 printk(KERN_WARNING "aty128: Backlight registration failed\n"); 1826 printk(KERN_WARNING "aty128: Backlight registration failed\n");
@@ -1829,7 +1832,6 @@ static void aty128_bl_init(struct aty128fb_par *par)
1829 63 * FB_BACKLIGHT_MAX / MAX_LEVEL, 1832 63 * FB_BACKLIGHT_MAX / MAX_LEVEL,
1830 219 * FB_BACKLIGHT_MAX / MAX_LEVEL); 1833 219 * FB_BACKLIGHT_MAX / MAX_LEVEL);
1831 1834
1832 bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
1833 bd->props.brightness = bd->props.max_brightness; 1835 bd->props.brightness = bd->props.max_brightness;
1834 bd->props.power = FB_BLANK_UNBLANK; 1836 bd->props.power = FB_BLANK_UNBLANK;
1835 backlight_update_status(bd); 1837 backlight_update_status(bd);
@@ -1931,22 +1933,22 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i
1931 * PowerMac2,2 summer 2000 iMacs 1933 * PowerMac2,2 summer 2000 iMacs
1932 * PowerMac4,1 january 2001 iMacs "flower power" 1934 * PowerMac4,1 january 2001 iMacs "flower power"
1933 */ 1935 */
1934 if (machine_is_compatible("PowerMac2,1") || 1936 if (of_machine_is_compatible("PowerMac2,1") ||
1935 machine_is_compatible("PowerMac2,2") || 1937 of_machine_is_compatible("PowerMac2,2") ||
1936 machine_is_compatible("PowerMac4,1")) 1938 of_machine_is_compatible("PowerMac4,1"))
1937 default_vmode = VMODE_1024_768_75; 1939 default_vmode = VMODE_1024_768_75;
1938 1940
1939 /* iBook SE */ 1941 /* iBook SE */
1940 if (machine_is_compatible("PowerBook2,2")) 1942 if (of_machine_is_compatible("PowerBook2,2"))
1941 default_vmode = VMODE_800_600_60; 1943 default_vmode = VMODE_800_600_60;
1942 1944
1943 /* PowerBook Firewire (Pismo), iBook Dual USB */ 1945 /* PowerBook Firewire (Pismo), iBook Dual USB */
1944 if (machine_is_compatible("PowerBook3,1") || 1946 if (of_machine_is_compatible("PowerBook3,1") ||
1945 machine_is_compatible("PowerBook4,1")) 1947 of_machine_is_compatible("PowerBook4,1"))
1946 default_vmode = VMODE_1024_768_60; 1948 default_vmode = VMODE_1024_768_60;
1947 1949
1948 /* PowerBook Titanium */ 1950 /* PowerBook Titanium */
1949 if (machine_is_compatible("PowerBook3,2")) 1951 if (of_machine_is_compatible("PowerBook3,2"))
1950 default_vmode = VMODE_1152_768_60; 1952 default_vmode = VMODE_1152_768_60;
1951 1953
1952 if (default_cmode > 16) 1954 if (default_cmode > 16)
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 913b4a47ae52..29d72851f85b 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -2232,6 +2232,7 @@ static struct backlight_ops aty_bl_data = {
2232 2232
2233static void aty_bl_init(struct atyfb_par *par) 2233static void aty_bl_init(struct atyfb_par *par)
2234{ 2234{
2235 struct backlight_properties props;
2235 struct fb_info *info = pci_get_drvdata(par->pdev); 2236 struct fb_info *info = pci_get_drvdata(par->pdev);
2236 struct backlight_device *bd; 2237 struct backlight_device *bd;
2237 char name[12]; 2238 char name[12];
@@ -2243,7 +2244,10 @@ static void aty_bl_init(struct atyfb_par *par)
2243 2244
2244 snprintf(name, sizeof(name), "atybl%d", info->node); 2245 snprintf(name, sizeof(name), "atybl%d", info->node);
2245 2246
2246 bd = backlight_device_register(name, info->dev, par, &aty_bl_data); 2247 memset(&props, 0, sizeof(struct backlight_properties));
2248 props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
2249 bd = backlight_device_register(name, info->dev, par, &aty_bl_data,
2250 &props);
2247 if (IS_ERR(bd)) { 2251 if (IS_ERR(bd)) {
2248 info->bl_dev = NULL; 2252 info->bl_dev = NULL;
2249 printk(KERN_WARNING "aty: Backlight registration failed\n"); 2253 printk(KERN_WARNING "aty: Backlight registration failed\n");
@@ -2255,7 +2259,6 @@ static void aty_bl_init(struct atyfb_par *par)
2255 0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL, 2259 0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL,
2256 0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL); 2260 0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL);
2257 2261
2258 bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
2259 bd->props.brightness = bd->props.max_brightness; 2262 bd->props.brightness = bd->props.max_brightness;
2260 bd->props.power = FB_BLANK_UNBLANK; 2263 bd->props.power = FB_BLANK_UNBLANK;
2261 backlight_update_status(bd); 2264 backlight_update_status(bd);
@@ -2439,7 +2442,7 @@ static int __devinit aty_init(struct fb_info *info)
2439 * The Apple iBook1 uses non-standard memory frequencies. 2442 * The Apple iBook1 uses non-standard memory frequencies.
2440 * We detect it and set the frequency manually. 2443 * We detect it and set the frequency manually.
2441 */ 2444 */
2442 if (machine_is_compatible("PowerBook2,1")) { 2445 if (of_machine_is_compatible("PowerBook2,1")) {
2443 par->pll_limits.mclk = 70; 2446 par->pll_limits.mclk = 70;
2444 par->pll_limits.xclk = 53; 2447 par->pll_limits.xclk = 53;
2445 } 2448 }
@@ -2659,7 +2662,7 @@ static int __devinit aty_init(struct fb_info *info)
2659 FBINFO_HWACCEL_YPAN; 2662 FBINFO_HWACCEL_YPAN;
2660 2663
2661#ifdef CONFIG_PMAC_BACKLIGHT 2664#ifdef CONFIG_PMAC_BACKLIGHT
2662 if (M64_HAS(G3_PB_1_1) && machine_is_compatible("PowerBook1,1")) { 2665 if (M64_HAS(G3_PB_1_1) && of_machine_is_compatible("PowerBook1,1")) {
2663 /* 2666 /*
2664 * these bits let the 101 powerbook 2667 * these bits let the 101 powerbook
2665 * wake up from sleep -- paulus 2668 * wake up from sleep -- paulus
@@ -2690,9 +2693,9 @@ static int __devinit aty_init(struct fb_info *info)
2690 if (M64_HAS(G3_PB_1024x768)) 2693 if (M64_HAS(G3_PB_1024x768))
2691 /* G3 PowerBook with 1024x768 LCD */ 2694 /* G3 PowerBook with 1024x768 LCD */
2692 default_vmode = VMODE_1024_768_60; 2695 default_vmode = VMODE_1024_768_60;
2693 else if (machine_is_compatible("iMac")) 2696 else if (of_machine_is_compatible("iMac"))
2694 default_vmode = VMODE_1024_768_75; 2697 default_vmode = VMODE_1024_768_75;
2695 else if (machine_is_compatible("PowerBook2,1")) 2698 else if (of_machine_is_compatible("PowerBook2,1"))
2696 /* iBook with 800x600 LCD */ 2699 /* iBook with 800x600 LCD */
2697 default_vmode = VMODE_800_600_60; 2700 default_vmode = VMODE_800_600_60;
2698 else 2701 else
@@ -3104,7 +3107,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
3104 } 3107 }
3105 3108
3106 dp = pci_device_to_OF_node(pdev); 3109 dp = pci_device_to_OF_node(pdev);
3107 if (node == dp->node) { 3110 if (node == dp->phandle) {
3108 struct fb_var_screeninfo *var = &default_var; 3111 struct fb_var_screeninfo *var = &default_var;
3109 unsigned int N, P, Q, M, T, R; 3112 unsigned int N, P, Q, M, T, R;
3110 u32 v_total, h_total; 3113 u32 v_total, h_total;
@@ -3276,7 +3279,7 @@ static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base)
3276 txtformat = "24 bit interface"; 3279 txtformat = "24 bit interface";
3277 break; 3280 break;
3278 default: 3281 default:
3279 txtformat = "unkown format"; 3282 txtformat = "unknown format";
3280 } 3283 }
3281 } else { 3284 } else {
3282 switch (format & 7) { 3285 switch (format & 7) {
@@ -3299,7 +3302,7 @@ static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base)
3299 txtformat = "262144 colours (FDPI-2 mode)"; 3302 txtformat = "262144 colours (FDPI-2 mode)";
3300 break; 3303 break;
3301 default: 3304 default:
3302 txtformat = "unkown format"; 3305 txtformat = "unknown format";
3303 } 3306 }
3304 } 3307 }
3305 PRINTKI("%s%s %s monitor detected: %s\n", 3308 PRINTKI("%s%s %s monitor detected: %s\n",
diff --git a/drivers/video/aty/mach64_cursor.c b/drivers/video/aty/mach64_cursor.c
index 04c710804bb0..2ba8b3c421a1 100644
--- a/drivers/video/aty/mach64_cursor.c
+++ b/drivers/video/aty/mach64_cursor.c
@@ -2,7 +2,6 @@
2 * ATI Mach64 CT/VT/GT/LT Cursor Support 2 * ATI Mach64 CT/VT/GT/LT Cursor Support
3 */ 3 */
4 4
5#include <linux/slab.h>
6#include <linux/fb.h> 5#include <linux/fb.h>
7#include <linux/init.h> 6#include <linux/init.h>
8#include <linux/string.h> 7#include <linux/string.h>
diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c
index 1a056adb61c8..256966e9667d 100644
--- a/drivers/video/aty/radeon_backlight.c
+++ b/drivers/video/aty/radeon_backlight.c
@@ -12,6 +12,7 @@
12 12
13#include "radeonfb.h" 13#include "radeonfb.h"
14#include <linux/backlight.h> 14#include <linux/backlight.h>
15#include <linux/slab.h>
15 16
16#ifdef CONFIG_PMAC_BACKLIGHT 17#ifdef CONFIG_PMAC_BACKLIGHT
17#include <asm/backlight.h> 18#include <asm/backlight.h>
@@ -134,6 +135,7 @@ static struct backlight_ops radeon_bl_data = {
134 135
135void radeonfb_bl_init(struct radeonfb_info *rinfo) 136void radeonfb_bl_init(struct radeonfb_info *rinfo)
136{ 137{
138 struct backlight_properties props;
137 struct backlight_device *bd; 139 struct backlight_device *bd;
138 struct radeon_bl_privdata *pdata; 140 struct radeon_bl_privdata *pdata;
139 char name[12]; 141 char name[12];
@@ -155,7 +157,10 @@ void radeonfb_bl_init(struct radeonfb_info *rinfo)
155 157
156 snprintf(name, sizeof(name), "radeonbl%d", rinfo->info->node); 158 snprintf(name, sizeof(name), "radeonbl%d", rinfo->info->node);
157 159
158 bd = backlight_device_register(name, rinfo->info->dev, pdata, &radeon_bl_data); 160 memset(&props, 0, sizeof(struct backlight_properties));
161 props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
162 bd = backlight_device_register(name, rinfo->info->dev, pdata,
163 &radeon_bl_data, &props);
159 if (IS_ERR(bd)) { 164 if (IS_ERR(bd)) {
160 rinfo->info->bl_dev = NULL; 165 rinfo->info->bl_dev = NULL;
161 printk("radeonfb: Backlight registration failed\n"); 166 printk("radeonfb: Backlight registration failed\n");
@@ -175,9 +180,9 @@ void radeonfb_bl_init(struct radeonfb_info *rinfo)
175 180
176#ifdef CONFIG_PMAC_BACKLIGHT 181#ifdef CONFIG_PMAC_BACKLIGHT
177 pdata->negative = pdata->negative || 182 pdata->negative = pdata->negative ||
178 machine_is_compatible("PowerBook4,3") || 183 of_machine_is_compatible("PowerBook4,3") ||
179 machine_is_compatible("PowerBook6,3") || 184 of_machine_is_compatible("PowerBook6,3") ||
180 machine_is_compatible("PowerBook6,5"); 185 of_machine_is_compatible("PowerBook6,5");
181#endif 186#endif
182 187
183 rinfo->info->bl_dev = bd; 188 rinfo->info->bl_dev = bd;
@@ -185,7 +190,6 @@ void radeonfb_bl_init(struct radeonfb_info *rinfo)
185 63 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL, 190 63 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL,
186 217 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL); 191 217 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL);
187 192
188 bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
189 bd->props.brightness = bd->props.max_brightness; 193 bd->props.brightness = bd->props.max_brightness;
190 bd->props.power = FB_BLANK_UNBLANK; 194 bd->props.power = FB_BLANK_UNBLANK;
191 backlight_update_status(bd); 195 backlight_update_status(bd);
diff --git a/drivers/video/aty/radeon_monitor.c b/drivers/video/aty/radeon_monitor.c
index b4d4b88afc09..9261c918fde8 100644
--- a/drivers/video/aty/radeon_monitor.c
+++ b/drivers/video/aty/radeon_monitor.c
@@ -1,4 +1,7 @@
1#include "radeonfb.h" 1#include "radeonfb.h"
2
3#include <linux/slab.h>
4
2#include "../edid.h" 5#include "../edid.h"
3 6
4static struct fb_var_screeninfo radeonfb_default_var = { 7static struct fb_var_screeninfo radeonfb_default_var = {
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index a699aab63820..40f61320ce16 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -52,6 +52,7 @@
52#include <linux/ctype.h> 52#include <linux/ctype.h>
53#include <linux/dma-mapping.h> 53#include <linux/dma-mapping.h>
54#include <linux/platform_device.h> 54#include <linux/platform_device.h>
55#include <linux/slab.h>
55 56
56#include <asm/mach-au1x00/au1000.h> 57#include <asm/mach-au1x00/au1000.h>
57 58
diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c
index 0d96f1d2d4c5..e77e8e4280fb 100644
--- a/drivers/video/au1200fb.c
+++ b/drivers/video/au1200fb.c
@@ -41,6 +41,7 @@
41#include <linux/interrupt.h> 41#include <linux/interrupt.h>
42#include <linux/ctype.h> 42#include <linux/ctype.h>
43#include <linux/dma-mapping.h> 43#include <linux/dma-mapping.h>
44#include <linux/slab.h>
44 45
45#include <asm/mach-au1x00/au1000.h> 46#include <asm/mach-au1x00/au1000.h>
46#include "au1200fb.h" 47#include "au1200fb.h"
diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c
new file mode 100644
index 000000000000..68d2518fadaa
--- /dev/null
+++ b/drivers/video/backlight/88pm860x_bl.c
@@ -0,0 +1,307 @@
1/*
2 * Backlight driver for Marvell Semiconductor 88PM8606
3 *
4 * Copyright (C) 2009 Marvell International Ltd.
5 * Haojian Zhuang <haojian.zhuang@marvell.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/init.h>
13#include <linux/kernel.h>
14#include <linux/platform_device.h>
15#include <linux/fb.h>
16#include <linux/i2c.h>
17#include <linux/backlight.h>
18#include <linux/mfd/88pm860x.h>
19#include <linux/slab.h>
20
21#define MAX_BRIGHTNESS (0xFF)
22#define MIN_BRIGHTNESS (0)
23
24#define CURRENT_MASK (0x1F << 1)
25
26struct pm860x_backlight_data {
27 struct pm860x_chip *chip;
28 struct i2c_client *i2c;
29 int current_brightness;
30 int port;
31 int pwm;
32 int iset;
33};
34
35static inline int wled_a(int port)
36{
37 int ret;
38
39 ret = ((port - PM8606_BACKLIGHT1) << 1) + 2;
40 return ret;
41}
42
43static inline int wled_b(int port)
44{
45 int ret;
46
47 ret = ((port - PM8606_BACKLIGHT1) << 1) + 3;
48 return ret;
49}
50
51/* WLED2 & WLED3 share the same IDC */
52static inline int wled_idc(int port)
53{
54 int ret;
55
56 switch (port) {
57 case PM8606_BACKLIGHT1:
58 case PM8606_BACKLIGHT2:
59 ret = ((port - PM8606_BACKLIGHT1) << 1) + 3;
60 break;
61 case PM8606_BACKLIGHT3:
62 default:
63 ret = ((port - PM8606_BACKLIGHT2) << 1) + 3;
64 break;
65 }
66 return ret;
67}
68
69static int pm860x_backlight_set(struct backlight_device *bl, int brightness)
70{
71 struct pm860x_backlight_data *data = bl_get_data(bl);
72 struct pm860x_chip *chip = data->chip;
73 unsigned char value;
74 int ret;
75
76 if (brightness > MAX_BRIGHTNESS)
77 value = MAX_BRIGHTNESS;
78 else
79 value = brightness;
80
81 ret = pm860x_reg_write(data->i2c, wled_a(data->port), value);
82 if (ret < 0)
83 goto out;
84
85 if ((data->current_brightness == 0) && brightness) {
86 if (data->iset) {
87 ret = pm860x_set_bits(data->i2c, wled_idc(data->port),
88 CURRENT_MASK, data->iset);
89 if (ret < 0)
90 goto out;
91 }
92 if (data->pwm) {
93 ret = pm860x_set_bits(data->i2c, PM8606_PWM,
94 PM8606_PWM_FREQ_MASK, data->pwm);
95 if (ret < 0)
96 goto out;
97 }
98 if (brightness == MAX_BRIGHTNESS) {
99 /* set WLED_ON bit as 100% */
100 ret = pm860x_set_bits(data->i2c, wled_b(data->port),
101 PM8606_WLED_ON, PM8606_WLED_ON);
102 }
103 } else {
104 if (brightness == MAX_BRIGHTNESS) {
105 /* set WLED_ON bit as 100% */
106 ret = pm860x_set_bits(data->i2c, wled_b(data->port),
107 PM8606_WLED_ON, PM8606_WLED_ON);
108 } else {
109 /* clear WLED_ON bit since it's not 100% */
110 ret = pm860x_set_bits(data->i2c, wled_b(data->port),
111 PM8606_WLED_ON, 0);
112 }
113 }
114 if (ret < 0)
115 goto out;
116
117 dev_dbg(chip->dev, "set brightness %d\n", value);
118 data->current_brightness = value;
119 return 0;
120out:
121 dev_dbg(chip->dev, "set brightness %d failure with return "
122 "value:%d\n", value, ret);
123 return ret;
124}
125
126static int pm860x_backlight_update_status(struct backlight_device *bl)
127{
128 int brightness = bl->props.brightness;
129
130 if (bl->props.power != FB_BLANK_UNBLANK)
131 brightness = 0;
132
133 if (bl->props.fb_blank != FB_BLANK_UNBLANK)
134 brightness = 0;
135
136 if (bl->props.state & BL_CORE_SUSPENDED)
137 brightness = 0;
138
139 return pm860x_backlight_set(bl, brightness);
140}
141
142static int pm860x_backlight_get_brightness(struct backlight_device *bl)
143{
144 struct pm860x_backlight_data *data = bl_get_data(bl);
145 struct pm860x_chip *chip = data->chip;
146 int ret;
147
148 ret = pm860x_reg_read(data->i2c, wled_a(data->port));
149 if (ret < 0)
150 goto out;
151 data->current_brightness = ret;
152 dev_dbg(chip->dev, "get brightness %d\n", data->current_brightness);
153 return data->current_brightness;
154out:
155 return -EINVAL;
156}
157
158static struct backlight_ops pm860x_backlight_ops = {
159 .options = BL_CORE_SUSPENDRESUME,
160 .update_status = pm860x_backlight_update_status,
161 .get_brightness = pm860x_backlight_get_brightness,
162};
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)
184{
185 struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
186 struct pm860x_platform_data *pm860x_pdata;
187 struct pm860x_backlight_pdata *pdata = NULL;
188 struct pm860x_backlight_data *data;
189 struct backlight_device *bl;
190 struct resource *res;
191 struct backlight_properties props;
192 unsigned char value;
193 char name[MFD_NAME_SIZE];
194 int ret;
195
196 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
197 if (res == NULL) {
198 dev_err(&pdev->dev, "No I/O resource!\n");
199 return -EINVAL;
200 }
201
202 if (pdev->dev.parent->platform_data) {
203 pm860x_pdata = pdev->dev.parent->platform_data;
204 pdata = pm860x_pdata->backlight;
205 }
206 if (pdata == NULL) {
207 dev_err(&pdev->dev, "platform data isn't assigned to "
208 "backlight\n");
209 return -EINVAL;
210 }
211
212 data = kzalloc(sizeof(struct pm860x_backlight_data), GFP_KERNEL);
213 if (data == NULL)
214 return -ENOMEM;
215 strncpy(name, res->name, MFD_NAME_SIZE);
216 data->chip = chip;
217 data->i2c = (chip->id == CHIP_PM8606) ? chip->client \
218 : chip->companion;
219 data->current_brightness = MAX_BRIGHTNESS;
220 data->pwm = pdata->pwm;
221 data->iset = pdata->iset;
222 data->port = __check_device(pdata, name);
223 if (data->port < 0) {
224 dev_err(&pdev->dev, "wrong platform data is assigned");
225 return -EINVAL;
226 }
227
228 memset(&props, 0, sizeof(struct backlight_properties));
229 props.max_brightness = MAX_BRIGHTNESS;
230 bl = backlight_device_register(name, &pdev->dev, data,
231 &pm860x_backlight_ops, &props);
232 if (IS_ERR(bl)) {
233 dev_err(&pdev->dev, "failed to register backlight\n");
234 kfree(data);
235 return PTR_ERR(bl);
236 }
237 bl->props.brightness = MAX_BRIGHTNESS;
238
239 platform_set_drvdata(pdev, bl);
240
241 /* Enable reference VSYS */
242 ret = pm860x_reg_read(data->i2c, PM8606_VSYS);
243 if (ret < 0)
244 goto out;
245 if ((ret & PM8606_VSYS_EN) == 0) {
246 value = ret | PM8606_VSYS_EN;
247 ret = pm860x_reg_write(data->i2c, PM8606_VSYS, value);
248 if (ret < 0)
249 goto out;
250 }
251 /* Enable reference OSC */
252 ret = pm860x_reg_read(data->i2c, PM8606_MISC);
253 if (ret < 0)
254 goto out;
255 if ((ret & PM8606_MISC_OSC_EN) == 0) {
256 value = ret | PM8606_MISC_OSC_EN;
257 ret = pm860x_reg_write(data->i2c, PM8606_MISC, value);
258 if (ret < 0)
259 goto out;
260 }
261 /* read current backlight */
262 ret = pm860x_backlight_get_brightness(bl);
263 if (ret < 0)
264 goto out;
265
266 backlight_update_status(bl);
267 return 0;
268out:
269 kfree(data);
270 return ret;
271}
272
273static int pm860x_backlight_remove(struct platform_device *pdev)
274{
275 struct backlight_device *bl = platform_get_drvdata(pdev);
276 struct pm860x_backlight_data *data = bl_get_data(bl);
277
278 backlight_device_unregister(bl);
279 kfree(data);
280 return 0;
281}
282
283static struct platform_driver pm860x_backlight_driver = {
284 .driver = {
285 .name = "88pm860x-backlight",
286 .owner = THIS_MODULE,
287 },
288 .probe = pm860x_backlight_probe,
289 .remove = pm860x_backlight_remove,
290};
291
292static int __init pm860x_backlight_init(void)
293{
294 return platform_driver_register(&pm860x_backlight_driver);
295}
296module_init(pm860x_backlight_init);
297
298static void __exit pm860x_backlight_exit(void)
299{
300 platform_driver_unregister(&pm860x_backlight_driver);
301}
302module_exit(pm860x_backlight_exit);
303
304MODULE_DESCRIPTION("Backlight Driver for Marvell Semiconductor 88PM8606");
305MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
306MODULE_LICENSE("GPL");
307MODULE_ALIAS("platform:88pm860x-backlight");
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 09bfa9662e4d..c025c84601b0 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -31,6 +31,13 @@ config LCD_CORGI
31 Say y here to support the LCD panels usually found on SHARP 31 Say y here to support the LCD panels usually found on SHARP
32 corgi (C7x0) and spitz (Cxx00) models. 32 corgi (C7x0) and spitz (Cxx00) models.
33 33
34config LCD_L4F00242T03
35 tristate "Epson L4F00242T03 LCD"
36 depends on LCD_CLASS_DEVICE && SPI_MASTER && GENERIC_GPIO
37 help
38 SPI driver for Epson L4F00242T03. This provides basic support
39 for init and powering the LCD up/down through a sysfs interface.
40
34config LCD_LMS283GF05 41config LCD_LMS283GF05
35 tristate "Samsung LMS283GF05 LCD" 42 tristate "Samsung LMS283GF05 LCD"
36 depends on LCD_CLASS_DEVICE && SPI_MASTER && GENERIC_GPIO 43 depends on LCD_CLASS_DEVICE && SPI_MASTER && GENERIC_GPIO
@@ -212,6 +219,13 @@ config BACKLIGHT_DA903X
212 If you have a LCD backlight connected to the WLED output of DA9030 219 If you have a LCD backlight connected to the WLED output of DA9030
213 or DA9034 WLED output, say Y here to enable this driver. 220 or DA9034 WLED output, say Y here to enable this driver.
214 221
222config BACKLIGHT_MAX8925
223 tristate "Backlight driver for MAX8925"
224 depends on BACKLIGHT_CLASS_DEVICE && MFD_MAX8925
225 help
226 If you have a LCD backlight connected to the WLED output of MAX8925
227 WLED output, say Y here to enable this driver.
228
215config BACKLIGHT_MBP_NVIDIA 229config BACKLIGHT_MBP_NVIDIA
216 tristate "MacBook Pro Nvidia Backlight Driver" 230 tristate "MacBook Pro Nvidia Backlight Driver"
217 depends on BACKLIGHT_CLASS_DEVICE && X86 231 depends on BACKLIGHT_CLASS_DEVICE && X86
@@ -262,3 +276,9 @@ config BACKLIGHT_ADP5520
262 To compile this driver as a module, choose M here: the module will 276 To compile this driver as a module, choose M here: the module will
263 be called adp5520_bl. 277 be called adp5520_bl.
264 278
279config BACKLIGHT_88PM860X
280 tristate "Backlight Driver for 88PM8606 using WLED"
281 depends on BACKLIGHT_CLASS_DEVICE && MFD_88PM860X
282 help
283 Say Y to enable the backlight driver for Marvell 88PM8606.
284
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 9a405548874c..09d1f14d6257 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -3,6 +3,7 @@
3obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o 3obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o
4obj-$(CONFIG_LCD_CORGI) += corgi_lcd.o 4obj-$(CONFIG_LCD_CORGI) += corgi_lcd.o
5obj-$(CONFIG_LCD_HP700) += jornada720_lcd.o 5obj-$(CONFIG_LCD_HP700) += jornada720_lcd.o
6obj-$(CONFIG_LCD_L4F00242T03) += l4f00242t03.o
6obj-$(CONFIG_LCD_LMS283GF05) += lms283gf05.o 7obj-$(CONFIG_LCD_LMS283GF05) += lms283gf05.o
7obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o 8obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o
8obj-$(CONFIG_LCD_ILI9320) += ili9320.o 9obj-$(CONFIG_LCD_ILI9320) += ili9320.o
@@ -22,10 +23,12 @@ obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o
22obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o 23obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o
23obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o 24obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o
24obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o 25obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o
26obj-$(CONFIG_BACKLIGHT_MAX8925) += max8925_bl.o
25obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o 27obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o
26obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o 28obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o
27obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o 29obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
28obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o 30obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o
29obj-$(CONFIG_BACKLIGHT_ADX) += adx_bl.o 31obj-$(CONFIG_BACKLIGHT_ADX) += adx_bl.o
30obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o 32obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o
33obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o
31 34
diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c
index ad05da5ba3c7..9f436e014f85 100644
--- a/drivers/video/backlight/adp5520_bl.c
+++ b/drivers/video/backlight/adp5520_bl.c
@@ -12,10 +12,11 @@
12#include <linux/fb.h> 12#include <linux/fb.h>
13#include <linux/backlight.h> 13#include <linux/backlight.h>
14#include <linux/mfd/adp5520.h> 14#include <linux/mfd/adp5520.h>
15#include <linux/slab.h>
15 16
16struct adp5520_bl { 17struct adp5520_bl {
17 struct device *master; 18 struct device *master;
18 struct adp5520_backlight_platfrom_data *pdata; 19 struct adp5520_backlight_platform_data *pdata;
19 struct mutex lock; 20 struct mutex lock;
20 unsigned long cached_daylight_max; 21 unsigned long cached_daylight_max;
21 int id; 22 int id;
@@ -31,29 +32,30 @@ static int adp5520_bl_set(struct backlight_device *bl, int brightness)
31 if (data->pdata->en_ambl_sens) { 32 if (data->pdata->en_ambl_sens) {
32 if ((brightness > 0) && (brightness < ADP5020_MAX_BRIGHTNESS)) { 33 if ((brightness > 0) && (brightness < ADP5020_MAX_BRIGHTNESS)) {
33 /* Disable Ambient Light auto adjust */ 34 /* Disable Ambient Light auto adjust */
34 ret |= adp5520_clr_bits(master, BL_CONTROL, 35 ret |= adp5520_clr_bits(master, ADP5520_BL_CONTROL,
35 BL_AUTO_ADJ); 36 ADP5520_BL_AUTO_ADJ);
36 ret |= adp5520_write(master, DAYLIGHT_MAX, brightness); 37 ret |= adp5520_write(master, ADP5520_DAYLIGHT_MAX,
38 brightness);
37 } else { 39 } else {
38 /* 40 /*
39 * MAX_BRIGHTNESS -> Enable Ambient Light auto adjust 41 * MAX_BRIGHTNESS -> Enable Ambient Light auto adjust
40 * restore daylight l3 sysfs brightness 42 * restore daylight l3 sysfs brightness
41 */ 43 */
42 ret |= adp5520_write(master, DAYLIGHT_MAX, 44 ret |= adp5520_write(master, ADP5520_DAYLIGHT_MAX,
43 data->cached_daylight_max); 45 data->cached_daylight_max);
44 ret |= adp5520_set_bits(master, BL_CONTROL, 46 ret |= adp5520_set_bits(master, ADP5520_BL_CONTROL,
45 BL_AUTO_ADJ); 47 ADP5520_BL_AUTO_ADJ);
46 } 48 }
47 } else { 49 } else {
48 ret |= adp5520_write(master, DAYLIGHT_MAX, brightness); 50 ret |= adp5520_write(master, ADP5520_DAYLIGHT_MAX, brightness);
49 } 51 }
50 52
51 if (data->current_brightness && brightness == 0) 53 if (data->current_brightness && brightness == 0)
52 ret |= adp5520_set_bits(master, 54 ret |= adp5520_set_bits(master,
53 MODE_STATUS, DIM_EN); 55 ADP5520_MODE_STATUS, ADP5520_DIM_EN);
54 else if (data->current_brightness == 0 && brightness) 56 else if (data->current_brightness == 0 && brightness)
55 ret |= adp5520_clr_bits(master, 57 ret |= adp5520_clr_bits(master,
56 MODE_STATUS, DIM_EN); 58 ADP5520_MODE_STATUS, ADP5520_DIM_EN);
57 59
58 if (!ret) 60 if (!ret)
59 data->current_brightness = brightness; 61 data->current_brightness = brightness;
@@ -79,12 +81,12 @@ static int adp5520_bl_get_brightness(struct backlight_device *bl)
79 int error; 81 int error;
80 uint8_t reg_val; 82 uint8_t reg_val;
81 83
82 error = adp5520_read(data->master, BL_VALUE, &reg_val); 84 error = adp5520_read(data->master, ADP5520_BL_VALUE, &reg_val);
83 85
84 return error ? data->current_brightness : reg_val; 86 return error ? data->current_brightness : reg_val;
85} 87}
86 88
87static struct backlight_ops adp5520_bl_ops = { 89static const struct backlight_ops adp5520_bl_ops = {
88 .update_status = adp5520_bl_update_status, 90 .update_status = adp5520_bl_update_status,
89 .get_brightness = adp5520_bl_get_brightness, 91 .get_brightness = adp5520_bl_get_brightness,
90}; 92};
@@ -93,33 +95,46 @@ static int adp5520_bl_setup(struct backlight_device *bl)
93{ 95{
94 struct adp5520_bl *data = bl_get_data(bl); 96 struct adp5520_bl *data = bl_get_data(bl);
95 struct device *master = data->master; 97 struct device *master = data->master;
96 struct adp5520_backlight_platfrom_data *pdata = data->pdata; 98 struct adp5520_backlight_platform_data *pdata = data->pdata;
97 int ret = 0; 99 int ret = 0;
98 100
99 ret |= adp5520_write(master, DAYLIGHT_MAX, pdata->l1_daylight_max); 101 ret |= adp5520_write(master, ADP5520_DAYLIGHT_MAX,
100 ret |= adp5520_write(master, DAYLIGHT_DIM, pdata->l1_daylight_dim); 102 pdata->l1_daylight_max);
103 ret |= adp5520_write(master, ADP5520_DAYLIGHT_DIM,
104 pdata->l1_daylight_dim);
101 105
102 if (pdata->en_ambl_sens) { 106 if (pdata->en_ambl_sens) {
103 data->cached_daylight_max = pdata->l1_daylight_max; 107 data->cached_daylight_max = pdata->l1_daylight_max;
104 ret |= adp5520_write(master, OFFICE_MAX, pdata->l2_office_max); 108 ret |= adp5520_write(master, ADP5520_OFFICE_MAX,
105 ret |= adp5520_write(master, OFFICE_DIM, pdata->l2_office_dim); 109 pdata->l2_office_max);
106 ret |= adp5520_write(master, DARK_MAX, pdata->l3_dark_max); 110 ret |= adp5520_write(master, ADP5520_OFFICE_DIM,
107 ret |= adp5520_write(master, DARK_DIM, pdata->l3_dark_dim); 111 pdata->l2_office_dim);
108 ret |= adp5520_write(master, L2_TRIP, pdata->l2_trip); 112 ret |= adp5520_write(master, ADP5520_DARK_MAX,
109 ret |= adp5520_write(master, L2_HYS, pdata->l2_hyst); 113 pdata->l3_dark_max);
110 ret |= adp5520_write(master, L3_TRIP, pdata->l3_trip); 114 ret |= adp5520_write(master, ADP5520_DARK_DIM,
111 ret |= adp5520_write(master, L3_HYS, pdata->l3_hyst); 115 pdata->l3_dark_dim);
112 ret |= adp5520_write(master, ALS_CMPR_CFG, 116 ret |= adp5520_write(master, ADP5520_L2_TRIP,
113 ALS_CMPR_CFG_VAL(pdata->abml_filt, L3_EN)); 117 pdata->l2_trip);
118 ret |= adp5520_write(master, ADP5520_L2_HYS,
119 pdata->l2_hyst);
120 ret |= adp5520_write(master, ADP5520_L3_TRIP,
121 pdata->l3_trip);
122 ret |= adp5520_write(master, ADP5520_L3_HYS,
123 pdata->l3_hyst);
124 ret |= adp5520_write(master, ADP5520_ALS_CMPR_CFG,
125 ALS_CMPR_CFG_VAL(pdata->abml_filt,
126 ADP5520_L3_EN));
114 } 127 }
115 128
116 ret |= adp5520_write(master, BL_CONTROL, 129 ret |= adp5520_write(master, ADP5520_BL_CONTROL,
117 BL_CTRL_VAL(pdata->fade_led_law, pdata->en_ambl_sens)); 130 BL_CTRL_VAL(pdata->fade_led_law,
131 pdata->en_ambl_sens));
118 132
119 ret |= adp5520_write(master, BL_FADE, FADE_VAL(pdata->fade_in, 133 ret |= adp5520_write(master, ADP5520_BL_FADE, FADE_VAL(pdata->fade_in,
120 pdata->fade_out)); 134 pdata->fade_out));
121 135
122 ret |= adp5520_set_bits(master, MODE_STATUS, BL_EN | DIM_EN); 136 ret |= adp5520_set_bits(master, ADP5520_MODE_STATUS,
137 ADP5520_BL_EN | ADP5520_DIM_EN);
123 138
124 return ret; 139 return ret;
125} 140}
@@ -156,29 +171,31 @@ static ssize_t adp5520_store(struct device *dev, const char *buf,
156} 171}
157 172
158static ssize_t adp5520_bl_dark_max_show(struct device *dev, 173static ssize_t adp5520_bl_dark_max_show(struct device *dev,
159 struct device_attribute *attr, char *buf) 174 struct device_attribute *attr, char *buf)
160{ 175{
161 return adp5520_show(dev, buf, DARK_MAX); 176 return adp5520_show(dev, buf, ADP5520_DARK_MAX);
162} 177}
163 178
164static ssize_t adp5520_bl_dark_max_store(struct device *dev, 179static ssize_t adp5520_bl_dark_max_store(struct device *dev,
165 struct device_attribute *attr, const char *buf, size_t count) 180 struct device_attribute *attr,
181 const char *buf, size_t count)
166{ 182{
167 return adp5520_store(dev, buf, count, DARK_MAX); 183 return adp5520_store(dev, buf, count, ADP5520_DARK_MAX);
168} 184}
169static DEVICE_ATTR(dark_max, 0664, adp5520_bl_dark_max_show, 185static DEVICE_ATTR(dark_max, 0664, adp5520_bl_dark_max_show,
170 adp5520_bl_dark_max_store); 186 adp5520_bl_dark_max_store);
171 187
172static ssize_t adp5520_bl_office_max_show(struct device *dev, 188static ssize_t adp5520_bl_office_max_show(struct device *dev,
173 struct device_attribute *attr, char *buf) 189 struct device_attribute *attr, char *buf)
174{ 190{
175 return adp5520_show(dev, buf, OFFICE_MAX); 191 return adp5520_show(dev, buf, ADP5520_OFFICE_MAX);
176} 192}
177 193
178static ssize_t adp5520_bl_office_max_store(struct device *dev, 194static ssize_t adp5520_bl_office_max_store(struct device *dev,
179 struct device_attribute *attr, const char *buf, size_t count) 195 struct device_attribute *attr,
196 const char *buf, size_t count)
180{ 197{
181 return adp5520_store(dev, buf, count, OFFICE_MAX); 198 return adp5520_store(dev, buf, count, ADP5520_OFFICE_MAX);
182} 199}
183static DEVICE_ATTR(office_max, 0664, adp5520_bl_office_max_show, 200static DEVICE_ATTR(office_max, 0664, adp5520_bl_office_max_show,
184 adp5520_bl_office_max_store); 201 adp5520_bl_office_max_store);
@@ -186,16 +203,17 @@ static DEVICE_ATTR(office_max, 0664, adp5520_bl_office_max_show,
186static ssize_t adp5520_bl_daylight_max_show(struct device *dev, 203static ssize_t adp5520_bl_daylight_max_show(struct device *dev,
187 struct device_attribute *attr, char *buf) 204 struct device_attribute *attr, char *buf)
188{ 205{
189 return adp5520_show(dev, buf, DAYLIGHT_MAX); 206 return adp5520_show(dev, buf, ADP5520_DAYLIGHT_MAX);
190} 207}
191 208
192static ssize_t adp5520_bl_daylight_max_store(struct device *dev, 209static ssize_t adp5520_bl_daylight_max_store(struct device *dev,
193 struct device_attribute *attr, const char *buf, size_t count) 210 struct device_attribute *attr,
211 const char *buf, size_t count)
194{ 212{
195 struct adp5520_bl *data = dev_get_drvdata(dev); 213 struct adp5520_bl *data = dev_get_drvdata(dev);
196 214
197 strict_strtoul(buf, 10, &data->cached_daylight_max); 215 strict_strtoul(buf, 10, &data->cached_daylight_max);
198 return adp5520_store(dev, buf, count, DAYLIGHT_MAX); 216 return adp5520_store(dev, buf, count, ADP5520_DAYLIGHT_MAX);
199} 217}
200static DEVICE_ATTR(daylight_max, 0664, adp5520_bl_daylight_max_show, 218static DEVICE_ATTR(daylight_max, 0664, adp5520_bl_daylight_max_show,
201 adp5520_bl_daylight_max_store); 219 adp5520_bl_daylight_max_store);
@@ -203,14 +221,14 @@ static DEVICE_ATTR(daylight_max, 0664, adp5520_bl_daylight_max_show,
203static ssize_t adp5520_bl_dark_dim_show(struct device *dev, 221static ssize_t adp5520_bl_dark_dim_show(struct device *dev,
204 struct device_attribute *attr, char *buf) 222 struct device_attribute *attr, char *buf)
205{ 223{
206 return adp5520_show(dev, buf, DARK_DIM); 224 return adp5520_show(dev, buf, ADP5520_DARK_DIM);
207} 225}
208 226
209static ssize_t adp5520_bl_dark_dim_store(struct device *dev, 227static ssize_t adp5520_bl_dark_dim_store(struct device *dev,
210 struct device_attribute *attr, 228 struct device_attribute *attr,
211 const char *buf, size_t count) 229 const char *buf, size_t count)
212{ 230{
213 return adp5520_store(dev, buf, count, DARK_DIM); 231 return adp5520_store(dev, buf, count, ADP5520_DARK_DIM);
214} 232}
215static DEVICE_ATTR(dark_dim, 0664, adp5520_bl_dark_dim_show, 233static DEVICE_ATTR(dark_dim, 0664, adp5520_bl_dark_dim_show,
216 adp5520_bl_dark_dim_store); 234 adp5520_bl_dark_dim_store);
@@ -218,29 +236,29 @@ static DEVICE_ATTR(dark_dim, 0664, adp5520_bl_dark_dim_show,
218static ssize_t adp5520_bl_office_dim_show(struct device *dev, 236static ssize_t adp5520_bl_office_dim_show(struct device *dev,
219 struct device_attribute *attr, char *buf) 237 struct device_attribute *attr, char *buf)
220{ 238{
221 return adp5520_show(dev, buf, OFFICE_DIM); 239 return adp5520_show(dev, buf, ADP5520_OFFICE_DIM);
222} 240}
223 241
224static ssize_t adp5520_bl_office_dim_store(struct device *dev, 242static ssize_t adp5520_bl_office_dim_store(struct device *dev,
225 struct device_attribute *attr, 243 struct device_attribute *attr,
226 const char *buf, size_t count) 244 const char *buf, size_t count)
227{ 245{
228 return adp5520_store(dev, buf, count, OFFICE_DIM); 246 return adp5520_store(dev, buf, count, ADP5520_OFFICE_DIM);
229} 247}
230static DEVICE_ATTR(office_dim, 0664, adp5520_bl_office_dim_show, 248static DEVICE_ATTR(office_dim, 0664, adp5520_bl_office_dim_show,
231 adp5520_bl_office_dim_store); 249 adp5520_bl_office_dim_store);
232 250
233static ssize_t adp5520_bl_daylight_dim_show(struct device *dev, 251static ssize_t adp5520_bl_daylight_dim_show(struct device *dev,
234 struct device_attribute *attr, char *buf) 252 struct device_attribute *attr, char *buf)
235{ 253{
236 return adp5520_show(dev, buf, DAYLIGHT_DIM); 254 return adp5520_show(dev, buf, ADP5520_DAYLIGHT_DIM);
237} 255}
238 256
239static ssize_t adp5520_bl_daylight_dim_store(struct device *dev, 257static ssize_t adp5520_bl_daylight_dim_store(struct device *dev,
240 struct device_attribute *attr, 258 struct device_attribute *attr,
241 const char *buf, size_t count) 259 const char *buf, size_t count)
242{ 260{
243 return adp5520_store(dev, buf, count, DAYLIGHT_DIM); 261 return adp5520_store(dev, buf, count, ADP5520_DAYLIGHT_DIM);
244} 262}
245static DEVICE_ATTR(daylight_dim, 0664, adp5520_bl_daylight_dim_show, 263static DEVICE_ATTR(daylight_dim, 0664, adp5520_bl_daylight_dim_show,
246 adp5520_bl_daylight_dim_store); 264 adp5520_bl_daylight_dim_store);
@@ -261,6 +279,7 @@ static const struct attribute_group adp5520_bl_attr_group = {
261 279
262static int __devinit adp5520_bl_probe(struct platform_device *pdev) 280static int __devinit adp5520_bl_probe(struct platform_device *pdev)
263{ 281{
282 struct backlight_properties props;
264 struct backlight_device *bl; 283 struct backlight_device *bl;
265 struct adp5520_bl *data; 284 struct adp5520_bl *data;
266 int ret = 0; 285 int ret = 0;
@@ -283,17 +302,17 @@ static int __devinit adp5520_bl_probe(struct platform_device *pdev)
283 302
284 mutex_init(&data->lock); 303 mutex_init(&data->lock);
285 304
286 bl = backlight_device_register(pdev->name, data->master, 305 memset(&props, 0, sizeof(struct backlight_properties));
287 data, &adp5520_bl_ops); 306 props.max_brightness = ADP5020_MAX_BRIGHTNESS;
307 bl = backlight_device_register(pdev->name, data->master, data,
308 &adp5520_bl_ops, &props);
288 if (IS_ERR(bl)) { 309 if (IS_ERR(bl)) {
289 dev_err(&pdev->dev, "failed to register backlight\n"); 310 dev_err(&pdev->dev, "failed to register backlight\n");
290 kfree(data); 311 kfree(data);
291 return PTR_ERR(bl); 312 return PTR_ERR(bl);
292 } 313 }
293 314
294 bl->props.max_brightness = 315 bl->props.brightness = ADP5020_MAX_BRIGHTNESS;
295 bl->props.brightness = ADP5020_MAX_BRIGHTNESS;
296
297 if (data->pdata->en_ambl_sens) 316 if (data->pdata->en_ambl_sens)
298 ret = sysfs_create_group(&bl->dev.kobj, 317 ret = sysfs_create_group(&bl->dev.kobj,
299 &adp5520_bl_attr_group); 318 &adp5520_bl_attr_group);
@@ -316,7 +335,7 @@ static int __devexit adp5520_bl_remove(struct platform_device *pdev)
316 struct backlight_device *bl = platform_get_drvdata(pdev); 335 struct backlight_device *bl = platform_get_drvdata(pdev);
317 struct adp5520_bl *data = bl_get_data(bl); 336 struct adp5520_bl *data = bl_get_data(bl);
318 337
319 adp5520_clr_bits(data->master, MODE_STATUS, BL_EN); 338 adp5520_clr_bits(data->master, ADP5520_MODE_STATUS, ADP5520_BL_EN);
320 339
321 if (data->pdata->en_ambl_sens) 340 if (data->pdata->en_ambl_sens)
322 sysfs_remove_group(&bl->dev.kobj, 341 sysfs_remove_group(&bl->dev.kobj,
diff --git a/drivers/video/backlight/adx_bl.c b/drivers/video/backlight/adx_bl.c
index 2c3bdfc620b7..7f4a7c30a98b 100644
--- a/drivers/video/backlight/adx_bl.c
+++ b/drivers/video/backlight/adx_bl.c
@@ -12,6 +12,7 @@
12 12
13#include <linux/backlight.h> 13#include <linux/backlight.h>
14#include <linux/fb.h> 14#include <linux/fb.h>
15#include <linux/gfp.h>
15#include <linux/io.h> 16#include <linux/io.h>
16#include <linux/module.h> 17#include <linux/module.h>
17#include <linux/platform_device.h> 18#include <linux/platform_device.h>
@@ -56,12 +57,12 @@ static int adx_backlight_get_brightness(struct backlight_device *bldev)
56 return brightness & 0xff; 57 return brightness & 0xff;
57} 58}
58 59
59static int adx_backlight_check_fb(struct fb_info *fb) 60static int adx_backlight_check_fb(struct backlight_device *bldev, struct fb_info *fb)
60{ 61{
61 return 1; 62 return 1;
62} 63}
63 64
64static struct backlight_ops adx_backlight_ops = { 65static const struct backlight_ops adx_backlight_ops = {
65 .options = 0, 66 .options = 0,
66 .update_status = adx_backlight_update_status, 67 .update_status = adx_backlight_update_status,
67 .get_brightness = adx_backlight_get_brightness, 68 .get_brightness = adx_backlight_get_brightness,
@@ -70,6 +71,7 @@ static struct backlight_ops adx_backlight_ops = {
70 71
71static int __devinit adx_backlight_probe(struct platform_device *pdev) 72static int __devinit adx_backlight_probe(struct platform_device *pdev)
72{ 73{
74 struct backlight_properties props;
73 struct backlight_device *bldev; 75 struct backlight_device *bldev;
74 struct resource *res; 76 struct resource *res;
75 struct adxbl *bl; 77 struct adxbl *bl;
@@ -101,14 +103,15 @@ static int __devinit adx_backlight_probe(struct platform_device *pdev)
101 goto out; 103 goto out;
102 } 104 }
103 105
104 bldev = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, bl, 106 memset(&props, 0, sizeof(struct backlight_properties));
105 &adx_backlight_ops); 107 props.max_brightness = 0xff;
108 bldev = backlight_device_register(dev_name(&pdev->dev), &pdev->dev,
109 bl, &adx_backlight_ops, &props);
106 if (!bldev) { 110 if (!bldev) {
107 ret = -ENOMEM; 111 ret = -ENOMEM;
108 goto out; 112 goto out;
109 } 113 }
110 114
111 bldev->props.max_brightness = 0xff;
112 bldev->props.brightness = 0xff; 115 bldev->props.brightness = 0xff;
113 bldev->props.power = FB_BLANK_UNBLANK; 116 bldev->props.power = FB_BLANK_UNBLANK;
114 117
diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c
index 505c0823a105..e6a66dab088c 100644
--- a/drivers/video/backlight/atmel-pwm-bl.c
+++ b/drivers/video/backlight/atmel-pwm-bl.c
@@ -17,6 +17,7 @@
17#include <linux/backlight.h> 17#include <linux/backlight.h>
18#include <linux/atmel_pwm.h> 18#include <linux/atmel_pwm.h>
19#include <linux/atmel-pwm-bl.h> 19#include <linux/atmel-pwm-bl.h>
20#include <linux/slab.h>
20 21
21struct atmel_pwm_bl { 22struct atmel_pwm_bl {
22 const struct atmel_pwm_bl_platform_data *pdata; 23 const struct atmel_pwm_bl_platform_data *pdata;
@@ -113,13 +114,14 @@ static int atmel_pwm_bl_init_pwm(struct atmel_pwm_bl *pwmbl)
113 return pwm_channel_enable(&pwmbl->pwmc); 114 return pwm_channel_enable(&pwmbl->pwmc);
114} 115}
115 116
116static struct backlight_ops atmel_pwm_bl_ops = { 117static const struct backlight_ops atmel_pwm_bl_ops = {
117 .get_brightness = atmel_pwm_bl_get_intensity, 118 .get_brightness = atmel_pwm_bl_get_intensity,
118 .update_status = atmel_pwm_bl_set_intensity, 119 .update_status = atmel_pwm_bl_set_intensity,
119}; 120};
120 121
121static int atmel_pwm_bl_probe(struct platform_device *pdev) 122static int atmel_pwm_bl_probe(struct platform_device *pdev)
122{ 123{
124 struct backlight_properties props;
123 const struct atmel_pwm_bl_platform_data *pdata; 125 const struct atmel_pwm_bl_platform_data *pdata;
124 struct backlight_device *bldev; 126 struct backlight_device *bldev;
125 struct atmel_pwm_bl *pwmbl; 127 struct atmel_pwm_bl *pwmbl;
@@ -158,15 +160,17 @@ static int atmel_pwm_bl_probe(struct platform_device *pdev)
158 goto err_free_pwm; 160 goto err_free_pwm;
159 } 161 }
160 162
161 /* Turn display off by defatult. */ 163 /* Turn display off by default. */
162 retval = gpio_direction_output(pwmbl->gpio_on, 164 retval = gpio_direction_output(pwmbl->gpio_on,
163 0 ^ pdata->on_active_low); 165 0 ^ pdata->on_active_low);
164 if (retval) 166 if (retval)
165 goto err_free_gpio; 167 goto err_free_gpio;
166 } 168 }
167 169
168 bldev = backlight_device_register("atmel-pwm-bl", 170 memset(&props, 0, sizeof(struct backlight_properties));
169 &pdev->dev, pwmbl, &atmel_pwm_bl_ops); 171 props.max_brightness = pdata->pwm_duty_max - pdata->pwm_duty_min;
172 bldev = backlight_device_register("atmel-pwm-bl", &pdev->dev, pwmbl,
173 &atmel_pwm_bl_ops, &props);
170 if (IS_ERR(bldev)) { 174 if (IS_ERR(bldev)) {
171 retval = PTR_ERR(bldev); 175 retval = PTR_ERR(bldev);
172 goto err_free_gpio; 176 goto err_free_gpio;
@@ -178,7 +182,6 @@ static int atmel_pwm_bl_probe(struct platform_device *pdev)
178 182
179 /* Power up the backlight by default at middle intesity. */ 183 /* Power up the backlight by default at middle intesity. */
180 bldev->props.power = FB_BLANK_UNBLANK; 184 bldev->props.power = FB_BLANK_UNBLANK;
181 bldev->props.max_brightness = pdata->pwm_duty_max - pdata->pwm_duty_min;
182 bldev->props.brightness = bldev->props.max_brightness / 2; 185 bldev->props.brightness = bldev->props.max_brightness / 2;
183 186
184 retval = atmel_pwm_bl_init_pwm(pwmbl); 187 retval = atmel_pwm_bl_init_pwm(pwmbl);
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 6615ac7fa60a..e207810bba3c 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -13,6 +13,7 @@
13#include <linux/ctype.h> 13#include <linux/ctype.h>
14#include <linux/err.h> 14#include <linux/err.h>
15#include <linux/fb.h> 15#include <linux/fb.h>
16#include <linux/slab.h>
16 17
17#ifdef CONFIG_PMAC_BACKLIGHT 18#ifdef CONFIG_PMAC_BACKLIGHT
18#include <asm/backlight.h> 19#include <asm/backlight.h>
@@ -38,7 +39,7 @@ static int fb_notifier_callback(struct notifier_block *self,
38 mutex_lock(&bd->ops_lock); 39 mutex_lock(&bd->ops_lock);
39 if (bd->ops) 40 if (bd->ops)
40 if (!bd->ops->check_fb || 41 if (!bd->ops->check_fb ||
41 bd->ops->check_fb(evdata->info)) { 42 bd->ops->check_fb(bd, evdata->info)) {
42 bd->props.fb_blank = *(int *)evdata->data; 43 bd->props.fb_blank = *(int *)evdata->data;
43 if (bd->props.fb_blank == FB_BLANK_UNBLANK) 44 if (bd->props.fb_blank == FB_BLANK_UNBLANK)
44 bd->props.state &= ~BL_CORE_FBBLANK; 45 bd->props.state &= ~BL_CORE_FBBLANK;
@@ -269,7 +270,8 @@ EXPORT_SYMBOL(backlight_force_update);
269 * ERR_PTR() or a pointer to the newly allocated device. 270 * ERR_PTR() or a pointer to the newly allocated device.
270 */ 271 */
271struct backlight_device *backlight_device_register(const char *name, 272struct backlight_device *backlight_device_register(const char *name,
272 struct device *parent, void *devdata, struct backlight_ops *ops) 273 struct device *parent, void *devdata, const struct backlight_ops *ops,
274 const struct backlight_properties *props)
273{ 275{
274 struct backlight_device *new_bd; 276 struct backlight_device *new_bd;
275 int rc; 277 int rc;
@@ -289,6 +291,11 @@ struct backlight_device *backlight_device_register(const char *name,
289 dev_set_name(&new_bd->dev, name); 291 dev_set_name(&new_bd->dev, name);
290 dev_set_drvdata(&new_bd->dev, devdata); 292 dev_set_drvdata(&new_bd->dev, devdata);
291 293
294 /* Set default properties */
295 if (props)
296 memcpy(&new_bd->props, props,
297 sizeof(struct backlight_properties));
298
292 rc = device_register(&new_bd->dev); 299 rc = device_register(&new_bd->dev);
293 if (rc) { 300 if (rc) {
294 kfree(new_bd); 301 kfree(new_bd);
diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c
index 96774949cd30..1e71c35083bb 100644
--- a/drivers/video/backlight/corgi_lcd.c
+++ b/drivers/video/backlight/corgi_lcd.c
@@ -24,6 +24,7 @@
24#include <linux/lcd.h> 24#include <linux/lcd.h>
25#include <linux/spi/spi.h> 25#include <linux/spi/spi.h>
26#include <linux/spi/corgi_lcd.h> 26#include <linux/spi/corgi_lcd.h>
27#include <linux/slab.h>
27#include <asm/mach/sharpsl_param.h> 28#include <asm/mach/sharpsl_param.h>
28 29
29#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) 30#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL)
@@ -451,7 +452,7 @@ void corgi_lcd_limit_intensity(int limit)
451} 452}
452EXPORT_SYMBOL(corgi_lcd_limit_intensity); 453EXPORT_SYMBOL(corgi_lcd_limit_intensity);
453 454
454static struct backlight_ops corgi_bl_ops = { 455static const struct backlight_ops corgi_bl_ops = {
455 .get_brightness = corgi_bl_get_intensity, 456 .get_brightness = corgi_bl_get_intensity,
456 .update_status = corgi_bl_update_status, 457 .update_status = corgi_bl_update_status,
457}; 458};
@@ -533,6 +534,7 @@ err_free_backlight_on:
533 534
534static int __devinit corgi_lcd_probe(struct spi_device *spi) 535static int __devinit corgi_lcd_probe(struct spi_device *spi)
535{ 536{
537 struct backlight_properties props;
536 struct corgi_lcd_platform_data *pdata = spi->dev.platform_data; 538 struct corgi_lcd_platform_data *pdata = spi->dev.platform_data;
537 struct corgi_lcd *lcd; 539 struct corgi_lcd *lcd;
538 int ret = 0; 540 int ret = 0;
@@ -559,13 +561,14 @@ static int __devinit corgi_lcd_probe(struct spi_device *spi)
559 lcd->power = FB_BLANK_POWERDOWN; 561 lcd->power = FB_BLANK_POWERDOWN;
560 lcd->mode = (pdata) ? pdata->init_mode : CORGI_LCD_MODE_VGA; 562 lcd->mode = (pdata) ? pdata->init_mode : CORGI_LCD_MODE_VGA;
561 563
562 lcd->bl_dev = backlight_device_register("corgi_bl", &spi->dev, 564 memset(&props, 0, sizeof(struct backlight_properties));
563 lcd, &corgi_bl_ops); 565 props.max_brightness = pdata->max_intensity;
566 lcd->bl_dev = backlight_device_register("corgi_bl", &spi->dev, lcd,
567 &corgi_bl_ops, &props);
564 if (IS_ERR(lcd->bl_dev)) { 568 if (IS_ERR(lcd->bl_dev)) {
565 ret = PTR_ERR(lcd->bl_dev); 569 ret = PTR_ERR(lcd->bl_dev);
566 goto err_unregister_lcd; 570 goto err_unregister_lcd;
567 } 571 }
568 lcd->bl_dev->props.max_brightness = pdata->max_intensity;
569 lcd->bl_dev->props.brightness = pdata->default_intensity; 572 lcd->bl_dev->props.brightness = pdata->default_intensity;
570 lcd->bl_dev->props.power = FB_BLANK_UNBLANK; 573 lcd->bl_dev->props.power = FB_BLANK_UNBLANK;
571 574
diff --git a/drivers/video/backlight/cr_bllcd.c b/drivers/video/backlight/cr_bllcd.c
index b9fe62b475c6..a4f4546f0be0 100644
--- a/drivers/video/backlight/cr_bllcd.c
+++ b/drivers/video/backlight/cr_bllcd.c
@@ -36,6 +36,7 @@
36#include <linux/backlight.h> 36#include <linux/backlight.h>
37#include <linux/lcd.h> 37#include <linux/lcd.h>
38#include <linux/pci.h> 38#include <linux/pci.h>
39#include <linux/slab.h>
39 40
40/* The LVDS- and panel power controls sits on the 41/* The LVDS- and panel power controls sits on the
41 * GPIO port of the ISA bridge. 42 * GPIO port of the ISA bridge.
@@ -108,7 +109,7 @@ static int cr_backlight_get_intensity(struct backlight_device *bd)
108 return intensity; 109 return intensity;
109} 110}
110 111
111static struct backlight_ops cr_backlight_ops = { 112static const struct backlight_ops cr_backlight_ops = {
112 .get_brightness = cr_backlight_get_intensity, 113 .get_brightness = cr_backlight_get_intensity,
113 .update_status = cr_backlight_set_intensity, 114 .update_status = cr_backlight_set_intensity,
114}; 115};
@@ -170,6 +171,7 @@ static struct lcd_ops cr_lcd_ops = {
170 171
171static int cr_backlight_probe(struct platform_device *pdev) 172static int cr_backlight_probe(struct platform_device *pdev)
172{ 173{
174 struct backlight_properties props;
173 struct backlight_device *bdp; 175 struct backlight_device *bdp;
174 struct lcd_device *ldp; 176 struct lcd_device *ldp;
175 struct cr_panel *crp; 177 struct cr_panel *crp;
@@ -190,8 +192,9 @@ static int cr_backlight_probe(struct platform_device *pdev)
190 return -ENODEV; 192 return -ENODEV;
191 } 193 }
192 194
193 bdp = backlight_device_register("cr-backlight", 195 memset(&props, 0, sizeof(struct backlight_properties));
194 &pdev->dev, NULL, &cr_backlight_ops); 196 bdp = backlight_device_register("cr-backlight", &pdev->dev, NULL,
197 &cr_backlight_ops, &props);
195 if (IS_ERR(bdp)) { 198 if (IS_ERR(bdp)) {
196 pci_dev_put(lpc_dev); 199 pci_dev_put(lpc_dev);
197 return PTR_ERR(bdp); 200 return PTR_ERR(bdp);
@@ -201,7 +204,7 @@ static int cr_backlight_probe(struct platform_device *pdev)
201 if (IS_ERR(ldp)) { 204 if (IS_ERR(ldp)) {
202 backlight_device_unregister(bdp); 205 backlight_device_unregister(bdp);
203 pci_dev_put(lpc_dev); 206 pci_dev_put(lpc_dev);
204 return PTR_ERR(bdp); 207 return PTR_ERR(ldp);
205 } 208 }
206 209
207 pci_read_config_dword(lpc_dev, CRVML_REG_GPIOBAR, 210 pci_read_config_dword(lpc_dev, CRVML_REG_GPIOBAR,
@@ -220,9 +223,7 @@ static int cr_backlight_probe(struct platform_device *pdev)
220 crp->cr_lcd_device = ldp; 223 crp->cr_lcd_device = ldp;
221 crp->cr_backlight_device->props.power = FB_BLANK_UNBLANK; 224 crp->cr_backlight_device->props.power = FB_BLANK_UNBLANK;
222 crp->cr_backlight_device->props.brightness = 0; 225 crp->cr_backlight_device->props.brightness = 0;
223 crp->cr_backlight_device->props.max_brightness = 0;
224 cr_backlight_set_intensity(crp->cr_backlight_device); 226 cr_backlight_set_intensity(crp->cr_backlight_device);
225
226 cr_lcd_set_power(crp->cr_lcd_device, FB_BLANK_UNBLANK); 227 cr_lcd_set_power(crp->cr_lcd_device, FB_BLANK_UNBLANK);
227 228
228 platform_set_drvdata(pdev, crp); 229 platform_set_drvdata(pdev, crp);
diff --git a/drivers/video/backlight/da903x_bl.c b/drivers/video/backlight/da903x_bl.c
index 701a1081e199..87659ed79bd7 100644
--- a/drivers/video/backlight/da903x_bl.c
+++ b/drivers/video/backlight/da903x_bl.c
@@ -18,6 +18,7 @@
18#include <linux/fb.h> 18#include <linux/fb.h>
19#include <linux/backlight.h> 19#include <linux/backlight.h>
20#include <linux/mfd/da903x.h> 20#include <linux/mfd/da903x.h>
21#include <linux/slab.h>
21 22
22#define DA9030_WLED_CONTROL 0x25 23#define DA9030_WLED_CONTROL 0x25
23#define DA9030_WLED_CP_EN (1 << 6) 24#define DA9030_WLED_CP_EN (1 << 6)
@@ -25,6 +26,7 @@
25 26
26#define DA9034_WLED_CONTROL1 0x3C 27#define DA9034_WLED_CONTROL1 0x3C
27#define DA9034_WLED_CONTROL2 0x3D 28#define DA9034_WLED_CONTROL2 0x3D
29#define DA9034_WLED_ISET(x) ((x) & 0x1f)
28 30
29#define DA9034_WLED_BOOST_EN (1 << 5) 31#define DA9034_WLED_BOOST_EN (1 << 5)
30 32
@@ -94,15 +96,17 @@ static int da903x_backlight_get_brightness(struct backlight_device *bl)
94 return data->current_brightness; 96 return data->current_brightness;
95} 97}
96 98
97static struct backlight_ops da903x_backlight_ops = { 99static const struct backlight_ops da903x_backlight_ops = {
98 .update_status = da903x_backlight_update_status, 100 .update_status = da903x_backlight_update_status,
99 .get_brightness = da903x_backlight_get_brightness, 101 .get_brightness = da903x_backlight_get_brightness,
100}; 102};
101 103
102static int da903x_backlight_probe(struct platform_device *pdev) 104static int da903x_backlight_probe(struct platform_device *pdev)
103{ 105{
106 struct da9034_backlight_pdata *pdata = pdev->dev.platform_data;
104 struct da903x_backlight_data *data; 107 struct da903x_backlight_data *data;
105 struct backlight_device *bl; 108 struct backlight_device *bl;
109 struct backlight_properties props;
106 int max_brightness; 110 int max_brightness;
107 111
108 data = kzalloc(sizeof(*data), GFP_KERNEL); 112 data = kzalloc(sizeof(*data), GFP_KERNEL);
@@ -127,15 +131,20 @@ static int da903x_backlight_probe(struct platform_device *pdev)
127 data->da903x_dev = pdev->dev.parent; 131 data->da903x_dev = pdev->dev.parent;
128 data->current_brightness = 0; 132 data->current_brightness = 0;
129 133
130 bl = backlight_device_register(pdev->name, data->da903x_dev, 134 /* adjust the WLED output current */
131 data, &da903x_backlight_ops); 135 if (pdata)
136 da903x_write(data->da903x_dev, DA9034_WLED_CONTROL2,
137 DA9034_WLED_ISET(pdata->output_current));
138
139 props.max_brightness = max_brightness;
140 bl = backlight_device_register(pdev->name, data->da903x_dev, data,
141 &da903x_backlight_ops, &props);
132 if (IS_ERR(bl)) { 142 if (IS_ERR(bl)) {
133 dev_err(&pdev->dev, "failed to register backlight\n"); 143 dev_err(&pdev->dev, "failed to register backlight\n");
134 kfree(data); 144 kfree(data);
135 return PTR_ERR(bl); 145 return PTR_ERR(bl);
136 } 146 }
137 147
138 bl->props.max_brightness = max_brightness;
139 bl->props.brightness = max_brightness; 148 bl->props.brightness = max_brightness;
140 149
141 platform_set_drvdata(pdev, bl); 150 platform_set_drvdata(pdev, bl);
@@ -170,7 +179,7 @@ static int da903x_backlight_resume(struct device *dev)
170 return 0; 179 return 0;
171} 180}
172 181
173static struct dev_pm_ops da903x_backlight_pm_ops = { 182static const struct dev_pm_ops da903x_backlight_pm_ops = {
174 .suspend = da903x_backlight_suspend, 183 .suspend = da903x_backlight_suspend,
175 .resume = da903x_backlight_resume, 184 .resume = da903x_backlight_resume,
176}; 185};
diff --git a/drivers/video/backlight/generic_bl.c b/drivers/video/backlight/generic_bl.c
index 6d27f62fdcd0..312ca619735d 100644
--- a/drivers/video/backlight/generic_bl.c
+++ b/drivers/video/backlight/generic_bl.c
@@ -70,7 +70,7 @@ void corgibl_limit_intensity(int limit)
70} 70}
71EXPORT_SYMBOL(corgibl_limit_intensity); 71EXPORT_SYMBOL(corgibl_limit_intensity);
72 72
73static struct backlight_ops genericbl_ops = { 73static const struct backlight_ops genericbl_ops = {
74 .options = BL_CORE_SUSPENDRESUME, 74 .options = BL_CORE_SUSPENDRESUME,
75 .get_brightness = genericbl_get_intensity, 75 .get_brightness = genericbl_get_intensity,
76 .update_status = genericbl_send_intensity, 76 .update_status = genericbl_send_intensity,
@@ -78,6 +78,7 @@ static struct backlight_ops genericbl_ops = {
78 78
79static int genericbl_probe(struct platform_device *pdev) 79static int genericbl_probe(struct platform_device *pdev)
80{ 80{
81 struct backlight_properties props;
81 struct generic_bl_info *machinfo = pdev->dev.platform_data; 82 struct generic_bl_info *machinfo = pdev->dev.platform_data;
82 const char *name = "generic-bl"; 83 const char *name = "generic-bl";
83 struct backlight_device *bd; 84 struct backlight_device *bd;
@@ -89,14 +90,15 @@ static int genericbl_probe(struct platform_device *pdev)
89 if (machinfo->name) 90 if (machinfo->name)
90 name = machinfo->name; 91 name = machinfo->name;
91 92
92 bd = backlight_device_register (name, 93 memset(&props, 0, sizeof(struct backlight_properties));
93 &pdev->dev, NULL, &genericbl_ops); 94 props.max_brightness = machinfo->max_intensity;
95 bd = backlight_device_register(name, &pdev->dev, NULL, &genericbl_ops,
96 &props);
94 if (IS_ERR (bd)) 97 if (IS_ERR (bd))
95 return PTR_ERR (bd); 98 return PTR_ERR (bd);
96 99
97 platform_set_drvdata(pdev, bd); 100 platform_set_drvdata(pdev, bd);
98 101
99 bd->props.max_brightness = machinfo->max_intensity;
100 bd->props.power = FB_BLANK_UNBLANK; 102 bd->props.power = FB_BLANK_UNBLANK;
101 bd->props.brightness = machinfo->default_intensity; 103 bd->props.brightness = machinfo->default_intensity;
102 backlight_update_status(bd); 104 backlight_update_status(bd);
diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c
index 7fb4eefff80d..267d23f8d645 100644
--- a/drivers/video/backlight/hp680_bl.c
+++ b/drivers/video/backlight/hp680_bl.c
@@ -98,23 +98,25 @@ static int hp680bl_get_intensity(struct backlight_device *bd)
98 return current_intensity; 98 return current_intensity;
99} 99}
100 100
101static struct backlight_ops hp680bl_ops = { 101static const struct backlight_ops hp680bl_ops = {
102 .get_brightness = hp680bl_get_intensity, 102 .get_brightness = hp680bl_get_intensity,
103 .update_status = hp680bl_set_intensity, 103 .update_status = hp680bl_set_intensity,
104}; 104};
105 105
106static int __devinit hp680bl_probe(struct platform_device *pdev) 106static int __devinit hp680bl_probe(struct platform_device *pdev)
107{ 107{
108 struct backlight_properties props;
108 struct backlight_device *bd; 109 struct backlight_device *bd;
109 110
110 bd = backlight_device_register ("hp680-bl", &pdev->dev, NULL, 111 memset(&props, 0, sizeof(struct backlight_properties));
111 &hp680bl_ops); 112 props.max_brightness = HP680_MAX_INTENSITY;
113 bd = backlight_device_register("hp680-bl", &pdev->dev, NULL,
114 &hp680bl_ops, &props);
112 if (IS_ERR(bd)) 115 if (IS_ERR(bd))
113 return PTR_ERR(bd); 116 return PTR_ERR(bd);
114 117
115 platform_set_drvdata(pdev, bd); 118 platform_set_drvdata(pdev, bd);
116 119
117 bd->props.max_brightness = HP680_MAX_INTENSITY;
118 bd->props.brightness = HP680_DEFAULT_INTENSITY; 120 bd->props.brightness = HP680_DEFAULT_INTENSITY;
119 hp680bl_send_intensity(bd); 121 hp680bl_send_intensity(bd);
120 122
diff --git a/drivers/video/backlight/ili9320.c b/drivers/video/backlight/ili9320.c
index ba89b41b639c..5118a9f029ab 100644
--- a/drivers/video/backlight/ili9320.c
+++ b/drivers/video/backlight/ili9320.c
@@ -17,6 +17,7 @@
17#include <linux/init.h> 17#include <linux/init.h>
18#include <linux/lcd.h> 18#include <linux/lcd.h>
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/slab.h>
20 21
21#include <linux/spi/spi.h> 22#include <linux/spi/spi.h>
22 23
diff --git a/drivers/video/backlight/jornada720_bl.c b/drivers/video/backlight/jornada720_bl.c
index 7aed2565c1bd..2f177b3a4885 100644
--- a/drivers/video/backlight/jornada720_bl.c
+++ b/drivers/video/backlight/jornada720_bl.c
@@ -93,7 +93,7 @@ out:
93 return ret; 93 return ret;
94} 94}
95 95
96static struct backlight_ops jornada_bl_ops = { 96static const struct backlight_ops jornada_bl_ops = {
97 .get_brightness = jornada_bl_get_brightness, 97 .get_brightness = jornada_bl_get_brightness,
98 .update_status = jornada_bl_update_status, 98 .update_status = jornada_bl_update_status,
99 .options = BL_CORE_SUSPENDRESUME, 99 .options = BL_CORE_SUSPENDRESUME,
@@ -101,10 +101,14 @@ static struct backlight_ops jornada_bl_ops = {
101 101
102static int jornada_bl_probe(struct platform_device *pdev) 102static int jornada_bl_probe(struct platform_device *pdev)
103{ 103{
104 struct backlight_properties props;
104 int ret; 105 int ret;
105 struct backlight_device *bd; 106 struct backlight_device *bd;
106 107
107 bd = backlight_device_register(S1D_DEVICENAME, &pdev->dev, NULL, &jornada_bl_ops); 108 memset(&props, 0, sizeof(struct backlight_properties));
109 props.max_brightness = BL_MAX_BRIGHT;
110 bd = backlight_device_register(S1D_DEVICENAME, &pdev->dev, NULL,
111 &jornada_bl_ops, &props);
108 112
109 if (IS_ERR(bd)) { 113 if (IS_ERR(bd)) {
110 ret = PTR_ERR(bd); 114 ret = PTR_ERR(bd);
@@ -117,7 +121,6 @@ static int jornada_bl_probe(struct platform_device *pdev)
117 /* note. make sure max brightness is set otherwise 121 /* note. make sure max brightness is set otherwise
118 you will get seemingly non-related errors when 122 you will get seemingly non-related errors when
119 trying to change brightness */ 123 trying to change brightness */
120 bd->props.max_brightness = BL_MAX_BRIGHT;
121 jornada_bl_update_status(bd); 124 jornada_bl_update_status(bd);
122 125
123 platform_set_drvdata(pdev, bd); 126 platform_set_drvdata(pdev, bd);
diff --git a/drivers/video/backlight/kb3886_bl.c b/drivers/video/backlight/kb3886_bl.c
index a38fda1742dd..f439a8632287 100644
--- a/drivers/video/backlight/kb3886_bl.c
+++ b/drivers/video/backlight/kb3886_bl.c
@@ -134,27 +134,31 @@ static int kb3886bl_get_intensity(struct backlight_device *bd)
134 return kb3886bl_intensity; 134 return kb3886bl_intensity;
135} 135}
136 136
137static struct backlight_ops kb3886bl_ops = { 137static const struct backlight_ops kb3886bl_ops = {
138 .get_brightness = kb3886bl_get_intensity, 138 .get_brightness = kb3886bl_get_intensity,
139 .update_status = kb3886bl_send_intensity, 139 .update_status = kb3886bl_send_intensity,
140}; 140};
141 141
142static int kb3886bl_probe(struct platform_device *pdev) 142static int kb3886bl_probe(struct platform_device *pdev)
143{ 143{
144 struct backlight_properties props;
144 struct kb3886bl_machinfo *machinfo = pdev->dev.platform_data; 145 struct kb3886bl_machinfo *machinfo = pdev->dev.platform_data;
145 146
146 bl_machinfo = machinfo; 147 bl_machinfo = machinfo;
147 if (!machinfo->limit_mask) 148 if (!machinfo->limit_mask)
148 machinfo->limit_mask = -1; 149 machinfo->limit_mask = -1;
149 150
151 memset(&props, 0, sizeof(struct backlight_properties));
152 props.max_brightness = machinfo->max_intensity;
150 kb3886_backlight_device = backlight_device_register("kb3886-bl", 153 kb3886_backlight_device = backlight_device_register("kb3886-bl",
151 &pdev->dev, NULL, &kb3886bl_ops); 154 &pdev->dev, NULL,
155 &kb3886bl_ops,
156 &props);
152 if (IS_ERR(kb3886_backlight_device)) 157 if (IS_ERR(kb3886_backlight_device))
153 return PTR_ERR(kb3886_backlight_device); 158 return PTR_ERR(kb3886_backlight_device);
154 159
155 platform_set_drvdata(pdev, kb3886_backlight_device); 160 platform_set_drvdata(pdev, kb3886_backlight_device);
156 161
157 kb3886_backlight_device->props.max_brightness = machinfo->max_intensity;
158 kb3886_backlight_device->props.power = FB_BLANK_UNBLANK; 162 kb3886_backlight_device->props.power = FB_BLANK_UNBLANK;
159 kb3886_backlight_device->props.brightness = machinfo->default_intensity; 163 kb3886_backlight_device->props.brightness = machinfo->default_intensity;
160 backlight_update_status(kb3886_backlight_device); 164 backlight_update_status(kb3886_backlight_device);
diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c
new file mode 100644
index 000000000000..bcdb12c93efd
--- /dev/null
+++ b/drivers/video/backlight/l4f00242t03.c
@@ -0,0 +1,258 @@
1/*
2 * l4f00242t03.c -- support for Epson L4F00242T03 LCD
3 *
4 * Copyright 2007-2009 Freescale Semiconductor, Inc. All Rights Reserved.
5 *
6 * Copyright (c) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
7 * Inspired by Marek Vasut work in l4f00242t03.c
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/device.h>
15#include <linux/kernel.h>
16#include <linux/delay.h>
17#include <linux/gpio.h>
18#include <linux/lcd.h>
19#include <linux/slab.h>
20#include <linux/regulator/consumer.h>
21
22#include <linux/spi/spi.h>
23#include <linux/spi/l4f00242t03.h>
24
25struct l4f00242t03_priv {
26 struct spi_device *spi;
27 struct lcd_device *ld;
28 int lcd_on:1;
29 struct regulator *io_reg;
30 struct regulator *core_reg;
31};
32
33
34static void l4f00242t03_reset(unsigned int gpio)
35{
36 pr_debug("l4f00242t03_reset.\n");
37 gpio_set_value(gpio, 1);
38 mdelay(100);
39 gpio_set_value(gpio, 0);
40 mdelay(10); /* tRES >= 100us */
41 gpio_set_value(gpio, 1);
42 mdelay(20);
43}
44
45#define param(x) ((x) | 0x100)
46
47static void l4f00242t03_lcd_init(struct spi_device *spi)
48{
49 struct l4f00242t03_pdata *pdata = spi->dev.platform_data;
50 struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev);
51 const u16 cmd[] = { 0x36, param(0), 0x3A, param(0x60) };
52
53 dev_dbg(&spi->dev, "initializing LCD\n");
54
55 if (priv->io_reg) {
56 regulator_set_voltage(priv->io_reg, 1800000, 1800000);
57 regulator_enable(priv->io_reg);
58 }
59
60 if (priv->core_reg) {
61 regulator_set_voltage(priv->core_reg, 2800000, 2800000);
62 regulator_enable(priv->core_reg);
63 }
64
65 gpio_set_value(pdata->data_enable_gpio, 1);
66 msleep(60);
67 spi_write(spi, (const u8 *)cmd, ARRAY_SIZE(cmd) * sizeof(u16));
68}
69
70static int l4f00242t03_lcd_power_set(struct lcd_device *ld, int power)
71{
72 struct l4f00242t03_priv *priv = lcd_get_data(ld);
73 struct spi_device *spi = priv->spi;
74
75 const u16 slpout = 0x11;
76 const u16 dison = 0x29;
77
78 const u16 slpin = 0x10;
79 const u16 disoff = 0x28;
80
81 if (power) {
82 if (priv->lcd_on)
83 return 0;
84
85 dev_dbg(&spi->dev, "turning on LCD\n");
86
87 spi_write(spi, (const u8 *)&slpout, sizeof(u16));
88 msleep(60);
89 spi_write(spi, (const u8 *)&dison, sizeof(u16));
90
91 priv->lcd_on = 1;
92 } else {
93 if (!priv->lcd_on)
94 return 0;
95
96 dev_dbg(&spi->dev, "turning off LCD\n");
97
98 spi_write(spi, (const u8 *)&disoff, sizeof(u16));
99 msleep(60);
100 spi_write(spi, (const u8 *)&slpin, sizeof(u16));
101
102 priv->lcd_on = 0;
103 }
104
105 return 0;
106}
107
108static struct lcd_ops l4f_ops = {
109 .set_power = l4f00242t03_lcd_power_set,
110 .get_power = NULL,
111};
112
113static int __devinit l4f00242t03_probe(struct spi_device *spi)
114{
115 struct l4f00242t03_priv *priv;
116 struct l4f00242t03_pdata *pdata = spi->dev.platform_data;
117 int ret;
118
119 if (pdata == NULL) {
120 dev_err(&spi->dev, "Uninitialized platform data.\n");
121 return -EINVAL;
122 }
123
124 priv = kzalloc(sizeof(struct l4f00242t03_priv), GFP_KERNEL);
125
126 if (priv == NULL) {
127 dev_err(&spi->dev, "No memory for this device.\n");
128 ret = -ENOMEM;
129 goto err;
130 }
131
132 dev_set_drvdata(&spi->dev, priv);
133 spi->bits_per_word = 9;
134 spi_setup(spi);
135
136 priv->spi = spi;
137
138 ret = gpio_request(pdata->reset_gpio, "lcd l4f00242t03 reset");
139 if (ret) {
140 dev_err(&spi->dev,
141 "Unable to get the lcd l4f00242t03 reset gpio.\n");
142 return ret;
143 }
144
145 ret = gpio_direction_output(pdata->reset_gpio, 1);
146 if (ret)
147 goto err2;
148
149 ret = gpio_request(pdata->data_enable_gpio,
150 "lcd l4f00242t03 data enable");
151 if (ret) {
152 dev_err(&spi->dev,
153 "Unable to get the lcd l4f00242t03 data en gpio.\n");
154 return ret;
155 }
156
157 ret = gpio_direction_output(pdata->data_enable_gpio, 0);
158 if (ret)
159 goto err3;
160
161 if (pdata->io_supply) {
162 priv->io_reg = regulator_get(NULL, pdata->io_supply);
163
164 if (IS_ERR(priv->io_reg)) {
165 pr_err("%s: Unable to get the IO regulator\n",
166 __func__);
167 goto err3;
168 }
169 }
170
171 if (pdata->core_supply) {
172 priv->core_reg = regulator_get(NULL, pdata->core_supply);
173
174 if (IS_ERR(priv->core_reg)) {
175 pr_err("%s: Unable to get the core regulator\n",
176 __func__);
177 goto err4;
178 }
179 }
180
181 priv->ld = lcd_device_register("l4f00242t03",
182 &spi->dev, priv, &l4f_ops);
183 if (IS_ERR(priv->ld)) {
184 ret = PTR_ERR(priv->ld);
185 goto err5;
186 }
187
188 /* Init the LCD */
189 l4f00242t03_reset(pdata->reset_gpio);
190 l4f00242t03_lcd_init(spi);
191 l4f00242t03_lcd_power_set(priv->ld, 1);
192
193 dev_info(&spi->dev, "Epson l4f00242t03 lcd probed.\n");
194
195 return 0;
196
197err5:
198 if (priv->core_reg)
199 regulator_put(priv->core_reg);
200err4:
201 if (priv->io_reg)
202 regulator_put(priv->io_reg);
203err3:
204 gpio_free(pdata->data_enable_gpio);
205err2:
206 gpio_free(pdata->reset_gpio);
207err:
208 kfree(priv);
209
210 return ret;
211}
212
213static int __devexit l4f00242t03_remove(struct spi_device *spi)
214{
215 struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev);
216 struct l4f00242t03_pdata *pdata = priv->spi->dev.platform_data;
217
218 l4f00242t03_lcd_power_set(priv->ld, 0);
219 lcd_device_unregister(priv->ld);
220
221 gpio_free(pdata->data_enable_gpio);
222 gpio_free(pdata->reset_gpio);
223
224 if (priv->io_reg)
225 regulator_put(priv->core_reg);
226 if (priv->core_reg)
227 regulator_put(priv->io_reg);
228
229 kfree(priv);
230
231 return 0;
232}
233
234static struct spi_driver l4f00242t03_driver = {
235 .driver = {
236 .name = "l4f00242t03",
237 .owner = THIS_MODULE,
238 },
239 .probe = l4f00242t03_probe,
240 .remove = __devexit_p(l4f00242t03_remove),
241};
242
243static __init int l4f00242t03_init(void)
244{
245 return spi_register_driver(&l4f00242t03_driver);
246}
247
248static __exit void l4f00242t03_exit(void)
249{
250 spi_unregister_driver(&l4f00242t03_driver);
251}
252
253module_init(l4f00242t03_init);
254module_exit(l4f00242t03_exit);
255
256MODULE_AUTHOR("Alberto Panizzo <maramaopercheseimorto@gmail.com>");
257MODULE_DESCRIPTION("EPSON L4F00242T03 LCD");
258MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index a482dd7b0311..71a11cadffc4 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -13,6 +13,7 @@
13#include <linux/ctype.h> 13#include <linux/ctype.h>
14#include <linux/err.h> 14#include <linux/err.h>
15#include <linux/fb.h> 15#include <linux/fb.h>
16#include <linux/slab.h>
16 17
17#if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \ 18#if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \
18 defined(CONFIG_LCD_CLASS_DEVICE_MODULE)) 19 defined(CONFIG_LCD_CLASS_DEVICE_MODULE))
@@ -101,7 +102,7 @@ static ssize_t lcd_store_power(struct device *dev,
101 int power = simple_strtoul(buf, &endp, 0); 102 int power = simple_strtoul(buf, &endp, 0);
102 size_t size = endp - buf; 103 size_t size = endp - buf;
103 104
104 if (*endp && isspace(*endp)) 105 if (isspace(*endp))
105 size++; 106 size++;
106 if (size != count) 107 if (size != count)
107 return -EINVAL; 108 return -EINVAL;
@@ -140,7 +141,7 @@ static ssize_t lcd_store_contrast(struct device *dev,
140 int contrast = simple_strtoul(buf, &endp, 0); 141 int contrast = simple_strtoul(buf, &endp, 0);
141 size_t size = endp - buf; 142 size_t size = endp - buf;
142 143
143 if (*endp && isspace(*endp)) 144 if (isspace(*endp))
144 size++; 145 size++;
145 if (size != count) 146 if (size != count)
146 return -EINVAL; 147 return -EINVAL;
diff --git a/drivers/video/backlight/lms283gf05.c b/drivers/video/backlight/lms283gf05.c
index 447b542a20ca..abc43a0eb97d 100644
--- a/drivers/video/backlight/lms283gf05.c
+++ b/drivers/video/backlight/lms283gf05.c
@@ -11,6 +11,7 @@
11#include <linux/device.h> 11#include <linux/device.h>
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/delay.h> 13#include <linux/delay.h>
14#include <linux/slab.h>
14#include <linux/gpio.h> 15#include <linux/gpio.h>
15#include <linux/lcd.h> 16#include <linux/lcd.h>
16 17
diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c
index 6b488b8a7eee..7571bc26071e 100644
--- a/drivers/video/backlight/locomolcd.c
+++ b/drivers/video/backlight/locomolcd.c
@@ -141,7 +141,7 @@ static int locomolcd_get_intensity(struct backlight_device *bd)
141 return current_intensity; 141 return current_intensity;
142} 142}
143 143
144static struct backlight_ops locomobl_data = { 144static const struct backlight_ops locomobl_data = {
145 .get_brightness = locomolcd_get_intensity, 145 .get_brightness = locomolcd_get_intensity,
146 .update_status = locomolcd_set_intensity, 146 .update_status = locomolcd_set_intensity,
147}; 147};
@@ -167,6 +167,7 @@ static int locomolcd_resume(struct locomo_dev *dev)
167 167
168static int locomolcd_probe(struct locomo_dev *ldev) 168static int locomolcd_probe(struct locomo_dev *ldev)
169{ 169{
170 struct backlight_properties props;
170 unsigned long flags; 171 unsigned long flags;
171 172
172 local_irq_save(flags); 173 local_irq_save(flags);
@@ -182,13 +183,16 @@ static int locomolcd_probe(struct locomo_dev *ldev)
182 183
183 local_irq_restore(flags); 184 local_irq_restore(flags);
184 185
185 locomolcd_bl_device = backlight_device_register("locomo-bl", &ldev->dev, NULL, &locomobl_data); 186 memset(&props, 0, sizeof(struct backlight_properties));
187 props.max_brightness = 4;
188 locomolcd_bl_device = backlight_device_register("locomo-bl",
189 &ldev->dev, NULL,
190 &locomobl_data, &props);
186 191
187 if (IS_ERR (locomolcd_bl_device)) 192 if (IS_ERR (locomolcd_bl_device))
188 return PTR_ERR (locomolcd_bl_device); 193 return PTR_ERR (locomolcd_bl_device);
189 194
190 /* Set up frontlight so that screen is readable */ 195 /* Set up frontlight so that screen is readable */
191 locomolcd_bl_device->props.max_brightness = 4,
192 locomolcd_bl_device->props.brightness = 2; 196 locomolcd_bl_device->props.brightness = 2;
193 locomolcd_set_intensity(locomolcd_bl_device); 197 locomolcd_set_intensity(locomolcd_bl_device);
194 198
diff --git a/drivers/video/backlight/ltv350qv.c b/drivers/video/backlight/ltv350qv.c
index 4631ca8fa4a4..8010aaeb5adb 100644
--- a/drivers/video/backlight/ltv350qv.c
+++ b/drivers/video/backlight/ltv350qv.c
@@ -13,6 +13,7 @@
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/lcd.h> 14#include <linux/lcd.h>
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/slab.h>
16#include <linux/spi/spi.h> 17#include <linux/spi/spi.h>
17 18
18#include "ltv350qv.h" 19#include "ltv350qv.h"
diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c
new file mode 100644
index 000000000000..b5accc957ad3
--- /dev/null
+++ b/drivers/video/backlight/max8925_bl.c
@@ -0,0 +1,203 @@
1/*
2 * Backlight driver for Maxim MAX8925
3 *
4 * Copyright (C) 2009 Marvell International Ltd.
5 * Haojian Zhuang <haojian.zhuang@marvell.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/init.h>
13#include <linux/kernel.h>
14#include <linux/platform_device.h>
15#include <linux/fb.h>
16#include <linux/i2c.h>
17#include <linux/backlight.h>
18#include <linux/mfd/max8925.h>
19#include <linux/slab.h>
20
21#define MAX_BRIGHTNESS (0xff)
22#define MIN_BRIGHTNESS (0)
23
24#define LWX_FREQ(x) (((x - 601) / 100) & 0x7)
25
26struct max8925_backlight_data {
27 struct max8925_chip *chip;
28
29 int current_brightness;
30};
31
32static int max8925_backlight_set(struct backlight_device *bl, int brightness)
33{
34 struct max8925_backlight_data *data = bl_get_data(bl);
35 struct max8925_chip *chip = data->chip;
36 unsigned char value;
37 int ret;
38
39 if (brightness > MAX_BRIGHTNESS)
40 value = MAX_BRIGHTNESS;
41 else
42 value = brightness;
43
44 ret = max8925_reg_write(chip->i2c, MAX8925_WLED_CNTL, value);
45 if (ret < 0)
46 goto out;
47
48 if (!data->current_brightness && brightness)
49 /* enable WLED output */
50 ret = max8925_set_bits(chip->i2c, MAX8925_WLED_MODE_CNTL, 1, 1);
51 else if (!brightness)
52 /* disable WLED output */
53 ret = max8925_set_bits(chip->i2c, MAX8925_WLED_MODE_CNTL, 1, 0);
54 if (ret < 0)
55 goto out;
56 dev_dbg(chip->dev, "set brightness %d\n", value);
57 data->current_brightness = value;
58 return 0;
59out:
60 dev_dbg(chip->dev, "set brightness %d failure with return value:%d\n",
61 value, ret);
62 return ret;
63}
64
65static int max8925_backlight_update_status(struct backlight_device *bl)
66{
67 int brightness = bl->props.brightness;
68
69 if (bl->props.power != FB_BLANK_UNBLANK)
70 brightness = 0;
71
72 if (bl->props.fb_blank != FB_BLANK_UNBLANK)
73 brightness = 0;
74
75 if (bl->props.state & BL_CORE_SUSPENDED)
76 brightness = 0;
77
78 return max8925_backlight_set(bl, brightness);
79}
80
81static int max8925_backlight_get_brightness(struct backlight_device *bl)
82{
83 struct max8925_backlight_data *data = bl_get_data(bl);
84 struct max8925_chip *chip = data->chip;
85 int ret;
86
87 ret = max8925_reg_read(chip->i2c, MAX8925_WLED_CNTL);
88 if (ret < 0)
89 return -EINVAL;
90 data->current_brightness = ret;
91 dev_dbg(chip->dev, "get brightness %d\n", data->current_brightness);
92 return ret;
93}
94
95static struct backlight_ops max8925_backlight_ops = {
96 .options = BL_CORE_SUSPENDRESUME,
97 .update_status = max8925_backlight_update_status,
98 .get_brightness = max8925_backlight_get_brightness,
99};
100
101static int __devinit max8925_backlight_probe(struct platform_device *pdev)
102{
103 struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
104 struct max8925_platform_data *max8925_pdata;
105 struct max8925_backlight_pdata *pdata = NULL;
106 struct max8925_backlight_data *data;
107 struct backlight_device *bl;
108 struct backlight_properties props;
109 struct resource *res;
110 char name[MAX8925_NAME_SIZE];
111 unsigned char value;
112 int ret;
113
114 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
115 if (res == NULL) {
116 dev_err(&pdev->dev, "No I/O resource!\n");
117 return -EINVAL;
118 }
119
120 if (pdev->dev.parent->platform_data) {
121 max8925_pdata = pdev->dev.parent->platform_data;
122 pdata = max8925_pdata->backlight;
123 }
124
125 if (!pdata) {
126 dev_err(&pdev->dev, "platform data isn't assigned to "
127 "backlight\n");
128 return -EINVAL;
129 }
130
131 data = kzalloc(sizeof(struct max8925_backlight_data), GFP_KERNEL);
132 if (data == NULL)
133 return -ENOMEM;
134 strncpy(name, res->name, MAX8925_NAME_SIZE);
135 data->chip = chip;
136 data->current_brightness = 0;
137
138 memset(&props, 0, sizeof(struct backlight_properties));
139 props.max_brightness = MAX_BRIGHTNESS;
140 bl = backlight_device_register(name, &pdev->dev, data,
141 &max8925_backlight_ops, &props);
142 if (IS_ERR(bl)) {
143 dev_err(&pdev->dev, "failed to register backlight\n");
144 kfree(data);
145 return PTR_ERR(bl);
146 }
147 bl->props.brightness = MAX_BRIGHTNESS;
148
149 platform_set_drvdata(pdev, bl);
150
151 value = 0;
152 if (pdata->lxw_scl)
153 value |= (1 << 7);
154 if (pdata->lxw_freq)
155 value |= (LWX_FREQ(pdata->lxw_freq) << 4);
156 if (pdata->dual_string)
157 value |= (1 << 1);
158 ret = max8925_set_bits(chip->i2c, MAX8925_WLED_MODE_CNTL, 0xfe, value);
159 if (ret < 0)
160 goto out;
161
162 backlight_update_status(bl);
163 return 0;
164out:
165 kfree(data);
166 return ret;
167}
168
169static int __devexit max8925_backlight_remove(struct platform_device *pdev)
170{
171 struct backlight_device *bl = platform_get_drvdata(pdev);
172 struct max8925_backlight_data *data = bl_get_data(bl);
173
174 backlight_device_unregister(bl);
175 kfree(data);
176 return 0;
177}
178
179static struct platform_driver max8925_backlight_driver = {
180 .driver = {
181 .name = "max8925-backlight",
182 .owner = THIS_MODULE,
183 },
184 .probe = max8925_backlight_probe,
185 .remove = __devexit_p(max8925_backlight_remove),
186};
187
188static int __init max8925_backlight_init(void)
189{
190 return platform_driver_register(&max8925_backlight_driver);
191}
192module_init(max8925_backlight_init);
193
194static void __exit max8925_backlight_exit(void)
195{
196 platform_driver_unregister(&max8925_backlight_driver);
197};
198module_exit(max8925_backlight_exit);
199
200MODULE_DESCRIPTION("Backlight Driver for Maxim MAX8925");
201MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
202MODULE_LICENSE("GPL");
203MODULE_ALIAS("platform:max8925-backlight");
diff --git a/drivers/video/backlight/mbp_nvidia_bl.c b/drivers/video/backlight/mbp_nvidia_bl.c
index 9edb8d7c295f..1b5d3fe6bbbc 100644
--- a/drivers/video/backlight/mbp_nvidia_bl.c
+++ b/drivers/video/backlight/mbp_nvidia_bl.c
@@ -33,7 +33,7 @@ struct dmi_match_data {
33 unsigned long iostart; 33 unsigned long iostart;
34 unsigned long iolen; 34 unsigned long iolen;
35 /* Backlight operations structure. */ 35 /* Backlight operations structure. */
36 struct backlight_ops backlight_ops; 36 const struct backlight_ops backlight_ops;
37}; 37};
38 38
39/* Module parameters. */ 39/* Module parameters. */
@@ -139,6 +139,51 @@ static int mbp_dmi_match(const struct dmi_system_id *id)
139static const struct dmi_system_id __initdata mbp_device_table[] = { 139static const struct dmi_system_id __initdata mbp_device_table[] = {
140 { 140 {
141 .callback = mbp_dmi_match, 141 .callback = mbp_dmi_match,
142 .ident = "MacBook 1,1",
143 .matches = {
144 DMI_MATCH(DMI_SYS_VENDOR, "Apple 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,
142 .ident = "MacBookPro 3,1", 187 .ident = "MacBookPro 3,1",
143 .matches = { 188 .matches = {
144 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), 189 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
@@ -220,6 +265,24 @@ static const struct dmi_system_id __initdata mbp_device_table[] = {
220 }, 265 },
221 { 266 {
222 .callback = mbp_dmi_match, 267 .callback = mbp_dmi_match,
268 .ident = "MacBookPro 5,3",
269 .matches = {
270 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
271 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,3"),
272 },
273 .driver_data = (void *)&nvidia_chipset_data,
274 },
275 {
276 .callback = mbp_dmi_match,
277 .ident = "MacBookPro 5,4",
278 .matches = {
279 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
280 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,4"),
281 },
282 .driver_data = (void *)&nvidia_chipset_data,
283 },
284 {
285 .callback = mbp_dmi_match,
223 .ident = "MacBookPro 5,5", 286 .ident = "MacBookPro 5,5",
224 .matches = { 287 .matches = {
225 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), 288 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
@@ -232,6 +295,7 @@ static const struct dmi_system_id __initdata mbp_device_table[] = {
232 295
233static int __init mbp_init(void) 296static int __init mbp_init(void)
234{ 297{
298 struct backlight_properties props;
235 if (!dmi_check_system(mbp_device_table)) 299 if (!dmi_check_system(mbp_device_table))
236 return -ENODEV; 300 return -ENODEV;
237 301
@@ -239,14 +303,17 @@ static int __init mbp_init(void)
239 "Macbook Pro backlight")) 303 "Macbook Pro backlight"))
240 return -ENXIO; 304 return -ENXIO;
241 305
242 mbp_backlight_device = backlight_device_register("mbp_backlight", 306 memset(&props, 0, sizeof(struct backlight_properties));
243 NULL, NULL, &driver_data->backlight_ops); 307 props.max_brightness = 15;
308 mbp_backlight_device = backlight_device_register("mbp_backlight", NULL,
309 NULL,
310 &driver_data->backlight_ops,
311 &props);
244 if (IS_ERR(mbp_backlight_device)) { 312 if (IS_ERR(mbp_backlight_device)) {
245 release_region(driver_data->iostart, driver_data->iolen); 313 release_region(driver_data->iostart, driver_data->iolen);
246 return PTR_ERR(mbp_backlight_device); 314 return PTR_ERR(mbp_backlight_device);
247 } 315 }
248 316
249 mbp_backlight_device->props.max_brightness = 15;
250 mbp_backlight_device->props.brightness = 317 mbp_backlight_device->props.brightness =
251 driver_data->backlight_ops.get_brightness(mbp_backlight_device); 318 driver_data->backlight_ops.get_brightness(mbp_backlight_device);
252 backlight_update_status(mbp_backlight_device); 319 backlight_update_status(mbp_backlight_device);
diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c
index cbad67e89826..d3bc56296c8d 100644
--- a/drivers/video/backlight/omap1_bl.c
+++ b/drivers/video/backlight/omap1_bl.c
@@ -24,10 +24,11 @@
24#include <linux/platform_device.h> 24#include <linux/platform_device.h>
25#include <linux/fb.h> 25#include <linux/fb.h>
26#include <linux/backlight.h> 26#include <linux/backlight.h>
27#include <linux/slab.h>
27 28
28#include <mach/hardware.h> 29#include <mach/hardware.h>
29#include <mach/board.h> 30#include <plat/board.h>
30#include <mach/mux.h> 31#include <plat/mux.h>
31 32
32#define OMAPBL_MAX_INTENSITY 0xff 33#define OMAPBL_MAX_INTENSITY 0xff
33 34
@@ -125,13 +126,14 @@ static int omapbl_get_intensity(struct backlight_device *dev)
125 return bl->current_intensity; 126 return bl->current_intensity;
126} 127}
127 128
128static struct backlight_ops omapbl_ops = { 129static const struct backlight_ops omapbl_ops = {
129 .get_brightness = omapbl_get_intensity, 130 .get_brightness = omapbl_get_intensity,
130 .update_status = omapbl_update_status, 131 .update_status = omapbl_update_status,
131}; 132};
132 133
133static int omapbl_probe(struct platform_device *pdev) 134static int omapbl_probe(struct platform_device *pdev)
134{ 135{
136 struct backlight_properties props;
135 struct backlight_device *dev; 137 struct backlight_device *dev;
136 struct omap_backlight *bl; 138 struct omap_backlight *bl;
137 struct omap_backlight_config *pdata = pdev->dev.platform_data; 139 struct omap_backlight_config *pdata = pdev->dev.platform_data;
@@ -139,13 +141,14 @@ static int omapbl_probe(struct platform_device *pdev)
139 if (!pdata) 141 if (!pdata)
140 return -ENXIO; 142 return -ENXIO;
141 143
142 omapbl_ops.check_fb = pdata->check_fb;
143
144 bl = kzalloc(sizeof(struct omap_backlight), GFP_KERNEL); 144 bl = kzalloc(sizeof(struct omap_backlight), GFP_KERNEL);
145 if (unlikely(!bl)) 145 if (unlikely(!bl))
146 return -ENOMEM; 146 return -ENOMEM;
147 147
148 dev = backlight_device_register("omap-bl", &pdev->dev, bl, &omapbl_ops); 148 memset(&props, 0, sizeof(struct backlight_properties));
149 props.max_brightness = OMAPBL_MAX_INTENSITY;
150 dev = backlight_device_register("omap-bl", &pdev->dev, bl, &omapbl_ops,
151 &props);
149 if (IS_ERR(dev)) { 152 if (IS_ERR(dev)) {
150 kfree(bl); 153 kfree(bl);
151 return PTR_ERR(dev); 154 return PTR_ERR(dev);
@@ -162,7 +165,6 @@ static int omapbl_probe(struct platform_device *pdev)
162 omap_cfg_reg(PWL); /* Conflicts with UART3 */ 165 omap_cfg_reg(PWL); /* Conflicts with UART3 */
163 166
164 dev->props.fb_blank = FB_BLANK_UNBLANK; 167 dev->props.fb_blank = FB_BLANK_UNBLANK;
165 dev->props.max_brightness = OMAPBL_MAX_INTENSITY;
166 dev->props.brightness = pdata->default_intensity; 168 dev->props.brightness = pdata->default_intensity;
167 omapbl_update_status(dev); 169 omapbl_update_status(dev);
168 170
diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c
index 738694d23889..302330acf628 100644
--- a/drivers/video/backlight/platform_lcd.c
+++ b/drivers/video/backlight/platform_lcd.c
@@ -16,6 +16,7 @@
16#include <linux/fb.h> 16#include <linux/fb.h>
17#include <linux/backlight.h> 17#include <linux/backlight.h>
18#include <linux/lcd.h> 18#include <linux/lcd.h>
19#include <linux/slab.h>
19 20
20#include <video/platform_lcd.h> 21#include <video/platform_lcd.h>
21 22
diff --git a/drivers/video/backlight/progear_bl.c b/drivers/video/backlight/progear_bl.c
index 9edaf24fd82d..809278c90738 100644
--- a/drivers/video/backlight/progear_bl.c
+++ b/drivers/video/backlight/progear_bl.c
@@ -54,15 +54,17 @@ static int progearbl_get_intensity(struct backlight_device *bd)
54 return intensity - HW_LEVEL_MIN; 54 return intensity - HW_LEVEL_MIN;
55} 55}
56 56
57static struct backlight_ops progearbl_ops = { 57static const struct backlight_ops progearbl_ops = {
58 .get_brightness = progearbl_get_intensity, 58 .get_brightness = progearbl_get_intensity,
59 .update_status = progearbl_set_intensity, 59 .update_status = progearbl_set_intensity,
60}; 60};
61 61
62static int progearbl_probe(struct platform_device *pdev) 62static int progearbl_probe(struct platform_device *pdev)
63{ 63{
64 struct backlight_properties props;
64 u8 temp; 65 u8 temp;
65 struct backlight_device *progear_backlight_device; 66 struct backlight_device *progear_backlight_device;
67 int ret;
66 68
67 pmu_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, NULL); 69 pmu_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, NULL);
68 if (!pmu_dev) { 70 if (!pmu_dev) {
@@ -73,28 +75,37 @@ static int progearbl_probe(struct platform_device *pdev)
73 sb_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); 75 sb_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
74 if (!sb_dev) { 76 if (!sb_dev) {
75 printk("ALI 1533 SB not found.\n"); 77 printk("ALI 1533 SB not found.\n");
76 pci_dev_put(pmu_dev); 78 ret = -ENODEV;
77 return -ENODEV; 79 goto put_pmu;
78 } 80 }
79 81
80 /* Set SB_MPS1 to enable brightness control. */ 82 /* Set SB_MPS1 to enable brightness control. */
81 pci_read_config_byte(sb_dev, SB_MPS1, &temp); 83 pci_read_config_byte(sb_dev, SB_MPS1, &temp);
82 pci_write_config_byte(sb_dev, SB_MPS1, temp | 0x20); 84 pci_write_config_byte(sb_dev, SB_MPS1, temp | 0x20);
83 85
86 memset(&props, 0, sizeof(struct backlight_properties));
87 props.max_brightness = HW_LEVEL_MAX - HW_LEVEL_MIN;
84 progear_backlight_device = backlight_device_register("progear-bl", 88 progear_backlight_device = backlight_device_register("progear-bl",
85 &pdev->dev, NULL, 89 &pdev->dev, NULL,
86 &progearbl_ops); 90 &progearbl_ops,
87 if (IS_ERR(progear_backlight_device)) 91 &props);
88 return PTR_ERR(progear_backlight_device); 92 if (IS_ERR(progear_backlight_device)) {
93 ret = PTR_ERR(progear_backlight_device);
94 goto put_sb;
95 }
89 96
90 platform_set_drvdata(pdev, progear_backlight_device); 97 platform_set_drvdata(pdev, progear_backlight_device);
91 98
92 progear_backlight_device->props.power = FB_BLANK_UNBLANK; 99 progear_backlight_device->props.power = FB_BLANK_UNBLANK;
93 progear_backlight_device->props.brightness = HW_LEVEL_MAX - HW_LEVEL_MIN; 100 progear_backlight_device->props.brightness = HW_LEVEL_MAX - HW_LEVEL_MIN;
94 progear_backlight_device->props.max_brightness = HW_LEVEL_MAX - HW_LEVEL_MIN;
95 progearbl_set_intensity(progear_backlight_device); 101 progearbl_set_intensity(progear_backlight_device);
96 102
97 return 0; 103 return 0;
104put_sb:
105 pci_dev_put(sb_dev);
106put_pmu:
107 pci_dev_put(pmu_dev);
108 return ret;
98} 109}
99 110
100static int progearbl_remove(struct platform_device *pdev) 111static int progearbl_remove(struct platform_device *pdev)
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index 887166267443..550443518891 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -19,11 +19,14 @@
19#include <linux/err.h> 19#include <linux/err.h>
20#include <linux/pwm.h> 20#include <linux/pwm.h>
21#include <linux/pwm_backlight.h> 21#include <linux/pwm_backlight.h>
22#include <linux/slab.h>
22 23
23struct pwm_bl_data { 24struct pwm_bl_data {
24 struct pwm_device *pwm; 25 struct pwm_device *pwm;
26 struct device *dev;
25 unsigned int period; 27 unsigned int period;
26 int (*notify)(int brightness); 28 int (*notify)(struct device *,
29 int brightness);
27}; 30};
28 31
29static int pwm_backlight_update_status(struct backlight_device *bl) 32static int pwm_backlight_update_status(struct backlight_device *bl)
@@ -39,7 +42,7 @@ static int pwm_backlight_update_status(struct backlight_device *bl)
39 brightness = 0; 42 brightness = 0;
40 43
41 if (pb->notify) 44 if (pb->notify)
42 brightness = pb->notify(brightness); 45 brightness = pb->notify(pb->dev, brightness);
43 46
44 if (brightness == 0) { 47 if (brightness == 0) {
45 pwm_config(pb->pwm, 0, pb->period); 48 pwm_config(pb->pwm, 0, pb->period);
@@ -56,13 +59,14 @@ static int pwm_backlight_get_brightness(struct backlight_device *bl)
56 return bl->props.brightness; 59 return bl->props.brightness;
57} 60}
58 61
59static struct backlight_ops pwm_backlight_ops = { 62static const struct backlight_ops pwm_backlight_ops = {
60 .update_status = pwm_backlight_update_status, 63 .update_status = pwm_backlight_update_status,
61 .get_brightness = pwm_backlight_get_brightness, 64 .get_brightness = pwm_backlight_get_brightness,
62}; 65};
63 66
64static int pwm_backlight_probe(struct platform_device *pdev) 67static int pwm_backlight_probe(struct platform_device *pdev)
65{ 68{
69 struct backlight_properties props;
66 struct platform_pwm_backlight_data *data = pdev->dev.platform_data; 70 struct platform_pwm_backlight_data *data = pdev->dev.platform_data;
67 struct backlight_device *bl; 71 struct backlight_device *bl;
68 struct pwm_bl_data *pb; 72 struct pwm_bl_data *pb;
@@ -88,6 +92,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
88 92
89 pb->period = data->pwm_period_ns; 93 pb->period = data->pwm_period_ns;
90 pb->notify = data->notify; 94 pb->notify = data->notify;
95 pb->dev = &pdev->dev;
91 96
92 pb->pwm = pwm_request(data->pwm_id, "backlight"); 97 pb->pwm = pwm_request(data->pwm_id, "backlight");
93 if (IS_ERR(pb->pwm)) { 98 if (IS_ERR(pb->pwm)) {
@@ -97,15 +102,16 @@ static int pwm_backlight_probe(struct platform_device *pdev)
97 } else 102 } else
98 dev_dbg(&pdev->dev, "got pwm for backlight\n"); 103 dev_dbg(&pdev->dev, "got pwm for backlight\n");
99 104
100 bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, 105 memset(&props, 0, sizeof(struct backlight_properties));
101 pb, &pwm_backlight_ops); 106 props.max_brightness = data->max_brightness;
107 bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, pb,
108 &pwm_backlight_ops, &props);
102 if (IS_ERR(bl)) { 109 if (IS_ERR(bl)) {
103 dev_err(&pdev->dev, "failed to register backlight\n"); 110 dev_err(&pdev->dev, "failed to register backlight\n");
104 ret = PTR_ERR(bl); 111 ret = PTR_ERR(bl);
105 goto err_bl; 112 goto err_bl;
106 } 113 }
107 114
108 bl->props.max_brightness = data->max_brightness;
109 bl->props.brightness = data->dft_brightness; 115 bl->props.brightness = data->dft_brightness;
110 backlight_update_status(bl); 116 backlight_update_status(bl);
111 117
@@ -146,7 +152,7 @@ static int pwm_backlight_suspend(struct platform_device *pdev,
146 struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev); 152 struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev);
147 153
148 if (pb->notify) 154 if (pb->notify)
149 pb->notify(0); 155 pb->notify(pb->dev, 0);
150 pwm_config(pb->pwm, 0, pb->period); 156 pwm_config(pb->pwm, 0, pb->period);
151 pwm_disable(pb->pwm); 157 pwm_disable(pb->pwm);
152 return 0; 158 return 0;
diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c
index bbfb502add67..1997e12a1057 100644
--- a/drivers/video/backlight/tdo24m.c
+++ b/drivers/video/backlight/tdo24m.c
@@ -17,6 +17,7 @@
17#include <linux/spi/tdo24m.h> 17#include <linux/spi/tdo24m.h>
18#include <linux/fb.h> 18#include <linux/fb.h>
19#include <linux/lcd.h> 19#include <linux/lcd.h>
20#include <linux/slab.h>
20 21
21#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) 22#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL)
22 23
@@ -367,6 +368,7 @@ static int __devinit tdo24m_probe(struct spi_device *spi)
367 368
368 spi_message_init(m); 369 spi_message_init(m);
369 370
371 x->cs_change = 1;
370 x->tx_buf = &lcd->buf[0]; 372 x->tx_buf = &lcd->buf[0];
371 spi_message_add_tail(x, m); 373 spi_message_add_tail(x, m);
372 374
diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c
index 43edbada12d1..e03e60bbfd85 100644
--- a/drivers/video/backlight/tosa_bl.c
+++ b/drivers/video/backlight/tosa_bl.c
@@ -18,6 +18,7 @@
18#include <linux/gpio.h> 18#include <linux/gpio.h>
19#include <linux/fb.h> 19#include <linux/fb.h>
20#include <linux/backlight.h> 20#include <linux/backlight.h>
21#include <linux/slab.h>
21 22
22#include <asm/mach/sharpsl_param.h> 23#include <asm/mach/sharpsl_param.h>
23 24
@@ -72,7 +73,7 @@ static int tosa_bl_get_brightness(struct backlight_device *dev)
72 return props->brightness; 73 return props->brightness;
73} 74}
74 75
75static struct backlight_ops bl_ops = { 76static const struct backlight_ops bl_ops = {
76 .get_brightness = tosa_bl_get_brightness, 77 .get_brightness = tosa_bl_get_brightness,
77 .update_status = tosa_bl_update_status, 78 .update_status = tosa_bl_update_status,
78}; 79};
@@ -80,6 +81,7 @@ static struct backlight_ops bl_ops = {
80static int __devinit tosa_bl_probe(struct i2c_client *client, 81static int __devinit tosa_bl_probe(struct i2c_client *client,
81 const struct i2c_device_id *id) 82 const struct i2c_device_id *id)
82{ 83{
84 struct backlight_properties props;
83 struct tosa_bl_data *data = kzalloc(sizeof(struct tosa_bl_data), GFP_KERNEL); 85 struct tosa_bl_data *data = kzalloc(sizeof(struct tosa_bl_data), GFP_KERNEL);
84 int ret = 0; 86 int ret = 0;
85 if (!data) 87 if (!data)
@@ -99,15 +101,16 @@ static int __devinit tosa_bl_probe(struct i2c_client *client,
99 i2c_set_clientdata(client, data); 101 i2c_set_clientdata(client, data);
100 data->i2c = client; 102 data->i2c = client;
101 103
102 data->bl = backlight_device_register("tosa-bl", &client->dev, 104 memset(&props, 0, sizeof(struct backlight_properties));
103 data, &bl_ops); 105 props.max_brightness = 512 - 1;
106 data->bl = backlight_device_register("tosa-bl", &client->dev, data,
107 &bl_ops, &props);
104 if (IS_ERR(data->bl)) { 108 if (IS_ERR(data->bl)) {
105 ret = PTR_ERR(data->bl); 109 ret = PTR_ERR(data->bl);
106 goto err_reg; 110 goto err_reg;
107 } 111 }
108 112
109 data->bl->props.brightness = 69; 113 data->bl->props.brightness = 69;
110 data->bl->props.max_brightness = 512 - 1;
111 data->bl->props.power = FB_BLANK_UNBLANK; 114 data->bl->props.power = FB_BLANK_UNBLANK;
112 115
113 backlight_update_status(data->bl); 116 backlight_update_status(data->bl);
diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c
index 50ec17dfc517..772f6015219a 100644
--- a/drivers/video/backlight/tosa_lcd.c
+++ b/drivers/video/backlight/tosa_lcd.c
@@ -15,6 +15,7 @@
15#include <linux/device.h> 15#include <linux/device.h>
16#include <linux/spi/spi.h> 16#include <linux/spi/spi.h>
17#include <linux/i2c.h> 17#include <linux/i2c.h>
18#include <linux/slab.h>
18#include <linux/gpio.h> 19#include <linux/gpio.h>
19#include <linux/delay.h> 20#include <linux/delay.h>
20#include <linux/lcd.h> 21#include <linux/lcd.h>
@@ -177,7 +178,7 @@ static int __devinit tosa_lcd_probe(struct spi_device *spi)
177 if (!data) 178 if (!data)
178 return -ENOMEM; 179 return -ENOMEM;
179 180
180 data->is_vga = true; /* defaut to VGA mode */ 181 data->is_vga = true; /* default to VGA mode */
181 182
182 /* 183 /*
183 * bits_per_word cannot be configured in platform data 184 * bits_per_word cannot be configured in platform data
diff --git a/drivers/video/backlight/wm831x_bl.c b/drivers/video/backlight/wm831x_bl.c
index 467bdb7efb23..08fd87f3aecc 100644
--- a/drivers/video/backlight/wm831x_bl.c
+++ b/drivers/video/backlight/wm831x_bl.c
@@ -13,6 +13,7 @@
13#include <linux/platform_device.h> 13#include <linux/platform_device.h>
14#include <linux/fb.h> 14#include <linux/fb.h>
15#include <linux/backlight.h> 15#include <linux/backlight.h>
16#include <linux/slab.h>
16 17
17#include <linux/mfd/wm831x/core.h> 18#include <linux/mfd/wm831x/core.h>
18#include <linux/mfd/wm831x/pdata.h> 19#include <linux/mfd/wm831x/pdata.h>
@@ -112,7 +113,7 @@ static int wm831x_backlight_get_brightness(struct backlight_device *bl)
112 return data->current_brightness; 113 return data->current_brightness;
113} 114}
114 115
115static struct backlight_ops wm831x_backlight_ops = { 116static const struct backlight_ops wm831x_backlight_ops = {
116 .options = BL_CORE_SUSPENDRESUME, 117 .options = BL_CORE_SUSPENDRESUME,
117 .update_status = wm831x_backlight_update_status, 118 .update_status = wm831x_backlight_update_status,
118 .get_brightness = wm831x_backlight_get_brightness, 119 .get_brightness = wm831x_backlight_get_brightness,
@@ -125,6 +126,7 @@ static int wm831x_backlight_probe(struct platform_device *pdev)
125 struct wm831x_backlight_pdata *pdata; 126 struct wm831x_backlight_pdata *pdata;
126 struct wm831x_backlight_data *data; 127 struct wm831x_backlight_data *data;
127 struct backlight_device *bl; 128 struct backlight_device *bl;
129 struct backlight_properties props;
128 int ret, i, max_isel, isink_reg, dcdc_cfg; 130 int ret, i, max_isel, isink_reg, dcdc_cfg;
129 131
130 /* We need platform data */ 132 /* We need platform data */
@@ -191,15 +193,15 @@ static int wm831x_backlight_probe(struct platform_device *pdev)
191 data->current_brightness = 0; 193 data->current_brightness = 0;
192 data->isink_reg = isink_reg; 194 data->isink_reg = isink_reg;
193 195
194 bl = backlight_device_register("wm831x", &pdev->dev, 196 props.max_brightness = max_isel;
195 data, &wm831x_backlight_ops); 197 bl = backlight_device_register("wm831x", &pdev->dev, data,
198 &wm831x_backlight_ops, &props);
196 if (IS_ERR(bl)) { 199 if (IS_ERR(bl)) {
197 dev_err(&pdev->dev, "failed to register backlight\n"); 200 dev_err(&pdev->dev, "failed to register backlight\n");
198 kfree(data); 201 kfree(data);
199 return PTR_ERR(bl); 202 return PTR_ERR(bl);
200 } 203 }
201 204
202 bl->props.max_brightness = max_isel;
203 bl->props.brightness = max_isel; 205 bl->props.brightness = max_isel;
204 206
205 platform_set_drvdata(pdev, bl); 207 platform_set_drvdata(pdev, bl);
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c
index e49ae5edcc00..23b2a8c0dbfc 100644
--- a/drivers/video/bf54x-lq043fb.c
+++ b/drivers/video/bf54x-lq043fb.c
@@ -82,7 +82,6 @@ struct bfin_bf54xfb_info {
82 unsigned char *fb_buffer; /* RGB Buffer */ 82 unsigned char *fb_buffer; /* RGB Buffer */
83 83
84 dma_addr_t dma_handle; 84 dma_addr_t dma_handle;
85 int lq043_mmap;
86 int lq043_open_cnt; 85 int lq043_open_cnt;
87 int irq; 86 int irq;
88 spinlock_t lock; /* lock */ 87 spinlock_t lock; /* lock */
@@ -316,7 +315,6 @@ static int bfin_bf54x_fb_release(struct fb_info *info, int user)
316 spin_lock(&fbi->lock); 315 spin_lock(&fbi->lock);
317 316
318 fbi->lq043_open_cnt--; 317 fbi->lq043_open_cnt--;
319 fbi->lq043_mmap = 0;
320 318
321 if (fbi->lq043_open_cnt <= 0) { 319 if (fbi->lq043_open_cnt <= 0) {
322 320
@@ -374,33 +372,6 @@ static int bfin_bf54x_fb_check_var(struct fb_var_screeninfo *var,
374 return 0; 372 return 0;
375} 373}
376 374
377static int bfin_bf54x_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
378{
379
380 struct bfin_bf54xfb_info *fbi = info->par;
381
382 if (fbi->lq043_mmap)
383 return -1;
384
385 spin_lock(&fbi->lock);
386 fbi->lq043_mmap = 1;
387 spin_unlock(&fbi->lock);
388
389 vma->vm_start = (unsigned long)(fbi->fb_buffer);
390
391 vma->vm_end = vma->vm_start + info->fix.smem_len;
392 /* For those who don't understand how mmap works, go read
393 * Documentation/nommu-mmap.txt.
394 * For those that do, you will know that the VM_MAYSHARE flag
395 * must be set in the vma->vm_flags structure on noMMU
396 * Other flags can be set, and are documented in
397 * include/linux/mm.h
398 */
399 vma->vm_flags |= VM_MAYSHARE | VM_SHARED;
400
401 return 0;
402}
403
404int bfin_bf54x_fb_cursor(struct fb_info *info, struct fb_cursor *cursor) 375int bfin_bf54x_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
405{ 376{
406 if (nocursor) 377 if (nocursor)
@@ -452,7 +423,6 @@ static struct fb_ops bfin_bf54x_fb_ops = {
452 .fb_fillrect = cfb_fillrect, 423 .fb_fillrect = cfb_fillrect,
453 .fb_copyarea = cfb_copyarea, 424 .fb_copyarea = cfb_copyarea,
454 .fb_imageblit = cfb_imageblit, 425 .fb_imageblit = cfb_imageblit,
455 .fb_mmap = bfin_bf54x_fb_mmap,
456 .fb_cursor = bfin_bf54x_fb_cursor, 426 .fb_cursor = bfin_bf54x_fb_cursor,
457 .fb_setcolreg = bfin_bf54x_fb_setcolreg, 427 .fb_setcolreg = bfin_bf54x_fb_setcolreg,
458}; 428};
@@ -463,7 +433,7 @@ static int bl_get_brightness(struct backlight_device *bd)
463 return 0; 433 return 0;
464} 434}
465 435
466static struct backlight_ops bfin_lq043fb_bl_ops = { 436static const struct backlight_ops bfin_lq043fb_bl_ops = {
467 .get_brightness = bl_get_brightness, 437 .get_brightness = bl_get_brightness,
468}; 438};
469 439
@@ -531,6 +501,7 @@ static irqreturn_t bfin_bf54x_irq_error(int irq, void *dev_id)
531 501
532static int __devinit bfin_bf54x_probe(struct platform_device *pdev) 502static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
533{ 503{
504 struct backlight_properties props;
534 struct bfin_bf54xfb_info *info; 505 struct bfin_bf54xfb_info *info;
535 struct fb_info *fbinfo; 506 struct fb_info *fbinfo;
536 int ret; 507 int ret;
@@ -675,10 +646,16 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
675 goto out8; 646 goto out8;
676 } 647 }
677#ifndef NO_BL_SUPPORT 648#ifndef NO_BL_SUPPORT
678 bl_dev = 649 memset(&props, 0, sizeof(struct backlight_properties));
679 backlight_device_register("bf54x-bl", NULL, NULL, 650 props.max_brightness = 255;
680 &bfin_lq043fb_bl_ops); 651 bl_dev = backlight_device_register("bf54x-bl", NULL, NULL,
681 bl_dev->props.max_brightness = 255; 652 &bfin_lq043fb_bl_ops, &props);
653 if (IS_ERR(bl_dev)) {
654 printk(KERN_ERR DRIVER_NAME
655 ": unable to register backlight.\n");
656 ret = -EINVAL;
657 goto out9;
658 }
682 659
683 lcd_dev = lcd_device_register(DRIVER_NAME, &pdev->dev, NULL, &bfin_lcd_ops); 660 lcd_dev = lcd_device_register(DRIVER_NAME, &pdev->dev, NULL, &bfin_lcd_ops);
684 lcd_dev->props.max_contrast = 255, printk(KERN_INFO "Done.\n"); 661 lcd_dev->props.max_contrast = 255, printk(KERN_INFO "Done.\n");
@@ -686,6 +663,8 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
686 663
687 return 0; 664 return 0;
688 665
666out9:
667 unregister_framebuffer(fbinfo);
689out8: 668out8:
690 free_irq(info->irq, info); 669 free_irq(info->irq, info);
691out7: 670out7:
diff --git a/drivers/video/bfin-lq035q1-fb.c b/drivers/video/bfin-lq035q1-fb.c
new file mode 100644
index 000000000000..2baac7cc1425
--- /dev/null
+++ b/drivers/video/bfin-lq035q1-fb.c
@@ -0,0 +1,826 @@
1/*
2 * Blackfin LCD Framebuffer driver SHARP LQ035Q1DH02
3 *
4 * Copyright 2008-2009 Analog Devices Inc.
5 * Licensed under the GPL-2 or later.
6 */
7
8#define DRIVER_NAME "bfin-lq035q1"
9#define pr_fmt(fmt) DRIVER_NAME ": " 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/fb.h>
16#include <linux/slab.h>
17#include <linux/init.h>
18#include <linux/types.h>
19#include <linux/interrupt.h>
20#include <linux/device.h>
21#include <linux/backlight.h>
22#include <linux/lcd.h>
23#include <linux/dma-mapping.h>
24#include <linux/platform_device.h>
25#include <linux/spi/spi.h>
26
27#include <asm/blackfin.h>
28#include <asm/irq.h>
29#include <asm/dma.h>
30#include <asm/portmux.h>
31#include <asm/gptimers.h>
32
33#include <asm/bfin-lq035q1.h>
34
35#if defined(BF533_FAMILY) || defined(BF538_FAMILY)
36#define TIMER_HSYNC_id TIMER1_id
37#define TIMER_HSYNCbit TIMER1bit
38#define TIMER_HSYNC_STATUS_TRUN TIMER_STATUS_TRUN1
39#define TIMER_HSYNC_STATUS_TIMIL TIMER_STATUS_TIMIL1
40#define TIMER_HSYNC_STATUS_TOVF TIMER_STATUS_TOVF1
41
42#define TIMER_VSYNC_id TIMER2_id
43#define TIMER_VSYNCbit TIMER2bit
44#define TIMER_VSYNC_STATUS_TRUN TIMER_STATUS_TRUN2
45#define TIMER_VSYNC_STATUS_TIMIL TIMER_STATUS_TIMIL2
46#define TIMER_VSYNC_STATUS_TOVF TIMER_STATUS_TOVF2
47#else
48#define TIMER_HSYNC_id TIMER0_id
49#define TIMER_HSYNCbit TIMER0bit
50#define TIMER_HSYNC_STATUS_TRUN TIMER_STATUS_TRUN0
51#define TIMER_HSYNC_STATUS_TIMIL TIMER_STATUS_TIMIL0
52#define TIMER_HSYNC_STATUS_TOVF TIMER_STATUS_TOVF0
53
54#define TIMER_VSYNC_id TIMER1_id
55#define TIMER_VSYNCbit TIMER1bit
56#define TIMER_VSYNC_STATUS_TRUN TIMER_STATUS_TRUN1
57#define TIMER_VSYNC_STATUS_TIMIL TIMER_STATUS_TIMIL1
58#define TIMER_VSYNC_STATUS_TOVF TIMER_STATUS_TOVF1
59#endif
60
61#define LCD_X_RES 320 /* Horizontal Resolution */
62#define LCD_Y_RES 240 /* Vertical Resolution */
63#define DMA_BUS_SIZE 16
64
65#define USE_RGB565_16_BIT_PPI
66
67#ifdef USE_RGB565_16_BIT_PPI
68#define LCD_BPP 16 /* Bit Per Pixel */
69#define CLOCKS_PER_PIX 1
70#define CPLD_PIPELINE_DELAY_COR 0 /* NO CPLB */
71#endif
72
73/* Interface 16/18-bit TFT over an 8-bit wide PPI using a small Programmable Logic Device (CPLD)
74 * http://blackfin.uclinux.org/gf/project/stamp/frs/?action=FrsReleaseBrowse&frs_package_id=165
75 */
76
77#ifdef USE_RGB565_8_BIT_PPI
78#define LCD_BPP 16 /* Bit Per Pixel */
79#define CLOCKS_PER_PIX 2
80#define CPLD_PIPELINE_DELAY_COR 3 /* RGB565 */
81#endif
82
83#ifdef USE_RGB888_8_BIT_PPI
84#define LCD_BPP 24 /* Bit Per Pixel */
85#define CLOCKS_PER_PIX 3
86#define CPLD_PIPELINE_DELAY_COR 5 /* RGB888 */
87#endif
88
89 /*
90 * HS and VS timing parameters (all in number of PPI clk ticks)
91 */
92
93#define U_LINE 4 /* Blanking Lines */
94
95#define H_ACTPIX (LCD_X_RES * CLOCKS_PER_PIX) /* active horizontal pixel */
96#define H_PERIOD (336 * CLOCKS_PER_PIX) /* HS period */
97#define H_PULSE (2 * CLOCKS_PER_PIX) /* HS pulse width */
98#define H_START (7 * CLOCKS_PER_PIX + CPLD_PIPELINE_DELAY_COR) /* first valid pixel */
99
100#define V_LINES (LCD_Y_RES + U_LINE) /* total vertical lines */
101#define V_PULSE (2 * CLOCKS_PER_PIX) /* VS pulse width (1-5 H_PERIODs) */
102#define V_PERIOD (H_PERIOD * V_LINES) /* VS period */
103
104#define ACTIVE_VIDEO_MEM_OFFSET ((U_LINE / 2) * LCD_X_RES * (LCD_BPP / 8))
105
106#define BFIN_LCD_NBR_PALETTE_ENTRIES 256
107
108#define PPI_TX_MODE 0x2
109#define PPI_XFER_TYPE_11 0xC
110#define PPI_PORT_CFG_01 0x10
111#define PPI_POLS_1 0x8000
112
113#if (CLOCKS_PER_PIX > 1)
114#define PPI_PMODE (DLEN_8 | PACK_EN)
115#else
116#define PPI_PMODE (DLEN_16)
117#endif
118
119#define LQ035_INDEX 0x74
120#define LQ035_DATA 0x76
121
122#define LQ035_DRIVER_OUTPUT_CTL 0x1
123#define LQ035_SHUT_CTL 0x11
124
125#define LQ035_DRIVER_OUTPUT_MASK (LQ035_LR | LQ035_TB | LQ035_BGR | LQ035_REV)
126#define LQ035_DRIVER_OUTPUT_DEFAULT (0x2AEF & ~LQ035_DRIVER_OUTPUT_MASK)
127
128#define LQ035_SHUT (1 << 0) /* Shutdown */
129#define LQ035_ON (0 << 0) /* Shutdown */
130
131struct bfin_lq035q1fb_info {
132 struct fb_info *fb;
133 struct device *dev;
134 struct spi_driver spidrv;
135 struct bfin_lq035q1fb_disp_info *disp_info;
136 unsigned char *fb_buffer; /* RGB Buffer */
137 dma_addr_t dma_handle;
138 int lq035_open_cnt;
139 int irq;
140 spinlock_t lock; /* lock */
141 u32 pseudo_pal[16];
142};
143
144static int nocursor;
145module_param(nocursor, int, 0644);
146MODULE_PARM_DESC(nocursor, "cursor enable/disable");
147
148struct spi_control {
149 unsigned short mode;
150};
151
152static int lq035q1_control(struct spi_device *spi, unsigned char reg, unsigned short value)
153{
154 int ret;
155 u8 regs[3] = { LQ035_INDEX, 0, 0 };
156 u8 dat[3] = { LQ035_DATA, 0, 0 };
157
158 if (!spi)
159 return -ENODEV;
160
161 regs[2] = reg;
162 dat[1] = value >> 8;
163 dat[2] = value & 0xFF;
164
165 ret = spi_write(spi, regs, ARRAY_SIZE(regs));
166 ret |= spi_write(spi, dat, ARRAY_SIZE(dat));
167 return ret;
168}
169
170static int __devinit lq035q1_spidev_probe(struct spi_device *spi)
171{
172 int ret;
173 struct spi_control *ctl;
174 struct bfin_lq035q1fb_info *info = container_of(spi->dev.driver,
175 struct bfin_lq035q1fb_info,
176 spidrv.driver);
177
178 ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
179
180 if (!ctl)
181 return -ENOMEM;
182
183 ctl->mode = (info->disp_info->mode &
184 LQ035_DRIVER_OUTPUT_MASK) | LQ035_DRIVER_OUTPUT_DEFAULT;
185
186 ret = lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_ON);
187 ret |= lq035q1_control(spi, LQ035_DRIVER_OUTPUT_CTL, ctl->mode);
188 if (ret)
189 return ret;
190
191 spi_set_drvdata(spi, ctl);
192
193 return 0;
194}
195
196static int lq035q1_spidev_remove(struct spi_device *spi)
197{
198 return lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_SHUT);
199}
200
201#ifdef CONFIG_PM
202static int lq035q1_spidev_suspend(struct spi_device *spi, pm_message_t state)
203{
204 return lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_SHUT);
205}
206
207static int lq035q1_spidev_resume(struct spi_device *spi)
208{
209 int ret;
210 struct spi_control *ctl = spi_get_drvdata(spi);
211
212 ret = lq035q1_control(spi, LQ035_DRIVER_OUTPUT_CTL, ctl->mode);
213 if (ret)
214 return ret;
215
216 return lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_ON);
217}
218#else
219# define lq035q1_spidev_suspend NULL
220# define lq035q1_spidev_resume NULL
221#endif
222
223/* Power down all displays on reboot, poweroff or halt */
224static void lq035q1_spidev_shutdown(struct spi_device *spi)
225{
226 lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_SHUT);
227}
228
229static int lq035q1_backlight(struct bfin_lq035q1fb_info *info, unsigned arg)
230{
231 if (info->disp_info->use_bl)
232 gpio_set_value(info->disp_info->gpio_bl, arg);
233
234 return 0;
235}
236
237static void bfin_lq035q1_config_ppi(struct bfin_lq035q1fb_info *fbi)
238{
239 bfin_write_PPI_DELAY(H_START);
240 bfin_write_PPI_COUNT(H_ACTPIX - 1);
241 bfin_write_PPI_FRAME(V_LINES);
242
243 bfin_write_PPI_CONTROL(PPI_TX_MODE | /* output mode , PORT_DIR */
244 PPI_XFER_TYPE_11 | /* sync mode XFR_TYPE */
245 PPI_PORT_CFG_01 | /* two frame sync PORT_CFG */
246 PPI_PMODE | /* 8/16 bit data length / PACK_EN? */
247 PPI_POLS_1); /* faling edge syncs POLS */
248}
249
250static inline void bfin_lq035q1_disable_ppi(void)
251{
252 bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() & ~PORT_EN);
253}
254
255static inline void bfin_lq035q1_enable_ppi(void)
256{
257 bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
258}
259
260static void bfin_lq035q1_start_timers(void)
261{
262 enable_gptimers(TIMER_VSYNCbit | TIMER_HSYNCbit);
263}
264
265static void bfin_lq035q1_stop_timers(void)
266{
267 disable_gptimers(TIMER_HSYNCbit | TIMER_VSYNCbit);
268
269 set_gptimer_status(0, TIMER_HSYNC_STATUS_TRUN | TIMER_VSYNC_STATUS_TRUN |
270 TIMER_HSYNC_STATUS_TIMIL | TIMER_VSYNC_STATUS_TIMIL |
271 TIMER_HSYNC_STATUS_TOVF | TIMER_VSYNC_STATUS_TOVF);
272
273}
274
275static void bfin_lq035q1_init_timers(void)
276{
277
278 bfin_lq035q1_stop_timers();
279
280 set_gptimer_period(TIMER_HSYNC_id, H_PERIOD);
281 set_gptimer_pwidth(TIMER_HSYNC_id, H_PULSE);
282 set_gptimer_config(TIMER_HSYNC_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT |
283 TIMER_TIN_SEL | TIMER_CLK_SEL|
284 TIMER_EMU_RUN);
285
286 set_gptimer_period(TIMER_VSYNC_id, V_PERIOD);
287 set_gptimer_pwidth(TIMER_VSYNC_id, V_PULSE);
288 set_gptimer_config(TIMER_VSYNC_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT |
289 TIMER_TIN_SEL | TIMER_CLK_SEL |
290 TIMER_EMU_RUN);
291
292}
293
294static void bfin_lq035q1_config_dma(struct bfin_lq035q1fb_info *fbi)
295{
296
297 set_dma_config(CH_PPI,
298 set_bfin_dma_config(DIR_READ, DMA_FLOW_AUTO,
299 INTR_DISABLE, DIMENSION_2D,
300 DATA_SIZE_16,
301 DMA_NOSYNC_KEEP_DMA_BUF));
302 set_dma_x_count(CH_PPI, (LCD_X_RES * LCD_BPP) / DMA_BUS_SIZE);
303 set_dma_x_modify(CH_PPI, DMA_BUS_SIZE / 8);
304 set_dma_y_count(CH_PPI, V_LINES);
305
306 set_dma_y_modify(CH_PPI, DMA_BUS_SIZE / 8);
307 set_dma_start_addr(CH_PPI, (unsigned long)fbi->fb_buffer);
308
309}
310
311#if (CLOCKS_PER_PIX == 1)
312static const u16 ppi0_req_16[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
313 P_PPI0_D0, P_PPI0_D1, P_PPI0_D2,
314 P_PPI0_D3, P_PPI0_D4, P_PPI0_D5,
315 P_PPI0_D6, P_PPI0_D7, P_PPI0_D8,
316 P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
317 P_PPI0_D12, P_PPI0_D13, P_PPI0_D14,
318 P_PPI0_D15, 0};
319#else
320static const u16 ppi0_req_16[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
321 P_PPI0_D0, P_PPI0_D1, P_PPI0_D2,
322 P_PPI0_D3, P_PPI0_D4, P_PPI0_D5,
323 P_PPI0_D6, P_PPI0_D7, 0};
324#endif
325
326static inline void bfin_lq035q1_free_ports(void)
327{
328 peripheral_free_list(ppi0_req_16);
329 if (ANOMALY_05000400)
330 gpio_free(P_IDENT(P_PPI0_FS3));
331}
332
333static int __devinit bfin_lq035q1_request_ports(struct platform_device *pdev)
334{
335 /* ANOMALY_05000400 - PPI Does Not Start Properly In Specific Mode:
336 * Drive PPI_FS3 Low
337 */
338 if (ANOMALY_05000400) {
339 int ret = gpio_request(P_IDENT(P_PPI0_FS3), "PPI_FS3");
340 if (ret)
341 return ret;
342 gpio_direction_output(P_IDENT(P_PPI0_FS3), 0);
343 }
344
345 if (peripheral_request_list(ppi0_req_16, DRIVER_NAME)) {
346 dev_err(&pdev->dev, "requesting peripherals failed\n");
347 return -EFAULT;
348 }
349
350 return 0;
351}
352
353static int bfin_lq035q1_fb_open(struct fb_info *info, int user)
354{
355 struct bfin_lq035q1fb_info *fbi = info->par;
356
357 spin_lock(&fbi->lock);
358 fbi->lq035_open_cnt++;
359
360 if (fbi->lq035_open_cnt <= 1) {
361
362 bfin_lq035q1_disable_ppi();
363 SSYNC();
364
365 bfin_lq035q1_config_dma(fbi);
366 bfin_lq035q1_config_ppi(fbi);
367 bfin_lq035q1_init_timers();
368
369 /* start dma */
370 enable_dma(CH_PPI);
371 bfin_lq035q1_enable_ppi();
372 bfin_lq035q1_start_timers();
373 lq035q1_backlight(fbi, 1);
374 }
375
376 spin_unlock(&fbi->lock);
377
378 return 0;
379}
380
381static int bfin_lq035q1_fb_release(struct fb_info *info, int user)
382{
383 struct bfin_lq035q1fb_info *fbi = info->par;
384
385 spin_lock(&fbi->lock);
386
387 fbi->lq035_open_cnt--;
388
389 if (fbi->lq035_open_cnt <= 0) {
390 lq035q1_backlight(fbi, 0);
391 bfin_lq035q1_disable_ppi();
392 SSYNC();
393 disable_dma(CH_PPI);
394 bfin_lq035q1_stop_timers();
395 }
396
397 spin_unlock(&fbi->lock);
398
399 return 0;
400}
401
402static int bfin_lq035q1_fb_check_var(struct fb_var_screeninfo *var,
403 struct fb_info *info)
404{
405 switch (var->bits_per_pixel) {
406#if (LCD_BPP == 24)
407 case 24:/* TRUECOLOUR, 16m */
408#else
409 case 16:/* DIRECTCOLOUR, 64k */
410#endif
411 var->red.offset = info->var.red.offset;
412 var->green.offset = info->var.green.offset;
413 var->blue.offset = info->var.blue.offset;
414 var->red.length = info->var.red.length;
415 var->green.length = info->var.green.length;
416 var->blue.length = info->var.blue.length;
417 var->transp.offset = 0;
418 var->transp.length = 0;
419 var->transp.msb_right = 0;
420 var->red.msb_right = 0;
421 var->green.msb_right = 0;
422 var->blue.msb_right = 0;
423 break;
424 default:
425 pr_debug("%s: depth not supported: %u BPP\n", __func__,
426 var->bits_per_pixel);
427 return -EINVAL;
428 }
429
430 if (info->var.xres != var->xres || info->var.yres != var->yres ||
431 info->var.xres_virtual != var->xres_virtual ||
432 info->var.yres_virtual != var->yres_virtual) {
433 pr_debug("%s: Resolution not supported: X%u x Y%u \n",
434 __func__, var->xres, var->yres);
435 return -EINVAL;
436 }
437
438 /*
439 * Memory limit
440 */
441
442 if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
443 pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
444 __func__, var->yres_virtual);
445 return -ENOMEM;
446 }
447
448
449 return 0;
450}
451
452int bfin_lq035q1_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
453{
454 if (nocursor)
455 return 0;
456 else
457 return -EINVAL; /* just to force soft_cursor() call */
458}
459
460static int bfin_lq035q1_fb_setcolreg(u_int regno, u_int red, u_int green,
461 u_int blue, u_int transp,
462 struct fb_info *info)
463{
464 if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES)
465 return -EINVAL;
466
467 if (info->var.grayscale) {
468 /* grayscale = 0.30*R + 0.59*G + 0.11*B */
469 red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
470 }
471
472 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
473
474 u32 value;
475 /* Place color in the pseudopalette */
476 if (regno > 16)
477 return -EINVAL;
478
479 red >>= (16 - info->var.red.length);
480 green >>= (16 - info->var.green.length);
481 blue >>= (16 - info->var.blue.length);
482
483 value = (red << info->var.red.offset) |
484 (green << info->var.green.offset) |
485 (blue << info->var.blue.offset);
486 value &= 0xFFFFFF;
487
488 ((u32 *) (info->pseudo_palette))[regno] = value;
489
490 }
491
492 return 0;
493}
494
495static struct fb_ops bfin_lq035q1_fb_ops = {
496 .owner = THIS_MODULE,
497 .fb_open = bfin_lq035q1_fb_open,
498 .fb_release = bfin_lq035q1_fb_release,
499 .fb_check_var = bfin_lq035q1_fb_check_var,
500 .fb_fillrect = cfb_fillrect,
501 .fb_copyarea = cfb_copyarea,
502 .fb_imageblit = cfb_imageblit,
503 .fb_cursor = bfin_lq035q1_fb_cursor,
504 .fb_setcolreg = bfin_lq035q1_fb_setcolreg,
505};
506
507static irqreturn_t bfin_lq035q1_irq_error(int irq, void *dev_id)
508{
509 /*struct bfin_lq035q1fb_info *info = (struct bfin_lq035q1fb_info *)dev_id;*/
510
511 u16 status = bfin_read_PPI_STATUS();
512 bfin_write_PPI_STATUS(-1);
513
514 if (status) {
515 bfin_lq035q1_disable_ppi();
516 disable_dma(CH_PPI);
517
518 /* start dma */
519 enable_dma(CH_PPI);
520 bfin_lq035q1_enable_ppi();
521 bfin_write_PPI_STATUS(-1);
522 }
523
524 return IRQ_HANDLED;
525}
526
527static int __devinit bfin_lq035q1_probe(struct platform_device *pdev)
528{
529 struct bfin_lq035q1fb_info *info;
530 struct fb_info *fbinfo;
531 int ret;
532
533 ret = request_dma(CH_PPI, DRIVER_NAME"_CH_PPI");
534 if (ret < 0) {
535 dev_err(&pdev->dev, "PPI DMA unavailable\n");
536 goto out1;
537 }
538
539 fbinfo = framebuffer_alloc(sizeof(*info), &pdev->dev);
540 if (!fbinfo) {
541 ret = -ENOMEM;
542 goto out2;
543 }
544
545 info = fbinfo->par;
546 info->fb = fbinfo;
547 info->dev = &pdev->dev;
548
549 info->disp_info = pdev->dev.platform_data;
550
551 platform_set_drvdata(pdev, fbinfo);
552
553 strcpy(fbinfo->fix.id, DRIVER_NAME);
554
555 fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
556 fbinfo->fix.type_aux = 0;
557 fbinfo->fix.xpanstep = 0;
558 fbinfo->fix.ypanstep = 0;
559 fbinfo->fix.ywrapstep = 0;
560 fbinfo->fix.accel = FB_ACCEL_NONE;
561 fbinfo->fix.visual = FB_VISUAL_TRUECOLOR;
562
563 fbinfo->var.nonstd = 0;
564 fbinfo->var.activate = FB_ACTIVATE_NOW;
565 fbinfo->var.height = -1;
566 fbinfo->var.width = -1;
567 fbinfo->var.accel_flags = 0;
568 fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
569
570 fbinfo->var.xres = LCD_X_RES;
571 fbinfo->var.xres_virtual = LCD_X_RES;
572 fbinfo->var.yres = LCD_Y_RES;
573 fbinfo->var.yres_virtual = LCD_Y_RES;
574 fbinfo->var.bits_per_pixel = LCD_BPP;
575
576 if (info->disp_info->mode & LQ035_BGR) {
577#if (LCD_BPP == 24)
578 fbinfo->var.red.offset = 0;
579 fbinfo->var.green.offset = 8;
580 fbinfo->var.blue.offset = 16;
581#else
582 fbinfo->var.red.offset = 0;
583 fbinfo->var.green.offset = 5;
584 fbinfo->var.blue.offset = 11;
585#endif
586 } else {
587#if (LCD_BPP == 24)
588 fbinfo->var.red.offset = 16;
589 fbinfo->var.green.offset = 8;
590 fbinfo->var.blue.offset = 0;
591#else
592 fbinfo->var.red.offset = 11;
593 fbinfo->var.green.offset = 5;
594 fbinfo->var.blue.offset = 0;
595#endif
596 }
597
598 fbinfo->var.transp.offset = 0;
599
600#if (LCD_BPP == 24)
601 fbinfo->var.red.length = 8;
602 fbinfo->var.green.length = 8;
603 fbinfo->var.blue.length = 8;
604#else
605 fbinfo->var.red.length = 5;
606 fbinfo->var.green.length = 6;
607 fbinfo->var.blue.length = 5;
608#endif
609
610 fbinfo->var.transp.length = 0;
611
612 fbinfo->fix.smem_len = LCD_X_RES * LCD_Y_RES * LCD_BPP / 8
613 + ACTIVE_VIDEO_MEM_OFFSET;
614
615 fbinfo->fix.line_length = fbinfo->var.xres_virtual *
616 fbinfo->var.bits_per_pixel / 8;
617
618
619 fbinfo->fbops = &bfin_lq035q1_fb_ops;
620 fbinfo->flags = FBINFO_FLAG_DEFAULT;
621
622 info->fb_buffer =
623 dma_alloc_coherent(NULL, fbinfo->fix.smem_len, &info->dma_handle,
624 GFP_KERNEL);
625
626 if (NULL == info->fb_buffer) {
627 dev_err(&pdev->dev, "couldn't allocate dma buffer\n");
628 ret = -ENOMEM;
629 goto out3;
630 }
631
632 fbinfo->screen_base = (void *)info->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET;
633 fbinfo->fix.smem_start = (int)info->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET;
634
635 fbinfo->fbops = &bfin_lq035q1_fb_ops;
636
637 fbinfo->pseudo_palette = &info->pseudo_pal;
638
639 ret = fb_alloc_cmap(&fbinfo->cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0);
640 if (ret < 0) {
641 dev_err(&pdev->dev, "failed to allocate colormap (%d entries)\n",
642 BFIN_LCD_NBR_PALETTE_ENTRIES);
643 goto out4;
644 }
645
646 ret = bfin_lq035q1_request_ports(pdev);
647 if (ret) {
648 dev_err(&pdev->dev, "couldn't request gpio port\n");
649 goto out6;
650 }
651
652 info->irq = platform_get_irq(pdev, 0);
653 if (info->irq < 0) {
654 ret = -EINVAL;
655 goto out7;
656 }
657
658 ret = request_irq(info->irq, bfin_lq035q1_irq_error, IRQF_DISABLED,
659 DRIVER_NAME" PPI ERROR", info);
660 if (ret < 0) {
661 dev_err(&pdev->dev, "unable to request PPI ERROR IRQ\n");
662 goto out7;
663 }
664
665 info->spidrv.driver.name = DRIVER_NAME"-spi";
666 info->spidrv.probe = lq035q1_spidev_probe;
667 info->spidrv.remove = __devexit_p(lq035q1_spidev_remove);
668 info->spidrv.shutdown = lq035q1_spidev_shutdown;
669 info->spidrv.suspend = lq035q1_spidev_suspend;
670 info->spidrv.resume = lq035q1_spidev_resume;
671
672 ret = spi_register_driver(&info->spidrv);
673 if (ret < 0) {
674 dev_err(&pdev->dev, "couldn't register SPI Interface\n");
675 goto out8;
676 }
677
678 if (info->disp_info->use_bl) {
679 ret = gpio_request(info->disp_info->gpio_bl, "LQ035 Backlight");
680
681 if (ret) {
682 dev_err(&pdev->dev, "failed to request GPIO %d\n",
683 info->disp_info->gpio_bl);
684 goto out9;
685 }
686 gpio_direction_output(info->disp_info->gpio_bl, 0);
687 }
688
689 ret = register_framebuffer(fbinfo);
690 if (ret < 0) {
691 dev_err(&pdev->dev, "unable to register framebuffer\n");
692 goto out10;
693 }
694
695 dev_info(&pdev->dev, "%dx%d %d-bit RGB FrameBuffer initialized\n",
696 LCD_X_RES, LCD_Y_RES, LCD_BPP);
697
698 return 0;
699
700 out10:
701 if (info->disp_info->use_bl)
702 gpio_free(info->disp_info->gpio_bl);
703 out9:
704 spi_unregister_driver(&info->spidrv);
705 out8:
706 free_irq(info->irq, info);
707 out7:
708 bfin_lq035q1_free_ports();
709 out6:
710 fb_dealloc_cmap(&fbinfo->cmap);
711 out4:
712 dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
713 info->dma_handle);
714 out3:
715 framebuffer_release(fbinfo);
716 out2:
717 free_dma(CH_PPI);
718 out1:
719 platform_set_drvdata(pdev, NULL);
720
721 return ret;
722}
723
724static int __devexit bfin_lq035q1_remove(struct platform_device *pdev)
725{
726 struct fb_info *fbinfo = platform_get_drvdata(pdev);
727 struct bfin_lq035q1fb_info *info = fbinfo->par;
728
729 if (info->disp_info->use_bl)
730 gpio_free(info->disp_info->gpio_bl);
731
732 spi_unregister_driver(&info->spidrv);
733
734 unregister_framebuffer(fbinfo);
735
736 free_dma(CH_PPI);
737 free_irq(info->irq, info);
738
739 if (info->fb_buffer != NULL)
740 dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
741 info->dma_handle);
742
743 fb_dealloc_cmap(&fbinfo->cmap);
744
745 bfin_lq035q1_free_ports();
746
747 platform_set_drvdata(pdev, NULL);
748 framebuffer_release(fbinfo);
749
750 dev_info(&pdev->dev, "unregistered LCD driver\n");
751
752 return 0;
753}
754
755#ifdef CONFIG_PM
756static int bfin_lq035q1_suspend(struct device *dev)
757{
758 struct fb_info *fbinfo = dev_get_drvdata(dev);
759 struct bfin_lq035q1fb_info *info = fbinfo->par;
760
761 if (info->lq035_open_cnt) {
762 lq035q1_backlight(info, 0);
763 bfin_lq035q1_disable_ppi();
764 SSYNC();
765 disable_dma(CH_PPI);
766 bfin_lq035q1_stop_timers();
767 bfin_write_PPI_STATUS(-1);
768 }
769
770 return 0;
771}
772
773static int bfin_lq035q1_resume(struct device *dev)
774{
775 struct fb_info *fbinfo = dev_get_drvdata(dev);
776 struct bfin_lq035q1fb_info *info = fbinfo->par;
777
778 if (info->lq035_open_cnt) {
779 bfin_lq035q1_disable_ppi();
780 SSYNC();
781
782 bfin_lq035q1_config_dma(info);
783 bfin_lq035q1_config_ppi(info);
784 bfin_lq035q1_init_timers();
785
786 /* start dma */
787 enable_dma(CH_PPI);
788 bfin_lq035q1_enable_ppi();
789 bfin_lq035q1_start_timers();
790 lq035q1_backlight(info, 1);
791 }
792
793 return 0;
794}
795
796static struct dev_pm_ops bfin_lq035q1_dev_pm_ops = {
797 .suspend = bfin_lq035q1_suspend,
798 .resume = bfin_lq035q1_resume,
799};
800#endif
801
802static struct platform_driver bfin_lq035q1_driver = {
803 .probe = bfin_lq035q1_probe,
804 .remove = __devexit_p(bfin_lq035q1_remove),
805 .driver = {
806 .name = DRIVER_NAME,
807#ifdef CONFIG_PM
808 .pm = &bfin_lq035q1_dev_pm_ops,
809#endif
810 },
811};
812
813static int __init bfin_lq035q1_driver_init(void)
814{
815 return platform_driver_register(&bfin_lq035q1_driver);
816}
817module_init(bfin_lq035q1_driver_init);
818
819static void __exit bfin_lq035q1_driver_cleanup(void)
820{
821 platform_driver_unregister(&bfin_lq035q1_driver);
822}
823module_exit(bfin_lq035q1_driver_cleanup);
824
825MODULE_DESCRIPTION("Blackfin TFT LCD Driver");
826MODULE_LICENSE("GPL");
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c
index 5cc36cfbf07b..c2ec3dcd4e91 100644
--- a/drivers/video/bfin-t350mcqb-fb.c
+++ b/drivers/video/bfin-t350mcqb-fb.c
@@ -32,6 +32,7 @@
32#include <linux/kernel.h> 32#include <linux/kernel.h>
33#include <linux/errno.h> 33#include <linux/errno.h>
34#include <linux/string.h> 34#include <linux/string.h>
35#include <linux/gfp.h>
35#include <linux/fb.h> 36#include <linux/fb.h>
36#include <linux/init.h> 37#include <linux/init.h>
37#include <linux/types.h> 38#include <linux/types.h>
@@ -87,7 +88,6 @@ struct bfin_t350mcqbfb_info {
87 struct device *dev; 88 struct device *dev;
88 unsigned char *fb_buffer; /* RGB Buffer */ 89 unsigned char *fb_buffer; /* RGB Buffer */
89 dma_addr_t dma_handle; 90 dma_addr_t dma_handle;
90 int lq043_mmap;
91 int lq043_open_cnt; 91 int lq043_open_cnt;
92 int irq; 92 int irq;
93 spinlock_t lock; /* lock */ 93 spinlock_t lock; /* lock */
@@ -235,7 +235,6 @@ static int bfin_t350mcqb_fb_release(struct fb_info *info, int user)
235 spin_lock(&fbi->lock); 235 spin_lock(&fbi->lock);
236 236
237 fbi->lq043_open_cnt--; 237 fbi->lq043_open_cnt--;
238 fbi->lq043_mmap = 0;
239 238
240 if (fbi->lq043_open_cnt <= 0) { 239 if (fbi->lq043_open_cnt <= 0) {
241 bfin_t350mcqb_disable_ppi(); 240 bfin_t350mcqb_disable_ppi();
@@ -293,32 +292,6 @@ static int bfin_t350mcqb_fb_check_var(struct fb_var_screeninfo *var,
293 return 0; 292 return 0;
294} 293}
295 294
296static int bfin_t350mcqb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
297{
298 struct bfin_t350mcqbfb_info *fbi = info->par;
299
300 if (fbi->lq043_mmap)
301 return -1;
302
303 spin_lock(&fbi->lock);
304 fbi->lq043_mmap = 1;
305 spin_unlock(&fbi->lock);
306
307 vma->vm_start = (unsigned long)(fbi->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET);
308
309 vma->vm_end = vma->vm_start + info->fix.smem_len;
310 /* For those who don't understand how mmap works, go read
311 * Documentation/nommu-mmap.txt.
312 * For those that do, you will know that the VM_MAYSHARE flag
313 * must be set in the vma->vm_flags structure on noMMU
314 * Other flags can be set, and are documented in
315 * include/linux/mm.h
316 */
317 vma->vm_flags |= VM_MAYSHARE | VM_SHARED;
318
319 return 0;
320}
321
322int bfin_t350mcqb_fb_cursor(struct fb_info *info, struct fb_cursor *cursor) 295int bfin_t350mcqb_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
323{ 296{
324 if (nocursor) 297 if (nocursor)
@@ -370,7 +343,6 @@ static struct fb_ops bfin_t350mcqb_fb_ops = {
370 .fb_fillrect = cfb_fillrect, 343 .fb_fillrect = cfb_fillrect,
371 .fb_copyarea = cfb_copyarea, 344 .fb_copyarea = cfb_copyarea,
372 .fb_imageblit = cfb_imageblit, 345 .fb_imageblit = cfb_imageblit,
373 .fb_mmap = bfin_t350mcqb_fb_mmap,
374 .fb_cursor = bfin_t350mcqb_fb_cursor, 346 .fb_cursor = bfin_t350mcqb_fb_cursor,
375 .fb_setcolreg = bfin_t350mcqb_fb_setcolreg, 347 .fb_setcolreg = bfin_t350mcqb_fb_setcolreg,
376}; 348};
@@ -381,7 +353,7 @@ static int bl_get_brightness(struct backlight_device *bd)
381 return 0; 353 return 0;
382} 354}
383 355
384static struct backlight_ops bfin_lq043fb_bl_ops = { 356static const struct backlight_ops bfin_lq043fb_bl_ops = {
385 .get_brightness = bl_get_brightness, 357 .get_brightness = bl_get_brightness,
386}; 358};
387 359
@@ -448,6 +420,7 @@ static irqreturn_t bfin_t350mcqb_irq_error(int irq, void *dev_id)
448 420
449static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev) 421static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev)
450{ 422{
423 struct backlight_properties props;
451 struct bfin_t350mcqbfb_info *info; 424 struct bfin_t350mcqbfb_info *info;
452 struct fb_info *fbinfo; 425 struct fb_info *fbinfo;
453 int ret; 426 int ret;
@@ -487,8 +460,8 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev)
487 460
488 fbinfo->var.nonstd = 0; 461 fbinfo->var.nonstd = 0;
489 fbinfo->var.activate = FB_ACTIVATE_NOW; 462 fbinfo->var.activate = FB_ACTIVATE_NOW;
490 fbinfo->var.height = -1; 463 fbinfo->var.height = 53;
491 fbinfo->var.width = -1; 464 fbinfo->var.width = 70;
492 fbinfo->var.accel_flags = 0; 465 fbinfo->var.accel_flags = 0;
493 fbinfo->var.vmode = FB_VMODE_NONINTERLACED; 466 fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
494 467
@@ -515,9 +488,9 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev)
515 fbinfo->fbops = &bfin_t350mcqb_fb_ops; 488 fbinfo->fbops = &bfin_t350mcqb_fb_ops;
516 fbinfo->flags = FBINFO_FLAG_DEFAULT; 489 fbinfo->flags = FBINFO_FLAG_DEFAULT;
517 490
518 info->fb_buffer = 491 info->fb_buffer = dma_alloc_coherent(NULL, fbinfo->fix.smem_len +
519 dma_alloc_coherent(NULL, fbinfo->fix.smem_len, &info->dma_handle, 492 ACTIVE_VIDEO_MEM_OFFSET,
520 GFP_KERNEL); 493 &info->dma_handle, GFP_KERNEL);
521 494
522 if (NULL == info->fb_buffer) { 495 if (NULL == info->fb_buffer) {
523 printk(KERN_ERR DRIVER_NAME 496 printk(KERN_ERR DRIVER_NAME
@@ -569,10 +542,16 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev)
569 goto out8; 542 goto out8;
570 } 543 }
571#ifndef NO_BL_SUPPORT 544#ifndef NO_BL_SUPPORT
572 bl_dev = 545 memset(&props, 0, sizeof(struct backlight_properties));
573 backlight_device_register("bf52x-bl", NULL, NULL, 546 props.max_brightness = 255;
574 &bfin_lq043fb_bl_ops); 547 bl_dev = backlight_device_register("bf52x-bl", NULL, NULL,
575 bl_dev->props.max_brightness = 255; 548 &bfin_lq043fb_bl_ops, &props);
549 if (IS_ERR(bl_dev)) {
550 printk(KERN_ERR DRIVER_NAME
551 ": unable to register backlight.\n");
552 ret = -EINVAL;
553 goto out9;
554 }
576 555
577 lcd_dev = lcd_device_register(DRIVER_NAME, NULL, &bfin_lcd_ops); 556 lcd_dev = lcd_device_register(DRIVER_NAME, NULL, &bfin_lcd_ops);
578 lcd_dev->props.max_contrast = 255, printk(KERN_INFO "Done.\n"); 557 lcd_dev->props.max_contrast = 255, printk(KERN_INFO "Done.\n");
@@ -580,6 +559,8 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev)
580 559
581 return 0; 560 return 0;
582 561
562out9:
563 unregister_framebuffer(fbinfo);
583out8: 564out8:
584 free_irq(info->irq, info); 565 free_irq(info->irq, info);
585out7: 566out7:
@@ -587,8 +568,8 @@ out7:
587out6: 568out6:
588 fb_dealloc_cmap(&fbinfo->cmap); 569 fb_dealloc_cmap(&fbinfo->cmap);
589out4: 570out4:
590 dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer, 571 dma_free_coherent(NULL, fbinfo->fix.smem_len + ACTIVE_VIDEO_MEM_OFFSET,
591 info->dma_handle); 572 info->fb_buffer, info->dma_handle);
592out3: 573out3:
593 framebuffer_release(fbinfo); 574 framebuffer_release(fbinfo);
594out2: 575out2:
@@ -611,8 +592,9 @@ static int __devexit bfin_t350mcqb_remove(struct platform_device *pdev)
611 free_irq(info->irq, info); 592 free_irq(info->irq, info);
612 593
613 if (info->fb_buffer != NULL) 594 if (info->fb_buffer != NULL)
614 dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer, 595 dma_free_coherent(NULL, fbinfo->fix.smem_len +
615 info->dma_handle); 596 ACTIVE_VIDEO_MEM_OFFSET, info->fb_buffer,
597 info->dma_handle);
616 598
617 fb_dealloc_cmap(&fbinfo->cmap); 599 fb_dealloc_cmap(&fbinfo->cmap);
618 600
@@ -634,17 +616,35 @@ static int __devexit bfin_t350mcqb_remove(struct platform_device *pdev)
634#ifdef CONFIG_PM 616#ifdef CONFIG_PM
635static int bfin_t350mcqb_suspend(struct platform_device *pdev, pm_message_t state) 617static int bfin_t350mcqb_suspend(struct platform_device *pdev, pm_message_t state)
636{ 618{
637 bfin_t350mcqb_disable_ppi(); 619 struct fb_info *fbinfo = platform_get_drvdata(pdev);
638 disable_dma(CH_PPI); 620 struct bfin_t350mcqbfb_info *fbi = fbinfo->par;
639 bfin_write_PPI_STATUS(0xFFFF); 621
622 if (fbi->lq043_open_cnt) {
623 bfin_t350mcqb_disable_ppi();
624 disable_dma(CH_PPI);
625 bfin_t350mcqb_stop_timers();
626 bfin_write_PPI_STATUS(-1);
627 }
628
640 629
641 return 0; 630 return 0;
642} 631}
643 632
644static int bfin_t350mcqb_resume(struct platform_device *pdev) 633static int bfin_t350mcqb_resume(struct platform_device *pdev)
645{ 634{
646 enable_dma(CH_PPI); 635 struct fb_info *fbinfo = platform_get_drvdata(pdev);
647 bfin_t350mcqb_enable_ppi(); 636 struct bfin_t350mcqbfb_info *fbi = fbinfo->par;
637
638 if (fbi->lq043_open_cnt) {
639 bfin_t350mcqb_config_dma(fbi);
640 bfin_t350mcqb_config_ppi(fbi);
641 bfin_t350mcqb_init_timers();
642
643 /* start dma */
644 enable_dma(CH_PPI);
645 bfin_t350mcqb_enable_ppi();
646 bfin_t350mcqb_start_timers();
647 }
648 648
649 return 0; 649 return 0;
650} 650}
diff --git a/drivers/video/broadsheetfb.c b/drivers/video/broadsheetfb.c
index 509cb92e8731..ebda6876d3a9 100644
--- a/drivers/video/broadsheetfb.c
+++ b/drivers/video/broadsheetfb.c
@@ -29,11 +29,65 @@
29#include <linux/init.h> 29#include <linux/init.h>
30#include <linux/platform_device.h> 30#include <linux/platform_device.h>
31#include <linux/list.h> 31#include <linux/list.h>
32#include <linux/firmware.h>
32#include <linux/uaccess.h> 33#include <linux/uaccess.h>
33 34
34#include <video/broadsheetfb.h> 35#include <video/broadsheetfb.h>
35 36
36/* Display specific information */ 37/* track panel specific parameters */
38struct panel_info {
39 int w;
40 int h;
41 u16 sdcfg;
42 u16 gdcfg;
43 u16 lutfmt;
44 u16 fsynclen;
45 u16 fendfbegin;
46 u16 lsynclen;
47 u16 lendlbegin;
48 u16 pixclk;
49};
50
51/* table of panel specific parameters to be indexed into by the board drivers */
52static struct panel_info panel_table[] = {
53 { /* standard 6" on TFT backplane */
54 .w = 800,
55 .h = 600,
56 .sdcfg = (100 | (1 << 8) | (1 << 9)),
57 .gdcfg = 2,
58 .lutfmt = (4 | (1 << 7)),
59 .fsynclen = 4,
60 .fendfbegin = (10 << 8) | 4,
61 .lsynclen = 10,
62 .lendlbegin = (100 << 8) | 4,
63 .pixclk = 6,
64 },
65 { /* custom 3.7" flexible on PET or steel */
66 .w = 320,
67 .h = 240,
68 .sdcfg = (67 | (0 << 8) | (0 << 9) | (0 << 10) | (0 << 12)),
69 .gdcfg = 3,
70 .lutfmt = (4 | (1 << 7)),
71 .fsynclen = 0,
72 .fendfbegin = (80 << 8) | 4,
73 .lsynclen = 10,
74 .lendlbegin = (80 << 8) | 20,
75 .pixclk = 14,
76 },
77 { /* standard 9.7" on TFT backplane */
78 .w = 1200,
79 .h = 825,
80 .sdcfg = (100 | (1 << 8) | (1 << 9) | (0 << 10) | (0 << 12)),
81 .gdcfg = 2,
82 .lutfmt = (4 | (1 << 7)),
83 .fsynclen = 0,
84 .fendfbegin = (4 << 8) | 4,
85 .lsynclen = 4,
86 .lendlbegin = (60 << 8) | 10,
87 .pixclk = 3,
88 },
89};
90
37#define DPY_W 800 91#define DPY_W 800
38#define DPY_H 600 92#define DPY_H 600
39 93
@@ -62,30 +116,30 @@ static struct fb_var_screeninfo broadsheetfb_var __devinitdata = {
62}; 116};
63 117
64/* main broadsheetfb functions */ 118/* main broadsheetfb functions */
65static void broadsheet_issue_data(struct broadsheetfb_par *par, u16 data) 119static void broadsheet_gpio_issue_data(struct broadsheetfb_par *par, u16 data)
66{ 120{
67 par->board->set_ctl(par, BS_WR, 0); 121 par->board->set_ctl(par, BS_WR, 0);
68 par->board->set_hdb(par, data); 122 par->board->set_hdb(par, data);
69 par->board->set_ctl(par, BS_WR, 1); 123 par->board->set_ctl(par, BS_WR, 1);
70} 124}
71 125
72static void broadsheet_issue_cmd(struct broadsheetfb_par *par, u16 data) 126static void broadsheet_gpio_issue_cmd(struct broadsheetfb_par *par, u16 data)
73{ 127{
74 par->board->set_ctl(par, BS_DC, 0); 128 par->board->set_ctl(par, BS_DC, 0);
75 broadsheet_issue_data(par, data); 129 broadsheet_gpio_issue_data(par, data);
76} 130}
77 131
78static void broadsheet_send_command(struct broadsheetfb_par *par, u16 data) 132static void broadsheet_gpio_send_command(struct broadsheetfb_par *par, u16 data)
79{ 133{
80 par->board->wait_for_rdy(par); 134 par->board->wait_for_rdy(par);
81 135
82 par->board->set_ctl(par, BS_CS, 0); 136 par->board->set_ctl(par, BS_CS, 0);
83 broadsheet_issue_cmd(par, data); 137 broadsheet_gpio_issue_cmd(par, data);
84 par->board->set_ctl(par, BS_DC, 1); 138 par->board->set_ctl(par, BS_DC, 1);
85 par->board->set_ctl(par, BS_CS, 1); 139 par->board->set_ctl(par, BS_CS, 1);
86} 140}
87 141
88static void broadsheet_send_cmdargs(struct broadsheetfb_par *par, u16 cmd, 142static void broadsheet_gpio_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
89 int argc, u16 *argv) 143 int argc, u16 *argv)
90{ 144{
91 int i; 145 int i;
@@ -93,15 +147,43 @@ static void broadsheet_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
93 par->board->wait_for_rdy(par); 147 par->board->wait_for_rdy(par);
94 148
95 par->board->set_ctl(par, BS_CS, 0); 149 par->board->set_ctl(par, BS_CS, 0);
96 broadsheet_issue_cmd(par, cmd); 150 broadsheet_gpio_issue_cmd(par, cmd);
97 par->board->set_ctl(par, BS_DC, 1); 151 par->board->set_ctl(par, BS_DC, 1);
98 152
99 for (i = 0; i < argc; i++) 153 for (i = 0; i < argc; i++)
100 broadsheet_issue_data(par, argv[i]); 154 broadsheet_gpio_issue_data(par, argv[i]);
101 par->board->set_ctl(par, BS_CS, 1); 155 par->board->set_ctl(par, BS_CS, 1);
102} 156}
103 157
104static void broadsheet_burst_write(struct broadsheetfb_par *par, int size, 158static void broadsheet_mmio_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
159 int argc, u16 *argv)
160{
161 int i;
162
163 par->board->mmio_write(par, BS_MMIO_CMD, cmd);
164
165 for (i = 0; i < argc; i++)
166 par->board->mmio_write(par, BS_MMIO_DATA, argv[i]);
167}
168
169static void broadsheet_send_command(struct broadsheetfb_par *par, u16 data)
170{
171 if (par->board->mmio_write)
172 par->board->mmio_write(par, BS_MMIO_CMD, data);
173 else
174 broadsheet_gpio_send_command(par, data);
175}
176
177static void broadsheet_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
178 int argc, u16 *argv)
179{
180 if (par->board->mmio_write)
181 broadsheet_mmio_send_cmdargs(par, cmd, argc, argv);
182 else
183 broadsheet_gpio_send_cmdargs(par, cmd, argc, argv);
184}
185
186static void broadsheet_gpio_burst_write(struct broadsheetfb_par *par, int size,
105 u16 *data) 187 u16 *data)
106{ 188{
107 int i; 189 int i;
@@ -121,7 +203,30 @@ static void broadsheet_burst_write(struct broadsheetfb_par *par, int size,
121 par->board->set_ctl(par, BS_CS, 1); 203 par->board->set_ctl(par, BS_CS, 1);
122} 204}
123 205
124static u16 broadsheet_get_data(struct broadsheetfb_par *par) 206static void broadsheet_mmio_burst_write(struct broadsheetfb_par *par, int size,
207 u16 *data)
208{
209 int i;
210 u16 tmp;
211
212 for (i = 0; i < size; i++) {
213 tmp = (data[i] & 0x0F) << 4;
214 tmp |= (data[i] & 0x0F00) << 4;
215 par->board->mmio_write(par, BS_MMIO_DATA, tmp);
216 }
217
218}
219
220static void broadsheet_burst_write(struct broadsheetfb_par *par, int size,
221 u16 *data)
222{
223 if (par->board->mmio_write)
224 broadsheet_mmio_burst_write(par, size, data);
225 else
226 broadsheet_gpio_burst_write(par, size, data);
227}
228
229static u16 broadsheet_gpio_get_data(struct broadsheetfb_par *par)
125{ 230{
126 u16 res; 231 u16 res;
127 /* wait for ready to go hi. (lo is busy) */ 232 /* wait for ready to go hi. (lo is busy) */
@@ -141,7 +246,16 @@ static u16 broadsheet_get_data(struct broadsheetfb_par *par)
141 return res; 246 return res;
142} 247}
143 248
144static void broadsheet_write_reg(struct broadsheetfb_par *par, u16 reg, 249
250static u16 broadsheet_get_data(struct broadsheetfb_par *par)
251{
252 if (par->board->mmio_read)
253 return par->board->mmio_read(par);
254 else
255 return broadsheet_gpio_get_data(par);
256}
257
258static void broadsheet_gpio_write_reg(struct broadsheetfb_par *par, u16 reg,
145 u16 data) 259 u16 data)
146{ 260{
147 /* wait for ready to go hi. (lo is busy) */ 261 /* wait for ready to go hi. (lo is busy) */
@@ -150,44 +264,541 @@ static void broadsheet_write_reg(struct broadsheetfb_par *par, u16 reg,
150 /* cs lo, dc lo for cmd, we lo for each data, db as usual */ 264 /* cs lo, dc lo for cmd, we lo for each data, db as usual */
151 par->board->set_ctl(par, BS_CS, 0); 265 par->board->set_ctl(par, BS_CS, 0);
152 266
153 broadsheet_issue_cmd(par, BS_CMD_WR_REG); 267 broadsheet_gpio_issue_cmd(par, BS_CMD_WR_REG);
154 268
155 par->board->set_ctl(par, BS_DC, 1); 269 par->board->set_ctl(par, BS_DC, 1);
156 270
157 broadsheet_issue_data(par, reg); 271 broadsheet_gpio_issue_data(par, reg);
158 broadsheet_issue_data(par, data); 272 broadsheet_gpio_issue_data(par, data);
159 273
160 par->board->set_ctl(par, BS_CS, 1); 274 par->board->set_ctl(par, BS_CS, 1);
161} 275}
162 276
277static void broadsheet_mmio_write_reg(struct broadsheetfb_par *par, u16 reg,
278 u16 data)
279{
280 par->board->mmio_write(par, BS_MMIO_CMD, BS_CMD_WR_REG);
281 par->board->mmio_write(par, BS_MMIO_DATA, reg);
282 par->board->mmio_write(par, BS_MMIO_DATA, data);
283
284}
285
286static void broadsheet_write_reg(struct broadsheetfb_par *par, u16 reg,
287 u16 data)
288{
289 if (par->board->mmio_write)
290 broadsheet_mmio_write_reg(par, reg, data);
291 else
292 broadsheet_gpio_write_reg(par, reg, data);
293}
294
295static void broadsheet_write_reg32(struct broadsheetfb_par *par, u16 reg,
296 u32 data)
297{
298 broadsheet_write_reg(par, reg, cpu_to_le32(data) & 0xFFFF);
299 broadsheet_write_reg(par, reg + 2, (cpu_to_le32(data) >> 16) & 0xFFFF);
300}
301
302
163static u16 broadsheet_read_reg(struct broadsheetfb_par *par, u16 reg) 303static u16 broadsheet_read_reg(struct broadsheetfb_par *par, u16 reg)
164{ 304{
165 broadsheet_send_command(par, reg); 305 broadsheet_send_cmdargs(par, BS_CMD_RD_REG, 1, &reg);
166 msleep(100); 306 par->board->wait_for_rdy(par);
167 return broadsheet_get_data(par); 307 return broadsheet_get_data(par);
168} 308}
169 309
310/* functions for waveform manipulation */
311static int is_broadsheet_pll_locked(struct broadsheetfb_par *par)
312{
313 return broadsheet_read_reg(par, 0x000A) & 0x0001;
314}
315
316static int broadsheet_setup_plls(struct broadsheetfb_par *par)
317{
318 int retry_count = 0;
319 u16 tmp;
320
321 /* disable arral saemipu mode */
322 broadsheet_write_reg(par, 0x0006, 0x0000);
323
324 broadsheet_write_reg(par, 0x0010, 0x0004);
325 broadsheet_write_reg(par, 0x0012, 0x5949);
326 broadsheet_write_reg(par, 0x0014, 0x0040);
327 broadsheet_write_reg(par, 0x0016, 0x0000);
328
329 do {
330 if (retry_count++ > 100)
331 return -ETIMEDOUT;
332 mdelay(1);
333 } while (!is_broadsheet_pll_locked(par));
334
335 tmp = broadsheet_read_reg(par, 0x0006);
336 tmp &= ~0x1;
337 broadsheet_write_reg(par, 0x0006, tmp);
338
339 return 0;
340}
341
342static int broadsheet_setup_spi(struct broadsheetfb_par *par)
343{
344
345 broadsheet_write_reg(par, 0x0204, ((3 << 3) | 1));
346 broadsheet_write_reg(par, 0x0208, 0x0001);
347
348 return 0;
349}
350
351static int broadsheet_setup_spiflash(struct broadsheetfb_par *par,
352 u16 *orig_sfmcd)
353{
354
355 *orig_sfmcd = broadsheet_read_reg(par, 0x0204);
356 broadsheet_write_reg(par, 0x0208, 0);
357 broadsheet_write_reg(par, 0x0204, 0);
358 broadsheet_write_reg(par, 0x0204, ((3 << 3) | 1));
359
360 return 0;
361}
362
363static int broadsheet_spiflash_wait_for_bit(struct broadsheetfb_par *par,
364 u16 reg, int bitnum, int val,
365 int timeout)
366{
367 u16 tmp;
368
369 do {
370 tmp = broadsheet_read_reg(par, reg);
371 if (((tmp >> bitnum) & 1) == val)
372 return 0;
373 mdelay(1);
374 } while (timeout--);
375
376 return -ETIMEDOUT;
377}
378
379static int broadsheet_spiflash_write_byte(struct broadsheetfb_par *par, u8 data)
380{
381 broadsheet_write_reg(par, 0x0202, (data | 0x100));
382
383 return broadsheet_spiflash_wait_for_bit(par, 0x0206, 3, 0, 100);
384}
385
386static int broadsheet_spiflash_read_byte(struct broadsheetfb_par *par, u8 *data)
387{
388 int err;
389 u16 tmp;
390
391 broadsheet_write_reg(par, 0x0202, 0);
392
393 err = broadsheet_spiflash_wait_for_bit(par, 0x0206, 3, 0, 100);
394 if (err)
395 return err;
396
397 tmp = broadsheet_read_reg(par, 0x200);
398
399 *data = tmp & 0xFF;
400
401 return 0;
402}
403
404static int broadsheet_spiflash_wait_for_status(struct broadsheetfb_par *par,
405 int timeout)
406{
407 u8 tmp;
408 int err;
409
410 do {
411 broadsheet_write_reg(par, 0x0208, 1);
412
413 err = broadsheet_spiflash_write_byte(par, 0x05);
414 if (err)
415 goto failout;
416
417 err = broadsheet_spiflash_read_byte(par, &tmp);
418 if (err)
419 goto failout;
420
421 broadsheet_write_reg(par, 0x0208, 0);
422
423 if (!(tmp & 0x1))
424 return 0;
425
426 mdelay(5);
427 } while (timeout--);
428
429 dev_err(par->info->device, "Timed out waiting for spiflash status\n");
430 return -ETIMEDOUT;
431
432failout:
433 broadsheet_write_reg(par, 0x0208, 0);
434 return err;
435}
436
437static int broadsheet_spiflash_op_on_address(struct broadsheetfb_par *par,
438 u8 op, u32 addr)
439{
440 int i;
441 u8 tmp;
442 int err;
443
444 broadsheet_write_reg(par, 0x0208, 1);
445
446 err = broadsheet_spiflash_write_byte(par, op);
447 if (err)
448 return err;
449
450 for (i = 2; i >= 0; i--) {
451 tmp = ((addr >> (i * 8)) & 0xFF);
452 err = broadsheet_spiflash_write_byte(par, tmp);
453 if (err)
454 return err;
455 }
456
457 return err;
458}
459
460static int broadsheet_verify_spiflash(struct broadsheetfb_par *par,
461 int *flash_type)
462{
463 int err = 0;
464 u8 sig;
465
466 err = broadsheet_spiflash_op_on_address(par, 0xAB, 0x00000000);
467 if (err)
468 goto failout;
469
470 err = broadsheet_spiflash_read_byte(par, &sig);
471 if (err)
472 goto failout;
473
474 if ((sig != 0x10) && (sig != 0x11)) {
475 dev_err(par->info->device, "Unexpected flash type\n");
476 err = -EINVAL;
477 goto failout;
478 }
479
480 *flash_type = sig;
481
482failout:
483 broadsheet_write_reg(par, 0x0208, 0);
484 return err;
485}
486
487static int broadsheet_setup_for_wfm_write(struct broadsheetfb_par *par,
488 u16 *initial_sfmcd, int *flash_type)
489
490{
491 int err;
492
493 err = broadsheet_setup_plls(par);
494 if (err)
495 return err;
496
497 broadsheet_write_reg(par, 0x0106, 0x0203);
498
499 err = broadsheet_setup_spi(par);
500 if (err)
501 return err;
502
503 err = broadsheet_setup_spiflash(par, initial_sfmcd);
504 if (err)
505 return err;
506
507 return broadsheet_verify_spiflash(par, flash_type);
508}
509
510static int broadsheet_spiflash_write_control(struct broadsheetfb_par *par,
511 int mode)
512{
513 int err;
514
515 broadsheet_write_reg(par, 0x0208, 1);
516 if (mode)
517 err = broadsheet_spiflash_write_byte(par, 0x06);
518 else
519 err = broadsheet_spiflash_write_byte(par, 0x04);
520
521 broadsheet_write_reg(par, 0x0208, 0);
522 return err;
523}
524
525static int broadsheet_spiflash_erase_sector(struct broadsheetfb_par *par,
526 int addr)
527{
528 int err;
529
530 broadsheet_spiflash_write_control(par, 1);
531
532 err = broadsheet_spiflash_op_on_address(par, 0xD8, addr);
533
534 broadsheet_write_reg(par, 0x0208, 0);
535
536 if (err)
537 return err;
538
539 err = broadsheet_spiflash_wait_for_status(par, 1000);
540
541 return err;
542}
543
544static int broadsheet_spiflash_read_range(struct broadsheetfb_par *par,
545 int addr, int size, char *data)
546{
547 int err;
548 int i;
549
550 err = broadsheet_spiflash_op_on_address(par, 0x03, addr);
551 if (err)
552 goto failout;
553
554 for (i = 0; i < size; i++) {
555 err = broadsheet_spiflash_read_byte(par, &data[i]);
556 if (err)
557 goto failout;
558 }
559
560failout:
561 broadsheet_write_reg(par, 0x0208, 0);
562 return err;
563}
564
565#define BS_SPIFLASH_PAGE_SIZE 256
566static int broadsheet_spiflash_write_page(struct broadsheetfb_par *par,
567 int addr, const char *data)
568{
569 int err;
570 int i;
571
572 broadsheet_spiflash_write_control(par, 1);
573
574 err = broadsheet_spiflash_op_on_address(par, 0x02, addr);
575 if (err)
576 goto failout;
577
578 for (i = 0; i < BS_SPIFLASH_PAGE_SIZE; i++) {
579 err = broadsheet_spiflash_write_byte(par, data[i]);
580 if (err)
581 goto failout;
582 }
583
584 broadsheet_write_reg(par, 0x0208, 0);
585
586 err = broadsheet_spiflash_wait_for_status(par, 100);
587
588failout:
589 return err;
590}
591
592static int broadsheet_spiflash_write_sector(struct broadsheetfb_par *par,
593 int addr, const char *data, int sector_size)
594{
595 int i;
596 int err;
597
598 for (i = 0; i < sector_size; i += BS_SPIFLASH_PAGE_SIZE) {
599 err = broadsheet_spiflash_write_page(par, addr + i, &data[i]);
600 if (err)
601 return err;
602 }
603 return 0;
604}
605
606/*
607 * The caller must guarantee that the data to be rewritten is entirely
608 * contained within this sector. That is, data_start_addr + data_len
609 * must be less than sector_start_addr + sector_size.
610 */
611static int broadsheet_spiflash_rewrite_sector(struct broadsheetfb_par *par,
612 int sector_size, int data_start_addr,
613 int data_len, const char *data)
614{
615 int err;
616 char *sector_buffer;
617 int tail_start_addr;
618 int start_sector_addr;
619
620 sector_buffer = kzalloc(sizeof(char)*sector_size, GFP_KERNEL);
621 if (!sector_buffer)
622 return -ENOMEM;
623
624 /* the start address of the sector is the 0th byte of that sector */
625 start_sector_addr = (data_start_addr / sector_size) * sector_size;
626
627 /*
628 * check if there is head data that we need to readback into our sector
629 * buffer first
630 */
631 if (data_start_addr != start_sector_addr) {
632 /*
633 * we need to read every byte up till the start address of our
634 * data and we put it into our sector buffer.
635 */
636 err = broadsheet_spiflash_read_range(par, start_sector_addr,
637 data_start_addr, sector_buffer);
638 if (err)
639 return err;
640 }
641
642 /* now we copy our data into the right place in the sector buffer */
643 memcpy(sector_buffer + data_start_addr, data, data_len);
644
645 /*
646 * now we check if there is a tail section of the sector that we need to
647 * readback.
648 */
649 tail_start_addr = (data_start_addr + data_len) % sector_size;
650
651 if (tail_start_addr) {
652 int tail_len;
653
654 tail_len = sector_size - tail_start_addr;
655
656 /* now we read this tail into our sector buffer */
657 err = broadsheet_spiflash_read_range(par, tail_start_addr,
658 tail_len, sector_buffer + tail_start_addr);
659 if (err)
660 return err;
661 }
662
663 /* if we got here we have the full sector that we want to rewrite. */
664
665 /* first erase the sector */
666 err = broadsheet_spiflash_erase_sector(par, start_sector_addr);
667 if (err)
668 return err;
669
670 /* now write it */
671 err = broadsheet_spiflash_write_sector(par, start_sector_addr,
672 sector_buffer, sector_size);
673 return err;
674}
675
676static int broadsheet_write_spiflash(struct broadsheetfb_par *par, u32 wfm_addr,
677 const u8 *wfm, int bytecount, int flash_type)
678{
679 int sector_size;
680 int err;
681 int cur_addr;
682 int writecount;
683 int maxlen;
684 int offset = 0;
685
686 switch (flash_type) {
687 case 0x10:
688 sector_size = 32*1024;
689 break;
690 case 0x11:
691 default:
692 sector_size = 64*1024;
693 break;
694 }
695
696 while (bytecount) {
697 cur_addr = wfm_addr + offset;
698 maxlen = roundup(cur_addr, sector_size) - cur_addr;
699 writecount = min(bytecount, maxlen);
700
701 err = broadsheet_spiflash_rewrite_sector(par, sector_size,
702 cur_addr, writecount, wfm + offset);
703 if (err)
704 return err;
705
706 offset += writecount;
707 bytecount -= writecount;
708 }
709
710 return 0;
711}
712
713static int broadsheet_store_waveform_to_spiflash(struct broadsheetfb_par *par,
714 const u8 *wfm, size_t wfm_size)
715{
716 int err = 0;
717 u16 initial_sfmcd = 0;
718 int flash_type = 0;
719
720 err = broadsheet_setup_for_wfm_write(par, &initial_sfmcd, &flash_type);
721 if (err)
722 goto failout;
723
724 err = broadsheet_write_spiflash(par, 0x886, wfm, wfm_size, flash_type);
725
726failout:
727 broadsheet_write_reg(par, 0x0204, initial_sfmcd);
728 return err;
729}
730
731static ssize_t broadsheet_loadstore_waveform(struct device *dev,
732 struct device_attribute *attr,
733 const char *buf, size_t len)
734{
735 int err;
736 struct fb_info *info = dev_get_drvdata(dev);
737 struct broadsheetfb_par *par = info->par;
738 const struct firmware *fw_entry;
739
740 if (len < 1)
741 return -EINVAL;
742
743 err = request_firmware(&fw_entry, "broadsheet.wbf", dev);
744 if (err < 0) {
745 dev_err(dev, "Failed to get broadsheet waveform\n");
746 goto err_failed;
747 }
748
749 /* try to enforce reasonable min max on waveform */
750 if ((fw_entry->size < 8*1024) || (fw_entry->size > 64*1024)) {
751 dev_err(dev, "Invalid waveform\n");
752 err = -EINVAL;
753 goto err_failed;
754 }
755
756 mutex_lock(&(par->io_lock));
757 err = broadsheet_store_waveform_to_spiflash(par, fw_entry->data,
758 fw_entry->size);
759
760 mutex_unlock(&(par->io_lock));
761 if (err < 0) {
762 dev_err(dev, "Failed to store broadsheet waveform\n");
763 goto err_failed;
764 }
765
766 dev_info(dev, "Stored broadsheet waveform, size %zd\n", fw_entry->size);
767
768 return len;
769
770err_failed:
771 return err;
772}
773static DEVICE_ATTR(loadstore_waveform, S_IWUSR, NULL,
774 broadsheet_loadstore_waveform);
775
776/* upper level functions that manipulate the display and other stuff */
170static void __devinit broadsheet_init_display(struct broadsheetfb_par *par) 777static void __devinit broadsheet_init_display(struct broadsheetfb_par *par)
171{ 778{
172 u16 args[5]; 779 u16 args[5];
173 780 int xres = par->info->var.xres;
174 args[0] = DPY_W; 781 int yres = par->info->var.yres;
175 args[1] = DPY_H; 782
176 args[2] = (100 | (1 << 8) | (1 << 9)); /* sdcfg */ 783 args[0] = panel_table[par->panel_index].w;
177 args[3] = 2; /* gdrv cfg */ 784 args[1] = panel_table[par->panel_index].h;
178 args[4] = (4 | (1 << 7)); /* lut index format */ 785 args[2] = panel_table[par->panel_index].sdcfg;
786 args[3] = panel_table[par->panel_index].gdcfg;
787 args[4] = panel_table[par->panel_index].lutfmt;
179 broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args); 788 broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args);
180 789
181 /* did the controller really set it? */ 790 /* did the controller really set it? */
182 broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args); 791 broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args);
183 792
184 args[0] = 4; /* fsync len */ 793 args[0] = panel_table[par->panel_index].fsynclen;
185 args[1] = (10 << 8) | 4; /* fend/fbegin len */ 794 args[1] = panel_table[par->panel_index].fendfbegin;
186 args[2] = 10; /* line sync len */ 795 args[2] = panel_table[par->panel_index].lsynclen;
187 args[3] = (100 << 8) | 4; /* line end/begin len */ 796 args[3] = panel_table[par->panel_index].lendlbegin;
188 args[4] = 6; /* pixel clock cfg */ 797 args[4] = panel_table[par->panel_index].pixclk;
189 broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_TMG, 5, args); 798 broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_TMG, 5, args);
190 799
800 broadsheet_write_reg32(par, 0x310, xres*yres*2);
801
191 /* setup waveform */ 802 /* setup waveform */
192 args[0] = 0x886; 803 args[0] = 0x886;
193 args[1] = 0; 804 args[1] = 0;
@@ -207,8 +818,9 @@ static void __devinit broadsheet_init_display(struct broadsheetfb_par *par)
207 args[0] = 0x154; 818 args[0] = 0x154;
208 broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args); 819 broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
209 820
210 broadsheet_burst_write(par, DPY_W*DPY_H/2, 821 broadsheet_burst_write(par, (panel_table[par->panel_index].w *
211 (u16 *) par->info->screen_base); 822 panel_table[par->panel_index].h)/2,
823 (u16 *) par->info->screen_base);
212 824
213 broadsheet_send_command(par, BS_CMD_LD_IMG_END); 825 broadsheet_send_command(par, BS_CMD_LD_IMG_END);
214 826
@@ -222,6 +834,21 @@ static void __devinit broadsheet_init_display(struct broadsheetfb_par *par)
222 par->board->wait_for_rdy(par); 834 par->board->wait_for_rdy(par);
223} 835}
224 836
837static void __devinit broadsheet_identify(struct broadsheetfb_par *par)
838{
839 u16 rev, prc;
840 struct device *dev = par->info->device;
841
842 rev = broadsheet_read_reg(par, BS_REG_REV);
843 prc = broadsheet_read_reg(par, BS_REG_PRC);
844 dev_info(dev, "Broadsheet Rev 0x%x, Product Code 0x%x\n", rev, prc);
845
846 if (prc != 0x0047)
847 dev_warn(dev, "Unrecognized Broadsheet Product Code\n");
848 if (rev != 0x0100)
849 dev_warn(dev, "Unrecognized Broadsheet Revision\n");
850}
851
225static void __devinit broadsheet_init(struct broadsheetfb_par *par) 852static void __devinit broadsheet_init(struct broadsheetfb_par *par)
226{ 853{
227 broadsheet_send_command(par, BS_CMD_INIT_SYS_RUN); 854 broadsheet_send_command(par, BS_CMD_INIT_SYS_RUN);
@@ -236,6 +863,7 @@ static void broadsheetfb_dpy_update_pages(struct broadsheetfb_par *par,
236 u16 args[5]; 863 u16 args[5];
237 unsigned char *buf = (unsigned char *)par->info->screen_base; 864 unsigned char *buf = (unsigned char *)par->info->screen_base;
238 865
866 mutex_lock(&(par->io_lock));
239 /* y1 must be a multiple of 4 so drop the lower bits */ 867 /* y1 must be a multiple of 4 so drop the lower bits */
240 y1 &= 0xFFFC; 868 y1 &= 0xFFFC;
241 /* y2 must be a multiple of 4 , but - 1 so up the lower bits */ 869 /* y2 must be a multiple of 4 , but - 1 so up the lower bits */
@@ -265,6 +893,7 @@ static void broadsheetfb_dpy_update_pages(struct broadsheetfb_par *par,
265 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND); 893 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
266 894
267 par->board->wait_for_rdy(par); 895 par->board->wait_for_rdy(par);
896 mutex_unlock(&(par->io_lock));
268 897
269} 898}
270 899
@@ -272,13 +901,15 @@ static void broadsheetfb_dpy_update(struct broadsheetfb_par *par)
272{ 901{
273 u16 args[5]; 902 u16 args[5];
274 903
904 mutex_lock(&(par->io_lock));
275 args[0] = 0x3 << 4; 905 args[0] = 0x3 << 4;
276 broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args); 906 broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args);
277 907
278 args[0] = 0x154; 908 args[0] = 0x154;
279 broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args); 909 broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
280 broadsheet_burst_write(par, DPY_W*DPY_H/2, 910 broadsheet_burst_write(par, (panel_table[par->panel_index].w *
281 (u16 *) par->info->screen_base); 911 panel_table[par->panel_index].h)/2,
912 (u16 *) par->info->screen_base);
282 913
283 broadsheet_send_command(par, BS_CMD_LD_IMG_END); 914 broadsheet_send_command(par, BS_CMD_LD_IMG_END);
284 915
@@ -290,7 +921,7 @@ static void broadsheetfb_dpy_update(struct broadsheetfb_par *par)
290 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND); 921 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
291 922
292 par->board->wait_for_rdy(par); 923 par->board->wait_for_rdy(par);
293 924 mutex_unlock(&(par->io_lock));
294} 925}
295 926
296/* this is called back from the deferred io workqueue */ 927/* this is called back from the deferred io workqueue */
@@ -436,6 +1067,8 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev)
436 unsigned char *videomemory; 1067 unsigned char *videomemory;
437 struct broadsheetfb_par *par; 1068 struct broadsheetfb_par *par;
438 int i; 1069 int i;
1070 int dpyw, dpyh;
1071 int panel_index;
439 1072
440 /* pick up board specific routines */ 1073 /* pick up board specific routines */
441 board = dev->dev.platform_data; 1074 board = dev->dev.platform_data;
@@ -450,7 +1083,24 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev)
450 if (!info) 1083 if (!info)
451 goto err; 1084 goto err;
452 1085
453 videomemorysize = (DPY_W*DPY_H); 1086 switch (board->get_panel_type()) {
1087 case 37:
1088 panel_index = 1;
1089 break;
1090 case 97:
1091 panel_index = 2;
1092 break;
1093 case 6:
1094 default:
1095 panel_index = 0;
1096 break;
1097 }
1098
1099 dpyw = panel_table[panel_index].w;
1100 dpyh = panel_table[panel_index].h;
1101
1102 videomemorysize = roundup((dpyw*dpyh), PAGE_SIZE);
1103
454 videomemory = vmalloc(videomemorysize); 1104 videomemory = vmalloc(videomemorysize);
455 if (!videomemory) 1105 if (!videomemory)
456 goto err_fb_rel; 1106 goto err_fb_rel;
@@ -460,17 +1110,26 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev)
460 info->screen_base = (char *)videomemory; 1110 info->screen_base = (char *)videomemory;
461 info->fbops = &broadsheetfb_ops; 1111 info->fbops = &broadsheetfb_ops;
462 1112
1113 broadsheetfb_var.xres = dpyw;
1114 broadsheetfb_var.yres = dpyh;
1115 broadsheetfb_var.xres_virtual = dpyw;
1116 broadsheetfb_var.yres_virtual = dpyh;
463 info->var = broadsheetfb_var; 1117 info->var = broadsheetfb_var;
1118
1119 broadsheetfb_fix.line_length = dpyw;
464 info->fix = broadsheetfb_fix; 1120 info->fix = broadsheetfb_fix;
465 info->fix.smem_len = videomemorysize; 1121 info->fix.smem_len = videomemorysize;
466 par = info->par; 1122 par = info->par;
1123 par->panel_index = panel_index;
467 par->info = info; 1124 par->info = info;
468 par->board = board; 1125 par->board = board;
469 par->write_reg = broadsheet_write_reg; 1126 par->write_reg = broadsheet_write_reg;
470 par->read_reg = broadsheet_read_reg; 1127 par->read_reg = broadsheet_read_reg;
471 init_waitqueue_head(&par->waitq); 1128 init_waitqueue_head(&par->waitq);
472 1129
473 info->flags = FBINFO_FLAG_DEFAULT; 1130 mutex_init(&par->io_lock);
1131
1132 info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
474 1133
475 info->fbdefio = &broadsheetfb_defio; 1134 info->fbdefio = &broadsheetfb_defio;
476 fb_deferred_io_init(info); 1135 fb_deferred_io_init(info);
@@ -496,13 +1155,20 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev)
496 if (retval < 0) 1155 if (retval < 0)
497 goto err_free_irq; 1156 goto err_free_irq;
498 1157
1158 broadsheet_identify(par);
1159
499 broadsheet_init(par); 1160 broadsheet_init(par);
500 1161
501 retval = register_framebuffer(info); 1162 retval = register_framebuffer(info);
502 if (retval < 0) 1163 if (retval < 0)
503 goto err_free_irq; 1164 goto err_free_irq;
1165
504 platform_set_drvdata(dev, info); 1166 platform_set_drvdata(dev, info);
505 1167
1168 retval = device_create_file(&dev->dev, &dev_attr_loadstore_waveform);
1169 if (retval < 0)
1170 goto err_unreg_fb;
1171
506 printk(KERN_INFO 1172 printk(KERN_INFO
507 "fb%d: Broadsheet frame buffer, using %dK of video memory\n", 1173 "fb%d: Broadsheet frame buffer, using %dK of video memory\n",
508 info->node, videomemorysize >> 10); 1174 info->node, videomemorysize >> 10);
@@ -510,6 +1176,8 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev)
510 1176
511 return 0; 1177 return 0;
512 1178
1179err_unreg_fb:
1180 unregister_framebuffer(info);
513err_free_irq: 1181err_free_irq:
514 board->cleanup(par); 1182 board->cleanup(par);
515err_cmap: 1183err_cmap:
@@ -530,6 +1198,8 @@ static int __devexit broadsheetfb_remove(struct platform_device *dev)
530 1198
531 if (info) { 1199 if (info) {
532 struct broadsheetfb_par *par = info->par; 1200 struct broadsheetfb_par *par = info->par;
1201
1202 device_remove_file(info->dev, &dev_attr_loadstore_waveform);
533 unregister_framebuffer(info); 1203 unregister_framebuffer(info);
534 fb_deferred_io_cleanup(info); 1204 fb_deferred_io_cleanup(info);
535 par->board->cleanup(par); 1205 par->board->cleanup(par);
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
index b0b147cb4cb3..43320925c4ce 100644
--- a/drivers/video/bw2.c
+++ b/drivers/video/bw2.c
@@ -12,7 +12,6 @@
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/errno.h> 13#include <linux/errno.h>
14#include <linux/string.h> 14#include <linux/string.h>
15#include <linux/slab.h>
16#include <linux/delay.h> 15#include <linux/delay.h>
17#include <linux/init.h> 16#include <linux/init.h>
18#include <linux/fb.h> 17#include <linux/fb.h>
diff --git a/drivers/video/carminefb.c b/drivers/video/carminefb.c
index 0c02f8ec4bf3..d8345fcc4fe3 100644
--- a/drivers/video/carminefb.c
+++ b/drivers/video/carminefb.c
@@ -11,6 +11,7 @@
11#include <linux/fb.h> 11#include <linux/fb.h>
12#include <linux/interrupt.h> 12#include <linux/interrupt.h>
13#include <linux/pci.h> 13#include <linux/pci.h>
14#include <linux/slab.h>
14 15
15#include "carminefb.h" 16#include "carminefb.h"
16#include "carminefb_regs.h" 17#include "carminefb_regs.h"
diff --git a/drivers/video/cfbcopyarea.c b/drivers/video/cfbcopyarea.c
index 79e5f40e6486..bb5a96b1645d 100644
--- a/drivers/video/cfbcopyarea.c
+++ b/drivers/video/cfbcopyarea.c
@@ -26,7 +26,6 @@
26#include <linux/kernel.h> 26#include <linux/kernel.h>
27#include <linux/string.h> 27#include <linux/string.h>
28#include <linux/fb.h> 28#include <linux/fb.h>
29#include <linux/slab.h>
30#include <asm/types.h> 29#include <asm/types.h>
31#include <asm/io.h> 30#include <asm/io.h>
32#include "fb_draw.h" 31#include "fb_draw.h"
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c
index fe45a3b8d0e0..77a040af20a7 100644
--- a/drivers/video/cg14.c
+++ b/drivers/video/cg14.c
@@ -11,7 +11,6 @@
11#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <linux/errno.h> 12#include <linux/errno.h>
13#include <linux/string.h> 13#include <linux/string.h>
14#include <linux/slab.h>
15#include <linux/delay.h> 14#include <linux/delay.h>
16#include <linux/init.h> 15#include <linux/init.h>
17#include <linux/fb.h> 16#include <linux/fb.h>
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c
index b2319fa7286f..30eedf79322c 100644
--- a/drivers/video/cg3.c
+++ b/drivers/video/cg3.c
@@ -12,7 +12,6 @@
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/errno.h> 13#include <linux/errno.h>
14#include <linux/string.h> 14#include <linux/string.h>
15#include <linux/slab.h>
16#include <linux/delay.h> 15#include <linux/delay.h>
17#include <linux/init.h> 16#include <linux/init.h>
18#include <linux/fb.h> 17#include <linux/fb.h>
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c
index 0d47c6030e3d..6d0fcb43696e 100644
--- a/drivers/video/cg6.c
+++ b/drivers/video/cg6.c
@@ -12,7 +12,6 @@
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/errno.h> 13#include <linux/errno.h>
14#include <linux/string.h> 14#include <linux/string.h>
15#include <linux/slab.h>
16#include <linux/delay.h> 15#include <linux/delay.h>
17#include <linux/init.h> 16#include <linux/init.h>
18#include <linux/fb.h> 17#include <linux/fb.h>
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index 57b9d276497e..d637e1f53172 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -19,7 +19,6 @@
19#include <linux/errno.h> 19#include <linux/errno.h>
20#include <linux/string.h> 20#include <linux/string.h>
21#include <linux/mm.h> 21#include <linux/mm.h>
22#include <linux/slab.h>
23#include <linux/vmalloc.h> 22#include <linux/vmalloc.h>
24#include <linux/delay.h> 23#include <linux/delay.h>
25#include <linux/interrupt.h> 24#include <linux/interrupt.h>
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index 4c2bf923418c..8d8dfda2f868 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -39,7 +39,6 @@
39#include <linux/errno.h> 39#include <linux/errno.h>
40#include <linux/string.h> 40#include <linux/string.h>
41#include <linux/mm.h> 41#include <linux/mm.h>
42#include <linux/slab.h>
43#include <linux/delay.h> 42#include <linux/delay.h>
44#include <linux/fb.h> 43#include <linux/fb.h>
45#include <linux/init.h> 44#include <linux/init.h>
diff --git a/drivers/video/clps711xfb.c b/drivers/video/clps711xfb.c
index 16f5db471ab5..99b354b8e257 100644
--- a/drivers/video/clps711xfb.c
+++ b/drivers/video/clps711xfb.c
@@ -19,8 +19,10 @@
19 * 19 *
20 * Framebuffer driver for the CLPS7111 and EP7212 processors. 20 * Framebuffer driver for the CLPS7111 and EP7212 processors.
21 */ 21 */
22#include <linux/mm.h>
22#include <linux/module.h> 23#include <linux/module.h>
23#include <linux/kernel.h> 24#include <linux/kernel.h>
25#include <linux/seq_file.h>
24#include <linux/slab.h> 26#include <linux/slab.h>
25#include <linux/fb.h> 27#include <linux/fb.h>
26#include <linux/init.h> 28#include <linux/init.h>
@@ -38,14 +40,6 @@ struct fb_info *cfb;
38 40
39#define CMAP_MAX_SIZE 16 41#define CMAP_MAX_SIZE 16
40 42
41/* The /proc entry for the backlight. */
42static struct proc_dir_entry *clps7111fb_backlight_proc_entry = NULL;
43
44static int clps7111fb_proc_backlight_read(char *page, char **start, off_t off,
45 int count, int *eof, void *data);
46static int clps7111fb_proc_backlight_write(struct file *file,
47 const char *buffer, unsigned long count, void *data);
48
49/* 43/*
50 * LCD AC Prescale. This comes from the LCD panel manufacturers specifications. 44 * LCD AC Prescale. This comes from the LCD panel manufacturers specifications.
51 * This determines how many clocks + 1 of CL1 before the M signal toggles. 45 * This determines how many clocks + 1 of CL1 before the M signal toggles.
@@ -221,26 +215,23 @@ static struct fb_ops clps7111fb_ops = {
221 .fb_imageblit = cfb_imageblit, 215 .fb_imageblit = cfb_imageblit,
222}; 216};
223 217
224static int 218static int backlight_proc_show(struct seq_file *m, void *v)
225clps7111fb_proc_backlight_read(char *page, char **start, off_t off,
226 int count, int *eof, void *data)
227{ 219{
228 /* We need at least two characters, one for the digit, and one for
229 * the terminating NULL. */
230 if (count < 2)
231 return -EINVAL;
232
233 if (machine_is_edb7211()) { 220 if (machine_is_edb7211()) {
234 return sprintf(page, "%d\n", 221 seq_printf(m, "%d\n",
235 (clps_readb(PDDR) & EDB_PD3_LCDBL) ? 1 : 0); 222 (clps_readb(PDDR) & EDB_PD3_LCDBL) ? 1 : 0);
236 } 223 }
237 224
238 return 0; 225 return 0;
239} 226}
240 227
241static int 228static int backlight_proc_open(struct inode *inode, struct file *file)
242clps7111fb_proc_backlight_write(struct file *file, const char *buffer, 229{
243 unsigned long count, void *data) 230 return single_open(file, backlight_proc_show, NULL);
231}
232
233static ssize_t backlight_proc_write(struct file *file, const char *buffer,
234 size_t count, loff_t *pos)
244{ 235{
245 unsigned char char_value; 236 unsigned char char_value;
246 int value; 237 int value;
@@ -271,6 +262,15 @@ clps7111fb_proc_backlight_write(struct file *file, const char *buffer,
271 return count; 262 return count;
272} 263}
273 264
265static const struct file_operations backlight_proc_fops = {
266 .owner = THIS_MODULE,
267 .open = backlight_proc_open,
268 .read = seq_read,
269 .llseek = seq_lseek,
270 .release = single_release,
271 .write = backlight_proc_write,
272};
273
274static void __init clps711x_guess_lcd_params(struct fb_info *info) 274static void __init clps711x_guess_lcd_params(struct fb_info *info)
275{ 275{
276 unsigned int lcdcon, syscon, size; 276 unsigned int lcdcon, syscon, size;
@@ -379,19 +379,11 @@ int __init clps711xfb_init(void)
379 379
380 fb_alloc_cmap(&cfb->cmap, CMAP_MAX_SIZE, 0); 380 fb_alloc_cmap(&cfb->cmap, CMAP_MAX_SIZE, 0);
381 381
382 /* Register the /proc entries. */ 382 if (!proc_create("backlight", 0444, NULL, &backlight_proc_fops)) {
383 clps7111fb_backlight_proc_entry = create_proc_entry("backlight", 0444,
384 NULL);
385 if (clps7111fb_backlight_proc_entry == NULL) {
386 printk("Couldn't create the /proc entry for the backlight.\n"); 383 printk("Couldn't create the /proc entry for the backlight.\n");
387 return -EINVAL; 384 return -EINVAL;
388 } 385 }
389 386
390 clps7111fb_backlight_proc_entry->read_proc =
391 &clps7111fb_proc_backlight_read;
392 clps7111fb_backlight_proc_entry->write_proc =
393 &clps7111fb_proc_backlight_write;
394
395 /* 387 /*
396 * Power up the LCD 388 * Power up the LCD
397 */ 389 */
diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c
index 108b89e09a80..5eb61b5adfe8 100644
--- a/drivers/video/cobalt_lcdfb.c
+++ b/drivers/video/cobalt_lcdfb.c
@@ -287,7 +287,7 @@ static struct fb_ops cobalt_lcd_fbops = {
287 .fb_cursor = cobalt_lcdfb_cursor, 287 .fb_cursor = cobalt_lcdfb_cursor,
288}; 288};
289 289
290static int __init cobalt_lcdfb_probe(struct platform_device *dev) 290static int __devinit cobalt_lcdfb_probe(struct platform_device *dev)
291{ 291{
292 struct fb_info *info; 292 struct fb_info *info;
293 struct resource *res; 293 struct resource *res;
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index fc7d9bbb548c..8e8f18d29d7a 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -37,6 +37,7 @@ config VGACON_SOFT_SCROLLBACK
37config VGACON_SOFT_SCROLLBACK_SIZE 37config VGACON_SOFT_SCROLLBACK_SIZE
38 int "Scrollback Buffer Size (in KB)" 38 int "Scrollback Buffer Size (in KB)"
39 depends on VGACON_SOFT_SCROLLBACK 39 depends on VGACON_SOFT_SCROLLBACK
40 range 1 1024
40 default "64" 41 default "64"
41 help 42 help
42 Enter the amount of System RAM to allocate for the scrollback 43 Enter the amount of System RAM to allocate for the scrollback
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
index 6b7c8fbc5495..af88651b0735 100644
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -11,6 +11,7 @@
11 */ 11 */
12 12
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/slab.h>
14#include <linux/string.h> 15#include <linux/string.h>
15#include <linux/fb.h> 16#include <linux/fb.h>
16#include <linux/vt_kern.h> 17#include <linux/vt_kern.h>
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 3681c6a88212..b0a3fa00706d 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -3025,6 +3025,20 @@ static int fbcon_fb_unregistered(struct fb_info *info)
3025 return 0; 3025 return 0;
3026} 3026}
3027 3027
3028static void fbcon_remap_all(int idx)
3029{
3030 int i;
3031 for (i = first_fb_vc; i <= last_fb_vc; i++)
3032 set_con2fb_map(i, idx, 0);
3033
3034 if (con_is_bound(&fb_con)) {
3035 printk(KERN_INFO "fbcon: Remapping primary device, "
3036 "fb%i, to tty %i-%i\n", idx,
3037 first_fb_vc + 1, last_fb_vc + 1);
3038 info_idx = idx;
3039 }
3040}
3041
3028#ifdef CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY 3042#ifdef CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
3029static void fbcon_select_primary(struct fb_info *info) 3043static void fbcon_select_primary(struct fb_info *info)
3030{ 3044{
@@ -3225,6 +3239,10 @@ static int fbcon_event_notify(struct notifier_block *self,
3225 caps = event->data; 3239 caps = event->data;
3226 fbcon_get_requirement(info, caps); 3240 fbcon_get_requirement(info, caps);
3227 break; 3241 break;
3242 case FB_EVENT_REMAP_ALL_CONSOLE:
3243 idx = info->node;
3244 fbcon_remap_all(idx);
3245 break;
3228 } 3246 }
3229done: 3247done:
3230 return ret; 3248 return ret;
diff --git a/drivers/video/console/fbcon_ccw.c b/drivers/video/console/fbcon_ccw.c
index bdf913ecf001..d135671d9961 100644
--- a/drivers/video/console/fbcon_ccw.c
+++ b/drivers/video/console/fbcon_ccw.c
@@ -9,6 +9,7 @@
9 */ 9 */
10 10
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/slab.h>
12#include <linux/string.h> 13#include <linux/string.h>
13#include <linux/fb.h> 14#include <linux/fb.h>
14#include <linux/vt_kern.h> 15#include <linux/vt_kern.h>
diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c
index a6819b9d1770..126110f8454f 100644
--- a/drivers/video/console/fbcon_cw.c
+++ b/drivers/video/console/fbcon_cw.c
@@ -9,6 +9,7 @@
9 */ 9 */
10 10
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/slab.h>
12#include <linux/string.h> 13#include <linux/string.h>
13#include <linux/fb.h> 14#include <linux/fb.h>
14#include <linux/vt_kern.h> 15#include <linux/vt_kern.h>
diff --git a/drivers/video/console/fbcon_rotate.c b/drivers/video/console/fbcon_rotate.c
index 00884e013f0f..db6528f2d3f2 100644
--- a/drivers/video/console/fbcon_rotate.c
+++ b/drivers/video/console/fbcon_rotate.c
@@ -9,6 +9,7 @@
9 */ 9 */
10 10
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/slab.h>
12#include <linux/string.h> 13#include <linux/string.h>
13#include <linux/fb.h> 14#include <linux/fb.h>
14#include <linux/vt_kern.h> 15#include <linux/vt_kern.h>
diff --git a/drivers/video/console/fbcon_ud.c b/drivers/video/console/fbcon_ud.c
index d9b5d6eb68a7..93a3e7381b50 100644
--- a/drivers/video/console/fbcon_ud.c
+++ b/drivers/video/console/fbcon_ud.c
@@ -9,6 +9,7 @@
9 */ 9 */
10 10
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/slab.h>
12#include <linux/string.h> 13#include <linux/string.h>
13#include <linux/fb.h> 14#include <linux/fb.h>
14#include <linux/vt_kern.h> 15#include <linux/vt_kern.h>
diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c
index dd3eaaad4441..0b67866cae10 100644
--- a/drivers/video/console/mdacon.c
+++ b/drivers/video/console/mdacon.c
@@ -33,7 +33,6 @@
33#include <linux/console.h> 33#include <linux/console.h>
34#include <linux/string.h> 34#include <linux/string.h>
35#include <linux/kd.h> 35#include <linux/kd.h>
36#include <linux/slab.h>
37#include <linux/vt_kern.h> 36#include <linux/vt_kern.h>
38#include <linux/vt_buffer.h> 37#include <linux/vt_buffer.h>
39#include <linux/selection.h> 38#include <linux/selection.h>
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c
index 857b3668b3ba..6468a297e341 100644
--- a/drivers/video/console/sticore.c
+++ b/drivers/video/console/sticore.c
@@ -436,7 +436,7 @@ sti_init_glob_cfg(struct sti_struct *sti,
436 (offs < PCI_BASE_ADDRESS_0 || 436 (offs < PCI_BASE_ADDRESS_0 ||
437 offs > PCI_BASE_ADDRESS_5)) { 437 offs > PCI_BASE_ADDRESS_5)) {
438 printk (KERN_WARNING 438 printk (KERN_WARNING
439 "STI pci region maping for region %d (%02x) can't be mapped\n", 439 "STI pci region mapping for region %d (%02x) can't be mapped\n",
440 i,sti->rm_entry[i]); 440 i,sti->rm_entry[i]);
441 continue; 441 continue;
442 } 442 }
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index da55ccaf4d55..182dd6f8aadd 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -112,7 +112,7 @@ static int vga_video_font_height;
112static int vga_scan_lines __read_mostly; 112static int vga_scan_lines __read_mostly;
113static unsigned int vga_rolled_over; 113static unsigned int vga_rolled_over;
114 114
115int vgacon_text_mode_force = 0; 115static int vgacon_text_mode_force;
116 116
117bool vgacon_text_force(void) 117bool vgacon_text_force(void)
118{ 118{
@@ -585,6 +585,11 @@ static void vgacon_init(struct vc_data *c, int init)
585 vgacon_uni_pagedir[1]++; 585 vgacon_uni_pagedir[1]++;
586 if (!vgacon_uni_pagedir[0] && p) 586 if (!vgacon_uni_pagedir[0] && p)
587 con_set_default_unimap(c); 587 con_set_default_unimap(c);
588
589 /* Only set the default if the user didn't deliberately override it */
590 if (global_cursor_default == -1)
591 global_cursor_default =
592 !(screen_info.flags & VIDEO_FLAGS_NOCURSOR);
588} 593}
589 594
590static void vgacon_deinit(struct vc_data *c) 595static void vgacon_deinit(struct vc_data *c)
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index da7c01b39be2..3a561df2e8a2 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -1573,15 +1573,15 @@ cyberpro_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
1573 if (err) 1573 if (err)
1574 return err; 1574 return err;
1575 1575
1576 err = pci_request_regions(dev, name);
1577 if (err)
1578 return err;
1579
1580 err = -ENOMEM; 1576 err = -ENOMEM;
1581 cfb = cyberpro_alloc_fb_info(id->driver_data, name); 1577 cfb = cyberpro_alloc_fb_info(id->driver_data, name);
1582 if (!cfb) 1578 if (!cfb)
1583 goto failed_release; 1579 goto failed_release;
1584 1580
1581 err = pci_request_regions(dev, cfb->fb.fix.id);
1582 if (err)
1583 goto failed_regions;
1584
1585 cfb->dev = dev; 1585 cfb->dev = dev;
1586 cfb->region = pci_ioremap_bar(dev, 0); 1586 cfb->region = pci_ioremap_bar(dev, 0);
1587 if (!cfb->region) 1587 if (!cfb->region)
@@ -1633,10 +1633,10 @@ cyberpro_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
1633failed: 1633failed:
1634 iounmap(cfb->region); 1634 iounmap(cfb->region);
1635failed_ioremap: 1635failed_ioremap:
1636 pci_release_regions(dev);
1637failed_regions:
1636 cyberpro_free_fb_info(cfb); 1638 cyberpro_free_fb_info(cfb);
1637failed_release: 1639failed_release:
1638 pci_release_regions(dev);
1639
1640 return err; 1640 return err;
1641} 1641}
1642 1642
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index ea1fd3f47511..8d244ba0f601 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -28,6 +28,9 @@
28#include <linux/uaccess.h> 28#include <linux/uaccess.h>
29#include <linux/interrupt.h> 29#include <linux/interrupt.h>
30#include <linux/clk.h> 30#include <linux/clk.h>
31#include <linux/cpufreq.h>
32#include <linux/console.h>
33#include <linux/slab.h>
31#include <video/da8xx-fb.h> 34#include <video/da8xx-fb.h>
32 35
33#define DRIVER_NAME "da8xx_lcdc" 36#define DRIVER_NAME "da8xx_lcdc"
@@ -113,6 +116,12 @@ struct da8xx_fb_par {
113 unsigned short pseudo_palette[16]; 116 unsigned short pseudo_palette[16];
114 unsigned int databuf_sz; 117 unsigned int databuf_sz;
115 unsigned int palette_sz; 118 unsigned int palette_sz;
119 unsigned int pxl_clk;
120 int blank;
121#ifdef CONFIG_CPU_FREQ
122 struct notifier_block freq_transition;
123#endif
124 void (*panel_power_ctrl)(int);
116}; 125};
117 126
118/* Variable Screen Information */ 127/* Variable Screen Information */
@@ -155,7 +164,7 @@ struct da8xx_panel {
155 int vfp; /* Vertical front porch */ 164 int vfp; /* Vertical front porch */
156 int vbp; /* Vertical back porch */ 165 int vbp; /* Vertical back porch */
157 int vsw; /* Vertical Sync Pulse Width */ 166 int vsw; /* Vertical Sync Pulse Width */
158 int pxl_clk; /* Pixel clock */ 167 unsigned int pxl_clk; /* Pixel clock */
159 unsigned char invert_pxl_clk; /* Invert Pixel clock */ 168 unsigned char invert_pxl_clk; /* Invert Pixel clock */
160}; 169};
161 170
@@ -171,7 +180,7 @@ static struct da8xx_panel known_lcd_panels[] = {
171 .vfp = 2, 180 .vfp = 2,
172 .vbp = 2, 181 .vbp = 2,
173 .vsw = 0, 182 .vsw = 0,
174 .pxl_clk = 0x10, 183 .pxl_clk = 4608000,
175 .invert_pxl_clk = 1, 184 .invert_pxl_clk = 1,
176 }, 185 },
177 /* Sharp LK043T1DG01 */ 186 /* Sharp LK043T1DG01 */
@@ -185,13 +194,23 @@ static struct da8xx_panel known_lcd_panels[] = {
185 .vfp = 2, 194 .vfp = 2,
186 .vbp = 2, 195 .vbp = 2,
187 .vsw = 10, 196 .vsw = 10,
188 .pxl_clk = 0x12, 197 .pxl_clk = 7833600,
189 .invert_pxl_clk = 0, 198 .invert_pxl_clk = 0,
190 }, 199 },
191}; 200};
192 201
202/* Enable the Raster Engine of the LCD Controller */
203static inline void lcd_enable_raster(void)
204{
205 u32 reg;
206
207 reg = lcdc_read(LCD_RASTER_CTRL_REG);
208 if (!(reg & LCD_RASTER_ENABLE))
209 lcdc_write(reg | LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
210}
211
193/* Disable the Raster Engine of the LCD Controller */ 212/* Disable the Raster Engine of the LCD Controller */
194static void lcd_disable_raster(struct da8xx_fb_par *par) 213static inline void lcd_disable_raster(void)
195{ 214{
196 u32 reg; 215 u32 reg;
197 216
@@ -443,14 +462,25 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
443static void lcd_reset(struct da8xx_fb_par *par) 462static void lcd_reset(struct da8xx_fb_par *par)
444{ 463{
445 /* Disable the Raster if previously Enabled */ 464 /* Disable the Raster if previously Enabled */
446 if (lcdc_read(LCD_RASTER_CTRL_REG) & LCD_RASTER_ENABLE) 465 lcd_disable_raster();
447 lcd_disable_raster(par);
448 466
449 /* DMA has to be disabled */ 467 /* DMA has to be disabled */
450 lcdc_write(0, LCD_DMA_CTRL_REG); 468 lcdc_write(0, LCD_DMA_CTRL_REG);
451 lcdc_write(0, LCD_RASTER_CTRL_REG); 469 lcdc_write(0, LCD_RASTER_CTRL_REG);
452} 470}
453 471
472static void lcd_calc_clk_divider(struct da8xx_fb_par *par)
473{
474 unsigned int lcd_clk, div;
475
476 lcd_clk = clk_get_rate(par->lcdc_clk);
477 div = lcd_clk / par->pxl_clk;
478
479 /* Configure the LCD clock divisor. */
480 lcdc_write(LCD_CLK_DIVISOR(div) |
481 (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG);
482}
483
454static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, 484static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
455 struct da8xx_panel *panel) 485 struct da8xx_panel *panel)
456{ 486{
@@ -459,9 +489,8 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
459 489
460 lcd_reset(par); 490 lcd_reset(par);
461 491
462 /* Configure the LCD clock divisor. */ 492 /* Calculate the divider */
463 lcdc_write(LCD_CLK_DIVISOR(panel->pxl_clk) | 493 lcd_calc_clk_divider(par);
464 (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG);
465 494
466 if (panel->invert_pxl_clk) 495 if (panel->invert_pxl_clk)
467 lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) | 496 lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) |
@@ -513,13 +542,11 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
513static irqreturn_t lcdc_irq_handler(int irq, void *arg) 542static irqreturn_t lcdc_irq_handler(int irq, void *arg)
514{ 543{
515 u32 stat = lcdc_read(LCD_STAT_REG); 544 u32 stat = lcdc_read(LCD_STAT_REG);
516 u32 reg;
517 545
518 if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { 546 if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
519 reg = lcdc_read(LCD_RASTER_CTRL_REG); 547 lcd_disable_raster();
520 lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
521 lcdc_write(stat, LCD_STAT_REG); 548 lcdc_write(stat, LCD_STAT_REG);
522 lcdc_write(reg | LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG); 549 lcd_enable_raster();
523 } else 550 } else
524 lcdc_write(stat, LCD_STAT_REG); 551 lcdc_write(stat, LCD_STAT_REG);
525 552
@@ -574,6 +601,38 @@ static int fb_check_var(struct fb_var_screeninfo *var,
574 return err; 601 return err;
575} 602}
576 603
604#ifdef CONFIG_CPU_FREQ
605static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb,
606 unsigned long val, void *data)
607{
608 struct da8xx_fb_par *par;
609
610 par = container_of(nb, struct da8xx_fb_par, freq_transition);
611 if (val == CPUFREQ_PRECHANGE) {
612 lcd_disable_raster();
613 } else if (val == CPUFREQ_POSTCHANGE) {
614 lcd_calc_clk_divider(par);
615 lcd_enable_raster();
616 }
617
618 return 0;
619}
620
621static inline int lcd_da8xx_cpufreq_register(struct da8xx_fb_par *par)
622{
623 par->freq_transition.notifier_call = lcd_da8xx_cpufreq_transition;
624
625 return cpufreq_register_notifier(&par->freq_transition,
626 CPUFREQ_TRANSITION_NOTIFIER);
627}
628
629static inline void lcd_da8xx_cpufreq_deregister(struct da8xx_fb_par *par)
630{
631 cpufreq_unregister_notifier(&par->freq_transition,
632 CPUFREQ_TRANSITION_NOTIFIER);
633}
634#endif
635
577static int __devexit fb_remove(struct platform_device *dev) 636static int __devexit fb_remove(struct platform_device *dev)
578{ 637{
579 struct fb_info *info = dev_get_drvdata(&dev->dev); 638 struct fb_info *info = dev_get_drvdata(&dev->dev);
@@ -581,8 +640,13 @@ static int __devexit fb_remove(struct platform_device *dev)
581 if (info) { 640 if (info) {
582 struct da8xx_fb_par *par = info->par; 641 struct da8xx_fb_par *par = info->par;
583 642
584 if (lcdc_read(LCD_RASTER_CTRL_REG) & LCD_RASTER_ENABLE) 643#ifdef CONFIG_CPU_FREQ
585 lcd_disable_raster(par); 644 lcd_da8xx_cpufreq_deregister(par);
645#endif
646 if (par->panel_power_ctrl)
647 par->panel_power_ctrl(0);
648
649 lcd_disable_raster();
586 lcdc_write(0, LCD_RASTER_CTRL_REG); 650 lcdc_write(0, LCD_RASTER_CTRL_REG);
587 651
588 /* disable DMA */ 652 /* disable DMA */
@@ -639,6 +703,35 @@ static int fb_ioctl(struct fb_info *info, unsigned int cmd,
639 return 0; 703 return 0;
640} 704}
641 705
706static int cfb_blank(int blank, struct fb_info *info)
707{
708 struct da8xx_fb_par *par = info->par;
709 int ret = 0;
710
711 if (par->blank == blank)
712 return 0;
713
714 par->blank = blank;
715 switch (blank) {
716 case FB_BLANK_UNBLANK:
717 if (par->panel_power_ctrl)
718 par->panel_power_ctrl(1);
719
720 lcd_enable_raster();
721 break;
722 case FB_BLANK_POWERDOWN:
723 if (par->panel_power_ctrl)
724 par->panel_power_ctrl(0);
725
726 lcd_disable_raster();
727 break;
728 default:
729 ret = -EINVAL;
730 }
731
732 return ret;
733}
734
642static struct fb_ops da8xx_fb_ops = { 735static struct fb_ops da8xx_fb_ops = {
643 .owner = THIS_MODULE, 736 .owner = THIS_MODULE,
644 .fb_check_var = fb_check_var, 737 .fb_check_var = fb_check_var,
@@ -647,6 +740,7 @@ static struct fb_ops da8xx_fb_ops = {
647 .fb_fillrect = cfb_fillrect, 740 .fb_fillrect = cfb_fillrect,
648 .fb_copyarea = cfb_copyarea, 741 .fb_copyarea = cfb_copyarea,
649 .fb_imageblit = cfb_imageblit, 742 .fb_imageblit = cfb_imageblit,
743 .fb_blank = cfb_blank,
650}; 744};
651 745
652static int __init fb_probe(struct platform_device *device) 746static int __init fb_probe(struct platform_device *device)
@@ -721,6 +815,12 @@ static int __init fb_probe(struct platform_device *device)
721 } 815 }
722 816
723 par = da8xx_fb_info->par; 817 par = da8xx_fb_info->par;
818 par->lcdc_clk = fb_clk;
819 par->pxl_clk = lcdc_info->pxl_clk;
820 if (fb_pdata->panel_power_ctrl) {
821 par->panel_power_ctrl = fb_pdata->panel_power_ctrl;
822 par->panel_power_ctrl(1);
823 }
724 824
725 if (lcd_init(par, lcd_cfg, lcdc_info) < 0) { 825 if (lcd_init(par, lcd_cfg, lcdc_info) < 0) {
726 dev_err(&device->dev, "lcd_init failed\n"); 826 dev_err(&device->dev, "lcd_init failed\n");
@@ -754,8 +854,6 @@ static int __init fb_probe(struct platform_device *device)
754 da8xx_fb_fix.smem_len = par->databuf_sz - par->palette_sz; 854 da8xx_fb_fix.smem_len = par->databuf_sz - par->palette_sz;
755 da8xx_fb_fix.line_length = (lcdc_info->width * lcd_cfg->bpp) / 8; 855 da8xx_fb_fix.line_length = (lcdc_info->width * lcd_cfg->bpp) / 8;
756 856
757 par->lcdc_clk = fb_clk;
758
759 par->irq = platform_get_irq(device, 0); 857 par->irq = platform_get_irq(device, 0);
760 if (par->irq < 0) { 858 if (par->irq < 0) {
761 ret = -ENOENT; 859 ret = -ENOENT;
@@ -814,12 +912,24 @@ static int __init fb_probe(struct platform_device *device)
814 goto err_dealloc_cmap; 912 goto err_dealloc_cmap;
815 } 913 }
816 914
915#ifdef CONFIG_CPU_FREQ
916 ret = lcd_da8xx_cpufreq_register(par);
917 if (ret) {
918 dev_err(&device->dev, "failed to register cpufreq\n");
919 goto err_cpu_freq;
920 }
921#endif
922
817 /* enable raster engine */ 923 /* enable raster engine */
818 lcdc_write(lcdc_read(LCD_RASTER_CTRL_REG) | 924 lcd_enable_raster();
819 LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
820 925
821 return 0; 926 return 0;
822 927
928#ifdef CONFIG_CPU_FREQ
929err_cpu_freq:
930 unregister_framebuffer(da8xx_fb_info);
931#endif
932
823err_dealloc_cmap: 933err_dealloc_cmap:
824 fb_dealloc_cmap(&da8xx_fb_info->cmap); 934 fb_dealloc_cmap(&da8xx_fb_info->cmap);
825 935
@@ -852,11 +962,35 @@ err_request_mem:
852#ifdef CONFIG_PM 962#ifdef CONFIG_PM
853static int fb_suspend(struct platform_device *dev, pm_message_t state) 963static int fb_suspend(struct platform_device *dev, pm_message_t state)
854{ 964{
855 return -EBUSY; 965 struct fb_info *info = platform_get_drvdata(dev);
966 struct da8xx_fb_par *par = info->par;
967
968 acquire_console_sem();
969 if (par->panel_power_ctrl)
970 par->panel_power_ctrl(0);
971
972 fb_set_suspend(info, 1);
973 lcd_disable_raster();
974 clk_disable(par->lcdc_clk);
975 release_console_sem();
976
977 return 0;
856} 978}
857static int fb_resume(struct platform_device *dev) 979static int fb_resume(struct platform_device *dev)
858{ 980{
859 return -EBUSY; 981 struct fb_info *info = platform_get_drvdata(dev);
982 struct da8xx_fb_par *par = info->par;
983
984 acquire_console_sem();
985 if (par->panel_power_ctrl)
986 par->panel_power_ctrl(1);
987
988 clk_enable(par->lcdc_clk);
989 lcd_enable_raster();
990 fb_set_suspend(info, 0);
991 release_console_sem();
992
993 return 0;
860} 994}
861#else 995#else
862#define fb_suspend NULL 996#define fb_suspend NULL
diff --git a/drivers/video/display/display-sysfs.c b/drivers/video/display/display-sysfs.c
index 4830b1bf51e5..f6a09ab0dac6 100644
--- a/drivers/video/display/display-sysfs.c
+++ b/drivers/video/display/display-sysfs.c
@@ -27,6 +27,7 @@
27#include <linux/idr.h> 27#include <linux/idr.h>
28#include <linux/err.h> 28#include <linux/err.h>
29#include <linux/kdev_t.h> 29#include <linux/kdev_t.h>
30#include <linux/slab.h>
30 31
31static ssize_t display_show_name(struct device *dev, 32static ssize_t display_show_name(struct device *dev,
32 struct device_attribute *attr, char *buf) 33 struct device_attribute *attr, char *buf)
@@ -67,7 +68,7 @@ static ssize_t display_store_contrast(struct device *dev,
67 contrast = simple_strtoul(buf, &endp, 0); 68 contrast = simple_strtoul(buf, &endp, 0);
68 size = endp - buf; 69 size = endp - buf;
69 70
70 if (*endp && isspace(*endp)) 71 if (isspace(*endp))
71 size++; 72 size++;
72 73
73 if (size != count) 74 if (size != count)
diff --git a/drivers/video/dnfb.c b/drivers/video/dnfb.c
index 606da043f4b4..ec56d2544c73 100644
--- a/drivers/video/dnfb.c
+++ b/drivers/video/dnfb.c
@@ -2,7 +2,6 @@
2#include <linux/errno.h> 2#include <linux/errno.h>
3#include <linux/string.h> 3#include <linux/string.h>
4#include <linux/mm.h> 4#include <linux/mm.h>
5#include <linux/slab.h>
6#include <linux/delay.h> 5#include <linux/delay.h>
7#include <linux/interrupt.h> 6#include <linux/interrupt.h>
8#include <linux/platform_device.h> 7#include <linux/platform_device.h>
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c
index eb12182b2059..ecf405562f5c 100644
--- a/drivers/video/efifb.c
+++ b/drivers/video/efifb.c
@@ -49,6 +49,7 @@ enum {
49 M_MBP_2, /* MacBook Pro 2nd gen */ 49 M_MBP_2, /* MacBook Pro 2nd gen */
50 M_MBP_SR, /* MacBook Pro (Santa Rosa) */ 50 M_MBP_SR, /* MacBook Pro (Santa Rosa) */
51 M_MBP_4, /* MacBook Pro, 4th gen */ 51 M_MBP_4, /* MacBook Pro, 4th gen */
52 M_MBP_5_1, /* MacBook Pro, 5,1th gen */
52 M_UNKNOWN /* placeholder */ 53 M_UNKNOWN /* placeholder */
53}; 54};
54 55
@@ -70,6 +71,7 @@ static struct efifb_dmi_info {
70 [M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */ 71 [M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */
71 [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 }, 72 [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 },
72 [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 }, 73 [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 },
74 [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900 },
73 [M_UNKNOWN] = { NULL, 0, 0, 0, 0 } 75 [M_UNKNOWN] = { NULL, 0, 0, 0, 0 }
74}; 76};
75 77
@@ -106,6 +108,7 @@ static struct dmi_system_id __initdata dmi_system_table[] = {
106 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro3,1", M_MBP_SR), 108 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro3,1", M_MBP_SR),
107 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro3,1", M_MBP_SR), 109 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro3,1", M_MBP_SR),
108 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro4,1", M_MBP_4), 110 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro4,1", M_MBP_4),
111 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,1", M_MBP_5_1),
109 {}, 112 {},
110}; 113};
111 114
@@ -161,8 +164,17 @@ static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green,
161 return 0; 164 return 0;
162} 165}
163 166
167static void efifb_destroy(struct fb_info *info)
168{
169 if (info->screen_base)
170 iounmap(info->screen_base);
171 release_mem_region(info->aperture_base, info->aperture_size);
172 framebuffer_release(info);
173}
174
164static struct fb_ops efifb_ops = { 175static struct fb_ops efifb_ops = {
165 .owner = THIS_MODULE, 176 .owner = THIS_MODULE,
177 .fb_destroy = efifb_destroy,
166 .fb_setcolreg = efifb_setcolreg, 178 .fb_setcolreg = efifb_setcolreg,
167 .fb_fillrect = cfb_fillrect, 179 .fb_fillrect = cfb_fillrect,
168 .fb_copyarea = cfb_copyarea, 180 .fb_copyarea = cfb_copyarea,
@@ -201,7 +213,7 @@ static int __init efifb_setup(char *options)
201 return 0; 213 return 0;
202} 214}
203 215
204static int __init efifb_probe(struct platform_device *dev) 216static int __devinit efifb_probe(struct platform_device *dev)
205{ 217{
206 struct fb_info *info; 218 struct fb_info *info;
207 int err; 219 int err;
@@ -281,7 +293,7 @@ static int __init efifb_probe(struct platform_device *dev)
281 info->par = NULL; 293 info->par = NULL;
282 294
283 info->aperture_base = efifb_fix.smem_start; 295 info->aperture_base = efifb_fix.smem_start;
284 info->aperture_size = size_total; 296 info->aperture_size = size_remap;
285 297
286 info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len); 298 info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len);
287 if (!info->screen_base) { 299 if (!info->screen_base) {
diff --git a/drivers/video/ep93xx-fb.c b/drivers/video/ep93xx-fb.c
index bd9d46f95291..0c99de0562ca 100644
--- a/drivers/video/ep93xx-fb.c
+++ b/drivers/video/ep93xx-fb.c
@@ -19,6 +19,7 @@
19 19
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/dma-mapping.h> 21#include <linux/dma-mapping.h>
22#include <linux/slab.h>
22#include <linux/clk.h> 23#include <linux/clk.h>
23#include <linux/fb.h> 24#include <linux/fb.h>
24 25
@@ -358,6 +359,8 @@ static int ep93xxfb_setcolreg(unsigned int regno, unsigned int red,
358 359
359 switch (info->fix.visual) { 360 switch (info->fix.visual) {
360 case FB_VISUAL_PSEUDOCOLOR: 361 case FB_VISUAL_PSEUDOCOLOR:
362 if (regno > 255)
363 return 1;
361 rgb = ((red & 0xff00) << 8) | (green & 0xff00) | 364 rgb = ((red & 0xff00) << 8) | (green & 0xff00) |
362 ((blue & 0xff00) >> 8); 365 ((blue & 0xff00) >> 8);
363 366
diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c
index 2735b79e52a1..db9713b49ce9 100644
--- a/drivers/video/epson1355fb.c
+++ b/drivers/video/epson1355fb.c
@@ -48,7 +48,6 @@
48#include <linux/errno.h> 48#include <linux/errno.h>
49#include <linux/string.h> 49#include <linux/string.h>
50#include <linux/mm.h> 50#include <linux/mm.h>
51#include <linux/slab.h>
52#include <linux/delay.h> 51#include <linux/delay.h>
53#include <linux/fb.h> 52#include <linux/fb.h>
54#include <linux/init.h> 53#include <linux/init.h>
@@ -602,7 +601,7 @@ static int epson1355fb_remove(struct platform_device *dev)
602 return 0; 601 return 0;
603} 602}
604 603
605int __init epson1355fb_probe(struct platform_device *dev) 604int __devinit epson1355fb_probe(struct platform_device *dev)
606{ 605{
607 struct epson1355_par *default_par; 606 struct epson1355_par *default_par;
608 struct fb_info *info; 607 struct fb_info *info;
diff --git a/drivers/video/fb_ddc.c b/drivers/video/fb_ddc.c
index 0cf96eb8a60f..4a874c8d039c 100644
--- a/drivers/video/fb_ddc.c
+++ b/drivers/video/fb_ddc.c
@@ -12,6 +12,7 @@
12#include <linux/device.h> 12#include <linux/device.h>
13#include <linux/fb.h> 13#include <linux/fb.h>
14#include <linux/i2c-algo-bit.h> 14#include <linux/i2c-algo-bit.h>
15#include <linux/slab.h>
15 16
16#include "edid.h" 17#include "edid.h"
17 18
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c
index c27ab1ed9604..6113c47e095a 100644
--- a/drivers/video/fb_defio.c
+++ b/drivers/video/fb_defio.c
@@ -13,7 +13,6 @@
13#include <linux/errno.h> 13#include <linux/errno.h>
14#include <linux/string.h> 14#include <linux/string.h>
15#include <linux/mm.h> 15#include <linux/mm.h>
16#include <linux/slab.h>
17#include <linux/vmalloc.h> 16#include <linux/vmalloc.h>
18#include <linux/delay.h> 17#include <linux/delay.h>
19#include <linux/interrupt.h> 18#include <linux/interrupt.h>
@@ -71,7 +70,7 @@ int fb_deferred_io_fsync(struct file *file, struct dentry *dentry, int datasync)
71{ 70{
72 struct fb_info *info = file->private_data; 71 struct fb_info *info = file->private_data;
73 72
74 /* Skip if deferred io is complied-in but disabled on this fbdev */ 73 /* Skip if deferred io is compiled-in but disabled on this fbdev */
75 if (!info->fbdefio) 74 if (!info->fbdefio)
76 return 0; 75 return 0;
77 76
@@ -144,7 +143,9 @@ static const struct address_space_operations fb_deferred_io_aops = {
144static int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma) 143static int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma)
145{ 144{
146 vma->vm_ops = &fb_deferred_io_vm_ops; 145 vma->vm_ops = &fb_deferred_io_vm_ops;
147 vma->vm_flags |= ( VM_IO | VM_RESERVED | VM_DONTEXPAND ); 146 vma->vm_flags |= ( VM_RESERVED | VM_DONTEXPAND );
147 if (!(info->flags & FBINFO_VIRTFB))
148 vma->vm_flags |= VM_IO;
148 vma->vm_private_data = info; 149 vma->vm_private_data = info;
149 return 0; 150 return 0;
150} 151}
diff --git a/drivers/video/fbcvt.c b/drivers/video/fbcvt.c
index 0847c5e72cbd..7293eaccd81b 100644
--- a/drivers/video/fbcvt.c
+++ b/drivers/video/fbcvt.c
@@ -13,6 +13,7 @@
13 * 13 *
14 */ 14 */
15#include <linux/fb.h> 15#include <linux/fb.h>
16#include <linux/slab.h>
16 17
17#define FB_CVT_CELLSIZE 8 18#define FB_CVT_CELLSIZE 8
18#define FB_CVT_GTF_C 40 19#define FB_CVT_GTF_C 40
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 99bbd282ce63..a15b44e9c003 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1513,7 +1513,6 @@ register_framebuffer(struct fb_info *fb_info)
1513 fb_info->fix.id, 1513 fb_info->fix.id,
1514 registered_fb[i]->fix.id); 1514 registered_fb[i]->fix.id);
1515 unregister_framebuffer(registered_fb[i]); 1515 unregister_framebuffer(registered_fb[i]);
1516 break;
1517 } 1516 }
1518 } 1517 }
1519 } 1518 }
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 9ae9cd32bd06..563a98b88e9b 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -29,6 +29,7 @@
29#include <linux/fb.h> 29#include <linux/fb.h>
30#include <linux/module.h> 30#include <linux/module.h>
31#include <linux/pci.h> 31#include <linux/pci.h>
32#include <linux/slab.h>
32#include <video/edid.h> 33#include <video/edid.h>
33#ifdef CONFIG_PPC_OF 34#ifdef CONFIG_PPC_OF
34#include <asm/prom.h> 35#include <asm/prom.h>
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index d4a2c11d9809..81aa3129c17d 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -16,6 +16,7 @@
16 */ 16 */
17 17
18#include <linux/kernel.h> 18#include <linux/kernel.h>
19#include <linux/slab.h>
19#include <linux/fb.h> 20#include <linux/fb.h>
20#include <linux/console.h> 21#include <linux/console.h>
21#include <linux/module.h> 22#include <linux/module.h>
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c
index 9dbb9646081f..a42fabab69df 100644
--- a/drivers/video/ffb.c
+++ b/drivers/video/ffb.c
@@ -10,7 +10,6 @@
10#include <linux/kernel.h> 10#include <linux/kernel.h>
11#include <linux/errno.h> 11#include <linux/errno.h>
12#include <linux/string.h> 12#include <linux/string.h>
13#include <linux/slab.h>
14#include <linux/delay.h> 13#include <linux/delay.h>
15#include <linux/init.h> 14#include <linux/init.h>
16#include <linux/fb.h> 15#include <linux/fb.h>
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index 72d68b3dc478..994358a4f302 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -1536,6 +1536,7 @@ static int __devinit fsl_diu_probe(struct of_device *ofdev,
1536 goto error; 1536 goto error;
1537 } 1537 }
1538 1538
1539 sysfs_attr_init(&machine_data->dev_attr.attr);
1539 machine_data->dev_attr.attr.name = "monitor"; 1540 machine_data->dev_attr.attr.name = "monitor";
1540 machine_data->dev_attr.attr.mode = S_IRUGO|S_IWUSR; 1541 machine_data->dev_attr.attr.mode = S_IRUGO|S_IWUSR;
1541 machine_data->dev_attr.show = show_monitor; 1542 machine_data->dev_attr.show = show_monitor;
@@ -1633,6 +1634,11 @@ static int __init fsl_diu_setup(char *options)
1633#endif 1634#endif
1634 1635
1635static struct of_device_id fsl_diu_match[] = { 1636static struct of_device_id fsl_diu_match[] = {
1637#ifdef CONFIG_PPC_MPC512x
1638 {
1639 .compatible = "fsl,mpc5121-diu",
1640 },
1641#endif
1636 { 1642 {
1637 .compatible = "fsl,diu", 1643 .compatible = "fsl,diu",
1638 }, 1644 },
diff --git a/drivers/video/g364fb.c b/drivers/video/g364fb.c
index b7655c05da53..d662317d85e3 100644
--- a/drivers/video/g364fb.c
+++ b/drivers/video/g364fb.c
@@ -20,7 +20,6 @@
20#include <linux/errno.h> 20#include <linux/errno.h>
21#include <linux/string.h> 21#include <linux/string.h>
22#include <linux/mm.h> 22#include <linux/mm.h>
23#include <linux/slab.h>
24#include <linux/vmalloc.h> 23#include <linux/vmalloc.h>
25#include <linux/delay.h> 24#include <linux/delay.h>
26#include <linux/interrupt.h> 25#include <linux/interrupt.h>
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index f67db4268374..7d8c55d7fd28 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -13,6 +13,7 @@
13#include <linux/platform_device.h> 13#include <linux/platform_device.h>
14#include <linux/dma-mapping.h> 14#include <linux/dma-mapping.h>
15#include <linux/errno.h> 15#include <linux/errno.h>
16#include <linux/gfp.h>
16#include <linux/fb.h> 17#include <linux/fb.h>
17#include <linux/init.h> 18#include <linux/init.h>
18#include <linux/interrupt.h> 19#include <linux/interrupt.h>
@@ -701,7 +702,7 @@ static int gbefb_set_par(struct fb_info *info)
701 blocks of 512x128, 256x128 or 128x128 pixels, respectively for 8bit, 702 blocks of 512x128, 256x128 or 128x128 pixels, respectively for 8bit,
702 16bit and 32 bit modes (64 kB). They cover the screen with partial 703 16bit and 32 bit modes (64 kB). They cover the screen with partial
703 tiles on the right and/or bottom of the screen if needed. 704 tiles on the right and/or bottom of the screen if needed.
704 For exemple in 640x480 8 bit mode the mapping is: 705 For example in 640x480 8 bit mode the mapping is:
705 706
706 <-------- 640 -----> 707 <-------- 640 ----->
707 <---- 512 ----><128|384 offscreen> 708 <---- 512 ----><128|384 offscreen>
@@ -1128,7 +1129,7 @@ static int __init gbefb_setup(char *options)
1128 return 0; 1129 return 0;
1129} 1130}
1130 1131
1131static int __init gbefb_probe(struct platform_device *p_dev) 1132static int __devinit gbefb_probe(struct platform_device *p_dev)
1132{ 1133{
1133 int i, ret = 0; 1134 int i, ret = 0;
1134 struct fb_info *info; 1135 struct fb_info *info;
diff --git a/drivers/video/geode/display_gx.c b/drivers/video/geode/display_gx.c
index e759895bf3d3..f0af911a096d 100644
--- a/drivers/video/geode/display_gx.c
+++ b/drivers/video/geode/display_gx.c
@@ -17,7 +17,7 @@
17#include <asm/io.h> 17#include <asm/io.h>
18#include <asm/div64.h> 18#include <asm/div64.h>
19#include <asm/delay.h> 19#include <asm/delay.h>
20#include <asm/geode.h> 20#include <linux/cs5535.h>
21 21
22#include "gxfb.h" 22#include "gxfb.h"
23 23
@@ -25,7 +25,7 @@ unsigned int gx_frame_buffer_size(void)
25{ 25{
26 unsigned int val; 26 unsigned int val;
27 27
28 if (!geode_has_vsa2()) { 28 if (!cs5535_has_vsa2()) {
29 uint32_t hi, lo; 29 uint32_t hi, lo;
30 30
31 /* The number of pages is (PMAX - PMIN)+1 */ 31 /* The number of pages is (PMAX - PMIN)+1 */
diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/geode/gx1fb_core.c
index f20eff8c4a81..c6b554f72c6d 100644
--- a/drivers/video/geode/gx1fb_core.c
+++ b/drivers/video/geode/gx1fb_core.c
@@ -15,7 +15,6 @@
15#include <linux/errno.h> 15#include <linux/errno.h>
16#include <linux/string.h> 16#include <linux/string.h>
17#include <linux/mm.h> 17#include <linux/mm.h>
18#include <linux/slab.h>
19#include <linux/delay.h> 18#include <linux/delay.h>
20#include <linux/fb.h> 19#include <linux/fb.h>
21#include <linux/init.h> 20#include <linux/init.h>
diff --git a/drivers/video/geode/gxfb.h b/drivers/video/geode/gxfb.h
index 16a96f8fd8c5..d19e9378b0c0 100644
--- a/drivers/video/geode/gxfb.h
+++ b/drivers/video/geode/gxfb.h
@@ -340,7 +340,7 @@ static inline void write_fp(struct gxfb_par *par, int reg, uint32_t val)
340} 340}
341 341
342 342
343/* MSRs are defined in asm/geode.h; their bitfields are here */ 343/* MSRs are defined in linux/cs5535.h; their bitfields are here */
344 344
345#define MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3 (1 << 3) 345#define MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3 (1 << 3)
346#define MSR_GLCP_SYS_RSTPLL_DOTPREMULT2 (1 << 2) 346#define MSR_GLCP_SYS_RSTPLL_DOTPREMULT2 (1 << 2)
diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c
index 2552cac39e1c..76e7dac6f259 100644
--- a/drivers/video/geode/gxfb_core.c
+++ b/drivers/video/geode/gxfb_core.c
@@ -25,14 +25,13 @@
25#include <linux/errno.h> 25#include <linux/errno.h>
26#include <linux/string.h> 26#include <linux/string.h>
27#include <linux/mm.h> 27#include <linux/mm.h>
28#include <linux/slab.h>
29#include <linux/delay.h> 28#include <linux/delay.h>
30#include <linux/fb.h> 29#include <linux/fb.h>
31#include <linux/console.h> 30#include <linux/console.h>
32#include <linux/suspend.h> 31#include <linux/suspend.h>
33#include <linux/init.h> 32#include <linux/init.h>
34#include <linux/pci.h> 33#include <linux/pci.h>
35#include <asm/geode.h> 34#include <linux/cs5535.h>
36 35
37#include "gxfb.h" 36#include "gxfb.h"
38 37
diff --git a/drivers/video/geode/lxfb.h b/drivers/video/geode/lxfb.h
index 6a51448fd3f7..e4c4d89b7860 100644
--- a/drivers/video/geode/lxfb.h
+++ b/drivers/video/geode/lxfb.h
@@ -1,3 +1,13 @@
1/* Geode LX framebuffer driver
2 *
3 * Copyright (C) 2006-2007, Advanced Micro Devices,Inc.
4 * Copyright (c) 2008 Andres Salomon <dilinger@debian.org>
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 as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
1#ifndef _LXFB_H_ 11#ifndef _LXFB_H_
2#define _LXFB_H_ 12#define _LXFB_H_
3 13
@@ -355,6 +365,8 @@ enum fp_registers {
355 FP_CRC, /* 0x458 */ 365 FP_CRC, /* 0x458 */
356}; 366};
357 367
368#define FP_PT2_HSP (1 << 22)
369#define FP_PT2_VSP (1 << 23)
358#define FP_PT2_SCRC (1 << 27) /* shfclk free */ 370#define FP_PT2_SCRC (1 << 27) /* shfclk free */
359 371
360#define FP_PM_P (1 << 24) /* panel power ctl */ 372#define FP_PM_P (1 << 24) /* panel power ctl */
@@ -409,7 +421,7 @@ static inline void write_fp(struct lxfb_par *par, int reg, uint32_t val)
409} 421}
410 422
411 423
412/* MSRs are defined in asm/geode.h; their bitfields are here */ 424/* MSRs are defined in linux/cs5535.h; their bitfields are here */
413 425
414#define MSR_GLCP_DOTPLL_LOCK (1 << 25) /* r/o */ 426#define MSR_GLCP_DOTPLL_LOCK (1 << 25) /* r/o */
415#define MSR_GLCP_DOTPLL_HALFPIX (1 << 24) 427#define MSR_GLCP_DOTPLL_HALFPIX (1 << 24)
diff --git a/drivers/video/geode/lxfb_core.c b/drivers/video/geode/lxfb_core.c
index 889cbe39e580..1a18da86d3fa 100644
--- a/drivers/video/geode/lxfb_core.c
+++ b/drivers/video/geode/lxfb_core.c
@@ -16,7 +16,6 @@
16#include <linux/string.h> 16#include <linux/string.h>
17#include <linux/console.h> 17#include <linux/console.h>
18#include <linux/mm.h> 18#include <linux/mm.h>
19#include <linux/slab.h>
20#include <linux/suspend.h> 19#include <linux/suspend.h>
21#include <linux/delay.h> 20#include <linux/delay.h>
22#include <linux/fb.h> 21#include <linux/fb.h>
diff --git a/drivers/video/geode/lxfb_ops.c b/drivers/video/geode/lxfb_ops.c
index b1cd49c99356..bc35a95e59d4 100644
--- a/drivers/video/geode/lxfb_ops.c
+++ b/drivers/video/geode/lxfb_ops.c
@@ -13,7 +13,7 @@
13#include <linux/fb.h> 13#include <linux/fb.h>
14#include <linux/uaccess.h> 14#include <linux/uaccess.h>
15#include <linux/delay.h> 15#include <linux/delay.h>
16#include <asm/geode.h> 16#include <linux/cs5535.h>
17 17
18#include "lxfb.h" 18#include "lxfb.h"
19 19
@@ -274,7 +274,15 @@ static void lx_graphics_enable(struct fb_info *info)
274 u32 msrlo, msrhi; 274 u32 msrlo, msrhi;
275 275
276 write_fp(par, FP_PT1, 0); 276 write_fp(par, FP_PT1, 0);
277 write_fp(par, FP_PT2, FP_PT2_SCRC); 277 temp = FP_PT2_SCRC;
278
279 if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
280 temp |= FP_PT2_HSP;
281
282 if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
283 temp |= FP_PT2_VSP;
284
285 write_fp(par, FP_PT2, temp);
278 write_fp(par, FP_DFC, FP_DFC_BC); 286 write_fp(par, FP_DFC, FP_DFC_BC);
279 287
280 msrlo = MSR_LX_MSR_PADSEL_TFT_SEL_LOW; 288 msrlo = MSR_LX_MSR_PADSEL_TFT_SEL_LOW;
@@ -307,7 +315,7 @@ unsigned int lx_framebuffer_size(void)
307{ 315{
308 unsigned int val; 316 unsigned int val;
309 317
310 if (!geode_has_vsa2()) { 318 if (!cs5535_has_vsa2()) {
311 uint32_t hi, lo; 319 uint32_t hi, lo;
312 320
313 /* The number of pages is (PMAX - PMIN)+1 */ 321 /* The number of pages is (PMAX - PMIN)+1 */
diff --git a/drivers/video/geode/suspend_gx.c b/drivers/video/geode/suspend_gx.c
index 9aff32ef8bb6..1bb043d70c64 100644
--- a/drivers/video/geode/suspend_gx.c
+++ b/drivers/video/geode/suspend_gx.c
@@ -10,7 +10,7 @@
10#include <linux/fb.h> 10#include <linux/fb.h>
11#include <asm/io.h> 11#include <asm/io.h>
12#include <asm/msr.h> 12#include <asm/msr.h>
13#include <asm/geode.h> 13#include <linux/cs5535.h>
14#include <asm/delay.h> 14#include <asm/delay.h>
15 15
16#include "gxfb.h" 16#include "gxfb.h"
diff --git a/drivers/video/geode/video_gx.c b/drivers/video/geode/video_gx.c
index b8d52a8360db..6082f653c68a 100644
--- a/drivers/video/geode/video_gx.c
+++ b/drivers/video/geode/video_gx.c
@@ -16,7 +16,7 @@
16#include <asm/io.h> 16#include <asm/io.h>
17#include <asm/delay.h> 17#include <asm/delay.h>
18#include <asm/msr.h> 18#include <asm/msr.h>
19#include <asm/geode.h> 19#include <linux/cs5535.h>
20 20
21#include "gxfb.h" 21#include "gxfb.h"
22 22
diff --git a/drivers/video/hecubafb.c b/drivers/video/hecubafb.c
index 0b4bffbe67c8..c77bcc6ab463 100644
--- a/drivers/video/hecubafb.c
+++ b/drivers/video/hecubafb.c
@@ -32,7 +32,6 @@
32#include <linux/errno.h> 32#include <linux/errno.h>
33#include <linux/string.h> 33#include <linux/string.h>
34#include <linux/mm.h> 34#include <linux/mm.h>
35#include <linux/slab.h>
36#include <linux/vmalloc.h> 35#include <linux/vmalloc.h>
37#include <linux/delay.h> 36#include <linux/delay.h>
38#include <linux/interrupt.h> 37#include <linux/interrupt.h>
@@ -253,7 +252,7 @@ static int __devinit hecubafb_probe(struct platform_device *dev)
253 par->send_command = apollo_send_command; 252 par->send_command = apollo_send_command;
254 par->send_data = apollo_send_data; 253 par->send_data = apollo_send_data;
255 254
256 info->flags = FBINFO_FLAG_DEFAULT; 255 info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
257 256
258 info->fbdefio = &hecubafb_defio; 257 info->fbdefio = &hecubafb_defio;
259 fb_deferred_io_init(info); 258 fb_deferred_io_init(info);
diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c
index 0129c044f6d6..8bbf251f83d9 100644
--- a/drivers/video/hgafb.c
+++ b/drivers/video/hgafb.c
@@ -36,7 +36,6 @@
36#include <linux/spinlock.h> 36#include <linux/spinlock.h>
37#include <linux/string.h> 37#include <linux/string.h>
38#include <linux/mm.h> 38#include <linux/mm.h>
39#include <linux/slab.h>
40#include <linux/delay.h> 39#include <linux/delay.h>
41#include <linux/fb.h> 40#include <linux/fb.h>
42#include <linux/init.h> 41#include <linux/init.h>
@@ -551,7 +550,7 @@ static struct fb_ops hgafb_ops = {
551 * Initialization 550 * Initialization
552 */ 551 */
553 552
554static int __init hgafb_probe(struct platform_device *pdev) 553static int __devinit hgafb_probe(struct platform_device *pdev)
555{ 554{
556 struct fb_info *info; 555 struct fb_info *info;
557 556
diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c
index e7116a6d82d3..393f3f3d3dfe 100644
--- a/drivers/video/hitfb.c
+++ b/drivers/video/hitfb.c
@@ -16,7 +16,6 @@
16#include <linux/errno.h> 16#include <linux/errno.h>
17#include <linux/string.h> 17#include <linux/string.h>
18#include <linux/mm.h> 18#include <linux/mm.h>
19#include <linux/slab.h>
20#include <linux/delay.h> 19#include <linux/delay.h>
21#include <linux/init.h> 20#include <linux/init.h>
22#include <linux/platform_device.h> 21#include <linux/platform_device.h>
@@ -325,7 +324,7 @@ static struct fb_ops hitfb_ops = {
325 .fb_imageblit = cfb_imageblit, 324 .fb_imageblit = cfb_imageblit,
326}; 325};
327 326
328static int __init hitfb_probe(struct platform_device *dev) 327static int __devinit hitfb_probe(struct platform_device *dev)
329{ 328{
330 unsigned short lcdclor, ldr3, ldvndr; 329 unsigned short lcdclor, ldr3, ldvndr;
331 struct fb_info *info; 330 struct fb_info *info;
@@ -456,7 +455,7 @@ static int hitfb_resume(struct device *dev)
456 return 0; 455 return 0;
457} 456}
458 457
459static struct dev_pm_ops hitfb_dev_pm_ops = { 458static const struct dev_pm_ops hitfb_dev_pm_ops = {
460 .suspend = hitfb_suspend, 459 .suspend = hitfb_suspend,
461 .resume = hitfb_resume, 460 .resume = hitfb_resume,
462}; 461};
diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c
index b8ebff1e8493..c8e280f1bb0b 100644
--- a/drivers/video/hpfb.c
+++ b/drivers/video/hpfb.c
@@ -10,7 +10,6 @@
10#include <linux/errno.h> 10#include <linux/errno.h>
11#include <linux/string.h> 11#include <linux/string.h>
12#include <linux/mm.h> 12#include <linux/mm.h>
13#include <linux/slab.h>
14#include <linux/delay.h> 13#include <linux/delay.h>
15#include <linux/init.h> 14#include <linux/init.h>
16#include <linux/fb.h> 15#include <linux/fb.h>
diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c
index 9dd55e5324a1..cd2c728a809b 100644
--- a/drivers/video/i810/i810-i2c.c
+++ b/drivers/video/i810/i810-i2c.c
@@ -11,6 +11,7 @@
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/delay.h> 13#include <linux/delay.h>
14#include <linux/gfp.h>
14#include <linux/pci.h> 15#include <linux/pci.h>
15#include <linux/fb.h> 16#include <linux/fb.h>
16#include "i810.h" 17#include "i810.h"
diff --git a/drivers/video/i810/i810_dvt.c b/drivers/video/i810/i810_dvt.c
index 27fa703a2e0a..b4b3670667ab 100644
--- a/drivers/video/i810/i810_dvt.c
+++ b/drivers/video/i810/i810_dvt.c
@@ -212,24 +212,29 @@ inline void round_off_yres(u32 *xres, u32 *yres)
212 *yres = (*xres * 3) >> 2; 212 *yres = (*xres * 3) >> 2;
213} 213}
214 214
215void i810fb_encode_registers(const struct fb_var_screeninfo *var, 215static int i810fb_find_best_mode(u32 xres, u32 yres, u32 pixclock)
216 struct i810fb_par *par, u32 xres, u32 yres)
217{ 216{
218 u32 diff = 0, diff_best = 0xFFFFFFFF, i = 0, i_best = 0; 217 u32 diff = 0, diff_best = 0xFFFFFFFF, i = 0, i_best = 0;
219 u8 hfl; 218 u8 hfl = (u8) ((xres >> 3) - 1);
220 219
221 hfl = (u8) ((xres >> 3) - 1);
222 for (i = 0; i < ARRAY_SIZE(std_modes); i++) { 220 for (i = 0; i < ARRAY_SIZE(std_modes); i++) {
223 if (std_modes[i].cr01 == hfl) { 221 if (std_modes[i].cr01 == hfl) {
224 if (std_modes[i].pixclock <= par->regs.pixclock) 222 if (std_modes[i].pixclock <= pixclock)
225 diff = par->regs.pixclock - 223 diff = pixclock - std_modes[i].pixclock;
226 std_modes[i].pixclock;
227 if (diff < diff_best) { 224 if (diff < diff_best) {
228 i_best = i; 225 i_best = i;
229 diff_best = diff; 226 diff_best = diff;
230 } 227 }
231 } 228 }
232 } 229 }
230 return i_best;
231}
232
233void i810fb_encode_registers(const struct fb_var_screeninfo *var,
234 struct i810fb_par *par, u32 xres, u32 yres)
235{
236 u32 i_best = i810fb_find_best_mode(xres, yres, par->regs.pixclock);
237
233 par->regs = std_modes[i_best]; 238 par->regs = std_modes[i_best];
234 239
235 /* overlay */ 240 /* overlay */
@@ -239,36 +244,36 @@ void i810fb_encode_registers(const struct fb_var_screeninfo *var,
239 244
240void i810fb_fill_var_timings(struct fb_var_screeninfo *var) 245void i810fb_fill_var_timings(struct fb_var_screeninfo *var)
241{ 246{
242 struct i810fb_par par;
243 u32 total, xres, yres; 247 u32 total, xres, yres;
248 u32 mode, pixclock;
244 249
245 xres = var->xres; 250 xres = var->xres;
246 yres = var->yres; 251 yres = var->yres;
247 252
248 par.regs.pixclock = 1000000000/var->pixclock; 253 pixclock = 1000000000 / var->pixclock;
249 i810fb_encode_registers(var, &par, xres, yres); 254 mode = i810fb_find_best_mode(xres, yres, pixclock);
250 255
251 total = ((par.regs.cr00 | (par.regs.cr35 & 1) << 8) + 3) << 3; 256 total = (std_modes[mode].cr00 | (std_modes[mode].cr35 & 1) << 8) + 3;
257 total <<= 3;
252 258
253 var->pixclock = 1000000000/par.regs.pixclock; 259 var->pixclock = 1000000000 / std_modes[mode].pixclock;
254 var->right_margin = (par.regs.cr04 << 3) - xres; 260 var->right_margin = (std_modes[mode].cr04 << 3) - xres;
255 var->hsync_len = ((par.regs.cr05 & 0x1F) - 261 var->hsync_len = ((std_modes[mode].cr05 & 0x1F) -
256 (par.regs.cr04 & 0x1F)) << 3; 262 (std_modes[mode].cr04 & 0x1F)) << 3;
257 var->left_margin = (total - (xres + var->right_margin + 263 var->left_margin = (total - (xres + var->right_margin +
258 var->hsync_len)); 264 var->hsync_len));
259 var->sync = FB_SYNC_ON_GREEN; 265 var->sync = FB_SYNC_ON_GREEN;
260 if (~(par.regs.msr & (1 << 6))) 266 if (~(std_modes[mode].msr & (1 << 6)))
261 var->sync |= FB_SYNC_HOR_HIGH_ACT; 267 var->sync |= FB_SYNC_HOR_HIGH_ACT;
262 if (~(par.regs.msr & (1 << 7))) 268 if (~(std_modes[mode].msr & (1 << 7)))
263 var->sync |= FB_SYNC_VERT_HIGH_ACT; 269 var->sync |= FB_SYNC_VERT_HIGH_ACT;
264 270
265 271 total = (std_modes[mode].cr06 | (std_modes[mode].cr30 & 0xF) << 8) + 2;
266 total = ((par.regs.cr06 | (par.regs.cr30 & 0x0F) << 8)) + 2; 272 var->lower_margin = (std_modes[mode].cr10 |
267 var->lower_margin = (par.regs.cr10 | 273 (std_modes[mode].cr32 & 0x0F) << 8) - yres;
268 (par.regs.cr32 & 0x0F) << 8) - yres; 274 var->vsync_len = (std_modes[mode].cr11 & 0x0F) -
269 var->vsync_len = (par.regs.cr11 & 0x0F) - (var->lower_margin & 0x0F); 275 (var->lower_margin & 0x0F);
270 var->upper_margin = total - (yres + var->lower_margin + 276 var->upper_margin = total - (yres + var->lower_margin + var->vsync_len);
271 var->vsync_len);
272} 277}
273 278
274u32 i810_get_watermark(struct fb_var_screeninfo *var, 279u32 i810_get_watermark(struct fb_var_screeninfo *var,
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
index 15d50b9906ce..efb2c10656b0 100644
--- a/drivers/video/imsttfb.c
+++ b/drivers/video/imsttfb.c
@@ -21,7 +21,6 @@
21#include <linux/errno.h> 21#include <linux/errno.h>
22#include <linux/string.h> 22#include <linux/string.h>
23#include <linux/mm.h> 23#include <linux/mm.h>
24#include <linux/slab.h>
25#include <linux/vmalloc.h> 24#include <linux/vmalloc.h>
26#include <linux/delay.h> 25#include <linux/delay.h>
27#include <linux/interrupt.h> 26#include <linux/interrupt.h>
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index 66358fa825f3..b4b6deceed15 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -593,7 +593,8 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
593 */ 593 */
594static int imxfb_suspend(struct platform_device *dev, pm_message_t state) 594static int imxfb_suspend(struct platform_device *dev, pm_message_t state)
595{ 595{
596 struct imxfb_info *fbi = platform_get_drvdata(dev); 596 struct fb_info *info = platform_get_drvdata(dev);
597 struct imxfb_info *fbi = info->par;
597 598
598 pr_debug("%s\n", __func__); 599 pr_debug("%s\n", __func__);
599 600
@@ -603,7 +604,8 @@ static int imxfb_suspend(struct platform_device *dev, pm_message_t state)
603 604
604static int imxfb_resume(struct platform_device *dev) 605static int imxfb_resume(struct platform_device *dev)
605{ 606{
606 struct imxfb_info *fbi = platform_get_drvdata(dev); 607 struct fb_info *info = platform_get_drvdata(dev);
608 struct imxfb_info *fbi = info->par;
607 609
608 pr_debug("%s\n", __func__); 610 pr_debug("%s\n", __func__);
609 611
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index 0cafd642fbc0..5ba399991050 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -874,6 +874,9 @@ static int __devinit intelfb_pci_register(struct pci_dev *pdev,
874 if (bailearly == 18) 874 if (bailearly == 18)
875 bailout(dinfo); 875 bailout(dinfo);
876 876
877 /* read active pipe */
878 dinfo->pipe = intelfbhw_active_pipe(&dinfo->save_state);
879
877 /* Cursor initialisation */ 880 /* Cursor initialisation */
878 if (dinfo->hwcursor) { 881 if (dinfo->hwcursor) {
879 intelfbhw_cursor_init(dinfo); 882 intelfbhw_cursor_init(dinfo);
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
index 0689f97c5238..38065cf94ac4 100644
--- a/drivers/video/intelfb/intelfbhw.c
+++ b/drivers/video/intelfb/intelfbhw.c
@@ -24,7 +24,6 @@
24#include <linux/errno.h> 24#include <linux/errno.h>
25#include <linux/string.h> 25#include <linux/string.h>
26#include <linux/mm.h> 26#include <linux/mm.h>
27#include <linux/slab.h>
28#include <linux/delay.h> 27#include <linux/delay.h>
29#include <linux/fb.h> 28#include <linux/fb.h>
30#include <linux/ioport.h> 29#include <linux/ioport.h>
@@ -469,6 +468,32 @@ void intelfbhw_do_blank(int blank, struct fb_info *info)
469} 468}
470 469
471 470
471/* Check which pipe is connected to an active display plane. */
472int intelfbhw_active_pipe(const struct intelfb_hwstate *hw)
473{
474 int pipe = -1;
475
476 /* keep old default behaviour - prefer PIPE_A */
477 if (hw->disp_b_ctrl & DISPPLANE_PLANE_ENABLE) {
478 pipe = (hw->disp_b_ctrl >> DISPPLANE_SEL_PIPE_SHIFT);
479 pipe &= PIPE_MASK;
480 if (unlikely(pipe == PIPE_A))
481 return PIPE_A;
482 }
483 if (hw->disp_a_ctrl & DISPPLANE_PLANE_ENABLE) {
484 pipe = (hw->disp_a_ctrl >> DISPPLANE_SEL_PIPE_SHIFT);
485 pipe &= PIPE_MASK;
486 if (likely(pipe == PIPE_A))
487 return PIPE_A;
488 }
489 /* Impossible that no pipe is selected - return PIPE_A */
490 WARN_ON(pipe == -1);
491 if (unlikely(pipe == -1))
492 pipe = PIPE_A;
493
494 return pipe;
495}
496
472void intelfbhw_setcolreg(struct intelfb_info *dinfo, unsigned regno, 497void intelfbhw_setcolreg(struct intelfb_info *dinfo, unsigned regno,
473 unsigned red, unsigned green, unsigned blue, 498 unsigned red, unsigned green, unsigned blue,
474 unsigned transp) 499 unsigned transp)
@@ -1019,7 +1044,7 @@ int intelfbhw_mode_to_hw(struct intelfb_info *dinfo,
1019 struct intelfb_hwstate *hw, 1044 struct intelfb_hwstate *hw,
1020 struct fb_var_screeninfo *var) 1045 struct fb_var_screeninfo *var)
1021{ 1046{
1022 int pipe = PIPE_A; 1047 int pipe = intelfbhw_active_pipe(hw);
1023 u32 *dpll, *fp0, *fp1; 1048 u32 *dpll, *fp0, *fp1;
1024 u32 m1, m2, n, p1, p2, clock_target, clock; 1049 u32 m1, m2, n, p1, p2, clock_target, clock;
1025 u32 hsync_start, hsync_end, hblank_start, hblank_end, htotal, hactive; 1050 u32 hsync_start, hsync_end, hblank_start, hblank_end, htotal, hactive;
@@ -1033,12 +1058,6 @@ int intelfbhw_mode_to_hw(struct intelfb_info *dinfo,
1033 /* Disable VGA */ 1058 /* Disable VGA */
1034 hw->vgacntrl |= VGA_DISABLE; 1059 hw->vgacntrl |= VGA_DISABLE;
1035 1060
1036 /* Check whether pipe A or pipe B is enabled. */
1037 if (hw->pipe_a_conf & PIPECONF_ENABLE)
1038 pipe = PIPE_A;
1039 else if (hw->pipe_b_conf & PIPECONF_ENABLE)
1040 pipe = PIPE_B;
1041
1042 /* Set which pipe's registers will be set. */ 1061 /* Set which pipe's registers will be set. */
1043 if (pipe == PIPE_B) { 1062 if (pipe == PIPE_B) {
1044 dpll = &hw->dpll_b; 1063 dpll = &hw->dpll_b;
@@ -1262,7 +1281,6 @@ int intelfbhw_mode_to_hw(struct intelfb_info *dinfo,
1262int intelfbhw_program_mode(struct intelfb_info *dinfo, 1281int intelfbhw_program_mode(struct intelfb_info *dinfo,
1263 const struct intelfb_hwstate *hw, int blank) 1282 const struct intelfb_hwstate *hw, int blank)
1264{ 1283{
1265 int pipe = PIPE_A;
1266 u32 tmp; 1284 u32 tmp;
1267 const u32 *dpll, *fp0, *fp1, *pipe_conf; 1285 const u32 *dpll, *fp0, *fp1, *pipe_conf;
1268 const u32 *hs, *ht, *hb, *vs, *vt, *vb, *ss; 1286 const u32 *hs, *ht, *hb, *vs, *vt, *vb, *ss;
@@ -1272,7 +1290,7 @@ int intelfbhw_program_mode(struct intelfb_info *dinfo,
1272 u32 src_size_reg; 1290 u32 src_size_reg;
1273 u32 count, tmp_val[3]; 1291 u32 count, tmp_val[3];
1274 1292
1275 /* Assume single pipe, display plane A, analog CRT. */ 1293 /* Assume single pipe */
1276 1294
1277#if VERBOSE > 0 1295#if VERBOSE > 0
1278 DBG_MSG("intelfbhw_program_mode\n"); 1296 DBG_MSG("intelfbhw_program_mode\n");
@@ -1283,15 +1301,9 @@ int intelfbhw_program_mode(struct intelfb_info *dinfo,
1283 tmp |= VGA_DISABLE; 1301 tmp |= VGA_DISABLE;
1284 OUTREG(VGACNTRL, tmp); 1302 OUTREG(VGACNTRL, tmp);
1285 1303
1286 /* Check whether pipe A or pipe B is enabled. */ 1304 dinfo->pipe = intelfbhw_active_pipe(hw);
1287 if (hw->pipe_a_conf & PIPECONF_ENABLE)
1288 pipe = PIPE_A;
1289 else if (hw->pipe_b_conf & PIPECONF_ENABLE)
1290 pipe = PIPE_B;
1291
1292 dinfo->pipe = pipe;
1293 1305
1294 if (pipe == PIPE_B) { 1306 if (dinfo->pipe == PIPE_B) {
1295 dpll = &hw->dpll_b; 1307 dpll = &hw->dpll_b;
1296 fp0 = &hw->fpb0; 1308 fp0 = &hw->fpb0;
1297 fp1 = &hw->fpb1; 1309 fp1 = &hw->fpb1;
diff --git a/drivers/video/intelfb/intelfbhw.h b/drivers/video/intelfb/intelfbhw.h
index 0b076bac321b..216ca20f259f 100644
--- a/drivers/video/intelfb/intelfbhw.h
+++ b/drivers/video/intelfb/intelfbhw.h
@@ -604,5 +604,6 @@ extern void intelfbhw_cursor_reset(struct intelfb_info *dinfo);
604extern int intelfbhw_enable_irq(struct intelfb_info *dinfo); 604extern int intelfbhw_enable_irq(struct intelfb_info *dinfo);
605extern void intelfbhw_disable_irq(struct intelfb_info *dinfo); 605extern void intelfbhw_disable_irq(struct intelfb_info *dinfo);
606extern int intelfbhw_wait_for_vsync(struct intelfb_info *dinfo, u32 pipe); 606extern int intelfbhw_wait_for_vsync(struct intelfb_info *dinfo, u32 pipe);
607extern int intelfbhw_active_pipe(const struct intelfb_hwstate *hw);
607 608
608#endif /* _INTELFBHW_H */ 609#endif /* _INTELFBHW_H */
diff --git a/drivers/video/leo.c b/drivers/video/leo.c
index e145e2d16fe3..1db55f128490 100644
--- a/drivers/video/leo.c
+++ b/drivers/video/leo.c
@@ -11,7 +11,6 @@
11#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <linux/errno.h> 12#include <linux/errno.h>
13#include <linux/string.h> 13#include <linux/string.h>
14#include <linux/slab.h>
15#include <linux/delay.h> 14#include <linux/delay.h>
16#include <linux/init.h> 15#include <linux/init.h>
17#include <linux/fb.h> 16#include <linux/fb.h>
diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c
index d66887e8cbb1..43207cc6cc19 100644
--- a/drivers/video/macfb.c
+++ b/drivers/video/macfb.c
@@ -1,29 +1,33 @@
1/* macfb.c: Generic framebuffer for Macs whose colourmaps/modes we 1/*
2 don't know how to set */ 2 * macfb.c: Generic framebuffer for Macs whose colourmaps/modes we
3 3 * don't know how to set.
4/* (c) 1999 David Huggins-Daines <dhd@debian.org> 4 *
5 5 * (c) 1999 David Huggins-Daines <dhd@debian.org>
6 Primarily based on vesafb.c, by Gerd Knorr 6 *
7 (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de> 7 * Primarily based on vesafb.c, by Gerd Knorr
8 8 * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
9 Also uses information and code from: 9 *
10 10 * Also uses information and code from:
11 The original macfb.c from Linux/mac68k 2.0, by Alan Cox, Juergen 11 *
12 Mellinger, Mikael Forselius, Michael Schmitz, and others. 12 * The original macfb.c from Linux/mac68k 2.0, by Alan Cox, Juergen
13 13 * Mellinger, Mikael Forselius, Michael Schmitz, and others.
14 valkyriefb.c, by Martin Costabel, Kevin Schoedel, Barry Nathan, Dan 14 *
15 Jacobowitz, Paul Mackerras, Fabio Riccardi, and Geert Uytterhoeven. 15 * valkyriefb.c, by Martin Costabel, Kevin Schoedel, Barry Nathan, Dan
16 16 * Jacobowitz, Paul Mackerras, Fabio Riccardi, and Geert Uytterhoeven.
17 This code is free software. You may copy, modify, and distribute 17 *
18 it subject to the terms and conditions of the GNU General Public 18 * The VideoToolbox "Bugs" web page at
19 License, version 2, or any later version, at your convenience. */ 19 * http://rajsky.psych.nyu.edu/Tips/VideoBugs.html
20 *
21 * This code is free software. You may copy, modify, and distribute
22 * it subject to the terms and conditions of the GNU General Public
23 * License, version 2, or any later version, at your convenience.
24 */
20 25
21#include <linux/module.h> 26#include <linux/module.h>
22#include <linux/kernel.h> 27#include <linux/kernel.h>
23#include <linux/errno.h> 28#include <linux/errno.h>
24#include <linux/string.h> 29#include <linux/string.h>
25#include <linux/mm.h> 30#include <linux/mm.h>
26#include <linux/slab.h>
27#include <linux/delay.h> 31#include <linux/delay.h>
28#include <linux/nubus.h> 32#include <linux/nubus.h>
29#include <linux/init.h> 33#include <linux/init.h>
@@ -31,9 +35,6 @@
31 35
32#include <asm/setup.h> 36#include <asm/setup.h>
33#include <asm/bootinfo.h> 37#include <asm/bootinfo.h>
34#include <asm/uaccess.h>
35#include <asm/pgtable.h>
36#include <asm/irq.h>
37#include <asm/macintosh.h> 38#include <asm/macintosh.h>
38#include <asm/io.h> 39#include <asm/io.h>
39 40
@@ -44,7 +45,7 @@
44#define DAFB_BASE 0xf9800200 45#define DAFB_BASE 0xf9800200
45 46
46/* Address for the built-in Civic framebuffer in Quadra AVs */ 47/* Address for the built-in Civic framebuffer in Quadra AVs */
47#define CIVIC_BASE 0x50f30800 /* Only tested on 660AV! */ 48#define CIVIC_BASE 0x50f30800
48 49
49/* GSC (Gray Scale Controller) base address */ 50/* GSC (Gray Scale Controller) base address */
50#define GSC_BASE 0x50F20000 51#define GSC_BASE 0x50F20000
@@ -52,37 +53,9 @@
52/* CSC (Color Screen Controller) base address */ 53/* CSC (Color Screen Controller) base address */
53#define CSC_BASE 0x50F20000 54#define CSC_BASE 0x50F20000
54 55
55static int (*macfb_setpalette) (unsigned int regno, unsigned int red, 56static int (*macfb_setpalette)(unsigned int regno, unsigned int red,
56 unsigned int green, unsigned int blue, 57 unsigned int green, unsigned int blue,
57 struct fb_info *info) = NULL; 58 struct fb_info *info);
58static int valkyrie_setpalette (unsigned int regno, unsigned int red,
59 unsigned int green, unsigned int blue,
60 struct fb_info *info);
61static int dafb_setpalette (unsigned int regno, unsigned int red,
62 unsigned int green, unsigned int blue,
63 struct fb_info *fb_info);
64static int rbv_setpalette (unsigned int regno, unsigned int red,
65 unsigned int green, unsigned int blue,
66 struct fb_info *fb_info);
67static int mdc_setpalette (unsigned int regno, unsigned int red,
68 unsigned int green, unsigned int blue,
69 struct fb_info *fb_info);
70static int toby_setpalette (unsigned int regno, unsigned int red,
71 unsigned int green, unsigned int blue,
72 struct fb_info *fb_info);
73static int civic_setpalette (unsigned int regno, unsigned int red,
74 unsigned int green, unsigned int blue,
75 struct fb_info *fb_info);
76static int csc_setpalette (unsigned int regno, unsigned int red,
77 unsigned int green, unsigned int blue,
78 struct fb_info *fb_info);
79
80static struct {
81 unsigned char addr;
82 /* Note: word-aligned */
83 char pad[3];
84 unsigned char lut;
85} __iomem *valkyrie_cmap_regs;
86 59
87static struct { 60static struct {
88 unsigned char addr; 61 unsigned char addr;
@@ -116,15 +89,15 @@ static struct {
116} __iomem *civic_cmap_regs; 89} __iomem *civic_cmap_regs;
117 90
118static struct { 91static struct {
119 char pad1[0x40]; 92 char pad1[0x40];
120 unsigned char clut_waddr; /* 0x40 */ 93 unsigned char clut_waddr; /* 0x40 */
121 char pad2; 94 char pad2;
122 unsigned char clut_data; /* 0x42 */ 95 unsigned char clut_data; /* 0x42 */
123 char pad3[0x3]; 96 char pad3[0x3];
124 unsigned char clut_raddr; /* 0x46 */ 97 unsigned char clut_raddr; /* 0x46 */
125} __iomem *csc_cmap_regs; 98} __iomem *csc_cmap_regs;
126 99
127/* We will leave these the way they are for the time being */ 100/* The registers in these structs are in NuBus slot space */
128struct mdc_cmap_regs { 101struct mdc_cmap_regs {
129 char pad1[0x200200]; 102 char pad1[0x200200];
130 unsigned char addr; 103 unsigned char addr;
@@ -145,13 +118,10 @@ struct jet_cmap_regs {
145 unsigned char lut; 118 unsigned char lut;
146}; 119};
147 120
148#define PIXEL_TO_MM(a) (((a)*10)/28) /* width in mm at 72 dpi */ 121#define PIXEL_TO_MM(a) (((a)*10)/28) /* width in mm at 72 dpi */
149
150/* mode */
151static int video_slot = 0;
152 122
153static struct fb_var_screeninfo macfb_defined = { 123static struct fb_var_screeninfo macfb_defined = {
154 .bits_per_pixel = 8, 124 .bits_per_pixel = 8,
155 .activate = FB_ACTIVATE_NOW, 125 .activate = FB_ACTIVATE_NOW,
156 .width = -1, 126 .width = -1,
157 .height = -1, 127 .height = -1,
@@ -167,181 +137,152 @@ static struct fb_fix_screeninfo macfb_fix = {
167 .accel = FB_ACCEL_NONE, 137 .accel = FB_ACCEL_NONE,
168}; 138};
169 139
140static void *slot_addr;
170static struct fb_info fb_info; 141static struct fb_info fb_info;
171static u32 pseudo_palette[16]; 142static u32 pseudo_palette[16];
172static int inverse = 0; 143static int inverse;
173static int vidtest = 0; 144static int vidtest;
174 145
175static int valkyrie_setpalette (unsigned int regno, unsigned int red, 146/*
176 unsigned int green, unsigned int blue, 147 * Unlike the Valkyrie, the DAFB cannot set individual colormap
177 struct fb_info *info) 148 * registers. Therefore, we do what the MacOS driver does (no
178{ 149 * kidding!) and simply set them one by one until we hit the one we
179 unsigned long flags; 150 * want.
180 151 */
181 red >>= 8; 152static int dafb_setpalette(unsigned int regno, unsigned int red,
182 green >>= 8; 153 unsigned int green, unsigned int blue,
183 blue >>= 8; 154 struct fb_info *info)
184
185 local_irq_save(flags);
186
187 /* tell clut which address to fill */
188 nubus_writeb(regno, &valkyrie_cmap_regs->addr);
189 nop();
190
191 /* send one color channel at a time */
192 nubus_writeb(red, &valkyrie_cmap_regs->lut);
193 nop();
194 nubus_writeb(green, &valkyrie_cmap_regs->lut);
195 nop();
196 nubus_writeb(blue, &valkyrie_cmap_regs->lut);
197
198 local_irq_restore(flags);
199 return 0;
200}
201
202/* Unlike the Valkyrie, the DAFB cannot set individual colormap
203 registers. Therefore, we do what the MacOS driver does (no
204 kidding!) and simply set them one by one until we hit the one we
205 want. */
206static int dafb_setpalette (unsigned int regno, unsigned int red,
207 unsigned int green, unsigned int blue,
208 struct fb_info *info)
209{ 155{
210 /* FIXME: really, really need to use ioremap() here,
211 phys_to_virt() doesn't work anymore */
212 static int lastreg = -1; 156 static int lastreg = -1;
213 unsigned long flags; 157 unsigned long flags;
214
215 red >>= 8;
216 green >>= 8;
217 blue >>= 8;
218 158
219 local_irq_save(flags); 159 local_irq_save(flags);
220 160
221 /* fbdev will set an entire colourmap, but X won't. Hopefully 161 /*
222 this should accommodate both of them */ 162 * fbdev will set an entire colourmap, but X won't. Hopefully
223 if (regno != lastreg+1) { 163 * this should accommodate both of them
164 */
165 if (regno != lastreg + 1) {
224 int i; 166 int i;
225 167
226 /* Stab in the dark trying to reset the CLUT pointer */ 168 /* Stab in the dark trying to reset the CLUT pointer */
227 nubus_writel(0, &dafb_cmap_regs->reset); 169 nubus_writel(0, &dafb_cmap_regs->reset);
228 nop(); 170 nop();
229 171
230 /* Loop until we get to the register we want */ 172 /* Loop until we get to the register we want */
231 for (i = 0; i < regno; i++) { 173 for (i = 0; i < regno; i++) {
232 nubus_writeb(info->cmap.red[i] >> 8, &dafb_cmap_regs->lut); 174 nubus_writeb(info->cmap.red[i] >> 8,
175 &dafb_cmap_regs->lut);
233 nop(); 176 nop();
234 nubus_writeb(info->cmap.green[i] >> 8, &dafb_cmap_regs->lut); 177 nubus_writeb(info->cmap.green[i] >> 8,
178 &dafb_cmap_regs->lut);
235 nop(); 179 nop();
236 nubus_writeb(info->cmap.blue[i] >> 8, &dafb_cmap_regs->lut); 180 nubus_writeb(info->cmap.blue[i] >> 8,
181 &dafb_cmap_regs->lut);
237 nop(); 182 nop();
238 } 183 }
239 } 184 }
240 185
241 nubus_writeb(red, &dafb_cmap_regs->lut); 186 nubus_writeb(red, &dafb_cmap_regs->lut);
242 nop(); 187 nop();
243 nubus_writeb(green, &dafb_cmap_regs->lut); 188 nubus_writeb(green, &dafb_cmap_regs->lut);
244 nop(); 189 nop();
245 nubus_writeb(blue, &dafb_cmap_regs->lut); 190 nubus_writeb(blue, &dafb_cmap_regs->lut);
246 191
247 local_irq_restore(flags); 192 local_irq_restore(flags);
248 lastreg = regno; 193 lastreg = regno;
249 return 0; 194 return 0;
250} 195}
251 196
252/* V8 and Brazil seem to use the same DAC. Sonora does as well. */ 197/* V8 and Brazil seem to use the same DAC. Sonora does as well. */
253static int v8_brazil_setpalette (unsigned int regno, unsigned int red, 198static int v8_brazil_setpalette(unsigned int regno, unsigned int red,
254 unsigned int green, unsigned int blue, 199 unsigned int green, unsigned int blue,
255 struct fb_info *info) 200 struct fb_info *info)
256{ 201{
257 unsigned int bpp = info->var.bits_per_pixel; 202 unsigned int bpp = info->var.bits_per_pixel;
258 unsigned char _red =red>>8;
259 unsigned char _green=green>>8;
260 unsigned char _blue =blue>>8;
261 unsigned char _regno;
262 unsigned long flags; 203 unsigned long flags;
263 204
264 if (bpp > 8) return 1; /* failsafe */ 205 if (bpp > 8)
206 return 1; /* failsafe */
265 207
266 local_irq_save(flags); 208 local_irq_save(flags);
267 209
268 /* On these chips, the CLUT register numbers are spread out 210 /* On these chips, the CLUT register numbers are spread out
269 across the register space. Thus: 211 * across the register space. Thus:
270 212 * In 8bpp, all regnos are valid.
271 In 8bpp, all regnos are valid. 213 * In 4bpp, the regnos are 0x0f, 0x1f, 0x2f, etc, etc
272 214 * In 2bpp, the regnos are 0x3f, 0x7f, 0xbf, 0xff
273 In 4bpp, the regnos are 0x0f, 0x1f, 0x2f, etc, etc 215 */
274 216 regno = (regno << (8 - bpp)) | (0xFF >> bpp);
275 In 2bpp, the regnos are 0x3f, 0x7f, 0xbf, 0xff */ 217 nubus_writeb(regno, &v8_brazil_cmap_regs->addr);
276 _regno = (regno << (8 - bpp)) | (0xFF >> bpp); 218 nop();
277 nubus_writeb(_regno, &v8_brazil_cmap_regs->addr); nop();
278 219
279 /* send one color channel at a time */ 220 /* send one color channel at a time */
280 nubus_writeb(_red, &v8_brazil_cmap_regs->lut); nop(); 221 nubus_writeb(red, &v8_brazil_cmap_regs->lut);
281 nubus_writeb(_green, &v8_brazil_cmap_regs->lut); nop(); 222 nop();
282 nubus_writeb(_blue, &v8_brazil_cmap_regs->lut); 223 nubus_writeb(green, &v8_brazil_cmap_regs->lut);
224 nop();
225 nubus_writeb(blue, &v8_brazil_cmap_regs->lut);
283 226
284 local_irq_restore(flags); 227 local_irq_restore(flags);
285 return 0; 228 return 0;
286} 229}
287 230
288static int rbv_setpalette (unsigned int regno, unsigned int red, 231/* RAM-Based Video */
289 unsigned int green, unsigned int blue, 232static int rbv_setpalette(unsigned int regno, unsigned int red,
290 struct fb_info *info) 233 unsigned int green, unsigned int blue,
234 struct fb_info *info)
291{ 235{
292 /* use MSBs */
293 unsigned char _red =red>>8;
294 unsigned char _green=green>>8;
295 unsigned char _blue =blue>>8;
296 unsigned char _regno;
297 unsigned long flags; 236 unsigned long flags;
298 237
299 if (info->var.bits_per_pixel > 8) return 1; /* failsafe */ 238 if (info->var.bits_per_pixel > 8)
239 return 1; /* failsafe */
300 240
301 local_irq_save(flags); 241 local_irq_save(flags);
302 242
303 /* From the VideoToolbox driver. Seems to be saying that 243 /* From the VideoToolbox driver. Seems to be saying that
304 * regno #254 and #255 are the important ones for 1-bit color, 244 * regno #254 and #255 are the important ones for 1-bit color,
305 * regno #252-255 are the important ones for 2-bit color, etc. 245 * regno #252-255 are the important ones for 2-bit color, etc.
306 */ 246 */
307 _regno = regno + (256-(1 << info->var.bits_per_pixel)); 247 regno += 256 - (1 << info->var.bits_per_pixel);
308 248
309 /* reset clut? (VideoToolbox sez "not necessary") */ 249 /* reset clut? (VideoToolbox sez "not necessary") */
310 nubus_writeb(0xFF, &rbv_cmap_regs->cntl); nop(); 250 nubus_writeb(0xFF, &rbv_cmap_regs->cntl);
311 251 nop();
252
312 /* tell clut which address to use. */ 253 /* tell clut which address to use. */
313 nubus_writeb(_regno, &rbv_cmap_regs->addr); nop(); 254 nubus_writeb(regno, &rbv_cmap_regs->addr);
314 255 nop();
256
315 /* send one color channel at a time. */ 257 /* send one color channel at a time. */
316 nubus_writeb(_red, &rbv_cmap_regs->lut); nop(); 258 nubus_writeb(red, &rbv_cmap_regs->lut);
317 nubus_writeb(_green, &rbv_cmap_regs->lut); nop(); 259 nop();
318 nubus_writeb(_blue, &rbv_cmap_regs->lut); 260 nubus_writeb(green, &rbv_cmap_regs->lut);
319 261 nop();
320 local_irq_restore(flags); /* done. */ 262 nubus_writeb(blue, &rbv_cmap_regs->lut);
263
264 local_irq_restore(flags);
321 return 0; 265 return 0;
322} 266}
323 267
324/* Macintosh Display Card (8x24) */ 268/* Macintosh Display Card (8*24) */
325static int mdc_setpalette(unsigned int regno, unsigned int red, 269static int mdc_setpalette(unsigned int regno, unsigned int red,
326 unsigned int green, unsigned int blue, 270 unsigned int green, unsigned int blue,
327 struct fb_info *info) 271 struct fb_info *info)
328{ 272{
329 volatile struct mdc_cmap_regs *cmap_regs = 273 struct mdc_cmap_regs *cmap_regs = slot_addr;
330 nubus_slot_addr(video_slot);
331 /* use MSBs */
332 unsigned char _red =red>>8;
333 unsigned char _green=green>>8;
334 unsigned char _blue =blue>>8;
335 unsigned char _regno=regno;
336 unsigned long flags; 274 unsigned long flags;
337 275
338 local_irq_save(flags); 276 local_irq_save(flags);
339 277
340 /* the nop's are there to order writes. */ 278 /* the nop's are there to order writes. */
341 nubus_writeb(_regno, &cmap_regs->addr); nop(); 279 nubus_writeb(regno, &cmap_regs->addr);
342 nubus_writeb(_red, &cmap_regs->lut); nop(); 280 nop();
343 nubus_writeb(_green, &cmap_regs->lut); nop(); 281 nubus_writeb(red, &cmap_regs->lut);
344 nubus_writeb(_blue, &cmap_regs->lut); 282 nop();
283 nubus_writeb(green, &cmap_regs->lut);
284 nop();
285 nubus_writeb(blue, &cmap_regs->lut);
345 286
346 local_irq_restore(flags); 287 local_irq_restore(flags);
347 return 0; 288 return 0;
@@ -350,24 +291,26 @@ static int mdc_setpalette(unsigned int regno, unsigned int red,
350/* Toby frame buffer */ 291/* Toby frame buffer */
351static int toby_setpalette(unsigned int regno, unsigned int red, 292static int toby_setpalette(unsigned int regno, unsigned int red,
352 unsigned int green, unsigned int blue, 293 unsigned int green, unsigned int blue,
353 struct fb_info *info) 294 struct fb_info *info)
354{ 295{
355 volatile struct toby_cmap_regs *cmap_regs = 296 struct toby_cmap_regs *cmap_regs = slot_addr;
356 nubus_slot_addr(video_slot);
357 unsigned int bpp = info->var.bits_per_pixel; 297 unsigned int bpp = info->var.bits_per_pixel;
358 /* use MSBs */
359 unsigned char _red =~(red>>8);
360 unsigned char _green=~(green>>8);
361 unsigned char _blue =~(blue>>8);
362 unsigned char _regno = (regno << (8 - bpp)) | (0xFF >> bpp);
363 unsigned long flags; 298 unsigned long flags;
364 299
300 red = ~red;
301 green = ~green;
302 blue = ~blue;
303 regno = (regno << (8 - bpp)) | (0xFF >> bpp);
304
365 local_irq_save(flags); 305 local_irq_save(flags);
366 306
367 nubus_writeb(_regno, &cmap_regs->addr); nop(); 307 nubus_writeb(regno, &cmap_regs->addr);
368 nubus_writeb(_red, &cmap_regs->lut); nop(); 308 nop();
369 nubus_writeb(_green, &cmap_regs->lut); nop(); 309 nubus_writeb(red, &cmap_regs->lut);
370 nubus_writeb(_blue, &cmap_regs->lut); 310 nop();
311 nubus_writeb(green, &cmap_regs->lut);
312 nop();
313 nubus_writeb(blue, &cmap_regs->lut);
371 314
372 local_irq_restore(flags); 315 local_irq_restore(flags);
373 return 0; 316 return 0;
@@ -378,20 +321,18 @@ static int jet_setpalette(unsigned int regno, unsigned int red,
378 unsigned int green, unsigned int blue, 321 unsigned int green, unsigned int blue,
379 struct fb_info *info) 322 struct fb_info *info)
380{ 323{
381 volatile struct jet_cmap_regs *cmap_regs = 324 struct jet_cmap_regs *cmap_regs = slot_addr;
382 nubus_slot_addr(video_slot);
383 /* use MSBs */
384 unsigned char _red = (red>>8);
385 unsigned char _green = (green>>8);
386 unsigned char _blue = (blue>>8);
387 unsigned long flags; 325 unsigned long flags;
388 326
389 local_irq_save(flags); 327 local_irq_save(flags);
390 328
391 nubus_writeb(regno, &cmap_regs->addr); nop(); 329 nubus_writeb(regno, &cmap_regs->addr);
392 nubus_writeb(_red, &cmap_regs->lut); nop(); 330 nop();
393 nubus_writeb(_green, &cmap_regs->lut); nop(); 331 nubus_writeb(red, &cmap_regs->lut);
394 nubus_writeb(_blue, &cmap_regs->lut); 332 nop();
333 nubus_writeb(green, &cmap_regs->lut);
334 nop();
335 nubus_writeb(blue, &cmap_regs->lut);
395 336
396 local_irq_restore(flags); 337 local_irq_restore(flags);
397 return 0; 338 return 0;
@@ -400,53 +341,27 @@ static int jet_setpalette(unsigned int regno, unsigned int red,
400/* 341/*
401 * Civic framebuffer -- Quadra AV built-in video. A chip 342 * Civic framebuffer -- Quadra AV built-in video. A chip
402 * called Sebastian holds the actual color palettes, and 343 * called Sebastian holds the actual color palettes, and
403 * apparently, there are two different banks of 512K RAM 344 * apparently, there are two different banks of 512K RAM
404 * which can act as separate framebuffers for doing video 345 * which can act as separate framebuffers for doing video
405 * input and viewing the screen at the same time! The 840AV 346 * input and viewing the screen at the same time! The 840AV
406 * Can add another 1MB RAM to give the two framebuffers 347 * Can add another 1MB RAM to give the two framebuffers
407 * 1MB RAM apiece. 348 * 1MB RAM apiece.
408 *
409 * FIXME: this doesn't seem to work anymore.
410 */ 349 */
411static int civic_setpalette (unsigned int regno, unsigned int red, 350static int civic_setpalette(unsigned int regno, unsigned int red,
412 unsigned int green, unsigned int blue, 351 unsigned int green, unsigned int blue,
413 struct fb_info *info) 352 struct fb_info *info)
414{ 353{
415 static int lastreg = -1;
416 unsigned long flags; 354 unsigned long flags;
417 int clut_status; 355 int clut_status;
418 356
419 if (info->var.bits_per_pixel > 8) return 1; /* failsafe */ 357 if (info->var.bits_per_pixel > 8)
420 358 return 1; /* failsafe */
421 red >>= 8;
422 green >>= 8;
423 blue >>= 8;
424 359
425 local_irq_save(flags); 360 local_irq_save(flags);
426
427 /*
428 * Set the register address
429 */
430 nubus_writeb(regno, &civic_cmap_regs->addr); nop();
431 361
432 /* 362 /* Set the register address */
433 * Wait for VBL interrupt here; 363 nubus_writeb(regno, &civic_cmap_regs->addr);
434 * They're usually not enabled from Penguin, so we won't check 364 nop();
435 */
436#if 0
437 {
438#define CIVIC_VBL_OFFSET 0x120
439 volatile unsigned long *vbl = nubus_readl(civic_cmap_regs->vbl_addr + CIVIC_VBL_OFFSET);
440 /* do interrupt setup stuff here? */
441 *vbl = 0L; nop(); /* clear */
442 *vbl = 1L; nop(); /* set */
443 while (*vbl != 0L) /* wait for next vbl */
444 {
445 usleep(10); /* needed? */
446 }
447 /* do interrupt shutdown stuff here? */
448 }
449#endif
450 365
451 /* 366 /*
452 * Grab a status word and do some checking; 367 * Grab a status word and do some checking;
@@ -459,39 +374,52 @@ static int civic_setpalette (unsigned int regno, unsigned int red,
459#if 0 374#if 0
460 if ((clut_status & 0x000D) != 0) 375 if ((clut_status & 0x000D) != 0)
461 { 376 {
462 nubus_writeb(0x00, &civic_cmap_regs->lut); nop(); 377 nubus_writeb(0x00, &civic_cmap_regs->lut);
463 nubus_writeb(0x00, &civic_cmap_regs->lut); nop(); 378 nop();
379 nubus_writeb(0x00, &civic_cmap_regs->lut);
380 nop();
464 } 381 }
465#endif 382#endif
466 383
467 nubus_writeb( red, &civic_cmap_regs->lut); nop(); 384 nubus_writeb(red, &civic_cmap_regs->lut);
468 nubus_writeb(green, &civic_cmap_regs->lut); nop(); 385 nop();
469 nubus_writeb( blue, &civic_cmap_regs->lut); nop(); 386 nubus_writeb(green, &civic_cmap_regs->lut);
470 nubus_writeb( 0x00, &civic_cmap_regs->lut); nop(); 387 nop();
388 nubus_writeb(blue, &civic_cmap_regs->lut);
389 nop();
390 nubus_writeb(0x00, &civic_cmap_regs->lut);
471 } 391 }
472 else 392 else
473 { 393 {
474 unsigned char junk; 394 unsigned char junk;
475 395
476 junk = nubus_readb(&civic_cmap_regs->lut); nop(); 396 junk = nubus_readb(&civic_cmap_regs->lut);
477 junk = nubus_readb(&civic_cmap_regs->lut); nop(); 397 nop();
478 junk = nubus_readb(&civic_cmap_regs->lut); nop(); 398 junk = nubus_readb(&civic_cmap_regs->lut);
479 junk = nubus_readb(&civic_cmap_regs->lut); nop(); 399 nop();
400 junk = nubus_readb(&civic_cmap_regs->lut);
401 nop();
402 junk = nubus_readb(&civic_cmap_regs->lut);
403 nop();
480 404
481 if ((clut_status & 0x000D) != 0) 405 if ((clut_status & 0x000D) != 0)
482 { 406 {
483 nubus_writeb(0x00, &civic_cmap_regs->lut); nop(); 407 nubus_writeb(0x00, &civic_cmap_regs->lut);
484 nubus_writeb(0x00, &civic_cmap_regs->lut); nop(); 408 nop();
409 nubus_writeb(0x00, &civic_cmap_regs->lut);
410 nop();
485 } 411 }
486 412
487 nubus_writeb( red, &civic_cmap_regs->lut); nop(); 413 nubus_writeb(red, &civic_cmap_regs->lut);
488 nubus_writeb(green, &civic_cmap_regs->lut); nop(); 414 nop();
489 nubus_writeb( blue, &civic_cmap_regs->lut); nop(); 415 nubus_writeb(green, &civic_cmap_regs->lut);
490 nubus_writeb( junk, &civic_cmap_regs->lut); nop(); 416 nop();
417 nubus_writeb(blue, &civic_cmap_regs->lut);
418 nop();
419 nubus_writeb(junk, &civic_cmap_regs->lut);
491 } 420 }
492 421
493 local_irq_restore(flags); 422 local_irq_restore(flags);
494 lastreg = regno;
495 return 0; 423 return 0;
496} 424}
497 425
@@ -500,16 +428,21 @@ static int civic_setpalette (unsigned int regno, unsigned int red,
500 * (and the 5300 too, but that's a PowerMac). This function 428 * (and the 5300 too, but that's a PowerMac). This function
501 * brought to you in part by the ECSC driver for MkLinux. 429 * brought to you in part by the ECSC driver for MkLinux.
502 */ 430 */
503 431static int csc_setpalette(unsigned int regno, unsigned int red,
504static int csc_setpalette (unsigned int regno, unsigned int red, 432 unsigned int green, unsigned int blue,
505 unsigned int green, unsigned int blue, 433 struct fb_info *info)
506 struct fb_info *info)
507{ 434{
508 mdelay(1); 435 unsigned long flags;
436
437 local_irq_save(flags);
438
439 udelay(1); /* mklinux on PB 5300 waits for 260 ns */
509 nubus_writeb(regno, &csc_cmap_regs->clut_waddr); 440 nubus_writeb(regno, &csc_cmap_regs->clut_waddr);
510 nubus_writeb(red, &csc_cmap_regs->clut_data); 441 nubus_writeb(red, &csc_cmap_regs->clut_data);
511 nubus_writeb(green, &csc_cmap_regs->clut_data); 442 nubus_writeb(green, &csc_cmap_regs->clut_data);
512 nubus_writeb(blue, &csc_cmap_regs->clut_data); 443 nubus_writeb(blue, &csc_cmap_regs->clut_data);
444
445 local_irq_restore(flags);
513 return 0; 446 return 0;
514} 447}
515 448
@@ -518,10 +451,10 @@ static int macfb_setcolreg(unsigned regno, unsigned red, unsigned green,
518 struct fb_info *fb_info) 451 struct fb_info *fb_info)
519{ 452{
520 /* 453 /*
521 * Set a single color register. The values supplied are 454 * Set a single color register. The values supplied are
522 * already rounded down to the hardware's capabilities 455 * already rounded down to the hardware's capabilities
523 * (according to the entries in the `var' structure). Return 456 * (according to the entries in the `var' structure).
524 * != 0 for invalid regno. 457 * Return non-zero for invalid regno.
525 */ 458 */
526 459
527 if (regno >= fb_info->cmap.len) 460 if (regno >= fb_info->cmap.len)
@@ -536,8 +469,8 @@ static int macfb_setcolreg(unsigned regno, unsigned red, unsigned green,
536 case 4: 469 case 4:
537 case 8: 470 case 8:
538 if (macfb_setpalette) 471 if (macfb_setpalette)
539 macfb_setpalette(regno, red, green, blue, 472 macfb_setpalette(regno, red >> 8, green >> 8,
540 fb_info); 473 blue >> 8, fb_info);
541 else 474 else
542 return 1; 475 return 1;
543 break; 476 break;
@@ -555,28 +488,22 @@ static int macfb_setcolreg(unsigned regno, unsigned red, unsigned green,
555 } else { 488 } else {
556 /* 0:5:6:5 */ 489 /* 0:5:6:5 */
557 ((u32*) (fb_info->pseudo_palette))[regno] = 490 ((u32*) (fb_info->pseudo_palette))[regno] =
558 ((red & 0xf800) ) | 491 ((red & 0xf800) >> 0) |
559 ((green & 0xfc00) >> 5) | 492 ((green & 0xfc00) >> 5) |
560 ((blue & 0xf800) >> 11); 493 ((blue & 0xf800) >> 11);
561 } 494 }
562 break; 495 break;
563 /* I'm pretty sure that one or the other of these 496 /*
564 doesn't exist on 68k Macs */ 497 * 24-bit colour almost doesn't exist on 68k Macs --
498 * http://support.apple.com/kb/TA28634 (Old Article: 10992)
499 */
565 case 24: 500 case 24:
566 red >>= 8;
567 green >>= 8;
568 blue >>= 8;
569 ((u32 *)(fb_info->pseudo_palette))[regno] =
570 (red << fb_info->var.red.offset) |
571 (green << fb_info->var.green.offset) |
572 (blue << fb_info->var.blue.offset);
573 break;
574 case 32: 501 case 32:
575 red >>= 8; 502 red >>= 8;
576 green >>= 8; 503 green >>= 8;
577 blue >>= 8; 504 blue >>= 8;
578 ((u32 *)(fb_info->pseudo_palette))[regno] = 505 ((u32 *)(fb_info->pseudo_palette))[regno] =
579 (red << fb_info->var.red.offset) | 506 (red << fb_info->var.red.offset) |
580 (green << fb_info->var.green.offset) | 507 (green << fb_info->var.green.offset) |
581 (blue << fb_info->var.blue.offset); 508 (blue << fb_info->var.blue.offset);
582 break; 509 break;
@@ -597,25 +524,24 @@ static struct fb_ops macfb_ops = {
597static void __init macfb_setup(char *options) 524static void __init macfb_setup(char *options)
598{ 525{
599 char *this_opt; 526 char *this_opt;
600 527
601 if (!options || !*options) 528 if (!options || !*options)
602 return; 529 return;
603 530
604 while ((this_opt = strsep(&options, ",")) != NULL) { 531 while ((this_opt = strsep(&options, ",")) != NULL) {
605 if (!*this_opt) continue; 532 if (!*this_opt)
606 533 continue;
607 if (! strcmp(this_opt, "inverse")) 534
608 inverse=1; 535 if (!strcmp(this_opt, "inverse"))
609 /* This means "turn on experimental CLUT code" */ 536 inverse = 1;
610 else if (!strcmp(this_opt, "vidtest")) 537 else
611 vidtest=1; 538 if (!strcmp(this_opt, "vidtest"))
539 vidtest = 1; /* enable experimental CLUT code */
612 } 540 }
613} 541}
614 542
615static void __init iounmap_macfb(void) 543static void __init iounmap_macfb(void)
616{ 544{
617 if (valkyrie_cmap_regs)
618 iounmap(valkyrie_cmap_regs);
619 if (dafb_cmap_regs) 545 if (dafb_cmap_regs)
620 iounmap(dafb_cmap_regs); 546 iounmap(dafb_cmap_regs);
621 if (v8_brazil_cmap_regs) 547 if (v8_brazil_cmap_regs)
@@ -642,48 +568,55 @@ static int __init macfb_init(void)
642 if (!MACH_IS_MAC) 568 if (!MACH_IS_MAC)
643 return -ENODEV; 569 return -ENODEV;
644 570
645 /* There can only be one internal video controller anyway so 571 if (mac_bi_data.id == MAC_MODEL_Q630 ||
646 we're not too worried about this */ 572 mac_bi_data.id == MAC_MODEL_P588)
573 return -ENODEV; /* See valkyriefb.c */
574
647 macfb_defined.xres = mac_bi_data.dimensions & 0xFFFF; 575 macfb_defined.xres = mac_bi_data.dimensions & 0xFFFF;
648 macfb_defined.yres = mac_bi_data.dimensions >> 16; 576 macfb_defined.yres = mac_bi_data.dimensions >> 16;
649 macfb_defined.bits_per_pixel = mac_bi_data.videodepth; 577 macfb_defined.bits_per_pixel = mac_bi_data.videodepth;
578
650 macfb_fix.line_length = mac_bi_data.videorow; 579 macfb_fix.line_length = mac_bi_data.videorow;
651 macfb_fix.smem_len = macfb_fix.line_length * macfb_defined.yres; 580 macfb_fix.smem_len = macfb_fix.line_length * macfb_defined.yres;
652 /* Note: physical address (since 2.1.127) */ 581 /* Note: physical address (since 2.1.127) */
653 macfb_fix.smem_start = mac_bi_data.videoaddr; 582 macfb_fix.smem_start = mac_bi_data.videoaddr;
654 /* This is actually redundant with the initial mappings. 583
655 However, there are some non-obvious aspects to the way
656 those mappings are set up, so this is in fact the safest
657 way to ensure that this driver will work on every possible
658 Mac */
659 fb_info.screen_base = ioremap(mac_bi_data.videoaddr, macfb_fix.smem_len);
660
661 printk("macfb: framebuffer at 0x%08lx, mapped to 0x%p, size %dk\n",
662 macfb_fix.smem_start, fb_info.screen_base, macfb_fix.smem_len/1024);
663 printk("macfb: mode is %dx%dx%d, linelength=%d\n",
664 macfb_defined.xres, macfb_defined.yres, macfb_defined.bits_per_pixel, macfb_fix.line_length);
665
666 /* 584 /*
667 * Fill in the available video resolution 585 * This is actually redundant with the initial mappings.
586 * However, there are some non-obvious aspects to the way
587 * those mappings are set up, so this is in fact the safest
588 * way to ensure that this driver will work on every possible Mac
668 */ 589 */
669 590 fb_info.screen_base = ioremap(mac_bi_data.videoaddr,
670 macfb_defined.xres_virtual = macfb_defined.xres; 591 macfb_fix.smem_len);
671 macfb_defined.yres_virtual = macfb_defined.yres; 592 if (!fb_info.screen_base)
672 macfb_defined.height = PIXEL_TO_MM(macfb_defined.yres); 593 return -ENODEV;
673 macfb_defined.width = PIXEL_TO_MM(macfb_defined.xres);
674 594
675 printk("macfb: scrolling: redraw\n"); 595 printk("macfb: framebuffer at 0x%08lx, mapped to 0x%p, size %dk\n",
596 macfb_fix.smem_start, fb_info.screen_base,
597 macfb_fix.smem_len / 1024);
598 printk("macfb: mode is %dx%dx%d, linelength=%d\n",
599 macfb_defined.xres, macfb_defined.yres,
600 macfb_defined.bits_per_pixel, macfb_fix.line_length);
601
602 /* Fill in the available video resolution */
603 macfb_defined.xres_virtual = macfb_defined.xres;
676 macfb_defined.yres_virtual = macfb_defined.yres; 604 macfb_defined.yres_virtual = macfb_defined.yres;
605 macfb_defined.height = PIXEL_TO_MM(macfb_defined.yres);
606 macfb_defined.width = PIXEL_TO_MM(macfb_defined.xres);
677 607
678 /* some dummy values for timing to make fbset happy */ 608 /* Some dummy values for timing to make fbset happy */
679 macfb_defined.pixclock = 10000000 / macfb_defined.xres * 1000 / macfb_defined.yres; 609 macfb_defined.pixclock = 10000000 / macfb_defined.xres *
610 1000 / macfb_defined.yres;
680 macfb_defined.left_margin = (macfb_defined.xres / 8) & 0xf8; 611 macfb_defined.left_margin = (macfb_defined.xres / 8) & 0xf8;
681 macfb_defined.hsync_len = (macfb_defined.xres / 8) & 0xf8; 612 macfb_defined.hsync_len = (macfb_defined.xres / 8) & 0xf8;
682 613
683 switch (macfb_defined.bits_per_pixel) { 614 switch (macfb_defined.bits_per_pixel) {
684 case 1: 615 case 1:
685 /* XXX: I think this will catch any program that tries 616 /*
686 to do FBIO_PUTCMAP when the visual is monochrome */ 617 * XXX: I think this will catch any program that tries
618 * to do FBIO_PUTCMAP when the visual is monochrome.
619 */
687 macfb_defined.red.length = macfb_defined.bits_per_pixel; 620 macfb_defined.red.length = macfb_defined.bits_per_pixel;
688 macfb_defined.green.length = macfb_defined.bits_per_pixel; 621 macfb_defined.green.length = macfb_defined.bits_per_pixel;
689 macfb_defined.blue.length = macfb_defined.bits_per_pixel; 622 macfb_defined.blue.length = macfb_defined.bits_per_pixel;
@@ -708,53 +641,52 @@ static int __init macfb_init(void)
708 macfb_defined.green.length = 5; 641 macfb_defined.green.length = 5;
709 macfb_defined.blue.offset = 0; 642 macfb_defined.blue.offset = 0;
710 macfb_defined.blue.length = 5; 643 macfb_defined.blue.length = 5;
711 printk("macfb: directcolor: "
712 "size=1:5:5:5, shift=15:10:5:0\n");
713 video_cmap_len = 16; 644 video_cmap_len = 16;
714 /* Should actually be FB_VISUAL_DIRECTCOLOR, but this 645 /*
715 works too */ 646 * Should actually be FB_VISUAL_DIRECTCOLOR, but this
647 * works too
648 */
716 macfb_fix.visual = FB_VISUAL_TRUECOLOR; 649 macfb_fix.visual = FB_VISUAL_TRUECOLOR;
717 break; 650 break;
718 case 24: 651 case 24:
719 case 32: 652 case 32:
720 /* XXX: have to test these... can any 68k Macs
721 actually do this on internal video? */
722 macfb_defined.red.offset = 16; 653 macfb_defined.red.offset = 16;
723 macfb_defined.red.length = 8; 654 macfb_defined.red.length = 8;
724 macfb_defined.green.offset = 8; 655 macfb_defined.green.offset = 8;
725 macfb_defined.green.length = 8; 656 macfb_defined.green.length = 8;
726 macfb_defined.blue.offset = 0; 657 macfb_defined.blue.offset = 0;
727 macfb_defined.blue.length = 8; 658 macfb_defined.blue.length = 8;
728 printk("macfb: truecolor: "
729 "size=0:8:8:8, shift=0:16:8:0\n");
730 video_cmap_len = 16; 659 video_cmap_len = 16;
731 macfb_fix.visual = FB_VISUAL_TRUECOLOR; 660 macfb_fix.visual = FB_VISUAL_TRUECOLOR;
661 break;
732 default: 662 default:
733 video_cmap_len = 0; 663 video_cmap_len = 0;
734 macfb_fix.visual = FB_VISUAL_MONO01; 664 macfb_fix.visual = FB_VISUAL_MONO01;
735 printk("macfb: unknown or unsupported bit depth: %d\n", macfb_defined.bits_per_pixel); 665 printk("macfb: unknown or unsupported bit depth: %d\n",
666 macfb_defined.bits_per_pixel);
736 break; 667 break;
737 } 668 }
738 669
739 /* Hardware dependent stuff */ 670 /*
740 /* We take a wild guess that if the video physical address is 671 * We take a wild guess that if the video physical address is
741 * in nubus slot space, that the nubus card is driving video. 672 * in nubus slot space, that the nubus card is driving video.
742 * Penguin really ought to tell us whether we are using internal 673 * Penguin really ought to tell us whether we are using internal
743 * video or not. 674 * video or not.
675 * Hopefully we only find one of them. Otherwise our NuBus
676 * code is really broken :-)
744 */ 677 */
745 /* Hopefully we only find one of them. Otherwise our NuBus
746 code is really broken :-) */
747 678
748 while ((ndev = nubus_find_type(NUBUS_CAT_DISPLAY, NUBUS_TYPE_VIDEO, ndev)) 679 while ((ndev = nubus_find_type(NUBUS_CAT_DISPLAY,
749 != NULL) 680 NUBUS_TYPE_VIDEO, ndev)))
750 { 681 {
751 if (!(mac_bi_data.videoaddr >= ndev->board->slot_addr 682 unsigned long base = ndev->board->slot_addr;
752 && (mac_bi_data.videoaddr < 683
753 (unsigned long)nubus_slot_addr(ndev->board->slot+1)))) 684 if (mac_bi_data.videoaddr < base ||
685 mac_bi_data.videoaddr - base > 0xFFFFFF)
754 continue; 686 continue;
687
755 video_is_nubus = 1; 688 video_is_nubus = 1;
756 /* We should probably just use the slot address... */ 689 slot_addr = (unsigned char *)base;
757 video_slot = ndev->board->slot;
758 690
759 switch(ndev->dr_hw) { 691 switch(ndev->dr_hw) {
760 case NUBUS_DRHW_APPLE_MDC: 692 case NUBUS_DRHW_APPLE_MDC:
@@ -771,7 +703,7 @@ static int __init macfb_init(void)
771 strcpy(macfb_fix.id, "Jet"); 703 strcpy(macfb_fix.id, "Jet");
772 macfb_setpalette = jet_setpalette; 704 macfb_setpalette = jet_setpalette;
773 macfb_defined.activate = FB_ACTIVATE_NOW; 705 macfb_defined.activate = FB_ACTIVATE_NOW;
774 break; 706 break;
775 default: 707 default:
776 strcpy(macfb_fix.id, "Generic NuBus"); 708 strcpy(macfb_fix.id, "Generic NuBus");
777 break; 709 break;
@@ -779,30 +711,19 @@ static int __init macfb_init(void)
779 } 711 }
780 712
781 /* If it's not a NuBus card, it must be internal video */ 713 /* If it's not a NuBus card, it must be internal video */
782 /* FIXME: this function is getting way too big. (this driver
783 is too...) */
784 if (!video_is_nubus) 714 if (!video_is_nubus)
785 switch( mac_bi_data.id ) 715 switch (mac_bi_data.id) {
786 { 716 /*
787 /* Valkyrie Quadras */ 717 * DAFB Quadras
788 case MAC_MODEL_Q630: 718 * Note: these first four have the v7 DAFB, which is
789 /* I'm not sure about this one */ 719 * known to be rather unlike the ones used in the
790 case MAC_MODEL_P588: 720 * other models
791 strcpy(macfb_fix.id, "Valkyrie"); 721 */
792 macfb_setpalette = valkyrie_setpalette;
793 macfb_defined.activate = FB_ACTIVATE_NOW;
794 valkyrie_cmap_regs = ioremap(DAC_BASE, 0x1000);
795 break;
796
797 /* DAFB Quadras */
798 /* Note: these first four have the v7 DAFB, which is
799 known to be rather unlike the ones used in the
800 other models */
801 case MAC_MODEL_P475: 722 case MAC_MODEL_P475:
802 case MAC_MODEL_P475F: 723 case MAC_MODEL_P475F:
803 case MAC_MODEL_P575: 724 case MAC_MODEL_P575:
804 case MAC_MODEL_Q605: 725 case MAC_MODEL_Q605:
805 726
806 case MAC_MODEL_Q800: 727 case MAC_MODEL_Q800:
807 case MAC_MODEL_Q650: 728 case MAC_MODEL_Q650:
808 case MAC_MODEL_Q610: 729 case MAC_MODEL_Q610:
@@ -817,17 +738,21 @@ static int __init macfb_init(void)
817 dafb_cmap_regs = ioremap(DAFB_BASE, 0x1000); 738 dafb_cmap_regs = ioremap(DAFB_BASE, 0x1000);
818 break; 739 break;
819 740
820 /* LC II uses the V8 framebuffer */ 741 /*
742 * LC II uses the V8 framebuffer
743 */
821 case MAC_MODEL_LCII: 744 case MAC_MODEL_LCII:
822 strcpy(macfb_fix.id, "V8"); 745 strcpy(macfb_fix.id, "V8");
823 macfb_setpalette = v8_brazil_setpalette; 746 macfb_setpalette = v8_brazil_setpalette;
824 macfb_defined.activate = FB_ACTIVATE_NOW; 747 macfb_defined.activate = FB_ACTIVATE_NOW;
825 v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); 748 v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
826 break; 749 break;
827 750
828 /* IIvi, IIvx use the "Brazil" framebuffer (which is 751 /*
829 very much like the V8, it seems, and probably uses 752 * IIvi, IIvx use the "Brazil" framebuffer (which is
830 the same DAC) */ 753 * very much like the V8, it seems, and probably uses
754 * the same DAC)
755 */
831 case MAC_MODEL_IIVI: 756 case MAC_MODEL_IIVI:
832 case MAC_MODEL_IIVX: 757 case MAC_MODEL_IIVX:
833 case MAC_MODEL_P600: 758 case MAC_MODEL_P600:
@@ -836,12 +761,14 @@ static int __init macfb_init(void)
836 macfb_defined.activate = FB_ACTIVATE_NOW; 761 macfb_defined.activate = FB_ACTIVATE_NOW;
837 v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); 762 v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
838 break; 763 break;
839 764
840 /* LC III (and friends) use the Sonora framebuffer */ 765 /*
841 /* Incidentally this is also used in the non-AV models 766 * LC III (and friends) use the Sonora framebuffer
842 of the x100 PowerMacs */ 767 * Incidentally this is also used in the non-AV models
843 /* These do in fact seem to use the same DAC interface 768 * of the x100 PowerMacs
844 as the LC II. */ 769 * These do in fact seem to use the same DAC interface
770 * as the LC II.
771 */
845 case MAC_MODEL_LCIII: 772 case MAC_MODEL_LCIII:
846 case MAC_MODEL_P520: 773 case MAC_MODEL_P520:
847 case MAC_MODEL_P550: 774 case MAC_MODEL_P550:
@@ -852,9 +779,11 @@ static int __init macfb_init(void)
852 v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); 779 v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
853 break; 780 break;
854 781
855 /* IIci and IIsi use the infamous RBV chip 782 /*
856 (the IIsi is just a rebadged and crippled 783 * IIci and IIsi use the infamous RBV chip
857 IIci in a different case, BTW) */ 784 * (the IIsi is just a rebadged and crippled
785 * IIci in a different case, BTW)
786 */
858 case MAC_MODEL_IICI: 787 case MAC_MODEL_IICI:
859 case MAC_MODEL_IISI: 788 case MAC_MODEL_IISI:
860 macfb_setpalette = rbv_setpalette; 789 macfb_setpalette = rbv_setpalette;
@@ -863,7 +792,9 @@ static int __init macfb_init(void)
863 rbv_cmap_regs = ioremap(DAC_BASE, 0x1000); 792 rbv_cmap_regs = ioremap(DAC_BASE, 0x1000);
864 break; 793 break;
865 794
866 /* AVs use the Civic framebuffer */ 795 /*
796 * AVs use the Civic framebuffer
797 */
867 case MAC_MODEL_Q840: 798 case MAC_MODEL_Q840:
868 case MAC_MODEL_C660: 799 case MAC_MODEL_C660:
869 macfb_setpalette = civic_setpalette; 800 macfb_setpalette = civic_setpalette;
@@ -873,15 +804,10 @@ static int __init macfb_init(void)
873 break; 804 break;
874 805
875 806
876 /* Write a setpalette function for your machine, then 807 /*
877 you can add something similar here. These are 808 * Assorted weirdos
878 grouped by classes of video chipsets. Some of this 809 * We think this may be like the LC II
879 information is from the VideoToolbox "Bugs" web 810 */
880 page at
881 http://rajsky.psych.nyu.edu/Tips/VideoBugs.html */
882
883 /* Assorted weirdos */
884 /* We think this may be like the LC II */
885 case MAC_MODEL_LC: 811 case MAC_MODEL_LC:
886 if (vidtest) { 812 if (vidtest) {
887 macfb_setpalette = v8_brazil_setpalette; 813 macfb_setpalette = v8_brazil_setpalette;
@@ -891,7 +817,10 @@ static int __init macfb_init(void)
891 } 817 }
892 strcpy(macfb_fix.id, "LC"); 818 strcpy(macfb_fix.id, "LC");
893 break; 819 break;
894 /* We think this may be like the LC II */ 820
821 /*
822 * We think this may be like the LC II
823 */
895 case MAC_MODEL_CCL: 824 case MAC_MODEL_CCL:
896 if (vidtest) { 825 if (vidtest) {
897 macfb_setpalette = v8_brazil_setpalette; 826 macfb_setpalette = v8_brazil_setpalette;
@@ -902,31 +831,42 @@ static int __init macfb_init(void)
902 strcpy(macfb_fix.id, "Color Classic"); 831 strcpy(macfb_fix.id, "Color Classic");
903 break; 832 break;
904 833
905 /* And we *do* mean "weirdos" */ 834 /*
835 * And we *do* mean "weirdos"
836 */
906 case MAC_MODEL_TV: 837 case MAC_MODEL_TV:
907 strcpy(macfb_fix.id, "Mac TV"); 838 strcpy(macfb_fix.id, "Mac TV");
908 break; 839 break;
909 840
910 /* These don't have colour, so no need to worry */ 841 /*
842 * These don't have colour, so no need to worry
843 */
911 case MAC_MODEL_SE30: 844 case MAC_MODEL_SE30:
912 case MAC_MODEL_CLII: 845 case MAC_MODEL_CLII:
913 strcpy(macfb_fix.id, "Monochrome"); 846 strcpy(macfb_fix.id, "Monochrome");
914 break; 847 break;
915 848
916 /* Powerbooks are particularly difficult. Many of 849 /*
917 them have separate framebuffers for external and 850 * Powerbooks are particularly difficult. Many of
918 internal video, which is admittedly pretty cool, 851 * them have separate framebuffers for external and
919 but will be a bit of a headache to support here. 852 * internal video, which is admittedly pretty cool,
920 Also, many of them are grayscale, and we don't 853 * but will be a bit of a headache to support here.
921 really support that. */ 854 * Also, many of them are grayscale, and we don't
922 855 * really support that.
856 */
857
858 /*
859 * Slot 0 ROM says TIM. No external video. B&W.
860 */
923 case MAC_MODEL_PB140: 861 case MAC_MODEL_PB140:
924 case MAC_MODEL_PB145: 862 case MAC_MODEL_PB145:
925 case MAC_MODEL_PB170: 863 case MAC_MODEL_PB170:
926 strcpy(macfb_fix.id, "DDC"); 864 strcpy(macfb_fix.id, "DDC");
927 break; 865 break;
928 866
929 /* Internal is GSC, External (if present) is ViSC */ 867 /*
868 * Internal is GSC, External (if present) is ViSC
869 */
930 case MAC_MODEL_PB150: /* no external video */ 870 case MAC_MODEL_PB150: /* no external video */
931 case MAC_MODEL_PB160: 871 case MAC_MODEL_PB160:
932 case MAC_MODEL_PB165: 872 case MAC_MODEL_PB165:
@@ -936,13 +876,17 @@ static int __init macfb_init(void)
936 strcpy(macfb_fix.id, "GSC"); 876 strcpy(macfb_fix.id, "GSC");
937 break; 877 break;
938 878
939 /* Internal is TIM, External is ViSC */ 879 /*
880 * Internal is TIM, External is ViSC
881 */
940 case MAC_MODEL_PB165C: 882 case MAC_MODEL_PB165C:
941 case MAC_MODEL_PB180C: 883 case MAC_MODEL_PB180C:
942 strcpy(macfb_fix.id, "TIM"); 884 strcpy(macfb_fix.id, "TIM");
943 break; 885 break;
944 886
945 /* Internal is CSC, External is Keystone+Ariel. */ 887 /*
888 * Internal is CSC, External is Keystone+Ariel.
889 */
946 case MAC_MODEL_PB190: /* external video is optional */ 890 case MAC_MODEL_PB190: /* external video is optional */
947 case MAC_MODEL_PB520: 891 case MAC_MODEL_PB520:
948 case MAC_MODEL_PB250: 892 case MAC_MODEL_PB250:
@@ -954,7 +898,7 @@ static int __init macfb_init(void)
954 strcpy(macfb_fix.id, "CSC"); 898 strcpy(macfb_fix.id, "CSC");
955 csc_cmap_regs = ioremap(CSC_BASE, 0x1000); 899 csc_cmap_regs = ioremap(CSC_BASE, 0x1000);
956 break; 900 break;
957 901
958 default: 902 default:
959 strcpy(macfb_fix.id, "Unknown"); 903 strcpy(macfb_fix.id, "Unknown");
960 break; 904 break;
@@ -969,7 +913,7 @@ static int __init macfb_init(void)
969 err = fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0); 913 err = fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0);
970 if (err) 914 if (err)
971 goto fail_unmap; 915 goto fail_unmap;
972 916
973 err = register_framebuffer(&fb_info); 917 err = register_framebuffer(&fb_info);
974 if (err) 918 if (err)
975 goto fail_dealloc; 919 goto fail_dealloc;
diff --git a/drivers/video/macmodes.c b/drivers/video/macmodes.c
index 083f60321ed8..af86c081d2be 100644
--- a/drivers/video/macmodes.c
+++ b/drivers/video/macmodes.c
@@ -33,6 +33,10 @@
33 33
34static const struct fb_videomode mac_modedb[] = { 34static const struct fb_videomode mac_modedb[] = {
35 { 35 {
36 /* 512x384, 60Hz, Non-Interlaced (15.67 MHz dot clock) */
37 "mac2", 60, 512, 384, 63828, 80, 16, 19, 1, 32, 3,
38 0, FB_VMODE_NONINTERLACED
39 }, {
36 /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ 40 /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
37 "mac5", 60, 640, 480, 39722, 32, 32, 33, 10, 96, 2, 41 "mac5", 60, 640, 480, 39722, 32, 32, 33, 10, 96, 2,
38 0, FB_VMODE_NONINTERLACED 42 0, FB_VMODE_NONINTERLACED
@@ -41,6 +45,10 @@ static const struct fb_videomode mac_modedb[] = {
41 "mac6", 67, 640, 480, 33334, 80, 80, 39, 3, 64, 3, 45 "mac6", 67, 640, 480, 33334, 80, 80, 39, 3, 64, 3,
42 0, FB_VMODE_NONINTERLACED 46 0, FB_VMODE_NONINTERLACED
43 }, { 47 }, {
48 /* 640x870, 75Hz (portrait), Non-Interlaced (57.28 MHz dot clock) */
49 "mac7", 75, 640, 870, 17457, 80, 32, 42, 3, 80, 3,
50 0, FB_VMODE_NONINTERLACED
51 }, {
44 /* 800x600, 56 Hz, Non-Interlaced (36.00 MHz dotclock) */ 52 /* 800x600, 56 Hz, Non-Interlaced (36.00 MHz dotclock) */
45 "mac9", 56, 800, 600, 27778, 112, 40, 22, 1, 72, 2, 53 "mac9", 56, 800, 600, 27778, 112, 40, 22, 1, 72, 2,
46 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED 54 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
@@ -105,10 +113,6 @@ static const struct fb_videomode mac_modedb[] = {
105 "mac1", 60, 512, 384, pixclock, left, right, upper, lower, hslen, vslen, 113 "mac1", 60, 512, 384, pixclock, left, right, upper, lower, hslen, vslen,
106 sync, FB_VMODE_INTERLACED 114 sync, FB_VMODE_INTERLACED
107 }, { 115 }, {
108 /* VMODE_512_384_60: 512x384, 60Hz, Non-Interlaced */
109 "mac2", 60, 512, 384, pixclock, left, right, upper, lower, hslen, vslen,
110 sync, FB_VMODE_NONINTERLACED
111 }, {
112 /* VMODE_640_480_50I: 640x480, 50Hz, Interlaced (PAL) */ 116 /* VMODE_640_480_50I: 640x480, 50Hz, Interlaced (PAL) */
113 "mac3", 50, 640, 480, pixclock, left, right, upper, lower, hslen, vslen, 117 "mac3", 50, 640, 480, pixclock, left, right, upper, lower, hslen, vslen,
114 sync, FB_VMODE_INTERLACED 118 sync, FB_VMODE_INTERLACED
@@ -117,10 +121,6 @@ static const struct fb_videomode mac_modedb[] = {
117 "mac4", 60, 640, 480, pixclock, left, right, upper, lower, hslen, vslen, 121 "mac4", 60, 640, 480, pixclock, left, right, upper, lower, hslen, vslen,
118 sync, FB_VMODE_INTERLACED 122 sync, FB_VMODE_INTERLACED
119 }, { 123 }, {
120 /* VMODE_640_870_75P: 640x870, 75Hz (portrait), Non-Interlaced */
121 "mac7", 75, 640, 870, pixclock, left, right, upper, lower, hslen, vslen,
122 sync, FB_VMODE_NONINTERLACED
123 }, {
124 /* VMODE_768_576_50I: 768x576, 50Hz (PAL full frame), Interlaced */ 124 /* VMODE_768_576_50I: 768x576, 50Hz (PAL full frame), Interlaced */
125 "mac8", 50, 768, 576, pixclock, left, right, upper, lower, hslen, vslen, 125 "mac8", 50, 768, 576, pixclock, left, right, upper, lower, hslen, vslen,
126 sync, FB_VMODE_INTERLACED 126 sync, FB_VMODE_INTERLACED
@@ -134,38 +134,42 @@ static const struct fb_videomode mac_modedb[] = {
134 * 134 *
135 * These MUST be ordered in 135 * These MUST be ordered in
136 * - increasing resolution 136 * - increasing resolution
137 * - decreasing refresh rate 137 * - decreasing pixel clock period
138 */ 138 */
139 139
140static const struct mode_map { 140static const struct mode_map {
141 int vmode; 141 int vmode;
142 const struct fb_videomode *mode; 142 const struct fb_videomode *mode;
143} mac_modes[] = { 143} mac_modes[] = {
144 /* 512x384 */
145 { VMODE_512_384_60, &mac_modedb[0] },
144 /* 640x480 */ 146 /* 640x480 */
145 { VMODE_640_480_67, &mac_modedb[1] }, 147 { VMODE_640_480_60, &mac_modedb[1] },
146 { VMODE_640_480_60, &mac_modedb[0] }, 148 { VMODE_640_480_67, &mac_modedb[2] },
149 /* 640x870 */
150 { VMODE_640_870_75P, &mac_modedb[3] },
147 /* 800x600 */ 151 /* 800x600 */
148 { VMODE_800_600_75, &mac_modedb[5] }, 152 { VMODE_800_600_56, &mac_modedb[4] },
149 { VMODE_800_600_72, &mac_modedb[4] }, 153 { VMODE_800_600_60, &mac_modedb[5] },
150 { VMODE_800_600_60, &mac_modedb[3] }, 154 { VMODE_800_600_75, &mac_modedb[7] },
151 { VMODE_800_600_56, &mac_modedb[2] }, 155 { VMODE_800_600_72, &mac_modedb[6] },
152 /* 832x624 */ 156 /* 832x624 */
153 { VMODE_832_624_75, &mac_modedb[6] }, 157 { VMODE_832_624_75, &mac_modedb[8] },
154 /* 1024x768 */ 158 /* 1024x768 */
155 { VMODE_1024_768_75, &mac_modedb[10] }, 159 { VMODE_1024_768_60, &mac_modedb[9] },
156 { VMODE_1024_768_75V, &mac_modedb[9] }, 160 { VMODE_1024_768_70, &mac_modedb[10] },
157 { VMODE_1024_768_70, &mac_modedb[8] }, 161 { VMODE_1024_768_75V, &mac_modedb[11] },
158 { VMODE_1024_768_60, &mac_modedb[7] }, 162 { VMODE_1024_768_75, &mac_modedb[12] },
159 /* 1152x768 */ 163 /* 1152x768 */
160 { VMODE_1152_768_60, &mac_modedb[14] }, 164 { VMODE_1152_768_60, &mac_modedb[16] },
161 /* 1152x870 */ 165 /* 1152x870 */
162 { VMODE_1152_870_75, &mac_modedb[11] }, 166 { VMODE_1152_870_75, &mac_modedb[13] },
163 /* 1280x960 */ 167 /* 1280x960 */
164 { VMODE_1280_960_75, &mac_modedb[12] }, 168 { VMODE_1280_960_75, &mac_modedb[14] },
165 /* 1280x1024 */ 169 /* 1280x1024 */
166 { VMODE_1280_1024_75, &mac_modedb[13] }, 170 { VMODE_1280_1024_75, &mac_modedb[15] },
167 /* 1600x1024 */ 171 /* 1600x1024 */
168 { VMODE_1600_1024_60, &mac_modedb[15] }, 172 { VMODE_1600_1024_60, &mac_modedb[17] },
169 { -1, NULL } 173 { -1, NULL }
170}; 174};
171 175
@@ -299,7 +303,6 @@ EXPORT_SYMBOL(mac_vmode_to_var);
299int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode, 303int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
300 int *cmode) 304 int *cmode)
301{ 305{
302 const struct fb_videomode *mode = NULL;
303 const struct mode_map *map; 306 const struct mode_map *map;
304 307
305 if (var->bits_per_pixel <= 8) 308 if (var->bits_per_pixel <= 8)
@@ -311,8 +314,13 @@ int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
311 else 314 else
312 return -EINVAL; 315 return -EINVAL;
313 316
317 /*
318 * Find the mac_mode with a matching resolution or failing that, the
319 * closest larger resolution. Skip modes with a shorter pixel clock period.
320 */
314 for (map = mac_modes; map->vmode != -1; map++) { 321 for (map = mac_modes; map->vmode != -1; map++) {
315 mode = map->mode; 322 const struct fb_videomode *mode = map->mode;
323
316 if (var->xres > mode->xres || var->yres > mode->yres) 324 if (var->xres > mode->xres || var->yres > mode->yres)
317 continue; 325 continue;
318 if (var->xres_virtual > mode->xres || var->yres_virtual > mode->yres) 326 if (var->xres_virtual > mode->xres || var->yres_virtual > mode->yres)
@@ -322,6 +330,24 @@ int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
322 if ((var->vmode & FB_VMODE_MASK) != mode->vmode) 330 if ((var->vmode & FB_VMODE_MASK) != mode->vmode)
323 continue; 331 continue;
324 *vmode = map->vmode; 332 *vmode = map->vmode;
333
334 /*
335 * Having found a good resolution, find the matching pixel clock
336 * or failing that, the closest longer pixel clock period.
337 */
338 map++;
339 while (map->vmode != -1) {
340 const struct fb_videomode *clk_mode = map->mode;
341
342 if (mode->xres != clk_mode->xres || mode->yres != clk_mode->yres)
343 break;
344 if (var->pixclock > mode->pixclock)
345 break;
346 if (mode->vmode != clk_mode->vmode)
347 continue;
348 *vmode = map->vmode;
349 map++;
350 }
325 return 0; 351 return 0;
326 } 352 }
327 return -EINVAL; 353 return -EINVAL;
diff --git a/drivers/video/matrox/g450_pll.c b/drivers/video/matrox/g450_pll.c
index 09f6e045d5be..c15f8a57498e 100644
--- a/drivers/video/matrox/g450_pll.c
+++ b/drivers/video/matrox/g450_pll.c
@@ -368,7 +368,8 @@ static int __g450_setclk(struct matrox_fb_info *minfo, unsigned int fout,
368 M1064_XDVICLKCTRL_C1DVICLKEN | 368 M1064_XDVICLKCTRL_C1DVICLKEN |
369 M1064_XDVICLKCTRL_DVILOOPCTL | 369 M1064_XDVICLKCTRL_DVILOOPCTL |
370 M1064_XDVICLKCTRL_P1LOOPBWDTCTL; 370 M1064_XDVICLKCTRL_P1LOOPBWDTCTL;
371 matroxfb_DAC_out(minfo, M1064_XDVICLKCTRL, tmp); 371 /* Setting this breaks PC systems so don't do it */
372 /* matroxfb_DAC_out(minfo, M1064_XDVICLKCTRL, tmp); */
372 matroxfb_DAC_out(minfo, M1064_XPWRCTRL, 373 matroxfb_DAC_out(minfo, M1064_XPWRCTRL,
373 xpwrctrl); 374 xpwrctrl);
374 375
diff --git a/drivers/video/matrox/i2c-matroxfb.c b/drivers/video/matrox/i2c-matroxfb.c
index f3728ab262f8..403b14445a78 100644
--- a/drivers/video/matrox/i2c-matroxfb.c
+++ b/drivers/video/matrox/i2c-matroxfb.c
@@ -13,6 +13,7 @@
13#include "matroxfb_base.h" 13#include "matroxfb_base.h"
14#include "matroxfb_maven.h" 14#include "matroxfb_maven.h"
15#include <linux/i2c.h> 15#include <linux/i2c.h>
16#include <linux/slab.h>
16#include <linux/i2c-algo-bit.h> 17#include <linux/i2c-algo-bit.h>
17 18
18/* MGA-TVO I2C for G200, G400 */ 19/* MGA-TVO I2C for G200, G400 */
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 7064fb4427b6..052dd9f0b760 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -113,6 +113,7 @@
113#include "matroxfb_g450.h" 113#include "matroxfb_g450.h"
114#include <linux/matroxfb.h> 114#include <linux/matroxfb.h>
115#include <linux/interrupt.h> 115#include <linux/interrupt.h>
116#include <linux/slab.h>
116#include <linux/uaccess.h> 117#include <linux/uaccess.h>
117 118
118#ifdef CONFIG_PPC_PMAC 119#ifdef CONFIG_PPC_PMAC
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c
index 78414baa5a54..d7112c39614b 100644
--- a/drivers/video/matrox/matroxfb_crtc2.c
+++ b/drivers/video/matrox/matroxfb_crtc2.c
@@ -15,6 +15,7 @@
15#include "matroxfb_misc.h" 15#include "matroxfb_misc.h"
16#include "matroxfb_DAC1064.h" 16#include "matroxfb_DAC1064.h"
17#include <linux/matroxfb.h> 17#include <linux/matroxfb.h>
18#include <linux/slab.h>
18#include <linux/uaccess.h> 19#include <linux/uaccess.h>
19 20
20/* **************************************************** */ 21/* **************************************************** */
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index 91af9159111f..1e3e8f19783e 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -17,6 +17,7 @@
17#include "matroxfb_DAC1064.h" 17#include "matroxfb_DAC1064.h"
18#include <linux/i2c.h> 18#include <linux/i2c.h>
19#include <linux/matroxfb.h> 19#include <linux/matroxfb.h>
20#include <linux/slab.h>
20#include <asm/div64.h> 21#include <asm/div64.h>
21 22
22#define MGATVO_B 1 23#define MGATVO_B 1
diff --git a/drivers/video/maxinefb.c b/drivers/video/maxinefb.c
index 5e91c2b30af9..5cf52d3c8e75 100644
--- a/drivers/video/maxinefb.c
+++ b/drivers/video/maxinefb.c
@@ -28,7 +28,6 @@
28#include <linux/errno.h> 28#include <linux/errno.h>
29#include <linux/string.h> 29#include <linux/string.h>
30#include <linux/mm.h> 30#include <linux/mm.h>
31#include <linux/slab.h>
32#include <linux/delay.h> 31#include <linux/delay.h>
33#include <linux/init.h> 32#include <linux/init.h>
34#include <linux/fb.h> 33#include <linux/fb.h>
@@ -92,6 +91,9 @@ static int maxinefb_setcolreg(unsigned regno, unsigned red, unsigned green,
92 /* value to be written into the palette reg. */ 91 /* value to be written into the palette reg. */
93 unsigned long hw_colorvalue = 0; 92 unsigned long hw_colorvalue = 0;
94 93
94 if (regno > 255)
95 return 1;
96
95 red >>= 8; /* The cmap fields are 16 bits */ 97 red >>= 8; /* The cmap fields are 16 bits */
96 green >>= 8; /* wide, but the harware colormap */ 98 green >>= 8; /* wide, but the harware colormap */
97 blue >>= 8; /* registers are only 8 bits wide */ 99 blue >>= 8; /* registers are only 8 bits wide */
diff --git a/drivers/video/mb862xx/Makefile b/drivers/video/mb862xx/Makefile
index 07664814bb1d..d7777714166b 100644
--- a/drivers/video/mb862xx/Makefile
+++ b/drivers/video/mb862xx/Makefile
@@ -2,4 +2,4 @@
2# Makefile for the MB862xx framebuffer driver 2# Makefile for the MB862xx framebuffer driver
3# 3#
4 4
5obj-$(CONFIG_FB_MB862XX) := mb862xxfb.o 5obj-$(CONFIG_FB_MB862XX) := mb862xxfb.o mb862xxfb_accel.o
diff --git a/drivers/video/mb862xx/mb862xxfb.c b/drivers/video/mb862xx/mb862xxfb.c
index a28e3cfbbf70..8280a58a0e55 100644
--- a/drivers/video/mb862xx/mb862xxfb.c
+++ b/drivers/video/mb862xx/mb862xxfb.c
@@ -31,15 +31,6 @@
31#define CARMINE_MEM_SIZE 0x8000000 31#define CARMINE_MEM_SIZE 0x8000000
32#define DRV_NAME "mb862xxfb" 32#define DRV_NAME "mb862xxfb"
33 33
34#if defined(CONFIG_LWMON5)
35static struct mb862xx_gc_mode lwmon5_gc_mode = {
36 /* Mode for Sharp LQ104V1DG61 TFT LCD Panel */
37 { "640x480", 60, 640, 480, 40000, 48, 16, 32, 11, 96, 2, 0, 0, 0 },
38 /* 16 bits/pixel, 32MB, 100MHz, SDRAM memory mode value */
39 16, 0x2000000, GC_CCF_COT_100, 0x414fb7f2
40};
41#endif
42
43#if defined(CONFIG_SOCRATES) 34#if defined(CONFIG_SOCRATES)
44static struct mb862xx_gc_mode socrates_gc_mode = { 35static struct mb862xx_gc_mode socrates_gc_mode = {
45 /* Mode for Prime View PM070WL4 TFT LCD Panel */ 36 /* Mode for Prime View PM070WL4 TFT LCD Panel */
@@ -214,6 +205,8 @@ static int mb862xxfb_set_par(struct fb_info *fbi)
214 unsigned long reg, sc; 205 unsigned long reg, sc;
215 206
216 dev_dbg(par->dev, "%s\n", __func__); 207 dev_dbg(par->dev, "%s\n", __func__);
208 if (par->type == BT_CORALP)
209 mb862xxfb_init_accel(fbi, fbi->var.xres);
217 210
218 if (par->pre_init) 211 if (par->pre_init)
219 return 0; 212 return 0;
@@ -453,6 +446,18 @@ static ssize_t mb862xxfb_show_dispregs(struct device *dev,
453 ptr += sprintf(ptr, "%08x = %08x\n", 446 ptr += sprintf(ptr, "%08x = %08x\n",
454 reg, inreg(disp, reg)); 447 reg, inreg(disp, reg));
455 448
449 for (reg = 0x400; reg <= 0x410; reg += 4)
450 ptr += sprintf(ptr, "geo %08x = %08x\n",
451 reg, inreg(geo, reg));
452
453 for (reg = 0x400; reg <= 0x410; reg += 4)
454 ptr += sprintf(ptr, "draw %08x = %08x\n",
455 reg, inreg(draw, reg));
456
457 for (reg = 0x440; reg <= 0x450; reg += 4)
458 ptr += sprintf(ptr, "draw %08x = %08x\n",
459 reg, inreg(draw, reg));
460
456 return ptr - buf; 461 return ptr - buf;
457} 462}
458 463
@@ -586,10 +591,6 @@ static int __devinit of_platform_mb862xx_probe(struct of_device *ofdev,
586 goto irqdisp; 591 goto irqdisp;
587 } 592 }
588 593
589#if defined(CONFIG_LWMON5)
590 par->gc_mode = &lwmon5_gc_mode;
591#endif
592
593#if defined(CONFIG_SOCRATES) 594#if defined(CONFIG_SOCRATES)
594 par->gc_mode = &socrates_gc_mode; 595 par->gc_mode = &socrates_gc_mode;
595#endif 596#endif
diff --git a/drivers/video/mb862xx/mb862xxfb.h b/drivers/video/mb862xx/mb862xxfb.h
index c4c8f4dd2217..d7e7cb76bbf2 100644
--- a/drivers/video/mb862xx/mb862xxfb.h
+++ b/drivers/video/mb862xx/mb862xxfb.h
@@ -61,6 +61,8 @@ struct mb862xxfb_par {
61 u32 pseudo_palette[16]; 61 u32 pseudo_palette[16];
62}; 62};
63 63
64extern void mb862xxfb_init_accel(struct fb_info *info, int xres);
65
64#if defined(CONFIG_FB_MB862XX_LIME) && defined(CONFIG_FB_MB862XX_PCI_GDC) 66#if defined(CONFIG_FB_MB862XX_LIME) && defined(CONFIG_FB_MB862XX_PCI_GDC)
65#error "Select Lime GDC or CoralP/Carmine support, but not both together" 67#error "Select Lime GDC or CoralP/Carmine support, but not both together"
66#endif 68#endif
diff --git a/drivers/video/mb862xx/mb862xxfb_accel.c b/drivers/video/mb862xx/mb862xxfb_accel.c
new file mode 100644
index 000000000000..fe92eed6da70
--- /dev/null
+++ b/drivers/video/mb862xx/mb862xxfb_accel.c
@@ -0,0 +1,335 @@
1/*
2 * drivers/mb862xx/mb862xxfb_accel.c
3 *
4 * Fujitsu Carmine/Coral-P(A)/Lime framebuffer driver acceleration support
5 *
6 * (C) 2007 Alexander Shishkin <virtuoso@slind.org>
7 * (C) 2009 Valentin Sitdikov <v.sitdikov@gmail.com>
8 * (C) 2009 Siemens AG
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 *
14 */
15#include <linux/fb.h>
16#include <linux/delay.h>
17#include <linux/init.h>
18#include <linux/interrupt.h>
19#include <linux/module.h>
20#include <linux/pci.h>
21#include <linux/slab.h>
22#if defined(CONFIG_OF)
23#include <linux/of_platform.h>
24#endif
25#include "mb862xxfb.h"
26#include "mb862xx_reg.h"
27#include "mb862xxfb_accel.h"
28
29static void mb862xxfb_write_fifo(u32 count, u32 *data, struct fb_info *info)
30{
31 struct mb862xxfb_par *par = info->par;
32 static u32 free;
33
34 u32 total = 0;
35 while (total < count) {
36 if (free) {
37 outreg(geo, GDC_GEO_REG_INPUT_FIFO, data[total]);
38 total++;
39 free--;
40 } else {
41 free = (u32) inreg(draw, GDC_REG_FIFO_COUNT);
42 }
43 }
44}
45
46static void mb86290fb_copyarea(struct fb_info *info,
47 const struct fb_copyarea *area)
48{
49 __u32 cmd[6];
50
51 cmd[0] = (GDC_TYPE_SETREGISTER << 24) | (1 << 16) | GDC_REG_MODE_BITMAP;
52 /* Set raster operation */
53 cmd[1] = (2 << 7) | (GDC_ROP_COPY << 9);
54 cmd[2] = GDC_TYPE_BLTCOPYP << 24;
55
56 if (area->sx >= area->dx && area->sy >= area->dy)
57 cmd[2] |= GDC_CMD_BLTCOPY_TOP_LEFT << 16;
58 else if (area->sx >= area->dx && area->sy <= area->dy)
59 cmd[2] |= GDC_CMD_BLTCOPY_BOTTOM_LEFT << 16;
60 else if (area->sx <= area->dx && area->sy >= area->dy)
61 cmd[2] |= GDC_CMD_BLTCOPY_TOP_RIGHT << 16;
62 else
63 cmd[2] |= GDC_CMD_BLTCOPY_BOTTOM_RIGHT << 16;
64
65 cmd[3] = (area->sy << 16) | area->sx;
66 cmd[4] = (area->dy << 16) | area->dx;
67 cmd[5] = (area->height << 16) | area->width;
68 mb862xxfb_write_fifo(6, cmd, info);
69}
70
71/*
72 * Fill in the cmd array /GDC FIFO commands/ to draw a 1bit image.
73 * Make sure cmd has enough room!
74 */
75static void mb86290fb_imageblit1(u32 *cmd, u16 step, u16 dx, u16 dy,
76 u16 width, u16 height, u32 fgcolor,
77 u32 bgcolor, const struct fb_image *image,
78 struct fb_info *info)
79{
80 int i;
81 unsigned const char *line;
82 u16 bytes;
83
84 /* set colors and raster operation regs */
85 cmd[0] = (GDC_TYPE_SETREGISTER << 24) | (1 << 16) | GDC_REG_MODE_BITMAP;
86 /* Set raster operation */
87 cmd[1] = (2 << 7) | (GDC_ROP_COPY << 9);
88 cmd[2] =
89 (GDC_TYPE_SETCOLORREGISTER << 24) | (GDC_CMD_BODY_FORE_COLOR << 16);
90 cmd[3] = fgcolor;
91 cmd[4] =
92 (GDC_TYPE_SETCOLORREGISTER << 24) | (GDC_CMD_BODY_BACK_COLOR << 16);
93 cmd[5] = bgcolor;
94
95 i = 0;
96 line = image->data;
97 bytes = (image->width + 7) >> 3;
98
99 /* and the image */
100 cmd[6] = (GDC_TYPE_DRAWBITMAPP << 24) |
101 (GDC_CMD_BITMAP << 16) | (2 + (step * height));
102 cmd[7] = (dy << 16) | dx;
103 cmd[8] = (height << 16) | width;
104
105 while (i < height) {
106 memcpy(&cmd[9 + i * step], line, step << 2);
107#ifdef __LITTLE_ENDIAN
108 {
109 int k = 0;
110 for (k = 0; k < step; k++)
111 cmd[9 + i * step + k] =
112 cpu_to_be32(cmd[9 + i * step + k]);
113 }
114#endif
115 line += bytes;
116 i++;
117 }
118}
119
120/*
121 * Fill in the cmd array /GDC FIFO commands/ to draw a 8bit image.
122 * Make sure cmd has enough room!
123 */
124static void mb86290fb_imageblit8(u32 *cmd, u16 step, u16 dx, u16 dy,
125 u16 width, u16 height, u32 fgcolor,
126 u32 bgcolor, const struct fb_image *image,
127 struct fb_info *info)
128{
129 int i, j;
130 unsigned const char *line, *ptr;
131 u16 bytes;
132
133 cmd[0] = (GDC_TYPE_DRAWBITMAPP << 24) |
134 (GDC_CMD_BLT_DRAW << 16) | (2 + (height * step));
135 cmd[1] = (dy << 16) | dx;
136 cmd[2] = (height << 16) | width;
137
138 i = 0;
139 line = ptr = image->data;
140 bytes = image->width;
141
142 while (i < height) {
143 ptr = line;
144 for (j = 0; j < step; j++) {
145 cmd[3 + i * step + j] =
146 (((u32 *) (info->pseudo_palette))[*ptr]) & 0xffff;
147 ptr++;
148 cmd[3 + i * step + j] |=
149 ((((u32 *) (info->
150 pseudo_palette))[*ptr]) & 0xffff) << 16;
151 ptr++;
152 }
153
154 line += bytes;
155 i++;
156 }
157}
158
159/*
160 * Fill in the cmd array /GDC FIFO commands/ to draw a 16bit image.
161 * Make sure cmd has enough room!
162 */
163static void mb86290fb_imageblit16(u32 *cmd, u16 step, u16 dx, u16 dy,
164 u16 width, u16 height, u32 fgcolor,
165 u32 bgcolor, const struct fb_image *image,
166 struct fb_info *info)
167{
168 int i;
169 unsigned const char *line;
170 u16 bytes;
171
172 i = 0;
173 line = image->data;
174 bytes = image->width << 1;
175
176 cmd[0] = (GDC_TYPE_DRAWBITMAPP << 24) |
177 (GDC_CMD_BLT_DRAW << 16) | (2 + step * height);
178 cmd[1] = (dy << 16) | dx;
179 cmd[2] = (height << 16) | width;
180
181 while (i < height) {
182 memcpy(&cmd[3 + i * step], line, step);
183 line += bytes;
184 i++;
185 }
186}
187
188static void mb86290fb_imageblit(struct fb_info *info,
189 const struct fb_image *image)
190{
191 int mdr;
192 u32 *cmd = NULL;
193 void (*cmdfn) (u32 *, u16, u16, u16, u16, u16, u32, u32,
194 const struct fb_image *, struct fb_info *) = NULL;
195 u32 cmdlen;
196 u32 fgcolor = 0, bgcolor = 0;
197 u16 step;
198
199 u16 width = image->width, height = image->height;
200 u16 dx = image->dx, dy = image->dy;
201 int x2, y2, vxres, vyres;
202
203 mdr = (GDC_ROP_COPY << 9);
204 x2 = image->dx + image->width;
205 y2 = image->dy + image->height;
206 vxres = info->var.xres_virtual;
207 vyres = info->var.yres_virtual;
208 x2 = min(x2, vxres);
209 y2 = min(y2, vyres);
210 width = x2 - dx;
211 height = y2 - dy;
212
213 switch (image->depth) {
214 case 1:
215 step = (width + 31) >> 5;
216 cmdlen = 9 + height * step;
217 cmdfn = mb86290fb_imageblit1;
218 if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
219 info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
220 fgcolor =
221 ((u32 *) (info->pseudo_palette))[image->fg_color];
222 bgcolor =
223 ((u32 *) (info->pseudo_palette))[image->bg_color];
224 } else {
225 fgcolor = image->fg_color;
226 bgcolor = image->bg_color;
227 }
228
229 break;
230
231 case 8:
232 step = (width + 1) >> 1;
233 cmdlen = 3 + height * step;
234 cmdfn = mb86290fb_imageblit8;
235 break;
236
237 case 16:
238 step = (width + 1) >> 1;
239 cmdlen = 3 + height * step;
240 cmdfn = mb86290fb_imageblit16;
241 break;
242
243 default:
244 cfb_imageblit(info, image);
245 return;
246 }
247
248 cmd = kmalloc(cmdlen * 4, GFP_DMA);
249 if (!cmd)
250 return cfb_imageblit(info, image);
251 cmdfn(cmd, step, dx, dy, width, height, fgcolor, bgcolor, image, info);
252 mb862xxfb_write_fifo(cmdlen, cmd, info);
253 kfree(cmd);
254}
255
256static void mb86290fb_fillrect(struct fb_info *info,
257 const struct fb_fillrect *rect)
258{
259
260 u32 x2, y2, vxres, vyres, height, width, fg;
261 u32 cmd[7];
262
263 vxres = info->var.xres_virtual;
264 vyres = info->var.yres_virtual;
265
266 if (!rect->width || !rect->height || rect->dx > vxres
267 || rect->dy > vyres)
268 return;
269
270 /* We could use hardware clipping but on many cards you get around
271 * hardware clipping by writing to framebuffer directly. */
272 x2 = rect->dx + rect->width;
273 y2 = rect->dy + rect->height;
274 x2 = min(x2, vxres);
275 y2 = min(y2, vyres);
276 width = x2 - rect->dx;
277 height = y2 - rect->dy;
278 if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
279 info->fix.visual == FB_VISUAL_DIRECTCOLOR)
280 fg = ((u32 *) (info->pseudo_palette))[rect->color];
281 else
282 fg = rect->color;
283
284 switch (rect->rop) {
285
286 case ROP_XOR:
287 /* Set raster operation */
288 cmd[1] = (2 << 7) | (GDC_ROP_XOR << 9);
289 break;
290
291 case ROP_COPY:
292 /* Set raster operation */
293 cmd[1] = (2 << 7) | (GDC_ROP_COPY << 9);
294 break;
295
296 }
297
298 cmd[0] = (GDC_TYPE_SETREGISTER << 24) | (1 << 16) | GDC_REG_MODE_BITMAP;
299 /* cmd[1] set earlier */
300 cmd[2] =
301 (GDC_TYPE_SETCOLORREGISTER << 24) | (GDC_CMD_BODY_FORE_COLOR << 16);
302 cmd[3] = fg;
303 cmd[4] = (GDC_TYPE_DRAWRECTP << 24) | (GDC_CMD_BLT_FILL << 16);
304 cmd[5] = (rect->dy << 16) | (rect->dx);
305 cmd[6] = (height << 16) | width;
306
307 mb862xxfb_write_fifo(7, cmd, info);
308}
309
310void mb862xxfb_init_accel(struct fb_info *info, int xres)
311{
312 struct mb862xxfb_par *par = info->par;
313
314 if (info->var.bits_per_pixel == 32) {
315 info->fbops->fb_fillrect = cfb_fillrect;
316 info->fbops->fb_copyarea = cfb_copyarea;
317 info->fbops->fb_imageblit = cfb_imageblit;
318 } else {
319 outreg(disp, GC_L0EM, 3);
320 info->fbops->fb_fillrect = mb86290fb_fillrect;
321 info->fbops->fb_copyarea = mb86290fb_copyarea;
322 info->fbops->fb_imageblit = mb86290fb_imageblit;
323 }
324 outreg(draw, GDC_REG_DRAW_BASE, 0);
325 outreg(draw, GDC_REG_MODE_MISC, 0x8000);
326 outreg(draw, GDC_REG_X_RESOLUTION, xres);
327
328 info->flags |=
329 FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
330 FBINFO_HWACCEL_IMAGEBLIT;
331 info->fix.accel = 0xff; /*FIXME: add right define */
332}
333EXPORT_SYMBOL(mb862xxfb_init_accel);
334
335MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/mb862xx/mb862xxfb_accel.h b/drivers/video/mb862xx/mb862xxfb_accel.h
new file mode 100644
index 000000000000..96a2dfef0f60
--- /dev/null
+++ b/drivers/video/mb862xx/mb862xxfb_accel.h
@@ -0,0 +1,203 @@
1#ifndef __MB826XXFB_ACCEL_H__
2#define __MB826XXFB_ACCEL_H__
3
4/* registers */
5#define GDC_GEO_REG_INPUT_FIFO 0x00000400L
6
7/* Special Registers */
8#define GDC_REG_CTRL 0x00000400L
9#define GDC_REG_FIFO_STATUS 0x00000404L
10#define GDC_REG_FIFO_COUNT 0x00000408L
11#define GDC_REG_SETUP_STATUS 0x0000040CL
12#define GDC_REG_DDA_STATUS 0x00000410L
13#define GDC_REG_ENGINE_STATUS 0x00000414L
14#define GDC_REG_ERROR_STATUS 0x00000418L
15#define GDC_REG_MODE_MISC 0x00000420L /* MDR0 */
16#define GDC_REG_MODE_LINE 0x00000424L /* MDR1 */
17#define GDC_REG_MODE_POLYGON 0x00000428L /* MDR2 */
18#define GDC_REG_MODE_TEXTURE 0x0000042CL /* MDR3 */
19#define GDC_REG_MODE_BITMAP 0x00000430L /* MDR4 */
20#define GDC_REG_MODE_EXTENSION 0x0000043CL /* MDR7 */
21
22/* Configuration Registers */
23#define GDC_REG_DRAW_BASE 0x00000440L
24#define GDC_REG_X_RESOLUTION 0x00000444L
25#define GDC_REG_Z_BASE 0x00000448L
26#define GDC_REG_TEXTURE_BASE 0x0000044CL
27#define GDC_REG_POLYGON_FLAG_BASE 0x00000450L
28#define GDC_REG_CLIP_XMIN 0x00000454L
29#define GDC_REG_CLIP_XMAX 0x00000458L
30#define GDC_REG_CLIP_YMIN 0x0000045CL
31#define GDC_REG_CLIP_YMAX 0x00000460L
32#define GDC_REG_TEXURE_SIZE 0x00000464L
33#define GDC_REG_TILE_SIZE 0x00000468L
34#define GDC_REG_TEX_BUF_OFFSET 0x0000046CL
35
36/* for MB86293 or later */
37#define GDC_REG_ALPHA_MAP_BASE 0x00000474L /* ABR */
38
39/* Constant Registers */
40#define GDC_REG_FOREGROUND_COLOR 0x00000480L
41#define GDC_REG_BACKGROUND_COLOR 0x00000484L
42#define GDC_REG_ALPHA 0x00000488L
43#define GDC_REG_LINE_PATTERN 0x0000048CL
44#define GDC_REG_TEX_BORDER_COLOR 0x00000494L
45#define GDC_REG_LINE_PATTERN_OFFSET 0x000003E0L
46
47/* Coomand Code */
48#define GDC_CMD_PIXEL 0x00000000L
49#define GDC_CMD_PIXEL_Z 0x00000001L
50
51#define GDC_CMD_X_VECTOR 0x00000020L
52#define GDC_CMD_Y_VECTOR 0x00000021L
53#define GDC_CMD_X_VECTOR_NOEND 0x00000022L
54#define GDC_CMD_Y_VECTOR_NOEND 0x00000023L
55#define GDC_CMD_X_VECTOR_BLPO 0x00000024L
56#define GDC_CMD_Y_VECTOR_BLPO 0x00000025L
57#define GDC_CMD_X_VECTOR_NOEND_BLPO 0x00000026L
58#define GDC_CMD_Y_VECTOR_NOEND_BLPO 0x00000027L
59#define GDC_CMD_AA_X_VECTOR 0x00000028L
60#define GDC_CMD_AA_Y_VECTOR 0x00000029L
61#define GDC_CMD_AA_X_VECTOR_NOEND 0x0000002AL
62#define GDC_CMD_AA_Y_VECTOR_NOEND 0x0000002BL
63#define GDC_CMD_AA_X_VECTOR_BLPO 0x0000002CL
64#define GDC_CMD_AA_Y_VECTOR_BLPO 0x0000002DL
65#define GDC_CMD_AA_X_VECTOR_NOEND_BLPO 0x0000002EL
66#define GDC_CMD_AA_Y_VECTOR_NOEND_BLPO 0x0000002FL
67
68#define GDC_CMD_0_VECTOR 0x00000030L
69#define GDC_CMD_1_VECTOR 0x00000031L
70#define GDC_CMD_0_VECTOR_NOEND 0x00000032L
71#define GDC_CMD_1_VECTOR_NOEND 0x00000033L
72#define GDC_CMD_0_VECTOR_BLPO 0x00000034L
73#define GDC_CMD_1_VECTOR_BLPO 0x00000035L
74#define GDC_CMD_0_VECTOR_NOEND_BLPO 0x00000036L
75#define GDC_CMD_1_VECTOR_NOEND_BLPO 0x00000037L
76#define GDC_CMD_AA_0_VECTOR 0x00000038L
77#define GDC_CMD_AA_1_VECTOR 0x00000039L
78#define GDC_CMD_AA_0_VECTOR_NOEND 0x0000003AL
79#define GDC_CMD_AA_1_VECTOR_NOEND 0x0000003BL
80#define GDC_CMD_AA_0_VECTOR_BLPO 0x0000003CL
81#define GDC_CMD_AA_1_VECTOR_BLPO 0x0000003DL
82#define GDC_CMD_AA_0_VECTOR_NOEND_BLPO 0x0000003EL
83#define GDC_CMD_AA_1_VECTOR_NOEND_BLPO 0x0000003FL
84
85#define GDC_CMD_BLT_FILL 0x00000041L
86#define GDC_CMD_BLT_DRAW 0x00000042L
87#define GDC_CMD_BITMAP 0x00000043L
88#define GDC_CMD_BLTCOPY_TOP_LEFT 0x00000044L
89#define GDC_CMD_BLTCOPY_TOP_RIGHT 0x00000045L
90#define GDC_CMD_BLTCOPY_BOTTOM_LEFT 0x00000046L
91#define GDC_CMD_BLTCOPY_BOTTOM_RIGHT 0x00000047L
92#define GDC_CMD_LOAD_TEXTURE 0x00000048L
93#define GDC_CMD_LOAD_TILE 0x00000049L
94
95#define GDC_CMD_TRAP_RIGHT 0x00000060L
96#define GDC_CMD_TRAP_LEFT 0x00000061L
97#define GDC_CMD_TRIANGLE_FAN 0x00000062L
98#define GDC_CMD_FLAG_TRIANGLE_FAN 0x00000063L
99
100#define GDC_CMD_FLUSH_FB 0x000000C1L
101#define GDC_CMD_FLUSH_Z 0x000000C2L
102
103#define GDC_CMD_POLYGON_BEGIN 0x000000E0L
104#define GDC_CMD_POLYGON_END 0x000000E1L
105#define GDC_CMD_CLEAR_POLY_FLAG 0x000000E2L
106#define GDC_CMD_NORMAL 0x000000FFL
107
108#define GDC_CMD_VECTOR_BLPO_FLAG 0x00040000L
109#define GDC_CMD_FAST_VECTOR_BLPO_FLAG 0x00000004L
110
111/* for MB86293 or later */
112#define GDC_CMD_MDR1 0x00000000L
113#define GDC_CMD_MDR1S 0x00000002L
114#define GDC_CMD_MDR1B 0x00000004L
115#define GDC_CMD_MDR2 0x00000001L
116#define GDC_CMD_MDR2S 0x00000003L
117#define GDC_CMD_MDR2TL 0x00000007L
118#define GDC_CMD_GMDR1E 0x00000010L
119#define GDC_CMD_GMDR2E 0x00000020L
120#define GDC_CMD_OVERLAP_SHADOW_XY 0x00000000L
121#define GDC_CMD_OVERLAP_SHADOW_XY_COMPOSITION 0x00000001L
122#define GDC_CMD_OVERLAP_Z_PACKED_ONBS 0x00000007L
123#define GDC_CMD_OVERLAP_Z_ORIGIN 0x00000000L
124#define GDC_CMD_OVERLAP_Z_NON_TOPLEFT 0x00000001L
125#define GDC_CMD_OVERLAP_Z_BORDER 0x00000002L
126#define GDC_CMD_OVERLAP_Z_SHADOW 0x00000003L
127#define GDC_CMD_BLTCOPY_ALT_ALPHA 0x00000000L /* Reserverd */
128#define GDC_CMD_DC_LOGOUT 0x00000000L /* Reserverd */
129#define GDC_CMD_BODY_FORE_COLOR 0x00000000L
130#define GDC_CMD_BODY_BACK_COLOR 0x00000001L
131#define GDC_CMD_SHADOW_FORE_COLOR 0x00000002L
132#define GDC_CMD_SHADOW_BACK_COLOR 0x00000003L
133#define GDC_CMD_BORDER_FORE_COLOR 0x00000004L
134#define GDC_CMD_BORDER_BACK_COLOR 0x00000005L
135
136/* Type Code Table */
137#define GDC_TYPE_G_NOP 0x00000020L
138#define GDC_TYPE_G_BEGIN 0x00000021L
139#define GDC_TYPE_G_BEGINCONT 0x00000022L
140#define GDC_TYPE_G_END 0x00000023L
141#define GDC_TYPE_G_VERTEX 0x00000030L
142#define GDC_TYPE_G_VERTEXLOG 0x00000032L
143#define GDC_TYPE_G_VERTEXNOPLOG 0x00000033L
144#define GDC_TYPE_G_INIT 0x00000040L
145#define GDC_TYPE_G_VIEWPORT 0x00000041L
146#define GDC_TYPE_G_DEPTHRANGE 0x00000042L
147#define GDC_TYPE_G_LOADMATRIX 0x00000043L
148#define GDC_TYPE_G_VIEWVOLUMEXYCLIP 0x00000044L
149#define GDC_TYPE_G_VIEWVOLUMEZCLIP 0x00000045L
150#define GDC_TYPE_G_VIEWVOLUMEWCLIP 0x00000046L
151#define GDC_TYPE_SETLVERTEX2I 0x00000072L
152#define GDC_TYPE_SETLVERTEX2IP 0x00000073L
153#define GDC_TYPE_SETMODEREGISTER 0x000000C0L
154#define GDC_TYPE_SETGMODEREGISTER 0x000000C1L
155#define GDC_TYPE_OVERLAPXYOFFT 0x000000C8L
156#define GDC_TYPE_OVERLAPZOFFT 0x000000C9L
157#define GDC_TYPE_DC_LOGOUTADDR 0x000000CCL
158#define GDC_TYPE_SETCOLORREGISTER 0x000000CEL
159#define GDC_TYPE_G_BEGINE 0x000000E1L
160#define GDC_TYPE_G_BEGINCONTE 0x000000E2L
161#define GDC_TYPE_G_ENDE 0x000000E3L
162#define GDC_TYPE_DRAWPIXEL 0x00000000L
163#define GDC_TYPE_DRAWPIXELZ 0x00000001L
164#define GDC_TYPE_DRAWLINE 0x00000002L
165#define GDC_TYPE_DRAWLINE2I 0x00000003L
166#define GDC_TYPE_DRAWLINE2IP 0x00000004L
167#define GDC_TYPE_DRAWTRAP 0x00000005L
168#define GDC_TYPE_DRAWVERTEX2I 0x00000006L
169#define GDC_TYPE_DRAWVERTEX2IP 0x00000007L
170#define GDC_TYPE_DRAWRECTP 0x00000009L
171#define GDC_TYPE_DRAWBITMAPP 0x0000000BL
172#define GDC_TYPE_BLTCOPYP 0x0000000DL
173#define GDC_TYPE_BLTCOPYALTERNATEP 0x0000000FL
174#define GDC_TYPE_LOADTEXTUREP 0x00000011L
175#define GDC_TYPE_BLTTEXTUREP 0x00000013L
176#define GDC_TYPE_BLTCOPYALTALPHABLENDP 0x0000001FL
177#define GDC_TYPE_SETVERTEX2I 0x00000070L
178#define GDC_TYPE_SETVERTEX2IP 0x00000071L
179#define GDC_TYPE_DRAW 0x000000F0L
180#define GDC_TYPE_SETREGISTER 0x000000F1L
181#define GDC_TYPE_SYNC 0x000000FCL
182#define GDC_TYPE_INTERRUPT 0x000000FDL
183#define GDC_TYPE_NOP 0x0
184
185/* Raster operation */
186#define GDC_ROP_CLEAR 0x0000
187#define GDC_ROP_AND 0x0001
188#define GDC_ROP_AND_REVERSE 0x0002
189#define GDC_ROP_COPY 0x0003
190#define GDC_ROP_AND_INVERTED 0x0004
191#define GDC_ROP_NOP 0x0005
192#define GDC_ROP_XOR 0x0006
193#define GDC_ROP_OR 0x0007
194#define GDC_ROP_NOR 0x0008
195#define GDC_ROP_EQUIV 0x0009
196#define GDC_ROP_INVERT 0x000A
197#define GDC_ROP_OR_REVERSE 0x000B
198#define GDC_ROP_COPY_INVERTED 0x000C
199#define GDC_ROP_OR_INVERTED 0x000D
200#define GDC_ROP_NAND 0x000E
201#define GDC_ROP_SET 0x000F
202
203#endif
diff --git a/drivers/video/mbx/mbxdebugfs.c b/drivers/video/mbx/mbxdebugfs.c
index 15b8b3c4330e..ecad96524570 100644
--- a/drivers/video/mbx/mbxdebugfs.c
+++ b/drivers/video/mbx/mbxdebugfs.c
@@ -1,4 +1,5 @@
1#include <linux/debugfs.h> 1#include <linux/debugfs.h>
2#include <linux/slab.h>
2 3
3#define BIG_BUFFER_SIZE (1024) 4#define BIG_BUFFER_SIZE (1024)
4 5
diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c
index 01f77bcc68f9..afea9abbd678 100644
--- a/drivers/video/mbx/mbxfb.c
+++ b/drivers/video/mbx/mbxfb.c
@@ -693,7 +693,7 @@ static void __devinit setup_memc(struct fb_info *fbi)
693 unsigned long tmp; 693 unsigned long tmp;
694 int i; 694 int i;
695 695
696 /* FIXME: use platfrom specific parameters */ 696 /* FIXME: use platform specific parameters */
697 /* setup SDRAM controller */ 697 /* setup SDRAM controller */
698 write_reg_dly((LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS | 698 write_reg_dly((LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS |
699 LMCFG_LMA_TS), 699 LMCFG_LMA_TS),
diff --git a/drivers/video/metronomefb.c b/drivers/video/metronomefb.c
index df1f757a6161..9b3d6e4584cc 100644
--- a/drivers/video/metronomefb.c
+++ b/drivers/video/metronomefb.c
@@ -23,7 +23,6 @@
23#include <linux/errno.h> 23#include <linux/errno.h>
24#include <linux/string.h> 24#include <linux/string.h>
25#include <linux/mm.h> 25#include <linux/mm.h>
26#include <linux/slab.h>
27#include <linux/vmalloc.h> 26#include <linux/vmalloc.h>
28#include <linux/delay.h> 27#include <linux/delay.h>
29#include <linux/interrupt.h> 28#include <linux/interrupt.h>
@@ -700,7 +699,7 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
700 if (retval < 0) 699 if (retval < 0)
701 goto err_free_irq; 700 goto err_free_irq;
702 701
703 info->flags = FBINFO_FLAG_DEFAULT; 702 info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
704 703
705 info->fbdefio = &metronomefb_defio; 704 info->fbdefio = &metronomefb_defio;
706 fb_deferred_io_init(info); 705 fb_deferred_io_init(info);
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index 34e4e7995169..0a4dbdc1693a 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -12,7 +12,9 @@
12 */ 12 */
13 13
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/slab.h>
15#include <linux/fb.h> 16#include <linux/fb.h>
17#include <linux/kernel.h>
16 18
17#undef DEBUG 19#undef DEBUG
18 20
@@ -402,21 +404,6 @@ const struct fb_videomode vesa_modes[] = {
402EXPORT_SYMBOL(vesa_modes); 404EXPORT_SYMBOL(vesa_modes);
403#endif /* CONFIG_FB_MODE_HELPERS */ 405#endif /* CONFIG_FB_MODE_HELPERS */
404 406
405static int my_atoi(const char *name)
406{
407 int val = 0;
408
409 for (;; name++) {
410 switch (*name) {
411 case '0' ... '9':
412 val = 10*val+(*name-'0');
413 break;
414 default:
415 return val;
416 }
417 }
418}
419
420/** 407/**
421 * fb_try_mode - test a video mode 408 * fb_try_mode - test a video mode
422 * @var: frame buffer user defined part of display 409 * @var: frame buffer user defined part of display
@@ -539,7 +526,7 @@ int fb_find_mode(struct fb_var_screeninfo *var,
539 namelen = i; 526 namelen = i;
540 if (!refresh_specified && !bpp_specified && 527 if (!refresh_specified && !bpp_specified &&
541 !yres_specified) { 528 !yres_specified) {
542 refresh = my_atoi(&name[i+1]); 529 refresh = simple_strtol(&name[i+1], NULL, 10);
543 refresh_specified = 1; 530 refresh_specified = 1;
544 if (cvt || rb) 531 if (cvt || rb)
545 cvt = 0; 532 cvt = 0;
@@ -549,7 +536,7 @@ int fb_find_mode(struct fb_var_screeninfo *var,
549 case '-': 536 case '-':
550 namelen = i; 537 namelen = i;
551 if (!bpp_specified && !yres_specified) { 538 if (!bpp_specified && !yres_specified) {
552 bpp = my_atoi(&name[i+1]); 539 bpp = simple_strtol(&name[i+1], NULL, 10);
553 bpp_specified = 1; 540 bpp_specified = 1;
554 if (cvt || rb) 541 if (cvt || rb)
555 cvt = 0; 542 cvt = 0;
@@ -558,7 +545,7 @@ int fb_find_mode(struct fb_var_screeninfo *var,
558 break; 545 break;
559 case 'x': 546 case 'x':
560 if (!yres_specified) { 547 if (!yres_specified) {
561 yres = my_atoi(&name[i+1]); 548 yres = simple_strtol(&name[i+1], NULL, 10);
562 yres_specified = 1; 549 yres_specified = 1;
563 } else 550 } else
564 goto done; 551 goto done;
@@ -586,7 +573,7 @@ int fb_find_mode(struct fb_var_screeninfo *var,
586 } 573 }
587 } 574 }
588 if (i < 0 && yres_specified) { 575 if (i < 0 && yres_specified) {
589 xres = my_atoi(name); 576 xres = simple_strtol(name, NULL, 10);
590 res_specified = 1; 577 res_specified = 1;
591 } 578 }
592done: 579done:
@@ -907,7 +894,7 @@ const struct fb_videomode *fb_match_mode(const struct fb_var_screeninfo *var,
907} 894}
908 895
909/** 896/**
910 * fb_add_videomode: adds videomode entry to modelist 897 * fb_add_videomode - adds videomode entry to modelist
911 * @mode: videomode to add 898 * @mode: videomode to add
912 * @head: struct list_head of modelist 899 * @head: struct list_head of modelist
913 * 900 *
@@ -942,7 +929,7 @@ int fb_add_videomode(const struct fb_videomode *mode, struct list_head *head)
942} 929}
943 930
944/** 931/**
945 * fb_delete_videomode: removed videomode entry from modelist 932 * fb_delete_videomode - removed videomode entry from modelist
946 * @mode: videomode to remove 933 * @mode: videomode to remove
947 * @head: struct list_head of modelist 934 * @head: struct list_head of modelist
948 * 935 *
@@ -967,7 +954,7 @@ void fb_delete_videomode(const struct fb_videomode *mode,
967} 954}
968 955
969/** 956/**
970 * fb_destroy_modelist: destroy modelist 957 * fb_destroy_modelist - destroy modelist
971 * @head: struct list_head of modelist 958 * @head: struct list_head of modelist
972 */ 959 */
973void fb_destroy_modelist(struct list_head *head) 960void fb_destroy_modelist(struct list_head *head)
@@ -982,7 +969,7 @@ void fb_destroy_modelist(struct list_head *head)
982EXPORT_SYMBOL_GPL(fb_destroy_modelist); 969EXPORT_SYMBOL_GPL(fb_destroy_modelist);
983 970
984/** 971/**
985 * fb_videomode_to_modelist: convert mode array to mode list 972 * fb_videomode_to_modelist - convert mode array to mode list
986 * @modedb: array of struct fb_videomode 973 * @modedb: array of struct fb_videomode
987 * @num: number of entries in array 974 * @num: number of entries in array
988 * @head: struct list_head of modelist 975 * @head: struct list_head of modelist
diff --git a/drivers/video/msm/mddi.c b/drivers/video/msm/mddi.c
index 474421fe79a6..c1ff271017a9 100644
--- a/drivers/video/msm/mddi.c
+++ b/drivers/video/msm/mddi.c
@@ -21,6 +21,7 @@
21#include <linux/interrupt.h> 21#include <linux/interrupt.h>
22#include <linux/platform_device.h> 22#include <linux/platform_device.h>
23#include <linux/delay.h> 23#include <linux/delay.h>
24#include <linux/gfp.h>
24#include <linux/spinlock.h> 25#include <linux/spinlock.h>
25#include <linux/clk.h> 26#include <linux/clk.h>
26#include <linux/io.h> 27#include <linux/io.h>
diff --git a/drivers/video/msm/mddi_client_dummy.c b/drivers/video/msm/mddi_client_dummy.c
index ebbae87885b6..d2a091cebe2c 100644
--- a/drivers/video/msm/mddi_client_dummy.c
+++ b/drivers/video/msm/mddi_client_dummy.c
@@ -15,6 +15,7 @@
15 * GNU General Public License for more details. 15 * GNU General Public License for more details.
16 */ 16 */
17 17
18#include <linux/slab.h>
18#include <linux/module.h> 19#include <linux/module.h>
19#include <linux/kernel.h> 20#include <linux/kernel.h>
20#include <linux/platform_device.h> 21#include <linux/platform_device.h>
diff --git a/drivers/video/msm/mddi_client_nt35399.c b/drivers/video/msm/mddi_client_nt35399.c
index c9e9349451cb..f239f4a25e01 100644
--- a/drivers/video/msm/mddi_client_nt35399.c
+++ b/drivers/video/msm/mddi_client_nt35399.c
@@ -21,6 +21,7 @@
21#include <linux/interrupt.h> 21#include <linux/interrupt.h>
22#include <linux/sched.h> 22#include <linux/sched.h>
23#include <linux/gpio.h> 23#include <linux/gpio.h>
24#include <linux/slab.h>
24#include <mach/msm_fb.h> 25#include <mach/msm_fb.h>
25 26
26static DECLARE_WAIT_QUEUE_HEAD(nt35399_vsync_wait); 27static DECLARE_WAIT_QUEUE_HEAD(nt35399_vsync_wait);
diff --git a/drivers/video/msm/mddi_client_toshiba.c b/drivers/video/msm/mddi_client_toshiba.c
index 71048e78f7f0..f9bc932ac46b 100644
--- a/drivers/video/msm/mddi_client_toshiba.c
+++ b/drivers/video/msm/mddi_client_toshiba.c
@@ -21,6 +21,7 @@
21#include <linux/interrupt.h> 21#include <linux/interrupt.h>
22#include <linux/gpio.h> 22#include <linux/gpio.h>
23#include <linux/sched.h> 23#include <linux/sched.h>
24#include <linux/slab.h>
24#include <mach/msm_fb.h> 25#include <mach/msm_fb.h>
25 26
26 27
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 6c519e2fa2b7..19c01c6208e8 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -23,6 +23,7 @@
23#include <linux/clk.h> 23#include <linux/clk.h>
24#include <linux/file.h> 24#include <linux/file.h>
25#include <linux/major.h> 25#include <linux/major.h>
26#include <linux/slab.h>
26 27
27#include <mach/msm_iomap.h> 28#include <mach/msm_iomap.h>
28#include <mach/msm_fb.h> 29#include <mach/msm_fb.h>
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 49101dda45ee..debe5933fd2e 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -17,6 +17,7 @@
17#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/fb.h> 19#include <linux/fb.h>
20#include <linux/slab.h>
20#include <linux/delay.h> 21#include <linux/delay.h>
21 22
22#include <linux/freezer.h> 23#include <linux/freezer.h>
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c
index 054ef29be479..772ba3f45e6f 100644
--- a/drivers/video/mx3fb.c
+++ b/drivers/video/mx3fb.c
@@ -324,8 +324,11 @@ static void sdc_enable_channel(struct mx3fb_info *mx3_fbi)
324 unsigned long flags; 324 unsigned long flags;
325 dma_cookie_t cookie; 325 dma_cookie_t cookie;
326 326
327 dev_dbg(mx3fb->dev, "mx3fbi %p, desc %p, sg %p\n", mx3_fbi, 327 if (mx3_fbi->txd)
328 to_tx_desc(mx3_fbi->txd), to_tx_desc(mx3_fbi->txd)->sg); 328 dev_dbg(mx3fb->dev, "mx3fbi %p, desc %p, sg %p\n", mx3_fbi,
329 to_tx_desc(mx3_fbi->txd), to_tx_desc(mx3_fbi->txd)->sg);
330 else
331 dev_dbg(mx3fb->dev, "mx3fbi %p, txd = NULL\n", mx3_fbi);
329 332
330 /* This enables the channel */ 333 /* This enables the channel */
331 if (mx3_fbi->cookie < 0) { 334 if (mx3_fbi->cookie < 0) {
@@ -646,6 +649,7 @@ static int sdc_set_global_alpha(struct mx3fb_data *mx3fb, bool enable, uint8_t a
646 649
647static void sdc_set_brightness(struct mx3fb_data *mx3fb, uint8_t value) 650static void sdc_set_brightness(struct mx3fb_data *mx3fb, uint8_t value)
648{ 651{
652 dev_dbg(mx3fb->dev, "%s: value = %d\n", __func__, value);
649 /* This might be board-specific */ 653 /* This might be board-specific */
650 mx3fb_write_reg(mx3fb, 0x03000000UL | value << 16, SDC_PWM_CTRL); 654 mx3fb_write_reg(mx3fb, 0x03000000UL | value << 16, SDC_PWM_CTRL);
651 return; 655 return;
@@ -1486,12 +1490,12 @@ static int mx3fb_probe(struct platform_device *pdev)
1486 goto ersdc0; 1490 goto ersdc0;
1487 } 1491 }
1488 1492
1493 mx3fb->backlight_level = 255;
1494
1489 ret = init_fb_chan(mx3fb, to_idmac_chan(chan)); 1495 ret = init_fb_chan(mx3fb, to_idmac_chan(chan));
1490 if (ret < 0) 1496 if (ret < 0)
1491 goto eisdc0; 1497 goto eisdc0;
1492 1498
1493 mx3fb->backlight_level = 255;
1494
1495 return 0; 1499 return 0;
1496 1500
1497eisdc0: 1501eisdc0:
diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
new file mode 100644
index 000000000000..6bf0d460a738
--- /dev/null
+++ b/drivers/video/nuc900fb.c
@@ -0,0 +1,779 @@
1/*
2 *
3 * Copyright (c) 2009 Nuvoton technology corporation
4 * All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * Description:
12 * Nuvoton LCD Controller Driver
13 * Author:
14 * Wang Qiang (rurality.linux@gmail.com) 2009/12/11
15 */
16#include <linux/module.h>
17#include <linux/kernel.h>
18#include <linux/errno.h>
19#include <linux/string.h>
20#include <linux/mm.h>
21#include <linux/tty.h>
22#include <linux/slab.h>
23#include <linux/delay.h>
24#include <linux/fb.h>
25#include <linux/init.h>
26#include <linux/dma-mapping.h>
27#include <linux/interrupt.h>
28#include <linux/workqueue.h>
29#include <linux/wait.h>
30#include <linux/platform_device.h>
31#include <linux/clk.h>
32#include <linux/cpufreq.h>
33#include <linux/io.h>
34#include <linux/pm.h>
35#include <linux/device.h>
36
37#include <mach/map.h>
38#include <mach/regs-clock.h>
39#include <mach/regs-ldm.h>
40#include <mach/fb.h>
41#include <mach/clkdev.h>
42
43#include "nuc900fb.h"
44
45
46/*
47 * Initialize the nuc900 video (dual) buffer address
48 */
49static void nuc900fb_set_lcdaddr(struct fb_info *info)
50{
51 struct nuc900fb_info *fbi = info->par;
52 void __iomem *regs = fbi->io;
53 unsigned long vbaddr1, vbaddr2;
54
55 vbaddr1 = info->fix.smem_start;
56 vbaddr2 = info->fix.smem_start;
57 vbaddr2 += info->fix.line_length * info->var.yres;
58
59 /* set frambuffer start phy addr*/
60 writel(vbaddr1, regs + REG_LCM_VA_BADDR0);
61 writel(vbaddr2, regs + REG_LCM_VA_BADDR1);
62
63 writel(fbi->regs.lcd_va_fbctrl, regs + REG_LCM_VA_FBCTRL);
64 writel(fbi->regs.lcd_va_scale, regs + REG_LCM_VA_SCALE);
65}
66
67/*
68 * calculate divider for lcd div
69 */
70static unsigned int nuc900fb_calc_pixclk(struct nuc900fb_info *fbi,
71 unsigned long pixclk)
72{
73 unsigned long clk = fbi->clk_rate;
74 unsigned long long div;
75
76 /* pixclk is in picseconds. our clock is in Hz*/
77 /* div = (clk * pixclk)/10^12 */
78 div = (unsigned long long)clk * pixclk;
79 div >>= 12;
80 do_div(div, 625 * 625UL * 625);
81
82 dev_dbg(fbi->dev, "pixclk %ld, divisor is %lld\n", pixclk, div);
83
84 return div;
85}
86
87/*
88 * Check the video params of 'var'.
89 */
90static int nuc900fb_check_var(struct fb_var_screeninfo *var,
91 struct fb_info *info)
92{
93 struct nuc900fb_info *fbi = info->par;
94 struct nuc900fb_mach_info *mach_info = fbi->dev->platform_data;
95 struct nuc900fb_display *display = NULL;
96 struct nuc900fb_display *default_display = mach_info->displays +
97 mach_info->default_display;
98 int i;
99
100 dev_dbg(fbi->dev, "check_var(var=%p, info=%p)\n", var, info);
101
102 /* validate x/y resolution */
103 /* choose default mode if possible */
104 if (var->xres == default_display->xres &&
105 var->yres == default_display->yres &&
106 var->bits_per_pixel == default_display->bpp)
107 display = default_display;
108 else
109 for (i = 0; i < mach_info->num_displays; i++)
110 if (var->xres == mach_info->displays[i].xres &&
111 var->yres == mach_info->displays[i].yres &&
112 var->bits_per_pixel == mach_info->displays[i].bpp) {
113 display = mach_info->displays + i;
114 break;
115 }
116
117 if (display == NULL) {
118 printk(KERN_ERR "wrong resolution or depth %dx%d at %d bit per pixel\n",
119 var->xres, var->yres, var->bits_per_pixel);
120 return -EINVAL;
121 }
122
123 /* it should be the same size as the display */
124 var->xres_virtual = display->xres;
125 var->yres_virtual = display->yres;
126 var->height = display->height;
127 var->width = display->width;
128
129 /* copy lcd settings */
130 var->pixclock = display->pixclock;
131 var->left_margin = display->left_margin;
132 var->right_margin = display->right_margin;
133 var->upper_margin = display->upper_margin;
134 var->lower_margin = display->lower_margin;
135 var->vsync_len = display->vsync_len;
136 var->hsync_len = display->hsync_len;
137
138 var->transp.offset = 0;
139 var->transp.length = 0;
140
141 fbi->regs.lcd_dccs = display->dccs;
142 fbi->regs.lcd_device_ctrl = display->devctl;
143 fbi->regs.lcd_va_fbctrl = display->fbctrl;
144 fbi->regs.lcd_va_scale = display->scale;
145
146 /* set R/G/B possions */
147 switch (var->bits_per_pixel) {
148 case 1:
149 case 2:
150 case 4:
151 case 8:
152 default:
153 var->red.offset = 0;
154 var->red.length = var->bits_per_pixel;
155 var->green = var->red;
156 var->blue = var->red;
157 break;
158 case 12:
159 var->red.length = 4;
160 var->green.length = 4;
161 var->blue.length = 4;
162 var->red.offset = 8;
163 var->green.offset = 4;
164 var->blue.offset = 0;
165 break;
166 case 16:
167 var->red.length = 5;
168 var->green.length = 6;
169 var->blue.length = 5;
170 var->red.offset = 11;
171 var->green.offset = 5;
172 var->blue.offset = 0;
173 break;
174 case 18:
175 var->red.length = 6;
176 var->green.length = 6;
177 var->blue.length = 6;
178 var->red.offset = 12;
179 var->green.offset = 6;
180 var->blue.offset = 0;
181 break;
182 case 32:
183 var->red.length = 8;
184 var->green.length = 8;
185 var->blue.length = 8;
186 var->red.offset = 16;
187 var->green.offset = 8;
188 var->blue.offset = 0;
189 break;
190 }
191
192 return 0;
193}
194
195/*
196 * Calculate lcd register values from var setting & save into hw
197 */
198static void nuc900fb_calculate_lcd_regs(const struct fb_info *info,
199 struct nuc900fb_hw *regs)
200{
201 const struct fb_var_screeninfo *var = &info->var;
202 int vtt = var->height + var->upper_margin + var->lower_margin;
203 int htt = var->width + var->left_margin + var->right_margin;
204 int hsync = var->width + var->right_margin;
205 int vsync = var->height + var->lower_margin;
206
207 regs->lcd_crtc_size = LCM_CRTC_SIZE_VTTVAL(vtt) |
208 LCM_CRTC_SIZE_HTTVAL(htt);
209 regs->lcd_crtc_dend = LCM_CRTC_DEND_VDENDVAL(var->height) |
210 LCM_CRTC_DEND_HDENDVAL(var->width);
211 regs->lcd_crtc_hr = LCM_CRTC_HR_EVAL(var->width + 5) |
212 LCM_CRTC_HR_SVAL(var->width + 1);
213 regs->lcd_crtc_hsync = LCM_CRTC_HSYNC_EVAL(hsync + var->hsync_len) |
214 LCM_CRTC_HSYNC_SVAL(hsync);
215 regs->lcd_crtc_vr = LCM_CRTC_VR_EVAL(vsync + var->vsync_len) |
216 LCM_CRTC_VR_SVAL(vsync);
217
218}
219
220/*
221 * Activate (set) the controller from the given framebuffer
222 * information
223 */
224static void nuc900fb_activate_var(struct fb_info *info)
225{
226 struct nuc900fb_info *fbi = info->par;
227 void __iomem *regs = fbi->io;
228 struct fb_var_screeninfo *var = &info->var;
229 int clkdiv;
230
231 clkdiv = nuc900fb_calc_pixclk(fbi, var->pixclock) - 1;
232 if (clkdiv < 0)
233 clkdiv = 0;
234
235 nuc900fb_calculate_lcd_regs(info, &fbi->regs);
236
237 /* set the new lcd registers*/
238
239 dev_dbg(fbi->dev, "new lcd register set:\n");
240 dev_dbg(fbi->dev, "dccs = 0x%08x\n", fbi->regs.lcd_dccs);
241 dev_dbg(fbi->dev, "dev_ctl = 0x%08x\n", fbi->regs.lcd_device_ctrl);
242 dev_dbg(fbi->dev, "crtc_size = 0x%08x\n", fbi->regs.lcd_crtc_size);
243 dev_dbg(fbi->dev, "crtc_dend = 0x%08x\n", fbi->regs.lcd_crtc_dend);
244 dev_dbg(fbi->dev, "crtc_hr = 0x%08x\n", fbi->regs.lcd_crtc_hr);
245 dev_dbg(fbi->dev, "crtc_hsync = 0x%08x\n", fbi->regs.lcd_crtc_hsync);
246 dev_dbg(fbi->dev, "crtc_vr = 0x%08x\n", fbi->regs.lcd_crtc_vr);
247
248 writel(fbi->regs.lcd_device_ctrl, regs + REG_LCM_DEV_CTRL);
249 writel(fbi->regs.lcd_crtc_size, regs + REG_LCM_CRTC_SIZE);
250 writel(fbi->regs.lcd_crtc_dend, regs + REG_LCM_CRTC_DEND);
251 writel(fbi->regs.lcd_crtc_hr, regs + REG_LCM_CRTC_HR);
252 writel(fbi->regs.lcd_crtc_hsync, regs + REG_LCM_CRTC_HSYNC);
253 writel(fbi->regs.lcd_crtc_vr, regs + REG_LCM_CRTC_VR);
254
255 /* set lcd address pointers */
256 nuc900fb_set_lcdaddr(info);
257
258 writel(fbi->regs.lcd_dccs, regs + REG_LCM_DCCS);
259}
260
261/*
262 * Alters the hardware state.
263 *
264 */
265static int nuc900fb_set_par(struct fb_info *info)
266{
267 struct fb_var_screeninfo *var = &info->var;
268
269 switch (var->bits_per_pixel) {
270 case 32:
271 case 24:
272 case 18:
273 case 16:
274 case 12:
275 info->fix.visual = FB_VISUAL_TRUECOLOR;
276 break;
277 case 1:
278 info->fix.visual = FB_VISUAL_MONO01;
279 break;
280 default:
281 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
282 break;
283 }
284
285 info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8;
286
287 /* activate this new configuration */
288 nuc900fb_activate_var(info);
289 return 0;
290}
291
292static inline unsigned int chan_to_field(unsigned int chan,
293 struct fb_bitfield *bf)
294{
295 chan &= 0xffff;
296 chan >>= 16 - bf->length;
297 return chan << bf->offset;
298}
299
300static int nuc900fb_setcolreg(unsigned regno,
301 unsigned red, unsigned green, unsigned blue,
302 unsigned transp, struct fb_info *info)
303{
304 unsigned int val;
305
306 switch (info->fix.visual) {
307 case FB_VISUAL_TRUECOLOR:
308 /* true-colour, use pseuo-palette */
309 if (regno < 16) {
310 u32 *pal = info->pseudo_palette;
311
312 val = chan_to_field(red, &info->var.red);
313 val |= chan_to_field(green, &info->var.green);
314 val |= chan_to_field(blue, &info->var.blue);
315 pal[regno] = val;
316 }
317 break;
318
319 default:
320 return 1; /* unknown type */
321 }
322 return 0;
323}
324
325/**
326 * nuc900fb_blank
327 *
328 */
329static int nuc900fb_blank(int blank_mode, struct fb_info *info)
330{
331
332 return 0;
333}
334
335static struct fb_ops nuc900fb_ops = {
336 .owner = THIS_MODULE,
337 .fb_check_var = nuc900fb_check_var,
338 .fb_set_par = nuc900fb_set_par,
339 .fb_blank = nuc900fb_blank,
340 .fb_setcolreg = nuc900fb_setcolreg,
341 .fb_fillrect = cfb_fillrect,
342 .fb_copyarea = cfb_copyarea,
343 .fb_imageblit = cfb_imageblit,
344};
345
346
347static inline void modify_gpio(void __iomem *reg,
348 unsigned long set, unsigned long mask)
349{
350 unsigned long tmp;
351 tmp = readl(reg) & ~mask;
352 writel(tmp | set, reg);
353}
354
355/*
356 * Initialise LCD-related registers
357 */
358static int nuc900fb_init_registers(struct fb_info *info)
359{
360 struct nuc900fb_info *fbi = info->par;
361 struct nuc900fb_mach_info *mach_info = fbi->dev->platform_data;
362 void __iomem *regs = fbi->io;
363
364 /*reset the display engine*/
365 writel(0, regs + REG_LCM_DCCS);
366 writel(readl(regs + REG_LCM_DCCS) | LCM_DCCS_ENG_RST,
367 regs + REG_LCM_DCCS);
368 ndelay(100);
369 writel(readl(regs + REG_LCM_DCCS) & (~LCM_DCCS_ENG_RST),
370 regs + REG_LCM_DCCS);
371 ndelay(100);
372
373 writel(0, regs + REG_LCM_DEV_CTRL);
374
375 /* config gpio output */
376 modify_gpio(W90X900_VA_GPIO + 0x54, mach_info->gpio_dir,
377 mach_info->gpio_dir_mask);
378 modify_gpio(W90X900_VA_GPIO + 0x58, mach_info->gpio_data,
379 mach_info->gpio_data_mask);
380
381 return 0;
382}
383
384
385/*
386 * Alloc the SDRAM region of NUC900 for the frame buffer.
387 * The buffer should be a non-cached, non-buffered, memory region
388 * to allow palette and pixel writes without flushing the cache.
389 */
390static int __init nuc900fb_map_video_memory(struct fb_info *info)
391{
392 struct nuc900fb_info *fbi = info->par;
393 dma_addr_t map_dma;
394 unsigned long map_size = PAGE_ALIGN(info->fix.smem_len);
395
396 dev_dbg(fbi->dev, "nuc900fb_map_video_memory(fbi=%p) map_size %lu\n",
397 fbi, map_size);
398
399 info->screen_base = dma_alloc_writecombine(fbi->dev, map_size,
400 &map_dma, GFP_KERNEL);
401
402 if (!info->screen_base)
403 return -ENOMEM;
404
405 memset(info->screen_base, 0x00, map_size);
406 info->fix.smem_start = map_dma;
407
408 return 0;
409}
410
411static inline void nuc900fb_unmap_video_memory(struct fb_info *info)
412{
413 struct nuc900fb_info *fbi = info->par;
414 dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
415 info->screen_base, info->fix.smem_start);
416}
417
418static irqreturn_t nuc900fb_irqhandler(int irq, void *dev_id)
419{
420 struct nuc900fb_info *fbi = dev_id;
421 void __iomem *regs = fbi->io;
422 void __iomem *irq_base = fbi->irq_base;
423 unsigned long lcdirq = readl(regs + REG_LCM_INT_CS);
424
425 if (lcdirq & LCM_INT_CS_DISP_F_STATUS) {
426 writel(readl(irq_base) | 1<<30, irq_base);
427
428 /* wait VA_EN low */
429 if ((readl(regs + REG_LCM_DCCS) &
430 LCM_DCCS_SINGLE) == LCM_DCCS_SINGLE)
431 while ((readl(regs + REG_LCM_DCCS) &
432 LCM_DCCS_VA_EN) == LCM_DCCS_VA_EN)
433 ;
434 /* display_out-enable */
435 writel(readl(regs + REG_LCM_DCCS) | LCM_DCCS_DISP_OUT_EN,
436 regs + REG_LCM_DCCS);
437 /* va-enable*/
438 writel(readl(regs + REG_LCM_DCCS) | LCM_DCCS_VA_EN,
439 regs + REG_LCM_DCCS);
440 } else if (lcdirq & LCM_INT_CS_UNDERRUN_INT) {
441 writel(readl(irq_base) | LCM_INT_CS_UNDERRUN_INT, irq_base);
442 } else if (lcdirq & LCM_INT_CS_BUS_ERROR_INT) {
443 writel(readl(irq_base) | LCM_INT_CS_BUS_ERROR_INT, irq_base);
444 }
445
446 return IRQ_HANDLED;
447}
448
449#ifdef CONFIG_CPU_FREQ
450
451static int nuc900fb_cpufreq_transition(struct notifier_block *nb,
452 unsigned long val, void *data)
453{
454 struct nuc900fb_info *info;
455 struct fb_info *fbinfo;
456 long delta_f;
457 info = container_of(nb, struct nuc900fb_info, freq_transition);
458 fbinfo = platform_get_drvdata(to_platform_device(info->dev));
459
460 delta_f = info->clk_rate - clk_get_rate(info->clk);
461
462 if ((val == CPUFREQ_POSTCHANGE && delta_f > 0) ||
463 (val == CPUFREQ_PRECHANGE && delta_f < 0)) {
464 info->clk_rate = clk_get_rate(info->clk);
465 nuc900fb_activate_var(fbinfo);
466 }
467
468 return 0;
469}
470
471static inline int nuc900fb_cpufreq_register(struct nuc900fb_info *fbi)
472{
473 fbi->freq_transition.notifier_call = nuc900fb_cpufreq_transition;
474 return cpufreq_register_notifier(&fbi->freq_transition,
475 CPUFREQ_TRANSITION_NOTIFIER);
476}
477
478static inline void nuc900fb_cpufreq_deregister(struct nuc900fb_info *fbi)
479{
480 cpufreq_unregister_notifier(&fbi->freq_transition,
481 CPUFREQ_TRANSITION_NOTIFIER);
482}
483#else
484static inline int nuc900fb_cpufreq_transition(struct notifier_block *nb,
485 unsigned long val, void *data)
486{
487 return 0;
488}
489
490static inline int nuc900fb_cpufreq_register(struct nuc900fb_info *fbi)
491{
492 return 0;
493}
494
495static inline void nuc900fb_cpufreq_deregister(struct nuc900fb_info *info)
496{
497}
498#endif
499
500static char driver_name[] = "nuc900fb";
501
502static int __devinit nuc900fb_probe(struct platform_device *pdev)
503{
504 struct nuc900fb_info *fbi;
505 struct nuc900fb_display *display;
506 struct fb_info *fbinfo;
507 struct nuc900fb_mach_info *mach_info;
508 struct resource *res;
509 int ret;
510 int irq;
511 int i;
512 int size;
513
514 dev_dbg(&pdev->dev, "devinit\n");
515 mach_info = pdev->dev.platform_data;
516 if (mach_info == NULL) {
517 dev_err(&pdev->dev,
518 "no platform data for lcd, cannot attach\n");
519 return -EINVAL;
520 }
521
522 if (mach_info->default_display > mach_info->num_displays) {
523 dev_err(&pdev->dev,
524 "default display No. is %d but only %d displays \n",
525 mach_info->default_display, mach_info->num_displays);
526 return -EINVAL;
527 }
528
529
530 display = mach_info->displays + mach_info->default_display;
531
532 irq = platform_get_irq(pdev, 0);
533 if (irq < 0) {
534 dev_err(&pdev->dev, "no irq for device\n");
535 return -ENOENT;
536 }
537
538 fbinfo = framebuffer_alloc(sizeof(struct nuc900fb_info), &pdev->dev);
539 if (!fbinfo)
540 return -ENOMEM;
541
542 platform_set_drvdata(pdev, fbinfo);
543
544 fbi = fbinfo->par;
545 fbi->dev = &pdev->dev;
546
547#ifdef CONFIG_CPU_NUC950
548 fbi->drv_type = LCDDRV_NUC950;
549#endif
550
551 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
552
553 size = (res->end - res->start) + 1;
554 fbi->mem = request_mem_region(res->start, size, pdev->name);
555 if (fbi->mem == NULL) {
556 dev_err(&pdev->dev, "failed to alloc memory region\n");
557 ret = -ENOENT;
558 goto free_fb;
559 }
560
561 fbi->io = ioremap(res->start, size);
562 if (fbi->io == NULL) {
563 dev_err(&pdev->dev, "ioremap() of lcd registers failed\n");
564 ret = -ENXIO;
565 goto release_mem_region;
566 }
567
568 fbi->irq_base = fbi->io + REG_LCM_INT_CS;
569
570
571 /* Stop the LCD */
572 writel(0, fbi->io + REG_LCM_DCCS);
573
574 /* fill the fbinfo*/
575 strcpy(fbinfo->fix.id, driver_name);
576 fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
577 fbinfo->fix.type_aux = 0;
578 fbinfo->fix.xpanstep = 0;
579 fbinfo->fix.ypanstep = 0;
580 fbinfo->fix.ywrapstep = 0;
581 fbinfo->fix.accel = FB_ACCEL_NONE;
582 fbinfo->var.nonstd = 0;
583 fbinfo->var.activate = FB_ACTIVATE_NOW;
584 fbinfo->var.accel_flags = 0;
585 fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
586 fbinfo->fbops = &nuc900fb_ops;
587 fbinfo->flags = FBINFO_FLAG_DEFAULT;
588 fbinfo->pseudo_palette = &fbi->pseudo_pal;
589
590 ret = request_irq(irq, nuc900fb_irqhandler, IRQF_DISABLED,
591 pdev->name, fbinfo);
592 if (ret) {
593 dev_err(&pdev->dev, "cannot register irq handler %d -err %d\n",
594 irq, ret);
595 ret = -EBUSY;
596 goto release_regs;
597 }
598
599 nuc900_driver_clksrc_div(&pdev->dev, "ext", 0x2);
600
601 fbi->clk = clk_get(&pdev->dev, NULL);
602 if (!fbi->clk || IS_ERR(fbi->clk)) {
603 printk(KERN_ERR "nuc900-lcd:failed to get lcd clock source\n");
604 ret = -ENOENT;
605 goto release_irq;
606 }
607
608 clk_enable(fbi->clk);
609 dev_dbg(&pdev->dev, "got and enabled clock\n");
610
611 fbi->clk_rate = clk_get_rate(fbi->clk);
612
613 /* calutate the video buffer size */
614 for (i = 0; i < mach_info->num_displays; i++) {
615 unsigned long smem_len = mach_info->displays[i].xres;
616 smem_len *= mach_info->displays[i].yres;
617 smem_len *= mach_info->displays[i].bpp;
618 smem_len >>= 3;
619 if (fbinfo->fix.smem_len < smem_len)
620 fbinfo->fix.smem_len = smem_len;
621 }
622
623 /* Initialize Video Memory */
624 ret = nuc900fb_map_video_memory(fbinfo);
625 if (ret) {
626 printk(KERN_ERR "Failed to allocate video RAM: %x\n", ret);
627 goto release_clock;
628 }
629
630 dev_dbg(&pdev->dev, "got video memory\n");
631
632 fbinfo->var.xres = display->xres;
633 fbinfo->var.yres = display->yres;
634 fbinfo->var.bits_per_pixel = display->bpp;
635
636 nuc900fb_init_registers(fbinfo);
637
638 nuc900fb_check_var(&fbinfo->var, fbinfo);
639
640 ret = nuc900fb_cpufreq_register(fbi);
641 if (ret < 0) {
642 dev_err(&pdev->dev, "Failed to register cpufreq\n");
643 goto free_video_memory;
644 }
645
646 ret = register_framebuffer(fbinfo);
647 if (ret) {
648 printk(KERN_ERR "failed to register framebuffer device: %d\n",
649 ret);
650 goto free_cpufreq;
651 }
652
653 printk(KERN_INFO "fb%d: %s frame buffer device\n",
654 fbinfo->node, fbinfo->fix.id);
655
656 return 0;
657
658free_cpufreq:
659 nuc900fb_cpufreq_deregister(fbi);
660free_video_memory:
661 nuc900fb_unmap_video_memory(fbinfo);
662release_clock:
663 clk_disable(fbi->clk);
664 clk_put(fbi->clk);
665release_irq:
666 free_irq(irq, fbi);
667release_regs:
668 iounmap(fbi->io);
669release_mem_region:
670 release_mem_region((unsigned long)fbi->mem, size);
671free_fb:
672 framebuffer_release(fbinfo);
673 return ret;
674}
675
676/*
677 * shutdown the lcd controller
678 */
679static void nuc900fb_stop_lcd(struct fb_info *info)
680{
681 struct nuc900fb_info *fbi = info->par;
682 void __iomem *regs = fbi->io;
683
684 writel((~LCM_DCCS_DISP_INT_EN) | (~LCM_DCCS_VA_EN) | (~LCM_DCCS_OSD_EN),
685 regs + REG_LCM_DCCS);
686}
687
688/*
689 * Cleanup
690 */
691static int nuc900fb_remove(struct platform_device *pdev)
692{
693 struct fb_info *fbinfo = platform_get_drvdata(pdev);
694 struct nuc900fb_info *fbi = fbinfo->par;
695 int irq;
696
697 nuc900fb_stop_lcd(fbinfo);
698 msleep(1);
699
700 nuc900fb_unmap_video_memory(fbinfo);
701
702 iounmap(fbi->io);
703
704 irq = platform_get_irq(pdev, 0);
705 free_irq(irq, fbi);
706
707 release_resource(fbi->mem);
708 kfree(fbi->mem);
709
710 platform_set_drvdata(pdev, NULL);
711 framebuffer_release(fbinfo);
712
713 return 0;
714}
715
716#ifdef CONFIG_PM
717
718/*
719 * suspend and resume support for the lcd controller
720 */
721
722static int nuc900fb_suspend(struct platform_device *dev, pm_message_t state)
723{
724 struct fb_info *fbinfo = platform_get_drvdata(dev);
725 struct nuc900fb_info *info = fbinfo->par;
726
727 nuc900fb_stop_lcd();
728 msleep(1);
729 clk_disable(info->clk);
730 return 0;
731}
732
733static int nuc900fb_resume(struct platform_device *dev)
734{
735 struct fb_info *fbinfo = platform_get_drvdata(dev);
736 struct nuc900fb_info *fbi = fbinfo->par;
737
738 printk(KERN_INFO "nuc900fb resume\n");
739
740 clk_enable(fbi->clk);
741 msleep(1);
742
743 nuc900fb_init_registers(fbinfo);
744 nuc900fb_activate_var(bfinfo);
745
746 return 0;
747}
748
749#else
750#define nuc900fb_suspend NULL
751#define nuc900fb_resume NULL
752#endif
753
754static struct platform_driver nuc900fb_driver = {
755 .probe = nuc900fb_probe,
756 .remove = nuc900fb_remove,
757 .suspend = nuc900fb_suspend,
758 .resume = nuc900fb_resume,
759 .driver = {
760 .name = "nuc900-lcd",
761 .owner = THIS_MODULE,
762 },
763};
764
765int __devinit nuc900fb_init(void)
766{
767 return platform_driver_register(&nuc900fb_driver);
768}
769
770static void __exit nuc900fb_cleanup(void)
771{
772 platform_driver_unregister(&nuc900fb_driver);
773}
774
775module_init(nuc900fb_init);
776module_exit(nuc900fb_cleanup);
777
778MODULE_DESCRIPTION("Framebuffer driver for the NUC900");
779MODULE_LICENSE("GPL");
diff --git a/drivers/video/nuc900fb.h b/drivers/video/nuc900fb.h
new file mode 100644
index 000000000000..6c23aa3d3b89
--- /dev/null
+++ b/drivers/video/nuc900fb.h
@@ -0,0 +1,55 @@
1/*
2 *
3 * Copyright (c) 2009 Nuvoton technology corporation
4 * All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * Auther:
12 * Wang Qiang(rurality.linux@gmail.com) 2009/12/16
13 */
14
15#ifndef __NUC900FB_H
16#define __NUC900FB_H
17
18#include <mach/map.h>
19#include <mach/fb.h>
20
21enum nuc900_lcddrv_type {
22 LCDDRV_NUC910,
23 LCDDRV_NUC930,
24 LCDDRV_NUC932,
25 LCDDRV_NUC950,
26 LCDDRV_NUC960,
27};
28
29
30#define PALETTE_BUFFER_SIZE 256
31#define PALETTE_BUFF_CLEAR (0x80000000) /* entry is clear/invalid */
32
33struct nuc900fb_info {
34 struct device *dev;
35 struct clk *clk;
36
37 struct resource *mem;
38 void __iomem *io;
39 void __iomem *irq_base;
40 int drv_type;
41 struct nuc900fb_hw regs;
42 unsigned long clk_rate;
43
44#ifdef CONFIG_CPU_FREQ
45 struct notifier_block freq_transition;
46#endif
47
48 /* keep these registers in case we need to re-write palette */
49 u32 palette_buffer[PALETTE_BUFFER_SIZE];
50 u32 pseudo_pal[16];
51};
52
53int nuc900fb_init(void);
54
55#endif /* __NUC900FB_H */
diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/nvidia/nv_backlight.c
index 443e3c85a9a0..2fb552a6f32c 100644
--- a/drivers/video/nvidia/nv_backlight.c
+++ b/drivers/video/nvidia/nv_backlight.c
@@ -94,6 +94,7 @@ static struct backlight_ops nvidia_bl_ops = {
94 94
95void nvidia_bl_init(struct nvidia_par *par) 95void nvidia_bl_init(struct nvidia_par *par)
96{ 96{
97 struct backlight_properties props;
97 struct fb_info *info = pci_get_drvdata(par->pci_dev); 98 struct fb_info *info = pci_get_drvdata(par->pci_dev);
98 struct backlight_device *bd; 99 struct backlight_device *bd;
99 char name[12]; 100 char name[12];
@@ -109,7 +110,10 @@ void nvidia_bl_init(struct nvidia_par *par)
109 110
110 snprintf(name, sizeof(name), "nvidiabl%d", info->node); 111 snprintf(name, sizeof(name), "nvidiabl%d", info->node);
111 112
112 bd = backlight_device_register(name, info->dev, par, &nvidia_bl_ops); 113 memset(&props, 0, sizeof(struct backlight_properties));
114 props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
115 bd = backlight_device_register(name, info->dev, par, &nvidia_bl_ops,
116 &props);
113 if (IS_ERR(bd)) { 117 if (IS_ERR(bd)) {
114 info->bl_dev = NULL; 118 info->bl_dev = NULL;
115 printk(KERN_WARNING "nvidia: Backlight registration failed\n"); 119 printk(KERN_WARNING "nvidia: Backlight registration failed\n");
@@ -121,7 +125,6 @@ void nvidia_bl_init(struct nvidia_par *par)
121 0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL, 125 0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL,
122 0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL); 126 0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL);
123 127
124 bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
125 bd->props.brightness = bd->props.max_brightness; 128 bd->props.brightness = bd->props.max_brightness;
126 bd->props.power = FB_BLANK_UNBLANK; 129 bd->props.power = FB_BLANK_UNBLANK;
127 backlight_update_status(bd); 130 backlight_update_status(bd);
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c
index 6aaddb4f6788..d7994a173245 100644
--- a/drivers/video/nvidia/nv_i2c.c
+++ b/drivers/video/nvidia/nv_i2c.c
@@ -13,6 +13,7 @@
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/delay.h> 15#include <linux/delay.h>
16#include <linux/gfp.h>
16#include <linux/pci.h> 17#include <linux/pci.h>
17#include <linux/fb.h> 18#include <linux/fb.h>
18 19
diff --git a/drivers/video/nvidia/nv_of.c b/drivers/video/nvidia/nv_of.c
index 73afd7eb9977..3bc13df4b120 100644
--- a/drivers/video/nvidia/nv_of.c
+++ b/drivers/video/nvidia/nv_of.c
@@ -13,6 +13,7 @@
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/delay.h> 15#include <linux/delay.h>
16#include <linux/gfp.h>
16#include <linux/pci.h> 17#include <linux/pci.h>
17#include <linux/fb.h> 18#include <linux/fb.h>
18 19
diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c
index eef2bb298d9f..2f2e162134fa 100644
--- a/drivers/video/nvidia/nv_setup.c
+++ b/drivers/video/nvidia/nv_setup.c
@@ -50,6 +50,7 @@
50#include <video/vga.h> 50#include <video/vga.h>
51#include <linux/delay.h> 51#include <linux/delay.h>
52#include <linux/pci.h> 52#include <linux/pci.h>
53#include <linux/slab.h>
53#include "nv_type.h" 54#include "nv_type.h"
54#include "nv_local.h" 55#include "nv_local.h"
55#include "nv_proto.h" 56#include "nv_proto.h"
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index 4d8c54c23dd7..61f8b8f919b0 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -17,7 +17,6 @@
17#include <linux/errno.h> 17#include <linux/errno.h>
18#include <linux/string.h> 18#include <linux/string.h>
19#include <linux/mm.h> 19#include <linux/mm.h>
20#include <linux/slab.h>
21#include <linux/vmalloc.h> 20#include <linux/vmalloc.h>
22#include <linux/delay.h> 21#include <linux/delay.h>
23#include <linux/interrupt.h> 22#include <linux/interrupt.h>
@@ -282,8 +281,17 @@ static int offb_set_par(struct fb_info *info)
282 return 0; 281 return 0;
283} 282}
284 283
284static void offb_destroy(struct fb_info *info)
285{
286 if (info->screen_base)
287 iounmap(info->screen_base);
288 release_mem_region(info->aperture_base, info->aperture_size);
289 framebuffer_release(info);
290}
291
285static struct fb_ops offb_ops = { 292static struct fb_ops offb_ops = {
286 .owner = THIS_MODULE, 293 .owner = THIS_MODULE,
294 .fb_destroy = offb_destroy,
287 .fb_setcolreg = offb_setcolreg, 295 .fb_setcolreg = offb_setcolreg,
288 .fb_set_par = offb_set_par, 296 .fb_set_par = offb_set_par,
289 .fb_blank = offb_blank, 297 .fb_blank = offb_blank,
@@ -482,10 +490,14 @@ static void __init offb_init_fb(const char *name, const char *full_name,
482 var->sync = 0; 490 var->sync = 0;
483 var->vmode = FB_VMODE_NONINTERLACED; 491 var->vmode = FB_VMODE_NONINTERLACED;
484 492
493 /* set offb aperture size for generic probing */
494 info->aperture_base = address;
495 info->aperture_size = fix->smem_len;
496
485 info->fbops = &offb_ops; 497 info->fbops = &offb_ops;
486 info->screen_base = ioremap(address, fix->smem_len); 498 info->screen_base = ioremap(address, fix->smem_len);
487 info->pseudo_palette = (void *) (info + 1); 499 info->pseudo_palette = (void *) (info + 1);
488 info->flags = FBINFO_DEFAULT | foreign_endian; 500 info->flags = FBINFO_DEFAULT | FBINFO_MISC_FIRMWARE | foreign_endian;
489 501
490 fb_alloc_cmap(&info->cmap, 256, 0); 502 fb_alloc_cmap(&info->cmap, 256, 0);
491 503
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig
index 551e3e9c4cbe..455c6055325d 100644
--- a/drivers/video/omap/Kconfig
+++ b/drivers/video/omap/Kconfig
@@ -1,6 +1,7 @@
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 3 depends on FB && ARCH_OMAP && (OMAP2_DSS = "n")
4
4 select FB_CFB_FILLRECT 5 select FB_CFB_FILLRECT
5 select FB_CFB_COPYAREA 6 select FB_CFB_COPYAREA
6 select FB_CFB_IMAGEBLIT 7 select FB_CFB_IMAGEBLIT
@@ -72,7 +73,7 @@ config FB_OMAP_LCD_MIPID
72 73
73config FB_OMAP_BOOTLOADER_INIT 74config FB_OMAP_BOOTLOADER_INIT
74 bool "Check bootloader initialization" 75 bool "Check bootloader initialization"
75 depends on FB_OMAP 76 depends on FB_OMAP || FB_OMAP2
76 help 77 help
77 Say Y here if you want to enable checking if the bootloader has 78 Say Y here if you want to enable checking if the bootloader has
78 already initialized the display controller. In this case the 79 already initialized the display controller. In this case the
diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile
index b63b198d1f03..49226a1b909e 100644
--- a/drivers/video/omap/Makefile
+++ b/drivers/video/omap/Makefile
@@ -35,6 +35,7 @@ objs-y$(CONFIG_MACH_OMAP3EVM) += lcd_omap3evm.o
35objs-y$(CONFIG_MACH_OMAP3_BEAGLE) += lcd_omap3beagle.o 35objs-y$(CONFIG_MACH_OMAP3_BEAGLE) += lcd_omap3beagle.o
36objs-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o 36objs-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o
37objs-y$(CONFIG_MACH_OVERO) += lcd_overo.o 37objs-y$(CONFIG_MACH_OVERO) += lcd_overo.o
38objs-y$(CONFIG_MACH_HERALD) += lcd_htcherald.o
38 39
39omapfb-objs := $(objs-yy) 40omapfb-objs := $(objs-yy)
40 41
diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c
index 70dadf9d2334..2ffb34af4c59 100644
--- a/drivers/video/omap/blizzard.c
+++ b/drivers/video/omap/blizzard.c
@@ -26,10 +26,10 @@
26#include <linux/delay.h> 26#include <linux/delay.h>
27#include <linux/clk.h> 27#include <linux/clk.h>
28 28
29#include <mach/dma.h> 29#include <plat/dma.h>
30#include <mach/omapfb.h> 30#include <plat/blizzard.h>
31#include <mach/blizzard.h>
32 31
32#include "omapfb.h"
33#include "dispc.h" 33#include "dispc.h"
34 34
35#define MODULE_NAME "blizzard" 35#define MODULE_NAME "blizzard"
diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c
index f16e42154229..529483467abf 100644
--- a/drivers/video/omap/dispc.c
+++ b/drivers/video/omap/dispc.c
@@ -24,11 +24,13 @@
24#include <linux/vmalloc.h> 24#include <linux/vmalloc.h>
25#include <linux/clk.h> 25#include <linux/clk.h>
26#include <linux/io.h> 26#include <linux/io.h>
27#include <linux/platform_device.h>
28#include <linux/slab.h>
27 29
28#include <mach/sram.h> 30#include <plat/sram.h>
29#include <mach/omapfb.h> 31#include <plat/board.h>
30#include <mach/board.h>
31 32
33#include "omapfb.h"
32#include "dispc.h" 34#include "dispc.h"
33 35
34#define MODULE_NAME "dispc" 36#define MODULE_NAME "dispc"
@@ -204,6 +206,7 @@ static u32 inline dispc_read_reg(int idx)
204/* Select RFBI or bypass mode */ 206/* Select RFBI or bypass mode */
205static void enable_rfbi_mode(int enable) 207static void enable_rfbi_mode(int enable)
206{ 208{
209 void __iomem *rfbi_control;
207 u32 l; 210 u32 l;
208 211
209 l = dispc_read_reg(DISPC_CONTROL); 212 l = dispc_read_reg(DISPC_CONTROL);
@@ -216,9 +219,15 @@ static void enable_rfbi_mode(int enable)
216 dispc_write_reg(DISPC_CONTROL, l); 219 dispc_write_reg(DISPC_CONTROL, l);
217 220
218 /* Set bypass mode in RFBI module */ 221 /* Set bypass mode in RFBI module */
219 l = __raw_readl(OMAP2_IO_ADDRESS(RFBI_CONTROL)); 222 rfbi_control = ioremap(RFBI_CONTROL, SZ_1K);
223 if (!rfbi_control) {
224 pr_err("Unable to ioremap rfbi_control\n");
225 return;
226 }
227 l = __raw_readl(rfbi_control);
220 l |= enable ? 0 : (1 << 1); 228 l |= enable ? 0 : (1 << 1);
221 __raw_writel(l, OMAP2_IO_ADDRESS(RFBI_CONTROL)); 229 __raw_writel(l, rfbi_control);
230 iounmap(rfbi_control);
222} 231}
223 232
224static void set_lcd_data_lines(int data_lines) 233static void set_lcd_data_lines(int data_lines)
@@ -907,20 +916,20 @@ static irqreturn_t omap_dispc_irq_handler(int irq, void *dev)
907 916
908static int get_dss_clocks(void) 917static int get_dss_clocks(void)
909{ 918{
910 dispc.dss_ick = clk_get(dispc.fbdev->dev, "ick"); 919 dispc.dss_ick = clk_get(&dispc.fbdev->dssdev->dev, "ick");
911 if (IS_ERR(dispc.dss_ick)) { 920 if (IS_ERR(dispc.dss_ick)) {
912 dev_err(dispc.fbdev->dev, "can't get ick\n"); 921 dev_err(dispc.fbdev->dev, "can't get ick\n");
913 return PTR_ERR(dispc.dss_ick); 922 return PTR_ERR(dispc.dss_ick);
914 } 923 }
915 924
916 dispc.dss1_fck = clk_get(dispc.fbdev->dev, "dss1_fck"); 925 dispc.dss1_fck = clk_get(&dispc.fbdev->dssdev->dev, "dss1_fck");
917 if (IS_ERR(dispc.dss1_fck)) { 926 if (IS_ERR(dispc.dss1_fck)) {
918 dev_err(dispc.fbdev->dev, "can't get dss1_fck\n"); 927 dev_err(dispc.fbdev->dev, "can't get dss1_fck\n");
919 clk_put(dispc.dss_ick); 928 clk_put(dispc.dss_ick);
920 return PTR_ERR(dispc.dss1_fck); 929 return PTR_ERR(dispc.dss1_fck);
921 } 930 }
922 931
923 dispc.dss_54m_fck = clk_get(dispc.fbdev->dev, "tv_fck"); 932 dispc.dss_54m_fck = clk_get(&dispc.fbdev->dssdev->dev, "tv_fck");
924 if (IS_ERR(dispc.dss_54m_fck)) { 933 if (IS_ERR(dispc.dss_54m_fck)) {
925 dev_err(dispc.fbdev->dev, "can't get tv_fck\n"); 934 dev_err(dispc.fbdev->dev, "can't get tv_fck\n");
926 clk_put(dispc.dss_ick); 935 clk_put(dispc.dss_ick);
@@ -1367,6 +1376,7 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
1367 int r; 1376 int r;
1368 u32 l; 1377 u32 l;
1369 struct lcd_panel *panel = fbdev->panel; 1378 struct lcd_panel *panel = fbdev->panel;
1379 void __iomem *ram_fw_base;
1370 int tmo = 10000; 1380 int tmo = 10000;
1371 int skip_init = 0; 1381 int skip_init = 0;
1372 int i; 1382 int i;
@@ -1441,7 +1451,13 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
1441 } 1451 }
1442 1452
1443 /* L3 firewall setting: enable access to OCM RAM */ 1453 /* L3 firewall setting: enable access to OCM RAM */
1444 __raw_writel(0x402000b0, OMAP2_IO_ADDRESS(0x680050a0)); 1454 ram_fw_base = ioremap(0x68005000, SZ_1K);
1455 if (!ram_fw_base) {
1456 dev_err(dispc.fbdev->dev, "Cannot ioremap to enable OCM RAM\n");
1457 goto fail1;
1458 }
1459 __raw_writel(0x402000b0, ram_fw_base + 0xa0);
1460 iounmap(ram_fw_base);
1445 1461
1446 if ((r = alloc_palette_ram()) < 0) 1462 if ((r = alloc_palette_ram()) < 0)
1447 goto fail2; 1463 goto fail2;
diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c
index ca51583ec98a..0016f77cd13f 100644
--- a/drivers/video/omap/hwa742.c
+++ b/drivers/video/omap/hwa742.c
@@ -25,10 +25,11 @@
25#include <linux/fb.h> 25#include <linux/fb.h>
26#include <linux/delay.h> 26#include <linux/delay.h>
27#include <linux/clk.h> 27#include <linux/clk.h>
28#include <linux/interrupt.h>
28 29
29#include <mach/dma.h> 30#include <plat/dma.h>
30#include <mach/omapfb.h> 31#include <plat/hwa742.h>
31#include <mach/hwa742.h> 32#include "omapfb.h"
32 33
33#define HWA742_REV_CODE_REG 0x0 34#define HWA742_REV_CODE_REG 0x0
34#define HWA742_CONFIG_REG 0x2 35#define HWA742_CONFIG_REG 0x2
diff --git a/drivers/video/omap/lcd_2430sdp.c b/drivers/video/omap/lcd_2430sdp.c
index 393712b6f369..e3eccc9af78e 100644
--- a/drivers/video/omap/lcd_2430sdp.c
+++ b/drivers/video/omap/lcd_2430sdp.c
@@ -25,12 +25,13 @@
25#include <linux/platform_device.h> 25#include <linux/platform_device.h>
26#include <linux/delay.h> 26#include <linux/delay.h>
27#include <linux/gpio.h> 27#include <linux/gpio.h>
28#include <linux/i2c/twl4030.h> 28#include <linux/i2c/twl.h>
29 29
30#include <mach/mux.h> 30#include <plat/mux.h>
31#include <mach/omapfb.h>
32#include <asm/mach-types.h> 31#include <asm/mach-types.h>
33 32
33#include "omapfb.h"
34
34#define SDP2430_LCD_PANEL_BACKLIGHT_GPIO 91 35#define SDP2430_LCD_PANEL_BACKLIGHT_GPIO 91
35#define SDP2430_LCD_PANEL_ENABLE_GPIO 154 36#define SDP2430_LCD_PANEL_ENABLE_GPIO 154
36#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 24 37#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 24
@@ -51,7 +52,7 @@ static unsigned enable_gpio;
51#define TWL4030_VPLL2_DEV_GRP 0x33 52#define TWL4030_VPLL2_DEV_GRP 0x33
52#define TWL4030_VPLL2_DEDICATED 0x36 53#define TWL4030_VPLL2_DEDICATED 0x36
53 54
54#define t2_out(c, r, v) twl4030_i2c_write_u8(c, r, v) 55#define t2_out(c, r, v) twl_i2c_write_u8(c, r, v)
55 56
56 57
57static int sdp2430_panel_init(struct lcd_panel *panel, 58static int sdp2430_panel_init(struct lcd_panel *panel,
diff --git a/drivers/video/omap/lcd_ams_delta.c b/drivers/video/omap/lcd_ams_delta.c
index 1f7439955e02..6978ae4ef83a 100644
--- a/drivers/video/omap/lcd_ams_delta.c
+++ b/drivers/video/omap/lcd_ams_delta.c
@@ -24,13 +24,80 @@
24#include <linux/platform_device.h> 24#include <linux/platform_device.h>
25#include <linux/io.h> 25#include <linux/io.h>
26#include <linux/delay.h> 26#include <linux/delay.h>
27#include <linux/lcd.h>
27 28
28#include <mach/board-ams-delta.h> 29#include <plat/board-ams-delta.h>
29#include <mach/hardware.h> 30#include <mach/hardware.h>
30#include <mach/omapfb.h> 31
32#include "omapfb.h"
31 33
32#define AMS_DELTA_DEFAULT_CONTRAST 112 34#define AMS_DELTA_DEFAULT_CONTRAST 112
33 35
36#define AMS_DELTA_MAX_CONTRAST 0x00FF
37#define AMS_DELTA_LCD_POWER 0x0100
38
39
40/* LCD class device section */
41
42static int ams_delta_lcd;
43
44static int ams_delta_lcd_set_power(struct lcd_device *dev, int power)
45{
46 if (power == FB_BLANK_UNBLANK) {
47 if (!(ams_delta_lcd & AMS_DELTA_LCD_POWER)) {
48 omap_writeb(ams_delta_lcd & AMS_DELTA_MAX_CONTRAST,
49 OMAP_PWL_ENABLE);
50 omap_writeb(1, OMAP_PWL_CLK_ENABLE);
51 ams_delta_lcd |= AMS_DELTA_LCD_POWER;
52 }
53 } else {
54 if (ams_delta_lcd & AMS_DELTA_LCD_POWER) {
55 omap_writeb(0, OMAP_PWL_ENABLE);
56 omap_writeb(0, OMAP_PWL_CLK_ENABLE);
57 ams_delta_lcd &= ~AMS_DELTA_LCD_POWER;
58 }
59 }
60 return 0;
61}
62
63static int ams_delta_lcd_set_contrast(struct lcd_device *dev, int value)
64{
65 if ((value >= 0) && (value <= AMS_DELTA_MAX_CONTRAST)) {
66 omap_writeb(value, OMAP_PWL_ENABLE);
67 ams_delta_lcd &= ~AMS_DELTA_MAX_CONTRAST;
68 ams_delta_lcd |= value;
69 }
70 return 0;
71}
72
73#ifdef CONFIG_LCD_CLASS_DEVICE
74static int ams_delta_lcd_get_power(struct lcd_device *dev)
75{
76 if (ams_delta_lcd & AMS_DELTA_LCD_POWER)
77 return FB_BLANK_UNBLANK;
78 else
79 return FB_BLANK_POWERDOWN;
80}
81
82static int ams_delta_lcd_get_contrast(struct lcd_device *dev)
83{
84 if (!(ams_delta_lcd & AMS_DELTA_LCD_POWER))
85 return 0;
86
87 return ams_delta_lcd & AMS_DELTA_MAX_CONTRAST;
88}
89
90static struct lcd_ops ams_delta_lcd_ops = {
91 .get_power = ams_delta_lcd_get_power,
92 .set_power = ams_delta_lcd_set_power,
93 .get_contrast = ams_delta_lcd_get_contrast,
94 .set_contrast = ams_delta_lcd_set_contrast,
95};
96#endif
97
98
99/* omapfb panel section */
100
34static int ams_delta_panel_init(struct lcd_panel *panel, 101static int ams_delta_panel_init(struct lcd_panel *panel,
35 struct omapfb_device *fbdev) 102 struct omapfb_device *fbdev)
36{ 103{
@@ -47,10 +114,6 @@ static int ams_delta_panel_enable(struct lcd_panel *panel)
47 AMS_DELTA_LATCH2_LCD_NDISP); 114 AMS_DELTA_LATCH2_LCD_NDISP);
48 ams_delta_latch2_write(AMS_DELTA_LATCH2_LCD_VBLEN, 115 ams_delta_latch2_write(AMS_DELTA_LATCH2_LCD_VBLEN,
49 AMS_DELTA_LATCH2_LCD_VBLEN); 116 AMS_DELTA_LATCH2_LCD_VBLEN);
50
51 omap_writeb(1, OMAP_PWL_CLK_ENABLE);
52 omap_writeb(AMS_DELTA_DEFAULT_CONTRAST, OMAP_PWL_ENABLE);
53
54 return 0; 117 return 0;
55} 118}
56 119
@@ -90,8 +153,31 @@ static struct lcd_panel ams_delta_panel = {
90 .get_caps = ams_delta_panel_get_caps, 153 .get_caps = ams_delta_panel_get_caps,
91}; 154};
92 155
156
157/* platform driver section */
158
93static int ams_delta_panel_probe(struct platform_device *pdev) 159static int ams_delta_panel_probe(struct platform_device *pdev)
94{ 160{
161 struct lcd_device *lcd_device = NULL;
162#ifdef CONFIG_LCD_CLASS_DEVICE
163 int ret;
164
165 lcd_device = lcd_device_register("omapfb", &pdev->dev, NULL,
166 &ams_delta_lcd_ops);
167
168 if (IS_ERR(lcd_device)) {
169 ret = PTR_ERR(lcd_device);
170 dev_err(&pdev->dev, "failed to register device\n");
171 return ret;
172 }
173
174 platform_set_drvdata(pdev, lcd_device);
175 lcd_device->props.max_contrast = AMS_DELTA_MAX_CONTRAST;
176#endif
177
178 ams_delta_lcd_set_contrast(lcd_device, AMS_DELTA_DEFAULT_CONTRAST);
179 ams_delta_lcd_set_power(lcd_device, FB_BLANK_UNBLANK);
180
95 omapfb_register_panel(&ams_delta_panel); 181 omapfb_register_panel(&ams_delta_panel);
96 return 0; 182 return 0;
97} 183}
@@ -123,12 +209,12 @@ struct platform_driver ams_delta_panel_driver = {
123 }, 209 },
124}; 210};
125 211
126static int ams_delta_panel_drv_init(void) 212static int __init ams_delta_panel_drv_init(void)
127{ 213{
128 return platform_driver_register(&ams_delta_panel_driver); 214 return platform_driver_register(&ams_delta_panel_driver);
129} 215}
130 216
131static void ams_delta_panel_drv_cleanup(void) 217static void __exit ams_delta_panel_drv_cleanup(void)
132{ 218{
133 platform_driver_unregister(&ams_delta_panel_driver); 219 platform_driver_unregister(&ams_delta_panel_driver);
134} 220}
diff --git a/drivers/video/omap/lcd_apollon.c b/drivers/video/omap/lcd_apollon.c
index 626ae3a532ff..2be94eb3bbf5 100644
--- a/drivers/video/omap/lcd_apollon.c
+++ b/drivers/video/omap/lcd_apollon.c
@@ -25,8 +25,9 @@
25#include <linux/platform_device.h> 25#include <linux/platform_device.h>
26 26
27#include <mach/gpio.h> 27#include <mach/gpio.h>
28#include <mach/mux.h> 28#include <plat/mux.h>
29#include <mach/omapfb.h> 29
30#include "omapfb.h"
30 31
31/* #define USE_35INCH_LCD 1 */ 32/* #define USE_35INCH_LCD 1 */
32 33
diff --git a/drivers/video/omap/lcd_h3.c b/drivers/video/omap/lcd_h3.c
index 417ae5efa8bb..8df688748b5a 100644
--- a/drivers/video/omap/lcd_h3.c
+++ b/drivers/video/omap/lcd_h3.c
@@ -24,7 +24,7 @@
24#include <linux/i2c/tps65010.h> 24#include <linux/i2c/tps65010.h>
25 25
26#include <mach/gpio.h> 26#include <mach/gpio.h>
27#include <mach/omapfb.h> 27#include "omapfb.h"
28 28
29#define MODULE_NAME "omapfb-lcd_h3" 29#define MODULE_NAME "omapfb-lcd_h3"
30 30
diff --git a/drivers/video/omap/lcd_h4.c b/drivers/video/omap/lcd_h4.c
index 0c398bda7601..03a06a982750 100644
--- a/drivers/video/omap/lcd_h4.c
+++ b/drivers/video/omap/lcd_h4.c
@@ -22,7 +22,7 @@
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24 24
25#include <mach/omapfb.h> 25#include "omapfb.h"
26 26
27static int h4_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) 27static int h4_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
28{ 28{
diff --git a/drivers/video/omap/lcd_htcherald.c b/drivers/video/omap/lcd_htcherald.c
new file mode 100644
index 000000000000..4802419da83b
--- /dev/null
+++ b/drivers/video/omap/lcd_htcherald.c
@@ -0,0 +1,130 @@
1/*
2 * File: drivers/video/omap/lcd-htcherald.c
3 *
4 * LCD panel support for the HTC Herald
5 *
6 * Copyright (C) 2009 Cory Maccarrone <darkstar6262@gmail.com>
7 * Copyright (C) 2009 Wing Linux
8 *
9 * Based on the lcd_htcwizard.c file from the linwizard project:
10 * Copyright (C) linwizard.sourceforge.net
11 * Author: Angelo Arrifano <miknix@gmail.com>
12 * Based on lcd_h4 by Imre Deak <imre.deak@nokia.com>
13 *
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 */
28
29#include <linux/module.h>
30#include <linux/platform_device.h>
31
32#include "omapfb.h"
33
34static int htcherald_panel_init(struct lcd_panel *panel,
35 struct omapfb_device *fbdev)
36{
37 return 0;
38}
39
40static void htcherald_panel_cleanup(struct lcd_panel *panel)
41{
42}
43
44static int htcherald_panel_enable(struct lcd_panel *panel)
45{
46 return 0;
47}
48
49static void htcherald_panel_disable(struct lcd_panel *panel)
50{
51}
52
53static unsigned long htcherald_panel_get_caps(struct lcd_panel *panel)
54{
55 return 0;
56}
57
58/* Found on WIZ200 (miknix) and some HERA110 models (darkstar62) */
59struct lcd_panel htcherald_panel_1 = {
60 .name = "lcd_herald",
61 .config = OMAP_LCDC_PANEL_TFT |
62 OMAP_LCDC_INV_HSYNC |
63 OMAP_LCDC_INV_VSYNC |
64 OMAP_LCDC_INV_PIX_CLOCK,
65 .bpp = 16,
66 .data_lines = 16,
67 .x_res = 240,
68 .y_res = 320,
69 .pixel_clock = 6093,
70 .pcd = 0, /* 15 */
71 .hsw = 10,
72 .hfp = 10,
73 .hbp = 20,
74 .vsw = 3,
75 .vfp = 2,
76 .vbp = 2,
77
78 .init = htcherald_panel_init,
79 .cleanup = htcherald_panel_cleanup,
80 .enable = htcherald_panel_enable,
81 .disable = htcherald_panel_disable,
82 .get_caps = htcherald_panel_get_caps,
83};
84
85static int htcherald_panel_probe(struct platform_device *pdev)
86{
87 omapfb_register_panel(&htcherald_panel_1);
88 return 0;
89}
90
91static int htcherald_panel_remove(struct platform_device *pdev)
92{
93 return 0;
94}
95
96static int htcherald_panel_suspend(struct platform_device *pdev,
97 pm_message_t mesg)
98{
99 return 0;
100}
101
102static int htcherald_panel_resume(struct platform_device *pdev)
103{
104 return 0;
105}
106
107struct platform_driver htcherald_panel_driver = {
108 .probe = htcherald_panel_probe,
109 .remove = htcherald_panel_remove,
110 .suspend = htcherald_panel_suspend,
111 .resume = htcherald_panel_resume,
112 .driver = {
113 .name = "lcd_htcherald",
114 .owner = THIS_MODULE,
115 },
116};
117
118static int __init htcherald_panel_drv_init(void)
119{
120 return platform_driver_register(&htcherald_panel_driver);
121}
122
123static void __exit htcherald_panel_drv_cleanup(void)
124{
125 platform_driver_unregister(&htcherald_panel_driver);
126}
127
128module_init(htcherald_panel_drv_init);
129module_exit(htcherald_panel_drv_cleanup);
130
diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/omap/lcd_inn1510.c
index cdbd8bb607be..3271f1643b26 100644
--- a/drivers/video/omap/lcd_inn1510.c
+++ b/drivers/video/omap/lcd_inn1510.c
@@ -23,8 +23,8 @@
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24#include <linux/io.h> 24#include <linux/io.h>
25 25
26#include <mach/fpga.h> 26#include <plat/fpga.h>
27#include <mach/omapfb.h> 27#include "omapfb.h"
28 28
29static int innovator1510_panel_init(struct lcd_panel *panel, 29static int innovator1510_panel_init(struct lcd_panel *panel,
30 struct omapfb_device *fbdev) 30 struct omapfb_device *fbdev)
diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c
index 268f7f808a4e..9fff86f67bde 100644
--- a/drivers/video/omap/lcd_inn1610.c
+++ b/drivers/video/omap/lcd_inn1610.c
@@ -23,7 +23,7 @@
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24 24
25#include <mach/gpio.h> 25#include <mach/gpio.h>
26#include <mach/omapfb.h> 26#include "omapfb.h"
27 27
28#define MODULE_NAME "omapfb-lcd_h3" 28#define MODULE_NAME "omapfb-lcd_h3"
29 29
diff --git a/drivers/video/omap/lcd_ldp.c b/drivers/video/omap/lcd_ldp.c
index dbfe8974fb94..0f5952cae85e 100644
--- a/drivers/video/omap/lcd_ldp.c
+++ b/drivers/video/omap/lcd_ldp.c
@@ -24,13 +24,14 @@
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/platform_device.h> 25#include <linux/platform_device.h>
26#include <linux/delay.h> 26#include <linux/delay.h>
27#include <linux/i2c/twl4030.h> 27#include <linux/i2c/twl.h>
28 28
29#include <mach/gpio.h> 29#include <mach/gpio.h>
30#include <mach/mux.h> 30#include <plat/mux.h>
31#include <mach/omapfb.h>
32#include <asm/mach-types.h> 31#include <asm/mach-types.h>
33 32
33#include "omapfb.h"
34
34#define LCD_PANEL_BACKLIGHT_GPIO (15 + OMAP_MAX_GPIO_LINES) 35#define LCD_PANEL_BACKLIGHT_GPIO (15 + OMAP_MAX_GPIO_LINES)
35#define LCD_PANEL_ENABLE_GPIO (7 + OMAP_MAX_GPIO_LINES) 36#define LCD_PANEL_ENABLE_GPIO (7 + OMAP_MAX_GPIO_LINES)
36 37
@@ -58,7 +59,7 @@
58#define TWL4030_VPLL2_DEV_GRP 0x33 59#define TWL4030_VPLL2_DEV_GRP 0x33
59#define TWL4030_VPLL2_DEDICATED 0x36 60#define TWL4030_VPLL2_DEDICATED 0x36
60 61
61#define t2_out(c, r, v) twl4030_i2c_write_u8(c, r, v) 62#define t2_out(c, r, v) twl_i2c_write_u8(c, r, v)
62 63
63 64
64static int ldp_panel_init(struct lcd_panel *panel, 65static int ldp_panel_init(struct lcd_panel *panel,
diff --git a/drivers/video/omap/lcd_mipid.c b/drivers/video/omap/lcd_mipid.c
index 918ee8934196..64dcc7439c99 100644
--- a/drivers/video/omap/lcd_mipid.c
+++ b/drivers/video/omap/lcd_mipid.c
@@ -20,11 +20,13 @@
20 */ 20 */
21#include <linux/device.h> 21#include <linux/device.h>
22#include <linux/delay.h> 22#include <linux/delay.h>
23#include <linux/slab.h>
23#include <linux/workqueue.h> 24#include <linux/workqueue.h>
24#include <linux/spi/spi.h> 25#include <linux/spi/spi.h>
25 26
26#include <mach/omapfb.h> 27#include <plat/lcd_mipid.h>
27#include <mach/lcd_mipid.h> 28
29#include "omapfb.h"
28 30
29#define MIPID_MODULE_NAME "lcd_mipid" 31#define MIPID_MODULE_NAME "lcd_mipid"
30 32
@@ -607,7 +609,7 @@ static struct spi_driver mipid_spi_driver = {
607 .remove = __devexit_p(mipid_spi_remove), 609 .remove = __devexit_p(mipid_spi_remove),
608}; 610};
609 611
610static int mipid_drv_init(void) 612static int __init mipid_drv_init(void)
611{ 613{
612 spi_register_driver(&mipid_spi_driver); 614 spi_register_driver(&mipid_spi_driver);
613 615
@@ -615,7 +617,7 @@ static int mipid_drv_init(void)
615} 617}
616module_init(mipid_drv_init); 618module_init(mipid_drv_init);
617 619
618static void mipid_drv_cleanup(void) 620static void __exit mipid_drv_cleanup(void)
619{ 621{
620 spi_unregister_driver(&mipid_spi_driver); 622 spi_unregister_driver(&mipid_spi_driver);
621} 623}
diff --git a/drivers/video/omap/lcd_omap2evm.c b/drivers/video/omap/lcd_omap2evm.c
index 7a2bbe2ecec3..7e7a65c08452 100644
--- a/drivers/video/omap/lcd_omap2evm.c
+++ b/drivers/video/omap/lcd_omap2evm.c
@@ -24,12 +24,13 @@
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/platform_device.h> 25#include <linux/platform_device.h>
26#include <linux/gpio.h> 26#include <linux/gpio.h>
27#include <linux/i2c/twl4030.h> 27#include <linux/i2c/twl.h>
28 28
29#include <mach/mux.h> 29#include <plat/mux.h>
30#include <mach/omapfb.h>
31#include <asm/mach-types.h> 30#include <asm/mach-types.h>
32 31
32#include "omapfb.h"
33
33#define LCD_PANEL_ENABLE_GPIO 154 34#define LCD_PANEL_ENABLE_GPIO 154
34#define LCD_PANEL_LR 128 35#define LCD_PANEL_LR 128
35#define LCD_PANEL_UD 129 36#define LCD_PANEL_UD 129
@@ -60,9 +61,9 @@ static int omap2evm_panel_init(struct lcd_panel *panel,
60 gpio_direction_output(LCD_PANEL_LR, 1); 61 gpio_direction_output(LCD_PANEL_LR, 1);
61 gpio_direction_output(LCD_PANEL_UD, 1); 62 gpio_direction_output(LCD_PANEL_UD, 1);
62 63
63 twl4030_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN); 64 twl_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN);
64 twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON); 65 twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON);
65 twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF); 66 twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF);
66 bklight_level = 100; 67 bklight_level = 100;
67 68
68 return 0; 69 return 0;
@@ -100,7 +101,7 @@ static int omap2evm_bklight_setlevel(struct lcd_panel *panel,
100 u8 c; 101 u8 c;
101 if ((level >= 0) && (level <= 100)) { 102 if ((level >= 0) && (level <= 100)) {
102 c = (125 * (100 - level)) / 100 + 2; 103 c = (125 * (100 - level)) / 100 + 2;
103 twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, c, TWL_PWMA_PWMAOFF); 104 twl_i2c_write_u8(TWL4030_MODULE_PWMA, c, TWL_PWMA_PWMAOFF);
104 bklight_level = level; 105 bklight_level = level;
105 } 106 }
106 return 0; 107 return 0;
diff --git a/drivers/video/omap/lcd_omap3beagle.c b/drivers/video/omap/lcd_omap3beagle.c
index 4011910123bf..ca75cc2a87a5 100644
--- a/drivers/video/omap/lcd_omap3beagle.c
+++ b/drivers/video/omap/lcd_omap3beagle.c
@@ -23,12 +23,14 @@
23#include <linux/module.h> 23#include <linux/module.h>
24#include <linux/platform_device.h> 24#include <linux/platform_device.h>
25#include <linux/gpio.h> 25#include <linux/gpio.h>
26#include <linux/i2c/twl4030.h> 26#include <linux/i2c/twl.h>
27 27
28#include <mach/mux.h> 28#include <plat/mux.h>
29#include <mach/omapfb.h> 29#include <plat/mux.h>
30#include <asm/mach-types.h> 30#include <asm/mach-types.h>
31 31
32#include "omapfb.h"
33
32#define LCD_PANEL_ENABLE_GPIO 170 34#define LCD_PANEL_ENABLE_GPIO 170
33 35
34static int omap3beagle_panel_init(struct lcd_panel *panel, 36static int omap3beagle_panel_init(struct lcd_panel *panel,
diff --git a/drivers/video/omap/lcd_omap3evm.c b/drivers/video/omap/lcd_omap3evm.c
index b6a4c2c57a2f..06840da0b094 100644
--- a/drivers/video/omap/lcd_omap3evm.c
+++ b/drivers/video/omap/lcd_omap3evm.c
@@ -23,12 +23,13 @@
23#include <linux/module.h> 23#include <linux/module.h>
24#include <linux/platform_device.h> 24#include <linux/platform_device.h>
25#include <linux/gpio.h> 25#include <linux/gpio.h>
26#include <linux/i2c/twl4030.h> 26#include <linux/i2c/twl.h>
27 27
28#include <mach/mux.h> 28#include <plat/mux.h>
29#include <mach/omapfb.h>
30#include <asm/mach-types.h> 29#include <asm/mach-types.h>
31 30
31#include "omapfb.h"
32
32#define LCD_PANEL_ENABLE_GPIO 153 33#define LCD_PANEL_ENABLE_GPIO 153
33#define LCD_PANEL_LR 2 34#define LCD_PANEL_LR 2
34#define LCD_PANEL_UD 3 35#define LCD_PANEL_UD 3
@@ -62,9 +63,9 @@ static int omap3evm_panel_init(struct lcd_panel *panel,
62 gpio_direction_output(LCD_PANEL_LR, 1); 63 gpio_direction_output(LCD_PANEL_LR, 1);
63 gpio_direction_output(LCD_PANEL_UD, 1); 64 gpio_direction_output(LCD_PANEL_UD, 1);
64 65
65 twl4030_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN); 66 twl_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN);
66 twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON); 67 twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON);
67 twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF); 68 twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF);
68 bklight_level = 100; 69 bklight_level = 100;
69 70
70 return 0; 71 return 0;
@@ -101,7 +102,7 @@ static int omap3evm_bklight_setlevel(struct lcd_panel *panel,
101 u8 c; 102 u8 c;
102 if ((level >= 0) && (level <= 100)) { 103 if ((level >= 0) && (level <= 100)) {
103 c = (125 * (100 - level)) / 100 + 2; 104 c = (125 * (100 - level)) / 100 + 2;
104 twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, c, TWL_PWMA_PWMAOFF); 105 twl_i2c_write_u8(TWL4030_MODULE_PWMA, c, TWL_PWMA_PWMAOFF);
105 bklight_level = level; 106 bklight_level = level;
106 } 107 }
107 return 0; 108 return 0;
diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/omap/lcd_osk.c
index b3fa88bc6269..b87e8b83f29c 100644
--- a/drivers/video/omap/lcd_osk.c
+++ b/drivers/video/omap/lcd_osk.c
@@ -24,8 +24,8 @@
24#include <linux/platform_device.h> 24#include <linux/platform_device.h>
25 25
26#include <mach/gpio.h> 26#include <mach/gpio.h>
27#include <mach/mux.h> 27#include <plat/mux.h>
28#include <mach/omapfb.h> 28#include "omapfb.h"
29 29
30static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) 30static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
31{ 31{
diff --git a/drivers/video/omap/lcd_overo.c b/drivers/video/omap/lcd_overo.c
index 2bc5c9268e5e..564933ffac6e 100644
--- a/drivers/video/omap/lcd_overo.c
+++ b/drivers/video/omap/lcd_overo.c
@@ -21,13 +21,14 @@
21 21
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24#include <linux/i2c/twl4030.h> 24#include <linux/i2c/twl.h>
25 25
26#include <mach/gpio.h> 26#include <mach/gpio.h>
27#include <mach/mux.h> 27#include <plat/mux.h>
28#include <mach/omapfb.h>
29#include <asm/mach-types.h> 28#include <asm/mach-types.h>
30 29
30#include "omapfb.h"
31
31#define LCD_ENABLE 144 32#define LCD_ENABLE 144
32 33
33static int overo_panel_init(struct lcd_panel *panel, 34static int overo_panel_init(struct lcd_panel *panel,
diff --git a/drivers/video/omap/lcd_palmte.c b/drivers/video/omap/lcd_palmte.c
index 4bf3c79f3cc7..4cb301750d02 100644
--- a/drivers/video/omap/lcd_palmte.c
+++ b/drivers/video/omap/lcd_palmte.c
@@ -23,8 +23,8 @@
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24#include <linux/io.h> 24#include <linux/io.h>
25 25
26#include <mach/fpga.h> 26#include <plat/fpga.h>
27#include <mach/omapfb.h> 27#include "omapfb.h"
28 28
29static int palmte_panel_init(struct lcd_panel *panel, 29static int palmte_panel_init(struct lcd_panel *panel,
30 struct omapfb_device *fbdev) 30 struct omapfb_device *fbdev)
diff --git a/drivers/video/omap/lcd_palmtt.c b/drivers/video/omap/lcd_palmtt.c
index 48ea1f9f2cbf..ff0e6d7ab3a2 100644
--- a/drivers/video/omap/lcd_palmtt.c
+++ b/drivers/video/omap/lcd_palmtt.c
@@ -30,7 +30,7 @@ GPIO13 - screen blanking
30#include <linux/io.h> 30#include <linux/io.h>
31 31
32#include <mach/gpio.h> 32#include <mach/gpio.h>
33#include <mach/omapfb.h> 33#include "omapfb.h"
34 34
35static int palmtt_panel_init(struct lcd_panel *panel, 35static int palmtt_panel_init(struct lcd_panel *panel,
36 struct omapfb_device *fbdev) 36 struct omapfb_device *fbdev)
diff --git a/drivers/video/omap/lcd_palmz71.c b/drivers/video/omap/lcd_palmz71.c
index 0697d29b4d3b..2334e56536bc 100644
--- a/drivers/video/omap/lcd_palmz71.c
+++ b/drivers/video/omap/lcd_palmz71.c
@@ -24,7 +24,7 @@
24#include <linux/platform_device.h> 24#include <linux/platform_device.h>
25#include <linux/io.h> 25#include <linux/io.h>
26 26
27#include <mach/omapfb.h> 27#include "omapfb.h"
28 28
29static int palmz71_panel_init(struct lcd_panel *panel, 29static int palmz71_panel_init(struct lcd_panel *panel,
30 struct omapfb_device *fbdev) 30 struct omapfb_device *fbdev)
diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c
index ab3949256677..43ab7d8b66b2 100644
--- a/drivers/video/omap/lcdc.c
+++ b/drivers/video/omap/lcdc.c
@@ -28,48 +28,19 @@
28#include <linux/dma-mapping.h> 28#include <linux/dma-mapping.h>
29#include <linux/vmalloc.h> 29#include <linux/vmalloc.h>
30#include <linux/clk.h> 30#include <linux/clk.h>
31#include <linux/gfp.h>
31 32
32#include <mach/dma.h> 33#include <mach/lcdc.h>
33#include <mach/omapfb.h> 34#include <plat/dma.h>
34 35
35#include <asm/mach-types.h> 36#include <asm/mach-types.h>
36 37
38#include "omapfb.h"
39
37#include "lcdc.h" 40#include "lcdc.h"
38 41
39#define MODULE_NAME "lcdc" 42#define MODULE_NAME "lcdc"
40 43
41#define OMAP_LCDC_BASE 0xfffec000
42#define OMAP_LCDC_SIZE 256
43#define OMAP_LCDC_IRQ INT_LCD_CTRL
44
45#define OMAP_LCDC_CONTROL (OMAP_LCDC_BASE + 0x00)
46#define OMAP_LCDC_TIMING0 (OMAP_LCDC_BASE + 0x04)
47#define OMAP_LCDC_TIMING1 (OMAP_LCDC_BASE + 0x08)
48#define OMAP_LCDC_TIMING2 (OMAP_LCDC_BASE + 0x0c)
49#define OMAP_LCDC_STATUS (OMAP_LCDC_BASE + 0x10)
50#define OMAP_LCDC_SUBPANEL (OMAP_LCDC_BASE + 0x14)
51#define OMAP_LCDC_LINE_INT (OMAP_LCDC_BASE + 0x18)
52#define OMAP_LCDC_DISPLAY_STATUS (OMAP_LCDC_BASE + 0x1c)
53
54#define OMAP_LCDC_STAT_DONE (1 << 0)
55#define OMAP_LCDC_STAT_VSYNC (1 << 1)
56#define OMAP_LCDC_STAT_SYNC_LOST (1 << 2)
57#define OMAP_LCDC_STAT_ABC (1 << 3)
58#define OMAP_LCDC_STAT_LINE_INT (1 << 4)
59#define OMAP_LCDC_STAT_FUF (1 << 5)
60#define OMAP_LCDC_STAT_LOADED_PALETTE (1 << 6)
61
62#define OMAP_LCDC_CTRL_LCD_EN (1 << 0)
63#define OMAP_LCDC_CTRL_LCD_TFT (1 << 7)
64#define OMAP_LCDC_CTRL_LINE_IRQ_CLR_SEL (1 << 10)
65
66#define OMAP_LCDC_IRQ_VSYNC (1 << 2)
67#define OMAP_LCDC_IRQ_DONE (1 << 3)
68#define OMAP_LCDC_IRQ_LOADED_PALETTE (1 << 4)
69#define OMAP_LCDC_IRQ_LINE_NIRQ (1 << 5)
70#define OMAP_LCDC_IRQ_LINE (1 << 6)
71#define OMAP_LCDC_IRQ_MASK (((1 << 5) - 1) << 2)
72
73#define MAX_PALETTE_SIZE PAGE_SIZE 44#define MAX_PALETTE_SIZE PAGE_SIZE
74 45
75enum lcdc_load_mode { 46enum lcdc_load_mode {
@@ -419,7 +390,7 @@ static int omap_lcdc_enable_plane(int plane, int enable)
419/* 390/*
420 * Configure the LCD DMA for a palette load operation and do the palette 391 * Configure the LCD DMA for a palette load operation and do the palette
421 * downloading synchronously. We don't use the frame+palette load mode of 392 * downloading synchronously. We don't use the frame+palette load mode of
422 * the controller, since the palette can always be downloaded seperately. 393 * the controller, since the palette can always be downloaded separately.
423 */ 394 */
424static void load_palette(void) 395static void load_palette(void)
425{ 396{
diff --git a/drivers/video/omap/omapfb.h b/drivers/video/omap/omapfb.h
new file mode 100644
index 000000000000..af3c9e571ec3
--- /dev/null
+++ b/drivers/video/omap/omapfb.h
@@ -0,0 +1,229 @@
1/*
2 * File: drivers/video/omap/omapfb.h
3 *
4 * Framebuffer driver for TI OMAP boards
5 *
6 * Copyright (C) 2004 Nokia Corporation
7 * Author: Imre Deak <imre.deak@nokia.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 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#ifndef __OMAPFB_H
25#define __OMAPFB_H
26
27#include <linux/fb.h>
28#include <linux/mutex.h>
29#include <linux/omapfb.h>
30
31#define OMAPFB_EVENT_READY 1
32#define OMAPFB_EVENT_DISABLED 2
33
34#define OMAP_LCDC_INV_VSYNC 0x0001
35#define OMAP_LCDC_INV_HSYNC 0x0002
36#define OMAP_LCDC_INV_PIX_CLOCK 0x0004
37#define OMAP_LCDC_INV_OUTPUT_EN 0x0008
38#define OMAP_LCDC_HSVS_RISING_EDGE 0x0010
39#define OMAP_LCDC_HSVS_OPPOSITE 0x0020
40
41#define OMAP_LCDC_SIGNAL_MASK 0x003f
42
43#define OMAP_LCDC_PANEL_TFT 0x0100
44
45#define OMAPFB_PLANE_XRES_MIN 8
46#define OMAPFB_PLANE_YRES_MIN 8
47
48struct omapfb_device;
49
50struct lcd_panel {
51 const char *name;
52 int config; /* TFT/STN, signal inversion */
53 int bpp; /* Pixel format in fb mem */
54 int data_lines; /* Lines on LCD HW interface */
55
56 int x_res, y_res;
57 int pixel_clock; /* In kHz */
58 int hsw; /* Horizontal synchronization
59 pulse width */
60 int hfp; /* Horizontal front porch */
61 int hbp; /* Horizontal back porch */
62 int vsw; /* Vertical synchronization
63 pulse width */
64 int vfp; /* Vertical front porch */
65 int vbp; /* Vertical back porch */
66 int acb; /* ac-bias pin frequency */
67 int pcd; /* pixel clock divider.
68 Obsolete use pixel_clock instead */
69
70 int (*init) (struct lcd_panel *panel,
71 struct omapfb_device *fbdev);
72 void (*cleanup) (struct lcd_panel *panel);
73 int (*enable) (struct lcd_panel *panel);
74 void (*disable) (struct lcd_panel *panel);
75 unsigned long (*get_caps) (struct lcd_panel *panel);
76 int (*set_bklight_level)(struct lcd_panel *panel,
77 unsigned int level);
78 unsigned int (*get_bklight_level)(struct lcd_panel *panel);
79 unsigned int (*get_bklight_max) (struct lcd_panel *panel);
80 int (*run_test) (struct lcd_panel *panel, int test_num);
81};
82
83struct extif_timings {
84 int cs_on_time;
85 int cs_off_time;
86 int we_on_time;
87 int we_off_time;
88 int re_on_time;
89 int re_off_time;
90 int we_cycle_time;
91 int re_cycle_time;
92 int cs_pulse_width;
93 int access_time;
94
95 int clk_div;
96
97 u32 tim[5]; /* set by extif->convert_timings */
98
99 int converted;
100};
101
102struct lcd_ctrl_extif {
103 int (*init) (struct omapfb_device *fbdev);
104 void (*cleanup) (void);
105 void (*get_clk_info) (u32 *clk_period, u32 *max_clk_div);
106 unsigned long (*get_max_tx_rate)(void);
107 int (*convert_timings) (struct extif_timings *timings);
108 void (*set_timings) (const struct extif_timings *timings);
109 void (*set_bits_per_cycle)(int bpc);
110 void (*write_command) (const void *buf, unsigned int len);
111 void (*read_data) (void *buf, unsigned int len);
112 void (*write_data) (const void *buf, unsigned int len);
113 void (*transfer_area) (int width, int height,
114 void (callback)(void *data), void *data);
115 int (*setup_tearsync) (unsigned pin_cnt,
116 unsigned hs_pulse_time, unsigned vs_pulse_time,
117 int hs_pol_inv, int vs_pol_inv, int div);
118 int (*enable_tearsync) (int enable, unsigned line);
119
120 unsigned long max_transmit_size;
121};
122
123struct omapfb_notifier_block {
124 struct notifier_block nb;
125 void *data;
126 int plane_idx;
127};
128
129typedef int (*omapfb_notifier_callback_t)(struct notifier_block *,
130 unsigned long event,
131 void *fbi);
132
133struct lcd_ctrl {
134 const char *name;
135 void *data;
136
137 int (*init) (struct omapfb_device *fbdev,
138 int ext_mode,
139 struct omapfb_mem_desc *req_md);
140 void (*cleanup) (void);
141 void (*bind_client) (struct omapfb_notifier_block *nb);
142 void (*get_caps) (int plane, struct omapfb_caps *caps);
143 int (*set_update_mode)(enum omapfb_update_mode mode);
144 enum omapfb_update_mode (*get_update_mode)(void);
145 int (*setup_plane) (int plane, int channel_out,
146 unsigned long offset,
147 int screen_width,
148 int pos_x, int pos_y, int width,
149 int height, int color_mode);
150 int (*set_rotate) (int angle);
151 int (*setup_mem) (int plane, size_t size,
152 int mem_type, unsigned long *paddr);
153 int (*mmap) (struct fb_info *info,
154 struct vm_area_struct *vma);
155 int (*set_scale) (int plane,
156 int orig_width, int orig_height,
157 int out_width, int out_height);
158 int (*enable_plane) (int plane, int enable);
159 int (*update_window) (struct fb_info *fbi,
160 struct omapfb_update_window *win,
161 void (*callback)(void *),
162 void *callback_data);
163 void (*sync) (void);
164 void (*suspend) (void);
165 void (*resume) (void);
166 int (*run_test) (int test_num);
167 int (*setcolreg) (u_int regno, u16 red, u16 green,
168 u16 blue, u16 transp,
169 int update_hw_mem);
170 int (*set_color_key) (struct omapfb_color_key *ck);
171 int (*get_color_key) (struct omapfb_color_key *ck);
172};
173
174enum omapfb_state {
175 OMAPFB_DISABLED = 0,
176 OMAPFB_SUSPENDED = 99,
177 OMAPFB_ACTIVE = 100
178};
179
180struct omapfb_plane_struct {
181 int idx;
182 struct omapfb_plane_info info;
183 enum omapfb_color_format color_mode;
184 struct omapfb_device *fbdev;
185};
186
187struct omapfb_device {
188 int state;
189 int ext_lcdc; /* Using external
190 LCD controller */
191 struct mutex rqueue_mutex;
192
193 int palette_size;
194 u32 pseudo_palette[17];
195
196 struct lcd_panel *panel; /* LCD panel */
197 const struct lcd_ctrl *ctrl; /* LCD controller */
198 const struct lcd_ctrl *int_ctrl; /* internal LCD ctrl */
199 struct lcd_ctrl_extif *ext_if; /* LCD ctrl external
200 interface */
201 struct device *dev;
202 struct fb_var_screeninfo new_var; /* for mode changes */
203
204 struct omapfb_mem_desc mem_desc;
205 struct fb_info *fb_info[OMAPFB_PLANE_NUM];
206
207 struct platform_device *dssdev; /* dummy dev for clocks */
208};
209
210#ifdef CONFIG_ARCH_OMAP1
211extern struct lcd_ctrl omap1_lcd_ctrl;
212#else
213extern struct lcd_ctrl omap2_disp_ctrl;
214#endif
215
216extern void omapfb_register_panel(struct lcd_panel *panel);
217extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
218extern void omapfb_notify_clients(struct omapfb_device *fbdev,
219 unsigned long event);
220extern int omapfb_register_client(struct omapfb_notifier_block *nb,
221 omapfb_notifier_callback_t callback,
222 void *callback_data);
223extern int omapfb_unregister_client(struct omapfb_notifier_block *nb);
224extern int omapfb_update_window_async(struct fb_info *fbi,
225 struct omapfb_update_window *win,
226 void (*callback)(void *),
227 void *callback_data);
228
229#endif /* __OMAPFB_H */
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
index 0d0c8c8b9b56..e264efd0278f 100644
--- a/drivers/video/omap/omapfb_main.c
+++ b/drivers/video/omap/omapfb_main.c
@@ -26,11 +26,12 @@
26 */ 26 */
27#include <linux/platform_device.h> 27#include <linux/platform_device.h>
28#include <linux/mm.h> 28#include <linux/mm.h>
29#include <linux/slab.h>
29#include <linux/uaccess.h> 30#include <linux/uaccess.h>
30 31
31#include <mach/dma.h> 32#include <plat/dma.h>
32#include <mach/omapfb.h>
33 33
34#include "omapfb.h"
34#include "lcdc.h" 35#include "lcdc.h"
35#include "dispc.h" 36#include "dispc.h"
36 37
@@ -83,6 +84,19 @@ static struct caps_table_struct color_caps[] = {
83 { 1 << OMAPFB_COLOR_YUY422, "YUY422", }, 84 { 1 << OMAPFB_COLOR_YUY422, "YUY422", },
84}; 85};
85 86
87static void omapdss_release(struct device *dev)
88{
89}
90
91/* dummy device for clocks */
92static struct platform_device omapdss_device = {
93 .name = "omapdss",
94 .id = -1,
95 .dev = {
96 .release = omapdss_release,
97 },
98};
99
86/* 100/*
87 * --------------------------------------------------------------------------- 101 * ---------------------------------------------------------------------------
88 * LCD panel 102 * LCD panel
@@ -473,10 +487,11 @@ static int set_color_mode(struct omapfb_plane_struct *plane,
473 return 0; 487 return 0;
474 case 12: 488 case 12:
475 var->bits_per_pixel = 16; 489 var->bits_per_pixel = 16;
476 plane->color_mode = OMAPFB_COLOR_RGB444;
477 return 0;
478 case 16: 490 case 16:
479 plane->color_mode = OMAPFB_COLOR_RGB565; 491 if (plane->fbdev->panel->bpp == 12)
492 plane->color_mode = OMAPFB_COLOR_RGB444;
493 else
494 plane->color_mode = OMAPFB_COLOR_RGB565;
480 return 0; 495 return 0;
481 default: 496 default:
482 return -EINVAL; 497 return -EINVAL;
@@ -1700,6 +1715,7 @@ static int omapfb_do_probe(struct platform_device *pdev,
1700 1715
1701 fbdev->dev = &pdev->dev; 1716 fbdev->dev = &pdev->dev;
1702 fbdev->panel = panel; 1717 fbdev->panel = panel;
1718 fbdev->dssdev = &omapdss_device;
1703 platform_set_drvdata(pdev, fbdev); 1719 platform_set_drvdata(pdev, fbdev);
1704 1720
1705 mutex_init(&fbdev->rqueue_mutex); 1721 mutex_init(&fbdev->rqueue_mutex);
@@ -1814,8 +1830,16 @@ cleanup:
1814 1830
1815static int omapfb_probe(struct platform_device *pdev) 1831static int omapfb_probe(struct platform_device *pdev)
1816{ 1832{
1833 int r;
1834
1817 BUG_ON(fbdev_pdev != NULL); 1835 BUG_ON(fbdev_pdev != NULL);
1818 1836
1837 r = platform_device_register(&omapdss_device);
1838 if (r) {
1839 dev_err(&pdev->dev, "can't register omapdss device\n");
1840 return r;
1841 }
1842
1819 /* Delay actual initialization until the LCD is registered */ 1843 /* Delay actual initialization until the LCD is registered */
1820 fbdev_pdev = pdev; 1844 fbdev_pdev = pdev;
1821 if (fbdev_panel != NULL) 1845 if (fbdev_panel != NULL)
@@ -1843,6 +1867,9 @@ static int omapfb_remove(struct platform_device *pdev)
1843 fbdev->state = OMAPFB_DISABLED; 1867 fbdev->state = OMAPFB_DISABLED;
1844 omapfb_free_resources(fbdev, saved_state); 1868 omapfb_free_resources(fbdev, saved_state);
1845 1869
1870 platform_device_unregister(&omapdss_device);
1871 fbdev->dssdev = NULL;
1872
1846 return 0; 1873 return 0;
1847} 1874}
1848 1875
diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c
index ee01e84e19c1..1162603c72e5 100644
--- a/drivers/video/omap/rfbi.c
+++ b/drivers/video/omap/rfbi.c
@@ -27,8 +27,7 @@
27#include <linux/clk.h> 27#include <linux/clk.h>
28#include <linux/io.h> 28#include <linux/io.h>
29 29
30#include <mach/omapfb.h> 30#include "omapfb.h"
31
32#include "dispc.h" 31#include "dispc.h"
33 32
34/* To work around an RFBI transfer rate limitation */ 33/* To work around an RFBI transfer rate limitation */
@@ -84,13 +83,13 @@ static inline u32 rfbi_read_reg(int idx)
84 83
85static int rfbi_get_clocks(void) 84static int rfbi_get_clocks(void)
86{ 85{
87 rfbi.dss_ick = clk_get(rfbi.fbdev->dev, "ick"); 86 rfbi.dss_ick = clk_get(&dispc.fbdev->dssdev->dev, "ick");
88 if (IS_ERR(rfbi.dss_ick)) { 87 if (IS_ERR(rfbi.dss_ick)) {
89 dev_err(rfbi.fbdev->dev, "can't get ick\n"); 88 dev_err(rfbi.fbdev->dev, "can't get ick\n");
90 return PTR_ERR(rfbi.dss_ick); 89 return PTR_ERR(rfbi.dss_ick);
91 } 90 }
92 91
93 rfbi.dss1_fck = clk_get(rfbi.fbdev->dev, "dss1_fck"); 92 rfbi.dss1_fck = clk_get(&dispc.fbdev->dssdev->dev, "dss1_fck");
94 if (IS_ERR(rfbi.dss1_fck)) { 93 if (IS_ERR(rfbi.dss1_fck)) {
95 dev_err(rfbi.fbdev->dev, "can't get dss1_fck\n"); 94 dev_err(rfbi.fbdev->dev, "can't get dss1_fck\n");
96 clk_put(rfbi.dss_ick); 95 clk_put(rfbi.dss_ick);
diff --git a/drivers/video/omap/sossi.c b/drivers/video/omap/sossi.c
index a76946220249..8fb7c708f563 100644
--- a/drivers/video/omap/sossi.c
+++ b/drivers/video/omap/sossi.c
@@ -23,10 +23,11 @@
23#include <linux/clk.h> 23#include <linux/clk.h>
24#include <linux/irq.h> 24#include <linux/irq.h>
25#include <linux/io.h> 25#include <linux/io.h>
26#include <linux/interrupt.h>
26 27
27#include <mach/dma.h> 28#include <plat/dma.h>
28#include <mach/omapfb.h>
29 29
30#include "omapfb.h"
30#include "lcdc.h" 31#include "lcdc.h"
31 32
32#define MODULE_NAME "omapfb-sossi" 33#define MODULE_NAME "omapfb-sossi"
diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
new file mode 100644
index 000000000000..d877c361abda
--- /dev/null
+++ b/drivers/video/omap2/Kconfig
@@ -0,0 +1,9 @@
1config OMAP2_VRAM
2 bool
3
4config OMAP2_VRFB
5 bool
6
7source "drivers/video/omap2/dss/Kconfig"
8source "drivers/video/omap2/omapfb/Kconfig"
9source "drivers/video/omap2/displays/Kconfig"
diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
new file mode 100644
index 000000000000..d853d05dad31
--- /dev/null
+++ b/drivers/video/omap2/Makefile
@@ -0,0 +1,6 @@
1obj-$(CONFIG_OMAP2_VRAM) += vram.o
2obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
3
4obj-y += dss/
5obj-y += omapfb/
6obj-y += displays/
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
new file mode 100644
index 000000000000..dfb57ee50861
--- /dev/null
+++ b/drivers/video/omap2/displays/Kconfig
@@ -0,0 +1,40 @@
1menu "OMAP2/3 Display Device Drivers"
2 depends on OMAP2_DSS
3
4config PANEL_GENERIC
5 tristate "Generic Panel"
6 help
7 Generic panel driver.
8 Used for DVI output for Beagle and OMAP3 SDP.
9
10config PANEL_SHARP_LS037V7DW01
11 tristate "Sharp LS037V7DW01 LCD Panel"
12 depends on OMAP2_DSS
13 help
14 LCD Panel used in TI's SDP3430 and EVM boards
15
16config PANEL_SHARP_LQ043T1DG01
17 tristate "Sharp LQ043T1DG01 LCD Panel"
18 depends on OMAP2_DSS
19 help
20 LCD Panel used in TI's OMAP3517 EVM boards
21
22config PANEL_TAAL
23 tristate "Taal DSI Panel"
24 depends on OMAP2_DSS_DSI
25 help
26 Taal DSI command mode panel from TPO.
27
28config PANEL_TOPPOLY_TDO35S
29 tristate "Toppoly TDO35S LCD Panel support"
30 depends on OMAP2_DSS
31 help
32 LCD Panel used in CM-T35
33
34config PANEL_TPO_TD043MTEA1
35 tristate "TPO TD043MTEA1 LCD Panel"
36 depends on OMAP2_DSS && I2C
37 help
38 LCD Panel used in OMAP3 Pandora
39
40endmenu
diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
new file mode 100644
index 000000000000..e2bb32168dee
--- /dev/null
+++ b/drivers/video/omap2/displays/Makefile
@@ -0,0 +1,7 @@
1obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o
2obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
3obj-$(CONFIG_PANEL_SHARP_LQ043T1DG01) += panel-sharp-lq043t1dg01.o
4
5obj-$(CONFIG_PANEL_TAAL) += panel-taal.o
6obj-$(CONFIG_PANEL_TOPPOLY_TDO35S) += panel-toppoly-tdo35s.o
7obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
diff --git a/drivers/video/omap2/displays/panel-generic.c b/drivers/video/omap2/displays/panel-generic.c
new file mode 100644
index 000000000000..300eff5de1b4
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-generic.c
@@ -0,0 +1,168 @@
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-sharp-lq043t1dg01.c b/drivers/video/omap2/displays/panel-sharp-lq043t1dg01.c
new file mode 100644
index 000000000000..10267461991c
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-sharp-lq043t1dg01.c
@@ -0,0 +1,159 @@
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
new file mode 100644
index 000000000000..8d51a5e6341c
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
@@ -0,0 +1,148 @@
1/*
2 * LCD panel driver for Sharp LS037V7DW01
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#include <linux/device.h>
23#include <linux/err.h>
24
25#include <plat/display.h>
26
27static struct omap_video_timings sharp_ls_timings = {
28 .x_res = 480,
29 .y_res = 640,
30
31 .pixel_clock = 19200,
32
33 .hsw = 2,
34 .hfp = 1,
35 .hbp = 28,
36
37 .vsw = 1,
38 .vfp = 1,
39 .vbp = 1,
40};
41
42static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
43{
44 dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
45 OMAP_DSS_LCD_IHS;
46 dssdev->panel.acb = 0x28;
47 dssdev->panel.timings = sharp_ls_timings;
48
49 return 0;
50}
51
52static void sharp_ls_panel_remove(struct omap_dss_device *dssdev)
53{
54}
55
56static int sharp_ls_power_on(struct omap_dss_device *dssdev)
57{
58 int r = 0;
59
60 r = omapdss_dpi_display_enable(dssdev);
61 if (r)
62 goto err0;
63
64 /* wait couple of vsyncs until enabling the LCD */
65 msleep(50);
66
67 if (dssdev->platform_enable) {
68 r = dssdev->platform_enable(dssdev);
69 if (r)
70 goto err1;
71 }
72
73 return 0;
74err1:
75 omapdss_dpi_display_disable(dssdev);
76err0:
77 return r;
78}
79
80static void sharp_ls_power_off(struct omap_dss_device *dssdev)
81{
82 if (dssdev->platform_disable)
83 dssdev->platform_disable(dssdev);
84
85 /* wait at least 5 vsyncs after disabling the LCD */
86
87 msleep(100);
88
89 omapdss_dpi_display_disable(dssdev);
90}
91
92static int sharp_ls_panel_enable(struct omap_dss_device *dssdev)
93{
94 int r;
95 r = sharp_ls_power_on(dssdev);
96 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
97 return r;
98}
99
100static void sharp_ls_panel_disable(struct omap_dss_device *dssdev)
101{
102 sharp_ls_power_off(dssdev);
103 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
104}
105
106static int sharp_ls_panel_suspend(struct omap_dss_device *dssdev)
107{
108 sharp_ls_power_off(dssdev);
109 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
110 return 0;
111}
112
113static int sharp_ls_panel_resume(struct omap_dss_device *dssdev)
114{
115 int r;
116 r = sharp_ls_power_on(dssdev);
117 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
118 return r;
119}
120
121static struct omap_dss_driver sharp_ls_driver = {
122 .probe = sharp_ls_panel_probe,
123 .remove = sharp_ls_panel_remove,
124
125 .enable = sharp_ls_panel_enable,
126 .disable = sharp_ls_panel_disable,
127 .suspend = sharp_ls_panel_suspend,
128 .resume = sharp_ls_panel_resume,
129
130 .driver = {
131 .name = "sharp_ls_panel",
132 .owner = THIS_MODULE,
133 },
134};
135
136static int __init sharp_ls_panel_drv_init(void)
137{
138 return omap_dss_register_driver(&sharp_ls_driver);
139}
140
141static void __exit sharp_ls_panel_drv_exit(void)
142{
143 omap_dss_unregister_driver(&sharp_ls_driver);
144}
145
146module_init(sharp_ls_panel_drv_init);
147module_exit(sharp_ls_panel_drv_exit);
148MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
new file mode 100644
index 000000000000..4f3988a41082
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -0,0 +1,1166 @@
1/*
2 * Taal DSI command mode panel
3 *
4 * Copyright (C) 2009 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/*#define DEBUG*/
21
22#include <linux/module.h>
23#include <linux/delay.h>
24#include <linux/err.h>
25#include <linux/jiffies.h>
26#include <linux/sched.h>
27#include <linux/backlight.h>
28#include <linux/fb.h>
29#include <linux/interrupt.h>
30#include <linux/gpio.h>
31#include <linux/completion.h>
32#include <linux/workqueue.h>
33#include <linux/slab.h>
34
35#include <plat/display.h>
36
37/* DSI Virtual channel. Hardcoded for now. */
38#define TCH 0
39
40#define DCS_READ_NUM_ERRORS 0x05
41#define DCS_READ_POWER_MODE 0x0a
42#define DCS_READ_MADCTL 0x0b
43#define DCS_READ_PIXEL_FORMAT 0x0c
44#define DCS_RDDSDR 0x0f
45#define DCS_SLEEP_IN 0x10
46#define DCS_SLEEP_OUT 0x11
47#define DCS_DISPLAY_OFF 0x28
48#define DCS_DISPLAY_ON 0x29
49#define DCS_COLUMN_ADDR 0x2a
50#define DCS_PAGE_ADDR 0x2b
51#define DCS_MEMORY_WRITE 0x2c
52#define DCS_TEAR_OFF 0x34
53#define DCS_TEAR_ON 0x35
54#define DCS_MEM_ACC_CTRL 0x36
55#define DCS_PIXEL_FORMAT 0x3a
56#define DCS_BRIGHTNESS 0x51
57#define DCS_CTRL_DISPLAY 0x53
58#define DCS_WRITE_CABC 0x55
59#define DCS_READ_CABC 0x56
60#define DCS_GET_ID1 0xda
61#define DCS_GET_ID2 0xdb
62#define DCS_GET_ID3 0xdc
63
64/* #define TAAL_USE_ESD_CHECK */
65#define TAAL_ESD_CHECK_PERIOD msecs_to_jiffies(5000)
66
67static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable);
68
69struct taal_data {
70 struct backlight_device *bldev;
71
72 unsigned long hw_guard_end; /* next value of jiffies when we can
73 * issue the next sleep in/out command
74 */
75 unsigned long hw_guard_wait; /* max guard time in jiffies */
76
77 struct omap_dss_device *dssdev;
78
79 bool enabled;
80 u8 rotate;
81 bool mirror;
82
83 bool te_enabled;
84 bool use_ext_te;
85 struct completion te_completion;
86
87 bool use_dsi_bl;
88
89 bool cabc_broken;
90 unsigned cabc_mode;
91
92 bool intro_printed;
93
94 struct workqueue_struct *esd_wq;
95 struct delayed_work esd_work;
96};
97
98static void taal_esd_work(struct work_struct *work);
99
100static void hw_guard_start(struct taal_data *td, int guard_msec)
101{
102 td->hw_guard_wait = msecs_to_jiffies(guard_msec);
103 td->hw_guard_end = jiffies + td->hw_guard_wait;
104}
105
106static void hw_guard_wait(struct taal_data *td)
107{
108 unsigned long wait = td->hw_guard_end - jiffies;
109
110 if ((long)wait > 0 && wait <= td->hw_guard_wait) {
111 set_current_state(TASK_UNINTERRUPTIBLE);
112 schedule_timeout(wait);
113 }
114}
115
116static int taal_dcs_read_1(u8 dcs_cmd, u8 *data)
117{
118 int r;
119 u8 buf[1];
120
121 r = dsi_vc_dcs_read(TCH, dcs_cmd, buf, 1);
122
123 if (r < 0)
124 return r;
125
126 *data = buf[0];
127
128 return 0;
129}
130
131static int taal_dcs_write_0(u8 dcs_cmd)
132{
133 return dsi_vc_dcs_write(TCH, &dcs_cmd, 1);
134}
135
136static int taal_dcs_write_1(u8 dcs_cmd, u8 param)
137{
138 u8 buf[2];
139 buf[0] = dcs_cmd;
140 buf[1] = param;
141 return dsi_vc_dcs_write(TCH, buf, 2);
142}
143
144static int taal_sleep_in(struct taal_data *td)
145
146{
147 u8 cmd;
148 int r;
149
150 hw_guard_wait(td);
151
152 cmd = DCS_SLEEP_IN;
153 r = dsi_vc_dcs_write_nosync(TCH, &cmd, 1);
154 if (r)
155 return r;
156
157 hw_guard_start(td, 120);
158
159 msleep(5);
160
161 return 0;
162}
163
164static int taal_sleep_out(struct taal_data *td)
165{
166 int r;
167
168 hw_guard_wait(td);
169
170 r = taal_dcs_write_0(DCS_SLEEP_OUT);
171 if (r)
172 return r;
173
174 hw_guard_start(td, 120);
175
176 msleep(5);
177
178 return 0;
179}
180
181static int taal_get_id(u8 *id1, u8 *id2, u8 *id3)
182{
183 int r;
184
185 r = taal_dcs_read_1(DCS_GET_ID1, id1);
186 if (r)
187 return r;
188 r = taal_dcs_read_1(DCS_GET_ID2, id2);
189 if (r)
190 return r;
191 r = taal_dcs_read_1(DCS_GET_ID3, id3);
192 if (r)
193 return r;
194
195 return 0;
196}
197
198static int taal_set_addr_mode(u8 rotate, bool mirror)
199{
200 int r;
201 u8 mode;
202 int b5, b6, b7;
203
204 r = taal_dcs_read_1(DCS_READ_MADCTL, &mode);
205 if (r)
206 return r;
207
208 switch (rotate) {
209 default:
210 case 0:
211 b7 = 0;
212 b6 = 0;
213 b5 = 0;
214 break;
215 case 1:
216 b7 = 0;
217 b6 = 1;
218 b5 = 1;
219 break;
220 case 2:
221 b7 = 1;
222 b6 = 1;
223 b5 = 0;
224 break;
225 case 3:
226 b7 = 1;
227 b6 = 0;
228 b5 = 1;
229 break;
230 }
231
232 if (mirror)
233 b6 = !b6;
234
235 mode &= ~((1<<7) | (1<<6) | (1<<5));
236 mode |= (b7 << 7) | (b6 << 6) | (b5 << 5);
237
238 return taal_dcs_write_1(DCS_MEM_ACC_CTRL, mode);
239}
240
241static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h)
242{
243 int r;
244 u16 x1 = x;
245 u16 x2 = x + w - 1;
246 u16 y1 = y;
247 u16 y2 = y + h - 1;
248
249 u8 buf[5];
250 buf[0] = DCS_COLUMN_ADDR;
251 buf[1] = (x1 >> 8) & 0xff;
252 buf[2] = (x1 >> 0) & 0xff;
253 buf[3] = (x2 >> 8) & 0xff;
254 buf[4] = (x2 >> 0) & 0xff;
255
256 r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf));
257 if (r)
258 return r;
259
260 buf[0] = DCS_PAGE_ADDR;
261 buf[1] = (y1 >> 8) & 0xff;
262 buf[2] = (y1 >> 0) & 0xff;
263 buf[3] = (y2 >> 8) & 0xff;
264 buf[4] = (y2 >> 0) & 0xff;
265
266 r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf));
267 if (r)
268 return r;
269
270 dsi_vc_send_bta_sync(TCH);
271
272 return r;
273}
274
275static int taal_bl_update_status(struct backlight_device *dev)
276{
277 struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
278 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
279 int r;
280 int level;
281
282 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
283 dev->props.power == FB_BLANK_UNBLANK)
284 level = dev->props.brightness;
285 else
286 level = 0;
287
288 dev_dbg(&dssdev->dev, "update brightness to %d\n", level);
289
290 if (td->use_dsi_bl) {
291 if (td->enabled) {
292 dsi_bus_lock();
293 r = taal_dcs_write_1(DCS_BRIGHTNESS, level);
294 dsi_bus_unlock();
295 if (r)
296 return r;
297 }
298 } else {
299 if (!dssdev->set_backlight)
300 return -EINVAL;
301
302 r = dssdev->set_backlight(dssdev, level);
303 if (r)
304 return r;
305 }
306
307 return 0;
308}
309
310static int taal_bl_get_intensity(struct backlight_device *dev)
311{
312 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
313 dev->props.power == FB_BLANK_UNBLANK)
314 return dev->props.brightness;
315
316 return 0;
317}
318
319static struct backlight_ops taal_bl_ops = {
320 .get_brightness = taal_bl_get_intensity,
321 .update_status = taal_bl_update_status,
322};
323
324static void taal_get_timings(struct omap_dss_device *dssdev,
325 struct omap_video_timings *timings)
326{
327 *timings = dssdev->panel.timings;
328}
329
330static void taal_get_resolution(struct omap_dss_device *dssdev,
331 u16 *xres, u16 *yres)
332{
333 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
334
335 if (td->rotate == 0 || td->rotate == 2) {
336 *xres = dssdev->panel.timings.x_res;
337 *yres = dssdev->panel.timings.y_res;
338 } else {
339 *yres = dssdev->panel.timings.x_res;
340 *xres = dssdev->panel.timings.y_res;
341 }
342}
343
344static irqreturn_t taal_te_isr(int irq, void *data)
345{
346 struct omap_dss_device *dssdev = data;
347 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
348
349 complete_all(&td->te_completion);
350
351 return IRQ_HANDLED;
352}
353
354static ssize_t taal_num_errors_show(struct device *dev,
355 struct device_attribute *attr, char *buf)
356{
357 struct omap_dss_device *dssdev = to_dss_device(dev);
358 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
359 u8 errors;
360 int r;
361
362 if (td->enabled) {
363 dsi_bus_lock();
364 r = taal_dcs_read_1(DCS_READ_NUM_ERRORS, &errors);
365 dsi_bus_unlock();
366 } else {
367 r = -ENODEV;
368 }
369
370 if (r)
371 return r;
372
373 return snprintf(buf, PAGE_SIZE, "%d\n", errors);
374}
375
376static ssize_t taal_hw_revision_show(struct device *dev,
377 struct device_attribute *attr, char *buf)
378{
379 struct omap_dss_device *dssdev = to_dss_device(dev);
380 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
381 u8 id1, id2, id3;
382 int r;
383
384 if (td->enabled) {
385 dsi_bus_lock();
386 r = taal_get_id(&id1, &id2, &id3);
387 dsi_bus_unlock();
388 } else {
389 r = -ENODEV;
390 }
391
392 if (r)
393 return r;
394
395 return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x\n", id1, id2, id3);
396}
397
398static const char *cabc_modes[] = {
399 "off", /* used also always when CABC is not supported */
400 "ui",
401 "still-image",
402 "moving-image",
403};
404
405static ssize_t show_cabc_mode(struct device *dev,
406 struct device_attribute *attr,
407 char *buf)
408{
409 struct omap_dss_device *dssdev = to_dss_device(dev);
410 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
411 const char *mode_str;
412 int mode;
413 int len;
414
415 mode = td->cabc_mode;
416
417 mode_str = "unknown";
418 if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes))
419 mode_str = cabc_modes[mode];
420 len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str);
421
422 return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1;
423}
424
425static ssize_t store_cabc_mode(struct device *dev,
426 struct device_attribute *attr,
427 const char *buf, size_t count)
428{
429 struct omap_dss_device *dssdev = to_dss_device(dev);
430 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
431 int i;
432
433 for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) {
434 if (sysfs_streq(cabc_modes[i], buf))
435 break;
436 }
437
438 if (i == ARRAY_SIZE(cabc_modes))
439 return -EINVAL;
440
441 if (td->enabled) {
442 dsi_bus_lock();
443 if (!td->cabc_broken)
444 taal_dcs_write_1(DCS_WRITE_CABC, i);
445 dsi_bus_unlock();
446 }
447
448 td->cabc_mode = i;
449
450 return count;
451}
452
453static ssize_t show_cabc_available_modes(struct device *dev,
454 struct device_attribute *attr,
455 char *buf)
456{
457 int len;
458 int i;
459
460 for (i = 0, len = 0;
461 len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++)
462 len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s",
463 i ? " " : "", cabc_modes[i],
464 i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : "");
465
466 return len < PAGE_SIZE ? len : PAGE_SIZE - 1;
467}
468
469static DEVICE_ATTR(num_dsi_errors, S_IRUGO, taal_num_errors_show, NULL);
470static DEVICE_ATTR(hw_revision, S_IRUGO, taal_hw_revision_show, NULL);
471static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR,
472 show_cabc_mode, store_cabc_mode);
473static DEVICE_ATTR(cabc_available_modes, S_IRUGO,
474 show_cabc_available_modes, NULL);
475
476static struct attribute *taal_attrs[] = {
477 &dev_attr_num_dsi_errors.attr,
478 &dev_attr_hw_revision.attr,
479 &dev_attr_cabc_mode.attr,
480 &dev_attr_cabc_available_modes.attr,
481 NULL,
482};
483
484static struct attribute_group taal_attr_group = {
485 .attrs = taal_attrs,
486};
487
488static int taal_probe(struct omap_dss_device *dssdev)
489{
490 struct backlight_properties props;
491 struct taal_data *td;
492 struct backlight_device *bldev;
493 int r;
494
495 const struct omap_video_timings taal_panel_timings = {
496 .x_res = 864,
497 .y_res = 480,
498 };
499
500 dev_dbg(&dssdev->dev, "probe\n");
501
502 dssdev->panel.config = OMAP_DSS_LCD_TFT;
503 dssdev->panel.timings = taal_panel_timings;
504 dssdev->ctrl.pixel_size = 24;
505
506 td = kzalloc(sizeof(*td), GFP_KERNEL);
507 if (!td) {
508 r = -ENOMEM;
509 goto err0;
510 }
511 td->dssdev = dssdev;
512
513 td->esd_wq = create_singlethread_workqueue("taal_esd");
514 if (td->esd_wq == NULL) {
515 dev_err(&dssdev->dev, "can't create ESD workqueue\n");
516 r = -ENOMEM;
517 goto err1;
518 }
519 INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work);
520
521 dev_set_drvdata(&dssdev->dev, td);
522
523 /* if no platform set_backlight() defined, presume DSI backlight
524 * control */
525 memset(&props, 0, sizeof(struct backlight_properties));
526 if (!dssdev->set_backlight)
527 td->use_dsi_bl = true;
528
529 if (td->use_dsi_bl)
530 props.max_brightness = 255;
531 else
532 props.max_brightness = 127;
533 bldev = backlight_device_register("taal", &dssdev->dev, dssdev,
534 &taal_bl_ops, &props);
535 if (IS_ERR(bldev)) {
536 r = PTR_ERR(bldev);
537 goto err2;
538 }
539
540 td->bldev = bldev;
541
542 bldev->props.fb_blank = FB_BLANK_UNBLANK;
543 bldev->props.power = FB_BLANK_UNBLANK;
544 if (td->use_dsi_bl)
545 bldev->props.brightness = 255;
546 else
547 bldev->props.brightness = 127;
548
549 taal_bl_update_status(bldev);
550
551 if (dssdev->phy.dsi.ext_te) {
552 int gpio = dssdev->phy.dsi.ext_te_gpio;
553
554 r = gpio_request(gpio, "taal irq");
555 if (r) {
556 dev_err(&dssdev->dev, "GPIO request failed\n");
557 goto err3;
558 }
559
560 gpio_direction_input(gpio);
561
562 r = request_irq(gpio_to_irq(gpio), taal_te_isr,
563 IRQF_DISABLED | IRQF_TRIGGER_RISING,
564 "taal vsync", dssdev);
565
566 if (r) {
567 dev_err(&dssdev->dev, "IRQ request failed\n");
568 gpio_free(gpio);
569 goto err3;
570 }
571
572 init_completion(&td->te_completion);
573
574 td->use_ext_te = true;
575 }
576
577 r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group);
578 if (r) {
579 dev_err(&dssdev->dev, "failed to create sysfs files\n");
580 goto err4;
581 }
582
583 return 0;
584err4:
585 if (td->use_ext_te) {
586 int gpio = dssdev->phy.dsi.ext_te_gpio;
587 free_irq(gpio_to_irq(gpio), dssdev);
588 gpio_free(gpio);
589 }
590err3:
591 backlight_device_unregister(bldev);
592err2:
593 cancel_delayed_work_sync(&td->esd_work);
594 destroy_workqueue(td->esd_wq);
595err1:
596 kfree(td);
597err0:
598 return r;
599}
600
601static void taal_remove(struct omap_dss_device *dssdev)
602{
603 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
604 struct backlight_device *bldev;
605
606 dev_dbg(&dssdev->dev, "remove\n");
607
608 sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group);
609
610 if (td->use_ext_te) {
611 int gpio = dssdev->phy.dsi.ext_te_gpio;
612 free_irq(gpio_to_irq(gpio), dssdev);
613 gpio_free(gpio);
614 }
615
616 bldev = td->bldev;
617 bldev->props.power = FB_BLANK_POWERDOWN;
618 taal_bl_update_status(bldev);
619 backlight_device_unregister(bldev);
620
621 cancel_delayed_work_sync(&td->esd_work);
622 destroy_workqueue(td->esd_wq);
623
624 kfree(td);
625}
626
627static int taal_power_on(struct omap_dss_device *dssdev)
628{
629 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
630 u8 id1, id2, id3;
631 int r;
632
633 if (dssdev->platform_enable) {
634 r = dssdev->platform_enable(dssdev);
635 if (r)
636 return r;
637 }
638
639 /* it seems we have to wait a bit until taal is ready */
640 msleep(5);
641
642 dsi_bus_lock();
643
644 r = omapdss_dsi_display_enable(dssdev);
645 if (r) {
646 dev_err(&dssdev->dev, "failed to enable DSI\n");
647 goto err0;
648 }
649
650 omapdss_dsi_vc_enable_hs(TCH, false);
651
652 r = taal_sleep_out(td);
653 if (r)
654 goto err;
655
656 r = taal_get_id(&id1, &id2, &id3);
657 if (r)
658 goto err;
659
660 /* on early revisions CABC is broken */
661 if (id2 == 0x00 || id2 == 0xff || id2 == 0x81)
662 td->cabc_broken = true;
663
664 taal_dcs_write_1(DCS_BRIGHTNESS, 0xff);
665 taal_dcs_write_1(DCS_CTRL_DISPLAY, (1<<2) | (1<<5)); /* BL | BCTRL */
666
667 taal_dcs_write_1(DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */
668
669 taal_set_addr_mode(td->rotate, td->mirror);
670 if (!td->cabc_broken)
671 taal_dcs_write_1(DCS_WRITE_CABC, td->cabc_mode);
672
673 taal_dcs_write_0(DCS_DISPLAY_ON);
674
675 r = _taal_enable_te(dssdev, td->te_enabled);
676 if (r)
677 goto err;
678
679#ifdef TAAL_USE_ESD_CHECK
680 queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD);
681#endif
682
683 td->enabled = 1;
684
685 if (!td->intro_printed) {
686 dev_info(&dssdev->dev, "revision %02x.%02x.%02x\n",
687 id1, id2, id3);
688 if (td->cabc_broken)
689 dev_info(&dssdev->dev,
690 "old Taal version, CABC disabled\n");
691 td->intro_printed = true;
692 }
693
694 omapdss_dsi_vc_enable_hs(TCH, true);
695
696 dsi_bus_unlock();
697
698 return 0;
699err:
700 dsi_bus_unlock();
701
702 omapdss_dsi_display_disable(dssdev);
703err0:
704 if (dssdev->platform_disable)
705 dssdev->platform_disable(dssdev);
706
707 return r;
708}
709
710static void taal_power_off(struct omap_dss_device *dssdev)
711{
712 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
713
714 dsi_bus_lock();
715
716 cancel_delayed_work(&td->esd_work);
717
718 taal_dcs_write_0(DCS_DISPLAY_OFF);
719 taal_sleep_in(td);
720
721 /* wait a bit so that the message goes through */
722 msleep(10);
723
724 omapdss_dsi_display_disable(dssdev);
725
726 if (dssdev->platform_disable)
727 dssdev->platform_disable(dssdev);
728
729 td->enabled = 0;
730
731 dsi_bus_unlock();
732}
733
734static int taal_enable(struct omap_dss_device *dssdev)
735{
736 int r;
737 dev_dbg(&dssdev->dev, "enable\n");
738
739 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)
740 return -EINVAL;
741
742 r = taal_power_on(dssdev);
743 if (r)
744 return r;
745
746 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
747
748 return r;
749}
750
751static void taal_disable(struct omap_dss_device *dssdev)
752{
753 dev_dbg(&dssdev->dev, "disable\n");
754
755 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
756 taal_power_off(dssdev);
757
758 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
759}
760
761static int taal_suspend(struct omap_dss_device *dssdev)
762{
763 dev_dbg(&dssdev->dev, "suspend\n");
764
765 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
766 return -EINVAL;
767
768 taal_power_off(dssdev);
769 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
770
771 return 0;
772}
773
774static int taal_resume(struct omap_dss_device *dssdev)
775{
776 int r;
777 dev_dbg(&dssdev->dev, "resume\n");
778
779 if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED)
780 return -EINVAL;
781
782 r = taal_power_on(dssdev);
783 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
784 return r;
785}
786
787static void taal_framedone_cb(int err, void *data)
788{
789 struct omap_dss_device *dssdev = data;
790 dev_dbg(&dssdev->dev, "framedone, err %d\n", err);
791 dsi_bus_unlock();
792}
793
794static int taal_update(struct omap_dss_device *dssdev,
795 u16 x, u16 y, u16 w, u16 h)
796{
797 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
798 int r;
799
800 dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h);
801
802 dsi_bus_lock();
803
804 if (!td->enabled) {
805 r = 0;
806 goto err;
807 }
808
809 r = omap_dsi_prepare_update(dssdev, &x, &y, &w, &h);
810 if (r)
811 goto err;
812
813 r = taal_set_update_window(x, y, w, h);
814 if (r)
815 goto err;
816
817 r = omap_dsi_update(dssdev, TCH, x, y, w, h,
818 taal_framedone_cb, dssdev);
819 if (r)
820 goto err;
821
822 /* note: no bus_unlock here. unlock is in framedone_cb */
823 return 0;
824err:
825 dsi_bus_unlock();
826 return r;
827}
828
829static int taal_sync(struct omap_dss_device *dssdev)
830{
831 dev_dbg(&dssdev->dev, "sync\n");
832
833 dsi_bus_lock();
834 dsi_bus_unlock();
835
836 dev_dbg(&dssdev->dev, "sync done\n");
837
838 return 0;
839}
840
841static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
842{
843 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
844 int r;
845
846 td->te_enabled = enable;
847
848 if (enable)
849 r = taal_dcs_write_1(DCS_TEAR_ON, 0);
850 else
851 r = taal_dcs_write_0(DCS_TEAR_OFF);
852
853 omapdss_dsi_enable_te(dssdev, enable);
854
855 /* XXX for some reason, DSI TE breaks if we don't wait here.
856 * Panel bug? Needs more studying */
857 msleep(100);
858
859 return r;
860}
861
862static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
863{
864 int r;
865
866 dsi_bus_lock();
867
868 r = _taal_enable_te(dssdev, enable);
869
870 dsi_bus_unlock();
871
872 return r;
873}
874
875static int taal_get_te(struct omap_dss_device *dssdev)
876{
877 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
878 return td->te_enabled;
879}
880
881static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
882{
883 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
884 int r;
885
886 dev_dbg(&dssdev->dev, "rotate %d\n", rotate);
887
888 dsi_bus_lock();
889
890 if (td->enabled) {
891 r = taal_set_addr_mode(rotate, td->mirror);
892 if (r)
893 goto err;
894 }
895
896 td->rotate = rotate;
897
898 dsi_bus_unlock();
899 return 0;
900err:
901 dsi_bus_unlock();
902 return r;
903}
904
905static u8 taal_get_rotate(struct omap_dss_device *dssdev)
906{
907 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
908 return td->rotate;
909}
910
911static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
912{
913 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
914 int r;
915
916 dev_dbg(&dssdev->dev, "mirror %d\n", enable);
917
918 dsi_bus_lock();
919 if (td->enabled) {
920 r = taal_set_addr_mode(td->rotate, enable);
921 if (r)
922 goto err;
923 }
924
925 td->mirror = enable;
926
927 dsi_bus_unlock();
928 return 0;
929err:
930 dsi_bus_unlock();
931 return r;
932}
933
934static bool taal_get_mirror(struct omap_dss_device *dssdev)
935{
936 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
937 return td->mirror;
938}
939
940static int taal_run_test(struct omap_dss_device *dssdev, int test_num)
941{
942 u8 id1, id2, id3;
943 int r;
944
945 dsi_bus_lock();
946
947 r = taal_dcs_read_1(DCS_GET_ID1, &id1);
948 if (r)
949 goto err;
950 r = taal_dcs_read_1(DCS_GET_ID2, &id2);
951 if (r)
952 goto err;
953 r = taal_dcs_read_1(DCS_GET_ID3, &id3);
954 if (r)
955 goto err;
956
957 dsi_bus_unlock();
958 return 0;
959err:
960 dsi_bus_unlock();
961 return r;
962}
963
964static int taal_memory_read(struct omap_dss_device *dssdev,
965 void *buf, size_t size,
966 u16 x, u16 y, u16 w, u16 h)
967{
968 int r;
969 int first = 1;
970 int plen;
971 unsigned buf_used = 0;
972 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
973
974 if (!td->enabled)
975 return -ENODEV;
976
977 if (size < w * h * 3)
978 return -ENOMEM;
979
980 size = min(w * h * 3,
981 dssdev->panel.timings.x_res *
982 dssdev->panel.timings.y_res * 3);
983
984 dsi_bus_lock();
985
986 /* plen 1 or 2 goes into short packet. until checksum error is fixed,
987 * use short packets. plen 32 works, but bigger packets seem to cause
988 * an error. */
989 if (size % 2)
990 plen = 1;
991 else
992 plen = 2;
993
994 taal_set_update_window(x, y, w, h);
995
996 r = dsi_vc_set_max_rx_packet_size(TCH, plen);
997 if (r)
998 goto err0;
999
1000 while (buf_used < size) {
1001 u8 dcs_cmd = first ? 0x2e : 0x3e;
1002 first = 0;
1003
1004 r = dsi_vc_dcs_read(TCH, dcs_cmd,
1005 buf + buf_used, size - buf_used);
1006
1007 if (r < 0) {
1008 dev_err(&dssdev->dev, "read error\n");
1009 goto err;
1010 }
1011
1012 buf_used += r;
1013
1014 if (r < plen) {
1015 dev_err(&dssdev->dev, "short read\n");
1016 break;
1017 }
1018
1019 if (signal_pending(current)) {
1020 dev_err(&dssdev->dev, "signal pending, "
1021 "aborting memory read\n");
1022 r = -ERESTARTSYS;
1023 goto err;
1024 }
1025 }
1026
1027 r = buf_used;
1028
1029err:
1030 dsi_vc_set_max_rx_packet_size(TCH, 1);
1031err0:
1032 dsi_bus_unlock();
1033 return r;
1034}
1035
1036static void taal_esd_work(struct work_struct *work)
1037{
1038 struct taal_data *td = container_of(work, struct taal_data,
1039 esd_work.work);
1040 struct omap_dss_device *dssdev = td->dssdev;
1041 u8 state1, state2;
1042 int r;
1043
1044 if (!td->enabled)
1045 return;
1046
1047 dsi_bus_lock();
1048
1049 r = taal_dcs_read_1(DCS_RDDSDR, &state1);
1050 if (r) {
1051 dev_err(&dssdev->dev, "failed to read Taal status\n");
1052 goto err;
1053 }
1054
1055 /* Run self diagnostics */
1056 r = taal_sleep_out(td);
1057 if (r) {
1058 dev_err(&dssdev->dev, "failed to run Taal self-diagnostics\n");
1059 goto err;
1060 }
1061
1062 r = taal_dcs_read_1(DCS_RDDSDR, &state2);
1063 if (r) {
1064 dev_err(&dssdev->dev, "failed to read Taal status\n");
1065 goto err;
1066 }
1067
1068 /* Each sleep out command will trigger a self diagnostic and flip
1069 * Bit6 if the test passes.
1070 */
1071 if (!((state1 ^ state2) & (1 << 6))) {
1072 dev_err(&dssdev->dev, "LCD self diagnostics failed\n");
1073 goto err;
1074 }
1075 /* Self-diagnostics result is also shown on TE GPIO line. We need
1076 * to re-enable TE after self diagnostics */
1077 if (td->use_ext_te && td->te_enabled) {
1078 r = taal_dcs_write_1(DCS_TEAR_ON, 0);
1079 if (r)
1080 goto err;
1081 }
1082
1083 dsi_bus_unlock();
1084
1085 queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD);
1086
1087 return;
1088err:
1089 dev_err(&dssdev->dev, "performing LCD reset\n");
1090
1091 taal_disable(dssdev);
1092 taal_enable(dssdev);
1093
1094 dsi_bus_unlock();
1095
1096 queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD);
1097}
1098
1099static int taal_set_update_mode(struct omap_dss_device *dssdev,
1100 enum omap_dss_update_mode mode)
1101{
1102 if (mode != OMAP_DSS_UPDATE_MANUAL)
1103 return -EINVAL;
1104 return 0;
1105}
1106
1107static enum omap_dss_update_mode taal_get_update_mode(
1108 struct omap_dss_device *dssdev)
1109{
1110 return OMAP_DSS_UPDATE_MANUAL;
1111}
1112
1113static struct omap_dss_driver taal_driver = {
1114 .probe = taal_probe,
1115 .remove = taal_remove,
1116
1117 .enable = taal_enable,
1118 .disable = taal_disable,
1119 .suspend = taal_suspend,
1120 .resume = taal_resume,
1121
1122 .set_update_mode = taal_set_update_mode,
1123 .get_update_mode = taal_get_update_mode,
1124
1125 .update = taal_update,
1126 .sync = taal_sync,
1127
1128 .get_resolution = taal_get_resolution,
1129 .get_recommended_bpp = omapdss_default_get_recommended_bpp,
1130
1131 .enable_te = taal_enable_te,
1132 .get_te = taal_get_te,
1133
1134 .set_rotate = taal_rotate,
1135 .get_rotate = taal_get_rotate,
1136 .set_mirror = taal_mirror,
1137 .get_mirror = taal_get_mirror,
1138 .run_test = taal_run_test,
1139 .memory_read = taal_memory_read,
1140
1141 .get_timings = taal_get_timings,
1142
1143 .driver = {
1144 .name = "taal",
1145 .owner = THIS_MODULE,
1146 },
1147};
1148
1149static int __init taal_init(void)
1150{
1151 omap_dss_register_driver(&taal_driver);
1152
1153 return 0;
1154}
1155
1156static void __exit taal_exit(void)
1157{
1158 omap_dss_unregister_driver(&taal_driver);
1159}
1160
1161module_init(taal_init);
1162module_exit(taal_exit);
1163
1164MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
1165MODULE_DESCRIPTION("Taal Driver");
1166MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-toppoly-tdo35s.c b/drivers/video/omap2/displays/panel-toppoly-tdo35s.c
new file mode 100644
index 000000000000..fa434ca6e4b7
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-toppoly-tdo35s.c
@@ -0,0 +1,154 @@
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 | OMAP_DSS_LCD_IVS |
77 OMAP_DSS_LCD_IHS;
78 dssdev->panel.timings = toppoly_tdo_panel_timings;
79
80 return 0;
81}
82
83static void toppoly_tdo_panel_remove(struct omap_dss_device *dssdev)
84{
85}
86
87static int toppoly_tdo_panel_enable(struct omap_dss_device *dssdev)
88{
89 int r = 0;
90
91 r = toppoly_tdo_panel_power_on(dssdev);
92 if (r)
93 return r;
94
95 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
96
97 return 0;
98}
99
100static void toppoly_tdo_panel_disable(struct omap_dss_device *dssdev)
101{
102 toppoly_tdo_panel_power_off(dssdev);
103
104 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
105}
106
107static int toppoly_tdo_panel_suspend(struct omap_dss_device *dssdev)
108{
109 toppoly_tdo_panel_power_off(dssdev);
110 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
111 return 0;
112}
113
114static int toppoly_tdo_panel_resume(struct omap_dss_device *dssdev)
115{
116 int r = 0;
117
118 r = toppoly_tdo_panel_power_on(dssdev);
119 if (r)
120 return r;
121
122 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
123
124 return 0;
125}
126
127static struct omap_dss_driver generic_driver = {
128 .probe = toppoly_tdo_panel_probe,
129 .remove = toppoly_tdo_panel_remove,
130
131 .enable = toppoly_tdo_panel_enable,
132 .disable = toppoly_tdo_panel_disable,
133 .suspend = toppoly_tdo_panel_suspend,
134 .resume = toppoly_tdo_panel_resume,
135
136 .driver = {
137 .name = "toppoly_tdo35s_panel",
138 .owner = THIS_MODULE,
139 },
140};
141
142static int __init toppoly_tdo_panel_drv_init(void)
143{
144 return omap_dss_register_driver(&generic_driver);
145}
146
147static void __exit toppoly_tdo_panel_drv_exit(void)
148{
149 omap_dss_unregister_driver(&generic_driver);
150}
151
152module_init(toppoly_tdo_panel_drv_init);
153module_exit(toppoly_tdo_panel_drv_exit);
154MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
new file mode 100644
index 000000000000..e866e76b13d0
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
@@ -0,0 +1,529 @@
1/*
2 * LCD panel driver for TPO TD043MTEA1
3 *
4 * Author: Gražvydas Ignotas <notasas@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <linux/module.h>
13#include <linux/delay.h>
14#include <linux/spi/spi.h>
15#include <linux/regulator/consumer.h>
16#include <linux/gpio.h>
17#include <linux/err.h>
18#include <linux/slab.h>
19
20#include <plat/display.h>
21
22#define TPO_R02_MODE(x) ((x) & 7)
23#define TPO_R02_MODE_800x480 7
24#define TPO_R02_NCLK_RISING BIT(3)
25#define TPO_R02_HSYNC_HIGH BIT(4)
26#define TPO_R02_VSYNC_HIGH BIT(5)
27
28#define TPO_R03_NSTANDBY BIT(0)
29#define TPO_R03_EN_CP_CLK BIT(1)
30#define TPO_R03_EN_VGL_PUMP BIT(2)
31#define TPO_R03_EN_PWM BIT(3)
32#define TPO_R03_DRIVING_CAP_100 BIT(4)
33#define TPO_R03_EN_PRE_CHARGE BIT(6)
34#define TPO_R03_SOFTWARE_CTL BIT(7)
35
36#define TPO_R04_NFLIP_H BIT(0)
37#define TPO_R04_NFLIP_V BIT(1)
38#define TPO_R04_CP_CLK_FREQ_1H BIT(2)
39#define TPO_R04_VGL_FREQ_1H BIT(4)
40
41#define TPO_R03_VAL_NORMAL (TPO_R03_NSTANDBY | TPO_R03_EN_CP_CLK | \
42 TPO_R03_EN_VGL_PUMP | TPO_R03_EN_PWM | \
43 TPO_R03_DRIVING_CAP_100 | TPO_R03_EN_PRE_CHARGE | \
44 TPO_R03_SOFTWARE_CTL)
45
46#define TPO_R03_VAL_STANDBY (TPO_R03_DRIVING_CAP_100 | \
47 TPO_R03_EN_PRE_CHARGE | TPO_R03_SOFTWARE_CTL)
48
49static const u16 tpo_td043_def_gamma[12] = {
50 106, 200, 289, 375, 460, 543, 625, 705, 785, 864, 942, 1020
51};
52
53struct tpo_td043_device {
54 struct spi_device *spi;
55 struct regulator *vcc_reg;
56 u16 gamma[12];
57 u32 mode;
58 u32 hmirror:1;
59 u32 vmirror:1;
60};
61
62static int tpo_td043_write(struct spi_device *spi, u8 addr, u8 data)
63{
64 struct spi_message m;
65 struct spi_transfer xfer;
66 u16 w;
67 int r;
68
69 spi_message_init(&m);
70
71 memset(&xfer, 0, sizeof(xfer));
72
73 w = ((u16)addr << 10) | (1 << 8) | data;
74 xfer.tx_buf = &w;
75 xfer.bits_per_word = 16;
76 xfer.len = 2;
77 spi_message_add_tail(&xfer, &m);
78
79 r = spi_sync(spi, &m);
80 if (r < 0)
81 dev_warn(&spi->dev, "failed to write to LCD reg (%d)\n", r);
82 return r;
83}
84
85static void tpo_td043_write_gamma(struct spi_device *spi, u16 gamma[12])
86{
87 u8 i, val;
88
89 /* gamma bits [9:8] */
90 for (val = i = 0; i < 4; i++)
91 val |= (gamma[i] & 0x300) >> ((i + 1) * 2);
92 tpo_td043_write(spi, 0x11, val);
93
94 for (val = i = 0; i < 4; i++)
95 val |= (gamma[i+4] & 0x300) >> ((i + 1) * 2);
96 tpo_td043_write(spi, 0x12, val);
97
98 for (val = i = 0; i < 4; i++)
99 val |= (gamma[i+8] & 0x300) >> ((i + 1) * 2);
100 tpo_td043_write(spi, 0x13, val);
101
102 /* gamma bits [7:0] */
103 for (val = i = 0; i < 12; i++)
104 tpo_td043_write(spi, 0x14 + i, gamma[i] & 0xff);
105}
106
107static int tpo_td043_write_mirror(struct spi_device *spi, bool h, bool v)
108{
109 u8 reg4 = TPO_R04_NFLIP_H | TPO_R04_NFLIP_V | \
110 TPO_R04_CP_CLK_FREQ_1H | TPO_R04_VGL_FREQ_1H;
111 if (h)
112 reg4 &= ~TPO_R04_NFLIP_H;
113 if (v)
114 reg4 &= ~TPO_R04_NFLIP_V;
115
116 return tpo_td043_write(spi, 4, reg4);
117}
118
119static int tpo_td043_set_hmirror(struct omap_dss_device *dssdev, bool enable)
120{
121 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
122
123 tpo_td043->hmirror = enable;
124 return tpo_td043_write_mirror(tpo_td043->spi, tpo_td043->hmirror,
125 tpo_td043->vmirror);
126}
127
128static bool tpo_td043_get_hmirror(struct omap_dss_device *dssdev)
129{
130 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
131
132 return tpo_td043->hmirror;
133}
134
135static ssize_t tpo_td043_vmirror_show(struct device *dev,
136 struct device_attribute *attr, char *buf)
137{
138 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
139
140 return snprintf(buf, PAGE_SIZE, "%d\n", tpo_td043->vmirror);
141}
142
143static ssize_t tpo_td043_vmirror_store(struct device *dev,
144 struct device_attribute *attr, const char *buf, size_t count)
145{
146 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
147 long val;
148 int ret;
149
150 ret = strict_strtol(buf, 0, &val);
151 if (ret < 0)
152 return ret;
153
154 ret = tpo_td043_write_mirror(tpo_td043->spi, tpo_td043->hmirror, val);
155 if (ret < 0)
156 return ret;
157
158 tpo_td043->vmirror = val;
159
160 return count;
161}
162
163static ssize_t tpo_td043_mode_show(struct device *dev,
164 struct device_attribute *attr, char *buf)
165{
166 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
167
168 return snprintf(buf, PAGE_SIZE, "%d\n", tpo_td043->mode);
169}
170
171static ssize_t tpo_td043_mode_store(struct device *dev,
172 struct device_attribute *attr, const char *buf, size_t count)
173{
174 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
175 long val;
176 int ret;
177
178 ret = strict_strtol(buf, 0, &val);
179 if (ret != 0 || val & ~7)
180 return -EINVAL;
181
182 tpo_td043->mode = val;
183
184 val |= TPO_R02_NCLK_RISING;
185 tpo_td043_write(tpo_td043->spi, 2, val);
186
187 return count;
188}
189
190static ssize_t tpo_td043_gamma_show(struct device *dev,
191 struct device_attribute *attr, char *buf)
192{
193 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
194 ssize_t len = 0;
195 int ret;
196 int i;
197
198 for (i = 0; i < ARRAY_SIZE(tpo_td043->gamma); i++) {
199 ret = snprintf(buf + len, PAGE_SIZE - len, "%u ",
200 tpo_td043->gamma[i]);
201 if (ret < 0)
202 return ret;
203 len += ret;
204 }
205 buf[len - 1] = '\n';
206
207 return len;
208}
209
210static ssize_t tpo_td043_gamma_store(struct device *dev,
211 struct device_attribute *attr, const char *buf, size_t count)
212{
213 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
214 unsigned int g[12];
215 int ret;
216 int i;
217
218 ret = sscanf(buf, "%u %u %u %u %u %u %u %u %u %u %u %u",
219 &g[0], &g[1], &g[2], &g[3], &g[4], &g[5],
220 &g[6], &g[7], &g[8], &g[9], &g[10], &g[11]);
221
222 if (ret != 12)
223 return -EINVAL;
224
225 for (i = 0; i < 12; i++)
226 tpo_td043->gamma[i] = g[i];
227
228 tpo_td043_write_gamma(tpo_td043->spi, tpo_td043->gamma);
229
230 return count;
231}
232
233static DEVICE_ATTR(vmirror, S_IRUGO | S_IWUSR,
234 tpo_td043_vmirror_show, tpo_td043_vmirror_store);
235static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
236 tpo_td043_mode_show, tpo_td043_mode_store);
237static DEVICE_ATTR(gamma, S_IRUGO | S_IWUSR,
238 tpo_td043_gamma_show, tpo_td043_gamma_store);
239
240static struct attribute *tpo_td043_attrs[] = {
241 &dev_attr_vmirror.attr,
242 &dev_attr_mode.attr,
243 &dev_attr_gamma.attr,
244 NULL,
245};
246
247static struct attribute_group tpo_td043_attr_group = {
248 .attrs = tpo_td043_attrs,
249};
250
251static const struct omap_video_timings tpo_td043_timings = {
252 .x_res = 800,
253 .y_res = 480,
254
255 .pixel_clock = 36000,
256
257 .hsw = 1,
258 .hfp = 68,
259 .hbp = 214,
260
261 .vsw = 1,
262 .vfp = 39,
263 .vbp = 34,
264};
265
266static int tpo_td043_power_on(struct omap_dss_device *dssdev)
267{
268 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
269 int nreset_gpio = dssdev->reset_gpio;
270 int r;
271
272 r = omapdss_dpi_display_enable(dssdev);
273 if (r)
274 goto err0;
275
276 if (dssdev->platform_enable) {
277 r = dssdev->platform_enable(dssdev);
278 if (r)
279 goto err1;
280 }
281
282 regulator_enable(tpo_td043->vcc_reg);
283
284 /* wait for power up */
285 msleep(160);
286
287 if (gpio_is_valid(nreset_gpio))
288 gpio_set_value(nreset_gpio, 1);
289
290 tpo_td043_write(tpo_td043->spi, 2,
291 TPO_R02_MODE(tpo_td043->mode) | TPO_R02_NCLK_RISING);
292 tpo_td043_write(tpo_td043->spi, 3, TPO_R03_VAL_NORMAL);
293 tpo_td043_write(tpo_td043->spi, 0x20, 0xf0);
294 tpo_td043_write(tpo_td043->spi, 0x21, 0xf0);
295 tpo_td043_write_mirror(tpo_td043->spi, tpo_td043->hmirror,
296 tpo_td043->vmirror);
297 tpo_td043_write_gamma(tpo_td043->spi, tpo_td043->gamma);
298
299 return 0;
300err1:
301 omapdss_dpi_display_disable(dssdev);
302err0:
303 return r;
304}
305
306static void tpo_td043_power_off(struct omap_dss_device *dssdev)
307{
308 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
309 int nreset_gpio = dssdev->reset_gpio;
310
311 tpo_td043_write(tpo_td043->spi, 3,
312 TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM);
313
314 if (gpio_is_valid(nreset_gpio))
315 gpio_set_value(nreset_gpio, 0);
316
317 /* wait for at least 2 vsyncs before cutting off power */
318 msleep(50);
319
320 tpo_td043_write(tpo_td043->spi, 3, TPO_R03_VAL_STANDBY);
321
322 regulator_disable(tpo_td043->vcc_reg);
323
324 if (dssdev->platform_disable)
325 dssdev->platform_disable(dssdev);
326
327 omapdss_dpi_display_disable(dssdev);
328}
329
330static int tpo_td043_enable(struct omap_dss_device *dssdev)
331{
332 int ret;
333
334 dev_dbg(&dssdev->dev, "enable\n");
335
336 ret = tpo_td043_power_on(dssdev);
337 if (ret)
338 return ret;
339
340 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
341
342 return 0;
343}
344
345static void tpo_td043_disable(struct omap_dss_device *dssdev)
346{
347 dev_dbg(&dssdev->dev, "disable\n");
348
349 tpo_td043_power_off(dssdev);
350
351 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
352}
353
354static int tpo_td043_suspend(struct omap_dss_device *dssdev)
355{
356 tpo_td043_power_off(dssdev);
357 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
358 return 0;
359}
360
361static int tpo_td043_resume(struct omap_dss_device *dssdev)
362{
363 int r = 0;
364
365 r = tpo_td043_power_on(dssdev);
366 if (r)
367 return r;
368
369 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
370
371 return 0;
372}
373
374static int tpo_td043_probe(struct omap_dss_device *dssdev)
375{
376 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
377 int nreset_gpio = dssdev->reset_gpio;
378 int ret = 0;
379
380 dev_dbg(&dssdev->dev, "probe\n");
381
382 if (tpo_td043 == NULL) {
383 dev_err(&dssdev->dev, "missing tpo_td043_device\n");
384 return -ENODEV;
385 }
386
387 dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IHS |
388 OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IPC;
389 dssdev->panel.timings = tpo_td043_timings;
390 dssdev->ctrl.pixel_size = 24;
391
392 tpo_td043->mode = TPO_R02_MODE_800x480;
393 memcpy(tpo_td043->gamma, tpo_td043_def_gamma, sizeof(tpo_td043->gamma));
394
395 tpo_td043->vcc_reg = regulator_get(&dssdev->dev, "vcc");
396 if (IS_ERR(tpo_td043->vcc_reg)) {
397 dev_err(&dssdev->dev, "failed to get LCD VCC regulator\n");
398 ret = PTR_ERR(tpo_td043->vcc_reg);
399 goto fail_regulator;
400 }
401
402 if (gpio_is_valid(nreset_gpio)) {
403 ret = gpio_request(nreset_gpio, "lcd reset");
404 if (ret < 0) {
405 dev_err(&dssdev->dev, "couldn't request reset GPIO\n");
406 goto fail_gpio_req;
407 }
408
409 ret = gpio_direction_output(nreset_gpio, 0);
410 if (ret < 0) {
411 dev_err(&dssdev->dev, "couldn't set GPIO direction\n");
412 goto fail_gpio_direction;
413 }
414 }
415
416 ret = sysfs_create_group(&dssdev->dev.kobj, &tpo_td043_attr_group);
417 if (ret)
418 dev_warn(&dssdev->dev, "failed to create sysfs files\n");
419
420 return 0;
421
422fail_gpio_direction:
423 gpio_free(nreset_gpio);
424fail_gpio_req:
425 regulator_put(tpo_td043->vcc_reg);
426fail_regulator:
427 kfree(tpo_td043);
428 return ret;
429}
430
431static void tpo_td043_remove(struct omap_dss_device *dssdev)
432{
433 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
434 int nreset_gpio = dssdev->reset_gpio;
435
436 dev_dbg(&dssdev->dev, "remove\n");
437
438 sysfs_remove_group(&dssdev->dev.kobj, &tpo_td043_attr_group);
439 regulator_put(tpo_td043->vcc_reg);
440 if (gpio_is_valid(nreset_gpio))
441 gpio_free(nreset_gpio);
442}
443
444static struct omap_dss_driver tpo_td043_driver = {
445 .probe = tpo_td043_probe,
446 .remove = tpo_td043_remove,
447
448 .enable = tpo_td043_enable,
449 .disable = tpo_td043_disable,
450 .suspend = tpo_td043_suspend,
451 .resume = tpo_td043_resume,
452 .set_mirror = tpo_td043_set_hmirror,
453 .get_mirror = tpo_td043_get_hmirror,
454
455 .driver = {
456 .name = "tpo_td043mtea1_panel",
457 .owner = THIS_MODULE,
458 },
459};
460
461static int tpo_td043_spi_probe(struct spi_device *spi)
462{
463 struct omap_dss_device *dssdev = spi->dev.platform_data;
464 struct tpo_td043_device *tpo_td043;
465 int ret;
466
467 if (dssdev == NULL) {
468 dev_err(&spi->dev, "missing dssdev\n");
469 return -ENODEV;
470 }
471
472 spi->bits_per_word = 16;
473 spi->mode = SPI_MODE_0;
474
475 ret = spi_setup(spi);
476 if (ret < 0) {
477 dev_err(&spi->dev, "spi_setup failed: %d\n", ret);
478 return ret;
479 }
480
481 tpo_td043 = kzalloc(sizeof(*tpo_td043), GFP_KERNEL);
482 if (tpo_td043 == NULL)
483 return -ENOMEM;
484
485 tpo_td043->spi = spi;
486 dev_set_drvdata(&spi->dev, tpo_td043);
487 dev_set_drvdata(&dssdev->dev, tpo_td043);
488
489 omap_dss_register_driver(&tpo_td043_driver);
490
491 return 0;
492}
493
494static int __devexit tpo_td043_spi_remove(struct spi_device *spi)
495{
496 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&spi->dev);
497
498 omap_dss_unregister_driver(&tpo_td043_driver);
499 kfree(tpo_td043);
500
501 return 0;
502}
503
504static struct spi_driver tpo_td043_spi_driver = {
505 .driver = {
506 .name = "tpo_td043mtea1_panel_spi",
507 .bus = &spi_bus_type,
508 .owner = THIS_MODULE,
509 },
510 .probe = tpo_td043_spi_probe,
511 .remove = __devexit_p(tpo_td043_spi_remove),
512};
513
514static int __init tpo_td043_init(void)
515{
516 return spi_register_driver(&tpo_td043_spi_driver);
517}
518
519static void __exit tpo_td043_exit(void)
520{
521 spi_unregister_driver(&tpo_td043_spi_driver);
522}
523
524module_init(tpo_td043_init);
525module_exit(tpo_td043_exit);
526
527MODULE_AUTHOR("Gražvydas Ignotas <notasas@gmail.com>");
528MODULE_DESCRIPTION("TPO TD043MTEA1 LCD Driver");
529MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
new file mode 100644
index 000000000000..87afb81b2c44
--- /dev/null
+++ b/drivers/video/omap2/dss/Kconfig
@@ -0,0 +1,114 @@
1menuconfig OMAP2_DSS
2 tristate "OMAP2/3 Display Subsystem support (EXPERIMENTAL)"
3 depends on ARCH_OMAP2 || ARCH_OMAP3
4 help
5 OMAP2/3 Display Subsystem support.
6
7if OMAP2_DSS
8
9config OMAP2_VRAM_SIZE
10 int "VRAM size (MB)"
11 range 0 32
12 default 0
13 help
14 The amount of SDRAM to reserve at boot time for video RAM use.
15 This VRAM will be used by omapfb and other drivers that need
16 large continuous RAM area for video use.
17
18 You can also set this with "vram=<bytes>" kernel argument, or
19 in the board file.
20
21config OMAP2_DSS_DEBUG_SUPPORT
22 bool "Debug support"
23 default y
24 help
25 This enables debug messages. You need to enable printing
26 with 'debug' module parameter.
27
28config OMAP2_DSS_COLLECT_IRQ_STATS
29 bool "Collect DSS IRQ statistics"
30 depends on OMAP2_DSS_DEBUG_SUPPORT
31 default n
32 help
33 Collect DSS IRQ statistics, printable via debugfs.
34
35 The statistics can be found from
36 <debugfs>/omapdss/dispc_irq for DISPC interrupts, and
37 <debugfs>/omapdss/dsi_irq for DSI interrupts.
38
39config OMAP2_DSS_RFBI
40 bool "RFBI support"
41 default n
42 help
43 MIPI DBI support (RFBI, Remote Framebuffer Interface, in Texas
44 Instrument's terminology).
45
46 DBI is a bus between the host processor and a peripheral,
47 such as a display or a framebuffer chip.
48
49 See http://www.mipi.org/ for DBI spesifications.
50
51config OMAP2_DSS_VENC
52 bool "VENC support"
53 default y
54 help
55 OMAP Video Encoder support for S-Video and composite TV-out.
56
57config OMAP2_DSS_SDI
58 bool "SDI support"
59 depends on ARCH_OMAP3
60 default n
61 help
62 SDI (Serial Display Interface) support.
63
64 SDI is a high speed one-way display serial bus between the host
65 processor and a display.
66
67config OMAP2_DSS_DSI
68 bool "DSI support"
69 depends on ARCH_OMAP3
70 default n
71 help
72 MIPI DSI (Display Serial Interface) support.
73
74 DSI is a high speed half-duplex serial interface between the host
75 processor and a peripheral, such as a display or a framebuffer chip.
76
77 See http://www.mipi.org/ for DSI spesifications.
78
79config OMAP2_DSS_USE_DSI_PLL
80 bool "Use DSI PLL for PCLK (EXPERIMENTAL)"
81 default n
82 depends on OMAP2_DSS_DSI
83 help
84 Use DSI PLL to generate pixel clock. Currently only for DPI output.
85 DSI PLL can be used to generate higher and more precise pixel clocks.
86
87config OMAP2_DSS_FAKE_VSYNC
88 bool "Fake VSYNC irq from manual update displays"
89 default n
90 help
91 If this is selected, DSI will generate a fake DISPC VSYNC interrupt
92 when DSI has sent a frame. This is only needed with DSI or RFBI
93 displays using manual mode, and you want VSYNC to, for example,
94 time animation.
95
96config OMAP2_DSS_MIN_FCK_PER_PCK
97 int "Minimum FCK/PCK ratio (for scaling)"
98 range 0 32
99 default 0
100 help
101 This can be used to adjust the minimum FCK/PCK ratio.
102
103 With this you can make sure that DISPC FCK is at least
104 n x PCK. Video plane scaling requires higher FCK than
105 normally.
106
107 If this is set to 0, there's no extra constraint on the
108 DISPC FCK. However, the FCK will at minimum be
109 2xPCK (if active matrix) or 3xPCK (if passive matrix).
110
111 Max FCK is 173MHz, so this doesn't work if your PCK
112 is very high.
113
114endif
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
new file mode 100644
index 000000000000..980c72c2db98
--- /dev/null
+++ b/drivers/video/omap2/dss/Makefile
@@ -0,0 +1,6 @@
1obj-$(CONFIG_OMAP2_DSS) += omapdss.o
2omapdss-y := core.o dss.o dispc.o dpi.o display.o manager.o overlay.o
3omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
4omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
5omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
6omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
new file mode 100644
index 000000000000..7ebe50b335ed
--- /dev/null
+++ b/drivers/video/omap2/dss/core.c
@@ -0,0 +1,976 @@
1/*
2 * linux/drivers/video/omap2/dss/core.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#define DSS_SUBSYS_NAME "CORE"
24
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/clk.h>
28#include <linux/err.h>
29#include <linux/platform_device.h>
30#include <linux/seq_file.h>
31#include <linux/debugfs.h>
32#include <linux/io.h>
33#include <linux/device.h>
34#include <linux/regulator/consumer.h>
35
36#include <plat/display.h>
37#include <plat/clock.h>
38
39#include "dss.h"
40
41static struct {
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
52 struct regulator *vdds_dsi_reg;
53 struct regulator *vdds_sdi_reg;
54 struct regulator *vdda_dac_reg;
55} core;
56
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;
63module_param_named(def_disp, def_disp_name, charp, 0);
64MODULE_PARM_DESC(def_disp_name, "default display name");
65
66#ifdef DEBUG
67unsigned int dss_debug;
68module_param_named(debug, dss_debug, bool, 0644);
69#endif
70
71/* CONTEXT */
72static int dss_get_ctx_id(void)
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
362/* REGULATORS */
363
364struct regulator *dss_get_vdds_dsi(void)
365{
366 struct regulator *reg;
367
368 if (core.vdds_dsi_reg != NULL)
369 return core.vdds_dsi_reg;
370
371 reg = regulator_get(&core.pdev->dev, "vdds_dsi");
372 if (!IS_ERR(reg))
373 core.vdds_dsi_reg = reg;
374
375 return reg;
376}
377
378struct regulator *dss_get_vdds_sdi(void)
379{
380 struct regulator *reg;
381
382 if (core.vdds_sdi_reg != NULL)
383 return core.vdds_sdi_reg;
384
385 reg = regulator_get(&core.pdev->dev, "vdds_sdi");
386 if (!IS_ERR(reg))
387 core.vdds_sdi_reg = reg;
388
389 return reg;
390}
391
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)
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)
419{
420 void (*func)(struct seq_file *) = s->private;
421 func(s);
422 return 0;
423}
424
425static int dss_debug_open(struct inode *inode, struct file *file)
426{
427 return single_open(file, dss_debug_show, inode->i_private);
428}
429
430static const struct file_operations dss_debug_fops = {
431 .open = dss_debug_open,
432 .read = seq_read,
433 .llseek = seq_lseek,
434 .release = single_release,
435};
436
437static struct dentry *dss_debugfs_dir;
438
439static int dss_initialize_debugfs(void)
440{
441 dss_debugfs_dir = debugfs_create_dir("omapdss", NULL);
442 if (IS_ERR(dss_debugfs_dir)) {
443 int err = PTR_ERR(dss_debugfs_dir);
444 dss_debugfs_dir = NULL;
445 return err;
446 }
447
448 debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir,
449 &dss_debug_dump_clocks, &dss_debug_fops);
450
451#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
452 debugfs_create_file("dispc_irq", S_IRUGO, dss_debugfs_dir,
453 &dispc_dump_irqs, &dss_debug_fops);
454#endif
455
456#if defined(CONFIG_OMAP2_DSS_DSI) && defined(CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS)
457 debugfs_create_file("dsi_irq", S_IRUGO, dss_debugfs_dir,
458 &dsi_dump_irqs, &dss_debug_fops);
459#endif
460
461 debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir,
462 &dss_dump_regs, &dss_debug_fops);
463 debugfs_create_file("dispc", S_IRUGO, dss_debugfs_dir,
464 &dispc_dump_regs, &dss_debug_fops);
465#ifdef CONFIG_OMAP2_DSS_RFBI
466 debugfs_create_file("rfbi", S_IRUGO, dss_debugfs_dir,
467 &rfbi_dump_regs, &dss_debug_fops);
468#endif
469#ifdef CONFIG_OMAP2_DSS_DSI
470 debugfs_create_file("dsi", S_IRUGO, dss_debugfs_dir,
471 &dsi_dump_regs, &dss_debug_fops);
472#endif
473#ifdef CONFIG_OMAP2_DSS_VENC
474 debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir,
475 &venc_dump_regs, &dss_debug_fops);
476#endif
477 return 0;
478}
479
480static void dss_uninitialize_debugfs(void)
481{
482 if (dss_debugfs_dir)
483 debugfs_remove_recursive(dss_debugfs_dir);
484}
485#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
486
487/* PLATFORM DEVICE */
488static int omap_dss_probe(struct platform_device *pdev)
489{
490 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
491 int skip_init = 0;
492 int r;
493 int i;
494
495 core.pdev = pdev;
496
497 dss_init_overlay_managers(pdev);
498 dss_init_overlays(pdev);
499
500 r = dss_get_clocks();
501 if (r)
502 goto fail0;
503
504 dss_clk_enable_all_no_ctx();
505
506 core.ctx_id = dss_get_ctx_id();
507 DSSDBG("initial ctx id %u\n", core.ctx_id);
508
509#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
510 /* DISPC_CONTROL */
511 if (omap_readl(0x48050440) & 1) /* LCD enabled? */
512 skip_init = 1;
513#endif
514
515 r = dss_init(skip_init);
516 if (r) {
517 DSSERR("Failed to initialize DSS\n");
518 goto fail0;
519 }
520
521#ifdef CONFIG_OMAP2_DSS_RFBI
522 r = rfbi_init();
523 if (r) {
524 DSSERR("Failed to initialize rfbi\n");
525 goto fail0;
526 }
527#endif
528
529 r = dpi_init(pdev);
530 if (r) {
531 DSSERR("Failed to initialize dpi\n");
532 goto fail0;
533 }
534
535 r = dispc_init();
536 if (r) {
537 DSSERR("Failed to initialize dispc\n");
538 goto fail0;
539 }
540#ifdef CONFIG_OMAP2_DSS_VENC
541 r = venc_init(pdev);
542 if (r) {
543 DSSERR("Failed to initialize venc\n");
544 goto fail0;
545 }
546#endif
547 if (cpu_is_omap34xx()) {
548#ifdef CONFIG_OMAP2_DSS_SDI
549 r = sdi_init(skip_init);
550 if (r) {
551 DSSERR("Failed to initialize SDI\n");
552 goto fail0;
553 }
554#endif
555#ifdef CONFIG_OMAP2_DSS_DSI
556 r = dsi_init(pdev);
557 if (r) {
558 DSSERR("Failed to initialize DSI\n");
559 goto fail0;
560 }
561#endif
562 }
563
564#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
565 r = dss_initialize_debugfs();
566 if (r)
567 goto fail0;
568#endif
569
570 for (i = 0; i < pdata->num_devices; ++i) {
571 struct omap_dss_device *dssdev = pdata->devices[i];
572
573 r = omap_dss_register_device(dssdev);
574 if (r)
575 DSSERR("device reg failed %d\n", i);
576
577 if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0)
578 pdata->default_device = dssdev;
579 }
580
581 dss_clk_disable_all();
582
583 return 0;
584
585 /* XXX fail correctly */
586fail0:
587 return r;
588}
589
590static int omap_dss_remove(struct platform_device *pdev)
591{
592 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
593 int i;
594 int c;
595
596#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
597 dss_uninitialize_debugfs();
598#endif
599
600#ifdef CONFIG_OMAP2_DSS_VENC
601 venc_exit();
602#endif
603 dispc_exit();
604 dpi_exit();
605#ifdef CONFIG_OMAP2_DSS_RFBI
606 rfbi_exit();
607#endif
608 if (cpu_is_omap34xx()) {
609#ifdef CONFIG_OMAP2_DSS_DSI
610 dsi_exit();
611#endif
612#ifdef CONFIG_OMAP2_DSS_SDI
613 sdi_exit();
614#endif
615 }
616
617 dss_exit();
618
619 /* these should be removed at some point */
620 c = core.dss_ick->usecount;
621 if (c > 0) {
622 DSSERR("warning: dss_ick usecount %d, disabling\n", c);
623 while (c-- > 0)
624 clk_disable(core.dss_ick);
625 }
626
627 c = core.dss1_fck->usecount;
628 if (c > 0) {
629 DSSERR("warning: dss1_fck usecount %d, disabling\n", c);
630 while (c-- > 0)
631 clk_disable(core.dss1_fck);
632 }
633
634 c = core.dss2_fck->usecount;
635 if (c > 0) {
636 DSSERR("warning: dss2_fck usecount %d, disabling\n", c);
637 while (c-- > 0)
638 clk_disable(core.dss2_fck);
639 }
640
641 c = core.dss_54m_fck->usecount;
642 if (c > 0) {
643 DSSERR("warning: dss_54m_fck usecount %d, disabling\n", c);
644 while (c-- > 0)
645 clk_disable(core.dss_54m_fck);
646 }
647
648 if (core.dss_96m_fck) {
649 c = core.dss_96m_fck->usecount;
650 if (c > 0) {
651 DSSERR("warning: dss_96m_fck usecount %d, disabling\n",
652 c);
653 while (c-- > 0)
654 clk_disable(core.dss_96m_fck);
655 }
656 }
657
658 dss_put_clocks();
659
660 dss_uninit_overlays(pdev);
661 dss_uninit_overlay_managers(pdev);
662
663 for (i = 0; i < pdata->num_devices; ++i)
664 omap_dss_unregister_device(pdata->devices[i]);
665
666 return 0;
667}
668
669static void omap_dss_shutdown(struct platform_device *pdev)
670{
671 DSSDBG("shutdown\n");
672 dss_disable_all_devices();
673}
674
675static int omap_dss_suspend(struct platform_device *pdev, pm_message_t state)
676{
677 DSSDBG("suspend %d\n", state.event);
678
679 return dss_suspend_all_devices();
680}
681
682static int omap_dss_resume(struct platform_device *pdev)
683{
684 DSSDBG("resume\n");
685
686 return dss_resume_all_devices();
687}
688
689static struct platform_driver omap_dss_driver = {
690 .probe = omap_dss_probe,
691 .remove = omap_dss_remove,
692 .shutdown = omap_dss_shutdown,
693 .suspend = omap_dss_suspend,
694 .resume = omap_dss_resume,
695 .driver = {
696 .name = "omapdss",
697 .owner = THIS_MODULE,
698 },
699};
700
701/* BUS */
702static int dss_bus_match(struct device *dev, struct device_driver *driver)
703{
704 struct omap_dss_device *dssdev = to_dss_device(dev);
705
706 DSSDBG("bus_match. dev %s/%s, drv %s\n",
707 dev_name(dev), dssdev->driver_name, driver->name);
708
709 return strcmp(dssdev->driver_name, driver->name) == 0;
710}
711
712static ssize_t device_name_show(struct device *dev,
713 struct device_attribute *attr, char *buf)
714{
715 struct omap_dss_device *dssdev = to_dss_device(dev);
716 return snprintf(buf, PAGE_SIZE, "%s\n",
717 dssdev->name ?
718 dssdev->name : "");
719}
720
721static struct device_attribute default_dev_attrs[] = {
722 __ATTR(name, S_IRUGO, device_name_show, NULL),
723 __ATTR_NULL,
724};
725
726static ssize_t driver_name_show(struct device_driver *drv, char *buf)
727{
728 struct omap_dss_driver *dssdrv = to_dss_driver(drv);
729 return snprintf(buf, PAGE_SIZE, "%s\n",
730 dssdrv->driver.name ?
731 dssdrv->driver.name : "");
732}
733static struct driver_attribute default_drv_attrs[] = {
734 __ATTR(name, S_IRUGO, driver_name_show, NULL),
735 __ATTR_NULL,
736};
737
738static struct bus_type dss_bus_type = {
739 .name = "omapdss",
740 .match = dss_bus_match,
741 .dev_attrs = default_dev_attrs,
742 .drv_attrs = default_drv_attrs,
743};
744
745static void dss_bus_release(struct device *dev)
746{
747 DSSDBG("bus_release\n");
748}
749
750static struct device dss_bus = {
751 .release = dss_bus_release,
752};
753
754struct bus_type *dss_get_bus(void)
755{
756 return &dss_bus_type;
757}
758
759/* DRIVER */
760static int dss_driver_probe(struct device *dev)
761{
762 int r;
763 struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
764 struct omap_dss_device *dssdev = to_dss_device(dev);
765 struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
766 bool force;
767
768 DSSDBG("driver_probe: dev %s/%s, drv %s\n",
769 dev_name(dev), dssdev->driver_name,
770 dssdrv->driver.name);
771
772 dss_init_device(core.pdev, dssdev);
773
774 force = pdata->default_device == dssdev;
775 dss_recheck_connections(dssdev, force);
776
777 r = dssdrv->probe(dssdev);
778
779 if (r) {
780 DSSERR("driver probe failed: %d\n", r);
781 dss_uninit_device(core.pdev, dssdev);
782 return r;
783 }
784
785 DSSDBG("probe done for device %s\n", dev_name(dev));
786
787 dssdev->driver = dssdrv;
788
789 return 0;
790}
791
792static int dss_driver_remove(struct device *dev)
793{
794 struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
795 struct omap_dss_device *dssdev = to_dss_device(dev);
796
797 DSSDBG("driver_remove: dev %s/%s\n", dev_name(dev),
798 dssdev->driver_name);
799
800 dssdrv->remove(dssdev);
801
802 dss_uninit_device(core.pdev, dssdev);
803
804 dssdev->driver = NULL;
805
806 return 0;
807}
808
809int omap_dss_register_driver(struct omap_dss_driver *dssdriver)
810{
811 dssdriver->driver.bus = &dss_bus_type;
812 dssdriver->driver.probe = dss_driver_probe;
813 dssdriver->driver.remove = dss_driver_remove;
814
815 if (dssdriver->get_resolution == NULL)
816 dssdriver->get_resolution = omapdss_default_get_resolution;
817 if (dssdriver->get_recommended_bpp == NULL)
818 dssdriver->get_recommended_bpp =
819 omapdss_default_get_recommended_bpp;
820
821 return driver_register(&dssdriver->driver);
822}
823EXPORT_SYMBOL(omap_dss_register_driver);
824
825void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver)
826{
827 driver_unregister(&dssdriver->driver);
828}
829EXPORT_SYMBOL(omap_dss_unregister_driver);
830
831/* DEVICE */
832static void reset_device(struct device *dev, int check)
833{
834 u8 *dev_p = (u8 *)dev;
835 u8 *dev_end = dev_p + sizeof(*dev);
836 void *saved_pdata;
837
838 saved_pdata = dev->platform_data;
839 if (check) {
840 /*
841 * Check if there is any other setting than platform_data
842 * in struct device; warn that these will be reset by our
843 * init.
844 */
845 dev->platform_data = NULL;
846 while (dev_p < dev_end) {
847 if (*dev_p) {
848 WARN("%s: struct device fields will be "
849 "discarded\n",
850 __func__);
851 break;
852 }
853 dev_p++;
854 }
855 }
856 memset(dev, 0, sizeof(*dev));
857 dev->platform_data = saved_pdata;
858}
859
860
861static void omap_dss_dev_release(struct device *dev)
862{
863 reset_device(dev, 0);
864}
865
866int omap_dss_register_device(struct omap_dss_device *dssdev)
867{
868 static int dev_num;
869
870 WARN_ON(!dssdev->driver_name);
871
872 reset_device(&dssdev->dev, 1);
873 dssdev->dev.bus = &dss_bus_type;
874 dssdev->dev.parent = &dss_bus;
875 dssdev->dev.release = omap_dss_dev_release;
876 dev_set_name(&dssdev->dev, "display%d", dev_num++);
877 return device_register(&dssdev->dev);
878}
879
880void omap_dss_unregister_device(struct omap_dss_device *dssdev)
881{
882 device_unregister(&dssdev->dev);
883}
884
885/* BUS */
886static int omap_dss_bus_register(void)
887{
888 int r;
889
890 r = bus_register(&dss_bus_type);
891 if (r) {
892 DSSERR("bus register failed\n");
893 return r;
894 }
895
896 dev_set_name(&dss_bus, "omapdss");
897 r = device_register(&dss_bus);
898 if (r) {
899 DSSERR("bus driver register failed\n");
900 bus_unregister(&dss_bus_type);
901 return r;
902 }
903
904 return 0;
905}
906
907/* INIT */
908
909#ifdef CONFIG_OMAP2_DSS_MODULE
910static void omap_dss_bus_unregister(void)
911{
912 device_unregister(&dss_bus);
913
914 bus_unregister(&dss_bus_type);
915}
916
917static int __init omap_dss_init(void)
918{
919 int r;
920
921 r = omap_dss_bus_register();
922 if (r)
923 return r;
924
925 r = platform_driver_register(&omap_dss_driver);
926 if (r) {
927 omap_dss_bus_unregister();
928 return r;
929 }
930
931 return 0;
932}
933
934static void __exit omap_dss_exit(void)
935{
936 if (core.vdds_dsi_reg != NULL) {
937 regulator_put(core.vdds_dsi_reg);
938 core.vdds_dsi_reg = NULL;
939 }
940
941 if (core.vdds_sdi_reg != NULL) {
942 regulator_put(core.vdds_sdi_reg);
943 core.vdds_sdi_reg = NULL;
944 }
945
946 if (core.vdda_dac_reg != NULL) {
947 regulator_put(core.vdda_dac_reg);
948 core.vdda_dac_reg = NULL;
949 }
950
951 platform_driver_unregister(&omap_dss_driver);
952
953 omap_dss_bus_unregister();
954}
955
956module_init(omap_dss_init);
957module_exit(omap_dss_exit);
958#else
959static int __init omap_dss_init(void)
960{
961 return omap_dss_bus_register();
962}
963
964static int __init omap_dss_init2(void)
965{
966 return platform_driver_register(&omap_dss_driver);
967}
968
969core_initcall(omap_dss_init);
970device_initcall(omap_dss_init2);
971#endif
972
973MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
974MODULE_DESCRIPTION("OMAP2/3 Display Subsystem");
975MODULE_LICENSE("GPL v2");
976
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
new file mode 100644
index 000000000000..e777e352dbcd
--- /dev/null
+++ b/drivers/video/omap2/dss/dispc.c
@@ -0,0 +1,3181 @@
1/*
2 * linux/drivers/video/omap2/dss/dispc.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#define DSS_SUBSYS_NAME "DISPC"
24
25#include <linux/kernel.h>
26#include <linux/dma-mapping.h>
27#include <linux/vmalloc.h>
28#include <linux/clk.h>
29#include <linux/io.h>
30#include <linux/jiffies.h>
31#include <linux/seq_file.h>
32#include <linux/delay.h>
33#include <linux/workqueue.h>
34
35#include <plat/sram.h>
36#include <plat/clock.h>
37
38#include <plat/display.h>
39
40#include "dss.h"
41
42/* DISPC */
43#define DISPC_BASE 0x48050400
44
45#define DISPC_SZ_REGS SZ_1K
46
47struct dispc_reg { u16 idx; };
48
49#define DISPC_REG(idx) ((const struct dispc_reg) { idx })
50
51/* DISPC common */
52#define DISPC_REVISION DISPC_REG(0x0000)
53#define DISPC_SYSCONFIG DISPC_REG(0x0010)
54#define DISPC_SYSSTATUS DISPC_REG(0x0014)
55#define DISPC_IRQSTATUS DISPC_REG(0x0018)
56#define DISPC_IRQENABLE DISPC_REG(0x001C)
57#define DISPC_CONTROL DISPC_REG(0x0040)
58#define DISPC_CONFIG DISPC_REG(0x0044)
59#define DISPC_CAPABLE DISPC_REG(0x0048)
60#define DISPC_DEFAULT_COLOR0 DISPC_REG(0x004C)
61#define DISPC_DEFAULT_COLOR1 DISPC_REG(0x0050)
62#define DISPC_TRANS_COLOR0 DISPC_REG(0x0054)
63#define DISPC_TRANS_COLOR1 DISPC_REG(0x0058)
64#define DISPC_LINE_STATUS DISPC_REG(0x005C)
65#define DISPC_LINE_NUMBER DISPC_REG(0x0060)
66#define DISPC_TIMING_H DISPC_REG(0x0064)
67#define DISPC_TIMING_V DISPC_REG(0x0068)
68#define DISPC_POL_FREQ DISPC_REG(0x006C)
69#define DISPC_DIVISOR DISPC_REG(0x0070)
70#define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074)
71#define DISPC_SIZE_DIG DISPC_REG(0x0078)
72#define DISPC_SIZE_LCD DISPC_REG(0x007C)
73
74/* DISPC GFX plane */
75#define DISPC_GFX_BA0 DISPC_REG(0x0080)
76#define DISPC_GFX_BA1 DISPC_REG(0x0084)
77#define DISPC_GFX_POSITION DISPC_REG(0x0088)
78#define DISPC_GFX_SIZE DISPC_REG(0x008C)
79#define DISPC_GFX_ATTRIBUTES DISPC_REG(0x00A0)
80#define DISPC_GFX_FIFO_THRESHOLD DISPC_REG(0x00A4)
81#define DISPC_GFX_FIFO_SIZE_STATUS DISPC_REG(0x00A8)
82#define DISPC_GFX_ROW_INC DISPC_REG(0x00AC)
83#define DISPC_GFX_PIXEL_INC DISPC_REG(0x00B0)
84#define DISPC_GFX_WINDOW_SKIP DISPC_REG(0x00B4)
85#define DISPC_GFX_TABLE_BA DISPC_REG(0x00B8)
86
87#define DISPC_DATA_CYCLE1 DISPC_REG(0x01D4)
88#define DISPC_DATA_CYCLE2 DISPC_REG(0x01D8)
89#define DISPC_DATA_CYCLE3 DISPC_REG(0x01DC)
90
91#define DISPC_CPR_COEF_R DISPC_REG(0x0220)
92#define DISPC_CPR_COEF_G DISPC_REG(0x0224)
93#define DISPC_CPR_COEF_B DISPC_REG(0x0228)
94
95#define DISPC_GFX_PRELOAD DISPC_REG(0x022C)
96
97/* DISPC Video plane, n = 0 for VID1 and n = 1 for VID2 */
98#define DISPC_VID_REG(n, idx) DISPC_REG(0x00BC + (n)*0x90 + idx)
99
100#define DISPC_VID_BA0(n) DISPC_VID_REG(n, 0x0000)
101#define DISPC_VID_BA1(n) DISPC_VID_REG(n, 0x0004)
102#define DISPC_VID_POSITION(n) DISPC_VID_REG(n, 0x0008)
103#define DISPC_VID_SIZE(n) DISPC_VID_REG(n, 0x000C)
104#define DISPC_VID_ATTRIBUTES(n) DISPC_VID_REG(n, 0x0010)
105#define DISPC_VID_FIFO_THRESHOLD(n) DISPC_VID_REG(n, 0x0014)
106#define DISPC_VID_FIFO_SIZE_STATUS(n) DISPC_VID_REG(n, 0x0018)
107#define DISPC_VID_ROW_INC(n) DISPC_VID_REG(n, 0x001C)
108#define DISPC_VID_PIXEL_INC(n) DISPC_VID_REG(n, 0x0020)
109#define DISPC_VID_FIR(n) DISPC_VID_REG(n, 0x0024)
110#define DISPC_VID_PICTURE_SIZE(n) DISPC_VID_REG(n, 0x0028)
111#define DISPC_VID_ACCU0(n) DISPC_VID_REG(n, 0x002C)
112#define DISPC_VID_ACCU1(n) DISPC_VID_REG(n, 0x0030)
113
114/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
115#define DISPC_VID_FIR_COEF_H(n, i) DISPC_REG(0x00F0 + (n)*0x90 + (i)*0x8)
116/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
117#define DISPC_VID_FIR_COEF_HV(n, i) DISPC_REG(0x00F4 + (n)*0x90 + (i)*0x8)
118/* coef index i = {0, 1, 2, 3, 4} */
119#define DISPC_VID_CONV_COEF(n, i) DISPC_REG(0x0130 + (n)*0x90 + (i)*0x4)
120/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
121#define DISPC_VID_FIR_COEF_V(n, i) DISPC_REG(0x01E0 + (n)*0x20 + (i)*0x4)
122
123#define DISPC_VID_PRELOAD(n) DISPC_REG(0x230 + (n)*0x04)
124
125
126#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
127 DISPC_IRQ_OCP_ERR | \
128 DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
129 DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
130 DISPC_IRQ_SYNC_LOST | \
131 DISPC_IRQ_SYNC_LOST_DIGIT)
132
133#define DISPC_MAX_NR_ISRS 8
134
135struct omap_dispc_isr_data {
136 omap_dispc_isr_t isr;
137 void *arg;
138 u32 mask;
139};
140
141#define REG_GET(idx, start, end) \
142 FLD_GET(dispc_read_reg(idx), start, end)
143
144#define REG_FLD_MOD(idx, val, start, end) \
145 dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
146
147static const struct dispc_reg dispc_reg_att[] = { DISPC_GFX_ATTRIBUTES,
148 DISPC_VID_ATTRIBUTES(0),
149 DISPC_VID_ATTRIBUTES(1) };
150
151struct dispc_irq_stats {
152 unsigned long last_reset;
153 unsigned irq_count;
154 unsigned irqs[32];
155};
156
157static struct {
158 void __iomem *base;
159
160 u32 fifo_size[3];
161
162 spinlock_t irq_lock;
163 u32 irq_error_mask;
164 struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
165 u32 error_irqs;
166 struct work_struct error_work;
167
168 u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
169
170#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
171 spinlock_t irq_stats_lock;
172 struct dispc_irq_stats irq_stats;
173#endif
174} dispc;
175
176static void _omap_dispc_set_irqs(void);
177
178static inline void dispc_write_reg(const struct dispc_reg idx, u32 val)
179{
180 __raw_writel(val, dispc.base + idx.idx);
181}
182
183static inline u32 dispc_read_reg(const struct dispc_reg idx)
184{
185 return __raw_readl(dispc.base + idx.idx);
186}
187
188#define SR(reg) \
189 dispc.ctx[(DISPC_##reg).idx / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
190#define RR(reg) \
191 dispc_write_reg(DISPC_##reg, dispc.ctx[(DISPC_##reg).idx / sizeof(u32)])
192
193void dispc_save_context(void)
194{
195 if (cpu_is_omap24xx())
196 return;
197
198 SR(SYSCONFIG);
199 SR(IRQENABLE);
200 SR(CONTROL);
201 SR(CONFIG);
202 SR(DEFAULT_COLOR0);
203 SR(DEFAULT_COLOR1);
204 SR(TRANS_COLOR0);
205 SR(TRANS_COLOR1);
206 SR(LINE_NUMBER);
207 SR(TIMING_H);
208 SR(TIMING_V);
209 SR(POL_FREQ);
210 SR(DIVISOR);
211 SR(GLOBAL_ALPHA);
212 SR(SIZE_DIG);
213 SR(SIZE_LCD);
214
215 SR(GFX_BA0);
216 SR(GFX_BA1);
217 SR(GFX_POSITION);
218 SR(GFX_SIZE);
219 SR(GFX_ATTRIBUTES);
220 SR(GFX_FIFO_THRESHOLD);
221 SR(GFX_ROW_INC);
222 SR(GFX_PIXEL_INC);
223 SR(GFX_WINDOW_SKIP);
224 SR(GFX_TABLE_BA);
225
226 SR(DATA_CYCLE1);
227 SR(DATA_CYCLE2);
228 SR(DATA_CYCLE3);
229
230 SR(CPR_COEF_R);
231 SR(CPR_COEF_G);
232 SR(CPR_COEF_B);
233
234 SR(GFX_PRELOAD);
235
236 /* VID1 */
237 SR(VID_BA0(0));
238 SR(VID_BA1(0));
239 SR(VID_POSITION(0));
240 SR(VID_SIZE(0));
241 SR(VID_ATTRIBUTES(0));
242 SR(VID_FIFO_THRESHOLD(0));
243 SR(VID_ROW_INC(0));
244 SR(VID_PIXEL_INC(0));
245 SR(VID_FIR(0));
246 SR(VID_PICTURE_SIZE(0));
247 SR(VID_ACCU0(0));
248 SR(VID_ACCU1(0));
249
250 SR(VID_FIR_COEF_H(0, 0));
251 SR(VID_FIR_COEF_H(0, 1));
252 SR(VID_FIR_COEF_H(0, 2));
253 SR(VID_FIR_COEF_H(0, 3));
254 SR(VID_FIR_COEF_H(0, 4));
255 SR(VID_FIR_COEF_H(0, 5));
256 SR(VID_FIR_COEF_H(0, 6));
257 SR(VID_FIR_COEF_H(0, 7));
258
259 SR(VID_FIR_COEF_HV(0, 0));
260 SR(VID_FIR_COEF_HV(0, 1));
261 SR(VID_FIR_COEF_HV(0, 2));
262 SR(VID_FIR_COEF_HV(0, 3));
263 SR(VID_FIR_COEF_HV(0, 4));
264 SR(VID_FIR_COEF_HV(0, 5));
265 SR(VID_FIR_COEF_HV(0, 6));
266 SR(VID_FIR_COEF_HV(0, 7));
267
268 SR(VID_CONV_COEF(0, 0));
269 SR(VID_CONV_COEF(0, 1));
270 SR(VID_CONV_COEF(0, 2));
271 SR(VID_CONV_COEF(0, 3));
272 SR(VID_CONV_COEF(0, 4));
273
274 SR(VID_FIR_COEF_V(0, 0));
275 SR(VID_FIR_COEF_V(0, 1));
276 SR(VID_FIR_COEF_V(0, 2));
277 SR(VID_FIR_COEF_V(0, 3));
278 SR(VID_FIR_COEF_V(0, 4));
279 SR(VID_FIR_COEF_V(0, 5));
280 SR(VID_FIR_COEF_V(0, 6));
281 SR(VID_FIR_COEF_V(0, 7));
282
283 SR(VID_PRELOAD(0));
284
285 /* VID2 */
286 SR(VID_BA0(1));
287 SR(VID_BA1(1));
288 SR(VID_POSITION(1));
289 SR(VID_SIZE(1));
290 SR(VID_ATTRIBUTES(1));
291 SR(VID_FIFO_THRESHOLD(1));
292 SR(VID_ROW_INC(1));
293 SR(VID_PIXEL_INC(1));
294 SR(VID_FIR(1));
295 SR(VID_PICTURE_SIZE(1));
296 SR(VID_ACCU0(1));
297 SR(VID_ACCU1(1));
298
299 SR(VID_FIR_COEF_H(1, 0));
300 SR(VID_FIR_COEF_H(1, 1));
301 SR(VID_FIR_COEF_H(1, 2));
302 SR(VID_FIR_COEF_H(1, 3));
303 SR(VID_FIR_COEF_H(1, 4));
304 SR(VID_FIR_COEF_H(1, 5));
305 SR(VID_FIR_COEF_H(1, 6));
306 SR(VID_FIR_COEF_H(1, 7));
307
308 SR(VID_FIR_COEF_HV(1, 0));
309 SR(VID_FIR_COEF_HV(1, 1));
310 SR(VID_FIR_COEF_HV(1, 2));
311 SR(VID_FIR_COEF_HV(1, 3));
312 SR(VID_FIR_COEF_HV(1, 4));
313 SR(VID_FIR_COEF_HV(1, 5));
314 SR(VID_FIR_COEF_HV(1, 6));
315 SR(VID_FIR_COEF_HV(1, 7));
316
317 SR(VID_CONV_COEF(1, 0));
318 SR(VID_CONV_COEF(1, 1));
319 SR(VID_CONV_COEF(1, 2));
320 SR(VID_CONV_COEF(1, 3));
321 SR(VID_CONV_COEF(1, 4));
322
323 SR(VID_FIR_COEF_V(1, 0));
324 SR(VID_FIR_COEF_V(1, 1));
325 SR(VID_FIR_COEF_V(1, 2));
326 SR(VID_FIR_COEF_V(1, 3));
327 SR(VID_FIR_COEF_V(1, 4));
328 SR(VID_FIR_COEF_V(1, 5));
329 SR(VID_FIR_COEF_V(1, 6));
330 SR(VID_FIR_COEF_V(1, 7));
331
332 SR(VID_PRELOAD(1));
333}
334
335void dispc_restore_context(void)
336{
337 RR(SYSCONFIG);
338 RR(IRQENABLE);
339 /*RR(CONTROL);*/
340 RR(CONFIG);
341 RR(DEFAULT_COLOR0);
342 RR(DEFAULT_COLOR1);
343 RR(TRANS_COLOR0);
344 RR(TRANS_COLOR1);
345 RR(LINE_NUMBER);
346 RR(TIMING_H);
347 RR(TIMING_V);
348 RR(POL_FREQ);
349 RR(DIVISOR);
350 RR(GLOBAL_ALPHA);
351 RR(SIZE_DIG);
352 RR(SIZE_LCD);
353
354 RR(GFX_BA0);
355 RR(GFX_BA1);
356 RR(GFX_POSITION);
357 RR(GFX_SIZE);
358 RR(GFX_ATTRIBUTES);
359 RR(GFX_FIFO_THRESHOLD);
360 RR(GFX_ROW_INC);
361 RR(GFX_PIXEL_INC);
362 RR(GFX_WINDOW_SKIP);
363 RR(GFX_TABLE_BA);
364
365 RR(DATA_CYCLE1);
366 RR(DATA_CYCLE2);
367 RR(DATA_CYCLE3);
368
369 RR(CPR_COEF_R);
370 RR(CPR_COEF_G);
371 RR(CPR_COEF_B);
372
373 RR(GFX_PRELOAD);
374
375 /* VID1 */
376 RR(VID_BA0(0));
377 RR(VID_BA1(0));
378 RR(VID_POSITION(0));
379 RR(VID_SIZE(0));
380 RR(VID_ATTRIBUTES(0));
381 RR(VID_FIFO_THRESHOLD(0));
382 RR(VID_ROW_INC(0));
383 RR(VID_PIXEL_INC(0));
384 RR(VID_FIR(0));
385 RR(VID_PICTURE_SIZE(0));
386 RR(VID_ACCU0(0));
387 RR(VID_ACCU1(0));
388
389 RR(VID_FIR_COEF_H(0, 0));
390 RR(VID_FIR_COEF_H(0, 1));
391 RR(VID_FIR_COEF_H(0, 2));
392 RR(VID_FIR_COEF_H(0, 3));
393 RR(VID_FIR_COEF_H(0, 4));
394 RR(VID_FIR_COEF_H(0, 5));
395 RR(VID_FIR_COEF_H(0, 6));
396 RR(VID_FIR_COEF_H(0, 7));
397
398 RR(VID_FIR_COEF_HV(0, 0));
399 RR(VID_FIR_COEF_HV(0, 1));
400 RR(VID_FIR_COEF_HV(0, 2));
401 RR(VID_FIR_COEF_HV(0, 3));
402 RR(VID_FIR_COEF_HV(0, 4));
403 RR(VID_FIR_COEF_HV(0, 5));
404 RR(VID_FIR_COEF_HV(0, 6));
405 RR(VID_FIR_COEF_HV(0, 7));
406
407 RR(VID_CONV_COEF(0, 0));
408 RR(VID_CONV_COEF(0, 1));
409 RR(VID_CONV_COEF(0, 2));
410 RR(VID_CONV_COEF(0, 3));
411 RR(VID_CONV_COEF(0, 4));
412
413 RR(VID_FIR_COEF_V(0, 0));
414 RR(VID_FIR_COEF_V(0, 1));
415 RR(VID_FIR_COEF_V(0, 2));
416 RR(VID_FIR_COEF_V(0, 3));
417 RR(VID_FIR_COEF_V(0, 4));
418 RR(VID_FIR_COEF_V(0, 5));
419 RR(VID_FIR_COEF_V(0, 6));
420 RR(VID_FIR_COEF_V(0, 7));
421
422 RR(VID_PRELOAD(0));
423
424 /* VID2 */
425 RR(VID_BA0(1));
426 RR(VID_BA1(1));
427 RR(VID_POSITION(1));
428 RR(VID_SIZE(1));
429 RR(VID_ATTRIBUTES(1));
430 RR(VID_FIFO_THRESHOLD(1));
431 RR(VID_ROW_INC(1));
432 RR(VID_PIXEL_INC(1));
433 RR(VID_FIR(1));
434 RR(VID_PICTURE_SIZE(1));
435 RR(VID_ACCU0(1));
436 RR(VID_ACCU1(1));
437
438 RR(VID_FIR_COEF_H(1, 0));
439 RR(VID_FIR_COEF_H(1, 1));
440 RR(VID_FIR_COEF_H(1, 2));
441 RR(VID_FIR_COEF_H(1, 3));
442 RR(VID_FIR_COEF_H(1, 4));
443 RR(VID_FIR_COEF_H(1, 5));
444 RR(VID_FIR_COEF_H(1, 6));
445 RR(VID_FIR_COEF_H(1, 7));
446
447 RR(VID_FIR_COEF_HV(1, 0));
448 RR(VID_FIR_COEF_HV(1, 1));
449 RR(VID_FIR_COEF_HV(1, 2));
450 RR(VID_FIR_COEF_HV(1, 3));
451 RR(VID_FIR_COEF_HV(1, 4));
452 RR(VID_FIR_COEF_HV(1, 5));
453 RR(VID_FIR_COEF_HV(1, 6));
454 RR(VID_FIR_COEF_HV(1, 7));
455
456 RR(VID_CONV_COEF(1, 0));
457 RR(VID_CONV_COEF(1, 1));
458 RR(VID_CONV_COEF(1, 2));
459 RR(VID_CONV_COEF(1, 3));
460 RR(VID_CONV_COEF(1, 4));
461
462 RR(VID_FIR_COEF_V(1, 0));
463 RR(VID_FIR_COEF_V(1, 1));
464 RR(VID_FIR_COEF_V(1, 2));
465 RR(VID_FIR_COEF_V(1, 3));
466 RR(VID_FIR_COEF_V(1, 4));
467 RR(VID_FIR_COEF_V(1, 5));
468 RR(VID_FIR_COEF_V(1, 6));
469 RR(VID_FIR_COEF_V(1, 7));
470
471 RR(VID_PRELOAD(1));
472
473 /* enable last, because LCD & DIGIT enable are here */
474 RR(CONTROL);
475}
476
477#undef SR
478#undef RR
479
480static inline void enable_clocks(bool enable)
481{
482 if (enable)
483 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
484 else
485 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
486}
487
488bool dispc_go_busy(enum omap_channel channel)
489{
490 int bit;
491
492 if (channel == OMAP_DSS_CHANNEL_LCD)
493 bit = 5; /* GOLCD */
494 else
495 bit = 6; /* GODIGIT */
496
497 return REG_GET(DISPC_CONTROL, bit, bit) == 1;
498}
499
500void dispc_go(enum omap_channel channel)
501{
502 int bit;
503
504 enable_clocks(1);
505
506 if (channel == OMAP_DSS_CHANNEL_LCD)
507 bit = 0; /* LCDENABLE */
508 else
509 bit = 1; /* DIGITALENABLE */
510
511 /* if the channel is not enabled, we don't need GO */
512 if (REG_GET(DISPC_CONTROL, bit, bit) == 0)
513 goto end;
514
515 if (channel == OMAP_DSS_CHANNEL_LCD)
516 bit = 5; /* GOLCD */
517 else
518 bit = 6; /* GODIGIT */
519
520 if (REG_GET(DISPC_CONTROL, bit, bit) == 1) {
521 DSSERR("GO bit not down for channel %d\n", channel);
522 goto end;
523 }
524
525 DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" : "DIGIT");
526
527 REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
528end:
529 enable_clocks(0);
530}
531
532static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value)
533{
534 BUG_ON(plane == OMAP_DSS_GFX);
535
536 dispc_write_reg(DISPC_VID_FIR_COEF_H(plane-1, reg), value);
537}
538
539static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value)
540{
541 BUG_ON(plane == OMAP_DSS_GFX);
542
543 dispc_write_reg(DISPC_VID_FIR_COEF_HV(plane-1, reg), value);
544}
545
546static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value)
547{
548 BUG_ON(plane == OMAP_DSS_GFX);
549
550 dispc_write_reg(DISPC_VID_FIR_COEF_V(plane-1, reg), value);
551}
552
553static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
554 int vscaleup, int five_taps)
555{
556 /* Coefficients for horizontal up-sampling */
557 static const u32 coef_hup[8] = {
558 0x00800000,
559 0x0D7CF800,
560 0x1E70F5FF,
561 0x335FF5FE,
562 0xF74949F7,
563 0xF55F33FB,
564 0xF5701EFE,
565 0xF87C0DFF,
566 };
567
568 /* Coefficients for horizontal down-sampling */
569 static const u32 coef_hdown[8] = {
570 0x24382400,
571 0x28371FFE,
572 0x2C361BFB,
573 0x303516F9,
574 0x11343311,
575 0x1635300C,
576 0x1B362C08,
577 0x1F372804,
578 };
579
580 /* Coefficients for horizontal and vertical up-sampling */
581 static const u32 coef_hvup[2][8] = {
582 {
583 0x00800000,
584 0x037B02FF,
585 0x0C6F05FE,
586 0x205907FB,
587 0x00404000,
588 0x075920FE,
589 0x056F0CFF,
590 0x027B0300,
591 },
592 {
593 0x00800000,
594 0x0D7CF8FF,
595 0x1E70F5FE,
596 0x335FF5FB,
597 0xF7404000,
598 0xF55F33FE,
599 0xF5701EFF,
600 0xF87C0D00,
601 },
602 };
603
604 /* Coefficients for horizontal and vertical down-sampling */
605 static const u32 coef_hvdown[2][8] = {
606 {
607 0x24382400,
608 0x28391F04,
609 0x2D381B08,
610 0x3237170C,
611 0x123737F7,
612 0x173732F9,
613 0x1B382DFB,
614 0x1F3928FE,
615 },
616 {
617 0x24382400,
618 0x28371F04,
619 0x2C361B08,
620 0x3035160C,
621 0x113433F7,
622 0x163530F9,
623 0x1B362CFB,
624 0x1F3728FE,
625 },
626 };
627
628 /* Coefficients for vertical up-sampling */
629 static const u32 coef_vup[8] = {
630 0x00000000,
631 0x0000FF00,
632 0x0000FEFF,
633 0x0000FBFE,
634 0x000000F7,
635 0x0000FEFB,
636 0x0000FFFE,
637 0x000000FF,
638 };
639
640
641 /* Coefficients for vertical down-sampling */
642 static const u32 coef_vdown[8] = {
643 0x00000000,
644 0x000004FE,
645 0x000008FB,
646 0x00000CF9,
647 0x0000F711,
648 0x0000F90C,
649 0x0000FB08,
650 0x0000FE04,
651 };
652
653 const u32 *h_coef;
654 const u32 *hv_coef;
655 const u32 *hv_coef_mod;
656 const u32 *v_coef;
657 int i;
658
659 if (hscaleup)
660 h_coef = coef_hup;
661 else
662 h_coef = coef_hdown;
663
664 if (vscaleup) {
665 hv_coef = coef_hvup[five_taps];
666 v_coef = coef_vup;
667
668 if (hscaleup)
669 hv_coef_mod = NULL;
670 else
671 hv_coef_mod = coef_hvdown[five_taps];
672 } else {
673 hv_coef = coef_hvdown[five_taps];
674 v_coef = coef_vdown;
675
676 if (hscaleup)
677 hv_coef_mod = coef_hvup[five_taps];
678 else
679 hv_coef_mod = NULL;
680 }
681
682 for (i = 0; i < 8; i++) {
683 u32 h, hv;
684
685 h = h_coef[i];
686
687 hv = hv_coef[i];
688
689 if (hv_coef_mod) {
690 hv &= 0xffffff00;
691 hv |= (hv_coef_mod[i] & 0xff);
692 }
693
694 _dispc_write_firh_reg(plane, i, h);
695 _dispc_write_firhv_reg(plane, i, hv);
696 }
697
698 if (!five_taps)
699 return;
700
701 for (i = 0; i < 8; i++) {
702 u32 v;
703 v = v_coef[i];
704 _dispc_write_firv_reg(plane, i, v);
705 }
706}
707
708static void _dispc_setup_color_conv_coef(void)
709{
710 const struct color_conv_coef {
711 int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
712 int full_range;
713 } ctbl_bt601_5 = {
714 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
715 };
716
717 const struct color_conv_coef *ct;
718
719#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
720
721 ct = &ctbl_bt601_5;
722
723 dispc_write_reg(DISPC_VID_CONV_COEF(0, 0), CVAL(ct->rcr, ct->ry));
724 dispc_write_reg(DISPC_VID_CONV_COEF(0, 1), CVAL(ct->gy, ct->rcb));
725 dispc_write_reg(DISPC_VID_CONV_COEF(0, 2), CVAL(ct->gcb, ct->gcr));
726 dispc_write_reg(DISPC_VID_CONV_COEF(0, 3), CVAL(ct->bcr, ct->by));
727 dispc_write_reg(DISPC_VID_CONV_COEF(0, 4), CVAL(0, ct->bcb));
728
729 dispc_write_reg(DISPC_VID_CONV_COEF(1, 0), CVAL(ct->rcr, ct->ry));
730 dispc_write_reg(DISPC_VID_CONV_COEF(1, 1), CVAL(ct->gy, ct->rcb));
731 dispc_write_reg(DISPC_VID_CONV_COEF(1, 2), CVAL(ct->gcb, ct->gcr));
732 dispc_write_reg(DISPC_VID_CONV_COEF(1, 3), CVAL(ct->bcr, ct->by));
733 dispc_write_reg(DISPC_VID_CONV_COEF(1, 4), CVAL(0, ct->bcb));
734
735#undef CVAL
736
737 REG_FLD_MOD(DISPC_VID_ATTRIBUTES(0), ct->full_range, 11, 11);
738 REG_FLD_MOD(DISPC_VID_ATTRIBUTES(1), ct->full_range, 11, 11);
739}
740
741
742static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr)
743{
744 const struct dispc_reg ba0_reg[] = { DISPC_GFX_BA0,
745 DISPC_VID_BA0(0),
746 DISPC_VID_BA0(1) };
747
748 dispc_write_reg(ba0_reg[plane], paddr);
749}
750
751static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr)
752{
753 const struct dispc_reg ba1_reg[] = { DISPC_GFX_BA1,
754 DISPC_VID_BA1(0),
755 DISPC_VID_BA1(1) };
756
757 dispc_write_reg(ba1_reg[plane], paddr);
758}
759
760static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y)
761{
762 const struct dispc_reg pos_reg[] = { DISPC_GFX_POSITION,
763 DISPC_VID_POSITION(0),
764 DISPC_VID_POSITION(1) };
765
766 u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
767 dispc_write_reg(pos_reg[plane], val);
768}
769
770static void _dispc_set_pic_size(enum omap_plane plane, int width, int height)
771{
772 const struct dispc_reg siz_reg[] = { DISPC_GFX_SIZE,
773 DISPC_VID_PICTURE_SIZE(0),
774 DISPC_VID_PICTURE_SIZE(1) };
775 u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
776 dispc_write_reg(siz_reg[plane], val);
777}
778
779static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)
780{
781 u32 val;
782 const struct dispc_reg vsi_reg[] = { DISPC_VID_SIZE(0),
783 DISPC_VID_SIZE(1) };
784
785 BUG_ON(plane == OMAP_DSS_GFX);
786
787 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
788 dispc_write_reg(vsi_reg[plane-1], val);
789}
790
791static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha)
792{
793
794 BUG_ON(plane == OMAP_DSS_VIDEO1);
795
796 if (cpu_is_omap24xx())
797 return;
798
799 if (plane == OMAP_DSS_GFX)
800 REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0);
801 else if (plane == OMAP_DSS_VIDEO2)
802 REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 23, 16);
803}
804
805static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc)
806{
807 const struct dispc_reg ri_reg[] = { DISPC_GFX_PIXEL_INC,
808 DISPC_VID_PIXEL_INC(0),
809 DISPC_VID_PIXEL_INC(1) };
810
811 dispc_write_reg(ri_reg[plane], inc);
812}
813
814static void _dispc_set_row_inc(enum omap_plane plane, s32 inc)
815{
816 const struct dispc_reg ri_reg[] = { DISPC_GFX_ROW_INC,
817 DISPC_VID_ROW_INC(0),
818 DISPC_VID_ROW_INC(1) };
819
820 dispc_write_reg(ri_reg[plane], inc);
821}
822
823static void _dispc_set_color_mode(enum omap_plane plane,
824 enum omap_color_mode color_mode)
825{
826 u32 m = 0;
827
828 switch (color_mode) {
829 case OMAP_DSS_COLOR_CLUT1:
830 m = 0x0; break;
831 case OMAP_DSS_COLOR_CLUT2:
832 m = 0x1; break;
833 case OMAP_DSS_COLOR_CLUT4:
834 m = 0x2; break;
835 case OMAP_DSS_COLOR_CLUT8:
836 m = 0x3; break;
837 case OMAP_DSS_COLOR_RGB12U:
838 m = 0x4; break;
839 case OMAP_DSS_COLOR_ARGB16:
840 m = 0x5; break;
841 case OMAP_DSS_COLOR_RGB16:
842 m = 0x6; break;
843 case OMAP_DSS_COLOR_RGB24U:
844 m = 0x8; break;
845 case OMAP_DSS_COLOR_RGB24P:
846 m = 0x9; break;
847 case OMAP_DSS_COLOR_YUV2:
848 m = 0xa; break;
849 case OMAP_DSS_COLOR_UYVY:
850 m = 0xb; break;
851 case OMAP_DSS_COLOR_ARGB32:
852 m = 0xc; break;
853 case OMAP_DSS_COLOR_RGBA32:
854 m = 0xd; break;
855 case OMAP_DSS_COLOR_RGBX32:
856 m = 0xe; break;
857 default:
858 BUG(); break;
859 }
860
861 REG_FLD_MOD(dispc_reg_att[plane], m, 4, 1);
862}
863
864static void _dispc_set_channel_out(enum omap_plane plane,
865 enum omap_channel channel)
866{
867 int shift;
868 u32 val;
869
870 switch (plane) {
871 case OMAP_DSS_GFX:
872 shift = 8;
873 break;
874 case OMAP_DSS_VIDEO1:
875 case OMAP_DSS_VIDEO2:
876 shift = 16;
877 break;
878 default:
879 BUG();
880 return;
881 }
882
883 val = dispc_read_reg(dispc_reg_att[plane]);
884 val = FLD_MOD(val, channel, shift, shift);
885 dispc_write_reg(dispc_reg_att[plane], val);
886}
887
888void dispc_set_burst_size(enum omap_plane plane,
889 enum omap_burst_size burst_size)
890{
891 int shift;
892 u32 val;
893
894 enable_clocks(1);
895
896 switch (plane) {
897 case OMAP_DSS_GFX:
898 shift = 6;
899 break;
900 case OMAP_DSS_VIDEO1:
901 case OMAP_DSS_VIDEO2:
902 shift = 14;
903 break;
904 default:
905 BUG();
906 return;
907 }
908
909 val = dispc_read_reg(dispc_reg_att[plane]);
910 val = FLD_MOD(val, burst_size, shift+1, shift);
911 dispc_write_reg(dispc_reg_att[plane], val);
912
913 enable_clocks(0);
914}
915
916static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
917{
918 u32 val;
919
920 BUG_ON(plane == OMAP_DSS_GFX);
921
922 val = dispc_read_reg(dispc_reg_att[plane]);
923 val = FLD_MOD(val, enable, 9, 9);
924 dispc_write_reg(dispc_reg_att[plane], val);
925}
926
927void dispc_enable_replication(enum omap_plane plane, bool enable)
928{
929 int bit;
930
931 if (plane == OMAP_DSS_GFX)
932 bit = 5;
933 else
934 bit = 10;
935
936 enable_clocks(1);
937 REG_FLD_MOD(dispc_reg_att[plane], enable, bit, bit);
938 enable_clocks(0);
939}
940
941void dispc_set_lcd_size(u16 width, u16 height)
942{
943 u32 val;
944 BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
945 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
946 enable_clocks(1);
947 dispc_write_reg(DISPC_SIZE_LCD, val);
948 enable_clocks(0);
949}
950
951void dispc_set_digit_size(u16 width, u16 height)
952{
953 u32 val;
954 BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
955 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
956 enable_clocks(1);
957 dispc_write_reg(DISPC_SIZE_DIG, val);
958 enable_clocks(0);
959}
960
961static void dispc_read_plane_fifo_sizes(void)
962{
963 const struct dispc_reg fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS,
964 DISPC_VID_FIFO_SIZE_STATUS(0),
965 DISPC_VID_FIFO_SIZE_STATUS(1) };
966 u32 size;
967 int plane;
968
969 enable_clocks(1);
970
971 for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
972 if (cpu_is_omap24xx())
973 size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 8, 0);
974 else if (cpu_is_omap34xx())
975 size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 10, 0);
976 else
977 BUG();
978
979 dispc.fifo_size[plane] = size;
980 }
981
982 enable_clocks(0);
983}
984
985u32 dispc_get_plane_fifo_size(enum omap_plane plane)
986{
987 return dispc.fifo_size[plane];
988}
989
990void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
991{
992 const struct dispc_reg ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD,
993 DISPC_VID_FIFO_THRESHOLD(0),
994 DISPC_VID_FIFO_THRESHOLD(1) };
995 enable_clocks(1);
996
997 DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
998 plane,
999 REG_GET(ftrs_reg[plane], 11, 0),
1000 REG_GET(ftrs_reg[plane], 27, 16),
1001 low, high);
1002
1003 if (cpu_is_omap24xx())
1004 dispc_write_reg(ftrs_reg[plane],
1005 FLD_VAL(high, 24, 16) | FLD_VAL(low, 8, 0));
1006 else
1007 dispc_write_reg(ftrs_reg[plane],
1008 FLD_VAL(high, 27, 16) | FLD_VAL(low, 11, 0));
1009
1010 enable_clocks(0);
1011}
1012
1013void dispc_enable_fifomerge(bool enable)
1014{
1015 enable_clocks(1);
1016
1017 DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
1018 REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
1019
1020 enable_clocks(0);
1021}
1022
1023static void _dispc_set_fir(enum omap_plane plane, int hinc, int vinc)
1024{
1025 u32 val;
1026 const struct dispc_reg fir_reg[] = { DISPC_VID_FIR(0),
1027 DISPC_VID_FIR(1) };
1028
1029 BUG_ON(plane == OMAP_DSS_GFX);
1030
1031 if (cpu_is_omap24xx())
1032 val = FLD_VAL(vinc, 27, 16) | FLD_VAL(hinc, 11, 0);
1033 else
1034 val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0);
1035 dispc_write_reg(fir_reg[plane-1], val);
1036}
1037
1038static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
1039{
1040 u32 val;
1041 const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0),
1042 DISPC_VID_ACCU0(1) };
1043
1044 BUG_ON(plane == OMAP_DSS_GFX);
1045
1046 val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
1047 dispc_write_reg(ac0_reg[plane-1], val);
1048}
1049
1050static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
1051{
1052 u32 val;
1053 const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0),
1054 DISPC_VID_ACCU1(1) };
1055
1056 BUG_ON(plane == OMAP_DSS_GFX);
1057
1058 val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
1059 dispc_write_reg(ac1_reg[plane-1], val);
1060}
1061
1062
1063static void _dispc_set_scaling(enum omap_plane plane,
1064 u16 orig_width, u16 orig_height,
1065 u16 out_width, u16 out_height,
1066 bool ilace, bool five_taps,
1067 bool fieldmode)
1068{
1069 int fir_hinc;
1070 int fir_vinc;
1071 int hscaleup, vscaleup;
1072 int accu0 = 0;
1073 int accu1 = 0;
1074 u32 l;
1075
1076 BUG_ON(plane == OMAP_DSS_GFX);
1077
1078 hscaleup = orig_width <= out_width;
1079 vscaleup = orig_height <= out_height;
1080
1081 _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps);
1082
1083 if (!orig_width || orig_width == out_width)
1084 fir_hinc = 0;
1085 else
1086 fir_hinc = 1024 * orig_width / out_width;
1087
1088 if (!orig_height || orig_height == out_height)
1089 fir_vinc = 0;
1090 else
1091 fir_vinc = 1024 * orig_height / out_height;
1092
1093 _dispc_set_fir(plane, fir_hinc, fir_vinc);
1094
1095 l = dispc_read_reg(dispc_reg_att[plane]);
1096 l &= ~((0x0f << 5) | (0x3 << 21));
1097
1098 l |= fir_hinc ? (1 << 5) : 0;
1099 l |= fir_vinc ? (1 << 6) : 0;
1100
1101 l |= hscaleup ? 0 : (1 << 7);
1102 l |= vscaleup ? 0 : (1 << 8);
1103
1104 l |= five_taps ? (1 << 21) : 0;
1105 l |= five_taps ? (1 << 22) : 0;
1106
1107 dispc_write_reg(dispc_reg_att[plane], l);
1108
1109 /*
1110 * field 0 = even field = bottom field
1111 * field 1 = odd field = top field
1112 */
1113 if (ilace && !fieldmode) {
1114 accu1 = 0;
1115 accu0 = (fir_vinc / 2) & 0x3ff;
1116 if (accu0 >= 1024/2) {
1117 accu1 = 1024/2;
1118 accu0 -= accu1;
1119 }
1120 }
1121
1122 _dispc_set_vid_accu0(plane, 0, accu0);
1123 _dispc_set_vid_accu1(plane, 0, accu1);
1124}
1125
1126static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
1127 bool mirroring, enum omap_color_mode color_mode)
1128{
1129 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1130 color_mode == OMAP_DSS_COLOR_UYVY) {
1131 int vidrot = 0;
1132
1133 if (mirroring) {
1134 switch (rotation) {
1135 case OMAP_DSS_ROT_0:
1136 vidrot = 2;
1137 break;
1138 case OMAP_DSS_ROT_90:
1139 vidrot = 1;
1140 break;
1141 case OMAP_DSS_ROT_180:
1142 vidrot = 0;
1143 break;
1144 case OMAP_DSS_ROT_270:
1145 vidrot = 3;
1146 break;
1147 }
1148 } else {
1149 switch (rotation) {
1150 case OMAP_DSS_ROT_0:
1151 vidrot = 0;
1152 break;
1153 case OMAP_DSS_ROT_90:
1154 vidrot = 1;
1155 break;
1156 case OMAP_DSS_ROT_180:
1157 vidrot = 2;
1158 break;
1159 case OMAP_DSS_ROT_270:
1160 vidrot = 3;
1161 break;
1162 }
1163 }
1164
1165 REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12);
1166
1167 if (rotation == OMAP_DSS_ROT_90 || rotation == OMAP_DSS_ROT_270)
1168 REG_FLD_MOD(dispc_reg_att[plane], 0x1, 18, 18);
1169 else
1170 REG_FLD_MOD(dispc_reg_att[plane], 0x0, 18, 18);
1171 } else {
1172 REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12);
1173 REG_FLD_MOD(dispc_reg_att[plane], 0, 18, 18);
1174 }
1175}
1176
1177static int color_mode_to_bpp(enum omap_color_mode color_mode)
1178{
1179 switch (color_mode) {
1180 case OMAP_DSS_COLOR_CLUT1:
1181 return 1;
1182 case OMAP_DSS_COLOR_CLUT2:
1183 return 2;
1184 case OMAP_DSS_COLOR_CLUT4:
1185 return 4;
1186 case OMAP_DSS_COLOR_CLUT8:
1187 return 8;
1188 case OMAP_DSS_COLOR_RGB12U:
1189 case OMAP_DSS_COLOR_RGB16:
1190 case OMAP_DSS_COLOR_ARGB16:
1191 case OMAP_DSS_COLOR_YUV2:
1192 case OMAP_DSS_COLOR_UYVY:
1193 return 16;
1194 case OMAP_DSS_COLOR_RGB24P:
1195 return 24;
1196 case OMAP_DSS_COLOR_RGB24U:
1197 case OMAP_DSS_COLOR_ARGB32:
1198 case OMAP_DSS_COLOR_RGBA32:
1199 case OMAP_DSS_COLOR_RGBX32:
1200 return 32;
1201 default:
1202 BUG();
1203 }
1204}
1205
1206static s32 pixinc(int pixels, u8 ps)
1207{
1208 if (pixels == 1)
1209 return 1;
1210 else if (pixels > 1)
1211 return 1 + (pixels - 1) * ps;
1212 else if (pixels < 0)
1213 return 1 - (-pixels + 1) * ps;
1214 else
1215 BUG();
1216}
1217
1218static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
1219 u16 screen_width,
1220 u16 width, u16 height,
1221 enum omap_color_mode color_mode, bool fieldmode,
1222 unsigned int field_offset,
1223 unsigned *offset0, unsigned *offset1,
1224 s32 *row_inc, s32 *pix_inc)
1225{
1226 u8 ps;
1227
1228 /* FIXME CLUT formats */
1229 switch (color_mode) {
1230 case OMAP_DSS_COLOR_CLUT1:
1231 case OMAP_DSS_COLOR_CLUT2:
1232 case OMAP_DSS_COLOR_CLUT4:
1233 case OMAP_DSS_COLOR_CLUT8:
1234 BUG();
1235 return;
1236 case OMAP_DSS_COLOR_YUV2:
1237 case OMAP_DSS_COLOR_UYVY:
1238 ps = 4;
1239 break;
1240 default:
1241 ps = color_mode_to_bpp(color_mode) / 8;
1242 break;
1243 }
1244
1245 DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
1246 width, height);
1247
1248 /*
1249 * field 0 = even field = bottom field
1250 * field 1 = odd field = top field
1251 */
1252 switch (rotation + mirror * 4) {
1253 case OMAP_DSS_ROT_0:
1254 case OMAP_DSS_ROT_180:
1255 /*
1256 * If the pixel format is YUV or UYVY divide the width
1257 * of the image by 2 for 0 and 180 degree rotation.
1258 */
1259 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1260 color_mode == OMAP_DSS_COLOR_UYVY)
1261 width = width >> 1;
1262 case OMAP_DSS_ROT_90:
1263 case OMAP_DSS_ROT_270:
1264 *offset1 = 0;
1265 if (field_offset)
1266 *offset0 = field_offset * screen_width * ps;
1267 else
1268 *offset0 = 0;
1269
1270 *row_inc = pixinc(1 + (screen_width - width) +
1271 (fieldmode ? screen_width : 0),
1272 ps);
1273 *pix_inc = pixinc(1, ps);
1274 break;
1275
1276 case OMAP_DSS_ROT_0 + 4:
1277 case OMAP_DSS_ROT_180 + 4:
1278 /* If the pixel format is YUV or UYVY divide the width
1279 * of the image by 2 for 0 degree and 180 degree
1280 */
1281 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1282 color_mode == OMAP_DSS_COLOR_UYVY)
1283 width = width >> 1;
1284 case OMAP_DSS_ROT_90 + 4:
1285 case OMAP_DSS_ROT_270 + 4:
1286 *offset1 = 0;
1287 if (field_offset)
1288 *offset0 = field_offset * screen_width * ps;
1289 else
1290 *offset0 = 0;
1291 *row_inc = pixinc(1 - (screen_width + width) -
1292 (fieldmode ? screen_width : 0),
1293 ps);
1294 *pix_inc = pixinc(1, ps);
1295 break;
1296
1297 default:
1298 BUG();
1299 }
1300}
1301
1302static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1303 u16 screen_width,
1304 u16 width, u16 height,
1305 enum omap_color_mode color_mode, bool fieldmode,
1306 unsigned int field_offset,
1307 unsigned *offset0, unsigned *offset1,
1308 s32 *row_inc, s32 *pix_inc)
1309{
1310 u8 ps;
1311 u16 fbw, fbh;
1312
1313 /* FIXME CLUT formats */
1314 switch (color_mode) {
1315 case OMAP_DSS_COLOR_CLUT1:
1316 case OMAP_DSS_COLOR_CLUT2:
1317 case OMAP_DSS_COLOR_CLUT4:
1318 case OMAP_DSS_COLOR_CLUT8:
1319 BUG();
1320 return;
1321 default:
1322 ps = color_mode_to_bpp(color_mode) / 8;
1323 break;
1324 }
1325
1326 DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
1327 width, height);
1328
1329 /* width & height are overlay sizes, convert to fb sizes */
1330
1331 if (rotation == OMAP_DSS_ROT_0 || rotation == OMAP_DSS_ROT_180) {
1332 fbw = width;
1333 fbh = height;
1334 } else {
1335 fbw = height;
1336 fbh = width;
1337 }
1338
1339 /*
1340 * field 0 = even field = bottom field
1341 * field 1 = odd field = top field
1342 */
1343 switch (rotation + mirror * 4) {
1344 case OMAP_DSS_ROT_0:
1345 *offset1 = 0;
1346 if (field_offset)
1347 *offset0 = *offset1 + field_offset * screen_width * ps;
1348 else
1349 *offset0 = *offset1;
1350 *row_inc = pixinc(1 + (screen_width - fbw) +
1351 (fieldmode ? screen_width : 0),
1352 ps);
1353 *pix_inc = pixinc(1, ps);
1354 break;
1355 case OMAP_DSS_ROT_90:
1356 *offset1 = screen_width * (fbh - 1) * ps;
1357 if (field_offset)
1358 *offset0 = *offset1 + field_offset * ps;
1359 else
1360 *offset0 = *offset1;
1361 *row_inc = pixinc(screen_width * (fbh - 1) + 1 +
1362 (fieldmode ? 1 : 0), ps);
1363 *pix_inc = pixinc(-screen_width, ps);
1364 break;
1365 case OMAP_DSS_ROT_180:
1366 *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
1367 if (field_offset)
1368 *offset0 = *offset1 - field_offset * screen_width * ps;
1369 else
1370 *offset0 = *offset1;
1371 *row_inc = pixinc(-1 -
1372 (screen_width - fbw) -
1373 (fieldmode ? screen_width : 0),
1374 ps);
1375 *pix_inc = pixinc(-1, ps);
1376 break;
1377 case OMAP_DSS_ROT_270:
1378 *offset1 = (fbw - 1) * ps;
1379 if (field_offset)
1380 *offset0 = *offset1 - field_offset * ps;
1381 else
1382 *offset0 = *offset1;
1383 *row_inc = pixinc(-screen_width * (fbh - 1) - 1 -
1384 (fieldmode ? 1 : 0), ps);
1385 *pix_inc = pixinc(screen_width, ps);
1386 break;
1387
1388 /* mirroring */
1389 case OMAP_DSS_ROT_0 + 4:
1390 *offset1 = (fbw - 1) * ps;
1391 if (field_offset)
1392 *offset0 = *offset1 + field_offset * screen_width * ps;
1393 else
1394 *offset0 = *offset1;
1395 *row_inc = pixinc(screen_width * 2 - 1 +
1396 (fieldmode ? screen_width : 0),
1397 ps);
1398 *pix_inc = pixinc(-1, ps);
1399 break;
1400
1401 case OMAP_DSS_ROT_90 + 4:
1402 *offset1 = 0;
1403 if (field_offset)
1404 *offset0 = *offset1 + field_offset * ps;
1405 else
1406 *offset0 = *offset1;
1407 *row_inc = pixinc(-screen_width * (fbh - 1) + 1 +
1408 (fieldmode ? 1 : 0),
1409 ps);
1410 *pix_inc = pixinc(screen_width, ps);
1411 break;
1412
1413 case OMAP_DSS_ROT_180 + 4:
1414 *offset1 = screen_width * (fbh - 1) * ps;
1415 if (field_offset)
1416 *offset0 = *offset1 - field_offset * screen_width * ps;
1417 else
1418 *offset0 = *offset1;
1419 *row_inc = pixinc(1 - screen_width * 2 -
1420 (fieldmode ? screen_width : 0),
1421 ps);
1422 *pix_inc = pixinc(1, ps);
1423 break;
1424
1425 case OMAP_DSS_ROT_270 + 4:
1426 *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
1427 if (field_offset)
1428 *offset0 = *offset1 - field_offset * ps;
1429 else
1430 *offset0 = *offset1;
1431 *row_inc = pixinc(screen_width * (fbh - 1) - 1 -
1432 (fieldmode ? 1 : 0),
1433 ps);
1434 *pix_inc = pixinc(-screen_width, ps);
1435 break;
1436
1437 default:
1438 BUG();
1439 }
1440}
1441
1442static unsigned long calc_fclk_five_taps(u16 width, u16 height,
1443 u16 out_width, u16 out_height, enum omap_color_mode color_mode)
1444{
1445 u32 fclk = 0;
1446 /* FIXME venc pclk? */
1447 u64 tmp, pclk = dispc_pclk_rate();
1448
1449 if (height > out_height) {
1450 /* FIXME get real display PPL */
1451 unsigned int ppl = 800;
1452
1453 tmp = pclk * height * out_width;
1454 do_div(tmp, 2 * out_height * ppl);
1455 fclk = tmp;
1456
1457 if (height > 2 * out_height) {
1458 if (ppl == out_width)
1459 return 0;
1460
1461 tmp = pclk * (height - 2 * out_height) * out_width;
1462 do_div(tmp, 2 * out_height * (ppl - out_width));
1463 fclk = max(fclk, (u32) tmp);
1464 }
1465 }
1466
1467 if (width > out_width) {
1468 tmp = pclk * width;
1469 do_div(tmp, out_width);
1470 fclk = max(fclk, (u32) tmp);
1471
1472 if (color_mode == OMAP_DSS_COLOR_RGB24U)
1473 fclk <<= 1;
1474 }
1475
1476 return fclk;
1477}
1478
1479static unsigned long calc_fclk(u16 width, u16 height,
1480 u16 out_width, u16 out_height)
1481{
1482 unsigned int hf, vf;
1483
1484 /*
1485 * FIXME how to determine the 'A' factor
1486 * for the no downscaling case ?
1487 */
1488
1489 if (width > 3 * out_width)
1490 hf = 4;
1491 else if (width > 2 * out_width)
1492 hf = 3;
1493 else if (width > out_width)
1494 hf = 2;
1495 else
1496 hf = 1;
1497
1498 if (height > out_height)
1499 vf = 2;
1500 else
1501 vf = 1;
1502
1503 /* FIXME venc pclk? */
1504 return dispc_pclk_rate() * vf * hf;
1505}
1506
1507void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out)
1508{
1509 enable_clocks(1);
1510 _dispc_set_channel_out(plane, channel_out);
1511 enable_clocks(0);
1512}
1513
1514static int _dispc_setup_plane(enum omap_plane plane,
1515 u32 paddr, u16 screen_width,
1516 u16 pos_x, u16 pos_y,
1517 u16 width, u16 height,
1518 u16 out_width, u16 out_height,
1519 enum omap_color_mode color_mode,
1520 bool ilace,
1521 enum omap_dss_rotation_type rotation_type,
1522 u8 rotation, int mirror,
1523 u8 global_alpha)
1524{
1525 const int maxdownscale = cpu_is_omap34xx() ? 4 : 2;
1526 bool five_taps = 0;
1527 bool fieldmode = 0;
1528 int cconv = 0;
1529 unsigned offset0, offset1;
1530 s32 row_inc;
1531 s32 pix_inc;
1532 u16 frame_height = height;
1533 unsigned int field_offset = 0;
1534
1535 if (paddr == 0)
1536 return -EINVAL;
1537
1538 if (ilace && height == out_height)
1539 fieldmode = 1;
1540
1541 if (ilace) {
1542 if (fieldmode)
1543 height /= 2;
1544 pos_y /= 2;
1545 out_height /= 2;
1546
1547 DSSDBG("adjusting for ilace: height %d, pos_y %d, "
1548 "out_height %d\n",
1549 height, pos_y, out_height);
1550 }
1551
1552 if (plane == OMAP_DSS_GFX) {
1553 if (width != out_width || height != out_height)
1554 return -EINVAL;
1555
1556 switch (color_mode) {
1557 case OMAP_DSS_COLOR_ARGB16:
1558 case OMAP_DSS_COLOR_ARGB32:
1559 case OMAP_DSS_COLOR_RGBA32:
1560 case OMAP_DSS_COLOR_RGBX32:
1561 if (cpu_is_omap24xx())
1562 return -EINVAL;
1563 /* fall through */
1564 case OMAP_DSS_COLOR_RGB12U:
1565 case OMAP_DSS_COLOR_RGB16:
1566 case OMAP_DSS_COLOR_RGB24P:
1567 case OMAP_DSS_COLOR_RGB24U:
1568 break;
1569
1570 default:
1571 return -EINVAL;
1572 }
1573 } else {
1574 /* video plane */
1575
1576 unsigned long fclk = 0;
1577
1578 if (out_width < width / maxdownscale ||
1579 out_width > width * 8)
1580 return -EINVAL;
1581
1582 if (out_height < height / maxdownscale ||
1583 out_height > height * 8)
1584 return -EINVAL;
1585
1586 switch (color_mode) {
1587 case OMAP_DSS_COLOR_RGBX32:
1588 case OMAP_DSS_COLOR_RGB12U:
1589 if (cpu_is_omap24xx())
1590 return -EINVAL;
1591 /* fall through */
1592 case OMAP_DSS_COLOR_RGB16:
1593 case OMAP_DSS_COLOR_RGB24P:
1594 case OMAP_DSS_COLOR_RGB24U:
1595 break;
1596
1597 case OMAP_DSS_COLOR_ARGB16:
1598 case OMAP_DSS_COLOR_ARGB32:
1599 case OMAP_DSS_COLOR_RGBA32:
1600 if (cpu_is_omap24xx())
1601 return -EINVAL;
1602 if (plane == OMAP_DSS_VIDEO1)
1603 return -EINVAL;
1604 break;
1605
1606 case OMAP_DSS_COLOR_YUV2:
1607 case OMAP_DSS_COLOR_UYVY:
1608 cconv = 1;
1609 break;
1610
1611 default:
1612 return -EINVAL;
1613 }
1614
1615 /* Must use 5-tap filter? */
1616 five_taps = height > out_height * 2;
1617
1618 if (!five_taps) {
1619 fclk = calc_fclk(width, height,
1620 out_width, out_height);
1621
1622 /* Try 5-tap filter if 3-tap fclk is too high */
1623 if (cpu_is_omap34xx() && height > out_height &&
1624 fclk > dispc_fclk_rate())
1625 five_taps = true;
1626 }
1627
1628 if (width > (2048 >> five_taps)) {
1629 DSSERR("failed to set up scaling, fclk too low\n");
1630 return -EINVAL;
1631 }
1632
1633 if (five_taps)
1634 fclk = calc_fclk_five_taps(width, height,
1635 out_width, out_height, color_mode);
1636
1637 DSSDBG("required fclk rate = %lu Hz\n", fclk);
1638 DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
1639
1640 if (!fclk || fclk > dispc_fclk_rate()) {
1641 DSSERR("failed to set up scaling, "
1642 "required fclk rate = %lu Hz, "
1643 "current fclk rate = %lu Hz\n",
1644 fclk, dispc_fclk_rate());
1645 return -EINVAL;
1646 }
1647 }
1648
1649 if (ilace && !fieldmode) {
1650 /*
1651 * when downscaling the bottom field may have to start several
1652 * source lines below the top field. Unfortunately ACCUI
1653 * registers will only hold the fractional part of the offset
1654 * so the integer part must be added to the base address of the
1655 * bottom field.
1656 */
1657 if (!height || height == out_height)
1658 field_offset = 0;
1659 else
1660 field_offset = height / out_height / 2;
1661 }
1662
1663 /* Fields are independent but interleaved in memory. */
1664 if (fieldmode)
1665 field_offset = 1;
1666
1667 if (rotation_type == OMAP_DSS_ROT_DMA)
1668 calc_dma_rotation_offset(rotation, mirror,
1669 screen_width, width, frame_height, color_mode,
1670 fieldmode, field_offset,
1671 &offset0, &offset1, &row_inc, &pix_inc);
1672 else
1673 calc_vrfb_rotation_offset(rotation, mirror,
1674 screen_width, width, frame_height, color_mode,
1675 fieldmode, field_offset,
1676 &offset0, &offset1, &row_inc, &pix_inc);
1677
1678 DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
1679 offset0, offset1, row_inc, pix_inc);
1680
1681 _dispc_set_color_mode(plane, color_mode);
1682
1683 _dispc_set_plane_ba0(plane, paddr + offset0);
1684 _dispc_set_plane_ba1(plane, paddr + offset1);
1685
1686 _dispc_set_row_inc(plane, row_inc);
1687 _dispc_set_pix_inc(plane, pix_inc);
1688
1689 DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, width, height,
1690 out_width, out_height);
1691
1692 _dispc_set_plane_pos(plane, pos_x, pos_y);
1693
1694 _dispc_set_pic_size(plane, width, height);
1695
1696 if (plane != OMAP_DSS_GFX) {
1697 _dispc_set_scaling(plane, width, height,
1698 out_width, out_height,
1699 ilace, five_taps, fieldmode);
1700 _dispc_set_vid_size(plane, out_width, out_height);
1701 _dispc_set_vid_color_conv(plane, cconv);
1702 }
1703
1704 _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode);
1705
1706 if (plane != OMAP_DSS_VIDEO1)
1707 _dispc_setup_global_alpha(plane, global_alpha);
1708
1709 return 0;
1710}
1711
1712static void _dispc_enable_plane(enum omap_plane plane, bool enable)
1713{
1714 REG_FLD_MOD(dispc_reg_att[plane], enable ? 1 : 0, 0, 0);
1715}
1716
1717static void dispc_disable_isr(void *data, u32 mask)
1718{
1719 struct completion *compl = data;
1720 complete(compl);
1721}
1722
1723static void _enable_lcd_out(bool enable)
1724{
1725 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0);
1726}
1727
1728static void dispc_enable_lcd_out(bool enable)
1729{
1730 struct completion frame_done_completion;
1731 bool is_on;
1732 int r;
1733
1734 enable_clocks(1);
1735
1736 /* When we disable LCD output, we need to wait until frame is done.
1737 * Otherwise the DSS is still working, and turning off the clocks
1738 * prevents DSS from going to OFF mode */
1739 is_on = REG_GET(DISPC_CONTROL, 0, 0);
1740
1741 if (!enable && is_on) {
1742 init_completion(&frame_done_completion);
1743
1744 r = omap_dispc_register_isr(dispc_disable_isr,
1745 &frame_done_completion,
1746 DISPC_IRQ_FRAMEDONE);
1747
1748 if (r)
1749 DSSERR("failed to register FRAMEDONE isr\n");
1750 }
1751
1752 _enable_lcd_out(enable);
1753
1754 if (!enable && is_on) {
1755 if (!wait_for_completion_timeout(&frame_done_completion,
1756 msecs_to_jiffies(100)))
1757 DSSERR("timeout waiting for FRAME DONE\n");
1758
1759 r = omap_dispc_unregister_isr(dispc_disable_isr,
1760 &frame_done_completion,
1761 DISPC_IRQ_FRAMEDONE);
1762
1763 if (r)
1764 DSSERR("failed to unregister FRAMEDONE isr\n");
1765 }
1766
1767 enable_clocks(0);
1768}
1769
1770static void _enable_digit_out(bool enable)
1771{
1772 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
1773}
1774
1775static void dispc_enable_digit_out(bool enable)
1776{
1777 struct completion frame_done_completion;
1778 int r;
1779
1780 enable_clocks(1);
1781
1782 if (REG_GET(DISPC_CONTROL, 1, 1) == enable) {
1783 enable_clocks(0);
1784 return;
1785 }
1786
1787 if (enable) {
1788 unsigned long flags;
1789 /* When we enable digit output, we'll get an extra digit
1790 * sync lost interrupt, that we need to ignore */
1791 spin_lock_irqsave(&dispc.irq_lock, flags);
1792 dispc.irq_error_mask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
1793 _omap_dispc_set_irqs();
1794 spin_unlock_irqrestore(&dispc.irq_lock, flags);
1795 }
1796
1797 /* When we disable digit output, we need to wait until fields are done.
1798 * Otherwise the DSS is still working, and turning off the clocks
1799 * prevents DSS from going to OFF mode. And when enabling, we need to
1800 * wait for the extra sync losts */
1801 init_completion(&frame_done_completion);
1802
1803 r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion,
1804 DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
1805 if (r)
1806 DSSERR("failed to register EVSYNC isr\n");
1807
1808 _enable_digit_out(enable);
1809
1810 /* XXX I understand from TRM that we should only wait for the
1811 * current field to complete. But it seems we have to wait
1812 * for both fields */
1813 if (!wait_for_completion_timeout(&frame_done_completion,
1814 msecs_to_jiffies(100)))
1815 DSSERR("timeout waiting for EVSYNC\n");
1816
1817 if (!wait_for_completion_timeout(&frame_done_completion,
1818 msecs_to_jiffies(100)))
1819 DSSERR("timeout waiting for EVSYNC\n");
1820
1821 r = omap_dispc_unregister_isr(dispc_disable_isr,
1822 &frame_done_completion,
1823 DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
1824 if (r)
1825 DSSERR("failed to unregister EVSYNC isr\n");
1826
1827 if (enable) {
1828 unsigned long flags;
1829 spin_lock_irqsave(&dispc.irq_lock, flags);
1830 dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
1831 dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
1832 _omap_dispc_set_irqs();
1833 spin_unlock_irqrestore(&dispc.irq_lock, flags);
1834 }
1835
1836 enable_clocks(0);
1837}
1838
1839bool dispc_is_channel_enabled(enum omap_channel channel)
1840{
1841 if (channel == OMAP_DSS_CHANNEL_LCD)
1842 return !!REG_GET(DISPC_CONTROL, 0, 0);
1843 else if (channel == OMAP_DSS_CHANNEL_DIGIT)
1844 return !!REG_GET(DISPC_CONTROL, 1, 1);
1845 else
1846 BUG();
1847}
1848
1849void dispc_enable_channel(enum omap_channel channel, bool enable)
1850{
1851 if (channel == OMAP_DSS_CHANNEL_LCD)
1852 dispc_enable_lcd_out(enable);
1853 else if (channel == OMAP_DSS_CHANNEL_DIGIT)
1854 dispc_enable_digit_out(enable);
1855 else
1856 BUG();
1857}
1858
1859void dispc_lcd_enable_signal_polarity(bool act_high)
1860{
1861 enable_clocks(1);
1862 REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
1863 enable_clocks(0);
1864}
1865
1866void dispc_lcd_enable_signal(bool enable)
1867{
1868 enable_clocks(1);
1869 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
1870 enable_clocks(0);
1871}
1872
1873void dispc_pck_free_enable(bool enable)
1874{
1875 enable_clocks(1);
1876 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
1877 enable_clocks(0);
1878}
1879
1880void dispc_enable_fifohandcheck(bool enable)
1881{
1882 enable_clocks(1);
1883 REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16);
1884 enable_clocks(0);
1885}
1886
1887
1888void dispc_set_lcd_display_type(enum omap_lcd_display_type type)
1889{
1890 int mode;
1891
1892 switch (type) {
1893 case OMAP_DSS_LCD_DISPLAY_STN:
1894 mode = 0;
1895 break;
1896
1897 case OMAP_DSS_LCD_DISPLAY_TFT:
1898 mode = 1;
1899 break;
1900
1901 default:
1902 BUG();
1903 return;
1904 }
1905
1906 enable_clocks(1);
1907 REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3);
1908 enable_clocks(0);
1909}
1910
1911void dispc_set_loadmode(enum omap_dss_load_mode mode)
1912{
1913 enable_clocks(1);
1914 REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1);
1915 enable_clocks(0);
1916}
1917
1918
1919void dispc_set_default_color(enum omap_channel channel, u32 color)
1920{
1921 const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0,
1922 DISPC_DEFAULT_COLOR1 };
1923
1924 enable_clocks(1);
1925 dispc_write_reg(def_reg[channel], color);
1926 enable_clocks(0);
1927}
1928
1929u32 dispc_get_default_color(enum omap_channel channel)
1930{
1931 const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0,
1932 DISPC_DEFAULT_COLOR1 };
1933 u32 l;
1934
1935 BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT &&
1936 channel != OMAP_DSS_CHANNEL_LCD);
1937
1938 enable_clocks(1);
1939 l = dispc_read_reg(def_reg[channel]);
1940 enable_clocks(0);
1941
1942 return l;
1943}
1944
1945void dispc_set_trans_key(enum omap_channel ch,
1946 enum omap_dss_trans_key_type type,
1947 u32 trans_key)
1948{
1949 const struct dispc_reg tr_reg[] = {
1950 DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 };
1951
1952 enable_clocks(1);
1953 if (ch == OMAP_DSS_CHANNEL_LCD)
1954 REG_FLD_MOD(DISPC_CONFIG, type, 11, 11);
1955 else /* OMAP_DSS_CHANNEL_DIGIT */
1956 REG_FLD_MOD(DISPC_CONFIG, type, 13, 13);
1957
1958 dispc_write_reg(tr_reg[ch], trans_key);
1959 enable_clocks(0);
1960}
1961
1962void dispc_get_trans_key(enum omap_channel ch,
1963 enum omap_dss_trans_key_type *type,
1964 u32 *trans_key)
1965{
1966 const struct dispc_reg tr_reg[] = {
1967 DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 };
1968
1969 enable_clocks(1);
1970 if (type) {
1971 if (ch == OMAP_DSS_CHANNEL_LCD)
1972 *type = REG_GET(DISPC_CONFIG, 11, 11);
1973 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
1974 *type = REG_GET(DISPC_CONFIG, 13, 13);
1975 else
1976 BUG();
1977 }
1978
1979 if (trans_key)
1980 *trans_key = dispc_read_reg(tr_reg[ch]);
1981 enable_clocks(0);
1982}
1983
1984void dispc_enable_trans_key(enum omap_channel ch, bool enable)
1985{
1986 enable_clocks(1);
1987 if (ch == OMAP_DSS_CHANNEL_LCD)
1988 REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
1989 else /* OMAP_DSS_CHANNEL_DIGIT */
1990 REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12);
1991 enable_clocks(0);
1992}
1993void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
1994{
1995 if (cpu_is_omap24xx())
1996 return;
1997
1998 enable_clocks(1);
1999 if (ch == OMAP_DSS_CHANNEL_LCD)
2000 REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
2001 else /* OMAP_DSS_CHANNEL_DIGIT */
2002 REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
2003 enable_clocks(0);
2004}
2005bool dispc_alpha_blending_enabled(enum omap_channel ch)
2006{
2007 bool enabled;
2008
2009 if (cpu_is_omap24xx())
2010 return false;
2011
2012 enable_clocks(1);
2013 if (ch == OMAP_DSS_CHANNEL_LCD)
2014 enabled = REG_GET(DISPC_CONFIG, 18, 18);
2015 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
2016 enabled = REG_GET(DISPC_CONFIG, 18, 18);
2017 else
2018 BUG();
2019 enable_clocks(0);
2020
2021 return enabled;
2022
2023}
2024
2025
2026bool dispc_trans_key_enabled(enum omap_channel ch)
2027{
2028 bool enabled;
2029
2030 enable_clocks(1);
2031 if (ch == OMAP_DSS_CHANNEL_LCD)
2032 enabled = REG_GET(DISPC_CONFIG, 10, 10);
2033 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
2034 enabled = REG_GET(DISPC_CONFIG, 12, 12);
2035 else
2036 BUG();
2037 enable_clocks(0);
2038
2039 return enabled;
2040}
2041
2042
2043void dispc_set_tft_data_lines(u8 data_lines)
2044{
2045 int code;
2046
2047 switch (data_lines) {
2048 case 12:
2049 code = 0;
2050 break;
2051 case 16:
2052 code = 1;
2053 break;
2054 case 18:
2055 code = 2;
2056 break;
2057 case 24:
2058 code = 3;
2059 break;
2060 default:
2061 BUG();
2062 return;
2063 }
2064
2065 enable_clocks(1);
2066 REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
2067 enable_clocks(0);
2068}
2069
2070void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode)
2071{
2072 u32 l;
2073 int stallmode;
2074 int gpout0 = 1;
2075 int gpout1;
2076
2077 switch (mode) {
2078 case OMAP_DSS_PARALLELMODE_BYPASS:
2079 stallmode = 0;
2080 gpout1 = 1;
2081 break;
2082
2083 case OMAP_DSS_PARALLELMODE_RFBI:
2084 stallmode = 1;
2085 gpout1 = 0;
2086 break;
2087
2088 case OMAP_DSS_PARALLELMODE_DSI:
2089 stallmode = 1;
2090 gpout1 = 1;
2091 break;
2092
2093 default:
2094 BUG();
2095 return;
2096 }
2097
2098 enable_clocks(1);
2099
2100 l = dispc_read_reg(DISPC_CONTROL);
2101
2102 l = FLD_MOD(l, stallmode, 11, 11);
2103 l = FLD_MOD(l, gpout0, 15, 15);
2104 l = FLD_MOD(l, gpout1, 16, 16);
2105
2106 dispc_write_reg(DISPC_CONTROL, l);
2107
2108 enable_clocks(0);
2109}
2110
2111static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
2112 int vsw, int vfp, int vbp)
2113{
2114 if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
2115 if (hsw < 1 || hsw > 64 ||
2116 hfp < 1 || hfp > 256 ||
2117 hbp < 1 || hbp > 256 ||
2118 vsw < 1 || vsw > 64 ||
2119 vfp < 0 || vfp > 255 ||
2120 vbp < 0 || vbp > 255)
2121 return false;
2122 } else {
2123 if (hsw < 1 || hsw > 256 ||
2124 hfp < 1 || hfp > 4096 ||
2125 hbp < 1 || hbp > 4096 ||
2126 vsw < 1 || vsw > 256 ||
2127 vfp < 0 || vfp > 4095 ||
2128 vbp < 0 || vbp > 4095)
2129 return false;
2130 }
2131
2132 return true;
2133}
2134
2135bool dispc_lcd_timings_ok(struct omap_video_timings *timings)
2136{
2137 return _dispc_lcd_timings_ok(timings->hsw, timings->hfp,
2138 timings->hbp, timings->vsw,
2139 timings->vfp, timings->vbp);
2140}
2141
2142static void _dispc_set_lcd_timings(int hsw, int hfp, int hbp,
2143 int vsw, int vfp, int vbp)
2144{
2145 u32 timing_h, timing_v;
2146
2147 if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
2148 timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) |
2149 FLD_VAL(hbp-1, 27, 20);
2150
2151 timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) |
2152 FLD_VAL(vbp, 27, 20);
2153 } else {
2154 timing_h = FLD_VAL(hsw-1, 7, 0) | FLD_VAL(hfp-1, 19, 8) |
2155 FLD_VAL(hbp-1, 31, 20);
2156
2157 timing_v = FLD_VAL(vsw-1, 7, 0) | FLD_VAL(vfp, 19, 8) |
2158 FLD_VAL(vbp, 31, 20);
2159 }
2160
2161 enable_clocks(1);
2162 dispc_write_reg(DISPC_TIMING_H, timing_h);
2163 dispc_write_reg(DISPC_TIMING_V, timing_v);
2164 enable_clocks(0);
2165}
2166
2167/* change name to mode? */
2168void dispc_set_lcd_timings(struct omap_video_timings *timings)
2169{
2170 unsigned xtot, ytot;
2171 unsigned long ht, vt;
2172
2173 if (!_dispc_lcd_timings_ok(timings->hsw, timings->hfp,
2174 timings->hbp, timings->vsw,
2175 timings->vfp, timings->vbp))
2176 BUG();
2177
2178 _dispc_set_lcd_timings(timings->hsw, timings->hfp, timings->hbp,
2179 timings->vsw, timings->vfp, timings->vbp);
2180
2181 dispc_set_lcd_size(timings->x_res, timings->y_res);
2182
2183 xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp;
2184 ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp;
2185
2186 ht = (timings->pixel_clock * 1000) / xtot;
2187 vt = (timings->pixel_clock * 1000) / xtot / ytot;
2188
2189 DSSDBG("xres %u yres %u\n", timings->x_res, timings->y_res);
2190 DSSDBG("pck %u\n", timings->pixel_clock);
2191 DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n",
2192 timings->hsw, timings->hfp, timings->hbp,
2193 timings->vsw, timings->vfp, timings->vbp);
2194
2195 DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt);
2196}
2197
2198static void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div)
2199{
2200 BUG_ON(lck_div < 1);
2201 BUG_ON(pck_div < 2);
2202
2203 enable_clocks(1);
2204 dispc_write_reg(DISPC_DIVISOR,
2205 FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
2206 enable_clocks(0);
2207}
2208
2209static void dispc_get_lcd_divisor(int *lck_div, int *pck_div)
2210{
2211 u32 l;
2212 l = dispc_read_reg(DISPC_DIVISOR);
2213 *lck_div = FLD_GET(l, 23, 16);
2214 *pck_div = FLD_GET(l, 7, 0);
2215}
2216
2217unsigned long dispc_fclk_rate(void)
2218{
2219 unsigned long r = 0;
2220
2221 if (dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK)
2222 r = dss_clk_get_rate(DSS_CLK_FCK1);
2223 else
2224#ifdef CONFIG_OMAP2_DSS_DSI
2225 r = dsi_get_dsi1_pll_rate();
2226#else
2227 BUG();
2228#endif
2229 return r;
2230}
2231
2232unsigned long dispc_lclk_rate(void)
2233{
2234 int lcd;
2235 unsigned long r;
2236 u32 l;
2237
2238 l = dispc_read_reg(DISPC_DIVISOR);
2239
2240 lcd = FLD_GET(l, 23, 16);
2241
2242 r = dispc_fclk_rate();
2243
2244 return r / lcd;
2245}
2246
2247unsigned long dispc_pclk_rate(void)
2248{
2249 int lcd, pcd;
2250 unsigned long r;
2251 u32 l;
2252
2253 l = dispc_read_reg(DISPC_DIVISOR);
2254
2255 lcd = FLD_GET(l, 23, 16);
2256 pcd = FLD_GET(l, 7, 0);
2257
2258 r = dispc_fclk_rate();
2259
2260 return r / lcd / pcd;
2261}
2262
2263void dispc_dump_clocks(struct seq_file *s)
2264{
2265 int lcd, pcd;
2266
2267 enable_clocks(1);
2268
2269 dispc_get_lcd_divisor(&lcd, &pcd);
2270
2271 seq_printf(s, "- DISPC -\n");
2272
2273 seq_printf(s, "dispc fclk source = %s\n",
2274 dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ?
2275 "dss1_alwon_fclk" : "dsi1_pll_fclk");
2276
2277 seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate());
2278 seq_printf(s, "lck\t\t%-16lulck div\t%u\n", dispc_lclk_rate(), lcd);
2279 seq_printf(s, "pck\t\t%-16lupck div\t%u\n", dispc_pclk_rate(), pcd);
2280
2281 enable_clocks(0);
2282}
2283
2284#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
2285void dispc_dump_irqs(struct seq_file *s)
2286{
2287 unsigned long flags;
2288 struct dispc_irq_stats stats;
2289
2290 spin_lock_irqsave(&dispc.irq_stats_lock, flags);
2291
2292 stats = dispc.irq_stats;
2293 memset(&dispc.irq_stats, 0, sizeof(dispc.irq_stats));
2294 dispc.irq_stats.last_reset = jiffies;
2295
2296 spin_unlock_irqrestore(&dispc.irq_stats_lock, flags);
2297
2298 seq_printf(s, "period %u ms\n",
2299 jiffies_to_msecs(jiffies - stats.last_reset));
2300
2301 seq_printf(s, "irqs %d\n", stats.irq_count);
2302#define PIS(x) \
2303 seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]);
2304
2305 PIS(FRAMEDONE);
2306 PIS(VSYNC);
2307 PIS(EVSYNC_EVEN);
2308 PIS(EVSYNC_ODD);
2309 PIS(ACBIAS_COUNT_STAT);
2310 PIS(PROG_LINE_NUM);
2311 PIS(GFX_FIFO_UNDERFLOW);
2312 PIS(GFX_END_WIN);
2313 PIS(PAL_GAMMA_MASK);
2314 PIS(OCP_ERR);
2315 PIS(VID1_FIFO_UNDERFLOW);
2316 PIS(VID1_END_WIN);
2317 PIS(VID2_FIFO_UNDERFLOW);
2318 PIS(VID2_END_WIN);
2319 PIS(SYNC_LOST);
2320 PIS(SYNC_LOST_DIGIT);
2321 PIS(WAKEUP);
2322#undef PIS
2323}
2324#endif
2325
2326void dispc_dump_regs(struct seq_file *s)
2327{
2328#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r))
2329
2330 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
2331
2332 DUMPREG(DISPC_REVISION);
2333 DUMPREG(DISPC_SYSCONFIG);
2334 DUMPREG(DISPC_SYSSTATUS);
2335 DUMPREG(DISPC_IRQSTATUS);
2336 DUMPREG(DISPC_IRQENABLE);
2337 DUMPREG(DISPC_CONTROL);
2338 DUMPREG(DISPC_CONFIG);
2339 DUMPREG(DISPC_CAPABLE);
2340 DUMPREG(DISPC_DEFAULT_COLOR0);
2341 DUMPREG(DISPC_DEFAULT_COLOR1);
2342 DUMPREG(DISPC_TRANS_COLOR0);
2343 DUMPREG(DISPC_TRANS_COLOR1);
2344 DUMPREG(DISPC_LINE_STATUS);
2345 DUMPREG(DISPC_LINE_NUMBER);
2346 DUMPREG(DISPC_TIMING_H);
2347 DUMPREG(DISPC_TIMING_V);
2348 DUMPREG(DISPC_POL_FREQ);
2349 DUMPREG(DISPC_DIVISOR);
2350 DUMPREG(DISPC_GLOBAL_ALPHA);
2351 DUMPREG(DISPC_SIZE_DIG);
2352 DUMPREG(DISPC_SIZE_LCD);
2353
2354 DUMPREG(DISPC_GFX_BA0);
2355 DUMPREG(DISPC_GFX_BA1);
2356 DUMPREG(DISPC_GFX_POSITION);
2357 DUMPREG(DISPC_GFX_SIZE);
2358 DUMPREG(DISPC_GFX_ATTRIBUTES);
2359 DUMPREG(DISPC_GFX_FIFO_THRESHOLD);
2360 DUMPREG(DISPC_GFX_FIFO_SIZE_STATUS);
2361 DUMPREG(DISPC_GFX_ROW_INC);
2362 DUMPREG(DISPC_GFX_PIXEL_INC);
2363 DUMPREG(DISPC_GFX_WINDOW_SKIP);
2364 DUMPREG(DISPC_GFX_TABLE_BA);
2365
2366 DUMPREG(DISPC_DATA_CYCLE1);
2367 DUMPREG(DISPC_DATA_CYCLE2);
2368 DUMPREG(DISPC_DATA_CYCLE3);
2369
2370 DUMPREG(DISPC_CPR_COEF_R);
2371 DUMPREG(DISPC_CPR_COEF_G);
2372 DUMPREG(DISPC_CPR_COEF_B);
2373
2374 DUMPREG(DISPC_GFX_PRELOAD);
2375
2376 DUMPREG(DISPC_VID_BA0(0));
2377 DUMPREG(DISPC_VID_BA1(0));
2378 DUMPREG(DISPC_VID_POSITION(0));
2379 DUMPREG(DISPC_VID_SIZE(0));
2380 DUMPREG(DISPC_VID_ATTRIBUTES(0));
2381 DUMPREG(DISPC_VID_FIFO_THRESHOLD(0));
2382 DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(0));
2383 DUMPREG(DISPC_VID_ROW_INC(0));
2384 DUMPREG(DISPC_VID_PIXEL_INC(0));
2385 DUMPREG(DISPC_VID_FIR(0));
2386 DUMPREG(DISPC_VID_PICTURE_SIZE(0));
2387 DUMPREG(DISPC_VID_ACCU0(0));
2388 DUMPREG(DISPC_VID_ACCU1(0));
2389
2390 DUMPREG(DISPC_VID_BA0(1));
2391 DUMPREG(DISPC_VID_BA1(1));
2392 DUMPREG(DISPC_VID_POSITION(1));
2393 DUMPREG(DISPC_VID_SIZE(1));
2394 DUMPREG(DISPC_VID_ATTRIBUTES(1));
2395 DUMPREG(DISPC_VID_FIFO_THRESHOLD(1));
2396 DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(1));
2397 DUMPREG(DISPC_VID_ROW_INC(1));
2398 DUMPREG(DISPC_VID_PIXEL_INC(1));
2399 DUMPREG(DISPC_VID_FIR(1));
2400 DUMPREG(DISPC_VID_PICTURE_SIZE(1));
2401 DUMPREG(DISPC_VID_ACCU0(1));
2402 DUMPREG(DISPC_VID_ACCU1(1));
2403
2404 DUMPREG(DISPC_VID_FIR_COEF_H(0, 0));
2405 DUMPREG(DISPC_VID_FIR_COEF_H(0, 1));
2406 DUMPREG(DISPC_VID_FIR_COEF_H(0, 2));
2407 DUMPREG(DISPC_VID_FIR_COEF_H(0, 3));
2408 DUMPREG(DISPC_VID_FIR_COEF_H(0, 4));
2409 DUMPREG(DISPC_VID_FIR_COEF_H(0, 5));
2410 DUMPREG(DISPC_VID_FIR_COEF_H(0, 6));
2411 DUMPREG(DISPC_VID_FIR_COEF_H(0, 7));
2412 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 0));
2413 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 1));
2414 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 2));
2415 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 3));
2416 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 4));
2417 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 5));
2418 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 6));
2419 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 7));
2420 DUMPREG(DISPC_VID_CONV_COEF(0, 0));
2421 DUMPREG(DISPC_VID_CONV_COEF(0, 1));
2422 DUMPREG(DISPC_VID_CONV_COEF(0, 2));
2423 DUMPREG(DISPC_VID_CONV_COEF(0, 3));
2424 DUMPREG(DISPC_VID_CONV_COEF(0, 4));
2425 DUMPREG(DISPC_VID_FIR_COEF_V(0, 0));
2426 DUMPREG(DISPC_VID_FIR_COEF_V(0, 1));
2427 DUMPREG(DISPC_VID_FIR_COEF_V(0, 2));
2428 DUMPREG(DISPC_VID_FIR_COEF_V(0, 3));
2429 DUMPREG(DISPC_VID_FIR_COEF_V(0, 4));
2430 DUMPREG(DISPC_VID_FIR_COEF_V(0, 5));
2431 DUMPREG(DISPC_VID_FIR_COEF_V(0, 6));
2432 DUMPREG(DISPC_VID_FIR_COEF_V(0, 7));
2433
2434 DUMPREG(DISPC_VID_FIR_COEF_H(1, 0));
2435 DUMPREG(DISPC_VID_FIR_COEF_H(1, 1));
2436 DUMPREG(DISPC_VID_FIR_COEF_H(1, 2));
2437 DUMPREG(DISPC_VID_FIR_COEF_H(1, 3));
2438 DUMPREG(DISPC_VID_FIR_COEF_H(1, 4));
2439 DUMPREG(DISPC_VID_FIR_COEF_H(1, 5));
2440 DUMPREG(DISPC_VID_FIR_COEF_H(1, 6));
2441 DUMPREG(DISPC_VID_FIR_COEF_H(1, 7));
2442 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 0));
2443 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 1));
2444 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 2));
2445 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 3));
2446 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 4));
2447 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 5));
2448 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 6));
2449 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 7));
2450 DUMPREG(DISPC_VID_CONV_COEF(1, 0));
2451 DUMPREG(DISPC_VID_CONV_COEF(1, 1));
2452 DUMPREG(DISPC_VID_CONV_COEF(1, 2));
2453 DUMPREG(DISPC_VID_CONV_COEF(1, 3));
2454 DUMPREG(DISPC_VID_CONV_COEF(1, 4));
2455 DUMPREG(DISPC_VID_FIR_COEF_V(1, 0));
2456 DUMPREG(DISPC_VID_FIR_COEF_V(1, 1));
2457 DUMPREG(DISPC_VID_FIR_COEF_V(1, 2));
2458 DUMPREG(DISPC_VID_FIR_COEF_V(1, 3));
2459 DUMPREG(DISPC_VID_FIR_COEF_V(1, 4));
2460 DUMPREG(DISPC_VID_FIR_COEF_V(1, 5));
2461 DUMPREG(DISPC_VID_FIR_COEF_V(1, 6));
2462 DUMPREG(DISPC_VID_FIR_COEF_V(1, 7));
2463
2464 DUMPREG(DISPC_VID_PRELOAD(0));
2465 DUMPREG(DISPC_VID_PRELOAD(1));
2466
2467 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
2468#undef DUMPREG
2469}
2470
2471static void _dispc_set_pol_freq(bool onoff, bool rf, bool ieo, bool ipc,
2472 bool ihs, bool ivs, u8 acbi, u8 acb)
2473{
2474 u32 l = 0;
2475
2476 DSSDBG("onoff %d rf %d ieo %d ipc %d ihs %d ivs %d acbi %d acb %d\n",
2477 onoff, rf, ieo, ipc, ihs, ivs, acbi, acb);
2478
2479 l |= FLD_VAL(onoff, 17, 17);
2480 l |= FLD_VAL(rf, 16, 16);
2481 l |= FLD_VAL(ieo, 15, 15);
2482 l |= FLD_VAL(ipc, 14, 14);
2483 l |= FLD_VAL(ihs, 13, 13);
2484 l |= FLD_VAL(ivs, 12, 12);
2485 l |= FLD_VAL(acbi, 11, 8);
2486 l |= FLD_VAL(acb, 7, 0);
2487
2488 enable_clocks(1);
2489 dispc_write_reg(DISPC_POL_FREQ, l);
2490 enable_clocks(0);
2491}
2492
2493void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb)
2494{
2495 _dispc_set_pol_freq((config & OMAP_DSS_LCD_ONOFF) != 0,
2496 (config & OMAP_DSS_LCD_RF) != 0,
2497 (config & OMAP_DSS_LCD_IEO) != 0,
2498 (config & OMAP_DSS_LCD_IPC) != 0,
2499 (config & OMAP_DSS_LCD_IHS) != 0,
2500 (config & OMAP_DSS_LCD_IVS) != 0,
2501 acbi, acb);
2502}
2503
2504/* with fck as input clock rate, find dispc dividers that produce req_pck */
2505void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
2506 struct dispc_clock_info *cinfo)
2507{
2508 u16 pcd_min = is_tft ? 2 : 3;
2509 unsigned long best_pck;
2510 u16 best_ld, cur_ld;
2511 u16 best_pd, cur_pd;
2512
2513 best_pck = 0;
2514 best_ld = 0;
2515 best_pd = 0;
2516
2517 for (cur_ld = 1; cur_ld <= 255; ++cur_ld) {
2518 unsigned long lck = fck / cur_ld;
2519
2520 for (cur_pd = pcd_min; cur_pd <= 255; ++cur_pd) {
2521 unsigned long pck = lck / cur_pd;
2522 long old_delta = abs(best_pck - req_pck);
2523 long new_delta = abs(pck - req_pck);
2524
2525 if (best_pck == 0 || new_delta < old_delta) {
2526 best_pck = pck;
2527 best_ld = cur_ld;
2528 best_pd = cur_pd;
2529
2530 if (pck == req_pck)
2531 goto found;
2532 }
2533
2534 if (pck < req_pck)
2535 break;
2536 }
2537
2538 if (lck / pcd_min < req_pck)
2539 break;
2540 }
2541
2542found:
2543 cinfo->lck_div = best_ld;
2544 cinfo->pck_div = best_pd;
2545 cinfo->lck = fck / cinfo->lck_div;
2546 cinfo->pck = cinfo->lck / cinfo->pck_div;
2547}
2548
2549/* calculate clock rates using dividers in cinfo */
2550int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
2551 struct dispc_clock_info *cinfo)
2552{
2553 if (cinfo->lck_div > 255 || cinfo->lck_div == 0)
2554 return -EINVAL;
2555 if (cinfo->pck_div < 2 || cinfo->pck_div > 255)
2556 return -EINVAL;
2557
2558 cinfo->lck = dispc_fclk_rate / cinfo->lck_div;
2559 cinfo->pck = cinfo->lck / cinfo->pck_div;
2560
2561 return 0;
2562}
2563
2564int dispc_set_clock_div(struct dispc_clock_info *cinfo)
2565{
2566 DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div);
2567 DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div);
2568
2569 dispc_set_lcd_divisor(cinfo->lck_div, cinfo->pck_div);
2570
2571 return 0;
2572}
2573
2574int dispc_get_clock_div(struct dispc_clock_info *cinfo)
2575{
2576 unsigned long fck;
2577
2578 fck = dispc_fclk_rate();
2579
2580 cinfo->lck_div = REG_GET(DISPC_DIVISOR, 23, 16);
2581 cinfo->pck_div = REG_GET(DISPC_DIVISOR, 7, 0);
2582
2583 cinfo->lck = fck / cinfo->lck_div;
2584 cinfo->pck = cinfo->lck / cinfo->pck_div;
2585
2586 return 0;
2587}
2588
2589/* dispc.irq_lock has to be locked by the caller */
2590static void _omap_dispc_set_irqs(void)
2591{
2592 u32 mask;
2593 u32 old_mask;
2594 int i;
2595 struct omap_dispc_isr_data *isr_data;
2596
2597 mask = dispc.irq_error_mask;
2598
2599 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
2600 isr_data = &dispc.registered_isr[i];
2601
2602 if (isr_data->isr == NULL)
2603 continue;
2604
2605 mask |= isr_data->mask;
2606 }
2607
2608 enable_clocks(1);
2609
2610 old_mask = dispc_read_reg(DISPC_IRQENABLE);
2611 /* clear the irqstatus for newly enabled irqs */
2612 dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask);
2613
2614 dispc_write_reg(DISPC_IRQENABLE, mask);
2615
2616 enable_clocks(0);
2617}
2618
2619int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
2620{
2621 int i;
2622 int ret;
2623 unsigned long flags;
2624 struct omap_dispc_isr_data *isr_data;
2625
2626 if (isr == NULL)
2627 return -EINVAL;
2628
2629 spin_lock_irqsave(&dispc.irq_lock, flags);
2630
2631 /* check for duplicate entry */
2632 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
2633 isr_data = &dispc.registered_isr[i];
2634 if (isr_data->isr == isr && isr_data->arg == arg &&
2635 isr_data->mask == mask) {
2636 ret = -EINVAL;
2637 goto err;
2638 }
2639 }
2640
2641 isr_data = NULL;
2642 ret = -EBUSY;
2643
2644 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
2645 isr_data = &dispc.registered_isr[i];
2646
2647 if (isr_data->isr != NULL)
2648 continue;
2649
2650 isr_data->isr = isr;
2651 isr_data->arg = arg;
2652 isr_data->mask = mask;
2653 ret = 0;
2654
2655 break;
2656 }
2657
2658 _omap_dispc_set_irqs();
2659
2660 spin_unlock_irqrestore(&dispc.irq_lock, flags);
2661
2662 return 0;
2663err:
2664 spin_unlock_irqrestore(&dispc.irq_lock, flags);
2665
2666 return ret;
2667}
2668EXPORT_SYMBOL(omap_dispc_register_isr);
2669
2670int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
2671{
2672 int i;
2673 unsigned long flags;
2674 int ret = -EINVAL;
2675 struct omap_dispc_isr_data *isr_data;
2676
2677 spin_lock_irqsave(&dispc.irq_lock, flags);
2678
2679 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
2680 isr_data = &dispc.registered_isr[i];
2681 if (isr_data->isr != isr || isr_data->arg != arg ||
2682 isr_data->mask != mask)
2683 continue;
2684
2685 /* found the correct isr */
2686
2687 isr_data->isr = NULL;
2688 isr_data->arg = NULL;
2689 isr_data->mask = 0;
2690
2691 ret = 0;
2692 break;
2693 }
2694
2695 if (ret == 0)
2696 _omap_dispc_set_irqs();
2697
2698 spin_unlock_irqrestore(&dispc.irq_lock, flags);
2699
2700 return ret;
2701}
2702EXPORT_SYMBOL(omap_dispc_unregister_isr);
2703
2704#ifdef DEBUG
2705static void print_irq_status(u32 status)
2706{
2707 if ((status & dispc.irq_error_mask) == 0)
2708 return;
2709
2710 printk(KERN_DEBUG "DISPC IRQ: 0x%x: ", status);
2711
2712#define PIS(x) \
2713 if (status & DISPC_IRQ_##x) \
2714 printk(#x " ");
2715 PIS(GFX_FIFO_UNDERFLOW);
2716 PIS(OCP_ERR);
2717 PIS(VID1_FIFO_UNDERFLOW);
2718 PIS(VID2_FIFO_UNDERFLOW);
2719 PIS(SYNC_LOST);
2720 PIS(SYNC_LOST_DIGIT);
2721#undef PIS
2722
2723 printk("\n");
2724}
2725#endif
2726
2727/* Called from dss.c. Note that we don't touch clocks here,
2728 * but we presume they are on because we got an IRQ. However,
2729 * an irq handler may turn the clocks off, so we may not have
2730 * clock later in the function. */
2731void dispc_irq_handler(void)
2732{
2733 int i;
2734 u32 irqstatus;
2735 u32 handledirqs = 0;
2736 u32 unhandled_errors;
2737 struct omap_dispc_isr_data *isr_data;
2738 struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
2739
2740 spin_lock(&dispc.irq_lock);
2741
2742 irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
2743
2744#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
2745 spin_lock(&dispc.irq_stats_lock);
2746 dispc.irq_stats.irq_count++;
2747 dss_collect_irq_stats(irqstatus, dispc.irq_stats.irqs);
2748 spin_unlock(&dispc.irq_stats_lock);
2749#endif
2750
2751#ifdef DEBUG
2752 if (dss_debug)
2753 print_irq_status(irqstatus);
2754#endif
2755 /* Ack the interrupt. Do it here before clocks are possibly turned
2756 * off */
2757 dispc_write_reg(DISPC_IRQSTATUS, irqstatus);
2758 /* flush posted write */
2759 dispc_read_reg(DISPC_IRQSTATUS);
2760
2761 /* make a copy and unlock, so that isrs can unregister
2762 * themselves */
2763 memcpy(registered_isr, dispc.registered_isr,
2764 sizeof(registered_isr));
2765
2766 spin_unlock(&dispc.irq_lock);
2767
2768 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
2769 isr_data = &registered_isr[i];
2770
2771 if (!isr_data->isr)
2772 continue;
2773
2774 if (isr_data->mask & irqstatus) {
2775 isr_data->isr(isr_data->arg, irqstatus);
2776 handledirqs |= isr_data->mask;
2777 }
2778 }
2779
2780 spin_lock(&dispc.irq_lock);
2781
2782 unhandled_errors = irqstatus & ~handledirqs & dispc.irq_error_mask;
2783
2784 if (unhandled_errors) {
2785 dispc.error_irqs |= unhandled_errors;
2786
2787 dispc.irq_error_mask &= ~unhandled_errors;
2788 _omap_dispc_set_irqs();
2789
2790 schedule_work(&dispc.error_work);
2791 }
2792
2793 spin_unlock(&dispc.irq_lock);
2794}
2795
2796static void dispc_error_worker(struct work_struct *work)
2797{
2798 int i;
2799 u32 errors;
2800 unsigned long flags;
2801
2802 spin_lock_irqsave(&dispc.irq_lock, flags);
2803 errors = dispc.error_irqs;
2804 dispc.error_irqs = 0;
2805 spin_unlock_irqrestore(&dispc.irq_lock, flags);
2806
2807 if (errors & DISPC_IRQ_GFX_FIFO_UNDERFLOW) {
2808 DSSERR("GFX_FIFO_UNDERFLOW, disabling GFX\n");
2809 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
2810 struct omap_overlay *ovl;
2811 ovl = omap_dss_get_overlay(i);
2812
2813 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
2814 continue;
2815
2816 if (ovl->id == 0) {
2817 dispc_enable_plane(ovl->id, 0);
2818 dispc_go(ovl->manager->id);
2819 mdelay(50);
2820 break;
2821 }
2822 }
2823 }
2824
2825 if (errors & DISPC_IRQ_VID1_FIFO_UNDERFLOW) {
2826 DSSERR("VID1_FIFO_UNDERFLOW, disabling VID1\n");
2827 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
2828 struct omap_overlay *ovl;
2829 ovl = omap_dss_get_overlay(i);
2830
2831 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
2832 continue;
2833
2834 if (ovl->id == 1) {
2835 dispc_enable_plane(ovl->id, 0);
2836 dispc_go(ovl->manager->id);
2837 mdelay(50);
2838 break;
2839 }
2840 }
2841 }
2842
2843 if (errors & DISPC_IRQ_VID2_FIFO_UNDERFLOW) {
2844 DSSERR("VID2_FIFO_UNDERFLOW, disabling VID2\n");
2845 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
2846 struct omap_overlay *ovl;
2847 ovl = omap_dss_get_overlay(i);
2848
2849 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
2850 continue;
2851
2852 if (ovl->id == 2) {
2853 dispc_enable_plane(ovl->id, 0);
2854 dispc_go(ovl->manager->id);
2855 mdelay(50);
2856 break;
2857 }
2858 }
2859 }
2860
2861 if (errors & DISPC_IRQ_SYNC_LOST) {
2862 struct omap_overlay_manager *manager = NULL;
2863 bool enable = false;
2864
2865 DSSERR("SYNC_LOST, disabling LCD\n");
2866
2867 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
2868 struct omap_overlay_manager *mgr;
2869 mgr = omap_dss_get_overlay_manager(i);
2870
2871 if (mgr->id == OMAP_DSS_CHANNEL_LCD) {
2872 manager = mgr;
2873 enable = mgr->device->state ==
2874 OMAP_DSS_DISPLAY_ACTIVE;
2875 mgr->device->driver->disable(mgr->device);
2876 break;
2877 }
2878 }
2879
2880 if (manager) {
2881 struct omap_dss_device *dssdev = manager->device;
2882 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
2883 struct omap_overlay *ovl;
2884 ovl = omap_dss_get_overlay(i);
2885
2886 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
2887 continue;
2888
2889 if (ovl->id != 0 && ovl->manager == manager)
2890 dispc_enable_plane(ovl->id, 0);
2891 }
2892
2893 dispc_go(manager->id);
2894 mdelay(50);
2895 if (enable)
2896 dssdev->driver->enable(dssdev);
2897 }
2898 }
2899
2900 if (errors & DISPC_IRQ_SYNC_LOST_DIGIT) {
2901 struct omap_overlay_manager *manager = NULL;
2902 bool enable = false;
2903
2904 DSSERR("SYNC_LOST_DIGIT, disabling TV\n");
2905
2906 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
2907 struct omap_overlay_manager *mgr;
2908 mgr = omap_dss_get_overlay_manager(i);
2909
2910 if (mgr->id == OMAP_DSS_CHANNEL_DIGIT) {
2911 manager = mgr;
2912 enable = mgr->device->state ==
2913 OMAP_DSS_DISPLAY_ACTIVE;
2914 mgr->device->driver->disable(mgr->device);
2915 break;
2916 }
2917 }
2918
2919 if (manager) {
2920 struct omap_dss_device *dssdev = manager->device;
2921 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
2922 struct omap_overlay *ovl;
2923 ovl = omap_dss_get_overlay(i);
2924
2925 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
2926 continue;
2927
2928 if (ovl->id != 0 && ovl->manager == manager)
2929 dispc_enable_plane(ovl->id, 0);
2930 }
2931
2932 dispc_go(manager->id);
2933 mdelay(50);
2934 if (enable)
2935 dssdev->driver->enable(dssdev);
2936 }
2937 }
2938
2939 if (errors & DISPC_IRQ_OCP_ERR) {
2940 DSSERR("OCP_ERR\n");
2941 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
2942 struct omap_overlay_manager *mgr;
2943 mgr = omap_dss_get_overlay_manager(i);
2944
2945 if (mgr->caps & OMAP_DSS_OVL_CAP_DISPC)
2946 mgr->device->driver->disable(mgr->device);
2947 }
2948 }
2949
2950 spin_lock_irqsave(&dispc.irq_lock, flags);
2951 dispc.irq_error_mask |= errors;
2952 _omap_dispc_set_irqs();
2953 spin_unlock_irqrestore(&dispc.irq_lock, flags);
2954}
2955
2956int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout)
2957{
2958 void dispc_irq_wait_handler(void *data, u32 mask)
2959 {
2960 complete((struct completion *)data);
2961 }
2962
2963 int r;
2964 DECLARE_COMPLETION_ONSTACK(completion);
2965
2966 r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
2967 irqmask);
2968
2969 if (r)
2970 return r;
2971
2972 timeout = wait_for_completion_timeout(&completion, timeout);
2973
2974 omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
2975
2976 if (timeout == 0)
2977 return -ETIMEDOUT;
2978
2979 if (timeout == -ERESTARTSYS)
2980 return -ERESTARTSYS;
2981
2982 return 0;
2983}
2984
2985int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
2986 unsigned long timeout)
2987{
2988 void dispc_irq_wait_handler(void *data, u32 mask)
2989 {
2990 complete((struct completion *)data);
2991 }
2992
2993 int r;
2994 DECLARE_COMPLETION_ONSTACK(completion);
2995
2996 r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
2997 irqmask);
2998
2999 if (r)
3000 return r;
3001
3002 timeout = wait_for_completion_interruptible_timeout(&completion,
3003 timeout);
3004
3005 omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
3006
3007 if (timeout == 0)
3008 return -ETIMEDOUT;
3009
3010 if (timeout == -ERESTARTSYS)
3011 return -ERESTARTSYS;
3012
3013 return 0;
3014}
3015
3016#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
3017void dispc_fake_vsync_irq(void)
3018{
3019 u32 irqstatus = DISPC_IRQ_VSYNC;
3020 int i;
3021
3022 local_irq_disable();
3023
3024 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
3025 struct omap_dispc_isr_data *isr_data;
3026 isr_data = &dispc.registered_isr[i];
3027
3028 if (!isr_data->isr)
3029 continue;
3030
3031 if (isr_data->mask & irqstatus)
3032 isr_data->isr(isr_data->arg, irqstatus);
3033 }
3034
3035 local_irq_enable();
3036}
3037#endif
3038
3039static void _omap_dispc_initialize_irq(void)
3040{
3041 unsigned long flags;
3042
3043 spin_lock_irqsave(&dispc.irq_lock, flags);
3044
3045 memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr));
3046
3047 dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
3048
3049 /* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
3050 * so clear it */
3051 dispc_write_reg(DISPC_IRQSTATUS, dispc_read_reg(DISPC_IRQSTATUS));
3052
3053 _omap_dispc_set_irqs();
3054
3055 spin_unlock_irqrestore(&dispc.irq_lock, flags);
3056}
3057
3058void dispc_enable_sidle(void)
3059{
3060 REG_FLD_MOD(DISPC_SYSCONFIG, 2, 4, 3); /* SIDLEMODE: smart idle */
3061}
3062
3063void dispc_disable_sidle(void)
3064{
3065 REG_FLD_MOD(DISPC_SYSCONFIG, 1, 4, 3); /* SIDLEMODE: no idle */
3066}
3067
3068static void _omap_dispc_initial_config(void)
3069{
3070 u32 l;
3071
3072 l = dispc_read_reg(DISPC_SYSCONFIG);
3073 l = FLD_MOD(l, 2, 13, 12); /* MIDLEMODE: smart standby */
3074 l = FLD_MOD(l, 2, 4, 3); /* SIDLEMODE: smart idle */
3075 l = FLD_MOD(l, 1, 2, 2); /* ENWAKEUP */
3076 l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */
3077 dispc_write_reg(DISPC_SYSCONFIG, l);
3078
3079 /* FUNCGATED */
3080 REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
3081
3082 /* L3 firewall setting: enable access to OCM RAM */
3083 /* XXX this should be somewhere in plat-omap */
3084 if (cpu_is_omap24xx())
3085 __raw_writel(0x402000b0, OMAP2_L3_IO_ADDRESS(0x680050a0));
3086
3087 _dispc_setup_color_conv_coef();
3088
3089 dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY);
3090
3091 dispc_read_plane_fifo_sizes();
3092}
3093
3094int dispc_init(void)
3095{
3096 u32 rev;
3097
3098 spin_lock_init(&dispc.irq_lock);
3099
3100#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
3101 spin_lock_init(&dispc.irq_stats_lock);
3102 dispc.irq_stats.last_reset = jiffies;
3103#endif
3104
3105 INIT_WORK(&dispc.error_work, dispc_error_worker);
3106
3107 dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS);
3108 if (!dispc.base) {
3109 DSSERR("can't ioremap DISPC\n");
3110 return -ENOMEM;
3111 }
3112
3113 enable_clocks(1);
3114
3115 _omap_dispc_initial_config();
3116
3117 _omap_dispc_initialize_irq();
3118
3119 dispc_save_context();
3120
3121 rev = dispc_read_reg(DISPC_REVISION);
3122 printk(KERN_INFO "OMAP DISPC rev %d.%d\n",
3123 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
3124
3125 enable_clocks(0);
3126
3127 return 0;
3128}
3129
3130void dispc_exit(void)
3131{
3132 iounmap(dispc.base);
3133}
3134
3135int dispc_enable_plane(enum omap_plane plane, bool enable)
3136{
3137 DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
3138
3139 enable_clocks(1);
3140 _dispc_enable_plane(plane, enable);
3141 enable_clocks(0);
3142
3143 return 0;
3144}
3145
3146int dispc_setup_plane(enum omap_plane plane,
3147 u32 paddr, u16 screen_width,
3148 u16 pos_x, u16 pos_y,
3149 u16 width, u16 height,
3150 u16 out_width, u16 out_height,
3151 enum omap_color_mode color_mode,
3152 bool ilace,
3153 enum omap_dss_rotation_type rotation_type,
3154 u8 rotation, bool mirror, u8 global_alpha)
3155{
3156 int r = 0;
3157
3158 DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> "
3159 "%dx%d, ilace %d, cmode %x, rot %d, mir %d\n",
3160 plane, paddr, screen_width, pos_x, pos_y,
3161 width, height,
3162 out_width, out_height,
3163 ilace, color_mode,
3164 rotation, mirror);
3165
3166 enable_clocks(1);
3167
3168 r = _dispc_setup_plane(plane,
3169 paddr, screen_width,
3170 pos_x, pos_y,
3171 width, height,
3172 out_width, out_height,
3173 color_mode, ilace,
3174 rotation_type,
3175 rotation, mirror,
3176 global_alpha);
3177
3178 enable_clocks(0);
3179
3180 return r;
3181}
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
new file mode 100644
index 000000000000..6a74ea116d29
--- /dev/null
+++ b/drivers/video/omap2/dss/display.c
@@ -0,0 +1,626 @@
1/*
2 * linux/drivers/video/omap2/dss/display.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#define DSS_SUBSYS_NAME "DISPLAY"
24
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/jiffies.h>
28#include <linux/list.h>
29#include <linux/platform_device.h>
30
31#include <plat/display.h>
32#include "dss.h"
33
34static LIST_HEAD(display_list);
35
36static ssize_t display_enabled_show(struct device *dev,
37 struct device_attribute *attr, char *buf)
38{
39 struct omap_dss_device *dssdev = to_dss_device(dev);
40 bool enabled = dssdev->state != OMAP_DSS_DISPLAY_DISABLED;
41
42 return snprintf(buf, PAGE_SIZE, "%d\n", enabled);
43}
44
45static ssize_t display_enabled_store(struct device *dev,
46 struct device_attribute *attr,
47 const char *buf, size_t size)
48{
49 struct omap_dss_device *dssdev = to_dss_device(dev);
50 bool enabled, r;
51
52 enabled = simple_strtoul(buf, NULL, 10);
53
54 if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
55 if (enabled) {
56 r = dssdev->driver->enable(dssdev);
57 if (r)
58 return r;
59 } else {
60 dssdev->driver->disable(dssdev);
61 }
62 }
63
64 return size;
65}
66
67static ssize_t display_upd_mode_show(struct device *dev,
68 struct device_attribute *attr, char *buf)
69{
70 struct omap_dss_device *dssdev = to_dss_device(dev);
71 enum omap_dss_update_mode mode = OMAP_DSS_UPDATE_AUTO;
72 if (dssdev->driver->get_update_mode)
73 mode = dssdev->driver->get_update_mode(dssdev);
74 return snprintf(buf, PAGE_SIZE, "%d\n", mode);
75}
76
77static ssize_t display_upd_mode_store(struct device *dev,
78 struct device_attribute *attr,
79 const char *buf, size_t size)
80{
81 struct omap_dss_device *dssdev = to_dss_device(dev);
82 int val, r;
83 enum omap_dss_update_mode mode;
84
85 val = simple_strtoul(buf, NULL, 10);
86
87 switch (val) {
88 case OMAP_DSS_UPDATE_DISABLED:
89 case OMAP_DSS_UPDATE_AUTO:
90 case OMAP_DSS_UPDATE_MANUAL:
91 mode = (enum omap_dss_update_mode)val;
92 break;
93 default:
94 return -EINVAL;
95 }
96
97 r = dssdev->driver->set_update_mode(dssdev, mode);
98 if (r)
99 return r;
100
101 return size;
102}
103
104static ssize_t display_tear_show(struct device *dev,
105 struct device_attribute *attr, char *buf)
106{
107 struct omap_dss_device *dssdev = to_dss_device(dev);
108 return snprintf(buf, PAGE_SIZE, "%d\n",
109 dssdev->driver->get_te ?
110 dssdev->driver->get_te(dssdev) : 0);
111}
112
113static ssize_t display_tear_store(struct device *dev,
114 struct device_attribute *attr, const char *buf, size_t size)
115{
116 struct omap_dss_device *dssdev = to_dss_device(dev);
117 unsigned long te;
118 int r;
119
120 if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
121 return -ENOENT;
122
123 te = simple_strtoul(buf, NULL, 0);
124
125 r = dssdev->driver->enable_te(dssdev, te);
126 if (r)
127 return r;
128
129 return size;
130}
131
132static ssize_t display_timings_show(struct device *dev,
133 struct device_attribute *attr, char *buf)
134{
135 struct omap_dss_device *dssdev = to_dss_device(dev);
136 struct omap_video_timings t;
137
138 if (!dssdev->driver->get_timings)
139 return -ENOENT;
140
141 dssdev->driver->get_timings(dssdev, &t);
142
143 return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
144 t.pixel_clock,
145 t.x_res, t.hfp, t.hbp, t.hsw,
146 t.y_res, t.vfp, t.vbp, t.vsw);
147}
148
149static ssize_t display_timings_store(struct device *dev,
150 struct device_attribute *attr, const char *buf, size_t size)
151{
152 struct omap_dss_device *dssdev = to_dss_device(dev);
153 struct omap_video_timings t;
154 int r, found;
155
156 if (!dssdev->driver->set_timings || !dssdev->driver->check_timings)
157 return -ENOENT;
158
159 found = 0;
160#ifdef CONFIG_OMAP2_DSS_VENC
161 if (strncmp("pal", buf, 3) == 0) {
162 t = omap_dss_pal_timings;
163 found = 1;
164 } else if (strncmp("ntsc", buf, 4) == 0) {
165 t = omap_dss_ntsc_timings;
166 found = 1;
167 }
168#endif
169 if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
170 &t.pixel_clock,
171 &t.x_res, &t.hfp, &t.hbp, &t.hsw,
172 &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
173 return -EINVAL;
174
175 r = dssdev->driver->check_timings(dssdev, &t);
176 if (r)
177 return r;
178
179 dssdev->driver->set_timings(dssdev, &t);
180
181 return size;
182}
183
184static ssize_t display_rotate_show(struct device *dev,
185 struct device_attribute *attr, char *buf)
186{
187 struct omap_dss_device *dssdev = to_dss_device(dev);
188 int rotate;
189 if (!dssdev->driver->get_rotate)
190 return -ENOENT;
191 rotate = dssdev->driver->get_rotate(dssdev);
192 return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
193}
194
195static ssize_t display_rotate_store(struct device *dev,
196 struct device_attribute *attr, const char *buf, size_t size)
197{
198 struct omap_dss_device *dssdev = to_dss_device(dev);
199 unsigned long rot;
200 int r;
201
202 if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
203 return -ENOENT;
204
205 rot = simple_strtoul(buf, NULL, 0);
206
207 r = dssdev->driver->set_rotate(dssdev, rot);
208 if (r)
209 return r;
210
211 return size;
212}
213
214static ssize_t display_mirror_show(struct device *dev,
215 struct device_attribute *attr, char *buf)
216{
217 struct omap_dss_device *dssdev = to_dss_device(dev);
218 int mirror;
219 if (!dssdev->driver->get_mirror)
220 return -ENOENT;
221 mirror = dssdev->driver->get_mirror(dssdev);
222 return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
223}
224
225static ssize_t display_mirror_store(struct device *dev,
226 struct device_attribute *attr, const char *buf, size_t size)
227{
228 struct omap_dss_device *dssdev = to_dss_device(dev);
229 unsigned long mirror;
230 int r;
231
232 if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
233 return -ENOENT;
234
235 mirror = simple_strtoul(buf, NULL, 0);
236
237 r = dssdev->driver->set_mirror(dssdev, mirror);
238 if (r)
239 return r;
240
241 return size;
242}
243
244static ssize_t display_wss_show(struct device *dev,
245 struct device_attribute *attr, char *buf)
246{
247 struct omap_dss_device *dssdev = to_dss_device(dev);
248 unsigned int wss;
249
250 if (!dssdev->driver->get_wss)
251 return -ENOENT;
252
253 wss = dssdev->driver->get_wss(dssdev);
254
255 return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
256}
257
258static ssize_t display_wss_store(struct device *dev,
259 struct device_attribute *attr, const char *buf, size_t size)
260{
261 struct omap_dss_device *dssdev = to_dss_device(dev);
262 unsigned long wss;
263 int r;
264
265 if (!dssdev->driver->get_wss || !dssdev->driver->set_wss)
266 return -ENOENT;
267
268 if (strict_strtoul(buf, 0, &wss))
269 return -EINVAL;
270
271 if (wss > 0xfffff)
272 return -EINVAL;
273
274 r = dssdev->driver->set_wss(dssdev, wss);
275 if (r)
276 return r;
277
278 return size;
279}
280
281static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
282 display_enabled_show, display_enabled_store);
283static DEVICE_ATTR(update_mode, S_IRUGO|S_IWUSR,
284 display_upd_mode_show, display_upd_mode_store);
285static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
286 display_tear_show, display_tear_store);
287static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
288 display_timings_show, display_timings_store);
289static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR,
290 display_rotate_show, display_rotate_store);
291static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR,
292 display_mirror_show, display_mirror_store);
293static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
294 display_wss_show, display_wss_store);
295
296static struct device_attribute *display_sysfs_attrs[] = {
297 &dev_attr_enabled,
298 &dev_attr_update_mode,
299 &dev_attr_tear_elim,
300 &dev_attr_timings,
301 &dev_attr_rotate,
302 &dev_attr_mirror,
303 &dev_attr_wss,
304 NULL
305};
306
307void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
308 u16 *xres, u16 *yres)
309{
310 *xres = dssdev->panel.timings.x_res;
311 *yres = dssdev->panel.timings.y_res;
312}
313EXPORT_SYMBOL(omapdss_default_get_resolution);
314
315void default_get_overlay_fifo_thresholds(enum omap_plane plane,
316 u32 fifo_size, enum omap_burst_size *burst_size,
317 u32 *fifo_low, u32 *fifo_high)
318{
319 unsigned burst_size_bytes;
320
321 *burst_size = OMAP_DSS_BURST_16x32;
322 burst_size_bytes = 16 * 32 / 8;
323
324 *fifo_high = fifo_size - 1;
325 *fifo_low = fifo_size - burst_size_bytes;
326}
327
328int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
329{
330 switch (dssdev->type) {
331 case OMAP_DISPLAY_TYPE_DPI:
332 if (dssdev->phy.dpi.data_lines == 24)
333 return 24;
334 else
335 return 16;
336
337 case OMAP_DISPLAY_TYPE_DBI:
338 case OMAP_DISPLAY_TYPE_DSI:
339 if (dssdev->ctrl.pixel_size == 24)
340 return 24;
341 else
342 return 16;
343 case OMAP_DISPLAY_TYPE_VENC:
344 case OMAP_DISPLAY_TYPE_SDI:
345 return 24;
346 return 24;
347 default:
348 BUG();
349 }
350}
351EXPORT_SYMBOL(omapdss_default_get_recommended_bpp);
352
353/* Checks if replication logic should be used. Only use for active matrix,
354 * when overlay is in RGB12U or RGB16 mode, and LCD interface is
355 * 18bpp or 24bpp */
356bool dss_use_replication(struct omap_dss_device *dssdev,
357 enum omap_color_mode mode)
358{
359 int bpp;
360
361 if (mode != OMAP_DSS_COLOR_RGB12U && mode != OMAP_DSS_COLOR_RGB16)
362 return false;
363
364 if (dssdev->type == OMAP_DISPLAY_TYPE_DPI &&
365 (dssdev->panel.config & OMAP_DSS_LCD_TFT) == 0)
366 return false;
367
368 switch (dssdev->type) {
369 case OMAP_DISPLAY_TYPE_DPI:
370 bpp = dssdev->phy.dpi.data_lines;
371 break;
372 case OMAP_DISPLAY_TYPE_VENC:
373 case OMAP_DISPLAY_TYPE_SDI:
374 bpp = 24;
375 break;
376 case OMAP_DISPLAY_TYPE_DBI:
377 case OMAP_DISPLAY_TYPE_DSI:
378 bpp = dssdev->ctrl.pixel_size;
379 break;
380 default:
381 BUG();
382 }
383
384 return bpp > 16;
385}
386
387void dss_init_device(struct platform_device *pdev,
388 struct omap_dss_device *dssdev)
389{
390 struct device_attribute *attr;
391 int i;
392 int r;
393
394 switch (dssdev->type) {
395 case OMAP_DISPLAY_TYPE_DPI:
396#ifdef CONFIG_OMAP2_DSS_RFBI
397 case OMAP_DISPLAY_TYPE_DBI:
398#endif
399#ifdef CONFIG_OMAP2_DSS_SDI
400 case OMAP_DISPLAY_TYPE_SDI:
401#endif
402#ifdef CONFIG_OMAP2_DSS_DSI
403 case OMAP_DISPLAY_TYPE_DSI:
404#endif
405#ifdef CONFIG_OMAP2_DSS_VENC
406 case OMAP_DISPLAY_TYPE_VENC:
407#endif
408 break;
409 default:
410 DSSERR("Support for display '%s' not compiled in.\n",
411 dssdev->name);
412 return;
413 }
414
415 switch (dssdev->type) {
416 case OMAP_DISPLAY_TYPE_DPI:
417 r = dpi_init_display(dssdev);
418 break;
419#ifdef CONFIG_OMAP2_DSS_RFBI
420 case OMAP_DISPLAY_TYPE_DBI:
421 r = rfbi_init_display(dssdev);
422 break;
423#endif
424#ifdef CONFIG_OMAP2_DSS_VENC
425 case OMAP_DISPLAY_TYPE_VENC:
426 r = venc_init_display(dssdev);
427 break;
428#endif
429#ifdef CONFIG_OMAP2_DSS_SDI
430 case OMAP_DISPLAY_TYPE_SDI:
431 r = sdi_init_display(dssdev);
432 break;
433#endif
434#ifdef CONFIG_OMAP2_DSS_DSI
435 case OMAP_DISPLAY_TYPE_DSI:
436 r = dsi_init_display(dssdev);
437 break;
438#endif
439 default:
440 BUG();
441 }
442
443 if (r) {
444 DSSERR("failed to init display %s\n", dssdev->name);
445 return;
446 }
447
448 /* create device sysfs files */
449 i = 0;
450 while ((attr = display_sysfs_attrs[i++]) != NULL) {
451 r = device_create_file(&dssdev->dev, attr);
452 if (r)
453 DSSERR("failed to create sysfs file\n");
454 }
455
456 /* create display? sysfs links */
457 r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
458 dev_name(&dssdev->dev));
459 if (r)
460 DSSERR("failed to create sysfs display link\n");
461}
462
463void dss_uninit_device(struct platform_device *pdev,
464 struct omap_dss_device *dssdev)
465{
466 struct device_attribute *attr;
467 int i = 0;
468
469 sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev));
470
471 while ((attr = display_sysfs_attrs[i++]) != NULL)
472 device_remove_file(&dssdev->dev, attr);
473
474 if (dssdev->manager)
475 dssdev->manager->unset_device(dssdev->manager);
476}
477
478static int dss_suspend_device(struct device *dev, void *data)
479{
480 int r;
481 struct omap_dss_device *dssdev = to_dss_device(dev);
482
483 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
484 dssdev->activate_after_resume = false;
485 return 0;
486 }
487
488 if (!dssdev->driver->suspend) {
489 DSSERR("display '%s' doesn't implement suspend\n",
490 dssdev->name);
491 return -ENOSYS;
492 }
493
494 r = dssdev->driver->suspend(dssdev);
495 if (r)
496 return r;
497
498 dssdev->activate_after_resume = true;
499
500 return 0;
501}
502
503int dss_suspend_all_devices(void)
504{
505 int r;
506 struct bus_type *bus = dss_get_bus();
507
508 r = bus_for_each_dev(bus, NULL, NULL, dss_suspend_device);
509 if (r) {
510 /* resume all displays that were suspended */
511 dss_resume_all_devices();
512 return r;
513 }
514
515 return 0;
516}
517
518static int dss_resume_device(struct device *dev, void *data)
519{
520 int r;
521 struct omap_dss_device *dssdev = to_dss_device(dev);
522
523 if (dssdev->activate_after_resume && dssdev->driver->resume) {
524 r = dssdev->driver->resume(dssdev);
525 if (r)
526 return r;
527 }
528
529 dssdev->activate_after_resume = false;
530
531 return 0;
532}
533
534int dss_resume_all_devices(void)
535{
536 struct bus_type *bus = dss_get_bus();
537
538 return bus_for_each_dev(bus, NULL, NULL, dss_resume_device);
539}
540
541static int dss_disable_device(struct device *dev, void *data)
542{
543 struct omap_dss_device *dssdev = to_dss_device(dev);
544 dssdev->driver->disable(dssdev);
545 return 0;
546}
547
548void dss_disable_all_devices(void)
549{
550 struct bus_type *bus = dss_get_bus();
551 bus_for_each_dev(bus, NULL, NULL, dss_disable_device);
552}
553
554
555void omap_dss_get_device(struct omap_dss_device *dssdev)
556{
557 get_device(&dssdev->dev);
558}
559EXPORT_SYMBOL(omap_dss_get_device);
560
561void omap_dss_put_device(struct omap_dss_device *dssdev)
562{
563 put_device(&dssdev->dev);
564}
565EXPORT_SYMBOL(omap_dss_put_device);
566
567/* ref count of the found device is incremented. ref count
568 * of from-device is decremented. */
569struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from)
570{
571 struct device *dev;
572 struct device *dev_start = NULL;
573 struct omap_dss_device *dssdev = NULL;
574
575 int match(struct device *dev, void *data)
576 {
577 return 1;
578 }
579
580 if (from)
581 dev_start = &from->dev;
582 dev = bus_find_device(dss_get_bus(), dev_start, NULL, match);
583 if (dev)
584 dssdev = to_dss_device(dev);
585 if (from)
586 put_device(&from->dev);
587
588 return dssdev;
589}
590EXPORT_SYMBOL(omap_dss_get_next_device);
591
592struct omap_dss_device *omap_dss_find_device(void *data,
593 int (*match)(struct omap_dss_device *dssdev, void *data))
594{
595 struct omap_dss_device *dssdev = NULL;
596
597 while ((dssdev = omap_dss_get_next_device(dssdev)) != NULL) {
598 if (match(dssdev, data))
599 return dssdev;
600 }
601
602 return NULL;
603}
604EXPORT_SYMBOL(omap_dss_find_device);
605
606int omap_dss_start_device(struct omap_dss_device *dssdev)
607{
608 if (!dssdev->driver) {
609 DSSDBG("no driver\n");
610 return -ENODEV;
611 }
612
613 if (!try_module_get(dssdev->dev.driver->owner)) {
614 return -ENODEV;
615 }
616
617 return 0;
618}
619EXPORT_SYMBOL(omap_dss_start_device);
620
621void omap_dss_stop_device(struct omap_dss_device *dssdev)
622{
623 module_put(dssdev->dev.driver->owner);
624}
625EXPORT_SYMBOL(omap_dss_stop_device);
626
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
new file mode 100644
index 000000000000..960e977a8bf0
--- /dev/null
+++ b/drivers/video/omap2/dss/dpi.c
@@ -0,0 +1,321 @@
1/*
2 * linux/drivers/video/omap2/dss/dpi.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#define DSS_SUBSYS_NAME "DPI"
24
25#include <linux/kernel.h>
26#include <linux/clk.h>
27#include <linux/delay.h>
28#include <linux/err.h>
29#include <linux/errno.h>
30#include <linux/platform_device.h>
31#include <linux/regulator/consumer.h>
32
33#include <plat/display.h>
34#include <plat/cpu.h>
35
36#include "dss.h"
37
38static struct {
39 struct regulator *vdds_dsi_reg;
40} dpi;
41
42#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
43static int dpi_set_dsi_clk(bool is_tft, unsigned long pck_req,
44 unsigned long *fck, int *lck_div, int *pck_div)
45{
46 struct dsi_clock_info dsi_cinfo;
47 struct dispc_clock_info dispc_cinfo;
48 int r;
49
50 r = dsi_pll_calc_clock_div_pck(is_tft, pck_req, &dsi_cinfo,
51 &dispc_cinfo);
52 if (r)
53 return r;
54
55 r = dsi_pll_set_clock_div(&dsi_cinfo);
56 if (r)
57 return r;
58
59 dss_select_dispc_clk_source(DSS_SRC_DSI1_PLL_FCLK);
60
61 r = dispc_set_clock_div(&dispc_cinfo);
62 if (r)
63 return r;
64
65 *fck = dsi_cinfo.dsi1_pll_fclk;
66 *lck_div = dispc_cinfo.lck_div;
67 *pck_div = dispc_cinfo.pck_div;
68
69 return 0;
70}
71#else
72static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req,
73 unsigned long *fck, int *lck_div, int *pck_div)
74{
75 struct dss_clock_info dss_cinfo;
76 struct dispc_clock_info dispc_cinfo;
77 int r;
78
79 r = dss_calc_clock_div(is_tft, pck_req, &dss_cinfo, &dispc_cinfo);
80 if (r)
81 return r;
82
83 r = dss_set_clock_div(&dss_cinfo);
84 if (r)
85 return r;
86
87 r = dispc_set_clock_div(&dispc_cinfo);
88 if (r)
89 return r;
90
91 *fck = dss_cinfo.fck;
92 *lck_div = dispc_cinfo.lck_div;
93 *pck_div = dispc_cinfo.pck_div;
94
95 return 0;
96}
97#endif
98
99static int dpi_set_mode(struct omap_dss_device *dssdev)
100{
101 struct omap_video_timings *t = &dssdev->panel.timings;
102 int lck_div, pck_div;
103 unsigned long fck;
104 unsigned long pck;
105 bool is_tft;
106 int r = 0;
107
108 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
109
110 dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi,
111 dssdev->panel.acb);
112
113 is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
114
115#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
116 r = dpi_set_dsi_clk(is_tft, t->pixel_clock * 1000,
117 &fck, &lck_div, &pck_div);
118#else
119 r = dpi_set_dispc_clk(is_tft, t->pixel_clock * 1000,
120 &fck, &lck_div, &pck_div);
121#endif
122 if (r)
123 goto err0;
124
125 pck = fck / lck_div / pck_div / 1000;
126
127 if (pck != t->pixel_clock) {
128 DSSWARN("Could not find exact pixel clock. "
129 "Requested %d kHz, got %lu kHz\n",
130 t->pixel_clock, pck);
131
132 t->pixel_clock = pck;
133 }
134
135 dispc_set_lcd_timings(t);
136
137err0:
138 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
139 return r;
140}
141
142static int dpi_basic_init(struct omap_dss_device *dssdev)
143{
144 bool is_tft;
145
146 is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
147
148 dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS);
149 dispc_set_lcd_display_type(is_tft ? OMAP_DSS_LCD_DISPLAY_TFT :
150 OMAP_DSS_LCD_DISPLAY_STN);
151 dispc_set_tft_data_lines(dssdev->phy.dpi.data_lines);
152
153 return 0;
154}
155
156int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
157{
158 int r;
159
160 r = omap_dss_start_device(dssdev);
161 if (r) {
162 DSSERR("failed to start device\n");
163 goto err0;
164 }
165
166 if (cpu_is_omap34xx()) {
167 r = regulator_enable(dpi.vdds_dsi_reg);
168 if (r)
169 goto err1;
170 }
171
172 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
173
174 r = dpi_basic_init(dssdev);
175 if (r)
176 goto err2;
177
178#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
179 dss_clk_enable(DSS_CLK_FCK2);
180 r = dsi_pll_init(dssdev, 0, 1);
181 if (r)
182 goto err3;
183#endif
184 r = dpi_set_mode(dssdev);
185 if (r)
186 goto err4;
187
188 mdelay(2);
189
190 dssdev->manager->enable(dssdev->manager);
191
192 return 0;
193
194err4:
195#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
196 dsi_pll_uninit();
197err3:
198 dss_clk_disable(DSS_CLK_FCK2);
199#endif
200err2:
201 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
202 if (cpu_is_omap34xx())
203 regulator_disable(dpi.vdds_dsi_reg);
204err1:
205 omap_dss_stop_device(dssdev);
206err0:
207 return r;
208}
209EXPORT_SYMBOL(omapdss_dpi_display_enable);
210
211void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
212{
213 dssdev->manager->disable(dssdev->manager);
214
215#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
216 dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
217 dsi_pll_uninit();
218 dss_clk_disable(DSS_CLK_FCK2);
219#endif
220
221 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
222
223 if (cpu_is_omap34xx())
224 regulator_disable(dpi.vdds_dsi_reg);
225
226 omap_dss_stop_device(dssdev);
227}
228EXPORT_SYMBOL(omapdss_dpi_display_disable);
229
230void dpi_set_timings(struct omap_dss_device *dssdev,
231 struct omap_video_timings *timings)
232{
233 DSSDBG("dpi_set_timings\n");
234 dssdev->panel.timings = *timings;
235 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
236 dpi_set_mode(dssdev);
237 dispc_go(OMAP_DSS_CHANNEL_LCD);
238 }
239}
240EXPORT_SYMBOL(dpi_set_timings);
241
242int dpi_check_timings(struct omap_dss_device *dssdev,
243 struct omap_video_timings *timings)
244{
245 bool is_tft;
246 int r;
247 int lck_div, pck_div;
248 unsigned long fck;
249 unsigned long pck;
250
251 if (!dispc_lcd_timings_ok(timings))
252 return -EINVAL;
253
254 if (timings->pixel_clock == 0)
255 return -EINVAL;
256
257 is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
258
259#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
260 {
261 struct dsi_clock_info dsi_cinfo;
262 struct dispc_clock_info dispc_cinfo;
263 r = dsi_pll_calc_clock_div_pck(is_tft,
264 timings->pixel_clock * 1000,
265 &dsi_cinfo, &dispc_cinfo);
266
267 if (r)
268 return r;
269
270 fck = dsi_cinfo.dsi1_pll_fclk;
271 lck_div = dispc_cinfo.lck_div;
272 pck_div = dispc_cinfo.pck_div;
273 }
274#else
275 {
276 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,
279 &dss_cinfo, &dispc_cinfo);
280
281 if (r)
282 return r;
283
284 fck = dss_cinfo.fck;
285 lck_div = dispc_cinfo.lck_div;
286 pck_div = dispc_cinfo.pck_div;
287 }
288#endif
289
290 pck = fck / lck_div / pck_div / 1000;
291
292 timings->pixel_clock = pck;
293
294 return 0;
295}
296EXPORT_SYMBOL(dpi_check_timings);
297
298int dpi_init_display(struct omap_dss_device *dssdev)
299{
300 DSSDBG("init_display\n");
301
302 return 0;
303}
304
305int dpi_init(struct platform_device *pdev)
306{
307 if (cpu_is_omap34xx()) {
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");
311 return PTR_ERR(dpi.vdds_dsi_reg);
312 }
313 }
314
315 return 0;
316}
317
318void dpi_exit(void)
319{
320}
321
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
new file mode 100644
index 000000000000..3af207b2bde3
--- /dev/null
+++ b/drivers/video/omap2/dss/dsi.c
@@ -0,0 +1,3340 @@
1/*
2 * linux/drivers/video/omap2/dss/dsi.c
3 *
4 * Copyright (C) 2009 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#define DSS_SUBSYS_NAME "DSI"
21
22#include <linux/kernel.h>
23#include <linux/io.h>
24#include <linux/clk.h>
25#include <linux/device.h>
26#include <linux/err.h>
27#include <linux/interrupt.h>
28#include <linux/delay.h>
29#include <linux/mutex.h>
30#include <linux/semaphore.h>
31#include <linux/seq_file.h>
32#include <linux/platform_device.h>
33#include <linux/regulator/consumer.h>
34#include <linux/wait.h>
35#include <linux/workqueue.h>
36
37#include <plat/display.h>
38#include <plat/clock.h>
39
40#include "dss.h"
41
42/*#define VERBOSE_IRQ*/
43#define DSI_CATCH_MISSING_TE
44
45#define DSI_BASE 0x4804FC00
46
47struct dsi_reg { u16 idx; };
48
49#define DSI_REG(idx) ((const struct dsi_reg) { idx })
50
51#define DSI_SZ_REGS SZ_1K
52/* DSI Protocol Engine */
53
54#define DSI_REVISION DSI_REG(0x0000)
55#define DSI_SYSCONFIG DSI_REG(0x0010)
56#define DSI_SYSSTATUS DSI_REG(0x0014)
57#define DSI_IRQSTATUS DSI_REG(0x0018)
58#define DSI_IRQENABLE DSI_REG(0x001C)
59#define DSI_CTRL DSI_REG(0x0040)
60#define DSI_COMPLEXIO_CFG1 DSI_REG(0x0048)
61#define DSI_COMPLEXIO_IRQ_STATUS DSI_REG(0x004C)
62#define DSI_COMPLEXIO_IRQ_ENABLE DSI_REG(0x0050)
63#define DSI_CLK_CTRL DSI_REG(0x0054)
64#define DSI_TIMING1 DSI_REG(0x0058)
65#define DSI_TIMING2 DSI_REG(0x005C)
66#define DSI_VM_TIMING1 DSI_REG(0x0060)
67#define DSI_VM_TIMING2 DSI_REG(0x0064)
68#define DSI_VM_TIMING3 DSI_REG(0x0068)
69#define DSI_CLK_TIMING DSI_REG(0x006C)
70#define DSI_TX_FIFO_VC_SIZE DSI_REG(0x0070)
71#define DSI_RX_FIFO_VC_SIZE DSI_REG(0x0074)
72#define DSI_COMPLEXIO_CFG2 DSI_REG(0x0078)
73#define DSI_RX_FIFO_VC_FULLNESS DSI_REG(0x007C)
74#define DSI_VM_TIMING4 DSI_REG(0x0080)
75#define DSI_TX_FIFO_VC_EMPTINESS DSI_REG(0x0084)
76#define DSI_VM_TIMING5 DSI_REG(0x0088)
77#define DSI_VM_TIMING6 DSI_REG(0x008C)
78#define DSI_VM_TIMING7 DSI_REG(0x0090)
79#define DSI_STOPCLK_TIMING DSI_REG(0x0094)
80#define DSI_VC_CTRL(n) DSI_REG(0x0100 + (n * 0x20))
81#define DSI_VC_TE(n) DSI_REG(0x0104 + (n * 0x20))
82#define DSI_VC_LONG_PACKET_HEADER(n) DSI_REG(0x0108 + (n * 0x20))
83#define DSI_VC_LONG_PACKET_PAYLOAD(n) DSI_REG(0x010C + (n * 0x20))
84#define DSI_VC_SHORT_PACKET_HEADER(n) DSI_REG(0x0110 + (n * 0x20))
85#define DSI_VC_IRQSTATUS(n) DSI_REG(0x0118 + (n * 0x20))
86#define DSI_VC_IRQENABLE(n) DSI_REG(0x011C + (n * 0x20))
87
88/* DSIPHY_SCP */
89
90#define DSI_DSIPHY_CFG0 DSI_REG(0x200 + 0x0000)
91#define DSI_DSIPHY_CFG1 DSI_REG(0x200 + 0x0004)
92#define DSI_DSIPHY_CFG2 DSI_REG(0x200 + 0x0008)
93#define DSI_DSIPHY_CFG5 DSI_REG(0x200 + 0x0014)
94
95/* DSI_PLL_CTRL_SCP */
96
97#define DSI_PLL_CONTROL DSI_REG(0x300 + 0x0000)
98#define DSI_PLL_STATUS DSI_REG(0x300 + 0x0004)
99#define DSI_PLL_GO DSI_REG(0x300 + 0x0008)
100#define DSI_PLL_CONFIGURATION1 DSI_REG(0x300 + 0x000C)
101#define DSI_PLL_CONFIGURATION2 DSI_REG(0x300 + 0x0010)
102
103#define REG_GET(idx, start, end) \
104 FLD_GET(dsi_read_reg(idx), start, end)
105
106#define REG_FLD_MOD(idx, val, start, end) \
107 dsi_write_reg(idx, FLD_MOD(dsi_read_reg(idx), val, start, end))
108
109/* Global interrupts */
110#define DSI_IRQ_VC0 (1 << 0)
111#define DSI_IRQ_VC1 (1 << 1)
112#define DSI_IRQ_VC2 (1 << 2)
113#define DSI_IRQ_VC3 (1 << 3)
114#define DSI_IRQ_WAKEUP (1 << 4)
115#define DSI_IRQ_RESYNC (1 << 5)
116#define DSI_IRQ_PLL_LOCK (1 << 7)
117#define DSI_IRQ_PLL_UNLOCK (1 << 8)
118#define DSI_IRQ_PLL_RECALL (1 << 9)
119#define DSI_IRQ_COMPLEXIO_ERR (1 << 10)
120#define DSI_IRQ_HS_TX_TIMEOUT (1 << 14)
121#define DSI_IRQ_LP_RX_TIMEOUT (1 << 15)
122#define DSI_IRQ_TE_TRIGGER (1 << 16)
123#define DSI_IRQ_ACK_TRIGGER (1 << 17)
124#define DSI_IRQ_SYNC_LOST (1 << 18)
125#define DSI_IRQ_LDO_POWER_GOOD (1 << 19)
126#define DSI_IRQ_TA_TIMEOUT (1 << 20)
127#define DSI_IRQ_ERROR_MASK \
128 (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \
129 DSI_IRQ_TA_TIMEOUT)
130#define DSI_IRQ_CHANNEL_MASK 0xf
131
132/* Virtual channel interrupts */
133#define DSI_VC_IRQ_CS (1 << 0)
134#define DSI_VC_IRQ_ECC_CORR (1 << 1)
135#define DSI_VC_IRQ_PACKET_SENT (1 << 2)
136#define DSI_VC_IRQ_FIFO_TX_OVF (1 << 3)
137#define DSI_VC_IRQ_FIFO_RX_OVF (1 << 4)
138#define DSI_VC_IRQ_BTA (1 << 5)
139#define DSI_VC_IRQ_ECC_NO_CORR (1 << 6)
140#define DSI_VC_IRQ_FIFO_TX_UDF (1 << 7)
141#define DSI_VC_IRQ_PP_BUSY_CHANGE (1 << 8)
142#define DSI_VC_IRQ_ERROR_MASK \
143 (DSI_VC_IRQ_CS | DSI_VC_IRQ_ECC_CORR | DSI_VC_IRQ_FIFO_TX_OVF | \
144 DSI_VC_IRQ_FIFO_RX_OVF | DSI_VC_IRQ_ECC_NO_CORR | \
145 DSI_VC_IRQ_FIFO_TX_UDF)
146
147/* ComplexIO interrupts */
148#define DSI_CIO_IRQ_ERRSYNCESC1 (1 << 0)
149#define DSI_CIO_IRQ_ERRSYNCESC2 (1 << 1)
150#define DSI_CIO_IRQ_ERRSYNCESC3 (1 << 2)
151#define DSI_CIO_IRQ_ERRESC1 (1 << 5)
152#define DSI_CIO_IRQ_ERRESC2 (1 << 6)
153#define DSI_CIO_IRQ_ERRESC3 (1 << 7)
154#define DSI_CIO_IRQ_ERRCONTROL1 (1 << 10)
155#define DSI_CIO_IRQ_ERRCONTROL2 (1 << 11)
156#define DSI_CIO_IRQ_ERRCONTROL3 (1 << 12)
157#define DSI_CIO_IRQ_STATEULPS1 (1 << 15)
158#define DSI_CIO_IRQ_STATEULPS2 (1 << 16)
159#define DSI_CIO_IRQ_STATEULPS3 (1 << 17)
160#define DSI_CIO_IRQ_ERRCONTENTIONLP0_1 (1 << 20)
161#define DSI_CIO_IRQ_ERRCONTENTIONLP1_1 (1 << 21)
162#define DSI_CIO_IRQ_ERRCONTENTIONLP0_2 (1 << 22)
163#define DSI_CIO_IRQ_ERRCONTENTIONLP1_2 (1 << 23)
164#define DSI_CIO_IRQ_ERRCONTENTIONLP0_3 (1 << 24)
165#define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25)
166#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30)
167#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31)
168
169#define DSI_DT_DCS_SHORT_WRITE_0 0x05
170#define DSI_DT_DCS_SHORT_WRITE_1 0x15
171#define DSI_DT_DCS_READ 0x06
172#define DSI_DT_SET_MAX_RET_PKG_SIZE 0x37
173#define DSI_DT_NULL_PACKET 0x09
174#define DSI_DT_DCS_LONG_WRITE 0x39
175
176#define DSI_DT_RX_ACK_WITH_ERR 0x02
177#define DSI_DT_RX_DCS_LONG_READ 0x1c
178#define DSI_DT_RX_SHORT_READ_1 0x21
179#define DSI_DT_RX_SHORT_READ_2 0x22
180
181#define FINT_MAX 2100000
182#define FINT_MIN 750000
183#define REGN_MAX (1 << 7)
184#define REGM_MAX ((1 << 11) - 1)
185#define REGM3_MAX (1 << 4)
186#define REGM4_MAX (1 << 4)
187#define LP_DIV_MAX ((1 << 13) - 1)
188
189enum fifo_size {
190 DSI_FIFO_SIZE_0 = 0,
191 DSI_FIFO_SIZE_32 = 1,
192 DSI_FIFO_SIZE_64 = 2,
193 DSI_FIFO_SIZE_96 = 3,
194 DSI_FIFO_SIZE_128 = 4,
195};
196
197enum dsi_vc_mode {
198 DSI_VC_MODE_L4 = 0,
199 DSI_VC_MODE_VP,
200};
201
202struct dsi_update_region {
203 u16 x, y, w, h;
204 struct omap_dss_device *device;
205};
206
207struct dsi_irq_stats {
208 unsigned long last_reset;
209 unsigned irq_count;
210 unsigned dsi_irqs[32];
211 unsigned vc_irqs[4][32];
212 unsigned cio_irqs[32];
213};
214
215static struct
216{
217 void __iomem *base;
218
219 struct dsi_clock_info current_cinfo;
220
221 struct regulator *vdds_dsi_reg;
222
223 struct {
224 enum dsi_vc_mode mode;
225 struct omap_dss_device *dssdev;
226 enum fifo_size fifo_size;
227 } vc[4];
228
229 struct mutex lock;
230 struct semaphore bus_lock;
231
232 unsigned pll_locked;
233
234 struct completion bta_completion;
235
236 int update_channel;
237 struct dsi_update_region update_region;
238
239 bool te_enabled;
240
241 struct work_struct framedone_work;
242 void (*framedone_callback)(int, void *);
243 void *framedone_data;
244
245 struct delayed_work framedone_timeout_work;
246
247#ifdef DSI_CATCH_MISSING_TE
248 struct timer_list te_timer;
249#endif
250
251 unsigned long cache_req_pck;
252 unsigned long cache_clk_freq;
253 struct dsi_clock_info cache_cinfo;
254
255 u32 errors;
256 spinlock_t errors_lock;
257#ifdef DEBUG
258 ktime_t perf_setup_time;
259 ktime_t perf_start_time;
260#endif
261 int debug_read;
262 int debug_write;
263
264#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
265 spinlock_t irq_stats_lock;
266 struct dsi_irq_stats irq_stats;
267#endif
268} dsi;
269
270#ifdef DEBUG
271static unsigned int dsi_perf;
272module_param_named(dsi_perf, dsi_perf, bool, 0644);
273#endif
274
275static inline void dsi_write_reg(const struct dsi_reg idx, u32 val)
276{
277 __raw_writel(val, dsi.base + idx.idx);
278}
279
280static inline u32 dsi_read_reg(const struct dsi_reg idx)
281{
282 return __raw_readl(dsi.base + idx.idx);
283}
284
285
286void dsi_save_context(void)
287{
288}
289
290void dsi_restore_context(void)
291{
292}
293
294void dsi_bus_lock(void)
295{
296 down(&dsi.bus_lock);
297}
298EXPORT_SYMBOL(dsi_bus_lock);
299
300void dsi_bus_unlock(void)
301{
302 up(&dsi.bus_lock);
303}
304EXPORT_SYMBOL(dsi_bus_unlock);
305
306static bool dsi_bus_is_locked(void)
307{
308 return dsi.bus_lock.count == 0;
309}
310
311static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum,
312 int value)
313{
314 int t = 100000;
315
316 while (REG_GET(idx, bitnum, bitnum) != value) {
317 if (--t == 0)
318 return !value;
319 }
320
321 return value;
322}
323
324#ifdef DEBUG
325static void dsi_perf_mark_setup(void)
326{
327 dsi.perf_setup_time = ktime_get();
328}
329
330static void dsi_perf_mark_start(void)
331{
332 dsi.perf_start_time = ktime_get();
333}
334
335static void dsi_perf_show(const char *name)
336{
337 ktime_t t, setup_time, trans_time;
338 u32 total_bytes;
339 u32 setup_us, trans_us, total_us;
340
341 if (!dsi_perf)
342 return;
343
344 t = ktime_get();
345
346 setup_time = ktime_sub(dsi.perf_start_time, dsi.perf_setup_time);
347 setup_us = (u32)ktime_to_us(setup_time);
348 if (setup_us == 0)
349 setup_us = 1;
350
351 trans_time = ktime_sub(t, dsi.perf_start_time);
352 trans_us = (u32)ktime_to_us(trans_time);
353 if (trans_us == 0)
354 trans_us = 1;
355
356 total_us = setup_us + trans_us;
357
358 total_bytes = dsi.update_region.w *
359 dsi.update_region.h *
360 dsi.update_region.device->ctrl.pixel_size / 8;
361
362 printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), "
363 "%u bytes, %u kbytes/sec\n",
364 name,
365 setup_us,
366 trans_us,
367 total_us,
368 1000*1000 / total_us,
369 total_bytes,
370 total_bytes * 1000 / total_us);
371}
372#else
373#define dsi_perf_mark_setup()
374#define dsi_perf_mark_start()
375#define dsi_perf_show(x)
376#endif
377
378static void print_irq_status(u32 status)
379{
380#ifndef VERBOSE_IRQ
381 if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0)
382 return;
383#endif
384 printk(KERN_DEBUG "DSI IRQ: 0x%x: ", status);
385
386#define PIS(x) \
387 if (status & DSI_IRQ_##x) \
388 printk(#x " ");
389#ifdef VERBOSE_IRQ
390 PIS(VC0);
391 PIS(VC1);
392 PIS(VC2);
393 PIS(VC3);
394#endif
395 PIS(WAKEUP);
396 PIS(RESYNC);
397 PIS(PLL_LOCK);
398 PIS(PLL_UNLOCK);
399 PIS(PLL_RECALL);
400 PIS(COMPLEXIO_ERR);
401 PIS(HS_TX_TIMEOUT);
402 PIS(LP_RX_TIMEOUT);
403 PIS(TE_TRIGGER);
404 PIS(ACK_TRIGGER);
405 PIS(SYNC_LOST);
406 PIS(LDO_POWER_GOOD);
407 PIS(TA_TIMEOUT);
408#undef PIS
409
410 printk("\n");
411}
412
413static void print_irq_status_vc(int channel, u32 status)
414{
415#ifndef VERBOSE_IRQ
416 if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
417 return;
418#endif
419 printk(KERN_DEBUG "DSI VC(%d) IRQ 0x%x: ", channel, status);
420
421#define PIS(x) \
422 if (status & DSI_VC_IRQ_##x) \
423 printk(#x " ");
424 PIS(CS);
425 PIS(ECC_CORR);
426#ifdef VERBOSE_IRQ
427 PIS(PACKET_SENT);
428#endif
429 PIS(FIFO_TX_OVF);
430 PIS(FIFO_RX_OVF);
431 PIS(BTA);
432 PIS(ECC_NO_CORR);
433 PIS(FIFO_TX_UDF);
434 PIS(PP_BUSY_CHANGE);
435#undef PIS
436 printk("\n");
437}
438
439static void print_irq_status_cio(u32 status)
440{
441 printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status);
442
443#define PIS(x) \
444 if (status & DSI_CIO_IRQ_##x) \
445 printk(#x " ");
446 PIS(ERRSYNCESC1);
447 PIS(ERRSYNCESC2);
448 PIS(ERRSYNCESC3);
449 PIS(ERRESC1);
450 PIS(ERRESC2);
451 PIS(ERRESC3);
452 PIS(ERRCONTROL1);
453 PIS(ERRCONTROL2);
454 PIS(ERRCONTROL3);
455 PIS(STATEULPS1);
456 PIS(STATEULPS2);
457 PIS(STATEULPS3);
458 PIS(ERRCONTENTIONLP0_1);
459 PIS(ERRCONTENTIONLP1_1);
460 PIS(ERRCONTENTIONLP0_2);
461 PIS(ERRCONTENTIONLP1_2);
462 PIS(ERRCONTENTIONLP0_3);
463 PIS(ERRCONTENTIONLP1_3);
464 PIS(ULPSACTIVENOT_ALL0);
465 PIS(ULPSACTIVENOT_ALL1);
466#undef PIS
467
468 printk("\n");
469}
470
471static int debug_irq;
472
473/* called from dss */
474void dsi_irq_handler(void)
475{
476 u32 irqstatus, vcstatus, ciostatus;
477 int i;
478
479 irqstatus = dsi_read_reg(DSI_IRQSTATUS);
480
481#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
482 spin_lock(&dsi.irq_stats_lock);
483 dsi.irq_stats.irq_count++;
484 dss_collect_irq_stats(irqstatus, dsi.irq_stats.dsi_irqs);
485#endif
486
487 if (irqstatus & DSI_IRQ_ERROR_MASK) {
488 DSSERR("DSI error, irqstatus %x\n", irqstatus);
489 print_irq_status(irqstatus);
490 spin_lock(&dsi.errors_lock);
491 dsi.errors |= irqstatus & DSI_IRQ_ERROR_MASK;
492 spin_unlock(&dsi.errors_lock);
493 } else if (debug_irq) {
494 print_irq_status(irqstatus);
495 }
496
497#ifdef DSI_CATCH_MISSING_TE
498 if (irqstatus & DSI_IRQ_TE_TRIGGER)
499 del_timer(&dsi.te_timer);
500#endif
501
502 for (i = 0; i < 4; ++i) {
503 if ((irqstatus & (1<<i)) == 0)
504 continue;
505
506 vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i));
507
508#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
509 dss_collect_irq_stats(vcstatus, dsi.irq_stats.vc_irqs[i]);
510#endif
511
512 if (vcstatus & DSI_VC_IRQ_BTA)
513 complete(&dsi.bta_completion);
514
515 if (vcstatus & DSI_VC_IRQ_ERROR_MASK) {
516 DSSERR("DSI VC(%d) error, vc irqstatus %x\n",
517 i, vcstatus);
518 print_irq_status_vc(i, vcstatus);
519 } else if (debug_irq) {
520 print_irq_status_vc(i, vcstatus);
521 }
522
523 dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus);
524 /* flush posted write */
525 dsi_read_reg(DSI_VC_IRQSTATUS(i));
526 }
527
528 if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) {
529 ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
530
531#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
532 dss_collect_irq_stats(ciostatus, dsi.irq_stats.cio_irqs);
533#endif
534
535 dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus);
536 /* flush posted write */
537 dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
538
539 DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus);
540 print_irq_status_cio(ciostatus);
541 }
542
543 dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
544 /* flush posted write */
545 dsi_read_reg(DSI_IRQSTATUS);
546
547#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
548 spin_unlock(&dsi.irq_stats_lock);
549#endif
550}
551
552
553static void _dsi_initialize_irq(void)
554{
555 u32 l;
556 int i;
557
558 /* disable all interrupts */
559 dsi_write_reg(DSI_IRQENABLE, 0);
560 for (i = 0; i < 4; ++i)
561 dsi_write_reg(DSI_VC_IRQENABLE(i), 0);
562 dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, 0);
563
564 /* clear interrupt status */
565 l = dsi_read_reg(DSI_IRQSTATUS);
566 dsi_write_reg(DSI_IRQSTATUS, l & ~DSI_IRQ_CHANNEL_MASK);
567
568 for (i = 0; i < 4; ++i) {
569 l = dsi_read_reg(DSI_VC_IRQSTATUS(i));
570 dsi_write_reg(DSI_VC_IRQSTATUS(i), l);
571 }
572
573 l = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
574 dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, l);
575
576 /* enable error irqs */
577 l = DSI_IRQ_ERROR_MASK;
578#ifdef DSI_CATCH_MISSING_TE
579 l |= DSI_IRQ_TE_TRIGGER;
580#endif
581 dsi_write_reg(DSI_IRQENABLE, l);
582
583 l = DSI_VC_IRQ_ERROR_MASK;
584 for (i = 0; i < 4; ++i)
585 dsi_write_reg(DSI_VC_IRQENABLE(i), l);
586
587 /* XXX zonda responds incorrectly, causing control error:
588 Exit from LP-ESC mode to LP11 uses wrong transition states on the
589 data lines LP0 and LN0. */
590 dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE,
591 -1 & (~DSI_CIO_IRQ_ERRCONTROL2));
592}
593
594static u32 dsi_get_errors(void)
595{
596 unsigned long flags;
597 u32 e;
598 spin_lock_irqsave(&dsi.errors_lock, flags);
599 e = dsi.errors;
600 dsi.errors = 0;
601 spin_unlock_irqrestore(&dsi.errors_lock, flags);
602 return e;
603}
604
605static void dsi_vc_enable_bta_irq(int channel)
606{
607 u32 l;
608
609 dsi_write_reg(DSI_VC_IRQSTATUS(channel), DSI_VC_IRQ_BTA);
610
611 l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
612 l |= DSI_VC_IRQ_BTA;
613 dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
614}
615
616static void dsi_vc_disable_bta_irq(int channel)
617{
618 u32 l;
619
620 l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
621 l &= ~DSI_VC_IRQ_BTA;
622 dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
623}
624
625/* DSI func clock. this could also be DSI2_PLL_FCLK */
626static inline void enable_clocks(bool enable)
627{
628 if (enable)
629 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
630 else
631 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
632}
633
634/* source clock for DSI PLL. this could also be PCLKFREE */
635static inline void dsi_enable_pll_clock(bool enable)
636{
637 if (enable)
638 dss_clk_enable(DSS_CLK_FCK2);
639 else
640 dss_clk_disable(DSS_CLK_FCK2);
641
642 if (enable && dsi.pll_locked) {
643 if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1)
644 DSSERR("cannot lock PLL when enabling clocks\n");
645 }
646}
647
648#ifdef DEBUG
649static void _dsi_print_reset_status(void)
650{
651 u32 l;
652
653 if (!dss_debug)
654 return;
655
656 /* A dummy read using the SCP interface to any DSIPHY register is
657 * required after DSIPHY reset to complete the reset of the DSI complex
658 * I/O. */
659 l = dsi_read_reg(DSI_DSIPHY_CFG5);
660
661 printk(KERN_DEBUG "DSI resets: ");
662
663 l = dsi_read_reg(DSI_PLL_STATUS);
664 printk("PLL (%d) ", FLD_GET(l, 0, 0));
665
666 l = dsi_read_reg(DSI_COMPLEXIO_CFG1);
667 printk("CIO (%d) ", FLD_GET(l, 29, 29));
668
669 l = dsi_read_reg(DSI_DSIPHY_CFG5);
670 printk("PHY (%x, %d, %d, %d)\n",
671 FLD_GET(l, 28, 26),
672 FLD_GET(l, 29, 29),
673 FLD_GET(l, 30, 30),
674 FLD_GET(l, 31, 31));
675}
676#else
677#define _dsi_print_reset_status()
678#endif
679
680static inline int dsi_if_enable(bool enable)
681{
682 DSSDBG("dsi_if_enable(%d)\n", enable);
683
684 enable = enable ? 1 : 0;
685 REG_FLD_MOD(DSI_CTRL, enable, 0, 0); /* IF_EN */
686
687 if (wait_for_bit_change(DSI_CTRL, 0, enable) != enable) {
688 DSSERR("Failed to set dsi_if_enable to %d\n", enable);
689 return -EIO;
690 }
691
692 return 0;
693}
694
695unsigned long dsi_get_dsi1_pll_rate(void)
696{
697 return dsi.current_cinfo.dsi1_pll_fclk;
698}
699
700static unsigned long dsi_get_dsi2_pll_rate(void)
701{
702 return dsi.current_cinfo.dsi2_pll_fclk;
703}
704
705static unsigned long dsi_get_txbyteclkhs(void)
706{
707 return dsi.current_cinfo.clkin4ddr / 16;
708}
709
710static unsigned long dsi_fclk_rate(void)
711{
712 unsigned long r;
713
714 if (dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK) {
715 /* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */
716 r = dss_clk_get_rate(DSS_CLK_FCK1);
717 } else {
718 /* DSI FCLK source is DSI2_PLL_FCLK */
719 r = dsi_get_dsi2_pll_rate();
720 }
721
722 return r;
723}
724
725static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev)
726{
727 unsigned long dsi_fclk;
728 unsigned lp_clk_div;
729 unsigned long lp_clk;
730
731 lp_clk_div = dssdev->phy.dsi.div.lp_clk_div;
732
733 if (lp_clk_div == 0 || lp_clk_div > LP_DIV_MAX)
734 return -EINVAL;
735
736 dsi_fclk = dsi_fclk_rate();
737
738 lp_clk = dsi_fclk / 2 / lp_clk_div;
739
740 DSSDBG("LP_CLK_DIV %u, LP_CLK %lu\n", lp_clk_div, lp_clk);
741 dsi.current_cinfo.lp_clk = lp_clk;
742 dsi.current_cinfo.lp_clk_div = lp_clk_div;
743
744 REG_FLD_MOD(DSI_CLK_CTRL, lp_clk_div, 12, 0); /* LP_CLK_DIVISOR */
745
746 REG_FLD_MOD(DSI_CLK_CTRL, dsi_fclk > 30000000 ? 1 : 0,
747 21, 21); /* LP_RX_SYNCHRO_ENABLE */
748
749 return 0;
750}
751
752
753enum dsi_pll_power_state {
754 DSI_PLL_POWER_OFF = 0x0,
755 DSI_PLL_POWER_ON_HSCLK = 0x1,
756 DSI_PLL_POWER_ON_ALL = 0x2,
757 DSI_PLL_POWER_ON_DIV = 0x3,
758};
759
760static int dsi_pll_power(enum dsi_pll_power_state state)
761{
762 int t = 0;
763
764 REG_FLD_MOD(DSI_CLK_CTRL, state, 31, 30); /* PLL_PWR_CMD */
765
766 /* PLL_PWR_STATUS */
767 while (FLD_GET(dsi_read_reg(DSI_CLK_CTRL), 29, 28) != state) {
768 if (++t > 1000) {
769 DSSERR("Failed to set DSI PLL power mode to %d\n",
770 state);
771 return -ENODEV;
772 }
773 udelay(1);
774 }
775
776 return 0;
777}
778
779/* calculate clock rates using dividers in cinfo */
780static int dsi_calc_clock_rates(struct dsi_clock_info *cinfo)
781{
782 if (cinfo->regn == 0 || cinfo->regn > REGN_MAX)
783 return -EINVAL;
784
785 if (cinfo->regm == 0 || cinfo->regm > REGM_MAX)
786 return -EINVAL;
787
788 if (cinfo->regm3 > REGM3_MAX)
789 return -EINVAL;
790
791 if (cinfo->regm4 > REGM4_MAX)
792 return -EINVAL;
793
794 if (cinfo->use_dss2_fck) {
795 cinfo->clkin = dss_clk_get_rate(DSS_CLK_FCK2);
796 /* XXX it is unclear if highfreq should be used
797 * with DSS2_FCK source also */
798 cinfo->highfreq = 0;
799 } else {
800 cinfo->clkin = dispc_pclk_rate();
801
802 if (cinfo->clkin < 32000000)
803 cinfo->highfreq = 0;
804 else
805 cinfo->highfreq = 1;
806 }
807
808 cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1));
809
810 if (cinfo->fint > FINT_MAX || cinfo->fint < FINT_MIN)
811 return -EINVAL;
812
813 cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint;
814
815 if (cinfo->clkin4ddr > 1800 * 1000 * 1000)
816 return -EINVAL;
817
818 if (cinfo->regm3 > 0)
819 cinfo->dsi1_pll_fclk = cinfo->clkin4ddr / cinfo->regm3;
820 else
821 cinfo->dsi1_pll_fclk = 0;
822
823 if (cinfo->regm4 > 0)
824 cinfo->dsi2_pll_fclk = cinfo->clkin4ddr / cinfo->regm4;
825 else
826 cinfo->dsi2_pll_fclk = 0;
827
828 return 0;
829}
830
831int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck,
832 struct dsi_clock_info *dsi_cinfo,
833 struct dispc_clock_info *dispc_cinfo)
834{
835 struct dsi_clock_info cur, best;
836 struct dispc_clock_info best_dispc;
837 int min_fck_per_pck;
838 int match = 0;
839 unsigned long dss_clk_fck2;
840
841 dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2);
842
843 if (req_pck == dsi.cache_req_pck &&
844 dsi.cache_cinfo.clkin == dss_clk_fck2) {
845 DSSDBG("DSI clock info found from cache\n");
846 *dsi_cinfo = dsi.cache_cinfo;
847 dispc_find_clk_divs(is_tft, req_pck, dsi_cinfo->dsi1_pll_fclk,
848 dispc_cinfo);
849 return 0;
850 }
851
852 min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
853
854 if (min_fck_per_pck &&
855 req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
856 DSSERR("Requested pixel clock not possible with the current "
857 "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
858 "the constraint off.\n");
859 min_fck_per_pck = 0;
860 }
861
862 DSSDBG("dsi_pll_calc\n");
863
864retry:
865 memset(&best, 0, sizeof(best));
866 memset(&best_dispc, 0, sizeof(best_dispc));
867
868 memset(&cur, 0, sizeof(cur));
869 cur.clkin = dss_clk_fck2;
870 cur.use_dss2_fck = 1;
871 cur.highfreq = 0;
872
873 /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */
874 /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
875 /* To reduce PLL lock time, keep Fint high (around 2 MHz) */
876 for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) {
877 if (cur.highfreq == 0)
878 cur.fint = cur.clkin / cur.regn;
879 else
880 cur.fint = cur.clkin / (2 * cur.regn);
881
882 if (cur.fint > FINT_MAX || cur.fint < FINT_MIN)
883 continue;
884
885 /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */
886 for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) {
887 unsigned long a, b;
888
889 a = 2 * cur.regm * (cur.clkin/1000);
890 b = cur.regn * (cur.highfreq + 1);
891 cur.clkin4ddr = a / b * 1000;
892
893 if (cur.clkin4ddr > 1800 * 1000 * 1000)
894 break;
895
896 /* DSI1_PLL_FCLK(MHz) = DSIPHY(MHz) / regm3 < 173MHz */
897 for (cur.regm3 = 1; cur.regm3 < REGM3_MAX;
898 ++cur.regm3) {
899 struct dispc_clock_info cur_dispc;
900 cur.dsi1_pll_fclk = cur.clkin4ddr / cur.regm3;
901
902 /* this will narrow down the search a bit,
903 * but still give pixclocks below what was
904 * requested */
905 if (cur.dsi1_pll_fclk < req_pck)
906 break;
907
908 if (cur.dsi1_pll_fclk > DISPC_MAX_FCK)
909 continue;
910
911 if (min_fck_per_pck &&
912 cur.dsi1_pll_fclk <
913 req_pck * min_fck_per_pck)
914 continue;
915
916 match = 1;
917
918 dispc_find_clk_divs(is_tft, req_pck,
919 cur.dsi1_pll_fclk,
920 &cur_dispc);
921
922 if (abs(cur_dispc.pck - req_pck) <
923 abs(best_dispc.pck - req_pck)) {
924 best = cur;
925 best_dispc = cur_dispc;
926
927 if (cur_dispc.pck == req_pck)
928 goto found;
929 }
930 }
931 }
932 }
933found:
934 if (!match) {
935 if (min_fck_per_pck) {
936 DSSERR("Could not find suitable clock settings.\n"
937 "Turning FCK/PCK constraint off and"
938 "trying again.\n");
939 min_fck_per_pck = 0;
940 goto retry;
941 }
942
943 DSSERR("Could not find suitable clock settings.\n");
944
945 return -EINVAL;
946 }
947
948 /* DSI2_PLL_FCLK (regm4) is not used */
949 best.regm4 = 0;
950 best.dsi2_pll_fclk = 0;
951
952 if (dsi_cinfo)
953 *dsi_cinfo = best;
954 if (dispc_cinfo)
955 *dispc_cinfo = best_dispc;
956
957 dsi.cache_req_pck = req_pck;
958 dsi.cache_clk_freq = 0;
959 dsi.cache_cinfo = best;
960
961 return 0;
962}
963
964int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo)
965{
966 int r = 0;
967 u32 l;
968 int f;
969
970 DSSDBGF();
971
972 dsi.current_cinfo.fint = cinfo->fint;
973 dsi.current_cinfo.clkin4ddr = cinfo->clkin4ddr;
974 dsi.current_cinfo.dsi1_pll_fclk = cinfo->dsi1_pll_fclk;
975 dsi.current_cinfo.dsi2_pll_fclk = cinfo->dsi2_pll_fclk;
976
977 dsi.current_cinfo.regn = cinfo->regn;
978 dsi.current_cinfo.regm = cinfo->regm;
979 dsi.current_cinfo.regm3 = cinfo->regm3;
980 dsi.current_cinfo.regm4 = cinfo->regm4;
981
982 DSSDBG("DSI Fint %ld\n", cinfo->fint);
983
984 DSSDBG("clkin (%s) rate %ld, highfreq %d\n",
985 cinfo->use_dss2_fck ? "dss2_fck" : "pclkfree",
986 cinfo->clkin,
987 cinfo->highfreq);
988
989 /* DSIPHY == CLKIN4DDR */
990 DSSDBG("CLKIN4DDR = 2 * %d / %d * %lu / %d = %lu\n",
991 cinfo->regm,
992 cinfo->regn,
993 cinfo->clkin,
994 cinfo->highfreq + 1,
995 cinfo->clkin4ddr);
996
997 DSSDBG("Data rate on 1 DSI lane %ld Mbps\n",
998 cinfo->clkin4ddr / 1000 / 1000 / 2);
999
1000 DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4);
1001
1002 DSSDBG("regm3 = %d, dsi1_pll_fclk = %lu\n",
1003 cinfo->regm3, cinfo->dsi1_pll_fclk);
1004 DSSDBG("regm4 = %d, dsi2_pll_fclk = %lu\n",
1005 cinfo->regm4, cinfo->dsi2_pll_fclk);
1006
1007 REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */
1008
1009 l = dsi_read_reg(DSI_PLL_CONFIGURATION1);
1010 l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */
1011 l = FLD_MOD(l, cinfo->regn - 1, 7, 1); /* DSI_PLL_REGN */
1012 l = FLD_MOD(l, cinfo->regm, 18, 8); /* DSI_PLL_REGM */
1013 l = FLD_MOD(l, cinfo->regm3 > 0 ? cinfo->regm3 - 1 : 0,
1014 22, 19); /* DSI_CLOCK_DIV */
1015 l = FLD_MOD(l, cinfo->regm4 > 0 ? cinfo->regm4 - 1 : 0,
1016 26, 23); /* DSIPROTO_CLOCK_DIV */
1017 dsi_write_reg(DSI_PLL_CONFIGURATION1, l);
1018
1019 BUG_ON(cinfo->fint < 750000 || cinfo->fint > 2100000);
1020 if (cinfo->fint < 1000000)
1021 f = 0x3;
1022 else if (cinfo->fint < 1250000)
1023 f = 0x4;
1024 else if (cinfo->fint < 1500000)
1025 f = 0x5;
1026 else if (cinfo->fint < 1750000)
1027 f = 0x6;
1028 else
1029 f = 0x7;
1030
1031 l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
1032 l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */
1033 l = FLD_MOD(l, cinfo->use_dss2_fck ? 0 : 1,
1034 11, 11); /* DSI_PLL_CLKSEL */
1035 l = FLD_MOD(l, cinfo->highfreq,
1036 12, 12); /* DSI_PLL_HIGHFREQ */
1037 l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
1038 l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */
1039 l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */
1040 dsi_write_reg(DSI_PLL_CONFIGURATION2, l);
1041
1042 REG_FLD_MOD(DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */
1043
1044 if (wait_for_bit_change(DSI_PLL_GO, 0, 0) != 0) {
1045 DSSERR("dsi pll go bit not going down.\n");
1046 r = -EIO;
1047 goto err;
1048 }
1049
1050 if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) {
1051 DSSERR("cannot lock PLL\n");
1052 r = -EIO;
1053 goto err;
1054 }
1055
1056 dsi.pll_locked = 1;
1057
1058 l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
1059 l = FLD_MOD(l, 0, 0, 0); /* DSI_PLL_IDLE */
1060 l = FLD_MOD(l, 0, 5, 5); /* DSI_PLL_PLLLPMODE */
1061 l = FLD_MOD(l, 0, 6, 6); /* DSI_PLL_LOWCURRSTBY */
1062 l = FLD_MOD(l, 0, 7, 7); /* DSI_PLL_TIGHTPHASELOCK */
1063 l = FLD_MOD(l, 0, 8, 8); /* DSI_PLL_DRIFTGUARDEN */
1064 l = FLD_MOD(l, 0, 10, 9); /* DSI_PLL_LOCKSEL */
1065 l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
1066 l = FLD_MOD(l, 1, 14, 14); /* DSIPHY_CLKINEN */
1067 l = FLD_MOD(l, 0, 15, 15); /* DSI_BYPASSEN */
1068 l = FLD_MOD(l, 1, 16, 16); /* DSS_CLOCK_EN */
1069 l = FLD_MOD(l, 0, 17, 17); /* DSS_CLOCK_PWDN */
1070 l = FLD_MOD(l, 1, 18, 18); /* DSI_PROTO_CLOCK_EN */
1071 l = FLD_MOD(l, 0, 19, 19); /* DSI_PROTO_CLOCK_PWDN */
1072 l = FLD_MOD(l, 0, 20, 20); /* DSI_HSDIVBYPASS */
1073 dsi_write_reg(DSI_PLL_CONFIGURATION2, l);
1074
1075 DSSDBG("PLL config done\n");
1076err:
1077 return r;
1078}
1079
1080int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk,
1081 bool enable_hsdiv)
1082{
1083 int r = 0;
1084 enum dsi_pll_power_state pwstate;
1085
1086 DSSDBG("PLL init\n");
1087
1088 enable_clocks(1);
1089 dsi_enable_pll_clock(1);
1090
1091 r = regulator_enable(dsi.vdds_dsi_reg);
1092 if (r)
1093 goto err0;
1094
1095 /* XXX PLL does not come out of reset without this... */
1096 dispc_pck_free_enable(1);
1097
1098 if (wait_for_bit_change(DSI_PLL_STATUS, 0, 1) != 1) {
1099 DSSERR("PLL not coming out of reset.\n");
1100 r = -ENODEV;
1101 goto err1;
1102 }
1103
1104 /* XXX ... but if left on, we get problems when planes do not
1105 * fill the whole display. No idea about this */
1106 dispc_pck_free_enable(0);
1107
1108 if (enable_hsclk && enable_hsdiv)
1109 pwstate = DSI_PLL_POWER_ON_ALL;
1110 else if (enable_hsclk)
1111 pwstate = DSI_PLL_POWER_ON_HSCLK;
1112 else if (enable_hsdiv)
1113 pwstate = DSI_PLL_POWER_ON_DIV;
1114 else
1115 pwstate = DSI_PLL_POWER_OFF;
1116
1117 r = dsi_pll_power(pwstate);
1118
1119 if (r)
1120 goto err1;
1121
1122 DSSDBG("PLL init done\n");
1123
1124 return 0;
1125err1:
1126 regulator_disable(dsi.vdds_dsi_reg);
1127err0:
1128 enable_clocks(0);
1129 dsi_enable_pll_clock(0);
1130 return r;
1131}
1132
1133void dsi_pll_uninit(void)
1134{
1135 enable_clocks(0);
1136 dsi_enable_pll_clock(0);
1137
1138 dsi.pll_locked = 0;
1139 dsi_pll_power(DSI_PLL_POWER_OFF);
1140 regulator_disable(dsi.vdds_dsi_reg);
1141 DSSDBG("PLL uninit done\n");
1142}
1143
1144void dsi_dump_clocks(struct seq_file *s)
1145{
1146 int clksel;
1147 struct dsi_clock_info *cinfo = &dsi.current_cinfo;
1148
1149 enable_clocks(1);
1150
1151 clksel = REG_GET(DSI_PLL_CONFIGURATION2, 11, 11);
1152
1153 seq_printf(s, "- DSI PLL -\n");
1154
1155 seq_printf(s, "dsi pll source = %s\n",
1156 clksel == 0 ?
1157 "dss2_alwon_fclk" : "pclkfree");
1158
1159 seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn);
1160
1161 seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n",
1162 cinfo->clkin4ddr, cinfo->regm);
1163
1164 seq_printf(s, "dsi1_pll_fck\t%-16luregm3 %u\t(%s)\n",
1165 cinfo->dsi1_pll_fclk,
1166 cinfo->regm3,
1167 dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ?
1168 "off" : "on");
1169
1170 seq_printf(s, "dsi2_pll_fck\t%-16luregm4 %u\t(%s)\n",
1171 cinfo->dsi2_pll_fclk,
1172 cinfo->regm4,
1173 dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ?
1174 "off" : "on");
1175
1176 seq_printf(s, "- DSI -\n");
1177
1178 seq_printf(s, "dsi fclk source = %s\n",
1179 dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ?
1180 "dss1_alwon_fclk" : "dsi2_pll_fclk");
1181
1182 seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate());
1183
1184 seq_printf(s, "DDR_CLK\t\t%lu\n",
1185 cinfo->clkin4ddr / 4);
1186
1187 seq_printf(s, "TxByteClkHS\t%lu\n", dsi_get_txbyteclkhs());
1188
1189 seq_printf(s, "LP_CLK\t\t%lu\n", cinfo->lp_clk);
1190
1191 seq_printf(s, "VP_CLK\t\t%lu\n"
1192 "VP_PCLK\t\t%lu\n",
1193 dispc_lclk_rate(),
1194 dispc_pclk_rate());
1195
1196 enable_clocks(0);
1197}
1198
1199#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
1200void dsi_dump_irqs(struct seq_file *s)
1201{
1202 unsigned long flags;
1203 struct dsi_irq_stats stats;
1204
1205 spin_lock_irqsave(&dsi.irq_stats_lock, flags);
1206
1207 stats = dsi.irq_stats;
1208 memset(&dsi.irq_stats, 0, sizeof(dsi.irq_stats));
1209 dsi.irq_stats.last_reset = jiffies;
1210
1211 spin_unlock_irqrestore(&dsi.irq_stats_lock, flags);
1212
1213 seq_printf(s, "period %u ms\n",
1214 jiffies_to_msecs(jiffies - stats.last_reset));
1215
1216 seq_printf(s, "irqs %d\n", stats.irq_count);
1217#define PIS(x) \
1218 seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]);
1219
1220 seq_printf(s, "-- DSI interrupts --\n");
1221 PIS(VC0);
1222 PIS(VC1);
1223 PIS(VC2);
1224 PIS(VC3);
1225 PIS(WAKEUP);
1226 PIS(RESYNC);
1227 PIS(PLL_LOCK);
1228 PIS(PLL_UNLOCK);
1229 PIS(PLL_RECALL);
1230 PIS(COMPLEXIO_ERR);
1231 PIS(HS_TX_TIMEOUT);
1232 PIS(LP_RX_TIMEOUT);
1233 PIS(TE_TRIGGER);
1234 PIS(ACK_TRIGGER);
1235 PIS(SYNC_LOST);
1236 PIS(LDO_POWER_GOOD);
1237 PIS(TA_TIMEOUT);
1238#undef PIS
1239
1240#define PIS(x) \
1241 seq_printf(s, "%-20s %10d %10d %10d %10d\n", #x, \
1242 stats.vc_irqs[0][ffs(DSI_VC_IRQ_##x)-1], \
1243 stats.vc_irqs[1][ffs(DSI_VC_IRQ_##x)-1], \
1244 stats.vc_irqs[2][ffs(DSI_VC_IRQ_##x)-1], \
1245 stats.vc_irqs[3][ffs(DSI_VC_IRQ_##x)-1]);
1246
1247 seq_printf(s, "-- VC interrupts --\n");
1248 PIS(CS);
1249 PIS(ECC_CORR);
1250 PIS(PACKET_SENT);
1251 PIS(FIFO_TX_OVF);
1252 PIS(FIFO_RX_OVF);
1253 PIS(BTA);
1254 PIS(ECC_NO_CORR);
1255 PIS(FIFO_TX_UDF);
1256 PIS(PP_BUSY_CHANGE);
1257#undef PIS
1258
1259#define PIS(x) \
1260 seq_printf(s, "%-20s %10d\n", #x, \
1261 stats.cio_irqs[ffs(DSI_CIO_IRQ_##x)-1]);
1262
1263 seq_printf(s, "-- CIO interrupts --\n");
1264 PIS(ERRSYNCESC1);
1265 PIS(ERRSYNCESC2);
1266 PIS(ERRSYNCESC3);
1267 PIS(ERRESC1);
1268 PIS(ERRESC2);
1269 PIS(ERRESC3);
1270 PIS(ERRCONTROL1);
1271 PIS(ERRCONTROL2);
1272 PIS(ERRCONTROL3);
1273 PIS(STATEULPS1);
1274 PIS(STATEULPS2);
1275 PIS(STATEULPS3);
1276 PIS(ERRCONTENTIONLP0_1);
1277 PIS(ERRCONTENTIONLP1_1);
1278 PIS(ERRCONTENTIONLP0_2);
1279 PIS(ERRCONTENTIONLP1_2);
1280 PIS(ERRCONTENTIONLP0_3);
1281 PIS(ERRCONTENTIONLP1_3);
1282 PIS(ULPSACTIVENOT_ALL0);
1283 PIS(ULPSACTIVENOT_ALL1);
1284#undef PIS
1285}
1286#endif
1287
1288void dsi_dump_regs(struct seq_file *s)
1289{
1290#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r))
1291
1292 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
1293
1294 DUMPREG(DSI_REVISION);
1295 DUMPREG(DSI_SYSCONFIG);
1296 DUMPREG(DSI_SYSSTATUS);
1297 DUMPREG(DSI_IRQSTATUS);
1298 DUMPREG(DSI_IRQENABLE);
1299 DUMPREG(DSI_CTRL);
1300 DUMPREG(DSI_COMPLEXIO_CFG1);
1301 DUMPREG(DSI_COMPLEXIO_IRQ_STATUS);
1302 DUMPREG(DSI_COMPLEXIO_IRQ_ENABLE);
1303 DUMPREG(DSI_CLK_CTRL);
1304 DUMPREG(DSI_TIMING1);
1305 DUMPREG(DSI_TIMING2);
1306 DUMPREG(DSI_VM_TIMING1);
1307 DUMPREG(DSI_VM_TIMING2);
1308 DUMPREG(DSI_VM_TIMING3);
1309 DUMPREG(DSI_CLK_TIMING);
1310 DUMPREG(DSI_TX_FIFO_VC_SIZE);
1311 DUMPREG(DSI_RX_FIFO_VC_SIZE);
1312 DUMPREG(DSI_COMPLEXIO_CFG2);
1313 DUMPREG(DSI_RX_FIFO_VC_FULLNESS);
1314 DUMPREG(DSI_VM_TIMING4);
1315 DUMPREG(DSI_TX_FIFO_VC_EMPTINESS);
1316 DUMPREG(DSI_VM_TIMING5);
1317 DUMPREG(DSI_VM_TIMING6);
1318 DUMPREG(DSI_VM_TIMING7);
1319 DUMPREG(DSI_STOPCLK_TIMING);
1320
1321 DUMPREG(DSI_VC_CTRL(0));
1322 DUMPREG(DSI_VC_TE(0));
1323 DUMPREG(DSI_VC_LONG_PACKET_HEADER(0));
1324 DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(0));
1325 DUMPREG(DSI_VC_SHORT_PACKET_HEADER(0));
1326 DUMPREG(DSI_VC_IRQSTATUS(0));
1327 DUMPREG(DSI_VC_IRQENABLE(0));
1328
1329 DUMPREG(DSI_VC_CTRL(1));
1330 DUMPREG(DSI_VC_TE(1));
1331 DUMPREG(DSI_VC_LONG_PACKET_HEADER(1));
1332 DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(1));
1333 DUMPREG(DSI_VC_SHORT_PACKET_HEADER(1));
1334 DUMPREG(DSI_VC_IRQSTATUS(1));
1335 DUMPREG(DSI_VC_IRQENABLE(1));
1336
1337 DUMPREG(DSI_VC_CTRL(2));
1338 DUMPREG(DSI_VC_TE(2));
1339 DUMPREG(DSI_VC_LONG_PACKET_HEADER(2));
1340 DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(2));
1341 DUMPREG(DSI_VC_SHORT_PACKET_HEADER(2));
1342 DUMPREG(DSI_VC_IRQSTATUS(2));
1343 DUMPREG(DSI_VC_IRQENABLE(2));
1344
1345 DUMPREG(DSI_VC_CTRL(3));
1346 DUMPREG(DSI_VC_TE(3));
1347 DUMPREG(DSI_VC_LONG_PACKET_HEADER(3));
1348 DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(3));
1349 DUMPREG(DSI_VC_SHORT_PACKET_HEADER(3));
1350 DUMPREG(DSI_VC_IRQSTATUS(3));
1351 DUMPREG(DSI_VC_IRQENABLE(3));
1352
1353 DUMPREG(DSI_DSIPHY_CFG0);
1354 DUMPREG(DSI_DSIPHY_CFG1);
1355 DUMPREG(DSI_DSIPHY_CFG2);
1356 DUMPREG(DSI_DSIPHY_CFG5);
1357
1358 DUMPREG(DSI_PLL_CONTROL);
1359 DUMPREG(DSI_PLL_STATUS);
1360 DUMPREG(DSI_PLL_GO);
1361 DUMPREG(DSI_PLL_CONFIGURATION1);
1362 DUMPREG(DSI_PLL_CONFIGURATION2);
1363
1364 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
1365#undef DUMPREG
1366}
1367
1368enum dsi_complexio_power_state {
1369 DSI_COMPLEXIO_POWER_OFF = 0x0,
1370 DSI_COMPLEXIO_POWER_ON = 0x1,
1371 DSI_COMPLEXIO_POWER_ULPS = 0x2,
1372};
1373
1374static int dsi_complexio_power(enum dsi_complexio_power_state state)
1375{
1376 int t = 0;
1377
1378 /* PWR_CMD */
1379 REG_FLD_MOD(DSI_COMPLEXIO_CFG1, state, 28, 27);
1380
1381 /* PWR_STATUS */
1382 while (FLD_GET(dsi_read_reg(DSI_COMPLEXIO_CFG1), 26, 25) != state) {
1383 if (++t > 1000) {
1384 DSSERR("failed to set complexio power state to "
1385 "%d\n", state);
1386 return -ENODEV;
1387 }
1388 udelay(1);
1389 }
1390
1391 return 0;
1392}
1393
1394static void dsi_complexio_config(struct omap_dss_device *dssdev)
1395{
1396 u32 r;
1397
1398 int clk_lane = dssdev->phy.dsi.clk_lane;
1399 int data1_lane = dssdev->phy.dsi.data1_lane;
1400 int data2_lane = dssdev->phy.dsi.data2_lane;
1401 int clk_pol = dssdev->phy.dsi.clk_pol;
1402 int data1_pol = dssdev->phy.dsi.data1_pol;
1403 int data2_pol = dssdev->phy.dsi.data2_pol;
1404
1405 r = dsi_read_reg(DSI_COMPLEXIO_CFG1);
1406 r = FLD_MOD(r, clk_lane, 2, 0);
1407 r = FLD_MOD(r, clk_pol, 3, 3);
1408 r = FLD_MOD(r, data1_lane, 6, 4);
1409 r = FLD_MOD(r, data1_pol, 7, 7);
1410 r = FLD_MOD(r, data2_lane, 10, 8);
1411 r = FLD_MOD(r, data2_pol, 11, 11);
1412 dsi_write_reg(DSI_COMPLEXIO_CFG1, r);
1413
1414 /* The configuration of the DSI complex I/O (number of data lanes,
1415 position, differential order) should not be changed while
1416 DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. In order for
1417 the hardware to take into account a new configuration of the complex
1418 I/O (done in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to
1419 follow this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1,
1420 then reset the DSS.DSI_CTRL[0] IF_EN to 0, then set
1421 DSS.DSI_CLK_CTRL[20] LP_CLK_ENABLE to 1 and finally set again the
1422 DSS.DSI_CTRL[0] IF_EN bit to 1. If the sequence is not followed, the
1423 DSI complex I/O configuration is unknown. */
1424
1425 /*
1426 REG_FLD_MOD(DSI_CTRL, 1, 0, 0);
1427 REG_FLD_MOD(DSI_CTRL, 0, 0, 0);
1428 REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20);
1429 REG_FLD_MOD(DSI_CTRL, 1, 0, 0);
1430 */
1431}
1432
1433static inline unsigned ns2ddr(unsigned ns)
1434{
1435 /* convert time in ns to ddr ticks, rounding up */
1436 unsigned long ddr_clk = dsi.current_cinfo.clkin4ddr / 4;
1437 return (ns * (ddr_clk / 1000 / 1000) + 999) / 1000;
1438}
1439
1440static inline unsigned ddr2ns(unsigned ddr)
1441{
1442 unsigned long ddr_clk = dsi.current_cinfo.clkin4ddr / 4;
1443 return ddr * 1000 * 1000 / (ddr_clk / 1000);
1444}
1445
1446static void dsi_complexio_timings(void)
1447{
1448 u32 r;
1449 u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit;
1450 u32 tlpx_half, tclk_trail, tclk_zero;
1451 u32 tclk_prepare;
1452
1453 /* calculate timings */
1454
1455 /* 1 * DDR_CLK = 2 * UI */
1456
1457 /* min 40ns + 4*UI max 85ns + 6*UI */
1458 ths_prepare = ns2ddr(70) + 2;
1459
1460 /* min 145ns + 10*UI */
1461 ths_prepare_ths_zero = ns2ddr(175) + 2;
1462
1463 /* min max(8*UI, 60ns+4*UI) */
1464 ths_trail = ns2ddr(60) + 5;
1465
1466 /* min 100ns */
1467 ths_exit = ns2ddr(145);
1468
1469 /* tlpx min 50n */
1470 tlpx_half = ns2ddr(25);
1471
1472 /* min 60ns */
1473 tclk_trail = ns2ddr(60) + 2;
1474
1475 /* min 38ns, max 95ns */
1476 tclk_prepare = ns2ddr(65);
1477
1478 /* min tclk-prepare + tclk-zero = 300ns */
1479 tclk_zero = ns2ddr(260);
1480
1481 DSSDBG("ths_prepare %u (%uns), ths_prepare_ths_zero %u (%uns)\n",
1482 ths_prepare, ddr2ns(ths_prepare),
1483 ths_prepare_ths_zero, ddr2ns(ths_prepare_ths_zero));
1484 DSSDBG("ths_trail %u (%uns), ths_exit %u (%uns)\n",
1485 ths_trail, ddr2ns(ths_trail),
1486 ths_exit, ddr2ns(ths_exit));
1487
1488 DSSDBG("tlpx_half %u (%uns), tclk_trail %u (%uns), "
1489 "tclk_zero %u (%uns)\n",
1490 tlpx_half, ddr2ns(tlpx_half),
1491 tclk_trail, ddr2ns(tclk_trail),
1492 tclk_zero, ddr2ns(tclk_zero));
1493 DSSDBG("tclk_prepare %u (%uns)\n",
1494 tclk_prepare, ddr2ns(tclk_prepare));
1495
1496 /* program timings */
1497
1498 r = dsi_read_reg(DSI_DSIPHY_CFG0);
1499 r = FLD_MOD(r, ths_prepare, 31, 24);
1500 r = FLD_MOD(r, ths_prepare_ths_zero, 23, 16);
1501 r = FLD_MOD(r, ths_trail, 15, 8);
1502 r = FLD_MOD(r, ths_exit, 7, 0);
1503 dsi_write_reg(DSI_DSIPHY_CFG0, r);
1504
1505 r = dsi_read_reg(DSI_DSIPHY_CFG1);
1506 r = FLD_MOD(r, tlpx_half, 22, 16);
1507 r = FLD_MOD(r, tclk_trail, 15, 8);
1508 r = FLD_MOD(r, tclk_zero, 7, 0);
1509 dsi_write_reg(DSI_DSIPHY_CFG1, r);
1510
1511 r = dsi_read_reg(DSI_DSIPHY_CFG2);
1512 r = FLD_MOD(r, tclk_prepare, 7, 0);
1513 dsi_write_reg(DSI_DSIPHY_CFG2, r);
1514}
1515
1516
1517static int dsi_complexio_init(struct omap_dss_device *dssdev)
1518{
1519 int r = 0;
1520
1521 DSSDBG("dsi_complexio_init\n");
1522
1523 /* CIO_CLK_ICG, enable L3 clk to CIO */
1524 REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14);
1525
1526 /* A dummy read using the SCP interface to any DSIPHY register is
1527 * required after DSIPHY reset to complete the reset of the DSI complex
1528 * I/O. */
1529 dsi_read_reg(DSI_DSIPHY_CFG5);
1530
1531 if (wait_for_bit_change(DSI_DSIPHY_CFG5, 30, 1) != 1) {
1532 DSSERR("ComplexIO PHY not coming out of reset.\n");
1533 r = -ENODEV;
1534 goto err;
1535 }
1536
1537 dsi_complexio_config(dssdev);
1538
1539 r = dsi_complexio_power(DSI_COMPLEXIO_POWER_ON);
1540
1541 if (r)
1542 goto err;
1543
1544 if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 29, 1) != 1) {
1545 DSSERR("ComplexIO not coming out of reset.\n");
1546 r = -ENODEV;
1547 goto err;
1548 }
1549
1550 if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) {
1551 DSSERR("ComplexIO LDO power down.\n");
1552 r = -ENODEV;
1553 goto err;
1554 }
1555
1556 dsi_complexio_timings();
1557
1558 /*
1559 The configuration of the DSI complex I/O (number of data lanes,
1560 position, differential order) should not be changed while
1561 DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. For the
1562 hardware to recognize a new configuration of the complex I/O (done
1563 in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to follow
1564 this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1, next
1565 reset the DSS.DSI_CTRL[0] IF_EN to 0, then set DSS.DSI_CLK_CTRL[20]
1566 LP_CLK_ENABLE to 1, and finally, set again the DSS.DSI_CTRL[0] IF_EN
1567 bit to 1. If the sequence is not followed, the DSi complex I/O
1568 configuration is undetermined.
1569 */
1570 dsi_if_enable(1);
1571 dsi_if_enable(0);
1572 REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */
1573 dsi_if_enable(1);
1574 dsi_if_enable(0);
1575
1576 DSSDBG("CIO init done\n");
1577err:
1578 return r;
1579}
1580
1581static void dsi_complexio_uninit(void)
1582{
1583 dsi_complexio_power(DSI_COMPLEXIO_POWER_OFF);
1584}
1585
1586static int _dsi_wait_reset(void)
1587{
1588 int t = 0;
1589
1590 while (REG_GET(DSI_SYSSTATUS, 0, 0) == 0) {
1591 if (++t > 5) {
1592 DSSERR("soft reset failed\n");
1593 return -ENODEV;
1594 }
1595 udelay(1);
1596 }
1597
1598 return 0;
1599}
1600
1601static int _dsi_reset(void)
1602{
1603 /* Soft reset */
1604 REG_FLD_MOD(DSI_SYSCONFIG, 1, 1, 1);
1605 return _dsi_wait_reset();
1606}
1607
1608static void dsi_reset_tx_fifo(int channel)
1609{
1610 u32 mask;
1611 u32 l;
1612
1613 /* set fifosize of the channel to 0, then return the old size */
1614 l = dsi_read_reg(DSI_TX_FIFO_VC_SIZE);
1615
1616 mask = FLD_MASK((8 * channel) + 7, (8 * channel) + 4);
1617 dsi_write_reg(DSI_TX_FIFO_VC_SIZE, l & ~mask);
1618
1619 dsi_write_reg(DSI_TX_FIFO_VC_SIZE, l);
1620}
1621
1622static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2,
1623 enum fifo_size size3, enum fifo_size size4)
1624{
1625 u32 r = 0;
1626 int add = 0;
1627 int i;
1628
1629 dsi.vc[0].fifo_size = size1;
1630 dsi.vc[1].fifo_size = size2;
1631 dsi.vc[2].fifo_size = size3;
1632 dsi.vc[3].fifo_size = size4;
1633
1634 for (i = 0; i < 4; i++) {
1635 u8 v;
1636 int size = dsi.vc[i].fifo_size;
1637
1638 if (add + size > 4) {
1639 DSSERR("Illegal FIFO configuration\n");
1640 BUG();
1641 }
1642
1643 v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
1644 r |= v << (8 * i);
1645 /*DSSDBG("TX FIFO vc %d: size %d, add %d\n", i, size, add); */
1646 add += size;
1647 }
1648
1649 dsi_write_reg(DSI_TX_FIFO_VC_SIZE, r);
1650}
1651
1652static void dsi_config_rx_fifo(enum fifo_size size1, enum fifo_size size2,
1653 enum fifo_size size3, enum fifo_size size4)
1654{
1655 u32 r = 0;
1656 int add = 0;
1657 int i;
1658
1659 dsi.vc[0].fifo_size = size1;
1660 dsi.vc[1].fifo_size = size2;
1661 dsi.vc[2].fifo_size = size3;
1662 dsi.vc[3].fifo_size = size4;
1663
1664 for (i = 0; i < 4; i++) {
1665 u8 v;
1666 int size = dsi.vc[i].fifo_size;
1667
1668 if (add + size > 4) {
1669 DSSERR("Illegal FIFO configuration\n");
1670 BUG();
1671 }
1672
1673 v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
1674 r |= v << (8 * i);
1675 /*DSSDBG("RX FIFO vc %d: size %d, add %d\n", i, size, add); */
1676 add += size;
1677 }
1678
1679 dsi_write_reg(DSI_RX_FIFO_VC_SIZE, r);
1680}
1681
1682static int dsi_force_tx_stop_mode_io(void)
1683{
1684 u32 r;
1685
1686 r = dsi_read_reg(DSI_TIMING1);
1687 r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
1688 dsi_write_reg(DSI_TIMING1, r);
1689
1690 if (wait_for_bit_change(DSI_TIMING1, 15, 0) != 0) {
1691 DSSERR("TX_STOP bit not going down\n");
1692 return -EIO;
1693 }
1694
1695 return 0;
1696}
1697
1698static int dsi_vc_enable(int channel, bool enable)
1699{
1700 DSSDBG("dsi_vc_enable channel %d, enable %d\n",
1701 channel, enable);
1702
1703 enable = enable ? 1 : 0;
1704
1705 REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 0, 0);
1706
1707 if (wait_for_bit_change(DSI_VC_CTRL(channel), 0, enable) != enable) {
1708 DSSERR("Failed to set dsi_vc_enable to %d\n", enable);
1709 return -EIO;
1710 }
1711
1712 return 0;
1713}
1714
1715static void dsi_vc_initial_config(int channel)
1716{
1717 u32 r;
1718
1719 DSSDBGF("%d", channel);
1720
1721 r = dsi_read_reg(DSI_VC_CTRL(channel));
1722
1723 if (FLD_GET(r, 15, 15)) /* VC_BUSY */
1724 DSSERR("VC(%d) busy when trying to configure it!\n",
1725 channel);
1726
1727 r = FLD_MOD(r, 0, 1, 1); /* SOURCE, 0 = L4 */
1728 r = FLD_MOD(r, 0, 2, 2); /* BTA_SHORT_EN */
1729 r = FLD_MOD(r, 0, 3, 3); /* BTA_LONG_EN */
1730 r = FLD_MOD(r, 0, 4, 4); /* MODE, 0 = command */
1731 r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */
1732 r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */
1733 r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */
1734
1735 r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */
1736 r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
1737
1738 dsi_write_reg(DSI_VC_CTRL(channel), r);
1739
1740 dsi.vc[channel].mode = DSI_VC_MODE_L4;
1741}
1742
1743static void dsi_vc_config_l4(int channel)
1744{
1745 if (dsi.vc[channel].mode == DSI_VC_MODE_L4)
1746 return;
1747
1748 DSSDBGF("%d", channel);
1749
1750 dsi_vc_enable(channel, 0);
1751
1752 if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */
1753 DSSERR("vc(%d) busy when trying to config for L4\n", channel);
1754
1755 REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */
1756
1757 dsi_vc_enable(channel, 1);
1758
1759 dsi.vc[channel].mode = DSI_VC_MODE_L4;
1760}
1761
1762static void dsi_vc_config_vp(int channel)
1763{
1764 if (dsi.vc[channel].mode == DSI_VC_MODE_VP)
1765 return;
1766
1767 DSSDBGF("%d", channel);
1768
1769 dsi_vc_enable(channel, 0);
1770
1771 if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */
1772 DSSERR("vc(%d) busy when trying to config for VP\n", channel);
1773
1774 REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */
1775
1776 dsi_vc_enable(channel, 1);
1777
1778 dsi.vc[channel].mode = DSI_VC_MODE_VP;
1779}
1780
1781
1782void omapdss_dsi_vc_enable_hs(int channel, bool enable)
1783{
1784 DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable);
1785
1786 WARN_ON(!dsi_bus_is_locked());
1787
1788 dsi_vc_enable(channel, 0);
1789 dsi_if_enable(0);
1790
1791 REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 9, 9);
1792
1793 dsi_vc_enable(channel, 1);
1794 dsi_if_enable(1);
1795
1796 dsi_force_tx_stop_mode_io();
1797}
1798EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs);
1799
1800static void dsi_vc_flush_long_data(int channel)
1801{
1802 while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
1803 u32 val;
1804 val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
1805 DSSDBG("\t\tb1 %#02x b2 %#02x b3 %#02x b4 %#02x\n",
1806 (val >> 0) & 0xff,
1807 (val >> 8) & 0xff,
1808 (val >> 16) & 0xff,
1809 (val >> 24) & 0xff);
1810 }
1811}
1812
1813static void dsi_show_rx_ack_with_err(u16 err)
1814{
1815 DSSERR("\tACK with ERROR (%#x):\n", err);
1816 if (err & (1 << 0))
1817 DSSERR("\t\tSoT Error\n");
1818 if (err & (1 << 1))
1819 DSSERR("\t\tSoT Sync Error\n");
1820 if (err & (1 << 2))
1821 DSSERR("\t\tEoT Sync Error\n");
1822 if (err & (1 << 3))
1823 DSSERR("\t\tEscape Mode Entry Command Error\n");
1824 if (err & (1 << 4))
1825 DSSERR("\t\tLP Transmit Sync Error\n");
1826 if (err & (1 << 5))
1827 DSSERR("\t\tHS Receive Timeout Error\n");
1828 if (err & (1 << 6))
1829 DSSERR("\t\tFalse Control Error\n");
1830 if (err & (1 << 7))
1831 DSSERR("\t\t(reserved7)\n");
1832 if (err & (1 << 8))
1833 DSSERR("\t\tECC Error, single-bit (corrected)\n");
1834 if (err & (1 << 9))
1835 DSSERR("\t\tECC Error, multi-bit (not corrected)\n");
1836 if (err & (1 << 10))
1837 DSSERR("\t\tChecksum Error\n");
1838 if (err & (1 << 11))
1839 DSSERR("\t\tData type not recognized\n");
1840 if (err & (1 << 12))
1841 DSSERR("\t\tInvalid VC ID\n");
1842 if (err & (1 << 13))
1843 DSSERR("\t\tInvalid Transmission Length\n");
1844 if (err & (1 << 14))
1845 DSSERR("\t\t(reserved14)\n");
1846 if (err & (1 << 15))
1847 DSSERR("\t\tDSI Protocol Violation\n");
1848}
1849
1850static u16 dsi_vc_flush_receive_data(int channel)
1851{
1852 /* RX_FIFO_NOT_EMPTY */
1853 while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
1854 u32 val;
1855 u8 dt;
1856 val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
1857 DSSDBG("\trawval %#08x\n", val);
1858 dt = FLD_GET(val, 5, 0);
1859 if (dt == DSI_DT_RX_ACK_WITH_ERR) {
1860 u16 err = FLD_GET(val, 23, 8);
1861 dsi_show_rx_ack_with_err(err);
1862 } else if (dt == DSI_DT_RX_SHORT_READ_1) {
1863 DSSDBG("\tDCS short response, 1 byte: %#x\n",
1864 FLD_GET(val, 23, 8));
1865 } else if (dt == DSI_DT_RX_SHORT_READ_2) {
1866 DSSDBG("\tDCS short response, 2 byte: %#x\n",
1867 FLD_GET(val, 23, 8));
1868 } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
1869 DSSDBG("\tDCS long response, len %d\n",
1870 FLD_GET(val, 23, 8));
1871 dsi_vc_flush_long_data(channel);
1872 } else {
1873 DSSERR("\tunknown datatype 0x%02x\n", dt);
1874 }
1875 }
1876 return 0;
1877}
1878
1879static int dsi_vc_send_bta(int channel)
1880{
1881 if (dsi.debug_write || dsi.debug_read)
1882 DSSDBG("dsi_vc_send_bta %d\n", channel);
1883
1884 WARN_ON(!dsi_bus_is_locked());
1885
1886 if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { /* RX_FIFO_NOT_EMPTY */
1887 DSSERR("rx fifo not empty when sending BTA, dumping data:\n");
1888 dsi_vc_flush_receive_data(channel);
1889 }
1890
1891 REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */
1892
1893 return 0;
1894}
1895
1896int dsi_vc_send_bta_sync(int channel)
1897{
1898 int r = 0;
1899 u32 err;
1900
1901 INIT_COMPLETION(dsi.bta_completion);
1902
1903 dsi_vc_enable_bta_irq(channel);
1904
1905 r = dsi_vc_send_bta(channel);
1906 if (r)
1907 goto err;
1908
1909 if (wait_for_completion_timeout(&dsi.bta_completion,
1910 msecs_to_jiffies(500)) == 0) {
1911 DSSERR("Failed to receive BTA\n");
1912 r = -EIO;
1913 goto err;
1914 }
1915
1916 err = dsi_get_errors();
1917 if (err) {
1918 DSSERR("Error while sending BTA: %x\n", err);
1919 r = -EIO;
1920 goto err;
1921 }
1922err:
1923 dsi_vc_disable_bta_irq(channel);
1924
1925 return r;
1926}
1927EXPORT_SYMBOL(dsi_vc_send_bta_sync);
1928
1929static inline void dsi_vc_write_long_header(int channel, u8 data_type,
1930 u16 len, u8 ecc)
1931{
1932 u32 val;
1933 u8 data_id;
1934
1935 WARN_ON(!dsi_bus_is_locked());
1936
1937 data_id = data_type | channel << 6;
1938
1939 val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) |
1940 FLD_VAL(ecc, 31, 24);
1941
1942 dsi_write_reg(DSI_VC_LONG_PACKET_HEADER(channel), val);
1943}
1944
1945static inline void dsi_vc_write_long_payload(int channel,
1946 u8 b1, u8 b2, u8 b3, u8 b4)
1947{
1948 u32 val;
1949
1950 val = b4 << 24 | b3 << 16 | b2 << 8 | b1 << 0;
1951
1952/* DSSDBG("\twriting %02x, %02x, %02x, %02x (%#010x)\n",
1953 b1, b2, b3, b4, val); */
1954
1955 dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(channel), val);
1956}
1957
1958static int dsi_vc_send_long(int channel, u8 data_type, u8 *data, u16 len,
1959 u8 ecc)
1960{
1961 /*u32 val; */
1962 int i;
1963 u8 *p;
1964 int r = 0;
1965 u8 b1, b2, b3, b4;
1966
1967 if (dsi.debug_write)
1968 DSSDBG("dsi_vc_send_long, %d bytes\n", len);
1969
1970 /* len + header */
1971 if (dsi.vc[channel].fifo_size * 32 * 4 < len + 4) {
1972 DSSERR("unable to send long packet: packet too long.\n");
1973 return -EINVAL;
1974 }
1975
1976 dsi_vc_config_l4(channel);
1977
1978 dsi_vc_write_long_header(channel, data_type, len, ecc);
1979
1980 p = data;
1981 for (i = 0; i < len >> 2; i++) {
1982 if (dsi.debug_write)
1983 DSSDBG("\tsending full packet %d\n", i);
1984
1985 b1 = *p++;
1986 b2 = *p++;
1987 b3 = *p++;
1988 b4 = *p++;
1989
1990 dsi_vc_write_long_payload(channel, b1, b2, b3, b4);
1991 }
1992
1993 i = len % 4;
1994 if (i) {
1995 b1 = 0; b2 = 0; b3 = 0;
1996
1997 if (dsi.debug_write)
1998 DSSDBG("\tsending remainder bytes %d\n", i);
1999
2000 switch (i) {
2001 case 3:
2002 b1 = *p++;
2003 b2 = *p++;
2004 b3 = *p++;
2005 break;
2006 case 2:
2007 b1 = *p++;
2008 b2 = *p++;
2009 break;
2010 case 1:
2011 b1 = *p++;
2012 break;
2013 }
2014
2015 dsi_vc_write_long_payload(channel, b1, b2, b3, 0);
2016 }
2017
2018 return r;
2019}
2020
2021static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc)
2022{
2023 u32 r;
2024 u8 data_id;
2025
2026 WARN_ON(!dsi_bus_is_locked());
2027
2028 if (dsi.debug_write)
2029 DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n",
2030 channel,
2031 data_type, data & 0xff, (data >> 8) & 0xff);
2032
2033 dsi_vc_config_l4(channel);
2034
2035 if (FLD_GET(dsi_read_reg(DSI_VC_CTRL(channel)), 16, 16)) {
2036 DSSERR("ERROR FIFO FULL, aborting transfer\n");
2037 return -EINVAL;
2038 }
2039
2040 data_id = data_type | channel << 6;
2041
2042 r = (data_id << 0) | (data << 8) | (ecc << 24);
2043
2044 dsi_write_reg(DSI_VC_SHORT_PACKET_HEADER(channel), r);
2045
2046 return 0;
2047}
2048
2049int dsi_vc_send_null(int channel)
2050{
2051 u8 nullpkg[] = {0, 0, 0, 0};
2052 return dsi_vc_send_long(channel, DSI_DT_NULL_PACKET, nullpkg, 4, 0);
2053}
2054EXPORT_SYMBOL(dsi_vc_send_null);
2055
2056int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len)
2057{
2058 int r;
2059
2060 BUG_ON(len == 0);
2061
2062 if (len == 1) {
2063 r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_0,
2064 data[0], 0);
2065 } else if (len == 2) {
2066 r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_1,
2067 data[0] | (data[1] << 8), 0);
2068 } else {
2069 /* 0x39 = DCS Long Write */
2070 r = dsi_vc_send_long(channel, DSI_DT_DCS_LONG_WRITE,
2071 data, len, 0);
2072 }
2073
2074 return r;
2075}
2076EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);
2077
2078int dsi_vc_dcs_write(int channel, u8 *data, int len)
2079{
2080 int r;
2081
2082 r = dsi_vc_dcs_write_nosync(channel, data, len);
2083 if (r)
2084 goto err;
2085
2086 r = dsi_vc_send_bta_sync(channel);
2087 if (r)
2088 goto err;
2089
2090 return 0;
2091err:
2092 DSSERR("dsi_vc_dcs_write(ch %d, cmd 0x%02x, len %d) failed\n",
2093 channel, data[0], len);
2094 return r;
2095}
2096EXPORT_SYMBOL(dsi_vc_dcs_write);
2097
2098int dsi_vc_dcs_write_0(int channel, u8 dcs_cmd)
2099{
2100 return dsi_vc_dcs_write(channel, &dcs_cmd, 1);
2101}
2102EXPORT_SYMBOL(dsi_vc_dcs_write_0);
2103
2104int dsi_vc_dcs_write_1(int channel, u8 dcs_cmd, u8 param)
2105{
2106 u8 buf[2];
2107 buf[0] = dcs_cmd;
2108 buf[1] = param;
2109 return dsi_vc_dcs_write(channel, buf, 2);
2110}
2111EXPORT_SYMBOL(dsi_vc_dcs_write_1);
2112
2113int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen)
2114{
2115 u32 val;
2116 u8 dt;
2117 int r;
2118
2119 if (dsi.debug_read)
2120 DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %x)\n", channel, dcs_cmd);
2121
2122 r = dsi_vc_send_short(channel, DSI_DT_DCS_READ, dcs_cmd, 0);
2123 if (r)
2124 goto err;
2125
2126 r = dsi_vc_send_bta_sync(channel);
2127 if (r)
2128 goto err;
2129
2130 /* RX_FIFO_NOT_EMPTY */
2131 if (REG_GET(DSI_VC_CTRL(channel), 20, 20) == 0) {
2132 DSSERR("RX fifo empty when trying to read.\n");
2133 r = -EIO;
2134 goto err;
2135 }
2136
2137 val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
2138 if (dsi.debug_read)
2139 DSSDBG("\theader: %08x\n", val);
2140 dt = FLD_GET(val, 5, 0);
2141 if (dt == DSI_DT_RX_ACK_WITH_ERR) {
2142 u16 err = FLD_GET(val, 23, 8);
2143 dsi_show_rx_ack_with_err(err);
2144 r = -EIO;
2145 goto err;
2146
2147 } else if (dt == DSI_DT_RX_SHORT_READ_1) {
2148 u8 data = FLD_GET(val, 15, 8);
2149 if (dsi.debug_read)
2150 DSSDBG("\tDCS short response, 1 byte: %02x\n", data);
2151
2152 if (buflen < 1) {
2153 r = -EIO;
2154 goto err;
2155 }
2156
2157 buf[0] = data;
2158
2159 return 1;
2160 } else if (dt == DSI_DT_RX_SHORT_READ_2) {
2161 u16 data = FLD_GET(val, 23, 8);
2162 if (dsi.debug_read)
2163 DSSDBG("\tDCS short response, 2 byte: %04x\n", data);
2164
2165 if (buflen < 2) {
2166 r = -EIO;
2167 goto err;
2168 }
2169
2170 buf[0] = data & 0xff;
2171 buf[1] = (data >> 8) & 0xff;
2172
2173 return 2;
2174 } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
2175 int w;
2176 int len = FLD_GET(val, 23, 8);
2177 if (dsi.debug_read)
2178 DSSDBG("\tDCS long response, len %d\n", len);
2179
2180 if (len > buflen) {
2181 r = -EIO;
2182 goto err;
2183 }
2184
2185 /* two byte checksum ends the packet, not included in len */
2186 for (w = 0; w < len + 2;) {
2187 int b;
2188 val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
2189 if (dsi.debug_read)
2190 DSSDBG("\t\t%02x %02x %02x %02x\n",
2191 (val >> 0) & 0xff,
2192 (val >> 8) & 0xff,
2193 (val >> 16) & 0xff,
2194 (val >> 24) & 0xff);
2195
2196 for (b = 0; b < 4; ++b) {
2197 if (w < len)
2198 buf[w] = (val >> (b * 8)) & 0xff;
2199 /* we discard the 2 byte checksum */
2200 ++w;
2201 }
2202 }
2203
2204 return len;
2205 } else {
2206 DSSERR("\tunknown datatype 0x%02x\n", dt);
2207 r = -EIO;
2208 goto err;
2209 }
2210
2211 BUG();
2212err:
2213 DSSERR("dsi_vc_dcs_read(ch %d, cmd 0x%02x) failed\n",
2214 channel, dcs_cmd);
2215 return r;
2216
2217}
2218EXPORT_SYMBOL(dsi_vc_dcs_read);
2219
2220int dsi_vc_dcs_read_1(int channel, u8 dcs_cmd, u8 *data)
2221{
2222 int r;
2223
2224 r = dsi_vc_dcs_read(channel, dcs_cmd, data, 1);
2225
2226 if (r < 0)
2227 return r;
2228
2229 if (r != 1)
2230 return -EIO;
2231
2232 return 0;
2233}
2234EXPORT_SYMBOL(dsi_vc_dcs_read_1);
2235
2236int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u16 *data)
2237{
2238 int r;
2239
2240 r = dsi_vc_dcs_read(channel, dcs_cmd, (u8 *)data, 2);
2241
2242 if (r < 0)
2243 return r;
2244
2245 if (r != 2)
2246 return -EIO;
2247
2248 return 0;
2249}
2250EXPORT_SYMBOL(dsi_vc_dcs_read_2);
2251
2252int dsi_vc_set_max_rx_packet_size(int channel, u16 len)
2253{
2254 int r;
2255 r = dsi_vc_send_short(channel, DSI_DT_SET_MAX_RET_PKG_SIZE,
2256 len, 0);
2257
2258 if (r)
2259 return r;
2260
2261 r = dsi_vc_send_bta_sync(channel);
2262
2263 return r;
2264}
2265EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size);
2266
2267static void dsi_set_lp_rx_timeout(unsigned long ns)
2268{
2269 u32 r;
2270 unsigned x4, x16;
2271 unsigned long fck;
2272 unsigned long ticks;
2273
2274 /* ticks in DSI_FCK */
2275
2276 fck = dsi_fclk_rate();
2277 ticks = (fck / 1000 / 1000) * ns / 1000;
2278 x4 = 0;
2279 x16 = 0;
2280
2281 if (ticks > 0x1fff) {
2282 ticks = (fck / 1000 / 1000) * ns / 1000 / 4;
2283 x4 = 1;
2284 x16 = 0;
2285 }
2286
2287 if (ticks > 0x1fff) {
2288 ticks = (fck / 1000 / 1000) * ns / 1000 / 16;
2289 x4 = 0;
2290 x16 = 1;
2291 }
2292
2293 if (ticks > 0x1fff) {
2294 ticks = (fck / 1000 / 1000) * ns / 1000 / (4 * 16);
2295 x4 = 1;
2296 x16 = 1;
2297 }
2298
2299 if (ticks > 0x1fff) {
2300 DSSWARN("LP_TX_TO over limit, setting it to max\n");
2301 ticks = 0x1fff;
2302 x4 = 1;
2303 x16 = 1;
2304 }
2305
2306 r = dsi_read_reg(DSI_TIMING2);
2307 r = FLD_MOD(r, 1, 15, 15); /* LP_RX_TO */
2308 r = FLD_MOD(r, x16, 14, 14); /* LP_RX_TO_X16 */
2309 r = FLD_MOD(r, x4, 13, 13); /* LP_RX_TO_X4 */
2310 r = FLD_MOD(r, ticks, 12, 0); /* LP_RX_COUNTER */
2311 dsi_write_reg(DSI_TIMING2, r);
2312
2313 DSSDBG("LP_RX_TO %lu ns (%#lx ticks%s%s)\n",
2314 (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
2315 (fck / 1000 / 1000),
2316 ticks, x4 ? " x4" : "", x16 ? " x16" : "");
2317}
2318
2319static void dsi_set_ta_timeout(unsigned long ns)
2320{
2321 u32 r;
2322 unsigned x8, x16;
2323 unsigned long fck;
2324 unsigned long ticks;
2325
2326 /* ticks in DSI_FCK */
2327 fck = dsi_fclk_rate();
2328 ticks = (fck / 1000 / 1000) * ns / 1000;
2329 x8 = 0;
2330 x16 = 0;
2331
2332 if (ticks > 0x1fff) {
2333 ticks = (fck / 1000 / 1000) * ns / 1000 / 8;
2334 x8 = 1;
2335 x16 = 0;
2336 }
2337
2338 if (ticks > 0x1fff) {
2339 ticks = (fck / 1000 / 1000) * ns / 1000 / 16;
2340 x8 = 0;
2341 x16 = 1;
2342 }
2343
2344 if (ticks > 0x1fff) {
2345 ticks = (fck / 1000 / 1000) * ns / 1000 / (8 * 16);
2346 x8 = 1;
2347 x16 = 1;
2348 }
2349
2350 if (ticks > 0x1fff) {
2351 DSSWARN("TA_TO over limit, setting it to max\n");
2352 ticks = 0x1fff;
2353 x8 = 1;
2354 x16 = 1;
2355 }
2356
2357 r = dsi_read_reg(DSI_TIMING1);
2358 r = FLD_MOD(r, 1, 31, 31); /* TA_TO */
2359 r = FLD_MOD(r, x16, 30, 30); /* TA_TO_X16 */
2360 r = FLD_MOD(r, x8, 29, 29); /* TA_TO_X8 */
2361 r = FLD_MOD(r, ticks, 28, 16); /* TA_TO_COUNTER */
2362 dsi_write_reg(DSI_TIMING1, r);
2363
2364 DSSDBG("TA_TO %lu ns (%#lx ticks%s%s)\n",
2365 (ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1) * 1000) /
2366 (fck / 1000 / 1000),
2367 ticks, x8 ? " x8" : "", x16 ? " x16" : "");
2368}
2369
2370static void dsi_set_stop_state_counter(unsigned long ns)
2371{
2372 u32 r;
2373 unsigned x4, x16;
2374 unsigned long fck;
2375 unsigned long ticks;
2376
2377 /* ticks in DSI_FCK */
2378
2379 fck = dsi_fclk_rate();
2380 ticks = (fck / 1000 / 1000) * ns / 1000;
2381 x4 = 0;
2382 x16 = 0;
2383
2384 if (ticks > 0x1fff) {
2385 ticks = (fck / 1000 / 1000) * ns / 1000 / 4;
2386 x4 = 1;
2387 x16 = 0;
2388 }
2389
2390 if (ticks > 0x1fff) {
2391 ticks = (fck / 1000 / 1000) * ns / 1000 / 16;
2392 x4 = 0;
2393 x16 = 1;
2394 }
2395
2396 if (ticks > 0x1fff) {
2397 ticks = (fck / 1000 / 1000) * ns / 1000 / (4 * 16);
2398 x4 = 1;
2399 x16 = 1;
2400 }
2401
2402 if (ticks > 0x1fff) {
2403 DSSWARN("STOP_STATE_COUNTER_IO over limit, "
2404 "setting it to max\n");
2405 ticks = 0x1fff;
2406 x4 = 1;
2407 x16 = 1;
2408 }
2409
2410 r = dsi_read_reg(DSI_TIMING1);
2411 r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
2412 r = FLD_MOD(r, x16, 14, 14); /* STOP_STATE_X16_IO */
2413 r = FLD_MOD(r, x4, 13, 13); /* STOP_STATE_X4_IO */
2414 r = FLD_MOD(r, ticks, 12, 0); /* STOP_STATE_COUNTER_IO */
2415 dsi_write_reg(DSI_TIMING1, r);
2416
2417 DSSDBG("STOP_STATE_COUNTER %lu ns (%#lx ticks%s%s)\n",
2418 (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
2419 (fck / 1000 / 1000),
2420 ticks, x4 ? " x4" : "", x16 ? " x16" : "");
2421}
2422
2423static void dsi_set_hs_tx_timeout(unsigned long ns)
2424{
2425 u32 r;
2426 unsigned x4, x16;
2427 unsigned long fck;
2428 unsigned long ticks;
2429
2430 /* ticks in TxByteClkHS */
2431
2432 fck = dsi_get_txbyteclkhs();
2433 ticks = (fck / 1000 / 1000) * ns / 1000;
2434 x4 = 0;
2435 x16 = 0;
2436
2437 if (ticks > 0x1fff) {
2438 ticks = (fck / 1000 / 1000) * ns / 1000 / 4;
2439 x4 = 1;
2440 x16 = 0;
2441 }
2442
2443 if (ticks > 0x1fff) {
2444 ticks = (fck / 1000 / 1000) * ns / 1000 / 16;
2445 x4 = 0;
2446 x16 = 1;
2447 }
2448
2449 if (ticks > 0x1fff) {
2450 ticks = (fck / 1000 / 1000) * ns / 1000 / (4 * 16);
2451 x4 = 1;
2452 x16 = 1;
2453 }
2454
2455 if (ticks > 0x1fff) {
2456 DSSWARN("HS_TX_TO over limit, setting it to max\n");
2457 ticks = 0x1fff;
2458 x4 = 1;
2459 x16 = 1;
2460 }
2461
2462 r = dsi_read_reg(DSI_TIMING2);
2463 r = FLD_MOD(r, 1, 31, 31); /* HS_TX_TO */
2464 r = FLD_MOD(r, x16, 30, 30); /* HS_TX_TO_X16 */
2465 r = FLD_MOD(r, x4, 29, 29); /* HS_TX_TO_X8 (4 really) */
2466 r = FLD_MOD(r, ticks, 28, 16); /* HS_TX_TO_COUNTER */
2467 dsi_write_reg(DSI_TIMING2, r);
2468
2469 DSSDBG("HS_TX_TO %lu ns (%#lx ticks%s%s)\n",
2470 (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
2471 (fck / 1000 / 1000),
2472 ticks, x4 ? " x4" : "", x16 ? " x16" : "");
2473}
2474static int dsi_proto_config(struct omap_dss_device *dssdev)
2475{
2476 u32 r;
2477 int buswidth = 0;
2478
2479 dsi_config_tx_fifo(DSI_FIFO_SIZE_32,
2480 DSI_FIFO_SIZE_32,
2481 DSI_FIFO_SIZE_32,
2482 DSI_FIFO_SIZE_32);
2483
2484 dsi_config_rx_fifo(DSI_FIFO_SIZE_32,
2485 DSI_FIFO_SIZE_32,
2486 DSI_FIFO_SIZE_32,
2487 DSI_FIFO_SIZE_32);
2488
2489 /* XXX what values for the timeouts? */
2490 dsi_set_stop_state_counter(1000);
2491 dsi_set_ta_timeout(6400000);
2492 dsi_set_lp_rx_timeout(48000);
2493 dsi_set_hs_tx_timeout(1000000);
2494
2495 switch (dssdev->ctrl.pixel_size) {
2496 case 16:
2497 buswidth = 0;
2498 break;
2499 case 18:
2500 buswidth = 1;
2501 break;
2502 case 24:
2503 buswidth = 2;
2504 break;
2505 default:
2506 BUG();
2507 }
2508
2509 r = dsi_read_reg(DSI_CTRL);
2510 r = FLD_MOD(r, 1, 1, 1); /* CS_RX_EN */
2511 r = FLD_MOD(r, 1, 2, 2); /* ECC_RX_EN */
2512 r = FLD_MOD(r, 1, 3, 3); /* TX_FIFO_ARBITRATION */
2513 r = FLD_MOD(r, 1, 4, 4); /* VP_CLK_RATIO, always 1, see errata*/
2514 r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */
2515 r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */
2516 r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */
2517 r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */
2518 r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */
2519 r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */
2520 r = FLD_MOD(r, 0, 25, 25); /* DCS_CMD_CODE, 1=start, 0=continue */
2521
2522 dsi_write_reg(DSI_CTRL, r);
2523
2524 dsi_vc_initial_config(0);
2525 dsi_vc_initial_config(1);
2526 dsi_vc_initial_config(2);
2527 dsi_vc_initial_config(3);
2528
2529 return 0;
2530}
2531
2532static void dsi_proto_timings(struct omap_dss_device *dssdev)
2533{
2534 unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail;
2535 unsigned tclk_pre, tclk_post;
2536 unsigned ths_prepare, ths_prepare_ths_zero, ths_zero;
2537 unsigned ths_trail, ths_exit;
2538 unsigned ddr_clk_pre, ddr_clk_post;
2539 unsigned enter_hs_mode_lat, exit_hs_mode_lat;
2540 unsigned ths_eot;
2541 u32 r;
2542
2543 r = dsi_read_reg(DSI_DSIPHY_CFG0);
2544 ths_prepare = FLD_GET(r, 31, 24);
2545 ths_prepare_ths_zero = FLD_GET(r, 23, 16);
2546 ths_zero = ths_prepare_ths_zero - ths_prepare;
2547 ths_trail = FLD_GET(r, 15, 8);
2548 ths_exit = FLD_GET(r, 7, 0);
2549
2550 r = dsi_read_reg(DSI_DSIPHY_CFG1);
2551 tlpx = FLD_GET(r, 22, 16) * 2;
2552 tclk_trail = FLD_GET(r, 15, 8);
2553 tclk_zero = FLD_GET(r, 7, 0);
2554
2555 r = dsi_read_reg(DSI_DSIPHY_CFG2);
2556 tclk_prepare = FLD_GET(r, 7, 0);
2557
2558 /* min 8*UI */
2559 tclk_pre = 20;
2560 /* min 60ns + 52*UI */
2561 tclk_post = ns2ddr(60) + 26;
2562
2563 /* ths_eot is 2 for 2 datalanes and 4 for 1 datalane */
2564 if (dssdev->phy.dsi.data1_lane != 0 &&
2565 dssdev->phy.dsi.data2_lane != 0)
2566 ths_eot = 2;
2567 else
2568 ths_eot = 4;
2569
2570 ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare,
2571 4);
2572 ddr_clk_post = DIV_ROUND_UP(tclk_post + ths_trail, 4) + ths_eot;
2573
2574 BUG_ON(ddr_clk_pre == 0 || ddr_clk_pre > 255);
2575 BUG_ON(ddr_clk_post == 0 || ddr_clk_post > 255);
2576
2577 r = dsi_read_reg(DSI_CLK_TIMING);
2578 r = FLD_MOD(r, ddr_clk_pre, 15, 8);
2579 r = FLD_MOD(r, ddr_clk_post, 7, 0);
2580 dsi_write_reg(DSI_CLK_TIMING, r);
2581
2582 DSSDBG("ddr_clk_pre %u, ddr_clk_post %u\n",
2583 ddr_clk_pre,
2584 ddr_clk_post);
2585
2586 enter_hs_mode_lat = 1 + DIV_ROUND_UP(tlpx, 4) +
2587 DIV_ROUND_UP(ths_prepare, 4) +
2588 DIV_ROUND_UP(ths_zero + 3, 4);
2589
2590 exit_hs_mode_lat = DIV_ROUND_UP(ths_trail + ths_exit, 4) + 1 + ths_eot;
2591
2592 r = FLD_VAL(enter_hs_mode_lat, 31, 16) |
2593 FLD_VAL(exit_hs_mode_lat, 15, 0);
2594 dsi_write_reg(DSI_VM_TIMING7, r);
2595
2596 DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",
2597 enter_hs_mode_lat, exit_hs_mode_lat);
2598}
2599
2600
2601#define DSI_DECL_VARS \
2602 int __dsi_cb = 0; u32 __dsi_cv = 0;
2603
2604#define DSI_FLUSH(ch) \
2605 if (__dsi_cb > 0) { \
2606 /*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \
2607 dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \
2608 __dsi_cb = __dsi_cv = 0; \
2609 }
2610
2611#define DSI_PUSH(ch, data) \
2612 do { \
2613 __dsi_cv |= (data) << (__dsi_cb * 8); \
2614 /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \
2615 if (++__dsi_cb > 3) \
2616 DSI_FLUSH(ch); \
2617 } while (0)
2618
2619static int dsi_update_screen_l4(struct omap_dss_device *dssdev,
2620 int x, int y, int w, int h)
2621{
2622 /* Note: supports only 24bit colors in 32bit container */
2623 int first = 1;
2624 int fifo_stalls = 0;
2625 int max_dsi_packet_size;
2626 int max_data_per_packet;
2627 int max_pixels_per_packet;
2628 int pixels_left;
2629 int bytespp = dssdev->ctrl.pixel_size / 8;
2630 int scr_width;
2631 u32 __iomem *data;
2632 int start_offset;
2633 int horiz_inc;
2634 int current_x;
2635 struct omap_overlay *ovl;
2636
2637 debug_irq = 0;
2638
2639 DSSDBG("dsi_update_screen_l4 (%d,%d %dx%d)\n",
2640 x, y, w, h);
2641
2642 ovl = dssdev->manager->overlays[0];
2643
2644 if (ovl->info.color_mode != OMAP_DSS_COLOR_RGB24U)
2645 return -EINVAL;
2646
2647 if (dssdev->ctrl.pixel_size != 24)
2648 return -EINVAL;
2649
2650 scr_width = ovl->info.screen_width;
2651 data = ovl->info.vaddr;
2652
2653 start_offset = scr_width * y + x;
2654 horiz_inc = scr_width - w;
2655 current_x = x;
2656
2657 /* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp) bytes
2658 * in fifo */
2659
2660 /* When using CPU, max long packet size is TX buffer size */
2661 max_dsi_packet_size = dsi.vc[0].fifo_size * 32 * 4;
2662
2663 /* we seem to get better perf if we divide the tx fifo to half,
2664 and while the other half is being sent, we fill the other half
2665 max_dsi_packet_size /= 2; */
2666
2667 max_data_per_packet = max_dsi_packet_size - 4 - 1;
2668
2669 max_pixels_per_packet = max_data_per_packet / bytespp;
2670
2671 DSSDBG("max_pixels_per_packet %d\n", max_pixels_per_packet);
2672
2673 pixels_left = w * h;
2674
2675 DSSDBG("total pixels %d\n", pixels_left);
2676
2677 data += start_offset;
2678
2679 while (pixels_left > 0) {
2680 /* 0x2c = write_memory_start */
2681 /* 0x3c = write_memory_continue */
2682 u8 dcs_cmd = first ? 0x2c : 0x3c;
2683 int pixels;
2684 DSI_DECL_VARS;
2685 first = 0;
2686
2687#if 1
2688 /* using fifo not empty */
2689 /* TX_FIFO_NOT_EMPTY */
2690 while (FLD_GET(dsi_read_reg(DSI_VC_CTRL(0)), 5, 5)) {
2691 fifo_stalls++;
2692 if (fifo_stalls > 0xfffff) {
2693 DSSERR("fifo stalls overflow, pixels left %d\n",
2694 pixels_left);
2695 dsi_if_enable(0);
2696 return -EIO;
2697 }
2698 udelay(1);
2699 }
2700#elif 1
2701 /* using fifo emptiness */
2702 while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 <
2703 max_dsi_packet_size) {
2704 fifo_stalls++;
2705 if (fifo_stalls > 0xfffff) {
2706 DSSERR("fifo stalls overflow, pixels left %d\n",
2707 pixels_left);
2708 dsi_if_enable(0);
2709 return -EIO;
2710 }
2711 }
2712#else
2713 while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 == 0) {
2714 fifo_stalls++;
2715 if (fifo_stalls > 0xfffff) {
2716 DSSERR("fifo stalls overflow, pixels left %d\n",
2717 pixels_left);
2718 dsi_if_enable(0);
2719 return -EIO;
2720 }
2721 }
2722#endif
2723 pixels = min(max_pixels_per_packet, pixels_left);
2724
2725 pixels_left -= pixels;
2726
2727 dsi_vc_write_long_header(0, DSI_DT_DCS_LONG_WRITE,
2728 1 + pixels * bytespp, 0);
2729
2730 DSI_PUSH(0, dcs_cmd);
2731
2732 while (pixels-- > 0) {
2733 u32 pix = __raw_readl(data++);
2734
2735 DSI_PUSH(0, (pix >> 16) & 0xff);
2736 DSI_PUSH(0, (pix >> 8) & 0xff);
2737 DSI_PUSH(0, (pix >> 0) & 0xff);
2738
2739 current_x++;
2740 if (current_x == x+w) {
2741 current_x = x;
2742 data += horiz_inc;
2743 }
2744 }
2745
2746 DSI_FLUSH(0);
2747 }
2748
2749 return 0;
2750}
2751
2752static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
2753 u16 x, u16 y, u16 w, u16 h)
2754{
2755 unsigned bytespp;
2756 unsigned bytespl;
2757 unsigned bytespf;
2758 unsigned total_len;
2759 unsigned packet_payload;
2760 unsigned packet_len;
2761 u32 l;
2762 const unsigned channel = dsi.update_channel;
2763 /* line buffer is 1024 x 24bits */
2764 /* XXX: for some reason using full buffer size causes considerable TX
2765 * slowdown with update sizes that fill the whole buffer */
2766 const unsigned line_buf_size = 1023 * 3;
2767
2768 DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",
2769 x, y, w, h);
2770
2771 dsi_vc_config_vp(channel);
2772
2773 bytespp = dssdev->ctrl.pixel_size / 8;
2774 bytespl = w * bytespp;
2775 bytespf = bytespl * h;
2776
2777 /* NOTE: packet_payload has to be equal to N * bytespl, where N is
2778 * number of lines in a packet. See errata about VP_CLK_RATIO */
2779
2780 if (bytespf < line_buf_size)
2781 packet_payload = bytespf;
2782 else
2783 packet_payload = (line_buf_size) / bytespl * bytespl;
2784
2785 packet_len = packet_payload + 1; /* 1 byte for DCS cmd */
2786 total_len = (bytespf / packet_payload) * packet_len;
2787
2788 if (bytespf % packet_payload)
2789 total_len += (bytespf % packet_payload) + 1;
2790
2791 l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */
2792 dsi_write_reg(DSI_VC_TE(channel), l);
2793
2794 dsi_vc_write_long_header(channel, DSI_DT_DCS_LONG_WRITE, packet_len, 0);
2795
2796 if (dsi.te_enabled)
2797 l = FLD_MOD(l, 1, 30, 30); /* TE_EN */
2798 else
2799 l = FLD_MOD(l, 1, 31, 31); /* TE_START */
2800 dsi_write_reg(DSI_VC_TE(channel), l);
2801
2802 /* We put SIDLEMODE to no-idle for the duration of the transfer,
2803 * because DSS interrupts are not capable of waking up the CPU and the
2804 * framedone interrupt could be delayed for quite a long time. I think
2805 * the same goes for any DSS interrupts, but for some reason I have not
2806 * seen the problem anywhere else than here.
2807 */
2808 dispc_disable_sidle();
2809
2810 dsi_perf_mark_start();
2811
2812 schedule_delayed_work(&dsi.framedone_timeout_work,
2813 msecs_to_jiffies(250));
2814
2815 dss_start_update(dssdev);
2816
2817 if (dsi.te_enabled) {
2818 /* disable LP_RX_TO, so that we can receive TE. Time to wait
2819 * for TE is longer than the timer allows */
2820 REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */
2821
2822 dsi_vc_send_bta(channel);
2823
2824#ifdef DSI_CATCH_MISSING_TE
2825 mod_timer(&dsi.te_timer, jiffies + msecs_to_jiffies(250));
2826#endif
2827 }
2828}
2829
2830#ifdef DSI_CATCH_MISSING_TE
2831static void dsi_te_timeout(unsigned long arg)
2832{
2833 DSSERR("TE not received for 250ms!\n");
2834}
2835#endif
2836
2837static void dsi_framedone_timeout_work_callback(struct work_struct *work)
2838{
2839 int r;
2840 const int channel = dsi.update_channel;
2841
2842 DSSERR("Framedone not received for 250ms!\n");
2843
2844 /* SIDLEMODE back to smart-idle */
2845 dispc_enable_sidle();
2846
2847 if (dsi.te_enabled) {
2848 /* enable LP_RX_TO again after the TE */
2849 REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
2850 }
2851
2852 /* Send BTA after the frame. We need this for the TE to work, as TE
2853 * trigger is only sent for BTAs without preceding packet. Thus we need
2854 * to BTA after the pixel packets so that next BTA will cause TE
2855 * trigger.
2856 *
2857 * This is not needed when TE is not in use, but we do it anyway to
2858 * make sure that the transfer has been completed. It would be more
2859 * optimal, but more complex, to wait only just before starting next
2860 * transfer. */
2861 r = dsi_vc_send_bta_sync(channel);
2862 if (r)
2863 DSSERR("BTA after framedone failed\n");
2864
2865 /* RX_FIFO_NOT_EMPTY */
2866 if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
2867 DSSERR("Received error during frame transfer:\n");
2868 dsi_vc_flush_receive_data(channel);
2869 }
2870
2871 dsi.framedone_callback(-ETIMEDOUT, dsi.framedone_data);
2872}
2873
2874static void dsi_framedone_irq_callback(void *data, u32 mask)
2875{
2876 /* Note: We get FRAMEDONE when DISPC has finished sending pixels and
2877 * turns itself off. However, DSI still has the pixels in its buffers,
2878 * and is sending the data.
2879 */
2880
2881 /* SIDLEMODE back to smart-idle */
2882 dispc_enable_sidle();
2883
2884 schedule_work(&dsi.framedone_work);
2885}
2886
2887static void dsi_handle_framedone(void)
2888{
2889 int r;
2890 const int channel = dsi.update_channel;
2891
2892 DSSDBG("FRAMEDONE\n");
2893
2894 if (dsi.te_enabled) {
2895 /* enable LP_RX_TO again after the TE */
2896 REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
2897 }
2898
2899 /* Send BTA after the frame. We need this for the TE to work, as TE
2900 * trigger is only sent for BTAs without preceding packet. Thus we need
2901 * to BTA after the pixel packets so that next BTA will cause TE
2902 * trigger.
2903 *
2904 * This is not needed when TE is not in use, but we do it anyway to
2905 * make sure that the transfer has been completed. It would be more
2906 * optimal, but more complex, to wait only just before starting next
2907 * transfer. */
2908 r = dsi_vc_send_bta_sync(channel);
2909 if (r)
2910 DSSERR("BTA after framedone failed\n");
2911
2912 /* RX_FIFO_NOT_EMPTY */
2913 if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
2914 DSSERR("Received error during frame transfer:\n");
2915 dsi_vc_flush_receive_data(channel);
2916 }
2917
2918#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
2919 dispc_fake_vsync_irq();
2920#endif
2921}
2922
2923static void dsi_framedone_work_callback(struct work_struct *work)
2924{
2925 DSSDBGF();
2926
2927 cancel_delayed_work_sync(&dsi.framedone_timeout_work);
2928
2929 dsi_handle_framedone();
2930
2931 dsi_perf_show("DISPC");
2932
2933 dsi.framedone_callback(0, dsi.framedone_data);
2934}
2935
2936int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
2937 u16 *x, u16 *y, u16 *w, u16 *h)
2938{
2939 u16 dw, dh;
2940
2941 dssdev->driver->get_resolution(dssdev, &dw, &dh);
2942
2943 if (*x > dw || *y > dh)
2944 return -EINVAL;
2945
2946 if (*x + *w > dw)
2947 return -EINVAL;
2948
2949 if (*y + *h > dh)
2950 return -EINVAL;
2951
2952 if (*w == 1)
2953 return -EINVAL;
2954
2955 if (*w == 0 || *h == 0)
2956 return -EINVAL;
2957
2958 dsi_perf_mark_setup();
2959
2960 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
2961 dss_setup_partial_planes(dssdev, x, y, w, h);
2962 dispc_set_lcd_size(*w, *h);
2963 }
2964
2965 return 0;
2966}
2967EXPORT_SYMBOL(omap_dsi_prepare_update);
2968
2969int omap_dsi_update(struct omap_dss_device *dssdev,
2970 int channel,
2971 u16 x, u16 y, u16 w, u16 h,
2972 void (*callback)(int, void *), void *data)
2973{
2974 dsi.update_channel = channel;
2975
2976 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
2977 dsi.framedone_callback = callback;
2978 dsi.framedone_data = data;
2979
2980 dsi.update_region.x = x;
2981 dsi.update_region.y = y;
2982 dsi.update_region.w = w;
2983 dsi.update_region.h = h;
2984 dsi.update_region.device = dssdev;
2985
2986 dsi_update_screen_dispc(dssdev, x, y, w, h);
2987 } else {
2988 dsi_update_screen_l4(dssdev, x, y, w, h);
2989 dsi_perf_show("L4");
2990 callback(0, data);
2991 }
2992
2993 return 0;
2994}
2995EXPORT_SYMBOL(omap_dsi_update);
2996
2997/* Display funcs */
2998
2999static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
3000{
3001 int r;
3002
3003 r = omap_dispc_register_isr(dsi_framedone_irq_callback, NULL,
3004 DISPC_IRQ_FRAMEDONE);
3005 if (r) {
3006 DSSERR("can't get FRAMEDONE irq\n");
3007 return r;
3008 }
3009
3010 dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
3011
3012 dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_DSI);
3013 dispc_enable_fifohandcheck(1);
3014
3015 dispc_set_tft_data_lines(dssdev->ctrl.pixel_size);
3016
3017 {
3018 struct omap_video_timings timings = {
3019 .hsw = 1,
3020 .hfp = 1,
3021 .hbp = 1,
3022 .vsw = 1,
3023 .vfp = 0,
3024 .vbp = 0,
3025 };
3026
3027 dispc_set_lcd_timings(&timings);
3028 }
3029
3030 return 0;
3031}
3032
3033static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
3034{
3035 omap_dispc_unregister_isr(dsi_framedone_irq_callback, NULL,
3036 DISPC_IRQ_FRAMEDONE);
3037}
3038
3039static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
3040{
3041 struct dsi_clock_info cinfo;
3042 int r;
3043
3044 /* we always use DSS2_FCK as input clock */
3045 cinfo.use_dss2_fck = true;
3046 cinfo.regn = dssdev->phy.dsi.div.regn;
3047 cinfo.regm = dssdev->phy.dsi.div.regm;
3048 cinfo.regm3 = dssdev->phy.dsi.div.regm3;
3049 cinfo.regm4 = dssdev->phy.dsi.div.regm4;
3050 r = dsi_calc_clock_rates(&cinfo);
3051 if (r)
3052 return r;
3053
3054 r = dsi_pll_set_clock_div(&cinfo);
3055 if (r) {
3056 DSSERR("Failed to set dsi clocks\n");
3057 return r;
3058 }
3059
3060 return 0;
3061}
3062
3063static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev)
3064{
3065 struct dispc_clock_info dispc_cinfo;
3066 int r;
3067 unsigned long long fck;
3068
3069 fck = dsi_get_dsi1_pll_rate();
3070
3071 dispc_cinfo.lck_div = dssdev->phy.dsi.div.lck_div;
3072 dispc_cinfo.pck_div = dssdev->phy.dsi.div.pck_div;
3073
3074 r = dispc_calc_clock_rates(fck, &dispc_cinfo);
3075 if (r) {
3076 DSSERR("Failed to calc dispc clocks\n");
3077 return r;
3078 }
3079
3080 r = dispc_set_clock_div(&dispc_cinfo);
3081 if (r) {
3082 DSSERR("Failed to set dispc clocks\n");
3083 return r;
3084 }
3085
3086 return 0;
3087}
3088
3089static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
3090{
3091 int r;
3092
3093 _dsi_print_reset_status();
3094
3095 r = dsi_pll_init(dssdev, true, true);
3096 if (r)
3097 goto err0;
3098
3099 r = dsi_configure_dsi_clocks(dssdev);
3100 if (r)
3101 goto err1;
3102
3103 dss_select_dispc_clk_source(DSS_SRC_DSI1_PLL_FCLK);
3104 dss_select_dsi_clk_source(DSS_SRC_DSI2_PLL_FCLK);
3105
3106 DSSDBG("PLL OK\n");
3107
3108 r = dsi_configure_dispc_clocks(dssdev);
3109 if (r)
3110 goto err2;
3111
3112 r = dsi_complexio_init(dssdev);
3113 if (r)
3114 goto err2;
3115
3116 _dsi_print_reset_status();
3117
3118 dsi_proto_timings(dssdev);
3119 dsi_set_lp_clk_divisor(dssdev);
3120
3121 if (1)
3122 _dsi_print_reset_status();
3123
3124 r = dsi_proto_config(dssdev);
3125 if (r)
3126 goto err3;
3127
3128 /* enable interface */
3129 dsi_vc_enable(0, 1);
3130 dsi_vc_enable(1, 1);
3131 dsi_vc_enable(2, 1);
3132 dsi_vc_enable(3, 1);
3133 dsi_if_enable(1);
3134 dsi_force_tx_stop_mode_io();
3135
3136 return 0;
3137err3:
3138 dsi_complexio_uninit();
3139err2:
3140 dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
3141 dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
3142err1:
3143 dsi_pll_uninit();
3144err0:
3145 return r;
3146}
3147
3148static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev)
3149{
3150 dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
3151 dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
3152 dsi_complexio_uninit();
3153 dsi_pll_uninit();
3154}
3155
3156static int dsi_core_init(void)
3157{
3158 /* Autoidle */
3159 REG_FLD_MOD(DSI_SYSCONFIG, 1, 0, 0);
3160
3161 /* ENWAKEUP */
3162 REG_FLD_MOD(DSI_SYSCONFIG, 1, 2, 2);
3163
3164 /* SIDLEMODE smart-idle */
3165 REG_FLD_MOD(DSI_SYSCONFIG, 2, 4, 3);
3166
3167 _dsi_initialize_irq();
3168
3169 return 0;
3170}
3171
3172int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
3173{
3174 int r = 0;
3175
3176 DSSDBG("dsi_display_enable\n");
3177
3178 WARN_ON(!dsi_bus_is_locked());
3179
3180 mutex_lock(&dsi.lock);
3181
3182 r = omap_dss_start_device(dssdev);
3183 if (r) {
3184 DSSERR("failed to start device\n");
3185 goto err0;
3186 }
3187
3188 enable_clocks(1);
3189 dsi_enable_pll_clock(1);
3190
3191 r = _dsi_reset();
3192 if (r)
3193 goto err1;
3194
3195 dsi_core_init();
3196
3197 r = dsi_display_init_dispc(dssdev);
3198 if (r)
3199 goto err1;
3200
3201 r = dsi_display_init_dsi(dssdev);
3202 if (r)
3203 goto err2;
3204
3205 mutex_unlock(&dsi.lock);
3206
3207 return 0;
3208
3209err2:
3210 dsi_display_uninit_dispc(dssdev);
3211err1:
3212 enable_clocks(0);
3213 dsi_enable_pll_clock(0);
3214 omap_dss_stop_device(dssdev);
3215err0:
3216 mutex_unlock(&dsi.lock);
3217 DSSDBG("dsi_display_enable FAILED\n");
3218 return r;
3219}
3220EXPORT_SYMBOL(omapdss_dsi_display_enable);
3221
3222void omapdss_dsi_display_disable(struct omap_dss_device *dssdev)
3223{
3224 DSSDBG("dsi_display_disable\n");
3225
3226 WARN_ON(!dsi_bus_is_locked());
3227
3228 mutex_lock(&dsi.lock);
3229
3230 dsi_display_uninit_dispc(dssdev);
3231
3232 dsi_display_uninit_dsi(dssdev);
3233
3234 enable_clocks(0);
3235 dsi_enable_pll_clock(0);
3236
3237 omap_dss_stop_device(dssdev);
3238
3239 mutex_unlock(&dsi.lock);
3240}
3241EXPORT_SYMBOL(omapdss_dsi_display_disable);
3242
3243int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
3244{
3245 dsi.te_enabled = enable;
3246 return 0;
3247}
3248EXPORT_SYMBOL(omapdss_dsi_enable_te);
3249
3250void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
3251 u32 fifo_size, enum omap_burst_size *burst_size,
3252 u32 *fifo_low, u32 *fifo_high)
3253{
3254 unsigned burst_size_bytes;
3255
3256 *burst_size = OMAP_DSS_BURST_16x32;
3257 burst_size_bytes = 16 * 32 / 8;
3258
3259 *fifo_high = fifo_size - burst_size_bytes;
3260 *fifo_low = fifo_size - burst_size_bytes * 8;
3261}
3262
3263int dsi_init_display(struct omap_dss_device *dssdev)
3264{
3265 DSSDBG("DSI init\n");
3266
3267 /* XXX these should be figured out dynamically */
3268 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
3269 OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
3270
3271 dsi.vc[0].dssdev = dssdev;
3272 dsi.vc[1].dssdev = dssdev;
3273
3274 return 0;
3275}
3276
3277int dsi_init(struct platform_device *pdev)
3278{
3279 u32 rev;
3280 int r;
3281
3282 spin_lock_init(&dsi.errors_lock);
3283 dsi.errors = 0;
3284
3285#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
3286 spin_lock_init(&dsi.irq_stats_lock);
3287 dsi.irq_stats.last_reset = jiffies;
3288#endif
3289
3290 init_completion(&dsi.bta_completion);
3291
3292 mutex_init(&dsi.lock);
3293 sema_init(&dsi.bus_lock, 1);
3294
3295 INIT_WORK(&dsi.framedone_work, dsi_framedone_work_callback);
3296 INIT_DELAYED_WORK_DEFERRABLE(&dsi.framedone_timeout_work,
3297 dsi_framedone_timeout_work_callback);
3298
3299#ifdef DSI_CATCH_MISSING_TE
3300 init_timer(&dsi.te_timer);
3301 dsi.te_timer.function = dsi_te_timeout;
3302 dsi.te_timer.data = 0;
3303#endif
3304 dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS);
3305 if (!dsi.base) {
3306 DSSERR("can't ioremap DSI\n");
3307 r = -ENOMEM;
3308 goto err1;
3309 }
3310
3311 dsi.vdds_dsi_reg = dss_get_vdds_dsi();
3312 if (IS_ERR(dsi.vdds_dsi_reg)) {
3313 iounmap(dsi.base);
3314 DSSERR("can't get VDDS_DSI regulator\n");
3315 r = PTR_ERR(dsi.vdds_dsi_reg);
3316 goto err2;
3317 }
3318
3319 enable_clocks(1);
3320
3321 rev = dsi_read_reg(DSI_REVISION);
3322 printk(KERN_INFO "OMAP DSI rev %d.%d\n",
3323 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
3324
3325 enable_clocks(0);
3326
3327 return 0;
3328err2:
3329 iounmap(dsi.base);
3330err1:
3331 return r;
3332}
3333
3334void dsi_exit(void)
3335{
3336 iounmap(dsi.base);
3337
3338 DSSDBG("omap_dsi_exit\n");
3339}
3340
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
new file mode 100644
index 000000000000..54344184dd73
--- /dev/null
+++ b/drivers/video/omap2/dss/dss.c
@@ -0,0 +1,621 @@
1/*
2 * linux/drivers/video/omap2/dss/dss.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#define DSS_SUBSYS_NAME "DSS"
24
25#include <linux/kernel.h>
26#include <linux/io.h>
27#include <linux/err.h>
28#include <linux/delay.h>
29#include <linux/interrupt.h>
30#include <linux/seq_file.h>
31#include <linux/clk.h>
32
33#include <plat/display.h>
34#include "dss.h"
35
36#define DSS_BASE 0x48050000
37
38#define DSS_SZ_REGS SZ_512
39
40struct dss_reg {
41 u16 idx;
42};
43
44#define DSS_REG(idx) ((const struct dss_reg) { idx })
45
46#define DSS_REVISION DSS_REG(0x0000)
47#define DSS_SYSCONFIG DSS_REG(0x0010)
48#define DSS_SYSSTATUS DSS_REG(0x0014)
49#define DSS_IRQSTATUS DSS_REG(0x0018)
50#define DSS_CONTROL DSS_REG(0x0040)
51#define DSS_SDI_CONTROL DSS_REG(0x0044)
52#define DSS_PLL_CONTROL DSS_REG(0x0048)
53#define DSS_SDI_STATUS DSS_REG(0x005C)
54
55#define REG_GET(idx, start, end) \
56 FLD_GET(dss_read_reg(idx), start, end)
57
58#define REG_FLD_MOD(idx, val, start, end) \
59 dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
60
61static struct {
62 void __iomem *base;
63
64 struct clk *dpll4_m4_ck;
65
66 unsigned long cache_req_pck;
67 unsigned long cache_prate;
68 struct dss_clock_info cache_dss_cinfo;
69 struct dispc_clock_info cache_dispc_cinfo;
70
71 enum dss_clk_source dsi_clk_source;
72 enum dss_clk_source dispc_clk_source;
73
74 u32 ctx[DSS_SZ_REGS / sizeof(u32)];
75} dss;
76
77static int _omap_dss_wait_reset(void);
78
79static inline void dss_write_reg(const struct dss_reg idx, u32 val)
80{
81 __raw_writel(val, dss.base + idx.idx);
82}
83
84static inline u32 dss_read_reg(const struct dss_reg idx)
85{
86 return __raw_readl(dss.base + idx.idx);
87}
88
89#define SR(reg) \
90 dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg)
91#define RR(reg) \
92 dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
93
94void dss_save_context(void)
95{
96 if (cpu_is_omap24xx())
97 return;
98
99 SR(SYSCONFIG);
100 SR(CONTROL);
101
102#ifdef CONFIG_OMAP2_DSS_SDI
103 SR(SDI_CONTROL);
104 SR(PLL_CONTROL);
105#endif
106}
107
108void dss_restore_context(void)
109{
110 if (_omap_dss_wait_reset())
111 DSSERR("DSS not coming out of reset after sleep\n");
112
113 RR(SYSCONFIG);
114 RR(CONTROL);
115
116#ifdef CONFIG_OMAP2_DSS_SDI
117 RR(SDI_CONTROL);
118 RR(PLL_CONTROL);
119#endif
120}
121
122#undef SR
123#undef RR
124
125void dss_sdi_init(u8 datapairs)
126{
127 u32 l;
128
129 BUG_ON(datapairs > 3 || datapairs < 1);
130
131 l = dss_read_reg(DSS_SDI_CONTROL);
132 l = FLD_MOD(l, 0xf, 19, 15); /* SDI_PDIV */
133 l = FLD_MOD(l, datapairs-1, 3, 2); /* SDI_PRSEL */
134 l = FLD_MOD(l, 2, 1, 0); /* SDI_BWSEL */
135 dss_write_reg(DSS_SDI_CONTROL, l);
136
137 l = dss_read_reg(DSS_PLL_CONTROL);
138 l = FLD_MOD(l, 0x7, 25, 22); /* SDI_PLL_FREQSEL */
139 l = FLD_MOD(l, 0xb, 16, 11); /* SDI_PLL_REGN */
140 l = FLD_MOD(l, 0xb4, 10, 1); /* SDI_PLL_REGM */
141 dss_write_reg(DSS_PLL_CONTROL, l);
142}
143
144int dss_sdi_enable(void)
145{
146 unsigned long timeout;
147
148 dispc_pck_free_enable(1);
149
150 /* Reset SDI PLL */
151 REG_FLD_MOD(DSS_PLL_CONTROL, 1, 18, 18); /* SDI_PLL_SYSRESET */
152 udelay(1); /* wait 2x PCLK */
153
154 /* Lock SDI PLL */
155 REG_FLD_MOD(DSS_PLL_CONTROL, 1, 28, 28); /* SDI_PLL_GOBIT */
156
157 /* Waiting for PLL lock request to complete */
158 timeout = jiffies + msecs_to_jiffies(500);
159 while (dss_read_reg(DSS_SDI_STATUS) & (1 << 6)) {
160 if (time_after_eq(jiffies, timeout)) {
161 DSSERR("PLL lock request timed out\n");
162 goto err1;
163 }
164 }
165
166 /* Clearing PLL_GO bit */
167 REG_FLD_MOD(DSS_PLL_CONTROL, 0, 28, 28);
168
169 /* Waiting for PLL to lock */
170 timeout = jiffies + msecs_to_jiffies(500);
171 while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5))) {
172 if (time_after_eq(jiffies, timeout)) {
173 DSSERR("PLL lock timed out\n");
174 goto err1;
175 }
176 }
177
178 dispc_lcd_enable_signal(1);
179
180 /* Waiting for SDI reset to complete */
181 timeout = jiffies + msecs_to_jiffies(500);
182 while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 2))) {
183 if (time_after_eq(jiffies, timeout)) {
184 DSSERR("SDI reset timed out\n");
185 goto err2;
186 }
187 }
188
189 return 0;
190
191 err2:
192 dispc_lcd_enable_signal(0);
193 err1:
194 /* Reset SDI PLL */
195 REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
196
197 dispc_pck_free_enable(0);
198
199 return -ETIMEDOUT;
200}
201
202void dss_sdi_disable(void)
203{
204 dispc_lcd_enable_signal(0);
205
206 dispc_pck_free_enable(0);
207
208 /* Reset SDI PLL */
209 REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
210}
211
212void dss_dump_clocks(struct seq_file *s)
213{
214 unsigned long dpll4_ck_rate;
215 unsigned long dpll4_m4_ck_rate;
216
217 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
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
222 seq_printf(s, "- DSS -\n");
223
224 seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
225
226 seq_printf(s, "dss1_alwon_fclk = %lu / %lu * 2 = %lu\n",
227 dpll4_ck_rate,
228 dpll4_ck_rate / dpll4_m4_ck_rate,
229 dss_clk_get_rate(DSS_CLK_FCK1));
230
231 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
232}
233
234void dss_dump_regs(struct seq_file *s)
235{
236#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
237
238 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
239
240 DUMPREG(DSS_REVISION);
241 DUMPREG(DSS_SYSCONFIG);
242 DUMPREG(DSS_SYSSTATUS);
243 DUMPREG(DSS_IRQSTATUS);
244 DUMPREG(DSS_CONTROL);
245 DUMPREG(DSS_SDI_CONTROL);
246 DUMPREG(DSS_PLL_CONTROL);
247 DUMPREG(DSS_SDI_STATUS);
248
249 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
250#undef DUMPREG
251}
252
253void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
254{
255 int b;
256
257 BUG_ON(clk_src != DSS_SRC_DSI1_PLL_FCLK &&
258 clk_src != DSS_SRC_DSS1_ALWON_FCLK);
259
260 b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1;
261
262 REG_FLD_MOD(DSS_CONTROL, b, 0, 0); /* DISPC_CLK_SWITCH */
263
264 dss.dispc_clk_source = clk_src;
265}
266
267void dss_select_dsi_clk_source(enum dss_clk_source clk_src)
268{
269 int b;
270
271 BUG_ON(clk_src != DSS_SRC_DSI2_PLL_FCLK &&
272 clk_src != DSS_SRC_DSS1_ALWON_FCLK);
273
274 b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1;
275
276 REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */
277
278 dss.dsi_clk_source = clk_src;
279}
280
281enum dss_clk_source dss_get_dispc_clk_source(void)
282{
283 return dss.dispc_clk_source;
284}
285
286enum dss_clk_source dss_get_dsi_clk_source(void)
287{
288 return dss.dsi_clk_source;
289}
290
291/* calculate clock rates using dividers in cinfo */
292int dss_calc_clock_rates(struct dss_clock_info *cinfo)
293{
294 unsigned long prate;
295
296 if (cinfo->fck_div > 16 || cinfo->fck_div == 0)
297 return -EINVAL;
298
299 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
300
301 cinfo->fck = prate / cinfo->fck_div;
302
303 return 0;
304}
305
306int dss_set_clock_div(struct dss_clock_info *cinfo)
307{
308 unsigned long prate;
309 int r;
310
311 if (cpu_is_omap34xx()) {
312 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
313 DSSDBG("dpll4_m4 = %ld\n", prate);
314
315 r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div);
316 if (r)
317 return r;
318 }
319
320 DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
321
322 return 0;
323}
324
325int dss_get_clock_div(struct dss_clock_info *cinfo)
326{
327 cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK1);
328
329 if (cpu_is_omap34xx()) {
330 unsigned long prate;
331 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
332 cinfo->fck_div = prate / (cinfo->fck / 2);
333 } else {
334 cinfo->fck_div = 0;
335 }
336
337 return 0;
338}
339
340unsigned long dss_get_dpll4_rate(void)
341{
342 if (cpu_is_omap34xx())
343 return clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
344 else
345 return 0;
346}
347
348int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
349 struct dss_clock_info *dss_cinfo,
350 struct dispc_clock_info *dispc_cinfo)
351{
352 unsigned long prate;
353 struct dss_clock_info best_dss;
354 struct dispc_clock_info best_dispc;
355
356 unsigned long fck;
357
358 u16 fck_div;
359
360 int match = 0;
361 int min_fck_per_pck;
362
363 prate = dss_get_dpll4_rate();
364
365 fck = dss_clk_get_rate(DSS_CLK_FCK1);
366 if (req_pck == dss.cache_req_pck &&
367 ((cpu_is_omap34xx() && prate == dss.cache_prate) ||
368 dss.cache_dss_cinfo.fck == fck)) {
369 DSSDBG("dispc clock info found from cache.\n");
370 *dss_cinfo = dss.cache_dss_cinfo;
371 *dispc_cinfo = dss.cache_dispc_cinfo;
372 return 0;
373 }
374
375 min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
376
377 if (min_fck_per_pck &&
378 req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
379 DSSERR("Requested pixel clock not possible with the current "
380 "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
381 "the constraint off.\n");
382 min_fck_per_pck = 0;
383 }
384
385retry:
386 memset(&best_dss, 0, sizeof(best_dss));
387 memset(&best_dispc, 0, sizeof(best_dispc));
388
389 if (cpu_is_omap24xx()) {
390 struct dispc_clock_info cur_dispc;
391 /* XXX can we change the clock on omap2? */
392 fck = dss_clk_get_rate(DSS_CLK_FCK1);
393 fck_div = 1;
394
395 dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
396 match = 1;
397
398 best_dss.fck = fck;
399 best_dss.fck_div = fck_div;
400
401 best_dispc = cur_dispc;
402
403 goto found;
404 } else if (cpu_is_omap34xx()) {
405 for (fck_div = 16; fck_div > 0; --fck_div) {
406 struct dispc_clock_info cur_dispc;
407
408 fck = prate / fck_div * 2;
409
410 if (fck > DISPC_MAX_FCK)
411 continue;
412
413 if (min_fck_per_pck &&
414 fck < req_pck * min_fck_per_pck)
415 continue;
416
417 match = 1;
418
419 dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
420
421 if (abs(cur_dispc.pck - req_pck) <
422 abs(best_dispc.pck - req_pck)) {
423
424 best_dss.fck = fck;
425 best_dss.fck_div = fck_div;
426
427 best_dispc = cur_dispc;
428
429 if (cur_dispc.pck == req_pck)
430 goto found;
431 }
432 }
433 } else {
434 BUG();
435 }
436
437found:
438 if (!match) {
439 if (min_fck_per_pck) {
440 DSSERR("Could not find suitable clock settings.\n"
441 "Turning FCK/PCK constraint off and"
442 "trying again.\n");
443 min_fck_per_pck = 0;
444 goto retry;
445 }
446
447 DSSERR("Could not find suitable clock settings.\n");
448
449 return -EINVAL;
450 }
451
452 if (dss_cinfo)
453 *dss_cinfo = best_dss;
454 if (dispc_cinfo)
455 *dispc_cinfo = best_dispc;
456
457 dss.cache_req_pck = req_pck;
458 dss.cache_prate = prate;
459 dss.cache_dss_cinfo = best_dss;
460 dss.cache_dispc_cinfo = best_dispc;
461
462 return 0;
463}
464
465
466
467static irqreturn_t dss_irq_handler_omap2(int irq, void *arg)
468{
469 dispc_irq_handler();
470
471 return IRQ_HANDLED;
472}
473
474static irqreturn_t dss_irq_handler_omap3(int irq, void *arg)
475{
476 u32 irqstatus;
477
478 irqstatus = dss_read_reg(DSS_IRQSTATUS);
479
480 if (irqstatus & (1<<0)) /* DISPC_IRQ */
481 dispc_irq_handler();
482#ifdef CONFIG_OMAP2_DSS_DSI
483 if (irqstatus & (1<<1)) /* DSI_IRQ */
484 dsi_irq_handler();
485#endif
486
487 return IRQ_HANDLED;
488}
489
490static int _omap_dss_wait_reset(void)
491{
492 int t = 0;
493
494 while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) {
495 if (++t > 1000) {
496 DSSERR("soft reset failed\n");
497 return -ENODEV;
498 }
499 udelay(1);
500 }
501
502 return 0;
503}
504
505static int _omap_dss_reset(void)
506{
507 /* Soft reset */
508 REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
509 return _omap_dss_wait_reset();
510}
511
512void dss_set_venc_output(enum omap_dss_venc_type type)
513{
514 int l = 0;
515
516 if (type == OMAP_DSS_VENC_TYPE_COMPOSITE)
517 l = 0;
518 else if (type == OMAP_DSS_VENC_TYPE_SVIDEO)
519 l = 1;
520 else
521 BUG();
522
523 /* venc out selection. 0 = comp, 1 = svideo */
524 REG_FLD_MOD(DSS_CONTROL, l, 6, 6);
525}
526
527void dss_set_dac_pwrdn_bgz(bool enable)
528{
529 REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
530}
531
532int dss_init(bool skip_init)
533{
534 int r;
535 u32 rev;
536
537 dss.base = ioremap(DSS_BASE, DSS_SZ_REGS);
538 if (!dss.base) {
539 DSSERR("can't ioremap DSS\n");
540 r = -ENOMEM;
541 goto fail0;
542 }
543
544 if (!skip_init) {
545 /* disable LCD and DIGIT output. This seems to fix the synclost
546 * problem that we get, if the bootloader starts the DSS and
547 * the kernel resets it */
548 omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
549
550 /* We need to wait here a bit, otherwise we sometimes start to
551 * get synclost errors, and after that only power cycle will
552 * restore DSS functionality. I have no idea why this happens.
553 * And we have to wait _before_ resetting the DSS, but after
554 * enabling clocks.
555 */
556 msleep(50);
557
558 _omap_dss_reset();
559 }
560
561 /* autoidle */
562 REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
563
564 /* Select DPLL */
565 REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
566
567#ifdef CONFIG_OMAP2_DSS_VENC
568 REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */
569 REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */
570 REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */
571#endif
572
573 r = request_irq(INT_24XX_DSS_IRQ,
574 cpu_is_omap24xx()
575 ? dss_irq_handler_omap2
576 : dss_irq_handler_omap3,
577 0, "OMAP DSS", NULL);
578
579 if (r < 0) {
580 DSSERR("omap2 dss: request_irq failed\n");
581 goto fail1;
582 }
583
584 if (cpu_is_omap34xx()) {
585 dss.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
586 if (IS_ERR(dss.dpll4_m4_ck)) {
587 DSSERR("Failed to get dpll4_m4_ck\n");
588 r = PTR_ERR(dss.dpll4_m4_ck);
589 goto fail2;
590 }
591 }
592
593 dss.dsi_clk_source = DSS_SRC_DSS1_ALWON_FCLK;
594 dss.dispc_clk_source = DSS_SRC_DSS1_ALWON_FCLK;
595
596 dss_save_context();
597
598 rev = dss_read_reg(DSS_REVISION);
599 printk(KERN_INFO "OMAP DSS rev %d.%d\n",
600 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
601
602 return 0;
603
604fail2:
605 free_irq(INT_24XX_DSS_IRQ, NULL);
606fail1:
607 iounmap(dss.base);
608fail0:
609 return r;
610}
611
612void dss_exit(void)
613{
614 if (cpu_is_omap34xx())
615 clk_put(dss.dpll4_m4_ck);
616
617 free_irq(INT_24XX_DSS_IRQ, NULL);
618
619 iounmap(dss.base);
620}
621
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
new file mode 100644
index 000000000000..24326a5fd292
--- /dev/null
+++ b/drivers/video/omap2/dss/dss.h
@@ -0,0 +1,395 @@
1/*
2 * linux/drivers/video/omap2/dss/dss.h
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#ifndef __OMAP2_DSS_H
24#define __OMAP2_DSS_H
25
26#ifdef CONFIG_OMAP2_DSS_DEBUG_SUPPORT
27#define DEBUG
28#endif
29
30#ifdef DEBUG
31extern unsigned int dss_debug;
32#ifdef DSS_SUBSYS_NAME
33#define DSSDBG(format, ...) \
34 if (dss_debug) \
35 printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME ": " format, \
36 ## __VA_ARGS__)
37#else
38#define DSSDBG(format, ...) \
39 if (dss_debug) \
40 printk(KERN_DEBUG "omapdss: " format, ## __VA_ARGS__)
41#endif
42
43#ifdef DSS_SUBSYS_NAME
44#define DSSDBGF(format, ...) \
45 if (dss_debug) \
46 printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME \
47 ": %s(" format ")\n", \
48 __func__, \
49 ## __VA_ARGS__)
50#else
51#define DSSDBGF(format, ...) \
52 if (dss_debug) \
53 printk(KERN_DEBUG "omapdss: " \
54 ": %s(" format ")\n", \
55 __func__, \
56 ## __VA_ARGS__)
57#endif
58
59#else /* DEBUG */
60#define DSSDBG(format, ...)
61#define DSSDBGF(format, ...)
62#endif
63
64
65#ifdef DSS_SUBSYS_NAME
66#define DSSERR(format, ...) \
67 printk(KERN_ERR "omapdss " DSS_SUBSYS_NAME " error: " format, \
68 ## __VA_ARGS__)
69#else
70#define DSSERR(format, ...) \
71 printk(KERN_ERR "omapdss error: " format, ## __VA_ARGS__)
72#endif
73
74#ifdef DSS_SUBSYS_NAME
75#define DSSINFO(format, ...) \
76 printk(KERN_INFO "omapdss " DSS_SUBSYS_NAME ": " format, \
77 ## __VA_ARGS__)
78#else
79#define DSSINFO(format, ...) \
80 printk(KERN_INFO "omapdss: " format, ## __VA_ARGS__)
81#endif
82
83#ifdef DSS_SUBSYS_NAME
84#define DSSWARN(format, ...) \
85 printk(KERN_WARNING "omapdss " DSS_SUBSYS_NAME ": " format, \
86 ## __VA_ARGS__)
87#else
88#define DSSWARN(format, ...) \
89 printk(KERN_WARNING "omapdss: " format, ## __VA_ARGS__)
90#endif
91
92/* OMAP TRM gives bitfields as start:end, where start is the higher bit
93 number. For example 7:0 */
94#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end))
95#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
96#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end))
97#define FLD_MOD(orig, val, start, end) \
98 (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
99
100#define DISPC_MAX_FCK 173000000
101
102enum omap_burst_size {
103 OMAP_DSS_BURST_4x32 = 0,
104 OMAP_DSS_BURST_8x32 = 1,
105 OMAP_DSS_BURST_16x32 = 2,
106};
107
108enum omap_parallel_interface_mode {
109 OMAP_DSS_PARALLELMODE_BYPASS, /* MIPI DPI */
110 OMAP_DSS_PARALLELMODE_RFBI, /* MIPI DBI */
111 OMAP_DSS_PARALLELMODE_DSI,
112};
113
114enum dss_clock {
115 DSS_CLK_ICK = 1 << 0,
116 DSS_CLK_FCK1 = 1 << 1,
117 DSS_CLK_FCK2 = 1 << 2,
118 DSS_CLK_54M = 1 << 3,
119 DSS_CLK_96M = 1 << 4,
120};
121
122enum dss_clk_source {
123 DSS_SRC_DSI1_PLL_FCLK,
124 DSS_SRC_DSI2_PLL_FCLK,
125 DSS_SRC_DSS1_ALWON_FCLK,
126};
127
128struct dss_clock_info {
129 /* rates that we get with dividers below */
130 unsigned long fck;
131
132 /* dividers */
133 u16 fck_div;
134};
135
136struct dispc_clock_info {
137 /* rates that we get with dividers below */
138 unsigned long lck;
139 unsigned long pck;
140
141 /* dividers */
142 u16 lck_div;
143 u16 pck_div;
144};
145
146struct dsi_clock_info {
147 /* rates that we get with dividers below */
148 unsigned long fint;
149 unsigned long clkin4ddr;
150 unsigned long clkin;
151 unsigned long dsi1_pll_fclk;
152 unsigned long dsi2_pll_fclk;
153
154 unsigned long lp_clk;
155
156 /* dividers */
157 u16 regn;
158 u16 regm;
159 u16 regm3;
160 u16 regm4;
161
162 u16 lp_clk_div;
163
164 u8 highfreq;
165 bool use_dss2_fck;
166};
167
168struct seq_file;
169struct platform_device;
170
171/* 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);
178struct regulator *dss_get_vdds_dsi(void);
179struct regulator *dss_get_vdds_sdi(void);
180struct regulator *dss_get_vdda_dac(void);
181
182/* display */
183int dss_suspend_all_devices(void);
184int dss_resume_all_devices(void);
185void dss_disable_all_devices(void);
186
187void dss_init_device(struct platform_device *pdev,
188 struct omap_dss_device *dssdev);
189void dss_uninit_device(struct platform_device *pdev,
190 struct omap_dss_device *dssdev);
191bool dss_use_replication(struct omap_dss_device *dssdev,
192 enum omap_color_mode mode);
193void default_get_overlay_fifo_thresholds(enum omap_plane plane,
194 u32 fifo_size, enum omap_burst_size *burst_size,
195 u32 *fifo_low, u32 *fifo_high);
196
197/* manager */
198int dss_init_overlay_managers(struct platform_device *pdev);
199void dss_uninit_overlay_managers(struct platform_device *pdev);
200int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
201void dss_setup_partial_planes(struct omap_dss_device *dssdev,
202 u16 *x, u16 *y, u16 *w, u16 *h);
203void dss_start_update(struct omap_dss_device *dssdev);
204
205/* overlay */
206void dss_init_overlays(struct platform_device *pdev);
207void dss_uninit_overlays(struct platform_device *pdev);
208int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev);
209void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
210#ifdef L4_EXAMPLE
211void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr);
212#endif
213void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
214
215/* DSS */
216int dss_init(bool skip_init);
217void dss_exit(void);
218
219void dss_save_context(void);
220void dss_restore_context(void);
221
222void dss_dump_regs(struct seq_file *s);
223
224void dss_sdi_init(u8 datapairs);
225int dss_sdi_enable(void);
226void dss_sdi_disable(void);
227
228void dss_select_dispc_clk_source(enum dss_clk_source clk_src);
229void dss_select_dsi_clk_source(enum dss_clk_source clk_src);
230enum dss_clk_source dss_get_dispc_clk_source(void);
231enum dss_clk_source dss_get_dsi_clk_source(void);
232
233void dss_set_venc_output(enum omap_dss_venc_type type);
234void dss_set_dac_pwrdn_bgz(bool enable);
235
236unsigned long dss_get_dpll4_rate(void);
237int dss_calc_clock_rates(struct dss_clock_info *cinfo);
238int dss_set_clock_div(struct dss_clock_info *cinfo);
239int dss_get_clock_div(struct dss_clock_info *cinfo);
240int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
241 struct dss_clock_info *dss_cinfo,
242 struct dispc_clock_info *dispc_cinfo);
243
244/* SDI */
245int sdi_init(bool skip_init);
246void sdi_exit(void);
247int sdi_init_display(struct omap_dss_device *display);
248
249/* DSI */
250int dsi_init(struct platform_device *pdev);
251void dsi_exit(void);
252
253void dsi_dump_clocks(struct seq_file *s);
254void dsi_dump_irqs(struct seq_file *s);
255void dsi_dump_regs(struct seq_file *s);
256
257void dsi_save_context(void);
258void dsi_restore_context(void);
259
260int dsi_init_display(struct omap_dss_device *display);
261void dsi_irq_handler(void);
262unsigned long dsi_get_dsi1_pll_rate(void);
263int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo);
264int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck,
265 struct dsi_clock_info *cinfo,
266 struct dispc_clock_info *dispc_cinfo);
267int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk,
268 bool enable_hsdiv);
269void dsi_pll_uninit(void);
270void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
271 u32 fifo_size, enum omap_burst_size *burst_size,
272 u32 *fifo_low, u32 *fifo_high);
273
274/* DPI */
275int dpi_init(struct platform_device *pdev);
276void dpi_exit(void);
277int dpi_init_display(struct omap_dss_device *dssdev);
278
279/* DISPC */
280int dispc_init(void);
281void dispc_exit(void);
282void dispc_dump_clocks(struct seq_file *s);
283void dispc_dump_irqs(struct seq_file *s);
284void dispc_dump_regs(struct seq_file *s);
285void dispc_irq_handler(void);
286void dispc_fake_vsync_irq(void);
287
288void dispc_save_context(void);
289void dispc_restore_context(void);
290
291void dispc_enable_sidle(void);
292void dispc_disable_sidle(void);
293
294void dispc_lcd_enable_signal_polarity(bool act_high);
295void dispc_lcd_enable_signal(bool enable);
296void dispc_pck_free_enable(bool enable);
297void dispc_enable_fifohandcheck(bool enable);
298
299void dispc_set_lcd_size(u16 width, u16 height);
300void dispc_set_digit_size(u16 width, u16 height);
301u32 dispc_get_plane_fifo_size(enum omap_plane plane);
302void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high);
303void dispc_enable_fifomerge(bool enable);
304void dispc_set_burst_size(enum omap_plane plane,
305 enum omap_burst_size burst_size);
306
307void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr);
308void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr);
309void dispc_set_plane_pos(enum omap_plane plane, u16 x, u16 y);
310void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height);
311void dispc_set_channel_out(enum omap_plane plane,
312 enum omap_channel channel_out);
313
314int dispc_setup_plane(enum omap_plane plane,
315 u32 paddr, u16 screen_width,
316 u16 pos_x, u16 pos_y,
317 u16 width, u16 height,
318 u16 out_width, u16 out_height,
319 enum omap_color_mode color_mode,
320 bool ilace,
321 enum omap_dss_rotation_type rotation_type,
322 u8 rotation, bool mirror,
323 u8 global_alpha);
324
325bool dispc_go_busy(enum omap_channel channel);
326void dispc_go(enum omap_channel channel);
327void dispc_enable_channel(enum omap_channel channel, bool enable);
328bool dispc_is_channel_enabled(enum omap_channel channel);
329int dispc_enable_plane(enum omap_plane plane, bool enable);
330void dispc_enable_replication(enum omap_plane plane, bool enable);
331
332void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode);
333void dispc_set_tft_data_lines(u8 data_lines);
334void dispc_set_lcd_display_type(enum omap_lcd_display_type type);
335void dispc_set_loadmode(enum omap_dss_load_mode mode);
336
337void dispc_set_default_color(enum omap_channel channel, u32 color);
338u32 dispc_get_default_color(enum omap_channel channel);
339void dispc_set_trans_key(enum omap_channel ch,
340 enum omap_dss_trans_key_type type,
341 u32 trans_key);
342void dispc_get_trans_key(enum omap_channel ch,
343 enum omap_dss_trans_key_type *type,
344 u32 *trans_key);
345void dispc_enable_trans_key(enum omap_channel ch, bool enable);
346void dispc_enable_alpha_blending(enum omap_channel ch, bool enable);
347bool dispc_trans_key_enabled(enum omap_channel ch);
348bool dispc_alpha_blending_enabled(enum omap_channel ch);
349
350bool dispc_lcd_timings_ok(struct omap_video_timings *timings);
351void dispc_set_lcd_timings(struct omap_video_timings *timings);
352unsigned long dispc_fclk_rate(void);
353unsigned long dispc_lclk_rate(void);
354unsigned long dispc_pclk_rate(void);
355void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb);
356void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
357 struct dispc_clock_info *cinfo);
358int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
359 struct dispc_clock_info *cinfo);
360int dispc_set_clock_div(struct dispc_clock_info *cinfo);
361int dispc_get_clock_div(struct dispc_clock_info *cinfo);
362
363
364/* VENC */
365int venc_init(struct platform_device *pdev);
366void venc_exit(void);
367void venc_dump_regs(struct seq_file *s);
368int venc_init_display(struct omap_dss_device *display);
369
370/* RFBI */
371int rfbi_init(void);
372void rfbi_exit(void);
373void rfbi_dump_regs(struct seq_file *s);
374
375int rfbi_configure(int rfbi_module, int bpp, int lines);
376void rfbi_enable_rfbi(bool enable);
377void rfbi_transfer_area(u16 width, u16 height,
378 void (callback)(void *data), void *data);
379void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t);
380unsigned long rfbi_get_max_tx_rate(void);
381int rfbi_init_display(struct omap_dss_device *display);
382
383
384#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
385static inline void dss_collect_irq_stats(u32 irqstatus, unsigned *irq_arr)
386{
387 int b;
388 for (b = 0; b < 32; ++b) {
389 if (irqstatus & (1 << b))
390 irq_arr[b]++;
391 }
392}
393#endif
394
395#endif
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
new file mode 100644
index 000000000000..0820986d4a68
--- /dev/null
+++ b/drivers/video/omap2/dss/manager.c
@@ -0,0 +1,1520 @@
1/*
2 * linux/drivers/video/omap2/dss/manager.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#define DSS_SUBSYS_NAME "MANAGER"
24
25#include <linux/kernel.h>
26#include <linux/slab.h>
27#include <linux/module.h>
28#include <linux/platform_device.h>
29#include <linux/spinlock.h>
30#include <linux/jiffies.h>
31
32#include <plat/display.h>
33#include <plat/cpu.h>
34
35#include "dss.h"
36
37static int num_managers;
38static struct list_head manager_list;
39
40static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
41{
42 return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
43}
44
45static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
46{
47 return snprintf(buf, PAGE_SIZE, "%s\n",
48 mgr->device ? mgr->device->name : "<none>");
49}
50
51static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
52 const char *buf, size_t size)
53{
54 int r = 0;
55 size_t len = size;
56 struct omap_dss_device *dssdev = NULL;
57
58 int match(struct omap_dss_device *dssdev, void *data)
59 {
60 const char *str = data;
61 return sysfs_streq(dssdev->name, str);
62 }
63
64 if (buf[size-1] == '\n')
65 --len;
66
67 if (len > 0)
68 dssdev = omap_dss_find_device((void *)buf, match);
69
70 if (len > 0 && dssdev == NULL)
71 return -EINVAL;
72
73 if (dssdev)
74 DSSDBG("display %s found\n", dssdev->name);
75
76 if (mgr->device) {
77 r = mgr->unset_device(mgr);
78 if (r) {
79 DSSERR("failed to unset display\n");
80 goto put_device;
81 }
82 }
83
84 if (dssdev) {
85 r = mgr->set_device(mgr, dssdev);
86 if (r) {
87 DSSERR("failed to set manager\n");
88 goto put_device;
89 }
90
91 r = mgr->apply(mgr);
92 if (r) {
93 DSSERR("failed to apply dispc config\n");
94 goto put_device;
95 }
96 }
97
98put_device:
99 if (dssdev)
100 omap_dss_put_device(dssdev);
101
102 return r ? r : size;
103}
104
105static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
106 char *buf)
107{
108 return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.default_color);
109}
110
111static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
112 const char *buf, size_t size)
113{
114 struct omap_overlay_manager_info info;
115 u32 color;
116 int r;
117
118 if (sscanf(buf, "%d", &color) != 1)
119 return -EINVAL;
120
121 mgr->get_manager_info(mgr, &info);
122
123 info.default_color = color;
124
125 r = mgr->set_manager_info(mgr, &info);
126 if (r)
127 return r;
128
129 r = mgr->apply(mgr);
130 if (r)
131 return r;
132
133 return size;
134}
135
136static const char *trans_key_type_str[] = {
137 "gfx-destination",
138 "video-source",
139};
140
141static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
142 char *buf)
143{
144 enum omap_dss_trans_key_type key_type;
145
146 key_type = mgr->info.trans_key_type;
147 BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
148
149 return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
150}
151
152static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
153 const char *buf, size_t size)
154{
155 enum omap_dss_trans_key_type key_type;
156 struct omap_overlay_manager_info info;
157 int r;
158
159 for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
160 key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
161 if (sysfs_streq(buf, trans_key_type_str[key_type]))
162 break;
163 }
164
165 if (key_type == ARRAY_SIZE(trans_key_type_str))
166 return -EINVAL;
167
168 mgr->get_manager_info(mgr, &info);
169
170 info.trans_key_type = key_type;
171
172 r = mgr->set_manager_info(mgr, &info);
173 if (r)
174 return r;
175
176 r = mgr->apply(mgr);
177 if (r)
178 return r;
179
180 return size;
181}
182
183static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
184 char *buf)
185{
186 return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_key);
187}
188
189static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
190 const char *buf, size_t size)
191{
192 struct omap_overlay_manager_info info;
193 u32 key_value;
194 int r;
195
196 if (sscanf(buf, "%d", &key_value) != 1)
197 return -EINVAL;
198
199 mgr->get_manager_info(mgr, &info);
200
201 info.trans_key = key_value;
202
203 r = mgr->set_manager_info(mgr, &info);
204 if (r)
205 return r;
206
207 r = mgr->apply(mgr);
208 if (r)
209 return r;
210
211 return size;
212}
213
214static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
215 char *buf)
216{
217 return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_enabled);
218}
219
220static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
221 const char *buf, size_t size)
222{
223 struct omap_overlay_manager_info info;
224 int enable;
225 int r;
226
227 if (sscanf(buf, "%d", &enable) != 1)
228 return -EINVAL;
229
230 mgr->get_manager_info(mgr, &info);
231
232 info.trans_enabled = enable ? true : false;
233
234 r = mgr->set_manager_info(mgr, &info);
235 if (r)
236 return r;
237
238 r = mgr->apply(mgr);
239 if (r)
240 return r;
241
242 return size;
243}
244
245static ssize_t manager_alpha_blending_enabled_show(
246 struct omap_overlay_manager *mgr, char *buf)
247{
248 return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.alpha_enabled);
249}
250
251static ssize_t manager_alpha_blending_enabled_store(
252 struct omap_overlay_manager *mgr,
253 const char *buf, size_t size)
254{
255 struct omap_overlay_manager_info info;
256 int enable;
257 int r;
258
259 if (sscanf(buf, "%d", &enable) != 1)
260 return -EINVAL;
261
262 mgr->get_manager_info(mgr, &info);
263
264 info.alpha_enabled = enable ? true : false;
265
266 r = mgr->set_manager_info(mgr, &info);
267 if (r)
268 return r;
269
270 r = mgr->apply(mgr);
271 if (r)
272 return r;
273
274 return size;
275}
276
277struct manager_attribute {
278 struct attribute attr;
279 ssize_t (*show)(struct omap_overlay_manager *, char *);
280 ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
281};
282
283#define MANAGER_ATTR(_name, _mode, _show, _store) \
284 struct manager_attribute manager_attr_##_name = \
285 __ATTR(_name, _mode, _show, _store)
286
287static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
288static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
289 manager_display_show, manager_display_store);
290static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
291 manager_default_color_show, manager_default_color_store);
292static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
293 manager_trans_key_type_show, manager_trans_key_type_store);
294static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
295 manager_trans_key_value_show, manager_trans_key_value_store);
296static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
297 manager_trans_key_enabled_show,
298 manager_trans_key_enabled_store);
299static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
300 manager_alpha_blending_enabled_show,
301 manager_alpha_blending_enabled_store);
302
303
304static struct attribute *manager_sysfs_attrs[] = {
305 &manager_attr_name.attr,
306 &manager_attr_display.attr,
307 &manager_attr_default_color.attr,
308 &manager_attr_trans_key_type.attr,
309 &manager_attr_trans_key_value.attr,
310 &manager_attr_trans_key_enabled.attr,
311 &manager_attr_alpha_blending_enabled.attr,
312 NULL
313};
314
315static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
316 char *buf)
317{
318 struct omap_overlay_manager *manager;
319 struct manager_attribute *manager_attr;
320
321 manager = container_of(kobj, struct omap_overlay_manager, kobj);
322 manager_attr = container_of(attr, struct manager_attribute, attr);
323
324 if (!manager_attr->show)
325 return -ENOENT;
326
327 return manager_attr->show(manager, buf);
328}
329
330static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
331 const char *buf, size_t size)
332{
333 struct omap_overlay_manager *manager;
334 struct manager_attribute *manager_attr;
335
336 manager = container_of(kobj, struct omap_overlay_manager, kobj);
337 manager_attr = container_of(attr, struct manager_attribute, attr);
338
339 if (!manager_attr->store)
340 return -ENOENT;
341
342 return manager_attr->store(manager, buf, size);
343}
344
345static const struct sysfs_ops manager_sysfs_ops = {
346 .show = manager_attr_show,
347 .store = manager_attr_store,
348};
349
350static struct kobj_type manager_ktype = {
351 .sysfs_ops = &manager_sysfs_ops,
352 .default_attrs = manager_sysfs_attrs,
353};
354
355/*
356 * We have 4 levels of cache for the dispc settings. First two are in SW and
357 * the latter two in HW.
358 *
359 * +--------------------+
360 * |overlay/manager_info|
361 * +--------------------+
362 * v
363 * apply()
364 * v
365 * +--------------------+
366 * | dss_cache |
367 * +--------------------+
368 * v
369 * configure()
370 * v
371 * +--------------------+
372 * | shadow registers |
373 * +--------------------+
374 * v
375 * VFP or lcd/digit_enable
376 * v
377 * +--------------------+
378 * | registers |
379 * +--------------------+
380 */
381
382struct overlay_cache_data {
383 /* If true, cache changed, but not written to shadow registers. Set
384 * in apply(), cleared when registers written. */
385 bool dirty;
386 /* If true, shadow registers contain changed values not yet in real
387 * registers. Set when writing to shadow registers, cleared at
388 * VSYNC/EVSYNC */
389 bool shadow_dirty;
390
391 bool enabled;
392
393 u32 paddr;
394 void __iomem *vaddr;
395 u16 screen_width;
396 u16 width;
397 u16 height;
398 enum omap_color_mode color_mode;
399 u8 rotation;
400 enum omap_dss_rotation_type rotation_type;
401 bool mirror;
402
403 u16 pos_x;
404 u16 pos_y;
405 u16 out_width; /* if 0, out_width == width */
406 u16 out_height; /* if 0, out_height == height */
407 u8 global_alpha;
408
409 enum omap_channel channel;
410 bool replication;
411 bool ilace;
412
413 enum omap_burst_size burst_size;
414 u32 fifo_low;
415 u32 fifo_high;
416
417 bool manual_update;
418};
419
420struct manager_cache_data {
421 /* If true, cache changed, but not written to shadow registers. Set
422 * in apply(), cleared when registers written. */
423 bool dirty;
424 /* If true, shadow registers contain changed values not yet in real
425 * registers. Set when writing to shadow registers, cleared at
426 * VSYNC/EVSYNC */
427 bool shadow_dirty;
428
429 u32 default_color;
430
431 enum omap_dss_trans_key_type trans_key_type;
432 u32 trans_key;
433 bool trans_enabled;
434
435 bool alpha_enabled;
436
437 bool manual_upd_display;
438 bool manual_update;
439 bool do_manual_update;
440
441 /* manual update region */
442 u16 x, y, w, h;
443};
444
445static struct {
446 spinlock_t lock;
447 struct overlay_cache_data overlay_cache[3];
448 struct manager_cache_data manager_cache[2];
449
450 bool irq_enabled;
451} dss_cache;
452
453
454
455static int omap_dss_set_device(struct omap_overlay_manager *mgr,
456 struct omap_dss_device *dssdev)
457{
458 int i;
459 int r;
460
461 if (dssdev->manager) {
462 DSSERR("display '%s' already has a manager '%s'\n",
463 dssdev->name, dssdev->manager->name);
464 return -EINVAL;
465 }
466
467 if ((mgr->supported_displays & dssdev->type) == 0) {
468 DSSERR("display '%s' does not support manager '%s'\n",
469 dssdev->name, mgr->name);
470 return -EINVAL;
471 }
472
473 for (i = 0; i < mgr->num_overlays; i++) {
474 struct omap_overlay *ovl = mgr->overlays[i];
475
476 if (ovl->manager != mgr || !ovl->info.enabled)
477 continue;
478
479 r = dss_check_overlay(ovl, dssdev);
480 if (r)
481 return r;
482 }
483
484 dssdev->manager = mgr;
485 mgr->device = dssdev;
486 mgr->device_changed = true;
487
488 return 0;
489}
490
491static int omap_dss_unset_device(struct omap_overlay_manager *mgr)
492{
493 if (!mgr->device) {
494 DSSERR("failed to unset display, display not set.\n");
495 return -EINVAL;
496 }
497
498 mgr->device->manager = NULL;
499 mgr->device = NULL;
500 mgr->device_changed = true;
501
502 return 0;
503}
504
505static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
506{
507 unsigned long timeout = msecs_to_jiffies(500);
508 u32 irq;
509
510 if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC)
511 irq = DISPC_IRQ_EVSYNC_ODD;
512 else
513 irq = DISPC_IRQ_VSYNC;
514
515 return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
516}
517
518static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
519{
520 unsigned long timeout = msecs_to_jiffies(500);
521 struct manager_cache_data *mc;
522 enum omap_channel channel;
523 u32 irq;
524 int r;
525 int i;
526 struct omap_dss_device *dssdev = mgr->device;
527
528 if (!dssdev)
529 return 0;
530
531 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
532 irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
533 channel = OMAP_DSS_CHANNEL_DIGIT;
534 } else {
535 if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
536 enum omap_dss_update_mode mode;
537 mode = dssdev->driver->get_update_mode(dssdev);
538 if (mode != OMAP_DSS_UPDATE_AUTO)
539 return 0;
540
541 irq = DISPC_IRQ_FRAMEDONE;
542 } else {
543 irq = DISPC_IRQ_VSYNC;
544 }
545 channel = OMAP_DSS_CHANNEL_LCD;
546 }
547
548 mc = &dss_cache.manager_cache[mgr->id];
549 i = 0;
550 while (1) {
551 unsigned long flags;
552 bool shadow_dirty, dirty;
553
554 spin_lock_irqsave(&dss_cache.lock, flags);
555 dirty = mc->dirty;
556 shadow_dirty = mc->shadow_dirty;
557 spin_unlock_irqrestore(&dss_cache.lock, flags);
558
559 if (!dirty && !shadow_dirty) {
560 r = 0;
561 break;
562 }
563
564 /* 4 iterations is the worst case:
565 * 1 - initial iteration, dirty = true (between VFP and VSYNC)
566 * 2 - first VSYNC, dirty = true
567 * 3 - dirty = false, shadow_dirty = true
568 * 4 - shadow_dirty = false */
569 if (i++ == 3) {
570 DSSERR("mgr(%d)->wait_for_go() not finishing\n",
571 mgr->id);
572 r = 0;
573 break;
574 }
575
576 r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
577 if (r == -ERESTARTSYS)
578 break;
579
580 if (r) {
581 DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id);
582 break;
583 }
584 }
585
586 return r;
587}
588
589int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
590{
591 unsigned long timeout = msecs_to_jiffies(500);
592 enum omap_channel channel;
593 struct overlay_cache_data *oc;
594 struct omap_dss_device *dssdev;
595 u32 irq;
596 int r;
597 int i;
598
599 if (!ovl->manager || !ovl->manager->device)
600 return 0;
601
602 dssdev = ovl->manager->device;
603
604 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
605 irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
606 channel = OMAP_DSS_CHANNEL_DIGIT;
607 } else {
608 if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
609 enum omap_dss_update_mode mode;
610 mode = dssdev->driver->get_update_mode(dssdev);
611 if (mode != OMAP_DSS_UPDATE_AUTO)
612 return 0;
613
614 irq = DISPC_IRQ_FRAMEDONE;
615 } else {
616 irq = DISPC_IRQ_VSYNC;
617 }
618 channel = OMAP_DSS_CHANNEL_LCD;
619 }
620
621 oc = &dss_cache.overlay_cache[ovl->id];
622 i = 0;
623 while (1) {
624 unsigned long flags;
625 bool shadow_dirty, dirty;
626
627 spin_lock_irqsave(&dss_cache.lock, flags);
628 dirty = oc->dirty;
629 shadow_dirty = oc->shadow_dirty;
630 spin_unlock_irqrestore(&dss_cache.lock, flags);
631
632 if (!dirty && !shadow_dirty) {
633 r = 0;
634 break;
635 }
636
637 /* 4 iterations is the worst case:
638 * 1 - initial iteration, dirty = true (between VFP and VSYNC)
639 * 2 - first VSYNC, dirty = true
640 * 3 - dirty = false, shadow_dirty = true
641 * 4 - shadow_dirty = false */
642 if (i++ == 3) {
643 DSSERR("ovl(%d)->wait_for_go() not finishing\n",
644 ovl->id);
645 r = 0;
646 break;
647 }
648
649 r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
650 if (r == -ERESTARTSYS)
651 break;
652
653 if (r) {
654 DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id);
655 break;
656 }
657 }
658
659 return r;
660}
661
662static int overlay_enabled(struct omap_overlay *ovl)
663{
664 return ovl->info.enabled && ovl->manager && ovl->manager->device;
665}
666
667/* Is rect1 a subset of rect2? */
668static bool rectangle_subset(int x1, int y1, int w1, int h1,
669 int x2, int y2, int w2, int h2)
670{
671 if (x1 < x2 || y1 < y2)
672 return false;
673
674 if (x1 + w1 > x2 + w2)
675 return false;
676
677 if (y1 + h1 > y2 + h2)
678 return false;
679
680 return true;
681}
682
683/* Do rect1 and rect2 overlap? */
684static bool rectangle_intersects(int x1, int y1, int w1, int h1,
685 int x2, int y2, int w2, int h2)
686{
687 if (x1 >= x2 + w2)
688 return false;
689
690 if (x2 >= x1 + w1)
691 return false;
692
693 if (y1 >= y2 + h2)
694 return false;
695
696 if (y2 >= y1 + h1)
697 return false;
698
699 return true;
700}
701
702static bool dispc_is_overlay_scaled(struct overlay_cache_data *oc)
703{
704 if (oc->out_width != 0 && oc->width != oc->out_width)
705 return true;
706
707 if (oc->out_height != 0 && oc->height != oc->out_height)
708 return true;
709
710 return false;
711}
712
713static int configure_overlay(enum omap_plane plane)
714{
715 struct overlay_cache_data *c;
716 struct manager_cache_data *mc;
717 u16 outw, outh;
718 u16 x, y, w, h;
719 u32 paddr;
720 int r;
721
722 DSSDBGF("%d", plane);
723
724 c = &dss_cache.overlay_cache[plane];
725
726 if (!c->enabled) {
727 dispc_enable_plane(plane, 0);
728 return 0;
729 }
730
731 mc = &dss_cache.manager_cache[c->channel];
732
733 x = c->pos_x;
734 y = c->pos_y;
735 w = c->width;
736 h = c->height;
737 outw = c->out_width == 0 ? c->width : c->out_width;
738 outh = c->out_height == 0 ? c->height : c->out_height;
739 paddr = c->paddr;
740
741 if (c->manual_update && mc->do_manual_update) {
742 unsigned bpp;
743 /* If the overlay is outside the update region, disable it */
744 if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h,
745 x, y, outw, outh)) {
746 dispc_enable_plane(plane, 0);
747 return 0;
748 }
749
750 switch (c->color_mode) {
751 case OMAP_DSS_COLOR_RGB16:
752 case OMAP_DSS_COLOR_ARGB16:
753 case OMAP_DSS_COLOR_YUV2:
754 case OMAP_DSS_COLOR_UYVY:
755 bpp = 16;
756 break;
757
758 case OMAP_DSS_COLOR_RGB24P:
759 bpp = 24;
760 break;
761
762 case OMAP_DSS_COLOR_RGB24U:
763 case OMAP_DSS_COLOR_ARGB32:
764 case OMAP_DSS_COLOR_RGBA32:
765 case OMAP_DSS_COLOR_RGBX32:
766 bpp = 32;
767 break;
768
769 default:
770 BUG();
771 }
772
773 if (dispc_is_overlay_scaled(c)) {
774 /* If the overlay is scaled, the update area has
775 * already been enlarged to cover the whole overlay. We
776 * only need to adjust x/y here */
777 x = c->pos_x - mc->x;
778 y = c->pos_y - mc->y;
779 } else {
780 if (mc->x > c->pos_x) {
781 x = 0;
782 w -= (mc->x - c->pos_x);
783 paddr += (mc->x - c->pos_x) * bpp / 8;
784 } else {
785 x = c->pos_x - mc->x;
786 }
787
788 if (mc->y > c->pos_y) {
789 y = 0;
790 h -= (mc->y - c->pos_y);
791 paddr += (mc->y - c->pos_y) * c->screen_width *
792 bpp / 8;
793 } else {
794 y = c->pos_y - mc->y;
795 }
796
797 if (mc->w < (x+w))
798 w -= (x+w) - (mc->w);
799
800 if (mc->h < (y+h))
801 h -= (y+h) - (mc->h);
802
803 outw = w;
804 outh = h;
805 }
806 }
807
808 r = dispc_setup_plane(plane,
809 paddr,
810 c->screen_width,
811 x, y,
812 w, h,
813 outw, outh,
814 c->color_mode,
815 c->ilace,
816 c->rotation_type,
817 c->rotation,
818 c->mirror,
819 c->global_alpha);
820
821 if (r) {
822 /* this shouldn't happen */
823 DSSERR("dispc_setup_plane failed for ovl %d\n", plane);
824 dispc_enable_plane(plane, 0);
825 return r;
826 }
827
828 dispc_enable_replication(plane, c->replication);
829
830 dispc_set_burst_size(plane, c->burst_size);
831 dispc_setup_plane_fifo(plane, c->fifo_low, c->fifo_high);
832
833 dispc_enable_plane(plane, 1);
834
835 return 0;
836}
837
838static void configure_manager(enum omap_channel channel)
839{
840 struct manager_cache_data *c;
841
842 DSSDBGF("%d", channel);
843
844 c = &dss_cache.manager_cache[channel];
845
846 dispc_set_trans_key(channel, c->trans_key_type, c->trans_key);
847 dispc_enable_trans_key(channel, c->trans_enabled);
848 dispc_enable_alpha_blending(channel, c->alpha_enabled);
849}
850
851/* configure_dispc() tries to write values from cache to shadow registers.
852 * It writes only to those managers/overlays that are not busy.
853 * returns 0 if everything could be written to shadow registers.
854 * returns 1 if not everything could be written to shadow registers. */
855static int configure_dispc(void)
856{
857 struct overlay_cache_data *oc;
858 struct manager_cache_data *mc;
859 const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
860 const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
861 int i;
862 int r;
863 bool mgr_busy[2];
864 bool mgr_go[2];
865 bool busy;
866
867 r = 0;
868 busy = false;
869
870 mgr_busy[0] = dispc_go_busy(0);
871 mgr_busy[1] = dispc_go_busy(1);
872 mgr_go[0] = false;
873 mgr_go[1] = false;
874
875 /* Commit overlay settings */
876 for (i = 0; i < num_ovls; ++i) {
877 oc = &dss_cache.overlay_cache[i];
878 mc = &dss_cache.manager_cache[oc->channel];
879
880 if (!oc->dirty)
881 continue;
882
883 if (oc->manual_update && !mc->do_manual_update)
884 continue;
885
886 if (mgr_busy[oc->channel]) {
887 busy = true;
888 continue;
889 }
890
891 r = configure_overlay(i);
892 if (r)
893 DSSERR("configure_overlay %d failed\n", i);
894
895 oc->dirty = false;
896 oc->shadow_dirty = true;
897 mgr_go[oc->channel] = true;
898 }
899
900 /* Commit manager settings */
901 for (i = 0; i < num_mgrs; ++i) {
902 mc = &dss_cache.manager_cache[i];
903
904 if (!mc->dirty)
905 continue;
906
907 if (mc->manual_update && !mc->do_manual_update)
908 continue;
909
910 if (mgr_busy[i]) {
911 busy = true;
912 continue;
913 }
914
915 configure_manager(i);
916 mc->dirty = false;
917 mc->shadow_dirty = true;
918 mgr_go[i] = true;
919 }
920
921 /* set GO */
922 for (i = 0; i < num_mgrs; ++i) {
923 mc = &dss_cache.manager_cache[i];
924
925 if (!mgr_go[i])
926 continue;
927
928 /* We don't need GO with manual update display. LCD iface will
929 * always be turned off after frame, and new settings will be
930 * taken in to use at next update */
931 if (!mc->manual_upd_display)
932 dispc_go(i);
933 }
934
935 if (busy)
936 r = 1;
937 else
938 r = 0;
939
940 return r;
941}
942
943/* Configure dispc for partial update. Return possibly modified update
944 * area */
945void dss_setup_partial_planes(struct omap_dss_device *dssdev,
946 u16 *xi, u16 *yi, u16 *wi, u16 *hi)
947{
948 struct overlay_cache_data *oc;
949 struct manager_cache_data *mc;
950 const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
951 struct omap_overlay_manager *mgr;
952 int i;
953 u16 x, y, w, h;
954 unsigned long flags;
955
956 x = *xi;
957 y = *yi;
958 w = *wi;
959 h = *hi;
960
961 DSSDBG("dispc_setup_partial_planes %d,%d %dx%d\n",
962 *xi, *yi, *wi, *hi);
963
964 mgr = dssdev->manager;
965
966 if (!mgr) {
967 DSSDBG("no manager\n");
968 return;
969 }
970
971 spin_lock_irqsave(&dss_cache.lock, flags);
972
973 /* We need to show the whole overlay if it is scaled. So look for
974 * those, and make the update area larger if found.
975 * Also mark the overlay cache dirty */
976 for (i = 0; i < num_ovls; ++i) {
977 unsigned x1, y1, x2, y2;
978 unsigned outw, outh;
979
980 oc = &dss_cache.overlay_cache[i];
981
982 if (oc->channel != mgr->id)
983 continue;
984
985 oc->dirty = true;
986
987 if (!oc->enabled)
988 continue;
989
990 if (!dispc_is_overlay_scaled(oc))
991 continue;
992
993 outw = oc->out_width == 0 ? oc->width : oc->out_width;
994 outh = oc->out_height == 0 ? oc->height : oc->out_height;
995
996 /* is the overlay outside the update region? */
997 if (!rectangle_intersects(x, y, w, h,
998 oc->pos_x, oc->pos_y,
999 outw, outh))
1000 continue;
1001
1002 /* if the overlay totally inside the update region? */
1003 if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh,
1004 x, y, w, h))
1005 continue;
1006
1007 if (x > oc->pos_x)
1008 x1 = oc->pos_x;
1009 else
1010 x1 = x;
1011
1012 if (y > oc->pos_y)
1013 y1 = oc->pos_y;
1014 else
1015 y1 = y;
1016
1017 if ((x + w) < (oc->pos_x + outw))
1018 x2 = oc->pos_x + outw;
1019 else
1020 x2 = x + w;
1021
1022 if ((y + h) < (oc->pos_y + outh))
1023 y2 = oc->pos_y + outh;
1024 else
1025 y2 = y + h;
1026
1027 x = x1;
1028 y = y1;
1029 w = x2 - x1;
1030 h = y2 - y1;
1031
1032 DSSDBG("changing upd area due to ovl(%d) scaling %d,%d %dx%d\n",
1033 i, x, y, w, h);
1034 }
1035
1036 mc = &dss_cache.manager_cache[mgr->id];
1037 mc->do_manual_update = true;
1038 mc->x = x;
1039 mc->y = y;
1040 mc->w = w;
1041 mc->h = h;
1042
1043 configure_dispc();
1044
1045 mc->do_manual_update = false;
1046
1047 spin_unlock_irqrestore(&dss_cache.lock, flags);
1048
1049 *xi = x;
1050 *yi = y;
1051 *wi = w;
1052 *hi = h;
1053}
1054
1055void dss_start_update(struct omap_dss_device *dssdev)
1056{
1057 struct manager_cache_data *mc;
1058 struct overlay_cache_data *oc;
1059 const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
1060 const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
1061 struct omap_overlay_manager *mgr;
1062 int i;
1063
1064 mgr = dssdev->manager;
1065
1066 for (i = 0; i < num_ovls; ++i) {
1067 oc = &dss_cache.overlay_cache[i];
1068 if (oc->channel != mgr->id)
1069 continue;
1070
1071 oc->shadow_dirty = false;
1072 }
1073
1074 for (i = 0; i < num_mgrs; ++i) {
1075 mc = &dss_cache.manager_cache[i];
1076 if (mgr->id != i)
1077 continue;
1078
1079 mc->shadow_dirty = false;
1080 }
1081
1082 dssdev->manager->enable(dssdev->manager);
1083}
1084
1085static void dss_apply_irq_handler(void *data, u32 mask)
1086{
1087 struct manager_cache_data *mc;
1088 struct overlay_cache_data *oc;
1089 const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
1090 const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
1091 int i, r;
1092 bool mgr_busy[2];
1093
1094 mgr_busy[0] = dispc_go_busy(0);
1095 mgr_busy[1] = dispc_go_busy(1);
1096
1097 spin_lock(&dss_cache.lock);
1098
1099 for (i = 0; i < num_ovls; ++i) {
1100 oc = &dss_cache.overlay_cache[i];
1101 if (!mgr_busy[oc->channel])
1102 oc->shadow_dirty = false;
1103 }
1104
1105 for (i = 0; i < num_mgrs; ++i) {
1106 mc = &dss_cache.manager_cache[i];
1107 if (!mgr_busy[i])
1108 mc->shadow_dirty = false;
1109 }
1110
1111 r = configure_dispc();
1112 if (r == 1)
1113 goto end;
1114
1115 /* re-read busy flags */
1116 mgr_busy[0] = dispc_go_busy(0);
1117 mgr_busy[1] = dispc_go_busy(1);
1118
1119 /* keep running as long as there are busy managers, so that
1120 * we can collect overlay-applied information */
1121 for (i = 0; i < num_mgrs; ++i) {
1122 if (mgr_busy[i])
1123 goto end;
1124 }
1125
1126 omap_dispc_unregister_isr(dss_apply_irq_handler, NULL,
1127 DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD |
1128 DISPC_IRQ_EVSYNC_EVEN);
1129 dss_cache.irq_enabled = false;
1130
1131end:
1132 spin_unlock(&dss_cache.lock);
1133}
1134
1135static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
1136{
1137 struct overlay_cache_data *oc;
1138 struct manager_cache_data *mc;
1139 int i;
1140 struct omap_overlay *ovl;
1141 int num_planes_enabled = 0;
1142 bool use_fifomerge;
1143 unsigned long flags;
1144 int r;
1145
1146 DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
1147
1148 spin_lock_irqsave(&dss_cache.lock, flags);
1149
1150 /* Configure overlays */
1151 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
1152 struct omap_dss_device *dssdev;
1153
1154 ovl = omap_dss_get_overlay(i);
1155
1156 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
1157 continue;
1158
1159 oc = &dss_cache.overlay_cache[ovl->id];
1160
1161 if (!overlay_enabled(ovl)) {
1162 if (oc->enabled) {
1163 oc->enabled = false;
1164 oc->dirty = true;
1165 }
1166 continue;
1167 }
1168
1169 if (!ovl->info_dirty) {
1170 if (oc->enabled)
1171 ++num_planes_enabled;
1172 continue;
1173 }
1174
1175 dssdev = ovl->manager->device;
1176
1177 if (dss_check_overlay(ovl, dssdev)) {
1178 if (oc->enabled) {
1179 oc->enabled = false;
1180 oc->dirty = true;
1181 }
1182 continue;
1183 }
1184
1185 ovl->info_dirty = false;
1186 oc->dirty = true;
1187
1188 oc->paddr = ovl->info.paddr;
1189 oc->vaddr = ovl->info.vaddr;
1190 oc->screen_width = ovl->info.screen_width;
1191 oc->width = ovl->info.width;
1192 oc->height = ovl->info.height;
1193 oc->color_mode = ovl->info.color_mode;
1194 oc->rotation = ovl->info.rotation;
1195 oc->rotation_type = ovl->info.rotation_type;
1196 oc->mirror = ovl->info.mirror;
1197 oc->pos_x = ovl->info.pos_x;
1198 oc->pos_y = ovl->info.pos_y;
1199 oc->out_width = ovl->info.out_width;
1200 oc->out_height = ovl->info.out_height;
1201 oc->global_alpha = ovl->info.global_alpha;
1202
1203 oc->replication =
1204 dss_use_replication(dssdev, ovl->info.color_mode);
1205
1206 oc->ilace = dssdev->type == OMAP_DISPLAY_TYPE_VENC;
1207
1208 oc->channel = ovl->manager->id;
1209
1210 oc->enabled = true;
1211
1212 oc->manual_update =
1213 dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
1214 dssdev->driver->get_update_mode(dssdev) !=
1215 OMAP_DSS_UPDATE_AUTO;
1216
1217 ++num_planes_enabled;
1218 }
1219
1220 /* Configure managers */
1221 list_for_each_entry(mgr, &manager_list, list) {
1222 struct omap_dss_device *dssdev;
1223
1224 if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC))
1225 continue;
1226
1227 mc = &dss_cache.manager_cache[mgr->id];
1228
1229 if (mgr->device_changed) {
1230 mgr->device_changed = false;
1231 mgr->info_dirty = true;
1232 }
1233
1234 if (!mgr->info_dirty)
1235 continue;
1236
1237 if (!mgr->device)
1238 continue;
1239
1240 dssdev = mgr->device;
1241
1242 mgr->info_dirty = false;
1243 mc->dirty = true;
1244
1245 mc->default_color = mgr->info.default_color;
1246 mc->trans_key_type = mgr->info.trans_key_type;
1247 mc->trans_key = mgr->info.trans_key;
1248 mc->trans_enabled = mgr->info.trans_enabled;
1249 mc->alpha_enabled = mgr->info.alpha_enabled;
1250
1251 mc->manual_upd_display =
1252 dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
1253
1254 mc->manual_update =
1255 dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
1256 dssdev->driver->get_update_mode(dssdev) !=
1257 OMAP_DSS_UPDATE_AUTO;
1258 }
1259
1260 /* XXX TODO: Try to get fifomerge working. The problem is that it
1261 * affects both managers, not individually but at the same time. This
1262 * means the change has to be well synchronized. I guess the proper way
1263 * is to have a two step process for fifo merge:
1264 * fifomerge enable:
1265 * 1. disable other planes, leaving one plane enabled
1266 * 2. wait until the planes are disabled on HW
1267 * 3. config merged fifo thresholds, enable fifomerge
1268 * fifomerge disable:
1269 * 1. config unmerged fifo thresholds, disable fifomerge
1270 * 2. wait until fifo changes are in HW
1271 * 3. enable planes
1272 */
1273 use_fifomerge = false;
1274
1275 /* Configure overlay fifos */
1276 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
1277 struct omap_dss_device *dssdev;
1278 u32 size;
1279
1280 ovl = omap_dss_get_overlay(i);
1281
1282 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
1283 continue;
1284
1285 oc = &dss_cache.overlay_cache[ovl->id];
1286
1287 if (!oc->enabled)
1288 continue;
1289
1290 dssdev = ovl->manager->device;
1291
1292 size = dispc_get_plane_fifo_size(ovl->id);
1293 if (use_fifomerge)
1294 size *= 3;
1295
1296 switch (dssdev->type) {
1297 case OMAP_DISPLAY_TYPE_DPI:
1298 case OMAP_DISPLAY_TYPE_DBI:
1299 case OMAP_DISPLAY_TYPE_SDI:
1300 case OMAP_DISPLAY_TYPE_VENC:
1301 default_get_overlay_fifo_thresholds(ovl->id, size,
1302 &oc->burst_size, &oc->fifo_low,
1303 &oc->fifo_high);
1304 break;
1305#ifdef CONFIG_OMAP2_DSS_DSI
1306 case OMAP_DISPLAY_TYPE_DSI:
1307 dsi_get_overlay_fifo_thresholds(ovl->id, size,
1308 &oc->burst_size, &oc->fifo_low,
1309 &oc->fifo_high);
1310 break;
1311#endif
1312 default:
1313 BUG();
1314 }
1315 }
1316
1317 r = 0;
1318 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
1319 if (!dss_cache.irq_enabled) {
1320 r = omap_dispc_register_isr(dss_apply_irq_handler, NULL,
1321 DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD |
1322 DISPC_IRQ_EVSYNC_EVEN);
1323 dss_cache.irq_enabled = true;
1324 }
1325 configure_dispc();
1326 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
1327
1328 spin_unlock_irqrestore(&dss_cache.lock, flags);
1329
1330 return r;
1331}
1332
1333static int dss_check_manager(struct omap_overlay_manager *mgr)
1334{
1335 /* OMAP supports only graphics source transparency color key and alpha
1336 * blending simultaneously. See TRM 15.4.2.4.2.2 Alpha Mode */
1337
1338 if (mgr->info.alpha_enabled && mgr->info.trans_enabled &&
1339 mgr->info.trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST)
1340 return -EINVAL;
1341
1342 return 0;
1343}
1344
1345static int omap_dss_mgr_set_info(struct omap_overlay_manager *mgr,
1346 struct omap_overlay_manager_info *info)
1347{
1348 int r;
1349 struct omap_overlay_manager_info old_info;
1350
1351 old_info = mgr->info;
1352 mgr->info = *info;
1353
1354 r = dss_check_manager(mgr);
1355 if (r) {
1356 mgr->info = old_info;
1357 return r;
1358 }
1359
1360 mgr->info_dirty = true;
1361
1362 return 0;
1363}
1364
1365static void omap_dss_mgr_get_info(struct omap_overlay_manager *mgr,
1366 struct omap_overlay_manager_info *info)
1367{
1368 *info = mgr->info;
1369}
1370
1371static int dss_mgr_enable(struct omap_overlay_manager *mgr)
1372{
1373 dispc_enable_channel(mgr->id, 1);
1374 return 0;
1375}
1376
1377static int dss_mgr_disable(struct omap_overlay_manager *mgr)
1378{
1379 dispc_enable_channel(mgr->id, 0);
1380 return 0;
1381}
1382
1383static void omap_dss_add_overlay_manager(struct omap_overlay_manager *manager)
1384{
1385 ++num_managers;
1386 list_add_tail(&manager->list, &manager_list);
1387}
1388
1389int dss_init_overlay_managers(struct platform_device *pdev)
1390{
1391 int i, r;
1392
1393 spin_lock_init(&dss_cache.lock);
1394
1395 INIT_LIST_HEAD(&manager_list);
1396
1397 num_managers = 0;
1398
1399 for (i = 0; i < 2; ++i) {
1400 struct omap_overlay_manager *mgr;
1401 mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
1402
1403 BUG_ON(mgr == NULL);
1404
1405 switch (i) {
1406 case 0:
1407 mgr->name = "lcd";
1408 mgr->id = OMAP_DSS_CHANNEL_LCD;
1409 mgr->supported_displays =
1410 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
1411 OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI;
1412 break;
1413 case 1:
1414 mgr->name = "tv";
1415 mgr->id = OMAP_DSS_CHANNEL_DIGIT;
1416 mgr->supported_displays = OMAP_DISPLAY_TYPE_VENC;
1417 break;
1418 }
1419
1420 mgr->set_device = &omap_dss_set_device;
1421 mgr->unset_device = &omap_dss_unset_device;
1422 mgr->apply = &omap_dss_mgr_apply;
1423 mgr->set_manager_info = &omap_dss_mgr_set_info;
1424 mgr->get_manager_info = &omap_dss_mgr_get_info;
1425 mgr->wait_for_go = &dss_mgr_wait_for_go;
1426 mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
1427
1428 mgr->enable = &dss_mgr_enable;
1429 mgr->disable = &dss_mgr_disable;
1430
1431 mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC;
1432
1433 dss_overlay_setup_dispc_manager(mgr);
1434
1435 omap_dss_add_overlay_manager(mgr);
1436
1437 r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
1438 &pdev->dev.kobj, "manager%d", i);
1439
1440 if (r) {
1441 DSSERR("failed to create sysfs file\n");
1442 continue;
1443 }
1444 }
1445
1446#ifdef L4_EXAMPLE
1447 {
1448 int omap_dss_mgr_apply_l4(struct omap_overlay_manager *mgr)
1449 {
1450 DSSDBG("omap_dss_mgr_apply_l4(%s)\n", mgr->name);
1451
1452 return 0;
1453 }
1454
1455 struct omap_overlay_manager *mgr;
1456 mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
1457
1458 BUG_ON(mgr == NULL);
1459
1460 mgr->name = "l4";
1461 mgr->supported_displays =
1462 OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI;
1463
1464 mgr->set_device = &omap_dss_set_device;
1465 mgr->unset_device = &omap_dss_unset_device;
1466 mgr->apply = &omap_dss_mgr_apply_l4;
1467 mgr->set_manager_info = &omap_dss_mgr_set_info;
1468 mgr->get_manager_info = &omap_dss_mgr_get_info;
1469
1470 dss_overlay_setup_l4_manager(mgr);
1471
1472 omap_dss_add_overlay_manager(mgr);
1473
1474 r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
1475 &pdev->dev.kobj, "managerl4");
1476
1477 if (r)
1478 DSSERR("failed to create sysfs file\n");
1479 }
1480#endif
1481
1482 return 0;
1483}
1484
1485void dss_uninit_overlay_managers(struct platform_device *pdev)
1486{
1487 struct omap_overlay_manager *mgr;
1488
1489 while (!list_empty(&manager_list)) {
1490 mgr = list_first_entry(&manager_list,
1491 struct omap_overlay_manager, list);
1492 list_del(&mgr->list);
1493 kobject_del(&mgr->kobj);
1494 kobject_put(&mgr->kobj);
1495 kfree(mgr);
1496 }
1497
1498 num_managers = 0;
1499}
1500
1501int omap_dss_get_num_overlay_managers(void)
1502{
1503 return num_managers;
1504}
1505EXPORT_SYMBOL(omap_dss_get_num_overlay_managers);
1506
1507struct omap_overlay_manager *omap_dss_get_overlay_manager(int num)
1508{
1509 int i = 0;
1510 struct omap_overlay_manager *mgr;
1511
1512 list_for_each_entry(mgr, &manager_list, list) {
1513 if (i++ == num)
1514 return mgr;
1515 }
1516
1517 return NULL;
1518}
1519EXPORT_SYMBOL(omap_dss_get_overlay_manager);
1520
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
new file mode 100644
index 000000000000..82336583adef
--- /dev/null
+++ b/drivers/video/omap2/dss/overlay.c
@@ -0,0 +1,681 @@
1/*
2 * linux/drivers/video/omap2/dss/overlay.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#define DSS_SUBSYS_NAME "OVERLAY"
24
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/err.h>
28#include <linux/sysfs.h>
29#include <linux/kobject.h>
30#include <linux/platform_device.h>
31#include <linux/delay.h>
32#include <linux/slab.h>
33
34#include <plat/display.h>
35#include <plat/cpu.h>
36
37#include "dss.h"
38
39static int num_overlays;
40static struct list_head overlay_list;
41
42static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
43{
44 return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
45}
46
47static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
48{
49 return snprintf(buf, PAGE_SIZE, "%s\n",
50 ovl->manager ? ovl->manager->name : "<none>");
51}
52
53static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
54 size_t size)
55{
56 int i, r;
57 struct omap_overlay_manager *mgr = NULL;
58 struct omap_overlay_manager *old_mgr;
59 int len = size;
60
61 if (buf[size-1] == '\n')
62 --len;
63
64 if (len > 0) {
65 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
66 mgr = omap_dss_get_overlay_manager(i);
67
68 if (strncmp(buf, mgr->name, len) == 0)
69 break;
70
71 mgr = NULL;
72 }
73 }
74
75 if (len > 0 && mgr == NULL)
76 return -EINVAL;
77
78 if (mgr)
79 DSSDBG("manager %s found\n", mgr->name);
80
81 if (mgr == ovl->manager)
82 return size;
83
84 old_mgr = ovl->manager;
85
86 /* detach old manager */
87 if (old_mgr) {
88 r = ovl->unset_manager(ovl);
89 if (r) {
90 DSSERR("detach failed\n");
91 return r;
92 }
93
94 r = old_mgr->apply(old_mgr);
95 if (r)
96 return r;
97 }
98
99 if (mgr) {
100 r = ovl->set_manager(ovl, mgr);
101 if (r) {
102 DSSERR("Failed to attach overlay\n");
103 return r;
104 }
105
106 r = mgr->apply(mgr);
107 if (r)
108 return r;
109 }
110
111 return size;
112}
113
114static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
115{
116 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
117 ovl->info.width, ovl->info.height);
118}
119
120static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
121{
122 return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.screen_width);
123}
124
125static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
126{
127 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
128 ovl->info.pos_x, ovl->info.pos_y);
129}
130
131static ssize_t overlay_position_store(struct omap_overlay *ovl,
132 const char *buf, size_t size)
133{
134 int r;
135 char *last;
136 struct omap_overlay_info info;
137
138 ovl->get_overlay_info(ovl, &info);
139
140 info.pos_x = simple_strtoul(buf, &last, 10);
141 ++last;
142 if (last - buf >= size)
143 return -EINVAL;
144
145 info.pos_y = simple_strtoul(last, &last, 10);
146
147 r = ovl->set_overlay_info(ovl, &info);
148 if (r)
149 return r;
150
151 if (ovl->manager) {
152 r = ovl->manager->apply(ovl->manager);
153 if (r)
154 return r;
155 }
156
157 return size;
158}
159
160static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
161{
162 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
163 ovl->info.out_width, ovl->info.out_height);
164}
165
166static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
167 const char *buf, size_t size)
168{
169 int r;
170 char *last;
171 struct omap_overlay_info info;
172
173 ovl->get_overlay_info(ovl, &info);
174
175 info.out_width = simple_strtoul(buf, &last, 10);
176 ++last;
177 if (last - buf >= size)
178 return -EINVAL;
179
180 info.out_height = simple_strtoul(last, &last, 10);
181
182 r = ovl->set_overlay_info(ovl, &info);
183 if (r)
184 return r;
185
186 if (ovl->manager) {
187 r = ovl->manager->apply(ovl->manager);
188 if (r)
189 return r;
190 }
191
192 return size;
193}
194
195static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
196{
197 return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.enabled);
198}
199
200static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
201 size_t size)
202{
203 int r;
204 struct omap_overlay_info info;
205
206 ovl->get_overlay_info(ovl, &info);
207
208 info.enabled = simple_strtoul(buf, NULL, 10);
209
210 r = ovl->set_overlay_info(ovl, &info);
211 if (r)
212 return r;
213
214 if (ovl->manager) {
215 r = ovl->manager->apply(ovl->manager);
216 if (r)
217 return r;
218 }
219
220 return size;
221}
222
223static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
224{
225 return snprintf(buf, PAGE_SIZE, "%d\n",
226 ovl->info.global_alpha);
227}
228
229static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
230 const char *buf, size_t size)
231{
232 int r;
233 struct omap_overlay_info info;
234
235 ovl->get_overlay_info(ovl, &info);
236
237 /* Video1 plane does not support global alpha
238 * to always make it 255 completely opaque
239 */
240 if (ovl->id == OMAP_DSS_VIDEO1)
241 info.global_alpha = 255;
242 else
243 info.global_alpha = simple_strtoul(buf, NULL, 10);
244
245 r = ovl->set_overlay_info(ovl, &info);
246 if (r)
247 return r;
248
249 if (ovl->manager) {
250 r = ovl->manager->apply(ovl->manager);
251 if (r)
252 return r;
253 }
254
255 return size;
256}
257
258struct overlay_attribute {
259 struct attribute attr;
260 ssize_t (*show)(struct omap_overlay *, char *);
261 ssize_t (*store)(struct omap_overlay *, const char *, size_t);
262};
263
264#define OVERLAY_ATTR(_name, _mode, _show, _store) \
265 struct overlay_attribute overlay_attr_##_name = \
266 __ATTR(_name, _mode, _show, _store)
267
268static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
269static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
270 overlay_manager_show, overlay_manager_store);
271static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
272static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
273static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
274 overlay_position_show, overlay_position_store);
275static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
276 overlay_output_size_show, overlay_output_size_store);
277static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
278 overlay_enabled_show, overlay_enabled_store);
279static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
280 overlay_global_alpha_show, overlay_global_alpha_store);
281
282static struct attribute *overlay_sysfs_attrs[] = {
283 &overlay_attr_name.attr,
284 &overlay_attr_manager.attr,
285 &overlay_attr_input_size.attr,
286 &overlay_attr_screen_width.attr,
287 &overlay_attr_position.attr,
288 &overlay_attr_output_size.attr,
289 &overlay_attr_enabled.attr,
290 &overlay_attr_global_alpha.attr,
291 NULL
292};
293
294static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
295 char *buf)
296{
297 struct omap_overlay *overlay;
298 struct overlay_attribute *overlay_attr;
299
300 overlay = container_of(kobj, struct omap_overlay, kobj);
301 overlay_attr = container_of(attr, struct overlay_attribute, attr);
302
303 if (!overlay_attr->show)
304 return -ENOENT;
305
306 return overlay_attr->show(overlay, buf);
307}
308
309static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
310 const char *buf, size_t size)
311{
312 struct omap_overlay *overlay;
313 struct overlay_attribute *overlay_attr;
314
315 overlay = container_of(kobj, struct omap_overlay, kobj);
316 overlay_attr = container_of(attr, struct overlay_attribute, attr);
317
318 if (!overlay_attr->store)
319 return -ENOENT;
320
321 return overlay_attr->store(overlay, buf, size);
322}
323
324static const struct sysfs_ops overlay_sysfs_ops = {
325 .show = overlay_attr_show,
326 .store = overlay_attr_store,
327};
328
329static struct kobj_type overlay_ktype = {
330 .sysfs_ops = &overlay_sysfs_ops,
331 .default_attrs = overlay_sysfs_attrs,
332};
333
334/* Check if overlay parameters are compatible with display */
335int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev)
336{
337 struct omap_overlay_info *info;
338 u16 outw, outh;
339 u16 dw, dh;
340
341 if (!dssdev)
342 return 0;
343
344 if (!ovl->info.enabled)
345 return 0;
346
347 info = &ovl->info;
348
349 if (info->paddr == 0) {
350 DSSDBG("check_overlay failed: paddr 0\n");
351 return -EINVAL;
352 }
353
354 dssdev->driver->get_resolution(dssdev, &dw, &dh);
355
356 DSSDBG("check_overlay %d: (%d,%d %dx%d -> %dx%d) disp (%dx%d)\n",
357 ovl->id,
358 info->pos_x, info->pos_y,
359 info->width, info->height,
360 info->out_width, info->out_height,
361 dw, dh);
362
363 if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
364 outw = info->width;
365 outh = info->height;
366 } else {
367 if (info->out_width == 0)
368 outw = info->width;
369 else
370 outw = info->out_width;
371
372 if (info->out_height == 0)
373 outh = info->height;
374 else
375 outh = info->out_height;
376 }
377
378 if (dw < info->pos_x + outw) {
379 DSSDBG("check_overlay failed 1: %d < %d + %d\n",
380 dw, info->pos_x, outw);
381 return -EINVAL;
382 }
383
384 if (dh < info->pos_y + outh) {
385 DSSDBG("check_overlay failed 2: %d < %d + %d\n",
386 dh, info->pos_y, outh);
387 return -EINVAL;
388 }
389
390 if ((ovl->supported_modes & info->color_mode) == 0) {
391 DSSERR("overlay doesn't support mode %d\n", info->color_mode);
392 return -EINVAL;
393 }
394
395 return 0;
396}
397
398static int dss_ovl_set_overlay_info(struct omap_overlay *ovl,
399 struct omap_overlay_info *info)
400{
401 int r;
402 struct omap_overlay_info old_info;
403
404 old_info = ovl->info;
405 ovl->info = *info;
406
407 if (ovl->manager) {
408 r = dss_check_overlay(ovl, ovl->manager->device);
409 if (r) {
410 ovl->info = old_info;
411 return r;
412 }
413 }
414
415 ovl->info_dirty = true;
416
417 return 0;
418}
419
420static void dss_ovl_get_overlay_info(struct omap_overlay *ovl,
421 struct omap_overlay_info *info)
422{
423 *info = ovl->info;
424}
425
426static int dss_ovl_wait_for_go(struct omap_overlay *ovl)
427{
428 return dss_mgr_wait_for_go_ovl(ovl);
429}
430
431static int omap_dss_set_manager(struct omap_overlay *ovl,
432 struct omap_overlay_manager *mgr)
433{
434 if (!mgr)
435 return -EINVAL;
436
437 if (ovl->manager) {
438 DSSERR("overlay '%s' already has a manager '%s'\n",
439 ovl->name, ovl->manager->name);
440 return -EINVAL;
441 }
442
443 if (ovl->info.enabled) {
444 DSSERR("overlay has to be disabled to change the manager\n");
445 return -EINVAL;
446 }
447
448 ovl->manager = mgr;
449
450 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
451 /* XXX: on manual update display, in auto update mode, a bug happens
452 * here. When an overlay is first enabled on LCD, then it's disabled,
453 * and the manager is changed to TV, we sometimes get SYNC_LOST_DIGIT
454 * errors. Waiting before changing the channel_out fixes it. I'm
455 * guessing that the overlay is still somehow being used for the LCD,
456 * but I don't understand how or why. */
457 msleep(40);
458 dispc_set_channel_out(ovl->id, mgr->id);
459 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
460
461 return 0;
462}
463
464static int omap_dss_unset_manager(struct omap_overlay *ovl)
465{
466 int r;
467
468 if (!ovl->manager) {
469 DSSERR("failed to detach overlay: manager not set\n");
470 return -EINVAL;
471 }
472
473 if (ovl->info.enabled) {
474 DSSERR("overlay has to be disabled to unset the manager\n");
475 return -EINVAL;
476 }
477
478 r = ovl->wait_for_go(ovl);
479 if (r)
480 return r;
481
482 ovl->manager = NULL;
483
484 return 0;
485}
486
487int omap_dss_get_num_overlays(void)
488{
489 return num_overlays;
490}
491EXPORT_SYMBOL(omap_dss_get_num_overlays);
492
493struct omap_overlay *omap_dss_get_overlay(int num)
494{
495 int i = 0;
496 struct omap_overlay *ovl;
497
498 list_for_each_entry(ovl, &overlay_list, list) {
499 if (i++ == num)
500 return ovl;
501 }
502
503 return NULL;
504}
505EXPORT_SYMBOL(omap_dss_get_overlay);
506
507static void omap_dss_add_overlay(struct omap_overlay *overlay)
508{
509 ++num_overlays;
510 list_add_tail(&overlay->list, &overlay_list);
511}
512
513static struct omap_overlay *dispc_overlays[3];
514
515void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr)
516{
517 mgr->num_overlays = 3;
518 mgr->overlays = dispc_overlays;
519}
520
521#ifdef L4_EXAMPLE
522static struct omap_overlay *l4_overlays[1];
523void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr)
524{
525 mgr->num_overlays = 1;
526 mgr->overlays = l4_overlays;
527}
528#endif
529
530void dss_init_overlays(struct platform_device *pdev)
531{
532 int i, r;
533
534 INIT_LIST_HEAD(&overlay_list);
535
536 num_overlays = 0;
537
538 for (i = 0; i < 3; ++i) {
539 struct omap_overlay *ovl;
540 ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
541
542 BUG_ON(ovl == NULL);
543
544 switch (i) {
545 case 0:
546 ovl->name = "gfx";
547 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;
552 ovl->info.global_alpha = 255;
553 break;
554 case 1:
555 ovl->name = "vid1";
556 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 |
561 OMAP_DSS_OVL_CAP_DISPC;
562 ovl->info.global_alpha = 255;
563 break;
564 case 2:
565 ovl->name = "vid2";
566 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 |
571 OMAP_DSS_OVL_CAP_DISPC;
572 ovl->info.global_alpha = 255;
573 break;
574 }
575
576 ovl->set_manager = &omap_dss_set_manager;
577 ovl->unset_manager = &omap_dss_unset_manager;
578 ovl->set_overlay_info = &dss_ovl_set_overlay_info;
579 ovl->get_overlay_info = &dss_ovl_get_overlay_info;
580 ovl->wait_for_go = &dss_ovl_wait_for_go;
581
582 omap_dss_add_overlay(ovl);
583
584 r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
585 &pdev->dev.kobj, "overlay%d", i);
586
587 if (r) {
588 DSSERR("failed to create sysfs file\n");
589 continue;
590 }
591
592 dispc_overlays[i] = ovl;
593 }
594
595#ifdef L4_EXAMPLE
596 {
597 struct omap_overlay *ovl;
598 ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
599
600 BUG_ON(ovl == NULL);
601
602 ovl->name = "l4";
603 ovl->supported_modes = OMAP_DSS_COLOR_RGB24U;
604
605 ovl->set_manager = &omap_dss_set_manager;
606 ovl->unset_manager = &omap_dss_unset_manager;
607 ovl->set_overlay_info = &dss_ovl_set_overlay_info;
608 ovl->get_overlay_info = &dss_ovl_get_overlay_info;
609
610 omap_dss_add_overlay(ovl);
611
612 r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
613 &pdev->dev.kobj, "overlayl4");
614
615 if (r)
616 DSSERR("failed to create sysfs file\n");
617
618 l4_overlays[0] = ovl;
619 }
620#endif
621}
622
623/* connect overlays to the new device, if not already connected. if force
624 * selected, connect always. */
625void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
626{
627 int i;
628 struct omap_overlay_manager *lcd_mgr;
629 struct omap_overlay_manager *tv_mgr;
630 struct omap_overlay_manager *mgr = NULL;
631
632 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);
634
635 if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) {
636 if (!lcd_mgr->device || force) {
637 if (lcd_mgr->device)
638 lcd_mgr->unset_device(lcd_mgr);
639 lcd_mgr->set_device(lcd_mgr, dssdev);
640 mgr = lcd_mgr;
641 }
642 }
643
644 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
645 if (!tv_mgr->device || force) {
646 if (tv_mgr->device)
647 tv_mgr->unset_device(tv_mgr);
648 tv_mgr->set_device(tv_mgr, dssdev);
649 mgr = tv_mgr;
650 }
651 }
652
653 if (mgr) {
654 for (i = 0; i < 3; i++) {
655 struct omap_overlay *ovl;
656 ovl = omap_dss_get_overlay(i);
657 if (!ovl->manager || force) {
658 if (ovl->manager)
659 omap_dss_unset_manager(ovl);
660 omap_dss_set_manager(ovl, mgr);
661 }
662 }
663 }
664}
665
666void dss_uninit_overlays(struct platform_device *pdev)
667{
668 struct omap_overlay *ovl;
669
670 while (!list_empty(&overlay_list)) {
671 ovl = list_first_entry(&overlay_list,
672 struct omap_overlay, list);
673 list_del(&ovl->list);
674 kobject_del(&ovl->kobj);
675 kobject_put(&ovl->kobj);
676 kfree(ovl);
677 }
678
679 num_overlays = 0;
680}
681
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
new file mode 100644
index 000000000000..cc23f53cc62d
--- /dev/null
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -0,0 +1,1056 @@
1/*
2 * linux/drivers/video/omap2/dss/rfbi.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#define DSS_SUBSYS_NAME "RFBI"
24
25#include <linux/kernel.h>
26#include <linux/dma-mapping.h>
27#include <linux/vmalloc.h>
28#include <linux/clk.h>
29#include <linux/io.h>
30#include <linux/delay.h>
31#include <linux/kfifo.h>
32#include <linux/ktime.h>
33#include <linux/hrtimer.h>
34#include <linux/seq_file.h>
35
36#include <plat/display.h>
37#include "dss.h"
38
39#define RFBI_BASE 0x48050800
40
41struct rfbi_reg { u16 idx; };
42
43#define RFBI_REG(idx) ((const struct rfbi_reg) { idx })
44
45#define RFBI_REVISION RFBI_REG(0x0000)
46#define RFBI_SYSCONFIG RFBI_REG(0x0010)
47#define RFBI_SYSSTATUS RFBI_REG(0x0014)
48#define RFBI_CONTROL RFBI_REG(0x0040)
49#define RFBI_PIXEL_CNT RFBI_REG(0x0044)
50#define RFBI_LINE_NUMBER RFBI_REG(0x0048)
51#define RFBI_CMD RFBI_REG(0x004c)
52#define RFBI_PARAM RFBI_REG(0x0050)
53#define RFBI_DATA RFBI_REG(0x0054)
54#define RFBI_READ RFBI_REG(0x0058)
55#define RFBI_STATUS RFBI_REG(0x005c)
56
57#define RFBI_CONFIG(n) RFBI_REG(0x0060 + (n)*0x18)
58#define RFBI_ONOFF_TIME(n) RFBI_REG(0x0064 + (n)*0x18)
59#define RFBI_CYCLE_TIME(n) RFBI_REG(0x0068 + (n)*0x18)
60#define RFBI_DATA_CYCLE1(n) RFBI_REG(0x006c + (n)*0x18)
61#define RFBI_DATA_CYCLE2(n) RFBI_REG(0x0070 + (n)*0x18)
62#define RFBI_DATA_CYCLE3(n) RFBI_REG(0x0074 + (n)*0x18)
63
64#define RFBI_VSYNC_WIDTH RFBI_REG(0x0090)
65#define RFBI_HSYNC_WIDTH RFBI_REG(0x0094)
66
67#define REG_FLD_MOD(idx, val, start, end) \
68 rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end))
69
70/* To work around an RFBI transfer rate limitation */
71#define OMAP_RFBI_RATE_LIMIT 1
72
73enum omap_rfbi_cycleformat {
74 OMAP_DSS_RFBI_CYCLEFORMAT_1_1 = 0,
75 OMAP_DSS_RFBI_CYCLEFORMAT_2_1 = 1,
76 OMAP_DSS_RFBI_CYCLEFORMAT_3_1 = 2,
77 OMAP_DSS_RFBI_CYCLEFORMAT_3_2 = 3,
78};
79
80enum omap_rfbi_datatype {
81 OMAP_DSS_RFBI_DATATYPE_12 = 0,
82 OMAP_DSS_RFBI_DATATYPE_16 = 1,
83 OMAP_DSS_RFBI_DATATYPE_18 = 2,
84 OMAP_DSS_RFBI_DATATYPE_24 = 3,
85};
86
87enum omap_rfbi_parallelmode {
88 OMAP_DSS_RFBI_PARALLELMODE_8 = 0,
89 OMAP_DSS_RFBI_PARALLELMODE_9 = 1,
90 OMAP_DSS_RFBI_PARALLELMODE_12 = 2,
91 OMAP_DSS_RFBI_PARALLELMODE_16 = 3,
92};
93
94enum update_cmd {
95 RFBI_CMD_UPDATE = 0,
96 RFBI_CMD_SYNC = 1,
97};
98
99static int rfbi_convert_timings(struct rfbi_timings *t);
100static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div);
101
102static struct {
103 void __iomem *base;
104
105 unsigned long l4_khz;
106
107 enum omap_rfbi_datatype datatype;
108 enum omap_rfbi_parallelmode parallelmode;
109
110 enum omap_rfbi_te_mode te_mode;
111 int te_enabled;
112
113 void (*framedone_callback)(void *data);
114 void *framedone_callback_data;
115
116 struct omap_dss_device *dssdev[2];
117
118 struct kfifo cmd_fifo;
119 spinlock_t cmd_lock;
120 struct completion cmd_done;
121 atomic_t cmd_fifo_full;
122 atomic_t cmd_pending;
123} rfbi;
124
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)
133{
134 __raw_writel(val, rfbi.base + idx.idx);
135}
136
137static inline u32 rfbi_read_reg(const struct rfbi_reg idx)
138{
139 return __raw_readl(rfbi.base + idx.idx);
140}
141
142static void rfbi_enable_clocks(bool enable)
143{
144 if (enable)
145 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
146 else
147 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
148}
149
150void omap_rfbi_write_command(const void *buf, u32 len)
151{
152 rfbi_enable_clocks(1);
153 switch (rfbi.parallelmode) {
154 case OMAP_DSS_RFBI_PARALLELMODE_8:
155 {
156 const u8 *b = buf;
157 for (; len; len--)
158 rfbi_write_reg(RFBI_CMD, *b++);
159 break;
160 }
161
162 case OMAP_DSS_RFBI_PARALLELMODE_16:
163 {
164 const u16 *w = buf;
165 BUG_ON(len & 1);
166 for (; len; len -= 2)
167 rfbi_write_reg(RFBI_CMD, *w++);
168 break;
169 }
170
171 case OMAP_DSS_RFBI_PARALLELMODE_9:
172 case OMAP_DSS_RFBI_PARALLELMODE_12:
173 default:
174 BUG();
175 }
176 rfbi_enable_clocks(0);
177}
178EXPORT_SYMBOL(omap_rfbi_write_command);
179
180void omap_rfbi_read_data(void *buf, u32 len)
181{
182 rfbi_enable_clocks(1);
183 switch (rfbi.parallelmode) {
184 case OMAP_DSS_RFBI_PARALLELMODE_8:
185 {
186 u8 *b = buf;
187 for (; len; len--) {
188 rfbi_write_reg(RFBI_READ, 0);
189 *b++ = rfbi_read_reg(RFBI_READ);
190 }
191 break;
192 }
193
194 case OMAP_DSS_RFBI_PARALLELMODE_16:
195 {
196 u16 *w = buf;
197 BUG_ON(len & ~1);
198 for (; len; len -= 2) {
199 rfbi_write_reg(RFBI_READ, 0);
200 *w++ = rfbi_read_reg(RFBI_READ);
201 }
202 break;
203 }
204
205 case OMAP_DSS_RFBI_PARALLELMODE_9:
206 case OMAP_DSS_RFBI_PARALLELMODE_12:
207 default:
208 BUG();
209 }
210 rfbi_enable_clocks(0);
211}
212EXPORT_SYMBOL(omap_rfbi_read_data);
213
214void omap_rfbi_write_data(const void *buf, u32 len)
215{
216 rfbi_enable_clocks(1);
217 switch (rfbi.parallelmode) {
218 case OMAP_DSS_RFBI_PARALLELMODE_8:
219 {
220 const u8 *b = buf;
221 for (; len; len--)
222 rfbi_write_reg(RFBI_PARAM, *b++);
223 break;
224 }
225
226 case OMAP_DSS_RFBI_PARALLELMODE_16:
227 {
228 const u16 *w = buf;
229 BUG_ON(len & 1);
230 for (; len; len -= 2)
231 rfbi_write_reg(RFBI_PARAM, *w++);
232 break;
233 }
234
235 case OMAP_DSS_RFBI_PARALLELMODE_9:
236 case OMAP_DSS_RFBI_PARALLELMODE_12:
237 default:
238 BUG();
239
240 }
241 rfbi_enable_clocks(0);
242}
243EXPORT_SYMBOL(omap_rfbi_write_data);
244
245void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
246 u16 x, u16 y,
247 u16 w, u16 h)
248{
249 int start_offset = scr_width * y + x;
250 int horiz_offset = scr_width - w;
251 int i;
252
253 rfbi_enable_clocks(1);
254
255 if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
256 rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
257 const u16 __iomem *pd = buf;
258 pd += start_offset;
259
260 for (; h; --h) {
261 for (i = 0; i < w; ++i) {
262 const u8 __iomem *b = (const u8 __iomem *)pd;
263 rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1));
264 rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0));
265 ++pd;
266 }
267 pd += horiz_offset;
268 }
269 } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_24 &&
270 rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
271 const u32 __iomem *pd = buf;
272 pd += start_offset;
273
274 for (; h; --h) {
275 for (i = 0; i < w; ++i) {
276 const u8 __iomem *b = (const u8 __iomem *)pd;
277 rfbi_write_reg(RFBI_PARAM, __raw_readb(b+2));
278 rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1));
279 rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0));
280 ++pd;
281 }
282 pd += horiz_offset;
283 }
284 } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
285 rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_16) {
286 const u16 __iomem *pd = buf;
287 pd += start_offset;
288
289 for (; h; --h) {
290 for (i = 0; i < w; ++i) {
291 rfbi_write_reg(RFBI_PARAM, __raw_readw(pd));
292 ++pd;
293 }
294 pd += horiz_offset;
295 }
296 } else {
297 BUG();
298 }
299
300 rfbi_enable_clocks(0);
301}
302EXPORT_SYMBOL(omap_rfbi_write_pixels);
303
304void rfbi_transfer_area(u16 width, u16 height,
305 void (callback)(void *data), void *data)
306{
307 u32 l;
308
309 /*BUG_ON(callback == 0);*/
310 BUG_ON(rfbi.framedone_callback != NULL);
311
312 DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
313
314 dispc_set_lcd_size(width, height);
315
316 dispc_enable_channel(OMAP_DSS_CHANNEL_LCD, true);
317
318 rfbi.framedone_callback = callback;
319 rfbi.framedone_callback_data = data;
320
321 rfbi_enable_clocks(1);
322
323 rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
324
325 l = rfbi_read_reg(RFBI_CONTROL);
326 l = FLD_MOD(l, 1, 0, 0); /* enable */
327 if (!rfbi.te_enabled)
328 l = FLD_MOD(l, 1, 4, 4); /* ITE */
329
330 rfbi_write_reg(RFBI_CONTROL, l);
331}
332
333static void framedone_callback(void *data, u32 mask)
334{
335 void (*callback)(void *data);
336
337 DSSDBG("FRAMEDONE\n");
338
339 REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0);
340
341 rfbi_enable_clocks(0);
342
343 callback = rfbi.framedone_callback;
344 rfbi.framedone_callback = NULL;
345
346 if (callback != NULL)
347 callback(rfbi.framedone_callback_data);
348
349 atomic_set(&rfbi.cmd_pending, 0);
350}
351
352#if 1 /* VERBOSE */
353static void rfbi_print_timings(void)
354{
355 u32 l;
356 u32 time;
357
358 l = rfbi_read_reg(RFBI_CONFIG(0));
359 time = 1000000000 / rfbi.l4_khz;
360 if (l & (1 << 4))
361 time *= 2;
362
363 DSSDBG("Tick time %u ps\n", time);
364 l = rfbi_read_reg(RFBI_ONOFF_TIME(0));
365 DSSDBG("CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, "
366 "REONTIME %d, REOFFTIME %d\n",
367 l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f,
368 (l >> 20) & 0x0f, (l >> 24) & 0x3f);
369
370 l = rfbi_read_reg(RFBI_CYCLE_TIME(0));
371 DSSDBG("WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, "
372 "ACCESSTIME %d\n",
373 (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f,
374 (l >> 22) & 0x3f);
375}
376#else
377static void rfbi_print_timings(void) {}
378#endif
379
380
381
382
383static u32 extif_clk_period;
384
385static inline unsigned long round_to_extif_ticks(unsigned long ps, int div)
386{
387 int bus_tick = extif_clk_period * div;
388 return (ps + bus_tick - 1) / bus_tick * bus_tick;
389}
390
391static int calc_reg_timing(struct rfbi_timings *t, int div)
392{
393 t->clk_div = div;
394
395 t->cs_on_time = round_to_extif_ticks(t->cs_on_time, div);
396
397 t->we_on_time = round_to_extif_ticks(t->we_on_time, div);
398 t->we_off_time = round_to_extif_ticks(t->we_off_time, div);
399 t->we_cycle_time = round_to_extif_ticks(t->we_cycle_time, div);
400
401 t->re_on_time = round_to_extif_ticks(t->re_on_time, div);
402 t->re_off_time = round_to_extif_ticks(t->re_off_time, div);
403 t->re_cycle_time = round_to_extif_ticks(t->re_cycle_time, div);
404
405 t->access_time = round_to_extif_ticks(t->access_time, div);
406 t->cs_off_time = round_to_extif_ticks(t->cs_off_time, div);
407 t->cs_pulse_width = round_to_extif_ticks(t->cs_pulse_width, div);
408
409 DSSDBG("[reg]cson %d csoff %d reon %d reoff %d\n",
410 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
411 DSSDBG("[reg]weon %d weoff %d recyc %d wecyc %d\n",
412 t->we_on_time, t->we_off_time, t->re_cycle_time,
413 t->we_cycle_time);
414 DSSDBG("[reg]rdaccess %d cspulse %d\n",
415 t->access_time, t->cs_pulse_width);
416
417 return rfbi_convert_timings(t);
418}
419
420static int calc_extif_timings(struct rfbi_timings *t)
421{
422 u32 max_clk_div;
423 int div;
424
425 rfbi_get_clk_info(&extif_clk_period, &max_clk_div);
426 for (div = 1; div <= max_clk_div; div++) {
427 if (calc_reg_timing(t, div) == 0)
428 break;
429 }
430
431 if (div <= max_clk_div)
432 return 0;
433
434 DSSERR("can't setup timings\n");
435 return -1;
436}
437
438
439void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t)
440{
441 int r;
442
443 if (!t->converted) {
444 r = calc_extif_timings(t);
445 if (r < 0)
446 DSSERR("Failed to calc timings\n");
447 }
448
449 BUG_ON(!t->converted);
450
451 rfbi_enable_clocks(1);
452 rfbi_write_reg(RFBI_ONOFF_TIME(rfbi_module), t->tim[0]);
453 rfbi_write_reg(RFBI_CYCLE_TIME(rfbi_module), t->tim[1]);
454
455 /* TIMEGRANULARITY */
456 REG_FLD_MOD(RFBI_CONFIG(rfbi_module),
457 (t->tim[2] ? 1 : 0), 4, 4);
458
459 rfbi_print_timings();
460 rfbi_enable_clocks(0);
461}
462
463static int ps_to_rfbi_ticks(int time, int div)
464{
465 unsigned long tick_ps;
466 int ret;
467
468 /* Calculate in picosecs to yield more exact results */
469 tick_ps = 1000000000 / (rfbi.l4_khz) * div;
470
471 ret = (time + tick_ps - 1) / tick_ps;
472
473 return ret;
474}
475
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)
530{
531 *clk_period = 1000000000 / rfbi.l4_khz;
532 *max_clk_div = 2;
533}
534
535static int rfbi_convert_timings(struct rfbi_timings *t)
536{
537 u32 l;
538 int reon, reoff, weon, weoff, cson, csoff, cs_pulse;
539 int actim, recyc, wecyc;
540 int div = t->clk_div;
541
542 if (div <= 0 || div > 2)
543 return -1;
544
545 /* Make sure that after conversion it still holds that:
546 * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff,
547 * csoff > cson, csoff >= max(weoff, reoff), actim > reon
548 */
549 weon = ps_to_rfbi_ticks(t->we_on_time, div);
550 weoff = ps_to_rfbi_ticks(t->we_off_time, div);
551 if (weoff <= weon)
552 weoff = weon + 1;
553 if (weon > 0x0f)
554 return -1;
555 if (weoff > 0x3f)
556 return -1;
557
558 reon = ps_to_rfbi_ticks(t->re_on_time, div);
559 reoff = ps_to_rfbi_ticks(t->re_off_time, div);
560 if (reoff <= reon)
561 reoff = reon + 1;
562 if (reon > 0x0f)
563 return -1;
564 if (reoff > 0x3f)
565 return -1;
566
567 cson = ps_to_rfbi_ticks(t->cs_on_time, div);
568 csoff = ps_to_rfbi_ticks(t->cs_off_time, div);
569 if (csoff <= cson)
570 csoff = cson + 1;
571 if (csoff < max(weoff, reoff))
572 csoff = max(weoff, reoff);
573 if (cson > 0x0f)
574 return -1;
575 if (csoff > 0x3f)
576 return -1;
577
578 l = cson;
579 l |= csoff << 4;
580 l |= weon << 10;
581 l |= weoff << 14;
582 l |= reon << 20;
583 l |= reoff << 24;
584
585 t->tim[0] = l;
586
587 actim = ps_to_rfbi_ticks(t->access_time, div);
588 if (actim <= reon)
589 actim = reon + 1;
590 if (actim > 0x3f)
591 return -1;
592
593 wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div);
594 if (wecyc < weoff)
595 wecyc = weoff;
596 if (wecyc > 0x3f)
597 return -1;
598
599 recyc = ps_to_rfbi_ticks(t->re_cycle_time, div);
600 if (recyc < reoff)
601 recyc = reoff;
602 if (recyc > 0x3f)
603 return -1;
604
605 cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div);
606 if (cs_pulse > 0x3f)
607 return -1;
608
609 l = wecyc;
610 l |= recyc << 6;
611 l |= cs_pulse << 12;
612 l |= actim << 22;
613
614 t->tim[1] = l;
615
616 t->tim[2] = div - 1;
617
618 t->converted = 1;
619
620 return 0;
621}
622
623/* xxx FIX module selection missing */
624int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
625 unsigned hs_pulse_time, unsigned vs_pulse_time,
626 int hs_pol_inv, int vs_pol_inv, int extif_div)
627{
628 int hs, vs;
629 int min;
630 u32 l;
631
632 hs = ps_to_rfbi_ticks(hs_pulse_time, 1);
633 vs = ps_to_rfbi_ticks(vs_pulse_time, 1);
634 if (hs < 2)
635 return -EDOM;
636 if (mode == OMAP_DSS_RFBI_TE_MODE_2)
637 min = 2;
638 else /* OMAP_DSS_RFBI_TE_MODE_1 */
639 min = 4;
640 if (vs < min)
641 return -EDOM;
642 if (vs == hs)
643 return -EINVAL;
644 rfbi.te_mode = mode;
645 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);
647
648 rfbi_enable_clocks(1);
649 rfbi_write_reg(RFBI_HSYNC_WIDTH, hs);
650 rfbi_write_reg(RFBI_VSYNC_WIDTH, vs);
651
652 l = rfbi_read_reg(RFBI_CONFIG(0));
653 if (hs_pol_inv)
654 l &= ~(1 << 21);
655 else
656 l |= 1 << 21;
657 if (vs_pol_inv)
658 l &= ~(1 << 20);
659 else
660 l |= 1 << 20;
661 rfbi_enable_clocks(0);
662
663 return 0;
664}
665EXPORT_SYMBOL(omap_rfbi_setup_te);
666
667/* xxx FIX module selection missing */
668int omap_rfbi_enable_te(bool enable, unsigned line)
669{
670 u32 l;
671
672 DSSDBG("te %d line %d mode %d\n", enable, line, rfbi.te_mode);
673 if (line > (1 << 11) - 1)
674 return -EINVAL;
675
676 rfbi_enable_clocks(1);
677 l = rfbi_read_reg(RFBI_CONFIG(0));
678 l &= ~(0x3 << 2);
679 if (enable) {
680 rfbi.te_enabled = 1;
681 l |= rfbi.te_mode << 2;
682 } else
683 rfbi.te_enabled = 0;
684 rfbi_write_reg(RFBI_CONFIG(0), l);
685 rfbi_write_reg(RFBI_LINE_NUMBER, line);
686 rfbi_enable_clocks(0);
687
688 return 0;
689}
690EXPORT_SYMBOL(omap_rfbi_enable_te);
691
692#if 0
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{
731 u32 l;
732 int cycle1 = 0, cycle2 = 0, cycle3 = 0;
733 enum omap_rfbi_cycleformat cycleformat;
734 enum omap_rfbi_datatype datatype;
735 enum omap_rfbi_parallelmode parallelmode;
736
737 switch (bpp) {
738 case 12:
739 datatype = OMAP_DSS_RFBI_DATATYPE_12;
740 break;
741 case 16:
742 datatype = OMAP_DSS_RFBI_DATATYPE_16;
743 break;
744 case 18:
745 datatype = OMAP_DSS_RFBI_DATATYPE_18;
746 break;
747 case 24:
748 datatype = OMAP_DSS_RFBI_DATATYPE_24;
749 break;
750 default:
751 BUG();
752 return 1;
753 }
754 rfbi.datatype = datatype;
755
756 switch (lines) {
757 case 8:
758 parallelmode = OMAP_DSS_RFBI_PARALLELMODE_8;
759 break;
760 case 9:
761 parallelmode = OMAP_DSS_RFBI_PARALLELMODE_9;
762 break;
763 case 12:
764 parallelmode = OMAP_DSS_RFBI_PARALLELMODE_12;
765 break;
766 case 16:
767 parallelmode = OMAP_DSS_RFBI_PARALLELMODE_16;
768 break;
769 default:
770 BUG();
771 return 1;
772 }
773 rfbi.parallelmode = parallelmode;
774
775 if ((bpp % lines) == 0) {
776 switch (bpp / lines) {
777 case 1:
778 cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_1_1;
779 break;
780 case 2:
781 cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_2_1;
782 break;
783 case 3:
784 cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_1;
785 break;
786 default:
787 BUG();
788 return 1;
789 }
790 } else if ((2 * bpp % lines) == 0) {
791 if ((2 * bpp / lines) == 3)
792 cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_2;
793 else {
794 BUG();
795 return 1;
796 }
797 } else {
798 BUG();
799 return 1;
800 }
801
802 switch (cycleformat) {
803 case OMAP_DSS_RFBI_CYCLEFORMAT_1_1:
804 cycle1 = lines;
805 break;
806
807 case OMAP_DSS_RFBI_CYCLEFORMAT_2_1:
808 cycle1 = lines;
809 cycle2 = lines;
810 break;
811
812 case OMAP_DSS_RFBI_CYCLEFORMAT_3_1:
813 cycle1 = lines;
814 cycle2 = lines;
815 cycle3 = lines;
816 break;
817
818 case OMAP_DSS_RFBI_CYCLEFORMAT_3_2:
819 cycle1 = lines;
820 cycle2 = (lines / 2) | ((lines / 2) << 16);
821 cycle3 = (lines << 16);
822 break;
823 }
824
825 rfbi_enable_clocks(1);
826
827 REG_FLD_MOD(RFBI_CONTROL, 0, 3, 2); /* clear CS */
828
829 l = 0;
830 l |= FLD_VAL(parallelmode, 1, 0);
831 l |= FLD_VAL(0, 3, 2); /* TRIGGERMODE: ITE */
832 l |= FLD_VAL(0, 4, 4); /* TIMEGRANULARITY */
833 l |= FLD_VAL(datatype, 6, 5);
834 /* l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */
835 l |= FLD_VAL(0, 8, 7); /* L4FORMAT, 1pix/L4 */
836 l |= FLD_VAL(cycleformat, 10, 9);
837 l |= FLD_VAL(0, 12, 11); /* UNUSEDBITS */
838 l |= FLD_VAL(0, 16, 16); /* A0POLARITY */
839 l |= FLD_VAL(0, 17, 17); /* REPOLARITY */
840 l |= FLD_VAL(0, 18, 18); /* WEPOLARITY */
841 l |= FLD_VAL(0, 19, 19); /* CSPOLARITY */
842 l |= FLD_VAL(1, 20, 20); /* TE_VSYNC_POLARITY */
843 l |= FLD_VAL(1, 21, 21); /* HSYNCPOLARITY */
844 rfbi_write_reg(RFBI_CONFIG(rfbi_module), l);
845
846 rfbi_write_reg(RFBI_DATA_CYCLE1(rfbi_module), cycle1);
847 rfbi_write_reg(RFBI_DATA_CYCLE2(rfbi_module), cycle2);
848 rfbi_write_reg(RFBI_DATA_CYCLE3(rfbi_module), cycle3);
849
850
851 l = rfbi_read_reg(RFBI_CONTROL);
852 l = FLD_MOD(l, rfbi_module+1, 3, 2); /* Select CSx */
853 l = FLD_MOD(l, 0, 1, 1); /* clear bypass */
854 rfbi_write_reg(RFBI_CONTROL, l);
855
856
857 DSSDBG("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n",
858 bpp, lines, cycle1, cycle2, cycle3);
859
860 rfbi_enable_clocks(0);
861
862 return 0;
863}
864EXPORT_SYMBOL(rfbi_configure);
865
866int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
867 u16 *x, u16 *y, u16 *w, u16 *h)
868{
869 u16 dw, dh;
870
871 dssdev->driver->get_resolution(dssdev, &dw, &dh);
872
873 if (*x > dw || *y > dh)
874 return -EINVAL;
875
876 if (*x + *w > dw)
877 return -EINVAL;
878
879 if (*y + *h > dh)
880 return -EINVAL;
881
882 if (*w == 1)
883 return -EINVAL;
884
885 if (*w == 0 || *h == 0)
886 return -EINVAL;
887
888 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
889 dss_setup_partial_planes(dssdev, x, y, w, h);
890 dispc_set_lcd_size(*w, *h);
891 }
892
893 return 0;
894}
895EXPORT_SYMBOL(omap_rfbi_prepare_update);
896
897int omap_rfbi_update(struct omap_dss_device *dssdev,
898 u16 x, u16 y, u16 w, u16 h,
899 void (*callback)(void *), void *data)
900{
901 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
902 rfbi_transfer_area(w, h, callback, data);
903 } else {
904 struct omap_overlay *ovl;
905 void __iomem *addr;
906 int scr_width;
907
908 ovl = dssdev->manager->overlays[0];
909 scr_width = ovl->info.screen_width;
910 addr = ovl->info.vaddr;
911
912 omap_rfbi_write_pixels(addr, scr_width, x, y, w, h);
913
914 callback(data);
915 }
916
917 return 0;
918}
919EXPORT_SYMBOL(omap_rfbi_update);
920
921void rfbi_dump_regs(struct seq_file *s)
922{
923#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
924
925 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
926
927 DUMPREG(RFBI_REVISION);
928 DUMPREG(RFBI_SYSCONFIG);
929 DUMPREG(RFBI_SYSSTATUS);
930 DUMPREG(RFBI_CONTROL);
931 DUMPREG(RFBI_PIXEL_CNT);
932 DUMPREG(RFBI_LINE_NUMBER);
933 DUMPREG(RFBI_CMD);
934 DUMPREG(RFBI_PARAM);
935 DUMPREG(RFBI_DATA);
936 DUMPREG(RFBI_READ);
937 DUMPREG(RFBI_STATUS);
938
939 DUMPREG(RFBI_CONFIG(0));
940 DUMPREG(RFBI_ONOFF_TIME(0));
941 DUMPREG(RFBI_CYCLE_TIME(0));
942 DUMPREG(RFBI_DATA_CYCLE1(0));
943 DUMPREG(RFBI_DATA_CYCLE2(0));
944 DUMPREG(RFBI_DATA_CYCLE3(0));
945
946 DUMPREG(RFBI_CONFIG(1));
947 DUMPREG(RFBI_ONOFF_TIME(1));
948 DUMPREG(RFBI_CYCLE_TIME(1));
949 DUMPREG(RFBI_DATA_CYCLE1(1));
950 DUMPREG(RFBI_DATA_CYCLE2(1));
951 DUMPREG(RFBI_DATA_CYCLE3(1));
952
953 DUMPREG(RFBI_VSYNC_WIDTH);
954 DUMPREG(RFBI_HSYNC_WIDTH);
955
956 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
957#undef DUMPREG
958}
959
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)
1005{
1006 int r;
1007
1008 r = omap_dss_start_device(dssdev);
1009 if (r) {
1010 DSSERR("failed to start device\n");
1011 goto err0;
1012 }
1013
1014 r = omap_dispc_register_isr(framedone_callback, NULL,
1015 DISPC_IRQ_FRAMEDONE);
1016 if (r) {
1017 DSSERR("can't get FRAMEDONE irq\n");
1018 goto err1;
1019 }
1020
1021 dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
1022
1023 dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_RFBI);
1024
1025 dispc_set_tft_data_lines(dssdev->ctrl.pixel_size);
1026
1027 rfbi_configure(dssdev->phy.rfbi.channel,
1028 dssdev->ctrl.pixel_size,
1029 dssdev->phy.rfbi.data_lines);
1030
1031 rfbi_set_timings(dssdev->phy.rfbi.channel,
1032 &dssdev->ctrl.rfbi_timings);
1033
1034
1035 return 0;
1036err1:
1037 omap_dss_stop_device(dssdev);
1038err0:
1039 return r;
1040}
1041EXPORT_SYMBOL(omapdss_rfbi_display_enable);
1042
1043void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
1044{
1045 omap_dispc_unregister_isr(framedone_callback, NULL,
1046 DISPC_IRQ_FRAMEDONE);
1047 omap_dss_stop_device(dssdev);
1048}
1049EXPORT_SYMBOL(omapdss_rfbi_display_disable);
1050
1051int rfbi_init_display(struct omap_dss_device *dssdev)
1052{
1053 rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
1054 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
1055 return 0;
1056}
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
new file mode 100644
index 000000000000..12eb4042dd82
--- /dev/null
+++ b/drivers/video/omap2/dss/sdi.c
@@ -0,0 +1,176 @@
1/*
2 * linux/drivers/video/omap2/dss/sdi.c
3 *
4 * Copyright (C) 2009 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#define DSS_SUBSYS_NAME "SDI"
21
22#include <linux/kernel.h>
23#include <linux/clk.h>
24#include <linux/delay.h>
25#include <linux/err.h>
26
27#include <plat/display.h>
28#include "dss.h"
29
30static struct {
31 bool skip_init;
32 bool update_enabled;
33} sdi;
34
35static void sdi_basic_init(void)
36{
37 dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS);
38
39 dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
40 dispc_set_tft_data_lines(24);
41 dispc_lcd_enable_signal_polarity(1);
42}
43
44int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
45{
46 struct omap_video_timings *t = &dssdev->panel.timings;
47 struct dss_clock_info dss_cinfo;
48 struct dispc_clock_info dispc_cinfo;
49 u16 lck_div, pck_div;
50 unsigned long fck;
51 unsigned long pck;
52 int r;
53
54 r = omap_dss_start_device(dssdev);
55 if (r) {
56 DSSERR("failed to start device\n");
57 goto err0;
58 }
59
60 /* In case of skip_init sdi_init has already enabled the clocks */
61 if (!sdi.skip_init)
62 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
63
64 sdi_basic_init();
65
66 /* 15.5.9.1.2 */
67 dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF;
68
69 dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi,
70 dssdev->panel.acb);
71
72 if (!sdi.skip_init) {
73 r = dss_calc_clock_div(1, t->pixel_clock * 1000,
74 &dss_cinfo, &dispc_cinfo);
75 } else {
76 r = dss_get_clock_div(&dss_cinfo);
77 r = dispc_get_clock_div(&dispc_cinfo);
78 }
79
80 if (r)
81 goto err2;
82
83 fck = dss_cinfo.fck;
84 lck_div = dispc_cinfo.lck_div;
85 pck_div = dispc_cinfo.pck_div;
86
87 pck = fck / lck_div / pck_div / 1000;
88
89 if (pck != t->pixel_clock) {
90 DSSWARN("Could not find exact pixel clock. Requested %d kHz, "
91 "got %lu kHz\n",
92 t->pixel_clock, pck);
93
94 t->pixel_clock = pck;
95 }
96
97
98 dispc_set_lcd_timings(t);
99
100 r = dss_set_clock_div(&dss_cinfo);
101 if (r)
102 goto err2;
103
104 r = dispc_set_clock_div(&dispc_cinfo);
105 if (r)
106 goto err2;
107
108 if (!sdi.skip_init) {
109 dss_sdi_init(dssdev->phy.sdi.datapairs);
110 r = dss_sdi_enable();
111 if (r)
112 goto err1;
113 mdelay(2);
114 }
115
116 dssdev->manager->enable(dssdev->manager);
117
118 if (dssdev->driver->enable) {
119 r = dssdev->driver->enable(dssdev);
120 if (r)
121 goto err3;
122 }
123
124 sdi.skip_init = 0;
125
126 return 0;
127err3:
128 dssdev->manager->disable(dssdev->manager);
129err2:
130 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
131err1:
132 omap_dss_stop_device(dssdev);
133err0:
134 return r;
135}
136EXPORT_SYMBOL(omapdss_sdi_display_enable);
137
138void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
139{
140 if (dssdev->driver->disable)
141 dssdev->driver->disable(dssdev);
142
143 dssdev->manager->disable(dssdev->manager);
144
145 dss_sdi_disable();
146
147 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
148
149 omap_dss_stop_device(dssdev);
150}
151EXPORT_SYMBOL(omapdss_sdi_display_disable);
152
153int sdi_init_display(struct omap_dss_device *dssdev)
154{
155 DSSDBG("SDI init\n");
156
157 return 0;
158}
159
160int sdi_init(bool skip_init)
161{
162 /* we store this for first display enable, then clear it */
163 sdi.skip_init = skip_init;
164
165 /*
166 * Enable clocks already here, otherwise there would be a toggle
167 * of them until sdi_display_enable is called.
168 */
169 if (skip_init)
170 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
171 return 0;
172}
173
174void sdi_exit(void)
175{
176}
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
new file mode 100644
index 000000000000..f0ba5732d84a
--- /dev/null
+++ b/drivers/video/omap2/dss/venc.c
@@ -0,0 +1,755 @@
1/*
2 * linux/drivers/video/omap2/dss/venc.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * VENC settings from TI's DSS driver
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 "VENC"
23
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <linux/clk.h>
27#include <linux/err.h>
28#include <linux/io.h>
29#include <linux/mutex.h>
30#include <linux/completion.h>
31#include <linux/delay.h>
32#include <linux/string.h>
33#include <linux/seq_file.h>
34#include <linux/platform_device.h>
35#include <linux/regulator/consumer.h>
36
37#include <plat/display.h>
38#include <plat/cpu.h>
39
40#include "dss.h"
41
42#define VENC_BASE 0x48050C00
43
44/* Venc registers */
45#define VENC_REV_ID 0x00
46#define VENC_STATUS 0x04
47#define VENC_F_CONTROL 0x08
48#define VENC_VIDOUT_CTRL 0x10
49#define VENC_SYNC_CTRL 0x14
50#define VENC_LLEN 0x1C
51#define VENC_FLENS 0x20
52#define VENC_HFLTR_CTRL 0x24
53#define VENC_CC_CARR_WSS_CARR 0x28
54#define VENC_C_PHASE 0x2C
55#define VENC_GAIN_U 0x30
56#define VENC_GAIN_V 0x34
57#define VENC_GAIN_Y 0x38
58#define VENC_BLACK_LEVEL 0x3C
59#define VENC_BLANK_LEVEL 0x40
60#define VENC_X_COLOR 0x44
61#define VENC_M_CONTROL 0x48
62#define VENC_BSTAMP_WSS_DATA 0x4C
63#define VENC_S_CARR 0x50
64#define VENC_LINE21 0x54
65#define VENC_LN_SEL 0x58
66#define VENC_L21__WC_CTL 0x5C
67#define VENC_HTRIGGER_VTRIGGER 0x60
68#define VENC_SAVID__EAVID 0x64
69#define VENC_FLEN__FAL 0x68
70#define VENC_LAL__PHASE_RESET 0x6C
71#define VENC_HS_INT_START_STOP_X 0x70
72#define VENC_HS_EXT_START_STOP_X 0x74
73#define VENC_VS_INT_START_X 0x78
74#define VENC_VS_INT_STOP_X__VS_INT_START_Y 0x7C
75#define VENC_VS_INT_STOP_Y__VS_EXT_START_X 0x80
76#define VENC_VS_EXT_STOP_X__VS_EXT_START_Y 0x84
77#define VENC_VS_EXT_STOP_Y 0x88
78#define VENC_AVID_START_STOP_X 0x90
79#define VENC_AVID_START_STOP_Y 0x94
80#define VENC_FID_INT_START_X__FID_INT_START_Y 0xA0
81#define VENC_FID_INT_OFFSET_Y__FID_EXT_START_X 0xA4
82#define VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y 0xA8
83#define VENC_TVDETGP_INT_START_STOP_X 0xB0
84#define VENC_TVDETGP_INT_START_STOP_Y 0xB4
85#define VENC_GEN_CTRL 0xB8
86#define VENC_OUTPUT_CONTROL 0xC4
87#define VENC_OUTPUT_TEST 0xC8
88#define VENC_DAC_B__DAC_C 0xC8
89
90struct venc_config {
91 u32 f_control;
92 u32 vidout_ctrl;
93 u32 sync_ctrl;
94 u32 llen;
95 u32 flens;
96 u32 hfltr_ctrl;
97 u32 cc_carr_wss_carr;
98 u32 c_phase;
99 u32 gain_u;
100 u32 gain_v;
101 u32 gain_y;
102 u32 black_level;
103 u32 blank_level;
104 u32 x_color;
105 u32 m_control;
106 u32 bstamp_wss_data;
107 u32 s_carr;
108 u32 line21;
109 u32 ln_sel;
110 u32 l21__wc_ctl;
111 u32 htrigger_vtrigger;
112 u32 savid__eavid;
113 u32 flen__fal;
114 u32 lal__phase_reset;
115 u32 hs_int_start_stop_x;
116 u32 hs_ext_start_stop_x;
117 u32 vs_int_start_x;
118 u32 vs_int_stop_x__vs_int_start_y;
119 u32 vs_int_stop_y__vs_ext_start_x;
120 u32 vs_ext_stop_x__vs_ext_start_y;
121 u32 vs_ext_stop_y;
122 u32 avid_start_stop_x;
123 u32 avid_start_stop_y;
124 u32 fid_int_start_x__fid_int_start_y;
125 u32 fid_int_offset_y__fid_ext_start_x;
126 u32 fid_ext_start_y__fid_ext_offset_y;
127 u32 tvdetgp_int_start_stop_x;
128 u32 tvdetgp_int_start_stop_y;
129 u32 gen_ctrl;
130};
131
132/* from TRM */
133static const struct venc_config venc_config_pal_trm = {
134 .f_control = 0,
135 .vidout_ctrl = 1,
136 .sync_ctrl = 0x40,
137 .llen = 0x35F, /* 863 */
138 .flens = 0x270, /* 624 */
139 .hfltr_ctrl = 0,
140 .cc_carr_wss_carr = 0x2F7225ED,
141 .c_phase = 0,
142 .gain_u = 0x111,
143 .gain_v = 0x181,
144 .gain_y = 0x140,
145 .black_level = 0x3B,
146 .blank_level = 0x3B,
147 .x_color = 0x7,
148 .m_control = 0x2,
149 .bstamp_wss_data = 0x3F,
150 .s_carr = 0x2A098ACB,
151 .line21 = 0,
152 .ln_sel = 0x01290015,
153 .l21__wc_ctl = 0x0000F603,
154 .htrigger_vtrigger = 0,
155
156 .savid__eavid = 0x06A70108,
157 .flen__fal = 0x00180270,
158 .lal__phase_reset = 0x00040135,
159 .hs_int_start_stop_x = 0x00880358,
160 .hs_ext_start_stop_x = 0x000F035F,
161 .vs_int_start_x = 0x01A70000,
162 .vs_int_stop_x__vs_int_start_y = 0x000001A7,
163 .vs_int_stop_y__vs_ext_start_x = 0x01AF0000,
164 .vs_ext_stop_x__vs_ext_start_y = 0x000101AF,
165 .vs_ext_stop_y = 0x00000025,
166 .avid_start_stop_x = 0x03530083,
167 .avid_start_stop_y = 0x026C002E,
168 .fid_int_start_x__fid_int_start_y = 0x0001008A,
169 .fid_int_offset_y__fid_ext_start_x = 0x002E0138,
170 .fid_ext_start_y__fid_ext_offset_y = 0x01380001,
171
172 .tvdetgp_int_start_stop_x = 0x00140001,
173 .tvdetgp_int_start_stop_y = 0x00010001,
174 .gen_ctrl = 0x00FF0000,
175};
176
177/* from TRM */
178static const struct venc_config venc_config_ntsc_trm = {
179 .f_control = 0,
180 .vidout_ctrl = 1,
181 .sync_ctrl = 0x8040,
182 .llen = 0x359,
183 .flens = 0x20C,
184 .hfltr_ctrl = 0,
185 .cc_carr_wss_carr = 0x043F2631,
186 .c_phase = 0,
187 .gain_u = 0x102,
188 .gain_v = 0x16C,
189 .gain_y = 0x12F,
190 .black_level = 0x43,
191 .blank_level = 0x38,
192 .x_color = 0x7,
193 .m_control = 0x1,
194 .bstamp_wss_data = 0x38,
195 .s_carr = 0x21F07C1F,
196 .line21 = 0,
197 .ln_sel = 0x01310011,
198 .l21__wc_ctl = 0x0000F003,
199 .htrigger_vtrigger = 0,
200
201 .savid__eavid = 0x069300F4,
202 .flen__fal = 0x0016020C,
203 .lal__phase_reset = 0x00060107,
204 .hs_int_start_stop_x = 0x008E0350,
205 .hs_ext_start_stop_x = 0x000F0359,
206 .vs_int_start_x = 0x01A00000,
207 .vs_int_stop_x__vs_int_start_y = 0x020701A0,
208 .vs_int_stop_y__vs_ext_start_x = 0x01AC0024,
209 .vs_ext_stop_x__vs_ext_start_y = 0x020D01AC,
210 .vs_ext_stop_y = 0x00000006,
211 .avid_start_stop_x = 0x03480078,
212 .avid_start_stop_y = 0x02060024,
213 .fid_int_start_x__fid_int_start_y = 0x0001008A,
214 .fid_int_offset_y__fid_ext_start_x = 0x01AC0106,
215 .fid_ext_start_y__fid_ext_offset_y = 0x01060006,
216
217 .tvdetgp_int_start_stop_x = 0x00140001,
218 .tvdetgp_int_start_stop_y = 0x00010001,
219 .gen_ctrl = 0x00F90000,
220};
221
222static const struct venc_config venc_config_pal_bdghi = {
223 .f_control = 0,
224 .vidout_ctrl = 0,
225 .sync_ctrl = 0,
226 .hfltr_ctrl = 0,
227 .x_color = 0,
228 .line21 = 0,
229 .ln_sel = 21,
230 .htrigger_vtrigger = 0,
231 .tvdetgp_int_start_stop_x = 0x00140001,
232 .tvdetgp_int_start_stop_y = 0x00010001,
233 .gen_ctrl = 0x00FB0000,
234
235 .llen = 864-1,
236 .flens = 625-1,
237 .cc_carr_wss_carr = 0x2F7625ED,
238 .c_phase = 0xDF,
239 .gain_u = 0x111,
240 .gain_v = 0x181,
241 .gain_y = 0x140,
242 .black_level = 0x3e,
243 .blank_level = 0x3e,
244 .m_control = 0<<2 | 1<<1,
245 .bstamp_wss_data = 0x42,
246 .s_carr = 0x2a098acb,
247 .l21__wc_ctl = 0<<13 | 0x16<<8 | 0<<0,
248 .savid__eavid = 0x06A70108,
249 .flen__fal = 23<<16 | 624<<0,
250 .lal__phase_reset = 2<<17 | 310<<0,
251 .hs_int_start_stop_x = 0x00920358,
252 .hs_ext_start_stop_x = 0x000F035F,
253 .vs_int_start_x = 0x1a7<<16,
254 .vs_int_stop_x__vs_int_start_y = 0x000601A7,
255 .vs_int_stop_y__vs_ext_start_x = 0x01AF0036,
256 .vs_ext_stop_x__vs_ext_start_y = 0x27101af,
257 .vs_ext_stop_y = 0x05,
258 .avid_start_stop_x = 0x03530082,
259 .avid_start_stop_y = 0x0270002E,
260 .fid_int_start_x__fid_int_start_y = 0x0005008A,
261 .fid_int_offset_y__fid_ext_start_x = 0x002E0138,
262 .fid_ext_start_y__fid_ext_offset_y = 0x01380005,
263};
264
265const struct omap_video_timings omap_dss_pal_timings = {
266 .x_res = 720,
267 .y_res = 574,
268 .pixel_clock = 13500,
269 .hsw = 64,
270 .hfp = 12,
271 .hbp = 68,
272 .vsw = 5,
273 .vfp = 5,
274 .vbp = 41,
275};
276EXPORT_SYMBOL(omap_dss_pal_timings);
277
278const struct omap_video_timings omap_dss_ntsc_timings = {
279 .x_res = 720,
280 .y_res = 482,
281 .pixel_clock = 13500,
282 .hsw = 64,
283 .hfp = 16,
284 .hbp = 58,
285 .vsw = 6,
286 .vfp = 6,
287 .vbp = 31,
288};
289EXPORT_SYMBOL(omap_dss_ntsc_timings);
290
291static struct {
292 void __iomem *base;
293 struct mutex venc_lock;
294 u32 wss_data;
295 struct regulator *vdda_dac_reg;
296} venc;
297
298static inline void venc_write_reg(int idx, u32 val)
299{
300 __raw_writel(val, venc.base + idx);
301}
302
303static inline u32 venc_read_reg(int idx)
304{
305 u32 l = __raw_readl(venc.base + idx);
306 return l;
307}
308
309static void venc_write_config(const struct venc_config *config)
310{
311 DSSDBG("write venc conf\n");
312
313 venc_write_reg(VENC_LLEN, config->llen);
314 venc_write_reg(VENC_FLENS, config->flens);
315 venc_write_reg(VENC_CC_CARR_WSS_CARR, config->cc_carr_wss_carr);
316 venc_write_reg(VENC_C_PHASE, config->c_phase);
317 venc_write_reg(VENC_GAIN_U, config->gain_u);
318 venc_write_reg(VENC_GAIN_V, config->gain_v);
319 venc_write_reg(VENC_GAIN_Y, config->gain_y);
320 venc_write_reg(VENC_BLACK_LEVEL, config->black_level);
321 venc_write_reg(VENC_BLANK_LEVEL, config->blank_level);
322 venc_write_reg(VENC_M_CONTROL, config->m_control);
323 venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
324 venc.wss_data);
325 venc_write_reg(VENC_S_CARR, config->s_carr);
326 venc_write_reg(VENC_L21__WC_CTL, config->l21__wc_ctl);
327 venc_write_reg(VENC_SAVID__EAVID, config->savid__eavid);
328 venc_write_reg(VENC_FLEN__FAL, config->flen__fal);
329 venc_write_reg(VENC_LAL__PHASE_RESET, config->lal__phase_reset);
330 venc_write_reg(VENC_HS_INT_START_STOP_X, config->hs_int_start_stop_x);
331 venc_write_reg(VENC_HS_EXT_START_STOP_X, config->hs_ext_start_stop_x);
332 venc_write_reg(VENC_VS_INT_START_X, config->vs_int_start_x);
333 venc_write_reg(VENC_VS_INT_STOP_X__VS_INT_START_Y,
334 config->vs_int_stop_x__vs_int_start_y);
335 venc_write_reg(VENC_VS_INT_STOP_Y__VS_EXT_START_X,
336 config->vs_int_stop_y__vs_ext_start_x);
337 venc_write_reg(VENC_VS_EXT_STOP_X__VS_EXT_START_Y,
338 config->vs_ext_stop_x__vs_ext_start_y);
339 venc_write_reg(VENC_VS_EXT_STOP_Y, config->vs_ext_stop_y);
340 venc_write_reg(VENC_AVID_START_STOP_X, config->avid_start_stop_x);
341 venc_write_reg(VENC_AVID_START_STOP_Y, config->avid_start_stop_y);
342 venc_write_reg(VENC_FID_INT_START_X__FID_INT_START_Y,
343 config->fid_int_start_x__fid_int_start_y);
344 venc_write_reg(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X,
345 config->fid_int_offset_y__fid_ext_start_x);
346 venc_write_reg(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y,
347 config->fid_ext_start_y__fid_ext_offset_y);
348
349 venc_write_reg(VENC_DAC_B__DAC_C, venc_read_reg(VENC_DAC_B__DAC_C));
350 venc_write_reg(VENC_VIDOUT_CTRL, config->vidout_ctrl);
351 venc_write_reg(VENC_HFLTR_CTRL, config->hfltr_ctrl);
352 venc_write_reg(VENC_X_COLOR, config->x_color);
353 venc_write_reg(VENC_LINE21, config->line21);
354 venc_write_reg(VENC_LN_SEL, config->ln_sel);
355 venc_write_reg(VENC_HTRIGGER_VTRIGGER, config->htrigger_vtrigger);
356 venc_write_reg(VENC_TVDETGP_INT_START_STOP_X,
357 config->tvdetgp_int_start_stop_x);
358 venc_write_reg(VENC_TVDETGP_INT_START_STOP_Y,
359 config->tvdetgp_int_start_stop_y);
360 venc_write_reg(VENC_GEN_CTRL, config->gen_ctrl);
361 venc_write_reg(VENC_F_CONTROL, config->f_control);
362 venc_write_reg(VENC_SYNC_CTRL, config->sync_ctrl);
363}
364
365static void venc_reset(void)
366{
367 int t = 1000;
368
369 venc_write_reg(VENC_F_CONTROL, 1<<8);
370 while (venc_read_reg(VENC_F_CONTROL) & (1<<8)) {
371 if (--t == 0) {
372 DSSERR("Failed to reset venc\n");
373 return;
374 }
375 }
376
377 /* the magical sleep that makes things work */
378 msleep(20);
379}
380
381static void venc_enable_clocks(int enable)
382{
383 if (enable)
384 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M |
385 DSS_CLK_96M);
386 else
387 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M |
388 DSS_CLK_96M);
389}
390
391static const struct venc_config *venc_timings_to_config(
392 struct omap_video_timings *timings)
393{
394 if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
395 return &venc_config_pal_trm;
396
397 if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
398 return &venc_config_ntsc_trm;
399
400 BUG();
401}
402
403static void venc_power_on(struct omap_dss_device *dssdev)
404{
405 u32 l;
406
407 venc_enable_clocks(1);
408
409 venc_reset();
410 venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
411
412 dss_set_venc_output(dssdev->phy.venc.type);
413 dss_set_dac_pwrdn_bgz(1);
414
415 l = 0;
416
417 if (dssdev->phy.venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE)
418 l |= 1 << 1;
419 else /* S-Video */
420 l |= (1 << 0) | (1 << 2);
421
422 if (dssdev->phy.venc.invert_polarity == false)
423 l |= 1 << 3;
424
425 venc_write_reg(VENC_OUTPUT_CONTROL, l);
426
427 dispc_set_digit_size(dssdev->panel.timings.x_res,
428 dssdev->panel.timings.y_res/2);
429
430 regulator_enable(venc.vdda_dac_reg);
431
432 if (dssdev->platform_enable)
433 dssdev->platform_enable(dssdev);
434
435 dssdev->manager->enable(dssdev->manager);
436}
437
438static void venc_power_off(struct omap_dss_device *dssdev)
439{
440 venc_write_reg(VENC_OUTPUT_CONTROL, 0);
441 dss_set_dac_pwrdn_bgz(0);
442
443 dssdev->manager->disable(dssdev->manager);
444
445 if (dssdev->platform_disable)
446 dssdev->platform_disable(dssdev);
447
448 regulator_disable(venc.vdda_dac_reg);
449
450 venc_enable_clocks(0);
451}
452
453
454
455
456
457/* driver */
458static int venc_panel_probe(struct omap_dss_device *dssdev)
459{
460 dssdev->panel.timings = omap_dss_pal_timings;
461
462 return 0;
463}
464
465static void venc_panel_remove(struct omap_dss_device *dssdev)
466{
467}
468
469static int venc_panel_enable(struct omap_dss_device *dssdev)
470{
471 int r = 0;
472
473 DSSDBG("venc_enable_display\n");
474
475 mutex_lock(&venc.venc_lock);
476
477 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
478 r = -EINVAL;
479 goto err1;
480 }
481
482 if (dssdev->platform_enable) {
483 r = dssdev->platform_enable(dssdev);
484 if (r)
485 goto err2;
486 }
487
488 venc_power_on(dssdev);
489
490 venc.wss_data = 0;
491
492 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
493
494 /* wait couple of vsyncs until enabling the LCD */
495 msleep(50);
496
497 mutex_unlock(&venc.venc_lock);
498
499 return r;
500err2:
501 venc_power_off(dssdev);
502err1:
503 mutex_unlock(&venc.venc_lock);
504 return r;
505}
506
507static void venc_panel_disable(struct omap_dss_device *dssdev)
508{
509 DSSDBG("venc_disable_display\n");
510
511 mutex_lock(&venc.venc_lock);
512
513 if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
514 goto end;
515
516 if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
517 /* suspended is the same as disabled with venc */
518 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
519 goto end;
520 }
521
522 venc_power_off(dssdev);
523
524 /* wait at least 5 vsyncs after disabling the LCD */
525 msleep(100);
526
527 if (dssdev->platform_disable)
528 dssdev->platform_disable(dssdev);
529
530 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
531end:
532 mutex_unlock(&venc.venc_lock);
533}
534
535static int venc_panel_suspend(struct omap_dss_device *dssdev)
536{
537 venc_panel_disable(dssdev);
538 return 0;
539}
540
541static int venc_panel_resume(struct omap_dss_device *dssdev)
542{
543 return venc_panel_enable(dssdev);
544}
545
546static enum omap_dss_update_mode venc_get_update_mode(
547 struct omap_dss_device *dssdev)
548{
549 return OMAP_DSS_UPDATE_AUTO;
550}
551
552static int venc_set_update_mode(struct omap_dss_device *dssdev,
553 enum omap_dss_update_mode mode)
554{
555 if (mode != OMAP_DSS_UPDATE_AUTO)
556 return -EINVAL;
557 return 0;
558}
559
560static void venc_get_timings(struct omap_dss_device *dssdev,
561 struct omap_video_timings *timings)
562{
563 *timings = dssdev->panel.timings;
564}
565
566static void venc_set_timings(struct omap_dss_device *dssdev,
567 struct omap_video_timings *timings)
568{
569 DSSDBG("venc_set_timings\n");
570
571 /* Reset WSS data when the TV standard changes. */
572 if (memcmp(&dssdev->panel.timings, timings, sizeof(*timings)))
573 venc.wss_data = 0;
574
575 dssdev->panel.timings = *timings;
576 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
577 /* turn the venc off and on to get new timings to use */
578 venc_panel_disable(dssdev);
579 venc_panel_enable(dssdev);
580 }
581}
582
583static int venc_check_timings(struct omap_dss_device *dssdev,
584 struct omap_video_timings *timings)
585{
586 DSSDBG("venc_check_timings\n");
587
588 if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
589 return 0;
590
591 if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
592 return 0;
593
594 return -EINVAL;
595}
596
597static u32 venc_get_wss(struct omap_dss_device *dssdev)
598{
599 /* Invert due to VENC_L21_WC_CTL:INV=1 */
600 return (venc.wss_data >> 8) ^ 0xfffff;
601}
602
603static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
604{
605 const struct venc_config *config;
606
607 DSSDBG("venc_set_wss\n");
608
609 mutex_lock(&venc.venc_lock);
610
611 config = venc_timings_to_config(&dssdev->panel.timings);
612
613 /* Invert due to VENC_L21_WC_CTL:INV=1 */
614 venc.wss_data = (wss ^ 0xfffff) << 8;
615
616 venc_enable_clocks(1);
617
618 venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
619 venc.wss_data);
620
621 venc_enable_clocks(0);
622
623 mutex_unlock(&venc.venc_lock);
624
625 return 0;
626}
627
628static struct omap_dss_driver venc_driver = {
629 .probe = venc_panel_probe,
630 .remove = venc_panel_remove,
631
632 .enable = venc_panel_enable,
633 .disable = venc_panel_disable,
634 .suspend = venc_panel_suspend,
635 .resume = venc_panel_resume,
636
637 .get_resolution = omapdss_default_get_resolution,
638 .get_recommended_bpp = omapdss_default_get_recommended_bpp,
639
640 .set_update_mode = venc_set_update_mode,
641 .get_update_mode = venc_get_update_mode,
642
643 .get_timings = venc_get_timings,
644 .set_timings = venc_set_timings,
645 .check_timings = venc_check_timings,
646
647 .get_wss = venc_get_wss,
648 .set_wss = venc_set_wss,
649
650 .driver = {
651 .name = "venc",
652 .owner = THIS_MODULE,
653 },
654};
655/* driver end */
656
657
658
659int venc_init(struct platform_device *pdev)
660{
661 u8 rev_id;
662
663 mutex_init(&venc.venc_lock);
664
665 venc.wss_data = 0;
666
667 venc.base = ioremap(VENC_BASE, SZ_1K);
668 if (!venc.base) {
669 DSSERR("can't ioremap VENC\n");
670 return -ENOMEM;
671 }
672
673 venc.vdda_dac_reg = dss_get_vdda_dac();
674 if (IS_ERR(venc.vdda_dac_reg)) {
675 iounmap(venc.base);
676 DSSERR("can't get VDDA_DAC regulator\n");
677 return PTR_ERR(venc.vdda_dac_reg);
678 }
679
680 venc_enable_clocks(1);
681
682 rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
683 printk(KERN_INFO "OMAP VENC rev %d\n", rev_id);
684
685 venc_enable_clocks(0);
686
687 return omap_dss_register_driver(&venc_driver);
688}
689
690void venc_exit(void)
691{
692 omap_dss_unregister_driver(&venc_driver);
693
694 iounmap(venc.base);
695}
696
697int venc_init_display(struct omap_dss_device *dssdev)
698{
699 DSSDBG("init_display\n");
700
701 return 0;
702}
703
704void venc_dump_regs(struct seq_file *s)
705{
706#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
707
708 venc_enable_clocks(1);
709
710 DUMPREG(VENC_F_CONTROL);
711 DUMPREG(VENC_VIDOUT_CTRL);
712 DUMPREG(VENC_SYNC_CTRL);
713 DUMPREG(VENC_LLEN);
714 DUMPREG(VENC_FLENS);
715 DUMPREG(VENC_HFLTR_CTRL);
716 DUMPREG(VENC_CC_CARR_WSS_CARR);
717 DUMPREG(VENC_C_PHASE);
718 DUMPREG(VENC_GAIN_U);
719 DUMPREG(VENC_GAIN_V);
720 DUMPREG(VENC_GAIN_Y);
721 DUMPREG(VENC_BLACK_LEVEL);
722 DUMPREG(VENC_BLANK_LEVEL);
723 DUMPREG(VENC_X_COLOR);
724 DUMPREG(VENC_M_CONTROL);
725 DUMPREG(VENC_BSTAMP_WSS_DATA);
726 DUMPREG(VENC_S_CARR);
727 DUMPREG(VENC_LINE21);
728 DUMPREG(VENC_LN_SEL);
729 DUMPREG(VENC_L21__WC_CTL);
730 DUMPREG(VENC_HTRIGGER_VTRIGGER);
731 DUMPREG(VENC_SAVID__EAVID);
732 DUMPREG(VENC_FLEN__FAL);
733 DUMPREG(VENC_LAL__PHASE_RESET);
734 DUMPREG(VENC_HS_INT_START_STOP_X);
735 DUMPREG(VENC_HS_EXT_START_STOP_X);
736 DUMPREG(VENC_VS_INT_START_X);
737 DUMPREG(VENC_VS_INT_STOP_X__VS_INT_START_Y);
738 DUMPREG(VENC_VS_INT_STOP_Y__VS_EXT_START_X);
739 DUMPREG(VENC_VS_EXT_STOP_X__VS_EXT_START_Y);
740 DUMPREG(VENC_VS_EXT_STOP_Y);
741 DUMPREG(VENC_AVID_START_STOP_X);
742 DUMPREG(VENC_AVID_START_STOP_Y);
743 DUMPREG(VENC_FID_INT_START_X__FID_INT_START_Y);
744 DUMPREG(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X);
745 DUMPREG(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y);
746 DUMPREG(VENC_TVDETGP_INT_START_STOP_X);
747 DUMPREG(VENC_TVDETGP_INT_START_STOP_Y);
748 DUMPREG(VENC_GEN_CTRL);
749 DUMPREG(VENC_OUTPUT_CONTROL);
750 DUMPREG(VENC_OUTPUT_TEST);
751
752 venc_enable_clocks(0);
753
754#undef DUMPREG
755}
diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig
new file mode 100644
index 000000000000..43496d6c377f
--- /dev/null
+++ b/drivers/video/omap2/omapfb/Kconfig
@@ -0,0 +1,28 @@
1menuconfig FB_OMAP2
2 tristate "OMAP2/3 frame buffer support (EXPERIMENTAL)"
3 depends on FB && OMAP2_DSS
4
5 select OMAP2_VRAM
6 select OMAP2_VRFB
7 select FB_CFB_FILLRECT
8 select FB_CFB_COPYAREA
9 select FB_CFB_IMAGEBLIT
10 help
11 Frame buffer driver for OMAP2/3 based boards.
12
13config FB_OMAP2_DEBUG_SUPPORT
14 bool "Debug support for OMAP2/3 FB"
15 default y
16 depends on FB_OMAP2
17 help
18 Support for debug output. You have to enable the actual printing
19 with 'debug' module parameter.
20
21config FB_OMAP2_NUM_FBS
22 int "Number of framebuffers"
23 range 1 10
24 default 3
25 depends on FB_OMAP2
26 help
27 Select the number of framebuffers created. OMAP2/3 has 3 overlays
28 so normally this would be 3.
diff --git a/drivers/video/omap2/omapfb/Makefile b/drivers/video/omap2/omapfb/Makefile
new file mode 100644
index 000000000000..51c2e00d9bf8
--- /dev/null
+++ b/drivers/video/omap2/omapfb/Makefile
@@ -0,0 +1,2 @@
1obj-$(CONFIG_FB_OMAP2) += omapfb.o
2omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
new file mode 100644
index 000000000000..1ffa760b8545
--- /dev/null
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -0,0 +1,785 @@
1/*
2 * linux/drivers/video/omap2/omapfb-ioctl.c
3 *
4 * Copyright (C) 2008 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#include <linux/fb.h>
24#include <linux/device.h>
25#include <linux/uaccess.h>
26#include <linux/platform_device.h>
27#include <linux/mm.h>
28#include <linux/omapfb.h>
29#include <linux/vmalloc.h>
30
31#include <plat/display.h>
32#include <plat/vrfb.h>
33#include <plat/vram.h>
34
35#include "omapfb.h"
36
37static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
38{
39 struct omapfb_info *ofbi = FB2OFB(fbi);
40 struct omapfb2_device *fbdev = ofbi->fbdev;
41 struct omap_overlay *ovl;
42 struct omap_overlay_info info;
43 int r = 0;
44
45 DBG("omapfb_setup_plane\n");
46
47 if (ofbi->num_overlays != 1) {
48 r = -EINVAL;
49 goto out;
50 }
51
52 /* XXX uses only the first overlay */
53 ovl = ofbi->overlays[0];
54
55 if (pi->enabled && !ofbi->region.size) {
56 /*
57 * This plane's memory was freed, can't enable it
58 * until it's reallocated.
59 */
60 r = -EINVAL;
61 goto out;
62 }
63
64 ovl->get_overlay_info(ovl, &info);
65
66 info.pos_x = pi->pos_x;
67 info.pos_y = pi->pos_y;
68 info.out_width = pi->out_width;
69 info.out_height = pi->out_height;
70 info.enabled = pi->enabled;
71
72 r = ovl->set_overlay_info(ovl, &info);
73 if (r)
74 goto out;
75
76 if (ovl->manager) {
77 r = ovl->manager->apply(ovl->manager);
78 if (r)
79 goto out;
80 }
81
82out:
83 if (r)
84 dev_err(fbdev->dev, "setup_plane failed\n");
85 return r;
86}
87
88static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
89{
90 struct omapfb_info *ofbi = FB2OFB(fbi);
91
92 if (ofbi->num_overlays != 1) {
93 memset(pi, 0, sizeof(*pi));
94 } else {
95 struct omap_overlay_info *ovli;
96 struct omap_overlay *ovl;
97
98 ovl = ofbi->overlays[0];
99 ovli = &ovl->info;
100
101 pi->pos_x = ovli->pos_x;
102 pi->pos_y = ovli->pos_y;
103 pi->enabled = ovli->enabled;
104 pi->channel_out = 0; /* xxx */
105 pi->mirror = 0;
106 pi->out_width = ovli->out_width;
107 pi->out_height = ovli->out_height;
108 }
109
110 return 0;
111}
112
113static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
114{
115 struct omapfb_info *ofbi = FB2OFB(fbi);
116 struct omapfb2_device *fbdev = ofbi->fbdev;
117 struct omapfb2_mem_region *rg;
118 int r, i;
119 size_t size;
120
121 if (mi->type > OMAPFB_MEMTYPE_MAX)
122 return -EINVAL;
123
124 size = PAGE_ALIGN(mi->size);
125
126 rg = &ofbi->region;
127
128 for (i = 0; i < ofbi->num_overlays; i++) {
129 if (ofbi->overlays[i]->info.enabled)
130 return -EBUSY;
131 }
132
133 if (rg->size != size || rg->type != mi->type) {
134 r = omapfb_realloc_fbmem(fbi, size, mi->type);
135 if (r) {
136 dev_err(fbdev->dev, "realloc fbmem failed\n");
137 return r;
138 }
139 }
140
141 return 0;
142}
143
144static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
145{
146 struct omapfb_info *ofbi = FB2OFB(fbi);
147 struct omapfb2_mem_region *rg;
148
149 rg = &ofbi->region;
150 memset(mi, 0, sizeof(*mi));
151
152 mi->size = rg->size;
153 mi->type = rg->type;
154
155 return 0;
156}
157
158static int omapfb_update_window_nolock(struct fb_info *fbi,
159 u32 x, u32 y, u32 w, u32 h)
160{
161 struct omap_dss_device *display = fb2display(fbi);
162 u16 dw, dh;
163
164 if (!display)
165 return 0;
166
167 if (w == 0 || h == 0)
168 return 0;
169
170 display->driver->get_resolution(display, &dw, &dh);
171
172 if (x + w > dw || y + h > dh)
173 return -EINVAL;
174
175 return display->driver->update(display, x, y, w, h);
176}
177
178/* This function is exported for SGX driver use */
179int omapfb_update_window(struct fb_info *fbi,
180 u32 x, u32 y, u32 w, u32 h)
181{
182 struct omapfb_info *ofbi = FB2OFB(fbi);
183 struct omapfb2_device *fbdev = ofbi->fbdev;
184 int r;
185
186 omapfb_lock(fbdev);
187 lock_fb_info(fbi);
188
189 r = omapfb_update_window_nolock(fbi, x, y, w, h);
190
191 unlock_fb_info(fbi);
192 omapfb_unlock(fbdev);
193
194 return r;
195}
196EXPORT_SYMBOL(omapfb_update_window);
197
198static int omapfb_set_update_mode(struct fb_info *fbi,
199 enum omapfb_update_mode mode)
200{
201 struct omap_dss_device *display = fb2display(fbi);
202 enum omap_dss_update_mode um;
203 int r;
204
205 if (!display || !display->driver->set_update_mode)
206 return -EINVAL;
207
208 switch (mode) {
209 case OMAPFB_UPDATE_DISABLED:
210 um = OMAP_DSS_UPDATE_DISABLED;
211 break;
212
213 case OMAPFB_AUTO_UPDATE:
214 um = OMAP_DSS_UPDATE_AUTO;
215 break;
216
217 case OMAPFB_MANUAL_UPDATE:
218 um = OMAP_DSS_UPDATE_MANUAL;
219 break;
220
221 default:
222 return -EINVAL;
223 }
224
225 r = display->driver->set_update_mode(display, um);
226
227 return r;
228}
229
230static int omapfb_get_update_mode(struct fb_info *fbi,
231 enum omapfb_update_mode *mode)
232{
233 struct omap_dss_device *display = fb2display(fbi);
234 enum omap_dss_update_mode m;
235
236 if (!display)
237 return -EINVAL;
238
239 if (!display->driver->get_update_mode) {
240 *mode = OMAPFB_AUTO_UPDATE;
241 return 0;
242 }
243
244 m = display->driver->get_update_mode(display);
245
246 switch (m) {
247 case OMAP_DSS_UPDATE_DISABLED:
248 *mode = OMAPFB_UPDATE_DISABLED;
249 break;
250 case OMAP_DSS_UPDATE_AUTO:
251 *mode = OMAPFB_AUTO_UPDATE;
252 break;
253 case OMAP_DSS_UPDATE_MANUAL:
254 *mode = OMAPFB_MANUAL_UPDATE;
255 break;
256 default:
257 BUG();
258 }
259
260 return 0;
261}
262
263/* XXX this color key handling is a hack... */
264static struct omapfb_color_key omapfb_color_keys[2];
265
266static int _omapfb_set_color_key(struct omap_overlay_manager *mgr,
267 struct omapfb_color_key *ck)
268{
269 struct omap_overlay_manager_info info;
270 enum omap_dss_trans_key_type kt;
271 int r;
272
273 mgr->get_manager_info(mgr, &info);
274
275 if (ck->key_type == OMAPFB_COLOR_KEY_DISABLED) {
276 info.trans_enabled = false;
277 omapfb_color_keys[mgr->id] = *ck;
278
279 r = mgr->set_manager_info(mgr, &info);
280 if (r)
281 return r;
282
283 r = mgr->apply(mgr);
284
285 return r;
286 }
287
288 switch (ck->key_type) {
289 case OMAPFB_COLOR_KEY_GFX_DST:
290 kt = OMAP_DSS_COLOR_KEY_GFX_DST;
291 break;
292 case OMAPFB_COLOR_KEY_VID_SRC:
293 kt = OMAP_DSS_COLOR_KEY_VID_SRC;
294 break;
295 default:
296 return -EINVAL;
297 }
298
299 info.default_color = ck->background;
300 info.trans_key = ck->trans_key;
301 info.trans_key_type = kt;
302 info.trans_enabled = true;
303
304 omapfb_color_keys[mgr->id] = *ck;
305
306 r = mgr->set_manager_info(mgr, &info);
307 if (r)
308 return r;
309
310 r = mgr->apply(mgr);
311
312 return r;
313}
314
315static int omapfb_set_color_key(struct fb_info *fbi,
316 struct omapfb_color_key *ck)
317{
318 struct omapfb_info *ofbi = FB2OFB(fbi);
319 struct omapfb2_device *fbdev = ofbi->fbdev;
320 int r;
321 int i;
322 struct omap_overlay_manager *mgr = NULL;
323
324 omapfb_lock(fbdev);
325
326 for (i = 0; i < ofbi->num_overlays; i++) {
327 if (ofbi->overlays[i]->manager) {
328 mgr = ofbi->overlays[i]->manager;
329 break;
330 }
331 }
332
333 if (!mgr) {
334 r = -EINVAL;
335 goto err;
336 }
337
338 r = _omapfb_set_color_key(mgr, ck);
339err:
340 omapfb_unlock(fbdev);
341
342 return r;
343}
344
345static int omapfb_get_color_key(struct fb_info *fbi,
346 struct omapfb_color_key *ck)
347{
348 struct omapfb_info *ofbi = FB2OFB(fbi);
349 struct omapfb2_device *fbdev = ofbi->fbdev;
350 struct omap_overlay_manager *mgr = NULL;
351 int r = 0;
352 int i;
353
354 omapfb_lock(fbdev);
355
356 for (i = 0; i < ofbi->num_overlays; i++) {
357 if (ofbi->overlays[i]->manager) {
358 mgr = ofbi->overlays[i]->manager;
359 break;
360 }
361 }
362
363 if (!mgr) {
364 r = -EINVAL;
365 goto err;
366 }
367
368 *ck = omapfb_color_keys[mgr->id];
369err:
370 omapfb_unlock(fbdev);
371
372 return r;
373}
374
375static int omapfb_memory_read(struct fb_info *fbi,
376 struct omapfb_memory_read *mr)
377{
378 struct omap_dss_device *display = fb2display(fbi);
379 void *buf;
380 int r;
381
382 if (!display || !display->driver->memory_read)
383 return -ENOENT;
384
385 if (!access_ok(VERIFY_WRITE, mr->buffer, mr->buffer_size))
386 return -EFAULT;
387
388 if (mr->w * mr->h * 3 > mr->buffer_size)
389 return -EINVAL;
390
391 buf = vmalloc(mr->buffer_size);
392 if (!buf) {
393 DBG("vmalloc failed\n");
394 return -ENOMEM;
395 }
396
397 r = display->driver->memory_read(display, buf, mr->buffer_size,
398 mr->x, mr->y, mr->w, mr->h);
399
400 if (r > 0) {
401 if (copy_to_user(mr->buffer, buf, mr->buffer_size))
402 r = -EFAULT;
403 }
404
405 vfree(buf);
406
407 return r;
408}
409
410static int omapfb_get_ovl_colormode(struct omapfb2_device *fbdev,
411 struct omapfb_ovl_colormode *mode)
412{
413 int ovl_idx = mode->overlay_idx;
414 int mode_idx = mode->mode_idx;
415 struct omap_overlay *ovl;
416 enum omap_color_mode supported_modes;
417 struct fb_var_screeninfo var;
418 int i;
419
420 if (ovl_idx >= fbdev->num_overlays)
421 return -ENODEV;
422 ovl = fbdev->overlays[ovl_idx];
423 supported_modes = ovl->supported_modes;
424
425 mode_idx = mode->mode_idx;
426
427 for (i = 0; i < sizeof(supported_modes) * 8; i++) {
428 if (!(supported_modes & (1 << i)))
429 continue;
430 /*
431 * It's possible that the FB doesn't support a mode
432 * that is supported by the overlay, so call the
433 * following here.
434 */
435 if (dss_mode_to_fb_mode(1 << i, &var) < 0)
436 continue;
437
438 mode_idx--;
439 if (mode_idx < 0)
440 break;
441 }
442
443 if (i == sizeof(supported_modes) * 8)
444 return -ENOENT;
445
446 mode->bits_per_pixel = var.bits_per_pixel;
447 mode->nonstd = var.nonstd;
448 mode->red = var.red;
449 mode->green = var.green;
450 mode->blue = var.blue;
451 mode->transp = var.transp;
452
453 return 0;
454}
455
456static int omapfb_wait_for_go(struct fb_info *fbi)
457{
458 struct omapfb_info *ofbi = FB2OFB(fbi);
459 int r = 0;
460 int i;
461
462 for (i = 0; i < ofbi->num_overlays; ++i) {
463 struct omap_overlay *ovl = ofbi->overlays[i];
464 r = ovl->wait_for_go(ovl);
465 if (r)
466 break;
467 }
468
469 return r;
470}
471
472int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
473{
474 struct omapfb_info *ofbi = FB2OFB(fbi);
475 struct omapfb2_device *fbdev = ofbi->fbdev;
476 struct omap_dss_device *display = fb2display(fbi);
477
478 union {
479 struct omapfb_update_window_old uwnd_o;
480 struct omapfb_update_window uwnd;
481 struct omapfb_plane_info plane_info;
482 struct omapfb_caps caps;
483 struct omapfb_mem_info mem_info;
484 struct omapfb_color_key color_key;
485 struct omapfb_ovl_colormode ovl_colormode;
486 enum omapfb_update_mode update_mode;
487 int test_num;
488 struct omapfb_memory_read memory_read;
489 struct omapfb_vram_info vram_info;
490 struct omapfb_tearsync_info tearsync_info;
491 struct omapfb_display_info display_info;
492 } p;
493
494 int r = 0;
495
496 switch (cmd) {
497 case OMAPFB_SYNC_GFX:
498 DBG("ioctl SYNC_GFX\n");
499 if (!display || !display->driver->sync) {
500 /* DSS1 never returns an error here, so we neither */
501 /*r = -EINVAL;*/
502 break;
503 }
504
505 r = display->driver->sync(display);
506 break;
507
508 case OMAPFB_UPDATE_WINDOW_OLD:
509 DBG("ioctl UPDATE_WINDOW_OLD\n");
510 if (!display || !display->driver->update) {
511 r = -EINVAL;
512 break;
513 }
514
515 if (copy_from_user(&p.uwnd_o,
516 (void __user *)arg,
517 sizeof(p.uwnd_o))) {
518 r = -EFAULT;
519 break;
520 }
521
522 r = omapfb_update_window_nolock(fbi, p.uwnd_o.x, p.uwnd_o.y,
523 p.uwnd_o.width, p.uwnd_o.height);
524 break;
525
526 case OMAPFB_UPDATE_WINDOW:
527 DBG("ioctl UPDATE_WINDOW\n");
528 if (!display || !display->driver->update) {
529 r = -EINVAL;
530 break;
531 }
532
533 if (copy_from_user(&p.uwnd, (void __user *)arg,
534 sizeof(p.uwnd))) {
535 r = -EFAULT;
536 break;
537 }
538
539 r = omapfb_update_window_nolock(fbi, p.uwnd.x, p.uwnd.y,
540 p.uwnd.width, p.uwnd.height);
541 break;
542
543 case OMAPFB_SETUP_PLANE:
544 DBG("ioctl SETUP_PLANE\n");
545 if (copy_from_user(&p.plane_info, (void __user *)arg,
546 sizeof(p.plane_info)))
547 r = -EFAULT;
548 else
549 r = omapfb_setup_plane(fbi, &p.plane_info);
550 break;
551
552 case OMAPFB_QUERY_PLANE:
553 DBG("ioctl QUERY_PLANE\n");
554 r = omapfb_query_plane(fbi, &p.plane_info);
555 if (r < 0)
556 break;
557 if (copy_to_user((void __user *)arg, &p.plane_info,
558 sizeof(p.plane_info)))
559 r = -EFAULT;
560 break;
561
562 case OMAPFB_SETUP_MEM:
563 DBG("ioctl SETUP_MEM\n");
564 if (copy_from_user(&p.mem_info, (void __user *)arg,
565 sizeof(p.mem_info)))
566 r = -EFAULT;
567 else
568 r = omapfb_setup_mem(fbi, &p.mem_info);
569 break;
570
571 case OMAPFB_QUERY_MEM:
572 DBG("ioctl QUERY_MEM\n");
573 r = omapfb_query_mem(fbi, &p.mem_info);
574 if (r < 0)
575 break;
576 if (copy_to_user((void __user *)arg, &p.mem_info,
577 sizeof(p.mem_info)))
578 r = -EFAULT;
579 break;
580
581 case OMAPFB_GET_CAPS:
582 DBG("ioctl GET_CAPS\n");
583 if (!display) {
584 r = -EINVAL;
585 break;
586 }
587
588 memset(&p.caps, 0, sizeof(p.caps));
589 if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
590 p.caps.ctrl |= OMAPFB_CAPS_MANUAL_UPDATE;
591 if (display->caps & OMAP_DSS_DISPLAY_CAP_TEAR_ELIM)
592 p.caps.ctrl |= OMAPFB_CAPS_TEARSYNC;
593
594 if (copy_to_user((void __user *)arg, &p.caps, sizeof(p.caps)))
595 r = -EFAULT;
596 break;
597
598 case OMAPFB_GET_OVERLAY_COLORMODE:
599 DBG("ioctl GET_OVERLAY_COLORMODE\n");
600 if (copy_from_user(&p.ovl_colormode, (void __user *)arg,
601 sizeof(p.ovl_colormode))) {
602 r = -EFAULT;
603 break;
604 }
605 r = omapfb_get_ovl_colormode(fbdev, &p.ovl_colormode);
606 if (r < 0)
607 break;
608 if (copy_to_user((void __user *)arg, &p.ovl_colormode,
609 sizeof(p.ovl_colormode)))
610 r = -EFAULT;
611 break;
612
613 case OMAPFB_SET_UPDATE_MODE:
614 DBG("ioctl SET_UPDATE_MODE\n");
615 if (get_user(p.update_mode, (int __user *)arg))
616 r = -EFAULT;
617 else
618 r = omapfb_set_update_mode(fbi, p.update_mode);
619 break;
620
621 case OMAPFB_GET_UPDATE_MODE:
622 DBG("ioctl GET_UPDATE_MODE\n");
623 r = omapfb_get_update_mode(fbi, &p.update_mode);
624 if (r)
625 break;
626 if (put_user(p.update_mode,
627 (enum omapfb_update_mode __user *)arg))
628 r = -EFAULT;
629 break;
630
631 case OMAPFB_SET_COLOR_KEY:
632 DBG("ioctl SET_COLOR_KEY\n");
633 if (copy_from_user(&p.color_key, (void __user *)arg,
634 sizeof(p.color_key)))
635 r = -EFAULT;
636 else
637 r = omapfb_set_color_key(fbi, &p.color_key);
638 break;
639
640 case OMAPFB_GET_COLOR_KEY:
641 DBG("ioctl GET_COLOR_KEY\n");
642 r = omapfb_get_color_key(fbi, &p.color_key);
643 if (r)
644 break;
645 if (copy_to_user((void __user *)arg, &p.color_key,
646 sizeof(p.color_key)))
647 r = -EFAULT;
648 break;
649
650 case OMAPFB_WAITFORVSYNC:
651 DBG("ioctl WAITFORVSYNC\n");
652 if (!display) {
653 r = -EINVAL;
654 break;
655 }
656
657 r = display->manager->wait_for_vsync(display->manager);
658 break;
659
660 case OMAPFB_WAITFORGO:
661 DBG("ioctl WAITFORGO\n");
662 if (!display) {
663 r = -EINVAL;
664 break;
665 }
666
667 r = omapfb_wait_for_go(fbi);
668 break;
669
670 /* LCD and CTRL tests do the same thing for backward
671 * compatibility */
672 case OMAPFB_LCD_TEST:
673 DBG("ioctl LCD_TEST\n");
674 if (get_user(p.test_num, (int __user *)arg)) {
675 r = -EFAULT;
676 break;
677 }
678 if (!display || !display->driver->run_test) {
679 r = -EINVAL;
680 break;
681 }
682
683 r = display->driver->run_test(display, p.test_num);
684
685 break;
686
687 case OMAPFB_CTRL_TEST:
688 DBG("ioctl CTRL_TEST\n");
689 if (get_user(p.test_num, (int __user *)arg)) {
690 r = -EFAULT;
691 break;
692 }
693 if (!display || !display->driver->run_test) {
694 r = -EINVAL;
695 break;
696 }
697
698 r = display->driver->run_test(display, p.test_num);
699
700 break;
701
702 case OMAPFB_MEMORY_READ:
703 DBG("ioctl MEMORY_READ\n");
704
705 if (copy_from_user(&p.memory_read, (void __user *)arg,
706 sizeof(p.memory_read))) {
707 r = -EFAULT;
708 break;
709 }
710
711 r = omapfb_memory_read(fbi, &p.memory_read);
712
713 break;
714
715 case OMAPFB_GET_VRAM_INFO: {
716 unsigned long vram, free, largest;
717
718 DBG("ioctl GET_VRAM_INFO\n");
719
720 omap_vram_get_info(&vram, &free, &largest);
721 p.vram_info.total = vram;
722 p.vram_info.free = free;
723 p.vram_info.largest_free_block = largest;
724
725 if (copy_to_user((void __user *)arg, &p.vram_info,
726 sizeof(p.vram_info)))
727 r = -EFAULT;
728 break;
729 }
730
731 case OMAPFB_SET_TEARSYNC: {
732 DBG("ioctl SET_TEARSYNC\n");
733
734 if (copy_from_user(&p.tearsync_info, (void __user *)arg,
735 sizeof(p.tearsync_info))) {
736 r = -EFAULT;
737 break;
738 }
739
740 if (!display->driver->enable_te) {
741 r = -ENODEV;
742 break;
743 }
744
745 r = display->driver->enable_te(display,
746 !!p.tearsync_info.enabled);
747
748 break;
749 }
750
751 case OMAPFB_GET_DISPLAY_INFO: {
752 u16 xres, yres;
753
754 DBG("ioctl GET_DISPLAY_INFO\n");
755
756 if (display == NULL) {
757 r = -ENODEV;
758 break;
759 }
760
761 display->driver->get_resolution(display, &xres, &yres);
762
763 p.display_info.xres = xres;
764 p.display_info.yres = yres;
765 p.display_info.width = 0;
766 p.display_info.height = 0;
767
768 if (copy_to_user((void __user *)arg, &p.display_info,
769 sizeof(p.display_info)))
770 r = -EFAULT;
771 break;
772 }
773
774 default:
775 dev_err(fbdev->dev, "Unknown ioctl 0x%x\n", cmd);
776 r = -EINVAL;
777 }
778
779 if (r < 0)
780 DBG("ioctl failed: %d\n", r);
781
782 return r;
783}
784
785
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
new file mode 100644
index 000000000000..4b4506da96da
--- /dev/null
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -0,0 +1,2287 @@
1/*
2 * linux/drivers/video/omap2/omapfb-main.c
3 *
4 * Copyright (C) 2008 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#include <linux/module.h>
24#include <linux/delay.h>
25#include <linux/slab.h>
26#include <linux/fb.h>
27#include <linux/dma-mapping.h>
28#include <linux/vmalloc.h>
29#include <linux/device.h>
30#include <linux/platform_device.h>
31#include <linux/omapfb.h>
32
33#include <plat/display.h>
34#include <plat/vram.h>
35#include <plat/vrfb.h>
36
37#include "omapfb.h"
38
39#define MODULE_NAME "omapfb"
40
41#define OMAPFB_PLANE_XRES_MIN 8
42#define OMAPFB_PLANE_YRES_MIN 8
43
44static char *def_mode;
45static char *def_vram;
46static int def_vrfb;
47static int def_rotate;
48static int def_mirror;
49
50#ifdef DEBUG
51unsigned int omapfb_debug;
52module_param_named(debug, omapfb_debug, bool, 0644);
53static unsigned int omapfb_test_pattern;
54module_param_named(test, omapfb_test_pattern, bool, 0644);
55#endif
56
57static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi);
58static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
59 struct omap_dss_device *dssdev);
60
61#ifdef DEBUG
62static void draw_pixel(struct fb_info *fbi, int x, int y, unsigned color)
63{
64 struct fb_var_screeninfo *var = &fbi->var;
65 struct fb_fix_screeninfo *fix = &fbi->fix;
66 void __iomem *addr = fbi->screen_base;
67 const unsigned bytespp = var->bits_per_pixel >> 3;
68 const unsigned line_len = fix->line_length / bytespp;
69
70 int r = (color >> 16) & 0xff;
71 int g = (color >> 8) & 0xff;
72 int b = (color >> 0) & 0xff;
73
74 if (var->bits_per_pixel == 16) {
75 u16 __iomem *p = (u16 __iomem *)addr;
76 p += y * line_len + x;
77
78 r = r * 32 / 256;
79 g = g * 64 / 256;
80 b = b * 32 / 256;
81
82 __raw_writew((r << 11) | (g << 5) | (b << 0), p);
83 } else if (var->bits_per_pixel == 24) {
84 u8 __iomem *p = (u8 __iomem *)addr;
85 p += (y * line_len + x) * 3;
86
87 __raw_writeb(b, p + 0);
88 __raw_writeb(g, p + 1);
89 __raw_writeb(r, p + 2);
90 } else if (var->bits_per_pixel == 32) {
91 u32 __iomem *p = (u32 __iomem *)addr;
92 p += y * line_len + x;
93 __raw_writel(color, p);
94 }
95}
96
97static void fill_fb(struct fb_info *fbi)
98{
99 struct fb_var_screeninfo *var = &fbi->var;
100 const short w = var->xres_virtual;
101 const short h = var->yres_virtual;
102 void __iomem *addr = fbi->screen_base;
103 int y, x;
104
105 if (!addr)
106 return;
107
108 DBG("fill_fb %dx%d, line_len %d bytes\n", w, h, fbi->fix.line_length);
109
110 for (y = 0; y < h; y++) {
111 for (x = 0; x < w; x++) {
112 if (x < 20 && y < 20)
113 draw_pixel(fbi, x, y, 0xffffff);
114 else if (x < 20 && (y > 20 && y < h - 20))
115 draw_pixel(fbi, x, y, 0xff);
116 else if (y < 20 && (x > 20 && x < w - 20))
117 draw_pixel(fbi, x, y, 0xff00);
118 else if (x > w - 20 && (y > 20 && y < h - 20))
119 draw_pixel(fbi, x, y, 0xff0000);
120 else if (y > h - 20 && (x > 20 && x < w - 20))
121 draw_pixel(fbi, x, y, 0xffff00);
122 else if (x == 20 || x == w - 20 ||
123 y == 20 || y == h - 20)
124 draw_pixel(fbi, x, y, 0xffffff);
125 else if (x == y || w - x == h - y)
126 draw_pixel(fbi, x, y, 0xff00ff);
127 else if (w - x == y || x == h - y)
128 draw_pixel(fbi, x, y, 0x00ffff);
129 else if (x > 20 && y > 20 && x < w - 20 && y < h - 20) {
130 int t = x * 3 / w;
131 unsigned r = 0, g = 0, b = 0;
132 unsigned c;
133 if (var->bits_per_pixel == 16) {
134 if (t == 0)
135 b = (y % 32) * 256 / 32;
136 else if (t == 1)
137 g = (y % 64) * 256 / 64;
138 else if (t == 2)
139 r = (y % 32) * 256 / 32;
140 } else {
141 if (t == 0)
142 b = (y % 256);
143 else if (t == 1)
144 g = (y % 256);
145 else if (t == 2)
146 r = (y % 256);
147 }
148 c = (r << 16) | (g << 8) | (b << 0);
149 draw_pixel(fbi, x, y, c);
150 } else {
151 draw_pixel(fbi, x, y, 0);
152 }
153 }
154 }
155}
156#endif
157
158static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot)
159{
160 const struct vrfb *vrfb = &ofbi->region.vrfb;
161 unsigned offset;
162
163 switch (rot) {
164 case FB_ROTATE_UR:
165 offset = 0;
166 break;
167 case FB_ROTATE_CW:
168 offset = vrfb->yoffset;
169 break;
170 case FB_ROTATE_UD:
171 offset = vrfb->yoffset * OMAP_VRFB_LINE_LEN + vrfb->xoffset;
172 break;
173 case FB_ROTATE_CCW:
174 offset = vrfb->xoffset * OMAP_VRFB_LINE_LEN;
175 break;
176 default:
177 BUG();
178 }
179
180 offset *= vrfb->bytespp;
181
182 return offset;
183}
184
185static u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot)
186{
187 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
188 return ofbi->region.vrfb.paddr[rot]
189 + omapfb_get_vrfb_offset(ofbi, rot);
190 } else {
191 return ofbi->region.paddr;
192 }
193}
194
195static u32 omapfb_get_region_paddr(const struct omapfb_info *ofbi)
196{
197 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
198 return ofbi->region.vrfb.paddr[0];
199 else
200 return ofbi->region.paddr;
201}
202
203static void __iomem *omapfb_get_region_vaddr(const struct omapfb_info *ofbi)
204{
205 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
206 return ofbi->region.vrfb.vaddr[0];
207 else
208 return ofbi->region.vaddr;
209}
210
211static struct omapfb_colormode omapfb_colormodes[] = {
212 {
213 .dssmode = OMAP_DSS_COLOR_UYVY,
214 .bits_per_pixel = 16,
215 .nonstd = OMAPFB_COLOR_YUV422,
216 }, {
217 .dssmode = OMAP_DSS_COLOR_YUV2,
218 .bits_per_pixel = 16,
219 .nonstd = OMAPFB_COLOR_YUY422,
220 }, {
221 .dssmode = OMAP_DSS_COLOR_ARGB16,
222 .bits_per_pixel = 16,
223 .red = { .length = 4, .offset = 8, .msb_right = 0 },
224 .green = { .length = 4, .offset = 4, .msb_right = 0 },
225 .blue = { .length = 4, .offset = 0, .msb_right = 0 },
226 .transp = { .length = 4, .offset = 12, .msb_right = 0 },
227 }, {
228 .dssmode = OMAP_DSS_COLOR_RGB16,
229 .bits_per_pixel = 16,
230 .red = { .length = 5, .offset = 11, .msb_right = 0 },
231 .green = { .length = 6, .offset = 5, .msb_right = 0 },
232 .blue = { .length = 5, .offset = 0, .msb_right = 0 },
233 .transp = { .length = 0, .offset = 0, .msb_right = 0 },
234 }, {
235 .dssmode = OMAP_DSS_COLOR_RGB24P,
236 .bits_per_pixel = 24,
237 .red = { .length = 8, .offset = 16, .msb_right = 0 },
238 .green = { .length = 8, .offset = 8, .msb_right = 0 },
239 .blue = { .length = 8, .offset = 0, .msb_right = 0 },
240 .transp = { .length = 0, .offset = 0, .msb_right = 0 },
241 }, {
242 .dssmode = OMAP_DSS_COLOR_RGB24U,
243 .bits_per_pixel = 32,
244 .red = { .length = 8, .offset = 16, .msb_right = 0 },
245 .green = { .length = 8, .offset = 8, .msb_right = 0 },
246 .blue = { .length = 8, .offset = 0, .msb_right = 0 },
247 .transp = { .length = 0, .offset = 0, .msb_right = 0 },
248 }, {
249 .dssmode = OMAP_DSS_COLOR_ARGB32,
250 .bits_per_pixel = 32,
251 .red = { .length = 8, .offset = 16, .msb_right = 0 },
252 .green = { .length = 8, .offset = 8, .msb_right = 0 },
253 .blue = { .length = 8, .offset = 0, .msb_right = 0 },
254 .transp = { .length = 8, .offset = 24, .msb_right = 0 },
255 }, {
256 .dssmode = OMAP_DSS_COLOR_RGBA32,
257 .bits_per_pixel = 32,
258 .red = { .length = 8, .offset = 24, .msb_right = 0 },
259 .green = { .length = 8, .offset = 16, .msb_right = 0 },
260 .blue = { .length = 8, .offset = 8, .msb_right = 0 },
261 .transp = { .length = 8, .offset = 0, .msb_right = 0 },
262 }, {
263 .dssmode = OMAP_DSS_COLOR_RGBX32,
264 .bits_per_pixel = 32,
265 .red = { .length = 8, .offset = 24, .msb_right = 0 },
266 .green = { .length = 8, .offset = 16, .msb_right = 0 },
267 .blue = { .length = 8, .offset = 8, .msb_right = 0 },
268 .transp = { .length = 0, .offset = 0, .msb_right = 0 },
269 },
270};
271
272static bool cmp_var_to_colormode(struct fb_var_screeninfo *var,
273 struct omapfb_colormode *color)
274{
275 bool cmp_component(struct fb_bitfield *f1, struct fb_bitfield *f2)
276 {
277 return f1->length == f2->length &&
278 f1->offset == f2->offset &&
279 f1->msb_right == f2->msb_right;
280 }
281
282 if (var->bits_per_pixel == 0 ||
283 var->red.length == 0 ||
284 var->blue.length == 0 ||
285 var->green.length == 0)
286 return 0;
287
288 return var->bits_per_pixel == color->bits_per_pixel &&
289 cmp_component(&var->red, &color->red) &&
290 cmp_component(&var->green, &color->green) &&
291 cmp_component(&var->blue, &color->blue) &&
292 cmp_component(&var->transp, &color->transp);
293}
294
295static void assign_colormode_to_var(struct fb_var_screeninfo *var,
296 struct omapfb_colormode *color)
297{
298 var->bits_per_pixel = color->bits_per_pixel;
299 var->nonstd = color->nonstd;
300 var->red = color->red;
301 var->green = color->green;
302 var->blue = color->blue;
303 var->transp = color->transp;
304}
305
306static int fb_mode_to_dss_mode(struct fb_var_screeninfo *var,
307 enum omap_color_mode *mode)
308{
309 enum omap_color_mode dssmode;
310 int i;
311
312 /* first match with nonstd field */
313 if (var->nonstd) {
314 for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
315 struct omapfb_colormode *m = &omapfb_colormodes[i];
316 if (var->nonstd == m->nonstd) {
317 assign_colormode_to_var(var, m);
318 *mode = m->dssmode;
319 return 0;
320 }
321 }
322
323 return -EINVAL;
324 }
325
326 /* then try exact match of bpp and colors */
327 for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
328 struct omapfb_colormode *m = &omapfb_colormodes[i];
329 if (cmp_var_to_colormode(var, m)) {
330 assign_colormode_to_var(var, m);
331 *mode = m->dssmode;
332 return 0;
333 }
334 }
335
336 /* match with bpp if user has not filled color fields
337 * properly */
338 switch (var->bits_per_pixel) {
339 case 1:
340 dssmode = OMAP_DSS_COLOR_CLUT1;
341 break;
342 case 2:
343 dssmode = OMAP_DSS_COLOR_CLUT2;
344 break;
345 case 4:
346 dssmode = OMAP_DSS_COLOR_CLUT4;
347 break;
348 case 8:
349 dssmode = OMAP_DSS_COLOR_CLUT8;
350 break;
351 case 12:
352 dssmode = OMAP_DSS_COLOR_RGB12U;
353 break;
354 case 16:
355 dssmode = OMAP_DSS_COLOR_RGB16;
356 break;
357 case 24:
358 dssmode = OMAP_DSS_COLOR_RGB24P;
359 break;
360 case 32:
361 dssmode = OMAP_DSS_COLOR_RGB24U;
362 break;
363 default:
364 return -EINVAL;
365 }
366
367 for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
368 struct omapfb_colormode *m = &omapfb_colormodes[i];
369 if (dssmode == m->dssmode) {
370 assign_colormode_to_var(var, m);
371 *mode = m->dssmode;
372 return 0;
373 }
374 }
375
376 return -EINVAL;
377}
378
379static int check_fb_res_bounds(struct fb_var_screeninfo *var)
380{
381 int xres_min = OMAPFB_PLANE_XRES_MIN;
382 int xres_max = 2048;
383 int yres_min = OMAPFB_PLANE_YRES_MIN;
384 int yres_max = 2048;
385
386 /* XXX: some applications seem to set virtual res to 0. */
387 if (var->xres_virtual == 0)
388 var->xres_virtual = var->xres;
389
390 if (var->yres_virtual == 0)
391 var->yres_virtual = var->yres;
392
393 if (var->xres_virtual < xres_min || var->yres_virtual < yres_min)
394 return -EINVAL;
395
396 if (var->xres < xres_min)
397 var->xres = xres_min;
398 if (var->yres < yres_min)
399 var->yres = yres_min;
400 if (var->xres > xres_max)
401 var->xres = xres_max;
402 if (var->yres > yres_max)
403 var->yres = yres_max;
404
405 if (var->xres > var->xres_virtual)
406 var->xres = var->xres_virtual;
407 if (var->yres > var->yres_virtual)
408 var->yres = var->yres_virtual;
409
410 return 0;
411}
412
413static void shrink_height(unsigned long max_frame_size,
414 struct fb_var_screeninfo *var)
415{
416 DBG("can't fit FB into memory, reducing y\n");
417 var->yres_virtual = max_frame_size /
418 (var->xres_virtual * var->bits_per_pixel >> 3);
419
420 if (var->yres_virtual < OMAPFB_PLANE_YRES_MIN)
421 var->yres_virtual = OMAPFB_PLANE_YRES_MIN;
422
423 if (var->yres > var->yres_virtual)
424 var->yres = var->yres_virtual;
425}
426
427static void shrink_width(unsigned long max_frame_size,
428 struct fb_var_screeninfo *var)
429{
430 DBG("can't fit FB into memory, reducing x\n");
431 var->xres_virtual = max_frame_size / var->yres_virtual /
432 (var->bits_per_pixel >> 3);
433
434 if (var->xres_virtual < OMAPFB_PLANE_XRES_MIN)
435 var->xres_virtual = OMAPFB_PLANE_XRES_MIN;
436
437 if (var->xres > var->xres_virtual)
438 var->xres = var->xres_virtual;
439}
440
441static int check_vrfb_fb_size(unsigned long region_size,
442 const struct fb_var_screeninfo *var)
443{
444 unsigned long min_phys_size = omap_vrfb_min_phys_size(var->xres_virtual,
445 var->yres_virtual, var->bits_per_pixel >> 3);
446
447 return min_phys_size > region_size ? -EINVAL : 0;
448}
449
450static int check_fb_size(const struct omapfb_info *ofbi,
451 struct fb_var_screeninfo *var)
452{
453 unsigned long max_frame_size = ofbi->region.size;
454 int bytespp = var->bits_per_pixel >> 3;
455 unsigned long line_size = var->xres_virtual * bytespp;
456
457 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
458 /* One needs to check for both VRFB and OMAPFB limitations. */
459 if (check_vrfb_fb_size(max_frame_size, var))
460 shrink_height(omap_vrfb_max_height(
461 max_frame_size, var->xres_virtual, bytespp) *
462 line_size, var);
463
464 if (check_vrfb_fb_size(max_frame_size, var)) {
465 DBG("cannot fit FB to memory\n");
466 return -EINVAL;
467 }
468
469 return 0;
470 }
471
472 DBG("max frame size %lu, line size %lu\n", max_frame_size, line_size);
473
474 if (line_size * var->yres_virtual > max_frame_size)
475 shrink_height(max_frame_size, var);
476
477 if (line_size * var->yres_virtual > max_frame_size) {
478 shrink_width(max_frame_size, var);
479 line_size = var->xres_virtual * bytespp;
480 }
481
482 if (line_size * var->yres_virtual > max_frame_size) {
483 DBG("cannot fit FB to memory\n");
484 return -EINVAL;
485 }
486
487 return 0;
488}
489
490/*
491 * Consider if VRFB assisted rotation is in use and if the virtual space for
492 * the zero degree view needs to be mapped. The need for mapping also acts as
493 * the trigger for setting up the hardware on the context in question. This
494 * ensures that one does not attempt to access the virtual view before the
495 * hardware is serving the address translations.
496 */
497static int setup_vrfb_rotation(struct fb_info *fbi)
498{
499 struct omapfb_info *ofbi = FB2OFB(fbi);
500 struct omapfb2_mem_region *rg = &ofbi->region;
501 struct vrfb *vrfb = &rg->vrfb;
502 struct fb_var_screeninfo *var = &fbi->var;
503 struct fb_fix_screeninfo *fix = &fbi->fix;
504 unsigned bytespp;
505 bool yuv_mode;
506 enum omap_color_mode mode;
507 int r;
508 bool reconf;
509
510 if (!rg->size || ofbi->rotation_type != OMAP_DSS_ROT_VRFB)
511 return 0;
512
513 DBG("setup_vrfb_rotation\n");
514
515 r = fb_mode_to_dss_mode(var, &mode);
516 if (r)
517 return r;
518
519 bytespp = var->bits_per_pixel >> 3;
520
521 yuv_mode = mode == OMAP_DSS_COLOR_YUV2 || mode == OMAP_DSS_COLOR_UYVY;
522
523 /* We need to reconfigure VRFB if the resolution changes, if yuv mode
524 * is enabled/disabled, or if bytes per pixel changes */
525
526 /* XXX we shouldn't allow this when framebuffer is mmapped */
527
528 reconf = false;
529
530 if (yuv_mode != vrfb->yuv_mode)
531 reconf = true;
532 else if (bytespp != vrfb->bytespp)
533 reconf = true;
534 else if (vrfb->xres != var->xres_virtual ||
535 vrfb->yres != var->yres_virtual)
536 reconf = true;
537
538 if (vrfb->vaddr[0] && reconf) {
539 fbi->screen_base = NULL;
540 fix->smem_start = 0;
541 fix->smem_len = 0;
542 iounmap(vrfb->vaddr[0]);
543 vrfb->vaddr[0] = NULL;
544 DBG("setup_vrfb_rotation: reset fb\n");
545 }
546
547 if (vrfb->vaddr[0])
548 return 0;
549
550 omap_vrfb_setup(&rg->vrfb, rg->paddr,
551 var->xres_virtual,
552 var->yres_virtual,
553 bytespp, yuv_mode);
554
555 /* Now one can ioremap the 0 angle view */
556 r = omap_vrfb_map_angle(vrfb, var->yres_virtual, 0);
557 if (r)
558 return r;
559
560 /* used by open/write in fbmem.c */
561 fbi->screen_base = ofbi->region.vrfb.vaddr[0];
562
563 fix->smem_start = ofbi->region.vrfb.paddr[0];
564
565 switch (var->nonstd) {
566 case OMAPFB_COLOR_YUV422:
567 case OMAPFB_COLOR_YUY422:
568 fix->line_length =
569 (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2;
570 break;
571 default:
572 fix->line_length =
573 (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
574 break;
575 }
576
577 fix->smem_len = var->yres_virtual * fix->line_length;
578
579 return 0;
580}
581
582int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
583 struct fb_var_screeninfo *var)
584{
585 int i;
586
587 for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) {
588 struct omapfb_colormode *mode = &omapfb_colormodes[i];
589 if (dssmode == mode->dssmode) {
590 assign_colormode_to_var(var, mode);
591 return 0;
592 }
593 }
594 return -ENOENT;
595}
596
597void set_fb_fix(struct fb_info *fbi)
598{
599 struct fb_fix_screeninfo *fix = &fbi->fix;
600 struct fb_var_screeninfo *var = &fbi->var;
601 struct omapfb_info *ofbi = FB2OFB(fbi);
602 struct omapfb2_mem_region *rg = &ofbi->region;
603
604 DBG("set_fb_fix\n");
605
606 /* used by open/write in fbmem.c */
607 fbi->screen_base = (char __iomem *)omapfb_get_region_vaddr(ofbi);
608
609 /* used by mmap in fbmem.c */
610 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
611 switch (var->nonstd) {
612 case OMAPFB_COLOR_YUV422:
613 case OMAPFB_COLOR_YUY422:
614 fix->line_length =
615 (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2;
616 break;
617 default:
618 fix->line_length =
619 (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
620 break;
621 }
622
623 fix->smem_len = var->yres_virtual * fix->line_length;
624 } else {
625 fix->line_length =
626 (var->xres_virtual * var->bits_per_pixel) >> 3;
627 fix->smem_len = rg->size;
628 }
629
630 fix->smem_start = omapfb_get_region_paddr(ofbi);
631
632 fix->type = FB_TYPE_PACKED_PIXELS;
633
634 if (var->nonstd)
635 fix->visual = FB_VISUAL_PSEUDOCOLOR;
636 else {
637 switch (var->bits_per_pixel) {
638 case 32:
639 case 24:
640 case 16:
641 case 12:
642 fix->visual = FB_VISUAL_TRUECOLOR;
643 /* 12bpp is stored in 16 bits */
644 break;
645 case 1:
646 case 2:
647 case 4:
648 case 8:
649 fix->visual = FB_VISUAL_PSEUDOCOLOR;
650 break;
651 }
652 }
653
654 fix->accel = FB_ACCEL_NONE;
655
656 fix->xpanstep = 1;
657 fix->ypanstep = 1;
658}
659
660/* check new var and possibly modify it to be ok */
661int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
662{
663 struct omapfb_info *ofbi = FB2OFB(fbi);
664 struct omap_dss_device *display = fb2display(fbi);
665 enum omap_color_mode mode = 0;
666 int i;
667 int r;
668
669 DBG("check_fb_var %d\n", ofbi->id);
670
671 if (ofbi->region.size == 0)
672 return 0;
673
674 r = fb_mode_to_dss_mode(var, &mode);
675 if (r) {
676 DBG("cannot convert var to omap dss mode\n");
677 return r;
678 }
679
680 for (i = 0; i < ofbi->num_overlays; ++i) {
681 if ((ofbi->overlays[i]->supported_modes & mode) == 0) {
682 DBG("invalid mode\n");
683 return -EINVAL;
684 }
685 }
686
687 if (var->rotate < 0 || var->rotate > 3)
688 return -EINVAL;
689
690 if (check_fb_res_bounds(var))
691 return -EINVAL;
692
693 if (check_fb_size(ofbi, var))
694 return -EINVAL;
695
696 if (var->xres + var->xoffset > var->xres_virtual)
697 var->xoffset = var->xres_virtual - var->xres;
698 if (var->yres + var->yoffset > var->yres_virtual)
699 var->yoffset = var->yres_virtual - var->yres;
700
701 DBG("xres = %d, yres = %d, vxres = %d, vyres = %d\n",
702 var->xres, var->yres,
703 var->xres_virtual, var->yres_virtual);
704
705 var->height = -1;
706 var->width = -1;
707 var->grayscale = 0;
708
709 if (display && display->driver->get_timings) {
710 struct omap_video_timings timings;
711 display->driver->get_timings(display, &timings);
712
713 /* pixclock in ps, the rest in pixclock */
714 var->pixclock = timings.pixel_clock != 0 ?
715 KHZ2PICOS(timings.pixel_clock) :
716 0;
717 var->left_margin = timings.hfp;
718 var->right_margin = timings.hbp;
719 var->upper_margin = timings.vfp;
720 var->lower_margin = timings.vbp;
721 var->hsync_len = timings.hsw;
722 var->vsync_len = timings.vsw;
723 } else {
724 var->pixclock = 0;
725 var->left_margin = 0;
726 var->right_margin = 0;
727 var->upper_margin = 0;
728 var->lower_margin = 0;
729 var->hsync_len = 0;
730 var->vsync_len = 0;
731 }
732
733 /* TODO: get these from panel->config */
734 var->vmode = FB_VMODE_NONINTERLACED;
735 var->sync = 0;
736
737 return 0;
738}
739
740/*
741 * ---------------------------------------------------------------------------
742 * fbdev framework callbacks
743 * ---------------------------------------------------------------------------
744 */
745static int omapfb_open(struct fb_info *fbi, int user)
746{
747 return 0;
748}
749
750static int omapfb_release(struct fb_info *fbi, int user)
751{
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;
782}
783
784static unsigned calc_rotation_offset_dma(const struct fb_var_screeninfo *var,
785 const struct fb_fix_screeninfo *fix, int rotation)
786{
787 unsigned offset;
788
789 offset = var->yoffset * fix->line_length +
790 var->xoffset * (var->bits_per_pixel >> 3);
791
792 return offset;
793}
794
795static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var,
796 const struct fb_fix_screeninfo *fix, int rotation)
797{
798 unsigned offset;
799
800 if (rotation == FB_ROTATE_UD)
801 offset = (var->yres_virtual - var->yres) *
802 fix->line_length;
803 else if (rotation == FB_ROTATE_CW)
804 offset = (var->yres_virtual - var->yres) *
805 (var->bits_per_pixel >> 3);
806 else
807 offset = 0;
808
809 if (rotation == FB_ROTATE_UR)
810 offset += var->yoffset * fix->line_length +
811 var->xoffset * (var->bits_per_pixel >> 3);
812 else if (rotation == FB_ROTATE_UD)
813 offset -= var->yoffset * fix->line_length +
814 var->xoffset * (var->bits_per_pixel >> 3);
815 else if (rotation == FB_ROTATE_CW)
816 offset -= var->xoffset * fix->line_length +
817 var->yoffset * (var->bits_per_pixel >> 3);
818 else if (rotation == FB_ROTATE_CCW)
819 offset += var->xoffset * fix->line_length +
820 var->yoffset * (var->bits_per_pixel >> 3);
821
822 return offset;
823}
824
825
826/* setup overlay according to the fb */
827static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
828 u16 posx, u16 posy, u16 outw, u16 outh)
829{
830 int r = 0;
831 struct omapfb_info *ofbi = FB2OFB(fbi);
832 struct fb_var_screeninfo *var = &fbi->var;
833 struct fb_fix_screeninfo *fix = &fbi->fix;
834 enum omap_color_mode mode = 0;
835 int offset;
836 u32 data_start_p;
837 void __iomem *data_start_v;
838 struct omap_overlay_info info;
839 int xres, yres;
840 int screen_width;
841 int mirror;
842 int rotation = var->rotate;
843 int i;
844
845 for (i = 0; i < ofbi->num_overlays; i++) {
846 if (ovl != ofbi->overlays[i])
847 continue;
848
849 rotation = (rotation + ofbi->rotation[i]) % 4;
850 break;
851 }
852
853 DBG("setup_overlay %d, posx %d, posy %d, outw %d, outh %d\n", ofbi->id,
854 posx, posy, outw, outh);
855
856 if (rotation == FB_ROTATE_CW || rotation == FB_ROTATE_CCW) {
857 xres = var->yres;
858 yres = var->xres;
859 } else {
860 xres = var->xres;
861 yres = var->yres;
862 }
863
864
865 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
866 data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
867 data_start_v = NULL;
868 } else {
869 data_start_p = omapfb_get_region_paddr(ofbi);
870 data_start_v = omapfb_get_region_vaddr(ofbi);
871 }
872
873 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
874 offset = calc_rotation_offset_vrfb(var, fix, rotation);
875 else
876 offset = calc_rotation_offset_dma(var, fix, rotation);
877
878 data_start_p += offset;
879 data_start_v += offset;
880
881 if (offset)
882 DBG("offset %d, %d = %d\n",
883 var->xoffset, var->yoffset, offset);
884
885 DBG("paddr %x, vaddr %p\n", data_start_p, data_start_v);
886
887 r = fb_mode_to_dss_mode(var, &mode);
888 if (r) {
889 DBG("fb_mode_to_dss_mode failed");
890 goto err;
891 }
892
893 switch (var->nonstd) {
894 case OMAPFB_COLOR_YUV422:
895 case OMAPFB_COLOR_YUY422:
896 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
897 screen_width = fix->line_length
898 / (var->bits_per_pixel >> 2);
899 break;
900 }
901 default:
902 screen_width = fix->line_length / (var->bits_per_pixel >> 3);
903 break;
904 }
905
906 ovl->get_overlay_info(ovl, &info);
907
908 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
909 mirror = 0;
910 else
911 mirror = ofbi->mirror;
912
913 info.paddr = data_start_p;
914 info.vaddr = data_start_v;
915 info.screen_width = screen_width;
916 info.width = xres;
917 info.height = yres;
918 info.color_mode = mode;
919 info.rotation_type = ofbi->rotation_type;
920 info.rotation = rotation;
921 info.mirror = mirror;
922
923 info.pos_x = posx;
924 info.pos_y = posy;
925 info.out_width = outw;
926 info.out_height = outh;
927
928 r = ovl->set_overlay_info(ovl, &info);
929 if (r) {
930 DBG("ovl->setup_overlay_info failed\n");
931 goto err;
932 }
933
934 return 0;
935
936err:
937 DBG("setup_overlay failed\n");
938 return r;
939}
940
941/* apply var to the overlay */
942int omapfb_apply_changes(struct fb_info *fbi, int init)
943{
944 int r = 0;
945 struct omapfb_info *ofbi = FB2OFB(fbi);
946 struct fb_var_screeninfo *var = &fbi->var;
947 struct omap_overlay *ovl;
948 u16 posx, posy;
949 u16 outw, outh;
950 int i;
951
952#ifdef DEBUG
953 if (omapfb_test_pattern)
954 fill_fb(fbi);
955#endif
956
957 for (i = 0; i < ofbi->num_overlays; i++) {
958 ovl = ofbi->overlays[i];
959
960 DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id);
961
962 if (ofbi->region.size == 0) {
963 /* the fb is not available. disable the overlay */
964 omapfb_overlay_enable(ovl, 0);
965 if (!init && ovl->manager)
966 ovl->manager->apply(ovl->manager);
967 continue;
968 }
969
970 if (init || (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
971 int rotation = (var->rotate + ofbi->rotation[i]) % 4;
972 if (rotation == FB_ROTATE_CW ||
973 rotation == FB_ROTATE_CCW) {
974 outw = var->yres;
975 outh = var->xres;
976 } else {
977 outw = var->xres;
978 outh = var->yres;
979 }
980 } else {
981 outw = ovl->info.out_width;
982 outh = ovl->info.out_height;
983 }
984
985 if (init) {
986 posx = 0;
987 posy = 0;
988 } else {
989 posx = ovl->info.pos_x;
990 posy = ovl->info.pos_y;
991 }
992
993 r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh);
994 if (r)
995 goto err;
996
997 if (!init && ovl->manager)
998 ovl->manager->apply(ovl->manager);
999 }
1000 return 0;
1001err:
1002 DBG("apply_changes failed\n");
1003 return r;
1004}
1005
1006/* checks var and eventually tweaks it to something supported,
1007 * DO NOT MODIFY PAR */
1008static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
1009{
1010 int r;
1011
1012 DBG("check_var(%d)\n", FB2OFB(fbi)->id);
1013
1014 r = check_fb_var(fbi, var);
1015
1016 return r;
1017}
1018
1019/* set the video mode according to info->var */
1020static int omapfb_set_par(struct fb_info *fbi)
1021{
1022 int r;
1023
1024 DBG("set_par(%d)\n", FB2OFB(fbi)->id);
1025
1026 set_fb_fix(fbi);
1027
1028 r = setup_vrfb_rotation(fbi);
1029 if (r)
1030 return r;
1031
1032 r = omapfb_apply_changes(fbi, 0);
1033
1034 return r;
1035}
1036
1037static int omapfb_pan_display(struct fb_var_screeninfo *var,
1038 struct fb_info *fbi)
1039{
1040 struct fb_var_screeninfo new_var;
1041 int r;
1042
1043 DBG("pan_display(%d)\n", FB2OFB(fbi)->id);
1044
1045 if (var->xoffset == fbi->var.xoffset &&
1046 var->yoffset == fbi->var.yoffset)
1047 return 0;
1048
1049 new_var = fbi->var;
1050 new_var.xoffset = var->xoffset;
1051 new_var.yoffset = var->yoffset;
1052
1053 fbi->var = new_var;
1054
1055 r = omapfb_apply_changes(fbi, 0);
1056
1057 return r;
1058}
1059
1060static void mmap_user_open(struct vm_area_struct *vma)
1061{
1062 struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data;
1063
1064 atomic_inc(&ofbi->map_count);
1065}
1066
1067static void mmap_user_close(struct vm_area_struct *vma)
1068{
1069 struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data;
1070
1071 atomic_dec(&ofbi->map_count);
1072}
1073
1074static struct vm_operations_struct mmap_user_ops = {
1075 .open = mmap_user_open,
1076 .close = mmap_user_close,
1077};
1078
1079static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
1080{
1081 struct omapfb_info *ofbi = FB2OFB(fbi);
1082 struct fb_fix_screeninfo *fix = &fbi->fix;
1083 unsigned long off;
1084 unsigned long start;
1085 u32 len;
1086
1087 if (vma->vm_end - vma->vm_start == 0)
1088 return 0;
1089 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
1090 return -EINVAL;
1091 off = vma->vm_pgoff << PAGE_SHIFT;
1092
1093 start = omapfb_get_region_paddr(ofbi);
1094 len = fix->smem_len;
1095 if (off >= len)
1096 return -EINVAL;
1097 if ((vma->vm_end - vma->vm_start + off) > len)
1098 return -EINVAL;
1099
1100 off += start;
1101
1102 DBG("user mmap region start %lx, len %d, off %lx\n", start, len, off);
1103
1104 vma->vm_pgoff = off >> PAGE_SHIFT;
1105 vma->vm_flags |= VM_IO | VM_RESERVED;
1106 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
1107 vma->vm_ops = &mmap_user_ops;
1108 vma->vm_private_data = ofbi;
1109 if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
1110 vma->vm_end - vma->vm_start, vma->vm_page_prot))
1111 return -EAGAIN;
1112 /* vm_ops.open won't be called for mmap itself. */
1113 atomic_inc(&ofbi->map_count);
1114 return 0;
1115}
1116
1117/* Store a single color palette entry into a pseudo palette or the hardware
1118 * palette if one is available. For now we support only 16bpp and thus store
1119 * the entry only to the pseudo palette.
1120 */
1121static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green,
1122 u_int blue, u_int transp, int update_hw_pal)
1123{
1124 /*struct omapfb_info *ofbi = FB2OFB(fbi);*/
1125 /*struct omapfb2_device *fbdev = ofbi->fbdev;*/
1126 struct fb_var_screeninfo *var = &fbi->var;
1127 int r = 0;
1128
1129 enum omapfb_color_format mode = OMAPFB_COLOR_RGB24U; /* XXX */
1130
1131 /*switch (plane->color_mode) {*/
1132 switch (mode) {
1133 case OMAPFB_COLOR_YUV422:
1134 case OMAPFB_COLOR_YUV420:
1135 case OMAPFB_COLOR_YUY422:
1136 r = -EINVAL;
1137 break;
1138 case OMAPFB_COLOR_CLUT_8BPP:
1139 case OMAPFB_COLOR_CLUT_4BPP:
1140 case OMAPFB_COLOR_CLUT_2BPP:
1141 case OMAPFB_COLOR_CLUT_1BPP:
1142 /*
1143 if (fbdev->ctrl->setcolreg)
1144 r = fbdev->ctrl->setcolreg(regno, red, green, blue,
1145 transp, update_hw_pal);
1146 */
1147 /* Fallthrough */
1148 r = -EINVAL;
1149 break;
1150 case OMAPFB_COLOR_RGB565:
1151 case OMAPFB_COLOR_RGB444:
1152 case OMAPFB_COLOR_RGB24P:
1153 case OMAPFB_COLOR_RGB24U:
1154 if (r != 0)
1155 break;
1156
1157 if (regno < 0) {
1158 r = -EINVAL;
1159 break;
1160 }
1161
1162 if (regno < 16) {
1163 u16 pal;
1164 pal = ((red >> (16 - var->red.length)) <<
1165 var->red.offset) |
1166 ((green >> (16 - var->green.length)) <<
1167 var->green.offset) |
1168 (blue >> (16 - var->blue.length));
1169 ((u32 *)(fbi->pseudo_palette))[regno] = pal;
1170 }
1171 break;
1172 default:
1173 BUG();
1174 }
1175 return r;
1176}
1177
1178static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
1179 u_int transp, struct fb_info *info)
1180{
1181 DBG("setcolreg\n");
1182
1183 return _setcolreg(info, regno, red, green, blue, transp, 1);
1184}
1185
1186static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
1187{
1188 int count, index, r;
1189 u16 *red, *green, *blue, *transp;
1190 u16 trans = 0xffff;
1191
1192 DBG("setcmap\n");
1193
1194 red = cmap->red;
1195 green = cmap->green;
1196 blue = cmap->blue;
1197 transp = cmap->transp;
1198 index = cmap->start;
1199
1200 for (count = 0; count < cmap->len; count++) {
1201 if (transp)
1202 trans = *transp++;
1203 r = _setcolreg(info, index++, *red++, *green++, *blue++, trans,
1204 count == cmap->len - 1);
1205 if (r != 0)
1206 return r;
1207 }
1208
1209 return 0;
1210}
1211
1212static int omapfb_blank(int blank, struct fb_info *fbi)
1213{
1214 struct omapfb_info *ofbi = FB2OFB(fbi);
1215 struct omapfb2_device *fbdev = ofbi->fbdev;
1216 struct omap_dss_device *display = fb2display(fbi);
1217 int do_update = 0;
1218 int r = 0;
1219
1220 omapfb_lock(fbdev);
1221
1222 switch (blank) {
1223 case FB_BLANK_UNBLANK:
1224 if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
1225 goto exit;
1226
1227 if (display->driver->resume)
1228 r = display->driver->resume(display);
1229
1230 if (r == 0 && display->driver->get_update_mode &&
1231 display->driver->get_update_mode(display) ==
1232 OMAP_DSS_UPDATE_MANUAL)
1233 do_update = 1;
1234
1235 break;
1236
1237 case FB_BLANK_NORMAL:
1238 /* FB_BLANK_NORMAL could be implemented.
1239 * Needs DSS additions. */
1240 case FB_BLANK_VSYNC_SUSPEND:
1241 case FB_BLANK_HSYNC_SUSPEND:
1242 case FB_BLANK_POWERDOWN:
1243 if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
1244 goto exit;
1245
1246 if (display->driver->suspend)
1247 r = display->driver->suspend(display);
1248
1249 break;
1250
1251 default:
1252 r = -EINVAL;
1253 }
1254
1255exit:
1256 omapfb_unlock(fbdev);
1257
1258 if (r == 0 && do_update && display->driver->update) {
1259 u16 w, h;
1260 display->driver->get_resolution(display, &w, &h);
1261
1262 r = display->driver->update(display, 0, 0, w, h);
1263 }
1264
1265 return r;
1266}
1267
1268#if 0
1269/* XXX fb_read and fb_write are needed for VRFB */
1270ssize_t omapfb_write(struct fb_info *info, const char __user *buf,
1271 size_t count, loff_t *ppos)
1272{
1273 DBG("omapfb_write %d, %lu\n", count, (unsigned long)*ppos);
1274 /* XXX needed for VRFB */
1275 return count;
1276}
1277#endif
1278
1279static struct fb_ops omapfb_ops = {
1280 .owner = THIS_MODULE,
1281 .fb_open = omapfb_open,
1282 .fb_release = omapfb_release,
1283 .fb_fillrect = cfb_fillrect,
1284 .fb_copyarea = cfb_copyarea,
1285 .fb_imageblit = cfb_imageblit,
1286 .fb_blank = omapfb_blank,
1287 .fb_ioctl = omapfb_ioctl,
1288 .fb_check_var = omapfb_check_var,
1289 .fb_set_par = omapfb_set_par,
1290 .fb_pan_display = omapfb_pan_display,
1291 .fb_mmap = omapfb_mmap,
1292 .fb_setcolreg = omapfb_setcolreg,
1293 .fb_setcmap = omapfb_setcmap,
1294 /*.fb_write = omapfb_write,*/
1295};
1296
1297static void omapfb_free_fbmem(struct fb_info *fbi)
1298{
1299 struct omapfb_info *ofbi = FB2OFB(fbi);
1300 struct omapfb2_device *fbdev = ofbi->fbdev;
1301 struct omapfb2_mem_region *rg;
1302
1303 rg = &ofbi->region;
1304
1305 if (rg->paddr)
1306 if (omap_vram_free(rg->paddr, rg->size))
1307 dev_err(fbdev->dev, "VRAM FREE failed\n");
1308
1309 if (rg->vaddr)
1310 iounmap(rg->vaddr);
1311
1312 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
1313 /* unmap the 0 angle rotation */
1314 if (rg->vrfb.vaddr[0]) {
1315 iounmap(rg->vrfb.vaddr[0]);
1316 omap_vrfb_release_ctx(&rg->vrfb);
1317 rg->vrfb.vaddr[0] = NULL;
1318 }
1319 }
1320
1321 rg->vaddr = NULL;
1322 rg->paddr = 0;
1323 rg->alloc = 0;
1324 rg->size = 0;
1325}
1326
1327static void clear_fb_info(struct fb_info *fbi)
1328{
1329 memset(&fbi->var, 0, sizeof(fbi->var));
1330 memset(&fbi->fix, 0, sizeof(fbi->fix));
1331 strlcpy(fbi->fix.id, MODULE_NAME, sizeof(fbi->fix.id));
1332}
1333
1334static int omapfb_free_all_fbmem(struct omapfb2_device *fbdev)
1335{
1336 int i;
1337
1338 DBG("free all fbmem\n");
1339
1340 for (i = 0; i < fbdev->num_fbs; i++) {
1341 struct fb_info *fbi = fbdev->fbs[i];
1342 omapfb_free_fbmem(fbi);
1343 clear_fb_info(fbi);
1344 }
1345
1346 return 0;
1347}
1348
1349static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
1350 unsigned long paddr)
1351{
1352 struct omapfb_info *ofbi = FB2OFB(fbi);
1353 struct omapfb2_device *fbdev = ofbi->fbdev;
1354 struct omapfb2_mem_region *rg;
1355 void __iomem *vaddr;
1356 int r;
1357
1358 rg = &ofbi->region;
1359 memset(rg, 0, sizeof(*rg));
1360
1361 size = PAGE_ALIGN(size);
1362
1363 if (!paddr) {
1364 DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
1365 r = omap_vram_alloc(OMAP_VRAM_MEMTYPE_SDRAM, size, &paddr);
1366 } else {
1367 DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr,
1368 ofbi->id);
1369 r = omap_vram_reserve(paddr, size);
1370 }
1371
1372 if (r) {
1373 dev_err(fbdev->dev, "failed to allocate framebuffer\n");
1374 return -ENOMEM;
1375 }
1376
1377 if (ofbi->rotation_type != OMAP_DSS_ROT_VRFB) {
1378 vaddr = ioremap_wc(paddr, size);
1379
1380 if (!vaddr) {
1381 dev_err(fbdev->dev, "failed to ioremap framebuffer\n");
1382 omap_vram_free(paddr, size);
1383 return -ENOMEM;
1384 }
1385
1386 DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr);
1387 } else {
1388 r = omap_vrfb_request_ctx(&rg->vrfb);
1389 if (r) {
1390 dev_err(fbdev->dev, "vrfb create ctx failed\n");
1391 return r;
1392 }
1393
1394 vaddr = NULL;
1395 }
1396
1397 rg->paddr = paddr;
1398 rg->vaddr = vaddr;
1399 rg->size = size;
1400 rg->alloc = 1;
1401
1402 return 0;
1403}
1404
1405/* allocate fbmem using display resolution as reference */
1406static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
1407 unsigned long paddr)
1408{
1409 struct omapfb_info *ofbi = FB2OFB(fbi);
1410 struct omapfb2_device *fbdev = ofbi->fbdev;
1411 struct omap_dss_device *display;
1412 int bytespp;
1413
1414 display = fb2display(fbi);
1415
1416 if (!display)
1417 return 0;
1418
1419 switch (omapfb_get_recommended_bpp(fbdev, display)) {
1420 case 16:
1421 bytespp = 2;
1422 break;
1423 case 24:
1424 bytespp = 4;
1425 break;
1426 default:
1427 bytespp = 4;
1428 break;
1429 }
1430
1431 if (!size) {
1432 u16 w, h;
1433
1434 display->driver->get_resolution(display, &w, &h);
1435
1436 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
1437 size = max(omap_vrfb_min_phys_size(w, h, bytespp),
1438 omap_vrfb_min_phys_size(h, w, bytespp));
1439
1440 DBG("adjusting fb mem size for VRFB, %u -> %lu\n",
1441 w * h * bytespp, size);
1442 } else {
1443 size = w * h * bytespp;
1444 }
1445 }
1446
1447 if (!size)
1448 return 0;
1449
1450 return omapfb_alloc_fbmem(fbi, size, paddr);
1451}
1452
1453static enum omap_color_mode fb_format_to_dss_mode(enum omapfb_color_format fmt)
1454{
1455 enum omap_color_mode mode;
1456
1457 switch (fmt) {
1458 case OMAPFB_COLOR_RGB565:
1459 mode = OMAP_DSS_COLOR_RGB16;
1460 break;
1461 case OMAPFB_COLOR_YUV422:
1462 mode = OMAP_DSS_COLOR_YUV2;
1463 break;
1464 case OMAPFB_COLOR_CLUT_8BPP:
1465 mode = OMAP_DSS_COLOR_CLUT8;
1466 break;
1467 case OMAPFB_COLOR_CLUT_4BPP:
1468 mode = OMAP_DSS_COLOR_CLUT4;
1469 break;
1470 case OMAPFB_COLOR_CLUT_2BPP:
1471 mode = OMAP_DSS_COLOR_CLUT2;
1472 break;
1473 case OMAPFB_COLOR_CLUT_1BPP:
1474 mode = OMAP_DSS_COLOR_CLUT1;
1475 break;
1476 case OMAPFB_COLOR_RGB444:
1477 mode = OMAP_DSS_COLOR_RGB12U;
1478 break;
1479 case OMAPFB_COLOR_YUY422:
1480 mode = OMAP_DSS_COLOR_UYVY;
1481 break;
1482 case OMAPFB_COLOR_ARGB16:
1483 mode = OMAP_DSS_COLOR_ARGB16;
1484 break;
1485 case OMAPFB_COLOR_RGB24U:
1486 mode = OMAP_DSS_COLOR_RGB24U;
1487 break;
1488 case OMAPFB_COLOR_RGB24P:
1489 mode = OMAP_DSS_COLOR_RGB24P;
1490 break;
1491 case OMAPFB_COLOR_ARGB32:
1492 mode = OMAP_DSS_COLOR_ARGB32;
1493 break;
1494 case OMAPFB_COLOR_RGBA32:
1495 mode = OMAP_DSS_COLOR_RGBA32;
1496 break;
1497 case OMAPFB_COLOR_RGBX32:
1498 mode = OMAP_DSS_COLOR_RGBX32;
1499 break;
1500 default:
1501 mode = -EINVAL;
1502 }
1503
1504 return mode;
1505}
1506
1507static int omapfb_parse_vram_param(const char *param, int max_entries,
1508 unsigned long *sizes, unsigned long *paddrs)
1509{
1510 int fbnum;
1511 unsigned long size;
1512 unsigned long paddr = 0;
1513 char *p, *start;
1514
1515 start = (char *)param;
1516
1517 while (1) {
1518 p = start;
1519
1520 fbnum = simple_strtoul(p, &p, 10);
1521
1522 if (p == param)
1523 return -EINVAL;
1524
1525 if (*p != ':')
1526 return -EINVAL;
1527
1528 if (fbnum >= max_entries)
1529 return -EINVAL;
1530
1531 size = memparse(p + 1, &p);
1532
1533 if (!size)
1534 return -EINVAL;
1535
1536 paddr = 0;
1537
1538 if (*p == '@') {
1539 paddr = simple_strtoul(p + 1, &p, 16);
1540
1541 if (!paddr)
1542 return -EINVAL;
1543
1544 }
1545
1546 paddrs[fbnum] = paddr;
1547 sizes[fbnum] = size;
1548
1549 if (*p == 0)
1550 break;
1551
1552 if (*p != ',')
1553 return -EINVAL;
1554
1555 ++p;
1556
1557 start = p;
1558 }
1559
1560 return 0;
1561}
1562
1563static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
1564{
1565 int i, r;
1566 unsigned long vram_sizes[10];
1567 unsigned long vram_paddrs[10];
1568
1569 memset(&vram_sizes, 0, sizeof(vram_sizes));
1570 memset(&vram_paddrs, 0, sizeof(vram_paddrs));
1571
1572 if (def_vram && omapfb_parse_vram_param(def_vram, 10,
1573 vram_sizes, vram_paddrs)) {
1574 dev_err(fbdev->dev, "failed to parse vram parameter\n");
1575
1576 memset(&vram_sizes, 0, sizeof(vram_sizes));
1577 memset(&vram_paddrs, 0, sizeof(vram_paddrs));
1578 }
1579
1580 if (fbdev->dev->platform_data) {
1581 struct omapfb_platform_data *opd;
1582 opd = fbdev->dev->platform_data;
1583 for (i = 0; i < opd->mem_desc.region_cnt; ++i) {
1584 if (!vram_sizes[i]) {
1585 unsigned long size;
1586 unsigned long paddr;
1587
1588 size = opd->mem_desc.region[i].size;
1589 paddr = opd->mem_desc.region[i].paddr;
1590
1591 vram_sizes[i] = size;
1592 vram_paddrs[i] = paddr;
1593 }
1594 }
1595 }
1596
1597 for (i = 0; i < fbdev->num_fbs; i++) {
1598 /* allocate memory automatically only for fb0, or if
1599 * excplicitly defined with vram or plat data option */
1600 if (i == 0 || vram_sizes[i] != 0) {
1601 r = omapfb_alloc_fbmem_display(fbdev->fbs[i],
1602 vram_sizes[i], vram_paddrs[i]);
1603
1604 if (r)
1605 return r;
1606 }
1607 }
1608
1609 for (i = 0; i < fbdev->num_fbs; i++) {
1610 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
1611 struct omapfb2_mem_region *rg;
1612 rg = &ofbi->region;
1613
1614 DBG("region%d phys %08x virt %p size=%lu\n",
1615 i,
1616 rg->paddr,
1617 rg->vaddr,
1618 rg->size);
1619 }
1620
1621 return 0;
1622}
1623
1624int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
1625{
1626 struct omapfb_info *ofbi = FB2OFB(fbi);
1627 struct omapfb2_device *fbdev = ofbi->fbdev;
1628 struct omap_dss_device *display = fb2display(fbi);
1629 struct omapfb2_mem_region *rg = &ofbi->region;
1630 unsigned long old_size = rg->size;
1631 unsigned long old_paddr = rg->paddr;
1632 int old_type = rg->type;
1633 int r;
1634
1635 if (type > OMAPFB_MEMTYPE_MAX)
1636 return -EINVAL;
1637
1638 size = PAGE_ALIGN(size);
1639
1640 if (old_size == size && old_type == type)
1641 return 0;
1642
1643 if (display && display->driver->sync)
1644 display->driver->sync(display);
1645
1646 omapfb_free_fbmem(fbi);
1647
1648 if (size == 0) {
1649 clear_fb_info(fbi);
1650 return 0;
1651 }
1652
1653 r = omapfb_alloc_fbmem(fbi, size, 0);
1654
1655 if (r) {
1656 if (old_size)
1657 omapfb_alloc_fbmem(fbi, old_size, old_paddr);
1658
1659 if (rg->size == 0)
1660 clear_fb_info(fbi);
1661
1662 return r;
1663 }
1664
1665 if (old_size == size)
1666 return 0;
1667
1668 if (old_size == 0) {
1669 DBG("initializing fb %d\n", ofbi->id);
1670 r = omapfb_fb_init(fbdev, fbi);
1671 if (r) {
1672 DBG("omapfb_fb_init failed\n");
1673 goto err;
1674 }
1675 r = omapfb_apply_changes(fbi, 1);
1676 if (r) {
1677 DBG("omapfb_apply_changes failed\n");
1678 goto err;
1679 }
1680 } else {
1681 struct fb_var_screeninfo new_var;
1682 memcpy(&new_var, &fbi->var, sizeof(new_var));
1683 r = check_fb_var(fbi, &new_var);
1684 if (r)
1685 goto err;
1686 memcpy(&fbi->var, &new_var, sizeof(fbi->var));
1687 set_fb_fix(fbi);
1688 r = setup_vrfb_rotation(fbi);
1689 if (r)
1690 goto err;
1691 }
1692
1693 return 0;
1694err:
1695 omapfb_free_fbmem(fbi);
1696 clear_fb_info(fbi);
1697 return r;
1698}
1699
1700/* initialize fb_info, var, fix to something sane based on the display */
1701static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
1702{
1703 struct fb_var_screeninfo *var = &fbi->var;
1704 struct omap_dss_device *display = fb2display(fbi);
1705 struct omapfb_info *ofbi = FB2OFB(fbi);
1706 int r = 0;
1707
1708 fbi->fbops = &omapfb_ops;
1709 fbi->flags = FBINFO_FLAG_DEFAULT;
1710 fbi->pseudo_palette = fbdev->pseudo_palette;
1711
1712 if (ofbi->region.size == 0) {
1713 clear_fb_info(fbi);
1714 return 0;
1715 }
1716
1717 var->nonstd = 0;
1718 var->bits_per_pixel = 0;
1719
1720 var->rotate = def_rotate;
1721
1722 /*
1723 * Check if there is a default color format set in the board file,
1724 * and use this format instead the default deducted from the
1725 * display bpp.
1726 */
1727 if (fbdev->dev->platform_data) {
1728 struct omapfb_platform_data *opd;
1729 int id = ofbi->id;
1730
1731 opd = fbdev->dev->platform_data;
1732 if (opd->mem_desc.region[id].format_used) {
1733 enum omap_color_mode mode;
1734 enum omapfb_color_format format;
1735
1736 format = opd->mem_desc.region[id].format;
1737 mode = fb_format_to_dss_mode(format);
1738 if (mode < 0) {
1739 r = mode;
1740 goto err;
1741 }
1742 r = dss_mode_to_fb_mode(mode, var);
1743 if (r < 0)
1744 goto err;
1745 }
1746 }
1747
1748 if (display) {
1749 u16 w, h;
1750 int rotation = (var->rotate + ofbi->rotation[0]) % 4;
1751
1752 display->driver->get_resolution(display, &w, &h);
1753
1754 if (rotation == FB_ROTATE_CW ||
1755 rotation == FB_ROTATE_CCW) {
1756 var->xres = h;
1757 var->yres = w;
1758 } else {
1759 var->xres = w;
1760 var->yres = h;
1761 }
1762
1763 var->xres_virtual = var->xres;
1764 var->yres_virtual = var->yres;
1765
1766 if (!var->bits_per_pixel) {
1767 switch (omapfb_get_recommended_bpp(fbdev, display)) {
1768 case 16:
1769 var->bits_per_pixel = 16;
1770 break;
1771 case 24:
1772 var->bits_per_pixel = 32;
1773 break;
1774 default:
1775 dev_err(fbdev->dev, "illegal display "
1776 "bpp\n");
1777 return -EINVAL;
1778 }
1779 }
1780 } else {
1781 /* if there's no display, let's just guess some basic values */
1782 var->xres = 320;
1783 var->yres = 240;
1784 var->xres_virtual = var->xres;
1785 var->yres_virtual = var->yres;
1786 if (!var->bits_per_pixel)
1787 var->bits_per_pixel = 16;
1788 }
1789
1790 r = check_fb_var(fbi, var);
1791 if (r)
1792 goto err;
1793
1794 set_fb_fix(fbi);
1795 r = setup_vrfb_rotation(fbi);
1796 if (r)
1797 goto err;
1798
1799 r = fb_alloc_cmap(&fbi->cmap, 256, 0);
1800 if (r)
1801 dev_err(fbdev->dev, "unable to allocate color map memory\n");
1802
1803err:
1804 return r;
1805}
1806
1807static void fbinfo_cleanup(struct omapfb2_device *fbdev, struct fb_info *fbi)
1808{
1809 fb_dealloc_cmap(&fbi->cmap);
1810}
1811
1812
1813static void omapfb_free_resources(struct omapfb2_device *fbdev)
1814{
1815 int i;
1816
1817 DBG("free_resources\n");
1818
1819 if (fbdev == NULL)
1820 return;
1821
1822 for (i = 0; i < fbdev->num_fbs; i++)
1823 unregister_framebuffer(fbdev->fbs[i]);
1824
1825 /* free the reserved fbmem */
1826 omapfb_free_all_fbmem(fbdev);
1827
1828 for (i = 0; i < fbdev->num_fbs; i++) {
1829 fbinfo_cleanup(fbdev, fbdev->fbs[i]);
1830 framebuffer_release(fbdev->fbs[i]);
1831 }
1832
1833 for (i = 0; i < fbdev->num_displays; i++) {
1834 if (fbdev->displays[i]->state != OMAP_DSS_DISPLAY_DISABLED)
1835 fbdev->displays[i]->driver->disable(fbdev->displays[i]);
1836
1837 omap_dss_put_device(fbdev->displays[i]);
1838 }
1839
1840 dev_set_drvdata(fbdev->dev, NULL);
1841 kfree(fbdev);
1842}
1843
1844static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
1845{
1846 int r, i;
1847
1848 fbdev->num_fbs = 0;
1849
1850 DBG("create %d framebuffers\n", CONFIG_FB_OMAP2_NUM_FBS);
1851
1852 /* allocate fb_infos */
1853 for (i = 0; i < CONFIG_FB_OMAP2_NUM_FBS; i++) {
1854 struct fb_info *fbi;
1855 struct omapfb_info *ofbi;
1856
1857 fbi = framebuffer_alloc(sizeof(struct omapfb_info),
1858 fbdev->dev);
1859
1860 if (fbi == NULL) {
1861 dev_err(fbdev->dev,
1862 "unable to allocate memory for plane info\n");
1863 return -ENOMEM;
1864 }
1865
1866 clear_fb_info(fbi);
1867
1868 fbdev->fbs[i] = fbi;
1869
1870 ofbi = FB2OFB(fbi);
1871 ofbi->fbdev = fbdev;
1872 ofbi->id = i;
1873
1874 /* assign these early, so that fb alloc can use them */
1875 ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
1876 OMAP_DSS_ROT_DMA;
1877 ofbi->mirror = def_mirror;
1878
1879 fbdev->num_fbs++;
1880 }
1881
1882 DBG("fb_infos allocated\n");
1883
1884 /* assign overlays for the fbs */
1885 for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) {
1886 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
1887
1888 ofbi->overlays[0] = fbdev->overlays[i];
1889 ofbi->num_overlays = 1;
1890 }
1891
1892 /* allocate fb memories */
1893 r = omapfb_allocate_all_fbs(fbdev);
1894 if (r) {
1895 dev_err(fbdev->dev, "failed to allocate fbmem\n");
1896 return r;
1897 }
1898
1899 DBG("fbmems allocated\n");
1900
1901 /* setup fb_infos */
1902 for (i = 0; i < fbdev->num_fbs; i++) {
1903 r = omapfb_fb_init(fbdev, fbdev->fbs[i]);
1904 if (r) {
1905 dev_err(fbdev->dev, "failed to setup fb_info\n");
1906 return r;
1907 }
1908 }
1909
1910 DBG("fb_infos initialized\n");
1911
1912 for (i = 0; i < fbdev->num_fbs; i++) {
1913 r = register_framebuffer(fbdev->fbs[i]);
1914 if (r != 0) {
1915 dev_err(fbdev->dev,
1916 "registering framebuffer %d failed\n", i);
1917 return r;
1918 }
1919 }
1920
1921 DBG("framebuffers registered\n");
1922
1923 for (i = 0; i < fbdev->num_fbs; i++) {
1924 r = omapfb_apply_changes(fbdev->fbs[i], 1);
1925 if (r) {
1926 dev_err(fbdev->dev, "failed to change mode\n");
1927 return r;
1928 }
1929 }
1930
1931 DBG("create sysfs for fbs\n");
1932 r = omapfb_create_sysfs(fbdev);
1933 if (r) {
1934 dev_err(fbdev->dev, "failed to create sysfs entries\n");
1935 return r;
1936 }
1937
1938 /* Enable fb0 */
1939 if (fbdev->num_fbs > 0) {
1940 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]);
1941
1942 if (ofbi->num_overlays > 0) {
1943 struct omap_overlay *ovl = ofbi->overlays[0];
1944
1945 r = omapfb_overlay_enable(ovl, 1);
1946
1947 if (r) {
1948 dev_err(fbdev->dev,
1949 "failed to enable overlay\n");
1950 return r;
1951 }
1952 }
1953 }
1954
1955 DBG("create_framebuffers done\n");
1956
1957 return 0;
1958}
1959
1960static int omapfb_mode_to_timings(const char *mode_str,
1961 struct omap_video_timings *timings, u8 *bpp)
1962{
1963 struct fb_info fbi;
1964 struct fb_var_screeninfo var;
1965 struct fb_ops fbops;
1966 int r;
1967
1968#ifdef CONFIG_OMAP2_DSS_VENC
1969 if (strcmp(mode_str, "pal") == 0) {
1970 *timings = omap_dss_pal_timings;
1971 *bpp = 0;
1972 return 0;
1973 } else if (strcmp(mode_str, "ntsc") == 0) {
1974 *timings = omap_dss_ntsc_timings;
1975 *bpp = 0;
1976 return 0;
1977 }
1978#endif
1979
1980 /* this is quite a hack, but I wanted to use the modedb and for
1981 * that we need fb_info and var, so we create dummy ones */
1982
1983 memset(&fbi, 0, sizeof(fbi));
1984 memset(&var, 0, sizeof(var));
1985 memset(&fbops, 0, sizeof(fbops));
1986 fbi.fbops = &fbops;
1987
1988 r = fb_find_mode(&var, &fbi, mode_str, NULL, 0, NULL, 24);
1989
1990 if (r != 0) {
1991 timings->pixel_clock = PICOS2KHZ(var.pixclock);
1992 timings->hfp = var.left_margin;
1993 timings->hbp = var.right_margin;
1994 timings->vfp = var.upper_margin;
1995 timings->vbp = var.lower_margin;
1996 timings->hsw = var.hsync_len;
1997 timings->vsw = var.vsync_len;
1998 timings->x_res = var.xres;
1999 timings->y_res = var.yres;
2000
2001 switch (var.bits_per_pixel) {
2002 case 16:
2003 *bpp = 16;
2004 break;
2005 case 24:
2006 case 32:
2007 default:
2008 *bpp = 24;
2009 break;
2010 }
2011
2012 return 0;
2013 } else {
2014 return -EINVAL;
2015 }
2016}
2017
2018static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
2019 struct omap_dss_device *display, char *mode_str)
2020{
2021 int r;
2022 u8 bpp;
2023 struct omap_video_timings timings;
2024
2025 r = omapfb_mode_to_timings(mode_str, &timings, &bpp);
2026 if (r)
2027 return r;
2028
2029 fbdev->bpp_overrides[fbdev->num_bpp_overrides].dssdev = display;
2030 fbdev->bpp_overrides[fbdev->num_bpp_overrides].bpp = bpp;
2031 ++fbdev->num_bpp_overrides;
2032
2033 if (!display->driver->check_timings || !display->driver->set_timings)
2034 return -EINVAL;
2035
2036 r = display->driver->check_timings(display, &timings);
2037 if (r)
2038 return r;
2039
2040 display->driver->set_timings(display, &timings);
2041
2042 return 0;
2043}
2044
2045static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
2046 struct omap_dss_device *dssdev)
2047{
2048 int i;
2049
2050 BUG_ON(dssdev->driver->get_recommended_bpp == NULL);
2051
2052 for (i = 0; i < fbdev->num_bpp_overrides; ++i) {
2053 if (dssdev == fbdev->bpp_overrides[i].dssdev)
2054 return fbdev->bpp_overrides[i].bpp;
2055 }
2056
2057 return dssdev->driver->get_recommended_bpp(dssdev);
2058}
2059
2060static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
2061{
2062 char *str, *options, *this_opt;
2063 int r = 0;
2064
2065 str = kmalloc(strlen(def_mode) + 1, GFP_KERNEL);
2066 strcpy(str, def_mode);
2067 options = str;
2068
2069 while (!r && (this_opt = strsep(&options, ",")) != NULL) {
2070 char *p, *display_str, *mode_str;
2071 struct omap_dss_device *display;
2072 int i;
2073
2074 p = strchr(this_opt, ':');
2075 if (!p) {
2076 r = -EINVAL;
2077 break;
2078 }
2079
2080 *p = 0;
2081 display_str = this_opt;
2082 mode_str = p + 1;
2083
2084 display = NULL;
2085 for (i = 0; i < fbdev->num_displays; ++i) {
2086 if (strcmp(fbdev->displays[i]->name,
2087 display_str) == 0) {
2088 display = fbdev->displays[i];
2089 break;
2090 }
2091 }
2092
2093 if (!display) {
2094 r = -EINVAL;
2095 break;
2096 }
2097
2098 r = omapfb_set_def_mode(fbdev, display, mode_str);
2099 if (r)
2100 break;
2101 }
2102
2103 kfree(str);
2104
2105 return r;
2106}
2107
2108static int omapfb_probe(struct platform_device *pdev)
2109{
2110 struct omapfb2_device *fbdev = NULL;
2111 int r = 0;
2112 int i;
2113 struct omap_overlay *ovl;
2114 struct omap_dss_device *def_display;
2115 struct omap_dss_device *dssdev;
2116
2117 DBG("omapfb_probe\n");
2118
2119 if (pdev->num_resources != 0) {
2120 dev_err(&pdev->dev, "probed for an unknown device\n");
2121 r = -ENODEV;
2122 goto err0;
2123 }
2124
2125 fbdev = kzalloc(sizeof(struct omapfb2_device), GFP_KERNEL);
2126 if (fbdev == NULL) {
2127 r = -ENOMEM;
2128 goto err0;
2129 }
2130
2131 mutex_init(&fbdev->mtx);
2132
2133 fbdev->dev = &pdev->dev;
2134 platform_set_drvdata(pdev, fbdev);
2135
2136 r = 0;
2137 fbdev->num_displays = 0;
2138 dssdev = NULL;
2139 for_each_dss_dev(dssdev) {
2140 omap_dss_get_device(dssdev);
2141
2142 if (!dssdev->driver) {
2143 dev_err(&pdev->dev, "no driver for display\n");
2144 r = -ENODEV;
2145 }
2146
2147 fbdev->displays[fbdev->num_displays++] = dssdev;
2148 }
2149
2150 if (r)
2151 goto cleanup;
2152
2153 if (fbdev->num_displays == 0) {
2154 dev_err(&pdev->dev, "no displays\n");
2155 r = -EINVAL;
2156 goto cleanup;
2157 }
2158
2159 fbdev->num_overlays = omap_dss_get_num_overlays();
2160 for (i = 0; i < fbdev->num_overlays; i++)
2161 fbdev->overlays[i] = omap_dss_get_overlay(i);
2162
2163 fbdev->num_managers = omap_dss_get_num_overlay_managers();
2164 for (i = 0; i < fbdev->num_managers; i++)
2165 fbdev->managers[i] = omap_dss_get_overlay_manager(i);
2166
2167 if (def_mode && strlen(def_mode) > 0) {
2168 if (omapfb_parse_def_modes(fbdev))
2169 dev_warn(&pdev->dev, "cannot parse default modes\n");
2170 }
2171
2172 r = omapfb_create_framebuffers(fbdev);
2173 if (r)
2174 goto cleanup;
2175
2176 for (i = 0; i < fbdev->num_managers; i++) {
2177 struct omap_overlay_manager *mgr;
2178 mgr = fbdev->managers[i];
2179 r = mgr->apply(mgr);
2180 if (r)
2181 dev_warn(fbdev->dev, "failed to apply dispc config\n");
2182 }
2183
2184 DBG("mgr->apply'ed\n");
2185
2186 /* gfx overlay should be the default one. find a display
2187 * connected to that, and use it as default display */
2188 ovl = omap_dss_get_overlay(0);
2189 if (ovl->manager && ovl->manager->device) {
2190 def_display = ovl->manager->device;
2191 } else {
2192 dev_warn(&pdev->dev, "cannot find default display\n");
2193 def_display = NULL;
2194 }
2195
2196 if (def_display) {
2197 struct omap_dss_driver *dssdrv = def_display->driver;
2198
2199 r = def_display->driver->enable(def_display);
2200 if (r) {
2201 dev_warn(fbdev->dev, "Failed to enable display '%s'\n",
2202 def_display->name);
2203 goto cleanup;
2204 }
2205
2206 if (def_display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
2207 u16 w, h;
2208 if (dssdrv->enable_te)
2209 dssdrv->enable_te(def_display, 1);
2210 if (dssdrv->set_update_mode)
2211 dssdrv->set_update_mode(def_display,
2212 OMAP_DSS_UPDATE_MANUAL);
2213
2214 dssdrv->get_resolution(def_display, &w, &h);
2215 def_display->driver->update(def_display, 0, 0, w, h);
2216 } else {
2217 if (dssdrv->set_update_mode)
2218 dssdrv->set_update_mode(def_display,
2219 OMAP_DSS_UPDATE_AUTO);
2220 }
2221 }
2222
2223 return 0;
2224
2225cleanup:
2226 omapfb_free_resources(fbdev);
2227err0:
2228 dev_err(&pdev->dev, "failed to setup omapfb\n");
2229 return r;
2230}
2231
2232static int omapfb_remove(struct platform_device *pdev)
2233{
2234 struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
2235
2236 /* FIXME: wait till completion of pending events */
2237
2238 omapfb_remove_sysfs(fbdev);
2239
2240 omapfb_free_resources(fbdev);
2241
2242 return 0;
2243}
2244
2245static struct platform_driver omapfb_driver = {
2246 .probe = omapfb_probe,
2247 .remove = omapfb_remove,
2248 .driver = {
2249 .name = "omapfb",
2250 .owner = THIS_MODULE,
2251 },
2252};
2253
2254static int __init omapfb_init(void)
2255{
2256 DBG("omapfb_init\n");
2257
2258 if (platform_driver_register(&omapfb_driver)) {
2259 printk(KERN_ERR "failed to register omapfb driver\n");
2260 return -ENODEV;
2261 }
2262
2263 return 0;
2264}
2265
2266static void __exit omapfb_exit(void)
2267{
2268 DBG("omapfb_exit\n");
2269 platform_driver_unregister(&omapfb_driver);
2270}
2271
2272module_param_named(mode, def_mode, charp, 0);
2273module_param_named(vram, def_vram, charp, 0);
2274module_param_named(rotate, def_rotate, int, 0);
2275module_param_named(vrfb, def_vrfb, bool, 0);
2276module_param_named(mirror, def_mirror, bool, 0);
2277
2278/* late_initcall to let panel/ctrl drivers loaded first.
2279 * I guess better option would be a more dynamic approach,
2280 * so that omapfb reacts to new panels when they are loaded */
2281late_initcall(omapfb_init);
2282/*module_init(omapfb_init);*/
2283module_exit(omapfb_exit);
2284
2285MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
2286MODULE_DESCRIPTION("OMAP2/3 Framebuffer");
2287MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
new file mode 100644
index 000000000000..62bb88f5c192
--- /dev/null
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -0,0 +1,507 @@
1/*
2 * linux/drivers/video/omap2/omapfb-sysfs.c
3 *
4 * Copyright (C) 2008 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#include <linux/fb.h>
24#include <linux/sysfs.h>
25#include <linux/device.h>
26#include <linux/uaccess.h>
27#include <linux/platform_device.h>
28#include <linux/kernel.h>
29#include <linux/mm.h>
30#include <linux/omapfb.h>
31
32#include <plat/display.h>
33#include <plat/vrfb.h>
34
35#include "omapfb.h"
36
37static ssize_t show_rotate_type(struct device *dev,
38 struct device_attribute *attr, char *buf)
39{
40 struct fb_info *fbi = dev_get_drvdata(dev);
41 struct omapfb_info *ofbi = FB2OFB(fbi);
42
43 return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->rotation_type);
44}
45
46static ssize_t store_rotate_type(struct device *dev,
47 struct device_attribute *attr,
48 const char *buf, size_t count)
49{
50 struct fb_info *fbi = dev_get_drvdata(dev);
51 struct omapfb_info *ofbi = FB2OFB(fbi);
52 enum omap_dss_rotation_type rot_type;
53 int r;
54
55 rot_type = simple_strtoul(buf, NULL, 0);
56
57 if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB)
58 return -EINVAL;
59
60 lock_fb_info(fbi);
61
62 r = 0;
63 if (rot_type == ofbi->rotation_type)
64 goto out;
65
66 if (ofbi->region.size) {
67 r = -EBUSY;
68 goto out;
69 }
70
71 ofbi->rotation_type = rot_type;
72
73 /*
74 * Since the VRAM for this FB is not allocated at the moment we don't
75 * need to do any further parameter checking at this point.
76 */
77out:
78 unlock_fb_info(fbi);
79
80 return r ? r : count;
81}
82
83
84static ssize_t show_mirror(struct device *dev,
85 struct device_attribute *attr, char *buf)
86{
87 struct fb_info *fbi = dev_get_drvdata(dev);
88 struct omapfb_info *ofbi = FB2OFB(fbi);
89
90 return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->mirror);
91}
92
93static ssize_t store_mirror(struct device *dev,
94 struct device_attribute *attr,
95 const char *buf, size_t count)
96{
97 struct fb_info *fbi = dev_get_drvdata(dev);
98 struct omapfb_info *ofbi = FB2OFB(fbi);
99 bool mirror;
100 int r;
101 struct fb_var_screeninfo new_var;
102
103 mirror = simple_strtoul(buf, NULL, 0);
104
105 if (mirror != 0 && mirror != 1)
106 return -EINVAL;
107
108 lock_fb_info(fbi);
109
110 ofbi->mirror = mirror;
111
112 memcpy(&new_var, &fbi->var, sizeof(new_var));
113 r = check_fb_var(fbi, &new_var);
114 if (r)
115 goto out;
116 memcpy(&fbi->var, &new_var, sizeof(fbi->var));
117
118 set_fb_fix(fbi);
119
120 r = omapfb_apply_changes(fbi, 0);
121 if (r)
122 goto out;
123
124 r = count;
125out:
126 unlock_fb_info(fbi);
127
128 return r;
129}
130
131static ssize_t show_overlays(struct device *dev,
132 struct device_attribute *attr, char *buf)
133{
134 struct fb_info *fbi = dev_get_drvdata(dev);
135 struct omapfb_info *ofbi = FB2OFB(fbi);
136 struct omapfb2_device *fbdev = ofbi->fbdev;
137 ssize_t l = 0;
138 int t;
139
140 omapfb_lock(fbdev);
141 lock_fb_info(fbi);
142
143 for (t = 0; t < ofbi->num_overlays; t++) {
144 struct omap_overlay *ovl = ofbi->overlays[t];
145 int ovlnum;
146
147 for (ovlnum = 0; ovlnum < fbdev->num_overlays; ++ovlnum)
148 if (ovl == fbdev->overlays[ovlnum])
149 break;
150
151 l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
152 t == 0 ? "" : ",", ovlnum);
153 }
154
155 l += snprintf(buf + l, PAGE_SIZE - l, "\n");
156
157 unlock_fb_info(fbi);
158 omapfb_unlock(fbdev);
159
160 return l;
161}
162
163static struct omapfb_info *get_overlay_fb(struct omapfb2_device *fbdev,
164 struct omap_overlay *ovl)
165{
166 int i, t;
167
168 for (i = 0; i < fbdev->num_fbs; i++) {
169 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
170
171 for (t = 0; t < ofbi->num_overlays; t++) {
172 if (ofbi->overlays[t] == ovl)
173 return ofbi;
174 }
175 }
176
177 return NULL;
178}
179
180static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
181 const char *buf, size_t count)
182{
183 struct fb_info *fbi = dev_get_drvdata(dev);
184 struct omapfb_info *ofbi = FB2OFB(fbi);
185 struct omapfb2_device *fbdev = ofbi->fbdev;
186 struct omap_overlay *ovls[OMAPFB_MAX_OVL_PER_FB];
187 struct omap_overlay *ovl;
188 int num_ovls, r, i;
189 int len;
190 bool added = false;
191
192 num_ovls = 0;
193
194 len = strlen(buf);
195 if (buf[len - 1] == '\n')
196 len = len - 1;
197
198 omapfb_lock(fbdev);
199 lock_fb_info(fbi);
200
201 if (len > 0) {
202 char *p = (char *)buf;
203 int ovlnum;
204
205 while (p < buf + len) {
206 int found;
207 if (num_ovls == OMAPFB_MAX_OVL_PER_FB) {
208 r = -EINVAL;
209 goto out;
210 }
211
212 ovlnum = simple_strtoul(p, &p, 0);
213 if (ovlnum > fbdev->num_overlays) {
214 r = -EINVAL;
215 goto out;
216 }
217
218 found = 0;
219 for (i = 0; i < num_ovls; ++i) {
220 if (ovls[i] == fbdev->overlays[ovlnum]) {
221 found = 1;
222 break;
223 }
224 }
225
226 if (!found)
227 ovls[num_ovls++] = fbdev->overlays[ovlnum];
228
229 p++;
230 }
231 }
232
233 for (i = 0; i < num_ovls; ++i) {
234 struct omapfb_info *ofbi2 = get_overlay_fb(fbdev, ovls[i]);
235 if (ofbi2 && ofbi2 != ofbi) {
236 dev_err(fbdev->dev, "overlay already in use\n");
237 r = -EINVAL;
238 goto out;
239 }
240 }
241
242 /* detach unused overlays */
243 for (i = 0; i < ofbi->num_overlays; ++i) {
244 int t, found;
245
246 ovl = ofbi->overlays[i];
247
248 found = 0;
249
250 for (t = 0; t < num_ovls; ++t) {
251 if (ovl == ovls[t]) {
252 found = 1;
253 break;
254 }
255 }
256
257 if (found)
258 continue;
259
260 DBG("detaching %d\n", ofbi->overlays[i]->id);
261
262 omapfb_overlay_enable(ovl, 0);
263
264 if (ovl->manager)
265 ovl->manager->apply(ovl->manager);
266
267 for (t = i + 1; t < ofbi->num_overlays; t++) {
268 ofbi->rotation[t-1] = ofbi->rotation[t];
269 ofbi->overlays[t-1] = ofbi->overlays[t];
270 }
271
272 ofbi->num_overlays--;
273 i--;
274 }
275
276 for (i = 0; i < num_ovls; ++i) {
277 int t, found;
278
279 ovl = ovls[i];
280
281 found = 0;
282
283 for (t = 0; t < ofbi->num_overlays; ++t) {
284 if (ovl == ofbi->overlays[t]) {
285 found = 1;
286 break;
287 }
288 }
289
290 if (found)
291 continue;
292 ofbi->rotation[ofbi->num_overlays] = 0;
293 ofbi->overlays[ofbi->num_overlays++] = ovl;
294
295 added = true;
296 }
297
298 if (added) {
299 r = omapfb_apply_changes(fbi, 0);
300 if (r)
301 goto out;
302 }
303
304 r = count;
305out:
306 unlock_fb_info(fbi);
307 omapfb_unlock(fbdev);
308
309 return r;
310}
311
312static ssize_t show_overlays_rotate(struct device *dev,
313 struct device_attribute *attr, char *buf)
314{
315 struct fb_info *fbi = dev_get_drvdata(dev);
316 struct omapfb_info *ofbi = FB2OFB(fbi);
317 ssize_t l = 0;
318 int t;
319
320 lock_fb_info(fbi);
321
322 for (t = 0; t < ofbi->num_overlays; t++) {
323 l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
324 t == 0 ? "" : ",", ofbi->rotation[t]);
325 }
326
327 l += snprintf(buf + l, PAGE_SIZE - l, "\n");
328
329 unlock_fb_info(fbi);
330
331 return l;
332}
333
334static ssize_t store_overlays_rotate(struct device *dev,
335 struct device_attribute *attr, const char *buf, size_t count)
336{
337 struct fb_info *fbi = dev_get_drvdata(dev);
338 struct omapfb_info *ofbi = FB2OFB(fbi);
339 int num_ovls = 0, r, i;
340 int len;
341 bool changed = false;
342 u8 rotation[OMAPFB_MAX_OVL_PER_FB];
343
344 len = strlen(buf);
345 if (buf[len - 1] == '\n')
346 len = len - 1;
347
348 lock_fb_info(fbi);
349
350 if (len > 0) {
351 char *p = (char *)buf;
352
353 while (p < buf + len) {
354 int rot;
355
356 if (num_ovls == ofbi->num_overlays) {
357 r = -EINVAL;
358 goto out;
359 }
360
361 rot = simple_strtoul(p, &p, 0);
362 if (rot < 0 || rot > 3) {
363 r = -EINVAL;
364 goto out;
365 }
366
367 if (ofbi->rotation[num_ovls] != rot)
368 changed = true;
369
370 rotation[num_ovls++] = rot;
371
372 p++;
373 }
374 }
375
376 if (num_ovls != ofbi->num_overlays) {
377 r = -EINVAL;
378 goto out;
379 }
380
381 if (changed) {
382 for (i = 0; i < num_ovls; ++i)
383 ofbi->rotation[i] = rotation[i];
384
385 r = omapfb_apply_changes(fbi, 0);
386 if (r)
387 goto out;
388
389 /* FIXME error handling? */
390 }
391
392 r = count;
393out:
394 unlock_fb_info(fbi);
395
396 return r;
397}
398
399static ssize_t show_size(struct device *dev,
400 struct device_attribute *attr, char *buf)
401{
402 struct fb_info *fbi = dev_get_drvdata(dev);
403 struct omapfb_info *ofbi = FB2OFB(fbi);
404
405 return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region.size);
406}
407
408static ssize_t store_size(struct device *dev, struct device_attribute *attr,
409 const char *buf, size_t count)
410{
411 struct fb_info *fbi = dev_get_drvdata(dev);
412 struct omapfb_info *ofbi = FB2OFB(fbi);
413 unsigned long size;
414 int r;
415 int i;
416
417 size = PAGE_ALIGN(simple_strtoul(buf, NULL, 0));
418
419 lock_fb_info(fbi);
420
421 for (i = 0; i < ofbi->num_overlays; i++) {
422 if (ofbi->overlays[i]->info.enabled) {
423 r = -EBUSY;
424 goto out;
425 }
426 }
427
428 if (size != ofbi->region.size) {
429 r = omapfb_realloc_fbmem(fbi, size, ofbi->region.type);
430 if (r) {
431 dev_err(dev, "realloc fbmem failed\n");
432 goto out;
433 }
434 }
435
436 r = count;
437out:
438 unlock_fb_info(fbi);
439
440 return r;
441}
442
443static ssize_t show_phys(struct device *dev,
444 struct device_attribute *attr, char *buf)
445{
446 struct fb_info *fbi = dev_get_drvdata(dev);
447 struct omapfb_info *ofbi = FB2OFB(fbi);
448
449 return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region.paddr);
450}
451
452static ssize_t show_virt(struct device *dev,
453 struct device_attribute *attr, char *buf)
454{
455 struct fb_info *fbi = dev_get_drvdata(dev);
456 struct omapfb_info *ofbi = FB2OFB(fbi);
457
458 return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region.vaddr);
459}
460
461static struct device_attribute omapfb_attrs[] = {
462 __ATTR(rotate_type, S_IRUGO | S_IWUSR, show_rotate_type,
463 store_rotate_type),
464 __ATTR(mirror, S_IRUGO | S_IWUSR, show_mirror, store_mirror),
465 __ATTR(size, S_IRUGO | S_IWUSR, show_size, store_size),
466 __ATTR(overlays, S_IRUGO | S_IWUSR, show_overlays, store_overlays),
467 __ATTR(overlays_rotate, S_IRUGO | S_IWUSR, show_overlays_rotate,
468 store_overlays_rotate),
469 __ATTR(phys_addr, S_IRUGO, show_phys, NULL),
470 __ATTR(virt_addr, S_IRUGO, show_virt, NULL),
471};
472
473int omapfb_create_sysfs(struct omapfb2_device *fbdev)
474{
475 int i;
476 int r;
477
478 DBG("create sysfs for fbs\n");
479 for (i = 0; i < fbdev->num_fbs; i++) {
480 int t;
481 for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++) {
482 r = device_create_file(fbdev->fbs[i]->dev,
483 &omapfb_attrs[t]);
484
485 if (r) {
486 dev_err(fbdev->dev, "failed to create sysfs "
487 "file\n");
488 return r;
489 }
490 }
491 }
492
493 return 0;
494}
495
496void omapfb_remove_sysfs(struct omapfb2_device *fbdev)
497{
498 int i, t;
499
500 DBG("remove sysfs for fbs\n");
501 for (i = 0; i < fbdev->num_fbs; i++) {
502 for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++)
503 device_remove_file(fbdev->fbs[i]->dev,
504 &omapfb_attrs[t]);
505 }
506}
507
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
new file mode 100644
index 000000000000..cd54fdbfd8bb
--- /dev/null
+++ b/drivers/video/omap2/omapfb/omapfb.h
@@ -0,0 +1,155 @@
1/*
2 * linux/drivers/video/omap2/omapfb.h
3 *
4 * Copyright (C) 2008 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * Some code and ideas taken from drivers/video/omap/ driver
8 * by Imre Deak.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#ifndef __DRIVERS_VIDEO_OMAP2_OMAPFB_H__
24#define __DRIVERS_VIDEO_OMAP2_OMAPFB_H__
25
26#ifdef CONFIG_FB_OMAP2_DEBUG_SUPPORT
27#define DEBUG
28#endif
29
30#include <plat/display.h>
31
32#ifdef DEBUG
33extern unsigned int omapfb_debug;
34#define DBG(format, ...) \
35 if (omapfb_debug) \
36 printk(KERN_DEBUG "OMAPFB: " format, ## __VA_ARGS__)
37#else
38#define DBG(format, ...)
39#endif
40
41#define FB2OFB(fb_info) ((struct omapfb_info *)(fb_info->par))
42
43/* max number of overlays to which a framebuffer data can be direct */
44#define OMAPFB_MAX_OVL_PER_FB 3
45
46struct omapfb2_mem_region {
47 u32 paddr;
48 void __iomem *vaddr;
49 struct vrfb vrfb;
50 unsigned long size;
51 u8 type; /* OMAPFB_PLANE_MEM_* */
52 bool alloc; /* allocated by the driver */
53 bool map; /* kernel mapped by the driver */
54};
55
56/* appended to fb_info */
57struct omapfb_info {
58 int id;
59 struct omapfb2_mem_region region;
60 atomic_t map_count;
61 int num_overlays;
62 struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB];
63 struct omapfb2_device *fbdev;
64 enum omap_dss_rotation_type rotation_type;
65 u8 rotation[OMAPFB_MAX_OVL_PER_FB];
66 bool mirror;
67};
68
69struct omapfb2_device {
70 struct device *dev;
71 struct mutex mtx;
72
73 u32 pseudo_palette[17];
74
75 int state;
76
77 unsigned num_fbs;
78 struct fb_info *fbs[10];
79
80 unsigned num_displays;
81 struct omap_dss_device *displays[10];
82 unsigned num_overlays;
83 struct omap_overlay *overlays[10];
84 unsigned num_managers;
85 struct omap_overlay_manager *managers[10];
86
87 unsigned num_bpp_overrides;
88 struct {
89 struct omap_dss_device *dssdev;
90 u8 bpp;
91 } bpp_overrides[10];
92};
93
94struct omapfb_colormode {
95 enum omap_color_mode dssmode;
96 u32 bits_per_pixel;
97 u32 nonstd;
98 struct fb_bitfield red;
99 struct fb_bitfield green;
100 struct fb_bitfield blue;
101 struct fb_bitfield transp;
102};
103
104void set_fb_fix(struct fb_info *fbi);
105int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var);
106int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type);
107int omapfb_apply_changes(struct fb_info *fbi, int init);
108
109int omapfb_create_sysfs(struct omapfb2_device *fbdev);
110void omapfb_remove_sysfs(struct omapfb2_device *fbdev);
111
112int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg);
113
114int omapfb_update_window(struct fb_info *fbi,
115 u32 x, u32 y, u32 w, u32 h);
116
117int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
118 struct fb_var_screeninfo *var);
119
120/* find the display connected to this fb, if any */
121static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
122{
123 struct omapfb_info *ofbi = FB2OFB(fbi);
124 int i;
125
126 /* XXX: returns the display connected to first attached overlay */
127 for (i = 0; i < ofbi->num_overlays; i++) {
128 if (ofbi->overlays[i]->manager)
129 return ofbi->overlays[i]->manager->device;
130 }
131
132 return NULL;
133}
134
135static inline void omapfb_lock(struct omapfb2_device *fbdev)
136{
137 mutex_lock(&fbdev->mtx);
138}
139
140static inline void omapfb_unlock(struct omapfb2_device *fbdev)
141{
142 mutex_unlock(&fbdev->mtx);
143}
144
145static inline int omapfb_overlay_enable(struct omap_overlay *ovl,
146 int enable)
147{
148 struct omap_overlay_info info;
149
150 ovl->get_overlay_info(ovl, &info);
151 info.enabled = enable;
152 return ovl->set_overlay_info(ovl, &info);
153}
154
155#endif
diff --git a/drivers/video/omap2/vram.c b/drivers/video/omap2/vram.c
new file mode 100644
index 000000000000..3b1237ad85ed
--- /dev/null
+++ b/drivers/video/omap2/vram.c
@@ -0,0 +1,657 @@
1/*
2 * VRAM manager for OMAP
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21/*#define DEBUG*/
22
23#include <linux/kernel.h>
24#include <linux/mm.h>
25#include <linux/list.h>
26#include <linux/slab.h>
27#include <linux/seq_file.h>
28#include <linux/bootmem.h>
29#include <linux/completion.h>
30#include <linux/debugfs.h>
31#include <linux/jiffies.h>
32#include <linux/module.h>
33
34#include <asm/setup.h>
35
36#include <plat/sram.h>
37#include <plat/vram.h>
38#include <plat/dma.h>
39
40#ifdef DEBUG
41#define DBG(format, ...) pr_debug("VRAM: " format, ## __VA_ARGS__)
42#else
43#define DBG(format, ...)
44#endif
45
46#define OMAP2_SRAM_START 0x40200000
47/* Maximum size, in reality this is smaller if SRAM is partially locked. */
48#define OMAP2_SRAM_SIZE 0xa0000 /* 640k */
49
50/* postponed regions are used to temporarily store region information at boot
51 * time when we cannot yet allocate the region list */
52#define MAX_POSTPONED_REGIONS 10
53
54static bool vram_initialized;
55static int postponed_cnt;
56static struct {
57 unsigned long paddr;
58 size_t size;
59} postponed_regions[MAX_POSTPONED_REGIONS];
60
61struct vram_alloc {
62 struct list_head list;
63 unsigned long paddr;
64 unsigned pages;
65};
66
67struct vram_region {
68 struct list_head list;
69 struct list_head alloc_list;
70 unsigned long paddr;
71 unsigned pages;
72};
73
74static DEFINE_MUTEX(region_mutex);
75static LIST_HEAD(region_list);
76
77static inline int region_mem_type(unsigned long paddr)
78{
79 if (paddr >= OMAP2_SRAM_START &&
80 paddr < OMAP2_SRAM_START + OMAP2_SRAM_SIZE)
81 return OMAP_VRAM_MEMTYPE_SRAM;
82 else
83 return OMAP_VRAM_MEMTYPE_SDRAM;
84}
85
86static struct vram_region *omap_vram_create_region(unsigned long paddr,
87 unsigned pages)
88{
89 struct vram_region *rm;
90
91 rm = kzalloc(sizeof(*rm), GFP_KERNEL);
92
93 if (rm) {
94 INIT_LIST_HEAD(&rm->alloc_list);
95 rm->paddr = paddr;
96 rm->pages = pages;
97 }
98
99 return rm;
100}
101
102#if 0
103static void omap_vram_free_region(struct vram_region *vr)
104{
105 list_del(&vr->list);
106 kfree(vr);
107}
108#endif
109
110static struct vram_alloc *omap_vram_create_allocation(struct vram_region *vr,
111 unsigned long paddr, unsigned pages)
112{
113 struct vram_alloc *va;
114 struct vram_alloc *new;
115
116 new = kzalloc(sizeof(*va), GFP_KERNEL);
117
118 if (!new)
119 return NULL;
120
121 new->paddr = paddr;
122 new->pages = pages;
123
124 list_for_each_entry(va, &vr->alloc_list, list) {
125 if (va->paddr > new->paddr)
126 break;
127 }
128
129 list_add_tail(&new->list, &va->list);
130
131 return new;
132}
133
134static void omap_vram_free_allocation(struct vram_alloc *va)
135{
136 list_del(&va->list);
137 kfree(va);
138}
139
140int omap_vram_add_region(unsigned long paddr, size_t size)
141{
142 struct vram_region *rm;
143 unsigned pages;
144
145 if (vram_initialized) {
146 DBG("adding region paddr %08lx size %d\n",
147 paddr, size);
148
149 size &= PAGE_MASK;
150 pages = size >> PAGE_SHIFT;
151
152 rm = omap_vram_create_region(paddr, pages);
153 if (rm == NULL)
154 return -ENOMEM;
155
156 list_add(&rm->list, &region_list);
157 } else {
158 if (postponed_cnt == MAX_POSTPONED_REGIONS)
159 return -ENOMEM;
160
161 postponed_regions[postponed_cnt].paddr = paddr;
162 postponed_regions[postponed_cnt].size = size;
163
164 ++postponed_cnt;
165 }
166 return 0;
167}
168
169int omap_vram_free(unsigned long paddr, size_t size)
170{
171 struct vram_region *rm;
172 struct vram_alloc *alloc;
173 unsigned start, end;
174
175 DBG("free mem paddr %08lx size %d\n", paddr, size);
176
177 size = PAGE_ALIGN(size);
178
179 mutex_lock(&region_mutex);
180
181 list_for_each_entry(rm, &region_list, list) {
182 list_for_each_entry(alloc, &rm->alloc_list, list) {
183 start = alloc->paddr;
184 end = alloc->paddr + (alloc->pages >> PAGE_SHIFT);
185
186 if (start >= paddr && end < paddr + size)
187 goto found;
188 }
189 }
190
191 mutex_unlock(&region_mutex);
192 return -EINVAL;
193
194found:
195 omap_vram_free_allocation(alloc);
196
197 mutex_unlock(&region_mutex);
198 return 0;
199}
200EXPORT_SYMBOL(omap_vram_free);
201
202static int _omap_vram_reserve(unsigned long paddr, unsigned pages)
203{
204 struct vram_region *rm;
205 struct vram_alloc *alloc;
206 size_t size;
207
208 size = pages << PAGE_SHIFT;
209
210 list_for_each_entry(rm, &region_list, list) {
211 unsigned long start, end;
212
213 DBG("checking region %lx %d\n", rm->paddr, rm->pages);
214
215 if (region_mem_type(rm->paddr) != region_mem_type(paddr))
216 continue;
217
218 start = rm->paddr;
219 end = start + (rm->pages << PAGE_SHIFT) - 1;
220 if (start > paddr || end < paddr + size - 1)
221 continue;
222
223 DBG("block ok, checking allocs\n");
224
225 list_for_each_entry(alloc, &rm->alloc_list, list) {
226 end = alloc->paddr - 1;
227
228 if (start <= paddr && end >= paddr + size - 1)
229 goto found;
230
231 start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
232 }
233
234 end = rm->paddr + (rm->pages << PAGE_SHIFT) - 1;
235
236 if (!(start <= paddr && end >= paddr + size - 1))
237 continue;
238found:
239 DBG("found area start %lx, end %lx\n", start, end);
240
241 if (omap_vram_create_allocation(rm, paddr, pages) == NULL)
242 return -ENOMEM;
243
244 return 0;
245 }
246
247 return -ENOMEM;
248}
249
250int omap_vram_reserve(unsigned long paddr, size_t size)
251{
252 unsigned pages;
253 int r;
254
255 DBG("reserve mem paddr %08lx size %d\n", paddr, size);
256
257 size = PAGE_ALIGN(size);
258 pages = size >> PAGE_SHIFT;
259
260 mutex_lock(&region_mutex);
261
262 r = _omap_vram_reserve(paddr, pages);
263
264 mutex_unlock(&region_mutex);
265
266 return r;
267}
268EXPORT_SYMBOL(omap_vram_reserve);
269
270static void _omap_vram_dma_cb(int lch, u16 ch_status, void *data)
271{
272 struct completion *compl = data;
273 complete(compl);
274}
275
276static int _omap_vram_clear(u32 paddr, unsigned pages)
277{
278 struct completion compl;
279 unsigned elem_count;
280 unsigned frame_count;
281 int r;
282 int lch;
283
284 init_completion(&compl);
285
286 r = omap_request_dma(OMAP_DMA_NO_DEVICE, "VRAM DMA",
287 _omap_vram_dma_cb,
288 &compl, &lch);
289 if (r) {
290 pr_err("VRAM: request_dma failed for memory clear\n");
291 return -EBUSY;
292 }
293
294 elem_count = pages * PAGE_SIZE / 4;
295 frame_count = 1;
296
297 omap_set_dma_transfer_params(lch, OMAP_DMA_DATA_TYPE_S32,
298 elem_count, frame_count,
299 OMAP_DMA_SYNC_ELEMENT,
300 0, 0);
301
302 omap_set_dma_dest_params(lch, 0, OMAP_DMA_AMODE_POST_INC,
303 paddr, 0, 0);
304
305 omap_set_dma_color_mode(lch, OMAP_DMA_CONSTANT_FILL, 0x000000);
306
307 omap_start_dma(lch);
308
309 if (wait_for_completion_timeout(&compl, msecs_to_jiffies(1000)) == 0) {
310 omap_stop_dma(lch);
311 pr_err("VRAM: dma timeout while clearing memory\n");
312 r = -EIO;
313 goto err;
314 }
315
316 r = 0;
317err:
318 omap_free_dma(lch);
319
320 return r;
321}
322
323static int _omap_vram_alloc(int mtype, unsigned pages, unsigned long *paddr)
324{
325 struct vram_region *rm;
326 struct vram_alloc *alloc;
327
328 list_for_each_entry(rm, &region_list, list) {
329 unsigned long start, end;
330
331 DBG("checking region %lx %d\n", rm->paddr, rm->pages);
332
333 if (region_mem_type(rm->paddr) != mtype)
334 continue;
335
336 start = rm->paddr;
337
338 list_for_each_entry(alloc, &rm->alloc_list, list) {
339 end = alloc->paddr;
340
341 if (end - start >= pages << PAGE_SHIFT)
342 goto found;
343
344 start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
345 }
346
347 end = rm->paddr + (rm->pages << PAGE_SHIFT);
348found:
349 if (end - start < pages << PAGE_SHIFT)
350 continue;
351
352 DBG("found %lx, end %lx\n", start, end);
353
354 alloc = omap_vram_create_allocation(rm, start, pages);
355 if (alloc == NULL)
356 return -ENOMEM;
357
358 *paddr = start;
359
360 _omap_vram_clear(start, pages);
361
362 return 0;
363 }
364
365 return -ENOMEM;
366}
367
368int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr)
369{
370 unsigned pages;
371 int r;
372
373 BUG_ON(mtype > OMAP_VRAM_MEMTYPE_MAX || !size);
374
375 DBG("alloc mem type %d size %d\n", mtype, size);
376
377 size = PAGE_ALIGN(size);
378 pages = size >> PAGE_SHIFT;
379
380 mutex_lock(&region_mutex);
381
382 r = _omap_vram_alloc(mtype, pages, paddr);
383
384 mutex_unlock(&region_mutex);
385
386 return r;
387}
388EXPORT_SYMBOL(omap_vram_alloc);
389
390void omap_vram_get_info(unsigned long *vram,
391 unsigned long *free_vram,
392 unsigned long *largest_free_block)
393{
394 struct vram_region *vr;
395 struct vram_alloc *va;
396
397 *vram = 0;
398 *free_vram = 0;
399 *largest_free_block = 0;
400
401 mutex_lock(&region_mutex);
402
403 list_for_each_entry(vr, &region_list, list) {
404 unsigned free;
405 unsigned long pa;
406
407 pa = vr->paddr;
408 *vram += vr->pages << PAGE_SHIFT;
409
410 list_for_each_entry(va, &vr->alloc_list, list) {
411 free = va->paddr - pa;
412 *free_vram += free;
413 if (free > *largest_free_block)
414 *largest_free_block = free;
415 pa = va->paddr + (va->pages << PAGE_SHIFT);
416 }
417
418 free = vr->paddr + (vr->pages << PAGE_SHIFT) - pa;
419 *free_vram += free;
420 if (free > *largest_free_block)
421 *largest_free_block = free;
422 }
423
424 mutex_unlock(&region_mutex);
425}
426EXPORT_SYMBOL(omap_vram_get_info);
427
428#if defined(CONFIG_DEBUG_FS)
429static int vram_debug_show(struct seq_file *s, void *unused)
430{
431 struct vram_region *vr;
432 struct vram_alloc *va;
433 unsigned size;
434
435 mutex_lock(&region_mutex);
436
437 list_for_each_entry(vr, &region_list, list) {
438 size = vr->pages << PAGE_SHIFT;
439 seq_printf(s, "%08lx-%08lx (%d bytes)\n",
440 vr->paddr, vr->paddr + size - 1,
441 size);
442
443 list_for_each_entry(va, &vr->alloc_list, list) {
444 size = va->pages << PAGE_SHIFT;
445 seq_printf(s, " %08lx-%08lx (%d bytes)\n",
446 va->paddr, va->paddr + size - 1,
447 size);
448 }
449 }
450
451 mutex_unlock(&region_mutex);
452
453 return 0;
454}
455
456static int vram_debug_open(struct inode *inode, struct file *file)
457{
458 return single_open(file, vram_debug_show, inode->i_private);
459}
460
461static const struct file_operations vram_debug_fops = {
462 .open = vram_debug_open,
463 .read = seq_read,
464 .llseek = seq_lseek,
465 .release = single_release,
466};
467
468static int __init omap_vram_create_debugfs(void)
469{
470 struct dentry *d;
471
472 d = debugfs_create_file("vram", S_IRUGO, NULL,
473 NULL, &vram_debug_fops);
474 if (IS_ERR(d))
475 return PTR_ERR(d);
476
477 return 0;
478}
479#endif
480
481static __init int omap_vram_init(void)
482{
483 int i;
484
485 vram_initialized = 1;
486
487 for (i = 0; i < postponed_cnt; i++)
488 omap_vram_add_region(postponed_regions[i].paddr,
489 postponed_regions[i].size);
490
491#ifdef CONFIG_DEBUG_FS
492 if (omap_vram_create_debugfs())
493 pr_err("VRAM: Failed to create debugfs file\n");
494#endif
495
496 return 0;
497}
498
499arch_initcall(omap_vram_init);
500
501/* boottime vram alloc stuff */
502
503/* set from board file */
504static u32 omap_vram_sram_start __initdata;
505static u32 omap_vram_sram_size __initdata;
506
507/* set from board file */
508static u32 omap_vram_sdram_start __initdata;
509static u32 omap_vram_sdram_size __initdata;
510
511/* set from kernel cmdline */
512static u32 omap_vram_def_sdram_size __initdata;
513static u32 omap_vram_def_sdram_start __initdata;
514
515static int __init omap_vram_early_vram(char *p)
516{
517 omap_vram_def_sdram_size = memparse(p, &p);
518 if (*p == ',')
519 omap_vram_def_sdram_start = simple_strtoul(p + 1, &p, 16);
520 return 0;
521}
522early_param("vram", omap_vram_early_vram);
523
524/*
525 * Called from map_io. We need to call to this early enough so that we
526 * can reserve the fixed SDRAM regions before VM could get hold of them.
527 */
528void __init omap_vram_reserve_sdram(void)
529{
530 struct bootmem_data *bdata;
531 unsigned long sdram_start, sdram_size;
532 u32 paddr;
533 u32 size = 0;
534
535 /* cmdline arg overrides the board file definition */
536 if (omap_vram_def_sdram_size) {
537 size = omap_vram_def_sdram_size;
538 paddr = omap_vram_def_sdram_start;
539 }
540
541 if (!size) {
542 size = omap_vram_sdram_size;
543 paddr = omap_vram_sdram_start;
544 }
545
546#ifdef CONFIG_OMAP2_VRAM_SIZE
547 if (!size) {
548 size = CONFIG_OMAP2_VRAM_SIZE * 1024 * 1024;
549 paddr = 0;
550 }
551#endif
552
553 if (!size)
554 return;
555
556 size = PAGE_ALIGN(size);
557
558 bdata = NODE_DATA(0)->bdata;
559 sdram_start = bdata->node_min_pfn << PAGE_SHIFT;
560 sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start;
561
562 if (paddr) {
563 if ((paddr & ~PAGE_MASK) || paddr < sdram_start ||
564 paddr + size > sdram_start + sdram_size) {
565 pr_err("Illegal SDRAM region for VRAM\n");
566 return;
567 }
568
569 if (reserve_bootmem(paddr, size, BOOTMEM_EXCLUSIVE) < 0) {
570 pr_err("FB: failed to reserve VRAM\n");
571 return;
572 }
573 } else {
574 if (size > sdram_size) {
575 pr_err("Illegal SDRAM size for VRAM\n");
576 return;
577 }
578
579 paddr = virt_to_phys(alloc_bootmem_pages(size));
580 BUG_ON(paddr & ~PAGE_MASK);
581 }
582
583 omap_vram_add_region(paddr, size);
584
585 pr_info("Reserving %u bytes SDRAM for VRAM\n", size);
586}
587
588/*
589 * Called at sram init time, before anything is pushed to the SRAM stack.
590 * Because of the stack scheme, we will allocate everything from the
591 * start of the lowest address region to the end of SRAM. This will also
592 * include padding for page alignment and possible holes between regions.
593 *
594 * As opposed to the SDRAM case, we'll also do any dynamic allocations at
595 * this point, since the driver built as a module would have problem with
596 * freeing / reallocating the regions.
597 */
598unsigned long __init omap_vram_reserve_sram(unsigned long sram_pstart,
599 unsigned long sram_vstart,
600 unsigned long sram_size,
601 unsigned long pstart_avail,
602 unsigned long size_avail)
603{
604 unsigned long pend_avail;
605 unsigned long reserved;
606 u32 paddr;
607 u32 size;
608
609 paddr = omap_vram_sram_start;
610 size = omap_vram_sram_size;
611
612 if (!size)
613 return 0;
614
615 reserved = 0;
616 pend_avail = pstart_avail + size_avail;
617
618 if (!paddr) {
619 /* Dynamic allocation */
620 if ((size_avail & PAGE_MASK) < size) {
621 pr_err("Not enough SRAM for VRAM\n");
622 return 0;
623 }
624 size_avail = (size_avail - size) & PAGE_MASK;
625 paddr = pstart_avail + size_avail;
626 }
627
628 if (paddr < sram_pstart ||
629 paddr + size > sram_pstart + sram_size) {
630 pr_err("Illegal SRAM region for VRAM\n");
631 return 0;
632 }
633
634 /* Reserve everything above the start of the region. */
635 if (pend_avail - paddr > reserved)
636 reserved = pend_avail - paddr;
637 size_avail = pend_avail - reserved - pstart_avail;
638
639 omap_vram_add_region(paddr, size);
640
641 if (reserved)
642 pr_info("Reserving %lu bytes SRAM for VRAM\n", reserved);
643
644 return reserved;
645}
646
647void __init omap_vram_set_sdram_vram(u32 size, u32 start)
648{
649 omap_vram_sdram_start = start;
650 omap_vram_sdram_size = size;
651}
652
653void __init omap_vram_set_sram_vram(u32 size, u32 start)
654{
655 omap_vram_sram_start = start;
656 omap_vram_sram_size = size;
657}
diff --git a/drivers/video/omap2/vrfb.c b/drivers/video/omap2/vrfb.c
new file mode 100644
index 000000000000..fd2271600370
--- /dev/null
+++ b/drivers/video/omap2/vrfb.c
@@ -0,0 +1,315 @@
1/*
2 * VRFB Rotation Engine
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21/*#define DEBUG*/
22
23#include <linux/kernel.h>
24#include <linux/module.h>
25#include <linux/ioport.h>
26#include <linux/io.h>
27#include <linux/bitops.h>
28#include <linux/mutex.h>
29
30#include <mach/io.h>
31#include <plat/vrfb.h>
32#include <plat/sdrc.h>
33
34#ifdef DEBUG
35#define DBG(format, ...) pr_debug("VRFB: " format, ## __VA_ARGS__)
36#else
37#define DBG(format, ...)
38#endif
39
40#define SMS_ROT_VIRT_BASE(context, rot) \
41 (((context >= 4) ? 0xD0000000 : 0x70000000) \
42 + (0x4000000 * (context)) \
43 + (0x1000000 * (rot)))
44
45#define OMAP_VRFB_SIZE (2048 * 2048 * 4)
46
47#define VRFB_PAGE_WIDTH_EXP 5 /* Assuming SDRAM pagesize= 1024 */
48#define VRFB_PAGE_HEIGHT_EXP 5 /* 1024 = 2^5 * 2^5 */
49#define VRFB_PAGE_WIDTH (1 << VRFB_PAGE_WIDTH_EXP)
50#define VRFB_PAGE_HEIGHT (1 << VRFB_PAGE_HEIGHT_EXP)
51#define SMS_IMAGEHEIGHT_OFFSET 16
52#define SMS_IMAGEWIDTH_OFFSET 0
53#define SMS_PH_OFFSET 8
54#define SMS_PW_OFFSET 4
55#define SMS_PS_OFFSET 0
56
57#define VRFB_NUM_CTXS 12
58/* bitmap of reserved contexts */
59static unsigned long ctx_map;
60
61static DEFINE_MUTEX(ctx_lock);
62
63/*
64 * Access to this happens from client drivers or the PM core after wake-up.
65 * For the first case we require locking at the driver level, for the second
66 * we don't need locking, since no drivers will run until after the wake-up
67 * has finished.
68 */
69static struct {
70 u32 physical_ba;
71 u32 control;
72 u32 size;
73} vrfb_hw_context[VRFB_NUM_CTXS];
74
75static inline void restore_hw_context(int ctx)
76{
77 omap2_sms_write_rot_control(vrfb_hw_context[ctx].control, ctx);
78 omap2_sms_write_rot_size(vrfb_hw_context[ctx].size, ctx);
79 omap2_sms_write_rot_physical_ba(vrfb_hw_context[ctx].physical_ba, ctx);
80}
81
82static u32 get_image_width_roundup(u16 width, u8 bytespp)
83{
84 unsigned long stride = width * bytespp;
85 unsigned long ceil_pages_per_stride = (stride / VRFB_PAGE_WIDTH) +
86 (stride % VRFB_PAGE_WIDTH != 0);
87
88 return ceil_pages_per_stride * VRFB_PAGE_WIDTH / bytespp;
89}
90
91/*
92 * This the extra space needed in the VRFB physical area for VRFB to safely wrap
93 * any memory accesses to the invisible part of the virtual view to the physical
94 * area.
95 */
96static inline u32 get_extra_physical_size(u16 image_width_roundup, u8 bytespp)
97{
98 return (OMAP_VRFB_LINE_LEN - image_width_roundup) * VRFB_PAGE_HEIGHT *
99 bytespp;
100}
101
102void omap_vrfb_restore_context(void)
103{
104 int i;
105 unsigned long map = ctx_map;
106
107 for (i = ffs(map); i; i = ffs(map)) {
108 /* i=1..32 */
109 i--;
110 map &= ~(1 << i);
111 restore_hw_context(i);
112 }
113}
114
115void omap_vrfb_adjust_size(u16 *width, u16 *height,
116 u8 bytespp)
117{
118 *width = ALIGN(*width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
119 *height = ALIGN(*height, VRFB_PAGE_HEIGHT);
120}
121EXPORT_SYMBOL(omap_vrfb_adjust_size);
122
123u32 omap_vrfb_min_phys_size(u16 width, u16 height, u8 bytespp)
124{
125 unsigned long image_width_roundup = get_image_width_roundup(width,
126 bytespp);
127
128 if (image_width_roundup > OMAP_VRFB_LINE_LEN)
129 return 0;
130
131 return (width * height * bytespp) + get_extra_physical_size(
132 image_width_roundup, bytespp);
133}
134EXPORT_SYMBOL(omap_vrfb_min_phys_size);
135
136u16 omap_vrfb_max_height(u32 phys_size, u16 width, u8 bytespp)
137{
138 unsigned long image_width_roundup = get_image_width_roundup(width,
139 bytespp);
140 unsigned long height;
141 unsigned long extra;
142
143 if (image_width_roundup > OMAP_VRFB_LINE_LEN)
144 return 0;
145
146 extra = get_extra_physical_size(image_width_roundup, bytespp);
147
148 if (phys_size < extra)
149 return 0;
150
151 height = (phys_size - extra) / (width * bytespp);
152
153 /* Virtual views provided by VRFB are limited to 2048x2048. */
154 return min_t(unsigned long, height, 2048);
155}
156EXPORT_SYMBOL(omap_vrfb_max_height);
157
158void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
159 u16 width, u16 height,
160 unsigned bytespp, bool yuv_mode)
161{
162 unsigned pixel_size_exp;
163 u16 vrfb_width;
164 u16 vrfb_height;
165 u8 ctx = vrfb->context;
166 u32 size;
167 u32 control;
168
169 DBG("omapfb_set_vrfb(%d, %lx, %dx%d, %d, %d)\n", ctx, paddr,
170 width, height, bytespp, yuv_mode);
171
172 /* For YUV2 and UYVY modes VRFB needs to handle pixels a bit
173 * differently. See TRM. */
174 if (yuv_mode) {
175 bytespp *= 2;
176 width /= 2;
177 }
178
179 if (bytespp == 4)
180 pixel_size_exp = 2;
181 else if (bytespp == 2)
182 pixel_size_exp = 1;
183 else
184 BUG();
185
186 vrfb_width = ALIGN(width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
187 vrfb_height = ALIGN(height, VRFB_PAGE_HEIGHT);
188
189 DBG("vrfb w %u, h %u bytespp %d\n", vrfb_width, vrfb_height, bytespp);
190
191 size = vrfb_width << SMS_IMAGEWIDTH_OFFSET;
192 size |= vrfb_height << SMS_IMAGEHEIGHT_OFFSET;
193
194 control = pixel_size_exp << SMS_PS_OFFSET;
195 control |= VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET;
196 control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET;
197
198 vrfb_hw_context[ctx].physical_ba = paddr;
199 vrfb_hw_context[ctx].size = size;
200 vrfb_hw_context[ctx].control = control;
201
202 omap2_sms_write_rot_physical_ba(paddr, ctx);
203 omap2_sms_write_rot_size(size, ctx);
204 omap2_sms_write_rot_control(control, ctx);
205
206 DBG("vrfb offset pixels %d, %d\n",
207 vrfb_width - width, vrfb_height - height);
208
209 vrfb->xres = width;
210 vrfb->yres = height;
211 vrfb->xoffset = vrfb_width - width;
212 vrfb->yoffset = vrfb_height - height;
213 vrfb->bytespp = bytespp;
214 vrfb->yuv_mode = yuv_mode;
215}
216EXPORT_SYMBOL(omap_vrfb_setup);
217
218int omap_vrfb_map_angle(struct vrfb *vrfb, u16 height, u8 rot)
219{
220 unsigned long size = height * OMAP_VRFB_LINE_LEN * vrfb->bytespp;
221
222 vrfb->vaddr[rot] = ioremap_wc(vrfb->paddr[rot], size);
223
224 if (!vrfb->vaddr[rot]) {
225 printk(KERN_ERR "vrfb: ioremap failed\n");
226 return -ENOMEM;
227 }
228
229 DBG("ioremapped vrfb area %d of size %lu into %p\n", rot, size,
230 vrfb->vaddr[rot]);
231
232 return 0;
233}
234EXPORT_SYMBOL(omap_vrfb_map_angle);
235
236void omap_vrfb_release_ctx(struct vrfb *vrfb)
237{
238 int rot;
239 int ctx = vrfb->context;
240
241 if (ctx == 0xff)
242 return;
243
244 DBG("release ctx %d\n", ctx);
245
246 mutex_lock(&ctx_lock);
247
248 BUG_ON(!(ctx_map & (1 << ctx)));
249
250 clear_bit(ctx, &ctx_map);
251
252 for (rot = 0; rot < 4; ++rot) {
253 if (vrfb->paddr[rot]) {
254 release_mem_region(vrfb->paddr[rot], OMAP_VRFB_SIZE);
255 vrfb->paddr[rot] = 0;
256 }
257 }
258
259 vrfb->context = 0xff;
260
261 mutex_unlock(&ctx_lock);
262}
263EXPORT_SYMBOL(omap_vrfb_release_ctx);
264
265int omap_vrfb_request_ctx(struct vrfb *vrfb)
266{
267 int rot;
268 u32 paddr;
269 u8 ctx;
270 int r;
271
272 DBG("request ctx\n");
273
274 mutex_lock(&ctx_lock);
275
276 for (ctx = 0; ctx < VRFB_NUM_CTXS; ++ctx)
277 if ((ctx_map & (1 << ctx)) == 0)
278 break;
279
280 if (ctx == VRFB_NUM_CTXS) {
281 pr_err("vrfb: no free contexts\n");
282 r = -EBUSY;
283 goto out;
284 }
285
286 DBG("found free ctx %d\n", ctx);
287
288 set_bit(ctx, &ctx_map);
289
290 memset(vrfb, 0, sizeof(*vrfb));
291
292 vrfb->context = ctx;
293
294 for (rot = 0; rot < 4; ++rot) {
295 paddr = SMS_ROT_VIRT_BASE(ctx, rot);
296 if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) {
297 pr_err("vrfb: failed to reserve VRFB "
298 "area for ctx %d, rotation %d\n",
299 ctx, rot * 90);
300 omap_vrfb_release_ctx(vrfb);
301 r = -ENOMEM;
302 goto out;
303 }
304
305 vrfb->paddr[rot] = paddr;
306
307 DBG("VRFB %d/%d: %lx\n", ctx, rot*90, vrfb->paddr[rot]);
308 }
309
310 r = 0;
311out:
312 mutex_unlock(&ctx_lock);
313 return r;
314}
315EXPORT_SYMBOL(omap_vrfb_request_ctx);
diff --git a/drivers/video/output.c b/drivers/video/output.c
index 5e6439ae7394..0d6f2cda9369 100644
--- a/drivers/video/output.c
+++ b/drivers/video/output.c
@@ -23,6 +23,7 @@
23 */ 23 */
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/video_output.h> 25#include <linux/video_output.h>
26#include <linux/slab.h>
26#include <linux/err.h> 27#include <linux/err.h>
27#include <linux/ctype.h> 28#include <linux/ctype.h>
28 29
@@ -50,7 +51,7 @@ static ssize_t video_output_store_state(struct device *dev,
50 int request_state = simple_strtoul(buf,&endp,0); 51 int request_state = simple_strtoul(buf,&endp,0);
51 size_t size = endp - buf; 52 size_t size = endp - buf;
52 53
53 if (*endp && isspace(*endp)) 54 if (isspace(*endp))
54 size++; 55 size++;
55 if (size != count) 56 if (size != count)
56 return -EINVAL; 57 return -EINVAL;
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c
index 7fa4ab01b0d3..81440f2b9091 100644
--- a/drivers/video/p9100.c
+++ b/drivers/video/p9100.c
@@ -10,7 +10,6 @@
10#include <linux/kernel.h> 10#include <linux/kernel.h>
11#include <linux/errno.h> 11#include <linux/errno.h>
12#include <linux/string.h> 12#include <linux/string.h>
13#include <linux/slab.h>
14#include <linux/delay.h> 13#include <linux/delay.h>
15#include <linux/init.h> 14#include <linux/init.h>
16#include <linux/fb.h> 15#include <linux/fb.h>
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index 0a366d86f08e..8a204e7a5b5b 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -24,7 +24,6 @@
24#include <linux/errno.h> 24#include <linux/errno.h>
25#include <linux/string.h> 25#include <linux/string.h>
26#include <linux/mm.h> 26#include <linux/mm.h>
27#include <linux/slab.h>
28#include <linux/vmalloc.h> 27#include <linux/vmalloc.h>
29#include <linux/delay.h> 28#include <linux/delay.h>
30#include <linux/interrupt.h> 29#include <linux/interrupt.h>
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index 36436ee6c1a4..27f93aab6ddc 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -896,7 +896,7 @@ static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green,
896 * Pseudocolor: 896 * Pseudocolor:
897 * uses offset = 0 && length = DAC register width. 897 * uses offset = 0 && length = DAC register width.
898 * var->{color}.offset is 0 898 * var->{color}.offset is 0
899 * var->{color}.length contains widht of DAC 899 * var->{color}.length contains width of DAC
900 * cmap is not used 900 * cmap is not used
901 * DAC[X] is programmed to (red, green, blue) 901 * DAC[X] is programmed to (red, green, blue)
902 * Truecolor: 902 * Truecolor:
diff --git a/drivers/video/pmag-aa-fb.c b/drivers/video/pmag-aa-fb.c
index 6515ec11c16b..838424817de2 100644
--- a/drivers/video/pmag-aa-fb.c
+++ b/drivers/video/pmag-aa-fb.c
@@ -28,7 +28,6 @@
28#include <linux/string.h> 28#include <linux/string.h>
29#include <linux/timer.h> 29#include <linux/timer.h>
30#include <linux/mm.h> 30#include <linux/mm.h>
31#include <linux/slab.h>
32#include <linux/delay.h> 31#include <linux/delay.h>
33#include <linux/init.h> 32#include <linux/init.h>
34#include <linux/fb.h> 33#include <linux/fb.h>
diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c
index 0573ec685a57..0f361b6100d2 100644
--- a/drivers/video/pmag-ba-fb.c
+++ b/drivers/video/pmag-ba-fb.c
@@ -98,7 +98,8 @@ static int pmagbafb_setcolreg(unsigned int regno, unsigned int red,
98{ 98{
99 struct pmagbafb_par *par = info->par; 99 struct pmagbafb_par *par = info->par;
100 100
101 BUG_ON(regno >= info->cmap.len); 101 if (regno >= info->cmap.len)
102 return 1;
102 103
103 red >>= 8; /* The cmap fields are 16 bits */ 104 red >>= 8; /* The cmap fields are 16 bits */
104 green >>= 8; /* wide, but the hardware colormap */ 105 green >>= 8; /* wide, but the hardware colormap */
diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c
index 98748723af9f..2de0806421b4 100644
--- a/drivers/video/pmagb-b-fb.c
+++ b/drivers/video/pmagb-b-fb.c
@@ -102,7 +102,8 @@ static int pmagbbfb_setcolreg(unsigned int regno, unsigned int red,
102{ 102{
103 struct pmagbbfb_par *par = info->par; 103 struct pmagbbfb_par *par = info->par;
104 104
105 BUG_ON(regno >= info->cmap.len); 105 if (regno >= info->cmap.len)
106 return 1;
106 107
107 red >>= 8; /* The cmap fields are 16 bits */ 108 red >>= 8; /* The cmap fields are 16 bits */
108 green >>= 8; /* wide, but the hardware colormap */ 109 green >>= 8; /* wide, but the hardware colormap */
diff --git a/drivers/video/pnx4008/pnxrgbfb.c b/drivers/video/pnx4008/pnxrgbfb.c
index 4db6b48a8715..b2252fea2858 100644
--- a/drivers/video/pnx4008/pnxrgbfb.c
+++ b/drivers/video/pnx4008/pnxrgbfb.c
@@ -18,7 +18,6 @@
18#include <linux/errno.h> 18#include <linux/errno.h>
19#include <linux/string.h> 19#include <linux/string.h>
20#include <linux/mm.h> 20#include <linux/mm.h>
21#include <linux/slab.h>
22#include <linux/vmalloc.h> 21#include <linux/vmalloc.h>
23#include <linux/delay.h> 22#include <linux/delay.h>
24#include <linux/interrupt.h> 23#include <linux/interrupt.h>
diff --git a/drivers/video/pnx4008/sdum.c b/drivers/video/pnx4008/sdum.c
index 2aa09bce3944..5ec4f2d439c9 100644
--- a/drivers/video/pnx4008/sdum.c
+++ b/drivers/video/pnx4008/sdum.c
@@ -20,7 +20,6 @@
20#include <linux/string.h> 20#include <linux/string.h>
21#include <linux/mm.h> 21#include <linux/mm.h>
22#include <linux/tty.h> 22#include <linux/tty.h>
23#include <linux/slab.h>
24#include <linux/vmalloc.h> 23#include <linux/vmalloc.h>
25#include <linux/delay.h> 24#include <linux/delay.h>
26#include <linux/interrupt.h> 25#include <linux/interrupt.h>
@@ -29,6 +28,7 @@
29#include <linux/init.h> 28#include <linux/init.h>
30#include <linux/dma-mapping.h> 29#include <linux/dma-mapping.h>
31#include <linux/clk.h> 30#include <linux/clk.h>
31#include <linux/gfp.h>
32#include <asm/uaccess.h> 32#include <asm/uaccess.h>
33#include <mach/gpio.h> 33#include <mach/gpio.h>
34 34
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
index 53f8f1100e81..f9975100d56d 100644
--- a/drivers/video/pvr2fb.c
+++ b/drivers/video/pvr2fb.c
@@ -831,7 +831,7 @@ static int __devinit pvr2fb_common_init(void)
831 printk(KERN_NOTICE "fb%d: registering with SQ API\n", fb_info->node); 831 printk(KERN_NOTICE "fb%d: registering with SQ API\n", fb_info->node);
832 832
833 pvr2fb_map = sq_remap(fb_info->fix.smem_start, fb_info->fix.smem_len, 833 pvr2fb_map = sq_remap(fb_info->fix.smem_start, fb_info->fix.smem_len,
834 fb_info->fix.id, pgprot_val(PAGE_SHARED)); 834 fb_info->fix.id, PAGE_SHARED);
835 835
836 printk(KERN_NOTICE "fb%d: Mapped video memory to SQ addr 0x%lx\n", 836 printk(KERN_NOTICE "fb%d: Mapped video memory to SQ addr 0x%lx\n",
837 fb_info->node, pvr2fb_map); 837 fb_info->node, pvr2fb_map);
diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c
index 84d8327e47db..c91a7f70f7b0 100644
--- a/drivers/video/pxa168fb.c
+++ b/drivers/video/pxa168fb.c
@@ -668,7 +668,7 @@ static int __init pxa168fb_probe(struct platform_device *pdev)
668 /* 668 /*
669 * Map LCD controller registers. 669 * Map LCD controller registers.
670 */ 670 */
671 fbi->reg_base = ioremap_nocache(res->start, res->end - res->start); 671 fbi->reg_base = ioremap_nocache(res->start, resource_size(res));
672 if (fbi->reg_base == NULL) { 672 if (fbi->reg_base == NULL) {
673 ret = -ENOMEM; 673 ret = -ENOMEM;
674 goto failed; 674 goto failed;
@@ -687,6 +687,7 @@ static int __init pxa168fb_probe(struct platform_device *pdev)
687 } 687 }
688 688
689 info->fix.smem_start = (unsigned long)fbi->fb_start_dma; 689 info->fix.smem_start = (unsigned long)fbi->fb_start_dma;
690 set_graphics_start(info, 0, 0);
690 691
691 /* 692 /*
692 * Set video mode according to platform data. 693 * Set video mode according to platform data.
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 1820c4a24434..825b665245bb 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -80,7 +80,8 @@
80static int pxafb_activate_var(struct fb_var_screeninfo *var, 80static int pxafb_activate_var(struct fb_var_screeninfo *var,
81 struct pxafb_info *); 81 struct pxafb_info *);
82static void set_ctrlr_state(struct pxafb_info *fbi, u_int state); 82static void set_ctrlr_state(struct pxafb_info *fbi, u_int state);
83static void setup_base_frame(struct pxafb_info *fbi, int branch); 83static void setup_base_frame(struct pxafb_info *fbi,
84 struct fb_var_screeninfo *var, int branch);
84static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal, 85static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal,
85 unsigned long offset, size_t size); 86 unsigned long offset, size_t size);
86 87
@@ -397,6 +398,7 @@ static void pxafb_setmode(struct fb_var_screeninfo *var,
397 var->lower_margin = mode->lower_margin; 398 var->lower_margin = mode->lower_margin;
398 var->sync = mode->sync; 399 var->sync = mode->sync;
399 var->grayscale = mode->cmap_greyscale; 400 var->grayscale = mode->cmap_greyscale;
401 var->transp.length = mode->transparency;
400 402
401 /* set the initial RGBA bitfields */ 403 /* set the initial RGBA bitfields */
402 pxafb_set_pixfmt(var, mode->depth); 404 pxafb_set_pixfmt(var, mode->depth);
@@ -531,12 +533,22 @@ static int pxafb_pan_display(struct fb_var_screeninfo *var,
531 struct fb_info *info) 533 struct fb_info *info)
532{ 534{
533 struct pxafb_info *fbi = (struct pxafb_info *)info; 535 struct pxafb_info *fbi = (struct pxafb_info *)info;
536 struct fb_var_screeninfo newvar;
534 int dma = DMA_MAX + DMA_BASE; 537 int dma = DMA_MAX + DMA_BASE;
535 538
536 if (fbi->state != C_ENABLE) 539 if (fbi->state != C_ENABLE)
537 return 0; 540 return 0;
538 541
539 setup_base_frame(fbi, 1); 542 /* Only take .xoffset, .yoffset and .vmode & FB_VMODE_YWRAP from what
543 * was passed in and copy the rest from the old screeninfo.
544 */
545 memcpy(&newvar, &fbi->fb.var, sizeof(newvar));
546 newvar.xoffset = var->xoffset;
547 newvar.yoffset = var->yoffset;
548 newvar.vmode &= ~FB_VMODE_YWRAP;
549 newvar.vmode |= var->vmode & FB_VMODE_YWRAP;
550
551 setup_base_frame(fbi, &newvar, 1);
540 552
541 if (fbi->lccr0 & LCCR0_SDS) 553 if (fbi->lccr0 & LCCR0_SDS)
542 lcd_writel(fbi, FBR1, fbi->fdadr[dma + 1] | 0x1); 554 lcd_writel(fbi, FBR1, fbi->fdadr[dma + 1] | 0x1);
@@ -1052,9 +1064,10 @@ static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal,
1052 return 0; 1064 return 0;
1053} 1065}
1054 1066
1055static void setup_base_frame(struct pxafb_info *fbi, int branch) 1067static void setup_base_frame(struct pxafb_info *fbi,
1068 struct fb_var_screeninfo *var,
1069 int branch)
1056{ 1070{
1057 struct fb_var_screeninfo *var = &fbi->fb.var;
1058 struct fb_fix_screeninfo *fix = &fbi->fb.fix; 1071 struct fb_fix_screeninfo *fix = &fbi->fb.fix;
1059 int nbytes, dma, pal, bpp = var->bits_per_pixel; 1072 int nbytes, dma, pal, bpp = var->bits_per_pixel;
1060 unsigned long offset; 1073 unsigned long offset;
@@ -1210,11 +1223,12 @@ static int pxafb_smart_thread(void *arg)
1210 struct pxafb_info *fbi = arg; 1223 struct pxafb_info *fbi = arg;
1211 struct pxafb_mach_info *inf = fbi->dev->platform_data; 1224 struct pxafb_mach_info *inf = fbi->dev->platform_data;
1212 1225
1213 if (!fbi || !inf->smart_update) { 1226 if (!inf->smart_update) {
1214 pr_err("%s: not properly initialized, thread terminated\n", 1227 pr_err("%s: not properly initialized, thread terminated\n",
1215 __func__); 1228 __func__);
1216 return -EINVAL; 1229 return -EINVAL;
1217 } 1230 }
1231 inf = fbi->dev->platform_data;
1218 1232
1219 pr_debug("%s(): task starting\n", __func__); 1233 pr_debug("%s(): task starting\n", __func__);
1220 1234
@@ -1332,7 +1346,7 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var,
1332#endif 1346#endif
1333 setup_parallel_timing(fbi, var); 1347 setup_parallel_timing(fbi, var);
1334 1348
1335 setup_base_frame(fbi, 0); 1349 setup_base_frame(fbi, var, 0);
1336 1350
1337 fbi->reg_lccr0 = fbi->lccr0 | 1351 fbi->reg_lccr0 = fbi->lccr0 |
1338 (LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM | 1352 (LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM |
@@ -1654,7 +1668,7 @@ static int pxafb_resume(struct device *dev)
1654 return 0; 1668 return 0;
1655} 1669}
1656 1670
1657static struct dev_pm_ops pxafb_pm_ops = { 1671static const struct dev_pm_ops pxafb_pm_ops = {
1658 .suspend = pxafb_suspend, 1672 .suspend = pxafb_suspend,
1659 .resume = pxafb_resume, 1673 .resume = pxafb_resume,
1660}; 1674};
diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c
index 4beac1df617b..fc32c323a381 100644
--- a/drivers/video/q40fb.c
+++ b/drivers/video/q40fb.c
@@ -14,7 +14,6 @@
14#include <linux/errno.h> 14#include <linux/errno.h>
15#include <linux/string.h> 15#include <linux/string.h>
16#include <linux/mm.h> 16#include <linux/mm.h>
17#include <linux/slab.h>
18#include <linux/delay.h> 17#include <linux/delay.h>
19#include <linux/interrupt.h> 18#include <linux/interrupt.h>
20#include <linux/platform_device.h> 19#include <linux/platform_device.h>
@@ -85,7 +84,7 @@ static struct fb_ops q40fb_ops = {
85 .fb_imageblit = cfb_imageblit, 84 .fb_imageblit = cfb_imageblit,
86}; 85};
87 86
88static int __init q40fb_probe(struct platform_device *dev) 87static int __devinit q40fb_probe(struct platform_device *dev)
89{ 88{
90 struct fb_info *info; 89 struct fb_info *info;
91 90
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index d94c57ffbdb1..618f36bec10d 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -338,6 +338,7 @@ static struct backlight_ops riva_bl_ops = {
338 338
339static void riva_bl_init(struct riva_par *par) 339static void riva_bl_init(struct riva_par *par)
340{ 340{
341 struct backlight_properties props;
341 struct fb_info *info = pci_get_drvdata(par->pdev); 342 struct fb_info *info = pci_get_drvdata(par->pdev);
342 struct backlight_device *bd; 343 struct backlight_device *bd;
343 char name[12]; 344 char name[12];
@@ -353,7 +354,10 @@ static void riva_bl_init(struct riva_par *par)
353 354
354 snprintf(name, sizeof(name), "rivabl%d", info->node); 355 snprintf(name, sizeof(name), "rivabl%d", info->node);
355 356
356 bd = backlight_device_register(name, info->dev, par, &riva_bl_ops); 357 memset(&props, 0, sizeof(struct backlight_properties));
358 props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
359 bd = backlight_device_register(name, info->dev, par, &riva_bl_ops,
360 &props);
357 if (IS_ERR(bd)) { 361 if (IS_ERR(bd)) {
358 info->bl_dev = NULL; 362 info->bl_dev = NULL;
359 printk(KERN_WARNING "riva: Backlight registration failed\n"); 363 printk(KERN_WARNING "riva: Backlight registration failed\n");
@@ -365,7 +369,6 @@ static void riva_bl_init(struct riva_par *par)
365 MIN_LEVEL * FB_BACKLIGHT_MAX / MAX_LEVEL, 369 MIN_LEVEL * FB_BACKLIGHT_MAX / MAX_LEVEL,
366 FB_BACKLIGHT_MAX); 370 FB_BACKLIGHT_MAX);
367 371
368 bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
369 bd->props.brightness = bd->props.max_brightness; 372 bd->props.brightness = bd->props.max_brightness;
370 bd->props.power = FB_BLANK_UNBLANK; 373 bd->props.power = FB_BLANK_UNBLANK;
371 backlight_update_status(bd); 374 backlight_update_status(bd);
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c
index 0deb0a8867b7..a6247fc081ab 100644
--- a/drivers/video/s1d13xxxfb.c
+++ b/drivers/video/s1d13xxxfb.c
@@ -31,6 +31,7 @@
31#include <linux/fb.h> 31#include <linux/fb.h>
32#include <linux/spinlock_types.h> 32#include <linux/spinlock_types.h>
33#include <linux/spinlock.h> 33#include <linux/spinlock.h>
34#include <linux/slab.h>
34 35
35#include <asm/io.h> 36#include <asm/io.h>
36 37
@@ -517,12 +518,12 @@ s1d13xxxfb_bitblt_copyarea(struct fb_info *info, const struct fb_copyarea *area)
517 src = (sy * stride) + (bpp * sx); 518 src = (sy * stride) + (bpp * sx);
518 } 519 }
519 520
520 /* set source adress */ 521 /* set source address */
521 s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START0, (src & 0xff)); 522 s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START0, (src & 0xff));
522 s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START1, (src >> 8) & 0x00ff); 523 s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START1, (src >> 8) & 0x00ff);
523 s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START2, (src >> 16) & 0x00ff); 524 s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START2, (src >> 16) & 0x00ff);
524 525
525 /* set destination adress */ 526 /* set destination address */
526 s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START0, (dst & 0xff)); 527 s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START0, (dst & 0xff));
527 s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START1, (dst >> 8) & 0x00ff); 528 s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START1, (dst >> 8) & 0x00ff);
528 s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START2, (dst >> 16) & 0x00ff); 529 s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START2, (dst >> 16) & 0x00ff);
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index adf9632c6b1f..9682ecc60e12 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -16,8 +16,8 @@
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/dma-mapping.h> 18#include <linux/dma-mapping.h>
19#include <linux/slab.h>
19#include <linux/init.h> 20#include <linux/init.h>
20#include <linux/gfp.h>
21#include <linux/clk.h> 21#include <linux/clk.h>
22#include <linux/fb.h> 22#include <linux/fb.h>
23#include <linux/io.h> 23#include <linux/io.h>
@@ -211,21 +211,23 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
211 211
212/** 212/**
213 * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock. 213 * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock.
214 * @id: window id.
215 * @sfb: The hardware state. 214 * @sfb: The hardware state.
216 * @pixclock: The pixel clock wanted, in picoseconds. 215 * @pixclock: The pixel clock wanted, in picoseconds.
217 * 216 *
218 * Given the specified pixel clock, work out the necessary divider to get 217 * Given the specified pixel clock, work out the necessary divider to get
219 * close to the output frequency. 218 * close to the output frequency.
220 */ 219 */
221static int s3c_fb_calc_pixclk(unsigned char id, struct s3c_fb *sfb, unsigned int pixclk) 220static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk)
222{ 221{
223 struct s3c_fb_pd_win *win = sfb->pdata->win[id];
224 unsigned long clk = clk_get_rate(sfb->bus_clk); 222 unsigned long clk = clk_get_rate(sfb->bus_clk);
223 unsigned long long tmp;
225 unsigned int result; 224 unsigned int result;
226 225
227 pixclk *= win->win_mode.refresh; 226 tmp = (unsigned long long)clk;
228 result = clk / pixclk; 227 tmp *= pixclk;
228
229 do_div(tmp, 1000000000UL);
230 result = (unsigned int)tmp / 1000;
229 231
230 dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n", 232 dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n",
231 pixclk, clk, result, clk / result); 233 pixclk, clk, result, clk / result);
@@ -301,7 +303,7 @@ static int s3c_fb_set_par(struct fb_info *info)
301 /* use window 0 as the basis for the lcd output timings */ 303 /* use window 0 as the basis for the lcd output timings */
302 304
303 if (win_no == 0) { 305 if (win_no == 0) {
304 clkdiv = s3c_fb_calc_pixclk(win_no, sfb, var->pixclock); 306 clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock);
305 307
306 data = sfb->pdata->vidcon0; 308 data = sfb->pdata->vidcon0;
307 data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR); 309 data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index aac661225c78..2b094dec4a56 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -1004,12 +1004,12 @@ dealloc_fb:
1004 return ret; 1004 return ret;
1005} 1005}
1006 1006
1007static int __init s3c2410fb_probe(struct platform_device *pdev) 1007static int __devinit s3c2410fb_probe(struct platform_device *pdev)
1008{ 1008{
1009 return s3c24xxfb_probe(pdev, DRV_S3C2410); 1009 return s3c24xxfb_probe(pdev, DRV_S3C2410);
1010} 1010}
1011 1011
1012static int __init s3c2412fb_probe(struct platform_device *pdev) 1012static int __devinit s3c2412fb_probe(struct platform_device *pdev)
1013{ 1013{
1014 return s3c24xxfb_probe(pdev, DRV_S3C2412); 1014 return s3c24xxfb_probe(pdev, DRV_S3C2412);
1015} 1015}
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c
index c3fad34309ed..d4471b4c0374 100644
--- a/drivers/video/s3fb.c
+++ b/drivers/video/s3fb.c
@@ -17,7 +17,6 @@
17#include <linux/string.h> 17#include <linux/string.h>
18#include <linux/mm.h> 18#include <linux/mm.h>
19#include <linux/tty.h> 19#include <linux/tty.h>
20#include <linux/slab.h>
21#include <linux/delay.h> 20#include <linux/delay.h>
22#include <linux/fb.h> 21#include <linux/fb.h>
23#include <linux/svga.h> 22#include <linux/svga.h>
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index cdaa873a6054..e8b76d65a070 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -1435,7 +1435,7 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
1435 return fbi; 1435 return fbi;
1436} 1436}
1437 1437
1438static int __init sa1100fb_probe(struct platform_device *pdev) 1438static int __devinit sa1100fb_probe(struct platform_device *pdev)
1439{ 1439{
1440 struct sa1100fb_info *fbi; 1440 struct sa1100fb_info *fbi;
1441 int ret, irq; 1441 int ret, irq;
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c
index 574b29e9f8f2..ed371c868b3a 100644
--- a/drivers/video/savage/savagefb-i2c.c
+++ b/drivers/video/savage/savagefb-i2c.c
@@ -13,6 +13,7 @@
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/delay.h> 15#include <linux/delay.h>
16#include <linux/gfp.h>
16#include <linux/pci.h> 17#include <linux/pci.h>
17#include <linux/fb.h> 18#include <linux/fb.h>
18 19
diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c
index bba53714a7b1..7a3a5e28eca1 100644
--- a/drivers/video/sgivwfb.c
+++ b/drivers/video/sgivwfb.c
@@ -260,13 +260,13 @@ static int sgivwfb_check_var(struct fb_var_screeninfo *var,
260 var->grayscale = 0; /* No grayscale for now */ 260 var->grayscale = 0; /* No grayscale for now */
261 261
262 /* determine valid resolution and timing */ 262 /* determine valid resolution and timing */
263 for (min_mode = 0; min_mode < DBE_VT_SIZE; min_mode++) { 263 for (min_mode = 0; min_mode < ARRAY_SIZE(dbeVTimings); min_mode++) {
264 if (dbeVTimings[min_mode].width >= var->xres && 264 if (dbeVTimings[min_mode].width >= var->xres &&
265 dbeVTimings[min_mode].height >= var->yres) 265 dbeVTimings[min_mode].height >= var->yres)
266 break; 266 break;
267 } 267 }
268 268
269 if (min_mode == DBE_VT_SIZE) 269 if (min_mode == ARRAY_SIZE(dbeVTimings))
270 return -EINVAL; /* Resolution to high */ 270 return -EINVAL; /* Resolution to high */
271 271
272 /* XXX FIXME - should try to pick best refresh rate */ 272 /* XXX FIXME - should try to pick best refresh rate */
@@ -745,7 +745,7 @@ int __init sgivwfb_setup(char *options)
745/* 745/*
746 * Initialisation 746 * Initialisation
747 */ 747 */
748static int __init sgivwfb_probe(struct platform_device *dev) 748static int __devinit sgivwfb_probe(struct platform_device *dev)
749{ 749{
750 struct sgivw_par *par; 750 struct sgivw_par *par;
751 struct fb_info *info; 751 struct fb_info *info;
diff --git a/drivers/video/sh7760fb.c b/drivers/video/sh7760fb.c
index 9f6d6e61f0cc..bea38fce2470 100644
--- a/drivers/video/sh7760fb.c
+++ b/drivers/video/sh7760fb.c
@@ -26,6 +26,7 @@
26#include <linux/kernel.h> 26#include <linux/kernel.h>
27#include <linux/module.h> 27#include <linux/module.h>
28#include <linux/platform_device.h> 28#include <linux/platform_device.h>
29#include <linux/slab.h>
29 30
30#include <asm/sh7760fb.h> 31#include <asm/sh7760fb.h>
31 32
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 3ad5157f9899..e8c769944812 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -19,6 +19,8 @@
19#include <linux/dma-mapping.h> 19#include <linux/dma-mapping.h>
20#include <linux/interrupt.h> 20#include <linux/interrupt.h>
21#include <linux/vmalloc.h> 21#include <linux/vmalloc.h>
22#include <linux/ioctl.h>
23#include <linux/slab.h>
22#include <video/sh_mobile_lcdc.h> 24#include <video/sh_mobile_lcdc.h>
23#include <asm/atomic.h> 25#include <asm/atomic.h>
24 26
@@ -106,6 +108,7 @@ static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = {
106#define LDRCNTR_SRC 0x00010000 108#define LDRCNTR_SRC 0x00010000
107#define LDRCNTR_MRS 0x00000002 109#define LDRCNTR_MRS 0x00000002
108#define LDRCNTR_MRC 0x00000001 110#define LDRCNTR_MRC 0x00000001
111#define LDSR_MRS 0x00000100
109 112
110struct sh_mobile_lcdc_priv; 113struct sh_mobile_lcdc_priv;
111struct sh_mobile_lcdc_chan { 114struct sh_mobile_lcdc_chan {
@@ -122,8 +125,8 @@ struct sh_mobile_lcdc_chan {
122 struct scatterlist *sglist; 125 struct scatterlist *sglist;
123 unsigned long frame_end; 126 unsigned long frame_end;
124 unsigned long pan_offset; 127 unsigned long pan_offset;
125 unsigned long new_pan_offset;
126 wait_queue_head_t frame_end_wait; 128 wait_queue_head_t frame_end_wait;
129 struct completion vsync_completion;
127}; 130};
128 131
129struct sh_mobile_lcdc_priv { 132struct sh_mobile_lcdc_priv {
@@ -281,18 +284,42 @@ static void sh_mobile_lcdc_deferred_io(struct fb_info *info,
281 struct list_head *pagelist) 284 struct list_head *pagelist)
282{ 285{
283 struct sh_mobile_lcdc_chan *ch = info->par; 286 struct sh_mobile_lcdc_chan *ch = info->par;
284 unsigned int nr_pages; 287 struct sh_mobile_lcdc_board_cfg *bcfg = &ch->cfg.board_cfg;
285 288
286 /* enable clocks before accessing hardware */ 289 /* enable clocks before accessing hardware */
287 sh_mobile_lcdc_clk_on(ch->lcdc); 290 sh_mobile_lcdc_clk_on(ch->lcdc);
288 291
289 nr_pages = sh_mobile_lcdc_sginit(info, pagelist); 292 /*
290 dma_map_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE); 293 * It's possible to get here without anything on the pagelist via
291 294 * sh_mobile_lcdc_deferred_io_touch() or via a userspace fsync()
292 /* trigger panel update */ 295 * invocation. In the former case, the acceleration routines are
293 lcdc_write_chan(ch, LDSM2R, 1); 296 * stepped in to when using the framebuffer console causing the
294 297 * workqueue to be scheduled without any dirty pages on the list.
295 dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE); 298 *
299 * Despite this, a panel update is still needed given that the
300 * acceleration routines have their own methods for writing in
301 * that still need to be updated.
302 *
303 * The fsync() and empty pagelist case could be optimized for,
304 * but we don't bother, as any application exhibiting such
305 * behaviour is fundamentally broken anyways.
306 */
307 if (!list_empty(pagelist)) {
308 unsigned int nr_pages = sh_mobile_lcdc_sginit(info, pagelist);
309
310 /* trigger panel update */
311 dma_map_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
312 if (bcfg->start_transfer)
313 bcfg->start_transfer(bcfg->board_data, ch,
314 &sh_mobile_lcdc_sys_bus_ops);
315 lcdc_write_chan(ch, LDSM2R, 1);
316 dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
317 } else {
318 if (bcfg->start_transfer)
319 bcfg->start_transfer(bcfg->board_data, ch,
320 &sh_mobile_lcdc_sys_bus_ops);
321 lcdc_write_chan(ch, LDSM2R, 1);
322 }
296} 323}
297 324
298static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info) 325static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info)
@@ -342,19 +369,8 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
342 } 369 }
343 370
344 /* VSYNC End */ 371 /* VSYNC End */
345 if (ldintr & LDINTR_VES) { 372 if (ldintr & LDINTR_VES)
346 unsigned long ldrcntr = lcdc_read(priv, _LDRCNTR); 373 complete(&ch->vsync_completion);
347 /* Set the source address for the next refresh */
348 lcdc_write_chan_mirror(ch, LDSA1R, ch->dma_handle +
349 ch->new_pan_offset);
350 if (lcdc_chan_is_sublcd(ch))
351 lcdc_write(ch->lcdc, _LDRCNTR,
352 ldrcntr ^ LDRCNTR_SRS);
353 else
354 lcdc_write(ch->lcdc, _LDRCNTR,
355 ldrcntr ^ LDRCNTR_MRS);
356 ch->pan_offset = ch->new_pan_offset;
357 }
358 } 374 }
359 375
360 return IRQ_HANDLED; 376 return IRQ_HANDLED;
@@ -679,6 +695,7 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
679 * 1) Enable Runtime PM 695 * 1) Enable Runtime PM
680 * 2) Force Runtime PM Resume since hardware is accessed from probe() 696 * 2) Force Runtime PM Resume since hardware is accessed from probe()
681 */ 697 */
698 priv->dev = &pdev->dev;
682 pm_runtime_enable(priv->dev); 699 pm_runtime_enable(priv->dev);
683 pm_runtime_resume(priv->dev); 700 pm_runtime_resume(priv->dev);
684 return 0; 701 return 0;
@@ -743,25 +760,69 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
743 struct fb_info *info) 760 struct fb_info *info)
744{ 761{
745 struct sh_mobile_lcdc_chan *ch = info->par; 762 struct sh_mobile_lcdc_chan *ch = info->par;
763 struct sh_mobile_lcdc_priv *priv = ch->lcdc;
764 unsigned long ldrcntr;
765 unsigned long new_pan_offset;
766
767 new_pan_offset = (var->yoffset * info->fix.line_length) +
768 (var->xoffset * (info->var.bits_per_pixel / 8));
746 769
747 if (info->var.xoffset == var->xoffset && 770 if (new_pan_offset == ch->pan_offset)
748 info->var.yoffset == var->yoffset)
749 return 0; /* No change, do nothing */ 771 return 0; /* No change, do nothing */
750 772
751 ch->new_pan_offset = (var->yoffset * info->fix.line_length) + 773 ldrcntr = lcdc_read(priv, _LDRCNTR);
752 (var->xoffset * (info->var.bits_per_pixel / 8));
753 774
754 if (ch->new_pan_offset != ch->pan_offset) { 775 /* Set the source address for the next refresh */
755 unsigned long ldintr; 776 lcdc_write_chan_mirror(ch, LDSA1R, ch->dma_handle + new_pan_offset);
756 ldintr = lcdc_read(ch->lcdc, _LDINTR); 777 if (lcdc_chan_is_sublcd(ch))
757 ldintr |= LDINTR_VEE; 778 lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS);
758 lcdc_write(ch->lcdc, _LDINTR, ldintr); 779 else
759 sh_mobile_lcdc_deferred_io_touch(info); 780 lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_MRS);
760 } 781
782 ch->pan_offset = new_pan_offset;
783
784 sh_mobile_lcdc_deferred_io_touch(info);
761 785
762 return 0; 786 return 0;
763} 787}
764 788
789static int sh_mobile_wait_for_vsync(struct fb_info *info)
790{
791 struct sh_mobile_lcdc_chan *ch = info->par;
792 unsigned long ldintr;
793 int ret;
794
795 /* Enable VSync End interrupt */
796 ldintr = lcdc_read(ch->lcdc, _LDINTR);
797 ldintr |= LDINTR_VEE;
798 lcdc_write(ch->lcdc, _LDINTR, ldintr);
799
800 ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion,
801 msecs_to_jiffies(100));
802 if (!ret)
803 return -ETIMEDOUT;
804
805 return 0;
806}
807
808static int sh_mobile_ioctl(struct fb_info *info, unsigned int cmd,
809 unsigned long arg)
810{
811 int retval;
812
813 switch (cmd) {
814 case FBIO_WAITFORVSYNC:
815 retval = sh_mobile_wait_for_vsync(info);
816 break;
817
818 default:
819 retval = -ENOIOCTLCMD;
820 break;
821 }
822 return retval;
823}
824
825
765static struct fb_ops sh_mobile_lcdc_ops = { 826static struct fb_ops sh_mobile_lcdc_ops = {
766 .owner = THIS_MODULE, 827 .owner = THIS_MODULE,
767 .fb_setcolreg = sh_mobile_lcdc_setcolreg, 828 .fb_setcolreg = sh_mobile_lcdc_setcolreg,
@@ -771,6 +832,7 @@ static struct fb_ops sh_mobile_lcdc_ops = {
771 .fb_copyarea = sh_mobile_lcdc_copyarea, 832 .fb_copyarea = sh_mobile_lcdc_copyarea,
772 .fb_imageblit = sh_mobile_lcdc_imageblit, 833 .fb_imageblit = sh_mobile_lcdc_imageblit,
773 .fb_pan_display = sh_mobile_fb_pan_display, 834 .fb_pan_display = sh_mobile_fb_pan_display,
835 .fb_ioctl = sh_mobile_ioctl,
774}; 836};
775 837
776static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp) 838static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp)
@@ -874,7 +936,7 @@ static int sh_mobile_lcdc_runtime_resume(struct device *dev)
874 return 0; 936 return 0;
875} 937}
876 938
877static struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = { 939static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = {
878 .suspend = sh_mobile_lcdc_suspend, 940 .suspend = sh_mobile_lcdc_suspend,
879 .resume = sh_mobile_lcdc_resume, 941 .resume = sh_mobile_lcdc_resume,
880 .runtime_suspend = sh_mobile_lcdc_runtime_suspend, 942 .runtime_suspend = sh_mobile_lcdc_runtime_suspend,
@@ -883,7 +945,7 @@ static struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = {
883 945
884static int sh_mobile_lcdc_remove(struct platform_device *pdev); 946static int sh_mobile_lcdc_remove(struct platform_device *pdev);
885 947
886static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) 948static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
887{ 949{
888 struct fb_info *info; 950 struct fb_info *info;
889 struct sh_mobile_lcdc_priv *priv; 951 struct sh_mobile_lcdc_priv *priv;
@@ -896,25 +958,24 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
896 958
897 if (!pdev->dev.platform_data) { 959 if (!pdev->dev.platform_data) {
898 dev_err(&pdev->dev, "no platform data defined\n"); 960 dev_err(&pdev->dev, "no platform data defined\n");
899 error = -EINVAL; 961 return -EINVAL;
900 goto err0;
901 } 962 }
902 963
903 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 964 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
904 i = platform_get_irq(pdev, 0); 965 i = platform_get_irq(pdev, 0);
905 if (!res || i < 0) { 966 if (!res || i < 0) {
906 dev_err(&pdev->dev, "cannot get platform resources\n"); 967 dev_err(&pdev->dev, "cannot get platform resources\n");
907 error = -ENOENT; 968 return -ENOENT;
908 goto err0;
909 } 969 }
910 970
911 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 971 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
912 if (!priv) { 972 if (!priv) {
913 dev_err(&pdev->dev, "cannot allocate device data\n"); 973 dev_err(&pdev->dev, "cannot allocate device data\n");
914 error = -ENOMEM; 974 return -ENOMEM;
915 goto err0;
916 } 975 }
917 976
977 platform_set_drvdata(pdev, priv);
978
918 error = request_irq(i, sh_mobile_lcdc_irq, IRQF_DISABLED, 979 error = request_irq(i, sh_mobile_lcdc_irq, IRQF_DISABLED,
919 dev_name(&pdev->dev), priv); 980 dev_name(&pdev->dev), priv);
920 if (error) { 981 if (error) {
@@ -923,8 +984,6 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
923 } 984 }
924 985
925 priv->irq = i; 986 priv->irq = i;
926 priv->dev = &pdev->dev;
927 platform_set_drvdata(pdev, priv);
928 pdata = pdev->dev.platform_data; 987 pdata = pdev->dev.platform_data;
929 988
930 j = 0; 989 j = 0;
@@ -938,8 +997,8 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
938 goto err1; 997 goto err1;
939 } 998 }
940 init_waitqueue_head(&priv->ch[i].frame_end_wait); 999 init_waitqueue_head(&priv->ch[i].frame_end_wait);
1000 init_completion(&priv->ch[i].vsync_completion);
941 priv->ch[j].pan_offset = 0; 1001 priv->ch[j].pan_offset = 0;
942 priv->ch[j].new_pan_offset = 0;
943 1002
944 switch (pdata->ch[i].chan) { 1003 switch (pdata->ch[i].chan) {
945 case LCDC_CHAN_MAINLCD: 1004 case LCDC_CHAN_MAINLCD:
@@ -1038,9 +1097,9 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
1038 info = ch->info; 1097 info = ch->info;
1039 1098
1040 if (info->fbdefio) { 1099 if (info->fbdefio) {
1041 priv->ch->sglist = vmalloc(sizeof(struct scatterlist) * 1100 ch->sglist = vmalloc(sizeof(struct scatterlist) *
1042 info->fix.smem_len >> PAGE_SHIFT); 1101 info->fix.smem_len >> PAGE_SHIFT);
1043 if (!priv->ch->sglist) { 1102 if (!ch->sglist) {
1044 dev_err(&pdev->dev, "cannot allocate sglist\n"); 1103 dev_err(&pdev->dev, "cannot allocate sglist\n");
1045 goto err1; 1104 goto err1;
1046 } 1105 }
@@ -1065,9 +1124,9 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
1065 } 1124 }
1066 1125
1067 return 0; 1126 return 0;
1068 err1: 1127err1:
1069 sh_mobile_lcdc_remove(pdev); 1128 sh_mobile_lcdc_remove(pdev);
1070 err0: 1129
1071 return error; 1130 return error;
1072} 1131}
1073 1132
@@ -1078,7 +1137,7 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
1078 int i; 1137 int i;
1079 1138
1080 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) 1139 for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
1081 if (priv->ch[i].info->dev) 1140 if (priv->ch[i].info && priv->ch[i].info->dev)
1082 unregister_framebuffer(priv->ch[i].info); 1141 unregister_framebuffer(priv->ch[i].info);
1083 1142
1084 sh_mobile_lcdc_stop(priv); 1143 sh_mobile_lcdc_stop(priv);
@@ -1101,7 +1160,8 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
1101 if (priv->dot_clk) 1160 if (priv->dot_clk)
1102 clk_put(priv->dot_clk); 1161 clk_put(priv->dot_clk);
1103 1162
1104 pm_runtime_disable(priv->dev); 1163 if (priv->dev)
1164 pm_runtime_disable(priv->dev);
1105 1165
1106 if (priv->base) 1166 if (priv->base)
1107 iounmap(priv->base); 1167 iounmap(priv->base);
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index a4e05e4d7501..a531a0f7cdf2 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -1891,9 +1891,6 @@ static struct fb_ops sisfb_ops = {
1891 .fb_fillrect = fbcon_sis_fillrect, 1891 .fb_fillrect = fbcon_sis_fillrect,
1892 .fb_copyarea = fbcon_sis_copyarea, 1892 .fb_copyarea = fbcon_sis_copyarea,
1893 .fb_imageblit = cfb_imageblit, 1893 .fb_imageblit = cfb_imageblit,
1894#ifdef CONFIG_FB_SOFT_CURSOR
1895 .fb_cursor = soft_cursor,
1896#endif
1897 .fb_sync = fbcon_sis_sync, 1894 .fb_sync = fbcon_sis_sync,
1898#ifdef SIS_NEW_CONFIG_COMPAT 1895#ifdef SIS_NEW_CONFIG_COMPAT
1899 .fb_compat_ioctl= sisfb_ioctl, 1896 .fb_compat_ioctl= sisfb_ioctl,
@@ -2115,7 +2112,7 @@ sisfb_detect_VB_connect(struct sis_video_info *ivideo)
2115 if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) && 2112 if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) &&
2116 (!((ivideo->sisvga_engine == SIS_315_VGA) && 2113 (!((ivideo->sisvga_engine == SIS_315_VGA) &&
2117 (ivideo->vbflags2 & VB2_CHRONTEL))) ) { 2114 (ivideo->vbflags2 & VB2_CHRONTEL))) ) {
2118 if(ivideo->sisfb_tvstd & (TV_PALN | TV_PALN | TV_NTSCJ)) { 2115 if(ivideo->sisfb_tvstd & (TV_PALM | TV_PALN | TV_NTSCJ)) {
2119 ivideo->sisfb_tvstd = -1; 2116 ivideo->sisfb_tvstd = -1;
2120 printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n"); 2117 printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
2121 } 2118 }
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index 924d79462780..b7dc1800efa9 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -29,8 +29,8 @@
29#include <linux/platform_device.h> 29#include <linux/platform_device.h>
30#include <linux/clk.h> 30#include <linux/clk.h>
31#include <linux/console.h> 31#include <linux/console.h>
32#include <linux/io.h>
32 33
33#include <asm/io.h>
34#include <asm/uaccess.h> 34#include <asm/uaccess.h>
35#include <asm/div64.h> 35#include <asm/div64.h>
36 36
@@ -66,6 +66,7 @@ struct sm501fb_info {
66 struct fb_info *fb[2]; /* fb info for both heads */ 66 struct fb_info *fb[2]; /* fb info for both heads */
67 struct resource *fbmem_res; /* framebuffer resource */ 67 struct resource *fbmem_res; /* framebuffer resource */
68 struct resource *regs_res; /* registers resource */ 68 struct resource *regs_res; /* registers resource */
69 struct resource *regs2d_res; /* 2d registers resource */
69 struct sm501_platdata_fb *pdata; /* our platform data */ 70 struct sm501_platdata_fb *pdata; /* our platform data */
70 71
71 unsigned long pm_crt_ctrl; /* pm: crt ctrl save */ 72 unsigned long pm_crt_ctrl; /* pm: crt ctrl save */
@@ -73,6 +74,7 @@ struct sm501fb_info {
73 int irq; 74 int irq;
74 int swap_endian; /* set to swap rgb=>bgr */ 75 int swap_endian; /* set to swap rgb=>bgr */
75 void __iomem *regs; /* remapped registers */ 76 void __iomem *regs; /* remapped registers */
77 void __iomem *regs2d; /* 2d remapped registers */
76 void __iomem *fbmem; /* remapped framebuffer */ 78 void __iomem *fbmem; /* remapped framebuffer */
77 size_t fbmem_len; /* length of remapped region */ 79 size_t fbmem_len; /* length of remapped region */
78}; 80};
@@ -123,9 +125,9 @@ static inline void sm501fb_sync_regs(struct sm501fb_info *info)
123 * This is an attempt to lay out memory for the two framebuffers and 125 * This is an attempt to lay out memory for the two framebuffers and
124 * everything else 126 * everything else
125 * 127 *
126 * |fbmem_res->start fbmem_res->end| 128 * |fbmem_res->start fbmem_res->end|
127 * | | 129 * | |
128 * |fb[0].fix.smem_start | |fb[1].fix.smem_start | 2K | 130 * |fb[0].fix.smem_start | |fb[1].fix.smem_start | 2K |
129 * |-> fb[0].fix.smem_len <-| spare |-> fb[1].fix.smem_len <-|-> cursors <-| 131 * |-> fb[0].fix.smem_len <-| spare |-> fb[1].fix.smem_len <-|-> cursors <-|
130 * 132 *
131 * The "spare" space is for the 2d engine data 133 * The "spare" space is for the 2d engine data
@@ -409,7 +411,7 @@ static int sm501fb_set_par_common(struct fb_info *info,
409 struct sm501fb_par *par = info->par; 411 struct sm501fb_par *par = info->par;
410 struct sm501fb_info *fbi = par->info; 412 struct sm501fb_info *fbi = par->info;
411 unsigned long pixclock; /* pixelclock in Hz */ 413 unsigned long pixclock; /* pixelclock in Hz */
412 unsigned long sm501pixclock; /* pixelclock the 501 can achive in Hz */ 414 unsigned long sm501pixclock; /* pixelclock the 501 can achieve in Hz */
413 unsigned int mem_type; 415 unsigned int mem_type;
414 unsigned int clock_type; 416 unsigned int clock_type;
415 unsigned int head_addr; 417 unsigned int head_addr;
@@ -1246,7 +1248,173 @@ static ssize_t sm501fb_debug_show_pnl(struct device *dev,
1246 1248
1247static DEVICE_ATTR(fbregs_pnl, 0444, sm501fb_debug_show_pnl, NULL); 1249static DEVICE_ATTR(fbregs_pnl, 0444, sm501fb_debug_show_pnl, NULL);
1248 1250
1249/* framebuffer ops */ 1251/* acceleration operations */
1252static int sm501fb_sync(struct fb_info *info)
1253{
1254 int count = 1000000;
1255 struct sm501fb_par *par = info->par;
1256 struct sm501fb_info *fbi = par->info;
1257
1258 /* wait for the 2d engine to be ready */
1259 while ((count > 0) &&
1260 (readl(fbi->regs + SM501_SYSTEM_CONTROL) &
1261 SM501_SYSCTRL_2D_ENGINE_STATUS) != 0)
1262 count--;
1263
1264 if (count <= 0) {
1265 dev_err(info->dev, "Timeout waiting for 2d engine sync\n");
1266 return 1;
1267 }
1268 return 0;
1269}
1270
1271static void sm501fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
1272{
1273 struct sm501fb_par *par = info->par;
1274 struct sm501fb_info *fbi = par->info;
1275 int width = area->width;
1276 int height = area->height;
1277 int sx = area->sx;
1278 int sy = area->sy;
1279 int dx = area->dx;
1280 int dy = area->dy;
1281 unsigned long rtl = 0;
1282
1283 /* source clip */
1284 if ((sx >= info->var.xres_virtual) ||
1285 (sy >= info->var.yres_virtual))
1286 /* source Area not within virtual screen, skipping */
1287 return;
1288 if ((sx + width) >= info->var.xres_virtual)
1289 width = info->var.xres_virtual - sx - 1;
1290 if ((sy + height) >= info->var.yres_virtual)
1291 height = info->var.yres_virtual - sy - 1;
1292
1293 /* dest clip */
1294 if ((dx >= info->var.xres_virtual) ||
1295 (dy >= info->var.yres_virtual))
1296 /* Destination Area not within virtual screen, skipping */
1297 return;
1298 if ((dx + width) >= info->var.xres_virtual)
1299 width = info->var.xres_virtual - dx - 1;
1300 if ((dy + height) >= info->var.yres_virtual)
1301 height = info->var.yres_virtual - dy - 1;
1302
1303 if ((sx < dx) || (sy < dy)) {
1304 rtl = 1 << 27;
1305 sx += width - 1;
1306 dx += width - 1;
1307 sy += height - 1;
1308 dy += height - 1;
1309 }
1310
1311 if (sm501fb_sync(info))
1312 return;
1313
1314 /* set the base addresses */
1315 writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
1316 writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_DESTINATION_BASE);
1317
1318 /* set the window width */
1319 writel((info->var.xres << 16) | info->var.xres,
1320 fbi->regs2d + SM501_2D_WINDOW_WIDTH);
1321
1322 /* set window stride */
1323 writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
1324 fbi->regs2d + SM501_2D_PITCH);
1325
1326 /* set data format */
1327 switch (info->var.bits_per_pixel) {
1328 case 8:
1329 writel(0, fbi->regs2d + SM501_2D_STRETCH);
1330 break;
1331 case 16:
1332 writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
1333 break;
1334 case 32:
1335 writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
1336 break;
1337 }
1338
1339 /* 2d compare mask */
1340 writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
1341
1342 /* 2d mask */
1343 writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
1344
1345 /* source and destination x y */
1346 writel((sx << 16) | sy, fbi->regs2d + SM501_2D_SOURCE);
1347 writel((dx << 16) | dy, fbi->regs2d + SM501_2D_DESTINATION);
1348
1349 /* w/h */
1350 writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
1351
1352 /* do area move */
1353 writel(0x800000cc | rtl, fbi->regs2d + SM501_2D_CONTROL);
1354}
1355
1356static void sm501fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
1357{
1358 struct sm501fb_par *par = info->par;
1359 struct sm501fb_info *fbi = par->info;
1360 int width = rect->width, height = rect->height;
1361
1362 if ((rect->dx >= info->var.xres_virtual) ||
1363 (rect->dy >= info->var.yres_virtual))
1364 /* Rectangle not within virtual screen, skipping */
1365 return;
1366 if ((rect->dx + width) >= info->var.xres_virtual)
1367 width = info->var.xres_virtual - rect->dx - 1;
1368 if ((rect->dy + height) >= info->var.yres_virtual)
1369 height = info->var.yres_virtual - rect->dy - 1;
1370
1371 if (sm501fb_sync(info))
1372 return;
1373
1374 /* set the base addresses */
1375 writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
1376 writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_DESTINATION_BASE);
1377
1378 /* set the window width */
1379 writel((info->var.xres << 16) | info->var.xres,
1380 fbi->regs2d + SM501_2D_WINDOW_WIDTH);
1381
1382 /* set window stride */
1383 writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
1384 fbi->regs2d + SM501_2D_PITCH);
1385
1386 /* set data format */
1387 switch (info->var.bits_per_pixel) {
1388 case 8:
1389 writel(0, fbi->regs2d + SM501_2D_STRETCH);
1390 break;
1391 case 16:
1392 writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
1393 break;
1394 case 32:
1395 writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
1396 break;
1397 }
1398
1399 /* 2d compare mask */
1400 writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
1401
1402 /* 2d mask */
1403 writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
1404
1405 /* colour */
1406 writel(rect->color, fbi->regs2d + SM501_2D_FOREGROUND);
1407
1408 /* x y */
1409 writel((rect->dx << 16) | rect->dy, fbi->regs2d + SM501_2D_DESTINATION);
1410
1411 /* w/h */
1412 writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
1413
1414 /* do rectangle fill */
1415 writel(0x800100cc, fbi->regs2d + SM501_2D_CONTROL);
1416}
1417
1250 1418
1251static struct fb_ops sm501fb_ops_crt = { 1419static struct fb_ops sm501fb_ops_crt = {
1252 .owner = THIS_MODULE, 1420 .owner = THIS_MODULE,
@@ -1256,9 +1424,10 @@ static struct fb_ops sm501fb_ops_crt = {
1256 .fb_setcolreg = sm501fb_setcolreg, 1424 .fb_setcolreg = sm501fb_setcolreg,
1257 .fb_pan_display = sm501fb_pan_crt, 1425 .fb_pan_display = sm501fb_pan_crt,
1258 .fb_cursor = sm501fb_cursor, 1426 .fb_cursor = sm501fb_cursor,
1259 .fb_fillrect = cfb_fillrect, 1427 .fb_fillrect = sm501fb_fillrect,
1260 .fb_copyarea = cfb_copyarea, 1428 .fb_copyarea = sm501fb_copyarea,
1261 .fb_imageblit = cfb_imageblit, 1429 .fb_imageblit = cfb_imageblit,
1430 .fb_sync = sm501fb_sync,
1262}; 1431};
1263 1432
1264static struct fb_ops sm501fb_ops_pnl = { 1433static struct fb_ops sm501fb_ops_pnl = {
@@ -1269,9 +1438,10 @@ static struct fb_ops sm501fb_ops_pnl = {
1269 .fb_blank = sm501fb_blank_pnl, 1438 .fb_blank = sm501fb_blank_pnl,
1270 .fb_setcolreg = sm501fb_setcolreg, 1439 .fb_setcolreg = sm501fb_setcolreg,
1271 .fb_cursor = sm501fb_cursor, 1440 .fb_cursor = sm501fb_cursor,
1272 .fb_fillrect = cfb_fillrect, 1441 .fb_fillrect = sm501fb_fillrect,
1273 .fb_copyarea = cfb_copyarea, 1442 .fb_copyarea = sm501fb_copyarea,
1274 .fb_imageblit = cfb_imageblit, 1443 .fb_imageblit = cfb_imageblit,
1444 .fb_sync = sm501fb_sync,
1275}; 1445};
1276 1446
1277/* sm501_init_cursor 1447/* sm501_init_cursor
@@ -1329,7 +1499,8 @@ static int sm501fb_start(struct sm501fb_info *info,
1329 dev_warn(dev, "no irq for device\n"); 1499 dev_warn(dev, "no irq for device\n");
1330 } 1500 }
1331 1501
1332 /* allocate, reserve and remap resources for registers */ 1502 /* allocate, reserve and remap resources for display
1503 * controller registers */
1333 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1504 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1334 if (res == NULL) { 1505 if (res == NULL) {
1335 dev_err(dev, "no resource definition for registers\n"); 1506 dev_err(dev, "no resource definition for registers\n");
@@ -1338,7 +1509,7 @@ static int sm501fb_start(struct sm501fb_info *info,
1338 } 1509 }
1339 1510
1340 info->regs_res = request_mem_region(res->start, 1511 info->regs_res = request_mem_region(res->start,
1341 res->end - res->start, 1512 resource_size(res),
1342 pdev->name); 1513 pdev->name);
1343 1514
1344 if (info->regs_res == NULL) { 1515 if (info->regs_res == NULL) {
@@ -1347,37 +1518,63 @@ static int sm501fb_start(struct sm501fb_info *info,
1347 goto err_release; 1518 goto err_release;
1348 } 1519 }
1349 1520
1350 info->regs = ioremap(res->start, (res->end - res->start)+1); 1521 info->regs = ioremap(res->start, resource_size(res));
1351 if (info->regs == NULL) { 1522 if (info->regs == NULL) {
1352 dev_err(dev, "cannot remap registers\n"); 1523 dev_err(dev, "cannot remap registers\n");
1353 ret = -ENXIO; 1524 ret = -ENXIO;
1354 goto err_regs_res; 1525 goto err_regs_res;
1355 } 1526 }
1356 1527
1528 /* allocate, reserve and remap resources for 2d
1529 * controller registers */
1530 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1531 if (res == NULL) {
1532 dev_err(dev, "no resource definition for 2d registers\n");
1533 ret = -ENOENT;
1534 goto err_regs_map;
1535 }
1536
1537 info->regs2d_res = request_mem_region(res->start,
1538 resource_size(res),
1539 pdev->name);
1540
1541 if (info->regs2d_res == NULL) {
1542 dev_err(dev, "cannot claim registers\n");
1543 ret = -ENXIO;
1544 goto err_regs_map;
1545 }
1546
1547 info->regs2d = ioremap(res->start, resource_size(res));
1548 if (info->regs2d == NULL) {
1549 dev_err(dev, "cannot remap registers\n");
1550 ret = -ENXIO;
1551 goto err_regs2d_res;
1552 }
1553
1357 /* allocate, reserve resources for framebuffer */ 1554 /* allocate, reserve resources for framebuffer */
1358 res = platform_get_resource(pdev, IORESOURCE_MEM, 2); 1555 res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
1359 if (res == NULL) { 1556 if (res == NULL) {
1360 dev_err(dev, "no memory resource defined\n"); 1557 dev_err(dev, "no memory resource defined\n");
1361 ret = -ENXIO; 1558 ret = -ENXIO;
1362 goto err_regs_map; 1559 goto err_regs2d_map;
1363 } 1560 }
1364 1561
1365 info->fbmem_res = request_mem_region(res->start, 1562 info->fbmem_res = request_mem_region(res->start,
1366 (res->end - res->start)+1, 1563 resource_size(res),
1367 pdev->name); 1564 pdev->name);
1368 if (info->fbmem_res == NULL) { 1565 if (info->fbmem_res == NULL) {
1369 dev_err(dev, "cannot claim framebuffer\n"); 1566 dev_err(dev, "cannot claim framebuffer\n");
1370 ret = -ENXIO; 1567 ret = -ENXIO;
1371 goto err_regs_map; 1568 goto err_regs2d_map;
1372 } 1569 }
1373 1570
1374 info->fbmem = ioremap(res->start, (res->end - res->start)+1); 1571 info->fbmem = ioremap(res->start, resource_size(res));
1375 if (info->fbmem == NULL) { 1572 if (info->fbmem == NULL) {
1376 dev_err(dev, "cannot remap framebuffer\n"); 1573 dev_err(dev, "cannot remap framebuffer\n");
1377 goto err_mem_res; 1574 goto err_mem_res;
1378 } 1575 }
1379 1576
1380 info->fbmem_len = (res->end - res->start)+1; 1577 info->fbmem_len = resource_size(res);
1381 1578
1382 /* clear framebuffer memory - avoids garbage data on unused fb */ 1579 /* clear framebuffer memory - avoids garbage data on unused fb */
1383 memset(info->fbmem, 0, info->fbmem_len); 1580 memset(info->fbmem, 0, info->fbmem_len);
@@ -1389,8 +1586,10 @@ static int sm501fb_start(struct sm501fb_info *info,
1389 /* enable display controller */ 1586 /* enable display controller */
1390 sm501_unit_power(dev->parent, SM501_GATE_DISPLAY, 1); 1587 sm501_unit_power(dev->parent, SM501_GATE_DISPLAY, 1);
1391 1588
1392 /* setup cursors */ 1589 /* enable 2d controller */
1590 sm501_unit_power(dev->parent, SM501_GATE_2D_ENGINE, 1);
1393 1591
1592 /* setup cursors */
1394 sm501_init_cursor(info->fb[HEAD_CRT], SM501_DC_CRT_HWC_ADDR); 1593 sm501_init_cursor(info->fb[HEAD_CRT], SM501_DC_CRT_HWC_ADDR);
1395 sm501_init_cursor(info->fb[HEAD_PANEL], SM501_DC_PANEL_HWC_ADDR); 1594 sm501_init_cursor(info->fb[HEAD_PANEL], SM501_DC_PANEL_HWC_ADDR);
1396 1595
@@ -1400,6 +1599,13 @@ static int sm501fb_start(struct sm501fb_info *info,
1400 release_resource(info->fbmem_res); 1599 release_resource(info->fbmem_res);
1401 kfree(info->fbmem_res); 1600 kfree(info->fbmem_res);
1402 1601
1602 err_regs2d_map:
1603 iounmap(info->regs2d);
1604
1605 err_regs2d_res:
1606 release_resource(info->regs2d_res);
1607 kfree(info->regs2d_res);
1608
1403 err_regs_map: 1609 err_regs_map:
1404 iounmap(info->regs); 1610 iounmap(info->regs);
1405 1611
@@ -1420,6 +1626,10 @@ static void sm501fb_stop(struct sm501fb_info *info)
1420 release_resource(info->fbmem_res); 1626 release_resource(info->fbmem_res);
1421 kfree(info->fbmem_res); 1627 kfree(info->fbmem_res);
1422 1628
1629 iounmap(info->regs2d);
1630 release_resource(info->regs2d_res);
1631 kfree(info->regs2d_res);
1632
1423 iounmap(info->regs); 1633 iounmap(info->regs);
1424 release_resource(info->regs_res); 1634 release_resource(info->regs_res);
1425 kfree(info->regs_res); 1635 kfree(info->regs_res);
@@ -1486,7 +1696,8 @@ static int sm501fb_init_fb(struct fb_info *fb,
1486 par->ops.fb_cursor = NULL; 1696 par->ops.fb_cursor = NULL;
1487 1697
1488 fb->fbops = &par->ops; 1698 fb->fbops = &par->ops;
1489 fb->flags = FBINFO_FLAG_DEFAULT | 1699 fb->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST |
1700 FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
1490 FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN; 1701 FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
1491 1702
1492 /* fixed data */ 1703 /* fixed data */
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c
index 609d0a521ca2..dee64c3b1e67 100644
--- a/drivers/video/sstfb.c
+++ b/drivers/video/sstfb.c
@@ -86,7 +86,6 @@
86#include <linux/pci.h> 86#include <linux/pci.h>
87#include <linux/delay.h> 87#include <linux/delay.h>
88#include <linux/init.h> 88#include <linux/init.h>
89#include <linux/slab.h>
90#include <asm/io.h> 89#include <asm/io.h>
91#include <linux/uaccess.h> 90#include <linux/uaccess.h>
92#include <video/sstfb.h> 91#include <video/sstfb.h>
@@ -1102,7 +1101,7 @@ static void sst_set_vidmod_ics(struct fb_info *info, const int bpp)
1102 * detect dac type 1101 * detect dac type
1103 * prerequisite : write to FbiInitx enabled, video and fbi and pci fifo reset, 1102 * prerequisite : write to FbiInitx enabled, video and fbi and pci fifo reset,
1104 * dram refresh disabled, FbiInit remaped. 1103 * dram refresh disabled, FbiInit remaped.
1105 * TODO: mmh.. maybe i shoud put the "prerequisite" in the func ... 1104 * TODO: mmh.. maybe i should put the "prerequisite" in the func ...
1106 */ 1105 */
1107 1106
1108 1107
diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c
index 6120f0c526fe..876648e15e9d 100644
--- a/drivers/video/stifb.c
+++ b/drivers/video/stifb.c
@@ -756,9 +756,9 @@ hyperResetPlanes(struct stifb_info *fb, int enable)
756 if (fb->info.var.bits_per_pixel == 32) 756 if (fb->info.var.bits_per_pixel == 32)
757 controlPlaneReg = 0x04000F00; 757 controlPlaneReg = 0x04000F00;
758 else 758 else
759 controlPlaneReg = 0x00000F00; /* 0x00000800 should be enought, but lets clear all 4 bits */ 759 controlPlaneReg = 0x00000F00; /* 0x00000800 should be enough, but lets clear all 4 bits */
760 else 760 else
761 controlPlaneReg = 0x00000F00; /* 0x00000100 should be enought, but lets clear all 4 bits */ 761 controlPlaneReg = 0x00000F00; /* 0x00000100 should be enough, but lets clear all 4 bits */
762 762
763 switch (enable) { 763 switch (enable) {
764 case ENABLE: 764 case ENABLE:
diff --git a/drivers/video/sunxvr1000.c b/drivers/video/sunxvr1000.c
new file mode 100644
index 000000000000..23e69e834a18
--- /dev/null
+++ b/drivers/video/sunxvr1000.c
@@ -0,0 +1,227 @@
1/* sunxvr1000.c: Sun XVR-1000 driver for sparc64 systems
2 *
3 * Copyright (C) 2010 David S. Miller (davem@davemloft.net)
4 */
5
6#include <linux/module.h>
7#include <linux/kernel.h>
8#include <linux/fb.h>
9#include <linux/init.h>
10#include <linux/of_device.h>
11
12struct gfb_info {
13 struct fb_info *info;
14
15 char __iomem *fb_base;
16 unsigned long fb_base_phys;
17
18 struct device_node *of_node;
19
20 unsigned int width;
21 unsigned int height;
22 unsigned int depth;
23 unsigned int fb_size;
24
25 u32 pseudo_palette[16];
26};
27
28static int __devinit gfb_get_props(struct gfb_info *gp)
29{
30 gp->width = of_getintprop_default(gp->of_node, "width", 0);
31 gp->height = of_getintprop_default(gp->of_node, "height", 0);
32 gp->depth = of_getintprop_default(gp->of_node, "depth", 32);
33
34 if (!gp->width || !gp->height) {
35 printk(KERN_ERR "gfb: Critical properties missing for %s\n",
36 gp->of_node->full_name);
37 return -EINVAL;
38 }
39
40 return 0;
41}
42
43static int gfb_setcolreg(unsigned regno,
44 unsigned red, unsigned green, unsigned blue,
45 unsigned transp, struct fb_info *info)
46{
47 u32 value;
48
49 if (regno < 16) {
50 red >>= 8;
51 green >>= 8;
52 blue >>= 8;
53
54 value = (blue << 16) | (green << 8) | red;
55 ((u32 *)info->pseudo_palette)[regno] = value;
56 }
57
58 return 0;
59}
60
61static struct fb_ops gfb_ops = {
62 .owner = THIS_MODULE,
63 .fb_setcolreg = gfb_setcolreg,
64 .fb_fillrect = cfb_fillrect,
65 .fb_copyarea = cfb_copyarea,
66 .fb_imageblit = cfb_imageblit,
67};
68
69static int __devinit gfb_set_fbinfo(struct gfb_info *gp)
70{
71 struct fb_info *info = gp->info;
72 struct fb_var_screeninfo *var = &info->var;
73
74 info->flags = FBINFO_DEFAULT;
75 info->fbops = &gfb_ops;
76 info->screen_base = gp->fb_base;
77 info->screen_size = gp->fb_size;
78
79 info->pseudo_palette = gp->pseudo_palette;
80
81 /* Fill fix common fields */
82 strlcpy(info->fix.id, "gfb", sizeof(info->fix.id));
83 info->fix.smem_start = gp->fb_base_phys;
84 info->fix.smem_len = gp->fb_size;
85 info->fix.type = FB_TYPE_PACKED_PIXELS;
86 if (gp->depth == 32 || gp->depth == 24)
87 info->fix.visual = FB_VISUAL_TRUECOLOR;
88 else
89 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
90
91 var->xres = gp->width;
92 var->yres = gp->height;
93 var->xres_virtual = var->xres;
94 var->yres_virtual = var->yres;
95 var->bits_per_pixel = gp->depth;
96
97 var->red.offset = 0;
98 var->red.length = 8;
99 var->green.offset = 8;
100 var->green.length = 8;
101 var->blue.offset = 16;
102 var->blue.length = 8;
103 var->transp.offset = 0;
104 var->transp.length = 0;
105
106 if (fb_alloc_cmap(&info->cmap, 256, 0)) {
107 printk(KERN_ERR "gfb: Cannot allocate color map.\n");
108 return -ENOMEM;
109 }
110
111 return 0;
112}
113
114static int __devinit gfb_probe(struct of_device *op,
115 const struct of_device_id *match)
116{
117 struct device_node *dp = op->node;
118 struct fb_info *info;
119 struct gfb_info *gp;
120 int err;
121
122 info = framebuffer_alloc(sizeof(struct gfb_info), &op->dev);
123 if (!info) {
124 printk(KERN_ERR "gfb: Cannot allocate fb_info\n");
125 err = -ENOMEM;
126 goto err_out;
127 }
128
129 gp = info->par;
130 gp->info = info;
131 gp->of_node = dp;
132
133 gp->fb_base_phys = op->resource[6].start;
134
135 err = gfb_get_props(gp);
136 if (err)
137 goto err_release_fb;
138
139 /* Framebuffer length is the same regardless of resolution. */
140 info->fix.line_length = 16384;
141 gp->fb_size = info->fix.line_length * gp->height;
142
143 gp->fb_base = of_ioremap(&op->resource[6], 0,
144 gp->fb_size, "gfb fb");
145 if (!gp->fb_base)
146 goto err_release_fb;
147
148 err = gfb_set_fbinfo(gp);
149 if (err)
150 goto err_unmap_fb;
151
152 printk("gfb: Found device at %s\n", dp->full_name);
153
154 err = register_framebuffer(info);
155 if (err < 0) {
156 printk(KERN_ERR "gfb: Could not register framebuffer %s\n",
157 dp->full_name);
158 goto err_unmap_fb;
159 }
160
161 dev_set_drvdata(&op->dev, info);
162
163 return 0;
164
165err_unmap_fb:
166 of_iounmap(&op->resource[6], gp->fb_base, gp->fb_size);
167
168err_release_fb:
169 framebuffer_release(info);
170
171err_out:
172 return err;
173}
174
175static int __devexit gfb_remove(struct of_device *op)
176{
177 struct fb_info *info = dev_get_drvdata(&op->dev);
178 struct gfb_info *gp = info->par;
179
180 unregister_framebuffer(info);
181
182 iounmap(gp->fb_base);
183
184 of_iounmap(&op->resource[6], gp->fb_base, gp->fb_size);
185
186 framebuffer_release(info);
187
188 dev_set_drvdata(&op->dev, NULL);
189
190 return 0;
191}
192
193static const struct of_device_id gfb_match[] = {
194 {
195 .name = "SUNW,gfb",
196 },
197 {},
198};
199MODULE_DEVICE_TABLE(of, ffb_match);
200
201static struct of_platform_driver gfb_driver = {
202 .name = "gfb",
203 .match_table = gfb_match,
204 .probe = gfb_probe,
205 .remove = __devexit_p(gfb_remove),
206};
207
208static int __init gfb_init(void)
209{
210 if (fb_get_options("gfb", NULL))
211 return -ENODEV;
212
213 return of_register_driver(&gfb_driver, &of_bus_type);
214}
215
216static void __exit gfb_exit(void)
217{
218 of_unregister_driver(&gfb_driver);
219}
220
221module_init(gfb_init);
222module_exit(gfb_exit);
223
224MODULE_DESCRIPTION("framebuffer driver for Sun XVR-1000 graphics");
225MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
226MODULE_VERSION("1.0");
227MODULE_LICENSE("GPL");
diff --git a/drivers/video/sunxvr2500.c b/drivers/video/sunxvr2500.c
index b1dde09e7015..5848436c19da 100644
--- a/drivers/video/sunxvr2500.c
+++ b/drivers/video/sunxvr2500.c
@@ -5,7 +5,6 @@
5 5
6#include <linux/module.h> 6#include <linux/module.h>
7#include <linux/kernel.h> 7#include <linux/kernel.h>
8#include <linux/slab.h>
9#include <linux/fb.h> 8#include <linux/fb.h>
10#include <linux/pci.h> 9#include <linux/pci.h>
11#include <linux/init.h> 10#include <linux/init.h>
diff --git a/drivers/video/sunxvr500.c b/drivers/video/sunxvr500.c
index 18b950706cad..b9c2b948d34d 100644
--- a/drivers/video/sunxvr500.c
+++ b/drivers/video/sunxvr500.c
@@ -5,7 +5,6 @@
5 5
6#include <linux/module.h> 6#include <linux/module.h>
7#include <linux/kernel.h> 7#include <linux/kernel.h>
8#include <linux/slab.h>
9#include <linux/fb.h> 8#include <linux/fb.h>
10#include <linux/pci.h> 9#include <linux/pci.h>
11#include <linux/init.h> 10#include <linux/init.h>
@@ -242,11 +241,27 @@ static int __devinit e3d_set_fbinfo(struct e3d_info *ep)
242static int __devinit e3d_pci_register(struct pci_dev *pdev, 241static int __devinit e3d_pci_register(struct pci_dev *pdev,
243 const struct pci_device_id *ent) 242 const struct pci_device_id *ent)
244{ 243{
244 struct device_node *of_node;
245 const char *device_type;
245 struct fb_info *info; 246 struct fb_info *info;
246 struct e3d_info *ep; 247 struct e3d_info *ep;
247 unsigned int line_length; 248 unsigned int line_length;
248 int err; 249 int err;
249 250
251 of_node = pci_device_to_OF_node(pdev);
252 if (!of_node) {
253 printk(KERN_ERR "e3d: Cannot find OF node of %s\n",
254 pci_name(pdev));
255 return -ENODEV;
256 }
257
258 device_type = of_get_property(of_node, "device_type", NULL);
259 if (!device_type) {
260 printk(KERN_INFO "e3d: Ignoring secondary output device "
261 "at %s\n", pci_name(pdev));
262 return -ENODEV;
263 }
264
250 err = pci_enable_device(pdev); 265 err = pci_enable_device(pdev);
251 if (err < 0) { 266 if (err < 0) {
252 printk(KERN_ERR "e3d: Cannot enable PCI device %s\n", 267 printk(KERN_ERR "e3d: Cannot enable PCI device %s\n",
@@ -265,13 +280,7 @@ static int __devinit e3d_pci_register(struct pci_dev *pdev,
265 ep->info = info; 280 ep->info = info;
266 ep->pdev = pdev; 281 ep->pdev = pdev;
267 spin_lock_init(&ep->lock); 282 spin_lock_init(&ep->lock);
268 ep->of_node = pci_device_to_OF_node(pdev); 283 ep->of_node = of_node;
269 if (!ep->of_node) {
270 printk(KERN_ERR "e3d: Cannot find OF node of %s\n",
271 pci_name(pdev));
272 err = -ENODEV;
273 goto err_release_fb;
274 }
275 284
276 /* Read the PCI base register of the frame buffer, which we 285 /* Read the PCI base register of the frame buffer, which we
277 * need in order to interpret the RAMDAC_VID_*FB* values in 286 * need in order to interpret the RAMDAC_VID_*FB* values in
@@ -400,6 +409,7 @@ static void __devexit e3d_pci_unregister(struct pci_dev *pdev)
400 409
401static struct pci_device_id e3d_pci_table[] = { 410static struct pci_device_id e3d_pci_table[] = {
402 { PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x7a0), }, 411 { PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x7a0), },
412 { PCI_DEVICE(0x1091, 0x7a0), },
403 { PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x7a2), }, 413 { PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x7a2), },
404 { .vendor = PCI_VENDOR_ID_3DLABS, 414 { .vendor = PCI_VENDOR_ID_3DLABS,
405 .device = PCI_ANY_ID, 415 .device = PCI_ANY_ID,
diff --git a/drivers/video/svgalib.c b/drivers/video/svgalib.c
index 9c7106701572..fdb45674e2f6 100644
--- a/drivers/video/svgalib.c
+++ b/drivers/video/svgalib.c
@@ -15,7 +15,6 @@
15#include <linux/string.h> 15#include <linux/string.h>
16#include <linux/fb.h> 16#include <linux/fb.h>
17#include <linux/svga.h> 17#include <linux/svga.h>
18#include <linux/slab.h>
19#include <asm/types.h> 18#include <asm/types.h>
20#include <asm/io.h> 19#include <asm/io.h>
21 20
diff --git a/drivers/video/syscopyarea.c b/drivers/video/syscopyarea.c
index a352d5f46bbf..844a32fd38ed 100644
--- a/drivers/video/syscopyarea.c
+++ b/drivers/video/syscopyarea.c
@@ -16,7 +16,6 @@
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/string.h> 17#include <linux/string.h>
18#include <linux/fb.h> 18#include <linux/fb.h>
19#include <linux/slab.h>
20#include <asm/types.h> 19#include <asm/types.h>
21#include <asm/io.h> 20#include <asm/io.h>
22#include "fb_draw.h" 21#include "fb_draw.h"
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c
index 45b883598bf0..c0c2b18fcdcf 100644
--- a/drivers/video/tcx.c
+++ b/drivers/video/tcx.c
@@ -12,7 +12,6 @@
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/errno.h> 13#include <linux/errno.h>
14#include <linux/string.h> 14#include <linux/string.h>
15#include <linux/slab.h>
16#include <linux/delay.h> 15#include <linux/delay.h>
17#include <linux/init.h> 16#include <linux/init.h>
18#include <linux/fb.h> 17#include <linux/fb.h>
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index ff43c8885028..980548390048 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -52,7 +52,7 @@
52 * 52 *
53 * 0.1.3 (released 1999-11-02) added Attila's panning support, code 53 * 0.1.3 (released 1999-11-02) added Attila's panning support, code
54 * reorg, hwcursor address page size alignment 54 * reorg, hwcursor address page size alignment
55 * (for mmaping both frame buffer and regs), 55 * (for mmapping both frame buffer and regs),
56 * and my changes to get rid of hardcoded 56 * and my changes to get rid of hardcoded
57 * VGA i/o register locations (uses PCI 57 * VGA i/o register locations (uses PCI
58 * configuration info now) 58 * configuration info now)
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c
index a86046ff60ad..1b3b1c718e80 100644
--- a/drivers/video/tgafb.c
+++ b/drivers/video/tgafb.c
@@ -25,7 +25,6 @@
25#include <linux/module.h> 25#include <linux/module.h>
26#include <linux/pci.h> 26#include <linux/pci.h>
27#include <linux/selection.h> 27#include <linux/selection.h>
28#include <linux/slab.h>
29#include <linux/string.h> 28#include <linux/string.h>
30#include <linux/tc.h> 29#include <linux/tc.h>
31 30
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index 03a9c35e9f55..c6c77562839d 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -19,6 +19,7 @@
19#include <linux/fb.h> 19#include <linux/fb.h>
20#include <linux/init.h> 20#include <linux/init.h>
21#include <linux/pci.h> 21#include <linux/pci.h>
22#include <linux/slab.h>
22 23
23#include <linux/delay.h> 24#include <linux/delay.h>
24#include <video/vga.h> 25#include <video/vga.h>
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index 54fbb2995a5f..7b8839ebf3c4 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -18,6 +18,7 @@
18#include <linux/fb.h> 18#include <linux/fb.h>
19#include <linux/io.h> 19#include <linux/io.h>
20#include <linux/mutex.h> 20#include <linux/mutex.h>
21#include <linux/slab.h>
21#include <video/edid.h> 22#include <video/edid.h>
22#include <video/uvesafb.h> 23#include <video/uvesafb.h>
23#ifdef CONFIG_X86 24#ifdef CONFIG_X86
diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c
index 4bb9a0b18950..6b52bf65f0b5 100644
--- a/drivers/video/valkyriefb.c
+++ b/drivers/video/valkyriefb.c
@@ -69,7 +69,7 @@
69#ifdef CONFIG_MAC 69#ifdef CONFIG_MAC
70/* We don't yet have functions to read the PRAM... perhaps we can 70/* We don't yet have functions to read the PRAM... perhaps we can
71 adapt them from the PPC code? */ 71 adapt them from the PPC code? */
72static int default_vmode = VMODE_640_480_67; 72static int default_vmode = VMODE_CHOOSE;
73static int default_cmode = CMODE_8; 73static int default_cmode = CMODE_8;
74#else 74#else
75static int default_vmode = VMODE_NVRAM; 75static int default_vmode = VMODE_NVRAM;
@@ -326,11 +326,11 @@ int __init valkyriefb_init(void)
326 326
327#ifdef CONFIG_MAC 327#ifdef CONFIG_MAC
328 if (!MACH_IS_MAC) 328 if (!MACH_IS_MAC)
329 return 0; 329 return -ENODEV;
330 if (!(mac_bi_data.id == MAC_MODEL_Q630 330 if (!(mac_bi_data.id == MAC_MODEL_Q630
331 /* I'm not sure about this one */ 331 /* I'm not sure about this one */
332 || mac_bi_data.id == MAC_MODEL_P588)) 332 || mac_bi_data.id == MAC_MODEL_P588))
333 return 0; 333 return -ENODEV;
334 334
335 /* Hardcoded addresses... welcome to 68k Macintosh country :-) */ 335 /* Hardcoded addresses... welcome to 68k Macintosh country :-) */
336 frame_buffer_phys = 0xf9000000; 336 frame_buffer_phys = 0xf9000000;
diff --git a/drivers/video/valkyriefb.h b/drivers/video/valkyriefb.h
index 97aaf7bb6417..d787441e5a42 100644
--- a/drivers/video/valkyriefb.h
+++ b/drivers/video/valkyriefb.h
@@ -134,15 +134,7 @@ static struct valkyrie_regvals valkyrie_reg_init_14 = {
134 { 1024, 0 }, 134 { 1024, 0 },
135 1024, 768 135 1024, 768
136}; 136};
137 137#endif /* !defined CONFIG_MAC */
138/* Register values for 800x600, 72Hz mode (11) */
139static struct valkyrie_regvals valkyrie_reg_init_11 = {
140 13,
141 { 17, 27, 3 }, /* pixel clock = 49.63MHz for V=71.66Hz */
142 { 800, 0 },
143 800, 600
144};
145#endif /* CONFIG_MAC */
146 138
147/* Register values for 832x624, 75Hz mode (13) */ 139/* Register values for 832x624, 75Hz mode (13) */
148static struct valkyrie_regvals valkyrie_reg_init_13 = { 140static struct valkyrie_regvals valkyrie_reg_init_13 = {
@@ -152,6 +144,14 @@ static struct valkyrie_regvals valkyrie_reg_init_13 = {
152 832, 624 144 832, 624
153}; 145};
154 146
147/* Register values for 800x600, 72Hz mode (11) */
148static struct valkyrie_regvals valkyrie_reg_init_11 = {
149 13,
150 { 17, 27, 3 }, /* pixel clock = 49.63MHz for V=71.66Hz */
151 { 800, 0 },
152 800, 600
153};
154
155/* Register values for 800x600, 60Hz mode (10) */ 155/* Register values for 800x600, 60Hz mode (10) */
156static struct valkyrie_regvals valkyrie_reg_init_10 = { 156static struct valkyrie_regvals valkyrie_reg_init_10 = {
157 12, 157 12,
@@ -188,24 +188,13 @@ static struct valkyrie_regvals *valkyrie_reg_init[VMODE_MAX] = {
188 NULL, 188 NULL,
189 NULL, 189 NULL,
190 &valkyrie_reg_init_10, 190 &valkyrie_reg_init_10,
191#ifdef CONFIG_MAC
192 NULL,
193 NULL,
194 &valkyrie_reg_init_13,
195 NULL,
196 NULL,
197 NULL,
198 NULL,
199#else
200 &valkyrie_reg_init_11, 191 &valkyrie_reg_init_11,
201 NULL, 192 NULL,
202 &valkyrie_reg_init_13, 193 &valkyrie_reg_init_13,
194#ifndef CONFIG_MAC
203 &valkyrie_reg_init_14, 195 &valkyrie_reg_init_14,
204 &valkyrie_reg_init_15, 196 &valkyrie_reg_init_15,
205 NULL, 197 NULL,
206 &valkyrie_reg_init_17, 198 &valkyrie_reg_init_17,
207#endif 199#endif
208 NULL,
209 NULL,
210 NULL
211}; 200};
diff --git a/drivers/video/vermilion/vermilion.c b/drivers/video/vermilion/vermilion.c
index c18f1884b550..931a567f9aff 100644
--- a/drivers/video/vermilion/vermilion.c
+++ b/drivers/video/vermilion/vermilion.c
@@ -33,6 +33,7 @@
33#include <linux/errno.h> 33#include <linux/errno.h>
34#include <linux/string.h> 34#include <linux/string.h>
35#include <linux/delay.h> 35#include <linux/delay.h>
36#include <linux/slab.h>
36#include <linux/mm.h> 37#include <linux/mm.h>
37#include <linux/fb.h> 38#include <linux/fb.h>
38#include <linux/pci.h> 39#include <linux/pci.h>
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index bd37ee1f6a25..0cadf7aee27e 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -13,7 +13,6 @@
13#include <linux/errno.h> 13#include <linux/errno.h>
14#include <linux/string.h> 14#include <linux/string.h>
15#include <linux/mm.h> 15#include <linux/mm.h>
16#include <linux/slab.h>
17#include <linux/delay.h> 16#include <linux/delay.h>
18#include <linux/fb.h> 17#include <linux/fb.h>
19#include <linux/ioport.h> 18#include <linux/ioport.h>
@@ -477,7 +476,6 @@ err:
477} 476}
478 477
479static struct platform_driver vesafb_driver = { 478static struct platform_driver vesafb_driver = {
480 .probe = vesafb_probe,
481 .driver = { 479 .driver = {
482 .name = "vesafb", 480 .name = "vesafb",
483 }, 481 },
@@ -493,20 +491,21 @@ static int __init vesafb_init(void)
493 /* ignore error return of fb_get_options */ 491 /* ignore error return of fb_get_options */
494 fb_get_options("vesafb", &option); 492 fb_get_options("vesafb", &option);
495 vesafb_setup(option); 493 vesafb_setup(option);
496 ret = platform_driver_register(&vesafb_driver);
497 494
498 if (!ret) { 495 vesafb_device = platform_device_alloc("vesafb", 0);
499 vesafb_device = platform_device_alloc("vesafb", 0); 496 if (!vesafb_device)
497 return -ENOMEM;
500 498
501 if (vesafb_device) 499 ret = platform_device_add(vesafb_device);
502 ret = platform_device_add(vesafb_device); 500 if (!ret) {
503 else 501 ret = platform_driver_probe(&vesafb_driver, vesafb_probe);
504 ret = -ENOMEM; 502 if (ret)
503 platform_device_del(vesafb_device);
504 }
505 505
506 if (ret) { 506 if (ret) {
507 platform_device_put(vesafb_device); 507 platform_device_put(vesafb_device);
508 platform_driver_unregister(&vesafb_driver); 508 vesafb_device = NULL;
509 }
510 } 509 }
511 510
512 return ret; 511 return ret;
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index 050d432c7d95..9b5532b4de35 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -15,7 +15,6 @@
15#include <linux/errno.h> 15#include <linux/errno.h>
16#include <linux/string.h> 16#include <linux/string.h>
17#include <linux/mm.h> 17#include <linux/mm.h>
18#include <linux/slab.h>
19#include <linux/vmalloc.h> 18#include <linux/vmalloc.h>
20#include <linux/delay.h> 19#include <linux/delay.h>
21#include <linux/interrupt.h> 20#include <linux/interrupt.h>
@@ -479,7 +478,7 @@ static int __init vfb_setup(char *options)
479 * Initialisation 478 * Initialisation
480 */ 479 */
481 480
482static int __init vfb_probe(struct platform_device *dev) 481static int __devinit vfb_probe(struct platform_device *dev)
483{ 482{
484 struct fb_info *info; 483 struct fb_info *info;
485 int retval = -ENOMEM; 484 int retval = -ENOMEM;
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 5b2938903ac2..bf638a47a5b3 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -15,7 +15,6 @@
15#include <linux/errno.h> 15#include <linux/errno.h>
16#include <linux/string.h> 16#include <linux/string.h>
17#include <linux/mm.h> 17#include <linux/mm.h>
18#include <linux/slab.h>
19#include <linux/delay.h> 18#include <linux/delay.h>
20#include <linux/fb.h> 19#include <linux/fb.h>
21#include <linux/ioport.h> 20#include <linux/ioport.h>
@@ -1293,7 +1292,7 @@ static int vga16fb_setup(char *options)
1293} 1292}
1294#endif 1293#endif
1295 1294
1296static int __init vga16fb_probe(struct platform_device *dev) 1295static int __devinit vga16fb_probe(struct platform_device *dev)
1297{ 1296{
1298 struct fb_info *info; 1297 struct fb_info *info;
1299 struct vga16fb_par *par; 1298 struct vga16fb_par *par;
diff --git a/drivers/video/via/Makefile b/drivers/video/via/Makefile
index e533b4b6aba4..eeed238ad6a2 100644
--- a/drivers/video/via/Makefile
+++ b/drivers/video/via/Makefile
@@ -4,4 +4,4 @@
4 4
5obj-$(CONFIG_FB_VIA) += viafb.o 5obj-$(CONFIG_FB_VIA) += viafb.o
6 6
7viafb-y :=viafbdev.o hw.o iface.o via_i2c.o dvi.o lcd.o ioctl.o accel.o via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o 7viafb-y :=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o
diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c
index 9d4f3a49ba4a..d5077dfa9e00 100644
--- a/drivers/video/via/accel.c
+++ b/drivers/video/via/accel.c
@@ -137,7 +137,7 @@ static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height,
137 tmp, dst_pitch); 137 tmp, dst_pitch);
138 return -EINVAL; 138 return -EINVAL;
139 } 139 }
140 tmp = (tmp >> 3) | (dst_pitch << (16 - 3)); 140 tmp = VIA_PITCH_ENABLE | (tmp >> 3) | (dst_pitch << (16 - 3));
141 writel(tmp, engine + 0x38); 141 writel(tmp, engine + 0x38);
142 142
143 if (op == VIA_BITBLT_FILL) 143 if (op == VIA_BITBLT_FILL)
@@ -352,6 +352,9 @@ int viafb_init_engine(struct fb_info *info)
352 viapar->shared->vq_vram_addr = viapar->fbmem_free; 352 viapar->shared->vq_vram_addr = viapar->fbmem_free;
353 viapar->fbmem_used += VQ_SIZE; 353 viapar->fbmem_used += VQ_SIZE;
354 354
355 /* Init 2D engine reg to reset 2D engine */
356 writel(0x0, engine + VIA_REG_KEYCONTROL);
357
355 /* Init AGP and VQ regs */ 358 /* Init AGP and VQ regs */
356 switch (chip_name) { 359 switch (chip_name) {
357 case UNICHROME_K8M890: 360 case UNICHROME_K8M890:
diff --git a/drivers/video/via/chip.h b/drivers/video/via/chip.h
index 474f428aea92..8c06bd3c0b4d 100644
--- a/drivers/video/via/chip.h
+++ b/drivers/video/via/chip.h
@@ -107,7 +107,6 @@
107struct tmds_chip_information { 107struct tmds_chip_information {
108 int tmds_chip_name; 108 int tmds_chip_name;
109 int tmds_chip_slave_addr; 109 int tmds_chip_slave_addr;
110 int dvi_panel_id;
111 int data_mode; 110 int data_mode;
112 int output_interface; 111 int output_interface;
113 int i2c_port; 112 int i2c_port;
@@ -142,14 +141,9 @@ struct tmds_setting_information {
142 int iga_path; 141 int iga_path;
143 int h_active; 142 int h_active;
144 int v_active; 143 int v_active;
145 int bpp;
146 int refresh_rate;
147 int get_dvi_size_method;
148 int max_pixel_clock; 144 int max_pixel_clock;
149 int dvi_panel_size; 145 int max_hres;
150 int dvi_panel_hres; 146 int max_vres;
151 int dvi_panel_vres;
152 int native_size;
153}; 147};
154 148
155struct lvds_setting_information { 149struct lvds_setting_information {
@@ -160,7 +154,6 @@ struct lvds_setting_information {
160 int refresh_rate; 154 int refresh_rate;
161 int get_lcd_size_method; 155 int get_lcd_size_method;
162 int lcd_panel_id; 156 int lcd_panel_id;
163 int lcd_panel_size;
164 int lcd_panel_hres; 157 int lcd_panel_hres;
165 int lcd_panel_vres; 158 int lcd_panel_vres;
166 int display_method; 159 int display_method;
diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c
index c5c32b6b6e6c..abe59b8c7a05 100644
--- a/drivers/video/via/dvi.c
+++ b/drivers/video/via/dvi.c
@@ -23,11 +23,10 @@
23static void tmds_register_write(int index, u8 data); 23static void tmds_register_write(int index, u8 data);
24static int tmds_register_read(int index); 24static int tmds_register_read(int index);
25static int tmds_register_read_bytes(int index, u8 *buff, int buff_len); 25static int tmds_register_read_bytes(int index, u8 *buff, int buff_len);
26static int check_reduce_blanking_mode(int mode_index, 26static void dvi_get_panel_size_from_DDCv1(struct tmds_chip_information
27 int refresh_rate); 27 *tmds_chip, struct tmds_setting_information *tmds_setting);
28static int dvi_get_panel_size_from_DDCv1(void); 28static void dvi_get_panel_size_from_DDCv2(struct tmds_chip_information
29static int dvi_get_panel_size_from_DDCv2(void); 29 *tmds_chip, struct tmds_setting_information *tmds_setting);
30static unsigned char dvi_get_panel_info(void);
31static int viafb_dvi_query_EDID(void); 30static int viafb_dvi_query_EDID(void);
32 31
33static int check_tmds_chip(int device_id_subaddr, int device_id) 32static int check_tmds_chip(int device_id_subaddr, int device_id)
@@ -38,23 +37,24 @@ static int check_tmds_chip(int device_id_subaddr, int device_id)
38 return FAIL; 37 return FAIL;
39} 38}
40 39
41void viafb_init_dvi_size(void) 40void viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
41 struct tmds_setting_information *tmds_setting)
42{ 42{
43 DEBUG_MSG(KERN_INFO "viafb_init_dvi_size()\n"); 43 DEBUG_MSG(KERN_INFO "viafb_init_dvi_size()\n");
44 DEBUG_MSG(KERN_INFO
45 "viaparinfo->tmds_setting_info->get_dvi_size_method %d\n",
46 viaparinfo->tmds_setting_info->get_dvi_size_method);
47 44
48 switch (viaparinfo->tmds_setting_info->get_dvi_size_method) { 45 viafb_dvi_sense();
49 case GET_DVI_SIZE_BY_SYSTEM_BIOS: 46 switch (viafb_dvi_query_EDID()) {
47 case 1:
48 dvi_get_panel_size_from_DDCv1(tmds_chip, tmds_setting);
50 break; 49 break;
51 case GET_DVI_SZIE_BY_HW_STRAPPING: 50 case 2:
51 dvi_get_panel_size_from_DDCv2(tmds_chip, tmds_setting);
52 break; 52 break;
53 case GET_DVI_SIZE_BY_VGA_BIOS:
54 default: 53 default:
55 dvi_get_panel_info(); 54 printk(KERN_WARNING "viafb_init_dvi_size: DVI panel size undetected!\n");
56 break; 55 break;
57 } 56 }
57
58 return; 58 return;
59} 59}
60 60
@@ -189,42 +189,14 @@ static int tmds_register_read_bytes(int index, u8 *buff, int buff_len)
189 return 0; 189 return 0;
190} 190}
191 191
192static int check_reduce_blanking_mode(int mode_index,
193 int refresh_rate)
194{
195 if (refresh_rate != 60)
196 return false;
197
198 switch (mode_index) {
199 /* Following modes have reduce blanking mode. */
200 case VIA_RES_1360X768:
201 case VIA_RES_1400X1050:
202 case VIA_RES_1440X900:
203 case VIA_RES_1600X900:
204 case VIA_RES_1680X1050:
205 case VIA_RES_1920X1080:
206 case VIA_RES_1920X1200:
207 break;
208
209 default:
210 DEBUG_MSG(KERN_INFO
211 "This dvi mode %d have no reduce blanking mode!\n",
212 mode_index);
213 return false;
214 }
215
216 return true;
217}
218
219/* DVI Set Mode */ 192/* DVI Set Mode */
220void viafb_dvi_set_mode(int video_index, int mode_bpp, int set_iga) 193void viafb_dvi_set_mode(struct VideoModeTable *mode, int mode_bpp,
194 int set_iga)
221{ 195{
222 struct VideoModeTable *videoMode = NULL; 196 struct VideoModeTable *rb_mode;
223 struct crt_mode_table *pDviTiming; 197 struct crt_mode_table *pDviTiming;
224 unsigned long desirePixelClock, maxPixelClock; 198 unsigned long desirePixelClock, maxPixelClock;
225 int status = 0; 199 pDviTiming = mode->crtc;
226 videoMode = viafb_get_modetbl_pointer(video_index);
227 pDviTiming = videoMode->crtc;
228 desirePixelClock = pDviTiming->clk / 1000000; 200 desirePixelClock = pDviTiming->clk / 1000000;
229 maxPixelClock = (unsigned long)viaparinfo-> 201 maxPixelClock = (unsigned long)viaparinfo->
230 tmds_setting_info->max_pixel_clock; 202 tmds_setting_info->max_pixel_clock;
@@ -232,20 +204,14 @@ void viafb_dvi_set_mode(int video_index, int mode_bpp, int set_iga)
232 DEBUG_MSG(KERN_INFO "\nDVI_set_mode!!\n"); 204 DEBUG_MSG(KERN_INFO "\nDVI_set_mode!!\n");
233 205
234 if ((maxPixelClock != 0) && (desirePixelClock > maxPixelClock)) { 206 if ((maxPixelClock != 0) && (desirePixelClock > maxPixelClock)) {
235 /*Check if reduce-blanking mode is exist */ 207 rb_mode = viafb_get_rb_mode(mode->crtc[0].crtc.hor_addr,
236 status = 208 mode->crtc[0].crtc.ver_addr);
237 check_reduce_blanking_mode(video_index, 209 if (rb_mode) {
238 pDviTiming->refresh_rate); 210 mode = rb_mode;
239 if (status) { 211 pDviTiming = rb_mode->crtc;
240 video_index += 100; /*Use reduce-blanking mode */
241 videoMode = viafb_get_modetbl_pointer(video_index);
242 pDviTiming = videoMode->crtc;
243 DEBUG_MSG(KERN_INFO
244 "DVI use reduce blanking mode %d!!\n",
245 video_index);
246 } 212 }
247 } 213 }
248 viafb_fill_crtc_timing(pDviTiming, video_index, mode_bpp / 8, set_iga); 214 viafb_fill_crtc_timing(pDviTiming, mode, mode_bpp / 8, set_iga);
249 viafb_set_output_path(DEVICE_DVI, set_iga, 215 viafb_set_output_path(DEVICE_DVI, set_iga,
250 viaparinfo->chip_info->tmds_chip_info.output_interface); 216 viaparinfo->chip_info->tmds_chip_info.output_interface);
251} 217}
@@ -350,25 +316,18 @@ static int viafb_dvi_query_EDID(void)
350 return false; 316 return false;
351} 317}
352 318
353/* 319/* Get Panel Size Using EDID1 Table */
354 * 320static void dvi_get_panel_size_from_DDCv1(struct tmds_chip_information
355 * int dvi_get_panel_size_from_DDCv1(void) 321 *tmds_chip, struct tmds_setting_information *tmds_setting)
356 *
357 * - Get Panel Size Using EDID1 Table
358 *
359 * Return Type: int
360 *
361 */
362static int dvi_get_panel_size_from_DDCv1(void)
363{ 322{
364 int i, max_h = 0, max_v = 0, tmp, restore; 323 int i, max_h = 0, tmp, restore;
365 unsigned char rData; 324 unsigned char rData;
366 unsigned char EDID_DATA[18]; 325 unsigned char EDID_DATA[18];
367 326
368 DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv1 \n"); 327 DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv1 \n");
369 328
370 restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr; 329 restore = tmds_chip->tmds_chip_slave_addr;
371 viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA0; 330 tmds_chip->tmds_chip_slave_addr = 0xA0;
372 331
373 rData = tmds_register_read(0x23); 332 rData = tmds_register_read(0x23);
374 if (rData & 0x3C) 333 if (rData & 0x3C)
@@ -414,8 +373,8 @@ static int dvi_get_panel_size_from_DDCv1(void)
414 /* The first two byte must be zero. */ 373 /* The first two byte must be zero. */
415 if (EDID_DATA[3] == 0xFD) { 374 if (EDID_DATA[3] == 0xFD) {
416 /* To get max pixel clock. */ 375 /* To get max pixel clock. */
417 viaparinfo->tmds_setting_info-> 376 tmds_setting->max_pixel_clock =
418 max_pixel_clock = EDID_DATA[9] * 10; 377 EDID_DATA[9] * 10;
419 } 378 }
420 } 379 }
421 break; 380 break;
@@ -425,154 +384,88 @@ static int dvi_get_panel_size_from_DDCv1(void)
425 } 384 }
426 } 385 }
427 386
387 tmds_setting->max_hres = max_h;
428 switch (max_h) { 388 switch (max_h) {
429 case 640: 389 case 640:
430 viaparinfo->tmds_setting_info->dvi_panel_size = 390 tmds_setting->max_vres = 480;
431 VIA_RES_640X480;
432 break; 391 break;
433 case 800: 392 case 800:
434 viaparinfo->tmds_setting_info->dvi_panel_size = 393 tmds_setting->max_vres = 600;
435 VIA_RES_800X600;
436 break; 394 break;
437 case 1024: 395 case 1024:
438 viaparinfo->tmds_setting_info->dvi_panel_size = 396 tmds_setting->max_vres = 768;
439 VIA_RES_1024X768;
440 break; 397 break;
441 case 1280: 398 case 1280:
442 viaparinfo->tmds_setting_info->dvi_panel_size = 399 tmds_setting->max_vres = 1024;
443 VIA_RES_1280X1024;
444 break; 400 break;
445 case 1400: 401 case 1400:
446 viaparinfo->tmds_setting_info->dvi_panel_size = 402 tmds_setting->max_vres = 1050;
447 VIA_RES_1400X1050;
448 break; 403 break;
449 case 1440: 404 case 1440:
450 viaparinfo->tmds_setting_info->dvi_panel_size = 405 tmds_setting->max_vres = 1050;
451 VIA_RES_1440X1050;
452 break; 406 break;
453 case 1600: 407 case 1600:
454 viaparinfo->tmds_setting_info->dvi_panel_size = 408 tmds_setting->max_vres = 1200;
455 VIA_RES_1600X1200;
456 break; 409 break;
457 case 1920: 410 case 1920:
458 if (max_v == 1200) { 411 tmds_setting->max_vres = 1080;
459 viaparinfo->tmds_setting_info->dvi_panel_size =
460 VIA_RES_1920X1200;
461 } else {
462 viaparinfo->tmds_setting_info->dvi_panel_size =
463 VIA_RES_1920X1080;
464 }
465
466 break; 412 break;
467 default: 413 default:
468 viaparinfo->tmds_setting_info->dvi_panel_size = 414 DEBUG_MSG(KERN_INFO "Unknown panel size max resolution = %d ! "
469 VIA_RES_1024X768; 415 "set default panel size.\n", max_h);
470 DEBUG_MSG(KERN_INFO "Unknow panel size max resolution = %d !\
471 set default panel size.\n", max_h);
472 break; 416 break;
473 } 417 }
474 418
475 DEBUG_MSG(KERN_INFO "DVI max pixelclock = %d\n", 419 DEBUG_MSG(KERN_INFO "DVI max pixelclock = %d\n",
476 viaparinfo->tmds_setting_info->max_pixel_clock); 420 tmds_setting->max_pixel_clock);
477 viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore; 421 tmds_chip->tmds_chip_slave_addr = restore;
478 return viaparinfo->tmds_setting_info->dvi_panel_size;
479} 422}
480 423
481/* 424/* Get Panel Size Using EDID2 Table */
482 * 425static void dvi_get_panel_size_from_DDCv2(struct tmds_chip_information
483 * int dvi_get_panel_size_from_DDCv2(void) 426 *tmds_chip, struct tmds_setting_information *tmds_setting)
484 *
485 * - Get Panel Size Using EDID2 Table
486 *
487 * Return Type: int
488 *
489 */
490static int dvi_get_panel_size_from_DDCv2(void)
491{ 427{
492 int HSize = 0, restore; 428 int restore;
493 unsigned char R_Buffer[2]; 429 unsigned char R_Buffer[2];
494 430
495 DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv2 \n"); 431 DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv2 \n");
496 432
497 restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr; 433 restore = tmds_chip->tmds_chip_slave_addr;
498 viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA2; 434 tmds_chip->tmds_chip_slave_addr = 0xA2;
499 435
500 /* Horizontal: 0x76, 0x77 */ 436 /* Horizontal: 0x76, 0x77 */
501 tmds_register_read_bytes(0x76, R_Buffer, 2); 437 tmds_register_read_bytes(0x76, R_Buffer, 2);
502 HSize = R_Buffer[0]; 438 tmds_setting->max_hres = R_Buffer[0] + (R_Buffer[1] << 8);
503 HSize += R_Buffer[1] << 8;
504 439
505 switch (HSize) { 440 switch (tmds_setting->max_hres) {
506 case 640: 441 case 640:
507 viaparinfo->tmds_setting_info->dvi_panel_size = 442 tmds_setting->max_vres = 480;
508 VIA_RES_640X480;
509 break; 443 break;
510 case 800: 444 case 800:
511 viaparinfo->tmds_setting_info->dvi_panel_size = 445 tmds_setting->max_vres = 600;
512 VIA_RES_800X600;
513 break; 446 break;
514 case 1024: 447 case 1024:
515 viaparinfo->tmds_setting_info->dvi_panel_size = 448 tmds_setting->max_vres = 768;
516 VIA_RES_1024X768;
517 break; 449 break;
518 case 1280: 450 case 1280:
519 viaparinfo->tmds_setting_info->dvi_panel_size = 451 tmds_setting->max_vres = 1024;
520 VIA_RES_1280X1024;
521 break; 452 break;
522 case 1400: 453 case 1400:
523 viaparinfo->tmds_setting_info->dvi_panel_size = 454 tmds_setting->max_vres = 1050;
524 VIA_RES_1400X1050;
525 break; 455 break;
526 case 1440: 456 case 1440:
527 viaparinfo->tmds_setting_info->dvi_panel_size = 457 tmds_setting->max_vres = 1050;
528 VIA_RES_1440X1050;
529 break; 458 break;
530 case 1600: 459 case 1600:
531 viaparinfo->tmds_setting_info->dvi_panel_size = 460 tmds_setting->max_vres = 1200;
532 VIA_RES_1600X1200;
533 break;
534 default:
535 viaparinfo->tmds_setting_info->dvi_panel_size =
536 VIA_RES_1024X768;
537 DEBUG_MSG(KERN_INFO "Unknow panel size max resolution = %d!\
538 set default panel size.\n", HSize);
539 break;
540 }
541
542 viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore;
543 return viaparinfo->tmds_setting_info->dvi_panel_size;
544}
545
546/*
547 *
548 * unsigned char dvi_get_panel_info(void)
549 *
550 * - Get Panel Size
551 *
552 * Return Type: unsigned char
553 */
554static unsigned char dvi_get_panel_info(void)
555{
556 unsigned char dvipanelsize;
557 DEBUG_MSG(KERN_INFO "dvi_get_panel_info! \n");
558
559 viafb_dvi_sense();
560 switch (viafb_dvi_query_EDID()) {
561 case 1:
562 dvi_get_panel_size_from_DDCv1();
563 break;
564 case 2:
565 dvi_get_panel_size_from_DDCv2();
566 break; 461 break;
567 default: 462 default:
463 DEBUG_MSG(KERN_INFO "Unknown panel size max resolution = %d! "
464 "set default panel size.\n", tmds_setting->max_hres);
568 break; 465 break;
569 } 466 }
570 467
571 DEBUG_MSG(KERN_INFO "dvi panel size is %2d \n", 468 tmds_chip->tmds_chip_slave_addr = restore;
572 viaparinfo->tmds_setting_info->dvi_panel_size);
573 dvipanelsize = (unsigned char)(viaparinfo->
574 tmds_setting_info->dvi_panel_size);
575 return dvipanelsize;
576} 469}
577 470
578/* If Disable DVI, turn off pad */ 471/* If Disable DVI, turn off pad */
diff --git a/drivers/video/via/dvi.h b/drivers/video/via/dvi.h
index e1ec37fb0dc3..0dffcfd395f3 100644
--- a/drivers/video/via/dvi.h
+++ b/drivers/video/via/dvi.h
@@ -53,12 +53,13 @@
53#define DEV_CONNECT_DVI 0x01 53#define DEV_CONNECT_DVI 0x01
54#define DEV_CONNECT_HDMI 0x02 54#define DEV_CONNECT_HDMI 0x02
55 55
56struct VideoModeTable *viafb_get_cea_mode_tbl_pointer(int Index);
57int viafb_dvi_sense(void); 56int viafb_dvi_sense(void);
58void viafb_dvi_disable(void); 57void viafb_dvi_disable(void);
59void viafb_dvi_enable(void); 58void viafb_dvi_enable(void);
60int viafb_tmds_trasmitter_identify(void); 59int viafb_tmds_trasmitter_identify(void);
61void viafb_init_dvi_size(void); 60void viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
62void viafb_dvi_set_mode(int video_index, int mode_bpp, int set_iga); 61 struct tmds_setting_information *tmds_setting);
62void viafb_dvi_set_mode(struct VideoModeTable *videoMode, int mode_bpp,
63 int set_iga);
63 64
64#endif /* __DVI_H__ */ 65#endif /* __DVI_H__ */
diff --git a/drivers/video/via/global.c b/drivers/video/via/global.c
index b675cdbb03ad..1ee511b73307 100644
--- a/drivers/video/via/global.c
+++ b/drivers/video/via/global.c
@@ -23,15 +23,12 @@ int viafb_platform_epia_dvi = STATE_OFF;
23int viafb_device_lcd_dualedge = STATE_OFF; 23int viafb_device_lcd_dualedge = STATE_OFF;
24int viafb_bus_width = 12; 24int viafb_bus_width = 12;
25int viafb_display_hardware_layout = HW_LAYOUT_LCD_DVI; 25int viafb_display_hardware_layout = HW_LAYOUT_LCD_DVI;
26int viafb_memsize;
27int viafb_DeviceStatus = CRT_Device; 26int viafb_DeviceStatus = CRT_Device;
28int viafb_hotplug; 27int viafb_hotplug;
29int viafb_refresh = 60; 28int viafb_refresh = 60;
30int viafb_refresh1 = 60; 29int viafb_refresh1 = 60;
31int viafb_lcd_dsp_method = LCD_EXPANDSION; 30int viafb_lcd_dsp_method = LCD_EXPANDSION;
32int viafb_lcd_mode = LCD_OPENLDI; 31int viafb_lcd_mode = LCD_OPENLDI;
33int viafb_bpp = 32;
34int viafb_bpp1 = 32;
35int viafb_CRT_ON = 1; 32int viafb_CRT_ON = 1;
36int viafb_DVI_ON; 33int viafb_DVI_ON;
37int viafb_LCD_ON ; 34int viafb_LCD_ON ;
@@ -42,8 +39,6 @@ int viafb_hotplug_Xres = 640;
42int viafb_hotplug_Yres = 480; 39int viafb_hotplug_Yres = 480;
43int viafb_hotplug_bpp = 32; 40int viafb_hotplug_bpp = 32;
44int viafb_hotplug_refresh = 60; 41int viafb_hotplug_refresh = 60;
45unsigned int viafb_second_offset;
46int viafb_second_size;
47int viafb_primary_dev = None_Device; 42int viafb_primary_dev = None_Device;
48unsigned int viafb_second_xres = 640; 43unsigned int viafb_second_xres = 640;
49unsigned int viafb_second_yres = 480; 44unsigned int viafb_second_yres = 480;
diff --git a/drivers/video/via/global.h b/drivers/video/via/global.h
index d69d0ca99c2f..8d95d5fd1388 100644
--- a/drivers/video/via/global.h
+++ b/drivers/video/via/global.h
@@ -35,7 +35,6 @@
35 35
36#include "debug.h" 36#include "debug.h"
37 37
38#include "iface.h"
39#include "viafbdev.h" 38#include "viafbdev.h"
40#include "chip.h" 39#include "chip.h"
41#include "accel.h" 40#include "accel.h"
@@ -68,8 +67,6 @@ extern int viafb_refresh;
68extern int viafb_refresh1; 67extern int viafb_refresh1;
69extern int viafb_lcd_dsp_method; 68extern int viafb_lcd_dsp_method;
70extern int viafb_lcd_mode; 69extern int viafb_lcd_mode;
71extern int viafb_bpp;
72extern int viafb_bpp1;
73 70
74extern int viafb_CRT_ON; 71extern int viafb_CRT_ON;
75extern int viafb_hotplug_Xres; 72extern int viafb_hotplug_Xres;
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index 3e083ff67ae2..f2583b1b527f 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -524,7 +524,6 @@ static void dvi_patch_skew_dvp1(void);
524static void dvi_patch_skew_dvp_low(void); 524static void dvi_patch_skew_dvp_low(void);
525static void set_dvi_output_path(int set_iga, int output_interface); 525static void set_dvi_output_path(int set_iga, int output_interface);
526static void set_lcd_output_path(int set_iga, int output_interface); 526static void set_lcd_output_path(int set_iga, int output_interface);
527static int search_mode_setting(int ModeInfoIndex);
528static void load_fix_bit_crtc_reg(void); 527static void load_fix_bit_crtc_reg(void);
529static void init_gfx_chip_info(struct pci_dev *pdev, 528static void init_gfx_chip_info(struct pci_dev *pdev,
530 const struct pci_device_id *pdi); 529 const struct pci_device_id *pdi);
@@ -686,6 +685,84 @@ void viafb_set_secondary_pitch(u32 pitch)
686 viafb_write_reg_mask(0x71, VIACR, (pitch >> (10 - 7)) & 0x80, 0x80); 685 viafb_write_reg_mask(0x71, VIACR, (pitch >> (10 - 7)) & 0x80, 0x80);
687} 686}
688 687
688void viafb_set_primary_color_depth(u8 depth)
689{
690 u8 value;
691
692 DEBUG_MSG(KERN_DEBUG "viafb_set_primary_color_depth(%d)\n", depth);
693 switch (depth) {
694 case 8:
695 value = 0x00;
696 break;
697 case 15:
698 value = 0x04;
699 break;
700 case 16:
701 value = 0x14;
702 break;
703 case 24:
704 value = 0x0C;
705 break;
706 case 30:
707 value = 0x08;
708 break;
709 default:
710 printk(KERN_WARNING "viafb_set_primary_color_depth: "
711 "Unsupported depth: %d\n", depth);
712 return;
713 }
714
715 viafb_write_reg_mask(0x15, VIASR, value, 0x1C);
716}
717
718void viafb_set_secondary_color_depth(u8 depth)
719{
720 u8 value;
721
722 DEBUG_MSG(KERN_DEBUG "viafb_set_secondary_color_depth(%d)\n", depth);
723 switch (depth) {
724 case 8:
725 value = 0x00;
726 break;
727 case 16:
728 value = 0x40;
729 break;
730 case 24:
731 value = 0xC0;
732 break;
733 case 30:
734 value = 0x80;
735 break;
736 default:
737 printk(KERN_WARNING "viafb_set_secondary_color_depth: "
738 "Unsupported depth: %d\n", depth);
739 return;
740 }
741
742 viafb_write_reg_mask(0x67, VIACR, value, 0xC0);
743}
744
745static void set_color_register(u8 index, u8 red, u8 green, u8 blue)
746{
747 outb(0xFF, 0x3C6); /* bit mask of palette */
748 outb(index, 0x3C8);
749 outb(red, 0x3C9);
750 outb(green, 0x3C9);
751 outb(blue, 0x3C9);
752}
753
754void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue)
755{
756 viafb_write_reg_mask(0x1A, VIASR, 0x00, 0x01);
757 set_color_register(index, red, green, blue);
758}
759
760void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue)
761{
762 viafb_write_reg_mask(0x1A, VIASR, 0x01, 0x01);
763 set_color_register(index, red, green, blue);
764}
765
689void viafb_set_output_path(int device, int set_iga, int output_interface) 766void viafb_set_output_path(int device, int set_iga, int output_interface)
690{ 767{
691 switch (device) { 768 switch (device) {
@@ -710,11 +787,8 @@ static void set_crt_output_path(int set_iga)
710 viafb_write_reg_mask(SR16, VIASR, 0x00, BIT6); 787 viafb_write_reg_mask(SR16, VIASR, 0x00, BIT6);
711 break; 788 break;
712 case IGA2: 789 case IGA2:
713 case IGA1_IGA2:
714 viafb_write_reg_mask(CR6A, VIACR, 0xC0, BIT6 + BIT7); 790 viafb_write_reg_mask(CR6A, VIACR, 0xC0, BIT6 + BIT7);
715 viafb_write_reg_mask(SR16, VIASR, 0x40, BIT6); 791 viafb_write_reg_mask(SR16, VIASR, 0x40, BIT6);
716 if (set_iga == IGA1_IGA2)
717 viafb_write_reg_mask(CR6B, VIACR, 0x08, BIT3);
718 break; 792 break;
719 } 793 }
720} 794}
@@ -904,13 +978,6 @@ static void set_lcd_output_path(int set_iga, int output_interface)
904 978
905 enable_second_display_channel(); 979 enable_second_display_channel();
906 break; 980 break;
907
908 case IGA1_IGA2:
909 viafb_write_reg_mask(CR6B, VIACR, 0x08, BIT3);
910 viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
911
912 disable_second_display_channel();
913 break;
914 } 981 }
915 982
916 switch (output_interface) { 983 switch (output_interface) {
@@ -987,49 +1054,6 @@ static void set_lcd_output_path(int set_iga, int output_interface)
987 } 1054 }
988} 1055}
989 1056
990/* Search Mode Index */
991static int search_mode_setting(int ModeInfoIndex)
992{
993 int i = 0;
994
995 while ((i < NUM_TOTAL_MODETABLE) &&
996 (ModeInfoIndex != CLE266Modes[i].ModeIndex))
997 i++;
998 if (i >= NUM_TOTAL_MODETABLE)
999 i = 0;
1000 return i;
1001
1002}
1003
1004struct VideoModeTable *viafb_get_modetbl_pointer(int Index)
1005{
1006 struct VideoModeTable *TmpTbl = NULL;
1007 TmpTbl = &CLE266Modes[search_mode_setting(Index)];
1008 return TmpTbl;
1009}
1010
1011struct VideoModeTable *viafb_get_cea_mode_tbl_pointer(int Index)
1012{
1013 struct VideoModeTable *TmpTbl = NULL;
1014 int i = 0;
1015 while ((i < NUM_TOTAL_CEA_MODES) &&
1016 (Index != CEA_HDMI_Modes[i].ModeIndex))
1017 i++;
1018 if ((i < NUM_TOTAL_CEA_MODES))
1019 TmpTbl = &CEA_HDMI_Modes[i];
1020 else {
1021 /*Still use general timing if don't find CEA timing */
1022 i = 0;
1023 while ((i < NUM_TOTAL_MODETABLE) &&
1024 (Index != CLE266Modes[i].ModeIndex))
1025 i++;
1026 if (i >= NUM_TOTAL_MODETABLE)
1027 i = 0;
1028 TmpTbl = &CLE266Modes[i];
1029 }
1030 return TmpTbl;
1031}
1032
1033static void load_fix_bit_crtc_reg(void) 1057static void load_fix_bit_crtc_reg(void)
1034{ 1058{
1035 /* always set to 1 */ 1059 /* always set to 1 */
@@ -1121,15 +1145,13 @@ void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga)
1121 struct io_register *reg = NULL; 1145 struct io_register *reg = NULL;
1122 1146
1123 switch (set_iga) { 1147 switch (set_iga) {
1124 case IGA1_IGA2:
1125 case IGA1: 1148 case IGA1:
1126 reg_value = IGA1_FETCH_COUNT_FORMULA(h_addr, bpp_byte); 1149 reg_value = IGA1_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
1127 viafb_load_reg_num = fetch_count_reg. 1150 viafb_load_reg_num = fetch_count_reg.
1128 iga1_fetch_count_reg.reg_num; 1151 iga1_fetch_count_reg.reg_num;
1129 reg = fetch_count_reg.iga1_fetch_count_reg.reg; 1152 reg = fetch_count_reg.iga1_fetch_count_reg.reg;
1130 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR); 1153 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1131 if (set_iga == IGA1) 1154 break;
1132 break;
1133 case IGA2: 1155 case IGA2:
1134 reg_value = IGA2_FETCH_COUNT_FORMULA(h_addr, bpp_byte); 1156 reg_value = IGA2_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
1135 viafb_load_reg_num = fetch_count_reg. 1157 viafb_load_reg_num = fetch_count_reg.
@@ -1499,7 +1521,7 @@ void viafb_set_vclock(u32 CLK, int set_iga)
1499 /* H.W. Reset : ON */ 1521 /* H.W. Reset : ON */
1500 viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7); 1522 viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
1501 1523
1502 if ((set_iga == IGA1) || (set_iga == IGA1_IGA2)) { 1524 if (set_iga == IGA1) {
1503 /* Change D,N FOR VCLK */ 1525 /* Change D,N FOR VCLK */
1504 switch (viaparinfo->chip_info->gfx_chip_name) { 1526 switch (viaparinfo->chip_info->gfx_chip_name) {
1505 case UNICHROME_CLE266: 1527 case UNICHROME_CLE266:
@@ -1528,7 +1550,7 @@ void viafb_set_vclock(u32 CLK, int set_iga)
1528 } 1550 }
1529 } 1551 }
1530 1552
1531 if ((set_iga == IGA2) || (set_iga == IGA1_IGA2)) { 1553 if (set_iga == IGA2) {
1532 /* Change D,N FOR LCK */ 1554 /* Change D,N FOR LCK */
1533 switch (viaparinfo->chip_info->gfx_chip_name) { 1555 switch (viaparinfo->chip_info->gfx_chip_name) {
1534 case UNICHROME_CLE266: 1556 case UNICHROME_CLE266:
@@ -1557,12 +1579,12 @@ void viafb_set_vclock(u32 CLK, int set_iga)
1557 viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7); 1579 viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
1558 1580
1559 /* Reset PLL */ 1581 /* Reset PLL */
1560 if ((set_iga == IGA1) || (set_iga == IGA1_IGA2)) { 1582 if (set_iga == IGA1) {
1561 viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1); 1583 viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1);
1562 viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1); 1584 viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1);
1563 } 1585 }
1564 1586
1565 if ((set_iga == IGA2) || (set_iga == IGA1_IGA2)) { 1587 if (set_iga == IGA2) {
1566 viafb_write_reg_mask(SR40, VIASR, 0x01, BIT0); 1588 viafb_write_reg_mask(SR40, VIASR, 0x01, BIT0);
1567 viafb_write_reg_mask(SR40, VIASR, 0x00, BIT0); 1589 viafb_write_reg_mask(SR40, VIASR, 0x00, BIT0);
1568 } 1590 }
@@ -1805,47 +1827,15 @@ void viafb_load_crtc_timing(struct display_timing device_timing,
1805 viafb_lock_crt(); 1827 viafb_lock_crt();
1806} 1828}
1807 1829
1808void viafb_set_color_depth(int bpp_byte, int set_iga)
1809{
1810 if (set_iga == IGA1) {
1811 switch (bpp_byte) {
1812 case MODE_8BPP:
1813 viafb_write_reg_mask(SR15, VIASR, 0x22, 0x7E);
1814 break;
1815 case MODE_16BPP:
1816 viafb_write_reg_mask(SR15, VIASR, 0xB6, 0xFE);
1817 break;
1818 case MODE_32BPP:
1819 viafb_write_reg_mask(SR15, VIASR, 0xAE, 0xFE);
1820 break;
1821 }
1822 } else {
1823 switch (bpp_byte) {
1824 case MODE_8BPP:
1825 viafb_write_reg_mask(CR67, VIACR, 0x00, BIT6 + BIT7);
1826 break;
1827 case MODE_16BPP:
1828 viafb_write_reg_mask(CR67, VIACR, 0x40, BIT6 + BIT7);
1829 break;
1830 case MODE_32BPP:
1831 viafb_write_reg_mask(CR67, VIACR, 0xC0, BIT6 + BIT7);
1832 break;
1833 }
1834 }
1835}
1836
1837void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, 1830void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
1838 int mode_index, int bpp_byte, int set_iga) 1831 struct VideoModeTable *video_mode, int bpp_byte, int set_iga)
1839{ 1832{
1840 struct VideoModeTable *video_mode;
1841 struct display_timing crt_reg; 1833 struct display_timing crt_reg;
1842 int i; 1834 int i;
1843 int index = 0; 1835 int index = 0;
1844 int h_addr, v_addr; 1836 int h_addr, v_addr;
1845 u32 pll_D_N; 1837 u32 pll_D_N;
1846 1838
1847 video_mode = &CLE266Modes[search_mode_setting(mode_index)];
1848
1849 for (i = 0; i < video_mode->mode_array; i++) { 1839 for (i = 0; i < video_mode->mode_array; i++) {
1850 index = i; 1840 index = i;
1851 1841
@@ -1858,8 +1848,10 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
1858 1848
1859 /* Mode 640x480 has border, but LCD/DFP didn't have border. */ 1849 /* Mode 640x480 has border, but LCD/DFP didn't have border. */
1860 /* So we would delete border. */ 1850 /* So we would delete border. */
1861 if ((viafb_LCD_ON | viafb_DVI_ON) && (mode_index == VIA_RES_640X480) 1851 if ((viafb_LCD_ON | viafb_DVI_ON)
1862 && (viaparinfo->crt_setting_info->refresh_rate == 60)) { 1852 && video_mode->crtc[0].crtc.hor_addr == 640
1853 && video_mode->crtc[0].crtc.ver_addr == 480
1854 && viaparinfo->crt_setting_info->refresh_rate == 60) {
1863 /* The border is 8 pixels. */ 1855 /* The border is 8 pixels. */
1864 crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8; 1856 crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8;
1865 1857
@@ -1912,9 +1904,6 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
1912 && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)) 1904 && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
1913 viafb_load_FIFO_reg(set_iga, h_addr, v_addr); 1905 viafb_load_FIFO_reg(set_iga, h_addr, v_addr);
1914 1906
1915 /* load SR Register About Memory and Color part */
1916 viafb_set_color_depth(bpp_byte, set_iga);
1917
1918 pll_D_N = viafb_get_clk_value(crt_table[index].clk); 1907 pll_D_N = viafb_get_clk_value(crt_table[index].clk);
1919 DEBUG_MSG(KERN_INFO "PLL=%x", pll_D_N); 1908 DEBUG_MSG(KERN_INFO "PLL=%x", pll_D_N);
1920 viafb_set_vclock(pll_D_N, set_iga); 1909 viafb_set_vclock(pll_D_N, set_iga);
@@ -1956,9 +1945,6 @@ void viafb_update_device_setting(int hres, int vres,
1956 1945
1957 viaparinfo->tmds_setting_info->h_active = hres; 1946 viaparinfo->tmds_setting_info->h_active = hres;
1958 viaparinfo->tmds_setting_info->v_active = vres; 1947 viaparinfo->tmds_setting_info->v_active = vres;
1959 viaparinfo->tmds_setting_info->bpp = bpp;
1960 viaparinfo->tmds_setting_info->refresh_rate =
1961 vmode_refresh;
1962 1948
1963 viaparinfo->lvds_setting_info->h_active = hres; 1949 viaparinfo->lvds_setting_info->h_active = hres;
1964 viaparinfo->lvds_setting_info->v_active = vres; 1950 viaparinfo->lvds_setting_info->v_active = vres;
@@ -1975,9 +1961,6 @@ void viafb_update_device_setting(int hres, int vres,
1975 if (viaparinfo->tmds_setting_info->iga_path == IGA2) { 1961 if (viaparinfo->tmds_setting_info->iga_path == IGA2) {
1976 viaparinfo->tmds_setting_info->h_active = hres; 1962 viaparinfo->tmds_setting_info->h_active = hres;
1977 viaparinfo->tmds_setting_info->v_active = vres; 1963 viaparinfo->tmds_setting_info->v_active = vres;
1978 viaparinfo->tmds_setting_info->bpp = bpp;
1979 viaparinfo->tmds_setting_info->refresh_rate =
1980 vmode_refresh;
1981 } 1964 }
1982 1965
1983 if (viaparinfo->lvds_setting_info->iga_path == IGA2) { 1966 if (viaparinfo->lvds_setting_info->iga_path == IGA2) {
@@ -2076,9 +2059,8 @@ static void init_tmds_chip_info(void)
2076 2059
2077 DEBUG_MSG(KERN_INFO "TMDS Chip = %d\n", 2060 DEBUG_MSG(KERN_INFO "TMDS Chip = %d\n",
2078 viaparinfo->chip_info->tmds_chip_info.tmds_chip_name); 2061 viaparinfo->chip_info->tmds_chip_info.tmds_chip_name);
2079 viaparinfo->tmds_setting_info->get_dvi_size_method = 2062 viafb_init_dvi_size(&viaparinfo->shared->chip_info.tmds_chip_info,
2080 GET_DVI_SIZE_BY_VGA_BIOS; 2063 &viaparinfo->shared->tmds_setting_info);
2081 viafb_init_dvi_size();
2082} 2064}
2083 2065
2084static void init_lvds_chip_info(void) 2066static void init_lvds_chip_info(void)
@@ -2195,28 +2177,19 @@ static void set_display_channel(void)
2195 } 2177 }
2196} 2178}
2197 2179
2198int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, 2180int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
2199 int vmode_index1, int hor_res1, int ver_res1, int video_bpp1) 2181 struct VideoModeTable *vmode_tbl1, int video_bpp1)
2200{ 2182{
2201 int i, j; 2183 int i, j;
2202 int port; 2184 int port;
2203 u8 value, index, mask; 2185 u8 value, index, mask;
2204 struct VideoModeTable *vmode_tbl;
2205 struct crt_mode_table *crt_timing; 2186 struct crt_mode_table *crt_timing;
2206 struct VideoModeTable *vmode_tbl1 = NULL;
2207 struct crt_mode_table *crt_timing1 = NULL; 2187 struct crt_mode_table *crt_timing1 = NULL;
2208 2188
2209 DEBUG_MSG(KERN_INFO "Set Mode!!\n");
2210 DEBUG_MSG(KERN_INFO
2211 "vmode_index=%d hor_res=%d ver_res=%d video_bpp=%d\n",
2212 vmode_index, hor_res, ver_res, video_bpp);
2213
2214 device_screen_off(); 2189 device_screen_off();
2215 vmode_tbl = &CLE266Modes[search_mode_setting(vmode_index)];
2216 crt_timing = vmode_tbl->crtc; 2190 crt_timing = vmode_tbl->crtc;
2217 2191
2218 if (viafb_SAMM_ON == 1) { 2192 if (viafb_SAMM_ON == 1) {
2219 vmode_tbl1 = &CLE266Modes[search_mode_setting(vmode_index1)];
2220 crt_timing1 = vmode_tbl1->crtc; 2193 crt_timing1 = vmode_tbl1->crtc;
2221 } 2194 }
2222 2195
@@ -2267,12 +2240,11 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp,
2267 outb(VPIT.SR[i - 1], VIASR + 1); 2240 outb(VPIT.SR[i - 1], VIASR + 1);
2268 } 2241 }
2269 2242
2270 viafb_set_primary_address(0); 2243 viafb_write_reg_mask(0x15, VIASR, 0xA2, 0xA2);
2271 viafb_set_secondary_address(viafb_SAMM_ON ? viafb_second_offset : 0);
2272 viafb_set_iga_path(); 2244 viafb_set_iga_path();
2273 2245
2274 /* Write CRTC */ 2246 /* Write CRTC */
2275 viafb_fill_crtc_timing(crt_timing, vmode_index, video_bpp / 8, IGA1); 2247 viafb_fill_crtc_timing(crt_timing, vmode_tbl, video_bpp / 8, IGA1);
2276 2248
2277 /* Write Graphic Controller */ 2249 /* Write Graphic Controller */
2278 for (i = 0; i < StdGR; i++) { 2250 for (i = 0; i < StdGR; i++) {
@@ -2292,65 +2264,25 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp,
2292 2264
2293 /* Update Patch Register */ 2265 /* Update Patch Register */
2294 2266
2295 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) 2267 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266
2296 || (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400)) { 2268 || viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400)
2297 for (i = 0; i < NUM_TOTAL_PATCH_MODE; i++) { 2269 && vmode_tbl->crtc[0].crtc.hor_addr == 1024
2298 if (res_patch_table[i].mode_index == vmode_index) { 2270 && vmode_tbl->crtc[0].crtc.ver_addr == 768) {
2299 for (j = 0; 2271 for (j = 0; j < res_patch_table[0].table_length; j++) {
2300 j < res_patch_table[i].table_length; j++) { 2272 index = res_patch_table[0].io_reg_table[j].index;
2301 index = 2273 port = res_patch_table[0].io_reg_table[j].port;
2302 res_patch_table[i]. 2274 value = res_patch_table[0].io_reg_table[j].value;
2303 io_reg_table[j].index; 2275 mask = res_patch_table[0].io_reg_table[j].mask;
2304 port = 2276 viafb_write_reg_mask(index, port, value, mask);
2305 res_patch_table[i].
2306 io_reg_table[j].port;
2307 value =
2308 res_patch_table[i].
2309 io_reg_table[j].value;
2310 mask =
2311 res_patch_table[i].
2312 io_reg_table[j].mask;
2313 viafb_write_reg_mask(index, port, value,
2314 mask);
2315 }
2316 }
2317 }
2318 }
2319
2320 if (viafb_SAMM_ON == 1) {
2321 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
2322 || (viaparinfo->chip_info->gfx_chip_name ==
2323 UNICHROME_K400)) {
2324 for (i = 0; i < NUM_TOTAL_PATCH_MODE; i++) {
2325 if (res_patch_table[i].mode_index ==
2326 vmode_index1) {
2327 for (j = 0;
2328 j <
2329 res_patch_table[i].
2330 table_length; j++) {
2331 index =
2332 res_patch_table[i].
2333 io_reg_table[j].index;
2334 port =
2335 res_patch_table[i].
2336 io_reg_table[j].port;
2337 value =
2338 res_patch_table[i].
2339 io_reg_table[j].value;
2340 mask =
2341 res_patch_table[i].
2342 io_reg_table[j].mask;
2343 viafb_write_reg_mask(index,
2344 port, value, mask);
2345 }
2346 }
2347 }
2348 } 2277 }
2349 } 2278 }
2350 2279
2351 viafb_set_primary_pitch(viafbinfo->fix.line_length); 2280 viafb_set_primary_pitch(viafbinfo->fix.line_length);
2352 viafb_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length 2281 viafb_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length
2353 : viafbinfo->fix.line_length); 2282 : viafbinfo->fix.line_length);
2283 viafb_set_primary_color_depth(viaparinfo->depth);
2284 viafb_set_secondary_color_depth(viafb_dual_fb ? viaparinfo1->depth
2285 : viaparinfo->depth);
2354 /* Update Refresh Rate Setting */ 2286 /* Update Refresh Rate Setting */
2355 2287
2356 /* Clear On Screen */ 2288 /* Clear On Screen */
@@ -2359,11 +2291,11 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp,
2359 if (viafb_CRT_ON) { 2291 if (viafb_CRT_ON) {
2360 if (viafb_SAMM_ON && (viaparinfo->crt_setting_info->iga_path == 2292 if (viafb_SAMM_ON && (viaparinfo->crt_setting_info->iga_path ==
2361 IGA2)) { 2293 IGA2)) {
2362 viafb_fill_crtc_timing(crt_timing1, vmode_index1, 2294 viafb_fill_crtc_timing(crt_timing1, vmode_tbl1,
2363 video_bpp1 / 8, 2295 video_bpp1 / 8,
2364 viaparinfo->crt_setting_info->iga_path); 2296 viaparinfo->crt_setting_info->iga_path);
2365 } else { 2297 } else {
2366 viafb_fill_crtc_timing(crt_timing, vmode_index, 2298 viafb_fill_crtc_timing(crt_timing, vmode_tbl,
2367 video_bpp / 8, 2299 video_bpp / 8,
2368 viaparinfo->crt_setting_info->iga_path); 2300 viaparinfo->crt_setting_info->iga_path);
2369 } 2301 }
@@ -2373,7 +2305,7 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp,
2373 /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode 2305 /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode
2374 to 8 alignment (1368),there is several pixels (2 pixels) 2306 to 8 alignment (1368),there is several pixels (2 pixels)
2375 on right side of screen. */ 2307 on right side of screen. */
2376 if (hor_res % 8) { 2308 if (vmode_tbl->crtc[0].crtc.hor_addr % 8) {
2377 viafb_unlock_crt(); 2309 viafb_unlock_crt();
2378 viafb_write_reg(CR02, VIACR, 2310 viafb_write_reg(CR02, VIACR,
2379 viafb_read_reg(VIACR, CR02) - 1); 2311 viafb_read_reg(VIACR, CR02) - 1);
@@ -2384,14 +2316,14 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp,
2384 if (viafb_DVI_ON) { 2316 if (viafb_DVI_ON) {
2385 if (viafb_SAMM_ON && 2317 if (viafb_SAMM_ON &&
2386 (viaparinfo->tmds_setting_info->iga_path == IGA2)) { 2318 (viaparinfo->tmds_setting_info->iga_path == IGA2)) {
2387 viafb_dvi_set_mode(viafb_get_mode_index 2319 viafb_dvi_set_mode(viafb_get_mode
2388 (viaparinfo->tmds_setting_info->h_active, 2320 (viaparinfo->tmds_setting_info->h_active,
2389 viaparinfo->tmds_setting_info-> 2321 viaparinfo->tmds_setting_info->
2390 v_active), 2322 v_active),
2391 video_bpp1, viaparinfo-> 2323 video_bpp1, viaparinfo->
2392 tmds_setting_info->iga_path); 2324 tmds_setting_info->iga_path);
2393 } else { 2325 } else {
2394 viafb_dvi_set_mode(viafb_get_mode_index 2326 viafb_dvi_set_mode(viafb_get_mode
2395 (viaparinfo->tmds_setting_info->h_active, 2327 (viaparinfo->tmds_setting_info->h_active,
2396 viaparinfo-> 2328 viaparinfo->
2397 tmds_setting_info->v_active), 2329 tmds_setting_info->v_active),
@@ -2445,8 +2377,8 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp,
2445 2377
2446 /* If set mode normally, save resolution information for hot-plug . */ 2378 /* If set mode normally, save resolution information for hot-plug . */
2447 if (!viafb_hotplug) { 2379 if (!viafb_hotplug) {
2448 viafb_hotplug_Xres = hor_res; 2380 viafb_hotplug_Xres = vmode_tbl->crtc[0].crtc.hor_addr;
2449 viafb_hotplug_Yres = ver_res; 2381 viafb_hotplug_Yres = vmode_tbl->crtc[0].crtc.ver_addr;
2450 viafb_hotplug_bpp = video_bpp; 2382 viafb_hotplug_bpp = video_bpp;
2451 viafb_hotplug_refresh = viafb_refresh; 2383 viafb_hotplug_refresh = viafb_refresh;
2452 2384
@@ -2706,13 +2638,11 @@ void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
2706 2638
2707/*According var's xres, yres fill var's other timing information*/ 2639/*According var's xres, yres fill var's other timing information*/
2708void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, 2640void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
2709 int mode_index) 2641 struct VideoModeTable *vmode_tbl)
2710{ 2642{
2711 struct VideoModeTable *vmode_tbl = NULL;
2712 struct crt_mode_table *crt_timing = NULL; 2643 struct crt_mode_table *crt_timing = NULL;
2713 struct display_timing crt_reg; 2644 struct display_timing crt_reg;
2714 int i = 0, index = 0; 2645 int i = 0, index = 0;
2715 vmode_tbl = &CLE266Modes[search_mode_setting(mode_index)];
2716 crt_timing = vmode_tbl->crtc; 2646 crt_timing = vmode_tbl->crtc;
2717 for (i = 0; i < vmode_tbl->mode_array; i++) { 2647 for (i = 0; i < vmode_tbl->mode_array; i++) {
2718 index = i; 2648 index = i;
@@ -2721,36 +2651,6 @@ void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
2721 } 2651 }
2722 2652
2723 crt_reg = crt_timing[index].crtc; 2653 crt_reg = crt_timing[index].crtc;
2724 switch (var->bits_per_pixel) {
2725 case 8:
2726 var->red.offset = 0;
2727 var->green.offset = 0;
2728 var->blue.offset = 0;
2729 var->red.length = 6;
2730 var->green.length = 6;
2731 var->blue.length = 6;
2732 break;
2733 case 16:
2734 var->red.offset = 11;
2735 var->green.offset = 5;
2736 var->blue.offset = 0;
2737 var->red.length = 5;
2738 var->green.length = 6;
2739 var->blue.length = 5;
2740 break;
2741 case 32:
2742 var->red.offset = 16;
2743 var->green.offset = 8;
2744 var->blue.offset = 0;
2745 var->red.length = 8;
2746 var->green.length = 8;
2747 var->blue.length = 8;
2748 break;
2749 default:
2750 /* never happed, put here to keep consistent */
2751 break;
2752 }
2753
2754 var->pixclock = viafb_get_pixclock(var->xres, var->yres, refresh); 2654 var->pixclock = viafb_get_pixclock(var->xres, var->yres, refresh);
2755 var->left_margin = 2655 var->left_margin =
2756 crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end); 2656 crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end);
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index b874d952b446..12ef32d334cb 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -22,6 +22,7 @@
22#ifndef __HW_H__ 22#ifndef __HW_H__
23#define __HW_H__ 23#define __HW_H__
24 24
25#include "viamode.h"
25#include "global.h" 26#include "global.h"
26 27
27/*************************************************** 28/***************************************************
@@ -862,8 +863,6 @@ struct pci_device_id_info {
862}; 863};
863 864
864extern unsigned int viafb_second_virtual_xres; 865extern unsigned int viafb_second_virtual_xres;
865extern unsigned int viafb_second_offset;
866extern int viafb_second_size;
867extern int viafb_SAMM_ON; 866extern int viafb_SAMM_ON;
868extern int viafb_dual_fb; 867extern int viafb_dual_fb;
869extern int viafb_LCD2_ON; 868extern int viafb_LCD2_ON;
@@ -874,8 +873,9 @@ extern int viafb_hotplug;
874void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask); 873void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask);
875void viafb_set_output_path(int device, int set_iga, 874void viafb_set_output_path(int device, int set_iga,
876 int output_interface); 875 int output_interface);
876
877void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, 877void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
878 int mode_index, int bpp_byte, int set_iga); 878 struct VideoModeTable *video_mode, int bpp_byte, int set_iga);
879 879
880void viafb_set_vclock(u32 CLK, int set_iga); 880void viafb_set_vclock(u32 CLK, int set_iga);
881void viafb_load_reg(int timing_value, int viafb_load_reg_num, 881void viafb_load_reg(int timing_value, int viafb_load_reg_num,
@@ -891,16 +891,15 @@ void viafb_lock_crt(void);
891void viafb_unlock_crt(void); 891void viafb_unlock_crt(void);
892void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga); 892void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga);
893void viafb_write_regx(struct io_reg RegTable[], int ItemNum); 893void viafb_write_regx(struct io_reg RegTable[], int ItemNum);
894struct VideoModeTable *viafb_get_modetbl_pointer(int Index);
895u32 viafb_get_clk_value(int clk); 894u32 viafb_get_clk_value(int clk);
896void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active); 895void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active);
897void viafb_set_color_depth(int bpp_byte, int set_iga);
898void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ 896void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
899 *p_gfx_dpa_setting); 897 *p_gfx_dpa_setting);
900 898
901int viafb_setmode(int vmode_index, int hor_res, int ver_res, 899int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
902 int video_bpp, int vmode_index1, int hor_res1, 900 struct VideoModeTable *vmode_tbl1, int video_bpp1);
903 int ver_res1, int video_bpp1); 901void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
902 struct VideoModeTable *vmode_tbl);
904void viafb_init_chip_info(struct pci_dev *pdev, 903void viafb_init_chip_info(struct pci_dev *pdev,
905 const struct pci_device_id *pdi); 904 const struct pci_device_id *pdi);
906void viafb_init_dac(int set_iga); 905void viafb_init_dac(int set_iga);
@@ -915,6 +914,8 @@ void viafb_set_primary_address(u32 addr);
915void viafb_set_secondary_address(u32 addr); 914void viafb_set_secondary_address(u32 addr);
916void viafb_set_primary_pitch(u32 pitch); 915void viafb_set_primary_pitch(u32 pitch);
917void viafb_set_secondary_pitch(u32 pitch); 916void viafb_set_secondary_pitch(u32 pitch);
917void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue);
918void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue);
918void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len); 919void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len);
919 920
920#endif /* __HW_H__ */ 921#endif /* __HW_H__ */
diff --git a/drivers/video/via/iface.c b/drivers/video/via/iface.c
deleted file mode 100644
index 1570636c8d51..000000000000
--- a/drivers/video/via/iface.c
+++ /dev/null
@@ -1,78 +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"
23
24/* Get frame buffer size from VGA BIOS */
25
26unsigned int viafb_get_memsize(void)
27{
28 unsigned int m;
29
30 /* If memory size provided by user */
31 if (viafb_memsize)
32 m = viafb_memsize * Mb;
33 else {
34 m = (unsigned int)viafb_read_reg(VIASR, SR39);
35 m = m * (4 * Mb);
36
37 if ((m < (16 * Mb)) || (m > (64 * Mb)))
38 m = 16 * Mb;
39 }
40 DEBUG_MSG(KERN_INFO "framebuffer size = %d Mb\n", m / Mb);
41 return m;
42}
43
44/* Get Video Buffer Starting Physical Address(back door)*/
45
46unsigned long viafb_get_videobuf_addr(void)
47{
48 struct pci_dev *pdev = NULL;
49 unsigned char sys_mem;
50 unsigned char video_mem;
51 unsigned long sys_mem_size;
52 unsigned long video_mem_size;
53 /*system memory = 256 MB, video memory 64 MB */
54 unsigned long vmem_starting_adr = 0x0C000000;
55
56 pdev =
57 (struct pci_dev *)pci_get_device(VIA_K800_BRIDGE_VID,
58 VIA_K800_BRIDGE_DID, NULL);
59 if (pdev != NULL) {
60 pci_read_config_byte(pdev, VIA_K800_SYSTEM_MEMORY_REG,
61 &sys_mem);
62 pci_read_config_byte(pdev, VIA_K800_VIDEO_MEMORY_REG,
63 &video_mem);
64 video_mem = (video_mem & 0x70) >> 4;
65 sys_mem_size = ((unsigned long)sys_mem) << 24;
66 if (video_mem != 0)
67 video_mem_size = (1 << (video_mem)) * 1024 * 1024;
68 else
69 video_mem_size = 0;
70
71 vmem_starting_adr = sys_mem_size - video_mem_size;
72 pci_dev_put(pdev);
73 }
74
75 DEBUG_MSG(KERN_INFO "Video Memory Starting Address = %lx \n",
76 vmem_starting_adr);
77 return vmem_starting_adr;
78}
diff --git a/drivers/video/via/iface.h b/drivers/video/via/iface.h
deleted file mode 100644
index 790ec3e3aea2..000000000000
--- a/drivers/video/via/iface.h
+++ /dev/null
@@ -1,38 +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 __IFACE_H__
23#define __IFACE_H__
24
25#define Kb (1024)
26#define Mb (Kb*Kb)
27
28#define VIA_K800_BRIDGE_VID 0x1106
29#define VIA_K800_BRIDGE_DID 0x3204
30
31#define VIA_K800_SYSTEM_MEMORY_REG 0x47
32#define VIA_K800_VIDEO_MEMORY_REG 0xA1
33
34extern int viafb_memsize;
35unsigned int viafb_get_memsize(void);
36unsigned long viafb_get_videobuf_addr(void);
37
38#endif /* __IFACE_H__ */
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c
index e3e597f937a5..1b1ccdc2d83d 100644
--- a/drivers/video/via/lcd.c
+++ b/drivers/video/via/lcd.c
@@ -22,25 +22,7 @@
22#include "global.h" 22#include "global.h"
23#include "lcdtbl.h" 23#include "lcdtbl.h"
24 24
25static struct iga2_shadow_crtc_timing iga2_shadow_crtc_reg = { 25#define viafb_compact_res(x, y) (((x)<<16)|(y))
26 /* IGA2 Shadow Horizontal Total */
27 {IGA2_SHADOW_HOR_TOTAL_REG_NUM, {{CR6D, 0, 7}, {CR71, 3, 3} } },
28 /* IGA2 Shadow Horizontal Blank End */
29 {IGA2_SHADOW_HOR_BLANK_END_REG_NUM, {{CR6E, 0, 7} } },
30 /* IGA2 Shadow Vertical Total */
31 {IGA2_SHADOW_VER_TOTAL_REG_NUM, {{CR6F, 0, 7}, {CR71, 0, 2} } },
32 /* IGA2 Shadow Vertical Addressable Video */
33 {IGA2_SHADOW_VER_ADDR_REG_NUM, {{CR70, 0, 7}, {CR71, 4, 6} } },
34 /* IGA2 Shadow Vertical Blank Start */
35 {IGA2_SHADOW_VER_BLANK_START_REG_NUM,
36 {{CR72, 0, 7}, {CR74, 4, 6} } },
37 /* IGA2 Shadow Vertical Blank End */
38 {IGA2_SHADOW_VER_BLANK_END_REG_NUM, {{CR73, 0, 7}, {CR74, 0, 2} } },
39 /* IGA2 Shadow Vertical Sync Start */
40 {IGA2_SHADOW_VER_SYNC_START_REG_NUM, {{CR75, 0, 7}, {CR76, 4, 6} } },
41 /* IGA2 Shadow Vertical Sync End */
42 {IGA2_SHADOW_VER_SYNC_END_REG_NUM, {{CR76, 0, 3} } }
43};
44 26
45static struct _lcd_scaling_factor lcd_scaling_factor = { 27static struct _lcd_scaling_factor lcd_scaling_factor = {
46 /* LCD Horizontal Scaling Factor Register */ 28 /* LCD Horizontal Scaling Factor Register */
@@ -59,16 +41,10 @@ static struct _lcd_scaling_factor lcd_scaling_factor_CLE = {
59 41
60static int check_lvds_chip(int device_id_subaddr, int device_id); 42static int check_lvds_chip(int device_id_subaddr, int device_id);
61static bool lvds_identify_integratedlvds(void); 43static bool lvds_identify_integratedlvds(void);
62static int fp_id_to_vindex(int panel_id); 44static void fp_id_to_vindex(int panel_id);
63static int lvds_register_read(int index); 45static int lvds_register_read(int index);
64static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres, 46static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
65 int panel_vres); 47 int panel_vres);
66static void load_lcd_k400_patch_tbl(int set_hres, int set_vres,
67 int panel_id);
68static void load_lcd_p880_patch_tbl(int set_hres, int set_vres,
69 int panel_id);
70static void load_lcd_patch_regs(int set_hres, int set_vres,
71 int panel_id, int set_iga);
72static void via_pitch_alignment_patch_lcd( 48static void via_pitch_alignment_patch_lcd(
73 struct lvds_setting_information *plvds_setting_info, 49 struct lvds_setting_information *plvds_setting_info,
74 struct lvds_chip_information 50 struct lvds_chip_information
@@ -98,8 +74,6 @@ static void check_diport_of_integrated_lvds(
98static struct display_timing lcd_centering_timging(struct display_timing 74static struct display_timing lcd_centering_timging(struct display_timing
99 mode_crt_reg, 75 mode_crt_reg,
100 struct display_timing panel_crt_reg); 76 struct display_timing panel_crt_reg);
101static void load_crtc_shadow_timing(struct display_timing mode_timing,
102 struct display_timing panel_timing);
103static void viafb_load_scaling_factor_for_p4m900(int set_hres, 77static void viafb_load_scaling_factor_for_p4m900(int set_hres,
104 int set_vres, int panel_hres, int panel_vres); 78 int set_vres, int panel_hres, int panel_vres);
105 79
@@ -125,33 +99,24 @@ void viafb_init_lcd_size(void)
125 break; 99 break;
126 case GET_LCD_SIZE_BY_VGA_BIOS: 100 case GET_LCD_SIZE_BY_VGA_BIOS:
127 DEBUG_MSG(KERN_INFO "Get LCD Size method by VGA BIOS !!\n"); 101 DEBUG_MSG(KERN_INFO "Get LCD Size method by VGA BIOS !!\n");
128 viaparinfo->lvds_setting_info->lcd_panel_size = 102 fp_id_to_vindex(viafb_lcd_panel_id);
129 fp_id_to_vindex(viafb_lcd_panel_id);
130 DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n", 103 DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n",
131 viaparinfo->lvds_setting_info->lcd_panel_id); 104 viaparinfo->lvds_setting_info->lcd_panel_id);
132 DEBUG_MSG(KERN_INFO "LCD Panel Size = %d\n",
133 viaparinfo->lvds_setting_info->lcd_panel_size);
134 break; 105 break;
135 case GET_LCD_SIZE_BY_USER_SETTING: 106 case GET_LCD_SIZE_BY_USER_SETTING:
136 DEBUG_MSG(KERN_INFO "Get LCD Size method by user setting !!\n"); 107 DEBUG_MSG(KERN_INFO "Get LCD Size method by user setting !!\n");
137 viaparinfo->lvds_setting_info->lcd_panel_size = 108 fp_id_to_vindex(viafb_lcd_panel_id);
138 fp_id_to_vindex(viafb_lcd_panel_id);
139 DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n", 109 DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n",
140 viaparinfo->lvds_setting_info->lcd_panel_id); 110 viaparinfo->lvds_setting_info->lcd_panel_id);
141 DEBUG_MSG(KERN_INFO "LCD Panel Size = %d\n",
142 viaparinfo->lvds_setting_info->lcd_panel_size);
143 break; 111 break;
144 default: 112 default:
145 DEBUG_MSG(KERN_INFO "viafb_init_lcd_size fail\n"); 113 DEBUG_MSG(KERN_INFO "viafb_init_lcd_size fail\n");
146 viaparinfo->lvds_setting_info->lcd_panel_id = 114 viaparinfo->lvds_setting_info->lcd_panel_id =
147 LCD_PANEL_ID1_800X600; 115 LCD_PANEL_ID1_800X600;
148 viaparinfo->lvds_setting_info->lcd_panel_size = 116 fp_id_to_vindex(LCD_PANEL_ID1_800X600);
149 fp_id_to_vindex(LCD_PANEL_ID1_800X600);
150 } 117 }
151 viaparinfo->lvds_setting_info2->lcd_panel_id = 118 viaparinfo->lvds_setting_info2->lcd_panel_id =
152 viaparinfo->lvds_setting_info->lcd_panel_id; 119 viaparinfo->lvds_setting_info->lcd_panel_id;
153 viaparinfo->lvds_setting_info2->lcd_panel_size =
154 viaparinfo->lvds_setting_info->lcd_panel_size;
155 viaparinfo->lvds_setting_info2->lcd_panel_hres = 120 viaparinfo->lvds_setting_info2->lcd_panel_hres =
156 viaparinfo->lvds_setting_info->lcd_panel_hres; 121 viaparinfo->lvds_setting_info->lcd_panel_hres;
157 viaparinfo->lvds_setting_info2->lcd_panel_vres = 122 viaparinfo->lvds_setting_info2->lcd_panel_vres =
@@ -171,13 +136,13 @@ static bool lvds_identify_integratedlvds(void)
171 if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) { 136 if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
172 viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name = 137 viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
173 INTEGRATED_LVDS; 138 INTEGRATED_LVDS;
174 DEBUG_MSG(KERN_INFO "Support two dual channel LVDS!\ 139 DEBUG_MSG(KERN_INFO "Support two dual channel LVDS! "
175 (Internal LVDS + External LVDS)\n"); 140 "(Internal LVDS + External LVDS)\n");
176 } else { 141 } else {
177 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = 142 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
178 INTEGRATED_LVDS; 143 INTEGRATED_LVDS;
179 DEBUG_MSG(KERN_INFO "Not found external LVDS,\ 144 DEBUG_MSG(KERN_INFO "Not found external LVDS, "
180 so can't support two dual channel LVDS!\n"); 145 "so can't support two dual channel LVDS!\n");
181 } 146 }
182 } else if (viafb_display_hardware_layout == HW_LAYOUT_LCD1_LCD2) { 147 } else if (viafb_display_hardware_layout == HW_LAYOUT_LCD1_LCD2) {
183 /* Two single channel LCD (Internal LVDS + Internal LVDS): */ 148 /* Two single channel LCD (Internal LVDS + Internal LVDS): */
@@ -185,8 +150,8 @@ static bool lvds_identify_integratedlvds(void)
185 INTEGRATED_LVDS; 150 INTEGRATED_LVDS;
186 viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name = 151 viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
187 INTEGRATED_LVDS; 152 INTEGRATED_LVDS;
188 DEBUG_MSG(KERN_INFO "Support two single channel LVDS!\ 153 DEBUG_MSG(KERN_INFO "Support two single channel LVDS! "
189 (Internal LVDS + Internal LVDS)\n"); 154 "(Internal LVDS + Internal LVDS)\n");
190 } else if (viafb_display_hardware_layout != HW_LAYOUT_DVI_ONLY) { 155 } else if (viafb_display_hardware_layout != HW_LAYOUT_DVI_ONLY) {
191 /* If we have found external LVDS, just use it, 156 /* If we have found external LVDS, just use it,
192 otherwise, we will use internal LVDS as default. */ 157 otherwise, we will use internal LVDS as default. */
@@ -248,7 +213,7 @@ int viafb_lvds_trasmitter_identify(void)
248 return FAIL; 213 return FAIL;
249} 214}
250 215
251static int fp_id_to_vindex(int panel_id) 216static void fp_id_to_vindex(int panel_id)
252{ 217{
253 DEBUG_MSG(KERN_INFO "fp_get_panel_id()\n"); 218 DEBUG_MSG(KERN_INFO "fp_get_panel_id()\n");
254 219
@@ -264,7 +229,6 @@ static int fp_id_to_vindex(int panel_id)
264 LCD_PANEL_ID0_640X480; 229 LCD_PANEL_ID0_640X480;
265 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 230 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
266 viaparinfo->lvds_setting_info->LCDDithering = 1; 231 viaparinfo->lvds_setting_info->LCDDithering = 1;
267 return VIA_RES_640X480;
268 break; 232 break;
269 case 0x1: 233 case 0x1:
270 viaparinfo->lvds_setting_info->lcd_panel_hres = 800; 234 viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
@@ -273,7 +237,6 @@ static int fp_id_to_vindex(int panel_id)
273 LCD_PANEL_ID1_800X600; 237 LCD_PANEL_ID1_800X600;
274 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 238 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
275 viaparinfo->lvds_setting_info->LCDDithering = 1; 239 viaparinfo->lvds_setting_info->LCDDithering = 1;
276 return VIA_RES_800X600;
277 break; 240 break;
278 case 0x2: 241 case 0x2:
279 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; 242 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
@@ -282,7 +245,6 @@ static int fp_id_to_vindex(int panel_id)
282 LCD_PANEL_ID2_1024X768; 245 LCD_PANEL_ID2_1024X768;
283 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 246 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
284 viaparinfo->lvds_setting_info->LCDDithering = 1; 247 viaparinfo->lvds_setting_info->LCDDithering = 1;
285 return VIA_RES_1024X768;
286 break; 248 break;
287 case 0x3: 249 case 0x3:
288 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; 250 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
@@ -291,7 +253,6 @@ static int fp_id_to_vindex(int panel_id)
291 LCD_PANEL_ID3_1280X768; 253 LCD_PANEL_ID3_1280X768;
292 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 254 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
293 viaparinfo->lvds_setting_info->LCDDithering = 1; 255 viaparinfo->lvds_setting_info->LCDDithering = 1;
294 return VIA_RES_1280X768;
295 break; 256 break;
296 case 0x4: 257 case 0x4:
297 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; 258 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
@@ -300,7 +261,6 @@ static int fp_id_to_vindex(int panel_id)
300 LCD_PANEL_ID4_1280X1024; 261 LCD_PANEL_ID4_1280X1024;
301 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; 262 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
302 viaparinfo->lvds_setting_info->LCDDithering = 1; 263 viaparinfo->lvds_setting_info->LCDDithering = 1;
303 return VIA_RES_1280X1024;
304 break; 264 break;
305 case 0x5: 265 case 0x5:
306 viaparinfo->lvds_setting_info->lcd_panel_hres = 1400; 266 viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
@@ -309,7 +269,6 @@ static int fp_id_to_vindex(int panel_id)
309 LCD_PANEL_ID5_1400X1050; 269 LCD_PANEL_ID5_1400X1050;
310 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; 270 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
311 viaparinfo->lvds_setting_info->LCDDithering = 1; 271 viaparinfo->lvds_setting_info->LCDDithering = 1;
312 return VIA_RES_1400X1050;
313 break; 272 break;
314 case 0x6: 273 case 0x6:
315 viaparinfo->lvds_setting_info->lcd_panel_hres = 1600; 274 viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
@@ -318,7 +277,6 @@ static int fp_id_to_vindex(int panel_id)
318 LCD_PANEL_ID6_1600X1200; 277 LCD_PANEL_ID6_1600X1200;
319 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; 278 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
320 viaparinfo->lvds_setting_info->LCDDithering = 1; 279 viaparinfo->lvds_setting_info->LCDDithering = 1;
321 return VIA_RES_1600X1200;
322 break; 280 break;
323 case 0x8: 281 case 0x8:
324 viaparinfo->lvds_setting_info->lcd_panel_hres = 800; 282 viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
@@ -327,7 +285,6 @@ static int fp_id_to_vindex(int panel_id)
327 LCD_PANEL_IDA_800X480; 285 LCD_PANEL_IDA_800X480;
328 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 286 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
329 viaparinfo->lvds_setting_info->LCDDithering = 1; 287 viaparinfo->lvds_setting_info->LCDDithering = 1;
330 return VIA_RES_800X480;
331 break; 288 break;
332 case 0x9: 289 case 0x9:
333 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; 290 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
@@ -336,7 +293,6 @@ static int fp_id_to_vindex(int panel_id)
336 LCD_PANEL_ID2_1024X768; 293 LCD_PANEL_ID2_1024X768;
337 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; 294 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
338 viaparinfo->lvds_setting_info->LCDDithering = 1; 295 viaparinfo->lvds_setting_info->LCDDithering = 1;
339 return VIA_RES_1024X768;
340 break; 296 break;
341 case 0xA: 297 case 0xA:
342 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; 298 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
@@ -345,7 +301,6 @@ static int fp_id_to_vindex(int panel_id)
345 LCD_PANEL_ID2_1024X768; 301 LCD_PANEL_ID2_1024X768;
346 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 302 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
347 viaparinfo->lvds_setting_info->LCDDithering = 0; 303 viaparinfo->lvds_setting_info->LCDDithering = 0;
348 return VIA_RES_1024X768;
349 break; 304 break;
350 case 0xB: 305 case 0xB:
351 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; 306 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
@@ -354,7 +309,6 @@ static int fp_id_to_vindex(int panel_id)
354 LCD_PANEL_ID2_1024X768; 309 LCD_PANEL_ID2_1024X768;
355 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; 310 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
356 viaparinfo->lvds_setting_info->LCDDithering = 0; 311 viaparinfo->lvds_setting_info->LCDDithering = 0;
357 return VIA_RES_1024X768;
358 break; 312 break;
359 case 0xC: 313 case 0xC:
360 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; 314 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
@@ -363,7 +317,6 @@ static int fp_id_to_vindex(int panel_id)
363 LCD_PANEL_ID3_1280X768; 317 LCD_PANEL_ID3_1280X768;
364 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 318 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
365 viaparinfo->lvds_setting_info->LCDDithering = 0; 319 viaparinfo->lvds_setting_info->LCDDithering = 0;
366 return VIA_RES_1280X768;
367 break; 320 break;
368 case 0xD: 321 case 0xD:
369 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; 322 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
@@ -372,7 +325,6 @@ static int fp_id_to_vindex(int panel_id)
372 LCD_PANEL_ID4_1280X1024; 325 LCD_PANEL_ID4_1280X1024;
373 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; 326 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
374 viaparinfo->lvds_setting_info->LCDDithering = 0; 327 viaparinfo->lvds_setting_info->LCDDithering = 0;
375 return VIA_RES_1280X1024;
376 break; 328 break;
377 case 0xE: 329 case 0xE:
378 viaparinfo->lvds_setting_info->lcd_panel_hres = 1400; 330 viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
@@ -381,7 +333,6 @@ static int fp_id_to_vindex(int panel_id)
381 LCD_PANEL_ID5_1400X1050; 333 LCD_PANEL_ID5_1400X1050;
382 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; 334 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
383 viaparinfo->lvds_setting_info->LCDDithering = 0; 335 viaparinfo->lvds_setting_info->LCDDithering = 0;
384 return VIA_RES_1400X1050;
385 break; 336 break;
386 case 0xF: 337 case 0xF:
387 viaparinfo->lvds_setting_info->lcd_panel_hres = 1600; 338 viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
@@ -390,7 +341,6 @@ static int fp_id_to_vindex(int panel_id)
390 LCD_PANEL_ID6_1600X1200; 341 LCD_PANEL_ID6_1600X1200;
391 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; 342 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
392 viaparinfo->lvds_setting_info->LCDDithering = 0; 343 viaparinfo->lvds_setting_info->LCDDithering = 0;
393 return VIA_RES_1600X1200;
394 break; 344 break;
395 case 0x10: 345 case 0x10:
396 viaparinfo->lvds_setting_info->lcd_panel_hres = 1366; 346 viaparinfo->lvds_setting_info->lcd_panel_hres = 1366;
@@ -399,7 +349,6 @@ static int fp_id_to_vindex(int panel_id)
399 LCD_PANEL_ID7_1366X768; 349 LCD_PANEL_ID7_1366X768;
400 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 350 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
401 viaparinfo->lvds_setting_info->LCDDithering = 0; 351 viaparinfo->lvds_setting_info->LCDDithering = 0;
402 return VIA_RES_1368X768;
403 break; 352 break;
404 case 0x11: 353 case 0x11:
405 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; 354 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
@@ -408,7 +357,6 @@ static int fp_id_to_vindex(int panel_id)
408 LCD_PANEL_ID8_1024X600; 357 LCD_PANEL_ID8_1024X600;
409 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 358 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
410 viaparinfo->lvds_setting_info->LCDDithering = 1; 359 viaparinfo->lvds_setting_info->LCDDithering = 1;
411 return VIA_RES_1024X600;
412 break; 360 break;
413 case 0x12: 361 case 0x12:
414 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; 362 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
@@ -417,7 +365,6 @@ static int fp_id_to_vindex(int panel_id)
417 LCD_PANEL_ID3_1280X768; 365 LCD_PANEL_ID3_1280X768;
418 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; 366 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
419 viaparinfo->lvds_setting_info->LCDDithering = 1; 367 viaparinfo->lvds_setting_info->LCDDithering = 1;
420 return VIA_RES_1280X768;
421 break; 368 break;
422 case 0x13: 369 case 0x13:
423 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; 370 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
@@ -426,7 +373,6 @@ static int fp_id_to_vindex(int panel_id)
426 LCD_PANEL_ID9_1280X800; 373 LCD_PANEL_ID9_1280X800;
427 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 374 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
428 viaparinfo->lvds_setting_info->LCDDithering = 1; 375 viaparinfo->lvds_setting_info->LCDDithering = 1;
429 return VIA_RES_1280X800;
430 break; 376 break;
431 case 0x14: 377 case 0x14:
432 viaparinfo->lvds_setting_info->lcd_panel_hres = 1360; 378 viaparinfo->lvds_setting_info->lcd_panel_hres = 1360;
@@ -435,7 +381,6 @@ static int fp_id_to_vindex(int panel_id)
435 LCD_PANEL_IDB_1360X768; 381 LCD_PANEL_IDB_1360X768;
436 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 382 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
437 viaparinfo->lvds_setting_info->LCDDithering = 0; 383 viaparinfo->lvds_setting_info->LCDDithering = 0;
438 return VIA_RES_1360X768;
439 break; 384 break;
440 case 0x15: 385 case 0x15:
441 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; 386 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
@@ -444,7 +389,6 @@ static int fp_id_to_vindex(int panel_id)
444 LCD_PANEL_ID3_1280X768; 389 LCD_PANEL_ID3_1280X768;
445 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; 390 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
446 viaparinfo->lvds_setting_info->LCDDithering = 0; 391 viaparinfo->lvds_setting_info->LCDDithering = 0;
447 return VIA_RES_1280X768;
448 break; 392 break;
449 case 0x16: 393 case 0x16:
450 viaparinfo->lvds_setting_info->lcd_panel_hres = 480; 394 viaparinfo->lvds_setting_info->lcd_panel_hres = 480;
@@ -453,7 +397,6 @@ static int fp_id_to_vindex(int panel_id)
453 LCD_PANEL_IDC_480X640; 397 LCD_PANEL_IDC_480X640;
454 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 398 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
455 viaparinfo->lvds_setting_info->LCDDithering = 1; 399 viaparinfo->lvds_setting_info->LCDDithering = 1;
456 return VIA_RES_480X640;
457 break; 400 break;
458 default: 401 default:
459 viaparinfo->lvds_setting_info->lcd_panel_hres = 800; 402 viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
@@ -462,7 +405,6 @@ static int fp_id_to_vindex(int panel_id)
462 LCD_PANEL_ID1_800X600; 405 LCD_PANEL_ID1_800X600;
463 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; 406 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
464 viaparinfo->lvds_setting_info->LCDDithering = 1; 407 viaparinfo->lvds_setting_info->LCDDithering = 1;
465 return VIA_RES_800X600;
466 } 408 }
467} 409}
468 410
@@ -573,284 +515,6 @@ static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
573 } 515 }
574} 516}
575 517
576static void load_lcd_k400_patch_tbl(int set_hres, int set_vres,
577 int panel_id)
578{
579 int vmode_index;
580 int reg_num = 0;
581 struct io_reg *lcd_patch_reg = NULL;
582
583 vmode_index = viafb_get_mode_index(set_hres, set_vres);
584 switch (panel_id) {
585 /* LCD 800x600 */
586 case LCD_PANEL_ID1_800X600:
587 switch (vmode_index) {
588 case VIA_RES_640X400:
589 case VIA_RES_640X480:
590 reg_num = NUM_TOTAL_K400_LCD_RES_6X4_8X6;
591 lcd_patch_reg = K400_LCD_RES_6X4_8X6;
592 break;
593 case VIA_RES_720X480:
594 case VIA_RES_720X576:
595 reg_num = NUM_TOTAL_K400_LCD_RES_7X4_8X6;
596 lcd_patch_reg = K400_LCD_RES_7X4_8X6;
597 break;
598 }
599 break;
600
601 /* LCD 1024x768 */
602 case LCD_PANEL_ID2_1024X768:
603 switch (vmode_index) {
604 case VIA_RES_640X400:
605 case VIA_RES_640X480:
606 reg_num = NUM_TOTAL_K400_LCD_RES_6X4_10X7;
607 lcd_patch_reg = K400_LCD_RES_6X4_10X7;
608 break;
609 case VIA_RES_720X480:
610 case VIA_RES_720X576:
611 reg_num = NUM_TOTAL_K400_LCD_RES_7X4_10X7;
612 lcd_patch_reg = K400_LCD_RES_7X4_10X7;
613 break;
614 case VIA_RES_800X600:
615 reg_num = NUM_TOTAL_K400_LCD_RES_8X6_10X7;
616 lcd_patch_reg = K400_LCD_RES_8X6_10X7;
617 break;
618 }
619 break;
620
621 /* LCD 1280x1024 */
622 case LCD_PANEL_ID4_1280X1024:
623 switch (vmode_index) {
624 case VIA_RES_640X400:
625 case VIA_RES_640X480:
626 reg_num = NUM_TOTAL_K400_LCD_RES_6X4_12X10;
627 lcd_patch_reg = K400_LCD_RES_6X4_12X10;
628 break;
629 case VIA_RES_720X480:
630 case VIA_RES_720X576:
631 reg_num = NUM_TOTAL_K400_LCD_RES_7X4_12X10;
632 lcd_patch_reg = K400_LCD_RES_7X4_12X10;
633 break;
634 case VIA_RES_800X600:
635 reg_num = NUM_TOTAL_K400_LCD_RES_8X6_12X10;
636 lcd_patch_reg = K400_LCD_RES_8X6_12X10;
637 break;
638 case VIA_RES_1024X768:
639 reg_num = NUM_TOTAL_K400_LCD_RES_10X7_12X10;
640 lcd_patch_reg = K400_LCD_RES_10X7_12X10;
641 break;
642
643 }
644 break;
645
646 /* LCD 1400x1050 */
647 case LCD_PANEL_ID5_1400X1050:
648 switch (vmode_index) {
649 case VIA_RES_640X480:
650 reg_num = NUM_TOTAL_K400_LCD_RES_6X4_14X10;
651 lcd_patch_reg = K400_LCD_RES_6X4_14X10;
652 break;
653 case VIA_RES_800X600:
654 reg_num = NUM_TOTAL_K400_LCD_RES_8X6_14X10;
655 lcd_patch_reg = K400_LCD_RES_8X6_14X10;
656 break;
657 case VIA_RES_1024X768:
658 reg_num = NUM_TOTAL_K400_LCD_RES_10X7_14X10;
659 lcd_patch_reg = K400_LCD_RES_10X7_14X10;
660 break;
661 case VIA_RES_1280X768:
662 case VIA_RES_1280X800:
663 case VIA_RES_1280X960:
664 case VIA_RES_1280X1024:
665 reg_num = NUM_TOTAL_K400_LCD_RES_12X10_14X10;
666 lcd_patch_reg = K400_LCD_RES_12X10_14X10;
667 break;
668 }
669 break;
670
671 /* LCD 1600x1200 */
672 case LCD_PANEL_ID6_1600X1200:
673 switch (vmode_index) {
674 case VIA_RES_640X400:
675 case VIA_RES_640X480:
676 reg_num = NUM_TOTAL_K400_LCD_RES_6X4_16X12;
677 lcd_patch_reg = K400_LCD_RES_6X4_16X12;
678 break;
679 case VIA_RES_720X480:
680 case VIA_RES_720X576:
681 reg_num = NUM_TOTAL_K400_LCD_RES_7X4_16X12;
682 lcd_patch_reg = K400_LCD_RES_7X4_16X12;
683 break;
684 case VIA_RES_800X600:
685 reg_num = NUM_TOTAL_K400_LCD_RES_8X6_16X12;
686 lcd_patch_reg = K400_LCD_RES_8X6_16X12;
687 break;
688 case VIA_RES_1024X768:
689 reg_num = NUM_TOTAL_K400_LCD_RES_10X7_16X12;
690 lcd_patch_reg = K400_LCD_RES_10X7_16X12;
691 break;
692 case VIA_RES_1280X768:
693 case VIA_RES_1280X800:
694 case VIA_RES_1280X960:
695 case VIA_RES_1280X1024:
696 reg_num = NUM_TOTAL_K400_LCD_RES_12X10_16X12;
697 lcd_patch_reg = K400_LCD_RES_12X10_16X12;
698 break;
699 }
700 break;
701
702 /* LCD 1366x768 */
703 case LCD_PANEL_ID7_1366X768:
704 switch (vmode_index) {
705 case VIA_RES_640X480:
706 reg_num = NUM_TOTAL_K400_LCD_RES_6X4_1366X7;
707 lcd_patch_reg = K400_LCD_RES_6X4_1366X7;
708 break;
709 case VIA_RES_720X480:
710 case VIA_RES_720X576:
711 reg_num = NUM_TOTAL_K400_LCD_RES_7X4_1366X7;
712 lcd_patch_reg = K400_LCD_RES_7X4_1366X7;
713 break;
714 case VIA_RES_800X600:
715 reg_num = NUM_TOTAL_K400_LCD_RES_8X6_1366X7;
716 lcd_patch_reg = K400_LCD_RES_8X6_1366X7;
717 break;
718 case VIA_RES_1024X768:
719 reg_num = NUM_TOTAL_K400_LCD_RES_10X7_1366X7;
720 lcd_patch_reg = K400_LCD_RES_10X7_1366X7;
721 break;
722 case VIA_RES_1280X768:
723 case VIA_RES_1280X800:
724 case VIA_RES_1280X960:
725 case VIA_RES_1280X1024:
726 reg_num = NUM_TOTAL_K400_LCD_RES_12X10_1366X7;
727 lcd_patch_reg = K400_LCD_RES_12X10_1366X7;
728 break;
729 }
730 break;
731
732 /* LCD 1360x768 */
733 case LCD_PANEL_IDB_1360X768:
734 break;
735 }
736 if (reg_num != 0) {
737 /* H.W. Reset : ON */
738 viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
739
740 viafb_write_regx(lcd_patch_reg, reg_num);
741
742 /* H.W. Reset : OFF */
743 viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
744
745 /* Reset PLL */
746 viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1);
747 viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1);
748
749 /* Fire! */
750 outb(inb(VIARMisc) | (BIT2 + BIT3), VIAWMisc);
751 }
752}
753
754static void load_lcd_p880_patch_tbl(int set_hres, int set_vres,
755 int panel_id)
756{
757 int vmode_index;
758 int reg_num = 0;
759 struct io_reg *lcd_patch_reg = NULL;
760
761 vmode_index = viafb_get_mode_index(set_hres, set_vres);
762
763 switch (panel_id) {
764 case LCD_PANEL_ID5_1400X1050:
765 switch (vmode_index) {
766 case VIA_RES_640X480:
767 reg_num = NUM_TOTAL_P880_LCD_RES_6X4_14X10;
768 lcd_patch_reg = P880_LCD_RES_6X4_14X10;
769 break;
770 case VIA_RES_800X600:
771 reg_num = NUM_TOTAL_P880_LCD_RES_8X6_14X10;
772 lcd_patch_reg = P880_LCD_RES_8X6_14X10;
773 break;
774 }
775 break;
776 case LCD_PANEL_ID6_1600X1200:
777 switch (vmode_index) {
778 case VIA_RES_640X400:
779 case VIA_RES_640X480:
780 reg_num = NUM_TOTAL_P880_LCD_RES_6X4_16X12;
781 lcd_patch_reg = P880_LCD_RES_6X4_16X12;
782 break;
783 case VIA_RES_720X480:
784 case VIA_RES_720X576:
785 reg_num = NUM_TOTAL_P880_LCD_RES_7X4_16X12;
786 lcd_patch_reg = P880_LCD_RES_7X4_16X12;
787 break;
788 case VIA_RES_800X600:
789 reg_num = NUM_TOTAL_P880_LCD_RES_8X6_16X12;
790 lcd_patch_reg = P880_LCD_RES_8X6_16X12;
791 break;
792 case VIA_RES_1024X768:
793 reg_num = NUM_TOTAL_P880_LCD_RES_10X7_16X12;
794 lcd_patch_reg = P880_LCD_RES_10X7_16X12;
795 break;
796 case VIA_RES_1280X768:
797 case VIA_RES_1280X960:
798 case VIA_RES_1280X1024:
799 reg_num = NUM_TOTAL_P880_LCD_RES_12X10_16X12;
800 lcd_patch_reg = P880_LCD_RES_12X10_16X12;
801 break;
802 }
803 break;
804
805 }
806 if (reg_num != 0) {
807 /* H.W. Reset : ON */
808 viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
809
810 viafb_write_regx(lcd_patch_reg, reg_num);
811
812 /* H.W. Reset : OFF */
813 viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
814
815 /* Reset PLL */
816 viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1);
817 viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1);
818
819 /* Fire! */
820 outb(inb(VIARMisc) | (BIT2 + BIT3), VIAWMisc);
821 }
822}
823
824static void load_lcd_patch_regs(int set_hres, int set_vres,
825 int panel_id, int set_iga)
826{
827 int vmode_index;
828
829 vmode_index = viafb_get_mode_index(set_hres, set_vres);
830
831 viafb_unlock_crt();
832
833 /* Patch for simultaneous & Expansion */
834 if ((set_iga == IGA1_IGA2) &&
835 (viaparinfo->lvds_setting_info->display_method ==
836 LCD_EXPANDSION)) {
837 switch (viaparinfo->chip_info->gfx_chip_name) {
838 case UNICHROME_CLE266:
839 case UNICHROME_K400:
840 load_lcd_k400_patch_tbl(set_hres, set_vres, panel_id);
841 break;
842 case UNICHROME_K800:
843 break;
844 case UNICHROME_PM800:
845 case UNICHROME_CN700:
846 case UNICHROME_CX700:
847 load_lcd_p880_patch_tbl(set_hres, set_vres, panel_id);
848 }
849 }
850
851 viafb_lock_crt();
852}
853
854static void via_pitch_alignment_patch_lcd( 518static void via_pitch_alignment_patch_lcd(
855 struct lvds_setting_information *plvds_setting_info, 519 struct lvds_setting_information *plvds_setting_info,
856 struct lvds_chip_information 520 struct lvds_chip_information
@@ -949,29 +613,25 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
949 struct lvds_setting_information *plvds_setting_info, 613 struct lvds_setting_information *plvds_setting_info,
950 struct lvds_chip_information *plvds_chip_info) 614 struct lvds_chip_information *plvds_chip_info)
951{ 615{
952 int video_index = plvds_setting_info->lcd_panel_size;
953 int set_iga = plvds_setting_info->iga_path; 616 int set_iga = plvds_setting_info->iga_path;
954 int mode_bpp = plvds_setting_info->bpp; 617 int mode_bpp = plvds_setting_info->bpp;
955 int set_hres, set_vres; 618 int set_hres = plvds_setting_info->h_active;
956 int panel_hres, panel_vres; 619 int set_vres = plvds_setting_info->v_active;
620 int panel_hres = plvds_setting_info->lcd_panel_hres;
621 int panel_vres = plvds_setting_info->lcd_panel_vres;
957 u32 pll_D_N; 622 u32 pll_D_N;
958 int offset;
959 struct display_timing mode_crt_reg, panel_crt_reg; 623 struct display_timing mode_crt_reg, panel_crt_reg;
960 struct crt_mode_table *panel_crt_table = NULL; 624 struct crt_mode_table *panel_crt_table = NULL;
961 struct VideoModeTable *vmode_tbl = NULL; 625 struct VideoModeTable *vmode_tbl = viafb_get_mode(panel_hres,
626 panel_vres);
962 627
963 DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n"); 628 DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n");
964 /* Get mode table */ 629 /* Get mode table */
965 mode_crt_reg = mode_crt_table->crtc; 630 mode_crt_reg = mode_crt_table->crtc;
966 /* Get panel table Pointer */ 631 /* Get panel table Pointer */
967 vmode_tbl = viafb_get_modetbl_pointer(video_index);
968 panel_crt_table = vmode_tbl->crtc; 632 panel_crt_table = vmode_tbl->crtc;
969 panel_crt_reg = panel_crt_table->crtc; 633 panel_crt_reg = panel_crt_table->crtc;
970 DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n"); 634 DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n");
971 set_hres = plvds_setting_info->h_active;
972 set_vres = plvds_setting_info->v_active;
973 panel_hres = plvds_setting_info->lcd_panel_hres;
974 panel_vres = plvds_setting_info->lcd_panel_vres;
975 if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) 635 if (VT1636_LVDS == plvds_chip_info->lvds_chip_name)
976 viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info); 636 viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info);
977 plvds_setting_info->vclk = panel_crt_table->clk; 637 plvds_setting_info->vclk = panel_crt_table->clk;
@@ -1001,54 +661,12 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
1001 } 661 }
1002 } 662 }
1003 663
1004 if (set_iga == IGA1_IGA2) { 664 /* Fetch count for IGA2 only */
1005 load_crtc_shadow_timing(mode_crt_reg, panel_crt_reg); 665 viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga);
1006 /* Fill shadow registers */
1007
1008 switch (plvds_setting_info->lcd_panel_id) {
1009 case LCD_PANEL_ID0_640X480:
1010 offset = 80;
1011 break;
1012 case LCD_PANEL_ID1_800X600:
1013 case LCD_PANEL_IDA_800X480:
1014 offset = 110;
1015 break;
1016 case LCD_PANEL_ID2_1024X768:
1017 offset = 150;
1018 break;
1019 case LCD_PANEL_ID3_1280X768:
1020 case LCD_PANEL_ID4_1280X1024:
1021 case LCD_PANEL_ID5_1400X1050:
1022 case LCD_PANEL_ID9_1280X800:
1023 offset = 190;
1024 break;
1025 case LCD_PANEL_ID6_1600X1200:
1026 offset = 250;
1027 break;
1028 case LCD_PANEL_ID7_1366X768:
1029 case LCD_PANEL_IDB_1360X768:
1030 offset = 212;
1031 break;
1032 default:
1033 offset = 140;
1034 break;
1035 }
1036
1037 /* Offset for simultaneous */
1038 viafb_set_secondary_pitch(offset << 3);
1039 DEBUG_MSG(KERN_INFO "viafb_load_reg!!\n");
1040 viafb_load_fetch_count_reg(set_hres, 4, IGA2);
1041 /* Fetch count for simultaneous */
1042 } else { /* SAMM */
1043 /* Fetch count for IGA2 only */
1044 viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga);
1045
1046 if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
1047 && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
1048 viafb_load_FIFO_reg(set_iga, set_hres, set_vres);
1049 666
1050 viafb_set_color_depth(mode_bpp / 8, set_iga); 667 if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
1051 } 668 && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
669 viafb_load_FIFO_reg(set_iga, set_hres, set_vres);
1052 670
1053 fill_lcd_format(); 671 fill_lcd_format();
1054 672
@@ -1065,11 +683,6 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
1065 || (UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name)) 683 || (UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name))
1066 viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0); 684 viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0);
1067 685
1068 load_lcd_patch_regs(set_hres, set_vres,
1069 plvds_setting_info->lcd_panel_id, set_iga);
1070
1071 DEBUG_MSG(KERN_INFO "load_lcd_patch_regs!!\n");
1072
1073 /* Patch for non 32bit alignment mode */ 686 /* Patch for non 32bit alignment mode */
1074 via_pitch_alignment_patch_lcd(plvds_setting_info, plvds_chip_info); 687 via_pitch_alignment_patch_lcd(plvds_setting_info, plvds_chip_info);
1075} 688}
@@ -1134,45 +747,33 @@ static void integrated_lvds_enable(struct lvds_setting_information
1134 *plvds_setting_info, 747 *plvds_setting_info,
1135 struct lvds_chip_information *plvds_chip_info) 748 struct lvds_chip_information *plvds_chip_info)
1136{ 749{
1137 bool turn_on_first_powersequence = false;
1138 bool turn_on_second_powersequence = false;
1139
1140 DEBUG_MSG(KERN_INFO "integrated_lvds_enable, out_interface:%d\n", 750 DEBUG_MSG(KERN_INFO "integrated_lvds_enable, out_interface:%d\n",
1141 plvds_chip_info->output_interface); 751 plvds_chip_info->output_interface);
1142 if (plvds_setting_info->lcd_mode == LCD_SPWG) 752 if (plvds_setting_info->lcd_mode == LCD_SPWG)
1143 viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT0 + BIT1); 753 viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT0 + BIT1);
1144 else 754 else
1145 viafb_write_reg_mask(CRD2, VIACR, 0x03, BIT0 + BIT1); 755 viafb_write_reg_mask(CRD2, VIACR, 0x03, BIT0 + BIT1);
1146 if (INTERFACE_LVDS0LVDS1 == plvds_chip_info->output_interface)
1147 turn_on_first_powersequence = true;
1148 if (INTERFACE_LVDS0 == plvds_chip_info->output_interface)
1149 turn_on_first_powersequence = true;
1150 if (INTERFACE_LVDS1 == plvds_chip_info->output_interface)
1151 turn_on_second_powersequence = true;
1152
1153 if (turn_on_second_powersequence) {
1154 /* Use second power sequence control: */
1155 756
1156 /* Use hardware control power sequence. */ 757 switch (plvds_chip_info->output_interface) {
1157 viafb_write_reg_mask(CRD3, VIACR, 0, BIT0); 758 case INTERFACE_LVDS0LVDS1:
1158 759 case INTERFACE_LVDS0:
1159 /* Turn on back light. */
1160 viafb_write_reg_mask(CRD3, VIACR, 0, BIT6 + BIT7);
1161
1162 /* Turn on hardware power sequence. */
1163 viafb_write_reg_mask(CRD4, VIACR, 0x02, BIT1);
1164 }
1165 if (turn_on_first_powersequence) {
1166 /* Use first power sequence control: */ 760 /* Use first power sequence control: */
1167
1168 /* Use hardware control power sequence. */ 761 /* Use hardware control power sequence. */
1169 viafb_write_reg_mask(CR91, VIACR, 0, BIT0); 762 viafb_write_reg_mask(CR91, VIACR, 0, BIT0);
1170
1171 /* Turn on back light. */ 763 /* Turn on back light. */
1172 viafb_write_reg_mask(CR91, VIACR, 0, BIT6 + BIT7); 764 viafb_write_reg_mask(CR91, VIACR, 0, BIT6 + BIT7);
1173
1174 /* Turn on hardware power sequence. */ 765 /* Turn on hardware power sequence. */
1175 viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3); 766 viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
767 break;
768 case INTERFACE_LVDS1:
769 /* Use second power sequence control: */
770 /* Use hardware control power sequence. */
771 viafb_write_reg_mask(CRD3, VIACR, 0, BIT0);
772 /* Turn on back light. */
773 viafb_write_reg_mask(CRD3, VIACR, 0, BIT6 + BIT7);
774 /* Turn on hardware power sequence. */
775 viafb_write_reg_mask(CRD4, VIACR, 0x02, BIT1);
776 break;
1176 } 777 }
1177 778
1178 /* Turn DFP High/Low pad on. */ 779 /* Turn DFP High/Low pad on. */
@@ -1295,8 +896,7 @@ void viafb_lcd_enable(void)
1295 viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48); 896 viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48);
1296 } 897 }
1297 898
1298 if ((viaparinfo->lvds_setting_info->iga_path == IGA1) 899 if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
1299 || (viaparinfo->lvds_setting_info->iga_path == IGA1_IGA2)) {
1300 /* CRT path set to IGA2 */ 900 /* CRT path set to IGA2 */
1301 viafb_write_reg_mask(SR16, VIASR, 0x40, 0x40); 901 viafb_write_reg_mask(SR16, VIASR, 0x40, 0x40);
1302 /* IGA2 path disabled */ 902 /* IGA2 path disabled */
@@ -1488,210 +1088,6 @@ static struct display_timing lcd_centering_timging(struct display_timing
1488 return crt_reg; 1088 return crt_reg;
1489} 1089}
1490 1090
1491static void load_crtc_shadow_timing(struct display_timing mode_timing,
1492 struct display_timing panel_timing)
1493{
1494 struct io_register *reg = NULL;
1495 int i;
1496 int viafb_load_reg_Num = 0;
1497 int reg_value = 0;
1498
1499 if (viaparinfo->lvds_setting_info->display_method == LCD_EXPANDSION) {
1500 /* Expansion */
1501 for (i = 12; i < 20; i++) {
1502 switch (i) {
1503 case H_TOTAL_SHADOW_INDEX:
1504 reg_value =
1505 IGA2_HOR_TOTAL_SHADOW_FORMULA
1506 (panel_timing.hor_total);
1507 viafb_load_reg_Num =
1508 iga2_shadow_crtc_reg.hor_total_shadow.
1509 reg_num;
1510 reg = iga2_shadow_crtc_reg.hor_total_shadow.reg;
1511 break;
1512 case H_BLANK_END_SHADOW_INDEX:
1513 reg_value =
1514 IGA2_HOR_BLANK_END_SHADOW_FORMULA
1515 (panel_timing.hor_blank_start,
1516 panel_timing.hor_blank_end);
1517 viafb_load_reg_Num =
1518 iga2_shadow_crtc_reg.
1519 hor_blank_end_shadow.reg_num;
1520 reg =
1521 iga2_shadow_crtc_reg.
1522 hor_blank_end_shadow.reg;
1523 break;
1524 case V_TOTAL_SHADOW_INDEX:
1525 reg_value =
1526 IGA2_VER_TOTAL_SHADOW_FORMULA
1527 (panel_timing.ver_total);
1528 viafb_load_reg_Num =
1529 iga2_shadow_crtc_reg.ver_total_shadow.
1530 reg_num;
1531 reg = iga2_shadow_crtc_reg.ver_total_shadow.reg;
1532 break;
1533 case V_ADDR_SHADOW_INDEX:
1534 reg_value =
1535 IGA2_VER_ADDR_SHADOW_FORMULA
1536 (panel_timing.ver_addr);
1537 viafb_load_reg_Num =
1538 iga2_shadow_crtc_reg.ver_addr_shadow.
1539 reg_num;
1540 reg = iga2_shadow_crtc_reg.ver_addr_shadow.reg;
1541 break;
1542 case V_BLANK_SATRT_SHADOW_INDEX:
1543 reg_value =
1544 IGA2_VER_BLANK_START_SHADOW_FORMULA
1545 (panel_timing.ver_blank_start);
1546 viafb_load_reg_Num =
1547 iga2_shadow_crtc_reg.
1548 ver_blank_start_shadow.reg_num;
1549 reg =
1550 iga2_shadow_crtc_reg.
1551 ver_blank_start_shadow.reg;
1552 break;
1553 case V_BLANK_END_SHADOW_INDEX:
1554 reg_value =
1555 IGA2_VER_BLANK_END_SHADOW_FORMULA
1556 (panel_timing.ver_blank_start,
1557 panel_timing.ver_blank_end);
1558 viafb_load_reg_Num =
1559 iga2_shadow_crtc_reg.
1560 ver_blank_end_shadow.reg_num;
1561 reg =
1562 iga2_shadow_crtc_reg.
1563 ver_blank_end_shadow.reg;
1564 break;
1565 case V_SYNC_SATRT_SHADOW_INDEX:
1566 reg_value =
1567 IGA2_VER_SYNC_START_SHADOW_FORMULA
1568 (panel_timing.ver_sync_start);
1569 viafb_load_reg_Num =
1570 iga2_shadow_crtc_reg.
1571 ver_sync_start_shadow.reg_num;
1572 reg =
1573 iga2_shadow_crtc_reg.
1574 ver_sync_start_shadow.reg;
1575 break;
1576 case V_SYNC_END_SHADOW_INDEX:
1577 reg_value =
1578 IGA2_VER_SYNC_END_SHADOW_FORMULA
1579 (panel_timing.ver_sync_start,
1580 panel_timing.ver_sync_end);
1581 viafb_load_reg_Num =
1582 iga2_shadow_crtc_reg.
1583 ver_sync_end_shadow.reg_num;
1584 reg =
1585 iga2_shadow_crtc_reg.
1586 ver_sync_end_shadow.reg;
1587 break;
1588 }
1589 viafb_load_reg(reg_value,
1590 viafb_load_reg_Num, reg, VIACR);
1591 }
1592 } else { /* Centering */
1593 for (i = 12; i < 20; i++) {
1594 switch (i) {
1595 case H_TOTAL_SHADOW_INDEX:
1596 reg_value =
1597 IGA2_HOR_TOTAL_SHADOW_FORMULA
1598 (panel_timing.hor_total);
1599 viafb_load_reg_Num =
1600 iga2_shadow_crtc_reg.hor_total_shadow.
1601 reg_num;
1602 reg = iga2_shadow_crtc_reg.hor_total_shadow.reg;
1603 break;
1604 case H_BLANK_END_SHADOW_INDEX:
1605 reg_value =
1606 IGA2_HOR_BLANK_END_SHADOW_FORMULA
1607 (panel_timing.hor_blank_start,
1608 panel_timing.hor_blank_end);
1609 viafb_load_reg_Num =
1610 iga2_shadow_crtc_reg.
1611 hor_blank_end_shadow.reg_num;
1612 reg =
1613 iga2_shadow_crtc_reg.
1614 hor_blank_end_shadow.reg;
1615 break;
1616 case V_TOTAL_SHADOW_INDEX:
1617 reg_value =
1618 IGA2_VER_TOTAL_SHADOW_FORMULA
1619 (panel_timing.ver_total);
1620 viafb_load_reg_Num =
1621 iga2_shadow_crtc_reg.ver_total_shadow.
1622 reg_num;
1623 reg = iga2_shadow_crtc_reg.ver_total_shadow.reg;
1624 break;
1625 case V_ADDR_SHADOW_INDEX:
1626 reg_value =
1627 IGA2_VER_ADDR_SHADOW_FORMULA
1628 (mode_timing.ver_addr);
1629 viafb_load_reg_Num =
1630 iga2_shadow_crtc_reg.ver_addr_shadow.
1631 reg_num;
1632 reg = iga2_shadow_crtc_reg.ver_addr_shadow.reg;
1633 break;
1634 case V_BLANK_SATRT_SHADOW_INDEX:
1635 reg_value =
1636 IGA2_VER_BLANK_START_SHADOW_FORMULA
1637 (mode_timing.ver_blank_start);
1638 viafb_load_reg_Num =
1639 iga2_shadow_crtc_reg.
1640 ver_blank_start_shadow.reg_num;
1641 reg =
1642 iga2_shadow_crtc_reg.
1643 ver_blank_start_shadow.reg;
1644 break;
1645 case V_BLANK_END_SHADOW_INDEX:
1646 reg_value =
1647 IGA2_VER_BLANK_END_SHADOW_FORMULA
1648 (panel_timing.ver_blank_start,
1649 panel_timing.ver_blank_end);
1650 viafb_load_reg_Num =
1651 iga2_shadow_crtc_reg.
1652 ver_blank_end_shadow.reg_num;
1653 reg =
1654 iga2_shadow_crtc_reg.
1655 ver_blank_end_shadow.reg;
1656 break;
1657 case V_SYNC_SATRT_SHADOW_INDEX:
1658 reg_value =
1659 IGA2_VER_SYNC_START_SHADOW_FORMULA(
1660 (panel_timing.ver_sync_start -
1661 panel_timing.ver_blank_start) +
1662 (panel_timing.ver_addr -
1663 mode_timing.ver_addr) / 2 +
1664 mode_timing.ver_addr);
1665 viafb_load_reg_Num =
1666 iga2_shadow_crtc_reg.ver_sync_start_shadow.
1667 reg_num;
1668 reg =
1669 iga2_shadow_crtc_reg.ver_sync_start_shadow.
1670 reg;
1671 break;
1672 case V_SYNC_END_SHADOW_INDEX:
1673 reg_value =
1674 IGA2_VER_SYNC_END_SHADOW_FORMULA(
1675 (panel_timing.ver_sync_start -
1676 panel_timing.ver_blank_start) +
1677 (panel_timing.ver_addr -
1678 mode_timing.ver_addr) / 2 +
1679 mode_timing.ver_addr,
1680 panel_timing.ver_sync_end);
1681 viafb_load_reg_Num =
1682 iga2_shadow_crtc_reg.ver_sync_end_shadow.
1683 reg_num;
1684 reg =
1685 iga2_shadow_crtc_reg.ver_sync_end_shadow.
1686 reg;
1687 break;
1688 }
1689 viafb_load_reg(reg_value,
1690 viafb_load_reg_Num, reg, VIACR);
1691 }
1692 }
1693}
1694
1695bool viafb_lcd_get_mobile_state(bool *mobile) 1091bool viafb_lcd_get_mobile_state(bool *mobile)
1696{ 1092{
1697 unsigned char *romptr, *tableptr; 1093 unsigned char *romptr, *tableptr;
diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h
index 7cd03e2a1275..d55aaa7b912c 100644
--- a/drivers/video/via/share.h
+++ b/drivers/video/via/share.h
@@ -43,61 +43,6 @@
43/* Video Memory Size */ 43/* Video Memory Size */
44#define VIDEO_MEMORY_SIZE_16M 0x1000000 44#define VIDEO_MEMORY_SIZE_16M 0x1000000
45 45
46/* Definition Mode Index
47*/
48#define VIA_RES_640X480 0
49#define VIA_RES_800X600 1
50#define VIA_RES_1024X768 2
51#define VIA_RES_1152X864 3
52#define VIA_RES_1280X1024 4
53#define VIA_RES_1600X1200 5
54#define VIA_RES_1440X1050 6
55#define VIA_RES_1280X768 7
56#define VIA_RES_1280X960 8
57#define VIA_RES_1920X1440 9
58#define VIA_RES_848X480 10
59#define VIA_RES_1400X1050 11
60#define VIA_RES_720X480 12
61#define VIA_RES_720X576 13
62#define VIA_RES_1024X512 14
63#define VIA_RES_856X480 15
64#define VIA_RES_1024X576 16
65#define VIA_RES_640X400 17
66#define VIA_RES_1280X720 18
67#define VIA_RES_1920X1080 19
68#define VIA_RES_800X480 20
69#define VIA_RES_1368X768 21
70#define VIA_RES_1024X600 22
71#define VIA_RES_1280X800 23
72#define VIA_RES_1680X1050 24
73#define VIA_RES_960X600 25
74#define VIA_RES_1000X600 26
75#define VIA_RES_1088X612 27
76#define VIA_RES_1152X720 28
77#define VIA_RES_1200X720 29
78#define VIA_RES_1280X600 30
79#define VIA_RES_1360X768 31
80#define VIA_RES_1366X768 32
81#define VIA_RES_1440X900 33
82#define VIA_RES_1600X900 34
83#define VIA_RES_1600X1024 35
84#define VIA_RES_1792X1344 36
85#define VIA_RES_1856X1392 37
86#define VIA_RES_1920X1200 38
87#define VIA_RES_2048X1536 39
88#define VIA_RES_480X640 40
89
90/*Reduce Blanking*/
91#define VIA_RES_1360X768_RB 131
92#define VIA_RES_1440X900_RB 133
93#define VIA_RES_1400X1050_RB 111
94#define VIA_RES_1600X900_RB 134
95#define VIA_RES_1680X1050_RB 124
96#define VIA_RES_1920X1080_RB 119
97#define VIA_RES_1920X1200_RB 138
98
99#define VIA_RES_INVALID 255
100
101/* standard VGA IO port 46/* standard VGA IO port
102*/ 47*/
103#define VIARMisc 0x3CC 48#define VIARMisc 0x3CC
@@ -118,7 +63,6 @@
118/* Display path */ 63/* Display path */
119#define IGA1 1 64#define IGA1 1
120#define IGA2 2 65#define IGA2 2
121#define IGA1_IGA2 3
122 66
123/* Define Color Depth */ 67/* Define Color Depth */
124#define MODE_8BPP 1 68#define MODE_8BPP 1
diff --git a/drivers/video/via/via_utility.c b/drivers/video/via/via_utility.c
index d53c3d54ed8e..aefdeeec89b1 100644
--- a/drivers/video/via/via_utility.c
+++ b/drivers/video/via/via_utility.c
@@ -239,15 +239,3 @@ void viafb_get_gamma_support_state(int bpp, unsigned int *support_state)
239 else 239 else
240 *support_state = CRT_Device | DVI_Device | LCD_Device; 240 *support_state = CRT_Device | DVI_Device | LCD_Device;
241} 241}
242
243int viafb_input_parameter_converter(int parameter_value)
244{
245 int result;
246
247 if (parameter_value >= 1 && parameter_value <= 9)
248 result = 1 << (parameter_value - 1);
249 else
250 result = 1;
251
252 return result;
253}
diff --git a/drivers/video/via/via_utility.h b/drivers/video/via/via_utility.h
index 2fd455202ebd..1670ba82143f 100644
--- a/drivers/video/via/via_utility.h
+++ b/drivers/video/via/via_utility.h
@@ -30,6 +30,5 @@ bool viafb_lcd_get_support_expand_state(u32 xres, u32 yres);
30void viafb_set_gamma_table(int bpp, unsigned int *gamma_table); 30void viafb_set_gamma_table(int bpp, unsigned int *gamma_table);
31void viafb_get_gamma_table(unsigned int *gamma_table); 31void viafb_get_gamma_table(unsigned int *gamma_table);
32void viafb_get_gamma_support_state(int bpp, unsigned int *support_state); 32void viafb_get_gamma_support_state(int bpp, unsigned int *support_state);
33int viafb_input_parameter_converter(int parameter_value);
34 33
35#endif /* __VIAUTILITY_H__ */ 34#endif /* __VIAUTILITY_H__ */
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index 56ec696e8afa..777b38a06d40 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -21,23 +21,28 @@
21 21
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/seq_file.h> 23#include <linux/seq_file.h>
24#include <linux/slab.h>
24#include <linux/stat.h> 25#include <linux/stat.h>
25#define _MASTER_FILE 26#define _MASTER_FILE
26 27
27#include "global.h" 28#include "global.h"
28 29
29static struct fb_var_screeninfo default_var;
30static char *viafb_name = "Via"; 30static char *viafb_name = "Via";
31static u32 pseudo_pal[17]; 31static u32 pseudo_pal[17];
32 32
33/* video mode */ 33/* video mode */
34static char *viafb_mode = "640x480"; 34static char *viafb_mode;
35static char *viafb_mode1 = "640x480"; 35static char *viafb_mode1;
36static int viafb_bpp = 32;
37static int viafb_bpp1 = 32;
38
39static unsigned int viafb_second_offset;
40static int viafb_second_size;
36 41
37static int viafb_accel = 1; 42static int viafb_accel = 1;
38 43
39/* Added for specifying active devices.*/ 44/* Added for specifying active devices.*/
40char *viafb_active_dev = ""; 45char *viafb_active_dev;
41 46
42/*Added for specify lcd output port*/ 47/*Added for specify lcd output port*/
43char *viafb_lcd_port = ""; 48char *viafb_lcd_port = "";
@@ -50,18 +55,78 @@ static void apply_second_mode_setting(struct fb_var_screeninfo
50 *sec_var); 55 *sec_var);
51static void retrieve_device_setting(struct viafb_ioctl_setting 56static void retrieve_device_setting(struct viafb_ioctl_setting
52 *setting_info); 57 *setting_info);
58static int viafb_pan_display(struct fb_var_screeninfo *var,
59 struct fb_info *info);
53 60
54static struct fb_ops viafb_ops; 61static struct fb_ops viafb_ops;
55 62
56 63
64static void viafb_fill_var_color_info(struct fb_var_screeninfo *var, u8 depth)
65{
66 var->grayscale = 0;
67 var->red.msb_right = 0;
68 var->green.msb_right = 0;
69 var->blue.msb_right = 0;
70 var->transp.offset = 0;
71 var->transp.length = 0;
72 var->transp.msb_right = 0;
73 var->nonstd = 0;
74 switch (depth) {
75 case 8:
76 var->bits_per_pixel = 8;
77 var->red.offset = 0;
78 var->green.offset = 0;
79 var->blue.offset = 0;
80 var->red.length = 8;
81 var->green.length = 8;
82 var->blue.length = 8;
83 break;
84 case 15:
85 var->bits_per_pixel = 16;
86 var->red.offset = 10;
87 var->green.offset = 5;
88 var->blue.offset = 0;
89 var->red.length = 5;
90 var->green.length = 5;
91 var->blue.length = 5;
92 break;
93 case 16:
94 var->bits_per_pixel = 16;
95 var->red.offset = 11;
96 var->green.offset = 5;
97 var->blue.offset = 0;
98 var->red.length = 5;
99 var->green.length = 6;
100 var->blue.length = 5;
101 break;
102 case 24:
103 var->bits_per_pixel = 32;
104 var->red.offset = 16;
105 var->green.offset = 8;
106 var->blue.offset = 0;
107 var->red.length = 8;
108 var->green.length = 8;
109 var->blue.length = 8;
110 break;
111 case 30:
112 var->bits_per_pixel = 32;
113 var->red.offset = 20;
114 var->green.offset = 10;
115 var->blue.offset = 0;
116 var->red.length = 10;
117 var->green.length = 10;
118 var->blue.length = 10;
119 break;
120 }
121}
122
57static void viafb_update_fix(struct fb_info *info) 123static void viafb_update_fix(struct fb_info *info)
58{ 124{
59 u32 bpp = info->var.bits_per_pixel; 125 u32 bpp = info->var.bits_per_pixel;
60 126
61 info->fix.visual = 127 info->fix.visual =
62 bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; 128 bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
63 info->fix.line_length = 129 info->fix.line_length = (info->var.xres_virtual * bpp / 8 + 7) & ~7;
64 ((info->var.xres_virtual + 7) & ~7) * bpp / 8;
65} 130}
66 131
67static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, 132static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix,
@@ -75,6 +140,7 @@ static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix,
75 140
76 fix->type = FB_TYPE_PACKED_PIXELS; 141 fix->type = FB_TYPE_PACKED_PIXELS;
77 fix->type_aux = 0; 142 fix->type_aux = 0;
143 fix->visual = FB_VISUAL_TRUECOLOR;
78 144
79 fix->xpanstep = fix->ywrapstep = 0; 145 fix->xpanstep = fix->ywrapstep = 0;
80 fix->ypanstep = 1; 146 fix->ypanstep = 1;
@@ -97,9 +163,10 @@ static int viafb_release(struct fb_info *info, int user)
97static int viafb_check_var(struct fb_var_screeninfo *var, 163static int viafb_check_var(struct fb_var_screeninfo *var,
98 struct fb_info *info) 164 struct fb_info *info)
99{ 165{
100 int vmode_index, htotal, vtotal; 166 int htotal, vtotal, depth;
167 struct VideoModeTable *vmode_entry;
101 struct viafb_par *ppar = info->par; 168 struct viafb_par *ppar = info->par;
102 u32 long_refresh; 169 u32 long_refresh, line;
103 170
104 DEBUG_MSG(KERN_INFO "viafb_check_var!\n"); 171 DEBUG_MSG(KERN_INFO "viafb_check_var!\n");
105 /* Sanity check */ 172 /* Sanity check */
@@ -107,26 +174,36 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
107 if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE) 174 if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE)
108 return -EINVAL; 175 return -EINVAL;
109 176
110 vmode_index = viafb_get_mode_index(var->xres, var->yres); 177 vmode_entry = viafb_get_mode(var->xres, var->yres);
111 if (vmode_index == VIA_RES_INVALID) { 178 if (!vmode_entry) {
112 DEBUG_MSG(KERN_INFO 179 DEBUG_MSG(KERN_INFO
113 "viafb: Mode %dx%dx%d not supported!!\n", 180 "viafb: Mode %dx%dx%d not supported!!\n",
114 var->xres, var->yres, var->bits_per_pixel); 181 var->xres, var->yres, var->bits_per_pixel);
115 return -EINVAL; 182 return -EINVAL;
116 } 183 }
117 184
118 if (24 == var->bits_per_pixel) 185 depth = fb_get_color_depth(var, &info->fix);
119 var->bits_per_pixel = 32; 186 if (!depth)
187 depth = var->bits_per_pixel;
120 188
121 if (var->bits_per_pixel != 8 && var->bits_per_pixel != 16 && 189 if (depth < 0 || depth > 32)
122 var->bits_per_pixel != 32)
123 return -EINVAL; 190 return -EINVAL;
191 else if (!depth)
192 depth = 24;
193 else if (depth == 15 && viafb_dual_fb && ppar->iga_path == IGA1)
194 depth = 15;
195 else if (depth == 30)
196 depth = 30;
197 else if (depth <= 8)
198 depth = 8;
199 else if (depth <= 16)
200 depth = 16;
201 else
202 depth = 24;
124 203
125 if ((var->xres_virtual * (var->bits_per_pixel >> 3)) & 0x1F) 204 viafb_fill_var_color_info(var, depth);
126 /*32 pixel alignment */ 205 line = (var->xres_virtual * var->bits_per_pixel / 8 + 7) & ~7;
127 var->xres_virtual = (var->xres_virtual + 31) & ~31; 206 if (line * var->yres_virtual > ppar->memsize)
128 if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 >
129 ppar->memsize)
130 return -EINVAL; 207 return -EINVAL;
131 208
132 /* Based on var passed in to calculate the refresh, 209 /* Based on var passed in to calculate the refresh,
@@ -142,7 +219,7 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
142 viafb_refresh = viafb_get_refresh(var->xres, var->yres, long_refresh); 219 viafb_refresh = viafb_get_refresh(var->xres, var->yres, long_refresh);
143 220
144 /* Adjust var according to our driver's own table */ 221 /* Adjust var according to our driver's own table */
145 viafb_fill_var_timing_info(var, viafb_refresh, vmode_index); 222 viafb_fill_var_timing_info(var, viafb_refresh, vmode_entry);
146 if (info->var.accel_flags & FB_ACCELF_TEXT && 223 if (info->var.accel_flags & FB_ACCELF_TEXT &&
147 !ppar->shared->engine_mmio) 224 !ppar->shared->engine_mmio)
148 info->var.accel_flags = 0; 225 info->var.accel_flags = 0;
@@ -153,40 +230,45 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
153static int viafb_set_par(struct fb_info *info) 230static int viafb_set_par(struct fb_info *info)
154{ 231{
155 struct viafb_par *viapar = info->par; 232 struct viafb_par *viapar = info->par;
156 int vmode_index; 233 struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL;
157 int vmode_index1 = 0;
158 DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); 234 DEBUG_MSG(KERN_INFO "viafb_set_par!\n");
159 235
160 viapar->depth = fb_get_color_depth(&info->var, &info->fix); 236 viapar->depth = fb_get_color_depth(&info->var, &info->fix);
161 viafb_update_device_setting(info->var.xres, info->var.yres, 237 viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres,
162 info->var.bits_per_pixel, viafb_refresh, 0); 238 viafbinfo->var.bits_per_pixel, viafb_refresh, 0);
163 239
164 vmode_index = viafb_get_mode_index(info->var.xres, info->var.yres); 240 vmode_entry = viafb_get_mode(viafbinfo->var.xres, viafbinfo->var.yres);
165 241 if (viafb_dual_fb) {
166 if (viafb_SAMM_ON == 1) { 242 vmode_entry1 = viafb_get_mode(viafbinfo1->var.xres,
243 viafbinfo1->var.yres);
244 viafb_update_device_setting(viafbinfo1->var.xres,
245 viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel,
246 viafb_refresh1, 1);
247 } else if (viafb_SAMM_ON == 1) {
167 DEBUG_MSG(KERN_INFO 248 DEBUG_MSG(KERN_INFO
168 "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n", 249 "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n",
169 viafb_second_xres, viafb_second_yres, viafb_bpp1); 250 viafb_second_xres, viafb_second_yres, viafb_bpp1);
170 vmode_index1 = viafb_get_mode_index(viafb_second_xres, 251 vmode_entry1 = viafb_get_mode(viafb_second_xres,
171 viafb_second_yres); 252 viafb_second_yres);
172 DEBUG_MSG(KERN_INFO "->viafb_SAMM_ON: index=%d\n",
173 vmode_index1);
174 253
175 viafb_update_device_setting(viafb_second_xres, 254 viafb_update_device_setting(viafb_second_xres,
176 viafb_second_yres, viafb_bpp1, viafb_refresh1, 1); 255 viafb_second_yres, viafb_bpp1, viafb_refresh1, 1);
177 } 256 }
178 257
179 if (vmode_index != VIA_RES_INVALID) { 258 if (vmode_entry) {
180 viafb_setmode(vmode_index, info->var.xres, info->var.yres,
181 info->var.bits_per_pixel, vmode_index1,
182 viafb_second_xres, viafb_second_yres, viafb_bpp1);
183
184 viafb_update_fix(info); 259 viafb_update_fix(info);
185 viafb_bpp = info->var.bits_per_pixel; 260 if (viafb_dual_fb && viapar->iga_path == IGA2)
261 viafb_bpp1 = info->var.bits_per_pixel;
262 else
263 viafb_bpp = info->var.bits_per_pixel;
264
186 if (info->var.accel_flags & FB_ACCELF_TEXT) 265 if (info->var.accel_flags & FB_ACCELF_TEXT)
187 info->flags &= ~FBINFO_HWACCEL_DISABLED; 266 info->flags &= ~FBINFO_HWACCEL_DISABLED;
188 else 267 else
189 info->flags |= FBINFO_HWACCEL_DISABLED; 268 info->flags |= FBINFO_HWACCEL_DISABLED;
269 viafb_setmode(vmode_entry, info->var.bits_per_pixel,
270 vmode_entry1, viafb_bpp1);
271 viafb_pan_display(&info->var, info);
190 } 272 }
191 273
192 return 0; 274 return 0;
@@ -196,234 +278,52 @@ static int viafb_set_par(struct fb_info *info)
196static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green, 278static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green,
197unsigned blue, unsigned transp, struct fb_info *info) 279unsigned blue, unsigned transp, struct fb_info *info)
198{ 280{
199 u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10; 281 struct viafb_par *viapar = info->par;
200 unsigned cmap_entries = (info->var.bits_per_pixel == 8) ? 256 : 16; 282 u32 r, g, b;
201 DEBUG_MSG(KERN_INFO "viafb_setcolreg!\n");
202 if (regno >= cmap_entries)
203 return 1;
204 if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) {
205 /*
206 * Read PCI bus 0,dev 0,function 0,index 0xF6 to get chip rev.
207 */
208 outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8);
209 rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff;
210 }
211 switch (info->var.bits_per_pixel) {
212 case 8:
213 outb(0x1A, 0x3C4);
214 sr1a = inb(0x3C5);
215 outb(0x1B, 0x3C4);
216 sr1b = inb(0x3C5);
217 outb(0x67, 0x3D4);
218 cr67 = inb(0x3D5);
219 outb(0x6A, 0x3D4);
220 cr6a = inb(0x3D5);
221
222 /* Map the 3C6/7/8/9 to the IGA2 */
223 outb(0x1A, 0x3C4);
224 outb(sr1a | 0x01, 0x3C5);
225 /* Second Display Engine colck always on */
226 outb(0x1B, 0x3C4);
227 outb(sr1b | 0x80, 0x3C5);
228 /* Second Display Color Depth 8 */
229 outb(0x67, 0x3D4);
230 outb(cr67 & 0x3F, 0x3D5);
231 outb(0x6A, 0x3D4);
232 /* Second Display Channel Reset CR6A[6]) */
233 outb(cr6a & 0xBF, 0x3D5);
234 /* Second Display Channel Enable CR6A[7] */
235 outb(cr6a | 0x80, 0x3D5);
236 /* Second Display Channel stop reset) */
237 outb(cr6a | 0x40, 0x3D5);
238
239 /* Bit mask of palette */
240 outb(0xFF, 0x3c6);
241 /* Write one register of IGA2 */
242 outb(regno, 0x3C8);
243 if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name &&
244 rev >= 15) {
245 shift = 8;
246 viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5);
247 viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7);
248 } else {
249 shift = 10;
250 viafb_write_reg_mask(CR6A, VIACR, 0, BIT5);
251 viafb_write_reg_mask(SR15, VIASR, 0, BIT7);
252 }
253 outb(red >> shift, 0x3C9);
254 outb(green >> shift, 0x3C9);
255 outb(blue >> shift, 0x3C9);
256
257 /* Map the 3C6/7/8/9 to the IGA1 */
258 outb(0x1A, 0x3C4);
259 outb(sr1a & 0xFE, 0x3C5);
260 /* Bit mask of palette */
261 outb(0xFF, 0x3c6);
262 /* Write one register of IGA1 */
263 outb(regno, 0x3C8);
264 outb(red >> shift, 0x3C9);
265 outb(green >> shift, 0x3C9);
266 outb(blue >> shift, 0x3C9);
267
268 outb(0x1A, 0x3C4);
269 outb(sr1a, 0x3C5);
270 outb(0x1B, 0x3C4);
271 outb(sr1b, 0x3C5);
272 outb(0x67, 0x3D4);
273 outb(cr67, 0x3D5);
274 outb(0x6A, 0x3D4);
275 outb(cr6a, 0x3D5);
276 break;
277 case 16:
278 ((u32 *) info->pseudo_palette)[regno] = (red & 0xF800) |
279 ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
280 break;
281 case 32:
282 ((u32 *) info->pseudo_palette)[regno] =
283 ((transp & 0xFF00) << 16) |
284 ((red & 0xFF00) << 8) |
285 ((green & 0xFF00)) | ((blue & 0xFF00) >> 8);
286 break;
287 }
288
289 return 0;
290 283
291} 284 if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
285 if (regno > 255)
286 return -EINVAL;
292 287
293/*CALLED BY: fb_set_cmap */ 288 if (!viafb_dual_fb || viapar->iga_path == IGA1)
294/* fb_set_var, pass 256 colors */ 289 viafb_set_primary_color_register(regno, red >> 8,
295/*CALLED BY: fb_set_cmap */ 290 green >> 8, blue >> 8);
296/* fbcon_set_palette, pass 16 colors */
297static int viafb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
298{
299 u32 len = cmap->len;
300 u32 i;
301 u16 *pred = cmap->red;
302 u16 *pgreen = cmap->green;
303 u16 *pblue = cmap->blue;
304 u16 *ptransp = cmap->transp;
305 u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10;
306 if (len > 256)
307 return 1;
308 if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) {
309 /*
310 * Read PCI bus 0, dev 0, function 0, index 0xF6 to get chip
311 * rev.
312 */
313 outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8);
314 rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff;
315 }
316 switch (info->var.bits_per_pixel) {
317 case 8:
318 outb(0x1A, 0x3C4);
319 sr1a = inb(0x3C5);
320 outb(0x1B, 0x3C4);
321 sr1b = inb(0x3C5);
322 outb(0x67, 0x3D4);
323 cr67 = inb(0x3D5);
324 outb(0x6A, 0x3D4);
325 cr6a = inb(0x3D5);
326 /* Map the 3C6/7/8/9 to the IGA2 */
327 outb(0x1A, 0x3C4);
328 outb(sr1a | 0x01, 0x3C5);
329 outb(0x1B, 0x3C4);
330 /* Second Display Engine colck always on */
331 outb(sr1b | 0x80, 0x3C5);
332 outb(0x67, 0x3D4);
333 /* Second Display Color Depth 8 */
334 outb(cr67 & 0x3F, 0x3D5);
335 outb(0x6A, 0x3D4);
336 /* Second Display Channel Reset CR6A[6]) */
337 outb(cr6a & 0xBF, 0x3D5);
338 /* Second Display Channel Enable CR6A[7] */
339 outb(cr6a | 0x80, 0x3D5);
340 /* Second Display Channel stop reset) */
341 outb(cr6a | 0xC0, 0x3D5);
342
343 /* Bit mask of palette */
344 outb(0xFF, 0x3c6);
345 outb(0x00, 0x3C8);
346 if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name &&
347 rev >= 15) {
348 shift = 8;
349 viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5);
350 viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7);
351 } else {
352 shift = 10;
353 viafb_write_reg_mask(CR6A, VIACR, 0, BIT5);
354 viafb_write_reg_mask(SR15, VIASR, 0, BIT7);
355 }
356 for (i = 0; i < len; i++) {
357 outb((*(pred + i)) >> shift, 0x3C9);
358 outb((*(pgreen + i)) >> shift, 0x3C9);
359 outb((*(pblue + i)) >> shift, 0x3C9);
360 }
361 291
362 outb(0x1A, 0x3C4); 292 if (!viafb_dual_fb || viapar->iga_path == IGA2)
363 /* Map the 3C6/7/8/9 to the IGA1 */ 293 viafb_set_secondary_color_register(regno, red >> 8,
364 outb(sr1a & 0xFE, 0x3C5); 294 green >> 8, blue >> 8);
365 /* Bit mask of palette */ 295 } else {
366 outb(0xFF, 0x3c6); 296 if (regno > 15)
367 outb(0x00, 0x3C8); 297 return -EINVAL;
368 for (i = 0; i < len; i++) {
369 outb((*(pred + i)) >> shift, 0x3C9);
370 outb((*(pgreen + i)) >> shift, 0x3C9);
371 outb((*(pblue + i)) >> shift, 0x3C9);
372 }
373 298
374 outb(0x1A, 0x3C4); 299 r = (red >> (16 - info->var.red.length))
375 outb(sr1a, 0x3C5); 300 << info->var.red.offset;
376 outb(0x1B, 0x3C4); 301 b = (blue >> (16 - info->var.blue.length))
377 outb(sr1b, 0x3C5); 302 << info->var.blue.offset;
378 outb(0x67, 0x3D4); 303 g = (green >> (16 - info->var.green.length))
379 outb(cr67, 0x3D5); 304 << info->var.green.offset;
380 outb(0x6A, 0x3D4); 305 ((u32 *) info->pseudo_palette)[regno] = r | g | b;
381 outb(cr6a, 0x3D5);
382 break;
383 case 16:
384 if (len > 17)
385 return 0; /* Because static u32 pseudo_pal[17]; */
386 for (i = 0; i < len; i++)
387 ((u32 *) info->pseudo_palette)[i] =
388 (*(pred + i) & 0xF800) |
389 ((*(pgreen + i) & 0xFC00) >> 5) |
390 ((*(pblue + i) & 0xF800) >> 11);
391 break;
392 case 32:
393 if (len > 17)
394 return 0;
395 if (ptransp) {
396 for (i = 0; i < len; i++)
397 ((u32 *) info->pseudo_palette)[i] =
398 ((*(ptransp + i) & 0xFF00) << 16) |
399 ((*(pred + i) & 0xFF00) << 8) |
400 ((*(pgreen + i) & 0xFF00)) |
401 ((*(pblue + i) & 0xFF00) >> 8);
402 } else {
403 for (i = 0; i < len; i++)
404 ((u32 *) info->pseudo_palette)[i] =
405 0x00000000 |
406 ((*(pred + i) & 0xFF00) << 8) |
407 ((*(pgreen + i) & 0xFF00)) |
408 ((*(pblue + i) & 0xFF00) >> 8);
409 }
410 break;
411 } 306 }
307
412 return 0; 308 return 0;
413} 309}
414 310
415static int viafb_pan_display(struct fb_var_screeninfo *var, 311static int viafb_pan_display(struct fb_var_screeninfo *var,
416 struct fb_info *info) 312 struct fb_info *info)
417{ 313{
418 unsigned int offset; 314 struct viafb_par *viapar = info->par;
419 315 u32 vram_addr = (var->yoffset * var->xres_virtual + var->xoffset)
420 DEBUG_MSG(KERN_INFO "viafb_pan_display!\n"); 316 * (var->bits_per_pixel / 8) + viapar->vram_addr;
421 317
422 offset = (var->xoffset + (var->yoffset * var->xres_virtual)) * 318 DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr);
423 var->bits_per_pixel / 16; 319 if (!viafb_dual_fb) {
320 viafb_set_primary_address(vram_addr);
321 viafb_set_secondary_address(vram_addr);
322 } else if (viapar->iga_path == IGA1)
323 viafb_set_primary_address(vram_addr);
324 else
325 viafb_set_secondary_address(vram_addr);
424 326
425 DEBUG_MSG(KERN_INFO "\nviafb_pan_display,offset =%d ", offset);
426 viafb_set_primary_address(offset);
427 return 0; 327 return 0;
428} 328}
429 329
@@ -477,6 +377,7 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
477 u32 gpu32; 377 u32 gpu32;
478 378
479 DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd); 379 DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd);
380 printk(KERN_WARNING "viafb_ioctl: Please avoid this interface as it is unstable and might change or vanish at any time!\n");
480 memset(&u, 0, sizeof(u)); 381 memset(&u, 0, sizeof(u));
481 382
482 switch (cmd) { 383 switch (cmd) {
@@ -680,7 +581,7 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
680 if (!viafb_gamma_table) 581 if (!viafb_gamma_table)
681 return -ENOMEM; 582 return -ENOMEM;
682 if (copy_from_user(viafb_gamma_table, argp, 583 if (copy_from_user(viafb_gamma_table, argp,
683 sizeof(viafb_gamma_table))) { 584 256 * sizeof(u32))) {
684 kfree(viafb_gamma_table); 585 kfree(viafb_gamma_table);
685 return -EFAULT; 586 return -EFAULT;
686 } 587 }
@@ -694,7 +595,7 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
694 return -ENOMEM; 595 return -ENOMEM;
695 viafb_get_gamma_table(viafb_gamma_table); 596 viafb_get_gamma_table(viafb_gamma_table);
696 if (copy_to_user(argp, viafb_gamma_table, 597 if (copy_to_user(argp, viafb_gamma_table,
697 sizeof(viafb_gamma_table))) { 598 256 * sizeof(u32))) {
698 kfree(viafb_gamma_table); 599 kfree(viafb_gamma_table);
699 return -EFAULT; 600 return -EFAULT;
700 } 601 }
@@ -872,7 +773,9 @@ static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
872 if (info->flags & FBINFO_HWACCEL_DISABLED || info != viafbinfo) 773 if (info->flags & FBINFO_HWACCEL_DISABLED || info != viafbinfo)
873 return -ENODEV; 774 return -ENODEV;
874 775
875 if (chip_name == UNICHROME_CLE266 && viapar->iga_path == IGA2) 776 /* LCD ouput does not support hw cursors (at least on VN896) */
777 if ((chip_name == UNICHROME_CLE266 && viapar->iga_path == IGA2) ||
778 viafb_LCD_ON)
876 return -ENODEV; 779 return -ENODEV;
877 780
878 viafb_show_hw_cursor(info, HW_Cursor_OFF); 781 viafb_show_hw_cursor(info, HW_Cursor_OFF);
@@ -1014,23 +917,6 @@ static int viafb_sync(struct fb_info *info)
1014 return 0; 917 return 0;
1015} 918}
1016 919
1017int viafb_get_mode_index(int hres, int vres)
1018{
1019 u32 i;
1020 DEBUG_MSG(KERN_INFO "viafb_get_mode_index!\n");
1021
1022 for (i = 0; i < NUM_TOTAL_MODETABLE; i++)
1023 if (CLE266Modes[i].mode_array &&
1024 CLE266Modes[i].crtc[0].crtc.hor_addr == hres &&
1025 CLE266Modes[i].crtc[0].crtc.ver_addr == vres)
1026 break;
1027
1028 if (i == NUM_TOTAL_MODETABLE)
1029 return VIA_RES_INVALID;
1030
1031 return CLE266Modes[i].ModeIndex;
1032}
1033
1034static void check_available_device_to_enable(int device_id) 920static void check_available_device_to_enable(int device_id)
1035{ 921{
1036 int device_num = 0; 922 int device_num = 0;
@@ -1329,7 +1215,7 @@ static void retrieve_device_setting(struct viafb_ioctl_setting
1329 setting_info->lcd_attributes.lcd_mode = viafb_lcd_mode; 1215 setting_info->lcd_attributes.lcd_mode = viafb_lcd_mode;
1330} 1216}
1331 1217
1332static void parse_active_dev(void) 1218static int parse_active_dev(void)
1333{ 1219{
1334 viafb_CRT_ON = STATE_OFF; 1220 viafb_CRT_ON = STATE_OFF;
1335 viafb_DVI_ON = STATE_OFF; 1221 viafb_DVI_ON = STATE_OFF;
@@ -1340,60 +1226,63 @@ static void parse_active_dev(void)
1340 IGA path to devices in SAMM case. */ 1226 IGA path to devices in SAMM case. */
1341 /* Note: The previous of active_dev is primary device, 1227 /* Note: The previous of active_dev is primary device,
1342 and the following is secondary device. */ 1228 and the following is secondary device. */
1343 if (!strncmp(viafb_active_dev, "CRT+DVI", 7)) { 1229 if (!viafb_active_dev) {
1230 viafb_CRT_ON = STATE_ON;
1231 viafb_SAMM_ON = STATE_OFF;
1232 } else if (!strcmp(viafb_active_dev, "CRT+DVI")) {
1344 /* CRT+DVI */ 1233 /* CRT+DVI */
1345 viafb_CRT_ON = STATE_ON; 1234 viafb_CRT_ON = STATE_ON;
1346 viafb_DVI_ON = STATE_ON; 1235 viafb_DVI_ON = STATE_ON;
1347 viafb_primary_dev = CRT_Device; 1236 viafb_primary_dev = CRT_Device;
1348 } else if (!strncmp(viafb_active_dev, "DVI+CRT", 7)) { 1237 } else if (!strcmp(viafb_active_dev, "DVI+CRT")) {
1349 /* DVI+CRT */ 1238 /* DVI+CRT */
1350 viafb_CRT_ON = STATE_ON; 1239 viafb_CRT_ON = STATE_ON;
1351 viafb_DVI_ON = STATE_ON; 1240 viafb_DVI_ON = STATE_ON;
1352 viafb_primary_dev = DVI_Device; 1241 viafb_primary_dev = DVI_Device;
1353 } else if (!strncmp(viafb_active_dev, "CRT+LCD", 7)) { 1242 } else if (!strcmp(viafb_active_dev, "CRT+LCD")) {
1354 /* CRT+LCD */ 1243 /* CRT+LCD */
1355 viafb_CRT_ON = STATE_ON; 1244 viafb_CRT_ON = STATE_ON;
1356 viafb_LCD_ON = STATE_ON; 1245 viafb_LCD_ON = STATE_ON;
1357 viafb_primary_dev = CRT_Device; 1246 viafb_primary_dev = CRT_Device;
1358 } else if (!strncmp(viafb_active_dev, "LCD+CRT", 7)) { 1247 } else if (!strcmp(viafb_active_dev, "LCD+CRT")) {
1359 /* LCD+CRT */ 1248 /* LCD+CRT */
1360 viafb_CRT_ON = STATE_ON; 1249 viafb_CRT_ON = STATE_ON;
1361 viafb_LCD_ON = STATE_ON; 1250 viafb_LCD_ON = STATE_ON;
1362 viafb_primary_dev = LCD_Device; 1251 viafb_primary_dev = LCD_Device;
1363 } else if (!strncmp(viafb_active_dev, "DVI+LCD", 7)) { 1252 } else if (!strcmp(viafb_active_dev, "DVI+LCD")) {
1364 /* DVI+LCD */ 1253 /* DVI+LCD */
1365 viafb_DVI_ON = STATE_ON; 1254 viafb_DVI_ON = STATE_ON;
1366 viafb_LCD_ON = STATE_ON; 1255 viafb_LCD_ON = STATE_ON;
1367 viafb_primary_dev = DVI_Device; 1256 viafb_primary_dev = DVI_Device;
1368 } else if (!strncmp(viafb_active_dev, "LCD+DVI", 7)) { 1257 } else if (!strcmp(viafb_active_dev, "LCD+DVI")) {
1369 /* LCD+DVI */ 1258 /* LCD+DVI */
1370 viafb_DVI_ON = STATE_ON; 1259 viafb_DVI_ON = STATE_ON;
1371 viafb_LCD_ON = STATE_ON; 1260 viafb_LCD_ON = STATE_ON;
1372 viafb_primary_dev = LCD_Device; 1261 viafb_primary_dev = LCD_Device;
1373 } else if (!strncmp(viafb_active_dev, "LCD+LCD2", 8)) { 1262 } else if (!strcmp(viafb_active_dev, "LCD+LCD2")) {
1374 viafb_LCD_ON = STATE_ON; 1263 viafb_LCD_ON = STATE_ON;
1375 viafb_LCD2_ON = STATE_ON; 1264 viafb_LCD2_ON = STATE_ON;
1376 viafb_primary_dev = LCD_Device; 1265 viafb_primary_dev = LCD_Device;
1377 } else if (!strncmp(viafb_active_dev, "LCD2+LCD", 8)) { 1266 } else if (!strcmp(viafb_active_dev, "LCD2+LCD")) {
1378 viafb_LCD_ON = STATE_ON; 1267 viafb_LCD_ON = STATE_ON;
1379 viafb_LCD2_ON = STATE_ON; 1268 viafb_LCD2_ON = STATE_ON;
1380 viafb_primary_dev = LCD2_Device; 1269 viafb_primary_dev = LCD2_Device;
1381 } else if (!strncmp(viafb_active_dev, "CRT", 3)) { 1270 } else if (!strcmp(viafb_active_dev, "CRT")) {
1382 /* CRT only */ 1271 /* CRT only */
1383 viafb_CRT_ON = STATE_ON; 1272 viafb_CRT_ON = STATE_ON;
1384 viafb_SAMM_ON = STATE_OFF; 1273 viafb_SAMM_ON = STATE_OFF;
1385 } else if (!strncmp(viafb_active_dev, "DVI", 3)) { 1274 } else if (!strcmp(viafb_active_dev, "DVI")) {
1386 /* DVI only */ 1275 /* DVI only */
1387 viafb_DVI_ON = STATE_ON; 1276 viafb_DVI_ON = STATE_ON;
1388 viafb_SAMM_ON = STATE_OFF; 1277 viafb_SAMM_ON = STATE_OFF;
1389 } else if (!strncmp(viafb_active_dev, "LCD", 3)) { 1278 } else if (!strcmp(viafb_active_dev, "LCD")) {
1390 /* LCD only */ 1279 /* LCD only */
1391 viafb_LCD_ON = STATE_ON; 1280 viafb_LCD_ON = STATE_ON;
1392 viafb_SAMM_ON = STATE_OFF; 1281 viafb_SAMM_ON = STATE_OFF;
1393 } else { 1282 } else
1394 viafb_CRT_ON = STATE_ON; 1283 return -EINVAL;
1395 viafb_SAMM_ON = STATE_OFF; 1284
1396 } 1285 return 0;
1397} 1286}
1398 1287
1399static int parse_port(char *opt_str, int *output_interface) 1288static int parse_port(char *opt_str, int *output_interface)
@@ -1797,7 +1686,7 @@ static const struct file_operations viafb_vt1636_proc_fops = {
1797static void viafb_init_proc(struct proc_dir_entry **viafb_entry) 1686static void viafb_init_proc(struct proc_dir_entry **viafb_entry)
1798{ 1687{
1799 *viafb_entry = proc_mkdir("viafb", NULL); 1688 *viafb_entry = proc_mkdir("viafb", NULL);
1800 if (viafb_entry) { 1689 if (*viafb_entry) {
1801 proc_create("dvp0", 0, *viafb_entry, &viafb_dvp0_proc_fops); 1690 proc_create("dvp0", 0, *viafb_entry, &viafb_dvp0_proc_fops);
1802 proc_create("dvp1", 0, *viafb_entry, &viafb_dvp1_proc_fops); 1691 proc_create("dvp1", 0, *viafb_entry, &viafb_dvp1_proc_fops);
1803 proc_create("dfph", 0, *viafb_entry, &viafb_dfph_proc_fops); 1692 proc_create("dfph", 0, *viafb_entry, &viafb_dfph_proc_fops);
@@ -1822,35 +1711,37 @@ static void viafb_remove_proc(struct proc_dir_entry *viafb_entry)
1822 remove_proc_entry("viafb", NULL); 1711 remove_proc_entry("viafb", NULL);
1823} 1712}
1824 1713
1825static void parse_mode(const char *str, u32 *xres, u32 *yres) 1714static int parse_mode(const char *str, u32 *xres, u32 *yres)
1826{ 1715{
1827 char *ptr; 1716 char *ptr;
1828 1717
1718 if (!str) {
1719 *xres = 640;
1720 *yres = 480;
1721 return 0;
1722 }
1723
1829 *xres = simple_strtoul(str, &ptr, 10); 1724 *xres = simple_strtoul(str, &ptr, 10);
1830 if (ptr[0] != 'x') 1725 if (ptr[0] != 'x')
1831 goto out_default; 1726 return -EINVAL;
1832 1727
1833 *yres = simple_strtoul(&ptr[1], &ptr, 10); 1728 *yres = simple_strtoul(&ptr[1], &ptr, 10);
1834 if (ptr[0]) 1729 if (ptr[0])
1835 goto out_default; 1730 return -EINVAL;
1836
1837 return;
1838 1731
1839out_default: 1732 return 0;
1840 printk(KERN_WARNING "viafb received invalid mode string: %s\n", str);
1841 *xres = 640;
1842 *yres = 480;
1843} 1733}
1844 1734
1845static int __devinit via_pci_probe(struct pci_dev *pdev, 1735static int __devinit via_pci_probe(struct pci_dev *pdev,
1846 const struct pci_device_id *ent) 1736 const struct pci_device_id *ent)
1847{ 1737{
1848 u32 default_xres, default_yres; 1738 u32 default_xres, default_yres;
1849 int vmode_index; 1739 struct VideoModeTable *vmode_entry;
1740 struct fb_var_screeninfo default_var;
1850 u32 viafb_par_length; 1741 u32 viafb_par_length;
1851 1742
1852 DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n"); 1743 DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n");
1853 1744 memset(&default_var, 0, sizeof(default_var));
1854 viafb_par_length = ALIGN(sizeof(struct viafb_par), BITS_PER_LONG/8); 1745 viafb_par_length = ALIGN(sizeof(struct viafb_par), BITS_PER_LONG/8);
1855 1746
1856 /* Allocate fb_info and ***_par here, also including some other needed 1747 /* Allocate fb_info and ***_par here, also including some other needed
@@ -1876,7 +1767,6 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
1876 1767
1877 if (viafb_dual_fb) 1768 if (viafb_dual_fb)
1878 viafb_SAMM_ON = 1; 1769 viafb_SAMM_ON = 1;
1879 parse_active_dev();
1880 parse_lcd_port(); 1770 parse_lcd_port();
1881 parse_dvi_port(); 1771 parse_dvi_port();
1882 1772
@@ -1925,9 +1815,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
1925 } 1815 }
1926 1816
1927 parse_mode(viafb_mode, &default_xres, &default_yres); 1817 parse_mode(viafb_mode, &default_xres, &default_yres);
1928 vmode_index = viafb_get_mode_index(default_xres, default_yres); 1818 vmode_entry = viafb_get_mode(default_xres, default_yres);
1929 DEBUG_MSG(KERN_INFO "0->index=%d\n", vmode_index);
1930
1931 if (viafb_SAMM_ON == 1) { 1819 if (viafb_SAMM_ON == 1) {
1932 parse_mode(viafb_mode1, &viafb_second_xres, 1820 parse_mode(viafb_mode1, &viafb_second_xres,
1933 &viafb_second_yres); 1821 &viafb_second_yres);
@@ -1946,19 +1834,6 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
1946 viafb_second_virtual_yres = viafb_second_yres; 1834 viafb_second_virtual_yres = viafb_second_yres;
1947 } 1835 }
1948 1836
1949 switch (viafb_bpp) {
1950 case 0 ... 8:
1951 viafb_bpp = 8;
1952 break;
1953 case 9 ... 16:
1954 viafb_bpp = 16;
1955 break;
1956 case 17 ... 32:
1957 viafb_bpp = 32;
1958 break;
1959 default:
1960 viafb_bpp = 8;
1961 }
1962 default_var.xres = default_xres; 1837 default_var.xres = default_xres;
1963 default_var.yres = default_yres; 1838 default_var.yres = default_yres;
1964 switch (default_xres) { 1839 switch (default_xres) {
@@ -1971,8 +1846,6 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
1971 } 1846 }
1972 default_var.yres_virtual = default_yres; 1847 default_var.yres_virtual = default_yres;
1973 default_var.bits_per_pixel = viafb_bpp; 1848 default_var.bits_per_pixel = viafb_bpp;
1974 if (default_var.bits_per_pixel == 15)
1975 default_var.bits_per_pixel = 16;
1976 default_var.pixclock = 1849 default_var.pixclock =
1977 viafb_get_pixclock(default_xres, default_yres, viafb_refresh); 1850 viafb_get_pixclock(default_xres, default_yres, viafb_refresh);
1978 default_var.left_margin = (default_xres >> 3) & 0xf8; 1851 default_var.left_margin = (default_xres >> 3) & 0xf8;
@@ -1981,6 +1854,8 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
1981 default_var.lower_margin = 4; 1854 default_var.lower_margin = 4;
1982 default_var.hsync_len = default_var.left_margin; 1855 default_var.hsync_len = default_var.left_margin;
1983 default_var.vsync_len = 4; 1856 default_var.vsync_len = 4;
1857 viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo);
1858 viafbinfo->var = default_var;
1984 1859
1985 if (viafb_dual_fb) { 1860 if (viafb_dual_fb) {
1986 viafbinfo1 = framebuffer_alloc(viafb_par_length, &pdev->dev); 1861 viafbinfo1 = framebuffer_alloc(viafb_par_length, &pdev->dev);
@@ -2015,8 +1890,6 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
2015 default_var.yres = viafb_second_yres; 1890 default_var.yres = viafb_second_yres;
2016 default_var.xres_virtual = viafb_second_virtual_xres; 1891 default_var.xres_virtual = viafb_second_virtual_xres;
2017 default_var.yres_virtual = viafb_second_virtual_yres; 1892 default_var.yres_virtual = viafb_second_virtual_yres;
2018 if (viafb_bpp1 != viafb_bpp)
2019 viafb_bpp1 = viafb_bpp;
2020 default_var.bits_per_pixel = viafb_bpp1; 1893 default_var.bits_per_pixel = viafb_bpp1;
2021 default_var.pixclock = 1894 default_var.pixclock =
2022 viafb_get_pixclock(viafb_second_xres, viafb_second_yres, 1895 viafb_get_pixclock(viafb_second_xres, viafb_second_yres,
@@ -2036,9 +1909,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
2036 &viafbinfo1->fix); 1909 &viafbinfo1->fix);
2037 } 1910 }
2038 1911
2039 viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo); 1912 viafb_check_var(&viafbinfo->var, viafbinfo);
2040 viafb_check_var(&default_var, viafbinfo);
2041 viafbinfo->var = default_var;
2042 viafb_update_fix(viafbinfo); 1913 viafb_update_fix(viafbinfo);
2043 viaparinfo->depth = fb_get_color_depth(&viafbinfo->var, 1914 viaparinfo->depth = fb_get_color_depth(&viafbinfo->var,
2044 &viafbinfo->fix); 1915 &viafbinfo->fix);
@@ -2196,12 +2067,20 @@ static struct pci_driver viafb_driver = {
2196 2067
2197static int __init viafb_init(void) 2068static int __init viafb_init(void)
2198{ 2069{
2070 u32 dummy;
2199#ifndef MODULE 2071#ifndef MODULE
2200 char *option = NULL; 2072 char *option = NULL;
2201 if (fb_get_options("viafb", &option)) 2073 if (fb_get_options("viafb", &option))
2202 return -ENODEV; 2074 return -ENODEV;
2203 viafb_setup(option); 2075 viafb_setup(option);
2204#endif 2076#endif
2077 if (parse_mode(viafb_mode, &dummy, &dummy)
2078 || parse_mode(viafb_mode1, &dummy, &dummy)
2079 || viafb_bpp < 0 || viafb_bpp > 32
2080 || viafb_bpp1 < 0 || viafb_bpp1 > 32
2081 || parse_active_dev())
2082 return -EINVAL;
2083
2205 printk(KERN_INFO 2084 printk(KERN_INFO
2206 "VIA Graphics Intergration Chipset framebuffer %d.%d initializing\n", 2085 "VIA Graphics Intergration Chipset framebuffer %d.%d initializing\n",
2207 VERSION_MAJOR, VERSION_MINOR); 2086 VERSION_MAJOR, VERSION_MINOR);
@@ -2229,15 +2108,12 @@ static struct fb_ops viafb_ops = {
2229 .fb_cursor = viafb_cursor, 2108 .fb_cursor = viafb_cursor,
2230 .fb_ioctl = viafb_ioctl, 2109 .fb_ioctl = viafb_ioctl,
2231 .fb_sync = viafb_sync, 2110 .fb_sync = viafb_sync,
2232 .fb_setcmap = viafb_setcmap,
2233}; 2111};
2234 2112
2235module_init(viafb_init); 2113module_init(viafb_init);
2236module_exit(viafb_exit); 2114module_exit(viafb_exit);
2237 2115
2238#ifdef MODULE 2116#ifdef MODULE
2239module_param(viafb_memsize, int, S_IRUSR);
2240
2241module_param(viafb_mode, charp, S_IRUSR); 2117module_param(viafb_mode, charp, S_IRUSR);
2242MODULE_PARM_DESC(viafb_mode, "Set resolution (default=640x480)"); 2118MODULE_PARM_DESC(viafb_mode, "Set resolution (default=640x480)");
2243 2119
diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h
index 0c94d2441922..61b5953cd159 100644
--- a/drivers/video/via/viafbdev.h
+++ b/drivers/video/via/viafbdev.h
@@ -83,22 +83,16 @@ struct viafb_par {
83 83
84extern unsigned int viafb_second_virtual_yres; 84extern unsigned int viafb_second_virtual_yres;
85extern unsigned int viafb_second_virtual_xres; 85extern unsigned int viafb_second_virtual_xres;
86extern unsigned int viafb_second_offset;
87extern int viafb_second_size;
88extern int viafb_SAMM_ON; 86extern int viafb_SAMM_ON;
89extern int viafb_dual_fb; 87extern int viafb_dual_fb;
90extern int viafb_LCD2_ON; 88extern int viafb_LCD2_ON;
91extern int viafb_LCD_ON; 89extern int viafb_LCD_ON;
92extern int viafb_DVI_ON; 90extern int viafb_DVI_ON;
93extern int viafb_hotplug; 91extern int viafb_hotplug;
94extern int viafb_memsize;
95 92
96extern int strict_strtoul(const char *cp, unsigned int base, 93extern int strict_strtoul(const char *cp, unsigned int base,
97 unsigned long *res); 94 unsigned long *res);
98 95
99void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
100 int mode_index);
101int viafb_get_mode_index(int hres, int vres);
102u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information 96u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
103 *plvds_setting_info, struct lvds_chip_information 97 *plvds_setting_info, struct lvds_chip_information
104 *plvds_chip_info, u8 index); 98 *plvds_chip_info, u8 index);
diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c
index b74f8a67923c..af50e244016c 100644
--- a/drivers/video/via/viamode.c
+++ b/drivers/video/via/viamode.c
@@ -412,7 +412,7 @@ struct io_reg PM1024x768[] = { {VIASR, 0x16, 0xBF, 0x0C},
412}; 412};
413 413
414struct patch_table res_patch_table[] = { 414struct patch_table res_patch_table[] = {
415 {VIA_RES_1024X768, ARRAY_SIZE(PM1024x768), PM1024x768} 415 {ARRAY_SIZE(PM1024x768), PM1024x768}
416}; 416};
417 417
418/* struct VPITTable { 418/* struct VPITTable {
@@ -879,169 +879,151 @@ struct crt_mode_table CRTM2048x1536[] = {
879 {2800, 2048, 2048, 752, 2200, 224, 1592, 1536, 1536, 56, 1539, 4} } 879 {2800, 2048, 2048, 752, 2200, 224, 1592, 1536, 1536, 56, 1539, 4} }
880}; 880};
881 881
882/* Video Mode Table */ 882struct VideoModeTable viafb_modes[] = {
883/* struct VideoModeTable {*/
884/* int ModeIndex;*/
885/* struct crt_mode_table *crtc;*/
886/* int mode_array;*/
887/* };*/
888struct VideoModeTable CLE266Modes[] = {
889 /* Display : 480x640 (GTF) */ 883 /* Display : 480x640 (GTF) */
890 {VIA_RES_480X640, CRTM480x640, ARRAY_SIZE(CRTM480x640)}, 884 {CRTM480x640, ARRAY_SIZE(CRTM480x640)},
891 885
892 /* Display : 640x480 */ 886 /* Display : 640x480 */
893 {VIA_RES_640X480, CRTM640x480, ARRAY_SIZE(CRTM640x480)}, 887 {CRTM640x480, ARRAY_SIZE(CRTM640x480)},
894 888
895 /* Display : 720x480 (GTF) */ 889 /* Display : 720x480 (GTF) */
896 {VIA_RES_720X480, CRTM720x480, ARRAY_SIZE(CRTM720x480)}, 890 {CRTM720x480, ARRAY_SIZE(CRTM720x480)},
897 891
898 /* Display : 720x576 (GTF) */ 892 /* Display : 720x576 (GTF) */
899 {VIA_RES_720X576, CRTM720x576, ARRAY_SIZE(CRTM720x576)}, 893 {CRTM720x576, ARRAY_SIZE(CRTM720x576)},
900 894
901 /* Display : 800x600 */ 895 /* Display : 800x600 */
902 {VIA_RES_800X600, CRTM800x600, ARRAY_SIZE(CRTM800x600)}, 896 {CRTM800x600, ARRAY_SIZE(CRTM800x600)},
903 897
904 /* Display : 800x480 (CVT) */ 898 /* Display : 800x480 (CVT) */
905 {VIA_RES_800X480, CRTM800x480, ARRAY_SIZE(CRTM800x480)}, 899 {CRTM800x480, ARRAY_SIZE(CRTM800x480)},
906 900
907 /* Display : 848x480 (CVT) */ 901 /* Display : 848x480 (CVT) */
908 {VIA_RES_848X480, CRTM848x480, ARRAY_SIZE(CRTM848x480)}, 902 {CRTM848x480, ARRAY_SIZE(CRTM848x480)},
909 903
910 /* Display : 852x480 (GTF) */ 904 /* Display : 852x480 (GTF) */
911 {VIA_RES_856X480, CRTM852x480, ARRAY_SIZE(CRTM852x480)}, 905 {CRTM852x480, ARRAY_SIZE(CRTM852x480)},
912 906
913 /* Display : 1024x512 (GTF) */ 907 /* Display : 1024x512 (GTF) */
914 {VIA_RES_1024X512, CRTM1024x512, ARRAY_SIZE(CRTM1024x512)}, 908 {CRTM1024x512, ARRAY_SIZE(CRTM1024x512)},
915 909
916 /* Display : 1024x600 */ 910 /* Display : 1024x600 */
917 {VIA_RES_1024X600, CRTM1024x600, ARRAY_SIZE(CRTM1024x600)}, 911 {CRTM1024x600, ARRAY_SIZE(CRTM1024x600)},
918
919 /* Display : 1024x576 (GTF) */
920 /*{ VIA_RES_1024X576, CRTM1024x576, ARRAY_SIZE(CRTM1024x576)}, */
921 912
922 /* Display : 1024x768 */ 913 /* Display : 1024x768 */
923 {VIA_RES_1024X768, CRTM1024x768, ARRAY_SIZE(CRTM1024x768)}, 914 {CRTM1024x768, ARRAY_SIZE(CRTM1024x768)},
924 915
925 /* Display : 1152x864 */ 916 /* Display : 1152x864 */
926 {VIA_RES_1152X864, CRTM1152x864, ARRAY_SIZE(CRTM1152x864)}, 917 {CRTM1152x864, ARRAY_SIZE(CRTM1152x864)},
927 918
928 /* Display : 1280x768 (GTF) */ 919 /* Display : 1280x768 (GTF) */
929 {VIA_RES_1280X768, CRTM1280x768, ARRAY_SIZE(CRTM1280x768)}, 920 {CRTM1280x768, ARRAY_SIZE(CRTM1280x768)},
930 921
931 /* Display : 960x600 (CVT) */ 922 /* Display : 960x600 (CVT) */
932 {VIA_RES_960X600, CRTM960x600, ARRAY_SIZE(CRTM960x600)}, 923 {CRTM960x600, ARRAY_SIZE(CRTM960x600)},
933 924
934 /* Display : 1000x600 (GTF) */ 925 /* Display : 1000x600 (GTF) */
935 {VIA_RES_1000X600, CRTM1000x600, ARRAY_SIZE(CRTM1000x600)}, 926 {CRTM1000x600, ARRAY_SIZE(CRTM1000x600)},
936 927
937 /* Display : 1024x576 (GTF) */ 928 /* Display : 1024x576 (GTF) */
938 {VIA_RES_1024X576, CRTM1024x576, ARRAY_SIZE(CRTM1024x576)}, 929 {CRTM1024x576, ARRAY_SIZE(CRTM1024x576)},
939 930
940 /* Display : 1088x612 (GTF) */ 931 /* Display : 1088x612 (GTF) */
941 {VIA_RES_1088X612, CRTM1088x612, ARRAY_SIZE(CRTM1088x612)}, 932 {CRTM1088x612, ARRAY_SIZE(CRTM1088x612)},
942 933
943 /* Display : 1152x720 (CVT) */ 934 /* Display : 1152x720 (CVT) */
944 {VIA_RES_1152X720, CRTM1152x720, ARRAY_SIZE(CRTM1152x720)}, 935 {CRTM1152x720, ARRAY_SIZE(CRTM1152x720)},
945 936
946 /* Display : 1200x720 (GTF) */ 937 /* Display : 1200x720 (GTF) */
947 {VIA_RES_1200X720, CRTM1200x720, ARRAY_SIZE(CRTM1200x720)}, 938 {CRTM1200x720, ARRAY_SIZE(CRTM1200x720)},
948 939
949 /* Display : 1280x600 (GTF) */ 940 /* Display : 1280x600 (GTF) */
950 {VIA_RES_1280X600, CRTM1280x600, ARRAY_SIZE(CRTM1280x600)}, 941 {CRTM1280x600, ARRAY_SIZE(CRTM1280x600)},
951 942
952 /* Display : 1280x800 (CVT) */ 943 /* Display : 1280x800 (CVT) */
953 {VIA_RES_1280X800, CRTM1280x800, ARRAY_SIZE(CRTM1280x800)}, 944 {CRTM1280x800, ARRAY_SIZE(CRTM1280x800)},
954
955 /* Display : 1280x800 (GTF) */
956 /*{ M1280x800, CRTM1280x800, ARRAY_SIZE(CRTM1280x800)}, */
957 945
958 /* Display : 1280x960 */ 946 /* Display : 1280x960 */
959 {VIA_RES_1280X960, CRTM1280x960, ARRAY_SIZE(CRTM1280x960)}, 947 {CRTM1280x960, ARRAY_SIZE(CRTM1280x960)},
960 948
961 /* Display : 1280x1024 */ 949 /* Display : 1280x1024 */
962 {VIA_RES_1280X1024, CRTM1280x1024, ARRAY_SIZE(CRTM1280x1024)}, 950 {CRTM1280x1024, ARRAY_SIZE(CRTM1280x1024)},
963 951
964 /* Display : 1360x768 (CVT) */ 952 /* Display : 1360x768 (CVT) */
965 {VIA_RES_1360X768, CRTM1360x768, ARRAY_SIZE(CRTM1360x768)}, 953 {CRTM1360x768, ARRAY_SIZE(CRTM1360x768)},
966
967 /* Display : 1360x768 (CVT Reduce Blanking) */
968 {VIA_RES_1360X768_RB, CRTM1360x768_RB,
969 ARRAY_SIZE(CRTM1360x768_RB)},
970 954
971 /* Display : 1366x768 */ 955 /* Display : 1366x768 */
972 {VIA_RES_1366X768, CRTM1366x768, ARRAY_SIZE(CRTM1366x768)}, 956 {CRTM1366x768, ARRAY_SIZE(CRTM1366x768)},
973 957
974 /* Display : 1368x768 (GTF) */ 958 /* Display : 1368x768 (GTF) */
975 /*{ M1368x768,CRTM1368x768,ARRAY_SIZE(CRTM1368x768)}, */ 959 {CRTM1368x768, ARRAY_SIZE(CRTM1368x768)},
976 /* Display : 1368x768 (GTF) */
977 {VIA_RES_1368X768, CRTM1368x768, ARRAY_SIZE(CRTM1368x768)},
978 960
979 /* Display : 1440x900 (CVT) */ 961 /* Display : 1440x900 (CVT) */
980 {VIA_RES_1440X900, CRTM1440x900, ARRAY_SIZE(CRTM1440x900)}, 962 {CRTM1440x900, ARRAY_SIZE(CRTM1440x900)},
981
982 /* Display : 1440x900 (CVT Reduce Blanking) */
983 {VIA_RES_1440X900_RB, CRTM1440x900_RB,
984 ARRAY_SIZE(CRTM1440x900_RB)},
985 963
986 /* Display : 1440x1050 (GTF) */ 964 /* Display : 1440x1050 (GTF) */
987 {VIA_RES_1440X1050, CRTM1440x1050, ARRAY_SIZE(CRTM1440x1050)}, 965 {CRTM1440x1050, ARRAY_SIZE(CRTM1440x1050)},
988
989 /* Display : 1400x1050 (CVT Reduce Blanking) */
990 {VIA_RES_1400X1050_RB, CRTM1400x1050_RB,
991 ARRAY_SIZE(CRTM1400x1050_RB)},
992 966
993 /* Display : 1600x900 (CVT) */ 967 /* Display : 1600x900 (CVT) */
994 {VIA_RES_1600X900, CRTM1600x900, ARRAY_SIZE(CRTM1600x900)}, 968 {CRTM1600x900, ARRAY_SIZE(CRTM1600x900)},
995
996 /* Display : 1600x900 (CVT Reduce Blanking) */
997 {VIA_RES_1600X900_RB, CRTM1600x900_RB,
998 ARRAY_SIZE(CRTM1600x900_RB)},
999 969
1000 /* Display : 1600x1024 (GTF) */ 970 /* Display : 1600x1024 (GTF) */
1001 {VIA_RES_1600X1024, CRTM1600x1024, ARRAY_SIZE(CRTM1600x1024)}, 971 {CRTM1600x1024, ARRAY_SIZE(CRTM1600x1024)},
1002 972
1003 /* Display : 1600x1200 */ 973 /* Display : 1600x1200 */
1004 {VIA_RES_1600X1200, CRTM1600x1200, ARRAY_SIZE(CRTM1600x1200)}, 974 {CRTM1600x1200, ARRAY_SIZE(CRTM1600x1200)},
1005 975
1006 /* Display : 1680x1050 (CVT) */ 976 /* Display : 1680x1050 (CVT) */
1007 {VIA_RES_1680X1050, CRTM1680x1050, ARRAY_SIZE(CRTM1680x1050)}, 977 {CRTM1680x1050, ARRAY_SIZE(CRTM1680x1050)},
1008
1009 /* Display : 1680x1050 (CVT Reduce Blanking) */
1010 {VIA_RES_1680X1050_RB, CRTM1680x1050_RB,
1011 ARRAY_SIZE(CRTM1680x1050_RB)},
1012 978
1013 /* Display : 1792x1344 (DMT) */ 979 /* Display : 1792x1344 (DMT) */
1014 {VIA_RES_1792X1344, CRTM1792x1344, ARRAY_SIZE(CRTM1792x1344)}, 980 {CRTM1792x1344, ARRAY_SIZE(CRTM1792x1344)},
1015 981
1016 /* Display : 1856x1392 (DMT) */ 982 /* Display : 1856x1392 (DMT) */
1017 {VIA_RES_1856X1392, CRTM1856x1392, ARRAY_SIZE(CRTM1856x1392)}, 983 {CRTM1856x1392, ARRAY_SIZE(CRTM1856x1392)},
1018 984
1019 /* Display : 1920x1440 */ 985 /* Display : 1920x1440 */
1020 {VIA_RES_1920X1440, CRTM1920x1440, ARRAY_SIZE(CRTM1920x1440)}, 986 {CRTM1920x1440, ARRAY_SIZE(CRTM1920x1440)},
1021 987
1022 /* Display : 2048x1536 */ 988 /* Display : 2048x1536 */
1023 {VIA_RES_2048X1536, CRTM2048x1536, ARRAY_SIZE(CRTM2048x1536)}, 989 {CRTM2048x1536, ARRAY_SIZE(CRTM2048x1536)},
1024 990
1025 /* Display : 1280x720 */ 991 /* Display : 1280x720 */
1026 {VIA_RES_1280X720, CRTM1280x720, ARRAY_SIZE(CRTM1280x720)}, 992 {CRTM1280x720, ARRAY_SIZE(CRTM1280x720)},
1027 993
1028 /* Display : 1920x1080 (CVT) */ 994 /* Display : 1920x1080 (CVT) */
1029 {VIA_RES_1920X1080, CRTM1920x1080, ARRAY_SIZE(CRTM1920x1080)}, 995 {CRTM1920x1080, ARRAY_SIZE(CRTM1920x1080)},
1030
1031 /* Display : 1920x1080 (CVT Reduce Blanking) */
1032 {VIA_RES_1920X1080_RB, CRTM1920x1080_RB,
1033 ARRAY_SIZE(CRTM1920x1080_RB)},
1034 996
1035 /* Display : 1920x1200 (CVT) */ 997 /* Display : 1920x1200 (CVT) */
1036 {VIA_RES_1920X1200, CRTM1920x1200, ARRAY_SIZE(CRTM1920x1200)}, 998 {CRTM1920x1200, ARRAY_SIZE(CRTM1920x1200)},
1037
1038 /* Display : 1920x1200 (CVT Reduce Blanking) */
1039 {VIA_RES_1920X1200_RB, CRTM1920x1200_RB,
1040 ARRAY_SIZE(CRTM1920x1200_RB)},
1041 999
1042 /* Display : 1400x1050 (CVT) */ 1000 /* Display : 1400x1050 (CVT) */
1043 {VIA_RES_1400X1050, CRTM1400x1050, ARRAY_SIZE(CRTM1400x1050)} 1001 {CRTM1400x1050, ARRAY_SIZE(CRTM1400x1050)}
1044}; 1002};
1003
1004struct VideoModeTable viafb_rb_modes[] = {
1005 /* Display : 1360x768 (CVT Reduce Blanking) */
1006 {CRTM1360x768_RB, ARRAY_SIZE(CRTM1360x768_RB)},
1007
1008 /* Display : 1440x900 (CVT Reduce Blanking) */
1009 {CRTM1440x900_RB, ARRAY_SIZE(CRTM1440x900_RB)},
1010
1011 /* Display : 1400x1050 (CVT Reduce Blanking) */
1012 {CRTM1400x1050_RB, ARRAY_SIZE(CRTM1400x1050_RB)},
1013
1014 /* Display : 1600x900 (CVT Reduce Blanking) */
1015 {CRTM1600x900_RB, ARRAY_SIZE(CRTM1600x900_RB)},
1016
1017 /* Display : 1680x1050 (CVT Reduce Blanking) */
1018 {CRTM1680x1050_RB, ARRAY_SIZE(CRTM1680x1050_RB)},
1019
1020 /* Display : 1920x1080 (CVT Reduce Blanking) */
1021 {CRTM1920x1080_RB, ARRAY_SIZE(CRTM1920x1080_RB)},
1022
1023 /* Display : 1920x1200 (CVT Reduce Blanking) */
1024 {CRTM1920x1200_RB, ARRAY_SIZE(CRTM1920x1200_RB)}
1025};
1026
1045struct crt_mode_table CEAM1280x720[] = { 1027struct crt_mode_table CEAM1280x720[] = {
1046 {REFRESH_60, CLK_74_270M, M1280X720_CEA_R60_HSP, 1028 {REFRESH_60, CLK_74_270M, M1280X720_CEA_R60_HSP,
1047 M1280X720_CEA_R60_VSP, 1029 M1280X720_CEA_R60_VSP,
@@ -1056,8 +1038,8 @@ struct crt_mode_table CEAM1920x1080[] = {
1056}; 1038};
1057struct VideoModeTable CEA_HDMI_Modes[] = { 1039struct VideoModeTable CEA_HDMI_Modes[] = {
1058 /* Display : 1280x720 */ 1040 /* Display : 1280x720 */
1059 {VIA_RES_1280X720, CEAM1280x720, ARRAY_SIZE(CEAM1280x720)}, 1041 {CEAM1280x720, ARRAY_SIZE(CEAM1280x720)},
1060 {VIA_RES_1920X1080, CEAM1920x1080, ARRAY_SIZE(CEAM1920x1080)} 1042 {CEAM1920x1080, ARRAY_SIZE(CEAM1920x1080)}
1061}; 1043};
1062 1044
1063int NUM_TOTAL_RES_MAP_REFRESH = ARRAY_SIZE(res_map_refresh_tbl); 1045int NUM_TOTAL_RES_MAP_REFRESH = ARRAY_SIZE(res_map_refresh_tbl);
@@ -1069,4 +1051,28 @@ int NUM_TOTAL_CX700_ModeXregs = ARRAY_SIZE(CX700_ModeXregs);
1069int NUM_TOTAL_VX855_ModeXregs = ARRAY_SIZE(VX855_ModeXregs); 1051int NUM_TOTAL_VX855_ModeXregs = ARRAY_SIZE(VX855_ModeXregs);
1070int NUM_TOTAL_CLE266_ModeXregs = ARRAY_SIZE(CLE266_ModeXregs); 1052int NUM_TOTAL_CLE266_ModeXregs = ARRAY_SIZE(CLE266_ModeXregs);
1071int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table); 1053int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table);
1072int NUM_TOTAL_MODETABLE = ARRAY_SIZE(CLE266Modes); 1054
1055
1056struct VideoModeTable *viafb_get_mode(int hres, int vres)
1057{
1058 u32 i;
1059 for (i = 0; i < ARRAY_SIZE(viafb_modes); i++)
1060 if (viafb_modes[i].mode_array &&
1061 viafb_modes[i].crtc[0].crtc.hor_addr == hres &&
1062 viafb_modes[i].crtc[0].crtc.ver_addr == vres)
1063 return &viafb_modes[i];
1064
1065 return NULL;
1066}
1067
1068struct VideoModeTable *viafb_get_rb_mode(int hres, int vres)
1069{
1070 u32 i;
1071 for (i = 0; i < ARRAY_SIZE(viafb_rb_modes); i++)
1072 if (viafb_rb_modes[i].mode_array &&
1073 viafb_rb_modes[i].crtc[0].crtc.hor_addr == hres &&
1074 viafb_rb_modes[i].crtc[0].crtc.ver_addr == vres)
1075 return &viafb_rb_modes[i];
1076
1077 return NULL;
1078}
diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h
index a9d6554fabdf..5b1ced86514b 100644
--- a/drivers/video/via/viamode.h
+++ b/drivers/video/via/viamode.h
@@ -32,13 +32,11 @@ struct VPITTable {
32}; 32};
33 33
34struct VideoModeTable { 34struct VideoModeTable {
35 int ModeIndex;
36 struct crt_mode_table *crtc; 35 struct crt_mode_table *crtc;
37 int mode_array; 36 int mode_array;
38}; 37};
39 38
40struct patch_table { 39struct patch_table {
41 int mode_index;
42 int table_length; 40 int table_length;
43 struct io_reg *io_reg_table; 41 struct io_reg *io_reg_table;
44}; 42};
@@ -59,13 +57,11 @@ extern int NUM_TOTAL_CX700_ModeXregs;
59extern int NUM_TOTAL_VX855_ModeXregs; 57extern int NUM_TOTAL_VX855_ModeXregs;
60extern int NUM_TOTAL_CLE266_ModeXregs; 58extern int NUM_TOTAL_CLE266_ModeXregs;
61extern int NUM_TOTAL_PATCH_MODE; 59extern int NUM_TOTAL_PATCH_MODE;
62extern int NUM_TOTAL_MODETABLE;
63 60
64/********************/ 61/********************/
65/* Mode Table */ 62/* Mode Table */
66/********************/ 63/********************/
67 64
68extern struct VideoModeTable CLE266Modes[];
69extern struct crt_mode_table CEAM1280x720[]; 65extern struct crt_mode_table CEAM1280x720[];
70extern struct crt_mode_table CEAM1920x1080[]; 66extern struct crt_mode_table CEAM1920x1080[];
71extern struct VideoModeTable CEA_HDMI_Modes[]; 67extern struct VideoModeTable CEA_HDMI_Modes[];
@@ -81,4 +77,8 @@ extern struct io_reg CLE266_ModeXregs[];
81extern struct io_reg PM1024x768[]; 77extern struct io_reg PM1024x768[];
82extern struct patch_table res_patch_table[]; 78extern struct patch_table res_patch_table[];
83extern struct VPITTable VPIT; 79extern struct VPITTable VPIT;
80
81struct VideoModeTable *viafb_get_mode(int hres, int vres);
82struct VideoModeTable *viafb_get_rb_mode(int hres, int vres);
83
84#endif /* __VIAMODE_H__ */ 84#endif /* __VIAMODE_H__ */
diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c
index 3df17dc8c3d7..d31dc96f838a 100644
--- a/drivers/video/vt8623fb.c
+++ b/drivers/video/vt8623fb.c
@@ -18,7 +18,6 @@
18#include <linux/string.h> 18#include <linux/string.h>
19#include <linux/mm.h> 19#include <linux/mm.h>
20#include <linux/tty.h> 20#include <linux/tty.h>
21#include <linux/slab.h>
22#include <linux/delay.h> 21#include <linux/delay.h>
23#include <linux/fb.h> 22#include <linux/fb.h>
24#include <linux/svga.h> 23#include <linux/svga.h>
@@ -446,7 +445,7 @@ static int vt8623fb_set_par(struct fb_info *info)
446 445
447 svga_wseq_mask(0x1E, 0xF0, 0xF0); // DI/DVP bus 446 svga_wseq_mask(0x1E, 0xF0, 0xF0); // DI/DVP bus
448 svga_wseq_mask(0x2A, 0x0F, 0x0F); // DI/DVP bus 447 svga_wseq_mask(0x2A, 0x0F, 0x0F); // DI/DVP bus
449 svga_wseq_mask(0x16, 0x08, 0xBF); // FIFO read treshold 448 svga_wseq_mask(0x16, 0x08, 0xBF); // FIFO read threshold
450 vga_wseq(NULL, 0x17, 0x1F); // FIFO depth 449 vga_wseq(NULL, 0x17, 0x1F); // FIFO depth
451 vga_wseq(NULL, 0x18, 0x4E); 450 vga_wseq(NULL, 0x18, 0x4E);
452 svga_wseq_mask(0x1A, 0x08, 0x08); // enable MMIO ? 451 svga_wseq_mask(0x1A, 0x08, 0x08); // enable MMIO ?
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
index 2376f688ec8b..31b0e17ed090 100644
--- a/drivers/video/w100fb.c
+++ b/drivers/video/w100fb.c
@@ -30,6 +30,7 @@
30#include <linux/kernel.h> 30#include <linux/kernel.h>
31#include <linux/mm.h> 31#include <linux/mm.h>
32#include <linux/platform_device.h> 32#include <linux/platform_device.h>
33#include <linux/slab.h>
33#include <linux/string.h> 34#include <linux/string.h>
34#include <linux/vmalloc.h> 35#include <linux/vmalloc.h>
35#include <asm/io.h> 36#include <asm/io.h>
@@ -628,7 +629,7 @@ static int w100fb_resume(struct platform_device *dev)
628#endif 629#endif
629 630
630 631
631int __init w100fb_probe(struct platform_device *pdev) 632int __devinit w100fb_probe(struct platform_device *pdev)
632{ 633{
633 int err = -EIO; 634 int err = -EIO;
634 struct w100fb_mach_info *inf; 635 struct w100fb_mach_info *inf;
diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
index 54cd91610174..fa97d3e7c21a 100644
--- a/drivers/video/xen-fbfront.c
+++ b/drivers/video/xen-fbfront.c
@@ -23,9 +23,13 @@
23#include <linux/errno.h> 23#include <linux/errno.h>
24#include <linux/fb.h> 24#include <linux/fb.h>
25#include <linux/module.h> 25#include <linux/module.h>
26#include <linux/slab.h>
26#include <linux/vmalloc.h> 27#include <linux/vmalloc.h>
27#include <linux/mm.h> 28#include <linux/mm.h>
29
28#include <asm/xen/hypervisor.h> 30#include <asm/xen/hypervisor.h>
31
32#include <xen/xen.h>
29#include <xen/events.h> 33#include <xen/events.h>
30#include <xen/page.h> 34#include <xen/page.h>
31#include <xen/interface/io/fbif.h> 35#include <xen/interface/io/fbif.h>
@@ -440,7 +444,7 @@ static int __devinit xenfb_probe(struct xenbus_device *dev,
440 fb_info->fix.type = FB_TYPE_PACKED_PIXELS; 444 fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
441 fb_info->fix.accel = FB_ACCEL_NONE; 445 fb_info->fix.accel = FB_ACCEL_NONE;
442 446
443 fb_info->flags = FBINFO_FLAG_DEFAULT; 447 fb_info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
444 448
445 ret = fb_alloc_cmap(&fb_info->cmap, 256, 0); 449 ret = fb_alloc_cmap(&fb_info->cmap, 256, 0);
446 if (ret < 0) { 450 if (ret < 0) {
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c
index ed7c8d0ddccb..3fcb83f03881 100644
--- a/drivers/video/xilinxfb.c
+++ b/drivers/video/xilinxfb.c
@@ -34,6 +34,7 @@
34#include <linux/of_platform.h> 34#include <linux/of_platform.h>
35#include <linux/io.h> 35#include <linux/io.h>
36#include <linux/xilinxfb.h> 36#include <linux/xilinxfb.h>
37#include <linux/slab.h>
37#include <asm/dcr.h> 38#include <asm/dcr.h>
38 39
39#define DRIVER_NAME "xilinxfb" 40#define DRIVER_NAME "xilinxfb"