From: 蔡枫 Date: Wed, 9 Mar 2011 03:17:40 +0000 (+0800) Subject: add hardware cursor support, auto switch to hardware cursor mode when using TVOUT... X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=ad9e5466460f823cfafa80c7cc3ac6ced8c25bf5;p=firefly-linux-kernel-4.4.55.git add hardware cursor support, auto switch to hardware cursor mode when using TVOUT or HDMI output --- diff --git a/drivers/video/rk29_fb.c b/drivers/video/rk29_fb.c index 05428474c863..f9cb93903c94 100755 --- a/drivers/video/rk29_fb.c +++ b/drivers/video/rk29_fb.c @@ -60,6 +60,42 @@ #include "./display/screen/screen.h" #define ANDROID_USE_THREE_BUFS 0 //android use three buffers to accelerate UI display in rgb plane +#define CURSOR_BUF_SIZE 256 //RK2818 cursor need 256B buf +int rk29_cursor_buf[CURSOR_BUF_SIZE]; +char cursor_img[] = { +0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00, +0x00,0x20,0x00,0x00, +0x00,0x30,0x00,0x00, +0x00,0x28,0x00,0x00, +0x00,0x24,0x00,0x00, +0x00,0x22,0x00,0x00, +0x00,0x21,0x00,0x00, +0x00,0x20,0x80,0x00, +0x00,0x20,0x40,0x00, +0x00,0x20,0x20,0x00, +0x00,0x20,0x10,0x00, +0x00,0x20,0x08,0x00, +0x00,0x20,0x7C,0x00, +0x00,0x22,0x40,0x00, +0x00,0x26,0x40,0x00, +0x00,0x29,0x20,0x00, +0x00,0x31,0x20,0x00, +0x00,0x20,0x90,0x00, +0x00,0x00,0x90,0x00, +0x00,0x00,0x48,0x00, +0x00,0x00,0x48,0x00, +0x00,0x00,0x30,0x00, +0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00 +}; #if 0 #define fbprintk(msg...) printk(msg); @@ -726,6 +762,107 @@ static int fb_setcolreg(unsigned regno, return 0; } + +int rk29_set_cursor_en(struct rk29fb_inf *inf, int enable) +{ + if (enable){ + printk("%s: enable hardware cursor \n",__func__); + LcdSetBit(inf, SYS_CONFIG, m_HWC_ENABLE); + }else{ + printk("%s: enable disable hardware cursor \n",__func__); + LcdClrBit(inf, SYS_CONFIG, m_HWC_ENABLE); + } + LcdWrReg(inf, REG_CFG_DONE, 0x01); + return 0; +} + +int rk29_set_cursor_pos(struct rk29fb_inf *inf, int x, int y) +{ + struct rk29fb_screen *screen = inf->cur_screen; + + /* set data */ + if (x >= 0x800 || y >= 0x800 ) + return -EINVAL; + printk("%s: %08x,%08x \n",__func__, x, y); + x += (screen->left_margin + screen->hsync_len); + y += (screen->upper_margin + screen->vsync_len); + LcdWrReg(inf, HWC_DSP_ST, v_BIT11LO(x)|v_BIT11HI(y)); + LcdWrReg(inf, REG_CFG_DONE, 0x01); + return 0; +} + + +int rk29_set_cursor_colour_map(struct rk29fb_inf *inf, int bg_col, int fg_col) +{ + printk("%s: bg = %08x,fg = %08x \n",__func__, bg_col, fg_col); + LcdMskReg(inf, HWC_COLOR_LUT0, m_HWC_R|m_HWC_G|m_HWC_B,bg_col); + LcdMskReg(inf, HWC_COLOR_LUT2, m_HWC_R|m_HWC_G|m_HWC_B,fg_col); + LcdSetBit(inf, SYS_CONFIG,m_HWC_RELOAD_EN); + LcdWrReg(inf, REG_CFG_DONE, 0x01); + return 0; +} + +#define RK29_CURSOR_WRITE_BIT(addr,mask,value) (*((char*)addr)) = (((*((char*)addr))&(~((char)mask)))|((char)value)) +int rk29_set_cursor_img_transform(char *data) +{ int x, y; + char *pmsk = data; + char *dst = (char*)rk29_cursor_buf; + unsigned char dmsk = 0; + unsigned int op,shift,offset; + + /* rk29 cursor is a 2 bpp 32x32 bitmap this routine + * clears it to transparent then combines the cursor + * shape plane with the colour plane to set the + * cursor */ + for (y = 0; y < 32; y++) + { + for (x = 0; x < 32; x++) + { + if ((x % 8) == 0) { + dmsk = *pmsk++; + } else { + dmsk <<= 1; + } + op = (dmsk & 0x80) ? 1 : 3; + shift = (x*2)%8; + offset = x/4; + RK29_CURSOR_WRITE_BIT((dst+offset),(3<device); + rk29_set_cursor_colour_map(inf, 0x000000ff, 0x00ff0000); + rk29_set_cursor_pos(inf, 0, 0); + rk29_set_cursor_img(inf, 0); + rk29_set_cursor_en(inf, 1); + return 0; +} #if 0 int rk29_set_cursor(struct fb_info *info, struct fb_cursor *cursor) @@ -1315,6 +1452,56 @@ static int fb0_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) break; case FBIOPUT_FBPHYADD: return info->fix.smem_start; + case FBIOPUT_SET_CURSOR_EN: + { + int en; + if(copy_from_user(&en, (void*)arg, sizeof(int))) + return -EFAULT; + rk29_set_cursor_en(inf, en); + } + break; + case FBIOPUT_SET_CURSOR_POS: + { + struct fbcurpos pos; + if(copy_from_user(&pos, (void*)arg, sizeof(struct fbcurpos))) + return -EFAULT; + rk29_set_cursor_pos(inf, pos.x , pos.y); + } + break; + case FBIOPUT_SET_CURSOR_IMG: + { + char cursor_buf[CURSOR_BUF_SIZE]; + if(copy_from_user(cursor_buf, (void*)arg, CURSOR_BUF_SIZE)) + return -EFAULT; + rk29_set_cursor_img(inf, cursor_buf); + } + break; + case FBIOPUT_SET_CURSOR_CMAP: + { + struct fb_image img; + if(copy_from_user(&img, (void*)arg, sizeof(struct fb_image))) + return -EFAULT; + rk29_set_cursor_colour_map(inf, img.bg_color, img.fg_color); + } + break; + case FBIOPUT_GET_CURSOR_RESOLUTION: + { + u32 panel_size[2]; + //struct rk29fb_inf *inf = dev_get_drvdata(info->device); + if(inf->fb1->var.rotate == 270) { + panel_size[0] = inf->cur_screen->y_res; //inf->cur_screen->y_res; change for hdmi video size + panel_size[1] = inf->cur_screen->x_res; + } else { + panel_size[0] = inf->cur_screen->x_res; + panel_size[1] = inf->cur_screen->y_res; + } + if(copy_to_user((void*)arg, panel_size, 8)) return -EFAULT; + } + case FBIOPUT_GET_CURSOR_EN: + { + u32 en = LcdReadBit(inf, SYS_CONFIG, m_HWC_ENABLE); + if(copy_to_user((void*)arg, &en, 4)) return -EFAULT; + } default: break; } @@ -1776,7 +1963,11 @@ int FB_Switch_Screen( struct rk29fb_screen *screen, u32 enable ) fb0_set_par(inf->fb0); LcdMskReg(inf, DSP_CTRL1, m_BLACK_MODE, v_BLACK_MODE(0)); LcdWrReg(inf, REG_CFG_DONE, 0x01); - + if(enable){ + rk29_set_cursor_en(inf, enable); + }else{ + rk29_set_cursor_en(inf, enable); + } return 0; } @@ -1799,6 +1990,7 @@ static ssize_t dsp_win0_info_read(struct device *device, xsize=LcdRdReg(inf, WIN0_DSP_INFO)& 0xffff; ysize=(LcdRdReg(inf, WIN0_DSP_INFO)>>16) & 0xffff; fbprintk("%s %d , %d, %d ,%d\n",__FUNCTION__,xpos,ypos,xsize,ysize); + rk29_set_cursor_test(inf->fb0); return snprintf(buf, PAGE_SIZE, "%d,%d,%d,%d\n", xpos,ypos,xsize,ysize); } @@ -1808,7 +2000,7 @@ static ssize_t dsp_win0_info_write(struct device *device, { printk("%s\n",__FUNCTION__); printk("%s %x \n",__FUNCTION__,*buf); - return 0; + return count; } static DEVICE_ATTR(dsp_win0_info, S_IRUGO|S_IWUSR, dsp_win0_info_read, dsp_win0_info_write); diff --git a/include/linux/fb.h b/include/linux/fb.h index 99950fde81a9..54ce1d9883b6 100755 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -20,6 +20,12 @@ struct dentry; #define FBIOPAN_DISPLAY 0x4606 #define FBIOPUT_16OR32 0x4607 #define FBIOPUT_FBPHYADD 0x4608 +#define FBIOPUT_SET_CURSOR_EN 0x4609 +#define FBIOPUT_SET_CURSOR_IMG 0x460a +#define FBIOPUT_SET_CURSOR_POS 0x460b +#define FBIOPUT_SET_CURSOR_CMAP 0x460c +#define FBIOPUT_GET_CURSOR_RESOLUTION 0x460d +#define FBIOPUT_GET_CURSOR_EN 0x460e #ifdef __KERNEL__ #define FBIO_CURSOR _IOWR('F', 0x08, struct fb_cursor_user) #else