diff mbox

[v6,6/7] efifb: Set info->fbcon_rotate_hint based on drm_get_panel_orientation_quirk

Message ID 20171125173341.14162-7-hdegoede@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Hans de Goede Nov. 25, 2017, 5:33 p.m. UTC
On some hardware the LCD panel is not mounted upright in the casing,
but rotated by 90 degrees. In this case we want the console to
automatically be rotated to compensate.

The drm subsys has a quirk table for this, use the
drm_get_panel_orientation_quirk function to get the panel orientation
and set info->fbcon_rotate_hint based on this, so that the fbcon console
on top of efifb gets automatically rotated to compensate for the panel
orientation.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/video/fbdev/Kconfig |  1 +
 drivers/video/fbdev/efifb.c | 21 ++++++++++++++++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

Comments

kernel test robot Nov. 28, 2017, 3:47 p.m. UTC | #1
Hi Hans,

I love your patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v4.15-rc1 next-20171128]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Hans-de-Goede/drm-fbdev-Panel-orientation-connector-property-support/20171128-225025
config: i386-randconfig-x003-201748 (attached as .config)
compiler: gcc-7 (Debian 7.2.0-12) 7.2.1 20171025
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   drivers/video/fbdev/efifb.c: In function 'efifb_probe':
>> drivers/video/fbdev/efifb.c:340:7: error: 'DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP' undeclared (first use in this function); did you mean 'DRM_MODE_PRESENT_BOTTOM_FIELD'?
     case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP:
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          DRM_MODE_PRESENT_BOTTOM_FIELD
   drivers/video/fbdev/efifb.c:340:7: note: each undeclared identifier is reported only once for each function it appears in
>> drivers/video/fbdev/efifb.c:343:7: error: 'DRM_MODE_PANEL_ORIENTATION_LEFT_UP' undeclared (first use in this function); did you mean 'DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP'?
     case DRM_MODE_PANEL_ORIENTATION_LEFT_UP:
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP
>> drivers/video/fbdev/efifb.c:346:7: error: 'DRM_MODE_PANEL_ORIENTATION_RIGHT_UP' undeclared (first use in this function); did you mean 'DRM_MODE_PANEL_ORIENTATION_LEFT_UP'?
     case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP:
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          DRM_MODE_PANEL_ORIENTATION_LEFT_UP

vim +340 drivers/video/fbdev/efifb.c

   158	
   159	static int efifb_probe(struct platform_device *dev)
   160	{
   161		struct fb_info *info;
   162		int err, orientation;
   163		unsigned int size_vmode;
   164		unsigned int size_remap;
   165		unsigned int size_total;
   166		char *option = NULL;
   167	
   168		if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI || pci_dev_disabled)
   169			return -ENODEV;
   170	
   171		if (fb_get_options("efifb", &option))
   172			return -ENODEV;
   173		efifb_setup(option);
   174	
   175		/* We don't get linelength from UGA Draw Protocol, only from
   176		 * EFI Graphics Protocol.  So if it's not in DMI, and it's not
   177		 * passed in from the user, we really can't use the framebuffer.
   178		 */
   179		if (!screen_info.lfb_linelength)
   180			return -ENODEV;
   181	
   182		if (!screen_info.lfb_depth)
   183			screen_info.lfb_depth = 32;
   184		if (!screen_info.pages)
   185			screen_info.pages = 1;
   186		if (!fb_base_is_valid()) {
   187			printk(KERN_DEBUG "efifb: invalid framebuffer address\n");
   188			return -ENODEV;
   189		}
   190		printk(KERN_INFO "efifb: probing for efifb\n");
   191	
   192		/* just assume they're all unset if any are */
   193		if (!screen_info.blue_size) {
   194			screen_info.blue_size = 8;
   195			screen_info.blue_pos = 0;
   196			screen_info.green_size = 8;
   197			screen_info.green_pos = 8;
   198			screen_info.red_size = 8;
   199			screen_info.red_pos = 16;
   200			screen_info.rsvd_size = 8;
   201			screen_info.rsvd_pos = 24;
   202		}
   203	
   204		efifb_fix.smem_start = screen_info.lfb_base;
   205	
   206		if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE) {
   207			u64 ext_lfb_base;
   208	
   209			ext_lfb_base = (u64)(unsigned long)screen_info.ext_lfb_base << 32;
   210			efifb_fix.smem_start |= ext_lfb_base;
   211		}
   212	
   213		if (bar_resource &&
   214		    bar_resource->start + bar_offset != efifb_fix.smem_start) {
   215			dev_info(&efifb_pci_dev->dev,
   216				 "BAR has moved, updating efifb address\n");
   217			efifb_fix.smem_start = bar_resource->start + bar_offset;
   218		}
   219	
   220		efifb_defined.bits_per_pixel = screen_info.lfb_depth;
   221		efifb_defined.xres = screen_info.lfb_width;
   222		efifb_defined.yres = screen_info.lfb_height;
   223		efifb_fix.line_length = screen_info.lfb_linelength;
   224	
   225		/*   size_vmode -- that is the amount of memory needed for the
   226		 *                 used video mode, i.e. the minimum amount of
   227		 *                 memory we need. */
   228		size_vmode = efifb_defined.yres * efifb_fix.line_length;
   229	
   230		/*   size_total -- all video memory we have. Used for
   231		 *                 entries, ressource allocation and bounds
   232		 *                 checking. */
   233		size_total = screen_info.lfb_size;
   234		if (size_total < size_vmode)
   235			size_total = size_vmode;
   236	
   237		/*   size_remap -- the amount of video memory we are going to
   238		 *                 use for efifb.  With modern cards it is no
   239		 *                 option to simply use size_total as that
   240		 *                 wastes plenty of kernel address space. */
   241		size_remap  = size_vmode * 2;
   242		if (size_remap > size_total)
   243			size_remap = size_total;
   244		if (size_remap % PAGE_SIZE)
   245			size_remap += PAGE_SIZE - (size_remap % PAGE_SIZE);
   246		efifb_fix.smem_len = size_remap;
   247	
   248		if (request_mem_region(efifb_fix.smem_start, size_remap, "efifb")) {
   249			request_mem_succeeded = true;
   250		} else {
   251			/* We cannot make this fatal. Sometimes this comes from magic
   252			   spaces our resource handlers simply don't know about */
   253			pr_warn("efifb: cannot reserve video memory at 0x%lx\n",
   254				efifb_fix.smem_start);
   255		}
   256	
   257		info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
   258		if (!info) {
   259			pr_err("efifb: cannot allocate framebuffer\n");
   260			err = -ENOMEM;
   261			goto err_release_mem;
   262		}
   263		platform_set_drvdata(dev, info);
   264		info->pseudo_palette = info->par;
   265		info->par = NULL;
   266	
   267		info->apertures = alloc_apertures(1);
   268		if (!info->apertures) {
   269			err = -ENOMEM;
   270			goto err_release_fb;
   271		}
   272		info->apertures->ranges[0].base = efifb_fix.smem_start;
   273		info->apertures->ranges[0].size = size_remap;
   274	
   275		if (nowc)
   276			info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len);
   277		else
   278			info->screen_base = ioremap_wc(efifb_fix.smem_start, efifb_fix.smem_len);
   279		if (!info->screen_base) {
   280			pr_err("efifb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n",
   281				efifb_fix.smem_len, efifb_fix.smem_start);
   282			err = -EIO;
   283			goto err_release_fb;
   284		}
   285	
   286		pr_info("efifb: framebuffer at 0x%lx, using %dk, total %dk\n",
   287		       efifb_fix.smem_start, size_remap/1024, size_total/1024);
   288		pr_info("efifb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
   289		       efifb_defined.xres, efifb_defined.yres,
   290		       efifb_defined.bits_per_pixel, efifb_fix.line_length,
   291		       screen_info.pages);
   292	
   293		efifb_defined.xres_virtual = efifb_defined.xres;
   294		efifb_defined.yres_virtual = efifb_fix.smem_len /
   295						efifb_fix.line_length;
   296		pr_info("efifb: scrolling: redraw\n");
   297		efifb_defined.yres_virtual = efifb_defined.yres;
   298	
   299		/* some dummy values for timing to make fbset happy */
   300		efifb_defined.pixclock     = 10000000 / efifb_defined.xres *
   301						1000 / efifb_defined.yres;
   302		efifb_defined.left_margin  = (efifb_defined.xres / 8) & 0xf8;
   303		efifb_defined.hsync_len    = (efifb_defined.xres / 8) & 0xf8;
   304	
   305		efifb_defined.red.offset    = screen_info.red_pos;
   306		efifb_defined.red.length    = screen_info.red_size;
   307		efifb_defined.green.offset  = screen_info.green_pos;
   308		efifb_defined.green.length  = screen_info.green_size;
   309		efifb_defined.blue.offset   = screen_info.blue_pos;
   310		efifb_defined.blue.length   = screen_info.blue_size;
   311		efifb_defined.transp.offset = screen_info.rsvd_pos;
   312		efifb_defined.transp.length = screen_info.rsvd_size;
   313	
   314		pr_info("efifb: %s: "
   315		       "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
   316		       "Truecolor",
   317		       screen_info.rsvd_size,
   318		       screen_info.red_size,
   319		       screen_info.green_size,
   320		       screen_info.blue_size,
   321		       screen_info.rsvd_pos,
   322		       screen_info.red_pos,
   323		       screen_info.green_pos,
   324		       screen_info.blue_pos);
   325	
   326		efifb_fix.ypanstep  = 0;
   327		efifb_fix.ywrapstep = 0;
   328	
   329		info->fbops = &efifb_ops;
   330		info->var = efifb_defined;
   331		info->fix = efifb_fix;
   332		info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE;
   333	
   334		orientation = drm_get_panel_orientation_quirk(efifb_defined.xres,
   335							      efifb_defined.yres);
   336		switch (orientation) {
   337		default:
   338			info->fbcon_rotate_hint = FB_ROTATE_UR;
   339			break;
 > 340		case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP:
   341			info->fbcon_rotate_hint = FB_ROTATE_UD;
   342			break;
 > 343		case DRM_MODE_PANEL_ORIENTATION_LEFT_UP:
   344			info->fbcon_rotate_hint = FB_ROTATE_CCW;
   345			break;
 > 346		case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP:
   347			info->fbcon_rotate_hint = FB_ROTATE_CW;
   348			break;
   349		}
   350	
   351		err = sysfs_create_groups(&dev->dev.kobj, efifb_groups);
   352		if (err) {
   353			pr_err("efifb: cannot add sysfs attrs\n");
   354			goto err_unmap;
   355		}
   356		err = fb_alloc_cmap(&info->cmap, 256, 0);
   357		if (err < 0) {
   358			pr_err("efifb: cannot allocate colormap\n");
   359			goto err_groups;
   360		}
   361		err = register_framebuffer(info);
   362		if (err < 0) {
   363			pr_err("efifb: cannot register framebuffer\n");
   364			goto err_fb_dealoc;
   365		}
   366		fb_info(info, "%s frame buffer device\n", info->fix.id);
   367		return 0;
   368	
   369	err_fb_dealoc:
   370		fb_dealloc_cmap(&info->cmap);
   371	err_groups:
   372		sysfs_remove_groups(&dev->dev.kobj, efifb_groups);
   373	err_unmap:
   374		iounmap(info->screen_base);
   375	err_release_fb:
   376		framebuffer_release(info);
   377	err_release_mem:
   378		if (request_mem_succeeded)
   379			release_mem_region(efifb_fix.smem_start, size_total);
   380		return err;
   381	}
   382	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
diff mbox

Patch

diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index 2f615b7f1c9f..2566cfbdebfb 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -772,6 +772,7 @@  config FB_VESA
 config FB_EFI
 	bool "EFI-based Framebuffer Support"
 	depends on (FB = y) && !IA64 && EFI
+	select DRM_PANEL_ORIENTATION_QUIRKS
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index d1bf9c2a78a7..88697ab1005b 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -16,6 +16,8 @@ 
 #include <linux/screen_info.h>
 #include <video/vga.h>
 #include <asm/efi.h>
+#include <drm/drm_utils.h> /* For drm_get_panel_orientation_quirk */
+#include <drm/drm_mode.h>  /* For DRM_MODE_PANEL_ORIENTATION_* */
 
 static bool request_mem_succeeded = false;
 static bool nowc = false;
@@ -157,7 +159,7 @@  static u64 bar_offset;
 static int efifb_probe(struct platform_device *dev)
 {
 	struct fb_info *info;
-	int err;
+	int err, orientation;
 	unsigned int size_vmode;
 	unsigned int size_remap;
 	unsigned int size_total;
@@ -329,6 +331,23 @@  static int efifb_probe(struct platform_device *dev)
 	info->fix = efifb_fix;
 	info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE;
 
+	orientation = drm_get_panel_orientation_quirk(efifb_defined.xres,
+						      efifb_defined.yres);
+	switch (orientation) {
+	default:
+		info->fbcon_rotate_hint = FB_ROTATE_UR;
+		break;
+	case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP:
+		info->fbcon_rotate_hint = FB_ROTATE_UD;
+		break;
+	case DRM_MODE_PANEL_ORIENTATION_LEFT_UP:
+		info->fbcon_rotate_hint = FB_ROTATE_CCW;
+		break;
+	case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP:
+		info->fbcon_rotate_hint = FB_ROTATE_CW;
+		break;
+	}
+
 	err = sysfs_create_groups(&dev->dev.kobj, efifb_groups);
 	if (err) {
 		pr_err("efifb: cannot add sysfs attrs\n");