Merge branch 'for-linus' of git://gitorious.org/linux-omap-dss2/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 2 Mar 2010 18:41:26 +0000 (10:41 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 2 Mar 2010 18:41:26 +0000 (10:41 -0800)
* 'for-linus' of git://gitorious.org/linux-omap-dss2/linux: (49 commits)
  OMAP: DSS2: Taal: Fix TE when resuming
  OMAP: DSS2: Taal: Fix ESD check
  OMAP: DSS2: OMAPFB: Constify some function parameters
  OMAP: DSS2: OMAPFB: install omapfb.h
  OMAP: DSS2: DSI: add error prints
  OMAP: DSS2: TPO-TD03MTEA1: fix function names
  OMAP: DSS2: DSI: add dsi_vc_dcs_read_2() helper
  OMAP: DSS2: OMAPFB: Remove FB_OMAP2_FORCE_AUTO_UPDATE
  OMAP: DSS2: DSI: remove external TE support
  OMAP: DSS2: move timing functions
  OMAP: DSS2: move set/get_wss()
  OMAP: DSS2: move enable/disable/suspend/resume
  OMAP: DSS2: move update() and sync()
  OMAP: DSS2: move set/get_update_mode()
  OMAP: DSS2: move enable/get_te()
  OMAP: DSS2: move get_recommended_bpp()
  OMAP: DSS2: move get_resolution()
  OMAP: DSS2: move enable/disable_channel to overlay manager
  OMAP: DSS2: move wait_vsync()
  OMAP: DSS2: move get/set_rotate()
  ...

31 files changed:
arch/arm/mach-omap2/board-3430sdp.c
arch/arm/plat-omap/include/plat/display.h
drivers/video/omap/lcd_ams_delta.c
drivers/video/omap/omapfb_main.c
drivers/video/omap2/displays/Kconfig
drivers/video/omap2/displays/Makefile
drivers/video/omap2/displays/panel-generic.c
drivers/video/omap2/displays/panel-sharp-lq043t1dg01.c [new file with mode: 0644]
drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
drivers/video/omap2/displays/panel-taal.c
drivers/video/omap2/displays/panel-toppoly-tdo35s.c [new file with mode: 0644]
drivers/video/omap2/displays/panel-tpo-td043mtea1.c [new file with mode: 0644]
drivers/video/omap2/dss/Kconfig
drivers/video/omap2/dss/core.c
drivers/video/omap2/dss/dispc.c
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/manager.c
drivers/video/omap2/dss/overlay.c
drivers/video/omap2/dss/rfbi.c
drivers/video/omap2/dss/sdi.c
drivers/video/omap2/dss/venc.c
drivers/video/omap2/omapfb/Kconfig
drivers/video/omap2/omapfb/omapfb-ioctl.c
drivers/video/omap2/omapfb/omapfb-main.c
drivers/video/omap2/omapfb/omapfb.h
include/linux/Kbuild
include/linux/omapfb.h

index f312b15..a101029 100644 (file)
@@ -541,10 +541,6 @@ static struct regulator_init_data sdp3430_vdac = {
 
 /* VPLL2 for digital video outputs */
 static struct regulator_consumer_supply sdp3430_vpll2_supplies[] = {
-       {
-               .supply         = "vdvi",
-               .dev            = &sdp3430_lcd_device.dev,
-       },
        {
                .supply         = "vdds_dsi",
                .dev            = &sdp3430_dss_device.dev,
index c66e464..1c529ce 100644 (file)
@@ -233,8 +233,12 @@ int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
 void dsi_bus_lock(void);
 void dsi_bus_unlock(void);
 int dsi_vc_dcs_write(int channel, u8 *data, int len);
+int dsi_vc_dcs_write_0(int channel, u8 dcs_cmd);
+int dsi_vc_dcs_write_1(int channel, u8 dcs_cmd, u8 param);
 int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len);
 int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen);
+int dsi_vc_dcs_read_1(int channel, u8 dcs_cmd, u8 *data);
+int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u16 *data);
 int dsi_vc_set_max_rx_packet_size(int channel, u16 len);
 int dsi_vc_send_null(int channel);
 int dsi_vc_send_bta_sync(int channel);
@@ -367,6 +371,10 @@ struct omap_overlay_manager {
 
        int (*apply)(struct omap_overlay_manager *mgr);
        int (*wait_for_go)(struct omap_overlay_manager *mgr);
+       int (*wait_for_vsync)(struct omap_overlay_manager *mgr);
+
+       int (*enable)(struct omap_overlay_manager *mgr);
+       int (*disable)(struct omap_overlay_manager *mgr);
 };
 
 struct omap_dss_device {
@@ -426,16 +434,11 @@ struct omap_dss_device {
                int acb;        /* ac-bias pin frequency */
 
                enum omap_panel_config config;
-
-               u8 recommended_bpp;
-
-               struct omap_dss_device *ctrl;
        } panel;
 
        struct {
                u8 pixel_size;
                struct rfbi_timings rfbi_timings;
-               struct omap_dss_device *panel;
        } ctrl;
 
        int reset_gpio;
@@ -460,49 +463,6 @@ struct omap_dss_device {
 
        enum omap_dss_display_state state;
 
-       int (*enable)(struct omap_dss_device *dssdev);
-       void (*disable)(struct omap_dss_device *dssdev);
-
-       int (*suspend)(struct omap_dss_device *dssdev);
-       int (*resume)(struct omap_dss_device *dssdev);
-
-       void (*get_resolution)(struct omap_dss_device *dssdev,
-                       u16 *xres, u16 *yres);
-       int (*get_recommended_bpp)(struct omap_dss_device *dssdev);
-
-       int (*check_timings)(struct omap_dss_device *dssdev,
-                       struct omap_video_timings *timings);
-       void (*set_timings)(struct omap_dss_device *dssdev,
-                       struct omap_video_timings *timings);
-       void (*get_timings)(struct omap_dss_device *dssdev,
-                       struct omap_video_timings *timings);
-       int (*update)(struct omap_dss_device *dssdev,
-                              u16 x, u16 y, u16 w, u16 h);
-       int (*sync)(struct omap_dss_device *dssdev);
-       int (*wait_vsync)(struct omap_dss_device *dssdev);
-
-       int (*set_update_mode)(struct omap_dss_device *dssdev,
-                       enum omap_dss_update_mode);
-       enum omap_dss_update_mode (*get_update_mode)
-               (struct omap_dss_device *dssdev);
-
-       int (*enable_te)(struct omap_dss_device *dssdev, bool enable);
-       int (*get_te)(struct omap_dss_device *dssdev);
-
-       u8 (*get_rotate)(struct omap_dss_device *dssdev);
-       int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate);
-
-       bool (*get_mirror)(struct omap_dss_device *dssdev);
-       int (*set_mirror)(struct omap_dss_device *dssdev, bool enable);
-
-       int (*run_test)(struct omap_dss_device *dssdev, int test);
-       int (*memory_read)(struct omap_dss_device *dssdev,
-                       void *buf, size_t size,
-                       u16 x, u16 y, u16 w, u16 h);
-
-       int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);
-       u32 (*get_wss)(struct omap_dss_device *dssdev);
-
        /* platform specific  */
        int (*platform_enable)(struct omap_dss_device *dssdev);
        void (*platform_disable)(struct omap_dss_device *dssdev);
@@ -522,11 +482,17 @@ struct omap_dss_driver {
        int (*resume)(struct omap_dss_device *display);
        int (*run_test)(struct omap_dss_device *display, int test);
 
-       void (*setup_update)(struct omap_dss_device *dssdev,
-                       u16 x, u16 y, u16 w, u16 h);
+       int (*set_update_mode)(struct omap_dss_device *dssdev,
+                       enum omap_dss_update_mode);
+       enum omap_dss_update_mode (*get_update_mode)(
+                       struct omap_dss_device *dssdev);
+
+       int (*update)(struct omap_dss_device *dssdev,
+                              u16 x, u16 y, u16 w, u16 h);
+       int (*sync)(struct omap_dss_device *dssdev);
 
        int (*enable_te)(struct omap_dss_device *dssdev, bool enable);
-       int (*wait_for_te)(struct omap_dss_device *dssdev);
+       int (*get_te)(struct omap_dss_device *dssdev);
 
        u8 (*get_rotate)(struct omap_dss_device *dssdev);
        int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate);
@@ -537,6 +503,20 @@ struct omap_dss_driver {
        int (*memory_read)(struct omap_dss_device *dssdev,
                        void *buf, size_t size,
                        u16 x, u16 y, u16 w, u16 h);
+
+       void (*get_resolution)(struct omap_dss_device *dssdev,
+                       u16 *xres, u16 *yres);
+       int (*get_recommended_bpp)(struct omap_dss_device *dssdev);
+
+       int (*check_timings)(struct omap_dss_device *dssdev,
+                       struct omap_video_timings *timings);
+       void (*set_timings)(struct omap_dss_device *dssdev,
+                       struct omap_video_timings *timings);
+       void (*get_timings)(struct omap_dss_device *dssdev,
+                       struct omap_video_timings *timings);
+
+       int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);
+       u32 (*get_wss)(struct omap_dss_device *dssdev);
 };
 
 int omap_dss_register_driver(struct omap_dss_driver *);
@@ -561,6 +541,10 @@ struct omap_overlay_manager *omap_dss_get_overlay_manager(int num);
 int omap_dss_get_num_overlays(void);
 struct omap_overlay *omap_dss_get_overlay(int num);
 
+void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
+               u16 *xres, u16 *yres);
+int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev);
+
 typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
 int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
 int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
@@ -572,4 +556,35 @@ int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
 #define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver)
 #define to_dss_device(x) container_of((x), struct omap_dss_device, dev)
 
+void omapdss_dsi_vc_enable_hs(int channel, bool enable);
+int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable);
+
+int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
+                                   u16 *x, u16 *y, u16 *w, u16 *h);
+int omap_dsi_update(struct omap_dss_device *dssdev,
+               int channel,
+               u16 x, u16 y, u16 w, u16 h,
+               void (*callback)(int, void *), void *data);
+
+int omapdss_dsi_display_enable(struct omap_dss_device *dssdev);
+void omapdss_dsi_display_disable(struct omap_dss_device *dssdev);
+
+int omapdss_dpi_display_enable(struct omap_dss_device *dssdev);
+void omapdss_dpi_display_disable(struct omap_dss_device *dssdev);
+void dpi_set_timings(struct omap_dss_device *dssdev,
+                       struct omap_video_timings *timings);
+int dpi_check_timings(struct omap_dss_device *dssdev,
+                       struct omap_video_timings *timings);
+
+int omapdss_sdi_display_enable(struct omap_dss_device *dssdev);
+void omapdss_sdi_display_disable(struct omap_dss_device *dssdev);
+
+int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev);
+void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev);
+int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
+               u16 *x, u16 *y, u16 *w, u16 *h);
+int omap_rfbi_update(struct omap_dss_device *dssdev,
+               u16 x, u16 y, u16 w, u16 h,
+               void (*callback)(void *), void *data);
+
 #endif
index 567db6a..6978ae4 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/delay.h>
+#include <linux/lcd.h>
 
 #include <plat/board-ams-delta.h>
 #include <mach/hardware.h>
 
 #define AMS_DELTA_DEFAULT_CONTRAST     112
 
+#define AMS_DELTA_MAX_CONTRAST         0x00FF
+#define AMS_DELTA_LCD_POWER            0x0100
+
+
+/* LCD class device section */
+
+static int ams_delta_lcd;
+
+static int ams_delta_lcd_set_power(struct lcd_device *dev, int power)
+{
+       if (power == FB_BLANK_UNBLANK) {
+               if (!(ams_delta_lcd & AMS_DELTA_LCD_POWER)) {
+                       omap_writeb(ams_delta_lcd & AMS_DELTA_MAX_CONTRAST,
+                                       OMAP_PWL_ENABLE);
+                       omap_writeb(1, OMAP_PWL_CLK_ENABLE);
+                       ams_delta_lcd |= AMS_DELTA_LCD_POWER;
+               }
+       } else {
+               if (ams_delta_lcd & AMS_DELTA_LCD_POWER) {
+                       omap_writeb(0, OMAP_PWL_ENABLE);
+                       omap_writeb(0, OMAP_PWL_CLK_ENABLE);
+                       ams_delta_lcd &= ~AMS_DELTA_LCD_POWER;
+               }
+       }
+       return 0;
+}
+
+static int ams_delta_lcd_set_contrast(struct lcd_device *dev, int value)
+{
+       if ((value >= 0) && (value <= AMS_DELTA_MAX_CONTRAST)) {
+               omap_writeb(value, OMAP_PWL_ENABLE);
+               ams_delta_lcd &= ~AMS_DELTA_MAX_CONTRAST;
+               ams_delta_lcd |= value;
+       }
+       return 0;
+}
+
+#ifdef CONFIG_LCD_CLASS_DEVICE
+static int ams_delta_lcd_get_power(struct lcd_device *dev)
+{
+       if (ams_delta_lcd & AMS_DELTA_LCD_POWER)
+               return FB_BLANK_UNBLANK;
+       else
+               return FB_BLANK_POWERDOWN;
+}
+
+static int ams_delta_lcd_get_contrast(struct lcd_device *dev)
+{
+       if (!(ams_delta_lcd & AMS_DELTA_LCD_POWER))
+               return 0;
+
+       return ams_delta_lcd & AMS_DELTA_MAX_CONTRAST;
+}
+
+static struct lcd_ops ams_delta_lcd_ops = {
+       .get_power = ams_delta_lcd_get_power,
+       .set_power = ams_delta_lcd_set_power,
+       .get_contrast = ams_delta_lcd_get_contrast,
+       .set_contrast = ams_delta_lcd_set_contrast,
+};
+#endif
+
+
+/* omapfb panel section */
+
 static int ams_delta_panel_init(struct lcd_panel *panel,
                struct omapfb_device *fbdev)
 {
@@ -48,10 +114,6 @@ static int ams_delta_panel_enable(struct lcd_panel *panel)
                        AMS_DELTA_LATCH2_LCD_NDISP);
        ams_delta_latch2_write(AMS_DELTA_LATCH2_LCD_VBLEN,
                        AMS_DELTA_LATCH2_LCD_VBLEN);
-
-       omap_writeb(1, OMAP_PWL_CLK_ENABLE);
-       omap_writeb(AMS_DELTA_DEFAULT_CONTRAST, OMAP_PWL_ENABLE);
-
        return 0;
 }
 
@@ -91,8 +153,31 @@ static struct lcd_panel ams_delta_panel = {
        .get_caps       = ams_delta_panel_get_caps,
 };
 
+
+/* platform driver section */
+
 static int ams_delta_panel_probe(struct platform_device *pdev)
 {
+       struct lcd_device *lcd_device = NULL;
+#ifdef CONFIG_LCD_CLASS_DEVICE
+       int ret;
+
+       lcd_device = lcd_device_register("omapfb", &pdev->dev, NULL,
+                                               &ams_delta_lcd_ops);
+
+       if (IS_ERR(lcd_device)) {
+               ret = PTR_ERR(lcd_device);
+               dev_err(&pdev->dev, "failed to register device\n");
+               return ret;
+       }
+
+       platform_set_drvdata(pdev, lcd_device);
+       lcd_device->props.max_contrast = AMS_DELTA_MAX_CONTRAST;
+#endif
+
+       ams_delta_lcd_set_contrast(lcd_device, AMS_DELTA_DEFAULT_CONTRAST);
+       ams_delta_lcd_set_power(lcd_device, FB_BLANK_UNBLANK);
+
        omapfb_register_panel(&ams_delta_panel);
        return 0;
 }
