rk3288 chromium: update for hdmi display
authoryzq <yzq@rock-chips.com>
Mon, 7 Apr 2014 07:33:43 +0000 (15:33 +0800)
committeryzq <yzq@rock-chips.com>
Mon, 7 Apr 2014 08:16:26 +0000 (16:16 +0800)
19 files changed:
arch/arm/configs/rockchip_chromium_defconfig
drivers/gpu/drm/rockchip/Kconfig
drivers/gpu/drm/rockchip/Makefile
drivers/gpu/drm/rockchip/rockchip_drm_connector.c
drivers/gpu/drm/rockchip/rockchip_drm_core.c
drivers/gpu/drm/rockchip/rockchip_drm_crtc.c
drivers/gpu/drm/rockchip/rockchip_drm_drv.c
drivers/gpu/drm/rockchip/rockchip_drm_drv.h
drivers/gpu/drm/rockchip/rockchip_drm_encoder.c
drivers/gpu/drm/rockchip/rockchip_drm_extend.c [new file with mode: 0644]
drivers/gpu/drm/rockchip/rockchip_drm_extend.h [new file with mode: 0644]
drivers/gpu/drm/rockchip/rockchip_drm_plane.c
drivers/gpu/drm/rockchip/rockchip_drm_primary.c
drivers/video/rockchip/hdmi/Kconfig
drivers/video/rockchip/hdmi/rk_hdmi_sysfs.c
drivers/video/rockchip/lcdc/rk3288_lcdc.c
drivers/video/rockchip/rk_drm_fb.c
drivers/video/rockchip/rk_drm_fb.h
include/linux/rk_fb.h

index 33f1fbf84ead52152754eaba20fa2d73dffe20fe..c853a5366586e86937232ad763e715bb682c1c39 100644 (file)
@@ -331,7 +331,8 @@ CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_DRM=y
 CONFIG_DRM_ROCKCHIP=y
 CONFIG_DRM_ROCKCHIP_DMABUF=y
-CONFIG_DRM_RK_PRIMARY=y
+CONFIG_DRM_ROCKCHIP_PRIMARY=y
+CONFIG_DRM_ROCKCHIP_HDMI=y
 CONFIG_MALI_T6XX=y
 CONFIG_MALI_T6XX_DVFS=y
 CONFIG_MALI_T6XX_RT_PM=y
@@ -347,6 +348,7 @@ CONFIG_BACKLIGHT_PWM=y
 CONFIG_LCDC_RK3288=y
 CONFIG_RK_TRSM=y
 CONFIG_RK32_LVDS=y
+CONFIG_RK_HDMI=y
 CONFIG_ROCKCHIP_RGA2=y
 # CONFIG_IEP is not set
 CONFIG_LOGO=y
index f38aa42242001e4cb6357d30c34ba83d436c418c..6e08c3b18913af4f435f52a6f5dc0e7c777b3104 100644 (file)
@@ -22,13 +22,14 @@ config DRM_ROCKCHIP_DMABUF
        help
          Choose this option if you want to use DMABUF feature for DRM.
 
-config DRM_RK_PRIMARY
+config DRM_ROCKCHIP_PRIMARY
          bool "RK DRM PRIMARY"
          depends on OF && DRM_ROCKCHIP 
          select FB_MODE_HELPERS
          select VIDEOMODE_HELPERS
          help
          Choose this option if you want to use Rockchip PRIMARY DISPLAY for DRM.
+
 config DRM_ROCKCHIP_HDMI
        bool "Rockchip DRM HDMI"
        depends on DRM_ROCKCHIP 
index 99aba1a9a093c0814604d203f5d6cf442862b185..cb46f9e855d31b42d3a6b36d5fa98de4998f9083 100644 (file)
@@ -10,10 +10,8 @@ rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_encoder.o rockchip_drm_connecto
 
 rockchipdrm-$(CONFIG_DRM_ROCKCHIP_IOMMU) += rockchip_drm_iommu.o
 rockchipdrm-$(CONFIG_DRM_ROCKCHIP_DMABUF) += rockchip_drm_dmabuf.o
-rockchipdrm-$(CONFIG_DRM_RK_PRIMARY)   += rockchip_drm_primary.o
-rockchipdrm-$(CONFIG_DRM_ROCKCHIP_HDMI)        += rockchip_hdmi.o rockchip_mixer.o \
-                                          rockchip_ddc.o rockchip_hdmiphy.o \
-                                          rockchip_drm_hdmi.o
+rockchipdrm-$(CONFIG_DRM_ROCKCHIP_PRIMARY)     += rockchip_drm_primary.o
+rockchipdrm-$(CONFIG_DRM_ROCKCHIP_HDMI)        += rockchip_drm_extend.o
 rockchipdrm-$(CONFIG_DRM_ROCKCHIP_VIDI)        += rockchip_drm_vidi.o
 
 obj-$(CONFIG_DRM_ROCKCHIP)             += rockchipdrm.o
index c3d5119a386ac350e48defe940c631fa23e58cb6..f205aa8bad50939eb260141ba1c9324c4f3b29f7 100644 (file)
@@ -57,7 +57,31 @@ convert_to_display_mode(struct drm_display_mode *mode,
        if (timing->vmode & FB_VMODE_DOUBLE)
                mode->flags |= DRM_MODE_FLAG_DBLSCAN;
 }
+static inline void
+convert_fbmode_to_display_mode(struct drm_display_mode *mode,
+                       struct fb_videomode *timing)
+{
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+
+       mode->clock = timing->pixclock / 1000;
+       mode->vrefresh = timing->refresh;
 
+       mode->hdisplay = timing->xres;
+       mode->hsync_start = mode->hdisplay + timing->right_margin;
+       mode->hsync_end = mode->hsync_start + timing->hsync_len;
+       mode->htotal = mode->hsync_end + timing->left_margin;
+
+       mode->vdisplay = timing->yres;
+       mode->vsync_start = mode->vdisplay + timing->lower_margin;
+       mode->vsync_end = mode->vsync_start + timing->vsync_len;
+       mode->vtotal = mode->vsync_end + timing->upper_margin;
+
+       if (timing->vmode & FB_VMODE_INTERLACED)
+               mode->flags |= DRM_MODE_FLAG_INTERLACE;
+
+       if (timing->vmode & FB_VMODE_DOUBLE)
+               mode->flags |= DRM_MODE_FLAG_DBLSCAN;
+}
 /* convert drm_display_mode to rockchip_video_timings */
 static inline void
 convert_to_video_timing(struct fb_videomode *timing,
@@ -130,6 +154,34 @@ static int rockchip_drm_connector_get_modes(struct drm_connector *connector)
                }
 
                drm_mode_connector_update_edid_property(connector, edid);
