[PATCH] OMAP: DSS2: GFX FIFO UNDERFLOW issue fixed

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Vaibhav Hiremath <hvaibhav@xxxxxx>

In case of 720P with 90/270 degree rotation, the system reports
GFX_FIFO_UNDERFLOW error which usually happens if DSS DMA is not able to fill
the FIFO as per requirement.

In TRM (section 11.2.6.1.3), where is has been clearly mentioned that,

"To improve the performance on 90 degree rotation, split the data access on
write side and not read side."

That means, read should always happen on 0 degree and write should go to
respective rotation view.

Signed-off-by: Vaibhav Hiremath <hvaibhav@xxxxxx>
---
 drivers/video/omap2/omapfb/omapfb-main.c |   85 +++++++++++++++++++----------
 1 files changed, 56 insertions(+), 29 deletions(-)

diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 4a76917..fea6b08 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -184,6 +184,11 @@ static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot)
 static u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot)
 {
 	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+		if (rot == FB_ROTATE_CW)
+			rot = FB_ROTATE_CCW;
+		else if (rot == FB_ROTATE_CCW)
+			rot = FB_ROTATE_CW;
+
 		return ofbi->region.vrfb.paddr[rot]
 			+ omapfb_get_vrfb_offset(ofbi, rot);
 	} else {
@@ -191,20 +196,32 @@ static u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot)
 	}
 }
 
-static u32 omapfb_get_region_paddr(const struct omapfb_info *ofbi)
+static u32 omapfb_get_region_paddr(struct omapfb_info *ofbi, int rot)
 {
-	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
-		return ofbi->region.vrfb.paddr[0];
-	else
+	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+		if (rot == FB_ROTATE_CW)
+			rot = FB_ROTATE_CCW;
+		else if (rot == FB_ROTATE_CCW)
+			rot = FB_ROTATE_CW;
+
+		return ofbi->region.vrfb.paddr[rot];
+	} else {
 		return ofbi->region.paddr;
+	}
 }
 
-static void __iomem *omapfb_get_region_vaddr(const struct omapfb_info *ofbi)
+static void __iomem *omapfb_get_region_vaddr(struct omapfb_info *ofbi, int rot)
 {
-	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
-		return ofbi->region.vrfb.vaddr[0];
-	else
+	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+		if (rot == FB_ROTATE_CW)
+			rot = FB_ROTATE_CCW;
+		else if (rot == FB_ROTATE_CCW)
+			rot = FB_ROTATE_CW;
+
+		return ofbi->region.vrfb.vaddr[rot];
+	} else {
 		return ofbi->region.vaddr;
+	}
 }
 
 static struct omapfb_colormode omapfb_colormodes[] = {
@@ -503,7 +520,7 @@ static int setup_vrfb_rotation(struct fb_info *fbi)
 	unsigned bytespp;
 	bool yuv_mode;
 	enum omap_color_mode mode;
-	int r;
+	int r, rotation = var->rotate;
 	bool reconf;
 
 	if (!rg->size || ofbi->rotation_type != OMAP_DSS_ROT_VRFB)
@@ -511,6 +528,11 @@ static int setup_vrfb_rotation(struct fb_info *fbi)
 
 	DBG("setup_vrfb_rotation\n");
 
+	if (rotation == FB_ROTATE_CW)
+		rotation = FB_ROTATE_CCW;
+	else if (rotation == FB_ROTATE_CCW)
+		rotation = FB_ROTATE_CW;
+
 	r = fb_mode_to_dss_mode(var, &mode);
 	if (r)
 		return r;
@@ -534,32 +556,35 @@ static int setup_vrfb_rotation(struct fb_info *fbi)
 			vrfb->yres != var->yres_virtual)
 		reconf = true;
 
