video: tegra: Add skeleton support for extensions
Robert Morell [Thu, 3 Mar 2011 21:04:00 +0000 (13:04 -0800)]
This adds the infrasturcture for an enhanced driver interface to program
extended capabilities of the Tegra display controller.

It exposes a new set of device nodes for userspace clients distinct from
the traditional fbdev device nodes.  This is necessary due to
limitations in the fbdev infrastructure that don't allow drivers to
store file-private data.

bug 818525

Original-Change-Id: I06cecf894792b9904c73f9ebcdeb746ff7455f6e
Signed-off-by: Robert Morell <rmorell@nvidia.com>
Reviewed-on: http://git-master/r/40512
Reviewed-by: Jonathan Mayo <jmayo@nvidia.com>

Rebase-Id: Rfa3969804d7f52c841be1ff96305c9463077e1c5

arch/arm/mach-tegra/include/mach/tegra_dc_ext.h [new file with mode: 0644]
drivers/video/tegra/Kconfig
drivers/video/tegra/dc/Makefile
drivers/video/tegra/dc/dc.c
drivers/video/tegra/dc/dc_priv.h
drivers/video/tegra/dc/ext/Makefile [new file with mode: 0644]
drivers/video/tegra/dc/ext/dev.c [new file with mode: 0644]
drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h [new file with mode: 0644]

diff --git a/arch/arm/mach-tegra/include/mach/tegra_dc_ext.h b/arch/arm/mach-tegra/include/mach/tegra_dc_ext.h
new file mode 100644 (file)
index 0000000..54680a5
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * arch/arm/mach-tegra/include/mach/tegra_dc_ext.h
+ *
+ * Copyright (C) 2011, NVIDIA Corporation
+ *
+ * Author: Robert Morell <rmorell@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ */
+
+#ifndef __MACH_TEGRA_DC_EXT_H
+#define __MACH_TEGRA_DC_EXT_H
+
+#include <mach/nvhost.h>
+
+struct tegra_dc_ext;
+
+#ifdef CONFIG_TEGRA_DC_EXTENSIONS
+int __init tegra_dc_ext_module_init(void);
+void __exit tegra_dc_ext_module_exit(void);
+
+struct tegra_dc_ext *tegra_dc_ext_register(struct nvhost_device *ndev,
+                                          struct tegra_dc *dc);
+void tegra_dc_ext_unregister(struct tegra_dc_ext *dc_ext);
+
+#else /* CONFIG_TEGRA_DC_EXTENSIONS */
+
+static inline
+int tegra_dc_ext_module_init(void)
+{
+       return 0;
+}
+static inline
+void tegra_dc_ext_module_exit(void)
+{
+}
+
+static inline
+struct tegra_dc_ext *tegra_dc_ext_register(struct nvhost_device *ndev,
+                                          struct tegra_dc *dc)
+{
+       return NULL;
+}
+static inline
+void tegra_dc_ext_unregister(struct tegra_dc_ext *dc_ext)
+{
+}
+#endif /* CONFIG_TEGRA_DC_EXTENSIONS */
+
+#endif /* __MACH_TEGRA_DC_EXT_H */
index b1da7f0..a29e248 100644 (file)
@@ -19,7 +19,7 @@ config TEGRA_DC
 
 config TEGRA_OVERLAY
        tristate "Tegra Overlay Device Node"
-       depends on TEGRA_DC
+       depends on TEGRA_DC && !TEGRA_DC_EXTENSIONS
        default y
        help
          Device node for multi-client overlay support.
@@ -34,6 +34,13 @@ config FB_TEGRA
        help
          Framebuffer device support for the Tegra display controller.
 
+config TEGRA_DC_EXTENSIONS
+       bool "Tegra Display Controller Extensions"
+       depends on TEGRA_DC
+       help
+         This exposes support for extended capabilities of the Tegra display
+         controller to userspace drivers.
+
 config TEGRA_NVMAP
        bool "Tegra GPU memory management driver (nvmap)"
        default y
