📄 hifb.c
字号:
/*****************************************************************************//* Copyright 2005 - 2005, Huawei Tech. Co., Ltd. *//* ALL RIGHTS RESERVED *//* *//* FileName: HI3510fb.c *//* Version: 01a *//* Description: create the framebuffer driver for HI3510 *//* *//* History: *//* 1. 01a,2006-5-19,z37062 Create this file. *//* 2. 01b,2006-7-21,z37062 fix the bug [D00564]. *//* add the open and close function *//* add the codes to select the layer when configureing *//* the module paramter. *//* 3. 01c,2006-7-25,z37062 fix the bug [D00565]. *//* Modify the default resultion when loading the module. *//*****************************************************************************/#include <linux/config.h>#include <linux/ctype.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/tty.h>#include <linux/slab.h>#include <linux/delay.h>#include <linux/fb.h>#include <linux/init.h>#include <asm/uaccess.h>#include <asm/ptrace.h>#include "asm/arch/media-mem.h" /*defined memory manage interface */#include "hi_vou.h" /* defined vou driver interface */#include "hifb.h"typedef struct taghi3510fb_par{ unsigned short which_layer; unsigned char alpha0; unsigned char alpha1; unsigned short screen_startx; unsigned short screen_starty; fb_colorkey ckey; atomic_t ref_count;}hi3510fb_par;#ifdef MODULEstatic char* video="hi3510fb:vram1_size:0,vram2_size:0";module_param(video, charp, S_IRUGO); #endif#define HI3510FB_NAME "hi3510fb"#define HI3510FB_DEF_VRAM_SIZE 0//(1024*768*4) /*byte*///#define HI3510FB_DEF_STRIDE 720*2 /*byte*///#define HI3510FB_DEF_WIDTH 720 /*pixel*///#define HI3510FB_DEF_HEIGHT 576 /*pixel*/#define HI3510FB_DEF_STRIDE 800*2 /*byte*/#define HI3510FB_DEF_WIDTH 800 /*pixel*/#define HI3510FB_DEF_HEIGHT 480 /*pixel*/#define HI3510FB_DEF_DEPTH 16 /*bits*///#define HI3510FB_DEF_XSTART 0#define HI3510FB_DEF_XSTART 0#define HI3510FB_DEF_YSTART 0#define HI3510FB_DEF_ALPHA 0x80#define HI3510FB_DEF_PIXEL_FORMAT PIXEL_FORMAT_RGB555//#define HI3510FB_MIN_VRAM_SIZE (720*576*2)#define HI3510FB_MIN_VRAM_SIZE (800*480*2)#define HI3510FB_OVLAYER_1 (VOU_LAYER_OVER1)#define HI3510FB_OVLAYER_2 (VOU_LAYER_OVER2)/*the value comes from tde_reg.h*/#define HI3510FB_2D_BASE_SIZE 0x84#define HI3510FB_2D_BASE_ADDR 0x90010300#define HI3510FB_TRACE(...) printk(KERN_INFO"hi3510fb debug: " __VA_ARGS__)#define HI3510FB_ERR(...) printk(KERN_WARNING"hi3510fb error: " __VA_ARGS__)#define HI3510FB_OVL1_OPT_NAME "vram1_size:"#define HI3510FB_OVL2_OPT_NAME "vram2_size:"#define HI3510FB_OVL_OPT_NAME_LEN (sizeof(HI3510FB_OVL1_OPT_NAME)-1)#define HI3510FB_FB_INFO(which_layer) (gphi3510fb_fb_infos[which_layer-1])static void __exit hi3510fb_overlay_cleanup(int which_layer, int need_unregister);static struct fb_info* gphi3510fb_fb_infos[2];static struct fb_fix_screeninfo gsthi3510fb_def_fix = { .id = HI3510FB_NAME, .type = FB_TYPE_PACKED_PIXELS, .visual = FB_VISUAL_TRUECOLOR, .xpanstep = 1, .ypanstep = 1, .ywrapstep = 0, .line_length = HI3510FB_DEF_STRIDE, .accel = FB_ACCEL_HI3510 };static struct fb_var_screeninfo gsthi3510fb_def_var = { .xres = HI3510FB_DEF_WIDTH, .yres = HI3510FB_DEF_HEIGHT, .xres_virtual = HI3510FB_DEF_WIDTH, .yres_virtual = HI3510FB_DEF_HEIGHT, .bits_per_pixel = HI3510FB_DEF_DEPTH, .red = {10, 5, 0}, .green = {5, 5, 0}, .blue = {0, 5, 0}, .transp = {15, 1, 0}, .activate = FB_ACTIVATE_NOW, .pixclock = -1, /* pixel clock in ps (pico seconds) */ .left_margin = -1, /* time from sync to picture */ .right_margin = -1, /* time from picture to sync */ .upper_margin=-1, /* time from sync to picture */ .lower_margin=-1, .hsync_len=-1, /* length of horizontal sync */ .vsync_len=-1, /* length of vertical sync */};/****************************************************************************** Function : hi3510fb_check_var Description : check if the paramter for framebuffer is supported. Data Accessed : Data Updated : Output : None Input : struct fb_var_screeninfo *var struct fb_info *info Return : return 0, if the paramter is supported, otherwise,return error code. Others : 0******************************************************************************/static int hi3510fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){ unsigned long stride = 0; unsigned long vram_size = 0; unsigned long bpp = 0; /*RGBA5551*/ struct fb_bitfield r_16 = {10, 5, 0}; struct fb_bitfield g_16 = {5, 5, 0}; struct fb_bitfield b_16 = {0, 5, 0}; struct fb_bitfield a_16 = {15, 1, 0}; /*RGBA8888*/ struct fb_bitfield r_32 = {16, 8, 0}; struct fb_bitfield g_32 = {8, 8, 0}; struct fb_bitfield b_32 = {0, 8, 0}; struct fb_bitfield a_32 = {24, 8, 0}; /*check the pixel format, if it is supported by 3510, return -EINVAL*/ if (var->bits_per_pixel == 32) { var->red = r_32; var->green = g_32; var->blue = b_32; var->transp = a_32; } else { var->bits_per_pixel = 16; var->red = r_16; var->green = g_16; var->blue = b_16; var->transp = a_16; } bpp = var->bits_per_pixel>>3; /*if the stride isnot 4 byte aligned, modify the virtual width to fit*/ stride = var->xres_virtual*bpp; if (stride & 0x3) { var->xres_virtual++; stride += bpp; } if (var->xres > var->xres_virtual) { var->xres = var->xres_virtual; } if (var->yres > var->yres_virtual) { var->yres = var->yres_virtual; } /*check if the vram is engouh*/ vram_size = stride*var->yres_virtual; if (vram_size > info->fix.smem_len) { HI3510FB_TRACE("Need more video memory!\n"); return -EINVAL; } /*check if the offset is valid*/ if (var->xoffset + var->xres > var->xres_virtual || var->yoffset + var->yres > var->yres_virtual) { HI3510FB_TRACE("offset is invalid!\n"); return -EINVAL; } return 0;}/****************************************************************************** Function : hi3510fb_set_par Description : set the variable parmater and make it use Data Accessed : Data Updated : Output : None Input : struct fb_info *info Return : return 0 Others : 0******************************************************************************/static int hi3510fb_set_par(struct fb_info *info){ hi3510fb_par *par = (hi3510fb_par *)info->par; unsigned long display_addr = 0; unsigned long stride; RECT_t layer_rc; /*set the stride and display start address*/ stride = info->var.xres_virtual*(info->var.bits_per_pixel>>3); display_addr = info->fix.smem_start + stride*info->var.yoffset + info->var.xoffset*(info->var.bits_per_pixel>>3); info->fix.line_length = stride; VOU_LayerSetAddrAndStride(par->which_layer, display_addr, 0, stride, 0); /*set the pixel format and screen width and height*/ if (info->var.bits_per_pixel == 16) { VOU_LayerSetDataType(par->which_layer, HI3510FB_DEF_PIXEL_FORMAT); } else if (info->var.bits_per_pixel == 32) { VOU_LayerSetDataType(par->which_layer, PIXEL_FORMAT_RGB888); } else { HI3510FB_TRACE("the pixel foramt is not supported, bits_per_pixel:%d!\n", info->var.bits_per_pixel); } layer_rc.x = par->screen_startx; layer_rc.y = par->screen_starty; layer_rc.w = info->var.xres; layer_rc.h = info->var.yres; if (layer_rc.h == 0 || layer_rc.w == 0) { VOU_LayerDisable(par->which_layer); } else { VOU_LayerSetRect(par->which_layer, layer_rc); VOU_LayerEnable(par->which_layer); } return 0;}/****************************************************************************** Function : hi3510fb_pan_display Description : pan display. Data Accessed : Data Updated : Output : None Input : struct fb_var_screeninfo *var Return : return 0 Others : 0******************************************************************************/static int hi3510fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info){ hi3510fb_par *par = (hi3510fb_par *)info->par; unsigned long display_addr = 0; unsigned long stride = 0; /*set the stride and display start address*/ stride = var->xres_virtual*(var->bits_per_pixel>>3); display_addr = info->fix.smem_start + stride*var->yoffset + var->xoffset*(var->bits_per_pixel>>3); VOU_LayerSetAddrAndStride(par->which_layer, display_addr, 0, stride, 0); return 0;}/****************************************************************************** Function : hi3510fb_ioctl Description : set the colorkey or alpha for overlay Data Accessed : Data Updated : Output : None Input : struct inode *inode struct file *file unsigned int cmd unsigned long arg struct fb_info *info Return : return 0 if succeed, otherwise return error code Others : 0******************************************************************************/static int hi3510fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg, struct fb_info *info){ hi3510fb_par *par = (hi3510fb_par *)info->par; void __user *argp = (void __user *)arg; if (argp == NULL) { return -EINVAL; } switch (cmd) { case FBIOGET_ALPHA_HI3510 : { int alpha = 0; if (info->var.bits_per_pixel != 16) { HI3510FB_TRACE("The pixel depth is invalid when getting alpha!\n"); return -EPERM; } alpha = (par->alpha1<<8) + par->alpha0; if (copy_to_user(argp, &alpha, sizeof(int)) < 0) { return -EFAULT; } break; } case FBIOPUT_ALPHA_HI3510 : { int alpha = 0; if (info->var.bits_per_pixel != 16) { HI3510FB_TRACE("The pixel depth is invalid when seting alpha!\n"); return -EPERM; } if (copy_from_user(&alpha, argp, sizeof(int) )< 0) { return -EFAULT; } par->alpha0 = alpha & 0x00ff; par->alpha1 = (alpha >> 8) & 0x00ff; VOU_LayerSetAlpha(par->which_layer, par->alpha0, par->alpha1); break; } case FBIOGET_COLORKEY_HI3510: { if (copy_to_user(argp, &par->ckey, sizeof(fb_colorkey)) < 0) { return -EFAULT; } break; } case FBIOPUT_COLORKEY_HI3510: { fb_colorkey ckey; unsigned long key; unsigned char key_enable, keymask_enable; if (copy_from_user(&ckey, argp, sizeof(fb_colorkey))< 0) { return -EFAULT; } key_enable = ckey.key_enable > 0 ? TRUE : FALSE; keymask_enable = ckey.mask_enable > 0 ? TRUE : FALSE; if (info->var.bits_per_pixel == 16) { unsigned char r, g, b; /*extend 16 bit to 24 bit, rules is : (r << 1) + (g << 2) + (b << 3); */ key = (unsigned short)ckey.key; r = (key >> info->var.red.offset) << 3; g = (key >> info->var.green.offset) << 3; b = (key >> info->var.blue.offset) << 3; key = (r << 16) + (g << 8) + b; } else { key = ckey.key; } HI3510FB_TRACE("key_enable:%d, colorkey:%x\n", key_enable, (unsigned int)key); VOU_LayerSetKey(par->which_layer, key_enable, key); VOU_LayerSetMask(par->which_layer, keymask_enable, ckey.rmask, ckey.gmask); HI3510FB_TRACE("keymask_enable:%d, rmaskkey:%x, gmask:%x\n", keymask_enable, ckey.rmask, ckey.gmask); par->ckey = ckey; break; } case FBIOGET_SCREEN_ORIGIN_HI3510: { unsigned long origin; origin = (par->screen_startx << 16) + par->screen_starty; if (copy_to_user(argp, &origin, sizeof(origin)) < 0) { return -EFAULT; } break; } case FBIOPUT_SCREEN_ORIGIN_HI3510: {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -