DSS2: VRFB rotation and mirroring implemented.
authorHardik Shah <hardik.shah@ti.com>
Thu, 9 Apr 2009 06:39:44 +0000 (12:09 +0530)
committerGrazvydas Ignotas <notasas@gmail.com>
Fri, 1 May 2009 16:45:04 +0000 (19:45 +0300)
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 <plasm@roo.me.uk>
Signed-off-by: Hardik Shah <hardik.shah@ti.com>
arch/arm/plat-omap/include/mach/display.h
arch/arm/plat-omap/include/mach/vrfb.h
arch/arm/plat-omap/vrfb.c
drivers/video/omap2/dss/dispc.c
drivers/video/omap2/dss/dss.h
drivers/video/omap2/dss/manager.c

index 6b702c7..b0a6272 100644 (file)
@@ -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;
index 2047862..12c7fab 100644 (file)
@@ -24,6 +24,7 @@
 #ifndef __VRFB_H
 #define __VRFB_H
 
+#include <mach/display.h>
 #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 */
index d68065f..2f08f6d 100644 (file)
@@ -5,7 +5,6 @@
 
 #include <mach/io.h>
 #include <mach/vrfb.h>
-
 /*#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();
index 16c68b8..23a8155 100644 (file)
@@ -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);
index d0917a8..584dce6 100644 (file)
@@ -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);
index b0fee80..8ca0bbb 100644 (file)
@@ -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);