index 63044ca..90b0389 100644 (file)
@@ -7,3 +7,4 @@ obj-y += nvsd.o
 obj-y += dsi.o
 obj-y += dc_sysfs.o
 obj-$(CONFIG_TEGRA_OVERLAY) += overlay.o
+obj-$(CONFIG_TEGRA_DC_EXTENSIONS) += ext/
index f6488ad..a0e8c45 100644 (file)
@@ -2371,6 +2371,12 @@ static int tegra_dc_probe(struct nvhost_device *ndev)
        if (dc->out && dc->out->hotplug_init)
                dc->out->hotplug_init();
 
+       dc->ext = tegra_dc_ext_register(ndev, dc);
+       if (IS_ERR_OR_NULL(dc->ext)) {
+               dev_warn(&ndev->dev, "Failed to enable Tegra DC extensions.\n");
+               dc->ext = NULL;
+       }
+
        if (dc->out_ops && dc->out_ops->detect)
                dc->out_ops->detect(dc);
 
@@ -2413,6 +2419,8 @@ static int tegra_dc_remove(struct nvhost_device *ndev)
                        release_resource(dc->fb_mem);
        }
 
+       if (dc->ext)
+               tegra_dc_ext_unregister(dc->ext);
 
        if (dc->enabled)
                _tegra_dc_disable(dc);
