au1200fb.c

来自「Linux环境下视频显示卡设备的驱动程序源代码」· C语言 代码 · 共 1,922 行 · 第 1/4 页

C
1,922
字号
/* * BRIEF MODULE DESCRIPTION *	Au1200 LCD Driver. * * Copyright 2004-2005 AMD * Author: AMD * * Based on: * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device *  Created 28 Dec 1997 by Geert Uytterhoeven * *  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  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT, *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *  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., *  675 Mass Ave, Cambridge, MA 02139, USA. */#include <linux/module.h>#include <linux/platform_device.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/fb.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/ctype.h>#include <linux/dma-mapping.h>#include <asm/mach-au1x00/au1000.h>#include "au1200fb.h"#ifdef CONFIG_PM#include <asm/mach-au1x00/au1xxx_pm.h>#endif#ifndef CONFIG_FB_AU1200_DEVS#define CONFIG_FB_AU1200_DEVS 4#endif#define DRIVER_NAME "au1200fb"#define DRIVER_DESC "LCD controller driver for AU1200 processors"#define DEBUG 1#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg)#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg)#define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg)#if DEBUG#define print_dbg(f, arg...) printk(KERN_DEBUG __FILE__ ": " f "\n", ## arg)#else#define print_dbg(f, arg...) do {} while (0)#endif#define AU1200_LCD_FB_IOCTL 0x46FF#define AU1200_LCD_SET_SCREEN 1#define AU1200_LCD_GET_SCREEN 2#define AU1200_LCD_SET_WINDOW 3#define AU1200_LCD_GET_WINDOW 4#define AU1200_LCD_SET_PANEL  5#define AU1200_LCD_GET_PANEL  6#define SCREEN_SIZE		    (1<< 1)#define SCREEN_BACKCOLOR    (1<< 2)#define SCREEN_BRIGHTNESS   (1<< 3)#define SCREEN_COLORKEY     (1<< 4)#define SCREEN_MASK         (1<< 5)struct au1200_lcd_global_regs_t {	unsigned int flags;	unsigned int xsize;	unsigned int ysize;	unsigned int backcolor;	unsigned int brightness;	unsigned int colorkey;	unsigned int mask;	unsigned int panel_choice;	char panel_desc[80];};#define WIN_POSITION            (1<< 0)#define WIN_ALPHA_COLOR         (1<< 1)#define WIN_ALPHA_MODE          (1<< 2)#define WIN_PRIORITY            (1<< 3)#define WIN_CHANNEL             (1<< 4)#define WIN_BUFFER_FORMAT       (1<< 5)#define WIN_COLOR_ORDER         (1<< 6)#define WIN_PIXEL_ORDER         (1<< 7)#define WIN_SIZE                (1<< 8)#define WIN_COLORKEY_MODE       (1<< 9)#define WIN_DOUBLE_BUFFER_MODE  (1<< 10)#define WIN_RAM_ARRAY_MODE      (1<< 11)#define WIN_BUFFER_SCALE        (1<< 12)#define WIN_ENABLE	            (1<< 13)struct au1200_lcd_window_regs_t {	unsigned int flags;	unsigned int xpos;	unsigned int ypos;	unsigned int alpha_color;	unsigned int alpha_mode;	unsigned int priority;	unsigned int channel;	unsigned int buffer_format;	unsigned int color_order;	unsigned int pixel_order;	unsigned int xsize;	unsigned int ysize;	unsigned int colorkey_mode;	unsigned int double_buffer_mode;	unsigned int ram_array_mode;	unsigned int xscale;	unsigned int yscale;	unsigned int enable;};struct au1200_lcd_iodata_t {	unsigned int subcmd;	struct au1200_lcd_global_regs_t global;	struct au1200_lcd_window_regs_t window;};#if defined(__BIG_ENDIAN)#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_11#else#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_00#endif#define LCD_CONTROL_DEFAULT_SBPPF LCD_CONTROL_SBPPF_565/* Private, per-framebuffer management information (independent of the panel itself) */struct au1200fb_device {	struct fb_info fb_info;			/* FB driver info record */	int					plane;	unsigned char* 		fb_mem;		/* FrameBuffer memory map */	unsigned int		fb_len;	dma_addr_t    		fb_phys;};static struct au1200fb_device _au1200fb_devices[CONFIG_FB_AU1200_DEVS];/********************************************************************//* LCD controller restrictions */#define AU1200_LCD_MAX_XRES	1280#define AU1200_LCD_MAX_YRES	1024#define AU1200_LCD_MAX_BPP	32#define AU1200_LCD_MAX_CLK	96000000 /* fixme: this needs to go away ? */#define AU1200_LCD_NBR_PALETTE_ENTRIES 256/* Default number of visible screen buffer to allocate */#define AU1200FB_NBR_VIDEO_BUFFERS 1/********************************************************************/static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR;static int window_index = 2; /* default is zero */static int panel_index = 2; /* default is zero */static struct window_settings *win;static struct panel_settings *panel;static int noblanking = 1;static int nohwcursor = 0;struct window_settings {	unsigned char name[64];	uint32 mode_backcolor;	uint32 mode_colorkey;	uint32 mode_colorkeymsk;	struct {		int xres;		int yres;		int xpos;		int ypos;		uint32 mode_winctrl1; /* winctrl1[FRM,CCO,PO,PIPE] */		uint32 mode_winenable;	} w[4];};#if defined(__BIG_ENDIAN)#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_00#else#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_01#endifextern int board_au1200fb_panel_init (void);extern int board_au1200fb_panel_shutdown (void);#ifdef CONFIG_PMint au1200fb_pm_callback(au1xxx_power_dev_t *dev,		au1xxx_request_t request, void *data);au1xxx_power_dev_t *LCD_pm_dev;#endif/* * Default window configurations */static struct window_settings windows[] = {	{ /* Index 0 */		"0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",		/* mode_backcolor	*/ 0x006600ff,		/* mode_colorkey,msk*/ 0, 0,		{			{			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |				LCD_WINCTRL1_PO_16BPP,			/* mode_winenable*/ LCD_WINENABLE_WEN0,			},			{			/* xres, yres, xpos, ypos */ 100, 100, 100, 100,			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |				LCD_WINCTRL1_PO_16BPP |				LCD_WINCTRL1_PIPE,			/* mode_winenable*/ LCD_WINENABLE_WEN1,			},			{			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |				LCD_WINCTRL1_PO_16BPP,			/* mode_winenable*/ 0,			},			{			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |				LCD_WINCTRL1_PO_16BPP |				LCD_WINCTRL1_PIPE,			/* mode_winenable*/ 0,			},		},	},	{ /* Index 1 */		"0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",		/* mode_backcolor	*/ 0x006600ff,		/* mode_colorkey,msk*/ 0, 0,		{			{			/* xres, yres, xpos, ypos */ 320, 240, 5, 5,			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_24BPP |				LCD_WINCTRL1_PO_00,			/* mode_winenable*/ LCD_WINENABLE_WEN0,			},			{			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565				| LCD_WINCTRL1_PO_16BPP,			/* mode_winenable*/ 0,			},			{			/* xres, yres, xpos, ypos */ 100, 100, 0, 0,			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |				LCD_WINCTRL1_PO_16BPP |				LCD_WINCTRL1_PIPE,			/* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/,			},			{			/* xres, yres, xpos, ypos */ 200, 25, 0, 0,			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |				LCD_WINCTRL1_PO_16BPP |				LCD_WINCTRL1_PIPE,			/* mode_winenable*/ 0,			},		},	},	{ /* Index 2 */		"0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",		/* mode_backcolor	*/ 0x006600ff,		/* mode_colorkey,msk*/ 0, 0,		{			{			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |				LCD_WINCTRL1_PO_16BPP,			/* mode_winenable*/ LCD_WINENABLE_WEN0,			},			{			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |				LCD_WINCTRL1_PO_16BPP,			/* mode_winenable*/ 0,			},			{			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_32BPP |				LCD_WINCTRL1_PO_00|LCD_WINCTRL1_PIPE,			/* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/,			},			{			/* xres, yres, xpos, ypos */ 0, 0, 0, 0,			/* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |				LCD_WINCTRL1_PO_16BPP |				LCD_WINCTRL1_PIPE,			/* mode_winenable*/ 0,			},		},	},	/* Need VGA 640 @ 24bpp, @ 32bpp */	/* Need VGA 800 @ 24bpp, @ 32bpp */	/* Need VGA 1024 @ 24bpp, @ 32bpp */};/* * Controller configurations for various panels. */struct panel_settings{	const char name[25];		/* Full name <vendor>_<model> */	struct 	fb_monspecs monspecs; 	/* FB monitor specs */	/* panel timings */	uint32 mode_screen;	uint32 mode_horztiming;	uint32 mode_verttiming;	uint32 mode_clkcontrol;	uint32 mode_pwmdiv;	uint32 mode_pwmhi;	uint32 mode_outmask;	uint32 mode_fifoctrl;	uint32 mode_toyclksrc;	uint32 mode_backlight;	uint32 mode_auxpll;	int (*device_init)(void);	int (*device_shutdown)(void);#define Xres min_xres#define Yres min_yres	u32	min_xres;		/* Minimum horizontal resolution */	u32	max_xres;		/* Maximum horizontal resolution */	u32 	min_yres;		/* Minimum vertical resolution */	u32 	max_yres;		/* Maximum vertical resolution */};/********************************************************************//* fixme: Maybe a modedb for the CRT ? otherwise panels should be as-is *//* List of panels known to work with the AU1200 LCD controller. * To add a new panel, enter the same specifications as the * Generic_TFT one, and MAKE SURE that it doesn't conflicts * with the controller restrictions. Restrictions are: * * STN color panels: max_bpp <= 12 * STN mono panels: max_bpp <= 4 * TFT panels: max_bpp <= 16 * max_xres <= 800 * max_yres <= 600 */static struct panel_settings known_lcd_panels[] ={	[0] = { /* QVGA 320x240 H:33.3kHz V:110Hz */		.name = "QVGA_320x240",		.monspecs = {			.modedb = NULL,			.modedb_len = 0,			.hfmin = 30000,			.hfmax = 70000,			.vfmin = 60,			.vfmax = 60,			.dclkmin = 6000000,			.dclkmax = 28000000,			.input = FB_DISP_RGB,		},		.mode_screen		= LCD_SCREEN_SX_N(320) |			LCD_SCREEN_SY_N(240),		.mode_horztiming	= 0x00c4623b,		.mode_verttiming	= 0x00502814,		.mode_clkcontrol	= 0x00020002, /* /4=24Mhz */		.mode_pwmdiv		= 0x00000000,		.mode_pwmhi		= 0x00000000,		.mode_outmask	= 0x00FFFFFF,		.mode_fifoctrl	= 0x2f2f2f2f,		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */		.mode_backlight	= 0x00000000,		.mode_auxpll		= 8, /* 96MHz AUXPLL */		.device_init		= NULL,		.device_shutdown	= NULL,		320, 320,		240, 240,	},	[1] = { /* VGA 640x480 H:30.3kHz V:58Hz */		.name = "VGA_640x480",		.monspecs = {			.modedb = NULL,			.modedb_len = 0,			.hfmin = 30000,			.hfmax = 70000,			.vfmin = 60,			.vfmax = 60,			.dclkmin = 6000000,			.dclkmax = 28000000,			.input = FB_DISP_RGB,		},		.mode_screen		= 0x13f9df80,		.mode_horztiming	= 0x003c5859,		.mode_verttiming	= 0x00741201,		.mode_clkcontrol	= 0x00020001, /* /4=24Mhz */		.mode_pwmdiv		= 0x00000000,		.mode_pwmhi		= 0x00000000,		.mode_outmask	= 0x00FFFFFF,		.mode_fifoctrl	= 0x2f2f2f2f,		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */		.mode_backlight	= 0x00000000,		.mode_auxpll		= 8, /* 96MHz AUXPLL */		.device_init		= NULL,		.device_shutdown	= NULL,		640, 480,		640, 480,	},	[2] = { /* SVGA 800x600 H:46.1kHz V:69Hz */		.name = "SVGA_800x600",		.monspecs = {			.modedb = NULL,			.modedb_len = 0,			.hfmin = 30000,			.hfmax = 70000,			.vfmin = 60,			.vfmax = 60,			.dclkmin = 6000000,			.dclkmax = 28000000,			.input = FB_DISP_RGB,		},		.mode_screen		= 0x18fa5780,		.mode_horztiming	= 0x00dc7e77,		.mode_verttiming	= 0x00584805,		.mode_clkcontrol	= 0x00020000, /* /2=48Mhz */		.mode_pwmdiv		= 0x00000000,		.mode_pwmhi		= 0x00000000,		.mode_outmask	= 0x00FFFFFF,		.mode_fifoctrl	= 0x2f2f2f2f,		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */		.mode_backlight	= 0x00000000,		.mode_auxpll		= 8, /* 96MHz AUXPLL */		.device_init		= NULL,		.device_shutdown	= NULL,		800, 800,		600, 600,	},	[3] = { /* XVGA 1024x768 H:56.2kHz V:70Hz */		.name = "XVGA_1024x768",		.monspecs = {			.modedb = NULL,			.modedb_len = 0,			.hfmin = 30000,			.hfmax = 70000,			.vfmin = 60,			.vfmax = 60,			.dclkmin = 6000000,			.dclkmax = 28000000,			.input = FB_DISP_RGB,		},		.mode_screen		= 0x1ffaff80,		.mode_horztiming	= 0x007d0e57,		.mode_verttiming	= 0x00740a01,		.mode_clkcontrol	= 0x000A0000, /* /1 */		.mode_pwmdiv		= 0x00000000,		.mode_pwmhi		= 0x00000000,		.mode_outmask	= 0x00FFFFFF,		.mode_fifoctrl	= 0x2f2f2f2f,		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?