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(a)st.com>
Date: Wed Jul 30 09:45:01 2008 -0400
Signed-off-by: Ryan Chen <ryan.chen(a)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