⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smi2d.c

📁 S3C2410的SM501驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 *  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 + -