📄 davincifb.c
字号:
struct dm_info *dm = (struct dm_info *) arg;
static unsigned long local_count=0;
++local_count;
//if (local_count % 2)
// return IRQ_HANDLED;
++dm->vsync_cnt;
wake_up_interruptible(&dm->vsync_wait);
return IRQ_HANDLED;
} /* Wait for a vsync interrupt. This routine sleeps so it can only be called * from process context. */static int dm64xxfb_wait_for_vsync(struct dm_win_info *w){ struct dm_info *dm = w->dm; wait_queue_t wq; unsigned long cnt; int ret; DBGENTER; init_waitqueue_entry(&wq, current); cnt = dm->vsync_cnt; ret = wait_event_interruptible_timeout(dm->vsync_wait, cnt != dm->vsync_cnt, dm->timeout); if (ret < 0) RETURN(ret); if (ret == 0) RETURN(-ETIMEDOUT); RETURN(0);}/* Sets a uniform attribute value over a rectangular area on the attribute * window. The attribute value (0 to 7) is passed through the fb_fillrect's * color parameter. */static int dm64xxfb_set_attr_blend(struct fb_fillrect *r){ struct fb_info *info = &dm.osd1->info; struct fb_var_screeninfo *var = &dm.osd1->info.var; unsigned long start = 0; u8 blend; u32 width_bytes; if (r->dx + r->width > var->xres_virtual) return -EINVAL; if (r->dy + r->height > var->yres_virtual) return -EINVAL; if (r->color < 0 || r->color > 7) return -EINVAL; /* since bits_per_pixel = 4, this will truncate the width if it is * not even. Similarly r->dx will be rounded down to an even pixel. * ... Do we want to return an error otherwise? */ width_bytes = r->width * var->bits_per_pixel / 8; start = dm.osd1->fb_base + r->dy * info->fix.line_length + r->dx * var->bits_per_pixel / 8; blend = (((u8) r->color & 0xf)<<4) | ((u8) r->color); while (r->height--) { start += info->fix.line_length; memset((void *) start, blend, width_bytes); } return 0;}static int dm64xxfb_set_attr_transp(int transp_on){}/* These position parameters are given through fb_var_screeninfo. * xp = var.reserved[0], yp = var.reserved[1], * xl = var.xres, yl = var.yres */static void set_win_position(char *id, u32 xp, u32 yp, u32 xl, u32 yl) //设置指定的窗口的位置{ int i = 0; DBGENTER; if (is_win(id, VID0)) { i = 0; /*printk("\n==============================>");printk("==============================>");printk("==============================>"); printk("Video Window 0 X Pixel Offset =%d\n", xp); printk("Video Window 0 Y Pixel Offset =%d\n", yp); printk("Video Window 0 X length =%d\n", xl); printk("Video Window 0 Y length =%d\n", yl); printk("VID0 XRES = =%d\n", VID0_XRES); */} else if (is_win(id, VID1)) { i = 1;/*printk("\n==============================>");printk("==============================>");printk("==============================>"); printk("Video Window 1 X Pixel Offset =%d\n", xp); printk("Video Window 1 Y Pixel Offset =%d\n", yp); printk("Video Window 1 X length =%d\n", xl); printk("Video Window 1 Y length =%d\n", yl); dispc_reg_out(OSD_WINXP(i), OSD0_XRES+16); dispc_reg_out(OSD_WINYP(i), OSD0_YRES+16); dispc_reg_out(OSD_WINXL(i), 712); dispc_reg_out(OSD_WINYL(i), 480);*/} else if (is_win(id, OSD0)) { i = 2;/* printk("OSD Window 0 X Pixel Offset =%d\n", xp); printk("OSD Window 0 Y Pixel Offset =%d\n", yp); printk("OSD Window 0 X length =%d\n", xl); printk("OSD Window 0 Y length =%d\n", yl);*/ } else if (is_win(id, OSD1)) { i = 3;// printk("OSD Window 1 X Pixel Offset =%d\n", xp);// printk("OSD Window 1 Y Pixel Offset =%d\n", yp);// printk("OSD Window 1 X length =%d\n", xl);// printk("OSD Window 1 Y length =%d\n", yl); } dispc_reg_out(OSD_WINXP(i), xp); dispc_reg_out(OSD_WINYP(i), yp); dispc_reg_out(OSD_WINXL(i), xl); dispc_reg_out(OSD_WINYL(i), yl); DBGEXIT;}static inline void get_win_position(struct dm_win_info *w, //获取指定的窗口w的位置
u32 *xp, u32 *yp, u32 *xl, u32 *yl){ struct fb_var_screeninfo *v = &w->info.var; *xp = x_pos(w); *yp = y_pos(w); *xl = v->xres; *yl = v->yres;}/* Returns 1 if the windows overlap, 0 otherwise */ //窗口w与指定的坐标之间有重叠返回1,否则0static int window_overlap(struct dm_win_info *w, u32 xp, u32 yp, u32 xl, u32 yl){ u32 _xp = 0, _yp = 0, _xl = 0, _yl = 0;#define OVERLAP(x1, y1, x2, y2, x3, y3, x4, y4) \(!( ((x1)<(x3) && (x2)<(x3)) || ((x1)>(x4) && (x2)>(x4)) || \ ((y1)<(y3) && (y2)<(y3)) || ((y1)>(y4) && (y2)>(y4)) ) \) DBGENTER; //进入调试 if (!w) RETURN(0); get_win_position(w, &_xp, &_yp, &_xl, &_yl); RETURN(OVERLAP(xp, yp, xp + xl, yp + yl, _xp, _yp, _xp + _xl, _yp + _yl));#undef OVERLAP }/* Returns 1 if the window parameters are within VID0, 0 otherwise */ //指定坐标的窗口是否在VID0中static int within_vid0_limits(u32 xp, u32 yp, u32 xl, u32 yl){ u32 vid0_xp = 0, vid0_yp = 0, vid0_xl = 0, vid0_yl = 0; DBGENTER; if (!dm.vid0) RETURN(1); get_win_position(dm.vid0, &vid0_xp, &vid0_yp, &vid0_xl, &vid0_yl); if ((xp >= vid0_xp) && (yp >= vid0_yp) && (xp + xl <= vid0_xp + vid0_xl) && (yp + yl <= vid0_yp + vid0_yl)) RETURN(1); RETURN(0);}/* VID0 must be large enough to hold all other windows */static int check_new_vid0_size(u32 xp0, u32 yp0, u32 xl0, u32 yl0) /*vid0必须足够大,让所有的其它窗口包含在VID0中*/{ u32 _xp = 0, _yp = 0, _xl = 0, _yl = 0;#define WITHIN_LIMITS \ ((_xp >= xp0) && (_yp >= yp0) && \ (_xp + _xl <= xp0 + xl0) && (_yp + _yl <= yp0 + yl0)) if (dm.osd0) { get_win_position(dm.osd0, &_xp, &_yp, &_xl, &_yl); if (!WITHIN_LIMITS) RETURN(-EINVAL); } if (dm.osd1) { get_win_position(dm.osd1, &_xp, &_yp, &_xl, &_yl); if (!WITHIN_LIMITS) RETURN(-EINVAL); } if (dm.vid1) { get_win_position(dm.vid1, &_xp, &_yp, &_xl, &_yl); if (!WITHIN_LIMITS) RETURN(-EINVAL); } RETURN(0); #undef WITHIN_LIMITS }/*---------------------------------------------------------------------------*//** * dm64xxfb_check_var - Validates a var passed in. * @var: frame buffer variable screen structure * @info: frame buffer structure that represents a single frame buffer * * Checks to see if the hardware supports the state requested by * var passed in. This function does not alter the hardware state!!! * This means the data stored in struct fb_info and struct xxx_par do * not change. This includes the var inside of struct fb_info. * Do NOT change these. This function can be called on its own if we * intent to only test a mode and not actually set it. * If the var passed in is slightly off by what the hardware can support * then we alter the var PASSED in to what we can do. * * Returns negative errno on error, or zero on success. */static int dm64xxfb_check_var(struct fb_var_screeninfo *var, //检查var中的设置是否满足硬件的支持要求,可能会跟据需要改变var的设置 struct fb_info *info){ const struct dm_win_info *w = (const struct dm_win_info *) info->par;
struct fb_var_screeninfo v; /* Rules: * 1) Vid1, OSD0, OSD1 and Cursor must be fully contained inside of Vid0. * 2) Vid0 and Vid1 are both set to accept YUV 4:2:2 (for now). * 3) OSD window data is always packed into 32-bit words and left justified. * 4) Each horizontal line of window data must be a multiple of 32 bytes. * 32 bytes = 32 bytes / 2 bytes per pixel = 16 pixels. * This implies that 'xres' must be a multiple of 32 bytes. * 5) The offset registers hold the distance between the start of one line and * the start of the next. This offset value must be a multiple of 32 bytes. * This implies that 'xres_virtual' is also a multiple of 32 bytes. Note * that 'xoffset' needn't be a multiple of 32 bytes. * 6) OSD0 is set to accept RGB565. * dispc_reg_merge(OSD_OSDWIN0ND, OSD_OSDWIN0ND_RGB0E, OSD_OSDWIN0ND_RGB0E) * 7) OSD1 is set to be the attribute window. * 8) Vid1 startX = Vid0 startX + N * 16 pixels (32 bytes) * 9) Vid1 width = (16*N - 8) pixels * 10) When one of the OSD windows is in RGB565, it cannot overlap with Vid1. * 11) Vid1 start X position must be offset a multiple of 16 pixels from the * left edge of Vid0. */ DBGENTER; memcpy(&v, var, sizeof(v)); RETURN(0); /* do board-specific checks on the var */ if (dm64xx_venc_check_mode(w, &v)) RETURN(-EINVAL); if (v.xres_virtual < v.xres || v.yres_virtual < v.yres) RETURN(-EINVAL); if (v.xoffset > v.xres_virtual - v.xres) RETURN(-EINVAL); if (v.yoffset > v.yres_virtual - v.yres) RETURN(-EINVAL); if ( //(v.xres * v.bits_per_pixel/8) % 32 || (v.xres_virtual * v.bits_per_pixel/8) % 32) /* Rules 4, 5 */ RETURN(-EINVAL); if (v.xres_virtual * v.yres_virtual * v.bits_per_pixel/8 > w->fb_size) //总的像素数大于FB缓冲区 RETURN(-EINVAL); if (!is_win(info->fix.id, VID0)) { /* Rule 1 */ /*When one of the OSD windows is in RGB565, it cannot overlap with Vid1. */// printk("****Going into vid0_limits*****\n");// printk("X Position: %d, Y Position: %d, X Length: %d, Y Length: %d\n",x_pos(w), y_pos(w), v.xres, v.yres); if (!within_vid0_limits(x_pos(w), y_pos(w), v.xres, v.yres)) RETURN(-EINVAL); } if (is_win(info->fix.id, OSD0)) { /* Rule 10 */ if (window_overlap(w->dm->vid1, x_pos(w), y_pos(w), v.xres, v.yres)) RETURN(-EINVAL); /* Rule 5 */ v.bits_per_pixel = 16; v.red.offset = 11; v.green.offset = 5; v.blue.offset = 0; v.red.length = 5; v.green.length = 6; v.blue.length = 5; v.transp.offset = v.transp.length = 0; v.red.msb_right = v.green.msb_right = v.blue.msb_right = v.transp.msb_right = 0; v.nonstd = 0; v.accel_flags = 0; } else if (is_win(info->fix.id, OSD1)) { v.bits_per_pixel = 4; } else if (is_win(info->fix.id, VID0)) { if (check_new_vid0_size(x_pos(w), y_pos(w), v.xres, v.yres)) RETURN(-EINVAL); v.bits_per_pixel = 16; } else if (is_win(info->fix.id, VID1)) { /* Rule 10 */ /* REVISIT: Confirm that overlapping VID1, OSD0 is ok */ // if (window_overlap(w->dm->osd0,// x_pos(w), y_pos(w),// v.xres, v.yres))// RETURN(-EINVAL); /* Rule 11 */ if ((x_pos(w->dm->vid0) - x_pos(w)) % 16) RETURN(-EINVAL); /* Video1 may be in YUV or RGB888 format */ if ((v.bits_per_pixel != 16) && (v.bits_per_pixel != 32)) RETURN(-EINVAL); v.bits_per_pixel = 32; v.red.offset = 16; v.green.offset = 8; v.blue.offset = 0; v.red.length = 8; v.green.length = 8; v.blue.length = 8; v.transp.offset = v.transp.length = 0; v.red.msb_right = v.green.msb_right = v.blue.msb_right = v.transp.msb_right = 0; } else RETURN(-EINVAL); memcpy(var, &v, sizeof(v)); RETURN(0);}/* Interlaced = Frame mode, Non-interlaced = Field mode */static void set_interlaced(char *id, unsigned int on) //把显示显示设为帧模式{ on = (on == 0) ? 0 : ~0; DBGENTER; if (is_win(id, VID0)) dispc_reg_merge(OSD_VIDWINMD, on, OSD_VIDWINMD_VFF0); else if (is_win(id, VID1)) dispc_reg_merge(OSD_VIDWINMD, on, OSD_VIDWINMD_VFF1); else if (is_win(id, OSD0)) dispc_reg_merge(OSD_OSDWIN0MD, on, OSD_OSDWIN0MD_OFF0); else if (is_win(id, OSD1)) dispc_reg_merge(OSD_OSDWIN1MD, on, OSD_OSDWIN1MD_OFF1); DBGEXIT;}/* For zooming, we just have to set the start of framebuffer, the zoom factors * and the display size. The hardware will then read only * (display size / zoom factor) area of the framebuffer and zoom and * display it. In the following function, we assume that the start of * framebuffer and the display size parameters are set already. */static void set_zoom(int WinID, int h_factor, int v_factor) //设置放大的因数{ DBGENTER; switch(WinID){ case 0: //VID0 dispc_reg_merge(OSD_VIDWINMD, h_factor << OSD_VIDWINMD_VHZ0_SHIFT, OSD_VIDWINMD_VHZ0); dispc_reg_merge(OSD_VIDWINMD, v_factor << OSD_VIDWINMD_VVZ0_SHIFT, OSD_VIDWINMD_VVZ0); break; case 1: //VID1 dispc_reg_merge(OSD_VIDWINMD, h_factor << OSD_VIDWINMD_VHZ1_SHIFT, OSD_VIDWINMD_VHZ1); dispc_reg_merge(OSD_VIDWINMD, v_factor << OSD_VIDWINMD_VVZ1_SHIFT, OSD_VIDWINMD_VVZ1); break; case 2://OSD0
dispc_reg_merge(OSD_OSDWIN0MD,
h_factor << OSD_OSDWIN0MD_OHZ0_SHIFT,
OSD_OSDWIN0MD_OHZ0);
dispc_reg_merge(OSD_OSDWIN0MD,
v_factor << OSD_OSDWIN0MD_OVZ0_SHIFT,
OSD_OSDWIN0MD_OVZ0);
break;
case 3:
dispc_reg_merge(OSD_OSDWIN1MD,
h_factor << OSD_OSDWIN1MD_OHZ1_SHIFT,
OSD_OSDWIN1MD_OHZ1);
dispc_reg_merge(OSD_OSDWIN1MD,
v_factor << OSD_OSDWIN1MD_OVZ1_SHIFT,
OSD_OSDWIN1MD_OVZ1);
break;
}
DBGEXIT;
}/* Chooses the ROM CLUT for now. Can be extended later. */static void set_bg_color(u8 clut, u8 color_offset) //设置背景颜色{ clut = 0; /* 0 = ROM, 1 = RAM */
DBGENTER;
dispc_reg_merge(OSD_MODE, OSD_MODE_BCLUT & clut, OSD_MODE_BCLUT);
dispc_reg_merge(OSD_MODE, color_offset << OSD_MODE_CABG_SHIFT,
OSD_MODE_CABG);
DBGEXIT;}static void set_sdram_params(char *id, u32 addr, u32 line_length) //设置指定窗口的ram的地址{ DBGENTER; /* The parameters to be written to the registers should be in * multiple of 32 bytes */ addr = addr ; /* div by 32 */ line_length = line_length /32 ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -