6410 linux,搞定s3c6410 linux下2D的Bitblt

开始将开发板带的三星的2.6.28的g2d驱动移植过来。结果在设置完命令寄存器以后,命令全都往FIFO里面放了,压根没有执行!

后来按照6410手册614页的寄存器设置,自己设置。结果设置完命令寄存器以后,命令运行了,但是没有看到任何输出。

问了几个开发板的技术支持,都说没用过linux下的2D,Wince下的倒是可以正常运行。

只好参考WinCE的2D驱动了,还好搞定了。

6410手册里面讲的太不清楚,有几个寄存器的设置他就没讲清楚甚至没讲!

1、DST_BASE_ADDR和SRC_BASE_ADDR要设置物理地址。不能是内核的虚拟地址或者应用程序中的地址。对于FB,要使用 dma_alloc_writecombine 第三个参数返回的物理地址 fbi->fix.smem_start。

2、在手册里bitblt没说要设置 clip 的寄存器,但是clip不设是不行的,感觉是使用默认值的0话就把图像全部剪掉了!我直接设为屏幕的分辨率了。

3、使用透明模式要设置的是 BS_COLOR,而不是BG_COLOR。开始我还以为是代码写错了。后来试了一下,感觉是手册写错了。Blue Screen Mode咋设置我就没有试了。

4、使用2D的画线和画点功能,也要设置DST_BASE_ADDR和clip的!手册里面都没说!

5、设置COORDn_X_REG+COORDn_Y_REG和设置COORDn_REG好像是一样的,都能跑。

下面是主要部分的代码,s3c_g2d_transparent_copy()是bitblt的主要函数。

注:因为不知道如何将用户空间的虚拟地址转换为物理地址,只好在内核里面alloc了一块buffer s3c_g2d_userFB,每次都要用copy_from_user把图片先拷贝到s3c_g2d_userFB,再由2D搬到屏幕。

大概测试过一下,一张800*600的图片 copy_from_user 用了大概 4ms。2D搬到屏幕上用了大概5~6ms。还是想把copy_from_user给剩了!

static void s3c_g2d_wait_allcmd_finish(void)

{

while (__raw_readl(s3c_g2d_base + S3C_G2D_FIFO_STAT_REG) != 0x600)

{

}

}

irqreturn_t s3c_g2d_irq(int irq, void *dev_id)

{

if(__raw_readl(s3c_g2d_base + S3C_G2D_INTC_PEND_REG) & S3C_G2D_PEND_REG_INTP_CMD_FIN) {

__raw_writel ( S3C_G2D_PEND_REG_INTP_CMD_FIN, s3c_g2d_base + S3C_G2D_INTC_PEND_REG );

wake_up_interruptible(&waitq_g2d);

s3c_g2d_poll_flag = 1;

}

return IRQ_HANDLED;

}

void s3c_g2d_enable_interrupt(void)

{

s3c_g2d_debug_reg(S3C_G2D_INTEN_REG_CCF, s3c_g2d_base + S3C_G2D_INTEN_REG);

}

void s3c_g2d_set_srcsurface(struct fb_info *info, u32 src_addr,

int src_width, int src_heigth)

{

s3c_g2d_check_fifo(4);

s3c_g2d_debug_reg(src_addr, s3c_g2d_base + S3C_G2D_SRC_BASE_ADDR);

s3c_g2d_debug_reg(S3C_G2D_COLOR_RGB_565,

s3c_g2d_base + S3C_G2D_SRC_COLOR_MODE);

s3c_g2d_debug_reg(src_width, s3c_g2d_base + S3C_G2D_HORI_RES_REG);

s3c_g2d_debug_reg(src_heigth, s3c_g2d_base + S3C_G2D_VERT_RES_REG);

}

void s3c_g2d_set_dstsurface(struct fb_info *info, u32 dst_addr)