-	if (vrfb->vaddr[0] && reconf) {
+	if (vrfb->vaddr[rotation] && reconf) {
 		fbi->screen_base = NULL;
 		fix->smem_start = 0;
 		fix->smem_len = 0;
-		iounmap(vrfb->vaddr[0]);
-		vrfb->vaddr[0] = NULL;
+		iounmap(vrfb->vaddr[rotation]);
+		vrfb->vaddr[rotation] = NULL;
 		DBG("setup_vrfb_rotation: reset fb\n");
 	}
 
-	if (vrfb->vaddr[0])
+	if (vrfb->vaddr[rotation])
 		return 0;
 
-	omap_vrfb_setup(&rg->vrfb, rg->paddr,
-			var->xres_virtual,
-			var->yres_virtual,
-			bytespp, yuv_mode);
+	if (rotation == FB_ROTATE_CW || rotation == FB_ROTATE_CCW)
+		omap_vrfb_setup(&rg->vrfb, rg->paddr,
+				var->yres_virtual, var->xres_virtual,
+				bytespp, yuv_mode);
+	else
+		omap_vrfb_setup(&rg->vrfb, rg->paddr,
+				var->xres_virtual, var->yres_virtual,
+				bytespp, yuv_mode);
 
-	/* Now one can ioremap the 0 angle view */
-	r = omap_vrfb_map_angle(vrfb, var->yres_virtual, 0);
+	/* Now one can ioremap the rotation angle view */
+	r = omap_vrfb_map_angle(vrfb, var->yres_virtual, rotation);
 	if (r)
 		return r;
-
 	/* used by open/write in fbmem.c */
-	fbi->screen_base = ofbi->region.vrfb.vaddr[0];
+	fbi->screen_base = ofbi->region.vrfb.vaddr[rotation];
 
-	fix->smem_start = ofbi->region.vrfb.paddr[0];
+	fix->smem_start = ofbi->region.vrfb.paddr[rotation];
 
 	switch (var->nonstd) {
 	case OMAPFB_COLOR_YUV422:
@@ -603,7 +628,8 @@ void set_fb_fix(struct fb_info *fbi)
 	DBG("set_fb_fix\n");
 
 	/* used by open/write in fbmem.c */
-	fbi->screen_base = (char __iomem *)omapfb_get_region_vaddr(ofbi);
+	fbi->screen_base = (char __iomem *)omapfb_get_region_vaddr(ofbi,
+			var->rotate);
 
 	/* used by mmap in fbmem.c */
 	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
@@ -626,7 +652,7 @@ void set_fb_fix(struct fb_info *fbi)
 		fix->smem_len = rg->size;
 	}
 
-	fix->smem_start = omapfb_get_region_paddr(ofbi);
+	fix->smem_start = omapfb_get_region_paddr(ofbi, var->rotate);
 
 	fix->type = FB_TYPE_PACKED_PIXELS;
 
@@ -862,15 +888,15 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
 
 
 	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
-		data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
+		data_start_p = omapfb_get_region_rot_paddr(ofbi, 0);
 		data_start_v = NULL;
 	} else {
-		data_start_p = omapfb_get_region_paddr(ofbi);
-		data_start_v = omapfb_get_region_vaddr(ofbi);
+		data_start_p = omapfb_get_region_paddr(ofbi, 0);
+		data_start_v = omapfb_get_region_vaddr(ofbi, 0);
 	}
 
 	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
-		offset = calc_rotation_offset_vrfb(var, fix, rotation);
+		offset = calc_rotation_offset_vrfb(var, fix, 0);
 	else
 		offset = calc_rotation_offset_dma(var, fix, rotation);
 
@@ -1078,6 +1104,7 @@ static struct vm_operations_struct mmap_user_ops = {
 static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
 {
 	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct fb_var_screeninfo *var = &fbi->var;
 	struct fb_fix_screeninfo *fix = &fbi->fix;
 	unsigned long off;
 	unsigned long start;
@@ -1089,7 +1116,7 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
 		return -EINVAL;
 	off = vma->vm_pgoff << PAGE_SHIFT;
 
-	start = omapfb_get_region_paddr(ofbi);
+	start = omapfb_get_region_paddr(ofbi, var->rotate);
 	len = fix->smem_len;
 	if (off >= len)
 		return -EINVAL;
-- 
1.6.2.4

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux