omap24xxfb.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,697 行 · 第 1/4 页
C
1,697 行
/* set the offset of the graphics window within the framebuffer */ dispc->gfx_ba0 = info->fix.smem_start + var->yoffset*info->fix.line_length + (var->xoffset*info->var.bits_per_pixel)/8; dispc->gfx_ba1 = dispc->gfx_ba0; dispc->gfx_row_inc = 1 + info->fix.line_length - (info->var.xres*info->var.bits_per_pixel)/8; dispc->gfx_pixel_inc = 1; if (oinfo->asleep) return 0; /* write our updated register values to the display controller */ dispc_reg_out(oinfo, DISPC_GFX_BA0, dispc->gfx_ba0); dispc_reg_out(oinfo, DISPC_GFX_BA1, dispc->gfx_ba1); dispc_reg_out(oinfo, DISPC_GFX_ROW_INC, dispc->gfx_row_inc); dispc_reg_out(oinfo, DISPC_GFX_PIXEL_INC, dispc->gfx_pixel_inc); /* * Inform the display controller that our register updates are complete. */ dispc_control = dispc->control & ~(DISPC_CONTROL_DIGITALENABLE | DISPC_CONTROL_LCDENABLE); dispc_control |= dispc_reg_in(oinfo, DISPC_CONTROL) & (DISPC_CONTROL_DIGITALENABLE | DISPC_CONTROL_LCDENABLE); if (dispc_control & DISPC_CONTROL_DIGITALENABLE) dispc_control |= DISPC_CONTROL_GODIGITAL; if (dispc_control & DISPC_CONTROL_LCDENABLE) dispc_control |= DISPC_CONTROL_GOLCD; dispc_reg_out(oinfo, DISPC_CONTROL, dispc_control); return 0;}/** * omap24xxfb_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 intomap24xxfb_blank(int blank_mode, struct fb_info *info){ struct omap24xxfb_info *oinfo = (struct omap24xxfb_info *) info->par; if (oinfo->asleep) return 0; if (blank_mode) { /* blank--disable display controller */ omap24xxfb_disable(oinfo, oinfo->timeout); } else { /* unblank--enable display controller */ omap24xxfb_enable(oinfo, &oinfo->state, oinfo->timeout); } return 0;}/** * omap24xxfb_sync - NOT a required function. Normally the accel engine * for a graphics card take a specific amount of time. * Often we have to wait for the accelerator to finish * its operation before we can write to the framebuffer * so we can have consistent display output. * * @info: frame buffer structure that represents a single frame buffer */static intomap24xxfb_sync(struct fb_info *info){ return 0;}/** * omap24xxfb_ioctl - handler for private ioctls. */static intomap24xxfb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg, struct fb_info *info){ struct omap24xxfb_info *oinfo = (struct omap24xxfb_info *) info->par; switch (cmd) { case FBIO_WAITFORVSYNC: /* This ioctl accepts an integer argument to specify a * display. We only support one display, so we will * simply ignore the argument. */ return omap24xxfb_wait_for_vsync(oinfo); } return -EINVAL;} /* * Frame buffer operations */static struct fb_ops omap24xxfb_ops = { .owner = THIS_MODULE, .fb_check_var = omap24xxfb_check_var, .fb_set_par = omap24xxfb_set_par, .fb_setcolreg = omap24xxfb_setcolreg, .fb_blank = omap24xxfb_blank, .fb_pan_display = omap24xxfb_pan_display, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_cursor = soft_cursor, .fb_rotate = NULL, .fb_sync = omap24xxfb_sync, .fb_ioctl = omap24xxfb_ioctl,};int __init omap24xxfb_setup(char *options){ /* no command-line options to parse for now */ return 0;} /* * Initialization */int __init omap24xxfb_init(void){ struct omap24xxfb_info *oinfo; struct fb_info *info;#ifndef MODULE { char *option; if (fb_get_options("omap24xxfb", &option)) { return -ENODEV; } omap24xxfb_setup(option); }#endif oinfo = kmalloc(sizeof(struct omap24xxfb_info), GFP_KERNEL); if (!oinfo) { printk(KERN_ERR FB_NAME ": could not allocate memory\n"); return -ENODEV; } memset(oinfo, 0, sizeof(struct omap24xxfb_info)); saved_oinfo = oinfo; /* set the period (in picoseconds) of the graphics timebase */ oinfo->gfx_clk_period = omap24xxfb_gfx_clk_period(); /* initialize the display resolution */ oinfo->display_xres = omap24xxfb_display_xres(); oinfo->display_yres = omap24xxfb_display_yres(); /* Set base addrs */ oinfo->fb_base_phys = omap24xxfb_fb_base(); oinfo->fb_size = omap24xxfb_fb_size(); oinfo->mmio_base_phys = DSS_REG_BASE; /* A null base address indicates that the framebuffer memory should be * dynamically allocated. */ if (!oinfo->fb_base_phys) oinfo->alloc_fb_mem = 1; /* request the mem regions */ if (!request_mem_region(oinfo->mmio_base_phys, DSS_REG_SIZE, FB_NAME)) { printk(KERN_ERR FB_NAME ": cannot reserve MMIO region\n"); goto free_par; } if (!oinfo->alloc_fb_mem) { if (!request_mem_region(oinfo->fb_base_phys, oinfo->fb_size, FB_NAME)) { printk(KERN_ERR FB_NAME ": cannot reserve FB region\n"); goto release_mmio; } } /* map the regions */ oinfo->mmio_base = (unsigned long) ioremap(oinfo->mmio_base_phys, DSS_REG_SIZE); if (!oinfo->mmio_base) { printk(KERN_ERR FB_NAME ": cannot map MMIO\n"); goto release_fb; } if (!oinfo->alloc_fb_mem) { oinfo->fb_base = (unsigned long) ioremap(oinfo->fb_base_phys, oinfo->fb_size); if (!oinfo->fb_base) { printk(KERN_ERR FB_NAME ": cannot map framebuffer\n"); goto unmap_mmio; } } else { /* allocate coherent memory for the framebuffer */ oinfo->fb_base = (unsigned long) dma_alloc_coherent(NULL, oinfo->fb_size, &oinfo->fb_base_phys, GFP_KERNEL | GFP_DMA); if (!oinfo->fb_base) { printk(KERN_ERR FB_NAME ": cannot allocate " "framebuffer\n"); goto unmap_mmio; } } memset((void *)oinfo->fb_base, 0, oinfo->fb_size); /* allocate coherent memory for the palette */ oinfo->palette = (u32 *) dma_alloc_coherent(NULL, sizeof(u32)*256, &oinfo->palette_phys, GFP_KERNEL | GFP_DMA); if (!oinfo->palette) { printk(KERN_ERR FB_NAME ": cannot allocate palette memory\n"); goto free_fb; } memset(oinfo->palette, 0, sizeof(u32)*256); /* reset the display controller with a timeout of 200ms */#ifndef OMAP_24XX_VIRTIO /* Right now there is a problem with softrest on virtio */ omap24xxfb_reset(oinfo, HZ/5);#endif /* capture the initial state of the display controller */ omap24xxfb_save_state(oinfo, &oinfo->state); /* initialize the fb_info structure */ info = &oinfo->info; info->flags = FBINFO_DEFAULT; info->fbops = &omap24xxfb_ops; info->screen_base = (char *)(oinfo->fb_base); info->currcon = -1; info->pseudo_palette = oinfo->pseudo_palette; info->par = oinfo; /* Initialize variable screeninfo. * The variable screeninfo can be directly specified by the user * via an ioctl. */ memcpy(&info->var, omap24xxfb_default_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, FB_NAME, sizeof(info->fix.id)); info->fix.smem_start = oinfo->fb_base_phys; info->fix.smem_len = oinfo->fb_size; info->fix.type = FB_TYPE_PACKED_PIXELS; info->fix.visual = ((var_to_depth(&info->var) <= 8) ? FB_VISUAL_PSEUDOCOLOR: FB_VISUAL_TRUECOLOR); info->fix.xpanstep = 0; info->fix.ypanstep = 0; info->fix.ywrapstep = 0; info->fix.line_length = (info->var.xres_virtual*info->var.bits_per_pixel)/8; info->fix.type_aux = 0; info->fix.mmio_start = oinfo->mmio_base_phys; info->fix.mmio_len = DSS_REG_SIZE; info->fix.accel = FB_ACCEL_NONE; /* Allocate the color map to the maximum size. * Color depths greater than 8 bits are true color and use a 16-bit * pseudo-palette instead of an actual palette, so the maximum color * map size is 256 colors. */ if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { printk(KERN_ERR FB_NAME ": cannot allocate color map\n"); goto free_palette; } if (omap24xxfb_check_var(&info->var, info)) { printk(KERN_ERR FB_NAME ": invalid default video mode\n"); goto dealloc_cmap; } /* initialize board-specific display controller registers */ omap24xxfb_change_mode(&info->var, &oinfo->state); oinfo->hsync = horizontal_sync_freq(&oinfo->state, &info->var); oinfo->vsync = vertical_sync_freq(&oinfo->state, &info->var); if (oinfo->vsync > 0) oinfo->timeout = ((HZ + oinfo->vsync - 1)/oinfo->vsync)*2; else oinfo->timeout = HZ/5; /* 200ms default timeout */ /* initialize the vsync wait queue */ init_waitqueue_head(&oinfo->vsync_wait); /* install our interrupt service routine */ if (request_irq(INT_DSS_IRQ, omap24xxfb_isr, SA_SHIRQ, FB_NAME, oinfo)) { printk(KERN_ERR FB_NAME ": could not install interrupt service routine\n"); goto dealloc_cmap; } if (register_framebuffer((struct fb_info *) oinfo) < 0) { printk(KERN_ERR FB_NAME ": could not register framebuffer\n"); goto uninstall_isr; } printk(KERN_INFO FB_NAME ": fb%d frame buffer device\n", info->node); printk(KERN_INFO FB_NAME ": OMAP24xx display controller hardware rev %d.%d\n", (oinfo->state.revision & DISPC_REVISION_MAJOR) >> DISPC_REVISION_MAJOR_SHIFT, (oinfo->state.revision & DISPC_REVISION_MINOR) >> DISPC_REVISION_MINOR_SHIFT); printk(KERN_INFO FB_NAME ": display mode %dx%dx%d", oinfo->display_xres, oinfo->display_yres, var_to_depth(&info->var)); if (oinfo->state.control & DISPC_CONTROL_LCDENABLE) { printk(" hsync %dkHz vsync %dHz", oinfo->hsync/1000, oinfo->vsync); } printk("\n"); return 0;uninstall_isr: free_irq(INT_DSS_IRQ, oinfo);dealloc_cmap: fb_dealloc_cmap(&info->cmap);free_palette: dma_free_coherent(NULL, sizeof(u32)*256, oinfo->palette, oinfo->palette_phys);free_fb: if (!oinfo->alloc_fb_mem) iounmap((void*)oinfo->fb_base); else dma_free_coherent(NULL, oinfo->fb_size, (void *)oinfo->fb_base, oinfo->fb_base_phys);unmap_mmio: iounmap((void*)oinfo->mmio_base);release_fb: if (!oinfo->alloc_fb_mem) release_mem_region(oinfo->fb_base_phys, oinfo->fb_size);release_mmio: release_mem_region(oinfo->mmio_base_phys, DSS_REG_SIZE);free_par: kfree(oinfo); saved_oinfo = NULL; return -ENODEV;} /* * Cleanup */static void __exit omap24xxfb_cleanup(void){ struct omap24xxfb_info *oinfo = saved_oinfo; if (!oinfo) return; unregister_framebuffer((struct fb_info *) oinfo); /* uninstall isr */ free_irq(INT_DSS_IRQ, oinfo); /* reset the video controller with a timeout of 200ms */#ifndef OMAP_24XX_VIRTIO /* Right now there is a problem with softrest on virtio */ omap24xxfb_reset(oinfo, HZ/5);#endif fb_dealloc_cmap(&oinfo->info.cmap); dma_free_coherent(NULL, sizeof(u32)*256, oinfo->palette, oinfo->palette_phys); if (!oinfo->alloc_fb_mem) iounmap((void*)oinfo->fb_base); else dma_free_coherent(NULL, oinfo->fb_size, (void *)oinfo->fb_base, oinfo->fb_base_phys); iounmap((void*)oinfo->mmio_base); if (!oinfo->alloc_fb_mem) release_mem_region(oinfo->fb_base_phys, oinfo->fb_size); release_mem_region(oinfo->mmio_base_phys, DSS_REG_SIZE); kfree(oinfo); saved_oinfo = NULL;} /* * Modularization */module_init(omap24xxfb_init);module_exit(omap24xxfb_cleanup);MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?