📄 davincifb.c
字号:
} RETURN(0);}/** * davincifb_pan_display - NOT a required function. Pans the display. * @var: frame buffer variable screen structure * @info: frame buffer structure that represents a single frame buffer * * Pan (or wrap, depending on the `vmode' field) the display using the * `xoffset' and `yoffset' fields of the `var' structure. * If the values don't fit, return -EINVAL. * * Returns negative errno on error, or zero on success. */static int davincifb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info){ struct dm_win_info *w = (struct dm_win_info *)info->par; u32 start = 0, offset = 0; DBGENTER; if (var->xoffset > var->xres_virtual - var->xres) RETURN(-EINVAL); if (var->yoffset > var->yres_virtual - var->yres) RETURN(-EINVAL); if ((var->xres_virtual * var->bits_per_pixel / 8) % 32) RETURN(-EINVAL); offset = var->yoffset * info->fix.line_length + var->xoffset * var->bits_per_pixel / 8; start = (u32) w->fb_base_phys + offset; if ((dispc_reg_in(VENC_VSTAT) & 0x00000010)==0x10) set_sdram_params(info->fix.id, start, info->fix.line_length); else w->sdram_address = start; RETURN(0);}/** * davincifb_blank - NOT a required function. Blanks the display. * @blank_mode: the blank mode we want. * @info: frame buffer structure that represents a single frame buffer * * Blank the screen if blank_mode != 0, else unblank. Return 0 if * blanking succeeded, != 0 if un-/blanking failed due to e.g. a * video mode which doesn't support it. Implements VESA suspend * and powerdown modes on hardware that supports disabling hsync/vsync: * blank_mode == 2: suspend vsync * blank_mode == 3: suspend hsync * blank_mode == 4: powerdown * * Returns negative errno on error, or zero on success. * */static int davincifb_blank(int blank_mode, struct fb_info *info){ DBGENTER; /* ... */ RETURN(0);}static int parse_win_params(char *wp, int *xres, int *yres, int *xpos, int *ypos){ char *s; if ((s = strsep(&wp, "x")) == NULL) return -EINVAL; *xres = simple_strtoul(s, NULL, 0); if ((s = strsep(&wp, "@")) == NULL) return -EINVAL; *yres = simple_strtoul(s, NULL, 0); if ((s = strsep(&wp, ",")) == NULL) return -EINVAL; *xpos = simple_strtoul(s, NULL, 0); if ((s = strsep(&wp, ":")) == NULL) return -EINVAL; *ypos = simple_strtoul(s, NULL, 0); return 0;}/* * Pass boot-time options by adding the following string to the boot params: * video=davincifb:[option[:option]] * Valid options: * output=[lcd|ntsc|pal] * format=[composite|s-video|component|rgb] * vid0=[off|MxN@X,Y] * vid1=[off|MxN@X,Y] * osd0=[off|MxN@X,Y] * osd1=[off|MxN@X,Y] * MxN specify the window resolution (displayed size) * X,Y specify the window position * M, N, X, Y are integers * M, X should be multiples of 16 */#ifndef MODULEint __init davincifb_setup(char *options){ char *this_opt; u32 xres, yres, xpos, ypos; int format_yres = 480; DBGENTER; printk("davincifb: Options \"%s\"\n", options); if (!options || !*options) return 0; while ((this_opt = strsep(&options, ":")) != NULL) { if (!*this_opt) continue; if (!strncmp(this_opt, "output=", 7)) { if (!strncmp(this_opt + 7, "lcd", 3)) { dmparams.output = LCD; dmparams.format = 0; } else if (!strncmp(this_opt + 7, "ntsc", 4)) dmparams.output = NTSC; else if (!strncmp(this_opt + 7, "pal", 3)) dmparams.output = PAL; } else if (!strncmp(this_opt, "format=", 7)) { if (dmparams.output == LCD) continue; if (!strncmp(this_opt + 7, "composite", 9)) dmparams.format = COMPOSITE; else if (!strncmp(this_opt + 7, "s-video", 7)) dmparams.format = SVIDEO; else if (!strncmp(this_opt + 7, "component", 9)) dmparams.format = COMPONENT; else if (!strncmp(this_opt + 7, "rgb", 3)) dmparams.format = RGB; } else if (!strncmp(this_opt, "vid0=", 5)) { if (!strncmp(this_opt + 5, "off", 3)) dmparams.windows &= ~(1 << VID0); else if (!parse_win_params(this_opt + 5, &xres, &yres, &xpos, &ypos)) { dmparams.vid0_xres = xres; dmparams.vid0_yres = yres; dmparams.vid0_xpos = xpos; dmparams.vid0_ypos = ypos; } } else if (!strncmp(this_opt, "vid1=", 5)) { if (!strncmp(this_opt + 5, "off", 3)) dmparams.windows &= ~(1 << VID1); else if (!parse_win_params(this_opt + 5, &xres, &yres, &xpos, &ypos)) { dmparams.vid1_xres = xres; dmparams.vid1_yres = yres; dmparams.vid1_xpos = xpos; dmparams.vid1_ypos = ypos; } } else if (!strncmp(this_opt, "osd0=", 5)) { if (!strncmp(this_opt + 5, "off", 3)) dmparams.windows &= ~(1 << OSD0); else if (!parse_win_params(this_opt + 5, &xres, &yres, &xpos, &ypos)) { dmparams.osd0_xres = xres; dmparams.osd0_yres = yres; dmparams.osd0_xpos = xpos; dmparams.osd0_ypos = ypos; } } else if (!strncmp(this_opt, "osd1=", 5)) { if (!strncmp(this_opt + 5, "off", 3)) dmparams.windows &= ~(1 << OSD1); else if (!parse_win_params(this_opt + 5, &xres, &yres, &xpos, &ypos)) { dmparams.osd1_xres = xres; dmparams.osd1_yres = yres; dmparams.osd1_xpos = xpos; dmparams.osd1_ypos = ypos; } } } printk(KERN_INFO "DaVinci: " "Output on %s%s, Enabled windows: %s %s %s %s\n", (dmparams.output == LCD) ? "LCD" : (dmparams.output == NTSC) ? "NTSC" : (dmparams.output == PAL) ? "PAL" : "unknown device!", (dmparams.format == 0) ? "" : (dmparams.format == COMPOSITE) ? " in COMPOSITE format" : (dmparams.format == SVIDEO) ? " in SVIDEO format" : (dmparams.format == COMPONENT) ? " in COMPONENT format" : (dmparams.format == RGB) ? " in RGB format" : "", (dmparams.windows & (1 << VID0)) ? "Video0" : "", (dmparams.windows & (1 << VID1)) ? "Video1" : "", (dmparams.windows & (1 << OSD0)) ? "OSD0" : "", (dmparams.windows & (1 << OSD1)) ? "OSD1" : ""); if (dmparams.output == NTSC) { format_yres = 480; } else if (dmparams.output == PAL) { format_yres = 576; } else { printk(KERN_INFO "DaVinci:invalid format..defaulting width to 480\n"); } dmparams.osd0_yres = osd0_default_var.yres = format_yres; dmparams.osd1_yres = osd1_default_var.yres = format_yres; dmparams.vid0_yres = vid0_default_var.yres = format_yres; dmparams.vid1_yres = vid1_default_var.yres = format_yres; osd0_default_var.yres_virtual = format_yres * DOUBLE_BUF; osd1_default_var.yres_virtual = format_yres * DOUBLE_BUF; vid0_default_var.yres_virtual = format_yres * TRIPLE_BUF; vid1_default_var.yres_virtual = format_yres * TRIPLE_BUF; if (dmparams.windows & (1 << VID0)) printk(KERN_INFO "Setting Video0 size %dx%d, " "position (%d,%d)\n", dmparams.vid0_xres, dmparams.vid0_yres, dmparams.vid0_xpos, dmparams.vid0_ypos); if (dmparams.windows & (1 << VID1)) printk(KERN_INFO "Setting Video1 size %dx%d, " "position (%d,%d)\n", dmparams.vid1_xres, dmparams.vid1_yres, dmparams.vid1_xpos, dmparams.vid1_ypos); if (dmparams.windows & (1 << OSD0)) printk(KERN_INFO "Setting OSD0 size %dx%d, " "position (%d,%d)\n", dmparams.osd0_xres, dmparams.osd0_yres, dmparams.osd0_xpos, dmparams.osd0_ypos); if (dmparams.windows & (1 << OSD1)) printk(KERN_INFO "Setting OSD1 size %dx%d, " "position (%d,%d)\n", dmparams.osd1_xres, dmparams.osd1_yres, dmparams.osd1_xpos, dmparams.osd1_ypos); RETURN(0);}#endifstatic int mem_release(struct dm_win_info *w){ DBGENTER; if (!w->alloc_fb_mem) { iounmap((void *)w->fb_base); release_mem_region(w->fb_base_phys, w->fb_size); } else dma_free_coherent(NULL, w->fb_size, (void *)w->fb_base, w->fb_base_phys); kfree(w); RETURN(0);}static int mem_alloc(struct dm_win_info **win, dma_addr_t fb_base_phys, unsigned long fb_size, char *fbname){ struct dm_win_info *w; struct device *dev = dm->dev; DBGENTER; w = kmalloc(sizeof(struct dm_win_info), GFP_KERNEL); if (!w) { dev_err(dev, "%s: could not allocate memory\n", fbname); RETURN(-ENOMEM); } memset(w, 0, sizeof(struct dm_win_info)); w->fb_base_phys = fb_base_phys; w->fb_size = fb_size; /* A null base address indicates that the framebuffer memory should be * dynamically allocated. */ if (!w->fb_base_phys) w->alloc_fb_mem = 1; if (!w->alloc_fb_mem) { if (!request_mem_region(w->fb_base_phys, w->fb_size, fbname)) { dev_err(dev, "%s: cannot reserve FB region\n", fbname); goto free_par; } w->fb_base = (unsigned long)ioremap(w->fb_base_phys, w->fb_size); if (!w->fb_base) { dev_err(dev, "%s: cannot map framebuffer\n", fbname); goto release_fb; } } else { /* allocate coherent memory for the framebuffer */ w->fb_base = (unsigned long)dma_alloc_coherent(dev, w->fb_size, &w->fb_base_phys, GFP_KERNEL | GFP_DMA); if (!w->fb_base) { dev_err(dev, "%s: cannot allocate framebuffer\n", fbname); goto free_par; } dev_dbg(dev, "Framebuffer allocated at 0x%x " "mapped to 0x%x, size %dk\n", (unsigned)w->fb_base_phys, (unsigned)w->fb_base, (unsigned)w->fb_size / 1024); } *win = w; RETURN(0); release_fb: if (!w->alloc_fb_mem) release_mem_region(w->fb_base_phys, w->fb_size); free_par: kfree(w); RETURN(-ENOMEM);}static struct fb_info *init_fb_info(struct dm_win_info *w, struct fb_var_screeninfo *var, char *id){ struct fb_info *info = &(w->info); struct dm_info *dm = w->dm; DBGENTER; /* initialize the fb_info structure */ info->flags = FBINFO_DEFAULT; info->fbops = &davincifb_ops; info->screen_base = (char *)(w->fb_base);/* info->currcon = -1; */ info->pseudo_palette = w->pseudo_palette; info->par = w; /* Initialize variable screeninfo. * The variable screeninfo can be directly specified by the user * via an ioctl. */ memcpy(&info->var, var, sizeof(info->var)); info->var.activate = FB_ACTIVATE_NOW; /* Initialize fixed screeninfo. * The fixed screeninfo cannot be directly specified by the user, but * it may change to reflect changes to the var info. */ strlcpy(info->fix.id, id, sizeof(info->fix.id)); info->fix.smem_start = w->fb_base_phys; info->fix.line_length = (info->var.xres_virtual * info->var.bits_per_pixel) / 8; info->fix.smem_len = w->fb_size; info->fix.type = FB_TYPE_PACKED_PIXELS; info->fix.visual = (info->var.bits_per_pixel <= 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; info->fix.xpanstep = 0; info->fix.ypanstep = 0; info->fix.ywrapstep = 0; info->fix.type_aux = 0; info->fix.mmio_start = dm->mmio_base_phys; info->fix.mmio_len = dm->mmio_size; info->fix.accel = FB_ACCEL_NONE; w->sdram_address = 0; DBGEXIT; return info;}static void davincifb_ntsc_composite_config(int on){ DBGENTER; if (on) { /* Reset video encoder module */ dispc_reg_out(VENC_VMOD, 0); /* Enable Composite output and start video encoder */ dispc_reg_out(VENC_VMOD, (VENC_VMOD_VIE | VENC_VMOD_VENC)); /* Set REC656 Mode */ dispc_reg_out(VENC_YCCCTL, 0x1); /* Enable output mode and NTSC */ dispc_reg_out(VENC_VMOD, 0x1003); /* Enable all DACs */ dispc_reg_out(VENC_DACTST, 0); } else { /* Reset video encoder module */ dispc_reg_out(VENC_VMOD, 0); } DBGEXIT;}static void davincifb_ntsc_svideo_config(int on){ DBGENTER; if (on) { /* Reset video encoder module */ dispc_reg_out(VENC_VMOD, 0); /* Enable Composite output and start video encoder */ dispc_reg_out(VENC_VMOD, (VENC_VMOD_VIE | VENC_VMOD_VENC)); /* Set REC656 Mode */ dispc_reg_out(VENC_YCCCTL, 0x1); /* Enable output mode and NTSC */ dispc_reg_out(VENC_VMOD, 0x1003); /* Enable S-Video Output; DAC B: S-Video Y, DAC C: S-Video C */ dispc_reg_out(VENC_DACSEL, 0x210); /* Enable all DACs */ dispc_reg_out(VENC_DACTST, 0); } else { /* Reset video encoder module */ dispc_reg_out(VENC_VMOD, 0); } DBGEXIT;}static void davincifb_ntsc_component_config(int on){ DBGENTER; if (on) { /* Reset video encoder module */ dispc_reg_out(VENC_VMOD, 0); /* Enable Composite output and start video encoder */ dispc_reg_out(VENC_VMOD, (VENC_VMOD_VIE | VENC_VMOD_VENC)); /* Set REC656 Mode */ dispc_reg_out(VENC_YCCCTL, 0x1); /* Enable output mode and NTSC */ dispc_reg_out(VENC_VMOD, 0x1003); /* Enable Component output; DAC A: Y, DAC B: Pb, DAC C: Pr */ dispc_reg_out(VENC_DACSEL, 0x543); /* Enable all DACs */ dispc_reg_out(VENC_DACTST, 0); } else { /* Reset video encoder module */ dispc_reg_out(VENC_VMOD, 0); } DBGEXIT;}static void davincifb_pal_composite_config(int on){ DBGENTER; if (on) { /* Reset video encoder module */ dispc_reg_out(VENC_VMOD, 0); /* Enable Composite output and start video encoder */ dispc_reg_out(VENC_VMOD, (VENC_VMOD_VIE | VENC_VMOD_VENC)); /* Set REC656 Mode */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -