Skip to contentSkip to conversation

sunxi: display: Add overscan correction

PATCH New Hans de Goede 3 participants 12 messages Aug 5, 2015 – Aug 12, 2015

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover sunxi: display: Add overscan correction

Hi Anatolij, Ian,

This series sits on top of the composite video out series Ian has just reviewed.

The first 2 patches are preparation patches adding support for stride != width to the cfbconsole code. Anatolij, can you either merge these 2 through your tree, or give us your ack for merging these through the sunxi tree ?

Thanks & Regards,

Hans

#1 lore raw

PATCH 1/3 cfbconsole: Remove width argument from the logo functions

The passed in width is always VIDEO_COLS. This is a preparation patch for adding stride != width support to the cfbconsole code.

---
 drivers/video/cfb_console.c | 21 ++++++++-------------
 1 file changed, 8 insertions(+), 13 deletions(-)
drivers/video/cfb_console.c +8 -13
index 7f2ddc1..d122ef7 100644
@@ -1826,20 +1826,16 @@ int video_display_bitmap(ulong bmp_image, int x, int y)
 static int video_logo_xpos;
 static int video_logo_ypos;
 
-static void plot_logo_or_black(void *screen, int width, int x, int y,	\
-			int black);
+static void plot_logo_or_black(void *screen, int x, int y, int black);
 
-static void logo_plot(void *screen, int width, int x, int y)
+static void logo_plot(void *screen, int x, int y)
 {
-	plot_logo_or_black(screen, width, x, y, 0);
+	plot_logo_or_black(screen, x, y, 0);
 }
 
 static void logo_black(void)
 {
-	plot_logo_or_black(video_fb_address, \
-			VIDEO_COLS, \
-			video_logo_xpos, \
-			video_logo_ypos, \
+	plot_logo_or_black(video_fb_address, video_logo_xpos, video_logo_ypos,
 			1);
 }
 
@@ -1858,11 +1854,11 @@ U_BOOT_CMD(
 	   " "
 	   );
 
-static void plot_logo_or_black(void *screen, int width, int x, int y, int black)
+static void plot_logo_or_black(void *screen, int x, int y, int black)
 {
 
 	int xcount, i;
-	int skip = (width - VIDEO_LOGO_WIDTH) * VIDEO_PIXEL_SIZE;
+	int skip = (VIDEO_COLS - VIDEO_LOGO_WIDTH) * VIDEO_PIXEL_SIZE;
 	int ycount = video_logo_height;
 	unsigned char r, g, b, *logo_red, *logo_blue, *logo_green;
 	unsigned char *source;
@@ -1880,7 +1876,7 @@ static void plot_logo_or_black(void *screen, int width, int x, int y, int black)
 		y = max(0, (int)(VIDEO_VISIBLE_ROWS - VIDEO_LOGO_HEIGHT + y + 1));
 #endif /* CONFIG_SPLASH_SCREEN_ALIGN */
 
-	dest = (unsigned char *)screen + (y * width  + x) * VIDEO_PIXEL_SIZE;
+	dest = (unsigned char *)screen + (y * VIDEO_COLS  + x) * VIDEO_PIXEL_SIZE;
 
 #ifdef CONFIG_VIDEO_BMP_LOGO
 	source = bmp_logo_bitmap;
@@ -2009,8 +2005,7 @@ static void *video_logo(void)
 	}
 #endif /* CONFIG_SPLASH_SCREEN */
 
-	logo_plot(video_fb_address, VIDEO_COLS,
-		  video_logo_xpos, video_logo_ypos);
+	logo_plot(video_fb_address, video_logo_xpos, video_logo_ypos);
 
 #ifdef CONFIG_SPLASH_SCREEN_ALIGN
 	/*
Signature · 1 line
2.4.3
#3 lore raw

PATCH 2/3 cfbconsole: Add support for stride != width

In reply to Hans de Goede

cfbconsole currently assumes that the width and stride of the framebuffer are the same, in most places where stride matters it uses a VIDEO_LINE_LEN helper macro.

This commit changes the few places not using VIDEO_LINE_LEN to also use VIDEO_LINE_LEN, and protects the default VIDEO_LINE_LEN with a #ifndef guard, allowing the boards config.h to override and, and thus support cases where stride != width.

---
 drivers/video/cfb_console.c | 72 +++++++++++++++++++++++----------------------
 1 file changed, 37 insertions(+), 35 deletions(-)
drivers/video/cfb_console.c +37 -35
index d122ef7..30e0317 100644
@@ -283,9 +283,10 @@ void console_cursor(int state);
 
 #define VIDEO_COLS		VIDEO_VISIBLE_COLS
 #define VIDEO_ROWS		VIDEO_VISIBLE_ROWS
-#define VIDEO_SIZE		(VIDEO_ROWS*VIDEO_COLS*VIDEO_PIXEL_SIZE)
-#define VIDEO_PIX_BLOCKS	(VIDEO_SIZE >> 2)
-#define VIDEO_LINE_LEN		(VIDEO_COLS*VIDEO_PIXEL_SIZE)
+#ifndef VIDEO_LINE_LEN
+#define VIDEO_LINE_LEN		(VIDEO_COLS * VIDEO_PIXEL_SIZE)
+#endif
+#define VIDEO_SIZE		(VIDEO_ROWS * VIDEO_LINE_LEN)
 #define VIDEO_BURST_LEN		(VIDEO_COLS/8)
 
 #ifdef	CONFIG_VIDEO_LOGO
@@ -1306,7 +1307,7 @@ static int display_rle8_bitmap(struct bmp_image *img, int xoff, int yoff,
 	struct palette p[256];
 	struct bmp_color_table_entry cte;
 	int green_shift, red_off;
-	int limit = VIDEO_COLS * VIDEO_ROWS;
+	int limit = (VIDEO_LINE_LEN / VIDEO_PIXEL_SIZE) * VIDEO_ROWS;
 	int pixels = 0;
 
 	x = 0;
@@ -1314,7 +1315,8 @@ static int display_rle8_bitmap(struct bmp_image *img, int xoff, int yoff,
 	ncolors = __le32_to_cpu(img->header.colors_used);
 	bpp = VIDEO_PIXEL_SIZE;
 	fbp = (unsigned char *) ((unsigned int) video_fb_address +
-				 (((y + yoff) * VIDEO_COLS) + xoff) * bpp);
+				 (y + yoff) * VIDEO_LINE_LEN +
+				 xoff * bpp);
 
 	bm = (uchar *) img + __le32_to_cpu(img->header.data_offset);
 
@@ -1368,8 +1370,8 @@ static int display_rle8_bitmap(struct bmp_image *img, int xoff, int yoff,
 				y--;
 				fbp = (unsigned char *)
 					((unsigned int) video_fb_address +
-					 (((y + yoff) * VIDEO_COLS) +
-					  xoff) * bpp);
+					 (y + yoff) * VIDEO_LINE_LEN +
+					 xoff * bpp);
 				continue;
 			case 1:
 				/* end of bitmap data marker */
@@ -1381,8 +1383,8 @@ static int display_rle8_bitmap(struct bmp_image *img, int xoff, int yoff,
 				y -= bm[3];
 				fbp = (unsigned char *)
 					((unsigned int) video_fb_address +
-					 (((y + yoff) * VIDEO_COLS) +
-					  x + xoff) * bpp);
+					 (y + yoff) * VIDEO_LINE_LEN +
+					 xoff * bpp);
 				bm += 4;
 				break;
 			default:
@@ -1561,7 +1563,7 @@ int video_display_bitmap(ulong bmp_image, int x, int y)
 
 	bmap = (uchar *) bmp + le32_to_cpu(bmp->header.data_offset);
 	fb = (uchar *) (video_fb_address +
-			((y + height - 1) * VIDEO_COLS * VIDEO_PIXEL_SIZE) +
+			((y + height - 1) * VIDEO_LINE_LEN) +
 			x * VIDEO_PIXEL_SIZE);
 
 #ifdef CONFIG_VIDEO_BMP_RLE8
@@ -1597,7 +1599,7 @@ int video_display_bitmap(ulong bmp_image, int x, int y)
 							   cte.blue);
 				}
 				bmap += padded_line;
-				fb -= (VIDEO_VISIBLE_COLS + width) *
+				fb -= VIDEO_LINE_LEN + width *
 					VIDEO_PIXEL_SIZE;
 			}
 			break;
@@ -1628,8 +1630,8 @@ int video_display_bitmap(ulong bmp_image, int x, int y)
 					*fb++ = *bmap++;
 				}
 				bmap += padded_line;
-				fb -= (VIDEO_VISIBLE_COLS + width) *
-							VIDEO_PIXEL_SIZE;
+				fb -= VIDEO_LINE_LEN + width *
+					VIDEO_PIXEL_SIZE;
 			}
 			break;
 		case GDF__8BIT_332RGB:
@@ -1642,8 +1644,8 @@ int video_display_bitmap(ulong bmp_image, int x, int y)
 							 cte.blue);
 				}
 				bmap += padded_line;
-				fb -= (VIDEO_VISIBLE_COLS + width) *
-							VIDEO_PIXEL_SIZE;
+				fb -= VIDEO_LINE_LEN + width *
+					VIDEO_PIXEL_SIZE;
 			}
 			break;
 		case GDF_15BIT_555RGB:
@@ -1666,8 +1668,8 @@ int video_display_bitmap(ulong bmp_image, int x, int y)
 #endif
 				}
 				bmap += padded_line;
-				fb -= (VIDEO_VISIBLE_COLS + width) *
-							VIDEO_PIXEL_SIZE;
+				fb -= VIDEO_LINE_LEN + width *
+					VIDEO_PIXEL_SIZE;
 			}
 			break;
 		case GDF_16BIT_565RGB:
@@ -1680,8 +1682,8 @@ int video_display_bitmap(ulong bmp_image, int x, int y)
 							  cte.blue);
 				}
 				bmap += padded_line;
-				fb -= (VIDEO_VISIBLE_COLS + width) *
-							VIDEO_PIXEL_SIZE;
+				fb -= VIDEO_LINE_LEN + width *
+					VIDEO_PIXEL_SIZE;
 			}
 			break;
 		case GDF_32BIT_X888RGB:
@@ -1694,8 +1696,8 @@ int video_display_bitmap(ulong bmp_image, int x, int y)
 							   cte.blue);
 				}
 				bmap += padded_line;
-				fb -= (VIDEO_VISIBLE_COLS + width) *
-							VIDEO_PIXEL_SIZE;
+				fb -= VIDEO_LINE_LEN + width *
+					VIDEO_PIXEL_SIZE;
 			}
 			break;
 		case GDF_24BIT_888RGB:
@@ -1708,8 +1710,8 @@ int video_display_bitmap(ulong bmp_image, int x, int y)
 							  cte.blue);
 				}
 				bmap += padded_line;
-				fb -= (VIDEO_VISIBLE_COLS + width) *
-							VIDEO_PIXEL_SIZE;
+				fb -= VIDEO_LINE_LEN + width *
+					VIDEO_PIXEL_SIZE;
 			}
 			break;
 		}
@@ -1728,8 +1730,8 @@ int video_display_bitmap(ulong bmp_image, int x, int y)
 					bmap += 3;
 				}
 				bmap += padded_line;
-				fb -= (VIDEO_VISIBLE_COLS + width) *
-							VIDEO_PIXEL_SIZE;
+				fb -= VIDEO_LINE_LEN + width *
+					VIDEO_PIXEL_SIZE;
 			}
 			break;
 		case GDF_15BIT_555RGB:
@@ -1751,8 +1753,8 @@ int video_display_bitmap(ulong bmp_image, int x, int y)
 					bmap += 3;
 				}
 				bmap += padded_line;
-				fb -= (VIDEO_VISIBLE_COLS + width) *
-							VIDEO_PIXEL_SIZE;
+				fb -= VIDEO_LINE_LEN + width *
+					VIDEO_PIXEL_SIZE;
 			}
 			break;
 		case GDF_16BIT_565RGB:
@@ -1765,8 +1767,8 @@ int video_display_bitmap(ulong bmp_image, int x, int y)
 					bmap += 3;
 				}
 				bmap += padded_line;
-				fb -= (VIDEO_VISIBLE_COLS + width) *
-							VIDEO_PIXEL_SIZE;
+				fb -= VIDEO_LINE_LEN + width *
+					VIDEO_PIXEL_SIZE;
 			}
 			break;
 		case GDF_32BIT_X888RGB:
@@ -1779,8 +1781,8 @@ int video_display_bitmap(ulong bmp_image, int x, int y)
 					bmap += 3;
 				}
 				bmap += padded_line;
-				fb -= (VIDEO_VISIBLE_COLS + width) *
-							VIDEO_PIXEL_SIZE;
+				fb -= VIDEO_LINE_LEN + width *
+					VIDEO_PIXEL_SIZE;
 			}
 			break;
 		case GDF_24BIT_888RGB:
@@ -1793,8 +1795,8 @@ int video_display_bitmap(ulong bmp_image, int x, int y)
 					bmap += 3;
 				}
 				bmap += padded_line;
-				fb -= (VIDEO_VISIBLE_COLS + width) *
-							VIDEO_PIXEL_SIZE;
+				fb -= VIDEO_LINE_LEN + width *
+					VIDEO_PIXEL_SIZE;
 			}
 			break;
 		default:
@@ -1858,7 +1860,7 @@ static void plot_logo_or_black(void *screen, int x, int y, int black)
 {
 
 	int xcount, i;
-	int skip = (VIDEO_COLS - VIDEO_LOGO_WIDTH) * VIDEO_PIXEL_SIZE;
+	int skip = VIDEO_LINE_LEN - VIDEO_LOGO_WIDTH * VIDEO_PIXEL_SIZE;
 	int ycount = video_logo_height;
 	unsigned char r, g, b, *logo_red, *logo_blue, *logo_green;
 	unsigned char *source;
@@ -1876,7 +1878,7 @@ static void plot_logo_or_black(void *screen, int x, int y, int black)
 		y = max(0, (int)(VIDEO_VISIBLE_ROWS - VIDEO_LOGO_HEIGHT + y + 1));
 #endif /* CONFIG_SPLASH_SCREEN_ALIGN */
 
-	dest = (unsigned char *)screen + (y * VIDEO_COLS  + x) * VIDEO_PIXEL_SIZE;
+	dest = (unsigned char *)screen + y * VIDEO_LINE_LEN + x * VIDEO_PIXEL_SIZE;
 
 #ifdef CONFIG_VIDEO_BMP_LOGO
 	source = bmp_logo_bitmap;
Signature · 1 line
2.4.3
#4 lore raw

PATCH 2/3 cfbconsole: Add support for stride != width

Quoted 10 lines · On Wed, 5 Aug 2015 17:17:30 +0200 Hans de Goede <[email protected]> wrote:

cfbconsole currently assumes that the width and stride of the framebuffer are the same, in most places where stride matters it uses a VIDEO_LINE_LEN helper macro.

This commit changes the few places not using VIDEO_LINE_LEN to also use VIDEO_LINE_LEN, and protects the default VIDEO_LINE_LEN with a #ifndef guard, allowing the boards config.h to override and, and thus support cases where stride != width.

#5 lore raw

PATCH 3/3 sunxi: display: Add overscan correction

In reply to Hans de Goede

Add support for making the visual area of the framebuffer smaller and drawing a black border around it. This is intended for use with overscanning monitors (esp. with composite video out), to avoid part of the picture being invisible.

---
 doc/README.video               |  5 +++++
 drivers/video/sunxi_display.c  | 48 +++++++++++++++++++++++++++++++++---------
 include/configs/sunxi-common.h |  1 +
 3 files changed, 44 insertions(+), 10 deletions(-)
doc/README.video +5 -0
index 4f7a4b5..62ac17b 100644
@@ -68,6 +68,11 @@ The sunxi u-boot driver supports the following video-mode options:
     overrides the xres, yres and refresh from the video-mode env. variable.
  Defaults to edid=1.
 
+- overscan_x/overscan_y=<int> - Set x/y overscan value
+ This configures a black border on the left and right resp. top and bottom
+ to deal with overscanning displays. Defaults to overscan_x=32 and
+ overscan_y=20 for composite monitors, 0 for other monitors.
+
 For example to always use the hdmi connector, even if no cable is inserted,
 using edid info when available and otherwise initalizing it at 1024x768 at 60Hz,
 use: "setenv video-mode sunxi:1024x768-24 at 60,monitor=dvi,hpd=0,edid=1".
drivers/video/sunxi_display.c +38 -10

108 lines not on this page · raw message

include/configs/sunxi-common.h +1 -0
index a2cbcf5..83b6556 100644
@@ -302,6 +302,7 @@ extern int soft_i2c_gpio_scl;
 #define CONFIG_VIDEO_LOGO
 #define CONFIG_VIDEO_STD_TIMINGS
 #define CONFIG_I2C_EDID
+#define VIDEO_LINE_LEN (pGD->plnSizeX)
 
 /* allow both serial and cfb console. */
 #define CONFIG_CONSOLE_MUX
Signature · 1 line
2.4.3
#6 lore raw

PATCH 3/3 sunxi: display: Add overscan correction

Quoted 7 lines · Hans de Goede
Quoted 2 lines
	> sunxi_display.fb_size =
	> 	> (mode->xres * mode->yres * 4 + 0xfff) & ~0xfff;

+> > overscan_offset = (overscan_y * mode->xres + overscan_x) * 4;
+> > /* We want to keep the fb_base for simplefb page aligned, where as
+> > * the sunxi dma engines will happily accept an unaligned address. */
+> > if (overscan_offset)
+> > > sunxi_display.fb_size += 0x1000;

Why plus 4K regardless of the magnitude of overscan_offset? What if it was 0x1004?

Also, what's the link between fb_base's alignment and fb_size which is implied by the comment?

Quoted 13 lines
Quoted 3 lines
	> gd->fb_base = gd->bd->bi_dram[0].start +
	> 	>       gd->bd->bi_dram[0].size - sunxi_display.fb_size;
	> sunxi_engines_init();

-> > sunxi_mode_set(mode, gd->fb_base - CONFIG_SYS_SDRAM_BASE);
+
+> > fb_dma_addr = gd->fb_base - CONFIG_SYS_SDRAM_BASE;
+> > sunxi_display.fb_addr = gd->fb_base;
+> > if (overscan_offset) {
+> > > fb_dma_addr += 0x1000 - (overscan_offset & 0xfff);
+> > > sunxi_display.fb_addr += (overscan_offset + 0xfff) & ~0xfff;
+> > > memset((void *)gd->fb_base, 0, sunxi_display.fb_size);
+> > > flush_cache(gd->fb_base, sunxi_display.fb_size);
+> > }

Hrm, I think this starts to answer, but I'm still not sure I follow, sorry.

drivers/video/sunxi_display.c void *video_hw_init(void)

Quoted 5 lines
drivers/video/sunxi_display.c +1 -0
+	sunxi_mode_set(mode, fb_dma_addr);
 
 	/*
 > 	>  * These are the only members of this structure that are used. All the
 > 	>  * others are driver specific. There is nothing to decribe pitch or

Pre-existing typo "describe".

#7 lore raw

PATCH 3/3 sunxi: display: Add overscan correction

Hi,

Quoted 11 lines · Ian Campbell
Quoted 7 lines · Hans de Goede
Quoted 2 lines
	> sunxi_display.fb_size =
	> 	> (mode->xres * mode->yres * 4 + 0xfff) & ~0xfff;

+> > overscan_offset = (overscan_y * mode->xres + overscan_x) * 4;
+> > /* We want to keep the fb_base for simplefb page aligned, where as
+> > * the sunxi dma engines will happily accept an unaligned address. */
+> > if (overscan_offset)
+> > > sunxi_display.fb_size += 0x1000;

Why plus 4K regardless of the magnitude of overscan_offset? What if it was 0x1004?

If overscan offset is 0x1004 then we make the simplefb start point to fb_base + 0x2000:

sunxi_display.fb_addr = gd->fb_base sunxi_display.fb_addr += (overscan_offset + 0xfff) & ~0xfff

And make the dma engine start at fb_base + 0xffc:

fb_dma_addr = gd->fb_base
fb_dma_addr += 0x1000 - (overscan_offset & 0xfff)

Notice how we make the dma_engine start at less then 0x1000 offset of fb_base, so making fb_size 0x1000 larger is enough.

Basically to page-align the start of the simplefb / sunxi_display.fb_addr we only need a single page, the rest we can get by offsetting sunxi_display.fb_addr from fb_base by a multiple of the page size.

Quoted 2 lines

Also, what's the link between fb_base's alignment and fb_size which is implied by the comment?

To align we need a page extra size as the dma-engine may start at an offset of up-to a page-size from gd->fb_base and the dma-engine will dma a full framebuffer size, including the black borders.

Quoted 15 lines
Quoted 4 lines
Quoted 4 lines
	> gd->fb_base = gd->bd->bi_dram[0].start +
	> 	>       gd->bd->bi_dram[0].size - sunxi_display.fb_size;
	> sunxi_engines_init();
Quoted 10 lines

-> > sunxi_mode_set(mode, gd->fb_base - CONFIG_SYS_SDRAM_BASE);
+
+> > fb_dma_addr = gd->fb_base - CONFIG_SYS_SDRAM_BASE;
+> > sunxi_display.fb_addr = gd->fb_base;
+> > if (overscan_offset) {
+> > > fb_dma_addr += 0x1000 - (overscan_offset & 0xfff);
+> > > sunxi_display.fb_addr += (overscan_offset + 0xfff) & ~0xfff;
+> > > memset((void *)gd->fb_base, 0, sunxi_display.fb_size);
+> > > flush_cache(gd->fb_base, sunxi_display.fb_size);
+> > }

Quoted 1 line

Hrm, I think this starts to answer, but I'm still not sure I follow, sorry.

Correct this is the answer, sorry for the tricky maths, this is the best solution without wasting a ton of memory with large overscans.

I hope the above explanation helps, if not keep asking.

Quoted 8 lines

drivers/video/sunxi_display.c void *video_hw_init(void)

Quoted 5 lines
drivers/video/sunxi_display.c +1 -0
+	sunxi_mode_set(mode, fb_dma_addr);
 
  	/*
  > 	>  * These are the only members of this structure that are used. All the
  > 	>  * others are driver specific. There is nothing to decribe pitch or

Pre-existing typo "describe".

Will fix,

Regards,

Hans

#8 lore raw

PATCH 3/3 sunxi: display: Add overscan correction

Quoted 1 line · Hans de Goede

[...big snip...]

Quoted 1 line

I hope the above explanation helps, if not keep asking.

It very much did, thanks.

#9 lore raw

PATCH 3/3 sunxi: display: Add overscan correction

In reply to Ian Campbell

Hi,

On 08/12/2015 12:45 PM, Ian Campbell wrote:

<snip>

Quoted 8 lines

drivers/video/sunxi_display.c void *video_hw_init(void)

Quoted 5 lines
drivers/video/sunxi_display.c +1 -0
+	sunxi_mode_set(mode, fb_dma_addr);
 
  	/*
  > 	>  * These are the only members of this structure that are used. All the
  > 	>  * others are driver specific. There is nothing to decribe pitch or

Pre-existing typo "describe".

Actually part of the overscan patch series is adding support for pitch != width to the cfbconsole code, so that comment is no longer accurate, I've squashed a fix for the comment into the patch adding overscan support to drivers/video/sunxi_display.c

Regards,

Hans

#10 lore raw

PATCH 3/3 sunxi: display: Add overscan correction

In reply to Hans de Goede
Quoted 6 lines · On Wed, 5 Aug 2015 17:17:31 +0200 Hans de Goede <[email protected]> wrote:

Add support for making the visual area of the framebuffer smaller and drawing a black border around it. This is intended for use with overscanning monitors (esp. with composite video out), to avoid part of the picture being invisible.

#11 lore raw

cover sunxi: display: Add overscan correction

In reply to Hans de Goede

Hi Hans,

On Wed, 5 Aug 2015 17:17:28 +0200
Hans de Goede <[email protected]> wrote:
...

Quoted 4 lines

The first 2 patches are preparation patches adding support for stride != width to the cfbconsole code. Anatolij, can you either merge these 2 through your tree, or give us your ack for merging these through the sunxi tree ?

I've replied with acks, please merge through the sunxi tree.

Thanks,

Anatolij