index 2c4f470..8ce60e1 100644 (file)
@@ -486,10 +486,11 @@ static int set_color_mode(struct omapfb_plane_struct *plane,
                return 0;
        case 12:
                var->bits_per_pixel = 16;
-               plane->color_mode = OMAPFB_COLOR_RGB444;
-               return 0;
        case 16:
-               plane->color_mode = OMAPFB_COLOR_RGB565;
+               if (plane->fbdev->panel->bpp == 12)
+                       plane->color_mode = OMAPFB_COLOR_RGB444;
+               else
+                       plane->color_mode = OMAPFB_COLOR_RGB565;
                return 0;
        default:
                return -EINVAL;
index b12a59c..dfb57ee 100644 (file)
@@ -13,10 +13,28 @@ config PANEL_SHARP_LS037V7DW01
         help
           LCD Panel used in TI's SDP3430 and EVM boards
 
+config PANEL_SHARP_LQ043T1DG01
+        tristate "Sharp LQ043T1DG01 LCD Panel"
+        depends on OMAP2_DSS
+        help
+          LCD Panel used in TI's OMAP3517 EVM boards
+
 config PANEL_TAAL
         tristate "Taal DSI Panel"
         depends on OMAP2_DSS_DSI
         help
           Taal DSI command mode panel from TPO.
 
+config PANEL_TOPPOLY_TDO35S
+        tristate "Toppoly TDO35S LCD Panel support"
+        depends on OMAP2_DSS
+        help
+          LCD Panel used in CM-T35
+
+config PANEL_TPO_TD043MTEA1
+        tristate "TPO TD043MTEA1 LCD Panel"
+        depends on OMAP2_DSS && I2C
+        help
+          LCD Panel used in OMAP3 Pandora
+
 endmenu
index 9556464..e2bb321 100644 (file)
@@ -1,4 +1,7 @@
 obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o
 obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
+obj-$(CONFIG_PANEL_SHARP_LQ043T1DG01) += panel-sharp-lq043t1dg01.o
 
 obj-$(CONFIG_PANEL_TAAL) += panel-taal.o
+obj-$(CONFIG_PANEL_TOPPOLY_TDO35S) += panel-toppoly-tdo35s.o
+obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
index eb48d1a..c59e4ba 100644 (file)
@@ -35,6 +35,35 @@ static struct omap_video_timings generic_panel_timings = {
        .vbp            = 7,
 };
 
+static int generic_panel_power_on(struct omap_dss_device *dssdev)
+{
+       int r;
+
+       r = omapdss_dpi_display_enable(dssdev);
+       if (r)
+               goto err0;
+
+       if (dssdev->platform_enable) {
+               r = dssdev->platform_enable(dssdev);
+               if (r)
+                       goto err1;
+       }
+
+       return 0;
+err1:
+       omapdss_dpi_display_disable(dssdev);
+err0:
+       return r;
+}
+
+static void generic_panel_power_off(struct omap_dss_device *dssdev)
+{
+       if (dssdev->platform_disable)
+               dssdev->platform_disable(dssdev);
+
+       omapdss_dpi_display_disable(dssdev);
+}
+
 static int generic_panel_probe(struct omap_dss_device *dssdev)
 {
        dssdev->panel.config = OMAP_DSS_LCD_TFT;
@@ -51,27 +80,40 @@ static int generic_panel_enable(struct omap_dss_device *dssdev)
 {
        int r = 0;
 
-       if (dssdev->platform_enable)
-               r = dssdev->platform_enable(dssdev);
+       r = generic_panel_power_on(dssdev);
+       if (r)
+               return r;
 
-       return r;
+       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+       return 0;
 }
 
 static void generic_panel_disable(struct omap_dss_device *dssdev)
 {
-       if (dssdev->platform_disable)
-               dssdev->platform_disable(dssdev);
+       generic_panel_power_off(dssdev);
+
+       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 }
 
 static int generic_panel_suspend(struct omap_dss_device *dssdev)
 {
-       generic_panel_disable(dssdev);
+       generic_panel_power_off(dssdev);
+       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
        return 0;
 }
 
 static int generic_panel_resume(struct omap_dss_device *dssdev)
 {
-       return generic_panel_enable(dssdev);
+       int r = 0;
+
+       r = generic_panel_power_on(dssdev);
+       if (r)
+               return r;
+
+       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+       return 0;
 }
 
 static struct omap_dss_driver generic_driver = {
diff --git a/drivers/video/omap2/displays/panel-sharp-lq043t1dg01.c b/drivers/video/omap2/displays/panel-sharp-lq043t1dg01.c
new file mode 100644 (file)
index 0000000..1026746
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * LCD panel driver for Sharp LQ043T1DG01
+ *
+ * Copyright (C) 2009 Texas Instruments Inc
+ * Author: Vaibhav Hiremath <hvaibhav@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/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+
+#include <plat/display.h>
+
+static struct omap_video_timings sharp_lq_timings = {
+       .x_res = 480,
+       .y_res = 272,
+
+       .pixel_clock    = 9000,
+
+       .hsw            = 42,
+       .hfp            = 3,
+       .hbp            = 2,
+
+       .vsw            = 11,
+       .vfp            = 3,
+       .vbp            = 2,
+};
+
+static int sharp_lq_panel_power_on(struct omap_dss_device *dssdev)
+{
+       int r;
+
+       r = omapdss_dpi_display_enable(dssdev);
+       if (r)
+               goto err0;
+
+       /* wait couple of vsyncs until enabling the LCD */
+       msleep(50);
+
+       if (dssdev->platform_enable) {
+               r = dssdev->platform_enable(dssdev);
+               if (r)
+                       goto err1;
+       }
+
+       return 0;
+err1:
+       omapdss_dpi_display_disable(dssdev);
+err0:
+       return r;
+}
+
+static void sharp_lq_panel_power_off(struct omap_dss_device *dssdev)
+{
+       if (dssdev->platform_disable)
+               dssdev->platform_disable(dssdev);
+
+       /* wait at least 5 vsyncs after disabling the LCD */
+       msleep(100);
+
+       omapdss_dpi_display_disable(dssdev);
+}
+
+static int sharp_lq_panel_probe(struct omap_dss_device *dssdev)
+{
+
+       dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+               OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IEO;
+       dssdev->panel.acb = 0x0;
+       dssdev->panel.timings = sharp_lq_timings;
+
+       return 0;
+}
+
+static void sharp_lq_panel_remove(struct omap_dss_device *dssdev)
+{
+}
+
+static int sharp_lq_panel_enable(struct omap_dss_device *dssdev)
+{
+       int r = 0;
+
+       r = sharp_lq_panel_power_on(dssdev);
+       if (r)
+               return r;
+
+       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+       return 0;
+}
+
+static void sharp_lq_panel_disable(struct omap_dss_device *dssdev)
+{
+       sharp_lq_panel_power_off(dssdev);
+
+       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+}
+
+static int sharp_lq_panel_suspend(struct omap_dss_device *dssdev)
+{
+       sharp_lq_panel_power_off(dssdev);
+       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+       return 0;
+}
+
+static int sharp_lq_panel_resume(struct omap_dss_device *dssdev)
+{
+       int r = 0;
+
+       r = sharp_lq_panel_power_on(dssdev);
+       if (r)
+               return r;
+
+       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+       return 0;
+}
+
+static struct omap_dss_driver sharp_lq_driver = {
+       .probe          = sharp_lq_panel_probe,
+       .remove         = sharp_lq_panel_remove,
+
+       .enable         = sharp_lq_panel_enable,
+       .disable        = sharp_lq_panel_disable,
+       .suspend        = sharp_lq_panel_suspend,
+       .resume         = sharp_lq_panel_resume,
+
+       .driver         = {
+               .name   = "sharp_lq_panel",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init sharp_lq_panel_drv_init(void)
+{
+       return omap_dss_register_driver(&sharp_lq_driver);
+}
+
+static void __exit sharp_lq_panel_drv_exit(void)
+{
+       omap_dss_unregister_driver(&sharp_lq_driver);
+}
+
+module_init(sharp_lq_panel_drv_init);
+module_exit(sharp_lq_panel_drv_exit);
+MODULE_LICENSE("GPL");
index bbe880b..8d51a5e 100644 (file)
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/device.h>
-#include <linux/regulator/consumer.h>
 #include <linux/err.h>
 
 #include <plat/display.h>
 
-struct sharp_data {
-       /* XXX This regulator should actually be in SDP board file, not here,
-        * as it doesn't actually power the LCD, but something else that
-        * affects the output to LCD (I think. Somebody clarify). It doesn't do
-        * harm here, as SDP is the only board using this currently */
-       struct regulator *vdvi_reg;
-};
-
 static struct omap_video_timings sharp_ls_timings = {
        .x_res = 480,
        .y_res = 640,
@@ -50,77 +41,81 @@ static struct omap_video_timings sharp_ls_timings = {
 
 static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
 {
-       struct sharp_data *sd;
-
        dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
                OMAP_DSS_LCD_IHS;
        dssdev->panel.acb = 0x28;
        dssdev->panel.timings = sharp_ls_timings;
 
-       sd = kzalloc(sizeof(*sd), GFP_KERNEL);
-       if (!sd)
-               return -ENOMEM;
-
-       dev_set_drvdata(&dssdev->dev, sd);
-
-       sd->vdvi_reg = regulator_get(&dssdev->dev, "vdvi");
-       if (IS_ERR(sd->vdvi_reg)) {
-               kfree(sd);
-               pr_err("failed to get VDVI regulator\n");
-               return PTR_ERR(sd->vdvi_reg);
-       }
-
        return 0;
 }
 
 static void sharp_ls_panel_remove(struct omap_dss_device *dssdev)
 {
-       struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
-
-       regulator_put(sd->vdvi_reg);
-
-       kfree(sd);
 }
 
-static int sharp_ls_panel_enable(struct omap_dss_device *dssdev)
+static int sharp_ls_power_on(struct omap_dss_device *dssdev)
 {
-       struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
        int r = 0;
 
+       r = omapdss_dpi_display_enable(dssdev);
+       if (r)
+               goto err0;
+
        /* wait couple of vsyncs until enabling the LCD */
        msleep(50);
 
-       regulator_enable(sd->vdvi_reg);
-
-       if (dssdev->platform_enable)
+       if (dssdev->platform_enable) {
                r = dssdev->platform_enable(dssdev);
+               if (r)
+                       goto err1;
+       }
 
+       return 0;
+err1:
+       omapdss_dpi_display_disable(dssdev);
+err0:
        return r;
 }
 
-static void sharp_ls_panel_disable(struct omap_dss_device *dssdev)
+static void sharp_ls_power_off(struct omap_dss_device *dssdev)
 {
-       struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
-
        if (dssdev->platform_disable)
                dssdev->platform_disable(dssdev);
 
-       regulator_disable(sd->vdvi_reg);
-
        /* wait at least 5 vsyncs after disabling the LCD */
 
        msleep(100);
+
+       omapdss_dpi_display_disable(dssdev);
+}
+
+static int sharp_ls_panel_enable(struct omap_dss_device *dssdev)
+{
+       int r;
+       r = sharp_ls_power_on(dssdev);
+       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+       return r;
+}
+
+static void sharp_ls_panel_disable(struct omap_dss_device *dssdev)
+{
+       sharp_ls_power_off(dssdev);
+       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 }
 
 static int sharp_ls_panel_suspend(struct omap_dss_device *dssdev)
 {
-       sharp_ls_panel_disable(dssdev);
+       sharp_ls_power_off(dssdev);
+       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
        return 0;
 }
 
 static int sharp_ls_panel_resume(struct omap_dss_device *dssdev)
 {
-       return sharp_ls_panel_enable(dssdev);
+       int r;
+       r = sharp_ls_power_on(dssdev);
+       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+       return r;
 }
 
 static struct omap_dss_driver sharp_ls_driver = {
index 1f01dfc..fcd6a61 100644 (file)
@@ -63,6 +63,8 @@
 /* #define TAAL_USE_ESD_CHECK */
 #define TAAL_ESD_CHECK_PERIOD  msecs_to_jiffies(5000)
 
+static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable);
+
 struct taal_data {
        struct backlight_device *bldev;
 
@@ -510,15 +512,12 @@ static int taal_probe(struct omap_dss_device *dssdev)
        if (td->esd_wq == NULL) {
                dev_err(&dssdev->dev, "can't create ESD workqueue\n");
                r = -ENOMEM;
-               goto err2;
+               goto err1;
        }
        INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work);
 
        dev_set_drvdata(&dssdev->dev, td);
 
-       dssdev->get_timings = taal_get_timings;
-       dssdev->get_resolution = taal_get_resolution;
-
        /* if no platform set_backlight() defined, presume DSI backlight
         * control */
        if (!dssdev->set_backlight)
@@ -528,7 +527,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
                        &taal_bl_ops);
        if (IS_ERR(bldev)) {
                r = PTR_ERR(bldev);
-               goto err1;
+               goto err2;
        }
 
        td->bldev = bldev;
@@ -621,14 +620,12 @@ static void taal_remove(struct omap_dss_device *dssdev)
        kfree(td);
 }
 
-static int taal_enable(struct omap_dss_device *dssdev)
+static int taal_power_on(struct omap_dss_device *dssdev)
 {
        struct taal_data *td = dev_get_drvdata(&dssdev->dev);
        u8 id1, id2, id3;
        int r;
 
-       dev_dbg(&dssdev->dev, "enable\n");
-
        if (dssdev->platform_enable) {
                r = dssdev->platform_enable(dssdev);
                if (r)
@@ -638,6 +635,16 @@ static int taal_enable(struct omap_dss_device *dssdev)
        /* it seems we have to wait a bit until taal is ready */
        msleep(5);
 
+       dsi_bus_lock();
+
+       r = omapdss_dsi_display_enable(dssdev);
+       if (r) {
+               dev_err(&dssdev->dev, "failed to enable DSI\n");
+               goto err0;
+       }
+
+       omapdss_dsi_vc_enable_hs(TCH, false);
+
        r = taal_sleep_out(td);
        if (r)
                goto err;
@@ -661,6 +668,10 @@ static int taal_enable(struct omap_dss_device *dssdev)
 
        taal_dcs_write_0(DCS_DISPLAY_ON);
 
+       r = _taal_enable_te(dssdev, td->te_enabled);
+       if (r)
+               goto err;
+
 #ifdef TAAL_USE_ESD_CHECK
        queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD);
 #endif
@@ -676,19 +687,27 @@ static int taal_enable(struct omap_dss_device *dssdev)
                td->intro_printed = true;
        }
 
+       omapdss_dsi_vc_enable_hs(TCH, true);
+
+       dsi_bus_unlock();
+
        return 0;
 err:
+       dsi_bus_unlock();
+
+       omapdss_dsi_display_disable(dssdev);
+err0:
        if (dssdev->platform_disable)
                dssdev->platform_disable(dssdev);
 
        return r;
 }
 
-static void taal_disable(struct omap_dss_device *dssdev)
+static void taal_power_off(struct omap_dss_device *dssdev)
 {
        struct taal_data *td = dev_get_drvdata(&dssdev->dev);
 
-       dev_dbg(&dssdev->dev, "disable\n");
+       dsi_bus_lock();
 
        cancel_delayed_work(&td->esd_work);
 
@@ -698,41 +717,124 @@ static void taal_disable(struct omap_dss_device *dssdev)
        /* wait a bit so that the message goes through */
        msleep(10);
 
+       omapdss_dsi_display_disable(dssdev);
+
        if (dssdev->platform_disable)
                dssdev->platform_disable(dssdev);
 
        td->enabled = 0;
+
+       dsi_bus_unlock();
+}
+
+static int taal_enable(struct omap_dss_device *dssdev)
+{
+       int r;
+       dev_dbg(&dssdev->dev, "enable\n");
+
+       if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)
+               return -EINVAL;
+
+       r = taal_power_on(dssdev);
+       if (r)
+               return r;
+
+       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+       return r;
+}
+
+static void taal_disable(struct omap_dss_device *dssdev)
+{
+       dev_dbg(&dssdev->dev, "disable\n");
+
+       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+               taal_power_off(dssdev);
+
+       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 }
 
 static int taal_suspend(struct omap_dss_device *dssdev)
 {
-       struct taal_data *td = dev_get_drvdata(&dssdev->dev);
-       struct backlight_device *bldev = td->bldev;
+       dev_dbg(&dssdev->dev, "suspend\n");
 
-       bldev->props.power = FB_BLANK_POWERDOWN;
-       taal_bl_update_status(bldev);
+       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+               return -EINVAL;
+
+       taal_power_off(dssdev);
+       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
 
        return 0;
 }
 
 static int taal_resume(struct omap_dss_device *dssdev)
+{
+       int r;
+       dev_dbg(&dssdev->dev, "resume\n");
+
+       if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED)
+               return -EINVAL;
+
+       r = taal_power_on(dssdev);
+       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+       return r;
+}
+
+static void taal_framedone_cb(int err, void *data)
+{
+       struct omap_dss_device *dssdev = data;
+       dev_dbg(&dssdev->dev, "framedone, err %d\n", err);
+       dsi_bus_unlock();
+}
+
+static int taal_update(struct omap_dss_device *dssdev,
+                                   u16 x, u16 y, u16 w, u16 h)
 {
        struct taal_data *td = dev_get_drvdata(&dssdev->dev);
-       struct backlight_device *bldev = td->bldev;
+       int r;
 
-       bldev->props.power = FB_BLANK_UNBLANK;
-       taal_bl_update_status(bldev);
+       dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h);
+
+       dsi_bus_lock();
+
+       if (!td->enabled) {
+               r = 0;
+               goto err;
+       }
+
+       r = omap_dsi_prepare_update(dssdev, &x, &y, &w, &h);
+       if (r)
+               goto err;
+
+       r = taal_set_update_window(x, y, w, h);
+       if (r)
+               goto err;
+
+       r = omap_dsi_update(dssdev, TCH, x, y, w, h,
+                       taal_framedone_cb, dssdev);
+       if (r)
+               goto err;
 
+       /* note: no bus_unlock here. unlock is in framedone_cb */
        return 0;
+err:
+       dsi_bus_unlock();
+       return r;
 }
 
-static void taal_setup_update(struct omap_dss_device *dssdev,
-                                   u16 x, u16 y, u16 w, u16 h)
+static int taal_sync(struct omap_dss_device *dssdev)
 {
-       taal_set_update_window(x, y, w, h);
+       dev_dbg(&dssdev->dev, "sync\n");
+
+       dsi_bus_lock();
+       dsi_bus_unlock();
+
+       dev_dbg(&dssdev->dev, "sync done\n");
+
+       return 0;
 }
 
-static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
+static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
 {
        struct taal_data *td = dev_get_drvdata(&dssdev->dev);
        int r;
@@ -744,25 +846,32 @@ static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
        else
                r = taal_dcs_write_0(DCS_TEAR_OFF);
 
+       omapdss_dsi_enable_te(dssdev, enable);
+
+       /* XXX for some reason, DSI TE breaks if we don't wait here.
+        * Panel bug? Needs more studying */
+       msleep(100);
+
        return r;
 }
 
-static int taal_wait_te(struct omap_dss_device *dssdev)
+static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
 {
-       struct taal_data *td = dev_get_drvdata(&dssdev->dev);
-       long wait = msecs_to_jiffies(500);
+       int r;
 
-       if (!td->use_ext_te || !td->te_enabled)
-               return 0;
+       dsi_bus_lock();
 
-       INIT_COMPLETION(td->te_completion);
-       wait = wait_for_completion_timeout(&td->te_completion, wait);
-       if (wait == 0) {
-               dev_err(&dssdev->dev, "timeout waiting TE\n");
-               return -ETIME;
-       }
+       r = _taal_enable_te(dssdev, enable);
 
-       return 0;
+       dsi_bus_unlock();
+
+       return r;
+}
+
+static int taal_get_te(struct omap_dss_device *dssdev)
+{
+       struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+       return td->te_enabled;
 }
 
 static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
@@ -772,16 +881,21 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
 
        dev_dbg(&dssdev->dev, "rotate %d\n", rotate);
 
+       dsi_bus_lock();
+
        if (td->enabled) {
                r = taal_set_addr_mode(rotate, td->mirror);
-
                if (r)
-                       return r;
+                       goto err;
        }
 
        td->rotate = rotate;
 
+       dsi_bus_unlock();
        return 0;
+err:
+       dsi_bus_unlock();
+       return r;
 }
 
 static u8 taal_get_rotate(struct omap_dss_device *dssdev)
@@ -797,16 +911,20 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
 
        dev_dbg(&dssdev->dev, "mirror %d\n", enable);
 
+       dsi_bus_lock();
        if (td->enabled) {
                r = taal_set_addr_mode(td->rotate, enable);
-
                if (r)
-                       return r;
+                       goto err;
        }
 
        td->mirror = enable;
 
+       dsi_bus_unlock();
        return 0;
+err:
+       dsi_bus_unlock();
+       return r;
 }
 
 static bool taal_get_mirror(struct omap_dss_device *dssdev)
@@ -820,17 +938,23 @@ static int taal_run_test(struct omap_dss_device *dssdev, int test_num)
        u8 id1, id2, id3;
        int r;
 
+       dsi_bus_lock();
+
        r = taal_dcs_read_1(DCS_GET_ID1, &id1);
        if (r)
-               return r;
+               goto err;
        r = taal_dcs_read_1(DCS_GET_ID2, &id2);
        if (r)
-               return r;
+               goto err;
        r = taal_dcs_read_1(DCS_GET_ID3, &id3);
        if (r)
-               return r;
+               goto err;
 
+       dsi_bus_unlock();
        return 0;
+err:
+       dsi_bus_unlock();
+       return r;
 }
 
 static int taal_memory_read(struct omap_dss_device *dssdev,
@@ -841,6 +965,10 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
        int first = 1;
        int plen;
        unsigned buf_used = 0;
+       struct taal_data *td = dev_get_drvdata(&dssdev->dev);
+
+       if (!td->enabled)
+               return -ENODEV;
 
        if (size < w * h * 3)
                return -ENOMEM;
@@ -849,6 +977,8 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
                        dssdev->panel.timings.x_res *
                        dssdev->panel.timings.y_res * 3);
 
+       dsi_bus_lock();
+
        /* plen 1 or 2 goes into short packet. until checksum error is fixed,
         * use short packets. plen 32 works, but bigger packets seem to cause
         * an error. */
@@ -857,11 +987,11 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
        else
                plen = 2;
 
-       taal_setup_update(dssdev, x, y, w, h);
+       taal_set_update_window(x, y, w, h);
 
        r = dsi_vc_set_max_rx_packet_size(TCH, plen);
        if (r)
-               return r;
+               goto err0;
 
        while (buf_used < size) {
                u8 dcs_cmd = first ? 0x2e : 0x3e;
@@ -894,7 +1024,8 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
 
 err:
        dsi_vc_set_max_rx_packet_size(TCH, 1);
-
+err0:
+       dsi_bus_unlock();
        return r;
 }
 
@@ -939,8 +1070,11 @@ 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->use_ext_te && td->te_enabled)
-               taal_enable_te(dssdev, true);
+       if (td->use_ext_te && td->te_enabled) {
+               r = taal_dcs_write_1(DCS_TEAR_ON, 0);
+               if (r)
+                       goto err;
+       }
 
        dsi_bus_unlock();
 
@@ -958,6 +1092,20 @@ err:
        queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD);
 }
 
