From 77e848eeba461e9b55b09d39fd0d640caea13e19 Mon Sep 17 00:00:00 2001 From: Hardik Shah Date: Thu, 9 Apr 2009 12:09:44 +0530 Subject: [PATCH] DSS2: VRFB rotation and mirroring implemented. DSS2 modified to accept the rotation_type input to get the dma or VRFB rotation. DSS2: VRFB: Changed to pass DSS mode to vrfb_setup instead of Bpp. VRFB size registers requires the width to be halved when the mode is YUV or UYVY. So modifed to pass the mode to omap_vrfb_setup function. Code added by Tim Yamin for few bug fixes Signed-off-by: Tim Yamin Signed-off-by: Hardik Shah --- arch/arm/plat-omap/include/mach/display.h | 6 ++ arch/arm/plat-omap/include/mach/vrfb.h | 3 +- arch/arm/plat-omap/vrfb.c | 36 +++++++++- drivers/video/omap2/dss/dispc.c | 109 +++++++++++++++++++++++++++-- drivers/video/omap2/dss/dss.h | 1 + drivers/video/omap2/dss/manager.c | 1 + 6 files changed, 144 insertions(+), 12 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/include/mach/vrfb.h b/arch/arm/plat-omap/include/mach/vrfb.h index 2047862..12c7fab 100644 --- a/arch/arm/plat-omap/include/mach/vrfb.h +++ b/arch/arm/plat-omap/include/mach/vrfb.h @@ -24,6 +24,7 @@ #ifndef __VRFB_H #define __VRFB_H +#include #define OMAP_VRFB_LINE_LEN 2048 struct vrfb @@ -42,6 +43,6 @@ extern void omap_vrfb_adjust_size(u16 *width, u16 *height, u8 bytespp); extern void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr, u16 width, u16 height, - u8 bytespp); + enum omap_color_mode color_mode); #endif /* __VRFB_H */ diff --git a/arch/arm/plat-omap/vrfb.c b/arch/arm/plat-omap/vrfb.c index d68065f..2f08f6d 100644 --- a/arch/arm/plat-omap/vrfb.c +++ b/arch/arm/plat-omap/vrfb.c @@ -5,7 +5,6 @@ #include #include - /*#define DEBUG*/ #ifdef DEBUG @@ -50,19 +49,48 @@ EXPORT_SYMBOL(omap_vrfb_adjust_size); void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr, u16 width, u16 height, - u8 bytespp) + enum omap_color_mode color_mode) { unsigned pixel_size_exp; u16 vrfb_width; u16 vrfb_height; u8 ctx = vrfb->context; + u8 bytespp; DBG("omapfb_set_vrfb(%d, %lx, %dx%d, %d)\n", ctx, paddr, width, height, bytespp); - if (bytespp == 4) + switch (color_mode) { + case OMAP_DSS_COLOR_RGB16: + case OMAP_DSS_COLOR_ARGB16: + bytespp = 2; + break; + + case OMAP_DSS_COLOR_RGB24P: + bytespp = 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: + bytespp = 4; + break; + + default: + BUG(); + return; + } + + if (color_mode == OMAP_DSS_COLOR_YUV2 || + color_mode == OMAP_DSS_COLOR_UYVY) + width >>= 1; + + if (bytespp == 4) { pixel_size_exp = 2; - else if (bytespp == 2) + } 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 16c68b8..23a8155 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,92 @@ 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 for 0 and 180 degree rotation. + */ + 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; + + case 4: + case 6: + /* If the pixel format is YUV or UYVY divide the width + * of the image by 2 for 0 degree and 180 degree + */ + if (color_mode == OMAP_DSS_COLOR_YUV2 || + color_mode == OMAP_DSS_COLOR_UYVY) + width = width >> 1; + case 5: + case 7: + *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 +1442,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 +1549,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, frame_height, color_mode, + fieldmode, + &offset0, &offset1, &row_inc, &pix_inc); + else + calc_vrfb_rotation_offset(rotation, mirror, + screen_width, width, frame_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); @@ -2889,6 +2981,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; @@ -2909,6 +3002,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); @@ -3122,7 +3216,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 d0917a8..584dce6 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -272,6 +272,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); -- 1.5.6.5