📄 smi2d.c
字号:
/*
* linux/drivers/video/smi2d.c -- Silicon Motion, Inc. video chip 2D drawing engine functions.
*
* Copyright (C) 2006 Silicon Motion, Inc.
* Ge Wang, gewang@siliconmotion.com
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
*/
#include "sm501hw.h"
#include "smi2d.h"
unsigned char SMI_de_busy = 0;
/**********************************************************************
*
* deInit
*
* Purpose
* Drawing engine initialization.
*
**********************************************************************/
void deInit(unsigned int nModeWidth, unsigned int nModeHeight, unsigned int bpp)
{
// Get current power configuration.
unsigned int gate, clock;
gate = regRead32(CURRENT_POWER_GATE);
clock = regRead32(CURRENT_POWER_CLOCK);
// Enable 2D Drawing Engine
gate = FIELD_SET(gate, CURRENT_POWER_GATE, 2D, ENABLE);
setPower(gate, clock);
regWrite32(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));
regWrite32(DE_PITCH,
FIELD_VALUE(0, DE_PITCH, DESTINATION, nModeWidth) |
FIELD_VALUE(0, DE_PITCH, SOURCE, nModeWidth));
regWrite32(DE_WINDOW_WIDTH,
FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, nModeWidth) |
FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE, nModeWidth));
switch (bpp)
{
case 8:
regWrite32(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 32:
regWrite32(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 16:
default:
regWrite32(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;
}
regWrite32(DE_MASKS,
FIELD_VALUE(0, DE_MASKS, BYTE_MASK, 0xFFFF) |
FIELD_VALUE(0, DE_MASKS, BIT_MASK, 0xFFFF));
regWrite32(DE_COLOR_COMPARE_MASK,
FIELD_VALUE(0, DE_COLOR_COMPARE_MASK, MASKS, 0xFFFFFF));
regWrite32(DE_COLOR_COMPARE,
FIELD_VALUE(0, DE_COLOR_COMPARE, COLOR, 0xFFFFFF));
}
void deWaitForNotBusy(void)
{
unsigned long i = 0x1000000;
while (i--)
{
unsigned long dwVal = regRead32(CMD_INTPR_STATUS);
if ((FIELD_GET(dwVal, CMD_INTPR_STATUS, 2D_ENGINE) == CMD_INTPR_STATUS_2D_ENGINE_IDLE) &&
(FIELD_GET(dwVal, CMD_INTPR_STATUS, 2D_FIFO) == CMD_INTPR_STATUS_2D_FIFO_EMPTY) &&
(FIELD_GET(dwVal, CMD_INTPR_STATUS, 2D_SETUP) == CMD_INTPR_STATUS_2D_SETUP_IDLE) &&
(FIELD_GET(dwVal, CMD_INTPR_STATUS, CSC_STATUS) == CMD_INTPR_STATUS_CSC_STATUS_IDLE) &&
(FIELD_GET(dwVal, CMD_INTPR_STATUS, 2D_MEMORY_FIFO) == CMD_INTPR_STATUS_2D_MEMORY_FIFO_EMPTY) &&
(FIELD_GET(dwVal, CMD_INTPR_STATUS, COMMAND_FIFO) == CMD_INTPR_STATUS_COMMAND_FIFO_EMPTY))
{
break;
}
}
SMI_de_busy = 0;
}
/**********************************************************************
*
* deSetClipRectangle
*
* Purpose
* Set drawing engine clip rectangle.
*
* Remarks
* Caller need to pass in valid rectangle parameter in device coordinate.
**********************************************************************/
void deSetClipRectangle(int left, int top, int right, int bottom)
{
/* Top left of clipping rectangle cannot be negative */
if (top < 0)
{
top = 0;
}
if (left < 0)
{
left = 0;
}
regWrite32(DE_CLIP_TL,
FIELD_VALUE(0, DE_CLIP_TL, TOP, top) |
FIELD_SET (0, DE_CLIP_TL, STATUS, ENABLE) |
FIELD_SET (0, DE_CLIP_TL, INHIBIT, OUTSIDE) |
FIELD_VALUE(0, DE_CLIP_TL, LEFT, left));
regWrite32(DE_CLIP_BR,
FIELD_VALUE(0, DE_CLIP_BR, BOTTOM, bottom) |
FIELD_VALUE(0, DE_CLIP_BR, RIGHT, right));
}
void deVerticalLine(unsigned long dst_base,
unsigned long dst_pitch,
unsigned long nX,
unsigned long nY,
unsigned long dst_height,
unsigned long nColor)
{
deWaitForNotBusy();
regWrite32(DE_WINDOW_DESTINATION_BASE, FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS, dst_base));
regWrite32(DE_PITCH,
FIELD_VALUE(0, DE_PITCH, DESTINATION, dst_pitch) |
FIELD_VALUE(0, DE_PITCH, SOURCE, dst_pitch));
regWrite32(DE_WINDOW_WIDTH,
FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, dst_pitch) |
FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE, dst_pitch));
regWrite32(DE_FOREGROUND,
FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
regWrite32(DE_DESTINATION,
FIELD_SET (0, DE_DESTINATION, WRAP, DISABLE) |
FIELD_VALUE(0, DE_DESTINATION, X, nX) |
FIELD_VALUE(0, DE_DESTINATION, Y, nY));
regWrite32(DE_DIMENSION,
FIELD_VALUE(0, DE_DIMENSION, X, 1) |
FIELD_VALUE(0, DE_DIMENSION, Y_ET, dst_height));
regWrite32(DE_CONTROL,
FIELD_SET (0, DE_CONTROL, STATUS, START) |
FIELD_SET (0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT) |
FIELD_SET (0, DE_CONTROL, MAJOR, Y) |
FIELD_SET (0, DE_CONTROL, STEP_X, NEGATIVE) |
FIELD_SET (0, DE_CONTROL, STEP_Y, POSITIVE) |
FIELD_SET (0, DE_CONTROL, LAST_PIXEL, OFF) |
FIELD_SET (0, DE_CONTROL, COMMAND, SHORT_STROKE) |
FIELD_SET (0, DE_CONTROL, ROP_SELECT, ROP2) |
FIELD_VALUE(0, DE_CONTROL, ROP, 0x0C));
SMI_de_busy = 1;
}
void deHorizontalLine(unsigned long dst_base,
unsigned long dst_pitch,
unsigned long nX,
unsigned long nY,
unsigned long dst_width,
unsigned long nColor)
{
deWaitForNotBusy();
regWrite32(DE_WINDOW_DESTINATION_BASE, FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS, dst_base));
regWrite32(DE_PITCH,
FIELD_VALUE(0, DE_PITCH, DESTINATION, dst_pitch) |
FIELD_VALUE(0, DE_PITCH, SOURCE, dst_pitch));
regWrite32(DE_WINDOW_WIDTH,
FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, dst_pitch) |
FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE, dst_pitch));
regWrite32(DE_FOREGROUND,
FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
regWrite32(DE_DESTINATION,
FIELD_SET (0, DE_DESTINATION, WRAP, DISABLE) |
FIELD_VALUE(0, DE_DESTINATION, X, nX) |
FIELD_VALUE(0, DE_DESTINATION, Y, nY));
regWrite32(DE_DIMENSION,
FIELD_VALUE(0, DE_DIMENSION, X, dst_width) |
FIELD_VALUE(0, DE_DIMENSION, Y_ET, 1));
regWrite32(DE_CONTROL,
FIELD_SET (0, DE_CONTROL, STATUS, START) |
FIELD_SET (0, DE_CONTROL, DIRECTION, RIGHT_TO_LEFT) |
FIELD_SET (0, DE_CONTROL, MAJOR, X) |
FIELD_SET (0, DE_CONTROL, STEP_X, POSITIVE) |
FIELD_SET (0, DE_CONTROL, STEP_Y, NEGATIVE) |
FIELD_SET (0, DE_CONTROL, LAST_PIXEL, OFF) |
FIELD_SET (0, DE_CONTROL, COMMAND, SHORT_STROKE) |
FIELD_SET (0, DE_CONTROL, ROP_SELECT, ROP2) |
FIELD_VALUE(0, DE_CONTROL, ROP, 0x0C));
SMI_de_busy = 1;
}
void deLine(unsigned long dst_base,
unsigned long dst_pitch,
unsigned long nX1,
unsigned long nY1,
unsigned long nX2,
unsigned long nY2,
unsigned long nColor)
{
unsigned long nCommand =
FIELD_SET (0, DE_CONTROL, STATUS, START) |
FIELD_SET (0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT) |
FIELD_SET (0, DE_CONTROL, MAJOR, X) |
FIELD_SET (0, DE_CONTROL, STEP_X, POSITIVE) |
FIELD_SET (0, DE_CONTROL, STEP_Y, POSITIVE) |
FIELD_SET (0, DE_CONTROL, LAST_PIXEL, OFF) |
FIELD_SET (0, DE_CONTROL, ROP_SELECT, ROP2) |
FIELD_VALUE(0, DE_CONTROL, ROP, 0x0C);
unsigned long DeltaX;
unsigned long DeltaY;
/* Calculate delta X */
if (nX1 <= nX2)
{
DeltaX = nX2 - nX1;
}
else
{
DeltaX = nX1 - nX2;
nCommand = FIELD_SET(nCommand, DE_CONTROL, STEP_X, NEGATIVE);
}
/* Calculate delta Y */
if (nY1 <= nY2)
{
DeltaY = nY2 - nY1;
}
else
{
DeltaY = nY1 - nY2;
nCommand = FIELD_SET(nCommand, DE_CONTROL, STEP_Y, NEGATIVE);
}
/* Determine the major axis */
if (DeltaX < DeltaY)
{
nCommand = FIELD_SET(nCommand, DE_CONTROL, MAJOR, Y);
}
/* Vertical line? */
if (nX1 == nX2)
deVerticalLine(dst_base, dst_pitch, nX1, nY1, DeltaY, nColor);
/* Horizontal line? */
else if (nY1 == nY2)
deHorizontalLine(dst_base, dst_pitch, nX1, nY1, DeltaX, nColor);
/* Diagonal line? */
else if (DeltaX == DeltaY)
{
deWaitForNotBusy();
regWrite32(DE_WINDOW_DESTINATION_BASE, FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS, dst_base));
regWrite32(DE_PITCH,
FIELD_VALUE(0, DE_PITCH, DESTINATION, dst_pitch) |
FIELD_VALUE(0, DE_PITCH, SOURCE, dst_pitch));
regWrite32(DE_WINDOW_WIDTH,
FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, dst_pitch) |
FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE, dst_pitch));
regWrite32(DE_FOREGROUND,
FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
regWrite32(DE_DESTINATION,
FIELD_SET (0, DE_DESTINATION, WRAP, DISABLE) |
FIELD_VALUE(0, DE_DESTINATION, X, 1) |
FIELD_VALUE(0, DE_DESTINATION, Y, nY1));
regWrite32(DE_DIMENSION,
FIELD_VALUE(0, DE_DIMENSION, X, 1) |
FIELD_VALUE(0, DE_DIMENSION, Y_ET, DeltaX));
regWrite32(DE_CONTROL,
FIELD_SET(nCommand, DE_CONTROL, COMMAND, SHORT_STROKE));
}
/* Generic line */
else
{
unsigned int k1, k2, et, w;
if (DeltaX < DeltaY)
{
k1 = 2 * DeltaX;
et = k1 - DeltaY;
k2 = et - DeltaY;
w = DeltaY + 1;
}
else
{
k1 = 2 * DeltaY;
et = k1 - DeltaX;
k2 = et - DeltaX;
w = DeltaX + 1;
}
deWaitForNotBusy();
regWrite32(DE_WINDOW_DESTINATION_BASE, FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS, dst_base));
regWrite32(DE_PITCH,
FIELD_VALUE(0, DE_PITCH, DESTINATION, dst_pitch) |
FIELD_VALUE(0, DE_PITCH, SOURCE, dst_pitch));
regWrite32(DE_WINDOW_WIDTH,
FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, dst_pitch) |
FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE, dst_pitch));
regWrite32(DE_FOREGROUND,
FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
regWrite32(DE_SOURCE,
FIELD_SET (0, DE_SOURCE, WRAP, DISABLE) |
FIELD_VALUE(0, DE_SOURCE, X_K1, k1) |
FIELD_VALUE(0, DE_SOURCE, Y_K2, k2));
regWrite32(DE_DESTINATION,
FIELD_SET (0, DE_DESTINATION, WRAP, DISABLE) |
FIELD_VALUE(0, DE_DESTINATION, X, nX1) |
FIELD_VALUE(0, DE_DESTINATION, Y, nY1));
regWrite32(DE_DIMENSION,
FIELD_VALUE(0, DE_DIMENSION, X, w) |
FIELD_VALUE(0, DE_DIMENSION, Y_ET, et));
regWrite32(DE_CONTROL,
FIELD_SET(nCommand, DE_CONTROL, COMMAND, LINE_DRAW));
}
SMI_de_busy = 1;
}
void deFillRect(unsigned long dst_base,
unsigned long dst_pitch,
unsigned long dst_X,
unsigned long dst_Y,
unsigned long dst_width,
unsigned long dst_height,
unsigned long nColor)
{
deWaitForNotBusy();
regWrite32(DE_WINDOW_DESTINATION_BASE, FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS, dst_base));
if (dst_pitch)
{
regWrite32(DE_PITCH,
FIELD_VALUE(0, DE_PITCH, DESTINATION, dst_pitch) |
FIELD_VALUE(0, DE_PITCH, SOURCE, dst_pitch));
regWrite32(DE_WINDOW_WIDTH,
FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, dst_pitch) |
FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE, dst_pitch));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -