diff mbox

YUV rotation support for DSS2 - 2.6.29 [WAS Re: Hello Tomi Valkeinen, I have some questions about dss2 driver.]

Message ID 792f5f410904071200h1dae9024v1f2d9cbd4f1bbebc@mail.gmail.com (mailing list archive)
State Not Applicable, archived
Delegated to: Tomi Valkeinen
Headers show

Commit Message

Tim Yamin April 7, 2009, 7 p.m. UTC
Hi Hardik / Tomi,

> [Shah, Hardik] I have also patched the DSS to support the DSS YUV rotation.  Here the rotation type is passed to know the type of rotation required by driver.  I have also modified the FBDEV driver to use this patch.  Please find the both patches.  I have tested it on the old master of tomi. Commit id is 4261fafc4fdc0730b3d4dd83c036d8be09ec8575.  I am planning to rebase it on the latest master soon. I have tested the FBDEV driver with different rotation and resolution settings.

I've merged my changes with your patches and rebased against master,
please find the new patch attached.

> [Shah, Hardik] In past I saw setting the FIFO size eliminates this problem.  I have some FIFO setting can you please try this out and let me know the result.
> FIFO_HIGH_THRES = 0x3FC and GFX_FIFO_LOW_THRES = 0x3BC.  This I tried in on OMAP3.

Tried this (see attached patch) but does not help -- still getting
these errors as soon as I try to play a video:

omapdss DISPC error: VID1_FIFO_UNDERFLOW, disabling VID1
omapdss DISPC error: SYNC_LOST, disabling LCD

The FIFOs are configured as follows:

omapdss DISPC: fifo(0) size 1024, low/high old 3008/3071, new 956/1020
omapdss DISPC: fifo(1) size 1024, low/high old 956/1020, new 956/1020

Cheers,

Tim

Comments

Hardik Shah April 13, 2009, 12:05 p.m. UTC | #1
Hi,


> -----Original Message-----
> From: plasmaroo@gmail.com [mailto:plasmaroo@gmail.com] On Behalf Of Tim Yamin
> Sent: Wednesday, April 08, 2009 12:31 AM
> To: Shah, Hardik
> Cc: gregoire@gentil.com; tomi.valkeinen@nokia.com; linux-omap@vger.kernel.org;
> beagleboard@googlegroups.com
> Subject: Re: YUV rotation support for DSS2 - 2.6.29 [WAS Re: Hello Tomi
> Valkeinen, I have some questions about dss2 driver.]
> 
> Hi Hardik / Tomi,
> 
> > [Shah, Hardik] I have also patched the DSS to support the DSS YUV rotation.
>  Here the rotation type is passed to know the type of rotation required by
> driver.  I have also modified the FBDEV driver to use this patch.  Please find
> the both patches.  I have tested it on the old master of tomi. Commit id is
> 4261fafc4fdc0730b3d4dd83c036d8be09ec8575.  I am planning to rebase it on the
> latest master soon. I have tested the FBDEV driver with different rotation and
> resolution settings.

Hi Tim,
I  have done few changes to your patch.  

-	else if (bytespp == 2)
+		width >>= 1;
Will not work for 32 bit formats like ARGB or RGB24u.

Secondly I have fixed lot many check patch warnings/errors in your patch.  So please do that before providing patches.

Third I have implemented VRFB mirroring also. 

I have tested YUV, UYVY, RGB24u, RGB16, and ARGB on V4L2 driver with rotation and mirroring with different resolutions on LCD and its working fine.


Tim,

Will you please test the YUV rotation with frame buffer driver with the attached patch and let us know the result.  I have tested RGB rotation and its working fine.



Hi Tomi,
If YUV rotation with frame buffer passes can you please review the patch and merge it to your latest.