+       } else if(display_ops->get_modelist){
+               struct list_head *pos,*head;
+               struct fb_modelist *modelist;
+               struct fb_videomode *mode;
+               struct drm_display_mode *disp_mode = NULL;
+               count=0;
+               head = display_ops->get_modelist(manager->dev);
+               
+               list_for_each(pos,head){
+                       modelist = list_entry(pos, struct fb_modelist, list);
+                       mode = &modelist->mode;
+                       disp_mode = drm_mode_create(connector->dev);
+                       if (!mode) {
+                               DRM_ERROR("failed to create a new display mode.\n");
+                               return count;
+                       }
+                       convert_fbmode_to_display_mode(disp_mode, mode);
+
+                       if(mode->xres == 1280 && mode->yres == 720 && mode->refresh == 60)
+                               disp_mode->type |=  DRM_MODE_TYPE_PREFERRED;
+
+                       drm_mode_set_name(disp_mode);
+//                     snprintf(disp_mode->name, DRM_DISPLAY_MODE_LEN, "%dx%d%s-%d",
+//                                     disp_mode->hdisplay, disp_mode->vdisplay,
+//                                     !!(disp_mode->flags & DRM_MODE_FLAG_INTERLACE)? "i" : "p",disp_mode->vrefresh);
+                       drm_mode_probed_add(connector, disp_mode);
+                       count++;
+               }
        } else {
                struct rockchip_drm_panel_info *panel;
                struct drm_display_mode *mode = drm_mode_create(connector->dev);
index 3e9b946cf4e446aba3885b7c0a469d7df2d975c8..393ff82f33574abbbea17bb130cabd480296f6d2 100644 (file)
@@ -28,7 +28,6 @@ static int rockchip_drm_create_enc_conn(struct drm_device *dev,
 
        DRM_DEBUG_DRIVER("%s\n", __FILE__);
 
-       printk(KERN_ERR"----->yzq %s %d\n",__func__,__LINE__);
        subdrv->manager->dev = subdrv->dev;
 
        /* create and initialize a encoder for this sub driver. */
@@ -116,15 +115,12 @@ int rockchip_drm_device_register(struct drm_device *dev)
 
        DRM_DEBUG_DRIVER("%s\n", __FILE__);
 
-       printk(KERN_ERR"----->yzq %s %d\n",__func__,__LINE__);
        if (!dev)
                return -EINVAL;
 
-       printk(KERN_ERR"----->yzq %s %d\n",__func__,__LINE__);
        list_for_each_entry_safe(subdrv, n, &rockchip_drm_subdrv_list, list) {
                err = rockchip_drm_subdrv_probe(dev, subdrv);
                if (err) {
-       printk(KERN_ERR"----->yzq %s %d\n",__func__,__LINE__);
                        DRM_DEBUG("rockchip drm subdrv probe failed.\n");
                        list_del(&subdrv->list);
                        continue;
@@ -141,7 +137,6 @@ int rockchip_drm_device_register(struct drm_device *dev)
 
                err = rockchip_drm_create_enc_conn(dev, subdrv);
                if (err) {
-       printk(KERN_ERR"----->yzq %s %d\n",__func__,__LINE__);
                        DRM_DEBUG("failed to create encoder and connector.\n");
                        rockchip_drm_subdrv_remove(dev, subdrv);
                        list_del(&subdrv->list);
@@ -151,7 +146,6 @@ int rockchip_drm_device_register(struct drm_device *dev)
                fine_cnt++;
        }
 
-       printk(KERN_ERR"----->yzq %s %d\n",__func__,__LINE__);
        if (!fine_cnt)
                return -EINVAL;
 
index 90b3ea956f769b6e9a5eccd9cd66784974597fc6..b02deebdbdfca3b27988132b915943479de8f543 100644 (file)
@@ -54,7 +54,7 @@ static void rockchip_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
        struct rockchip_drm_crtc *rockchip_crtc = to_rockchip_crtc(crtc);
 
-       DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode);
+//     printk(KERN_ERR"crtc[%d] mode[%d]\n", crtc->base.id, mode);
 
        if (rockchip_crtc->dpms == mode) {
                DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n");
@@ -147,11 +147,11 @@ static int rockchip_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
        int ret;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
-
+       
        /* when framebuffer changing is requested, crtc's dpms should be on */
        if (rockchip_crtc->dpms > DRM_MODE_DPMS_ON) {
                DRM_ERROR("failed framebuffer changing request.\n");
-               return -EPERM;
+//             return -EPERM;
        }
 
        crtc_w = crtc->fb->width - x;
@@ -204,6 +204,7 @@ static int rockchip_drm_crtc_page_flip(struct drm_crtc *crtc,
        struct drm_framebuffer *old_fb = crtc->fb;
        int ret = -EINVAL;
 
+
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
        /* when the page flip is requested, crtc's dpms should be on */
@@ -370,7 +371,24 @@ int rockchip_drm_crtc_create(struct drm_device *dev, unsigned int nr)
 
        return 0;
 }
+#if 0
+int rockchip_get_crtc_vblank_timestamp(struct drm_device *dev, int crtc,
+                                   int *max_error,
+                                   struct timeval *vblank_time,
+                                   unsigned flags)
+{
+       struct rockchip_drm_private *private = dev->dev_private;
+       struct rockchip_drm_crtc *rockchip_crtc =
+               to_rockchip_crtc(private->crtc[crtc]);
+
+       if (rockchip_crtc->dpms != DRM_MODE_DPMS_ON)
+               return -EPERM;
 
+       rockchip_drm_fn_encoder(private->crtc[crtc], &crtc,
+                       rockchip_get_vblank_timestamp);
+       
+}
+#endif
 int rockchip_drm_crtc_enable_vblank(struct drm_device *dev, int crtc)
 {
        struct rockchip_drm_private *private = dev->dev_private;
index 0c7923491fe5ecf7ed1abecb41e7290a2fafd4a3..eeb8d08f22622b2d9db8f9545c29993637e9c107 100644 (file)
@@ -252,6 +252,7 @@ static struct drm_driver rockchip_drm_driver = {
        .get_vblank_counter     = drm_vblank_count,
        .enable_vblank          = rockchip_drm_crtc_enable_vblank,
        .disable_vblank         = rockchip_drm_crtc_disable_vblank,
+//     .get_vblank_timestamp   = rockchip_get_crtc_vblank_timestamp,
        .gem_init_object        = rockchip_drm_gem_init_object,
        .gem_free_object        = rockchip_drm_gem_free_object,
        .gem_vm_ops             = &rockchip_drm_gem_vm_ops,
@@ -306,13 +307,20 @@ static int __init rockchip_drm_init(void)
        DRM_DEBUG_DRIVER("%s\n", __FILE__);
 
 
-#ifdef CONFIG_DRM_RK_PRIMARY
+#ifdef CONFIG_DRM_ROCKCHIP_PRIMARY
        ret = platform_driver_register(&primary_platform_driver);
        if (ret < 0)
-               goto out_fimd;
+               goto out_primary;
        platform_device_register_simple("primary-display", -1,
                        NULL, 0);
 #endif
+#ifdef CONFIG_DRM_ROCKCHIP_HDMI
+       ret = platform_driver_register(&extend_platform_driver);
+       if (ret < 0)
+               goto out_extend;
+       platform_device_register_simple("extend-display", -1,
+                       NULL, 0);
+#endif
 
        ret = platform_driver_register(&rockchip_drm_platform_driver);
        if (ret < 0)
@@ -331,9 +339,13 @@ static int __init rockchip_drm_init(void)
 out:
        platform_driver_unregister(&rockchip_drm_platform_driver);
 out_drm:
-#ifdef CONFIG_DRM_RK_PRIMARY
+#ifdef CONFIG_DRM_ROCKCHIP_PRIMARY
        platform_driver_unregister(&primary_platform_driver);
-out_fimd:
+out_primary:
+#endif
+#ifdef CONFIG_DRM_ROCKCHIP_HDMI
+       platform_driver_unregister(&extend_platform_driver);
+out_extend:
 #endif
        return ret;
 }
index d0d63cfe8410ac599c2a78ed5f5b3c95ba7beb31..96072670f88093bab69f820d8e8cc9dcce463515 100644 (file)
@@ -117,6 +117,7 @@ struct rockchip_drm_overlay {
        unsigned int mode_width;
        unsigned int mode_height;
        unsigned int refresh;
+       unsigned int pixclock;
        unsigned int scan_flag;
        unsigned int bpp;
        unsigned int pitch;
@@ -149,6 +150,7 @@ struct rockchip_drm_display_ops {
        struct edid *(*get_edid)(struct device *dev,
                        struct drm_connector *connector);
        void *(*get_panel)(struct device *dev);
+       void *(*get_modelist)(struct device *dev);
        int (*check_timing)(struct device *dev, void *timing);
        int (*power_on)(struct device *dev, int mode);
 };
@@ -338,6 +340,7 @@ int rockchip_platform_device_ipp_register(void);
 void rockchip_platform_device_ipp_unregister(void);
 
 extern struct platform_driver primary_platform_driver;
+extern struct platform_driver extend_platform_driver;
 extern struct platform_driver hdmi_driver;
 extern struct platform_driver mixer_driver;
 extern struct platform_driver rockchip_drm_common_hdmi_driver;
index 671267bf39b06531800cc26d89f1ee05199d8979..8ec2f30d8b953deebd95f7b4edc4fd75b108247b 100644 (file)
@@ -389,7 +389,34 @@ void rockchip_drm_fn_encoder(struct drm_crtc *crtc, void *data,
                fn(encoder, data);
        }
 }
+int rockchip_get_crtc_vblank_timestamp(struct drm_device *dev, int crtc,
+                                   int *max_error,
+                                   struct timeval *vblank_time,
+                                   unsigned flags)
+{
+#if 0
+       ktime_t stime, etime, mono_time_offset;
+       struct timeval tv_etime;
+       struct drm_display_mode *mode;
+       int vbl_status, vtotal, vdisplay;
+       int vpos, hpos, i;
+       s64 framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns;
+       bool invbl;
+
+       if (crtc < 0 || crtc >= dev->num_crtcs) {
+               DRM_ERROR("Invalid crtc %d\n", crtc);
+               return -EINVAL;
+       }
 
+       /* Scanout position query not supported? Should not happen. */
+       if (!dev->driver->get_scanout_position) {
+               DRM_ERROR("Called from driver w/o get_scanout_position()!?\n");
+               return -EIO;
+       }
+#endif
+       return 0;//vbl_status;
+
+}
 void rockchip_drm_enable_vblank(struct drm_encoder *encoder, void *data)
 {
        struct rockchip_drm_manager *manager =
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_extend.c b/drivers/gpu/drm/rockchip/rockchip_drm_extend.c
new file mode 100644 (file)
index 0000000..677e859
--- /dev/null
@@ -0,0 +1,872 @@
+/*
+ * rk3288_drm_fimd.c
+ *
+ * Copyright (C) ROCKCHIP, Inc.
+ * Author:yzq<yzq@rock-chips.com>
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+#include <drm/drmP.h>
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_edid.h>
+
+#include <video/of_display_timing.h>
+#include <drm/rockchip_drm.h>
+#include <linux/rockchip/cpu.h>
+#include <linux/rockchip/iomap.h>
+#include <linux/rk_fb.h>
+#include <video/display_timing.h>
+#include <linux/rockchip/cpu.h>
+#include <linux/rockchip/iomap.h>
+#include <linux/rockchip/grf.h>
+#include "rockchip_drm_drv.h"
+#include "rockchip_drm_fbdev.h"
+#include "rockchip_drm_crtc.h"
+#include "rockchip_drm_iommu.h"
+#include "rockchip_drm_extend.h"
+static struct device *g_dev = NULL;
+static int extend_activate(struct extend_context *ctx, bool enable);
+#if 0
+extern struct void *get_extend_drv(void);
+#endif
+#if 0
+static const char fake_edid_info[] = {
+       0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x4c, 0x2d, 0x05, 0x05,
+       0x00, 0x00, 0x00, 0x00, 0x30, 0x12, 0x01, 0x03, 0x80, 0x10, 0x09, 0x78,
+       0x0a, 0xee, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26, 0x0f, 0x50, 0x54, 0xbd,
+       0xee, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x66, 0x21, 0x50, 0xb0, 0x51, 0x00,
+       0x1b, 0x30, 0x40, 0x70, 0x36, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e,
+       0x01, 0x1d, 0x00, 0x72, 0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00,
+       0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x18,
+       0x4b, 0x1a, 0x44, 0x17, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+       0x00, 0x00, 0x00, 0xfc, 0x00, 0x53, 0x41, 0x4d, 0x53, 0x55, 0x4e, 0x47,
+       0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0xbc, 0x02, 0x03, 0x1e, 0xf1,
+       0x46, 0x84, 0x05, 0x03, 0x10, 0x20, 0x22, 0x23, 0x09, 0x07, 0x07, 0x83,
+       0x01, 0x00, 0x00, 0xe2, 0x00, 0x0f, 0x67, 0x03, 0x0c, 0x00, 0x10, 0x00,
+       0xb8, 0x2d, 0x01, 0x1d, 0x80, 0x18, 0x71, 0x1c, 0x16, 0x20, 0x58, 0x2c,
+       0x25, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x9e, 0x8c, 0x0a, 0xd0, 0x8a,
+       0x20, 0xe0, 0x2d, 0x10, 0x10, 0x3e, 0x96, 0x00, 0xa0, 0x5a, 0x00, 0x00,
+       0x00, 0x18, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
+       0x45, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x06
+};
+#endif
+extern int primary_is_display;
+extern wait_queue_head_t wait_primary_queue;
+static bool extend_display_is_connected(struct device *dev)
+{
+       struct extend_context *ctx = get_extend_context(dev);
+       struct rk_drm_display *drm_disp = ctx->drm_disp;
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+       printk(KERN_ERR"%s %d\n", __func__,__LINE__);
+
+       return drm_disp->is_connected?true:false;
+       
+       /* TODO. */
+}
+
+static void *extend_get_panel(struct device *dev)
+{
+       struct extend_context *ctx = get_extend_context(dev);
+       struct rk_drm_display *drm_disp = ctx->drm_disp;
+       struct list_head *pos;
+       struct fb_modelist *modelist;
+       struct fb_videomode *mode;
+
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+       if(!drm_disp->is_connected)
+               return NULL;
+       list_for_each(pos,drm_disp->modelist){
+               modelist = list_entry(pos, struct fb_modelist, list);
+               mode = &modelist->mode;
+               if(mode->flag == HDMI_VIDEO_DEFAULT_MODE)
+                       break;
+       }
+       
+       memcpy(&ctx->panel->timing,mode,sizeof(struct fb_videomode));
+
+       return ctx->panel;
+}
+static void *extend_get_modelist(struct device *dev)
+{
+       struct extend_context *ctx = get_extend_context(dev);
+       struct rk_drm_display *drm_disp = ctx->drm_disp;
+
+       return drm_disp->modelist;
+}
+static int extend_check_timing(struct device *dev, void *timing)
+{
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+
+       printk(KERN_ERR"%s %d\n", __func__,__LINE__);
+       /* TODO. */
+
+       return 0;
+}
+
+static int extend_display_power_on(struct device *dev, int mode)
+{
+       struct extend_context *ctx = get_extend_context(dev);
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+       /* TODO */
+       printk(KERN_ERR"%s %d\n", __func__,__LINE__);
+       extend_activate(ctx,mode == DRM_MODE_DPMS_ON?true:false);
+       
+       return 0;
+}
+struct edid *extend_get_edid(struct device *dev,
+                       struct drm_connector *connector)
+{
+#if 0
+       int i, j = 0, valid_extensions = 0;
+       struct hdmi *hdmi = get_extend_drv();
+       u8 *block, *new;
+       struct edid *edid = NULL;
+       struct edid *raw_edid = NULL;
+       bool print_bad_edid = !connector->bad_edid_counter;
+
+       if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
+               return NULL;
+       /* base block fetch */
+       for (i = 0; i < 4; i++) {
+               if(hdmi->read_edid(hdmi, 0, block))
+                       goto out;
+               if (drm_edid_block_valid(block, 0, print_bad_edid))
+                       break;
+       }
+       if (i == 4)
+               goto carp;
+
+       /* if there's no extensions, we're done */
+       if (block[0x7e] == 0)
+               return block;
+
+       new = krealloc(block, (block[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL);
+       if (!new)
+               goto out;
+       block = new;
+
+       for (j = 1; j <= block[0x7e]; j++) {
+               for (i = 0; i < 4; i++) {
+                       if(hdmi->read_edid(hdmi, j, block))
+                               goto out;
+                       if (drm_edid_block_valid(block + (valid_extensions + 1) * EDID_LENGTH, j, print_bad_edid)) {
+                               valid_extensions++;
+                               break;
+                       }
+               }
+
+               if (i == 4 && print_bad_edid) {
+                       dev_warn(connector->dev->dev,
+                        "%s: Ignoring invalid EDID block %d.\n",
+                        drm_get_connector_name(connector), j);
+
+                       connector->bad_edid_counter++;
+               }
+       }
+
+       if (valid_extensions != block[0x7e]) {
+               block[EDID_LENGTH-1] += block[0x7e] - valid_extensions;
+               block[0x7e] = valid_extensions;
+               new = krealloc(block, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL);
+               if (!new)
+                       goto out;
+               block = new;
+       }
+       edid = (struct edid *)block;
+       return edid;
+
+carp:
+       if (print_bad_edid) {
+               dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n",
+                        drm_get_connector_name(connector), j);
+       }
+       connector->bad_edid_counter++;
+
+out:
+       kfree(block);
+       raw_edid = (struct edid *)fake_edid_info;
+       edid = kmemdup(raw_edid, (1 + raw_edid->extensions) * EDID_LENGTH, GFP_KERNEL);
+       if (!edid) {
+               DRM_DEBUG_KMS("failed to allocate edid\n");
+               return ERR_PTR(-ENOMEM);
+       }
+       return edid;
+#endif
+}
+
+static struct rockchip_drm_display_ops extend_display_ops = {
+       .type = ROCKCHIP_DISPLAY_TYPE_HDMI,
+       .is_connected = extend_display_is_connected,
+       .get_panel = extend_get_panel,
+       .get_modelist = extend_get_modelist,
+       .check_timing = extend_check_timing,
+       .power_on = extend_display_power_on,
+//     .get_edid = extend_get_edid,
+};
+
+static void extend_dpms(struct device *subdrv_dev, int mode)
+{
+       struct extend_context *ctx = get_extend_context(subdrv_dev);
+
+       DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
+
+       mutex_lock(&ctx->lock);
+
+       printk(KERN_ERR"%s %d\n", __func__,__LINE__);
+       switch (mode) {
+       case DRM_MODE_DPMS_ON:
+               /*
+                * enable primary hardware only if suspended status.
+                *
+                * P.S. extend_dpms function would be called at booting time so
+                * clk_enable could be called double time.
+                */
+
+               if (ctx->suspended)
+                       pm_runtime_get_sync(subdrv_dev);
+               break;
+       case DRM_MODE_DPMS_STANDBY:
+       case DRM_MODE_DPMS_SUSPEND:
+       case DRM_MODE_DPMS_OFF:
+               if (!ctx->suspended)
+                       pm_runtime_put_sync(subdrv_dev);
+               break;
+       default:
+               DRM_DEBUG_KMS("unspecified mode %d\n", mode);
+               break;
+       }
+
+       mutex_unlock(&ctx->lock);
+}
+
+static void extend_apply(struct device *subdrv_dev)
+{
+       struct extend_context *ctx = get_extend_context(subdrv_dev);
+       struct rockchip_drm_manager *mgr = ctx->subdrv.manager;
+       struct rockchip_drm_manager_ops *mgr_ops = mgr->ops;
+       struct rockchip_drm_overlay_ops *ovl_ops = mgr->overlay_ops;
+       struct extend_win_data *win_data;
+       int i;
+
+       printk(KERN_ERR"%s %d\n", __func__,__LINE__);
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+
+       for (i = 0; i < WINDOWS_NR; i++) {
+               win_data = &ctx->win_data[i];
+               if (win_data->enabled && (ovl_ops && ovl_ops->commit))
+                       ovl_ops->commit(subdrv_dev, i);
+       }
+
+       if (mgr_ops && mgr_ops->commit)
+               mgr_ops->commit(subdrv_dev);
+}
+
+static void extend_commit(struct device *dev)
+{
+       struct extend_context *ctx = get_extend_context(dev);
+       struct rk_drm_display *drm_disp = ctx->drm_disp;
+       struct rockchip_drm_panel_info *panel = (struct rockchip_drm_panel_info *)extend_get_panel(dev);
+
+//     printk(KERN_ERR"%s %d\n", __func__,__LINE__);
+       if (ctx->suspended)
+               return;
+
+       drm_disp->mode = &panel->timing;
+
+       drm_disp->enable = true;
+       rk_drm_disp_handle(drm_disp,0,RK_DRM_SCREEN_SET);
+}
+
+static int extend_enable_vblank(struct device *dev)
+{
+       struct extend_context *ctx = get_extend_context(dev);
+
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+
+       if (ctx->suspended)
+               return -EPERM;
+
+       ctx->vblank_en = true;
+       return 0;
+}
+
+static void extend_disable_vblank(struct device *dev)
+{
+       struct extend_context *ctx = get_extend_context(dev);
+
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+
+       if (ctx->suspended)
+               return;
+       
+       ctx->vblank_en = false;
+}
+
+static void extend_wait_for_vblank(struct device *dev)
+{
+       struct extend_context *ctx = get_extend_context(dev);
+
+       if (ctx->suspended)
+               return;
+#if 1
+       atomic_set(&ctx->wait_vsync_event, 1);
+
+       if (!wait_event_timeout(ctx->wait_vsync_queue,
+                               !atomic_read(&ctx->wait_vsync_event),
+                               DRM_HZ/20))
+               DRM_DEBUG_KMS("vblank wait timed out.\n");
+#endif
+}
+
+static void extend_event_call_back_handle(struct rk_drm_display *drm_disp,int win_id,int event)
+{
+       struct extend_context *ctx = get_extend_context(g_dev);
+       struct rockchip_drm_subdrv *subdrv = &ctx->subdrv;
+       struct rockchip_drm_manager *manager = subdrv->manager;
+       struct drm_device *drm_dev = subdrv->drm_dev;
+       switch(event){
+               case RK_DRM_CALLBACK_VSYNC:
+                       /* check the crtc is detached already from encoder */
+                       if (manager->pipe < 0)
+                               return;
+               
+                       drm_handle_vblank(drm_dev, manager->pipe);
+                       rockchip_drm_crtc_finish_pageflip(drm_dev, manager->pipe);
+
+                       /* set wait vsync event to zero and wake up queue. */
+                       if (atomic_read(&ctx->wait_vsync_event)) {
+                               atomic_set(&ctx->wait_vsync_event, 0);
+                               DRM_WAKEUP(&ctx->wait_vsync_queue);
+                       }
+                       break;
+               case RK_DRM_CALLBACK_HOTPLUG:
+#if 0
+                       if(0){//primary_is_display == 0){
+                               printk(KERN_ERR"-->%s waitfor hotplug event %d\n",__func__,event);
+                               int is_connected = drm_disp->is_connected;
+                               drm_disp->is_connected = false;
+
+                               if (!wait_event_timeout(wait_primary_queue,
+                                                       primary_is_display,
+                                                       20*1000)){
+                                       printk(KERN_ERR"-->%s waitfot hotplug event %d timeout\n",__func__,event);
+                               }
+                               drm_disp->is_connected = true;
+                       }
+#endif
+                       printk(KERN_ERR"-->%s hotplug event %d\n",__func__,event);
+                       drm_helper_hpd_irq_event(drm_dev);
+                       break;
+
+               default:
+                       printk(KERN_ERR"-->%s unhandle event %d\n",__func__,event);
+                       break;
+       }
+}
+static void extend_get_max_resol(void *ctx, unsigned int *width,
+                                       unsigned int *height)
+{
+       DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
+
+       *width = MAX_HDMI_WIDTH;
+       *height = MAX_HDMI_HEIGHT;
+}
+static struct rockchip_drm_manager_ops extend_manager_ops = {
+       .dpms = extend_dpms,
+       .apply = extend_apply,
+       .commit = extend_commit,
+       .enable_vblank = extend_enable_vblank,
+       .disable_vblank = extend_disable_vblank,
+       .wait_for_vblank = extend_wait_for_vblank,
+       .get_max_resol = extend_get_max_resol,
+};
+
+static void extend_win_mode_set(struct device *dev,
+                             struct rockchip_drm_overlay *overlay)
+{
+       struct extend_context *ctx = get_extend_context(dev);
+       struct rk_drm_display *drm_disp = ctx->drm_disp;
+       struct extend_win_data *win_data;
+       int win;
+       unsigned long offset;
+       struct list_head *pos,*head;
+       struct fb_modelist *modelist;
+       struct fb_videomode *mode;
+       struct drm_display_mode *disp_mode = NULL;
+
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+
+       if (!overlay) {
+               dev_err(dev, "overlay is NULL\n");
+               return;
+       }
+
+       win = overlay->zpos;
+       if (win == DEFAULT_ZPOS)
+               win = ctx->default_win;
+
+       if (win < 0 || win > WINDOWS_NR)
+               return;
+
+       offset = overlay->fb_x * (overlay->bpp >> 3);
+       offset += overlay->fb_y * overlay->pitch;
+
+//     printk("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch);
+//     printk("crtc_x=%d crtc_y=%d crtc_width=%d crtc_height=%d\n",overlay->crtc_x,overlay->crtc_y,overlay->crtc_width,overlay->crtc_height);
+//     printk("fb_width=%d fb_height=%d dma_addr=%x offset=%x\n",overlay->fb_width,overlay->fb_height,overlay->dma_addr[0],offset);
+
+       win_data = &ctx->win_data[win];
+
+       win_data->offset_x = overlay->crtc_x;
+       win_data->offset_y = overlay->crtc_y;
+       win_data->ovl_width = overlay->crtc_width;
+       win_data->ovl_height = overlay->crtc_height;
+       win_data->fb_width = overlay->fb_width;
+       win_data->fb_height = overlay->fb_height;
+       win_data->dma_addr = overlay->dma_addr[0] + offset;
+       win_data->bpp = overlay->bpp;
+       win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
+                               (overlay->bpp >> 3);
+       win_data->line_size = overlay->crtc_width * (overlay->bpp >> 3);
+       head = drm_disp->modelist;
+       list_for_each(pos,head){
+               modelist = list_entry(pos, struct fb_modelist, list);
+               mode = &modelist->mode;
+               if(mode->xres == overlay->mode_width && mode->yres == overlay->mode_height
+                               && mode->pixclock == overlay->pixclock)
+                       break;
+       }
+       if(drm_disp->mode != mode){
+       printk(KERN_ERR"%s %d\n", __func__,__LINE__);
+               drm_disp->mode = mode;
+               printk("overlay [%dx%d-%d] mode[%dx%d-%d]\n",overlay->mode_width,overlay->mode_height,overlay->pixclock,mode->xres,mode->yres,mode->pixclock);
+//             printk("overlay->mode_width=%d overlay->mode_height=%d mode_width=%d mode_height=%d",overlay->mode_width,overlay->mode_height,mode->xres,mode->yres);
+
+               drm_disp->enable = true;
+               rk_drm_disp_handle(drm_disp,0,RK_DRM_SCREEN_SET);
+       }
+
+
+}
+
+static void extend_win_set_pixfmt(struct device *dev, unsigned int win)
+{
+       struct extend_context *ctx = get_extend_context(dev);
+       struct extend_win_data *win_data = &ctx->win_data[win];
+}
+
+static void extend_win_set_colkey(struct device *dev, unsigned int win)
+{
+//     struct extend_context *ctx = get_extend_context(dev);
+
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+
+}
+
+ktime_t win_start;
+ktime_t win_end;
+ktime_t win_start1;
+ktime_t win_end1;
+static void extend_win_commit(struct device *dev, int zpos)
+{
+       struct extend_context *ctx = get_extend_context(dev);
+       struct rk_drm_display *drm_disp = ctx->drm_disp;
+       struct rk_win_data *rk_win = NULL; 
+       struct extend_win_data *win_data;
+       int win = zpos;
+       unsigned long val,  size;
+       u32 xpos, ypos;
+
+       //printk(KERN_ERR"%s %d\n", __func__,__LINE__);
+       if (ctx->suspended)
+               return;
+
+       if (win == DEFAULT_ZPOS)
+               win = ctx->default_win;
+
+       if (win < 0 || win > WINDOWS_NR)
+               return;
+       if(win == 0){
+               win_start = ktime_get();
+               win_start = ktime_sub(win_start, win_end);
+//             printk("user flip buffer time %dms\n", (int)ktime_to_ms(win_start));
+               //      win_start = ktime_get();
+       }
+       rk_win = &drm_disp->win[win];
+       win_data = &ctx->win_data[win];
+       switch(win_data->bpp){
+               case 32:
+                       rk_win->format = ARGB888;
+                       break;
+               case 24:
+                       rk_win->format = RGB888;
+                       break;
+               case 16:
+                       rk_win->format = RGB565;
+                       break;
+               default:
+                       printk("not support format %d\n",win_data->bpp);
+                       break;
+       }
+
+       rk_win->xpos = win_data->offset_x;
+       rk_win->ypos = win_data->offset_y;
+       rk_win->xact = win_data->ovl_width;
+       rk_win->yact = win_data->ovl_height;
+       rk_win->xsize = win_data->ovl_width;
+       rk_win->ysize = win_data->ovl_height;
+       rk_win->xvir = win_data->fb_width;
+       rk_win->yrgb_addr = win_data->dma_addr;
+       rk_win->enabled = true;
+
+       rk_drm_disp_handle(drm_disp,1<<win,RK_DRM_WIN_COMMIT | RK_DRM_DISPLAY_COMMIT);
+               
+       win_data->enabled = true;
+       if(win ==0){
+       //      win_end = ktime_get();
+       //      win_end = ktime_sub(win_end, win_start);
+       //      printk("flip buffer time %dus\n", (int)ktime_to_us(win_end));
+               win_end = ktime_get();
+       }
+}
+
+static void extend_win_disable(struct device *dev, int zpos)
+{
+       struct extend_context *ctx = get_extend_context(dev);
+       struct rk_drm_display *drm_disp = ctx->drm_disp;
+       struct extend_win_data *win_data;
+       int win = zpos;
+
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+
+       if (win == DEFAULT_ZPOS)
+               win = ctx->default_win;
+
+       if (win < 0 || win > WINDOWS_NR)
+               return;
+
+       win_data = &ctx->win_data[win];
+
+       if (ctx->suspended) {
+               /* do not resume this window*/
+               win_data->resume = false;
+               return;
+       }
+       drm_disp->win[win].enabled = false;
+       rk_drm_disp_handle(drm_disp,1<<win,RK_DRM_WIN_COMMIT | RK_DRM_DISPLAY_COMMIT);
+
+       win_data->enabled = false;
+}
+
+static struct rockchip_drm_overlay_ops extend_overlay_ops = {
+       .mode_set = extend_win_mode_set,
+       .commit = extend_win_commit,
+       .disable = extend_win_disable,
+};
+
+static struct rockchip_drm_manager extend_manager = {
+       .pipe           = -1,
+       .ops            = &extend_manager_ops,
+       .overlay_ops    = &extend_overlay_ops,
+       .display_ops    = &extend_display_ops,
+};
+#if 0
+static irqreturn_t extend_irq_handler(int irq, void *dev_id)
+{
+       struct extend_context *ctx = (struct extend_context *)dev_id;
+       struct rockchip_drm_subdrv *subdrv = &ctx->subdrv;
+       struct drm_device *drm_dev = subdrv->drm_dev;
+       struct rockchip_drm_manager *manager = subdrv->manager;
+       u32 intr0_reg;
+
+
+
+       /* check the crtc is detached already from encoder */
+       if (manager->pipe < 0)
+               goto out;
+
+       drm_handle_vblank(drm_dev, manager->pipe);
+       rockchip_drm_crtc_finish_pageflip(drm_dev, manager->pipe);
+
+       /* set wait vsync event to zero and wake up queue. */
+       if (atomic_read(&ctx->wait_vsync_event)) {
+               atomic_set(&ctx->wait_vsync_event, 0);
+               DRM_WAKEUP(&ctx->wait_vsync_queue);
+       }
+out:
+       return IRQ_HANDLED;
+}
+#endif
+static int extend_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
+{
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+
+       /*
+        * enable drm irq mode.
+        * - with irq_enabled = 1, we can use the vblank feature.
+        *
+        * P.S. note that we wouldn't use drm irq handler but
+        *      just specific driver own one instead because
+        *      drm framework supports only one irq handler.
+        */
+       drm_dev->irq_enabled = 1;
+
+       /*
+        * with vblank_disable_allowed = 1, vblank interrupt will be disabled
+        * by drm timer once a current process gives up ownership of
+        * vblank event.(after drm_vblank_put function is called)
+        */
+       drm_dev->vblank_disable_allowed = 1;
+
+       /* attach this sub driver to iommu mapping if supported. */
+       if (is_drm_iommu_supported(drm_dev))
+               drm_iommu_attach_device(drm_dev, dev);
+
+       return 0;
+}
+
+static void extend_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
+{
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+
+       /* detach this sub driver from iommu mapping if supported. */
+       if (is_drm_iommu_supported(drm_dev))
+               drm_iommu_detach_device(drm_dev, dev);
+}
+
+
+static void extend_clear_win(struct extend_context *ctx, int win)
+{
+       u32 val;
+
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+
+}
+
+
+static void extend_window_suspend(struct device *dev)
+{
+       struct extend_win_data *win_data = NULL;
+       struct extend_context *ctx = get_extend_context(dev);
+       int i;
+
+       for (i = 0; i < WINDOWS_NR; i++) {
+               win_data = &ctx->win_data[i];
+               win_data->resume = win_data->enabled;
+               extend_win_disable(dev, i);
+       }
+       extend_wait_for_vblank(dev);
+}
+
+static void extend_window_resume(struct device *dev)
+{
+       struct extend_context *ctx = get_extend_context(dev);
+       struct extend_win_data *win_data;
+       int i;
+
+       for (i = 0; i < WINDOWS_NR; i++) {
+               win_data = &ctx->win_data[i];
+               win_data->enabled = win_data->resume;
+               win_data->resume = false;
+       }
+}
+
+static int extend_activate(struct extend_context *ctx, bool enable)
+{
+       struct device *dev = ctx->subdrv.dev;
+       struct rk_drm_display *drm_disp = ctx->drm_disp;
+       if (enable) {
+               int ret;
+
+               ctx->suspended = false;
+
+               drm_disp->enable = true;
+
+               rk_drm_disp_handle(drm_disp,0,RK_DRM_SCREEN_BLANK);
+
+               /* if vblank was enabled status, enable it again. */
+               if (ctx->vblank_en)
+                       extend_enable_vblank(dev);
+
+               extend_window_resume(dev);
+       } else {
+               extend_window_suspend(dev);
+
+               drm_disp->enable = false;
+
+               rk_drm_disp_handle(drm_disp,0,RK_DRM_SCREEN_BLANK);
+
+               ctx->suspended = true;
+       }
+
+       return 0;
+}
+
+static int extend_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct extend_context *ctx;
+       struct rockchip_drm_subdrv *subdrv;
+       struct rockchip_drm_panel_info *panel;
+       struct rk_drm_display *drm_display = NULL;
+       int ret = -EINVAL;
+
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+
+       g_dev = dev;
+       ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+
+       panel = devm_kzalloc(dev, sizeof(struct rockchip_drm_panel_info), GFP_KERNEL);
+       ctx->panel = panel;
+
+       drm_display = rk_drm_get_diplay(RK_DRM_EXTEND_SCREEN);
+       ctx->drm_disp = drm_display;
+       ctx->default_win = 0;
+
+       drm_display->event_call_back = extend_event_call_back_handle;
+
+       DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue);
+       atomic_set(&ctx->wait_vsync_event, 0);
+
+       subdrv = &ctx->subdrv;
+
+       subdrv->dev = dev;
+       subdrv->manager = &extend_manager;
+       subdrv->probe = extend_subdrv_probe;
+       subdrv->remove = extend_subdrv_remove;
+
+       mutex_init(&ctx->lock);
+
+       platform_set_drvdata(pdev, ctx);
+
+       pm_runtime_enable(dev);
+       pm_runtime_get_sync(dev);
+       
+       //extend_commit(dev);
+       extend_activate(ctx, true);
+
+       rockchip_drm_subdrv_register(subdrv);
+
+       return 0;
+}
+
+static int extend_remove(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct extend_context *ctx = platform_get_drvdata(pdev);
+
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+
+       rockchip_drm_subdrv_unregister(&ctx->subdrv);
+
+       if (ctx->suspended)
+               goto out;
+
+       pm_runtime_set_suspended(dev);
+       pm_runtime_put_sync(dev);
+
+out:
+       pm_runtime_disable(dev);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int extend_suspend(struct device *dev)
+{
+       struct extend_context *ctx = get_extend_context(dev);
+
+       /*
+        * do not use pm_runtime_suspend(). if pm_runtime_suspend() is
+        * called here, an error would be returned by that interface
+        * because the usage_count of pm runtime is more than 1.
+        */
+       if (!pm_runtime_suspended(dev))
+               return extend_activate(ctx, false);
+
+       return 0;
+}
+
+static int extend_resume(struct device *dev)
+{
+       struct extend_context *ctx = get_extend_context(dev);
+
+       /*
+        * if entered to sleep when lcd panel was on, the usage_count
+        * of pm runtime would still be 1 so in this case, fimd driver
+        * should be on directly not drawing on pm runtime interface.
+        */
+       if (!pm_runtime_suspended(dev)) {
+               int ret;
+
+               ret = extend_activate(ctx, true);
+               if (ret < 0)
+                       return ret;
+
+               /*
+                * in case of dpms on(standby), extend_apply function will
+                * be called by encoder's dpms callback to update fimd's
+                * registers but in case of sleep wakeup, it's not.
+                * so extend_apply function should be called at here.
+                */
+               extend_apply(dev);
+       }
+
+       return 0;
+}
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+static int extend_runtime_suspend(struct device *dev)
+{
+       struct extend_context *ctx = get_extend_context(dev);
+
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+
+       return extend_activate(ctx, false);
+}
+
+static int extend_runtime_resume(struct device *dev)
+{
+       struct extend_context *ctx = get_extend_context(dev);
+
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+
+       return extend_activate(ctx, true);
+}
+#endif
+
+static const struct dev_pm_ops extend_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(extend_suspend, extend_resume)
+       SET_RUNTIME_PM_OPS(extend_runtime_suspend, extend_runtime_resume, NULL)
+};
+
+struct platform_driver extend_platform_driver = {
+       .probe          = extend_probe,
+       .remove         = extend_remove,
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = "extend-display",
+               .pm     = &extend_pm_ops,
+       },
+};
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_extend.h b/drivers/gpu/drm/rockchip/rockchip_drm_extend.h
new file mode 100644 (file)
index 0000000..d9696e8
--- /dev/null
@@ -0,0 +1,37 @@
+#include "../../../video/rockchip/rk_drm_fb.h"
+#include "../../../video/rockchip/hdmi/rk_hdmi.h"
+#define WINDOWS_NR     4
+#define MAX_HDMI_WIDTH   1920
+#define MAX_HDMI_HEIGHT  1080
+
+#define get_extend_context(dev)        platform_get_drvdata(to_platform_device(dev))
+
+struct extend_win_data {
+       unsigned int            offset_x;
+       unsigned int            offset_y;
+       unsigned int            ovl_width;
+       unsigned int            ovl_height;
+       unsigned int            fb_width;
+       unsigned int            fb_height;
+       unsigned int            bpp;
+       dma_addr_t              dma_addr;
+       unsigned int            buf_offsize;
+       unsigned int            line_size;      /* bytes */
+       bool                    enabled;
+       bool                    resume;
+};
+
+struct extend_context {
+       struct rockchip_drm_subdrv      subdrv;
+       int                             vblank_en;
+       struct drm_crtc                 *crtc;
+       struct rk_drm_display           *drm_disp;
+       struct extend_win_data          win_data[WINDOWS_NR];
+       unsigned int                    default_win;
+       bool                            suspended;
+       struct mutex                    lock;
+       wait_queue_head_t               wait_vsync_queue;
+       atomic_t                        wait_vsync_event;
+       
+       struct rockchip_drm_panel_info *panel;
+};
index 956c7cc064df40e47ccde541713e131386010e8a..fe32195fb249fa8d9175b5f5cce47ce5235a1f04 100644 (file)
@@ -136,8 +136,10 @@ int rockchip_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
        overlay->mode_width = crtc->mode.hdisplay;
        overlay->mode_height = crtc->mode.vdisplay;
        overlay->refresh = crtc->mode.vrefresh;
+       overlay->pixclock = crtc->mode.clock*1000;
        overlay->scan_flag = crtc->mode.flags;
 
+//     printk("--->yzq %s crtc->mode->refresh =%d \n",__func__,crtc->mode.vrefresh);
        DRM_DEBUG_KMS("overlay : offset_x/y(%d,%d), width/height(%d,%d)",
                        overlay->crtc_x, overlay->crtc_y,
                        overlay->crtc_width, overlay->crtc_height);
index 3fa19ea35b06dada295db6c670f02145b3b75ad2..4a09a72010d5f8ebd94b6ff330088bf184910faa 100644 (file)
@@ -39,11 +39,10 @@ static struct device *g_dev = NULL;
 
 static bool primary_display_is_connected(struct device *dev)
 {
-       DRM_DEBUG_KMS("%s\n", __FILE__);
 
        /* TODO. */
 
-       return true;
+       return false;
 }
 
 static void *primary_get_panel(struct device *dev)
@@ -140,12 +139,13 @@ static void primary_commit(struct device *dev)
 {
        struct primary_context *ctx = get_primary_context(dev);
        struct rk_drm_display *drm_disp = ctx->drm_disp;
+       struct rockchip_drm_panel_info *panel = (struct rockchip_drm_panel_info *)primary_get_panel(dev);
+       struct fb_videomode *mode;
 
        printk(KERN_ERR"%s %d\n", __func__,__LINE__);
        if (ctx->suspended)
                return;
-
-       drm_disp->mode_id = drm_disp->best_mode;
+       drm_disp->mode = &panel->timing;
        drm_disp->enable = true;
        rk_drm_disp_handle(drm_disp,0,RK_DRM_SCREEN_SET);
 }
@@ -201,7 +201,6 @@ static void primary_event_call_back_handle(struct rk_drm_display *drm_disp,int w
 
                        drm_handle_vblank(drm_dev, manager->pipe);
                        rockchip_drm_crtc_finish_pageflip(drm_dev, manager->pipe);
-
                        /* set wait vsync event to zero and wake up queue. */
                        if (atomic_read(&ctx->wait_vsync_event)) {
                                atomic_set(&ctx->wait_vsync_event, 0);
@@ -280,7 +279,12 @@ static void primary_win_set_colkey(struct device *dev, unsigned int win)
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
 }
-
+#if 0
+static ktime_t win_start;
+static ktime_t win_end;
+static ktime_t win_start1;
+static ktime_t win_end1;
+#endif
 static void primary_win_commit(struct device *dev, int zpos)
 {
        struct primary_context *ctx = get_primary_context(dev);
@@ -301,6 +305,14 @@ static void primary_win_commit(struct device *dev, int zpos)
 
        if (win < 0 || win > WINDOWS_NR)
                return;
+#if 0
+       if(win == 0){
+               win_start = ktime_get();
+               win_start = ktime_sub(win_start, win_end);
+               printk("user flip buffer time %dus\n", (int)ktime_to_us(win_start));
+       //      win_start = ktime_get();
+       }
+#endif
        rk_win = &drm_disp->win[win];
        win_data = &ctx->win_data[win];
        switch(win_data->bpp){
@@ -331,6 +343,14 @@ static void primary_win_commit(struct device *dev, int zpos)
        rk_drm_disp_handle(drm_disp,1<<win,RK_DRM_WIN_COMMIT | RK_DRM_DISPLAY_COMMIT);
                
        win_data->enabled = true;
+#if 0
+       if(win ==0){
+       //      win_end = ktime_get();
+       //      win_end = ktime_sub(win_end, win_start);
+       //      printk("flip buffer time %dus\n", (int)ktime_to_us(win_end));
+               win_end = ktime_get();
+       }
+#endif
 
 }
 
@@ -513,7 +533,8 @@ static int primary_probe(struct platform_device *pdev)
        struct rockchip_drm_subdrv *subdrv;
        struct rockchip_drm_panel_info *panel;
        struct rk_drm_display *drm_display = NULL;
-       int ret = -EINVAL;
+       struct fb_modelist *modelist;
+       struct fb_videomode *mode;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
@@ -528,7 +549,9 @@ static int primary_probe(struct platform_device *pdev)
        drm_display = rk_drm_get_diplay(RK_DRM_PRIMARY_SCREEN);
        ctx->drm_disp = drm_display;
        ctx->default_win = 0;
-       memcpy(&panel->timing,drm_display->mode,sizeof(struct fb_videomode));
+       modelist = list_first_entry(drm_display->modelist, struct fb_modelist, list);
+       mode = &modelist->mode;
+       memcpy(&panel->timing,mode,sizeof(struct fb_videomode));
 
        drm_display->event_call_back = primary_event_call_back_handle;
 
@@ -549,7 +572,7 @@ static int primary_probe(struct platform_device *pdev)
        pm_runtime_enable(dev);
        pm_runtime_get_sync(dev);
        
-       primary_commit(dev);
+       //primary_commit(dev);
        primary_activate(ctx, true);
 
        rockchip_drm_subdrv_register(subdrv);
index 27a76ee5f7ab250811b7fc89c4bd5bac6031040e..71d8803c788c4c373207eaba67b85a5a487d0a6f 100755 (executable)
@@ -1,6 +1,6 @@
 menuconfig RK_HDMI
        bool "Rockchip HDMI support"
-       depends on FB_ROCKCHIP
+       depends on FB_ROCKCHIP || DRM_ROCKCHIP
        select FB_MODE_HELPERS
        
 if RK_HDMI
index 971f16810c5ff1cf954acdf5ef4e14341614294f..c045d77021a05191b6f681b306bf0f8e75191a1a 100755 (executable)
@@ -171,10 +171,16 @@ static struct rk_display_driver display_hdmi = {
 };
 
 static struct rk_display_device *display_device_hdmi = NULL;
+#ifdef CONFIG_DRM_ROCKCHIP
+extern void rk_drm_display_register(struct rk_display_ops *extend_ops, void *displaydata,int type);
+#endif
 
 void hdmi_register_display_sysfs(struct hdmi *hdmi, struct device *parent)
 {
        display_device_hdmi = rk_display_device_register(&display_hdmi, parent, hdmi);
+#ifdef CONFIG_DRM_ROCKCHIP
+       rk_drm_display_register(&hdmi_display_ops,hdmi,SCREEN_HDMI);
+#endif
 }
 
 void hdmi_unregister_display_sysfs(struct hdmi *hdmi)
index 9dd5724f7e599b90243baa7dda7c061faa344ee6..0f928f6c3e05ce7dedd8b9be890c63f4adc2a666 100755 (executable)
@@ -3144,6 +3144,9 @@ static irqreturn_t rk3288_lcdc_isr(int irq, void *dev_id)
                        complete(&(lcdc_dev->driver.frame_done));
                        spin_unlock(&(lcdc_dev->driver.cpl_lock));
                }
+#ifdef CONFIG_DRM_ROCKCHIP
+               lcdc_dev->driver.irq_call_back(&lcdc_dev->driver);
+#endif 
                lcdc_dev->driver.vsync_info.timestamp = timestamp;
                wake_up_interruptible_all(&lcdc_dev->driver.vsync_info.wait);
 
index eb99fa6188d2caaeb4c2c652a1f0709bbb0b504f..41e7bfa00bbbac9bd7a303bd52ab9c9b9978674c 100755 (executable)
@@ -29,6 +29,7 @@
 #include <linux/rk_fb.h>
 #include <linux/linux_logo.h>
 #include <linux/dma-mapping.h>
+#include <drm/drm_os_linux.h>
 #include <linux/of_gpio.h>
 #ifdef CONFIG_OF
 #include <linux/of.h>
@@ -38,6 +39,7 @@
 #include <dt-bindings/rkfb/rk_fb.h>
 #endif
 
+#include <linux/display-sys.h>
 #include "rk_drm_fb.h"
 __weak int support_uboot_display(void)
 {
@@ -47,6 +49,21 @@ static struct platform_device *drm_fb_pdev;
 static struct rk_fb_trsm_ops *trsm_lvds_ops;
 static struct rk_fb_trsm_ops *trsm_edp_ops;
 static struct rk_fb_trsm_ops *trsm_mipi_ops;
+static struct rk_display_device *disp_hdmi_devices;
+void rk_drm_display_register(struct rk_display_ops *extend_ops, void *displaydata,int type)
+{
+       switch(type) {
+               case SCREEN_HDMI:
+                       disp_hdmi_devices = kzalloc(sizeof(struct rk_display_device), GFP_KERNEL);
+                       disp_hdmi_devices->priv_data = displaydata;
+                       disp_hdmi_devices->ops = extend_ops;
+                       break;
+               default:
+                       printk(KERN_WARNING "%s:un supported extend display:%d!\n",
+                       __func__, type);
+               break;
+       }
+}
 int rk_fb_trsm_ops_register(struct rk_fb_trsm_ops *ops, int type)
 {
        switch (type) {
@@ -70,6 +87,30 @@ int rk_fb_trsm_ops_register(struct rk_fb_trsm_ops *ops, int type)
        return 0;
 }
 
+struct rk_display_device *rk_drm_extend_display_get(int type)
+{
+       struct rk_display_device *extend_display = NULL;
+       switch (type) {
+               case SCREEN_HDMI:
+                       if(disp_hdmi_devices)
+                               extend_display = disp_hdmi_devices;
+                       else
+                               printk(KERN_WARNING "%s:screen hdmi ops is NULL!\n",__func__);
+                       break;
+               default:
+                       printk(KERN_WARNING "%s:un supported extend display:%d!\n",
+                       __func__, type);
+                       break;
+       }
+       return extend_display;
+}
+#if 0
+struct void *get_extend_drv(void)
+{
+       struct rk_display_device *extend_display = rk_drm_extend_display_get(SCREEN_HDMI);
+       return extend_display->priv_data;
+}
+#endif
 struct rk_fb_trsm_ops *rk_fb_trsm_ops_get(int type)
 {
        struct rk_fb_trsm_ops *ops;
@@ -320,8 +361,8 @@ static int init_lcdc_device_driver(struct rk_drm_screen_private *screen_priv,
        if (dev_drv->prop == PRMRY) {
                rk_fb_set_prmry_screen(screen);
                rk_fb_get_prmry_screen(screen);
+               dev_drv->trsm_ops = rk_fb_trsm_ops_get(screen->type);
        }
-       dev_drv->trsm_ops = rk_fb_trsm_ops_get(screen->type);
 
        return 0;
 
@@ -483,19 +524,45 @@ static int rk_fb_wait_for_vsync_thread(void *data)
                int ret = wait_event_interruptible(dev_drv->vsync_info.wait,
                        !ktime_equal(timestamp, dev_drv->vsync_info.timestamp) &&
                        (dev_drv->vsync_info.active || dev_drv->vsync_info.irq_stop));
-
+#if 1
+               if(atomic_read(&drm_screen_priv->wait_vsync_done)){
+                       atomic_set(&drm_screen_priv->wait_vsync_done,0);
+                       DRM_WAKEUP(&drm_screen_priv->wait_vsync_queue);
+               }
                if(!ret && drm_display->event_call_back)
                        drm_display->event_call_back(drm_display,0,RK_DRM_CALLBACK_VSYNC);
+#endif
        }
 
        return 0;
 }
+
+static void rk_drm_irq_handle(struct rk_lcdc_driver *dev_drv)
+{
+       struct rk_drm_private *rk_drm_priv = platform_get_drvdata(drm_fb_pdev);
+       struct rk_drm_screen_private *drm_screen_priv = NULL;
+       struct rk_drm_display *drm_display = NULL;
+       if(dev_drv->prop == PRMRY)
+               drm_screen_priv = &rk_drm_priv->screen_priv[0];
+       else if(dev_drv->prop == EXTEND)
+               drm_screen_priv = &rk_drm_priv->screen_priv[1];
+       if(drm_screen_priv == NULL)
+               return -1;
+       drm_display = &drm_screen_priv->drm_disp;
+       if(atomic_read(&drm_screen_priv->wait_vsync_done)){
+                       atomic_set(&drm_screen_priv->wait_vsync_done,0);
+                       DRM_WAKEUP(&drm_screen_priv->wait_vsync_queue);
+       }
+
+       if(drm_display->event_call_back)
+                       drm_display->event_call_back(drm_display,0,RK_DRM_CALLBACK_VSYNC);
+}
 int rk_fb_register(struct rk_lcdc_driver *dev_drv,
                struct rk_lcdc_win *win, int id)
 {
        struct rk_drm_private *rk_drm_priv = platform_get_drvdata(drm_fb_pdev);
        struct rk_drm_display *drm_display = NULL;
-       struct rk_win_data *win_data = NULL;
+       struct rk_drm_screen_private *drm_screen_priv = NULL;
        int i=0;
 
        if (rk_drm_priv->num_screen == RK30_MAX_LCDC_SUPPORT)
@@ -504,29 +571,53 @@ int rk_fb_register(struct rk_lcdc_driver *dev_drv,
                if (!rk_drm_priv->screen_priv[i].lcdc_dev_drv) 
                        break;
        }
-       
        rk_drm_priv->num_screen++;
-       rk_drm_priv->screen_priv[i].lcdc_dev_drv = dev_drv;
-       rk_drm_priv->screen_priv[i].lcdc_dev_drv->id = id;
+       drm_screen_priv = &rk_drm_priv->screen_priv[i]; 
+       drm_screen_priv->lcdc_dev_drv = dev_drv;
+       drm_screen_priv->lcdc_dev_drv->id = id;
 
-       init_lcdc_device_driver(&rk_drm_priv->screen_priv[i],win,i);
+       init_lcdc_device_driver(drm_screen_priv,win,i);
+       dev_drv->irq_call_back = rk_drm_irq_handle;
        
-       drm_display = &rk_drm_priv->screen_priv[i].drm_disp;
+       drm_display = &drm_screen_priv->drm_disp;
        drm_display->num_win = dev_drv->lcdc_win_num;
+       atomic_set(&drm_screen_priv->wait_vsync_done, 1);
+       DRM_INIT_WAITQUEUE(&drm_screen_priv->wait_vsync_queue);
        if(dev_drv->prop == PRMRY){
+               struct fb_modelist *modelist_new;
+               struct fb_modelist *modelist;
+               struct fb_videomode *mode;
+               drm_display->modelist = kmalloc(sizeof(struct list_head),GFP_KERNEL);
+               INIT_LIST_HEAD(drm_display->modelist);
+               modelist_new = kmalloc(sizeof(struct fb_modelist),
+                                 GFP_KERNEL);
                drm_display->screen_type = RK_DRM_PRIMARY_SCREEN;
                drm_display->num_videomode = 1;
                drm_display->best_mode = 0;
                drm_display->is_connected = 1;
-               drm_display->mode = &dev_drv->cur_screen->mode;
-               printk("----->yzq mode dclk=%d\n",drm_display->mode->pixclock);
+               memcpy(&modelist_new->mode,&dev_drv->cur_screen->mode,sizeof(struct fb_videomode));
+
+       //      printk("---->yzq mode xres=%d yres=%d \n",modelist_new->mode.xres,modelist_new->mode.yres);
+               list_add_tail(&modelist_new->list,drm_display->modelist);
+
+               modelist = list_first_entry(drm_display->modelist, struct fb_modelist, list);
+               mode=&modelist->mode;
+       //      printk("---->yzq 1mode xres=%d yres=%d \n",mode->xres,mode->yres);
+
        }else if(dev_drv->prop == EXTEND){
+               struct list_head *modelist;
+               drm_screen_priv->ex_display = rk_drm_extend_display_get(SCREEN_HDMI);
+       //      printk("------>yzq ex_display=%x\n",drm_screen_priv->ex_display);
                drm_display->screen_type = RK_DRM_EXTEND_SCREEN;
-               drm_display->num_videomode = 1;
-               drm_display->best_mode = 0;
                drm_display->is_connected = 0;
+#if 0
+               drm_screen_priv->ex_display->ops->getmodelist(drm_screen_priv->ex_display,&modelist);
+
+               memcpy(&drm_display->modelist,modelist,sizeof(struct list_head));
+               drm_display->is_connected = drm_screen_priv->ex_display->ops->getstatus(drm_screen_priv->ex_display);
+#endif
        }
-       if (dev_drv->prop == PRMRY) {
+       if (1){//dev_drv->prop == PRMRY) {
                init_waitqueue_head(&dev_drv->vsync_info.wait);
                dev_drv->vsync_info.thread = kthread_run(rk_fb_wait_for_vsync_thread,
                                dev_drv, "fb-vsync");
@@ -593,6 +684,80 @@ static int rk_drm_screen_blank(struct rk_drm_display *drm_disp)
 
        return 0;
 }
+
+int rk_fb_disp_scale(u8 scale_x, u8 scale_y, u8 lcdc_id)
+{
+       return 0;
+}
+/**********************************************************************
+this is for hdmi
+name: lcdc device name ,lcdc0 , lcdc1
+***********************************************************************/
+struct rk_lcdc_driver *rk_get_lcdc_drv(char *name)
+{
+       struct rk_drm_private *rk_drm_priv = platform_get_drvdata(drm_fb_pdev);
+       int i = 0;
+       for (i = 0; i < rk_drm_priv->num_screen; i++) {
+               if (!strcmp(rk_drm_priv->screen_priv[i].lcdc_dev_drv->name, name))
+                       break;
+       }
+       return rk_drm_priv->screen_priv[i].lcdc_dev_drv;
+
+}
+int rk_fb_switch_screen(struct rk_screen *screen , int enable, int lcdc_id)
+{
+       struct rk_drm_private *rk_drm_priv = platform_get_drvdata(drm_fb_pdev);
+       struct rk_lcdc_driver *dev_drv = NULL;
+       struct rk_drm_display *drm_disp = NULL;
+       char name[6];
+       int i;
+       
+       sprintf(name, "lcdc%d", lcdc_id);
+
+       if (rk_drm_priv->disp_mode != DUAL) {
+               dev_drv = rk_drm_priv->screen_priv[0].lcdc_dev_drv;
+       } else {
+
+               for (i = 0; i < rk_drm_priv->num_screen; i++) {
+                       if (rk_drm_priv->screen_priv[i].lcdc_dev_drv->prop == EXTEND) {
+                               drm_disp = &rk_drm_priv->screen_priv[i].drm_disp;
+                               dev_drv = rk_drm_priv->screen_priv[i].lcdc_dev_drv;
+                               break;
+                       }
+               }
+
+               if (i == rk_drm_priv->num_screen) {
+                       printk(KERN_ERR "%s driver not found!", name);
+                       return -ENODEV;
+               }
+       }
+       printk("hdmi %s lcdc%d\n", enable ? "connect to" : "remove from", dev_drv->id);
+
+
+       if(enable && !drm_disp->is_connected ){
+               struct list_head *modelist;
+               struct fb_modelist *modelist1;
+               struct fb_videomode *mode;
+               struct rk_display_device *ex_display = rk_drm_priv->screen_priv[i].ex_display;
+               memcpy(dev_drv->cur_screen, screen, sizeof(struct rk_screen));
+               if(ex_display == NULL)
+                       ex_display = rk_drm_extend_display_get(SCREEN_HDMI);
+               rk_drm_priv->screen_priv[i].ex_display = ex_display;
+               ex_display->ops->getmodelist(ex_display,&modelist);
+               
+               drm_disp->modelist = modelist;
+
+               drm_disp->is_connected = true;
+               drm_disp->event_call_back(drm_disp,0,RK_DRM_CALLBACK_HOTPLUG);
+       }else{
+//     printk("----->yzq %s %d \n",__func__,__LINE__);
+               drm_disp->is_connected = false;
+               drm_disp->event_call_back(drm_disp,0,RK_DRM_CALLBACK_HOTPLUG);
+//     printk("----->yzq %s %d \n",__func__,__LINE__);
+       }
+
+
+}
 static int rk_drm_screen_videomode_set(struct rk_drm_display *drm_disp)
 {
 //     struct rk_drm_private *rk_drm_priv = platform_get_drvdata(drm_fb_pdev);
@@ -605,14 +770,29 @@ static int rk_drm_screen_videomode_set(struct rk_drm_display *drm_disp)
                return -1;
        }
 
-       if(mode != &lcdc_dev->cur_screen->mode)
-               memcpy(&lcdc_dev->cur_screen->mode,mode,sizeof(struct fb_videomode));
-       
+//     printk("----->yzq %s %d xres=%d yres=%d refresh=%d \n",__func__,__LINE__,mode->xres,mode->yres,mode->refresh);
+       if(lcdc_dev->prop == PRMRY){
+               if(mode != &lcdc_dev->cur_screen->mode)
+                       memcpy(&lcdc_dev->cur_screen->mode,mode,sizeof(struct fb_videomode));
+
+       }else{
+               struct rk_display_device *ex_display = drm_screen_priv->ex_display;
+               if(ex_display == NULL)
+                       ex_display = rk_drm_extend_display_get(SCREEN_HDMI);
+
+       //      printk("------>yzq ex_display=%x\n",ex_display);
+               if(ex_display == NULL){
+                       printk(KERN_ERR"-->%s can not find extend display ops\n",__func__);
+                       return -1;
+               }
+               ex_display->ops->setmode(ex_display, mode);
+       }
        if(!lcdc_dev->atv_layer_cnt)
                lcdc_dev->ops->open(lcdc_dev, 0,true);
-       
+
        lcdc_dev->ops->ovl_mgr(lcdc_dev, 3210, 1);
        lcdc_dev->ops->load_screen(lcdc_dev,1);
+
        return 0;
 }
 
@@ -664,9 +844,12 @@ static int rk_drm_display_commit(struct rk_drm_display *drm_disp)
        lcdc_dev->ops->lcdc_reg_update(lcdc_dev);
        return 0;
 }
+
 int rk_drm_disp_handle(struct rk_drm_display *drm_disp,unsigned int win_id,unsigned int cmd_id)
 {
 //     struct rk_drm_private *rk_drm_priv = platform_get_drvdata(drm_fb_pdev);
+       struct rk_drm_screen_private *drm_screen_priv =
+               container_of(drm_disp, struct rk_drm_screen_private, drm_disp);
        int i=0;
        for( i=1; i<RK_DRM_CMD_MASK; i=i<<1){
                switch(i&cmd_id){
@@ -680,8 +863,17 @@ int rk_drm_disp_handle(struct rk_drm_display *drm_disp,unsigned int win_id,unsig
                                rk_drm_win_commit(drm_disp, win_id);
                                break;
                        case RK_DRM_DISPLAY_COMMIT:
+                               if(win_id & i){
+                                       if (!wait_event_timeout(drm_screen_priv->wait_vsync_queue,
+                                                               !atomic_read(&drm_screen_priv->wait_vsync_done),
+                                                               DRM_HZ/20))
+                                               printk("wait frame timed out.\n");
+                               }
+
                                rk_drm_display_commit(drm_disp);
-                               break;
+                               if(win_id & i){
+                                       atomic_set(&drm_screen_priv->wait_vsync_done,1);
+                               }
                }
                        
        }
index a24a925dfae0d388da9229cb8f0d308ac201bdc5..4fb45ebcfdb3b852649bbca56a604f63ed43067a 100644 (file)
@@ -3,7 +3,8 @@
 #define RK_DRM_WIN_MASK  0x7fff
 #define RK_DRM_CMD_MASK  0x7fff
 
-#define RK_DRM_CALLBACK_VSYNC   0x1
+#define RK_DRM_CALLBACK_VSYNC     0x1
+#define RK_DRM_CALLBACK_HOTPLUG   0x2
 
 #define RK_DRM_SCREEN_SET      1<<0
 #define        RK_DRM_SCREEN_BLANK     1<<1
@@ -35,13 +36,14 @@ struct rk_win_data {
 struct rk_drm_display {
 /***** hardware define *****/ 
        enum drm_screen_type screen_type;
-       struct fb_videomode *mode;
+
+       struct list_head *modelist;
        int num_videomode;
        int best_mode;
        bool is_connected;
 
 /***** user fill info  *****/
-       int mode_id;
+       struct fb_videomode *mode;
        bool enable;
        struct rk_win_data win[RK30_MAX_LAYER_SUPPORT]; 
        int num_win;
@@ -52,8 +54,12 @@ struct rk_drm_display {
 struct rk_drm_screen_private {
        struct rk_drm_display drm_disp;
        struct rk_screen screen;
+       atomic_t wait_vsync_done;
+       wait_queue_head_t wait_vsync_queue;
        struct rk_fb_trsm_ops *trsm_ops;
        struct rk_lcdc_driver *lcdc_dev_drv;
+
+       struct rk_display_device *ex_display;
 };
 struct rk_drm_private {
        struct rk_drm_screen_private screen_priv[RK_DRM_MAX_SCREEN_NUM];
index 2a4589eb53db511867f9d80a7bce91e61bf61bc2..8cc9e78da782c385f7277652805056df5b32b534 100755 (executable)
@@ -515,6 +515,9 @@ struct rk_lcdc_driver {
        struct list_head pwrlist_head;
        struct rk_lcdc_drv_ops *ops;
        struct rk_fb_trsm_ops *trsm_ops;
+#ifdef CONFIG_DRM_ROCKCHIP
+       void (*irq_call_back)(struct rk_lcdc_driver *driver);
+#endif
 
 };