
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