[U-Boot-Users] [PATCH]:Enable 2D Engine in SM501 to hurry up fresh speed!

Ryan CHEN ryan.chen at st.com
Wed Jul 30 08:14:47 CEST 2008


Hi all, 
This patch is to enable 2D Engine in SM501 video chip to hurry up fresh speed. It change some 2D Engine registers and could obviously fasten screen scroll up. I think it's reasonable to do it for consumerism.


commit 02e99b0a871f91fd3598024a2468a059971ef28d
Parent: 699f05125509249072a0b865c8d35520d97cd501
Author: Ryan Chen <ryan.chen at st.com>
Date:   Wed Jul 30 09:45:01 2008 -0400

    Signed-off-by: Ryan Chen <ryan.chen at st.com>
    
    	modified:   drivers/video/sm501.c

diff --git a/drivers/video/sm501.c b/drivers/video/sm501.c
old mode 100644
new mode 100755
index 23db02c..f20cf94
--- a/drivers/video/sm501.c
+++ b/drivers/video/sm501.c
@@ -35,6 +35,7 @@
 
 #include <video_fb.h>
 #include <sm501.h>
+#include <asm/io.h>
 
 #define read8(ptrReg)                \
     *(volatile unsigned char *)(sm501.isaBase + ptrReg)
@@ -54,6 +55,46 @@
 #define write32(ptrReg, value) \
     (*(volatile unsigned int *)(sm501.isaBase + ptrReg) = value)
 
