0e830a4cf5c698c35e0c86b2898893f263d3be1c
[linux-3.10.git] / drivers / video / tegra / fb.c
1 /*
2  * drivers/video/tegra/fb.c
3  *
4  * Copyright (C) 2010 Google, Inc.
5  * Author: Erik Gilling <konkers@android.com>
6  *         Colin Cross <ccross@android.com>
7  *         Travis Geiselbrecht <travis@palm.com>
8  *
9  * Copyright (c) 2010-2016, NVIDIA CORPORATION, All rights reserved.
10  *
11  * This software is licensed under the terms of the GNU General Public
12  * License version 2, as published by the Free Software Foundation, and
13  * may be copied, distributed, and modified under those terms.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  */
21
22 #include <linux/fb.h>
23 #include <linux/module.h>
24 #include <linux/kernel.h>
25 #include <linux/errno.h>
26 #include <linux/string.h>
27 #include <linux/mm.h>
28 #include <linux/highmem.h>
29 #include <linux/uaccess.h>
30 #include <linux/slab.h>
31 #include <linux/file.h>
32 #include <linux/workqueue.h>
33 #include <linux/console.h>
34
35 #include <asm/atomic.h>
36
37 #include <video/tegrafb.h>
38
39 #include <mach/dc.h>
40 #include <mach/fb.h>
41 #include <linux/nvhost.h>
42 #include <linux/nvmap.h>
43
44 #include "host/dev.h"
45 #include "dc/dc_priv.h"
46 #include "dc/edid.h"
47 #include "dc/dc_config.h"
48
49 /* Pad pitch to 256-byte boundary. */
50 #define TEGRA_LINEAR_PITCH_ALIGNMENT 256
51
52 #ifdef CONFIG_COMPAT
53 #define user_ptr(p) ((void __user *)(uintptr_t)(p))
54 #else
55 #define user_ptr(p) (p)
56 #endif
57
58 /* support up to 4K (3840x2150) with double buffering */
59 #define DEFAULT_FBMEM_SIZE      (SZ_64M + SZ_8M)
60
61 struct tegra_fb_info {
62         struct tegra_dc_win     win;
63         struct tegra_dc_win     blank_win;
64         struct platform_device  *ndev;
65         struct fb_info          *info;
66         bool                    valid;
67
68         struct resource         *fb_mem;
69         size_t                  fb_size;
70
71         int                     xres;
72         int                     yres;
73         int                     curr_xoffset;
74         int                     curr_yoffset;
75
76         struct fb_videomode     mode;
77         phys_addr_t             phys_start;
78         int                     kuse_count;
79         int                     mmap_count;
80
81         char __iomem            *blank_base;    /* Virtual address */
82         phys_addr_t             blank_start;
83 };
84
85 /* palette array used by the fbcon */
86 static u32 pseudo_palette[16];
87
88 int tegra_fb_release_fbmem(struct tegra_fb_info *info)
89 {
90         if (info && info->phys_start) {
91                 /* do not release the framebuffer if:
92                  * 1) kernel is using (e.g. fbcon)
93                  * 2) user space has mmap
94                  */
95                 if (info->kuse_count || info->mmap_count)
96                         return -EBUSY;
97
98                 dma_free_writecombine(&info->ndev->dev,
99                                 info->fb_size,
100                                 info->win.virt_addr,
101                                 info->phys_start);
102
103                 info->phys_start = 0;
104                 info->win.virt_addr = NULL;
105         }
106         return 0;
107 }
108
109 static int tegra_fb_open(struct fb_info *fb_info, int user)
110 {
111         struct tegra_fb_info *info = fb_info->par;
112         if (user == 0)
113                 info->kuse_count++;
114         return 0;
115 }
116
117 static int tegra_fb_release(struct fb_info *fb_info, int user)
118 {
119         struct tegra_fb_info *info = fb_info->par;
120         if (user == 0)
121                 info->kuse_count--;
122         return 0;
123 }
124
125 static int tegra_fb_check_var(struct fb_var_screeninfo *var,
126                               struct fb_info *info)
127 {
128         struct tegra_fb_info *tegra_fb = info->par;
129         struct tegra_dc *dc = tegra_fb->win.dc;
130         struct tegra_dc_out_ops *ops = dc->out_ops;
131         struct fb_videomode mode;
132
133         if ((var->yres * var->xres * var->bits_per_pixel / 8 * 2) >
134                 info->screen_size) {
135                 dev_err(&tegra_fb->ndev->dev,
136                         "FB %lu is NOT enough for %dx%d %dbpp!\n",
137                         info->screen_size, var->xres, var->yres,
138                         var->bits_per_pixel);
139                 return -EINVAL;
140         }
141
142         /* Apply mode filter for HDMI only -LVDS supports only fix mode */
143         if (ops && ops->mode_filter) {
144                 /* xoffset and yoffset are not preserved by conversion
145                  * to fb_videomode */
146                 __u32 xoffset = var->xoffset;
147                 __u32 yoffset = var->yoffset;
148
149                 fb_var_to_videomode(&mode, var);
150                 if (!ops->mode_filter(dc, &mode))
151                         return -EINVAL;
152
153                 /* Mode filter may have modified the mode */
154                 fb_videomode_to_var(var, &mode);
155
156                 var->xoffset = xoffset;
157                 var->yoffset = yoffset;
158         }
159
160         /* Double yres_virtual to allow double buffering through pan_display */
161         var->yres_virtual = var->yres * 2;
162
163         return 0;
164 }
165
166 static int tegra_fb_set_par(struct fb_info *info)
167 {
168         struct tegra_fb_info *tegra_fb = info->par;
169         struct fb_var_screeninfo *var = &info->var;
170         struct tegra_dc *dc = tegra_fb->win.dc;
171
172         if (var->bits_per_pixel) {
173                 /* we only support RGB ordering for now */
174                 switch (var->bits_per_pixel) {
175                 case 32:
176                         var->red.offset = 0;
177                         var->red.length = 8;
178                         var->green.offset = 8;
179                         var->green.length = 8;
180                         var->blue.offset = 16;
181                         var->blue.length = 8;
182                         var->transp.offset = 24;
183                         var->transp.length = 8;
184                         tegra_fb->win.fmt = TEGRA_WIN_FMT_R8G8B8A8;
185                         break;
186                 case 16:
187                         var->red.offset = 11;
188                         var->red.length = 5;
189                         var->green.offset = 5;
190                         var->green.length = 6;
191                         var->blue.offset = 0;
192                         var->blue.length = 5;
193                         tegra_fb->win.fmt = TEGRA_WIN_FMT_B5G6R5;
194                         break;
195
196                 default:
197                         return -EINVAL;
198                 }
199                 /* if line_length unset, then pad the stride */
200                 if (!info->fix.line_length) {
201                         info->fix.line_length = var->xres * var->bits_per_pixel
202                                 / 8;
203                         info->fix.line_length = round_up(info->fix.line_length,
204                                                 TEGRA_LINEAR_PITCH_ALIGNMENT);
205                 }
206                 tegra_fb->win.stride = info->fix.line_length;
207                 tegra_fb->win.stride_uv = 0;
208                 tegra_fb->win.phys_addr_u = 0;
209                 tegra_fb->win.phys_addr_v = 0;
210         }
211
212         if (var->pixclock) {
213                 bool stereo;
214                 unsigned old_len = 0;
215                 struct fb_videomode m;
216                 struct fb_videomode *old_mode = NULL;
217                 struct tegra_fb_info *tegra_fb = info->par;
218
219
220                 fb_var_to_videomode(&m, var);
221
222                 /* Load framebuffer info with new mode details*/
223                 old_mode = info->mode;
224                 old_len  = info->fix.line_length;
225                 memcpy(&tegra_fb->mode, &m, sizeof(tegra_fb->mode));
226                 info->mode = (struct fb_videomode *)&tegra_fb->mode;
227                 if (!info->mode) {
228                         dev_warn(&tegra_fb->ndev->dev, "can't match video mode\n");
229                         info->mode = old_mode;
230                         return -EINVAL;
231                 }
232
233                 /* Update fix line_length and window stride as per new mode */
234                 info->fix.line_length = var->xres * var->bits_per_pixel / 8;
235                 info->fix.line_length = round_up(info->fix.line_length,
236                         TEGRA_LINEAR_PITCH_ALIGNMENT);
237                 tegra_fb->win.stride = info->fix.line_length;
238
239                 /*
240                  * only enable stereo if the mode supports it and
241                  * client requests it
242                  */
243                 stereo = !!(var->vmode & info->mode->vmode &
244 #ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT
245                                         FB_VMODE_STEREO_FRAME_PACK);
246 #else
247                                         FB_VMODE_STEREO_LEFT_RIGHT);
248 #endif
249
250                 /* Configure DC with new mode */
251                 if (tegra_dc_set_fb_mode(dc, info->mode, stereo)) {
252                         /* Error while configuring DC, fallback to old mode */
253                         dev_warn(&tegra_fb->ndev->dev, "can't configure dc with mode %ux%u\n",
254                                 info->mode->xres, info->mode->yres);
255                         info->mode = old_mode;
256                         info->fix.line_length = old_len;
257                         tegra_fb->win.stride = old_len;
258                         return -EINVAL;
259                 }
260
261                 tegra_fb->win.w.full = dfixed_const(info->mode->xres);
262                 tegra_fb->win.h.full = dfixed_const(info->mode->yres);
263                 tegra_fb->win.out_w = info->mode->xres;
264                 tegra_fb->win.out_h = info->mode->yres;
265         }
266         return 0;
267 }
268
269 static int tegra_fb_setcolreg(unsigned regno, unsigned red, unsigned green,
270         unsigned blue, unsigned transp, struct fb_info *info)
271 {
272         struct fb_var_screeninfo *var = &info->var;
273
274         if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
275             info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
276                 u32 v;
277
278                 if (regno >= 16)
279                         return -EINVAL;
280
281                 red = (red >> (16 - info->var.red.length));
282                 green = (green >> (16 - info->var.green.length));
283                 blue = (blue >> (16 - info->var.blue.length));
284
285                 v = (red << var->red.offset) |
286                         (green << var->green.offset) |
287                         (blue << var->blue.offset);
288
289                 ((u32 *)info->pseudo_palette)[regno] = v;
290         }
291
292         return 0;
293 }
294
295
296 static int tegra_fb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
297 {
298         struct tegra_fb_info *tegra_fb = info->par;
299         struct tegra_dc *dc = tegra_fb->win.dc;
300         int i;
301 #if defined(CONFIG_TEGRA_LUT)
302         u16 *red = cmap->red;
303         u16 *green = cmap->green;
304         u16 *blue = cmap->blue;
305 #elif defined(CONFIG_TEGRA_LUT_V2)
306         u64 *red = (u64 *)cmap->red;
307         u64 *green = (u64 *)cmap->green;
308         u64 *blue = (u64 *)cmap->blue;
309 #endif
310         int start = cmap->start;
311
312         if (((unsigned)start > 255) || ((start + cmap->len) > 256))
313                 return -EINVAL;
314
315         if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
316                 info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
317                 /*
318                  * For now we are considering color schemes with
319                  * cmap->len <=16 as special case of basic color
320                  * scheme to support fbconsole.But for DirectColor
321                  * visuals(like the one we actually have, that include
322                  * a HW LUT),the way it's intended to work is that the
323                  * actual LUT HW is programmed to the intended values,
324                  * even for small color maps like those with 16 or fewer
325                  * entries. The pseudo_palette is then programmed to the
326                  * identity transform.
327                  */
328                 if (cmap->len <= 16) {
329                         /* Low-color schemes like fbconsole*/
330                         u16 *transp = cmap->transp;
331                         u_int vtransp = 0xffff;
332
333                         for (i = 0; i < cmap->len; i++) {
334                                 if (transp)
335                                         vtransp = *transp++;
336                                 if (tegra_fb_setcolreg(start++, *red++,
337                                         *green++, *blue++,
338                                         vtransp, info))
339                                                 return -EINVAL;
340                         }
341                 } else {
342                         /* High-color schemes*/
343                         for (i = 0; i < cmap->len; i++) {
344 #if defined(CONFIG_TEGRA_LUT)
345                                 dc->fb_lut.r[start+i] = *red++ >> 8;
346                                 dc->fb_lut.g[start+i] = *green++ >> 8;
347                                 dc->fb_lut.b[start+i] = *blue++ >> 8;
348 #elif defined(CONFIG_TEGRA_LUT_V2)
349                                 dc->fb_lut.rgb[start+i] = ((*red++ >> 8) |
350                                                 ((*green++ >> 8) << 16) |
351                                                 ((*blue++ >> 8) << 32));
352 #endif
353                         }
354                         tegra_dc_update_lut(dc, -1, -1);
355                 }
356         }
357         return 0;
358 }
359
360 static int tegra_fb_blank(int blank, struct fb_info *info)
361 {
362         struct tegra_fb_info *tegra_fb = info->par;
363         struct tegra_dc *dc = tegra_fb->win.dc;
364
365         switch (blank) {
366         case FB_BLANK_UNBLANK:
367                 dev_info(&tegra_fb->ndev->dev, "unblank\n");
368                 tegra_dc_enable(dc);
369 #ifdef CONFIG_FRAMEBUFFER_CONSOLE
370                 tegra_dc_cursor_resume(dc);
371 #endif
372                 if (!dc->suspended && dc->blanked &&
373                     !tegra_dc_restore(dc)) {
374                         struct tegra_dc_win *win = &tegra_fb->win;
375                         tegra_dc_update_windows(&win, 1, NULL, true);
376                         tegra_dc_sync_windows(&win, 1);
377                         tegra_dc_program_bandwidth(dc, true);
378                 }
379
380                 dc->blanked = false;
381                 return 0;
382
383         case FB_BLANK_NORMAL:
384                 dev_info(&tegra_fb->ndev->dev, "blank - normal\n");
385                 /* To pan fb at the unblank */
386                 if (dc->enabled)
387                         tegra_fb->curr_xoffset = -1;
388                 dc->blanked = true;
389 #ifdef CONFIG_FRAMEBUFFER_CONSOLE
390                 tegra_dc_cursor_suspend(dc);
391 #endif
392                 tegra_dc_blank(dc, BLANK_ALL);
393                 return 0;
394
395         case FB_BLANK_VSYNC_SUSPEND:
396         case FB_BLANK_HSYNC_SUSPEND:
397         case FB_BLANK_POWERDOWN:
398                 dev_info(&tegra_fb->ndev->dev, "blank - powerdown\n");
399                 /* To pan fb while switching from X */
400                 if (!dc->suspended && dc->enabled)
401                         tegra_fb->curr_xoffset = -1;
402                 tegra_dc_disable(dc);
403 #ifdef CONFIG_FRAMEBUFFER_CONSOLE
404                 dc->blanked = true;
405 #endif
406                 return 0;
407
408         default:
409                 return -ENOTTY;
410         }
411 }
412
413 static int tegra_fb_pan_display(struct fb_var_screeninfo *var,
414                                 struct fb_info *info)
415 {
416         struct tegra_fb_info *tegra_fb = info->par;
417         char __iomem *flush_start;
418         char __iomem *flush_end;
419         phys_addr_t    addr;
420
421         /*
422          * Do nothing if display parameters are same as current values.
423          */
424 #if defined(CONFIG_ANDROID)
425         if ((var->xoffset == tegra_fb->curr_xoffset) &&
426             (var->yoffset == tegra_fb->curr_yoffset) &&
427             !(var->activate & FB_ACTIVATE_FORCE))
428                 return 0;
429 #endif
430
431         if (!tegra_fb->win.cur_handle) {
432                 flush_start = info->screen_base +
433                 (var->yoffset * info->fix.line_length);
434                 flush_end = flush_start + (var->yres * info->fix.line_length);
435
436                 info->var.xoffset = var->xoffset;
437                 info->var.yoffset = var->yoffset;
438                 /*
439                  * Save previous values of xoffset and yoffset so we can
440                  * pan display only when needed.
441                  */
442                 tegra_fb->curr_xoffset = var->xoffset;
443                 tegra_fb->curr_yoffset = var->yoffset;
444
445                 addr = tegra_fb->phys_start + (var->yoffset * info->fix.line_length) +
446                         (var->xoffset * (var->bits_per_pixel/8));
447
448                 tegra_fb->win.phys_addr = addr;
449                 tegra_fb->win.flags = TEGRA_WIN_FLAG_ENABLED;
450                 tegra_fb->win.flags |= TEGRA_WIN_FLAG_FB;
451                 tegra_fb->win.virt_addr = info->screen_base;
452
453                 if (!tegra_fb->win.dc->suspended) {
454                         struct tegra_dc_win *win = &tegra_fb->win;
455                         tegra_dc_update_windows(&win, 1, NULL, true);
456                         tegra_dc_sync_windows(&win, 1);
457                         tegra_dc_program_bandwidth(win->dc, true);
458                 }
459         }
460
461         return 0;
462 }
463
464 static void tegra_fb_fillrect(struct fb_info *info,
465                               const struct fb_fillrect *rect)
466 {
467         cfb_fillrect(info, rect);
468 }
469
470 static void tegra_fb_copyarea(struct fb_info *info,
471                               const struct fb_copyarea *region)
472 {
473         cfb_copyarea(info, region);
474 }
475
476 static void tegra_fb_imageblit(struct fb_info *info,
477                                const struct fb_image *image)
478 {
479         cfb_imageblit(info, image);
480 }
481
482 static int tegra_get_modedb(struct tegra_dc *dc, struct tegra_fb_modedb *modedb,
483         struct fb_info *info)
484 {
485         unsigned i;
486         struct fb_var_screeninfo *modedb_ptr;
487         struct fb_modelist *modelist;
488
489         i = 0;
490         modedb_ptr = user_ptr(modedb->modedb);
491         list_for_each_entry(modelist, &info->modelist, list) {
492                 struct fb_var_screeninfo var;
493
494                 /* fb_videomode_to_var doesn't fill out all the members
495                    of fb_var_screeninfo */
496                 memset(&var, 0x0, sizeof(var));
497
498                 fb_videomode_to_var(&var, &modelist->mode);
499                 var.width = tegra_dc_get_out_width(dc);
500                 var.height = tegra_dc_get_out_height(dc);
501
502                 if (i < modedb->modedb_len) {
503                         void __user *ptr = &modedb_ptr[i];
504
505                         if (copy_to_user(ptr, &var, sizeof(var)))
506                                 return -EFAULT;
507                 }
508                 i++;
509
510                 if (var.vmode & FB_VMODE_STEREO_MASK) {
511                         if (i < modedb->modedb_len) {
512                                 void __user *ptr = &modedb_ptr[i];
513
514                                 var.vmode &= ~FB_VMODE_STEREO_MASK;
515                                 if (copy_to_user(ptr,
516                                         &var, sizeof(var)))
517                                         return -EFAULT;
518                         }
519                         i++;
520                 }
521         }
522
523         /*
524          * If modedb_len == 0, return how many modes are
525          * available; otherwise, return how many modes were written.
526          */
527         if (modedb->modedb_len == 0)
528                 modedb->modedb_len = i;
529         else
530                 modedb->modedb_len = min(modedb->modedb_len, i);
531
532         return 0;
533 }
534
535 static int tegra_fb_ioctl(struct fb_info *info,
536         unsigned int cmd, unsigned long arg)
537 {
538         int res;
539         struct tegra_fb_info *tegra_fb = (struct tegra_fb_info *)info->par;
540         struct tegra_dc *dc = tegra_fb->win.dc;
541         struct tegra_fb_modedb modedb;
542         struct fb_vblank vblank = {};
543
544         switch (cmd) {
545 #ifdef CONFIG_COMPAT
546         case FBIO_TEGRA_GET_MODEDB_COMPAT: {
547                 struct tegra_fb_modedb_compat modedb_compat;
548
549                 if (copy_from_user(&modedb_compat, (void __user *)arg,
550                         sizeof(modedb_compat)))
551                         return -EFAULT;
552                 /* convert compat version to full version */
553                 modedb.modedb = user_ptr(modedb_compat.modedb);
554                 modedb.modedb_len = modedb_compat.modedb_len;
555
556                 res = tegra_get_modedb(dc, &modedb, info);
557                 if (res)
558                         return res;
559
560                 /* convert full version back to compat version */
561                 modedb_compat.modedb_len = modedb.modedb_len;
562                 if (copy_to_user((void __user *)arg, &modedb_compat,
563                         sizeof(modedb_compat)))
564                         return -EFAULT;
565                 break;
566         }
567 #endif
568         case FBIO_TEGRA_GET_MODEDB:
569                 if (copy_from_user(&modedb, (void __user *)arg, sizeof(modedb)))
570                         return -EFAULT;
571
572                 res = tegra_get_modedb(dc, &modedb, info);
573                 if (res)
574                         return res;
575
576                 if (copy_to_user((void __user *)arg, &modedb, sizeof(modedb)))
577                         return -EFAULT;
578                 break;
579
580         case FBIOGET_VBLANK:
581                 if (tegra_dc_has_vsync(dc))
582                         vblank.flags = FB_VBLANK_HAVE_VSYNC;
583
584                 if (copy_to_user(
585                         (void __user *)arg, &vblank, sizeof(vblank)))
586                         return -EFAULT;
587                 break;
588
589         case FBIO_WAITFORVSYNC:
590                 return tegra_dc_wait_for_vsync(dc);
591
592         default:
593                 return -ENOTTY;
594         }
595
596         return 0;
597 }
598
599 int tegra_fb_update_modelist(struct tegra_dc *dc, int fblistindex)
600 {
601         struct list_head *pos, *n;
602         struct fb_info *info = dc->fb->info;
603         struct list_head *srclist = &info->modelist;
604         int index = 0;
605
606         list_for_each_safe(pos, n, srclist) {
607                 if (fblistindex) {
608                         if (index >= fblistindex) {
609                                 /* remove the invalid modes*/
610                                 list_del(pos);
611                                 kfree(pos);
612                         }
613                 }
614                 index += 1;
615         }
616         return index;
617 }
618
619 static int tegra_fb_get_mode_refresh(struct tegra_dc *dc)
620 {
621         if (!dc->fb->info->mode)
622                 return -1;
623         return dc->fb->info->mode->refresh;
624 }
625
626 struct fb_videomode *tegra_fb_get_mode(struct tegra_dc *dc)
627 {
628         if (dc && dc->fb && dc->fb->info && dc->fb->info->mode)
629                 return dc->fb->info->mode;
630         else
631                 return NULL;
632 }
633
634 static int tegra_fb_set_mode(struct tegra_dc *dc, int fps)
635 {
636         size_t stereo;
637         struct list_head *pos;
638         struct fb_videomode *best_mode = NULL;
639         int curr_diff = INT_MAX; /* difference of best_mode refresh rate */
640         struct fb_modelist *modelist;
641         struct fb_info *info = dc->fb->info;
642
643         list_for_each(pos, &info->modelist) {
644                 struct fb_videomode *mode;
645
646                 modelist = list_entry(pos, struct fb_modelist, list);
647                 mode = &modelist->mode;
648                 if (fps <= mode->refresh && curr_diff > (mode->refresh - fps)) {
649                         curr_diff = mode->refresh - fps;
650                         best_mode = mode;
651                 }
652         }
653         if (best_mode) {
654                 info->mode = best_mode;
655                 stereo = !!(info->var.vmode & info->mode->vmode &
656 #ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT
657                                 FB_VMODE_STEREO_FRAME_PACK);
658 #else
659                                 FB_VMODE_STEREO_LEFT_RIGHT);
660 #endif
661                 return tegra_dc_set_fb_mode(dc, best_mode, stereo);
662         }
663         return -EIO;
664 }
665
666 static int tegra_fb_mmap(struct fb_info *fb_info, struct vm_area_struct *vma)
667 {
668         struct tegra_fb_info *info = fb_info->par;
669
670         if (info->phys_start) {
671                 info->mmap_count++;
672                 return dma_mmap_writecombine(&info->ndev->dev, vma,
673                                 info->win.virt_addr,
674                                 info->phys_start,
675                                 info->fb_size);
676         }
677         return -ENOMEM;
678 }
679
680 static struct fb_ops tegra_fb_ops = {
681         .owner = THIS_MODULE,
682         .fb_open = tegra_fb_open,
683         .fb_release = tegra_fb_release,
684         .fb_check_var = tegra_fb_check_var,
685         .fb_set_par = tegra_fb_set_par,
686         .fb_setcmap = tegra_fb_setcmap,
687         .fb_blank = tegra_fb_blank,
688         .fb_pan_display = tegra_fb_pan_display,
689         .fb_fillrect = tegra_fb_fillrect,
690         .fb_copyarea = tegra_fb_copyarea,
691         .fb_imageblit = tegra_fb_imageblit,
692         .fb_ioctl = tegra_fb_ioctl,
693 #ifdef CONFIG_COMPAT
694         .fb_compat_ioctl = tegra_fb_ioctl,
695 #endif
696         .fb_mmap = tegra_fb_mmap,
697 };
698
699 /* Enabling the pan_display by resetting the cache of offset */
700 void tegra_fb_pan_display_reset(struct tegra_fb_info *fb_info)
701 {
702         fb_info->curr_xoffset = -1;
703 }
704
705 void tegra_fb_update_monspecs(struct tegra_fb_info *fb_info,
706                               struct fb_monspecs *specs,
707                               bool (*mode_filter)(const struct tegra_dc *dc,
708                                                   struct fb_videomode *mode))
709
710 {
711         struct fb_event event;
712         int i;
713         int blank = FB_BLANK_NORMAL;
714         struct tegra_dc *dc = fb_info->win.dc;
715
716         mutex_lock(&fb_info->info->lock);
717         fb_destroy_modedb(fb_info->info->monspecs.modedb);
718
719         fb_destroy_modelist(&fb_info->info->modelist);
720
721         event.info = fb_info->info;
722         event.data = &blank;
723
724         /* Notify layers above fb.c that the hardware is unavailable */
725         fb_info->info->state = FBINFO_STATE_SUSPENDED;
726
727         if (specs == NULL) {
728                 struct tegra_dc_mode mode;
729                 memset(&fb_info->info->monspecs, 0x0,
730                        sizeof(fb_info->info->monspecs));
731                 memset(&mode, 0x0, sizeof(mode));
732
733                 /*
734                  * reset video mode properties to prevent garbage being
735                  * displayed on 'mode' device.
736                  */
737                 fb_info->info->mode = (struct fb_videomode*) NULL;
738
739 #ifdef CONFIG_FRAMEBUFFER_CONSOLE
740                 blank = FB_BLANK_POWERDOWN;
741                 console_lock();
742                 fb_add_videomode(&tegra_dc_vga_mode, &fb_info->info->modelist);
743                 fb_videomode_to_var(&fb_info->info->var, &tegra_dc_vga_mode);
744                 fb_notifier_call_chain(FB_EVENT_BLANK, &event);
745                 console_unlock();
746 #endif
747                 /* For L4T - After the next hotplug, framebuffer console will
748                  * use the old variable screeninfo by default, only video-mode
749                  * settings will be overwritten as per monitor connected.
750                  */
751 #ifndef CONFIG_FRAMEBUFFER_CONSOLE
752                 memset(&fb_info->info->var, 0x0, sizeof(fb_info->info->var));
753 #endif /* CONFIG_FRAMEBUFFER_CONSOLE */
754
755                 tegra_dc_set_mode(dc, &mode);
756                 mutex_unlock(&fb_info->info->lock);
757                 return;
758         }
759
760         memcpy(&fb_info->info->monspecs, specs,
761                sizeof(fb_info->info->monspecs));
762         fb_info->info->mode = specs->modedb;
763
764         for (i = 0; i < specs->modedb_len; i++) {
765                 if (mode_filter) {
766                         if (mode_filter(dc, &specs->modedb[i]))
767                                 fb_add_videomode(&specs->modedb[i],
768                                                  &fb_info->info->modelist);
769                 } else {
770                         fb_add_videomode(&specs->modedb[i],
771                                          &fb_info->info->modelist);
772                 }
773         }
774
775         if (dc->out_ops->vrr_update_monspecs)
776                 dc->out_ops->vrr_update_monspecs(dc,
777                         &fb_info->info->modelist);
778
779         event.info = fb_info->info;
780         /* Restoring to state running. */
781         fb_info->info->state =  FBINFO_STATE_RUNNING;
782 #ifdef CONFIG_FRAMEBUFFER_CONSOLE
783         console_lock();
784         tegra_dc_set_fb_mode(fb_info->win.dc, specs->modedb, false);
785         fb_videomode_to_var(&fb_info->info->var, &specs->modedb[0]);
786         fb_notifier_call_chain(FB_EVENT_MODE_CHANGE_ALL, &event);
787         fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event);
788         fb_notifier_call_chain(FB_EVENT_BLANK, &event);
789         blank = FB_BLANK_UNBLANK;
790         fb_notifier_call_chain(FB_EVENT_BLANK, &event);
791         console_unlock();
792 #else
793         fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event);
794 #endif
795         mutex_unlock(&fb_info->info->lock);
796 }
797
798 void tegra_fb_update_fix(struct tegra_fb_info *fb_info,
799                                 struct fb_monspecs *specs)
800 {
801         struct tegra_dc *dc = fb_info->win.dc;
802         struct tegra_edid *dc_edid = dc->edid;
803         struct fb_fix_screeninfo *fix = &fb_info->info->fix;
804
805         mutex_lock(&fb_info->info->lock);
806
807         /* FB_CAP_* and TEGRA_DC_* color depth flags are shifted by 1 */
808         BUILD_BUG_ON((TEGRA_DC_Y420_30 << 1) != FB_CAP_Y420_DC_30);
809         BUILD_BUG_ON((TEGRA_DC_RGB_48 << 1) != FB_CAP_RGB_DC_48);
810         fix->capabilities = (tegra_edid_get_cd_flag(dc_edid) << 1);
811         if (tegra_edid_support_yuv422(dc_edid))
812                 fix->capabilities |= FB_CAP_Y422;
813         if (tegra_edid_support_yuv444(dc_edid))
814                 fix->capabilities |= FB_CAP_Y444;
815         fix->capabilities |= tegra_edid_get_ex_hdr_cap(dc_edid);
816         fix->capabilities |= tegra_edid_get_quant_cap(dc_edid);
817
818         fix->max_clk_rate = tegra_edid_get_max_clk_rate(dc_edid);
819
820         fix->colorimetry = tegra_edid_get_ex_colorimetry(dc_edid);
821
822         mutex_unlock(&fb_info->info->lock);
823 }
824
825 struct fb_var_screeninfo *tegra_fb_get_var(struct tegra_fb_info *fb_info)
826 {
827         if (!fb_info || !fb_info->info)
828                 return NULL;
829
830         return &fb_info->info->var;
831 }
832
833 static ssize_t nvdps_show(struct device *device,
834         struct device_attribute *attr, char *buf)
835 {
836         int refresh_rate;
837         struct platform_device *ndev = to_platform_device(device);
838         struct tegra_dc *dc = platform_get_drvdata(ndev);
839
840         refresh_rate = tegra_fb_get_mode_refresh(dc);
841         return snprintf(buf, PAGE_SIZE, "%d\n", refresh_rate);
842 }
843
844
845 static ssize_t nvdps_store(struct device *dev,
846         struct device_attribute *attr, const char *buf, size_t count)
847 {
848         struct platform_device *ndev = to_platform_device(dev);
849         struct tegra_dc *dc = platform_get_drvdata(ndev);
850         int refresh_rate;
851         int e;
852
853         e = kstrtoint(buf, 10, &refresh_rate);
854         if (e)
855                 return e;
856         e = tegra_fb_set_mode(dc, refresh_rate);
857         if (e)
858                 return e;
859
860         return count;
861 }
862
863 static DEVICE_ATTR(nvdps, S_IRUGO|S_IWUSR, nvdps_show, nvdps_store);
864
865
866 int tegra_fb_create_sysfs(struct device *dev)
867 {
868         return device_create_file(dev, &dev_attr_nvdps);
869 }
870
871 void tegra_fb_remove_sysfs(struct device *dev)
872 {
873         device_remove_file(dev, &dev_attr_nvdps);
874 }
875
876 #define BLANK_LINE_WIDTH        2400
877 #define BLANK_LINE_SIZE         (BLANK_LINE_WIDTH*4)
878
879 static void tegra_fb_fill_420_10bpc_blank_frame(struct tegra_dc_win *win)
880 {
881 #define phase0(p0)      (p0 & 0xff)
882 #define phase1(p0, p1)  (((p1 & 0x3f) << 2) | ((p0 & 0x300) >> 8))
883 #define phase2(p1, p2)  (((p2 & 0xf) << 4) | ((p1 & 0x3c0) >> 6))
884 #define phase3(p2, p3)  (((p3 & 0x3) << 6) | ((p2 & 0x3f0) >> 4))
885 #define phase4(p3)      ((p3 & 0x3fc) >> 2)
886 #define p0(y, c, a)     (phase0(a) << 24 | phase0(y) << 16 | \
887                 phase0(y) << 8 | phase0(c))
888 #define p1(y, c, a)     (phase1(a, a) << 24 | phase1(y, y) << 16 | \
889                 phase1(y, y) << 8 | phase1(c, c))
890 #define p2(y, c, a)     (phase2(a, a) << 24 | phase2(y, y) << 16 | \
891                 phase2(y, y) << 8 | phase2(c, c))
892 #define p3(y, c, a)     (phase3(a, a) << 24 | phase3(y, y) << 16 | \
893                 phase3(y, y) << 8 | phase3(c, c))
894 #define p4(y, c, a)     (phase4(a) << 24 | phase4(y) << 16 | \
895                 phase4(y) << 8 | phase4(c))
896 #define YCC_10BPC_Y_BLACK (64)
897 #define YCC_10BPC_C_BLACK (512)
898
899         u32 y = YCC_10BPC_Y_BLACK;
900         u32 crcb = YCC_10BPC_C_BLACK;
901         u32 a = 0;
902         u32 active_width = BLANK_LINE_WIDTH;
903         u32 temp_w;
904         u32 bytes_per_pix;
905         char __iomem *mem_start = win->virt_addr;
906         u32 offset = 0;
907
908         /* phase statically rendered for TEGRA_WIN_FMT_B8G8R8A8 */
909         bytes_per_pix = tegra_dc_fmt_bpp(TEGRA_WIN_FMT_B8G8R8A8) / 8;
910
911         /* A single line can be repeated through the whole frame height, hence
912          * only the first line needs to be setup. */
913         for (temp_w = 0; temp_w < active_width; temp_w += 5) {
914                 writel_relaxed(p0(y, crcb, a), mem_start +
915                                 offset);
916                 writel_relaxed(p1(y, crcb, a), mem_start +
917                                 ({offset += bytes_per_pix; }));
918                 writel_relaxed(p2(y, crcb, a), mem_start +
919                                 ({offset += bytes_per_pix; }));
920                 writel_relaxed(p3(y, crcb, a), mem_start +
921                                 ({offset += bytes_per_pix; }));
922                 writel_relaxed(p4(y, crcb, a), mem_start +
923                                 ({offset += bytes_per_pix; }));
924                 offset += bytes_per_pix;
925         }
926
927 #undef YCC_10BPC_C_BLACK
928 #undef YCC_10BPC_Y_BLACK
929 #undef p4
930 #undef p3
931 #undef p2
932 #undef p1
933 #undef phase4
934 #undef phase3
935 #undef phase2
936 #undef phase1
937 #undef phase0
938 }
939
940 struct tegra_dc_win *tegra_fb_get_win(struct tegra_fb_info *tegra_fb)
941 {
942         if (!tegra_fb)
943                 return NULL;
944
945         return &tegra_fb->win;
946 }
947
948 struct tegra_dc_win *tegra_fb_get_blank_win(struct tegra_fb_info *tegra_fb)
949 {
950         if (!tegra_fb)
951                 return NULL;
952
953         return &tegra_fb->blank_win;
954 }
955
956 static void tegra_fb_copy_fbmem(void *to, size_t size, struct resource *fb)
957 {
958         size_t i;
959         phys_addr_t from = fb->start;
960         size = min_t(size_t, size, resource_size(fb));
961
962         if (!from || size <= 0)
963                 return;
964
965         BUG_ON(PAGE_ALIGN((unsigned long)to) != (unsigned long)to);
966         BUG_ON(PAGE_ALIGN(from) != from);
967         BUG_ON(PAGE_ALIGN(size) != size);
968         BUG_ON(!pfn_valid(page_to_pfn(phys_to_page(from))));
969
970         for (i = 0; i < size; i += PAGE_SIZE) {
971                 struct page *page = phys_to_page(from + i);
972                 void *from_virt = kmap(page);
973                 memcpy(to + i, from_virt, PAGE_SIZE);
974                 kunmap(page);
975         }
976 }
977
978 struct tegra_fb_info *tegra_fb_register(struct platform_device *ndev,
979                                         struct tegra_dc *dc,
980                                         struct tegra_fb_data *fb_data,
981                                         struct resource *fb_mem,
982                                         void *virt_addr)
983 {
984         struct fb_info *info;
985         struct tegra_fb_info *tegra_fb;
986         void *fb_base = NULL;
987         phys_addr_t fb_size = 0;
988         int ret = 0;
989         int mode_idx;
990         unsigned stride;
991         struct fb_videomode m;
992         DEFINE_DMA_ATTRS(attrs);
993
994         if (!tegra_dc_get_window(dc, fb_data->win)) {
995                 dev_err(&ndev->dev, "dc does not have a window at index %d\n",
996                         fb_data->win);
997                 return ERR_PTR(-ENOENT);
998         }
999
1000         info = framebuffer_alloc(sizeof(struct tegra_fb_info), &ndev->dev);
1001         if (!info) {
1002                 ret = -ENOMEM;
1003                 goto err;
1004         }
1005
1006         tegra_fb = info->par;
1007         tegra_fb->ndev = ndev;
1008         tegra_fb->fb_mem = fb_mem;
1009         tegra_fb->xres = fb_data->xres;
1010         tegra_fb->yres = fb_data->yres;
1011
1012         tegra_fb->win.idx = fb_data->win;
1013
1014         fb_size = fb_data->fbmem_size ? : DEFAULT_FBMEM_SIZE;
1015         fb_base = dma_alloc_writecombine(&ndev->dev, fb_size,
1016                         &tegra_fb->phys_start, GFP_KERNEL);
1017         if (!fb_base) {
1018                 dev_err(&ndev->dev, "failed to allocate framebuffer\n");
1019                 ret = -EBUSY;
1020                 goto err_free;
1021         }
1022
1023         /* copy content from the bootloader framebuffer */
1024         tegra_fb_copy_fbmem(fb_base, fb_size, fb_mem);
1025         tegra_fb->fb_size = fb_size;
1026         tegra_fb->valid = true;
1027
1028         dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
1029         tegra_fb->blank_base = dma_alloc_attrs(&ndev->dev,
1030                                                BLANK_LINE_SIZE,
1031                                                &tegra_fb->blank_start,
1032                                                GFP_KERNEL,
1033                                                &attrs);
1034         if (!tegra_fb->blank_base) {
1035                 dev_err(&ndev->dev, "failed to allocate blank buffer\n");
1036                 ret = -EBUSY;
1037                 goto err_free_fbmem;
1038         }
1039
1040         info->fix.line_length = fb_data->xres * fb_data->bits_per_pixel / 8;
1041
1042         stride = tegra_dc_get_stride(dc, fb_data->win);
1043         if (!stride) /* default to pad the stride */
1044                 stride = round_up(info->fix.line_length,
1045                         TEGRA_LINEAR_PITCH_ALIGNMENT);
1046
1047         info->fbops = &tegra_fb_ops;
1048         info->pseudo_palette = pseudo_palette;
1049         info->screen_base = fb_base;
1050         info->screen_size = fb_size;
1051
1052         strlcpy(info->fix.id, "tegra_fb", sizeof(info->fix.id));
1053         info->fix.type          = FB_TYPE_PACKED_PIXELS;
1054         info->fix.visual        = FB_VISUAL_TRUECOLOR;
1055         info->fix.xpanstep      = 1;
1056         info->fix.ypanstep      = 1;
1057         info->fix.accel         = FB_ACCEL_NONE;
1058         /* Note:- Use tegra_fb_info.phys_start instead of
1059          *        fb_info.fix->smem_start when LPAE is enabled. */
1060         info->fix.smem_start    = (u32)tegra_fb->phys_start;
1061         info->fix.smem_len      = fb_size;
1062         info->fix.line_length = stride;
1063         INIT_LIST_HEAD(&info->modelist);
1064         /* pick first mode as the default for initialization */
1065         tegra_dc_to_fb_videomode(&m, &dc->mode);
1066         fb_videomode_to_var(&info->var, &m);
1067         info->var.xres_virtual          = fb_data->xres;
1068         info->var.yres_virtual          = fb_data->yres * 2;
1069         info->var.bits_per_pixel        = fb_data->bits_per_pixel;
1070         info->var.activate              = FB_ACTIVATE_VBL;
1071         info->var.height                = tegra_dc_get_out_height(dc);
1072         info->var.width                 = tegra_dc_get_out_width(dc);
1073
1074         tegra_fb->win.dc = dc;
1075         tegra_fb->win.x.full = dfixed_const(0);
1076         tegra_fb->win.y.full = dfixed_const(0);
1077         tegra_fb->win.w.full = dfixed_const(fb_data->xres);
1078         tegra_fb->win.h.full = dfixed_const(fb_data->yres);
1079         /* TODO: set to output res dc */
1080         tegra_fb->win.out_x = 0;
1081         tegra_fb->win.out_y = 0;
1082         tegra_fb->win.out_w = fb_data->xres;
1083         tegra_fb->win.out_h = fb_data->yres;
1084         tegra_fb->win.z = 0;
1085         tegra_fb->win.phys_addr = tegra_fb->phys_start;
1086         tegra_fb->win.virt_addr = fb_base;
1087         tegra_fb->win.phys_addr_u = 0;
1088         tegra_fb->win.phys_addr_v = 0;
1089         tegra_fb->win.stride = info->fix.line_length;
1090         tegra_fb->win.stride_uv = 0;
1091         tegra_fb->win.flags = TEGRA_WIN_FLAG_ENABLED;
1092         tegra_fb->win.global_alpha = 0xFF;
1093
1094         tegra_fb->blank_win = tegra_fb->win;
1095         tegra_fb->blank_win.phys_addr = tegra_fb->blank_start;
1096         tegra_fb->blank_win.virt_addr = tegra_fb->blank_base;
1097         tegra_fb_fill_420_10bpc_blank_frame(&tegra_fb->blank_win);
1098
1099         for (mode_idx = 0; mode_idx < dc->out->n_modes; mode_idx++) {
1100                 struct tegra_dc_mode mode = dc->out->modes[mode_idx];
1101                 struct fb_videomode vmode;
1102
1103                 mode.pclk = dc->mode.pclk;
1104
1105                 if (mode.pclk > 1000) {
1106                         tegra_dc_to_fb_videomode(&vmode, &mode);
1107                         fb_add_videomode(&vmode, &info->modelist);
1108                 }
1109         }
1110
1111         if (dc->out_ops->vrr_update_monspecs)
1112                 dc->out_ops->vrr_update_monspecs(dc, &info->modelist);
1113
1114         if (fb_mem)
1115                 tegra_fb_set_par(info);
1116
1117         if (register_framebuffer(info)) {
1118                 dev_err(&ndev->dev, "failed to register framebuffer\n");
1119                 ret = -ENODEV;
1120                 goto err_iounmap_fb;
1121         }
1122
1123         if (ndev->id != info->node) {
1124                 dev_err(&ndev->dev, "FB device numbering does not\n"
1125                           "match device numbering of extended\n"
1126                           "display interfaces\n");
1127                 ret = -EINVAL;
1128                 goto err_iounmap_fb;
1129         }
1130
1131         tegra_fb->info = info;
1132
1133         if (fb_data->flags & TEGRA_FB_FLIP_ON_PROBE) {
1134                 struct tegra_dc_win *win = &tegra_fb->win;
1135                 tegra_dc_update_windows(&win, 1, NULL, true);
1136                 tegra_dc_sync_windows(&win, 1);
1137                 tegra_dc_program_bandwidth(win->dc, true);
1138         }
1139
1140         dev_info(&ndev->dev, "fb registered\n");
1141
1142         return tegra_fb;
1143
1144 err_iounmap_fb:
1145         dma_free_attrs(&ndev->dev, BLANK_LINE_SIZE, tegra_fb->blank_base,
1146                        tegra_fb->blank_start, &attrs);
1147         if (fb_base)
1148                 iounmap(fb_base);
1149 err_free_fbmem:
1150         tegra_fb_release_fbmem(tegra_fb);
1151 err_free:
1152         framebuffer_release(info);
1153 err:
1154         return ERR_PTR(ret);
1155 }
1156
1157 void tegra_fb_unregister(struct tegra_fb_info *fb_info)
1158 {
1159         struct fb_info *info = fb_info->info;
1160         struct device *dev = &fb_info->ndev->dev;
1161         DEFINE_DMA_ATTRS(attrs);
1162
1163         dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
1164
1165         dma_free_attrs(dev, BLANK_LINE_SIZE, fb_info->blank_base,
1166                        fb_info->blank_start, &attrs);
1167
1168         tegra_fb_release_fbmem(fb_info);
1169         unregister_framebuffer(info);
1170         iounmap(info->screen_base);
1171         framebuffer_release(info);
1172 }