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
From 5c575fd5226164c75e0bc98a5ead80ee6900fdc1 Mon Sep 17 00:00:00 2001 From: Tim Yamin <plasm@xxxxxxxxx> Date: Tue, 7 Apr 2009 11:27:54 -0700 Subject: [PATCH] Change FIFO settings as suggested by Hardik. --- drivers/video/omap2/dss/dispc.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 550a2a0..61785e3 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -960,6 +960,12 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high) BUG_ON(low > size || high > size); + if(size == 1024) + { + high = 0x3FC; + low = 0x3BC; + } + DSSDBG("fifo(%d) size %d, low/high old %u/%u, new %u/%u\n", plane, size, REG_GET(ftrs_reg[plane], 11, 0), @@ -1463,6 +1469,8 @@ static int _dispc_setup_plane(enum omap_plane plane, out_width, out_height); _dispc_set_plane_pos(plane, pos_x, pos_y); + if (plane != OMAP_DSS_GFX) + _dispc_set_plane_pos(plane, 5, 5); _dispc_set_pic_size(plane, width, height); -- 1.5.6.3
From 826edf9b2b9af7b9bc32f4363724af174911175c Mon Sep 17 00:00:00 2001 From: Tim Yamin <plasm@xxxxxxxxx> 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@xxxxxxxxx> --- 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