📄 omap_fb.c
字号:
info->fix.smem_start = oinfo->sms_rot_phy[omap_rotation_index(oinfo->rotation_deg)]; info->screen_base = (char *)(oinfo->sms_rot_virt[omap_rotation_index(oinfo->rotation_deg)]); } } /* Graphics DMA parameters */ ret = omap24xxfb_set_dma_params(var, &info->fix, (oinfo->rotation_support ? var->rotate : -1), omap24xxfb_mirroring); /* LCD parameters */ clkdiv = var->pixclock / oinfo->gfx_clk_period; /* horizontal timing parameters in pixclocks */ hbp = (var->left_margin > 0) ? (var->left_margin - 1) : 0; hfp = (var->right_margin > 0) ? (var->right_margin - 1) : 0; hsw = (var->hsync_len > 0) ? (var->hsync_len - 1) : 0; /* vertical timing parameters in line clocks */ vbp = var->upper_margin; vfp = var->lower_margin; vsw = (var->vsync_len > 0) ? (var->vsync_len - 1) : var->vsync_len; oinfo->hsync = horizontal_sync_freq(var); oinfo->vsync = vertical_sync_freq(var); if (oinfo->vsync > 0) oinfo->timeout = ((HZ + oinfo->vsync - 1)/oinfo->vsync)*2; else oinfo->timeout = HZ/5; /* 200ms default timeout */ omap2_disp_config_lcd(clkdiv, hbp, hfp, hsw, vbp, vfp, vsw); if (!ret) { if(fb_out_layer == OMAP2_GRAPHICS) omap2_disp_start_gfxlayer(); else{ omap24xxfb_set_output_layer(fb_out_layer); omap2_disp_start_gfxlayer(); } wait_for_reg_sync(SCHEDULE_WAIT, oinfo->timeout); } omap2_disp_put_dss(); return ret;}intomap24xxfb_set_output_layer(int layer){ struct omap24xxfb_info *oinfo = (struct omap24xxfb_info *) saved_oinfo; int ret = 0; struct fb_var_screeninfo *var = &oinfo->info.var; struct v4l2_pix_format pix; struct v4l2_rect crop; struct v4l2_window win; int rotate = -1; memset(&pix, 0, sizeof(pix)); memset(&crop, 0, sizeof(crop)); memset(&win, 0, sizeof(win)); pix.pixelformat = V4L2_PIX_FMT_RGB565; pix.colorspace = V4L2_COLORSPACE_SRGB; pix.field = V4L2_FIELD_NONE; pix.width = var->xres; pix.height = var->yres; pix.bytesperline = pix.width * 2; pix.priv = 0; pix.sizeimage = pix.bytesperline * pix.height; crop.left = 0; crop.top = 0; crop.width = var->xres; crop.height = var->yres; win.w.width = var->xres; win.w.height = var->yres; win.w.left = var->xoffset; win.w.top = var->yoffset; DBGENTER; if(layer == OMAP2_GRAPHICS){ omap24xxfb_set_par(&saved_oinfo->info); } else { mdelay(1); rotate = (oinfo->rotation_support) ? var->rotate : -1; omap2_disp_config_vlayer(layer,&pix,&crop,&win,rotate,omap24xxfb_mirroring); mdelay(1); omap2_disp_start_vlayer(layer,&pix,&crop,&win, (rotate>=0)? SMS_ROT_VIRT_BASE(0,0):oinfo->info.fix.smem_start,rotate,omap24xxfb_mirroring); wait_for_reg_sync(SCHEDULE_WAIT, oinfo->timeout); } DBGLEAVE; return ret;}/* * omap24xxfb_setcolreg - Sets a color register. * @regno: Which register in the CLUT we are programming * @red: The red value which can be up to 16 bits wide * @green: The green value which can be up to 16 bits wide * @blue: The blue value which can be up to 16 bits wide. * @transp: If supported the alpha value which can be up to 16 bits wide. * @info: frame buffer info structure * * Returns non-zero on error, or zero on success. */static intomap24xxfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info){ struct omap24xxfb_info *oinfo = (struct omap24xxfb_info *) info->par; int output_dev = omap2_disp_get_output_dev(OMAP2_GRAPHICS); if (regno >= 256) /* maximum number of palette entries */ return 1; omap2_disp_get_dss(); if (info->var.grayscale) { /* grayscale = 0.30*R + 0.59*G + 0.11*B */ red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; } /* Truecolor has hardware-independent 16-entry pseudo-palette */ if (info->fix.visual == FB_VISUAL_TRUECOLOR) { u32 v; if (regno >= 16) { omap2_disp_put_dss(); return 1; } red >>= (16 - info->var.red.length); green >>= (16 - info->var.green.length); blue >>= (16 - info->var.blue.length); v = (red << info->var.red.offset) | (green << info->var.green.offset) | (blue << info->var.blue.offset); switch (info->var.bits_per_pixel) { case 16: ((u16*)(info->pseudo_palette))[regno] = v; break; case 32: ((u32*)(info->pseudo_palette))[regno] = v; break; default: omap2_disp_put_dss(); return 1; } omap2_disp_put_dss(); return 0; } red >>= 8; green >>= 8; blue >>= 8; (oinfo->palette)[regno] = (red << 16) | (green << 8) | (blue << 0); if(regno == 255){ omap2_disp_set_gfx_palette(oinfo->palette_phys); omap2_disp_reg_sync(output_dev); } omap2_disp_put_dss(); DBGLEAVE; return 0;}/* * omap24xxfb_pan_display - Pans the display. * @var: frame buffer variable screen structure * @info: frame buffer structure that represents a single frame buffer * * Pan the display using the `xoffset' and `yoffset' fields of the `var' * structure. We don't support wrapping and ignore the FB_VMODE_YWRAP * flag. * * If the values don't fit, return -EINVAL. * * Returns negative errno on error, or zero on success. */static intomap24xxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info){ struct omap24xxfb_info *oinfo = (struct omap24xxfb_info *) info->par; int ret; DBGENTER; if (var->xoffset > info->var.xres_virtual - info->var.xres) return -EINVAL; if (var->yoffset > info->var.yres_virtual - info->var.yres) return -EINVAL; if ((info->var.bits_per_pixel < 8) && ((var->xoffset % 8) != 0)) { return -EINVAL; } if (oinfo->asleep) return 0; omap2_disp_get_dss(); /* Graphics DMA parameters */ ret = omap24xxfb_set_dma_params(var, &info->fix, (oinfo->rotation_support ? var->rotate : -1), omap24xxfb_mirroring); if (!ret) { if (fb_out_layer == OMAP2_GRAPHICS) omap2_disp_start_gfxlayer(); else{ omap2_disp_start_gfxlayer(); omap24xxfb_set_output_layer(fb_out_layer); } wait_for_reg_sync(SCHEDULE_WAIT, oinfo->timeout); } omap2_disp_put_dss(); DBGLEAVE; return ret;}/** * 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. */static intomap24xxfb_blank(int blank_mode, struct fb_info *info){ struct omap24xxfb_info *oinfo = (struct omap24xxfb_info *) info->par; DBGENTER; /* No need for suspend lockout because if the framebuffer device is * suspended, then the console is already blanked. */ if (oinfo->asleep) return 0; if ((blank_mode) && (!oinfo->blanked)) { /* blank--disable display controller */ /* wait until Vsync */ if (omap24xxfb_wait_for_vsync(oinfo) != 0) printk("omap24xxfb_blank: vsyn wait failed \n"); omap2_disp_disable_layer(OMAP2_GRAPHICS); omap2_disp_disable_layer(fb_out_layer); omap2_disp_disable(HZ/5); disable_backlight(); omap2_disp_put_dss(); omap2_dss_rgb_disable(); oinfo->blanked = 1; } else if ((!blank_mode) && (oinfo->blanked)) { /* unblank--enable display controller */ omap2_dss_rgb_enable(); omap2_disp_get_dss(); omap2_disp_enable_layer(OMAP2_GRAPHICS); omap2_disp_enable_layer(fb_out_layer); omap2_disp_enable_output_dev(OMAP2_OUTPUT_LCD); omap2_disp_enable_output_dev(OMAP2_OUTPUT_TV); oinfo->blanked = 0; udelay(20); enable_backlight(); /* omap2_disp_disable function disables tv clock it has * to be enabled */ omap2_disp_power_on_tv(); } DBGLEAVE; 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_set_mirroring - enables and disables mirroring */static intomap24xxfb_set_mirroring (struct fb_info *info, int mirroring){ int ret = 0; struct omap24xxfb_info *oinfo = (struct omap24xxfb_info *) info->par; omap24xxfb_mirroring = mirroring; ret = omap24xxfb_set_dma_params(&info->var, &info->fix, (oinfo->rotation_support ? info->var.rotate : -1), omap24xxfb_mirroring); if (!ret) { if (fb_out_layer == OMAP2_GRAPHICS) omap2_disp_start_gfxlayer(); else{ omap24xxfb_set_output_layer(fb_out_layer); omap2_disp_start_gfxlayer(); } wait_for_reg_sync(SCHEDULE_WAIT, oinfo->timeout); } return ret;}/** * omap24xxfb_ioctl - handler for private ioctls. */static intomap24xxfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg){ struct omap24xxfb_info *oinfo = (struct omap24xxfb_info *) info->par; void __user *argp = (void __user *)arg; int mirroring; int ret; struct omap_lcd_info *lcd_inf; DBGENTER; omap2_disp_get_dss(); omap24xxfb_suspend_lockout(&fb_suspend_data); 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. */ ret = omap24xxfb_wait_for_vsync(oinfo); omap2_disp_put_dss(); return ret; case FBIO_MIRROR: /* This ioctl accepts an integer argument to specify the * mirroring status. */ if (!copy_from_user(&mirroring, argp, sizeof(mirroring))) { ret = omap24xxfb_set_mirroring (info, mirroring); omap2_disp_put_dss(); return ret; } /* This ioctl accepts a structure of type lcd_info and * uses that to configure the LCD */ case FBIO_LCD_PUT_SCREENINFO: lcd_inf = (struct omap_lcd_info *)arg; ret = omap_lcd_init(lcd_inf); return ret; } omap2_disp_put_dss(); DBGLEAVE; 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_rotate = NULL, .fb_sync = omap24xxfb_sync, .fb_ioctl = omap24xxfb_ioctl,};/*---------------------------------------------------------------------------*/static int awake = 0;/* PM suspend */static int omap24xxfb_suspend(struct platform_device *dev, pm_message_t state){ struct omap24xxfb_info *oinfo = saved_oinfo; acquire_console_sem(); fb_set_suspend(&oinfo->info, 1); release_console_sem(); printk(KERN_DEBUG "Suspend Check Awake\n"); if (!awake) return 0; printk(KERN_DEBUG "Disable LCD\n"); omap24xxfb_blank(1, &oinfo->info); awake = 0; oinfo->asleep = 1; return 0;}/* PM resume */static int omap24xxfb_resume(struct platform_device *dev){ struct omap24xxfb_info *oinfo = saved_oinfo; printk(KERN_DEBUG "Resume Check Awake\n"); /* If already awake then leave */ if (awake) return 0; printk(KERN_DEBUG "Enable LCD\n"); oinfo->asleep = 0; /* unblank the screen */ omap24xxfb_blank(0, &oinfo->info); awake = 1; acquire_console_sem(); fb_set_suspend(&oinfo->info, 0); release_console_sem(); return 0;}static intomap24xxfb_probe (struct platform_device *dev){ return 0;}static voidomap24xxfb_release (struct device *dev){ return;}static struct platform_driver omap24xxfb_driver = { .driver = { .name = OMAPFB_DRIVER, }, .probe = omap24xxfb_probe, .suspend = omap24xxfb_suspend, .resume = omap24xxfb_resume,};static struct platform_device omap24xxfb_device = { .name = OMAPFB_DEVICE, .id = 6, .dev = { .release = omap24xxfb_release, },};int omap24xx_get_dss1_clock(void){ struct device *dev = NULL; struct clk *dss1f; dss1f = clk_get(dev, "dss1_fck"); return clk_get_rate(dss1f);}/*---------------------------------------------------------------------------*/int omap24xxfb_setup(char *options){ char *this_opt; printk(KERN_INFO "omap24xxfb: Options \"%s\"\n", options); if (!options || !*options) return 0; while((this_opt = strsep(&options, ",")) != NULL) { if (!*this_opt) continue; if (!strncmp(this_opt, "rotation=", 9)) { int deg = simple_strtoul(this_opt + 9, NULL, 0); if (deg == 0 || deg == 90 || deg == 180 || deg == 270) omap24xxfb_rotation = deg; else omap24xxfb_rotation = -1; printk(KERN_INFO "omap24xxfb: Rotation %s\n", (omap24xxfb_rotation == -1) ? "none (supported: \"rotation=[0|90|180|270]\")": this_opt); } else printk(KERN_INFO "omap24xxfb: Invalid parameter \"%s\" " "(supported: \"rotation=[0|90|180|270]\")\n", this_opt); } return 0;}static ssize_tread_fb_out(char *buf){ int p = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -