diff options
author | Robert Morell <rmorell@nvidia.com> | 2011-03-03 14:24:25 -0800 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2011-08-11 11:35:40 -0700 |
commit | ec418628e7b69c09b9af87c4bf8f228e847c2c13 (patch) | |
tree | 91ab48f6c8294a4277c1b0ecc9eadaece1956b77 | |
parent | 4edcb139115cbb3fe390949098bf91a7b94d7bc9 (diff) |
video: tegra: Remove fbdev SET_NVMAP and FLIP ioctls
This is necessary so that multiple clients can open /dev/fb* at the same
time. The functionaly has been moved to the dc extension device nodes.
bug 818525
Change-Id: I299e060fce3bb9e3cbf976f3d94dbabc4b3f1654
Signed-off-by: Robert Morell <rmorell@nvidia.com>
Reviewed-on: http://git-master/r/40515
Reviewed-by: Jonathan Mayo <jmayo@nvidia.com>
-rw-r--r-- | arch/arm/mach-tegra/include/mach/fb.h | 5 | ||||
-rw-r--r-- | drivers/video/tegra/dc/dc.c | 1 | ||||
-rw-r--r-- | drivers/video/tegra/fb.c | 391 | ||||
-rw-r--r-- | include/video/tegrafb.h | 68 |
4 files changed, 4 insertions, 461 deletions
diff --git a/arch/arm/mach-tegra/include/mach/fb.h b/arch/arm/mach-tegra/include/mach/fb.h index 063e8712c70f..ced6f9c2cb44 100644 --- a/arch/arm/mach-tegra/include/mach/fb.h +++ b/arch/arm/mach-tegra/include/mach/fb.h @@ -38,8 +38,6 @@ void tegra_fb_update_monspecs(struct tegra_fb_info *fb_info, struct fb_monspecs *specs, bool (*mode_filter)(const struct tegra_dc *dc, struct fb_videomode *mode)); -/* called by display controller on suspend */ -void tegra_fb_suspend(struct tegra_fb_info *tegra_fb); #else static inline struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev, struct tegra_dc *dc, @@ -58,9 +56,6 @@ static inline void tegra_fb_update_monspecs(struct tegra_fb_info *fb_info, bool (*mode_filter)(struct fb_videomode *mode)) { } -static inline void tegra_fb_suspend(struct tegra_fb_info *tegra_fb) -{ -} #endif #endif diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index 25b3f44ef82b..894f1cd6b896 100644 --- a/drivers/video/tegra/dc/dc.c +++ b/drivers/video/tegra/dc/dc.c @@ -2472,7 +2472,6 @@ static int tegra_dc_suspend(struct nvhost_device *ndev, pm_message_t state) dc->out_ops->suspend(dc); if (dc->enabled) { - tegra_fb_suspend(dc->fb); tegra_dc_ext_suspend(dc->ext); _tegra_dc_disable(dc); diff --git a/drivers/video/tegra/fb.c b/drivers/video/tegra/fb.c index 14e505b14739..a3d5c26289dd 100644 --- a/drivers/video/tegra/fb.c +++ b/drivers/video/tegra/fb.c @@ -56,76 +56,11 @@ struct tegra_fb_info { int xres; int yres; - - atomic_t in_use; - struct nvmap_client *user_nvmap; - struct nvmap_client *fb_nvmap; - - struct workqueue_struct *flip_wq; -}; - -struct tegra_fb_flip_win { - struct tegra_fb_windowattr attr; - struct nvmap_handle_ref *handle; - dma_addr_t phys_addr; -}; - -struct tegra_fb_flip_data { - struct work_struct work; - struct tegra_fb_info *fb; - struct tegra_fb_flip_win win[TEGRA_FB_FLIP_N_WINDOWS]; - u32 syncpt_max; }; /* palette array used by the fbcon */ static u32 pseudo_palette[16]; -static int tegra_fb_open(struct fb_info *info, int user) -{ - struct tegra_fb_info *tegra_fb = info->par; - - if (atomic_xchg(&tegra_fb->in_use, 1)) - return -EBUSY; - - tegra_fb->user_nvmap = NULL; - - return 0; -} - -static int tegra_fb_release(struct fb_info *info, int user) -{ - struct tegra_fb_info *tegra_fb = info->par; - struct fb_var_screeninfo *var = &info->var; - - flush_workqueue(tegra_fb->flip_wq); - - if (tegra_fb->win->cur_handle) { - nvmap_unpin(tegra_fb->fb_nvmap, tegra_fb->win->cur_handle); - nvmap_free(tegra_fb->fb_nvmap, tegra_fb->win->cur_handle); - - tegra_fb->win->cur_handle = NULL; - - tegra_fb->win->x = 0; - tegra_fb->win->y = 0; - tegra_fb->win->w = var->xres; - tegra_fb->win->h = var->yres; - tegra_fb->win->out_x = 0; - tegra_fb->win->out_y = 0; - tegra_fb->win->out_w = var->xres; - tegra_fb->win->out_h = var->yres; - tegra_fb->win->flags = TEGRA_WIN_FLAG_ENABLED; - } - - if (tegra_fb->user_nvmap) { - nvmap_client_put(tegra_fb->user_nvmap); - tegra_fb->user_nvmap = NULL; - } - - WARN_ON(!atomic_xchg(&tegra_fb->in_use, 0)); - - return 0; -} - static int tegra_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { @@ -252,7 +187,6 @@ static int tegra_fb_blank(int blank, struct fb_info *info) case FB_BLANK_HSYNC_SUSPEND: case FB_BLANK_POWERDOWN: dev_dbg(&tegra_fb->ndev->dev, "blank\n"); - flush_workqueue(tegra_fb->flip_wq); tegra_dc_disable(tegra_fb->win->dc); return 0; @@ -261,12 +195,6 @@ static int tegra_fb_blank(int blank, struct fb_info *info) } } -void tegra_fb_suspend(struct tegra_fb_info *tegra_fb) -{ - flush_workqueue(tegra_fb->flip_wq); -} - - static int tegra_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { @@ -313,296 +241,13 @@ static void tegra_fb_imageblit(struct fb_info *info, cfb_imageblit(info, image); } -/* TODO: implement ALLOC, FREE, BLANK ioctls */ - -static int tegra_fb_set_nvmap_fd(struct tegra_fb_info *tegra_fb, int fd) -{ - struct nvmap_client *nvmap = NULL; - - if (fd < 0) - return -EINVAL; - - nvmap = nvmap_client_get_file(fd); - if (IS_ERR(nvmap)) - return PTR_ERR(nvmap); - - if (tegra_fb->user_nvmap) - nvmap_client_put(tegra_fb->user_nvmap); - - tegra_fb->user_nvmap = nvmap; - - return 0; -} - -static int tegra_fb_pin_window(struct tegra_fb_info *tegra_fb, - struct tegra_fb_flip_win *flip_win) -{ - 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(tegra_fb->user_nvmap, buff_id); - if (win_handle == NULL) { - dev_err(&tegra_fb->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(tegra_fb->fb_nvmap, buff_id); - nvmap_handle_put(win_handle); - - if (IS_ERR(win_dupe)) { - dev_err(&tegra_fb->ndev->dev, "couldn't duplicate handle\n"); - return PTR_ERR(win_dupe); - } - - flip_win->handle = win_dupe; - - flip_win->phys_addr = nvmap_pin(tegra_fb->fb_nvmap, win_dupe); - if (IS_ERR((void *)flip_win->phys_addr)) { - dev_err(&tegra_fb->ndev->dev, "couldn't pin handle\n"); - nvmap_free(tegra_fb->fb_nvmap, win_dupe); - return PTR_ERR((void *)flip_win->phys_addr); - } - - return 0; -} - -static int tegra_fb_set_windowattr(struct tegra_fb_info *tegra_fb, - struct tegra_dc_win *win, - const struct tegra_fb_flip_win *flip_win) -{ - int xres, yres; - if (flip_win->handle == NULL) { - win->flags = 0; - win->cur_handle = NULL; - return 0; - } - - xres = tegra_fb->win->dc->mode.h_active; - yres = tegra_fb->win->dc->mode.v_active; - - 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; - if (flip_win->attr.flags & TEGRA_FB_WIN_FLAG_INVERT_H) - win->flags |= TEGRA_WIN_FLAG_INVERT_H; - if (flip_win->attr.flags & TEGRA_FB_WIN_FLAG_INVERT_V) - win->flags |= TEGRA_WIN_FLAG_INVERT_V; - if (flip_win->attr.flags & TEGRA_FB_WIN_FLAG_TILED) - win->flags |= TEGRA_WIN_FLAG_TILED; - - 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; - - WARN_ONCE(win->out_x >= xres, - "%s:application window x offset(%d) exceeds display width(%d)\n", - dev_name(&win->dc->ndev->dev), win->out_x, xres); - WARN_ONCE(win->out_y >= yres, - "%s:application window y offset(%d) exceeds display height(%d)\n", - dev_name(&win->dc->ndev->dev), win->out_y, yres); - WARN_ONCE(win->out_x + win->out_w > xres && win->out_x < xres, - "%s:application window width(%d) exceeds display width(%d)\n", - dev_name(&win->dc->ndev->dev), win->out_x + win->out_w, xres); - WARN_ONCE(win->out_y + win->out_h > yres && win->out_y < yres, - "%s:application window height(%d) exceeds display height(%d)\n", - dev_name(&win->dc->ndev->dev), win->out_y + win->out_h, yres); - - if (((win->out_x + win->out_w) > xres) && (win->out_x < xres)) { - long new_w = xres - win->out_x; - win->w = win->w * new_w / win->out_w; - win->out_w = new_w; - } - if (((win->out_y + win->out_h) > yres) && (win->out_y < yres)) { - long new_h = yres - win->out_y; - win->h = win->h * new_h / win->out_h; - win->out_h = new_h; - } - - 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; - win->offset = flip_win->attr.offset; - win->offset_u = flip_win->attr.offset_u; - win->offset_v = flip_win->attr.offset_v; - win->stride = flip_win->attr.stride; - win->stride_uv = flip_win->attr.stride_uv; - - if ((s32)flip_win->attr.pre_syncpt_id >= 0) { - nvhost_syncpt_wait_timeout(&tegra_fb->ndev->host->syncpt, - flip_win->attr.pre_syncpt_id, - flip_win->attr.pre_syncpt_val, - msecs_to_jiffies(500), - NULL); - } - - - return 0; -} - -static void tegra_fb_flip_worker(struct work_struct *work) -{ - struct tegra_fb_flip_data *data = - container_of(work, struct tegra_fb_flip_data, work); - struct tegra_fb_info *tegra_fb = data->fb; - 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_fb_flip_data, work); - - for (i = 0; i < TEGRA_FB_FLIP_N_WINDOWS; i++) { - struct tegra_fb_flip_win *flip_win = &data->win[i]; - int idx = flip_win->attr.index; - win = tegra_dc_get_window(tegra_fb->win->dc, idx); - - if (!win) - continue; - - if (win->flags && win->cur_handle) - unpin_handles[nr_unpin++] = win->cur_handle; - - tegra_fb_set_windowattr(tegra_fb, 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(&tegra_fb->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(tegra_fb->win->dc, data->syncpt_max); - - /* unpin and deref previous front buffers */ - for (i = 0; i < nr_unpin; i++) { - nvmap_unpin(tegra_fb->fb_nvmap, unpin_handles[i]); - nvmap_free(tegra_fb->fb_nvmap, unpin_handles[i]); - } - - kfree(data); -} - -static int tegra_fb_flip(struct tegra_fb_info *tegra_fb, - struct tegra_fb_flip_args *args) -{ - struct tegra_fb_flip_data *data; - struct tegra_fb_flip_win *flip_win; - u32 syncpt_max; - int i, err; - - if (WARN_ON(!tegra_fb->user_nvmap)) - return -EFAULT; - - if (WARN_ON(!tegra_fb->ndev)) - return -EFAULT; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (data == NULL) { - dev_err(&tegra_fb->ndev->dev, - "can't allocate memory for flip\n"); - return -ENOMEM; - } - - INIT_WORK(&data->work, tegra_fb_flip_worker); - data->fb = tegra_fb; - - 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)); - - err = tegra_fb_pin_window(tegra_fb, flip_win); - if (err < 0) { - dev_err(&tegra_fb->ndev->dev, - "error setting window attributes\n"); - goto surf_err; - } - } - - syncpt_max = tegra_dc_incr_syncpt_max(tegra_fb->win->dc); - data->syncpt_max = syncpt_max; - - queue_work(tegra_fb->flip_wq, &data->work); - - args->post_syncpt_val = syncpt_max; - args->post_syncpt_id = tegra_dc_get_syncpt_id(tegra_fb->win->dc); - - return 0; - -surf_err: - while (i--) { - if (data->win[i].handle) { - nvmap_unpin(tegra_fb->fb_nvmap, - data->win[i].handle); - nvmap_free(tegra_fb->fb_nvmap, - data->win[i].handle); - } - } - kfree(data); - return err; -} - -/* TODO: implement private window ioctls to set overlay x,y */ - static int tegra_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { - struct tegra_fb_info *tegra_fb = info->par; - struct tegra_fb_flip_args flip_args; struct tegra_fb_modedb modedb; struct fb_modelist *modelist; int i; - int fd; - int ret; switch (cmd) { - case FBIO_TEGRA_SET_NVMAP_FD: - if (copy_from_user(&fd, (void __user *)arg, sizeof(fd))) - return -EFAULT; - - return tegra_fb_set_nvmap_fd(tegra_fb, fd); - - case FBIO_TEGRA_FLIP: - if (copy_from_user(&flip_args, (void __user *)arg, sizeof(flip_args))) - return -EFAULT; - - ret = tegra_fb_flip(tegra_fb, &flip_args); - - if (copy_to_user((void __user *)arg, &flip_args, sizeof(flip_args))) - return -EFAULT; - - return ret; - case FBIO_TEGRA_GET_MODEDB: if (copy_from_user(&modedb, (void __user *)arg, sizeof(modedb))) return -EFAULT; @@ -651,8 +296,6 @@ static int tegra_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long static struct fb_ops tegra_fb_ops = { .owner = THIS_MODULE, - .fb_open = tegra_fb_open, - .fb_release = tegra_fb_release, .fb_check_var = tegra_fb_check_var, .fb_set_par = tegra_fb_set_par, .fb_setcolreg = tegra_fb_setcolreg, @@ -759,20 +402,6 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev, tegra_fb->fb_mem = fb_mem; tegra_fb->xres = fb_data->xres; tegra_fb->yres = fb_data->yres; - tegra_fb->fb_nvmap = nvmap_create_client(nvmap_dev, "tegra-fb"); - if (!tegra_fb->fb_nvmap) { - dev_err(&ndev->dev, "couldn't create nvmap client\n"); - ret = -ENOMEM; - goto err_free; - } - atomic_set(&tegra_fb->in_use, 0); - - tegra_fb->flip_wq = create_singlethread_workqueue(dev_name(&ndev->dev)); - if (!tegra_fb->flip_wq) { - dev_err(&ndev->dev, "couldn't create flip work-queue\n"); - ret = -ENOMEM; - goto err_put_client; - } if (fb_mem) { fb_size = resource_size(fb_mem); @@ -781,7 +410,7 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev, if (!fb_base) { dev_err(&ndev->dev, "fb can't be mapped\n"); ret = -EBUSY; - goto err_delete_wq; + goto err_free; } tegra_fb->valid = true; } @@ -858,11 +487,8 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev, return tegra_fb; err_iounmap_fb: - iounmap(fb_base); -err_delete_wq: - destroy_workqueue(tegra_fb->flip_wq); -err_put_client: - nvmap_client_put(tegra_fb->fb_nvmap); + if (fb_base) + iounmap(fb_base); err_free: framebuffer_release(info); err: @@ -873,19 +499,8 @@ void tegra_fb_unregister(struct tegra_fb_info *fb_info) { struct fb_info *info = fb_info->info; - if (fb_info->win->cur_handle) { - nvmap_unpin(fb_info->fb_nvmap, fb_info->win->cur_handle); - nvmap_free(fb_info->fb_nvmap, fb_info->win->cur_handle); - } - - if (fb_info->fb_nvmap) - nvmap_client_put(fb_info->fb_nvmap); - unregister_framebuffer(info); - flush_workqueue(fb_info->flip_wq); - destroy_workqueue(fb_info->flip_wq); - iounmap(info->screen_base); framebuffer_release(info); } diff --git a/include/video/tegrafb.h b/include/video/tegrafb.h index 6e765c5b175a..919661b1a8e0 100644 --- a/include/video/tegrafb.h +++ b/include/video/tegrafb.h @@ -20,79 +20,13 @@ #include <linux/fb.h> #include <linux/types.h> -#include <asm/ioctl.h> - -#define TEGRA_FB_WIN_FMT_P1 0 -#define TEGRA_FB_WIN_FMT_P2 1 -#define TEGRA_FB_WIN_FMT_P4 2 -#define TEGRA_FB_WIN_FMT_P8 3 -#define TEGRA_FB_WIN_FMT_B4G4R4A4 4 -#define TEGRA_FB_WIN_FMT_B5G5R5A 5 -#define TEGRA_FB_WIN_FMT_B5G6R5 6 -#define TEGRA_FB_WIN_FMT_AB5G5R5 7 -#define TEGRA_FB_WIN_FMT_B8G8R8A8 12 -#define TEGRA_FB_WIN_FMT_R8G8B8A8 13 -#define TEGRA_FB_WIN_FMT_B6x2G6x2R6x2A8 14 -#define TEGRA_FB_WIN_FMT_R6x2G6x2B6x2A8 15 -#define TEGRA_FB_WIN_FMT_YCbCr422 16 -#define TEGRA_FB_WIN_FMT_YUV422 17 -#define TEGRA_FB_WIN_FMT_YCbCr420P 18 -#define TEGRA_FB_WIN_FMT_YUV420P 19 -#define TEGRA_FB_WIN_FMT_YCbCr422P 20 -#define TEGRA_FB_WIN_FMT_YUV422P 21 -#define TEGRA_FB_WIN_FMT_YCbCr422R 22 -#define TEGRA_FB_WIN_FMT_YUV422R 23 -#define TEGRA_FB_WIN_FMT_YCbCr422RA 24 -#define TEGRA_FB_WIN_FMT_YUV422RA 25 - -#define TEGRA_FB_WIN_BLEND_NONE 0 -#define TEGRA_FB_WIN_BLEND_PREMULT 1 -#define TEGRA_FB_WIN_BLEND_COVERAGE 2 - -#define TEGRA_FB_WIN_FLAG_INVERT_H (1 << 0) -#define TEGRA_FB_WIN_FLAG_INVERT_V (1 << 1) -#define TEGRA_FB_WIN_FLAG_TILED (1 << 2) - -/* set index to -1 to ignore window data */ -struct tegra_fb_windowattr { - __s32 index; - __u32 buff_id; - __u32 flags; - __u32 blend; - __u32 offset; - __u32 offset_u; - __u32 offset_v; - __u32 stride; - __u32 stride_uv; - __u32 pixformat; - __u32 x; - __u32 y; - __u32 w; - __u32 h; - __u32 out_x; - __u32 out_y; - __u32 out_w; - __u32 out_h; - __u32 z; - __u32 pre_syncpt_id; - __u32 pre_syncpt_val; -}; - -#define TEGRA_FB_FLIP_N_WINDOWS 3 - -struct tegra_fb_flip_args { - struct tegra_fb_windowattr win[TEGRA_FB_FLIP_N_WINDOWS]; - __u32 post_syncpt_id; - __u32 post_syncpt_val; -}; +#include <linux/ioctl.h> struct tegra_fb_modedb { struct fb_var_screeninfo *modedb; __u32 modedb_len; }; -#define FBIO_TEGRA_SET_NVMAP_FD _IOW('F', 0x40, __u32) -#define FBIO_TEGRA_FLIP _IOW('F', 0x41, struct tegra_fb_flip_args) #define FBIO_TEGRA_GET_MODEDB _IOWR('F', 0x42, struct tegra_fb_modedb) #endif |