move driver/video/display/display-sys.c to driver/video/rockchip/display-sys.c
authorzwl <zwl@rock-chips.com>
Thu, 13 Feb 2014 12:41:03 +0000 (20:41 +0800)
committerzwl <zwl@rock-chips.com>
Thu, 13 Feb 2014 12:41:03 +0000 (20:41 +0800)
drivers/video/display/display-sys.c [deleted file]
drivers/video/rockchip/Makefile
drivers/video/rockchip/display-sys.c [new file with mode: 0644]

diff --git a/drivers/video/display/display-sys.c b/drivers/video/display/display-sys.c
deleted file mode 100755 (executable)
index 738b568..0000000
+++ /dev/null
@@ -1,448 +0,0 @@
-#include <linux/module.h>
-#include <linux/ctype.h>
-#include <linux/idr.h>
-#include <linux/err.h>
-#include <linux/kdev_t.h>
-#include <linux/display-sys.h>
-
-static struct list_head display_device_list;
-
-static ssize_t display_show_name(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       struct rk_display_device *dsp = dev_get_drvdata(dev);
-       return snprintf(buf, PAGE_SIZE, "%s\n", dsp->name);
-}
-
-static ssize_t display_show_type(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       struct rk_display_device *dsp = dev_get_drvdata(dev);
-       return snprintf(buf, PAGE_SIZE, "%s\n", dsp->type);
-}
-
-static ssize_t display_show_enable(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       struct rk_display_device *dsp = dev_get_drvdata(dev);
-       int enable;
-       if(dsp->ops && dsp->ops->getenable)
-               enable = dsp->ops->getenable(dsp);
-       else
-               return 0;
-       return snprintf(buf, PAGE_SIZE, "%d\n", enable);
-}
-
-static ssize_t display_store_enable(struct device *dev, 
-                                               struct device_attribute *attr,
-                                               const char *buf, size_t size)
-{
-       struct rk_display_device *dsp = dev_get_drvdata(dev);
-       int enable;
-       
-       sscanf(buf, "%d", &enable);
-       if(dsp->ops && dsp->ops->setenable)
-               dsp->ops->setenable(dsp, enable);
-       return size;
-}
-
-static ssize_t display_show_connect(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       struct rk_display_device *dsp = dev_get_drvdata(dev);
-       int connect;
-       if(dsp->ops && dsp->ops->getstatus)
-               connect = dsp->ops->getstatus(dsp);
-       else
-               return 0;
-       return snprintf(buf, PAGE_SIZE, "%d\n", connect);
-}
-
-static int mode_string(char *buf, unsigned int offset,
-                      const struct fb_videomode *mode)
-{
-//     char m = 'U';
-       char v = 'p';
-
-//     if (mode->flag & FB_MODE_IS_DETAILED)
-//             m = 'D';
-//     if (mode->flag & FB_MODE_IS_VESA)
-//             m = 'V';
-//     if (mode->flag & FB_MODE_IS_STANDARD)
-//             m = 'S';
-
-       if (mode->vmode & FB_VMODE_INTERLACED)
-               v = 'i';
-       if (mode->vmode & FB_VMODE_DOUBLE)
-               v = 'd';
-
-       return snprintf(&buf[offset], PAGE_SIZE - offset, "%dx%d%c-%d\n",
-                       mode->xres, mode->yres, v, mode->refresh);
-}
-static ssize_t display_show_modes(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       struct rk_display_device *dsp = dev_get_drvdata(dev);
-       struct list_head *modelist, *pos;
-       struct fb_modelist *fb_modelist;
-       const struct fb_videomode *mode;
-       int i;
-       if(dsp->ops && dsp->ops->getmodelist)
-       {
-               if(dsp->ops->getmodelist(dsp, &modelist))
-                       return -EINVAL;
-       }
-       else
-               return 0;
-
-       i = 0;
-       list_for_each(pos, modelist) {
-               fb_modelist = list_entry(pos, struct fb_modelist, list);
-               mode = &fb_modelist->mode;
-               i += mode_string(buf, i, mode);
-       }
-       return i;
-}
-
-static ssize_t display_show_mode(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       struct rk_display_device *dsp = dev_get_drvdata(dev);
-       struct fb_videomode mode;
-       
-       if(dsp->ops && dsp->ops->getmode)
-               if(dsp->ops->getmode(dsp, &mode) == 0)
-                       return mode_string(buf, 0, &mode);
-       return 0;
-}
-
-static ssize_t display_store_mode(struct device *dev, 
-                                               struct device_attribute *attr,
-                                               const char *buf, size_t count)
-{
-       struct rk_display_device *dsp = dev_get_drvdata(dev);
-       char mstr[100];
-       struct list_head *modelist, *pos;
-       struct fb_modelist *fb_modelist;
-       struct fb_videomode *mode;     
-       size_t i;                   
-
-       if(dsp->ops && dsp->ops->getmodelist)
-       {
-               if(dsp->ops && dsp->ops->getmodelist)
-               {
-                       if(dsp->ops->getmodelist(dsp, &modelist))
-                               return -EINVAL;
-               }
-               list_for_each(pos, modelist) {
-                       fb_modelist = list_entry(pos, struct fb_modelist, list);
-                       mode = &fb_modelist->mode;
-                       i = mode_string(mstr, 0, mode);
-                       if (strncmp(mstr, buf, max(count, i)) == 0) {
-                               if(dsp->ops && dsp->ops->setmode)
-                                       dsp->ops->setmode(dsp, mode);
-                               return count;
-                       }
-               }
-       }
-       return -EINVAL;
-}
-
-static ssize_t display_show_scale(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       struct rk_display_device *dsp = dev_get_drvdata(dev);
-       int xscale, yscale;
-       
-       if(dsp->ops && dsp->ops->getscale) {
-               xscale = dsp->ops->getscale(dsp, DISPLAY_SCALE_X);
-               yscale = dsp->ops->getscale(dsp, DISPLAY_SCALE_Y);
-               if(xscale && yscale)
-                       return snprintf(buf, PAGE_SIZE, "xscale=%d yscale=%d\n", xscale, yscale);
-       }
-       return -EINVAL;
-}
-
-static ssize_t display_store_scale(struct device *dev, 
-                                               struct device_attribute *attr,
-                                               const char *buf, size_t count)
-{
-       struct rk_display_device *dsp = dev_get_drvdata(dev);
-       int scale = 100;
-       
-       if(dsp->ops && dsp->ops->setscale) {
-               if(!strncmp(buf, "xscale", 6)) {
-                       sscanf(buf, "xscale=%d", &scale);
-                       dsp->ops->setscale(dsp, DISPLAY_SCALE_X, scale);
-               }
-               else if(!strncmp(buf, "yscale", 6)) {
-                       sscanf(buf, "yscale=%d", &scale);
-                       dsp->ops->setscale(dsp, DISPLAY_SCALE_Y, scale);
-               }
-               else {
-                       sscanf(buf, "%d", &scale);
-                       dsp->ops->setscale(dsp, DISPLAY_SCALE_X, scale);
-                       dsp->ops->setscale(dsp, DISPLAY_SCALE_Y, scale);
-               }
-               return count;
-       }
-       return -EINVAL;
-}
-
-static struct device_attribute display_attrs[] = {
-       __ATTR(name, S_IRUGO, display_show_name, NULL),
-       __ATTR(type, S_IRUGO, display_show_type, NULL),
-       __ATTR(enable, 0664, display_show_enable, display_store_enable),
-       __ATTR(connect, S_IRUGO, display_show_connect, NULL),
-       __ATTR(modes, S_IRUGO, display_show_modes, NULL),
-       __ATTR(mode, 0664, display_show_mode, display_store_mode),
-       __ATTR(scale, 0664, display_show_scale, display_store_scale),
-       __ATTR_NULL
-};
-
-static int display_suspend(struct device *dev, pm_message_t state)
-{
-       struct rk_display_device *dsp = dev_get_drvdata(dev);
-
-       mutex_lock(&dsp->lock);
-       if (likely(dsp->driver->suspend))
-               dsp->driver->suspend(dsp, state);
-       mutex_unlock(&dsp->lock);
-       return 0;
-};
-
-static int display_resume(struct device *dev)
-{
-       struct rk_display_device *dsp = dev_get_drvdata(dev);
-
-       mutex_lock(&dsp->lock);
-       if (likely(dsp->driver->resume))
-               dsp->driver->resume(dsp);
-       mutex_unlock(&dsp->lock);
-       return 0;
-};
-
-void rk_display_device_enable(struct rk_display_device *ddev)
-{
-#ifndef CONFIG_DISPLAY_AUTO_SWITCH     
-       return;
-#else
-       struct list_head *pos, *head = &display_device_list;
-       struct rk_display_device *dev = NULL, *dev_enabled = NULL, *dev_enable = NULL;
-       int enable = 0,connect, has_connect = 0;
-       
-       list_for_each(pos, head) {
-               dev = list_entry(pos, struct rk_display_device, list);
-               enable = dev->ops->getenable(dev);
-               connect = dev->ops->getstatus(dev);
-               if(connect)
-                       dev_enable = dev;
-               if(enable == 1)
-                       dev_enabled = dev;
-       }
-       // If no device is connected, enable highest priority device.
-       if(dev_enable == NULL) {
-               dev->ops->setenable(dev, 1);
-               return;
-       }
-       
-       if(dev_enable == dev_enabled) {
-               if(dev_enable != ddev)
-                       ddev->ops->setenable(ddev, 0);
-       }
-       else {
-               if(dev_enabled)
-                       dev_enabled->ops->setenable(dev_enabled, 0);
-               dev_enable->ops->setenable(dev_enable, 1);
-       }
-               
-
-#endif
-}
-EXPORT_SYMBOL(rk_display_device_enable);
-
-void rk_display_device_enable_other(struct rk_display_device *ddev)
-{
-#ifndef CONFIG_DISPLAY_AUTO_SWITCH     
-       return;
-#else
-       struct list_head *pos, *head = &display_device_list;
-       struct rk_display_device *dev;  
-       int connect = 0;
-       
-       list_for_each_prev(pos, head) {
-               dev = list_entry(pos, struct rk_display_device, list);
-               if(dev != ddev)
-               {
-                       connect = dev->ops->getstatus(dev);
-                       if(connect)
-                       {
-                               dev->ops->setenable(dev, 1);
-                               return;
-                       }
-               }
-       }
-#endif
-}
-EXPORT_SYMBOL(rk_display_device_enable_other);
-
-void rk_display_device_disable_other(struct rk_display_device *ddev)
-{
-#ifndef CONFIG_DISPLAY_AUTO_SWITCH
-       return;
-#else
-       struct list_head *pos, *head = &display_device_list;
-       struct rk_display_device *dev;  
-       int enable = 0;
-       
-       list_for_each(pos, head) {
-               dev = list_entry(pos, struct rk_display_device, list);
-               if(dev != ddev)
-               {
-                       enable = dev->ops->getenable(dev);
-                       if(enable)
-                               dev->ops->setenable(dev, 0);
-               }
-       }
-       ddev->ops->setenable(ddev, 1);
-#endif
-}
-EXPORT_SYMBOL(rk_display_device_disable_other);
-
-void rk_display_device_select(int priority)
-{
-       struct list_head *pos, *head = &display_device_list;
-       struct rk_display_device *dev;
-       int enable, found = 0;
-       
-       list_for_each(pos, head) {
-               dev = list_entry(pos, struct rk_display_device, list);
-               if(dev->priority == priority)
-                       found = 1;
-       }
-       
-       if(!found)
-       {
-               printk("[%s] select display interface %d not exist\n", __FUNCTION__, priority);
-               return;
-       }
-       
-       list_for_each(pos, head) {
-               dev = list_entry(pos, struct rk_display_device, list);
-               enable = dev->ops->getenable(dev);
-               if(dev->priority == priority)
-               {
-                       if(!enable)     
-                               dev->ops->setenable(dev, 1);
-               }
-               else if(enable) 
-                       dev->ops->setenable(dev, 0);
-       }
-}
-EXPORT_SYMBOL(rk_display_device_select);
-static struct mutex allocated_dsp_lock;
-static DEFINE_IDR(allocated_dsp);
-static struct class *display_class;
-
-struct rk_display_device *rk_display_device_register(struct rk_display_driver *driver,
-                                               struct device *parent, void *devdata)
-{
-       struct rk_display_device *new_dev = NULL;
-       int ret = -EINVAL;
-
-       if (unlikely(!driver))
-               return ERR_PTR(ret);
-
-       mutex_lock(&allocated_dsp_lock);
-       ret = idr_pre_get(&allocated_dsp, GFP_KERNEL);
-       mutex_unlock(&allocated_dsp_lock);
-       if (!ret)
-               return ERR_PTR(ret);
-
-       new_dev = kzalloc(sizeof(struct rk_display_device), GFP_KERNEL);
-       if (likely(new_dev) && unlikely(driver->probe(new_dev, devdata))) {
-               // Reserve the index for this display
-               mutex_lock(&allocated_dsp_lock);
-               ret = idr_get_new(&allocated_dsp, new_dev, &new_dev->idx);
-               mutex_unlock(&allocated_dsp_lock);
-
-               if (!ret) {
-                       new_dev->dev = device_create(display_class, parent,
-                                                    MKDEV(0, 0), new_dev,
-                                                    "%s", new_dev->type);
-                       if (!IS_ERR(new_dev->dev)) {
-                               new_dev->parent = parent;
-                               new_dev->driver = driver;
-                               if(parent)
-                                       new_dev->dev->driver = parent->driver;
-                               mutex_init(&new_dev->lock);
-                               // Add new device to display device list.
-                               {
-                                       struct list_head *pos, *head = &display_device_list;
-                                       struct rk_display_device *dev;
-                                       
-                                       list_for_each(pos, head) {
-                                               dev = list_entry(pos, struct rk_display_device, list);
-                                               if(dev->priority > new_dev->priority)
-                                                       break;
-                                       }
-                                       list_add_tail(&new_dev->list, pos);
-                               }
-                               return new_dev;
-                       }
-                       mutex_lock(&allocated_dsp_lock);
-                       idr_remove(&allocated_dsp, new_dev->idx);
-                       mutex_unlock(&allocated_dsp_lock);
-                       ret = -EINVAL;
-               }
-       }
-       kfree(new_dev);
-       return ERR_PTR(ret);
-}
-EXPORT_SYMBOL(rk_display_device_register);
-
-void rk_display_device_unregister(struct rk_display_device *ddev)
-{
-       if (!ddev)
-               return;
-       // Free device
-       mutex_lock(&ddev->lock);
-       device_unregister(ddev->dev);
-       mutex_unlock(&ddev->lock);
-       // Mark device index as avaliable
-       mutex_lock(&allocated_dsp_lock);
-       idr_remove(&allocated_dsp, ddev->idx);
-       mutex_unlock(&allocated_dsp_lock);
-       list_del(&ddev->list);
-       kfree(ddev);
-}
-EXPORT_SYMBOL(rk_display_device_unregister);
-
-static int __init rk_display_class_init(void)
-{
-       display_class = class_create(THIS_MODULE, "display");
-       if (IS_ERR(display_class)) {
-               printk(KERN_ERR "Failed to create display class\n");
-               display_class = NULL;
-               return -EINVAL;
-       }
-       display_class->dev_attrs = display_attrs;
-       display_class->suspend = display_suspend;
-       display_class->resume = display_resume;
-       mutex_init(&allocated_dsp_lock);
-       INIT_LIST_HEAD(&display_device_list);
-       return 0;
-}
-
-static void __exit rk_display_class_exit(void)
-{
-       class_destroy(display_class);
-}
-
-subsys_initcall(rk_display_class_init);
-module_exit(rk_display_class_exit);
-
-
-MODULE_AUTHOR("zhengyang@rock-chips.com");
-MODULE_DESCRIPTION("Driver for rk display device");
-MODULE_LICENSE("GPL");
index b3593154890a7159920d59e7257eb8fee646f34d..6db75ea4eca1bad7226fc0f4c1e618a3be366349 100755 (executable)
@@ -1,4 +1,4 @@
 obj-$(CONFIG_FB_ROCKCHIP) += rk_fb.o rkfb_sysfs.o lcdc/ 
 obj-$(CONFIG_RK_TRSM) += transmitter/
 obj-$(CONFIG_RGA_RK30) += rga/
-obj-$(CONFIG_RK_HDMI) += hdmi/
+obj-$(CONFIG_RK_HDMI) += display-sys.o hdmi/
diff --git a/drivers/video/rockchip/display-sys.c b/drivers/video/rockchip/display-sys.c
new file mode 100644 (file)
index 0000000..738b568
--- /dev/null
@@ -0,0 +1,448 @@
+#include <linux/module.h>
+#include <linux/ctype.h>
+#include <linux/idr.h>
+#include <linux/err.h>
+#include <linux/kdev_t.h>
+#include <linux/display-sys.h>
+
+static struct list_head display_device_list;
+
+static ssize_t display_show_name(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct rk_display_device *dsp = dev_get_drvdata(dev);
+       return snprintf(buf, PAGE_SIZE, "%s\n", dsp->name);
+}
+
+static ssize_t display_show_type(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct rk_display_device *dsp = dev_get_drvdata(dev);
+       return snprintf(buf, PAGE_SIZE, "%s\n", dsp->type);
+}
+
+static ssize_t display_show_enable(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct rk_display_device *dsp = dev_get_drvdata(dev);
+       int enable;
+       if(dsp->ops && dsp->ops->getenable)
+               enable = dsp->ops->getenable(dsp);
+       else
+               return 0;
+       return snprintf(buf, PAGE_SIZE, "%d\n", enable);
+}
+
+static ssize_t display_store_enable(struct device *dev, 
+                                               struct device_attribute *attr,
+                                               const char *buf, size_t size)
+{
+       struct rk_display_device *dsp = dev_get_drvdata(dev);
+       int enable;
+       
+       sscanf(buf, "%d", &enable);
+       if(dsp->ops && dsp->ops->setenable)
+               dsp->ops->setenable(dsp, enable);
+       return size;
+}
+
+static ssize_t display_show_connect(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct rk_display_device *dsp = dev_get_drvdata(dev);
+       int connect;
+       if(dsp->ops && dsp->ops->getstatus)
+               connect = dsp->ops->getstatus(dsp);
+       else
+               return 0;
+       return snprintf(buf, PAGE_SIZE, "%d\n", connect);
+}
+
+static int mode_string(char *buf, unsigned int offset,
+                      const struct fb_videomode *mode)
+{
+//     char m = 'U';
+       char v = 'p';
+
+//     if (mode->flag & FB_MODE_IS_DETAILED)
+//             m = 'D';
+//     if (mode->flag & FB_MODE_IS_VESA)
+//             m = 'V';
+//     if (mode->flag & FB_MODE_IS_STANDARD)
+//             m = 'S';
+
+       if (mode->vmode & FB_VMODE_INTERLACED)
+               v = 'i';
+       if (mode->vmode & FB_VMODE_DOUBLE)
+               v = 'd';
+
+       return snprintf(&buf[offset], PAGE_SIZE - offset, "%dx%d%c-%d\n",
+                       mode->xres, mode->yres, v, mode->refresh);
+}
+static ssize_t display_show_modes(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct rk_display_device *dsp = dev_get_drvdata(dev);
+       struct list_head *modelist, *pos;
+       struct fb_modelist *fb_modelist;
+       const struct fb_videomode *mode;
+       int i;
+       if(dsp->ops && dsp->ops->getmodelist)
+       {
+               if(dsp->ops->getmodelist(dsp, &modelist))
+                       return -EINVAL;
+       }
+       else
+               return 0;
+
+       i = 0;
+       list_for_each(pos, modelist) {
+               fb_modelist = list_entry(pos, struct fb_modelist, list);
+               mode = &fb_modelist->mode;
+               i += mode_string(buf, i, mode);
+       }
+       return i;
+}
+
+static ssize_t display_show_mode(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct rk_display_device *dsp = dev_get_drvdata(dev);
+       struct fb_videomode mode;
+       
+       if(dsp->ops && dsp->ops->getmode)
+               if(dsp->ops->getmode(dsp, &mode) == 0)
+                       return mode_string(buf, 0, &mode);
+       return 0;
+}
+
+static ssize_t display_store_mode(struct device *dev, 
+                                               struct device_attribute *attr,
+                                               const char *buf, size_t count)
+{
+       struct rk_display_device *dsp = dev_get_drvdata(dev);
+       char mstr[100];
+       struct list_head *modelist, *pos;
+       struct fb_modelist *fb_modelist;
+       struct fb_videomode *mode;     
+       size_t i;                   
+
+       if(dsp->ops && dsp->ops->getmodelist)
+       {
+               if(dsp->ops && dsp->ops->getmodelist)
+               {
+                       if(dsp->ops->getmodelist(dsp, &modelist))
+                               return -EINVAL;
+               }
+               list_for_each(pos, modelist) {
+                       fb_modelist = list_entry(pos, struct fb_modelist, list);
+                       mode = &fb_modelist->mode;
+                       i = mode_string(mstr, 0, mode);
+                       if (strncmp(mstr, buf, max(count, i)) == 0) {
+                               if(dsp->ops && dsp->ops->setmode)
+                                       dsp->ops->setmode(dsp, mode);
+                               return count;
+                       }
+               }
+       }
+       return -EINVAL;
+}
+
+static ssize_t display_show_scale(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct rk_display_device *dsp = dev_get_drvdata(dev);
+       int xscale, yscale;
+       
+       if(dsp->ops && dsp->ops->getscale) {
+               xscale = dsp->ops->getscale(dsp, DISPLAY_SCALE_X);
+               yscale = dsp->ops->getscale(dsp, DISPLAY_SCALE_Y);
+               if(xscale && yscale)
+                       return snprintf(buf, PAGE_SIZE, "xscale=%d yscale=%d\n", xscale, yscale);
+       }
+       return -EINVAL;
+}
+
+static ssize_t display_store_scale(struct device *dev, 
+                                               struct device_attribute *attr,
+                                               const char *buf, size_t count)
+{
+       struct rk_display_device *dsp = dev_get_drvdata(dev);
+       int scale = 100;
+       
+       if(dsp->ops && dsp->ops->setscale) {
+               if(!strncmp(buf, "xscale", 6)) {
+                       sscanf(buf, "xscale=%d", &scale);
+                       dsp->ops->setscale(dsp, DISPLAY_SCALE_X, scale);
+               }
+               else if(!strncmp(buf, "yscale", 6)) {
+                       sscanf(buf, "yscale=%d", &scale);
+                       dsp->ops->setscale(dsp, DISPLAY_SCALE_Y, scale);
+               }
+               else {
+                       sscanf(buf, "%d", &scale);
+                       dsp->ops->setscale(dsp, DISPLAY_SCALE_X, scale);
+                       dsp->ops->setscale(dsp, DISPLAY_SCALE_Y, scale);
+               }
+               return count;
+       }
+       return -EINVAL;
+}
+
+static struct device_attribute display_attrs[] = {
+       __ATTR(name, S_IRUGO, display_show_name, NULL),
+       __ATTR(type, S_IRUGO, display_show_type, NULL),
+       __ATTR(enable, 0664, display_show_enable, display_store_enable),
+       __ATTR(connect, S_IRUGO, display_show_connect, NULL),
+       __ATTR(modes, S_IRUGO, display_show_modes, NULL),
+       __ATTR(mode, 0664, display_show_mode, display_store_mode),
+       __ATTR(scale, 0664, display_show_scale, display_store_scale),
+       __ATTR_NULL
+};
+
+static int display_suspend(struct device *dev, pm_message_t state)
+{
+       struct rk_display_device *dsp = dev_get_drvdata(dev);
+
+       mutex_lock(&dsp->lock);
+       if (likely(dsp->driver->suspend))
+               dsp->driver->suspend(dsp, state);
+       mutex_unlock(&dsp->lock);
+       return 0;
+};
+
+static int display_resume(struct device *dev)
+{
+       struct rk_display_device *dsp = dev_get_drvdata(dev);
+
+       mutex_lock(&dsp->lock);
+       if (likely(dsp->driver->resume))
+               dsp->driver->resume(dsp);
+       mutex_unlock(&dsp->lock);
+       return 0;
+};
+
+void rk_display_device_enable(struct rk_display_device *ddev)
+{
+#ifndef CONFIG_DISPLAY_AUTO_SWITCH     
+       return;
+#else
+       struct list_head *pos, *head = &display_device_list;
+       struct rk_display_device *dev = NULL, *dev_enabled = NULL, *dev_enable = NULL;
+       int enable = 0,connect, has_connect = 0;
+       
+       list_for_each(pos, head) {
+               dev = list_entry(pos, struct rk_display_device, list);
+               enable = dev->ops->getenable(dev);
+               connect = dev->ops->getstatus(dev);
+               if(connect)
+                       dev_enable = dev;
+               if(enable == 1)
+                       dev_enabled = dev;
+       }
+       // If no device is connected, enable highest priority device.
+       if(dev_enable == NULL) {
+               dev->ops->setenable(dev, 1);
+               return;
+       }
+       
+       if(dev_enable == dev_enabled) {
+               if(dev_enable != ddev)
+                       ddev->ops->setenable(ddev, 0);
+       }
+       else {
+               if(dev_enabled)
+                       dev_enabled->ops->setenable(dev_enabled, 0);
+               dev_enable->ops->setenable(dev_enable, 1);
+       }
+               
+
+#endif
+}
+EXPORT_SYMBOL(rk_display_device_enable);
+
+void rk_display_device_enable_other(struct rk_display_device *ddev)
+{
+#ifndef CONFIG_DISPLAY_AUTO_SWITCH     
+       return;
+#else
+       struct list_head *pos, *head = &display_device_list;
+       struct rk_display_device *dev;  
+       int connect = 0;
+       
+       list_for_each_prev(pos, head) {
+               dev = list_entry(pos, struct rk_display_device, list);
+               if(dev != ddev)
+               {
+                       connect = dev->ops->getstatus(dev);
+                       if(connect)
+                       {
+                               dev->ops->setenable(dev, 1);
+                               return;
+                       }
+               }
+       }
+#endif
+}
+EXPORT_SYMBOL(rk_display_device_enable_other);
+
+void rk_display_device_disable_other(struct rk_display_device *ddev)
+{
+#ifndef CONFIG_DISPLAY_AUTO_SWITCH
+       return;
+#else
+       struct list_head *pos, *head = &display_device_list;
+       struct rk_display_device *dev;  
+       int enable = 0;
+       
+       list_for_each(pos, head) {
+               dev = list_entry(pos, struct rk_display_device, list);
+               if(dev != ddev)
+               {
+                       enable = dev->ops->getenable(dev);
+                       if(enable)
+                               dev->ops->setenable(dev, 0);
+               }
+       }
+       ddev->ops->setenable(ddev, 1);
+#endif
+}
+EXPORT_SYMBOL(rk_display_device_disable_other);
+
+void rk_display_device_select(int priority)
+{
+       struct list_head *pos, *head = &display_device_list;
+       struct rk_display_device *dev;
+       int enable, found = 0;
+       
+       list_for_each(pos, head) {
+               dev = list_entry(pos, struct rk_display_device, list);
+               if(dev->priority == priority)
+                       found = 1;
+       }
+       
+       if(!found)
+       {
+               printk("[%s] select display interface %d not exist\n", __FUNCTION__, priority);
+               return;
+       }
+       
+       list_for_each(pos, head) {
+               dev = list_entry(pos, struct rk_display_device, list);
+               enable = dev->ops->getenable(dev);
+               if(dev->priority == priority)
+               {
+                       if(!enable)     
+                               dev->ops->setenable(dev, 1);
+               }
+               else if(enable) 
+                       dev->ops->setenable(dev, 0);
+       }
+}
+EXPORT_SYMBOL(rk_display_device_select);
+static struct mutex allocated_dsp_lock;
+static DEFINE_IDR(allocated_dsp);
+static struct class *display_class;
+
+struct rk_display_device *rk_display_device_register(struct rk_display_driver *driver,
+                                               struct device *parent, void *devdata)
+{
+       struct rk_display_device *new_dev = NULL;
+       int ret = -EINVAL;
+
+       if (unlikely(!driver))
+               return ERR_PTR(ret);
+
+       mutex_lock(&allocated_dsp_lock);
+       ret = idr_pre_get(&allocated_dsp, GFP_KERNEL);
+       mutex_unlock(&allocated_dsp_lock);
+       if (!ret)
+               return ERR_PTR(ret);
+
+       new_dev = kzalloc(sizeof(struct rk_display_device), GFP_KERNEL);
+       if (likely(new_dev) && unlikely(driver->probe(new_dev, devdata))) {
+               // Reserve the index for this display
+               mutex_lock(&allocated_dsp_lock);
+               ret = idr_get_new(&allocated_dsp, new_dev, &new_dev->idx);
+               mutex_unlock(&allocated_dsp_lock);
+
+               if (!ret) {
+                       new_dev->dev = device_create(display_class, parent,
+                                                    MKDEV(0, 0), new_dev,
+                                                    "%s", new_dev->type);
+                       if (!IS_ERR(new_dev->dev)) {
+                               new_dev->parent = parent;
+                               new_dev->driver = driver;
+                               if(parent)
+                                       new_dev->dev->driver = parent->driver;
+                               mutex_init(&new_dev->lock);
+                               // Add new device to display device list.
+                               {
+                                       struct list_head *pos, *head = &display_device_list;
+                                       struct rk_display_device *dev;
+                                       
+                                       list_for_each(pos, head) {
+                                               dev = list_entry(pos, struct rk_display_device, list);
+                                               if(dev->priority > new_dev->priority)
+                                                       break;
+                                       }
+                                       list_add_tail(&new_dev->list, pos);
+                               }
+                               return new_dev;
+                       }
+                       mutex_lock(&allocated_dsp_lock);
+                       idr_remove(&allocated_dsp, new_dev->idx);
+                       mutex_unlock(&allocated_dsp_lock);
+                       ret = -EINVAL;
+               }
+       }
+       kfree(new_dev);
+       return ERR_PTR(ret);
+}
+EXPORT_SYMBOL(rk_display_device_register);
+
+void rk_display_device_unregister(struct rk_display_device *ddev)
+{
+       if (!ddev)
+               return;
+       // Free device
+       mutex_lock(&ddev->lock);
+       device_unregister(ddev->dev);
+       mutex_unlock(&ddev->lock);
+       // Mark device index as avaliable
+       mutex_lock(&allocated_dsp_lock);
+       idr_remove(&allocated_dsp, ddev->idx);
+       mutex_unlock(&allocated_dsp_lock);
+       list_del(&ddev->list);
+       kfree(ddev);
+}
+EXPORT_SYMBOL(rk_display_device_unregister);
+
+static int __init rk_display_class_init(void)
+{
+       display_class = class_create(THIS_MODULE, "display");
+       if (IS_ERR(display_class)) {
+               printk(KERN_ERR "Failed to create display class\n");
+               display_class = NULL;
+               return -EINVAL;
+       }
+       display_class->dev_attrs = display_attrs;
+       display_class->suspend = display_suspend;
+       display_class->resume = display_resume;
+       mutex_init(&allocated_dsp_lock);
+       INIT_LIST_HEAD(&display_device_list);
+       return 0;
+}
+
+static void __exit rk_display_class_exit(void)
+{
+       class_destroy(display_class);
+}
+
+subsys_initcall(rk_display_class_init);
+module_exit(rk_display_class_exit);
+
+
+MODULE_AUTHOR("zhengyang@rock-chips.com");
+MODULE_DESCRIPTION("Driver for rk display device");
+MODULE_LICENSE("GPL");