|
@@ -44,34 +44,40 @@
|
|
|
/* DISPC */
|
|
|
#define DISPC_BASE 0x48050400
|
|
|
|
|
|
-#define DISPC_SZ_REGS SZ_1K
|
|
|
+#define DISPC_SZ_REGS SZ_4K
|
|
|
|
|
|
struct dispc_reg { u16 idx; };
|
|
|
|
|
|
#define DISPC_REG(idx) ((const struct dispc_reg) { idx })
|
|
|
|
|
|
-/* DISPC common */
|
|
|
+/*
|
|
|
+ * DISPC common registers and
|
|
|
+ * DISPC channel registers , ch = 0 for LCD, ch = 1 for
|
|
|
+ * DIGIT, and ch = 2 for LCD2
|
|
|
+ */
|
|
|
#define DISPC_REVISION DISPC_REG(0x0000)
|
|
|
#define DISPC_SYSCONFIG DISPC_REG(0x0010)
|
|
|
#define DISPC_SYSSTATUS DISPC_REG(0x0014)
|
|
|
#define DISPC_IRQSTATUS DISPC_REG(0x0018)
|
|
|
#define DISPC_IRQENABLE DISPC_REG(0x001C)
|
|
|
#define DISPC_CONTROL DISPC_REG(0x0040)
|
|
|
+#define DISPC_CONTROL2 DISPC_REG(0x0238)
|
|
|
#define DISPC_CONFIG DISPC_REG(0x0044)
|
|
|
+#define DISPC_CONFIG2 DISPC_REG(0x0620)
|
|
|
#define DISPC_CAPABLE DISPC_REG(0x0048)
|
|
|
-#define DISPC_DEFAULT_COLOR0 DISPC_REG(0x004C)
|
|
|
-#define DISPC_DEFAULT_COLOR1 DISPC_REG(0x0050)
|
|
|
-#define DISPC_TRANS_COLOR0 DISPC_REG(0x0054)
|
|
|
-#define DISPC_TRANS_COLOR1 DISPC_REG(0x0058)
|
|
|
+#define DISPC_DEFAULT_COLOR(ch) DISPC_REG(ch == 0 ? 0x004C : \
|
|
|
+ (ch == 1 ? 0x0050 : 0x03AC))
|
|
|
+#define DISPC_TRANS_COLOR(ch) DISPC_REG(ch == 0 ? 0x0054 : \
|
|
|
+ (ch == 1 ? 0x0058 : 0x03B0))
|
|
|
#define DISPC_LINE_STATUS DISPC_REG(0x005C)
|
|
|
#define DISPC_LINE_NUMBER DISPC_REG(0x0060)
|
|
|
-#define DISPC_TIMING_H DISPC_REG(0x0064)
|
|
|
-#define DISPC_TIMING_V DISPC_REG(0x0068)
|
|
|
-#define DISPC_POL_FREQ DISPC_REG(0x006C)
|
|
|
-#define DISPC_DIVISOR DISPC_REG(0x0070)
|
|
|
+#define DISPC_TIMING_H(ch) DISPC_REG(ch != 2 ? 0x0064 : 0x0400)
|
|
|
+#define DISPC_TIMING_V(ch) DISPC_REG(ch != 2 ? 0x0068 : 0x0404)
|
|
|
+#define DISPC_POL_FREQ(ch) DISPC_REG(ch != 2 ? 0x006C : 0x0408)
|
|
|
+#define DISPC_DIVISOR(ch) DISPC_REG(ch != 2 ? 0x0070 : 0x040C)
|
|
|
#define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074)
|
|
|
#define DISPC_SIZE_DIG DISPC_REG(0x0078)
|
|
|
-#define DISPC_SIZE_LCD DISPC_REG(0x007C)
|
|
|
+#define DISPC_SIZE_LCD(ch) DISPC_REG(ch != 2 ? 0x007C : 0x03CC)
|
|
|
|
|
|
/* DISPC GFX plane */
|
|
|
#define DISPC_GFX_BA0 DISPC_REG(0x0080)
|
|
@@ -86,13 +92,12 @@ struct dispc_reg { u16 idx; };
|
|
|
#define DISPC_GFX_WINDOW_SKIP DISPC_REG(0x00B4)
|
|
|
#define DISPC_GFX_TABLE_BA DISPC_REG(0x00B8)
|
|
|
|
|
|
-#define DISPC_DATA_CYCLE1 DISPC_REG(0x01D4)
|
|
|
-#define DISPC_DATA_CYCLE2 DISPC_REG(0x01D8)
|
|
|
-#define DISPC_DATA_CYCLE3 DISPC_REG(0x01DC)
|
|
|
-
|
|
|
-#define DISPC_CPR_COEF_R DISPC_REG(0x0220)
|
|
|
-#define DISPC_CPR_COEF_G DISPC_REG(0x0224)
|
|
|
-#define DISPC_CPR_COEF_B DISPC_REG(0x0228)
|
|
|
+#define DISPC_DATA_CYCLE1(ch) DISPC_REG(ch != 2 ? 0x01D4 : 0x03C0)
|
|
|
+#define DISPC_DATA_CYCLE2(ch) DISPC_REG(ch != 2 ? 0x01D8 : 0x03C4)
|
|
|
+#define DISPC_DATA_CYCLE3(ch) DISPC_REG(ch != 2 ? 0x01DC : 0x03C8)
|
|
|
+#define DISPC_CPR_COEF_R(ch) DISPC_REG(ch != 2 ? 0x0220 : 0x03BC)
|
|
|
+#define DISPC_CPR_COEF_G(ch) DISPC_REG(ch != 2 ? 0x0224 : 0x03B8)
|
|
|
+#define DISPC_CPR_COEF_B(ch) DISPC_REG(ch != 2 ? 0x0228 : 0x03B4)
|
|
|
|
|
|
#define DISPC_GFX_PRELOAD DISPC_REG(0x022C)
|
|
|
|
|
@@ -217,18 +222,29 @@ void dispc_save_context(void)
|
|
|
SR(IRQENABLE);
|
|
|
SR(CONTROL);
|
|
|
SR(CONFIG);
|
|
|
- SR(DEFAULT_COLOR0);
|
|
|
- SR(DEFAULT_COLOR1);
|
|
|
- SR(TRANS_COLOR0);
|
|
|
- SR(TRANS_COLOR1);
|
|
|
+ SR(DEFAULT_COLOR(0));
|
|
|
+ SR(DEFAULT_COLOR(1));
|
|
|
+ SR(TRANS_COLOR(0));
|
|
|
+ SR(TRANS_COLOR(1));
|
|
|
SR(LINE_NUMBER);
|
|
|
- SR(TIMING_H);
|
|
|
- SR(TIMING_V);
|
|
|
- SR(POL_FREQ);
|
|
|
- SR(DIVISOR);
|
|
|
+ SR(TIMING_H(0));
|
|
|
+ SR(TIMING_V(0));
|
|
|
+ SR(POL_FREQ(0));
|
|
|
+ SR(DIVISOR(0));
|
|
|
SR(GLOBAL_ALPHA);
|
|
|
SR(SIZE_DIG);
|
|
|
- SR(SIZE_LCD);
|
|
|
+ SR(SIZE_LCD(0));
|
|
|
+ if (dss_has_feature(FEAT_MGR_LCD2)) {
|
|
|
+ SR(CONTROL2);
|
|
|
+ SR(DEFAULT_COLOR(2));
|
|
|
+ SR(TRANS_COLOR(2));
|
|
|
+ SR(SIZE_LCD(2));
|
|
|
+ SR(TIMING_H(2));
|
|
|
+ SR(TIMING_V(2));
|
|
|
+ SR(POL_FREQ(2));
|
|
|
+ SR(DIVISOR(2));
|
|
|
+ SR(CONFIG2);
|
|
|
+ }
|
|
|
|
|
|
SR(GFX_BA0);
|
|
|
SR(GFX_BA1);
|
|
@@ -241,13 +257,22 @@ void dispc_save_context(void)
|
|
|
SR(GFX_WINDOW_SKIP);
|
|
|
SR(GFX_TABLE_BA);
|
|
|
|
|
|
- SR(DATA_CYCLE1);
|
|
|
- SR(DATA_CYCLE2);
|
|
|
- SR(DATA_CYCLE3);
|
|
|
-
|
|
|
- SR(CPR_COEF_R);
|
|
|
- SR(CPR_COEF_G);
|
|
|
- SR(CPR_COEF_B);
|
|
|
+ SR(DATA_CYCLE1(0));
|
|
|
+ SR(DATA_CYCLE2(0));
|
|
|
+ SR(DATA_CYCLE3(0));
|
|
|
+
|
|
|
+ SR(CPR_COEF_R(0));
|
|
|
+ SR(CPR_COEF_G(0));
|
|
|
+ SR(CPR_COEF_B(0));
|
|
|
+ if (dss_has_feature(FEAT_MGR_LCD2)) {
|
|
|
+ SR(CPR_COEF_B(2));
|
|
|
+ SR(CPR_COEF_G(2));
|
|
|
+ SR(CPR_COEF_R(2));
|
|
|
+
|
|
|
+ SR(DATA_CYCLE1(2));
|
|
|
+ SR(DATA_CYCLE2(2));
|
|
|
+ SR(DATA_CYCLE3(2));
|
|
|
+ }
|
|
|
|
|
|
SR(GFX_PRELOAD);
|
|
|
|
|
@@ -356,18 +381,28 @@ void dispc_restore_context(void)
|
|
|
/*RR(IRQENABLE);*/
|
|
|
/*RR(CONTROL);*/
|
|
|
RR(CONFIG);
|
|
|
- RR(DEFAULT_COLOR0);
|
|
|
- RR(DEFAULT_COLOR1);
|
|
|
- RR(TRANS_COLOR0);
|
|
|
- RR(TRANS_COLOR1);
|
|
|
+ RR(DEFAULT_COLOR(0));
|
|
|
+ RR(DEFAULT_COLOR(1));
|
|
|
+ RR(TRANS_COLOR(0));
|
|
|
+ RR(TRANS_COLOR(1));
|
|
|
RR(LINE_NUMBER);
|
|
|
- RR(TIMING_H);
|
|
|
- RR(TIMING_V);
|
|
|
- RR(POL_FREQ);
|
|
|
- RR(DIVISOR);
|
|
|
+ RR(TIMING_H(0));
|
|
|
+ RR(TIMING_V(0));
|
|
|
+ RR(POL_FREQ(0));
|
|
|
+ RR(DIVISOR(0));
|
|
|
RR(GLOBAL_ALPHA);
|
|
|
RR(SIZE_DIG);
|
|
|
- RR(SIZE_LCD);
|
|
|
+ RR(SIZE_LCD(0));
|
|
|
+ if (dss_has_feature(FEAT_MGR_LCD2)) {
|
|
|
+ RR(DEFAULT_COLOR(2));
|
|
|
+ RR(TRANS_COLOR(2));
|
|
|
+ RR(SIZE_LCD(2));
|
|
|
+ RR(TIMING_H(2));
|
|
|
+ RR(TIMING_V(2));
|
|
|
+ RR(POL_FREQ(2));
|
|
|
+ RR(DIVISOR(2));
|
|
|
+ RR(CONFIG2);
|
|
|
+ }
|
|
|
|
|
|
RR(GFX_BA0);
|
|
|
RR(GFX_BA1);
|
|
@@ -380,13 +415,22 @@ void dispc_restore_context(void)
|
|
|
RR(GFX_WINDOW_SKIP);
|
|
|
RR(GFX_TABLE_BA);
|
|
|
|
|
|
- RR(DATA_CYCLE1);
|
|
|
- RR(DATA_CYCLE2);
|
|
|
- RR(DATA_CYCLE3);
|
|
|
-
|
|
|
- RR(CPR_COEF_R);
|
|
|
- RR(CPR_COEF_G);
|
|
|
- RR(CPR_COEF_B);
|
|
|
+ RR(DATA_CYCLE1(0));
|
|
|
+ RR(DATA_CYCLE2(0));
|
|
|
+ RR(DATA_CYCLE3(0));
|
|
|
+
|
|
|
+ RR(CPR_COEF_R(0));
|
|
|
+ RR(CPR_COEF_G(0));
|
|
|
+ RR(CPR_COEF_B(0));
|
|
|
+ if (dss_has_feature(FEAT_MGR_LCD2)) {
|
|
|
+ RR(DATA_CYCLE1(2));
|
|
|
+ RR(DATA_CYCLE2(2));
|
|
|
+ RR(DATA_CYCLE3(2));
|
|
|
+
|
|
|
+ RR(CPR_COEF_B(2));
|
|
|
+ RR(CPR_COEF_G(2));
|
|
|
+ RR(CPR_COEF_R(2));
|
|
|
+ }
|
|
|
|
|
|
RR(GFX_PRELOAD);
|
|
|
|
|
@@ -490,7 +534,8 @@ void dispc_restore_context(void)
|
|
|
|
|
|
/* enable last, because LCD & DIGIT enable are here */
|
|
|
RR(CONTROL);
|
|
|
-
|
|
|
+ if (dss_has_feature(FEAT_MGR_LCD2))
|
|
|
+ RR(CONTROL2);
|
|
|
/* clear spurious SYNC_LOST_DIGIT interrupts */
|
|
|
dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
|
|
|
|
|
@@ -516,42 +561,63 @@ bool dispc_go_busy(enum omap_channel channel)
|
|
|
{
|
|
|
int bit;
|
|
|
|
|
|
- if (channel == OMAP_DSS_CHANNEL_LCD)
|
|
|
+ if (channel == OMAP_DSS_CHANNEL_LCD ||
|
|
|
+ channel == OMAP_DSS_CHANNEL_LCD2)
|
|
|
bit = 5; /* GOLCD */
|
|
|
else
|
|
|
bit = 6; /* GODIGIT */
|
|
|
|
|
|
- return REG_GET(DISPC_CONTROL, bit, bit) == 1;
|
|
|
+ if (channel == OMAP_DSS_CHANNEL_LCD2)
|
|
|
+ return REG_GET(DISPC_CONTROL2, bit, bit) == 1;
|
|
|
+ else
|
|
|
+ return REG_GET(DISPC_CONTROL, bit, bit) == 1;
|
|
|
}
|
|
|
|
|
|
void dispc_go(enum omap_channel channel)
|
|
|
{
|
|
|
int bit;
|
|
|
+ bool enable_bit, go_bit;
|
|
|
|
|
|
enable_clocks(1);
|
|
|
|
|
|
- if (channel == OMAP_DSS_CHANNEL_LCD)
|
|
|
+ if (channel == OMAP_DSS_CHANNEL_LCD ||
|
|
|
+ channel == OMAP_DSS_CHANNEL_LCD2)
|
|
|
bit = 0; /* LCDENABLE */
|
|
|
else
|
|
|
bit = 1; /* DIGITALENABLE */
|
|
|
|
|
|
/* if the channel is not enabled, we don't need GO */
|
|
|
- if (REG_GET(DISPC_CONTROL, bit, bit) == 0)
|
|
|
+ if (channel == OMAP_DSS_CHANNEL_LCD2)
|
|
|
+ enable_bit = REG_GET(DISPC_CONTROL2, bit, bit) == 1;
|
|
|
+ else
|
|
|
+ enable_bit = REG_GET(DISPC_CONTROL, bit, bit) == 1;
|
|
|
+
|
|
|
+ if (!enable_bit)
|
|
|
goto end;
|
|
|
|
|
|
- if (channel == OMAP_DSS_CHANNEL_LCD)
|
|
|
+ if (channel == OMAP_DSS_CHANNEL_LCD ||
|
|
|
+ channel == OMAP_DSS_CHANNEL_LCD2)
|
|
|
bit = 5; /* GOLCD */
|
|
|
else
|
|
|
bit = 6; /* GODIGIT */
|
|
|
|
|
|
- if (REG_GET(DISPC_CONTROL, bit, bit) == 1) {
|
|
|
+ if (channel == OMAP_DSS_CHANNEL_LCD2)
|
|
|
+ go_bit = REG_GET(DISPC_CONTROL2, bit, bit) == 1;
|
|
|
+ else
|
|
|
+ go_bit = REG_GET(DISPC_CONTROL, bit, bit) == 1;
|
|
|
+
|
|
|
+ if (go_bit) {
|
|
|
DSSERR("GO bit not down for channel %d\n", channel);
|
|
|
goto end;
|
|
|
}
|
|
|
|
|
|
- DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" : "DIGIT");
|
|
|
+ DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" :
|
|
|
+ (channel == OMAP_DSS_CHANNEL_LCD2 ? "LCD2" : "DIGIT"));
|
|
|
|
|
|
- REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
|
|
|
+ if (channel == OMAP_DSS_CHANNEL_LCD2)
|
|
|
+ REG_FLD_MOD(DISPC_CONTROL2, 1, bit, bit);
|
|
|
+ else
|
|
|
+ REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
|
|
|
end:
|
|
|
enable_clocks(0);
|
|
|
}
|
|
@@ -773,13 +839,26 @@ static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)
|
|
|
dispc_write_reg(vsi_reg[plane-1], val);
|
|
|
}
|
|
|
|
|
|
+static void _dispc_set_pre_mult_alpha(enum omap_plane plane, bool enable)
|
|
|
+{
|
|
|
+ if (!dss_has_feature(FEAT_PRE_MULT_ALPHA))
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
|
|
|
+ plane == OMAP_DSS_VIDEO1)
|
|
|
+ return;
|
|
|
+
|
|
|
+ REG_FLD_MOD(dispc_reg_att[plane], enable ? 1 : 0, 28, 28);
|
|
|
+}
|
|
|
+
|
|
|
static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha)
|
|
|
{
|
|
|
if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
|
|
|
return;
|
|
|
|
|
|
- BUG_ON(!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
|
|
|
- plane == OMAP_DSS_VIDEO1);
|
|
|
+ if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
|
|
|
+ plane == OMAP_DSS_VIDEO1)
|
|
|
+ return;
|
|
|
|
|
|
if (plane == OMAP_DSS_GFX)
|
|
|
REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0);
|
|
@@ -851,6 +930,7 @@ static void _dispc_set_channel_out(enum omap_plane plane,
|
|
|
{
|
|
|
int shift;
|
|
|
u32 val;
|
|
|
+ int chan = 0, chan2 = 0;
|
|
|
|
|
|
switch (plane) {
|
|
|
case OMAP_DSS_GFX:
|
|
@@ -866,7 +946,29 @@ static void _dispc_set_channel_out(enum omap_plane plane,
|
|
|
}
|
|
|
|
|
|
val = dispc_read_reg(dispc_reg_att[plane]);
|
|
|
- val = FLD_MOD(val, channel, shift, shift);
|
|
|
+ if (dss_has_feature(FEAT_MGR_LCD2)) {
|
|
|
+ switch (channel) {
|
|
|
+ case OMAP_DSS_CHANNEL_LCD:
|
|
|
+ chan = 0;
|
|
|
+ chan2 = 0;
|
|
|
+ break;
|
|
|
+ case OMAP_DSS_CHANNEL_DIGIT:
|
|
|
+ chan = 1;
|
|
|
+ chan2 = 0;
|
|
|
+ break;
|
|
|
+ case OMAP_DSS_CHANNEL_LCD2:
|
|
|
+ chan = 0;
|
|
|
+ chan2 = 1;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ BUG();
|
|
|
+ }
|
|
|
+
|
|
|
+ val = FLD_MOD(val, chan, shift, shift);
|
|
|
+ val = FLD_MOD(val, chan2, 31, 30);
|
|
|
+ } else {
|
|
|
+ val = FLD_MOD(val, channel, shift, shift);
|
|
|
+ }
|
|
|
dispc_write_reg(dispc_reg_att[plane], val);
|
|
|
}
|
|
|
|
|
@@ -923,13 +1025,13 @@ void dispc_enable_replication(enum omap_plane plane, bool enable)
|
|
|
enable_clocks(0);
|
|
|
}
|
|
|
|
|
|
-void dispc_set_lcd_size(u16 width, u16 height)
|
|
|
+void dispc_set_lcd_size(enum omap_channel channel, 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);
|
|
|
enable_clocks(1);
|
|
|
- dispc_write_reg(DISPC_SIZE_LCD, val);
|
|
|
+ dispc_write_reg(DISPC_SIZE_LCD(channel), val);
|
|
|
enable_clocks(0);
|
|
|
}
|
|
|
|
|
@@ -1426,12 +1528,13 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static unsigned long calc_fclk_five_taps(u16 width, u16 height,
|
|
|
- u16 out_width, u16 out_height, enum omap_color_mode color_mode)
|
|
|
+static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width,
|
|
|
+ u16 height, u16 out_width, u16 out_height,
|
|
|
+ enum omap_color_mode color_mode)
|
|
|
{
|
|
|
u32 fclk = 0;
|
|
|
/* FIXME venc pclk? */
|
|
|
- u64 tmp, pclk = dispc_pclk_rate();
|
|
|
+ u64 tmp, pclk = dispc_pclk_rate(channel);
|
|
|
|
|
|
if (height > out_height) {
|
|
|
/* FIXME get real display PPL */
|
|
@@ -1463,8 +1566,8 @@ static unsigned long calc_fclk_five_taps(u16 width, u16 height,
|
|
|
return fclk;
|
|
|
}
|
|
|
|
|
|
-static unsigned long calc_fclk(u16 width, u16 height,
|
|
|
- u16 out_width, u16 out_height)
|
|
|
+static unsigned long calc_fclk(enum omap_channel channel, u16 width,
|
|
|
+ u16 height, u16 out_width, u16 out_height)
|
|
|
{
|
|
|
unsigned int hf, vf;
|
|
|
|
|
@@ -1488,7 +1591,7 @@ static unsigned long calc_fclk(u16 width, u16 height,
|
|
|
vf = 1;
|
|
|
|
|
|
/* FIXME venc pclk? */
|
|
|
- return dispc_pclk_rate() * vf * hf;
|
|
|
+ return dispc_pclk_rate(channel) * vf * hf;
|
|
|
}
|
|
|
|
|
|
void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out)
|
|
@@ -1507,7 +1610,8 @@ static int _dispc_setup_plane(enum omap_plane plane,
|
|
|
bool ilace,
|
|
|
enum omap_dss_rotation_type rotation_type,
|
|
|
u8 rotation, int mirror,
|
|
|
- u8 global_alpha)
|
|
|
+ u8 global_alpha, u8 pre_mult_alpha,
|
|
|
+ enum omap_channel channel)
|
|
|
{
|
|
|
const int maxdownscale = cpu_is_omap34xx() ? 4 : 2;
|
|
|
bool five_taps = 0;
|
|
@@ -1536,29 +1640,12 @@ static int _dispc_setup_plane(enum omap_plane plane,
|
|
|
height, pos_y, out_height);
|
|
|
}
|
|
|
|
|
|
+ if (!dss_feat_color_mode_supported(plane, color_mode))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
if (plane == OMAP_DSS_GFX) {
|
|
|
if (width != out_width || height != out_height)
|
|
|
return -EINVAL;
|
|
|
-
|
|
|
- switch (color_mode) {
|
|
|
- case OMAP_DSS_COLOR_ARGB16:
|
|
|
- case OMAP_DSS_COLOR_ARGB32:
|
|
|
- case OMAP_DSS_COLOR_RGBA32:
|
|
|
- if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
|
|
|
- return -EINVAL;
|
|
|
- case OMAP_DSS_COLOR_RGBX32:
|
|
|
- if (cpu_is_omap24xx())
|
|
|
- return -EINVAL;
|
|
|
- /* fall through */
|
|
|
- case OMAP_DSS_COLOR_RGB12U:
|
|
|
- case OMAP_DSS_COLOR_RGB16:
|
|
|
- case OMAP_DSS_COLOR_RGB24P:
|
|
|
- case OMAP_DSS_COLOR_RGB24U:
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
} else {
|
|
|
/* video plane */
|
|
|
|
|
@@ -1572,42 +1659,16 @@ static int _dispc_setup_plane(enum omap_plane plane,
|
|
|
out_height > height * 8)
|
|
|
return -EINVAL;
|
|
|
|
|
|
- switch (color_mode) {
|
|
|
- case OMAP_DSS_COLOR_RGBX32:
|
|
|
- case OMAP_DSS_COLOR_RGB12U:
|
|
|
- if (cpu_is_omap24xx())
|
|
|
- return -EINVAL;
|
|
|
- /* fall through */
|
|
|
- case OMAP_DSS_COLOR_RGB16:
|
|
|
- case OMAP_DSS_COLOR_RGB24P:
|
|
|
- case OMAP_DSS_COLOR_RGB24U:
|
|
|
- break;
|
|
|
-
|
|
|
- case OMAP_DSS_COLOR_ARGB16:
|
|
|
- case OMAP_DSS_COLOR_ARGB32:
|
|
|
- case OMAP_DSS_COLOR_RGBA32:
|
|
|
- if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
|
|
|
- return -EINVAL;
|
|
|
- if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
|
|
|
- plane == OMAP_DSS_VIDEO1)
|
|
|
- return -EINVAL;
|
|
|
- break;
|
|
|
-
|
|
|
- case OMAP_DSS_COLOR_YUV2:
|
|
|
- case OMAP_DSS_COLOR_UYVY:
|
|
|
+ if (color_mode == OMAP_DSS_COLOR_YUV2 ||
|
|
|
+ color_mode == OMAP_DSS_COLOR_UYVY)
|
|
|
cconv = 1;
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
|
|
|
/* Must use 5-tap filter? */
|
|
|
five_taps = height > out_height * 2;
|
|
|
|
|
|
if (!five_taps) {
|
|
|
- fclk = calc_fclk(width, height,
|
|
|
- out_width, out_height);
|
|
|
+ fclk = calc_fclk(channel, width, height, out_width,
|
|
|
+ out_height);
|
|
|
|
|
|
/* Try 5-tap filter if 3-tap fclk is too high */
|
|
|
if (cpu_is_omap34xx() && height > out_height &&
|
|
@@ -1621,7 +1682,7 @@ static int _dispc_setup_plane(enum omap_plane plane,
|
|
|
}
|
|
|
|
|
|
if (five_taps)
|
|
|
- fclk = calc_fclk_five_taps(width, height,
|
|
|
+ fclk = calc_fclk_five_taps(channel, width, height,
|
|
|
out_width, out_height, color_mode);
|
|
|
|
|
|
DSSDBG("required fclk rate = %lu Hz\n", fclk);
|
|
@@ -1693,8 +1754,8 @@ static int _dispc_setup_plane(enum omap_plane plane,
|
|
|
|
|
|
_dispc_set_rotation_attrs(plane, rotation, mirror, color_mode);
|
|
|
|
|
|
- if (plane != OMAP_DSS_VIDEO1)
|
|
|
- _dispc_setup_global_alpha(plane, global_alpha);
|
|
|
+ _dispc_set_pre_mult_alpha(plane, pre_mult_alpha);
|
|
|
+ _dispc_setup_global_alpha(plane, global_alpha);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -1710,36 +1771,44 @@ static void dispc_disable_isr(void *data, u32 mask)
|
|
|
complete(compl);
|
|
|
}
|
|
|
|
|
|
-static void _enable_lcd_out(bool enable)
|
|
|
+static void _enable_lcd_out(enum omap_channel channel, bool enable)
|
|
|
{
|
|
|
- REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0);
|
|
|
+ if (channel == OMAP_DSS_CHANNEL_LCD2)
|
|
|
+ REG_FLD_MOD(DISPC_CONTROL2, enable ? 1 : 0, 0, 0);
|
|
|
+ else
|
|
|
+ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0);
|
|
|
}
|
|
|
|
|
|
-static void dispc_enable_lcd_out(bool enable)
|
|
|
+static void dispc_enable_lcd_out(enum omap_channel channel, bool enable)
|
|
|
{
|
|
|
struct completion frame_done_completion;
|
|
|
bool is_on;
|
|
|
int r;
|
|
|
+ u32 irq;
|
|
|
|
|
|
enable_clocks(1);
|
|
|
|
|
|
/* When we disable LCD output, we need to wait until frame is done.
|
|
|
* Otherwise the DSS is still working, and turning off the clocks
|
|
|
* prevents DSS from going to OFF mode */
|
|
|
- is_on = REG_GET(DISPC_CONTROL, 0, 0);
|
|
|
+ is_on = channel == OMAP_DSS_CHANNEL_LCD2 ?
|
|
|
+ REG_GET(DISPC_CONTROL2, 0, 0) :
|
|
|
+ REG_GET(DISPC_CONTROL, 0, 0);
|
|
|
+
|
|
|
+ irq = channel == OMAP_DSS_CHANNEL_LCD2 ? DISPC_IRQ_FRAMEDONE2 :
|
|
|
+ DISPC_IRQ_FRAMEDONE;
|
|
|
|
|
|
if (!enable && is_on) {
|
|
|
init_completion(&frame_done_completion);
|
|
|
|
|
|
r = omap_dispc_register_isr(dispc_disable_isr,
|
|
|
- &frame_done_completion,
|
|
|
- DISPC_IRQ_FRAMEDONE);
|
|
|
+ &frame_done_completion, irq);
|
|
|
|
|
|
if (r)
|
|
|
DSSERR("failed to register FRAMEDONE isr\n");
|
|
|
}
|
|
|
|
|
|
- _enable_lcd_out(enable);
|
|
|
+ _enable_lcd_out(channel, enable);
|
|
|
|
|
|
if (!enable && is_on) {
|
|
|
if (!wait_for_completion_timeout(&frame_done_completion,
|
|
@@ -1747,8 +1816,7 @@ static void dispc_enable_lcd_out(bool enable)
|
|
|
DSSERR("timeout waiting for FRAME DONE\n");
|
|
|
|
|
|
r = omap_dispc_unregister_isr(dispc_disable_isr,
|
|
|
- &frame_done_completion,
|
|
|
- DISPC_IRQ_FRAMEDONE);
|
|
|
+ &frame_done_completion, irq);
|
|
|
|
|
|
if (r)
|
|
|
DSSERR("failed to unregister FRAMEDONE isr\n");
|
|
@@ -1818,6 +1886,8 @@ static void dispc_enable_digit_out(bool enable)
|
|
|
unsigned long flags;
|
|
|
spin_lock_irqsave(&dispc.irq_lock, flags);
|
|
|
dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
|
|
|
+ if (dss_has_feature(FEAT_MGR_LCD2))
|
|
|
+ dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
|
|
|
dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
|
|
|
_omap_dispc_set_irqs();
|
|
|
spin_unlock_irqrestore(&dispc.irq_lock, flags);
|
|
@@ -1832,14 +1902,17 @@ bool dispc_is_channel_enabled(enum omap_channel channel)
|
|
|
return !!REG_GET(DISPC_CONTROL, 0, 0);
|
|
|
else if (channel == OMAP_DSS_CHANNEL_DIGIT)
|
|
|
return !!REG_GET(DISPC_CONTROL, 1, 1);
|
|
|
+ else if (channel == OMAP_DSS_CHANNEL_LCD2)
|
|
|
+ return !!REG_GET(DISPC_CONTROL2, 0, 0);
|
|
|
else
|
|
|
BUG();
|
|
|
}
|
|
|
|
|
|
void dispc_enable_channel(enum omap_channel channel, bool enable)
|
|
|
{
|
|
|
- if (channel == OMAP_DSS_CHANNEL_LCD)
|
|
|
- dispc_enable_lcd_out(enable);
|
|
|
+ if (channel == OMAP_DSS_CHANNEL_LCD ||
|
|
|
+ channel == OMAP_DSS_CHANNEL_LCD2)
|
|
|
+ dispc_enable_lcd_out(channel, enable);
|
|
|
else if (channel == OMAP_DSS_CHANNEL_DIGIT)
|
|
|
dispc_enable_digit_out(enable);
|
|
|
else
|
|
@@ -1848,6 +1921,9 @@ void dispc_enable_channel(enum omap_channel channel, bool enable)
|
|
|
|
|
|
void dispc_lcd_enable_signal_polarity(bool act_high)
|
|
|
{
|
|
|
+ if (!dss_has_feature(FEAT_LCDENABLEPOL))
|
|
|
+ return;
|
|
|
+
|
|
|
enable_clocks(1);
|
|
|
REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
|
|
|
enable_clocks(0);
|
|
@@ -1855,6 +1931,9 @@ void dispc_lcd_enable_signal_polarity(bool act_high)
|
|
|
|
|
|
void dispc_lcd_enable_signal(bool enable)
|
|
|
{
|
|
|
+ if (!dss_has_feature(FEAT_LCDENABLESIGNAL))
|
|
|
+ return;
|
|
|
+
|
|
|
enable_clocks(1);
|
|
|
REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
|
|
|
enable_clocks(0);
|
|
@@ -1862,20 +1941,27 @@ void dispc_lcd_enable_signal(bool enable)
|
|
|
|
|
|
void dispc_pck_free_enable(bool enable)
|
|
|
{
|
|
|
+ if (!dss_has_feature(FEAT_PCKFREEENABLE))
|
|
|
+ return;
|
|
|
+
|
|
|
enable_clocks(1);
|
|
|
REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
|
|
|
enable_clocks(0);
|
|
|
}
|
|
|
|
|
|
-void dispc_enable_fifohandcheck(bool enable)
|
|
|
+void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable)
|
|
|
{
|
|
|
enable_clocks(1);
|
|
|
- REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16);
|
|
|
+ if (channel == OMAP_DSS_CHANNEL_LCD2)
|
|
|
+ REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16);
|
|
|
+ else
|
|
|
+ REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16);
|
|
|
enable_clocks(0);
|
|
|
}
|
|
|
|
|
|
|
|
|
-void dispc_set_lcd_display_type(enum omap_lcd_display_type type)
|
|
|
+void dispc_set_lcd_display_type(enum omap_channel channel,
|
|
|
+ enum omap_lcd_display_type type)
|
|
|
{
|
|
|
int mode;
|
|
|
|
|
@@ -1894,7 +1980,10 @@ void dispc_set_lcd_display_type(enum omap_lcd_display_type type)
|
|
|
}
|
|
|
|
|
|
enable_clocks(1);
|
|
|
- REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3);
|
|
|
+ if (channel == OMAP_DSS_CHANNEL_LCD2)
|
|
|
+ REG_FLD_MOD(DISPC_CONTROL2, mode, 3, 3);
|
|
|
+ else
|
|
|
+ REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3);
|
|
|
enable_clocks(0);
|
|
|
}
|
|
|
|
|
@@ -1908,25 +1997,21 @@ void dispc_set_loadmode(enum omap_dss_load_mode mode)
|
|
|
|
|
|
void dispc_set_default_color(enum omap_channel channel, u32 color)
|
|
|
{
|
|
|
- const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0,
|
|
|
- DISPC_DEFAULT_COLOR1 };
|
|
|
-
|
|
|
enable_clocks(1);
|
|
|
- dispc_write_reg(def_reg[channel], color);
|
|
|
+ dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color);
|
|
|
enable_clocks(0);
|
|
|
}
|
|
|
|
|
|
u32 dispc_get_default_color(enum omap_channel channel)
|
|
|
{
|
|
|
- const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0,
|
|
|
- DISPC_DEFAULT_COLOR1 };
|
|
|
u32 l;
|
|
|
|
|
|
BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT &&
|
|
|
- channel != OMAP_DSS_CHANNEL_LCD);
|
|
|
+ channel != OMAP_DSS_CHANNEL_LCD &&
|
|
|
+ channel != OMAP_DSS_CHANNEL_LCD2);
|
|
|
|
|
|
enable_clocks(1);
|
|
|
- l = dispc_read_reg(def_reg[channel]);
|
|
|
+ l = dispc_read_reg(DISPC_DEFAULT_COLOR(channel));
|
|
|
enable_clocks(0);
|
|
|
|
|
|
return l;
|
|
@@ -1936,16 +2021,15 @@ void dispc_set_trans_key(enum omap_channel ch,
|
|
|
enum omap_dss_trans_key_type type,
|
|
|
u32 trans_key)
|
|
|
{
|
|
|
- const struct dispc_reg tr_reg[] = {
|
|
|
- DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 };
|
|
|
-
|
|
|
enable_clocks(1);
|
|
|
if (ch == OMAP_DSS_CHANNEL_LCD)
|
|
|
REG_FLD_MOD(DISPC_CONFIG, type, 11, 11);
|
|
|
- else /* OMAP_DSS_CHANNEL_DIGIT */
|
|
|
+ else if (ch == OMAP_DSS_CHANNEL_DIGIT)
|
|
|
REG_FLD_MOD(DISPC_CONFIG, type, 13, 13);
|
|
|
+ else /* OMAP_DSS_CHANNEL_LCD2 */
|
|
|
+ REG_FLD_MOD(DISPC_CONFIG2, type, 11, 11);
|
|
|
|
|
|
- dispc_write_reg(tr_reg[ch], trans_key);
|
|
|
+ dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key);
|
|
|
enable_clocks(0);
|
|
|
}
|
|
|
|
|
@@ -1953,21 +2037,20 @@ void dispc_get_trans_key(enum omap_channel ch,
|
|
|
enum omap_dss_trans_key_type *type,
|
|
|
u32 *trans_key)
|
|
|
{
|
|
|
- const struct dispc_reg tr_reg[] = {
|
|
|
- DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 };
|
|
|
-
|
|
|
enable_clocks(1);
|
|
|
if (type) {
|
|
|
if (ch == OMAP_DSS_CHANNEL_LCD)
|
|
|
*type = REG_GET(DISPC_CONFIG, 11, 11);
|
|
|
else if (ch == OMAP_DSS_CHANNEL_DIGIT)
|
|
|
*type = REG_GET(DISPC_CONFIG, 13, 13);
|
|
|
+ else if (ch == OMAP_DSS_CHANNEL_LCD2)
|
|
|
+ *type = REG_GET(DISPC_CONFIG2, 11, 11);
|
|
|
else
|
|
|
BUG();
|
|
|
}
|
|
|
|
|
|
if (trans_key)
|
|
|
- *trans_key = dispc_read_reg(tr_reg[ch]);
|
|
|
+ *trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch));
|
|
|
enable_clocks(0);
|
|
|
}
|
|
|
|
|
@@ -1976,8 +2059,10 @@ void dispc_enable_trans_key(enum omap_channel ch, bool enable)
|
|
|
enable_clocks(1);
|
|
|
if (ch == OMAP_DSS_CHANNEL_LCD)
|
|
|
REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
|
|
|
- else /* OMAP_DSS_CHANNEL_DIGIT */
|
|
|
+ else if (ch == OMAP_DSS_CHANNEL_DIGIT)
|
|
|
REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12);
|
|
|
+ else /* OMAP_DSS_CHANNEL_LCD2 */
|
|
|
+ REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10);
|
|
|
enable_clocks(0);
|
|
|
}
|
|
|
void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
|
|
@@ -1988,8 +2073,10 @@ 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 */
|
|
|
+ else if (ch == OMAP_DSS_CHANNEL_DIGIT)
|
|
|
REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
|
|
|
+ else /* OMAP_DSS_CHANNEL_LCD2 */
|
|
|
+ REG_FLD_MOD(DISPC_CONFIG2, enable, 18, 18);
|
|
|
enable_clocks(0);
|
|
|
}
|
|
|
bool dispc_alpha_blending_enabled(enum omap_channel ch)
|
|
@@ -2003,13 +2090,14 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch)
|
|
|
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);
|
|
|
+ enabled = REG_GET(DISPC_CONFIG, 19, 19);
|
|
|
+ else if (ch == OMAP_DSS_CHANNEL_LCD2)
|
|
|
+ enabled = REG_GET(DISPC_CONFIG2, 18, 18);
|
|
|
else
|
|
|
BUG();
|
|
|
enable_clocks(0);
|
|
|
|
|
|
return enabled;
|
|
|
-
|
|
|
}
|
|
|
|
|
|
|
|
@@ -2022,6 +2110,8 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
|
|
|
enabled = REG_GET(DISPC_CONFIG, 10, 10);
|
|
|
else if (ch == OMAP_DSS_CHANNEL_DIGIT)
|
|
|
enabled = REG_GET(DISPC_CONFIG, 12, 12);
|
|
|
+ else if (ch == OMAP_DSS_CHANNEL_LCD2)
|
|
|
+ enabled = REG_GET(DISPC_CONFIG2, 10, 10);
|
|
|
else
|
|
|
BUG();
|
|
|
enable_clocks(0);
|
|
@@ -2030,7 +2120,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
|
|
|
}
|
|
|
|
|
|
|
|
|
-void dispc_set_tft_data_lines(u8 data_lines)
|
|
|
+void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
|
|
|
{
|
|
|
int code;
|
|
|
|
|
@@ -2053,11 +2143,15 @@ void dispc_set_tft_data_lines(u8 data_lines)
|
|
|
}
|
|
|
|
|
|
enable_clocks(1);
|
|
|
- REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
|
|
|
+ if (channel == OMAP_DSS_CHANNEL_LCD2)
|
|
|
+ REG_FLD_MOD(DISPC_CONTROL2, code, 9, 8);
|
|
|
+ else
|
|
|
+ REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
|
|
|
enable_clocks(0);
|
|
|
}
|
|
|
|
|
|
-void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode)
|
|
|
+void dispc_set_parallel_interface_mode(enum omap_channel channel,
|
|
|
+ enum omap_parallel_interface_mode mode)
|
|
|
{
|
|
|
u32 l;
|
|
|
int stallmode;
|
|
@@ -2087,13 +2181,17 @@ void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode)
|
|
|
|
|
|
enable_clocks(1);
|
|
|
|
|
|
- l = dispc_read_reg(DISPC_CONTROL);
|
|
|
-
|
|
|
- l = FLD_MOD(l, stallmode, 11, 11);
|
|
|
- l = FLD_MOD(l, gpout0, 15, 15);
|
|
|
- l = FLD_MOD(l, gpout1, 16, 16);
|
|
|
-
|
|
|
- dispc_write_reg(DISPC_CONTROL, l);
|
|
|
+ if (channel == OMAP_DSS_CHANNEL_LCD2) {
|
|
|
+ l = dispc_read_reg(DISPC_CONTROL2);
|
|
|
+ l = FLD_MOD(l, stallmode, 11, 11);
|
|
|
+ dispc_write_reg(DISPC_CONTROL2, l);
|
|
|
+ } else {
|
|
|
+ l = dispc_read_reg(DISPC_CONTROL);
|
|
|
+ l = FLD_MOD(l, stallmode, 11, 11);
|
|
|
+ l = FLD_MOD(l, gpout0, 15, 15);
|
|
|
+ l = FLD_MOD(l, gpout1, 16, 16);
|
|
|
+ dispc_write_reg(DISPC_CONTROL, l);
|
|
|
+ }
|
|
|
|
|
|
enable_clocks(0);
|
|
|
}
|
|
@@ -2129,8 +2227,8 @@ bool dispc_lcd_timings_ok(struct omap_video_timings *timings)
|
|
|
timings->vfp, timings->vbp);
|
|
|
}
|
|
|
|
|
|
-static void _dispc_set_lcd_timings(int hsw, int hfp, int hbp,
|
|
|
- int vsw, int vfp, int vbp)
|
|
|
+static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw,
|
|
|
+ int hfp, int hbp, int vsw, int vfp, int vbp)
|
|
|
{
|
|
|
u32 timing_h, timing_v;
|
|
|
|
|
@@ -2149,13 +2247,14 @@ static void _dispc_set_lcd_timings(int hsw, int hfp, int hbp,
|
|
|
}
|
|
|
|
|
|
enable_clocks(1);
|
|
|
- dispc_write_reg(DISPC_TIMING_H, timing_h);
|
|
|
- dispc_write_reg(DISPC_TIMING_V, timing_v);
|
|
|
+ dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
|
|
|
+ dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
|
|
|
enable_clocks(0);
|
|
|
}
|
|
|
|
|
|
/* change name to mode? */
|
|
|
-void dispc_set_lcd_timings(struct omap_video_timings *timings)
|
|
|
+void dispc_set_lcd_timings(enum omap_channel channel,
|
|
|
+ struct omap_video_timings *timings)
|
|
|
{
|
|
|
unsigned xtot, ytot;
|
|
|
unsigned long ht, vt;
|
|
@@ -2165,10 +2264,11 @@ void dispc_set_lcd_timings(struct omap_video_timings *timings)
|
|
|
timings->vfp, timings->vbp))
|
|
|
BUG();
|
|
|
|
|
|
- _dispc_set_lcd_timings(timings->hsw, timings->hfp, timings->hbp,
|
|
|
- timings->vsw, timings->vfp, timings->vbp);
|
|
|
+ _dispc_set_lcd_timings(channel, timings->hsw, timings->hfp,
|
|
|
+ timings->hbp, timings->vsw, timings->vfp,
|
|
|
+ timings->vbp);
|
|
|
|
|
|
- dispc_set_lcd_size(timings->x_res, timings->y_res);
|
|
|
+ dispc_set_lcd_size(channel, timings->x_res, timings->y_res);
|
|
|
|
|
|
xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp;
|
|
|
ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp;
|
|
@@ -2176,7 +2276,8 @@ void dispc_set_lcd_timings(struct omap_video_timings *timings)
|
|
|
ht = (timings->pixel_clock * 1000) / xtot;
|
|
|
vt = (timings->pixel_clock * 1000) / xtot / ytot;
|
|
|
|
|
|
- DSSDBG("xres %u yres %u\n", timings->x_res, timings->y_res);
|
|
|
+ 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,
|
|
@@ -2185,21 +2286,23 @@ void dispc_set_lcd_timings(struct omap_video_timings *timings)
|
|
|
DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt);
|
|
|
}
|
|
|
|
|
|
-static void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div)
|
|
|
+static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
|
|
|
+ u16 pck_div)
|
|
|
{
|
|
|
BUG_ON(lck_div < 1);
|
|
|
BUG_ON(pck_div < 2);
|
|
|
|
|
|
enable_clocks(1);
|
|
|
- dispc_write_reg(DISPC_DIVISOR,
|
|
|
+ dispc_write_reg(DISPC_DIVISOR(channel),
|
|
|
FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
|
|
|
enable_clocks(0);
|
|
|
}
|
|
|
|
|
|
-static void dispc_get_lcd_divisor(int *lck_div, int *pck_div)
|
|
|
+static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div,
|
|
|
+ int *pck_div)
|
|
|
{
|
|
|
u32 l;
|
|
|
- l = dispc_read_reg(DISPC_DIVISOR);
|
|
|
+ l = dispc_read_reg(DISPC_DIVISOR(channel));
|
|
|
*lck_div = FLD_GET(l, 23, 16);
|
|
|
*pck_div = FLD_GET(l, 7, 0);
|
|
|
}
|
|
@@ -2219,13 +2322,13 @@ unsigned long dispc_fclk_rate(void)
|
|
|
return r;
|
|
|
}
|
|
|
|
|
|
-unsigned long dispc_lclk_rate(void)
|
|
|
+unsigned long dispc_lclk_rate(enum omap_channel channel)
|
|
|
{
|
|
|
int lcd;
|
|
|
unsigned long r;
|
|
|
u32 l;
|
|
|
|
|
|
- l = dispc_read_reg(DISPC_DIVISOR);
|
|
|
+ l = dispc_read_reg(DISPC_DIVISOR(channel));
|
|
|
|
|
|
lcd = FLD_GET(l, 23, 16);
|
|
|
|
|
@@ -2234,13 +2337,13 @@ unsigned long dispc_lclk_rate(void)
|
|
|
return r / lcd;
|
|
|
}
|
|
|
|
|
|
-unsigned long dispc_pclk_rate(void)
|
|
|
+unsigned long dispc_pclk_rate(enum omap_channel channel)
|
|
|
{
|
|
|
int lcd, pcd;
|
|
|
unsigned long r;
|
|
|
u32 l;
|
|
|
|
|
|
- l = dispc_read_reg(DISPC_DIVISOR);
|
|
|
+ l = dispc_read_reg(DISPC_DIVISOR(channel));
|
|
|
|
|
|
lcd = FLD_GET(l, 23, 16);
|
|
|
pcd = FLD_GET(l, 7, 0);
|
|
@@ -2256,8 +2359,6 @@ void dispc_dump_clocks(struct seq_file *s)
|
|
|
|
|
|
enable_clocks(1);
|
|
|
|
|
|
- dispc_get_lcd_divisor(&lcd, &pcd);
|
|
|
-
|
|
|
seq_printf(s, "- DISPC -\n");
|
|
|
|
|
|
seq_printf(s, "dispc fclk source = %s\n",
|
|
@@ -2265,9 +2366,25 @@ void dispc_dump_clocks(struct seq_file *s)
|
|
|
"dss1_alwon_fclk" : "dsi1_pll_fclk");
|
|
|
|
|
|
seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate());
|
|
|
- seq_printf(s, "lck\t\t%-16lulck div\t%u\n", dispc_lclk_rate(), lcd);
|
|
|
- seq_printf(s, "pck\t\t%-16lupck div\t%u\n", dispc_pclk_rate(), pcd);
|
|
|
|
|
|
+ seq_printf(s, "- LCD1 -\n");
|
|
|
+
|
|
|
+ dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd);
|
|
|
+
|
|
|
+ seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
|
|
|
+ dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD), lcd);
|
|
|
+ seq_printf(s, "pck\t\t%-16lupck div\t%u\n",
|
|
|
+ dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD), pcd);
|
|
|
+ if (dss_has_feature(FEAT_MGR_LCD2)) {
|
|
|
+ seq_printf(s, "- LCD2 -\n");
|
|
|
+
|
|
|
+ dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd);
|
|
|
+
|
|
|
+ seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
|
|
|
+ dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD2), lcd);
|
|
|
+ seq_printf(s, "pck\t\t%-16lupck div\t%u\n",
|
|
|
+ dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd);
|
|
|
+ }
|
|
|
enable_clocks(0);
|
|
|
}
|
|
|
|
|
@@ -2309,6 +2426,12 @@ void dispc_dump_irqs(struct seq_file *s)
|
|
|
PIS(SYNC_LOST);
|
|
|
PIS(SYNC_LOST_DIGIT);
|
|
|
PIS(WAKEUP);
|
|
|
+ if (dss_has_feature(FEAT_MGR_LCD2)) {
|
|
|
+ PIS(FRAMEDONE2);
|
|
|
+ PIS(VSYNC2);
|
|
|
+ PIS(ACBIAS_COUNT_STAT2);
|
|
|
+ PIS(SYNC_LOST2);
|
|
|
+ }
|
|
|
#undef PIS
|
|
|
}
|
|
|
#endif
|
|
@@ -2327,19 +2450,30 @@ void dispc_dump_regs(struct seq_file *s)
|
|
|
DUMPREG(DISPC_CONTROL);
|
|
|
DUMPREG(DISPC_CONFIG);
|
|
|
DUMPREG(DISPC_CAPABLE);
|
|
|
- DUMPREG(DISPC_DEFAULT_COLOR0);
|
|
|
- DUMPREG(DISPC_DEFAULT_COLOR1);
|
|
|
- DUMPREG(DISPC_TRANS_COLOR0);
|
|
|
- DUMPREG(DISPC_TRANS_COLOR1);
|
|
|
+ DUMPREG(DISPC_DEFAULT_COLOR(0));
|
|
|
+ DUMPREG(DISPC_DEFAULT_COLOR(1));
|
|
|
+ DUMPREG(DISPC_TRANS_COLOR(0));
|
|
|
+ DUMPREG(DISPC_TRANS_COLOR(1));
|
|
|
DUMPREG(DISPC_LINE_STATUS);
|
|
|
DUMPREG(DISPC_LINE_NUMBER);
|
|
|
- DUMPREG(DISPC_TIMING_H);
|
|
|
- DUMPREG(DISPC_TIMING_V);
|
|
|
- DUMPREG(DISPC_POL_FREQ);
|
|
|
- DUMPREG(DISPC_DIVISOR);
|
|
|
+ DUMPREG(DISPC_TIMING_H(0));
|
|
|
+ DUMPREG(DISPC_TIMING_V(0));
|
|
|
+ DUMPREG(DISPC_POL_FREQ(0));
|
|
|
+ DUMPREG(DISPC_DIVISOR(0));
|
|
|
DUMPREG(DISPC_GLOBAL_ALPHA);
|
|
|
DUMPREG(DISPC_SIZE_DIG);
|
|
|
- DUMPREG(DISPC_SIZE_LCD);
|
|
|
+ DUMPREG(DISPC_SIZE_LCD(0));
|
|
|
+ if (dss_has_feature(FEAT_MGR_LCD2)) {
|
|
|
+ DUMPREG(DISPC_CONTROL2);
|
|
|
+ DUMPREG(DISPC_CONFIG2);
|
|
|
+ DUMPREG(DISPC_DEFAULT_COLOR(2));
|
|
|
+ DUMPREG(DISPC_TRANS_COLOR(2));
|
|
|
+ DUMPREG(DISPC_TIMING_H(2));
|
|
|
+ DUMPREG(DISPC_TIMING_V(2));
|
|
|
+ DUMPREG(DISPC_POL_FREQ(2));
|
|
|
+ DUMPREG(DISPC_DIVISOR(2));
|
|
|
+ DUMPREG(DISPC_SIZE_LCD(2));
|
|
|
+ }
|
|
|
|
|
|
DUMPREG(DISPC_GFX_BA0);
|
|
|
DUMPREG(DISPC_GFX_BA1);
|
|
@@ -2353,13 +2487,22 @@ void dispc_dump_regs(struct seq_file *s)
|
|
|
DUMPREG(DISPC_GFX_WINDOW_SKIP);
|
|
|
DUMPREG(DISPC_GFX_TABLE_BA);
|
|
|
|
|
|
- DUMPREG(DISPC_DATA_CYCLE1);
|
|
|
- DUMPREG(DISPC_DATA_CYCLE2);
|
|
|
- DUMPREG(DISPC_DATA_CYCLE3);
|
|
|
-
|
|
|
- DUMPREG(DISPC_CPR_COEF_R);
|
|
|
- DUMPREG(DISPC_CPR_COEF_G);
|
|
|
- DUMPREG(DISPC_CPR_COEF_B);
|
|
|
+ DUMPREG(DISPC_DATA_CYCLE1(0));
|
|
|
+ DUMPREG(DISPC_DATA_CYCLE2(0));
|
|
|
+ DUMPREG(DISPC_DATA_CYCLE3(0));
|
|
|
+
|
|
|
+ DUMPREG(DISPC_CPR_COEF_R(0));
|
|
|
+ DUMPREG(DISPC_CPR_COEF_G(0));
|
|
|
+ DUMPREG(DISPC_CPR_COEF_B(0));
|
|
|
+ if (dss_has_feature(FEAT_MGR_LCD2)) {
|
|
|
+ DUMPREG(DISPC_DATA_CYCLE1(2));
|
|
|
+ DUMPREG(DISPC_DATA_CYCLE2(2));
|
|
|
+ DUMPREG(DISPC_DATA_CYCLE3(2));
|
|
|
+
|
|
|
+ DUMPREG(DISPC_CPR_COEF_R(2));
|
|
|
+ DUMPREG(DISPC_CPR_COEF_G(2));
|
|
|
+ DUMPREG(DISPC_CPR_COEF_B(2));
|
|
|
+ }
|
|
|
|
|
|
DUMPREG(DISPC_GFX_PRELOAD);
|
|
|
|
|
@@ -2458,8 +2601,8 @@ void dispc_dump_regs(struct seq_file *s)
|
|
|
#undef DUMPREG
|
|
|
}
|
|
|
|
|
|
-static void _dispc_set_pol_freq(bool onoff, bool rf, bool ieo, bool ipc,
|
|
|
- bool ihs, bool ivs, u8 acbi, u8 acb)
|
|
|
+static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf,
|
|
|
+ bool ieo, bool ipc, bool ihs, bool ivs, u8 acbi, u8 acb)
|
|
|
{
|
|
|
u32 l = 0;
|
|
|
|
|
@@ -2476,13 +2619,14 @@ static void _dispc_set_pol_freq(bool onoff, bool rf, bool ieo, bool ipc,
|
|
|
l |= FLD_VAL(acb, 7, 0);
|
|
|
|
|
|
enable_clocks(1);
|
|
|
- dispc_write_reg(DISPC_POL_FREQ, l);
|
|
|
+ dispc_write_reg(DISPC_POL_FREQ(channel), l);
|
|
|
enable_clocks(0);
|
|
|
}
|
|
|
|
|
|
-void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb)
|
|
|
+void dispc_set_pol_freq(enum omap_channel channel,
|
|
|
+ enum omap_panel_config config, u8 acbi, u8 acb)
|
|
|
{
|
|
|
- _dispc_set_pol_freq((config & OMAP_DSS_LCD_ONOFF) != 0,
|
|
|
+ _dispc_set_pol_freq(channel, (config & OMAP_DSS_LCD_ONOFF) != 0,
|
|
|
(config & OMAP_DSS_LCD_RF) != 0,
|
|
|
(config & OMAP_DSS_LCD_IEO) != 0,
|
|
|
(config & OMAP_DSS_LCD_IPC) != 0,
|
|
@@ -2551,24 +2695,26 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-int dispc_set_clock_div(struct dispc_clock_info *cinfo)
|
|
|
+int dispc_set_clock_div(enum omap_channel channel,
|
|
|
+ struct dispc_clock_info *cinfo)
|
|
|
{
|
|
|
DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div);
|
|
|
DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div);
|
|
|
|
|
|
- dispc_set_lcd_divisor(cinfo->lck_div, cinfo->pck_div);
|
|
|
+ dispc_set_lcd_divisor(channel, cinfo->lck_div, cinfo->pck_div);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-int dispc_get_clock_div(struct dispc_clock_info *cinfo)
|
|
|
+int dispc_get_clock_div(enum omap_channel channel,
|
|
|
+ struct dispc_clock_info *cinfo)
|
|
|
{
|
|
|
unsigned long fck;
|
|
|
|
|
|
fck = dispc_fclk_rate();
|
|
|
|
|
|
- cinfo->lck_div = REG_GET(DISPC_DIVISOR, 23, 16);
|
|
|
- cinfo->pck_div = REG_GET(DISPC_DIVISOR, 7, 0);
|
|
|
+ cinfo->lck_div = REG_GET(DISPC_DIVISOR(channel), 23, 16);
|
|
|
+ cinfo->pck_div = REG_GET(DISPC_DIVISOR(channel), 7, 0);
|
|
|
|
|
|
cinfo->lck = fck / cinfo->lck_div;
|
|
|
cinfo->pck = cinfo->lck / cinfo->pck_div;
|
|
@@ -2708,6 +2854,8 @@ static void print_irq_status(u32 status)
|
|
|
PIS(VID2_FIFO_UNDERFLOW);
|
|
|
PIS(SYNC_LOST);
|
|
|
PIS(SYNC_LOST_DIGIT);
|
|
|
+ if (dss_has_feature(FEAT_MGR_LCD2))
|
|
|
+ PIS(SYNC_LOST2);
|
|
|
#undef PIS
|
|
|
|
|
|
printk("\n");
|
|
@@ -2926,6 +3074,45 @@ static void dispc_error_worker(struct work_struct *work)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ if (errors & DISPC_IRQ_SYNC_LOST2) {
|
|
|
+ struct omap_overlay_manager *manager = NULL;
|
|
|
+ bool enable = false;
|
|
|
+
|
|
|
+ DSSERR("SYNC_LOST for LCD2, disabling LCD2\n");
|
|
|
+
|
|
|
+ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
|
|
|
+ struct omap_overlay_manager *mgr;
|
|
|
+ mgr = omap_dss_get_overlay_manager(i);
|
|
|
+
|
|
|
+ if (mgr->id == OMAP_DSS_CHANNEL_LCD2) {
|
|
|
+ manager = mgr;
|
|
|
+ enable = mgr->device->state ==
|
|
|
+ OMAP_DSS_DISPLAY_ACTIVE;
|
|
|
+ mgr->device->driver->disable(mgr->device);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (manager) {
|
|
|
+ struct omap_dss_device *dssdev = manager->device;
|
|
|
+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
|
|
|
+ struct omap_overlay *ovl;
|
|
|
+ ovl = omap_dss_get_overlay(i);
|
|
|
+
|
|
|
+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (ovl->id != 0 && ovl->manager == manager)
|
|
|
+ dispc_enable_plane(ovl->id, 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ dispc_go(manager->id);
|
|
|
+ mdelay(50);
|
|
|
+ if (enable)
|
|
|
+ dssdev->driver->enable(dssdev);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
if (errors & DISPC_IRQ_OCP_ERR) {
|
|
|
DSSERR("OCP_ERR\n");
|
|
|
for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
|
|
@@ -3033,6 +3220,8 @@ static void _omap_dispc_initialize_irq(void)
|
|
|
memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr));
|
|
|
|
|
|
dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
|
|
|
+ if (dss_has_feature(FEAT_MGR_LCD2))
|
|
|
+ dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
|
|
|
|
|
|
/* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
|
|
|
* so clear it */
|
|
@@ -3065,7 +3254,8 @@ static void _omap_dispc_initial_config(void)
|
|
|
dispc_write_reg(DISPC_SYSCONFIG, l);
|
|
|
|
|
|
/* FUNCGATED */
|
|
|
- REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
|
|
|
+ if (dss_has_feature(FEAT_FUNCGATED))
|
|
|
+ REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
|
|
|
|
|
|
/* L3 firewall setting: enable access to OCM RAM */
|
|
|
/* XXX this should be somewhere in plat-omap */
|
|
@@ -3139,17 +3329,18 @@ int dispc_setup_plane(enum omap_plane plane,
|
|
|
enum omap_color_mode color_mode,
|
|
|
bool ilace,
|
|
|
enum omap_dss_rotation_type rotation_type,
|
|
|
- u8 rotation, bool mirror, u8 global_alpha)
|
|
|
+ u8 rotation, bool mirror, u8 global_alpha,
|
|
|
+ u8 pre_mult_alpha, enum omap_channel channel)
|
|
|
{
|
|
|
int r = 0;
|
|
|
|
|
|
DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> "
|
|
|
- "%dx%d, ilace %d, cmode %x, rot %d, mir %d\n",
|
|
|
+ "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n",
|
|
|
plane, paddr, screen_width, pos_x, pos_y,
|
|
|
width, height,
|
|
|
out_width, out_height,
|
|
|
ilace, color_mode,
|
|
|
- rotation, mirror);
|
|
|
+ rotation, mirror, channel);
|
|
|
|
|
|
enable_clocks(1);
|
|
|
|
|
@@ -3161,7 +3352,8 @@ int dispc_setup_plane(enum omap_plane plane,
|
|
|
color_mode, ilace,
|
|
|
rotation_type,
|
|
|
rotation, mirror,
|
|
|
- global_alpha);
|
|
|
+ global_alpha,
|
|
|
+ pre_mult_alpha, channel);
|
|
|
|
|
|
enable_clocks(0);
|
|
|
|