{

s3c_g2d_check_fifo(4);

s3c_g2d_debug_reg(dst_addr, s3c_g2d_base + S3C_G2D_DST_BASE_ADDR);

s3c_g2d_debug_reg(S3C_G2D_COLOR_RGB_565,

s3c_g2d_base + S3C_G2D_SRC_COLOR_MODE);

s3c_g2d_debug_reg(info->var.xres, s3c_g2d_base + S3C_G2D_SC_HORI_REG);

s3c_g2d_debug_reg(info->var.yres, s3c_g2d_base + S3C_G2D_SC_VERT_REG);

}

void s3c_g2d_set_clipwindows(struct fb_info *info)

{

s3c_g2d_check_fifo(4);

s3c_g2d_debug_reg(0, s3c_g2d_base + S3C_G2D_CW_LT_X_REG);

s3c_g2d_debug_reg(0, s3c_g2d_base + S3C_G2D_CW_LT_Y_REG);

s3c_g2d_debug_reg(info->var.xres, s3c_g2d_base + S3C_G2D_CW_RB_X_REG);

s3c_g2d_debug_reg(info->var.yres, s3c_g2d_base + S3C_G2D_CW_RB_Y_REG);

}

void s3c_g2d_set_transparentmode(struct fb_info *info, int is_transp, u32 color)

{

u32 tmp;

s3c_g2d_check_fifo(2);

tmp = __raw_readl(s3c_g2d_base + S3C_G2D_ROP_REG);

if (is_transp)

{

tmp |= S3C_G2D_ROP_REG_T_TRANSP_MODE;

}

else

{

tmp &= ~S3C_G2D_ROP_REG_T_TRANSP_MODE;

}

s3c_g2d_debug_reg(tmp, s3c_g2d_base + S3C_G2D_ROP_REG);

s3c_g2d_debug_reg(color, s3c_g2d_base + S3C_G2D_BS_COLOR_REG);  //wy!Rev in wince set bs_color????

//s3c_g2d_debug_reg(color, s3c_g2d_base + S3C_G2D_BG_COLOR_REG);      //wy ! rev!!!!

}

void s3c_g2d_set_rotationmode(struct fb_info *info, S3C_G2D_ROT_TYPE rot_type)

{

u32 tmp;

s3c_g2d_check_fifo(1);

tmp = __raw_readl(s3c_g2d_base + S3C_G2D_ROTATE_REG);

tmp = (tmp&~0x3f) | rot_type;

s3c_g2d_debug_reg(tmp, s3c_g2d_base + S3C_G2D_ROTATE_REG);

}

void s3c_g2d_set_srccoordinate(struct fb_info *info,

int start_x, int start_y, int end_x, int end_y)

{

s3c_g2d_check_fifo(4);

s3c_g2d_debug_reg(start_x, s3c_g2d_base + S3C_G2D_COORD0_X_REG);

s3c_g2d_debug_reg(start_y, s3c_g2d_base + S3C_G2D_COORD0_Y_REG);

s3c_g2d_debug_reg(end_x,   s3c_g2d_base + S3C_G2D_COORD1_X_REG);

s3c_g2d_debug_reg(end_y,   s3c_g2d_base + S3C_G2D_COORD1_Y_REG);

}

void s3c_g2d_set_dstcoordinate(struct fb_info *info,

int start_x, int start_y, int end_x, int end_y)

{

s3c_g2d_check_fifo(4);

s3c_g2d_debug_reg(start_x, s3c_g2d_base + S3C_G2D_COORD2_X_REG);

s3c_g2d_debug_reg(start_y, s3c_g2d_base + S3C_G2D_COORD2_Y_REG);

s3c_g2d_debug_reg(end_x,   s3c_g2d_base + S3C_G2D_COORD3_X_REG);

s3c_g2d_debug_reg(end_y,   s3c_g2d_base + S3C_G2D_COORD3_Y_REG);

}

void s3c_g2d_set_rotationorg(struct fb_info *info, int x, int y)

