开始将开发板带的三星的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);
}
阅读(3484) | 评论(4) | 转发(1) |