Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(680)

Side by Side Diff: drivers/video/tegra/fb.c

Issue 6672056: [07/23] video: tegra: Remove fbdev SET_NVMAP and FLIP ioctls (Closed)
Patch Set: Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « drivers/video/tegra/dc/dc.c ('k') | include/video/tegrafb.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * drivers/video/tegra/fb.c 2 * drivers/video/tegra/fb.c
3 * 3 *
4 * Copyright (C) 2010 Google, Inc. 4 * Copyright (C) 2010 Google, Inc.
5 * Author: Erik Gilling <konkers@android.com> 5 * Author: Erik Gilling <konkers@android.com>
6 * Colin Cross <ccross@android.com> 6 * Colin Cross <ccross@android.com>
7 * Travis Geiselbrecht <travis@palm.com> 7 * Travis Geiselbrecht <travis@palm.com>
8 * 8 *
9 * This software is licensed under the terms of the GNU General Public 9 * This software is licensed under the terms of the GNU General Public
10 * License version 2, as published by the Free Software Foundation, and 10 * License version 2, as published by the Free Software Foundation, and
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 struct tegra_fb_info { 43 struct tegra_fb_info {
44 struct tegra_dc_win *win; 44 struct tegra_dc_win *win;
45 struct nvhost_device *ndev; 45 struct nvhost_device *ndev;
46 struct fb_info *info; 46 struct fb_info *info;
47 bool valid; 47 bool valid;
48 48
49 struct resource *fb_mem; 49 struct resource *fb_mem;
50 50
51 int xres; 51 int xres;
52 int yres; 52 int yres;
53
54 atomic_t in_use;
55 struct nvmap_client *user_nvmap;
56 struct nvmap_client *fb_nvmap;
57
58 struct workqueue_struct *flip_wq;
59 };
60
61 struct tegra_fb_flip_win {
62 struct tegra_fb_windowattr attr;
63 struct nvmap_handle_ref *handle;
64 dma_addr_t phys_addr;
65 };
66
67 struct tegra_fb_flip_data {
68 struct work_struct work;
69 struct tegra_fb_info *fb;
70 struct tegra_fb_flip_win win[TEGRA_FB_FLIP_N_WINDOWS];
71 u32 syncpt_max;
72 }; 53 };
73 54
74 /* palette array used by the fbcon */ 55 /* palette array used by the fbcon */
75 static u32 pseudo_palette[16]; 56 static u32 pseudo_palette[16];
76 57
77 static int tegra_fb_open(struct fb_info *info, int user)
78 {
79 struct tegra_fb_info *tegra_fb = info->par;
80
81 if (atomic_xchg(&tegra_fb->in_use, 1))
82 return -EBUSY;
83
84 tegra_fb->user_nvmap = NULL;
85
86 return 0;
87 }
88
89 static int tegra_fb_release(struct fb_info *info, int user)
90 {
91 struct tegra_fb_info *tegra_fb = info->par;
92 struct fb_var_screeninfo *var = &info->var;
93
94 flush_workqueue(tegra_fb->flip_wq);
95
96 if (tegra_fb->win->cur_handle) {
97 nvmap_unpin(tegra_fb->fb_nvmap, tegra_fb->win->cur_handle);
98 nvmap_free(tegra_fb->fb_nvmap, tegra_fb->win->cur_handle);
99
100 tegra_fb->win->cur_handle = NULL;
101
102 tegra_fb->win->x = 0;
103 tegra_fb->win->y = 0;
104 tegra_fb->win->w = var->xres;
105 tegra_fb->win->h = var->yres;
106 tegra_fb->win->out_x = 0;
107 tegra_fb->win->out_y = 0;
108 tegra_fb->win->out_w = var->xres;
109 tegra_fb->win->out_h = var->yres;
110 tegra_fb->win->flags = TEGRA_WIN_FLAG_ENABLED;
111 }
112
113 if (tegra_fb->user_nvmap) {
114 nvmap_client_put(tegra_fb->user_nvmap);
115 tegra_fb->user_nvmap = NULL;
116 }
117
118 WARN_ON(!atomic_xchg(&tegra_fb->in_use, 0));
119
120 return 0;
121 }
122
123 static int tegra_fb_check_var(struct fb_var_screeninfo *var, 58 static int tegra_fb_check_var(struct fb_var_screeninfo *var,
124 struct fb_info *info) 59 struct fb_info *info)
125 { 60 {
126 if ((var->yres * var->xres * var->bits_per_pixel / 8 * 2) > 61 if ((var->yres * var->xres * var->bits_per_pixel / 8 * 2) >
127 info->screen_size) 62 info->screen_size)
128 return -EINVAL; 63 return -EINVAL;
129 64
130 /* double yres_virtual to allow double buffering through pan_display */ 65 /* double yres_virtual to allow double buffering through pan_display */
131 var->yres_virtual = var->yres * 2; 66 var->yres_virtual = var->yres * 2;
132 67
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 case FB_BLANK_UNBLANK: 173 case FB_BLANK_UNBLANK:
239 dev_dbg(&tegra_fb->ndev->dev, "unblank\n"); 174 dev_dbg(&tegra_fb->ndev->dev, "unblank\n");
240 tegra_dc_enable(tegra_fb->win->dc); 175 tegra_dc_enable(tegra_fb->win->dc);
241 return 0; 176 return 0;
242 177
243 case FB_BLANK_NORMAL: 178 case FB_BLANK_NORMAL:
244 case FB_BLANK_VSYNC_SUSPEND: 179 case FB_BLANK_VSYNC_SUSPEND:
245 case FB_BLANK_HSYNC_SUSPEND: 180 case FB_BLANK_HSYNC_SUSPEND:
246 case FB_BLANK_POWERDOWN: 181 case FB_BLANK_POWERDOWN:
247 dev_dbg(&tegra_fb->ndev->dev, "blank\n"); 182 dev_dbg(&tegra_fb->ndev->dev, "blank\n");
248 flush_workqueue(tegra_fb->flip_wq);
249 tegra_dc_disable(tegra_fb->win->dc); 183 tegra_dc_disable(tegra_fb->win->dc);
250 return 0; 184 return 0;
251 185
252 default: 186 default:
253 return -ENOTTY; 187 return -ENOTTY;
254 } 188 }
255 } 189 }
256 190
257 void tegra_fb_suspend(struct tegra_fb_info *tegra_fb)
258 {
259 flush_workqueue(tegra_fb->flip_wq);
260 }
261
262
263 static int tegra_fb_pan_display(struct fb_var_screeninfo *var, 191 static int tegra_fb_pan_display(struct fb_var_screeninfo *var,
264 struct fb_info *info) 192 struct fb_info *info)
265 { 193 {
266 struct tegra_fb_info *tegra_fb = info->par; 194 struct tegra_fb_info *tegra_fb = info->par;
267 char __iomem *flush_start; 195 char __iomem *flush_start;
268 char __iomem *flush_end; 196 char __iomem *flush_end;
269 u32 addr; 197 u32 addr;
270 198
271 if (!tegra_fb->win->cur_handle) { 199 if (!tegra_fb->win->cur_handle) {
272 flush_start = info->screen_base + (var->yoffset * info->fix.line _length); 200 flush_start = info->screen_base + (var->yoffset * info->fix.line _length);
(...skipping 26 matching lines...) Expand all
299 { 227 {
300 cfb_copyarea(info, region); 228 cfb_copyarea(info, region);
301 } 229 }
302 230
303 static void tegra_fb_imageblit(struct fb_info *info, 231 static void tegra_fb_imageblit(struct fb_info *info,
304 const struct fb_image *image) 232 const struct fb_image *image)
305 { 233 {
306 cfb_imageblit(info, image); 234 cfb_imageblit(info, image);
307 } 235 }
308 236
309 /* TODO: implement ALLOC, FREE, BLANK ioctls */
310
311 static int tegra_fb_set_nvmap_fd(struct tegra_fb_info *tegra_fb, int fd)
312 {
313 struct nvmap_client *nvmap = NULL;
314
315 if (fd < 0)
316 return -EINVAL;
317
318 nvmap = nvmap_client_get_file(fd);
319 if (IS_ERR(nvmap))
320 return PTR_ERR(nvmap);
321
322 if (tegra_fb->user_nvmap)
323 nvmap_client_put(tegra_fb->user_nvmap);
324
325 tegra_fb->user_nvmap = nvmap;
326
327 return 0;
328 }
329
330 static int tegra_fb_pin_window(struct tegra_fb_info *tegra_fb,
331 struct tegra_fb_flip_win *flip_win)
332 {
333 struct nvmap_handle_ref *win_dupe;
334 struct nvmap_handle *win_handle;
335 unsigned long buff_id = flip_win->attr.buff_id;
336
337 if (!buff_id)
338 return 0;
339
340 win_handle = nvmap_get_handle_id(tegra_fb->user_nvmap, buff_id);
341 if (win_handle == NULL) {
342 dev_err(&tegra_fb->ndev->dev, "%s: flip invalid "
343 "handle %08lx\n", current->comm, buff_id);
344 return -EPERM;
345 }
346
347 /* duplicate the new framebuffer's handle into the fb driver's
348 * nvmap context, to ensure that the handle won't be freed as
349 * long as it is in-use by the fb driver */
350 win_dupe = nvmap_duplicate_handle_id(tegra_fb->fb_nvmap, buff_id);
351 nvmap_handle_put(win_handle);
352
353 if (IS_ERR(win_dupe)) {
354 dev_err(&tegra_fb->ndev->dev, "couldn't duplicate handle\n");
355 return PTR_ERR(win_dupe);
356 }
357
358 flip_win->handle = win_dupe;
359
360 flip_win->phys_addr = nvmap_pin(tegra_fb->fb_nvmap, win_dupe);
361 if (IS_ERR((void *)flip_win->phys_addr)) {
362 dev_err(&tegra_fb->ndev->dev, "couldn't pin handle\n");
363 nvmap_free(tegra_fb->fb_nvmap, win_dupe);
364 return PTR_ERR((void *)flip_win->phys_addr);
365 }
366
367 return 0;
368 }
369
370 static int tegra_fb_set_windowattr(struct tegra_fb_info *tegra_fb,
371 struct tegra_dc_win *win,
372 const struct tegra_fb_flip_win *flip_win)
373 {
374 if (flip_win->handle == NULL) {
375 win->flags = 0;
376 win->cur_handle = NULL;
377 return 0;
378 }
379
380 win->flags = TEGRA_WIN_FLAG_ENABLED;
381 if (flip_win->attr.blend == TEGRA_FB_WIN_BLEND_PREMULT)
382 win->flags |= TEGRA_WIN_FLAG_BLEND_PREMULT;
383 else if (flip_win->attr.blend == TEGRA_FB_WIN_BLEND_COVERAGE)
384 win->flags |= TEGRA_WIN_FLAG_BLEND_COVERAGE;
385 win->fmt = flip_win->attr.pixformat;
386 win->x = flip_win->attr.x;
387 win->y = flip_win->attr.y;
388 win->w = flip_win->attr.w;
389 win->h = flip_win->attr.h;
390 win->out_x = flip_win->attr.out_x;
391 win->out_y = flip_win->attr.out_y;
392 win->out_w = flip_win->attr.out_w;
393 win->out_h = flip_win->attr.out_h;
394 win->z = flip_win->attr.z;
395 win->cur_handle = flip_win->handle;
396
397 /* STOPSHIP verify that this won't read outside of the surface */
398 win->phys_addr = flip_win->phys_addr + flip_win->attr.offset;
399 win->offset_u = flip_win->attr.offset_u + flip_win->attr.offset;
400 win->offset_v = flip_win->attr.offset_v + flip_win->attr.offset;
401 win->stride = flip_win->attr.stride;
402 win->stride_uv = flip_win->attr.stride_uv;
403
404 if ((s32)flip_win->attr.pre_syncpt_id >= 0) {
405 nvhost_syncpt_wait_timeout(&tegra_fb->ndev->host->syncpt,
406 flip_win->attr.pre_syncpt_id,
407 flip_win->attr.pre_syncpt_val,
408 msecs_to_jiffies(500));
409 }
410
411
412 return 0;
413 }
414
415 static void tegra_fb_flip_worker(struct work_struct *work)
416 {
417 struct tegra_fb_flip_data *data =
418 container_of(work, struct tegra_fb_flip_data, work);
419 struct tegra_fb_info *tegra_fb = data->fb;
420 struct tegra_dc_win *win;
421 struct tegra_dc_win *wins[TEGRA_FB_FLIP_N_WINDOWS];
422 struct nvmap_handle_ref *unpin_handles[TEGRA_FB_FLIP_N_WINDOWS];
423 int i, nr_win = 0, nr_unpin = 0;
424
425 data = container_of(work, struct tegra_fb_flip_data, work);
426
427 for (i = 0; i < TEGRA_FB_FLIP_N_WINDOWS; i++) {
428 struct tegra_fb_flip_win *flip_win = &data->win[i];
429 int idx = flip_win->attr.index;
430 win = tegra_dc_get_window(tegra_fb->win->dc, idx);
431
432 if (!win)
433 continue;
434
435 if (win->flags && win->cur_handle)
436 unpin_handles[nr_unpin++] = win->cur_handle;
437
438 tegra_fb_set_windowattr(tegra_fb, win, &data->win[i]);
439
440 wins[nr_win++] = win;
441
442 #if 0
443 if (flip_win->attr.pre_syncpt_id < 0)
444 continue;
445 printk("%08x %08x\n",
446 flip_win->attr.pre_syncpt_id,
447 flip_win->attr.pre_syncpt_val);
448
449 nvhost_syncpt_wait_timeout(&tegra_fb->ndev->host->syncpt,
450 flip_win->attr.pre_syncpt_id,
451 flip_win->attr.pre_syncpt_val,
452 msecs_to_jiffies(500));
453 #endif
454 }
455
456 tegra_dc_update_windows(wins, nr_win);
457 /* TODO: implement swapinterval here */
458 tegra_dc_sync_windows(wins, nr_win);
459
460 tegra_dc_incr_syncpt_min(tegra_fb->win->dc, data->syncpt_max);
461
462 /* unpin and deref previous front buffers */
463 for (i = 0; i < nr_unpin; i++) {
464 nvmap_unpin(tegra_fb->fb_nvmap, unpin_handles[i]);
465 nvmap_free(tegra_fb->fb_nvmap, unpin_handles[i]);
466 }
467
468 kfree(data);
469 }
470
471 static int tegra_fb_flip(struct tegra_fb_info *tegra_fb,
472 struct tegra_fb_flip_args *args)
473 {
474 struct tegra_fb_flip_data *data;
475 struct tegra_fb_flip_win *flip_win;
476 u32 syncpt_max;
477 int i, err;
478
479 if (WARN_ON(!tegra_fb->user_nvmap))
480 return -EFAULT;
481
482 if (WARN_ON(!tegra_fb->ndev))
483 return -EFAULT;
484
485 data = kzalloc(sizeof(*data), GFP_KERNEL);
486 if (data == NULL) {
487 dev_err(&tegra_fb->ndev->dev,
488 "can't allocate memory for flip\n");
489 return -ENOMEM;
490 }
491
492 INIT_WORK(&data->work, tegra_fb_flip_worker);
493 data->fb = tegra_fb;
494
495 for (i = 0; i < TEGRA_FB_FLIP_N_WINDOWS; i++) {
496 flip_win = &data->win[i];
497
498 memcpy(&flip_win->attr, &args->win[i], sizeof(flip_win->attr));
499
500 err = tegra_fb_pin_window(tegra_fb, flip_win);
501 if (err < 0) {
502 dev_err(&tegra_fb->ndev->dev,
503 "error setting window attributes\n");
504 goto surf_err;
505 }
506 }
507
508 syncpt_max = tegra_dc_incr_syncpt_max(tegra_fb->win->dc);
509 data->syncpt_max = syncpt_max;
510
511 queue_work(tegra_fb->flip_wq, &data->work);
512
513 args->post_syncpt_val = syncpt_max;
514 args->post_syncpt_id = tegra_dc_get_syncpt_id(tegra_fb->win->dc);
515
516 return 0;
517
518 surf_err:
519 while (i--) {
520 if (data->win[i].handle) {
521 nvmap_unpin(tegra_fb->fb_nvmap,
522 data->win[i].handle);
523 nvmap_free(tegra_fb->fb_nvmap,
524 data->win[i].handle);
525 }
526 }
527 kfree(data);
528 return err;
529 }
530
531 /* TODO: implement private window ioctls to set overlay x,y */
532
533 static int tegra_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) 237 static int tegra_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
534 { 238 {
535 struct tegra_fb_info *tegra_fb = info->par;
536 struct tegra_fb_flip_args flip_args;
537 struct tegra_fb_modedb modedb; 239 struct tegra_fb_modedb modedb;
538 struct fb_modelist *modelist; 240 struct fb_modelist *modelist;
539 int i; 241 int i;
540 int fd;
541 int ret;
542 242
543 switch (cmd) { 243 switch (cmd) {
544 case FBIO_TEGRA_SET_NVMAP_FD:
545 if (copy_from_user(&fd, (void __user *)arg, sizeof(fd)))
546 return -EFAULT;
547
548 return tegra_fb_set_nvmap_fd(tegra_fb, fd);
549
550 case FBIO_TEGRA_FLIP:
551 if (copy_from_user(&flip_args, (void __user *)arg, sizeof(flip_a rgs)))
552 return -EFAULT;
553
554 ret = tegra_fb_flip(tegra_fb, &flip_args);
555
556 if (copy_to_user((void __user *)arg, &flip_args, sizeof(flip_arg s)))
557 return -EFAULT;
558
559 return ret;
560
561 case FBIO_TEGRA_GET_MODEDB: 244 case FBIO_TEGRA_GET_MODEDB:
562 if (copy_from_user(&modedb, (void __user *)arg, sizeof(modedb))) 245 if (copy_from_user(&modedb, (void __user *)arg, sizeof(modedb)))
563 return -EFAULT; 246 return -EFAULT;
564 247
565 i = 0; 248 i = 0;
566 list_for_each_entry(modelist, &info->modelist, list) { 249 list_for_each_entry(modelist, &info->modelist, list) {
567 struct fb_var_screeninfo var; 250 struct fb_var_screeninfo var;
568 251
569 if (i >= modedb.modedb_len) 252 if (i >= modedb.modedb_len)
570 break; 253 break;
(...skipping 12 matching lines...) Expand all
583 266
584 default: 267 default:
585 return -ENOTTY; 268 return -ENOTTY;
586 } 269 }
587 270
588 return 0; 271 return 0;
589 } 272 }
590 273
591 static struct fb_ops tegra_fb_ops = { 274 static struct fb_ops tegra_fb_ops = {
592 .owner = THIS_MODULE, 275 .owner = THIS_MODULE,
593 .fb_open = tegra_fb_open,
594 .fb_release = tegra_fb_release,
595 .fb_check_var = tegra_fb_check_var, 276 .fb_check_var = tegra_fb_check_var,
596 .fb_set_par = tegra_fb_set_par, 277 .fb_set_par = tegra_fb_set_par,
597 .fb_setcolreg = tegra_fb_setcolreg, 278 .fb_setcolreg = tegra_fb_setcolreg,
598 .fb_blank = tegra_fb_blank, 279 .fb_blank = tegra_fb_blank,
599 .fb_pan_display = tegra_fb_pan_display, 280 .fb_pan_display = tegra_fb_pan_display,
600 .fb_fillrect = tegra_fb_fillrect, 281 .fb_fillrect = tegra_fb_fillrect,
601 .fb_copyarea = tegra_fb_copyarea, 282 .fb_copyarea = tegra_fb_copyarea,
602 .fb_imageblit = tegra_fb_imageblit, 283 .fb_imageblit = tegra_fb_imageblit,
603 .fb_ioctl = tegra_fb_ioctl, 284 .fb_ioctl = tegra_fb_ioctl,
604 }; 285 };
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
686 ret = -ENOMEM; 367 ret = -ENOMEM;
687 goto err; 368 goto err;
688 } 369 }
689 370
690 tegra_fb = info->par; 371 tegra_fb = info->par;
691 tegra_fb->win = win; 372 tegra_fb->win = win;
692 tegra_fb->ndev = ndev; 373 tegra_fb->ndev = ndev;
693 tegra_fb->fb_mem = fb_mem; 374 tegra_fb->fb_mem = fb_mem;
694 tegra_fb->xres = fb_data->xres; 375 tegra_fb->xres = fb_data->xres;
695 tegra_fb->yres = fb_data->yres; 376 tegra_fb->yres = fb_data->yres;
696 tegra_fb->fb_nvmap = nvmap_create_client(nvmap_dev, "tegra-fb");
697 if (!tegra_fb->fb_nvmap) {
698 dev_err(&ndev->dev, "couldn't create nvmap client\n");
699 ret = -ENOMEM;
700 goto err_free;
701 }
702 atomic_set(&tegra_fb->in_use, 0);
703
704 tegra_fb->flip_wq = create_singlethread_workqueue(dev_name(&ndev->dev));
705 if (!tegra_fb->flip_wq) {
706 dev_err(&ndev->dev, "couldn't create flip work-queue\n");
707 ret = -ENOMEM;
708 goto err_delete_wq;
709 }
710 377
711 if (fb_mem) { 378 if (fb_mem) {
712 fb_size = resource_size(fb_mem); 379 fb_size = resource_size(fb_mem);
713 fb_phys = fb_mem->start; 380 fb_phys = fb_mem->start;
714 fb_base = ioremap_nocache(fb_phys, fb_size); 381 fb_base = ioremap_nocache(fb_phys, fb_size);
715 if (!fb_base) { 382 if (!fb_base) {
716 dev_err(&ndev->dev, "fb can't be mapped\n"); 383 dev_err(&ndev->dev, "fb can't be mapped\n");
717 ret = -EBUSY; 384 ret = -EBUSY;
718 » » » goto err_put_client; 385 » » » goto err_free;
719 } 386 }
720 tegra_fb->valid = true; 387 tegra_fb->valid = true;
721 } 388 }
722 389
723 info->fbops = &tegra_fb_ops; 390 info->fbops = &tegra_fb_ops;
724 info->pseudo_palette = pseudo_palette; 391 info->pseudo_palette = pseudo_palette;
725 info->screen_base = fb_base; 392 info->screen_base = fb_base;
726 info->screen_size = fb_size; 393 info->screen_size = fb_size;
727 394
728 strlcpy(info->fix.id, "tegra_fb", sizeof(info->fix.id)); 395 strlcpy(info->fix.id, "tegra_fb", sizeof(info->fix.id));
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
784 dev_info(&ndev->dev, "probed\n"); 451 dev_info(&ndev->dev, "probed\n");
785 452
786 if (fb_data->flags & TEGRA_FB_FLIP_ON_PROBE) { 453 if (fb_data->flags & TEGRA_FB_FLIP_ON_PROBE) {
787 tegra_dc_update_windows(&tegra_fb->win, 1); 454 tegra_dc_update_windows(&tegra_fb->win, 1);
788 tegra_dc_sync_windows(&tegra_fb->win, 1); 455 tegra_dc_sync_windows(&tegra_fb->win, 1);
789 } 456 }
790 457
791 return tegra_fb; 458 return tegra_fb;
792 459
793 err_iounmap_fb: 460 err_iounmap_fb:
794 » iounmap(fb_base); 461 » if (fb_base)
795 err_put_client: 462 » » iounmap(fb_base);
796 » nvmap_client_put(tegra_fb->fb_nvmap);
797 err_delete_wq:
798 » destroy_workqueue(tegra_fb->flip_wq);
799 err_free: 463 err_free:
800 framebuffer_release(info); 464 framebuffer_release(info);
801 err: 465 err:
802 return ERR_PTR(ret); 466 return ERR_PTR(ret);
803 } 467 }
804 468
805 void tegra_fb_unregister(struct tegra_fb_info *fb_info) 469 void tegra_fb_unregister(struct tegra_fb_info *fb_info)
806 { 470 {
807 struct fb_info *info = fb_info->info; 471 struct fb_info *info = fb_info->info;
808 472
809 if (fb_info->win->cur_handle) {
810 nvmap_unpin(fb_info->fb_nvmap, fb_info->win->cur_handle);
811 nvmap_free(fb_info->fb_nvmap, fb_info->win->cur_handle);
812 }
813
814 if (fb_info->fb_nvmap)
815 nvmap_client_put(fb_info->fb_nvmap);
816
817 unregister_framebuffer(info); 473 unregister_framebuffer(info);
818 474
819 flush_workqueue(fb_info->flip_wq);
820 destroy_workqueue(fb_info->flip_wq);
821
822 iounmap(info->screen_base); 475 iounmap(info->screen_base);
823 framebuffer_release(info); 476 framebuffer_release(info);
824 } 477 }
OLDNEW
« no previous file with comments | « drivers/video/tegra/dc/dc.c ('k') | include/video/tegrafb.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698