+static int taal_set_update_mode(struct omap_dss_device *dssdev,
+               enum omap_dss_update_mode mode)
+{
+       if (mode != OMAP_DSS_UPDATE_MANUAL)
+               return -EINVAL;
+       return 0;
+}
+
+static enum omap_dss_update_mode taal_get_update_mode(
+               struct omap_dss_device *dssdev)
+{
+       return OMAP_DSS_UPDATE_MANUAL;
+}
+
 static struct omap_dss_driver taal_driver = {
        .probe          = taal_probe,
        .remove         = taal_remove,
@@ -967,9 +1115,18 @@ static struct omap_dss_driver taal_driver = {
        .suspend        = taal_suspend,
        .resume         = taal_resume,
 
-       .setup_update   = taal_setup_update,
+       .set_update_mode = taal_set_update_mode,
+       .get_update_mode = taal_get_update_mode,
+
+       .update         = taal_update,
+       .sync           = taal_sync,
+
+       .get_resolution = taal_get_resolution,
+       .get_recommended_bpp = omapdss_default_get_recommended_bpp,
+
        .enable_te      = taal_enable_te,
-       .wait_for_te    = taal_wait_te,
+       .get_te         = taal_get_te,
+
        .set_rotate     = taal_rotate,
        .get_rotate     = taal_get_rotate,
        .set_mirror     = taal_mirror,
@@ -977,6 +1134,8 @@ static struct omap_dss_driver taal_driver = {
        .run_test       = taal_run_test,
        .memory_read    = taal_memory_read,
 
+       .get_timings    = taal_get_timings,
+
        .driver         = {
                .name   = "taal",
                .owner  = THIS_MODULE,
diff --git a/drivers/video/omap2/displays/panel-toppoly-tdo35s.c b/drivers/video/omap2/displays/panel-toppoly-tdo35s.c
new file mode 100644 (file)
index 0000000..fa434ca
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * LCD panel driver for Toppoly TDO35S
+ *
+ * Copyright (C) 2009 CompuLab, Ltd.
+ * Author: Mike Rapoport <mike@compulab.co.il>
+ *
+ * Based on generic panel support
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.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/delay.h>
+
+#include <plat/display.h>
+
+static struct omap_video_timings toppoly_tdo_panel_timings = {
+       /* 640 x 480 @ 60 Hz  Reduced blanking VESA CVT 0.31M3-R */
+       .x_res          = 480,
+       .y_res          = 640,
+
+       .pixel_clock    = 26000,
+
+       .hfp            = 104,
+       .hsw            = 8,
+       .hbp            = 8,
+
+       .vfp            = 4,
+       .vsw            = 2,
+       .vbp            = 2,
+};
+
+static int toppoly_tdo_panel_power_on(struct omap_dss_device *dssdev)
+{
+       int r;
+
+       r = omapdss_dpi_display_enable(dssdev);
+       if (r)
+               goto err0;
+
+       if (dssdev->platform_enable) {
+               r = dssdev->platform_enable(dssdev);
+               if (r)
+                       goto err1;
+       }
+
+       return 0;
+err1:
+       omapdss_dpi_display_disable(dssdev);
+err0:
+       return r;
+}
+
+static void toppoly_tdo_panel_power_off(struct omap_dss_device *dssdev)
+{
+       if (dssdev->platform_disable)
+               dssdev->platform_disable(dssdev);
+
+       omapdss_dpi_display_disable(dssdev);
+}
+
+static int toppoly_tdo_panel_probe(struct omap_dss_device *dssdev)
+{
+       dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+               OMAP_DSS_LCD_IHS;
+       dssdev->panel.timings = toppoly_tdo_panel_timings;
+
+       return 0;
+}
+
+static void toppoly_tdo_panel_remove(struct omap_dss_device *dssdev)
+{
+}
+
+static int toppoly_tdo_panel_enable(struct omap_dss_device *dssdev)
+{
+       int r = 0;
+
+       r = toppoly_tdo_panel_power_on(dssdev);
+       if (r)
+               return r;
+
+       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+       return 0;
+}
+
+static void toppoly_tdo_panel_disable(struct omap_dss_device *dssdev)
+{
+       toppoly_tdo_panel_power_off(dssdev);
+
+       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+}
+
+static int toppoly_tdo_panel_suspend(struct omap_dss_device *dssdev)
+{
+       toppoly_tdo_panel_power_off(dssdev);
+       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+       return 0;
+}
+
+static int toppoly_tdo_panel_resume(struct omap_dss_device *dssdev)
+{
+       int r = 0;
+
+       r = toppoly_tdo_panel_power_on(dssdev);
+       if (r)
+               return r;
+
+       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+       return 0;
+}
+
+static struct omap_dss_driver generic_driver = {
+       .probe          = toppoly_tdo_panel_probe,
+       .remove         = toppoly_tdo_panel_remove,
+
+       .enable         = toppoly_tdo_panel_enable,
+       .disable        = toppoly_tdo_panel_disable,
+       .suspend        = toppoly_tdo_panel_suspend,
+       .resume         = toppoly_tdo_panel_resume,
+
+       .driver         = {
+               .name   = "toppoly_tdo35s_panel",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init toppoly_tdo_panel_drv_init(void)
+{
+       return omap_dss_register_driver(&generic_driver);
+}
+
+static void __exit toppoly_tdo_panel_drv_exit(void)
+{
+       omap_dss_unregister_driver(&generic_driver);
+}
+
+module_init(toppoly_tdo_panel_drv_init);
+module_exit(toppoly_tdo_panel_drv_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
new file mode 100644 (file)
index 0000000..d578fee
--- /dev/null
@@ -0,0 +1,528 @@
+/*
+ * LCD panel driver for TPO TD043MTEA1
+ *
+ * Author: Gražvydas Ignotas <notasas@gmail.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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <linux/regulator/consumer.h>
+#include <linux/gpio.h>
+#include <linux/err.h>
+
+#include <plat/display.h>
+
+#define TPO_R02_MODE(x)                ((x) & 7)
+#define TPO_R02_MODE_800x480   7
+#define TPO_R02_NCLK_RISING    BIT(3)
+#define TPO_R02_HSYNC_HIGH     BIT(4)
+#define TPO_R02_VSYNC_HIGH     BIT(5)
+
+#define TPO_R03_NSTANDBY       BIT(0)
+#define TPO_R03_EN_CP_CLK      BIT(1)
+#define TPO_R03_EN_VGL_PUMP    BIT(2)
+#define TPO_R03_EN_PWM         BIT(3)
+#define TPO_R03_DRIVING_CAP_100        BIT(4)
+#define TPO_R03_EN_PRE_CHARGE  BIT(6)
+#define TPO_R03_SOFTWARE_CTL   BIT(7)
+
+#define TPO_R04_NFLIP_H                BIT(0)
+#define TPO_R04_NFLIP_V                BIT(1)
+#define TPO_R04_CP_CLK_FREQ_1H BIT(2)
+#define TPO_R04_VGL_FREQ_1H    BIT(4)
+
+#define TPO_R03_VAL_NORMAL (TPO_R03_NSTANDBY | TPO_R03_EN_CP_CLK | \
+                       TPO_R03_EN_VGL_PUMP |  TPO_R03_EN_PWM | \
+                       TPO_R03_DRIVING_CAP_100 | TPO_R03_EN_PRE_CHARGE | \
+                       TPO_R03_SOFTWARE_CTL)
+
+#define TPO_R03_VAL_STANDBY (TPO_R03_DRIVING_CAP_100 | \
+                       TPO_R03_EN_PRE_CHARGE | TPO_R03_SOFTWARE_CTL)
+
+static const u16 tpo_td043_def_gamma[12] = {
+       106, 200, 289, 375, 460, 543, 625, 705, 785, 864, 942, 1020
+};
+
+struct tpo_td043_device {
+       struct spi_device *spi;
+       struct regulator *vcc_reg;
+       u16 gamma[12];
+       u32 mode;
+       u32 hmirror:1;
+       u32 vmirror:1;
+};
+
+static int tpo_td043_write(struct spi_device *spi, u8 addr, u8 data)
+{
+       struct spi_message      m;
+       struct spi_transfer     xfer;
+       u16                     w;
+       int                     r;
+
+       spi_message_init(&m);
+
+       memset(&xfer, 0, sizeof(xfer));
+
+       w = ((u16)addr << 10) | (1 << 8) | data;
+       xfer.tx_buf = &w;
+       xfer.bits_per_word = 16;
+       xfer.len = 2;
+       spi_message_add_tail(&xfer, &m);
+
+       r = spi_sync(spi, &m);
+       if (r < 0)
+               dev_warn(&spi->dev, "failed to write to LCD reg (%d)\n", r);
+       return r;
+}
+
+static void tpo_td043_write_gamma(struct spi_device *spi, u16 gamma[12])
+{
+       u8 i, val;
+
+       /* gamma bits [9:8] */
+       for (val = i = 0; i < 4; i++)
+               val |= (gamma[i] & 0x300) >> ((i + 1) * 2);
+       tpo_td043_write(spi, 0x11, val);
+
+       for (val = i = 0; i < 4; i++)
+               val |= (gamma[i+4] & 0x300) >> ((i + 1) * 2);
+       tpo_td043_write(spi, 0x12, val);
+
+       for (val = i = 0; i < 4; i++)
+               val |= (gamma[i+8] & 0x300) >> ((i + 1) * 2);
+       tpo_td043_write(spi, 0x13, val);
+
+       /* gamma bits [7:0] */
+       for (val = i = 0; i < 12; i++)
+               tpo_td043_write(spi, 0x14 + i, gamma[i] & 0xff);
+}
+
+static int tpo_td043_write_mirror(struct spi_device *spi, bool h, bool v)
+{
+       u8 reg4 = TPO_R04_NFLIP_H | TPO_R04_NFLIP_V | \
+               TPO_R04_CP_CLK_FREQ_1H | TPO_R04_VGL_FREQ_1H;
+       if (h)
+               reg4 &= ~TPO_R04_NFLIP_H;
+       if (v)
+               reg4 &= ~TPO_R04_NFLIP_V;
+
+       return tpo_td043_write(spi, 4, reg4);
+}
+
+static int tpo_td043_set_hmirror(struct omap_dss_device *dssdev, bool enable)
+{
+       struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
+
+       tpo_td043->hmirror = enable;
+       return tpo_td043_write_mirror(tpo_td043->spi, tpo_td043->hmirror,
+                       tpo_td043->vmirror);
+}
+
+static bool tpo_td043_get_hmirror(struct omap_dss_device *dssdev)
+{
+       struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
+
+       return tpo_td043->hmirror;
+}
+
+static ssize_t tpo_td043_vmirror_show(struct device *dev,
+       struct device_attribute *attr, char *buf)
+{
+       struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", tpo_td043->vmirror);
+}
+
+static ssize_t tpo_td043_vmirror_store(struct device *dev,
+       struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
+       long val;
+       int ret;
+
+       ret = strict_strtol(buf, 0, &val);
+       if (ret < 0)
+               return ret;
+
+       ret = tpo_td043_write_mirror(tpo_td043->spi, tpo_td043->hmirror, val);
+       if (ret < 0)
+               return ret;
+
+       tpo_td043->vmirror = val;
+
+       return count;
+}
+
+static ssize_t tpo_td043_mode_show(struct device *dev,
+       struct device_attribute *attr, char *buf)
+{
+       struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", tpo_td043->mode);
+}
+
+static ssize_t tpo_td043_mode_store(struct device *dev,
+       struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
+       long val;
+       int ret;
+
+       ret = strict_strtol(buf, 0, &val);
+       if (ret != 0 || val & ~7)
+               return -EINVAL;
+
+       tpo_td043->mode = val;
+
+       val |= TPO_R02_NCLK_RISING;
+       tpo_td043_write(tpo_td043->spi, 2, val);
+
+       return count;
+}
+
+static ssize_t tpo_td043_gamma_show(struct device *dev,
+       struct device_attribute *attr, char *buf)
+{
+       struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
+       ssize_t len = 0;
+       int ret;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(tpo_td043->gamma); i++) {
+               ret = snprintf(buf + len, PAGE_SIZE - len, "%u ",
+                               tpo_td043->gamma[i]);
+               if (ret < 0)
+                       return ret;
+               len += ret;
+       }
+       buf[len - 1] = '\n';
+
+       return len;
+}
+
+static ssize_t tpo_td043_gamma_store(struct device *dev,
+       struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
+       unsigned int g[12];
+       int ret;
+       int i;
+
+       ret = sscanf(buf, "%u %u %u %u %u %u %u %u %u %u %u %u",
+                       &g[0], &g[1], &g[2], &g[3], &g[4], &g[5],
+                       &g[6], &g[7], &g[8], &g[9], &g[10], &g[11]);
+
+       if (ret != 12)
+               return -EINVAL;
+
+       for (i = 0; i < 12; i++)
+               tpo_td043->gamma[i] = g[i];
+
+       tpo_td043_write_gamma(tpo_td043->spi, tpo_td043->gamma);
+
+       return count;
+}
+
+static DEVICE_ATTR(vmirror, S_IRUGO | S_IWUSR,
+               tpo_td043_vmirror_show, tpo_td043_vmirror_store);
+static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
+               tpo_td043_mode_show, tpo_td043_mode_store);
+static DEVICE_ATTR(gamma, S_IRUGO | S_IWUSR,
+               tpo_td043_gamma_show, tpo_td043_gamma_store);
+
+static struct attribute *tpo_td043_attrs[] = {
+       &dev_attr_vmirror.attr,
+       &dev_attr_mode.attr,
+       &dev_attr_gamma.attr,
+       NULL,
+};
+
+static struct attribute_group tpo_td043_attr_group = {
+       .attrs = tpo_td043_attrs,
+};
+
+static const struct omap_video_timings tpo_td043_timings = {
+       .x_res          = 800,
+       .y_res          = 480,
+
+       .pixel_clock    = 36000,
+
+       .hsw            = 1,
+       .hfp            = 68,
+       .hbp            = 214,
+
+       .vsw            = 1,
+       .vfp            = 39,
+       .vbp            = 34,
+};
+
+static int tpo_td043_power_on(struct omap_dss_device *dssdev)
+{
+       struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
+       int nreset_gpio = dssdev->reset_gpio;
+       int r;
+
+       r = omapdss_dpi_display_enable(dssdev);
+       if (r)
+               goto err0;
+
+       if (dssdev->platform_enable) {
+               r = dssdev->platform_enable(dssdev);
+               if (r)
+                       goto err1;
+       }
+
+       regulator_enable(tpo_td043->vcc_reg);
+
+       /* wait for power up */
+       msleep(160);
+
+       if (gpio_is_valid(nreset_gpio))
+               gpio_set_value(nreset_gpio, 1);
+
+       tpo_td043_write(tpo_td043->spi, 2,
+                       TPO_R02_MODE(tpo_td043->mode) | TPO_R02_NCLK_RISING);
+       tpo_td043_write(tpo_td043->spi, 3, TPO_R03_VAL_NORMAL);
+       tpo_td043_write(tpo_td043->spi, 0x20, 0xf0);
+       tpo_td043_write(tpo_td043->spi, 0x21, 0xf0);
+       tpo_td043_write_mirror(tpo_td043->spi, tpo_td043->hmirror,
+                       tpo_td043->vmirror);
+       tpo_td043_write_gamma(tpo_td043->spi, tpo_td043->gamma);
+
+       return 0;
+err1:
+       omapdss_dpi_display_disable(dssdev);
+err0:
+       return r;
+}
+
+static void tpo_td043_power_off(struct omap_dss_device *dssdev)
+{
+       struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
+       int nreset_gpio = dssdev->reset_gpio;
+
+       tpo_td043_write(tpo_td043->spi, 3,
+                       TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM);
+
+       if (gpio_is_valid(nreset_gpio))
+               gpio_set_value(nreset_gpio, 0);
+
+       /* wait for at least 2 vsyncs before cutting off power */
+       msleep(50);
+
+       tpo_td043_write(tpo_td043->spi, 3, TPO_R03_VAL_STANDBY);
+
+       regulator_disable(tpo_td043->vcc_reg);
+
+       if (dssdev->platform_disable)
+               dssdev->platform_disable(dssdev);
+
+       omapdss_dpi_display_disable(dssdev);
+}
+
+static int tpo_td043_enable(struct omap_dss_device *dssdev)
+{
+       int ret;
+
+       dev_dbg(&dssdev->dev, "enable\n");
+
+       ret = tpo_td043_power_on(dssdev);
+       if (ret)
+               return ret;
+
+       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+       return 0;
+}
+
+static void tpo_td043_disable(struct omap_dss_device *dssdev)
+{
+       dev_dbg(&dssdev->dev, "disable\n");
+
+       tpo_td043_power_off(dssdev);
+
+       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+}
+
+static int tpo_td043_suspend(struct omap_dss_device *dssdev)
+{
+       tpo_td043_power_off(dssdev);
+       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+       return 0;
+}
+
+static int tpo_td043_resume(struct omap_dss_device *dssdev)
+{
+       int r = 0;
+
+       r = tpo_td043_power_on(dssdev);
+       if (r)
+               return r;
+
+       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+       return 0;
+}
+
+static int tpo_td043_probe(struct omap_dss_device *dssdev)
+{
+       struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
+       int nreset_gpio = dssdev->reset_gpio;
+       int ret = 0;
+
+       dev_dbg(&dssdev->dev, "probe\n");
+
+       if (tpo_td043 == NULL) {
+               dev_err(&dssdev->dev, "missing tpo_td043_device\n");
+               return -ENODEV;
+       }
+
+       dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IHS |
+                               OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IPC;
+       dssdev->panel.timings = tpo_td043_timings;
+       dssdev->ctrl.pixel_size = 24;
+
+       tpo_td043->mode = TPO_R02_MODE_800x480;
+       memcpy(tpo_td043->gamma, tpo_td043_def_gamma, sizeof(tpo_td043->gamma));
+
+       tpo_td043->vcc_reg = regulator_get(&dssdev->dev, "vcc");
+       if (IS_ERR(tpo_td043->vcc_reg)) {
+               dev_err(&dssdev->dev, "failed to get LCD VCC regulator\n");
+               ret = PTR_ERR(tpo_td043->vcc_reg);
+               goto fail_regulator;
+       }
+
+       if (gpio_is_valid(nreset_gpio)) {
+               ret = gpio_request(nreset_gpio, "lcd reset");
+               if (ret < 0) {
+                       dev_err(&dssdev->dev, "couldn't request reset GPIO\n");
+                       goto fail_gpio_req;
+               }
+
+               ret = gpio_direction_output(nreset_gpio, 0);
+               if (ret < 0) {
+                       dev_err(&dssdev->dev, "couldn't set GPIO direction\n");
+                       goto fail_gpio_direction;
+               }
+       }
+
+       ret = sysfs_create_group(&dssdev->dev.kobj, &tpo_td043_attr_group);
+       if (ret)
+               dev_warn(&dssdev->dev, "failed to create sysfs files\n");
+
+       return 0;
+
+fail_gpio_direction:
+       gpio_free(nreset_gpio);
+fail_gpio_req:
+       regulator_put(tpo_td043->vcc_reg);
+fail_regulator:
+       kfree(tpo_td043);
+       return ret;
+}
+
+static void tpo_td043_remove(struct omap_dss_device *dssdev)
+{
+       struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
+       int nreset_gpio = dssdev->reset_gpio;
+
+       dev_dbg(&dssdev->dev, "remove\n");
+
+       sysfs_remove_group(&dssdev->dev.kobj, &tpo_td043_attr_group);
+       regulator_put(tpo_td043->vcc_reg);
+       if (gpio_is_valid(nreset_gpio))
+               gpio_free(nreset_gpio);
+}
+
+static struct omap_dss_driver tpo_td043_driver = {
+       .probe          = tpo_td043_probe,
+       .remove         = tpo_td043_remove,
+
+       .enable         = tpo_td043_enable,
+       .disable        = tpo_td043_disable,
+       .suspend        = tpo_td043_suspend,
+       .resume         = tpo_td043_resume,
+       .set_mirror     = tpo_td043_set_hmirror,
+       .get_mirror     = tpo_td043_get_hmirror,
+
+       .driver         = {
+               .name   = "tpo_td043mtea1_panel",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int tpo_td043_spi_probe(struct spi_device *spi)
+{
+       struct omap_dss_device *dssdev = spi->dev.platform_data;
+       struct tpo_td043_device *tpo_td043;
+       int ret;
+
+       if (dssdev == NULL) {
+               dev_err(&spi->dev, "missing dssdev\n");
+               return -ENODEV;
+       }
+
+       spi->bits_per_word = 16;
+       spi->mode = SPI_MODE_0;
+
+       ret = spi_setup(spi);
+       if (ret < 0) {
+               dev_err(&spi->dev, "spi_setup failed: %d\n", ret);
+               return ret;
+       }
+
+       tpo_td043 = kzalloc(sizeof(*tpo_td043), GFP_KERNEL);
+       if (tpo_td043 == NULL)
+               return -ENOMEM;
+
+       tpo_td043->spi = spi;
+       dev_set_drvdata(&spi->dev, tpo_td043);
+       dev_set_drvdata(&dssdev->dev, tpo_td043);
+
+       omap_dss_register_driver(&tpo_td043_driver);
+
+       return 0;
+}
+
+static int __devexit tpo_td043_spi_remove(struct spi_device *spi)
+{
+       struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&spi->dev);
+
+       omap_dss_unregister_driver(&tpo_td043_driver);
+       kfree(tpo_td043);
+
+       return 0;
+}
+
+static struct spi_driver tpo_td043_spi_driver = {
+       .driver = {
+               .name   = "tpo_td043mtea1_panel_spi",
+               .bus    = &spi_bus_type,
+               .owner  = THIS_MODULE,
+       },
+       .probe  = tpo_td043_spi_probe,
+       .remove = __devexit_p(tpo_td043_spi_remove),
+};
+
+static int __init tpo_td043_init(void)
+{
+       return spi_register_driver(&tpo_td043_spi_driver);
+}
+
+static void __exit tpo_td043_exit(void)
+{
+       spi_unregister_driver(&tpo_td043_spi_driver);
+}
+
+module_init(tpo_td043_init);
+module_exit(tpo_td043_exit);
+
+MODULE_AUTHOR("Gražvydas Ignotas <notasas@gmail.com>");
+MODULE_DESCRIPTION("TPO TD043MTEA1 LCD Driver");
+MODULE_LICENSE("GPL");
index c63ce76..87afb81 100644 (file)
@@ -30,19 +30,29 @@ config OMAP2_DSS_COLLECT_IRQ_STATS
        depends on OMAP2_DSS_DEBUG_SUPPORT
        default n
        help
-         Collect DSS IRQ statistics, printable via debugfs
+         Collect DSS IRQ statistics, printable via debugfs.
+
+         The statistics can be found from
+         <debugfs>/omapdss/dispc_irq for DISPC interrupts, and
+         <debugfs>/omapdss/dsi_irq for DSI interrupts.
 
 config OMAP2_DSS_RFBI
        bool "RFBI support"
         default n
        help
-         MIPI DBI, or RFBI (Remote Framebuffer Interface), support.
+         MIPI DBI support (RFBI, Remote Framebuffer Interface, in Texas
+         Instrument's terminology).
+
+         DBI is a bus between the host processor and a peripheral,
+         such as a display or a framebuffer chip.
+
+         See http://www.mipi.org/ for DBI spesifications.
 
 config OMAP2_DSS_VENC
        bool "VENC support"
         default y
        help
-         OMAP Video Encoder support.
+         OMAP Video Encoder support for S-Video and composite TV-out.
 
 config OMAP2_DSS_SDI
        bool "SDI support"
@@ -51,12 +61,20 @@ config OMAP2_DSS_SDI
        help
          SDI (Serial Display Interface) support.
 
+         SDI is a high speed one-way display serial bus between the host
+         processor and a display.
+
 config OMAP2_DSS_DSI
        bool "DSI support"
        depends on ARCH_OMAP3
         default n
        help
-         MIPI DSI support.
+         MIPI DSI (Display Serial Interface) support.
+
+         DSI is a high speed half-duplex serial interface between the host
+         processor and a peripheral, such as a display or a framebuffer chip.
+
+         See http://www.mipi.org/ for DSI spesifications.
 
 config OMAP2_DSS_USE_DSI_PLL
        bool "Use DSI PLL for PCLK (EXPERIMENTAL)"
index 82918ee..7ebe50b 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/debugfs.h>
 #include <linux/io.h>
 #include <linux/device.h>
+#include <linux/regulator/consumer.h>
 
 #include <plat/display.h>
 #include <plat/clock.h>
@@ -47,6 +48,10 @@ static struct {
        struct clk      *dss_54m_fck;
        struct clk      *dss_96m_fck;
        unsigned        num_clks_enabled;
+
+       struct regulator *vdds_dsi_reg;
+       struct regulator *vdds_sdi_reg;
+       struct regulator *vdda_dac_reg;
 } core;
 
 static void dss_clk_enable_all_no_ctx(void);
@@ -284,9 +289,11 @@ static void dss_clk_enable_no_ctx(enum dss_clock clks)
 
 void dss_clk_enable(enum dss_clock clks)
 {
+       bool check_ctx = core.num_clks_enabled == 0;
+
        dss_clk_enable_no_ctx(clks);
 
-       if (cpu_is_omap34xx() && dss_need_ctx_restore())
+       if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore())
                restore_all_ctx();
 }
 
@@ -352,6 +359,50 @@ static void dss_clk_disable_all(void)
        dss_clk_disable(clks);
 }
 
+/* REGULATORS */
+
+struct regulator *dss_get_vdds_dsi(void)
+{
+       struct regulator *reg;
+
+       if (core.vdds_dsi_reg != NULL)
+               return core.vdds_dsi_reg;
+
+       reg = regulator_get(&core.pdev->dev, "vdds_dsi");
+       if (!IS_ERR(reg))
+               core.vdds_dsi_reg = reg;
+
+       return reg;
+}
+
+struct regulator *dss_get_vdds_sdi(void)
+{
+       struct regulator *reg;
+
+       if (core.vdds_sdi_reg != NULL)
+               return core.vdds_sdi_reg;
+
+       reg = regulator_get(&core.pdev->dev, "vdds_sdi");
+       if (!IS_ERR(reg))
+               core.vdds_sdi_reg = reg;
+
+       return reg;
+}
+
+struct regulator *dss_get_vdda_dac(void)
+{
+       struct regulator *reg;
+
+       if (core.vdda_dac_reg != NULL)
+               return core.vdda_dac_reg;
+
+       reg = regulator_get(&core.pdev->dev, "vdda_dac");
+       if (!IS_ERR(reg))
+               core.vdda_dac_reg = reg;
+
+       return reg;
+}
+
 /* DEBUGFS */
 #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
 static void dss_debug_dump_clocks(struct seq_file *s)
@@ -397,10 +448,12 @@ static int dss_initialize_debugfs(void)
        debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir,
                        &dss_debug_dump_clocks, &dss_debug_fops);
 
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
        debugfs_create_file("dispc_irq", S_IRUGO, dss_debugfs_dir,
                        &dispc_dump_irqs, &dss_debug_fops);
+#endif
 
-#ifdef CONFIG_OMAP2_DSS_DSI
+#if defined(CONFIG_OMAP2_DSS_DSI) && defined(CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS)
        debugfs_create_file("dsi_irq", S_IRUGO, dss_debugfs_dir,
                        &dsi_dump_irqs, &dss_debug_fops);
 #endif
@@ -473,7 +526,7 @@ static int omap_dss_probe(struct platform_device *pdev)
        }
 #endif
 
-       r = dpi_init();
+       r = dpi_init(pdev);
        if (r) {
                DSSERR("Failed to initialize dpi\n");
                goto fail0;
@@ -718,16 +771,14 @@ static int dss_driver_probe(struct device *dev)
 
        dss_init_device(core.pdev, dssdev);
 
-       /* skip this if the device is behind a ctrl */
-       if (!dssdev->panel.ctrl) {
-               force = pdata->default_device == dssdev;
-               dss_recheck_connections(dssdev, force);
-       }
+       force = pdata->default_device == dssdev;
+       dss_recheck_connections(dssdev, force);
 
        r = dssdrv->probe(dssdev);
 
        if (r) {
                DSSERR("driver probe failed: %d\n", r);
+               dss_uninit_device(core.pdev, dssdev);
                return r;
        }
 
@@ -760,6 +811,13 @@ int omap_dss_register_driver(struct omap_dss_driver *dssdriver)
        dssdriver->driver.bus = &dss_bus_type;
        dssdriver->driver.probe = dss_driver_probe;
        dssdriver->driver.remove = dss_driver_remove;
+
+       if (dssdriver->get_resolution == NULL)
+               dssdriver->get_resolution = omapdss_default_get_resolution;
+       if (dssdriver->get_recommended_bpp == NULL)
+               dssdriver->get_recommended_bpp =
+                       omapdss_default_get_recommended_bpp;
+
        return driver_register(&dssdriver->driver);
 }
 EXPORT_SYMBOL(omap_dss_register_driver);
@@ -808,8 +866,6 @@ static void omap_dss_dev_release(struct device *dev)
 int omap_dss_register_device(struct omap_dss_device *dssdev)
 {
        static int dev_num;
-       static int panel_num;
-       int r;
 
        WARN_ON(!dssdev->driver_name);
 
@@ -818,36 +874,12 @@ int omap_dss_register_device(struct omap_dss_device *dssdev)
        dssdev->dev.parent = &dss_bus;
        dssdev->dev.release = omap_dss_dev_release;
        dev_set_name(&dssdev->dev, "display%d", dev_num++);
-       r = device_register(&dssdev->dev);
-       if (r)
-               return r;
-
-       if (dssdev->ctrl.panel) {
-               struct omap_dss_device *panel = dssdev->ctrl.panel;
-
-               panel->panel.ctrl = dssdev;
-
-               reset_device(&panel->dev, 1);
-               panel->dev.bus = &dss_bus_type;
-               panel->dev.parent = &dssdev->dev;
-               panel->dev.release = omap_dss_dev_release;
-               dev_set_name(&panel->dev, "panel%d", panel_num++);
-               r = device_register(&panel->dev);
-               if (r)
-                       return r;
-       }
-
-       return 0;
+       return device_register(&dssdev->dev);
 }
 
 void omap_dss_unregister_device(struct omap_dss_device *dssdev)
 {
        device_unregister(&dssdev->dev);
-
-       if (dssdev->ctrl.panel) {
-               struct omap_dss_device *panel = dssdev->ctrl.panel;
-               device_unregister(&panel->dev);
-       }
 }
 
 /* BUS */
@@ -901,6 +933,21 @@ static int __init omap_dss_init(void)
 
 static void __exit omap_dss_exit(void)
 {
+       if (core.vdds_dsi_reg != NULL) {
+               regulator_put(core.vdds_dsi_reg);
+               core.vdds_dsi_reg = NULL;
+       }
+
+       if (core.vdds_sdi_reg != NULL) {
+               regulator_put(core.vdds_sdi_reg);
+               core.vdds_sdi_reg = NULL;
+       }
+
+       if (core.vdda_dac_reg != NULL) {
+               regulator_put(core.vdda_dac_reg);
+               core.vdda_dac_reg = NULL;
+       }
+
        platform_driver_unregister(&omap_dss_driver);
 
        omap_dss_bus_unregister();
index de8bfba..e777e35 100644 (file)
@@ -1725,7 +1725,7 @@ static void _enable_lcd_out(bool enable)
        REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0);
 }
 
-void dispc_enable_lcd_out(bool enable)
+static void dispc_enable_lcd_out(bool enable)
 {
        struct completion frame_done_completion;
        bool is_on;
@@ -1772,7 +1772,7 @@ static void _enable_digit_out(bool enable)
        REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
 }
 
-void dispc_enable_digit_out(bool enable)
+static void dispc_enable_digit_out(bool enable)
 {
        struct completion frame_done_completion;
        int r;
@@ -1836,6 +1836,26 @@ void dispc_enable_digit_out(bool enable)
        enable_clocks(0);
 }
 
+bool dispc_is_channel_enabled(enum omap_channel channel)
+{
+       if (channel == OMAP_DSS_CHANNEL_LCD)
+               return !!REG_GET(DISPC_CONTROL, 0, 0);
+       else if (channel == OMAP_DSS_CHANNEL_DIGIT)
+               return !!REG_GET(DISPC_CONTROL, 1, 1);
+       else
+               BUG();
+}
+
+void dispc_enable_channel(enum omap_channel channel, bool enable)
+{
+       if (channel == OMAP_DSS_CHANNEL_LCD)
+               dispc_enable_lcd_out(enable);
+       else if (channel == OMAP_DSS_CHANNEL_DIGIT)
+               dispc_enable_digit_out(enable);
+       else
+               BUG();
+}
+
 void dispc_lcd_enable_signal_polarity(bool act_high)
 {
        enable_clocks(1);
@@ -2198,7 +2218,7 @@ unsigned long dispc_fclk_rate(void)
 {
        unsigned long r = 0;
 
-       if (dss_get_dispc_clk_source() == 0)
+       if (dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK)
                r = dss_clk_get_rate(DSS_CLK_FCK1);
        else
 #ifdef CONFIG_OMAP2_DSS_DSI
@@ -2251,7 +2271,7 @@ void dispc_dump_clocks(struct seq_file *s)
        seq_printf(s, "- DISPC -\n");
 
        seq_printf(s, "dispc fclk source = %s\n",
-                       dss_get_dispc_clk_source() == 0 ?
+                       dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ?
                        "dss1_alwon_fclk" : "dsi1_pll_fclk");
 
        seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate());
@@ -2301,8 +2321,6 @@ void dispc_dump_irqs(struct seq_file *s)
        PIS(WAKEUP);
 #undef PIS
 }
-#else
-void dispc_dump_irqs(struct seq_file *s) { }
 #endif
 
 void dispc_dump_regs(struct seq_file *s)
@@ -2854,12 +2872,13 @@ static void dispc_error_worker(struct work_struct *work)
                                manager = mgr;
                                enable = mgr->device->state ==
                                                OMAP_DSS_DISPLAY_ACTIVE;
-                               mgr->device->disable(mgr->device);
+                               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);
@@ -2874,7 +2893,7 @@ static void dispc_error_worker(struct work_struct *work)
                        dispc_go(manager->id);
                        mdelay(50);
                        if (enable)
-                               manager->device->enable(manager->device);
+                               dssdev->driver->enable(dssdev);
                }
        }
 
@@ -2892,12 +2911,13 @@ static void dispc_error_worker(struct work_struct *work)
                                manager = mgr;
                                enable = mgr->device->state ==
                                                OMAP_DSS_DISPLAY_ACTIVE;
-                               mgr->device->disable(mgr->device);
+                               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);
@@ -2912,7 +2932,7 @@ static void dispc_error_worker(struct work_struct *work)
                        dispc_go(manager->id);
                        mdelay(50);
                        if (enable)
-                               manager->device->enable(manager->device);
+                               dssdev->driver->enable(dssdev);
                }
        }
 
@@ -2923,7 +2943,7 @@ static void dispc_error_worker(struct work_struct *work)
                        mgr = omap_dss_get_overlay_manager(i);
 
                        if (mgr->caps & OMAP_DSS_OVL_CAP_DISPC)
-                               mgr->device->disable(mgr->device);
+                               mgr->device->driver->disable(mgr->device);
                }
        }
 
index 3b92b84..6a74ea1 100644 (file)
@@ -53,11 +53,11 @@ static ssize_t display_enabled_store(struct device *dev,
 
        if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
                if (enabled) {
-                       r = dssdev->enable(dssdev);
+                       r = dssdev->driver->enable(dssdev);
                        if (r)
                                return r;
                } else {
-                       dssdev->disable(dssdev);
+                       dssdev->driver->disable(dssdev);
                }
        }
 
@@ -69,8 +69,8 @@ static ssize_t display_upd_mode_show(struct device *dev,
 {
        struct omap_dss_device *dssdev = to_dss_device(dev);
        enum omap_dss_update_mode mode = OMAP_DSS_UPDATE_AUTO;
-       if (dssdev->get_update_mode)
-               mode = dssdev->get_update_mode(dssdev);
+       if (dssdev->driver->get_update_mode)
+               mode = dssdev->driver->get_update_mode(dssdev);
        return snprintf(buf, PAGE_SIZE, "%d\n", mode);
 }
 
@@ -94,7 +94,7 @@ static ssize_t display_upd_mode_store(struct device *dev,
                return -EINVAL;
        }
 
-       r = dssdev->set_update_mode(dssdev, mode);
+       r = dssdev->driver->set_update_mode(dssdev, mode);
        if (r)
                return r;
 
@@ -106,7 +106,8 @@ static ssize_t display_tear_show(struct device *dev,
 {
        struct omap_dss_device *dssdev = to_dss_device(dev);
        return snprintf(buf, PAGE_SIZE, "%d\n",
-                       dssdev->get_te ? dssdev->get_te(dssdev) : 0);
+                       dssdev->driver->get_te ?
+                       dssdev->driver->get_te(dssdev) : 0);
 }
 
 static ssize_t display_tear_store(struct device *dev,
@@ -116,12 +117,12 @@ static ssize_t display_tear_store(struct device *dev,
        unsigned long te;
        int r;
 
-       if (!dssdev->enable_te || !dssdev->get_te)
+       if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
                return -ENOENT;
 
        te = simple_strtoul(buf, NULL, 0);
 
-       r = dssdev->enable_te(dssdev, te);
+       r = dssdev->driver->enable_te(dssdev, te);
        if (r)
                return r;
 
@@ -134,10 +135,10 @@ static ssize_t display_timings_show(struct device *dev,
        struct omap_dss_device *dssdev = to_dss_device(dev);
        struct omap_video_timings t;
 
-       if (!dssdev->get_timings)
+       if (!dssdev->driver->get_timings)
                return -ENOENT;
 
-       dssdev->get_timings(dssdev, &t);
+       dssdev->driver->get_timings(dssdev, &t);
 
        return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
                        t.pixel_clock,
@@ -152,7 +153,7 @@ static ssize_t display_timings_store(struct device *dev,
        struct omap_video_timings t;
        int r, found;
 
-       if (!dssdev->set_timings || !dssdev->check_timings)
+       if (!dssdev->driver->set_timings || !dssdev->driver->check_timings)
                return -ENOENT;
 
        found = 0;
@@ -171,11 +172,11 @@ static ssize_t display_timings_store(struct device *dev,
                                &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
                return -EINVAL;
 
-       r = dssdev->check_timings(dssdev, &t);
+       r = dssdev->driver->check_timings(dssdev, &t);
        if (r)
                return r;
 
-       dssdev->set_timings(dssdev, &t);
+       dssdev->driver->set_timings(dssdev, &t);
 
        return size;
 }
@@ -185,9 +186,9 @@ static ssize_t display_rotate_show(struct device *dev,
 {
        struct omap_dss_device *dssdev = to_dss_device(dev);
        int rotate;
-       if (!dssdev->get_rotate)
+       if (!dssdev->driver->get_rotate)
                return -ENOENT;
-       rotate = dssdev->get_rotate(dssdev);
+       rotate = dssdev->driver->get_rotate(dssdev);
        return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
 }
 
@@ -198,12 +199,12 @@ static ssize_t display_rotate_store(struct device *dev,
        unsigned long rot;
        int r;
 
-       if (!dssdev->set_rotate || !dssdev->get_rotate)
+       if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
                return -ENOENT;
 
        rot = simple_strtoul(buf, NULL, 0);
 
-       r = dssdev->set_rotate(dssdev, rot);
+       r = dssdev->driver->set_rotate(dssdev, rot);
        if (r)
                return r;
 
@@ -215,9 +216,9 @@ static ssize_t display_mirror_show(struct device *dev,
 {
        struct omap_dss_device *dssdev = to_dss_device(dev);
        int mirror;
-       if (!dssdev->get_mirror)
+       if (!dssdev->driver->get_mirror)
                return -ENOENT;
-       mirror = dssdev->get_mirror(dssdev);
+       mirror = dssdev->driver->get_mirror(dssdev);
        return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
 }
 
@@ -228,12 +229,12 @@ static ssize_t display_mirror_store(struct device *dev,
        unsigned long mirror;
        int r;
 
-       if (!dssdev->set_mirror || !dssdev->get_mirror)
+       if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
                return -ENOENT;
 
        mirror = simple_strtoul(buf, NULL, 0);
 
-       r = dssdev->set_mirror(dssdev, mirror);
+       r = dssdev->driver->set_mirror(dssdev, mirror);
        if (r)
                return r;
 
@@ -246,10 +247,10 @@ static ssize_t display_wss_show(struct device *dev,
        struct omap_dss_device *dssdev = to_dss_device(dev);
        unsigned int wss;
 
-       if (!dssdev->get_wss)
+       if (!dssdev->driver->get_wss)
                return -ENOENT;
 
-       wss = dssdev->get_wss(dssdev);
+       wss = dssdev->driver->get_wss(dssdev);
 
        return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
 }
@@ -261,7 +262,7 @@ static ssize_t display_wss_store(struct device *dev,
        unsigned long wss;
        int r;
 
-       if (!dssdev->get_wss || !dssdev->set_wss)
+       if (!dssdev->driver->get_wss || !dssdev->driver->set_wss)
                return -ENOENT;
 
        if (strict_strtoul(buf, 0, &wss))
@@ -270,7 +271,7 @@ static ssize_t display_wss_store(struct device *dev,
        if (wss > 0xfffff)
                return -EINVAL;
 
-       r = dssdev->set_wss(dssdev, wss);
+       r = dssdev->driver->set_wss(dssdev, wss);
        if (r)
                return r;
 
@@ -303,12 +304,13 @@ static struct device_attribute *display_sysfs_attrs[] = {
        NULL
 };
 
-static void default_get_resolution(struct omap_dss_device *dssdev,
+void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
                        u16 *xres, u16 *yres)
 {
        *xres = dssdev->panel.timings.x_res;
        *yres = dssdev->panel.timings.y_res;
 }
+EXPORT_SYMBOL(omapdss_default_get_resolution);
 
 void default_get_overlay_fifo_thresholds(enum omap_plane plane,
                u32 fifo_size, enum omap_burst_size *burst_size,
@@ -323,24 +325,8 @@ void default_get_overlay_fifo_thresholds(enum omap_plane plane,
        *fifo_low = fifo_size - burst_size_bytes;
 }
 
-static int default_wait_vsync(struct omap_dss_device *dssdev)
+int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
 {
-       unsigned long timeout = msecs_to_jiffies(500);
-       u32 irq;
-
-       if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
-               irq = DISPC_IRQ_EVSYNC_ODD;
-       else
-               irq = DISPC_IRQ_VSYNC;
-
-       return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
-}
-
-static int default_get_recommended_bpp(struct omap_dss_device *dssdev)
-{
-       if (dssdev->panel.recommended_bpp)
-               return dssdev->panel.recommended_bpp;
-
        switch (dssdev->type) {
        case OMAP_DISPLAY_TYPE_DPI:
                if (dssdev->phy.dpi.data_lines == 24)
@@ -362,6 +348,7 @@ static int default_get_recommended_bpp(struct omap_dss_device *dssdev)
                BUG();
        }
 }
+EXPORT_SYMBOL(omapdss_default_get_recommended_bpp);
 
 /* Checks if replication logic should be used. Only use for active matrix,
  * when overlay is in RGB12U or RGB16 mode, and LCD interface is
@@ -425,10 +412,6 @@ void dss_init_device(struct platform_device *pdev,
                return;
        }
 
-       dssdev->get_resolution = default_get_resolution;
-       dssdev->get_recommended_bpp = default_get_recommended_bpp;
-       dssdev->wait_vsync = default_wait_vsync;
-
        switch (dssdev->type) {
        case OMAP_DISPLAY_TYPE_DPI:
                r = dpi_init_display(dssdev);
@@ -502,13 +485,13 @@ static int dss_suspend_device(struct device *dev, void *data)
                return 0;
        }
 
-       if (!dssdev->suspend) {
+       if (!dssdev->driver->suspend) {
                DSSERR("display '%s' doesn't implement suspend\n",
                                dssdev->name);
                return -ENOSYS;
        }
 
-       r = dssdev->suspend(dssdev);
+       r = dssdev->driver->suspend(dssdev);
        if (r)
                return r;
 
@@ -537,8 +520,8 @@ static int dss_resume_device(struct device *dev, void *data)
        int r;
        struct omap_dss_device *dssdev = to_dss_device(dev);
 
-       if (dssdev->activate_after_resume && dssdev->resume) {
-               r = dssdev->resume(dssdev);
+       if (dssdev->activate_after_resume && dssdev->driver->resume) {
+               r = dssdev->driver->resume(dssdev);
                if (r)
                        return r;
        }
@@ -558,7 +541,7 @@ int dss_resume_all_devices(void)
 static int dss_disable_device(struct device *dev, void *data)
 {
        struct omap_dss_device *dssdev = to_dss_device(dev);
-       dssdev->disable(dssdev);
+       dssdev->driver->disable(dssdev);
        return 0;
 }
 
@@ -591,10 +574,6 @@ struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from)
 
        int match(struct device *dev, void *data)
        {
-               /* skip panels connected to controllers */
-               if (to_dss_device(dev)->panel.ctrl)
-                       return 0;
-
                return 1;
        }
 
@@ -626,45 +605,21 @@ EXPORT_SYMBOL(omap_dss_find_device);
 
 int omap_dss_start_device(struct omap_dss_device *dssdev)
 {
-       int r;
-
        if (!dssdev->driver) {
                DSSDBG("no driver\n");
-               r = -ENODEV;
-               goto err0;
-       }
-
-       if (dssdev->ctrl.panel && !dssdev->ctrl.panel->driver) {
-               DSSDBG("no panel driver\n");
-               r = -ENODEV;
-               goto err0;
+               return -ENODEV;
        }
 
        if (!try_module_get(dssdev->dev.driver->owner)) {
-               r = -ENODEV;
-               goto err0;
-       }
-
-       if (dssdev->ctrl.panel) {
-               if (!try_module_get(dssdev->ctrl.panel->dev.driver->owner)) {
-                       r = -ENODEV;
-                       goto err1;
-               }
+               return -ENODEV;
        }
 
        return 0;
-err1:
-       module_put(dssdev->dev.driver->owner);
-err0:
-       return r;
 }
 EXPORT_SYMBOL(omap_dss_start_device);
 
 void omap_dss_stop_device(struct omap_dss_device *dssdev)
 {
-       if (dssdev->ctrl.panel)
-               module_put(dssdev->ctrl.panel->dev.driver->owner);
-
        module_put(dssdev->dev.driver->owner);
 }
 EXPORT_SYMBOL(omap_dss_stop_device);
index 2d71031..960e977 100644 (file)
 #include <linux/kernel.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/err.h>
 #include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
 
 #include <plat/display.h>
 #include <plat/cpu.h>
@@ -33,7 +36,7 @@
 #include "dss.h"
 
 static struct {
-       int update_enabled;
+       struct regulator *vdds_dsi_reg;
 } dpi;
 
 #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
@@ -53,7 +56,7 @@ static int dpi_set_dsi_clk(bool is_tft, unsigned long pck_req,
        if (r)
                return r;
 
-       dss_select_clk_source(0, 1);
+       dss_select_dispc_clk_source(DSS_SRC_DSI1_PLL_FCLK);
 
        r = dispc_set_clock_div(&dispc_cinfo);
        if (r)
@@ -150,7 +153,7 @@ static int dpi_basic_init(struct omap_dss_device *dssdev)
        return 0;
 }
 
-static int dpi_display_enable(struct omap_dss_device *dssdev)
+int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 {
        int r;
 
@@ -160,10 +163,10 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
                goto err0;
        }
 
-       if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
-               DSSERR("display already enabled\n");
-               r = -EINVAL;
-               goto err1;
+       if (cpu_is_omap34xx()) {
+               r = regulator_enable(dpi.vdds_dsi_reg);
+               if (r)
+                       goto err1;
        }
 
        dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
@@ -184,18 +187,10 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
 
        mdelay(2);
 
-       dispc_enable_lcd_out(1);
-
-       r = dssdev->driver->enable(dssdev);
-       if (r)
-               goto err5;
-
-       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+       dssdev->manager->enable(dssdev->manager);
 
        return 0;
 
-err5:
-       dispc_enable_lcd_out(0);
 err4:
 #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
        dsi_pll_uninit();
@@ -204,78 +199,35 @@ err3:
 #endif
 err2:
        dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+       if (cpu_is_omap34xx())
+               regulator_disable(dpi.vdds_dsi_reg);
 err1:
        omap_dss_stop_device(dssdev);
 err0:
        return r;
 }
+EXPORT_SYMBOL(omapdss_dpi_display_enable);
 
-static int dpi_display_resume(struct omap_dss_device *dssdev);
-
-static void dpi_display_disable(struct omap_dss_device *dssdev)
+void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
 {
-       if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
-               return;
-
-       if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
-               dpi_display_resume(dssdev);
-
-       dssdev->driver->disable(dssdev);
-
-       dispc_enable_lcd_out(0);
+       dssdev->manager->disable(dssdev->manager);
 
 #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
-       dss_select_clk_source(0, 0);
+       dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
        dsi_pll_uninit();
        dss_clk_disable(DSS_CLK_FCK2);
 #endif
 
        dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
 
-       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+       if (cpu_is_omap34xx())
+               regulator_disable(dpi.vdds_dsi_reg);
 
        omap_dss_stop_device(dssdev);
 }
+EXPORT_SYMBOL(omapdss_dpi_display_disable);
 
-static int dpi_display_suspend(struct omap_dss_device *dssdev)
-{
-       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
-               return -EINVAL;
-
-       DSSDBG("dpi_display_suspend\n");
-
-       if (dssdev->driver->suspend)
-               dssdev->driver->suspend(dssdev);
-
-       dispc_enable_lcd_out(0);
-
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
-
-       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
-       return 0;
-}
-
-static int dpi_display_resume(struct omap_dss_device *dssdev)
-{
-       if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED)
-               return -EINVAL;
-
-       DSSDBG("dpi_display_resume\n");
-
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
-
-       dispc_enable_lcd_out(1);
-
-       if (dssdev->driver->resume)
-               dssdev->driver->resume(dssdev);
-
-       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-       return 0;
-}
-
-static void dpi_set_timings(struct omap_dss_device *dssdev,
+void dpi_set_timings(struct omap_dss_device *dssdev,
                        struct omap_video_timings *timings)
 {
        DSSDBG("dpi_set_timings\n");
@@ -285,8 +237,9 @@ static void dpi_set_timings(struct omap_dss_device *dssdev,
                dispc_go(OMAP_DSS_CHANNEL_LCD);
        }
 }
+EXPORT_SYMBOL(dpi_set_timings);
 
-static int dpi_check_timings(struct omap_dss_device *dssdev,
+int dpi_check_timings(struct omap_dss_device *dssdev,
                        struct omap_video_timings *timings)
 {
        bool is_tft;
@@ -340,56 +293,25 @@ static int dpi_check_timings(struct omap_dss_device *dssdev,
 
        return 0;
 }
-
-static void dpi_get_timings(struct omap_dss_device *dssdev,
-                       struct omap_video_timings *timings)
-{
-       *timings = dssdev->panel.timings;
-}
-
-static int dpi_display_set_update_mode(struct omap_dss_device *dssdev,
-               enum omap_dss_update_mode mode)
-{
-       if (mode == OMAP_DSS_UPDATE_MANUAL)
-               return -EINVAL;
-
-       if (mode == OMAP_DSS_UPDATE_DISABLED) {
-               dispc_enable_lcd_out(0);
-               dpi.update_enabled = 0;
-       } else {
-               dispc_enable_lcd_out(1);
-               dpi.update_enabled = 1;
-       }
-
-       return 0;
-}
-
-static enum omap_dss_update_mode dpi_display_get_update_mode(
-               struct omap_dss_device *dssdev)
-{
-       return dpi.update_enabled ? OMAP_DSS_UPDATE_AUTO :
-               OMAP_DSS_UPDATE_DISABLED;
-}
+EXPORT_SYMBOL(dpi_check_timings);
 
 int dpi_init_display(struct omap_dss_device *dssdev)
 {
        DSSDBG("init_display\n");
 
-       dssdev->enable = dpi_display_enable;
-       dssdev->disable = dpi_display_disable;
-       dssdev->suspend = dpi_display_suspend;
-       dssdev->resume = dpi_display_resume;
-       dssdev->set_timings = dpi_set_timings;
-       dssdev->check_timings = dpi_check_timings;
-       dssdev->get_timings = dpi_get_timings;
-       dssdev->set_update_mode = dpi_display_set_update_mode;
-       dssdev->get_update_mode = dpi_display_get_update_mode;
-
        return 0;
 }
 
-int dpi_init(void)
+int dpi_init(struct platform_device *pdev)
 {
+       if (cpu_is_omap34xx()) {
+               dpi.vdds_dsi_reg = dss_get_vdds_dsi();
+               if (IS_ERR(dpi.vdds_dsi_reg)) {
+                       DSSERR("can't get VDDS_DSI regulator\n");
+                       return PTR_ERR(dpi.vdds_dsi_reg);
+               }
+       }
+
        return 0;
 }
 
index 6122178..3af207b 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
+#include <linux/semaphore.h>
 #include <linux/seq_file.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
-#include <linux/kthread.h>
 #include <linux/wait.h>
+#include <linux/workqueue.h>
 
 #include <plat/display.h>
 #include <plat/clock.h>
@@ -199,7 +200,6 @@ enum dsi_vc_mode {
 };
 
 struct dsi_update_region {
-       bool dirty;
        u16 x, y, w, h;
        struct omap_dss_device *device;
 };
@@ -224,29 +224,25 @@ static struct
                enum dsi_vc_mode mode;
                struct omap_dss_device *dssdev;
                enum fifo_size fifo_size;
-               int dest_per;   /* destination peripheral 0-3 */
        } vc[4];
 
        struct mutex lock;
-       struct mutex bus_lock;
+       struct semaphore bus_lock;
 
        unsigned pll_locked;
 
        struct completion bta_completion;
 
-       struct task_struct *thread;
-       wait_queue_head_t waitqueue;
-
-       spinlock_t update_lock;
-       bool framedone_received;
+       int update_channel;
        struct dsi_update_region update_region;
-       struct dsi_update_region active_update_region;
-       struct completion update_completion;
 
-       enum omap_dss_update_mode user_update_mode;
-       enum omap_dss_update_mode update_mode;
        bool te_enabled;
-       bool use_ext_te;
+
+       struct work_struct framedone_work;
+       void (*framedone_callback)(int, void *);
+       void *framedone_data;
+
+       struct delayed_work framedone_timeout_work;
 
 #ifdef DSI_CATCH_MISSING_TE
        struct timer_list te_timer;
@@ -261,8 +257,6 @@ static struct
 #ifdef DEBUG
        ktime_t perf_setup_time;
        ktime_t perf_start_time;
-       ktime_t perf_start_time_auto;
-       int perf_measure_frames;
 #endif
        int debug_read;
        int debug_write;
@@ -299,16 +293,21 @@ void dsi_restore_context(void)
 
 void dsi_bus_lock(void)
 {
-       mutex_lock(&dsi.bus_lock);
+       down(&dsi.bus_lock);
 }
 EXPORT_SYMBOL(dsi_bus_lock);
 
 void dsi_bus_unlock(void)
 {
-       mutex_unlock(&dsi.bus_lock);
+       up(&dsi.bus_lock);
 }
 EXPORT_SYMBOL(dsi_bus_unlock);
 
+static bool dsi_bus_is_locked(void)
+{
+       return dsi.bus_lock.count == 0;
+}
+
 static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum,
                int value)
 {
@@ -333,12 +332,6 @@ static void dsi_perf_mark_start(void)
        dsi.perf_start_time = ktime_get();
 }
 
-static void dsi_perf_mark_start_auto(void)
-{
-       dsi.perf_measure_frames = 0;
-       dsi.perf_start_time_auto = ktime_get();
-}
-
 static void dsi_perf_show(const char *name)
 {
        ktime_t t, setup_time, trans_time;
@@ -348,9 +341,6 @@ static void dsi_perf_show(const char *name)
        if (!dsi_perf)
                return;
 
-       if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED)
-               return;
-
        t = ktime_get();
 
        setup_time = ktime_sub(dsi.perf_start_time, dsi.perf_setup_time);
@@ -365,76 +355,23 @@ static void dsi_perf_show(const char *name)
 
        total_us = setup_us + trans_us;
 
-       total_bytes = dsi.active_update_region.w *
-               dsi.active_update_region.h *
-               dsi.active_update_region.device->ctrl.pixel_size / 8;
-
-       if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) {
-               static u32 s_total_trans_us, s_total_setup_us;
-               static u32 s_min_trans_us = 0xffffffff, s_min_setup_us;
-               static u32 s_max_trans_us, s_max_setup_us;
-               const int numframes = 100;
-               ktime_t total_time_auto;
-               u32 total_time_auto_us;
-
-               dsi.perf_measure_frames++;
-
-               if (setup_us < s_min_setup_us)
-                       s_min_setup_us = setup_us;
+       total_bytes = dsi.update_region.w *
+               dsi.update_region.h *
+               dsi.update_region.device->ctrl.pixel_size / 8;
 
-               if (setup_us > s_max_setup_us)
-                       s_max_setup_us = setup_us;
-
-               s_total_setup_us += setup_us;
-
-               if (trans_us < s_min_trans_us)
-                       s_min_trans_us = trans_us;
-
-               if (trans_us > s_max_trans_us)
-                       s_max_trans_us = trans_us;
-
-               s_total_trans_us += trans_us;
-
-               if (dsi.perf_measure_frames < numframes)
-                       return;
-
-               total_time_auto = ktime_sub(t, dsi.perf_start_time_auto);
-               total_time_auto_us = (u32)ktime_to_us(total_time_auto);
-
-               printk(KERN_INFO "DSI(%s): %u fps, setup %u/%u/%u, "
-                               "trans %u/%u/%u\n",
-                               name,
-                               1000 * 1000 * numframes / total_time_auto_us,
-                               s_min_setup_us,
-                               s_max_setup_us,
-                               s_total_setup_us / numframes,
-                               s_min_trans_us,
-                               s_max_trans_us,
-                               s_total_trans_us / numframes);
-
-               s_total_setup_us = 0;
-               s_min_setup_us = 0xffffffff;
-               s_max_setup_us = 0;
-               s_total_trans_us = 0;
-               s_min_trans_us = 0xffffffff;
-               s_max_trans_us = 0;
-               dsi_perf_mark_start_auto();
-       } else {
-               printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), "
-                               "%u bytes, %u kbytes/sec\n",
-                               name,
-                               setup_us,
-                               trans_us,
-                               total_us,
-                               1000*1000 / total_us,
-                               total_bytes,
-                               total_bytes * 1000 / total_us);
-       }
+       printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), "
+                       "%u bytes, %u kbytes/sec\n",
+                       name,
+                       setup_us,
+                       trans_us,
+                       total_us,
+                       1000*1000 / total_us,
+                       total_bytes,
+                       total_bytes * 1000 / total_us);
 }
 #else
 #define dsi_perf_mark_setup()
 #define dsi_perf_mark_start()
-#define dsi_perf_mark_start_auto()
 #define dsi_perf_show(x)
 #endif
 
@@ -774,7 +711,7 @@ static unsigned long dsi_fclk_rate(void)
 {
        unsigned long r;
 
-       if (dss_get_dsi_clk_source() == 0) {
+       if (dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK) {
                /* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */
                r = dss_clk_get_rate(DSS_CLK_FCK1);
        } else {
@@ -1227,17 +1164,19 @@ void dsi_dump_clocks(struct seq_file *s)
        seq_printf(s,   "dsi1_pll_fck\t%-16luregm3 %u\t(%s)\n",
                        cinfo->dsi1_pll_fclk,
                        cinfo->regm3,
-                       dss_get_dispc_clk_source() == 0 ? "off" : "on");
+                       dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ?
+                       "off" : "on");
 
        seq_printf(s,   "dsi2_pll_fck\t%-16luregm4 %u\t(%s)\n",
                        cinfo->dsi2_pll_fclk,
                        cinfo->regm4,
-                       dss_get_dsi_clk_source() == 0 ? "off" : "on");
+                       dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ?
+                       "off" : "on");
 
        seq_printf(s,   "- DSI -\n");
 
        seq_printf(s,   "dsi fclk source = %s\n",
-                       dss_get_dsi_clk_source() == 0 ?
+                       dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ?
                        "dss1_alwon_fclk" : "dsi2_pll_fclk");
 
        seq_printf(s,   "DSI_FCLK\t%lu\n", dsi_fclk_rate());
@@ -1756,29 +1695,10 @@ static int dsi_force_tx_stop_mode_io(void)
        return 0;
 }
 
-static void dsi_vc_print_status(int channel)
-{
-       u32 r;
-
-       r = dsi_read_reg(DSI_VC_CTRL(channel));
-       DSSDBG("vc %d: TX_FIFO_NOT_EMPTY %d, BTA_EN %d, VC_BUSY %d, "
-                       "TX_FIFO_FULL %d, RX_FIFO_NOT_EMPTY %d, ",
-                       channel,
-                       FLD_GET(r, 5, 5),
-                       FLD_GET(r, 6, 6),
-                       FLD_GET(r, 15, 15),
-                       FLD_GET(r, 16, 16),
-                       FLD_GET(r, 20, 20));
-
-       r = dsi_read_reg(DSI_TX_FIFO_VC_EMPTINESS);
-       DSSDBG("EMPTINESS %d\n", (r >> (8 * channel)) & 0xff);
-}
-
 static int dsi_vc_enable(int channel, bool enable)
 {
-       if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
-               DSSDBG("dsi_vc_enable channel %d, enable %d\n",
-                               channel, enable);
+       DSSDBG("dsi_vc_enable channel %d, enable %d\n",
+                       channel, enable);
 
        enable = enable ? 1 : 0;
 
@@ -1859,10 +1779,12 @@ static void dsi_vc_config_vp(int channel)
 }
 
 
-static void dsi_vc_enable_hs(int channel, bool enable)
+void omapdss_dsi_vc_enable_hs(int channel, bool enable)
 {
        DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable);
 
+       WARN_ON(!dsi_bus_is_locked());
+
        dsi_vc_enable(channel, 0);
        dsi_if_enable(0);
 
@@ -1873,6 +1795,7 @@ static void dsi_vc_enable_hs(int channel, bool enable)
 
        dsi_force_tx_stop_mode_io();
 }
+EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs);
 
 static void dsi_vc_flush_long_data(int channel)
 {
@@ -1955,11 +1878,10 @@ static u16 dsi_vc_flush_receive_data(int channel)
 
 static int dsi_vc_send_bta(int channel)
 {
-       if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO &&
-                       (dsi.debug_write || dsi.debug_read))
+       if (dsi.debug_write || dsi.debug_read)
                DSSDBG("dsi_vc_send_bta %d\n", channel);
 
-       WARN_ON(!mutex_is_locked(&dsi.bus_lock));
+       WARN_ON(!dsi_bus_is_locked());
 
        if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {    /* RX_FIFO_NOT_EMPTY */
                DSSERR("rx fifo not empty when sending BTA, dumping data:\n");
@@ -2010,10 +1932,9 @@ static inline void dsi_vc_write_long_header(int channel, u8 data_type,
        u32 val;
        u8 data_id;
 
-       WARN_ON(!mutex_is_locked(&dsi.bus_lock));
+       WARN_ON(!dsi_bus_is_locked());
 
-       /*data_id = data_type | channel << 6; */
-       data_id = data_type | dsi.vc[channel].dest_per << 6;
+       data_id = data_type | channel << 6;
 
        val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) |
                FLD_VAL(ecc, 31, 24);
@@ -2056,13 +1977,10 @@ static int dsi_vc_send_long(int channel, u8 data_type, u8 *data, u16 len,
 
        dsi_vc_write_long_header(channel, data_type, len, ecc);
 
-       /*dsi_vc_print_status(0); */
-
        p = data;
        for (i = 0; i < len >> 2; i++) {
                if (dsi.debug_write)
                        DSSDBG("\tsending full packet %d\n", i);
-               /*dsi_vc_print_status(0); */
 
                b1 = *p++;
                b2 = *p++;
@@ -2105,7 +2023,7 @@ static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc)
        u32 r;
        u8 data_id;
 
-       WARN_ON(!mutex_is_locked(&dsi.bus_lock));
+       WARN_ON(!dsi_bus_is_locked());
 
        if (dsi.debug_write)
                DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n",
@@ -2119,7 +2037,7 @@ static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc)
                return -EINVAL;
        }
 
-       data_id = data_type | dsi.vc[channel].dest_per << 6;
+       data_id = data_type | channel << 6;
 
        r = (data_id << 0) | (data << 8) | (ecc << 24);
 
@@ -2163,14 +2081,35 @@ int dsi_vc_dcs_write(int channel, u8 *data, int len)
 
        r = dsi_vc_dcs_write_nosync(channel, data, len);
        if (r)
-               return r;
+               goto err;
 
        r = dsi_vc_send_bta_sync(channel);
+       if (r)
+               goto err;
 
+       return 0;
+err:
+       DSSERR("dsi_vc_dcs_write(ch %d, cmd 0x%02x, len %d) failed\n",
+                       channel, data[0], len);
        return r;
 }
 EXPORT_SYMBOL(dsi_vc_dcs_write);
 
+int dsi_vc_dcs_write_0(int channel, u8 dcs_cmd)
+{
+       return dsi_vc_dcs_write(channel, &dcs_cmd, 1);
+}
+EXPORT_SYMBOL(dsi_vc_dcs_write_0);
+
+int dsi_vc_dcs_write_1(int channel, u8 dcs_cmd, u8 param)
+{
+       u8 buf[2];
+       buf[0] = dcs_cmd;
+       buf[1] = param;
+       return dsi_vc_dcs_write(channel, buf, 2);
+}
+EXPORT_SYMBOL(dsi_vc_dcs_write_1);
+
 int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen)
 {
        u32 val;
@@ -2182,16 +2121,17 @@ int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen)
 
        r = dsi_vc_send_short(channel, DSI_DT_DCS_READ, dcs_cmd, 0);
        if (r)
-               return r;
+               goto err;
 
        r = dsi_vc_send_bta_sync(channel);
        if (r)
-               return r;
+               goto err;
 
        /* RX_FIFO_NOT_EMPTY */
        if (REG_GET(DSI_VC_CTRL(channel), 20, 20) == 0) {
                DSSERR("RX fifo empty when trying to read.\n");
-               return -EIO;
+               r = -EIO;
+               goto err;
        }
 
        val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
@@ -2201,15 +2141,18 @@ int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen)
        if (dt == DSI_DT_RX_ACK_WITH_ERR) {
                u16 err = FLD_GET(val, 23, 8);
                dsi_show_rx_ack_with_err(err);
-               return -EIO;
+               r = -EIO;
+               goto err;
 
        } else if (dt == DSI_DT_RX_SHORT_READ_1) {
                u8 data = FLD_GET(val, 15, 8);
                if (dsi.debug_read)
                        DSSDBG("\tDCS short response, 1 byte: %02x\n", data);
 
-               if (buflen < 1)
-                       return -EIO;
+               if (buflen < 1) {
+                       r = -EIO;
+                       goto err;
+               }
 
                buf[0] = data;
 
@@ -2219,8 +2162,10 @@ int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen)
                if (dsi.debug_read)
                        DSSDBG("\tDCS short response, 2 byte: %04x\n", data);
 
-               if (buflen < 2)
-                       return -EIO;
+               if (buflen < 2) {
+                       r = -EIO;
+                       goto err;
+               }
 
                buf[0] = data & 0xff;
                buf[1] = (data >> 8) & 0xff;
@@ -2232,8 +2177,10 @@ int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen)
                if (dsi.debug_read)
                        DSSDBG("\tDCS long response, len %d\n", len);
 
-               if (len > buflen)
-                       return -EIO;
+               if (len > buflen) {
+                       r = -EIO;
+                       goto err;
+               }
 
                /* two byte checksum ends the packet, not included in len */
                for (w = 0; w < len + 2;) {
@@ -2255,14 +2202,52 @@ int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen)
                }
 
                return len;
-
        } else {
                DSSERR("\tunknown datatype 0x%02x\n", dt);
-               return -EIO;
+               r = -EIO;
+               goto err;
        }
+
+       BUG();
+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(int channel, u8 dcs_cmd, u8 *data)
+{
+       int r;
+
+       r = dsi_vc_dcs_read(channel, dcs_cmd, data, 1);
+
+       if (r < 0)
+               return r;
+
+       if (r != 1)
+               return -EIO;
+
+       return 0;
+}
+EXPORT_SYMBOL(dsi_vc_dcs_read_1);
+
+int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u16 *data)
+{
+       int r;
+
+       r = dsi_vc_dcs_read(channel, dcs_cmd, (u8 *)data, 2);
+
+       if (r < 0)
+               return r;
+
+       if (r != 2)
+               return -EIO;
+
+       return 0;
+}
+EXPORT_SYMBOL(dsi_vc_dcs_read_2);
 
 int dsi_vc_set_max_rx_packet_size(int channel, u16 len)
 {
@@ -2491,15 +2476,15 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
        u32 r;
        int buswidth = 0;
 
-       dsi_config_tx_fifo(DSI_FIFO_SIZE_128,
-                       DSI_FIFO_SIZE_0,
-                       DSI_FIFO_SIZE_0,
-                       DSI_FIFO_SIZE_0);
+       dsi_config_tx_fifo(DSI_FIFO_SIZE_32,
+                       DSI_FIFO_SIZE_32,
+                       DSI_FIFO_SIZE_32,
+                       DSI_FIFO_SIZE_32);
 
-       dsi_config_rx_fifo(DSI_FIFO_SIZE_128,
-                       DSI_FIFO_SIZE_0,
-                       DSI_FIFO_SIZE_0,
-                       DSI_FIFO_SIZE_0);
+       dsi_config_rx_fifo(DSI_FIFO_SIZE_32,
+                       DSI_FIFO_SIZE_32,
+                       DSI_FIFO_SIZE_32,
+                       DSI_FIFO_SIZE_32);
 
        /* XXX what values for the timeouts? */
        dsi_set_stop_state_counter(1000);
@@ -2537,12 +2522,9 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
        dsi_write_reg(DSI_CTRL, r);
 
        dsi_vc_initial_config(0);
-
-       /* set all vc targets to peripheral 0 */
-       dsi.vc[0].dest_per = 0;
-       dsi.vc[1].dest_per = 0;
-       dsi.vc[2].dest_per = 0;
-       dsi.vc[3].dest_per = 0;
+       dsi_vc_initial_config(1);
+       dsi_vc_initial_config(2);
+       dsi_vc_initial_config(3);
 
        return 0;
 }
@@ -2777,18 +2759,16 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
        unsigned packet_payload;
        unsigned packet_len;
        u32 l;
-       bool use_te_trigger;
-       const unsigned channel = 0;
+       const unsigned channel = dsi.update_channel;
        /* line buffer is 1024 x 24bits */
        /* XXX: for some reason using full buffer size causes considerable TX
         * slowdown with update sizes that fill the whole buffer */
        const unsigned line_buf_size = 1023 * 3;
 
-       use_te_trigger = dsi.te_enabled && !dsi.use_ext_te;
+       DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",
+                       x, y, w, h);
 
-       if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
-               DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",
-                               x, y, w, h);
+       dsi_vc_config_vp(channel);
 
        bytespp = dssdev->ctrl.pixel_size / 8;
        bytespl = w * bytespp;
@@ -2808,15 +2788,12 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
        if (bytespf % packet_payload)
                total_len += (bytespf % packet_payload) + 1;
 
-       if (0)
-               dsi_vc_print_status(1);
-
        l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */
        dsi_write_reg(DSI_VC_TE(channel), l);
 
        dsi_vc_write_long_header(channel, DSI_DT_DCS_LONG_WRITE, packet_len, 0);
 
-       if (use_te_trigger)
+       if (dsi.te_enabled)
                l = FLD_MOD(l, 1, 30, 30); /* TE_EN */
        else
                l = FLD_MOD(l, 1, 31, 31); /* TE_START */
@@ -2830,9 +2807,14 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
         */
        dispc_disable_sidle();
 
+       dsi_perf_mark_start();
+
+       schedule_delayed_work(&dsi.framedone_timeout_work,
+                       msecs_to_jiffies(250));
+
        dss_start_update(dssdev);
 
-       if (use_te_trigger) {
+       if (dsi.te_enabled) {
                /* disable LP_RX_TO, so that we can receive TE.  Time to wait
                 * for TE is longer than the timer allows */
                REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */
@@ -2852,110 +2834,64 @@ static void dsi_te_timeout(unsigned long arg)
 }
 #endif
 
-static void dsi_framedone_irq_callback(void *data, u32 mask)
+static void dsi_framedone_timeout_work_callback(struct work_struct *work)
 {
-       /* Note: We get FRAMEDONE when DISPC has finished sending pixels and
-        * turns itself off. However, DSI still has the pixels in its buffers,
-        * and is sending the data.
-        */
+       int r;
+       const int channel = dsi.update_channel;
+
+       DSSERR("Framedone not received for 250ms!\n");
 
        /* SIDLEMODE back to smart-idle */
        dispc_enable_sidle();
 
-       dsi.framedone_received = true;
-       wake_up(&dsi.waitqueue);
-}
-
-static void dsi_set_update_region(struct omap_dss_device *dssdev,
-               u16 x, u16 y, u16 w, u16 h)
-{
-       spin_lock(&dsi.update_lock);
-       if (dsi.update_region.dirty) {
-               dsi.update_region.x = min(x, dsi.update_region.x);
-               dsi.update_region.y = min(y, dsi.update_region.y);
-               dsi.update_region.w = max(w, dsi.update_region.w);
-               dsi.update_region.h = max(h, dsi.update_region.h);
-       } else {
-               dsi.update_region.x = x;
-               dsi.update_region.y = y;
-               dsi.update_region.w = w;
-               dsi.update_region.h = h;
+       if (dsi.te_enabled) {
+               /* enable LP_RX_TO again after the TE */
+               REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
        }
 
-       dsi.update_region.device = dssdev;
-       dsi.update_region.dirty = true;
-
-       spin_unlock(&dsi.update_lock);
-
-}
-
-static int dsi_set_update_mode(struct omap_dss_device *dssdev,
-               enum omap_dss_update_mode mode)
-{
-       int r = 0;
-       int i;
-
-       WARN_ON(!mutex_is_locked(&dsi.bus_lock));
-
-       if (dsi.update_mode != mode) {
-               dsi.update_mode = mode;
-
-               /* Mark the overlays dirty, and do apply(), so that we get the
-                * overlays configured properly after update mode change. */
-               for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
-                       struct omap_overlay *ovl;
-                       ovl = omap_dss_get_overlay(i);
-                       if (ovl->manager == dssdev->manager)
-                               ovl->info_dirty = true;
-               }
-
-               r = dssdev->manager->apply(dssdev->manager);
-
-               if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE &&
-                               mode == OMAP_DSS_UPDATE_AUTO) {
-                       u16 w, h;
-
-                       DSSDBG("starting auto update\n");
-
-                       dssdev->get_resolution(dssdev, &w, &h);
-
-                       dsi_set_update_region(dssdev, 0, 0, w, h);
-
-                       dsi_perf_mark_start_auto();
+       /* Send BTA after the frame. We need this for the TE to work, as TE
+        * trigger is only sent for BTAs without preceding packet. Thus we need
+        * to BTA after the pixel packets so that next BTA will cause TE
+        * trigger.
+        *
+        * This is not needed when TE is not in use, but we do it anyway to
+        * make sure that the transfer has been completed. It would be more
+        * optimal, but more complex, to wait only just before starting next
+        * transfer. */
+       r = dsi_vc_send_bta_sync(channel);
+       if (r)
+               DSSERR("BTA after framedone failed\n");
 
-                       wake_up(&dsi.waitqueue);
-               }
+       /* RX_FIFO_NOT_EMPTY */
+       if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
+               DSSERR("Received error during frame transfer:\n");
+               dsi_vc_flush_receive_data(channel);
        }
 
-       return r;
+       dsi.framedone_callback(-ETIMEDOUT, dsi.framedone_data);
 }
 
-static int dsi_set_te(struct omap_dss_device *dssdev, bool enable)
+static void dsi_framedone_irq_callback(void *data, u32 mask)
 {
-       int r = 0;
+       /* Note: We get FRAMEDONE when DISPC has finished sending pixels and
+        * turns itself off. However, DSI still has the pixels in its buffers,
+        * and is sending the data.
+        */
 
-       if (dssdev->driver->enable_te) {
-               r = dssdev->driver->enable_te(dssdev, enable);
-               /* XXX for some reason, DSI TE breaks if we don't wait here.
-                * Panel bug? Needs more studying */
-               msleep(100);
-       }
+       /* SIDLEMODE back to smart-idle */
+       dispc_enable_sidle();
 
-       return r;
+       schedule_work(&dsi.framedone_work);
 }
 
 static void dsi_handle_framedone(void)
 {
        int r;
-       const int channel = 0;
-       bool use_te_trigger;
-
-       use_te_trigger = dsi.te_enabled && !dsi.use_ext_te;
+       const int channel = dsi.update_channel;
 
-       if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
-               DSSDBG("FRAMEDONE\n");
+       DSSDBG("FRAMEDONE\n");
 
-       if (use_te_trigger) {
+       if (dsi.te_enabled) {
                /* enable LP_RX_TO again after the TE */
                REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
        }
@@ -2976,7 +2912,7 @@ static void dsi_handle_framedone(void)
        /* RX_FIFO_NOT_EMPTY */
        if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
                DSSERR("Received error during frame transfer:\n");
-               dsi_vc_flush_receive_data(0);
+               dsi_vc_flush_receive_data(channel);
        }
 
 #ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
@@ -2984,118 +2920,79 @@ static void dsi_handle_framedone(void)
 #endif
 }
 
-static int dsi_update_thread(void *data)
+static void dsi_framedone_work_callback(struct work_struct *work)
 {
-       unsigned long timeout;
-       struct omap_dss_device *device;
-       u16 x, y, w, h;
-
-       while (1) {
-               bool sched;
-
-               wait_event_interruptible(dsi.waitqueue,
-                               dsi.update_mode == OMAP_DSS_UPDATE_AUTO ||
-                               (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL &&
-                                dsi.update_region.dirty == true) ||
-                               kthread_should_stop());
-
-               if (kthread_should_stop())
-                       break;
-
-               dsi_bus_lock();
-
-               if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED ||
-                               kthread_should_stop()) {
-                       dsi_bus_unlock();
-                       break;
-               }
-
-               dsi_perf_mark_setup();
-
-               if (dsi.update_region.dirty) {
-                       spin_lock(&dsi.update_lock);
-                       dsi.active_update_region = dsi.update_region;
-                       dsi.update_region.dirty = false;
-                       spin_unlock(&dsi.update_lock);
-               }
+       DSSDBGF();
 
-               device = dsi.active_update_region.device;
-               x = dsi.active_update_region.x;
-               y = dsi.active_update_region.y;
-               w = dsi.active_update_region.w;
-               h = dsi.active_update_region.h;
+       cancel_delayed_work_sync(&dsi.framedone_timeout_work);
 
-               if (device->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
+       dsi_handle_framedone();
 
-                       if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL)
-                               dss_setup_partial_planes(device,
-                                               &x, &y, &w, &h);
+       dsi_perf_show("DISPC");
 
-                       dispc_set_lcd_size(w, h);
-               }
+       dsi.framedone_callback(0, dsi.framedone_data);
+}
 
-               if (dsi.active_update_region.dirty) {
-                       dsi.active_update_region.dirty = false;
-                       /* XXX TODO we don't need to send the coords, if they
-                        * are the same that are already programmed to the
-                        * panel. That should speed up manual update a bit */
-                       device->driver->setup_update(device, x, y, w, h);
-               }
+int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
+                                   u16 *x, u16 *y, u16 *w, u16 *h)
+{
+       u16 dw, dh;
 
-               dsi_perf_mark_start();
+       dssdev->driver->get_resolution(dssdev, &dw, &dh);
 
-               if (device->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
-                       dsi_vc_config_vp(0);
+       if  (*x > dw || *y > dh)
+               return -EINVAL;
 
-                       if (dsi.te_enabled && dsi.use_ext_te)
-                               device->driver->wait_for_te(device);
+       if (*x + *w > dw)
+               return -EINVAL;
 
-                       dsi.framedone_received = false;
+       if (*y + *h > dh)
+               return -EINVAL;
 
-                       dsi_update_screen_dispc(device, x, y, w, h);
+       if (*w == 1)
+               return -EINVAL;
 
-                       /* wait for framedone */
-                       timeout = msecs_to_jiffies(1000);
-                       wait_event_timeout(dsi.waitqueue,
-                                       dsi.framedone_received == true,
-                                       timeout);
+       if (*w == 0 || *h == 0)
+               return -EINVAL;
 
-                       if (!dsi.framedone_received) {
-                               DSSERR("framedone timeout\n");
-                               DSSERR("failed update %d,%d %dx%d\n",
-                                               x, y, w, h);
+       dsi_perf_mark_setup();
 
-                               dispc_enable_sidle();
-                               dispc_enable_lcd_out(0);
+       if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
+               dss_setup_partial_planes(dssdev, x, y, w, h);
+               dispc_set_lcd_size(*w, *h);
+       }
 
-                               dsi_reset_tx_fifo(0);
-                       } else {
-                               dsi_handle_framedone();
-                               dsi_perf_show("DISPC");
-                       }
-               } else {
-                       dsi_update_screen_l4(device, x, y, w, h);
-                       dsi_perf_show("L4");
-               }
+       return 0;
+}
+EXPORT_SYMBOL(omap_dsi_prepare_update);
 
-               sched = atomic_read(&dsi.bus_lock.count) < 0;
+int omap_dsi_update(struct omap_dss_device *dssdev,
+               int channel,
+               u16 x, u16 y, u16 w, u16 h,
+               void (*callback)(int, void *), void *data)
+{
+       dsi.update_channel = channel;
 
-               complete_all(&dsi.update_completion);
+       if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
+               dsi.framedone_callback = callback;
+               dsi.framedone_data = data;
 
-               dsi_bus_unlock();
+               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;
 
-               /* XXX We need to give others chance to get the bus lock. Is
-                * there a better way for this? */
-               if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO && sched)
-                       schedule_timeout_interruptible(1);
+               dsi_update_screen_dispc(dssdev, x, y, w, h);
+       } else {
+               dsi_update_screen_l4(dssdev, x, y, w, h);
+               dsi_perf_show("L4");
+               callback(0, data);
        }
 
-       DSSDBG("update thread exiting\n");
-
        return 0;
 }
-
-
+EXPORT_SYMBOL(omap_dsi_update);
 
 /* Display funcs */
 
@@ -3203,7 +3100,8 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
        if (r)
                goto err1;
 
-       dss_select_clk_source(true, true);
+       dss_select_dispc_clk_source(DSS_SRC_DSI1_PLL_FCLK);
+       dss_select_dsi_clk_source(DSS_SRC_DSI2_PLL_FCLK);
 
        DSSDBG("PLL OK\n");
 
@@ -3229,25 +3127,18 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
 
        /* enable interface */
        dsi_vc_enable(0, 1);
+       dsi_vc_enable(1, 1);
+       dsi_vc_enable(2, 1);
+       dsi_vc_enable(3, 1);
        dsi_if_enable(1);
        dsi_force_tx_stop_mode_io();
 
-       if (dssdev->driver->enable) {
-               r = dssdev->driver->enable(dssdev);
-               if (r)
-                       goto err4;
-       }
-
-       /* enable high-speed after initial config */
-       dsi_vc_enable_hs(0, 1);
-
        return 0;
-err4:
-       dsi_if_enable(0);
 err3:
        dsi_complexio_uninit();
 err2:
-       dss_select_clk_source(false, false);
+       dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
+       dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
 err1:
        dsi_pll_uninit();
 err0:
@@ -3256,10 +3147,8 @@ err0:
 
 static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev)
 {
-       if (dssdev->driver->disable)
-               dssdev->driver->disable(dssdev);
-
-       dss_select_clk_source(false, false);
+       dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
+       dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
        dsi_complexio_uninit();
        dsi_pll_uninit();
 }
@@ -3280,14 +3169,15 @@ static int dsi_core_init(void)
        return 0;
 }
 
-static int dsi_display_enable(struct omap_dss_device *dssdev)
+int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
 {
        int r = 0;
 
        DSSDBG("dsi_display_enable\n");
 
+       WARN_ON(!dsi_bus_is_locked());
+
        mutex_lock(&dsi.lock);
-       dsi_bus_lock();
 
        r = omap_dss_start_device(dssdev);
        if (r) {
@@ -3295,100 +3185,47 @@ static int dsi_display_enable(struct omap_dss_device *dssdev)
                goto err0;
        }
 
-       if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
-               DSSERR("dssdev already enabled\n");
-               r = -EINVAL;
-               goto err1;
-       }
-
        enable_clocks(1);
        dsi_enable_pll_clock(1);
 
        r = _dsi_reset();
        if (r)
-               goto err2;
+               goto err1;
 
        dsi_core_init();
 
        r = dsi_display_init_dispc(dssdev);
        if (r)
-               goto err2;
+               goto err1;
 
        r = dsi_display_init_dsi(dssdev);
        if (r)
-               goto err3;
-
-       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-       dsi.use_ext_te = dssdev->phy.dsi.ext_te;
-       r = dsi_set_te(dssdev, dsi.te_enabled);
-       if (r)
-               goto err4;
-
-       dsi_set_update_mode(dssdev, dsi.user_update_mode);
+               goto err2;
 
-       dsi_bus_unlock();
        mutex_unlock(&dsi.lock);
 
        return 0;
 
-err4:
-
-       dsi_display_uninit_dsi(dssdev);
-err3:
-       dsi_display_uninit_dispc(dssdev);
 err2:
+       dsi_display_uninit_dispc(dssdev);
+err1:
        enable_clocks(0);
        dsi_enable_pll_clock(0);
-err1:
        omap_dss_stop_device(dssdev);
 err0:
-       dsi_bus_unlock();
        mutex_unlock(&dsi.lock);
        DSSDBG("dsi_display_enable FAILED\n");
        return r;
 }
+EXPORT_SYMBOL(omapdss_dsi_display_enable);
 
-static void dsi_display_disable(struct omap_dss_device *dssdev)
+void omapdss_dsi_display_disable(struct omap_dss_device *dssdev)
 {
        DSSDBG("dsi_display_disable\n");
 
-       mutex_lock(&dsi.lock);
-       dsi_bus_lock();
-
-       if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
-                       dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
-               goto end;
-
-       dsi.update_mode = OMAP_DSS_UPDATE_DISABLED;
-       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-
-       dsi_display_uninit_dispc(dssdev);
-
-       dsi_display_uninit_dsi(dssdev);
-
-       enable_clocks(0);
-       dsi_enable_pll_clock(0);
-
-       omap_dss_stop_device(dssdev);
-end:
-       dsi_bus_unlock();
-       mutex_unlock(&dsi.lock);
-}
-
-static int dsi_display_suspend(struct omap_dss_device *dssdev)
-{
-       DSSDBG("dsi_display_suspend\n");
+       WARN_ON(!dsi_bus_is_locked());
 
        mutex_lock(&dsi.lock);
-       dsi_bus_lock();
-
-       if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
-                       dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
-               goto end;
-
-       dsi.update_mode = OMAP_DSS_UPDATE_DISABLED;
-       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
 
        dsi_display_uninit_dispc(dssdev);
 
@@ -3396,312 +3233,19 @@ static int dsi_display_suspend(struct omap_dss_device *dssdev)
 
        enable_clocks(0);
        dsi_enable_pll_clock(0);
-end:
-       dsi_bus_unlock();
-       mutex_unlock(&dsi.lock);
-
-       return 0;
-}
-
-static int dsi_display_resume(struct omap_dss_device *dssdev)
-{
-       int r;
-
-       DSSDBG("dsi_display_resume\n");
-
-       mutex_lock(&dsi.lock);
-       dsi_bus_lock();
-
-       if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
-               DSSERR("dssdev not suspended\n");
-               r = -EINVAL;
-               goto err0;
-       }
-
-       enable_clocks(1);
-       dsi_enable_pll_clock(1);
-
-       r = _dsi_reset();
-       if (r)
-               goto err1;
-
-       dsi_core_init();
-
-       r = dsi_display_init_dispc(dssdev);
-       if (r)
-               goto err1;
-
-       r = dsi_display_init_dsi(dssdev);
-       if (r)
-               goto err2;
-
-       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-       r = dsi_set_te(dssdev, dsi.te_enabled);
-       if (r)
-               goto err2;
-
-       dsi_set_update_mode(dssdev, dsi.user_update_mode);
-
-       dsi_bus_unlock();
-       mutex_unlock(&dsi.lock);
-
-       return 0;
-
-err2:
-       dsi_display_uninit_dispc(dssdev);
-err1:
-       enable_clocks(0);
-       dsi_enable_pll_clock(0);
-err0:
-       dsi_bus_unlock();
-       mutex_unlock(&dsi.lock);
-       DSSDBG("dsi_display_resume FAILED\n");
-       return r;
-}
-
-static int dsi_display_update(struct omap_dss_device *dssdev,
-                       u16 x, u16 y, u16 w, u16 h)
-{
-       int r = 0;
-       u16 dw, dh;
-
-       DSSDBG("dsi_display_update(%d,%d %dx%d)\n", x, y, w, h);
 
-       mutex_lock(&dsi.lock);
-
-       if (dsi.update_mode != OMAP_DSS_UPDATE_MANUAL)
-               goto end;
-
-       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
-               goto end;
-
-       dssdev->get_resolution(dssdev, &dw, &dh);
-
-       if  (x > dw || y > dh)
-               goto end;
-
-       if (x + w > dw)
-               w = dw - x;
-
-       if (y + h > dh)
-               h = dh - y;
-
-       if (w == 0 || h == 0)
-               goto end;
-
-       if (w == 1) {
-               r = -EINVAL;
-               goto end;
-       }
-
-       dsi_set_update_region(dssdev, x, y, w, h);
-
-       wake_up(&dsi.waitqueue);
-
-end:
-       mutex_unlock(&dsi.lock);
-
-       return r;
-}
-
-static int dsi_display_sync(struct omap_dss_device *dssdev)
-{
-       bool wait;
-
-       DSSDBG("dsi_display_sync()\n");
-
-       mutex_lock(&dsi.lock);
-       dsi_bus_lock();
-
-       if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL &&
-                       dsi.update_region.dirty) {
-               INIT_COMPLETION(dsi.update_completion);
-               wait = true;
-       } else {
-               wait = false;
-       }
-
-       dsi_bus_unlock();
-       mutex_unlock(&dsi.lock);
-
-       if (wait)
-               wait_for_completion_interruptible(&dsi.update_completion);
-
-       DSSDBG("dsi_display_sync() done\n");
-       return 0;
-}
-
-static int dsi_display_set_update_mode(struct omap_dss_device *dssdev,
-               enum omap_dss_update_mode mode)
-{
-       int r = 0;
-
-       DSSDBGF("%d", mode);
-
-       mutex_lock(&dsi.lock);
-       dsi_bus_lock();
-
-       dsi.user_update_mode = mode;
-       r = dsi_set_update_mode(dssdev, mode);
+       omap_dss_stop_device(dssdev);
 
-       dsi_bus_unlock();
        mutex_unlock(&dsi.lock);
-
-       return r;
 }
+EXPORT_SYMBOL(omapdss_dsi_display_disable);
 
-static enum omap_dss_update_mode dsi_display_get_update_mode(
-               struct omap_dss_device *dssdev)
+int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
 {
-       return dsi.update_mode;
-}
-
-
-static int dsi_display_enable_te(struct omap_dss_device *dssdev, bool enable)
-{
-       int r = 0;
-
-       DSSDBGF("%d", enable);
-
-       if (!dssdev->driver->enable_te)
-               return -ENOENT;
-
-       dsi_bus_lock();
-
        dsi.te_enabled = enable;
-
-       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
-               goto end;
-
-       r = dsi_set_te(dssdev, enable);
-end:
-       dsi_bus_unlock();
-
-       return r;
-}
-
-static int dsi_display_get_te(struct omap_dss_device *dssdev)
-{
-       return dsi.te_enabled;
-}
-
-static int dsi_display_set_rotate(struct omap_dss_device *dssdev, u8 rotate)
-{
-
-       DSSDBGF("%d", rotate);
-
-       if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
-               return -EINVAL;
-
-       dsi_bus_lock();
-       dssdev->driver->set_rotate(dssdev, rotate);
-       if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) {
-               u16 w, h;
-               /* the display dimensions may have changed, so set a new
-                * update region */
-               dssdev->get_resolution(dssdev, &w, &h);
-               dsi_set_update_region(dssdev, 0, 0, w, h);
-       }
-       dsi_bus_unlock();
-
        return 0;
 }
-
-static u8 dsi_display_get_rotate(struct omap_dss_device *dssdev)
-{
-       if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
-               return 0;
-
-       return dssdev->driver->get_rotate(dssdev);
-}
-
-static int dsi_display_set_mirror(struct omap_dss_device *dssdev, bool mirror)
-{
-       DSSDBGF("%d", mirror);
-
-       if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
-               return -EINVAL;
-
-       dsi_bus_lock();
-       dssdev->driver->set_mirror(dssdev, mirror);
-       dsi_bus_unlock();
-
-       return 0;
-}
-
-static bool dsi_display_get_mirror(struct omap_dss_device *dssdev)
-{
-       if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
-               return 0;
-
-       return dssdev->driver->get_mirror(dssdev);
-}
-
-static int dsi_display_run_test(struct omap_dss_device *dssdev, int test_num)
-{
-       int r;
-
-       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
-               return -EIO;
-
-       DSSDBGF("%d", test_num);
-
-       dsi_bus_lock();
-
-       /* run test first in low speed mode */
-       dsi_vc_enable_hs(0, 0);
-
-       if (dssdev->driver->run_test) {
-               r = dssdev->driver->run_test(dssdev, test_num);
-               if (r)
-                       goto end;
-       }
-
-       /* then in high speed */
-       dsi_vc_enable_hs(0, 1);
-
-       if (dssdev->driver->run_test) {
-               r = dssdev->driver->run_test(dssdev, test_num);
-               if (r)
-                       goto end;
-       }
-
-end:
-       dsi_vc_enable_hs(0, 1);
-
-       dsi_bus_unlock();
-
-       return r;
-}
-
-static int dsi_display_memory_read(struct omap_dss_device *dssdev,
-               void *buf, size_t size,
-               u16 x, u16 y, u16 w, u16 h)
-{
-       int r;
-
-       DSSDBGF("");
-
-       if (!dssdev->driver->memory_read)
-               return -EINVAL;
-
-       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
-               return -EIO;
-
-       dsi_bus_lock();
-
-       r = dssdev->driver->memory_read(dssdev, buf, size,
-                       x, y, w, h);
-
-       /* Memory read usually changes the update area. This will
-        * force the next update to re-set the update area */
-       dsi.active_update_region.dirty = true;
-
-       dsi_bus_unlock();
-
-       return r;
-}
+EXPORT_SYMBOL(omapdss_dsi_enable_te);
 
 void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
                u32 fifo_size, enum omap_burst_size *burst_size,
@@ -3720,26 +3264,6 @@ int dsi_init_display(struct omap_dss_device *dssdev)
 {
        DSSDBG("DSI init\n");
 
-       dssdev->enable = dsi_display_enable;
-       dssdev->disable = dsi_display_disable;
-       dssdev->suspend = dsi_display_suspend;
-       dssdev->resume = dsi_display_resume;
-       dssdev->update = dsi_display_update;
-       dssdev->sync = dsi_display_sync;
-       dssdev->set_update_mode = dsi_display_set_update_mode;
-       dssdev->get_update_mode = dsi_display_get_update_mode;
-       dssdev->enable_te = dsi_display_enable_te;
-       dssdev->get_te = dsi_display_get_te;
-
-       dssdev->get_rotate = dsi_display_get_rotate;
-       dssdev->set_rotate = dsi_display_set_rotate;
-
-       dssdev->get_mirror = dsi_display_get_mirror;
-       dssdev->set_mirror = dsi_display_set_mirror;
-
-       dssdev->run_test = dsi_display_run_test;
-       dssdev->memory_read = dsi_display_memory_read;
-
        /* XXX these should be figured out dynamically */
        dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
                OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
@@ -3754,9 +3278,6 @@ int dsi_init(struct platform_device *pdev)
 {
        u32 rev;
        int r;
-       struct sched_param param = {
-               .sched_priority = MAX_USER_RT_PRIO-1
-       };
 
        spin_lock_init(&dsi.errors_lock);
        dsi.errors = 0;
@@ -3767,31 +3288,19 @@ int dsi_init(struct platform_device *pdev)
 #endif
 
        init_completion(&dsi.bta_completion);
-       init_completion(&dsi.update_completion);
-
-       dsi.thread = kthread_create(dsi_update_thread, NULL, "dsi");
-       if (IS_ERR(dsi.thread)) {
-               DSSERR("cannot create kthread\n");
-               r = PTR_ERR(dsi.thread);
-               goto err0;
-       }
-       sched_setscheduler(dsi.thread, SCHED_FIFO, &param);
-
-       init_waitqueue_head(&dsi.waitqueue);
-       spin_lock_init(&dsi.update_lock);
 
        mutex_init(&dsi.lock);
-       mutex_init(&dsi.bus_lock);
+       sema_init(&dsi.bus_lock, 1);
+
+       INIT_WORK(&dsi.framedone_work, dsi_framedone_work_callback);
+       INIT_DELAYED_WORK_DEFERRABLE(&dsi.framedone_timeout_work,
+                       dsi_framedone_timeout_work_callback);
 
 #ifdef DSI_CATCH_MISSING_TE
        init_timer(&dsi.te_timer);
        dsi.te_timer.function = dsi_te_timeout;
        dsi.te_timer.data = 0;
 #endif
-
-       dsi.update_mode = OMAP_DSS_UPDATE_DISABLED;
-       dsi.user_update_mode = OMAP_DSS_UPDATE_DISABLED;
-
        dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS);
        if (!dsi.base) {
                DSSERR("can't ioremap DSI\n");
@@ -3799,7 +3308,7 @@ int dsi_init(struct platform_device *pdev)
                goto err1;
        }
 
-       dsi.vdds_dsi_reg = regulator_get(&pdev->dev, "vdds_dsi");
+       dsi.vdds_dsi_reg = dss_get_vdds_dsi();
        if (IS_ERR(dsi.vdds_dsi_reg)) {
                iounmap(dsi.base);
                DSSERR("can't get VDDS_DSI regulator\n");
@@ -3815,23 +3324,15 @@ int dsi_init(struct platform_device *pdev)
 
        enable_clocks(0);
 
-       wake_up_process(dsi.thread);
-
        return 0;
 err2:
        iounmap(dsi.base);
 err1:
-       kthread_stop(dsi.thread);
-err0:
        return r;
 }
 
 void dsi_exit(void)
 {
-       kthread_stop(dsi.thread);
-
-       regulator_put(dsi.vdds_dsi_reg);
-
        iounmap(dsi.base);
 
        DSSDBG("omap_dsi_exit\n");
index 0a26b7d..8254a42 100644 (file)
@@ -68,6 +68,9 @@ static struct {
        struct dss_clock_info cache_dss_cinfo;
        struct dispc_clock_info cache_dispc_cinfo;
 
+       enum dss_clk_source dsi_clk_source;
+       enum dss_clk_source dispc_clk_source;
+
        u32             ctx[DSS_SZ_REGS / sizeof(u32)];
 } dss;
 
@@ -247,23 +250,42 @@ void dss_dump_regs(struct seq_file *s)
 #undef DUMPREG
 }
 
-void dss_select_clk_source(bool dsi, bool dispc)
+void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
+{
+       int b;
+
+       BUG_ON(clk_src != DSS_SRC_DSI1_PLL_FCLK &&
+                       clk_src != DSS_SRC_DSS1_ALWON_FCLK);
+
+       b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1;
+
+       REG_FLD_MOD(DSS_CONTROL, b, 0, 0);      /* DISPC_CLK_SWITCH */
+
+       dss.dispc_clk_source = clk_src;
+}
+
+void dss_select_dsi_clk_source(enum dss_clk_source clk_src)
 {
-       u32 r;
-       r = dss_read_reg(DSS_CONTROL);
-       r = FLD_MOD(r, dsi, 1, 1);      /* DSI_CLK_SWITCH */
-       r = FLD_MOD(r, dispc, 0, 0);    /* DISPC_CLK_SWITCH */
-       dss_write_reg(DSS_CONTROL, r);
+       int b;
+
+       BUG_ON(clk_src != DSS_SRC_DSI2_PLL_FCLK &&
+                       clk_src != DSS_SRC_DSS1_ALWON_FCLK);
+
+       b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1;
+
+       REG_FLD_MOD(DSS_CONTROL, b, 1, 1);      /* DSI_CLK_SWITCH */
+
+       dss.dsi_clk_source = clk_src;
 }
 
-int dss_get_dsi_clk_source(void)
+enum dss_clk_source dss_get_dispc_clk_source(void)
 {
-       return FLD_GET(dss_read_reg(DSS_CONTROL), 1, 1);
+       return dss.dispc_clk_source;
 }
 
-int dss_get_dispc_clk_source(void)
+enum dss_clk_source dss_get_dsi_clk_source(void)
 {
-       return FLD_GET(dss_read_reg(DSS_CONTROL), 0, 0);
+       return dss.dsi_clk_source;
 }
 
 /* calculate clock rates using dividers in cinfo */
index 2bcb124..24326a5 100644 (file)
@@ -119,6 +119,12 @@ enum dss_clock {
        DSS_CLK_96M     = 1 << 4,
 };
 
+enum dss_clk_source {
+       DSS_SRC_DSI1_PLL_FCLK,
+       DSS_SRC_DSI2_PLL_FCLK,
+       DSS_SRC_DSS1_ALWON_FCLK,
+};
+
 struct dss_clock_info {
        /* rates that we get with dividers below */
        unsigned long fck;
@@ -169,6 +175,9 @@ unsigned long dss_clk_get_rate(enum dss_clock clk);
 int dss_need_ctx_restore(void);
 void dss_dump_clocks(struct seq_file *s);
 struct bus_type *dss_get_bus(void);
+struct regulator *dss_get_vdds_dsi(void);
+struct regulator *dss_get_vdds_sdi(void);
+struct regulator *dss_get_vdda_dac(void);
 
 /* display */
 int dss_suspend_all_devices(void);
@@ -216,9 +225,11 @@ void dss_sdi_init(u8 datapairs);
 int dss_sdi_enable(void);
 void dss_sdi_disable(void);
 
-void dss_select_clk_source(bool dsi, bool dispc);
-int dss_get_dsi_clk_source(void);
-int dss_get_dispc_clk_source(void);
+void dss_select_dispc_clk_source(enum dss_clk_source clk_src);
+void dss_select_dsi_clk_source(enum dss_clk_source clk_src);
+enum dss_clk_source dss_get_dispc_clk_source(void);
+enum dss_clk_source dss_get_dsi_clk_source(void);
+
 void dss_set_venc_output(enum omap_dss_venc_type type);
 void dss_set_dac_pwrdn_bgz(bool enable);
 
@@ -261,7 +272,7 @@ void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
                u32 *fifo_low, u32 *fifo_high);
 
 /* DPI */
-int dpi_init(void);
+int dpi_init(struct platform_device *pdev);
 void dpi_exit(void);
 int dpi_init_display(struct omap_dss_device *dssdev);
 
@@ -313,8 +324,8 @@ int dispc_setup_plane(enum omap_plane plane,
 
 bool dispc_go_busy(enum omap_channel channel);
 void dispc_go(enum omap_channel channel);
-void dispc_enable_lcd_out(bool enable);
-void dispc_enable_digit_out(bool enable);
+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);
 
index 27d9c46..913142d 100644 (file)
@@ -501,6 +501,19 @@ static int omap_dss_unset_device(struct omap_overlay_manager *mgr)
        return 0;
 }
 
+static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
+{
+       unsigned long timeout = msecs_to_jiffies(500);
+       u32 irq;
+
+       if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC)
+               irq = DISPC_IRQ_EVSYNC_ODD;
+       else
+               irq = DISPC_IRQ_VSYNC;
+
+       return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
+}
+
 static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
 {
        unsigned long timeout = msecs_to_jiffies(500);
@@ -509,17 +522,18 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
        u32 irq;
        int r;
        int i;
+       struct omap_dss_device *dssdev = mgr->device;
 
-       if (!mgr->device)
+       if (!dssdev)
                return 0;
 
-       if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) {
+       if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
                irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
                channel = OMAP_DSS_CHANNEL_DIGIT;
        } else {
-               if (mgr->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
+               if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
                        enum omap_dss_update_mode mode;
-                       mode = mgr->device->get_update_mode(mgr->device);
+                       mode = dssdev->driver->get_update_mode(dssdev);
                        if (mode != OMAP_DSS_UPDATE_AUTO)
                                return 0;
 
@@ -592,7 +606,7 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
        } else {
                if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
                        enum omap_dss_update_mode mode;
-                       mode = dssdev->get_update_mode(dssdev);
+                       mode = dssdev->driver->get_update_mode(dssdev);
                        if (mode != OMAP_DSS_UPDATE_AUTO)
                                return 0;
 
@@ -1064,7 +1078,7 @@ void dss_start_update(struct omap_dss_device *dssdev)
                mc->shadow_dirty = false;
        }
 
-       dispc_enable_lcd_out(1);
+       dssdev->manager->enable(dssdev->manager);
 }
 
 static void dss_apply_irq_handler(void *data, u32 mask)
@@ -1196,7 +1210,8 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 
                oc->manual_update =
                        dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
-                       dssdev->get_update_mode(dssdev) != OMAP_DSS_UPDATE_AUTO;
+                       dssdev->driver->get_update_mode(dssdev) !=
+                               OMAP_DSS_UPDATE_AUTO;
 
                ++num_planes_enabled;
        }
@@ -1237,7 +1252,8 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 
                mc->manual_update =
                        dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
-                       dssdev->get_update_mode(dssdev) != OMAP_DSS_UPDATE_AUTO;
+                       dssdev->driver->get_update_mode(dssdev) !=
+                               OMAP_DSS_UPDATE_AUTO;
        }
 
        /* XXX TODO: Try to get fifomerge working. The problem is that it
@@ -1351,6 +1367,18 @@ static void omap_dss_mgr_get_info(struct omap_overlay_manager *mgr,
        *info = mgr->info;
 }
 
+static int dss_mgr_enable(struct omap_overlay_manager *mgr)
+{
+       dispc_enable_channel(mgr->id, 1);
+       return 0;
+}
+
+static int dss_mgr_disable(struct omap_overlay_manager *mgr)
+{
+       dispc_enable_channel(mgr->id, 0);
+       return 0;
+}
+
 static void omap_dss_add_overlay_manager(struct omap_overlay_manager *manager)
 {
        ++num_managers;
@@ -1394,6 +1422,10 @@ int dss_init_overlay_managers(struct platform_device *pdev)
                mgr->set_manager_info = &omap_dss_mgr_set_info;
                mgr->get_manager_info = &omap_dss_mgr_get_info;
                mgr->wait_for_go = &dss_mgr_wait_for_go;
+               mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
+
+               mgr->enable = &dss_mgr_enable;
+               mgr->disable = &dss_mgr_disable;
 
                mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC;
 
index b7f9a73..0c5bea2 100644 (file)
@@ -350,7 +350,7 @@ int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev)
                return -EINVAL;
        }
 
-       dssdev->get_resolution(dssdev, &dw, &dh);
+       dssdev->driver->get_resolution(dssdev, &dw, &dh);
 
        DSSDBG("check_overlay %d: (%d,%d %dx%d -> %dx%d) disp (%dx%d)\n",
                        ovl->id,
index b936495..cc23f53 100644 (file)
@@ -36,8 +36,6 @@
 #include <plat/display.h>
 #include "dss.h"
 
-/*#define MEASURE_PERF*/
-
 #define RFBI_BASE               0x48050800
 
 struct rfbi_reg { u16 idx; };
