diff options
author | Dan Willemsen <dwillemsen@nvidia.com> | 2011-01-24 02:07:05 -0800 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2011-01-27 17:17:53 -0800 |
commit | 2a2f0d7f6cb8c708dceb9c980693772fed4ec000 (patch) | |
tree | b18a7a63fb4e71a45087e19a167902109cc3151c /drivers | |
parent | 399d6b57202df9e41b5de6fc78f2357d88d5216c (diff) |
video: tegra: Multi client overlay management
This creates a new device node per head - /dev/tegra_dc%u. There are a
number of ioctls in linux/tegra_overlay.h to open, close, and flip
overlays.
This is a replacement for the extensions in the tegra fb interface, but
does not remove that functionality for compatibility reasons. Once
everyone has moved, we can remove the tegra fb extensions.
Change-Id: Id78a94482637a7ce229ec64eb5feaf2dec2b7804
Reviewed-on: http://git-master/r/16700
Reviewed-by: Daniel Willemsen <dwillemsen@nvidia.com>
Tested-by: Daniel Willemsen <dwillemsen@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/tegra/Kconfig | 7 | ||||
-rw-r--r-- | drivers/video/tegra/dc/Makefile | 1 | ||||
-rw-r--r-- | drivers/video/tegra/dc/dc.c | 11 | ||||
-rw-r--r-- | drivers/video/tegra/dc/dc_priv.h | 2 | ||||
-rw-r--r-- | drivers/video/tegra/dc/overlay.c | 650 | ||||
-rw-r--r-- | drivers/video/tegra/dc/overlay.h | 38 |
6 files changed, 709 insertions, 0 deletions
diff --git a/drivers/video/tegra/Kconfig b/drivers/video/tegra/Kconfig index c431cc670a46..9968738777fd 100644 --- a/drivers/video/tegra/Kconfig +++ b/drivers/video/tegra/Kconfig @@ -17,6 +17,13 @@ config TEGRA_DC help Tegra display controller support. +config TEGRA_OVERLAY + tristate "Tegra Overlay Device Node" + depends on TEGRA_DC + default y + help + Device node for multi-client overlay support. + config FB_TEGRA tristate "Tegra Framebuffer driver" depends on TEGRA_DC && FB = y diff --git a/drivers/video/tegra/dc/Makefile b/drivers/video/tegra/dc/Makefile index 7ecf59a74db5..7336f46111e0 100644 --- a/drivers/video/tegra/dc/Makefile +++ b/drivers/video/tegra/dc/Makefile @@ -3,3 +3,4 @@ obj-y += rgb.o obj-y += hdmi.o obj-y += edid.o obj-y += nvhdcp.o +obj-$(CONFIG_TEGRA_OVERLAY) += overlay.o diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index bbee5b874ada..2a03ae9f8a2e 100644 --- a/drivers/video/tegra/dc/dc.c +++ b/drivers/video/tegra/dc/dc.c @@ -39,6 +39,7 @@ #include "dc_reg.h" #include "dc_priv.h" +#include "overlay.h" static int no_vsync; @@ -1323,6 +1324,12 @@ static int tegra_dc_probe(struct nvhost_device *ndev) dc->fb = NULL; } + if (dc->fb) { + dc->overlay = tegra_overlay_register(ndev, dc); + if (IS_ERR_OR_NULL(dc->overlay)) + dc->overlay = NULL; + } + if (dc->out_ops && dc->out_ops->detect) dc->out_ops->detect(dc); @@ -1350,6 +1357,10 @@ static int tegra_dc_remove(struct nvhost_device *ndev) { struct tegra_dc *dc = nvhost_get_drvdata(ndev); + if (dc->overlay) { + tegra_overlay_unregister(dc->overlay); + } + if (dc->fb) { tegra_fb_unregister(dc->fb); if (dc->fb_mem) diff --git a/drivers/video/tegra/dc/dc_priv.h b/drivers/video/tegra/dc/dc_priv.h index 3f7fdbff023b..ddd7d341e429 100644 --- a/drivers/video/tegra/dc/dc_priv.h +++ b/drivers/video/tegra/dc/dc_priv.h @@ -81,6 +81,8 @@ struct tegra_dc { struct resource *fb_mem; struct tegra_fb_info *fb; + struct tegra_overlay_info *overlay; + u32 syncpt_id; u32 syncpt_min; u32 syncpt_max; diff --git a/drivers/video/tegra/dc/overlay.c b/drivers/video/tegra/dc/overlay.c new file mode 100644 index 000000000000..c968f828815b --- /dev/null +++ b/drivers/video/tegra/dc/overlay.c @@ -0,0 +1,650 @@ +/* + * drivers/video/tegra/overlay/overlay.c + * + * Copyright (c) 2010-2011, NVIDIA Corporation. + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/miscdevice.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/spinlock.h> +#include <linux/tegra_overlay.h> +#include <linux/uaccess.h> + +#include <asm/atomic.h> + +#include <mach/dc.h> +#include <mach/fb.h> +#include <mach/nvhost.h> + +#include "dc_priv.h" +#include "../nvmap/nvmap.h" +#include "overlay.h" + +struct overlay_client; + +struct overlay { + struct overlay_client *owner; +}; + +struct tegra_overlay_info { + struct miscdevice dev; + + struct list_head clients; + spinlock_t clients_lock; + + struct overlay overlays[DC_N_WINDOWS]; + spinlock_t overlays_lock; + + struct nvhost_device *ndev; + + struct nvmap_client *overlay_nvmap; + + struct tegra_dc *dc; + + struct workqueue_struct *flip_wq; + + /* Big enough for tegra_dc%u when %u < 10 */ + char name[10]; +}; + +struct overlay_client { + struct tegra_overlay_info *dev; + struct list_head list; + struct task_struct *task; + struct nvmap_client *user_nvmap; +}; + +struct tegra_overlay_flip_win { + struct tegra_overlay_windowattr attr; + struct nvmap_handle_ref *handle; + dma_addr_t phys_addr; +}; + +struct tegra_overlay_flip_data { + struct work_struct work; + struct tegra_overlay_info *overlay; + struct tegra_overlay_flip_win win[TEGRA_FB_FLIP_N_WINDOWS]; + u32 syncpt_max; +}; + +/* Overlay window manipulation */ +static int tegra_overlay_pin_window(struct tegra_overlay_info *overlay, + struct tegra_overlay_flip_win *flip_win, + struct nvmap_client *user_nvmap) +{ + struct nvmap_handle_ref *win_dupe; + struct nvmap_handle *win_handle; + unsigned long buff_id = flip_win->attr.buff_id; + + if (!buff_id) + return 0; + + win_handle = nvmap_get_handle_id(user_nvmap, buff_id); + if (win_handle == NULL) { + dev_err(&overlay->ndev->dev, "%s: flip invalid " + "handle %08lx\n", current->comm, buff_id); + return -EPERM; + } + + /* duplicate the new framebuffer's handle into the fb driver's + * nvmap context, to ensure that the handle won't be freed as + * long as it is in-use by the fb driver */ + win_dupe = nvmap_duplicate_handle_id(overlay->overlay_nvmap, buff_id); + nvmap_handle_put(win_handle); + + if (IS_ERR(win_dupe)) { + dev_err(&overlay->ndev->dev, "couldn't duplicate handle\n"); + return PTR_ERR(win_dupe); + } + + flip_win->handle = win_dupe; + + flip_win->phys_addr = nvmap_pin(overlay->overlay_nvmap, win_dupe); + if (IS_ERR((void *)flip_win->phys_addr)) { + dev_err(&overlay->ndev->dev, "couldn't pin handle\n"); + nvmap_free(overlay->overlay_nvmap, win_dupe); + return PTR_ERR((void *)flip_win->phys_addr); + } + + return 0; +} + +static int tegra_overlay_set_windowattr(struct tegra_overlay_info *overlay, + struct tegra_dc_win *win, + const struct tegra_overlay_flip_win *flip_win) +{ + if (flip_win->handle == NULL) { + win->flags = 0; + win->cur_handle = NULL; + return 0; + } + +#if 0 + xres = overlay->dc->fb->info->var.xres; + yres = overlay->dc->fb->info->var.yres; +#endif + + win->flags = TEGRA_WIN_FLAG_ENABLED; + if (flip_win->attr.blend == TEGRA_FB_WIN_BLEND_PREMULT) + win->flags |= TEGRA_WIN_FLAG_BLEND_PREMULT; + else if (flip_win->attr.blend == TEGRA_FB_WIN_BLEND_COVERAGE) + win->flags |= TEGRA_WIN_FLAG_BLEND_COVERAGE; + win->fmt = flip_win->attr.pixformat; + win->x = flip_win->attr.x; + win->y = flip_win->attr.y; + win->w = flip_win->attr.w; + win->h = flip_win->attr.h; + win->out_x = flip_win->attr.out_x; + win->out_y = flip_win->attr.out_y; + win->out_w = flip_win->attr.out_w; + win->out_h = flip_win->attr.out_h; + +#if 0 + if (((win->out_x + win->out_w) > xres) && (win->out_x < xres)) + win->out_w = xres - win->out_x; + + if (((win->out_y + win->out_h) > yres) && (win->out_y < yres)) + win->out_h = yres - win->out_y; +#endif + + win->z = flip_win->attr.z; + win->cur_handle = flip_win->handle; + + /* STOPSHIP verify that this won't read outside of the surface */ + win->phys_addr = flip_win->phys_addr + flip_win->attr.offset; + win->offset_u = flip_win->attr.offset_u + flip_win->attr.offset; + win->offset_v = flip_win->attr.offset_v + flip_win->attr.offset; + win->stride = flip_win->attr.stride; + win->stride_uv = flip_win->attr.stride_uv; + if (flip_win->attr.tiled) + win->flags |= TEGRA_WIN_FLAG_TILED; + + if ((s32)flip_win->attr.pre_syncpt_id >= 0) { + nvhost_syncpt_wait_timeout(&overlay->ndev->host->syncpt, + flip_win->attr.pre_syncpt_id, + flip_win->attr.pre_syncpt_val, + msecs_to_jiffies(500)); + } + + + return 0; +} + +static void tegra_overlay_flip_worker(struct work_struct *work) +{ + struct tegra_overlay_flip_data *data = + container_of(work, struct tegra_overlay_flip_data, work); + struct tegra_overlay_info *overlay = data->overlay; + struct tegra_dc_win *win; + struct tegra_dc_win *wins[TEGRA_FB_FLIP_N_WINDOWS]; + struct nvmap_handle_ref *unpin_handles[TEGRA_FB_FLIP_N_WINDOWS]; + int i, nr_win = 0, nr_unpin = 0; + + data = container_of(work, struct tegra_overlay_flip_data, work); + + for (i = 0; i < TEGRA_FB_FLIP_N_WINDOWS; i++) { + struct tegra_overlay_flip_win *flip_win = &data->win[i]; + int idx = flip_win->attr.index; + + if (idx == -1) + continue; + + win = tegra_dc_get_window(overlay->dc, idx); + + if (!win) + continue; + + if (win->flags && win->cur_handle) + unpin_handles[nr_unpin++] = win->cur_handle; + + tegra_overlay_set_windowattr(overlay, win, &data->win[i]); + + wins[nr_win++] = win; + +#if 0 + if (flip_win->attr.pre_syncpt_id < 0) + continue; + printk("%08x %08x\n", + flip_win->attr.pre_syncpt_id, + flip_win->attr.pre_syncpt_val); + + nvhost_syncpt_wait_timeout(&overlay->ndev->host->syncpt, + flip_win->attr.pre_syncpt_id, + flip_win->attr.pre_syncpt_val, + msecs_to_jiffies(500)); +#endif + } + + tegra_dc_update_windows(wins, nr_win); + /* TODO: implement swapinterval here */ + tegra_dc_sync_windows(wins, nr_win); + + tegra_dc_incr_syncpt_min(overlay->dc, data->syncpt_max); + + /* unpin and deref previous front buffers */ + for (i = 0; i < nr_unpin; i++) { + nvmap_unpin(overlay->overlay_nvmap, unpin_handles[i]); + nvmap_free(overlay->overlay_nvmap, unpin_handles[i]); + } + + kfree(data); +} + +static int tegra_overlay_flip(struct tegra_overlay_info *overlay, + struct tegra_overlay_flip_args *args, + struct nvmap_client *user_nvmap) +{ + struct tegra_overlay_flip_data *data; + struct tegra_overlay_flip_win *flip_win; + u32 syncpt_max; + int i, err; + + if (WARN_ON(!overlay->ndev)) + return -EFAULT; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (data == NULL) { + dev_err(&overlay->ndev->dev, + "can't allocate memory for flip\n"); + return -ENOMEM; + } + + INIT_WORK(&data->work, tegra_overlay_flip_worker); + data->overlay = overlay; + + for (i = 0; i < TEGRA_FB_FLIP_N_WINDOWS; i++) { + flip_win = &data->win[i]; + + memcpy(&flip_win->attr, &args->win[i], sizeof(flip_win->attr)); + + if (flip_win->attr.index == -1) + continue; + + err = tegra_overlay_pin_window(overlay, flip_win, user_nvmap); + if (err < 0) { + dev_err(&overlay->ndev->dev, + "error setting window attributes\n"); + goto surf_err; + } + } + + syncpt_max = tegra_dc_incr_syncpt_max(overlay->dc); + data->syncpt_max = syncpt_max; + + queue_work(overlay->flip_wq, &data->work); + + args->post_syncpt_val = syncpt_max; + args->post_syncpt_id = tegra_dc_get_syncpt_id(overlay->dc); + + return 0; + +surf_err: + while (i--) { + if (data->win[i].handle) { + nvmap_unpin(overlay->overlay_nvmap, + data->win[i].handle); + nvmap_free(overlay->overlay_nvmap, + data->win[i].handle); + } + } + kfree(data); + return err; +} + + +/* Overlay functions */ +static bool tegra_overlay_get(struct overlay_client *client, int idx) +{ + unsigned long flags; + struct tegra_overlay_info *dev = client->dev; + bool ret = false; + + if (idx < 0 || idx > dev->dc->n_windows) + return ret; + + spin_lock_irqsave(&dev->overlays_lock, flags); + if (dev->overlays[idx].owner == NULL) { + dev->overlays[idx].owner = client; + ret = true; + } + spin_unlock_irqrestore(&dev->overlays_lock, flags); + + return ret; +} + +static void tegra_overlay_put_unlocked(struct overlay_client *client, int idx) +{ + struct tegra_overlay_flip_args flip_args; + struct tegra_overlay_info *dev = client->dev; + + if (idx < 0 || idx > dev->dc->n_windows) + return; + + if (dev->overlays[idx].owner != client) + return; + + dev->overlays[idx].owner = NULL; + + flip_args.win[0].index = idx; + flip_args.win[0].buff_id = 0; + flip_args.win[1].index = -1; + flip_args.win[2].index = -1; + + tegra_overlay_flip(dev, &flip_args, NULL); +} + +static void tegra_overlay_put(struct overlay_client *client, int idx) +{ + unsigned long flags; + + spin_lock_irqsave(&client->dev->overlays_lock, flags); + tegra_overlay_put_unlocked(client, idx); + spin_unlock_irqrestore(&client->dev->overlays_lock, flags); +} + +/* Ioctl implementations */ +static int tegra_overlay_ioctl_open(struct overlay_client *client, + void __user *arg) +{ + int idx = -1; + + if (copy_from_user(&idx, arg, sizeof(idx))) + return -EFAULT; + + if (!tegra_overlay_get(client, idx)) + return -EBUSY; + + if (copy_to_user(arg, &idx, sizeof(idx))) { + tegra_overlay_put(client, idx); + return -EFAULT; + } + + return 0; +} + +static int tegra_overlay_ioctl_close(struct overlay_client *client, + void __user *arg) +{ + int err = 0; + int idx; + unsigned long flags; + + if (copy_from_user(&idx, arg, sizeof(idx))) + return -EFAULT; + + if (idx < 0 || idx > client->dev->dc->n_windows) + return -EINVAL; + + spin_lock_irqsave(&client->dev->overlays_lock, flags); + if (client->dev->overlays[idx].owner == client) + tegra_overlay_put_unlocked(client, idx); + else + err = -EINVAL; + spin_unlock_irqrestore(&client->dev->overlays_lock, flags); + + return err; +} + +static int tegra_overlay_ioctl_flip(struct overlay_client *client, + void __user *arg) +{ + int i = 0; + int idx = 0; + bool found_one = false; + struct tegra_overlay_flip_args flip_args; + + if (copy_from_user(&flip_args, arg, sizeof(flip_args))) + return -EFAULT; + + for (i = 0; i < TEGRA_FB_FLIP_N_WINDOWS; i++) { + idx = flip_args.win[i].index; + if (idx == -1) { + flip_args.win[i].buff_id = 0; + continue; + } + + if (idx < 0 || idx > client->dev->dc->n_windows) { + dev_err(&client->dev->ndev->dev, + "Flipping an invalid overlay! %d\n", idx); + flip_args.win[i].index = -1; + flip_args.win[i].buff_id = 0; + continue; + } + + if (client->dev->overlays[idx].owner != client) { + dev_err(&client->dev->ndev->dev, + "Flipping a non-owned overlay! %d\n", idx); + flip_args.win[i].index = -1; + flip_args.win[i].buff_id = 0; + continue; + } + + found_one = true; + } + + if (!found_one) + return -EFAULT; + + tegra_overlay_flip(client->dev, &flip_args, client->user_nvmap); + + if (copy_to_user(arg, &flip_args, sizeof(flip_args))) + return -EFAULT; + + return 0; +} + +static int tegra_overlay_ioctl_set_nvmap_fd(struct overlay_client *client, + void __user *arg) +{ + int fd; + struct nvmap_client *nvmap = NULL; + + if (copy_from_user(&fd, arg, sizeof(fd))) + return -EFAULT; + + if (fd < 0) + return -EINVAL; + + nvmap = nvmap_client_get_file(fd); + if (IS_ERR(nvmap)) + return PTR_ERR(nvmap); + + if (client->user_nvmap) + nvmap_client_put(client->user_nvmap); + + client->user_nvmap = nvmap; + + return 0; +} + +/* File operations */ +static int tegra_overlay_open(struct inode *inode, struct file *filp) +{ + struct miscdevice *miscdev = filp->private_data; + struct tegra_overlay_info *dev = container_of(miscdev, + struct tegra_overlay_info, + dev); + struct overlay_client *priv; + unsigned long flags; + int ret; + + ret = nonseekable_open(inode, filp); + if (unlikely(ret)) + return ret; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = dev; + + get_task_struct(current); + priv->task = current; + + spin_lock_irqsave(&dev->clients_lock, flags); + list_add(&priv->list, &dev->clients); + spin_unlock_irqrestore(&dev->clients_lock, flags); + + filp->private_data = priv; + return 0; +} + +static int tegra_overlay_release(struct inode *inode, struct file *filp) +{ + struct overlay_client *client = filp->private_data; + unsigned long flags; + int i; + + spin_lock_irqsave(&client->dev->overlays_lock, flags); + for (i = 0; i < client->dev->dc->n_windows; i++) + if (client->dev->overlays[i].owner == client) + tegra_overlay_put_unlocked(client, i); + spin_unlock_irqrestore(&client->dev->overlays_lock, flags); + + spin_lock_irqsave(&client->dev->clients_lock, flags); + list_del(&client->list); + spin_unlock_irqrestore(&client->dev->clients_lock, flags); + + put_task_struct(client->task); + + kfree(client); + return 0; +} + +static long tegra_overlay_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg) +{ + struct overlay_client *client = filp->private_data; + int err = 0; + void __user *uarg = (void __user *)arg; + + if (_IOC_TYPE(cmd) != TEGRA_OVERLAY_IOCTL_MAGIC) + return -ENOTTY; + + if (_IOC_NR(cmd) < TEGRA_OVERLAY_IOCTL_MIN_NR) + return -ENOTTY; + + if (_IOC_NR(cmd) > TEGRA_OVERLAY_IOCTL_MAX_NR) + return -ENOTTY; + + if (_IOC_DIR(cmd) & _IOC_READ) + err = !access_ok(VERIFY_WRITE, uarg, _IOC_SIZE(cmd)); + if (_IOC_DIR(cmd) & _IOC_WRITE) + err = !access_ok(VERIFY_READ, uarg, _IOC_SIZE(cmd)); + + if (err) + return -EFAULT; + + switch (cmd) { + case TEGRA_OVERLAY_IOCTL_OPEN_WINDOW: + err = tegra_overlay_ioctl_open(client, uarg); + break; + case TEGRA_OVERLAY_IOCTL_CLOSE_WINDOW: + err = tegra_overlay_ioctl_close(client, uarg); + break; + case TEGRA_OVERLAY_IOCTL_FLIP: + err = tegra_overlay_ioctl_flip(client, uarg); + break; + case TEGRA_OVERLAY_IOCTL_SET_NVMAP_FD: + err = tegra_overlay_ioctl_set_nvmap_fd(client, uarg); + break; + default: + return -ENOTTY; + } + return err; +} + +static const struct file_operations overlay_fops = { + .owner = THIS_MODULE, + .open = tegra_overlay_open, + .release = tegra_overlay_release, + .unlocked_ioctl = tegra_overlay_ioctl, +}; + +/* Registration */ +struct tegra_overlay_info *tegra_overlay_register(struct nvhost_device *ndev, + struct tegra_dc *dc) +{ + struct tegra_overlay_info *dev; + int e; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) { + dev_err(&ndev->dev, "out of memory for device\n"); + return ERR_PTR(-ENOMEM); + } + + snprintf(dev->name, sizeof(dev->name), "tegra_dc%u", ndev->id); + + dev->ndev = ndev; + dev->dev.minor = MISC_DYNAMIC_MINOR; + dev->dev.name = dev->name; + dev->dev.fops = &overlay_fops; + dev->dev.parent = &ndev->dev; + + spin_lock_init(&dev->clients_lock); + INIT_LIST_HEAD(&dev->clients); + + spin_lock_init(&dev->overlays_lock); + + e = misc_register(&dev->dev); + if (e) { + dev_err(&ndev->dev, "unable to register miscdevice %s\n", + dev->dev.name); + goto fail; + } + + dev->overlay_nvmap = nvmap_create_client(nvmap_dev, "overlay"); + if (!dev->overlay_nvmap) { + dev_err(&ndev->dev, "couldn't create nvmap client\n"); + e = -ENOMEM; + goto err_free; + } + + dev->flip_wq = create_singlethread_workqueue(dev_name(&ndev->dev)); + if (!dev->flip_wq) { + dev_err(&ndev->dev, "couldn't create flip work-queue\n"); + e = -ENOMEM; + goto err_delete_wq; + } + + dev->dc = dc; + + dev_info(&ndev->dev, "registered overlay\n"); + + return dev; + +err_delete_wq: +err_free: +fail: + if (dev->dev.minor != MISC_DYNAMIC_MINOR) + misc_deregister(&dev->dev); + kfree(dev); + return ERR_PTR(e); +} + +void tegra_overlay_unregister(struct tegra_overlay_info *info) +{ + misc_deregister(&info->dev); + + kfree(info); +} + + diff --git a/drivers/video/tegra/dc/overlay.h b/drivers/video/tegra/dc/overlay.h new file mode 100644 index 000000000000..a3469813b1bf --- /dev/null +++ b/drivers/video/tegra/dc/overlay.h @@ -0,0 +1,38 @@ +/* + * drivers/video/tegra/dc/overlay.h + * + * Copyright (c) 2010-2011, NVIDIA Corporation. + * + * 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. + * + */ + +#ifndef __DRIVERS_VIDEO_TEGRA_OVERLAY_H +#define __DRIVERS_VIDEO_TEGRA_OVERLAY_H + +struct tegra_overlay_info; + +#ifdef CONFIG_TEGRA_OVERLAY +struct tegra_overlay_info *tegra_overlay_register(struct nvhost_device *ndev, + struct tegra_dc *dc); +void tegra_overlay_unregister(struct tegra_overlay_info *overlay_info); +#else +static inline struct tegra_overlay_info *tegra_overlay_register(struct nvhost_device *ndev, + struct tegra_dc *dc) +{ + return NULL; +} + +static inline void tegra_overlay_unregister(struct tegra_overlay_info *overlay_info) +{ +} +#endif + +#endif |