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

Ryan CHEN ryan.chen at st.com
Fri Aug 1 04:57:58 CEST 2008


Hi  Wolfgang,
I have modified my patch. New macro "CONFIG_SM501_ENABLE_2DENGINE" be
included to specify codes what enable SM501 2D engine. The macro need be
declared in config header file.
Why does it need to enable 2D engine? The reason is most of framebuffer
contents need be moved in VRAM when screen scrolls up. The work be done by
software in current U-Boot for SM501. The patch is to enable 2D engine to do
it by hardware without CPU interference.  

Signed-off-by: Ryan Chen <ryan.chen at st.com>

diff --git a/drivers/video/sm501.c b/drivers/video/sm501.c
old mode 100644
new mode 100644
index 23db02c..250e445
--- a/drivers/video/sm501.c
+++ b/drivers/video/sm501.c
@@ -54,6 +54,48 @@
 #define write32(ptrReg, value) \
     (*(volatile unsigned int *)(sm501.isaBase + ptrReg) = value)
 
+#ifdef CONFIG_SM501_ENABLE_2DENGINE
+/* 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 */
+#endif/* CONFIG_SM501_ENABLE_2DENGINE */
+
 GraphicDevice sm501;
 
 
/*--------------------------------------------------------------------------
---
@@ -77,11 +119,148 @@ static void SmiSetRegs (void)
 	}
 }
 
+#ifdef CONFIG_SM501_ENABLE_2DENGINE
+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));
+}
+#endif/* CONFIG_SM501_ENABLE_2DENGINE */
+
 
/*--------------------------------------------------------------------------
---
  * 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;
 
@@ -125,6 +304,12 @@ void *video_hw_init (void)
 	/* (see board/RPXClassic/RPXClassic.c) */
 	board_validate_screen (sm501.isaBase);
 
+#ifdef CONFIG_SM501_ENABLE_2DENGINE
+	set_current_gate();
+	
+	deInit(sm501.winSizeX, sm501.winSizeY, sm501.gdfBytesPP);
+#endif/* CONFIG_SM501_ENABLE_2DENGINE*/
+
 	/* Clear video memory */
 	i = sm501.memSize/4;
 	vm = (unsigned int *)sm501.frameAdrs;
@@ -138,7 +323,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 +336,162 @@ void video_set_lut (
 {
 }
 
+#ifdef CONFIG_SM501_ENABLE_2DENGINE
+#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_SM501_ENABLE_2DENGINE*/
 #endif /* CONFIG_VIDEO_SM501 */ 


Best Regards,
Ryan Chen
-----Original Message-----
From: wd at denx.de [mailto:wd at denx.de] 
Sent: Wednesday, July 30, 2008 4:10 PM
To: Ryan CHEN
Cc: u-boot-users at lists.sourceforge.net; Antonio Maria BORNEO
Subject: Re: [U-Boot-Users] [PATCH]:Enable 2D Engine in SM501 to hurry up
fresh speed!

In message <008c01c8f20b$91240c80$30065e0a at SHZ.ST.COM> you wrote:
> 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.

Your line is way too long.

What exactly is "fresh speed"? 

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

Please format your patches using git-format-patch and make sure to supply a
reasonable comit message.


Your patch adds a lot of code that may or may not be needed on some systems.
Please make it optional using a CONFIG_ option.


> diff --git a/drivers/video/sm501.c b/drivers/video/sm501.c old mode 
> 100644 new mode 100755

Please do not set exec permissions on plain source files.

> 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>

What is this needed for?

...
> +/* 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)
> +	{

Coding Style:

	switch (control_value) {

> +	switch (bpp)
> +	{

Ditto...

> +#if defined CONFIG_MULTI_VIDEO_CARD
> +void *sm501_video_hw_init (void)
> +#else
>  void *video_hw_init (void)
> +#endif

This seems to be an unrelated change that should be plit into a separate
patch.


Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de He had
quite a powerful intellect, but it  was  as  powerful  like  a locomotive,
and  ran on rails and was therefore almost impossible to
steer.                          - Terry Pratchett, _Lords and Ladies_





More information about the U-Boot mailing list