omapfb_main.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,875 行 · 第 1/4 页
C
1,875 行
}/* Normal image blit */static void omapfb_imageblit(struct fb_info *fbi, const struct fb_image *image){ do_imageblit(fbi, image, 0);}/* Transparent image blit, using image->bg_color as the color key */static void omapfb_transparent_blit(struct fb_info *fbi, const struct fb_image *image){ do_imageblit(fbi, image, COPY_MODE_TRANSPARENT);}/* Set fb_info.fix fields and also updates fbdev. * When calling this fb_info.var must be set up already. */static void set_fb_fix(struct omapfb_device *fbdev){ struct fb_info *fbi = fbdev->fb_info; struct fb_fix_screeninfo *fix = &fbi->fix; struct fb_var_screeninfo *var = &fbi->var; struct fb_ops *fbops = fbi->fbops; int frame_size; strncpy(fix->id, OMAPFB_DRIVER, sizeof(fix->id)); fix->type = FB_TYPE_PACKED_PIXELS; switch (var->bits_per_pixel) { case 16: fix->visual = FB_VISUAL_TRUECOLOR; break; case 1: case 2: case 4: case 8: fix->visual = FB_VISUAL_PSEUDOCOLOR; break; } fix->accel = FB_ACCEL_OMAP1610; fix->line_length = var->xres_virtual * var->bits_per_pixel / 8; fix->smem_len = fbdev->lcddma_mem_size - fbdev->frame0_org; fix->smem_start = fbdev->lcddma_handle + fbdev->frame0_org; if (var->accel_flags == FB_ACCELF_TEXT && var->bits_per_pixel >= 8) { fbops->fb_fillrect = omapfb_fillrect; fbops->fb_copyarea = omapfb_copyarea; fbops->fb_imageblit = omapfb_imageblit; } else { fbops->fb_fillrect = cfb_fillrect; fbops->fb_copyarea = cfb_copyarea; fbops->fb_imageblit = cfb_imageblit; } /* Set the second frame buffer offset for flipping if there is * room for it. */ frame_size = fix->line_length * var->yres + var->xres * var->bits_per_pixel / 8; fbdev->frame1_org = fbdev->frame0_org + frame_size; if (fbdev->frame1_org > fbdev->lcddma_mem_size) fbdev->frame1_org = 0; fbdev->vis_frame_org = fbdev->src_frame_org = fbdev->dst_frame_org = fbdev->frame0_org; fbdev->view_org = var->yoffset * fix->line_length + var->xoffset * var->bits_per_pixel / 8;}/* Check the values in var against our capabilities and in case of out of * bound values try to adjust them. */static int set_fb_var(struct omapfb_device *fbdev, struct fb_var_screeninfo *var){ int bpp; unsigned long max_frame_size; unsigned long line_size; bpp = var->bits_per_pixel = fbdev->panel->video_mode->bpp; if (bpp != 16) /* Not yet supported */ return -1; switch (var->rotate) { case 0: case 180: var->xres = fbdev->panel->video_mode->x_res; var->yres = fbdev->panel->video_mode->y_res; break; case 90: case 270: var->xres = fbdev->panel->video_mode->y_res; var->yres = fbdev->panel->video_mode->x_res; break; default: return -1; } if (var->xres_virtual < var->xres) var->xres_virtual = var->xres; if (var->yres_virtual < var->yres) var->yres_virtual = var->yres; max_frame_size = fbdev->lcddma_mem_size - fbdev->frame0_org; line_size = var->xres_virtual * bpp / 8; if (line_size * var->yres_virtual > max_frame_size) { /* Try to keep yres_virtual first */ line_size = max_frame_size / var->yres_virtual; var->xres_virtual = line_size * 8 / bpp; if (var->xres_virtual < var->xres) { /* Still doesn't fit. Shrink yres_virtual too */ var->xres_virtual = var->xres; line_size = var->xres * bpp / 8; var->yres_virtual = max_frame_size / line_size; } } if (var->xres + var->xoffset > var->xres_virtual) var->xoffset = var->xres_virtual - var->xres; if (var->yres + var->yoffset > var->yres_virtual) var->yoffset = var->yres_virtual - var->yres; line_size = var->xres * bpp / 8; var->red.offset = 11; var->red.length = 5; var->red.msb_right = 0; var->green.offset= 5; var->green.length = 6; var->green.msb_right = 0; var->blue.offset = 0; var->blue.length = 5; var->blue.msb_right = 0; var->height = -1; var->width = -1; var->grayscale = 0; var->nonstd = 0; /* TODO: video timing params, sync */ var->pixclock = -1; var->left_margin = -1; var->right_margin = -1; var->upper_margin = -1; var->lower_margin = -1; var->hsync_len = -1; var->vsync_len = -1; var->vmode = FB_VMODE_NONINTERLACED; var->sync = 0; return 0;}static struct fb_var_screeninfo new_var;/* Set rotation (0, 90, 180, 270 degree), and switch to the new mode. */static void omapfb_rotate(struct fb_info *fbi, int rotate){ struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par; DBGENTER(1); if (cpu_is_omap1510() && rotate != fbdev->fb_info->var.rotate) { memcpy(&new_var, &fbi->var, sizeof(new_var)); new_var.rotate = rotate; if (set_fb_var(fbdev, &new_var) == 0 && memcmp(&new_var, &fbi->var, sizeof(new_var))) { memcpy(&fbi->var, &new_var, sizeof(new_var)); set_fb_fix(fbdev); ctrl_change_mode(fbdev); } } DBGLEAVE(1);}/* Set new x,y offsets in the virtual display for the visible area and switch * to the new mode. */static int omapfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi){ struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par; int r = 0; DBGENTER(1); if (var->xoffset != fbi->var.xoffset || var->yoffset != fbi->var.yoffset) { memcpy(&new_var, &fbi->var, sizeof(new_var)); new_var.xoffset = var->xoffset; new_var.yoffset = var->yoffset; if (set_fb_var(fbdev, &new_var)) r = -EINVAL; else { memcpy(&fbi->var, &new_var, sizeof(new_var)); set_fb_fix(fbdev); ctrl_change_mode(fbdev); } } DBGLEAVE(1); return r;}/* Set mirror to vertical axis and switch to the new mode. */static int omapfb_mirror(struct fb_info *fbi, int mirror){ struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par; int r = 0; DBGENTER(1); mirror = mirror ? 1 : 0; if (cpu_is_omap1510()) r = -EINVAL; else if (mirror != fbdev->mirror) { fbdev->mirror = mirror; ctrl_change_mode(fbdev); } DBGLEAVE(1); return r;}/* Set x,y scale and switch to the new mode */static int omapfb_scale(struct fb_info *fbi, unsigned int xscale, unsigned int yscale){ struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par; int r = 0; DBGENTER(1); if (cpu_is_omap1510()) r = -EINVAL; else if (xscale != fbdev->xscale || yscale != fbdev->yscale) { if (fbi->var.xres * xscale > fbi->var.xres_virtual || fbi->var.yres * yscale > fbi->var.yres_virtual) r = -EINVAL; else { fbdev->xscale = xscale; fbdev->yscale = yscale; ctrl_change_mode(fbdev); } } DBGLEAVE(1); return r;}/* Check values in var, try to adjust them in case of out of bound values if * possible, or return error. */static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi){ struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par; int r; DBGENTER(1); r = set_fb_var(fbdev, var); DBGLEAVE(1); return r;}/* Switch to a new mode. The parameters for it has been check already by * omapfb_check_var. */static int omapfb_set_par(struct fb_info *fbi){ struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par; DBGENTER(1); set_fb_fix(fbdev); ctrl_change_mode(fbdev); DBGLEAVE(1); return 0;}/* Frame flipping support. Assign the primary or the secondary frame to the * visible frame, as well as the source and destination frames for graphics * operations like rectangle fill and area copy. Flipping is only possible * if we have enough video memory for the secondary frame. */static int omapfb_select_frame(struct fb_info *fbi, unsigned int vis_idx, unsigned int src_idx, unsigned int dst_idx){ struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par; if ((vis_idx | src_idx | dst_idx) & ~1) return -EINVAL; if (((vis_idx | src_idx | dst_idx) & 1) && !fbdev->frame1_org) return -EINVAL; fbdev->vis_frame_org = vis_idx ? fbdev->frame1_org : fbdev->frame0_org; fbdev->src_frame_org = src_idx ? fbdev->frame1_org : fbdev->frame0_org; fbdev->dst_frame_org = dst_idx ? fbdev->frame1_org : fbdev->frame0_org; ctrl_change_mode(fbdev); return 0;}/* Get the address of the primary and secondary frames */static int omapfb_get_frame_offset(struct fb_info *fbi, struct fb_frame_offset *fb_offset){ struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par; if (fb_offset->idx > 1) return -EINVAL; if (fb_offset->idx == 1 && !fbdev->frame1_org) return -EINVAL; fb_offset->offset = fb_offset->idx ? fbdev->frame1_org : fbdev->frame0_org; return 0;}static int omapfb_activate(struct omapfb_device *fbdev);/* If late_activate option is set, start the image transfer now. */static int omapfb_late_activate(struct fb_info *fbi){ struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par; if (!late_activate) { PRNERR("late_activate option is not set"); return -EINVAL; } if (fbdev->state != OMAPFB_DEACTIVATED) { PRNERR("device is already active or in wrong state"); return -EINVAL; } omapfb_activate(fbdev); /* call this in case some has changed meanwhile the fb params */ ctrl_change_mode(fbdev); return 0;}/* Ioctl interface. Part of the kernel mode frame buffer API is duplicated * here to be accessible by user mode code. In addition transparent copy * graphics transformations, frame flipping support is provided through this * interface. */static int omapfb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg, struct fb_info *fbi){ struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par; struct fb_ops *ops = fbi->fbops; union { struct fb_fillrect rect; struct fb_copyarea area; struct fb_image image; struct fb_scale scale; struct fb_frame_offset frame_offset; unsigned int frame_idx; unsigned int mirror; } p; int r = 0; DBGENTER(2); BUG_ON(!ops); DBGPRINT(2, "cmd=%010x\n", cmd); switch (cmd) { case OMAPFB_FILLRECT: if (copy_from_user(&p.rect, (void *)arg, sizeof(p.rect))) r = -EFAULT; else ops->fb_fillrect(fbi, &p.rect); break; case OMAPFB_COPYAREA: if (copy_from_user(&p.area, (void *)arg, sizeof(p.area))) r = -EFAULT; else ops->fb_copyarea(fbi, &p.area); break; case OMAPFB_IMAGEBLIT: if (copy_from_user(&p.image, (void *)arg, sizeof(p.image))) r = -EFAULT; else ops->fb_imageblit(fbi, &p.image); break; case OMAPFB_TRANSPARENT_BLIT: if (copy_from_user(&p.image, (void *)arg, sizeof(p.image))) r = -EFAULT; else omapfb_transparent_blit(fbi, &p.image); break; case OMAPFB_MIRROR: if (get_user(p.mirror, (int *)arg)) r = -EFAULT; else omapfb_mirror(fbi, p.mirror); break; case OMAPFB_SCALE: if (copy_from_user(&p.scale, (void *)arg, sizeof(p.scale))) r = -EFAULT; else r = omapfb_scale(fbi, p.scale.xscale, p.scale.yscale); break; case OMAPFB_SELECT_VIS_FRAME: if (get_user(p.frame_idx, (int *)arg)) r = -EFAULT; else r = omapfb_select_frame(fbi, p.frame_idx, fbdev->src_frame_org, fbdev->dst_frame_org); break; case OMAPFB_SELECT_SRC_FRAME: if (get_user(p.frame_idx, (int *)arg)) r = - EFAULT; else r = omapfb_select_frame(fbi, fbdev->vis_frame_org, p.frame_idx, fbdev->dst_frame_org); break; case OMAPFB_SELECT_DST_FRAME: if (get_user(p.frame_idx, (int *)arg)) r = -EFAULT; else r = omapfb_select_frame(fbi, fbdev->vis_frame_org, fbdev->src_frame_org, p.frame_idx); break; case OMAPFB_GET_FRAME_OFFSET: if (copy_from_user(&p.frame_offset, (void *)arg, sizeof(p.frame_offset))) r = -EFAULT; else { r = omapfb_get_frame_offset(fbi, &p.frame_offset); if (copy_to_user((void *)arg, &p.frame_offset, sizeof(p.frame_offset))) r = -EFAULT; } break; case OMAPFB_SYNC_GFX: gfxdma_sync(&fbdev->gfx); break; case OMAPFB_VSYNC: break; case OMAPFB_LATE_ACTIVATE: r = omapfb_late_activate(fbi); break; default: r = -EINVAL; } DBGLEAVE(2); return r;}/* Callback table for the frame buffer framework. Some of these pointers * will be changed according to the current setting of fb_info->accel_flags. */static struct fb_ops omapfb_ops = { .owner = THIS_MODULE, .fb_open = omapfb_open, .fb_release = omapfb_release, .fb_setcolreg = omapfb_setcolreg, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_cursor = soft_cursor, .fb_blank = omapfb_blank, .fb_ioctl = omapfb_ioctl, .fb_check_var = omapfb_check_var, .fb_set_par = omapfb_set_par, .fb_rotate = omapfb_rotate, .fb_pan_display = omapfb_pan_display,};/*
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?