@@ -2522,12 +2530,16 @@ struct nvhost_driver tegra_dc_driver = {
 
 static int __init tegra_dc_module_init(void)
 {
+       int ret = tegra_dc_ext_module_init();
+       if (ret)
+               return ret;
        return nvhost_driver_register(&tegra_dc_driver);
 }
 
 static void __exit tegra_dc_module_exit(void)
 {
        nvhost_driver_unregister(&tegra_dc_driver);
+       tegra_dc_ext_module_exit();
 }
 
 module_exit(tegra_dc_module_exit);
index ebd339c..4bf429f 100644 (file)
@@ -28,6 +28,8 @@
 #include "../host/dev.h"
 #include "../host/t20/syncpt_t20.h"
 
+#include <mach/tegra_dc_ext.h>
+
 #define WIN_IS_TILED(win)      ((win)->flags & TEGRA_WIN_FLAG_TILED)
 #define WIN_IS_ENABLED(win)    ((win)->flags & TEGRA_WIN_FLAG_ENABLED)
 #define WIN_USE_V_FILTER(win)  ((win)->flags & TEGRA_WIN_FLAG_V_FILTER)
@@ -121,6 +123,8 @@ struct tegra_dc {
                unsigned                underflows_c;
        } stats;
 
+       struct tegra_dc_ext             *ext;
+
 #ifdef CONFIG_DEBUG_FS
        struct dentry                   *debugdir;
 #endif
diff --git a/drivers/video/tegra/dc/ext/Makefile b/drivers/video/tegra/dc/ext/Makefile
new file mode 100644 (file)
index 0000000..44c5231
--- /dev/null
@@ -0,0 +1 @@
+obj-y += dev.o
diff --git a/drivers/video/tegra/dc/ext/dev.c b/drivers/video/tegra/dc/ext/dev.c
new file mode 100644 (file)
index 0000000..6fe7788
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * drivers/video/tegra/dc/dev.c
+ *
+ * Copyright (C) 2011, NVIDIA Corporation
+ *
+ * Author: Robert Morell <rmorell@nvidia.com>
+ * Some code based on fbdev extensions written by:
+ *     Erik Gilling <konkers@android.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 <linux/file.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+
+#include <mach/dc.h>
+#include <mach/tegra_dc_ext.h>
+
+#include "tegra_dc_ext_priv.h"
+
+static int tegra_dc_ext_devno;
+static struct class *tegra_dc_ext_class;
+
+static int tegra_dc_release(struct inode *inode, struct file *filp)
+{
+       struct tegra_dc_ext_user *user = filp->private_data;
+
+       kfree(user);
+
+       return 0;
+}
+
+static int tegra_dc_open(struct inode *inode, struct file *filp)
+{
+       struct tegra_dc_ext_user *user;
+
+       user = kzalloc(sizeof(*user), GFP_KERNEL);
+       if (!user)
+               return -ENOMEM;
+
+       filp->private_data = user;
+
+       return 0;
+}
+
+static long tegra_dc_ioctl(struct file *filp, unsigned int cmd,
+                          unsigned long arg)
+{
+       return 0;
+}
+
+static const struct file_operations tegra_dc_devops = {
+       .owner =                THIS_MODULE,
+       .open =                 tegra_dc_open,
+       .release =              tegra_dc_release,
+       .unlocked_ioctl =       tegra_dc_ioctl,
+};
+
+struct tegra_dc_ext *tegra_dc_ext_register(struct nvhost_device *ndev,
+                                          struct tegra_dc *dc)
+{
+       int ret;
+       struct tegra_dc_ext *ext;
+
+       ext = kzalloc(sizeof(*ext), GFP_KERNEL);
+       if (!ext)
+               return ERR_PTR(-ENOMEM);
+
+       BUG_ON(!tegra_dc_ext_devno);
+       cdev_init(&ext->cdev, &tegra_dc_devops);
+       ext->cdev.owner = THIS_MODULE;
+       ret = cdev_add(&ext->cdev, tegra_dc_ext_devno, 1);
+       if (ret) {
+               dev_err(&ndev->dev, "Failed to create character device\n");
+               goto cleanup_alloc;
+       }
+
+       ext->dev = device_create(tegra_dc_ext_class,
+                                &ndev->dev,
+                                tegra_dc_ext_devno,
+                                NULL,
+                                "tegra_dc_%d",
+                                ndev->id);
+
+       if (IS_ERR(ext->dev)) {
+               ret = PTR_ERR(ext->dev);
+               goto cleanup_cdev;
+       }
+
+       tegra_dc_ext_devno++;
+
+       return ext;
+
+cleanup_cdev:
+       cdev_del(&ext->cdev);
+
+cleanup_alloc:
+       kfree(ext);
+
+       return ERR_PTR(ret);
+}
+
+void tegra_dc_ext_unregister(struct tegra_dc_ext *ext)
+{
+       cdev_del(&ext->cdev);
+       kfree(ext);
+}
+
+int __init tegra_dc_ext_module_init(void)
+{
+       int ret;
+
+       tegra_dc_ext_class = class_create(THIS_MODULE, "tegra_dc_ext");
+       if (!tegra_dc_ext_class) {
+               printk(KERN_ERR "tegra_dc_ext: failed to create class\n");
+               return -ENOMEM;
+       }
+
+       ret = alloc_chrdev_region(&tegra_dc_ext_devno,
+                                 0, TEGRA_MAX_DC,
+                                 "tegra_dc_ext");
+       if (ret)
+               class_destroy(tegra_dc_ext_class);
+
+       return ret;
+}
+
+void __exit tegra_dc_ext_module_exit(void)
+{
+       unregister_chrdev_region(tegra_dc_ext_devno, TEGRA_MAX_DC);
+       class_destroy(tegra_dc_ext_class);
+}
diff --git a/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h b/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
new file mode 100644 (file)
index 0000000..387af54
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
+ *
+ * Copyright (C) 2011, NVIDIA Corporation
+ *
+ * Author: Robert Morell <rmorell@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ */
+
+#ifndef __TEGRA_DC_EXT_PRIV_H
+#define __TEGRA_DC_EXT_PRIV_H
+
+#include <linux/cdev.h>
+
+struct tegra_dc_ext {
+       struct cdev     cdev;
+       struct device   *dev;
+};
+
+struct tegra_dc_ext_user {
+
+};
+
+#endif /* __TEGRA_DC_EXT_PRIV_H */