📄 omapfb_main.c
字号:
/* * Framebuffer driver for TI OMAP boards * * Copyright (C) 2004 Nokia Corporation * Author: Imre Deak <imre.deak@nokia.com> * * Acknowledgements: * Alex McMains <aam@ridgerun.com> - Original driver * Juha Yrjola <juha.yrjola@nokia.com> - Original driver and improvements * Dirk Behme <dirk.behme@de.bosch.com> - changes for 2.6 kernel API * Texas Instruments - H3 support * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <linux/platform_device.h>#include <linux/mm.h>#include <linux/uaccess.h>#include <mach/dma.h>#include <mach/omapfb.h>#include "lcdc.h"#include "dispc.h"#define MODULE_NAME "omapfb"static unsigned int def_accel;static unsigned long def_vram[OMAPFB_PLANE_NUM];static unsigned int def_vram_cnt;static unsigned long def_vxres;static unsigned long def_vyres;static unsigned int def_rotate;static unsigned int def_mirror;#ifdef CONFIG_FB_OMAP_MANUAL_UPDATEstatic int manual_update = 1;#elsestatic int manual_update;#endifstatic struct platform_device *fbdev_pdev;static struct lcd_panel *fbdev_panel;static struct omapfb_device *omapfb_dev;struct caps_table_struct { unsigned long flag; const char *name;};static struct caps_table_struct ctrl_caps[] = { { OMAPFB_CAPS_MANUAL_UPDATE, "manual update" }, { OMAPFB_CAPS_TEARSYNC, "tearing synchronization" }, { OMAPFB_CAPS_PLANE_RELOCATE_MEM, "relocate plane memory" }, { OMAPFB_CAPS_PLANE_SCALE, "scale plane" }, { OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE, "pixel double window" }, { OMAPFB_CAPS_WINDOW_SCALE, "scale window" }, { OMAPFB_CAPS_WINDOW_OVERLAY, "overlay window" }, { OMAPFB_CAPS_SET_BACKLIGHT, "backlight setting" },};static struct caps_table_struct color_caps[] = { { 1 << OMAPFB_COLOR_RGB565, "RGB565", }, { 1 << OMAPFB_COLOR_YUV422, "YUV422", }, { 1 << OMAPFB_COLOR_YUV420, "YUV420", }, { 1 << OMAPFB_COLOR_CLUT_8BPP, "CLUT8", }, { 1 << OMAPFB_COLOR_CLUT_4BPP, "CLUT4", }, { 1 << OMAPFB_COLOR_CLUT_2BPP, "CLUT2", }, { 1 << OMAPFB_COLOR_CLUT_1BPP, "CLUT1", }, { 1 << OMAPFB_COLOR_RGB444, "RGB444", }, { 1 << OMAPFB_COLOR_YUY422, "YUY422", },};/* * --------------------------------------------------------------------------- * LCD panel * --------------------------------------------------------------------------- */extern struct lcd_ctrl hwa742_ctrl;extern struct lcd_ctrl blizzard_ctrl;static const struct lcd_ctrl *ctrls[] = {#ifdef CONFIG_ARCH_OMAP1 &omap1_int_ctrl,#else &omap2_int_ctrl,#endif#ifdef CONFIG_FB_OMAP_LCDC_HWA742 &hwa742_ctrl,#endif#ifdef CONFIG_FB_OMAP_LCDC_BLIZZARD &blizzard_ctrl,#endif};#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL#ifdef CONFIG_ARCH_OMAP1extern struct lcd_ctrl_extif omap1_ext_if;#elseextern struct lcd_ctrl_extif omap2_ext_if;#endif#endifstatic void omapfb_rqueue_lock(struct omapfb_device *fbdev){ mutex_lock(&fbdev->rqueue_mutex);}static void omapfb_rqueue_unlock(struct omapfb_device *fbdev){ mutex_unlock(&fbdev->rqueue_mutex);}/* * --------------------------------------------------------------------------- * LCD controller and LCD DMA * --------------------------------------------------------------------------- *//* Lookup table to map elem size to elem type. */static const int dma_elem_type[] = { 0, OMAP_DMA_DATA_TYPE_S8, OMAP_DMA_DATA_TYPE_S16, 0, OMAP_DMA_DATA_TYPE_S32,};/* * Allocate resources needed for LCD controller and LCD DMA operations. Video * memory is allocated from system memory according to the virtual display * size, except if a bigger memory size is specified explicitly as a kernel * parameter. */static int ctrl_init(struct omapfb_device *fbdev){ int r; int i; /* kernel/module vram parameters override boot tags/board config */ if (def_vram_cnt) { for (i = 0; i < def_vram_cnt; i++) fbdev->mem_desc.region[i].size = PAGE_ALIGN(def_vram[i]); fbdev->mem_desc.region_cnt = i; } else { struct omapfb_platform_data *conf; conf = fbdev->dev->platform_data; fbdev->mem_desc = conf->mem_desc; } if (!fbdev->mem_desc.region_cnt) { struct lcd_panel *panel = fbdev->panel; int def_size; int bpp = panel->bpp; /* 12 bpp is packed in 16 bits */ if (bpp == 12) bpp = 16; def_size = def_vxres * def_vyres * bpp / 8; fbdev->mem_desc.region_cnt = 1; fbdev->mem_desc.region[0].size = PAGE_ALIGN(def_size); } r = fbdev->ctrl->init(fbdev, 0, &fbdev->mem_desc); if (r < 0) { dev_err(fbdev->dev, "controller initialization failed (%d)\n", r); return r; }#ifdef DEBUG for (i = 0; i < fbdev->mem_desc.region_cnt; i++) { dev_dbg(fbdev->dev, "region%d phys %08x virt %p size=%lu\n", i, fbdev->mem_desc.region[i].paddr, fbdev->mem_desc.region[i].vaddr, fbdev->mem_desc.region[i].size); }#endif return 0;}static void ctrl_cleanup(struct omapfb_device *fbdev){ fbdev->ctrl->cleanup();}/* Must be called with fbdev->rqueue_mutex held. */static int ctrl_change_mode(struct fb_info *fbi){ int r; unsigned long offset; struct omapfb_plane_struct *plane = fbi->par; struct omapfb_device *fbdev = plane->fbdev; struct fb_var_screeninfo *var = &fbi->var; offset = var->yoffset * fbi->fix.line_length + var->xoffset * var->bits_per_pixel / 8; if (fbdev->ctrl->sync) fbdev->ctrl->sync(); r = fbdev->ctrl->setup_plane(plane->idx, plane->info.channel_out, offset, var->xres_virtual, plane->info.pos_x, plane->info.pos_y, var->xres, var->yres, plane->color_mode); if (fbdev->ctrl->set_scale != NULL) r = fbdev->ctrl->set_scale(plane->idx, var->xres, var->yres, plane->info.out_width, plane->info.out_height); return r;}/* * --------------------------------------------------------------------------- * fbdev framework callbacks and the ioctl interface * --------------------------------------------------------------------------- *//* Called each time the omapfb device is opened */static int omapfb_open(struct fb_info *info, int user){ return 0;}static void omapfb_sync(struct fb_info *info);/* Called when the omapfb device is closed. We make sure that any pending * gfx DMA operations are ended, before we return. */static int omapfb_release(struct fb_info *info, int user){ omapfb_sync(info); return 0;}/* Store a single color palette entry into a pseudo palette or the hardware * palette if one is available. For now we support only 16bpp and thus store * the entry only to the pseudo palette. */static int _setcolreg(struct fb_info *info, u_int regno, u_int red, u_int green, u_int blue, u_int transp, int update_hw_pal){ struct omapfb_plane_struct *plane = info->par; struct omapfb_device *fbdev = plane->fbdev; struct fb_var_screeninfo *var = &info->var; int r = 0; switch (plane->color_mode) { case OMAPFB_COLOR_YUV422: case OMAPFB_COLOR_YUV420: case OMAPFB_COLOR_YUY422: r = -EINVAL; break; case OMAPFB_COLOR_CLUT_8BPP: case OMAPFB_COLOR_CLUT_4BPP: case OMAPFB_COLOR_CLUT_2BPP: case OMAPFB_COLOR_CLUT_1BPP: if (fbdev->ctrl->setcolreg) r = fbdev->ctrl->setcolreg(regno, red, green, blue, transp, update_hw_pal); /* Fallthrough */ case OMAPFB_COLOR_RGB565: case OMAPFB_COLOR_RGB444: if (r != 0) break; if (regno < 0) { r = -EINVAL; break; } if (regno < 16) { u16 pal; pal = ((red >> (16 - var->red.length)) << var->red.offset) | ((green >> (16 - var->green.length)) << var->green.offset) | (blue >> (16 - var->blue.length)); ((u32 *)(info->pseudo_palette))[regno] = pal; } break; default: BUG(); } return r;}static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info){ return _setcolreg(info, regno, red, green, blue, transp, 1);}static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info){ int count, index, r; u16 *red, *green, *blue, *transp; u16 trans = 0xffff; red = cmap->red; green = cmap->green; blue = cmap->blue; transp = cmap->transp; index = cmap->start; for (count = 0; count < cmap->len; count++) { if (transp) trans = *transp++; r = _setcolreg(info, index++, *red++, *green++, *blue++, trans, count == cmap->len - 1); if (r != 0) return r; } return 0;}static int omapfb_update_full_screen(struct fb_info *fbi);static int omapfb_blank(int blank, struct fb_info *fbi){ struct omapfb_plane_struct *plane = fbi->par; struct omapfb_device *fbdev = plane->fbdev; int do_update = 0; int r = 0; omapfb_rqueue_lock(fbdev); switch (blank) { case VESA_NO_BLANKING: if (fbdev->state == OMAPFB_SUSPENDED) { if (fbdev->ctrl->resume) fbdev->ctrl->resume(); fbdev->panel->enable(fbdev->panel); fbdev->state = OMAPFB_ACTIVE; if (fbdev->ctrl->get_update_mode() == OMAPFB_MANUAL_UPDATE) do_update = 1; } break; case VESA_POWERDOWN: if (fbdev->state == OMAPFB_ACTIVE) { fbdev->panel->disable(fbdev->panel); if (fbdev->ctrl->suspend) fbdev->ctrl->suspend(); fbdev->state = OMAPFB_SUSPENDED; } break; default: r = -EINVAL; } omapfb_rqueue_unlock(fbdev); if (r == 0 && do_update) r = omapfb_update_full_screen(fbi); return r;}static void omapfb_sync(struct fb_info *fbi){ struct omapfb_plane_struct *plane = fbi->par; struct omapfb_device *fbdev = plane->fbdev; omapfb_rqueue_lock(fbdev); if (fbdev->ctrl->sync) fbdev->ctrl->sync(); omapfb_rqueue_unlock(fbdev);}/* * 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 fb_info *fbi){ struct fb_fix_screeninfo *fix = &fbi->fix; struct fb_var_screeninfo *var = &fbi->var; struct omapfb_plane_struct *plane = fbi->par; struct omapfb_mem_region *rg; int bpp; rg = &plane->fbdev->mem_desc.region[plane->idx]; fbi->screen_base = rg->vaddr; fix->smem_start = rg->paddr; fix->smem_len = rg->size; fix->type = FB_TYPE_PACKED_PIXELS; bpp = var->bits_per_pixel; if (var->nonstd) fix->visual = FB_VISUAL_PSEUDOCOLOR; else switch (var->bits_per_pixel) { case 16: case 12: fix->visual = FB_VISUAL_TRUECOLOR; /* 12bpp is stored in 16 bits */ bpp = 16; 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 * bpp / 8;}static int set_color_mode(struct omapfb_plane_struct *plane, struct fb_var_screeninfo *var){ switch (var->nonstd) { case 0: break; case OMAPFB_COLOR_YUV422: var->bits_per_pixel = 16; plane->color_mode = var->nonstd; return 0; case OMAPFB_COLOR_YUV420: var->bits_per_pixel = 12; plane->color_mode = var->nonstd; return 0; case OMAPFB_COLOR_YUY422: var->bits_per_pixel = 16; plane->color_mode = var->nonstd; return 0; default: return -EINVAL; } switch (var->bits_per_pixel) { case 1: plane->color_mode = OMAPFB_COLOR_CLUT_1BPP; return 0; case 2: plane->color_mode = OMAPFB_COLOR_CLUT_2BPP; return 0; case 4: plane->color_mode = OMAPFB_COLOR_CLUT_4BPP; return 0; case 8: plane->color_mode = OMAPFB_COLOR_CLUT_8BPP; return 0; case 12: var->bits_per_pixel = 16; plane->color_mode = OMAPFB_COLOR_RGB444; return 0; case 16: plane->color_mode = OMAPFB_COLOR_RGB565; return 0; default: return -EINVAL; }}/* * 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 fb_info *fbi, struct fb_var_screeninfo *var){ int bpp; unsigned long max_frame_size; unsigned long line_size; int xres_min, xres_max; int yres_min, yres_max; struct omapfb_plane_struct *plane = fbi->par; struct omapfb_device *fbdev = plane->fbdev; struct lcd_panel *panel = fbdev->panel; if (set_color_mode(plane, var) < 0) return -EINVAL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -