]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
video: tegra: compat version of TEGRA_GET_MODEDB
authorJon Mayo <jmayo@nvidia.com>
Fri, 21 Feb 2014 22:01:24 +0000 (14:01 -0800)
committerJon Mayo <jmayo@nvidia.com>
Tue, 25 Feb 2014 22:38:34 +0000 (14:38 -0800)
Provide a compat version of FBIO_TEGRA_GET_MODEDB.

Bug 1466416

Change-Id: Id976d9e5059d4bb81a25e1412941ecfcc38b4657
Signed-off-by: Jon Mayo <jmayo@nvidia.com>
Reviewed-on: http://git-master/r/373105
Reviewed-by: Automatic_Commit_Validation_User
drivers/video/tegra/fb.c
include/video/tegrafb.h

index 36e79dd18203b65bd1cb0532f0042f3c460f4e05..7ad8711ef7ac3786b0d2e9288e95eaa36590ca62 100644 (file)
@@ -404,61 +404,99 @@ static void tegra_fb_imageblit(struct fb_info *info,
        cfb_imageblit(info, image);
 }
 
-static int tegra_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
+static int tegra_get_modedb(struct tegra_dc *dc, struct tegra_fb_modedb *modedb,
+       struct fb_info *info)
 {
-       struct tegra_fb_info *tegra_fb = (struct tegra_fb_info *)info->par;
-       struct tegra_dc *dc = tegra_fb->win->dc;
-       struct tegra_fb_modedb modedb;
-       struct fb_modelist *modelist;
-       struct fb_vblank vblank = {};
-       struct fb_var_screeninfo *modedb_ptr;
        unsigned i;
+       struct fb_var_screeninfo *modedb_ptr;
+       struct fb_modelist *modelist;
 
-       switch (cmd) {
-       case FBIO_TEGRA_GET_MODEDB:
-               if (copy_from_user(&modedb, (void __user *)arg, sizeof(modedb)))
-                       return -EFAULT;
+       i = 0;
+       modedb_ptr = user_ptr(modedb->modedb);
+       list_for_each_entry(modelist, &info->modelist, list) {
+               struct fb_var_screeninfo var;
+
+               /* fb_videomode_to_var doesn't fill out all the members
+                  of fb_var_screeninfo */
+               memset(&var, 0x0, sizeof(var));
 
-               i = 0;
-               modedb_ptr = user_ptr(modedb.modedb);
-               list_for_each_entry(modelist, &info->modelist, list) {
-                       struct fb_var_screeninfo var;
+               fb_videomode_to_var(&var, &modelist->mode);
+               var.width = tegra_dc_get_out_width(dc);
+               var.height = tegra_dc_get_out_height(dc);
 
-                       /* fb_videomode_to_var doesn't fill out all the members
-                          of fb_var_screeninfo */
-                       memset(&var, 0x0, sizeof(var));
+               if (i < modedb->modedb_len) {
+                       void __user *ptr = &modedb_ptr[i];
 
-                       fb_videomode_to_var(&var, &modelist->mode);
-                       var.width = tegra_dc_get_out_width(dc);
-                       var.height = tegra_dc_get_out_height(dc);
+                       if (copy_to_user(ptr, &var, sizeof(var)))
+                               return -EFAULT;
+               }
+               i++;
 
-                       if (i < modedb.modedb_len) {
+               if (var.vmode & FB_VMODE_STEREO_MASK) {
+                       if (i < modedb->modedb_len) {
                                void __user *ptr = &modedb_ptr[i];
-                               if (copy_to_user(ptr, &var, sizeof(var)))
+
+                               var.vmode &= ~FB_VMODE_STEREO_MASK;
+                               if (copy_to_user(ptr,
+                                       &var, sizeof(var)))
                                        return -EFAULT;
                        }
                        i++;
-
-                       if (var.vmode & FB_VMODE_STEREO_MASK) {
-                               if (i < modedb.modedb_len) {
-                                       void __user *ptr = &modedb_ptr[i];
-                                       var.vmode &= ~FB_VMODE_STEREO_MASK;
-                                       if (copy_to_user(ptr,
-                                               &var, sizeof(var)))
-                                               return -EFAULT;
-                               }
-                               i++;
-                       }
                }
+       }
 
-               /*
-                * If modedb_len == 0, return how many modes are
-                * available; otherwise, return how many modes were written.
-                */
-               if (modedb.modedb_len == 0)
-                       modedb.modedb_len = i;
-               else
-                       modedb.modedb_len = min(modedb.modedb_len, i);
+       /*
+        * If modedb_len == 0, return how many modes are
+        * available; otherwise, return how many modes were written.
+        */
+       if (modedb->modedb_len == 0)
+               modedb->modedb_len = i;
+       else
+               modedb->modedb_len = min(modedb->modedb_len, i);
+
+       return 0;
+}
+
+static int tegra_fb_ioctl(struct fb_info *info,
+       unsigned int cmd, unsigned long arg)
+{
+       int res;
+       struct tegra_fb_info *tegra_fb = (struct tegra_fb_info *)info->par;
+       struct tegra_dc *dc = tegra_fb->win->dc;
+       struct tegra_fb_modedb modedb;
+       struct fb_vblank vblank = {};
+
+       switch (cmd) {
+#ifdef CONFIG_COMPAT
+       case FBIO_TEGRA_GET_MODEDB_COMPAT: {
+               struct tegra_fb_modedb_compat modedb_compat;
+
+               if (copy_from_user(&modedb_compat, (void __user *)arg,
+                       sizeof(modedb_compat)))
+                       return -EFAULT;
+               /* convert compat version to full version */
+               modedb.modedb = (void __user *)modedb_compat.modedb;
+               modedb.modedb_len = modedb_compat.modedb_len;
+
+               res = tegra_get_modedb(dc, &modedb, info);
+               if (res)
+                       return res;
+
+               /* convert full version back to compat version */
+               modedb_compat.modedb_len = modedb.modedb_len;
+               if (copy_to_user((void __user *)arg, &modedb_compat,
+                       sizeof(modedb_compat)))
+                       return -EFAULT;
+               break;
+       }
+#endif
+       case FBIO_TEGRA_GET_MODEDB:
+               if (copy_from_user(&modedb, (void __user *)arg, sizeof(modedb)))
+                       return -EFAULT;
+
+               res = tegra_get_modedb(dc, &modedb, info);
+               if (res)
+                       return res;
 
                if (copy_to_user((void __user *)arg, &modedb, sizeof(modedb)))
                        return -EFAULT;
index 60bf30944af3c2e0e04528dfbec455f4f15a77f5..c524c083a3c5c20ffa626e280ba83340aaacfeda 100644 (file)
@@ -4,6 +4,8 @@
  * Copyright (C) 2010 Google, Inc.
  * Author: Erik Gilling <konkers@android.com>
  *
+ * Copyright (c) 2014 NVIDIA CORPORATION. All rights reserved.
+ *
  * 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.
 #endif
 
 struct tegra_fb_modedb {
+       struct fb_var_screeninfo *modedb;
+       __u32 modedb_len;
+};
+
 #ifdef CONFIG_COMPAT
+struct tegra_fb_modedb_compat {
        __u32 modedb;
-#else
-       struct fb_var_screeninfo *modedb;
-#endif
        __u32 modedb_len;
 };
 
+#define FBIO_TEGRA_GET_MODEDB_COMPAT \
+               _IOWR('F', 0x42, struct tegra_fb_modedb_compat)
+#endif
+
 #define FBIO_TEGRA_GET_MODEDB  _IOWR('F', 0x42, struct tegra_fb_modedb)
 
 #endif