Regards,
Hardik
> 
> I've merged my changes with your patches and rebased against master,
> please find the new patch attached.
[Shah, Hardik] Hi Tim,
I have modified your DSS2 rotation patch to make it more generic to support YUV as well as ARGB32 and RGB24u formats.
> 
> > [Shah, Hardik] In past I saw setting the FIFO size eliminates this problem.
>  I have some FIFO setting can you please try this out and let me know the
> result.
> > FIFO_HIGH_THRES = 0x3FC and GFX_FIFO_LOW_THRES = 0x3BC.  This I tried in on
> OMAP3.
> 
> Tried this (see attached patch) but does not help -- still getting
> these errors as soon as I try to play a video:
> 
> omapdss DISPC error: VID1_FIFO_UNDERFLOW, disabling VID1
> omapdss DISPC error: SYNC_LOST, disabling LCD
> 
> The FIFOs are configured as follows:
> 
> omapdss DISPC: fifo(0) size 1024, low/high old 3008/3071, new 956/1020
> omapdss DISPC: fifo(1) size 1024, low/high old 956/1020, new 956/1020
> 
> Cheers,
> 
> Tim
diff mbox

Patch

From 826edf9b2b9af7b9bc32f4363724af174911175c Mon Sep 17 00:00:00 2001
From: Tim Yamin <plasm@roo.me.uk>
Date: Tue, 7 Apr 2009 11:52:35 -0700
Subject: [PATCH] DSS2: Add YUV VRFB rotation support

This is a rebased version of Hardik Shah's patch with a few additional
tweaks from me.

Signed-off-by: Tim Yamin <plasm@roo.me.uk>
---
 arch/arm/plat-omap/include/mach/display.h |    6 ++
 arch/arm/plat-omap/vrfb.c                 |    4 +-
 drivers/video/omap2/dss/dispc.c           |   87 ++++++++++++++++++++++++++--
 drivers/video/omap2/dss/dss.h             |    1 +
 drivers/video/omap2/dss/manager.c         |    1 +
 drivers/video/omap2/omapfb/omapfb-main.c  |   66 +++++++++++-----------
 drivers/video/omap2/omapfb/omapfb.h       |    7 +--
 7 files changed, 126 insertions(+), 46 deletions(-)

diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h
index 6b702c7..b0a6272 100644
--- a/arch/arm/plat-omap/include/mach/display.h
+++ b/arch/arm/plat-omap/include/mach/display.h
@@ -341,6 +341,11 @@  enum omap_dss_overlay_managers {
 
 struct omap_overlay_manager;
 
+enum omap_dss_rotation_type {
+	OMAP_DSS_ROT_DMA = 0,
+	OMAP_DSS_ROT_VRFB = 1,
+};
+
 struct omap_overlay_info {
 	bool enabled;
 
@@ -351,6 +356,7 @@  struct omap_overlay_info {
 	u16 height;
 	enum omap_color_mode color_mode;
 	u8 rotation;
+	enum omap_dss_rotation_type rotation_type;
 	bool mirror;
 
 	u16 pos_x;
diff --git a/arch/arm/plat-omap/vrfb.c b/arch/arm/plat-omap/vrfb.c
index 7e0f8fc..77aa9a7 100644
--- a/arch/arm/plat-omap/vrfb.c
+++ b/arch/arm/plat-omap/vrfb.c
@@ -61,8 +61,10 @@  void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
 			width, height, bytespp);
 
 	if (bytespp == 4)
+	{
 		pixel_size_exp = 2;
-	else if (bytespp == 2)
+		width >>= 1;
+	} else if (bytespp == 2)
 		pixel_size_exp = 1;
 	else
 		BUG();
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index ae7be3d..b1dbb79 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -1106,7 +1106,7 @@  static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
 			case 0: vidrot = 0; break;
 			case 1: vidrot = 1; break;
 			case 2: vidrot = 2; break;
-			case 3: vidrot = 1; break;
+			case 3: vidrot = 3; break;
 			}
 		}
 
@@ -1134,7 +1134,70 @@  static s32 pixinc(int pixels, u8 ps)
 		BUG();
 }
 
-static void calc_rotation_offset(u8 rotation, bool mirror,
+static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
+		u16 screen_width,
+		u16 width, u16 height,
+		enum omap_color_mode color_mode, bool fieldmode,
+		unsigned *offset0, unsigned *offset1,
+		s32 *row_inc, s32 *pix_inc)
+{
+	u8 ps;
+
+	switch (color_mode) {
+	case OMAP_DSS_COLOR_RGB16:
+	case OMAP_DSS_COLOR_ARGB16:
+		ps = 2;
+		break;
+
+	case OMAP_DSS_COLOR_RGB24P:
+		ps = 3;
+		break;
+
+	case OMAP_DSS_COLOR_RGB24U:
+	case OMAP_DSS_COLOR_ARGB32:
+	case OMAP_DSS_COLOR_RGBA32:
+	case OMAP_DSS_COLOR_RGBX32:
+	case OMAP_DSS_COLOR_YUV2:
+	case OMAP_DSS_COLOR_UYVY:
+		ps = 4;
+		break;
+
+	default:
+		BUG();
+		return;
+	}
+
+	DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width,
+			width, height);
+	switch (rotation + mirror * 4) {
+	case 0:
+	case 2:
+		/*
+		 * If the pixel format is YUV or UYVY divide the width
+		 * of the image by 2.
+		 */
+		if (color_mode == OMAP_DSS_COLOR_YUV2 ||
+			color_mode == OMAP_DSS_COLOR_UYVY)
+			width = width >> 1;
+	case 1:
+	case 3:
+		*offset0 = 0;
+		if (fieldmode)
+			*offset1 = screen_width * ps;
+		else
+			*offset1 = 0;
+
+		*row_inc = pixinc(1 + (screen_width - width) +
+				(fieldmode ? screen_width : 0),
+				ps);
+		*pix_inc = pixinc(1, ps);
+		break;
+	default:
+		BUG();
+	}
+}
+
+static void calc_dma_rotation_offset(u8 rotation, bool mirror,
 		u16 screen_width,
 		u16 width, u16 height,
 		enum omap_color_mode color_mode, bool fieldmode,
@@ -1357,6 +1420,7 @@  static int _dispc_setup_plane(enum omap_plane plane,
 		u16 out_width, u16 out_height,
 		enum omap_color_mode color_mode,
 		bool ilace,
+		enum omap_dss_rotation_type rotation_type,
 		u8 rotation, int mirror)
 {
 	const int maxdownscale = cpu_is_omap34xx() ? 4 : 2;
@@ -1463,10 +1527,16 @@  static int _dispc_setup_plane(enum omap_plane plane,
 			return -EINVAL;
 	}
 
-	calc_rotation_offset(rotation, mirror,
-			screen_width, width, frame_height, color_mode,
-			fieldmode,
-			&offset0, &offset1, &row_inc, &pix_inc);
+	if (rotation_type == OMAP_DSS_ROT_DMA)
+		calc_dma_rotation_offset(rotation, mirror,
+				screen_width, width, height, color_mode,
+				fieldmode,
+				&offset0, &offset1, &row_inc, &pix_inc);
+	else
+		calc_vrfb_rotation_offset(rotation, mirror,
+				screen_width, width, height, color_mode,
+				fieldmode,
+				&offset0, &offset1, &row_inc, &pix_inc);
 
 	DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
 			offset0, offset1, row_inc, pix_inc);
@@ -2879,6 +2949,7 @@  int dispc_setup_plane(enum omap_plane plane, enum omap_channel channel_out,
 		       u16 out_width, u16 out_height,
 		       enum omap_color_mode color_mode,
 		       bool ilace,
+		       enum omap_dss_rotation_type rotation_type,
 		       u8 rotation, bool mirror)
 {
 	int r = 0;
@@ -2899,6 +2970,7 @@  int dispc_setup_plane(enum omap_plane plane, enum omap_channel channel_out,
 			   width, height,
 			   out_width, out_height,
 			   color_mode, ilace,
+			   rotation_type,
 			   rotation, mirror);
 
 	enable_clocks(0);
@@ -3112,7 +3184,8 @@  void dispc_setup_partial_planes(struct omap_display *display,
 				pw, ph,
 				pow, poh,
 				pi->color_mode, 0,
-				pi->rotation, // XXX rotation probably wrong
+				pi->rotation_type,
+				pi->rotation,
 				pi->mirror);
 
 		dispc_enable_plane(ovl->id, 1);
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 0be42b6..c722eee 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -269,6 +269,7 @@  int dispc_setup_plane(enum omap_plane plane, enum omap_channel channel_out,
 		      u16 out_width, u16 out_height,
 		      enum omap_color_mode color_mode,
 		      bool ilace,
+		      enum omap_dss_rotation_type rotation_type,
 		      u8 rotation, bool mirror);
 
 void dispc_go(enum omap_channel channel);
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index b0fee80..8ca0bbb 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -395,6 +395,7 @@  static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 				outh,
 				ovl->info.color_mode,
 				ilace,
+				ovl->info.rotation_type,
 				ovl->info.rotation,
 				ovl->info.mirror);
 
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 12ce0c3..8327681 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -176,15 +176,9 @@  static unsigned omapfb_get_vrfb_offset(struct omapfb_info *ofbi, int rot)
 
 static u32 omapfb_get_region_rot_paddr(struct omapfb_info *ofbi)
 {
-	if (ofbi->rotation_type == OMAPFB_ROT_VRFB) {
-		unsigned offset;
-		int rot;
-
-		rot = ofbi->rotation;
-
-		offset = omapfb_get_vrfb_offset(ofbi, rot);
-
-		return ofbi->region.vrfb.paddr[rot] + offset;
+	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+		return ofbi->region.vrfb.paddr[ofbi->rotation]
+			+ omapfb_get_vrfb_offset(ofbi, ofbi->rotation);
 	} else {
 		return ofbi->region.paddr;
 	}
@@ -192,7 +186,7 @@  static u32 omapfb_get_region_rot_paddr(struct omapfb_info *ofbi)
 
 u32 omapfb_get_region_paddr(struct omapfb_info *ofbi)
 {
-	if (ofbi->rotation_type == OMAPFB_ROT_VRFB)
+	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
 		return ofbi->region.vrfb.paddr[0];
 	else
 		return ofbi->region.paddr;
@@ -200,7 +194,7 @@  u32 omapfb_get_region_paddr(struct omapfb_info *ofbi)
 
 void __iomem *omapfb_get_region_vaddr(struct omapfb_info *ofbi)
 {
-	if (ofbi->rotation_type == OMAPFB_ROT_VRFB)
+	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
 		return ofbi->region.vrfb.vaddr[0];
 	else
 		return ofbi->region.vaddr;
@@ -383,7 +377,7 @@  void set_fb_fix(struct fb_info *fbi)
 	fbi->screen_base = (char __iomem *)omapfb_get_region_vaddr(ofbi);
 
 	/* used by mmap in fbmem.c */
-	if (ofbi->rotation_type == OMAPFB_ROT_VRFB)
+	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
 		fix->line_length =
 			(OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3;
 	else
@@ -419,11 +413,21 @@  void set_fb_fix(struct fb_info *fbi)
 	fix->xpanstep = 1;
 	fix->ypanstep = 1;
 
-	if (rg->size) {
-		if (ofbi->rotation_type == OMAPFB_ROT_VRFB)
-			omap_vrfb_setup(&rg->vrfb, rg->paddr,
-					var->xres_virtual, var->yres_virtual,
-					var->bits_per_pixel >> 3);
+	if (rg->size && ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+		switch(var->nonstd)
+		{
+			case OMAPFB_COLOR_YUV422:
+			case OMAPFB_COLOR_YUV420:
+			case OMAPFB_COLOR_YUY422:
+				omap_vrfb_setup(&rg->vrfb, rg->paddr,
+						var->xres_virtual, var->yres_virtual,
+						var->bits_per_pixel >> 2);
+				break;
+			default:
+				omap_vrfb_setup(&rg->vrfb, rg->paddr,
+						var->xres_virtual, var->yres_virtual,
+						var->bits_per_pixel >> 3);
+		}
 	}
 }
 
@@ -512,7 +516,7 @@  int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
 	if (var->yres > var->yres_virtual)
 		var->yres = var->yres_virtual;
 
-	if (ofbi->rotation_type == OMAPFB_ROT_VRFB)
+	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
 		line_size = OMAP_VRFB_LINE_LEN * bytespp;
 	else
 		line_size = var->xres_virtual * bytespp;
@@ -534,7 +538,7 @@  int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
 
 	if (line_size * var->yres_virtual > max_frame_size) {
 		DBG("can't fit FB into memory, reducing x\n");
-		if (ofbi->rotation_type == OMAPFB_ROT_VRFB)
+		if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
 			return -EINVAL;
 
 		var->xres_virtual = max_frame_size / var->yres_virtual /
@@ -657,7 +661,7 @@  static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
 	struct omap_overlay_info info;
 	int xres, yres;
 	int screen_width;
-	int rot, mirror;
+	int mirror;
 
 	DBG("setup_overlay %d, posx %d, posy %d, outw %d, outh %d\n", ofbi->id,
 			posx, posy, outw, outh);
@@ -673,7 +677,7 @@  static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
 	offset = ((var->yoffset * var->xres_virtual +
 				var->xoffset) * var->bits_per_pixel) >> 3;
 
-	if (ofbi->rotation_type == OMAPFB_ROT_VRFB) {
+	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
 		data_start_p = omapfb_get_region_rot_paddr(ofbi);
 		data_start_v = NULL;
 	} else {
@@ -696,13 +700,10 @@  static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
 
 	ovl->get_overlay_info(ovl, &info);
 
-	if (ofbi->rotation_type == OMAPFB_ROT_VRFB) {
-		rot = 0;
+	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
 		mirror = 0;
-	} else {
-		rot = ofbi->rotation;
+	else
 		mirror = ofbi->mirror;
-	}
 
 	info.paddr = data_start_p;
 	info.vaddr = data_start_v;
@@ -710,7 +711,8 @@  static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
 	info.width = xres;
 	info.height = yres;
 	info.color_mode = mode;
-	info.rotation = rot;
+	info.rotation_type = ofbi->rotation_type;
+	info.rotation = ofbi->rotation;
 	info.mirror = mirror;
 
 	info.pos_x = posx;
@@ -1106,7 +1108,7 @@  static void omapfb_free_fbmem(struct fb_info *fbi)
 	if (rg->vaddr)
 		iounmap(rg->vaddr);
 
-	if (ofbi->rotation_type == OMAPFB_ROT_VRFB) {
+	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
 		/* unmap the 0 angle rotation */
 		if (rg->vrfb.vaddr[0]) {
 			iounmap(rg->vrfb.vaddr[0]);
@@ -1166,7 +1168,7 @@  static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
 		return -ENOMEM;
 	}
 
-	if (ofbi->rotation_type != OMAPFB_ROT_VRFB) {
+	if (ofbi->rotation_type != OMAP_DSS_ROT_VRFB) {
 		vaddr = ioremap_wc(paddr, size);
 
 		if (!vaddr) {
@@ -1245,7 +1247,7 @@  static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
 
 		display->get_resolution(display, &w, &h);
 
-		if (ofbi->rotation_type == OMAPFB_ROT_VRFB) {
+		if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
 #ifdef DEBUG
 			int oldw = w, oldh = h;
 #endif
@@ -1602,8 +1604,8 @@  static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
 		ofbi->id = i;
 
 		/* assign these early, so that fb alloc can use them */
-		ofbi->rotation_type = def_vrfb ? OMAPFB_ROT_VRFB :
-			OMAPFB_ROT_DMA;
+		ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
+			OMAP_DSS_ROT_DMA;
 		ofbi->rotation = def_rotate;
 		ofbi->mirror = def_mirror;
 
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
index 65e9e6e..88e7675 100644
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ b/drivers/video/omap2/omapfb/omapfb.h
@@ -51,11 +51,6 @@  struct omapfb2_mem_region {
 	bool		map;		/* kernel mapped by the driver */
 };
 
-enum omapfb_rotation_type {
-	OMAPFB_ROT_DMA = 0,
-	OMAPFB_ROT_VRFB = 1,
-};
-
 /* appended to fb_info */
 struct omapfb_info {
 	int id;
@@ -64,7 +59,7 @@  struct omapfb_info {
 	int num_overlays;
 	struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB];
 	struct omapfb2_device *fbdev;
-	enum omapfb_rotation_type rotation_type;
+	enum omap_dss_rotation_type rotation_type;
 	u8 rotation;
 	bool mirror;
 };
-- 
1.5.6.3