{

s3c_g2d_check_fifo(2);

s3c_g2d_debug_reg(x, s3c_g2d_base + S3C_G2D_ROT_OC_X_REG);

s3c_g2d_debug_reg(y, s3c_g2d_base + S3C_G2D_ROT_OC_Y_REG);

}

void s3c_g2d_transparent_copy(struct fb_info *info, S3CFB_COPY_INFO *copy_info)

{

s3c_g2d_wait_allcmd_finish();

if (copy_from_user(s3c_g2d_userFB, (unsigned short *)copy_info->src_base,

copy_info->dst_width * copy_info->dst_height

* (info->var.bits_per_pixel>>3) ) )

{

printk("G2D TransparentCopy copy from user error!\n");

return ;

}

copy_info->src_base   = __pa(s3c_g2d_userFB);

copy_info->dst_base   = info->fix.smem_start;

s3c_g2d_enable_interrupt();

s3c_g2d_set_srcsurface(info, copy_info->src_base,

copy_info->dst_width, copy_info->dst_height);

s3c_g2d_set_dstsurface(info, copy_info->dst_base);

s3c_g2d_set_clipwindows(info);

if (copy_info->transparent_enable)

{

s3c_g2d_set_transparentmode(info, 1, copy_info->transparent_color);

}

else

{

s3c_g2d_set_transparentmode(info, 0, 0);

}

s3c_g2d_set_rotationmode(info, G2D_ROT_0);

s3c_g2d_set_srccoordinate(info, copy_info->src_X, copy_info->src_Y,

copy_info->src_X+copy_info->dst_width-1,

copy_info->src_Y+copy_info->dst_height-1);

s3c_g2d_set_rotationorg(info, copy_info->dst_X, copy_info->dst_Y);

s3c_g2d_set_dstcoordinate(info, copy_info->dst_X, copy_info->dst_Y,

copy_info->dst_X+copy_info->dst_width-1,

copy_info->dst_Y+copy_info->dst_height-1);

s3c_g2d_debug_reg(1, s3c_g2d_base + S3C_G2D_CMD1_REG);

}

static void s3c_fb_g2d_init(void)

{

//DisableEffect

s3c_g2d_debug_reg(__raw_readl(s3c_g2d_base+S3C_G2D_ROP_REG)&~(0x7<<10),

s3c_g2d_base + S3C_G2D_ROP_REG);

//SetColorKeyOff

s3c_g2d_debug_reg(__raw_readl(s3c_g2d_base+S3C_G2D_ROP_REG)&(~(0x1<<9)),

s3c_g2d_base + S3C_G2D_ROP_REG);

s3c_g2d_debug_reg(__raw_readl(s3c_g2d_base+S3C_G2D_STENCIL_CNTL_REG)&(~(0x1U<<31)),

s3c_g2d_base + S3C_G2D_STENCIL_CNTL_REG);

s3c_g2d_debug_reg((FADING_OFFSET_DISABLE | ALPHA_VALUE_DISABLE),

s3c_g2d_base + S3C_G2D_ALPHA_REG);

s3c_g2d_debug_reg((G2D_OPERAND3_FG_BIT | G2D_NO_ALPHA_BIT | OPAQUE_ENABLE | G2D_ROP_SRC_ONLY),

s3c_g2d_base + S3C_G2D_ROP_REG);

//SetRotationOrg

s3c_g2d_debug_reg((0&0x000007FF),

s3c_g2d_base + S3C_G2D_ROT_OC_X_REG);

s3c_g2d_debug_reg((0&0x000007FF),

s3c_g2d_base + S3C_G2D_ROT_OC_Y_REG);

s3c_g2d_debug_reg((0x1<<0),

s3c_g2d_base + S3C_G2D_ROTATE_REG);

s3c_g2d_debug_reg(0,

s3c_g2d_base + S3C_G2D_ALPHA_REG);

}

阅读(2852) | 评论(4) | 转发(1) |

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值