@@ -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();
@@ -1089,7 +1089,8 @@ static void _dispc_set_scaling(enum omap_plane plane,
}
static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
- bool mirroring, enum omap_color_mode color_mode)
+ bool mirroring, enum omap_color_mode color_mode, u16 width,
+ u16 height)
{
if (color_mode == OMAP_DSS_COLOR_YUV2 ||
color_mode == OMAP_DSS_COLOR_UYVY) {
@@ -1107,7 +1108,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;
}
}
@@ -1121,6 +1122,13 @@ static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12);
REG_FLD_MOD(dispc_reg_att[plane], 0, 18, 18);
}
+
+ /* Turn on DMA optimization. For this to work, both height
+ and width need to be even... */
+ if(width % 2 == 0 && height % 2 == 0 && (rotation == 1 || rotation == 3))
+ REG_FLD_MOD(dispc_reg_att[plane], 1, 20, 20);
+ else
+ REG_FLD_MOD(dispc_reg_att[plane], 0, 20, 20);
}
static s32 pixinc(int pixels, u8 ps)
@@ -1283,6 +1291,76 @@ static void calc_rotation_offset(u8 rotation, bool mirror,
}
}
+static void calc_rotation_offset_vrfb(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;
+ u16 fbw, fbh;
+
+ DSSDBG("calc_rot(%d): scrw %d, %dx%d, cm %d\n", rotation, screen_width,
+ width, height, color_mode);
+
+ /* width & height are overlay sizes, convert to fb sizes */
+ if (rotation == 0 || rotation == 2) {
+ fbw = width;
+ fbh = height;
+ } else {
+ fbw = height;
+ fbh = width;
+ }
+
+ 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:
+ ps = 4;
+ break;
+
+ case OMAP_DSS_COLOR_YUV2:
+ case OMAP_DSS_COLOR_UYVY:
+ ps = 4;
+ fbw >>= 1;
+ break;
+ default:
+ BUG();
+ return;
+ }
+
+ *pix_inc = 1;
+ switch(rotation + mirror * 4) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ *offset0 = *offset1 = 0;
+ break;
+ default:
+ BUG();
+ }
+
+ if(!mirror) {
+ if(rotation == 0 || rotation == 2)
+ *row_inc = 1 + (screen_width - fbw) * ps;
+ else
+ *row_inc = 1 + (screen_width - fbh) * ps;
+ } else
+ BUG();
+}
+
static int _dispc_setup_plane(enum omap_plane plane,
enum omap_channel channel_out,
u32 paddr, u16 screen_width,
@@ -1361,7 +1439,7 @@ static int _dispc_setup_plane(enum omap_plane plane,
if (ilace && height >= out_height)
fieldmode = 1;
- calc_rotation_offset(rotation, mirror,
+ calc_rotation_offset_vrfb(rotation, mirror,
screen_width, width, height, color_mode,
fieldmode,
&offset0, &offset1, &row_inc, &pix_inc);
@@ -1393,18 +1471,25 @@ static int _dispc_setup_plane(enum omap_plane plane,
out_width, out_height);
_dispc_set_plane_pos(plane, pos_x, pos_y);
-
_dispc_set_pic_size(plane, width, height);
if (plane != OMAP_DSS_GFX) {
- _dispc_set_scaling(plane, width, height,
- out_width, out_height,
- ilace);
- _dispc_set_vid_size(plane, out_width, out_height);
+ if(rotation == 0 || rotation == 2)
+ {
+ _dispc_set_scaling(plane, width, height,
+ out_width, out_height,
+ ilace);
+ _dispc_set_vid_size(plane, out_width, out_height);
+ } else {
+ _dispc_set_scaling(plane, width, height,
+ out_height, out_width,
+ ilace);
+ _dispc_set_vid_size(plane, out_height, out_width);
+ }
_dispc_set_vid_color_conv(plane, cconv);
}
- _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode);
+ _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode, width, height);
return 0;
}
@@ -420,10 +420,14 @@ void set_fb_fix(struct fb_info *fbi)
fix->ypanstep = 1;
if (rg->size) {
- if (ofbi->rotation_type == OMAPFB_ROT_VRFB)
+ if (ofbi->rotation_type == OMAPFB_ROT_VRFB && ofbi->id == 0)
omap_vrfb_setup(&rg->vrfb, rg->paddr,
var->xres_virtual, var->yres_virtual,
var->bits_per_pixel >> 3);
+ else if (ofbi->rotation_type == OMAPFB_ROT_VRFB && ofbi->id != 0)
+ omap_vrfb_setup(&rg->vrfb, rg->paddr,
+ var->xres_virtual, var->yres_virtual,
+ var->bits_per_pixel >> 2);
}
}
@@ -487,6 +491,8 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
yres_max = 2048;
bytespp = var->bits_per_pixel >> 3;
+ if(mode == OMAP_DSS_COLOR_YUV2 || mode == OMAP_DSS_COLOR_UYVY)
+ bytespp <<= 1;
/* XXX: some applications seem to set virtual res to 0. */
if (var->xres_virtual == 0)
@@ -696,13 +702,8 @@ 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;
- mirror = 0;
- } else {
- rot = ofbi->rotation;
- mirror = ofbi->mirror;
- }
+ rot = ofbi->rotation;
+ mirror = ofbi->mirror;
info.paddr = data_start_p;
info.vaddr = data_start_v;