+/* Register Macroes*/
+#define _F_START(f)             (0 ? f)
+#define _F_END(f)               (1 ? f)
+#define _F_SIZE(f)              (1 + _F_END(f) - _F_START(f))
+#define _F_MASK(f)              (((1 << _F_SIZE(f)) - 1) << _F_START(f))
+#define _F_NORMALIZE(v, f)      (((v) & _F_MASK(f)) >> _F_START(f))
+#define _F_DENORMALIZE(v, f)    (((v) << _F_START(f)) & _F_MASK(f))
+#define FIELD_GET(x, reg, field) \
+( \
+    _F_NORMALIZE((x), reg ## _ ## field) \
+)
+#define FIELD_SET(x, reg, field, value) \
+( \
+    (x & ~_F_MASK(reg ## _ ## field)) \
+    | _F_DENORMALIZE(reg ## _ ## field ## _ ## value, reg ## _ ## field) \
+)
+#define FIELD_VALUE(x, reg, field, value) \
+( \
+    (x & ~_F_MASK(reg ## _ ## field)) \
+    | _F_DENORMALIZE(value, reg ## _ ## field) \
+)
+#define FIELD_CLEAR(reg, field) \
+( \
+    ~ _F_MASK(reg ## _ ## field) \
+)
+#define FIELD_START(field)              (0 ? field)
+#define FIELD_END(field)                (1 ? field)
+#define FIELD_SIZE(field)               (1 + FIELD_END(field) - FIELD_START(field))
+#define FIELD_MASK(field)               (((1 << (FIELD_SIZE(field)-1)) | ((1 << (FIELD_SIZE(field)-1)) - 1)) << FIELD_START(field))
+#define FIELD_NORMALIZE(reg, field)     (((reg) & FIELD_MASK(field)) >> FIELD_START(field))
+#define FIELD_DENORMALIZE(field, value) (((value) << FIELD_START(field)) & FIELD_MASK(field))
+#define FIELD_INIT(reg, field, value)   FIELD_DENORMALIZE(reg ## _ ## field, \
+                                                          reg ## _ ## field ## _ ## value)
+#define FIELD_INIT_VAL(reg, field, value) \
+                                        (FIELD_DENORMALIZE(reg ## _ ## field, value))
+#define FIELD_VAL_SET(x, r, f, v)       x = x & ~FIELD_MASK(r ## _ ## f) \
+                                              | FIELD_DENORMALIZE(r ## _ ## f, r ## _ ## f ## _ ## v)
+
+#define SM501_TIMEOUT		20000	/* 20 ms */
+
 GraphicDevice sm501;
 
 /*-----------------------------------------------------------------------------
@@ -77,11 +118,148 @@ static void SmiSetRegs (void)
 	}
 }
 
+static void set_current_gate(void)
+{
+	unsigned long value, gate;
+	/* change to mode0 */
+	value = read32(POWER_MODE_CTRL);
+	value = FIELD_SET(value, POWER_MODE_CTRL, MODE, MODE0);
+	write32(POWER_MODE_CTRL, value);
+
+	/* Don't forget to set up power mode0 gate properly. */
+	gate = read32(CURRENT_POWER_GATE);
+	gate = FIELD_SET(gate, CURRENT_POWER_GATE, 2D,  ENABLE);
+	write32(POWER_MODE0_GATE, gate);	
+}
+
+/* Program new power mode. */
+static void setPower(unsigned long nGates, unsigned long Clock)
+{
+	unsigned long gate_reg, clock_reg;
+	unsigned long control_value;
+	u32 i;
+
+	/*  Get current power mode. */
+	control_value = FIELD_GET(read32(POWER_MODE_CTRL),
+		POWER_MODE_CTRL,
+		MODE);
+
+	switch (control_value)
+	{
+		case POWER_MODE_CTRL_MODE_MODE0:
+		/* Switch from mode 0 to mode 1.*/
+		gate_reg = POWER_MODE1_GATE;
+		clock_reg = POWER_MODE1_CLOCK;
+		control_value = FIELD_SET(control_value,
+			POWER_MODE_CTRL, MODE, MODE1);
+		break;
+
+		case POWER_MODE_CTRL_MODE_MODE1:
+		case POWER_MODE_CTRL_MODE_SLEEP:
+		/* Switch from mode 1 or sleep to mode 0.*/
+		gate_reg = POWER_MODE0_GATE;
+		clock_reg = POWER_MODE0_CLOCK;
+		control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, MODE0);
+		break;
+
+		default:
+		/* Invalid mode */
+		return;
+	}
+
+	/* Program new power mode. */
+	write32(gate_reg, nGates);
+	write32(clock_reg, Clock);
+	write32(POWER_MODE_CTRL, control_value);
+
+	/* When returning from sleep, wait until finished. */
+	i = SM501_TIMEOUT;
+	while ((FIELD_GET(read32(POWER_MODE_CTRL), POWER_MODE_CTRL, \
+		SLEEP_STATUS) == POWER_MODE_CTRL_SLEEP_STATUS_ACTIVE) && (i != 0)) {
+		udelay(1);
+		i--;
+	}
+	if(i == 0) {
+		printf("setPower Timeout!\n");
+	}
+}
+
+static void deInit(unsigned int nModeWidth, unsigned int nModeHeight, unsigned int bpp)
+{
+	unsigned int gate, clock;
+	/* Get current power configuration*/
+	gate  = read32(CURRENT_POWER_GATE);
+	clock = read32(CURRENT_POWER_CLOCK);
+	/* Enable 2D Drawing Engine */
+	gate = FIELD_SET(gate, CURRENT_POWER_GATE, 2D, ENABLE);
+	setPower(gate, clock);
+
+	write32((DE_REGISTER_OFFSET + DE_CLIP_TL), \
+		FIELD_VALUE(0, DE_CLIP_TL, TOP,     0) | \
+ 		FIELD_SET  (0, DE_CLIP_TL, STATUS,  DISABLE) | \
+		FIELD_SET  (0, DE_CLIP_TL, INHIBIT, OUTSIDE) | \
+		FIELD_VALUE(0, DE_CLIP_TL, LEFT,    0));
+
+	write32((DE_REGISTER_OFFSET + DE_PITCH), \
+		FIELD_VALUE(0, DE_PITCH, DESTINATION, nModeWidth) | 
+		FIELD_VALUE(0, DE_PITCH, SOURCE, nModeWidth));
+
+	write32((DE_REGISTER_OFFSET + DE_WINDOW_WIDTH), \
+		FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, nModeWidth) | \
+		FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE, nModeWidth));
+
+	switch (bpp)
+	{
+		case 1:
+		write32((DE_REGISTER_OFFSET + DE_STRETCH_FORMAT), \
+			FIELD_SET  (0, DE_STRETCH_FORMAT, PATTERN_XY, NORMAL) | \
+			FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_Y, 0) | \
+			FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_X, 0) | \
+			FIELD_SET  (0, DE_STRETCH_FORMAT, PIXEL_FORMAT, 8) | \
+			FIELD_SET  (0, DE_STRETCH_FORMAT, ADDRESSING, XY) | \
+			FIELD_VALUE(0, DE_STRETCH_FORMAT, SOURCE_HEIGHT, 3));
+		break;
+
+		case 4:
+		write32((DE_REGISTER_OFFSET + DE_STRETCH_FORMAT), \
+			FIELD_SET  (0, DE_STRETCH_FORMAT, PATTERN_XY, NORMAL) | \
+			FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_Y, 0) | \
+			FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_X, 0) | \
+			FIELD_SET  (0, DE_STRETCH_FORMAT, PIXEL_FORMAT, 32) | \
+			FIELD_SET  (0, DE_STRETCH_FORMAT, ADDRESSING, XY) | \
+			FIELD_VALUE(0, DE_STRETCH_FORMAT, SOURCE_HEIGHT, 3));
+		break;
+
+		case 2:
+		default:
+		write32((DE_REGISTER_OFFSET + DE_STRETCH_FORMAT), \
+			FIELD_SET  (0, DE_STRETCH_FORMAT, PATTERN_XY, NORMAL) | \
+			FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_Y, 0) | \
+			FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_X, 0) | \
+			FIELD_SET  (0, DE_STRETCH_FORMAT, PIXEL_FORMAT, 16) | \
+			FIELD_SET  (0, DE_STRETCH_FORMAT, ADDRESSING, XY) | \
+			FIELD_VALUE(0, DE_STRETCH_FORMAT, SOURCE_HEIGHT, 3));
+		break;
+	}
+
+	write32((DE_REGISTER_OFFSET + DE_MASKS), \
+		FIELD_VALUE(0, DE_MASKS, BYTE_MASK, 0xFFFF) | \
+		FIELD_VALUE(0, DE_MASKS, BIT_MASK,  0xFFFF));
+	write32((DE_REGISTER_OFFSET + DE_COLOR_COMPARE_MASK), \
+		FIELD_VALUE(0, DE_COLOR_COMPARE_MASK, MASKS, 0xFFFFFF));
+	write32((DE_REGISTER_OFFSET + DE_COLOR_COMPARE), \
+		FIELD_VALUE(0, DE_COLOR_COMPARE, COLOR, 0xFFFFFF));
+}
+
 /*-----------------------------------------------------------------------------
  * video_hw_init --
  *-----------------------------------------------------------------------------
  */
+#if defined CONFIG_MULTI_VIDEO_CARD
+void *sm501_video_hw_init (void)
+#else
 void *video_hw_init (void)
+#endif
 {
 	unsigned int *vm, i;
 
@@ -124,6 +302,10 @@ void *video_hw_init (void)
 
 	/* (see board/RPXClassic/RPXClassic.c) */
 	board_validate_screen (sm501.isaBase);
+	
+	set_current_gate();
+	
+	deInit(sm501.winSizeX, sm501.winSizeY, sm501.gdfBytesPP);
 
 	/* Clear video memory */
 	i = sm501.memSize/4;
@@ -138,7 +320,11 @@ void *video_hw_init (void)
  * video_set_lut --
  *-----------------------------------------------------------------------------
  */
+#if defined CONFIG_MULTI_VIDEO_CARD
+void sm501_video_set_lut (
+#else
 void video_set_lut (
+#endif
 	unsigned int index,           /* color number */
 	unsigned char r,              /* red */
 	unsigned char g,              /* green */
@@ -147,4 +333,160 @@ void video_set_lut (
 {
 }
 
+#if defined CONFIG_MULTI_VIDEO_CARD
+void sm501_video_hw_bitblt (
+#else
+void video_hw_bitblt (
+#endif
+	unsigned int bpp,             /* bytes per pixel */
+	unsigned int src_x,           /* source pos x */
+	unsigned int src_y,           /* source pos y */
+	unsigned int dst_x,           /* dest pos x */
+	unsigned int dst_y,           /* dest pos y */
+	unsigned int dim_x,           /* frame width */
+	unsigned int dim_y            /* frame height */
+	)
+{
+	u8 nDirection = 0;
+	u32 de_ctrl = 0;
+	u32 i;
+
+	/* clear 2d interrupt */
+	write32((DE_REGISTER_OFFSET + DE_STATUS), read32(DE_REGISTER_OFFSET + DE_STATUS) &~ 0x1);
+	write32((DE_REGISTER_OFFSET + DE_PITCH), FIELD_VALUE(0, DE_PITCH, DESTINATION, dim_x) | \
+		FIELD_VALUE(0, DE_PITCH, SOURCE, dim_x));
+	write32((DE_REGISTER_OFFSET + DE_WINDOW_WIDTH), FIELD_VALUE(0, DE_WINDOW_WIDTH, \
+		DESTINATION, dim_x) | FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE, dim_x));
+	write32((DE_REGISTER_OFFSET + DE_WINDOW_SOURCE_BASE), FIELD_VALUE(0, DE_WINDOW_SOURCE_BASE, \
+		ADDRESS, 0));
+	write32((DE_REGISTER_OFFSET + DE_WINDOW_DESTINATION_BASE), FIELD_VALUE(0, \
+		DE_WINDOW_DESTINATION_BASE, ADDRESS, 0));
+	if (src_y < dst_y) {
+		/* +----------+
+		|S         |
+		|   +----------+
+		|   |      |   |
+		|   |      |   |
+		+---|------+   |
+		|         D|
+		+----------+ */
+		nDirection = BOTTOM_TO_TOP;
+	} else if (src_y > dst_y) {
+		/* +----------+
+		|D         |
+		|   +----------+
+		|   |      |   |
+		|   |      |   |
+		+---|------+   |
+		|         S|
+		+----------+ */
+		nDirection = TOP_TO_BOTTOM;
+	} else {
+		/* nSrcY == nDestY */
+		if (src_x <= dst_x) {
+			/* +------+---+------+
+			|S     |   |     D|
+			|      |   |      |
+			|      |   |      |
+			|      |   |      |
+			+------+---+------+ */
+			nDirection = RIGHT_TO_LEFT;
+		} else {
+			/* nSrcX > nDestX */
+			/* +------+---+------+
+			|D     |   |     S|
+			|      |   |      |
+			|      |   |      |
+			|      |   |      |
+			+------+---+------+ */
+			nDirection = LEFT_TO_RIGHT;
+		}
+	}
+
+	if ((nDirection == BOTTOM_TO_TOP) || (nDirection == RIGHT_TO_LEFT)) {
+		src_x += dim_x - 1;
+		src_y += dim_y - 1;
+		dst_x += dim_x - 1;
+		dst_y += dim_y - 1;
+	} 
+
+	write32((DE_REGISTER_OFFSET + DE_SOURCE), \
+		FIELD_SET  (0, DE_SOURCE, WRAP, DISABLE) | \
+		FIELD_VALUE(0, DE_SOURCE, X_K1, src_x)| \
+		FIELD_VALUE(0, DE_SOURCE, Y_K2, src_y));
+	write32((DE_REGISTER_OFFSET + DE_DESTINATION), \
+		FIELD_SET  (0, DE_DESTINATION, WRAP, DISABLE) | \
+		FIELD_VALUE(0, DE_DESTINATION, X,    dst_x)  | \
+		FIELD_VALUE(0, DE_DESTINATION, Y,    dst_y));
+	write32((DE_REGISTER_OFFSET + DE_DIMENSION), \
+		FIELD_VALUE(0, DE_DIMENSION, X,    dim_x) | \
+		FIELD_VALUE(0, DE_DIMENSION, Y_ET, dim_y));
+	de_ctrl = FIELD_VALUE(0, DE_CONTROL, ROP, 0x0c) | \
+		FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) | \
+		FIELD_SET(0, DE_CONTROL, COMMAND, BITBLT) | \
+		((nDirection == 1) ? FIELD_SET(0, DE_CONTROL, DIRECTION,RIGHT_TO_LEFT):  \
+		FIELD_SET(0, DE_CONTROL, DIRECTION,LEFT_TO_RIGHT)) | \
+		FIELD_SET(0, DE_CONTROL, STATUS, START);
+	write32((DE_REGISTER_OFFSET + DE_CONTROL), de_ctrl);
+	
+	i  = SM501_TIMEOUT;
+	while(((read32(DE_REGISTER_OFFSET + DE_STATUS) & 0x1) == 0x0) && (i != 0)) {
+		udelay(1);
+		i--;
+	}
+	if(i == 0) {
+		printf("sm501_video_hw_rectfill Timeout!\n");
+	}
+	/* clear 2d interrupt */
+	write32((DE_REGISTER_OFFSET + DE_STATUS), read32(DE_REGISTER_OFFSET + DE_STATUS) &~ 0x1);
+}
+
+#if defined CONFIG_MULTI_VIDEO_CARD
+void sm501_video_hw_rectfill (
+#else
+void video_hw_rectfill (
+#endif
+	unsigned int bpp,             /* bytes per pixel */
+	unsigned int dst_x,           /* dest pos x */
+	unsigned int dst_y,           /* dest pos y */
+	unsigned int dim_x,           /* frame width */
+	unsigned int dim_y,           /* frame height */
+	unsigned int color            /* fill color */
+	)
+{
+	u32 i;
+
+	/* clear 2d interrupt */
+	write32((DE_REGISTER_OFFSET + DE_STATUS), read32(DE_REGISTER_OFFSET + DE_STATUS) &~ 0x1);
+	write32((DE_REGISTER_OFFSET + DE_WINDOW_DESTINATION_BASE), \
+		FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS, 0));
+	write32((DE_REGISTER_OFFSET + DE_FOREGROUND), color);
+	write32((DE_REGISTER_OFFSET + DE_DESTINATION),  \
+		FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) | \
+		FIELD_VALUE(0, DE_DESTINATION, X, dst_x) | \
+		FIELD_VALUE(0, DE_DESTINATION, Y, dst_y));
+
+	write32((DE_REGISTER_OFFSET + DE_DIMENSION), \
+		FIELD_VALUE(0, DE_DIMENSION, X, dim_x + 1) | \
+		FIELD_VALUE(0, DE_DIMENSION, Y_ET, dim_y + 1));
+
+	write32((DE_REGISTER_OFFSET + DE_CONTROL), \
+		FIELD_SET  (0, DE_CONTROL, STATUS, START) | \
+		FIELD_SET  (0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT) | \
+		FIELD_SET  (0, DE_CONTROL, LAST_PIXEL, OFF) | \
+		FIELD_SET  (0, DE_CONTROL, COMMAND, RECTANGLE_FILL) | \
+		FIELD_SET  (0, DE_CONTROL, ROP_SELECT, ROP2) | \
+		FIELD_VALUE(0, DE_CONTROL, ROP, 0x0C));
+
+	i  = SM501_TIMEOUT;
+	while(((read32(DE_REGISTER_OFFSET + DE_STATUS) & 0x1) == 0x0) && (i != 0)) {
+		udelay(1);
+		i--;
+	}
+	if(i == 0) {
+		printf("sm501_video_hw_rectfill Timeout!\n");
+	}
+	/* clear 2d interrupt */
+	write32((DE_REGISTER_OFFSET + DE_STATUS), read32(DE_REGISTER_OFFSET + DE_STATUS) &~ 0x1);
+}
 #endif /* CONFIG_VIDEO_SM501 */

Best Regards,
Ryan Chen





More information about the U-Boot mailing list