/* * linux/drivers/video/fbmem.c * * Copyright (C) 1994 Martin Schaller * * 2001 - Documented with DocBook * - Brad Douglas <brad@neruo.com> * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive * for more details.
*/
/* * Frame buffer device initialization and setup routines
*/
#define FBPIXMAPSIZE (1024 * 8)
structclass *fb_class;
DEFINE_MUTEX(registration_lock); struct fb_info *registered_fb[FB_MAX] __read_mostly; int num_registered_fb __read_mostly; #define for_each_registered_fb(i) \ for (i = 0; i < FB_MAX; i++) \ if (!registered_fb[i]) {} else
/* * we need to lock this section since fb_cursor * may use fb_imageblit()
*/ char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size)
{
u32 align = buf->buf_align - 1, offset; char *addr = buf->addr;
/* If IO mapped, we need to sync before access, no sharing of * the pixmap is done
*/ if (buf->flags & FB_PIXMAP_IO) { if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC))
info->fbops->fb_sync(info); return addr;
}
/* See if we fit in the remaining pixmap space */
offset = buf->offset + align;
offset &= ~align; if (offset + size > buf->size) { /* We do not fit. In order to be able to re-use the buffer, * we must ensure no asynchronous DMA'ing or whatever operation * is in progress, we sync for that.
*/ if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC))
info->fbops->fb_sync(info);
offset = 0;
}
buf->offset = offset + size;
addr += offset;
int
fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
{ int ret = 0;
u32 activate; struct fb_var_screeninfo old_var; struct fb_videomode mode;
u32 unused;
if (var->activate & FB_ACTIVATE_INV_MODE) { struct fb_videomode mode1, mode2;
fb_var_to_videomode(&mode1, var);
fb_var_to_videomode(&mode2, &info->var); /* make sure we don't delete the videomode of current var */
ret = fb_mode_is_equal(&mode1, &mode2); if (!ret) {
ret = fbcon_mode_deleted(info, &mode1); if (!ret)
fb_delete_videomode(&mode1, &info->modelist);
}
return ret ? -EINVAL : 0;
}
if (!(var->activate & FB_ACTIVATE_FORCE) &&
!memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) return 0;
activate = var->activate;
/* When using FOURCC mode, make sure the red, green, blue and * transp fields are set to 0.
*/ if ((info->fix.capabilities & FB_CAP_FOURCC) &&
var->grayscale > 1) { if (var->red.offset || var->green.offset ||
var->blue.offset || var->transp.offset ||
var->red.length || var->green.length ||
var->blue.length || var->transp.length ||
var->red.msb_right || var->green.msb_right ||
var->blue.msb_right || var->transp.msb_right) return -EINVAL;
}
if (!info->fbops->fb_check_var) {
*var = info->var; return 0;
}
/* bitfill_aligned() assumes that it's at least 8x8 */ if (var->xres < 8 || var->yres < 8) return -EINVAL;
/* Too huge resolution causes multiplication overflow. */ if (check_mul_overflow(var->xres, var->yres, &unused) ||
check_mul_overflow(var->xres_virtual, var->yres_virtual, &unused)) return -EINVAL;
ret = info->fbops->fb_check_var(var, info);
if (ret) return ret;
/* verify that virtual resolution >= physical resolution */ if (var->xres_virtual < var->xres ||
var->yres_virtual < var->yres) {
pr_warn("WARNING: fbcon: Driver '%s' missed to adjust virtual screen size (%ux%u vs. %ux%u)\n",
info->fix.id,
var->xres_virtual, var->yres_virtual,
var->xres, var->yres); return -EINVAL;
}
if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) return 0;
if (info->fbops->fb_get_caps) {
ret = fb_check_caps(info, var, activate);
if (ret) return ret;
}
old_var = info->var;
info->var = *var;
if (info->fbops->fb_set_par) {
ret = info->fbops->fb_set_par(info);
if (info->modelist.prev && info->modelist.next &&
!list_empty(&info->modelist))
ret = fb_add_videomode(&mode, &info->modelist);
if (ret) {
info->var = old_var; return ret;
}
fb_lcd_notify_mode_change(info, &mode);
return 0;
}
EXPORT_SYMBOL(fb_set_var);
staticvoid fb_lcd_notify_blank(struct fb_info *info)
{ int power;
switch (info->blank) { case FB_BLANK_UNBLANK:
power = LCD_POWER_ON; break; /* deprecated; TODO: should become 'off' */ case FB_BLANK_NORMAL:
power = LCD_POWER_REDUCED; break; case FB_BLANK_VSYNC_SUSPEND:
power = LCD_POWER_REDUCED_VSYNC_SUSPEND; break; /* 'off' */ case FB_BLANK_HSYNC_SUSPEND: case FB_BLANK_POWERDOWN: default:
power = LCD_POWER_OFF; break;
}
/* * With an fb_blank callback present, we assume that the * display is blank, so that fb_blank() enables it on the * first modeset.
*/ if (fb_info->fbops->fb_blank)
fb_info->blank = FB_BLANK_POWERDOWN;
/* this may free fb info */
put_fb_info(fb_info);
}
/** * register_framebuffer - registers a frame buffer device * @fb_info: frame buffer info structure * * Registers a frame buffer device @fb_info. * * Returns negative errno on error, or zero for success. *
*/ int
register_framebuffer(struct fb_info *fb_info)
{ int ret;
mutex_lock(®istration_lock);
ret = do_register_framebuffer(fb_info);
mutex_unlock(®istration_lock);
/** * unregister_framebuffer - releases a frame buffer device * @fb_info: frame buffer info structure * * Unregisters a frame buffer device @fb_info. * * Returns negative errno on error, or zero for success. * * This function will also notify the framebuffer console * to release the driver. * * This is meant to be called within a driver's module_exit() * function. If this is called outside module_exit(), ensure * that the driver implements fb_open() and fb_release() to * check that no processes are using the device.
*/ void
unregister_framebuffer(struct fb_info *fb_info)
{
mutex_lock(®istration_lock);
do_unregister_framebuffer(fb_info);
mutex_unlock(®istration_lock);
}
EXPORT_SYMBOL(unregister_framebuffer);
/** * fb_set_suspend - low level driver signals suspend * @info: framebuffer affected * @state: 0 = resuming, !=0 = suspending * * This is meant to be used by low level drivers to * signal suspend/resume to the core & clients. * It must be called with the console semaphore held
*/ void fb_set_suspend(struct fb_info *info, int state)
{
WARN_CONSOLE_UNLOCKED();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.