BUG_ON(plane == OMAP_DSS_GFX);
- val = FLD_VAL(vinc, 27, 16) | FLD_VAL(hinc, 11, 0);
+ if (cpu_is_omap24xx())
+ val = FLD_VAL(vinc, 27, 16) | FLD_VAL(hinc, 11, 0);
+ else
+ val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0);
dispc_write_reg(fir_reg[plane-1], val);
}
static void _dispc_set_scaling(enum omap_plane plane,
u16 orig_width, u16 orig_height,
u16 out_width, u16 out_height,
- bool ilace, bool five_taps)
+ bool ilace, bool five_taps,
+ bool fieldmode)
{
int fir_hinc;
int fir_vinc;
int hscaleup, vscaleup;
- int fieldmode = 0;
int accu0 = 0;
int accu1 = 0;
u32 l;
dispc_write_reg(dispc_reg_att[plane], l);
- if (ilace) {
- if (fieldmode) {
- accu0 = fir_vinc / 2;
- accu1 = 0;
- } else {
- accu0 = 0;
- accu1 = fir_vinc / 2;
- if (accu1 >= 1024/2) {
- accu0 = 1024/2;
- accu1 -= accu0;
- }
+ /*
+ * field 0 = even field = bottom field
+ * field 1 = odd field = top field
+ */
+ if (ilace && !fieldmode) {
+ accu1 = 0;
+ accu0 = fir_vinc / 2;
+ if (accu0 >= 1024/2) {
+ accu1 = 1024/2;
+ accu0 -= accu1;
}
}
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;
}
}
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,
fbh = width;
}
+ /*
+ * field 0 = even field = bottom field
+ * field 1 = odd field = top field
+ */
switch (rotation + mirror * 4) {
case 0:
- *offset0 = 0;
+ *offset1 = 0;
if (fieldmode)
- *offset1 = screen_width * ps;
+ *offset0 = screen_width * ps;
else
- *offset1 = 0;
+ *offset0 = 0;
*row_inc = pixinc(1 + (screen_width - fbw) +
(fieldmode ? screen_width : 0),
ps);
*pix_inc = pixinc(1, ps);
break;
case 1:
- *offset0 = screen_width * (fbh - 1) * ps;
+ *offset1 = screen_width * (fbh - 1) * ps;
if (fieldmode)
- *offset1 = *offset0 + ps;
+ *offset0 = *offset1 + ps;
else
- *offset1 = *offset0;
+ *offset0 = *offset1;
*row_inc = pixinc(screen_width * (fbh - 1) + 1 +
(fieldmode ? 1 : 0), ps);
*pix_inc = pixinc(-screen_width, ps);
break;
case 2:
- *offset0 = (screen_width * (fbh - 1) + fbw - 1) * ps;
+ *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
if (fieldmode)
- *offset1 = *offset0 - screen_width * ps;
+ *offset0 = *offset1 - screen_width * ps;
else
- *offset1 = *offset0;
+ *offset0 = *offset1;
*row_inc = pixinc(-1 -
(screen_width - fbw) -
(fieldmode ? screen_width : 0),
*pix_inc = pixinc(-1, ps);
break;
case 3:
- *offset0 = (fbw - 1) * ps;
+ *offset1 = (fbw - 1) * ps;
if (fieldmode)
- *offset1 = *offset0 - ps;
+ *offset0 = *offset1 - ps;
else
- *offset1 = *offset0;
+ *offset0 = *offset1;
*row_inc = pixinc(-screen_width * (fbh - 1) - 1 -
(fieldmode ? 1 : 0), ps);
*pix_inc = pixinc(screen_width, ps);
/* mirroring */
case 0 + 4:
- *offset0 = (fbw - 1) * ps;
+ *offset1 = (fbw - 1) * ps;
if (fieldmode)
- *offset1 = *offset0 + screen_width * ps;
+ *offset0 = *offset1 + screen_width * ps;
else
- *offset1 = *offset0;
+ *offset0 = *offset1;
*row_inc = pixinc(screen_width * 2 - 1 +
(fieldmode ? screen_width : 0),
ps);
break;
case 1 + 4:
- *offset0 = 0;
+ *offset1 = 0;
if (fieldmode)
- *offset1 = *offset0 + screen_width * ps;
+ *offset0 = *offset1 + screen_width * ps;
else
- *offset1 = *offset0;
+ *offset0 = *offset1;
*row_inc = pixinc(-screen_width * (fbh - 1) + 1 +
(fieldmode ? 1 : 0),
ps);
break;
case 2 + 4:
- *offset0 = screen_width * (fbh - 1) * ps;
+ *offset1 = screen_width * (fbh - 1) * ps;
if (fieldmode)
- *offset1 = *offset0 + screen_width * ps;
+ *offset0 = *offset1 + screen_width * ps;
else
- *offset1 = *offset0;
+ *offset0 = *offset1;
*row_inc = pixinc(1 - screen_width * 2 -
(fieldmode ? screen_width : 0),
ps);
break;
case 3 + 4:
- *offset0 = (screen_width * (fbh - 1) + fbw - 1) * ps;
+ *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
if (fieldmode)
- *offset1 = *offset0 + screen_width * ps;
+ *offset0 = *offset1 + screen_width * ps;
else
- *offset1 = *offset0;
+ *offset0 = *offset1;
*row_inc = pixinc(screen_width * (fbh - 1) - 1 -
(fieldmode ? 1 : 0),
ps);
}
static unsigned long calc_fclk(u16 width, u16 height,
- u16 out_width, u16 out_height,
- enum omap_color_mode color_mode, bool five_taps)
+ u16 out_width, u16 out_height)
{
unsigned int hf, vf;
- if (five_taps)
- return calc_fclk_five_taps(width, height,
- out_width, out_height, color_mode);
-
/*
* FIXME how to determine the 'A' factor
* for the no downscaling case ?
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;
if (paddr == 0)
return -EINVAL;
- if (ilace && height >= out_height)
+ if (ilace && height == out_height)
fieldmode = 1;
if (ilace) {
} else {
/* video plane */
- unsigned long fclk;
+ unsigned long fclk = 0;
if (out_width < width / maxdownscale ||
out_width > width * 8)
/* Must use 5-tap filter? */
five_taps = height > out_height * 2;
- /* Try to use 5-tap filter whenever possible. */
- if (cpu_is_omap34xx() && !five_taps &&
- height > out_height && width <= 1024) {
- fclk = calc_fclk_five_taps(width, height,
- out_width, out_height, color_mode);
- if (fclk <= dispc_fclk_rate())
+ if (!five_taps) {
+ fclk = calc_fclk(width, height,
+ out_width, out_height);
+
+ /* Try 5-tap filter if 3-tap fclk is too high */
+ if (cpu_is_omap34xx() && height > out_height &&
+ fclk > dispc_fclk_rate())
five_taps = true;
}
if (width > (2048 >> five_taps))
return -EINVAL;
- fclk = calc_fclk(width, height, out_width, out_height,
- color_mode, five_taps);
+ if (five_taps)
+ fclk = calc_fclk_five_taps(width, height,
+ out_width, out_height, color_mode);
DSSDBG("required fclk rate = %lu Hz\n", fclk);
DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
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);
if (plane != OMAP_DSS_GFX) {
_dispc_set_scaling(plane, width, height,
out_width, out_height,
- ilace, five_taps);
+ ilace, five_taps, fieldmode);
_dispc_set_vid_size(plane, out_width, out_height);
_dispc_set_vid_color_conv(plane, cconv);
}
enable_clocks(1);
if (type) {
if (ch == OMAP_DSS_CHANNEL_LCD)
- *type = REG_GET(DISPC_CONFIG, 11, 11) >> 11;
+ *type = REG_GET(DISPC_CONFIG, 11, 11);
else if (ch == OMAP_DSS_CHANNEL_DIGIT)
- *type = REG_GET(DISPC_CONFIG, 13, 13) >> 13;
+ *type = REG_GET(DISPC_CONFIG, 13, 13);
else
BUG();
}
REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12);
enable_clocks(0);
}
+void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
+{
+ enable_clocks(1);
+ if (ch == OMAP_DSS_CHANNEL_LCD)
+ REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
+ else /* OMAP_DSS_CHANNEL_DIGIT */
+ REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
+ enable_clocks(0);
+}
+bool dispc_alpha_blending_enabled(enum omap_channel ch)
+{
+ bool enabled;
+
+ enable_clocks(1);
+ if (ch == OMAP_DSS_CHANNEL_LCD)
+ enabled = REG_GET(DISPC_CONFIG, 18, 18);
+ else if (ch == OMAP_DSS_CHANNEL_DIGIT)
+ enabled = REG_GET(DISPC_CONFIG, 18, 18);
+ else
+ BUG();
+ enable_clocks(0);
+
+ return enabled;
+
+}
+
bool dispc_trans_key_enabled(enum omap_channel ch)
{
omap_dispc_set_irqs();
}
+void dispc_enable_sidle(void)
+{
+ REG_FLD_MOD(DISPC_SYSCONFIG, 2, 4, 3); /* SIDLEMODE: smart idle */
+}
+
+void dispc_disable_sidle(void)
+{
+ REG_FLD_MOD(DISPC_SYSCONFIG, 1, 4, 3); /* SIDLEMODE: no idle */
+}
+
static void _omap_dispc_initial_config(void)
{
u32 l;
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;
width, height,
out_width, out_height,
color_mode, ilace,
+ rotation_type,
rotation, mirror);
enable_clocks(0);
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);