2 * drivers/video/tegra/fb.c
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>
9 * Copyright (c) 2010-2016, NVIDIA CORPORATION, All rights reserved.
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.
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.
23 #include <linux/module.h>
24 #include <linux/kernel.h>
25 #include <linux/errno.h>
26 #include <linux/string.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>
34 #include <asm/atomic.h>
36 #include <video/tegrafb.h>
40 #include <linux/nvhost.h>
41 #include <linux/nvmap.h>
44 #include "dc/dc_priv.h"
46 #include "dc/dc_config.h"
48 /* Pad pitch to 256-byte boundary. */
49 #define TEGRA_LINEAR_PITCH_ALIGNMENT 256
52 #define user_ptr(p) ((void __user *)(uintptr_t)(p))
54 #define user_ptr(p) (p)
57 struct tegra_fb_info {
58 struct tegra_dc_win win;
59 struct tegra_dc_win blank_win;
60 struct platform_device *ndev;
64 struct resource *fb_mem;
71 struct fb_videomode mode;
72 phys_addr_t phys_start;
74 char __iomem *blank_base; /* Virtual address */
75 phys_addr_t blank_start;
78 /* palette array used by the fbcon */
79 static u32 pseudo_palette[16];
81 static int tegra_fb_check_var(struct fb_var_screeninfo *var,
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;
89 if ((var->yres * var->xres * var->bits_per_pixel / 8 * 2) >
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,
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
102 __u32 xoffset = var->xoffset;
103 __u32 yoffset = var->yoffset;
105 fb_var_to_videomode(&mode, var);
106 if (!ops->mode_filter(dc, &mode))
109 /* Mode filter may have modified the mode */
110 fb_videomode_to_var(var, &mode);
112 var->xoffset = xoffset;
113 var->yoffset = yoffset;
116 /* Double yres_virtual to allow double buffering through pan_display */
117 var->yres_virtual = var->yres * 2;
122 static int tegra_fb_set_par(struct fb_info *info)
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;
128 if (var->bits_per_pixel) {
129 /* we only support RGB ordering for now */
130 switch (var->bits_per_pixel) {
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;
143 var->red.offset = 11;
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;
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
159 info->fix.line_length = round_up(info->fix.line_length,
160 TEGRA_LINEAR_PITCH_ALIGNMENT);
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;
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;
176 fb_var_to_videomode(&m, var);
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;
184 dev_warn(&tegra_fb->ndev->dev, "can't match video mode\n");
185 info->mode = old_mode;
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;
196 * only enable stereo if the mode supports it and
199 stereo = !!(var->vmode & info->mode->vmode &
200 #ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT
201 FB_VMODE_STEREO_FRAME_PACK);
203 FB_VMODE_STEREO_LEFT_RIGHT);
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;
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;
225 static int tegra_fb_setcolreg(unsigned regno, unsigned red, unsigned green,
226 unsigned blue, unsigned transp, struct fb_info *info)
228 struct fb_var_screeninfo *var = &info->var;
230 if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
231 info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
237 red = (red >> (16 - info->var.red.length));
238 green = (green >> (16 - info->var.green.length));
239 blue = (blue >> (16 - info->var.blue.length));
241 v = (red << var->red.offset) |
242 (green << var->green.offset) |
243 (blue << var->blue.offset);
245 ((u32 *)info->pseudo_palette)[regno] = v;
252 static int tegra_fb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
254 struct tegra_fb_info *tegra_fb = info->par;
255 struct tegra_dc *dc = tegra_fb->win.dc;
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;
266 int start = cmap->start;
268 if (((unsigned)start > 255) || ((start + cmap->len) > 256))
271 if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
272 info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
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.
284 if (cmap->len <= 16) {
285 /* Low-color schemes like fbconsole*/
286 u16 *transp = cmap->transp;
287 u_int vtransp = 0xffff;
289 for (i = 0; i < cmap->len; i++) {
292 if (tegra_fb_setcolreg(start++, *red++,
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));
310 tegra_dc_update_lut(dc, -1, -1);
316 static int tegra_fb_blank(int blank, struct fb_info *info)
318 struct tegra_fb_info *tegra_fb = info->par;
319 struct tegra_dc *dc = tegra_fb->win.dc;
322 case FB_BLANK_UNBLANK:
323 dev_info(&tegra_fb->ndev->dev, "unblank\n");
325 #ifdef CONFIG_FRAMEBUFFER_CONSOLE
326 tegra_dc_cursor_resume(dc);
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);
339 case FB_BLANK_NORMAL:
340 dev_info(&tegra_fb->ndev->dev, "blank - normal\n");
341 /* To pan fb at the unblank */
343 tegra_fb->curr_xoffset = -1;
345 #ifdef CONFIG_FRAMEBUFFER_CONSOLE
346 tegra_dc_cursor_suspend(dc);
348 tegra_dc_blank(dc, BLANK_ALL);
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);
366 static int tegra_fb_pan_display(struct fb_var_screeninfo *var,
367 struct fb_info *info)
369 struct tegra_fb_info *tegra_fb = info->par;
370 char __iomem *flush_start;
371 char __iomem *flush_end;
375 * Do nothing if display parameters are same as current values.
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))
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);
389 info->var.xoffset = var->xoffset;
390 info->var.yoffset = var->yoffset;
392 * Save previous values of xoffset and yoffset so we can
393 * pan display only when needed.
395 tegra_fb->curr_xoffset = var->xoffset;
396 tegra_fb->curr_yoffset = var->yoffset;
398 addr = tegra_fb->phys_start + (var->yoffset * info->fix.line_length) +
399 (var->xoffset * (var->bits_per_pixel/8));
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;
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);
417 static void tegra_fb_fillrect(struct fb_info *info,
418 const struct fb_fillrect *rect)
420 cfb_fillrect(info, rect);
423 static void tegra_fb_copyarea(struct fb_info *info,
424 const struct fb_copyarea *region)
426 cfb_copyarea(info, region);
429 static void tegra_fb_imageblit(struct fb_info *info,
430 const struct fb_image *image)
432 cfb_imageblit(info, image);
435 static int tegra_get_modedb(struct tegra_dc *dc, struct tegra_fb_modedb *modedb,
436 struct fb_info *info)
439 struct fb_var_screeninfo *modedb_ptr;
440 struct fb_modelist *modelist;
443 modedb_ptr = user_ptr(modedb->modedb);
444 list_for_each_entry(modelist, &info->modelist, list) {
445 struct fb_var_screeninfo var;
447 /* fb_videomode_to_var doesn't fill out all the members
448 of fb_var_screeninfo */
449 memset(&var, 0x0, sizeof(var));
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);
455 if (i < modedb->modedb_len) {
456 void __user *ptr = &modedb_ptr[i];
458 if (copy_to_user(ptr, &var, sizeof(var)))
463 if (var.vmode & FB_VMODE_STEREO_MASK) {
464 if (i < modedb->modedb_len) {
465 void __user *ptr = &modedb_ptr[i];
467 var.vmode &= ~FB_VMODE_STEREO_MASK;
468 if (copy_to_user(ptr,
477 * If modedb_len == 0, return how many modes are
478 * available; otherwise, return how many modes were written.
480 if (modedb->modedb_len == 0)
481 modedb->modedb_len = i;
483 modedb->modedb_len = min(modedb->modedb_len, i);
488 static int tegra_fb_ioctl(struct fb_info *info,
489 unsigned int cmd, unsigned long arg)
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 = {};
499 case FBIO_TEGRA_GET_MODEDB_COMPAT: {
500 struct tegra_fb_modedb_compat modedb_compat;
502 if (copy_from_user(&modedb_compat, (void __user *)arg,
503 sizeof(modedb_compat)))
505 /* convert compat version to full version */
506 modedb.modedb = user_ptr(modedb_compat.modedb);
507 modedb.modedb_len = modedb_compat.modedb_len;
509 res = tegra_get_modedb(dc, &modedb, info);
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)))
521 case FBIO_TEGRA_GET_MODEDB:
522 if (copy_from_user(&modedb, (void __user *)arg, sizeof(modedb)))
525 res = tegra_get_modedb(dc, &modedb, info);
529 if (copy_to_user((void __user *)arg, &modedb, sizeof(modedb)))
534 if (tegra_dc_has_vsync(dc))
535 vblank.flags = FB_VBLANK_HAVE_VSYNC;
538 (void __user *)arg, &vblank, sizeof(vblank)))
542 case FBIO_WAITFORVSYNC:
543 return tegra_dc_wait_for_vsync(dc);
552 int tegra_fb_update_modelist(struct tegra_dc *dc, int fblistindex)
554 struct list_head *pos, *n;
555 struct fb_info *info = dc->fb->info;
556 struct list_head *srclist = &info->modelist;
559 list_for_each_safe(pos, n, srclist) {
561 if (index >= fblistindex) {
562 /* remove the invalid modes*/
572 static int tegra_fb_get_mode_refresh(struct tegra_dc *dc)
574 if (!dc->fb->info->mode)
576 return dc->fb->info->mode->refresh;
579 struct fb_videomode *tegra_fb_get_mode(struct tegra_dc *dc)
581 if (dc && dc->fb && dc->fb->info && dc->fb->info->mode)
582 return dc->fb->info->mode;
587 static int tegra_fb_set_mode(struct tegra_dc *dc, int fps)
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;
596 list_for_each(pos, &info->modelist) {
597 struct fb_videomode *mode;
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;
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);
612 FB_VMODE_STEREO_LEFT_RIGHT);
614 return tegra_dc_set_fb_mode(dc, best_mode, stereo);
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,
631 .fb_compat_ioctl = tegra_fb_ioctl,
635 /* Enabling the pan_display by resetting the cache of offset */
636 void tegra_fb_pan_display_reset(struct tegra_fb_info *fb_info)
638 fb_info->curr_xoffset = -1;
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))
647 struct fb_event event;
649 int blank = FB_BLANK_UNBLANK;
650 struct tegra_dc *dc = fb_info->win.dc;
652 mutex_lock(&fb_info->info->lock);
653 fb_destroy_modedb(fb_info->info->monspecs.modedb);
655 fb_destroy_modelist(&fb_info->info->modelist);
657 event.info = fb_info->info;
660 /* Notify layers above fb.c that the hardware is unavailable */
661 fb_info->info->state = FBINFO_STATE_SUSPENDED;
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));
670 * reset video mode properties to prevent garbage being
671 * displayed on 'mode' device.
673 fb_info->info->mode = (struct fb_videomode*) NULL;
675 #ifdef CONFIG_FRAMEBUFFER_CONSOLE
676 blank = FB_BLANK_POWERDOWN;
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);
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.
687 #ifndef CONFIG_FRAMEBUFFER_CONSOLE
688 memset(&fb_info->info->var, 0x0, sizeof(fb_info->info->var));
689 #endif /* CONFIG_FRAMEBUFFER_CONSOLE */
691 tegra_dc_set_mode(dc, &mode);
692 mutex_unlock(&fb_info->info->lock);
696 memcpy(&fb_info->info->monspecs, specs,
697 sizeof(fb_info->info->monspecs));
698 fb_info->info->mode = specs->modedb;
700 for (i = 0; i < specs->modedb_len; i++) {
702 if (mode_filter(dc, &specs->modedb[i]))
703 fb_add_videomode(&specs->modedb[i],
704 &fb_info->info->modelist);
706 fb_add_videomode(&specs->modedb[i],
707 &fb_info->info->modelist);
711 if (dc->out_ops->vrr_update_monspecs)
712 dc->out_ops->vrr_update_monspecs(dc,
713 &fb_info->info->modelist);
715 event.info = fb_info->info;
716 /* Restoring to state running. */
717 fb_info->info->state = FBINFO_STATE_RUNNING;
718 #ifdef CONFIG_FRAMEBUFFER_CONSOLE
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);
727 fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event);
729 mutex_unlock(&fb_info->info->lock);
732 void tegra_fb_update_fix(struct tegra_fb_info *fb_info,
733 struct fb_monspecs *specs)
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;
739 mutex_lock(&fb_info->info->lock);
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;
752 fix->max_clk_rate = tegra_edid_get_max_clk_rate(dc_edid);
754 fix->colorimetry = tegra_edid_get_ex_colorimetry(dc_edid);
756 mutex_unlock(&fb_info->info->lock);
759 struct fb_var_screeninfo *tegra_fb_get_var(struct tegra_fb_info *fb_info)
761 if (!fb_info || !fb_info->info)
764 return &fb_info->info->var;
767 static ssize_t nvdps_show(struct device *device,
768 struct device_attribute *attr, char *buf)
771 struct platform_device *ndev = to_platform_device(device);
772 struct tegra_dc *dc = platform_get_drvdata(ndev);
774 refresh_rate = tegra_fb_get_mode_refresh(dc);
775 return snprintf(buf, PAGE_SIZE, "%d\n", refresh_rate);
779 static ssize_t nvdps_store(struct device *dev,
780 struct device_attribute *attr, const char *buf, size_t count)
782 struct platform_device *ndev = to_platform_device(dev);
783 struct tegra_dc *dc = platform_get_drvdata(ndev);
787 e = kstrtoint(buf, 10, &refresh_rate);
790 e = tegra_fb_set_mode(dc, refresh_rate);
797 static DEVICE_ATTR(nvdps, S_IRUGO|S_IWUSR, nvdps_show, nvdps_store);
800 int tegra_fb_create_sysfs(struct device *dev)
802 return device_create_file(dev, &dev_attr_nvdps);
805 void tegra_fb_remove_sysfs(struct device *dev)
807 device_remove_file(dev, &dev_attr_nvdps);
810 #define BLANK_LINE_WIDTH 2400
811 #define BLANK_LINE_SIZE (BLANK_LINE_WIDTH*4)
813 static void tegra_fb_fill_420_10bpc_blank_frame(struct tegra_dc_win *win)
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)
833 u32 y = YCC_10BPC_Y_BLACK;
834 u32 crcb = YCC_10BPC_C_BLACK;
836 u32 active_width = BLANK_LINE_WIDTH;
839 char __iomem *mem_start = win->virt_addr;
842 /* phase statically rendered for TEGRA_WIN_FMT_B8G8R8A8 */
843 bytes_per_pix = tegra_dc_fmt_bpp(TEGRA_WIN_FMT_B8G8R8A8) / 8;
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 +
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;
861 #undef YCC_10BPC_C_BLACK
862 #undef YCC_10BPC_Y_BLACK
874 struct tegra_dc_win *tegra_fb_get_win(struct tegra_fb_info *tegra_fb)
879 return &tegra_fb->win;
882 struct tegra_dc_win *tegra_fb_get_blank_win(struct tegra_fb_info *tegra_fb)
887 return &tegra_fb->blank_win;
890 struct tegra_fb_info *tegra_fb_register(struct platform_device *ndev,
892 struct tegra_fb_data *fb_data,
893 struct resource *fb_mem,
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;
903 struct fb_videomode m;
904 DEFINE_DMA_ATTRS(attrs);
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",
909 return ERR_PTR(-ENOENT);
912 info = framebuffer_alloc(sizeof(struct tegra_fb_info), &ndev->dev);
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;
924 tegra_fb->win.idx = fb_data->win;
927 fb_size = resource_size(fb_mem);
928 tegra_fb->phys_start = fb_mem->start;
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);
935 dev_err(&ndev->dev, "fb can't be mapped\n");
939 tegra_fb->valid = true;
942 dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
943 tegra_fb->blank_base = dma_alloc_attrs(&ndev->dev,
945 &tegra_fb->blank_start,
948 if (!tegra_fb->blank_base) {
949 dev_err(&ndev->dev, "failed to allocate blank buffer\n");
954 info->fix.line_length = fb_data->xres * fb_data->bits_per_pixel / 8;
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);
961 info->fbops = &tegra_fb_ops;
962 info->pseudo_palette = pseudo_palette;
963 info->screen_base = fb_base;
964 info->screen_size = fb_size;
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);
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;
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;
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);
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;
1017 mode.pclk = dc->mode.pclk;
1019 if (mode.pclk > 1000) {
1020 tegra_dc_to_fb_videomode(&vmode, &mode);
1021 fb_add_videomode(&vmode, &info->modelist);
1025 if (dc->out_ops->vrr_update_monspecs)
1026 dc->out_ops->vrr_update_monspecs(dc, &info->modelist);
1029 tegra_fb_set_par(info);
1031 if (register_framebuffer(info)) {
1032 dev_err(&ndev->dev, "failed to register framebuffer\n");
1034 goto err_iounmap_fb;
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");
1042 goto err_iounmap_fb;
1045 tegra_fb->info = info;
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);
1054 dev_info(&ndev->dev, "fb registered\n");
1059 dma_free_attrs(&ndev->dev, BLANK_LINE_SIZE, tegra_fb->blank_base,
1060 tegra_fb->blank_start, &attrs);
1064 framebuffer_release(info);
1066 return ERR_PTR(ret);
1069 void tegra_fb_unregister(struct tegra_fb_info *fb_info)
1071 struct fb_info *info = fb_info->info;
1072 struct device *dev = &fb_info->ndev->dev;
1073 DEFINE_DMA_ATTRS(attrs);
1075 dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
1077 dma_free_attrs(dev, BLANK_LINE_SIZE, fb_info->blank_base,
1078 fb_info->blank_start, &attrs);
1080 unregister_framebuffer(info);
1082 iounmap(info->screen_base);
1083 framebuffer_release(info);