Merge branch 'fbdev-next' of git://github.com/schandinat/linux-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 30 Oct 2011 22:30:01 +0000 (15:30 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 30 Oct 2011 22:30:01 +0000 (15:30 -0700)
* 'fbdev-next' of git://github.com/schandinat/linux-2.6: (270 commits)
  video: platinumfb: Add __devexit_p at necessary place
  drivers/video: fsl-diu-fb: merge diu_pool into fsl_diu_data
  drivers/video: fsl-diu-fb: merge diu_hw into fsl_diu_data
  drivers/video: fsl-diu-fb: only DIU modes 0 and 1 are supported
  drivers/video: fsl-diu-fb: remove unused panel operating mode support
  drivers/video: fsl-diu-fb: use an enum for the AOI index
  drivers/video: fsl-diu-fb: add several new video modes
  drivers/video: fsl-diu-fb: remove broken screen blanking support
  drivers/video: fsl-diu-fb: move some definitions out of the header file
  drivers/video: fsl-diu-fb: fix some ioctls
  video: da8xx-fb: Increased resolution configuration of revised LCDC IP
  OMAPDSS: picodlp: add missing #include <linux/module.h>
  fb: fix au1100fb bitrot.
  mx3fb: fix NULL pointer dereference in screen blanking.
  video: irq: Remove IRQF_DISABLED
  smscufx: change edid data to u8 instead of char
  OMAPDSS: DISPC: zorder support for DSS overlays
  OMAPDSS: DISPC: VIDEO3 pipeline support
  OMAPDSS/OMAP_VOUT: Fix incorrect OMAP3-alpha compatibility setting
  video/omap: fix build dependencies
  ...

Fix up conflicts in:
 - drivers/staging/xgifb/XGI_main_26.c
Changes to XGIfb_pan_var()
 - drivers/video/omap/{lcd_apollon.c,lcd_ldp.c,lcd_overo.c}
Removed (or in the case of apollon.c, merged into the generic
DSS panel in drivers/video/omap2/displays/panel-generic-dpi.c)

163 files changed:
Documentation/fb/udlfb.txt
MAINTAINERS
arch/arm/mach-omap2/board-2430sdp.c
arch/arm/mach-omap2/board-3430sdp.c
arch/arm/mach-omap2/board-4430sdp.c
arch/arm/mach-omap2/board-am3517evm.c
arch/arm/mach-omap2/board-apollon.c
arch/arm/mach-omap2/board-cm-t35.c
arch/arm/mach-omap2/board-devkit8000.c
arch/arm/mach-omap2/board-h4.c
arch/arm/mach-omap2/board-igep0020.c
arch/arm/mach-omap2/board-ldp.c
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-omap2/board-omap3evm.c
arch/arm/mach-omap2/board-omap3pandora.c
arch/arm/mach-omap2/board-omap3stalker.c
arch/arm/mach-omap2/board-omap3touchbook.c
arch/arm/mach-omap2/board-omap4panda.c
arch/arm/mach-omap2/board-overo.c
arch/arm/mach-omap2/board-rx51.c
arch/arm/mach-omap2/display.c
arch/arm/mach-omap2/twl-common.c
arch/arm/mach-shmobile/board-mackerel.c
arch/powerpc/platforms/512x/mpc512x_shared.c
arch/powerpc/platforms/85xx/p1022_ds.c
arch/powerpc/platforms/86xx/mpc8610_hpcd.c
arch/powerpc/sysdev/fsl_soc.h
drivers/media/video/omap/omap_vout.c
drivers/staging/xgifb/XGI_main_26.c
drivers/video/68328fb.c
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/acornfb.c
drivers/video/arkfb.c
drivers/video/atmel_lcdfb.c
drivers/video/aty/radeon_base.c
drivers/video/au1100fb.c
drivers/video/au1100fb.h
drivers/video/au1200fb.c
drivers/video/backlight/adp8860_bl.c
drivers/video/backlight/adp8870_bl.c
drivers/video/bf54x-lq043fb.c
drivers/video/bfin-lq035q1-fb.c
drivers/video/bfin-t350mcqb-fb.c
drivers/video/bfin_adv7393fb.c
drivers/video/carminefb.c
drivers/video/controlfb.c
drivers/video/da8xx-fb.c
drivers/video/fb-puv3.c
drivers/video/fb_defio.c
drivers/video/fbmem.c
drivers/video/fbmon.c
drivers/video/fbsysfs.c
drivers/video/fsl-diu-fb.c
drivers/video/g364fb.c
drivers/video/grvga.c [new file with mode: 0644]
drivers/video/gxt4500.c
drivers/video/hgafb.c
drivers/video/imsttfb.c
drivers/video/intelfb/intelfbhw.c
drivers/video/mb862xx/mb862xx-i2c.c
drivers/video/mb862xx/mb862xxfbdrv.c
drivers/video/modedb.c
drivers/video/msm/mddi.c
drivers/video/msm/mdp.c
drivers/video/mx3fb.c
drivers/video/mxsfb.c
drivers/video/neofb.c
drivers/video/nuc900fb.c
drivers/video/omap/Kconfig
drivers/video/omap/Makefile
drivers/video/omap/lcd_2430sdp.c [deleted file]
drivers/video/omap/lcd_apollon.c [deleted file]
drivers/video/omap/lcd_h4.c [deleted file]
drivers/video/omap/lcd_ldp.c [deleted file]
drivers/video/omap/lcd_omap3beagle.c [deleted file]
drivers/video/omap/lcd_omap3evm.c [deleted file]
drivers/video/omap/lcd_overo.c [deleted file]
drivers/video/omap2/displays/Kconfig
drivers/video/omap2/displays/Makefile
drivers/video/omap2/displays/panel-dvi.c [new file with mode: 0644]
drivers/video/omap2/displays/panel-generic-dpi.c
drivers/video/omap2/displays/panel-n8x0.c [new file with mode: 0644]
drivers/video/omap2/displays/panel-picodlp.c [new file with mode: 0644]
drivers/video/omap2/displays/panel-picodlp.h [new file with mode: 0644]
drivers/video/omap2/displays/panel-taal.c
drivers/video/omap2/dss/Kconfig
drivers/video/omap2/dss/Makefile
drivers/video/omap2/dss/core.c
drivers/video/omap2/dss/dispc.c
drivers/video/omap2/dss/dispc.h
drivers/video/omap2/dss/display.c
drivers/video/omap2/dss/dpi.c
drivers/video/omap2/dss/dsi.c
drivers/video/omap2/dss/dss.c
drivers/video/omap2/dss/dss.h
drivers/video/omap2/dss/dss_features.c
drivers/video/omap2/dss/dss_features.h
drivers/video/omap2/dss/hdmi.c
drivers/video/omap2/dss/hdmi_panel.c [moved from drivers/video/omap2/dss/hdmi_omap4_panel.c with 79% similarity]
drivers/video/omap2/dss/manager.c
drivers/video/omap2/dss/overlay.c
drivers/video/omap2/dss/rfbi.c
drivers/video/omap2/dss/sdi.c
drivers/video/omap2/dss/ti_hdmi.h [new file with mode: 0644]
drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c [new file with mode: 0644]
drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h [moved from drivers/video/omap2/dss/hdmi.h with 54% similarity]
drivers/video/omap2/dss/venc.c
drivers/video/omap2/omapfb/Kconfig
drivers/video/omap2/omapfb/omapfb-main.c
drivers/video/omap2/omapfb/omapfb-sysfs.c
drivers/video/platinumfb.c
drivers/video/pm2fb.c
drivers/video/pm3fb.c
drivers/video/ps3fb.c
drivers/video/pxa3xx-gcu.c
drivers/video/pxafb.c
drivers/video/s3c-fb.c
drivers/video/s3c2410fb.c
drivers/video/s3fb.c
drivers/video/sa1100fb.c
drivers/video/savage/savagefb_driver.c
drivers/video/sh_mobile_hdmi.c
drivers/video/sh_mobile_lcdcfb.c
drivers/video/sh_mobile_lcdcfb.h
drivers/video/sh_mobile_meram.c
drivers/video/sh_mobile_meram.h [deleted file]
drivers/video/sis/sis_main.c
drivers/video/skeletonfb.c
drivers/video/sm501fb.c
drivers/video/smscufx.c [new file with mode: 0644]
drivers/video/tmiofb.c
drivers/video/tridentfb.c
drivers/video/udlfb.c
drivers/video/valkyriefb.c
drivers/video/vfb.c
drivers/video/vga16fb.c
drivers/video/via/dvi.c
drivers/video/via/dvi.h
drivers/video/via/global.c
drivers/video/via/global.h
drivers/video/via/hw.c
drivers/video/via/hw.h
drivers/video/via/lcd.c
drivers/video/via/lcd.h
drivers/video/via/share.h
drivers/video/via/via-core.c
drivers/video/via/via_modesetting.c
drivers/video/via/via_modesetting.h
drivers/video/via/viafbdev.c
drivers/video/via/viamode.c
drivers/video/via/viamode.h
drivers/video/vt8500lcdfb.c
drivers/video/vt8623fb.c
drivers/video/xilinxfb.c
include/linux/fsl-diu-fb.h
include/video/omap-panel-dvi.h [new file with mode: 0644]
include/video/omap-panel-n8x0.h [new file with mode: 0644]
include/video/omap-panel-nokia-dsi.h
include/video/omap-panel-picodlp.h [new file with mode: 0644]
include/video/omapdss.h
include/video/sh_mobile_lcdc.h
include/video/udlfb.h

index 7fdde2a..57d2f29 100644 (file)
@@ -87,23 +87,38 @@ Special configuration for udlfb is usually unnecessary. There are a few
 options, however.
 
 From the command line, pass options to modprobe
-modprobe udlfb defio=1 console=1
+modprobe udlfb fb_defio=0 console=1 shadow=1
 
-Or for permanent option, create file like /etc/modprobe.d/options with text
-options udlfb defio=1 console=1
+Or modify options on the fly at /sys/module/udlfb/parameters directory via
+sudo nano fb_defio
+change the parameter in place, and save the file.
 
-Accepted options:
+Unplug/replug USB device to apply with new settings
+
+Or for permanent option, create file like /etc/modprobe.d/udlfb.conf with text
+options udlfb fb_defio=0 console=1 shadow=1
+
+Accepted boolean options:
 
 fb_defio       Make use of the fb_defio (CONFIG_FB_DEFERRED_IO) kernel
                module to track changed areas of the framebuffer by page faults.
-               Standard fbdev applications that use mmap but that do not
-               report damage, may be able to work with this enabled.
-               Disabled by default because of overhead and other issues.
-
-console                Allow fbcon to attach to udlfb provided framebuffers. This
-               is disabled by default because fbcon will aggressively consume
-               the first framebuffer it finds, which isn't usually what the
-               user wants in the case of USB displays.
+               Standard fbdev applications that use mmap but that do not
+               report damage, should be able to work with this enabled.
+               Disable when running with X server that supports reporting
+               changed regions via ioctl, as this method is simpler,
+               more stable, and higher performance.
+               default: fb_defio=1
+
+console        Allow fbcon to attach to udlfb provided framebuffers.
+               Can be disabled if fbcon and other clients
+               (e.g. X with --shared-vt) are in conflict.
+               default: console=1
+
+shadow         Allocate a 2nd framebuffer to shadow what's currently across
+               the USB bus in device memory. If any pixels are unchanged,
+               do not transmit. Spends host memory to save USB transfers.
+               Enabled by default. Only disable on very low memory systems.
+               default: shadow=1
 
 Sysfs Attributes
 ================
index 07e5dbd..2014c1f 100644 (file)
@@ -5970,6 +5970,12 @@ L:       netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/smsc/smsc9420.*
 
+SMSC UFX6000 and UFX7000 USB to VGA DRIVER
+M:     Steve Glendinning <steve.glendinning@smsc.com>
+L:     linux-fbdev@vger.kernel.org
+S:     Supported
+F:     drivers/video/smscufx.c
+
 SN-IA64 (Itanium) SUB-PLATFORM
 M:     Jes Sorensen <jes@sgi.com>
 L:     linux-altix@sgi.com
index 87f43ad..f8ce84b 100644 (file)
@@ -39,6 +39,9 @@
 #include <plat/usb.h>
 #include <plat/gpmc-smc91x.h>
 
+#include <video/omapdss.h>
+#include <video/omap-panel-generic-dpi.h>
+
 #include "mux.h"
 #include "hsmmc.h"
 #include "common-board-devices.h"
@@ -99,20 +102,72 @@ static struct platform_device sdp2430_flash_device = {
        .resource       = &sdp2430_flash_resource,
 };
 
-static struct platform_device sdp2430_lcd_device = {
-       .name           = "sdp2430_lcd",
-       .id             = -1,
-};
-
 static struct platform_device *sdp2430_devices[] __initdata = {
        &sdp2430_flash_device,
+};
+
+/* LCD */
+#define SDP2430_LCD_PANEL_BACKLIGHT_GPIO       91
+#define SDP2430_LCD_PANEL_ENABLE_GPIO          154
+
+static int sdp2430_panel_enable_lcd(struct omap_dss_device *dssdev)
+{
+       gpio_direction_output(SDP2430_LCD_PANEL_ENABLE_GPIO, 1);
+       gpio_direction_output(SDP2430_LCD_PANEL_BACKLIGHT_GPIO, 1);
+
+       return 0;
+}
+
+static void sdp2430_panel_disable_lcd(struct omap_dss_device *dssdev)
+{
+       gpio_direction_output(SDP2430_LCD_PANEL_ENABLE_GPIO, 0);
+       gpio_direction_output(SDP2430_LCD_PANEL_BACKLIGHT_GPIO, 0);
+}
+
+static struct panel_generic_dpi_data sdp2430_panel_data = {
+       .name                   = "nec_nl2432dr22-11b",
+       .platform_enable        = sdp2430_panel_enable_lcd,
+       .platform_disable       = sdp2430_panel_disable_lcd,
+};
+
+static struct omap_dss_device sdp2430_lcd_device = {
+       .name                   = "lcd",
+       .driver_name            = "generic_dpi_panel",
+       .type                   = OMAP_DISPLAY_TYPE_DPI,
+       .phy.dpi.data_lines     = 16,
+       .data                   = &sdp2430_panel_data,
+};
+
+static struct omap_dss_device *sdp2430_dss_devices[] = {
        &sdp2430_lcd_device,
 };
 
-static struct omap_lcd_config sdp2430_lcd_config __initdata = {
-       .ctrl_name      = "internal",
+static struct omap_dss_board_info sdp2430_dss_data = {
+       .num_devices    = ARRAY_SIZE(sdp2430_dss_devices),
+       .devices        = sdp2430_dss_devices,
+       .default_device = &sdp2430_lcd_device,
 };
 
+static void __init sdp2430_display_init(void)
+{
+       int r;
+
+       static struct gpio gpios[] __initdata = {
+               { SDP2430_LCD_PANEL_ENABLE_GPIO, GPIOF_OUT_INIT_LOW,
+                       "LCD reset" },
+               { SDP2430_LCD_PANEL_BACKLIGHT_GPIO, GPIOF_OUT_INIT_LOW,
+                       "LCD Backlight" },
+       };
+
+       r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
+       if (r) {
+               pr_err("Cannot request LCD GPIOs, error %d\n", r);
+               return;
+       }
+
+       omap_display_init(&sdp2430_dss_data);
+}
+
 #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91x_MODULE)
 
 static struct omap_smc91x_platform_data board_smc91x_data = {
@@ -137,10 +192,6 @@ static inline void board_smc91x_init(void)
 
 #endif
 
-static struct omap_board_config_kernel sdp2430_config[] __initdata = {
-       {OMAP_TAG_LCD, &sdp2430_lcd_config},
-};
-
 static void __init omap_2430sdp_init_early(void)
 {
        omap2_init_common_infrastructure();
@@ -229,9 +280,6 @@ static void __init omap_2430sdp_init(void)
 {
        omap2430_mux_init(board_mux, OMAP_PACKAGE_ZAC);
 
-       omap_board_config = sdp2430_config;
-       omap_board_config_size = ARRAY_SIZE(sdp2430_config);
-
        omap2430_i2c_init();
 
        platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices));
@@ -247,6 +295,8 @@ static void __init omap_2430sdp_init(void)
        /* Turn off secondary LCD backlight */
        gpio_request_one(SECONDARY_LCD_GPIO, GPIOF_OUT_INIT_LOW,
                         "Secondary LCD backlight");
+
+       sdp2430_display_init();
 }
 
 static void __init omap_2430sdp_map_io(void)
index 2430531..204bedd 100644 (file)
@@ -37,7 +37,7 @@
 #include <plat/dma.h>
 #include <plat/gpmc.h>
 #include <video/omapdss.h>
-#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 
 #include <plat/gpmc-smc91x.h>
 
@@ -186,8 +186,7 @@ static struct omap_dss_device sdp3430_lcd_device = {
        .platform_disable       = sdp3430_panel_disable_lcd,
 };
 
-static struct panel_generic_dpi_data dvi_panel = {
-       .name                   = "generic",
+static struct panel_dvi_platform_data dvi_panel = {
        .platform_enable        = sdp3430_panel_enable_dvi,
        .platform_disable       = sdp3430_panel_disable_dvi,
 };
@@ -195,7 +194,7 @@ static struct panel_generic_dpi_data dvi_panel = {
 static struct omap_dss_device sdp3430_dvi_device = {
        .name                   = "dvi",
        .type                   = OMAP_DISPLAY_TYPE_DPI,
-       .driver_name            = "generic_dpi_panel",
+       .driver_name            = "dvi",
        .data                   = &dvi_panel,
        .phy.dpi.data_lines     = 24,
 };
index be93110..484cec5 100644 (file)
@@ -38,6 +38,8 @@
 #include <plat/mmc.h>
 #include <plat/omap4-keypad.h>
 #include <video/omapdss.h>
+#include <video/omap-panel-nokia-dsi.h>
+#include <video/omap-panel-picodlp.h>
 #include <linux/wl12xx.h>
 
 #include "mux.h"
@@ -52,6 +54,8 @@
 #define OMAP4_SFH7741_ENABLE_GPIO              188
 #define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */
 #define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
+#define DISPLAY_SEL_GPIO       59      /* LCD2/PicoDLP switch */
+#define DLP_POWER_ON_GPIO      40
 
 #define GPIO_WIFI_PMENA                54
 #define GPIO_WIFI_IRQ          53
@@ -340,11 +344,6 @@ static int __init omap_ethernet_init(void)
        return status;
 }
 
-static struct platform_device sdp4430_lcd_device = {
-       .name           = "sdp4430_lcd",
-       .id             = -1,
-};
-
 static struct regulator_consumer_supply sdp4430_vbat_supply[] = {
        REGULATOR_SUPPLY("vddvibl", "twl6040-vibra"),
        REGULATOR_SUPPLY("vddvibr", "twl6040-vibra"),
@@ -374,21 +373,12 @@ static struct platform_device sdp4430_vbat = {
 };
 
 static struct platform_device *sdp4430_devices[] __initdata = {
-       &sdp4430_lcd_device,
        &sdp4430_gpio_keys_device,
        &sdp4430_leds_gpio,
        &sdp4430_leds_pwm,
        &sdp4430_vbat,
 };
 
-static struct omap_lcd_config sdp4430_lcd_config __initdata = {
-       .ctrl_name      = "internal",
-};
-
-static struct omap_board_config_kernel sdp4430_config[] __initdata = {
-       { OMAP_TAG_LCD,         &sdp4430_lcd_config },
-};
-
 static void __init omap_4430sdp_init_early(void)
 {
        omap2_init_common_infrastructure();
@@ -648,37 +638,202 @@ static void sdp4430_panel_disable_hdmi(struct omap_dss_device *dssdev)
        gpio_free(HDMI_GPIO_HPD);
 }
 
-static struct omap_dss_device sdp4430_hdmi_device = {
-       .name = "hdmi",
-       .driver_name = "hdmi_panel",
-       .type = OMAP_DISPLAY_TYPE_HDMI,
-       .clocks = {
-               .dispc  = {
+static struct nokia_dsi_panel_data dsi1_panel = {
+               .name           = "taal",
+               .reset_gpio     = 102,
+               .use_ext_te     = false,
+               .ext_te_gpio    = 101,
+               .esd_interval   = 0,
+};
+
+static struct omap_dss_device sdp4430_lcd_device = {
+       .name                   = "lcd",
+       .driver_name            = "taal",
+       .type                   = OMAP_DISPLAY_TYPE_DSI,
+       .data                   = &dsi1_panel,
+       .phy.dsi                = {
+               .clk_lane       = 1,
+               .clk_pol        = 0,
+               .data1_lane     = 2,
+               .data1_pol      = 0,
+               .data2_lane     = 3,
+               .data2_pol      = 0,
+
+               .module         = 0,
+       },
+
+       .clocks = {
+               .dispc = {
+                       .channel = {
+                               /* Logic Clock = 172.8 MHz */
+                               .lck_div        = 1,
+                               /* Pixel Clock = 34.56 MHz */
+                               .pck_div        = 5,
+                               .lcd_clk_src    = OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC,
+                       },
                        .dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK,
                },
-               .hdmi   = {
-                       .regn   = 15,
-                       .regm2  = 1,
+
+               .dsi = {
+                       .regn           = 16,   /* Fint = 2.4 MHz */
+                       .regm           = 180,  /* DDR Clock = 216 MHz */
+                       .regm_dispc     = 5,    /* PLL1_CLK1 = 172.8 MHz */
+                       .regm_dsi       = 5,    /* PLL1_CLK2 = 172.8 MHz */
+
+                       .lp_clk_div     = 10,   /* LP Clock = 8.64 MHz */
+                       .dsi_fclk_src   = OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI,
+               },
+       },
+       .channel                = OMAP_DSS_CHANNEL_LCD,
+};
+
+static struct nokia_dsi_panel_data dsi2_panel = {
+               .name           = "taal",
+               .reset_gpio     = 104,
+               .use_ext_te     = false,
+               .ext_te_gpio    = 103,
+               .esd_interval   = 0,
+};
+
+static struct omap_dss_device sdp4430_lcd2_device = {
+       .name                   = "lcd2",
+       .driver_name            = "taal",
+       .type                   = OMAP_DISPLAY_TYPE_DSI,
+       .data                   = &dsi2_panel,
+       .phy.dsi                = {
+               .clk_lane       = 1,
+               .clk_pol        = 0,
+               .data1_lane     = 2,
+               .data1_pol      = 0,
+               .data2_lane     = 3,
+               .data2_pol      = 0,
+
+               .module         = 1,
+       },
+
+       .clocks = {
+               .dispc = {
+                       .channel = {
+                               /* Logic Clock = 172.8 MHz */
+                               .lck_div        = 1,
+                               /* Pixel Clock = 34.56 MHz */
+                               .pck_div        = 5,
+                               .lcd_clk_src    = OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC,
+                       },
+                       .dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK,
+               },
+
+               .dsi = {
+                       .regn           = 16,   /* Fint = 2.4 MHz */
+                       .regm           = 180,  /* DDR Clock = 216 MHz */
+                       .regm_dispc     = 5,    /* PLL1_CLK1 = 172.8 MHz */
+                       .regm_dsi       = 5,    /* PLL1_CLK2 = 172.8 MHz */
+
+                       .lp_clk_div     = 10,   /* LP Clock = 8.64 MHz */
+                       .dsi_fclk_src   = OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI,
                },
        },
+       .channel                = OMAP_DSS_CHANNEL_LCD2,
+};
+
+static void sdp4430_lcd_init(void)
+{
+       int r;
+
+       r = gpio_request_one(dsi1_panel.reset_gpio, GPIOF_DIR_OUT,
+               "lcd1_reset_gpio");
+       if (r)
+               pr_err("%s: Could not get lcd1_reset_gpio\n", __func__);
+
+       r = gpio_request_one(dsi2_panel.reset_gpio, GPIOF_DIR_OUT,
+               "lcd2_reset_gpio");
+       if (r)
+               pr_err("%s: Could not get lcd2_reset_gpio\n", __func__);
+}
+
+static struct omap_dss_device sdp4430_hdmi_device = {
+       .name = "hdmi",
+       .driver_name = "hdmi_panel",
+       .type = OMAP_DISPLAY_TYPE_HDMI,
        .platform_enable = sdp4430_panel_enable_hdmi,
        .platform_disable = sdp4430_panel_disable_hdmi,
        .channel = OMAP_DSS_CHANNEL_DIGIT,
 };
 
+static struct picodlp_panel_data sdp4430_picodlp_pdata = {
+       .picodlp_adapter_id     = 2,
+       .emu_done_gpio          = 44,
+       .pwrgood_gpio           = 45,
+};
+
+static void sdp4430_picodlp_init(void)
+{
+       int r;
+       const struct gpio picodlp_gpios[] = {
+               {DLP_POWER_ON_GPIO, GPIOF_OUT_INIT_LOW,
+                       "DLP POWER ON"},
+               {sdp4430_picodlp_pdata.emu_done_gpio, GPIOF_IN,
+                       "DLP EMU DONE"},
+               {sdp4430_picodlp_pdata.pwrgood_gpio, GPIOF_OUT_INIT_LOW,
+                       "DLP PWRGOOD"},
+       };
+
+       r = gpio_request_array(picodlp_gpios, ARRAY_SIZE(picodlp_gpios));
+       if (r)
+               pr_err("Cannot request PicoDLP GPIOs, error %d\n", r);
+}
+
+static int sdp4430_panel_enable_picodlp(struct omap_dss_device *dssdev)
+{
+       gpio_set_value(DISPLAY_SEL_GPIO, 0);
+       gpio_set_value(DLP_POWER_ON_GPIO, 1);
+
+       return 0;
+}
+
+static void sdp4430_panel_disable_picodlp(struct omap_dss_device *dssdev)
+{
+       gpio_set_value(DLP_POWER_ON_GPIO, 0);
+       gpio_set_value(DISPLAY_SEL_GPIO, 1);
+}
+
+static struct omap_dss_device sdp4430_picodlp_device = {
+       .name                   = "picodlp",
+       .driver_name            = "picodlp_panel",
+       .type                   = OMAP_DISPLAY_TYPE_DPI,
+       .phy.dpi.data_lines     = 24,
+       .channel                = OMAP_DSS_CHANNEL_LCD2,
+       .platform_enable        = sdp4430_panel_enable_picodlp,
+       .platform_disable       = sdp4430_panel_disable_picodlp,
+       .data                   = &sdp4430_picodlp_pdata,
+};
+
 static struct omap_dss_device *sdp4430_dss_devices[] = {
+       &sdp4430_lcd_device,
+       &sdp4430_lcd2_device,
        &sdp4430_hdmi_device,
+       &sdp4430_picodlp_device,
 };
 
 static struct omap_dss_board_info sdp4430_dss_data = {
        .num_devices    = ARRAY_SIZE(sdp4430_dss_devices),
        .devices        = sdp4430_dss_devices,
-       .default_device = &sdp4430_hdmi_device,
+       .default_device = &sdp4430_lcd_device,
 };
 
-void omap_4430sdp_display_init(void)
+static void omap_4430sdp_display_init(void)
 {
+       int r;
+
+       /* Enable LCD2 by default (instead of Pico DLP) */
+       r = gpio_request_one(DISPLAY_SEL_GPIO, GPIOF_OUT_INIT_HIGH,
+                       "display_sel");
+       if (r)
+               pr_err("%s: Could not get display_sel GPIO\n", __func__);
+
+       sdp4430_lcd_init();
        sdp4430_hdmi_mux_init();
+       sdp4430_picodlp_init();
        omap_display_init(&sdp4430_dss_data);
 }
 
@@ -802,9 +957,6 @@ static void __init omap_4430sdp_init(void)
                package = OMAP_PACKAGE_CBL;
        omap4_mux_init(board_mux, NULL, package);
 
-       omap_board_config = sdp4430_config;
-       omap_board_config_size = ARRAY_SIZE(sdp4430_config);
-
        omap4_i2c_init();
        omap_sfh7741prox_init();
        platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices));
index 1325085..ab10f75 100644 (file)
@@ -36,6 +36,7 @@
 #include <plat/usb.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 
 #include "mux.h"
 #include "control.h"
@@ -333,8 +334,7 @@ static void am3517_evm_panel_disable_dvi(struct omap_dss_device *dssdev)
        dvi_enabled = 0;
 }
 
-static struct panel_generic_dpi_data dvi_panel = {
-       .name                   = "generic",
+static struct panel_dvi_platform_data dvi_panel = {
        .platform_enable        = am3517_evm_panel_enable_dvi,
        .platform_disable       = am3517_evm_panel_disable_dvi,
 };
@@ -342,7 +342,7 @@ static struct panel_generic_dpi_data dvi_panel = {
 static struct omap_dss_device am3517_evm_dvi_device = {
        .type                   = OMAP_DISPLAY_TYPE_DPI,
        .name                   = "dvi",
-       .driver_name            = "generic_dpi_panel",
+       .driver_name            = "dvi",
        .data                   = &dvi_panel,
        .phy.dpi.data_lines     = 24,
 };
index 67800e6..ad55351 100644 (file)
@@ -40,6 +40,9 @@
 #include <plat/common.h>
 #include <plat/gpmc.h>
 
+#include <video/omapdss.h>
+#include <video/omap-panel-generic-dpi.h>
+
 #include "mux.h"
 #include "control.h"
 
@@ -149,11 +152,6 @@ static struct platform_device apollon_smc91x_device = {
        .resource       = apollon_smc91x_resources,
 };
 
-static struct platform_device apollon_lcd_device = {
-       .name           = "apollon_lcd",
-       .id             = -1,
-};
-
 static struct omap_led_config apollon_led_config[] = {
        {
                .cdev   = {
@@ -191,7 +189,6 @@ static struct platform_device apollon_led_device = {
 static struct platform_device *apollon_devices[] __initdata = {
        &apollon_onenand_device,
        &apollon_smc91x_device,
-       &apollon_lcd_device,
        &apollon_led_device,
 };
 
@@ -265,12 +262,26 @@ static struct omap_usb_config apollon_usb_config __initdata = {
        .pins[0]        = 6,
 };
 
-static struct omap_lcd_config apollon_lcd_config __initdata = {
-       .ctrl_name      = "internal",
+static struct panel_generic_dpi_data apollon_panel_data = {
+       .name                   = "apollon",
 };
 
-static struct omap_board_config_kernel apollon_config[] __initdata = {
-       { OMAP_TAG_LCD,         &apollon_lcd_config },
+static struct omap_dss_device apollon_lcd_device = {
+       .name                   = "lcd",
+       .driver_name            = "generic_dpi_panel",
+       .type                   = OMAP_DISPLAY_TYPE_DPI,
+       .phy.dpi.data_lines     = 18,
+       .data                   = &apollon_panel_data,
+};
+
+static struct omap_dss_device *apollon_dss_devices[] = {
+       &apollon_lcd_device,
+};
+
+static struct omap_dss_board_info apollon_dss_data = {
+       .num_devices    = ARRAY_SIZE(apollon_dss_devices),
+       .devices        = apollon_dss_devices,
+       .default_device = &apollon_lcd_device,
 };
 
 static void __init omap_apollon_init_early(void)
@@ -314,8 +325,6 @@ static void __init omap_apollon_init(void)
        u32 v;
 
        omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAC);
-       omap_board_config = apollon_config;
-       omap_board_config_size = ARRAY_SIZE(apollon_config);
 
        apollon_init_smc91x();
        apollon_led_init();
@@ -340,6 +349,8 @@ static void __init omap_apollon_init(void)
         */
        platform_add_devices(apollon_devices, ARRAY_SIZE(apollon_devices));
        omap_serial_init();
+
+       omap_display_init(&apollon_dss_data);
 }
 
 static void __init omap_apollon_map_io(void)
index 38179c1..6e0f0d2 100644 (file)
@@ -43,6 +43,7 @@
 #include <plat/usb.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 #include <plat/mcspi.h>
 
 #include <mach/hardware.h>
@@ -242,8 +243,7 @@ static struct omap_dss_device cm_t35_lcd_device = {
        .phy.dpi.data_lines     = 18,
 };
 
-static struct panel_generic_dpi_data dvi_panel = {
-       .name                   = "generic",
+static struct panel_dvi_platform_data dvi_panel = {
        .platform_enable        = cm_t35_panel_enable_dvi,
        .platform_disable       = cm_t35_panel_disable_dvi,
 };
@@ -251,7 +251,7 @@ static struct panel_generic_dpi_data dvi_panel = {
 static struct omap_dss_device cm_t35_dvi_device = {
        .name                   = "dvi",
        .type                   = OMAP_DISPLAY_TYPE_DPI,
-       .driver_name            = "generic_dpi_panel",
+       .driver_name            = "dvi",
        .data                   = &dvi_panel,
        .phy.dpi.data_lines     = 24,
 };
index 99a4243..d9bfe54 100644 (file)
@@ -47,6 +47,7 @@
 #include <plat/usb.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 
 #include <plat/mcspi.h>
 #include <linux/input/matrix_keypad.h>
@@ -139,7 +140,7 @@ static struct regulator_consumer_supply devkit8000_vio_supply[] = {
 };
 
 static struct panel_generic_dpi_data lcd_panel = {
-       .name                   = "generic",
+       .name                   = "innolux_at070tn83",
        .platform_enable        = devkit8000_panel_enable_lcd,
        .platform_disable       = devkit8000_panel_disable_lcd,
 };
@@ -152,8 +153,7 @@ static struct omap_dss_device devkit8000_lcd_device = {
        .phy.dpi.data_lines     = 24,
 };
 
-static struct panel_generic_dpi_data dvi_panel = {
-       .name                   = "generic",
+static struct panel_dvi_platform_data dvi_panel = {
        .platform_enable        = devkit8000_panel_enable_dvi,
        .platform_disable       = devkit8000_panel_disable_dvi,
 };
@@ -161,7 +161,7 @@ static struct panel_generic_dpi_data dvi_panel = {
 static struct omap_dss_device devkit8000_dvi_device = {
        .name                   = "dvi",
        .type                   = OMAP_DISPLAY_TYPE_DPI,
-       .driver_name            = "generic_dpi_panel",
+       .driver_name            = "dvi",
        .data                   = &dvi_panel,
        .phy.dpi.data_lines     = 24,
 };
@@ -267,7 +267,7 @@ static struct twl4030_gpio_platform_data devkit8000_gpio_data = {
 
 static struct regulator_consumer_supply devkit8000_vpll1_supplies[] = {
        REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
-       REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+       REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"),
 };
 
 /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
index 82421a4..8fcf796 100644 (file)
@@ -39,6 +39,9 @@
 #include <plat/dma.h>
 #include <plat/gpmc.h>
 
+#include <video/omapdss.h>
+#include <video/omap-panel-generic-dpi.h>
+
 #include "mux.h"
 #include "control.h"
 
@@ -156,17 +159,33 @@ static struct platform_device h4_kp_device = {
        },
 };
 
-static struct platform_device h4_lcd_device = {
-       .name           = "lcd_h4",
-       .id             = -1,
-};
-
 static struct platform_device *h4_devices[] __initdata = {
        &h4_flash_device,
        &h4_kp_device,
+};
+
+static struct panel_generic_dpi_data h4_panel_data = {
+       .name                   = "h4",
+};
+
+static struct omap_dss_device h4_lcd_device = {
+       .name                   = "lcd",
+       .driver_name            = "generic_dpi_panel",
+       .type                   = OMAP_DISPLAY_TYPE_DPI,
+       .phy.dpi.data_lines     = 16,
+       .data                   = &h4_panel_data,
+};
+
+static struct omap_dss_device *h4_dss_devices[] = {
        &h4_lcd_device,
 };
 
+static struct omap_dss_board_info h4_dss_data = {
+       .num_devices    = ARRAY_SIZE(h4_dss_devices),
+       .devices        = h4_dss_devices,
+       .default_device = &h4_lcd_device,
+};
+
 /* 2420 Sysboot setup (2430 is different) */
 static u32 get_sysboot_value(void)
 {
@@ -270,10 +289,6 @@ static void __init h4_init_flash(void)
        h4_flash_resource.end   = base + SZ_64M - 1;
 }
 
-static struct omap_lcd_config h4_lcd_config __initdata = {
-       .ctrl_name      = "internal",
-};
-
 static struct omap_usb_config h4_usb_config __initdata = {
        /* S1.10 OFF -- usb "download port"
         * usb0 switched to Mini-B port and isp1105 transceiver;
@@ -285,10 +300,6 @@ static struct omap_usb_config h4_usb_config __initdata = {
        .hmc_mode       = 0x00,         /* 0:dev|otg 1:disable 2:disable */
 };
 
-static struct omap_board_config_kernel h4_config[] __initdata = {
-       { OMAP_TAG_LCD,         &h4_lcd_config },
-};
-
 static void __init omap_h4_init_early(void)
 {
        omap2_init_common_infrastructure();
@@ -330,9 +341,6 @@ static void __init omap_h4_init(void)
 {
        omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAF);
 
-       omap_board_config = h4_config;
-       omap_board_config_size = ARRAY_SIZE(h4_config);
-
        /*
         * Make sure the serial ports are muxed on at this point.
         * You have to mux them off in device drivers later on
@@ -371,6 +379,8 @@ static void __init omap_h4_init(void)
        omap2_usbfs_init(&h4_usb_config);
        omap_serial_init();
        h4_init_flash();
+
+       omap_display_init(&h4_dss_data);
 }
 
 static void __init omap_h4_map_io(void)
index 7040352..96f9ef3 100644 (file)
@@ -32,7 +32,7 @@
 #include <plat/gpmc.h>
 #include <plat/usb.h>
 #include <video/omapdss.h>
-#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 #include <plat/onenand.h>
 
 #include "mux.h"
@@ -455,16 +455,16 @@ static void igep2_disable_dvi(struct omap_dss_device *dssdev)
        gpio_direction_output(IGEP2_GPIO_DVI_PUP, 0);
 }
 
-static struct panel_generic_dpi_data dvi_panel = {
-       .name                   = "generic",
+static struct panel_dvi_platform_data dvi_panel = {
        .platform_enable        = igep2_enable_dvi,
        .platform_disable       = igep2_disable_dvi,
+       .i2c_bus_num = 3,
 };
 
 static struct omap_dss_device igep2_dvi_device = {
        .type                   = OMAP_DISPLAY_TYPE_DPI,
        .name                   = "dvi",
-       .driver_name            = "generic_dpi_panel",
+       .driver_name            = "dvi",
        .data                   = &dvi_panel,
        .phy.dpi.data_lines     = 24,
 };
index abe8c7e..f8f8a68 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/io.h>
 #include <linux/smsc911x.h>
 #include <linux/mmc/host.h>
+#include <linux/gpio.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -43,6 +44,9 @@
 #include <plat/usb.h>
 #include <plat/gpmc-smsc911x.h>
 
+#include <video/omapdss.h>
+#include <video/omap-panel-generic-dpi.h>
+
 #include "board-flash.h"
 #include "mux.h"
 #include "hsmmc.h"
@@ -179,29 +183,108 @@ static inline void __init ldp_init_smsc911x(void)
        gpmc_smsc911x_init(&smsc911x_cfg);
 }
 
-static struct platform_device ldp_lcd_device = {
-       .name           = "ldp_lcd",
-       .id             = -1,
+/* LCD */
+
+static int ldp_backlight_gpio;
+static int ldp_lcd_enable_gpio;
+
+#define LCD_PANEL_RESET_GPIO           55
+#define LCD_PANEL_QVGA_GPIO            56
+
+static int ldp_panel_enable_lcd(struct omap_dss_device *dssdev)
+{
+       if (gpio_is_valid(ldp_lcd_enable_gpio))
+               gpio_direction_output(ldp_lcd_enable_gpio, 1);
+       if (gpio_is_valid(ldp_backlight_gpio))
+               gpio_direction_output(ldp_backlight_gpio, 1);
+
+       return 0;
+}
+
+static void ldp_panel_disable_lcd(struct omap_dss_device *dssdev)
+{
+       if (gpio_is_valid(ldp_lcd_enable_gpio))
+               gpio_direction_output(ldp_lcd_enable_gpio, 0);
+       if (gpio_is_valid(ldp_backlight_gpio))
+               gpio_direction_output(ldp_backlight_gpio, 0);
+}
+
+static struct panel_generic_dpi_data ldp_panel_data = {
+       .name                   = "nec_nl2432dr22-11b",
+       .platform_enable        = ldp_panel_enable_lcd,
+       .platform_disable       = ldp_panel_disable_lcd,
 };
 
-static struct omap_lcd_config ldp_lcd_config __initdata = {
-       .ctrl_name      = "internal",
+static struct omap_dss_device ldp_lcd_device = {
+       .name                   = "lcd",
+       .driver_name            = "generic_dpi_panel",
+       .type                   = OMAP_DISPLAY_TYPE_DPI,
+       .phy.dpi.data_lines     = 18,
+       .data                   = &ldp_panel_data,
+};
+
+static struct omap_dss_device *ldp_dss_devices[] = {
+       &ldp_lcd_device,
 };
 
-static struct omap_board_config_kernel ldp_config[] __initdata = {
-       { OMAP_TAG_LCD,         &ldp_lcd_config },
+static struct omap_dss_board_info ldp_dss_data = {
+       .num_devices    = ARRAY_SIZE(ldp_dss_devices),
+       .devices        = ldp_dss_devices,
+       .default_device = &ldp_lcd_device,
 };
 
+static void __init ldp_display_init(void)
+{
+       int r;
+
+       static struct gpio gpios[] __initdata = {
+               {LCD_PANEL_RESET_GPIO, GPIOF_OUT_INIT_HIGH, "LCD RESET"},
+               {LCD_PANEL_QVGA_GPIO, GPIOF_OUT_INIT_HIGH, "LCD QVGA"},
+       };
+
+       r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
+       if (r) {
+               pr_err("Cannot request LCD GPIOs, error %d\n", r);
+               return;
+       }
+
+       omap_display_init(&ldp_dss_data);
+}
+
 static void __init omap_ldp_init_early(void)
 {
        omap2_init_common_infrastructure();
        omap2_init_common_devices(NULL, NULL);
 }
 
+static int ldp_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio)
+{
+       int r;
+
+       struct gpio gpios[] = {
+               {gpio + 7 , GPIOF_OUT_INIT_LOW, "LCD ENABLE"},
+               {gpio + 15, GPIOF_OUT_INIT_LOW, "LCD BACKLIGHT"},
+       };
+
+       r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
+       if (r) {
+               pr_err("Cannot request LCD GPIOs, error %d\n", r);
+               ldp_backlight_gpio = -EINVAL;
+               ldp_lcd_enable_gpio = -EINVAL;
+               return r;
+       }
+
+       ldp_backlight_gpio = gpio + 15;
+       ldp_lcd_enable_gpio = gpio + 7;
+
+       return 0;
+}
+
 static struct twl4030_gpio_platform_data ldp_gpio_data = {
        .gpio_base      = OMAP_MAX_GPIO_LINES,
        .irq_base       = TWL4030_GPIO_IRQ_BASE,
        .irq_end        = TWL4030_GPIO_IRQ_END,
+       .setup          = ldp_twl_gpio_setup,
 };
 
 static struct regulator_consumer_supply ldp_vmmc1_supply[] = {
@@ -243,10 +326,31 @@ static struct regulator_init_data ldp_vaux1 = {
        .consumer_supplies              = ldp_vaux1_supplies,
 };
 
+static struct regulator_consumer_supply ldp_vpll2_supplies[] = {
+       REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+       REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+};
+
+static struct regulator_init_data ldp_vpll2 = {
+       .constraints = {
+               .name                   = "VDVI",
+               .min_uV                 = 1800000,
+               .max_uV                 = 1800000,
+               .apply_uV               = true,
+               .valid_modes_mask       = REGULATOR_MODE_NORMAL
+                                       | REGULATOR_MODE_STANDBY,
+               .valid_ops_mask         = REGULATOR_CHANGE_MODE
+                                       | REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(ldp_vpll2_supplies),
+       .consumer_supplies      = ldp_vpll2_supplies,
+};
+
 static struct twl4030_platform_data ldp_twldata = {
        /* platform_data for children goes here */
        .vmmc1          = &ldp_vmmc1,
        .vaux1          = &ldp_vaux1,
+       .vpll2          = &ldp_vpll2,
        .gpio           = &ldp_gpio_data,
        .keypad         = &ldp_kp_twl4030_data,
 };
@@ -272,7 +376,6 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
 };
 
 static struct platform_device *ldp_devices[] __initdata = {
-       &ldp_lcd_device,
        &ldp_gpio_keys_device,
 };
 
@@ -317,8 +420,6 @@ static struct mtd_partition ldp_nand_partitions[] = {
 static void __init omap_ldp_init(void)
 {
        omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
-       omap_board_config = ldp_config;
-       omap_board_config_size = ARRAY_SIZE(ldp_config);
        ldp_init_smsc911x();
        omap_i2c_init();
        platform_add_devices(ldp_devices, ARRAY_SIZE(ldp_devices));
@@ -329,6 +430,7 @@ static void __init omap_ldp_init(void)
                ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0);
 
        omap2_hsmmc_init(mmc);
+       ldp_display_init();
 }
 
 MACHINE_START(OMAP_LDP, "OMAP LDP board")
index 1fde8a0..928933b 100644 (file)
@@ -42,7 +42,7 @@
 #include <plat/board.h>
 #include <plat/common.h>
 #include <video/omapdss.h>
-#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 #include <plat/gpmc.h>
 #include <plat/nand.h>
 #include <plat/usb.h>
@@ -203,16 +203,16 @@ static void beagle_disable_dvi(struct omap_dss_device *dssdev)
                gpio_set_value(dssdev->reset_gpio, 0);
 }
 
-static struct panel_generic_dpi_data dvi_panel = {
-       .name = "generic",
+static struct panel_dvi_platform_data dvi_panel = {
        .platform_enable = beagle_enable_dvi,
        .platform_disable = beagle_disable_dvi,
+       .i2c_bus_num = 3,
 };
 
 static struct omap_dss_device beagle_dvi_device = {
        .type = OMAP_DISPLAY_TYPE_DPI,
        .name = "dvi",
-       .driver_name = "generic_dpi_panel",
+       .driver_name = "dvi",
        .data = &dvi_panel,
        .phy.dpi.data_lines = 24,
        .reset_gpio = -EINVAL,
index 15c69a0..0d5a9e4 100644 (file)
@@ -45,7 +45,7 @@
 #include <plat/common.h>
 #include <plat/mcspi.h>
 #include <video/omapdss.h>
-#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 
 #include "mux.h"
 #include "sdram-micron-mt46h32m32lf-6.h"
@@ -247,8 +247,7 @@ static void omap3_evm_disable_dvi(struct omap_dss_device *dssdev)
        dvi_enabled = 0;
 }
 
-static struct panel_generic_dpi_data dvi_panel = {
-       .name                   = "generic",
+static struct panel_dvi_platform_data dvi_panel = {
        .platform_enable        = omap3_evm_enable_dvi,
        .platform_disable       = omap3_evm_disable_dvi,
 };
@@ -256,7 +255,7 @@ static struct panel_generic_dpi_data dvi_panel = {
 static struct omap_dss_device omap3_evm_dvi_device = {
        .name                   = "dvi",
        .type                   = OMAP_DISPLAY_TYPE_DPI,
-       .driver_name            = "generic_dpi_panel",
+       .driver_name            = "dvi",
        .data                   = &dvi_panel,
        .phy.dpi.data_lines     = 24,
 };
index ace5693..cca523e 100644 (file)
@@ -335,7 +335,7 @@ static struct regulator_consumer_supply pandora_vmmc3_supply[] = {
 static struct regulator_consumer_supply pandora_vdds_supplies[] = {
        REGULATOR_SUPPLY("vdds_sdi", "omapdss"),
        REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
-       REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+       REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"),
 };
 
 static struct regulator_consumer_supply pandora_vcc_lcd_supply[] = {
index ba13e1d..4732589 100644 (file)
@@ -41,6 +41,7 @@
 #include <plat/usb.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 
 #include <plat/mcspi.h>
 #include <linux/input/matrix_keypad.h>
@@ -107,39 +108,6 @@ static void __init omap3_stalker_display_init(void)
        return;
 }
 
-static int omap3_stalker_enable_lcd(struct omap_dss_device *dssdev)
-{
-       if (dvi_enabled) {
-               printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
-               return -EINVAL;
-       }
-       gpio_set_value(DSS_ENABLE_GPIO, 1);
-       gpio_set_value(LCD_PANEL_BKLIGHT_GPIO, 1);
-       lcd_enabled = 1;
-       return 0;
-}
-
-static void omap3_stalker_disable_lcd(struct omap_dss_device *dssdev)
-{
-       gpio_set_value(DSS_ENABLE_GPIO, 0);
-       gpio_set_value(LCD_PANEL_BKLIGHT_GPIO, 0);
-       lcd_enabled = 0;
-}
-
-static struct panel_generic_dpi_data lcd_panel = {
-       .name                   = "generic",
-       .platform_enable        = omap3_stalker_enable_lcd,
-       .platform_disable       = omap3_stalker_disable_lcd,
-};
-
-static struct omap_dss_device omap3_stalker_lcd_device = {
-       .name                   = "lcd",
-       .driver_name            = "generic_dpi_panel",
-       .data                   = &lcd_panel,
-       .phy.dpi.data_lines     = 24,
-       .type                   = OMAP_DISPLAY_TYPE_DPI,
-};
-
 static int omap3_stalker_enable_tv(struct omap_dss_device *dssdev)
 {
        return 0;
@@ -179,8 +147,7 @@ static void omap3_stalker_disable_dvi(struct omap_dss_device *dssdev)
        dvi_enabled = 0;
 }
 
-static struct panel_generic_dpi_data dvi_panel = {
-       .name                   = "generic",
+static struct panel_dvi_platform_data dvi_panel = {
        .platform_enable        = omap3_stalker_enable_dvi,
        .platform_disable       = omap3_stalker_disable_dvi,
 };
@@ -188,13 +155,12 @@ static struct panel_generic_dpi_data dvi_panel = {
 static struct omap_dss_device omap3_stalker_dvi_device = {
        .name                   = "dvi",
        .type                   = OMAP_DISPLAY_TYPE_DPI,
-       .driver_name            = "generic_dpi_panel",
+       .driver_name            = "dvi",
        .data                   = &dvi_panel,
        .phy.dpi.data_lines     = 24,
 };
 
 static struct omap_dss_device *omap3_stalker_dss_devices[] = {
-       &omap3_stalker_lcd_device,
        &omap3_stalker_tv_device,
        &omap3_stalker_dvi_device,
 };
index 49e4bd2..abb6891 100644 (file)
@@ -104,15 +104,6 @@ static struct omap2_hsmmc_info mmc[] = {
        {}      /* Terminator */
 };
 
-static struct platform_device omap3_touchbook_lcd_device = {
-       .name           = "omap3touchbook_lcd",
-       .id             = -1,
-};
-
-static struct omap_lcd_config omap3_touchbook_lcd_config __initdata = {
-       .ctrl_name      = "internal",
-};
-
 static struct regulator_consumer_supply touchbook_vmmc1_supply[] = {
        REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
 };
@@ -165,14 +156,12 @@ static struct twl4030_gpio_platform_data touchbook_gpio_data = {
 static struct regulator_consumer_supply touchbook_vdac_supply[] = {
 {
        .supply         = "vdac",
-       .dev            = &omap3_touchbook_lcd_device.dev,
 },
 };
 
 static struct regulator_consumer_supply touchbook_vdvi_supply[] = {
 {
        .supply         = "vdvi",
-       .dev            = &omap3_touchbook_lcd_device.dev,
 },
 };
 
@@ -316,10 +305,6 @@ static struct platform_device keys_gpio = {
        },
 };
 
-static struct omap_board_config_kernel omap3_touchbook_config[] __initdata = {
-       { OMAP_TAG_LCD,         &omap3_touchbook_lcd_config },
-};
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
        { .reg_offset = OMAP_MUX_TERMINATOR },
@@ -339,7 +324,6 @@ static void __init omap3_touchbook_init_irq(void)
 }
 
 static struct platform_device *omap3_touchbook_devices[] __initdata = {
-       &omap3_touchbook_lcd_device,
        &leds_gpio,
        &keys_gpio,
 };
@@ -376,8 +360,6 @@ early_param("tbr", early_touchbook_revision);
 static void __init omap3_touchbook_init(void)
 {
        omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
-       omap_board_config = omap3_touchbook_config;
-       omap_board_config_size = ARRAY_SIZE(omap3_touchbook_config);
 
        pm_power_off = omap3_touchbook_poweroff;
 
index 683bede..ed38d8f 100644 (file)
@@ -40,7 +40,7 @@
 #include <plat/common.h>
 #include <plat/usb.h>
 #include <plat/mmc.h>
-#include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 
 #include "hsmmc.h"
 #include "control.h"
@@ -455,16 +455,16 @@ static void omap4_panda_disable_dvi(struct omap_dss_device *dssdev)
 }
 
 /* Using generic display panel */
-static struct panel_generic_dpi_data omap4_dvi_panel = {
-       .name                   = "generic",
+static struct panel_dvi_platform_data omap4_dvi_panel = {
        .platform_enable        = omap4_panda_enable_dvi,
        .platform_disable       = omap4_panda_disable_dvi,
+       .i2c_bus_num = 3,
 };
 
 struct omap_dss_device omap4_panda_dvi_device = {
        .type                   = OMAP_DISPLAY_TYPE_DPI,
        .name                   = "dvi",
-       .driver_name            = "generic_dpi_panel",
+       .driver_name            = "dvi",
        .data                   = &omap4_dvi_panel,
        .phy.dpi.data_lines     = 24,
        .reset_gpio             = PANDA_DVI_TFP410_POWER_DOWN_GPIO,
index e592fb1..ec0f60c 100644 (file)
@@ -46,6 +46,7 @@
 #include <plat/common.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
+#include <video/omap-panel-dvi.h>
 #include <plat/gpmc.h>
 #include <mach/hardware.h>
 #include <plat/nand.h>
@@ -182,16 +183,16 @@ static void overo_panel_disable_dvi(struct omap_dss_device *dssdev)
        dvi_enabled = 0;
 }
 
-static struct panel_generic_dpi_data dvi_panel = {
-       .name                   = "generic",
+static struct panel_dvi_platform_data dvi_panel = {
        .platform_enable        = overo_panel_enable_dvi,
        .platform_disable       = overo_panel_disable_dvi,
+       .i2c_bus_num            = 3,
 };
 
 static struct omap_dss_device overo_dvi_device = {
        .name                   = "dvi",
        .type                   = OMAP_DISPLAY_TYPE_DPI,
-       .driver_name            = "generic_dpi_panel",
+       .driver_name            = "dvi",
        .data                   = &dvi_panel,
        .phy.dpi.data_lines     = 24,
 };
index a6c473b..faa2a8e 100644 (file)
@@ -79,29 +79,6 @@ static struct cpuidle_params rx51_cpuidle_params[] = {
        {7505 + 15274, 484329, 1},
 };
 
-static struct omap_lcd_config rx51_lcd_config = {
-       .ctrl_name      = "internal",
-};
-
-static struct omap_fbmem_config rx51_fbmem0_config = {
-       .size = 752 * 1024,
-};
-
-static struct omap_fbmem_config rx51_fbmem1_config = {
-       .size = 752 * 1024,
-};
-
-static struct omap_fbmem_config rx51_fbmem2_config = {
-       .size = 752 * 1024,
-};
-
-static struct omap_board_config_kernel rx51_config[] = {
-       { OMAP_TAG_FBMEM,       &rx51_fbmem0_config },
-       { OMAP_TAG_FBMEM,       &rx51_fbmem1_config },
-       { OMAP_TAG_FBMEM,       &rx51_fbmem2_config },
-       { OMAP_TAG_LCD,         &rx51_lcd_config },
-};
-
 static void __init rx51_init_early(void)
 {
        struct omap_sdrc_params *sdrc_params;
@@ -128,8 +105,6 @@ static struct omap_musb_board_data musb_board_data = {
 static void __init rx51_init(void)
 {
        omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
-       omap_board_config = rx51_config;
-       omap_board_config_size = ARRAY_SIZE(rx51_config);
        omap3_pm_init_cpuidle(rx51_cpuidle_params);
        omap_serial_init();
        usb_musb_init(&musb_board_data);
index a5b7a23..62510ec 100644 (file)
@@ -27,6 +27,8 @@
 #include <plat/omap_device.h>
 #include <plat/omap-pm.h>
 
+#include "control.h"
+
 static struct platform_device omap_display_device = {
        .name          = "omapdss",
        .id            = -1,
@@ -61,7 +63,7 @@ static const struct omap_dss_hwmod_data omap3_dss_hwmod_data[] __initdata = {
        { "dss_dispc", "omapdss_dispc", -1 },
        { "dss_rfbi", "omapdss_rfbi", -1 },
        { "dss_venc", "omapdss_venc", -1 },
-       { "dss_dsi1", "omapdss_dsi1", -1 },
+       { "dss_dsi1", "omapdss_dsi", 0 },
 };
 
 static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initdata = {
@@ -69,11 +71,58 @@ static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initdata = {
        { "dss_dispc", "omapdss_dispc", -1 },
        { "dss_rfbi", "omapdss_rfbi", -1 },
        { "dss_venc", "omapdss_venc", -1 },
-       { "dss_dsi1", "omapdss_dsi1", -1 },
-       { "dss_dsi2", "omapdss_dsi2", -1 },
+       { "dss_dsi1", "omapdss_dsi", 0 },
+       { "dss_dsi2", "omapdss_dsi", 1 },
        { "dss_hdmi", "omapdss_hdmi", -1 },
 };
 
+static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
+{
+       u32 enable_mask, enable_shift;
+       u32 pipd_mask, pipd_shift;
+       u32 reg;
+
+       if (dsi_id == 0) {
+               enable_mask = OMAP4_DSI1_LANEENABLE_MASK;
+               enable_shift = OMAP4_DSI1_LANEENABLE_SHIFT;
+               pipd_mask = OMAP4_DSI1_PIPD_MASK;
+               pipd_shift = OMAP4_DSI1_PIPD_SHIFT;
+       } else if (dsi_id == 1) {
+               enable_mask = OMAP4_DSI2_LANEENABLE_MASK;
+               enable_shift = OMAP4_DSI2_LANEENABLE_SHIFT;
+               pipd_mask = OMAP4_DSI2_PIPD_MASK;
+               pipd_shift = OMAP4_DSI2_PIPD_SHIFT;
+       } else {
+               return -ENODEV;
+       }
+
+       reg = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY);
+
+       reg &= ~enable_mask;
+       reg &= ~pipd_mask;
+
+       reg |= (lanes << enable_shift) & enable_mask;
+       reg |= (lanes << pipd_shift) & pipd_mask;
+
+       omap4_ctrl_pad_writel(reg, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY);
+
+       return 0;
+}
+
+static int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
+{
+       if (cpu_is_omap44xx())
+               return omap4_dsi_mux_pads(dsi_id, lane_mask);
+
+       return 0;
+}
+
+static void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask)
+{
+       if (cpu_is_omap44xx())
+               omap4_dsi_mux_pads(dsi_id, 0);
+}
+
 int __init omap_display_init(struct omap_dss_board_info *board_data)
 {
        int r = 0;
@@ -96,6 +145,11 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
                oh_count = ARRAY_SIZE(omap4_dss_hwmod_data);
        }
 
+       if (board_data->dsi_enable_pads == NULL)
+               board_data->dsi_enable_pads = omap_dsi_enable_pads;
+       if (board_data->dsi_disable_pads == NULL)
+               board_data->dsi_disable_pads = omap_dsi_disable_pads;
+
        pdata.board_data = board_data;
        pdata.board_data->get_context_loss_count =
                omap_pm_get_dev_context_loss_count;
index daa056e..5224357 100644 (file)
@@ -99,7 +99,7 @@ static struct regulator_init_data omap3_vdac_idata = {
 
 static struct regulator_consumer_supply omap3_vpll2_supplies[] = {
        REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
-       REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+       REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"),
 };
 
 static struct regulator_init_data omap3_vpll2_idata = {
@@ -235,6 +235,12 @@ static struct regulator_init_data omap4_vana_idata = {
        },
 };
 
+static struct regulator_consumer_supply omap4_vcxio_supply[] = {
+       REGULATOR_SUPPLY("vdds_dsi", "omapdss_dss"),
+       REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"),
+       REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.1"),
+};
+
 static struct regulator_init_data omap4_vcxio_idata = {
        .constraints = {
                .min_uV                 = 1800000,
@@ -243,7 +249,10 @@ static struct regulator_init_data omap4_vcxio_idata = {
                                        | REGULATOR_MODE_STANDBY,
                .valid_ops_mask         = REGULATOR_CHANGE_MODE
                                        | REGULATOR_CHANGE_STATUS,
+               .always_on              = true,
        },
+       .num_consumer_supplies  = ARRAY_SIZE(omap4_vcxio_supply),
+       .consumer_supplies      = omap4_vcxio_supply,
 };
 
 static struct regulator_init_data omap4_vusb_idata = {
index 4de92dc..3689ad2 100644 (file)
@@ -1597,6 +1597,7 @@ static void __init mackerel_init(void)
 
        sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device);
        sh7372_add_device_to_domain(&sh7372_a4lc, &hdmi_lcdc_device);
+       sh7372_add_device_to_domain(&sh7372_a4lc, &meram_device);
        sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device);
        sh7372_add_device_to_domain(&sh7372_a3sp, &usbhs0_device);
        sh7372_add_device_to_domain(&sh7372_a3sp, &usbhs1_device);
index e41ebbd..cfe958e 100644 (file)
@@ -66,8 +66,8 @@ struct fsl_diu_shared_fb {
        bool            in_use;
 };
 
-unsigned int mpc512x_get_pixel_format(unsigned int bits_per_pixel,
-                                     int monitor_port)
+u32 mpc512x_get_pixel_format(enum fsl_diu_monitor_port port,
+                            unsigned int bits_per_pixel)
 {
        switch (bits_per_pixel) {
        case 32:
@@ -80,11 +80,12 @@ unsigned int mpc512x_get_pixel_format(unsigned int bits_per_pixel,
        return 0x00000400;
 }
 
-void mpc512x_set_gamma_table(int monitor_port, char *gamma_table_base)
+void mpc512x_set_gamma_table(enum fsl_diu_monitor_port port,
+                            char *gamma_table_base)
 {
 }
 
-void mpc512x_set_monitor_port(int monitor_port)
+void mpc512x_set_monitor_port(enum fsl_diu_monitor_port port)
 {
 }
 
@@ -182,14 +183,10 @@ void mpc512x_set_pixel_clock(unsigned int pixclock)
        iounmap(ccm);
 }
 
-ssize_t mpc512x_show_monitor_port(int monitor_port, char *buf)
+enum fsl_diu_monitor_port
+mpc512x_valid_monitor_port(enum fsl_diu_monitor_port port)
 {
-       return sprintf(buf, "0 - 5121 LCD\n");
-}
-
-int mpc512x_set_sysfs_monitor_port(int val)
-{
-       return 0;
+       return FSL_DIU_PORT_DVI;
 }
 
 static struct fsl_diu_shared_fb __attribute__ ((__aligned__(8))) diu_shared_fb;
@@ -256,7 +253,7 @@ void __init mpc512x_init_diu(void)
        }
 
        mode = in_be32(&diu_reg->diu_mode);
-       if (mode != MFB_MODE1) {
+       if (mode == MFB_MODE0) {
                pr_info("%s: DIU OFF\n", __func__);
                goto out;
        }
@@ -332,8 +329,7 @@ void __init mpc512x_setup_diu(void)
        diu_ops.set_gamma_table         = mpc512x_set_gamma_table;
        diu_ops.set_monitor_port        = mpc512x_set_monitor_port;
        diu_ops.set_pixel_clock         = mpc512x_set_pixel_clock;
-       diu_ops.show_monitor_port       = mpc512x_show_monitor_port;
-       diu_ops.set_sysfs_monitor_port  = mpc512x_set_sysfs_monitor_port;
+       diu_ops.valid_monitor_port      = mpc512x_valid_monitor_port;
        diu_ops.release_bootmem         = mpc512x_release_bootmem;
 #endif
 }
index 266b3aa..c01c727 100644 (file)
@@ -93,8 +93,8 @@
  * The Area Descriptor is a 32-bit value that determine which bits in each
  * pixel are to be used for each color.
  */
-static unsigned int p1022ds_get_pixel_format(unsigned int bits_per_pixel,
-       int monitor_port)
+static u32 p1022ds_get_pixel_format(enum fsl_diu_monitor_port port,
+                                   unsigned int bits_per_pixel)
 {
        switch (bits_per_pixel) {
        case 32:
@@ -118,7 +118,8 @@ static unsigned int p1022ds_get_pixel_format(unsigned int bits_per_pixel,
  * On some boards, the gamma table for some ports may need to be modified.
  * This is not the case on the P1022DS, so we do nothing.
 */
-static void p1022ds_set_gamma_table(int monitor_port, char *gamma_table_base)
+static void p1022ds_set_gamma_table(enum fsl_diu_monitor_port port,
+                                   char *gamma_table_base)
 {
 }
 
@@ -126,7 +127,7 @@ static void p1022ds_set_gamma_table(int monitor_port, char *gamma_table_base)
  * p1022ds_set_monitor_port: switch the output to a different monitor port
  *
  */
-static void p1022ds_set_monitor_port(int monitor_port)
+static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
 {
        struct device_node *pixis_node;
        void __iomem *pixis;
@@ -145,19 +146,21 @@ static void p1022ds_set_monitor_port(int monitor_port)
        }
        brdcfg1 = pixis + 9;    /* BRDCFG1 is at offset 9 in the ngPIXIS */
 
-       switch (monitor_port) {
-       case 0: /* DVI */
+       switch (port) {
+       case FSL_DIU_PORT_DVI:
+               printk(KERN_INFO "%s:%u\n", __func__, __LINE__);
                /* Enable the DVI port, disable the DFP and the backlight */
                clrsetbits_8(brdcfg1, PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT,
                             PX_BRDCFG1_DVIEN);
                break;
-       case 1: /* Single link LVDS */
+       case FSL_DIU_PORT_LVDS:
+               printk(KERN_INFO "%s:%u\n", __func__, __LINE__);
                /* Enable the DFP port, disable the DVI and the backlight */
                clrsetbits_8(brdcfg1, PX_BRDCFG1_DVIEN | PX_BRDCFG1_BACKLIGHT,
                             PX_BRDCFG1_DFPEN);
                break;
        default:
-               pr_err("p1022ds: unsupported monitor port %i\n", monitor_port);
+               pr_err("p1022ds: unsupported monitor port %i\n", port);
        }
 
        iounmap(pixis);
@@ -214,23 +217,18 @@ void p1022ds_set_pixel_clock(unsigned int pixclock)
 }
 
 /**
- * p1022ds_show_monitor_port: show the current monitor
- *
- * This function returns a string indicating whether the current monitor is
- * set to DVI or LVDS.
- */
-ssize_t p1022ds_show_monitor_port(int monitor_port, char *buf)
-{
-       return sprintf(buf, "%c0 - DVI\n%c1 - Single link LVDS\n",
-               monitor_port == 0 ? '*' : ' ', monitor_port == 1 ? '*' : ' ');
-}
-
-/**
- * p1022ds_set_sysfs_monitor_port: set the monitor port for sysfs
+ * p1022ds_valid_monitor_port: set the monitor port for sysfs
  */
-int p1022ds_set_sysfs_monitor_port(int val)
+enum fsl_diu_monitor_port
+p1022ds_valid_monitor_port(enum fsl_diu_monitor_port port)
 {
-       return val < 2 ? val : 0;
+       switch (port) {
+       case FSL_DIU_PORT_DVI:
+       case FSL_DIU_PORT_LVDS:
+               return port;
+       default:
+               return FSL_DIU_PORT_DVI; /* Dual-link LVDS is not supported */
+       }
 }
 
 #endif
@@ -305,8 +303,7 @@ static void __init p1022_ds_setup_arch(void)
        diu_ops.set_gamma_table         = p1022ds_set_gamma_table;
        diu_ops.set_monitor_port        = p1022ds_set_monitor_port;
        diu_ops.set_pixel_clock         = p1022ds_set_pixel_clock;
-       diu_ops.show_monitor_port       = p1022ds_show_monitor_port;
-       diu_ops.set_sysfs_monitor_port  = p1022ds_set_sysfs_monitor_port;
+       diu_ops.valid_monitor_port      = p1022ds_valid_monitor_port;
 #endif
 
 #ifdef CONFIG_SMP
index 74e018e..13fa9a6 100644 (file)
@@ -152,10 +152,10 @@ machine_device_initcall(mpc86xx_hpcd, mpc8610_declare_of_platform_devices);
        (c2 << AD_COMP_2_SHIFT) | (c1 << AD_COMP_1_SHIFT) | \
        (c0 << AD_COMP_0_SHIFT) | (size << AD_PIXEL_S_SHIFT))
 
-unsigned int mpc8610hpcd_get_pixel_format(unsigned int bits_per_pixel,
-                                               int monitor_port)
+u32 mpc8610hpcd_get_pixel_format(enum fsl_diu_monitor_port port,
+                                unsigned int bits_per_pixel)
 {
-       static const unsigned long pixelformat[][3] = {
+       static const u32 pixelformat[][3] = {
                {
                        MAKE_AD(3, 0, 2, 1, 3, 8, 8, 8, 8),
                        MAKE_AD(4, 2, 0, 1, 2, 8, 8, 8, 0),
@@ -170,7 +170,8 @@ unsigned int mpc8610hpcd_get_pixel_format(unsigned int bits_per_pixel,
        unsigned int arch_monitor;
 
        /* The DVI port is mis-wired on revision 1 of this board. */
-       arch_monitor = ((*pixis_arch == 0x01) && (monitor_port == 0))? 0 : 1;
+       arch_monitor =
+               ((*pixis_arch == 0x01) && (port == FSL_DIU_PORT_DVI)) ? 0 : 1;
 
        switch (bits_per_pixel) {
        case 32:
@@ -185,10 +186,11 @@ unsigned int mpc8610hpcd_get_pixel_format(unsigned int bits_per_pixel,
        }
 }
 
-void mpc8610hpcd_set_gamma_table(int monitor_port, char *gamma_table_base)
+void mpc8610hpcd_set_gamma_table(enum fsl_diu_monitor_port port,
+                                char *gamma_table_base)
 {
        int i;
-       if (monitor_port == 2) {                /* dual link LVDS */
+       if (port == FSL_DIU_PORT_DLVDS) {
                for (i = 0; i < 256*3; i++)
                        gamma_table_base[i] = (gamma_table_base[i] << 2) |
                                         ((gamma_table_base[i] >> 6) & 0x03);
@@ -199,17 +201,21 @@ void mpc8610hpcd_set_gamma_table(int monitor_port, char *gamma_table_base)
 #define PX_BRDCFG0_DLINK       (1 << 4)
 #define PX_BRDCFG0_DIU_MASK    (PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK)
 
-void mpc8610hpcd_set_monitor_port(int monitor_port)
+void mpc8610hpcd_set_monitor_port(enum fsl_diu_monitor_port port)
 {
-       static const u8 bdcfg[] = {
-               PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK,
-               PX_BRDCFG0_DLINK,
-               0,
-       };
-
-       if (monitor_port < 3)
+       switch (port) {
+       case FSL_DIU_PORT_DVI:
                clrsetbits_8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK,
-                            bdcfg[monitor_port]);
+                            PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK);
+               break;
+       case FSL_DIU_PORT_LVDS:
+               clrsetbits_8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK,
+                            PX_BRDCFG0_DLINK);
+               break;
+       case FSL_DIU_PORT_DLVDS:
+               clrbits8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK);
+               break;
+       }
 }
 
 /**
@@ -262,20 +268,10 @@ void mpc8610hpcd_set_pixel_clock(unsigned int pixclock)
        iounmap(guts);
 }
 
-ssize_t mpc8610hpcd_show_monitor_port(int monitor_port, char *buf)
-{
-       return snprintf(buf, PAGE_SIZE,
-                       "%c0 - DVI\n"
-                       "%c1 - Single link LVDS\n"
-                       "%c2 - Dual link LVDS\n",
-                       monitor_port == 0 ? '*' : ' ',
-                       monitor_port == 1 ? '*' : ' ',
-                       monitor_port == 2 ? '*' : ' ');
-}
-
-int mpc8610hpcd_set_sysfs_monitor_port(int val)
+enum fsl_diu_monitor_port
+mpc8610hpcd_valid_monitor_port(enum fsl_diu_monitor_port port)
 {
-       return val < 3 ? val : 0;
+       return port;
 }
 
 #endif
@@ -307,8 +303,7 @@ static void __init mpc86xx_hpcd_setup_arch(void)
        diu_ops.set_gamma_table         = mpc8610hpcd_set_gamma_table;
        diu_ops.set_monitor_port        = mpc8610hpcd_set_monitor_port;
        diu_ops.set_pixel_clock         = mpc8610hpcd_set_pixel_clock;
-       diu_ops.show_monitor_port       = mpc8610hpcd_show_monitor_port;
-       diu_ops.set_sysfs_monitor_port  = mpc8610hpcd_set_sysfs_monitor_port;
+       diu_ops.valid_monitor_port      = mpc8610hpcd_valid_monitor_port;
 #endif
 
        pixis_node = of_find_compatible_node(NULL, NULL, "fsl,fpga-pixis");
index 2ece02b..c6d0073 100644 (file)
@@ -22,15 +22,24 @@ struct device_node;
 extern void fsl_rstcr_restart(char *cmd);
 
 #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
+
+/* The different ports that the DIU can be connected to */
+enum fsl_diu_monitor_port {
+       FSL_DIU_PORT_DVI,       /* DVI */
+       FSL_DIU_PORT_LVDS,      /* Single-link LVDS */
+       FSL_DIU_PORT_DLVDS      /* Dual-link LVDS */
+};
+
 struct platform_diu_data_ops {
-       unsigned int (*get_pixel_format) (unsigned int bits_per_pixel,
-               int monitor_port);
-       void (*set_gamma_table) (int monitor_port, char *gamma_table_base);
-       void (*set_monitor_port) (int monitor_port);
-       void (*set_pixel_clock) (unsigned int pixclock);
-       ssize_t (*show_monitor_port) (int monitor_port, char *buf);
-       int (*set_sysfs_monitor_port) (int val);
-       void (*release_bootmem) (void);
+       u32 (*get_pixel_format)(enum fsl_diu_monitor_port port,
+               unsigned int bpp);
+       void (*set_gamma_table)(enum fsl_diu_monitor_port port,
+               char *gamma_table_base);
+       void (*set_monitor_port)(enum fsl_diu_monitor_port port);
+       void (*set_pixel_clock)(unsigned int pixclock);
+       enum fsl_diu_monitor_port (*valid_monitor_port)
+               (enum fsl_diu_monitor_port port);
+       void (*release_bootmem)(void);
 };
 
 extern struct platform_diu_data_ops diu_ops;
index b3a5ecd..30d8896 100644 (file)
@@ -400,7 +400,6 @@ static int omapvid_setup_overlay(struct omap_vout_device *vout,
 
        ovl->get_overlay_info(ovl, &info);
        info.paddr = addr;
-       info.vaddr = NULL;
        info.width = cropwidth;
        info.height = cropheight;
        info.color_mode = vout->dss_mode;
@@ -1165,12 +1164,17 @@ static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh,
 {
        int ret = 0;
        struct omap_vout_device *vout = fh;
+       struct omap_overlay *ovl;
+       struct omapvideo_info *ovid;
        struct v4l2_window *win = &f->fmt.win;
 
+       ovid = &vout->vid_info;
+       ovl = ovid->overlays[0];
+
        ret = omap_vout_try_window(&vout->fbuf, win);
 
        if (!ret) {
-               if (vout->vid == OMAP_VIDEO1)
+               if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
                        win->global_alpha = 255;
                else
                        win->global_alpha = f->fmt.win.global_alpha;
@@ -1194,8 +1198,8 @@ static int vidioc_s_fmt_vid_overlay(struct file *file, void *fh,
 
        ret = omap_vout_new_window(&vout->crop, &vout->win, &vout->fbuf, win);
        if (!ret) {
-               /* Video1 plane does not support global alpha */
-               if (ovl->id == OMAP_DSS_VIDEO1)
+               /* Video1 plane does not support global alpha on OMAP3 */
+               if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
                        vout->win.global_alpha = 255;
                else
                        vout->win.global_alpha = f->fmt.win.global_alpha;
@@ -1788,7 +1792,9 @@ static int vidioc_s_fbuf(struct file *file, void *fh,
        if (ovl->manager && ovl->manager->get_manager_info &&
                        ovl->manager->set_manager_info) {
                ovl->manager->get_manager_info(ovl->manager, &info);
-               info.alpha_enabled = enable;
+               /* enable this only if there is no zorder cap */
+               if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
+                       info.partial_alpha_enabled = enable;
                if (ovl->manager->set_manager_info(ovl->manager, &info))
                        return -EINVAL;
        }
@@ -1820,7 +1826,7 @@ static int vidioc_g_fbuf(struct file *file, void *fh,
        }
        if (ovl->manager && ovl->manager->get_manager_info) {
                ovl->manager->get_manager_info(ovl->manager, &info);
-               if (info.alpha_enabled)
+               if (info.partial_alpha_enabled)
                        a->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
        }
 
index 36db231..277e408 100644 (file)
@@ -1300,27 +1300,17 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
        return 0;
 }
 
-static int XGIfb_pan_var(struct xgifb_video_info *xgifb_info,
-                        struct fb_var_screeninfo *var)
+static int XGIfb_pan_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
+       struct xgifb_video_info *xgifb_info = info->par;
        unsigned int base;
 
        /* printk("Inside pan_var"); */
 
-       if (var->xoffset > (var->xres_virtual - var->xres)) {
-               /* printk("Pan: xo: %d xv %d xr %d\n",
-                       var->xoffset, var->xres_virtual, var->xres); */
-               return -EINVAL;
-       }
-       if (var->yoffset > (var->yres_virtual - var->yres)) {
-               /* printk("Pan: yo: %d yv %d yr %d\n",
-                       var->yoffset, var->yres_virtual, var->yres); */
-               return -EINVAL;
-       }
-       base = var->yoffset * var->xres_virtual + var->xoffset;
+       base = var->yoffset * info->var.xres_virtual + var->xoffset;
 
        /* calculate base bpp dep. */
-       switch (var->bits_per_pixel) {
+       switch (info->var.bits_per_pixel) {
        case 16:
                base >>= 1;
                break;
@@ -1615,13 +1605,12 @@ static int XGIfb_pan_display(struct fb_var_screeninfo *var,
                struct fb_info *info)
 {
        int err;
-       struct xgifb_video_info *xgifb_info = info->par;
 
        /* printk("\nInside pan_display:\n"); */
 
-       if (var->xoffset > (var->xres_virtual - var->xres))
+       if (var->xoffset > (info->var.xres_virtual - info->var.xres))
                return -EINVAL;
-       if (var->yoffset > (var->yres_virtual - var->yres))
+       if (var->yoffset > (info->var.yres_virtual - info->var.yres))
                return -EINVAL;
 
        if (var->vmode & FB_VMODE_YWRAP) {
@@ -1634,7 +1623,7 @@ static int XGIfb_pan_display(struct fb_var_screeninfo *var,
                                                > info->var.yres_virtual)
                        return -EINVAL;
        }
-       err = XGIfb_pan_var(xgifb_info, var);
+       err = XGIfb_pan_var(var, info);
        if (err < 0)
                return err;
 
index 75a39ea..a425d65 100644 (file)
@@ -378,8 +378,8 @@ static int mc68x328fb_pan_display(struct fb_var_screeninfo *var,
                    || var->xoffset)
                        return -EINVAL;
        } else {
-               if (var->xoffset + var->xres > info->var.xres_virtual ||
-                   var->yoffset + var->yres > info->var.yres_virtual)
+               if (var->xoffset + info->var.xres > info->var.xres_virtual ||
+                   var->yoffset + info->var.yres > info->var.yres_virtual)
                        return -EINVAL;
        }
        info->var.xoffset = var->xoffset;
index 549b960..8165c55 100644 (file)
@@ -259,6 +259,15 @@ config FB_TILEBLITTING
 comment "Frame buffer hardware drivers"
        depends on FB
 
+config FB_GRVGA
+       tristate "Aeroflex Gaisler framebuffer support"
+       depends on FB && SPARC
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       ---help---
+       This enables support for the SVGACTRL framebuffer in the GRLIB IP library from Aeroflex Gaisler.
+
 config FB_CIRRUS
        tristate "Cirrus Logic support"
        depends on FB && (ZORRO || PCI)
@@ -1756,9 +1765,10 @@ config FB_AU1100
 config FB_AU1200
        bool "Au1200 LCD Driver"
        depends on (FB = y) && MIPS && SOC_AU1200
-       select FB_CFB_FILLRECT
-       select FB_CFB_COPYAREA
-       select FB_CFB_IMAGEBLIT
+       select FB_SYS_FILLRECT
+       select FB_SYS_COPYAREA
+       select FB_SYS_IMAGEBLIT
+       select FB_SYS_FOPS
        help
          This is the framebuffer driver for the AMD Au1200 SOC.  It can drive
          various panels and CRTs by passing in kernel cmd line option
@@ -2027,7 +2037,7 @@ config FB_TMIO_ACCELL
 
 config FB_S3C
        tristate "Samsung S3C framebuffer support"
-       depends on FB && S3C_DEV_FB
+       depends on FB && (S3C_DEV_FB || S5P_DEV_FIMD0)
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
@@ -2110,6 +2120,22 @@ config FB_SM501
 
          If unsure, say N.
 
+config FB_SMSCUFX
+       tristate "SMSC UFX6000/7000 USB Framebuffer support"
+       depends on FB && USB
+       select FB_MODE_HELPERS
+       select FB_SYS_FILLRECT
+       select FB_SYS_COPYAREA
+       select FB_SYS_IMAGEBLIT
+       select FB_SYS_FOPS
+       select FB_DEFERRED_IO
+       ---help---
+         This is a kernel framebuffer driver for SMSC UFX USB devices.
+         Supports fbdev clients like xf86-video-fbdev, kdrive, fbi, and
+         mplayer -vo fbdev. Supports both UFX6000 (USB 2.0) and UFX7000
+         (USB 3.0) devices.
+         To compile as a module, choose M here: the module name is smscufx.
+
 config FB_UDL
        tristate "Displaylink USB Framebuffer support"
        depends on FB && USB
index 8b83129..9b9d8ff 100644 (file)
@@ -33,6 +33,7 @@ obj-$(CONFIG_FB_AMIGA)            += amifb.o c2p_planar.o
 obj-$(CONFIG_FB_ARC)              += arcfb.o
 obj-$(CONFIG_FB_CLPS711X)         += clps711xfb.o
 obj-$(CONFIG_FB_CYBER2000)        += cyber2000fb.o
+obj-$(CONFIG_FB_GRVGA)            += grvga.o
 obj-$(CONFIG_FB_PM2)              += pm2fb.o
 obj-$(CONFIG_FB_PM3)             += pm3fb.o
 
@@ -127,6 +128,7 @@ obj-$(CONFIG_FB_IBM_GXT4500)          += gxt4500.o
 obj-$(CONFIG_FB_PS3)             += ps3fb.o
 obj-$(CONFIG_FB_SM501)            += sm501fb.o
 obj-$(CONFIG_FB_UDL)             += udlfb.o
+obj-$(CONFIG_FB_SMSCUFX)         += smscufx.o
 obj-$(CONFIG_FB_XILINX)           += xilinxfb.o
 obj-$(CONFIG_SH_MIPI_DSI)        += sh_mipi_dsi.o
 obj-$(CONFIG_FB_SH_MOBILE_HDMI)          += sh_mobile_hdmi.o
index 6183a57..b303f17 100644 (file)
@@ -850,9 +850,10 @@ acornfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
        u_int y_bottom = var->yoffset;
 
        if (!(var->vmode & FB_VMODE_YWRAP))
-               y_bottom += var->yres;
+               y_bottom += info->var.yres;
 
-       BUG_ON(y_bottom > var->yres_virtual);
+       if (y_bottom > info->var.yres_virtual)
+               return -EINVAL;
 
        acornfb_update_dma(info, var);
 
index 8686429..555dd4c 100644 (file)
@@ -908,13 +908,14 @@ static int arkfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info
        unsigned int offset;
 
        /* Calculate the offset */
-       if (var->bits_per_pixel == 0) {
-               offset = (var->yoffset / 16) * (var->xres_virtual / 2) + (var->xoffset / 2);
+       if (info->var.bits_per_pixel == 0) {
+               offset = (var->yoffset / 16) * (info->var.xres_virtual / 2)
+                      + (var->xoffset / 2);
                offset = offset >> 2;
        } else {
                offset = (var->yoffset * info->fix.line_length) +
-                        (var->xoffset * var->bits_per_pixel / 8);
-               offset = offset >> ((var->bits_per_pixel == 4) ? 2 : 3);
+                        (var->xoffset * info->var.bits_per_pixel / 8);
+               offset = offset >> ((info->var.bits_per_pixel == 4) ? 2 : 3);
        }
 
        /* Set the offset */
index dda9206..4ac48d9 100644 (file)
@@ -39,7 +39,8 @@
                                         | FBINFO_HWACCEL_YPAN)
 
 static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
-                                       struct fb_var_screeninfo *var)
+                                       struct fb_var_screeninfo *var,
+                                       struct fb_info *info)
 {
 
 }
@@ -50,14 +51,16 @@ static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
                                        | FBINFO_HWACCEL_YPAN)
 
 static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
-                                    struct fb_var_screeninfo *var)
+                                    struct fb_var_screeninfo *var,
+                                    struct fb_info *info)
 {
        u32 dma2dcfg;
        u32 pixeloff;
 
-       pixeloff = (var->xoffset * var->bits_per_pixel) & 0x1f;
+       pixeloff = (var->xoffset * info->var.bits_per_pixel) & 0x1f;
 
-       dma2dcfg = ((var->xres_virtual - var->xres) * var->bits_per_pixel) / 8;
+       dma2dcfg = (info->var.xres_virtual - info->var.xres)
+                * info->var.bits_per_pixel / 8;
        dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET;
        lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg);
 
@@ -249,14 +252,14 @@ static void atmel_lcdfb_update_dma(struct fb_info *info,
        unsigned long dma_addr;
 
        dma_addr = (fix->smem_start + var->yoffset * fix->line_length
-                   + var->xoffset * var->bits_per_pixel / 8);
+                   + var->xoffset * info->var.bits_per_pixel / 8);
 
        dma_addr &= ~3UL;
 
        /* Set framebuffer DMA base address and pixel offset */
        lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr);
 
-       atmel_lcdfb_update_dma2d(sinfo, var);
+       atmel_lcdfb_update_dma2d(sinfo, var, info);
 }
 
 static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo)
index 32f8cf6..1506848 100644 (file)
@@ -845,16 +845,16 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var,
 {
         struct radeonfb_info *rinfo = info->par;
 
-        if ((var->xoffset + var->xres > var->xres_virtual)
-           || (var->yoffset + var->yres > var->yres_virtual))
-               return -EINVAL;
+       if ((var->xoffset + info->var.xres > info->var.xres_virtual)
+           || (var->yoffset + info->var.yres > info->var.yres_virtual))
+               return -EINVAL;
                 
         if (rinfo->asleep)
                return 0;
 
        radeon_fifo_wait(2);
-        OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset)
-                            * var->bits_per_pixel / 8) & ~7);
+       OUTREG(CRTC_OFFSET, (var->yoffset * info->fix.line_length +
+                            var->xoffset * info->var.bits_per_pixel / 8) & ~7);
         return 0;
 }
 
index 01a8fde..649cb35 100644 (file)
@@ -110,12 +110,6 @@ static struct fb_var_screeninfo au1100fb_var __devinitdata = {
        .vmode          = FB_VMODE_NONINTERLACED,
 };
 
-static struct au1100fb_drv_info drv_info;
-
-static int nocursor = 0;
-module_param(nocursor, int, 0644);
-MODULE_PARM_DESC(nocursor, "cursor enable/disable");
-
 /* fb_blank
  * Blank the screen. Depending on the mode, the screen will be
  * activated with the backlight color, or desactivated
@@ -132,7 +126,7 @@ static int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi)
                        /* Turn on panel */
                        fbdev->regs->lcd_control |= LCD_CONTROL_GO;
 #ifdef CONFIG_MIPS_PB1100
-                       if (drv_info.panel_idx == 1) {
+                       if (fbdev->panel_idx == 1) {
                                au_writew(au_readw(PB1100_G_CONTROL)
                                          | (PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD),
                        PB1100_G_CONTROL);
@@ -147,7 +141,7 @@ static int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi)
                        /* Turn off panel */
                        fbdev->regs->lcd_control &= ~LCD_CONTROL_GO;
 #ifdef CONFIG_MIPS_PB1100
-                       if (drv_info.panel_idx == 1) {
+                       if (fbdev->panel_idx == 1) {
                                au_writew(au_readw(PB1100_G_CONTROL)
                                          & ~(PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD),
                        PB1100_G_CONTROL);
@@ -428,17 +422,6 @@ int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
        return 0;
 }
 
-/* fb_cursor
- * Used to disable cursor drawing...
- */
-int au1100fb_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-       if (nocursor)
-               return 0;
-       else
-               return -EINVAL; /* just to force soft_cursor() call */
-}
-
 static struct fb_ops au1100fb_ops =
 {
        .owner                  = THIS_MODULE,
@@ -450,13 +433,53 @@ static struct fb_ops au1100fb_ops =
        .fb_imageblit           = cfb_imageblit,
        .fb_rotate              = au1100fb_fb_rotate,
        .fb_mmap                = au1100fb_fb_mmap,
-       .fb_cursor              = au1100fb_fb_cursor,
 };
 
 
 /*-------------------------------------------------------------------------*/
 
-/* AU1100 LCD controller device driver */
+static int au1100fb_setup(struct au1100fb_device *fbdev)
+{
+       char *this_opt, *options;
+       int num_panels = ARRAY_SIZE(known_lcd_panels);
+
+       if (num_panels <= 0) {
+               print_err("No LCD panels supported by driver!");
+               return -ENODEV;
+       }
+
+       if (fb_get_options(DRIVER_NAME, &options))
+               return -ENODEV;
+       if (!options)
+               return -ENODEV;
+
+       while ((this_opt = strsep(&options, ",")) != NULL) {
+               /* Panel option */
+               if (!strncmp(this_opt, "panel:", 6)) {
+                       int i;
+                       this_opt += 6;
+                       for (i = 0; i < num_panels; i++) {
+                               if (!strncmp(this_opt, known_lcd_panels[i].name,
+                                            strlen(this_opt))) {
+                                       fbdev->panel = &known_lcd_panels[i];
+                                       fbdev->panel_idx = i;
+                                       break;
+                               }
+                       }
+                       if (i >= num_panels) {
+                               print_warn("Panel '%s' not supported!", this_opt);
+                               return -ENODEV;
+                       }
+               }
+               /* Unsupported option */
+               else
+                       print_warn("Unsupported option \"%s\"", this_opt);
+       }
+
+       print_info("Panel=%s", fbdev->panel->name);
+
+       return 0;
+}
 
 static int __devinit au1100fb_drv_probe(struct platform_device *dev)
 {
@@ -465,22 +488,21 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev)
        unsigned long page;
        u32 sys_clksrc;
 
-       if (!dev)
-                       return -EINVAL;
-
        /* Allocate new device private */
-       if (!(fbdev = kzalloc(sizeof(struct au1100fb_device), GFP_KERNEL))) {
+       fbdev = kzalloc(sizeof(struct au1100fb_device), GFP_KERNEL);
+       if (!fbdev) {
                print_err("fail to allocate device private record");
                return -ENOMEM;
        }
 
-       fbdev->panel = &known_lcd_panels[drv_info.panel_idx];
+       if (au1100fb_setup(fbdev))
+               goto failed;
 
        platform_set_drvdata(dev, (void *)fbdev);
 
        /* Allocate region for our registers and map them */
-       if (!(regs_res = platform_get_resource(to_platform_device(dev),
-                                       IORESOURCE_MEM, 0))) {
+       regs_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+       if (!regs_res) {
                print_err("fail to retrieve registers resource");
                return -EFAULT;
        }
@@ -500,13 +522,11 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev)
        print_dbg("Register memory map at %p", fbdev->regs);
        print_dbg("phys=0x%08x, size=%d", fbdev->regs_phys, fbdev->regs_len);
 
-
-
        /* Allocate the framebuffer to the maximum screen size * nbr of video buffers */
        fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres *
                        (fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS;
 
-       fbdev->fb_mem = dma_alloc_coherent(dev, PAGE_ALIGN(fbdev->fb_len),
+       fbdev->fb_mem = dma_alloc_coherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len),
                                        &fbdev->fb_phys, GFP_KERNEL);
        if (!fbdev->fb_mem) {
                print_err("fail to allocate frambuffer (size: %dK))",
@@ -525,7 +545,7 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev)
             page < PAGE_ALIGN((unsigned long)fbdev->fb_mem + fbdev->fb_len);
             page += PAGE_SIZE) {
 #if CONFIG_DMA_NONCOHERENT
-               SetPageReserved(virt_to_page(CAC_ADDR(page)));
+               SetPageReserved(virt_to_page(CAC_ADDR((void *)page)));
 #else
                SetPageReserved(virt_to_page(page));
 #endif
@@ -578,7 +598,8 @@ failed:
                release_mem_region(fbdev->regs_phys, fbdev->regs_len);
        }
        if (fbdev->fb_mem) {
-               dma_free_noncoherent(dev, fbdev->fb_len, fbdev->fb_mem, fbdev->fb_phys);
+               dma_free_noncoherent(&dev->dev, fbdev->fb_len, fbdev->fb_mem,
+                                    fbdev->fb_phys);
        }
        if (fbdev->info.cmap.len != 0) {
                fb_dealloc_cmap(&fbdev->info.cmap);
@@ -608,7 +629,8 @@ int au1100fb_drv_remove(struct platform_device *dev)
 
        release_mem_region(fbdev->regs_phys, fbdev->regs_len);
 
-       dma_free_coherent(dev, PAGE_ALIGN(fbdev->fb_len), fbdev->fb_mem, fbdev->fb_phys);
+       dma_free_coherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len), fbdev->fb_mem,
+                         fbdev->fb_phys);
 
        fb_dealloc_cmap(&fbdev->info.cmap);
        kfree(fbdev->info.pseudo_palette);
@@ -675,101 +697,18 @@ static struct platform_driver au1100fb_driver = {
         .resume                = au1100fb_drv_resume,
 };
 
-/*-------------------------------------------------------------------------*/
-
-/* Kernel driver */
-
-int au1100fb_setup(char *options)
-{
-       char* this_opt;
-       int num_panels = ARRAY_SIZE(known_lcd_panels);
-       char* mode = NULL;
-       int panel_idx = 0;
-
-       if (num_panels <= 0) {
-               print_err("No LCD panels supported by driver!");
-               return -EFAULT;
-                       }
-
-       if (options) {
-               while ((this_opt = strsep(&options,",")) != NULL) {
-                       /* Panel option */
-                       if (!strncmp(this_opt, "panel:", 6)) {
-                               int i;
-                               this_opt += 6;
-                               for (i = 0; i < num_panels; i++) {
-                                       if (!strncmp(this_opt,
-                                                    known_lcd_panels[i].name,
-                                                       strlen(this_opt))) {
-                                               panel_idx = i;
-                                               break;
-                                       }
-                               }
-                               if (i >= num_panels) {
-                                       print_warn("Panel %s not supported!", this_opt);
-                               }
-                       }
-                       if (!strncmp(this_opt, "nocursor", 8)) {
-                               this_opt += 8;
-                               nocursor = 1;
-                               print_info("Cursor disabled");
-                       }
-                       /* Mode option (only option that start with digit) */
-                       else if (isdigit(this_opt[0])) {
-                               mode = kstrdup(this_opt, GFP_KERNEL);
-                               if (!mode) {
-                                       print_err("memory allocation failed");
-                                       return -ENOMEM;
-                               }
-                       }
-                       /* Unsupported option */
-                       else {
-                               print_warn("Unsupported option \"%s\"", this_opt);
-                       }
-               }
-       }
-
-       drv_info.panel_idx = panel_idx;
-       drv_info.opt_mode = mode;
-
-       print_info("Panel=%s Mode=%s",
-                       known_lcd_panels[drv_info.panel_idx].name,
-                       drv_info.opt_mode ? drv_info.opt_mode : "default");
-
-       return 0;
-}
-
-int __init au1100fb_init(void)
+static int __init au1100fb_load(void)
 {
-       char* options;
-       int ret;
-
-       print_info("" DRIVER_DESC "");
-
-       memset(&drv_info, 0, sizeof(drv_info));
-
-       if (fb_get_options(DRIVER_NAME, &options))
-               return -ENODEV;
-
-       /* Setup driver with options */
-       ret = au1100fb_setup(options);
-       if (ret < 0) {
-               print_err("Fail to setup driver");
-               return ret;
-       }
-
        return platform_driver_register(&au1100fb_driver);
 }
 
-void __exit au1100fb_cleanup(void)
+static void __exit au1100fb_unload(void)
 {
        platform_driver_unregister(&au1100fb_driver);
-
-       kfree(drv_info.opt_mode);
 }
 
-module_init(au1100fb_init);
-module_exit(au1100fb_cleanup);
+module_init(au1100fb_load);
+module_exit(au1100fb_unload);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
index 164fe2f..12d9642 100644 (file)
@@ -108,6 +108,7 @@ struct au1100fb_device {
        unsigned char*          fb_mem;         /* FrameBuffer memory map */
        size_t                  fb_len;
        dma_addr_t              fb_phys;
+       int                     panel_idx;
 };
 
 /********************************************************************/
@@ -364,11 +365,6 @@ static struct au1100fb_panel known_lcd_panels[] =
        },
 };
 
-struct au1100fb_drv_info {
-       int     panel_idx;
-       char    *opt_mode;
-};
-
 /********************************************************************/
 
 /* Inline helpers */
index 5dff32a..7200559 100644 (file)
 #include <asm/mach-au1x00/au1000.h>
 #include "au1200fb.h"
 
-#ifdef CONFIG_PM
-#include <asm/mach-au1x00/au1xxx_pm.h>
-#endif
-
-#ifndef CONFIG_FB_AU1200_DEVS
-#define CONFIG_FB_AU1200_DEVS 4
-#endif
-
 #define DRIVER_NAME "au1200fb"
 #define DRIVER_DESC "LCD controller driver for AU1200 processors"
 
-#define DEBUG 1
+#define DEBUG 0
 
 #define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg)
 #define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg)
@@ -150,7 +142,7 @@ struct au1200_lcd_iodata_t {
 
 /* Private, per-framebuffer management information (independent of the panel itself) */
 struct au1200fb_device {
-       struct fb_info fb_info;                 /* FB driver info record */
+       struct fb_info *fb_info;                /* FB driver info record */
 
        int                                     plane;
        unsigned char*          fb_mem;         /* FrameBuffer memory map */
@@ -158,7 +150,6 @@ struct au1200fb_device {
        dma_addr_t              fb_phys;
 };
 
-static struct au1200fb_device _au1200fb_devices[CONFIG_FB_AU1200_DEVS];
 /********************************************************************/
 
 /* LCD controller restrictions */
@@ -171,10 +162,18 @@ static struct au1200fb_device _au1200fb_devices[CONFIG_FB_AU1200_DEVS];
 /* Default number of visible screen buffer to allocate */
 #define AU1200FB_NBR_VIDEO_BUFFERS 1
 
+/* Default maximum number of fb devices to create */
+#define MAX_DEVICE_COUNT       4
+
+/* Default window configuration entry to use (see windows[]) */
+#define DEFAULT_WINDOW_INDEX   2
+
 /********************************************************************/
 
+static struct fb_info *_au1200fb_infos[MAX_DEVICE_COUNT];
 static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR;
-static int window_index = 2; /* default is zero */
+static int device_count = MAX_DEVICE_COUNT;
+static int window_index = DEFAULT_WINDOW_INDEX;        /* default is zero */
 static int panel_index = 2; /* default is zero */
 static struct window_settings *win;
 static struct panel_settings *panel;
@@ -205,12 +204,6 @@ struct window_settings {
 extern int board_au1200fb_panel_init (void);
 extern int board_au1200fb_panel_shutdown (void);
 
-#ifdef CONFIG_PM
-int au1200fb_pm_callback(au1xxx_power_dev_t *dev,
-               au1xxx_request_t request, void *data);
-au1xxx_power_dev_t *LCD_pm_dev;
-#endif
-
 /*
  * Default window configurations
  */
@@ -652,25 +645,6 @@ static struct panel_settings known_lcd_panels[] =
 
 /********************************************************************/
 
-#ifdef CONFIG_PM
-static int set_brightness(unsigned int brightness)
-{
-       unsigned int hi1, divider;
-
-       /* limit brightness pwm duty to >= 30/1600 */
-       if (brightness < 30) {
-               brightness = 30;
-       }
-       divider = (lcd->pwmdiv & 0x3FFFF) + 1;
-       hi1 = (lcd->pwmhi >> 16) + 1;
-       hi1 = (((brightness & 0xFF) + 1) * divider >> 8);
-       lcd->pwmhi &= 0xFFFF;
-       lcd->pwmhi |= (hi1 << 16);
-
-       return brightness;
-}
-#endif /* CONFIG_PM */
-
 static int winbpp (unsigned int winctrl1)
 {
        int bits = 0;
@@ -712,8 +686,8 @@ static int fbinfo2index (struct fb_info *fb_info)
 {
        int i;
 
-       for (i = 0; i < CONFIG_FB_AU1200_DEVS; ++i) {
-               if (fb_info == (struct fb_info *)(&_au1200fb_devices[i].fb_info))
+       for (i = 0; i < device_count; ++i) {
+               if (fb_info == _au1200fb_infos[i])
                        return i;
        }
        printk("au1200fb: ERROR: fbinfo2index failed!\n");
@@ -962,7 +936,7 @@ static void au1200_setmode(struct au1200fb_device *fbdev)
        lcd->window[plane].winctrl2 = ( 0
                | LCD_WINCTRL2_CKMODE_00
                | LCD_WINCTRL2_DBM
-               | LCD_WINCTRL2_BX_N( fbdev->fb_info.fix.line_length)
+               | LCD_WINCTRL2_BX_N(fbdev->fb_info->fix.line_length)
                | LCD_WINCTRL2_SCX_1
                | LCD_WINCTRL2_SCY_1
                ) ;
@@ -1050,7 +1024,7 @@ static void au1200fb_update_fbinfo(struct fb_info *fbi)
 static int au1200fb_fb_check_var(struct fb_var_screeninfo *var,
        struct fb_info *fbi)
 {
-       struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi;
+       struct au1200fb_device *fbdev = fbi->par;
        u32 pixclock;
        int screen_size, plane;
 
@@ -1142,7 +1116,7 @@ static int au1200fb_fb_check_var(struct fb_var_screeninfo *var,
  */
 static int au1200fb_fb_set_par(struct fb_info *fbi)
 {
-       struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi;
+       struct au1200fb_device *fbdev = fbi->par;
 
        au1200fb_update_fbinfo(fbi);
        au1200_setmode(fbdev);
@@ -1246,11 +1220,7 @@ static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
 {
        unsigned int len;
        unsigned long start=0, off;
-       struct au1200fb_device *fbdev = (struct au1200fb_device *) info;
-
-#ifdef CONFIG_PM
-       au1xxx_pm_access(LCD_pm_dev);
-#endif
+       struct au1200fb_device *fbdev = info->par;
 
        if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
                return -EINVAL;
@@ -1461,10 +1431,6 @@ static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd,
        int plane;
        int val;
 
-#ifdef CONFIG_PM
-       au1xxx_pm_access(LCD_pm_dev);
-#endif
-
        plane = fbinfo2index(info);
        print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane);
 
@@ -1536,9 +1502,11 @@ static struct fb_ops au1200fb_fb_ops = {
        .fb_set_par     = au1200fb_fb_set_par,
        .fb_setcolreg   = au1200fb_fb_setcolreg,
        .fb_blank       = au1200fb_fb_blank,
-       .fb_fillrect    = cfb_fillrect,
-       .fb_copyarea    = cfb_copyarea,
-       .fb_imageblit   = cfb_imageblit,
+       .fb_fillrect    = sys_fillrect,
+       .fb_copyarea    = sys_copyarea,
+       .fb_imageblit   = sys_imageblit,
+       .fb_read        = fb_sys_read,
+       .fb_write       = fb_sys_write,
        .fb_sync        = NULL,
        .fb_ioctl       = au1200fb_ioctl,
        .fb_mmap        = au1200fb_fb_mmap,
@@ -1561,10 +1529,9 @@ static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id)
 
 static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev)
 {
-       struct fb_info *fbi = &fbdev->fb_info;
+       struct fb_info *fbi = fbdev->fb_info;
        int bpp;
 
-       memset(fbi, 0, sizeof(struct fb_info));
        fbi->fbops = &au1200fb_fb_ops;
 
        bpp = winbpp(win->w[fbdev->plane].mode_winctrl1);
@@ -1623,24 +1590,36 @@ static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev)
 
 /* AU1200 LCD controller device driver */
 
-static int au1200fb_drv_probe(struct platform_device *dev)
+static int __devinit au1200fb_drv_probe(struct platform_device *dev)
 {
        struct au1200fb_device *fbdev;
+       struct fb_info *fbi = NULL;
        unsigned long page;
-       int bpp, plane, ret;
+       int bpp, plane, ret, irq;
 
-       if (!dev)
-               return -EINVAL;
+       /* shut gcc up */
+       ret = 0;
+       fbdev = NULL;
+
+       /* Kickstart the panel */
+       au1200_setpanel(panel);
 
-       for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) {
+       for (plane = 0; plane < device_count; ++plane) {
                bpp = winbpp(win->w[plane].mode_winctrl1);
                if (win->w[plane].xres == 0)
                        win->w[plane].xres = panel->Xres;
                if (win->w[plane].yres == 0)
                        win->w[plane].yres = panel->Yres;
 
-               fbdev = &_au1200fb_devices[plane];
-               memset(fbdev, 0, sizeof(struct au1200fb_device));
+               fbi = framebuffer_alloc(sizeof(struct au1200fb_device),
+                                       &dev->dev);
+               if (!fbi)
+                       goto failed;
+
+               _au1200fb_infos[plane] = fbi;
+               fbdev = fbi->par;
+               fbdev->fb_info = fbi;
+
                fbdev->plane = plane;
 
                /* Allocate the framebuffer to the maximum screen size */
@@ -1673,30 +1652,31 @@ static int au1200fb_drv_probe(struct platform_device *dev)
                        goto failed;
 
                /* Register new framebuffer */
-               if ((ret = register_framebuffer(&fbdev->fb_info)) < 0) {
+               ret = register_framebuffer(fbi);
+               if (ret < 0) {
                        print_err("cannot register new framebuffer");
                        goto failed;
                }
 
-               au1200fb_fb_set_par(&fbdev->fb_info);
+               au1200fb_fb_set_par(fbi);
 
 #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
                if (plane == 0)
-                       if (fb_prepare_logo(&fbdev->fb_info, FB_ROTATE_UR)) {
+                       if (fb_prepare_logo(fbi, FB_ROTATE_UR)) {
                                /* Start display and show logo on boot */
-                               fb_set_cmap(&fbdev->fb_info.cmap,
-                                               &fbdev->fb_info);
-
-                               fb_show_logo(&fbdev->fb_info, FB_ROTATE_UR);
+                               fb_set_cmap(&fbi->cmap, fbi);
+                               fb_show_logo(fbi, FB_ROTATE_UR);
                        }
 #endif
        }
 
        /* Now hook interrupt too */
-       if ((ret = request_irq(AU1200_LCD_INT, au1200fb_handle_irq,
-                         IRQF_DISABLED | IRQF_SHARED, "lcd", (void *)dev)) < 0) {
+       irq = platform_get_irq(dev, 0);
+       ret = request_irq(irq, au1200fb_handle_irq,
+                         IRQF_SHARED, "lcd", (void *)dev);
+       if (ret) {
                print_err("fail to request interrupt line %d (err: %d)",
-                         AU1200_LCD_INT, ret);
+                         irq, ret);
                goto failed;
        }
 
@@ -1705,84 +1685,108 @@ static int au1200fb_drv_probe(struct platform_device *dev)
 failed:
        /* NOTE: This only does the current plane/window that failed; others are still active */
        if (fbdev->fb_mem)
-               dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len),
+               dma_free_noncoherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len),
                                fbdev->fb_mem, fbdev->fb_phys);
-       if (fbdev->fb_info.cmap.len != 0)
-               fb_dealloc_cmap(&fbdev->fb_info.cmap);
-       if (fbdev->fb_info.pseudo_palette)
-               kfree(fbdev->fb_info.pseudo_palette);
+       if (fbi) {
+               if (fbi->cmap.len != 0)
+                       fb_dealloc_cmap(&fbi->cmap);
+               kfree(fbi->pseudo_palette);
+       }
        if (plane == 0)
                free_irq(AU1200_LCD_INT, (void*)dev);
        return ret;
 }
 
-static int au1200fb_drv_remove(struct platform_device *dev)
+static int __devexit au1200fb_drv_remove(struct platform_device *dev)
 {
        struct au1200fb_device *fbdev;
+       struct fb_info *fbi;
        int plane;
 
-       if (!dev)
-               return -ENODEV;
-
        /* Turn off the panel */
        au1200_setpanel(NULL);
 
-       for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane)
-       {
-               fbdev = &_au1200fb_devices[plane];
+       for (plane = 0; plane < device_count; ++plane)  {
+               fbi = _au1200fb_infos[plane];
+               fbdev = fbi->par;
 
                /* Clean up all probe data */
-               unregister_framebuffer(&fbdev->fb_info);
+               unregister_framebuffer(fbi);
                if (fbdev->fb_mem)
                        dma_free_noncoherent(&dev->dev,
                                        PAGE_ALIGN(fbdev->fb_len),
                                        fbdev->fb_mem, fbdev->fb_phys);
-               if (fbdev->fb_info.cmap.len != 0)
-                       fb_dealloc_cmap(&fbdev->fb_info.cmap);
-               if (fbdev->fb_info.pseudo_palette)
-                       kfree(fbdev->fb_info.pseudo_palette);
+               if (fbi->cmap.len != 0)
+                       fb_dealloc_cmap(&fbi->cmap);
+               kfree(fbi->pseudo_palette);
+
+               framebuffer_release(fbi);
+               _au1200fb_infos[plane] = NULL;
        }
 
-       free_irq(AU1200_LCD_INT, (void *)dev);
+       free_irq(platform_get_irq(dev, 0), (void *)dev);
 
        return 0;
 }
 
 #ifdef CONFIG_PM
-static int au1200fb_drv_suspend(struct platform_device *dev, u32 state)
+static int au1200fb_drv_suspend(struct device *dev)
 {
-       /* TODO */
+       au1200_setpanel(NULL);
+
+       lcd->outmask = 0;
+       au_sync();
+
        return 0;
 }
 
-static int au1200fb_drv_resume(struct platform_device *dev)
+static int au1200fb_drv_resume(struct device *dev)
 {
-       /* TODO */
+       struct fb_info *fbi;
+       int i;
+
+       /* Kickstart the panel */
+       au1200_setpanel(panel);
+
+       for (i = 0; i < device_count; i++) {
+               fbi = _au1200fb_infos[i];
+               au1200fb_fb_set_par(fbi);
+       }
+
        return 0;
 }
+
+static const struct dev_pm_ops au1200fb_pmops = {
+       .suspend        = au1200fb_drv_suspend,
+       .resume         = au1200fb_drv_resume,
+       .freeze         = au1200fb_drv_suspend,
+       .thaw           = au1200fb_drv_resume,
+};
+
+#define AU1200FB_PMOPS (&au1200fb_pmops)
+
+#else
+#define AU1200FB_PMOPS NULL
 #endif /* CONFIG_PM */
 
 static struct platform_driver au1200fb_driver = {
        .driver = {
-               .name           = "au1200-lcd",
-               .owner          = THIS_MODULE,
+               .name   = "au1200-lcd",
+               .owner  = THIS_MODULE,
+               .pm     = AU1200FB_PMOPS,
        },
        .probe          = au1200fb_drv_probe,
-       .remove         = au1200fb_drv_remove,
-#ifdef CONFIG_PM
-       .suspend        = au1200fb_drv_suspend,
-       .resume         = au1200fb_drv_resume,
-#endif
+       .remove         = __devexit_p(au1200fb_drv_remove),
 };
 
 /*-------------------------------------------------------------------------*/
 
 /* Kernel driver */
 
-static void au1200fb_setup(void)
+static int au1200fb_setup(void)
 {
-       charoptions = NULL;
-       char* this_opt;
+       char *options = NULL;
+       char *this_opt, *endptr;
        int num_panels = ARRAY_SIZE(known_lcd_panels);
        int panel_idx = -1;
 
@@ -1827,70 +1831,42 @@ static void au1200fb_setup(void)
                                nohwcursor = 1;
                        }
 
-                       /* Unsupported option */
-                       else {
-                               print_warn("Unsupported option \"%s\"", this_opt);
+                       else if (strncmp(this_opt, "devices:", 8) == 0) {
+                               this_opt += 8;
+                               device_count = simple_strtol(this_opt,
+                                                            &endptr, 0);
+                               if ((device_count < 0) ||
+                                   (device_count > MAX_DEVICE_COUNT))
+                                       device_count = MAX_DEVICE_COUNT;
                        }
-               }
-       }
-}
 
-#ifdef CONFIG_PM
-static int au1200fb_pm_callback(au1xxx_power_dev_t *dev,
-               au1xxx_request_t request, void *data) {
-       int retval = -1;
-       unsigned int d = 0;
-       unsigned int brightness = 0;
-
-       if (request == AU1XXX_PM_SLEEP) {
-               board_au1200fb_panel_shutdown();
-       }
-       else if (request == AU1XXX_PM_WAKEUP) {
-               if(dev->prev_state == SLEEP_STATE)
-               {
-                       int plane;
-                       au1200_setpanel(panel);
-                       for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane)         {
-                               struct au1200fb_device *fbdev;
-                               fbdev = &_au1200fb_devices[plane];
-                               au1200fb_fb_set_par(&fbdev->fb_info);
+                       else if (strncmp(this_opt, "wincfg:", 7) == 0) {
+                               this_opt += 7;
+                               window_index = simple_strtol(this_opt,
+                                                            &endptr, 0);
+                               if ((window_index < 0) ||
+                                   (window_index >= ARRAY_SIZE(windows)))
+                                       window_index = DEFAULT_WINDOW_INDEX;
                        }
-               }
 
-               d = *((unsigned int*)data);
-               if(d <=10) brightness = 26;
-               else if(d<=20) brightness = 51;
-               else if(d<=30) brightness = 77;
-               else if(d<=40) brightness = 102;
-               else if(d<=50) brightness = 128;
-               else if(d<=60) brightness = 153;
-               else if(d<=70) brightness = 179;
-               else if(d<=80) brightness = 204;
-               else if(d<=90) brightness = 230;
-               else brightness = 255;
-               set_brightness(brightness);
-       } else if (request == AU1XXX_PM_GETSTATUS) {
-               return dev->cur_state;
-       } else if (request == AU1XXX_PM_ACCESS) {
-               if (dev->cur_state != SLEEP_STATE)
-                       return retval;
-               else {
-                       au1200_setpanel(panel);
+                       else if (strncmp(this_opt, "off", 3) == 0)
+                               return 1;
+                       /* Unsupported option */
+                       else {
+                               print_warn("Unsupported option \"%s\"", this_opt);
+                       }
                }
-       } else if (request == AU1XXX_PM_IDLE) {
-       } else if (request == AU1XXX_PM_CLEANUP) {
        }
-
-       return retval;
+       return 0;
 }
-#endif
 
 static int __init au1200fb_init(void)
 {
        print_info("" DRIVER_DESC "");
 
        /* Setup driver with options */
-       au1200fb_setup();
+       if (au1200fb_setup())
+               return -ENODEV;
 
        /* Point to the panel selected */
        panel = &known_lcd_panels[panel_index];
@@ -1899,17 +1875,6 @@ static int __init au1200fb_init(void)
        printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name);
        printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name);
 
-       /* Kickstart the panel, the framebuffers/windows come soon enough */
-       au1200_setpanel(panel);
-
-       #ifdef CONFIG_PM
-       LCD_pm_dev = new_au1xxx_power_device("LCD", &au1200fb_pm_callback, NULL);
-       if ( LCD_pm_dev == NULL)
-               printk(KERN_INFO "Unable to create a power management device entry for the au1200fb.\n");
-       else
-               printk(KERN_INFO "Power management device entry for the au1200fb loaded.\n");
-       #endif
-
        return platform_driver_register(&au1200fb_driver);
 }
 
index 183b6f6..66bc74d 100644 (file)
@@ -7,7 +7,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/pm.h>
index d06886a..98e0304 100644 (file)
@@ -7,7 +7,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/pm.h>
index 2464b91..56720fb 100644 (file)
@@ -633,7 +633,7 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
                goto out7;
        }
 
-       if (request_irq(info->irq, bfin_bf54x_irq_error, IRQF_DISABLED,
+       if (request_irq(info->irq, bfin_bf54x_irq_error, 0,
                        "PPI ERROR", info) < 0) {
                printk(KERN_ERR DRIVER_NAME
                       ": unable to request PPI ERROR IRQ\n");
index 23b6c4b..c633068 100644 (file)
@@ -695,7 +695,7 @@ static int __devinit bfin_lq035q1_probe(struct platform_device *pdev)
                goto out7;
        }
 
-       ret = request_irq(info->irq, bfin_lq035q1_irq_error, IRQF_DISABLED,
+       ret = request_irq(info->irq, bfin_lq035q1_irq_error, 0,
                        DRIVER_NAME" PPI ERROR", info);
        if (ret < 0) {
                dev_err(&pdev->dev, "unable to request PPI ERROR IRQ\n");
index d8de29f..d5e1267 100644 (file)
@@ -529,7 +529,7 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev)
                goto out7;
        }
 
-       ret = request_irq(info->irq, bfin_t350mcqb_irq_error, IRQF_DISABLED,
+       ret = request_irq(info->irq, bfin_t350mcqb_irq_error, 0,
                        "PPI ERROR", info);
        if (ret < 0) {
                printk(KERN_ERR DRIVER_NAME
index 8486f54..811dd7f 100644 (file)
@@ -481,7 +481,7 @@ static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client,
                goto out_4;
        }
 
-       if (request_irq(IRQ_PPI_ERROR, ppi_irq_error, IRQF_DISABLED,
+       if (request_irq(IRQ_PPI_ERROR, ppi_irq_error, 0,
                        "PPI ERROR", fbdev) < 0) {
                dev_err(&client->dev, "unable to request PPI ERROR IRQ\n");
                ret = -EFAULT;
index caaa27d..cb09aa1 100644 (file)
 #define CARMINEFB_DEFAULT_VIDEO_MODE   1
 
 static unsigned int fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE;
-module_param(fb_mode, uint, 444);
+module_param(fb_mode, uint, 0444);
 MODULE_PARM_DESC(fb_mode, "Initial video mode as integer.");
 
 static char *fb_mode_str;
-module_param(fb_mode_str, charp, 444);
+module_param(fb_mode_str, charp, 0444);
 MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters.");
 
 /*
@@ -46,7 +46,7 @@ MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters.");
  * 0b010 Display 1
  */
 static int fb_displays = CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1;
-module_param(fb_displays, int, 444);
+module_param(fb_displays, int, 0444);
 MODULE_PARM_DESC(fb_displays, "Bit mode, which displays are used");
 
 struct carmine_hw {
index 9075bea..7b2c40a 100644 (file)
@@ -550,7 +550,7 @@ static void control_set_hardware(struct fb_info_control *p, struct fb_par_contro
 
 
 /*
- * Parse user speficied options (`video=controlfb:')
+ * Parse user specified options (`video=controlfb:')
  */
 static void __init control_setup(char *options)
 {
index fcdac87..55f91d9 100644 (file)
@@ -35,6 +35,9 @@
 
 #define DRIVER_NAME "da8xx_lcdc"
 
+#define LCD_VERSION_1  1
+#define LCD_VERSION_2  2
+
 /* LCD Status Register */
 #define LCD_END_OF_FRAME1              BIT(9)
 #define LCD_END_OF_FRAME0              BIT(8)
@@ -49,7 +52,9 @@
 #define LCD_DMA_BURST_4                        0x2
 #define LCD_DMA_BURST_8                        0x3
 #define LCD_DMA_BURST_16               0x4
-#define LCD_END_OF_FRAME_INT_ENA       BIT(2)
+#define LCD_V1_END_OF_FRAME_INT_ENA    BIT(2)
+#define LCD_V2_END_OF_FRAME0_INT_ENA   BIT(8)
+#define LCD_V2_END_OF_FRAME1_INT_ENA   BIT(9)
 #define LCD_DUAL_FRAME_BUFFER_ENABLE   BIT(0)
 
 /* LCD Control Register */
 #define LCD_MONO_8BIT_MODE             BIT(9)
 #define LCD_RASTER_ORDER               BIT(8)
 #define LCD_TFT_MODE                   BIT(7)
-#define LCD_UNDERFLOW_INT_ENA          BIT(6)
-#define LCD_PL_ENABLE                  BIT(4)
+#define LCD_V1_UNDERFLOW_INT_ENA       BIT(6)
+#define LCD_V2_UNDERFLOW_INT_ENA       BIT(5)
+#define LCD_V1_PL_INT_ENA              BIT(4)
+#define LCD_V2_PL_INT_ENA              BIT(6)
 #define LCD_MONOCHROME_MODE            BIT(1)
 #define LCD_RASTER_ENABLE              BIT(0)
 #define LCD_TFT_ALT_ENABLE             BIT(23)
 #define LCD_STN_565_ENABLE             BIT(24)
+#define LCD_V2_DMA_CLK_EN              BIT(2)
+#define LCD_V2_LIDD_CLK_EN             BIT(1)
+#define LCD_V2_CORE_CLK_EN             BIT(0)
+#define LCD_V2_LPP_B10                 26
 
 /* LCD Raster Timing 2 Register */
 #define LCD_AC_BIAS_TRANSITIONS_PER_INT(x)     ((x) << 16)
@@ -82,6 +93,7 @@
 #define LCD_INVERT_FRAME_CLOCK                 BIT(20)
 
 /* LCD Block */
+#define  LCD_PID_REG                           0x0
 #define  LCD_CTRL_REG                          0x4
 #define  LCD_STAT_REG                          0x8
 #define  LCD_RASTER_CTRL_REG                   0x28
 #define  LCD_DMA_FRM_BUF_BASE_ADDR_1_REG       0x4C
 #define  LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG    0x50
 
+/* Interrupt Registers available only in Version 2 */
+#define  LCD_RAW_STAT_REG                      0x58
+#define  LCD_MASKED_STAT_REG                   0x5c
+#define  LCD_INT_ENABLE_SET_REG                        0x60
+#define  LCD_INT_ENABLE_CLR_REG                        0x64
+#define  LCD_END_OF_INT_IND_REG                        0x68
+
+/* Clock registers available only on Version 2 */
+#define  LCD_CLK_ENABLE_REG                    0x6c
+#define  LCD_CLK_RESET_REG                     0x70
+
 #define LCD_NUM_BUFFERS        2
 
 #define WSI_TIMEOUT    50
 
 static resource_size_t da8xx_fb_reg_base;
 static struct resource *lcdc_regs;
+static unsigned int lcd_revision;
+static irq_handler_t lcdc_irq_handler;
 
 static inline unsigned int lcdc_read(unsigned int addr)
 {
@@ -240,6 +265,7 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
        u32 end;
        u32 reg_ras;
        u32 reg_dma;
+       u32 reg_int;
 
        /* init reg to clear PLM (loading mode) fields */
        reg_ras = lcdc_read(LCD_RASTER_CTRL_REG);
@@ -252,7 +278,14 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
                end      = par->dma_end;
 
                reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY);
-               reg_dma |= LCD_END_OF_FRAME_INT_ENA;
+               if (lcd_revision == LCD_VERSION_1) {
+                       reg_dma |= LCD_V1_END_OF_FRAME_INT_ENA;
+               } else {
+                       reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
+                               LCD_V2_END_OF_FRAME0_INT_ENA |
+                               LCD_V2_END_OF_FRAME1_INT_ENA;
+                       lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
+               }
                reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE;
 
                lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
@@ -264,7 +297,14 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
                end      = start + par->palette_sz - 1;
 
                reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY);
-               reg_ras |= LCD_PL_ENABLE;
+
+               if (lcd_revision == LCD_VERSION_1) {
+                       reg_ras |= LCD_V1_PL_INT_ENA;
+               } else {
+                       reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
+                               LCD_V2_PL_INT_ENA;
+                       lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
+               }
 
                lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
                lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
@@ -348,6 +388,7 @@ static void lcd_cfg_vertical_sync(int back_porch, int pulse_width,
 static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
 {
        u32 reg;
+       u32 reg_int;
 
        reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE |
                                                LCD_MONO_8BIT_MODE |
@@ -375,7 +416,13 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
        }
 
        /* enable additional interrupts here */
-       reg |= LCD_UNDERFLOW_INT_ENA;
+       if (lcd_revision == LCD_VERSION_1) {
+               reg |= LCD_V1_UNDERFLOW_INT_ENA;
+       } else {
+               reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
+                       LCD_V2_UNDERFLOW_INT_ENA;
+               lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
+       }
 
        lcdc_write(reg, LCD_RASTER_CTRL_REG);
 
@@ -413,18 +460,43 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
 
        /* Set the Panel Width */
        /* Pixels per line = (PPL + 1)*16 */
-       /*0x3F in bits 4..9 gives max horisontal resolution = 1024 pixels*/
-       width &= 0x3f0;
+       if (lcd_revision == LCD_VERSION_1) {
+               /*
+                * 0x3F in bits 4..9 gives max horizontal resolution = 1024
+                * pixels.
+                */
+               width &= 0x3f0;
+       } else {
+               /*
+                * 0x7F in bits 4..10 gives max horizontal resolution = 2048
+                * pixels.
+                */
+               width &= 0x7f0;
+       }
+
        reg = lcdc_read(LCD_RASTER_TIMING_0_REG);
        reg &= 0xfffffc00;
-       reg |= ((width >> 4) - 1) << 4;
+       if (lcd_revision == LCD_VERSION_1) {
+               reg |= ((width >> 4) - 1) << 4;
+       } else {
+               width = (width >> 4) - 1;
+               reg |= ((width & 0x3f) << 4) | ((width & 0x40) >> 3);
+       }
        lcdc_write(reg, LCD_RASTER_TIMING_0_REG);
 
        /* Set the Panel Height */
+       /* Set bits 9:0 of Lines Per Pixel */
        reg = lcdc_read(LCD_RASTER_TIMING_1_REG);
        reg = ((height - 1) & 0x3ff) | (reg & 0xfffffc00);
        lcdc_write(reg, LCD_RASTER_TIMING_1_REG);
 
+       /* Set bit 10 of Lines Per Pixel */
+       if (lcd_revision == LCD_VERSION_2) {
+               reg = lcdc_read(LCD_RASTER_TIMING_2_REG);
+               reg |= ((height - 1) & 0x400) << 16;
+               lcdc_write(reg, LCD_RASTER_TIMING_2_REG);
+       }
+
        /* Set the Raster Order of the Frame Buffer */
        reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8);
        if (raster_order)
@@ -511,6 +583,9 @@ static void lcd_reset(struct da8xx_fb_par *par)
        /* DMA has to be disabled */
        lcdc_write(0, LCD_DMA_CTRL_REG);
        lcdc_write(0, LCD_RASTER_CTRL_REG);
+
+       if (lcd_revision == LCD_VERSION_2)
+               lcdc_write(0, LCD_INT_ENABLE_SET_REG);
 }
 
 static void lcd_calc_clk_divider(struct da8xx_fb_par *par)
@@ -523,6 +598,11 @@ static void lcd_calc_clk_divider(struct da8xx_fb_par *par)
        /* Configure the LCD clock divisor. */
        lcdc_write(LCD_CLK_DIVISOR(div) |
                        (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG);
+
+       if (lcd_revision == LCD_VERSION_2)
+               lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN |
+                               LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG);
+
 }
 
 static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
@@ -583,7 +663,63 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
        return 0;
 }
 
-static irqreturn_t lcdc_irq_handler(int irq, void *arg)
+/* IRQ handler for version 2 of LCDC */
+static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
+{
+       struct da8xx_fb_par *par = arg;
+       u32 stat = lcdc_read(LCD_MASKED_STAT_REG);
+       u32 reg_int;
+
+       if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
+               lcd_disable_raster();
+               lcdc_write(stat, LCD_MASKED_STAT_REG);
+               lcd_enable_raster();
+       } else if (stat & LCD_PL_LOAD_DONE) {
+               /*
+                * Must disable raster before changing state of any control bit.
+                * And also must be disabled before clearing the PL loading
+                * interrupt via the following write to the status register. If
+                * this is done after then one gets multiple PL done interrupts.
+                */
+               lcd_disable_raster();
+
+               lcdc_write(stat, LCD_MASKED_STAT_REG);
+
+               /* Disable PL completion inerrupt */
+               reg_int = lcdc_read(LCD_INT_ENABLE_CLR_REG) |
+                      (LCD_V2_PL_INT_ENA);
+               lcdc_write(reg_int, LCD_INT_ENABLE_CLR_REG);
+
+               /* Setup and start data loading mode */
+               lcd_blit(LOAD_DATA, par);
+       } else {
+               lcdc_write(stat, LCD_MASKED_STAT_REG);
+
+               if (stat & LCD_END_OF_FRAME0) {
+                       lcdc_write(par->dma_start,
+                                  LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
+                       lcdc_write(par->dma_end,
+                                  LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
+                       par->vsync_flag = 1;
+                       wake_up_interruptible(&par->vsync_wait);
+               }
+
+               if (stat & LCD_END_OF_FRAME1) {
+                       lcdc_write(par->dma_start,
+                                  LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
+                       lcdc_write(par->dma_end,
+                                  LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
+                       par->vsync_flag = 1;
+                       wake_up_interruptible(&par->vsync_wait);
+               }
+       }
+
+       lcdc_write(0, LCD_END_OF_INT_IND_REG);
+       return IRQ_HANDLED;
+}
+
+/* IRQ handler for version 1 LCDC */
+static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)
 {
        struct da8xx_fb_par *par = arg;
        u32 stat = lcdc_read(LCD_STAT_REG);
@@ -606,7 +742,7 @@ static irqreturn_t lcdc_irq_handler(int irq, void *arg)
 
                /* Disable PL completion inerrupt */
                reg_ras  = lcdc_read(LCD_RASTER_CTRL_REG);
-               reg_ras &= ~LCD_PL_ENABLE;
+               reg_ras &= ~LCD_V1_PL_INT_ENA;
                lcdc_write(reg_ras, LCD_RASTER_CTRL_REG);
 
                /* Setup and start data loading mode */
@@ -877,8 +1013,8 @@ static int da8xx_pan_display(struct fb_var_screeninfo *var,
 
                        start   = fix->smem_start +
                                new_var.yoffset * fix->line_length +
-                               new_var.xoffset * var->bits_per_pixel / 8;
-                       end     = start + var->yres * fix->line_length - 1;
+                               new_var.xoffset * fbi->var.bits_per_pixel / 8;
+                       end     = start + fbi->var.yres * fix->line_length - 1;
                        par->dma_start  = start;
                        par->dma_end    = end;
                }
@@ -945,6 +1081,22 @@ static int __devinit fb_probe(struct platform_device *device)
        if (ret)
                goto err_clk_put;
 
+       /* Determine LCD IP Version */
+       switch (lcdc_read(LCD_PID_REG)) {
+       case 0x4C100102:
+               lcd_revision = LCD_VERSION_1;
+               break;
+       case 0x4F200800:
+               lcd_revision = LCD_VERSION_2;
+               break;
+       default:
+               dev_warn(&device->dev, "Unknown PID Reg value 0x%x, "
+                               "defaulting to LCD revision 1\n",
+                               lcdc_read(LCD_PID_REG));
+               lcd_revision = LCD_VERSION_1;
+               break;
+       }
+
        for (i = 0, lcdc_info = known_lcd_panels;
                i < ARRAY_SIZE(known_lcd_panels);
                i++, lcdc_info++) {
@@ -1085,7 +1237,13 @@ static int __devinit fb_probe(struct platform_device *device)
        }
 #endif
 
-       ret = request_irq(par->irq, lcdc_irq_handler, 0, DRIVER_NAME, par);
+       if (lcd_revision == LCD_VERSION_1)
+               lcdc_irq_handler = lcdc_irq_handler_rev01;
+       else
+               lcdc_irq_handler = lcdc_irq_handler_rev02;
+
+       ret = request_irq(par->irq, lcdc_irq_handler, 0,
+                       DRIVER_NAME, par);
        if (ret)
                goto irq_freq;
        return 0;
index 27f2c57..60a787f 100644 (file)
@@ -624,8 +624,8 @@ static int unifb_pan_display(struct fb_var_screeninfo *var,
                    || var->xoffset)
                        return -EINVAL;
        } else {
-               if (var->xoffset + var->xres > info->var.xres_virtual ||
-                   var->yoffset + var->yres > info->var.yres_virtual)
+               if (var->xoffset + info->var.xres > info->var.xres_virtual ||
+                   var->yoffset + info->var.yres > info->var.yres_virtual)
                        return -EINVAL;
        }
        info->var.xoffset = var->xoffset;
index 32814e8..c27e153 100644 (file)
@@ -223,8 +223,7 @@ void fb_deferred_io_cleanup(struct fb_info *info)
        int i;
 
        BUG_ON(!fbdefio);
-       cancel_delayed_work(&info->deferred_work);
-       flush_scheduled_work();
+       cancel_delayed_work_sync(&info->deferred_work);
 
        /* clear out the mapping that we setup */
        for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) {
index 5aac00e..ad93629 100644 (file)
@@ -1738,8 +1738,6 @@ void fb_set_suspend(struct fb_info *info, int state)
 {
        struct fb_event event;
 
-       if (!lock_fb_info(info))
-               return;
        event.info = info;
        if (state) {
                fb_notifier_call_chain(FB_EVENT_SUSPEND, &event);
@@ -1748,7 +1746,6 @@ void fb_set_suspend(struct fb_info *info, int state)
                info->state = FBINFO_STATE_RUNNING;
                fb_notifier_call_chain(FB_EVENT_RESUME, &event);
        }
-       unlock_fb_info(info);
 }
 
 /**
index 4f57485..cef6557 100644 (file)
@@ -493,7 +493,8 @@ static int get_est_timing(unsigned char *block, struct fb_videomode *mode)
        return num;
 }
 
-static int get_std_timing(unsigned char *block, struct fb_videomode *mode)
+static int get_std_timing(unsigned char *block, struct fb_videomode *mode,
+               int ver, int rev)
 {
        int xres, yres = 0, refresh, ratio, i;
 
@@ -504,7 +505,11 @@ static int get_std_timing(unsigned char *block, struct fb_videomode *mode)
        ratio = (block[1] & 0xc0) >> 6;
        switch (ratio) {
        case 0:
-               yres = xres;
+               /* in EDID 1.3 the meaning of 0 changed to 16:10 (prior 1:1) */
+               if (ver < 1 || (ver == 1 && rev < 3))
+                       yres = xres;
+               else
+                       yres = (xres * 10)/16;
                break;
        case 1:
                yres = (xres * 3)/4;
@@ -533,12 +538,12 @@ static int get_std_timing(unsigned char *block, struct fb_videomode *mode)
 }
 
 static int get_dst_timing(unsigned char *block,
-                         struct fb_videomode *mode)
+                         struct fb_videomode *mode, int ver, int rev)
 {
        int j, num = 0;
 
        for (j = 0; j < 6; j++, block += STD_TIMING_DESCRIPTION_SIZE)
-               num += get_std_timing(block, &mode[num]);
+               num += get_std_timing(block, &mode[num], ver, rev);
 
        return num;
 }
@@ -599,6 +604,10 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
        struct fb_videomode *mode, *m;
        unsigned char *block;
        int num = 0, i, first = 1;
+       int ver, rev;
+
+       ver = edid[EDID_STRUCT_VERSION];
+       rev = edid[EDID_STRUCT_REVISION];
 
        mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
        if (mode == NULL)
@@ -632,12 +641,12 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
        DPRINTK("   Standard Timings\n");
        block = edid + STD_TIMING_DESCRIPTIONS_START;
        for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE)
-               num += get_std_timing(block, &mode[num]);
+               num += get_std_timing(block, &mode[num], ver, rev);
 
        block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
        for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
                if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa)
-                       num += get_dst_timing(block + 5, &mode[num]);
+                       num += get_dst_timing(block + 5, &mode[num], ver, rev);
        }
 
        /* Yikes, EDID data is totally useless */
index 04251ce..67afa9c 100644 (file)
@@ -399,9 +399,12 @@ static ssize_t store_fbstate(struct device *device,
 
        state = simple_strtoul(buf, &last, 0);
 
+       if (!lock_fb_info(fb_info))
+               return -ENODEV;
        console_lock();
        fb_set_suspend(fb_info, (int)state);
        console_unlock();
+       unlock_fb_info(fb_info);
 
        return count;
 }
index 0acc7d6..a16beeb 100644 (file)
 #include <linux/clk.h>
 #include <linux/uaccess.h>
 #include <linux/vmalloc.h>
-
-#include <linux/of_platform.h>
+#include <linux/spinlock.h>
 
 #include <sysdev/fsl_soc.h>
 #include <linux/fsl-diu-fb.h>
 #include "edid.h"
 
-/*
- * These parameters give default parameters
- * for video output 1024x768,
- * FIXME - change timing to proper amounts
- * hsync 31.5kHz, vsync 60Hz
- */
-static struct fb_videomode __devinitdata fsl_diu_default_mode = {
-       .refresh        = 60,
-       .xres           = 1024,
-       .yres           = 768,
-       .pixclock       = 15385,
-       .left_margin    = 160,
-       .right_margin   = 24,
-       .upper_margin   = 29,
-       .lower_margin   = 3,
-       .hsync_len      = 136,
-       .vsync_len      = 6,
-       .sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-       .vmode          = FB_VMODE_NONINTERLACED
+#define FSL_AOI_NUM    6       /* 5 AOIs and one dummy AOI */
+                               /* 1 for plane 0, 2 for plane 1&2 each */
+
+/* HW cursor parameters */
+#define MAX_CURS               32
+
+/* INT_STATUS/INT_MASK field descriptions */
+#define INT_VSYNC      0x01    /* Vsync interrupt  */
+#define INT_VSYNC_WB   0x02    /* Vsync interrupt for write back operation */
+#define INT_UNDRUN     0x04    /* Under run exception interrupt */
+#define INT_PARERR     0x08    /* Display parameters error interrupt */
+#define INT_LS_BF_VS   0x10    /* Lines before vsync. interrupt */
+
+struct diu_addr {
+       void *vaddr;            /* Virtual address */
+       dma_addr_t paddr;       /* Physical address */
+       __u32 offset;
 };
 
+/*
+ * List of supported video modes
+ *
+ * The first entry is the default video mode.  The remain entries are in
+ * order if increasing resolution and frequency.  The 320x240-60 mode is
+ * the initial AOI for the second and third planes.
+ */
 static struct fb_videomode __devinitdata fsl_diu_mode_db[] = {
        {
-               .name           = "1024x768-60",
                .refresh        = 60,
                .xres           = 1024,
                .yres           = 768,
@@ -75,7 +78,132 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = {
                .vmode          = FB_VMODE_NONINTERLACED
        },
        {
-               .name           = "1024x768-70",
+               .refresh        = 60,
+               .xres           = 320,
+               .yres           = 240,
+               .pixclock       = 79440,
+               .left_margin    = 16,
+               .right_margin   = 16,
+               .upper_margin   = 16,
+               .lower_margin   = 5,
+               .hsync_len      = 48,
+               .vsync_len      = 1,
+               .sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+               .vmode          = FB_VMODE_NONINTERLACED
+       },
+       {
+               .refresh        = 60,
+               .xres           = 640,
+               .yres           = 480,
+               .pixclock       = 39722,
+               .left_margin    = 48,
+               .right_margin   = 16,
+               .upper_margin   = 33,
+               .lower_margin   = 10,
+               .hsync_len      = 96,
+               .vsync_len      = 2,
+               .sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+               .vmode          = FB_VMODE_NONINTERLACED
+       },
+       {
+               .refresh        = 72,
+               .xres           = 640,
+               .yres           = 480,
+               .pixclock       = 32052,
+               .left_margin    = 128,
+               .right_margin   = 24,
+               .upper_margin   = 28,
+               .lower_margin   = 9,
+               .hsync_len      = 40,
+               .vsync_len      = 3,
+               .sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+               .vmode          = FB_VMODE_NONINTERLACED
+       },
+       {
+               .refresh        = 75,
+               .xres           = 640,
+               .yres           = 480,
+               .pixclock       = 31747,
+               .left_margin    = 120,
+               .right_margin   = 16,
+               .upper_margin   = 16,
+               .lower_margin   = 1,
+               .hsync_len      = 64,
+               .vsync_len      = 3,
+               .sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+               .vmode          = FB_VMODE_NONINTERLACED
+       },
+       {
+               .refresh        = 90,
+               .xres           = 640,
+               .yres           = 480,
+               .pixclock       = 25057,
+               .left_margin    = 120,
+               .right_margin   = 32,
+               .upper_margin   = 14,
+               .lower_margin   = 25,
+               .hsync_len      = 40,
+               .vsync_len      = 14,
+               .sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+               .vmode          = FB_VMODE_NONINTERLACED
+       },
+       {
+               .refresh        = 100,
+               .xres           = 640,
+               .yres           = 480,
+               .pixclock       = 22272,
+               .left_margin    = 48,
+               .right_margin   = 32,
+               .upper_margin   = 17,
+               .lower_margin   = 22,
+               .hsync_len      = 128,
+               .vsync_len      = 12,
+               .sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+               .vmode          = FB_VMODE_NONINTERLACED
+       },
+       {
+               .refresh        = 60,
+               .xres           = 800,
+               .yres           = 480,
+               .pixclock       = 33805,
+               .left_margin    = 96,
+               .right_margin   = 24,
+               .upper_margin   = 10,
+               .lower_margin   = 3,
+               .hsync_len      = 72,
+               .vsync_len      = 7,
+               .sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+               .vmode          = FB_VMODE_NONINTERLACED
+       },
+       {
+               .refresh        = 60,
+               .xres           = 800,
+               .yres           = 600,
+               .pixclock       = 25000,
+               .left_margin    = 88,
+               .right_margin   = 40,
+               .upper_margin   = 23,
+               .lower_margin   = 1,
+               .hsync_len      = 128,
+               .vsync_len      = 4,
+               .sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+               .vmode          = FB_VMODE_NONINTERLACED
+       },
+       {
+               .refresh        = 60,
+               .xres           = 854,
+               .yres           = 480,
+               .pixclock       = 31518,
+               .left_margin    = 104,
+               .right_margin   = 16,
+               .upper_margin   = 13,
+               .lower_margin   = 1,
+               .hsync_len      = 88,
+               .vsync_len      = 3,
+               .sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+               .vmode          = FB_VMODE_NONINTERLACED
+       },
+       {
                .refresh        = 70,
                .xres           = 1024,
                .yres           = 768,
@@ -90,7 +218,6 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = {
                .vmode          = FB_VMODE_NONINTERLACED
        },
        {
-               .name           = "1024x768-75",
                .refresh        = 75,
                .xres           = 1024,
                .yres           = 768,
@@ -105,7 +232,34 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = {
                .vmode          = FB_VMODE_NONINTERLACED
        },
        {
-               .name           = "1280x1024-60",
+               .refresh        = 60,
+               .xres           = 1280,
+               .yres           = 480,
+               .pixclock       = 18939,
+               .left_margin    = 353,
+               .right_margin   = 47,
+               .upper_margin   = 39,
+               .lower_margin   = 4,
+               .hsync_len      = 8,
+               .vsync_len      = 2,
+               .sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+               .vmode          = FB_VMODE_NONINTERLACED
+       },
+       {
+               .refresh        = 60,
+               .xres           = 1280,
+               .yres           = 720,
+               .pixclock       = 13426,
+               .left_margin    = 192,
+               .right_margin   = 64,
+               .upper_margin   = 22,
+               .lower_margin   = 1,
+               .hsync_len      = 136,
+               .vsync_len      = 3,
+               .sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+               .vmode          = FB_VMODE_NONINTERLACED
+       },
+       {
                .refresh        = 60,
                .xres           = 1280,
                .yres           = 1024,
@@ -120,7 +274,6 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = {
                .vmode          = FB_VMODE_NONINTERLACED
        },
        {
-               .name           = "1280x1024-70",
                .refresh        = 70,
                .xres           = 1280,
                .yres           = 1024,
@@ -135,7 +288,6 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = {
                .vmode          = FB_VMODE_NONINTERLACED
        },
        {
-               .name           = "1280x1024-75",
                .refresh        = 75,
                .xres           = 1280,
                .yres           = 1024,
@@ -150,40 +302,25 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = {
                .vmode          = FB_VMODE_NONINTERLACED
        },
        {
-               .name           = "320x240",            /* for AOI only */
                .refresh        = 60,
-               .xres           = 320,
-               .yres           = 240,
-               .pixclock       = 15385,
-               .left_margin    = 0,
-               .right_margin   = 0,
-               .upper_margin   = 0,
-               .lower_margin   = 0,
-               .hsync_len      = 0,
-               .vsync_len      = 0,
-               .sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-               .vmode          = FB_VMODE_NONINTERLACED
-       },
-       {
-               .name           = "1280x480-60",
-               .refresh        = 60,
-               .xres           = 1280,
-               .yres           = 480,
-               .pixclock       = 18939,
-               .left_margin    = 353,
-               .right_margin   = 47,
-               .upper_margin   = 39,
-               .lower_margin   = 4,
-               .hsync_len      = 8,
-               .vsync_len      = 2,
+               .xres           = 1920,
+               .yres           = 1080,
+               .pixclock       = 5787,
+               .left_margin    = 328,
+               .right_margin   = 120,
+               .upper_margin   = 34,
+               .lower_margin   = 1,
+               .hsync_len      = 208,
+               .vsync_len      = 3,
                .sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
                .vmode          = FB_VMODE_NONINTERLACED
        },
 };
 
-static char *fb_mode = "1024x768-32@60";
+static char *fb_mode;
 static unsigned long default_bpp = 32;
-static int monitor_port;
+static enum fsl_diu_monitor_port monitor_port;
+static char *monitor_string;
 
 #if defined(CONFIG_NOT_COHERENT_CACHE)
 static u8 *coherence_data;
@@ -201,15 +338,27 @@ struct fsl_diu_data {
        void *dummy_aoi_virt;
        unsigned int irq;
        int fb_enabled;
-       int monitor_port;
+       enum fsl_diu_monitor_port monitor_port;
+       struct diu __iomem *diu_reg;
+       spinlock_t reg_lock;
+       struct diu_addr ad;
+       struct diu_addr gamma;
+       struct diu_addr pallete;
+       struct diu_addr cursor;
+};
+
+enum mfb_index {
+       PLANE0 = 0,     /* Plane 0, only one AOI that fills the screen */
+       PLANE1_AOI0,    /* Plane 1, first AOI */
+       PLANE1_AOI1,    /* Plane 1, second AOI */
+       PLANE2_AOI0,    /* Plane 2, first AOI */
+       PLANE2_AOI1,    /* Plane 2, second AOI */
 };
 
 struct mfb_info {
-       int index;
-       int type;
+       enum mfb_index index;
        char *id;
        int registered;
-       int blank;
        unsigned long pseudo_palette[16];
        struct diu_ad *ad;
        int cursor_reset;
@@ -223,63 +372,82 @@ struct mfb_info {
 
 
 static struct mfb_info mfb_template[] = {
-       {               /* AOI 0 for plane 0 */
-       .index = 0,
-       .type = MFB_TYPE_OUTPUT,
-       .id = "Panel0",
-       .registered = 0,
-       .count = 0,
-       .x_aoi_d = 0,
-       .y_aoi_d = 0,
+       {
+               .index = PLANE0,
+               .id = "Panel0",
+               .registered = 0,
+               .count = 0,
+               .x_aoi_d = 0,
+               .y_aoi_d = 0,
        },
-       {               /* AOI 0 for plane 1 */
-       .index = 1,
-       .type = MFB_TYPE_OUTPUT,
-       .id = "Panel1 AOI0",
-       .registered = 0,
-       .g_alpha = 0xff,
-       .count = 0,
-       .x_aoi_d = 0,
-       .y_aoi_d = 0,
+       {
+               .index = PLANE1_AOI0,
+               .id = "Panel1 AOI0",
+               .registered = 0,
+               .g_alpha = 0xff,
+               .count = 0,
+               .x_aoi_d = 0,
+               .y_aoi_d = 0,
        },
-       {               /* AOI 1 for plane 1 */
-       .index = 2,
-       .type = MFB_TYPE_OUTPUT,
-       .id = "Panel1 AOI1",
-       .registered = 0,
-       .g_alpha = 0xff,
-       .count = 0,
-       .x_aoi_d = 0,
-       .y_aoi_d = 480,
+       {
+               .index = PLANE1_AOI1,
+               .id = "Panel1 AOI1",
+               .registered = 0,
+               .g_alpha = 0xff,
+               .count = 0,
+               .x_aoi_d = 0,
+               .y_aoi_d = 480,
        },
-       {               /* AOI 0 for plane 2 */
-       .index = 3,
-       .type = MFB_TYPE_OUTPUT,
-       .id = "Panel2 AOI0",
-       .registered = 0,
-       .g_alpha = 0xff,
-       .count = 0,
-       .x_aoi_d = 640,
-       .y_aoi_d = 0,
+       {
+               .index = PLANE2_AOI0,
+               .id = "Panel2 AOI0",
+               .registered = 0,
+               .g_alpha = 0xff,
+               .count = 0,
+               .x_aoi_d = 640,
+               .y_aoi_d = 0,
        },
-       {               /* AOI 1 for plane 2 */
-       .index = 4,
-       .type = MFB_TYPE_OUTPUT,
-       .id = "Panel2 AOI1",
-       .registered = 0,
-       .g_alpha = 0xff,
-       .count = 0,
-       .x_aoi_d = 640,
-       .y_aoi_d = 480,
+       {
+               .index = PLANE2_AOI1,
+               .id = "Panel2 AOI1",
+               .registered = 0,
+               .g_alpha = 0xff,
+               .count = 0,
+               .x_aoi_d = 640,
+               .y_aoi_d = 480,
        },
 };
 
-static struct diu_hw dr = {
-       .mode = MFB_MODE1,
-       .reg_lock = __SPIN_LOCK_UNLOCKED(diu_hw.reg_lock),
-};
+/**
+ * fsl_diu_name_to_port - convert a port name to a monitor port enum
+ *
+ * Takes the name of a monitor port ("dvi", "lvds", or "dlvds") and returns
+ * the enum fsl_diu_monitor_port that corresponds to that string.
+ *
+ * For compatibility with older versions, a number ("0", "1", or "2") is also
+ * supported.
+ *
+ * If the string is unknown, DVI is assumed.
+ *
+ * If the particular port is not supported by the platform, another port
+ * (platform-specific) is chosen instead.
+ */
+static enum fsl_diu_monitor_port fsl_diu_name_to_port(const char *s)
+{
+       enum fsl_diu_monitor_port port = FSL_DIU_PORT_DVI;
+       unsigned long val;
 
-static struct diu_pool pool;
+       if (s) {
+               if (!strict_strtoul(s, 10, &val) && (val <= 2))
+                       port = (enum fsl_diu_monitor_port) val;
+               else if (strncmp(s, "lvds", 4) == 0)
+                       port = FSL_DIU_PORT_LVDS;
+               else if (strncmp(s, "dlvds", 5) == 0)
+                       port = FSL_DIU_PORT_DLVDS;
+       }
+
+       return diu_ops.valid_monitor_port(port);
+}
 
 /**
  * fsl_diu_alloc - allocate memory for the DIU
@@ -292,14 +460,9 @@ static void *fsl_diu_alloc(size_t size, phys_addr_t *phys)
 {
        void *virt;
 
-       pr_debug("size=%zu\n", size);
-
        virt = alloc_pages_exact(size, GFP_DMA | __GFP_ZERO);
-       if (virt) {
+       if (virt)
                *phys = virt_to_phys(virt);
-               pr_debug("virt=%p phys=%llx\n", virt,
-                       (unsigned long long)*phys);
-       }
 
        return virt;
 }
@@ -313,8 +476,6 @@ static void *fsl_diu_alloc(size_t size, phys_addr_t *phys)
  */
 static void fsl_diu_free(void *virt, size_t size)
 {
-       pr_debug("virt=%p size=%zu\n", virt, size);
-
        if (virt && size)
                free_pages_exact(virt, size);
 }
@@ -330,82 +491,72 @@ void wr_reg_wa(u32 *reg, u32 val)
        } while (in_be32(reg) != val);
 }
 
-static int fsl_diu_enable_panel(struct fb_info *info)
+static void fsl_diu_enable_panel(struct fb_info *info)
 {
        struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par;
-       struct diu *hw = dr.diu_reg;
        struct diu_ad *ad = mfbi->ad;
        struct fsl_diu_data *machine_data = mfbi->parent;
-       int res = 0;
+       struct diu __iomem *hw = machine_data->diu_reg;
 
-       pr_debug("enable_panel index %d\n", mfbi->index);
-       if (mfbi->type != MFB_TYPE_OFF) {
-               switch (mfbi->index) {
-               case 0:                         /* plane 0 */
-                       if (hw->desc[0] != ad->paddr)
-                               wr_reg_wa(&hw->desc[0], ad->paddr);
-                       break;
-               case 1:                         /* plane 1 AOI 0 */
-                       cmfbi = machine_data->fsl_diu_info[2]->par;
-                       if (hw->desc[1] != ad->paddr) { /* AOI0 closed */
-                               if (cmfbi->count > 0)   /* AOI1 open */
-                                       ad->next_ad =
-                                               cpu_to_le32(cmfbi->ad->paddr);
-                               else
-                                       ad->next_ad = 0;
-                               wr_reg_wa(&hw->desc[1], ad->paddr);
-                       }
-                       break;
-               case 3:                         /* plane 2 AOI 0 */
-                       cmfbi = machine_data->fsl_diu_info[4]->par;
-                       if (hw->desc[2] != ad->paddr) { /* AOI0 closed */
-                               if (cmfbi->count > 0)   /* AOI1 open */
-                                       ad->next_ad =
-                                               cpu_to_le32(cmfbi->ad->paddr);
-                               else
-                                       ad->next_ad = 0;
-                               wr_reg_wa(&hw->desc[2], ad->paddr);
-                       }
-                       break;
-               case 2:                         /* plane 1 AOI 1 */
-                       pmfbi = machine_data->fsl_diu_info[1]->par;
-                       ad->next_ad = 0;
-                       if (hw->desc[1] == machine_data->dummy_ad->paddr)
-                               wr_reg_wa(&hw->desc[1], ad->paddr);
-                       else                                    /* AOI0 open */
-                               pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
-                       break;
-               case 4:                         /* plane 2 AOI 1 */
-                       pmfbi = machine_data->fsl_diu_info[3]->par;
-                       ad->next_ad = 0;
-                       if (hw->desc[2] == machine_data->dummy_ad->paddr)
-                               wr_reg_wa(&hw->desc[2], ad->paddr);
-                       else                            /* AOI0 was open */
-                               pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
-                       break;
-               default:
-                       res = -EINVAL;
-                       break;
+       switch (mfbi->index) {
+       case PLANE0:
+               if (hw->desc[0] != ad->paddr)
+                       wr_reg_wa(&hw->desc[0], ad->paddr);
+               break;
+       case PLANE1_AOI0:
+               cmfbi = machine_data->fsl_diu_info[2]->par;
+               if (hw->desc[1] != ad->paddr) { /* AOI0 closed */
+                       if (cmfbi->count > 0)   /* AOI1 open */
+                               ad->next_ad =
+                                       cpu_to_le32(cmfbi->ad->paddr);
+                       else
+                               ad->next_ad = 0;
+                       wr_reg_wa(&hw->desc[1], ad->paddr);
                }
-       } else
-               res = -EINVAL;
-       return res;
+               break;
+       case PLANE2_AOI0:
+               cmfbi = machine_data->fsl_diu_info[4]->par;
+               if (hw->desc[2] != ad->paddr) { /* AOI0 closed */
+                       if (cmfbi->count > 0)   /* AOI1 open */
+                               ad->next_ad =
+                                       cpu_to_le32(cmfbi->ad->paddr);
+                       else
+                               ad->next_ad = 0;
+                       wr_reg_wa(&hw->desc[2], ad->paddr);
+               }
+               break;
+       case PLANE1_AOI1:
+               pmfbi = machine_data->fsl_diu_info[1]->par;
+               ad->next_ad = 0;
+               if (hw->desc[1] == machine_data->dummy_ad->paddr)
+                       wr_reg_wa(&hw->desc[1], ad->paddr);
+               else                                    /* AOI0 open */
+                       pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
+               break;
+       case PLANE2_AOI1:
+               pmfbi = machine_data->fsl_diu_info[3]->par;
+               ad->next_ad = 0;
+               if (hw->desc[2] == machine_data->dummy_ad->paddr)
+                       wr_reg_wa(&hw->desc[2], ad->paddr);
+               else                            /* AOI0 was open */
+                       pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
+               break;
+       }
 }
 
-static int fsl_diu_disable_panel(struct fb_info *info)
+static void fsl_diu_disable_panel(struct fb_info *info)
 {
        struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par;
-       struct diu *hw = dr.diu_reg;
        struct diu_ad *ad = mfbi->ad;
        struct fsl_diu_data *machine_data = mfbi->parent;
-       int res = 0;
+       struct diu __iomem *hw = machine_data->diu_reg;
 
        switch (mfbi->index) {
-       case 0:                                 /* plane 0 */
+       case PLANE0:
                if (hw->desc[0] != machine_data->dummy_ad->paddr)
                        wr_reg_wa(&hw->desc[0], machine_data->dummy_ad->paddr);
                break;
-       case 1:                                 /* plane 1 AOI 0 */
+       case PLANE1_AOI0:
                cmfbi = machine_data->fsl_diu_info[2]->par;
                if (cmfbi->count > 0)   /* AOI1 is open */
                        wr_reg_wa(&hw->desc[1], cmfbi->ad->paddr);
@@ -414,7 +565,7 @@ static int fsl_diu_disable_panel(struct fb_info *info)
                        wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr);
                                        /* close AOI 0 */
                break;
-       case 3:                                 /* plane 2 AOI 0 */
+       case PLANE2_AOI0:
                cmfbi = machine_data->fsl_diu_info[4]->par;
                if (cmfbi->count > 0)   /* AOI1 is open */
                        wr_reg_wa(&hw->desc[2], cmfbi->ad->paddr);
@@ -423,7 +574,7 @@ static int fsl_diu_disable_panel(struct fb_info *info)
                        wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr);
                                        /* close AOI 0 */
                break;
-       case 2:                                 /* plane 1 AOI 1 */
+       case PLANE1_AOI1:
                pmfbi = machine_data->fsl_diu_info[1]->par;
                if (hw->desc[1] != ad->paddr) {
                                /* AOI1 is not the first in the chain */
@@ -434,7 +585,7 @@ static int fsl_diu_disable_panel(struct fb_info *info)
                        wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr);
                                        /* close AOI 1 */
                break;
-       case 4:                                 /* plane 2 AOI 1 */
+       case PLANE2_AOI1:
                pmfbi = machine_data->fsl_diu_info[3]->par;
                if (hw->desc[2] != ad->paddr) {
                                /* AOI1 is not the first in the chain */
@@ -445,31 +596,26 @@ static int fsl_diu_disable_panel(struct fb_info *info)
                        wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr);
                                /* close AOI 1 */
                break;
-       default:
-               res = -EINVAL;
-               break;
        }
-
-       return res;
 }
 
 static void enable_lcdc(struct fb_info *info)
 {
-       struct diu *hw = dr.diu_reg;
        struct mfb_info *mfbi = info->par;
        struct fsl_diu_data *machine_data = mfbi->parent;
+       struct diu __iomem *hw = machine_data->diu_reg;
 
        if (!machine_data->fb_enabled) {
-               out_be32(&hw->diu_mode, dr.mode);
+               out_be32(&hw->diu_mode, MFB_MODE1);
                machine_data->fb_enabled++;
        }
 }
 
 static void disable_lcdc(struct fb_info *info)
 {
-       struct diu *hw = dr.diu_reg;
        struct mfb_info *mfbi = info->par;
        struct fsl_diu_data *machine_data = mfbi->parent;
+       struct diu __iomem *hw = machine_data->diu_reg;
 
        if (machine_data->fb_enabled) {
                out_be32(&hw->diu_mode, 0);
@@ -482,7 +628,8 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
 {
        struct mfb_info *lower_aoi_mfbi, *upper_aoi_mfbi, *mfbi = info->par;
        struct fsl_diu_data *machine_data = mfbi->parent;
-       int available_height, upper_aoi_bottom, index = mfbi->index;
+       int available_height, upper_aoi_bottom;
+       enum mfb_index index = mfbi->index;
        int lower_aoi_is_open, upper_aoi_is_open;
        __u32 base_plane_width, base_plane_height, upper_aoi_height;
 
@@ -494,14 +641,14 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
        if (mfbi->y_aoi_d < 0)
                mfbi->y_aoi_d = 0;
        switch (index) {
-       case 0:
+       case PLANE0:
                if (mfbi->x_aoi_d != 0)
                        mfbi->x_aoi_d = 0;
                if (mfbi->y_aoi_d != 0)
                        mfbi->y_aoi_d = 0;
                break;
-       case 1:                 /* AOI 0 */
-       case 3:
+       case PLANE1_AOI0:
+       case PLANE2_AOI0:
                lower_aoi_mfbi = machine_data->fsl_diu_info[index+1]->par;
                lower_aoi_is_open = lower_aoi_mfbi->count > 0 ? 1 : 0;
                if (var->xres > base_plane_width)
@@ -518,8 +665,8 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
                if ((mfbi->y_aoi_d + var->yres) > available_height)
                        mfbi->y_aoi_d = available_height - var->yres;
                break;
-       case 2:                 /* AOI 1 */
-       case 4:
+       case PLANE1_AOI1:
+       case PLANE2_AOI1:
                upper_aoi_mfbi = machine_data->fsl_diu_info[index-1]->par;
                upper_aoi_height =
                                machine_data->fsl_diu_info[index-1]->var.yres;
@@ -555,9 +702,6 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
 static int fsl_diu_check_var(struct fb_var_screeninfo *var,
                                struct fb_info *info)
 {
-       pr_debug("check_var xres: %d\n", var->xres);
-       pr_debug("check_var yres: %d\n", var->yres);
-
        if (var->xres_virtual < var->xres)
                var->xres_virtual = var->xres;
        if (var->yres_virtual < var->yres)
@@ -652,7 +796,7 @@ static void set_fix(struct fb_info *info)
        struct fb_var_screeninfo *var = &info->var;
        struct mfb_info *mfbi = info->par;
 
-       strncpy(fix->id, mfbi->id, strlen(mfbi->id));
+       strncpy(fix->id, mfbi->id, sizeof(fix->id));
        fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
        fix->type = FB_TYPE_PACKED_PIXELS;
        fix->accel = FB_ACCEL_NONE;
@@ -666,45 +810,37 @@ static void update_lcdc(struct fb_info *info)
        struct fb_var_screeninfo *var = &info->var;
        struct mfb_info *mfbi = info->par;
        struct fsl_diu_data *machine_data = mfbi->parent;
-       struct diu *hw;
+       struct diu __iomem *hw;
        int i, j;
        char __iomem *cursor_base, *gamma_table_base;
 
        u32 temp;
 
-       hw = dr.diu_reg;
-
-       if (mfbi->type == MFB_TYPE_OFF) {
-               fsl_diu_disable_panel(info);
-               return;
-       }
+       hw = machine_data->diu_reg;
 
        diu_ops.set_monitor_port(machine_data->monitor_port);
-       gamma_table_base = pool.gamma.vaddr;
-       cursor_base = pool.cursor.vaddr;
+       gamma_table_base = machine_data->gamma.vaddr;
+       cursor_base = machine_data->cursor.vaddr;
        /* Prep for DIU init  - gamma table, cursor table */
 
        for (i = 0; i <= 2; i++)
-          for (j = 0; j <= 255; j++)
-             *gamma_table_base++ = j;
+               for (j = 0; j <= 255; j++)
+                       *gamma_table_base++ = j;
 
-       diu_ops.set_gamma_table(machine_data->monitor_port, pool.gamma.vaddr);
+       diu_ops.set_gamma_table(machine_data->monitor_port,
+                               machine_data->gamma.vaddr);
 
-       pr_debug("update-lcdc: HW - %p\n Disabling DIU\n", hw);
        disable_lcdc(info);
 
        /* Program DIU registers */
 
-       out_be32(&hw->gamma, pool.gamma.paddr);
-       out_be32(&hw->cursor, pool.cursor.paddr);
+       out_be32(&hw->gamma, machine_data->gamma.paddr);
+       out_be32(&hw->cursor, machine_data->cursor.paddr);
 
        out_be32(&hw->bgnd, 0x007F7F7F);        /* BGND */
        out_be32(&hw->bgnd_wb, 0);              /* BGND_WB */
        out_be32(&hw->disp_size, (var->yres << 16 | var->xres));
                                                /* DISP SIZE */
-       pr_debug("DIU xres: %d\n", var->xres);
-       pr_debug("DIU yres: %d\n", var->yres);
-
        out_be32(&hw->wb_size, 0); /* WB SIZE */
        out_be32(&hw->wb_mem_addr, 0); /* WB MEM ADDR */
 
@@ -721,15 +857,6 @@ static void update_lcdc(struct fb_info *info)
 
        out_be32(&hw->vsyn_para, temp);
 
-       pr_debug("DIU right_margin - %d\n", var->right_margin);
-       pr_debug("DIU left_margin - %d\n", var->left_margin);
-       pr_debug("DIU hsync_len - %d\n", var->hsync_len);
-       pr_debug("DIU upper_margin - %d\n", var->upper_margin);
-       pr_debug("DIU lower_margin - %d\n", var->lower_margin);
-       pr_debug("DIU vsync_len - %d\n", var->vsync_len);
-       pr_debug("DIU HSYNC - 0x%08x\n", hw->hsyn_para);
-       pr_debug("DIU VSYNC - 0x%08x\n", hw->vsyn_para);
-
        diu_ops.set_pixel_clock(var->pixclock);
 
        out_be32(&hw->syn_pol, 0);      /* SYNC SIGNALS POLARITY */
@@ -746,14 +873,9 @@ static int map_video_memory(struct fb_info *info)
        phys_addr_t phys;
        u32 smem_len = info->fix.line_length * info->var.yres_virtual;
 
-       pr_debug("info->var.xres_virtual = %d\n", info->var.xres_virtual);
-       pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual);
-       pr_debug("info->fix.line_length  = %d\n", info->fix.line_length);
-       pr_debug("MAP_VIDEO_MEMORY: smem_len = %u\n", smem_len);
-
        info->screen_base = fsl_diu_alloc(smem_len, &phys);
        if (info->screen_base == NULL) {
-               printk(KERN_ERR "Unable to allocate fb memory\n");
+               dev_err(info->dev, "unable to allocate fb memory\n");
                return -ENOMEM;
        }
        mutex_lock(&info->mm_lock);
@@ -762,10 +884,6 @@ static int map_video_memory(struct fb_info *info)
        mutex_unlock(&info->mm_lock);
        info->screen_size = info->fix.smem_len;
 
-       pr_debug("Allocated fb @ paddr=0x%08lx, size=%d.\n",
-                info->fix.smem_start, info->fix.smem_len);
-       pr_debug("screen base %p\n", info->screen_base);
-
        return 0;
 }
 
@@ -810,9 +928,9 @@ static int fsl_diu_set_par(struct fb_info *info)
        struct mfb_info *mfbi = info->par;
        struct fsl_diu_data *machine_data = mfbi->parent;
        struct diu_ad *ad = mfbi->ad;
-       struct diu *hw;
+       struct diu __iomem *hw;
 
-       hw = dr.diu_reg;
+       hw = machine_data->diu_reg;
 
        set_fix(info);
        mfbi->cursor_reset = 1;
@@ -822,18 +940,16 @@ static int fsl_diu_set_par(struct fb_info *info)
        if (len != info->fix.smem_len) {
                if (info->fix.smem_start)
                        unmap_video_memory(info);
-               pr_debug("SET PAR: smem_len = %d\n", info->fix.smem_len);
 
                /* Memory allocation for framebuffer */
                if (map_video_memory(info)) {
-                       printk(KERN_ERR "Unable to allocate fb memory 1\n");
+                       dev_err(info->dev, "unable to allocate fb memory 1\n");
                        return -ENOMEM;
                }
        }
 
-       ad->pix_fmt =
-               diu_ops.get_pixel_format(var->bits_per_pixel,
-                                        machine_data->monitor_port);
+       ad->pix_fmt = diu_ops.get_pixel_format(machine_data->monitor_port,
+                                              var->bits_per_pixel);
        ad->addr    = cpu_to_le32(info->fix.smem_start);
        ad->src_size_g_alpha = cpu_to_le32((var->yres_virtual << 12) |
                                var->xres_virtual) | mfbi->g_alpha;
@@ -851,14 +967,14 @@ static int fsl_diu_set_par(struct fb_info *info)
        ad->ckmin_g = 255;
        ad->ckmin_b = 255;
 
-       if (mfbi->index == 0)
+       if (mfbi->index == PLANE0)
                update_lcdc(info);
        return 0;
 }
 
 static inline __u32 CNVT_TOHW(__u32 val, __u32 width)
 {
-       return ((val<<width) + 0x7FFF - val)>>16;
+       return ((val << width) + 0x7FFF - val) >> 16;
 }
 
 /*
@@ -870,8 +986,9 @@ static inline __u32 CNVT_TOHW(__u32 val, __u32 width)
  * pseudo_palette in struct fb_info. For pseudocolor mode we have a limited
  * color palette.
  */
-static int fsl_diu_setcolreg(unsigned regno, unsigned red, unsigned green,
-                          unsigned blue, unsigned transp, struct fb_info *info)
+static int fsl_diu_setcolreg(unsigned int regno, unsigned int red,
+                            unsigned int green, unsigned int blue,
+                            unsigned int transp, struct fb_info *info)
 {
        int ret = 1;
 
@@ -906,9 +1023,6 @@ static int fsl_diu_setcolreg(unsigned regno, unsigned red, unsigned green,
                        ret = 0;
                }
                break;
-       case FB_VISUAL_STATIC_PSEUDOCOLOR:
-       case FB_VISUAL_PSEUDOCOLOR:
-               break;
        }
 
        return ret;
@@ -944,37 +1058,6 @@ static int fsl_diu_pan_display(struct fb_var_screeninfo *var,
        return 0;
 }
 
-/*
- * Blank the screen if blank_mode != 0, else unblank. Return 0 if blanking
- * succeeded, != 0 if un-/blanking failed.
- * blank_mode == 2: suspend vsync
- * blank_mode == 3: suspend hsync
- * blank_mode == 4: powerdown
- */
-static int fsl_diu_blank(int blank_mode, struct fb_info *info)
-{
-       struct mfb_info *mfbi = info->par;
-
-       mfbi->blank = blank_mode;
-
-       switch (blank_mode) {
-       case FB_BLANK_VSYNC_SUSPEND:
-       case FB_BLANK_HSYNC_SUSPEND:
-       /* FIXME: fixes to enable_panel and enable lcdc needed */
-       case FB_BLANK_NORMAL:
-       /*      fsl_diu_disable_panel(info);*/
-               break;
-       case FB_BLANK_POWERDOWN:
-       /*      disable_lcdc(info);     */
-               break;
-       case FB_BLANK_UNBLANK:
-       /*      fsl_diu_enable_panel(info);*/
-               break;
-       }
-
-       return 0;
-}
-
 static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd,
                       unsigned long arg)
 {
@@ -989,25 +1072,29 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd,
        if (!arg)
                return -EINVAL;
        switch (cmd) {
+       case MFB_SET_PIXFMT_OLD:
+               dev_warn(info->dev,
+                        "MFB_SET_PIXFMT value of 0x%08x is deprecated.\n",
+                        MFB_SET_PIXFMT_OLD);
        case MFB_SET_PIXFMT:
                if (copy_from_user(&pix_fmt, buf, sizeof(pix_fmt)))
                        return -EFAULT;
                ad->pix_fmt = pix_fmt;
-               pr_debug("Set pixel format to 0x%08x\n", ad->pix_fmt);
                break;
+       case MFB_GET_PIXFMT_OLD:
+               dev_warn(info->dev,
+                        "MFB_GET_PIXFMT value of 0x%08x is deprecated.\n",
+                        MFB_GET_PIXFMT_OLD);
        case MFB_GET_PIXFMT:
                pix_fmt = ad->pix_fmt;
                if (copy_to_user(buf, &pix_fmt, sizeof(pix_fmt)))
                        return -EFAULT;
-               pr_debug("get pixel format 0x%08x\n", ad->pix_fmt);
                break;
        case MFB_SET_AOID:
                if (copy_from_user(&aoi_d, buf, sizeof(aoi_d)))
                        return -EFAULT;
                mfbi->x_aoi_d = aoi_d.x_aoi_d;
                mfbi->y_aoi_d = aoi_d.y_aoi_d;
-               pr_debug("set AOI display offset of index %d to (%d,%d)\n",
-                                mfbi->index, aoi_d.x_aoi_d, aoi_d.y_aoi_d);
                fsl_diu_check_var(&info->var, info);
                fsl_diu_set_aoi(info);
                break;
@@ -1016,14 +1103,11 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd,
                aoi_d.y_aoi_d = mfbi->y_aoi_d;
                if (copy_to_user(buf, &aoi_d, sizeof(aoi_d)))
                        return -EFAULT;
-               pr_debug("get AOI display offset of index %d (%d,%d)\n",
-                               mfbi->index, aoi_d.x_aoi_d, aoi_d.y_aoi_d);
                break;
        case MFB_GET_ALPHA:
                global_alpha = mfbi->g_alpha;
                if (copy_to_user(buf, &global_alpha, sizeof(global_alpha)))
                        return -EFAULT;
-               pr_debug("get global alpha of index %d\n", mfbi->index);
                break;
        case MFB_SET_ALPHA:
                /* set panel information */
@@ -1032,7 +1116,6 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd,
                ad->src_size_g_alpha = (ad->src_size_g_alpha & (~0xff)) |
                                                        (global_alpha & 0xff);
                mfbi->g_alpha = global_alpha;
-               pr_debug("set global alpha for index %d\n", mfbi->index);
                break;
        case MFB_SET_CHROMA_KEY:
                /* set panel winformation */
@@ -1060,27 +1143,9 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd,
                        ad->ckmin_g = ck.green_min;
                        ad->ckmin_b = ck.blue_min;
                }
-               pr_debug("set chroma key\n");
                break;
-       case FBIOGET_GWINFO:
-               if (mfbi->type == MFB_TYPE_OFF)
-                       return -ENODEV;
-               /* get graphic window information */
-               if (copy_to_user(buf, ad, sizeof(*ad)))
-                       return -EFAULT;
-               break;
-       case FBIOGET_HWCINFO:
-               pr_debug("FBIOGET_HWCINFO:0x%08x\n", FBIOGET_HWCINFO);
-               break;
-       case FBIOPUT_MODEINFO:
-               pr_debug("FBIOPUT_MODEINFO:0x%08x\n", FBIOPUT_MODEINFO);
-               break;
-       case FBIOGET_DISPINFO:
-               pr_debug("FBIOGET_DISPINFO:0x%08x\n", FBIOGET_DISPINFO);
-               break;
-
        default:
-               printk(KERN_ERR "Unknown ioctl command (0x%08X)\n", cmd);
+               dev_err(info->dev, "unknown ioctl command (0x%08X)\n", cmd);
                return -ENOIOCTLCMD;
        }
 
@@ -1095,22 +1160,18 @@ static int fsl_diu_open(struct fb_info *info, int user)
        int res = 0;
 
        /* free boot splash memory on first /dev/fb0 open */
-       if (!mfbi->index && diu_ops.release_bootmem)
+       if ((mfbi->index == PLANE0) && diu_ops.release_bootmem)
                diu_ops.release_bootmem();
 
        spin_lock(&diu_lock);
        mfbi->count++;
        if (mfbi->count == 1) {
-               pr_debug("open plane index %d\n", mfbi->index);
                fsl_diu_check_var(&info->var, info);
                res = fsl_diu_set_par(info);
                if (res < 0)
                        mfbi->count--;
-               else {
-                       res = fsl_diu_enable_panel(info);
-                       if (res < 0)
-                               mfbi->count--;
-               }
+               else
+                       fsl_diu_enable_panel(info);
        }
 
        spin_unlock(&diu_lock);
@@ -1126,12 +1187,9 @@ static int fsl_diu_release(struct fb_info *info, int user)
 
        spin_lock(&diu_lock);
        mfbi->count--;
-       if (mfbi->count == 0) {
-               pr_debug("release plane index %d\n", mfbi->index);
-               res = fsl_diu_disable_panel(info);
-               if (res < 0)
-                       mfbi->count++;
-       }
+       if (mfbi->count == 0)
+               fsl_diu_disable_panel(info);
+
        spin_unlock(&diu_lock);
        return res;
 }
@@ -1141,7 +1199,6 @@ static struct fb_ops fsl_diu_ops = {
        .fb_check_var = fsl_diu_check_var,
        .fb_set_par = fsl_diu_set_par,
        .fb_setcolreg = fsl_diu_setcolreg,
-       .fb_blank = fsl_diu_blank,
        .fb_pan_display = fsl_diu_pan_display,
        .fb_fillrect = cfb_fillrect,
        .fb_copyarea = cfb_copyarea,
@@ -1178,7 +1235,7 @@ static int __devinit install_fb(struct fb_info *info)
        if (init_fbinfo(info))
                return -EINVAL;
 
-       if (mfbi->index == 0) { /* plane 0 */
+       if (mfbi->index == PLANE0) {
                if (mfbi->edid_data) {
                        /* Now build modedb from EDID */
                        fb_edid_to_monspecs(mfbi->edid_data, &info->monspecs);
@@ -1192,43 +1249,23 @@ static int __devinit install_fb(struct fb_info *info)
        } else {
                aoi_mode = init_aoi_mode;
        }
-       pr_debug("mode used = %s\n", aoi_mode);
-       rc = fb_find_mode(&info->var, info, aoi_mode, db, dbsize,
-                         &fsl_diu_default_mode, default_bpp);
-       switch (rc) {
-       case 1:
-               pr_debug("using mode specified in @mode\n");
-               break;
-       case 2:
-               pr_debug("using mode specified in @mode "
-                       "with ignored refresh rate\n");
-               break;
-       case 3:
-               pr_debug("using mode default mode\n");
-               break;
-       case 4:
-               pr_debug("using mode from list\n");
-               break;
-       default:
-               pr_debug("rc = %d\n", rc);
-               pr_debug("failed to find mode\n");
+       rc = fb_find_mode(&info->var, info, aoi_mode, db, dbsize, NULL,
+                         default_bpp);
+       if (!rc) {
                /*
                 * For plane 0 we continue and look into
                 * driver's internal modedb.
                 */
-               if (mfbi->index == 0 && mfbi->edid_data)
+               if ((mfbi->index == PLANE0) && mfbi->edid_data)
                        has_default_mode = 0;
                else
                        return -EINVAL;
-               break;
        }
 
        if (!has_default_mode) {
                rc = fb_find_mode(&info->var, info, aoi_mode, fsl_diu_mode_db,
-                                 ARRAY_SIZE(fsl_diu_mode_db),
-                                 &fsl_diu_default_mode,
-                                 default_bpp);
-               if (rc > 0 && rc < 5)
+                       ARRAY_SIZE(fsl_diu_mode_db), NULL, default_bpp);
+               if (rc)
                        has_default_mode = 1;
        }
 
@@ -1256,33 +1293,22 @@ static int __devinit install_fb(struct fb_info *info)
                fb_videomode_to_var(&info->var, modedb);
        }
 
-       pr_debug("xres_virtual %d\n", info->var.xres_virtual);
-       pr_debug("bits_per_pixel %d\n", info->var.bits_per_pixel);
-
-       pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual);
-       pr_debug("info->fix.line_length = %d\n", info->fix.line_length);
-
-       if (mfbi->type == MFB_TYPE_OFF)
-               mfbi->blank = FB_BLANK_NORMAL;
-       else
-               mfbi->blank = FB_BLANK_UNBLANK;
-
        if (fsl_diu_check_var(&info->var, info)) {
-               printk(KERN_ERR "fb_check_var failed");
+               dev_err(info->dev, "fsl_diu_check_var failed\n");
+               unmap_video_memory(info);
                fb_dealloc_cmap(&info->cmap);
                return -EINVAL;
        }
 
        if (register_framebuffer(info) < 0) {
-               printk(KERN_ERR "register_framebuffer failed");
+               dev_err(info->dev, "register_framebuffer failed\n");
                unmap_video_memory(info);
                fb_dealloc_cmap(&info->cmap);
                return -EINVAL;
        }
 
        mfbi->registered = 1;
-       printk(KERN_INFO "fb%d: %s fb device registered successfully.\n",
-                info->node, info->fix.id);
+       dev_info(info->dev, "%s registered successfully\n", mfbi->id);
 
        return 0;
 }
@@ -1294,7 +1320,7 @@ static void uninstall_fb(struct fb_info *info)
        if (!mfbi->registered)
                return;
 
-       if (mfbi->index == 0)
+       if (mfbi->index == PLANE0)
                kfree(mfbi->edid_data);
 
        unregister_framebuffer(info);
@@ -1307,20 +1333,20 @@ static void uninstall_fb(struct fb_info *info)
 
 static irqreturn_t fsl_diu_isr(int irq, void *dev_id)
 {
-       struct diu *hw = dr.diu_reg;
+       struct diu __iomem *hw = dev_id;
        unsigned int status = in_be32(&hw->int_status);
 
        if (status) {
                /* This is the workaround for underrun */
                if (status & INT_UNDRUN) {
                        out_be32(&hw->diu_mode, 0);
-                       pr_debug("Err: DIU occurs underrun!\n");
                        udelay(1);
                        out_be32(&hw->diu_mode, 1);
                }
 #if defined(CONFIG_NOT_COHERENT_CACHE)
                else if (status & INT_VSYNC) {
                        unsigned int i;
+
                        for (i = 0; i < coherence_data_size;
                                i += d_cache_line_size)
                                __asm__ __volatile__ (
@@ -1333,43 +1359,38 @@ static irqreturn_t fsl_diu_isr(int irq, void *dev_id)
        return IRQ_NONE;
 }
 
-static int request_irq_local(int irq)
+static int request_irq_local(struct fsl_diu_data *machine_data)
 {
-       unsigned long status, ints;
-       struct diu *hw;
+       struct diu __iomem *hw = machine_data->diu_reg;
+       u32 ints;
        int ret;
 
-       hw = dr.diu_reg;
-
        /* Read to clear the status */
-       status = in_be32(&hw->int_status);
+       in_be32(&hw->int_status);
 
-       ret = request_irq(irq, fsl_diu_isr, 0, "diu", NULL);
-       if (ret)
-               pr_info("Request diu IRQ failed.\n");
-       else {
+       ret = request_irq(machine_data->irq, fsl_diu_isr, 0, "fsl-diu-fb", hw);
+       if (!ret) {
                ints = INT_PARERR | INT_LS_BF_VS;
 #if !defined(CONFIG_NOT_COHERENT_CACHE)
                ints |= INT_VSYNC;
 #endif
-               if (dr.mode == MFB_MODE2 || dr.mode == MFB_MODE3)
-                       ints |= INT_VSYNC_WB;
 
                /* Read to clear the status */
-               status = in_be32(&hw->int_status);
+               in_be32(&hw->int_status);
                out_be32(&hw->int_mask, ints);
        }
+
        return ret;
 }
 
-static void free_irq_local(int irq)
+static void free_irq_local(struct fsl_diu_data *machine_data)
 {
-       struct diu *hw = dr.diu_reg;
+       struct diu __iomem *hw = machine_data->diu_reg;
 
        /* Disable all LCDC interrupt */
        out_be32(&hw->int_mask, 0x1f);
 
-       free_irq(irq, NULL);
+       free_irq(machine_data->irq, NULL);
 }
 
 #ifdef CONFIG_PM
@@ -1406,49 +1427,42 @@ static int fsl_diu_resume(struct platform_device *ofdev)
 static int allocate_buf(struct device *dev, struct diu_addr *buf, u32 size,
                        u32 bytes_align)
 {
-       u32 offset, ssize;
-       u32 mask;
-       dma_addr_t paddr = 0;
+       u32 offset;
+       dma_addr_t mask;
 
-       ssize = size + bytes_align;
-       buf->vaddr = dma_alloc_coherent(dev, ssize, &paddr, GFP_DMA |
-                                                            __GFP_ZERO);
+       buf->vaddr =
+               dma_alloc_coherent(dev, size + bytes_align, &buf->paddr,
+                                  GFP_DMA | __GFP_ZERO);
        if (!buf->vaddr)
                return -ENOMEM;
 
-       buf->paddr = (__u32) paddr;
-
        mask = bytes_align - 1;
-       offset = (u32)buf->paddr & mask;
+       offset = buf->paddr & mask;
        if (offset) {
                buf->offset = bytes_align - offset;
-               buf->paddr = (u32)buf->paddr + offset;
+               buf->paddr = buf->paddr + offset;
        } else
                buf->offset = 0;
+
        return 0;
 }
 
 static void free_buf(struct device *dev, struct diu_addr *buf, u32 size,
                     u32 bytes_align)
 {
-       dma_free_coherent(dev, size + bytes_align,
-                               buf->vaddr, (buf->paddr - buf->offset));
-       return;
+       dma_free_coherent(dev, size + bytes_align, buf->vaddr,
+                         buf->paddr - buf->offset);
 }
 
 static ssize_t store_monitor(struct device *device,
        struct device_attribute *attr, const char *buf, size_t count)
 {
-       int old_monitor_port;
-       unsigned long val;
+       enum fsl_diu_monitor_port old_monitor_port;
        struct fsl_diu_data *machine_data =
                container_of(attr, struct fsl_diu_data, dev_attr);
 
-       if (strict_strtoul(buf, 10, &val))
-               return 0;
-
        old_monitor_port = machine_data->monitor_port;
-       machine_data->monitor_port = diu_ops.set_sysfs_monitor_port(val);
+       machine_data->monitor_port = fsl_diu_name_to_port(buf);
 
        if (old_monitor_port != machine_data->monitor_port) {
                /* All AOIs need adjust pixel format
@@ -1468,16 +1482,25 @@ static ssize_t show_monitor(struct device *device,
 {
        struct fsl_diu_data *machine_data =
                container_of(attr, struct fsl_diu_data, dev_attr);
-       return diu_ops.show_monitor_port(machine_data->monitor_port, buf);
+
+       switch (machine_data->monitor_port) {
+       case FSL_DIU_PORT_DVI:
+               return sprintf(buf, "DVI\n");
+       case FSL_DIU_PORT_LVDS:
+               return sprintf(buf, "Single-link LVDS\n");
+       case FSL_DIU_PORT_DLVDS:
+               return sprintf(buf, "Dual-link LVDS\n");
+       }
+
+       return 0;
 }
 
-static int __devinit fsl_diu_probe(struct platform_device *ofdev)
+static int __devinit fsl_diu_probe(struct platform_device *pdev)
 {
-       struct device_node *np = ofdev->dev.of_node;
+       struct device_node *np = pdev->dev.of_node;
        struct mfb_info *mfbi;
-       phys_addr_t dummy_ad_addr;
+       phys_addr_t dummy_ad_addr = 0;
        int ret, i, error = 0;
-       struct resource res;
        struct fsl_diu_data *machine_data;
        int diu_mode;
 
@@ -1485,11 +1508,13 @@ static int __devinit fsl_diu_probe(struct platform_device *ofdev)
        if (!machine_data)
                return -ENOMEM;
 
+       spin_lock_init(&machine_data->reg_lock);
+
        for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) {
                machine_data->fsl_diu_info[i] =
-                       framebuffer_alloc(sizeof(struct mfb_info), &ofdev->dev);
+                       framebuffer_alloc(sizeof(struct mfb_info), &pdev->dev);
                if (!machine_data->fsl_diu_info[i]) {
-                       dev_err(&ofdev->dev, "cannot allocate memory\n");
+                       dev_err(&pdev->dev, "cannot allocate memory\n");
                        ret = -ENOMEM;
                        goto error2;
                }
@@ -1497,7 +1522,7 @@ static int __devinit fsl_diu_probe(struct platform_device *ofdev)
                memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info));
                mfbi->parent = machine_data;
 
-               if (mfbi->index == 0) {
+               if (mfbi->index == PLANE0) {
                        const u8 *prop;
                        int len;
 
@@ -1509,60 +1534,49 @@ static int __devinit fsl_diu_probe(struct platform_device *ofdev)
                }
        }
 
-       ret = of_address_to_resource(np, 0, &res);
-       if (ret) {
-               dev_err(&ofdev->dev, "could not obtain DIU address\n");
-               goto error;
-       }
-       if (!res.start) {
-               dev_err(&ofdev->dev, "invalid DIU address\n");
-               goto error;
-       }
-       dev_dbg(&ofdev->dev, "%s, res.start: 0x%08x\n", __func__, res.start);
-
-       dr.diu_reg = ioremap(res.start, sizeof(struct diu));
-       if (!dr.diu_reg) {
-               dev_err(&ofdev->dev, "Err: can't map DIU registers!\n");
+       machine_data->diu_reg = of_iomap(np, 0);
+       if (!machine_data->diu_reg) {
+               dev_err(&pdev->dev, "cannot map DIU registers\n");
                ret = -EFAULT;
                goto error2;
        }
 
-       diu_mode = in_be32(&dr.diu_reg->diu_mode);
-       if (diu_mode != MFB_MODE1)
-               out_be32(&dr.diu_reg->diu_mode, 0);     /* disable DIU */
+       diu_mode = in_be32(&machine_data->diu_reg->diu_mode);
+       if (diu_mode == MFB_MODE0)
+               out_be32(&machine_data->diu_reg->diu_mode, 0); /* disable DIU */
 
        /* Get the IRQ of the DIU */
        machine_data->irq = irq_of_parse_and_map(np, 0);
 
        if (!machine_data->irq) {
-               dev_err(&ofdev->dev, "could not get DIU IRQ\n");
+               dev_err(&pdev->dev, "could not get DIU IRQ\n");
                ret = -EINVAL;
                goto error;
        }
        machine_data->monitor_port = monitor_port;
 
        /* Area descriptor memory pool aligns to 64-bit boundary */
-       if (allocate_buf(&ofdev->dev, &pool.ad,
+       if (allocate_buf(&pdev->dev, &machine_data->ad,
                         sizeof(struct diu_ad) * FSL_AOI_NUM, 8))
                return -ENOMEM;
 
        /* Get memory for Gamma Table  - 32-byte aligned memory */
-       if (allocate_buf(&ofdev->dev, &pool.gamma, 768, 32)) {
+       if (allocate_buf(&pdev->dev, &machine_data->gamma, 768, 32)) {
                ret = -ENOMEM;
                goto error;
        }
 
        /* For performance, cursor bitmap buffer aligns to 32-byte boundary */
-       if (allocate_buf(&ofdev->dev, &pool.cursor, MAX_CURS * MAX_CURS * 2,
-                        32)) {
+       if (allocate_buf(&pdev->dev, &machine_data->cursor,
+                        MAX_CURS * MAX_CURS * 2, 32)) {
                ret = -ENOMEM;
                goto error;
        }
 
        i = ARRAY_SIZE(machine_data->fsl_diu_info);
-       machine_data->dummy_ad = (struct diu_ad *)
-                       ((u32)pool.ad.vaddr + pool.ad.offset) + i;
-       machine_data->dummy_ad->paddr = pool.ad.paddr +
+       machine_data->dummy_ad = (struct diu_ad *)((u32)machine_data->ad.vaddr +
+                       machine_data->ad.offset) + i;
+       machine_data->dummy_ad->paddr = machine_data->ad.paddr +
                        i * sizeof(struct diu_ad);
        machine_data->dummy_aoi_virt = fsl_diu_alloc(64, &dummy_ad_addr);
        if (!machine_data->dummy_aoi_virt) {
@@ -1581,30 +1595,29 @@ static int __devinit fsl_diu_probe(struct platform_device *ofdev)
         * Let DIU display splash screen if it was pre-initialized
         * by the bootloader, set dummy area descriptor otherwise.
         */
-       if (diu_mode != MFB_MODE1)
-               out_be32(&dr.diu_reg->desc[0], machine_data->dummy_ad->paddr);
+       if (diu_mode == MFB_MODE0)
+               out_be32(&machine_data->diu_reg->desc[0],
+                        machine_data->dummy_ad->paddr);
 
-       out_be32(&dr.diu_reg->desc[1], machine_data->dummy_ad->paddr);
-       out_be32(&dr.diu_reg->desc[2], machine_data->dummy_ad->paddr);
+       out_be32(&machine_data->diu_reg->desc[1], machine_data->dummy_ad->paddr);
+       out_be32(&machine_data->diu_reg->desc[2], machine_data->dummy_ad->paddr);
 
        for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) {
                machine_data->fsl_diu_info[i]->fix.smem_start = 0;
                mfbi = machine_data->fsl_diu_info[i]->par;
-               mfbi->ad = (struct diu_ad *)((u32)pool.ad.vaddr
-                                       + pool.ad.offset) + i;
-               mfbi->ad->paddr = pool.ad.paddr + i * sizeof(struct diu_ad);
+               mfbi->ad = (struct diu_ad *)((u32)machine_data->ad.vaddr
+                                       + machine_data->ad.offset) + i;
+               mfbi->ad->paddr =
+                       machine_data->ad.paddr + i * sizeof(struct diu_ad);
                ret = install_fb(machine_data->fsl_diu_info[i]);
                if (ret) {
-                       dev_err(&ofdev->dev,
-                               "Failed to register framebuffer %d\n",
-                               i);
+                       dev_err(&pdev->dev, "could not register fb %d\n", i);
                        goto error;
                }
        }
 
-       if (request_irq_local(machine_data->irq)) {
-               dev_err(machine_data->fsl_diu_info[0]->dev,
-                       "could not request irq for diu.");
+       if (request_irq_local(machine_data)) {
+               dev_err(&pdev->dev, "could not claim irq\n");
                goto error;
        }
 
@@ -1616,29 +1629,28 @@ static int __devinit fsl_diu_probe(struct platform_device *ofdev)
        error = device_create_file(machine_data->fsl_diu_info[0]->dev,
                                  &machine_data->dev_attr);
        if (error) {
-               dev_err(machine_data->fsl_diu_info[0]->dev,
-                       "could not create sysfs %s file\n",
+               dev_err(&pdev->dev, "could not create sysfs file %s\n",
                        machine_data->dev_attr.attr.name);
        }
 
-       dev_set_drvdata(&ofdev->dev, machine_data);
+       dev_set_drvdata(&pdev->dev, machine_data);
        return 0;
 
 error:
-       for (i = ARRAY_SIZE(machine_data->fsl_diu_info);
-               i > 0; i--)
-               uninstall_fb(machine_data->fsl_diu_info[i - 1]);
-       if (pool.ad.vaddr)
-               free_buf(&ofdev->dev, &pool.ad,
+       for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
+               uninstall_fb(machine_data->fsl_diu_info[i]);
+
+       if (machine_data->ad.vaddr)
+               free_buf(&pdev->dev, &machine_data->ad,
                         sizeof(struct diu_ad) * FSL_AOI_NUM, 8);
-       if (pool.gamma.vaddr)
-               free_buf(&ofdev->dev, &pool.gamma, 768, 32);
-       if (pool.cursor.vaddr)
-               free_buf(&ofdev->dev, &pool.cursor, MAX_CURS * MAX_CURS * 2,
-                        32);
+       if (machine_data->gamma.vaddr)
+               free_buf(&pdev->dev, &machine_data->gamma, 768, 32);
+       if (machine_data->cursor.vaddr)
+               free_buf(&pdev->dev, &machine_data->cursor,
+                        MAX_CURS * MAX_CURS * 2, 32);
        if (machine_data->dummy_aoi_virt)
                fsl_diu_free(machine_data->dummy_aoi_virt, 64);
-       iounmap(dr.diu_reg);
+       iounmap(machine_data->diu_reg);
 
 error2:
        for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
@@ -1649,28 +1661,27 @@ error2:
        return ret;
 }
 
-
-static int fsl_diu_remove(struct platform_device *ofdev)
+static int fsl_diu_remove(struct platform_device *pdev)
 {
        struct fsl_diu_data *machine_data;
        int i;
 
-       machine_data = dev_get_drvdata(&ofdev->dev);
+       machine_data = dev_get_drvdata(&pdev->dev);
        disable_lcdc(machine_data->fsl_diu_info[0]);
-       free_irq_local(machine_data->irq);
-       for (i = ARRAY_SIZE(machine_data->fsl_diu_info); i > 0; i--)
-               uninstall_fb(machine_data->fsl_diu_info[i - 1]);
-       if (pool.ad.vaddr)
-               free_buf(&ofdev->dev, &pool.ad,
+       free_irq_local(machine_data);
+       for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
+               uninstall_fb(machine_data->fsl_diu_info[i]);
+       if (machine_data->ad.vaddr)
+               free_buf(&pdev->dev, &machine_data->ad,
                         sizeof(struct diu_ad) * FSL_AOI_NUM, 8);
-       if (pool.gamma.vaddr)
-               free_buf(&ofdev->dev, &pool.gamma, 768, 32);
-       if (pool.cursor.vaddr)
-               free_buf(&ofdev->dev, &pool.cursor, MAX_CURS * MAX_CURS * 2,
-                        32);
+       if (machine_data->gamma.vaddr)
+               free_buf(&pdev->dev, &machine_data->gamma, 768, 32);
+       if (machine_data->cursor.vaddr)
+               free_buf(&pdev->dev, &machine_data->cursor,
+                        MAX_CURS * MAX_CURS * 2, 32);
        if (machine_data->dummy_aoi_virt)
                fsl_diu_free(machine_data->dummy_aoi_virt, 64);
-       iounmap(dr.diu_reg);
+       iounmap(machine_data->diu_reg);
        for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
                if (machine_data->fsl_diu_info[i])
                        framebuffer_release(machine_data->fsl_diu_info[i]);
@@ -1692,8 +1703,7 @@ static int __init fsl_diu_setup(char *options)
                if (!*opt)
                        continue;
                if (!strncmp(opt, "monitor=", 8)) {
-                       if (!strict_strtoul(opt + 8, 10, &val) && (val <= 2))
-                               monitor_port = val;
+                       monitor_port = fsl_diu_name_to_port(opt + 8);
                } else if (!strncmp(opt, "bpp=", 4)) {
                        if (!strict_strtoul(opt + 4, 10, &val))
                                default_bpp = val;
@@ -1720,7 +1730,7 @@ MODULE_DEVICE_TABLE(of, fsl_diu_match);
 
 static struct platform_driver fsl_diu_driver = {
        .driver = {
-               .name = "fsl_diu",
+               .name = "fsl-diu-fb",
                .owner = THIS_MODULE,
                .of_match_table = fsl_diu_match,
        },
@@ -1746,48 +1756,54 @@ static int __init fsl_diu_init(void)
        if (fb_get_options("fslfb", &option))
                return -ENODEV;
        fsl_diu_setup(option);
+#else
+       monitor_port = fsl_diu_name_to_port(monitor_string);
 #endif
-       printk(KERN_INFO "Freescale DIU driver\n");
+       pr_info("Freescale Display Interface Unit (DIU) framebuffer driver\n");
 
 #ifdef CONFIG_NOT_COHERENT_CACHE
        np = of_find_node_by_type(NULL, "cpu");
        if (!np) {
-               printk(KERN_ERR "Err: can't find device node 'cpu'\n");
+               pr_err("fsl-diu-fb: can't find 'cpu' device node\n");
                return -ENODEV;
        }
 
        prop = of_get_property(np, "d-cache-size", NULL);
        if (prop == NULL) {
+               pr_err("fsl-diu-fb: missing 'd-cache-size' property' "
+                      "in 'cpu' node\n");
                of_node_put(np);
                return -ENODEV;
        }
 
-       /* Freescale PLRU requires 13/8 times the cache size to do a proper
-          displacement flush
+       /*
+        * Freescale PLRU requires 13/8 times the cache size to do a proper
+        * displacement flush
         */
-       coherence_data_size = *prop * 13;
+       coherence_data_size = be32_to_cpup(prop) * 13;
        coherence_data_size /= 8;
 
        prop = of_get_property(np, "d-cache-line-size", NULL);
        if (prop == NULL) {
+               pr_err("fsl-diu-fb: missing 'd-cache-line-size' property' "
+                      "in 'cpu' node\n");
                of_node_put(np);
                return -ENODEV;
        }
-       d_cache_line_size = *prop;
+       d_cache_line_size = be32_to_cpup(prop);
 
        of_node_put(np);
        coherence_data = vmalloc(coherence_data_size);
        if (!coherence_data)
                return -ENOMEM;
 #endif
+
        ret = platform_driver_register(&fsl_diu_driver);
        if (ret) {
-               printk(KERN_ERR
-                       "fsl-diu: failed to register platform driver\n");
+               pr_err("fsl-diu-fb: failed to register platform driver\n");
 #if defined(CONFIG_NOT_COHERENT_CACHE)
                vfree(coherence_data);
 #endif
-               iounmap(dr.diu_reg);
        }
        return ret;
 }
@@ -1811,8 +1827,8 @@ module_param_named(mode, fb_mode, charp, 0);
 MODULE_PARM_DESC(mode,
        "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
 module_param_named(bpp, default_bpp, ulong, 0);
-MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified mode");
-module_param_named(monitor, monitor_port, int, 0);
-MODULE_PARM_DESC(monitor,
-       "Specify the monitor port (0, 1 or 2) if supported by the platform");
+MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified in 'mode'");
+module_param_named(monitor, monitor_string, charp, 0);
+MODULE_PARM_DESC(monitor, "Specify the monitor port "
+       "(\"dvi\", \"lvds\", or \"dlvds\") if supported by the platform");
 
index d662317..223896c 100644 (file)
@@ -149,10 +149,11 @@ int g364fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 static int g364fb_pan_display(struct fb_var_screeninfo *var, 
                              struct fb_info *info)
 {
-       if (var->xoffset || var->yoffset + var->yres > var->yres_virtual)
+       if (var->xoffset ||
+           var->yoffset + info->var.yres > info->var.yres_virtual)
                return -EINVAL;
 
-       *(unsigned int *) TOP_REG = var->yoffset * var->xres;
+       *(unsigned int *) TOP_REG = var->yoffset * info->var.xres;
        return 0;
 }
 
diff --git a/drivers/video/grvga.c b/drivers/video/grvga.c
new file mode 100644 (file)
index 0000000..f37e025
--- /dev/null
@@ -0,0 +1,579 @@
+/*
+ * Driver for Aeroflex Gaisler SVGACTRL framebuffer device.
+ *
+ * 2011 (c) Aeroflex Gaisler AB
+ *
+ * Full documentation of the core can be found here:
+ * http://www.gaisler.com/products/grlib/grip.pdf
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Contributors: Kristoffer Glembo <kristoffer@gaisler.com>
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/io.h>
+
+struct grvga_regs {
+       u32 status;             /* 0x00 */
+       u32 video_length;       /* 0x04 */
+       u32 front_porch;        /* 0x08 */
+       u32 sync_length;        /* 0x0C */
+       u32 line_length;        /* 0x10 */
+       u32 fb_pos;             /* 0x14 */
+       u32 clk_vector[4];      /* 0x18 */
+       u32 clut;               /* 0x20 */
+};
+
+struct grvga_par {
+       struct grvga_regs *regs;
+       u32 color_palette[16];  /* 16 entry pseudo palette used by fbcon in true color mode */
+       int clk_sel;
+       int fb_alloced;         /* = 1 if framebuffer is allocated in main memory */
+};
+
+
+static const struct fb_videomode grvga_modedb[] = {
+    {
+       /* 640x480 @ 60 Hz */
+       NULL, 60, 640, 480, 40000, 48, 16, 39, 11, 96, 2,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 800x600 @ 60 Hz */
+       NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 800x600 @ 72 Hz */
+       NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
+       0, FB_VMODE_NONINTERLACED
+    }, {
+       /* 1024x768 @ 60 Hz */
+       NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6,
+       0, FB_VMODE_NONINTERLACED
+    }
+ };
+
+static struct fb_fix_screeninfo grvga_fix __initdata = {
+       .id =           "AG SVGACTRL",
+       .type =         FB_TYPE_PACKED_PIXELS,
+       .visual =       FB_VISUAL_PSEUDOCOLOR,
+       .xpanstep =     0,
+       .ypanstep =     1,
+       .ywrapstep =    0,
+       .accel =        FB_ACCEL_NONE,
+};
+
+static int grvga_check_var(struct fb_var_screeninfo *var,
+                          struct fb_info *info)
+{
+       struct grvga_par *par = info->par;
+       int i;
+
+       if (!var->xres)
+               var->xres = 1;
+       if (!var->yres)
+               var->yres = 1;
+       if (var->bits_per_pixel <= 8)
+               var->bits_per_pixel = 8;
+       else if (var->bits_per_pixel <= 16)
+               var->bits_per_pixel = 16;
+       else if (var->bits_per_pixel <= 24)
+               var->bits_per_pixel = 24;
+       else if (var->bits_per_pixel <= 32)
+               var->bits_per_pixel = 32;
+       else
+               return -EINVAL;
+
+       var->xres_virtual = var->xres;
+       var->yres_virtual = 2*var->yres;
+
+       if (info->fix.smem_len) {
+               if ((var->yres_virtual*var->xres_virtual*var->bits_per_pixel/8) > info->fix.smem_len)
+                       return -ENOMEM;
+       }
+
+       /* Which clocks that are available can be read out in these registers */
+       for (i = 0; i <= 3 ; i++) {
+               if (var->pixclock == par->regs->clk_vector[i])
+                       break;
+       }
+       if (i <= 3)
+               par->clk_sel = i;
+       else
+               return -EINVAL;
+
+       switch (info->var.bits_per_pixel) {
+       case 8:
+               var->red   = (struct fb_bitfield) {0, 8, 0};      /* offset, length, msb-right */
+               var->green = (struct fb_bitfield) {0, 8, 0};
+               var->blue  = (struct fb_bitfield) {0, 8, 0};
+               var->transp = (struct fb_bitfield) {0, 0, 0};
+               break;
+       case 16:
+               var->red   = (struct fb_bitfield) {11, 5, 0};
+               var->green = (struct fb_bitfield) {5, 6, 0};
+               var->blue  = (struct fb_bitfield) {0, 5, 0};
+               var->transp = (struct fb_bitfield) {0, 0, 0};
+               break;
+       case 24:
+       case 32:
+               var->red   = (struct fb_bitfield) {16, 8, 0};
+               var->green = (struct fb_bitfield) {8, 8, 0};
+               var->blue  = (struct fb_bitfield) {0, 8, 0};
+               var->transp = (struct fb_bitfield) {24, 8, 0};
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int grvga_set_par(struct fb_info *info)
+{
+
+       u32 func = 0;
+       struct grvga_par *par = info->par;
+
+       __raw_writel(((info->var.yres - 1) << 16) | (info->var.xres - 1),
+                    &par->regs->video_length);
+
+       __raw_writel((info->var.lower_margin << 16) | (info->var.right_margin),
+                    &par->regs->front_porch);
+
+       __raw_writel((info->var.vsync_len << 16) | (info->var.hsync_len),
+                    &par->regs->sync_length);
+
+       __raw_writel(((info->var.yres + info->var.lower_margin + info->var.upper_margin + info->var.vsync_len - 1) << 16) |
+                    (info->var.xres + info->var.right_margin + info->var.left_margin + info->var.hsync_len - 1),
+                    &par->regs->line_length);
+
+       switch (info->var.bits_per_pixel) {
+       case 8:
+               info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+               func = 1;
+               break;
+       case 16:
+               info->fix.visual = FB_VISUAL_TRUECOLOR;
+               func = 2;
+               break;
+       case 24:
+       case 32:
+               info->fix.visual = FB_VISUAL_TRUECOLOR;
+               func = 3;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       __raw_writel((par->clk_sel << 6) | (func << 4) | 1,
+                    &par->regs->status);
+
+       info->fix.line_length = (info->var.xres_virtual*info->var.bits_per_pixel)/8;
+       return 0;
+}
+
+static int grvga_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info)
+{
+       struct grvga_par *par;
+       par = info->par;
+
+       if (regno >= 256)       /* Size of CLUT */
+               return -EINVAL;
+
+       if (info->var.grayscale) {
+               /* grayscale = 0.30*R + 0.59*G + 0.11*B */
+               red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+       }
+
+
+
+#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
+
+       red    = CNVT_TOHW(red,   info->var.red.length);
+       green  = CNVT_TOHW(green, info->var.green.length);
+       blue   = CNVT_TOHW(blue,  info->var.blue.length);
+       transp = CNVT_TOHW(transp, info->var.transp.length);
+
+#undef CNVT_TOHW
+
+       /* In PSEUDOCOLOR we use the hardware CLUT */
+       if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
+               __raw_writel((regno << 24) | (red << 16) | (green << 8) | blue,
+                            &par->regs->clut);
+
+       /* Truecolor uses the pseudo palette */
+       else if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+               u32 v;
+               if (regno >= 16)
+                       return -EINVAL;
+
+
+               v =     (red    << info->var.red.offset)   |
+                       (green  << info->var.green.offset) |
+                       (blue   << info->var.blue.offset)  |
+                       (transp << info->var.transp.offset);
+
+               ((u32 *) (info->pseudo_palette))[regno] = v;
+       }
+       return 0;
+}
+
+static int grvga_pan_display(struct fb_var_screeninfo *var,
+                            struct fb_info *info)
+{
+       struct grvga_par *par = info->par;
+       struct fb_fix_screeninfo *fix = &info->fix;
+       u32 base_addr;
+
+       if (var->xoffset != 0)
+               return -EINVAL;
+
+       base_addr = fix->smem_start + (var->yoffset * fix->line_length);
+       base_addr &= ~3UL;
+
+       /* Set framebuffer base address  */
+       __raw_writel(base_addr,
+                    &par->regs->fb_pos);
+
+       return 0;
+}
+
+static struct fb_ops grvga_ops = {
+       .owner          = THIS_MODULE,
+       .fb_check_var   = grvga_check_var,
+       .fb_set_par     = grvga_set_par,
+       .fb_setcolreg   = grvga_setcolreg,
+       .fb_pan_display = grvga_pan_display,
+       .fb_fillrect    = cfb_fillrect,
+       .fb_copyarea    = cfb_copyarea,
+       .fb_imageblit   = cfb_imageblit
+};
+
+static int __init grvga_parse_custom(char *options,
+                                    struct fb_var_screeninfo *screendata)
+{
+       char *this_opt;
+       int count = 0;
+       if (!options || !*options)
+               return -1;
+
+       while ((this_opt = strsep(&options, " ")) != NULL) {
+               if (!*this_opt)
+                       continue;
+
+               switch (count) {
+               case 0:
+                       screendata->pixclock = simple_strtoul(this_opt, NULL, 0);
+                       count++;
+                       break;
+               case 1:
+                       screendata->xres = screendata->xres_virtual = simple_strtoul(this_opt, NULL, 0);
+                       count++;
+                       break;
+               case 2:
+                       screendata->right_margin = simple_strtoul(this_opt, NULL, 0);
+                       count++;
+                       break;
+               case 3:
+                       screendata->hsync_len = simple_strtoul(this_opt, NULL, 0);
+                       count++;
+                       break;
+               case 4:
+                       screendata->left_margin = simple_strtoul(this_opt, NULL, 0);
+                       count++;
+                       break;
+               case 5:
+                       screendata->yres = screendata->yres_virtual = simple_strtoul(this_opt, NULL, 0);
+                       count++;
+                       break;
+               case 6:
+                       screendata->lower_margin = simple_strtoul(this_opt, NULL, 0);
+                       count++;
+                       break;
+               case 7:
+                       screendata->vsync_len = simple_strtoul(this_opt, NULL, 0);
+                       count++;
+                       break;
+               case 8:
+                       screendata->upper_margin = simple_strtoul(this_opt, NULL, 0);
+                       count++;
+                       break;
+               case 9:
+                       screendata->bits_per_pixel = simple_strtoul(this_opt, NULL, 0);
+                       count++;
+                       break;
+               default:
+                       return -1;
+               }
+       }
+       screendata->activate  = FB_ACTIVATE_NOW;
+       screendata->vmode     = FB_VMODE_NONINTERLACED;
+       return 0;
+}
+
+static int __devinit grvga_probe(struct platform_device *dev)
+{
+       struct fb_info *info;
+       int retval = -ENOMEM;
+       unsigned long virtual_start;
+       unsigned long grvga_fix_addr = 0;
+       unsigned long physical_start = 0;
+       unsigned long grvga_mem_size = 0;
+       struct grvga_par *par = NULL;
+       char *options = NULL, *mode_opt = NULL;
+
+       info = framebuffer_alloc(sizeof(struct grvga_par), &dev->dev);
+       if (!info) {
+               dev_err(&dev->dev, "framebuffer_alloc failed\n");
+               return -ENOMEM;
+       }
+
+       /* Expecting: "grvga: modestring, [addr:<framebuffer physical address>], [size:<framebuffer size>]
+        *
+        * If modestring is custom:<custom mode string> we parse the string which then contains all videoparameters
+        * If address is left out, we allocate memory,
+        * if size is left out we only allocate enough to support the given mode.
+        */
+       if (fb_get_options("grvga", &options)) {
+               retval = -ENODEV;
+               goto err;
+       }
+
+       if (!options || !*options)
+               options =  "640x480-8@60";
+
+       while (1) {
+               char *this_opt = strsep(&options, ",");
+
+               if (!this_opt)
+                       break;
+
+               if (!strncmp(this_opt, "custom", 6)) {
+                       if (grvga_parse_custom(this_opt, &info->var) < 0) {
+                               dev_err(&dev->dev, "Failed to parse custom mode (%s).\n", this_opt);
+                               retval = -EINVAL;
+                               goto err1;
+                       }
+               } else if (!strncmp(this_opt, "addr", 4))
+                       grvga_fix_addr = simple_strtoul(this_opt + 5, NULL, 16);
+               else if (!strncmp(this_opt, "size", 4))
+                       grvga_mem_size = simple_strtoul(this_opt + 5, NULL, 0);
+               else
+                       mode_opt = this_opt;
+       }
+
+       par = info->par;
+       info->fbops = &grvga_ops;
+       info->fix = grvga_fix;
+       info->pseudo_palette = par->color_palette;
+       info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN;
+       info->fix.smem_len = grvga_mem_size;
+
+       if (!request_mem_region(dev->resource[0].start, resource_size(&dev->resource[0]), "grlib-svgactrl regs")) {
+               dev_err(&dev->dev, "registers already mapped\n");
+               retval = -EBUSY;
+               goto err;
+       }
+
+       par->regs = of_ioremap(&dev->resource[0], 0,
+                              resource_size(&dev->resource[0]),
+                              "grlib-svgactrl regs");
+
+       if (!par->regs) {
+               dev_err(&dev->dev, "failed to map registers\n");
+               retval = -ENOMEM;
+               goto err1;
+       }
+
+       retval = fb_alloc_cmap(&info->cmap, 256, 0);
+       if (retval < 0) {
+               dev_err(&dev->dev, "failed to allocate mem with fb_alloc_cmap\n");
+               retval = -ENOMEM;
+               goto err2;
+       }
+
+       if (mode_opt) {
+               retval = fb_find_mode(&info->var, info, mode_opt,
+                                     grvga_modedb, sizeof(grvga_modedb), &grvga_modedb[0], 8);
+               if (!retval || retval == 4) {
+                       retval = -EINVAL;
+                       goto err3;
+               }
+       }
+
+       if (!grvga_mem_size)
+               grvga_mem_size = info->var.xres_virtual * info->var.yres_virtual * info->var.bits_per_pixel/8;
+
+       if (grvga_fix_addr) {
+               /* Got framebuffer base address from argument list */
+
+               physical_start = grvga_fix_addr;
+
+               if (!request_mem_region(physical_start, grvga_mem_size, dev->name)) {
+                       dev_err(&dev->dev, "failed to request memory region\n");
+                       retval = -ENOMEM;
+                       goto err3;
+               }
+
+               virtual_start = (unsigned long) ioremap(physical_start, grvga_mem_size);
+
+               if (!virtual_start) {
+                       dev_err(&dev->dev, "error mapping framebuffer memory\n");
+                       retval = -ENOMEM;
+                       goto err4;
+               }
+       } else {        /* Allocate frambuffer memory */
+
+               unsigned long page;
+
+               virtual_start = (unsigned long) __get_free_pages(GFP_DMA,
+                                                                get_order(grvga_mem_size));
+               if (!virtual_start) {
+                       dev_err(&dev->dev,
+                               "unable to allocate framebuffer memory (%lu bytes)\n",
+                               grvga_mem_size);
+                       retval = -ENOMEM;
+                       goto err3;
+               }
+
+               physical_start = dma_map_single(&dev->dev, (void *)virtual_start, grvga_mem_size, DMA_TO_DEVICE);
+
+               /* Set page reserved so that mmap will work. This is necessary
+                * since we'll be remapping normal memory.
+                */
+               for (page = virtual_start;
+                    page < PAGE_ALIGN(virtual_start + grvga_mem_size);
+                    page += PAGE_SIZE) {
+                       SetPageReserved(virt_to_page(page));
+               }
+
+               par->fb_alloced = 1;
+       }
+
+       memset((unsigned long *) virtual_start, 0, grvga_mem_size);
+
+       info->screen_base = (char __iomem *) virtual_start;
+       info->fix.smem_start = physical_start;
+       info->fix.smem_len   = grvga_mem_size;
+
+       dev_set_drvdata(&dev->dev, info);
+
+       dev_info(&dev->dev,
+                "Aeroflex Gaisler framebuffer device (fb%d), %dx%d-%d, using %luK of video memory @ %p\n",
+                info->node, info->var.xres, info->var.yres, info->var.bits_per_pixel,
+                grvga_mem_size >> 10, info->screen_base);
+
+       retval = register_framebuffer(info);
+       if (retval < 0) {
+               dev_err(&dev->dev, "failed to register framebuffer\n");
+               goto err4;
+       }
+
+       __raw_writel(physical_start, &par->regs->fb_pos);
+       __raw_writel(__raw_readl(&par->regs->status) | 1,  /* Enable framebuffer */
+                    &par->regs->status);
+
+       return 0;
+
+err4:
+       dev_set_drvdata(&dev->dev, NULL);
+       if (grvga_fix_addr) {
+               release_mem_region(physical_start, grvga_mem_size);
+               iounmap((void *)virtual_start);
+       } else
+               kfree((void *)virtual_start);
+err3:
+       fb_dealloc_cmap(&info->cmap);
+err2:
+       of_iounmap(&dev->resource[0], par->regs,
+                  resource_size(&dev->resource[0]));
+err1:
+       release_mem_region(dev->resource[0].start, resource_size(&dev->resource[0]));
+err:
+       framebuffer_release(info);
+
+       return retval;
+}
+
+static int __devexit grvga_remove(struct platform_device *device)
+{
+       struct fb_info *info = dev_get_drvdata(&device->dev);
+       struct grvga_par *par = info->par;
+
+       if (info) {
+               unregister_framebuffer(info);
+               fb_dealloc_cmap(&info->cmap);
+
+               of_iounmap(&device->resource[0], par->regs,
+                          resource_size(&device->resource[0]));
+               release_mem_region(device->resource[0].start, resource_size(&device->resource[0]));
+
+               if (!par->fb_alloced) {
+                       release_mem_region(info->fix.smem_start, info->fix.smem_len);
+                       iounmap(info->screen_base);
+               } else
+                       kfree((void *)info->screen_base);
+
+               framebuffer_release(info);
+               dev_set_drvdata(&device->dev, NULL);
+       }
+
+       return 0;
+}
+
+static struct of_device_id svgactrl_of_match[] = {
+       {
+               .name = "GAISLER_SVGACTRL",
+       },
+       {
+               .name = "01_063",
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, svgactrl_of_match);
+
+static struct platform_driver grvga_driver = {
+       .driver = {
+               .name = "grlib-svgactrl",
+               .owner = THIS_MODULE,
+               .of_match_table = svgactrl_of_match,
+       },
+       .probe          = grvga_probe,
+       .remove         = __devexit_p(grvga_remove),
+};
+
+
+static int __init grvga_init(void)
+{
+       return platform_driver_register(&grvga_driver);
+}
+
+static void __exit grvga_exit(void)
+{
+       platform_driver_unregister(&grvga_driver);
+}
+
+module_init(grvga_init);
+module_exit(grvga_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Aeroflex Gaisler");
+MODULE_DESCRIPTION("Aeroflex Gaisler framebuffer device driver");
index 896e53d..0fad23f 100644 (file)
@@ -543,8 +543,8 @@ static int gxt4500_pan_display(struct fb_var_screeninfo *var,
 
        if (var->xoffset & 7)
                return -EINVAL;
-       if (var->xoffset + var->xres > var->xres_virtual ||
-           var->yoffset + var->yres > var->yres_virtual)
+       if (var->xoffset + info->var.xres > info->var.xres_virtual ||
+           var->yoffset + info->var.yres > info->var.yres_virtual)
                return -EINVAL;
 
        writereg(par, REFRESH_START, (var->xoffset << 16) | var->yoffset);
index 4052718..4394389 100644 (file)
@@ -422,8 +422,8 @@ static int hgafb_pan_display(struct fb_var_screeninfo *var,
                    var->xoffset)
                        return -EINVAL;
        } else {
-               if (var->xoffset + var->xres > info->var.xres_virtual
-                || var->yoffset + var->yres > info->var.yres_virtual
+               if (var->xoffset + info->var.xres > info->var.xres_virtual
+                || var->yoffset + info->var.yres > info->var.yres_virtual
                 || var->yoffset % 8)
                        return -EINVAL;
        }
index efb2c10..8149356 100644 (file)
@@ -749,7 +749,7 @@ set_offset (struct fb_var_screeninfo *var, struct fb_info *info)
 {
        struct imstt_par *par = info->par;
        __u32 off = var->yoffset * (info->fix.line_length >> 3)
-                   + ((var->xoffset * (var->bits_per_pixel >> 3)) >> 3);
+                   + ((var->xoffset * (info->var.bits_per_pixel >> 3)) >> 3);
        write_reg_le32(par->dc_regs, SSR, off);
 }
 
index 38065cf..fbad61d 100644 (file)
@@ -390,12 +390,12 @@ int intelfbhw_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
        xoffset = ROUND_DOWN_TO(var->xoffset, 8);
        yoffset = var->yoffset;
 
-       if ((xoffset + var->xres > var->xres_virtual) ||
-           (yoffset + var->yres > var->yres_virtual))
+       if ((xoffset + info->var.xres > info->var.xres_virtual) ||
+           (yoffset + info->var.yres > info->var.yres_virtual))
                return -EINVAL;
 
        offset = (yoffset * dinfo->pitch) +
-                (xoffset * var->bits_per_pixel) / 8;
+                (xoffset * info->var.bits_per_pixel) / 8;
 
        offset += dinfo->fb.offset << 12;
 
index b953099..934081d 100644 (file)
@@ -23,7 +23,7 @@ static int mb862xx_i2c_wait_event(struct i2c_adapter *adap)
        u32 reg;
 
        do {
-               udelay(1);
+               udelay(10);
                reg = inreg(i2c, GC_I2C_BCR);
                if (reg & (I2C_INT | I2C_BER))
                        break;
index ee1de3e..c16ff1d 100644 (file)
@@ -278,7 +278,7 @@ static int mb862xxfb_pan(struct fb_var_screeninfo *var,
        reg = pack(var->yoffset, var->xoffset);
        outreg(disp, GC_L0WY_L0WX, reg);
 
-       reg = pack(var->yres_virtual, var->xres_virtual);
+       reg = pack(info->var.yres_virtual, info->var.xres_virtual);
        outreg(disp, GC_L0WH_L0WW, reg);
        return 0;
 }
@@ -737,7 +737,7 @@ static int __devinit of_platform_mb862xx_probe(struct platform_device *ofdev)
        if (mb862xx_gdc_init(par))
                goto io_unmap;
 
-       if (request_irq(par->irq, mb862xx_intr, IRQF_DISABLED,
+       if (request_irq(par->irq, mb862xx_intr, 0,
                        DRV_NAME, (void *)par)) {
                dev_err(dev, "Cannot request irq\n");
                goto io_unmap;
@@ -1073,7 +1073,7 @@ static int __devinit mb862xx_pci_probe(struct pci_dev *pdev,
        if (mb862xx_pci_gdc_init(par))
                goto io_unmap;
 
-       if (request_irq(par->irq, mb862xx_intr, IRQF_DISABLED | IRQF_SHARED,
+       if (request_irq(par->irq, mb862xx_intr, IRQF_SHARED,
                        DRV_NAME, (void *)par)) {
                dev_err(dev, "Cannot request irq\n");
                goto io_unmap;
index cb175fe..a9a907c 100644 (file)
@@ -491,55 +491,56 @@ EXPORT_SYMBOL(vesa_modes);
 static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
                       const struct fb_videomode *mode, unsigned int bpp)
 {
-    int err = 0;
-
-    DPRINTK("Trying mode %s %dx%d-%d@%d\n", mode->name ? mode->name : "noname",
-           mode->xres, mode->yres, bpp, mode->refresh);
-    var->xres = mode->xres;
-    var->yres = mode->yres;
-    var->xres_virtual = mode->xres;
-    var->yres_virtual = mode->yres;
-    var->xoffset = 0;
-    var->yoffset = 0;
-    var->bits_per_pixel = bpp;
-    var->activate |= FB_ACTIVATE_TEST;
-    var->pixclock = mode->pixclock;
-    var->left_margin = mode->left_margin;
-    var->right_margin = mode->right_margin;
-    var->upper_margin = mode->upper_margin;
-    var->lower_margin = mode->lower_margin;
-    var->hsync_len = mode->hsync_len;
-    var->vsync_len = mode->vsync_len;
-    var->sync = mode->sync;
-    var->vmode = mode->vmode;
-    if (info->fbops->fb_check_var)
-       err = info->fbops->fb_check_var(var, info);
-    var->activate &= ~FB_ACTIVATE_TEST;
-    return err;
+       int err = 0;
+
+       DPRINTK("Trying mode %s %dx%d-%d@%d\n",
+               mode->name ? mode->name : "noname",
+               mode->xres, mode->yres, bpp, mode->refresh);
+       var->xres = mode->xres;
+       var->yres = mode->yres;
+       var->xres_virtual = mode->xres;
+       var->yres_virtual = mode->yres;
+       var->xoffset = 0;
+       var->yoffset = 0;
+       var->bits_per_pixel = bpp;
+       var->activate |= FB_ACTIVATE_TEST;
+       var->pixclock = mode->pixclock;
+       var->left_margin = mode->left_margin;
+       var->right_margin = mode->right_margin;
+       var->upper_margin = mode->upper_margin;
+       var->lower_margin = mode->lower_margin;
+       var->hsync_len = mode->hsync_len;
+       var->vsync_len = mode->vsync_len;
+       var->sync = mode->sync;
+       var->vmode = mode->vmode;
+       if (info->fbops->fb_check_var)
+               err = info->fbops->fb_check_var(var, info);
+       var->activate &= ~FB_ACTIVATE_TEST;
+       return err;
 }
 
 /**
- *     fb_find_mode - finds a valid video mode
- *     @var: frame buffer user defined part of display
- *     @info: frame buffer info structure
- *     @mode_option: string video mode to find
- *     @db: video mode database
- *     @dbsize: size of @db
- *     @default_mode: default video mode to fall back to
- *     @default_bpp: default color depth in bits per pixel
+ *     fb_find_mode - finds a valid video mode
+ *     @var: frame buffer user defined part of display
+ *     @info: frame buffer info structure
+ *     @mode_option: string video mode to find
+ *     @db: video mode database
+ *     @dbsize: size of @db
+ *     @default_mode: default video mode to fall back to
+ *     @default_bpp: default color depth in bits per pixel
  *
- *     Finds a suitable video mode, starting with the specified mode
- *     in @mode_option with fallback to @default_mode.  If
- *     @default_mode fails, all modes in the video mode database will
- *     be tried.
+ *     Finds a suitable video mode, starting with the specified mode
+ *     in @mode_option with fallback to @default_mode.  If
+ *     @default_mode fails, all modes in the video mode database will
+ *     be tried.
  *
- *     Valid mode specifiers for @mode_option:
+ *     Valid mode specifiers for @mode_option:
  *
- *     <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m] or
- *     <name>[-<bpp>][@<refresh>]
+ *     <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m] or
+ *     <name>[-<bpp>][@<refresh>]
  *
- *     with <xres>, <yres>, <bpp> and <refresh> decimal numbers and
- *     <name> a string.
+ *     with <xres>, <yres>, <bpp> and <refresh> decimal numbers and
+ *     <name> a string.
  *
  *      If 'M' is present after yres (and before refresh/bpp if present),
  *      the function will compute the timings using VESA(tm) Coordinated
@@ -551,12 +552,12 @@ static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
  *
  *      1024x768MR-8@60m - Reduced blank with margins at 60Hz.
  *
- *     NOTE: The passed struct @var is _not_ cleared!  This allows you
- *     to supply values for e.g. the grayscale and accel_flags fields.
+ *     NOTE: The passed struct @var is _not_ cleared!  This allows you
+ *     to supply values for e.g. the grayscale and accel_flags fields.
  *
- *     Returns zero for failure, 1 if using specified @mode_option,
- *     2 if using specified @mode_option with an ignored refresh rate,
- *     3 if default mode is used, 4 if fall back to any valid mode.
+ *     Returns zero for failure, 1 if using specified @mode_option,
+ *     2 if using specified @mode_option with an ignored refresh rate,
+ *     3 if default mode is used, 4 if fall back to any valid mode.
  *
  */
 
@@ -566,198 +567,203 @@ int fb_find_mode(struct fb_var_screeninfo *var,
                 const struct fb_videomode *default_mode,
                 unsigned int default_bpp)
 {
-    int i;
-
-    /* Set up defaults */
-    if (!db) {
-       db = modedb;
-       dbsize = ARRAY_SIZE(modedb);
-    }
-
-    if (!default_mode)
-       default_mode = &db[0];
-
-    if (!default_bpp)
-       default_bpp = 8;
-
-    /* Did the user specify a video mode? */
-    if (!mode_option)
-       mode_option = fb_mode_option;
-    if (mode_option) {
-       const char *name = mode_option;
-       unsigned int namelen = strlen(name);
-       int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
-       unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0;
-       int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0;
-       u32 best, diff, tdiff;
-
-       for (i = namelen-1; i >= 0; i--) {
-           switch (name[i]) {
-               case '@':
-                   namelen = i;
-                   if (!refresh_specified && !bpp_specified &&
-                       !yres_specified) {
-                       refresh = simple_strtol(&name[i+1], NULL, 10);
-                       refresh_specified = 1;
-                       if (cvt || rb)
-                           cvt = 0;
-                   } else
-                       goto done;
-                   break;
-               case '-':
-                   namelen = i;
-                   if (!bpp_specified && !yres_specified) {
-                       bpp = simple_strtol(&name[i+1], NULL, 10);
-                       bpp_specified = 1;
-                       if (cvt || rb)
-                           cvt = 0;
-                   } else
-                       goto done;
-                   break;
-               case 'x':
-                   if (!yres_specified) {
-                       yres = simple_strtol(&name[i+1], NULL, 10);
-                       yres_specified = 1;
-                   } else
-                       goto done;
-                   break;
-               case '0' ... '9':
-                   break;
-               case 'M':
-                   if (!yres_specified)
-                       cvt = 1;
-                   break;
-               case 'R':
-                   if (!cvt)
-                       rb = 1;
-                   break;
-               case 'm':
-                   if (!cvt)
-                       margins = 1;
-                   break;
-               case 'i':
-                   if (!cvt)
-                       interlace = 1;
-                   break;
-               default:
-                   goto done;
-           }
-       }
-       if (i < 0 && yres_specified) {
-           xres = simple_strtol(name, NULL, 10);
-           res_specified = 1;
-       }
-done:
-       if (cvt) {
-           struct fb_videomode cvt_mode;
-           int ret;
-
-           DPRINTK("CVT mode %dx%d@%dHz%s%s%s\n", xres, yres,
-                   (refresh) ? refresh : 60, (rb) ? " reduced blanking" :
-                   "", (margins) ? " with margins" : "", (interlace) ?
-                   " interlaced" : "");
-
-           memset(&cvt_mode, 0, sizeof(cvt_mode));
-           cvt_mode.xres = xres;
-           cvt_mode.yres = yres;
-           cvt_mode.refresh = (refresh) ? refresh : 60;
+       int i;
 
-           if (interlace)
-               cvt_mode.vmode |= FB_VMODE_INTERLACED;
-           else
-               cvt_mode.vmode &= ~FB_VMODE_INTERLACED;
+       /* Set up defaults */
+       if (!db) {
+               db = modedb;
+               dbsize = ARRAY_SIZE(modedb);
+       }
 
-           ret = fb_find_mode_cvt(&cvt_mode, margins, rb);
+       if (!default_mode)
+               default_mode = &db[0];
+
+       if (!default_bpp)
+               default_bpp = 8;
+
+       /* Did the user specify a video mode? */
+       if (!mode_option)
+               mode_option = fb_mode_option;
+       if (mode_option) {
+               const char *name = mode_option;
+               unsigned int namelen = strlen(name);
+               int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
+               unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0;
+               int yres_specified = 0, cvt = 0, rb = 0, interlace = 0;
+               int margins = 0;
+               u32 best, diff, tdiff;
+
+               for (i = namelen-1; i >= 0; i--) {
+                       switch (name[i]) {
+                       case '@':
+                               namelen = i;
+                               if (!refresh_specified && !bpp_specified &&
+                                   !yres_specified) {
+                                       refresh = simple_strtol(&name[i+1], NULL,
+                                                               10);
+                                       refresh_specified = 1;
+                                       if (cvt || rb)
+                                               cvt = 0;
+                               } else
+                                       goto done;
+                               break;
+                       case '-':
+                               namelen = i;
+                               if (!bpp_specified && !yres_specified) {
+                                       bpp = simple_strtol(&name[i+1], NULL,
+                                                           10);
+                                       bpp_specified = 1;
+                                       if (cvt || rb)
+                                               cvt = 0;
+                               } else
+                                       goto done;
+                               break;
+                       case 'x':
+                               if (!yres_specified) {
+                                       yres = simple_strtol(&name[i+1], NULL,
+                                                            10);
+                                       yres_specified = 1;
+                               } else
+                                       goto done;
+                               break;
+                       case '0' ... '9':
+                               break;
+                       case 'M':
+                               if (!yres_specified)
+                                       cvt = 1;
+                               break;
+                       case 'R':
+                               if (!cvt)
+                                       rb = 1;
+                               break;
+                       case 'm':
+                               if (!cvt)
+                                       margins = 1;
+                               break;
+                       case 'i':
+                               if (!cvt)
+                                       interlace = 1;
+                               break;
+                       default:
+                               goto done;
+                       }
+               }
+               if (i < 0 && yres_specified) {
+                       xres = simple_strtol(name, NULL, 10);
+                       res_specified = 1;
+               }
+done:
+               if (cvt) {
+                       struct fb_videomode cvt_mode;
+                       int ret;
+
+                       DPRINTK("CVT mode %dx%d@%dHz%s%s%s\n", xres, yres,
+                               (refresh) ? refresh : 60,
+                               (rb) ? " reduced blanking" : "",
+                               (margins) ? " with margins" : "",
+                               (interlace) ? " interlaced" : "");
+
+                       memset(&cvt_mode, 0, sizeof(cvt_mode));
+                       cvt_mode.xres = xres;
+                       cvt_mode.yres = yres;
+                       cvt_mode.refresh = (refresh) ? refresh : 60;
+
+                       if (interlace)
+                               cvt_mode.vmode |= FB_VMODE_INTERLACED;
+                       else
+                               cvt_mode.vmode &= ~FB_VMODE_INTERLACED;
+
+                       ret = fb_find_mode_cvt(&cvt_mode, margins, rb);
+
+                       if (!ret && !fb_try_mode(var, info, &cvt_mode, bpp)) {
+                               DPRINTK("modedb CVT: CVT mode ok\n");
+                               return 1;
+                       }
 
-           if (!ret && !fb_try_mode(var, info, &cvt_mode, bpp)) {
-               DPRINTK("modedb CVT: CVT mode ok\n");
-               return 1;
-           }
+                       DPRINTK("CVT mode invalid, getting mode from database\n");
+               }
 
-           DPRINTK("CVT mode invalid, getting mode from database\n");
-       }
+               DPRINTK("Trying specified video mode%s %ix%i\n",
+                       refresh_specified ? "" : " (ignoring refresh rate)",
+                       xres, yres);
 
-       DPRINTK("Trying specified video mode%s %ix%i\n",
-           refresh_specified ? "" : " (ignoring refresh rate)", xres, yres);
-
-       if (!refresh_specified) {
-               /*
-                * If the caller has provided a custom mode database and a
-                * valid monspecs structure, we look for the mode with the
-                * highest refresh rate.  Otherwise we play it safe it and
-                * try to find a mode with a refresh rate closest to the
-                * standard 60 Hz.
-                */
-               if (db != modedb &&
-                   info->monspecs.vfmin && info->monspecs.vfmax &&
-                   info->monspecs.hfmin && info->monspecs.hfmax &&
-                   info->monspecs.dclkmax) {
-                       refresh = 1000;
-               } else {
-                       refresh = 60;
+               if (!refresh_specified) {
+                       /*
+                        * If the caller has provided a custom mode database and
+                        * a valid monspecs structure, we look for the mode with
+                        * the highest refresh rate.  Otherwise we play it safe
+                        * it and try to find a mode with a refresh rate closest
+                        * to the standard 60 Hz.
+                        */
+                       if (db != modedb &&
+                           info->monspecs.vfmin && info->monspecs.vfmax &&
+                           info->monspecs.hfmin && info->monspecs.hfmax &&
+                           info->monspecs.dclkmax) {
+                               refresh = 1000;
+                       } else {
+                               refresh = 60;
+                       }
                }
-       }
 
-       diff = -1;
-       best = -1;
-       for (i = 0; i < dbsize; i++) {
-               if ((name_matches(db[i], name, namelen) ||
-                   (res_specified && res_matches(db[i], xres, yres))) &&
-                   !fb_try_mode(var, info, &db[i], bpp)) {
-                       if (refresh_specified && db[i].refresh == refresh) {
-                               return 1;
-                       } else {
+               diff = -1;
+               best = -1;
+               for (i = 0; i < dbsize; i++) {
+                       if ((name_matches(db[i], name, namelen) ||
+                            (res_specified && res_matches(db[i], xres, yres))) &&
+                           !fb_try_mode(var, info, &db[i], bpp)) {
+                               if (refresh_specified && db[i].refresh == refresh)
+                                       return 1;
+
                                if (abs(db[i].refresh - refresh) < diff) {
                                        diff = abs(db[i].refresh - refresh);
                                        best = i;
                                }
                        }
                }
-       }
-       if (best != -1) {
-               fb_try_mode(var, info, &db[best], bpp);
-               return (refresh_specified) ? 2 : 1;
-       }
-
-       diff = 2 * (xres + yres);
-       best = -1;
-       DPRINTK("Trying best-fit modes\n");
-       for (i = 0; i < dbsize; i++) {
-               DPRINTK("Trying %ix%i\n", db[i].xres, db[i].yres);
-               if (!fb_try_mode(var, info, &db[i], bpp)) {
-                       tdiff = abs(db[i].xres - xres) +
-                               abs(db[i].yres - yres);
-
-                       /*
-                        * Penalize modes with resolutions smaller
-                        * than requested.
-                        */
-                       if (xres > db[i].xres || yres > db[i].yres)
-                               tdiff += xres + yres;
+               if (best != -1) {
+                       fb_try_mode(var, info, &db[best], bpp);
+                       return (refresh_specified) ? 2 : 1;
+               }
 
-                       if (diff > tdiff) {
-                               diff = tdiff;
-                               best = i;
+               diff = 2 * (xres + yres);
+               best = -1;
+               DPRINTK("Trying best-fit modes\n");
+               for (i = 0; i < dbsize; i++) {
+                       DPRINTK("Trying %ix%i\n", db[i].xres, db[i].yres);
+                       if (!fb_try_mode(var, info, &db[i], bpp)) {
+                               tdiff = abs(db[i].xres - xres) +
+                                       abs(db[i].yres - yres);
+
+                               /*
+                                * Penalize modes with resolutions smaller
+                                * than requested.
+                                */
+                               if (xres > db[i].xres || yres > db[i].yres)
+                                       tdiff += xres + yres;
+
+                               if (diff > tdiff) {
+                                       diff = tdiff;
+                                       best = i;
+                               }
                        }
                }
+               if (best != -1) {
+                       fb_try_mode(var, info, &db[best], bpp);
+                       return 5;
+               }
        }
-       if (best != -1) {
-           fb_try_mode(var, info, &db[best], bpp);
-           return 5;
-       }
-    }
 
-    DPRINTK("Trying default video mode\n");
-    if (!fb_try_mode(var, info, default_mode, default_bpp))
-       return 3;
+       DPRINTK("Trying default video mode\n");
+       if (!fb_try_mode(var, info, default_mode, default_bpp))
+               return 3;
 
-    DPRINTK("Trying all modes\n");
-    for (i = 0; i < dbsize; i++)
-       if (!fb_try_mode(var, info, &db[i], default_bpp))
-           return 4;
+       DPRINTK("Trying all modes\n");
+       for (i = 0; i < dbsize; i++)
+               if (!fb_try_mode(var, info, &db[i], default_bpp))
+                       return 4;
 
-    DPRINTK("No valid mode found\n");
-    return 0;
+       DPRINTK("No valid mode found\n");
+       return 0;
 }
 
 /**
index 178b072..4527cbf 100644 (file)
@@ -715,7 +715,7 @@ static int __devinit mddi_probe(struct platform_device *pdev)
 
        mddi->int_enable = 0;
        mddi_writel(mddi->int_enable, INTEN);
-       ret = request_irq(mddi->irq, mddi_isr, IRQF_DISABLED, "mddi",
+       ret = request_irq(mddi->irq, mddi_isr, 0, "mddi",
                          &mddi->client_data);
        if (ret) {
                printk(KERN_ERR "mddi: failed to request enable irq!\n");
index 243d16f..b934477 100644 (file)
@@ -421,10 +421,11 @@ int mdp_probe(struct platform_device *pdev)
        clk = clk_get(&pdev->dev, "mdp_clk");
        if (IS_ERR(clk)) {
                printk(KERN_INFO "mdp: failed to get mdp clk");
-               return PTR_ERR(clk);
+               ret = PTR_ERR(clk);
+               goto error_get_clk;
        }
 
-       ret = request_irq(mdp->irq, mdp_isr, IRQF_DISABLED, "msm_mdp", mdp);
+       ret = request_irq(mdp->irq, mdp_isr, 0, "msm_mdp", mdp);
        if (ret)
                goto error_request_irq;
        disable_irq(mdp->irq);
@@ -495,6 +496,7 @@ int mdp_probe(struct platform_device *pdev)
 error_device_register:
        free_irq(mdp->irq, mdp);
 error_request_irq:
+error_get_clk:
        iounmap(mdp->base);
 error_get_irq:
 error_ioremap:
index 7e3a490..e3406ab 100644 (file)
@@ -382,6 +382,9 @@ static void sdc_disable_channel(struct mx3fb_info *mx3_fbi)
        uint32_t enabled;
        unsigned long flags;
 
+       if (mx3_fbi->txd == NULL)
+               return;
+
        spin_lock_irqsave(&mx3fb->lock, flags);
 
        enabled = sdc_fb_uninit(mx3_fbi);
@@ -986,9 +989,19 @@ static void __blank(int blank, struct fb_info *fbi)
 {
        struct mx3fb_info *mx3_fbi = fbi->par;
        struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
+       int was_blank = mx3_fbi->blank;
 
        mx3_fbi->blank = blank;
 
+       /* Attention!
+        * Do not call sdc_disable_channel() for a channel that is disabled
+        * already! This will result in a kernel NULL pointer dereference
+        * (mx3_fbi->txd is NULL). Hide the fact, that all blank modes are
+        * handled equally by this driver.
+        */
+       if (blank > FB_BLANK_UNBLANK && was_blank > FB_BLANK_UNBLANK)
+               return;
+
        switch (blank) {
        case FB_BLANK_POWERDOWN:
        case FB_BLANK_VSYNC_SUSPEND:
@@ -1062,15 +1075,15 @@ static int mx3fb_pan_display(struct fb_var_screeninfo *var,
        y_bottom = var->yoffset;
 
        if (!(var->vmode & FB_VMODE_YWRAP))
-               y_bottom += var->yres;
+               y_bottom += fbi->var.yres;
 
        if (y_bottom > fbi->var.yres_virtual)
                return -EINVAL;
 
        mutex_lock(&mx3_fbi->mutex);
 
-       offset = (var->yoffset * var->xres_virtual + var->xoffset) *
-               (var->bits_per_pixel / 8);
+       offset = var->yoffset * fbi->fix.line_length
+              + var->xoffset * (fbi->var.bits_per_pixel / 8);
        base = fbi->fix.smem_start + offset;
 
        dev_dbg(fbi->device, "Updating SDC BG buf %d address=0x%08lX\n",
index 0b2f2dd..d837d63 100644 (file)
@@ -39,6 +39,7 @@
  * the required value in the imx_fb_videomode structure.
  */
 
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
index 588527a..feea7b1 100644 (file)
@@ -1185,8 +1185,8 @@ static int neofb_pan_display(struct fb_var_screeninfo *var,
 
        DBG("neofb_update_start");
 
-       Base = (var->yoffset * var->xres_virtual + var->xoffset) >> 2;
-       Base *= (var->bits_per_pixel + 7) / 8;
+       Base = (var->yoffset * info->var.xres_virtual + var->xoffset) >> 2;
+       Base *= (info->var.bits_per_pixel + 7) / 8;
 
        neoUnlock();
 
index 0fff597..d1fbbd8 100644 (file)
@@ -39,7 +39,6 @@
 #include <mach/regs-clock.h>
 #include <mach/regs-ldm.h>
 #include <mach/fb.h>
-#include <mach/clkdev.h>
 
 #include "nuc900fb.h"
 
@@ -588,7 +587,7 @@ static int __devinit nuc900fb_probe(struct platform_device *pdev)
        fbinfo->flags                   = FBINFO_FLAG_DEFAULT;
        fbinfo->pseudo_palette          = &fbi->pseudo_pal;
 
-       ret = request_irq(irq, nuc900fb_irqhandler, IRQF_DISABLED,
+       ret = request_irq(irq, nuc900fb_irqhandler, 0,
                          pdev->name, fbinfo);
        if (ret) {
                dev_err(&pdev->dev, "cannot register irq handler %d -err %d\n",
index 196fa2e..84ff232 100644 (file)
@@ -9,35 +9,6 @@ config FB_OMAP
        help
           Frame buffer driver for OMAP based boards.
 
-config FB_OMAP_LCD_VGA
-        bool "Use LCD in VGA mode"
-               depends on MACH_OMAP_3430SDP || MACH_OMAP_LDP
-               help
-                 Set LCD resolution as VGA (640 X 480).
-                 Default resolution without this option is QVGA(320 X 240).
-                 Please take a look at drivers/video/omap/lcd_ldp.c file
-                 for lcd driver code.
-choice
-       depends on FB_OMAP && MACH_OVERO
-       prompt "Screen resolution"
-       default FB_OMAP_079M3R
-       help
-         Selected desired screen resolution
-
-config FB_OMAP_031M3R
-       boolean "640 x 480 @ 60 Hz Reduced blanking"
-
-config FB_OMAP_048M3R
-       boolean "800 x 600 @ 60 Hz Reduced blanking"
-
-config FB_OMAP_079M3R
-       boolean "1024 x 768 @ 60 Hz Reduced blanking"
-
-config FB_OMAP_092M9R
-       boolean "1280 x 720 @ 60 Hz Reduced blanking"
-
-endchoice
-
 config FB_OMAP_LCDC_EXTERNAL
        bool "External LCD controller support"
        depends on FB_OMAP
index 25db556..ef78550 100644 (file)
@@ -17,7 +17,6 @@ objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o
 objs-y$(CONFIG_FB_OMAP_LCDC_BLIZZARD) += blizzard.o
 
 objs-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o
-objs-y$(CONFIG_MACH_OMAP_H4) += lcd_h4.o
 objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o
 objs-y$(CONFIG_MACH_OMAP_PALMTE) += lcd_palmte.o
 objs-y$(CONFIG_MACH_OMAP_PALMTT) += lcd_palmtt.o
@@ -26,14 +25,7 @@ objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1610.o
 objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o
 objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o
 
-objs-y$(CONFIG_MACH_OMAP_APOLLON) += lcd_apollon.o
-objs-y$(CONFIG_MACH_OMAP_2430SDP) += lcd_2430sdp.o
-objs-y$(CONFIG_MACH_OMAP_3430SDP) += lcd_2430sdp.o
-objs-y$(CONFIG_MACH_OMAP_LDP) += lcd_ldp.o
-objs-y$(CONFIG_MACH_OMAP3EVM) += lcd_omap3evm.o
-objs-y$(CONFIG_MACH_OMAP3_BEAGLE) += lcd_omap3beagle.o
 objs-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o
-objs-y$(CONFIG_MACH_OVERO) += lcd_overo.o
 objs-y$(CONFIG_MACH_HERALD) += lcd_htcherald.o
 
 omapfb-objs := $(objs-yy)
diff --git a/drivers/video/omap/lcd_2430sdp.c b/drivers/video/omap/lcd_2430sdp.c
deleted file mode 100644 (file)
index e3eccc9..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * LCD panel support for the TI 2430SDP board
- *
- * Copyright (C) 2007 MontaVista
- * Author: Hunyue Yau <hyau@mvista.com>
- *
- * Derived from drivers/video/omap/lcd-apollon.c
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/i2c/twl.h>
-
-#include <plat/mux.h>
-#include <asm/mach-types.h>
-
-#include "omapfb.h"
-
-#define SDP2430_LCD_PANEL_BACKLIGHT_GPIO       91
-#define SDP2430_LCD_PANEL_ENABLE_GPIO          154
-#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO       24
-#define SDP3430_LCD_PANEL_ENABLE_GPIO          28
-
-static unsigned backlight_gpio;
-static unsigned enable_gpio;
-
-#define LCD_PIXCLOCK_MAX               5400 /* freq 5.4 MHz */
-#define PM_RECEIVER             TWL4030_MODULE_PM_RECEIVER
-#define ENABLE_VAUX2_DEDICATED  0x09
-#define ENABLE_VAUX2_DEV_GRP    0x20
-#define ENABLE_VAUX3_DEDICATED 0x03
-#define ENABLE_VAUX3_DEV_GRP   0x20
-
-#define ENABLE_VPLL2_DEDICATED          0x05
-#define ENABLE_VPLL2_DEV_GRP            0xE0
-#define TWL4030_VPLL2_DEV_GRP           0x33
-#define TWL4030_VPLL2_DEDICATED         0x36
-
-#define t2_out(c, r, v) twl_i2c_write_u8(c, r, v)
-
-
-static int sdp2430_panel_init(struct lcd_panel *panel,
-                               struct omapfb_device *fbdev)
-{
-       if (machine_is_omap_3430sdp()) {
-               enable_gpio    = SDP3430_LCD_PANEL_ENABLE_GPIO;
-               backlight_gpio = SDP3430_LCD_PANEL_BACKLIGHT_GPIO;
-       } else {
-               enable_gpio    = SDP2430_LCD_PANEL_ENABLE_GPIO;
-               backlight_gpio = SDP2430_LCD_PANEL_BACKLIGHT_GPIO;
-       }
-
-       gpio_request(enable_gpio, "LCD enable");        /* LCD panel */
-       gpio_request(backlight_gpio, "LCD bl");         /* LCD backlight */
-       gpio_direction_output(enable_gpio, 0);
-       gpio_direction_output(backlight_gpio, 0);
-
-       return 0;
-}
-
-static void sdp2430_panel_cleanup(struct lcd_panel *panel)
-{
-       gpio_free(backlight_gpio);
-       gpio_free(enable_gpio);
-}
-
-static int sdp2430_panel_enable(struct lcd_panel *panel)
-{
-       u8 ded_val, ded_reg;
-       u8 grp_val, grp_reg;
-
-       if (machine_is_omap_3430sdp()) {
-               ded_reg = TWL4030_VAUX3_DEDICATED;
-               ded_val = ENABLE_VAUX3_DEDICATED;
-               grp_reg = TWL4030_VAUX3_DEV_GRP;
-               grp_val = ENABLE_VAUX3_DEV_GRP;
-
-               if (omap_rev() > OMAP3430_REV_ES1_0) {
-                       t2_out(PM_RECEIVER, ENABLE_VPLL2_DEDICATED,
-                                       TWL4030_VPLL2_DEDICATED);
-                       t2_out(PM_RECEIVER, ENABLE_VPLL2_DEV_GRP,
-                                       TWL4030_VPLL2_DEV_GRP);
-               }
-       } else {
-               ded_reg = TWL4030_VAUX2_DEDICATED;
-               ded_val = ENABLE_VAUX2_DEDICATED;
-               grp_reg = TWL4030_VAUX2_DEV_GRP;
-               grp_val = ENABLE_VAUX2_DEV_GRP;
-       }
-
-       gpio_set_value(enable_gpio, 1);
-       gpio_set_value(backlight_gpio, 1);
-
-       if (0 != t2_out(PM_RECEIVER, ded_val, ded_reg))
-               return -EIO;
-       if (0 != t2_out(PM_RECEIVER, grp_val, grp_reg))
-               return -EIO;
-
-       return 0;
-}
-
-static void sdp2430_panel_disable(struct lcd_panel *panel)
-{
-       gpio_set_value(enable_gpio, 0);
-       gpio_set_value(backlight_gpio, 0);
-       if (omap_rev() > OMAP3430_REV_ES1_0) {
-               t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEDICATED);
-               t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEV_GRP);
-               msleep(4);
-       }
-}
-
-static unsigned long sdp2430_panel_get_caps(struct lcd_panel *panel)
-{
-       return 0;
-}
-
-struct lcd_panel sdp2430_panel = {
-       .name           = "sdp2430",
-       .config         = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
-                         OMAP_LCDC_INV_HSYNC,
-
-       .bpp            = 16,
-       .data_lines     = 16,
-       .x_res          = 240,
-       .y_res          = 320,
-       .hsw            = 3,            /* hsync_len (4) - 1 */
-       .hfp            = 3,            /* right_margin (4) - 1 */
-       .hbp            = 39,           /* left_margin (40) - 1 */
-       .vsw            = 1,            /* vsync_len (2) - 1 */
-       .vfp            = 2,            /* lower_margin */
-       .vbp            = 7,            /* upper_margin (8) - 1 */
-
-       .pixel_clock    = LCD_PIXCLOCK_MAX,
-
-       .init           = sdp2430_panel_init,
-       .cleanup        = sdp2430_panel_cleanup,
-       .enable         = sdp2430_panel_enable,
-       .disable        = sdp2430_panel_disable,
-       .get_caps       = sdp2430_panel_get_caps,
-};
-
-static int sdp2430_panel_probe(struct platform_device *pdev)
-{
-       omapfb_register_panel(&sdp2430_panel);
-       return 0;
-}
-
-static int sdp2430_panel_remove(struct platform_device *pdev)
-{
-       return 0;
-}
-
-static int sdp2430_panel_suspend(struct platform_device *pdev,
-                                       pm_message_t mesg)
-{
-       return 0;
-}
-
-static int sdp2430_panel_resume(struct platform_device *pdev)
-{
-       return 0;
-}
-
-struct platform_driver sdp2430_panel_driver = {
-       .probe          = sdp2430_panel_probe,
-       .remove         = sdp2430_panel_remove,
-       .suspend        = sdp2430_panel_suspend,
-       .resume         = sdp2430_panel_resume,
-       .driver         = {
-               .name   = "sdp2430_lcd",
-               .owner  = THIS_MODULE,
-       },
-};
-
-static int __init sdp2430_panel_drv_init(void)
-{
-       return platform_driver_register(&sdp2430_panel_driver);
-}
-
-static void __exit sdp2430_panel_drv_exit(void)
-{
-       platform_driver_unregister(&sdp2430_panel_driver);
-}
-
-module_init(sdp2430_panel_drv_init);
-module_exit(sdp2430_panel_drv_exit);
diff --git a/drivers/video/omap/lcd_apollon.c b/drivers/video/omap/lcd_apollon.c
deleted file mode 100644 (file)
index 4b24f54..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * LCD panel support for the Samsung OMAP2 Apollon board
- *
- * Copyright (C) 2005,2006 Samsung Electronics
- * Author: Kyungmin Park <kyungmin.park@samsung.com>
- *
- * Derived from drivers/video/omap/lcd-h4.c
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-#include <asm/gpio.h>
-
-#include "omapfb.h"
-
-/* #define USE_35INCH_LCD 1 */
-
-static int apollon_panel_init(struct lcd_panel *panel,
-                               struct omapfb_device *fbdev)
-{
-       return 0;
-}
-
-static void apollon_panel_cleanup(struct lcd_panel *panel)
-{
-}
-
-static int apollon_panel_enable(struct lcd_panel *panel)
-{
-       return 0;
-}
-
-static void apollon_panel_disable(struct lcd_panel *panel)
-{
-}
-
-static unsigned long apollon_panel_get_caps(struct lcd_panel *panel)
-{
-       return 0;
-}
-
-struct lcd_panel apollon_panel = {
-       .name           = "apollon",
-       .config         = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
-                         OMAP_LCDC_INV_HSYNC,
-
-       .bpp            = 16,
-       .data_lines     = 18,
-#ifdef USE_35INCH_LCD
-       .x_res          = 240,
-       .y_res          = 320,
-       .hsw            = 2,
-       .hfp            = 3,
-       .hbp            = 9,
-       .vsw            = 4,
-       .vfp            = 3,
-       .vbp            = 5,
-#else
-       .x_res          = 480,
-       .y_res          = 272,
-       .hsw            = 41,
-       .hfp            = 2,
-       .hbp            = 2,
-       .vsw            = 10,
-       .vfp            = 2,
-       .vbp            = 2,
-#endif
-       .pixel_clock    = 6250,
-
-       .init           = apollon_panel_init,
-       .cleanup        = apollon_panel_cleanup,
-       .enable         = apollon_panel_enable,
-       .disable        = apollon_panel_disable,
-       .get_caps       = apollon_panel_get_caps,
-};
-
-static int apollon_panel_probe(struct platform_device *pdev)
-{
-       omapfb_register_panel(&apollon_panel);
-       return 0;
-}
-
-static int apollon_panel_remove(struct platform_device *pdev)
-{
-       return 0;
-}
-
-static int apollon_panel_suspend(struct platform_device *pdev,
-                                 pm_message_t mesg)
-{
-       return 0;
-}
-
-static int apollon_panel_resume(struct platform_device *pdev)
-{
-       return 0;
-}
-
-struct platform_driver apollon_panel_driver = {
-       .probe          = apollon_panel_probe,
-       .remove         = apollon_panel_remove,
-       .suspend        = apollon_panel_suspend,
-       .resume         = apollon_panel_resume,
-       .driver         = {
-               .name   = "apollon_lcd",
-               .owner  = THIS_MODULE,
-       },
-};
-
-static int __init apollon_panel_drv_init(void)
-{
-       return platform_driver_register(&apollon_panel_driver);
-}
-
-static void __exit apollon_panel_drv_exit(void)
-{
-       platform_driver_unregister(&apollon_panel_driver);
-}
-
-module_init(apollon_panel_drv_init);
-module_exit(apollon_panel_drv_exit);
diff --git a/drivers/video/omap/lcd_h4.c b/drivers/video/omap/lcd_h4.c
deleted file mode 100644 (file)
index 03a06a9..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * LCD panel support for the TI OMAP H4 board
- *
- * Copyright (C) 2004 Nokia Corporation
- * Author: Imre Deak <imre.deak@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-#include "omapfb.h"
-
-static int h4_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
-{
-       return 0;
-}
-
-static void h4_panel_cleanup(struct lcd_panel *panel)
-{
-}
-
-static int h4_panel_enable(struct lcd_panel *panel)
-{
-       return 0;
-}
-
-static void h4_panel_disable(struct lcd_panel *panel)
-{
-}
-
-static unsigned long h4_panel_get_caps(struct lcd_panel *panel)
-{
-       return 0;
-}
-
-static struct lcd_panel h4_panel = {
-       .name           = "h4",
-       .config         = OMAP_LCDC_PANEL_TFT,
-
-       .bpp            = 16,
-       .data_lines     = 16,
-       .x_res          = 240,
-       .y_res          = 320,
-       .pixel_clock    = 6250,
-       .hsw            = 15,
-       .hfp            = 15,
-       .hbp            = 60,
-       .vsw            = 1,
-       .vfp            = 1,
-       .vbp            = 1,
-
-       .init           = h4_panel_init,
-       .cleanup        = h4_panel_cleanup,
-       .enable         = h4_panel_enable,
-       .disable        = h4_panel_disable,
-       .get_caps       = h4_panel_get_caps,
-};
-
-static int h4_panel_probe(struct platform_device *pdev)
-{
-       omapfb_register_panel(&h4_panel);
-       return 0;
-}
-
-static int h4_panel_remove(struct platform_device *pdev)
-{
-       return 0;
-}
-
-static int h4_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
-{
-       return 0;
-}
-
-static int h4_panel_resume(struct platform_device *pdev)
-{
-       return 0;
-}
-
-static struct platform_driver h4_panel_driver = {
-       .probe          = h4_panel_probe,
-       .remove         = h4_panel_remove,
-       .suspend        = h4_panel_suspend,
-       .resume         = h4_panel_resume,
-       .driver         = {
-               .name   = "lcd_h4",
-               .owner  = THIS_MODULE,
-       },
-};
-
-static int __init h4_panel_drv_init(void)
-{
-       return platform_driver_register(&h4_panel_driver);
-}
-
-static void __exit h4_panel_drv_cleanup(void)
-{
-       platform_driver_unregister(&h4_panel_driver);
-}
-
-module_init(h4_panel_drv_init);
-module_exit(h4_panel_drv_cleanup);
-
diff --git a/drivers/video/omap/lcd_ldp.c b/drivers/video/omap/lcd_ldp.c
deleted file mode 100644 (file)
index 0624664..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * LCD panel support for the TI LDP board
- *
- * Copyright (C) 2007 WindRiver
- * Author: Stanley Miao <stanley.miao@windriver.com>
- *
- * Derived from drivers/video/omap/lcd-2430sdp.c
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/i2c/twl.h>
-
-#include <asm/gpio.h>
-#include <plat/mux.h>
-#include <asm/mach-types.h>
-
-#include "omapfb.h"
-
-#define LCD_PANEL_BACKLIGHT_GPIO       (15 + OMAP_MAX_GPIO_LINES)
-#define LCD_PANEL_ENABLE_GPIO          (7 + OMAP_MAX_GPIO_LINES)
-
-#define LCD_PANEL_RESET_GPIO           55
-#define LCD_PANEL_QVGA_GPIO            56
-
-#ifdef CONFIG_FB_OMAP_LCD_VGA
-#define LCD_XRES               480
-#define LCD_YRES               640
-#define LCD_PIXCLOCK_MAX       41700
-#else
-#define LCD_XRES               240
-#define LCD_YRES               320
-#define LCD_PIXCLOCK_MAX       185186
-#endif
-
-#define PM_RECEIVER             TWL4030_MODULE_PM_RECEIVER
-#define ENABLE_VAUX2_DEDICATED  0x09
-#define ENABLE_VAUX2_DEV_GRP    0x20
-#define ENABLE_VAUX3_DEDICATED 0x03
-#define ENABLE_VAUX3_DEV_GRP   0x20
-
-#define ENABLE_VPLL2_DEDICATED          0x05
-#define ENABLE_VPLL2_DEV_GRP            0xE0
-#define TWL4030_VPLL2_DEV_GRP           0x33
-#define TWL4030_VPLL2_DEDICATED         0x36
-
-#define t2_out(c, r, v) twl_i2c_write_u8(c, r, v)
-
-
-static int ldp_panel_init(struct lcd_panel *panel,
-                               struct omapfb_device *fbdev)
-{
-       gpio_request(LCD_PANEL_RESET_GPIO, "lcd reset");
-       gpio_request(LCD_PANEL_QVGA_GPIO, "lcd qvga");
-       gpio_request(LCD_PANEL_ENABLE_GPIO, "lcd panel");
-       gpio_request(LCD_PANEL_BACKLIGHT_GPIO, "lcd backlight");
-
-       gpio_direction_output(LCD_PANEL_QVGA_GPIO, 0);
-       gpio_direction_output(LCD_PANEL_RESET_GPIO, 0);
-       gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 0);
-       gpio_direction_output(LCD_PANEL_BACKLIGHT_GPIO, 0);
-
-#ifdef CONFIG_FB_OMAP_LCD_VGA
-       gpio_set_value(LCD_PANEL_QVGA_GPIO, 0);
-#else
-       gpio_set_value(LCD_PANEL_QVGA_GPIO, 1);
-#endif
-       gpio_set_value(LCD_PANEL_RESET_GPIO, 1);
-
-       return 0;
-}
-
-static void ldp_panel_cleanup(struct lcd_panel *panel)
-{
-       gpio_free(LCD_PANEL_BACKLIGHT_GPIO);
-       gpio_free(LCD_PANEL_ENABLE_GPIO);
-       gpio_free(LCD_PANEL_QVGA_GPIO);
-       gpio_free(LCD_PANEL_RESET_GPIO);
-}
-
-static int ldp_panel_enable(struct lcd_panel *panel)
-{
-       if (0 != t2_out(PM_RECEIVER, ENABLE_VPLL2_DEDICATED,
-                       TWL4030_VPLL2_DEDICATED))
-               return -EIO;
-       if (0 != t2_out(PM_RECEIVER, ENABLE_VPLL2_DEV_GRP,
-                       TWL4030_VPLL2_DEV_GRP))
-               return -EIO;
-
-       gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 1);
-       gpio_direction_output(LCD_PANEL_BACKLIGHT_GPIO, 1);
-
-       if (0 != t2_out(PM_RECEIVER, ENABLE_VAUX3_DEDICATED,
-                               TWL4030_VAUX3_DEDICATED))
-               return -EIO;
-       if (0 != t2_out(PM_RECEIVER, ENABLE_VAUX3_DEV_GRP,
-                               TWL4030_VAUX3_DEV_GRP))
-               return -EIO;
-
-       return 0;
-}
-
-static void ldp_panel_disable(struct lcd_panel *panel)
-{
-       gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 0);
-       gpio_direction_output(LCD_PANEL_BACKLIGHT_GPIO, 0);
-
-       t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEDICATED);
-       t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEV_GRP);
-       msleep(4);
-}
-
-static unsigned long ldp_panel_get_caps(struct lcd_panel *panel)
-{
-       return 0;
-}
-
-struct lcd_panel ldp_panel = {
-       .name           = "ldp",
-       .config         = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
-                         OMAP_LCDC_INV_HSYNC,
-
-       .bpp            = 16,
-       .data_lines     = 18,
-       .x_res          = LCD_XRES,
-       .y_res          = LCD_YRES,
-       .hsw            = 3,            /* hsync_len (4) - 1 */
-       .hfp            = 3,            /* right_margin (4) - 1 */
-       .hbp            = 39,           /* left_margin (40) - 1 */
-       .vsw            = 1,            /* vsync_len (2) - 1 */
-       .vfp            = 2,            /* lower_margin */
-       .vbp            = 7,            /* upper_margin (8) - 1 */
-
-       .pixel_clock    = LCD_PIXCLOCK_MAX,
-
-       .init           = ldp_panel_init,
-       .cleanup        = ldp_panel_cleanup,
-       .enable         = ldp_panel_enable,
-       .disable        = ldp_panel_disable,
-       .get_caps       = ldp_panel_get_caps,
-};
-
-static int ldp_panel_probe(struct platform_device *pdev)
-{
-       omapfb_register_panel(&ldp_panel);
-       return 0;
-}
-
-static int ldp_panel_remove(struct platform_device *pdev)
-{
-       return 0;
-}
-
-static int ldp_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
-{
-       return 0;
-}
-
-static int ldp_panel_resume(struct platform_device *pdev)
-{
-       return 0;
-}
-
-struct platform_driver ldp_panel_driver = {
-       .probe          = ldp_panel_probe,
-       .remove         = ldp_panel_remove,
-       .suspend        = ldp_panel_suspend,
-       .resume         = ldp_panel_resume,
-       .driver         = {
-               .name   = "ldp_lcd",
-               .owner  = THIS_MODULE,
-       },
-};
-
-static int __init ldp_panel_drv_init(void)
-{
-       return platform_driver_register(&ldp_panel_driver);
-}
-
-static void __exit ldp_panel_drv_exit(void)
-{
-       platform_driver_unregister(&ldp_panel_driver);
-}
-
-module_init(ldp_panel_drv_init);
-module_exit(ldp_panel_drv_exit);
diff --git a/drivers/video/omap/lcd_omap3beagle.c b/drivers/video/omap/lcd_omap3beagle.c
deleted file mode 100644 (file)
index d7c6c3e..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * LCD panel support for the TI OMAP3 Beagle board
- *
- * Author: Koen Kooi <koen@openembedded.org>
- *
- * Derived from drivers/video/omap/lcd-omap3evm.c
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/i2c/twl.h>
-
-#include <asm/mach-types.h>
-
-#include "omapfb.h"
-
-#define LCD_PANEL_ENABLE_GPIO       170
-
-static int omap3beagle_panel_init(struct lcd_panel *panel,
-                               struct omapfb_device *fbdev)
-{
-       gpio_request(LCD_PANEL_ENABLE_GPIO, "LCD enable");
-       return 0;
-}
-
-static void omap3beagle_panel_cleanup(struct lcd_panel *panel)
-{
-       gpio_free(LCD_PANEL_ENABLE_GPIO);
-}
-
-static int omap3beagle_panel_enable(struct lcd_panel *panel)
-{
-       gpio_set_value(LCD_PANEL_ENABLE_GPIO, 1);
-       return 0;
-}
-
-static void omap3beagle_panel_disable(struct lcd_panel *panel)
-{
-       gpio_set_value(LCD_PANEL_ENABLE_GPIO, 0);
-}
-
-static unsigned long omap3beagle_panel_get_caps(struct lcd_panel *panel)
-{
-       return 0;
-}
-
-struct lcd_panel omap3beagle_panel = {
-       .name           = "omap3beagle",
-       .config         = OMAP_LCDC_PANEL_TFT,
-
-       .bpp            = 16,
-       .data_lines     = 24,
-       .x_res          = 1024,
-       .y_res          = 768,
-       .hsw            = 3,            /* hsync_len (4) - 1 */
-       .hfp            = 3,            /* right_margin (4) - 1 */
-       .hbp            = 39,           /* left_margin (40) - 1 */
-       .vsw            = 1,            /* vsync_len (2) - 1 */
-       .vfp            = 2,            /* lower_margin */
-       .vbp            = 7,            /* upper_margin (8) - 1 */
-
-       .pixel_clock    = 64000,
-
-       .init           = omap3beagle_panel_init,
-       .cleanup        = omap3beagle_panel_cleanup,
-       .enable         = omap3beagle_panel_enable,
-       .disable        = omap3beagle_panel_disable,
-       .get_caps       = omap3beagle_panel_get_caps,
-};
-
-static int omap3beagle_panel_probe(struct platform_device *pdev)
-{
-       omapfb_register_panel(&omap3beagle_panel);
-       return 0;
-}
-
-static int omap3beagle_panel_remove(struct platform_device *pdev)
-{
-       return 0;
-}
-
-static int omap3beagle_panel_suspend(struct platform_device *pdev,
-                                  pm_message_t mesg)
-{
-       return 0;
-}
-
-static int omap3beagle_panel_resume(struct platform_device *pdev)
-{
-       return 0;
-}
-
-struct platform_driver omap3beagle_panel_driver = {
-       .probe          = omap3beagle_panel_probe,
-       .remove         = omap3beagle_panel_remove,
-       .suspend        = omap3beagle_panel_suspend,
-       .resume         = omap3beagle_panel_resume,
-       .driver         = {
-               .name   = "omap3beagle_lcd",
-               .owner  = THIS_MODULE,
-       },
-};
-
-static int __init omap3beagle_panel_drv_init(void)
-{
-       return platform_driver_register(&omap3beagle_panel_driver);
-}
-
-static void __exit omap3beagle_panel_drv_exit(void)
-{
-       platform_driver_unregister(&omap3beagle_panel_driver);
-}
-
-module_init(omap3beagle_panel_drv_init);
-module_exit(omap3beagle_panel_drv_exit);
diff --git a/drivers/video/omap/lcd_omap3evm.c b/drivers/video/omap/lcd_omap3evm.c
deleted file mode 100644 (file)
index 06840da..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * LCD panel support for the TI OMAP3 EVM board
- *
- * Author: Steve Sakoman <steve@sakoman.com>
- *
- * Derived from drivers/video/omap/lcd-apollon.c
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/i2c/twl.h>
-
-#include <plat/mux.h>
-#include <asm/mach-types.h>
-
-#include "omapfb.h"
-
-#define LCD_PANEL_ENABLE_GPIO       153
-#define LCD_PANEL_LR                2
-#define LCD_PANEL_UD                3
-#define LCD_PANEL_INI               152
-#define LCD_PANEL_QVGA              154
-#define LCD_PANEL_RESB              155
-
-#define ENABLE_VDAC_DEDICATED  0x03
-#define ENABLE_VDAC_DEV_GRP    0x20
-#define ENABLE_VPLL2_DEDICATED 0x05
-#define ENABLE_VPLL2_DEV_GRP   0xE0
-
-#define TWL_LED_LEDEN          0x00
-#define TWL_PWMA_PWMAON                0x00
-#define TWL_PWMA_PWMAOFF       0x01
-
-static unsigned int bklight_level;
-
-static int omap3evm_panel_init(struct lcd_panel *panel,
-                               struct omapfb_device *fbdev)
-{
-       gpio_request(LCD_PANEL_LR, "LCD lr");
-       gpio_request(LCD_PANEL_UD, "LCD ud");
-       gpio_request(LCD_PANEL_INI, "LCD ini");
-       gpio_request(LCD_PANEL_RESB, "LCD resb");
-       gpio_request(LCD_PANEL_QVGA, "LCD qvga");
-
-       gpio_direction_output(LCD_PANEL_RESB, 1);
-       gpio_direction_output(LCD_PANEL_INI, 1);
-       gpio_direction_output(LCD_PANEL_QVGA, 0);
-       gpio_direction_output(LCD_PANEL_LR, 1);
-       gpio_direction_output(LCD_PANEL_UD, 1);
-
-       twl_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN);
-       twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON);
-       twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF);
-       bklight_level = 100;
-
-       return 0;
-}
-
-static void omap3evm_panel_cleanup(struct lcd_panel *panel)
-{
-       gpio_free(LCD_PANEL_QVGA);
-       gpio_free(LCD_PANEL_RESB);
-       gpio_free(LCD_PANEL_INI);
-       gpio_free(LCD_PANEL_UD);
-       gpio_free(LCD_PANEL_LR);
-}
-
-static int omap3evm_panel_enable(struct lcd_panel *panel)
-{
-       gpio_set_value(LCD_PANEL_ENABLE_GPIO, 0);
-       return 0;
-}
-
-static void omap3evm_panel_disable(struct lcd_panel *panel)
-{
-       gpio_set_value(LCD_PANEL_ENABLE_GPIO, 1);
-}
-
-static unsigned long omap3evm_panel_get_caps(struct lcd_panel *panel)
-{
-       return 0;
-}
-
-static int omap3evm_bklight_setlevel(struct lcd_panel *panel,
-                                               unsigned int level)
-{
-       u8 c;
-       if ((level >= 0) && (level <= 100)) {
-               c = (125 * (100 - level)) / 100 + 2;
-               twl_i2c_write_u8(TWL4030_MODULE_PWMA, c, TWL_PWMA_PWMAOFF);
-               bklight_level = level;
-       }
-       return 0;
-}
-
-static unsigned int omap3evm_bklight_getlevel(struct lcd_panel *panel)
-{
-       return bklight_level;
-}
-
-static unsigned int omap3evm_bklight_getmaxlevel(struct lcd_panel *panel)
-{
-       return 100;
-}
-
-struct lcd_panel omap3evm_panel = {
-       .name           = "omap3evm",
-       .config         = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
-                         OMAP_LCDC_INV_HSYNC,
-
-       .bpp            = 16,
-       .data_lines     = 18,
-       .x_res          = 480,
-       .y_res          = 640,
-       .hsw            = 3,            /* hsync_len (4) - 1 */
-       .hfp            = 3,            /* right_margin (4) - 1 */
-       .hbp            = 39,           /* left_margin (40) - 1 */
-       .vsw            = 1,            /* vsync_len (2) - 1 */
-       .vfp            = 2,            /* lower_margin */
-       .vbp            = 7,            /* upper_margin (8) - 1 */
-
-       .pixel_clock    = 26000,
-
-       .init           = omap3evm_panel_init,
-       .cleanup        = omap3evm_panel_cleanup,
-       .enable         = omap3evm_panel_enable,
-       .disable        = omap3evm_panel_disable,
-       .get_caps       = omap3evm_panel_get_caps,
-       .set_bklight_level      = omap3evm_bklight_setlevel,
-       .get_bklight_level      = omap3evm_bklight_getlevel,
-       .get_bklight_max        = omap3evm_bklight_getmaxlevel,
-};
-
-static int omap3evm_panel_probe(struct platform_device *pdev)
-{
-       omapfb_register_panel(&omap3evm_panel);
-       return 0;
-}
-
-static int omap3evm_panel_remove(struct platform_device *pdev)
-{
-       return 0;
-}
-
-static int omap3evm_panel_suspend(struct platform_device *pdev,
-                                  pm_message_t mesg)
-{
-       return 0;
-}
-
-static int omap3evm_panel_resume(struct platform_device *pdev)
-{
-       return 0;
-}
-
-struct platform_driver omap3evm_panel_driver = {
-       .probe          = omap3evm_panel_probe,
-       .remove         = omap3evm_panel_remove,
-       .suspend        = omap3evm_panel_suspend,
-       .resume         = omap3evm_panel_resume,
-       .driver         = {
-               .name   = "omap3evm_lcd",
-               .owner  = THIS_MODULE,
-       },
-};
-
-static int __init omap3evm_panel_drv_init(void)
-{
-       return platform_driver_register(&omap3evm_panel_driver);
-}
-
-static void __exit omap3evm_panel_drv_exit(void)
-{
-       platform_driver_unregister(&omap3evm_panel_driver);
-}
-
-module_init(omap3evm_panel_drv_init);
-module_exit(omap3evm_panel_drv_exit);
diff --git a/drivers/video/omap/lcd_overo.c b/drivers/video/omap/lcd_overo.c
deleted file mode 100644 (file)
index b8fd5b2..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * LCD panel support for the Gumstix Overo
- *
- * Author: Steve Sakoman <steve@sakoman.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- *
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/i2c/twl.h>
-
-#include <asm/gpio.h>
-#include <plat/mux.h>
-#include <asm/mach-types.h>
-
-#include "omapfb.h"
-
-#define LCD_ENABLE       144
-
-static int overo_panel_init(struct lcd_panel *panel,
-                               struct omapfb_device *fbdev)
-{
-       if ((gpio_request(LCD_ENABLE, "LCD_ENABLE") == 0) &&
-           (gpio_direction_output(LCD_ENABLE, 1) == 0))
-               gpio_export(LCD_ENABLE, 0);
-       else
-               printk(KERN_ERR "could not obtain gpio for LCD_ENABLE\n");
-
-       return 0;
-}
-
-static void overo_panel_cleanup(struct lcd_panel *panel)
-{
-       gpio_free(LCD_ENABLE);
-}
-
-static int overo_panel_enable(struct lcd_panel *panel)
-{
-       gpio_set_value(LCD_ENABLE, 1);
-       return 0;
-}
-
-static void overo_panel_disable(struct lcd_panel *panel)
-{
-       gpio_set_value(LCD_ENABLE, 0);
-}
-
-static unsigned long overo_panel_get_caps(struct lcd_panel *panel)
-{
-       return 0;
-}
-
-struct lcd_panel overo_panel = {
-       .name           = "overo",
-       .config         = OMAP_LCDC_PANEL_TFT,
-       .bpp            = 16,
-       .data_lines     = 24,
-
-#if defined CONFIG_FB_OMAP_031M3R
-
-       /* 640 x 480 @ 60 Hz  Reduced blanking VESA CVT 0.31M3-R */
-       .x_res          = 640,
-       .y_res          = 480,
-       .hfp            = 48,
-       .hsw            = 32,
-       .hbp            = 80,
-       .vfp            = 3,
-       .vsw            = 4,
-       .vbp            = 7,
-       .pixel_clock    = 23500,
-
-#elif defined CONFIG_FB_OMAP_048M3R
-
-       /* 800 x 600 @ 60 Hz  Reduced blanking VESA CVT 0.48M3-R */
-       .x_res          = 800,
-       .y_res          = 600,
-       .hfp            = 48,
-       .hsw            = 32,
-       .hbp            = 80,
-       .vfp            = 3,
-       .vsw            = 4,
-       .vbp            = 11,
-       .pixel_clock    = 35500,
-
-#elif defined CONFIG_FB_OMAP_079M3R
-
-       /* 1024 x 768 @ 60 Hz  Reduced blanking VESA CVT 0.79M3-R */
-       .x_res          = 1024,
-       .y_res          = 768,
-       .hfp            = 48,
-       .hsw            = 32,
-       .hbp            = 80,
-       .vfp            = 3,
-       .vsw            = 4,
-       .vbp            = 15,
-       .pixel_clock    = 56000,
-
-#elif defined CONFIG_FB_OMAP_092M9R
-
-       /* 1280 x 720 @ 60 Hz  Reduced blanking VESA CVT 0.92M9-R */
-       .x_res          = 1280,
-       .y_res          = 720,
-       .hfp            = 48,
-       .hsw            = 32,
-       .hbp            = 80,
-       .vfp            = 3,
-       .vsw            = 5,
-       .vbp            = 13,
-       .pixel_clock    = 64000,
-
-#else
-
-       /* use 640 x 480 if no config option */
-       /* 640 x 480 @ 60 Hz  Reduced blanking VESA CVT 0.31M3-R */
-       .x_res          = 640,
-       .y_res          = 480,
-       .hfp            = 48,
-       .hsw            = 32,
-       .hbp            = 80,
-       .vfp            = 3,
-       .vsw            = 4,
-       .vbp            = 7,
-       .pixel_clock    = 23500,
-
-#endif
-
-       .init           = overo_panel_init,
-       .cleanup        = overo_panel_cleanup,
-       .enable         = overo_panel_enable,
-       .disable        = overo_panel_disable,
-       .get_caps       = overo_panel_get_caps,
-};
-
-static int overo_panel_probe(struct platform_device *pdev)
-{
-       omapfb_register_panel(&overo_panel);
-       return 0;
-}
-
-static int overo_panel_remove(struct platform_device *pdev)
-{
-       /* omapfb does not have unregister_panel */
-       return 0;
-}
-
-static struct platform_driver overo_panel_driver = {
-       .probe          = overo_panel_probe,
-       .remove         = overo_panel_remove,
-       .driver         = {
-               .name   = "overo_lcd",
-               .owner  = THIS_MODULE,
-       },
-};
-
-static int __init overo_panel_drv_init(void)
-{
-       return platform_driver_register(&overo_panel_driver);
-}
-
-static void __exit overo_panel_drv_exit(void)
-{
-       platform_driver_unregister(&overo_panel_driver);
-}
-
-module_init(overo_panel_drv_init);
-module_exit(overo_panel_drv_exit);
index 609a280..8d8e1fe 100644 (file)
@@ -10,6 +10,13 @@ config PANEL_GENERIC_DPI
          Supports LCD Panel used in TI SDP3430 and EVM boards,
          OMAP3517 EVM boards and CM-T35.
 
+config PANEL_DVI
+       tristate "DVI output"
+       depends on OMAP2_DSS_DPI
+       help
+         Driver for external monitors, connected via DVI. The driver uses i2c
+         to read EDID information from the monitor.
+
 config PANEL_LGPHILIPS_LB035Q02
        tristate "LG.Philips LB035Q02 LCD Panel"
        depends on OMAP2_DSS_DPI && SPI
@@ -19,20 +26,30 @@ config PANEL_LGPHILIPS_LB035Q02
 config PANEL_SHARP_LS037V7DW01
         tristate "Sharp LS037V7DW01 LCD Panel"
         depends on OMAP2_DSS_DPI
-        select BACKLIGHT_CLASS_DEVICE
+        depends on BACKLIGHT_CLASS_DEVICE
         help
           LCD Panel used in TI's SDP3430 and EVM boards
 
 config PANEL_NEC_NL8048HL11_01B
        tristate "NEC NL8048HL11-01B Panel"
        depends on OMAP2_DSS_DPI
+       depends on SPI
+       depends on BACKLIGHT_CLASS_DEVICE
        help
                This NEC NL8048HL11-01B panel is TFT LCD
                used in the Zoom2/3/3630 sdp boards.
 
+config PANEL_PICODLP
+       tristate "TI PICO DLP mini-projector"
+       depends on OMAP2_DSS && I2C
+       help
+               A mini-projector used in TI's SDP4430 and EVM boards
+               For more info please visit http://www.dlp.com/projector/
+
 config PANEL_TAAL
         tristate "Taal DSI Panel"
         depends on OMAP2_DSS_DSI
+        depends on BACKLIGHT_CLASS_DEVICE
         help
           Taal DSI command mode panel from TPO.
 
@@ -45,7 +62,14 @@ config PANEL_TPO_TD043MTEA1
 config PANEL_ACX565AKM
        tristate "ACX565AKM Panel"
        depends on OMAP2_DSS_SDI && SPI
-       select BACKLIGHT_CLASS_DEVICE
+       depends on BACKLIGHT_CLASS_DEVICE
        help
          This is the LCD panel used on Nokia N900
+
+config PANEL_N8X0
+       tristate "N8X0 Panel"
+       depends on OMAP2_DSS_RFBI && SPI
+       depends on BACKLIGHT_CLASS_DEVICE
+       help
+         This is the LCD panel used on Nokia N8x0
 endmenu
index 0f601ab..fbfafc6 100644 (file)
@@ -1,8 +1,11 @@
 obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o
+obj-$(CONFIG_PANEL_DVI) += panel-dvi.o
 obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o
 obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
 obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o
 
 obj-$(CONFIG_PANEL_TAAL) += panel-taal.o
+obj-$(CONFIG_PANEL_PICODLP) +=  panel-picodlp.o
 obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
 obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o
+obj-$(CONFIG_PANEL_N8X0) += panel-n8x0.o
diff --git a/drivers/video/omap2/displays/panel-dvi.c b/drivers/video/omap2/displays/panel-dvi.c
new file mode 100644 (file)
index 0000000..03eb14a
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * DVI output support
+ *
+ * Copyright (C) 2011 Texas Instruments Inc
+ * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <video/omapdss.h>
+#include <linux/i2c.h>
+#include <drm/drm_edid.h>
+
+#include <video/omap-panel-dvi.h>
+
+static const struct omap_video_timings panel_dvi_default_timings = {
+       .x_res          = 640,
+       .y_res          = 480,
+
+       .pixel_clock    = 23500,
+
+       .hfp            = 48,
+       .hsw            = 32,
+       .hbp            = 80,
+
+       .vfp            = 3,
+       .vsw            = 4,
+       .vbp            = 7,
+};
+
+struct panel_drv_data {
+       struct omap_dss_device *dssdev;
+
+       struct mutex lock;
+};
+
+static inline struct panel_dvi_platform_data
+*get_pdata(const struct omap_dss_device *dssdev)
+{
+       return dssdev->data;
+}
+
+static int panel_dvi_power_on(struct omap_dss_device *dssdev)
+{
+       struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
+       int r;
+
+       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+               return 0;
+
+       r = omapdss_dpi_display_enable(dssdev);
+       if (r)
+               goto err0;
+
+       if (pdata->platform_enable) {
+               r = pdata->platform_enable(dssdev);
+               if (r)
+                       goto err1;
+       }
+
+       return 0;
+err1:
+       omapdss_dpi_display_disable(dssdev);
+err0:
+       return r;
+}
+
+static void panel_dvi_power_off(struct omap_dss_device *dssdev)
+{
+       struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
+
+       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+               return;
+
+       if (pdata->platform_disable)
+               pdata->platform_disable(dssdev);
+
+       omapdss_dpi_display_disable(dssdev);
+}
+
+static int panel_dvi_probe(struct omap_dss_device *dssdev)
+{
+       struct panel_drv_data *ddata;
+
+       ddata = kzalloc(sizeof(*ddata), GFP_KERNEL);
+       if (!ddata)
+               return -ENOMEM;
+
+       dssdev->panel.timings = panel_dvi_default_timings;
+       dssdev->panel.config = OMAP_DSS_LCD_TFT;
+
+       ddata->dssdev = dssdev;
+       mutex_init(&ddata->lock);
+
+       dev_set_drvdata(&dssdev->dev, ddata);
+
+       return 0;
+}
+
+static void __exit panel_dvi_remove(struct omap_dss_device *dssdev)
+{
+       struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
+
+       mutex_lock(&ddata->lock);
+
+       dev_set_drvdata(&dssdev->dev, NULL);
+
+       mutex_unlock(&ddata->lock);
+
+       kfree(ddata);
+}
+
+static int panel_dvi_enable(struct omap_dss_device *dssdev)
+{
+       struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
+       int r;
+
+       mutex_lock(&ddata->lock);
+
+       r = panel_dvi_power_on(dssdev);
+       if (r == 0)
+               dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+       mutex_unlock(&ddata->lock);
+
+       return r;
+}
+
+static void panel_dvi_disable(struct omap_dss_device *dssdev)
+{
+       struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
+
+       mutex_lock(&ddata->lock);
+
+       panel_dvi_power_off(dssdev);
+
+       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+
+       mutex_unlock(&ddata->lock);
+}
+
+static int panel_dvi_suspend(struct omap_dss_device *dssdev)
+{
+       struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
+
+       mutex_lock(&ddata->lock);
+
+       panel_dvi_power_off(dssdev);
+
+       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+
+       mutex_unlock(&ddata->lock);
+
+       return 0;
+}
+
+static int panel_dvi_resume(struct omap_dss_device *dssdev)
+{
+       struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
+       int r;
+
+       mutex_lock(&ddata->lock);
+
+       r = panel_dvi_power_on(dssdev);
+       if (r == 0)
+               dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+       mutex_unlock(&ddata->lock);
+
+       return r;
+}
+
+static void panel_dvi_set_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings)
+{
+       struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
+
+       mutex_lock(&ddata->lock);
+       dpi_set_timings(dssdev, timings);
+       mutex_unlock(&ddata->lock);
+}
+
+static void panel_dvi_get_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings)
+{
+       struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
+
+       mutex_lock(&ddata->lock);
+       *timings = dssdev->panel.timings;
+       mutex_unlock(&ddata->lock);
+}
+
+static int panel_dvi_check_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings)
+{
+       struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
+       int r;
+
+       mutex_lock(&ddata->lock);
+       r = dpi_check_timings(dssdev, timings);
+       mutex_unlock(&ddata->lock);
+
+       return r;
+}
+
+
+static int panel_dvi_ddc_read(struct i2c_adapter *adapter,
+               unsigned char *buf, u16 count, u8 offset)
+{
+       int r, retries;
+
+       for (retries = 3; retries > 0; retries--) {
+               struct i2c_msg msgs[] = {
+                       {
+                               .addr   = DDC_ADDR,
+                               .flags  = 0,
+                               .len    = 1,
+                               .buf    = &offset,
+                       }, {
+                               .addr   = DDC_ADDR,
+                               .flags  = I2C_M_RD,
+                               .len    = count,
+                               .buf    = buf,
+                       }
+               };
+
+               r = i2c_transfer(adapter, msgs, 2);
+               if (r == 2)
+                       return 0;
+
+               if (r != -EAGAIN)
+                       break;
+       }
+
+       return r < 0 ? r : -EIO;
+}
+
+static int panel_dvi_read_edid(struct omap_dss_device *dssdev,
+               u8 *edid, int len)
+{
+       struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
+       struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
+       struct i2c_adapter *adapter;
+       int r, l, bytes_read;
+
+       mutex_lock(&ddata->lock);
+
+       if (pdata->i2c_bus_num == 0) {
+               r = -ENODEV;
+               goto err;
+       }
+
+       adapter = i2c_get_adapter(pdata->i2c_bus_num);
+       if (!adapter) {
+               dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n",
+                               pdata->i2c_bus_num);
+               r = -EINVAL;
+               goto err;
+       }
+
+       l = min(EDID_LENGTH, len);
+       r = panel_dvi_ddc_read(adapter, edid, l, 0);
+       if (r)
+               goto err;
+
+       bytes_read = l;
+
+       /* if there are extensions, read second block */
+       if (len > EDID_LENGTH && edid[0x7e] > 0) {
+               l = min(EDID_LENGTH, len - EDID_LENGTH);
+
+               r = panel_dvi_ddc_read(adapter, edid + EDID_LENGTH,
+                               l, EDID_LENGTH);
+               if (r)
+                       goto err;
+
+               bytes_read += l;
+       }
+
+       mutex_unlock(&ddata->lock);
+
+       return bytes_read;
+
+err:
+       mutex_unlock(&ddata->lock);
+       return r;
+}
+
+static bool panel_dvi_detect(struct omap_dss_device *dssdev)
+{
+       struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
+       struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
+       struct i2c_adapter *adapter;
+       unsigned char out;
+       int r;
+
+       mutex_lock(&ddata->lock);
+
+       if (pdata->i2c_bus_num == 0)
+               goto out;
+
+       adapter = i2c_get_adapter(pdata->i2c_bus_num);
+       if (!adapter)
+               goto out;
+
+       r = panel_dvi_ddc_read(adapter, &out, 1, 0);
+
+       mutex_unlock(&ddata->lock);
+
+       return r == 0;
+
+out:
+       mutex_unlock(&ddata->lock);
+       return true;
+}
+
+static struct omap_dss_driver panel_dvi_driver = {
+       .probe          = panel_dvi_probe,
+       .remove         = __exit_p(panel_dvi_remove),
+
+       .enable         = panel_dvi_enable,
+       .disable        = panel_dvi_disable,
+       .suspend        = panel_dvi_suspend,
+       .resume         = panel_dvi_resume,
+
+       .set_timings    = panel_dvi_set_timings,
+       .get_timings    = panel_dvi_get_timings,
+       .check_timings  = panel_dvi_check_timings,
+
+       .read_edid      = panel_dvi_read_edid,
+       .detect         = panel_dvi_detect,
+
+       .driver         = {
+               .name   = "dvi",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init panel_dvi_init(void)
+{
+       return omap_dss_register_driver(&panel_dvi_driver);
+}
+
+static void __exit panel_dvi_exit(void)
+{
+       omap_dss_unregister_driver(&panel_dvi_driver);
+}
+
+module_init(panel_dvi_init);
+module_exit(panel_dvi_exit);
+MODULE_LICENSE("GPL");
index 9c90f75..519c47d 100644 (file)
@@ -58,30 +58,6 @@ struct panel_config {
 
 /* Panel configurations */
 static struct panel_config generic_dpi_panels[] = {
-       /* Generic Panel */
-       {
-               {
-                       .x_res          = 640,
-                       .y_res          = 480,
-
-                       .pixel_clock    = 23500,
-
-                       .hfp            = 48,
-                       .hsw            = 32,
-                       .hbp            = 80,
-
-                       .vfp            = 3,
-                       .vsw            = 4,
-                       .vbp            = 7,
-               },
-               .acbi                   = 0x0,
-               .acb                    = 0x0,
-               .config                 = OMAP_DSS_LCD_TFT,
-               .power_on_delay         = 0,
-               .power_off_delay        = 0,
-               .name                   = "generic",
-       },
-
        /* Sharp LQ043T1DG01 */
        {
                {
@@ -232,6 +208,95 @@ static struct panel_config generic_dpi_panels[] = {
                .power_off_delay        = 0,
                .name                   = "powertip_ph480272t",
        },
+
+       /* Innolux AT070TN83 */
+       {
+               {
+                       .x_res          = 800,
+                       .y_res          = 480,
+
+                       .pixel_clock    = 40000,
+
+                       .hsw            = 48,
+                       .hfp            = 1,
+                       .hbp            = 1,
+
+                       .vsw            = 3,
+                       .vfp            = 12,
+                       .vbp            = 25,
+               },
+               .acbi                   = 0x0,
+               .acb                    = 0x28,
+               .config                 = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+                                         OMAP_DSS_LCD_IHS,
+               .power_on_delay         = 0,
+               .power_off_delay        = 0,
+               .name                   = "innolux_at070tn83",
+       },
+
+       /* NEC NL2432DR22-11B */
+       {
+               {
+                       .x_res          = 240,
+                       .y_res          = 320,
+
+                       .pixel_clock    = 5400,
+
+                       .hsw            = 3,
+                       .hfp            = 3,
+                       .hbp            = 39,
+
+                       .vsw            = 1,
+                       .vfp            = 2,
+                       .vbp            = 7,
+               },
+               .config                 = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+                                               OMAP_DSS_LCD_IHS,
+               .name                   = "nec_nl2432dr22-11b",
+       },
+
+       /* Unknown panel used in OMAP H4 */
+       {
+               {
+                       .x_res          = 240,
+                       .y_res          = 320,
+
+                       .pixel_clock    = 6250,
+
+                       .hsw            = 15,
+                       .hfp            = 15,
+                       .hbp            = 60,
+
+                       .vsw            = 1,
+                       .vfp            = 1,
+                       .vbp            = 1,
+               },
+               .config                 = OMAP_DSS_LCD_TFT,
+
+               .name                   = "h4",
+       },
+
+       /* Unknown panel used in Samsung OMAP2 Apollon */
+       {
+               {
+                       .x_res          = 480,
+                       .y_res          = 272,
+
+                       .pixel_clock    = 6250,
+
+                       .hsw            = 41,
+                       .hfp            = 2,
+                       .hbp            = 2,
+
+                       .vsw            = 10,
+                       .vfp            = 2,
+                       .vbp            = 2,
+               },
+               .config                 = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+                                               OMAP_DSS_LCD_IHS,
+
+               .name                   = "apollon",
+       },
 };
 
 struct panel_drv_data {
diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c
new file mode 100644 (file)
index 0000000..150e8ba
--- /dev/null
@@ -0,0 +1,747 @@
+/* #define DEBUG */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/backlight.h>
+#include <linux/fb.h>
+
+#include <video/omapdss.h>
+#include <video/omap-panel-n8x0.h>
+
+#define BLIZZARD_REV_CODE                      0x00
+#define BLIZZARD_CONFIG                        0x02
+#define BLIZZARD_PLL_DIV                       0x04
+#define BLIZZARD_PLL_LOCK_RANGE                0x06
+#define BLIZZARD_PLL_CLOCK_SYNTH_0             0x08
+#define BLIZZARD_PLL_CLOCK_SYNTH_1             0x0a
+#define BLIZZARD_PLL_MODE                      0x0c
+#define BLIZZARD_CLK_SRC                       0x0e
+#define BLIZZARD_MEM_BANK0_ACTIVATE            0x10
+#define BLIZZARD_MEM_BANK0_STATUS              0x14
+#define BLIZZARD_PANEL_CONFIGURATION           0x28
+#define BLIZZARD_HDISP                         0x2a
+#define BLIZZARD_HNDP                          0x2c
+#define BLIZZARD_VDISP0                        0x2e
+#define BLIZZARD_VDISP1                        0x30
+#define BLIZZARD_VNDP                          0x32
+#define BLIZZARD_HSW                           0x34
+#define BLIZZARD_VSW                           0x38
+#define BLIZZARD_DISPLAY_MODE                  0x68
+#define BLIZZARD_INPUT_WIN_X_START_0           0x6c
+#define BLIZZARD_DATA_SOURCE_SELECT            0x8e
+#define BLIZZARD_DISP_MEM_DATA_PORT            0x90
+#define BLIZZARD_DISP_MEM_READ_ADDR0           0x92
+#define BLIZZARD_POWER_SAVE                    0xE6
+#define BLIZZARD_NDISP_CTRL_STATUS             0xE8
+
+/* Data source select */
+/* For S1D13745 */
+#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND      0x00
+#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE     0x01
+#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE      0x04
+#define BLIZZARD_SRC_DISABLE_OVERLAY           0x05
+/* For S1D13744 */
+#define BLIZZARD_SRC_WRITE_LCD                 0x00
+#define BLIZZARD_SRC_BLT_LCD                   0x06
+
+#define BLIZZARD_COLOR_RGB565                  0x01
+#define BLIZZARD_COLOR_YUV420                  0x09
+
+#define BLIZZARD_VERSION_S1D13745              0x01    /* Hailstorm */
+#define BLIZZARD_VERSION_S1D13744              0x02    /* Blizzard */
+
+#define MIPID_CMD_READ_DISP_ID         0x04
+#define MIPID_CMD_READ_RED             0x06
+#define MIPID_CMD_READ_GREEN           0x07
+#define MIPID_CMD_READ_BLUE            0x08
+#define MIPID_CMD_READ_DISP_STATUS     0x09
+#define MIPID_CMD_RDDSDR               0x0F
+#define MIPID_CMD_SLEEP_IN             0x10
+#define MIPID_CMD_SLEEP_OUT            0x11
+#define MIPID_CMD_DISP_OFF             0x28
+#define MIPID_CMD_DISP_ON              0x29
+
+static struct panel_drv_data {
+       struct mutex lock;
+
+       struct omap_dss_device *dssdev;
+       struct spi_device *spidev;
+       struct backlight_device *bldev;
+
+       int blizzard_ver;
+} s_drv_data;
+
+
+static inline
+struct panel_n8x0_data *get_board_data(const struct omap_dss_device *dssdev)
+{
+       return dssdev->data;
+}
+
+static inline
+struct panel_drv_data *get_drv_data(const struct omap_dss_device *dssdev)
+{
+       return &s_drv_data;
+}
+
+
+static inline void blizzard_cmd(u8 cmd)
+{
+       omap_rfbi_write_command(&cmd, 1);
+}
+
+static inline void blizzard_write(u8 cmd, const u8 *buf, int len)
+{
+       omap_rfbi_write_command(&cmd, 1);
+       omap_rfbi_write_data(buf, len);
+}
+
+static inline void blizzard_read(u8 cmd, u8 *buf, int len)
+{
+       omap_rfbi_write_command(&cmd, 1);
+       omap_rfbi_read_data(buf, len);
+}
+
+static u8 blizzard_read_reg(u8 cmd)
+{
+       u8 data;
+       blizzard_read(cmd, &data, 1);
+       return data;
+}
+
+static void blizzard_ctrl_setup_update(struct omap_dss_device *dssdev,
+               int x, int y, int w, int h)
+{
+       struct panel_drv_data *ddata = get_drv_data(dssdev);
+       u8 tmp[18];
+       int x_end, y_end;
+
+       x_end = x + w - 1;
+       y_end = y + h - 1;
+
+       tmp[0] = x;
+       tmp[1] = x >> 8;
+       tmp[2] = y;
+       tmp[3] = y >> 8;
+       tmp[4] = x_end;
+       tmp[5] = x_end >> 8;
+       tmp[6] = y_end;
+       tmp[7] = y_end >> 8;
+
+       /* scaling? */
+       tmp[8] = x;
+       tmp[9] = x >> 8;
+       tmp[10] = y;
+       tmp[11] = y >> 8;
+       tmp[12] = x_end;
+       tmp[13] = x_end >> 8;
+       tmp[14] = y_end;
+       tmp[15] = y_end >> 8;
+
+       tmp[16] = BLIZZARD_COLOR_RGB565;
+
+       if (ddata->blizzard_ver == BLIZZARD_VERSION_S1D13745)
+               tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND;
+       else
+               tmp[17] = ddata->blizzard_ver == BLIZZARD_VERSION_S1D13744 ?
+                       BLIZZARD_SRC_WRITE_LCD :
+                       BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
+
+       omap_rfbi_configure(dssdev, 16, 8);
+
+       blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18);
+
+       omap_rfbi_configure(dssdev, 16, 16);
+}
+
+static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf,
+               int wlen, u8 *rbuf, int rlen)
+{
+       struct spi_message      m;
+       struct spi_transfer     *x, xfer[4];
+       u16                     w;
+       int                     r;
+
+       spi_message_init(&m);
+
+       memset(xfer, 0, sizeof(xfer));
+       x = &xfer[0];
+
+       cmd &=  0xff;
+       x->tx_buf               = &cmd;
+       x->bits_per_word        = 9;
+       x->len                  = 2;
+       spi_message_add_tail(x, &m);
+
+       if (wlen) {
+               x++;
+               x->tx_buf               = wbuf;
+               x->len                  = wlen;
+               x->bits_per_word        = 9;
+               spi_message_add_tail(x, &m);
+       }
+
+       if (rlen) {
+               x++;
+               x->rx_buf       = &w;
+               x->len          = 1;
+               spi_message_add_tail(x, &m);
+
+               if (rlen > 1) {
+                       /* Arrange for the extra clock before the first
+                        * data bit.
+                        */
+                       x->bits_per_word = 9;
+                       x->len           = 2;
+
+                       x++;
+                       x->rx_buf        = &rbuf[1];
+                       x->len           = rlen - 1;
+                       spi_message_add_tail(x, &m);
+               }
+       }
+
+       r = spi_sync(spi, &m);
+       if (r < 0)
+               dev_dbg(&spi->dev, "spi_sync %d\n", r);
+
+       if (rlen)
+               rbuf[0] = w & 0xff;
+}
+
+static inline void mipid_cmd(struct spi_device *spi, int cmd)
+{
+       mipid_transfer(spi, cmd, NULL, 0, NULL, 0);
+}
+
+static inline void mipid_write(struct spi_device *spi,
+               int reg, const u8 *buf, int len)
+{
+       mipid_transfer(spi, reg, buf, len, NULL, 0);
+}
+
+static inline void mipid_read(struct spi_device *spi,
+               int reg, u8 *buf, int len)
+{
+       mipid_transfer(spi, reg, NULL, 0, buf, len);
+}
+
+static void set_data_lines(struct spi_device *spi, int data_lines)
+{
+       u16 par;
+
+       switch (data_lines) {
+       case 16:
+               par = 0x150;
+               break;
+       case 18:
+               par = 0x160;
+               break;
+       case 24:
+               par = 0x170;
+               break;
+       }
+
+       mipid_write(spi, 0x3a, (u8 *)&par, 2);
+}
+
+static void send_init_string(struct spi_device *spi)
+{
+       u16 initpar[] = { 0x0102, 0x0100, 0x0100 };
+       mipid_write(spi, 0xc2, (u8 *)initpar, sizeof(initpar));
+}
+
+static void send_display_on(struct spi_device *spi)
+{
+       mipid_cmd(spi, MIPID_CMD_DISP_ON);
+}
+
+static void send_display_off(struct spi_device *spi)
+{
+       mipid_cmd(spi, MIPID_CMD_DISP_OFF);
+}
+
+static void send_sleep_out(struct spi_device *spi)
+{
+       mipid_cmd(spi, MIPID_CMD_SLEEP_OUT);
+       msleep(120);
+}
+
+static void send_sleep_in(struct spi_device *spi)
+{
+       mipid_cmd(spi, MIPID_CMD_SLEEP_IN);
+       msleep(50);
+}
+
+static int n8x0_panel_power_on(struct omap_dss_device *dssdev)
+{
+       int r;
+       struct panel_n8x0_data *bdata = get_board_data(dssdev);
+       struct panel_drv_data *ddata = get_drv_data(dssdev);
+       struct spi_device *spi = ddata->spidev;
+       u8 rev, conf;
+       u8 display_id[3];
+       const char *panel_name;
+
+       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+               return 0;
+
+       gpio_direction_output(bdata->ctrl_pwrdown, 1);
+
+       if (bdata->platform_enable) {
+               r = bdata->platform_enable(dssdev);
+               if (r)
+                       goto err_plat_en;
+       }
+
+       r = omapdss_rfbi_display_enable(dssdev);
+       if (r)
+               goto err_rfbi_en;
+
+       rev = blizzard_read_reg(BLIZZARD_REV_CODE);
+       conf = blizzard_read_reg(BLIZZARD_CONFIG);
+
+       switch (rev & 0xfc) {
+       case 0x9c:
+               ddata->blizzard_ver = BLIZZARD_VERSION_S1D13744;
+               dev_info(&dssdev->dev, "s1d13744 LCD controller rev %d "
+                       "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
+               break;
+       case 0xa4:
+               ddata->blizzard_ver = BLIZZARD_VERSION_S1D13745;
+               dev_info(&dssdev->dev, "s1d13745 LCD controller rev %d "
+                       "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
+               break;
+       default:
+               dev_err(&dssdev->dev, "invalid s1d1374x revision %02x\n", rev);
+               r = -ENODEV;
+               goto err_inv_chip;
+       }
+
+       /* panel */
+
+       gpio_direction_output(bdata->panel_reset, 1);
+
+       mipid_read(spi, MIPID_CMD_READ_DISP_ID, display_id, 3);
+       dev_dbg(&spi->dev, "MIPI display ID: %02x%02x%02x\n",
+                       display_id[0], display_id[1], display_id[2]);
+
+       switch (display_id[0]) {
+       case 0x45:
+               panel_name = "lph8923";
+               break;
+       case 0x83:
+               panel_name = "ls041y3";
+               break;
+       default:
+               dev_err(&dssdev->dev, "invalid display ID 0x%x\n",
+                               display_id[0]);
+               r = -ENODEV;
+               goto err_inv_panel;
+       }
+
+       dev_info(&dssdev->dev, "%s rev %02x LCD detected\n",
+                       panel_name, display_id[1]);
+
+       send_sleep_out(spi);
+       send_init_string(spi);
+       set_data_lines(spi, 24);
+       send_display_on(spi);
+
+       return 0;
+
+err_inv_panel:
+       /*
+        * HACK: we should turn off the panel here, but there is some problem
+        * with the initialization sequence, and we fail to init the panel if we
+        * have turned it off
+        */
+       /* gpio_direction_output(bdata->panel_reset, 0); */
+err_inv_chip:
+       omapdss_rfbi_display_disable(dssdev);
+err_rfbi_en:
+       if (bdata->platform_disable)
+               bdata->platform_disable(dssdev);
+err_plat_en:
+       gpio_direction_output(bdata->ctrl_pwrdown, 0);
+       return r;
+}
+
+static void n8x0_panel_power_off(struct omap_dss_device *dssdev)
+{
+       struct panel_n8x0_data *bdata = get_board_data(dssdev);
+       struct panel_drv_data *ddata = get_drv_data(dssdev);
+       struct spi_device *spi = ddata->spidev;
+
+       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+               return;
+
+       send_display_off(spi);
+       send_sleep_in(spi);
+
+       if (bdata->platform_disable)
+               bdata->platform_disable(dssdev);
+
+       /*
+        * HACK: we should turn off the panel here, but there is some problem
+        * with the initialization sequence, and we fail to init the panel if we
+        * have turned it off
+        */
+       /* gpio_direction_output(bdata->panel_reset, 0); */
+       gpio_direction_output(bdata->ctrl_pwrdown, 0);
+       omapdss_rfbi_display_disable(dssdev);
+}
+
+static const struct rfbi_timings n8x0_panel_timings = {
+       .cs_on_time     = 0,
+
+       .we_on_time     = 9000,
+       .we_off_time    = 18000,
+       .we_cycle_time  = 36000,
+
+       .re_on_time     = 9000,
+       .re_off_time    = 27000,
+       .re_cycle_time  = 36000,
+
+       .access_time    = 27000,
+       .cs_off_time    = 36000,
+
+       .cs_pulse_width = 0,
+};
+
+static int n8x0_bl_update_status(struct backlight_device *dev)
+{
+       struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
+       struct panel_n8x0_data *bdata = get_board_data(dssdev);
+       struct panel_drv_data *ddata = get_drv_data(dssdev);
+       int r;
+       int level;
+
+       mutex_lock(&ddata->lock);
+
+       if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
+                       dev->props.power == FB_BLANK_UNBLANK)
+               level = dev->props.brightness;
+       else
+               level = 0;
+
+       dev_dbg(&dssdev->dev, "update brightness to %d\n", level);
+
+       if (!bdata->set_backlight)
+               r = -EINVAL;
+       else
+               r = bdata->set_backlight(dssdev, level);
+
+       mutex_unlock(&ddata->lock);
+
+       return r;
+}
+
+static int n8x0_bl_get_intensity(struct backlight_device *dev)
+{
+       if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
+                       dev->props.power == FB_BLANK_UNBLANK)
+               return dev->props.brightness;
+
+       return 0;
+}
+
+static const struct backlight_ops n8x0_bl_ops = {
+       .get_brightness = n8x0_bl_get_intensity,
+       .update_status  = n8x0_bl_update_status,
+};
+
+static int n8x0_panel_probe(struct omap_dss_device *dssdev)
+{
+       struct panel_n8x0_data *bdata = get_board_data(dssdev);
+       struct panel_drv_data *ddata;
+       struct backlight_device *bldev;
+       struct backlight_properties props;
+       int r;
+
+       dev_dbg(&dssdev->dev, "probe\n");
+
+       if (!bdata)
+               return -EINVAL;
+
+       s_drv_data.dssdev = dssdev;
+
+       ddata = &s_drv_data;
+
+       mutex_init(&ddata->lock);
+
+       dssdev->panel.config = OMAP_DSS_LCD_TFT;
+       dssdev->panel.timings.x_res = 800;
+       dssdev->panel.timings.y_res = 480;
+       dssdev->ctrl.pixel_size = 16;
+       dssdev->ctrl.rfbi_timings = n8x0_panel_timings;
+
+       memset(&props, 0, sizeof(props));
+       props.max_brightness = 127;
+       props.type = BACKLIGHT_PLATFORM;
+       bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev,
+                       dssdev, &n8x0_bl_ops, &props);
+       if (IS_ERR(bldev)) {
+               r = PTR_ERR(bldev);
+               dev_err(&dssdev->dev, "register backlight failed\n");
+               return r;
+       }
+
+       ddata->bldev = bldev;
+
+       bldev->props.fb_blank = FB_BLANK_UNBLANK;
+       bldev->props.power = FB_BLANK_UNBLANK;
+       bldev->props.brightness = 127;
+
+       n8x0_bl_update_status(bldev);
+
+       return 0;
+}
+
+static void n8x0_panel_remove(struct omap_dss_device *dssdev)
+{
+       struct panel_drv_data *ddata = get_drv_data(dssdev);
+       struct backlight_device *bldev;
+
+       dev_dbg(&dssdev->dev, "remove\n");
+
+       bldev = ddata->bldev;
+       bldev->props.power = FB_BLANK_POWERDOWN;
+       n8x0_bl_update_status(bldev);
+       backlight_device_unregister(bldev);
+
+       dev_set_drvdata(&dssdev->dev, NULL);
+}
+
+static int n8x0_panel_enable(struct omap_dss_device *dssdev)
+{
+       struct panel_drv_data *ddata = get_drv_data(dssdev);
+       int r;
+
+       dev_dbg(&dssdev->dev, "enable\n");
+
+       mutex_lock(&ddata->lock);
+
+       rfbi_bus_lock();
+
+       r = n8x0_panel_power_on(dssdev);
+
+       rfbi_bus_unlock();
+
+       if (r) {
+               mutex_unlock(&ddata->lock);
+               return r;
+       }
+
+       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+       mutex_unlock(&ddata->lock);
+
+       return 0;
+}
+
+static void n8x0_panel_disable(struct omap_dss_device *dssdev)
+{
+       struct panel_drv_data *ddata = get_drv_data(dssdev);
+
+       dev_dbg(&dssdev->dev, "disable\n");
+
+       mutex_lock(&ddata->lock);
+
+       rfbi_bus_lock();
+
+       n8x0_panel_power_off(dssdev);
+
+       rfbi_bus_unlock();
+
+       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+
+       mutex_unlock(&ddata->lock);
+}
+
+static int n8x0_panel_suspend(struct omap_dss_device *dssdev)
+{
+       struct panel_drv_data *ddata = get_drv_data(dssdev);
+
+       dev_dbg(&dssdev->dev, "suspend\n");
+
+       mutex_lock(&ddata->lock);
+
+       rfbi_bus_lock();
+
+       n8x0_panel_power_off(dssdev);
+
+       rfbi_bus_unlock();
+
+       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+
+       mutex_unlock(&ddata->lock);
+
+       return 0;
+}
+
+static int n8x0_panel_resume(struct omap_dss_device *dssdev)
+{
+       struct panel_drv_data *ddata = get_drv_data(dssdev);
+       int r;
+
+       dev_dbg(&dssdev->dev, "resume\n");
+
+       mutex_lock(&ddata->lock);
+
+       rfbi_bus_lock();
+
+       r = n8x0_panel_power_on(dssdev);
+
+       rfbi_bus_unlock();
+
+       if (r) {
+               mutex_unlock(&ddata->lock);
+               return r;
+       }
+
+       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+       mutex_unlock(&ddata->lock);
+
+       return 0;
+}
+
+static void n8x0_panel_get_timings(struct omap_dss_device *dssdev,
+               struct omap_video_timings *timings)
+{
+       *timings = dssdev->panel.timings;
+}
+
+static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev,
+               u16 *xres, u16 *yres)
+{
+       *xres = dssdev->panel.timings.x_res;
+       *yres = dssdev->panel.timings.y_res;
+}
+
+static void update_done(void *data)
+{
+       rfbi_bus_unlock();
+}
+
+static int n8x0_panel_update(struct omap_dss_device *dssdev,
+               u16 x, u16 y, u16 w, u16 h)
+{
+       struct panel_drv_data *ddata = get_drv_data(dssdev);
+
+       dev_dbg(&dssdev->dev, "update\n");
+
+       mutex_lock(&ddata->lock);
+       rfbi_bus_lock();
+
+       omap_rfbi_prepare_update(dssdev, &x, &y, &w, &h);
+
+       blizzard_ctrl_setup_update(dssdev, x, y, w, h);
+
+       omap_rfbi_update(dssdev, x, y, w, h, update_done, NULL);
+
+       mutex_unlock(&ddata->lock);
+
+       return 0;
+}
+
+static int n8x0_panel_sync(struct omap_dss_device *dssdev)
+{
+       struct panel_drv_data *ddata = get_drv_data(dssdev);
+
+       dev_dbg(&dssdev->dev, "sync\n");
+
+       mutex_lock(&ddata->lock);
+       rfbi_bus_lock();
+       rfbi_bus_unlock();
+       mutex_unlock(&ddata->lock);
+
+       return 0;
+}
+
+static struct omap_dss_driver n8x0_panel_driver = {
+       .probe          = n8x0_panel_probe,
+       .remove         = n8x0_panel_remove,
+
+       .enable         = n8x0_panel_enable,
+       .disable        = n8x0_panel_disable,
+       .suspend        = n8x0_panel_suspend,
+       .resume         = n8x0_panel_resume,
+
+       .update         = n8x0_panel_update,
+       .sync           = n8x0_panel_sync,
+
+       .get_resolution = n8x0_panel_get_resolution,
+       .get_recommended_bpp = omapdss_default_get_recommended_bpp,
+
+       .get_timings    = n8x0_panel_get_timings,
+
+       .driver         = {
+               .name   = "n8x0_panel",
+               .owner  = THIS_MODULE,
+       },
+};
+
+/* PANEL */
+
+static int mipid_spi_probe(struct spi_device *spi)
+{
+       dev_dbg(&spi->dev, "mipid_spi_probe\n");
+
+       spi->mode = SPI_MODE_0;
+
+       s_drv_data.spidev = spi;
+
+       return 0;
+}
+
+static int mipid_spi_remove(struct spi_device *spi)
+{
+       dev_dbg(&spi->dev, "mipid_spi_remove\n");
+       return 0;
+}
+
+static struct spi_driver mipid_spi_driver = {
+       .driver = {
+               .name   = "lcd_mipid",
+               .bus    = &spi_bus_type,
+               .owner  = THIS_MODULE,
+       },
+       .probe  = mipid_spi_probe,
+       .remove = __devexit_p(mipid_spi_remove),
+};
+
+static int __init n8x0_panel_drv_init(void)
+{
+       int r;
+
+       r = spi_register_driver(&mipid_spi_driver);
+       if (r) {
+               pr_err("n8x0_panel: spi driver registration failed\n");
+               return r;
+       }
+
+       r = omap_dss_register_driver(&n8x0_panel_driver);
+       if (r) {
+               pr_err("n8x0_panel: dss driver registration failed\n");
+               spi_unregister_driver(&mipid_spi_driver);
+               return r;
+       }
+
+       return 0;
+}
+
+static void __exit n8x0_panel_drv_exit(void)
+{
+       spi_unregister_driver(&mipid_spi_driver);
+
+       omap_dss_unregister_driver(&n8x0_panel_driver);
+}
+
+module_init(n8x0_panel_drv_init);
+module_exit(n8x0_panel_drv_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-picodlp.c b/drivers/video/omap2/displays/panel-picodlp.c
new file mode 100644 (file)
index 0000000..98ebdad
--- /dev/null
@@ -0,0 +1,594 @@
+/*
+ * picodlp panel driver
+ * picodlp_i2c_driver: i2c_client driver
+ *
+ * Copyright (C) 2009-2011 Texas Instruments
+ * Author: Mythri P K <mythripk@ti.com>
+ * Mayuresh Janorkar <mayur@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/firmware.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+
+#include <video/omapdss.h>
+#include <video/omap-panel-picodlp.h>
+
+#include "panel-picodlp.h"
+
+struct picodlp_data {
+       struct mutex lock;
+       struct i2c_client *picodlp_i2c_client;
+};
+
+static struct i2c_board_info picodlp_i2c_board_info = {
+       I2C_BOARD_INFO("picodlp_i2c_driver", 0x1b),
+};
+
+struct picodlp_i2c_data {
+       struct mutex xfer_lock;
+};
+
+static struct i2c_device_id picodlp_i2c_id[] = {
+       { "picodlp_i2c_driver", 0 },
+};
+
+struct picodlp_i2c_command {
+       u8 reg;
+       u32 value;
+};
+
+static struct omap_video_timings pico_ls_timings = {
+       .x_res          = 864,
+       .y_res          = 480,
+       .hsw            = 7,
+       .hfp            = 11,
+       .hbp            = 7,
+
+       .pixel_clock    = 19200,
+
+       .vsw            = 2,
+       .vfp            = 3,
+       .vbp            = 14,
+};
+
+static inline struct picodlp_panel_data
+               *get_panel_data(const struct omap_dss_device *dssdev)
+{
+       return (struct picodlp_panel_data *) dssdev->data;
+}
+
+static u32 picodlp_i2c_read(struct i2c_client *client, u8 reg)
+{
+       u8 read_cmd[] = {READ_REG_SELECT, reg}, data[4];
+       struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client);
+       struct i2c_msg msg[2];
+
+       mutex_lock(&picodlp_i2c_data->xfer_lock);
+
+       msg[0].addr = client->addr;
+       msg[0].flags = 0;
+       msg[0].len = 2;
+       msg[0].buf = read_cmd;
+
+       msg[1].addr = client->addr;
+       msg[1].flags = I2C_M_RD;
+       msg[1].len = 4;
+       msg[1].buf = data;
+
+       i2c_transfer(client->adapter, msg, 2);
+       mutex_unlock(&picodlp_i2c_data->xfer_lock);
+       return (data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24));
+}
+
+static int picodlp_i2c_write_block(struct i2c_client *client,
+                                       u8 *data, int len)
+{
+       struct i2c_msg msg;
+       int i, r, msg_count = 1;
+
+       struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client);
+
+       if (len < 1 || len > 32) {
+               dev_err(&client->dev,
+                       "too long syn_write_block len %d\n", len);
+               return -EIO;
+       }
+       mutex_lock(&picodlp_i2c_data->xfer_lock);
+
+       msg.addr = client->addr;
+       msg.flags = 0;
+       msg.len = len;
+       msg.buf = data;
+       r = i2c_transfer(client->adapter, &msg, msg_count);
+       mutex_unlock(&picodlp_i2c_data->xfer_lock);
+
+       /*
+        * i2c_transfer returns:
+        * number of messages sent in case of success
+        * a negative error number in case of failure
+        */
+       if (r != msg_count)
+               goto err;
+
+       /* In case of success */
+       for (i = 0; i < len; i++)
+               dev_dbg(&client->dev,
+                       "addr %x bw 0x%02x[%d]: 0x%02x\n",
+                       client->addr, data[0] + i, i, data[i]);
+
+       return 0;
+err:
+       dev_err(&client->dev, "picodlp_i2c_write error\n");
+       return r;
+}
+
+static int picodlp_i2c_write(struct i2c_client *client, u8 reg, u32 value)
+{
+       u8 data[5];
+       int i;
+
+       data[0] = reg;
+       for (i = 1; i < 5; i++)
+               data[i] = (value >> (32 - (i) * 8)) & 0xFF;
+
+       return picodlp_i2c_write_block(client, data, 5);
+}
+
+static int picodlp_i2c_write_array(struct i2c_client *client,
+                       const struct picodlp_i2c_command commands[],
+                       int count)
+{
+       int i, r = 0;
+       for (i = 0; i < count; i++) {
+               r = picodlp_i2c_write(client, commands[i].reg,
+                                               commands[i].value);
+               if (r)
+                       return r;
+       }
+       return r;
+}
+
+static int picodlp_wait_for_dma_done(struct i2c_client *client)
+{
+       u8 trial = 100;
+
+       do {
+               msleep(1);
+               if (!trial--)
+                       return -ETIMEDOUT;
+       } while (picodlp_i2c_read(client, MAIN_STATUS) & DMA_STATUS);
+
+       return 0;
+}
+
+/**
+ * picodlp_i2c_init:   i2c_initialization routine
+ * client:     i2c_client for communication
+ *
+ * return
+ *             0       : Success, no error
+ *     error code      : Failure
+ */
+static int picodlp_i2c_init(struct i2c_client *client)
+{
+       int r;
+       static const struct picodlp_i2c_command init_cmd_set1[] = {
+               {SOFT_RESET, 1},
+               {DMD_PARK_TRIGGER, 1},
+               {MISC_REG, 5},
+               {SEQ_CONTROL, 0},
+               {SEQ_VECTOR, 0x100},
+               {DMD_BLOCK_COUNT, 7},
+               {DMD_VCC_CONTROL, 0x109},
+               {DMD_PARK_PULSE_COUNT, 0xA},
+               {DMD_PARK_PULSE_WIDTH, 0xB},
+               {DMD_PARK_DELAY, 0x2ED},
+               {DMD_SHADOW_ENABLE, 0},
+               {FLASH_OPCODE, 0xB},
+               {FLASH_DUMMY_BYTES, 1},
+               {FLASH_ADDR_BYTES, 3},
+               {PBC_CONTROL, 0},
+               {FLASH_START_ADDR, CMT_LUT_0_START_ADDR},
+               {FLASH_READ_BYTES, CMT_LUT_0_SIZE},
+               {CMT_SPLASH_LUT_START_ADDR, 0},
+               {CMT_SPLASH_LUT_DEST_SELECT, CMT_LUT_ALL},
+               {PBC_CONTROL, 1},
+       };
+
+       static const struct picodlp_i2c_command init_cmd_set2[] = {
+               {PBC_CONTROL, 0},
+               {CMT_SPLASH_LUT_DEST_SELECT, 0},
+               {PBC_CONTROL, 0},
+               {FLASH_START_ADDR, SEQUENCE_0_START_ADDR},
+               {FLASH_READ_BYTES, SEQUENCE_0_SIZE},
+               {SEQ_RESET_LUT_START_ADDR, 0},
+               {SEQ_RESET_LUT_DEST_SELECT, SEQ_SEQ_LUT},
+               {PBC_CONTROL, 1},
+       };
+
+       static const struct picodlp_i2c_command init_cmd_set3[] = {
+               {PBC_CONTROL, 0},
+               {SEQ_RESET_LUT_DEST_SELECT, 0},
+               {PBC_CONTROL, 0},
+               {FLASH_START_ADDR, DRC_TABLE_0_START_ADDR},
+               {FLASH_READ_BYTES, DRC_TABLE_0_SIZE},
+               {SEQ_RESET_LUT_START_ADDR, 0},
+               {SEQ_RESET_LUT_DEST_SELECT, SEQ_DRC_LUT_ALL},
+               {PBC_CONTROL, 1},
+       };
+
+       static const struct picodlp_i2c_command init_cmd_set4[] = {
+               {PBC_CONTROL, 0},
+               {SEQ_RESET_LUT_DEST_SELECT, 0},
+               {SDC_ENABLE, 1},
+               {AGC_CTRL, 7},
+               {CCA_C1A, 0x100},
+               {CCA_C1B, 0x0},
+               {CCA_C1C, 0x0},
+               {CCA_C2A, 0x0},
+               {CCA_C2B, 0x100},
+               {CCA_C2C, 0x0},
+               {CCA_C3A, 0x0},
+               {CCA_C3B, 0x0},
+               {CCA_C3C, 0x100},
+               {CCA_C7A, 0x100},
+               {CCA_C7B, 0x100},
+               {CCA_C7C, 0x100},
+               {CCA_ENABLE, 1},
+               {CPU_IF_MODE, 1},
+               {SHORT_FLIP, 1},
+               {CURTAIN_CONTROL, 0},
+               {DMD_PARK_TRIGGER, 0},
+               {R_DRIVE_CURRENT, 0x298},
+               {G_DRIVE_CURRENT, 0x298},
+               {B_DRIVE_CURRENT, 0x298},
+               {RGB_DRIVER_ENABLE, 7},
+               {SEQ_CONTROL, 0},
+               {ACTGEN_CONTROL, 0x10},
+               {SEQUENCE_MODE, SEQ_LOCK},
+               {DATA_FORMAT, RGB888},
+               {INPUT_RESOLUTION, WVGA_864_LANDSCAPE},
+               {INPUT_SOURCE, PARALLEL_RGB},
+               {CPU_IF_SYNC_METHOD, 1},
+               {SEQ_CONTROL, 1}
+       };
+
+       r = picodlp_i2c_write_array(client, init_cmd_set1,
+                                               ARRAY_SIZE(init_cmd_set1));
+       if (r)
+               return r;
+
+       r = picodlp_wait_for_dma_done(client);
+       if (r)
+               return r;
+
+       r = picodlp_i2c_write_array(client, init_cmd_set2,
+                                       ARRAY_SIZE(init_cmd_set2));
+       if (r)
+               return r;
+
+       r = picodlp_wait_for_dma_done(client);
+       if (r)
+               return r;
+
+       r = picodlp_i2c_write_array(client, init_cmd_set3,
+                                       ARRAY_SIZE(init_cmd_set3));
+       if (r)
+               return r;
+
+       r = picodlp_wait_for_dma_done(client);
+       if (r)
+               return r;
+
+       r = picodlp_i2c_write_array(client, init_cmd_set4,
+                                       ARRAY_SIZE(init_cmd_set4));
+       if (r)
+               return r;
+
+       return 0;
+}
+
+static int picodlp_i2c_probe(struct i2c_client *client,
+               const struct i2c_device_id *id)
+{
+       struct picodlp_i2c_data *picodlp_i2c_data;
+
+       picodlp_i2c_data = kzalloc(sizeof(struct picodlp_i2c_data), GFP_KERNEL);
+
+       if (!picodlp_i2c_data)
+               return -ENOMEM;
+
+       mutex_init(&picodlp_i2c_data->xfer_lock);
+       i2c_set_clientdata(client, picodlp_i2c_data);
+
+       return 0;
+}
+
+static int picodlp_i2c_remove(struct i2c_client *client)
+{
+       struct picodlp_i2c_data *picodlp_i2c_data =
+                                       i2c_get_clientdata(client);
+       kfree(picodlp_i2c_data);
+       return 0;
+}
+
+static struct i2c_driver picodlp_i2c_driver = {
+       .driver = {
+               .name   = "picodlp_i2c_driver",
+       },
+       .probe          = picodlp_i2c_probe,
+       .remove         = picodlp_i2c_remove,
+       .id_table       = picodlp_i2c_id,
+};
+
+static int picodlp_panel_power_on(struct omap_dss_device *dssdev)
+{
+       int r, trial = 100;
+       struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
+       struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
+
+       if (dssdev->platform_enable) {
+               r = dssdev->platform_enable(dssdev);
+               if (r)
+                       return r;
+       }
+
+       gpio_set_value(picodlp_pdata->pwrgood_gpio, 0);
+       msleep(1);
+       gpio_set_value(picodlp_pdata->pwrgood_gpio, 1);
+
+       while (!gpio_get_value(picodlp_pdata->emu_done_gpio)) {
+               if (!trial--) {
+                       dev_err(&dssdev->dev, "emu_done signal not"
+                                               " going high\n");
+                       return -ETIMEDOUT;
+               }
+               msleep(5);
+       }
+       /*
+        * As per dpp2600 programming guide,
+        * it is required to sleep for 1000ms after emu_done signal goes high
+        * then only i2c commands can be successfully sent to dpp2600
+        */
+       msleep(1000);
+       r = omapdss_dpi_display_enable(dssdev);
+       if (r) {
+               dev_err(&dssdev->dev, "failed to enable DPI\n");
+               goto err1;
+       }
+
+       r = picodlp_i2c_init(picod->picodlp_i2c_client);
+       if (r)
+               goto err;
+
+       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+       return r;
+err:
+       omapdss_dpi_display_disable(dssdev);
+err1:
+       if (dssdev->platform_disable)
+               dssdev->platform_disable(dssdev);
+
+       return r;
+}
+
+static void picodlp_panel_power_off(struct omap_dss_device *dssdev)
+{
+       struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
+
+       omapdss_dpi_display_disable(dssdev);
+
+       gpio_set_value(picodlp_pdata->emu_done_gpio, 0);
+       gpio_set_value(picodlp_pdata->pwrgood_gpio, 0);
+
+       if (dssdev->platform_disable)
+               dssdev->platform_disable(dssdev);
+}
+
+static int picodlp_panel_probe(struct omap_dss_device *dssdev)
+{
+       struct picodlp_data *picod;
+       struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
+       struct i2c_adapter *adapter;
+       struct i2c_client *picodlp_i2c_client;
+       int r = 0, picodlp_adapter_id;
+
+       dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_ONOFF |
+                               OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IVS;
+       dssdev->panel.acb = 0x0;
+       dssdev->panel.timings = pico_ls_timings;
+
+       picod =  kzalloc(sizeof(struct picodlp_data), GFP_KERNEL);
+       if (!picod)
+               return -ENOMEM;
+
+       mutex_init(&picod->lock);
+
+       picodlp_adapter_id = picodlp_pdata->picodlp_adapter_id;
+
+       adapter = i2c_get_adapter(picodlp_adapter_id);
+       if (!adapter) {
+               dev_err(&dssdev->dev, "can't get i2c adapter\n");
+               r = -ENODEV;
+               goto err;
+       }
+
+       picodlp_i2c_client = i2c_new_device(adapter, &picodlp_i2c_board_info);
+       if (!picodlp_i2c_client) {
+               dev_err(&dssdev->dev, "can't add i2c device::"
+                                        " picodlp_i2c_client is NULL\n");
+               r = -ENODEV;
+               goto err;
+       }
+
+       picod->picodlp_i2c_client = picodlp_i2c_client;
+
+       dev_set_drvdata(&dssdev->dev, picod);
+       return r;
+err:
+       kfree(picod);
+       return r;
+}
+
+static void picodlp_panel_remove(struct omap_dss_device *dssdev)
+{
+       struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
+
+       i2c_unregister_device(picod->picodlp_i2c_client);
+       dev_set_drvdata(&dssdev->dev, NULL);
+       dev_dbg(&dssdev->dev, "removing picodlp panel\n");
+
+       kfree(picod);
+}
+
+static int picodlp_panel_enable(struct omap_dss_device *dssdev)
+{
+       struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
+       int r;
+
+       dev_dbg(&dssdev->dev, "enabling picodlp panel\n");
+
+       mutex_lock(&picod->lock);
+       if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
+               mutex_unlock(&picod->lock);
+               return -EINVAL;
+       }
+
+       r = picodlp_panel_power_on(dssdev);
+       mutex_unlock(&picod->lock);
+
+       return r;
+}
+
+static void picodlp_panel_disable(struct omap_dss_device *dssdev)
+{
+       struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
+
+       mutex_lock(&picod->lock);
+       /* Turn off DLP Power */
+       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+               picodlp_panel_power_off(dssdev);
+
+       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+       mutex_unlock(&picod->lock);
+
+       dev_dbg(&dssdev->dev, "disabling picodlp panel\n");
+}
+
+static int picodlp_panel_suspend(struct omap_dss_device *dssdev)
+{
+       struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
+
+       mutex_lock(&picod->lock);
+       /* Turn off DLP Power */
+       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
+               mutex_unlock(&picod->lock);
+               dev_err(&dssdev->dev, "unable to suspend picodlp panel,"
+                                       " panel is not ACTIVE\n");
+               return -EINVAL;
+       }
+
+       picodlp_panel_power_off(dssdev);
+
+       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+       mutex_unlock(&picod->lock);
+
+       dev_dbg(&dssdev->dev, "suspending picodlp panel\n");
+       return 0;
+}
+
+static int picodlp_panel_resume(struct omap_dss_device *dssdev)
+{
+       struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
+       int r;
+
+       mutex_lock(&picod->lock);
+       if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
+               mutex_unlock(&picod->lock);
+               dev_err(&dssdev->dev, "unable to resume picodlp panel,"
+                       " panel is not ACTIVE\n");
+               return -EINVAL;
+       }
+
+       r = picodlp_panel_power_on(dssdev);
+       mutex_unlock(&picod->lock);
+       dev_dbg(&dssdev->dev, "resuming picodlp panel\n");
+       return r;
+}
+
+static void picodlp_get_resolution(struct omap_dss_device *dssdev,
+                                       u16 *xres, u16 *yres)
+{
+       *xres = dssdev->panel.timings.x_res;
+       *yres = dssdev->panel.timings.y_res;
+}
+
+static struct omap_dss_driver picodlp_driver = {
+       .probe          = picodlp_panel_probe,
+       .remove         = picodlp_panel_remove,
+
+       .enable         = picodlp_panel_enable,
+       .disable        = picodlp_panel_disable,
+
+       .get_resolution = picodlp_get_resolution,
+
+       .suspend        = picodlp_panel_suspend,
+       .resume         = picodlp_panel_resume,
+
+       .driver         = {
+               .name   = "picodlp_panel",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init picodlp_init(void)
+{
+       int r = 0;
+
+       r = i2c_add_driver(&picodlp_i2c_driver);
+       if (r) {
+               printk(KERN_WARNING "picodlp_i2c_driver" \
+                       " registration failed\n");
+               return r;
+       }
+
+       r = omap_dss_register_driver(&picodlp_driver);
+       if (r)
+               i2c_del_driver(&picodlp_i2c_driver);
+
+       return r;
+}
+
+static void __exit picodlp_exit(void)
+{
+       i2c_del_driver(&picodlp_i2c_driver);
+       omap_dss_unregister_driver(&picodlp_driver);
+}
+
+module_init(picodlp_init);
+module_exit(picodlp_exit);
+
+MODULE_AUTHOR("Mythri P K <mythripk@ti.com>");
+MODULE_DESCRIPTION("picodlp driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-picodlp.h b/drivers/video/omap2/displays/panel-picodlp.h
new file mode 100644 (file)
index 0000000..a34b431
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * Header file required by picodlp panel driver
+ *
+ * Copyright (C) 2009-2011 Texas Instruments
+ * Author: Mythri P K <mythripk@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __OMAP2_DISPLAY_PANEL_PICODLP_H
+#define __OMAP2_DISPLAY_PANEL_PICODLP_H
+
+/* Commands used for configuring picodlp panel */
+
+#define MAIN_STATUS                    0x03
+#define PBC_CONTROL                    0x08
+#define INPUT_SOURCE                   0x0B
+#define INPUT_RESOLUTION               0x0C
+#define DATA_FORMAT                    0x0D
+#define IMG_ROTATION                   0x0E
+#define LONG_FLIP                      0x0F
+#define SHORT_FLIP                     0x10
+#define TEST_PAT_SELECT                        0x11
+#define R_DRIVE_CURRENT                        0x12
+#define G_DRIVE_CURRENT                        0x13
+#define B_DRIVE_CURRENT                        0x14
+#define READ_REG_SELECT                        0x15
+#define RGB_DRIVER_ENABLE              0x16
+
+#define CPU_IF_MODE                    0x18
+#define FRAME_RATE                     0x19
+#define CPU_IF_SYNC_METHOD             0x1A
+#define CPU_IF_SOF                     0x1B
+#define CPU_IF_EOF                     0x1C
+#define CPU_IF_SLEEP                   0x1D
+
+#define SEQUENCE_MODE                  0x1E
+#define SOFT_RESET                     0x1F
+#define FRONT_END_RESET                        0x21
+#define AUTO_PWR_ENABLE                        0x22
+
+#define VSYNC_LINE_DELAY               0x23
+#define CPU_PI_HORIZ_START             0x24
+#define CPU_PI_VERT_START              0x25
+#define CPU_PI_HORIZ_WIDTH             0x26
+#define CPU_PI_VERT_HEIGHT             0x27
+
+#define PIXEL_MASK_CROP                        0x28
+#define CROP_FIRST_LINE                        0x29
+#define CROP_LAST_LINE                 0x2A
+#define CROP_FIRST_PIXEL               0x2B
+#define CROP_LAST_PIXEL                        0x2C
+#define DMD_PARK_TRIGGER               0x2D
+
+#define MISC_REG                       0x30
+
+/* AGC registers */
+#define AGC_CTRL                       0x50
+#define AGC_CLIPPED_PIXS               0x55
+#define AGC_BRIGHT_PIXS                        0x56
+#define AGC_BG_PIXS                    0x57
+#define AGC_SAFETY_MARGIN              0x17
+
+/* Color Coordinate Adjustment registers */
+#define CCA_ENABLE             0x5E
+#define CCA_C1A                        0x5F
+#define CCA_C1B                        0x60
+#define CCA_C1C                        0x61
+#define CCA_C2A                        0x62
+#define CCA_C2B                        0x63
+#define CCA_C2C                        0x64
+#define CCA_C3A                        0x65
+#define CCA_C3B                        0x66
+#define CCA_C3C                        0x67
+#define CCA_C7A                        0x71
+#define CCA_C7B                        0x72
+#define CCA_C7C                        0x73
+
+/**
+ * DLP Pico Processor 2600 comes with flash
+ * We can do DMA operations from flash for accessing Look Up Tables
+ */
+#define DMA_STATUS                     0x100
+#define FLASH_ADDR_BYTES               0x74
+#define FLASH_DUMMY_BYTES              0x75
+#define FLASH_WRITE_BYTES              0x76
+#define FLASH_READ_BYTES               0x77
+#define FLASH_OPCODE                   0x78
+#define FLASH_START_ADDR               0x79
+#define FLASH_DUMMY2                   0x7A
+#define FLASH_WRITE_DATA               0x7B
+
+#define TEMPORAL_DITH_DISABLE          0x7E
+#define SEQ_CONTROL                    0x82
+#define SEQ_VECTOR                     0x83
+
+/* DMD is Digital Micromirror Device */
+#define DMD_BLOCK_COUNT                        0x84
+#define DMD_VCC_CONTROL                        0x86
+#define DMD_PARK_PULSE_COUNT           0x87
+#define DMD_PARK_PULSE_WIDTH           0x88
+#define DMD_PARK_DELAY                 0x89
+#define DMD_SHADOW_ENABLE              0x8E
+#define SEQ_STATUS                     0x8F
+#define FLASH_CLOCK_CONTROL            0x98
+#define DMD_PARK                       0x2D
+
+#define SDRAM_BIST_ENABLE              0x46
+#define DDR_DRIVER_STRENGTH            0x9A
+#define SDC_ENABLE                     0x9D
+#define SDC_BUFF_SWAP_DISABLE          0xA3
+#define CURTAIN_CONTROL                        0xA6
+#define DDR_BUS_SWAP_ENABLE            0xA7
+#define DMD_TRC_ENABLE                 0xA8
+#define DMD_BUS_SWAP_ENABLE            0xA9
+
+#define ACTGEN_ENABLE                  0xAE
+#define ACTGEN_CONTROL                 0xAF
+#define ACTGEN_HORIZ_BP                        0xB0
+#define ACTGEN_VERT_BP                 0xB1
+
+/* Look Up Table access */
+#define CMT_SPLASH_LUT_START_ADDR      0xFA
+#define CMT_SPLASH_LUT_DEST_SELECT     0xFB
+#define CMT_SPLASH_LUT_DATA            0xFC
+#define SEQ_RESET_LUT_START_ADDR       0xFD
+#define SEQ_RESET_LUT_DEST_SELECT      0xFE
+#define SEQ_RESET_LUT_DATA             0xFF
+
+/* Input source definitions */
+#define PARALLEL_RGB           0
+#define INT_TEST_PATTERN       1
+#define SPLASH_SCREEN          2
+#define CPU_INTF               3
+#define BT656                  4
+
+/* Standard input resolution definitions */
+#define QWVGA_LANDSCAPE                3       /* (427h*240v) */
+#define WVGA_864_LANDSCAPE     21      /* (864h*480v) */
+#define WVGA_DMD_OPTICAL_TEST  35      /* (608h*684v) */
+
+/* Standard data format definitions */
+#define RGB565                 0
+#define RGB666                 1
+#define RGB888                 2
+
+/* Test Pattern definitions */
+#define TPG_CHECKERBOARD       0
+#define TPG_BLACK              1
+#define TPG_WHITE              2
+#define TPG_RED                        3
+#define TPG_BLUE               4
+#define TPG_GREEN              5
+#define TPG_VLINES_BLACK       6
+#define TPG_HLINES_BLACK       7
+#define TPG_VLINES_ALT         8
+#define TPG_HLINES_ALT         9
+#define TPG_DIAG_LINES         10
+#define TPG_GREYRAMP_VERT      11
+#define TPG_GREYRAMP_HORIZ     12
+#define TPG_ANSI_CHECKERBOARD  13
+
+/* sequence mode definitions */
+#define SEQ_FREE_RUN           0
+#define SEQ_LOCK               1
+
+/* curtain color definitions */
+#define CURTAIN_BLACK          0
+#define CURTAIN_RED            1
+#define CURTAIN_GREEN          2
+#define CURTAIN_BLUE           3
+#define CURTAIN_YELLOW         4
+#define CURTAIN_MAGENTA                5
+#define CURTAIN_CYAN           6
+#define CURTAIN_WHITE          7
+
+/* LUT definitions */
+#define CMT_LUT_NONE           0
+#define CMT_LUT_GREEN          1
+#define CMT_LUT_RED            2
+#define CMT_LUT_BLUE           3
+#define CMT_LUT_ALL            4
+#define SPLASH_LUT             5
+
+#define SEQ_LUT_NONE           0
+#define SEQ_DRC_LUT_0          1
+#define SEQ_DRC_LUT_1          2
+#define SEQ_DRC_LUT_2          3
+#define SEQ_DRC_LUT_3          4
+#define SEQ_SEQ_LUT            5
+#define SEQ_DRC_LUT_ALL                6
+#define WPC_PROGRAM_LUT                7
+
+#define BITSTREAM_START_ADDR           0x00000000
+#define BITSTREAM_SIZE                 0x00040000
+
+#define WPC_FW_0_START_ADDR            0x00040000
+#define WPC_FW_0_SIZE                  0x00000ce8
+
+#define SEQUENCE_0_START_ADDR          0x00044000
+#define SEQUENCE_0_SIZE                        0x00001000
+
+#define SEQUENCE_1_START_ADDR          0x00045000
+#define SEQUENCE_1_SIZE                        0x00000d10
+
+#define SEQUENCE_2_START_ADDR          0x00046000
+#define SEQUENCE_2_SIZE                        0x00000d10
+
+#define SEQUENCE_3_START_ADDR          0x00047000
+#define SEQUENCE_3_SIZE                        0x00000d10
+
+#define SEQUENCE_4_START_ADDR          0x00048000
+#define SEQUENCE_4_SIZE                        0x00000d10
+
+#define SEQUENCE_5_START_ADDR          0x00049000
+#define SEQUENCE_5_SIZE                        0x00000d10
+
+#define SEQUENCE_6_START_ADDR          0x0004a000
+#define SEQUENCE_6_SIZE                        0x00000d10
+
+#define CMT_LUT_0_START_ADDR           0x0004b200
+#define CMT_LUT_0_SIZE                 0x00000600
+
+#define CMT_LUT_1_START_ADDR           0x0004b800
+#define CMT_LUT_1_SIZE                 0x00000600
+
+#define CMT_LUT_2_START_ADDR           0x0004be00
+#define CMT_LUT_2_SIZE                 0x00000600
+
+#define CMT_LUT_3_START_ADDR           0x0004c400
+#define CMT_LUT_3_SIZE                 0x00000600
+
+#define CMT_LUT_4_START_ADDR           0x0004ca00
+#define CMT_LUT_4_SIZE                 0x00000600
+
+#define CMT_LUT_5_START_ADDR           0x0004d000
+#define CMT_LUT_5_SIZE                 0x00000600
+
+#define CMT_LUT_6_START_ADDR           0x0004d600
+#define CMT_LUT_6_SIZE                 0x00000600
+
+#define DRC_TABLE_0_START_ADDR         0x0004dc00
+#define DRC_TABLE_0_SIZE               0x00000100
+
+#define SPLASH_0_START_ADDR            0x0004dd00
+#define SPLASH_0_SIZE                  0x00032280
+
+#define SEQUENCE_7_START_ADDR          0x00080000
+#define SEQUENCE_7_SIZE                        0x00000d10
+
+#define SEQUENCE_8_START_ADDR          0x00081800
+#define SEQUENCE_8_SIZE                        0x00000d10
+
+#define SEQUENCE_9_START_ADDR          0x00083000
+#define SEQUENCE_9_SIZE                        0x00000d10
+
+#define CMT_LUT_7_START_ADDR           0x0008e000
+#define CMT_LUT_7_SIZE                 0x00000600
+
+#define CMT_LUT_8_START_ADDR           0x0008e800
+#define CMT_LUT_8_SIZE                 0x00000600
+
+#define CMT_LUT_9_START_ADDR           0x0008f000
+#define CMT_LUT_9_SIZE                 0x00000600
+
+#define SPLASH_1_START_ADDR            0x0009a000
+#define SPLASH_1_SIZE                  0x00032280
+
+#define SPLASH_2_START_ADDR            0x000cd000
+#define SPLASH_2_SIZE                  0x00032280
+
+#define SPLASH_3_START_ADDR            0x00100000
+#define SPLASH_3_SIZE                  0x00032280
+
+#define OPT_SPLASH_0_START_ADDR                0x00134000
+#define OPT_SPLASH_0_SIZE              0x000cb100
+
+#endif
index 4e888ac..80c3f6a 100644 (file)
 
 #include <video/omapdss.h>
 #include <video/omap-panel-nokia-dsi.h>
+#include <video/mipi_display.h>
 
 /* DSI Virtual channel. Hardcoded for now. */
 #define TCH 0
 
 #define DCS_READ_NUM_ERRORS    0x05
-#define DCS_READ_POWER_MODE    0x0a
-#define DCS_READ_MADCTL                0x0b
-#define DCS_READ_PIXEL_FORMAT  0x0c
-#define DCS_RDDSDR             0x0f
-#define DCS_SLEEP_IN           0x10
-#define DCS_SLEEP_OUT          0x11
-#define DCS_DISPLAY_OFF                0x28
-#define DCS_DISPLAY_ON         0x29
-#define DCS_COLUMN_ADDR                0x2a
-#define DCS_PAGE_ADDR          0x2b
-#define DCS_MEMORY_WRITE       0x2c
-#define DCS_TEAR_OFF           0x34
-#define DCS_TEAR_ON            0x35
-#define DCS_MEM_ACC_CTRL       0x36
-#define DCS_PIXEL_FORMAT       0x3a
 #define DCS_BRIGHTNESS         0x51
 #define DCS_CTRL_DISPLAY       0x53
 #define DCS_WRITE_CABC         0x55
@@ -222,8 +208,6 @@ struct taal_data {
 
        struct delayed_work te_timeout_work;
 
-       bool use_dsi_bl;
-
        bool cabc_broken;
        unsigned cabc_mode;
 
@@ -302,7 +286,7 @@ static int taal_sleep_in(struct taal_data *td)
 
        hw_guard_wait(td);
 
-       cmd = DCS_SLEEP_IN;
+       cmd = MIPI_DCS_ENTER_SLEEP_MODE;
        r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, &cmd, 1);
        if (r)
                return r;
@@ -321,7 +305,7 @@ static int taal_sleep_out(struct taal_data *td)
 
        hw_guard_wait(td);
 
-       r = taal_dcs_write_0(td, DCS_SLEEP_OUT);
+       r = taal_dcs_write_0(td, MIPI_DCS_EXIT_SLEEP_MODE);
        if (r)
                return r;
 
@@ -356,7 +340,7 @@ static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror)
        u8 mode;
        int b5, b6, b7;
 
-       r = taal_dcs_read_1(td, DCS_READ_MADCTL, &mode);
+       r = taal_dcs_read_1(td, MIPI_DCS_GET_ADDRESS_MODE, &mode);
        if (r)
                return r;
 
@@ -390,7 +374,7 @@ static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror)
        mode &= ~((1<<7) | (1<<6) | (1<<5));
        mode |= (b7 << 7) | (b6 << 6) | (b5 << 5);
 
-       return taal_dcs_write_1(td, DCS_MEM_ACC_CTRL, mode);
+       return taal_dcs_write_1(td, MIPI_DCS_SET_ADDRESS_MODE, mode);
 }
 
 static int taal_set_update_window(struct taal_data *td,
@@ -403,7 +387,7 @@ static int taal_set_update_window(struct taal_data *td,
        u16 y2 = y + h - 1;
 
        u8 buf[5];
-       buf[0] = DCS_COLUMN_ADDR;
+       buf[0] = MIPI_DCS_SET_COLUMN_ADDRESS;
        buf[1] = (x1 >> 8) & 0xff;
        buf[2] = (x1 >> 0) & 0xff;
        buf[3] = (x2 >> 8) & 0xff;
@@ -413,7 +397,7 @@ static int taal_set_update_window(struct taal_data *td,
        if (r)
                return r;
 
-       buf[0] = DCS_PAGE_ADDR;
+       buf[0] = MIPI_DCS_SET_PAGE_ADDRESS;
        buf[1] = (y1 >> 8) & 0xff;
        buf[2] = (y1 >> 0) & 0xff;
        buf[3] = (y2 >> 8) & 0xff;
@@ -555,7 +539,6 @@ static int taal_bl_update_status(struct backlight_device *dev)
 {
        struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
        struct taal_data *td = dev_get_drvdata(&dssdev->dev);
-       struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
        int r;
        int level;
 
@@ -569,23 +552,16 @@ static int taal_bl_update_status(struct backlight_device *dev)
 
        mutex_lock(&td->lock);
 
-       if (td->use_dsi_bl) {
-               if (td->enabled) {
-                       dsi_bus_lock(dssdev);
+       if (td->enabled) {
+               dsi_bus_lock(dssdev);
 
-                       r = taal_wake_up(dssdev);
-                       if (!r)
-                               r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level);
+               r = taal_wake_up(dssdev);
+               if (!r)
+                       r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level);
 
-                       dsi_bus_unlock(dssdev);
-               } else {
-                       r = 0;
-               }
+               dsi_bus_unlock(dssdev);
        } else {
-               if (!panel_data->set_backlight)
-                       r = -EINVAL;
-               else
-                       r = panel_data->set_backlight(dssdev, level);
+               r = 0;
        }
 
        mutex_unlock(&td->lock);
@@ -964,7 +940,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
 {
        struct backlight_properties props;
        struct taal_data *td;
-       struct backlight_device *bldev;
+       struct backlight_device *bldev = NULL;
        struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
        struct panel_config *panel_config = NULL;
        int r, i;
@@ -990,7 +966,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
 
        dssdev->panel.config = OMAP_DSS_LCD_TFT;
        dssdev->panel.timings = panel_config->timings;
-       dssdev->ctrl.pixel_size = 24;
+       dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
 
        td = kzalloc(sizeof(*td), GFP_KERNEL);
        if (!td) {
@@ -1025,35 +1001,26 @@ static int taal_probe(struct omap_dss_device *dssdev)
 
        taal_hw_reset(dssdev);
 
-       /* if no platform set_backlight() defined, presume DSI backlight
-        * control */
-       memset(&props, 0, sizeof(struct backlight_properties));
-       if (!panel_data->set_backlight)
-               td->use_dsi_bl = true;
-
-       if (td->use_dsi_bl)
+       if (panel_data->use_dsi_backlight) {
+               memset(&props, 0, sizeof(struct backlight_properties));
                props.max_brightness = 255;
-       else
-               props.max_brightness = 127;
-
-       props.type = BACKLIGHT_RAW;
-       bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev,
-                                       dssdev, &taal_bl_ops, &props);
-       if (IS_ERR(bldev)) {
-               r = PTR_ERR(bldev);
-               goto err_bl;
-       }
 
-       td->bldev = bldev;
+               props.type = BACKLIGHT_RAW;
+               bldev = backlight_device_register(dev_name(&dssdev->dev),
+                               &dssdev->dev, dssdev, &taal_bl_ops, &props);
+               if (IS_ERR(bldev)) {
+                       r = PTR_ERR(bldev);
+                       goto err_bl;
+               }
+
+               td->bldev = bldev;
 
-       bldev->props.fb_blank = FB_BLANK_UNBLANK;
-       bldev->props.power = FB_BLANK_UNBLANK;
-       if (td->use_dsi_bl)
+               bldev->props.fb_blank = FB_BLANK_UNBLANK;
+               bldev->props.power = FB_BLANK_UNBLANK;
                bldev->props.brightness = 255;
-       else
-               bldev->props.brightness = 127;
 
-       taal_bl_update_status(bldev);
+               taal_bl_update_status(bldev);
+       }
 
        if (panel_data->use_ext_te) {
                int gpio = panel_data->ext_te_gpio;
@@ -1067,7 +1034,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
                gpio_direction_input(gpio);
 
                r = request_irq(gpio_to_irq(gpio), taal_te_isr,
-                               IRQF_DISABLED | IRQF_TRIGGER_RISING,
+                               IRQF_TRIGGER_RISING,
                                "taal vsync", dssdev);
 
                if (r) {
@@ -1111,7 +1078,8 @@ err_irq:
        if (panel_data->use_ext_te)
                gpio_free(panel_data->ext_te_gpio);
 err_gpio:
-       backlight_device_unregister(bldev);
+       if (bldev != NULL)
+               backlight_device_unregister(bldev);
 err_bl:
        destroy_workqueue(td->workqueue);
 err_wq:
@@ -1140,9 +1108,11 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
        }
 
        bldev = td->bldev;
-       bldev->props.power = FB_BLANK_POWERDOWN;
-       taal_bl_update_status(bldev);
-       backlight_device_unregister(bldev);
+       if (bldev != NULL) {
+               bldev->props.power = FB_BLANK_POWERDOWN;
+               taal_bl_update_status(bldev);
+               backlight_device_unregister(bldev);
+       }
 
        taal_cancel_ulps_work(dssdev);
        taal_cancel_esd_work(dssdev);
@@ -1195,7 +1165,8 @@ static int taal_power_on(struct omap_dss_device *dssdev)
        if (r)
                goto err;
 
-       r = taal_dcs_write_1(td, DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */
+       r = taal_dcs_write_1(td, MIPI_DCS_SET_PIXEL_FORMAT,
+               MIPI_DCS_PIXEL_FMT_24BIT);
        if (r)
                goto err;
 
@@ -1209,7 +1180,7 @@ static int taal_power_on(struct omap_dss_device *dssdev)
                        goto err;
        }
 
-       r = taal_dcs_write_0(td, DCS_DISPLAY_ON);
+       r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_ON);
        if (r)
                goto err;
 
@@ -1246,7 +1217,7 @@ static void taal_power_off(struct omap_dss_device *dssdev)
        struct taal_data *td = dev_get_drvdata(&dssdev->dev);
        int r;
 
-       r = taal_dcs_write_0(td, DCS_DISPLAY_OFF);
+       r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_OFF);
        if (!r)
                r = taal_sleep_in(td);
 
@@ -1529,9 +1500,9 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
        int r;
 
        if (enable)
-               r = taal_dcs_write_1(td, DCS_TEAR_ON, 0);
+               r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0);
        else
-               r = taal_dcs_write_0(td, DCS_TEAR_OFF);
+               r = taal_dcs_write_0(td, MIPI_DCS_SET_TEAR_OFF);
 
        if (!panel_data->use_ext_te)
                omapdss_dsi_enable_te(dssdev, enable);
@@ -1851,7 +1822,7 @@ static void taal_esd_work(struct work_struct *work)
                goto err;
        }
 
-       r = taal_dcs_read_1(td, DCS_RDDSDR, &state1);
+       r = taal_dcs_read_1(td, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state1);
        if (r) {
                dev_err(&dssdev->dev, "failed to read Taal status\n");
                goto err;
@@ -1864,7 +1835,7 @@ static void taal_esd_work(struct work_struct *work)
                goto err;
        }
 
-       r = taal_dcs_read_1(td, DCS_RDDSDR, &state2);
+       r = taal_dcs_read_1(td, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state2);
        if (r) {
                dev_err(&dssdev->dev, "failed to read Taal status\n");
                goto err;
@@ -1880,7 +1851,7 @@ static void taal_esd_work(struct work_struct *work)
        /* Self-diagnostics result is also shown on TE GPIO line. We need
         * to re-enable TE after self diagnostics */
        if (td->te_enabled && panel_data->use_ext_te) {
-               r = taal_dcs_write_1(td, DCS_TEAR_ON, 0);
+               r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0);
                if (r)
                        goto err;
        }
index 0d12524..7be7c06 100644 (file)
@@ -1,5 +1,5 @@
 menuconfig OMAP2_DSS
-        tristate "OMAP2+ Display Subsystem support (EXPERIMENTAL)"
+        tristate "OMAP2+ Display Subsystem support"
         depends on ARCH_OMAP2PLUS
         help
          OMAP2+ Display Subsystem support.
index 10d9d3b..bd34ac5 100644 (file)
@@ -6,4 +6,4 @@ omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
 omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
 omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
 omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \
-                                   hdmi_omap4_panel.o
+                                   hdmi_panel.o ti_hdmi_4xxx_ip.o
index 76821fe..86ec12e 100644 (file)
@@ -144,6 +144,10 @@ static int dss_initialize_debugfs(void)
 #ifdef CONFIG_OMAP2_DSS_VENC
        debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir,
                        &venc_dump_regs, &dss_debug_fops);
+#endif
+#ifdef CONFIG_OMAP4_DSS_HDMI
+       debugfs_create_file("hdmi", S_IRUGO, dss_debugfs_dir,
+                       &hdmi_dump_regs, &dss_debug_fops);
 #endif
        return 0;
 }
index 0f3961a..6892cfd 100644 (file)
@@ -106,7 +106,7 @@ static struct {
        int irq;
        struct clk *dss_clk;
 
-       u32     fifo_size[3];
+       u32     fifo_size[MAX_DSS_OVERLAYS];
 
        spinlock_t irq_lock;
        u32 irq_error_mask;
@@ -171,172 +171,98 @@ static int dispc_get_ctx_loss_count(void)
 
 static void dispc_save_context(void)
 {
-       int i;
+       int i, j;
 
        DSSDBG("dispc_save_context\n");
 
        SR(IRQENABLE);
        SR(CONTROL);
        SR(CONFIG);
-       SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD));
-       SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT));
-       SR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD));
-       SR(TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT));
        SR(LINE_NUMBER);
-       SR(TIMING_H(OMAP_DSS_CHANNEL_LCD));
-       SR(TIMING_V(OMAP_DSS_CHANNEL_LCD));
-       SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
-       SR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
-       if (dss_has_feature(FEAT_GLOBAL_ALPHA))
+       if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) ||
+                       dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
                SR(GLOBAL_ALPHA);
-       SR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
-       SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
        if (dss_has_feature(FEAT_MGR_LCD2)) {
                SR(CONTROL2);
-               SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2));
-               SR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2));
-               SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD2));
-               SR(TIMING_H(OMAP_DSS_CHANNEL_LCD2));
-               SR(TIMING_V(OMAP_DSS_CHANNEL_LCD2));
-               SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD2));
-               SR(DIVISORo(OMAP_DSS_CHANNEL_LCD2));
                SR(CONFIG2);
        }
 
-       SR(OVL_BA0(OMAP_DSS_GFX));
-       SR(OVL_BA1(OMAP_DSS_GFX));
-       SR(OVL_POSITION(OMAP_DSS_GFX));
-       SR(OVL_SIZE(OMAP_DSS_GFX));
-       SR(OVL_ATTRIBUTES(OMAP_DSS_GFX));
-       SR(OVL_FIFO_THRESHOLD(OMAP_DSS_GFX));
-       SR(OVL_ROW_INC(OMAP_DSS_GFX));
-       SR(OVL_PIXEL_INC(OMAP_DSS_GFX));
-       SR(OVL_WINDOW_SKIP(OMAP_DSS_GFX));
-       SR(OVL_TABLE_BA(OMAP_DSS_GFX));
+       for (i = 0; i < dss_feat_get_num_mgrs(); i++) {
+               SR(DEFAULT_COLOR(i));
+               SR(TRANS_COLOR(i));
+               SR(SIZE_MGR(i));
+               if (i == OMAP_DSS_CHANNEL_DIGIT)
+                       continue;
+               SR(TIMING_H(i));
+               SR(TIMING_V(i));
+               SR(POL_FREQ(i));
+               SR(DIVISORo(i));
 
-       SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD));
-       SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
-       SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
+               SR(DATA_CYCLE1(i));
+               SR(DATA_CYCLE2(i));
+               SR(DATA_CYCLE3(i));
 
-       if (dss_has_feature(FEAT_CPR)) {
-               SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
-               SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
-               SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
-       }
-       if (dss_has_feature(FEAT_MGR_LCD2)) {
                if (dss_has_feature(FEAT_CPR)) {
-                       SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
-                       SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
-                       SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+                       SR(CPR_COEF_R(i));
+                       SR(CPR_COEF_G(i));
+                       SR(CPR_COEF_B(i));
                }
-
-               SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
-               SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
-               SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
        }
 
-       if (dss_has_feature(FEAT_PRELOAD))
-               SR(OVL_PRELOAD(OMAP_DSS_GFX));
-
-       /* VID1 */
-       SR(OVL_BA0(OMAP_DSS_VIDEO1));
-       SR(OVL_BA1(OMAP_DSS_VIDEO1));
-       SR(OVL_POSITION(OMAP_DSS_VIDEO1));
-       SR(OVL_SIZE(OMAP_DSS_VIDEO1));
-       SR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO1));
-       SR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1));
-       SR(OVL_ROW_INC(OMAP_DSS_VIDEO1));
-       SR(OVL_PIXEL_INC(OMAP_DSS_VIDEO1));
-       SR(OVL_FIR(OMAP_DSS_VIDEO1));
-       SR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1));
-       SR(OVL_ACCU0(OMAP_DSS_VIDEO1));
-       SR(OVL_ACCU1(OMAP_DSS_VIDEO1));
-
-       for (i = 0; i < 8; i++)
-               SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, i));
-
-       for (i = 0; i < 8; i++)
-               SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, i));
-
-       for (i = 0; i < 5; i++)
-               SR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i));
-
-       if (dss_has_feature(FEAT_FIR_COEF_V)) {
-               for (i = 0; i < 8; i++)
-                       SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
-       }
-
-       if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
-               SR(OVL_BA0_UV(OMAP_DSS_VIDEO1));
-               SR(OVL_BA1_UV(OMAP_DSS_VIDEO1));
-               SR(OVL_FIR2(OMAP_DSS_VIDEO1));
-               SR(OVL_ACCU2_0(OMAP_DSS_VIDEO1));
-               SR(OVL_ACCU2_1(OMAP_DSS_VIDEO1));
-
-               for (i = 0; i < 8; i++)
-                       SR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, i));
-
-               for (i = 0; i < 8; i++)
-                       SR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, i));
-
-               for (i = 0; i < 8; i++)
-                       SR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, i));
-       }
-       if (dss_has_feature(FEAT_ATTR2))
-               SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
-
-       if (dss_has_feature(FEAT_PRELOAD))
-               SR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
-
-       /* VID2 */
-       SR(OVL_BA0(OMAP_DSS_VIDEO2));
-       SR(OVL_BA1(OMAP_DSS_VIDEO2));
-       SR(OVL_POSITION(OMAP_DSS_VIDEO2));
-       SR(OVL_SIZE(OMAP_DSS_VIDEO2));
-       SR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO2));
-       SR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2));
-       SR(OVL_ROW_INC(OMAP_DSS_VIDEO2));
-       SR(OVL_PIXEL_INC(OMAP_DSS_VIDEO2));
-       SR(OVL_FIR(OMAP_DSS_VIDEO2));
-       SR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2));
-       SR(OVL_ACCU0(OMAP_DSS_VIDEO2));
-       SR(OVL_ACCU1(OMAP_DSS_VIDEO2));
+       for (i = 0; i < dss_feat_get_num_ovls(); i++) {
+               SR(OVL_BA0(i));
+               SR(OVL_BA1(i));
+               SR(OVL_POSITION(i));
+               SR(OVL_SIZE(i));
+               SR(OVL_ATTRIBUTES(i));
+               SR(OVL_FIFO_THRESHOLD(i));
+               SR(OVL_ROW_INC(i));
+               SR(OVL_PIXEL_INC(i));
+               if (dss_has_feature(FEAT_PRELOAD))
+                       SR(OVL_PRELOAD(i));
+               if (i == OMAP_DSS_GFX) {
+                       SR(OVL_WINDOW_SKIP(i));
+                       SR(OVL_TABLE_BA(i));
+                       continue;
+               }
+               SR(OVL_FIR(i));
+               SR(OVL_PICTURE_SIZE(i));
+               SR(OVL_ACCU0(i));
+               SR(OVL_ACCU1(i));
 
-       for (i = 0; i < 8; i++)
-               SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, i));
+               for (j = 0; j < 8; j++)
+                       SR(OVL_FIR_COEF_H(i, j));
 
-       for (i = 0; i < 8; i++)
-               SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, i));
+               for (j = 0; j < 8; j++)
+                       SR(OVL_FIR_COEF_HV(i, j));
 
-       for (i = 0; i < 5; i++)
-               SR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i));
+               for (j = 0; j < 5; j++)
+                       SR(OVL_CONV_COEF(i, j));
 
-       if (dss_has_feature(FEAT_FIR_COEF_V)) {
-               for (i = 0; i < 8; i++)
-                       SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
-       }
+               if (dss_has_feature(FEAT_FIR_COEF_V)) {
+                       for (j = 0; j < 8; j++)
+                               SR(OVL_FIR_COEF_V(i, j));
+               }
 
-       if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
-               SR(OVL_BA0_UV(OMAP_DSS_VIDEO2));
-               SR(OVL_BA1_UV(OMAP_DSS_VIDEO2));
-               SR(OVL_FIR2(OMAP_DSS_VIDEO2));
-               SR(OVL_ACCU2_0(OMAP_DSS_VIDEO2));
-               SR(OVL_ACCU2_1(OMAP_DSS_VIDEO2));
+               if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
+                       SR(OVL_BA0_UV(i));
+                       SR(OVL_BA1_UV(i));
+                       SR(OVL_FIR2(i));
+                       SR(OVL_ACCU2_0(i));
+                       SR(OVL_ACCU2_1(i));
 
-               for (i = 0; i < 8; i++)
-                       SR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, i));
+                       for (j = 0; j < 8; j++)
+                               SR(OVL_FIR_COEF_H2(i, j));
 
-               for (i = 0; i < 8; i++)
-                       SR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, i));
+                       for (j = 0; j < 8; j++)
+                               SR(OVL_FIR_COEF_HV2(i, j));
 
-               for (i = 0; i < 8; i++)
-                       SR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, i));
+                       for (j = 0; j < 8; j++)
+                               SR(OVL_FIR_COEF_V2(i, j));
+               }
+               if (dss_has_feature(FEAT_ATTR2))
+                       SR(OVL_ATTRIBUTES2(i));
        }
-       if (dss_has_feature(FEAT_ATTR2))
-               SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
-
-       if (dss_has_feature(FEAT_PRELOAD))
-               SR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
 
        if (dss_has_feature(FEAT_CORE_CLK_DIV))
                SR(DIVISOR);
@@ -349,7 +275,7 @@ static void dispc_save_context(void)
 
 static void dispc_restore_context(void)
 {
-       int i, ctx;
+       int i, j, ctx;
 
        DSSDBG("dispc_restore_context\n");
 
@@ -367,165 +293,89 @@ static void dispc_restore_context(void)
        /*RR(IRQENABLE);*/
        /*RR(CONTROL);*/
        RR(CONFIG);
-       RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD));
-       RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT));
-       RR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD));
-       RR(TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT));
        RR(LINE_NUMBER);
-       RR(TIMING_H(OMAP_DSS_CHANNEL_LCD));
-       RR(TIMING_V(OMAP_DSS_CHANNEL_LCD));
-       RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
-       RR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
-       if (dss_has_feature(FEAT_GLOBAL_ALPHA))
+       if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) ||
+                       dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
                RR(GLOBAL_ALPHA);
-       RR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
-       RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
-       if (dss_has_feature(FEAT_MGR_LCD2)) {
-               RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2));
-               RR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2));
-               RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD2));
-               RR(TIMING_H(OMAP_DSS_CHANNEL_LCD2));
-               RR(TIMING_V(OMAP_DSS_CHANNEL_LCD2));
-               RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD2));
-               RR(DIVISORo(OMAP_DSS_CHANNEL_LCD2));
+       if (dss_has_feature(FEAT_MGR_LCD2))
                RR(CONFIG2);
-       }
-
-       RR(OVL_BA0(OMAP_DSS_GFX));
-       RR(OVL_BA1(OMAP_DSS_GFX));
-       RR(OVL_POSITION(OMAP_DSS_GFX));
-       RR(OVL_SIZE(OMAP_DSS_GFX));
-       RR(OVL_ATTRIBUTES(OMAP_DSS_GFX));
-       RR(OVL_FIFO_THRESHOLD(OMAP_DSS_GFX));
-       RR(OVL_ROW_INC(OMAP_DSS_GFX));
-       RR(OVL_PIXEL_INC(OMAP_DSS_GFX));
-       RR(OVL_WINDOW_SKIP(OMAP_DSS_GFX));
-       RR(OVL_TABLE_BA(OMAP_DSS_GFX));
-
 
-       RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD));
-       RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
-       RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
+       for (i = 0; i < dss_feat_get_num_mgrs(); i++) {
+               RR(DEFAULT_COLOR(i));
+               RR(TRANS_COLOR(i));
+               RR(SIZE_MGR(i));
+               if (i == OMAP_DSS_CHANNEL_DIGIT)
+                       continue;
+               RR(TIMING_H(i));
+               RR(TIMING_V(i));
+               RR(POL_FREQ(i));
+               RR(DIVISORo(i));
 
-       if (dss_has_feature(FEAT_CPR)) {
-               RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
-               RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
-               RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
-       }
-       if (dss_has_feature(FEAT_MGR_LCD2)) {
-               RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
-               RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
-               RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
+               RR(DATA_CYCLE1(i));
+               RR(DATA_CYCLE2(i));
+               RR(DATA_CYCLE3(i));
 
                if (dss_has_feature(FEAT_CPR)) {
-                       RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
-                       RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
-                       RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+                       RR(CPR_COEF_R(i));
+                       RR(CPR_COEF_G(i));
+                       RR(CPR_COEF_B(i));
                }
        }
 
-       if (dss_has_feature(FEAT_PRELOAD))
-               RR(OVL_PRELOAD(OMAP_DSS_GFX));
-
-       /* VID1 */
-       RR(OVL_BA0(OMAP_DSS_VIDEO1));
-       RR(OVL_BA1(OMAP_DSS_VIDEO1));
-       RR(OVL_POSITION(OMAP_DSS_VIDEO1));
-       RR(OVL_SIZE(OMAP_DSS_VIDEO1));
-       RR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO1));
-       RR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1));
-       RR(OVL_ROW_INC(OMAP_DSS_VIDEO1));
-       RR(OVL_PIXEL_INC(OMAP_DSS_VIDEO1));
-       RR(OVL_FIR(OMAP_DSS_VIDEO1));
-       RR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1));
-       RR(OVL_ACCU0(OMAP_DSS_VIDEO1));
-       RR(OVL_ACCU1(OMAP_DSS_VIDEO1));
-
-       for (i = 0; i < 8; i++)
-               RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, i));
-
-       for (i = 0; i < 8; i++)
-               RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, i));
-
-       for (i = 0; i < 5; i++)
-               RR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i));
-
-       if (dss_has_feature(FEAT_FIR_COEF_V)) {
-               for (i = 0; i < 8; i++)
-                       RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
-       }
-
-       if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
-               RR(OVL_BA0_UV(OMAP_DSS_VIDEO1));
-               RR(OVL_BA1_UV(OMAP_DSS_VIDEO1));
-               RR(OVL_FIR2(OMAP_DSS_VIDEO1));
-               RR(OVL_ACCU2_0(OMAP_DSS_VIDEO1));
-               RR(OVL_ACCU2_1(OMAP_DSS_VIDEO1));
-
-               for (i = 0; i < 8; i++)
-                       RR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, i));
-
-               for (i = 0; i < 8; i++)
-                       RR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, i));
-
-               for (i = 0; i < 8; i++)
-                       RR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, i));
-       }
-       if (dss_has_feature(FEAT_ATTR2))
-               RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
-
-       if (dss_has_feature(FEAT_PRELOAD))
-               RR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
-
-       /* VID2 */
-       RR(OVL_BA0(OMAP_DSS_VIDEO2));
-       RR(OVL_BA1(OMAP_DSS_VIDEO2));
-       RR(OVL_POSITION(OMAP_DSS_VIDEO2));
-       RR(OVL_SIZE(OMAP_DSS_VIDEO2));
-       RR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO2));
-       RR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2));
-       RR(OVL_ROW_INC(OMAP_DSS_VIDEO2));
-       RR(OVL_PIXEL_INC(OMAP_DSS_VIDEO2));
-       RR(OVL_FIR(OMAP_DSS_VIDEO2));
-       RR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2));
-       RR(OVL_ACCU0(OMAP_DSS_VIDEO2));
-       RR(OVL_ACCU1(OMAP_DSS_VIDEO2));
+       for (i = 0; i < dss_feat_get_num_ovls(); i++) {
+               RR(OVL_BA0(i));
+               RR(OVL_BA1(i));
+               RR(OVL_POSITION(i));
+               RR(OVL_SIZE(i));
+               RR(OVL_ATTRIBUTES(i));
+               RR(OVL_FIFO_THRESHOLD(i));
+               RR(OVL_ROW_INC(i));
+               RR(OVL_PIXEL_INC(i));
+               if (dss_has_feature(FEAT_PRELOAD))
+                       RR(OVL_PRELOAD(i));
+               if (i == OMAP_DSS_GFX) {
+                       RR(OVL_WINDOW_SKIP(i));
+                       RR(OVL_TABLE_BA(i));
+                       continue;
+               }
+               RR(OVL_FIR(i));
+               RR(OVL_PICTURE_SIZE(i));
+               RR(OVL_ACCU0(i));
+               RR(OVL_ACCU1(i));
 
-       for (i = 0; i < 8; i++)
-               RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, i));
+               for (j = 0; j < 8; j++)
+                       RR(OVL_FIR_COEF_H(i, j));
 
-       for (i = 0; i < 8; i++)
-               RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, i));
+               for (j = 0; j < 8; j++)
+                       RR(OVL_FIR_COEF_HV(i, j));
 
-       for (i = 0; i < 5; i++)
-               RR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i));
+               for (j = 0; j < 5; j++)
+                       RR(OVL_CONV_COEF(i, j));
 
-       if (dss_has_feature(FEAT_FIR_COEF_V)) {
-               for (i = 0; i < 8; i++)
-                       RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
-       }
+               if (dss_has_feature(FEAT_FIR_COEF_V)) {
+                       for (j = 0; j < 8; j++)
+                               RR(OVL_FIR_COEF_V(i, j));
+               }
 
-       if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
-               RR(OVL_BA0_UV(OMAP_DSS_VIDEO2));
-               RR(OVL_BA1_UV(OMAP_DSS_VIDEO2));
-               RR(OVL_FIR2(OMAP_DSS_VIDEO2));
-               RR(OVL_ACCU2_0(OMAP_DSS_VIDEO2));
-               RR(OVL_ACCU2_1(OMAP_DSS_VIDEO2));
+               if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
+                       RR(OVL_BA0_UV(i));
+                       RR(OVL_BA1_UV(i));
+                       RR(OVL_FIR2(i));
+                       RR(OVL_ACCU2_0(i));
+                       RR(OVL_ACCU2_1(i));
 
-               for (i = 0; i < 8; i++)
-                       RR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, i));
+                       for (j = 0; j < 8; j++)
+                               RR(OVL_FIR_COEF_H2(i, j));
 
-               for (i = 0; i < 8; i++)
-                       RR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, i));
+                       for (j = 0; j < 8; j++)
+                               RR(OVL_FIR_COEF_HV2(i, j));
 
-               for (i = 0; i < 8; i++)
-                       RR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, i));
+                       for (j = 0; j < 8; j++)
+                               RR(OVL_FIR_COEF_V2(i, j));
+               }
+               if (dss_has_feature(FEAT_ATTR2))
+                       RR(OVL_ATTRIBUTES2(i));
        }
-       if (dss_has_feature(FEAT_ATTR2))
-               RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
-
-       if (dss_has_feature(FEAT_PRELOAD))
-               RR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
 
        if (dss_has_feature(FEAT_CORE_CLK_DIV))
                RR(DIVISOR);
@@ -570,13 +420,28 @@ void dispc_runtime_put(void)
        WARN_ON(r < 0);
 }
 
+static inline bool dispc_mgr_is_lcd(enum omap_channel channel)
+{
+       if (channel == OMAP_DSS_CHANNEL_LCD ||
+                       channel == OMAP_DSS_CHANNEL_LCD2)
+               return true;
+       else
+               return false;
+}
+
+static struct omap_dss_device *dispc_mgr_get_device(enum omap_channel channel)
+{
+       struct omap_overlay_manager *mgr =
+               omap_dss_get_overlay_manager(channel);
 
-bool dispc_go_busy(enum omap_channel channel)
+       return mgr ? mgr->device : NULL;
+}
+
+bool dispc_mgr_go_busy(enum omap_channel channel)
 {
        int bit;
 
-       if (channel == OMAP_DSS_CHANNEL_LCD ||
-                       channel == OMAP_DSS_CHANNEL_LCD2)
+       if (dispc_mgr_is_lcd(channel))
                bit = 5; /* GOLCD */
        else
                bit = 6; /* GODIGIT */
@@ -587,13 +452,12 @@ bool dispc_go_busy(enum omap_channel channel)
                return REG_GET(DISPC_CONTROL, bit, bit) == 1;
 }
 
-void dispc_go(enum omap_channel channel)
+void dispc_mgr_go(enum omap_channel channel)
 {
        int bit;
        bool enable_bit, go_bit;
 
-       if (channel == OMAP_DSS_CHANNEL_LCD ||
-                       channel == OMAP_DSS_CHANNEL_LCD2)
+       if (dispc_mgr_is_lcd(channel))
                bit = 0; /* LCDENABLE */
        else
                bit = 1; /* DIGITALENABLE */
@@ -607,8 +471,7 @@ void dispc_go(enum omap_channel channel)
        if (!enable_bit)
                return;
 
-       if (channel == OMAP_DSS_CHANNEL_LCD ||
-                       channel == OMAP_DSS_CHANNEL_LCD2)
+       if (dispc_mgr_is_lcd(channel))
                bit = 5; /* GOLCD */
        else
                bit = 6; /* GODIGIT */
@@ -632,43 +495,44 @@ void dispc_go(enum omap_channel channel)
                REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
 }
 
-static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value)
+static void dispc_ovl_write_firh_reg(enum omap_plane plane, int reg, u32 value)
 {
        dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value);
 }
 
-static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value)
+static void dispc_ovl_write_firhv_reg(enum omap_plane plane, int reg, u32 value)
 {
        dispc_write_reg(DISPC_OVL_FIR_COEF_HV(plane, reg), value);
 }
 
-static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value)
+static void dispc_ovl_write_firv_reg(enum omap_plane plane, int reg, u32 value)
 {
        dispc_write_reg(DISPC_OVL_FIR_COEF_V(plane, reg), value);
 }
 
-static void _dispc_write_firh2_reg(enum omap_plane plane, int reg, u32 value)
+static void dispc_ovl_write_firh2_reg(enum omap_plane plane, int reg, u32 value)
 {
        BUG_ON(plane == OMAP_DSS_GFX);
 
        dispc_write_reg(DISPC_OVL_FIR_COEF_H2(plane, reg), value);
 }
 
-static void _dispc_write_firhv2_reg(enum omap_plane plane, int reg, u32 value)
+static void dispc_ovl_write_firhv2_reg(enum omap_plane plane, int reg,
+               u32 value)
 {
        BUG_ON(plane == OMAP_DSS_GFX);
 
        dispc_write_reg(DISPC_OVL_FIR_COEF_HV2(plane, reg), value);
 }
 
-static void _dispc_write_firv2_reg(enum omap_plane plane, int reg, u32 value)
+static void dispc_ovl_write_firv2_reg(enum omap_plane plane, int reg, u32 value)
 {
        BUG_ON(plane == OMAP_DSS_GFX);
 
        dispc_write_reg(DISPC_OVL_FIR_COEF_V2(plane, reg), value);
 }
 
-static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
+static void dispc_ovl_set_scale_coef(enum omap_plane plane, int hscaleup,
                                  int vscaleup, int five_taps,
                                  enum omap_color_component color_comp)
 {
@@ -769,11 +633,11 @@ static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
                        | FLD_VAL(v_coef[i].vc2, 31, 24);
 
                if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) {
-                       _dispc_write_firh_reg(plane, i, h);
-                       _dispc_write_firhv_reg(plane, i, hv);
+                       dispc_ovl_write_firh_reg(plane, i, h);
+                       dispc_ovl_write_firhv_reg(plane, i, hv);
                } else {
-                       _dispc_write_firh2_reg(plane, i, h);
-                       _dispc_write_firhv2_reg(plane, i, hv);
+                       dispc_ovl_write_firh2_reg(plane, i, h);
+                       dispc_ovl_write_firhv2_reg(plane, i, hv);
                }
 
        }
@@ -784,15 +648,16 @@ static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
                        v = FLD_VAL(v_coef[i].vc00, 7, 0)
                                | FLD_VAL(v_coef[i].vc22, 15, 8);
                        if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y)
-                               _dispc_write_firv_reg(plane, i, v);
+                               dispc_ovl_write_firv_reg(plane, i, v);
                        else
-                               _dispc_write_firv2_reg(plane, i, v);
+                               dispc_ovl_write_firv2_reg(plane, i, v);
                }
        }
 }
 
 static void _dispc_setup_color_conv_coef(void)
 {
+       int i;
        const struct color_conv_coef {
                int  ry,  rcr,  rcb,   gy,  gcr,  gcb,   by,  bcr,  bcb;
                int  full_range;
@@ -806,65 +671,54 @@ static void _dispc_setup_color_conv_coef(void)
 
        ct = &ctbl_bt601_5;
 
-       dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0),
-               CVAL(ct->rcr, ct->ry));
-       dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1),
-               CVAL(ct->gy,  ct->rcb));
-       dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2),
-               CVAL(ct->gcb, ct->gcr));
-       dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3),
-               CVAL(ct->bcr, ct->by));
-       dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4),
-               CVAL(0, ct->bcb));
-
-       dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0),
-               CVAL(ct->rcr, ct->ry));
-       dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1),
-               CVAL(ct->gy, ct->rcb));
-       dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2),
-               CVAL(ct->gcb, ct->gcr));
-       dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3),
-               CVAL(ct->bcr, ct->by));
-       dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4),
-               CVAL(0, ct->bcb));
+       for (i = 1; i < dss_feat_get_num_ovls(); i++) {
+               dispc_write_reg(DISPC_OVL_CONV_COEF(i, 0),
+                       CVAL(ct->rcr, ct->ry));
+               dispc_write_reg(DISPC_OVL_CONV_COEF(i, 1),
+                       CVAL(ct->gy,  ct->rcb));
+               dispc_write_reg(DISPC_OVL_CONV_COEF(i, 2),
+                       CVAL(ct->gcb, ct->gcr));
+               dispc_write_reg(DISPC_OVL_CONV_COEF(i, 3),
+                       CVAL(ct->bcr, ct->by));
+               dispc_write_reg(DISPC_OVL_CONV_COEF(i, 4),
+                       CVAL(0, ct->bcb));
 
-#undef CVAL
+               REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), ct->full_range,
+                       11, 11);
+       }
 
-       REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO1),
-               ct->full_range, 11, 11);
-       REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO2),
-               ct->full_range, 11, 11);
+#undef CVAL
 }
 
 
-static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr)
+static void dispc_ovl_set_ba0(enum omap_plane plane, u32 paddr)
 {
        dispc_write_reg(DISPC_OVL_BA0(plane), paddr);
 }
 
-static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr)
+static void dispc_ovl_set_ba1(enum omap_plane plane, u32 paddr)
 {
        dispc_write_reg(DISPC_OVL_BA1(plane), paddr);
 }
 
-static void _dispc_set_plane_ba0_uv(enum omap_plane plane, u32 paddr)
+static void dispc_ovl_set_ba0_uv(enum omap_plane plane, u32 paddr)
 {
        dispc_write_reg(DISPC_OVL_BA0_UV(plane), paddr);
 }
 
-static void _dispc_set_plane_ba1_uv(enum omap_plane plane, u32 paddr)
+static void dispc_ovl_set_ba1_uv(enum omap_plane plane, u32 paddr)
 {
        dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr);
 }
 
-static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y)
+static void dispc_ovl_set_pos(enum omap_plane plane, int x, int y)
 {
        u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
 
        dispc_write_reg(DISPC_OVL_POSITION(plane), val);
 }
 
-static void _dispc_set_pic_size(enum omap_plane plane, int width, int height)
+static void dispc_ovl_set_pic_size(enum omap_plane plane, int width, int height)
 {
        u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
 
@@ -874,7 +728,7 @@ static void _dispc_set_pic_size(enum omap_plane plane, int width, int height)
                dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);
 }
 
-static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)
+static void dispc_ovl_set_vid_size(enum omap_plane plane, int width, int height)
 {
        u32 val;
 
@@ -885,44 +739,61 @@ static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)
        dispc_write_reg(DISPC_OVL_SIZE(plane), val);
 }
 
-static void _dispc_set_pre_mult_alpha(enum omap_plane plane, bool enable)
+static void dispc_ovl_set_zorder(enum omap_plane plane, u8 zorder)
 {
-       if (!dss_has_feature(FEAT_PRE_MULT_ALPHA))
+       struct omap_overlay *ovl = omap_dss_get_overlay(plane);
+
+       if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
                return;
 
-       if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
-               plane == OMAP_DSS_VIDEO1)
+       REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26);
+}
+
+static void dispc_ovl_enable_zorder_planes(void)
+{
+       int i;
+
+       if (!dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
                return;
 
-       REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28);
+       for (i = 0; i < dss_feat_get_num_ovls(); i++)
+               REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25);
 }
 
-static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha)
+static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane, bool enable)
 {
-       if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
+       struct omap_overlay *ovl = omap_dss_get_overlay(plane);
+
+       if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
                return;
 
-       if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
-               plane == OMAP_DSS_VIDEO1)
+       REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28);
+}
+
+static void dispc_ovl_setup_global_alpha(enum omap_plane plane, u8 global_alpha)
+{
+       static const unsigned shifts[] = { 0, 8, 16, 24, };
+       int shift;
+       struct omap_overlay *ovl = omap_dss_get_overlay(plane);
+
+       if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
                return;
 
-       if (plane == OMAP_DSS_GFX)
-               REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0);
-       else if (plane == OMAP_DSS_VIDEO2)
-               REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 23, 16);
+       shift = shifts[plane];
+       REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, shift + 7, shift);
 }
 
-static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc)
+static void dispc_ovl_set_pix_inc(enum omap_plane plane, s32 inc)
 {
        dispc_write_reg(DISPC_OVL_PIXEL_INC(plane), inc);
 }
 
-static void _dispc_set_row_inc(enum omap_plane plane, s32 inc)
+static void dispc_ovl_set_row_inc(enum omap_plane plane, s32 inc)
 {
        dispc_write_reg(DISPC_OVL_ROW_INC(plane), inc);
 }
 
-static void _dispc_set_color_mode(enum omap_plane plane,
+static void dispc_ovl_set_color_mode(enum omap_plane plane,
                enum omap_color_mode color_mode)
 {
        u32 m = 0;
@@ -1003,7 +874,7 @@ static void _dispc_set_color_mode(enum omap_plane plane,
        REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
 }
 
-void dispc_set_channel_out(enum omap_plane plane,
+static void dispc_ovl_set_channel_out(enum omap_plane plane,
                enum omap_channel channel)
 {
        int shift;
@@ -1016,6 +887,7 @@ void dispc_set_channel_out(enum omap_plane plane,
                break;
        case OMAP_DSS_VIDEO1:
        case OMAP_DSS_VIDEO2:
+       case OMAP_DSS_VIDEO3:
                shift = 16;
                break;
        default:
@@ -1050,24 +922,13 @@ void dispc_set_channel_out(enum omap_plane plane,
        dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
 }
 
-static void dispc_set_burst_size(enum omap_plane plane,
+static void dispc_ovl_set_burst_size(enum omap_plane plane,
                enum omap_burst_size burst_size)
 {
+       static const unsigned shifts[] = { 6, 14, 14, 14, };
        int shift;
 
-       switch (plane) {
-       case OMAP_DSS_GFX:
-               shift = 6;
-               break;
-       case OMAP_DSS_VIDEO1:
-       case OMAP_DSS_VIDEO2:
-               shift = 14;
-               break;
-       default:
-               BUG();
-               return;
-       }
-
+       shift = shifts[plane];
        REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), burst_size, shift + 1, shift);
 }
 
@@ -1078,10 +939,10 @@ static void dispc_configure_burst_sizes(void)
 
        /* Configure burst size always to maximum size */
        for (i = 0; i < omap_dss_get_num_overlays(); ++i)
-               dispc_set_burst_size(i, burst_size);
+               dispc_ovl_set_burst_size(i, burst_size);
 }
 
-u32 dispc_get_burst_size(enum omap_plane plane)
+u32 dispc_ovl_get_burst_size(enum omap_plane plane)
 {
        unsigned unit = dss_feat_get_burst_size_unit();
        /* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */
@@ -1102,7 +963,7 @@ void dispc_enable_gamma_table(bool enable)
        REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9);
 }
 
-void dispc_enable_cpr(enum omap_channel channel, bool enable)
+void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable)
 {
        u16 reg;
 
@@ -1116,12 +977,12 @@ void dispc_enable_cpr(enum omap_channel channel, bool enable)
        REG_FLD_MOD(reg, enable, 15, 15);
 }
 
-void dispc_set_cpr_coef(enum omap_channel channel,
+void dispc_mgr_set_cpr_coef(enum omap_channel channel,
                struct omap_dss_cpr_coefs *coefs)
 {
        u32 coef_r, coef_g, coef_b;
 
-       if (channel != OMAP_DSS_CHANNEL_LCD && channel != OMAP_DSS_CHANNEL_LCD2)
+       if (!dispc_mgr_is_lcd(channel))
                return;
 
        coef_r = FLD_VAL(coefs->rr, 31, 22) | FLD_VAL(coefs->rg, 20, 11) |
@@ -1136,7 +997,7 @@ void dispc_set_cpr_coef(enum omap_channel channel,
        dispc_write_reg(DISPC_CPR_COEF_B(channel), coef_b);
 }
 
-static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
+static void dispc_ovl_set_vid_color_conv(enum omap_plane plane, bool enable)
 {
        u32 val;
 
@@ -1147,19 +1008,16 @@ static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
        dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
 }
 
-void dispc_enable_replication(enum omap_plane plane, bool enable)
+static void dispc_ovl_enable_replication(enum omap_plane plane, bool enable)
 {
-       int bit;
-
-       if (plane == OMAP_DSS_GFX)
-               bit = 5;
-       else
-               bit = 10;
+       static const unsigned shifts[] = { 5, 10, 10, 10 };
+       int shift;
 
-       REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit);
+       shift = shifts[plane];
+       REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift);
 }
 
-void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
+void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
 {
        u32 val;
        BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
@@ -1186,19 +1044,20 @@ static void dispc_read_plane_fifo_sizes(void)
 
        dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
 
-       for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
+       for (plane = 0; plane < dss_feat_get_num_ovls(); ++plane) {
                size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(plane), start, end);
                size *= unit;
                dispc.fifo_size[plane] = size;
        }
 }
 
-u32 dispc_get_plane_fifo_size(enum omap_plane plane)
+u32 dispc_ovl_get_fifo_size(enum omap_plane plane)
 {
        return dispc.fifo_size[plane];
 }
 
-void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
+static void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low,
+               u32 high)
 {
        u8 hi_start, hi_end, lo_start, lo_end;
        u32 unit;
@@ -1233,7 +1092,7 @@ void dispc_enable_fifomerge(bool enable)
        REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
 }
 
-static void _dispc_set_fir(enum omap_plane plane,
+static void dispc_ovl_set_fir(enum omap_plane plane,
                                int hinc, int vinc,
                                enum omap_color_component color_comp)
 {
@@ -1256,7 +1115,7 @@ static void _dispc_set_fir(enum omap_plane plane,
        }
 }
 
-static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
+static void dispc_ovl_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
 {
        u32 val;
        u8 hor_start, hor_end, vert_start, vert_end;
@@ -1270,7 +1129,7 @@ static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
        dispc_write_reg(DISPC_OVL_ACCU0(plane), val);
 }
 
-static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
+static void dispc_ovl_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
 {
        u32 val;
        u8 hor_start, hor_end, vert_start, vert_end;
@@ -1284,7 +1143,8 @@ static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
        dispc_write_reg(DISPC_OVL_ACCU1(plane), val);
 }
 
-static void _dispc_set_vid_accu2_0(enum omap_plane plane, int haccu, int vaccu)
+static void dispc_ovl_set_vid_accu2_0(enum omap_plane plane, int haccu,
+               int vaccu)
 {
        u32 val;
 
@@ -1292,7 +1152,8 @@ static void _dispc_set_vid_accu2_0(enum omap_plane plane, int haccu, int vaccu)
        dispc_write_reg(DISPC_OVL_ACCU2_0(plane), val);
 }
 
-static void _dispc_set_vid_accu2_1(enum omap_plane plane, int haccu, int vaccu)
+static void dispc_ovl_set_vid_accu2_1(enum omap_plane plane, int haccu,
+               int vaccu)
 {
        u32 val;
 
@@ -1300,7 +1161,7 @@ static void _dispc_set_vid_accu2_1(enum omap_plane plane, int haccu, int vaccu)
        dispc_write_reg(DISPC_OVL_ACCU2_1(plane), val);
 }
 
-static void _dispc_set_scale_param(enum omap_plane plane,
+static void dispc_ovl_set_scale_param(enum omap_plane plane,
                u16 orig_width, u16 orig_height,
                u16 out_width, u16 out_height,
                bool five_taps, u8 rotation,
@@ -1312,15 +1173,16 @@ static void _dispc_set_scale_param(enum omap_plane plane,
        hscaleup = orig_width <= out_width;
        vscaleup = orig_height <= out_height;
 
-       _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps, color_comp);
+       dispc_ovl_set_scale_coef(plane, hscaleup, vscaleup, five_taps,
+                       color_comp);
 
        fir_hinc = 1024 * orig_width / out_width;
        fir_vinc = 1024 * orig_height / out_height;
 
-       _dispc_set_fir(plane, fir_hinc, fir_vinc, color_comp);
+       dispc_ovl_set_fir(plane, fir_hinc, fir_vinc, color_comp);
 }
 
-static void _dispc_set_scaling_common(enum omap_plane plane,
+static void dispc_ovl_set_scaling_common(enum omap_plane plane,
                u16 orig_width, u16 orig_height,
                u16 out_width, u16 out_height,
                bool ilace, bool five_taps,
@@ -1331,7 +1193,7 @@ static void _dispc_set_scaling_common(enum omap_plane plane,
        int accu1 = 0;
        u32 l;
 
-       _dispc_set_scale_param(plane, orig_width, orig_height,
+       dispc_ovl_set_scale_param(plane, orig_width, orig_height,
                                out_width, out_height, five_taps,
                                rotation, DISPC_COLOR_COMPONENT_RGB_Y);
        l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
@@ -1370,11 +1232,11 @@ static void _dispc_set_scaling_common(enum omap_plane plane,
                }
        }
 
-       _dispc_set_vid_accu0(plane, 0, accu0);
-       _dispc_set_vid_accu1(plane, 0, accu1);
+       dispc_ovl_set_vid_accu0(plane, 0, accu0);
+       dispc_ovl_set_vid_accu1(plane, 0, accu1);
 }
 
-static void _dispc_set_scaling_uv(enum omap_plane plane,
+static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
                u16 orig_width, u16 orig_height,
                u16 out_width, u16 out_height,
                bool ilace, bool five_taps,
@@ -1422,7 +1284,7 @@ static void _dispc_set_scaling_uv(enum omap_plane plane,
        if (out_height != orig_height)
                scale_y = true;
 
-       _dispc_set_scale_param(plane, orig_width, orig_height,
+       dispc_ovl_set_scale_param(plane, orig_width, orig_height,
                        out_width, out_height, five_taps,
                                rotation, DISPC_COLOR_COMPONENT_UV);
 
@@ -1433,11 +1295,11 @@ static void _dispc_set_scaling_uv(enum omap_plane plane,
        /* set V scaling */
        REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6);
 
-       _dispc_set_vid_accu2_0(plane, 0x80, 0);
-       _dispc_set_vid_accu2_1(plane, 0x80, 0);
+       dispc_ovl_set_vid_accu2_0(plane, 0x80, 0);
+       dispc_ovl_set_vid_accu2_1(plane, 0x80, 0);
 }
 
-static void _dispc_set_scaling(enum omap_plane plane,
+static void dispc_ovl_set_scaling(enum omap_plane plane,
                u16 orig_width, u16 orig_height,
                u16 out_width, u16 out_height,
                bool ilace, bool five_taps,
@@ -1446,14 +1308,14 @@ static void _dispc_set_scaling(enum omap_plane plane,
 {
        BUG_ON(plane == OMAP_DSS_GFX);
 
-       _dispc_set_scaling_common(plane,
+       dispc_ovl_set_scaling_common(plane,
                        orig_width, orig_height,
                        out_width, out_height,
                        ilace, five_taps,
                        fieldmode, color_mode,
                        rotation);
 
-       _dispc_set_scaling_uv(plane,
+       dispc_ovl_set_scaling_uv(plane,
                orig_width, orig_height,
                out_width, out_height,
                ilace, five_taps,
@@ -1461,7 +1323,7 @@ static void _dispc_set_scaling(enum omap_plane plane,
                rotation);
 }
 
-static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
+static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation,
                bool mirroring, enum omap_color_mode color_mode)
 {
        bool row_repeat = false;
@@ -1789,12 +1651,11 @@ static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width,
                enum omap_color_mode color_mode)
 {
        u32 fclk = 0;
-       /* FIXME venc pclk? */
-       u64 tmp, pclk = dispc_pclk_rate(channel);
+       u64 tmp, pclk = dispc_mgr_pclk_rate(channel);
 
        if (height > out_height) {
-               /* FIXME get real display PPL */
-               unsigned int ppl = 800;
+               struct omap_dss_device *dssdev = dispc_mgr_get_device(channel);
+               unsigned int ppl = dssdev->panel.timings.x_res;
 
                tmp = pclk * height * out_width;
                do_div(tmp, 2 * out_height * ppl);
@@ -1846,114 +1707,120 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
        else
                vf = 1;
 
-       /* FIXME venc pclk? */
-       return dispc_pclk_rate(channel) * vf * hf;
+       return dispc_mgr_pclk_rate(channel) * vf * hf;
 }
 
-int dispc_setup_plane(enum omap_plane plane,
-               u32 paddr, u16 screen_width,
-               u16 pos_x, u16 pos_y,
-               u16 width, u16 height,
+static int dispc_ovl_calc_scaling(enum omap_plane plane,
+               enum omap_channel channel, u16 width, u16 height,
                u16 out_width, u16 out_height,
-               enum omap_color_mode color_mode,
-               bool ilace,
-               enum omap_dss_rotation_type rotation_type,
-               u8 rotation, bool mirror,
-               u8 global_alpha, u8 pre_mult_alpha,
-               enum omap_channel channel, u32 puv_addr)
-{
-       const int maxdownscale = cpu_is_omap34xx() ? 4 : 2;
-       bool five_taps = 0;
-       bool fieldmode = 0;
-       int cconv = 0;
-       unsigned offset0, offset1;
-       s32 row_inc;
-       s32 pix_inc;
-       u16 frame_height = height;
-       unsigned int field_offset = 0;
+               enum omap_color_mode color_mode, bool *five_taps)
+{
+       struct omap_overlay *ovl = omap_dss_get_overlay(plane);
+       const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
+       unsigned long fclk = 0;
 
-       DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> "
-              "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n",
-              plane, paddr, screen_width, pos_x, pos_y,
-              width, height,
-              out_width, out_height,
-              ilace, color_mode,
-              rotation, mirror, channel);
+       if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
+               if (width != out_width || height != out_height)
+                       return -EINVAL;
+               else
+                       return 0;
+       }
 
-       if (paddr == 0)
+       if (out_width < width / maxdownscale ||
+                       out_width > width * 8)
                return -EINVAL;
 
-       if (ilace && height == out_height)
-               fieldmode = 1;
+       if (out_height < height / maxdownscale ||
+                       out_height > height * 8)
+               return -EINVAL;
 
-       if (ilace) {
-               if (fieldmode)
-                       height /= 2;
-               pos_y /= 2;
-               out_height /= 2;
+       /* Must use 5-tap filter? */
+       *five_taps = height > out_height * 2;
 
-               DSSDBG("adjusting for ilace: height %d, pos_y %d, "
-                               "out_height %d\n",
-                               height, pos_y, out_height);
+       if (!*five_taps) {
+               fclk = calc_fclk(channel, width, height, out_width,
+                               out_height);
+
+               /* Try 5-tap filter if 3-tap fclk is too high */
+               if (cpu_is_omap34xx() && height > out_height &&
+                               fclk > dispc_fclk_rate())
+                       *five_taps = true;
        }
 
-       if (!dss_feat_color_mode_supported(plane, color_mode))
+       if (width > (2048 >> *five_taps)) {
+               DSSERR("failed to set up scaling, fclk too low\n");
                return -EINVAL;
+       }
 
-       if (plane == OMAP_DSS_GFX) {
-               if (width != out_width || height != out_height)
-                       return -EINVAL;
-       } else {
-               /* video plane */
+       if (*five_taps)
+               fclk = calc_fclk_five_taps(channel, width, height,
+                               out_width, out_height, color_mode);
 
-               unsigned long fclk = 0;
+       DSSDBG("required fclk rate = %lu Hz\n", fclk);
+       DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
 
-               if (out_width < width / maxdownscale ||
-                  out_width > width * 8)
-                       return -EINVAL;
+       if (!fclk || fclk > dispc_fclk_rate()) {
+               DSSERR("failed to set up scaling, "
+                       "required fclk rate = %lu Hz, "
+                       "current fclk rate = %lu Hz\n",
+                       fclk, dispc_fclk_rate());
+               return -EINVAL;
+       }
 
-               if (out_height < height / maxdownscale ||
-                  out_height > height * 8)
-                       return -EINVAL;
+       return 0;
+}
 
-               if (color_mode == OMAP_DSS_COLOR_YUV2 ||
-                       color_mode == OMAP_DSS_COLOR_UYVY ||
-                       color_mode == OMAP_DSS_COLOR_NV12)
-                       cconv = 1;
+int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
+               bool ilace, enum omap_channel channel, bool replication,
+               u32 fifo_low, u32 fifo_high)
+{
+       struct omap_overlay *ovl = omap_dss_get_overlay(plane);
+       bool five_taps = false;
+       bool fieldmode = 0;
+       int r, cconv = 0;
+       unsigned offset0, offset1;
+       s32 row_inc;
+       s32 pix_inc;
+       u16 frame_height = oi->height;
+       unsigned int field_offset = 0;
 
-               /* Must use 5-tap filter? */
-               five_taps = height > out_height * 2;
+       DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> "
+               "%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d "
+               "fifo_low %d fifo high %d\n", plane, oi->paddr, oi->p_uv_addr,
+               oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
+               oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
+               oi->mirror, ilace, channel, replication, fifo_low, fifo_high);
 
-               if (!five_taps) {
-                       fclk = calc_fclk(channel, width, height, out_width,
-                                       out_height);
+       if (oi->paddr == 0)
+               return -EINVAL;
 
-                       /* Try 5-tap filter if 3-tap fclk is too high */
-                       if (cpu_is_omap34xx() && height > out_height &&
-                                       fclk > dispc_fclk_rate())
-                               five_taps = true;
-               }
+       if (ilace && oi->height == oi->out_height)
+               fieldmode = 1;
 
-               if (width > (2048 >> five_taps)) {
-                       DSSERR("failed to set up scaling, fclk too low\n");
-                       return -EINVAL;
-               }
+       if (ilace) {
+               if (fieldmode)
+                       oi->height /= 2;
+               oi->pos_y /= 2;
+               oi->out_height /= 2;
 
-               if (five_taps)
-                       fclk = calc_fclk_five_taps(channel, width, height,
-                                       out_width, out_height, color_mode);
+               DSSDBG("adjusting for ilace: height %d, pos_y %d, "
+                               "out_height %d\n",
+                               oi->height, oi->pos_y, oi->out_height);
+       }
 
-               DSSDBG("required fclk rate = %lu Hz\n", fclk);
-               DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
+       if (!dss_feat_color_mode_supported(plane, oi->color_mode))
+               return -EINVAL;
 
-               if (!fclk || fclk > dispc_fclk_rate()) {
-                       DSSERR("failed to set up scaling, "
-                                       "required fclk rate = %lu Hz, "
-                                       "current fclk rate = %lu Hz\n",
-                                       fclk, dispc_fclk_rate());
-                       return -EINVAL;
-               }
-       }
+       r = dispc_ovl_calc_scaling(plane, channel, oi->width, oi->height,
+                       oi->out_width, oi->out_height, oi->color_mode,
+                       &five_taps);
+       if (r)
+               return r;
+
+       if (oi->color_mode == OMAP_DSS_COLOR_YUV2 ||
+                       oi->color_mode == OMAP_DSS_COLOR_UYVY ||
+                       oi->color_mode == OMAP_DSS_COLOR_NV12)
+               cconv = 1;
 
        if (ilace && !fieldmode) {
                /*
@@ -1963,69 +1830,76 @@ int dispc_setup_plane(enum omap_plane plane,
                 * so the integer part must be added to the base address of the
                 * bottom field.
                 */
-               if (!height || height == out_height)
+               if (!oi->height || oi->height == oi->out_height)
                        field_offset = 0;
                else
-                       field_offset = height / out_height / 2;
+                       field_offset = oi->height / oi->out_height / 2;
        }
 
        /* Fields are independent but interleaved in memory. */
        if (fieldmode)
                field_offset = 1;
 
-       if (rotation_type == OMAP_DSS_ROT_DMA)
-               calc_dma_rotation_offset(rotation, mirror,
-                               screen_width, width, frame_height, color_mode,
-                               fieldmode, field_offset,
+       if (oi->rotation_type == OMAP_DSS_ROT_DMA)
+               calc_dma_rotation_offset(oi->rotation, oi->mirror,
+                               oi->screen_width, oi->width, frame_height,
+                               oi->color_mode, fieldmode, field_offset,
                                &offset0, &offset1, &row_inc, &pix_inc);
        else
-               calc_vrfb_rotation_offset(rotation, mirror,
-                               screen_width, width, frame_height, color_mode,
-                               fieldmode, field_offset,
+               calc_vrfb_rotation_offset(oi->rotation, oi->mirror,
+                               oi->screen_width, oi->width, frame_height,
+                               oi->color_mode, fieldmode, field_offset,
                                &offset0, &offset1, &row_inc, &pix_inc);
 
        DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
                        offset0, offset1, row_inc, pix_inc);
 
-       _dispc_set_color_mode(plane, color_mode);
+       dispc_ovl_set_color_mode(plane, oi->color_mode);
 
-       _dispc_set_plane_ba0(plane, paddr + offset0);
-       _dispc_set_plane_ba1(plane, paddr + offset1);
+       dispc_ovl_set_ba0(plane, oi->paddr + offset0);
+       dispc_ovl_set_ba1(plane, oi->paddr + offset1);
 
-       if (OMAP_DSS_COLOR_NV12 == color_mode) {
-               _dispc_set_plane_ba0_uv(plane, puv_addr + offset0);
-               _dispc_set_plane_ba1_uv(plane, puv_addr + offset1);
+       if (OMAP_DSS_COLOR_NV12 == oi->color_mode) {
+               dispc_ovl_set_ba0_uv(plane, oi->p_uv_addr + offset0);
+               dispc_ovl_set_ba1_uv(plane, oi->p_uv_addr + offset1);
        }
 
 
-       _dispc_set_row_inc(plane, row_inc);
-       _dispc_set_pix_inc(plane, pix_inc);
+       dispc_ovl_set_row_inc(plane, row_inc);
+       dispc_ovl_set_pix_inc(plane, pix_inc);
 
-       DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, width, height,
-                       out_width, out_height);
+       DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, oi->width,
+                       oi->height, oi->out_width, oi->out_height);
 
-       _dispc_set_plane_pos(plane, pos_x, pos_y);
+       dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y);
 
-       _dispc_set_pic_size(plane, width, height);
+       dispc_ovl_set_pic_size(plane, oi->width, oi->height);
 
-       if (plane != OMAP_DSS_GFX) {
-               _dispc_set_scaling(plane, width, height,
-                                  out_width, out_height,
+       if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) {
+               dispc_ovl_set_scaling(plane, oi->width, oi->height,
+                                  oi->out_width, oi->out_height,
                                   ilace, five_taps, fieldmode,
-                                  color_mode, rotation);
-               _dispc_set_vid_size(plane, out_width, out_height);
-               _dispc_set_vid_color_conv(plane, cconv);
+                                  oi->color_mode, oi->rotation);
+               dispc_ovl_set_vid_size(plane, oi->out_width, oi->out_height);
+               dispc_ovl_set_vid_color_conv(plane, cconv);
        }
 
-       _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode);
+       dispc_ovl_set_rotation_attrs(plane, oi->rotation, oi->mirror,
+                       oi->color_mode);
+
+       dispc_ovl_set_zorder(plane, oi->zorder);
+       dispc_ovl_set_pre_mult_alpha(plane, oi->pre_mult_alpha);
+       dispc_ovl_setup_global_alpha(plane, oi->global_alpha);
 
-       _dispc_set_pre_mult_alpha(plane, pre_mult_alpha);
-       _dispc_setup_global_alpha(plane, global_alpha);
+       dispc_ovl_set_channel_out(plane, channel);
+
+       dispc_ovl_enable_replication(plane, replication);
+       dispc_ovl_set_fifo_threshold(plane, fifo_low, fifo_high);
 
        return 0;
 }
 
-int dispc_enable_plane(enum omap_plane plane, bool enable)
+int dispc_ovl_enable(enum omap_plane plane, bool enable)
 {
        DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
 
@@ -2048,7 +1922,7 @@ static void _enable_lcd_out(enum omap_channel channel, bool enable)
                REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0);
 }
 
-static void dispc_enable_lcd_out(enum omap_channel channel, bool enable)
+static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable)
 {
        struct completion frame_done_completion;
        bool is_on;
@@ -2095,14 +1969,19 @@ static void _enable_digit_out(bool enable)
        REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
 }
 
-static void dispc_enable_digit_out(bool enable)
+static void dispc_mgr_enable_digit_out(bool enable)
 {
        struct completion frame_done_completion;
-       int r;
+       enum dss_hdmi_venc_clk_source_select src;
+       int r, i;
+       u32 irq_mask;
+       int num_irqs;
 
        if (REG_GET(DISPC_CONTROL, 1, 1) == enable)
                return;
 
+       src = dss_get_hdmi_venc_clk_source();
+
        if (enable) {
                unsigned long flags;
                /* When we enable digit output, we'll get an extra digit
@@ -2119,43 +1998,47 @@ static void dispc_enable_digit_out(bool enable)
         * wait for the extra sync losts */
        init_completion(&frame_done_completion);
 
+       if (src == DSS_HDMI_M_PCLK && enable == false) {
+               irq_mask = DISPC_IRQ_FRAMEDONETV;
+               num_irqs = 1;
+       } else {
+               irq_mask = DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD;
+               /* XXX I understand from TRM that we should only wait for the
+                * current field to complete. But it seems we have to wait for
+                * both fields */
+               num_irqs = 2;
+       }
+
        r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion,
-                       DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
+                       irq_mask);
        if (r)
-               DSSERR("failed to register EVSYNC isr\n");
+               DSSERR("failed to register %x isr\n", irq_mask);
 
        _enable_digit_out(enable);
 
-       /* XXX I understand from TRM that we should only wait for the
-        * current field to complete. But it seems we have to wait
-        * for both fields */
-       if (!wait_for_completion_timeout(&frame_done_completion,
-                               msecs_to_jiffies(100)))
-               DSSERR("timeout waiting for EVSYNC\n");
-
-       if (!wait_for_completion_timeout(&frame_done_completion,
-                               msecs_to_jiffies(100)))
-               DSSERR("timeout waiting for EVSYNC\n");
+       for (i = 0; i < num_irqs; ++i) {
+               if (!wait_for_completion_timeout(&frame_done_completion,
+                                       msecs_to_jiffies(100)))
+                       DSSERR("timeout waiting for digit out to %s\n",
+                                       enable ? "start" : "stop");
+       }
 
-       r = omap_dispc_unregister_isr(dispc_disable_isr,
-                       &frame_done_completion,
-                       DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
+       r = omap_dispc_unregister_isr(dispc_disable_isr, &frame_done_completion,
+                       irq_mask);
        if (r)
-               DSSERR("failed to unregister EVSYNC isr\n");
+               DSSERR("failed to unregister %x isr\n", irq_mask);
 
        if (enable) {
                unsigned long flags;
                spin_lock_irqsave(&dispc.irq_lock, flags);
-               dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
-               if (dss_has_feature(FEAT_MGR_LCD2))
-                       dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
+               dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST_DIGIT;
                dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
                _omap_dispc_set_irqs();
                spin_unlock_irqrestore(&dispc.irq_lock, flags);
        }
 }
 
-bool dispc_is_channel_enabled(enum omap_channel channel)
+bool dispc_mgr_is_enabled(enum omap_channel channel)
 {
        if (channel == OMAP_DSS_CHANNEL_LCD)
                return !!REG_GET(DISPC_CONTROL, 0, 0);
@@ -2167,13 +2050,12 @@ bool dispc_is_channel_enabled(enum omap_channel channel)
                BUG();
 }
 
-void dispc_enable_channel(enum omap_channel channel, bool enable)
+void dispc_mgr_enable(enum omap_channel channel, bool enable)
 {
-       if (channel == OMAP_DSS_CHANNEL_LCD ||
-                       channel == OMAP_DSS_CHANNEL_LCD2)
-               dispc_enable_lcd_out(channel, enable);
+       if (dispc_mgr_is_lcd(channel))
+               dispc_mgr_enable_lcd_out(channel, enable);
        else if (channel == OMAP_DSS_CHANNEL_DIGIT)
-               dispc_enable_digit_out(enable);
+               dispc_mgr_enable_digit_out(enable);
        else
                BUG();
 }
@@ -2202,7 +2084,7 @@ void dispc_pck_free_enable(bool enable)
        REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
 }
 
-void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable)
+void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable)
 {
        if (channel == OMAP_DSS_CHANNEL_LCD2)
                REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16);
@@ -2211,7 +2093,7 @@ void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable)
 }
 
 
-void dispc_set_lcd_display_type(enum omap_channel channel,
+void dispc_mgr_set_lcd_display_type(enum omap_channel channel,
                enum omap_lcd_display_type type)
 {
        int mode;
@@ -2242,12 +2124,12 @@ void dispc_set_loadmode(enum omap_dss_load_mode mode)
 }
 
 
-void dispc_set_default_color(enum omap_channel channel, u32 color)
+void dispc_mgr_set_default_color(enum omap_channel channel, u32 color)
 {
        dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color);
 }
 
-u32 dispc_get_default_color(enum omap_channel channel)
+u32 dispc_mgr_get_default_color(enum omap_channel channel)
 {
        u32 l;
 
@@ -2260,7 +2142,7 @@ u32 dispc_get_default_color(enum omap_channel channel)
        return l;
 }
 
-void dispc_set_trans_key(enum omap_channel ch,
+void dispc_mgr_set_trans_key(enum omap_channel ch,
                enum omap_dss_trans_key_type type,
                u32 trans_key)
 {
@@ -2274,7 +2156,7 @@ void dispc_set_trans_key(enum omap_channel ch,
        dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key);
 }
 
-void dispc_get_trans_key(enum omap_channel ch,
+void dispc_mgr_get_trans_key(enum omap_channel ch,
                enum omap_dss_trans_key_type *type,
                u32 *trans_key)
 {
@@ -2293,7 +2175,7 @@ void dispc_get_trans_key(enum omap_channel ch,
                *trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch));
 }
 
-void dispc_enable_trans_key(enum omap_channel ch, bool enable)
+void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable)
 {
        if (ch == OMAP_DSS_CHANNEL_LCD)
                REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
@@ -2302,39 +2184,36 @@ void dispc_enable_trans_key(enum omap_channel ch, bool enable)
        else /* OMAP_DSS_CHANNEL_LCD2 */
                REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10);
 }
-void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
+
+void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable)
 {
-       if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
+       if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
                return;
 
        if (ch == OMAP_DSS_CHANNEL_LCD)
                REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
        else if (ch == OMAP_DSS_CHANNEL_DIGIT)
                REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
-       else /* OMAP_DSS_CHANNEL_LCD2 */
-               REG_FLD_MOD(DISPC_CONFIG2, enable, 18, 18);
 }
-bool dispc_alpha_blending_enabled(enum omap_channel ch)
+
+bool dispc_mgr_alpha_fixed_zorder_enabled(enum omap_channel ch)
 {
        bool enabled;
 
-       if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
+       if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
                return false;
 
        if (ch == OMAP_DSS_CHANNEL_LCD)
                enabled = REG_GET(DISPC_CONFIG, 18, 18);
        else if (ch == OMAP_DSS_CHANNEL_DIGIT)
                enabled = REG_GET(DISPC_CONFIG, 19, 19);
-       else if (ch == OMAP_DSS_CHANNEL_LCD2)
-               enabled = REG_GET(DISPC_CONFIG2, 18, 18);
        else
                BUG();
 
        return enabled;
 }
 
-
-bool dispc_trans_key_enabled(enum omap_channel ch)
+bool dispc_mgr_trans_key_enabled(enum omap_channel ch)
 {
        bool enabled;
 
@@ -2351,7 +2230,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
 }
 
 
-void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
+void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
 {
        int code;
 
@@ -2379,46 +2258,41 @@ void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
                REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
 }
 
-void dispc_set_parallel_interface_mode(enum omap_channel channel,
-               enum omap_parallel_interface_mode mode)
+void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode)
 {
        u32 l;
-       int stallmode;
-       int gpout0 = 1;
-       int gpout1;
+       int gpout0, gpout1;
 
        switch (mode) {
-       case OMAP_DSS_PARALLELMODE_BYPASS:
-               stallmode = 0;
-               gpout1 = 1;
+       case DSS_IO_PAD_MODE_RESET:
+               gpout0 = 0;
+               gpout1 = 0;
                break;
-
-       case OMAP_DSS_PARALLELMODE_RFBI:
-               stallmode = 1;
+       case DSS_IO_PAD_MODE_RFBI:
+               gpout0 = 1;
                gpout1 = 0;
                break;
-
-       case OMAP_DSS_PARALLELMODE_DSI:
-               stallmode = 1;
+       case DSS_IO_PAD_MODE_BYPASS:
+               gpout0 = 1;
                gpout1 = 1;
                break;
-
        default:
                BUG();
                return;
        }
 
-       if (channel == OMAP_DSS_CHANNEL_LCD2) {
-               l = dispc_read_reg(DISPC_CONTROL2);
-               l = FLD_MOD(l, stallmode, 11, 11);
-               dispc_write_reg(DISPC_CONTROL2, l);
-       } else {
-               l = dispc_read_reg(DISPC_CONTROL);
-               l = FLD_MOD(l, stallmode, 11, 11);
-               l = FLD_MOD(l, gpout0, 15, 15);
-               l = FLD_MOD(l, gpout1, 16, 16);
-               dispc_write_reg(DISPC_CONTROL, l);
-       }
+       l = dispc_read_reg(DISPC_CONTROL);
+       l = FLD_MOD(l, gpout0, 15, 15);
+       l = FLD_MOD(l, gpout1, 16, 16);
+       dispc_write_reg(DISPC_CONTROL, l);
+}
+
+void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable)
+{
+       if (channel == OMAP_DSS_CHANNEL_LCD2)
+               REG_FLD_MOD(DISPC_CONTROL2, enable, 11, 11);
+       else
+               REG_FLD_MOD(DISPC_CONTROL, enable, 11, 11);
 }
 
 static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
@@ -2452,7 +2326,7 @@ bool dispc_lcd_timings_ok(struct omap_video_timings *timings)
                        timings->vfp, timings->vbp);
 }
 
-static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw,
+static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
                int hfp, int hbp, int vsw, int vfp, int vbp)
 {
        u32 timing_h, timing_v;
@@ -2476,7 +2350,7 @@ static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw,
 }
 
 /* change name to mode? */
-void dispc_set_lcd_timings(enum omap_channel channel,
+void dispc_mgr_set_lcd_timings(enum omap_channel channel,
                struct omap_video_timings *timings)
 {
        unsigned xtot, ytot;
@@ -2487,11 +2361,11 @@ void dispc_set_lcd_timings(enum omap_channel channel,
                                timings->vfp, timings->vbp))
                BUG();
 
-       _dispc_set_lcd_timings(channel, timings->hsw, timings->hfp,
+       _dispc_mgr_set_lcd_timings(channel, timings->hsw, timings->hfp,
                        timings->hbp, timings->vsw, timings->vfp,
                        timings->vbp);
 
-       dispc_set_lcd_size(channel, timings->x_res, timings->y_res);
+       dispc_mgr_set_lcd_size(channel, timings->x_res, timings->y_res);
 
        xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp;
        ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp;
@@ -2509,17 +2383,17 @@ void dispc_set_lcd_timings(enum omap_channel channel,
        DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt);
 }
 
-static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
+static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
                u16 pck_div)
 {
        BUG_ON(lck_div < 1);
-       BUG_ON(pck_div < 2);
+       BUG_ON(pck_div < 1);
 
        dispc_write_reg(DISPC_DIVISORo(channel),
                        FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
 }
 
-static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div,
+static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div,
                int *pck_div)
 {
        u32 l;
@@ -2552,7 +2426,7 @@ unsigned long dispc_fclk_rate(void)
        return r;
 }
 
-unsigned long dispc_lclk_rate(enum omap_channel channel)
+unsigned long dispc_mgr_lclk_rate(enum omap_channel channel)
 {
        struct platform_device *dsidev;
        int lcd;
@@ -2582,19 +2456,34 @@ unsigned long dispc_lclk_rate(enum omap_channel channel)
        return r / lcd;
 }
 
-unsigned long dispc_pclk_rate(enum omap_channel channel)
+unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
 {
-       int pcd;
        unsigned long r;
-       u32 l;
 
-       l = dispc_read_reg(DISPC_DIVISORo(channel));
+       if (dispc_mgr_is_lcd(channel)) {
+               int pcd;
+               u32 l;
 
-       pcd = FLD_GET(l, 7, 0);
+               l = dispc_read_reg(DISPC_DIVISORo(channel));
 
-       r = dispc_lclk_rate(channel);
+               pcd = FLD_GET(l, 7, 0);
 
-       return r / pcd;
+               r = dispc_mgr_lclk_rate(channel);
+
+               return r / pcd;
+       } else {
+               struct omap_dss_device *dssdev =
+                       dispc_mgr_get_device(channel);
+
+               switch (dssdev->type) {
+               case OMAP_DISPLAY_TYPE_VENC:
+                       return venc_get_pixel_clock();
+               case OMAP_DISPLAY_TYPE_HDMI:
+                       return hdmi_get_pixel_clock();
+               default:
+                       BUG();
+               }
+       }
 }
 
 void dispc_dump_clocks(struct seq_file *s)
@@ -2631,12 +2520,12 @@ void dispc_dump_clocks(struct seq_file *s)
                dss_get_generic_clk_source_name(lcd_clk_src),
                dss_feat_get_clk_source_name(lcd_clk_src));
 
-       dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd);
+       dispc_mgr_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd);
 
        seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
-                       dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD), lcd);
+                       dispc_mgr_lclk_rate(OMAP_DSS_CHANNEL_LCD), lcd);
        seq_printf(s, "pck\t\t%-16lupck div\t%u\n",
-                       dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD), pcd);
+                       dispc_mgr_pclk_rate(OMAP_DSS_CHANNEL_LCD), pcd);
        if (dss_has_feature(FEAT_MGR_LCD2)) {
                seq_printf(s, "- LCD2 -\n");
 
@@ -2646,12 +2535,12 @@ void dispc_dump_clocks(struct seq_file *s)
                        dss_get_generic_clk_source_name(lcd_clk_src),
                        dss_feat_get_clk_source_name(lcd_clk_src));
 
-               dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd);
+               dispc_mgr_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd);
 
                seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
-                               dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD2), lcd);
+                               dispc_mgr_lclk_rate(OMAP_DSS_CHANNEL_LCD2), lcd);
                seq_printf(s, "pck\t\t%-16lupck div\t%u\n",
-                               dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd);
+                               dispc_mgr_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd);
        }
 
        dispc_runtime_put();
@@ -2692,6 +2581,10 @@ void dispc_dump_irqs(struct seq_file *s)
        PIS(VID1_END_WIN);
        PIS(VID2_FIFO_UNDERFLOW);
        PIS(VID2_END_WIN);
+       if (dss_feat_get_num_ovls() > 3) {
+               PIS(VID3_FIFO_UNDERFLOW);
+               PIS(VID3_END_WIN);
+       }
        PIS(SYNC_LOST);
        PIS(SYNC_LOST_DIGIT);
        PIS(WAKEUP);
@@ -2707,11 +2600,26 @@ void dispc_dump_irqs(struct seq_file *s)
 
 void dispc_dump_regs(struct seq_file *s)
 {
+       int i, j;
+       const char *mgr_names[] = {
+               [OMAP_DSS_CHANNEL_LCD]          = "LCD",
+               [OMAP_DSS_CHANNEL_DIGIT]        = "TV",
+               [OMAP_DSS_CHANNEL_LCD2]         = "LCD2",
+       };
+       const char *ovl_names[] = {
+               [OMAP_DSS_GFX]          = "GFX",
+               [OMAP_DSS_VIDEO1]       = "VID1",
+               [OMAP_DSS_VIDEO2]       = "VID2",
+               [OMAP_DSS_VIDEO3]       = "VID3",
+       };
+       const char **p_names;
+
 #define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r))
 
        if (dispc_runtime_get())
                return;
 
+       /* DISPC common registers */
        DUMPREG(DISPC_REVISION);
        DUMPREG(DISPC_SYSCONFIG);
        DUMPREG(DISPC_SYSSTATUS);
@@ -2720,247 +2628,139 @@ void dispc_dump_regs(struct seq_file *s)
        DUMPREG(DISPC_CONTROL);
        DUMPREG(DISPC_CONFIG);
        DUMPREG(DISPC_CAPABLE);
-       DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD));
-       DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT));
-       DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_LCD));
-       DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT));
        DUMPREG(DISPC_LINE_STATUS);
        DUMPREG(DISPC_LINE_NUMBER);
-       DUMPREG(DISPC_TIMING_H(OMAP_DSS_CHANNEL_LCD));
-       DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD));
-       DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD));
-       DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD));
-       if (dss_has_feature(FEAT_GLOBAL_ALPHA))
+       if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) ||
+                       dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
                DUMPREG(DISPC_GLOBAL_ALPHA);
-       DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
-       DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
        if (dss_has_feature(FEAT_MGR_LCD2)) {
                DUMPREG(DISPC_CONTROL2);
                DUMPREG(DISPC_CONFIG2);
-               DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2));
-               DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2));
-               DUMPREG(DISPC_TIMING_H(OMAP_DSS_CHANNEL_LCD2));
-               DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD2));
-               DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD2));
-               DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD2));
-               DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD2));
-       }
-
-       DUMPREG(DISPC_OVL_BA0(OMAP_DSS_GFX));
-       DUMPREG(DISPC_OVL_BA1(OMAP_DSS_GFX));
-       DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_GFX));
-       DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_GFX));
-       DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_GFX));
-       DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_GFX));
-       DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_GFX));
-       DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_GFX));
-       DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_GFX));
-       DUMPREG(DISPC_OVL_WINDOW_SKIP(OMAP_DSS_GFX));
-       DUMPREG(DISPC_OVL_TABLE_BA(OMAP_DSS_GFX));
-
-       DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD));
-       DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
-       DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
-
-       if (dss_has_feature(FEAT_CPR)) {
-               DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
-               DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
-               DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
        }
-       if (dss_has_feature(FEAT_MGR_LCD2)) {
-               DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
-               DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
-               DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
+
+#undef DUMPREG
+
+#define DISPC_REG(i, name) name(i)
+#define DUMPREG(i, r) seq_printf(s, "%s(%s)%*s %08x\n", #r, p_names[i], \
+       48 - strlen(#r) - strlen(p_names[i]), " ", \
+       dispc_read_reg(DISPC_REG(i, r)))
+
+       p_names = mgr_names;
+
+       /* DISPC channel specific registers */
+       for (i = 0; i < dss_feat_get_num_mgrs(); i++) {
+               DUMPREG(i, DISPC_DEFAULT_COLOR);
+               DUMPREG(i, DISPC_TRANS_COLOR);
+               DUMPREG(i, DISPC_SIZE_MGR);
+
+               if (i == OMAP_DSS_CHANNEL_DIGIT)
+                       continue;
+
+               DUMPREG(i, DISPC_DEFAULT_COLOR);
+               DUMPREG(i, DISPC_TRANS_COLOR);
+               DUMPREG(i, DISPC_TIMING_H);
+               DUMPREG(i, DISPC_TIMING_V);
+               DUMPREG(i, DISPC_POL_FREQ);
+               DUMPREG(i, DISPC_DIVISORo);
+               DUMPREG(i, DISPC_SIZE_MGR);
+
+               DUMPREG(i, DISPC_DATA_CYCLE1);
+               DUMPREG(i, DISPC_DATA_CYCLE2);
+               DUMPREG(i, DISPC_DATA_CYCLE3);
 
                if (dss_has_feature(FEAT_CPR)) {
-                       DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
-                       DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
-                       DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
+                       DUMPREG(i, DISPC_CPR_COEF_R);
+                       DUMPREG(i, DISPC_CPR_COEF_G);
+                       DUMPREG(i, DISPC_CPR_COEF_B);
+               }
+       }
+
+       p_names = ovl_names;
+
+       for (i = 0; i < dss_feat_get_num_ovls(); i++) {
+               DUMPREG(i, DISPC_OVL_BA0);
+               DUMPREG(i, DISPC_OVL_BA1);
+               DUMPREG(i, DISPC_OVL_POSITION);
+               DUMPREG(i, DISPC_OVL_SIZE);
+               DUMPREG(i, DISPC_OVL_ATTRIBUTES);
+               DUMPREG(i, DISPC_OVL_FIFO_THRESHOLD);
+               DUMPREG(i, DISPC_OVL_FIFO_SIZE_STATUS);
+               DUMPREG(i, DISPC_OVL_ROW_INC);
+               DUMPREG(i, DISPC_OVL_PIXEL_INC);
+               if (dss_has_feature(FEAT_PRELOAD))
+                       DUMPREG(i, DISPC_OVL_PRELOAD);
+
+               if (i == OMAP_DSS_GFX) {
+                       DUMPREG(i, DISPC_OVL_WINDOW_SKIP);
+                       DUMPREG(i, DISPC_OVL_TABLE_BA);
+                       continue;
+               }
+
+               DUMPREG(i, DISPC_OVL_FIR);
+               DUMPREG(i, DISPC_OVL_PICTURE_SIZE);
+               DUMPREG(i, DISPC_OVL_ACCU0);
+               DUMPREG(i, DISPC_OVL_ACCU1);
+               if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
+                       DUMPREG(i, DISPC_OVL_BA0_UV);
+                       DUMPREG(i, DISPC_OVL_BA1_UV);
+                       DUMPREG(i, DISPC_OVL_FIR2);
+                       DUMPREG(i, DISPC_OVL_ACCU2_0);
+                       DUMPREG(i, DISPC_OVL_ACCU2_1);
                }
+               if (dss_has_feature(FEAT_ATTR2))
+                       DUMPREG(i, DISPC_OVL_ATTRIBUTES2);
+               if (dss_has_feature(FEAT_PRELOAD))
+                       DUMPREG(i, DISPC_OVL_PRELOAD);
        }
 
-       if (dss_has_feature(FEAT_PRELOAD))
-               DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX));
-
-       DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO1));
-       DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO1));
-       DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_VIDEO1));
-       DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_VIDEO1));
-       DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO1));
-       DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1));
-       DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_VIDEO1));
-       DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_VIDEO1));
-       DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_VIDEO1));
-       DUMPREG(DISPC_OVL_FIR(OMAP_DSS_VIDEO1));
-       DUMPREG(DISPC_OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1));
-       DUMPREG(DISPC_OVL_ACCU0(OMAP_DSS_VIDEO1));
-       DUMPREG(DISPC_OVL_ACCU1(OMAP_DSS_VIDEO1));
-
-       DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO2));
-       DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO2));
-       DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_VIDEO2));
-       DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_VIDEO2));
-       DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO2));
-       DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2));
-       DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_VIDEO2));
-       DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_VIDEO2));
-       DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_VIDEO2));
-       DUMPREG(DISPC_OVL_FIR(OMAP_DSS_VIDEO2));
-       DUMPREG(DISPC_OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2));
-       DUMPREG(DISPC_OVL_ACCU0(OMAP_DSS_VIDEO2));
-       DUMPREG(DISPC_OVL_ACCU1(OMAP_DSS_VIDEO2));
-
-       DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 0));
-       DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 1));
-       DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 2));
-       DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 3));
-       DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 4));
-       DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 5));
-       DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 6));
-       DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 7));
-       DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 0));
-       DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 1));
-       DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 2));
-       DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 3));
-       DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 4));
-       DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 5));
-       DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 6));
-       DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 7));
-       DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0));
-       DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1));
-       DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2));
-       DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3));
-       DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4));
-       if (dss_has_feature(FEAT_FIR_COEF_V)) {
-               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0));
-               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1));
-               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2));
-               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3));
-               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4));
-               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5));
-               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6));
-               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7));
-       }
-
-       if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
-               DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO1));
-               DUMPREG(DISPC_OVL_BA1_UV(OMAP_DSS_VIDEO1));
-               DUMPREG(DISPC_OVL_FIR2(OMAP_DSS_VIDEO1));
-               DUMPREG(DISPC_OVL_ACCU2_0(OMAP_DSS_VIDEO1));
-               DUMPREG(DISPC_OVL_ACCU2_1(OMAP_DSS_VIDEO1));
-
-               DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 0));
-               DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 1));
-               DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 2));
-               DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 3));
-               DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 4));
-               DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 5));
-               DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 6));
-               DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 7));
-
-               DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 0));
-               DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 1));
-               DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 2));
-               DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 3));
-               DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 4));
-               DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 5));
-               DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 6));
-               DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 7));
-
-               DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 0));
-               DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 1));
-               DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 2));
-               DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 3));
-               DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 4));
-               DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 5));
-               DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 6));
-               DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 7));
-       }
-       if (dss_has_feature(FEAT_ATTR2))
-               DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
-
-
-       DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 0));
-       DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 1));
-       DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 2));
-       DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 3));
-       DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 4));
-       DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 5));
-       DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 6));
-       DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 7));
-       DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 0));
-       DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 1));
-       DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 2));
-       DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 3));
-       DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 4));
-       DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 5));
-       DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 6));
-       DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 7));
-       DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0));
-       DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1));
-       DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2));
-       DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3));
-       DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4));
-
-       if (dss_has_feature(FEAT_FIR_COEF_V)) {
-               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0));
-               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1));
-               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2));
-               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3));
-               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4));
-               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5));
-               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6));
-               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7));
-       }
-
-       if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
-               DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO2));
-               DUMPREG(DISPC_OVL_BA1_UV(OMAP_DSS_VIDEO2));
-               DUMPREG(DISPC_OVL_FIR2(OMAP_DSS_VIDEO2));
-               DUMPREG(DISPC_OVL_ACCU2_0(OMAP_DSS_VIDEO2));
-               DUMPREG(DISPC_OVL_ACCU2_1(OMAP_DSS_VIDEO2));
-
-               DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 0));
-               DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 1));
-               DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 2));
-               DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 3));
-               DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 4));
-               DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 5));
-               DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 6));
-               DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 7));
-
-               DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 0));
-               DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 1));
-               DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 2));
-               DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 3));
-               DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 4));
-               DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 5));
-               DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 6));
-               DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 7));
-
-               DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 0));
-               DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 1));
-               DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 2));
-               DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 3));
-               DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 4));
-               DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 5));
-               DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 6));
-               DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 7));
-       }
-       if (dss_has_feature(FEAT_ATTR2))
-               DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
-
-       if (dss_has_feature(FEAT_PRELOAD)) {
-               DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1));
-               DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2));
+#undef DISPC_REG
+#undef DUMPREG
+
+#define DISPC_REG(plane, name, i) name(plane, i)
+#define DUMPREG(plane, name, i) \
+       seq_printf(s, "%s_%d(%s)%*s %08x\n", #name, i, p_names[plane], \
+       46 - strlen(#name) - strlen(p_names[plane]), " ", \
+       dispc_read_reg(DISPC_REG(plane, name, i)))
+
+       /* Video pipeline coefficient registers */
+
+       /* start from OMAP_DSS_VIDEO1 */
+       for (i = 1; i < dss_feat_get_num_ovls(); i++) {
+               for (j = 0; j < 8; j++)
+                       DUMPREG(i, DISPC_OVL_FIR_COEF_H, j);
+
+               for (j = 0; j < 8; j++)
+                       DUMPREG(i, DISPC_OVL_FIR_COEF_HV, j);
+
+               for (j = 0; j < 5; j++)
+                       DUMPREG(i, DISPC_OVL_CONV_COEF, j);
+
+               if (dss_has_feature(FEAT_FIR_COEF_V)) {
+                       for (j = 0; j < 8; j++)
+                               DUMPREG(i, DISPC_OVL_FIR_COEF_V, j);
+               }
+
+               if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
+                       for (j = 0; j < 8; j++)
+                               DUMPREG(i, DISPC_OVL_FIR_COEF_H2, j);
+
+                       for (j = 0; j < 8; j++)
+                               DUMPREG(i, DISPC_OVL_FIR_COEF_HV2, j);
+
+                       for (j = 0; j < 8; j++)
+                               DUMPREG(i, DISPC_OVL_FIR_COEF_V2, j);
+               }
        }
 
        dispc_runtime_put();
+
+#undef DISPC_REG
 #undef DUMPREG
 }
 
-static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf,
-               bool ieo, bool ipc, bool ihs, bool ivs, u8 acbi, u8 acb)
+static void _dispc_mgr_set_pol_freq(enum omap_channel channel, bool onoff,
+               bool rf, bool ieo, bool ipc, bool ihs, bool ivs, u8 acbi,
+               u8 acb)
 {
        u32 l = 0;
 
@@ -2979,10 +2779,10 @@ static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf,
        dispc_write_reg(DISPC_POL_FREQ(channel), l);
 }
 
-void dispc_set_pol_freq(enum omap_channel channel,
+void dispc_mgr_set_pol_freq(enum omap_channel channel,
                enum omap_panel_config config, u8 acbi, u8 acb)
 {
-       _dispc_set_pol_freq(channel, (config & OMAP_DSS_LCD_ONOFF) != 0,
+       _dispc_mgr_set_pol_freq(channel, (config & OMAP_DSS_LCD_ONOFF) != 0,
                        (config & OMAP_DSS_LCD_RF) != 0,
                        (config & OMAP_DSS_LCD_IEO) != 0,
                        (config & OMAP_DSS_LCD_IPC) != 0,
@@ -2995,11 +2795,17 @@ void dispc_set_pol_freq(enum omap_channel channel,
 void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
                struct dispc_clock_info *cinfo)
 {
-       u16 pcd_min = is_tft ? 2 : 3;
+       u16 pcd_min, pcd_max;
        unsigned long best_pck;
        u16 best_ld, cur_ld;
        u16 best_pd, cur_pd;
 
+       pcd_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD);
+       pcd_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD);
+
+       if (!is_tft)
+               pcd_min = 3;
+
        best_pck = 0;
        best_ld = 0;
        best_pd = 0;
@@ -3007,7 +2813,7 @@ void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
        for (cur_ld = 1; cur_ld <= 255; ++cur_ld) {
                unsigned long lck = fck / cur_ld;
 
-               for (cur_pd = pcd_min; cur_pd <= 255; ++cur_pd) {
+               for (cur_pd = pcd_min; cur_pd <= pcd_max; ++cur_pd) {
                        unsigned long pck = lck / cur_pd;
                        long old_delta = abs(best_pck - req_pck);
                        long new_delta = abs(pck - req_pck);
@@ -3042,7 +2848,7 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
 {
        if (cinfo->lck_div > 255 || cinfo->lck_div == 0)
                return -EINVAL;
-       if (cinfo->pck_div < 2 || cinfo->pck_div > 255)
+       if (cinfo->pck_div < 1 || cinfo->pck_div > 255)
                return -EINVAL;
 
        cinfo->lck = dispc_fclk_rate / cinfo->lck_div;
@@ -3051,18 +2857,18 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
        return 0;
 }
 
-int dispc_set_clock_div(enum omap_channel channel,
+int dispc_mgr_set_clock_div(enum omap_channel channel,
                struct dispc_clock_info *cinfo)
 {
        DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div);
        DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div);
 
-       dispc_set_lcd_divisor(channel, cinfo->lck_div, cinfo->pck_div);
+       dispc_mgr_set_lcd_divisor(channel, cinfo->lck_div, cinfo->pck_div);
 
        return 0;
 }
 
-int dispc_get_clock_div(enum omap_channel channel,
+int dispc_mgr_get_clock_div(enum omap_channel channel,
                struct dispc_clock_info *cinfo)
 {
        unsigned long fck;
@@ -3207,6 +3013,8 @@ static void print_irq_status(u32 status)
        PIS(OCP_ERR);
        PIS(VID1_FIFO_UNDERFLOW);
        PIS(VID2_FIFO_UNDERFLOW);
+       if (dss_feat_get_num_ovls() > 3)
+               PIS(VID3_FIFO_UNDERFLOW);
        PIS(SYNC_LOST);
        PIS(SYNC_LOST_DIGIT);
        if (dss_has_feature(FEAT_MGR_LCD2))
@@ -3300,178 +3108,72 @@ static void dispc_error_worker(struct work_struct *work)
        int i;
        u32 errors;
        unsigned long flags;
+       static const unsigned fifo_underflow_bits[] = {
+               DISPC_IRQ_GFX_FIFO_UNDERFLOW,
+               DISPC_IRQ_VID1_FIFO_UNDERFLOW,
+               DISPC_IRQ_VID2_FIFO_UNDERFLOW,
+               DISPC_IRQ_VID3_FIFO_UNDERFLOW,
+       };
+
+       static const unsigned sync_lost_bits[] = {
+               DISPC_IRQ_SYNC_LOST,
+               DISPC_IRQ_SYNC_LOST_DIGIT,
+               DISPC_IRQ_SYNC_LOST2,
+       };
 
        spin_lock_irqsave(&dispc.irq_lock, flags);
        errors = dispc.error_irqs;
        dispc.error_irqs = 0;
        spin_unlock_irqrestore(&dispc.irq_lock, flags);
 
-       if (errors & DISPC_IRQ_GFX_FIFO_UNDERFLOW) {
-               DSSERR("GFX_FIFO_UNDERFLOW, disabling GFX\n");
-               for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
-                       struct omap_overlay *ovl;
-                       ovl = omap_dss_get_overlay(i);
-
-                       if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
-                               continue;
-
-                       if (ovl->id == 0) {
-                               dispc_enable_plane(ovl->id, 0);
-                               dispc_go(ovl->manager->id);
-                               mdelay(50);
-                               break;
-                       }
-               }
-       }
-
-       if (errors & DISPC_IRQ_VID1_FIFO_UNDERFLOW) {
-               DSSERR("VID1_FIFO_UNDERFLOW, disabling VID1\n");
-               for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
-                       struct omap_overlay *ovl;
-                       ovl = omap_dss_get_overlay(i);
-
-                       if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
-                               continue;
-
-                       if (ovl->id == 1) {
-                               dispc_enable_plane(ovl->id, 0);
-                               dispc_go(ovl->manager->id);
-                               mdelay(50);
-                               break;
-                       }
-               }
-       }
-
-       if (errors & DISPC_IRQ_VID2_FIFO_UNDERFLOW) {
-               DSSERR("VID2_FIFO_UNDERFLOW, disabling VID2\n");
-               for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
-                       struct omap_overlay *ovl;
-                       ovl = omap_dss_get_overlay(i);
-
-                       if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
-                               continue;
+       dispc_runtime_get();
 
-                       if (ovl->id == 2) {
-                               dispc_enable_plane(ovl->id, 0);
-                               dispc_go(ovl->manager->id);
-                               mdelay(50);
-                               break;
-                       }
-               }
-       }
-
-       if (errors & DISPC_IRQ_SYNC_LOST) {
-               struct omap_overlay_manager *manager = NULL;
-               bool enable = false;
+       for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
+               struct omap_overlay *ovl;
+               unsigned bit;
 
-               DSSERR("SYNC_LOST, disabling LCD\n");
+               ovl = omap_dss_get_overlay(i);
+               bit = fifo_underflow_bits[i];
 
-               for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
-                       struct omap_overlay_manager *mgr;
-                       mgr = omap_dss_get_overlay_manager(i);
-
-                       if (mgr->id == OMAP_DSS_CHANNEL_LCD) {
-                               manager = mgr;
-                               enable = mgr->device->state ==
-                                               OMAP_DSS_DISPLAY_ACTIVE;
-                               mgr->device->driver->disable(mgr->device);
-                               break;
-                       }
-               }
-
-               if (manager) {
-                       struct omap_dss_device *dssdev = manager->device;
-                       for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
-                               struct omap_overlay *ovl;
-                               ovl = omap_dss_get_overlay(i);
-
-                               if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
-                                       continue;
-
-                               if (ovl->id != 0 && ovl->manager == manager)
-                                       dispc_enable_plane(ovl->id, 0);
-                       }
-
-                       dispc_go(manager->id);
+               if (bit & errors) {
+                       DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n",
+                                       ovl->name);
+                       dispc_ovl_enable(ovl->id, false);
+                       dispc_mgr_go(ovl->manager->id);
                        mdelay(50);
-                       if (enable)
-                               dssdev->driver->enable(dssdev);
                }
        }
 
-       if (errors & DISPC_IRQ_SYNC_LOST_DIGIT) {
-               struct omap_overlay_manager *manager = NULL;
-               bool enable = false;
+       for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
+               struct omap_overlay_manager *mgr;
+               unsigned bit;
 
-               DSSERR("SYNC_LOST_DIGIT, disabling TV\n");
+               mgr = omap_dss_get_overlay_manager(i);
+               bit = sync_lost_bits[i];
 
-               for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
-                       struct omap_overlay_manager *mgr;
-                       mgr = omap_dss_get_overlay_manager(i);
+               if (bit & errors) {
+                       struct omap_dss_device *dssdev = mgr->device;
+                       bool enable;
 
-                       if (mgr->id == OMAP_DSS_CHANNEL_DIGIT) {
-                               manager = mgr;
-                               enable = mgr->device->state ==
-                                               OMAP_DSS_DISPLAY_ACTIVE;
-                               mgr->device->driver->disable(mgr->device);
-                               break;
-                       }
-               }
+                       DSSERR("SYNC_LOST on channel %s, restarting the output "
+                                       "with video overlays disabled\n",
+                                       mgr->name);
 
-               if (manager) {
-                       struct omap_dss_device *dssdev = manager->device;
-                       for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
-                               struct omap_overlay *ovl;
-                               ovl = omap_dss_get_overlay(i);
-
-                               if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
-                                       continue;
-
-                               if (ovl->id != 0 && ovl->manager == manager)
-                                       dispc_enable_plane(ovl->id, 0);
-                       }
+                       enable = dssdev->state == OMAP_DSS_DISPLAY_ACTIVE;
+                       dssdev->driver->disable(dssdev);
 
-                       dispc_go(manager->id);
-                       mdelay(50);
-                       if (enable)
-                               dssdev->driver->enable(dssdev);
-               }
-       }
-
-       if (errors & DISPC_IRQ_SYNC_LOST2) {
-               struct omap_overlay_manager *manager = NULL;
-               bool enable = false;
-
-               DSSERR("SYNC_LOST for LCD2, disabling LCD2\n");
-
-               for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
-                       struct omap_overlay_manager *mgr;
-                       mgr = omap_dss_get_overlay_manager(i);
-
-                       if (mgr->id == OMAP_DSS_CHANNEL_LCD2) {
-                               manager = mgr;
-                               enable = mgr->device->state ==
-                                               OMAP_DSS_DISPLAY_ACTIVE;
-                               mgr->device->driver->disable(mgr->device);
-                               break;
-                       }
-               }
-
-               if (manager) {
-                       struct omap_dss_device *dssdev = manager->device;
                        for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
                                struct omap_overlay *ovl;
                                ovl = omap_dss_get_overlay(i);
 
-                               if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
-                                       continue;
-
-                               if (ovl->id != 0 && ovl->manager == manager)
-                                       dispc_enable_plane(ovl->id, 0);
+                               if (ovl->id != OMAP_DSS_GFX &&
+                                               ovl->manager == mgr)
+                                       dispc_ovl_enable(ovl->id, false);
                        }
 
-                       dispc_go(manager->id);
+                       dispc_mgr_go(mgr->id);
                        mdelay(50);
+
                        if (enable)
                                dssdev->driver->enable(dssdev);
                }
@@ -3482,9 +3184,7 @@ static void dispc_error_worker(struct work_struct *work)
                for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
                        struct omap_overlay_manager *mgr;
                        mgr = omap_dss_get_overlay_manager(i);
-
-                       if (mgr->caps & OMAP_DSS_OVL_CAP_DISPC)
-                               mgr->device->driver->disable(mgr->device);
+                       mgr->device->driver->disable(mgr->device);
                }
        }
 
@@ -3492,6 +3192,8 @@ static void dispc_error_worker(struct work_struct *work)
        dispc.irq_error_mask |= errors;
        _omap_dispc_set_irqs();
        spin_unlock_irqrestore(&dispc.irq_lock, flags);
+
+       dispc_runtime_put();
 }
 
 int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout)
@@ -3586,6 +3288,8 @@ static void _omap_dispc_initialize_irq(void)
        dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
        if (dss_has_feature(FEAT_MGR_LCD2))
                dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
+       if (dss_feat_get_num_ovls() > 3)
+               dispc.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW;
 
        /* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
         * so clear it */
@@ -3635,6 +3339,8 @@ static void _omap_dispc_initial_config(void)
        dispc_read_plane_fifo_sizes();
 
        dispc_configure_burst_sizes();
+
+       dispc_ovl_enable_zorder_planes();
 }
 
 /* DISPC HW IP initialisation */
@@ -3734,7 +3440,6 @@ static int omap_dispchw_remove(struct platform_device *pdev)
 static int dispc_runtime_suspend(struct device *dev)
 {
        dispc_save_context();
-       clk_disable(dispc.dss_clk);
        dss_runtime_put();
 
        return 0;
@@ -3748,7 +3453,6 @@ static int dispc_runtime_resume(struct device *dev)
        if (r < 0)
                return r;
 
-       clk_enable(dispc.dss_clk);
        dispc_restore_context();
 
        return 0;
index 6c9ee0a..c06efc3 100644 (file)
@@ -291,6 +291,8 @@ static inline u16 DISPC_OVL_BASE(enum omap_plane plane)
                return 0x00BC;
        case OMAP_DSS_VIDEO2:
                return 0x014C;
+       case OMAP_DSS_VIDEO3:
+               return 0x0300;
        default:
                BUG();
        }
@@ -304,6 +306,8 @@ static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane)
        case OMAP_DSS_VIDEO1:
        case OMAP_DSS_VIDEO2:
                return 0x0000;
+       case OMAP_DSS_VIDEO3:
+               return 0x0008;
        default:
                BUG();
        }
@@ -316,6 +320,8 @@ static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane)
        case OMAP_DSS_VIDEO1:
        case OMAP_DSS_VIDEO2:
                return 0x0004;
+       case OMAP_DSS_VIDEO3:
+               return 0x000C;
        default:
                BUG();
        }
@@ -330,6 +336,8 @@ static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane)
                return 0x0544;
        case OMAP_DSS_VIDEO2:
                return 0x04BC;
+       case OMAP_DSS_VIDEO3:
+               return 0x0310;
        default:
                BUG();
        }
@@ -344,6 +352,8 @@ static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane)
                return 0x0548;
        case OMAP_DSS_VIDEO2:
                return 0x04C0;
+       case OMAP_DSS_VIDEO3:
+               return 0x0314;
        default:
                BUG();
        }
@@ -356,6 +366,8 @@ static inline u16 DISPC_POS_OFFSET(enum omap_plane plane)
        case OMAP_DSS_VIDEO1:
        case OMAP_DSS_VIDEO2:
                return 0x0008;
+       case OMAP_DSS_VIDEO3:
+               return 0x009C;
        default:
                BUG();
        }
@@ -368,6 +380,8 @@ static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane)
        case OMAP_DSS_VIDEO1:
        case OMAP_DSS_VIDEO2:
                return 0x000C;
+       case OMAP_DSS_VIDEO3:
+               return 0x00A8;
        default:
                BUG();
        }
@@ -381,6 +395,8 @@ static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane)
        case OMAP_DSS_VIDEO1:
        case OMAP_DSS_VIDEO2:
                return 0x0010;
+       case OMAP_DSS_VIDEO3:
+               return 0x0070;
        default:
                BUG();
        }
@@ -395,6 +411,8 @@ static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane)
                return 0x0568;
        case OMAP_DSS_VIDEO2:
                return 0x04DC;
+       case OMAP_DSS_VIDEO3:
+               return 0x032C;
        default:
                BUG();
        }
@@ -408,6 +426,8 @@ static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane)
        case OMAP_DSS_VIDEO1:
        case OMAP_DSS_VIDEO2:
                return 0x0014;
+       case OMAP_DSS_VIDEO3:
+               return 0x008C;
        default:
                BUG();
        }
@@ -421,6 +441,8 @@ static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane)
        case OMAP_DSS_VIDEO1:
        case OMAP_DSS_VIDEO2:
                return 0x0018;
+       case OMAP_DSS_VIDEO3:
+               return 0x0088;
        default:
                BUG();
        }
@@ -434,6 +456,8 @@ static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane)
        case OMAP_DSS_VIDEO1:
        case OMAP_DSS_VIDEO2:
                return 0x001C;
+       case OMAP_DSS_VIDEO3:
+               return 0x00A4;
        default:
                BUG();
        }
@@ -447,6 +471,8 @@ static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane)
        case OMAP_DSS_VIDEO1:
        case OMAP_DSS_VIDEO2:
                return 0x0020;
+       case OMAP_DSS_VIDEO3:
+               return 0x0098;
        default:
                BUG();
        }
@@ -459,6 +485,7 @@ static inline u16 DISPC_WINDOW_SKIP_OFFSET(enum omap_plane plane)
                return 0x0034;
        case OMAP_DSS_VIDEO1:
        case OMAP_DSS_VIDEO2:
+       case OMAP_DSS_VIDEO3:
                BUG();
        default:
                BUG();
@@ -472,6 +499,7 @@ static inline u16 DISPC_TABLE_BA_OFFSET(enum omap_plane plane)
                return 0x0038;
        case OMAP_DSS_VIDEO1:
        case OMAP_DSS_VIDEO2:
+       case OMAP_DSS_VIDEO3:
                BUG();
        default:
                BUG();
@@ -486,6 +514,8 @@ static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane)
        case OMAP_DSS_VIDEO1:
        case OMAP_DSS_VIDEO2:
                return 0x0024;
+       case OMAP_DSS_VIDEO3:
+               return 0x0090;
        default:
                BUG();
        }
@@ -500,6 +530,8 @@ static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane)
                return 0x0580;
        case OMAP_DSS_VIDEO2:
                return 0x055C;
+       case OMAP_DSS_VIDEO3:
+               return 0x0424;
        default:
                BUG();
        }
@@ -513,6 +545,8 @@ static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane)
        case OMAP_DSS_VIDEO1:
        case OMAP_DSS_VIDEO2:
                return 0x0028;
+       case OMAP_DSS_VIDEO3:
+               return 0x0094;
        default:
                BUG();
        }
@@ -527,6 +561,8 @@ static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane)
        case OMAP_DSS_VIDEO1:
        case OMAP_DSS_VIDEO2:
                return 0x002C;
+       case OMAP_DSS_VIDEO3:
+               return 0x0000;
        default:
                BUG();
        }
@@ -541,6 +577,8 @@ static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane)
                return 0x0584;
        case OMAP_DSS_VIDEO2:
                return 0x0560;
+       case OMAP_DSS_VIDEO3:
+               return 0x0428;
        default:
                BUG();
        }
@@ -554,6 +592,8 @@ static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane)
        case OMAP_DSS_VIDEO1:
        case OMAP_DSS_VIDEO2:
                return 0x0030;
+       case OMAP_DSS_VIDEO3:
+               return 0x0004;
        default:
                BUG();
        }
@@ -568,6 +608,8 @@ static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane)
                return 0x0588;
        case OMAP_DSS_VIDEO2:
                return 0x0564;
+       case OMAP_DSS_VIDEO3:
+               return 0x042C;
        default:
                BUG();
        }
@@ -582,6 +624,8 @@ static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i)
        case OMAP_DSS_VIDEO1:
        case OMAP_DSS_VIDEO2:
                return 0x0034 + i * 0x8;
+       case OMAP_DSS_VIDEO3:
+               return 0x0010 + i * 0x8;
        default:
                BUG();
        }
@@ -597,6 +641,8 @@ static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i)
                return 0x058C + i * 0x8;
        case OMAP_DSS_VIDEO2:
                return 0x0568 + i * 0x8;
+       case OMAP_DSS_VIDEO3:
+               return 0x0430 + i * 0x8;
        default:
                BUG();
        }
@@ -611,6 +657,8 @@ static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i)
        case OMAP_DSS_VIDEO1:
        case OMAP_DSS_VIDEO2:
                return 0x0038 + i * 0x8;
+       case OMAP_DSS_VIDEO3:
+               return 0x0014 + i * 0x8;
        default:
                BUG();
        }
@@ -626,6 +674,8 @@ static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i)
                return 0x0590 + i * 8;
        case OMAP_DSS_VIDEO2:
                return 0x056C + i * 0x8;
+       case OMAP_DSS_VIDEO3:
+               return 0x0434 + i * 0x8;
        default:
                BUG();
        }
@@ -639,6 +689,7 @@ static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i)
                BUG();
        case OMAP_DSS_VIDEO1:
        case OMAP_DSS_VIDEO2:
+       case OMAP_DSS_VIDEO3:
                return 0x0074 + i * 0x4;
        default:
                BUG();
@@ -655,6 +706,8 @@ static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i)
                return 0x0124 + i * 0x4;
        case OMAP_DSS_VIDEO2:
                return 0x00B4 + i * 0x4;
+       case OMAP_DSS_VIDEO3:
+               return 0x0050 + i * 0x4;
        default:
                BUG();
        }
@@ -670,6 +723,8 @@ static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i)
                return 0x05CC + i * 0x4;
        case OMAP_DSS_VIDEO2:
                return 0x05A8 + i * 0x4;
+       case OMAP_DSS_VIDEO3:
+               return 0x0470 + i * 0x4;
        default:
                BUG();
        }
@@ -684,6 +739,8 @@ static inline u16 DISPC_PRELOAD_OFFSET(enum omap_plane plane)
                return 0x0174;
        case OMAP_DSS_VIDEO2:
                return 0x00E8;
+       case OMAP_DSS_VIDEO3:
+               return 0x00A0;
        default:
                BUG();
        }
index 94495e4..be331dc 100644 (file)
@@ -45,14 +45,13 @@ static ssize_t display_enabled_store(struct device *dev,
                const char *buf, size_t size)
 {
        struct omap_dss_device *dssdev = to_dss_device(dev);
-       int r, enabled;
+       int r;
+       bool enabled;
 
-       r = kstrtoint(buf, 0, &enabled);
+       r = strtobool(buf, &enabled);
        if (r)
                return r;
 
-       enabled = !!enabled;
-
        if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
                if (enabled) {
                        r = dssdev->driver->enable(dssdev);
@@ -79,17 +78,16 @@ static ssize_t display_tear_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t size)
 {
        struct omap_dss_device *dssdev = to_dss_device(dev);
-       int te, r;
+       int r;
+       bool te;
 
        if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
                return -ENOENT;
 
-       r = kstrtoint(buf, 0, &te);
+       r = strtobool(buf, &te);
        if (r)
                return r;
 
-       te = !!te;
-
        r = dssdev->driver->enable_te(dssdev, te);
        if (r)
                return r;
@@ -195,17 +193,16 @@ static ssize_t display_mirror_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t size)
 {
        struct omap_dss_device *dssdev = to_dss_device(dev);
-       int mirror, r;
+       int r;
+       bool mirror;
 
        if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
                return -ENOENT;
 
-       r = kstrtoint(buf, 0, &mirror);
+       r = strtobool(buf, &mirror);
        if (r)
                return r;
 
-       mirror = !!mirror;
-
        r = dssdev->driver->set_mirror(dssdev, mirror);
        if (r)
                return r;
@@ -302,11 +299,15 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
                        return 16;
 
        case OMAP_DISPLAY_TYPE_DBI:
-       case OMAP_DISPLAY_TYPE_DSI:
                if (dssdev->ctrl.pixel_size == 24)
                        return 24;
                else
                        return 16;
+       case OMAP_DISPLAY_TYPE_DSI:
+               if (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) > 16)
+                       return 24;
+               else
+                       return 16;
        case OMAP_DISPLAY_TYPE_VENC:
        case OMAP_DISPLAY_TYPE_SDI:
        case OMAP_DISPLAY_TYPE_HDMI:
@@ -342,9 +343,11 @@ bool dss_use_replication(struct omap_dss_device *dssdev,
                bpp = 24;
                break;
        case OMAP_DISPLAY_TYPE_DBI:
-       case OMAP_DISPLAY_TYPE_DSI:
                bpp = dssdev->ctrl.pixel_size;
                break;
+       case OMAP_DISPLAY_TYPE_DSI:
+               bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
+               break;
        default:
                BUG();
        }
index f053b18..483888a 100644 (file)
@@ -82,9 +82,11 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft,
 
        dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
 
-       r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
-       if (r)
+       r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo);
+       if (r) {
+               dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
                return r;
+       }
 
        *fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
        *lck_div = dispc_cinfo.lck_div;
@@ -109,7 +111,7 @@ static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, bool is_tft,
        if (r)
                return r;
 
-       r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
+       r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo);
        if (r)
                return r;
 
@@ -129,7 +131,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
        bool is_tft;
        int r = 0;
 
-       dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
+       dispc_mgr_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
                        dssdev->panel.acbi, dssdev->panel.acb);
 
        is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
@@ -153,7 +155,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
                t->pixel_clock = pck;
        }
 
-       dispc_set_lcd_timings(dssdev->manager->id, t);
+       dispc_mgr_set_lcd_timings(dssdev->manager->id, t);
 
        return 0;
 }
@@ -164,11 +166,12 @@ static void dpi_basic_init(struct omap_dss_device *dssdev)
 
        is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
 
-       dispc_set_parallel_interface_mode(dssdev->manager->id,
-                       OMAP_DSS_PARALLELMODE_BYPASS);
-       dispc_set_lcd_display_type(dssdev->manager->id, is_tft ?
+       dispc_mgr_set_io_pad_mode(DSS_IO_PAD_MODE_BYPASS);
+       dispc_mgr_enable_stallmode(dssdev->manager->id, false);
+
+       dispc_mgr_set_lcd_display_type(dssdev->manager->id, is_tft ?
                        OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN);
-       dispc_set_tft_data_lines(dssdev->manager->id,
+       dispc_mgr_set_tft_data_lines(dssdev->manager->id,
                        dssdev->phy.dpi.data_lines);
 }
 
@@ -176,6 +179,11 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 {
        int r;
 
+       if (dssdev->manager == NULL) {
+               DSSERR("failed to enable display: no manager\n");
+               return -ENODEV;
+       }
+
        r = omap_dss_start_device(dssdev);
        if (r) {
                DSSERR("failed to start device\n");
@@ -277,7 +285,7 @@ void dpi_set_timings(struct omap_dss_device *dssdev,
                }
 
                dpi_set_mode(dssdev);
-               dispc_go(dssdev->manager->id);
+               dispc_mgr_go(dssdev->manager->id);
 
                dispc_runtime_put();
                dss_runtime_put();
index 7adbbeb..43c04a9 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/pm_runtime.h>
 
 #include <video/omapdss.h>
+#include <video/mipi_display.h>
 #include <plat/clock.h>
 
 #include "dss.h"
@@ -131,7 +132,7 @@ struct dsi_reg { u16 idx; };
 #define DSI_IRQ_TA_TIMEOUT     (1 << 20)
 #define DSI_IRQ_ERROR_MASK \
        (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \
-       DSI_IRQ_TA_TIMEOUT)
+       DSI_IRQ_TA_TIMEOUT | DSI_IRQ_SYNC_LOST)
 #define DSI_IRQ_CHANNEL_MASK   0xf
 
 /* Virtual channel interrupts */
@@ -198,18 +199,6 @@ struct dsi_reg { u16 idx; };
         DSI_CIO_IRQ_ERRCONTENTIONLP0_4 | DSI_CIO_IRQ_ERRCONTENTIONLP1_4 | \
         DSI_CIO_IRQ_ERRCONTENTIONLP0_5 | DSI_CIO_IRQ_ERRCONTENTIONLP1_5)
 
-#define DSI_DT_DCS_SHORT_WRITE_0       0x05
-#define DSI_DT_DCS_SHORT_WRITE_1       0x15
-#define DSI_DT_DCS_READ                        0x06
-#define DSI_DT_SET_MAX_RET_PKG_SIZE    0x37
-#define DSI_DT_NULL_PACKET             0x09
-#define DSI_DT_DCS_LONG_WRITE          0x39
-
-#define DSI_DT_RX_ACK_WITH_ERR         0x02
-#define DSI_DT_RX_DCS_LONG_READ                0x1c
-#define DSI_DT_RX_SHORT_READ_1         0x21
-#define DSI_DT_RX_SHORT_READ_2         0x22
-
 typedef void (*omap_dsi_isr_t) (void *arg, u32 mask);
 
 #define DSI_MAX_NR_ISRS                2
@@ -228,9 +217,9 @@ enum fifo_size {
        DSI_FIFO_SIZE_128       = 4,
 };
 
-enum dsi_vc_mode {
-       DSI_VC_MODE_L4 = 0,
-       DSI_VC_MODE_VP,
+enum dsi_vc_source {
+       DSI_VC_SOURCE_L4 = 0,
+       DSI_VC_SOURCE_VP,
 };
 
 enum dsi_lane {
@@ -274,7 +263,8 @@ struct dsi_data {
        struct clk *dss_clk;
        struct clk *sys_clk;
 
-       void (*dsi_mux_pads)(bool enable);
+       int (*enable_pads)(int dsi_id, unsigned lane_mask);
+       void (*disable_pads)(int dsi_id, unsigned lane_mask);
 
        struct dsi_clock_info current_cinfo;
 
@@ -282,7 +272,7 @@ struct dsi_data {
        struct regulator *vdds_dsi_reg;
 
        struct {
-               enum dsi_vc_mode mode;
+               enum dsi_vc_source source;
                struct omap_dss_device *dssdev;
                enum fifo_size fifo_size;
                int vc_id;
@@ -368,14 +358,9 @@ struct platform_device *dsi_get_dsidev_from_id(int module)
        return dsi_pdev_map[module];
 }
 
-static int dsi_get_dsidev_id(struct platform_device *dsidev)
+static inline int dsi_get_dsidev_id(struct platform_device *dsidev)
 {
-       /* TEMP: Pass 0 as the dsi module index till the time the dsi platform
-        * device names aren't changed to the form "omapdss_dsi.0",
-        * "omapdss_dsi.1" and so on */
-       BUG_ON(dsidev->id != -1);
-
-       return 0;
+       return dsidev->id;
 }
 
 static inline void dsi_write_reg(struct platform_device *dsidev,
@@ -437,6 +422,21 @@ static inline int wait_for_bit_change(struct platform_device *dsidev,
        return value;
 }
 
+u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt)
+{
+       switch (fmt) {
+       case OMAP_DSS_DSI_FMT_RGB888:
+       case OMAP_DSS_DSI_FMT_RGB666:
+               return 24;
+       case OMAP_DSS_DSI_FMT_RGB666_PACKED:
+               return 18;
+       case OMAP_DSS_DSI_FMT_RGB565:
+               return 16;
+       default:
+               BUG();
+       }
+}
+
 #ifdef DEBUG
 static void dsi_perf_mark_setup(struct platform_device *dsidev)
 {
@@ -453,6 +453,7 @@ static void dsi_perf_mark_start(struct platform_device *dsidev)
 static void dsi_perf_show(struct platform_device *dsidev, const char *name)
 {
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       struct omap_dss_device *dssdev = dsi->update_region.device;
        ktime_t t, setup_time, trans_time;
        u32 total_bytes;
        u32 setup_us, trans_us, total_us;
@@ -476,7 +477,7 @@ static void dsi_perf_show(struct platform_device *dsidev, const char *name)
 
        total_bytes = dsi->update_region.w *
                dsi->update_region.h *
-               dsi->update_region.device->ctrl.pixel_size / 8;
+               dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8;
 
        printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), "
                        "%u bytes, %u kbytes/sec\n",
@@ -1287,7 +1288,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,
                 * with DSS_SYS_CLK source also */
                cinfo->highfreq = 0;
        } else {
-               cinfo->clkin = dispc_pclk_rate(dssdev->manager->id);
+               cinfo->clkin = dispc_mgr_pclk_rate(dssdev->manager->id);
 
                if (cinfo->clkin < 32000000)
                        cinfo->highfreq = 0;
@@ -2360,6 +2361,24 @@ static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev)
        return 0;
 }
 
+static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev)
+{
+       unsigned lanes = 0;
+
+       if (dssdev->phy.dsi.clk_lane != 0)
+               lanes |= 1 << (dssdev->phy.dsi.clk_lane - 1);
+       if (dssdev->phy.dsi.data1_lane != 0)
+               lanes |= 1 << (dssdev->phy.dsi.data1_lane - 1);
+       if (dssdev->phy.dsi.data2_lane != 0)
+               lanes |= 1 << (dssdev->phy.dsi.data2_lane - 1);
+       if (dssdev->phy.dsi.data3_lane != 0)
+               lanes |= 1 << (dssdev->phy.dsi.data3_lane - 1);
+       if (dssdev->phy.dsi.data4_lane != 0)
+               lanes |= 1 << (dssdev->phy.dsi.data4_lane - 1);
+
+       return lanes;
+}
+
 static int dsi_cio_init(struct omap_dss_device *dssdev)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -2370,8 +2389,9 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
 
        DSSDBGF();
 
-       if (dsi->dsi_mux_pads)
-               dsi->dsi_mux_pads(true);
+       r = dsi->enable_pads(dsidev->id, dsi_get_lane_mask(dssdev));
+       if (r)
+               return r;
 
        dsi_enable_scp_clk(dsidev);
 
@@ -2452,6 +2472,12 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
 
        dsi_cio_timings(dsidev);
 
+       if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
+               /* DDR_CLK_ALWAYS_ON */
+               REG_FLD_MOD(dsidev, DSI_CLK_CTRL,
+                       dssdev->panel.dsi_vm_data.ddr_clk_always_on, 13, 13);
+       }
+
        dsi->ulps_enabled = false;
 
        DSSDBG("CIO init done\n");
@@ -2467,19 +2493,21 @@ err_cio_pwr:
                dsi_cio_disable_lane_override(dsidev);
 err_scp_clk_dom:
        dsi_disable_scp_clk(dsidev);
-       if (dsi->dsi_mux_pads)
-               dsi->dsi_mux_pads(false);
+       dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev));
        return r;
 }
 
-static void dsi_cio_uninit(struct platform_device *dsidev)
+static void dsi_cio_uninit(struct omap_dss_device *dssdev)
 {
+       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
+       /* DDR_CLK_ALWAYS_ON */
+       REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 13, 13);
+
        dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF);
        dsi_disable_scp_clk(dsidev);
-       if (dsi->dsi_mux_pads)
-               dsi->dsi_mux_pads(false);
+       dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev));
 }
 
 static void dsi_config_tx_fifo(struct platform_device *dsidev,
@@ -2669,10 +2697,10 @@ static int dsi_sync_vc(struct platform_device *dsidev, int channel)
        if (!dsi_vc_is_enabled(dsidev, channel))
                return 0;
 
-       switch (dsi->vc[channel].mode) {
-       case DSI_VC_MODE_VP:
+       switch (dsi->vc[channel].source) {
+       case DSI_VC_SOURCE_VP:
                return dsi_sync_vc_vp(dsidev, channel);
-       case DSI_VC_MODE_L4:
+       case DSI_VC_SOURCE_L4:
                return dsi_sync_vc_l4(dsidev, channel);
        default:
                BUG();
@@ -2726,43 +2754,12 @@ static void dsi_vc_initial_config(struct platform_device *dsidev, int channel)
        dsi_write_reg(dsidev, DSI_VC_CTRL(channel), r);
 }
 
-static int dsi_vc_config_l4(struct platform_device *dsidev, int channel)
+static int dsi_vc_config_source(struct platform_device *dsidev, int channel,
+               enum dsi_vc_source source)
 {
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
-       if (dsi->vc[channel].mode == DSI_VC_MODE_L4)
-               return 0;
-
-       DSSDBGF("%d", channel);
-
-       dsi_sync_vc(dsidev, channel);
-
-       dsi_vc_enable(dsidev, channel, 0);
-
-       /* VC_BUSY */
-       if (wait_for_bit_change(dsidev, DSI_VC_CTRL(channel), 15, 0) != 0) {
-               DSSERR("vc(%d) busy when trying to config for L4\n", channel);
-               return -EIO;
-       }
-
-       REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */
-
-       /* DCS_CMD_ENABLE */
-       if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC))
-               REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 30, 30);
-
-       dsi_vc_enable(dsidev, channel, 1);
-
-       dsi->vc[channel].mode = DSI_VC_MODE_L4;
-
-       return 0;
-}
-
-static int dsi_vc_config_vp(struct platform_device *dsidev, int channel)
-{
-       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-       if (dsi->vc[channel].mode == DSI_VC_MODE_VP)
+       if (dsi->vc[channel].source == source)
                return 0;
 
        DSSDBGF("%d", channel);
@@ -2777,21 +2774,22 @@ static int dsi_vc_config_vp(struct platform_device *dsidev, int channel)
                return -EIO;
        }
 
-       /* SOURCE, 1 = video port */
-       REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 1, 1);
+       /* SOURCE, 0 = L4, 1 = video port */
+       REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), source, 1, 1);
 
        /* DCS_CMD_ENABLE */
-       if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC))
-               REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 30, 30);
+       if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) {
+               bool enable = source == DSI_VC_SOURCE_VP;
+               REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 30, 30);
+       }
 
        dsi_vc_enable(dsidev, channel, 1);
 
-       dsi->vc[channel].mode = DSI_VC_MODE_VP;
+       dsi->vc[channel].source = source;
 
        return 0;
 }
 
-
 void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
                bool enable)
 {
@@ -2810,6 +2808,10 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
        dsi_if_enable(dsidev, 1);
 
        dsi_force_tx_stop_mode_io(dsidev);
+
+       /* start the DDR clock by sending a NULL packet */
+       if (dssdev->panel.dsi_vm_data.ddr_clk_always_on && enable)
+               dsi_vc_send_null(dssdev, channel);
 }
 EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs);
 
@@ -2873,16 +2875,16 @@ static u16 dsi_vc_flush_receive_data(struct platform_device *dsidev,
                val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel));
                DSSERR("\trawval %#08x\n", val);
                dt = FLD_GET(val, 5, 0);
-               if (dt == DSI_DT_RX_ACK_WITH_ERR) {
+               if (dt == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT) {
                        u16 err = FLD_GET(val, 23, 8);
                        dsi_show_rx_ack_with_err(err);
-               } else if (dt == DSI_DT_RX_SHORT_READ_1) {
+               } else if (dt == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE) {
                        DSSERR("\tDCS short response, 1 byte: %#x\n",
                                        FLD_GET(val, 23, 8));
-               } else if (dt == DSI_DT_RX_SHORT_READ_2) {
+               } else if (dt == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE) {
                        DSSERR("\tDCS short response, 2 byte: %#x\n",
                                        FLD_GET(val, 23, 8));
-               } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
+               } else if (dt == MIPI_DSI_RX_DCS_LONG_READ_RESPONSE) {
                        DSSERR("\tDCS long response, len %d\n",
                                        FLD_GET(val, 23, 8));
                        dsi_vc_flush_long_data(dsidev, channel);
@@ -3007,7 +3009,7 @@ static int dsi_vc_send_long(struct platform_device *dsidev, int channel,
                return -EINVAL;
        }
 
-       dsi_vc_config_l4(dsidev, channel);
+       dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_L4);
 
        dsi_vc_write_long_header(dsidev, channel, data_type, len, ecc);
 
@@ -3066,7 +3068,7 @@ static int dsi_vc_send_short(struct platform_device *dsidev, int channel,
                                channel,
                                data_type, data & 0xff, (data >> 8) & 0xff);
 
-       dsi_vc_config_l4(dsidev, channel);
+       dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_L4);
 
        if (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(channel)), 16, 16)) {
                DSSERR("ERROR FIFO FULL, aborting transfer\n");
@@ -3085,44 +3087,66 @@ static int dsi_vc_send_short(struct platform_device *dsidev, int channel,
 int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-       u8 nullpkg[] = {0, 0, 0, 0};
 
-       return dsi_vc_send_long(dsidev, channel, DSI_DT_NULL_PACKET, nullpkg,
-               4, 0);
+       return dsi_vc_send_long(dsidev, channel, MIPI_DSI_NULL_PACKET, NULL,
+               0, 0);
 }
 EXPORT_SYMBOL(dsi_vc_send_null);
 
-int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel,
-               u8 *data, int len)
+static int dsi_vc_write_nosync_common(struct omap_dss_device *dssdev,
+               int channel, u8 *data, int len, enum dss_dsi_content_type type)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        int r;
 
-       BUG_ON(len == 0);
-
-       if (len == 1) {
-               r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_SHORT_WRITE_0,
-                               data[0], 0);
+       if (len == 0) {
+               BUG_ON(type == DSS_DSI_CONTENT_DCS);
+               r = dsi_vc_send_short(dsidev, channel,
+                               MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM, 0, 0);
+       } else if (len == 1) {
+               r = dsi_vc_send_short(dsidev, channel,
+                               type == DSS_DSI_CONTENT_GENERIC ?
+                               MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM :
+                               MIPI_DSI_DCS_SHORT_WRITE, data[0], 0);
        } else if (len == 2) {
-               r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_SHORT_WRITE_1,
+               r = dsi_vc_send_short(dsidev, channel,
+                               type == DSS_DSI_CONTENT_GENERIC ?
+                               MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM :
+                               MIPI_DSI_DCS_SHORT_WRITE_PARAM,
                                data[0] | (data[1] << 8), 0);
        } else {
-               /* 0x39 = DCS Long Write */
-               r = dsi_vc_send_long(dsidev, channel, DSI_DT_DCS_LONG_WRITE,
-                               data, len, 0);
+               r = dsi_vc_send_long(dsidev, channel,
+                               type == DSS_DSI_CONTENT_GENERIC ?
+                               MIPI_DSI_GENERIC_LONG_WRITE :
+                               MIPI_DSI_DCS_LONG_WRITE, data, len, 0);
        }
 
        return r;
 }
+
+int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel,
+               u8 *data, int len)
+{
+       return dsi_vc_write_nosync_common(dssdev, channel, data, len,
+                       DSS_DSI_CONTENT_DCS);
+}
 EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);
 
-int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
-               int len)
+int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel,
+               u8 *data, int len)
+{
+       return dsi_vc_write_nosync_common(dssdev, channel, data, len,
+                       DSS_DSI_CONTENT_GENERIC);
+}
+EXPORT_SYMBOL(dsi_vc_generic_write_nosync);
+
+static int dsi_vc_write_common(struct omap_dss_device *dssdev, int channel,
+               u8 *data, int len, enum dss_dsi_content_type type)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        int r;
 
-       r = dsi_vc_dcs_write_nosync(dssdev, channel, data, len);
+       r = dsi_vc_write_nosync_common(dssdev, channel, data, len, type);
        if (r)
                goto err;
 
@@ -3140,18 +3164,39 @@ int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
 
        return 0;
 err:
-       DSSERR("dsi_vc_dcs_write(ch %d, cmd 0x%02x, len %d) failed\n",
+       DSSERR("dsi_vc_write_common(ch %d, cmd 0x%02x, len %d) failed\n",
                        channel, data[0], len);
        return r;
 }
+
+int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
+               int len)
+{
+       return dsi_vc_write_common(dssdev, channel, data, len,
+                       DSS_DSI_CONTENT_DCS);
+}
 EXPORT_SYMBOL(dsi_vc_dcs_write);
 
+int dsi_vc_generic_write(struct omap_dss_device *dssdev, int channel, u8 *data,
+               int len)
+{
+       return dsi_vc_write_common(dssdev, channel, data, len,
+                       DSS_DSI_CONTENT_GENERIC);
+}
+EXPORT_SYMBOL(dsi_vc_generic_write);
+
 int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd)
 {
        return dsi_vc_dcs_write(dssdev, channel, &dcs_cmd, 1);
 }
 EXPORT_SYMBOL(dsi_vc_dcs_write_0);
 
+int dsi_vc_generic_write_0(struct omap_dss_device *dssdev, int channel)
+{
+       return dsi_vc_generic_write(dssdev, channel, NULL, 0);
+}
+EXPORT_SYMBOL(dsi_vc_generic_write_0);
+
 int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
                u8 param)
 {
@@ -3162,25 +3207,87 @@ int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
 }
 EXPORT_SYMBOL(dsi_vc_dcs_write_1);
 
-int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
-               u8 *buf, int buflen)
+int dsi_vc_generic_write_1(struct omap_dss_device *dssdev, int channel,
+               u8 param)
+{
+       return dsi_vc_generic_write(dssdev, channel, &param, 1);
+}
+EXPORT_SYMBOL(dsi_vc_generic_write_1);
+
+int dsi_vc_generic_write_2(struct omap_dss_device *dssdev, int channel,
+               u8 param1, u8 param2)
+{
+       u8 buf[2];
+       buf[0] = param1;
+       buf[1] = param2;
+       return dsi_vc_generic_write(dssdev, channel, buf, 2);
+}
+EXPORT_SYMBOL(dsi_vc_generic_write_2);
+
+static int dsi_vc_dcs_send_read_request(struct omap_dss_device *dssdev,
+               int channel, u8 dcs_cmd)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-       u32 val;
-       u8 dt;
        int r;
 
        if (dsi->debug_read)
-               DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %x)\n", channel, dcs_cmd);
+               DSSDBG("dsi_vc_dcs_send_read_request(ch%d, dcs_cmd %x)\n",
+                       channel, dcs_cmd);
 
-       r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_READ, dcs_cmd, 0);
-       if (r)
-               goto err;
+       r = dsi_vc_send_short(dsidev, channel, MIPI_DSI_DCS_READ, dcs_cmd, 0);
+       if (r) {
+               DSSERR("dsi_vc_dcs_send_read_request(ch %d, cmd 0x%02x)"
+                       " failed\n", channel, dcs_cmd);
+               return r;
+       }
 
-       r = dsi_vc_send_bta_sync(dssdev, channel);
-       if (r)
-               goto err;
+       return 0;
+}
+
+static int dsi_vc_generic_send_read_request(struct omap_dss_device *dssdev,
+               int channel, u8 *reqdata, int reqlen)
+{
+       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       u16 data;
+       u8 data_type;
+       int r;
+
+       if (dsi->debug_read)
+               DSSDBG("dsi_vc_generic_send_read_request(ch %d, reqlen %d)\n",
+                       channel, reqlen);
+
+       if (reqlen == 0) {
+               data_type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM;
+               data = 0;
+       } else if (reqlen == 1) {
+               data_type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM;
+               data = reqdata[0];
+       } else if (reqlen == 2) {
+               data_type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM;
+               data = reqdata[0] | (reqdata[1] << 8);
+       } else {
+               BUG();
+       }
+
+       r = dsi_vc_send_short(dsidev, channel, data_type, data, 0);
+       if (r) {
+               DSSERR("dsi_vc_generic_send_read_request(ch %d, reqlen %d)"
+                       " failed\n", channel, reqlen);
+               return r;
+       }
+
+       return 0;
+}
+
+static int dsi_vc_read_rx_fifo(struct platform_device *dsidev, int channel,
+               u8 *buf, int buflen, enum dss_dsi_content_type type)
+{
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       u32 val;
+       u8 dt;
+       int r;
 
        /* RX_FIFO_NOT_EMPTY */
        if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20) == 0) {
@@ -3193,16 +3300,20 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
        if (dsi->debug_read)
                DSSDBG("\theader: %08x\n", val);
        dt = FLD_GET(val, 5, 0);
-       if (dt == DSI_DT_RX_ACK_WITH_ERR) {
+       if (dt == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT) {
                u16 err = FLD_GET(val, 23, 8);
                dsi_show_rx_ack_with_err(err);
                r = -EIO;
                goto err;
 
-       } else if (dt == DSI_DT_RX_SHORT_READ_1) {
+       } else if (dt == (type == DSS_DSI_CONTENT_GENERIC ?
+                       MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE :
+                       MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE)) {
                u8 data = FLD_GET(val, 15, 8);
                if (dsi->debug_read)
-                       DSSDBG("\tDCS short response, 1 byte: %02x\n", data);
+                       DSSDBG("\t%s short response, 1 byte: %02x\n",
+                               type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" :
+                               "DCS", data);
 
                if (buflen < 1) {
                        r = -EIO;
@@ -3212,10 +3323,14 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
                buf[0] = data;
 
                return 1;
-       } else if (dt == DSI_DT_RX_SHORT_READ_2) {
+       } else if (dt == (type == DSS_DSI_CONTENT_GENERIC ?
+                       MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE :
+                       MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE)) {
                u16 data = FLD_GET(val, 23, 8);
                if (dsi->debug_read)
-                       DSSDBG("\tDCS short response, 2 byte: %04x\n", data);
+                       DSSDBG("\t%s short response, 2 byte: %04x\n",
+                               type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" :
+                               "DCS", data);
 
                if (buflen < 2) {
                        r = -EIO;
@@ -3226,11 +3341,15 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
                buf[1] = (data >> 8) & 0xff;
 
                return 2;
-       } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
+       } else if (dt == (type == DSS_DSI_CONTENT_GENERIC ?
+                       MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE :
+                       MIPI_DSI_RX_DCS_LONG_READ_RESPONSE)) {
                int w;
                int len = FLD_GET(val, 23, 8);
                if (dsi->debug_read)
-                       DSSDBG("\tDCS long response, len %d\n", len);
+                       DSSDBG("\t%s long response, len %d\n",
+                               type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" :
+                               "DCS", len);
 
                if (len > buflen) {
                        r = -EIO;
@@ -3266,58 +3385,126 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
 
        BUG();
 err:
-       DSSERR("dsi_vc_dcs_read(ch %d, cmd 0x%02x) failed\n",
-                       channel, dcs_cmd);
+       DSSERR("dsi_vc_read_rx_fifo(ch %d type %s) failed\n", channel,
+               type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : "DCS");
+
        return r;
+}
 
+int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
+               u8 *buf, int buflen)
+{
+       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       int r;
+
+       r = dsi_vc_dcs_send_read_request(dssdev, channel, dcs_cmd);
+       if (r)
+               goto err;
+
+       r = dsi_vc_send_bta_sync(dssdev, channel);
+       if (r)
+               goto err;
+
+       r = dsi_vc_read_rx_fifo(dsidev, channel, buf, buflen,
+               DSS_DSI_CONTENT_DCS);
+       if (r < 0)
+               goto err;
+
+       if (r != buflen) {
+               r = -EIO;
+               goto err;
+       }
+
+       return 0;
+err:
+       DSSERR("dsi_vc_dcs_read(ch %d, cmd 0x%02x) failed\n", channel, dcs_cmd);
+       return r;
 }
 EXPORT_SYMBOL(dsi_vc_dcs_read);
 
-int dsi_vc_dcs_read_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
-               u8 *data)
+static int dsi_vc_generic_read(struct omap_dss_device *dssdev, int channel,
+               u8 *reqdata, int reqlen, u8 *buf, int buflen)
 {
+       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        int r;
 
-       r = dsi_vc_dcs_read(dssdev, channel, dcs_cmd, data, 1);
+       r = dsi_vc_generic_send_read_request(dssdev, channel, reqdata, reqlen);
+       if (r)
+               return r;
+
+       r = dsi_vc_send_bta_sync(dssdev, channel);
+       if (r)
+               return r;
 
+       r = dsi_vc_read_rx_fifo(dsidev, channel, buf, buflen,
+               DSS_DSI_CONTENT_GENERIC);
        if (r < 0)
                return r;
 
-       if (r != 1)
-               return -EIO;
+       if (r != buflen) {
+               r = -EIO;
+               return r;
+       }
 
        return 0;
 }
-EXPORT_SYMBOL(dsi_vc_dcs_read_1);
 
-int dsi_vc_dcs_read_2(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
-               u8 *data1, u8 *data2)
+int dsi_vc_generic_read_0(struct omap_dss_device *dssdev, int channel, u8 *buf,
+               int buflen)
 {
-       u8 buf[2];
        int r;
 
-       r = dsi_vc_dcs_read(dssdev, channel, dcs_cmd, buf, 2);
+       r = dsi_vc_generic_read(dssdev, channel, NULL, 0, buf, buflen);
+       if (r) {
+               DSSERR("dsi_vc_generic_read_0(ch %d) failed\n", channel);
+               return r;
+       }
 
-       if (r < 0)
+       return 0;
+}
+EXPORT_SYMBOL(dsi_vc_generic_read_0);
+
+int dsi_vc_generic_read_1(struct omap_dss_device *dssdev, int channel, u8 param,
+               u8 *buf, int buflen)
+{
+       int r;
+
+       r = dsi_vc_generic_read(dssdev, channel, &param, 1, buf, buflen);
+       if (r) {
+               DSSERR("dsi_vc_generic_read_1(ch %d) failed\n", channel);
                return r;
+       }
 
-       if (r != 2)
-               return -EIO;
+       return 0;
+}
+EXPORT_SYMBOL(dsi_vc_generic_read_1);
 
-       *data1 = buf[0];
-       *data2 = buf[1];
+int dsi_vc_generic_read_2(struct omap_dss_device *dssdev, int channel,
+               u8 param1, u8 param2, u8 *buf, int buflen)
+{
+       int r;
+       u8 reqdata[2];
+
+       reqdata[0] = param1;
+       reqdata[1] = param2;
+
+       r = dsi_vc_generic_read(dssdev, channel, reqdata, 2, buf, buflen);
+       if (r) {
+               DSSERR("dsi_vc_generic_read_2(ch %d) failed\n", channel);
+               return r;
+       }
 
        return 0;
 }
-EXPORT_SYMBOL(dsi_vc_dcs_read_2);
+EXPORT_SYMBOL(dsi_vc_generic_read_2);
 
 int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel,
                u16 len)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
 
-       return dsi_vc_send_short(dsidev, channel, DSI_DT_SET_MAX_RET_PKG_SIZE,
-                       len, 0);
+       return dsi_vc_send_short(dsidev, channel,
+                       MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, len, 0);
 }
 EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size);
 
@@ -3508,6 +3695,75 @@ static void dsi_set_hs_tx_timeout(struct platform_device *dsidev,
                        ticks, x4 ? " x4" : "", x16 ? " x16" : "",
                        (total_ticks * 1000) / (fck / 1000 / 1000));
 }
+
+static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev)
+{
+       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       int num_line_buffers;
+
+       if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
+               int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
+               unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
+               struct omap_video_timings *timings = &dssdev->panel.timings;
+               /*
+                * Don't use line buffers if width is greater than the video
+                * port's line buffer size
+                */
+               if (line_buf_size <= timings->x_res * bpp / 8)
+                       num_line_buffers = 0;
+               else
+                       num_line_buffers = 2;
+       } else {
+               /* Use maximum number of line buffers in command mode */
+               num_line_buffers = 2;
+       }
+
+       /* LINE_BUFFER */
+       REG_FLD_MOD(dsidev, DSI_CTRL, num_line_buffers, 13, 12);
+}
+
+static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev)
+{
+       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       int de_pol = dssdev->panel.dsi_vm_data.vp_de_pol;
+       int hsync_pol = dssdev->panel.dsi_vm_data.vp_hsync_pol;
+       int vsync_pol = dssdev->panel.dsi_vm_data.vp_vsync_pol;
+       bool vsync_end = dssdev->panel.dsi_vm_data.vp_vsync_end;
+       bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end;
+       u32 r;
+
+       r = dsi_read_reg(dsidev, DSI_CTRL);
+       r = FLD_MOD(r, de_pol, 9, 9);           /* VP_DE_POL */
+       r = FLD_MOD(r, hsync_pol, 10, 10);      /* VP_HSYNC_POL */
+       r = FLD_MOD(r, vsync_pol, 11, 11);      /* VP_VSYNC_POL */
+       r = FLD_MOD(r, 1, 15, 15);              /* VP_VSYNC_START */
+       r = FLD_MOD(r, vsync_end, 16, 16);      /* VP_VSYNC_END */
+       r = FLD_MOD(r, 1, 17, 17);              /* VP_HSYNC_START */
+       r = FLD_MOD(r, hsync_end, 18, 18);      /* VP_HSYNC_END */
+       dsi_write_reg(dsidev, DSI_CTRL, r);
+}
+
+static void dsi_config_blanking_modes(struct omap_dss_device *dssdev)
+{
+       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+       int blanking_mode = dssdev->panel.dsi_vm_data.blanking_mode;
+       int hfp_blanking_mode = dssdev->panel.dsi_vm_data.hfp_blanking_mode;
+       int hbp_blanking_mode = dssdev->panel.dsi_vm_data.hbp_blanking_mode;
+       int hsa_blanking_mode = dssdev->panel.dsi_vm_data.hsa_blanking_mode;
+       u32 r;
+
+       /*
+        * 0 = TX FIFO packets sent or LPS in corresponding blanking periods
+        * 1 = Long blanking packets are sent in corresponding blanking periods
+        */
+       r = dsi_read_reg(dsidev, DSI_CTRL);
+       r = FLD_MOD(r, blanking_mode, 20, 20);          /* BLANKING_MODE */
+       r = FLD_MOD(r, hfp_blanking_mode, 21, 21);      /* HFP_BLANKING */
+       r = FLD_MOD(r, hbp_blanking_mode, 22, 22);      /* HBP_BLANKING */
+       r = FLD_MOD(r, hsa_blanking_mode, 23, 23);      /* HSA_BLANKING */
+       dsi_write_reg(dsidev, DSI_CTRL, r);
+}
+
 static int dsi_proto_config(struct omap_dss_device *dssdev)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -3530,7 +3786,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
        dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true);
        dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true);
 
-       switch (dssdev->ctrl.pixel_size) {
+       switch (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt)) {
        case 16:
                buswidth = 0;
                break;
@@ -3551,7 +3807,6 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
        r = FLD_MOD(r, 1, 4, 4);        /* VP_CLK_RATIO, always 1, see errata*/
        r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */
        r = FLD_MOD(r, 0, 8, 8);        /* VP_CLK_POL */
-       r = FLD_MOD(r, 2, 13, 12);      /* LINE_BUFFER, 2 lines */
        r = FLD_MOD(r, 1, 14, 14);      /* TRIGGER_RESET_MODE */
        r = FLD_MOD(r, 1, 19, 19);      /* EOT_ENABLE */
        if (!dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) {
@@ -3562,6 +3817,13 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
 
        dsi_write_reg(dsidev, DSI_CTRL, r);
 
+       dsi_config_vp_num_line_buffers(dssdev);
+
+       if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
+               dsi_config_vp_sync_events(dssdev);
+               dsi_config_blanking_modes(dssdev);
+       }
+
        dsi_vc_initial_config(dsidev, 0);
        dsi_vc_initial_config(dsidev, 1);
        dsi_vc_initial_config(dsidev, 2);
@@ -3580,6 +3842,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
        unsigned ddr_clk_pre, ddr_clk_post;
        unsigned enter_hs_mode_lat, exit_hs_mode_lat;
        unsigned ths_eot;
+       int ndl = dsi_get_num_data_lanes_dssdev(dssdev);
        u32 r;
 
        r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0);
@@ -3602,7 +3865,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
        /* min 60ns + 52*UI */
        tclk_post = ns2ddr(dsidev, 60) + 26;
 
-       ths_eot = DIV_ROUND_UP(4, dsi_get_num_data_lanes_dssdev(dssdev));
+       ths_eot = DIV_ROUND_UP(4, ndl);
 
        ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare,
                        4);
@@ -3632,162 +3895,114 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
 
        DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",
                        enter_hs_mode_lat, exit_hs_mode_lat);
-}
-
-
-#define DSI_DECL_VARS \
-       int __dsi_cb = 0; u32 __dsi_cv = 0;
 
-#define DSI_FLUSH(dsidev, ch) \
-       if (__dsi_cb > 0) { \
-               /*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \
-               dsi_write_reg(dsidev, DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \
-               __dsi_cb = __dsi_cv = 0; \
+        if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
+               /* TODO: Implement a video mode check_timings function */
+               int hsa = dssdev->panel.dsi_vm_data.hsa;
+               int hfp = dssdev->panel.dsi_vm_data.hfp;
+               int hbp = dssdev->panel.dsi_vm_data.hbp;
+               int vsa = dssdev->panel.dsi_vm_data.vsa;
+               int vfp = dssdev->panel.dsi_vm_data.vfp;
+               int vbp = dssdev->panel.dsi_vm_data.vbp;
+               int window_sync = dssdev->panel.dsi_vm_data.window_sync;
+               bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end;
+               struct omap_video_timings *timings = &dssdev->panel.timings;
+               int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
+               int tl, t_he, width_bytes;
+
+               t_he = hsync_end ?
+                       ((hsa == 0 && ndl == 3) ? 1 : DIV_ROUND_UP(4, ndl)) : 0;
+
+               width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8);
+
+               /* TL = t_HS + HSA + t_HE + HFP + ceil((WC + 6) / NDL) + HBP */
+               tl = DIV_ROUND_UP(4, ndl) + (hsync_end ? hsa : 0) + t_he + hfp +
+                       DIV_ROUND_UP(width_bytes + 6, ndl) + hbp;
+
+               DSSDBG("HBP: %d, HFP: %d, HSA: %d, TL: %d TXBYTECLKHS\n", hbp,
+                       hfp, hsync_end ? hsa : 0, tl);
+               DSSDBG("VBP: %d, VFP: %d, VSA: %d, VACT: %d lines\n", vbp, vfp,
+                       vsa, timings->y_res);
+
+               r = dsi_read_reg(dsidev, DSI_VM_TIMING1);
+               r = FLD_MOD(r, hbp, 11, 0);     /* HBP */
+               r = FLD_MOD(r, hfp, 23, 12);    /* HFP */
+               r = FLD_MOD(r, hsync_end ? hsa : 0, 31, 24);    /* HSA */
+               dsi_write_reg(dsidev, DSI_VM_TIMING1, r);
+
+               r = dsi_read_reg(dsidev, DSI_VM_TIMING2);
+               r = FLD_MOD(r, vbp, 7, 0);      /* VBP */
+               r = FLD_MOD(r, vfp, 15, 8);     /* VFP */
+               r = FLD_MOD(r, vsa, 23, 16);    /* VSA */
+               r = FLD_MOD(r, window_sync, 27, 24);    /* WINDOW_SYNC */
+               dsi_write_reg(dsidev, DSI_VM_TIMING2, r);
+
+               r = dsi_read_reg(dsidev, DSI_VM_TIMING3);
+               r = FLD_MOD(r, timings->y_res, 14, 0);  /* VACT */
+               r = FLD_MOD(r, tl, 31, 16);             /* TL */
+               dsi_write_reg(dsidev, DSI_VM_TIMING3, r);
        }
+}
 
-#define DSI_PUSH(dsidev, ch, data) \
-       do { \
-               __dsi_cv |= (data) << (__dsi_cb * 8); \
-               /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \
-               if (++__dsi_cb > 3) \
-                       DSI_FLUSH(dsidev, ch); \
-       } while (0)
-
-static int dsi_update_screen_l4(struct omap_dss_device *dssdev,
-                       int x, int y, int w, int h)
+int dsi_video_mode_enable(struct omap_dss_device *dssdev, int channel)
 {
-       /* Note: supports only 24bit colors in 32bit container */
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-       int first = 1;
-       int fifo_stalls = 0;
-       int max_dsi_packet_size;
-       int max_data_per_packet;
-       int max_pixels_per_packet;
-       int pixels_left;
-       int bytespp = dssdev->ctrl.pixel_size / 8;
-       int scr_width;
-       u32 __iomem *data;
-       int start_offset;
-       int horiz_inc;
-       int current_x;
-       struct omap_overlay *ovl;
-
-       debug_irq = 0;
-
-       DSSDBG("dsi_update_screen_l4 (%d,%d %dx%d)\n",
-                       x, y, w, h);
+       int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
+       u8 data_type;
+       u16 word_count;
 
-       ovl = dssdev->manager->overlays[0];
-
-       if (ovl->info.color_mode != OMAP_DSS_COLOR_RGB24U)
-               return -EINVAL;
-
-       if (dssdev->ctrl.pixel_size != 24)
-               return -EINVAL;
-
-       scr_width = ovl->info.screen_width;
-       data = ovl->info.vaddr;
-
-       start_offset = scr_width * y + x;
-       horiz_inc = scr_width - w;
-       current_x = x;
-
-       /* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp) bytes
-        * in fifo */
-
-       /* When using CPU, max long packet size is TX buffer size */
-       max_dsi_packet_size = dsi->vc[0].fifo_size * 32 * 4;
-
-       /* we seem to get better perf if we divide the tx fifo to half,
-          and while the other half is being sent, we fill the other half
-          max_dsi_packet_size /= 2; */
-
-       max_data_per_packet = max_dsi_packet_size - 4 - 1;
-
-       max_pixels_per_packet = max_data_per_packet / bytespp;
-
-       DSSDBG("max_pixels_per_packet %d\n", max_pixels_per_packet);
-
-       pixels_left = w * h;
+       switch (dssdev->panel.dsi_pix_fmt) {
+       case OMAP_DSS_DSI_FMT_RGB888:
+               data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24;
+               break;
+       case OMAP_DSS_DSI_FMT_RGB666:
+               data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
+               break;
+       case OMAP_DSS_DSI_FMT_RGB666_PACKED:
+               data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18;
+               break;
+       case OMAP_DSS_DSI_FMT_RGB565:
+               data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16;
+               break;
+       default:
+               BUG();
+       };
 
-       DSSDBG("total pixels %d\n", pixels_left);
+       dsi_if_enable(dsidev, false);
+       dsi_vc_enable(dsidev, channel, false);
 
-       data += start_offset;
+       /* MODE, 1 = video mode */
+       REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4);
 
-       while (pixels_left > 0) {
-               /* 0x2c = write_memory_start */
-               /* 0x3c = write_memory_continue */
-               u8 dcs_cmd = first ? 0x2c : 0x3c;
-               int pixels;
-               DSI_DECL_VARS;
-               first = 0;
+       word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8);
 
-#if 1
-               /* using fifo not empty */
-               /* TX_FIFO_NOT_EMPTY */
-               while (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(0)), 5, 5)) {
-                       fifo_stalls++;
-                       if (fifo_stalls > 0xfffff) {
-                               DSSERR("fifo stalls overflow, pixels left %d\n",
-                                               pixels_left);
-                               dsi_if_enable(dsidev, 0);
-                               return -EIO;
-                       }
-                       udelay(1);
-               }
-#elif 1
-               /* using fifo emptiness */
-               while ((REG_GET(dsidev, DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 <
-                               max_dsi_packet_size) {
-                       fifo_stalls++;
-                       if (fifo_stalls > 0xfffff) {
-                               DSSERR("fifo stalls overflow, pixels left %d\n",
-                                              pixels_left);
-                               dsi_if_enable(dsidev, 0);
-                               return -EIO;
-                       }
-               }
-#else
-               while ((REG_GET(dsidev, DSI_TX_FIFO_VC_EMPTINESS,
-                               7, 0) + 1) * 4 == 0) {
-                       fifo_stalls++;
-                       if (fifo_stalls > 0xfffff) {
-                               DSSERR("fifo stalls overflow, pixels left %d\n",
-                                              pixels_left);
-                               dsi_if_enable(dsidev, 0);
-                               return -EIO;
-                       }
-               }
-#endif
-               pixels = min(max_pixels_per_packet, pixels_left);
+       dsi_vc_write_long_header(dsidev, channel, data_type, word_count, 0);
 
-               pixels_left -= pixels;
+       dsi_vc_enable(dsidev, channel, true);
+       dsi_if_enable(dsidev, true);
 
-               dsi_vc_write_long_header(dsidev, 0, DSI_DT_DCS_LONG_WRITE,
-                               1 + pixels * bytespp, 0);
+       dssdev->manager->enable(dssdev->manager);
 
-               DSI_PUSH(dsidev, 0, dcs_cmd);
+       return 0;
+}
+EXPORT_SYMBOL(dsi_video_mode_enable);
 
-               while (pixels-- > 0) {
-                       u32 pix = __raw_readl(data++);
+void dsi_video_mode_disable(struct omap_dss_device *dssdev, int channel)
+{
+       struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
 
-                       DSI_PUSH(dsidev, 0, (pix >> 16) & 0xff);
-                       DSI_PUSH(dsidev, 0, (pix >> 8) & 0xff);
-                       DSI_PUSH(dsidev, 0, (pix >> 0) & 0xff);
+       dsi_if_enable(dsidev, false);
+       dsi_vc_enable(dsidev, channel, false);
 
-                       current_x++;
-                       if (current_x == x+w) {
-                               current_x = x;
-                               data += horiz_inc;
-                       }
-               }
+       /* MODE, 0 = command mode */
+       REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 4, 4);
 
-               DSI_FLUSH(dsidev, 0);
-       }
+       dsi_vc_enable(dsidev, channel, true);
+       dsi_if_enable(dsidev, true);
 
-       return 0;
+       dssdev->manager->disable(dssdev->manager);
 }
+EXPORT_SYMBOL(dsi_video_mode_disable);
 
 static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
                u16 x, u16 y, u16 w, u16 h)
@@ -3808,9 +4023,9 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
        DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",
                        x, y, w, h);
 
-       dsi_vc_config_vp(dsidev, channel);
+       dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP);
 
-       bytespp = dssdev->ctrl.pixel_size / 8;
+       bytespp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8;
        bytespl = w * bytespp;
        bytespf = bytespl * h;
 
@@ -3831,7 +4046,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
        l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */
        dsi_write_reg(dsidev, DSI_VC_TE(channel), l);
 
-       dsi_vc_write_long_header(dsidev, channel, DSI_DT_DCS_LONG_WRITE,
+       dsi_vc_write_long_header(dsidev, channel, MIPI_DSI_DCS_LONG_WRITE,
                packet_len, 0);
 
        if (dsi->te_enabled)
@@ -3956,11 +4171,9 @@ int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
 
        dsi_perf_mark_setup(dsidev);
 
-       if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
-               dss_setup_partial_planes(dssdev, x, y, w, h,
-                               enlarge_update_area);
-               dispc_set_lcd_size(dssdev->manager->id, *w, *h);
-       }
+       dss_setup_partial_planes(dssdev, x, y, w, h,
+                       enlarge_update_area);
+       dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h);
 
        return 0;
 }
@@ -3982,27 +4195,16 @@ int omap_dsi_update(struct omap_dss_device *dssdev,
         * see rather obscure HW error happening, as DSS halts. */
        BUG_ON(x % 2 == 1);
 
-       if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
-               dsi->framedone_callback = callback;
-               dsi->framedone_data = data;
-
-               dsi->update_region.x = x;
-               dsi->update_region.y = y;
-               dsi->update_region.w = w;
-               dsi->update_region.h = h;
-               dsi->update_region.device = dssdev;
-
-               dsi_update_screen_dispc(dssdev, x, y, w, h);
-       } else {
-               int r;
+       dsi->framedone_callback = callback;
+       dsi->framedone_data = data;
 
-               r = dsi_update_screen_l4(dssdev, x, y, w, h);
-               if (r)
-                       return r;
+       dsi->update_region.x = x;
+       dsi->update_region.y = y;
+       dsi->update_region.w = w;
+       dsi->update_region.h = h;
+       dsi->update_region.device = dssdev;
 
-               dsi_perf_show(dsidev, "L4");
-               callback(0, data);
-       }
+       dsi_update_screen_dispc(dssdev, x, y, w, h);
 
        return 0;
 }
@@ -4013,28 +4215,9 @@ EXPORT_SYMBOL(omap_dsi_update);
 static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
 {
        int r;
-       u32 irq;
-
-       irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ?
-               DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2;
 
-       r = omap_dispc_register_isr(dsi_framedone_irq_callback, (void *) dssdev,
-                       irq);
-       if (r) {
-               DSSERR("can't get FRAMEDONE irq\n");
-               return r;
-       }
-
-       dispc_set_lcd_display_type(dssdev->manager->id,
-                       OMAP_DSS_LCD_DISPLAY_TFT);
-
-       dispc_set_parallel_interface_mode(dssdev->manager->id,
-                       OMAP_DSS_PARALLELMODE_DSI);
-       dispc_enable_fifohandcheck(dssdev->manager->id, 1);
-
-       dispc_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size);
-
-       {
+       if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) {
+               u32 irq;
                struct omap_video_timings timings = {
                        .hsw            = 1,
                        .hfp            = 1,
@@ -4044,21 +4227,46 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
                        .vbp            = 0,
                };
 
-               dispc_set_lcd_timings(dssdev->manager->id, &timings);
+               irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ?
+                       DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2;
+
+               r = omap_dispc_register_isr(dsi_framedone_irq_callback,
+                       (void *) dssdev, irq);
+               if (r) {
+                       DSSERR("can't get FRAMEDONE irq\n");
+                       return r;
+               }
+
+               dispc_mgr_enable_stallmode(dssdev->manager->id, true);
+               dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 1);
+
+               dispc_mgr_set_lcd_timings(dssdev->manager->id, &timings);
+       } else {
+               dispc_mgr_enable_stallmode(dssdev->manager->id, false);
+               dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 0);
+
+               dispc_mgr_set_lcd_timings(dssdev->manager->id,
+                       &dssdev->panel.timings);
        }
 
+               dispc_mgr_set_lcd_display_type(dssdev->manager->id,
+                       OMAP_DSS_LCD_DISPLAY_TFT);
+               dispc_mgr_set_tft_data_lines(dssdev->manager->id,
+                       dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt));
        return 0;
 }
 
 static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
 {
-       u32 irq;
+       if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) {
+               u32 irq;
 
-       irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ?
-               DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2;
+               irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ?
+                       DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2;
 
-       omap_dispc_unregister_isr(dsi_framedone_irq_callback, (void *) dssdev,
-                       irq);
+               omap_dispc_unregister_isr(dsi_framedone_irq_callback,
+                       (void *) dssdev, irq);
+       }
 }
 
 static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
@@ -4106,7 +4314,7 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev)
                return r;
        }
 
-       r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
+       r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo);
        if (r) {
                DSSERR("Failed to set dispc clocks\n");
                return r;
@@ -4166,10 +4374,12 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
 
        return 0;
 err3:
-       dsi_cio_uninit(dsidev);
+       dsi_cio_uninit(dssdev);
 err2:
        dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
        dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK);
+       dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK);
+
 err1:
        dsi_pll_uninit(dsidev, true);
 err0:
@@ -4195,7 +4405,8 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
 
        dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
        dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK);
-       dsi_cio_uninit(dsidev);
+       dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK);
+       dsi_cio_uninit(dssdev);
        dsi_pll_uninit(dsidev, disconnect_lanes);
 }
 
@@ -4211,6 +4422,12 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
 
        mutex_lock(&dsi->lock);
 
+       if (dssdev->manager == NULL) {
+               DSSERR("failed to enable display: no manager\n");
+               r = -ENODEV;
+               goto err_start_dev;
+       }
+
        r = omap_dss_start_device(dssdev);
        if (r) {
                DSSERR("failed to start device\n");
@@ -4307,9 +4524,10 @@ int dsi_init_display(struct omap_dss_device *dssdev)
 
        DSSDBG("DSI init\n");
 
-       /* XXX these should be figured out dynamically */
-       dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
-               OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
+       if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) {
+               dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
+                       OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
+       }
 
        if (dsi->vdds_dsi_reg == NULL) {
                struct regulator *vdds_dsi;
@@ -4435,10 +4653,7 @@ static int dsi_get_clocks(struct platform_device *dsidev)
 
        dsi->dss_clk = clk;
 
-       if (cpu_is_omap34xx() || cpu_is_omap3630())
-               clk = clk_get(&dsidev->dev, "dss2_alwon_fck");
-       else
-               clk = clk_get(&dsidev->dev, "sys_clk");
+       clk = clk_get(&dsidev->dev, "sys_clk");
        if (IS_ERR(clk)) {
                DSSERR("can't get sys_clk\n");
                clk_put(dsi->dss_clk);
@@ -4462,7 +4677,7 @@ static void dsi_put_clocks(struct platform_device *dsidev)
 }
 
 /* DSI1 HW IP initialisation */
-static int omap_dsi1hw_probe(struct platform_device *dsidev)
+static int omap_dsihw_probe(struct platform_device *dsidev)
 {
        struct omap_display_platform_data *dss_plat_data;
        struct omap_dss_board_info *board_info;
@@ -4483,7 +4698,8 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
 
        dss_plat_data = dsidev->dev.platform_data;
        board_info = dss_plat_data->board_data;
-       dsi->dsi_mux_pads = board_info->dsi_mux_pads;
+       dsi->enable_pads = board_info->dsi_enable_pads;
+       dsi->disable_pads = board_info->dsi_disable_pads;
 
        spin_lock_init(&dsi->irq_lock);
        spin_lock_init(&dsi->errors_lock);
@@ -4539,7 +4755,7 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
 
        /* DSI VCs initialization */
        for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) {
-               dsi->vc[i].mode = DSI_VC_MODE_L4;
+               dsi->vc[i].source = DSI_VC_SOURCE_L4;
                dsi->vc[i].dssdev = NULL;
                dsi->vc[i].vc_id = 0;
        }
@@ -4572,7 +4788,7 @@ err_alloc:
        return r;
 }
 
-static int omap_dsi1hw_remove(struct platform_device *dsidev)
+static int omap_dsihw_remove(struct platform_device *dsidev)
 {
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
@@ -4602,10 +4818,6 @@ static int omap_dsi1hw_remove(struct platform_device *dsidev)
 
 static int dsi_runtime_suspend(struct device *dev)
 {
-       struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev));
-
-       clk_disable(dsi->dss_clk);
-
        dispc_runtime_put();
        dss_runtime_put();
 
@@ -4614,7 +4826,6 @@ static int dsi_runtime_suspend(struct device *dev)
 
 static int dsi_runtime_resume(struct device *dev)
 {
-       struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev));
        int r;
 
        r = dss_runtime_get();
@@ -4625,8 +4836,6 @@ static int dsi_runtime_resume(struct device *dev)
        if (r)
                goto err_get_dispc;
 
-       clk_enable(dsi->dss_clk);
-
        return 0;
 
 err_get_dispc:
@@ -4640,11 +4849,11 @@ static const struct dev_pm_ops dsi_pm_ops = {
        .runtime_resume = dsi_runtime_resume,
 };
 
-static struct platform_driver omap_dsi1hw_driver = {
-       .probe          = omap_dsi1hw_probe,
-       .remove         = omap_dsi1hw_remove,
+static struct platform_driver omap_dsihw_driver = {
+       .probe          = omap_dsihw_probe,
+       .remove         = omap_dsihw_remove,
        .driver         = {
-               .name   = "omapdss_dsi1",
+               .name   = "omapdss_dsi",
                .owner  = THIS_MODULE,
                .pm     = &dsi_pm_ops,
        },
@@ -4652,10 +4861,10 @@ static struct platform_driver omap_dsi1hw_driver = {
 
 int dsi_init_platform_driver(void)
 {
-       return platform_driver_register(&omap_dsi1hw_driver);
+       return platform_driver_register(&omap_dsihw_driver);
 }
 
 void dsi_uninit_platform_driver(void)
 {
-       return platform_driver_unregister(&omap_dsi1hw_driver);
+       return platform_driver_unregister(&omap_dsihw_driver);
 }
index 0f9c3a6..3e09726 100644 (file)
@@ -639,6 +639,17 @@ void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi)
        REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */
 }
 
+enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
+{
+       enum omap_display_type displays;
+
+       displays = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
+       if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0)
+               return DSS_VENC_TV_CLK;
+
+       return REG_GET(DSS_CONTROL, 15, 15);
+}
+
 static int dss_get_clocks(void)
 {
        struct clk *clk;
@@ -691,11 +702,6 @@ static void dss_put_clocks(void)
        clk_put(dss.dss_clk);
 }
 
-struct clk *dss_get_ick(void)
-{
-       return clk_get(&dss.pdev->dev, "ick");
-}
-
 int dss_runtime_get(void)
 {
        int r;
@@ -824,13 +830,11 @@ static int omap_dsshw_remove(struct platform_device *pdev)
 static int dss_runtime_suspend(struct device *dev)
 {
        dss_save_context();
-       clk_disable(dss.dss_clk);
        return 0;
 }
 
 static int dss_runtime_resume(struct device *dev)
 {
-       clk_enable(dss.dss_clk);
        dss_restore_context();
        return 0;
 }
index 9c94b11..6308fc5 100644 (file)
@@ -97,10 +97,10 @@ extern unsigned int dss_debug;
 #define FLD_MOD(orig, val, start, end) \
        (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
 
-enum omap_parallel_interface_mode {
-       OMAP_DSS_PARALLELMODE_BYPASS,           /* MIPI DPI */
-       OMAP_DSS_PARALLELMODE_RFBI,             /* MIPI DBI */
-       OMAP_DSS_PARALLELMODE_DSI,
+enum dss_io_pad_mode {
+       DSS_IO_PAD_MODE_RESET,
+       DSS_IO_PAD_MODE_RFBI,
+       DSS_IO_PAD_MODE_BYPASS,
 };
 
 enum dss_hdmi_venc_clk_source_select {
@@ -108,6 +108,11 @@ enum dss_hdmi_venc_clk_source_select {
        DSS_HDMI_M_PCLK = 1,
 };
 
+enum dss_dsi_content_type {
+       DSS_DSI_CONTENT_DCS,
+       DSS_DSI_CONTENT_GENERIC,
+};
+
 struct dss_clock_info {
        /* rates that we get with dividers below */
        unsigned long fck;
@@ -150,16 +155,6 @@ struct dsi_clock_info {
        bool use_sys_clk;
 };
 
-/* HDMI PLL structure */
-struct hdmi_pll_info {
-       u16 regn;
-       u16 regm;
-       u32 regmf;
-       u16 regm2;
-       u16 regsd;
-       u16 dcofreq;
-};
-
 struct seq_file;
 struct platform_device;
 
@@ -209,9 +204,8 @@ void dss_uninit_platform_driver(void);
 int dss_runtime_get(void);
 void dss_runtime_put(void);
 
-struct clk *dss_get_ick(void);
-
 void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
+enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
 const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
 void dss_dump_clocks(struct seq_file *s);
 
@@ -279,6 +273,8 @@ void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir,
 
 int dsi_init_display(struct omap_dss_device *display);
 void dsi_irq_handler(void);
+u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt);
+
 unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
 int dsi_pll_set_clock_div(struct platform_device *dsidev,
                struct dsi_clock_info *cinfo);
@@ -309,6 +305,11 @@ static inline int dsi_runtime_get(struct platform_device *dsidev)
 static inline void dsi_runtime_put(struct platform_device *dsidev)
 {
 }
+static inline u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt)
+{
+       WARN("%s: DSI not compiled in, returning pixel_size as 0\n", __func__);
+       return 0;
+}
 static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
 {
        WARN("%s: DSI not compiled in, returning rate as 0\n", __func__);
@@ -385,90 +386,71 @@ void dispc_disable_sidle(void);
 void dispc_lcd_enable_signal_polarity(bool act_high);
 void dispc_lcd_enable_signal(bool enable);
 void dispc_pck_free_enable(bool enable);
-void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable);
-
-void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height);
 void dispc_set_digit_size(u16 width, u16 height);
-u32 dispc_get_plane_fifo_size(enum omap_plane plane);
-void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
 void dispc_enable_fifomerge(bool enable);
-u32 dispc_get_burst_size(enum omap_plane plane);
-void dispc_enable_cpr(enum omap_channel channel, bool enable);
-void dispc_set_cpr_coef(enum omap_channel channel,
-               struct omap_dss_cpr_coefs *coefs);
-
-void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr);
-void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr);
-void dispc_set_plane_pos(enum omap_plane plane, u16 x, u16 y);
-void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height);
-void dispc_set_channel_out(enum omap_plane plane,
-               enum omap_channel channel_out);
-
 void dispc_enable_gamma_table(bool enable);
-int dispc_setup_plane(enum omap_plane plane,
-                     u32 paddr, u16 screen_width,
-                     u16 pos_x, u16 pos_y,
-                     u16 width, u16 height,
-                     u16 out_width, u16 out_height,
-                     enum omap_color_mode color_mode,
-                     bool ilace,
-                     enum omap_dss_rotation_type rotation_type,
-                     u8 rotation, bool mirror,
-                     u8 global_alpha, u8 pre_mult_alpha,
-                     enum omap_channel channel,
-                     u32 puv_addr);
-
-bool dispc_go_busy(enum omap_channel channel);
-void dispc_go(enum omap_channel channel);
-void dispc_enable_channel(enum omap_channel channel, bool enable);
-bool dispc_is_channel_enabled(enum omap_channel channel);
-int dispc_enable_plane(enum omap_plane plane, bool enable);
-void dispc_enable_replication(enum omap_plane plane, bool enable);
-
-void dispc_set_parallel_interface_mode(enum omap_channel channel,
-               enum omap_parallel_interface_mode mode);
-void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines);
-void dispc_set_lcd_display_type(enum omap_channel channel,
-               enum omap_lcd_display_type type);
 void dispc_set_loadmode(enum omap_dss_load_mode mode);
 
-void dispc_set_default_color(enum omap_channel channel, u32 color);
-u32 dispc_get_default_color(enum omap_channel channel);
-void dispc_set_trans_key(enum omap_channel ch,
-               enum omap_dss_trans_key_type type,
-               u32 trans_key);
-void dispc_get_trans_key(enum omap_channel ch,
-               enum omap_dss_trans_key_type *type,
-               u32 *trans_key);
-void dispc_enable_trans_key(enum omap_channel ch, bool enable);
-void dispc_enable_alpha_blending(enum omap_channel ch, bool enable);
-bool dispc_trans_key_enabled(enum omap_channel ch);
-bool dispc_alpha_blending_enabled(enum omap_channel ch);
-
 bool dispc_lcd_timings_ok(struct omap_video_timings *timings);
-void dispc_set_lcd_timings(enum omap_channel channel,
-               struct omap_video_timings *timings);
 unsigned long dispc_fclk_rate(void);
-unsigned long dispc_lclk_rate(enum omap_channel channel);
-unsigned long dispc_pclk_rate(enum omap_channel channel);
-void dispc_set_pol_freq(enum omap_channel channel,
-               enum omap_panel_config config, u8 acbi, u8 acb);
 void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
                struct dispc_clock_info *cinfo);
 int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
                struct dispc_clock_info *cinfo);
-int dispc_set_clock_div(enum omap_channel channel,
+
+
+u32 dispc_ovl_get_fifo_size(enum omap_plane plane);
+u32 dispc_ovl_get_burst_size(enum omap_plane plane);
+int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
+               bool ilace, enum omap_channel channel, bool replication,
+               u32 fifo_low, u32 fifo_high);
+int dispc_ovl_enable(enum omap_plane plane, bool enable);
+
+
+void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable);
+void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height);
+void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable);
+void dispc_mgr_set_cpr_coef(enum omap_channel channel,
+               struct omap_dss_cpr_coefs *coefs);
+bool dispc_mgr_go_busy(enum omap_channel channel);
+void dispc_mgr_go(enum omap_channel channel);
+void dispc_mgr_enable(enum omap_channel channel, bool enable);
+bool dispc_mgr_is_channel_enabled(enum omap_channel channel);
+void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode);
+void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable);
+void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines);
+void dispc_mgr_set_lcd_display_type(enum omap_channel channel,
+               enum omap_lcd_display_type type);
+void dispc_mgr_set_default_color(enum omap_channel channel, u32 color);
+u32 dispc_mgr_get_default_color(enum omap_channel channel);
+void dispc_mgr_set_trans_key(enum omap_channel ch,
+               enum omap_dss_trans_key_type type,
+               u32 trans_key);
+void dispc_mgr_get_trans_key(enum omap_channel ch,
+               enum omap_dss_trans_key_type *type,
+               u32 *trans_key);
+void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable);
+void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable);
+bool dispc_mgr_trans_key_enabled(enum omap_channel ch);
+bool dispc_mgr_alpha_fixed_zorder_enabled(enum omap_channel ch);
+void dispc_mgr_set_lcd_timings(enum omap_channel channel,
+               struct omap_video_timings *timings);
+void dispc_mgr_set_pol_freq(enum omap_channel channel,
+               enum omap_panel_config config, u8 acbi, u8 acb);
+unsigned long dispc_mgr_lclk_rate(enum omap_channel channel);
+unsigned long dispc_mgr_pclk_rate(enum omap_channel channel);
+int dispc_mgr_set_clock_div(enum omap_channel channel,
                struct dispc_clock_info *cinfo);
-int dispc_get_clock_div(enum omap_channel channel,
+int dispc_mgr_get_clock_div(enum omap_channel channel,
                struct dispc_clock_info *cinfo);
 
-
 /* VENC */
 #ifdef CONFIG_OMAP2_DSS_VENC
 int venc_init_platform_driver(void);
 void venc_uninit_platform_driver(void);
 void venc_dump_regs(struct seq_file *s);
 int venc_init_display(struct omap_dss_device *display);
+unsigned long venc_get_pixel_clock(void);
 #else
 static inline int venc_init_platform_driver(void)
 {
@@ -477,6 +459,11 @@ static inline int venc_init_platform_driver(void)
 static inline void venc_uninit_platform_driver(void)
 {
 }
+static inline unsigned long venc_get_pixel_clock(void)
+{
+       WARN("%s: VENC not compiled in, returning pclk as 0\n", __func__);
+       return 0;
+}
 #endif
 
 /* HDMI */
@@ -484,6 +471,8 @@ static inline void venc_uninit_platform_driver(void)
 int hdmi_init_platform_driver(void);
 void hdmi_uninit_platform_driver(void);
 int hdmi_init_display(struct omap_dss_device *dssdev);
+unsigned long hdmi_get_pixel_clock(void);
+void hdmi_dump_regs(struct seq_file *s);
 #else
 static inline int hdmi_init_display(struct omap_dss_device *dssdev)
 {
@@ -496,12 +485,19 @@ static inline int hdmi_init_platform_driver(void)
 static inline void hdmi_uninit_platform_driver(void)
 {
 }
+static inline unsigned long hdmi_get_pixel_clock(void)
+{
+       WARN("%s: HDMI not compiled in, returning pclk as 0\n", __func__);
+       return 0;
+}
 #endif
 int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev);
 void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);
 void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev);
 int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
                                        struct omap_video_timings *timings);
+int omapdss_hdmi_read_edid(u8 *buf, int len);
+bool omapdss_hdmi_detect(void);
 int hdmi_panel_init(void);
 void hdmi_panel_exit(void);
 
index b415c4e..b402699 100644 (file)
@@ -47,6 +47,7 @@ struct omap_dss_features {
        const int num_ovls;
        const enum omap_display_type *supported_displays;
        const enum omap_color_mode *supported_color_modes;
+       const enum omap_overlay_caps *overlay_caps;
        const char * const *clksrc_names;
        const struct dss_param_range *dss_params;
 
@@ -209,6 +210,68 @@ static const enum omap_color_mode omap4_dss_supported_color_modes[] = {
        OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
        OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
        OMAP_DSS_COLOR_RGBX32,
+
+       /* OMAP_DSS_VIDEO3 */
+       OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
+       OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
+       OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
+       OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
+       OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
+       OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
+       OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
+       OMAP_DSS_COLOR_RGBX32,
+};
+
+static const enum omap_overlay_caps omap2_dss_overlay_caps[] = {
+       /* OMAP_DSS_GFX */
+       0,
+
+       /* OMAP_DSS_VIDEO1 */
+       OMAP_DSS_OVL_CAP_SCALE,
+
+       /* OMAP_DSS_VIDEO2 */
+       OMAP_DSS_OVL_CAP_SCALE,
+};
+
+static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = {
+       /* OMAP_DSS_GFX */
+       OMAP_DSS_OVL_CAP_GLOBAL_ALPHA,
+
+       /* OMAP_DSS_VIDEO1 */
+       OMAP_DSS_OVL_CAP_SCALE,
+
+       /* OMAP_DSS_VIDEO2 */
+       OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA,
+};
+
+static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = {
+       /* OMAP_DSS_GFX */
+       OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA,
+
+       /* OMAP_DSS_VIDEO1 */
+       OMAP_DSS_OVL_CAP_SCALE,
+
+       /* OMAP_DSS_VIDEO2 */
+       OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
+               OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA,
+};
+
+static const enum omap_overlay_caps omap4_dss_overlay_caps[] = {
+       /* OMAP_DSS_GFX */
+       OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
+               OMAP_DSS_OVL_CAP_ZORDER,
+
+       /* OMAP_DSS_VIDEO1 */
+       OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
+               OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER,
+
+       /* OMAP_DSS_VIDEO2 */
+       OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
+               OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER,
+
+       /* OMAP_DSS_VIDEO3 */
+       OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
+               OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER,
 };
 
 static const char * const omap2_dss_clk_source_names[] = {
@@ -233,32 +296,38 @@ static const char * const omap4_dss_clk_source_names[] = {
 
 static const struct dss_param_range omap2_dss_param_range[] = {
        [FEAT_PARAM_DSS_FCK]                    = { 0, 173000000 },
+       [FEAT_PARAM_DSS_PCD]                    = { 2, 255 },
        [FEAT_PARAM_DSIPLL_REGN]                = { 0, 0 },
        [FEAT_PARAM_DSIPLL_REGM]                = { 0, 0 },
        [FEAT_PARAM_DSIPLL_REGM_DISPC]          = { 0, 0 },
        [FEAT_PARAM_DSIPLL_REGM_DSI]            = { 0, 0 },
        [FEAT_PARAM_DSIPLL_FINT]                = { 0, 0 },
        [FEAT_PARAM_DSIPLL_LPDIV]               = { 0, 0 },
+       [FEAT_PARAM_DOWNSCALE]                  = { 1, 2 },
 };
 
 static const struct dss_param_range omap3_dss_param_range[] = {
        [FEAT_PARAM_DSS_FCK]                    = { 0, 173000000 },
+       [FEAT_PARAM_DSS_PCD]                    = { 1, 255 },
        [FEAT_PARAM_DSIPLL_REGN]                = { 0, (1 << 7) - 1 },
        [FEAT_PARAM_DSIPLL_REGM]                = { 0, (1 << 11) - 1 },
        [FEAT_PARAM_DSIPLL_REGM_DISPC]          = { 0, (1 << 4) - 1 },
        [FEAT_PARAM_DSIPLL_REGM_DSI]            = { 0, (1 << 4) - 1 },
        [FEAT_PARAM_DSIPLL_FINT]                = { 750000, 2100000 },
        [FEAT_PARAM_DSIPLL_LPDIV]               = { 1, (1 << 13) - 1},
+       [FEAT_PARAM_DOWNSCALE]                  = { 1, 4 },
 };
 
 static const struct dss_param_range omap4_dss_param_range[] = {
        [FEAT_PARAM_DSS_FCK]                    = { 0, 186000000 },
+       [FEAT_PARAM_DSS_PCD]                    = { 1, 255 },
        [FEAT_PARAM_DSIPLL_REGN]                = { 0, (1 << 8) - 1 },
        [FEAT_PARAM_DSIPLL_REGM]                = { 0, (1 << 12) - 1 },
        [FEAT_PARAM_DSIPLL_REGM_DISPC]          = { 0, (1 << 5) - 1 },
        [FEAT_PARAM_DSIPLL_REGM_DSI]            = { 0, (1 << 5) - 1 },
        [FEAT_PARAM_DSIPLL_FINT]                = { 500000, 2500000 },
        [FEAT_PARAM_DSIPLL_LPDIV]               = { 0, (1 << 13) - 1 },
+       [FEAT_PARAM_DOWNSCALE]                  = { 1, 4 },
 };
 
 /* OMAP2 DSS Features */
@@ -275,6 +344,7 @@ static const struct omap_dss_features omap2_dss_features = {
        .num_ovls = 3,
        .supported_displays = omap2_dss_supported_displays,
        .supported_color_modes = omap2_dss_supported_color_modes,
+       .overlay_caps = omap2_dss_overlay_caps,
        .clksrc_names = omap2_dss_clk_source_names,
        .dss_params = omap2_dss_param_range,
        .buffer_size_unit = 1,
@@ -287,18 +357,19 @@ static const struct omap_dss_features omap3430_dss_features = {
        .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
 
        .has_feature    =
-               FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL |
+               FEAT_LCDENABLEPOL |
                FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
                FEAT_FUNCGATED | FEAT_ROWREPEATENABLE |
                FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF |
                FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC |
                FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD |
-               FEAT_FIR_COEF_V,
+               FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER,
 
        .num_mgrs = 2,
        .num_ovls = 3,
        .supported_displays = omap3430_dss_supported_displays,
        .supported_color_modes = omap3_dss_supported_color_modes,
+       .overlay_caps = omap3430_dss_overlay_caps,
        .clksrc_names = omap3_dss_clk_source_names,
        .dss_params = omap3_dss_param_range,
        .buffer_size_unit = 1,
@@ -310,18 +381,19 @@ static const struct omap_dss_features omap3630_dss_features = {
        .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
 
        .has_feature    =
-               FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL |
+               FEAT_LCDENABLEPOL |
                FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
-               FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED |
+               FEAT_FUNCGATED |
                FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT |
                FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG |
                FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD |
-               FEAT_FIR_COEF_V,
+               FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER,
 
        .num_mgrs = 2,
        .num_ovls = 3,
        .supported_displays = omap3630_dss_supported_displays,
        .supported_color_modes = omap3_dss_supported_color_modes,
+       .overlay_caps = omap3630_dss_overlay_caps,
        .clksrc_names = omap3_dss_clk_source_names,
        .dss_params = omap3_dss_param_range,
        .buffer_size_unit = 1,
@@ -335,17 +407,18 @@ static const struct omap_dss_features omap4430_es1_0_dss_features  = {
        .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
 
        .has_feature    =
-               FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA |
-               FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 |
+               FEAT_MGR_LCD2 |
                FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
                FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
                FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 |
-               FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V,
+               FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V |
+               FEAT_ALPHA_FREE_ZORDER,
 
        .num_mgrs = 3,
-       .num_ovls = 3,
+       .num_ovls = 4,
        .supported_displays = omap4_dss_supported_displays,
        .supported_color_modes = omap4_dss_supported_color_modes,
+       .overlay_caps = omap4_dss_overlay_caps,
        .clksrc_names = omap4_dss_clk_source_names,
        .dss_params = omap4_dss_param_range,
        .buffer_size_unit = 16,
@@ -358,24 +431,50 @@ static const struct omap_dss_features omap4_dss_features = {
        .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
 
        .has_feature    =
-               FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA |
-               FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 |
+               FEAT_MGR_LCD2 |
                FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
                FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
                FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE |
                FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR |
-               FEAT_PRELOAD | FEAT_FIR_COEF_V,
+               FEAT_PRELOAD | FEAT_FIR_COEF_V | FEAT_ALPHA_FREE_ZORDER,
 
        .num_mgrs = 3,
-       .num_ovls = 3,
+       .num_ovls = 4,
        .supported_displays = omap4_dss_supported_displays,
        .supported_color_modes = omap4_dss_supported_color_modes,
+       .overlay_caps = omap4_dss_overlay_caps,
        .clksrc_names = omap4_dss_clk_source_names,
        .dss_params = omap4_dss_param_range,
        .buffer_size_unit = 16,
        .burst_size_unit = 16,
 };
 
+#if defined(CONFIG_OMAP4_DSS_HDMI)
+/* HDMI OMAP4 Functions*/
+static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
+
+       .video_configure        =       ti_hdmi_4xxx_basic_configure,
+       .phy_enable             =       ti_hdmi_4xxx_phy_enable,
+       .phy_disable            =       ti_hdmi_4xxx_phy_disable,
+       .read_edid              =       ti_hdmi_4xxx_read_edid,
+       .detect                 =       ti_hdmi_4xxx_detect,
+       .pll_enable             =       ti_hdmi_4xxx_pll_enable,
+       .pll_disable            =       ti_hdmi_4xxx_pll_disable,
+       .video_enable           =       ti_hdmi_4xxx_wp_video_start,
+       .dump_wrapper           =       ti_hdmi_4xxx_wp_dump,
+       .dump_core              =       ti_hdmi_4xxx_core_dump,
+       .dump_pll               =       ti_hdmi_4xxx_pll_dump,
+       .dump_phy               =       ti_hdmi_4xxx_phy_dump,
+
+};
+
+void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data)
+{
+       if (cpu_is_omap44xx())
+               ip_data->ops = &omap4_hdmi_functions;
+}
+#endif
+
 /* Functions returning values related to a DSS feature */
 int dss_feat_get_num_mgrs(void)
 {
@@ -407,6 +506,11 @@ enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)
        return omap_current_dss_features->supported_color_modes[plane];
 }
 
+enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane)
+{
+       return omap_current_dss_features->overlay_caps[plane];
+}
+
 bool dss_feat_color_mode_supported(enum omap_plane plane,
                enum omap_color_mode color_mode)
 {
index b7398cb..6a6c05d 100644 (file)
 #ifndef __OMAP2_DSS_FEATURES_H
 #define __OMAP2_DSS_FEATURES_H
 
+#if defined(CONFIG_OMAP4_DSS_HDMI)
+#include "ti_hdmi.h"
+#endif
+
 #define MAX_DSS_MANAGERS       3
-#define MAX_DSS_OVERLAYS       3
+#define MAX_DSS_OVERLAYS       4
 #define MAX_DSS_LCD_MANAGERS   2
 #define MAX_NUM_DSI            2
 
 /* DSS has feature id */
 enum dss_feat_id {
-       FEAT_GLOBAL_ALPHA               = 1 << 0,
-       FEAT_GLOBAL_ALPHA_VID1          = 1 << 1,
-       FEAT_PRE_MULT_ALPHA             = 1 << 2,
        FEAT_LCDENABLEPOL               = 1 << 3,
        FEAT_LCDENABLESIGNAL            = 1 << 4,
        FEAT_PCKFREEENABLE              = 1 << 5,
@@ -55,6 +56,8 @@ enum dss_feat_id {
        FEAT_CPR                        = 1 << 23,
        FEAT_PRELOAD                    = 1 << 24,
        FEAT_FIR_COEF_V                 = 1 << 25,
+       FEAT_ALPHA_FIXED_ZORDER         = 1 << 26,
+       FEAT_ALPHA_FREE_ZORDER          = 1 << 27,
 };
 
 /* DSS register field id */
@@ -75,12 +78,14 @@ enum dss_feat_reg_field {
 
 enum dss_range_param {
        FEAT_PARAM_DSS_FCK,
+       FEAT_PARAM_DSS_PCD,
        FEAT_PARAM_DSIPLL_REGN,
        FEAT_PARAM_DSIPLL_REGM,
        FEAT_PARAM_DSIPLL_REGM_DISPC,
        FEAT_PARAM_DSIPLL_REGM_DSI,
        FEAT_PARAM_DSIPLL_FINT,
        FEAT_PARAM_DSIPLL_LPDIV,
+       FEAT_PARAM_DOWNSCALE,
 };
 
 /* DSS Feature Functions */
@@ -90,6 +95,7 @@ unsigned long dss_feat_get_param_min(enum dss_range_param param);
 unsigned long dss_feat_get_param_max(enum dss_range_param param);
 enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);
 enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
+enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane);
 bool dss_feat_color_mode_supported(enum omap_plane plane,
                enum omap_color_mode color_mode);
 const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id);
@@ -100,4 +106,7 @@ u32 dss_feat_get_burst_size_unit(void);             /* in bytes */
 bool dss_has_feature(enum dss_feat_id id);
 void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
 void dss_features_init(void);
+#if defined(CONFIG_OMAP4_DSS_HDMI)
+void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data);
+#endif
 #endif
index 256f27a..3262f0f 100644 (file)
        defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
 #include <sound/soc.h>
 #include <sound/pcm_params.h>
+#include "ti_hdmi_4xxx_ip.h"
 #endif
 
+#include "ti_hdmi.h"
 #include "dss.h"
-#include "hdmi.h"
 #include "dss_features.h"
 
+#define HDMI_WP                        0x0
+#define HDMI_CORE_SYS          0x400
+#define HDMI_CORE_AV           0x900
+#define HDMI_PLLCTRL           0x200
+#define HDMI_PHY               0x300
+
+/* HDMI EDID Length move this */
+#define HDMI_EDID_MAX_LENGTH                   256
+#define EDID_TIMING_DESCRIPTOR_SIZE            0x12
+#define EDID_DESCRIPTOR_BLOCK0_ADDRESS         0x36
+#define EDID_DESCRIPTOR_BLOCK1_ADDRESS         0x80
+#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR     4
+#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR     4
+
+#define OMAP_HDMI_TIMINGS_NB                   34
+
+#define HDMI_DEFAULT_REGN 16
+#define HDMI_DEFAULT_REGM2 1
+
 static struct {
        struct mutex lock;
        struct omap_display_platform_data *pdata;
        struct platform_device *pdev;
-       void __iomem *base_wp;  /* HDMI wrapper */
+       struct hdmi_ip_data ip_data;
        int code;
        int mode;
-       u8 edid[HDMI_EDID_MAX_LENGTH];
-       u8 edid_set;
-       bool custom_set;
-       struct hdmi_config cfg;
 
        struct clk *sys_clk;
-       struct clk *hdmi_clk;
 } hdmi;
 
 /*
@@ -144,30 +159,6 @@ static const int code_vesa[85] = {
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, 27, 28, -1, 33};
 
-static const u8 edid_header[8] = {0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0};
-
-static inline void hdmi_write_reg(const struct hdmi_reg idx, u32 val)
-{
-       __raw_writel(val, hdmi.base_wp + idx.idx);
-}
-
-static inline u32 hdmi_read_reg(const struct hdmi_reg idx)
-{
-       return __raw_readl(hdmi.base_wp + idx.idx);
-}
-
-static inline int hdmi_wait_for_bit_change(const struct hdmi_reg idx,
-                               int b2, int b1, u32 val)
-{
-       u32 t = 0;
-       while (val != REG_GET(idx, b2, b1)) {
-               udelay(1);
-               if (t++ > 10000)
-                       return !val;
-       }
-       return val;
-}
-
 static int hdmi_runtime_get(void)
 {
        int r;
@@ -193,304 +184,7 @@ int hdmi_init_display(struct omap_dss_device *dssdev)
 {
        DSSDBG("init_display\n");
 
-       return 0;
-}
-
-static int hdmi_pll_init(enum hdmi_clk_refsel refsel, int dcofreq,
-               struct hdmi_pll_info *fmt, u16 sd)
-{
-       u32 r;
-
-       /* PLL start always use manual mode */
-       REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 0, 0);
-
-       r = hdmi_read_reg(PLLCTRL_CFG1);
-       r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */
-       r = FLD_MOD(r, fmt->regn, 8, 1);  /* CFG1_PLL_REGN */
-
-       hdmi_write_reg(PLLCTRL_CFG1, r);
-
-       r = hdmi_read_reg(PLLCTRL_CFG2);
-
-       r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */
-       r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */
-       r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */
-
-       if (dcofreq) {
-               /* divider programming for frequency beyond 1000Mhz */
-               REG_FLD_MOD(PLLCTRL_CFG3, sd, 17, 10);
-               r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */
-       } else {
-               r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */
-       }
-
-       hdmi_write_reg(PLLCTRL_CFG2, r);
-
-       r = hdmi_read_reg(PLLCTRL_CFG4);
-       r = FLD_MOD(r, fmt->regm2, 24, 18);
-       r = FLD_MOD(r, fmt->regmf, 17, 0);
-
-       hdmi_write_reg(PLLCTRL_CFG4, r);
-
-       /* go now */
-       REG_FLD_MOD(PLLCTRL_PLL_GO, 0x1, 0, 0);
-
-       /* wait for bit change */
-       if (hdmi_wait_for_bit_change(PLLCTRL_PLL_GO, 0, 0, 1) != 1) {
-               DSSERR("PLL GO bit not set\n");
-               return -ETIMEDOUT;
-       }
-
-       /* Wait till the lock bit is set in PLL status */
-       if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) {
-               DSSWARN("cannot lock PLL\n");
-               DSSWARN("CFG1 0x%x\n",
-                       hdmi_read_reg(PLLCTRL_CFG1));
-               DSSWARN("CFG2 0x%x\n",
-                       hdmi_read_reg(PLLCTRL_CFG2));
-               DSSWARN("CFG4 0x%x\n",
-                       hdmi_read_reg(PLLCTRL_CFG4));
-               return -ETIMEDOUT;
-       }
-
-       DSSDBG("PLL locked!\n");
-
-       return 0;
-}
-
-/* PHY_PWR_CMD */
-static int hdmi_set_phy_pwr(enum hdmi_phy_pwr val)
-{
-       /* Command for power control of HDMI PHY */
-       REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 7, 6);
-
-       /* Status of the power control of HDMI PHY */
-       if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 5, 4, val) != val) {
-               DSSERR("Failed to set PHY power mode to %d\n", val);
-               return -ETIMEDOUT;
-       }
-
-       return 0;
-}
-
-/* PLL_PWR_CMD */
-static int hdmi_set_pll_pwr(enum hdmi_pll_pwr val)
-{
-       /* Command for power control of HDMI PLL */
-       REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 3, 2);
-
-       /* wait till PHY_PWR_STATUS is set */
-       if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 1, 0, val) != val) {
-               DSSERR("Failed to set PHY_PWR_STATUS\n");
-               return -ETIMEDOUT;
-       }
-
-       return 0;
-}
-
-static int hdmi_pll_reset(void)
-{
-       /* SYSRESET  controlled by power FSM */
-       REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 3, 3);
-
-       /* READ 0x0 reset is in progress */
-       if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) {
-               DSSERR("Failed to sysreset PLL\n");
-               return -ETIMEDOUT;
-       }
-
-       return 0;
-}
-
-static int hdmi_phy_init(void)
-{
-       u16 r = 0;
-
-       r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_LDOON);
-       if (r)
-               return r;
-
-       r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_TXON);
-       if (r)
-               return r;
-
-       /*
-        * Read address 0 in order to get the SCP reset done completed
-        * Dummy access performed to make sure reset is done
-        */
-       hdmi_read_reg(HDMI_TXPHY_TX_CTRL);
-
-       /*
-        * Write to phy address 0 to configure the clock
-        * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field
-        */
-       REG_FLD_MOD(HDMI_TXPHY_TX_CTRL, 0x1, 31, 30);
-
-       /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */
-       hdmi_write_reg(HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000);
-
-       /* Setup max LDO voltage */
-       REG_FLD_MOD(HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0);
-
-       /* Write to phy address 3 to change the polarity control */
-       REG_FLD_MOD(HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27);
-
-       return 0;
-}
-
-static int hdmi_pll_program(struct hdmi_pll_info *fmt)
-{
-       u16 r = 0;
-       enum hdmi_clk_refsel refsel;
-
-       r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
-       if (r)
-               return r;
-
-       r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
-       if (r)
-               return r;
-
-       r = hdmi_pll_reset();
-       if (r)
-               return r;
-
-       refsel = HDMI_REFSEL_SYSCLK;
-
-       r = hdmi_pll_init(refsel, fmt->dcofreq, fmt, fmt->regsd);
-       if (r)
-               return r;
-
-       return 0;
-}
-
-static void hdmi_phy_off(void)
-{
-       hdmi_set_phy_pwr(HDMI_PHYPWRCMD_OFF);
-}
-
-static int hdmi_core_ddc_edid(u8 *pedid, int ext)
-{
-       u32 i, j;
-       char checksum = 0;
-       u32 offset = 0;
-
-       /* Turn on CLK for DDC */
-       REG_FLD_MOD(HDMI_CORE_AV_DPD, 0x7, 2, 0);
-
-       /*
-        * SW HACK : Without the Delay DDC(i2c bus) reads 0 values /
-        * right shifted values( The behavior is not consistent and seen only
-        * with some TV's)
-        */
-       usleep_range(800, 1000);
-
-       if (!ext) {
-               /* Clk SCL Devices */
-               REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0xA, 3, 0);
-
-               /* HDMI_CORE_DDC_STATUS_IN_PROG */
-               if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS,
-                                               4, 4, 0) != 0) {
-                       DSSERR("Failed to program DDC\n");
-                       return -ETIMEDOUT;
-               }
-
-               /* Clear FIFO */
-               REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x9, 3, 0);
-
-               /* HDMI_CORE_DDC_STATUS_IN_PROG */
-               if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS,
-                                               4, 4, 0) != 0) {
-                       DSSERR("Failed to program DDC\n");
-                       return -ETIMEDOUT;
-               }
-
-       } else {
-               if (ext % 2 != 0)
-                       offset = 0x80;
-       }
-
-       /* Load Segment Address Register */
-       REG_FLD_MOD(HDMI_CORE_DDC_SEGM, ext/2, 7, 0);
-
-       /* Load Slave Address Register */
-       REG_FLD_MOD(HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1);
-
-       /* Load Offset Address Register */
-       REG_FLD_MOD(HDMI_CORE_DDC_OFFSET, offset, 7, 0);
-
-       /* Load Byte Count */
-       REG_FLD_MOD(HDMI_CORE_DDC_COUNT1, 0x80, 7, 0);
-       REG_FLD_MOD(HDMI_CORE_DDC_COUNT2, 0x0, 1, 0);
-
-       /* Set DDC_CMD */
-       if (ext)
-               REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x4, 3, 0);
-       else
-               REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x2, 3, 0);
-
-       /* HDMI_CORE_DDC_STATUS_BUS_LOW */
-       if (REG_GET(HDMI_CORE_DDC_STATUS, 6, 6) == 1) {
-               DSSWARN("I2C Bus Low?\n");
-               return -EIO;
-       }
-       /* HDMI_CORE_DDC_STATUS_NO_ACK */
-       if (REG_GET(HDMI_CORE_DDC_STATUS, 5, 5) == 1) {
-               DSSWARN("I2C No Ack\n");
-               return -EIO;
-       }
-
-       i = ext * 128;
-       j = 0;
-       while (((REG_GET(HDMI_CORE_DDC_STATUS, 4, 4) == 1) ||
-                       (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0)) &&
-                       j < 128) {
-
-               if (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0) {
-                       /* FIFO not empty */
-                       pedid[i++] = REG_GET(HDMI_CORE_DDC_DATA, 7, 0);
-                       j++;
-               }
-       }
-
-       for (j = 0; j < 128; j++)
-               checksum += pedid[j];
-
-       if (checksum != 0) {
-               DSSERR("E-EDID checksum failed!!\n");
-               return -EIO;
-       }
-
-       return 0;
-}
-
-static int read_edid(u8 *pedid, u16 max_length)
-{
-       int r = 0, n = 0, i = 0;
-       int max_ext_blocks = (max_length / 128) - 1;
-
-       r = hdmi_core_ddc_edid(pedid, 0);
-       if (r) {
-               return r;
-       } else {
-               n = pedid[0x7e];
-
-               /*
-                * README: need to comply with max_length set by the caller.
-                * Better implementation should be to allocate necessary
-                * memory to store EDID according to nb_block field found
-                * in first block
-                */
-               if (n > max_ext_blocks)
-                       n = max_ext_blocks;
-
-               for (i = 1; i <= n; i++) {
-                       r = hdmi_core_ddc_edid(pedid, i);
-                       if (r)
-                               return r;
-               }
-       }
+       dss_init_hdmi_ip_ops(&hdmi.ip_data);
        return 0;
 }
 
@@ -518,7 +212,7 @@ static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
 {
        int i = 0, code = -1, temp_vsync = 0, temp_hsync = 0;
        int timing_vsync = 0, timing_hsync = 0;
-       struct omap_video_timings temp;
+       struct hdmi_video_timings temp;
        struct hdmi_cm cm = {-1};
        DSSDBG("hdmi_get_code\n");
 
@@ -556,500 +250,6 @@ static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
        return cm;
 }
 
-static void get_horz_vert_timing_info(int current_descriptor_addrs, u8 *edid ,
-               struct omap_video_timings *timings)
-{
-       /* X and Y resolution */
-       timings->x_res = (((edid[current_descriptor_addrs + 4] & 0xF0) << 4) |
-                        edid[current_descriptor_addrs + 2]);
-       timings->y_res = (((edid[current_descriptor_addrs + 7] & 0xF0) << 4) |
-                        edid[current_descriptor_addrs + 5]);
-
-       timings->pixel_clock = ((edid[current_descriptor_addrs + 1] << 8) |
-                               edid[current_descriptor_addrs]);
-
-       timings->pixel_clock = 10 * timings->pixel_clock;
-
-       /* HORIZONTAL FRONT PORCH */
-       timings->hfp = edid[current_descriptor_addrs + 8] |
-                       ((edid[current_descriptor_addrs + 11] & 0xc0) << 2);
-       /* HORIZONTAL SYNC WIDTH */
-       timings->hsw = edid[current_descriptor_addrs + 9] |
-                       ((edid[current_descriptor_addrs + 11] & 0x30) << 4);
-       /* HORIZONTAL BACK PORCH */
-       timings->hbp = (((edid[current_descriptor_addrs + 4] & 0x0F) << 8) |
-                       edid[current_descriptor_addrs + 3]) -
-                       (timings->hfp + timings->hsw);
-       /* VERTICAL FRONT PORCH */
-       timings->vfp = ((edid[current_descriptor_addrs + 10] & 0xF0) >> 4) |
-                       ((edid[current_descriptor_addrs + 11] & 0x0f) << 2);
-       /* VERTICAL SYNC WIDTH */
-       timings->vsw = (edid[current_descriptor_addrs + 10] & 0x0F) |
-                       ((edid[current_descriptor_addrs + 11] & 0x03) << 4);
-       /* VERTICAL BACK PORCH */
-       timings->vbp = (((edid[current_descriptor_addrs + 7] & 0x0F) << 8) |
-                       edid[current_descriptor_addrs + 6]) -
-                       (timings->vfp + timings->vsw);
-
-}
-
-/* Description : This function gets the resolution information from EDID */
-static void get_edid_timing_data(u8 *edid)
-{
-       u8 count;
-       u16 current_descriptor_addrs;
-       struct hdmi_cm cm;
-       struct omap_video_timings edid_timings;
-
-       /* search block 0, there are 4 DTDs arranged in priority order */
-       for (count = 0; count < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; count++) {
-               current_descriptor_addrs =
-                       EDID_DESCRIPTOR_BLOCK0_ADDRESS +
-                       count * EDID_TIMING_DESCRIPTOR_SIZE;
-               get_horz_vert_timing_info(current_descriptor_addrs,
-                               edid, &edid_timings);
-               cm = hdmi_get_code(&edid_timings);
-               DSSDBG("Block0[%d] value matches code = %d , mode = %d\n",
-                       count, cm.code, cm.mode);
-               if (cm.code == -1) {
-                       continue;
-               } else {
-                       hdmi.code = cm.code;
-                       hdmi.mode = cm.mode;
-                       DSSDBG("code = %d , mode = %d\n",
-                               hdmi.code, hdmi.mode);
-                       return;
-               }
-       }
-       if (edid[0x7e] != 0x00) {
-               for (count = 0; count < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR;
-                       count++) {
-                       current_descriptor_addrs =
-                       EDID_DESCRIPTOR_BLOCK1_ADDRESS +
-                       count * EDID_TIMING_DESCRIPTOR_SIZE;
-                       get_horz_vert_timing_info(current_descriptor_addrs,
-                                               edid, &edid_timings);
-                       cm = hdmi_get_code(&edid_timings);
-                       DSSDBG("Block1[%d] value matches code = %d, mode = %d",
-                               count, cm.code, cm.mode);
-                       if (cm.code == -1) {
-                               continue;
-                       } else {
-                               hdmi.code = cm.code;
-                               hdmi.mode = cm.mode;
-                               DSSDBG("code = %d , mode = %d\n",
-                                       hdmi.code, hdmi.mode);
-                               return;
-                       }
-               }
-       }
-
-       DSSINFO("no valid timing found , falling back to VGA\n");
-       hdmi.code = 4; /* setting default value of 640 480 VGA */
-       hdmi.mode = HDMI_DVI;
-}
-
-static void hdmi_read_edid(struct omap_video_timings *dp)
-{
-       int ret = 0, code;
-
-       memset(hdmi.edid, 0, HDMI_EDID_MAX_LENGTH);
-
-       if (!hdmi.edid_set)
-               ret = read_edid(hdmi.edid, HDMI_EDID_MAX_LENGTH);
-
-       if (!ret) {
-               if (!memcmp(hdmi.edid, edid_header, sizeof(edid_header))) {
-                       /* search for timings of default resolution */
-                       get_edid_timing_data(hdmi.edid);
-                       hdmi.edid_set = true;
-               }
-       } else {
-               DSSWARN("failed to read E-EDID\n");
-       }
-
-       if (!hdmi.edid_set) {
-               DSSINFO("fallback to VGA\n");
-               hdmi.code = 4; /* setting default value of 640 480 VGA */
-               hdmi.mode = HDMI_DVI;
-       }
-
-       code = get_timings_index();
-
-       *dp = cea_vesa_timings[code].timings;
-}
-
-static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,
-                       struct hdmi_core_infoframe_avi *avi_cfg,
-                       struct hdmi_core_packet_enable_repeat *repeat_cfg)
-{
-       DSSDBG("Enter hdmi_core_init\n");
-
-       /* video core */
-       video_cfg->ip_bus_width = HDMI_INPUT_8BIT;
-       video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT;
-       video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE;
-       video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE;
-       video_cfg->hdmi_dvi = HDMI_DVI;
-       video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK;
-
-       /* info frame */
-       avi_cfg->db1_format = 0;
-       avi_cfg->db1_active_info = 0;
-       avi_cfg->db1_bar_info_dv = 0;
-       avi_cfg->db1_scan_info = 0;
-       avi_cfg->db2_colorimetry = 0;
-       avi_cfg->db2_aspect_ratio = 0;
-       avi_cfg->db2_active_fmt_ar = 0;
-       avi_cfg->db3_itc = 0;
-       avi_cfg->db3_ec = 0;
-       avi_cfg->db3_q_range = 0;
-       avi_cfg->db3_nup_scaling = 0;
-       avi_cfg->db4_videocode = 0;
-       avi_cfg->db5_pixel_repeat = 0;
-       avi_cfg->db6_7_line_eoftop = 0 ;
-       avi_cfg->db8_9_line_sofbottom = 0;
-       avi_cfg->db10_11_pixel_eofleft = 0;
-       avi_cfg->db12_13_pixel_sofright = 0;
-
-       /* packet enable and repeat */
-       repeat_cfg->audio_pkt = 0;
-       repeat_cfg->audio_pkt_repeat = 0;
-       repeat_cfg->avi_infoframe = 0;
-       repeat_cfg->avi_infoframe_repeat = 0;
-       repeat_cfg->gen_cntrl_pkt = 0;
-       repeat_cfg->gen_cntrl_pkt_repeat = 0;
-       repeat_cfg->generic_pkt = 0;
-       repeat_cfg->generic_pkt_repeat = 0;
-}
-
-static void hdmi_core_powerdown_disable(void)
-{
-       DSSDBG("Enter hdmi_core_powerdown_disable\n");
-       REG_FLD_MOD(HDMI_CORE_CTRL1, 0x0, 0, 0);
-}
-
-static void hdmi_core_swreset_release(void)
-{
-       DSSDBG("Enter hdmi_core_swreset_release\n");
-       REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x0, 0, 0);
-}
-
-static void hdmi_core_swreset_assert(void)
-{
-       DSSDBG("Enter hdmi_core_swreset_assert\n");
-       REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x1, 0, 0);
-}
-
-/* DSS_HDMI_CORE_VIDEO_CONFIG */
-static void hdmi_core_video_config(struct hdmi_core_video_config *cfg)
-{
-       u32 r = 0;
-
-       /* sys_ctrl1 default configuration not tunable */
-       r = hdmi_read_reg(HDMI_CORE_CTRL1);
-       r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5);
-       r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4);
-       r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2);
-       r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1);
-       hdmi_write_reg(HDMI_CORE_CTRL1, r);
-
-       REG_FLD_MOD(HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6);
-
-       /* Vid_Mode */
-       r = hdmi_read_reg(HDMI_CORE_SYS_VID_MODE);
-
-       /* dither truncation configuration */
-       if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) {
-               r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6);
-               r = FLD_MOD(r, 1, 5, 5);
-       } else {
-               r = FLD_MOD(r, cfg->op_dither_truc, 7, 6);
-               r = FLD_MOD(r, 0, 5, 5);
-       }
-       hdmi_write_reg(HDMI_CORE_SYS_VID_MODE, r);
-
-       /* HDMI_Ctrl */
-       r = hdmi_read_reg(HDMI_CORE_AV_HDMI_CTRL);
-       r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6);
-       r = FLD_MOD(r, cfg->pkt_mode, 5, 3);
-       r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0);
-       hdmi_write_reg(HDMI_CORE_AV_HDMI_CTRL, r);
-
-       /* TMDS_CTRL */
-       REG_FLD_MOD(HDMI_CORE_SYS_TMDS_CTRL,
-               cfg->tclk_sel_clkmult, 6, 5);
-}
-
-static void hdmi_core_aux_infoframe_avi_config(
-               struct hdmi_core_infoframe_avi info_avi)
-{
-       u32 val;
-       char sum = 0, checksum = 0;
-
-       sum += 0x82 + 0x002 + 0x00D;
-       hdmi_write_reg(HDMI_CORE_AV_AVI_TYPE, 0x082);
-       hdmi_write_reg(HDMI_CORE_AV_AVI_VERS, 0x002);
-       hdmi_write_reg(HDMI_CORE_AV_AVI_LEN, 0x00D);
-
-       val = (info_avi.db1_format << 5) |
-               (info_avi.db1_active_info << 4) |
-               (info_avi.db1_bar_info_dv << 2) |
-               (info_avi.db1_scan_info);
-       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(0), val);
-       sum += val;
-
-       val = (info_avi.db2_colorimetry << 6) |
-               (info_avi.db2_aspect_ratio << 4) |
-               (info_avi.db2_active_fmt_ar);
-       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(1), val);
-       sum += val;
-
-       val = (info_avi.db3_itc << 7) |
-               (info_avi.db3_ec << 4) |
-               (info_avi.db3_q_range << 2) |
-               (info_avi.db3_nup_scaling);
-       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(2), val);
-       sum += val;
-
-       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(3), info_avi.db4_videocode);
-       sum += info_avi.db4_videocode;
-
-       val = info_avi.db5_pixel_repeat;
-       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(4), val);
-       sum += val;
-
-       val = info_avi.db6_7_line_eoftop & 0x00FF;
-       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(5), val);
-       sum += val;
-
-       val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF);
-       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(6), val);
-       sum += val;
-
-       val = info_avi.db8_9_line_sofbottom & 0x00FF;
-       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(7), val);
-       sum += val;
-
-       val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF);
-       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(8), val);
-       sum += val;
-
-       val = info_avi.db10_11_pixel_eofleft & 0x00FF;
-       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(9), val);
-       sum += val;
-
-       val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF);
-       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(10), val);
-       sum += val;
-
-       val = info_avi.db12_13_pixel_sofright & 0x00FF;
-       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(11), val);
-       sum += val;
-
-       val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF);
-       hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(12), val);
-       sum += val;
-
-       checksum = 0x100 - sum;
-       hdmi_write_reg(HDMI_CORE_AV_AVI_CHSUM, checksum);
-}
-
-static void hdmi_core_av_packet_config(
-               struct hdmi_core_packet_enable_repeat repeat_cfg)
-{
-       /* enable/repeat the infoframe */
-       hdmi_write_reg(HDMI_CORE_AV_PB_CTRL1,
-               (repeat_cfg.audio_pkt << 5) |
-               (repeat_cfg.audio_pkt_repeat << 4) |
-               (repeat_cfg.avi_infoframe << 1) |
-               (repeat_cfg.avi_infoframe_repeat));
-
-       /* enable/repeat the packet */
-       hdmi_write_reg(HDMI_CORE_AV_PB_CTRL2,
-               (repeat_cfg.gen_cntrl_pkt << 3) |
-               (repeat_cfg.gen_cntrl_pkt_repeat << 2) |
-               (repeat_cfg.generic_pkt << 1) |
-               (repeat_cfg.generic_pkt_repeat));
-}
-
-static void hdmi_wp_init(struct omap_video_timings *timings,
-                       struct hdmi_video_format *video_fmt,
-                       struct hdmi_video_interface *video_int)
-{
-       DSSDBG("Enter hdmi_wp_init\n");
-
-       timings->hbp = 0;
-       timings->hfp = 0;
-       timings->hsw = 0;
-       timings->vbp = 0;
-       timings->vfp = 0;
-       timings->vsw = 0;
-
-       video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444;
-       video_fmt->y_res = 0;
-       video_fmt->x_res = 0;
-
-       video_int->vsp = 0;
-       video_int->hsp = 0;
-
-       video_int->interlacing = 0;
-       video_int->tm = 0; /* HDMI_TIMING_SLAVE */
-
-}
-
-static void hdmi_wp_video_start(bool start)
-{
-       REG_FLD_MOD(HDMI_WP_VIDEO_CFG, start, 31, 31);
-}
-
-static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt,
-       struct omap_video_timings *timings, struct hdmi_config *param)
-{
-       DSSDBG("Enter hdmi_wp_video_init_format\n");
-
-       video_fmt->y_res = param->timings.timings.y_res;
-       video_fmt->x_res = param->timings.timings.x_res;
-
-       timings->hbp = param->timings.timings.hbp;
-       timings->hfp = param->timings.timings.hfp;
-       timings->hsw = param->timings.timings.hsw;
-       timings->vbp = param->timings.timings.vbp;
-       timings->vfp = param->timings.timings.vfp;
-       timings->vsw = param->timings.timings.vsw;
-}
-
-static void hdmi_wp_video_config_format(
-               struct hdmi_video_format *video_fmt)
-{
-       u32 l = 0;
-
-       REG_FLD_MOD(HDMI_WP_VIDEO_CFG, video_fmt->packing_mode, 10, 8);
-
-       l |= FLD_VAL(video_fmt->y_res, 31, 16);
-       l |= FLD_VAL(video_fmt->x_res, 15, 0);
-       hdmi_write_reg(HDMI_WP_VIDEO_SIZE, l);
-}
-
-static void hdmi_wp_video_config_interface(
-               struct hdmi_video_interface *video_int)
-{
-       u32 r;
-       DSSDBG("Enter hdmi_wp_video_config_interface\n");
-
-       r = hdmi_read_reg(HDMI_WP_VIDEO_CFG);
-       r = FLD_MOD(r, video_int->vsp, 7, 7);
-       r = FLD_MOD(r, video_int->hsp, 6, 6);
-       r = FLD_MOD(r, video_int->interlacing, 3, 3);
-       r = FLD_MOD(r, video_int->tm, 1, 0);
-       hdmi_write_reg(HDMI_WP_VIDEO_CFG, r);
-}
-
-static void hdmi_wp_video_config_timing(
-               struct omap_video_timings *timings)
-{
-       u32 timing_h = 0;
-       u32 timing_v = 0;
-
-       DSSDBG("Enter hdmi_wp_video_config_timing\n");
-
-       timing_h |= FLD_VAL(timings->hbp, 31, 20);
-       timing_h |= FLD_VAL(timings->hfp, 19, 8);
-       timing_h |= FLD_VAL(timings->hsw, 7, 0);
-       hdmi_write_reg(HDMI_WP_VIDEO_TIMING_H, timing_h);
-
-       timing_v |= FLD_VAL(timings->vbp, 31, 20);
-       timing_v |= FLD_VAL(timings->vfp, 19, 8);
-       timing_v |= FLD_VAL(timings->vsw, 7, 0);
-       hdmi_write_reg(HDMI_WP_VIDEO_TIMING_V, timing_v);
-}
-
-static void hdmi_basic_configure(struct hdmi_config *cfg)
-{
-       /* HDMI */
-       struct omap_video_timings video_timing;
-       struct hdmi_video_format video_format;
-       struct hdmi_video_interface video_interface;
-       /* HDMI core */
-       struct hdmi_core_infoframe_avi avi_cfg;
-       struct hdmi_core_video_config v_core_cfg;
-       struct hdmi_core_packet_enable_repeat repeat_cfg;
-
-       hdmi_wp_init(&video_timing, &video_format,
-               &video_interface);
-
-       hdmi_core_init(&v_core_cfg,
-               &avi_cfg,
-               &repeat_cfg);
-
-       hdmi_wp_video_init_format(&video_format,
-                       &video_timing, cfg);
-
-       hdmi_wp_video_config_timing(&video_timing);
-
-       /* video config */
-       video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422;
-
-       hdmi_wp_video_config_format(&video_format);
-
-       video_interface.vsp = cfg->timings.vsync_pol;
-       video_interface.hsp = cfg->timings.hsync_pol;
-       video_interface.interlacing = cfg->interlace;
-       video_interface.tm = 1 ; /* HDMI_TIMING_MASTER_24BIT */
-
-       hdmi_wp_video_config_interface(&video_interface);
-
-       /*
-        * configure core video part
-        * set software reset in the core
-        */
-       hdmi_core_swreset_assert();
-
-       /* power down off */
-       hdmi_core_powerdown_disable();
-
-       v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL;
-       v_core_cfg.hdmi_dvi = cfg->cm.mode;
-
-       hdmi_core_video_config(&v_core_cfg);
-
-       /* release software reset in the core */
-       hdmi_core_swreset_release();
-
-       /*
-        * configure packet
-        * info frame video see doc CEA861-D page 65
-        */
-       avi_cfg.db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB;
-       avi_cfg.db1_active_info =
-               HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF;
-       avi_cfg.db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO;
-       avi_cfg.db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0;
-       avi_cfg.db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO;
-       avi_cfg.db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO;
-       avi_cfg.db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME;
-       avi_cfg.db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO;
-       avi_cfg.db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601;
-       avi_cfg.db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT;
-       avi_cfg.db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO;
-       avi_cfg.db4_videocode = cfg->cm.code;
-       avi_cfg.db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO;
-       avi_cfg.db6_7_line_eoftop = 0;
-       avi_cfg.db8_9_line_sofbottom = 0;
-       avi_cfg.db10_11_pixel_eofleft = 0;
-       avi_cfg.db12_13_pixel_sofright = 0;
-
-       hdmi_core_aux_infoframe_avi_config(avi_cfg);
-
-       /* enable/repeat the infoframe */
-       repeat_cfg.avi_infoframe = HDMI_PACKETENABLE;
-       repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON;
-       /* wakeup */
-       repeat_cfg.audio_pkt = HDMI_PACKETENABLE;
-       repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON;
-       hdmi_core_av_packet_config(repeat_cfg);
-}
-
 static void update_hdmi_timings(struct hdmi_config *cfg,
                struct omap_video_timings *timings, int code)
 {
@@ -1066,6 +266,12 @@ static void update_hdmi_timings(struct hdmi_config *cfg,
        cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol;
 }
 
+unsigned long hdmi_get_pixel_clock(void)
+{
+       /* HDMI Pixel Clock in Mhz */
+       return hdmi.ip_data.cfg.timings.timings.pixel_clock * 10000;
+}
+
 static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
                struct hdmi_pll_info *pi)
 {
@@ -1077,15 +283,23 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
         * Input clock is predivided by N + 1
         * out put of which is reference clk
         */
-       pi->regn = dssdev->clocks.hdmi.regn;
-       refclk = clkin / (pi->regn + 1);
+       if (dssdev->clocks.hdmi.regn == 0)
+               pi->regn = HDMI_DEFAULT_REGN;
+       else
+               pi->regn = dssdev->clocks.hdmi.regn;
+
+       refclk = clkin / pi->regn;
 
        /*
         * multiplier is pixel_clk/ref_clk
         * Multiplying by 100 to avoid fractional part removal
         */
        pi->regm = (phy * 100 / (refclk)) / 100;
-       pi->regm2 = dssdev->clocks.hdmi.regm2;
+
+       if (dssdev->clocks.hdmi.regm2 == 0)
+               pi->regm2 = HDMI_DEFAULT_REGM2;
+       else
+               pi->regm2 = dssdev->clocks.hdmi.regm2;
 
        /*
         * fractional multiplier is remainder of the difference between
@@ -1100,7 +314,10 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
         * is greater than 1000MHz
         */
        pi->dcofreq = phy > 1000 * 100;
-       pi->regsd = ((pi->regm * clkin / 10) / ((pi->regn + 1) * 250) + 5) / 10;
+       pi->regsd = ((pi->regm * clkin / 10) / (pi->regn * 250) + 5) / 10;
+
+       /* Set the reference clock to sysclk reference */
+       pi->refsel = HDMI_REFSEL_SYSCLK;
 
        DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf);
        DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
@@ -1109,7 +326,6 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
 static int hdmi_power_on(struct omap_dss_device *dssdev)
 {
        int r, code = 0;
-       struct hdmi_pll_info pll_data;
        struct omap_video_timings *p;
        unsigned long phy;
 
@@ -1117,7 +333,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
        if (r)
                return r;
 
-       dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0);
+       dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 0);
 
        p = &dssdev->panel.timings;
 
@@ -1125,36 +341,31 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
                dssdev->panel.timings.x_res,
                dssdev->panel.timings.y_res);
 
-       if (!hdmi.custom_set) {
-               DSSDBG("Read EDID as no EDID is not set on poweron\n");
-               hdmi_read_edid(p);
-       }
        code = get_timings_index();
-       dssdev->panel.timings = cea_vesa_timings[code].timings;
-       update_hdmi_timings(&hdmi.cfg, p, code);
+       update_hdmi_timings(&hdmi.ip_data.cfg, p, code);
 
        phy = p->pixel_clock;
 
-       hdmi_compute_pll(dssdev, phy, &pll_data);
+       hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data);
 
-       hdmi_wp_video_start(0);
+       hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0);
 
-       /* config the PLL and PHY first */
-       r = hdmi_pll_program(&pll_data);
+       /* config the PLL and PHY hdmi_set_pll_pwrfirst */
+       r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data);
        if (r) {
                DSSDBG("Failed to lock PLL\n");
                goto err;
        }
 
-       r = hdmi_phy_init();
+       r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data);
        if (r) {
                DSSDBG("Failed to start PHY\n");
                goto err;
        }
 
-       hdmi.cfg.cm.mode = hdmi.mode;
-       hdmi.cfg.cm.code = hdmi.code;
-       hdmi_basic_configure(&hdmi.cfg);
+       hdmi.ip_data.cfg.cm.mode = hdmi.mode;
+       hdmi.ip_data.cfg.cm.code = hdmi.code;
+       hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
 
        /* Make selection of HDMI in DSS */
        dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
@@ -1174,9 +385,9 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
        dispc_set_digit_size(dssdev->panel.timings.x_res,
                        dssdev->panel.timings.y_res);
 
-       dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 1);
+       hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 1);
 
-       hdmi_wp_video_start(1);
+       dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 1);
 
        return 0;
 err:
@@ -1186,14 +397,12 @@ err:
 
 static void hdmi_power_off(struct omap_dss_device *dssdev)
 {
-       dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0);
+       dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 0);
 
-       hdmi_wp_video_start(0);
-       hdmi_phy_off();
-       hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
+       hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0);
+       hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
+       hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
        hdmi_runtime_put();
-
-       hdmi.edid_set = 0;
 }
 
 int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
@@ -1203,7 +412,6 @@ int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
 
        cm = hdmi_get_code(timings);
        if (cm.code == -1) {
-               DSSERR("Invalid timing entered\n");
                return -EINVAL;
        }
 
@@ -1215,12 +423,69 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
 {
        struct hdmi_cm cm;
 
-       hdmi.custom_set = 1;
        cm = hdmi_get_code(&dssdev->panel.timings);
        hdmi.code = cm.code;
        hdmi.mode = cm.mode;
-       omapdss_hdmi_display_enable(dssdev);
-       hdmi.custom_set = 0;
+
+       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
+               int r;
+
+               hdmi_power_off(dssdev);
+
+               r = hdmi_power_on(dssdev);
+               if (r)
+                       DSSERR("failed to power on device\n");
+       }
+}
+
+void hdmi_dump_regs(struct seq_file *s)
+{
+       mutex_lock(&hdmi.lock);
+
+       if (hdmi_runtime_get())
+               return;
+
+       hdmi.ip_data.ops->dump_wrapper(&hdmi.ip_data, s);
+       hdmi.ip_data.ops->dump_pll(&hdmi.ip_data, s);
+       hdmi.ip_data.ops->dump_phy(&hdmi.ip_data, s);
+       hdmi.ip_data.ops->dump_core(&hdmi.ip_data, s);
+
+       hdmi_runtime_put();
+       mutex_unlock(&hdmi.lock);
+}
+
+int omapdss_hdmi_read_edid(u8 *buf, int len)
+{
+       int r;
+
+       mutex_lock(&hdmi.lock);
+
+       r = hdmi_runtime_get();
+       BUG_ON(r);
+
+       r = hdmi.ip_data.ops->read_edid(&hdmi.ip_data, buf, len);
+
+       hdmi_runtime_put();
+       mutex_unlock(&hdmi.lock);
+
+       return r;
+}
+
+bool omapdss_hdmi_detect(void)
+{
+       int r;
+
+       mutex_lock(&hdmi.lock);
+
+       r = hdmi_runtime_get();
+       BUG_ON(r);
+
+       r = hdmi.ip_data.ops->detect(&hdmi.ip_data);
+
+       hdmi_runtime_put();
+       mutex_unlock(&hdmi.lock);
+
+       return r == 1;
 }
 
 int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
@@ -1231,6 +496,12 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
 
        mutex_lock(&hdmi.lock);
 
+       if (dssdev->manager == NULL) {
+               DSSERR("failed to enable display: no manager\n");
+               r = -ENODEV;
+               goto err0;
+       }
+
        r = omap_dss_start_device(dssdev);
        if (r) {
                DSSERR("failed to start device\n");
@@ -1282,219 +553,9 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
 
 #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
        defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
-static void hdmi_wp_audio_config_format(
-               struct hdmi_audio_format *aud_fmt)
-{
-       u32 r;
-
-       DSSDBG("Enter hdmi_wp_audio_config_format\n");
-
-       r = hdmi_read_reg(HDMI_WP_AUDIO_CFG);
-       r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24);
-       r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16);
-       r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5);
-       r = FLD_MOD(r, aud_fmt->type, 4, 4);
-       r = FLD_MOD(r, aud_fmt->justification, 3, 3);
-       r = FLD_MOD(r, aud_fmt->sample_order, 2, 2);
-       r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1);
-       r = FLD_MOD(r, aud_fmt->sample_size, 0, 0);
-       hdmi_write_reg(HDMI_WP_AUDIO_CFG, r);
-}
-
-static void hdmi_wp_audio_config_dma(struct hdmi_audio_dma *aud_dma)
-{
-       u32 r;
-
-       DSSDBG("Enter hdmi_wp_audio_config_dma\n");
-
-       r = hdmi_read_reg(HDMI_WP_AUDIO_CFG2);
-       r = FLD_MOD(r, aud_dma->transfer_size, 15, 8);
-       r = FLD_MOD(r, aud_dma->block_size, 7, 0);
-       hdmi_write_reg(HDMI_WP_AUDIO_CFG2, r);
-
-       r = hdmi_read_reg(HDMI_WP_AUDIO_CTRL);
-       r = FLD_MOD(r, aud_dma->mode, 9, 9);
-       r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0);
-       hdmi_write_reg(HDMI_WP_AUDIO_CTRL, r);
-}
-
-static void hdmi_core_audio_config(struct hdmi_core_audio_config *cfg)
-{
-       u32 r;
-
-       /* audio clock recovery parameters */
-       r = hdmi_read_reg(HDMI_CORE_AV_ACR_CTRL);
-       r = FLD_MOD(r, cfg->use_mclk, 2, 2);
-       r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1);
-       r = FLD_MOD(r, cfg->cts_mode, 0, 0);
-       hdmi_write_reg(HDMI_CORE_AV_ACR_CTRL, r);
-
-       REG_FLD_MOD(HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0);
-       REG_FLD_MOD(HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0);
-       REG_FLD_MOD(HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0);
-
-       if (cfg->cts_mode == HDMI_AUDIO_CTS_MODE_SW) {
-               REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0);
-               REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0);
-               REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0);
-       } else {
-               /*
-                * HDMI IP uses this configuration to divide the MCLK to
-                * update CTS value.
-                */
-               REG_FLD_MOD(HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0);
-
-               /* Configure clock for audio packets */
-               REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_1,
-                       cfg->aud_par_busclk, 7, 0);
-               REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_2,
-                       (cfg->aud_par_busclk >> 8), 7, 0);
-               REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_3,
-                       (cfg->aud_par_busclk >> 16), 7, 0);
-       }
-
-       /* Override of SPDIF sample frequency with value in I2S_CHST4 */
-       REG_FLD_MOD(HDMI_CORE_AV_SPDIF_CTRL, cfg->fs_override, 1, 1);
-
-       /* I2S parameters */
-       REG_FLD_MOD(HDMI_CORE_AV_I2S_CHST4, cfg->freq_sample, 3, 0);
-
-       r = hdmi_read_reg(HDMI_CORE_AV_I2S_IN_CTRL);
-       r = FLD_MOD(r, cfg->i2s_cfg.en_high_bitrate_aud, 7, 7);
-       r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6);
-       r = FLD_MOD(r, cfg->i2s_cfg.cbit_order, 5, 5);
-       r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4);
-       r = FLD_MOD(r, cfg->i2s_cfg.ws_polarity, 3, 3);
-       r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2);
-       r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1);
-       r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0);
-       hdmi_write_reg(HDMI_CORE_AV_I2S_IN_CTRL, r);
-
-       r = hdmi_read_reg(HDMI_CORE_AV_I2S_CHST5);
-       r = FLD_MOD(r, cfg->freq_sample, 7, 4);
-       r = FLD_MOD(r, cfg->i2s_cfg.word_length, 3, 1);
-       r = FLD_MOD(r, cfg->i2s_cfg.word_max_length, 0, 0);
-       hdmi_write_reg(HDMI_CORE_AV_I2S_CHST5, r);
-
-       REG_FLD_MOD(HDMI_CORE_AV_I2S_IN_LEN, cfg->i2s_cfg.in_length_bits, 3, 0);
-
-       /* Audio channels and mode parameters */
-       REG_FLD_MOD(HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1);
-       r = hdmi_read_reg(HDMI_CORE_AV_AUD_MODE);
-       r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4);
-       r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3);
-       r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2);
-       r = FLD_MOD(r, cfg->en_spdif, 1, 1);
-       hdmi_write_reg(HDMI_CORE_AV_AUD_MODE, r);
-}
-
-static void hdmi_core_audio_infoframe_config(
-               struct hdmi_core_infoframe_audio *info_aud)
-{
-       u8 val;
-       u8 sum = 0, checksum = 0;
-
-       /*
-        * Set audio info frame type, version and length as
-        * described in HDMI 1.4a Section 8.2.2 specification.
-        * Checksum calculation is defined in Section 5.3.5.
-        */
-       hdmi_write_reg(HDMI_CORE_AV_AUDIO_TYPE, 0x84);
-       hdmi_write_reg(HDMI_CORE_AV_AUDIO_VERS, 0x01);
-       hdmi_write_reg(HDMI_CORE_AV_AUDIO_LEN, 0x0a);
-       sum += 0x84 + 0x001 + 0x00a;
-
-       val = (info_aud->db1_coding_type << 4)
-                       | (info_aud->db1_channel_count - 1);
-       hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(0), val);
-       sum += val;
-
-       val = (info_aud->db2_sample_freq << 2) | info_aud->db2_sample_size;
-       hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(1), val);
-       sum += val;
-
-       hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(2), 0x00);
-
-       val = info_aud->db4_channel_alloc;
-       hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(3), val);
-       sum += val;
-
-       val = (info_aud->db5_downmix_inh << 7) | (info_aud->db5_lsv << 3);
-       hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(4), val);
-       sum += val;
-
-       hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(5), 0x00);
-       hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(6), 0x00);
-       hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(7), 0x00);
-       hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(8), 0x00);
-       hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(9), 0x00);
 
-       checksum = 0x100 - sum;
-       hdmi_write_reg(HDMI_CORE_AV_AUDIO_CHSUM, checksum);
-
-       /*
-        * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing
-        * is available.
-        */
-}
-
-static int hdmi_config_audio_acr(u32 sample_freq, u32 *n, u32 *cts)
-{
-       u32 r;
-       u32 deep_color = 0;
-       u32 pclk = hdmi.cfg.timings.timings.pixel_clock;
-
-       if (n == NULL || cts == NULL)
-               return -EINVAL;
-       /*
-        * Obtain current deep color configuration. This needed
-        * to calculate the TMDS clock based on the pixel clock.
-        */
-       r = REG_GET(HDMI_WP_VIDEO_CFG, 1, 0);
-       switch (r) {
-       case 1: /* No deep color selected */
-               deep_color = 100;
-               break;
-       case 2: /* 10-bit deep color selected */
-               deep_color = 125;
-               break;
-       case 3: /* 12-bit deep color selected */
-               deep_color = 150;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       switch (sample_freq) {
-       case 32000:
-               if ((deep_color == 125) && ((pclk == 54054)
-                               || (pclk == 74250)))
-                       *n = 8192;
-               else
-                       *n = 4096;
-               break;
-       case 44100:
-               *n = 6272;
-               break;
-       case 48000:
-               if ((deep_color == 125) && ((pclk == 54054)
-                               || (pclk == 74250)))
-                       *n = 8192;
-               else
-                       *n = 6144;
-               break;
-       default:
-               *n = 0;
-               return -EINVAL;
-       }
-
-       /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
-       *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10);
-
-       return 0;
-}
-
-static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
+static int hdmi_audio_hw_params(struct hdmi_ip_data *ip_data,
+                                       struct snd_pcm_substream *substream,
                                    struct snd_pcm_hw_params *params,
                                    struct snd_soc_dai *dai)
 {
@@ -1548,7 +609,7 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       err = hdmi_config_audio_acr(params_rate(params), &n, &cts);
+       err = hdmi_config_audio_acr(ip_data, params_rate(params), &n, &cts);
        if (err < 0)
                return err;
 
@@ -1564,8 +625,8 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
        audio_dma.mode = HDMI_AUDIO_TRANSF_DMA;
        audio_dma.fifo_threshold = 0x20; /* in number of samples */
 
-       hdmi_wp_audio_config_dma(&audio_dma);
-       hdmi_wp_audio_config_format(&audio_format);
+       hdmi_wp_audio_config_dma(ip_data, &audio_dma);
+       hdmi_wp_audio_config_format(ip_data, &audio_format);
 
        /*
         * I2S config
@@ -1609,7 +670,7 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
        /* Use parallel audio interface */
        core_cfg.en_parallel_aud_input = true;
 
-       hdmi_core_audio_config(&core_cfg);
+       hdmi_core_audio_config(ip_data, &core_cfg);
 
        /*
         * Configure packet
@@ -1623,36 +684,10 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
        aud_if_cfg.db5_downmix_inh = false;
        aud_if_cfg.db5_lsv = 0;
 
-       hdmi_core_audio_infoframe_config(&aud_if_cfg);
+       hdmi_core_audio_infoframe_config(ip_data, &aud_if_cfg);
        return 0;
 }
 
-static int hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
-                                 struct snd_soc_dai *dai)
-{
-       int err = 0;
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-       case SNDRV_PCM_TRIGGER_RESUME:
-       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 1, 0, 0);
-               REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 31, 31);
-               REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 30, 30);
-               break;
-
-       case SNDRV_PCM_TRIGGER_STOP:
-       case SNDRV_PCM_TRIGGER_SUSPEND:
-       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 0, 0, 0);
-               REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 30, 30);
-               REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 31, 31);
-               break;
-       default:
-               err = -EINVAL;
-       }
-       return err;
-}
-
 static int hdmi_audio_startup(struct snd_pcm_substream *substream,
                                  struct snd_soc_dai *dai)
 {
@@ -1698,15 +733,6 @@ static int hdmi_get_clocks(struct platform_device *pdev)
 
        hdmi.sys_clk = clk;
 
-       clk = clk_get(&pdev->dev, "dss_48mhz_clk");
-       if (IS_ERR(clk)) {
-               DSSERR("can't get hdmi_clk\n");
-               clk_put(hdmi.sys_clk);
-               return PTR_ERR(clk);
-       }
-
-       hdmi.hdmi_clk = clk;
-
        return 0;
 }
 
@@ -1714,8 +740,6 @@ static void hdmi_put_clocks(void)
 {
        if (hdmi.sys_clk)
                clk_put(hdmi.sys_clk);
-       if (hdmi.hdmi_clk)
-               clk_put(hdmi.hdmi_clk);
 }
 
 /* HDMI HW IP initialisation */
@@ -1736,20 +760,26 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
        }
 
        /* Base address taken from platform */
-       hdmi.base_wp = ioremap(hdmi_mem->start, resource_size(hdmi_mem));
-       if (!hdmi.base_wp) {
+       hdmi.ip_data.base_wp = ioremap(hdmi_mem->start,
+                                               resource_size(hdmi_mem));
+       if (!hdmi.ip_data.base_wp) {
                DSSERR("can't ioremap WP\n");
                return -ENOMEM;
        }
 
        r = hdmi_get_clocks(pdev);
        if (r) {
-               iounmap(hdmi.base_wp);
+               iounmap(hdmi.ip_data.base_wp);
                return r;
        }
 
        pm_runtime_enable(&pdev->dev);
 
+       hdmi.ip_data.core_sys_offset = HDMI_CORE_SYS;
+       hdmi.ip_data.core_av_offset = HDMI_CORE_AV;
+       hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
+       hdmi.ip_data.phy_offset = HDMI_PHY;
+
        hdmi_panel_init();
 
 #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
@@ -1779,14 +809,13 @@ static int omapdss_hdmihw_remove(struct platform_device *pdev)
 
        hdmi_put_clocks();
 
-       iounmap(hdmi.base_wp);
+       iounmap(hdmi.ip_data.base_wp);
 
        return 0;
 }
 
 static int hdmi_runtime_suspend(struct device *dev)
 {
-       clk_disable(hdmi.hdmi_clk);
        clk_disable(hdmi.sys_clk);
 
        dispc_runtime_put();
@@ -1809,7 +838,6 @@ static int hdmi_runtime_resume(struct device *dev)
 
 
        clk_enable(hdmi.sys_clk);
-       clk_enable(hdmi.hdmi_clk);
 
        return 0;
 
similarity index 79%
rename from drivers/video/omap2/dss/hdmi_omap4_panel.c
rename to drivers/video/omap2/dss/hdmi_panel.c
index 7d4f2bd..533d5dc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * hdmi_omap4_panel.c
+ * hdmi_panel.c
  *
  * HDMI library support functions for TI OMAP4 processors.
  *
@@ -25,6 +25,7 @@
 #include <linux/mutex.h>
 #include <linux/module.h>
 #include <video/omapdss.h>
+#include <linux/slab.h>
 
 #include "dss.h"
 
@@ -40,13 +41,7 @@ static int hdmi_panel_probe(struct omap_dss_device *dssdev)
        dssdev->panel.config = OMAP_DSS_LCD_TFT |
                        OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS;
 
-       /*
-        * Initialize the timings to 640 * 480
-        * This is only for framebuffer update not for TV timing setting
-        * Setting TV timing will be done only on enable
-        */
-       dssdev->panel.timings.x_res = 640;
-       dssdev->panel.timings.y_res = 480;
+       dssdev->panel.timings = (struct omap_video_timings){640, 480, 25175, 96, 16, 48, 2 , 11, 31};
 
        DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n",
                dssdev->panel.timings.x_res,
@@ -161,12 +156,7 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev,
        mutex_lock(&hdmi.hdmi_lock);
 
        dssdev->panel.timings = *timings;
-
-       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
-               /* turn the hdmi off and on to get new timings to use */
-               omapdss_hdmi_display_disable(dssdev);
-               omapdss_hdmi_display_set_timing(dssdev);
-       }
+       omapdss_hdmi_display_set_timing(dssdev);
 
        mutex_unlock(&hdmi.hdmi_lock);
 }
@@ -181,12 +171,54 @@ static int hdmi_check_timings(struct omap_dss_device *dssdev,
        mutex_lock(&hdmi.hdmi_lock);
 
        r = omapdss_hdmi_display_check_timing(dssdev, timings);
-       if (r) {
-               DSSERR("Timing cannot be applied\n");
-               goto err;
+
+       mutex_unlock(&hdmi.hdmi_lock);
+       return r;
+}
+
+static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len)
+{
+       int r;
+
+       mutex_lock(&hdmi.hdmi_lock);
+
+       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
+               r = omapdss_hdmi_display_enable(dssdev);
+               if (r)
+                       goto err;
+       }
+
+       r = omapdss_hdmi_read_edid(buf, len);
+
+       if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
+                       dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
+               omapdss_hdmi_display_disable(dssdev);
+err:
+       mutex_unlock(&hdmi.hdmi_lock);
+
+       return r;
+}
+
+static bool hdmi_detect(struct omap_dss_device *dssdev)
+{
+       int r;
+
+       mutex_lock(&hdmi.hdmi_lock);
+
+       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
+               r = omapdss_hdmi_display_enable(dssdev);
+               if (r)
+                       goto err;
        }
+
+       r = omapdss_hdmi_detect();
+
+       if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
+                       dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
+               omapdss_hdmi_display_disable(dssdev);
 err:
        mutex_unlock(&hdmi.hdmi_lock);
+
        return r;
 }
 
@@ -200,6 +232,8 @@ static struct omap_dss_driver hdmi_driver = {
        .get_timings    = hdmi_get_timings,
        .set_timings    = hdmi_set_timings,
        .check_timings  = hdmi_check_timings,
+       .read_edid      = hdmi_read_edid,
+       .detect         = hdmi_detect,
        .driver                 = {
                .name   = "hdmi_panel",
                .owner  = THIS_MODULE,
index 13d72d5..6e63845 100644 (file)
@@ -106,7 +106,7 @@ put_device:
 static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
                                          char *buf)
 {
-       return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.default_color);
+       return snprintf(buf, PAGE_SIZE, "%#x\n", mgr->info.default_color);
 }
 
 static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
@@ -116,8 +116,9 @@ static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
        u32 color;
        int r;
 
-       if (sscanf(buf, "%d", &color) != 1)
-               return -EINVAL;
+       r = kstrtouint(buf, 0, &color);
+       if (r)
+               return r;
 
        mgr->get_manager_info(mgr, &info);
 
@@ -184,7 +185,7 @@ static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
 static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
                                            char *buf)
 {
-       return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_key);
+       return snprintf(buf, PAGE_SIZE, "%#x\n", mgr->info.trans_key);
 }
 
 static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
@@ -194,8 +195,9 @@ static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
        u32 key_value;
        int r;
 
-       if (sscanf(buf, "%d", &key_value) != 1)
-               return -EINVAL;
+       r = kstrtouint(buf, 0, &key_value);
+       if (r)
+               return r;
 
        mgr->get_manager_info(mgr, &info);
 
@@ -222,15 +224,16 @@ static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
                                               const char *buf, size_t size)
 {
        struct omap_overlay_manager_info info;
-       int enable;
+       bool enable;
        int r;
 
-       if (sscanf(buf, "%d", &enable) != 1)
-               return -EINVAL;
+       r = strtobool(buf, &enable);
+       if (r)
+               return r;
 
        mgr->get_manager_info(mgr, &info);
 
-       info.trans_enabled = enable ? true : false;
+       info.trans_enabled = enable;
 
        r = mgr->set_manager_info(mgr, &info);
        if (r)
@@ -246,7 +249,10 @@ static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
 static ssize_t manager_alpha_blending_enabled_show(
                struct omap_overlay_manager *mgr, char *buf)
 {
-       return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.alpha_enabled);
+       WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
+
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+               mgr->info.partial_alpha_enabled);
 }
 
 static ssize_t manager_alpha_blending_enabled_store(
@@ -254,15 +260,18 @@ static ssize_t manager_alpha_blending_enabled_store(
                const char *buf, size_t size)
 {
        struct omap_overlay_manager_info info;
-       int enable;
+       bool enable;
        int r;
 
-       if (sscanf(buf, "%d", &enable) != 1)
-               return -EINVAL;
+       WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
+
+       r = strtobool(buf, &enable);
+       if (r)
+               return r;
 
        mgr->get_manager_info(mgr, &info);
 
-       info.alpha_enabled = enable ? true : false;
+       info.partial_alpha_enabled = enable;
 
        r = mgr->set_manager_info(mgr, &info);
        if (r)
@@ -285,19 +294,16 @@ static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
                const char *buf, size_t size)
 {
        struct omap_overlay_manager_info info;
-       int v;
        int r;
        bool enable;
 
        if (!dss_has_feature(FEAT_CPR))
                return -ENODEV;
 
-       r = kstrtoint(buf, 0, &v);
+       r = strtobool(buf, &enable);
        if (r)
                return r;
 
-       enable = !!v;
-
        mgr->get_manager_info(mgr, &info);
 
        if (info.cpr_enable == enable)
@@ -586,6 +592,13 @@ static int omap_dss_unset_device(struct omap_overlay_manager *mgr)
                return -EINVAL;
        }
 
+       /*
+        * Don't allow currently enabled displays to have the overlay manager
+        * pulled out from underneath them
+        */
+       if (mgr->device->state != OMAP_DSS_DISPLAY_DISABLED)
+               return -EINVAL;
+
        mgr->device->manager = NULL;
        mgr->device = NULL;
        mgr->device_changed = true;
@@ -801,7 +814,7 @@ static int configure_overlay(enum omap_plane plane)
 {
        struct overlay_cache_data *c;
        struct manager_cache_data *mc;
-       struct omap_overlay_info *oi;
+       struct omap_overlay_info *oi, new_oi;
        struct omap_overlay_manager_info *mi;
        u16 outw, outh;
        u16 x, y, w, h;
@@ -815,7 +828,7 @@ static int configure_overlay(enum omap_plane plane)
        oi = &c->info;
 
        if (!c->enabled) {
-               dispc_enable_plane(plane, 0);
+               dispc_ovl_enable(plane, 0);
                return 0;
        }
 
@@ -843,7 +856,7 @@ static int configure_overlay(enum omap_plane plane)
                /* If the overlay is outside the update region, disable it */
                if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h,
                                        x, y, outw, outh)) {
-                       dispc_enable_plane(plane, 0);
+                       dispc_ovl_enable(plane, 0);
                        return 0;
                }
 
@@ -921,34 +934,27 @@ static int configure_overlay(enum omap_plane plane)
                }
        }
 
-       r = dispc_setup_plane(plane,
-                       paddr,
-                       oi->screen_width,
-                       x, y,
-                       w, h,
-                       outw, outh,
-                       oi->color_mode,
-                       c->ilace,
-                       oi->rotation_type,
-                       oi->rotation,
-                       oi->mirror,
-                       oi->global_alpha,
-                       oi->pre_mult_alpha,
-                       c->channel,
-                       oi->p_uv_addr);
+       new_oi = *oi;
+
+       /* update new_oi members which could have been possibly updated */
+       new_oi.pos_x = x;
+       new_oi.pos_y = y;
+       new_oi.width = w;
+       new_oi.height = h;
+       new_oi.out_width = outw;
+       new_oi.out_height = outh;
+       new_oi.paddr = paddr;
 
+       r = dispc_ovl_setup(plane, &new_oi, c->ilace, c->channel,
+               c->replication, c->fifo_low, c->fifo_high);
        if (r) {
                /* this shouldn't happen */
-               DSSERR("dispc_setup_plane failed for ovl %d\n", plane);
-               dispc_enable_plane(plane, 0);
+               DSSERR("dispc_ovl_setup failed for ovl %d\n", plane);
+               dispc_ovl_enable(plane, 0);
                return r;
        }
 
-       dispc_enable_replication(plane, c->replication);
-
-       dispc_set_fifo_threshold(plane, c->fifo_low, c->fifo_high);
-
-       dispc_enable_plane(plane, 1);
+       dispc_ovl_enable(plane, 1);
 
        return 0;
 }
@@ -962,13 +968,13 @@ static void configure_manager(enum omap_channel channel)
        /* picking info from the cache */
        mi = &dss_cache.manager_cache[channel].info;
 
-       dispc_set_default_color(channel, mi->default_color);
-       dispc_set_trans_key(channel, mi->trans_key_type, mi->trans_key);
-       dispc_enable_trans_key(channel, mi->trans_enabled);
-       dispc_enable_alpha_blending(channel, mi->alpha_enabled);
+       dispc_mgr_set_default_color(channel, mi->default_color);
+       dispc_mgr_set_trans_key(channel, mi->trans_key_type, mi->trans_key);
+       dispc_mgr_enable_trans_key(channel, mi->trans_enabled);
+       dispc_mgr_enable_alpha_fixed_zorder(channel, mi->partial_alpha_enabled);
        if (dss_has_feature(FEAT_CPR)) {
-               dispc_enable_cpr(channel, mi->cpr_enable);
-               dispc_set_cpr_coef(channel, &mi->cpr_coefs);
+               dispc_mgr_enable_cpr(channel, mi->cpr_enable);
+               dispc_mgr_set_cpr_coef(channel, &mi->cpr_coefs);
        }
 }
 
@@ -992,7 +998,7 @@ static int configure_dispc(void)
        busy = false;
 
        for (i = 0; i < num_mgrs; i++) {
-               mgr_busy[i] = dispc_go_busy(i);
+               mgr_busy[i] = dispc_mgr_go_busy(i);
                mgr_go[i] = false;
        }
 
@@ -1053,7 +1059,7 @@ static int configure_dispc(void)
                 * always be turned off after frame, and new settings will be
                 * taken in to use at next update */
                if (!mc->manual_update)
-                       dispc_go(i);
+                       dispc_mgr_go(i);
        }
 
        if (busy)
@@ -1258,7 +1264,7 @@ static void dss_apply_irq_handler(void *data, u32 mask)
        u32 irq_mask;
 
        for (i = 0; i < num_mgrs; i++)
-               mgr_busy[i] = dispc_go_busy(i);
+               mgr_busy[i] = dispc_mgr_go_busy(i);
 
        spin_lock(&dss_cache.lock);
 
@@ -1280,7 +1286,7 @@ static void dss_apply_irq_handler(void *data, u32 mask)
 
        /* re-read busy flags */
        for (i = 0; i < num_mgrs; i++)
-               mgr_busy[i] = dispc_go_busy(i);
+               mgr_busy[i] = dispc_mgr_go_busy(i);
 
        /* keep running as long as there are busy managers, so that
         * we can collect overlay-applied information */
@@ -1326,11 +1332,13 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 
                ovl = omap_dss_get_overlay(i);
 
-               if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
-                       continue;
-
                oc = &dss_cache.overlay_cache[ovl->id];
 
+               if (ovl->manager_changed) {
+                       ovl->manager_changed = false;
+                       ovl->info_dirty  = true;
+               }
+
                if (!overlay_enabled(ovl)) {
                        if (oc->enabled) {
                                oc->enabled = false;
@@ -1375,9 +1383,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
        list_for_each_entry(mgr, &manager_list, list) {
                struct omap_dss_device *dssdev;
 
-               if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC))
-                       continue;
-
                mc = &dss_cache.manager_cache[mgr->id];
 
                if (mgr->device_changed) {
@@ -1423,9 +1428,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 
                ovl = omap_dss_get_overlay(i);
 
-               if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
-                       continue;
-
                oc = &dss_cache.overlay_cache[ovl->id];
 
                if (!oc->enabled)
@@ -1433,11 +1435,11 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 
                dssdev = ovl->manager->device;
 
-               size = dispc_get_plane_fifo_size(ovl->id);
+               size = dispc_ovl_get_fifo_size(ovl->id);
                if (use_fifomerge)
                        size *= 3;
 
-               burst_size = dispc_get_burst_size(ovl->id);
+               burst_size = dispc_ovl_get_burst_size(ovl->id);
 
                switch (dssdev->type) {
                case OMAP_DISPLAY_TYPE_DPI:
@@ -1484,12 +1486,17 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 
 static int dss_check_manager(struct omap_overlay_manager *mgr)
 {
-       /* OMAP supports only graphics source transparency color key and alpha
-        * blending simultaneously. See TRM 15.4.2.4.2.2 Alpha Mode */
-
-       if (mgr->info.alpha_enabled && mgr->info.trans_enabled &&
-                       mgr->info.trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST)
-               return -EINVAL;
+       if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) {
+               /*
+                * OMAP3 supports only graphics source transparency color key
+                * and alpha blending simultaneously. See TRM 15.4.2.4.2.2
+                * Alpha Mode
+                */
+               if (mgr->info.partial_alpha_enabled && mgr->info.trans_enabled
+                       && mgr->info.trans_key_type !=
+                               OMAP_DSS_COLOR_KEY_GFX_DST)
+                       return -EINVAL;
+       }
 
        return 0;
 }
@@ -1522,13 +1529,13 @@ static void omap_dss_mgr_get_info(struct omap_overlay_manager *mgr,
 
 static int dss_mgr_enable(struct omap_overlay_manager *mgr)
 {
-       dispc_enable_channel(mgr->id, 1);
+       dispc_mgr_enable(mgr->id, 1);
        return 0;
 }
 
 static int dss_mgr_disable(struct omap_overlay_manager *mgr)
 {
-       dispc_enable_channel(mgr->id, 0);
+       dispc_mgr_enable(mgr->id, 0);
        return 0;
 }
 
@@ -1580,7 +1587,7 @@ int dss_init_overlay_managers(struct platform_device *pdev)
                mgr->enable = &dss_mgr_enable;
                mgr->disable = &dss_mgr_disable;
 
-               mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC;
+               mgr->caps = 0;
                mgr->supported_displays =
                        dss_feat_get_supported_displays(mgr->id);
 
@@ -1597,42 +1604,6 @@ int dss_init_overlay_managers(struct platform_device *pdev)
                }
        }
 
-#ifdef L4_EXAMPLE
-       {
-               int omap_dss_mgr_apply_l4(struct omap_overlay_manager *mgr)
-               {
-                       DSSDBG("omap_dss_mgr_apply_l4(%s)\n", mgr->name);
-
-                       return 0;
-               }
-
-               struct omap_overlay_manager *mgr;
-               mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
-
-               BUG_ON(mgr == NULL);
-
-               mgr->name = "l4";
-               mgr->supported_displays =
-                       OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI;
-
-               mgr->set_device = &omap_dss_set_device;
-               mgr->unset_device = &omap_dss_unset_device;
-               mgr->apply = &omap_dss_mgr_apply_l4;
-               mgr->set_manager_info = &omap_dss_mgr_set_info;
-               mgr->get_manager_info = &omap_dss_mgr_get_info;
-
-               dss_overlay_setup_l4_manager(mgr);
-
-               omap_dss_add_overlay_manager(mgr);
-
-               r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
-                               &pdev->dev.kobj, "managerl4");
-
-               if (r)
-                       DSSERR("failed to create sysfs file\n");
-       }
-#endif
-
        return 0;
 }
 
index c84380c..ab8e40e 100644 (file)
@@ -211,16 +211,17 @@ static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
 static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
                size_t size)
 {
-       int r, enable;
+       int r;
+       bool enable;
        struct omap_overlay_info info;
 
        ovl->get_overlay_info(ovl, &info);
 
-       r = kstrtoint(buf, 0, &enable);
+       r = strtobool(buf, &enable);
        if (r)
                return r;
 
-       info.enabled = !!enable;
+       info.enabled = enable;
 
        r = ovl->set_overlay_info(ovl, &info);
        if (r)
@@ -248,7 +249,7 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
        u8 alpha;
        struct omap_overlay_info info;
 
-       if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
+       if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
                return -ENODEV;
 
        r = kstrtou8(buf, 0, &alpha);
@@ -257,14 +258,7 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
 
        ovl->get_overlay_info(ovl, &info);
 
-       /* Video1 plane does not support global alpha
-        * to always make it 255 completely opaque
-        */
-       if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
-                       ovl->id == OMAP_DSS_VIDEO1)
-               info.global_alpha = 255;
-       else
-               info.global_alpha = alpha;
+       info.global_alpha = alpha;
 
        r = ovl->set_overlay_info(ovl, &info);
        if (r)
@@ -293,20 +287,52 @@ static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
        u8 alpha;
        struct omap_overlay_info info;
 
+       if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
+               return -ENODEV;
+
        r = kstrtou8(buf, 0, &alpha);
        if (r)
                return r;
 
        ovl->get_overlay_info(ovl, &info);
 
-       /* only GFX and Video2 plane support pre alpha multiplied
-        * set zero for Video1 plane
-        */
-       if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
-               ovl->id == OMAP_DSS_VIDEO1)
-               info.pre_mult_alpha = 0;
-       else
-               info.pre_mult_alpha = alpha;
+       info.pre_mult_alpha = alpha;
+
+       r = ovl->set_overlay_info(ovl, &info);
+       if (r)
+               return r;
+
+       if (ovl->manager) {
+               r = ovl->manager->apply(ovl->manager);
+               if (r)
+                       return r;
+       }
+
+       return size;
+}
+
+static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.zorder);
+}
+
+static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
+               const char *buf, size_t size)
+{
+       int r;
+       u8 zorder;
+       struct omap_overlay_info info;
+
+       if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
+               return -ENODEV;
+
+       r = kstrtou8(buf, 0, &zorder);
+       if (r)
+               return r;
+
+       ovl->get_overlay_info(ovl, &info);
+
+       info.zorder = zorder;
 
        r = ovl->set_overlay_info(ovl, &info);
        if (r)
@@ -347,6 +373,8 @@ static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
 static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
                overlay_pre_mult_alpha_show,
                overlay_pre_mult_alpha_store);
+static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
+               overlay_zorder_show, overlay_zorder_store);
 
 static struct attribute *overlay_sysfs_attrs[] = {
        &overlay_attr_name.attr,
@@ -358,6 +386,7 @@ static struct attribute *overlay_sysfs_attrs[] = {
        &overlay_attr_enabled.attr,
        &overlay_attr_global_alpha.attr,
        &overlay_attr_pre_mult_alpha.attr,
+       &overlay_attr_zorder.attr,
        NULL
 };
 
@@ -407,6 +436,7 @@ int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev)
        struct omap_overlay_info *info;
        u16 outw, outh;
        u16 dw, dh;
+       int i;
 
        if (!dssdev)
                return 0;
@@ -462,6 +492,31 @@ int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev)
                return -EINVAL;
        }
 
+       if (ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) {
+               if (info->zorder < 0 || info->zorder > 3) {
+                       DSSERR("zorder out of range: %d\n",
+                               info->zorder);
+                       return -EINVAL;
+               }
+               /*
+                * Check that zorder doesn't match with zorder of any other
+                * overlay which is enabled and is also connected to the same
+                * manager
+                */
+               for (i = 0; i < omap_dss_get_num_overlays(); i++) {
+                       struct omap_overlay *tmp_ovl = omap_dss_get_overlay(i);
+
+                       if (tmp_ovl->id != ovl->id &&
+                                       tmp_ovl->manager == ovl->manager &&
+                                       tmp_ovl->info.enabled == true &&
+                                       tmp_ovl->info.zorder == info->zorder) {
+                               DSSERR("%s and %s have same zorder: %d\n",
+                                       ovl->name, tmp_ovl->name, info->zorder);
+                               return -EINVAL;
+                       }
+               }
+       }
+
        return 0;
 }
 
@@ -516,6 +571,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
        }
 
        ovl->manager = mgr;
+       ovl->manager_changed = true;
 
        /* XXX: When there is an overlay on a DSI manual update display, and
         * the overlay is first disabled, then moved to tv, and enabled, we
@@ -529,15 +585,12 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
         * Userspace workaround for this is to update the LCD after disabling
         * the overlay, but before moving the overlay to TV.
         */
-       dispc_set_channel_out(ovl->id, mgr->id);
 
        return 0;
 }
 
 static int omap_dss_unset_manager(struct omap_overlay *ovl)
 {
-       int r;
-
        if (!ovl->manager) {
                DSSERR("failed to detach overlay: manager not set\n");
                return -EINVAL;
@@ -548,11 +601,8 @@ static int omap_dss_unset_manager(struct omap_overlay *ovl)
                return -EINVAL;
        }
 
-       r = ovl->wait_for_go(ovl);
-       if (r)
-               return r;
-
        ovl->manager = NULL;
+       ovl->manager_changed = true;
 
        return 0;
 }
@@ -618,22 +668,29 @@ void dss_init_overlays(struct platform_device *pdev)
                case 0:
                        ovl->name = "gfx";
                        ovl->id = OMAP_DSS_GFX;
-                       ovl->caps = OMAP_DSS_OVL_CAP_DISPC;
                        ovl->info.global_alpha = 255;
+                       ovl->info.zorder = 0;
                        break;
                case 1:
                        ovl->name = "vid1";
                        ovl->id = OMAP_DSS_VIDEO1;
-                       ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
-                               OMAP_DSS_OVL_CAP_DISPC;
                        ovl->info.global_alpha = 255;
+                       ovl->info.zorder =
+                               dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0;
                        break;
                case 2:
                        ovl->name = "vid2";
                        ovl->id = OMAP_DSS_VIDEO2;
-                       ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
-                               OMAP_DSS_OVL_CAP_DISPC;
                        ovl->info.global_alpha = 255;
+                       ovl->info.zorder =
+                               dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0;
+                       break;
+               case 3:
+                       ovl->name = "vid3";
+                       ovl->id = OMAP_DSS_VIDEO3;
+                       ovl->info.global_alpha = 255;
+                       ovl->info.zorder =
+                               dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0;
                        break;
                }
 
@@ -643,6 +700,7 @@ void dss_init_overlays(struct platform_device *pdev)
                ovl->get_overlay_info = &dss_ovl_get_overlay_info;
                ovl->wait_for_go = &dss_ovl_wait_for_go;
 
+               ovl->caps = dss_feat_get_overlay_caps(ovl->id);
                ovl->supported_modes =
                        dss_feat_get_supported_color_modes(ovl->id);
 
index 39f4c59..1bd3703 100644 (file)
@@ -309,9 +309,9 @@ static void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width,
 
        DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
 
-       dispc_set_lcd_size(dssdev->manager->id, width, height);
+       dispc_mgr_set_lcd_size(dssdev->manager->id, width, height);
 
-       dispc_enable_channel(dssdev->manager->id, true);
+       dispc_mgr_enable(dssdev->manager->id, true);
 
        rfbi.framedone_callback = callback;
        rfbi.framedone_callback_data = data;
@@ -783,10 +783,8 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
        if (*w == 0 || *h == 0)
                return -EINVAL;
 
-       if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
-               dss_setup_partial_planes(dssdev, x, y, w, h, true);
-               dispc_set_lcd_size(dssdev->manager->id, *w, *h);
-       }
+       dss_setup_partial_planes(dssdev, x, y, w, h, true);
+       dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h);
 
        return 0;
 }
@@ -796,22 +794,7 @@ int omap_rfbi_update(struct omap_dss_device *dssdev,
                u16 x, u16 y, u16 w, u16 h,
                void (*callback)(void *), void *data)
 {
-       if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
-               rfbi_transfer_area(dssdev, w, h, callback, data);
-       } else {
-               struct omap_overlay *ovl;
-               void __iomem *addr;
-               int scr_width;
-
-               ovl = dssdev->manager->overlays[0];
-               scr_width = ovl->info.screen_width;
-               addr = ovl->info.vaddr;
-
-               omap_rfbi_write_pixels(addr, scr_width, x, y, w, h);
-
-               callback(data);
-       }
-
+       rfbi_transfer_area(dssdev, w, h, callback, data);
        return 0;
 }
 EXPORT_SYMBOL(omap_rfbi_update);
@@ -860,6 +843,11 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
 {
        int r;
 
+       if (dssdev->manager == NULL) {
+               DSSERR("failed to enable display: no manager\n");
+               return -ENODEV;
+       }
+
        r = rfbi_runtime_get();
        if (r)
                return r;
@@ -877,13 +865,13 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
                goto err1;
        }
 
-       dispc_set_lcd_display_type(dssdev->manager->id,
+       dispc_mgr_set_lcd_display_type(dssdev->manager->id,
                        OMAP_DSS_LCD_DISPLAY_TFT);
 
-       dispc_set_parallel_interface_mode(dssdev->manager->id,
-                       OMAP_DSS_PARALLELMODE_RFBI);
+       dispc_mgr_set_io_pad_mode(DSS_IO_PAD_MODE_RFBI);
+       dispc_mgr_enable_stallmode(dssdev->manager->id, true);
 
-       dispc_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size);
+       dispc_mgr_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size);
 
        rfbi_configure(dssdev->phy.rfbi.channel,
                               dssdev->ctrl.pixel_size,
@@ -952,10 +940,7 @@ static int omap_rfbihw_probe(struct platform_device *pdev)
 
        msleep(10);
 
-       if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap3630())
-               clk = dss_get_ick();
-       else
-               clk = clk_get(&pdev->dev, "ick");
+       clk = clk_get(&pdev->dev, "ick");
        if (IS_ERR(clk)) {
                DSSERR("can't get ick\n");
                r = PTR_ERR(clk);
index 3a688c8..695dc04 100644 (file)
@@ -35,13 +35,13 @@ static struct {
 static void sdi_basic_init(struct omap_dss_device *dssdev)
 
 {
-       dispc_set_parallel_interface_mode(dssdev->manager->id,
-                       OMAP_DSS_PARALLELMODE_BYPASS);
+       dispc_mgr_set_io_pad_mode(DSS_IO_PAD_MODE_BYPASS);
+       dispc_mgr_enable_stallmode(dssdev->manager->id, false);
 
-       dispc_set_lcd_display_type(dssdev->manager->id,
+       dispc_mgr_set_lcd_display_type(dssdev->manager->id,
                        OMAP_DSS_LCD_DISPLAY_TFT);
 
-       dispc_set_tft_data_lines(dssdev->manager->id, 24);
+       dispc_mgr_set_tft_data_lines(dssdev->manager->id, 24);
        dispc_lcd_enable_signal_polarity(1);
 }
 
@@ -55,6 +55,11 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
        unsigned long pck;
        int r;
 
+       if (dssdev->manager == NULL) {
+               DSSERR("failed to enable display: no manager\n");
+               return -ENODEV;
+       }
+
        r = omap_dss_start_device(dssdev);
        if (r) {
                DSSERR("failed to start device\n");
@@ -78,7 +83,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
        /* 15.5.9.1.2 */
        dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF;
 
-       dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
+       dispc_mgr_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
                        dssdev->panel.acbi, dssdev->panel.acb);
 
        r = dss_calc_clock_div(1, t->pixel_clock * 1000,
@@ -101,13 +106,13 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
        }
 
 
-       dispc_set_lcd_timings(dssdev->manager->id, t);
+       dispc_mgr_set_lcd_timings(dssdev->manager->id, t);
 
        r = dss_set_clock_div(&dss_cinfo);
        if (r)
                goto err_set_dss_clock_div;
 
-       r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
+       r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo);
        if (r)
                goto err_set_dispc_clock_div;
 
diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h
new file mode 100644 (file)
index 0000000..2c3443d
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * ti_hdmi.h
+ *
+ * HDMI driver definition for TI OMAP4, DM81xx, DM38xx  Processor.
+ *
+ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _TI_HDMI_H
+#define _TI_HDMI_H
+
+struct hdmi_ip_data;
+
+enum hdmi_pll_pwr {
+       HDMI_PLLPWRCMD_ALLOFF = 0,
+       HDMI_PLLPWRCMD_PLLONLY = 1,
+       HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2,
+       HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3
+};
+
+enum hdmi_core_hdmi_dvi {
+       HDMI_DVI = 0,
+       HDMI_HDMI = 1
+};
+
+enum hdmi_clk_refsel {
+       HDMI_REFSEL_PCLK = 0,
+       HDMI_REFSEL_REF1 = 1,
+       HDMI_REFSEL_REF2 = 2,
+       HDMI_REFSEL_SYSCLK = 3
+};
+
+struct hdmi_video_timings {
+       u16 x_res;
+       u16 y_res;
+       /* Unit: KHz */
+       u32 pixel_clock;
+       u16 hsw;
+       u16 hfp;
+       u16 hbp;
+       u16 vsw;
+       u16 vfp;
+       u16 vbp;
+};
+
+/* HDMI timing structure */
+struct hdmi_timings {
+       struct hdmi_video_timings timings;
+       int vsync_pol;
+       int hsync_pol;
+};
+
+struct hdmi_cm {
+       int     code;
+       int     mode;
+};
+
+struct hdmi_config {
+       struct hdmi_timings timings;
+       u16     interlace;
+       struct hdmi_cm cm;
+};
+
+/* HDMI PLL structure */
+struct hdmi_pll_info {
+       u16 regn;
+       u16 regm;
+       u32 regmf;
+       u16 regm2;
+       u16 regsd;
+       u16 dcofreq;
+       enum hdmi_clk_refsel refsel;
+};
+
+struct ti_hdmi_ip_ops {
+
+       void (*video_configure)(struct hdmi_ip_data *ip_data);
+
+       int (*phy_enable)(struct hdmi_ip_data *ip_data);
+
+       void (*phy_disable)(struct hdmi_ip_data *ip_data);
+
+       int (*read_edid)(struct hdmi_ip_data *ip_data, u8 *edid, int len);
+
+       bool (*detect)(struct hdmi_ip_data *ip_data);
+
+       int (*pll_enable)(struct hdmi_ip_data *ip_data);
+
+       void (*pll_disable)(struct hdmi_ip_data *ip_data);
+
+       void (*video_enable)(struct hdmi_ip_data *ip_data, bool start);
+
+       void (*dump_wrapper)(struct hdmi_ip_data *ip_data, struct seq_file *s);
+
+       void (*dump_core)(struct hdmi_ip_data *ip_data, struct seq_file *s);
+
+       void (*dump_pll)(struct hdmi_ip_data *ip_data, struct seq_file *s);
+
+       void (*dump_phy)(struct hdmi_ip_data *ip_data, struct seq_file *s);
+
+};
+
+struct hdmi_ip_data {
+       void __iomem    *base_wp;       /* HDMI wrapper */
+       unsigned long   core_sys_offset;
+       unsigned long   core_av_offset;
+       unsigned long   pll_offset;
+       unsigned long   phy_offset;
+       const struct ti_hdmi_ip_ops *ops;
+       struct hdmi_config cfg;
+       struct hdmi_pll_info pll_data;
+};
+int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data);
+void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data);
+int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, u8 *edid, int len);
+bool ti_hdmi_4xxx_detect(struct hdmi_ip_data *ip_data);
+void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start);
+int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data);
+void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data);
+void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data);
+void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
+void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
+void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
+void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
+
+#endif
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
new file mode 100644 (file)
index 0000000..e1a6ce5
--- /dev/null
@@ -0,0 +1,1239 @@
+/*
+ * ti_hdmi_4xxx_ip.c
+ *
+ * HDMI TI81xx, TI38xx, TI OMAP4 etc IP driver Library
+ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Authors: Yong Zhi
+ *     Mythri pk <mythripk@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/seq_file.h>
+
+#include "ti_hdmi_4xxx_ip.h"
+#include "dss.h"
+
+static inline void hdmi_write_reg(void __iomem *base_addr,
+                               const u16 idx, u32 val)
+{
+       __raw_writel(val, base_addr + idx);
+}
+
+static inline u32 hdmi_read_reg(void __iomem *base_addr,
+                               const u16 idx)
+{
+       return __raw_readl(base_addr + idx);
+}
+
+static inline void __iomem *hdmi_wp_base(struct hdmi_ip_data *ip_data)
+{
+       return ip_data->base_wp;
+}
+
+static inline void __iomem *hdmi_phy_base(struct hdmi_ip_data *ip_data)
+{
+       return ip_data->base_wp + ip_data->phy_offset;
+}
+
+static inline void __iomem *hdmi_pll_base(struct hdmi_ip_data *ip_data)
+{
+       return ip_data->base_wp + ip_data->pll_offset;
+}
+
+static inline void __iomem *hdmi_av_base(struct hdmi_ip_data *ip_data)
+{
+       return ip_data->base_wp + ip_data->core_av_offset;
+}
+
+static inline void __iomem *hdmi_core_sys_base(struct hdmi_ip_data *ip_data)
+{
+       return ip_data->base_wp + ip_data->core_sys_offset;
+}
+
+static inline int hdmi_wait_for_bit_change(void __iomem *base_addr,
+                               const u16 idx,
+                               int b2, int b1, u32 val)
+{
+       u32 t = 0;
+       while (val != REG_GET(base_addr, idx, b2, b1)) {
+               udelay(1);
+               if (t++ > 10000)
+                       return !val;
+       }
+       return val;
+}
+
+static int hdmi_pll_init(struct hdmi_ip_data *ip_data)
+{
+       u32 r;
+       void __iomem *pll_base = hdmi_pll_base(ip_data);
+       struct hdmi_pll_info *fmt = &ip_data->pll_data;
+
+       /* PLL start always use manual mode */
+       REG_FLD_MOD(pll_base, PLLCTRL_PLL_CONTROL, 0x0, 0, 0);
+
+       r = hdmi_read_reg(pll_base, PLLCTRL_CFG1);
+       r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */
+       r = FLD_MOD(r, fmt->regn - 1, 8, 1);  /* CFG1_PLL_REGN */
+
+       hdmi_write_reg(pll_base, PLLCTRL_CFG1, r);
+
+       r = hdmi_read_reg(pll_base, PLLCTRL_CFG2);
+
+       r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */
+       r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */
+       r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */
+       r = FLD_MOD(r, fmt->refsel, 22, 21); /* REFSEL */
+
+       if (fmt->dcofreq) {
+               /* divider programming for frequency beyond 1000Mhz */
+               REG_FLD_MOD(pll_base, PLLCTRL_CFG3, fmt->regsd, 17, 10);
+               r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */
+       } else {
+               r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */
+       }
+
+       hdmi_write_reg(pll_base, PLLCTRL_CFG2, r);
+
+       r = hdmi_read_reg(pll_base, PLLCTRL_CFG4);
+       r = FLD_MOD(r, fmt->regm2, 24, 18);
+       r = FLD_MOD(r, fmt->regmf, 17, 0);
+
+       hdmi_write_reg(pll_base, PLLCTRL_CFG4, r);
+
+       /* go now */
+       REG_FLD_MOD(pll_base, PLLCTRL_PLL_GO, 0x1, 0, 0);
+
+       /* wait for bit change */
+       if (hdmi_wait_for_bit_change(pll_base, PLLCTRL_PLL_GO,
+                                                       0, 0, 1) != 1) {
+               pr_err("PLL GO bit not set\n");
+               return -ETIMEDOUT;
+       }
+
+       /* Wait till the lock bit is set in PLL status */
+       if (hdmi_wait_for_bit_change(pll_base,
+                               PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) {
+               pr_err("cannot lock PLL\n");
+               pr_err("CFG1 0x%x\n",
+                       hdmi_read_reg(pll_base, PLLCTRL_CFG1));
+               pr_err("CFG2 0x%x\n",
+                       hdmi_read_reg(pll_base, PLLCTRL_CFG2));
+               pr_err("CFG4 0x%x\n",
+                       hdmi_read_reg(pll_base, PLLCTRL_CFG4));
+               return -ETIMEDOUT;
+       }
+
+       pr_debug("PLL locked!\n");
+
+       return 0;
+}
+
+/* PHY_PWR_CMD */
+static int hdmi_set_phy_pwr(struct hdmi_ip_data *ip_data, enum hdmi_phy_pwr val)
+{
+       /* Command for power control of HDMI PHY */
+       REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, val, 7, 6);
+
+       /* Status of the power control of HDMI PHY */
+       if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data),
+                               HDMI_WP_PWR_CTRL, 5, 4, val) != val) {
+               pr_err("Failed to set PHY power mode to %d\n", val);
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+/* PLL_PWR_CMD */
+static int hdmi_set_pll_pwr(struct hdmi_ip_data *ip_data, enum hdmi_pll_pwr val)
+{
+       /* Command for power control of HDMI PLL */
+       REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, val, 3, 2);
+
+       /* wait till PHY_PWR_STATUS is set */
+       if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL,
+                                               1, 0, val) != val) {
+               pr_err("Failed to set PLL_PWR_STATUS\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static int hdmi_pll_reset(struct hdmi_ip_data *ip_data)
+{
+       /* SYSRESET  controlled by power FSM */
+       REG_FLD_MOD(hdmi_pll_base(ip_data), PLLCTRL_PLL_CONTROL, 0x0, 3, 3);
+
+       /* READ 0x0 reset is in progress */
+       if (hdmi_wait_for_bit_change(hdmi_pll_base(ip_data),
+                               PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) {
+               pr_err("Failed to sysreset PLL\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data)
+{
+       u16 r = 0;
+
+       r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF);
+       if (r)
+               return r;
+
+       r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
+       if (r)
+               return r;
+
+       r = hdmi_pll_reset(ip_data);
+       if (r)
+               return r;
+
+       r = hdmi_pll_init(ip_data);
+       if (r)
+               return r;
+
+       return 0;
+}
+
+void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data)
+{
+       hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF);
+}
+
+int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data)
+{
+       u16 r = 0;
+       void __iomem *phy_base = hdmi_phy_base(ip_data);
+
+       r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON);
+       if (r)
+               return r;
+
+       r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_TXON);
+       if (r)
+               return r;
+
+       /*
+        * Read address 0 in order to get the SCP reset done completed
+        * Dummy access performed to make sure reset is done
+        */
+       hdmi_read_reg(phy_base, HDMI_TXPHY_TX_CTRL);
+
+       /*
+        * Write to phy address 0 to configure the clock
+        * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field
+        */
+       REG_FLD_MOD(phy_base, HDMI_TXPHY_TX_CTRL, 0x1, 31, 30);
+
+       /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */
+       hdmi_write_reg(phy_base, HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000);
+
+       /* Setup max LDO voltage */
+       REG_FLD_MOD(phy_base, HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0);
+
+       /* Write to phy address 3 to change the polarity control */
+       REG_FLD_MOD(phy_base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27);
+
+       return 0;
+}
+
+void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data)
+{
+       hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
+}
+
+static int hdmi_core_ddc_init(struct hdmi_ip_data *ip_data)
+{
+       void __iomem *base = hdmi_core_sys_base(ip_data);
+
+       /* Turn on CLK for DDC */
+       REG_FLD_MOD(base, HDMI_CORE_AV_DPD, 0x7, 2, 0);
+
+       /* IN_PROG */
+       if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 1) {
+               /* Abort transaction */
+               REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xf, 3, 0);
+               /* IN_PROG */
+               if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
+                                       4, 4, 0) != 0) {
+                       DSSERR("Timeout aborting DDC transaction\n");
+                       return -ETIMEDOUT;
+               }
+       }
+
+       /* Clk SCL Devices */
+       REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xA, 3, 0);
+
+       /* HDMI_CORE_DDC_STATUS_IN_PROG */
+       if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
+                               4, 4, 0) != 0) {
+               DSSERR("Timeout starting SCL clock\n");
+               return -ETIMEDOUT;
+       }
+
+       /* Clear FIFO */
+       REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x9, 3, 0);
+
+       /* HDMI_CORE_DDC_STATUS_IN_PROG */
+       if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
+                               4, 4, 0) != 0) {
+               DSSERR("Timeout clearing DDC fifo\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static int hdmi_core_ddc_edid(struct hdmi_ip_data *ip_data,
+               u8 *pedid, int ext)
+{
+       void __iomem *base = hdmi_core_sys_base(ip_data);
+       u32 i;
+       char checksum;
+       u32 offset = 0;
+
+       /* HDMI_CORE_DDC_STATUS_IN_PROG */
+       if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
+                               4, 4, 0) != 0) {
+               DSSERR("Timeout waiting DDC to be ready\n");
+               return -ETIMEDOUT;
+       }
+
+       if (ext % 2 != 0)
+               offset = 0x80;
+
+       /* Load Segment Address Register */
+       REG_FLD_MOD(base, HDMI_CORE_DDC_SEGM, ext / 2, 7, 0);
+
+       /* Load Slave Address Register */
+       REG_FLD_MOD(base, HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1);
+
+       /* Load Offset Address Register */
+       REG_FLD_MOD(base, HDMI_CORE_DDC_OFFSET, offset, 7, 0);
+
+       /* Load Byte Count */
+       REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT1, 0x80, 7, 0);
+       REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT2, 0x0, 1, 0);
+
+       /* Set DDC_CMD */
+       if (ext)
+               REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x4, 3, 0);
+       else
+               REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x2, 3, 0);
+
+       /* HDMI_CORE_DDC_STATUS_BUS_LOW */
+       if (REG_GET(base, HDMI_CORE_DDC_STATUS, 6, 6) == 1) {
+               pr_err("I2C Bus Low?\n");
+               return -EIO;
+       }
+       /* HDMI_CORE_DDC_STATUS_NO_ACK */
+       if (REG_GET(base, HDMI_CORE_DDC_STATUS, 5, 5) == 1) {
+               pr_err("I2C No Ack\n");
+               return -EIO;
+       }
+
+       for (i = 0; i < 0x80; ++i) {
+               int t;
+
+               /* IN_PROG */
+               if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 0) {
+                       DSSERR("operation stopped when reading edid\n");
+                       return -EIO;
+               }
+
+               t = 0;
+               /* FIFO_EMPTY */
+               while (REG_GET(base, HDMI_CORE_DDC_STATUS, 2, 2) == 1) {
+                       if (t++ > 10000) {
+                               DSSERR("timeout reading edid\n");
+                               return -ETIMEDOUT;
+                       }
+                       udelay(1);
+               }
+
+               pedid[i] = REG_GET(base, HDMI_CORE_DDC_DATA, 7, 0);
+       }
+
+       checksum = 0;
+       for (i = 0; i < 0x80; ++i)
+               checksum += pedid[i];
+
+       if (checksum != 0) {
+               pr_err("E-EDID checksum failed!!\n");
+               return -EIO;
+       }
+
+       return 0;
+}
+
+int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data,
+                               u8 *edid, int len)
+{
+       int r, l;
+
+       if (len < 128)
+               return -EINVAL;
+
+       r = hdmi_core_ddc_init(ip_data);
+       if (r)
+               return r;
+
+       r = hdmi_core_ddc_edid(ip_data, edid, 0);
+       if (r)
+               return r;
+
+       l = 128;
+
+       if (len >= 128 * 2 && edid[0x7e] > 0) {
+               r = hdmi_core_ddc_edid(ip_data, edid + 0x80, 1);
+               if (r)
+                       return r;
+               l += 128;
+       }
+
+       return l;
+}
+
+bool ti_hdmi_4xxx_detect(struct hdmi_ip_data *ip_data)
+{
+       int r;
+
+       void __iomem *base = hdmi_core_sys_base(ip_data);
+
+       /* HPD */
+       r = REG_GET(base, HDMI_CORE_SYS_SYS_STAT, 1, 1);
+
+       return r == 1;
+}
+
+static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,
+                       struct hdmi_core_infoframe_avi *avi_cfg,
+                       struct hdmi_core_packet_enable_repeat *repeat_cfg)
+{
+       pr_debug("Enter hdmi_core_init\n");
+
+       /* video core */
+       video_cfg->ip_bus_width = HDMI_INPUT_8BIT;
+       video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT;
+       video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE;
+       video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE;
+       video_cfg->hdmi_dvi = HDMI_DVI;
+       video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK;
+
+       /* info frame */
+       avi_cfg->db1_format = 0;
+       avi_cfg->db1_active_info = 0;
+       avi_cfg->db1_bar_info_dv = 0;
+       avi_cfg->db1_scan_info = 0;
+       avi_cfg->db2_colorimetry = 0;
+       avi_cfg->db2_aspect_ratio = 0;
+       avi_cfg->db2_active_fmt_ar = 0;
+       avi_cfg->db3_itc = 0;
+       avi_cfg->db3_ec = 0;
+       avi_cfg->db3_q_range = 0;
+       avi_cfg->db3_nup_scaling = 0;
+       avi_cfg->db4_videocode = 0;
+       avi_cfg->db5_pixel_repeat = 0;
+       avi_cfg->db6_7_line_eoftop = 0 ;
+       avi_cfg->db8_9_line_sofbottom = 0;
+       avi_cfg->db10_11_pixel_eofleft = 0;
+       avi_cfg->db12_13_pixel_sofright = 0;
+
+       /* packet enable and repeat */
+       repeat_cfg->audio_pkt = 0;
+       repeat_cfg->audio_pkt_repeat = 0;
+       repeat_cfg->avi_infoframe = 0;
+       repeat_cfg->avi_infoframe_repeat = 0;
+       repeat_cfg->gen_cntrl_pkt = 0;
+       repeat_cfg->gen_cntrl_pkt_repeat = 0;
+       repeat_cfg->generic_pkt = 0;
+       repeat_cfg->generic_pkt_repeat = 0;
+}
+
+static void hdmi_core_powerdown_disable(struct hdmi_ip_data *ip_data)
+{
+       pr_debug("Enter hdmi_core_powerdown_disable\n");
+       REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_CTRL1, 0x0, 0, 0);
+}
+
+static void hdmi_core_swreset_release(struct hdmi_ip_data *ip_data)
+{
+       pr_debug("Enter hdmi_core_swreset_release\n");
+       REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_SRST, 0x0, 0, 0);
+}
+
+static void hdmi_core_swreset_assert(struct hdmi_ip_data *ip_data)
+{
+       pr_debug("Enter hdmi_core_swreset_assert\n");
+       REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_SRST, 0x1, 0, 0);
+}
+
+/* HDMI_CORE_VIDEO_CONFIG */
+static void hdmi_core_video_config(struct hdmi_ip_data *ip_data,
+                               struct hdmi_core_video_config *cfg)
+{
+       u32 r = 0;
+       void __iomem *core_sys_base = hdmi_core_sys_base(ip_data);
+
+       /* sys_ctrl1 default configuration not tunable */
+       r = hdmi_read_reg(core_sys_base, HDMI_CORE_CTRL1);
+       r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5);
+       r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4);
+       r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2);
+       r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1);
+       hdmi_write_reg(core_sys_base, HDMI_CORE_CTRL1, r);
+
+       REG_FLD_MOD(core_sys_base,
+                       HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6);
+
+       /* Vid_Mode */
+       r = hdmi_read_reg(core_sys_base, HDMI_CORE_SYS_VID_MODE);
+
+       /* dither truncation configuration */
+       if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) {
+               r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6);
+               r = FLD_MOD(r, 1, 5, 5);
+       } else {
+               r = FLD_MOD(r, cfg->op_dither_truc, 7, 6);
+               r = FLD_MOD(r, 0, 5, 5);
+       }
+       hdmi_write_reg(core_sys_base, HDMI_CORE_SYS_VID_MODE, r);
+
+       /* HDMI_Ctrl */
+       r = hdmi_read_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_HDMI_CTRL);
+       r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6);
+       r = FLD_MOD(r, cfg->pkt_mode, 5, 3);
+       r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0);
+       hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_HDMI_CTRL, r);
+
+       /* TMDS_CTRL */
+       REG_FLD_MOD(core_sys_base,
+                       HDMI_CORE_SYS_TMDS_CTRL, cfg->tclk_sel_clkmult, 6, 5);
+}
+
+static void hdmi_core_aux_infoframe_avi_config(struct hdmi_ip_data *ip_data,
+               struct hdmi_core_infoframe_avi info_avi)
+{
+       u32 val;
+       char sum = 0, checksum = 0;
+       void __iomem *av_base = hdmi_av_base(ip_data);
+
+       sum += 0x82 + 0x002 + 0x00D;
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_TYPE, 0x082);
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_VERS, 0x002);
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_LEN, 0x00D);
+
+       val = (info_avi.db1_format << 5) |
+               (info_avi.db1_active_info << 4) |
+               (info_avi.db1_bar_info_dv << 2) |
+               (info_avi.db1_scan_info);
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(0), val);
+       sum += val;
+
+       val = (info_avi.db2_colorimetry << 6) |
+               (info_avi.db2_aspect_ratio << 4) |
+               (info_avi.db2_active_fmt_ar);
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(1), val);
+       sum += val;
+
+       val = (info_avi.db3_itc << 7) |
+               (info_avi.db3_ec << 4) |
+               (info_avi.db3_q_range << 2) |
+               (info_avi.db3_nup_scaling);
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(2), val);
+       sum += val;
+
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(3),
+                                       info_avi.db4_videocode);
+       sum += info_avi.db4_videocode;
+
+       val = info_avi.db5_pixel_repeat;
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(4), val);
+       sum += val;
+
+       val = info_avi.db6_7_line_eoftop & 0x00FF;
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(5), val);
+       sum += val;
+
+       val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF);
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(6), val);
+       sum += val;
+
+       val = info_avi.db8_9_line_sofbottom & 0x00FF;
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(7), val);
+       sum += val;
+
+       val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF);
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(8), val);
+       sum += val;
+
+       val = info_avi.db10_11_pixel_eofleft & 0x00FF;
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(9), val);
+       sum += val;
+
+       val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF);
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(10), val);
+       sum += val;
+
+       val = info_avi.db12_13_pixel_sofright & 0x00FF;
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(11), val);
+       sum += val;
+
+       val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF);
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(12), val);
+       sum += val;
+
+       checksum = 0x100 - sum;
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_CHSUM, checksum);
+}
+
+static void hdmi_core_av_packet_config(struct hdmi_ip_data *ip_data,
+               struct hdmi_core_packet_enable_repeat repeat_cfg)
+{
+       /* enable/repeat the infoframe */
+       hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_PB_CTRL1,
+               (repeat_cfg.audio_pkt << 5) |
+               (repeat_cfg.audio_pkt_repeat << 4) |
+               (repeat_cfg.avi_infoframe << 1) |
+               (repeat_cfg.avi_infoframe_repeat));
+
+       /* enable/repeat the packet */
+       hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_PB_CTRL2,
+               (repeat_cfg.gen_cntrl_pkt << 3) |
+               (repeat_cfg.gen_cntrl_pkt_repeat << 2) |
+               (repeat_cfg.generic_pkt << 1) |
+               (repeat_cfg.generic_pkt_repeat));
+}
+
+static void hdmi_wp_init(struct omap_video_timings *timings,
+                       struct hdmi_video_format *video_fmt,
+                       struct hdmi_video_interface *video_int)
+{
+       pr_debug("Enter hdmi_wp_init\n");
+
+       timings->hbp = 0;
+       timings->hfp = 0;
+       timings->hsw = 0;
+       timings->vbp = 0;
+       timings->vfp = 0;
+       timings->vsw = 0;
+
+       video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444;
+       video_fmt->y_res = 0;
+       video_fmt->x_res = 0;
+
+       video_int->vsp = 0;
+       video_int->hsp = 0;
+
+       video_int->interlacing = 0;
+       video_int->tm = 0; /* HDMI_TIMING_SLAVE */
+
+}
+
+void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start)
+{
+       REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, start, 31, 31);
+}
+
+static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt,
+       struct omap_video_timings *timings, struct hdmi_config *param)
+{
+       pr_debug("Enter hdmi_wp_video_init_format\n");
+
+       video_fmt->y_res = param->timings.timings.y_res;
+       video_fmt->x_res = param->timings.timings.x_res;
+
+       timings->hbp = param->timings.timings.hbp;
+       timings->hfp = param->timings.timings.hfp;
+       timings->hsw = param->timings.timings.hsw;
+       timings->vbp = param->timings.timings.vbp;
+       timings->vfp = param->timings.timings.vfp;
+       timings->vsw = param->timings.timings.vsw;
+}
+
+static void hdmi_wp_video_config_format(struct hdmi_ip_data *ip_data,
+               struct hdmi_video_format *video_fmt)
+{
+       u32 l = 0;
+
+       REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG,
+                       video_fmt->packing_mode, 10, 8);
+
+       l |= FLD_VAL(video_fmt->y_res, 31, 16);
+       l |= FLD_VAL(video_fmt->x_res, 15, 0);
+       hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_SIZE, l);
+}
+
+static void hdmi_wp_video_config_interface(struct hdmi_ip_data *ip_data,
+               struct hdmi_video_interface *video_int)
+{
+       u32 r;
+       pr_debug("Enter hdmi_wp_video_config_interface\n");
+
+       r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG);
+       r = FLD_MOD(r, video_int->vsp, 7, 7);
+       r = FLD_MOD(r, video_int->hsp, 6, 6);
+       r = FLD_MOD(r, video_int->interlacing, 3, 3);
+       r = FLD_MOD(r, video_int->tm, 1, 0);
+       hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, r);
+}
+
+static void hdmi_wp_video_config_timing(struct hdmi_ip_data *ip_data,
+               struct omap_video_timings *timings)
+{
+       u32 timing_h = 0;
+       u32 timing_v = 0;
+
+       pr_debug("Enter hdmi_wp_video_config_timing\n");
+
+       timing_h |= FLD_VAL(timings->hbp, 31, 20);
+       timing_h |= FLD_VAL(timings->hfp, 19, 8);
+       timing_h |= FLD_VAL(timings->hsw, 7, 0);
+       hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_TIMING_H, timing_h);
+
+       timing_v |= FLD_VAL(timings->vbp, 31, 20);
+       timing_v |= FLD_VAL(timings->vfp, 19, 8);
+       timing_v |= FLD_VAL(timings->vsw, 7, 0);
+       hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_TIMING_V, timing_v);
+}
+
+void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data)
+{
+       /* HDMI */
+       struct omap_video_timings video_timing;
+       struct hdmi_video_format video_format;
+       struct hdmi_video_interface video_interface;
+       /* HDMI core */
+       struct hdmi_core_infoframe_avi avi_cfg;
+       struct hdmi_core_video_config v_core_cfg;
+       struct hdmi_core_packet_enable_repeat repeat_cfg;
+       struct hdmi_config *cfg = &ip_data->cfg;
+
+       hdmi_wp_init(&video_timing, &video_format,
+               &video_interface);
+
+       hdmi_core_init(&v_core_cfg,
+               &avi_cfg,
+               &repeat_cfg);
+
+       hdmi_wp_video_init_format(&video_format, &video_timing, cfg);
+
+       hdmi_wp_video_config_timing(ip_data, &video_timing);
+
+       /* video config */
+       video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422;
+
+       hdmi_wp_video_config_format(ip_data, &video_format);
+
+       video_interface.vsp = cfg->timings.vsync_pol;
+       video_interface.hsp = cfg->timings.hsync_pol;
+       video_interface.interlacing = cfg->interlace;
+       video_interface.tm = 1 ; /* HDMI_TIMING_MASTER_24BIT */
+
+       hdmi_wp_video_config_interface(ip_data, &video_interface);
+
+       /*
+        * configure core video part
+        * set software reset in the core
+        */
+       hdmi_core_swreset_assert(ip_data);
+
+       /* power down off */
+       hdmi_core_powerdown_disable(ip_data);
+
+       v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL;
+       v_core_cfg.hdmi_dvi = cfg->cm.mode;
+
+       hdmi_core_video_config(ip_data, &v_core_cfg);
+
+       /* release software reset in the core */
+       hdmi_core_swreset_release(ip_data);
+
+       /*
+        * configure packet
+        * info frame video see doc CEA861-D page 65
+        */
+       avi_cfg.db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB;
+       avi_cfg.db1_active_info =
+               HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF;
+       avi_cfg.db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO;
+       avi_cfg.db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0;
+       avi_cfg.db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO;
+       avi_cfg.db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO;
+       avi_cfg.db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME;
+       avi_cfg.db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO;
+       avi_cfg.db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601;
+       avi_cfg.db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT;
+       avi_cfg.db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO;
+       avi_cfg.db4_videocode = cfg->cm.code;
+       avi_cfg.db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO;
+       avi_cfg.db6_7_line_eoftop = 0;
+       avi_cfg.db8_9_line_sofbottom = 0;
+       avi_cfg.db10_11_pixel_eofleft = 0;
+       avi_cfg.db12_13_pixel_sofright = 0;
+
+       hdmi_core_aux_infoframe_avi_config(ip_data, avi_cfg);
+
+       /* enable/repeat the infoframe */
+       repeat_cfg.avi_infoframe = HDMI_PACKETENABLE;
+       repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON;
+       /* wakeup */
+       repeat_cfg.audio_pkt = HDMI_PACKETENABLE;
+       repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON;
+       hdmi_core_av_packet_config(ip_data, repeat_cfg);
+}
+
+void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
+{
+#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r,\
+               hdmi_read_reg(hdmi_wp_base(ip_data), r))
+
+       DUMPREG(HDMI_WP_REVISION);
+       DUMPREG(HDMI_WP_SYSCONFIG);
+       DUMPREG(HDMI_WP_IRQSTATUS_RAW);
+       DUMPREG(HDMI_WP_IRQSTATUS);
+       DUMPREG(HDMI_WP_PWR_CTRL);
+       DUMPREG(HDMI_WP_IRQENABLE_SET);
+       DUMPREG(HDMI_WP_VIDEO_CFG);
+       DUMPREG(HDMI_WP_VIDEO_SIZE);
+       DUMPREG(HDMI_WP_VIDEO_TIMING_H);
+       DUMPREG(HDMI_WP_VIDEO_TIMING_V);
+       DUMPREG(HDMI_WP_WP_CLK);
+       DUMPREG(HDMI_WP_AUDIO_CFG);
+       DUMPREG(HDMI_WP_AUDIO_CFG2);
+       DUMPREG(HDMI_WP_AUDIO_CTRL);
+       DUMPREG(HDMI_WP_AUDIO_DATA);
+}
+
+void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
+{
+#define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\
+               hdmi_read_reg(hdmi_pll_base(ip_data), r))
+
+       DUMPPLL(PLLCTRL_PLL_CONTROL);
+       DUMPPLL(PLLCTRL_PLL_STATUS);
+       DUMPPLL(PLLCTRL_PLL_GO);
+       DUMPPLL(PLLCTRL_CFG1);
+       DUMPPLL(PLLCTRL_CFG2);
+       DUMPPLL(PLLCTRL_CFG3);
+       DUMPPLL(PLLCTRL_CFG4);
+}
+
+void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
+{
+       int i;
+
+#define CORE_REG(i, name) name(i)
+#define DUMPCORE(r) seq_printf(s, "%-35s %08x\n", #r,\
+               hdmi_read_reg(hdmi_pll_base(ip_data), r))
+#define DUMPCOREAV(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \
+               (i < 10) ? 32 - strlen(#r) : 31 - strlen(#r), " ", \
+               hdmi_read_reg(hdmi_pll_base(ip_data), CORE_REG(i, r)))
+
+       DUMPCORE(HDMI_CORE_SYS_VND_IDL);
+       DUMPCORE(HDMI_CORE_SYS_DEV_IDL);
+       DUMPCORE(HDMI_CORE_SYS_DEV_IDH);
+       DUMPCORE(HDMI_CORE_SYS_DEV_REV);
+       DUMPCORE(HDMI_CORE_SYS_SRST);
+       DUMPCORE(HDMI_CORE_CTRL1);
+       DUMPCORE(HDMI_CORE_SYS_SYS_STAT);
+       DUMPCORE(HDMI_CORE_SYS_VID_ACEN);
+       DUMPCORE(HDMI_CORE_SYS_VID_MODE);
+       DUMPCORE(HDMI_CORE_SYS_INTR_STATE);
+       DUMPCORE(HDMI_CORE_SYS_INTR1);
+       DUMPCORE(HDMI_CORE_SYS_INTR2);
+       DUMPCORE(HDMI_CORE_SYS_INTR3);
+       DUMPCORE(HDMI_CORE_SYS_INTR4);
+       DUMPCORE(HDMI_CORE_SYS_UMASK1);
+       DUMPCORE(HDMI_CORE_SYS_TMDS_CTRL);
+       DUMPCORE(HDMI_CORE_SYS_DE_DLY);
+       DUMPCORE(HDMI_CORE_SYS_DE_CTRL);
+       DUMPCORE(HDMI_CORE_SYS_DE_TOP);
+       DUMPCORE(HDMI_CORE_SYS_DE_CNTL);
+       DUMPCORE(HDMI_CORE_SYS_DE_CNTH);
+       DUMPCORE(HDMI_CORE_SYS_DE_LINL);
+       DUMPCORE(HDMI_CORE_SYS_DE_LINH_1);
+
+       DUMPCORE(HDMI_CORE_DDC_CMD);
+       DUMPCORE(HDMI_CORE_DDC_STATUS);
+       DUMPCORE(HDMI_CORE_DDC_ADDR);
+       DUMPCORE(HDMI_CORE_DDC_OFFSET);
+       DUMPCORE(HDMI_CORE_DDC_COUNT1);
+       DUMPCORE(HDMI_CORE_DDC_COUNT2);
+       DUMPCORE(HDMI_CORE_DDC_DATA);
+       DUMPCORE(HDMI_CORE_DDC_SEGM);
+
+       DUMPCORE(HDMI_CORE_AV_HDMI_CTRL);
+       DUMPCORE(HDMI_CORE_AV_DPD);
+       DUMPCORE(HDMI_CORE_AV_PB_CTRL1);
+       DUMPCORE(HDMI_CORE_AV_PB_CTRL2);
+       DUMPCORE(HDMI_CORE_AV_AVI_TYPE);
+       DUMPCORE(HDMI_CORE_AV_AVI_VERS);
+       DUMPCORE(HDMI_CORE_AV_AVI_LEN);
+       DUMPCORE(HDMI_CORE_AV_AVI_CHSUM);
+
+       for (i = 0; i < HDMI_CORE_AV_AVI_DBYTE_NELEMS; i++)
+               DUMPCOREAV(i, HDMI_CORE_AV_AVI_DBYTE);
+
+       for (i = 0; i < HDMI_CORE_AV_SPD_DBYTE_NELEMS; i++)
+               DUMPCOREAV(i, HDMI_CORE_AV_SPD_DBYTE);
+
+       for (i = 0; i < HDMI_CORE_AV_AUD_DBYTE_NELEMS; i++)
+               DUMPCOREAV(i, HDMI_CORE_AV_AUD_DBYTE);
+
+       for (i = 0; i < HDMI_CORE_AV_MPEG_DBYTE_NELEMS; i++)
+               DUMPCOREAV(i, HDMI_CORE_AV_MPEG_DBYTE);
+
+       for (i = 0; i < HDMI_CORE_AV_GEN_DBYTE_NELEMS; i++)
+               DUMPCOREAV(i, HDMI_CORE_AV_GEN_DBYTE);
+
+       for (i = 0; i < HDMI_CORE_AV_GEN2_DBYTE_NELEMS; i++)
+               DUMPCOREAV(i, HDMI_CORE_AV_GEN2_DBYTE);
+
+       DUMPCORE(HDMI_CORE_AV_ACR_CTRL);
+       DUMPCORE(HDMI_CORE_AV_FREQ_SVAL);
+       DUMPCORE(HDMI_CORE_AV_N_SVAL1);
+       DUMPCORE(HDMI_CORE_AV_N_SVAL2);
+       DUMPCORE(HDMI_CORE_AV_N_SVAL3);
+       DUMPCORE(HDMI_CORE_AV_CTS_SVAL1);
+       DUMPCORE(HDMI_CORE_AV_CTS_SVAL2);
+       DUMPCORE(HDMI_CORE_AV_CTS_SVAL3);
+       DUMPCORE(HDMI_CORE_AV_CTS_HVAL1);
+       DUMPCORE(HDMI_CORE_AV_CTS_HVAL2);
+       DUMPCORE(HDMI_CORE_AV_CTS_HVAL3);
+       DUMPCORE(HDMI_CORE_AV_AUD_MODE);
+       DUMPCORE(HDMI_CORE_AV_SPDIF_CTRL);
+       DUMPCORE(HDMI_CORE_AV_HW_SPDIF_FS);
+       DUMPCORE(HDMI_CORE_AV_SWAP_I2S);
+       DUMPCORE(HDMI_CORE_AV_SPDIF_ERTH);
+       DUMPCORE(HDMI_CORE_AV_I2S_IN_MAP);
+       DUMPCORE(HDMI_CORE_AV_I2S_IN_CTRL);
+       DUMPCORE(HDMI_CORE_AV_I2S_CHST0);
+       DUMPCORE(HDMI_CORE_AV_I2S_CHST1);
+       DUMPCORE(HDMI_CORE_AV_I2S_CHST2);
+       DUMPCORE(HDMI_CORE_AV_I2S_CHST4);
+       DUMPCORE(HDMI_CORE_AV_I2S_CHST5);
+       DUMPCORE(HDMI_CORE_AV_ASRC);
+       DUMPCORE(HDMI_CORE_AV_I2S_IN_LEN);
+       DUMPCORE(HDMI_CORE_AV_HDMI_CTRL);
+       DUMPCORE(HDMI_CORE_AV_AUDO_TXSTAT);
+       DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_1);
+       DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_2);
+       DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_3);
+       DUMPCORE(HDMI_CORE_AV_TEST_TXCTRL);
+       DUMPCORE(HDMI_CORE_AV_DPD);
+       DUMPCORE(HDMI_CORE_AV_PB_CTRL1);
+       DUMPCORE(HDMI_CORE_AV_PB_CTRL2);
+       DUMPCORE(HDMI_CORE_AV_AVI_TYPE);
+       DUMPCORE(HDMI_CORE_AV_AVI_VERS);
+       DUMPCORE(HDMI_CORE_AV_AVI_LEN);
+       DUMPCORE(HDMI_CORE_AV_AVI_CHSUM);
+       DUMPCORE(HDMI_CORE_AV_SPD_TYPE);
+       DUMPCORE(HDMI_CORE_AV_SPD_VERS);
+       DUMPCORE(HDMI_CORE_AV_SPD_LEN);
+       DUMPCORE(HDMI_CORE_AV_SPD_CHSUM);
+       DUMPCORE(HDMI_CORE_AV_AUDIO_TYPE);
+       DUMPCORE(HDMI_CORE_AV_AUDIO_VERS);
+       DUMPCORE(HDMI_CORE_AV_AUDIO_LEN);
+       DUMPCORE(HDMI_CORE_AV_AUDIO_CHSUM);
+       DUMPCORE(HDMI_CORE_AV_MPEG_TYPE);
+       DUMPCORE(HDMI_CORE_AV_MPEG_VERS);
+       DUMPCORE(HDMI_CORE_AV_MPEG_LEN);
+       DUMPCORE(HDMI_CORE_AV_MPEG_CHSUM);
+       DUMPCORE(HDMI_CORE_AV_CP_BYTE1);
+       DUMPCORE(HDMI_CORE_AV_CEC_ADDR_ID);
+}
+
+void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
+{
+#define DUMPPHY(r) seq_printf(s, "%-35s %08x\n", #r,\
+               hdmi_read_reg(hdmi_phy_base(ip_data), r))
+
+       DUMPPHY(HDMI_TXPHY_TX_CTRL);
+       DUMPPHY(HDMI_TXPHY_DIGITAL_CTRL);
+       DUMPPHY(HDMI_TXPHY_POWER_CTRL);
+       DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL);
+}
+
+#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
+       defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
+void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data,
+                                       struct hdmi_audio_format *aud_fmt)
+{
+       u32 r;
+
+       DSSDBG("Enter hdmi_wp_audio_config_format\n");
+
+       r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG);
+       r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24);
+       r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16);
+       r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5);
+       r = FLD_MOD(r, aud_fmt->type, 4, 4);
+       r = FLD_MOD(r, aud_fmt->justification, 3, 3);
+       r = FLD_MOD(r, aud_fmt->sample_order, 2, 2);
+       r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1);
+       r = FLD_MOD(r, aud_fmt->sample_size, 0, 0);
+       hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG, r);
+}
+
+void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data,
+                                       struct hdmi_audio_dma *aud_dma)
+{
+       u32 r;
+
+       DSSDBG("Enter hdmi_wp_audio_config_dma\n");
+
+       r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG2);
+       r = FLD_MOD(r, aud_dma->transfer_size, 15, 8);
+       r = FLD_MOD(r, aud_dma->block_size, 7, 0);
+       hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG2, r);
+
+       r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL);
+       r = FLD_MOD(r, aud_dma->mode, 9, 9);
+       r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0);
+       hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL, r);
+}
+
+void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
+                                       struct hdmi_core_audio_config *cfg)
+{
+       u32 r;
+       void __iomem *av_base = hdmi_av_base(ip_data);
+
+       /* audio clock recovery parameters */
+       r = hdmi_read_reg(av_base, HDMI_CORE_AV_ACR_CTRL);
+       r = FLD_MOD(r, cfg->use_mclk, 2, 2);
+       r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1);
+       r = FLD_MOD(r, cfg->cts_mode, 0, 0);
+       hdmi_write_reg(av_base, HDMI_CORE_AV_ACR_CTRL, r);
+
+       REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0);
+       REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0);
+       REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0);
+
+       if (cfg->cts_mode == HDMI_AUDIO_CTS_MODE_SW) {
+               REG_FLD_MOD(av_base, HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0);
+               REG_FLD_MOD(av_base,
+                               HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0);
+               REG_FLD_MOD(av_base,
+                               HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0);
+       } else {
+               /*
+                * HDMI IP uses this configuration to divide the MCLK to
+                * update CTS value.
+                */
+               REG_FLD_MOD(av_base,
+                               HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0);
+
+               /* Configure clock for audio packets */
+               REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_1,
+                               cfg->aud_par_busclk, 7, 0);
+               REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_2,
+                               (cfg->aud_par_busclk >> 8), 7, 0);
+               REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_3,
+                               (cfg->aud_par_busclk >> 16), 7, 0);
+       }
+
+       /* Override of SPDIF sample frequency with value in I2S_CHST4 */
+       REG_FLD_MOD(av_base, HDMI_CORE_AV_SPDIF_CTRL,
+                                               cfg->fs_override, 1, 1);
+
+       /* I2S parameters */
+       REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_CHST4,
+                                               cfg->freq_sample, 3, 0);
+
+       r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL);
+       r = FLD_MOD(r, cfg->i2s_cfg.en_high_bitrate_aud, 7, 7);
+       r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6);
+       r = FLD_MOD(r, cfg->i2s_cfg.cbit_order, 5, 5);
+       r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4);
+       r = FLD_MOD(r, cfg->i2s_cfg.ws_polarity, 3, 3);
+       r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2);
+       r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1);
+       r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0);
+       hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL, r);
+
+       r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_CHST5);
+       r = FLD_MOD(r, cfg->freq_sample, 7, 4);
+       r = FLD_MOD(r, cfg->i2s_cfg.word_length, 3, 1);
+       r = FLD_MOD(r, cfg->i2s_cfg.word_max_length, 0, 0);
+       hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST5, r);
+
+       REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_IN_LEN,
+                       cfg->i2s_cfg.in_length_bits, 3, 0);
+
+       /* Audio channels and mode parameters */
+       REG_FLD_MOD(av_base, HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1);
+       r = hdmi_read_reg(av_base, HDMI_CORE_AV_AUD_MODE);
+       r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4);
+       r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3);
+       r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2);
+       r = FLD_MOD(r, cfg->en_spdif, 1, 1);
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_MODE, r);
+}
+
+void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
+               struct hdmi_core_infoframe_audio *info_aud)
+{
+       u8 val;
+       u8 sum = 0, checksum = 0;
+       void __iomem *av_base = hdmi_av_base(ip_data);
+
+       /*
+        * Set audio info frame type, version and length as
+        * described in HDMI 1.4a Section 8.2.2 specification.
+        * Checksum calculation is defined in Section 5.3.5.
+        */
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_TYPE, 0x84);
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_VERS, 0x01);
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_LEN, 0x0a);
+       sum += 0x84 + 0x001 + 0x00a;
+
+       val = (info_aud->db1_coding_type << 4)
+                       | (info_aud->db1_channel_count - 1);
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(0), val);
+       sum += val;
+
+       val = (info_aud->db2_sample_freq << 2) | info_aud->db2_sample_size;
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(1), val);
+       sum += val;
+
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(2), 0x00);
+
+       val = info_aud->db4_channel_alloc;
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(3), val);
+       sum += val;
+
+       val = (info_aud->db5_downmix_inh << 7) | (info_aud->db5_lsv << 3);
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(4), val);
+       sum += val;
+
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(5), 0x00);
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(6), 0x00);
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(7), 0x00);
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(8), 0x00);
+       hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(9), 0x00);
+
+       checksum = 0x100 - sum;
+       hdmi_write_reg(av_base,
+                                       HDMI_CORE_AV_AUDIO_CHSUM, checksum);
+
+       /*
+        * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing
+        * is available.
+        */
+}
+
+int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data,
+                               u32 sample_freq, u32 *n, u32 *cts)
+{
+       u32 r;
+       u32 deep_color = 0;
+       u32 pclk = ip_data->cfg.timings.timings.pixel_clock;
+
+       if (n == NULL || cts == NULL)
+               return -EINVAL;
+       /*
+        * Obtain current deep color configuration. This needed
+        * to calculate the TMDS clock based on the pixel clock.
+        */
+       r = REG_GET(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, 1, 0);
+       switch (r) {
+       case 1: /* No deep color selected */
+               deep_color = 100;
+               break;
+       case 2: /* 10-bit deep color selected */
+               deep_color = 125;
+               break;
+       case 3: /* 12-bit deep color selected */
+               deep_color = 150;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (sample_freq) {
+       case 32000:
+               if ((deep_color == 125) && ((pclk == 54054)
+                               || (pclk == 74250)))
+                       *n = 8192;
+               else
+                       *n = 4096;
+               break;
+       case 44100:
+               *n = 6272;
+               break;
+       case 48000:
+               if ((deep_color == 125) && ((pclk == 54054)
+                               || (pclk == 74250)))
+                       *n = 8192;
+               else
+                       *n = 6144;
+               break;
+       default:
+               *n = 0;
+               return -EINVAL;
+       }
+
+       /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
+       *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10);
+
+       return 0;
+}
+
+int hdmi_audio_trigger(struct hdmi_ip_data *ip_data,
+                               struct snd_pcm_substream *substream, int cmd,
+                               struct snd_soc_dai *dai)
+{
+       int err = 0;
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               REG_FLD_MOD(hdmi_av_base(ip_data),
+                                       HDMI_CORE_AV_AUD_MODE, 1, 0, 0);
+               REG_FLD_MOD(hdmi_wp_base(ip_data),
+                                       HDMI_WP_AUDIO_CTRL, 1, 31, 31);
+               REG_FLD_MOD(hdmi_wp_base(ip_data),
+                                       HDMI_WP_AUDIO_CTRL, 1, 30, 30);
+               break;
+
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               REG_FLD_MOD(hdmi_av_base(ip_data),
+                                       HDMI_CORE_AV_AUD_MODE, 0, 0, 0);
+               REG_FLD_MOD(hdmi_wp_base(ip_data),
+                                       HDMI_WP_AUDIO_CTRL, 0, 30, 30);
+               REG_FLD_MOD(hdmi_wp_base(ip_data),
+                                       HDMI_WP_AUDIO_CTRL, 0, 31, 31);
+               break;
+       default:
+               err = -EINVAL;
+       }
+       return err;
+}
+#endif
similarity index 54%
rename from drivers/video/omap2/dss/hdmi.h
rename to drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
index c885f9c..2040956 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * hdmi.h
+ * ti_hdmi_4xxx_ip.h
  *
- * HDMI driver definition for TI OMAP4 processors.
+ * HDMI header definition for DM81xx, DM38xx, TI OMAP4 etc processors.
  *
  * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
  *
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef _OMAP4_DSS_HDMI_H_
-#define _OMAP4_DSS_HDMI_H_
+#ifndef _HDMI_TI_4xxx_H_
+#define _HDMI_TI_4xxx_H_
 
 #include <linux/string.h>
 #include <video/omapdss.h>
-
-#define HDMI_WP                0x0
-#define HDMI_CORE_SYS          0x400
-#define HDMI_CORE_AV           0x900
-#define HDMI_PLLCTRL           0x200
-#define HDMI_PHY               0x300
-
-struct hdmi_reg { u16 idx; };
-
-#define HDMI_REG(idx)                  ((const struct hdmi_reg) { idx })
+#include "ti_hdmi.h"
+#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
+       defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+#endif
 
 /* HDMI Wrapper */
-#define HDMI_WP_REG(idx)                       HDMI_REG(HDMI_WP + idx)
-
-#define HDMI_WP_REVISION                       HDMI_WP_REG(0x0)
-#define HDMI_WP_SYSCONFIG                      HDMI_WP_REG(0x10)
-#define HDMI_WP_IRQSTATUS_RAW                  HDMI_WP_REG(0x24)
-#define HDMI_WP_IRQSTATUS                      HDMI_WP_REG(0x28)
-#define HDMI_WP_PWR_CTRL                       HDMI_WP_REG(0x40)
-#define HDMI_WP_IRQENABLE_SET                  HDMI_WP_REG(0x2C)
-#define HDMI_WP_VIDEO_CFG                      HDMI_WP_REG(0x50)
-#define HDMI_WP_VIDEO_SIZE                     HDMI_WP_REG(0x60)
-#define HDMI_WP_VIDEO_TIMING_H                 HDMI_WP_REG(0x68)
-#define HDMI_WP_VIDEO_TIMING_V                 HDMI_WP_REG(0x6C)
-#define HDMI_WP_WP_CLK                         HDMI_WP_REG(0x70)
-#define HDMI_WP_AUDIO_CFG                      HDMI_WP_REG(0x80)
-#define HDMI_WP_AUDIO_CFG2                     HDMI_WP_REG(0x84)
-#define HDMI_WP_AUDIO_CTRL                     HDMI_WP_REG(0x88)
-#define HDMI_WP_AUDIO_DATA                     HDMI_WP_REG(0x8C)
+
+#define HDMI_WP_REVISION                       0x0
+#define HDMI_WP_SYSCONFIG                      0x10
+#define HDMI_WP_IRQSTATUS_RAW                  0x24
+#define HDMI_WP_IRQSTATUS                      0x28
+#define HDMI_WP_PWR_CTRL                       0x40
+#define HDMI_WP_IRQENABLE_SET                  0x2C
+#define HDMI_WP_VIDEO_CFG                      0x50
+#define HDMI_WP_VIDEO_SIZE                     0x60
+#define HDMI_WP_VIDEO_TIMING_H                 0x68
+#define HDMI_WP_VIDEO_TIMING_V                 0x6C
+#define HDMI_WP_WP_CLK                         0x70
+#define HDMI_WP_AUDIO_CFG                      0x80
+#define HDMI_WP_AUDIO_CFG2                     0x84
+#define HDMI_WP_AUDIO_CTRL                     0x88
+#define HDMI_WP_AUDIO_DATA                     0x8C
 
 /* HDMI IP Core System */
-#define HDMI_CORE_SYS_REG(idx)                 HDMI_REG(HDMI_CORE_SYS + idx)
-
-#define HDMI_CORE_SYS_VND_IDL                  HDMI_CORE_SYS_REG(0x0)
-#define HDMI_CORE_SYS_DEV_IDL                  HDMI_CORE_SYS_REG(0x8)
-#define HDMI_CORE_SYS_DEV_IDH                  HDMI_CORE_SYS_REG(0xC)
-#define HDMI_CORE_SYS_DEV_REV                  HDMI_CORE_SYS_REG(0x10)
-#define HDMI_CORE_SYS_SRST                     HDMI_CORE_SYS_REG(0x14)
-#define HDMI_CORE_CTRL1                        HDMI_CORE_SYS_REG(0x20)
-#define HDMI_CORE_SYS_SYS_STAT                 HDMI_CORE_SYS_REG(0x24)
-#define HDMI_CORE_SYS_VID_ACEN                 HDMI_CORE_SYS_REG(0x124)
-#define HDMI_CORE_SYS_VID_MODE                 HDMI_CORE_SYS_REG(0x128)
-#define HDMI_CORE_SYS_INTR_STATE               HDMI_CORE_SYS_REG(0x1C0)
-#define HDMI_CORE_SYS_INTR1                    HDMI_CORE_SYS_REG(0x1C4)
-#define HDMI_CORE_SYS_INTR2                    HDMI_CORE_SYS_REG(0x1C8)
-#define HDMI_CORE_SYS_INTR3                    HDMI_CORE_SYS_REG(0x1CC)
-#define HDMI_CORE_SYS_INTR4                    HDMI_CORE_SYS_REG(0x1D0)
-#define HDMI_CORE_SYS_UMASK1                   HDMI_CORE_SYS_REG(0x1D4)
-#define HDMI_CORE_SYS_TMDS_CTRL                HDMI_CORE_SYS_REG(0x208)
-#define HDMI_CORE_SYS_DE_DLY                   HDMI_CORE_SYS_REG(0xC8)
-#define HDMI_CORE_SYS_DE_CTRL                  HDMI_CORE_SYS_REG(0xCC)
-#define HDMI_CORE_SYS_DE_TOP                   HDMI_CORE_SYS_REG(0xD0)
-#define HDMI_CORE_SYS_DE_CNTL                  HDMI_CORE_SYS_REG(0xD8)
-#define HDMI_CORE_SYS_DE_CNTH                  HDMI_CORE_SYS_REG(0xDC)
-#define HDMI_CORE_SYS_DE_LINL                  HDMI_CORE_SYS_REG(0xE0)
-#define HDMI_CORE_SYS_DE_LINH_1                HDMI_CORE_SYS_REG(0xE4)
+
+#define HDMI_CORE_SYS_VND_IDL                  0x0
+#define HDMI_CORE_SYS_DEV_IDL                  0x8
+#define HDMI_CORE_SYS_DEV_IDH                  0xC
+#define HDMI_CORE_SYS_DEV_REV                  0x10
+#define HDMI_CORE_SYS_SRST                     0x14
+#define HDMI_CORE_CTRL1                                0x20
+#define HDMI_CORE_SYS_SYS_STAT                 0x24
+#define HDMI_CORE_SYS_VID_ACEN                 0x124
+#define HDMI_CORE_SYS_VID_MODE                 0x128
+#define HDMI_CORE_SYS_INTR_STATE               0x1C0
+#define HDMI_CORE_SYS_INTR1                    0x1C4
+#define HDMI_CORE_SYS_INTR2                    0x1C8
+#define HDMI_CORE_SYS_INTR3                    0x1CC
+#define HDMI_CORE_SYS_INTR4                    0x1D0
+#define HDMI_CORE_SYS_UMASK1                   0x1D4
+#define HDMI_CORE_SYS_TMDS_CTRL                        0x208
+#define HDMI_CORE_SYS_DE_DLY                   0xC8
+#define HDMI_CORE_SYS_DE_CTRL                  0xCC
+#define HDMI_CORE_SYS_DE_TOP                   0xD0
+#define HDMI_CORE_SYS_DE_CNTL                  0xD8
+#define HDMI_CORE_SYS_DE_CNTH                  0xDC
+#define HDMI_CORE_SYS_DE_LINL                  0xE0
+#define HDMI_CORE_SYS_DE_LINH_1                        0xE4
 #define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC        0x1
 #define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC        0x1
 #define HDMI_CORE_CTRL1_BSEL_24BITBUS          0x1
 #define HDMI_CORE_CTRL1_EDGE_RISINGEDGE        0x1
 
 /* HDMI DDC E-DID */
-#define HDMI_CORE_DDC_CMD                      HDMI_CORE_SYS_REG(0x3CC)
-#define HDMI_CORE_DDC_STATUS                   HDMI_CORE_SYS_REG(0x3C8)
-#define HDMI_CORE_DDC_ADDR                     HDMI_CORE_SYS_REG(0x3B4)
-#define HDMI_CORE_DDC_OFFSET                   HDMI_CORE_SYS_REG(0x3BC)
-#define HDMI_CORE_DDC_COUNT1                   HDMI_CORE_SYS_REG(0x3C0)
-#define HDMI_CORE_DDC_COUNT2                   HDMI_CORE_SYS_REG(0x3C4)
-#define HDMI_CORE_DDC_DATA                     HDMI_CORE_SYS_REG(0x3D0)
-#define HDMI_CORE_DDC_SEGM                     HDMI_CORE_SYS_REG(0x3B8)
+#define HDMI_CORE_DDC_CMD                      0x3CC
+#define HDMI_CORE_DDC_STATUS                   0x3C8
+#define HDMI_CORE_DDC_ADDR                     0x3B4
+#define HDMI_CORE_DDC_OFFSET                   0x3BC
+#define HDMI_CORE_DDC_COUNT1                   0x3C0
+#define HDMI_CORE_DDC_COUNT2                   0x3C4
+#define HDMI_CORE_DDC_DATA                     0x3D0
+#define HDMI_CORE_DDC_SEGM                     0x3B8
 
 /* HDMI IP Core Audio Video */
-#define HDMI_CORE_AV_REG(idx)                  HDMI_REG(HDMI_CORE_AV + idx)
-
-#define HDMI_CORE_AV_HDMI_CTRL                 HDMI_CORE_AV_REG(0xBC)
-#define HDMI_CORE_AV_DPD                       HDMI_CORE_AV_REG(0xF4)
-#define HDMI_CORE_AV_PB_CTRL1                  HDMI_CORE_AV_REG(0xF8)
-#define HDMI_CORE_AV_PB_CTRL2                  HDMI_CORE_AV_REG(0xFC)
-#define HDMI_CORE_AV_AVI_TYPE                  HDMI_CORE_AV_REG(0x100)
-#define HDMI_CORE_AV_AVI_VERS                  HDMI_CORE_AV_REG(0x104)
-#define HDMI_CORE_AV_AVI_LEN                   HDMI_CORE_AV_REG(0x108)
-#define HDMI_CORE_AV_AVI_CHSUM                 HDMI_CORE_AV_REG(0x10C)
-#define HDMI_CORE_AV_AVI_DBYTE(n)              HDMI_CORE_AV_REG(n * 4 + 0x110)
-#define HDMI_CORE_AV_AVI_DBYTE_NELEMS          HDMI_CORE_AV_REG(15)
-#define HDMI_CORE_AV_SPD_DBYTE                 HDMI_CORE_AV_REG(0x190)
-#define HDMI_CORE_AV_SPD_DBYTE_NELEMS          HDMI_CORE_AV_REG(27)
-#define HDMI_CORE_AV_AUD_DBYTE(n)              HDMI_CORE_AV_REG(n * 4 + 0x210)
-#define HDMI_CORE_AV_AUD_DBYTE_NELEMS          HDMI_CORE_AV_REG(10)
-#define HDMI_CORE_AV_MPEG_DBYTE                HDMI_CORE_AV_REG(0x290)
-#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS         HDMI_CORE_AV_REG(27)
-#define HDMI_CORE_AV_GEN_DBYTE                 HDMI_CORE_AV_REG(0x300)
-#define HDMI_CORE_AV_GEN_DBYTE_NELEMS          HDMI_CORE_AV_REG(31)
-#define HDMI_CORE_AV_GEN2_DBYTE                HDMI_CORE_AV_REG(0x380)
-#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS         HDMI_CORE_AV_REG(31)
-#define HDMI_CORE_AV_ACR_CTRL                  HDMI_CORE_AV_REG(0x4)
-#define HDMI_CORE_AV_FREQ_SVAL                 HDMI_CORE_AV_REG(0x8)
-#define HDMI_CORE_AV_N_SVAL1                   HDMI_CORE_AV_REG(0xC)
-#define HDMI_CORE_AV_N_SVAL2                   HDMI_CORE_AV_REG(0x10)
-#define HDMI_CORE_AV_N_SVAL3                   HDMI_CORE_AV_REG(0x14)
-#define HDMI_CORE_AV_CTS_SVAL1                 HDMI_CORE_AV_REG(0x18)
-#define HDMI_CORE_AV_CTS_SVAL2                 HDMI_CORE_AV_REG(0x1C)
-#define HDMI_CORE_AV_CTS_SVAL3                 HDMI_CORE_AV_REG(0x20)
-#define HDMI_CORE_AV_CTS_HVAL1                 HDMI_CORE_AV_REG(0x24)
-#define HDMI_CORE_AV_CTS_HVAL2                 HDMI_CORE_AV_REG(0x28)
-#define HDMI_CORE_AV_CTS_HVAL3                 HDMI_CORE_AV_REG(0x2C)
-#define HDMI_CORE_AV_AUD_MODE                  HDMI_CORE_AV_REG(0x50)
-#define HDMI_CORE_AV_SPDIF_CTRL                HDMI_CORE_AV_REG(0x54)
-#define HDMI_CORE_AV_HW_SPDIF_FS               HDMI_CORE_AV_REG(0x60)
-#define HDMI_CORE_AV_SWAP_I2S                  HDMI_CORE_AV_REG(0x64)
-#define HDMI_CORE_AV_SPDIF_ERTH                HDMI_CORE_AV_REG(0x6C)
-#define HDMI_CORE_AV_I2S_IN_MAP                HDMI_CORE_AV_REG(0x70)
-#define HDMI_CORE_AV_I2S_IN_CTRL               HDMI_CORE_AV_REG(0x74)
-#define HDMI_CORE_AV_I2S_CHST0                 HDMI_CORE_AV_REG(0x78)
-#define HDMI_CORE_AV_I2S_CHST1                 HDMI_CORE_AV_REG(0x7C)
-#define HDMI_CORE_AV_I2S_CHST2                 HDMI_CORE_AV_REG(0x80)
-#define HDMI_CORE_AV_I2S_CHST4                 HDMI_CORE_AV_REG(0x84)
-#define HDMI_CORE_AV_I2S_CHST5                 HDMI_CORE_AV_REG(0x88)
-#define HDMI_CORE_AV_ASRC                      HDMI_CORE_AV_REG(0x8C)
-#define HDMI_CORE_AV_I2S_IN_LEN                HDMI_CORE_AV_REG(0x90)
-#define HDMI_CORE_AV_HDMI_CTRL                 HDMI_CORE_AV_REG(0xBC)
-#define HDMI_CORE_AV_AUDO_TXSTAT               HDMI_CORE_AV_REG(0xC0)
-#define HDMI_CORE_AV_AUD_PAR_BUSCLK_1          HDMI_CORE_AV_REG(0xCC)
-#define HDMI_CORE_AV_AUD_PAR_BUSCLK_2          HDMI_CORE_AV_REG(0xD0)
-#define HDMI_CORE_AV_AUD_PAR_BUSCLK_3          HDMI_CORE_AV_REG(0xD4)
-#define HDMI_CORE_AV_TEST_TXCTRL               HDMI_CORE_AV_REG(0xF0)
-#define HDMI_CORE_AV_DPD                       HDMI_CORE_AV_REG(0xF4)
-#define HDMI_CORE_AV_PB_CTRL1                  HDMI_CORE_AV_REG(0xF8)
-#define HDMI_CORE_AV_PB_CTRL2                  HDMI_CORE_AV_REG(0xFC)
-#define HDMI_CORE_AV_AVI_TYPE                  HDMI_CORE_AV_REG(0x100)
-#define HDMI_CORE_AV_AVI_VERS                  HDMI_CORE_AV_REG(0x104)
-#define HDMI_CORE_AV_AVI_LEN                   HDMI_CORE_AV_REG(0x108)
-#define HDMI_CORE_AV_AVI_CHSUM                 HDMI_CORE_AV_REG(0x10C)
-#define HDMI_CORE_AV_SPD_TYPE                  HDMI_CORE_AV_REG(0x180)
-#define HDMI_CORE_AV_SPD_VERS                  HDMI_CORE_AV_REG(0x184)
-#define HDMI_CORE_AV_SPD_LEN                   HDMI_CORE_AV_REG(0x188)
-#define HDMI_CORE_AV_SPD_CHSUM                 HDMI_CORE_AV_REG(0x18C)
-#define HDMI_CORE_AV_AUDIO_TYPE                HDMI_CORE_AV_REG(0x200)
-#define HDMI_CORE_AV_AUDIO_VERS                HDMI_CORE_AV_REG(0x204)
-#define HDMI_CORE_AV_AUDIO_LEN                 HDMI_CORE_AV_REG(0x208)
-#define HDMI_CORE_AV_AUDIO_CHSUM               HDMI_CORE_AV_REG(0x20C)
-#define HDMI_CORE_AV_MPEG_TYPE                 HDMI_CORE_AV_REG(0x280)
-#define HDMI_CORE_AV_MPEG_VERS                 HDMI_CORE_AV_REG(0x284)
-#define HDMI_CORE_AV_MPEG_LEN                  HDMI_CORE_AV_REG(0x288)
-#define HDMI_CORE_AV_MPEG_CHSUM                HDMI_CORE_AV_REG(0x28C)
-#define HDMI_CORE_AV_CP_BYTE1                  HDMI_CORE_AV_REG(0x37C)
-#define HDMI_CORE_AV_CEC_ADDR_ID               HDMI_CORE_AV_REG(0x3FC)
+
+#define HDMI_CORE_AV_HDMI_CTRL                 0xBC
+#define HDMI_CORE_AV_DPD                       0xF4
+#define HDMI_CORE_AV_PB_CTRL1                  0xF8
+#define HDMI_CORE_AV_PB_CTRL2                  0xFC
+#define HDMI_CORE_AV_AVI_TYPE                  0x100
+#define HDMI_CORE_AV_AVI_VERS                  0x104
+#define HDMI_CORE_AV_AVI_LEN                   0x108
+#define HDMI_CORE_AV_AVI_CHSUM                 0x10C
+#define HDMI_CORE_AV_AVI_DBYTE(n)              (n * 4 + 0x110)
+#define HDMI_CORE_AV_AVI_DBYTE_NELEMS          15
+#define HDMI_CORE_AV_SPD_DBYTE(n)              (n * 4 + 0x190)
+#define HDMI_CORE_AV_SPD_DBYTE_NELEMS          27
+#define HDMI_CORE_AV_AUD_DBYTE(n)              (n * 4 + 0x210)
+#define HDMI_CORE_AV_AUD_DBYTE_NELEMS          10
+#define HDMI_CORE_AV_MPEG_DBYTE(n)             (n * 4 + 0x290)
+#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS         27
+#define HDMI_CORE_AV_GEN_DBYTE(n)              (n * 4 + 0x300)
+#define HDMI_CORE_AV_GEN_DBYTE_NELEMS          31
+#define HDMI_CORE_AV_GEN2_DBYTE(n)             (n * 4 + 0x380)
+#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS         31
+#define HDMI_CORE_AV_ACR_CTRL                  0x4
+#define HDMI_CORE_AV_FREQ_SVAL                 0x8
+#define HDMI_CORE_AV_N_SVAL1                   0xC
+#define HDMI_CORE_AV_N_SVAL2                   0x10
+#define HDMI_CORE_AV_N_SVAL3                   0x14
+#define HDMI_CORE_AV_CTS_SVAL1                 0x18
+#define HDMI_CORE_AV_CTS_SVAL2                 0x1C
+#define HDMI_CORE_AV_CTS_SVAL3                 0x20
+#define HDMI_CORE_AV_CTS_HVAL1                 0x24
+#define HDMI_CORE_AV_CTS_HVAL2                 0x28
+#define HDMI_CORE_AV_CTS_HVAL3                 0x2C
+#define HDMI_CORE_AV_AUD_MODE                  0x50
+#define HDMI_CORE_AV_SPDIF_CTRL                        0x54
+#define HDMI_CORE_AV_HW_SPDIF_FS               0x60
+#define HDMI_CORE_AV_SWAP_I2S                  0x64
+#define HDMI_CORE_AV_SPDIF_ERTH                        0x6C
+#define HDMI_CORE_AV_I2S_IN_MAP                        0x70
+#define HDMI_CORE_AV_I2S_IN_CTRL               0x74
+#define HDMI_CORE_AV_I2S_CHST0                 0x78
+#define HDMI_CORE_AV_I2S_CHST1                 0x7C
+#define HDMI_CORE_AV_I2S_CHST2                 0x80
+#define HDMI_CORE_AV_I2S_CHST4                 0x84
+#define HDMI_CORE_AV_I2S_CHST5                 0x88
+#define HDMI_CORE_AV_ASRC                      0x8C
+#define HDMI_CORE_AV_I2S_IN_LEN                        0x90
+#define HDMI_CORE_AV_HDMI_CTRL                 0xBC
+#define HDMI_CORE_AV_AUDO_TXSTAT               0xC0
+#define HDMI_CORE_AV_AUD_PAR_BUSCLK_1          0xCC
+#define HDMI_CORE_AV_AUD_PAR_BUSCLK_2          0xD0
+#define HDMI_CORE_AV_AUD_PAR_BUSCLK_3          0xD4
+#define HDMI_CORE_AV_TEST_TXCTRL               0xF0
+#define HDMI_CORE_AV_DPD                       0xF4
+#define HDMI_CORE_AV_PB_CTRL1                  0xF8
+#define HDMI_CORE_AV_PB_CTRL2                  0xFC
+#define HDMI_CORE_AV_AVI_TYPE                  0x100
+#define HDMI_CORE_AV_AVI_VERS                  0x104
+#define HDMI_CORE_AV_AVI_LEN                   0x108
+#define HDMI_CORE_AV_AVI_CHSUM                 0x10C
+#define HDMI_CORE_AV_SPD_TYPE                  0x180
+#define HDMI_CORE_AV_SPD_VERS                  0x184
+#define HDMI_CORE_AV_SPD_LEN                   0x188
+#define HDMI_CORE_AV_SPD_CHSUM                 0x18C
+#define HDMI_CORE_AV_AUDIO_TYPE                        0x200
+#define HDMI_CORE_AV_AUDIO_VERS                        0x204
+#define HDMI_CORE_AV_AUDIO_LEN                 0x208
+#define HDMI_CORE_AV_AUDIO_CHSUM               0x20C
+#define HDMI_CORE_AV_MPEG_TYPE                 0x280
+#define HDMI_CORE_AV_MPEG_VERS                 0x284
+#define HDMI_CORE_AV_MPEG_LEN                  0x288
+#define HDMI_CORE_AV_MPEG_CHSUM                        0x28C
+#define HDMI_CORE_AV_CP_BYTE1                  0x37C
+#define HDMI_CORE_AV_CEC_ADDR_ID               0x3FC
 #define HDMI_CORE_AV_SPD_DBYTE_ELSIZE          0x4
 #define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE         0x4
 #define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE         0x4
 #define HDMI_CORE_AV_GEN_DBYTE_ELSIZE          0x4
 
 /* PLL */
-#define HDMI_PLL_REG(idx)                      HDMI_REG(HDMI_PLLCTRL + idx)
 
-#define PLLCTRL_PLL_CONTROL                    HDMI_PLL_REG(0x0)
-#define PLLCTRL_PLL_STATUS                     HDMI_PLL_REG(0x4)
-#define PLLCTRL_PLL_GO                         HDMI_PLL_REG(0x8)
-#define PLLCTRL_CFG1                           HDMI_PLL_REG(0xC)
-#define PLLCTRL_CFG2                           HDMI_PLL_REG(0x10)
-#define PLLCTRL_CFG3                           HDMI_PLL_REG(0x14)
-#define PLLCTRL_CFG4                           HDMI_PLL_REG(0x20)
+#define PLLCTRL_PLL_CONTROL                    0x0
+#define PLLCTRL_PLL_STATUS                     0x4
+#define PLLCTRL_PLL_GO                         0x8
+#define PLLCTRL_CFG1                           0xC
+#define PLLCTRL_CFG2                           0x10
+#define PLLCTRL_CFG3                           0x14
+#define PLLCTRL_CFG4                           0x20
 
 /* HDMI PHY */
-#define HDMI_PHY_REG(idx)                      HDMI_REG(HDMI_PHY + idx)
-
-#define HDMI_TXPHY_TX_CTRL                     HDMI_PHY_REG(0x0)
-#define HDMI_TXPHY_DIGITAL_CTRL                HDMI_PHY_REG(0x4)
-#define HDMI_TXPHY_POWER_CTRL                  HDMI_PHY_REG(0x8)
-#define HDMI_TXPHY_PAD_CFG_CTRL                HDMI_PHY_REG(0xC)
-
-/* HDMI EDID Length  */
-#define HDMI_EDID_MAX_LENGTH                   256
-#define EDID_TIMING_DESCRIPTOR_SIZE            0x12
-#define EDID_DESCRIPTOR_BLOCK0_ADDRESS         0x36
-#define EDID_DESCRIPTOR_BLOCK1_ADDRESS         0x80
-#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR     4
-#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR     4
 
-#define OMAP_HDMI_TIMINGS_NB                   34
+#define HDMI_TXPHY_TX_CTRL                     0x0
+#define HDMI_TXPHY_DIGITAL_CTRL                        0x4
+#define HDMI_TXPHY_POWER_CTRL                  0x8
+#define HDMI_TXPHY_PAD_CFG_CTRL                        0xC
 
-#define REG_FLD_MOD(idx, val, start, end) \
-       hdmi_write_reg(idx, FLD_MOD(hdmi_read_reg(idx), val, start, end))
-#define REG_GET(idx, start, end) \
-       FLD_GET(hdmi_read_reg(idx), start, end)
-
-/* HDMI timing structure */
-struct hdmi_timings {
-       struct omap_video_timings timings;
-       int vsync_pol;
-       int hsync_pol;
-};
+#define REG_FLD_MOD(base, idx, val, start, end) \
+       hdmi_write_reg(base, idx, FLD_MOD(hdmi_read_reg(base, idx),\
+                                                       val, start, end))
+#define REG_GET(base, idx, start, end) \
+       FLD_GET(hdmi_read_reg(base, idx), start, end)
 
 enum hdmi_phy_pwr {
        HDMI_PHYPWRCMD_OFF = 0,
@@ -221,20 +196,6 @@ enum hdmi_phy_pwr {
        HDMI_PHYPWRCMD_TXON = 2
 };
 
-enum hdmi_pll_pwr {
-       HDMI_PLLPWRCMD_ALLOFF = 0,
-       HDMI_PLLPWRCMD_PLLONLY = 1,
-       HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2,
-       HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3
-};
-
-enum hdmi_clk_refsel {
-       HDMI_REFSEL_PCLK = 0,
-       HDMI_REFSEL_REF1 = 1,
-       HDMI_REFSEL_REF2 = 2,
-       HDMI_REFSEL_SYSCLK = 3
-};
-
 enum hdmi_core_inputbus_width {
        HDMI_INPUT_8BIT = 0,
        HDMI_INPUT_10BIT = 1,
@@ -263,11 +224,6 @@ enum hdmi_core_packet_mode {
        HDMI_PACKETMODE48BITPERPIXEL = 7
 };
 
-enum hdmi_core_hdmi_dvi {
-       HDMI_DVI = 0,
-       HDMI_HDMI = 1
-};
-
 enum hdmi_core_tclkselclkmult {
        HDMI_FPLL05IDCK = 0,
        HDMI_FPLL10IDCK = 1,
@@ -495,40 +451,40 @@ struct hdmi_core_video_config {
  * details about infoframe databytes
  */
 struct hdmi_core_infoframe_avi {
+       /* Y0, Y1 rgb,yCbCr */
        u8      db1_format;
-               /* Y0, Y1 rgb,yCbCr */
+       /* A0  Active information Present */
        u8      db1_active_info;
-               /* A0  Active information Present */
+       /* B0, B1 Bar info data valid */
        u8      db1_bar_info_dv;
-               /* B0, B1 Bar info data valid */
+       /* S0, S1 scan information */
        u8      db1_scan_info;
-               /* S0, S1 scan information */
+       /* C0, C1 colorimetry */
        u8      db2_colorimetry;
-               /* C0, C1 colorimetry */
+       /* M0, M1 Aspect ratio (4:3, 16:9) */
        u8      db2_aspect_ratio;
-               /* M0, M1 Aspect ratio (4:3, 16:9) */
+       /* R0...R3 Active format aspect ratio */
        u8      db2_active_fmt_ar;
-               /* R0...R3 Active format aspect ratio */
+       /* ITC IT content. */
        u8      db3_itc;
-               /* ITC IT content. */
+       /* EC0, EC1, EC2 Extended colorimetry */
        u8      db3_ec;
-               /* EC0, EC1, EC2 Extended colorimetry */
+       /* Q1, Q0 Quantization range */
        u8      db3_q_range;
-               /* Q1, Q0 Quantization range */
+       /* SC1, SC0 Non-uniform picture scaling */
        u8      db3_nup_scaling;
-               /* SC1, SC0 Non-uniform picture scaling */
+       /* VIC0..6 Video format identification */
        u8      db4_videocode;
-               /* VIC0..6 Video format identification */
+       /* PR0..PR3 Pixel repetition factor */
        u8      db5_pixel_repeat;
-               /* PR0..PR3 Pixel repetition factor */
+       /* Line number end of top bar */
        u16     db6_7_line_eoftop;
-               /* Line number end of top bar */
+       /* Line number start of bottom bar */
        u16     db8_9_line_sofbottom;
-               /* Line number start of bottom bar */
+       /* Pixel number end of left bar */
        u16     db10_11_pixel_eofleft;
-               /* Pixel number end of left bar */
+       /* Pixel number start of right bar */
        u16     db12_13_pixel_sofright;
-               /* Pixel number start of right bar */
 };
 /*
  * Refer to section 8.2 in HDMI 1.3 specification for
@@ -568,17 +524,6 @@ struct hdmi_video_interface {
        int     tm;     /* Timing mode */
 };
 
-struct hdmi_cm {
-       int     code;
-       int     mode;
-};
-
-struct hdmi_config {
-       struct hdmi_timings timings;
-       u16     interlace;
-       struct hdmi_cm cm;
-};
-
 struct hdmi_audio_format {
        enum hdmi_stereo_channels               stereo_channels;
        u8                                      active_chnnls_msk;
@@ -628,4 +573,21 @@ struct hdmi_core_audio_config {
        bool                                    en_parallel_aud_input;
        bool                                    en_spdif;
 };
+
+#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
+       defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
+int hdmi_audio_trigger(struct hdmi_ip_data *ip_data,
+                               struct snd_pcm_substream *substream, int cmd,
+                               struct snd_soc_dai *dai);
+int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data,
+                               u32 sample_freq, u32 *n, u32 *cts);
+void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
+               struct hdmi_core_infoframe_audio *info_aud);
+void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
+                                       struct hdmi_core_audio_config *cfg);
+void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data,
+                                       struct hdmi_audio_dma *aud_dma);
+void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data,
+                                       struct hdmi_audio_format *aud_fmt);
+#endif
 #endif
index 173c664..7533458 100644 (file)
@@ -295,7 +295,6 @@ static struct {
        u32 wss_data;
        struct regulator *vdda_dac_reg;
 
-       struct clk      *tv_clk;
        struct clk      *tv_dac_clk;
 } venc;
 
@@ -464,9 +463,11 @@ static void venc_power_off(struct omap_dss_device *dssdev)
        regulator_disable(venc.vdda_dac_reg);
 }
 
-
-
-
+unsigned long venc_get_pixel_clock(void)
+{
+       /* VENC Pixel Clock in Mhz */
+       return 13500000;
+}
 
 /* driver */
 static int venc_panel_probe(struct omap_dss_device *dssdev)
@@ -732,22 +733,10 @@ static int venc_get_clocks(struct platform_device *pdev)
 {
        struct clk *clk;
 
-       clk = clk_get(&pdev->dev, "fck");
-       if (IS_ERR(clk)) {
-               DSSERR("can't get fck\n");
-               return PTR_ERR(clk);
-       }
-
-       venc.tv_clk = clk;
-
        if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) {
-               if (cpu_is_omap34xx() || cpu_is_omap3630())
-                       clk = clk_get(&pdev->dev, "dss_96m_fck");
-               else
-                       clk = clk_get(&pdev->dev, "tv_dac_clk");
+               clk = clk_get(&pdev->dev, "tv_dac_clk");
                if (IS_ERR(clk)) {
                        DSSERR("can't get tv_dac_clk\n");
-                       clk_put(venc.tv_clk);
                        return PTR_ERR(clk);
                }
        } else {
@@ -761,8 +750,6 @@ static int venc_get_clocks(struct platform_device *pdev)
 
 static void venc_put_clocks(void)
 {
-       if (venc.tv_clk)
-               clk_put(venc.tv_clk);
        if (venc.tv_dac_clk)
                clk_put(venc.tv_dac_clk);
 }
@@ -838,7 +825,6 @@ static int venc_runtime_suspend(struct device *dev)
 {
        if (venc.tv_dac_clk)
                clk_disable(venc.tv_dac_clk);
-       clk_disable(venc.tv_clk);
 
        dispc_runtime_put();
        dss_runtime_put();
@@ -858,7 +844,6 @@ static int venc_runtime_resume(struct device *dev)
        if (r < 0)
                goto err_get_dispc;
 
-       clk_enable(venc.tv_clk);
        if (venc.tv_dac_clk)
                clk_enable(venc.tv_dac_clk);
 
index aa33386..83d3fe7 100644 (file)
@@ -1,5 +1,5 @@
 menuconfig FB_OMAP2
-        tristate "OMAP2+ frame buffer support (EXPERIMENTAL)"
+        tristate "OMAP2+ frame buffer support"
         depends on FB && OMAP2_DSS
 
        select OMAP2_VRAM
index 602b71a..70aa47d 100644 (file)
@@ -808,19 +808,15 @@ static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var,
 static void omapfb_calc_addr(const struct omapfb_info *ofbi,
                             const struct fb_var_screeninfo *var,
                             const struct fb_fix_screeninfo *fix,
-                            int rotation, u32 *paddr, void __iomem **vaddr)
+                            int rotation, u32 *paddr)
 {
        u32 data_start_p;
-       void __iomem *data_start_v;
        int offset;
 
-       if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+       if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
                data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
-               data_start_v = NULL;
-       } else {
+       else
                data_start_p = omapfb_get_region_paddr(ofbi);
-               data_start_v = omapfb_get_region_vaddr(ofbi);
-       }
 
        if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
                offset = calc_rotation_offset_vrfb(var, fix, rotation);
@@ -828,16 +824,14 @@ static void omapfb_calc_addr(const struct omapfb_info *ofbi,
                offset = calc_rotation_offset_dma(var, fix, rotation);
 
        data_start_p += offset;
-       data_start_v += offset;
 
        if (offset)
                DBG("offset %d, %d = %d\n",
                    var->xoffset, var->yoffset, offset);
 
-       DBG("paddr %x, vaddr %p\n", data_start_p, data_start_v);
+       DBG("paddr %x\n", data_start_p);
 
        *paddr = data_start_p;
-       *vaddr = data_start_v;
 }
 
 /* setup overlay according to the fb */
@@ -850,7 +844,6 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
        struct fb_fix_screeninfo *fix = &fbi->fix;
        enum omap_color_mode mode = 0;
        u32 data_start_p = 0;
-       void __iomem *data_start_v = NULL;
        struct omap_overlay_info info;
        int xres, yres;
        int screen_width;
@@ -880,8 +873,7 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
        }
 
        if (ofbi->region->size)
-               omapfb_calc_addr(ofbi, var, fix, rotation,
-                                &data_start_p, &data_start_v);
+               omapfb_calc_addr(ofbi, var, fix, rotation, &data_start_p);
 
        r = fb_mode_to_dss_mode(var, &mode);
        if (r) {
@@ -910,7 +902,6 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
                mirror = ofbi->mirror;
 
        info.paddr = data_start_p;
-       info.vaddr = data_start_v;
        info.screen_width = screen_width;
        info.width = xres;
        info.height = yres;
@@ -2276,6 +2267,87 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
        return r;
 }
 
+static void fb_videomode_to_omap_timings(struct fb_videomode *m,
+               struct omap_video_timings *t)
+{
+       t->x_res = m->xres;
+       t->y_res = m->yres;
+       t->pixel_clock = PICOS2KHZ(m->pixclock);
+       t->hsw = m->hsync_len;
+       t->hfp = m->right_margin;
+       t->hbp = m->left_margin;
+       t->vsw = m->vsync_len;
+       t->vfp = m->lower_margin;
+       t->vbp = m->upper_margin;
+}
+
+static int omapfb_find_best_mode(struct omap_dss_device *display,
+               struct omap_video_timings *timings)
+{
+       struct fb_monspecs *specs;
+       u8 *edid;
+       int r, i, best_xres, best_idx, len;
+
+       if (!display->driver->read_edid)
+               return -ENODEV;
+
+       len = 0x80 * 2;
+       edid = kmalloc(len, GFP_KERNEL);
+
+       r = display->driver->read_edid(display, edid, len);
+       if (r < 0)
+               goto err1;
+
+       specs = kzalloc(sizeof(*specs), GFP_KERNEL);
+
+       fb_edid_to_monspecs(edid, specs);
+
+       if (edid[126] > 0)
+               fb_edid_add_monspecs(edid + 0x80, specs);
+
+       best_xres = 0;
+       best_idx = -1;
+
+       for (i = 0; i < specs->modedb_len; ++i) {
+               struct fb_videomode *m;
+               struct omap_video_timings t;
+
+               m = &specs->modedb[i];
+
+               if (m->pixclock == 0)
+                       continue;
+
+               /* skip repeated pixel modes */
+               if (m->xres == 2880 || m->xres == 1440)
+                       continue;
+
+               fb_videomode_to_omap_timings(m, &t);
+
+               r = display->driver->check_timings(display, &t);
+               if (r == 0 && best_xres < m->xres) {
+                       best_xres = m->xres;
+                       best_idx = i;
+               }
+       }
+
+       if (best_xres == 0) {
+               r = -ENOENT;
+               goto err2;
+       }
+
+       fb_videomode_to_omap_timings(&specs->modedb[best_idx], timings);
+
+       r = 0;
+
+err2:
+       fb_destroy_modedb(specs->modedb);
+       kfree(specs);
+err1:
+       kfree(edid);
+
+       return r;
+}
+
 static int omapfb_init_display(struct omapfb2_device *fbdev,
                struct omap_dss_device *dssdev)
 {
@@ -2373,8 +2445,10 @@ static int omapfb_probe(struct platform_device *pdev)
                omap_dss_get_device(dssdev);
 
                if (!dssdev->driver) {
-                       dev_err(&pdev->dev, "no driver for display\n");
-                       r = -ENODEV;
+                       dev_warn(&pdev->dev, "no driver for display: %s\n",
+                               dssdev->name);
+                       omap_dss_put_device(dssdev);
+                       continue;
                }
 
                d = &fbdev->displays[fbdev->num_displays++];
@@ -2402,9 +2476,27 @@ static int omapfb_probe(struct platform_device *pdev)
        for (i = 0; i < fbdev->num_managers; i++)
                fbdev->managers[i] = omap_dss_get_overlay_manager(i);
 
+       /* gfx overlay should be the default one. find a display
+        * connected to that, and use it as default display */
+       ovl = omap_dss_get_overlay(0);
+       if (ovl->manager && ovl->manager->device) {
+               def_display = ovl->manager->device;
+       } else {
+               dev_warn(&pdev->dev, "cannot find default display\n");
+               def_display = NULL;
+       }
+
        if (def_mode && strlen(def_mode) > 0) {
                if (omapfb_parse_def_modes(fbdev))
                        dev_warn(&pdev->dev, "cannot parse default modes\n");
+       } else if (def_display && def_display->driver->set_timings &&
+                       def_display->driver->check_timings) {
+               struct omap_video_timings t;
+
+               r = omapfb_find_best_mode(def_display, &t);
+
+               if (r == 0)
+                       def_display->driver->set_timings(def_display, &t);
        }
 
        r = omapfb_create_framebuffers(fbdev);
@@ -2421,16 +2513,6 @@ static int omapfb_probe(struct platform_device *pdev)
 
        DBG("mgr->apply'ed\n");
 
-       /* gfx overlay should be the default one. find a display
-        * connected to that, and use it as default display */
-       ovl = omap_dss_get_overlay(0);
-       if (ovl->manager && ovl->manager->device) {
-               def_display = ovl->manager->device;
-       } else {
-               dev_warn(&pdev->dev, "cannot find default display\n");
-               def_display = NULL;
-       }
-
        if (def_display) {
                r = omapfb_init_display(fbdev, def_display);
                if (r) {
index 153bf1a..1694d51 100644 (file)
@@ -104,16 +104,14 @@ static ssize_t store_mirror(struct device *dev,
 {
        struct fb_info *fbi = dev_get_drvdata(dev);
        struct omapfb_info *ofbi = FB2OFB(fbi);
-       int mirror;
+       bool mirror;
        int r;
        struct fb_var_screeninfo new_var;
 
-       r = kstrtoint(buf, 0, &mirror);
+       r = strtobool(buf, &mirror);
        if (r)
                return r;
 
-       mirror = !!mirror;
-
        if (!lock_fb_info(fbi))
                return -ENODEV;
 
index f27ae16..ae3caa6 100644 (file)
@@ -490,7 +490,7 @@ static int platinum_var_to_par(struct fb_var_screeninfo *var,
 
 
 /* 
- * Parse user speficied options (`video=platinumfb:')
+ * Parse user specified options (`video=platinumfb:')
  */
 static int __init platinumfb_setup(char *options)
 {
@@ -683,7 +683,7 @@ static struct platform_driver platinum_driver =
                .of_match_table = platinumfb_match,
        },
        .probe          = platinumfb_probe,
-       .remove         = platinumfb_remove,
+       .remove         = __devexit_p(platinumfb_remove),
 };
 
 static int __init platinumfb_init(void)
index 27f93aa..dc7bfa9 100644 (file)
@@ -973,8 +973,8 @@ static int pm2fb_pan_display(struct fb_var_screeninfo *var,
 {
        struct pm2fb_par *p = info->par;
        u32 base;
-       u32 depth = (var->bits_per_pixel + 7) & ~7;
-       u32 xres = (var->xres + 31) & ~31;
+       u32 depth = (info->var.bits_per_pixel + 7) & ~7;
+       u32 xres = (info->var.xres + 31) & ~31;
 
        depth = (depth > 32) ? 32 : depth;
        base = to3264(var->yoffset * xres + var->xoffset, depth, 1);
@@ -1773,7 +1773,7 @@ MODULE_DEVICE_TABLE(pci, pm2fb_id_table);
 
 #ifndef MODULE
 /**
- * Parse user speficied options.
+ * Parse user specified options.
  *
  * This is, comma-separated options following `video=pm2fb:'.
  */
index 6666f45..6632ee5 100644 (file)
@@ -1147,9 +1147,9 @@ static int pm3fb_pan_display(struct fb_var_screeninfo *var,
                                 struct fb_info *info)
 {
        struct pm3_par *par = info->par;
-       const u32 xres = (var->xres + 31) & ~31;
+       const u32 xres = (info->var.xres + 31) & ~31;
 
-       par->base = pm3fb_shift_bpp(var->bits_per_pixel,
+       par->base = pm3fb_shift_bpp(info->var.bits_per_pixel,
                                        (var->yoffset * xres)
                                        + var->xoffset);
        PM3_WAIT(par, 1);
@@ -1525,7 +1525,7 @@ static int __init pm3fb_setup(char *options)
 {
        char *this_opt;
 
-       /* Parse user speficied options (`video=pm3fb:') */
+       /* Parse user specified options (`video=pm3fb:') */
        if (!options || !*options)
                return 0;
 
index 65560a1..213fbbc 100644 (file)
@@ -1082,7 +1082,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
        }
 
        retval = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt,
-                            IRQF_DISABLED, DEVICE_NAME, &dev->core);
+                            0, DEVICE_NAME, &dev->core);
        if (retval) {
                dev_err(&dev->core, "%s: request_irq failed %d\n", __func__,
                        retval);
index 0283c70..1ed8b36 100644 (file)
@@ -31,8 +31,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/version.h>
-
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/miscdevice.h>
@@ -678,7 +676,7 @@ pxa3xx_gcu_probe(struct platform_device *dev)
        }
 
        ret = request_irq(irq, pxa3xx_gcu_handle_irq,
-                         IRQF_DISABLED, DRV_NAME, priv);
+                         0, DRV_NAME, priv);
        if (ret) {
                dev_err(&dev->dev, "request_irq failed\n");
                ret = -EBUSY;
index 0f4e8c9..e89778f 100644 (file)
@@ -2191,7 +2191,7 @@ static int __devinit pxafb_probe(struct platform_device *dev)
                goto failed_free_mem;
        }
 
-       ret = request_irq(irq, pxafb_handle_irq, IRQF_DISABLED, "LCD", fbi);
+       ret = request_irq(irq, pxafb_handle_irq, 0, "LCD", fbi);
        if (ret) {
                dev_err(&dev->dev, "request_irq failed: %d\n", ret);
                ret = -EBUSY;
index 4aecf21..0753b1c 100644 (file)
@@ -81,6 +81,7 @@ struct s3c_fb;
  * @palette: Address of palette memory, or 0 if none.
  * @has_prtcon: Set if has PRTCON register.
  * @has_shadowcon: Set if has SHADOWCON register.
+ * @has_clksel: Set if VIDCON0 register has CLKSEL bit.
  */
 struct s3c_fb_variant {
        unsigned int    is_2443:1;
@@ -98,6 +99,7 @@ struct s3c_fb_variant {
 
        unsigned int    has_prtcon:1;
        unsigned int    has_shadowcon:1;
+       unsigned int    has_clksel:1;
 };
 
 /**
@@ -186,6 +188,7 @@ struct s3c_fb_vsync {
  * @dev: The device that we bound to, for printing, etc.
  * @regs_res: The resource we claimed for the IO registers.
  * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk.
+ * @lcd_clk: The clk (sclk) feeding pixclk.
  * @regs: The mapped hardware registers.
  * @variant: Variant information for this hardware.
  * @enabled: A bitmask of enabled hardware windows.
@@ -200,6 +203,7 @@ struct s3c_fb {
        struct device           *dev;
        struct resource         *regs_res;
        struct clk              *bus_clk;
+       struct clk              *lcd_clk;
        void __iomem            *regs;
        struct s3c_fb_variant    variant;
 
@@ -336,10 +340,15 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
  */
 static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk)
 {
-       unsigned long clk = clk_get_rate(sfb->bus_clk);
+       unsigned long clk;
        unsigned long long tmp;
        unsigned int result;
 
+       if (sfb->variant.has_clksel)
+               clk = clk_get_rate(sfb->bus_clk);
+       else
+               clk = clk_get_rate(sfb->lcd_clk);
+
        tmp = (unsigned long long)clk;
        tmp *= pixclk;
 
@@ -883,7 +892,7 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var,
                }
        }
        /* Offset in bytes to the end of the displayed area */
-       end_boff = start_boff + var->yres * info->fix.line_length;
+       end_boff = start_boff + info->var.yres * info->fix.line_length;
 
        /* Temporarily turn off per-vsync update from shadow registers until
         * both start and end addresses are updated to prevent corruption */
@@ -1354,13 +1363,24 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
 
        clk_enable(sfb->bus_clk);
 
+       if (!sfb->variant.has_clksel) {
+               sfb->lcd_clk = clk_get(dev, "sclk_fimd");
+               if (IS_ERR(sfb->lcd_clk)) {
+                       dev_err(dev, "failed to get lcd clock\n");
+                       ret = PTR_ERR(sfb->lcd_clk);
+                       goto err_bus_clk;
+               }
+
+               clk_enable(sfb->lcd_clk);
+       }
+
        pm_runtime_enable(sfb->dev);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
                dev_err(dev, "failed to find registers\n");
                ret = -ENOENT;
-               goto err_clk;
+               goto err_lcd_clk;
        }
 
        sfb->regs_res = request_mem_region(res->start, resource_size(res),
@@ -1368,7 +1388,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
        if (!sfb->regs_res) {
                dev_err(dev, "failed to claim register region\n");
                ret = -ENOENT;
-               goto err_clk;
+               goto err_lcd_clk;
        }
 
        sfb->regs = ioremap(res->start, resource_size(res));
@@ -1450,7 +1470,13 @@ err_ioremap:
 err_req_region:
        release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res));
 
-err_clk:
+err_lcd_clk:
+       if (!sfb->variant.has_clksel) {
+               clk_disable(sfb->lcd_clk);
+               clk_put(sfb->lcd_clk);
+       }
+
+err_bus_clk:
        clk_disable(sfb->bus_clk);
        clk_put(sfb->bus_clk);
 
@@ -1481,6 +1507,11 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
 
        iounmap(sfb->regs);
 
+       if (!sfb->variant.has_clksel) {
+               clk_disable(sfb->lcd_clk);
+               clk_put(sfb->lcd_clk);
+       }
+
        clk_disable(sfb->bus_clk);
        clk_put(sfb->bus_clk);
 
@@ -1510,6 +1541,9 @@ static int s3c_fb_suspend(struct device *dev)
                s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
        }
 
+       if (!sfb->variant.has_clksel)
+               clk_disable(sfb->lcd_clk);
+
        clk_disable(sfb->bus_clk);
        return 0;
 }
@@ -1524,6 +1558,9 @@ static int s3c_fb_resume(struct device *dev)
 
        clk_enable(sfb->bus_clk);
 
+       if (!sfb->variant.has_clksel)
+               clk_enable(sfb->lcd_clk);
+
        /* setup gpio and output polarity controls */
        pd->setup_gpio();
        writel(pd->vidcon1, sfb->regs + VIDCON1);
@@ -1569,6 +1606,9 @@ static int s3c_fb_runtime_suspend(struct device *dev)
                s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
        }
 
+       if (!sfb->variant.has_clksel)
+               clk_disable(sfb->lcd_clk);
+
        clk_disable(sfb->bus_clk);
        return 0;
 }
@@ -1583,6 +1623,9 @@ static int s3c_fb_runtime_resume(struct device *dev)
 
        clk_enable(sfb->bus_clk);
 
+       if (!sfb->variant.has_clksel)
+               clk_enable(sfb->lcd_clk);
+
        /* setup gpio and output polarity controls */
        pd->setup_gpio();
        writel(pd->vidcon1, sfb->regs + VIDCON1);
@@ -1755,6 +1798,7 @@ static struct s3c_fb_driverdata s3c_fb_data_64xx = {
                },
 
                .has_prtcon     = 1,
+               .has_clksel     = 1,
        },
        .win[0] = &s3c_fb_data_64xx_wins[0],
        .win[1] = &s3c_fb_data_64xx_wins[1],
@@ -1785,6 +1829,7 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pc100 = {
                },
 
                .has_prtcon     = 1,
+               .has_clksel     = 1,
        },
        .win[0] = &s3c_fb_data_s5p_wins[0],
        .win[1] = &s3c_fb_data_s5p_wins[1],
@@ -1794,6 +1839,37 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pc100 = {
 };
 
 static struct s3c_fb_driverdata s3c_fb_data_s5pv210 = {
+       .variant = {
+               .nr_windows     = 5,
+               .vidtcon        = VIDTCON0,
+               .wincon         = WINCON(0),
+               .winmap         = WINxMAP(0),
+               .keycon         = WKEYCON,
+               .osd            = VIDOSD_BASE,
+               .osd_stride     = 16,
+               .buf_start      = VIDW_BUF_START(0),
+               .buf_size       = VIDW_BUF_SIZE(0),
+               .buf_end        = VIDW_BUF_END(0),
+
+               .palette = {
+                       [0] = 0x2400,
+                       [1] = 0x2800,
+                       [2] = 0x2c00,
+                       [3] = 0x3000,
+                       [4] = 0x3400,
+               },
+
+               .has_shadowcon  = 1,
+               .has_clksel     = 1,
+       },
+       .win[0] = &s3c_fb_data_s5p_wins[0],
+       .win[1] = &s3c_fb_data_s5p_wins[1],
+       .win[2] = &s3c_fb_data_s5p_wins[2],
+       .win[3] = &s3c_fb_data_s5p_wins[3],
+       .win[4] = &s3c_fb_data_s5p_wins[4],
+};
+
+static struct s3c_fb_driverdata s3c_fb_data_exynos4 = {
        .variant = {
                .nr_windows     = 5,
                .vidtcon        = VIDTCON0,
@@ -1843,6 +1919,7 @@ static struct s3c_fb_driverdata s3c_fb_data_s3c2443 = {
                        [0] = 0x400,
                        [1] = 0x800,
                },
+               .has_clksel     = 1,
        },
        .win[0] = &(struct s3c_fb_win_variant) {
                .palette_sz     = 256,
@@ -1859,6 +1936,30 @@ static struct s3c_fb_driverdata s3c_fb_data_s3c2443 = {
        },
 };
 
+static struct s3c_fb_driverdata s3c_fb_data_s5p64x0 = {
+       .variant = {
+               .nr_windows     = 3,
+               .vidtcon        = VIDTCON0,
+               .wincon         = WINCON(0),
+               .winmap         = WINxMAP(0),
+               .keycon         = WKEYCON,
+               .osd            = VIDOSD_BASE,
+               .osd_stride     = 16,
+               .buf_start      = VIDW_BUF_START(0),
+               .buf_size       = VIDW_BUF_SIZE(0),
+               .buf_end        = VIDW_BUF_END(0),
+
+               .palette = {
+                       [0] = 0x2400,
+                       [1] = 0x2800,
+                       [2] = 0x2c00,
+               },
+       },
+       .win[0] = &s3c_fb_data_s5p_wins[0],
+       .win[1] = &s3c_fb_data_s5p_wins[1],
+       .win[2] = &s3c_fb_data_s5p_wins[2],
+};
+
 static struct platform_device_id s3c_fb_driver_ids[] = {
        {
                .name           = "s3c-fb",
@@ -1869,9 +1970,15 @@ static struct platform_device_id s3c_fb_driver_ids[] = {
        }, {
                .name           = "s5pv210-fb",
                .driver_data    = (unsigned long)&s3c_fb_data_s5pv210,
+       }, {
+               .name           = "exynos4-fb",
+               .driver_data    = (unsigned long)&s3c_fb_data_exynos4,
        }, {
                .name           = "s3c2443-fb",
                .driver_data    = (unsigned long)&s3c_fb_data_s3c2443,
+       }, {
+               .name           = "s5p64x0-fb",
+               .driver_data    = (unsigned long)&s3c_fb_data_s5p64x0,
        },
        {},
 };
index 0aa1376..ee4c0df 100644 (file)
@@ -767,7 +767,6 @@ static irqreturn_t s3c2410fb_irq(int irq, void *dev_id)
 static int s3c2410fb_cpufreq_transition(struct notifier_block *nb,
                                        unsigned long val, void *data)
 {
-       struct cpufreq_freqs *freqs = data;
        struct s3c2410fb_info *info;
        struct fb_info *fbinfo;
        long delta_f;
@@ -911,7 +910,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
        for (i = 0; i < 256; i++)
                info->palette_buffer[i] = PALETTE_BUFF_CLEAR;
 
-       ret = request_irq(irq, s3c2410fb_irq, IRQF_DISABLED, pdev->name, info);
+       ret = request_irq(irq, s3c2410fb_irq, 0, pdev->name, info);
        if (ret) {
                dev_err(&pdev->dev, "cannot get irq %d - err %d\n", irq, ret);
                ret = -EBUSY;
index 4ca5d0c..946a949 100644 (file)
@@ -1019,12 +1019,13 @@ static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
        unsigned int offset;
 
        /* Calculate the offset */
-       if (var->bits_per_pixel == 0) {
-               offset = (var->yoffset / 16) * (var->xres_virtual / 2) + (var->xoffset / 2);
+       if (info->var.bits_per_pixel == 0) {
+               offset = (var->yoffset / 16) * (info->var.xres_virtual / 2)
+                      + (var->xoffset / 2);
                offset = offset >> 2;
        } else {
                offset = (var->yoffset * info->fix.line_length) +
-                        (var->xoffset * var->bits_per_pixel / 8);
+                        (var->xoffset * info->var.bits_per_pixel / 8);
                offset = offset >> 2;
        }
 
@@ -1504,7 +1505,7 @@ static struct pci_driver s3fb_pci_driver = {
        .resume         = s3_pci_resume,
 };
 
-/* Parse user speficied options */
+/* Parse user specified options */
 
 #ifndef MODULE
 static int  __init s3fb_setup(char *options)
index e8b76d6..98d55d0 100644 (file)
@@ -1457,8 +1457,7 @@ static int __devinit sa1100fb_probe(struct platform_device *pdev)
        if (ret)
                goto failed;
 
-       ret = request_irq(irq, sa1100fb_handle_irq, IRQF_DISABLED,
-                         "LCD", fbi);
+       ret = request_irq(irq, sa1100fb_handle_irq, 0, "LCD", fbi);
        if (ret) {
                printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret);
                goto failed;
index 4de541c..beb4950 100644 (file)
@@ -1477,15 +1477,9 @@ static void savagefb_set_par_int(struct savagefb_par  *par, struct savage_reg *r
        vgaHWProtect(par, 0);
 }
 
-static void savagefb_update_start(struct savagefb_par      *par,
-                                 struct fb_var_screeninfo *var)
+static void savagefb_update_start(struct savagefb_par *par, int base)
 {
-       int base;
-
-       base = ((var->yoffset * var->xres_virtual + (var->xoffset & ~1))
-               * ((var->bits_per_pixel+7) / 8)) >> 2;
-
-       /* now program the start address registers */
+       /* program the start address registers */
        vga_out16(0x3d4, (base & 0x00ff00) | 0x0c, par);
        vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d, par);
        vga_out8(0x3d4, 0x69, par);
@@ -1550,8 +1544,12 @@ static int savagefb_pan_display(struct fb_var_screeninfo *var,
                                struct fb_info           *info)
 {
        struct savagefb_par *par = info->par;
+       int base;
+
+       base = (var->yoffset * info->fix.line_length
+            + (var->xoffset & ~1) * ((info->var.bits_per_pixel+7) / 8)) >> 2;
 
-       savagefb_update_start(par, var);
+       savagefb_update_start(par, base);
        return 0;
 }
 
index 7d54e2c..647ba98 100644 (file)
@@ -1111,6 +1111,7 @@ static long sh_hdmi_clk_configure(struct sh_hdmi *hdmi, unsigned long hdmi_rate,
 static void sh_hdmi_edid_work_fn(struct work_struct *work)
 {
        struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work);
+       struct fb_info *info;
        struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
        struct sh_mobile_lcdc_chan *ch;
        int ret;
@@ -1123,8 +1124,9 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
 
        mutex_lock(&hdmi->mutex);
 
+       info = hdmi->info;
+
        if (hdmi->hp_state == HDMI_HOTPLUG_CONNECTED) {
-               struct fb_info *info = hdmi->info;
                unsigned long parent_rate = 0, hdmi_rate;
 
                ret = sh_hdmi_read_edid(hdmi, &hdmi_rate, &parent_rate);
@@ -1148,42 +1150,45 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
 
                ch = info->par;
 
-               console_lock();
+               if (lock_fb_info(info)) {
+                       console_lock();
 
-               /* HDMI plug in */
-               if (!sh_hdmi_must_reconfigure(hdmi) &&
-                   info->state == FBINFO_STATE_RUNNING) {
-                       /*
-                        * First activation with the default monitor - just turn
-                        * on, if we run a resume here, the logo disappears
-                        */
-                       if (lock_fb_info(info)) {
+                       /* HDMI plug in */
+                       if (!sh_hdmi_must_reconfigure(hdmi) &&
+                           info->state == FBINFO_STATE_RUNNING) {
+                               /*
+                                * First activation with the default monitor - just turn
+                                * on, if we run a resume here, the logo disappears
+                                */
                                info->var.width = hdmi->var.width;
                                info->var.height = hdmi->var.height;
                                sh_hdmi_display_on(hdmi, info);
-                               unlock_fb_info(info);
+                       } else {
+                               /* New monitor or have to wake up */
+                               fb_set_suspend(info, 0);
                        }
-               } else {
-                       /* New monitor or have to wake up */
-                       fb_set_suspend(info, 0);
-               }
 
-               console_unlock();
+                       console_unlock();
+                       unlock_fb_info(info);
+               }
        } else {
                ret = 0;
-               if (!hdmi->info)
+               if (!info)
                        goto out;
 
                hdmi->monspec.modedb_len = 0;
                fb_destroy_modedb(hdmi->monspec.modedb);
                hdmi->monspec.modedb = NULL;
 
-               console_lock();
+               if (lock_fb_info(info)) {
+                       console_lock();
 
-               /* HDMI disconnect */
-               fb_set_suspend(hdmi->info, 1);
+                       /* HDMI disconnect */
+                       fb_set_suspend(info, 1);
 
-               console_unlock();
+                       console_unlock();
+                       unlock_fb_info(info);
+               }
        }
 
 out:
index b048417..3a41c01 100644 (file)
 #include <linux/backlight.h>
 #include <linux/gpio.h>
 #include <video/sh_mobile_lcdc.h>
+#include <video/sh_mobile_meram.h>
 #include <linux/atomic.h>
 
 #include "sh_mobile_lcdcfb.h"
-#include "sh_mobile_meram.h"
 
 #define SIDE_B_OFFSET 0x1000
 #define MIRROR_OFFSET 0x2000
 
-/* shared registers */
-#define _LDDCKR 0x410
-#define _LDDCKSTPR 0x414
-#define _LDINTR 0x468
-#define _LDSR 0x46c
-#define _LDCNT1R 0x470
-#define _LDCNT2R 0x474
-#define _LDRCNTR 0x478
-#define _LDDDSR 0x47c
-#define _LDDWD0R 0x800
-#define _LDDRDR 0x840
-#define _LDDWAR 0x900
-#define _LDDRAR 0x904
-
-/* shared registers and their order for context save/restore */
-static int lcdc_shared_regs[] = {
-       _LDDCKR,
-       _LDDCKSTPR,
-       _LDINTR,
-       _LDDDSR,
-       _LDCNT1R,
-       _LDCNT2R,
-};
-#define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs)
-
 #define MAX_XRES 1920
 #define MAX_YRES 1080
 
@@ -98,22 +73,6 @@ static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = {
        [LDPMR] = 0x63c,
 };
 
-#define START_LCDC     0x00000001
-#define LCDC_RESET     0x00000100
-#define DISPLAY_BEU    0x00000008
-#define LCDC_ENABLE    0x00000001
-#define LDINTR_FE      0x00000400
-#define LDINTR_VSE     0x00000200
-#define LDINTR_VEE     0x00000100
-#define LDINTR_FS      0x00000004
-#define LDINTR_VSS     0x00000002
-#define LDINTR_VES     0x00000001
-#define LDRCNTR_SRS    0x00020000
-#define LDRCNTR_SRC    0x00010000
-#define LDRCNTR_MRS    0x00000002
-#define LDRCNTR_MRC    0x00000001
-#define LDSR_MRS       0x00000100
-
 static const struct fb_videomode default_720p = {
        .name = "HDMI 720p",
        .xres = 1280,
@@ -141,7 +100,6 @@ struct sh_mobile_lcdc_priv {
        unsigned long lddckr;
        struct sh_mobile_lcdc_chan ch[2];
        struct notifier_block notifier;
-       unsigned long saved_shared_regs[NR_SHARED_REGS];
        int started;
        int forced_bpp; /* 2 channel LCDC must share bpp setting */
        struct sh_mobile_meram_info *meram_dev;
@@ -218,33 +176,36 @@ static void lcdc_sys_write_index(void *handle, unsigned long data)
 {
        struct sh_mobile_lcdc_chan *ch = handle;
 
-       lcdc_write(ch->lcdc, _LDDWD0R, data | 0x10000000);
-       lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
-       lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
-       lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
+       lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT);
+       lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
+       lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA |
+                  (lcdc_chan_is_sublcd(ch) ? 2 : 0));
+       lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
 }
 
 static void lcdc_sys_write_data(void *handle, unsigned long data)
 {
        struct sh_mobile_lcdc_chan *ch = handle;
 
-       lcdc_write(ch->lcdc, _LDDWD0R, data | 0x11000000);
-       lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
-       lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
-       lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
+       lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT | LDDWDxR_RSW);
+       lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
+       lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA |
+                  (lcdc_chan_is_sublcd(ch) ? 2 : 0));
+       lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
 }
 
 static unsigned long lcdc_sys_read_data(void *handle)
 {
        struct sh_mobile_lcdc_chan *ch = handle;
 
-       lcdc_write(ch->lcdc, _LDDRDR, 0x01000000);
-       lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
-       lcdc_write(ch->lcdc, _LDDRAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
+       lcdc_write(ch->lcdc, _LDDRDR, LDDRDR_RSR);
+       lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
+       lcdc_write(ch->lcdc, _LDDRAR, LDDRAR_RA |
+                  (lcdc_chan_is_sublcd(ch) ? 2 : 0));
        udelay(1);
-       lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
+       lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0);
 
-       return lcdc_read(ch->lcdc, _LDDRDR) & 0x3ffff;
+       return lcdc_read(ch->lcdc, _LDDRDR) & LDDRDR_DRD_MASK;
 }
 
 struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
@@ -256,18 +217,22 @@ struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
 static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
 {
        if (atomic_inc_and_test(&priv->hw_usecnt)) {
-               pm_runtime_get_sync(priv->dev);
                if (priv->dot_clk)
                        clk_enable(priv->dot_clk);
+               pm_runtime_get_sync(priv->dev);
+               if (priv->meram_dev && priv->meram_dev->pdev)
+                       pm_runtime_get_sync(&priv->meram_dev->pdev->dev);
        }
 }
 
 static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv)
 {
        if (atomic_sub_return(1, &priv->hw_usecnt) == -1) {
+               if (priv->meram_dev && priv->meram_dev->pdev)
+                       pm_runtime_put_sync(&priv->meram_dev->pdev->dev);
+               pm_runtime_put(priv->dev);
                if (priv->dot_clk)
                        clk_disable(priv->dot_clk);
-               pm_runtime_put(priv->dev);
        }
 }
 
@@ -319,13 +284,13 @@ static void sh_mobile_lcdc_deferred_io(struct fb_info *info,
                if (bcfg->start_transfer)
                        bcfg->start_transfer(bcfg->board_data, ch,
                                             &sh_mobile_lcdc_sys_bus_ops);
-               lcdc_write_chan(ch, LDSM2R, 1);
+               lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG);
                dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
        } else {
                if (bcfg->start_transfer)
                        bcfg->start_transfer(bcfg->board_data, ch,
                                             &sh_mobile_lcdc_sys_bus_ops);
-               lcdc_write_chan(ch, LDSM2R, 1);
+               lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG);
        }
 }
 
@@ -341,22 +306,16 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
 {
        struct sh_mobile_lcdc_priv *priv = data;
        struct sh_mobile_lcdc_chan *ch;
-       unsigned long tmp;
        unsigned long ldintr;
        int is_sub;
        int k;
 
-       /* acknowledge interrupt */
-       ldintr = tmp = lcdc_read(priv, _LDINTR);
-       /*
-        * disable further VSYNC End IRQs, preserve all other enabled IRQs,
-        * write 0 to bits 0-6 to ack all triggered IRQs.
-        */
-       tmp &= 0xffffff00 & ~LDINTR_VEE;
-       lcdc_write(priv, _LDINTR, tmp);
+       /* Acknowledge interrupts and disable further VSYNC End IRQs. */
+       ldintr = lcdc_read(priv, _LDINTR);
+       lcdc_write(priv, _LDINTR, (ldintr ^ LDINTR_STATUS_MASK) & ~LDINTR_VEE);
 
        /* figure out if this interrupt is for main or sub lcd */
-       is_sub = (lcdc_read(priv, _LDSR) & (1 << 10)) ? 1 : 0;
+       is_sub = (lcdc_read(priv, _LDSR) & LDSR_MSS) ? 1 : 0;
 
        /* wake up channel and disable clocks */
        for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
@@ -365,7 +324,7 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
                if (!ch->enabled)
                        continue;
 
-               /* Frame Start */
+               /* Frame End */
                if (ldintr & LDINTR_FS) {
                        if (is_sub == lcdc_chan_is_sublcd(ch)) {
                                ch->frame_end = 1;
@@ -391,16 +350,17 @@ static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
 
        /* start or stop the lcdc */
        if (start)
-               lcdc_write(priv, _LDCNT2R, tmp | START_LCDC);
+               lcdc_write(priv, _LDCNT2R, tmp | LDCNT2R_DO);
        else
-               lcdc_write(priv, _LDCNT2R, tmp & ~START_LCDC);
+               lcdc_write(priv, _LDCNT2R, tmp & ~LDCNT2R_DO);
 
        /* wait until power is applied/stopped on all channels */
        for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
                if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled)
                        while (1) {
-                               tmp = lcdc_read_chan(&priv->ch[k], LDPMR) & 3;
-                               if (start && tmp == 3)
+                               tmp = lcdc_read_chan(&priv->ch[k], LDPMR)
+                                   & LDPMR_LPS;
+                               if (start && tmp == LDPMR_LPS)
                                        break;
                                if (!start && tmp == 0)
                                        break;
@@ -418,13 +378,13 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
        u32 tmp;
 
        tmp = ch->ldmt1r_value;
-       tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1 << 28;
-       tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1 << 27;
-       tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? 1 << 26 : 0;
-       tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? 1 << 25 : 0;
-       tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? 1 << 24 : 0;
-       tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? 1 << 17 : 0;
-       tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? 1 << 16 : 0;
+       tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : LDMT1R_VPOL;
+       tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : LDMT1R_HPOL;
+       tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? LDMT1R_DWPOL : 0;
+       tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? LDMT1R_DIPOL : 0;
+       tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? LDMT1R_DAPOL : 0;
+       tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? LDMT1R_HSCNT : 0;
+       tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? LDMT1R_DWCNT : 0;
        lcdc_write_chan(ch, LDMT1R, tmp);
 
        /* setup SYS bus */
@@ -463,242 +423,239 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
        lcdc_write_chan(ch, LDHAJR, tmp);
 }
 
-static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
+/*
+ * __sh_mobile_lcdc_start - Configure and tart the LCDC
+ * @priv: LCDC device
+ *
+ * Configure all enabled channels and start the LCDC device. All external
+ * devices (clocks, MERAM, panels, ...) are not touched by this function.
+ */
+static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 {
        struct sh_mobile_lcdc_chan *ch;
-       struct sh_mobile_lcdc_board_cfg *board_cfg;
        unsigned long tmp;
        int bpp = 0;
-       unsigned long ldddsr;
-       int k, m, ret;
+       int k, m;
 
-       /* enable clocks before accessing the hardware */
-       for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
-               if (priv->ch[k].enabled) {
-                       sh_mobile_lcdc_clk_on(priv);
-                       if (!bpp)
-                               bpp = priv->ch[k].info->var.bits_per_pixel;
-               }
-       }
-
-       /* reset */
-       lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LCDC_RESET);
-       lcdc_wait_bit(priv, _LDCNT2R, LCDC_RESET, 0);
-
-       /* enable LCDC channels */
-       tmp = lcdc_read(priv, _LDCNT2R);
-       tmp |= priv->ch[0].enabled;
-       tmp |= priv->ch[1].enabled;
-       lcdc_write(priv, _LDCNT2R, tmp);
-
-       /* read data from external memory, avoid using the BEU for now */
-       lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) & ~DISPLAY_BEU);
+       /* Enable LCDC channels. Read data from external memory, avoid using the
+        * BEU for now.
+        */
+       lcdc_write(priv, _LDCNT2R, priv->ch[0].enabled | priv->ch[1].enabled);
 
-       /* stop the lcdc first */
+       /* Stop the LCDC first and disable all interrupts. */
        sh_mobile_lcdc_start_stop(priv, 0);
+       lcdc_write(priv, _LDINTR, 0);
 
-       /* configure clocks */
+       /* Configure power supply, dot clocks and start them. */
        tmp = priv->lddckr;
        for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
                ch = &priv->ch[k];
-
-               if (!priv->ch[k].enabled)
+               if (!ch->enabled)
                        continue;
 
+               if (!bpp)
+                       bpp = ch->info->var.bits_per_pixel;
+
+               /* Power supply */
+               lcdc_write_chan(ch, LDPMR, 0);
+
                m = ch->cfg.clock_divider;
                if (!m)
                        continue;
 
-               if (m == 1)
-                       m = 1 << 6;
-               tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0);
-
-               /* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider denominator */
+               /* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider
+                * denominator.
+                */
                lcdc_write_chan(ch, LDDCKPAT1R, 0);
                lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1);
+
+               if (m == 1)
+                       m = LDDCKR_MOSEL;
+               tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0);
        }
 
        lcdc_write(priv, _LDDCKR, tmp);
-
-       /* start dotclock again */
        lcdc_write(priv, _LDDCKSTPR, 0);
        lcdc_wait_bit(priv, _LDDCKSTPR, ~0, 0);
 
-       /* interrupts are disabled to begin with */
-       lcdc_write(priv, _LDINTR, 0);
-
+       /* Setup geometry, format, frame buffer memory and operation mode. */
        for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
                ch = &priv->ch[k];
-
                if (!ch->enabled)
                        continue;
 
                sh_mobile_lcdc_geometry(ch);
 
-               /* power supply */
-               lcdc_write_chan(ch, LDPMR, 0);
-
-               board_cfg = &ch->cfg.board_cfg;
-               if (board_cfg->setup_sys) {
-                       ret = board_cfg->setup_sys(board_cfg->board_data,
-                                               ch, &sh_mobile_lcdc_sys_bus_ops);
-                       if (ret)
-                               return ret;
-               }
-       }
-
-       /* word and long word swap */
-       ldddsr = lcdc_read(priv, _LDDDSR);
-       if  (priv->ch[0].info->var.nonstd)
-               lcdc_write(priv, _LDDDSR, ldddsr | 7);
-       else {
-               switch (bpp) {
-               case 16:
-                       lcdc_write(priv, _LDDDSR, ldddsr | 6);
-                       break;
-               case 24:
-                       lcdc_write(priv, _LDDDSR, ldddsr | 7);
-                       break;
-               case 32:
-                       lcdc_write(priv, _LDDDSR, ldddsr | 4);
-                       break;
-               }
-       }
-
-       for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
-               unsigned long base_addr_y;
-               unsigned long base_addr_c = 0;
-               int pitch;
-               ch = &priv->ch[k];
-
-               if (!priv->ch[k].enabled)
-                       continue;
-
-               /* set bpp format in PKF[4:0] */
-               tmp = lcdc_read_chan(ch, LDDFR);
-               tmp &= ~0x0003031f;
                if (ch->info->var.nonstd) {
-                       tmp |= (ch->info->var.nonstd << 16);
+                       tmp = (ch->info->var.nonstd << 16);
                        switch (ch->info->var.bits_per_pixel) {
                        case 12:
+                               tmp |= LDDFR_YF_420;
                                break;
                        case 16:
-                               tmp |= (0x1 << 8);
+                               tmp |= LDDFR_YF_422;
                                break;
                        case 24:
-                               tmp |= (0x2 << 8);
+                       default:
+                               tmp |= LDDFR_YF_444;
                                break;
                        }
                } else {
                        switch (ch->info->var.bits_per_pixel) {
                        case 16:
-                               tmp |= 0x03;
+                               tmp = LDDFR_PKF_RGB16;
                                break;
                        case 24:
-                               tmp |= 0x0b;
+                               tmp = LDDFR_PKF_RGB24;
                                break;
                        case 32:
+                       default:
+                               tmp = LDDFR_PKF_ARGB32;
                                break;
                        }
                }
+
                lcdc_write_chan(ch, LDDFR, tmp);
+               lcdc_write_chan(ch, LDMLSR, ch->pitch);
+               lcdc_write_chan(ch, LDSA1R, ch->base_addr_y);
+               if (ch->info->var.nonstd)
+                       lcdc_write_chan(ch, LDSA2R, ch->base_addr_c);
 
-               base_addr_y = ch->info->fix.smem_start;
-               base_addr_c = base_addr_y +
-                               ch->info->var.xres *
-                               ch->info->var.yres_virtual;
-               pitch = ch->info->fix.line_length;
+               /* When using deferred I/O mode, configure the LCDC for one-shot
+                * operation and enable the frame end interrupt. Otherwise use
+                * continuous read mode.
+                */
+               if (ch->ldmt1r_value & LDMT1R_IFM &&
+                   ch->cfg.sys_bus_cfg.deferred_io_msec) {
+                       lcdc_write_chan(ch, LDSM1R, LDSM1R_OS);
+                       lcdc_write(priv, _LDINTR, LDINTR_FE);
+               } else {
+                       lcdc_write_chan(ch, LDSM1R, 0);
+               }
+       }
 
-               /* test if we can enable meram */
-               if (ch->cfg.meram_cfg && priv->meram_dev &&
-                               priv->meram_dev->ops) {
-                       struct sh_mobile_meram_cfg *cfg;
-                       struct sh_mobile_meram_info *mdev;
-                       unsigned long icb_addr_y, icb_addr_c;
-                       int icb_pitch;
-                       int pf;
+       /* Word and long word swap. */
+       if  (priv->ch[0].info->var.nonstd)
+               tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
+       else {
+               switch (bpp) {
+               case 16:
+                       tmp = LDDDSR_LS | LDDDSR_WS;
+                       break;
+               case 24:
+                       tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
+                       break;
+               case 32:
+               default:
+                       tmp = LDDDSR_LS;
+                       break;
+               }
+       }
+       lcdc_write(priv, _LDDDSR, tmp);
 
-                       cfg = ch->cfg.meram_cfg;
-                       mdev = priv->meram_dev;
-                       /* we need to de-init configured ICBs before we
-                        * we can re-initialize them.
-                        */
-                       if (ch->meram_enabled)
-                               mdev->ops->meram_unregister(mdev, cfg);
+       /* Enable the display output. */
+       lcdc_write(priv, _LDCNT1R, LDCNT1R_DE);
+       sh_mobile_lcdc_start_stop(priv, 1);
+       priv->started = 1;
+}
 
-                       ch->meram_enabled = 0;
+static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
+{
+       struct sh_mobile_meram_info *mdev = priv->meram_dev;
+       struct sh_mobile_lcdc_board_cfg *board_cfg;
+       struct sh_mobile_lcdc_chan *ch;
+       unsigned long tmp;
+       int ret;
+       int k;
 
-                       if (ch->info->var.nonstd) {
-                               if (ch->info->var.bits_per_pixel == 24)
-                                       pf = SH_MOBILE_MERAM_PF_NV24;
-                               else
-                                       pf = SH_MOBILE_MERAM_PF_NV;
-                       } else {
-                               pf = SH_MOBILE_MERAM_PF_RGB;
-                       }
+       /* enable clocks before accessing the hardware */
+       for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+               if (priv->ch[k].enabled)
+                       sh_mobile_lcdc_clk_on(priv);
+       }
 
-                       ret = mdev->ops->meram_register(mdev, cfg, pitch,
-                                               ch->info->var.yres,
-                                               pf,
-                                               base_addr_y,
-                                               base_addr_c,
-                                               &icb_addr_y,
-                                               &icb_addr_c,
-                                               &icb_pitch);
-                       if (!ret)  {
-                               /* set LDSA1R value */
-                               base_addr_y = icb_addr_y;
-                               pitch = icb_pitch;
-
-                               /* set LDSA2R value if required */
-                               if (base_addr_c)
-                                       base_addr_c = icb_addr_c;
-
-                               ch->meram_enabled = 1;
-                       }
-               }
+       /* reset */
+       lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LDCNT2R_BR);
+       lcdc_wait_bit(priv, _LDCNT2R, LDCNT2R_BR, 0);
 
-               /* point out our frame buffer */
-               lcdc_write_chan(ch, LDSA1R, base_addr_y);
-               if (ch->info->var.nonstd)
-                       lcdc_write_chan(ch, LDSA2R, base_addr_c);
+       for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+               ch = &priv->ch[k];
 
-               /* set line size */
-               lcdc_write_chan(ch, LDMLSR, pitch);
+               if (!ch->enabled)
+                       continue;
 
-               /* setup deferred io if SYS bus */
-               tmp = ch->cfg.sys_bus_cfg.deferred_io_msec;
-               if (ch->ldmt1r_value & (1 << 12) && tmp) {
-                       ch->defio.deferred_io = sh_mobile_lcdc_deferred_io;
-                       ch->defio.delay = msecs_to_jiffies(tmp);
-                       ch->info->fbdefio = &ch->defio;
-                       fb_deferred_io_init(ch->info);
+               board_cfg = &ch->cfg.board_cfg;
+               if (board_cfg->setup_sys) {
+                       ret = board_cfg->setup_sys(board_cfg->board_data, ch,
+                                                  &sh_mobile_lcdc_sys_bus_ops);
+                       if (ret)
+                               return ret;
+               }
+       }
 
-                       /* one-shot mode */
-                       lcdc_write_chan(ch, LDSM1R, 1);
+       /* Compute frame buffer base address and pitch for each channel. */
+       for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+               struct sh_mobile_meram_cfg *cfg;
+               int pixelformat;
 
-                       /* enable "Frame End Interrupt Enable" bit */
-                       lcdc_write(priv, _LDINTR, LDINTR_FE);
+               ch = &priv->ch[k];
+               if (!ch->enabled)
+                       continue;
 
-               } else {
-                       /* continuous read mode */
-                       lcdc_write_chan(ch, LDSM1R, 0);
+               ch->base_addr_y = ch->info->fix.smem_start;
+               ch->base_addr_c = ch->base_addr_y
+                               + ch->info->var.xres
+                               * ch->info->var.yres_virtual;
+               ch->pitch = ch->info->fix.line_length;
+
+               /* Enable MERAM if possible. */
+               cfg = ch->cfg.meram_cfg;
+               if (mdev == NULL || mdev->ops == NULL || cfg == NULL)
+                       continue;
+
+               /* we need to de-init configured ICBs before we can
+                * re-initialize them.
+                */
+               if (ch->meram_enabled) {
+                       mdev->ops->meram_unregister(mdev, cfg);
+                       ch->meram_enabled = 0;
                }
+
+               if (!ch->info->var.nonstd)
+                       pixelformat = SH_MOBILE_MERAM_PF_RGB;
+               else if (ch->info->var.bits_per_pixel == 24)
+                       pixelformat = SH_MOBILE_MERAM_PF_NV24;
+               else
+                       pixelformat = SH_MOBILE_MERAM_PF_NV;
+
+               ret = mdev->ops->meram_register(mdev, cfg, ch->pitch,
+                                       ch->info->var.yres, pixelformat,
+                                       ch->base_addr_y, ch->base_addr_c,
+                                       &ch->base_addr_y, &ch->base_addr_c,
+                                       &ch->pitch);
+               if (!ret)
+                       ch->meram_enabled = 1;
        }
 
-       /* display output */
-       lcdc_write(priv, _LDCNT1R, LCDC_ENABLE);
+       /* Start the LCDC. */
+       __sh_mobile_lcdc_start(priv);
 
-       /* start the lcdc */
-       sh_mobile_lcdc_start_stop(priv, 1);
-       priv->started = 1;
-
-       /* tell the board code to enable the panel */
+       /* Setup deferred I/O, tell the board code to enable the panels, and
+        * turn backlight on.
+        */
        for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
                ch = &priv->ch[k];
                if (!ch->enabled)
                        continue;
 
+               tmp = ch->cfg.sys_bus_cfg.deferred_io_msec;
+               if (ch->ldmt1r_value & LDMT1R_IFM && tmp) {
+                       ch->defio.deferred_io = sh_mobile_lcdc_deferred_io;
+                       ch->defio.delay = msecs_to_jiffies(tmp);
+                       ch->info->fbdefio = &ch->defio;
+                       fb_deferred_io_init(ch->info);
+               }
+
                board_cfg = &ch->cfg.board_cfg;
                if (board_cfg->display_on && try_module_get(board_cfg->owner)) {
                        board_cfg->display_on(board_cfg->board_data, ch->info);
@@ -776,42 +733,42 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
 
 static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch)
 {
-       int ifm, miftyp;
-
-       switch (ch->cfg.interface_type) {
-       case RGB8: ifm = 0; miftyp = 0; break;
-       case RGB9: ifm = 0; miftyp = 4; break;
-       case RGB12A: ifm = 0; miftyp = 5; break;
-       case RGB12B: ifm = 0; miftyp = 6; break;
-       case RGB16: ifm = 0; miftyp = 7; break;
-       case RGB18: ifm = 0; miftyp = 10; break;
-       case RGB24: ifm = 0; miftyp = 11; break;
-       case SYS8A: ifm = 1; miftyp = 0; break;
-       case SYS8B: ifm = 1; miftyp = 1; break;
-       case SYS8C: ifm = 1; miftyp = 2; break;
-       case SYS8D: ifm = 1; miftyp = 3; break;
-       case SYS9: ifm = 1; miftyp = 4; break;
-       case SYS12: ifm = 1; miftyp = 5; break;
-       case SYS16A: ifm = 1; miftyp = 7; break;
-       case SYS16B: ifm = 1; miftyp = 8; break;
-       case SYS16C: ifm = 1; miftyp = 9; break;
-       case SYS18: ifm = 1; miftyp = 10; break;
-       case SYS24: ifm = 1; miftyp = 11; break;
-       default: goto bad;
+       int interface_type = ch->cfg.interface_type;
+
+       switch (interface_type) {
+       case RGB8:
+       case RGB9:
+       case RGB12A:
+       case RGB12B:
+       case RGB16:
+       case RGB18:
+       case RGB24:
+       case SYS8A:
+       case SYS8B:
+       case SYS8C:
+       case SYS8D:
+       case SYS9:
+       case SYS12:
+       case SYS16A:
+       case SYS16B:
+       case SYS16C:
+       case SYS18:
+       case SYS24:
+               break;
+       default:
+               return -EINVAL;
        }
 
        /* SUBLCD only supports SYS interface */
        if (lcdc_chan_is_sublcd(ch)) {
-               if (ifm == 0)
-                       goto bad;
-               else
-                       ifm = 0;
+               if (!(interface_type & LDMT1R_IFM))
+                       return -EINVAL;
+
+               interface_type &= ~LDMT1R_IFM;
        }
 
-       ch->ldmt1r_value = (ifm << 12) | miftyp;
+       ch->ldmt1r_value = interface_type;
        return 0;
- bad:
-       return -EINVAL;
 }
 
 static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
@@ -819,18 +776,24 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
                                       struct sh_mobile_lcdc_priv *priv)
 {
        char *str;
-       int icksel;
 
        switch (clock_source) {
-       case LCDC_CLK_BUS: str = "bus_clk"; icksel = 0; break;
-       case LCDC_CLK_PERIPHERAL: str = "peripheral_clk"; icksel = 1; break;
-       case LCDC_CLK_EXTERNAL: str = NULL; icksel = 2; break;
+       case LCDC_CLK_BUS:
+               str = "bus_clk";
+               priv->lddckr = LDDCKR_ICKSEL_BUS;
+               break;
+       case LCDC_CLK_PERIPHERAL:
+               str = "peripheral_clk";
+               priv->lddckr = LDDCKR_ICKSEL_MIPI;
+               break;
+       case LCDC_CLK_EXTERNAL:
+               str = NULL;
+               priv->lddckr = LDDCKR_ICKSEL_HDMI;
+               break;
        default:
                return -EINVAL;
        }
 
-       priv->lddckr = icksel << 16;
-
        if (str) {
                priv->dot_clk = clk_get(&pdev->dev, str);
                if (IS_ERR(priv->dot_clk)) {
@@ -914,12 +877,12 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
        unsigned long base_addr_y, base_addr_c;
        unsigned long c_offset;
 
-       if (!var->nonstd)
-               new_pan_offset = (var->yoffset * info->fix.line_length) +
-                       (var->xoffset * (info->var.bits_per_pixel / 8));
+       if (!info->var.nonstd)
+               new_pan_offset = var->yoffset * info->fix.line_length
+                              + var->xoffset * (info->var.bits_per_pixel / 8);
        else
-               new_pan_offset = (var->yoffset * info->fix.line_length) +
-                       (var->xoffset);
+               new_pan_offset = var->yoffset * info->fix.line_length
+                              + var->xoffset;
 
        if (new_pan_offset == ch->pan_offset)
                return 0;       /* No change, do nothing */
@@ -928,44 +891,40 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
 
        /* Set the source address for the next refresh */
        base_addr_y = ch->dma_handle + new_pan_offset;
-       if (var->nonstd) {
+       if (info->var.nonstd) {
                /* Set y offset */
-               c_offset = (var->yoffset *
-                       info->fix.line_length *
-                       (info->var.bits_per_pixel - 8)) / 8;
-               base_addr_c = ch->dma_handle + var->xres * var->yres_virtual +
-                       c_offset;
+               c_offset = var->yoffset * info->fix.line_length
+                        * (info->var.bits_per_pixel - 8) / 8;
+               base_addr_c = ch->dma_handle
+                           + info->var.xres * info->var.yres_virtual
+                           + c_offset;
                /* Set x offset */
                if (info->var.bits_per_pixel == 24)
                        base_addr_c += 2 * var->xoffset;
                else
                        base_addr_c += var->xoffset;
-       } else
-               base_addr_c = 0;
+       }
 
-       if (!ch->meram_enabled) {
-               lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
-               if (base_addr_c)
-                       lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
-       } else {
+       if (ch->meram_enabled) {
                struct sh_mobile_meram_cfg *cfg;
                struct sh_mobile_meram_info *mdev;
-               unsigned long icb_addr_y, icb_addr_c;
                int ret;
 
                cfg = ch->cfg.meram_cfg;
                mdev = priv->meram_dev;
                ret = mdev->ops->meram_update(mdev, cfg,
                                        base_addr_y, base_addr_c,
-                                       &icb_addr_y, &icb_addr_c);
+                                       &base_addr_y, &base_addr_c);
                if (ret)
                        return ret;
+       }
 
-               lcdc_write_chan_mirror(ch, LDSA1R, icb_addr_y);
-               if (icb_addr_c)
-                       lcdc_write_chan_mirror(ch, LDSA2R, icb_addr_c);
+       ch->base_addr_y = base_addr_y;
+       ch->base_addr_c = base_addr_c;
 
-       }
+       lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
+       if (info->var.nonstd)
+               lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
 
        if (lcdc_chan_is_sublcd(ch))
                lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS);
@@ -985,9 +944,11 @@ static int sh_mobile_wait_for_vsync(struct fb_info *info)
        unsigned long ldintr;
        int ret;
 
-       /* Enable VSync End interrupt */
+       /* Enable VSync End interrupt and be careful not to acknowledge any
+        * pending interrupt.
+        */
        ldintr = lcdc_read(ch->lcdc, _LDINTR);
-       ldintr |= LDINTR_VEE;
+       ldintr |= LDINTR_VEE | LDINTR_STATUS_MASK;
        lcdc_write(ch->lcdc, _LDINTR, ldintr);
 
        ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion,
@@ -1037,11 +998,6 @@ static void sh_mobile_fb_reconfig(struct fb_info *info)
                /* Couldn't reconfigure, hopefully, can continue as before */
                return;
 
-       if (info->var.nonstd)
-               info->fix.line_length = mode1.xres;
-       else
-               info->fix.line_length = mode1.xres * (ch->cfg.bpp / 8);
-
        /*
         * fb_set_var() calls the notifier change internally, only if
         * FBINFO_MISC_USEREVENT flag is set. Since we do not want to fake a
@@ -1094,30 +1050,126 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in
 {
        struct sh_mobile_lcdc_chan *ch = info->par;
        struct sh_mobile_lcdc_priv *p = ch->lcdc;
+       unsigned int best_dist = (unsigned int)-1;
+       unsigned int best_xres = 0;
+       unsigned int best_yres = 0;
+       unsigned int i;
 
-       if (var->xres > MAX_XRES || var->yres > MAX_YRES ||
-           var->xres * var->yres * (ch->cfg.bpp / 8) * 2 > info->fix.smem_len) {
-               dev_warn(info->dev, "Invalid info: %u-%u-%u-%u x %u-%u-%u-%u @ %lukHz!\n",
-                        var->left_margin, var->xres, var->right_margin, var->hsync_len,
-                        var->upper_margin, var->yres, var->lower_margin, var->vsync_len,
-                        PICOS2KHZ(var->pixclock));
+       if (var->xres > MAX_XRES || var->yres > MAX_YRES)
                return -EINVAL;
+
+       /* If board code provides us with a list of available modes, make sure
+        * we use one of them. Find the mode closest to the requested one. The
+        * distance between two modes is defined as the size of the
+        * non-overlapping parts of the two rectangles.
+        */
+       for (i = 0; i < ch->cfg.num_cfg; ++i) {
+               const struct fb_videomode *mode = &ch->cfg.lcd_cfg[i];
+               unsigned int dist;
+
+               /* We can only round up. */
+               if (var->xres > mode->xres || var->yres > mode->yres)
+                       continue;
+
+               dist = var->xres * var->yres + mode->xres * mode->yres
+                    - 2 * min(var->xres, mode->xres)
+                        * min(var->yres, mode->yres);
+
+               if (dist < best_dist) {
+                       best_xres = mode->xres;
+                       best_yres = mode->yres;
+                       best_dist = dist;
+               }
+       }
+
+       /* If no available mode can be used, return an error. */
+       if (ch->cfg.num_cfg != 0) {
+               if (best_dist == (unsigned int)-1)
+                       return -EINVAL;
+
+               var->xres = best_xres;
+               var->yres = best_yres;
        }
 
+       /* Make sure the virtual resolution is at least as big as the visible
+        * resolution.
+        */
+       if (var->xres_virtual < var->xres)
+               var->xres_virtual = var->xres;
+       if (var->yres_virtual < var->yres)
+               var->yres_virtual = var->yres;
+
+       if (var->bits_per_pixel <= 16) {                /* RGB 565 */
+               var->bits_per_pixel = 16;
+               var->red.offset = 11;
+               var->red.length = 5;
+               var->green.offset = 5;
+               var->green.length = 6;
+               var->blue.offset = 0;
+               var->blue.length = 5;
+               var->transp.offset = 0;
+               var->transp.length = 0;
+       } else if (var->bits_per_pixel <= 24) {         /* RGB 888 */
+               var->bits_per_pixel = 24;
+               var->red.offset = 16;
+               var->red.length = 8;
+               var->green.offset = 8;
+               var->green.length = 8;
+               var->blue.offset = 0;
+               var->blue.length = 8;
+               var->transp.offset = 0;
+               var->transp.length = 0;
+       } else if (var->bits_per_pixel <= 32) {         /* RGBA 888 */
+               var->bits_per_pixel = 32;
+               var->red.offset = 16;
+               var->red.length = 8;
+               var->green.offset = 8;
+               var->green.length = 8;
+               var->blue.offset = 0;
+               var->blue.length = 8;
+               var->transp.offset = 24;
+               var->transp.length = 8;
+       } else
+               return -EINVAL;
+
+       var->red.msb_right = 0;
+       var->green.msb_right = 0;
+       var->blue.msb_right = 0;
+       var->transp.msb_right = 0;
+
+       /* Make sure we don't exceed our allocated memory. */
+       if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 >
+           info->fix.smem_len)
+               return -EINVAL;
+
        /* only accept the forced_bpp for dual channel configurations */
        if (p->forced_bpp && p->forced_bpp != var->bits_per_pixel)
                return -EINVAL;
 
-       switch (var->bits_per_pixel) {
-       case 16: /* PKF[4:0] = 00011 - RGB 565 */
-       case 24: /* PKF[4:0] = 01011 - RGB 888 */
-       case 32: /* PKF[4:0] = 00000 - RGBA 888 */
-               break;
-       default:
-               return -EINVAL;
+       return 0;
+}
+
+static int sh_mobile_set_par(struct fb_info *info)
+{
+       struct sh_mobile_lcdc_chan *ch = info->par;
+       u32 line_length = info->fix.line_length;
+       int ret;
+
+       sh_mobile_lcdc_stop(ch->lcdc);
+
+       if (info->var.nonstd)
+               info->fix.line_length = info->var.xres;
+       else
+               info->fix.line_length = info->var.xres
+                                     * info->var.bits_per_pixel / 8;
+
+       ret = sh_mobile_lcdc_start(ch->lcdc);
+       if (ret < 0) {
+               dev_err(info->dev, "%s: unable to restart LCDC\n", __func__);
+               info->fix.line_length = line_length;
        }
 
-       return 0;
+       return ret;
 }
 
 /*
@@ -1177,6 +1229,7 @@ static struct fb_ops sh_mobile_lcdc_ops = {
        .fb_open        = sh_mobile_open,
        .fb_release     = sh_mobile_release,
        .fb_check_var   = sh_mobile_check_var,
+       .fb_set_par     = sh_mobile_set_par,
 };
 
 static int sh_mobile_lcdc_update_bl(struct backlight_device *bdev)
@@ -1238,66 +1291,6 @@ static void sh_mobile_lcdc_bl_remove(struct backlight_device *bdev)
        backlight_device_unregister(bdev);
 }
 
-static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp,
-                                  int nonstd)
-{
-       if (nonstd) {
-               switch (bpp) {
-               case 12:
-               case 16:
-               case 24:
-                       var->bits_per_pixel = bpp;
-                       var->nonstd = nonstd;
-                       return 0;
-               default:
-                       return -EINVAL;
-               }
-       }
-
-       switch (bpp) {
-       case 16: /* PKF[4:0] = 00011 - RGB 565 */
-               var->red.offset = 11;
-               var->red.length = 5;
-               var->green.offset = 5;
-               var->green.length = 6;
-               var->blue.offset = 0;
-               var->blue.length = 5;
-               var->transp.offset = 0;
-               var->transp.length = 0;
-               break;
-
-       case 24: /* PKF[4:0] = 01011 - RGB 888 */
-               var->red.offset = 16;
-               var->red.length = 8;
-               var->green.offset = 8;
-               var->green.length = 8;
-               var->blue.offset = 0;
-               var->blue.length = 8;
-               var->transp.offset = 0;
-               var->transp.length = 0;
-               break;
-
-       case 32: /* PKF[4:0] = 00000 - RGBA 888 */
-               var->red.offset = 16;
-               var->red.length = 8;
-               var->green.offset = 8;
-               var->green.length = 8;
-               var->blue.offset = 0;
-               var->blue.length = 8;
-               var->transp.offset = 24;
-               var->transp.length = 8;
-               break;
-       default:
-               return -EINVAL;
-       }
-       var->bits_per_pixel = bpp;
-       var->red.msb_right = 0;
-       var->green.msb_right = 0;
-       var->blue.msb_right = 0;
-       var->transp.msb_right = 0;
-       return 0;
-}
-
 static int sh_mobile_lcdc_suspend(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
@@ -1316,47 +1309,20 @@ static int sh_mobile_lcdc_resume(struct device *dev)
 static int sh_mobile_lcdc_runtime_suspend(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
-       struct sh_mobile_lcdc_priv *p = platform_get_drvdata(pdev);
-       struct sh_mobile_lcdc_chan *ch;
-       int k, n;
-
-       /* save per-channel registers */
-       for (k = 0; k < ARRAY_SIZE(p->ch); k++) {
-               ch = &p->ch[k];
-               if (!ch->enabled)
-                       continue;
-               for (n = 0; n < NR_CH_REGS; n++)
-                       ch->saved_ch_regs[n] = lcdc_read_chan(ch, n);
-       }
-
-       /* save shared registers */
-       for (n = 0; n < NR_SHARED_REGS; n++)
-               p->saved_shared_regs[n] = lcdc_read(p, lcdc_shared_regs[n]);
+       struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
 
        /* turn off LCDC hardware */
-       lcdc_write(p, _LDCNT1R, 0);
+       lcdc_write(priv, _LDCNT1R, 0);
+
        return 0;
 }
 
 static int sh_mobile_lcdc_runtime_resume(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
-       struct sh_mobile_lcdc_priv *p = platform_get_drvdata(pdev);
-       struct sh_mobile_lcdc_chan *ch;
-       int k, n;
-
-       /* restore per-channel registers */
-       for (k = 0; k < ARRAY_SIZE(p->ch); k++) {
-               ch = &p->ch[k];
-               if (!ch->enabled)
-                       continue;
-               for (n = 0; n < NR_CH_REGS; n++)
-                       lcdc_write_chan(ch, n, ch->saved_ch_regs[n]);
-       }
+       struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
 
-       /* restore shared registers */
-       for (n = 0; n < NR_SHARED_REGS; n++)
-               lcdc_write(p, lcdc_shared_regs[n], p->saved_shared_regs[n]);
+       __sh_mobile_lcdc_start(priv);
 
        return 0;
 }
@@ -1408,17 +1374,187 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb,
        return NOTIFY_OK;
 }
 
-static int sh_mobile_lcdc_remove(struct platform_device *pdev);
+static int sh_mobile_lcdc_remove(struct platform_device *pdev)
+{
+       struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
+       struct fb_info *info;
+       int i;
 
-static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
+       fb_unregister_client(&priv->notifier);
+
+       for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
+               if (priv->ch[i].info && priv->ch[i].info->dev)
+                       unregister_framebuffer(priv->ch[i].info);
+
+       sh_mobile_lcdc_stop(priv);
+
+       for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
+               info = priv->ch[i].info;
+
+               if (!info || !info->device)
+                       continue;
+
+               if (priv->ch[i].sglist)
+                       vfree(priv->ch[i].sglist);
+
+               if (info->screen_base)
+                       dma_free_coherent(&pdev->dev, info->fix.smem_len,
+                                         info->screen_base,
+                                         priv->ch[i].dma_handle);
+               fb_dealloc_cmap(&info->cmap);
+               framebuffer_release(info);
+       }
+
+       for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
+               if (priv->ch[i].bl)
+                       sh_mobile_lcdc_bl_remove(priv->ch[i].bl);
+       }
+
+       if (priv->dot_clk)
+               clk_put(priv->dot_clk);
+
+       if (priv->dev)
+               pm_runtime_disable(priv->dev);
+
+       if (priv->base)
+               iounmap(priv->base);
+
+       if (priv->irq)
+               free_irq(priv->irq, priv);
+       kfree(priv);
+       return 0;
+}
+
+static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
+                                                struct device *dev)
 {
+       struct sh_mobile_lcdc_chan_cfg *cfg = &ch->cfg;
+       const struct fb_videomode *max_mode;
+       const struct fb_videomode *mode;
+       struct fb_var_screeninfo *var;
        struct fb_info *info;
-       struct sh_mobile_lcdc_priv *priv;
+       unsigned int max_size;
+       int num_cfg;
+       void *buf;
+       int ret;
+       int i;
+
+       mutex_init(&ch->open_lock);
+
+       /* Allocate the frame buffer device. */
+       ch->info = framebuffer_alloc(0, dev);
+       if (!ch->info) {
+               dev_err(dev, "unable to allocate fb_info\n");
+               return -ENOMEM;
+       }
+
+       info = ch->info;
+       info->fbops = &sh_mobile_lcdc_ops;
+       info->par = ch;
+       info->pseudo_palette = &ch->pseudo_palette;
+       info->flags = FBINFO_FLAG_DEFAULT;
+
+       /* Iterate through the modes to validate them and find the highest
+        * resolution.
+        */
+       max_mode = NULL;
+       max_size = 0;
+
+       for (i = 0, mode = cfg->lcd_cfg; i < cfg->num_cfg; i++, mode++) {
+               unsigned int size = mode->yres * mode->xres;
+
+               /* NV12 buffers must have even number of lines */
+               if ((cfg->nonstd) && cfg->bpp == 12 &&
+                               (mode->yres & 0x1)) {
+                       dev_err(dev, "yres must be multiple of 2 for YCbCr420 "
+                               "mode.\n");
+                       return -EINVAL;
+               }
+
+               if (size > max_size) {
+                       max_mode = mode;
+                       max_size = size;
+               }
+       }
+
+       if (!max_size)
+               max_size = MAX_XRES * MAX_YRES;
+       else
+               dev_dbg(dev, "Found largest videomode %ux%u\n",
+                       max_mode->xres, max_mode->yres);
+
+       /* Initialize fixed screen information. Restrict pan to 2 lines steps
+        * for NV12.
+        */
+       info->fix = sh_mobile_lcdc_fix;
+       info->fix.smem_len = max_size * 2 * cfg->bpp / 8;
+       if (cfg->nonstd && cfg->bpp == 12)
+               info->fix.ypanstep = 2;
+
+       /* Create the mode list. */
+       if (cfg->lcd_cfg == NULL) {
+               mode = &default_720p;
+               num_cfg = 1;
+       } else {
+               mode = cfg->lcd_cfg;
+               num_cfg = cfg->num_cfg;
+       }
+
+       fb_videomode_to_modelist(mode, num_cfg, &info->modelist);
+
+       /* Initialize variable screen information using the first mode as
+        * default. The default Y virtual resolution is twice the panel size to
+        * allow for double-buffering.
+        */
+       var = &info->var;
+       fb_videomode_to_var(var, mode);
+       var->bits_per_pixel = cfg->bpp;
+       var->width = cfg->lcd_size_cfg.width;
+       var->height = cfg->lcd_size_cfg.height;
+       var->yres_virtual = var->yres * 2;
+       var->activate = FB_ACTIVATE_NOW;
+
+       ret = sh_mobile_check_var(var, info);
+       if (ret)
+               return ret;
+
+       /* Allocate frame buffer memory and color map. */
+       buf = dma_alloc_coherent(dev, info->fix.smem_len, &ch->dma_handle,
+                                GFP_KERNEL);
+       if (!buf) {
+               dev_err(dev, "unable to allocate buffer\n");
+               return -ENOMEM;
+       }
+
+       ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
+       if (ret < 0) {
+               dev_err(dev, "unable to allocate cmap\n");
+               dma_free_coherent(dev, info->fix.smem_len,
+                                 buf, ch->dma_handle);
+               return ret;
+       }
+
+       info->fix.smem_start = ch->dma_handle;
+       if (var->nonstd)
+               info->fix.line_length = var->xres;
+       else
+               info->fix.line_length = var->xres * (cfg->bpp / 8);
+
+       info->screen_base = buf;
+       info->device = dev;
+       ch->display_var = *var;
+
+       return 0;
+}
+
+static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
+{
        struct sh_mobile_lcdc_info *pdata = pdev->dev.platform_data;
+       struct sh_mobile_lcdc_priv *priv;
        struct resource *res;
+       int num_channels;
        int error;
-       void *buf;
-       int i, j;
+       int i;
 
        if (!pdata) {
                dev_err(&pdev->dev, "no platform data defined\n");
@@ -1440,7 +1576,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, priv);
 
-       error = request_irq(i, sh_mobile_lcdc_irq, IRQF_DISABLED,
+       error = request_irq(i, sh_mobile_lcdc_irq, 0,
                            dev_name(&pdev->dev), priv);
        if (error) {
                dev_err(&pdev->dev, "unable to request irq\n");
@@ -1450,9 +1586,8 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
        priv->irq = i;
        atomic_set(&priv->hw_usecnt, -1);
 
-       j = 0;
-       for (i = 0; i < ARRAY_SIZE(pdata->ch); i++) {
-               struct sh_mobile_lcdc_chan *ch = priv->ch + j;
+       for (i = 0, num_channels = 0; i < ARRAY_SIZE(pdata->ch); i++) {
+               struct sh_mobile_lcdc_chan *ch = priv->ch + num_channels;
 
                ch->lcdc = priv;
                memcpy(&ch->cfg, &pdata->ch[i], sizeof(pdata->ch[i]));
@@ -1472,26 +1607,26 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
 
                switch (pdata->ch[i].chan) {
                case LCDC_CHAN_MAINLCD:
-                       ch->enabled = 1 << 1;
+                       ch->enabled = LDCNT2R_ME;
                        ch->reg_offs = lcdc_offs_mainlcd;
-                       j++;
+                       num_channels++;
                        break;
                case LCDC_CHAN_SUBLCD:
-                       ch->enabled = 1 << 2;
+                       ch->enabled = LDCNT2R_SE;
                        ch->reg_offs = lcdc_offs_sublcd;
-                       j++;
+                       num_channels++;
                        break;
                }
        }
 
-       if (!j) {
+       if (!num_channels) {
                dev_err(&pdev->dev, "no channels defined\n");
                error = -EINVAL;
                goto err1;
        }
 
        /* for dual channel LCDC (MAIN + SUB) force shared bpp setting */
-       if (j == 2)
+       if (num_channels == 2)
                priv->forced_bpp = pdata->ch[0].bpp;
 
        priv->base = ioremap_nocache(res->start, resource_size(res));
@@ -1506,125 +1641,23 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
 
        priv->meram_dev = pdata->meram_dev;
 
-       for (i = 0; i < j; i++) {
-               struct fb_var_screeninfo *var;
-               const struct fb_videomode *lcd_cfg, *max_cfg = NULL;
+       for (i = 0; i < num_channels; i++) {
                struct sh_mobile_lcdc_chan *ch = priv->ch + i;
-               struct sh_mobile_lcdc_chan_cfg *cfg = &ch->cfg;
-               const struct fb_videomode *mode = cfg->lcd_cfg;
-               unsigned long max_size = 0;
-               int k;
-               int num_cfg;
-
-               ch->info = framebuffer_alloc(0, &pdev->dev);
-               if (!ch->info) {
-                       dev_err(&pdev->dev, "unable to allocate fb_info\n");
-                       error = -ENOMEM;
-                       break;
-               }
-
-               info = ch->info;
-               var = &info->var;
-               info->fbops = &sh_mobile_lcdc_ops;
-               info->par = ch;
-
-               mutex_init(&ch->open_lock);
-
-               for (k = 0, lcd_cfg = mode;
-                    k < cfg->num_cfg && lcd_cfg;
-                    k++, lcd_cfg++) {
-                       unsigned long size = lcd_cfg->yres * lcd_cfg->xres;
-                       /* NV12 buffers must have even number of lines */
-                       if ((cfg->nonstd) && cfg->bpp == 12 &&
-                                       (lcd_cfg->yres & 0x1)) {
-                               dev_err(&pdev->dev, "yres must be multiple of 2"
-                                               " for YCbCr420 mode.\n");
-                               error = -EINVAL;
-                               goto err1;
-                       }
-
-                       if (size > max_size) {
-                               max_cfg = lcd_cfg;
-                               max_size = size;
-                       }
-               }
-
-               if (!mode)
-                       max_size = MAX_XRES * MAX_YRES;
-               else if (max_cfg)
-                       dev_dbg(&pdev->dev, "Found largest videomode %ux%u\n",
-                               max_cfg->xres, max_cfg->yres);
 
-               info->fix = sh_mobile_lcdc_fix;
-               info->fix.smem_len = max_size * 2 * cfg->bpp / 8;
-
-                /* Only pan in 2 line steps for NV12 */
-               if (cfg->nonstd && cfg->bpp == 12)
-                       info->fix.ypanstep = 2;
-
-               if (!mode) {
-                       mode = &default_720p;
-                       num_cfg = 1;
-               } else {
-                       num_cfg = cfg->num_cfg;
-               }
-
-               fb_videomode_to_modelist(mode, num_cfg, &info->modelist);
-
-               fb_videomode_to_var(var, mode);
-               var->width = cfg->lcd_size_cfg.width;
-               var->height = cfg->lcd_size_cfg.height;
-               /* Default Y virtual resolution is 2x panel size */
-               var->yres_virtual = var->yres * 2;
-               var->activate = FB_ACTIVATE_NOW;
-
-               error = sh_mobile_lcdc_set_bpp(var, cfg->bpp, cfg->nonstd);
+               error = sh_mobile_lcdc_channel_init(ch, &pdev->dev);
                if (error)
-                       break;
-
-               buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len,
-                                        &ch->dma_handle, GFP_KERNEL);
-               if (!buf) {
-                       dev_err(&pdev->dev, "unable to allocate buffer\n");
-                       error = -ENOMEM;
-                       break;
-               }
-
-               info->pseudo_palette = &ch->pseudo_palette;
-               info->flags = FBINFO_FLAG_DEFAULT;
-
-               error = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
-               if (error < 0) {
-                       dev_err(&pdev->dev, "unable to allocate cmap\n");
-                       dma_free_coherent(&pdev->dev, info->fix.smem_len,
-                                         buf, ch->dma_handle);
-                       break;
-               }
-
-               info->fix.smem_start = ch->dma_handle;
-               if (var->nonstd)
-                       info->fix.line_length = var->xres;
-               else
-                       info->fix.line_length = var->xres * (cfg->bpp / 8);
-
-               info->screen_base = buf;
-               info->device = &pdev->dev;
-               ch->display_var = *var;
+                       goto err1;
        }
 
-       if (error)
-               goto err1;
-
        error = sh_mobile_lcdc_start(priv);
        if (error) {
                dev_err(&pdev->dev, "unable to start hardware\n");
                goto err1;
        }
 
-       for (i = 0; i < j; i++) {
+       for (i = 0; i < num_channels; i++) {
                struct sh_mobile_lcdc_chan *ch = priv->ch + i;
-
-               info = ch->info;
+               struct fb_info *info = ch->info;
 
                if (info->fbdefio) {
                        ch->sglist = vmalloc(sizeof(struct scatterlist) *
@@ -1665,57 +1698,6 @@ err1:
        return error;
 }
 
-static int sh_mobile_lcdc_remove(struct platform_device *pdev)
-{
-       struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
-       struct fb_info *info;
-       int i;
-
-       fb_unregister_client(&priv->notifier);
-
-       for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
-               if (priv->ch[i].info && priv->ch[i].info->dev)
-                       unregister_framebuffer(priv->ch[i].info);
-
-       sh_mobile_lcdc_stop(priv);
-
-       for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
-               info = priv->ch[i].info;
-
-               if (!info || !info->device)
-                       continue;
-
-               if (priv->ch[i].sglist)
-                       vfree(priv->ch[i].sglist);
-
-               if (info->screen_base)
-                       dma_free_coherent(&pdev->dev, info->fix.smem_len,
-                                         info->screen_base,
-                                         priv->ch[i].dma_handle);
-               fb_dealloc_cmap(&info->cmap);
-               framebuffer_release(info);
-       }
-
-       for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
-               if (priv->ch[i].bl)
-                       sh_mobile_lcdc_bl_remove(priv->ch[i].bl);
-       }
-
-       if (priv->dot_clk)
-               clk_put(priv->dot_clk);
-
-       if (priv->dev)
-               pm_runtime_disable(priv->dev);
-
-       if (priv->base)
-               iounmap(priv->base);
-
-       if (priv->irq)
-               free_irq(priv->irq, priv);
-       kfree(priv);
-       return 0;
-}
-
 static struct platform_driver sh_mobile_lcdc_driver = {
        .driver         = {
                .name           = "sh_mobile_lcdc_fb",
index aeed668..a58a0f3 100644 (file)
@@ -18,6 +18,13 @@ struct sh_mobile_lcdc_priv;
 struct fb_info;
 struct backlight_device;
 
+/*
+ * struct sh_mobile_lcdc_chan - LCDC display channel
+ *
+ * @base_addr_y: Frame buffer viewport base address (luma component)
+ * @base_addr_c: Frame buffer viewport base address (chroma component)
+ * @pitch: Frame buffer line pitch
+ */
 struct sh_mobile_lcdc_chan {
        struct sh_mobile_lcdc_priv *lcdc;
        unsigned long *reg_offs;
@@ -25,7 +32,6 @@ struct sh_mobile_lcdc_chan {
        unsigned long enabled; /* ME and SE in LDCNT2R */
        struct sh_mobile_lcdc_chan_cfg cfg;
        u32 pseudo_palette[PALETTE_NR];
-       unsigned long saved_ch_regs[NR_CH_REGS];
        struct fb_info *info;
        struct backlight_device *bl;
        dma_addr_t dma_handle;
@@ -40,6 +46,10 @@ struct sh_mobile_lcdc_chan {
        int blank_status;
        struct mutex open_lock;         /* protects the use counter */
        int meram_enabled;
+
+       unsigned long base_addr_y;
+       unsigned long base_addr_c;
+       unsigned int pitch;
 };
 
 #endif
index cc7d732..4d63490 100644 (file)
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/device.h>
+#include <linux/pm_runtime.h>
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
-
-#include "sh_mobile_meram.h"
+#include <video/sh_mobile_meram.h>
 
 /* meram registers */
-#define MExxCTL 0x0
-#define MExxBSIZE 0x4
-#define MExxMNCF 0x8
-#define MExxSARA 0x10
-#define MExxSARB 0x14
-#define MExxSBSIZE 0x18
-
-#define MERAM_MExxCTL_VAL(ctl, next_icb, addr) \
-       ((ctl) | (((next_icb) & 0x1f) << 11) | (((addr) & 0x7ff) << 16))
-#define        MERAM_MExxBSIZE_VAL(a, b, c) \
-       (((a) << 28) | ((b) << 16) | (c))
-
-#define MEVCR1 0x4
-#define MEACTS 0x10
-#define MEQSEL1 0x40
-#define MEQSEL2 0x44
+#define MEVCR1                 0x4
+#define MEVCR1_RST             (1 << 31)
+#define MEVCR1_WD              (1 << 30)
+#define MEVCR1_AMD1            (1 << 29)
+#define MEVCR1_AMD0            (1 << 28)
+#define MEQSEL1                        0x40
+#define MEQSEL2                        0x44
+
+#define MExxCTL                        0x400
+#define MExxCTL_BV             (1 << 31)
+#define MExxCTL_BSZ_SHIFT      28
+#define MExxCTL_MSAR_MASK      (0x7ff << MExxCTL_MSAR_SHIFT)
+#define MExxCTL_MSAR_SHIFT     16
+#define MExxCTL_NXT_MASK       (0x1f << MExxCTL_NXT_SHIFT)
+#define MExxCTL_NXT_SHIFT      11
+#define MExxCTL_WD1            (1 << 10)
+#define MExxCTL_WD0            (1 << 9)
+#define MExxCTL_WS             (1 << 8)
+#define MExxCTL_CB             (1 << 7)
+#define MExxCTL_WBF            (1 << 6)
+#define MExxCTL_WF             (1 << 5)
+#define MExxCTL_RF             (1 << 4)
+#define MExxCTL_CM             (1 << 3)
+#define MExxCTL_MD_READ                (1 << 0)
+#define MExxCTL_MD_WRITE       (2 << 0)
+#define MExxCTL_MD_ICB_WB      (3 << 0)
+#define MExxCTL_MD_ICB         (4 << 0)
+#define MExxCTL_MD_FB          (7 << 0)
+#define MExxCTL_MD_MASK                (7 << 0)
+#define MExxBSIZE              0x404
+#define MExxBSIZE_RCNT_SHIFT   28
+#define MExxBSIZE_YSZM1_SHIFT  16
+#define MExxBSIZE_XSZM1_SHIFT  0
+#define MExxMNCF               0x408
+#define MExxMNCF_KWBNM_SHIFT   28
+#define MExxMNCF_KRBNM_SHIFT   24
+#define MExxMNCF_BNM_SHIFT     16
+#define MExxMNCF_XBV           (1 << 15)
+#define MExxMNCF_CPL_YCBCR444  (1 << 12)
+#define MExxMNCF_CPL_YCBCR420  (2 << 12)
+#define MExxMNCF_CPL_YCBCR422  (3 << 12)
+#define MExxMNCF_CPL_MSK       (3 << 12)
+#define MExxMNCF_BL            (1 << 2)
+#define MExxMNCF_LNM_SHIFT     0
+#define MExxSARA               0x410
+#define MExxSARB               0x414
+#define MExxSBSIZE             0x418
+#define MExxSBSIZE_HDV         (1 << 31)
+#define MExxSBSIZE_HSZ16       (0 << 28)
+#define MExxSBSIZE_HSZ32       (1 << 28)
+#define MExxSBSIZE_HSZ64       (2 << 28)
+#define MExxSBSIZE_HSZ128      (3 << 28)
+#define MExxSBSIZE_SBSIZZ_SHIFT        0
+
+#define MERAM_MExxCTL_VAL(next, addr)  \
+       ((((next) << MExxCTL_NXT_SHIFT) & MExxCTL_NXT_MASK) | \
+        (((addr) << MExxCTL_MSAR_SHIFT) & MExxCTL_MSAR_MASK))
+#define        MERAM_MExxBSIZE_VAL(rcnt, yszm1, xszm1) \
+       (((rcnt) << MExxBSIZE_RCNT_SHIFT) | \
+        ((yszm1) << MExxBSIZE_YSZM1_SHIFT) | \
+        ((xszm1) << MExxBSIZE_XSZM1_SHIFT))
+
+#define SH_MOBILE_MERAM_ICB_NUM                32
+
+static unsigned long common_regs[] = {
+       MEVCR1,
+       MEQSEL1,
+       MEQSEL2,
+};
+#define CMN_REGS_SIZE ARRAY_SIZE(common_regs)
+
+static unsigned long icb_regs[] = {
+       MExxCTL,
+       MExxBSIZE,
+       MExxMNCF,
+       MExxSARA,
+       MExxSARB,
+       MExxSBSIZE,
+};
+#define ICB_REGS_SIZE ARRAY_SIZE(icb_regs)
+
+struct sh_mobile_meram_priv {
+       void __iomem    *base;
+       struct mutex    lock;
+       unsigned long   used_icb;
+       int             used_meram_cache_regions;
+       unsigned long   used_meram_cache[SH_MOBILE_MERAM_ICB_NUM];
+       unsigned long   cmn_saved_regs[CMN_REGS_SIZE];
+       unsigned long   icb_saved_regs[ICB_REGS_SIZE * SH_MOBILE_MERAM_ICB_NUM];
+};
 
 /* settings */
 #define MERAM_SEC_LINE 15
  * MERAM/ICB access functions
  */
 
-#define MERAM_ICB_OFFSET(base, idx, off)       \
-       ((base) + (0x400 + ((idx) * 0x20) + (off)))
+#define MERAM_ICB_OFFSET(base, idx, off)       ((base) + (off) + (idx) * 0x20)
 
 static inline void meram_write_icb(void __iomem *base, int idx, int off,
        unsigned long val)
@@ -280,17 +353,18 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
        /*
         * Set MERAM for framebuffer
         *
-        * 0x70f:  WD = 0x3, WS=0x1, CM=0x1, MD=FB mode
         * we also chain the cache_icb and the marker_icb.
         * we also split the allocated MERAM buffer between two ICBs.
         */
        meram_write_icb(priv->base, icb->cache_icb, MExxCTL,
-                       MERAM_MExxCTL_VAL(0x70f, icb->marker_icb,
-                                         icb->meram_offset));
+                       MERAM_MExxCTL_VAL(icb->marker_icb, icb->meram_offset) |
+                       MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM |
+                       MExxCTL_MD_FB);
        meram_write_icb(priv->base, icb->marker_icb, MExxCTL,
-                       MERAM_MExxCTL_VAL(0x70f, icb->cache_icb,
-                                         icb->meram_offset +
-                                         icb->meram_size / 2));
+                       MERAM_MExxCTL_VAL(icb->cache_icb, icb->meram_offset +
+                                         icb->meram_size / 2) |
+                       MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM |
+                       MExxCTL_MD_FB);
 
        return 0;
 }
@@ -299,8 +373,10 @@ static void meram_deinit(struct sh_mobile_meram_priv *priv,
                        struct sh_mobile_meram_icb *icb)
 {
        /* disable ICB */
-       meram_write_icb(priv->base, icb->cache_icb,  MExxCTL, 0);
-       meram_write_icb(priv->base, icb->marker_icb, MExxCTL, 0);
+       meram_write_icb(priv->base, icb->cache_icb,  MExxCTL,
+                       MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF);
+       meram_write_icb(priv->base, icb->marker_icb, MExxCTL,
+                       MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF);
        icb->cache_unit = 0;
 }
 
@@ -337,24 +413,22 @@ static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
                xres, yres, (!pixelformat) ? "yuv" : "rgb",
                base_addr_y, base_addr_c);
 
-       mutex_lock(&priv->lock);
-
        /* we can't handle wider than 8192px */
        if (xres > 8192) {
                dev_err(&pdev->dev, "width exceeding the limit (> 8192).");
-               error = -EINVAL;
-               goto err;
-       }
-
-       if (priv->used_meram_cache_regions + 2 > SH_MOBILE_MERAM_ICB_NUM) {
-               dev_err(&pdev->dev, "no more ICB available.");
-               error = -EINVAL;
-               goto err;
+               return -EINVAL;
        }
 
        /* do we have at least one ICB config? */
        if (cfg->icb[0].marker_icb < 0 || cfg->icb[0].cache_icb < 0) {
                dev_err(&pdev->dev, "at least one ICB is required.");
+               return -EINVAL;
+       }
+
+       mutex_lock(&priv->lock);
+
+       if (priv->used_meram_cache_regions + 2 > SH_MOBILE_MERAM_ICB_NUM) {
+               dev_err(&pdev->dev, "no more ICB available.");
                error = -EINVAL;
                goto err;
        }
@@ -460,6 +534,57 @@ static int sh_mobile_meram_update(struct sh_mobile_meram_info *pdata,
        return 0;
 }
 
+static int sh_mobile_meram_runtime_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
+       int k, j;
+
+       for (k = 0; k < CMN_REGS_SIZE; k++)
+               priv->cmn_saved_regs[k] = meram_read_reg(priv->base,
+                       common_regs[k]);
+
+       for (j = 0; j < 32; j++) {
+               if (!test_bit(j, &priv->used_icb))
+                       continue;
+               for (k = 0; k < ICB_REGS_SIZE; k++) {
+                       priv->icb_saved_regs[j * ICB_REGS_SIZE + k] =
+                               meram_read_icb(priv->base, j, icb_regs[k]);
+                       /* Reset ICB on resume */
+                       if (icb_regs[k] == MExxCTL)
+                               priv->icb_saved_regs[j * ICB_REGS_SIZE + k] |=
+                                       MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF;
+               }
+       }
+       return 0;
+}
+
+static int sh_mobile_meram_runtime_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
+       int k, j;
+
+       for (j = 0; j < 32; j++) {
+               if (!test_bit(j, &priv->used_icb))
+                       continue;
+               for (k = 0; k < ICB_REGS_SIZE; k++) {
+                       meram_write_icb(priv->base, j, icb_regs[k],
+                       priv->icb_saved_regs[j * ICB_REGS_SIZE + k]);
+               }
+       }
+
+       for (k = 0; k < CMN_REGS_SIZE; k++)
+               meram_write_reg(priv->base, common_regs[k],
+                       priv->cmn_saved_regs[k]);
+       return 0;
+}
+
+static const struct dev_pm_ops sh_mobile_meram_dev_pm_ops = {
+       .runtime_suspend = sh_mobile_meram_runtime_suspend,
+       .runtime_resume = sh_mobile_meram_runtime_resume,
+};
+
 static struct sh_mobile_meram_ops sh_mobile_meram_ops = {
        .module                 = THIS_MODULE,
        .meram_register         = sh_mobile_meram_register,
@@ -513,7 +638,9 @@ static int __devinit sh_mobile_meram_probe(struct platform_device *pdev)
 
        /* initialize ICB addressing mode */
        if (pdata->addr_mode == SH_MOBILE_MERAM_MODE1)
-               meram_write_reg(priv->base, MEVCR1, 1 << 29);
+               meram_write_reg(priv->base, MEVCR1, MEVCR1_AMD1);
+
+       pm_runtime_enable(&pdev->dev);
 
        dev_info(&pdev->dev, "sh_mobile_meram initialized.");
 
@@ -530,6 +657,8 @@ static int sh_mobile_meram_remove(struct platform_device *pdev)
 {
        struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
 
+       pm_runtime_disable(&pdev->dev);
+
        if (priv->base)
                iounmap(priv->base);
 
@@ -544,6 +673,7 @@ static struct platform_driver sh_mobile_meram_driver = {
        .driver = {
                .name           = "sh_mobile_meram",
                .owner          = THIS_MODULE,
+               .pm             = &sh_mobile_meram_dev_pm_ops,
        },
        .probe          = sh_mobile_meram_probe,
        .remove         = sh_mobile_meram_remove,
diff --git a/drivers/video/sh_mobile_meram.h b/drivers/video/sh_mobile_meram.h
deleted file mode 100644 (file)
index 82c54fb..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef __sh_mobile_meram_h__
-#define __sh_mobile_meram_h__
-
-#include <linux/mutex.h>
-#include <video/sh_mobile_meram.h>
-
-/*
- * MERAM private
- */
-
-#define MERAM_ICB_Y 0x1
-#define MERAM_ICB_C 0x2
-
-/* MERAM cache size */
-#define SH_MOBILE_MERAM_ICB_NUM                32
-
-#define SH_MOBILE_MERAM_CACHE_OFFSET(p)        ((p) >> 16)
-#define SH_MOBILE_MERAM_CACHE_SIZE(p)  ((p) & 0xffff)
-
-struct sh_mobile_meram_priv {
-       void __iomem    *base;
-       struct mutex    lock;
-       unsigned long   used_icb;
-       int             used_meram_cache_regions;
-       unsigned long   used_meram_cache[SH_MOBILE_MERAM_ICB_NUM];
-};
-
-int sh_mobile_meram_alloc_icb(const struct sh_mobile_meram_cfg *cfg,
-                  int xres,
-                  int yres,
-                  unsigned int base_addr,
-                  int yuv_mode,
-                  int *marker_icb,
-                  int *out_pitch);
-
-void sh_mobile_meram_free_icb(int marker_icb);
-
-#define SH_MOBILE_MERAM_START(ind, ab) \
-       (0xC0000000 | ((ab & 0x1) << 23) | ((ind & 0x1F) << 24))
-
-#endif /* !__sh_mobile_meram_h__ */
index 7525984..078ca21 100644 (file)
@@ -1333,19 +1333,14 @@ sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
 }
 
 static int
-sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
+sisfb_pan_var(struct sis_video_info *ivideo, struct fb_info *info,
+             struct fb_var_screeninfo *var)
 {
-       if(var->xoffset > (var->xres_virtual - var->xres)) {
-               return -EINVAL;
-       }
-       if(var->yoffset > (var->yres_virtual - var->yres)) {
-               return -EINVAL;
-       }
-
-       ivideo->current_base = (var->yoffset * var->xres_virtual) + var->xoffset;
+       ivideo->current_base = var->yoffset * info->var.xres_virtual
+                            + var->xoffset;
 
        /* calculate base bpp dep. */
-       switch(var->bits_per_pixel) {
+       switch (info->var.bits_per_pixel) {
        case 32:
                break;
        case 16:
@@ -1635,20 +1630,15 @@ sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
        struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
        int err;
 
-       if(var->xoffset > (var->xres_virtual - var->xres))
-               return -EINVAL;
-
-       if(var->yoffset > (var->yres_virtual - var->yres))
-               return -EINVAL;
-
-       if(var->vmode & FB_VMODE_YWRAP)
+       if (var->vmode & FB_VMODE_YWRAP)
                return -EINVAL;
 
-       if(var->xoffset + info->var.xres > info->var.xres_virtual ||
-          var->yoffset + info->var.yres > info->var.yres_virtual)
+       if (var->xoffset + info->var.xres > info->var.xres_virtual ||
+           var->yoffset + info->var.yres > info->var.yres_virtual)
                return -EINVAL;
 
-       if((err = sisfb_pan_var(ivideo, var)) < 0)
+       err = sisfb_pan_var(ivideo, info, var);
+       if (err < 0)
                return err;
 
        info->var.xoffset = var->xoffset;
index 89158bc..30f7a81 100644 (file)
@@ -989,7 +989,7 @@ static struct platform_device *xxxfb_device;
  */
 int __init xxxfb_setup(char *options)
 {
-    /* Parse user speficied options (`video=xxxfb:') */
+    /* Parse user specified options (`video=xxxfb:') */
 }
 #endif /* MODULE */
 
index 6294dca..a78254c 100644 (file)
@@ -582,7 +582,7 @@ static int sm501fb_pan_crt(struct fb_var_screeninfo *var,
 {
        struct sm501fb_par  *par = info->par;
        struct sm501fb_info *fbi = par->info;
-       unsigned int bytes_pixel = var->bits_per_pixel / 8;
+       unsigned int bytes_pixel = info->var.bits_per_pixel / 8;
        unsigned long reg;
        unsigned long xoffs;
 
@@ -614,10 +614,10 @@ static int sm501fb_pan_pnl(struct fb_var_screeninfo *var,
        struct sm501fb_info *fbi = par->info;
        unsigned long reg;
 
-       reg = var->xoffset | (var->xres_virtual << 16);
+       reg = var->xoffset | (info->var.xres_virtual << 16);
        smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH);
 
-       reg = var->yoffset | (var->yres_virtual << 16);
+       reg = var->yoffset | (info->var.yres_virtual << 16);
        smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT);
 
        sm501fb_sync_regs(fbi);
diff --git a/drivers/video/smscufx.c b/drivers/video/smscufx.c
new file mode 100644 (file)
index 0000000..aaccffa
--- /dev/null
@@ -0,0 +1,1994 @@
+/*
+ * smscufx.c -- Framebuffer driver for SMSC UFX USB controller
+ *
+ * Copyright (C) 2011 Steve Glendinning <steve.glendinning@smsc.com>
+ * Copyright (C) 2009 Roberto De Ioris <roberto@unbit.it>
+ * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com>
+ * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License v2. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * Based on udlfb, with work from Florian Echtler, Henrik Bjerregaard Pedersen,
+ * and others.
+ *
+ * Works well with Bernie Thompson's X DAMAGE patch to xf86-video-fbdev
+ * available from http://git.plugable.com
+ *
+ * Layout is based on skeletonfb by James Simmons and Geert Uytterhoeven,
+ * usb-skeleton by GregKH.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <linux/uaccess.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "edid.h"
+
+#define check_warn(status, fmt, args...) \
+       ({ if (status < 0) pr_warn(fmt, ##args); })
+
+#define check_warn_return(status, fmt, args...) \
+       ({ if (status < 0) { pr_warn(fmt, ##args); return status; } })
+
+#define check_warn_goto_error(status, fmt, args...) \
+       ({ if (status < 0) { pr_warn(fmt, ##args); goto error; } })
+
+#define all_bits_set(x, bits) (((x) & (bits)) == (bits))
+
+#define USB_VENDOR_REQUEST_WRITE_REGISTER      0xA0
+#define USB_VENDOR_REQUEST_READ_REGISTER       0xA1
+
+/*
+ * TODO: Propose standard fb.h ioctl for reporting damage,
+ * using _IOWR() and one of the existing area structs from fb.h
+ * Consider these ioctls deprecated, but they're still used by the
+ * DisplayLink X server as yet - need both to be modified in tandem
+ * when new ioctl(s) are ready.
+ */
+#define UFX_IOCTL_RETURN_EDID  (0xAD)
+#define UFX_IOCTL_REPORT_DAMAGE        (0xAA)
+
+/* -BULK_SIZE as per usb-skeleton. Can we get full page and avoid overhead? */
+#define BULK_SIZE              (512)
+#define MAX_TRANSFER           (PAGE_SIZE*16 - BULK_SIZE)
+#define WRITES_IN_FLIGHT       (4)
+
+#define GET_URB_TIMEOUT                (HZ)
+#define FREE_URB_TIMEOUT       (HZ*2)
+
+#define BPP                    2
+
+#define UFX_DEFIO_WRITE_DELAY  5 /* fb_deferred_io.delay in jiffies */
+#define UFX_DEFIO_WRITE_DISABLE        (HZ*60) /* "disable" with long delay */
+
+struct dloarea {
+       int x, y;
+       int w, h;
+};
+
+struct urb_node {
+       struct list_head entry;
+       struct ufx_data *dev;
+       struct delayed_work release_urb_work;
+       struct urb *urb;
+};
+
+struct urb_list {
+       struct list_head list;
+       spinlock_t lock;
+       struct semaphore limit_sem;
+       int available;
+       int count;
+       size_t size;
+};
+
+struct ufx_data {
+       struct usb_device *udev;
+       struct device *gdev; /* &udev->dev */
+       struct fb_info *info;
+       struct urb_list urbs;
+       struct kref kref;
+       int fb_count;
+       bool virtualized; /* true when physical usb device not present */
+       struct delayed_work free_framebuffer_work;
+       atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */
+       atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */
+       u8 *edid; /* null until we read edid from hw or get from sysfs */
+       size_t edid_size;
+       u32 pseudo_palette[256];
+};
+
+static struct fb_fix_screeninfo ufx_fix = {
+       .id =           "smscufx",
+       .type =         FB_TYPE_PACKED_PIXELS,
+       .visual =       FB_VISUAL_TRUECOLOR,
+       .xpanstep =     0,
+       .ypanstep =     0,
+       .ywrapstep =    0,
+       .accel =        FB_ACCEL_NONE,
+};
+
+static const u32 smscufx_info_flags = FBINFO_DEFAULT | FBINFO_READS_FAST |
+       FBINFO_VIRTFB | FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT |
+       FBINFO_HWACCEL_COPYAREA | FBINFO_MISC_ALWAYS_SETPAR;
+
+static struct usb_device_id id_table[] = {
+       {USB_DEVICE(0x0424, 0x9d00),},
+       {USB_DEVICE(0x0424, 0x9d01),},
+       {},
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+/* module options */
+static int console;   /* Optionally allow fbcon to consume first framebuffer */
+static int fb_defio = true;  /* Optionally enable fb_defio mmap support */
+
+/* ufx keeps a list of urbs for efficient bulk transfers */
+static void ufx_urb_completion(struct urb *urb);
+static struct urb *ufx_get_urb(struct ufx_data *dev);
+static int ufx_submit_urb(struct ufx_data *dev, struct urb * urb, size_t len);
+static int ufx_alloc_urb_list(struct ufx_data *dev, int count, size_t size);
+static void ufx_free_urb_list(struct ufx_data *dev);
+
+/* reads a control register */
+static int ufx_reg_read(struct ufx_data *dev, u32 index, u32 *data)
+{
+       u32 *buf = kmalloc(4, GFP_KERNEL);
+       int ret;
+
+       BUG_ON(!dev);
+
+       if (!buf)
+               return -ENOMEM;
+
+       ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
+               USB_VENDOR_REQUEST_READ_REGISTER,
+               USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+               00, index, buf, 4, USB_CTRL_GET_TIMEOUT);
+
+       le32_to_cpus(buf);
+       *data = *buf;
+       kfree(buf);
+
+       if (unlikely(ret < 0))
+               pr_warn("Failed to read register index 0x%08x\n", index);
+
+       return ret;
+}
+
+/* writes a control register */
+static int ufx_reg_write(struct ufx_data *dev, u32 index, u32 data)
+{
+       u32 *buf = kmalloc(4, GFP_KERNEL);
+       int ret;
+
+       BUG_ON(!dev);
+
+       if (!buf)
+               return -ENOMEM;
+
+       *buf = data;
+       cpu_to_le32s(buf);
+
+       ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+               USB_VENDOR_REQUEST_WRITE_REGISTER,
+               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+               00, index, buf, 4, USB_CTRL_SET_TIMEOUT);
+
+       kfree(buf);
+
+       if (unlikely(ret < 0))
+               pr_warn("Failed to write register index 0x%08x with value "
+                       "0x%08x\n", index, data);
+
+       return ret;
+}
+
+static int ufx_reg_clear_and_set_bits(struct ufx_data *dev, u32 index,
+       u32 bits_to_clear, u32 bits_to_set)
+{
+       u32 data;
+       int status = ufx_reg_read(dev, index, &data);
+       check_warn_return(status, "ufx_reg_clear_and_set_bits error reading "
+               "0x%x", index);
+
+       data &= (~bits_to_clear);
+       data |= bits_to_set;
+
+       status = ufx_reg_write(dev, index, data);
+       check_warn_return(status, "ufx_reg_clear_and_set_bits error writing "
+               "0x%x", index);
+
+       return 0;
+}
+
+static int ufx_reg_set_bits(struct ufx_data *dev, u32 index, u32 bits)
+{
+       return ufx_reg_clear_and_set_bits(dev, index, 0, bits);
+}
+
+static int ufx_reg_clear_bits(struct ufx_data *dev, u32 index, u32 bits)
+{
+       return ufx_reg_clear_and_set_bits(dev, index, bits, 0);
+}
+
+static int ufx_lite_reset(struct ufx_data *dev)
+{
+       int status;
+       u32 value;
+
+       status = ufx_reg_write(dev, 0x3008, 0x00000001);
+       check_warn_return(status, "ufx_lite_reset error writing 0x3008");
+
+       status = ufx_reg_read(dev, 0x3008, &value);
+       check_warn_return(status, "ufx_lite_reset error reading 0x3008");
+
+       return (value == 0) ? 0 : -EIO;
+}
+
+/* If display is unblanked, then blank it */
+static int ufx_blank(struct ufx_data *dev, bool wait)
+{
+       u32 dc_ctrl, dc_sts;
+       int i;
+
+       int status = ufx_reg_read(dev, 0x2004, &dc_sts);
+       check_warn_return(status, "ufx_blank error reading 0x2004");
+
+       status = ufx_reg_read(dev, 0x2000, &dc_ctrl);
+       check_warn_return(status, "ufx_blank error reading 0x2000");
+
+       /* return success if display is already blanked */
+       if ((dc_sts & 0x00000100) || (dc_ctrl & 0x00000100))
+               return 0;
+
+       /* request the DC to blank the display */
+       dc_ctrl |= 0x00000100;
+       status = ufx_reg_write(dev, 0x2000, dc_ctrl);
+       check_warn_return(status, "ufx_blank error writing 0x2000");
+
+       /* return success immediately if we don't have to wait */
+       if (!wait)
+               return 0;
+
+       for (i = 0; i < 250; i++) {
+               status = ufx_reg_read(dev, 0x2004, &dc_sts);
+               check_warn_return(status, "ufx_blank error reading 0x2004");
+
+               if (dc_sts & 0x00000100)
+                       return 0;
+       }
+
+       /* timed out waiting for display to blank */
+       return -EIO;
+}
+
+/* If display is blanked, then unblank it */
+static int ufx_unblank(struct ufx_data *dev, bool wait)
+{
+       u32 dc_ctrl, dc_sts;
+       int i;
+
+       int status = ufx_reg_read(dev, 0x2004, &dc_sts);
+       check_warn_return(status, "ufx_unblank error reading 0x2004");
+
+       status = ufx_reg_read(dev, 0x2000, &dc_ctrl);
+       check_warn_return(status, "ufx_unblank error reading 0x2000");
+
+       /* return success if display is already unblanked */
+       if (((dc_sts & 0x00000100) == 0) || ((dc_ctrl & 0x00000100) == 0))
+               return 0;
+
+       /* request the DC to unblank the display */
+       dc_ctrl &= ~0x00000100;
+       status = ufx_reg_write(dev, 0x2000, dc_ctrl);
+       check_warn_return(status, "ufx_unblank error writing 0x2000");
+
+       /* return success immediately if we don't have to wait */
+       if (!wait)
+               return 0;
+
+       for (i = 0; i < 250; i++) {
+               status = ufx_reg_read(dev, 0x2004, &dc_sts);
+               check_warn_return(status, "ufx_unblank error reading 0x2004");
+
+               if ((dc_sts & 0x00000100) == 0)
+                       return 0;
+       }
+
+       /* timed out waiting for display to unblank */
+       return -EIO;
+}
+
+/* If display is enabled, then disable it */
+static int ufx_disable(struct ufx_data *dev, bool wait)
+{
+       u32 dc_ctrl, dc_sts;
+       int i;
+
+       int status = ufx_reg_read(dev, 0x2004, &dc_sts);
+       check_warn_return(status, "ufx_disable error reading 0x2004");
+
+       status = ufx_reg_read(dev, 0x2000, &dc_ctrl);
+       check_warn_return(status, "ufx_disable error reading 0x2000");
+
+       /* return success if display is already disabled */
+       if (((dc_sts & 0x00000001) == 0) || ((dc_ctrl & 0x00000001) == 0))
+               return 0;
+
+       /* request the DC to disable the display */
+       dc_ctrl &= ~(0x00000001);
+       status = ufx_reg_write(dev, 0x2000, dc_ctrl);
+       check_warn_return(status, "ufx_disable error writing 0x2000");
+
+       /* return success immediately if we don't have to wait */
+       if (!wait)
+               return 0;
+
+       for (i = 0; i < 250; i++) {
+               status = ufx_reg_read(dev, 0x2004, &dc_sts);
+               check_warn_return(status, "ufx_disable error reading 0x2004");
+
+               if ((dc_sts & 0x00000001) == 0)
+                       return 0;
+       }
+
+       /* timed out waiting for display to disable */
+       return -EIO;
+}
+
+/* If display is disabled, then enable it */
+static int ufx_enable(struct ufx_data *dev, bool wait)
+{
+       u32 dc_ctrl, dc_sts;
+       int i;
+
+       int status = ufx_reg_read(dev, 0x2004, &dc_sts);
+       check_warn_return(status, "ufx_enable error reading 0x2004");
+
+       status = ufx_reg_read(dev, 0x2000, &dc_ctrl);
+       check_warn_return(status, "ufx_enable error reading 0x2000");
+
+       /* return success if display is already enabled */
+       if ((dc_sts & 0x00000001) || (dc_ctrl & 0x00000001))
+               return 0;
+
+       /* request the DC to enable the display */
+       dc_ctrl |= 0x00000001;
+       status = ufx_reg_write(dev, 0x2000, dc_ctrl);
+       check_warn_return(status, "ufx_enable error writing 0x2000");
+
+       /* return success immediately if we don't have to wait */
+       if (!wait)
+               return 0;
+
+       for (i = 0; i < 250; i++) {
+               status = ufx_reg_read(dev, 0x2004, &dc_sts);
+               check_warn_return(status, "ufx_enable error reading 0x2004");
+
+               if (dc_sts & 0x00000001)
+                       return 0;
+       }
+
+       /* timed out waiting for display to enable */
+       return -EIO;
+}
+
+static int ufx_config_sys_clk(struct ufx_data *dev)
+{
+       int status = ufx_reg_write(dev, 0x700C, 0x8000000F);
+       check_warn_return(status, "error writing 0x700C");
+
+       status = ufx_reg_write(dev, 0x7014, 0x0010024F);
+       check_warn_return(status, "error writing 0x7014");
+
+       status = ufx_reg_write(dev, 0x7010, 0x00000000);
+       check_warn_return(status, "error writing 0x7010");
+
+       status = ufx_reg_clear_bits(dev, 0x700C, 0x0000000A);
+       check_warn_return(status, "error clearing PLL1 bypass in 0x700C");
+       msleep(1);
+
+       status = ufx_reg_clear_bits(dev, 0x700C, 0x80000000);
+       check_warn_return(status, "error clearing output gate in 0x700C");
+
+       return 0;
+}
+
+static int ufx_config_ddr2(struct ufx_data *dev)
+{
+       int status, i = 0;
+       u32 tmp;
+
+       status = ufx_reg_write(dev, 0x0004, 0x001F0F77);
+       check_warn_return(status, "error writing 0x0004");
+
+       status = ufx_reg_write(dev, 0x0008, 0xFFF00000);
+       check_warn_return(status, "error writing 0x0008");
+
+       status = ufx_reg_write(dev, 0x000C, 0x0FFF2222);
+       check_warn_return(status, "error writing 0x000C");
+
+       status = ufx_reg_write(dev, 0x0010, 0x00030814);
+       check_warn_return(status, "error writing 0x0010");
+
+       status = ufx_reg_write(dev, 0x0014, 0x00500019);
+       check_warn_return(status, "error writing 0x0014");
+
+       status = ufx_reg_write(dev, 0x0018, 0x020D0F15);
+       check_warn_return(status, "error writing 0x0018");
+
+       status = ufx_reg_write(dev, 0x001C, 0x02532305);
+       check_warn_return(status, "error writing 0x001C");
+
+       status = ufx_reg_write(dev, 0x0020, 0x0B030905);
+       check_warn_return(status, "error writing 0x0020");
+
+       status = ufx_reg_write(dev, 0x0024, 0x00000827);
+       check_warn_return(status, "error writing 0x0024");
+
+       status = ufx_reg_write(dev, 0x0028, 0x00000000);
+       check_warn_return(status, "error writing 0x0028");
+
+       status = ufx_reg_write(dev, 0x002C, 0x00000042);
+       check_warn_return(status, "error writing 0x002C");
+
+       status = ufx_reg_write(dev, 0x0030, 0x09520000);
+       check_warn_return(status, "error writing 0x0030");
+
+       status = ufx_reg_write(dev, 0x0034, 0x02223314);
+       check_warn_return(status, "error writing 0x0034");
+
+       status = ufx_reg_write(dev, 0x0038, 0x00430043);
+       check_warn_return(status, "error writing 0x0038");
+
+       status = ufx_reg_write(dev, 0x003C, 0xF00F000F);
+       check_warn_return(status, "error writing 0x003C");
+
+       status = ufx_reg_write(dev, 0x0040, 0xF380F00F);
+       check_warn_return(status, "error writing 0x0040");
+
+       status = ufx_reg_write(dev, 0x0044, 0xF00F0496);
+       check_warn_return(status, "error writing 0x0044");
+
+       status = ufx_reg_write(dev, 0x0048, 0x03080406);
+       check_warn_return(status, "error writing 0x0048");
+
+       status = ufx_reg_write(dev, 0x004C, 0x00001000);
+       check_warn_return(status, "error writing 0x004C");
+
+       status = ufx_reg_write(dev, 0x005C, 0x00000007);
+       check_warn_return(status, "error writing 0x005C");
+
+       status = ufx_reg_write(dev, 0x0100, 0x54F00012);
+       check_warn_return(status, "error writing 0x0100");
+
+       status = ufx_reg_write(dev, 0x0104, 0x00004012);
+       check_warn_return(status, "error writing 0x0104");
+
+       status = ufx_reg_write(dev, 0x0118, 0x40404040);
+       check_warn_return(status, "error writing 0x0118");
+
+       status = ufx_reg_write(dev, 0x0000, 0x00000001);
+       check_warn_return(status, "error writing 0x0000");
+
+       while (i++ < 500) {
+               status = ufx_reg_read(dev, 0x0000, &tmp);
+               check_warn_return(status, "error reading 0x0000");
+
+               if (all_bits_set(tmp, 0xC0000000))
+                       return 0;
+       }
+
+       pr_err("DDR2 initialisation timed out, reg 0x0000=0x%08x", tmp);
+       return -ETIMEDOUT;
+}
+
+struct pll_values {
+       u32 div_r0;
+       u32 div_f0;
+       u32 div_q0;
+       u32 range0;
+       u32 div_r1;
+       u32 div_f1;
+       u32 div_q1;
+       u32 range1;
+};
+
+static u32 ufx_calc_range(u32 ref_freq)
+{
+       if (ref_freq >= 88000000)
+               return 7;
+
+       if (ref_freq >= 54000000)
+               return 6;
+
+       if (ref_freq >= 34000000)
+               return 5;
+
+       if (ref_freq >= 21000000)
+               return 4;
+
+       if (ref_freq >= 13000000)
+               return 3;
+
+       if (ref_freq >= 8000000)
+               return 2;
+
+       return 1;
+}
+
+/* calculates PLL divider settings for a desired target frequency */
+static void ufx_calc_pll_values(const u32 clk_pixel_pll, struct pll_values *asic_pll)
+{
+       const u32 ref_clk = 25000000;
+       u32 div_r0, div_f0, div_q0, div_r1, div_f1, div_q1;
+       u32 min_error = clk_pixel_pll;
+
+       for (div_r0 = 1; div_r0 <= 32; div_r0++) {
+               u32 ref_freq0 = ref_clk / div_r0;
+               if (ref_freq0 < 5000000)
+                       break;
+
+               if (ref_freq0 > 200000000)
+                       continue;
+
+               for (div_f0 = 1; div_f0 <= 256; div_f0++) {
+                       u32 vco_freq0 = ref_freq0 * div_f0;
+
+                       if (vco_freq0 < 350000000)
+                               continue;
+
+                       if (vco_freq0 > 700000000)
+                               break;
+
+                       for (div_q0 = 0; div_q0 < 7; div_q0++) {
+                               u32 pllout_freq0 = vco_freq0 / (1 << div_q0);
+
+                               if (pllout_freq0 < 5000000)
+                                       break;
+
+                               if (pllout_freq0 > 200000000)
+                                       continue;
+
+                               for (div_r1 = 1; div_r1 <= 32; div_r1++) {
+                                       u32 ref_freq1 = pllout_freq0 / div_r1;
+
+                                       if (ref_freq1 < 5000000)
+                                               break;
+
+                                       for (div_f1 = 1; div_f1 <= 256; div_f1++) {
+                                               u32 vco_freq1 = ref_freq1 * div_f1;
+
+                                               if (vco_freq1 < 350000000)
+                                                       continue;
+
+                                               if (vco_freq1 > 700000000)
+                                                       break;
+
+                                               for (div_q1 = 0; div_q1 < 7; div_q1++) {
+                                                       u32 pllout_freq1 = vco_freq1 / (1 << div_q1);
+                                                       int error = abs(pllout_freq1 - clk_pixel_pll);
+
+                                                       if (pllout_freq1 < 5000000)
+                                                               break;
+
+                                                       if (pllout_freq1 > 700000000)
+                                                               continue;
+
+                                                       if (error < min_error) {
+                                                               min_error = error;
+
+                                                               /* final returned value is equal to calculated value - 1
+                                                                * because a value of 0 = divide by 1 */
+                                                               asic_pll->div_r0 = div_r0 - 1;
+                                                               asic_pll->div_f0 = div_f0 - 1;
+                                                               asic_pll->div_q0 = div_q0;
+                                                               asic_pll->div_r1 = div_r1 - 1;
+                                                               asic_pll->div_f1 = div_f1 - 1;
+                                                               asic_pll->div_q1 = div_q1;
+
+                                                               asic_pll->range0 = ufx_calc_range(ref_freq0);
+                                                               asic_pll->range1 = ufx_calc_range(ref_freq1);
+
+                                                               if (min_error == 0)
+                                                                       return;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+/* sets analog bit PLL configuration values */
+static int ufx_config_pix_clk(struct ufx_data *dev, u32 pixclock)
+{
+       struct pll_values asic_pll = {0};
+       u32 value, clk_pixel, clk_pixel_pll;
+       int status;
+
+       /* convert pixclock (in ps) to frequency (in Hz) */
+       clk_pixel = PICOS2KHZ(pixclock) * 1000;
+       pr_debug("pixclock %d ps = clk_pixel %d Hz", pixclock, clk_pixel);
+
+       /* clk_pixel = 1/2 clk_pixel_pll */
+       clk_pixel_pll = clk_pixel * 2;
+
+       ufx_calc_pll_values(clk_pixel_pll, &asic_pll);
+
+       /* Keep BYPASS and RESET signals asserted until configured */
+       status = ufx_reg_write(dev, 0x7000, 0x8000000F);
+       check_warn_return(status, "error writing 0x7000");
+
+       value = (asic_pll.div_f1 | (asic_pll.div_r1 << 8) |
+               (asic_pll.div_q1 << 16) | (asic_pll.range1 << 20));
+       status = ufx_reg_write(dev, 0x7008, value);
+       check_warn_return(status, "error writing 0x7008");
+
+       value = (asic_pll.div_f0 | (asic_pll.div_r0 << 8) |
+               (asic_pll.div_q0 << 16) | (asic_pll.range0 << 20));
+       status = ufx_reg_write(dev, 0x7004, value);
+       check_warn_return(status, "error writing 0x7004");
+
+       status = ufx_reg_clear_bits(dev, 0x7000, 0x00000005);
+       check_warn_return(status,
+               "error clearing PLL0 bypass bits in 0x7000");
+       msleep(1);
+
+       status = ufx_reg_clear_bits(dev, 0x7000, 0x0000000A);
+       check_warn_return(status,
+               "error clearing PLL1 bypass bits in 0x7000");
+       msleep(1);
+
+       status = ufx_reg_clear_bits(dev, 0x7000, 0x80000000);
+       check_warn_return(status, "error clearing gate bits in 0x7000");
+
+       return 0;
+}
+
+static int ufx_set_vid_mode(struct ufx_data *dev, struct fb_var_screeninfo *var)
+{
+       u32 temp;
+       u16 h_total, h_active, h_blank_start, h_blank_end, h_sync_start, h_sync_end;
+       u16 v_total, v_active, v_blank_start, v_blank_end, v_sync_start, v_sync_end;
+
+       int status = ufx_reg_write(dev, 0x8028, 0);
+       check_warn_return(status, "ufx_set_vid_mode error disabling RGB pad");
+
+       status = ufx_reg_write(dev, 0x8024, 0);
+       check_warn_return(status, "ufx_set_vid_mode error disabling VDAC");
+
+       /* shut everything down before changing timing */
+       status = ufx_blank(dev, true);
+       check_warn_return(status, "ufx_set_vid_mode error blanking display");
+
+       status = ufx_disable(dev, true);
+       check_warn_return(status, "ufx_set_vid_mode error disabling display");
+
+       status = ufx_config_pix_clk(dev, var->pixclock);
+       check_warn_return(status, "ufx_set_vid_mode error configuring pixclock");
+
+       status = ufx_reg_write(dev, 0x2000, 0x00000104);
+       check_warn_return(status, "ufx_set_vid_mode error writing 0x2000");
+
+       /* set horizontal timings */
+       h_total = var->xres + var->right_margin + var->hsync_len + var->left_margin;
+       h_active = var->xres;
+       h_blank_start = var->xres + var->right_margin;
+       h_blank_end = var->xres + var->right_margin + var->hsync_len;
+       h_sync_start = var->xres + var->right_margin;
+       h_sync_end = var->xres + var->right_margin + var->hsync_len;
+
+       temp = ((h_total - 1) << 16) | (h_active - 1);
+       status = ufx_reg_write(dev, 0x2008, temp);
+       check_warn_return(status, "ufx_set_vid_mode error writing 0x2008");
+
+       temp = ((h_blank_start - 1) << 16) | (h_blank_end - 1);
+       status = ufx_reg_write(dev, 0x200C, temp);
+       check_warn_return(status, "ufx_set_vid_mode error writing 0x200C");
+
+       temp = ((h_sync_start - 1) << 16) | (h_sync_end - 1);
+       status = ufx_reg_write(dev, 0x2010, temp);
+       check_warn_return(status, "ufx_set_vid_mode error writing 0x2010");
+
+       /* set vertical timings */
+       v_total = var->upper_margin + var->yres + var->lower_margin + var->vsync_len;
+       v_active = var->yres;
+       v_blank_start = var->yres + var->lower_margin;
+       v_blank_end = var->yres + var->lower_margin + var->vsync_len;
+       v_sync_start = var->yres + var->lower_margin;
+       v_sync_end = var->yres + var->lower_margin + var->vsync_len;
+
+       temp = ((v_total - 1) << 16) | (v_active - 1);
+       status = ufx_reg_write(dev, 0x2014, temp);
+       check_warn_return(status, "ufx_set_vid_mode error writing 0x2014");
+
+       temp = ((v_blank_start - 1) << 16) | (v_blank_end - 1);
+       status = ufx_reg_write(dev, 0x2018, temp);
+       check_warn_return(status, "ufx_set_vid_mode error writing 0x2018");
+
+       temp = ((v_sync_start - 1) << 16) | (v_sync_end - 1);
+       status = ufx_reg_write(dev, 0x201C, temp);
+       check_warn_return(status, "ufx_set_vid_mode error writing 0x201C");
+
+       status = ufx_reg_write(dev, 0x2020, 0x00000000);
+       check_warn_return(status, "ufx_set_vid_mode error writing 0x2020");
+
+       status = ufx_reg_write(dev, 0x2024, 0x00000000);
+       check_warn_return(status, "ufx_set_vid_mode error writing 0x2024");
+
+       /* Set the frame length register (#pix * 2 bytes/pixel) */
+       temp = var->xres * var->yres * 2;
+       temp = (temp + 7) & (~0x7);
+       status = ufx_reg_write(dev, 0x2028, temp);
+       check_warn_return(status, "ufx_set_vid_mode error writing 0x2028");
+
+       /* enable desired output interface & disable others */
+       status = ufx_reg_write(dev, 0x2040, 0);
+       check_warn_return(status, "ufx_set_vid_mode error writing 0x2040");
+
+       status = ufx_reg_write(dev, 0x2044, 0);
+       check_warn_return(status, "ufx_set_vid_mode error writing 0x2044");
+
+       status = ufx_reg_write(dev, 0x2048, 0);
+       check_warn_return(status, "ufx_set_vid_mode error writing 0x2048");
+
+       /* set the sync polarities & enable bit */
+       temp = 0x00000001;
+       if (var->sync & FB_SYNC_HOR_HIGH_ACT)
+               temp |= 0x00000010;
+
+       if (var->sync & FB_SYNC_VERT_HIGH_ACT)
+               temp |= 0x00000008;
+
+       status = ufx_reg_write(dev, 0x2040, temp);
+       check_warn_return(status, "ufx_set_vid_mode error writing 0x2040");
+
+       /* start everything back up */
+       status = ufx_enable(dev, true);
+       check_warn_return(status, "ufx_set_vid_mode error enabling display");
+
+       /* Unblank the display */
+       status = ufx_unblank(dev, true);
+       check_warn_return(status, "ufx_set_vid_mode error unblanking display");
+
+       /* enable RGB pad */
+       status = ufx_reg_write(dev, 0x8028, 0x00000003);
+       check_warn_return(status, "ufx_set_vid_mode error enabling RGB pad");
+
+       /* enable VDAC */
+       status = ufx_reg_write(dev, 0x8024, 0x00000007);
+       check_warn_return(status, "ufx_set_vid_mode error enabling VDAC");
+
+       return 0;
+}
+
+static int ufx_ops_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+       unsigned long start = vma->vm_start;
+       unsigned long size = vma->vm_end - vma->vm_start;
+       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+       unsigned long page, pos;
+
+       if (offset + size > info->fix.smem_len)
+               return -EINVAL;
+
+       pos = (unsigned long)info->fix.smem_start + offset;
+
+       pr_debug("mmap() framebuffer addr:%lu size:%lu\n",
+                 pos, size);
+
+       while (size > 0) {
+               page = vmalloc_to_pfn((void *)pos);
+               if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
+                       return -EAGAIN;
+
+               start += PAGE_SIZE;
+               pos += PAGE_SIZE;
+               if (size > PAGE_SIZE)
+                       size -= PAGE_SIZE;
+               else
+                       size = 0;
+       }
+
+       vma->vm_flags |= VM_RESERVED;   /* avoid to swap out this VMA */
+       return 0;
+}
+
+static void ufx_raw_rect(struct ufx_data *dev, u16 *cmd, int x, int y,
+       int width, int height)
+{
+       size_t packed_line_len = ALIGN((width * 2), 4);
+       size_t packed_rect_len = packed_line_len * height;
+       int line;
+
+       BUG_ON(!dev);
+       BUG_ON(!dev->info);
+
+       /* command word */
+       *((u32 *)&cmd[0]) = cpu_to_le32(0x01);
+
+       /* length word */
+       *((u32 *)&cmd[2]) = cpu_to_le32(packed_rect_len + 16);
+
+       cmd[4] = cpu_to_le16(x);
+       cmd[5] = cpu_to_le16(y);
+       cmd[6] = cpu_to_le16(width);
+       cmd[7] = cpu_to_le16(height);
+
+       /* frame base address */
+       *((u32 *)&cmd[8]) = cpu_to_le32(0);
+
+       /* color mode and horizontal resolution */
+       cmd[10] = cpu_to_le16(0x4000 | dev->info->var.xres);
+
+       /* vertical resolution */
+       cmd[11] = cpu_to_le16(dev->info->var.yres);
+
+       /* packed data */
+       for (line = 0; line < height; line++) {
+               const int line_offset = dev->info->fix.line_length * (y + line);
+               const int byte_offset = line_offset + (x * BPP);
+               memcpy(&cmd[(24 + (packed_line_len * line)) / 2],
+                       (char *)dev->info->fix.smem_start + byte_offset, width * BPP);
+       }
+}
+
+int ufx_handle_damage(struct ufx_data *dev, int x, int y,
+       int width, int height)
+{
+       size_t packed_line_len = ALIGN((width * 2), 4);
+       int len, status, urb_lines, start_line = 0;
+
+       if ((width <= 0) || (height <= 0) ||
+           (x + width > dev->info->var.xres) ||
+           (y + height > dev->info->var.yres))
+               return -EINVAL;
+
+       if (!atomic_read(&dev->usb_active))
+               return 0;
+
+       while (start_line < height) {
+               struct urb *urb = ufx_get_urb(dev);
+               if (!urb) {
+                       pr_warn("ufx_handle_damage unable to get urb");
+                       return 0;
+               }
+
+               /* assume we have enough space to transfer at least one line */
+               BUG_ON(urb->transfer_buffer_length < (24 + (width * 2)));
+
+               /* calculate the maximum number of lines we could fit in */
+               urb_lines = (urb->transfer_buffer_length - 24) / packed_line_len;
+
+               /* but we might not need this many */
+               urb_lines = min(urb_lines, (height - start_line));
+
+               memset(urb->transfer_buffer, 0, urb->transfer_buffer_length);
+
+               ufx_raw_rect(dev, urb->transfer_buffer, x, (y + start_line), width, urb_lines);
+               len = 24 + (packed_line_len * urb_lines);
+
+               status = ufx_submit_urb(dev, urb, len);
+               check_warn_return(status, "Error submitting URB");
+
+               start_line += urb_lines;
+       }
+
+       return 0;
+}
+
+/* Path triggered by usermode clients who write to filesystem
+ * e.g. cat filename > /dev/fb1
+ * Not used by X Windows or text-mode console. But useful for testing.
+ * Slow because of extra copy and we must assume all pixels dirty. */
+static ssize_t ufx_ops_write(struct fb_info *info, const char __user *buf,
+                         size_t count, loff_t *ppos)
+{
+       ssize_t result;
+       struct ufx_data *dev = info->par;
+       u32 offset = (u32) *ppos;
+
+       result = fb_sys_write(info, buf, count, ppos);
+
+       if (result > 0) {
+               int start = max((int)(offset / info->fix.line_length) - 1, 0);
+               int lines = min((u32)((result / info->fix.line_length) + 1),
+                               (u32)info->var.yres);
+
+               ufx_handle_damage(dev, 0, start, info->var.xres, lines);
+       }
+
+       return result;
+}
+
+static void ufx_ops_copyarea(struct fb_info *info,
+                               const struct fb_copyarea *area)
+{
+
+       struct ufx_data *dev = info->par;
+
+       sys_copyarea(info, area);
+
+       ufx_handle_damage(dev, area->dx, area->dy,
+                       area->width, area->height);
+}
+
+static void ufx_ops_imageblit(struct fb_info *info,
+                               const struct fb_image *image)
+{
+       struct ufx_data *dev = info->par;
+
+       sys_imageblit(info, image);
+
+       ufx_handle_damage(dev, image->dx, image->dy,
+                       image->width, image->height);
+}
+
+static void ufx_ops_fillrect(struct fb_info *info,
+                         const struct fb_fillrect *rect)
+{
+       struct ufx_data *dev = info->par;
+
+       sys_fillrect(info, rect);
+
+       ufx_handle_damage(dev, rect->dx, rect->dy, rect->width,
+                             rect->height);
+}
+
+/* NOTE: fb_defio.c is holding info->fbdefio.mutex
+ *   Touching ANY framebuffer memory that triggers a page fault
+ *   in fb_defio will cause a deadlock, when it also tries to
+ *   grab the same mutex. */
+static void ufx_dpy_deferred_io(struct fb_info *info,
+                               struct list_head *pagelist)
+{
+       struct page *cur;
+       struct fb_deferred_io *fbdefio = info->fbdefio;
+       struct ufx_data *dev = info->par;
+
+       if (!fb_defio)
+               return;
+
+       if (!atomic_read(&dev->usb_active))
+               return;
+
+       /* walk the written page list and render each to device */
+       list_for_each_entry(cur, &fbdefio->pagelist, lru) {
+               /* create a rectangle of full screen width that encloses the
+                * entire dirty framebuffer page */
+               const int x = 0;
+               const int width = dev->info->var.xres;
+               const int y = (cur->index << PAGE_SHIFT) / (width * 2);
+               int height = (PAGE_SIZE / (width * 2)) + 1;
+               height = min(height, (int)(dev->info->var.yres - y));
+
+               BUG_ON(y >= dev->info->var.yres);
+               BUG_ON((y + height) > dev->info->var.yres);
+
+               ufx_handle_damage(dev, x, y, width, height);
+       }
+}
+
+static int ufx_ops_ioctl(struct fb_info *info, unsigned int cmd,
+                        unsigned long arg)
+{
+       struct ufx_data *dev = info->par;
+       struct dloarea *area = NULL;
+
+       if (!atomic_read(&dev->usb_active))
+               return 0;
+
+       /* TODO: Update X server to get this from sysfs instead */
+       if (cmd == UFX_IOCTL_RETURN_EDID) {
+               u8 __user *edid = (u8 __user *)arg;
+               if (copy_to_user(edid, dev->edid, dev->edid_size))
+                       return -EFAULT;
+               return 0;
+       }
+
+       /* TODO: Help propose a standard fb.h ioctl to report mmap damage */
+       if (cmd == UFX_IOCTL_REPORT_DAMAGE) {
+               /* If we have a damage-aware client, turn fb_defio "off"
+                * To avoid perf imact of unecessary page fault handling.
+                * Done by resetting the delay for this fb_info to a very
+                * long period. Pages will become writable and stay that way.
+                * Reset to normal value when all clients have closed this fb.
+                */
+               if (info->fbdefio)
+                       info->fbdefio->delay = UFX_DEFIO_WRITE_DISABLE;
+
+               area = (struct dloarea *)arg;
+
+               if (area->x < 0)
+                       area->x = 0;
+
+               if (area->x > info->var.xres)
+                       area->x = info->var.xres;
+
+               if (area->y < 0)
+                       area->y = 0;
+
+               if (area->y > info->var.yres)
+                       area->y = info->var.yres;
+
+               ufx_handle_damage(dev, area->x, area->y, area->w, area->h);
+       }
+
+       return 0;
+}
+
+/* taken from vesafb */
+static int
+ufx_ops_setcolreg(unsigned regno, unsigned red, unsigned green,
+              unsigned blue, unsigned transp, struct fb_info *info)
+{
+       int err = 0;
+
+       if (regno >= info->cmap.len)
+               return 1;
+
+       if (regno < 16) {
+               if (info->var.red.offset == 10) {
+                       /* 1:5:5:5 */
+                       ((u32 *) (info->pseudo_palette))[regno] =
+                           ((red & 0xf800) >> 1) |
+                           ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
+               } else {
+                       /* 0:5:6:5 */
+                       ((u32 *) (info->pseudo_palette))[regno] =
+                           ((red & 0xf800)) |
+                           ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
+               }
+       }
+
+       return err;
+}
+
+/* It's common for several clients to have framebuffer open simultaneously.
+ * e.g. both fbcon and X. Makes things interesting.
+ * Assumes caller is holding info->lock (for open and release at least) */
+static int ufx_ops_open(struct fb_info *info, int user)
+{
+       struct ufx_data *dev = info->par;
+
+       /* fbcon aggressively connects to first framebuffer it finds,
+        * preventing other clients (X) from working properly. Usually
+        * not what the user wants. Fail by default with option to enable. */
+       if (user == 0 && !console)
+               return -EBUSY;
+
+       /* If the USB device is gone, we don't accept new opens */
+       if (dev->virtualized)
+               return -ENODEV;
+
+       dev->fb_count++;
+
+       kref_get(&dev->kref);
+
+       if (fb_defio && (info->fbdefio == NULL)) {
+               /* enable defio at last moment if not disabled by client */
+
+               struct fb_deferred_io *fbdefio;
+
+               fbdefio = kmalloc(sizeof(struct fb_deferred_io), GFP_KERNEL);
+
+               if (fbdefio) {
+                       fbdefio->delay = UFX_DEFIO_WRITE_DELAY;
+                       fbdefio->deferred_io = ufx_dpy_deferred_io;
+               }
+
+               info->fbdefio = fbdefio;
+               fb_deferred_io_init(info);
+       }
+
+       pr_debug("open /dev/fb%d user=%d fb_info=%p count=%d",
+               info->node, user, info, dev->fb_count);
+
+       return 0;
+}
+
+/*
+ * Called when all client interfaces to start transactions have been disabled,
+ * and all references to our device instance (ufx_data) are released.
+ * Every transaction must have a reference, so we know are fully spun down
+ */
+static void ufx_free(struct kref *kref)
+{
+       struct ufx_data *dev = container_of(kref, struct ufx_data, kref);
+
+       /* this function will wait for all in-flight urbs to complete */
+       if (dev->urbs.count > 0)
+               ufx_free_urb_list(dev);
+
+       pr_debug("freeing ufx_data %p", dev);
+
+       kfree(dev);
+}
+
+static void ufx_release_urb_work(struct work_struct *work)
+{
+       struct urb_node *unode = container_of(work, struct urb_node,
+                                             release_urb_work.work);
+
+       up(&unode->dev->urbs.limit_sem);
+}
+
+static void ufx_free_framebuffer_work(struct work_struct *work)
+{
+       struct ufx_data *dev = container_of(work, struct ufx_data,
+                                           free_framebuffer_work.work);
+       struct fb_info *info = dev->info;
+       int node = info->node;
+
+       unregister_framebuffer(info);
+
+       if (info->cmap.len != 0)
+               fb_dealloc_cmap(&info->cmap);
+       if (info->monspecs.modedb)
+               fb_destroy_modedb(info->monspecs.modedb);
+       if (info->screen_base)
+               vfree(info->screen_base);
+
+       fb_destroy_modelist(&info->modelist);
+
+       dev->info = 0;
+
+       /* Assume info structure is freed after this point */
+       framebuffer_release(info);
+
+       pr_debug("fb_info for /dev/fb%d has been freed", node);
+
+       /* ref taken in probe() as part of registering framebfufer */
+       kref_put(&dev->kref, ufx_free);
+}
+
+/*
+ * Assumes caller is holding info->lock mutex (for open and release at least)
+ */
+static int ufx_ops_release(struct fb_info *info, int user)
+{
+       struct ufx_data *dev = info->par;
+
+       dev->fb_count--;
+
+       /* We can't free fb_info here - fbmem will touch it when we return */
+       if (dev->virtualized && (dev->fb_count == 0))
+               schedule_delayed_work(&dev->free_framebuffer_work, HZ);
+
+       if ((dev->fb_count == 0) && (info->fbdefio)) {
+               fb_deferred_io_cleanup(info);
+               kfree(info->fbdefio);
+               info->fbdefio = NULL;
+               info->fbops->fb_mmap = ufx_ops_mmap;
+       }
+
+       pr_debug("released /dev/fb%d user=%d count=%d",
+                 info->node, user, dev->fb_count);
+
+       kref_put(&dev->kref, ufx_free);
+
+       return 0;
+}
+
+/* Check whether a video mode is supported by the chip
+ * We start from monitor's modes, so don't need to filter that here */
+static int ufx_is_valid_mode(struct fb_videomode *mode,
+               struct fb_info *info)
+{
+       if ((mode->xres * mode->yres) > (2048 * 1152)) {
+               pr_debug("%dx%d too many pixels",
+                      mode->xres, mode->yres);
+               return 0;
+       }
+
+       if (mode->pixclock < 5000) {
+               pr_debug("%dx%d %dps pixel clock too fast",
+                      mode->xres, mode->yres, mode->pixclock);
+               return 0;
+       }
+
+       pr_debug("%dx%d (pixclk %dps %dMHz) valid mode", mode->xres, mode->yres,
+               mode->pixclock, (1000000 / mode->pixclock));
+       return 1;
+}
+
+static void ufx_var_color_format(struct fb_var_screeninfo *var)
+{
+       const struct fb_bitfield red = { 11, 5, 0 };
+       const struct fb_bitfield green = { 5, 6, 0 };
+       const struct fb_bitfield blue = { 0, 5, 0 };
+
+       var->bits_per_pixel = 16;
+       var->red = red;
+       var->green = green;
+       var->blue = blue;
+}
+
+static int ufx_ops_check_var(struct fb_var_screeninfo *var,
+                               struct fb_info *info)
+{
+       struct fb_videomode mode;
+
+       /* TODO: support dynamically changing framebuffer size */
+       if ((var->xres * var->yres * 2) > info->fix.smem_len)
+               return -EINVAL;
+
+       /* set device-specific elements of var unrelated to mode */
+       ufx_var_color_format(var);
+
+       fb_var_to_videomode(&mode, var);
+
+       if (!ufx_is_valid_mode(&mode, info))
+               return -EINVAL;
+
+       return 0;
+}
+
+static int ufx_ops_set_par(struct fb_info *info)
+{
+       struct ufx_data *dev = info->par;
+       int result;
+       u16 *pix_framebuffer;
+       int i;
+
+       pr_debug("set_par mode %dx%d", info->var.xres, info->var.yres);
+       result = ufx_set_vid_mode(dev, &info->var);
+
+       if ((result == 0) && (dev->fb_count == 0)) {
+               /* paint greenscreen */
+               pix_framebuffer = (u16 *) info->screen_base;
+               for (i = 0; i < info->fix.smem_len / 2; i++)
+                       pix_framebuffer[i] = 0x37e6;
+
+               ufx_handle_damage(dev, 0, 0, info->var.xres, info->var.yres);
+       }
+
+       /* re-enable defio if previously disabled by damage tracking */
+       if (info->fbdefio)
+               info->fbdefio->delay = UFX_DEFIO_WRITE_DELAY;
+
+       return result;
+}
+
+/* In order to come back from full DPMS off, we need to set the mode again */
+static int ufx_ops_blank(int blank_mode, struct fb_info *info)
+{
+       struct ufx_data *dev = info->par;
+       ufx_set_vid_mode(dev, &info->var);
+       return 0;
+}
+
+static struct fb_ops ufx_ops = {
+       .owner = THIS_MODULE,
+       .fb_read = fb_sys_read,
+       .fb_write = ufx_ops_write,
+       .fb_setcolreg = ufx_ops_setcolreg,
+       .fb_fillrect = ufx_ops_fillrect,
+       .fb_copyarea = ufx_ops_copyarea,
+       .fb_imageblit = ufx_ops_imageblit,
+       .fb_mmap = ufx_ops_mmap,
+       .fb_ioctl = ufx_ops_ioctl,
+       .fb_open = ufx_ops_open,
+       .fb_release = ufx_ops_release,
+       .fb_blank = ufx_ops_blank,
+       .fb_check_var = ufx_ops_check_var,
+       .fb_set_par = ufx_ops_set_par,
+};
+
+/* Assumes &info->lock held by caller
+ * Assumes no active clients have framebuffer open */
+static int ufx_realloc_framebuffer(struct ufx_data *dev, struct fb_info *info)
+{
+       int retval = -ENOMEM;
+       int old_len = info->fix.smem_len;
+       int new_len;
+       unsigned char *old_fb = info->screen_base;
+       unsigned char *new_fb;
+
+       pr_debug("Reallocating framebuffer. Addresses will change!");
+
+       new_len = info->fix.line_length * info->var.yres;
+
+       if (PAGE_ALIGN(new_len) > old_len) {
+               /*
+                * Alloc system memory for virtual framebuffer
+                */
+               new_fb = vmalloc(new_len);
+               if (!new_fb) {
+                       pr_err("Virtual framebuffer alloc failed");
+                       goto error;
+               }
+
+               if (info->screen_base) {
+                       memcpy(new_fb, old_fb, old_len);
+                       vfree(info->screen_base);
+               }
+
+               info->screen_base = new_fb;
+               info->fix.smem_len = PAGE_ALIGN(new_len);
+               info->fix.smem_start = (unsigned long) new_fb;
+               info->flags = smscufx_info_flags;
+       }
+
+       retval = 0;
+
+error:
+       return retval;
+}
+
+/* sets up I2C Controller for 100 Kbps, std. speed, 7-bit addr, master,
+ * restart enabled, but no start byte, enable controller */
+static int ufx_i2c_init(struct ufx_data *dev)
+{
+       u32 tmp;
+
+       /* disable the controller before it can be reprogrammed */
+       int status = ufx_reg_write(dev, 0x106C, 0x00);
+       check_warn_return(status, "failed to disable I2C");
+
+       /* Setup the clock count registers
+        * (12+1) = 13 clks @ 2.5 MHz = 5.2 uS */
+       status = ufx_reg_write(dev, 0x1018, 12);
+       check_warn_return(status, "error writing 0x1018");
+
+       /* (6+8) = 14 clks @ 2.5 MHz = 5.6 uS */
+       status = ufx_reg_write(dev, 0x1014, 6);
+       check_warn_return(status, "error writing 0x1014");
+
+       status = ufx_reg_read(dev, 0x1000, &tmp);
+       check_warn_return(status, "error reading 0x1000");
+
+       /* set speed to std mode */
+       tmp &= ~(0x06);
+       tmp |= 0x02;
+
+       /* 7-bit (not 10-bit) addressing */
+       tmp &= ~(0x10);
+
+       /* enable restart conditions and master mode */
+       tmp |= 0x21;
+
+       status = ufx_reg_write(dev, 0x1000, tmp);
+       check_warn_return(status, "error writing 0x1000");
+
+       /* Set normal tx using target address 0 */
+       status = ufx_reg_clear_and_set_bits(dev, 0x1004, 0xC00, 0x000);
+       check_warn_return(status, "error setting TX mode bits in 0x1004");
+
+       /* Enable the controller */
+       status = ufx_reg_write(dev, 0x106C, 0x01);
+       check_warn_return(status, "failed to enable I2C");
+
+       return 0;
+}
+
+/* sets the I2C port mux and target address */
+static int ufx_i2c_configure(struct ufx_data *dev)
+{
+       int status = ufx_reg_write(dev, 0x106C, 0x00);
+       check_warn_return(status, "failed to disable I2C");
+
+       status = ufx_reg_write(dev, 0x3010, 0x00000000);
+       check_warn_return(status, "failed to write 0x3010");
+
+       /* A0h is std for any EDID, right shifted by one */
+       status = ufx_reg_clear_and_set_bits(dev, 0x1004, 0x3FF, (0xA0 >> 1));
+       check_warn_return(status, "failed to set TAR bits in 0x1004");
+
+       status = ufx_reg_write(dev, 0x106C, 0x01);
+       check_warn_return(status, "failed to enable I2C");
+
+       return 0;
+}
+
+/* wait for BUSY to clear, with a timeout of 50ms with 10ms sleeps. if no
+ * monitor is connected, there is no error except for timeout */
+static int ufx_i2c_wait_busy(struct ufx_data *dev)
+{
+       u32 tmp;
+       int i, status;
+
+       for (i = 0; i < 15; i++) {
+               status = ufx_reg_read(dev, 0x1100, &tmp);
+               check_warn_return(status, "0x1100 read failed");
+
+               /* if BUSY is clear, check for error */
+               if ((tmp & 0x80000000) == 0) {
+                       if (tmp & 0x20000000) {
+                               pr_warn("I2C read failed, 0x1100=0x%08x", tmp);
+                               return -EIO;
+                       }
+
+                       return 0;
+               }
+
+               /* perform the first 10 retries without delay */
+               if (i >= 10)
+                       msleep(10);
+       }
+
+       pr_warn("I2C access timed out, resetting I2C hardware");
+       status =  ufx_reg_write(dev, 0x1100, 0x40000000);
+       check_warn_return(status, "0x1100 write failed");
+
+       return -ETIMEDOUT;
+}
+
+/* reads a 128-byte EDID block from the currently selected port and TAR */
+static int ufx_read_edid(struct ufx_data *dev, u8 *edid, int edid_len)
+{
+       int i, j, status;
+       u32 *edid_u32 = (u32 *)edid;
+
+       BUG_ON(edid_len != EDID_LENGTH);
+
+       status = ufx_i2c_configure(dev);
+       if (status < 0) {
+               pr_err("ufx_i2c_configure failed");
+               return status;
+       }
+
+       memset(edid, 0xff, EDID_LENGTH);
+
+       /* Read the 128-byte EDID as 2 bursts of 64 bytes */
+       for (i = 0; i < 2; i++) {
+               u32 temp = 0x28070000 | (63 << 20) | (((u32)(i * 64)) << 8);
+               status = ufx_reg_write(dev, 0x1100, temp);
+               check_warn_return(status, "Failed to write 0x1100");
+
+               temp |= 0x80000000;
+               status = ufx_reg_write(dev, 0x1100, temp);
+               check_warn_return(status, "Failed to write 0x1100");
+
+               status = ufx_i2c_wait_busy(dev);
+               check_warn_return(status, "Timeout waiting for I2C BUSY to clear");
+
+               for (j = 0; j < 16; j++) {
+                       u32 data_reg_addr = 0x1110 + (j * 4);
+                       status = ufx_reg_read(dev, data_reg_addr, edid_u32++);
+                       check_warn_return(status, "Error reading i2c data");
+               }
+       }
+
+       /* all FF's in the first 16 bytes indicates nothing is connected */
+       for (i = 0; i < 16; i++) {
+               if (edid[i] != 0xFF) {
+                       pr_debug("edid data read succesfully");
+                       return EDID_LENGTH;
+               }
+       }
+
+       pr_warn("edid data contains all 0xff");
+       return -ETIMEDOUT;
+}
+
+/* 1) use sw default
+ * 2) Parse into various fb_info structs
+ * 3) Allocate virtual framebuffer memory to back highest res mode
+ *
+ * Parses EDID into three places used by various parts of fbdev:
+ * fb_var_screeninfo contains the timing of the monitor's preferred mode
+ * fb_info.monspecs is full parsed EDID info, including monspecs.modedb
+ * fb_info.modelist is a linked list of all monitor & VESA modes which work
+ *
+ * If EDID is not readable/valid, then modelist is all VESA modes,
+ * monspecs is NULL, and fb_var_screeninfo is set to safe VESA mode
+ * Returns 0 if successful */
+static int ufx_setup_modes(struct ufx_data *dev, struct fb_info *info,
+       char *default_edid, size_t default_edid_size)
+{
+       const struct fb_videomode *default_vmode = NULL;
+       u8 *edid;
+       int i, result = 0, tries = 3;
+
+       if (info->dev) /* only use mutex if info has been registered */
+               mutex_lock(&info->lock);
+
+       edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+       if (!edid) {
+               result = -ENOMEM;
+               goto error;
+       }
+
+       fb_destroy_modelist(&info->modelist);
+       memset(&info->monspecs, 0, sizeof(info->monspecs));
+
+       /* Try to (re)read EDID from hardware first
+        * EDID data may return, but not parse as valid
+        * Try again a few times, in case of e.g. analog cable noise */
+       while (tries--) {
+               i = ufx_read_edid(dev, edid, EDID_LENGTH);
+
+               if (i >= EDID_LENGTH)
+                       fb_edid_to_monspecs(edid, &info->monspecs);
+
+               if (info->monspecs.modedb_len > 0) {
+                       dev->edid = edid;
+                       dev->edid_size = i;
+                       break;
+               }
+       }
+
+       /* If that fails, use a previously returned EDID if available */
+       if (info->monspecs.modedb_len == 0) {
+               pr_err("Unable to get valid EDID from device/display\n");
+
+               if (dev->edid) {
+                       fb_edid_to_monspecs(dev->edid, &info->monspecs);
+                       if (info->monspecs.modedb_len > 0)
+                               pr_err("Using previously queried EDID\n");
+               }
+       }
+
+       /* If that fails, use the default EDID we were handed */
+       if (info->monspecs.modedb_len == 0) {
+               if (default_edid_size >= EDID_LENGTH) {
+                       fb_edid_to_monspecs(default_edid, &info->monspecs);
+                       if (info->monspecs.modedb_len > 0) {
+                               memcpy(edid, default_edid, default_edid_size);
+                               dev->edid = edid;
+                               dev->edid_size = default_edid_size;
+                               pr_err("Using default/backup EDID\n");
+                       }
+               }
+       }
+
+       /* If we've got modes, let's pick a best default mode */
+       if (info->monspecs.modedb_len > 0) {
+
+               for (i = 0; i < info->monspecs.modedb_len; i++) {
+                       if (ufx_is_valid_mode(&info->monspecs.modedb[i], info))
+                               fb_add_videomode(&info->monspecs.modedb[i],
+                                       &info->modelist);
+                       else /* if we've removed top/best mode */
+                               info->monspecs.misc &= ~FB_MISC_1ST_DETAIL;
+               }
+
+               default_vmode = fb_find_best_display(&info->monspecs,
+                                                    &info->modelist);
+       }
+
+       /* If everything else has failed, fall back to safe default mode */
+       if (default_vmode == NULL) {
+
+               struct fb_videomode fb_vmode = {0};
+
+               /* Add the standard VESA modes to our modelist
+                * Since we don't have EDID, there may be modes that
+                * overspec monitor and/or are incorrect aspect ratio, etc.
+                * But at least the user has a chance to choose
+                */
+               for (i = 0; i < VESA_MODEDB_SIZE; i++) {
+                       if (ufx_is_valid_mode((struct fb_videomode *)
+                                               &vesa_modes[i], info))
+                               fb_add_videomode(&vesa_modes[i],
+                                                &info->modelist);
+               }
+
+               /* default to resolution safe for projectors
+                * (since they are most common case without EDID)
+                */
+               fb_vmode.xres = 800;
+               fb_vmode.yres = 600;
+               fb_vmode.refresh = 60;
+               default_vmode = fb_find_nearest_mode(&fb_vmode,
+                                                    &info->modelist);
+       }
+
+       /* If we have good mode and no active clients */
+       if ((default_vmode != NULL) && (dev->fb_count == 0)) {
+
+               fb_videomode_to_var(&info->var, default_vmode);
+               ufx_var_color_format(&info->var);
+
+               /* with mode size info, we can now alloc our framebuffer */
+               memcpy(&info->fix, &ufx_fix, sizeof(ufx_fix));
+               info->fix.line_length = info->var.xres *
+                       (info->var.bits_per_pixel / 8);
+
+               result = ufx_realloc_framebuffer(dev, info);
+
+       } else
+               result = -EINVAL;
+
+error:
+       if (edid && (dev->edid != edid))
+               kfree(edid);
+
+       if (info->dev)
+               mutex_unlock(&info->lock);
+
+       return result;
+}
+
+static int ufx_usb_probe(struct usb_interface *interface,
+                       const struct usb_device_id *id)
+{
+       struct usb_device *usbdev;
+       struct ufx_data *dev;
+       struct fb_info *info = 0;
+       int retval = -ENOMEM;
+       u32 id_rev, fpga_rev;
+
+       /* usb initialization */
+       usbdev = interface_to_usbdev(interface);
+       BUG_ON(!usbdev);
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (dev == NULL) {
+               dev_err(&usbdev->dev, "ufx_usb_probe: failed alloc of dev struct\n");
+               goto error;
+       }
+
+       /* we need to wait for both usb and fbdev to spin down on disconnect */
+       kref_init(&dev->kref); /* matching kref_put in usb .disconnect fn */
+       kref_get(&dev->kref); /* matching kref_put in free_framebuffer_work */
+
+       dev->udev = usbdev;
+       dev->gdev = &usbdev->dev; /* our generic struct device * */
+       usb_set_intfdata(interface, dev);
+
+       dev_dbg(dev->gdev, "%s %s - serial #%s\n",
+               usbdev->manufacturer, usbdev->product, usbdev->serial);
+       dev_dbg(dev->gdev, "vid_%04x&pid_%04x&rev_%04x driver's ufx_data struct at %p\n",
+               usbdev->descriptor.idVendor, usbdev->descriptor.idProduct,
+               usbdev->descriptor.bcdDevice, dev);
+       dev_dbg(dev->gdev, "console enable=%d\n", console);
+       dev_dbg(dev->gdev, "fb_defio enable=%d\n", fb_defio);
+
+       if (!ufx_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) {
+               retval = -ENOMEM;
+               dev_err(dev->gdev, "ufx_alloc_urb_list failed\n");
+               goto error;
+       }
+
+       /* We don't register a new USB class. Our client interface is fbdev */
+
+       /* allocates framebuffer driver structure, not framebuffer memory */
+       info = framebuffer_alloc(0, &usbdev->dev);
+       if (!info) {
+               retval = -ENOMEM;
+               dev_err(dev->gdev, "framebuffer_alloc failed\n");
+               goto error;
+       }
+
+       dev->info = info;
+       info->par = dev;
+       info->pseudo_palette = dev->pseudo_palette;
+       info->fbops = &ufx_ops;
+
+       retval = fb_alloc_cmap(&info->cmap, 256, 0);
+       if (retval < 0) {
+               dev_err(dev->gdev, "fb_alloc_cmap failed %x\n", retval);
+               goto error;
+       }
+
+       INIT_DELAYED_WORK(&dev->free_framebuffer_work,
+                         ufx_free_framebuffer_work);
+
+       INIT_LIST_HEAD(&info->modelist);
+
+       retval = ufx_reg_read(dev, 0x3000, &id_rev);
+       check_warn_goto_error(retval, "error %d reading 0x3000 register from device", retval);
+       dev_dbg(dev->gdev, "ID_REV register value 0x%08x", id_rev);
+
+       retval = ufx_reg_read(dev, 0x3004, &fpga_rev);
+       check_warn_goto_error(retval, "error %d reading 0x3004 register from device", retval);
+       dev_dbg(dev->gdev, "FPGA_REV register value 0x%08x", fpga_rev);
+
+       dev_dbg(dev->gdev, "resetting device");
+       retval = ufx_lite_reset(dev);
+       check_warn_goto_error(retval, "error %d resetting device", retval);
+
+       dev_dbg(dev->gdev, "configuring system clock");
+       retval = ufx_config_sys_clk(dev);
+       check_warn_goto_error(retval, "error %d configuring system clock", retval);
+
+       dev_dbg(dev->gdev, "configuring DDR2 controller");
+       retval = ufx_config_ddr2(dev);
+       check_warn_goto_error(retval, "error %d initialising DDR2 controller", retval);
+
+       dev_dbg(dev->gdev, "configuring I2C controller");
+       retval = ufx_i2c_init(dev);
+       check_warn_goto_error(retval, "error %d initialising I2C controller", retval);
+
+       dev_dbg(dev->gdev, "selecting display mode");
+       retval = ufx_setup_modes(dev, info, NULL, 0);
+       check_warn_goto_error(retval, "unable to find common mode for display and adapter");
+
+       retval = ufx_reg_set_bits(dev, 0x4000, 0x00000001);
+       check_warn_goto_error(retval, "error %d enabling graphics engine", retval);
+
+       /* ready to begin using device */
+       atomic_set(&dev->usb_active, 1);
+
+       dev_dbg(dev->gdev, "checking var");
+       retval = ufx_ops_check_var(&info->var, info);
+       check_warn_goto_error(retval, "error %d ufx_ops_check_var", retval);
+
+       dev_dbg(dev->gdev, "setting par");
+       retval = ufx_ops_set_par(info);
+       check_warn_goto_error(retval, "error %d ufx_ops_set_par", retval);
+
+       dev_dbg(dev->gdev, "registering framebuffer");
+       retval = register_framebuffer(info);
+       check_warn_goto_error(retval, "error %d register_framebuffer", retval);
+
+       dev_info(dev->gdev, "SMSC UDX USB device /dev/fb%d attached. %dx%d resolution."
+               " Using %dK framebuffer memory\n", info->node,
+               info->var.xres, info->var.yres, info->fix.smem_len >> 10);
+
+       return 0;
+
+error:
+       if (dev) {
+               if (info) {
+                       if (info->cmap.len != 0)
+                               fb_dealloc_cmap(&info->cmap);
+                       if (info->monspecs.modedb)
+                               fb_destroy_modedb(info->monspecs.modedb);
+                       if (info->screen_base)
+                               vfree(info->screen_base);
+
+                       fb_destroy_modelist(&info->modelist);
+
+                       framebuffer_release(info);
+               }
+
+               kref_put(&dev->kref, ufx_free); /* ref for framebuffer */
+               kref_put(&dev->kref, ufx_free); /* last ref from kref_init */
+
+               /* dev has been deallocated. Do not dereference */
+       }
+
+       return retval;
+}
+
+static void ufx_usb_disconnect(struct usb_interface *interface)
+{
+       struct ufx_data *dev;
+       struct fb_info *info;
+
+       dev = usb_get_intfdata(interface);
+       info = dev->info;
+
+       pr_debug("USB disconnect starting\n");
+
+       /* we virtualize until all fb clients release. Then we free */
+       dev->virtualized = true;
+
+       /* When non-active we'll update virtual framebuffer, but no new urbs */
+       atomic_set(&dev->usb_active, 0);
+
+       usb_set_intfdata(interface, NULL);
+
+       /* if clients still have us open, will be freed on last close */
+       if (dev->fb_count == 0)
+               schedule_delayed_work(&dev->free_framebuffer_work, 0);
+
+       /* release reference taken by kref_init in probe() */
+       kref_put(&dev->kref, ufx_free);
+
+       /* consider ufx_data freed */
+}
+
+static struct usb_driver ufx_driver = {
+       .name = "smscufx",
+       .probe = ufx_usb_probe,
+       .disconnect = ufx_usb_disconnect,
+       .id_table = id_table,
+};
+
+static int __init ufx_module_init(void)
+{
+       int res;
+
+       res = usb_register(&ufx_driver);
+       if (res)
+               err("usb_register failed. Error number %d", res);
+
+       return res;
+}
+
+static void __exit ufx_module_exit(void)
+{
+       usb_deregister(&ufx_driver);
+}
+
+module_init(ufx_module_init);
+module_exit(ufx_module_exit);
+
+static void ufx_urb_completion(struct urb *urb)
+{
+       struct urb_node *unode = urb->context;
+       struct ufx_data *dev = unode->dev;
+       unsigned long flags;
+
+       /* sync/async unlink faults aren't errors */
+       if (urb->status) {
+               if (!(urb->status == -ENOENT ||
+                   urb->status == -ECONNRESET ||
+                   urb->status == -ESHUTDOWN)) {
+                       pr_err("%s - nonzero write bulk status received: %d\n",
+                               __func__, urb->status);
+                       atomic_set(&dev->lost_pixels, 1);
+               }
+       }
+
+       urb->transfer_buffer_length = dev->urbs.size; /* reset to actual */
+
+       spin_lock_irqsave(&dev->urbs.lock, flags);
+       list_add_tail(&unode->entry, &dev->urbs.list);
+       dev->urbs.available++;
+       spin_unlock_irqrestore(&dev->urbs.lock, flags);
+
+       /* When using fb_defio, we deadlock if up() is called
+        * while another is waiting. So queue to another process */
+       if (fb_defio)
+               schedule_delayed_work(&unode->release_urb_work, 0);
+       else
+               up(&dev->urbs.limit_sem);
+}
+
+static void ufx_free_urb_list(struct ufx_data *dev)
+{
+       int count = dev->urbs.count;
+       struct list_head *node;
+       struct urb_node *unode;
+       struct urb *urb;
+       int ret;
+       unsigned long flags;
+
+       pr_debug("Waiting for completes and freeing all render urbs\n");
+
+       /* keep waiting and freeing, until we've got 'em all */
+       while (count--) {
+               /* Getting interrupted means a leak, but ok at shutdown*/
+               ret = down_interruptible(&dev->urbs.limit_sem);
+               if (ret)
+                       break;
+
+               spin_lock_irqsave(&dev->urbs.lock, flags);
+
+               node = dev->urbs.list.next; /* have reserved one with sem */
+               list_del_init(node);
+
+               spin_unlock_irqrestore(&dev->urbs.lock, flags);
+
+               unode = list_entry(node, struct urb_node, entry);
+               urb = unode->urb;
+
+               /* Free each separately allocated piece */
+               usb_free_coherent(urb->dev, dev->urbs.size,
+                                 urb->transfer_buffer, urb->transfer_dma);
+               usb_free_urb(urb);
+               kfree(node);
+       }
+}
+
+static int ufx_alloc_urb_list(struct ufx_data *dev, int count, size_t size)
+{
+       int i = 0;
+       struct urb *urb;
+       struct urb_node *unode;
+       char *buf;
+
+       spin_lock_init(&dev->urbs.lock);
+
+       dev->urbs.size = size;
+       INIT_LIST_HEAD(&dev->urbs.list);
+
+       while (i < count) {
+               unode = kzalloc(sizeof(struct urb_node), GFP_KERNEL);
+               if (!unode)
+                       break;
+               unode->dev = dev;
+
+               INIT_DELAYED_WORK(&unode->release_urb_work,
+                         ufx_release_urb_work);
+
+               urb = usb_alloc_urb(0, GFP_KERNEL);
+               if (!urb) {
+                       kfree(unode);
+                       break;
+               }
+               unode->urb = urb;
+
+               buf = usb_alloc_coherent(dev->udev, size, GFP_KERNEL,
+                                        &urb->transfer_dma);
+               if (!buf) {
+                       kfree(unode);
+                       usb_free_urb(urb);
+                       break;
+               }
+
+               /* urb->transfer_buffer_length set to actual before submit */
+               usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 1),
+                       buf, size, ufx_urb_completion, unode);
+               urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+               list_add_tail(&unode->entry, &dev->urbs.list);
+
+               i++;
+       }
+
+       sema_init(&dev->urbs.limit_sem, i);
+       dev->urbs.count = i;
+       dev->urbs.available = i;
+
+       pr_debug("allocated %d %d byte urbs\n", i, (int) size);
+
+       return i;
+}
+
+static struct urb *ufx_get_urb(struct ufx_data *dev)
+{
+       int ret = 0;
+       struct list_head *entry;
+       struct urb_node *unode;
+       struct urb *urb = NULL;
+       unsigned long flags;
+
+       /* Wait for an in-flight buffer to complete and get re-queued */
+       ret = down_timeout(&dev->urbs.limit_sem, GET_URB_TIMEOUT);
+       if (ret) {
+               atomic_set(&dev->lost_pixels, 1);
+               pr_warn("wait for urb interrupted: %x available: %d\n",
+                      ret, dev->urbs.available);
+               goto error;
+       }
+
+       spin_lock_irqsave(&dev->urbs.lock, flags);
+
+       BUG_ON(list_empty(&dev->urbs.list)); /* reserved one with limit_sem */
+       entry = dev->urbs.list.next;
+       list_del_init(entry);
+       dev->urbs.available--;
+
+       spin_unlock_irqrestore(&dev->urbs.lock, flags);
+
+       unode = list_entry(entry, struct urb_node, entry);
+       urb = unode->urb;
+
+error:
+       return urb;
+}
+
+static int ufx_submit_urb(struct ufx_data *dev, struct urb *urb, size_t len)
+{
+       int ret;
+
+       BUG_ON(len > dev->urbs.size);
+
+       urb->transfer_buffer_length = len; /* set to actual payload len */
+       ret = usb_submit_urb(urb, GFP_KERNEL);
+       if (ret) {
+               ufx_urb_completion(urb); /* because no one else will */
+               atomic_set(&dev->lost_pixels, 1);
+               pr_err("usb_submit_urb error %x\n", ret);
+       }
+       return ret;
+}
+
+module_param(console, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
+MODULE_PARM_DESC(console, "Allow fbcon to be used on this display");
+
+module_param(fb_defio, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
+MODULE_PARM_DESC(fb_defio, "Enable fb_defio mmap support");
+
+MODULE_AUTHOR("Steve Glendinning <steve.glendinning@smsc.com>");
+MODULE_DESCRIPTION("SMSC UFX kernel framebuffer driver");
+MODULE_LICENSE("GPL");
index cd1c4dc..8e4a446 100644 (file)
@@ -744,7 +744,7 @@ static int __devinit tmiofb_probe(struct platform_device *dev)
                goto err_ioremap_vram;
        }
 
-       retval = request_irq(irq, &tmiofb_irq, IRQF_DISABLED,
+       retval = request_irq(irq, &tmiofb_irq, 0,
                                        dev_name(&dev->dev), info);
 
        if (retval)
index c6c7756..34cf019 100644 (file)
@@ -987,8 +987,8 @@ static int tridentfb_pan_display(struct fb_var_screeninfo *var,
        unsigned int offset;
 
        debug("enter\n");
-       offset = (var->xoffset + (var->yoffset * var->xres_virtual))
-               * var->bits_per_pixel / 32;
+       offset = (var->xoffset + (var->yoffset * info->var.xres_virtual))
+               * info->var.bits_per_pixel / 32;
        set_screen_start(par, offset);
        debug("exit\n");
        return 0;
index 087fc99..3473e75 100644 (file)
@@ -48,20 +48,30 @@ static const u32 udlfb_info_flags = FBINFO_DEFAULT | FBINFO_READS_FAST |
                FBINFO_HWACCEL_COPYAREA | FBINFO_MISC_ALWAYS_SETPAR;
 
 /*
- * There are many DisplayLink-based products, all with unique PIDs. We are able
- * to support all volume ones (circa 2009) with a single driver, so we match
- * globally on VID. TODO: Probe() needs to detect when we might be running
- * "future" chips, and bail on those, so a compatible driver can match.
+ * There are many DisplayLink-based graphics products, all with unique PIDs.
+ * So we match on DisplayLink's VID + Vendor-Defined Interface Class (0xff)
+ * We also require a match on SubClass (0x00) and Protocol (0x00),
+ * which is compatible with all known USB 2.0 era graphics chips and firmware,
+ * but allows DisplayLink to increment those for any future incompatible chips
  */
 static struct usb_device_id id_table[] = {
-       {.idVendor = 0x17e9, .match_flags = USB_DEVICE_ID_MATCH_VENDOR,},
+       {.idVendor = 0x17e9,
+        .bInterfaceClass = 0xff,
+        .bInterfaceSubClass = 0x00,
+        .bInterfaceProtocol = 0x00,
+        .match_flags = USB_DEVICE_ID_MATCH_VENDOR |
+               USB_DEVICE_ID_MATCH_INT_CLASS |
+               USB_DEVICE_ID_MATCH_INT_SUBCLASS |
+               USB_DEVICE_ID_MATCH_INT_PROTOCOL,
+       },
        {},
 };
 MODULE_DEVICE_TABLE(usb, id_table);
 
 /* module options */
-static int console;   /* Optionally allow fbcon to consume first framebuffer */
-static int fb_defio;  /* Optionally enable experimental fb_defio mmap support */
+static int console = 1; /* Allow fbcon to open framebuffer */
+static int fb_defio = 1;  /* Detect mmap writes using page faults */
+static int shadow = 1; /* Optionally disable shadow framebuffer */
 
 /* dlfb keeps a list of urbs for efficient bulk transfers */
 static void dlfb_urb_completion(struct urb *urb);
@@ -94,17 +104,39 @@ static char *dlfb_vidreg_unlock(char *buf)
 }
 
 /*
- * On/Off for driving the DisplayLink framebuffer to the display
- *  0x00 H and V sync on
- *  0x01 H and V sync off (screen blank but powered)
- *  0x07 DPMS powerdown (requires modeset to come back)
+ * Map FB_BLANK_* to DisplayLink register
+ * DLReg FB_BLANK_*
+ * ----- -----------------------------
+ *  0x00 FB_BLANK_UNBLANK (0)
+ *  0x01 FB_BLANK (1)
+ *  0x03 FB_BLANK_VSYNC_SUSPEND (2)
+ *  0x05 FB_BLANK_HSYNC_SUSPEND (3)
+ *  0x07 FB_BLANK_POWERDOWN (4) Note: requires modeset to come back
  */
-static char *dlfb_enable_hvsync(char *buf, bool enable)
+static char *dlfb_blanking(char *buf, int fb_blank)
 {
-       if (enable)
-               return dlfb_set_register(buf, 0x1F, 0x00);
-       else
-               return dlfb_set_register(buf, 0x1F, 0x07);
+       u8 reg;
+
+       switch (fb_blank) {
+       case FB_BLANK_POWERDOWN:
+               reg = 0x07;
+               break;
+       case FB_BLANK_HSYNC_SUSPEND:
+               reg = 0x05;
+               break;
+       case FB_BLANK_VSYNC_SUSPEND:
+               reg = 0x03;
+               break;
+       case FB_BLANK_NORMAL:
+               reg = 0x01;
+               break;
+       default:
+               reg = 0x00;
+       }
+
+       buf = dlfb_set_register(buf, 0x1F, reg);
+
+       return buf;
 }
 
 static char *dlfb_set_color_depth(char *buf, u8 selection)
@@ -272,13 +304,15 @@ static int dlfb_set_video_mode(struct dlfb_data *dev,
        wrptr = dlfb_set_base8bpp(wrptr, dev->info->fix.smem_len);
 
        wrptr = dlfb_set_vid_cmds(wrptr, var);
-       wrptr = dlfb_enable_hvsync(wrptr, true);
+       wrptr = dlfb_blanking(wrptr, FB_BLANK_UNBLANK);
        wrptr = dlfb_vidreg_unlock(wrptr);
 
        writesize = wrptr - buf;
 
        retval = dlfb_submit_urb(dev, urb, writesize);
 
+       dev->blank_mode = FB_BLANK_UNBLANK;
+
        return retval;
 }
 
@@ -752,14 +786,13 @@ static int dlfb_ops_ioctl(struct fb_info *info, unsigned int cmd,
 {
 
        struct dlfb_data *dev = info->par;
-       struct dloarea *area = NULL;
 
        if (!atomic_read(&dev->usb_active))
                return 0;
 
        /* TODO: Update X server to get this from sysfs instead */
        if (cmd == DLFB_IOCTL_RETURN_EDID) {
-               char *edid = (char *)arg;
+               void __user *edid = (void __user *)arg;
                if (copy_to_user(edid, dev->edid, dev->edid_size))
                        return -EFAULT;
                return 0;
@@ -767,6 +800,11 @@ static int dlfb_ops_ioctl(struct fb_info *info, unsigned int cmd,
 
        /* TODO: Help propose a standard fb.h ioctl to report mmap damage */
        if (cmd == DLFB_IOCTL_REPORT_DAMAGE) {
+               struct dloarea area;
+
+               if (copy_from_user(&area, (void __user *)arg,
+                                 sizeof(struct dloarea)))
+                       return -EFAULT;
 
                /*
                 * If we have a damage-aware client, turn fb_defio "off"
@@ -778,21 +816,19 @@ static int dlfb_ops_ioctl(struct fb_info *info, unsigned int cmd,
                if (info->fbdefio)
                        info->fbdefio->delay = DL_DEFIO_WRITE_DISABLE;
 
-               area = (struct dloarea *)arg;
+               if (area.x < 0)
+                       area.x = 0;
 
-               if (area->x < 0)
-                       area->x = 0;
+               if (area.x > info->var.xres)
+                       area.x = info->var.xres;
 
-               if (area->x > info->var.xres)
-                       area->x = info->var.xres;
+               if (area.y < 0)
+                       area.y = 0;
 
-               if (area->y < 0)
-                       area->y = 0;
+               if (area.y > info->var.yres)
+                       area.y = info->var.yres;
 
-               if (area->y > info->var.yres)
-                       area->y = info->var.yres;
-
-               dlfb_handle_damage(dev, area->x, area->y, area->w, area->h,
+               dlfb_handle_damage(dev, area.x, area.y, area.w, area.h,
                           info->screen_base);
        }
 
@@ -840,7 +876,7 @@ static int dlfb_ops_open(struct fb_info *info, int user)
         * preventing other clients (X) from working properly. Usually
         * not what the user wants. Fail by default with option to enable.
         */
-       if ((user == 0) & (!console))
+       if ((user == 0) && (!console))
                return -EBUSY;
 
        /* If the USB device is gone, we don't accept new opens */
@@ -1039,32 +1075,57 @@ static int dlfb_ops_set_par(struct fb_info *info)
        return result;
 }
 
+/* To fonzi the jukebox (e.g. make blanking changes take effect) */
+static char *dlfb_dummy_render(char *buf)
+{
+       *buf++ = 0xAF;
+       *buf++ = 0x6A; /* copy */
+       *buf++ = 0x00; /* from address*/
+       *buf++ = 0x00;
+       *buf++ = 0x00;
+       *buf++ = 0x01; /* one pixel */
+       *buf++ = 0x00; /* to address */
+       *buf++ = 0x00;
+       *buf++ = 0x00;
+       return buf;
+}
+
 /*
  * In order to come back from full DPMS off, we need to set the mode again
  */
 static int dlfb_ops_blank(int blank_mode, struct fb_info *info)
 {
        struct dlfb_data *dev = info->par;
+       char *bufptr;
+       struct urb *urb;
 
-       if (blank_mode != FB_BLANK_UNBLANK) {
-               char *bufptr;
-               struct urb *urb;
-
-               urb = dlfb_get_urb(dev);
-               if (!urb)
-                       return 0;
+       pr_info("/dev/fb%d FB_BLANK mode %d --> %d\n",
+               info->node, dev->blank_mode, blank_mode);
 
-               bufptr = (char *) urb->transfer_buffer;
-               bufptr = dlfb_vidreg_lock(bufptr);
-               bufptr = dlfb_enable_hvsync(bufptr, false);
-               bufptr = dlfb_vidreg_unlock(bufptr);
+       if ((dev->blank_mode == FB_BLANK_POWERDOWN) &&
+           (blank_mode != FB_BLANK_POWERDOWN)) {
 
-               dlfb_submit_urb(dev, urb, bufptr -
-                               (char *) urb->transfer_buffer);
-       } else {
+               /* returning from powerdown requires a fresh modeset */
                dlfb_set_video_mode(dev, &info->var);
        }
 
+       urb = dlfb_get_urb(dev);
+       if (!urb)
+               return 0;
+
+       bufptr = (char *) urb->transfer_buffer;
+       bufptr = dlfb_vidreg_lock(bufptr);
+       bufptr = dlfb_blanking(bufptr, blank_mode);
+       bufptr = dlfb_vidreg_unlock(bufptr);
+
+       /* seems like a render op is needed to have blank change take effect */
+       bufptr = dlfb_dummy_render(bufptr);
+
+       dlfb_submit_urb(dev, urb, bufptr -
+                       (char *) urb->transfer_buffer);
+
+       dev->blank_mode = blank_mode;
+
        return 0;
 }
 
@@ -1097,7 +1158,7 @@ static int dlfb_realloc_framebuffer(struct dlfb_data *dev, struct fb_info *info)
        int new_len;
        unsigned char *old_fb = info->screen_base;
        unsigned char *new_fb;
-       unsigned char *new_back;
+       unsigned char *new_back = 0;
 
        pr_warn("Reallocating framebuffer. Addresses will change!\n");
 
@@ -1129,7 +1190,8 @@ static int dlfb_realloc_framebuffer(struct dlfb_data *dev, struct fb_info *info)
                 * But with imperfect damage info we may send pixels over USB
                 * that were, in fact, unchanged - wasting limited USB bandwidth
                 */
-               new_back = vzalloc(new_len);
+               if (shadow)
+                       new_back = vzalloc(new_len);
                if (!new_back)
                        pr_info("No shadow/backing buffer allocated\n");
                else {
@@ -1430,21 +1492,30 @@ static int dlfb_select_std_channel(struct dlfb_data *dev)
 }
 
 static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev,
-                                       struct usb_device *usbdev)
+                                       struct usb_interface *interface)
 {
        char *desc;
        char *buf;
        char *desc_end;
 
-       u8 total_len = 0;
+       int total_len = 0;
 
        buf = kzalloc(MAX_VENDOR_DESCRIPTOR_SIZE, GFP_KERNEL);
        if (!buf)
                return false;
        desc = buf;
 
-       total_len = usb_get_descriptor(usbdev, 0x5f, /* vendor specific */
-                                   0, desc, MAX_VENDOR_DESCRIPTOR_SIZE);
+       total_len = usb_get_descriptor(interface_to_usbdev(interface),
+                                       0x5f, /* vendor specific */
+                                       0, desc, MAX_VENDOR_DESCRIPTOR_SIZE);
+
+       /* if not found, look in configuration descriptor */
+       if (total_len < 0) {
+               if (0 == usb_get_extra_descriptor(interface->cur_altsetting,
+                       0x5f, &desc))
+                       total_len = (int) desc[0];
+       }
+
        if (total_len > 5) {
                pr_info("vendor descriptor length:%x data:%02x %02x %02x %02x" \
                        "%02x %02x %02x %02x %02x %02x %02x\n",
@@ -1485,6 +1556,8 @@ static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev,
                        }
                        desc += length;
                }
+       } else {
+               pr_info("vendor descriptor not available (%d)\n", total_len);
        }
 
        goto success;
@@ -1531,10 +1604,11 @@ static int dlfb_usb_probe(struct usb_interface *interface,
                usbdev->descriptor.bcdDevice, dev);
        pr_info("console enable=%d\n", console);
        pr_info("fb_defio enable=%d\n", fb_defio);
+       pr_info("shadow enable=%d\n", shadow);
 
        dev->sku_pixel_limit = 2048 * 1152; /* default to maximum */
 
-       if (!dlfb_parse_vendor_descriptor(dev, usbdev)) {
+       if (!dlfb_parse_vendor_descriptor(dev, interface)) {
                pr_err("firmware not recognized. Assume incompatible device\n");
                goto error;
        }
@@ -1548,7 +1622,7 @@ static int dlfb_usb_probe(struct usb_interface *interface,
        /* We don't register a new USB class. Our client interface is fbdev */
 
        /* allocates framebuffer driver structure, not framebuffer memory */
-       info = framebuffer_alloc(0, &usbdev->dev);
+       info = framebuffer_alloc(0, &interface->dev);
        if (!info) {
                retval = -ENOMEM;
                pr_err("framebuffer_alloc failed\n");
@@ -1883,10 +1957,13 @@ static int dlfb_submit_urb(struct dlfb_data *dev, struct urb *urb, size_t len)
 }
 
 module_param(console, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
-MODULE_PARM_DESC(console, "Allow fbcon to consume first framebuffer found");
+MODULE_PARM_DESC(console, "Allow fbcon to open framebuffer");
 
 module_param(fb_defio, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
-MODULE_PARM_DESC(fb_defio, "Enable fb_defio mmap support. *Experimental*");
+MODULE_PARM_DESC(fb_defio, "Page fault detection of mmap writes");
+
+module_param(shadow, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
+MODULE_PARM_DESC(shadow, "Shadow vid mem. Disable to save mem but lose perf");
 
 MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, "
              "Jaya Kumar <jayakumar.lkml@gmail.com>, "
index 6b52bf6..3f5a041 100644 (file)
@@ -555,7 +555,7 @@ static int __init valkyrie_init_info(struct fb_info *info,
 
 
 /*
- * Parse user speficied options (`video=valkyriefb:')
+ * Parse user specified options (`video=valkyriefb:')
  */
 int __init valkyriefb_setup(char *options)
 {
index bc67251..bf2f780 100644 (file)
@@ -395,8 +395,8 @@ static int vfb_pan_display(struct fb_var_screeninfo *var,
                    || var->xoffset)
                        return -EINVAL;
        } else {
-               if (var->xoffset + var->xres > info->var.xres_virtual ||
-                   var->yoffset + var->yres > info->var.yres_virtual)
+               if (var->xoffset + info->var.xres > info->var.xres_virtual ||
+                   var->yoffset + info->var.yres > info->var.yres_virtual)
                        return -EINVAL;
        }
        info->var.xoffset = var->xoffset;
index 305c975..0267acd 100644 (file)
@@ -207,7 +207,7 @@ static void vga16fb_pan_var(struct fb_info *info,
         * granularity if someone supports xoffset in bit resolution */
        vga_io_r(VGA_IS1_RC);           /* reset flip-flop */
        vga_io_w(VGA_ATT_IW, VGA_ATC_PEL);
-       if (var->bits_per_pixel == 8)
+       if (info->var.bits_per_pixel == 8)
                vga_io_w(VGA_ATT_IW, (xoffset & 3) << 1);
        else
                vga_io_w(VGA_ATT_IW, xoffset & 7);
index b1f3647..9138e51 100644 (file)
@@ -172,30 +172,20 @@ static int tmds_register_read_bytes(int index, u8 *buff, int buff_len)
 }
 
 /* DVI Set Mode */
-void viafb_dvi_set_mode(struct VideoModeTable *mode, int mode_bpp,
-       int set_iga)
+void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, int iga)
 {
-       struct VideoModeTable *rb_mode;
-       struct crt_mode_table *pDviTiming;
-       unsigned long desirePixelClock, maxPixelClock;
-       pDviTiming = mode->crtc;
-       desirePixelClock = pDviTiming->refresh_rate
-               * pDviTiming->crtc.hor_total * pDviTiming->crtc.ver_total
-               / 1000000;
-       maxPixelClock = (unsigned long)viaparinfo->
-               tmds_setting_info->max_pixel_clock;
-
-       DEBUG_MSG(KERN_INFO "\nDVI_set_mode!!\n");
-
-       if ((maxPixelClock != 0) && (desirePixelClock > maxPixelClock)) {
-               rb_mode = viafb_get_rb_mode(mode->crtc[0].crtc.hor_addr,
-                       mode->crtc[0].crtc.ver_addr);
-               if (rb_mode) {
-                       mode = rb_mode;
-                       pDviTiming = rb_mode->crtc;
-               }
+       struct fb_var_screeninfo dvi_var = *var;
+       struct crt_mode_table *rb_mode;
+       int maxPixelClock;
+
+       maxPixelClock = viaparinfo->shared->tmds_setting_info.max_pixel_clock;
+       if (maxPixelClock && PICOS2KHZ(var->pixclock) / 1000 > maxPixelClock) {
+               rb_mode = viafb_get_best_rb_mode(var->xres, var->yres, 60);
+               if (rb_mode)
+                       viafb_fill_var_timing_info(&dvi_var, rb_mode);
        }
-       viafb_fill_crtc_timing(pDviTiming, mode, mode_bpp / 8, set_iga);
+
+       viafb_fill_crtc_timing(&dvi_var, iga);
 }
 
 /* Sense DVI Connector */
index f473dd0..e2116aa 100644 (file)
@@ -59,7 +59,6 @@ void viafb_dvi_enable(void);
 bool __devinit viafb_tmds_trasmitter_identify(void);
 void __devinit viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
        struct tmds_setting_information *tmds_setting);
-void viafb_dvi_set_mode(struct VideoModeTable *videoMode, int mode_bpp,
-       int set_iga);
+void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, int iga);
 
 #endif /* __DVI_H__ */
index e10d824..3102171 100644 (file)
@@ -35,6 +35,8 @@ int viafb_LCD_ON ;
 int viafb_LCD2_ON;
 int viafb_SAMM_ON;
 int viafb_dual_fb;
+unsigned int viafb_second_xres = 640;
+unsigned int viafb_second_yres = 480;
 int viafb_hotplug_Xres = 640;
 int viafb_hotplug_Yres = 480;
 int viafb_hotplug_bpp = 32;
index ff969dc..275dbbb 100644 (file)
@@ -67,6 +67,8 @@ extern int viafb_lcd_dsp_method;
 extern int viafb_lcd_mode;
 
 extern int viafb_CRT_ON;
+extern unsigned int viafb_second_xres;
+extern unsigned int viafb_second_yres;
 extern int viafb_hotplug_Xres;
 extern int viafb_hotplug_Yres;
 extern int viafb_hotplug_bpp;
index 47b1353..d5aaca9 100644 (file)
@@ -191,67 +191,6 @@ static struct fetch_count fetch_count_reg = {
        {IGA2_FETCH_COUNT_REG_NUM, {{CR65, 0, 7}, {CR67, 2, 3} } }
 };
 
-static struct iga1_crtc_timing iga1_crtc_reg = {
-       /* IGA1 Horizontal Total */
-       {IGA1_HOR_TOTAL_REG_NUM, {{CR00, 0, 7}, {CR36, 3, 3} } },
-       /* IGA1 Horizontal Addressable Video */
-       {IGA1_HOR_ADDR_REG_NUM, {{CR01, 0, 7} } },
-       /* IGA1 Horizontal Blank Start */
-       {IGA1_HOR_BLANK_START_REG_NUM, {{CR02, 0, 7} } },
-       /* IGA1 Horizontal Blank End */
-       {IGA1_HOR_BLANK_END_REG_NUM,
-        {{CR03, 0, 4}, {CR05, 7, 7}, {CR33, 5, 5} } },
-       /* IGA1 Horizontal Sync Start */
-       {IGA1_HOR_SYNC_START_REG_NUM, {{CR04, 0, 7}, {CR33, 4, 4} } },
-       /* IGA1 Horizontal Sync End */
-       {IGA1_HOR_SYNC_END_REG_NUM, {{CR05, 0, 4} } },
-       /* IGA1 Vertical Total */
-       {IGA1_VER_TOTAL_REG_NUM,
-        {{CR06, 0, 7}, {CR07, 0, 0}, {CR07, 5, 5}, {CR35, 0, 0} } },
-       /* IGA1 Vertical Addressable Video */
-       {IGA1_VER_ADDR_REG_NUM,
-        {{CR12, 0, 7}, {CR07, 1, 1}, {CR07, 6, 6}, {CR35, 2, 2} } },
-       /* IGA1 Vertical Blank Start */
-       {IGA1_VER_BLANK_START_REG_NUM,
-        {{CR15, 0, 7}, {CR07, 3, 3}, {CR09, 5, 5}, {CR35, 3, 3} } },
-       /* IGA1 Vertical Blank End */
-       {IGA1_VER_BLANK_END_REG_NUM, {{CR16, 0, 7} } },
-       /* IGA1 Vertical Sync Start */
-       {IGA1_VER_SYNC_START_REG_NUM,
-        {{CR10, 0, 7}, {CR07, 2, 2}, {CR07, 7, 7}, {CR35, 1, 1} } },
-       /* IGA1 Vertical Sync End */
-       {IGA1_VER_SYNC_END_REG_NUM, {{CR11, 0, 3} } }
-};
-
-static struct iga2_crtc_timing iga2_crtc_reg = {
-       /* IGA2 Horizontal Total */
-       {IGA2_HOR_TOTAL_REG_NUM, {{CR50, 0, 7}, {CR55, 0, 3} } },
-       /* IGA2 Horizontal Addressable Video */
-       {IGA2_HOR_ADDR_REG_NUM, {{CR51, 0, 7}, {CR55, 4, 6} } },
-       /* IGA2 Horizontal Blank Start */
-       {IGA2_HOR_BLANK_START_REG_NUM, {{CR52, 0, 7}, {CR54, 0, 2} } },
-       /* IGA2 Horizontal Blank End */
-       {IGA2_HOR_BLANK_END_REG_NUM,
-        {{CR53, 0, 7}, {CR54, 3, 5}, {CR5D, 6, 6} } },
-       /* IGA2 Horizontal Sync Start */
-       {IGA2_HOR_SYNC_START_REG_NUM,
-        {{CR56, 0, 7}, {CR54, 6, 7}, {CR5C, 7, 7}, {CR5D, 7, 7} } },
-       /* IGA2 Horizontal Sync End */
-       {IGA2_HOR_SYNC_END_REG_NUM, {{CR57, 0, 7}, {CR5C, 6, 6} } },
-       /* IGA2 Vertical Total */
-       {IGA2_VER_TOTAL_REG_NUM, {{CR58, 0, 7}, {CR5D, 0, 2} } },
-       /* IGA2 Vertical Addressable Video */
-       {IGA2_VER_ADDR_REG_NUM, {{CR59, 0, 7}, {CR5D, 3, 5} } },
-       /* IGA2 Vertical Blank Start */
-       {IGA2_VER_BLANK_START_REG_NUM, {{CR5A, 0, 7}, {CR5C, 0, 2} } },
-       /* IGA2 Vertical Blank End */
-       {IGA2_VER_BLANK_END_REG_NUM, {{CR5B, 0, 7}, {CR5C, 3, 5} } },
-       /* IGA2 Vertical Sync Start */
-       {IGA2_VER_SYNC_START_REG_NUM, {{CR5E, 0, 7}, {CR5F, 5, 7} } },
-       /* IGA2 Vertical Sync End */
-       {IGA2_VER_SYNC_END_REG_NUM, {{CR5F, 0, 4} } }
-};
-
 static struct rgbLUT palLUT_table[] = {
        /* {R,G,B} */
        /* Index 0x00~0x03 */
@@ -1528,302 +1467,40 @@ void viafb_set_vclock(u32 clk, int set_iga)
        via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */
 }
 
-void viafb_load_crtc_timing(struct display_timing device_timing,
-       int set_iga)
+static struct display_timing var_to_timing(const struct fb_var_screeninfo *var)
 {
-       int i;
-       int viafb_load_reg_num = 0;
-       int reg_value = 0;
-       struct io_register *reg = NULL;
-
-       viafb_unlock_crt();
-
-       for (i = 0; i < 12; i++) {
-               if (set_iga == IGA1) {
-                       switch (i) {
-                       case H_TOTAL_INDEX:
-                               reg_value =
-                                   IGA1_HOR_TOTAL_FORMULA(device_timing.
-                                                          hor_total);
-                               viafb_load_reg_num =
-                                       iga1_crtc_reg.hor_total.reg_num;
-                               reg = iga1_crtc_reg.hor_total.reg;
-                               break;
-                       case H_ADDR_INDEX:
-                               reg_value =
-                                   IGA1_HOR_ADDR_FORMULA(device_timing.
-                                                         hor_addr);
-                               viafb_load_reg_num =
-                                       iga1_crtc_reg.hor_addr.reg_num;
-                               reg = iga1_crtc_reg.hor_addr.reg;
-                               break;
-                       case H_BLANK_START_INDEX:
-                               reg_value =
-                                   IGA1_HOR_BLANK_START_FORMULA
-                                   (device_timing.hor_blank_start);
-                               viafb_load_reg_num =
-                                   iga1_crtc_reg.hor_blank_start.reg_num;
-                               reg = iga1_crtc_reg.hor_blank_start.reg;
-                               break;
-                       case H_BLANK_END_INDEX:
-                               reg_value =
-                                   IGA1_HOR_BLANK_END_FORMULA
-                                   (device_timing.hor_blank_start,
-                                    device_timing.hor_blank_end);
-                               viafb_load_reg_num =
-                                   iga1_crtc_reg.hor_blank_end.reg_num;
-                               reg = iga1_crtc_reg.hor_blank_end.reg;
-                               break;
-                       case H_SYNC_START_INDEX:
-                               reg_value =
-                                   IGA1_HOR_SYNC_START_FORMULA
-                                   (device_timing.hor_sync_start);
-                               viafb_load_reg_num =
-                                   iga1_crtc_reg.hor_sync_start.reg_num;
-                               reg = iga1_crtc_reg.hor_sync_start.reg;
-                               break;
-                       case H_SYNC_END_INDEX:
-                               reg_value =
-                                   IGA1_HOR_SYNC_END_FORMULA
-                                   (device_timing.hor_sync_start,
-                                    device_timing.hor_sync_end);
-                               viafb_load_reg_num =
-                                   iga1_crtc_reg.hor_sync_end.reg_num;
-                               reg = iga1_crtc_reg.hor_sync_end.reg;
-                               break;
-                       case V_TOTAL_INDEX:
-                               reg_value =
-                                   IGA1_VER_TOTAL_FORMULA(device_timing.
-                                                          ver_total);
-                               viafb_load_reg_num =
-                                       iga1_crtc_reg.ver_total.reg_num;
-                               reg = iga1_crtc_reg.ver_total.reg;
-                               break;
-                       case V_ADDR_INDEX:
-                               reg_value =
-                                   IGA1_VER_ADDR_FORMULA(device_timing.
-                                                         ver_addr);
-                               viafb_load_reg_num =
-                                       iga1_crtc_reg.ver_addr.reg_num;
-                               reg = iga1_crtc_reg.ver_addr.reg;
-                               break;
-                       case V_BLANK_START_INDEX:
-                               reg_value =
-                                   IGA1_VER_BLANK_START_FORMULA
-                                   (device_timing.ver_blank_start);
-                               viafb_load_reg_num =
-                                   iga1_crtc_reg.ver_blank_start.reg_num;
-                               reg = iga1_crtc_reg.ver_blank_start.reg;
-                               break;
-                       case V_BLANK_END_INDEX:
-                               reg_value =
-                                   IGA1_VER_BLANK_END_FORMULA
-                                   (device_timing.ver_blank_start,
-                                    device_timing.ver_blank_end);
-                               viafb_load_reg_num =
-                                   iga1_crtc_reg.ver_blank_end.reg_num;
-                               reg = iga1_crtc_reg.ver_blank_end.reg;
-                               break;
-                       case V_SYNC_START_INDEX:
-                               reg_value =
-                                   IGA1_VER_SYNC_START_FORMULA
-                                   (device_timing.ver_sync_start);
-                               viafb_load_reg_num =
-                                   iga1_crtc_reg.ver_sync_start.reg_num;
-                               reg = iga1_crtc_reg.ver_sync_start.reg;
-                               break;
-                       case V_SYNC_END_INDEX:
-                               reg_value =
-                                   IGA1_VER_SYNC_END_FORMULA
-                                   (device_timing.ver_sync_start,
-                                    device_timing.ver_sync_end);
-                               viafb_load_reg_num =
-                                   iga1_crtc_reg.ver_sync_end.reg_num;
-                               reg = iga1_crtc_reg.ver_sync_end.reg;
-                               break;
-
-                       }
-               }
-
-               if (set_iga == IGA2) {
-                       switch (i) {
-                       case H_TOTAL_INDEX:
-                               reg_value =
-                                   IGA2_HOR_TOTAL_FORMULA(device_timing.
-                                                          hor_total);
-                               viafb_load_reg_num =
-                                       iga2_crtc_reg.hor_total.reg_num;
-                               reg = iga2_crtc_reg.hor_total.reg;
-                               break;
-                       case H_ADDR_INDEX:
-                               reg_value =
-                                   IGA2_HOR_ADDR_FORMULA(device_timing.
-                                                         hor_addr);
-                               viafb_load_reg_num =
-                                       iga2_crtc_reg.hor_addr.reg_num;
-                               reg = iga2_crtc_reg.hor_addr.reg;
-                               break;
-                       case H_BLANK_START_INDEX:
-                               reg_value =
-                                   IGA2_HOR_BLANK_START_FORMULA
-                                   (device_timing.hor_blank_start);
-                               viafb_load_reg_num =
-                                   iga2_crtc_reg.hor_blank_start.reg_num;
-                               reg = iga2_crtc_reg.hor_blank_start.reg;
-                               break;
-                       case H_BLANK_END_INDEX:
-                               reg_value =
-                                   IGA2_HOR_BLANK_END_FORMULA
-                                   (device_timing.hor_blank_start,
-                                    device_timing.hor_blank_end);
-                               viafb_load_reg_num =
-                                   iga2_crtc_reg.hor_blank_end.reg_num;
-                               reg = iga2_crtc_reg.hor_blank_end.reg;
-                               break;
-                       case H_SYNC_START_INDEX:
-                               reg_value =
-                                   IGA2_HOR_SYNC_START_FORMULA
-                                   (device_timing.hor_sync_start);
-                               if (UNICHROME_CN700 <=
-                                       viaparinfo->chip_info->gfx_chip_name)
-                                       viafb_load_reg_num =
-                                           iga2_crtc_reg.hor_sync_start.
-                                           reg_num;
-                               else
-                                       viafb_load_reg_num = 3;
-                               reg = iga2_crtc_reg.hor_sync_start.reg;
-                               break;
-                       case H_SYNC_END_INDEX:
-                               reg_value =
-                                   IGA2_HOR_SYNC_END_FORMULA
-                                   (device_timing.hor_sync_start,
-                                    device_timing.hor_sync_end);
-                               viafb_load_reg_num =
-                                   iga2_crtc_reg.hor_sync_end.reg_num;
-                               reg = iga2_crtc_reg.hor_sync_end.reg;
-                               break;
-                       case V_TOTAL_INDEX:
-                               reg_value =
-                                   IGA2_VER_TOTAL_FORMULA(device_timing.
-                                                          ver_total);
-                               viafb_load_reg_num =
-                                       iga2_crtc_reg.ver_total.reg_num;
-                               reg = iga2_crtc_reg.ver_total.reg;
-                               break;
-                       case V_ADDR_INDEX:
-                               reg_value =
-                                   IGA2_VER_ADDR_FORMULA(device_timing.
-                                                         ver_addr);
-                               viafb_load_reg_num =
-                                       iga2_crtc_reg.ver_addr.reg_num;
-                               reg = iga2_crtc_reg.ver_addr.reg;
-                               break;
-                       case V_BLANK_START_INDEX:
-                               reg_value =
-                                   IGA2_VER_BLANK_START_FORMULA
-                                   (device_timing.ver_blank_start);
-                               viafb_load_reg_num =
-                                   iga2_crtc_reg.ver_blank_start.reg_num;
-                               reg = iga2_crtc_reg.ver_blank_start.reg;
-                               break;
-                       case V_BLANK_END_INDEX:
-                               reg_value =
-                                   IGA2_VER_BLANK_END_FORMULA
-                                   (device_timing.ver_blank_start,
-                                    device_timing.ver_blank_end);
-                               viafb_load_reg_num =
-                                   iga2_crtc_reg.ver_blank_end.reg_num;
-                               reg = iga2_crtc_reg.ver_blank_end.reg;
-                               break;
-                       case V_SYNC_START_INDEX:
-                               reg_value =
-                                   IGA2_VER_SYNC_START_FORMULA
-                                   (device_timing.ver_sync_start);
-                               viafb_load_reg_num =
-                                   iga2_crtc_reg.ver_sync_start.reg_num;
-                               reg = iga2_crtc_reg.ver_sync_start.reg;
-                               break;
-                       case V_SYNC_END_INDEX:
-                               reg_value =
-                                   IGA2_VER_SYNC_END_FORMULA
-                                   (device_timing.ver_sync_start,
-                                    device_timing.ver_sync_end);
-                               viafb_load_reg_num =
-                                   iga2_crtc_reg.ver_sync_end.reg_num;
-                               reg = iga2_crtc_reg.ver_sync_end.reg;
-                               break;
-
-                       }
-               }
-               viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
-       }
-
-       viafb_lock_crt();
+       struct display_timing timing;
+
+       timing.hor_addr = var->xres;
+       timing.hor_sync_start = timing.hor_addr + var->right_margin;
+       timing.hor_sync_end = timing.hor_sync_start + var->hsync_len;
+       timing.hor_total = timing.hor_sync_end + var->left_margin;
+       timing.hor_blank_start = timing.hor_addr;
+       timing.hor_blank_end = timing.hor_total;
+       timing.ver_addr = var->yres;
+       timing.ver_sync_start = timing.ver_addr + var->lower_margin;
+       timing.ver_sync_end = timing.ver_sync_start + var->vsync_len;
+       timing.ver_total = timing.ver_sync_end + var->upper_margin;
+       timing.ver_blank_start = timing.ver_addr;
+       timing.ver_blank_end = timing.ver_total;
+       return timing;
 }
 
-void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
-       struct VideoModeTable *video_mode, int bpp_byte, int set_iga)
+void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, int iga)
 {
-       struct display_timing crt_reg;
-       int i;
-       int index = 0;
-       int h_addr, v_addr;
-       u32 clock, refresh = viafb_refresh;
-
-       if (viafb_SAMM_ON && set_iga == IGA2)
-               refresh = viafb_refresh1;
-
-       for (i = 0; i < video_mode->mode_array; i++) {
-               index = i;
-
-               if (crt_table[i].refresh_rate == refresh)
-                       break;
-       }
+       struct display_timing crt_reg = var_to_timing(var);
 
-       crt_reg = crt_table[index].crtc;
+       if (iga == IGA1)
+               via_set_primary_timing(&crt_reg);
+       else if (iga == IGA2)
+               via_set_secondary_timing(&crt_reg);
 
-       /* Mode 640x480 has border, but LCD/DFP didn't have border. */
-       /* So we would delete border. */
-       if ((viafb_LCD_ON | viafb_DVI_ON)
-           && video_mode->crtc[0].crtc.hor_addr == 640
-           && video_mode->crtc[0].crtc.ver_addr == 480
-           && refresh == 60) {
-               /* The border is 8 pixels. */
-               crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8;
-
-               /* Blanking time should add left and right borders. */
-               crt_reg.hor_blank_end = crt_reg.hor_blank_end + 16;
-       }
-
-       h_addr = crt_reg.hor_addr;
-       v_addr = crt_reg.ver_addr;
-       if (set_iga == IGA1) {
-               viafb_unlock_crt();
-               viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
-       }
-
-       switch (set_iga) {
-       case IGA1:
-               viafb_load_crtc_timing(crt_reg, IGA1);
-               break;
-       case IGA2:
-               viafb_load_crtc_timing(crt_reg, IGA2);
-               break;
-       }
-
-       viafb_lock_crt();
-       viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
-       viafb_load_fetch_count_reg(h_addr, bpp_byte, set_iga);
-
-       /* load FIFO */
-       if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
-           && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
-               viafb_load_FIFO_reg(set_iga, h_addr, v_addr);
-
-       clock = crt_reg.hor_total * crt_reg.ver_total
-               * crt_table[index].refresh_rate;
-       viafb_set_vclock(clock, set_iga);
+       viafb_load_fetch_count_reg(var->xres, var->bits_per_pixel / 8, iga);
+       if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266
+               && viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)
+               viafb_load_FIFO_reg(iga, var->xres, var->yres);
 
+       viafb_set_vclock(PICOS2KHZ(var->pixclock) * 1000, iga);
 }
 
 void __devinit viafb_init_chip_info(int chip_type)
@@ -2092,23 +1769,9 @@ static u8 get_sync(struct fb_info *info)
        return polarity;
 }
 
-int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
-       struct VideoModeTable *vmode_tbl1, int video_bpp1)
+static void hw_init(void)
 {
-       int i, j;
-       int port;
-       u32 devices = viaparinfo->shared->iga1_devices
-               | viaparinfo->shared->iga2_devices;
-       u8 value, index, mask;
-       struct crt_mode_table *crt_timing;
-       struct crt_mode_table *crt_timing1 = NULL;
-
-       device_screen_off();
-       crt_timing = vmode_tbl->crtc;
-
-       if (viafb_SAMM_ON == 1) {
-               crt_timing1 = vmode_tbl1->crtc;
-       }
+       int i;
 
        inb(VIAStatus);
        outb(0x00, VIAAR);
@@ -2147,9 +1810,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
                break;
        }
 
+       /* probably this should go to the scaling code one day */
        viafb_write_regx(scaling_parameters, ARRAY_SIZE(scaling_parameters));
-       device_off();
-       via_set_state(devices, VIA_STATE_OFF);
 
        /* Fill VPIT Parameters */
        /* Write Misc Register */
@@ -2175,12 +1837,29 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
        inb(VIAStatus);
        outb(0x20, VIAAR);
 
+       load_fix_bit_crtc_reg();
+}
+
+int viafb_setmode(int video_bpp, int video_bpp1)
+{
+       int j;
+       int port;
+       u32 devices = viaparinfo->shared->iga1_devices
+               | viaparinfo->shared->iga2_devices;
+       u8 value, index, mask;
+       struct fb_var_screeninfo var2;
+
+       device_screen_off();
+       device_off();
+       via_set_state(devices, VIA_STATE_OFF);
+
+       hw_init();
+
        /* Update Patch Register */
 
        if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266
-           || viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400)
-           && vmode_tbl->crtc[0].crtc.hor_addr == 1024
-           && vmode_tbl->crtc[0].crtc.ver_addr == 768) {
+               || viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400)
+               && viafbinfo->var.xres == 1024 && viafbinfo->var.yres == 768) {
                for (j = 0; j < res_patch_table[0].table_length; j++) {
                        index = res_patch_table[0].io_reg_table[j].index;
                        port = res_patch_table[0].io_reg_table[j].port;
@@ -2190,7 +1869,6 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
                }
        }
 
-       load_fix_bit_crtc_reg();
        via_set_primary_pitch(viafbinfo->fix.line_length);
        via_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length
                : viafbinfo->fix.line_length);
@@ -2208,23 +1886,28 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
 
        /* Clear On Screen */
 
+       if (viafb_dual_fb) {
+               var2 = viafbinfo1->var;
+       } else if (viafb_SAMM_ON) {
+               viafb_fill_var_timing_info(&var2, viafb_get_best_mode(
+                       viafb_second_xres, viafb_second_yres, viafb_refresh1));
+               var2.bits_per_pixel = viafbinfo->var.bits_per_pixel;
+       }
+
        /* CRT set mode */
        if (viafb_CRT_ON) {
-               if (viafb_SAMM_ON &&
-                       viaparinfo->shared->iga2_devices & VIA_CRT) {
-                       viafb_fill_crtc_timing(crt_timing1, vmode_tbl1,
-                               video_bpp1 / 8, IGA2);
-               } else {
-                       viafb_fill_crtc_timing(crt_timing, vmode_tbl,
-                               video_bpp / 8,
+               if (viaparinfo->shared->iga2_devices & VIA_CRT
+                       && viafb_SAMM_ON)
+                       viafb_fill_crtc_timing(&var2, IGA2);
+               else
+                       viafb_fill_crtc_timing(&viafbinfo->var,
                                (viaparinfo->shared->iga1_devices & VIA_CRT)
                                ? IGA1 : IGA2);
-               }
 
                /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode
                to 8 alignment (1368),there is several pixels (2 pixels)
                on right side of screen. */
-               if (vmode_tbl->crtc[0].crtc.hor_addr % 8) {
+               if (viafbinfo->var.xres % 8) {
                        viafb_unlock_crt();
                        viafb_write_reg(CR02, VIACR,
                                viafb_read_reg(VIACR, CR02) - 1);
@@ -2233,31 +1916,20 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
        }
 
        if (viafb_DVI_ON) {
-               if (viafb_SAMM_ON &&
-                       (viaparinfo->tmds_setting_info->iga_path == IGA2)) {
-                       viafb_dvi_set_mode(viafb_get_mode
-                                    (viaparinfo->tmds_setting_info->h_active,
-                                     viaparinfo->tmds_setting_info->
-                                     v_active),
-                                    video_bpp1, viaparinfo->
-                                    tmds_setting_info->iga_path);
-               } else {
-                       viafb_dvi_set_mode(viafb_get_mode
-                                    (viaparinfo->tmds_setting_info->h_active,
-                                     viaparinfo->
-                                     tmds_setting_info->v_active),
-                                    video_bpp, viaparinfo->
-                                    tmds_setting_info->iga_path);
-               }
+               if (viaparinfo->shared->tmds_setting_info.iga_path == IGA2
+                       && viafb_SAMM_ON)
+                       viafb_dvi_set_mode(&var2, IGA2);
+               else
+                       viafb_dvi_set_mode(&viafbinfo->var,
+                               viaparinfo->tmds_setting_info->iga_path);
        }
 
        if (viafb_LCD_ON) {
                if (viafb_SAMM_ON &&
                        (viaparinfo->lvds_setting_info->iga_path == IGA2)) {
                        viaparinfo->lvds_setting_info->bpp = video_bpp1;
-                       viafb_lcd_set_mode(crt_timing1, viaparinfo->
-                               lvds_setting_info,
-                                    &viaparinfo->chip_info->lvds_chip_info);
+                       viafb_lcd_set_mode(viaparinfo->lvds_setting_info,
+                               &viaparinfo->chip_info->lvds_chip_info);
                } else {
                        /* IGA1 doesn't have LCD scaling, so set it center. */
                        if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
@@ -2265,18 +1937,16 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
                                    LCD_CENTERING;
                        }
                        viaparinfo->lvds_setting_info->bpp = video_bpp;
-                       viafb_lcd_set_mode(crt_timing, viaparinfo->
-                               lvds_setting_info,
-                                    &viaparinfo->chip_info->lvds_chip_info);
+                       viafb_lcd_set_mode(viaparinfo->lvds_setting_info,
+                               &viaparinfo->chip_info->lvds_chip_info);
                }
        }
        if (viafb_LCD2_ON) {
                if (viafb_SAMM_ON &&
                        (viaparinfo->lvds_setting_info2->iga_path == IGA2)) {
                        viaparinfo->lvds_setting_info2->bpp = video_bpp1;
-                       viafb_lcd_set_mode(crt_timing1, viaparinfo->
-                               lvds_setting_info2,
-                                    &viaparinfo->chip_info->lvds_chip_info2);
+                       viafb_lcd_set_mode(viaparinfo->lvds_setting_info2,
+                               &viaparinfo->chip_info->lvds_chip_info2);
                } else {
                        /* IGA1 doesn't have LCD scaling, so set it center. */
                        if (viaparinfo->lvds_setting_info2->iga_path == IGA1) {
@@ -2284,9 +1954,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
                                    LCD_CENTERING;
                        }
                        viaparinfo->lvds_setting_info2->bpp = video_bpp;
-                       viafb_lcd_set_mode(crt_timing, viaparinfo->
-                               lvds_setting_info2,
-                                    &viaparinfo->chip_info->lvds_chip_info2);
+                       viafb_lcd_set_mode(viaparinfo->lvds_setting_info2,
+                               &viaparinfo->chip_info->lvds_chip_info2);
                }
        }
 
@@ -2296,8 +1965,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
 
        /* If set mode normally, save resolution information for hot-plug . */
        if (!viafb_hotplug) {
-               viafb_hotplug_Xres = vmode_tbl->crtc[0].crtc.hor_addr;
-               viafb_hotplug_Yres = vmode_tbl->crtc[0].crtc.ver_addr;
+               viafb_hotplug_Xres = viafbinfo->var.xres;
+               viafb_hotplug_Yres = viafbinfo->var.yres;
                viafb_hotplug_bpp = video_bpp;
                viafb_hotplug_refresh = viafb_refresh;
 
@@ -2348,42 +2017,14 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
        return 1;
 }
 
-int viafb_get_pixclock(int hres, int vres, int vmode_refresh)
-{
-       int i;
-       struct crt_mode_table *best;
-       struct VideoModeTable *vmode = viafb_get_mode(hres, vres);
-
-       if (!vmode)
-               return RES_640X480_60HZ_PIXCLOCK;
-
-       best = &vmode->crtc[0];
-       for (i = 1; i < vmode->mode_array; i++) {
-               if (abs(vmode->crtc[i].refresh_rate - vmode_refresh)
-                       < abs(best->refresh_rate - vmode_refresh))
-                       best = &vmode->crtc[i];
-       }
-
-       return 1000000000 / (best->crtc.hor_total * best->crtc.ver_total)
-               * 1000 / best->refresh_rate;
-}
-
 int viafb_get_refresh(int hres, int vres, u32 long_refresh)
 {
-       int i;
        struct crt_mode_table *best;
-       struct VideoModeTable *vmode = viafb_get_mode(hres, vres);
 
-       if (!vmode)
+       best = viafb_get_best_mode(hres, vres, long_refresh);
+       if (!best)
                return 60;
 
-       best = &vmode->crtc[0];
-       for (i = 1; i < vmode->mode_array; i++) {
-               if (abs(vmode->crtc[i].refresh_rate - long_refresh)
-                       < abs(best->refresh_rate - long_refresh))
-                       best = &vmode->crtc[i];
-       }
-
        if (abs(best->refresh_rate - long_refresh) > 3) {
                if (hres == 1200 && vres == 900)
                        return 49; /* OLPC DCON only supports 50 Hz */
@@ -2485,21 +2126,14 @@ void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
 }
 
 /*According var's xres, yres fill var's other timing information*/
-void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
-       struct VideoModeTable *vmode_tbl)
+void viafb_fill_var_timing_info(struct fb_var_screeninfo *var,
+       struct crt_mode_table *mode)
 {
-       struct crt_mode_table *crt_timing = NULL;
        struct display_timing crt_reg;
-       int i = 0, index = 0;
-       crt_timing = vmode_tbl->crtc;
-       for (i = 0; i < vmode_tbl->mode_array; i++) {
-               index = i;
-               if (crt_timing[i].refresh_rate == refresh)
-                       break;
-       }
 
-       crt_reg = crt_timing[index].crtc;
-       var->pixclock = viafb_get_pixclock(var->xres, var->yres, refresh);
+       crt_reg = mode->crtc;
+       var->pixclock = 1000000000 / (crt_reg.hor_total * crt_reg.ver_total)
+               * 1000 / mode->refresh_rate;
        var->left_margin =
            crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end);
        var->right_margin = crt_reg.hor_sync_start - crt_reg.hor_addr;
@@ -2509,8 +2143,8 @@ void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
        var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr;
        var->vsync_len = crt_reg.ver_sync_end;
        var->sync = 0;
-       if (crt_timing[index].h_sync_polarity == POSITIVE)
+       if (mode->h_sync_polarity == POSITIVE)
                var->sync |= FB_SYNC_HOR_HIGH_ACT;
-       if (crt_timing[index].v_sync_polarity == POSITIVE)
+       if (mode->v_sync_polarity == POSITIVE)
                var->sync |= FB_SYNC_VERT_HIGH_ACT;
 }
index c7239eb..4db5b6e 100644 (file)
 #define VIA_HSYNC_NEGATIVE     0x01
 #define VIA_VSYNC_NEGATIVE     0x02
 
-/***************************************************
-* Definition IGA1 Design Method of CRTC Registers *
-****************************************************/
-#define IGA1_HOR_TOTAL_FORMULA(x)           (((x)/8)-5)
-#define IGA1_HOR_ADDR_FORMULA(x)            (((x)/8)-1)
-#define IGA1_HOR_BLANK_START_FORMULA(x)     (((x)/8)-1)
-#define IGA1_HOR_BLANK_END_FORMULA(x, y)     (((x+y)/8)-1)
-#define IGA1_HOR_SYNC_START_FORMULA(x)      ((x)/8)
-#define IGA1_HOR_SYNC_END_FORMULA(x, y)      ((x+y)/8)
-
-#define IGA1_VER_TOTAL_FORMULA(x)           ((x)-2)
-#define IGA1_VER_ADDR_FORMULA(x)            ((x)-1)
-#define IGA1_VER_BLANK_START_FORMULA(x)     ((x)-1)
-#define IGA1_VER_BLANK_END_FORMULA(x, y)     ((x+y)-1)
-#define IGA1_VER_SYNC_START_FORMULA(x)      ((x)-1)
-#define IGA1_VER_SYNC_END_FORMULA(x, y)      ((x+y)-1)
-
-/***************************************************
-** Definition IGA2 Design Method of CRTC Registers *
-****************************************************/
-#define IGA2_HOR_TOTAL_FORMULA(x)           ((x)-1)
-#define IGA2_HOR_ADDR_FORMULA(x)            ((x)-1)
-#define IGA2_HOR_BLANK_START_FORMULA(x)     ((x)-1)
-#define IGA2_HOR_BLANK_END_FORMULA(x, y)     ((x+y)-1)
-#define IGA2_HOR_SYNC_START_FORMULA(x)      ((x)-1)
-#define IGA2_HOR_SYNC_END_FORMULA(x, y)      ((x+y)-1)
-
-#define IGA2_VER_TOTAL_FORMULA(x)           ((x)-1)
-#define IGA2_VER_ADDR_FORMULA(x)            ((x)-1)
-#define IGA2_VER_BLANK_START_FORMULA(x)     ((x)-1)
-#define IGA2_VER_BLANK_END_FORMULA(x, y)     ((x+y)-1)
-#define IGA2_VER_SYNC_START_FORMULA(x)      ((x)-1)
-#define IGA2_VER_SYNC_END_FORMULA(x, y)      ((x+y)-1)
-
 /**********************************************************/
 /* Definition IGA2 Design Method of CRTC Shadow Registers */
 /**********************************************************/
 #define IGA2_VER_SYNC_START_SHADOW_FORMULA(x)      (x)
 #define IGA2_VER_SYNC_END_SHADOW_FORMULA(x, y)      (x+y)
 
-/* Define Register Number for IGA1 CRTC Timing */
-
-/* location: {CR00,0,7},{CR36,3,3} */
-#define IGA1_HOR_TOTAL_REG_NUM         2
-/* location: {CR01,0,7} */
-#define IGA1_HOR_ADDR_REG_NUM          1
-/* location: {CR02,0,7} */
-#define IGA1_HOR_BLANK_START_REG_NUM    1
-/* location: {CR03,0,4},{CR05,7,7},{CR33,5,5} */
-#define IGA1_HOR_BLANK_END_REG_NUM     3
-/* location: {CR04,0,7},{CR33,4,4} */
-#define IGA1_HOR_SYNC_START_REG_NUM    2
-/* location: {CR05,0,4} */
-#define IGA1_HOR_SYNC_END_REG_NUM       1
-/* location: {CR06,0,7},{CR07,0,0},{CR07,5,5},{CR35,0,0} */
-#define IGA1_VER_TOTAL_REG_NUM          4
-/* location: {CR12,0,7},{CR07,1,1},{CR07,6,6},{CR35,2,2} */
-#define IGA1_VER_ADDR_REG_NUM           4
-/* location: {CR15,0,7},{CR07,3,3},{CR09,5,5},{CR35,3,3} */
-#define IGA1_VER_BLANK_START_REG_NUM    4
-/* location: {CR16,0,7} */
-#define IGA1_VER_BLANK_END_REG_NUM      1
-/* location: {CR10,0,7},{CR07,2,2},{CR07,7,7},{CR35,1,1} */
-#define IGA1_VER_SYNC_START_REG_NUM     4
-/* location: {CR11,0,3} */
-#define IGA1_VER_SYNC_END_REG_NUM       1
-
 /* Define Register Number for IGA2 Shadow CRTC Timing */
 
 /* location: {CR6D,0,7},{CR71,3,3} */
 /* location: {CR76,0,3} */
 #define IGA2_SHADOW_VER_SYNC_END_REG_NUM    1
 
-/* Define Register Number for IGA2 CRTC Timing */
-
-/* location: {CR50,0,7},{CR55,0,3} */
-#define IGA2_HOR_TOTAL_REG_NUM          2
-/* location: {CR51,0,7},{CR55,4,6} */
-#define IGA2_HOR_ADDR_REG_NUM           2
-/* location: {CR52,0,7},{CR54,0,2} */
-#define IGA2_HOR_BLANK_START_REG_NUM    2
-/* location: CLE266: {CR53,0,7},{CR54,3,5} => CLE266's CR5D[6]
-is reserved, so it may have problem to set 1600x1200 on IGA2. */
-/*             Others: {CR53,0,7},{CR54,3,5},{CR5D,6,6} */
-#define IGA2_HOR_BLANK_END_REG_NUM      3
-/* location: {CR56,0,7},{CR54,6,7},{CR5C,7,7} */
-/* VT3314 and Later: {CR56,0,7},{CR54,6,7},{CR5C,7,7}, {CR5D,7,7} */
-#define IGA2_HOR_SYNC_START_REG_NUM     4
-
-/* location: {CR57,0,7},{CR5C,6,6} */
-#define IGA2_HOR_SYNC_END_REG_NUM       2
-/* location: {CR58,0,7},{CR5D,0,2} */
-#define IGA2_VER_TOTAL_REG_NUM          2
-/* location: {CR59,0,7},{CR5D,3,5} */
-#define IGA2_VER_ADDR_REG_NUM           2
-/* location: {CR5A,0,7},{CR5C,0,2} */
-#define IGA2_VER_BLANK_START_REG_NUM    2
-/* location: {CR5E,0,7},{CR5C,3,5} */
-#define IGA2_VER_BLANK_END_REG_NUM      2
-/* location: {CR5E,0,7},{CR5F,5,7} */
-#define IGA2_VER_SYNC_START_REG_NUM     2
-/* location: {CR5F,0,4} */
-#define IGA2_VER_SYNC_END_REG_NUM       1
-
 /* Define Fetch Count Register*/
 
 /* location: {SR1C,0,7},{SR1D,0,1} */
@@ -446,87 +354,12 @@ is reserved, so it may have problem to set 1600x1200 on IGA2. */
 /* location: {CR78,0,7},{CR79,6,7} */
 #define LCD_VER_SCALING_FACTOR_REG_NUM_CLE  2
 
-/************************************************
- *****     Define IGA1 Display Timing       *****
- ************************************************/
 struct io_register {
        u8 io_addr;
        u8 start_bit;
        u8 end_bit;
 };
 
-/* IGA1 Horizontal Total */
-struct iga1_hor_total {
-       int reg_num;
-       struct io_register reg[IGA1_HOR_TOTAL_REG_NUM];
-};
-
-/* IGA1 Horizontal Addressable Video */
-struct iga1_hor_addr {
-       int reg_num;
-       struct io_register reg[IGA1_HOR_ADDR_REG_NUM];
-};
-
-/* IGA1 Horizontal Blank Start */
-struct iga1_hor_blank_start {
-       int reg_num;
-       struct io_register reg[IGA1_HOR_BLANK_START_REG_NUM];
-};
-
-/* IGA1 Horizontal Blank End */
-struct iga1_hor_blank_end {
-       int reg_num;
-       struct io_register reg[IGA1_HOR_BLANK_END_REG_NUM];
-};
-
-/* IGA1 Horizontal Sync Start */
-struct iga1_hor_sync_start {
-       int reg_num;
-       struct io_register reg[IGA1_HOR_SYNC_START_REG_NUM];
-};
-
-/* IGA1 Horizontal Sync End */
-struct iga1_hor_sync_end {
-       int reg_num;
-       struct io_register reg[IGA1_HOR_SYNC_END_REG_NUM];
-};
-
-/* IGA1 Vertical Total */
-struct iga1_ver_total {
-       int reg_num;
-       struct io_register reg[IGA1_VER_TOTAL_REG_NUM];
-};
-
-/* IGA1 Vertical Addressable Video */
-struct iga1_ver_addr {
-       int reg_num;
-       struct io_register reg[IGA1_VER_ADDR_REG_NUM];
-};
-
-/* IGA1 Vertical Blank Start */
-struct iga1_ver_blank_start {
-       int reg_num;
-       struct io_register reg[IGA1_VER_BLANK_START_REG_NUM];
-};
-
-/* IGA1 Vertical Blank End */
-struct iga1_ver_blank_end {
-       int reg_num;
-       struct io_register reg[IGA1_VER_BLANK_END_REG_NUM];
-};
-
-/* IGA1 Vertical Sync Start */
-struct iga1_ver_sync_start {
-       int reg_num;
-       struct io_register reg[IGA1_VER_SYNC_START_REG_NUM];
-};
-
-/* IGA1 Vertical Sync End */
-struct iga1_ver_sync_end {
-       int reg_num;
-       struct io_register reg[IGA1_VER_SYNC_END_REG_NUM];
-};
-
 /*****************************************************
 **      Define IGA2 Shadow Display Timing         ****
 *****************************************************/
@@ -579,82 +412,6 @@ struct iga2_shadow_ver_sync_end {
        struct io_register reg[IGA2_SHADOW_VER_SYNC_END_REG_NUM];
 };
 
-/*****************************************************
-**      Define IGA2 Display Timing                ****
-******************************************************/
-
-/* IGA2 Horizontal Total */
-struct iga2_hor_total {
-       int reg_num;
-       struct io_register reg[IGA2_HOR_TOTAL_REG_NUM];
-};
-
-/* IGA2 Horizontal Addressable Video */
-struct iga2_hor_addr {
-       int reg_num;
-       struct io_register reg[IGA2_HOR_ADDR_REG_NUM];
-};
-
-/* IGA2 Horizontal Blank Start */
-struct iga2_hor_blank_start {
-       int reg_num;
-       struct io_register reg[IGA2_HOR_BLANK_START_REG_NUM];
-};
-
-/* IGA2 Horizontal Blank End */
-struct iga2_hor_blank_end {
-       int reg_num;
-       struct io_register reg[IGA2_HOR_BLANK_END_REG_NUM];
-};
-
-/* IGA2 Horizontal Sync Start */
-struct iga2_hor_sync_start {
-       int reg_num;
-       struct io_register reg[IGA2_HOR_SYNC_START_REG_NUM];
-};
-
-/* IGA2 Horizontal Sync End */
-struct iga2_hor_sync_end {
-       int reg_num;
-       struct io_register reg[IGA2_HOR_SYNC_END_REG_NUM];
-};
-
-/* IGA2 Vertical Total */
-struct iga2_ver_total {
-       int reg_num;
-       struct io_register reg[IGA2_VER_TOTAL_REG_NUM];
-};
-
-/* IGA2 Vertical Addressable Video */
-struct iga2_ver_addr {
-       int reg_num;
-       struct io_register reg[IGA2_VER_ADDR_REG_NUM];
-};
-
-/* IGA2 Vertical Blank Start */
-struct iga2_ver_blank_start {
-       int reg_num;
-       struct io_register reg[IGA2_VER_BLANK_START_REG_NUM];
-};
-
-/* IGA2 Vertical Blank End */
-struct iga2_ver_blank_end {
-       int reg_num;
-       struct io_register reg[IGA2_VER_BLANK_END_REG_NUM];
-};
-
-/* IGA2 Vertical Sync Start */
-struct iga2_ver_sync_start {
-       int reg_num;
-       struct io_register reg[IGA2_VER_SYNC_START_REG_NUM];
-};
-
-/* IGA2 Vertical Sync End */
-struct iga2_ver_sync_end {
-       int reg_num;
-       struct io_register reg[IGA2_VER_SYNC_END_REG_NUM];
-};
-
 /* IGA1 Fetch Count Register */
 struct iga1_fetch_count {
        int reg_num;
@@ -817,21 +574,6 @@ struct display_queue_expire_num {
         iga2_display_queue_expire_num_reg;
 };
 
-struct iga1_crtc_timing {
-       struct iga1_hor_total hor_total;
-       struct iga1_hor_addr hor_addr;
-       struct iga1_hor_blank_start hor_blank_start;
-       struct iga1_hor_blank_end hor_blank_end;
-       struct iga1_hor_sync_start hor_sync_start;
-       struct iga1_hor_sync_end hor_sync_end;
-       struct iga1_ver_total ver_total;
-       struct iga1_ver_addr ver_addr;
-       struct iga1_ver_blank_start ver_blank_start;
-       struct iga1_ver_blank_end ver_blank_end;
-       struct iga1_ver_sync_start ver_sync_start;
-       struct iga1_ver_sync_end ver_sync_end;
-};
-
 struct iga2_shadow_crtc_timing {
        struct iga2_shadow_hor_total hor_total_shadow;
        struct iga2_shadow_hor_blank_end hor_blank_end_shadow;
@@ -843,21 +585,6 @@ struct iga2_shadow_crtc_timing {
        struct iga2_shadow_ver_sync_end ver_sync_end_shadow;
 };
 
-struct iga2_crtc_timing {
-       struct iga2_hor_total hor_total;
-       struct iga2_hor_addr hor_addr;
-       struct iga2_hor_blank_start hor_blank_start;
-       struct iga2_hor_blank_end hor_blank_end;
-       struct iga2_hor_sync_start hor_sync_start;
-       struct iga2_hor_sync_end hor_sync_end;
-       struct iga2_ver_total ver_total;
-       struct iga2_ver_addr ver_addr;
-       struct iga2_ver_blank_start ver_blank_start;
-       struct iga2_ver_blank_end ver_blank_end;
-       struct iga2_ver_sync_start ver_sync_start;
-       struct iga2_ver_sync_end ver_sync_end;
-};
-
 /* device ID */
 #define CLE266_FUNCTION3    0x3123
 #define KM400_FUNCTION3     0x3205
@@ -910,9 +637,7 @@ extern int viafb_LCD_ON;
 extern int viafb_DVI_ON;
 extern int viafb_hotplug;
 
-void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
-       struct VideoModeTable *video_mode, int bpp_byte, int set_iga);
-
+void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, int iga);
 void viafb_set_vclock(u32 CLK, int set_iga);
 void viafb_load_reg(int timing_value, int viafb_load_reg_num,
        struct io_register *reg,
@@ -932,13 +657,11 @@ void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active);
 void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
                                        *p_gfx_dpa_setting);
 
-int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
-       struct VideoModeTable *vmode_tbl1, int video_bpp1);
-void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
-       struct VideoModeTable *vmode_tbl);
+int viafb_setmode(int video_bpp, int video_bpp1);
+void viafb_fill_var_timing_info(struct fb_var_screeninfo *var,
+       struct crt_mode_table *mode);
 void __devinit viafb_init_chip_info(int chip_type);
 void __devinit viafb_init_dac(int set_iga);
-int viafb_get_pixclock(int hres, int vres, int vmode_refresh);
 int viafb_get_refresh(int hres, int vres, u32 float_refresh);
 void viafb_update_device_setting(int hres, int vres, int bpp, int flag);
 
index 6e06981..5f3b4e3 100644 (file)
@@ -548,9 +548,8 @@ static void lcd_patch_skew(struct lvds_setting_information
 }
 
 /* LCD Set Mode */
-void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
-                 struct lvds_setting_information *plvds_setting_info,
-                 struct lvds_chip_information *plvds_chip_info)
+void viafb_lcd_set_mode(struct lvds_setting_information *plvds_setting_info,
+       struct lvds_chip_information *plvds_chip_info)
 {
        int set_iga = plvds_setting_info->iga_path;
        int mode_bpp = plvds_setting_info->bpp;
@@ -559,16 +558,15 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
        int panel_hres = plvds_setting_info->lcd_panel_hres;
        int panel_vres = plvds_setting_info->lcd_panel_vres;
        u32 clock;
-       struct display_timing mode_crt_reg, panel_crt_reg;
-       struct crt_mode_table *panel_crt_table = NULL;
-       struct VideoModeTable *vmode_tbl = viafb_get_mode(panel_hres,
-               panel_vres);
+       struct display_timing mode_crt_reg, panel_crt_reg, timing;
+       struct crt_mode_table *mode_crt_table, *panel_crt_table;
 
        DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n");
        /* Get mode table */
+       mode_crt_table = viafb_get_best_mode(set_hres, set_vres, 60);
        mode_crt_reg = mode_crt_table->crtc;
        /* Get panel table Pointer */
-       panel_crt_table = vmode_tbl->crtc;
+       panel_crt_table = viafb_get_best_mode(panel_hres, panel_vres, 60);
        panel_crt_reg = panel_crt_table->crtc;
        DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n");
        if (VT1636_LVDS == plvds_chip_info->lvds_chip_name)
@@ -576,31 +574,28 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
        clock = panel_crt_reg.hor_total * panel_crt_reg.ver_total
                * panel_crt_table->refresh_rate;
        plvds_setting_info->vclk = clock;
-       if (set_iga == IGA1) {
-               /* IGA1 doesn't have LCD scaling, so set it as centering. */
-               viafb_load_crtc_timing(lcd_centering_timging
-                                (mode_crt_reg, panel_crt_reg), IGA1);
+
+       if (set_iga == IGA2 && (set_hres < panel_hres || set_vres < panel_vres)
+               && plvds_setting_info->display_method == LCD_EXPANDSION) {
+               timing = panel_crt_reg;
+               load_lcd_scaling(set_hres, set_vres, panel_hres, panel_vres);
        } else {
-               /* Expansion */
-               if (plvds_setting_info->display_method == LCD_EXPANDSION
-                       && (set_hres < panel_hres || set_vres < panel_vres)) {
-                       /* expansion timing IGA2 loaded panel set timing*/
-                       viafb_load_crtc_timing(panel_crt_reg, IGA2);
-                       DEBUG_MSG(KERN_INFO "viafb_load_crtc_timing!!\n");
-                       load_lcd_scaling(set_hres, set_vres, panel_hres,
-                                        panel_vres);
-                       DEBUG_MSG(KERN_INFO "load_lcd_scaling!!\n");
-               } else {        /* Centering */
-                       /* centering timing IGA2 always loaded panel
-                          and mode releative timing */
-                       viafb_load_crtc_timing(lcd_centering_timging
-                                        (mode_crt_reg, panel_crt_reg), IGA2);
-                       viafb_write_reg_mask(CR79, VIACR, 0x00,
+               timing = lcd_centering_timging(mode_crt_reg, panel_crt_reg);
+               if (set_iga == IGA2)
+                       /* disable scaling */
+                       via_write_reg_mask(VIACR, 0x79, 0x00,
                                BIT0 + BIT1 + BIT2);
-                       /* LCD scaling disabled */
-               }
        }
 
+       timing.hor_blank_end += timing.hor_blank_start;
+       timing.hor_sync_end += timing.hor_sync_start;
+       timing.ver_blank_end += timing.ver_blank_start;
+       timing.ver_sync_end += timing.ver_sync_start;
+       if (set_iga == IGA1)
+               via_set_primary_timing(&timing);
+       else if (set_iga == IGA2)
+               via_set_secondary_timing(&timing);
+
        /* Fetch count for IGA2 only */
        viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga);
 
index 75f60a6..77ca7b8 100644 (file)
@@ -76,16 +76,13 @@ void __devinit viafb_init_lvds_output_interface(struct lvds_chip_information
                                *plvds_chip_info,
                                struct lvds_setting_information
                                *plvds_setting_info);
-void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
-                 struct lvds_setting_information *plvds_setting_info,
-                 struct lvds_chip_information *plvds_chip_info);
+void viafb_lcd_set_mode(struct lvds_setting_information *plvds_setting_info,
+       struct lvds_chip_information *plvds_chip_info);
 bool __devinit viafb_lvds_trasmitter_identify(void);
 void viafb_init_lvds_output_interface(struct lvds_chip_information
                                *plvds_chip_info,
                                struct lvds_setting_information
                                *plvds_setting_info);
 bool viafb_lcd_get_mobile_state(bool *mobile);
-void viafb_load_crtc_timing(struct display_timing device_timing,
-       int set_iga);
 
 #endif /* __LCD_H__ */
index 61b0bd5..69d882c 100644 (file)
@@ -22,6 +22,8 @@
 #ifndef __SHARE_H__
 #define __SHARE_H__
 
+#include "via_modesetting.h"
+
 /* Define Bit Field */
 #define BIT0    0x01
 #define BIT1    0x02
 #define V_SYNC_SATRT_SHADOW_INDEX   18
 #define V_SYNC_END_SHADOW_INDEX     19
 
-/* Definition Video Mode Pixel Clock (picoseconds)
-*/
-#define RES_640X480_60HZ_PIXCLOCK    39722
-
 /* LCD display method
 */
 #define     LCD_EXPANDSION              0x00
 #define     LCD_OPENLDI               0x00
 #define     LCD_SPWG                  0x01
 
-/* Define display timing
-*/
-struct display_timing {
-       u16 hor_total;
-       u16 hor_addr;
-       u16 hor_blank_start;
-       u16 hor_blank_end;
-       u16 hor_sync_start;
-       u16 hor_sync_end;
-       u16 ver_total;
-       u16 ver_addr;
-       u16 ver_blank_start;
-       u16 ver_blank_end;
-       u16 ver_sync_start;
-       u16 ver_sync_end;
-};
-
 struct crt_mode_table {
        int refresh_rate;
        int h_sync_polarity;
index eb112b6..dd58b53 100644 (file)
@@ -35,7 +35,7 @@ static struct via_port_cfg adap_configs[] = {
  * The OLPC XO-1.5 puts the camera power and reset lines onto
  * GPIO 2C.
  */
-static const struct via_port_cfg olpc_adap_configs[] = {
+static struct via_port_cfg olpc_adap_configs[] = {
        [VIA_PORT_26]   = { VIA_PORT_I2C,  VIA_MODE_I2C, VIASR, 0x26 },
        [VIA_PORT_31]   = { VIA_PORT_I2C,  VIA_MODE_I2C, VIASR, 0x31 },
        [VIA_PORT_25]   = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 },
index 3cddcff..0e431ae 100644 (file)
 #include "share.h"
 #include "debug.h"
 
+
+void via_set_primary_timing(const struct display_timing *timing)
+{
+       struct display_timing raw;
+
+       raw.hor_total = timing->hor_total / 8 - 5;
+       raw.hor_addr = timing->hor_addr / 8 - 1;
+       raw.hor_blank_start = timing->hor_blank_start / 8 - 1;
+       raw.hor_blank_end = timing->hor_blank_end / 8 - 1;
+       raw.hor_sync_start = timing->hor_sync_start / 8;
+       raw.hor_sync_end = timing->hor_sync_end / 8;
+       raw.ver_total = timing->ver_total - 2;
+       raw.ver_addr = timing->ver_addr - 1;
+       raw.ver_blank_start = timing->ver_blank_start - 1;
+       raw.ver_blank_end = timing->ver_blank_end - 1;
+       raw.ver_sync_start = timing->ver_sync_start - 1;
+       raw.ver_sync_end = timing->ver_sync_end - 1;
+
+       /* unlock timing registers */
+       via_write_reg_mask(VIACR, 0x11, 0x00, 0x80);
+
+       via_write_reg(VIACR, 0x00, raw.hor_total & 0xFF);
+       via_write_reg(VIACR, 0x01, raw.hor_addr & 0xFF);
+       via_write_reg(VIACR, 0x02, raw.hor_blank_start & 0xFF);
+       via_write_reg_mask(VIACR, 0x03, raw.hor_blank_end & 0x1F, 0x1F);
+       via_write_reg(VIACR, 0x04, raw.hor_sync_start & 0xFF);
+       via_write_reg_mask(VIACR, 0x05, (raw.hor_sync_end & 0x1F)
+               | (raw.hor_blank_end << (7 - 5) & 0x80), 0x9F);
+       via_write_reg(VIACR, 0x06, raw.ver_total & 0xFF);
+       via_write_reg_mask(VIACR, 0x07, (raw.ver_total >> 8 & 0x01)
+               | (raw.ver_addr >> (8 - 1) & 0x02)
+               | (raw.ver_sync_start >> (8 - 2) & 0x04)
+               | (raw.ver_blank_start >> (8 - 3) & 0x08)
+               | (raw.ver_total >> (9 - 5) & 0x20)
+               | (raw.ver_addr >> (9 - 6) & 0x40)
+               | (raw.ver_sync_start >> (9 - 7) & 0x80), 0xEF);
+       via_write_reg_mask(VIACR, 0x09, raw.ver_blank_start >> (9 - 5) & 0x20,
+               0x20);
+       via_write_reg(VIACR, 0x10, raw.ver_sync_start & 0xFF);
+       via_write_reg_mask(VIACR, 0x11, raw.ver_sync_end & 0x0F, 0x0F);
+       via_write_reg(VIACR, 0x12, raw.ver_addr & 0xFF);
+       via_write_reg(VIACR, 0x15, raw.ver_blank_start & 0xFF);
+       via_write_reg(VIACR, 0x16, raw.ver_blank_end & 0xFF);
+       via_write_reg_mask(VIACR, 0x33, (raw.hor_sync_start >> (8 - 4) & 0x10)
+               | (raw.hor_blank_end >> (6 - 5) & 0x20), 0x30);
+       via_write_reg_mask(VIACR, 0x35, (raw.ver_total >> 10 & 0x01)
+               | (raw.ver_sync_start >> (10 - 1) & 0x02)
+               | (raw.ver_addr >> (10 - 2) & 0x04)
+               | (raw.ver_blank_start >> (10 - 3) & 0x08), 0x0F);
+       via_write_reg_mask(VIACR, 0x36, raw.hor_total >> (8 - 3) & 0x08, 0x08);
+
+       /* lock timing registers */
+       via_write_reg_mask(VIACR, 0x11, 0x80, 0x80);
+
+       /* reset timing control */
+       via_write_reg_mask(VIACR, 0x17, 0x00, 0x80);
+       via_write_reg_mask(VIACR, 0x17, 0x80, 0x80);
+}
+
+void via_set_secondary_timing(const struct display_timing *timing)
+{
+       struct display_timing raw;
+
+       raw.hor_total = timing->hor_total - 1;
+       raw.hor_addr = timing->hor_addr - 1;
+       raw.hor_blank_start = timing->hor_blank_start - 1;
+       raw.hor_blank_end = timing->hor_blank_end - 1;
+       raw.hor_sync_start = timing->hor_sync_start - 1;
+       raw.hor_sync_end = timing->hor_sync_end - 1;
+       raw.ver_total = timing->ver_total - 1;
+       raw.ver_addr = timing->ver_addr - 1;
+       raw.ver_blank_start = timing->ver_blank_start - 1;
+       raw.ver_blank_end = timing->ver_blank_end - 1;
+       raw.ver_sync_start = timing->ver_sync_start - 1;
+       raw.ver_sync_end = timing->ver_sync_end - 1;
+
+       via_write_reg(VIACR, 0x50, raw.hor_total & 0xFF);
+       via_write_reg(VIACR, 0x51, raw.hor_addr & 0xFF);
+       via_write_reg(VIACR, 0x52, raw.hor_blank_start & 0xFF);
+       via_write_reg(VIACR, 0x53, raw.hor_blank_end & 0xFF);
+       via_write_reg(VIACR, 0x54, (raw.hor_blank_start >> 8 & 0x07)
+               | (raw.hor_blank_end >> (8 - 3) & 0x38)
+               | (raw.hor_sync_start >> (8 - 6) & 0xC0));
+       via_write_reg_mask(VIACR, 0x55, (raw.hor_total >> 8 & 0x0F)
+               | (raw.hor_addr >> (8 - 4) & 0x70), 0x7F);
+       via_write_reg(VIACR, 0x56, raw.hor_sync_start & 0xFF);
+       via_write_reg(VIACR, 0x57, raw.hor_sync_end & 0xFF);
+       via_write_reg(VIACR, 0x58, raw.ver_total & 0xFF);
+       via_write_reg(VIACR, 0x59, raw.ver_addr & 0xFF);
+       via_write_reg(VIACR, 0x5A, raw.ver_blank_start & 0xFF);
+       via_write_reg(VIACR, 0x5B, raw.ver_blank_end & 0xFF);
+       via_write_reg(VIACR, 0x5C, (raw.ver_blank_start >> 8 & 0x07)
+               | (raw.ver_blank_end >> (8 - 3) & 0x38)
+               | (raw.hor_sync_end >> (8 - 6) & 0x40)
+               | (raw.hor_sync_start >> (10 - 7) & 0x80));
+       via_write_reg(VIACR, 0x5D, (raw.ver_total >> 8 & 0x07)
+               | (raw.ver_addr >> (8 - 3) & 0x38)
+               | (raw.hor_blank_end >> (11 - 6) & 0x40)
+               | (raw.hor_sync_start >> (11 - 7) & 0x80));
+       via_write_reg(VIACR, 0x5E, raw.ver_sync_start & 0xFF);
+       via_write_reg(VIACR, 0x5F, (raw.ver_sync_end & 0x1F)
+               | (raw.ver_sync_start >> (8 - 5) & 0xE0));
+}
+
 void via_set_primary_address(u32 addr)
 {
        DEBUG_MSG(KERN_DEBUG "via_set_primary_address(0x%08X)\n", addr);
index ae35cfd..06e09fe 100644 (file)
 
 #include <linux/types.h>
 
+
+#define VIA_PITCH_SIZE (1<<3)
+#define VIA_PITCH_MAX  0x3FF8
+
+
+struct display_timing {
+       u16 hor_total;
+       u16 hor_addr;
+       u16 hor_blank_start;
+       u16 hor_blank_end;
+       u16 hor_sync_start;
+       u16 hor_sync_end;
+       u16 ver_total;
+       u16 ver_addr;
+       u16 ver_blank_start;
+       u16 ver_blank_end;
+       u16 ver_sync_start;
+       u16 ver_sync_end;
+};
+
+
+void via_set_primary_timing(const struct display_timing *timing);
+void via_set_secondary_timing(const struct display_timing *timing);
 void via_set_primary_address(u32 addr);
 void via_set_secondary_address(u32 addr);
 void via_set_primary_pitch(u32 pitch);
index 53aa443..a13c258 100644 (file)
@@ -38,8 +38,6 @@ static char *viafb_mode1;
 static int viafb_bpp = 32;
 static int viafb_bpp1 = 32;
 
-static unsigned int viafb_second_xres = 640;
-static unsigned int viafb_second_yres = 480;
 static unsigned int viafb_second_offset;
 static int viafb_second_size;
 
@@ -151,7 +149,8 @@ static void viafb_update_fix(struct fb_info *info)
 
        info->fix.visual =
                bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
-       info->fix.line_length = (info->var.xres_virtual * bpp / 8 + 7) & ~7;
+       info->fix.line_length = ALIGN(info->var.xres_virtual * bpp / 8,
+               VIA_PITCH_SIZE);
 }
 
 static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix,
@@ -200,7 +199,6 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
        struct fb_info *info)
 {
        int depth, refresh;
-       struct VideoModeTable *vmode_entry;
        struct viafb_par *ppar = info->par;
        u32 line;
 
@@ -210,8 +208,10 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
        if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE)
                return -EINVAL;
 
-       vmode_entry = viafb_get_mode(var->xres, var->yres);
-       if (!vmode_entry) {
+       /* the refresh rate is not important here, as we only want to know
+        * whether the resolution exists
+        */
+       if (!viafb_get_best_mode(var->xres, var->yres, 60)) {
                DEBUG_MSG(KERN_INFO
                          "viafb: Mode %dx%dx%d not supported!!\n",
                          var->xres, var->yres, var->bits_per_pixel);
@@ -238,8 +238,12 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
                depth = 24;
 
        viafb_fill_var_color_info(var, depth);
-       line = (var->xres_virtual * var->bits_per_pixel / 8 + 7) & ~7;
-       if (line * var->yres_virtual > ppar->memsize)
+       if (var->xres_virtual < var->xres)
+               var->xres_virtual = var->xres;
+
+       line = ALIGN(var->xres_virtual * var->bits_per_pixel / 8,
+               VIA_PITCH_SIZE);
+       if (line > VIA_PITCH_MAX || line * var->yres_virtual > ppar->memsize)
                return -EINVAL;
 
        /* Based on var passed in to calculate the refresh,
@@ -249,7 +253,8 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
                get_var_refresh(var));
 
        /* Adjust var according to our driver's own table */
-       viafb_fill_var_timing_info(var, refresh, vmode_entry);
+       viafb_fill_var_timing_info(var,
+               viafb_get_best_mode(var->xres, var->yres, refresh));
        if (var->accel_flags & FB_ACCELF_TEXT &&
                !ppar->shared->vdev->engine_mmio)
                var->accel_flags = 0;
@@ -260,7 +265,6 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
 static int viafb_set_par(struct fb_info *info)
 {
        struct viafb_par *viapar = info->par;
-       struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL;
        int refresh;
        DEBUG_MSG(KERN_INFO "viafb_set_par!\n");
 
@@ -269,10 +273,7 @@ static int viafb_set_par(struct fb_info *info)
        viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres,
                viafbinfo->var.bits_per_pixel, 0);
 
-       vmode_entry = viafb_get_mode(viafbinfo->var.xres, viafbinfo->var.yres);
        if (viafb_dual_fb) {
-               vmode_entry1 = viafb_get_mode(viafbinfo1->var.xres,
-                       viafbinfo1->var.yres);
                viafb_update_device_setting(viafbinfo1->var.xres,
                        viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel,
                        1);
@@ -280,8 +281,6 @@ static int viafb_set_par(struct fb_info *info)
                DEBUG_MSG(KERN_INFO
                "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n",
                          viafb_second_xres, viafb_second_yres, viafb_bpp1);
-               vmode_entry1 = viafb_get_mode(viafb_second_xres,
-                       viafb_second_yres);
 
                viafb_update_device_setting(viafb_second_xres,
                        viafb_second_yres, viafb_bpp1, 1);
@@ -289,7 +288,8 @@ static int viafb_set_par(struct fb_info *info)
 
        refresh = viafb_get_refresh(info->var.xres, info->var.yres,
                get_var_refresh(&info->var));
-       if (vmode_entry) {
+       if (viafb_get_best_mode(viafbinfo->var.xres, viafbinfo->var.yres,
+               refresh)) {
                if (viafb_dual_fb && viapar->iga_path == IGA2) {
                        viafb_bpp1 = info->var.bits_per_pixel;
                        viafb_refresh1 = refresh;
@@ -302,8 +302,7 @@ static int viafb_set_par(struct fb_info *info)
                        info->flags &= ~FBINFO_HWACCEL_DISABLED;
                else
                        info->flags |= FBINFO_HWACCEL_DISABLED;
-               viafb_setmode(vmode_entry, info->var.bits_per_pixel,
-                       vmode_entry1, viafb_bpp1);
+               viafb_setmode(info->var.bits_per_pixel, viafb_bpp1);
                viafb_pan_display(&info->var, info);
        }
 
@@ -348,8 +347,9 @@ static int viafb_pan_display(struct fb_var_screeninfo *var,
        struct fb_info *info)
 {
        struct viafb_par *viapar = info->par;
-       u32 vram_addr = (var->yoffset * var->xres_virtual + var->xoffset)
-               * (var->bits_per_pixel / 8) + viapar->vram_addr;
+       u32 vram_addr = viapar->vram_addr
+               + var->yoffset * info->fix.line_length
+               + var->xoffset * info->var.bits_per_pixel / 8;
 
        DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr);
        if (!viafb_dual_fb) {
@@ -1158,7 +1158,8 @@ static ssize_t viafb_dvp0_proc_write(struct file *file,
        for (i = 0; i < 3; i++) {
                value = strsep(&pbuf, " ");
                if (value != NULL) {
-                       strict_strtoul(value, 0, (unsigned long *)&reg_val);
+                       if (kstrtou8(value, 0, &reg_val) < 0)
+                               return -EINVAL;
                        DEBUG_MSG(KERN_INFO "DVP0:reg_val[%l]=:%x\n", i,
                                  reg_val);
                        switch (i) {
@@ -1228,7 +1229,8 @@ static ssize_t viafb_dvp1_proc_write(struct file *file,
        for (i = 0; i < 3; i++) {
                value = strsep(&pbuf, " ");
                if (value != NULL) {
-                       strict_strtoul(value, 0, (unsigned long *)&reg_val);
+                       if (kstrtou8(value, 0, &reg_val) < 0)
+                               return -EINVAL;
                        switch (i) {
                        case 0:
                                viafb_write_reg_mask(CR9B, VIACR,
@@ -1286,7 +1288,8 @@ static ssize_t viafb_dfph_proc_write(struct file *file,
        if (copy_from_user(&buf[0], buffer, length))
                return -EFAULT;
        buf[length - 1] = '\0'; /*Ensure end string */
-       strict_strtoul(&buf[0], 0, (unsigned long *)&reg_val);
+       if (kstrtou8(buf, 0, &reg_val) < 0)
+               return -EINVAL;
        viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f);
        return count;
 }
@@ -1325,7 +1328,8 @@ static ssize_t viafb_dfpl_proc_write(struct file *file,
        if (copy_from_user(&buf[0], buffer, length))
                return -EFAULT;
        buf[length - 1] = '\0'; /*Ensure end string */
-       strict_strtoul(&buf[0], 0, (unsigned long *)&reg_val);
+       if (kstrtou8(buf, 0, &reg_val) < 0)
+               return -EINVAL;
        viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f);
        return count;
 }
@@ -1394,8 +1398,8 @@ static ssize_t viafb_vt1636_proc_write(struct file *file,
                for (i = 0; i < 2; i++) {
                        value = strsep(&pbuf, " ");
                        if (value != NULL) {
-                               strict_strtoul(value, 0,
-                                       (unsigned long *)&reg_val.Data);
+                               if (kstrtou8(value, 0, &reg_val.Data) < 0)
+                                       return -EINVAL;
                                switch (i) {
                                case 0:
                                        reg_val.Index = 0x08;
@@ -1431,8 +1435,8 @@ static ssize_t viafb_vt1636_proc_write(struct file *file,
                for (i = 0; i < 2; i++) {
                        value = strsep(&pbuf, " ");
                        if (value != NULL) {
-                               strict_strtoul(value, 0,
-                                       (unsigned long *)&reg_val.Data);
+                               if (kstrtou8(value, 0, &reg_val.Data) < 0)
+                                       return -EINVAL;
                                switch (i) {
                                case 0:
                                        reg_val.Index = 0x08;
@@ -1729,7 +1733,6 @@ static struct viafb_pm_hooks viafb_fb_pm_hooks = {
 int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
 {
        u32 default_xres, default_yres;
-       struct VideoModeTable *vmode_entry;
        struct fb_var_screeninfo default_var;
        int rc;
        u32 viafb_par_length;
@@ -1802,7 +1805,6 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
        }
 
        parse_mode(viafb_mode, &default_xres, &default_yres);
-       vmode_entry = viafb_get_mode(default_xres, default_yres);
        if (viafb_SAMM_ON == 1)
                parse_mode(viafb_mode1, &viafb_second_xres,
                        &viafb_second_yres);
@@ -1812,9 +1814,8 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
        default_var.xres_virtual = default_xres;
        default_var.yres_virtual = default_yres;
        default_var.bits_per_pixel = viafb_bpp;
-       viafb_fill_var_timing_info(&default_var, viafb_get_refresh(
-               default_var.xres, default_var.yres, viafb_refresh),
-               viafb_get_mode(default_var.xres, default_var.yres));
+       viafb_fill_var_timing_info(&default_var, viafb_get_best_mode(
+               default_var.xres, default_var.yres, viafb_refresh));
        viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo);
        viafbinfo->var = default_var;
 
@@ -1853,9 +1854,8 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
                default_var.xres_virtual = viafb_second_xres;
                default_var.yres_virtual = viafb_second_yres;
                default_var.bits_per_pixel = viafb_bpp1;
-               viafb_fill_var_timing_info(&default_var, viafb_get_refresh(
-                       default_var.xres, default_var.yres, viafb_refresh1),
-                       viafb_get_mode(default_var.xres, default_var.yres));
+               viafb_fill_var_timing_info(&default_var, viafb_get_best_mode(
+                       default_var.xres, default_var.yres, viafb_refresh1));
 
                viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1);
                viafb_check_var(&default_var, viafbinfo1);
@@ -1950,61 +1950,67 @@ static int __init viafb_setup(void)
                if (!*this_opt)
                        continue;
 
-               if (!strncmp(this_opt, "viafb_mode1=", 12))
+               if (!strncmp(this_opt, "viafb_mode1=", 12)) {
                        viafb_mode1 = kstrdup(this_opt + 12, GFP_KERNEL);
-               else if (!strncmp(this_opt, "viafb_mode=", 11))
+               } else if (!strncmp(this_opt, "viafb_mode=", 11)) {
                        viafb_mode = kstrdup(this_opt + 11, GFP_KERNEL);
-               else if (!strncmp(this_opt, "viafb_bpp1=", 11))
-                       strict_strtoul(this_opt + 11, 0,
-                               (unsigned long *)&viafb_bpp1);
-               else if (!strncmp(this_opt, "viafb_bpp=", 10))
-                       strict_strtoul(this_opt + 10, 0,
-                               (unsigned long *)&viafb_bpp);
-               else if (!strncmp(this_opt, "viafb_refresh1=", 15))
-                       strict_strtoul(this_opt + 15, 0,
-                               (unsigned long *)&viafb_refresh1);
-               else if (!strncmp(this_opt, "viafb_refresh=", 14))
-                       strict_strtoul(this_opt + 14, 0,
-                               (unsigned long *)&viafb_refresh);
-               else if (!strncmp(this_opt, "viafb_lcd_dsp_method=", 21))
-                       strict_strtoul(this_opt + 21, 0,
-                               (unsigned long *)&viafb_lcd_dsp_method);
-               else if (!strncmp(this_opt, "viafb_lcd_panel_id=", 19))
-                       strict_strtoul(this_opt + 19, 0,
-                               (unsigned long *)&viafb_lcd_panel_id);
-               else if (!strncmp(this_opt, "viafb_accel=", 12))
-                       strict_strtoul(this_opt + 12, 0,
-                               (unsigned long *)&viafb_accel);
-               else if (!strncmp(this_opt, "viafb_SAMM_ON=", 14))
-                       strict_strtoul(this_opt + 14, 0,
-                               (unsigned long *)&viafb_SAMM_ON);
-               else if (!strncmp(this_opt, "viafb_active_dev=", 17))
+               } else if (!strncmp(this_opt, "viafb_bpp1=", 11)) {
+                       if (kstrtouint(this_opt + 11, 0, &viafb_bpp1) < 0)
+                               return -EINVAL;
+               } else if (!strncmp(this_opt, "viafb_bpp=", 10)) {
+                       if (kstrtouint(this_opt + 10, 0, &viafb_bpp) < 0)
+                               return -EINVAL;
+               } else if (!strncmp(this_opt, "viafb_refresh1=", 15)) {
+                       if (kstrtoint(this_opt + 15, 0, &viafb_refresh1) < 0)
+                               return -EINVAL;
+               } else if (!strncmp(this_opt, "viafb_refresh=", 14)) {
+                       if (kstrtoint(this_opt + 14, 0, &viafb_refresh) < 0)
+                               return -EINVAL;
+               } else if (!strncmp(this_opt, "viafb_lcd_dsp_method=", 21)) {
+                       if (kstrtoint(this_opt + 21, 0,
+                                     &viafb_lcd_dsp_method) < 0)
+                               return -EINVAL;
+               } else if (!strncmp(this_opt, "viafb_lcd_panel_id=", 19)) {
+                       if (kstrtoint(this_opt + 19, 0,
+                                     &viafb_lcd_panel_id) < 0)
+                               return -EINVAL;
+               } else if (!strncmp(this_opt, "viafb_accel=", 12)) {
+                       if (kstrtoint(this_opt + 12, 0, &viafb_accel) < 0)
+                               return -EINVAL;
+               } else if (!strncmp(this_opt, "viafb_SAMM_ON=", 14)) {
+                       if (kstrtoint(this_opt + 14, 0, &viafb_SAMM_ON) < 0)
+                               return -EINVAL;
+               } else if (!strncmp(this_opt, "viafb_active_dev=", 17)) {
                        viafb_active_dev = kstrdup(this_opt + 17, GFP_KERNEL);
-               else if (!strncmp(this_opt,
-                       "viafb_display_hardware_layout=", 30))
-                       strict_strtoul(this_opt + 30, 0,
-                       (unsigned long *)&viafb_display_hardware_layout);
-               else if (!strncmp(this_opt, "viafb_second_size=", 18))
-                       strict_strtoul(this_opt + 18, 0,
-                               (unsigned long *)&viafb_second_size);
-               else if (!strncmp(this_opt,
-                       "viafb_platform_epia_dvi=", 24))
-                       strict_strtoul(this_opt + 24, 0,
-                               (unsigned long *)&viafb_platform_epia_dvi);
-               else if (!strncmp(this_opt,
-                       "viafb_device_lcd_dualedge=", 26))
-                       strict_strtoul(this_opt + 26, 0,
-                               (unsigned long *)&viafb_device_lcd_dualedge);
-               else if (!strncmp(this_opt, "viafb_bus_width=", 16))
-                       strict_strtoul(this_opt + 16, 0,
-                               (unsigned long *)&viafb_bus_width);
-               else if (!strncmp(this_opt, "viafb_lcd_mode=", 15))
-                       strict_strtoul(this_opt + 15, 0,
-                               (unsigned long *)&viafb_lcd_mode);
-               else if (!strncmp(this_opt, "viafb_lcd_port=", 15))
+               } else if (!strncmp(this_opt,
+                       "viafb_display_hardware_layout=", 30)) {
+                       if (kstrtoint(this_opt + 30, 0,
+                                     &viafb_display_hardware_layout) < 0)
+                               return -EINVAL;
+               } else if (!strncmp(this_opt, "viafb_second_size=", 18)) {
+                       if (kstrtoint(this_opt + 18, 0, &viafb_second_size) < 0)
+                               return -EINVAL;
+               } else if (!strncmp(this_opt,
+                       "viafb_platform_epia_dvi=", 24)) {
+                       if (kstrtoint(this_opt + 24, 0,
+                                     &viafb_platform_epia_dvi) < 0)
+                               return -EINVAL;
+               } else if (!strncmp(this_opt,
+                       "viafb_device_lcd_dualedge=", 26)) {
+                       if (kstrtoint(this_opt + 26, 0,
+                                     &viafb_device_lcd_dualedge) < 0)
+                               return -EINVAL;
+               } else if (!strncmp(this_opt, "viafb_bus_width=", 16)) {
+                       if (kstrtoint(this_opt + 16, 0, &viafb_bus_width) < 0)
+                               return -EINVAL;
+               } else if (!strncmp(this_opt, "viafb_lcd_mode=", 15)) {
+                       if (kstrtoint(this_opt + 15, 0, &viafb_lcd_mode) < 0)
+                               return -EINVAL;
+               } else if (!strncmp(this_opt, "viafb_lcd_port=", 15)) {
                        viafb_lcd_port = kstrdup(this_opt + 15, GFP_KERNEL);
-               else if (!strncmp(this_opt, "viafb_dvi_port=", 15))
+               } else if (!strncmp(this_opt, "viafb_dvi_port=", 15)) {
                        viafb_dvi_port = kstrdup(this_opt + 15, GFP_KERNEL);
+               }
        }
        return 0;
 }
@@ -2028,9 +2034,9 @@ int __init viafb_init(void)
                return r;
 #endif
        if (parse_mode(viafb_mode, &dummy_x, &dummy_y)
-               || !viafb_get_mode(dummy_x, dummy_y)
+               || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh)
                || parse_mode(viafb_mode1, &dummy_x, &dummy_y)
-               || !viafb_get_mode(dummy_x, dummy_y)
+               || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh1)
                || viafb_bpp < 0 || viafb_bpp > 32
                || viafb_bpp1 < 0 || viafb_bpp1 > 32
                || parse_active_dev())
index 58df74e..0911cac 100644 (file)
@@ -281,7 +281,7 @@ static struct crt_mode_table CRTM640x480[] = {
        /*r_rate,hsp,vsp */
        /*HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
        {REFRESH_60, M640X480_R60_HSP, M640X480_R60_VSP,
-        {800, 640, 648, 144, 656, 96, 525, 480, 480, 45, 490, 2} },
+        {800, 640, 640, 160, 656, 96, 525, 480, 480, 45, 490, 2} },
        {REFRESH_75, M640X480_R75_HSP, M640X480_R75_VSP,
         {840, 640, 640, 200, 656, 64, 500, 480, 480, 20, 481, 3} },
        {REFRESH_85, M640X480_R85_HSP, M640X480_R85_VSP,
@@ -863,26 +863,56 @@ int NUM_TOTAL_CLE266_ModeXregs = ARRAY_SIZE(CLE266_ModeXregs);
 int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table);
 
 
-struct VideoModeTable *viafb_get_mode(int hres, int vres)
+static struct VideoModeTable *get_modes(struct VideoModeTable *vmt, int n,
+       int hres, int vres)
 {
-       u32 i;
-       for (i = 0; i < ARRAY_SIZE(viafb_modes); i++)
-               if (viafb_modes[i].mode_array &&
-                       viafb_modes[i].crtc[0].crtc.hor_addr == hres &&
-                       viafb_modes[i].crtc[0].crtc.ver_addr == vres)
+       int i;
+
+       for (i = 0; i < n; i++)
+               if (vmt[i].mode_array &&
+                       vmt[i].crtc[0].crtc.hor_addr == hres &&
+                       vmt[i].crtc[0].crtc.ver_addr == vres)
                        return &viafb_modes[i];
 
        return NULL;
 }
 
-struct VideoModeTable *viafb_get_rb_mode(int hres, int vres)
+static struct crt_mode_table *get_best_mode(struct VideoModeTable *vmt,
+       int refresh)
 {
-       u32 i;
-       for (i = 0; i < ARRAY_SIZE(viafb_rb_modes); i++)
-               if (viafb_rb_modes[i].mode_array &&
-                       viafb_rb_modes[i].crtc[0].crtc.hor_addr == hres &&
-                       viafb_rb_modes[i].crtc[0].crtc.ver_addr == vres)
-                       return &viafb_rb_modes[i];
+       struct crt_mode_table *best;
+       int i;
 
-       return NULL;
+       if (!vmt)
+               return NULL;
+
+       best = &vmt->crtc[0];
+       for (i = 1; i < vmt->mode_array; i++) {
+               if (abs(vmt->crtc[i].refresh_rate - refresh)
+                       < abs(best->refresh_rate - refresh))
+                       best = &vmt->crtc[i];
+       }
+
+       return best;
+}
+
+static struct VideoModeTable *viafb_get_mode(int hres, int vres)
+{
+       return get_modes(viafb_modes, ARRAY_SIZE(viafb_modes), hres, vres);
+}
+
+struct crt_mode_table *viafb_get_best_mode(int hres, int vres, int refresh)
+{
+       return get_best_mode(viafb_get_mode(hres, vres), refresh);
+}
+
+static struct VideoModeTable *viafb_get_rb_mode(int hres, int vres)
+{
+       return get_modes(viafb_rb_modes, ARRAY_SIZE(viafb_rb_modes), hres,
+               vres);
+}
+
+struct crt_mode_table *viafb_get_best_rb_mode(int hres, int vres, int refresh)
+{
+       return get_best_mode(viafb_get_rb_mode(hres, vres), refresh);
 }
index 3751289..5917a2b 100644 (file)
@@ -60,7 +60,7 @@ extern struct io_reg PM1024x768[];
 extern struct patch_table res_patch_table[];
 extern struct VPITTable VPIT;
 
-struct VideoModeTable *viafb_get_mode(int hres, int vres);
-struct VideoModeTable *viafb_get_rb_mode(int hres, int vres);
+struct crt_mode_table *viafb_get_best_mode(int hres, int vres, int refresh);
+struct crt_mode_table *viafb_get_best_rb_mode(int hres, int vres, int refresh);
 
 #endif /* __VIAMODE_H__ */
index 0e120d6..777c21d 100644 (file)
@@ -210,8 +210,8 @@ static int vt8500lcd_pan_display(struct fb_var_screeninfo *var,
        struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
 
        writel((1 << 31)
-               | (((var->xres_virtual - var->xres) * pixlen / 4) << 20)
-               | (off >> 2), fbi->regbase + 0x20);
+            | (((info->var.xres_virtual - info->var.xres) * pixlen / 4) << 20)
+            | (off >> 2), fbi->regbase + 0x20);
        return 0;
 }
 
@@ -355,7 +355,7 @@ static int __devinit vt8500lcd_probe(struct platform_device *pdev)
                goto failed_free_palette;
        }
 
-       ret = request_irq(irq, vt8500lcd_handle_irq, IRQF_DISABLED, "LCD", fbi);
+       ret = request_irq(irq, vt8500lcd_handle_irq, 0, "LCD", fbi);
        if (ret) {
                dev_err(&pdev->dev, "request_irq failed: %d\n", ret);
                ret = -EBUSY;
index f9b3e3d..4e74d26 100644 (file)
@@ -620,13 +620,14 @@ static int vt8623fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *i
        unsigned int offset;
 
        /* Calculate the offset */
-       if (var->bits_per_pixel == 0) {
-               offset = (var->yoffset / 16) * var->xres_virtual + var->xoffset;
+       if (info->var.bits_per_pixel == 0) {
+               offset = (var->yoffset / 16) * info->var.xres_virtual
+                      + var->xoffset;
                offset = offset >> 3;
        } else {
                offset = (var->yoffset * info->fix.line_length) +
-                        (var->xoffset * var->bits_per_pixel / 8);
-               offset = offset >> ((var->bits_per_pixel == 4) ? 2 : 1);
+                        (var->xoffset * info->var.bits_per_pixel / 8);
+               offset = offset >> ((info->var.bits_per_pixel == 4) ? 2 : 1);
        }
 
        /* Set the offset */
index 77dea01..fcb6cd9 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
index daa9952..11c16a1 100644 (file)
 #ifndef __FSL_DIU_FB_H__
 #define __FSL_DIU_FB_H__
 
-/* Arbitrary threshold to determine the allocation method
- * See mpc8610fb_set_par(), map_video_memory(), and unmap_video_memory()
- */
-#define MEM_ALLOC_THRESHOLD (1024*768*4+32)
-
 #include <linux/types.h>
 
-struct mfb_alpha {
-       int enable;
-       int alpha;
-};
-
 struct mfb_chroma_key {
        int enable;
        __u8  red_max;
@@ -43,25 +33,29 @@ struct mfb_chroma_key {
 };
 
 struct aoi_display_offset {
-       int x_aoi_d;
-       int y_aoi_d;
+       __s32 x_aoi_d;
+       __s32 y_aoi_d;
 };
 
 #define MFB_SET_CHROMA_KEY     _IOW('M', 1, struct mfb_chroma_key)
 #define MFB_SET_BRIGHTNESS     _IOW('M', 3, __u8)
+#define MFB_SET_ALPHA          _IOW('M', 0, __u8)
+#define MFB_GET_ALPHA          _IOR('M', 0, __u8)
+#define MFB_SET_AOID           _IOW('M', 4, struct aoi_display_offset)
+#define MFB_GET_AOID           _IOR('M', 4, struct aoi_display_offset)
+#define MFB_SET_PIXFMT         _IOW('M', 8, __u32)
+#define MFB_GET_PIXFMT         _IOR('M', 8, __u32)
 
-#define MFB_SET_ALPHA          0x80014d00
-#define MFB_GET_ALPHA          0x40014d00
-#define MFB_SET_AOID           0x80084d04
-#define MFB_GET_AOID           0x40084d04
-#define MFB_SET_PIXFMT         0x80014d08
-#define MFB_GET_PIXFMT         0x40014d08
-
-#define FBIOGET_GWINFO         0x46E0
-#define FBIOPUT_GWINFO         0x46E1
+/*
+ * The original definitions of MFB_SET_PIXFMT and MFB_GET_PIXFMT used the
+ * wrong value for 'size' field of the ioctl.  The current macros above use the
+ * right size, but we still need to provide backwards compatibility, at least
+ * for a while.
+*/
+#define MFB_SET_PIXFMT_OLD     0x80014d08
+#define MFB_GET_PIXFMT_OLD     0x40014d08
 
 #ifdef __KERNEL__
-#include <linux/spinlock.h>
 
 /*
  * These are the fields of area descriptor(in DDR memory) for every plane
@@ -159,58 +153,12 @@ struct diu {
        __be32 plut;
 } __attribute__ ((packed));
 
-struct diu_hw {
-       struct diu *diu_reg;
-       spinlock_t reg_lock;
-
-       __u32 mode;             /* DIU operation mode */
-};
-
-struct diu_addr {
-       __u8 __iomem *vaddr;    /* Virtual address */
-       dma_addr_t paddr;       /* Physical address */
-       __u32      offset;
-};
-
-struct diu_pool {
-       struct diu_addr ad;
-       struct diu_addr gamma;
-       struct diu_addr pallete;
-       struct diu_addr cursor;
-};
-
-#define FSL_DIU_BASE_OFFSET    0x2C000 /* Offset of DIU */
-#define INT_LCDC               64      /* DIU interrupt number */
-
-#define FSL_AOI_NUM    6       /* 5 AOIs and one dummy AOI */
-                               /* 1 for plane 0, 2 for plane 1&2 each */
-
-/* Minimum X and Y resolutions */
-#define MIN_XRES       64
-#define MIN_YRES       64
-
-/* HW cursor parameters */
-#define MAX_CURS               32
-
-/* Modes of operation of DIU */
+/*
+ * Modes of operation of DIU.  The DIU supports five different modes, but
+ * the driver only supports modes 0 and 1.
+ */
 #define MFB_MODE0      0       /* DIU off */
 #define MFB_MODE1      1       /* All three planes output to display */
-#define MFB_MODE2      2       /* Plane 1 to display, planes 2+3 written back*/
-#define MFB_MODE3      3       /* All three planes written back to memory */
-#define MFB_MODE4      4       /* Color bar generation */
-
-/* INT_STATUS/INT_MASK field descriptions */
-#define INT_VSYNC      0x01    /* Vsync interrupt  */
-#define INT_VSYNC_WB   0x02    /* Vsync interrupt for write back operation */
-#define INT_UNDRUN     0x04    /* Under run exception interrupt */
-#define INT_PARERR     0x08    /* Display parameters error interrupt */
-#define INT_LS_BF_VS   0x10    /* Lines before vsync. interrupt */
-
-/* Panels'operation modes */
-#define MFB_TYPE_OUTPUT        0       /* Panel output to display */
-#define MFB_TYPE_OFF   1       /* Panel off */
-#define MFB_TYPE_WB    2       /* Panel written back to memory */
-#define MFB_TYPE_TEST  3       /* Panel generate color bar */
 
 #endif /* __KERNEL__ */
 #endif /* __FSL_DIU_FB_H__ */
diff --git a/include/video/omap-panel-dvi.h b/include/video/omap-panel-dvi.h
new file mode 100644 (file)
index 0000000..87ad567
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Header for DVI output driver
+ *
+ * Copyright (C) 2011 Texas Instruments Inc
+ * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __OMAP_PANEL_DVI_H
+#define __OMAP_PANEL_DVI_H
+
+struct omap_dss_device;
+
+/**
+ * struct panel_dvi_platform_data - panel driver configuration data
+ * @platform_enable: platform specific panel enable function
+ * @platform_disable: platform specific panel disable function
+ * @i2c_bus_num: i2c bus id for the panel
+ */
+struct panel_dvi_platform_data {
+       int (*platform_enable)(struct omap_dss_device *dssdev);
+       void (*platform_disable)(struct omap_dss_device *dssdev);
+       u16 i2c_bus_num;
+};
+
+#endif /* __OMAP_PANEL_DVI_H */
diff --git a/include/video/omap-panel-n8x0.h b/include/video/omap-panel-n8x0.h
new file mode 100644 (file)
index 0000000..50a1302
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef __OMAP_PANEL_N8X0_H
+#define __OMAP_PANEL_N8X0_H
+
+struct omap_dss_device;
+
+struct panel_n8x0_data {
+       int (*platform_enable)(struct omap_dss_device *dssdev);
+       void (*platform_disable)(struct omap_dss_device *dssdev);
+       int panel_reset;
+       int ctrl_pwrdown;
+
+       int (*set_backlight)(struct omap_dss_device *dssdev, int level);
+};
+
+#endif
index 921ae93..7dc71f9 100644 (file)
@@ -10,9 +10,7 @@ struct omap_dss_device;
  * @ext_te_gpio: external TE GPIO
  * @esd_interval: interval of ESD checks, 0 = disabled (ms)
  * @ulps_timeout: time to wait before entering ULPS, 0 = disabled (ms)
- * @max_backlight_level: maximum backlight level
- * @set_backlight: pointer to backlight set function
- * @get_backlight: pointer to backlight get function
+ * @use_dsi_backlight: true if panel uses DSI command to control backlight
  */
 struct nokia_dsi_panel_data {
        const char *name;
@@ -25,9 +23,7 @@ struct nokia_dsi_panel_data {
        unsigned esd_interval;
        unsigned ulps_timeout;
 
-       int max_backlight_level;
-       int (*set_backlight)(struct omap_dss_device *dssdev, int level);
-       int (*get_backlight)(struct omap_dss_device *dssdev);
+       bool use_dsi_backlight;
 };
 
 #endif /* __OMAP_NOKIA_DSI_PANEL_H */
diff --git a/include/video/omap-panel-picodlp.h b/include/video/omap-panel-picodlp.h
new file mode 100644 (file)
index 0000000..1c342ef
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * panel data for picodlp panel
+ *
+ * Copyright (C) 2011 Texas Instruments
+ *
+ * Author: Mayuresh Janorkar <mayur@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __PANEL_PICODLP_H
+#define __PANEL_PICODLP_H
+/**
+ * struct : picodlp panel data
+ * picodlp_adapter_id: i2c_adapter number for picodlp
+ */
+struct picodlp_panel_data {
+       int picodlp_adapter_id;
+       int emu_done_gpio;
+       int pwrgood_gpio;
+};
+#endif /* __PANEL_PICODLP_H */
index 3b55ef2..b66ebb2 100644 (file)
 #define DISPC_IRQ_WAKEUP               (1 << 16)
 #define DISPC_IRQ_SYNC_LOST2           (1 << 17)
 #define DISPC_IRQ_VSYNC2               (1 << 18)
+#define DISPC_IRQ_VID3_END_WIN         (1 << 19)
+#define DISPC_IRQ_VID3_FIFO_UNDERFLOW  (1 << 20)
 #define DISPC_IRQ_ACBIAS_COUNT_STAT2   (1 << 21)
 #define DISPC_IRQ_FRAMEDONE2           (1 << 22)
+#define DISPC_IRQ_FRAMEDONEWB          (1 << 23)
+#define DISPC_IRQ_FRAMEDONETV          (1 << 24)
+#define DISPC_IRQ_WBBUFFEROVERFLOW     (1 << 25)
 
 struct omap_dss_device;
 struct omap_overlay_manager;
@@ -60,7 +65,8 @@ enum omap_display_type {
 enum omap_plane {
        OMAP_DSS_GFX    = 0,
        OMAP_DSS_VIDEO1 = 1,
-       OMAP_DSS_VIDEO2 = 2
+       OMAP_DSS_VIDEO2 = 2,
+       OMAP_DSS_VIDEO3 = 3,
 };
 
 enum omap_channel {
@@ -129,6 +135,18 @@ enum omap_dss_venc_type {
        OMAP_DSS_VENC_TYPE_SVIDEO,
 };
 
+enum omap_dss_dsi_pixel_format {
+       OMAP_DSS_DSI_FMT_RGB888,
+       OMAP_DSS_DSI_FMT_RGB666,
+       OMAP_DSS_DSI_FMT_RGB666_PACKED,
+       OMAP_DSS_DSI_FMT_RGB565,
+};
+
+enum omap_dss_dsi_mode {
+       OMAP_DSS_DSI_CMD_MODE = 0,
+       OMAP_DSS_DSI_VIDEO_MODE,
+};
+
 enum omap_display_caps {
        OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE      = 1 << 0,
        OMAP_DSS_DISPLAY_CAP_TEAR_ELIM          = 1 << 1,
@@ -162,11 +180,13 @@ enum omap_dss_rotation_angle {
 
 enum omap_overlay_caps {
        OMAP_DSS_OVL_CAP_SCALE = 1 << 0,
-       OMAP_DSS_OVL_CAP_DISPC = 1 << 1,
+       OMAP_DSS_OVL_CAP_GLOBAL_ALPHA = 1 << 1,
+       OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA = 1 << 2,
+       OMAP_DSS_OVL_CAP_ZORDER = 1 << 3,
 };
 
 enum omap_overlay_manager_caps {
-       OMAP_DSS_OVL_MGR_CAP_DISPC = 1 << 0,
+       OMAP_DSS_DUMMY_VALUE, /* add a dummy value to prevent compiler error */
 };
 
 enum omap_dss_clk_source {
@@ -215,26 +235,67 @@ void rfbi_bus_lock(void);
 void rfbi_bus_unlock(void);
 
 /* DSI */
+
+struct omap_dss_dsi_videomode_data {
+       /* DSI video mode blanking data */
+       /* Unit: byte clock cycles */
+       u16 hsa;
+       u16 hfp;
+       u16 hbp;
+       /* Unit: line clocks */
+       u16 vsa;
+       u16 vfp;
+       u16 vbp;
+
+       /* DSI blanking modes */
+       int blanking_mode;
+       int hsa_blanking_mode;
+       int hbp_blanking_mode;
+       int hfp_blanking_mode;
+
+       /* Video port sync events */
+       int vp_de_pol;
+       int vp_hsync_pol;
+       int vp_vsync_pol;
+       bool vp_vsync_end;
+       bool vp_hsync_end;
+
+       bool ddr_clk_always_on;
+       int window_sync;
+};
+
 void dsi_bus_lock(struct omap_dss_device *dssdev);
 void dsi_bus_unlock(struct omap_dss_device *dssdev);
 int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
                int len);
-int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel,
-               u8 dcs_cmd);
+int dsi_vc_generic_write(struct omap_dss_device *dssdev, int channel, u8 *data,
+               int len);
+int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd);
+int dsi_vc_generic_write_0(struct omap_dss_device *dssdev, int channel);
 int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
                u8 param);
+int dsi_vc_generic_write_1(struct omap_dss_device *dssdev, int channel,
+               u8 param);
+int dsi_vc_generic_write_2(struct omap_dss_device *dssdev, int channel,
+               u8 param1, u8 param2);
 int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel,
                u8 *data, int len);
+int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel,
+               u8 *data, int len);
 int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
                u8 *buf, int buflen);
-int dsi_vc_dcs_read_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
-               u8 *data);
-int dsi_vc_dcs_read_2(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
-               u8 *data1, u8 *data2);
+int dsi_vc_generic_read_0(struct omap_dss_device *dssdev, int channel, u8 *buf,
+               int buflen);
+int dsi_vc_generic_read_1(struct omap_dss_device *dssdev, int channel, u8 param,
+               u8 *buf, int buflen);
+int dsi_vc_generic_read_2(struct omap_dss_device *dssdev, int channel,
+               u8 param1, u8 param2, u8 *buf, int buflen);
 int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel,
                u16 len);
 int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel);
 int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel);
+int dsi_video_mode_enable(struct omap_dss_device *dssdev, int channel);
+void dsi_video_mode_disable(struct omap_dss_device *dssdev, int channel);
 
 /* Board specific data */
 struct omap_dss_board_info {
@@ -242,7 +303,8 @@ struct omap_dss_board_info {
        int num_devices;
        struct omap_dss_device **devices;
        struct omap_dss_device *default_device;
-       void (*dsi_mux_pads)(bool enable);
+       int (*dsi_enable_pads)(int dsi_id, unsigned lane_mask);
+       void (*dsi_disable_pads)(int dsi_id, unsigned lane_mask);
 };
 
 #if defined(CONFIG_OMAP2_DSS_MODULE) || defined(CONFIG_OMAP2_DSS)
@@ -300,7 +362,6 @@ struct omap_overlay_info {
        bool enabled;
 
        u32 paddr;
-       void __iomem *vaddr;
        u32 p_uv_addr;  /* for NV12 format */
        u16 screen_width;
        u16 width;
@@ -316,6 +377,7 @@ struct omap_overlay_info {
        u16 out_height; /* if 0, out_height == height */
        u8 global_alpha;
        u8 pre_mult_alpha;
+       u8 zorder;
 };
 
 struct omap_overlay {
@@ -324,7 +386,7 @@ struct omap_overlay {
 
        /* static fields */
        const char *name;
-       int id;
+       enum omap_plane id;
        enum omap_color_mode supported_modes;
        enum omap_overlay_caps caps;
 
@@ -332,6 +394,7 @@ struct omap_overlay {
        struct omap_overlay_manager *manager;
        struct omap_overlay_info info;
 
+       bool manager_changed;
        /* if true, info has been changed, but not applied() yet */
        bool info_dirty;
 
@@ -354,7 +417,7 @@ struct omap_overlay_manager_info {
        u32 trans_key;
        bool trans_enabled;
 
-       bool alpha_enabled;
+       bool partial_alpha_enabled;
 
        bool cpr_enable;
        struct omap_dss_cpr_coefs cpr_coefs;
@@ -366,7 +429,7 @@ struct omap_overlay_manager {
 
        /* static fields */
        const char *name;
-       int id;
+       enum omap_channel id;
        enum omap_overlay_manager_caps caps;
        int num_overlays;
        struct omap_overlay **overlays;
@@ -454,6 +517,7 @@ struct omap_dss_device {
                } dispc;
 
                struct {
+                       /* regn is one greater than TRM's REGN value */
                        u16 regn;
                        u16 regm;
                        u16 regm_dispc;
@@ -464,6 +528,7 @@ struct omap_dss_device {
                } dsi;
 
                struct {
+                       /* regn is one greater than TRM's REGN value */
                        u16 regn;
                        u16 regm2;
                } hdmi;
@@ -477,6 +542,10 @@ struct omap_dss_device {
                int acb;        /* ac-bias pin frequency */
 
                enum omap_panel_config config;
+
+               enum omap_dss_dsi_pixel_format dsi_pix_fmt;
+               enum omap_dss_dsi_mode dsi_mode;
+               struct omap_dss_dsi_videomode_data dsi_vm_data;
        } panel;
 
        struct {
@@ -557,6 +626,9 @@ struct omap_dss_driver {
 
        int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);
        u32 (*get_wss)(struct omap_dss_device *dssdev);
+
+       int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
+       bool (*detect)(struct omap_dss_device *dssdev);
 };
 
 int omap_dss_register_driver(struct omap_dss_driver *);
index d964e68..8101b72 100644 (file)
 #include <linux/fb.h>
 #include <video/sh_mobile_meram.h>
 
+/* Register definitions */
+#define _LDDCKR                        0x410
+#define LDDCKR_ICKSEL_BUS      (0 << 16)
+#define LDDCKR_ICKSEL_MIPI     (1 << 16)
+#define LDDCKR_ICKSEL_HDMI     (2 << 16)
+#define LDDCKR_ICKSEL_EXT      (3 << 16)
+#define LDDCKR_ICKSEL_MASK     (7 << 16)
+#define LDDCKR_MOSEL           (1 << 6)
+#define _LDDCKSTPR             0x414
+#define _LDINTR                        0x468
+#define LDINTR_FE              (1 << 10)
+#define LDINTR_VSE             (1 << 9)
+#define LDINTR_VEE             (1 << 8)
+#define LDINTR_FS              (1 << 2)
+#define LDINTR_VSS             (1 << 1)
+#define LDINTR_VES             (1 << 0)
+#define LDINTR_STATUS_MASK     (0xff << 0)
+#define _LDSR                  0x46c
+#define LDSR_MSS               (1 << 10)
+#define LDSR_MRS               (1 << 8)
+#define LDSR_AS                        (1 << 1)
+#define _LDCNT1R               0x470
+#define LDCNT1R_DE             (1 << 0)
+#define _LDCNT2R               0x474
+#define LDCNT2R_BR             (1 << 8)
+#define LDCNT2R_MD             (1 << 3)
+#define LDCNT2R_SE             (1 << 2)
+#define LDCNT2R_ME             (1 << 1)
+#define LDCNT2R_DO             (1 << 0)
+#define _LDRCNTR               0x478
+#define LDRCNTR_SRS            (1 << 17)
+#define LDRCNTR_SRC            (1 << 16)
+#define LDRCNTR_MRS            (1 << 1)
+#define LDRCNTR_MRC            (1 << 0)
+#define _LDDDSR                        0x47c
+#define LDDDSR_LS              (1 << 2)
+#define LDDDSR_WS              (1 << 1)
+#define LDDDSR_BS              (1 << 0)
+
+#define LDMT1R_VPOL            (1 << 28)
+#define LDMT1R_HPOL            (1 << 27)
+#define LDMT1R_DWPOL           (1 << 26)
+#define LDMT1R_DIPOL           (1 << 25)
+#define LDMT1R_DAPOL           (1 << 24)
+#define LDMT1R_HSCNT           (1 << 17)
+#define LDMT1R_DWCNT           (1 << 16)
+#define LDMT1R_IFM             (1 << 12)
+#define LDMT1R_MIFTYP_RGB8     (0x0 << 0)
+#define LDMT1R_MIFTYP_RGB9     (0x4 << 0)
+#define LDMT1R_MIFTYP_RGB12A   (0x5 << 0)
+#define LDMT1R_MIFTYP_RGB12B   (0x6 << 0)
+#define LDMT1R_MIFTYP_RGB16    (0x7 << 0)
+#define LDMT1R_MIFTYP_RGB18    (0xa << 0)
+#define LDMT1R_MIFTYP_RGB24    (0xb << 0)
+#define LDMT1R_MIFTYP_YCBCR    (0xf << 0)
+#define LDMT1R_MIFTYP_SYS8A    (0x0 << 0)
+#define LDMT1R_MIFTYP_SYS8B    (0x1 << 0)
+#define LDMT1R_MIFTYP_SYS8C    (0x2 << 0)
+#define LDMT1R_MIFTYP_SYS8D    (0x3 << 0)
+#define LDMT1R_MIFTYP_SYS9     (0x4 << 0)
+#define LDMT1R_MIFTYP_SYS12    (0x5 << 0)
+#define LDMT1R_MIFTYP_SYS16A   (0x7 << 0)
+#define LDMT1R_MIFTYP_SYS16B   (0x8 << 0)
+#define LDMT1R_MIFTYP_SYS16C   (0x9 << 0)
+#define LDMT1R_MIFTYP_SYS18    (0xa << 0)
+#define LDMT1R_MIFTYP_SYS24    (0xb << 0)
+#define LDMT1R_MIFTYP_MASK     (0xf << 0)
+
+#define LDDFR_CF1              (1 << 18)
+#define LDDFR_CF0              (1 << 17)
+#define LDDFR_CC               (1 << 16)
+#define LDDFR_YF_420           (0 << 8)
+#define LDDFR_YF_422           (1 << 8)
+#define LDDFR_YF_444           (2 << 8)
+#define LDDFR_YF_MASK          (3 << 8)
+#define LDDFR_PKF_ARGB32       (0x00 << 0)
+#define LDDFR_PKF_RGB16                (0x03 << 0)
+#define LDDFR_PKF_RGB24                (0x0b << 0)
+#define LDDFR_PKF_MASK         (0x1f << 0)
+
+#define LDSM1R_OS              (1 << 0)
+
+#define LDSM2R_OSTRG           (1 << 0)
+
+#define LDPMR_LPS              (3 << 0)
+
+#define _LDDWD0R               0x800
+#define LDDWDxR_WDACT          (1 << 28)
+#define LDDWDxR_RSW            (1 << 24)
+#define _LDDRDR                        0x840
+#define LDDRDR_RSR             (1 << 24)
+#define LDDRDR_DRD_MASK                (0x3ffff << 0)
+#define _LDDWAR                        0x900
+#define LDDWAR_WA              (1 << 0)
+#define _LDDRAR                        0x904
+#define LDDRAR_RA              (1 << 0)
+
 enum {
-       RGB8,   /* 24bpp, 8:8:8 */
-       RGB9,   /* 18bpp, 9:9 */
-       RGB12A, /* 24bpp, 12:12 */
-       RGB12B, /* 12bpp */
-       RGB16,  /* 16bpp */
-       RGB18,  /* 18bpp */
-       RGB24,  /* 24bpp */
-       YUV422, /* 16bpp */
-       SYS8A,  /* 24bpp, 8:8:8 */
-       SYS8B,  /* 18bpp, 8:8:2 */
-       SYS8C,  /* 18bpp, 2:8:8 */
-       SYS8D,  /* 16bpp, 8:8 */
-       SYS9,   /* 18bpp, 9:9 */
-       SYS12,  /* 24bpp, 12:12 */
-       SYS16A, /* 16bpp */
-       SYS16B, /* 18bpp, 16:2 */
-       SYS16C, /* 18bpp, 2:16 */
-       SYS18,  /* 18bpp */
-       SYS24,  /* 24bpp */
+       RGB8    = LDMT1R_MIFTYP_RGB8,   /* 24bpp, 8:8:8 */
+       RGB9    = LDMT1R_MIFTYP_RGB9,   /* 18bpp, 9:9 */
+       RGB12A  = LDMT1R_MIFTYP_RGB12A, /* 24bpp, 12:12 */
+       RGB12B  = LDMT1R_MIFTYP_RGB12B, /* 12bpp */
+       RGB16   = LDMT1R_MIFTYP_RGB16,  /* 16bpp */
+       RGB18   = LDMT1R_MIFTYP_RGB18,  /* 18bpp */
+       RGB24   = LDMT1R_MIFTYP_RGB24,  /* 24bpp */
+       YUV422  = LDMT1R_MIFTYP_YCBCR,  /* 16bpp */
+       SYS8A   = LDMT1R_IFM | LDMT1R_MIFTYP_SYS8A,     /* 24bpp, 8:8:8 */
+       SYS8B   = LDMT1R_IFM | LDMT1R_MIFTYP_SYS8B,     /* 18bpp, 8:8:2 */
+       SYS8C   = LDMT1R_IFM | LDMT1R_MIFTYP_SYS8C,     /* 18bpp, 2:8:8 */
+       SYS8D   = LDMT1R_IFM | LDMT1R_MIFTYP_SYS8D,     /* 16bpp, 8:8 */
+       SYS9    = LDMT1R_IFM | LDMT1R_MIFTYP_SYS9,      /* 18bpp, 9:9 */
+       SYS12   = LDMT1R_IFM | LDMT1R_MIFTYP_SYS12,     /* 24bpp, 12:12 */
+       SYS16A  = LDMT1R_IFM | LDMT1R_MIFTYP_SYS16A,    /* 16bpp */
+       SYS16B  = LDMT1R_IFM | LDMT1R_MIFTYP_SYS16B,    /* 18bpp, 16:2 */
+       SYS16C  = LDMT1R_IFM | LDMT1R_MIFTYP_SYS16C,    /* 18bpp, 2:16 */
+       SYS18   = LDMT1R_IFM | LDMT1R_MIFTYP_SYS18,     /* 18bpp */
+       SYS24   = LDMT1R_IFM | LDMT1R_MIFTYP_SYS24,     /* 24bpp */
 };
 
 enum { LCDC_CHAN_DISABLED = 0,
index 69d485a..c41f308 100644 (file)
@@ -50,6 +50,7 @@ struct dlfb_data {
        int base16;
        int base8;
        u32 pseudo_palette[256];
+       int blank_mode; /*one of FB_BLANK_ */
        /* blit-only rendering path metrics, exposed through sysfs */
        atomic_t bytes_rendered; /* raw pixel-bytes driver asked to render */
        atomic_t bytes_identical; /* saved effort with backbuffer comparison */