Index: drivers/video/tegra/fb.c |
diff --git a/drivers/video/tegra/fb.c b/drivers/video/tegra/fb.c |
index 754bcf2b688203700eacddd4242b0842abf69e53..b946031555106f029f984b048d805236d70b720b 100644 |
--- a/drivers/video/tegra/fb.c |
+++ b/drivers/video/tegra/fb.c |
@@ -50,76 +50,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) |
{ |
@@ -245,7 +180,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; |
@@ -254,12 +188,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) |
{ |
@@ -306,258 +234,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) |
-{ |
- if (flip_win->handle == NULL) { |
- win->flags = 0; |
- win->cur_handle = NULL; |
- return 0; |
- } |
- |
- 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; |
- 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 ((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)); |
- } |
- |
- |
- 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; |
@@ -590,8 +273,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, |
@@ -693,20 +374,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_delete_wq; |
- } |
if (fb_mem) { |
fb_size = resource_size(fb_mem); |
@@ -715,7 +382,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_put_client; |
+ goto err_free; |
} |
tegra_fb->valid = true; |
} |
@@ -791,11 +458,8 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev, |
return tegra_fb; |
err_iounmap_fb: |
- iounmap(fb_base); |
-err_put_client: |
- nvmap_client_put(tegra_fb->fb_nvmap); |
-err_delete_wq: |
- destroy_workqueue(tegra_fb->flip_wq); |
+ if (fb_base) |
+ iounmap(fb_base); |
err_free: |
framebuffer_release(info); |
err: |
@@ -806,19 +470,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); |
} |