📄 davincifb.c
字号:
/* * drivers/video/dm64xxfb.c * * Framebuffer driver for Texas Instruments DM644x display controller. * * Copyright (C) 2005 Texas Instruments, Inc. * Rishi Bhattacharya <support@ti.com> * * Leveraged from the framebuffer driver for OMAP24xx * written by Andy Lowe (source@mvista.com) * Copyright (C) 2004 MontaVista Software, Inc. * * This file is licensed under the terms of the GNU General Public License * version 2. This program is licensed "as is" without any warranty of any * kind, whether express or implied. */#include <linux/module.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/tty.h>#include <linux/slab.h>//包含内存分配函数,原来的malloc.h不存在#include <linux/delay.h>#include <linux/fb.h>#include <linux/init.h>#include <linux/dma-mapping.h>#include <linux/interrupt.h>#include <asm/irq.h>#include <asm/uaccess.h>#include <video/davincifb.h>
/*为了定义 pinmux0和pinmux1而包含以下的文件,调试时可根据结果删减文件*/
/*
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/major.h>
#include <linux/root_dev.h>
#include <asm/setup.h>
#include <asm/semaphore.h>
#include <asm/hardware/clock.h>
#include <asm/io.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/arch/hardware.h>
//#include "clock.h"
#define PINMUX0 __REG(0x01c40000)
#define PINMUX1 __REG(0x01c40004)
///////////////////////////////////////////////////
*/
#define PINMUX0 IO_ADDRESS(0x01c40000)
#define PINMUX1 IO_ADDRESS(0x01c40004)
#define LCDS 7#define PLL IO_ADDRESS(0x01c40c00)#define PLLM (PLL+0x110) //PLL的默认值是12,与文档中不一样#define PLLDIV1 (PLL+0x118) //PLLDIV1的默认值是5,与文档中不一样#define PLLDIV2 (PLL+0x11c)#define POSTDIV (PLL+0x128)#define PLLCTL (PLL+0x100)#define EDMA IO_ADDRESS(0x01c00000)#define EER (EDMA+0x1020)#define EERH (EDMA+0x1024)#define EECR (EDMA+0x1028)#define EECRH (EDMA+0x102c)#define EESR (EDMA+0x1030)#define EESRH (EDMA+0x1034)#define DDR IO_ADDRESS(0x20000000)#define DDR_SDRSTAT (DDR+0x04)#define DDR_SDBCR (DDR+0x08)#define DDR_SDRCR (DDR+0x0c)#define DDR_DDRPHYCR (DDR+0xe4)/* Output Format Selection */#define COMPOSITE_OUTPUT//#define SVIDEO_OUTPUT//#define COMPONENT_OUTPUT//#define DEBUG#ifdef DEBUG#define DBGENTER printk("Entered %s\n", __FUNCTION__)#define DBGEXIT printk("Exited %s\n", __FUNCTION__)#define RETURN(x) \do { \ int __ret = (x); \ printk("Exited %s : ret %d\n", __FUNCTION__, __ret); \ return __ret; \} while(0)#else#define DBGENTER#define DBGEXIT#define RETURN(x) return (x)#endif//#define MULTIPLE_BUFFERING 1 #ifdef MULTIPLE_BUFFERING#define DOUBLE_BUF 2#define TRIPLE_BUF 3#else#define DOUBLE_BUF 1#define TRIPLE_BUF 1#endif/* * display controller register I/O routines */static __inline__ u32dispc_reg_in(u32 offset) //把offset地址中的值读入{ return(inl(offset));}static __inline__ u32dispc_reg_out(u32 offset, u32 val) //把val写到offset地址中{ /* outw(val, offset); */ outl(val, offset); return(val);}static __inline__ u32dispc_reg_merge(u32 offset, u32 val, u32 mask)//寄存器值的合并,把val中mask指定的位写入到寄存器中{ u32 addr = offset; u32 new_val = (inl(addr) & ~mask) | (val & mask); outl(new_val, addr); return(new_val);}/* There are 4 framebuffers, each represented by an fb_info and * a dm_win_info structure */#define DRIVER "dm64xxfb"
#define OSD0_FBNAME "dm_osd0_fb"#define OSD1_FBNAME "dm_osd1_fb"#define VID0_FBNAME "dm_vid0_fb"#define VID1_FBNAME "dm_vid1_fb"/* usage: if (is_win(info->fix.id, OSD0)) ... */#define is_win(name, x) ((strcmp(name, x ## _FBNAME) == 0) ? 1 : 0) struct dm_win_info { //窗口的信息结构 struct fb_info info; //此窗口的fb_info信息 /* X and Y position */
unsigned int x, y; //x,y的坐标
/* framebuffer area */
dma_addr_t fb_base_phys; //ram 的物理地址
unsigned long fb_base; //fb的起始地址
unsigned long fb_size; //fb的大小
u32 pseudo_palette[17];
/* flag to identify if framebuffer area is fixed already or not */
int alloc_fb_mem;
struct dm_info *dm; //
};static struct dm_info { struct dm_win_info *osd0; struct dm_win_info *osd1;
struct dm_win_info *vid0;
struct dm_win_info *vid1; /* to map the registers */ dma_addr_t mmio_base_phys; unsigned long mmio_base; unsigned long mmio_size; wait_queue_head_t vsync_wait; unsigned long vsync_cnt; int timeout; /* this is the function that configures the output device (NTSC/PAL/LCD) * for the required output format (composite/s-video/component/rgb) */ void (*output_device_config)(int on);} dm;static struct fb_ops dm64xxfb_ops;#define BASEX 0x25 //80#define BASEY 0x15#define NTSCPAL LCDS#define DISP_XRES 1280#define DISP_YRES 1024#define DISP_MEMY 1024#ifdef COMPOSITE_OUTPUT#define OUTPUT COMPOSITE#endif#ifdef SVIDEO_OUTPUT#define OUTPUT SVIDEO#endif#ifdef COMPONENT_OUTPUT#define OUTPUT COMPONENT#endif/* Random value chosen for now. Should be within the panel's supported range */#define LCD_PANEL_CLOCK 18518 //这个还没弄懂!!!/* All window widths have to be rounded up to a multiple of 32 bytes *//* The OSD0 window has to be always within VID0. Plus, since it is in RGB565 * mode, it _cannot_ overlap with VID1. * For defaults, we are setting the OSD0 window to be displayed in the top * left quadrant of the screen, and the VID1 in the bottom right quadrant. * So the default 'xres' and 'yres' are set to half of the screen width and * height respectively. Note however that the framebuffer size is allocated * for the full screen size so the user can change the 'xres' and 'yres' by * using the FBIOPUT_VSCREENINFO ioctl within the limits of the screen size. */#define round_32(width) ((((width) + 31) / 32) * 32 ) //把width取到32的整数倍 #define OSD0_XRES round_32((720)*16/8) * 8/16 /* pixels */ //round_32((DISP_XRES)*16/8)是round后水平方向含有的byte数#define OSD0_YRES 480 //DISP_YRES //垂直方向的分辨率,不用是32的整数倍#define OSD0_FB_PHY 0#define OSD0_FB_SIZE (round_32((720)*16/8) * DISP_MEMY * DOUBLE_BUF) //FB的大小,水平方向的byte数×DISP_MEMY×buffer的个数 /* 16 bpp, Double buffered */static struct fb_var_screeninfo osd0_default_var = { .xres = 256;//OSD0_XRES, //x方向可见分辨率 .yres = 200;//OSD0_YRES, //y方向可见分辨率 .xres_virtual = OSD0_XRES,
.yres_virtual = OSD0_YRES * DOUBLE_BUF, //y方向的虚拟(存储)分辨率 .xoffset = 0, //可见画面与可显示画面的偏移 .yoffset = 0, .bits_per_pixel = 16, //每个象素有16bit .grayscale = 0, //灰度平衡 0 .red = {11, 5, 0}, /*RGB 565 模式*/ .green = { 5, 6, 0}, .blue = { 0, 5, 0}, .transp = { 0, 0, 0}, .nonstd = 0, .activate = FB_ACTIVATE_NOW, .height = -1, .width = -1, .accel_flags = 0, .pixclock = LCD_PANEL_CLOCK, /* picoseconds */ .left_margin = 40, /* pixclocks */ .right_margin = 4, /* pixclocks */ .upper_margin = 8, /* line clocks */ .lower_margin = 2, /* line clocks */ .hsync_len = 4, /* pixclocks */
.vsync_len = 2, /* line clocks */ .sync = 0, .vmode = FB_VMODE_INTERLACED, .reserved[0] = 0, /* X position */ .reserved[1] = 0, /* Y position */ //.reserved[3] = 0, /* Zoom */};/* Using the full screen for OSD1 by default */
#define OSD1_XRES round_32(DISP_XRES*4/8) * 8/4 /* pixels */
#define OSD1_YRES DISP_YRES
#define OSD1_FB_PHY 0
#define OSD1_FB_SIZE (round_32(DISP_XRES*4/8) * DISP_MEMY * DOUBLE_BUF)
static struct fb_var_screeninfo osd1_default_var = {
.xres = DISP_XRES, .yres = OSD1_YRES, .xres_virtual = OSD1_XRES, .yres_virtual = OSD1_YRES * DOUBLE_BUF, .xoffset = 0, .yoffset = 0, .bits_per_pixel = 4, .activate = FB_ACTIVATE_NOW, .accel_flags = 0, .pixclock = LCD_PANEL_CLOCK, /* picoseconds */ .vmode = FB_VMODE_INTERLACED, .reserved[0] = 0, /* X position */ .reserved[1] = 0, /* Y position */ //.reserved[3] = 0, /* Zoom */};/* Using the full screen for VID0 by default */#define VID0_XRES (round_32((DISP_XRES)*16/8) * 8/16) /* pixels */#define VID0_YRES DISP_YRES#define VID0_FB_PHY 0#define VID0_FB_SIZE (round_32((DISP_XRES)*16/8) * DISP_MEMY * TRIPLE_BUF)static struct fb_var_screeninfo vid0_default_var = { .xres = VID0_XRES, .yres = VID0_YRES, .xres_virtual = VID0_XRES, .yres_virtual = VID0_YRES * TRIPLE_BUF , //////////// .xoffset = 0, .yoffset = 0, .bits_per_pixel = 16, .activate = FB_ACTIVATE_NOW, .height = -1, .width = -1, .left_margin = 20, /* pixclocks */ .right_margin = 4, /* pixclocks */ .upper_margin = 8, /* line clocks */ .lower_margin = 2, /* line clocks */ .hsync_len = 4, /* pixclocks */
.vsync_len = 2, /* line clocks */ .sync = 0, .accel_flags = 0, .pixclock = LCD_PANEL_CLOCK, /* picoseconds */ .vmode = FB_VMODE_INTERLACED, .reserved[0] = 0, /* X position */ .reserved[1] = 0, /* Y position */ //.reserved[3] = 0, /* Zoom */};/* Using the bottom right quadrant of the screen screen for VID1 by default, * but keeping the framebuffer allocated for the full screen, so the user can * change the 'xres' and 'yres' later using the FBIOPUT_VSCREENINFO ioctl. */#define VID1_BPP 32 //*****16 /* Video1 can be in YUV or RGB888 format */#define VID1_XRES (round_32((DISP_XRES)*32/8) * 8/32) /* pixels */#define VID1_YRES DISP_YRES#define VID1_FB_PHY 0#define VID1_FB_SIZE (round_32((DISP_XRES)*32/8) * DISP_MEMY * TRIPLE_BUF)static struct fb_var_screeninfo vid1_default_var = { .xres = VID1_XRES, .yres = VID1_YRES, .xres_virtual = VID1_XRES, .yres_virtual = VID1_YRES * TRIPLE_BUF, .xoffset = 0, .yoffset = 0, .red={16,8,0}, .green={8,8,0}, .blue={0,8,0}, .transp = { 0, 0, 0}, .nonstd = 0, .grayscale=0, .height = -1, .width = -1, .left_margin = 20, /* pixclocks */ .right_margin = 4, /* pixclocks */ .upper_margin = 8, /* line clocks */ .lower_margin = 2, /* line clocks */ .hsync_len = 4, /* pixclocks */
.vsync_len = 2, /* line clocks */ .sync = 0, .bits_per_pixel = VID1_BPP, .activate = FB_ACTIVATE_NOW, .accel_flags = 0, .pixclock = LCD_PANEL_CLOCK, /* picoseconds */ .vmode = FB_VMODE_INTERLACED, //.reserved[0] = 256 + 16, /* X position */ //相对于OSD0窗口的位置
//.reserved[1] = 200 + 16, /* Y position */ //.reserved[3] = 0, /* Zoom */};#define x_pos(w) ((w)->x)#define y_pos(w) ((w)->y)#define zoom(w) ((w)->zoom)/*#define x_pos(v) ((v)->reserved[0])#define y_pos(v) ((v)->reserved[1])#define zoom(v) ((v)->reserved[2])*/static struct dmparams_t { u8 output; u8 format; u8 windows; /* bitmap flag based on VID0, VID1, OSD0, OSD1 * definitions in header file */ u32 vid0_xres; u32 vid0_yres; u32 vid0_xpos; u32 vid0_ypos; u32 vid1_xres; u32 vid1_yres; u32 vid1_xpos; u32 vid1_ypos; u32 osd0_xres;
u32 osd0_yres; u32 osd0_xpos; u32 osd0_ypos; u32 osd1_xres; u32 osd1_yres; u32 osd1_xpos; u32 osd1_ypos;} dmparams = { NTSCPAL, /* output */ OUTPUT, /* format */ (1<<VID0)|(1<<VID1)|(1<<OSD0)&~(1<<OSD1), /*设置窗口的使能与否*/ /* windows registered */ VID0_XRES, VID0_YRES, 0, 0, //712,480,256+16,200+16, /* vid0 size and position */ VID1_XRES, VID1_YRES, 0, 0, /* vid1 size and position */ //720 , 480 , 0 , 0 , //712 ,480 ,16 , 0 , 256,200, 0,0, /* osd0 size and position */ OSD1_XRES,OSD1_YRES, 0, 0, /* osd1 size and position */ };/* Must do checks against the limits of the output device */static int dm64xx_venc_check_mode(const struct dm_win_info *w, const struct fb_var_screeninfo *var){ DBGENTER; RETURN(0);}static irqreturn_t dm64xxfb_isr(int irq, void *arg, struct pt_regs *regs){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -