Display/Troubleshooting

= Generic debugging steps =
== Look at ~/.xsession-errors and ~/.xsession-errors.old ==
When lightDM starts your session, it redirects its output in that file. Including if that's a Wayland session!
If both files are empty, you can expect your graphical interface to have started without error. If they aren't created, lightDM may not have been started successfully. You can also try this: Display_manager#CanGraphical_issue .
== Changing the panning ==
Some devices might have a framebuffer virtual size that's twice as big as the panel resolution, this is a common double buffering method. The application renders to one side of the display while the panning is set to
the other side. You can try changing the panning with the `panning` file in the sysfs directory.
$ cat /sys/class/graphics/fb0/virtual_size
720,1280
$ cat /sys/class/graphics/fb0/pan
todo: add file contents here
$ echo 0 0 > /sys/class/graphics/fb0/pan
== LightDM no longer starts Xorg on device without GPU driver ==
Set logind-check-graphical=false in /usr/share/lightdm/lightdm.conf.d/some-file.conf.
See also: , https://github.com/canonical/lightdm/commit/77a7c6b7b8ca896b98ef43826641bdd520650bfb
= Generic troubleshooting (any manufacturer) =
== Screen does not refresh ==
Symptoms of this problem may, for instance, be that the desktop environment starts and is displayed with initial content, but is frozen at that moment and never updates. At first it may seem to be a touchscreen problem, but the lack of automatic changes (e.g. clock showing current time) can point of frozen display instead.
Check if your screen refreshes when you do the following:
$ cat /sys/class/graphics/fb0/modes > /sys/class/graphics/fb0/mode
If it does, add msm-fb-refresher to the depends= of your device-package. It will basically do the same automatically. Despite the name, the tool is not specific to MSM at all, and is usually required for MediaTek-based mobile devices.
(If the above command does not refresh your screen, you could try the msm-fb-refresher anyway.)
== Colors are wrong in some way ==
Different framebuffer modes exist where the order of colors and transparency differ. Typically you have R (red) G (green) B (blue) and A (transparency), and they might be supplied as RGBA, BGRA, ARGB or another variant. If the order is wrong you can have different issues:
* Everything is red-ish: example
* Blue and red are swapped: example
* Screen appears to show nothing (observed by switching from RGBA (which is correct) to ARGB)
To try to find a fix you need to locate the place(s) where the order is defined or set, somewhere in drivers/video. If the suggested patches in the subsections below do not work for you then have a look in the Debugging the kernel driver-section.
=== Qualcomm MSM devices ===
On Qualcomm devices the correct file should be drivers/video/msm/msm_fb.c or drivers/video/msm/mdss/mdss_fb.c. Changing the mode can (hopefully) be done in one of the following ways:
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 53112ca6..69673017 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -569,7 +569,7 @@ static int mdss_fb_probe(struct platform_device *pdev)
 	mfd->bl_level = 0;
 	mfd->bl_scale = 1024;
	mfd->bl_min_lvl = 30;
-	mfd->fb_imgType = MDP_RGBA_8888;
+	mfd->fb_imgType = MDP_RGB_888;
 
 	mfd->pdev = pdev;
 	if (pdata->next)
imgType could also be MDP_RGBA_8888 like with motorola-condor and probably some other MSM8210 devices
Alternative patch (requires CONFIG_FB_MSM_DEFAULT_DEPTH_ARGB8888=y in the kernel config):
From 0001-fix-video-argb-setting.patch
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 251a5cbb753d..dcd9262a88f4 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -1342,16 +1342,16 @@ static int msm_fb_register(struct msm_fb_data_type *mfd)
 		fix->xpanstep = 1;
 		fix->ypanstep = 1;
 		var->vmode = FB_VMODE_NONINTERLACED;
-		var->blue.offset = 0;
-		var->green.offset = 8;
-		var->red.offset = 16;
+		var->blue.offset = 24;
+		var->green.offset = 16;
+		var->red.offset = 8;
 		var->blue.length = 8;
 		var->green.length = 8;
 		var->red.length = 8;
 		var->blue.msb_right = 0;
 		var->green.msb_right = 0;
 		var->red.msb_right = 0;
-		var->transp.offset = 24;
+		var->transp.offset = 0;
 		var->transp.length = 8;
 		bpp = 4;
 		break;
@@ -1361,16 +1361,16 @@ static int msm_fb_register(struct msm_fb_data_type *mfd)
 		fix->xpanstep = 1;
 		fix->ypanstep = 1;
 		var->vmode = FB_VMODE_NONINTERLACED;
-		var->blue.offset = 8;
-		var->green.offset = 16;
-		var->red.offset = 24;
+		var->blue.offset = 16;
+		var->green.offset = 8;
+		var->red.offset = 0;
 		var->blue.length = 8;
 		var->green.length = 8;
 		var->red.length = 8;
 		var->blue.msb_right = 0;
 		var->green.msb_right = 0;
 		var->red.msb_right = 0;
-		var->transp.offset = 0;
+		var->transp.offset = 24;
 		var->transp.length = 8;
 		bpp = 4;
 		break;
@@ -2260,15 +2260,15 @@ static int msm_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 		/* Figure out if the user meant RGBA or ARGB
 		 and verify the position of the RGB components */
 
-		if (var->transp.offset == 24) {
-			if ((var->blue.offset != 0) ||
-			 (var->green.offset != 8) ||
-			 (var->red.offset != 16))
-				return -EINVAL;
-		} else if (var->transp.offset == 0) {
-			if ((var->blue.offset != 8) ||
+		if (var->transp.offset == 0) {
+			if ((var->blue.offset != 24) ||
 			 (var->green.offset != 16) ||
-			 (var->red.offset != 24))
+			 (var->red.offset != 8))
+				return -EINVAL;
+		} else if (var->transp.offset == 24) {
+			if ((var->blue.offset != 16) ||
+			 (var->green.offset != 8) ||
+			 (var->red.offset != 0))
 				return -EINVAL;
 		} else
 			return -EINVAL;
@@ -2365,7 +2365,7 @@ static int msm_fb_set_par(struct fb_info *info)
 		break;
 
 	case 32:
-		if (var->transp.offset == 24)
+		if (var->transp.offset == 0)
 			mfd->fb_imgType = MDP_ARGB_8888;
 		else
 			mfd->fb_imgType = MDP_RGBA_8888;
You might also need to add the mode, as done for linux-xiaomi-santoni:
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 075ee8a3880..b4531f66a06 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -868,7 +868,8 @@ static int mdss_fb_probe(struct platform_device *pdev)
 	mfd->bl_scale = 1024;
 	mfd->bl_min_lvl = 30;
 	mfd->ad_bl_level = 0;
-	mfd->fb_imgType = MDP_RGBA_8888;
+	// Default framebuffer format.
+	mfd->fb_imgType = MDP_BGRA_8888;
 	mfd->calib_mode_bl = 0;
 
 	if (mfd->panel.type == MIPI_VIDEO_PANEL ||
@@ -2143,6 +2144,25 @@ static int mdss_fb_register(struct msm_fb_data_type *mfd)
 		bpp = 4;
 		break;
 
+	case MDP_BGRA_8888:
+		fix->type = FB_TYPE_PACKED_PIXELS;
+		fix->xpanstep = 1;
+		fix->ypanstep = 1;
+		var->vmode = FB_VMODE_NONINTERLACED;
+		var->blue.offset = 0;
+		var->green.offset = 8;
+		var->red.offset = 16;
+		var->blue.length = 8;
+		var->green.length = 8;
+		var->red.length = 8;
+		var->blue.msb_right = 0;
+		var->green.msb_right = 0;
+		var->red.msb_right = 0;
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		bpp = 4;
+		break;
+
 	case MDP_YCRYCB_H2V1:
 		fix->type = FB_TYPE_INTERLEAVED_PLANES;
 		fix->xpanstep = 2;
Another possible workaround might be setting the default color depth to 16 bits per pixel (see this comment).
=== Exynos devices ===
On newer exynos devices you typically need to edit a file in drivers/video/fbdev/exynos/SOMETHING/decon_dsi.c.
To fix the problem where red and blue were swapped for dreamlte (exynos8895) the following patch worked:
diff --git a/drivers/video/fbdev/exynos/dpu/decon_dsi.c b/drivers/video/fbdev/exynos/dpu/decon_dsi.c
index eeaa2ba19778..3e597a145432 100644
--- a/drivers/video/fbdev/exynos/dpu/decon_dsi.c
+++ b/drivers/video/fbdev/exynos/dpu/decon_dsi.c
@@ -862,11 +862,11 @@ int decon_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 	case 24:
 		/* our 24bpp is unpacked, so 32bpp */
 		var->bits_per_pixel	= 32;
-		var->red.offset		= 16;
+		var->red.offset		= 0;
 		var->red.length		= 8;
 		var->green.offset	= 8;
 		var->green.length	= 8;
-		var->blue.offset	= 0;
+		var->blue.offset	= 16;
 		var->blue.length	= 8;
 		break;
How this patch was found is described in the Debugging the kernel driver-section.
= Qualcomm framebuffer (mdss, mdp3) =
== MSM framebuffer doesn't work ==
We found out that removing the 3D driver support makes the MSM framebuffer work. See #66.
CONFIG_MSM_KGSL=n
-> Device Drivers
 -> Graphics support
 -> MSM 3D Graphics driver
On devices using the mdss_fb driver, adding mdss-fb-init-hack to the dependencies of the device package (example) might help.
== Screen output flicker and inactivity ==
If you notice a very brief flicker upon boot, but immediately disappears and screen turns black, you might have a buggy framebuffer Qualcomm MDSS MDP3 driver.
You can try patching the source code by removing the function assigned to the mdp3_interface->off_fnc in the mdp3_ctrl.c file.
See example patch: 
== Screen output messed up ==
If the output on the screen is not aligned correctly (see picture) it's probably because you have a wrong value in /sys/class/graphics/fb0/bits_per_pixel.
You can try patching the source code by setting a different video mode (RGB/ARGB/RGBA/YCRYCB/...).
This may also help, when your X11 is segfaulting (see ).
See example patch: 06_fix_mdss_fb_rgb_mode.patch
== Screen is blank outside of Weston ==
Something like that should help, see #603:
$ echo 0 > /sys/class/graphics/fb0/blank
$ echo 1 > /sys/devices/fd900000.qcom,mdss_mdp/qcom,mdss_fb_primary.134/leds/lcd-backlight/brightness
= Debugging the kernel driver =
Generally to understand what happens in the kernel you want to print messages to dmesg with information like error codes or the value of some variable. 
The quickest way to try different kernel patches is to obtain the kernel source (git clone or download a source tar archive), add debug messages, build the kernel with envkernel.sh and then flash it. The whole build and flash procedure is described in Compiling kernels with envkernel.sh. Compiling and flashing only the kernel is faster than compiling and re-installing the kernel and rootfs everytime, which is done when you run pmbootstrap install [--android-recovery-zip].
To add debug messages you need to find interesting places where to add those though. If you have a display issue then drivers/video/ should be where to look.
== Example: error in Xorg.0.log ==
In the screen just showed noise, and /var/log/Xorg.0.log contained lots of these errors: (EE) FBDEV(0): FBIOPUTCMAP: Invalid argument. It was desired to get more information about the error (what exactly is the invalid argument?). 
greping for FBIOPUTCMAP in the kernel source showed that the error comes from drivers/video/fbmem.c, and so some suitable debug messages could be:
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 3e6371dc9038..a3ccb86baec6 100755
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1096,9 +1096,15 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
 		ret = copy_to_user(argp, &fix, sizeof(fix)) ? -EFAULT : 0;
 		break;
 	case FBIOPUTCMAP:
-		if (copy_from_user(&cmap, argp, sizeof(cmap)))
+			printk(KERN_ERR "PMOS DEBUG: calling copy_from_user...\n");
+		if (copy_from_user(&cmap, argp, sizeof(cmap))) {
+			printk(KERN_ERR "PMOS DEBUG: copy_from_user failed!\n");
 			return -EFAULT;
+		}
+		printk(KERN_ERR "PMOS DEBUG: copy_from_user ok!\n");
+		printk(KERN_ERR "PMOS DEBUG: calling fb_set_user_cmap...\n");
 		ret = fb_set_user_cmap(&cmap, info);
+		printk(KERN_ERR "PMOS DEBUG: fb_set_user_cmap returned %d\n", ret);
 		break;
 	case FBIOGETCMAP:
 		if (copy_from_user(&cmap, argp, sizeof(cmap)))
== Example: red and blue colors are swapped ==
In red and blue were switched on the display. As described in Colors are wrong in some way this most likely meant that that the framebuffer mode had to be changed somewhere. greping for BGRA, RGBA and red\.offset in drivers/video/ showed quite a lot of places to investigate. Since this was on an exynos device files in drivers/video/fbdev/exynos seemed especially interesting.
Since for many Qualcomm devices it was possible to simply change the mode from BGRA to RGBA or vice-versa, the first thing tried was this patch:
diff --git a/drivers/video/fbdev/exynos/decon_8890/decon_core.c b/drivers/video/fbdev/exynos/decon_8890/decon_core.c
index 2b65c68d8c74..388e94077847 100644
--- a/drivers/video/fbdev/exynos/decon_8890/decon_core.c
+++ b/drivers/video/fbdev/exynos/decon_8890/decon_core.c
@@ -3924,7 +3924,8 @@ static int decon_probe(struct platform_device *pdev)
 decon->vpp_used[decon->default_idma] = true;
 memset(&config, 0, sizeof(struct decon_win_config));
 config.vpp_parm.addr[0] = fbinfo->fix.smem_start;
- config.format = DECON_PIXEL_FORMAT_RGBA_8888;
+ pr_err("PMOS DEBUG: decon_8890/decon_core: setting format to BGRA\n");
+ config.format = DECON_PIXEL_FORMAT_BGRA_8888;
 config.src.w = fbinfo->var.xres;
 config.src.h = fbinfo->var.yres;
 config.src.f_w = fbinfo->var.xres;
diff --git a/drivers/video/fbdev/exynos/dpu/decon_core.c b/drivers/video/fbdev/exynos/dpu/decon_core.c
index 152c86e06d74..662c0dc1a74f 100644
--- a/drivers/video/fbdev/exynos/dpu/decon_core.c
+++ b/drivers/video/fbdev/exynos/dpu/decon_core.c
@@ -4076,7 +4076,8 @@ static int decon_initial_display(struct decon_device *decon, bool is_colormap)
 set_bit(decon->dt.dft_idma, &decon->prev_used_dpp);
 memset(&config, 0, sizeof(struct decon_win_config));
 config.dpp_parm.addr[0] = fbinfo->fix.smem_start;
- config.format = DECON_PIXEL_FORMAT_BGRA_8888;
+ pr_err("PMOS DEBUG: decon_8890/decon_dsi: setting format to RGBA\n");
+ config.format = DECON_PIXEL_FORMAT_RGBA_8888;
 config.src.w = fbinfo->var.xres;
 config.src.h = fbinfo->var.yres;
 config.src.f_w = fbinfo->var.xres;
diff --git a/drivers/video/fbdev/exynos/dual_dpu/decon_core.c b/drivers/video/fbdev/exynos/dual_dpu/decon_core.c
index d02af9c7e30a..1b9aa3ee57b1 100644
--- a/drivers/video/fbdev/exynos/dual_dpu/decon_core.c
+++ b/drivers/video/fbdev/exynos/dual_dpu/decon_core.c
@@ -3735,7 +3735,8 @@ static int decon_initial_display(struct decon_device *decon, bool is_colormap)
 set_bit(decon->dt.dft_idma, &decon->prev_used_dpp);
 memset(&config, 0, sizeof(struct decon_win_config));
 config.dpp_parm.addr[0] = fbinfo->fix.smem_start;
- config.format = DECON_PIXEL_FORMAT_BGRA_8888;
+ pr_err("PMOS DEBUG: dual_dpu/decon_core: setting format to RGBA\n");
+ config.format = DECON_PIXEL_FORMAT_RGBA_8888;
 config.src.w = fbinfo->var.xres;
 config.src.h = fbinfo->var.yres;
 config.src.f_w = fbinfo->var.xres;
After compiling, flashing and booting the kernel, the colors were still wrong, and none of the messages showed up in dmesg, so this not the right places to set the mode. Next focus was therefore on the grep results of red\.offset in drivers/video/fbdev/exynos/. red.offset was being set in drivers/video/fbdev/exynos/decon_8890/decon_dsi.c, drivers/video/fbdev/exynos/dpu/decon_dsi.c and drivers/video/fbdev/exynos/dual_dpu/decon_dsi.c so this patch was added:
diff --git a/drivers/video/fbdev/exynos/decon_8890/decon_dsi.c b/drivers/video/fbdev/exynos/decon_8890/decon_dsi.c
index 8703b56108ac..101d1460ee98 100644
--- a/drivers/video/fbdev/exynos/decon_8890/decon_dsi.c
+++ b/drivers/video/fbdev/exynos/decon_8890/decon_dsi.c
@@ -187,6 +187,8 @@ int decon_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 var->transp.offset = 0;
 var->transp.length = 0;
 
+ pr_err("PMOS_DEBUG: decon_8890/decon_dsi: bits_per_pixel %d\n", var->bits_per_pixel);
+
 switch (var->bits_per_pixel) {
 case 1:
 case 2:
diff --git a/drivers/video/fbdev/exynos/dpu/decon_dsi.c b/drivers/video/fbdev/exynos/dpu/decon_dsi.c
index eeaa2ba19778..70a645fd8f4b 100644
--- a/drivers/video/fbdev/exynos/dpu/decon_dsi.c
+++ b/drivers/video/fbdev/exynos/dpu/decon_dsi.c
@@ -812,6 +812,8 @@ int decon_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 var->transp.offset = 0;
 var->transp.length = 0;
 
+ pr_err("PMOS_DEBUG: dpu/decon_dsi: bits_per_pixel %d\n", var->bits_per_pixel);
+
 switch (var->bits_per_pixel) {
 case 1:
 case 2:
diff --git a/drivers/video/fbdev/exynos/dual_dpu/decon_dsi.c b/drivers/video/fbdev/exynos/dual_dpu/decon_dsi.c
index d01b913bc8e0..30d7391b1bfa 100644
--- a/drivers/video/fbdev/exynos/dual_dpu/decon_dsi.c
+++ b/drivers/video/fbdev/exynos/dual_dpu/decon_dsi.c
@@ -815,6 +815,8 @@ int decon_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 var->transp.offset = 0;
 var->transp.length = 0;
 
+ pr_err("PMOS_DEBUG: dual_dpu/decon_dsi: bits_per_pixel %d\n", var->bits_per_pixel);
+
 switch (var->bits_per_pixel) {
 case 1:
 case 2:
After compiling, flashing and booting the kernel only the message from dpu/decon_dsi.c appeared in dmesg, and bits_per_pixel was 32.
In the same file we have
	switch (var->bits_per_pixel) {
 [...]
	case 32:
	case 28:
	case 25:
		var->transp.length	= var->bits_per_pixel - 24;
		var->transp.offset	= 24;
		/* drop through */
	case 24:
		/* our 24bpp is unpacked, so 32bpp */
		var->bits_per_pixel	= 32;
		var->red.offset		= 16;
		var->red.length		= 8;
		var->green.offset	= 8;
		var->green.length	= 8;
		var->blue.offset	= 0;
		var->blue.length	= 8;
		break;
Each pixel is 32 bit, and they are unpacked in the order BGRA, since blue.offset=0, green.offset=8, red.offset=16 and transp.offset=24. Since we want to swap blue<->red we change those offsets:
diff --git a/drivers/video/fbdev/exynos/dpu/decon_dsi.c b/drivers/video/fbdev/exynos/dpu/decon_dsi.c
index eeaa2ba19778..3e597a145432 100644
--- a/drivers/video/fbdev/exynos/dpu/decon_dsi.c
+++ b/drivers/video/fbdev/exynos/dpu/decon_dsi.c
@@ -862,11 +862,11 @@ int decon_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 	case 24:
 		/* our 24bpp is unpacked, so 32bpp */
 		var->bits_per_pixel	= 32;
-		var->red.offset		= 16;
+		var->red.offset		= 0;
 		var->red.length		= 8;
 		var->green.offset	= 8;
 		var->green.length	= 8;
-		var->blue.offset	= 0;
+		var->blue.offset	= 16;
 		var->blue.length	= 8;
 		break;
And after compiling, flashing and booting the kernel the problem is solved!
= See also =
* : framebuffer: red and blue are swapped on devices using MSM8974
* : alternative patch to fix refresh rate for kernel 3.4.113 android_kernel_oppo_msm8974 and similar
* : red and blue are swapped on dreamlte (exynos8895)
* Kernel documentation on the framebuffer api
* Red screen issue on HTC-One XL
display