|
@@ -131,23 +131,6 @@ static inline u32 dispc_read_reg(const u16 idx)
|
|
return __raw_readl(dispc.base + idx);
|
|
return __raw_readl(dispc.base + idx);
|
|
}
|
|
}
|
|
|
|
|
|
-static int dispc_get_ctx_loss_count(void)
|
|
|
|
-{
|
|
|
|
- struct device *dev = &dispc.pdev->dev;
|
|
|
|
- struct omap_display_platform_data *pdata = dev->platform_data;
|
|
|
|
- struct omap_dss_board_info *board_data = pdata->board_data;
|
|
|
|
- int cnt;
|
|
|
|
-
|
|
|
|
- if (!board_data->get_context_loss_count)
|
|
|
|
- return -ENOENT;
|
|
|
|
-
|
|
|
|
- cnt = board_data->get_context_loss_count(dev);
|
|
|
|
-
|
|
|
|
- WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
|
|
|
|
-
|
|
|
|
- return cnt;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
#define SR(reg) \
|
|
#define SR(reg) \
|
|
dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
|
|
dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
|
|
#define RR(reg) \
|
|
#define RR(reg) \
|
|
@@ -251,7 +234,7 @@ static void dispc_save_context(void)
|
|
if (dss_has_feature(FEAT_CORE_CLK_DIV))
|
|
if (dss_has_feature(FEAT_CORE_CLK_DIV))
|
|
SR(DIVISOR);
|
|
SR(DIVISOR);
|
|
|
|
|
|
- dispc.ctx_loss_cnt = dispc_get_ctx_loss_count();
|
|
|
|
|
|
+ dispc.ctx_loss_cnt = dss_get_ctx_loss_count(&dispc.pdev->dev);
|
|
dispc.ctx_valid = true;
|
|
dispc.ctx_valid = true;
|
|
|
|
|
|
DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt);
|
|
DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt);
|
|
@@ -266,7 +249,7 @@ static void dispc_restore_context(void)
|
|
if (!dispc.ctx_valid)
|
|
if (!dispc.ctx_valid)
|
|
return;
|
|
return;
|
|
|
|
|
|
- ctx = dispc_get_ctx_loss_count();
|
|
|
|
|
|
+ ctx = dss_get_ctx_loss_count(&dispc.pdev->dev);
|
|
|
|
|
|
if (ctx >= 0 && ctx == dispc.ctx_loss_cnt)
|
|
if (ctx >= 0 && ctx == dispc.ctx_loss_cnt)
|
|
return;
|
|
return;
|
|
@@ -413,14 +396,6 @@ static inline bool dispc_mgr_is_lcd(enum omap_channel channel)
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
-static struct omap_dss_device *dispc_mgr_get_device(enum omap_channel channel)
|
|
|
|
-{
|
|
|
|
- struct omap_overlay_manager *mgr =
|
|
|
|
- omap_dss_get_overlay_manager(channel);
|
|
|
|
-
|
|
|
|
- return mgr ? mgr->device : NULL;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
u32 dispc_mgr_get_vsync_irq(enum omap_channel channel)
|
|
u32 dispc_mgr_get_vsync_irq(enum omap_channel channel)
|
|
{
|
|
{
|
|
switch (channel) {
|
|
switch (channel) {
|
|
@@ -432,6 +407,7 @@ u32 dispc_mgr_get_vsync_irq(enum omap_channel channel)
|
|
return DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
|
|
return DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
|
|
default:
|
|
default:
|
|
BUG();
|
|
BUG();
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -446,6 +422,7 @@ u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)
|
|
return 0;
|
|
return 0;
|
|
default:
|
|
default:
|
|
BUG();
|
|
BUG();
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -764,7 +741,7 @@ static void dispc_ovl_set_color_mode(enum omap_plane plane,
|
|
case OMAP_DSS_COLOR_XRGB16_1555:
|
|
case OMAP_DSS_COLOR_XRGB16_1555:
|
|
m = 0xf; break;
|
|
m = 0xf; break;
|
|
default:
|
|
default:
|
|
- BUG(); break;
|
|
|
|
|
|
+ BUG(); return;
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
switch (color_mode) {
|
|
switch (color_mode) {
|
|
@@ -801,13 +778,25 @@ static void dispc_ovl_set_color_mode(enum omap_plane plane,
|
|
case OMAP_DSS_COLOR_XRGB16_1555:
|
|
case OMAP_DSS_COLOR_XRGB16_1555:
|
|
m = 0xf; break;
|
|
m = 0xf; break;
|
|
default:
|
|
default:
|
|
- BUG(); break;
|
|
|
|
|
|
+ BUG(); return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
|
|
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void dispc_ovl_configure_burst_type(enum omap_plane plane,
|
|
|
|
+ enum omap_dss_rotation_type rotation_type)
|
|
|
|
+{
|
|
|
|
+ if (dss_has_feature(FEAT_BURST_2D) == 0)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ if (rotation_type == OMAP_DSS_ROT_TILER)
|
|
|
|
+ REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), 1, 29, 29);
|
|
|
|
+ else
|
|
|
|
+ REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), 0, 29, 29);
|
|
|
|
+}
|
|
|
|
+
|
|
void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel)
|
|
void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel)
|
|
{
|
|
{
|
|
int shift;
|
|
int shift;
|
|
@@ -845,6 +834,7 @@ void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel)
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
BUG();
|
|
BUG();
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
|
|
|
|
val = FLD_MOD(val, chan, shift, shift);
|
|
val = FLD_MOD(val, chan, shift, shift);
|
|
@@ -872,6 +862,7 @@ static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane)
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
BUG();
|
|
BUG();
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
|
|
val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
|
|
@@ -983,20 +974,13 @@ static void dispc_ovl_enable_replication(enum omap_plane plane, bool enable)
|
|
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift);
|
|
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift);
|
|
}
|
|
}
|
|
|
|
|
|
-void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
|
|
|
|
|
|
+static void dispc_mgr_set_size(enum omap_channel channel, u16 width,
|
|
|
|
+ u16 height)
|
|
{
|
|
{
|
|
u32 val;
|
|
u32 val;
|
|
- BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
|
|
|
|
- val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
|
|
|
|
- dispc_write_reg(DISPC_SIZE_MGR(channel), val);
|
|
|
|
-}
|
|
|
|
|
|
|
|
-void dispc_set_digit_size(u16 width, u16 height)
|
|
|
|
-{
|
|
|
|
- u32 val;
|
|
|
|
- BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
|
|
|
|
val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
|
|
val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
|
|
- dispc_write_reg(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT), val);
|
|
|
|
|
|
+ dispc_write_reg(DISPC_SIZE_MGR(channel), val);
|
|
}
|
|
}
|
|
|
|
|
|
static void dispc_read_plane_fifo_sizes(void)
|
|
static void dispc_read_plane_fifo_sizes(void)
|
|
@@ -1063,7 +1047,8 @@ void dispc_enable_fifomerge(bool enable)
|
|
}
|
|
}
|
|
|
|
|
|
void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
|
|
void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
|
|
- u32 *fifo_low, u32 *fifo_high, bool use_fifomerge)
|
|
|
|
|
|
+ u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,
|
|
|
|
+ bool manual_update)
|
|
{
|
|
{
|
|
/*
|
|
/*
|
|
* All sizes are in bytes. Both the buffer and burst are made of
|
|
* All sizes are in bytes. Both the buffer and burst are made of
|
|
@@ -1091,7 +1076,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
|
|
* combined fifo size
|
|
* combined fifo size
|
|
*/
|
|
*/
|
|
|
|
|
|
- if (dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) {
|
|
|
|
|
|
+ if (manual_update && dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) {
|
|
*fifo_low = ovl_fifo_size - burst_size * 2;
|
|
*fifo_low = ovl_fifo_size - burst_size * 2;
|
|
*fifo_high = total_fifo_size - burst_size;
|
|
*fifo_high = total_fifo_size - burst_size;
|
|
} else {
|
|
} else {
|
|
@@ -1185,6 +1170,94 @@ static void dispc_ovl_set_scale_param(enum omap_plane plane,
|
|
dispc_ovl_set_fir(plane, fir_hinc, fir_vinc, color_comp);
|
|
dispc_ovl_set_fir(plane, fir_hinc, fir_vinc, color_comp);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void dispc_ovl_set_accu_uv(enum omap_plane plane,
|
|
|
|
+ u16 orig_width, u16 orig_height, u16 out_width, u16 out_height,
|
|
|
|
+ bool ilace, enum omap_color_mode color_mode, u8 rotation)
|
|
|
|
+{
|
|
|
|
+ int h_accu2_0, h_accu2_1;
|
|
|
|
+ int v_accu2_0, v_accu2_1;
|
|
|
|
+ int chroma_hinc, chroma_vinc;
|
|
|
|
+ int idx;
|
|
|
|
+
|
|
|
|
+ struct accu {
|
|
|
|
+ s8 h0_m, h0_n;
|
|
|
|
+ s8 h1_m, h1_n;
|
|
|
|
+ s8 v0_m, v0_n;
|
|
|
|
+ s8 v1_m, v1_n;
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ const struct accu *accu_table;
|
|
|
|
+ const struct accu *accu_val;
|
|
|
|
+
|
|
|
|
+ static const struct accu accu_nv12[4] = {
|
|
|
|
+ { 0, 1, 0, 1 , -1, 2, 0, 1 },
|
|
|
|
+ { 1, 2, -3, 4 , 0, 1, 0, 1 },
|
|
|
|
+ { -1, 1, 0, 1 , -1, 2, 0, 1 },
|
|
|
|
+ { -1, 2, -1, 2 , -1, 1, 0, 1 },
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ static const struct accu accu_nv12_ilace[4] = {
|
|
|
|
+ { 0, 1, 0, 1 , -3, 4, -1, 4 },
|
|
|
|
+ { -1, 4, -3, 4 , 0, 1, 0, 1 },
|
|
|
|
+ { -1, 1, 0, 1 , -1, 4, -3, 4 },
|
|
|
|
+ { -3, 4, -3, 4 , -1, 1, 0, 1 },
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ static const struct accu accu_yuv[4] = {
|
|
|
|
+ { 0, 1, 0, 1, 0, 1, 0, 1 },
|
|
|
|
+ { 0, 1, 0, 1, 0, 1, 0, 1 },
|
|
|
|
+ { -1, 1, 0, 1, 0, 1, 0, 1 },
|
|
|
|
+ { 0, 1, 0, 1, -1, 1, 0, 1 },
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ switch (rotation) {
|
|
|
|
+ case OMAP_DSS_ROT_0:
|
|
|
|
+ idx = 0;
|
|
|
|
+ break;
|
|
|
|
+ case OMAP_DSS_ROT_90:
|
|
|
|
+ idx = 1;
|
|
|
|
+ break;
|
|
|
|
+ case OMAP_DSS_ROT_180:
|
|
|
|
+ idx = 2;
|
|
|
|
+ break;
|
|
|
|
+ case OMAP_DSS_ROT_270:
|
|
|
|
+ idx = 3;
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ BUG();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ switch (color_mode) {
|
|
|
|
+ case OMAP_DSS_COLOR_NV12:
|
|
|
|
+ if (ilace)
|
|
|
|
+ accu_table = accu_nv12_ilace;
|
|
|
|
+ else
|
|
|
|
+ accu_table = accu_nv12;
|
|
|
|
+ break;
|
|
|
|
+ case OMAP_DSS_COLOR_YUV2:
|
|
|
|
+ case OMAP_DSS_COLOR_UYVY:
|
|
|
|
+ accu_table = accu_yuv;
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ BUG();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ accu_val = &accu_table[idx];
|
|
|
|
+
|
|
|
|
+ chroma_hinc = 1024 * orig_width / out_width;
|
|
|
|
+ chroma_vinc = 1024 * orig_height / out_height;
|
|
|
|
+
|
|
|
|
+ h_accu2_0 = (accu_val->h0_m * chroma_hinc / accu_val->h0_n) % 1024;
|
|
|
|
+ h_accu2_1 = (accu_val->h1_m * chroma_hinc / accu_val->h1_n) % 1024;
|
|
|
|
+ v_accu2_0 = (accu_val->v0_m * chroma_vinc / accu_val->v0_n) % 1024;
|
|
|
|
+ v_accu2_1 = (accu_val->v1_m * chroma_vinc / accu_val->v1_n) % 1024;
|
|
|
|
+
|
|
|
|
+ dispc_ovl_set_vid_accu2_0(plane, h_accu2_0, v_accu2_0);
|
|
|
|
+ dispc_ovl_set_vid_accu2_1(plane, h_accu2_1, v_accu2_1);
|
|
|
|
+}
|
|
|
|
+
|
|
static void dispc_ovl_set_scaling_common(enum omap_plane plane,
|
|
static void dispc_ovl_set_scaling_common(enum omap_plane plane,
|
|
u16 orig_width, u16 orig_height,
|
|
u16 orig_width, u16 orig_height,
|
|
u16 out_width, u16 out_height,
|
|
u16 out_width, u16 out_height,
|
|
@@ -1258,6 +1331,10 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
|
|
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8);
|
|
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ dispc_ovl_set_accu_uv(plane, orig_width, orig_height, out_width,
|
|
|
|
+ out_height, ilace, color_mode, rotation);
|
|
|
|
+
|
|
switch (color_mode) {
|
|
switch (color_mode) {
|
|
case OMAP_DSS_COLOR_NV12:
|
|
case OMAP_DSS_COLOR_NV12:
|
|
/* UV is subsampled by 2 vertically*/
|
|
/* UV is subsampled by 2 vertically*/
|
|
@@ -1280,6 +1357,7 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
BUG();
|
|
BUG();
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
|
|
|
|
if (out_width != orig_width)
|
|
if (out_width != orig_width)
|
|
@@ -1297,9 +1375,6 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
|
|
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5);
|
|
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5);
|
|
/* set V scaling */
|
|
/* set V scaling */
|
|
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6);
|
|
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6);
|
|
-
|
|
|
|
- dispc_ovl_set_vid_accu2_0(plane, 0x80, 0);
|
|
|
|
- dispc_ovl_set_vid_accu2_1(plane, 0x80, 0);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
static void dispc_ovl_set_scaling(enum omap_plane plane,
|
|
static void dispc_ovl_set_scaling(enum omap_plane plane,
|
|
@@ -1410,6 +1485,7 @@ static int color_mode_to_bpp(enum omap_color_mode color_mode)
|
|
return 32;
|
|
return 32;
|
|
default:
|
|
default:
|
|
BUG();
|
|
BUG();
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1423,6 +1499,7 @@ static s32 pixinc(int pixels, u8 ps)
|
|
return 1 - (-pixels + 1) * ps;
|
|
return 1 - (-pixels + 1) * ps;
|
|
else
|
|
else
|
|
BUG();
|
|
BUG();
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
|
|
static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
|
|
@@ -1431,7 +1508,7 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
|
|
enum omap_color_mode color_mode, bool fieldmode,
|
|
enum omap_color_mode color_mode, bool fieldmode,
|
|
unsigned int field_offset,
|
|
unsigned int field_offset,
|
|
unsigned *offset0, unsigned *offset1,
|
|
unsigned *offset0, unsigned *offset1,
|
|
- s32 *row_inc, s32 *pix_inc)
|
|
|
|
|
|
+ s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim)
|
|
{
|
|
{
|
|
u8 ps;
|
|
u8 ps;
|
|
|
|
|
|
@@ -1477,10 +1554,10 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
|
|
else
|
|
else
|
|
*offset0 = 0;
|
|
*offset0 = 0;
|
|
|
|
|
|
- *row_inc = pixinc(1 + (screen_width - width) +
|
|
|
|
- (fieldmode ? screen_width : 0),
|
|
|
|
- ps);
|
|
|
|
- *pix_inc = pixinc(1, ps);
|
|
|
|
|
|
+ *row_inc = pixinc(1 +
|
|
|
|
+ (y_predecim * screen_width - x_predecim * width) +
|
|
|
|
+ (fieldmode ? screen_width : 0), ps);
|
|
|
|
+ *pix_inc = pixinc(x_predecim, ps);
|
|
break;
|
|
break;
|
|
|
|
|
|
case OMAP_DSS_ROT_0 + 4:
|
|
case OMAP_DSS_ROT_0 + 4:
|
|
@@ -1498,14 +1575,15 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
|
|
*offset0 = field_offset * screen_width * ps;
|
|
*offset0 = field_offset * screen_width * ps;
|
|
else
|
|
else
|
|
*offset0 = 0;
|
|
*offset0 = 0;
|
|
- *row_inc = pixinc(1 - (screen_width + width) -
|
|
|
|
- (fieldmode ? screen_width : 0),
|
|
|
|
- ps);
|
|
|
|
- *pix_inc = pixinc(1, ps);
|
|
|
|
|
|
+ *row_inc = pixinc(1 -
|
|
|
|
+ (y_predecim * screen_width + x_predecim * width) -
|
|
|
|
+ (fieldmode ? screen_width : 0), ps);
|
|
|
|
+ *pix_inc = pixinc(x_predecim, ps);
|
|
break;
|
|
break;
|
|
|
|
|
|
default:
|
|
default:
|
|
BUG();
|
|
BUG();
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1515,7 +1593,7 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
|
|
enum omap_color_mode color_mode, bool fieldmode,
|
|
enum omap_color_mode color_mode, bool fieldmode,
|
|
unsigned int field_offset,
|
|
unsigned int field_offset,
|
|
unsigned *offset0, unsigned *offset1,
|
|
unsigned *offset0, unsigned *offset1,
|
|
- s32 *row_inc, s32 *pix_inc)
|
|
|
|
|
|
+ s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim)
|
|
{
|
|
{
|
|
u8 ps;
|
|
u8 ps;
|
|
u16 fbw, fbh;
|
|
u16 fbw, fbh;
|
|
@@ -1557,10 +1635,14 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
|
|
*offset0 = *offset1 + field_offset * screen_width * ps;
|
|
*offset0 = *offset1 + field_offset * screen_width * ps;
|
|
else
|
|
else
|
|
*offset0 = *offset1;
|
|
*offset0 = *offset1;
|
|
- *row_inc = pixinc(1 + (screen_width - fbw) +
|
|
|
|
- (fieldmode ? screen_width : 0),
|
|
|
|
- ps);
|
|
|
|
- *pix_inc = pixinc(1, ps);
|
|
|
|
|
|
+ *row_inc = pixinc(1 +
|
|
|
|
+ (y_predecim * screen_width - fbw * x_predecim) +
|
|
|
|
+ (fieldmode ? screen_width : 0), ps);
|
|
|
|
+ if (color_mode == OMAP_DSS_COLOR_YUV2 ||
|
|
|
|
+ color_mode == OMAP_DSS_COLOR_UYVY)
|
|
|
|
+ *pix_inc = pixinc(x_predecim, 2 * ps);
|
|
|
|
+ else
|
|
|
|
+ *pix_inc = pixinc(x_predecim, ps);
|
|
break;
|
|
break;
|
|
case OMAP_DSS_ROT_90:
|
|
case OMAP_DSS_ROT_90:
|
|
*offset1 = screen_width * (fbh - 1) * ps;
|
|
*offset1 = screen_width * (fbh - 1) * ps;
|
|
@@ -1568,9 +1650,9 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
|
|
*offset0 = *offset1 + field_offset * ps;
|
|
*offset0 = *offset1 + field_offset * ps;
|
|
else
|
|
else
|
|
*offset0 = *offset1;
|
|
*offset0 = *offset1;
|
|
- *row_inc = pixinc(screen_width * (fbh - 1) + 1 +
|
|
|
|
- (fieldmode ? 1 : 0), ps);
|
|
|
|
- *pix_inc = pixinc(-screen_width, ps);
|
|
|
|
|
|
+ *row_inc = pixinc(screen_width * (fbh * x_predecim - 1) +
|
|
|
|
+ y_predecim + (fieldmode ? 1 : 0), ps);
|
|
|
|
+ *pix_inc = pixinc(-x_predecim * screen_width, ps);
|
|
break;
|
|
break;
|
|
case OMAP_DSS_ROT_180:
|
|
case OMAP_DSS_ROT_180:
|
|
*offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
|
|
*offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
|
|
@@ -1579,10 +1661,13 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
|
|
else
|
|
else
|
|
*offset0 = *offset1;
|
|
*offset0 = *offset1;
|
|
*row_inc = pixinc(-1 -
|
|
*row_inc = pixinc(-1 -
|
|
- (screen_width - fbw) -
|
|
|
|
- (fieldmode ? screen_width : 0),
|
|
|
|
- ps);
|
|
|
|
- *pix_inc = pixinc(-1, ps);
|
|
|
|
|
|
+ (y_predecim * screen_width - fbw * x_predecim) -
|
|
|
|
+ (fieldmode ? screen_width : 0), ps);
|
|
|
|
+ if (color_mode == OMAP_DSS_COLOR_YUV2 ||
|
|
|
|
+ color_mode == OMAP_DSS_COLOR_UYVY)
|
|
|
|
+ *pix_inc = pixinc(-x_predecim, 2 * ps);
|
|
|
|
+ else
|
|
|
|
+ *pix_inc = pixinc(-x_predecim, ps);
|
|
break;
|
|
break;
|
|
case OMAP_DSS_ROT_270:
|
|
case OMAP_DSS_ROT_270:
|
|
*offset1 = (fbw - 1) * ps;
|
|
*offset1 = (fbw - 1) * ps;
|
|
@@ -1590,9 +1675,9 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
|
|
*offset0 = *offset1 - field_offset * ps;
|
|
*offset0 = *offset1 - field_offset * ps;
|
|
else
|
|
else
|
|
*offset0 = *offset1;
|
|
*offset0 = *offset1;
|
|
- *row_inc = pixinc(-screen_width * (fbh - 1) - 1 -
|
|
|
|
- (fieldmode ? 1 : 0), ps);
|
|
|
|
- *pix_inc = pixinc(screen_width, ps);
|
|
|
|
|
|
+ *row_inc = pixinc(-screen_width * (fbh * x_predecim - 1) -
|
|
|
|
+ y_predecim - (fieldmode ? 1 : 0), ps);
|
|
|
|
+ *pix_inc = pixinc(x_predecim * screen_width, ps);
|
|
break;
|
|
break;
|
|
|
|
|
|
/* mirroring */
|
|
/* mirroring */
|
|
@@ -1602,10 +1687,14 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
|
|
*offset0 = *offset1 + field_offset * screen_width * ps;
|
|
*offset0 = *offset1 + field_offset * screen_width * ps;
|
|
else
|
|
else
|
|
*offset0 = *offset1;
|
|
*offset0 = *offset1;
|
|
- *row_inc = pixinc(screen_width * 2 - 1 +
|
|
|
|
|
|
+ *row_inc = pixinc(y_predecim * screen_width * 2 - 1 +
|
|
(fieldmode ? screen_width : 0),
|
|
(fieldmode ? screen_width : 0),
|
|
ps);
|
|
ps);
|
|
- *pix_inc = pixinc(-1, ps);
|
|
|
|
|
|
+ if (color_mode == OMAP_DSS_COLOR_YUV2 ||
|
|
|
|
+ color_mode == OMAP_DSS_COLOR_UYVY)
|
|
|
|
+ *pix_inc = pixinc(-x_predecim, 2 * ps);
|
|
|
|
+ else
|
|
|
|
+ *pix_inc = pixinc(-x_predecim, ps);
|
|
break;
|
|
break;
|
|
|
|
|
|
case OMAP_DSS_ROT_90 + 4:
|
|
case OMAP_DSS_ROT_90 + 4:
|
|
@@ -1614,10 +1703,10 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
|
|
*offset0 = *offset1 + field_offset * ps;
|
|
*offset0 = *offset1 + field_offset * ps;
|
|
else
|
|
else
|
|
*offset0 = *offset1;
|
|
*offset0 = *offset1;
|
|
- *row_inc = pixinc(-screen_width * (fbh - 1) + 1 +
|
|
|
|
- (fieldmode ? 1 : 0),
|
|
|
|
|
|
+ *row_inc = pixinc(-screen_width * (fbh * x_predecim - 1) +
|
|
|
|
+ y_predecim + (fieldmode ? 1 : 0),
|
|
ps);
|
|
ps);
|
|
- *pix_inc = pixinc(screen_width, ps);
|
|
|
|
|
|
+ *pix_inc = pixinc(x_predecim * screen_width, ps);
|
|
break;
|
|
break;
|
|
|
|
|
|
case OMAP_DSS_ROT_180 + 4:
|
|
case OMAP_DSS_ROT_180 + 4:
|
|
@@ -1626,10 +1715,14 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
|
|
*offset0 = *offset1 - field_offset * screen_width * ps;
|
|
*offset0 = *offset1 - field_offset * screen_width * ps;
|
|
else
|
|
else
|
|
*offset0 = *offset1;
|
|
*offset0 = *offset1;
|
|
- *row_inc = pixinc(1 - screen_width * 2 -
|
|
|
|
|
|
+ *row_inc = pixinc(1 - y_predecim * screen_width * 2 -
|
|
(fieldmode ? screen_width : 0),
|
|
(fieldmode ? screen_width : 0),
|
|
ps);
|
|
ps);
|
|
- *pix_inc = pixinc(1, ps);
|
|
|
|
|
|
+ if (color_mode == OMAP_DSS_COLOR_YUV2 ||
|
|
|
|
+ color_mode == OMAP_DSS_COLOR_UYVY)
|
|
|
|
+ *pix_inc = pixinc(x_predecim, 2 * ps);
|
|
|
|
+ else
|
|
|
|
+ *pix_inc = pixinc(x_predecim, ps);
|
|
break;
|
|
break;
|
|
|
|
|
|
case OMAP_DSS_ROT_270 + 4:
|
|
case OMAP_DSS_ROT_270 + 4:
|
|
@@ -1638,34 +1731,130 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
|
|
*offset0 = *offset1 - field_offset * ps;
|
|
*offset0 = *offset1 - field_offset * ps;
|
|
else
|
|
else
|
|
*offset0 = *offset1;
|
|
*offset0 = *offset1;
|
|
- *row_inc = pixinc(screen_width * (fbh - 1) - 1 -
|
|
|
|
- (fieldmode ? 1 : 0),
|
|
|
|
|
|
+ *row_inc = pixinc(screen_width * (fbh * x_predecim - 1) -
|
|
|
|
+ y_predecim - (fieldmode ? 1 : 0),
|
|
ps);
|
|
ps);
|
|
- *pix_inc = pixinc(-screen_width, ps);
|
|
|
|
|
|
+ *pix_inc = pixinc(-x_predecim * screen_width, ps);
|
|
break;
|
|
break;
|
|
|
|
|
|
default:
|
|
default:
|
|
BUG();
|
|
BUG();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void calc_tiler_rotation_offset(u16 screen_width, u16 width,
|
|
|
|
+ enum omap_color_mode color_mode, bool fieldmode,
|
|
|
|
+ unsigned int field_offset, unsigned *offset0, unsigned *offset1,
|
|
|
|
+ s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim)
|
|
|
|
+{
|
|
|
|
+ u8 ps;
|
|
|
|
+
|
|
|
|
+ switch (color_mode) {
|
|
|
|
+ case OMAP_DSS_COLOR_CLUT1:
|
|
|
|
+ case OMAP_DSS_COLOR_CLUT2:
|
|
|
|
+ case OMAP_DSS_COLOR_CLUT4:
|
|
|
|
+ case OMAP_DSS_COLOR_CLUT8:
|
|
|
|
+ BUG();
|
|
|
|
+ return;
|
|
|
|
+ default:
|
|
|
|
+ ps = color_mode_to_bpp(color_mode) / 8;
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ DSSDBG("scrw %d, width %d\n", screen_width, width);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * field 0 = even field = bottom field
|
|
|
|
+ * field 1 = odd field = top field
|
|
|
|
+ */
|
|
|
|
+ *offset1 = 0;
|
|
|
|
+ if (field_offset)
|
|
|
|
+ *offset0 = *offset1 + field_offset * screen_width * ps;
|
|
|
|
+ else
|
|
|
|
+ *offset0 = *offset1;
|
|
|
|
+ *row_inc = pixinc(1 + (y_predecim * screen_width - width * x_predecim) +
|
|
|
|
+ (fieldmode ? screen_width : 0), ps);
|
|
|
|
+ if (color_mode == OMAP_DSS_COLOR_YUV2 ||
|
|
|
|
+ color_mode == OMAP_DSS_COLOR_UYVY)
|
|
|
|
+ *pix_inc = pixinc(x_predecim, 2 * ps);
|
|
|
|
+ else
|
|
|
|
+ *pix_inc = pixinc(x_predecim, ps);
|
|
}
|
|
}
|
|
|
|
|
|
-static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width,
|
|
|
|
|
|
+/*
|
|
|
|
+ * This function is used to avoid synclosts in OMAP3, because of some
|
|
|
|
+ * undocumented horizontal position and timing related limitations.
|
|
|
|
+ */
|
|
|
|
+static int check_horiz_timing_omap3(enum omap_channel channel,
|
|
|
|
+ const struct omap_video_timings *t, u16 pos_x,
|
|
|
|
+ u16 width, u16 height, u16 out_width, u16 out_height)
|
|
|
|
+{
|
|
|
|
+ int DS = DIV_ROUND_UP(height, out_height);
|
|
|
|
+ unsigned long nonactive, lclk, pclk;
|
|
|
|
+ static const u8 limits[3] = { 8, 10, 20 };
|
|
|
|
+ u64 val, blank;
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width;
|
|
|
|
+ pclk = dispc_mgr_pclk_rate(channel);
|
|
|
|
+ if (dispc_mgr_is_lcd(channel))
|
|
|
|
+ lclk = dispc_mgr_lclk_rate(channel);
|
|
|
|
+ else
|
|
|
|
+ lclk = dispc_fclk_rate();
|
|
|
|
+
|
|
|
|
+ i = 0;
|
|
|
|
+ if (out_height < height)
|
|
|
|
+ i++;
|
|
|
|
+ if (out_width < width)
|
|
|
|
+ i++;
|
|
|
|
+ blank = div_u64((u64)(t->hbp + t->hsw + t->hfp) * lclk, pclk);
|
|
|
|
+ DSSDBG("blanking period + ppl = %llu (limit = %u)\n", blank, limits[i]);
|
|
|
|
+ if (blank <= limits[i])
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Pixel data should be prepared before visible display point starts.
|
|
|
|
+ * So, atleast DS-2 lines must have already been fetched by DISPC
|
|
|
|
+ * during nonactive - pos_x period.
|
|
|
|
+ */
|
|
|
|
+ val = div_u64((u64)(nonactive - pos_x) * lclk, pclk);
|
|
|
|
+ DSSDBG("(nonactive - pos_x) * pcd = %llu max(0, DS - 2) * width = %d\n",
|
|
|
|
+ val, max(0, DS - 2) * width);
|
|
|
|
+ if (val < max(0, DS - 2) * width)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * All lines need to be refilled during the nonactive period of which
|
|
|
|
+ * only one line can be loaded during the active period. So, atleast
|
|
|
|
+ * DS - 1 lines should be loaded during nonactive period.
|
|
|
|
+ */
|
|
|
|
+ val = div_u64((u64)nonactive * lclk, pclk);
|
|
|
|
+ DSSDBG("nonactive * pcd = %llu, max(0, DS - 1) * width = %d\n",
|
|
|
|
+ val, max(0, DS - 1) * width);
|
|
|
|
+ if (val < max(0, DS - 1) * width)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static unsigned long calc_core_clk_five_taps(enum omap_channel channel,
|
|
|
|
+ const struct omap_video_timings *mgr_timings, u16 width,
|
|
u16 height, u16 out_width, u16 out_height,
|
|
u16 height, u16 out_width, u16 out_height,
|
|
enum omap_color_mode color_mode)
|
|
enum omap_color_mode color_mode)
|
|
{
|
|
{
|
|
- u32 fclk = 0;
|
|
|
|
|
|
+ u32 core_clk = 0;
|
|
u64 tmp, pclk = dispc_mgr_pclk_rate(channel);
|
|
u64 tmp, pclk = dispc_mgr_pclk_rate(channel);
|
|
|
|
|
|
if (height <= out_height && width <= out_width)
|
|
if (height <= out_height && width <= out_width)
|
|
return (unsigned long) pclk;
|
|
return (unsigned long) pclk;
|
|
|
|
|
|
if (height > out_height) {
|
|
if (height > out_height) {
|
|
- struct omap_dss_device *dssdev = dispc_mgr_get_device(channel);
|
|
|
|
- unsigned int ppl = dssdev->panel.timings.x_res;
|
|
|
|
|
|
+ unsigned int ppl = mgr_timings->x_res;
|
|
|
|
|
|
tmp = pclk * height * out_width;
|
|
tmp = pclk * height * out_width;
|
|
do_div(tmp, 2 * out_height * ppl);
|
|
do_div(tmp, 2 * out_height * ppl);
|
|
- fclk = tmp;
|
|
|
|
|
|
+ core_clk = tmp;
|
|
|
|
|
|
if (height > 2 * out_height) {
|
|
if (height > 2 * out_height) {
|
|
if (ppl == out_width)
|
|
if (ppl == out_width)
|
|
@@ -1673,23 +1862,23 @@ static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width,
|
|
|
|
|
|
tmp = pclk * (height - 2 * out_height) * out_width;
|
|
tmp = pclk * (height - 2 * out_height) * out_width;
|
|
do_div(tmp, 2 * out_height * (ppl - out_width));
|
|
do_div(tmp, 2 * out_height * (ppl - out_width));
|
|
- fclk = max(fclk, (u32) tmp);
|
|
|
|
|
|
+ core_clk = max_t(u32, core_clk, tmp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (width > out_width) {
|
|
if (width > out_width) {
|
|
tmp = pclk * width;
|
|
tmp = pclk * width;
|
|
do_div(tmp, out_width);
|
|
do_div(tmp, out_width);
|
|
- fclk = max(fclk, (u32) tmp);
|
|
|
|
|
|
+ core_clk = max_t(u32, core_clk, tmp);
|
|
|
|
|
|
if (color_mode == OMAP_DSS_COLOR_RGB24U)
|
|
if (color_mode == OMAP_DSS_COLOR_RGB24U)
|
|
- fclk <<= 1;
|
|
|
|
|
|
+ core_clk <<= 1;
|
|
}
|
|
}
|
|
|
|
|
|
- return fclk;
|
|
|
|
|
|
+ return core_clk;
|
|
}
|
|
}
|
|
|
|
|
|
-static unsigned long calc_fclk(enum omap_channel channel, u16 width,
|
|
|
|
|
|
+static unsigned long calc_core_clk(enum omap_channel channel, u16 width,
|
|
u16 height, u16 out_width, u16 out_height)
|
|
u16 height, u16 out_width, u16 out_height)
|
|
{
|
|
{
|
|
unsigned int hf, vf;
|
|
unsigned int hf, vf;
|
|
@@ -1730,15 +1919,20 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
|
|
}
|
|
}
|
|
|
|
|
|
static int dispc_ovl_calc_scaling(enum omap_plane plane,
|
|
static int dispc_ovl_calc_scaling(enum omap_plane plane,
|
|
- enum omap_channel channel, u16 width, u16 height,
|
|
|
|
- u16 out_width, u16 out_height,
|
|
|
|
- enum omap_color_mode color_mode, bool *five_taps)
|
|
|
|
|
|
+ enum omap_channel channel,
|
|
|
|
+ const struct omap_video_timings *mgr_timings,
|
|
|
|
+ u16 width, u16 height, u16 out_width, u16 out_height,
|
|
|
|
+ enum omap_color_mode color_mode, bool *five_taps,
|
|
|
|
+ int *x_predecim, int *y_predecim, u16 pos_x)
|
|
{
|
|
{
|
|
struct omap_overlay *ovl = omap_dss_get_overlay(plane);
|
|
struct omap_overlay *ovl = omap_dss_get_overlay(plane);
|
|
const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
|
|
const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
|
|
const int maxsinglelinewidth =
|
|
const int maxsinglelinewidth =
|
|
dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
|
|
dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
|
|
- unsigned long fclk = 0;
|
|
|
|
|
|
+ const int max_decim_limit = 16;
|
|
|
|
+ unsigned long core_clk = 0;
|
|
|
|
+ int decim_x, decim_y, error, min_factor;
|
|
|
|
+ u16 in_width, in_height, in_width_max = 0;
|
|
|
|
|
|
if (width == out_width && height == out_height)
|
|
if (width == out_width && height == out_height)
|
|
return 0;
|
|
return 0;
|
|
@@ -1746,64 +1940,154 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
|
|
if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
|
|
if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- if (out_width < width / maxdownscale ||
|
|
|
|
- out_width > width * 8)
|
|
|
|
|
|
+ *x_predecim = max_decim_limit;
|
|
|
|
+ *y_predecim = max_decim_limit;
|
|
|
|
+
|
|
|
|
+ if (color_mode == OMAP_DSS_COLOR_CLUT1 ||
|
|
|
|
+ color_mode == OMAP_DSS_COLOR_CLUT2 ||
|
|
|
|
+ color_mode == OMAP_DSS_COLOR_CLUT4 ||
|
|
|
|
+ color_mode == OMAP_DSS_COLOR_CLUT8) {
|
|
|
|
+ *x_predecim = 1;
|
|
|
|
+ *y_predecim = 1;
|
|
|
|
+ *five_taps = false;
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale);
|
|
|
|
+ decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale);
|
|
|
|
+
|
|
|
|
+ min_factor = min(decim_x, decim_y);
|
|
|
|
+
|
|
|
|
+ if (decim_x > *x_predecim || out_width > width * 8)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- if (out_height < height / maxdownscale ||
|
|
|
|
- out_height > height * 8)
|
|
|
|
|
|
+ if (decim_y > *y_predecim || out_height > height * 8)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
if (cpu_is_omap24xx()) {
|
|
if (cpu_is_omap24xx()) {
|
|
- if (width > maxsinglelinewidth)
|
|
|
|
- DSSERR("Cannot scale max input width exceeded");
|
|
|
|
*five_taps = false;
|
|
*five_taps = false;
|
|
- fclk = calc_fclk(channel, width, height, out_width,
|
|
|
|
- out_height);
|
|
|
|
|
|
+
|
|
|
|
+ do {
|
|
|
|
+ in_height = DIV_ROUND_UP(height, decim_y);
|
|
|
|
+ in_width = DIV_ROUND_UP(width, decim_x);
|
|
|
|
+ core_clk = calc_core_clk(channel, in_width, in_height,
|
|
|
|
+ out_width, out_height);
|
|
|
|
+ error = (in_width > maxsinglelinewidth || !core_clk ||
|
|
|
|
+ core_clk > dispc_core_clk_rate());
|
|
|
|
+ if (error) {
|
|
|
|
+ if (decim_x == decim_y) {
|
|
|
|
+ decim_x = min_factor;
|
|
|
|
+ decim_y++;
|
|
|
|
+ } else {
|
|
|
|
+ swap(decim_x, decim_y);
|
|
|
|
+ if (decim_x < decim_y)
|
|
|
|
+ decim_x++;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } while (decim_x <= *x_predecim && decim_y <= *y_predecim &&
|
|
|
|
+ error);
|
|
|
|
+
|
|
|
|
+ if (in_width > maxsinglelinewidth) {
|
|
|
|
+ DSSERR("Cannot scale max input width exceeded");
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
} else if (cpu_is_omap34xx()) {
|
|
} else if (cpu_is_omap34xx()) {
|
|
- if (width > (maxsinglelinewidth * 2)) {
|
|
|
|
|
|
+
|
|
|
|
+ do {
|
|
|
|
+ in_height = DIV_ROUND_UP(height, decim_y);
|
|
|
|
+ in_width = DIV_ROUND_UP(width, decim_x);
|
|
|
|
+ core_clk = calc_core_clk_five_taps(channel, mgr_timings,
|
|
|
|
+ in_width, in_height, out_width, out_height,
|
|
|
|
+ color_mode);
|
|
|
|
+
|
|
|
|
+ error = check_horiz_timing_omap3(channel, mgr_timings,
|
|
|
|
+ pos_x, in_width, in_height, out_width,
|
|
|
|
+ out_height);
|
|
|
|
+
|
|
|
|
+ if (in_width > maxsinglelinewidth)
|
|
|
|
+ if (in_height > out_height &&
|
|
|
|
+ in_height < out_height * 2)
|
|
|
|
+ *five_taps = false;
|
|
|
|
+ if (!*five_taps)
|
|
|
|
+ core_clk = calc_core_clk(channel, in_width,
|
|
|
|
+ in_height, out_width, out_height);
|
|
|
|
+ error = (error || in_width > maxsinglelinewidth * 2 ||
|
|
|
|
+ (in_width > maxsinglelinewidth && *five_taps) ||
|
|
|
|
+ !core_clk || core_clk > dispc_core_clk_rate());
|
|
|
|
+ if (error) {
|
|
|
|
+ if (decim_x == decim_y) {
|
|
|
|
+ decim_x = min_factor;
|
|
|
|
+ decim_y++;
|
|
|
|
+ } else {
|
|
|
|
+ swap(decim_x, decim_y);
|
|
|
|
+ if (decim_x < decim_y)
|
|
|
|
+ decim_x++;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } while (decim_x <= *x_predecim && decim_y <= *y_predecim
|
|
|
|
+ && error);
|
|
|
|
+
|
|
|
|
+ if (check_horiz_timing_omap3(channel, mgr_timings, pos_x, width,
|
|
|
|
+ height, out_width, out_height)){
|
|
|
|
+ DSSERR("horizontal timing too tight\n");
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (in_width > (maxsinglelinewidth * 2)) {
|
|
DSSERR("Cannot setup scaling");
|
|
DSSERR("Cannot setup scaling");
|
|
DSSERR("width exceeds maximum width possible");
|
|
DSSERR("width exceeds maximum width possible");
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
- fclk = calc_fclk_five_taps(channel, width, height, out_width,
|
|
|
|
- out_height, color_mode);
|
|
|
|
- if (width > maxsinglelinewidth) {
|
|
|
|
- if (height > out_height && height < out_height * 2)
|
|
|
|
- *five_taps = false;
|
|
|
|
- else {
|
|
|
|
- DSSERR("cannot setup scaling with five taps");
|
|
|
|
- return -EINVAL;
|
|
|
|
- }
|
|
|
|
|
|
+
|
|
|
|
+ if (in_width > maxsinglelinewidth && *five_taps) {
|
|
|
|
+ DSSERR("cannot setup scaling with five taps");
|
|
|
|
+ return -EINVAL;
|
|
}
|
|
}
|
|
- if (!*five_taps)
|
|
|
|
- fclk = calc_fclk(channel, width, height, out_width,
|
|
|
|
- out_height);
|
|
|
|
} else {
|
|
} else {
|
|
- if (width > maxsinglelinewidth) {
|
|
|
|
|
|
+ int decim_x_min = decim_x;
|
|
|
|
+ in_height = DIV_ROUND_UP(height, decim_y);
|
|
|
|
+ in_width_max = dispc_core_clk_rate() /
|
|
|
|
+ DIV_ROUND_UP(dispc_mgr_pclk_rate(channel),
|
|
|
|
+ out_width);
|
|
|
|
+ decim_x = DIV_ROUND_UP(width, in_width_max);
|
|
|
|
+
|
|
|
|
+ decim_x = decim_x > decim_x_min ? decim_x : decim_x_min;
|
|
|
|
+ if (decim_x > *x_predecim)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ do {
|
|
|
|
+ in_width = DIV_ROUND_UP(width, decim_x);
|
|
|
|
+ } while (decim_x <= *x_predecim &&
|
|
|
|
+ in_width > maxsinglelinewidth && decim_x++);
|
|
|
|
+
|
|
|
|
+ if (in_width > maxsinglelinewidth) {
|
|
DSSERR("Cannot scale width exceeds max line width");
|
|
DSSERR("Cannot scale width exceeds max line width");
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
- fclk = calc_fclk(channel, width, height, out_width,
|
|
|
|
- out_height);
|
|
|
|
|
|
+
|
|
|
|
+ core_clk = calc_core_clk(channel, in_width, in_height,
|
|
|
|
+ out_width, out_height);
|
|
}
|
|
}
|
|
|
|
|
|
- DSSDBG("required fclk rate = %lu Hz\n", fclk);
|
|
|
|
- DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
|
|
|
|
|
|
+ DSSDBG("required core clk rate = %lu Hz\n", core_clk);
|
|
|
|
+ DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate());
|
|
|
|
|
|
- if (!fclk || fclk > dispc_fclk_rate()) {
|
|
|
|
|
|
+ if (!core_clk || core_clk > dispc_core_clk_rate()) {
|
|
DSSERR("failed to set up scaling, "
|
|
DSSERR("failed to set up scaling, "
|
|
- "required fclk rate = %lu Hz, "
|
|
|
|
- "current fclk rate = %lu Hz\n",
|
|
|
|
- fclk, dispc_fclk_rate());
|
|
|
|
|
|
+ "required core clk rate = %lu Hz, "
|
|
|
|
+ "current core clk rate = %lu Hz\n",
|
|
|
|
+ core_clk, dispc_core_clk_rate());
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ *x_predecim = decim_x;
|
|
|
|
+ *y_predecim = decim_y;
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
|
|
int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
|
|
- bool ilace, bool replication)
|
|
|
|
|
|
+ bool ilace, bool replication,
|
|
|
|
+ const struct omap_video_timings *mgr_timings)
|
|
{
|
|
{
|
|
struct omap_overlay *ovl = omap_dss_get_overlay(plane);
|
|
struct omap_overlay *ovl = omap_dss_get_overlay(plane);
|
|
bool five_taps = true;
|
|
bool five_taps = true;
|
|
@@ -1814,8 +2098,11 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
|
|
s32 pix_inc;
|
|
s32 pix_inc;
|
|
u16 frame_height = oi->height;
|
|
u16 frame_height = oi->height;
|
|
unsigned int field_offset = 0;
|
|
unsigned int field_offset = 0;
|
|
- u16 outw, outh;
|
|
|
|
|
|
+ u16 in_height = oi->height;
|
|
|
|
+ u16 in_width = oi->width;
|
|
|
|
+ u16 out_width, out_height;
|
|
enum omap_channel channel;
|
|
enum omap_channel channel;
|
|
|
|
+ int x_predecim = 1, y_predecim = 1;
|
|
|
|
|
|
channel = dispc_ovl_get_channel_out(plane);
|
|
channel = dispc_ovl_get_channel_out(plane);
|
|
|
|
|
|
@@ -1829,32 +2116,35 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
|
|
if (oi->paddr == 0)
|
|
if (oi->paddr == 0)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- outw = oi->out_width == 0 ? oi->width : oi->out_width;
|
|
|
|
- outh = oi->out_height == 0 ? oi->height : oi->out_height;
|
|
|
|
|
|
+ out_width = oi->out_width == 0 ? oi->width : oi->out_width;
|
|
|
|
+ out_height = oi->out_height == 0 ? oi->height : oi->out_height;
|
|
|
|
|
|
- if (ilace && oi->height == outh)
|
|
|
|
|
|
+ if (ilace && oi->height == out_height)
|
|
fieldmode = 1;
|
|
fieldmode = 1;
|
|
|
|
|
|
if (ilace) {
|
|
if (ilace) {
|
|
if (fieldmode)
|
|
if (fieldmode)
|
|
- oi->height /= 2;
|
|
|
|
|
|
+ in_height /= 2;
|
|
oi->pos_y /= 2;
|
|
oi->pos_y /= 2;
|
|
- outh /= 2;
|
|
|
|
|
|
+ out_height /= 2;
|
|
|
|
|
|
DSSDBG("adjusting for ilace: height %d, pos_y %d, "
|
|
DSSDBG("adjusting for ilace: height %d, pos_y %d, "
|
|
"out_height %d\n",
|
|
"out_height %d\n",
|
|
- oi->height, oi->pos_y, outh);
|
|
|
|
|
|
+ in_height, oi->pos_y, out_height);
|
|
}
|
|
}
|
|
|
|
|
|
if (!dss_feat_color_mode_supported(plane, oi->color_mode))
|
|
if (!dss_feat_color_mode_supported(plane, oi->color_mode))
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- r = dispc_ovl_calc_scaling(plane, channel, oi->width, oi->height,
|
|
|
|
- outw, outh, oi->color_mode,
|
|
|
|
- &five_taps);
|
|
|
|
|
|
+ r = dispc_ovl_calc_scaling(plane, channel, mgr_timings, in_width,
|
|
|
|
+ in_height, out_width, out_height, oi->color_mode,
|
|
|
|
+ &five_taps, &x_predecim, &y_predecim, oi->pos_x);
|
|
if (r)
|
|
if (r)
|
|
return r;
|
|
return r;
|
|
|
|
|
|
|
|
+ in_width = DIV_ROUND_UP(in_width, x_predecim);
|
|
|
|
+ in_height = DIV_ROUND_UP(in_height, y_predecim);
|
|
|
|
+
|
|
if (oi->color_mode == OMAP_DSS_COLOR_YUV2 ||
|
|
if (oi->color_mode == OMAP_DSS_COLOR_YUV2 ||
|
|
oi->color_mode == OMAP_DSS_COLOR_UYVY ||
|
|
oi->color_mode == OMAP_DSS_COLOR_UYVY ||
|
|
oi->color_mode == OMAP_DSS_COLOR_NV12)
|
|
oi->color_mode == OMAP_DSS_COLOR_NV12)
|
|
@@ -1868,32 +2158,46 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
|
|
* so the integer part must be added to the base address of the
|
|
* so the integer part must be added to the base address of the
|
|
* bottom field.
|
|
* bottom field.
|
|
*/
|
|
*/
|
|
- if (!oi->height || oi->height == outh)
|
|
|
|
|
|
+ if (!in_height || in_height == out_height)
|
|
field_offset = 0;
|
|
field_offset = 0;
|
|
else
|
|
else
|
|
- field_offset = oi->height / outh / 2;
|
|
|
|
|
|
+ field_offset = in_height / out_height / 2;
|
|
}
|
|
}
|
|
|
|
|
|
/* Fields are independent but interleaved in memory. */
|
|
/* Fields are independent but interleaved in memory. */
|
|
if (fieldmode)
|
|
if (fieldmode)
|
|
field_offset = 1;
|
|
field_offset = 1;
|
|
|
|
|
|
- if (oi->rotation_type == OMAP_DSS_ROT_DMA)
|
|
|
|
|
|
+ offset0 = 0;
|
|
|
|
+ offset1 = 0;
|
|
|
|
+ row_inc = 0;
|
|
|
|
+ pix_inc = 0;
|
|
|
|
+
|
|
|
|
+ if (oi->rotation_type == OMAP_DSS_ROT_TILER)
|
|
|
|
+ calc_tiler_rotation_offset(oi->screen_width, in_width,
|
|
|
|
+ oi->color_mode, fieldmode, field_offset,
|
|
|
|
+ &offset0, &offset1, &row_inc, &pix_inc,
|
|
|
|
+ x_predecim, y_predecim);
|
|
|
|
+ else if (oi->rotation_type == OMAP_DSS_ROT_DMA)
|
|
calc_dma_rotation_offset(oi->rotation, oi->mirror,
|
|
calc_dma_rotation_offset(oi->rotation, oi->mirror,
|
|
- oi->screen_width, oi->width, frame_height,
|
|
|
|
|
|
+ oi->screen_width, in_width, frame_height,
|
|
oi->color_mode, fieldmode, field_offset,
|
|
oi->color_mode, fieldmode, field_offset,
|
|
- &offset0, &offset1, &row_inc, &pix_inc);
|
|
|
|
|
|
+ &offset0, &offset1, &row_inc, &pix_inc,
|
|
|
|
+ x_predecim, y_predecim);
|
|
else
|
|
else
|
|
calc_vrfb_rotation_offset(oi->rotation, oi->mirror,
|
|
calc_vrfb_rotation_offset(oi->rotation, oi->mirror,
|
|
- oi->screen_width, oi->width, frame_height,
|
|
|
|
|
|
+ oi->screen_width, in_width, frame_height,
|
|
oi->color_mode, fieldmode, field_offset,
|
|
oi->color_mode, fieldmode, field_offset,
|
|
- &offset0, &offset1, &row_inc, &pix_inc);
|
|
|
|
|
|
+ &offset0, &offset1, &row_inc, &pix_inc,
|
|
|
|
+ x_predecim, y_predecim);
|
|
|
|
|
|
DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
|
|
DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
|
|
offset0, offset1, row_inc, pix_inc);
|
|
offset0, offset1, row_inc, pix_inc);
|
|
|
|
|
|
dispc_ovl_set_color_mode(plane, oi->color_mode);
|
|
dispc_ovl_set_color_mode(plane, oi->color_mode);
|
|
|
|
|
|
|
|
+ dispc_ovl_configure_burst_type(plane, oi->rotation_type);
|
|
|
|
+
|
|
dispc_ovl_set_ba0(plane, oi->paddr + offset0);
|
|
dispc_ovl_set_ba0(plane, oi->paddr + offset0);
|
|
dispc_ovl_set_ba1(plane, oi->paddr + offset1);
|
|
dispc_ovl_set_ba1(plane, oi->paddr + offset1);
|
|
|
|
|
|
@@ -1906,19 +2210,18 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
|
|
dispc_ovl_set_row_inc(plane, row_inc);
|
|
dispc_ovl_set_row_inc(plane, row_inc);
|
|
dispc_ovl_set_pix_inc(plane, pix_inc);
|
|
dispc_ovl_set_pix_inc(plane, pix_inc);
|
|
|
|
|
|
- DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, oi->width,
|
|
|
|
- oi->height, outw, outh);
|
|
|
|
|
|
+ DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, in_width,
|
|
|
|
+ in_height, out_width, out_height);
|
|
|
|
|
|
dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y);
|
|
dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y);
|
|
|
|
|
|
- dispc_ovl_set_pic_size(plane, oi->width, oi->height);
|
|
|
|
|
|
+ dispc_ovl_set_pic_size(plane, in_width, in_height);
|
|
|
|
|
|
if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) {
|
|
if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) {
|
|
- dispc_ovl_set_scaling(plane, oi->width, oi->height,
|
|
|
|
- outw, outh,
|
|
|
|
- ilace, five_taps, fieldmode,
|
|
|
|
|
|
+ dispc_ovl_set_scaling(plane, in_width, in_height, out_width,
|
|
|
|
+ out_height, ilace, five_taps, fieldmode,
|
|
oi->color_mode, oi->rotation);
|
|
oi->color_mode, oi->rotation);
|
|
- dispc_ovl_set_vid_size(plane, outw, outh);
|
|
|
|
|
|
+ dispc_ovl_set_vid_size(plane, out_width, out_height);
|
|
dispc_ovl_set_vid_color_conv(plane, cconv);
|
|
dispc_ovl_set_vid_color_conv(plane, cconv);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2087,8 +2390,10 @@ bool dispc_mgr_is_enabled(enum omap_channel channel)
|
|
return !!REG_GET(DISPC_CONTROL, 1, 1);
|
|
return !!REG_GET(DISPC_CONTROL, 1, 1);
|
|
else if (channel == OMAP_DSS_CHANNEL_LCD2)
|
|
else if (channel == OMAP_DSS_CHANNEL_LCD2)
|
|
return !!REG_GET(DISPC_CONTROL2, 0, 0);
|
|
return !!REG_GET(DISPC_CONTROL2, 0, 0);
|
|
- else
|
|
|
|
|
|
+ else {
|
|
BUG();
|
|
BUG();
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
void dispc_mgr_enable(enum omap_channel channel, bool enable)
|
|
void dispc_mgr_enable(enum omap_channel channel, bool enable)
|
|
@@ -2285,6 +2590,12 @@ void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable)
|
|
REG_FLD_MOD(DISPC_CONTROL, enable, 11, 11);
|
|
REG_FLD_MOD(DISPC_CONTROL, enable, 11, 11);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static bool _dispc_mgr_size_ok(u16 width, u16 height)
|
|
|
|
+{
|
|
|
|
+ return width <= dss_feat_get_param_max(FEAT_PARAM_MGR_WIDTH) &&
|
|
|
|
+ height <= dss_feat_get_param_max(FEAT_PARAM_MGR_HEIGHT);
|
|
|
|
+}
|
|
|
|
+
|
|
static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
|
|
static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
|
|
int vsw, int vfp, int vbp)
|
|
int vsw, int vfp, int vbp)
|
|
{
|
|
{
|
|
@@ -2309,11 +2620,20 @@ static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
-bool dispc_lcd_timings_ok(struct omap_video_timings *timings)
|
|
|
|
|
|
+bool dispc_mgr_timings_ok(enum omap_channel channel,
|
|
|
|
+ const struct omap_video_timings *timings)
|
|
{
|
|
{
|
|
- return _dispc_lcd_timings_ok(timings->hsw, timings->hfp,
|
|
|
|
- timings->hbp, timings->vsw,
|
|
|
|
- timings->vfp, timings->vbp);
|
|
|
|
|
|
+ bool timings_ok;
|
|
|
|
+
|
|
|
|
+ timings_ok = _dispc_mgr_size_ok(timings->x_res, timings->y_res);
|
|
|
|
+
|
|
|
|
+ if (dispc_mgr_is_lcd(channel))
|
|
|
|
+ timings_ok = timings_ok && _dispc_lcd_timings_ok(timings->hsw,
|
|
|
|
+ timings->hfp, timings->hbp,
|
|
|
|
+ timings->vsw, timings->vfp,
|
|
|
|
+ timings->vbp);
|
|
|
|
+
|
|
|
|
+ return timings_ok;
|
|
}
|
|
}
|
|
|
|
|
|
static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
|
|
static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
|
|
@@ -2340,37 +2660,45 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
|
|
}
|
|
}
|
|
|
|
|
|
/* change name to mode? */
|
|
/* change name to mode? */
|
|
-void dispc_mgr_set_lcd_timings(enum omap_channel channel,
|
|
|
|
|
|
+void dispc_mgr_set_timings(enum omap_channel channel,
|
|
struct omap_video_timings *timings)
|
|
struct omap_video_timings *timings)
|
|
{
|
|
{
|
|
unsigned xtot, ytot;
|
|
unsigned xtot, ytot;
|
|
unsigned long ht, vt;
|
|
unsigned long ht, vt;
|
|
|
|
+ struct omap_video_timings t = *timings;
|
|
|
|
+
|
|
|
|
+ DSSDBG("channel %d xres %u yres %u\n", channel, t.x_res, t.y_res);
|
|
|
|
|
|
- if (!_dispc_lcd_timings_ok(timings->hsw, timings->hfp,
|
|
|
|
- timings->hbp, timings->vsw,
|
|
|
|
- timings->vfp, timings->vbp))
|
|
|
|
|
|
+ if (!dispc_mgr_timings_ok(channel, &t)) {
|
|
BUG();
|
|
BUG();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (dispc_mgr_is_lcd(channel)) {
|
|
|
|
+ _dispc_mgr_set_lcd_timings(channel, t.hsw, t.hfp, t.hbp, t.vsw,
|
|
|
|
+ t.vfp, t.vbp);
|
|
|
|
+
|
|
|
|
+ xtot = t.x_res + t.hfp + t.hsw + t.hbp;
|
|
|
|
+ ytot = t.y_res + t.vfp + t.vsw + t.vbp;
|
|
|
|
|
|
- _dispc_mgr_set_lcd_timings(channel, timings->hsw, timings->hfp,
|
|
|
|
- timings->hbp, timings->vsw, timings->vfp,
|
|
|
|
- timings->vbp);
|
|
|
|
|
|
+ ht = (timings->pixel_clock * 1000) / xtot;
|
|
|
|
+ vt = (timings->pixel_clock * 1000) / xtot / ytot;
|
|
|
|
|
|
- dispc_mgr_set_lcd_size(channel, timings->x_res, timings->y_res);
|
|
|
|
|
|
+ DSSDBG("pck %u\n", timings->pixel_clock);
|
|
|
|
+ DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n",
|
|
|
|
+ t.hsw, t.hfp, t.hbp, t.vsw, t.vfp, t.vbp);
|
|
|
|
|
|
- xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp;
|
|
|
|
- ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp;
|
|
|
|
|
|
+ DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt);
|
|
|
|
+ } else {
|
|
|
|
+ enum dss_hdmi_venc_clk_source_select source;
|
|
|
|
|
|
- ht = (timings->pixel_clock * 1000) / xtot;
|
|
|
|
- vt = (timings->pixel_clock * 1000) / xtot / ytot;
|
|
|
|
|
|
+ source = dss_get_hdmi_venc_clk_source();
|
|
|
|
|
|
- DSSDBG("channel %d xres %u yres %u\n", channel, timings->x_res,
|
|
|
|
- timings->y_res);
|
|
|
|
- DSSDBG("pck %u\n", timings->pixel_clock);
|
|
|
|
- DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n",
|
|
|
|
- timings->hsw, timings->hfp, timings->hbp,
|
|
|
|
- timings->vsw, timings->vfp, timings->vbp);
|
|
|
|
|
|
+ if (source == DSS_VENC_TV_CLK)
|
|
|
|
+ t.y_res /= 2;
|
|
|
|
+ }
|
|
|
|
|
|
- DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt);
|
|
|
|
|
|
+ dispc_mgr_set_size(channel, t.x_res, t.y_res);
|
|
}
|
|
}
|
|
|
|
|
|
static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
|
|
static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
|
|
@@ -2411,6 +2739,7 @@ unsigned long dispc_fclk_rate(void)
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
BUG();
|
|
BUG();
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
return r;
|
|
return r;
|
|
@@ -2441,6 +2770,7 @@ unsigned long dispc_mgr_lclk_rate(enum omap_channel channel)
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
BUG();
|
|
BUG();
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
return r / lcd;
|
|
return r / lcd;
|
|
@@ -2462,20 +2792,35 @@ unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
|
|
|
|
|
|
return r / pcd;
|
|
return r / pcd;
|
|
} else {
|
|
} else {
|
|
- struct omap_dss_device *dssdev =
|
|
|
|
- dispc_mgr_get_device(channel);
|
|
|
|
|
|
+ enum dss_hdmi_venc_clk_source_select source;
|
|
|
|
|
|
- switch (dssdev->type) {
|
|
|
|
- case OMAP_DISPLAY_TYPE_VENC:
|
|
|
|
|
|
+ source = dss_get_hdmi_venc_clk_source();
|
|
|
|
+
|
|
|
|
+ switch (source) {
|
|
|
|
+ case DSS_VENC_TV_CLK:
|
|
return venc_get_pixel_clock();
|
|
return venc_get_pixel_clock();
|
|
- case OMAP_DISPLAY_TYPE_HDMI:
|
|
|
|
|
|
+ case DSS_HDMI_M_PCLK:
|
|
return hdmi_get_pixel_clock();
|
|
return hdmi_get_pixel_clock();
|
|
default:
|
|
default:
|
|
BUG();
|
|
BUG();
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+unsigned long dispc_core_clk_rate(void)
|
|
|
|
+{
|
|
|
|
+ int lcd;
|
|
|
|
+ unsigned long fclk = dispc_fclk_rate();
|
|
|
|
+
|
|
|
|
+ if (dss_has_feature(FEAT_CORE_CLK_DIV))
|
|
|
|
+ lcd = REG_GET(DISPC_DIVISOR, 23, 16);
|
|
|
|
+ else
|
|
|
|
+ lcd = REG_GET(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD), 23, 16);
|
|
|
|
+
|
|
|
|
+ return fclk / lcd;
|
|
|
|
+}
|
|
|
|
+
|
|
void dispc_dump_clocks(struct seq_file *s)
|
|
void dispc_dump_clocks(struct seq_file *s)
|
|
{
|
|
{
|
|
int lcd, pcd;
|
|
int lcd, pcd;
|
|
@@ -2588,7 +2933,7 @@ void dispc_dump_irqs(struct seq_file *s)
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
-void dispc_dump_regs(struct seq_file *s)
|
|
|
|
|
|
+static void dispc_dump_regs(struct seq_file *s)
|
|
{
|
|
{
|
|
int i, j;
|
|
int i, j;
|
|
const char *mgr_names[] = {
|
|
const char *mgr_names[] = {
|
|
@@ -3247,27 +3592,6 @@ int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
|
|
|
|
-void dispc_fake_vsync_irq(void)
|
|
|
|
-{
|
|
|
|
- u32 irqstatus = DISPC_IRQ_VSYNC;
|
|
|
|
- int i;
|
|
|
|
-
|
|
|
|
- WARN_ON(!in_interrupt());
|
|
|
|
-
|
|
|
|
- for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
|
|
|
|
- struct omap_dispc_isr_data *isr_data;
|
|
|
|
- isr_data = &dispc.registered_isr[i];
|
|
|
|
-
|
|
|
|
- if (!isr_data->isr)
|
|
|
|
- continue;
|
|
|
|
-
|
|
|
|
- if (isr_data->mask & irqstatus)
|
|
|
|
- isr_data->isr(isr_data->arg, irqstatus);
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
static void _omap_dispc_initialize_irq(void)
|
|
static void _omap_dispc_initialize_irq(void)
|
|
{
|
|
{
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
@@ -3330,7 +3654,7 @@ static void _omap_dispc_initial_config(void)
|
|
}
|
|
}
|
|
|
|
|
|
/* DISPC HW IP initialisation */
|
|
/* DISPC HW IP initialisation */
|
|
-static int omap_dispchw_probe(struct platform_device *pdev)
|
|
|
|
|
|
+static int __init omap_dispchw_probe(struct platform_device *pdev)
|
|
{
|
|
{
|
|
u32 rev;
|
|
u32 rev;
|
|
int r = 0;
|
|
int r = 0;
|
|
@@ -3399,6 +3723,11 @@ static int omap_dispchw_probe(struct platform_device *pdev)
|
|
|
|
|
|
dispc_runtime_put();
|
|
dispc_runtime_put();
|
|
|
|
|
|
|
|
+ dss_debugfs_create_file("dispc", dispc_dump_regs);
|
|
|
|
+
|
|
|
|
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
|
|
|
|
+ dss_debugfs_create_file("dispc_irq", dispc_dump_irqs);
|
|
|
|
+#endif
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
err_runtime_get:
|
|
err_runtime_get:
|
|
@@ -3407,7 +3736,7 @@ err_runtime_get:
|
|
return r;
|
|
return r;
|
|
}
|
|
}
|
|
|
|
|
|
-static int omap_dispchw_remove(struct platform_device *pdev)
|
|
|
|
|
|
+static int __exit omap_dispchw_remove(struct platform_device *pdev)
|
|
{
|
|
{
|
|
pm_runtime_disable(&pdev->dev);
|
|
pm_runtime_disable(&pdev->dev);
|
|
|
|
|
|
@@ -3419,19 +3748,12 @@ static int omap_dispchw_remove(struct platform_device *pdev)
|
|
static int dispc_runtime_suspend(struct device *dev)
|
|
static int dispc_runtime_suspend(struct device *dev)
|
|
{
|
|
{
|
|
dispc_save_context();
|
|
dispc_save_context();
|
|
- dss_runtime_put();
|
|
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
static int dispc_runtime_resume(struct device *dev)
|
|
static int dispc_runtime_resume(struct device *dev)
|
|
{
|
|
{
|
|
- int r;
|
|
|
|
-
|
|
|
|
- r = dss_runtime_get();
|
|
|
|
- if (r < 0)
|
|
|
|
- return r;
|
|
|
|
-
|
|
|
|
dispc_restore_context();
|
|
dispc_restore_context();
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
@@ -3443,8 +3765,7 @@ static const struct dev_pm_ops dispc_pm_ops = {
|
|
};
|
|
};
|
|
|
|
|
|
static struct platform_driver omap_dispchw_driver = {
|
|
static struct platform_driver omap_dispchw_driver = {
|
|
- .probe = omap_dispchw_probe,
|
|
|
|
- .remove = omap_dispchw_remove,
|
|
|
|
|
|
+ .remove = __exit_p(omap_dispchw_remove),
|
|
.driver = {
|
|
.driver = {
|
|
.name = "omapdss_dispc",
|
|
.name = "omapdss_dispc",
|
|
.owner = THIS_MODULE,
|
|
.owner = THIS_MODULE,
|
|
@@ -3452,12 +3773,12 @@ static struct platform_driver omap_dispchw_driver = {
|
|
},
|
|
},
|
|
};
|
|
};
|
|
|
|
|
|
-int dispc_init_platform_driver(void)
|
|
|
|
|
|
+int __init dispc_init_platform_driver(void)
|
|
{
|
|
{
|
|
- return platform_driver_register(&omap_dispchw_driver);
|
|
|
|
|
|
+ return platform_driver_probe(&omap_dispchw_driver, omap_dispchw_probe);
|
|
}
|
|
}
|
|
|
|
|
|
-void dispc_uninit_platform_driver(void)
|
|
|
|
|
|
+void __exit dispc_uninit_platform_driver(void)
|
|
{
|
|
{
|
|
- return platform_driver_unregister(&omap_dispchw_driver);
|
|
|
|
|
|
+ platform_driver_unregister(&omap_dispchw_driver);
|
|
}
|
|
}
|