@@ -66,8 +64,6 @@ struct rfbi_reg { u16 idx; };
 #define RFBI_VSYNC_WIDTH       RFBI_REG(0x0090)
 #define RFBI_HSYNC_WIDTH       RFBI_REG(0x0094)
 
-#define RFBI_CMD_FIFO_LEN_BYTES (16 * sizeof(struct update_param))
-
 #define REG_FLD_MOD(idx, val, start, end) \
        rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end))
 
@@ -102,7 +98,6 @@ enum update_cmd {
 
 static int rfbi_convert_timings(struct rfbi_timings *t);
 static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div);
-static void process_cmd_fifo(void);
 
 static struct {
        void __iomem    *base;
@@ -125,11 +120,6 @@ static struct {
        struct completion cmd_done;
        atomic_t          cmd_fifo_full;
        atomic_t          cmd_pending;
-#ifdef MEASURE_PERF
-       unsigned perf_bytes;
-       ktime_t perf_setup_time;
-       ktime_t perf_start_time;
-#endif
 } rfbi;
 
 struct update_region {
@@ -139,16 +129,6 @@ struct update_region {
        u16     h;
 };
 
-struct update_param {
-       u8 rfbi_module;
-       u8 cmd;
-
-       union {
-               struct update_region r;
-               struct completion *sync;
-       } par;
-};
-
 static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
 {
        __raw_writel(val, rfbi.base + idx.idx);
@@ -321,55 +301,6 @@ void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
 }
 EXPORT_SYMBOL(omap_rfbi_write_pixels);
 
-#ifdef MEASURE_PERF
-static void perf_mark_setup(void)
-{
-       rfbi.perf_setup_time = ktime_get();
-}
-
-static void perf_mark_start(void)
-{
-       rfbi.perf_start_time = ktime_get();
-}
-
-static void perf_show(const char *name)
-{
-       ktime_t t, setup_time, trans_time;
-       u32 total_bytes;
-       u32 setup_us, trans_us, total_us;
-
-       t = ktime_get();
-
-       setup_time = ktime_sub(rfbi.perf_start_time, rfbi.perf_setup_time);
-       setup_us = (u32)ktime_to_us(setup_time);
-       if (setup_us == 0)
-               setup_us = 1;
-
-       trans_time = ktime_sub(t, rfbi.perf_start_time);
-       trans_us = (u32)ktime_to_us(trans_time);
-       if (trans_us == 0)
-               trans_us = 1;
-
-       total_us = setup_us + trans_us;
-
-       total_bytes = rfbi.perf_bytes;
-
-       DSSINFO("%s update %u us + %u us = %u us (%uHz), %u bytes, "
-                       "%u kbytes/sec\n",
-                       name,
-                       setup_us,
-                       trans_us,
-                       total_us,
-                       1000*1000 / total_us,
-                       total_bytes,
-                       total_bytes * 1000 / total_us);
-}
-#else
-#define perf_mark_setup()
-#define perf_mark_start()
-#define perf_show(x)
-#endif
-
 void rfbi_transfer_area(u16 width, u16 height,
                             void (callback)(void *data), void *data)
 {
@@ -382,7 +313,7 @@ void rfbi_transfer_area(u16 width, u16 height,
 
        dispc_set_lcd_size(width, height);
 
-       dispc_enable_lcd_out(1);
+       dispc_enable_channel(OMAP_DSS_CHANNEL_LCD, true);
 
        rfbi.framedone_callback = callback;
        rfbi.framedone_callback_data = data;
@@ -396,8 +327,6 @@ void rfbi_transfer_area(u16 width, u16 height,
        if (!rfbi.te_enabled)
                l = FLD_MOD(l, 1, 4, 4); /* ITE */
 
-       perf_mark_start();
-
        rfbi_write_reg(RFBI_CONTROL, l);
 }
 
@@ -407,8 +336,6 @@ static void framedone_callback(void *data, u32 mask)
 
        DSSDBG("FRAMEDONE\n");
 
-       perf_show("DISPC");
-
        REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0);
 
        rfbi_enable_clocks(0);
@@ -416,11 +343,10 @@ static void framedone_callback(void *data, u32 mask)
        callback = rfbi.framedone_callback;
        rfbi.framedone_callback = NULL;
 
-       /*callback(rfbi.framedone_callback_data);*/
+       if (callback != NULL)
+               callback(rfbi.framedone_callback_data);
 
        atomic_set(&rfbi.cmd_pending, 0);
-
-       process_cmd_fifo();
 }
 
 #if 1 /* VERBOSE */
@@ -937,52 +863,43 @@ int rfbi_configure(int rfbi_module, int bpp, int lines)
 }
 EXPORT_SYMBOL(rfbi_configure);
 
-static int rfbi_find_display(struct omap_dss_device *dssdev)
+int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
+               u16 *x, u16 *y, u16 *w, u16 *h)
 {
-       if (dssdev == rfbi.dssdev[0])
-               return 0;
+       u16 dw, dh;
 
-       if (dssdev == rfbi.dssdev[1])
-               return 1;
+       dssdev->driver->get_resolution(dssdev, &dw, &dh);
 
-       BUG();
-       return -1;
-}
+       if  (*x > dw || *y > dh)
+               return -EINVAL;
 
+       if (*x + *w > dw)
+               return -EINVAL;
 
-static void signal_fifo_waiters(void)
-{
-       if (atomic_read(&rfbi.cmd_fifo_full) > 0) {
-               /* DSSDBG("SIGNALING: Fifo not full for waiter!\n"); */
-               complete(&rfbi.cmd_done);
-               atomic_dec(&rfbi.cmd_fifo_full);
-       }
-}
+       if (*y + *h > dh)
+               return -EINVAL;
 
-/* returns 1 for async op, and 0 for sync op */
-static int do_update(struct omap_dss_device *dssdev, struct update_region *upd)
-{
-       u16 x = upd->x;
-       u16 y = upd->y;
-       u16 w = upd->w;
-       u16 h = upd->h;
+       if (*w == 1)
+               return -EINVAL;
 
-       perf_mark_setup();
+       if (*w == 0 || *h == 0)
+               return -EINVAL;
 
        if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
-               /*dssdev->driver->enable_te(dssdev, 1); */
-               dss_setup_partial_planes(dssdev, &x, &y, &w, &h);
+               dss_setup_partial_planes(dssdev, x, y, w, h);
+               dispc_set_lcd_size(*w, *h);
        }
 
-#ifdef MEASURE_PERF
-       rfbi.perf_bytes = w * h * 2; /* XXX always 16bit */
-#endif
-
-       dssdev->driver->setup_update(dssdev, x, y, w, h);
+       return 0;
+}
+EXPORT_SYMBOL(omap_rfbi_prepare_update);
 
+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(w, h, NULL, NULL);
-               return 1;
+               rfbi_transfer_area(w, h, callback, data);
        } else {
                struct omap_overlay *ovl;
                void __iomem *addr;
@@ -994,123 +911,12 @@ static int do_update(struct omap_dss_device *dssdev, struct update_region *upd)
 
                omap_rfbi_write_pixels(addr, scr_width, x, y, w, h);
 
-               perf_show("L4");
-
-               return 0;
+               callback(data);
        }
-}
-
-static void process_cmd_fifo(void)
-{
-       int len;
-       struct update_param p;
-       struct omap_dss_device *dssdev;
-       unsigned long flags;
-
-       if (atomic_inc_return(&rfbi.cmd_pending) != 1)
-               return;
-
-       while (true) {
-               spin_lock_irqsave(&rfbi.cmd_lock, flags);
-
-               len = kfifo_out(&rfbi.cmd_fifo, (unsigned char *)&p,
-                                 sizeof(struct update_param));
-               if (len == 0) {
-                       DSSDBG("nothing more in fifo\n");
-                       atomic_set(&rfbi.cmd_pending, 0);
-                       spin_unlock_irqrestore(&rfbi.cmd_lock, flags);
-                       break;
-               }
-
-               /* DSSDBG("fifo full %d\n", rfbi.cmd_fifo_full.counter);*/
-
-               spin_unlock_irqrestore(&rfbi.cmd_lock, flags);
-
-               BUG_ON(len != sizeof(struct update_param));
-               BUG_ON(p.rfbi_module > 1);
-
-               dssdev = rfbi.dssdev[p.rfbi_module];
-
-               if (p.cmd == RFBI_CMD_UPDATE) {
-                       if (do_update(dssdev, &p.par.r))
-                               break; /* async op */
-               } else if (p.cmd == RFBI_CMD_SYNC) {
-                       DSSDBG("Signaling SYNC done!\n");
-                       complete(p.par.sync);
-               } else
-                       BUG();
-       }
-
-       signal_fifo_waiters();
-}
 
-static void rfbi_push_cmd(struct update_param *p)
-{
-       int ret;
-
-       while (1) {
-               unsigned long flags;
-               int available;
-
-               spin_lock_irqsave(&rfbi.cmd_lock, flags);
-               available = RFBI_CMD_FIFO_LEN_BYTES -
-                       kfifo_len(&rfbi.cmd_fifo);
-
-/*             DSSDBG("%d bytes left in fifo\n", available); */
-               if (available < sizeof(struct update_param)) {
-                       DSSDBG("Going to wait because FIFO FULL..\n");
-                       spin_unlock_irqrestore(&rfbi.cmd_lock, flags);
-                       atomic_inc(&rfbi.cmd_fifo_full);
-                       wait_for_completion(&rfbi.cmd_done);
-                       /*DSSDBG("Woke up because fifo not full anymore\n");*/
-                       continue;
-               }
-
-               ret = kfifo_in(&rfbi.cmd_fifo, (unsigned char *)p,
-                                 sizeof(struct update_param));
-/*             DSSDBG("pushed %d bytes\n", ret);*/
-
-               spin_unlock_irqrestore(&rfbi.cmd_lock, flags);
-
-               BUG_ON(ret != sizeof(struct update_param));
-
-               break;
-       }
-}
-
-static void rfbi_push_update(int rfbi_module, int x, int y, int w, int h)
-{
-       struct update_param p;
-
-       p.rfbi_module = rfbi_module;
-       p.cmd = RFBI_CMD_UPDATE;
-
-       p.par.r.x = x;
-       p.par.r.y = y;
-       p.par.r.w = w;
-       p.par.r.h = h;
-
-       DSSDBG("RFBI pushed %d,%d %dx%d\n", x, y, w, h);
-
-       rfbi_push_cmd(&p);
-
-       process_cmd_fifo();
-}
-
-static void rfbi_push_sync(int rfbi_module, struct completion *sync_comp)
-{
-       struct update_param p;
-
-       p.rfbi_module = rfbi_module;
-       p.cmd = RFBI_CMD_SYNC;
-       p.par.sync = sync_comp;
-
-       rfbi_push_cmd(&p);
-
-       DSSDBG("RFBI sync pushed to cmd fifo\n");
-
-       process_cmd_fifo();
+       return 0;
 }
+EXPORT_SYMBOL(omap_rfbi_update);
 
 void rfbi_dump_regs(struct seq_file *s)
 {
@@ -1155,12 +961,8 @@ int rfbi_init(void)
 {
        u32 rev;
        u32 l;
-       int r;
 
        spin_lock_init(&rfbi.cmd_lock);
-       r = kfifo_alloc(&rfbi.cmd_fifo, RFBI_CMD_FIFO_LEN_BYTES, GFP_KERNEL);
-       if (r)
-               return r;
 
        init_completion(&rfbi.cmd_done);
        atomic_set(&rfbi.cmd_fifo_full, 0);
@@ -1196,49 +998,10 @@ void rfbi_exit(void)
 {
        DSSDBG("rfbi_exit\n");
 
-       kfifo_free(&rfbi.cmd_fifo);
-
        iounmap(rfbi.base);
 }
 
-/* struct omap_display support */
-static int rfbi_display_update(struct omap_dss_device *dssdev,
-                       u16 x, u16 y, u16 w, u16 h)
-{
-       int rfbi_module;
-
-       if (w == 0 || h == 0)
-               return 0;
-
-       rfbi_module = rfbi_find_display(dssdev);
-
-       rfbi_push_update(rfbi_module, x, y, w, h);
-
-       return 0;
-}
-
-static int rfbi_display_sync(struct omap_dss_device *dssdev)
-{
-       struct completion sync_comp;
-       int rfbi_module;
-
-       rfbi_module = rfbi_find_display(dssdev);
-
-       init_completion(&sync_comp);
-       rfbi_push_sync(rfbi_module, &sync_comp);
-       DSSDBG("Waiting for SYNC to happen...\n");
-       wait_for_completion(&sync_comp);
-       DSSDBG("Released from SYNC\n");
-       return 0;
-}
-
-static int rfbi_display_enable_te(struct omap_dss_device *dssdev, bool enable)
-{
-       dssdev->driver->enable_te(dssdev, enable);
-       return 0;
-}
-
-static int rfbi_display_enable(struct omap_dss_device *dssdev)
+int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
 {
        int r;
 
@@ -1269,41 +1032,25 @@ static int rfbi_display_enable(struct omap_dss_device *dssdev)
                         &dssdev->ctrl.rfbi_timings);
 
 
-       if (dssdev->driver->enable) {
-               r = dssdev->driver->enable(dssdev);
-               if (r)
-                       goto err2;
-       }
-
        return 0;
-err2:
-       omap_dispc_unregister_isr(framedone_callback, NULL,
-                       DISPC_IRQ_FRAMEDONE);
 err1:
        omap_dss_stop_device(dssdev);
 err0:
        return r;
 }
+EXPORT_SYMBOL(omapdss_rfbi_display_enable);
 
-static void rfbi_display_disable(struct omap_dss_device *dssdev)
+void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
 {
-       dssdev->driver->disable(dssdev);
        omap_dispc_unregister_isr(framedone_callback, NULL,
                        DISPC_IRQ_FRAMEDONE);
        omap_dss_stop_device(dssdev);
 }
+EXPORT_SYMBOL(omapdss_rfbi_display_disable);
 
 int rfbi_init_display(struct omap_dss_device *dssdev)
 {
-       dssdev->enable = rfbi_display_enable;
-       dssdev->disable = rfbi_display_disable;
-       dssdev->update = rfbi_display_update;
-       dssdev->sync = rfbi_display_sync;
-       dssdev->enable_te = rfbi_display_enable_te;
-
        rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
-
        dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
-
        return 0;
 }
index c24f307..12eb404 100644 (file)
@@ -41,7 +41,7 @@ static void sdi_basic_init(void)
        dispc_lcd_enable_signal_polarity(1);
 }
 
-static int sdi_display_enable(struct omap_dss_device *dssdev)
+int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
 {
        struct omap_video_timings *t = &dssdev->panel.timings;
        struct dss_clock_info dss_cinfo;
@@ -57,12 +57,6 @@ static int sdi_display_enable(struct omap_dss_device *dssdev)
                goto err0;
        }
 
-       if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
-               DSSERR("dssdev already enabled\n");
-               r = -EINVAL;
-               goto err1;
-       }
-
        /* In case of skip_init sdi_init has already enabled the clocks */
        if (!sdi.skip_init)
                dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
@@ -119,7 +113,7 @@ static int sdi_display_enable(struct omap_dss_device *dssdev)
                mdelay(2);
        }
 
-       dispc_enable_lcd_out(1);
+       dssdev->manager->enable(dssdev->manager);
 
        if (dssdev->driver->enable) {
                r = dssdev->driver->enable(dssdev);
@@ -127,13 +121,11 @@ static int sdi_display_enable(struct omap_dss_device *dssdev)
                        goto err3;
        }
 
-       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
        sdi.skip_init = 0;
 
        return 0;
 err3:
-       dispc_enable_lcd_out(0);
+       dssdev->manager->disable(dssdev->manager);
 err2:
        dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
 err1:
@@ -141,120 +133,27 @@ err1:
 err0:
        return r;
 }
+EXPORT_SYMBOL(omapdss_sdi_display_enable);
 
-static int sdi_display_resume(struct omap_dss_device *dssdev);
-
-static void sdi_display_disable(struct omap_dss_device *dssdev)
+void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
 {
-       if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
-               return;
-
-       if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
-               if (sdi_display_resume(dssdev))
-                       return;
-
        if (dssdev->driver->disable)
                dssdev->driver->disable(dssdev);
 
-       dispc_enable_lcd_out(0);
+       dssdev->manager->disable(dssdev->manager);
 
        dss_sdi_disable();
 
        dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
 
-       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-
        omap_dss_stop_device(dssdev);
 }
-
-static int sdi_display_suspend(struct omap_dss_device *dssdev)
-{
-       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
-               return -EINVAL;
-
-       if (dssdev->driver->suspend)
-               dssdev->driver->suspend(dssdev);
-
-       dispc_enable_lcd_out(0);
-
-       dss_sdi_disable();
-
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
-
-       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
-       return 0;
-}
-
-static int sdi_display_resume(struct omap_dss_device *dssdev)
-{
-       int r;
-
-       if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED)
-               return -EINVAL;
-
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
-
-       r = dss_sdi_enable();
-       if (r)
-               goto err;
-       mdelay(2);
-
-       dispc_enable_lcd_out(1);
-
-       if (dssdev->driver->resume)
-               dssdev->driver->resume(dssdev);
-
-       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-       return 0;
-err:
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
-       return r;
-}
-
-static int sdi_display_set_update_mode(struct omap_dss_device *dssdev,
-               enum omap_dss_update_mode mode)
-{
-       if (mode == OMAP_DSS_UPDATE_MANUAL)
-               return -EINVAL;
-
-       if (mode == OMAP_DSS_UPDATE_DISABLED) {
-               dispc_enable_lcd_out(0);
-               sdi.update_enabled = 0;
-       } else {
-               dispc_enable_lcd_out(1);
-               sdi.update_enabled = 1;
-       }
-
-       return 0;
-}
-
-static enum omap_dss_update_mode sdi_display_get_update_mode(
-               struct omap_dss_device *dssdev)
-{
-       return sdi.update_enabled ? OMAP_DSS_UPDATE_AUTO :
-               OMAP_DSS_UPDATE_DISABLED;
-}
-
-static void sdi_get_timings(struct omap_dss_device *dssdev,
-                       struct omap_video_timings *timings)
-{
-       *timings = dssdev->panel.timings;
-}
+EXPORT_SYMBOL(omapdss_sdi_display_disable);
 
 int sdi_init_display(struct omap_dss_device *dssdev)
 {
        DSSDBG("SDI init\n");
 
-       dssdev->enable = sdi_display_enable;
-       dssdev->disable = sdi_display_disable;
-       dssdev->suspend = sdi_display_suspend;
-       dssdev->resume = sdi_display_resume;
-       dssdev->set_update_mode = sdi_display_set_update_mode;
-       dssdev->get_update_mode = sdi_display_get_update_mode;
-       dssdev->get_timings = sdi_get_timings;
-
        return 0;
 }
 
index 749a5a0..f0ba573 100644 (file)
@@ -400,114 +400,6 @@ static const struct venc_config *venc_timings_to_config(
        BUG();
 }
 
-
-
-
-
-/* driver */
-static int venc_panel_probe(struct omap_dss_device *dssdev)
-{
-       dssdev->panel.timings = omap_dss_pal_timings;
-
-       return 0;
-}
-
-static void venc_panel_remove(struct omap_dss_device *dssdev)
-{
-}
-
-static int venc_panel_enable(struct omap_dss_device *dssdev)
-{
-       int r = 0;
-
-       /* wait couple of vsyncs until enabling the LCD */
-       msleep(50);
-
-       if (dssdev->platform_enable)
-               r = dssdev->platform_enable(dssdev);
-
-       return r;
-}
-
-static void venc_panel_disable(struct omap_dss_device *dssdev)
-{
-       if (dssdev->platform_disable)
-               dssdev->platform_disable(dssdev);
-
-       /* wait at least 5 vsyncs after disabling the LCD */
-
-       msleep(100);
-}
-
-static int venc_panel_suspend(struct omap_dss_device *dssdev)
-{
-       venc_panel_disable(dssdev);
-       return 0;
-}
-
-static int venc_panel_resume(struct omap_dss_device *dssdev)
-{
-       return venc_panel_enable(dssdev);
-}
-
-static struct omap_dss_driver venc_driver = {
-       .probe          = venc_panel_probe,
-       .remove         = venc_panel_remove,
-
-       .enable         = venc_panel_enable,
-       .disable        = venc_panel_disable,
-       .suspend        = venc_panel_suspend,
-       .resume         = venc_panel_resume,
-
-       .driver         = {
-               .name   = "venc",
-               .owner  = THIS_MODULE,
-       },
-};
-/* driver end */
-
-
-
-int venc_init(struct platform_device *pdev)
-{
-       u8 rev_id;
-
-       mutex_init(&venc.venc_lock);
-
-       venc.wss_data = 0;
-
-       venc.base = ioremap(VENC_BASE, SZ_1K);
-       if (!venc.base) {
-               DSSERR("can't ioremap VENC\n");
-               return -ENOMEM;
-       }
-
-       venc.vdda_dac_reg = regulator_get(&pdev->dev, "vdda_dac");
-       if (IS_ERR(venc.vdda_dac_reg)) {
-               iounmap(venc.base);
-               DSSERR("can't get VDDA_DAC regulator\n");
-               return PTR_ERR(venc.vdda_dac_reg);
-       }
-
-       venc_enable_clocks(1);
-
-       rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
-       printk(KERN_INFO "OMAP VENC rev %d\n", rev_id);
-
-       venc_enable_clocks(0);
-
-       return omap_dss_register_driver(&venc_driver);
-}
-
-void venc_exit(void)
-{
-       omap_dss_unregister_driver(&venc_driver);
-
-       regulator_put(venc.vdda_dac_reg);
-
-       iounmap(venc.base);
-}
-
 static void venc_power_on(struct omap_dss_device *dssdev)
 {
        u32 l;
@@ -540,7 +432,7 @@ static void venc_power_on(struct omap_dss_device *dssdev)
        if (dssdev->platform_enable)
                dssdev->platform_enable(dssdev);
 
-       dispc_enable_digit_out(1);
+       dssdev->manager->enable(dssdev->manager);
 }
 
 static void venc_power_off(struct omap_dss_device *dssdev)
@@ -548,7 +440,7 @@ static void venc_power_off(struct omap_dss_device *dssdev)
        venc_write_reg(VENC_OUTPUT_CONTROL, 0);
        dss_set_dac_pwrdn_bgz(0);
 
-       dispc_enable_digit_out(0);
+       dssdev->manager->disable(dssdev->manager);
 
        if (dssdev->platform_disable)
                dssdev->platform_disable(dssdev);
@@ -558,7 +450,23 @@ static void venc_power_off(struct omap_dss_device *dssdev)
        venc_enable_clocks(0);
 }
 
-static int venc_enable_display(struct omap_dss_device *dssdev)
+
+
+
+
+/* driver */
+static int venc_panel_probe(struct omap_dss_device *dssdev)
+{
+       dssdev->panel.timings = omap_dss_pal_timings;
+
+       return 0;
+}
+
+static void venc_panel_remove(struct omap_dss_device *dssdev)
+{
+}
+
+static int venc_panel_enable(struct omap_dss_device *dssdev)
 {
        int r = 0;
 
@@ -568,7 +476,13 @@ static int venc_enable_display(struct omap_dss_device *dssdev)
 
        if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
                r = -EINVAL;
-               goto err;
+               goto err1;
+       }
+
+       if (dssdev->platform_enable) {
+               r = dssdev->platform_enable(dssdev);
+               if (r)
+                       goto err2;
        }
 
        venc_power_on(dssdev);
@@ -576,13 +490,21 @@ static int venc_enable_display(struct omap_dss_device *dssdev)
        venc.wss_data = 0;
 
        dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-err:
+
+       /* wait couple of vsyncs until enabling the LCD */
+       msleep(50);
+
        mutex_unlock(&venc.venc_lock);
 
+       return r;
+err2:
+       venc_power_off(dssdev);
+err1:
+       mutex_unlock(&venc.venc_lock);
        return r;
 }
 
-static void venc_disable_display(struct omap_dss_device *dssdev)
+static void venc_panel_disable(struct omap_dss_device *dssdev)
 {
        DSSDBG("venc_disable_display\n");
 
@@ -599,53 +521,40 @@ static void venc_disable_display(struct omap_dss_device *dssdev)
 
        venc_power_off(dssdev);
 
+       /* wait at least 5 vsyncs after disabling the LCD */
+       msleep(100);
+
+       if (dssdev->platform_disable)
+               dssdev->platform_disable(dssdev);
+
        dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 end:
        mutex_unlock(&venc.venc_lock);
 }
 
-static int venc_display_suspend(struct omap_dss_device *dssdev)
+static int venc_panel_suspend(struct omap_dss_device *dssdev)
 {
-       int r = 0;
-
-       DSSDBG("venc_display_suspend\n");
-
-       mutex_lock(&venc.venc_lock);
-
-       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
-               r = -EINVAL;
-               goto err;
-       }
-
-       venc_power_off(dssdev);
-
-       dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-err:
-       mutex_unlock(&venc.venc_lock);
-
-       return r;
+       venc_panel_disable(dssdev);
+       return 0;
 }
 
-static int venc_display_resume(struct omap_dss_device *dssdev)
+static int venc_panel_resume(struct omap_dss_device *dssdev)
 {
-       int r = 0;
-
-       DSSDBG("venc_display_resume\n");
-
-       mutex_lock(&venc.venc_lock);
-
-       if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
-               r = -EINVAL;
-               goto err;
-       }
-
-       venc_power_on(dssdev);
+       return venc_panel_enable(dssdev);
+}
 
-       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-err:
-       mutex_unlock(&venc.venc_lock);
+static enum omap_dss_update_mode venc_get_update_mode(
+               struct omap_dss_device *dssdev)
+{
+       return OMAP_DSS_UPDATE_AUTO;
+}
 
-       return r;
+static int venc_set_update_mode(struct omap_dss_device *dssdev,
+               enum omap_dss_update_mode mode)
+{
+       if (mode != OMAP_DSS_UPDATE_AUTO)
+               return -EINVAL;
+       return 0;
 }
 
 static void venc_get_timings(struct omap_dss_device *dssdev,
@@ -666,8 +575,8 @@ static void venc_set_timings(struct omap_dss_device *dssdev,
        dssdev->panel.timings = *timings;
        if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
                /* turn the venc off and on to get new timings to use */
-               venc_disable_display(dssdev);
-               venc_enable_display(dssdev);
+               venc_panel_disable(dssdev);
+               venc_panel_enable(dssdev);
        }
 }
 
@@ -716,30 +625,79 @@ static int venc_set_wss(struct omap_dss_device *dssdev,   u32 wss)
        return 0;
 }
 
-static enum omap_dss_update_mode venc_display_get_update_mode(
-               struct omap_dss_device *dssdev)
+static struct omap_dss_driver venc_driver = {
+       .probe          = venc_panel_probe,
+       .remove         = venc_panel_remove,
+
+       .enable         = venc_panel_enable,
+       .disable        = venc_panel_disable,
+       .suspend        = venc_panel_suspend,
+       .resume         = venc_panel_resume,
+
+       .get_resolution = omapdss_default_get_resolution,
+       .get_recommended_bpp = omapdss_default_get_recommended_bpp,
+
+       .set_update_mode = venc_set_update_mode,
+       .get_update_mode = venc_get_update_mode,
+
+       .get_timings    = venc_get_timings,
+       .set_timings    = venc_set_timings,
+       .check_timings  = venc_check_timings,
+
+       .get_wss        = venc_get_wss,
+       .set_wss        = venc_set_wss,
+
+       .driver         = {
+               .name   = "venc",
+               .owner  = THIS_MODULE,
+       },
+};
+/* driver end */
+
+
+
+int venc_init(struct platform_device *pdev)
 {
-       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
-               return OMAP_DSS_UPDATE_AUTO;
-       else
-               return OMAP_DSS_UPDATE_DISABLED;
+       u8 rev_id;
+
+       mutex_init(&venc.venc_lock);
+
+       venc.wss_data = 0;
+
+       venc.base = ioremap(VENC_BASE, SZ_1K);
+       if (!venc.base) {
+               DSSERR("can't ioremap VENC\n");
+               return -ENOMEM;
+       }
+
+       venc.vdda_dac_reg = dss_get_vdda_dac();
+       if (IS_ERR(venc.vdda_dac_reg)) {
+               iounmap(venc.base);
+               DSSERR("can't get VDDA_DAC regulator\n");
+               return PTR_ERR(venc.vdda_dac_reg);
+       }
+
+       venc_enable_clocks(1);
+
+       rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
+       printk(KERN_INFO "OMAP VENC rev %d\n", rev_id);
+
+       venc_enable_clocks(0);
+
+       return omap_dss_register_driver(&venc_driver);
+}
+
+void venc_exit(void)
+{
+       omap_dss_unregister_driver(&venc_driver);
+
+       iounmap(venc.base);
 }
 
 int venc_init_display(struct omap_dss_device *dssdev)
 {
        DSSDBG("init_display\n");
 
-       dssdev->enable = venc_enable_display;
-       dssdev->disable = venc_disable_display;
-       dssdev->suspend = venc_display_suspend;
-       dssdev->resume = venc_display_resume;
-       dssdev->get_timings = venc_get_timings;
-       dssdev->set_timings = venc_set_timings;
-       dssdev->check_timings = venc_check_timings;
-       dssdev->get_wss = venc_get_wss;
-       dssdev->set_wss = venc_set_wss;
-       dssdev->get_update_mode = venc_display_get_update_mode;
-
        return 0;
 }
 
index bb694cc..43496d6 100644 (file)
@@ -16,16 +16,7 @@ config FB_OMAP2_DEBUG_SUPPORT
        depends on FB_OMAP2
        help
          Support for debug output. You have to enable the actual printing
-         with debug module parameter.
-
-config FB_OMAP2_FORCE_AUTO_UPDATE
-       bool "Force main display to automatic update mode"
-       depends on FB_OMAP2
-       help
-         Forces main display to automatic update mode (if possible),
-         and also enables tearsync (if possible). By default
-         displays that support manual update are started in manual
-         update mode.
+         with 'debug' module parameter.
 
 config FB_OMAP2_NUM_FBS
        int "Number of framebuffers"
index 4c4bafd..1ffa760 100644 (file)
@@ -167,12 +167,12 @@ static int omapfb_update_window_nolock(struct fb_info *fbi,
        if (w == 0 || h == 0)
                return 0;
 
-       display->get_resolution(display, &dw, &dh);
+       display->driver->get_resolution(display, &dw, &dh);
 
        if (x + w > dw || y + h > dh)
                return -EINVAL;
 
-       return display->update(display, x, y, w, h);
+       return display->driver->update(display, x, y, w, h);
 }
 
 /* This function is exported for SGX driver use */
@@ -202,7 +202,7 @@ static int omapfb_set_update_mode(struct fb_info *fbi,
        enum omap_dss_update_mode um;
        int r;
 
-       if (!display || !display->set_update_mode)
+       if (!display || !display->driver->set_update_mode)
                return -EINVAL;
 
        switch (mode) {
@@ -222,7 +222,7 @@ static int omapfb_set_update_mode(struct fb_info *fbi,
                return -EINVAL;
        }
 
-       r = display->set_update_mode(display, um);
+       r = display->driver->set_update_mode(display, um);
 
        return r;
 }
@@ -233,10 +233,15 @@ static int omapfb_get_update_mode(struct fb_info *fbi,
        struct omap_dss_device *display = fb2display(fbi);
        enum omap_dss_update_mode m;
 
-       if (!display || !display->get_update_mode)
+       if (!display)
                return -EINVAL;
 
-       m = display->get_update_mode(display);
+       if (!display->driver->get_update_mode) {
+               *mode = OMAPFB_AUTO_UPDATE;
+               return 0;
+       }
+
+       m = display->driver->get_update_mode(display);
 
        switch (m) {
        case OMAP_DSS_UPDATE_DISABLED:
@@ -374,7 +379,7 @@ static int omapfb_memory_read(struct fb_info *fbi,
        void *buf;
        int r;
 
-       if (!display || !display->memory_read)
+       if (!display || !display->driver->memory_read)
                return -ENOENT;
 
        if (!access_ok(VERIFY_WRITE, mr->buffer, mr->buffer_size))
@@ -389,7 +394,7 @@ static int omapfb_memory_read(struct fb_info *fbi,
                return -ENOMEM;
        }
 
-       r = display->memory_read(display, buf, mr->buffer_size,
+       r = display->driver->memory_read(display, buf, mr->buffer_size,
                        mr->x, mr->y, mr->w, mr->h);
 
        if (r > 0) {
@@ -483,6 +488,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
                struct omapfb_memory_read       memory_read;
                struct omapfb_vram_info         vram_info;
                struct omapfb_tearsync_info     tearsync_info;
+               struct omapfb_display_info      display_info;
        } p;
 
        int r = 0;
@@ -490,18 +496,18 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
        switch (cmd) {
        case OMAPFB_SYNC_GFX:
                DBG("ioctl SYNC_GFX\n");
-               if (!display || !display->sync) {
+               if (!display || !display->driver->sync) {
                        /* DSS1 never returns an error here, so we neither */
                        /*r = -EINVAL;*/
                        break;
                }
 
-               r = display->sync(display);
+               r = display->driver->sync(display);
                break;
 
        case OMAPFB_UPDATE_WINDOW_OLD:
                DBG("ioctl UPDATE_WINDOW_OLD\n");
-               if (!display || !display->update) {
+               if (!display || !display->driver->update) {
                        r = -EINVAL;
                        break;
                }
@@ -519,7 +525,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
 
        case OMAPFB_UPDATE_WINDOW:
                DBG("ioctl UPDATE_WINDOW\n");
-               if (!display || !display->update) {
+               if (!display || !display->driver->update) {
                        r = -EINVAL;
                        break;
                }
@@ -648,7 +654,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
                        break;
                }
 
-               r = display->wait_vsync(display);
+               r = display->manager->wait_for_vsync(display->manager);
                break;
 
        case OMAPFB_WAITFORGO:
@@ -669,12 +675,12 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
                        r = -EFAULT;
                        break;
                }
-               if (!display || !display->run_test) {
+               if (!display || !display->driver->run_test) {
                        r = -EINVAL;
                        break;
                }
 
-               r = display->run_test(display, p.test_num);
+               r = display->driver->run_test(display, p.test_num);
 
                break;
 
@@ -684,12 +690,12 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
                        r = -EFAULT;
                        break;
                }
-               if (!display || !display->run_test) {
+               if (!display || !display->driver->run_test) {
                        r = -EINVAL;
                        break;
                }
 
-               r = display->run_test(display, p.test_num);
+               r = display->driver->run_test(display, p.test_num);
 
                break;
 
@@ -731,13 +737,37 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
                        break;
                }
 
-               if (!display->enable_te) {
+               if (!display->driver->enable_te) {
                        r = -ENODEV;
                        break;
                }
 
-               r = display->enable_te(display, !!p.tearsync_info.enabled);
+               r = display->driver->enable_te(display,
+                               !!p.tearsync_info.enabled);
+
+               break;
+       }
+
+       case OMAPFB_GET_DISPLAY_INFO: {
+               u16 xres, yres;
 
+               DBG("ioctl GET_DISPLAY_INFO\n");
+
+               if (display == NULL) {
+                       r = -ENODEV;
+                       break;
+               }
+
+               display->driver->get_resolution(display, &xres, &yres);
+
+               p.display_info.xres = xres;
+               p.display_info.yres = yres;
+               p.display_info.width = 0;
+               p.display_info.height = 0;
+
+               if (copy_to_user((void __user *)arg, &p.display_info,
+                                       sizeof(p.display_info)))
+                       r = -EFAULT;
                break;
        }
 
index d17caef..4a76917 100644 (file)
@@ -54,6 +54,8 @@ module_param_named(test, omapfb_test_pattern, bool, 0644);
 #endif
 
 static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi);
+static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
+               struct omap_dss_device *dssdev);
 
 #ifdef DEBUG
 static void draw_pixel(struct fb_info *fbi, int x, int y, unsigned color)
@@ -152,9 +154,9 @@ static void fill_fb(struct fb_info *fbi)
 }
 #endif
 
-static unsigned omapfb_get_vrfb_offset(struct omapfb_info *ofbi, int rot)
+static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot)
 {
-       struct vrfb *vrfb = &ofbi->region.vrfb;
+       const struct vrfb *vrfb = &ofbi->region.vrfb;
        unsigned offset;
 
        switch (rot) {
@@ -179,7 +181,7 @@ static unsigned omapfb_get_vrfb_offset(struct omapfb_info *ofbi, int rot)
        return offset;
 }
 
-static u32 omapfb_get_region_rot_paddr(struct omapfb_info *ofbi, int rot)
+static u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot)
 {
        if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
                return ofbi->region.vrfb.paddr[rot]
@@ -189,7 +191,7 @@ static u32 omapfb_get_region_rot_paddr(struct omapfb_info *ofbi, int rot)
        }
 }
 
-static u32 omapfb_get_region_paddr(struct omapfb_info *ofbi)
+static u32 omapfb_get_region_paddr(const struct omapfb_info *ofbi)
 {
        if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
                return ofbi->region.vrfb.paddr[0];
@@ -197,7 +199,7 @@ static u32 omapfb_get_region_paddr(struct omapfb_info *ofbi)
                return ofbi->region.paddr;
 }
 
-static void __iomem *omapfb_get_region_vaddr(struct omapfb_info *ofbi)
+static void __iomem *omapfb_get_region_vaddr(const struct omapfb_info *ofbi)
 {
        if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
                return ofbi->region.vrfb.vaddr[0];
@@ -703,9 +705,9 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
        var->width              = -1;
        var->grayscale          = 0;
 
-       if (display && display->get_timings) {
+       if (display && display->driver->get_timings) {
                struct omap_video_timings timings;
-               display->get_timings(display, &timings);
+               display->driver->get_timings(display, &timings);
 
                /* pixclock in ps, the rest in pixclock */
                var->pixclock = timings.pixel_clock != 0 ?
@@ -778,8 +780,8 @@ static int omapfb_release(struct fb_info *fbi, int user)
        return 0;
 }
 
-static unsigned calc_rotation_offset_dma(struct fb_var_screeninfo *var,
-               struct fb_fix_screeninfo *fix, int rotation)
+static unsigned calc_rotation_offset_dma(const struct fb_var_screeninfo *var,
+               const struct fb_fix_screeninfo *fix, int rotation)
 {
        unsigned offset;
 
@@ -789,8 +791,8 @@ static unsigned calc_rotation_offset_dma(struct fb_var_screeninfo *var,
        return offset;
 }
 
-static unsigned calc_rotation_offset_vrfb(struct fb_var_screeninfo *var,
-               struct fb_fix_screeninfo *fix, int rotation)
+static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var,
+               const struct fb_fix_screeninfo *fix, int rotation)
 {
        unsigned offset;
 
@@ -1221,11 +1223,11 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
                if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
                        goto exit;
 
-               if (display->resume)
-                       r = display->resume(display);
+               if (display->driver->resume)
+                       r = display->driver->resume(display);
 
-               if (r == 0 && display->get_update_mode &&
-                               display->get_update_mode(display) ==
+               if (r == 0 && display->driver->get_update_mode &&
+                               display->driver->get_update_mode(display) ==
                                OMAP_DSS_UPDATE_MANUAL)
                        do_update = 1;
 
@@ -1240,8 +1242,8 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
                if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
                        goto exit;
 
-               if (display->suspend)
-                       r = display->suspend(display);
+               if (display->driver->suspend)
+                       r = display->driver->suspend(display);
 
                break;
 
@@ -1252,11 +1254,11 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
 exit:
        omapfb_unlock(fbdev);
 
-       if (r == 0 && do_update && display->update) {
+       if (r == 0 && do_update && display->driver->update) {
                u16 w, h;
-               display->get_resolution(display, &w, &h);
+               display->driver->get_resolution(display, &w, &h);
 
-               r = display->update(display, 0, 0, w, h);
+               r = display->driver->update(display, 0, 0, w, h);
        }
 
        return r;
@@ -1404,6 +1406,7 @@ static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
                unsigned long paddr)
 {
        struct omapfb_info *ofbi = FB2OFB(fbi);
+       struct omapfb2_device *fbdev = ofbi->fbdev;
        struct omap_dss_device *display;
        int bytespp;
 
@@ -1412,7 +1415,7 @@ static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
        if (!display)
                return 0;
 
-       switch (display->get_recommended_bpp(display)) {
+       switch (omapfb_get_recommended_bpp(fbdev, display)) {
        case 16:
                bytespp = 2;
                break;
@@ -1427,7 +1430,7 @@ static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
        if (!size) {
                u16 w, h;
 
-               display->get_resolution(display, &w, &h);
+               display->driver->get_resolution(display, &w, &h);
 
                if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
                        size = max(omap_vrfb_min_phys_size(w, h, bytespp),
@@ -1636,8 +1639,8 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
        if (old_size == size && old_type == type)
                return 0;
 
-       if (display && display->sync)
-                       display->sync(display);
+       if (display && display->driver->sync)
+                       display->driver->sync(display);
 
        omapfb_free_fbmem(fbi);
 
@@ -1745,7 +1748,7 @@ static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
                u16 w, h;
                int rotation = (var->rotate + ofbi->rotation[0]) % 4;
 
-               display->get_resolution(display, &w, &h);
+               display->driver->get_resolution(display, &w, &h);
 
                if (rotation == FB_ROTATE_CW ||
                                rotation == FB_ROTATE_CCW) {
@@ -1760,7 +1763,7 @@ static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
                var->yres_virtual = var->yres;
 
                if (!var->bits_per_pixel) {
-                       switch (display->get_recommended_bpp(display)) {
+                       switch (omapfb_get_recommended_bpp(fbdev, display)) {
                        case 16:
                                var->bits_per_pixel = 16;
                                break;
@@ -1828,7 +1831,7 @@ static void omapfb_free_resources(struct omapfb2_device *fbdev)
 
        for (i = 0; i < fbdev->num_displays; i++) {
                if (fbdev->displays[i]->state != OMAP_DSS_DISPLAY_DISABLED)
-                       fbdev->displays[i]->disable(fbdev->displays[i]);
+                       fbdev->displays[i]->driver->disable(fbdev->displays[i]);
 
                omap_dss_put_device(fbdev->displays[i]);
        }
@@ -2011,7 +2014,8 @@ static int omapfb_mode_to_timings(const char *mode_str,
        }
 }
 
-static int omapfb_set_def_mode(struct omap_dss_device *display, char *mode_str)
+static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
+               struct omap_dss_device *display, char *mode_str)
 {
        int r;
        u8 bpp;
@@ -2021,20 +2025,37 @@ static int omapfb_set_def_mode(struct omap_dss_device *display, char *mode_str)
        if (r)
                return r;
 
-       display->panel.recommended_bpp = bpp;
+       fbdev->bpp_overrides[fbdev->num_bpp_overrides].dssdev = display;
+       fbdev->bpp_overrides[fbdev->num_bpp_overrides].bpp = bpp;
+       ++fbdev->num_bpp_overrides;
 
-       if (!display->check_timings || !display->set_timings)
+       if (!display->driver->check_timings || !display->driver->set_timings)
                return -EINVAL;
 
-       r = display->check_timings(display, &timings);
+       r = display->driver->check_timings(display, &timings);
        if (r)
                return r;
 
-       display->set_timings(display, &timings);
+       display->driver->set_timings(display, &timings);
 
        return 0;
 }
 
+static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
+               struct omap_dss_device *dssdev)
+{
+       int i;
+
+       BUG_ON(dssdev->driver->get_recommended_bpp == NULL);
+
+       for (i = 0; i < fbdev->num_bpp_overrides; ++i) {
+               if (dssdev == fbdev->bpp_overrides[i].dssdev)
+                       return fbdev->bpp_overrides[i].bpp;
+       }
+
+       return dssdev->driver->get_recommended_bpp(dssdev);
+}
+
 static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
 {
        char *str, *options, *this_opt;
@@ -2073,7 +2094,7 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
                        break;
                }
 
-               r = omapfb_set_def_mode(display, mode_str);
+               r = omapfb_set_def_mode(fbdev, display, mode_str);
                if (r)
                        break;
        }
@@ -2111,18 +2132,23 @@ static int omapfb_probe(struct platform_device *pdev)
        fbdev->dev = &pdev->dev;
        platform_set_drvdata(pdev, fbdev);
 
+       r = 0;
        fbdev->num_displays = 0;
        dssdev = NULL;
        for_each_dss_dev(dssdev) {
                omap_dss_get_device(dssdev);
+
                if (!dssdev->driver) {
                        dev_err(&pdev->dev, "no driver for display\n");
-                       r = -EINVAL;
-                       goto cleanup;
+                       r = -ENODEV;
                }
+
                fbdev->displays[fbdev->num_displays++] = dssdev;
        }
 
+       if (r)
+               goto cleanup;
+
        if (fbdev->num_displays == 0) {
                dev_err(&pdev->dev, "no displays\n");
                r = -EINVAL;
@@ -2167,35 +2193,28 @@ static int omapfb_probe(struct platform_device *pdev)
        }
 
        if (def_display) {
-#ifndef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE
-               u16 w, h;
-#endif
-               r = def_display->enable(def_display);
-               if (r)
+               struct omap_dss_driver *dssdrv = def_display->driver;
+
+               r = def_display->driver->enable(def_display);
+               if (r) {
                        dev_warn(fbdev->dev, "Failed to enable display '%s'\n",
                                        def_display->name);
+                       goto cleanup;
+               }
 
-               /* set the update mode */
                if (def_display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
-#ifdef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE
-                       if (def_display->enable_te)
-                               def_display->enable_te(def_display, 1);
-                       if (def_display->set_update_mode)
-                               def_display->set_update_mode(def_display,
-                                               OMAP_DSS_UPDATE_AUTO);
-#else /* MANUAL_UPDATE */
-                       if (def_display->enable_te)
-                               def_display->enable_te(def_display, 0);
-                       if (def_display->set_update_mode)
-                               def_display->set_update_mode(def_display,
+                       u16 w, h;
+                       if (dssdrv->enable_te)
+                               dssdrv->enable_te(def_display, 1);
+                       if (dssdrv->set_update_mode)
+                               dssdrv->set_update_mode(def_display,
                                                OMAP_DSS_UPDATE_MANUAL);
 
-                       def_display->get_resolution(def_display, &w, &h);
-                       def_display->update(def_display, 0, 0, w, h);
-#endif
+                       dssdrv->get_resolution(def_display, &w, &h);
+                       def_display->driver->update(def_display, 0, 0, w, h);
                } else {
-                       if (def_display->set_update_mode)
-                               def_display->set_update_mode(def_display,
+                       if (dssdrv->set_update_mode)
+                               dssdrv->set_update_mode(def_display,
                                                OMAP_DSS_UPDATE_AUTO);
                }
        }
index f7c9c73..cd54fdb 100644 (file)
@@ -83,6 +83,12 @@ struct omapfb2_device {
        struct omap_overlay *overlays[10];
        unsigned num_managers;
        struct omap_overlay_manager *managers[10];
+
+       unsigned num_bpp_overrides;
+       struct {
+               struct omap_dss_device *dssdev;
+               u8 bpp;
+       } bpp_overrides[10];
 };
 
 struct omapfb_colormode {
@@ -105,6 +111,9 @@ void omapfb_remove_sysfs(struct omapfb2_device *fbdev);
 
 int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg);
 
+int omapfb_update_window(struct fb_info *fbi,
+               u32 x, u32 y, u32 w, u32 h);
+
 int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
                        struct fb_var_screeninfo *var);
 
index 5b0d997..e2ea0b2 100644 (file)
@@ -126,6 +126,7 @@ header-y += nfs2.h
 header-y += nfs4_mount.h
 header-y += nfs_mount.h
 header-y += nl80211.h
+header-y += omapfb.h
 header-y += param.h
 header-y += pci_regs.h
 header-y += perf_event.h
index f46c40a..9bdd914 100644 (file)
@@ -57,6 +57,7 @@
 #define OMAPFB_WAITFORGO       OMAP_IO(60)
 #define OMAPFB_GET_VRAM_INFO   OMAP_IOR(61, struct omapfb_vram_info)
 #define OMAPFB_SET_TEARSYNC    OMAP_IOW(62, struct omapfb_tearsync_info)
+#define OMAPFB_GET_DISPLAY_INFO        OMAP_IOR(63, struct omapfb_display_info)
 
 #define OMAPFB_CAPS_GENERIC_MASK       0x00000fff
 #define OMAPFB_CAPS_LCDC_MASK          0x00fff000
@@ -206,6 +207,14 @@ struct omapfb_tearsync_info {
        __u16 reserved2;
 };
 
+struct omapfb_display_info {
+       __u16 xres;
+       __u16 yres;
+       __u32 width;    /* phys width of the display in micrometers */
+       __u32 height;   /* phys height of the display in micrometers */
+       __u32 reserved[5];
+};
+
 #ifdef __KERNEL__
 
 #include <plat/board.h>