arm64: dts: rk3368-android: enable iep default
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / display-sys.c
old mode 100755 (executable)
new mode 100644 (file)
index b85d5db..6db202a
@@ -8,32 +8,38 @@
 static struct list_head main_display_device_list;
 static struct list_head aux_display_device_list;
 
-static ssize_t display_show_name(struct device *dev,
-                                struct device_attribute *attr, char *buf)
+static ssize_t name_show(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)
+static DEVICE_ATTR_RO(name);
+
+static ssize_t type_show(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_property(struct device *dev,
-                                    struct device_attribute *attr, char *buf)
+static DEVICE_ATTR_RO(type);
+
+static ssize_t property_show(struct device *dev,
+                            struct device_attribute *attr, char *buf)
 {
        struct rk_display_device *dsp = dev_get_drvdata(dev);
 
        return snprintf(buf, PAGE_SIZE, "%d\n", dsp->property);
 }
 
-static ssize_t display_show_enable(struct device *dev,
-                                  struct device_attribute *attr, char *buf)
+static DEVICE_ATTR_RO(property);
+
+static ssize_t enable_show(struct device *dev,
+                          struct device_attribute *attr, char *buf)
 {
        struct rk_display_device *dsp = dev_get_drvdata(dev);
        int enable;
@@ -45,9 +51,9 @@ static ssize_t display_show_enable(struct device *dev,
        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)
+static ssize_t enable_store(struct device *dev,
+                           struct device_attribute *attr,
+                           const char *buf, size_t size)
 {
        struct rk_display_device *dsp = dev_get_drvdata(dev);
        int enable;
@@ -59,8 +65,10 @@ static ssize_t display_store_enable(struct device *dev,
        return size;
 }
 
-static ssize_t display_show_connect(struct device *dev,
-                                   struct device_attribute *attr, char *buf)
+static DEVICE_ATTR_RW(enable);
+
+static ssize_t connect_show(struct device *dev,
+                           struct device_attribute *attr, char *buf)
 {
        struct rk_display_device *dsp = dev_get_drvdata(dev);
        int connect;
@@ -72,21 +80,19 @@ static ssize_t display_show_connect(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "%d\n", connect);
 }
 
+static DEVICE_ATTR_RO(connect);
+
 static int mode_string(char *buf, unsigned int offset,
                       const struct fb_videomode *mode)
 {
        char v = 'p';
 
+       if (!buf || !mode) {
+               pr_err("%s parameter error\n", __func__);
+               return 0;
+       }
        if (mode->xres == 0 && mode->yres == 0)
                return snprintf(&buf[offset], PAGE_SIZE - offset, "auto\n");
-/*
-       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)
@@ -101,8 +107,8 @@ static int mode_string(char *buf, unsigned int offset,
                                mode->xres, mode->yres, v, mode->refresh);
 }
 
-static ssize_t display_show_modes(struct device *dev,
-                                 struct device_attribute *attr, char *buf)
+static ssize_t modes_show(struct device *dev,
+                         struct device_attribute *attr, char *buf)
 {
        struct rk_display_device *dsp = dev_get_drvdata(dev);
        struct list_head *modelist, *pos;
@@ -110,10 +116,14 @@ static ssize_t display_show_modes(struct device *dev,
        const struct fb_videomode *mode;
        int i;
 
+       mutex_lock(&dsp->lock);
        if (dsp->ops && dsp->ops->getmodelist) {
-               if (dsp->ops->getmodelist(dsp, &modelist))
+               if (dsp->ops->getmodelist(dsp, &modelist)) {
+                       mutex_unlock(&dsp->lock);
                        return -EINVAL;
+               }
        } else {
+               mutex_unlock(&dsp->lock);
                return 0;
        }
        i = 0;
@@ -127,11 +137,14 @@ static ssize_t display_show_modes(struct device *dev,
                mode = &display_modelist->mode;
                i += mode_string(buf, i, mode);
        }
+       mutex_unlock(&dsp->lock);
        return i;
 }
 
-static ssize_t display_show_mode(struct device *dev,
-                                struct device_attribute *attr, char *buf)
+static DEVICE_ATTR_RO(modes);
+
+static ssize_t mode_show(struct device *dev,
+                        struct device_attribute *attr, char *buf)
 {
        struct rk_display_device *dsp = dev_get_drvdata(dev);
        struct fb_videomode mode;
@@ -142,9 +155,9 @@ static ssize_t display_show_mode(struct device *dev,
        return 0;
 }
 
-static ssize_t display_store_mode(struct device *dev,
-                                 struct device_attribute *attr,
-                                 const char *buf, size_t count)
+static ssize_t mode_store(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];
@@ -153,16 +166,20 @@ static ssize_t display_store_mode(struct device *dev,
        struct fb_videomode *mode;
        size_t i;
 
+       mutex_lock(&dsp->lock);
        if (!memcmp(buf, "auto", 4)) {
                if (dsp->ops && dsp->ops->setmode)
                        dsp->ops->setmode(dsp, NULL);
+               mutex_unlock(&dsp->lock);
                return count;
        }
 
        if (dsp->ops && dsp->ops->getmodelist) {
                if (dsp->ops && dsp->ops->getmodelist) {
-                       if (dsp->ops->getmodelist(dsp, &modelist))
+                       if (dsp->ops->getmodelist(dsp, &modelist)) {
+                               mutex_unlock(&dsp->lock);
                                return -EINVAL;
+                       }
                }
                list_for_each(pos, modelist) {
                        display_modelist = list_entry(pos,
@@ -173,16 +190,20 @@ static ssize_t display_store_mode(struct device *dev,
                        if (strncmp(mstr, buf, max(count, i)) == 0) {
                                if (dsp->ops && dsp->ops->setmode)
                                        dsp->ops->setmode(dsp, mode);
+                               mutex_unlock(&dsp->lock);
                                return count;
                        }
                }
        }
+       mutex_unlock(&dsp->lock);
        return -EINVAL;
 }
 
-static ssize_t display_show_scale(struct device *dev,
-                                 struct device_attribute *attr,
-                                 char *buf)
+static DEVICE_ATTR_RW(mode);
+
+static ssize_t scale_show(struct device *dev,
+                         struct device_attribute *attr,
+                         char *buf)
 {
        struct rk_display_device *dsp = dev_get_drvdata(dev);
        int xscale, yscale;
@@ -198,9 +219,9 @@ static ssize_t display_show_scale(struct device *dev,
        return -EINVAL;
 }
 
-static ssize_t display_store_scale(struct device *dev,
-                                  struct device_attribute *attr,
-                                  const char *buf, size_t count)
+static ssize_t scale_store(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;
@@ -231,26 +252,37 @@ static ssize_t display_store_scale(struct device *dev,
        return -EINVAL;
 }
 
-static ssize_t display_show_3dmode(struct device *dev,
-                                  struct device_attribute *attr, char *buf)
+static DEVICE_ATTR_RW(scale);
+
+static ssize_t mode3d_show(struct device *dev,
+                          struct device_attribute *attr, char *buf)
 {
        struct rk_display_device *dsp = dev_get_drvdata(dev);
        struct list_head *modelist, *pos;
        struct display_modelist *display_modelist;
        struct fb_videomode mode;
        int i = 0, cur_3d_mode = -1;
+       char mode_str[128];
+       int mode_strlen, format_3d;
 
+       mutex_lock(&dsp->lock);
        if (dsp->ops && dsp->ops->getmodelist) {
-               if (dsp->ops->getmodelist(dsp, &modelist))
+               if (dsp->ops->getmodelist(dsp, &modelist)) {
+                       mutex_unlock(&dsp->lock);
                        return -EINVAL;
+               }
        } else {
+               mutex_unlock(&dsp->lock);
                return 0;
        }
 
        if (dsp->ops && dsp->ops->getmode) {
-               if (dsp->ops->getmode(dsp, &mode))
+               if (dsp->ops->getmode(dsp, &mode)) {
+                       mutex_unlock(&dsp->lock);
                        return -EINVAL;
+               }
        } else {
+               mutex_unlock(&dsp->lock);
                return 0;
        }
 
@@ -258,10 +290,10 @@ static ssize_t display_show_3dmode(struct device *dev,
                display_modelist = list_entry(pos,
                                              struct display_modelist,
                                              list);
-               if (fb_mode_is_equal(&mode, &display_modelist->mode))
-                       break;
-               else
+               if (!fb_mode_is_equal(&mode, &display_modelist->mode))
                        display_modelist = NULL;
+               else
+                       break;
        }
        if (display_modelist)
                i = snprintf(buf, PAGE_SIZE, "3dmodes=%d\n",
@@ -271,120 +303,187 @@ static ssize_t display_show_3dmode(struct device *dev,
 
        if (dsp->ops && dsp->ops->get3dmode)
                cur_3d_mode = dsp->ops->get3dmode(dsp);
-       i += snprintf(buf + i, PAGE_SIZE - i, "cur3dmode=%d", cur_3d_mode);
+       i += snprintf(buf + i, PAGE_SIZE - i, "cur3dmode=%d\n", cur_3d_mode);
+
+       list_for_each(pos, modelist) {
+               display_modelist = list_entry(pos,
+                                             struct display_modelist,
+                                             list);
+               mode_strlen = mode_string(mode_str, 0,
+                                         &display_modelist->mode);
+               mode_str[mode_strlen - 1] = 0;
+               format_3d = display_modelist->format_3d;
+               i += snprintf(buf + i, PAGE_SIZE, "%s,%d\n",
+                             mode_str, format_3d);
+       }
+       mutex_unlock(&dsp->lock);
        return i;
 }
 
-static ssize_t display_store_3dmode(struct device *dev,
-                                   struct device_attribute *attr,
-                                   const char *buf, size_t count)
+static ssize_t mode3d_store(struct device *dev,
+                           struct device_attribute *attr,
+                           const char *buf, size_t count)
 {
        struct rk_display_device *dsp = dev_get_drvdata(dev);
        int mode;
 
+       mutex_lock(&dsp->lock);
        if (dsp->ops && dsp->ops->set3dmode) {
                if (!kstrtoint(buf, 0, &mode))
                        dsp->ops->set3dmode(dsp, mode);
+               mutex_unlock(&dsp->lock);
                return count;
        }
+       mutex_unlock(&dsp->lock);
        return -EINVAL;
 }
 
-static ssize_t display_show_color(struct device *dev,
-                                 struct device_attribute *attr, char *buf)
+static DEVICE_ATTR_RW(mode3d);
+
+static ssize_t color_show(struct device *dev,
+                         struct device_attribute *attr, char *buf)
 {
        struct rk_display_device *dsp = dev_get_drvdata(dev);
-       
-       if(dsp->ops && dsp->ops->getcolor)
-               return dsp->ops->getcolor(dsp, buf);
-       else
-               return 0;
+       int ret = 0;
+
+       mutex_lock(&dsp->lock);
+       if (dsp->ops && dsp->ops->getcolor)
+               ret = dsp->ops->getcolor(dsp, buf);
+       mutex_unlock(&dsp->lock);
+       return ret;
 }
 
-static ssize_t display_store_color(struct device *dev, 
-                                  struct device_attribute *attr,
-                                  const char *buf, size_t count)
+static ssize_t color_store(struct device *dev,
+                          struct device_attribute *attr,
+                          const char *buf, size_t count)
 {
        struct rk_display_device *dsp = dev_get_drvdata(dev);
 
-       if(dsp->ops && dsp->ops->setcolor) {
-               if (!dsp->ops->setcolor(dsp, buf, count));
+       mutex_lock(&dsp->lock);
+       if (dsp->ops && dsp->ops->setcolor) {
+               if (!dsp->ops->setcolor(dsp, buf, count)) {
+                       mutex_unlock(&dsp->lock);
                        return count;
+               }
        }
+       mutex_unlock(&dsp->lock);
        return -EINVAL;
 }
 
-static ssize_t display_show_sinkaudioinfo(struct device *dev,
-                                         struct device_attribute *attr,
-                                         char *buf)
+static DEVICE_ATTR_RW(color);
+
+static ssize_t audioinfo_show(struct device *dev,
+                             struct device_attribute *attr,
+                             char *buf)
 {
        struct rk_display_device *dsp = dev_get_drvdata(dev);
        char audioinfo[200];
        int ret = 0;
 
+       mutex_lock(&dsp->lock);
        if (dsp->ops && dsp->ops->getedidaudioinfo) {
                ret = dsp->ops->getedidaudioinfo(dsp, audioinfo, 200);
-               if (!ret)
+               if (!ret) {
+                       mutex_unlock(&dsp->lock);
                        return snprintf(buf, PAGE_SIZE, "%s\n", audioinfo);
+               }
        }
+       mutex_unlock(&dsp->lock);
        return -EINVAL;
 }
 
-static ssize_t display_show_monspecs(struct device *dev,
-                                    struct device_attribute *attr, char *buf)
+static DEVICE_ATTR_RO(audioinfo);
+
+static ssize_t monspecs_show(struct device *dev,
+                            struct device_attribute *attr, char *buf)
 {
        struct rk_display_device *dsp = dev_get_drvdata(dev);
        struct fb_monspecs monspecs;
        int ret = 0;
 
+       mutex_lock(&dsp->lock);
        if (dsp->ops && dsp->ops->getmonspecs) {
                ret = dsp->ops->getmonspecs(dsp, &monspecs);
                if (!ret) {
+                       mutex_unlock(&dsp->lock);
                        memcpy(buf, &monspecs, sizeof(struct fb_monspecs));
                        return sizeof(struct fb_monspecs);
                }
        }
+       mutex_unlock(&dsp->lock);
        return -EINVAL;
 }
 
-static ssize_t display_show_debug(struct device *dev,
-                                 struct device_attribute *attr, char *buf)
+static DEVICE_ATTR_RO(monspecs);
+
+static ssize_t debug_show(struct device *dev,
+                         struct device_attribute *attr, char *buf)
 {
-       return -EINVAL;
+       struct rk_display_device *dsp = dev_get_drvdata(dev);
+       int ret = -EINVAL;
+
+       mutex_lock(&dsp->lock);
+       if (dsp->ops && dsp->ops->getdebug)
+               ret = dsp->ops->getdebug(dsp, buf);
+       mutex_unlock(&dsp->lock);
+       return ret;
 }
 
-static ssize_t display_store_debug(struct device *dev,
-                                  struct device_attribute *attr,
-                                  const char *buf, size_t count)
+static ssize_t debug_store(struct device *dev,
+                          struct device_attribute *attr,
+                          const char *buf, size_t count)
 {
-       int cmd;
+       int cmd, ret = -EINVAL;
        struct rk_display_device *dsp = dev_get_drvdata(dev);
 
-       if(dsp->ops && dsp->ops->setdebug) {
-               if (sscanf(buf, "%d", &cmd) != -1)
+       mutex_lock(&dsp->lock);
+       if (dsp->ops && dsp->ops->setdebug) {
+               if (kstrtoint(buf, 0, &cmd) == 0)
                        dsp->ops->setdebug(dsp, cmd);
-               return count;
+               ret = count;
        }
-       return -EINVAL;
+       mutex_unlock(&dsp->lock);
+       return ret;
 }
 
-static struct device_attribute display_attrs[] = {
-       __ATTR(name, S_IRUGO, display_show_name, NULL),
-       __ATTR(type, S_IRUGO, display_show_type, NULL),
-       __ATTR(property, S_IRUGO, display_show_property, NULL),
-       __ATTR(enable, 0666, display_show_enable, display_store_enable),
-       __ATTR(connect, S_IRUGO, display_show_connect, NULL),
-       __ATTR(modes, S_IRUGO, display_show_modes, NULL),
-       __ATTR(mode, 0666, display_show_mode, display_store_mode),
-       __ATTR(scale, 0666, display_show_scale, display_store_scale),
-       __ATTR(3dmode, 0666, display_show_3dmode, display_store_3dmode),
-       __ATTR(color, 0666, display_show_color, display_store_color),
-       __ATTR(audioinfo, S_IRUGO, display_show_sinkaudioinfo, NULL),
-       __ATTR(monspecs, S_IRUGO, display_show_monspecs, NULL),
-       __ATTR(debug, 0664, display_show_debug, display_store_debug),
-       __ATTR_NULL
+static DEVICE_ATTR_RW(debug);
+
+static ssize_t prop_show(struct device *dev,
+                        struct device_attribute *attr, char *buf)
+{
+       struct rk_display_device *dsp = dev_get_drvdata(dev);
+       int ret = -EINVAL;
+
+       mutex_lock(&dsp->lock);
+       if (dsp->ops && dsp->ops->getvrinfo)
+               ret = dsp->ops->getvrinfo(dsp, buf);
+       mutex_unlock(&dsp->lock);
+
+       return ret;
+}
+
+static DEVICE_ATTR_RO(prop);
+
+static struct attribute *display_device_attrs[] = {
+       &dev_attr_name.attr,
+       &dev_attr_type.attr,
+       &dev_attr_property.attr,
+       &dev_attr_enable.attr,
+       &dev_attr_connect.attr,
+       &dev_attr_modes.attr,
+       &dev_attr_mode.attr,
+       &dev_attr_scale.attr,
+       &dev_attr_mode3d.attr,
+       &dev_attr_color.attr,
+       &dev_attr_audioinfo.attr,
+       &dev_attr_monspecs.attr,
+       &dev_attr_debug.attr,
+       &dev_attr_prop.attr,
+       NULL,
 };
 
+ATTRIBUTE_GROUPS(display_device);
+
 static int display_suspend(struct device *dev, pm_message_t state)
 {
        struct rk_display_device *dsp = dev_get_drvdata(dev);
@@ -457,7 +556,7 @@ void rk_display_device_enable(struct rk_display_device *ddev)
                        dev_enabled = dev;
        }
        /* If no device is connected, enable highest priority device. */
-       if (dev_enable == NULL) {
+       if (!dev_enable) {
                dev->ops->setenable(dev, 1);
                return;
        }
@@ -466,7 +565,8 @@ void rk_display_device_enable(struct rk_display_device *ddev)
                if (dev_enable != ddev)
                        ddev->ops->setenable(ddev, 0);
        } else {
-               if (dev_enabled)
+               if (dev_enabled &&
+                   dev_enabled->priority != DISPLAY_PRIORITY_HDMI)
                        dev_enabled->ops->setenable(dev_enabled, 0);
                dev_enable->ops->setenable(dev_enable, 1);
        }
@@ -586,7 +686,21 @@ struct rk_display_device
                mutex_unlock(&allocated_dsp_lock);
 
                if (new_dev->idx >= 0) {
-                       if (new_dev->property == DISPLAY_MAIN)
+                       struct list_head *pos, *head;
+                       struct rk_display_device *dev;
+                       int i = 0;
+
+                       head = &main_display_device_list;
+                       list_for_each_entry(dev, head, list) {
+                               if (strcmp(dev->type, new_dev->type) == 0)
+                                       i++;
+                       }
+                       head = &aux_display_device_list;
+                       list_for_each_entry(dev, head, list) {
+                               if (strcmp(dev->type, new_dev->type) == 0)
+                                       i++;
+                       }
+                       if (i == 0)
                                new_dev->dev =
                                device_create(display_class, parent,
                                              MKDEV(0, 0), new_dev,
@@ -595,9 +709,8 @@ struct rk_display_device
                                new_dev->dev =
                                device_create(display_class, parent,
                                              MKDEV(0, 0), new_dev,
-                                             "display%d.%s",
-                                             new_dev->property,
-                                             new_dev->type);
+                                             "%s%d", new_dev->type, i);
+
                        if (!IS_ERR(new_dev->dev)) {
                                new_dev->parent = parent;
                                new_dev->driver = driver;
@@ -605,10 +718,6 @@ struct rk_display_device
                                        new_dev->dev->driver = parent->driver;
                                mutex_init(&new_dev->lock);
                                /* Add new device to display device list. */
-                               {
-                               struct list_head *pos, *head;
-                               struct rk_display_device *dev;
-
                                if (new_dev->property == DISPLAY_MAIN)
                                        head = &main_display_device_list;
                                else
@@ -624,7 +733,6 @@ struct rk_display_device
                                }
                                list_add_tail(&new_dev->list, pos);
                                return new_dev;
-                               }
                        }
                        mutex_lock(&allocated_dsp_lock);
                        idr_remove(&allocated_dsp, new_dev->idx);
@@ -645,7 +753,7 @@ void rk_display_device_unregister(struct rk_display_device *ddev)
        mutex_lock(&ddev->lock);
        device_unregister(ddev->dev);
        mutex_unlock(&ddev->lock);
-       /* Mark device index as avaliable */
+       /* Mark device index as available */
        mutex_lock(&allocated_dsp_lock);
        idr_remove(&allocated_dsp, ddev->idx);
        mutex_unlock(&allocated_dsp_lock);
@@ -662,7 +770,7 @@ static int __init rk_display_class_init(void)
                display_class = NULL;
                return -EINVAL;
        }
-       display_class->dev_attrs = display_attrs;
+       display_class->dev_groups = display_device_groups;
        display_class->suspend = display_suspend;
        display_class->resume = display_resume;
        mutex_init(&allocated_dsp_lock);
@@ -679,7 +787,6 @@ static void __exit rk_display_class_exit(void)
 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");