public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Ryan CHEN <ryan.chen@st.com>
To: u-boot@lists.denx.de
Subject: [U-Boot-Users] [PATCH]:Enable 2D Engine in SM501 to hurry up fresh speed!
Date: Wed, 30 Jul 2008 14:14:47 +0800	[thread overview]
Message-ID: <008c01c8f20b$91240c80$30065e0a@SHZ.ST.COM> (raw)

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@st.com>
Date:   Wed Jul 30 09:45:01 2008 -0400

    Signed-off-by: Ryan Chen <ryan.chen@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

             reply	other threads:[~2008-07-30  6:14 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-07-30  6:14 Ryan CHEN [this message]
2008-07-30  8:10 ` [U-Boot-Users] [PATCH]:Enable 2D Engine in SM501 to hurry up fresh speed! Wolfgang Denk
2008-08-01  2:57   ` Ryan CHEN
2008-08-01  7:54     ` Wolfgang Denk
2008-08-01  7:58     ` Wolfgang Denk

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='008c01c8f20b$91240c80$30065e0a@SHZ.ST.COM' \
    --to=ryan.chen@st.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox