⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dispc.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * OMAP2 display controller support * * Copyright (C) 2005 Nokia Corporation * Author: Imre Deak <imre.deak@nokia.com> * * 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/kernel.h>#include <linux/dma-mapping.h>#include <linux/mm.h>#include <linux/vmalloc.h>#include <linux/clk.h>#include <linux/io.h>#include <mach/sram.h>#include <mach/omapfb.h>#include <mach/board.h>#include "dispc.h"#define MODULE_NAME			"dispc"#define DSS_BASE			0x48050000#define DSS_SYSCONFIG			0x0010#define DISPC_BASE			0x48050400/* DISPC common */#define DISPC_REVISION			0x0000#define DISPC_SYSCONFIG			0x0010#define DISPC_SYSSTATUS			0x0014#define DISPC_IRQSTATUS			0x0018#define DISPC_IRQENABLE			0x001C#define DISPC_CONTROL			0x0040#define DISPC_CONFIG			0x0044#define DISPC_CAPABLE			0x0048#define DISPC_DEFAULT_COLOR0		0x004C#define DISPC_DEFAULT_COLOR1		0x0050#define DISPC_TRANS_COLOR0		0x0054#define DISPC_TRANS_COLOR1		0x0058#define DISPC_LINE_STATUS		0x005C#define DISPC_LINE_NUMBER		0x0060#define DISPC_TIMING_H			0x0064#define DISPC_TIMING_V			0x0068#define DISPC_POL_FREQ			0x006C#define DISPC_DIVISOR			0x0070#define DISPC_SIZE_DIG			0x0078#define DISPC_SIZE_LCD			0x007C#define DISPC_DATA_CYCLE1		0x01D4#define DISPC_DATA_CYCLE2		0x01D8#define DISPC_DATA_CYCLE3		0x01DC/* DISPC GFX plane */#define DISPC_GFX_BA0			0x0080#define DISPC_GFX_BA1			0x0084#define DISPC_GFX_POSITION		0x0088#define DISPC_GFX_SIZE			0x008C#define DISPC_GFX_ATTRIBUTES		0x00A0#define DISPC_GFX_FIFO_THRESHOLD	0x00A4#define DISPC_GFX_FIFO_SIZE_STATUS	0x00A8#define DISPC_GFX_ROW_INC		0x00AC#define DISPC_GFX_PIXEL_INC		0x00B0#define DISPC_GFX_WINDOW_SKIP		0x00B4#define DISPC_GFX_TABLE_BA		0x00B8/* DISPC Video plane 1/2 */#define DISPC_VID1_BASE			0x00BC#define DISPC_VID2_BASE			0x014C/* Offsets into DISPC_VID1/2_BASE */#define DISPC_VID_BA0			0x0000#define DISPC_VID_BA1			0x0004#define DISPC_VID_POSITION		0x0008#define DISPC_VID_SIZE			0x000C#define DISPC_VID_ATTRIBUTES		0x0010#define DISPC_VID_FIFO_THRESHOLD	0x0014#define DISPC_VID_FIFO_SIZE_STATUS	0x0018#define DISPC_VID_ROW_INC		0x001C#define DISPC_VID_PIXEL_INC		0x0020#define DISPC_VID_FIR			0x0024#define DISPC_VID_PICTURE_SIZE		0x0028#define DISPC_VID_ACCU0			0x002C#define DISPC_VID_ACCU1			0x0030/* 8 elements in 8 byte increments */#define DISPC_VID_FIR_COEF_H0		0x0034/* 8 elements in 8 byte increments */#define DISPC_VID_FIR_COEF_HV0		0x0038/* 5 elements in 4 byte increments */#define DISPC_VID_CONV_COEF0		0x0074#define DISPC_IRQ_FRAMEMASK		0x0001#define DISPC_IRQ_VSYNC			0x0002#define DISPC_IRQ_EVSYNC_EVEN		0x0004#define DISPC_IRQ_EVSYNC_ODD		0x0008#define DISPC_IRQ_ACBIAS_COUNT_STAT	0x0010#define DISPC_IRQ_PROG_LINE_NUM		0x0020#define DISPC_IRQ_GFX_FIFO_UNDERFLOW	0x0040#define DISPC_IRQ_GFX_END_WIN		0x0080#define DISPC_IRQ_PAL_GAMMA_MASK	0x0100#define DISPC_IRQ_OCP_ERR		0x0200#define DISPC_IRQ_VID1_FIFO_UNDERFLOW	0x0400#define DISPC_IRQ_VID1_END_WIN		0x0800#define DISPC_IRQ_VID2_FIFO_UNDERFLOW	0x1000#define DISPC_IRQ_VID2_END_WIN		0x2000#define DISPC_IRQ_SYNC_LOST		0x4000#define DISPC_IRQ_MASK_ALL		0x7fff#define DISPC_IRQ_MASK_ERROR		(DISPC_IRQ_GFX_FIFO_UNDERFLOW |	\					     DISPC_IRQ_VID1_FIFO_UNDERFLOW | \					     DISPC_IRQ_VID2_FIFO_UNDERFLOW | \					     DISPC_IRQ_SYNC_LOST)#define RFBI_CONTROL			0x48050040#define MAX_PALETTE_SIZE		(256 * 16)#define FLD_MASK(pos, len)	(((1 << len) - 1) << pos)#define MOD_REG_FLD(reg, mask, val) \	dispc_write_reg((reg), (dispc_read_reg(reg) & ~(mask)) | (val));#define OMAP2_SRAM_START		0x40200000/* Maximum size, in reality this is smaller if SRAM is partially locked. */#define OMAP2_SRAM_SIZE			0xa0000		/* 640k *//* We support the SDRAM / SRAM types. See OMAPFB_PLANE_MEMTYPE_* in omapfb.h */#define DISPC_MEMTYPE_NUM		2#define RESMAP_SIZE(_page_cnt)						\	((_page_cnt + (sizeof(unsigned long) * 8) - 1) / 8)#define RESMAP_PTR(_res_map, _page_nr)					\	(((_res_map)->map) + (_page_nr) / (sizeof(unsigned long) * 8))#define RESMAP_MASK(_page_nr)						\	(1 << ((_page_nr) & (sizeof(unsigned long) * 8 - 1)))struct resmap {	unsigned long	start;	unsigned	page_cnt;	unsigned long	*map;};static struct {	void __iomem	*base;	struct omapfb_mem_desc	mem_desc;	struct resmap		*res_map[DISPC_MEMTYPE_NUM];	atomic_t		map_count[OMAPFB_PLANE_NUM];	dma_addr_t	palette_paddr;	void		*palette_vaddr;	int		ext_mode;	unsigned long	enabled_irqs;	void		(*irq_callback)(void *);	void		*irq_callback_data;	struct completion	frame_done;	int		fir_hinc[OMAPFB_PLANE_NUM];	int		fir_vinc[OMAPFB_PLANE_NUM];	struct clk	*dss_ick, *dss1_fck;	struct clk	*dss_54m_fck;	enum omapfb_update_mode	update_mode;	struct omapfb_device	*fbdev;	struct omapfb_color_key	color_key;} dispc;static void enable_lcd_clocks(int enable);static void inline dispc_write_reg(int idx, u32 val){	__raw_writel(val, dispc.base + idx);}static u32 inline dispc_read_reg(int idx){	u32 l = __raw_readl(dispc.base + idx);	return l;}/* Select RFBI or bypass mode */static void enable_rfbi_mode(int enable){	u32 l;	l = dispc_read_reg(DISPC_CONTROL);	/* Enable RFBI, GPIO0/1 */	l &= ~((1 << 11) | (1 << 15) | (1 << 16));	l |= enable ? (1 << 11) : 0;	/* RFBI En: GPIO0/1=10  RFBI Dis: GPIO0/1=11 */	l |= 1 << 15;	l |= enable ? 0 : (1 << 16);	dispc_write_reg(DISPC_CONTROL, l);	/* Set bypass mode in RFBI module */	l = __raw_readl(IO_ADDRESS(RFBI_CONTROL));	l |= enable ? 0 : (1 << 1);	__raw_writel(l, IO_ADDRESS(RFBI_CONTROL));}static void set_lcd_data_lines(int data_lines){	u32 l;	int code = 0;	switch (data_lines) {	case 12:		code = 0;		break;	case 16:		code = 1;		break;	case 18:		code = 2;		break;	case 24:		code = 3;		break;	default:		BUG();	}	l = dispc_read_reg(DISPC_CONTROL);	l &= ~(0x03 << 8);	l |= code << 8;	dispc_write_reg(DISPC_CONTROL, l);}static void set_load_mode(int mode){	BUG_ON(mode & ~(DISPC_LOAD_CLUT_ONLY | DISPC_LOAD_FRAME_ONLY |			DISPC_LOAD_CLUT_ONCE_FRAME));	MOD_REG_FLD(DISPC_CONFIG, 0x03 << 1, mode << 1);}void omap_dispc_set_lcd_size(int x, int y){	BUG_ON((x > (1 << 11)) || (y > (1 << 11)));	enable_lcd_clocks(1);	MOD_REG_FLD(DISPC_SIZE_LCD, FLD_MASK(16, 11) | FLD_MASK(0, 11),			((y - 1) << 16) | (x - 1));	enable_lcd_clocks(0);}EXPORT_SYMBOL(omap_dispc_set_lcd_size);void omap_dispc_set_digit_size(int x, int y){	BUG_ON((x > (1 << 11)) || (y > (1 << 11)));	enable_lcd_clocks(1);	MOD_REG_FLD(DISPC_SIZE_DIG, FLD_MASK(16, 11) | FLD_MASK(0, 11),			((y - 1) << 16) | (x - 1));	enable_lcd_clocks(0);}EXPORT_SYMBOL(omap_dispc_set_digit_size);static void setup_plane_fifo(int plane, int ext_mode){	const u32 ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD,				DISPC_VID1_BASE + DISPC_VID_FIFO_THRESHOLD,			        DISPC_VID2_BASE + DISPC_VID_FIFO_THRESHOLD };	const u32 fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS,				DISPC_VID1_BASE + DISPC_VID_FIFO_SIZE_STATUS,				DISPC_VID2_BASE + DISPC_VID_FIFO_SIZE_STATUS };	int low, high;	u32 l;	BUG_ON(plane > 2);	l = dispc_read_reg(fsz_reg[plane]);	l &= FLD_MASK(0, 9);	if (ext_mode) {		low = l * 3 / 4;		high = l;	} else {		low = l / 4;		high = l * 3 / 4;	}	MOD_REG_FLD(ftrs_reg[plane], FLD_MASK(16, 9) | FLD_MASK(0, 9),			(high << 16) | low);}void omap_dispc_enable_lcd_out(int enable){	enable_lcd_clocks(1);	MOD_REG_FLD(DISPC_CONTROL, 1, enable ? 1 : 0);	enable_lcd_clocks(0);}EXPORT_SYMBOL(omap_dispc_enable_lcd_out);void omap_dispc_enable_digit_out(int enable){	enable_lcd_clocks(1);	MOD_REG_FLD(DISPC_CONTROL, 1 << 1, enable ? 1 << 1 : 0);	enable_lcd_clocks(0);}EXPORT_SYMBOL(omap_dispc_enable_digit_out);static inline int _setup_plane(int plane, int channel_out,				  u32 paddr, int screen_width,				  int pos_x, int pos_y, int width, int height,				  int color_mode){	const u32 at_reg[] = { DISPC_GFX_ATTRIBUTES,				DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES,			        DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };	const u32 ba_reg[] = { DISPC_GFX_BA0, DISPC_VID1_BASE + DISPC_VID_BA0,				DISPC_VID2_BASE + DISPC_VID_BA0 };	const u32 ps_reg[] = { DISPC_GFX_POSITION,				DISPC_VID1_BASE + DISPC_VID_POSITION,				DISPC_VID2_BASE + DISPC_VID_POSITION };	const u32 sz_reg[] = { DISPC_GFX_SIZE,				DISPC_VID1_BASE + DISPC_VID_PICTURE_SIZE,				DISPC_VID2_BASE + DISPC_VID_PICTURE_SIZE };	const u32 ri_reg[] = { DISPC_GFX_ROW_INC,				DISPC_VID1_BASE + DISPC_VID_ROW_INC,			        DISPC_VID2_BASE + DISPC_VID_ROW_INC };	const u32 vs_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_SIZE,				DISPC_VID2_BASE + DISPC_VID_SIZE };	int chout_shift, burst_shift;	int chout_val;	int color_code;	int bpp;	int cconv_en;	int set_vsize;	u32 l;#ifdef VERBOSE	dev_dbg(dispc.fbdev->dev, "plane %d channel %d paddr %#08x scr_width %d"		    " pos_x %d pos_y %d width %d height %d color_mode %d\n",		    plane, channel_out, paddr, screen_width, pos_x, pos_y,		    width, height, color_mode);#endif	set_vsize = 0;	switch (plane) {	case OMAPFB_PLANE_GFX:		burst_shift = 6;		chout_shift = 8;		break;	case OMAPFB_PLANE_VID1:	case OMAPFB_PLANE_VID2:		burst_shift = 14;		chout_shift = 16;		set_vsize = 1;		break;	default:		return -EINVAL;	}	switch (channel_out) {	case OMAPFB_CHANNEL_OUT_LCD:		chout_val = 0;		break;	case OMAPFB_CHANNEL_OUT_DIGIT:		chout_val = 1;		break;	default:		return -EINVAL;	}	cconv_en = 0;	switch (color_mode) {	case OMAPFB_COLOR_RGB565:		color_code = DISPC_RGB_16_BPP;		bpp = 16;		break;	case OMAPFB_COLOR_YUV422:		if (plane == 0)			return -EINVAL;		color_code = DISPC_UYVY_422;		cconv_en = 1;		bpp = 16;		break;	case OMAPFB_COLOR_YUY422:		if (plane == 0)			return -EINVAL;		color_code = DISPC_YUV2_422;		cconv_en = 1;		bpp = 16;		break;	default:		return -EINVAL;	}	l = dispc_read_reg(at_reg[plane]);	l &= ~(0x0f << 1);	l |= color_code << 1;	l &= ~(1 << 9);	l |= cconv_en << 9;	l &= ~(0x03 << burst_shift);	l |= DISPC_BURST_8x32 << burst_shift;	l &= ~(1 << chout_shift);	l |= chout_val << chout_shift;	dispc_write_reg(at_reg[plane], l);	dispc_write_reg(ba_reg[plane], paddr);	MOD_REG_FLD(ps_reg[plane],		    FLD_MASK(16, 11) | FLD_MASK(0, 11), (pos_y << 16) | pos_x);	MOD_REG_FLD(sz_reg[plane], FLD_MASK(16, 11) | FLD_MASK(0, 11),			((height - 1) << 16) | (width - 1));	if (set_vsize) {		/* Set video size if set_scale hasn't set it */		if (!dispc.fir_vinc[plane])			MOD_REG_FLD(vs_reg[plane],				FLD_MASK(16, 11), (height - 1) << 16);		if (!dispc.fir_hinc[plane])			MOD_REG_FLD(vs_reg[plane],				FLD_MASK(0, 11), width - 1);	}	dispc_write_reg(ri_reg[plane], (screen_width - width) * bpp / 8 + 1);	return height * screen_width * bpp / 8;}static int omap_dispc_setup_plane(int plane, int channel_out,				  unsigned long offset,				  int screen_width,				  int pos_x, int pos_y, int width, int height,				  int color_mode){	u32 paddr;	int r;	if ((unsigned)plane > dispc.mem_desc.region_cnt)		return -EINVAL;	paddr = dispc.mem_desc.region[plane].paddr + offset;	enable_lcd_clocks(1);	r = _setup_plane(plane, channel_out, paddr,			screen_width,			pos_x, pos_y, width, height, color_mode);	enable_lcd_clocks(0);	return r;}static void write_firh_reg(int plane, int reg, u32 value){	u32 base;	if (plane == 1)		base = DISPC_VID1_BASE + DISPC_VID_FIR_COEF_H0;	else		base = DISPC_VID2_BASE + DISPC_VID_FIR_COEF_H0;	dispc_write_reg(base + reg * 8,	value);}static void write_firhv_reg(int plane, int reg, u32 value){	u32 base;	if (plane == 1)		base = DISPC_VID1_BASE + DISPC_VID_FIR_COEF_HV0;	else		base = DISPC_VID2_BASE + DISPC_VID_FIR_COEF_HV0;	dispc_write_reg(base + reg * 8,	value);}static void set_upsampling_coef_table(int plane){	const u32 coef[][2] = {		{ 0x00800000, 0x00800000 },		{ 0x0D7CF800, 0x037B02FF },		{ 0x1E70F5FF, 0x0C6F05FE },		{ 0x335FF5FE, 0x205907FB },		{ 0xF74949F7, 0x00404000 },		{ 0xF55F33FB, 0x075920FE },		{ 0xF5701EFE, 0x056F0CFF },		{ 0xF87C0DFF, 0x027B0300 },	};	int i;	for (i = 0; i < 8; i++) {		write_firh_reg(plane, i, coef[i][0]);		write_firhv_reg(plane, i, coef[i][1]);	}}static int omap_dispc_set_scale(int plane,

⌨️ 快捷键说明

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