omap24xxfb.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,697 行 · 第 1/4 页
C
1,697 行
struct fb_var_screeninfo v; u32 clkdiv, pixclock, hbp, hfp, hsw, vbp, vfp, vsw; memcpy(&v, var, sizeof(v)); /* do board-specific checks on the var */ if (omap24xxfb_check_mode(&v)) return -EINVAL; switch (v.bits_per_pixel) { case 0 ... 1: v.bits_per_pixel = 1; break; case 2: v.bits_per_pixel = 2; break; case 3 ... 4: v.bits_per_pixel = 4; break; case 5 ... 8: v.bits_per_pixel = 8; break; case 9 ... 16: if (v.grayscale) return -EINVAL; v.bits_per_pixel = 16; break; case 17 ... 32: if (v.grayscale) return -EINVAL; v.bits_per_pixel = 32; break; default: return -EINVAL; } switch (var_to_depth(&v)) { case 1: v.red.offset = v.green.offset = v.blue.offset = 0; v.red.length = v.green.length = v.blue.length = 1; v.transp.offset = v.transp.length = 0; break; case 2: v.red.offset = v.green.offset = v.blue.offset = 0; v.red.length = v.green.length = v.blue.length = 2; v.transp.offset = v.transp.length = 0; break; case 4: v.red.offset = v.green.offset = v.blue.offset = 0; v.red.length = v.green.length = v.blue.length = 4; v.transp.offset = v.transp.length = 0; break; case 8: v.red.offset = v.green.offset = v.blue.offset = 0; v.red.length = v.green.length = v.blue.length = 8; v.transp.offset = v.transp.length = 0; break; case 12: v.red.offset = 8; v.green.offset = 4; v.blue.offset = 0; v.red.length = v.green.length = v.blue.length = 4; v.transp.offset = v.transp.length = 0; break; case 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; break; case 24: v.red.offset = 16; v.green.offset = 8; v.blue.offset = 0; v.red.length = v.blue.length = v.green.length = 8; v.transp.offset = v.transp.length = 0; break; default: return -EINVAL; } /* 2048x2048 is max res supported by OMAP24xx display controller */ if (oinfo->display_xres > 2048 || oinfo->display_yres > 2048) return -EINVAL; if (oinfo->display_xres == 0 || oinfo->display_yres == 0) return -EINVAL; if (v.xres_virtual < v.xres || v.yres_virtual < v.yres) return -EINVAL; if (oinfo->display_xres < v.xres || oinfo->display_yres < 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.bits_per_pixel < 8) && (((v.xres_virtual % 8) != 0) || ((v.xres % 8) != 0) || ((v.xoffset % 8) != 0))) { return -EINVAL; } /* check if we have enough video memory to support this framebuffer */ if (((v.xres_virtual*v.yres_virtual*v.bits_per_pixel)/8) > info->fix.smem_len) { return -EINVAL; } /* Convert the timing parameters in the var info to the values needed * to program into the display controller timing registers, and then * convert the register values back to the var info values. */ pixclock = (v.pixclock > 0) ? v.pixclock : (oinfo->gfx_clk_period * 8); clkdiv = pixclock / oinfo->gfx_clk_period; if (clkdiv < 2) /* minimum divisor is 2 */ clkdiv = 2; else if (clkdiv > 255) clkdiv = 255; /* maximum divisor is 255 */ pixclock = oinfo->gfx_clk_period * clkdiv; v.pixclock = pixclock; /* calculate horizontal timing parameters in pixclocks */ hbp = (v.left_margin > 0) ? (v.left_margin - 1) : 0; if (hbp > 255) hbp = 255; hfp = (v.right_margin > 0) ? (v.right_margin - 1) : 0; if (hfp > 255) hfp = 255; hsw = (v.hsync_len > 0) ? (v.hsync_len - 1) : 0; if (hsw > 63) hsw = 63; v.left_margin = hbp + 1; v.right_margin = hfp + 1; v.hsync_len = hsw + 1; /* calculate vertical timing parameters in line clocks */ vbp = v.upper_margin; if (vbp > 255) vbp = 255; vfp = v.lower_margin; if (vfp > 255) vfp = 255; vsw = (v.vsync_len > 0) ? (v.vsync_len - 1) : v.vsync_len; if (vsw > 63) vsw = 63; v.upper_margin = vbp; v.lower_margin = vfp; v.vsync_len = vsw + 1; v.red.msb_right = v.green.msb_right = v.blue.msb_right = v.transp.msb_right = 0; v.nonstd = 0; v.accel_flags = 0; memcpy(var, &v, sizeof(v)); return 0;}/* * omap24xxfb_set_par - Alters the hardware state. * @info: frame buffer structure that represents a single frame buffer * * Using the fb_var_screeninfo in fb_info we set the resolution of * this particular framebuffer. This function alters the par AND the * fb_fix_screeninfo stored in fb_info. It does not alter var in * fb_info since we are using that data. This means we depend on the * data in var inside fb_info to be supported by the hardware. * omap24xxfb_check_var is always called before omap24xxfb_set_par to * ensure this. * */static intomap24xxfb_set_par(struct fb_info *info){ struct omap24xxfb_info *oinfo = (struct omap24xxfb_info *) info->par; struct fb_var_screeninfo *var = &info->var; struct omap24xx_dispc_regs *dispc = &oinfo->state; u32 gfx_format; u32 clkdiv, pixclock, hbp, hfp, hsw, vbp, vfp, vsw; /* update the fix screeninfo */ info->fix.line_length = (var->xres_virtual*var->bits_per_pixel)/8; info->fix.visual = ((var_to_depth(var) <= 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR); /* Call a board-specific function to configure * the display controller registers for this mode. * This function may modify values in dispc but must not modify * values in var. */ omap24xxfb_change_mode(var, dispc); /* Disable RFBI mode, which is not currently supported. */ dispc->control &= ~DISPC_CONTROL_RFBIMODE; /* Convert the timing parameters in the var info to the values needed * to program into the display controller timing registers. */ pixclock = (var->pixclock > 0) ? var->pixclock : (oinfo->gfx_clk_period * 8); clkdiv = pixclock / oinfo->gfx_clk_period; if (clkdiv < 2) /* minimum divisor is 2 */ clkdiv = 2; else if (clkdiv > 255) clkdiv = 255; /* maximum divisor is 255 */ dispc->divisor = (1 << DISPC_DIVISOR_LCD_SHIFT) | (clkdiv << DISPC_DIVISOR_PCD_SHIFT); /* calculate horizontal timing parameters in pixclocks */ hbp = (var->left_margin > 0) ? (var->left_margin - 1) : 0; if (hbp > 255) hbp = 255; hfp = (var->right_margin > 0) ? (var->right_margin - 1) : 0; if (hfp > 255) hfp = 255; hsw = (var->hsync_len > 0) ? (var->hsync_len - 1) : 0; if (hsw > 63) hsw = 63; dispc->timing_h = (hbp << DISPC_TIMING_H_HBP_SHIFT) | (hfp << DISPC_TIMING_H_HFP_SHIFT) | (hsw << DISPC_TIMING_H_HSW_SHIFT); /* calculate vertical timing parameters in line clocks */ vbp = var->upper_margin; if (vbp > 255) vbp = 255; vfp = var->lower_margin; if (vfp > 255) vfp = 255; vsw = (var->vsync_len > 0) ? (var->vsync_len - 1) : var->vsync_len; if (vsw > 63) vsw = 63; dispc->timing_v = (vbp << DISPC_TIMING_V_VBP_SHIFT) | (vfp << DISPC_TIMING_V_VFP_SHIFT) | (vsw << DISPC_TIMING_V_VSW_SHIFT); oinfo->hsync = horizontal_sync_freq(dispc, var); oinfo->vsync = vertical_sync_freq(dispc, var); if (oinfo->vsync > 0) oinfo->timeout = ((HZ + oinfo->vsync - 1)/oinfo->vsync)*2; else oinfo->timeout = HZ/5; /* 200ms default timeout */ /* set the sync polarity */ if (var->sync & FB_SYNC_HOR_HIGH_ACT) dispc->pol_freq |= DISPC_POL_FREQ_IHS; else dispc->pol_freq &= ~DISPC_POL_FREQ_IHS; if (var->sync & FB_SYNC_VERT_HIGH_ACT) dispc->pol_freq |= DISPC_POL_FREQ_IVS; else dispc->pol_freq &= ~DISPC_POL_FREQ_IVS; /* set the display size */ dispc->size_lcd = (((oinfo->display_xres - 1) << DISPC_SIZE_LCD_PPL_SHIFT) & DISPC_SIZE_LCD_PPL) | (((oinfo->display_yres - 1) << DISPC_SIZE_LCD_LPP_SHIFT) & DISPC_SIZE_LCD_LPP); dispc->size_dig = dispc->size_lcd; /* set the graphics window size */ dispc->gfx_size = (((var->xres - 1) << DISPC_GFX_SIZE_GFXSIZEX_SHIFT) & DISPC_GFX_SIZE_GFXSIZEX) | (((var->yres - 1) << DISPC_GFX_SIZE_GFXSIZEY_SHIFT) & DISPC_GFX_SIZE_GFXSIZEY); /* 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*var->bits_per_pixel)/8; dispc->gfx_ba1 = dispc->gfx_ba0; dispc->gfx_row_inc = 1 + info->fix.line_length - (var->xres*var->bits_per_pixel)/8; dispc->gfx_pixel_inc = 1; /* Set the base address of the palette */ dispc->gfx_table_ba = oinfo->palette_phys; /* set the graphics format */ switch(var_to_depth(var)) { case 1: gfx_format = DISPC_GFX_ATTRIBUTES_GFXFORMAT_BITMAP1; break; case 2: gfx_format = DISPC_GFX_ATTRIBUTES_GFXFORMAT_BITMAP2; break; case 4: gfx_format = DISPC_GFX_ATTRIBUTES_GFXFORMAT_BITMAP4; break; case 8: gfx_format = DISPC_GFX_ATTRIBUTES_GFXFORMAT_BITMAP8; break; case 12: gfx_format = DISPC_GFX_ATTRIBUTES_GFXFORMAT_RGB12; break; case 16: gfx_format = DISPC_GFX_ATTRIBUTES_GFXFORMAT_RGB16; break; case 24: gfx_format = DISPC_GFX_ATTRIBUTES_GFXFORMAT_RGB24; break; default: gfx_format = dispc->gfx_attributes & DISPC_GFX_ATTRIBUTES_GFXFORMAT; break; } dispc->gfx_attributes &= ~DISPC_GFX_ATTRIBUTES_GFXFORMAT; dispc->gfx_attributes |= gfx_format; /* disable the graphics window if its size is zero */ if (var->xres == 0 || var->yres == 0) dispc->gfx_attributes &= ~DISPC_GFX_ATTRIBUTES_ENABLE; else dispc->gfx_attributes |= DISPC_GFX_ATTRIBUTES_ENABLE; if (!oinfo->asleep) omap24xxfb_write_state(oinfo, dispc, oinfo->timeout); return 0; }/* * 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; if (regno >= 256) /* maximum number of palette entries */ return 1; 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) 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: return 1; } return 0; } red >>= 8; green >>= 8; blue >>= 8; (oinfo->palette)[regno] = (red << 16) | (green << 8) | (blue << 0); if (!oinfo->asleep) { /* tell the display controller to reload the palette table */ dispc_reg_out(oinfo, DISPC_CONFIG, oinfo->state.config); } 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; struct omap24xx_dispc_regs *dispc = &oinfo->state; u32 dispc_control; 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; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?