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