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

📄 blizzard.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Epson Blizzard LCD controller driver * * Copyright (C) 2004-2005 Nokia Corporation * Authors:     Juha Yrjola   <juha.yrjola@nokia.com> *	        Imre Deak     <imre.deak@nokia.com> * YUV support: Jussi Laako   <jussi.laako@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/module.h>#include <linux/mm.h>#include <linux/fb.h>#include <linux/delay.h>#include <linux/clk.h>#include <mach/dma.h>#include <mach/omapfb.h>#include <mach/blizzard.h>#include "dispc.h"#define MODULE_NAME				"blizzard"#define BLIZZARD_REV_CODE			0x00#define BLIZZARD_CONFIG				0x02#define BLIZZARD_PLL_DIV			0x04#define BLIZZARD_PLL_LOCK_RANGE			0x06#define BLIZZARD_PLL_CLOCK_SYNTH_0		0x08#define BLIZZARD_PLL_CLOCK_SYNTH_1		0x0a#define BLIZZARD_PLL_MODE			0x0c#define BLIZZARD_CLK_SRC			0x0e#define BLIZZARD_MEM_BANK0_ACTIVATE		0x10#define BLIZZARD_MEM_BANK0_STATUS		0x14#define BLIZZARD_HDISP				0x2a#define BLIZZARD_HNDP				0x2c#define BLIZZARD_VDISP0				0x2e#define BLIZZARD_VDISP1				0x30#define BLIZZARD_VNDP				0x32#define BLIZZARD_HSW				0x34#define BLIZZARD_VSW				0x38#define BLIZZARD_DISPLAY_MODE			0x68#define BLIZZARD_INPUT_WIN_X_START_0		0x6c#define BLIZZARD_DATA_SOURCE_SELECT		0x8e#define BLIZZARD_DISP_MEM_DATA_PORT		0x90#define BLIZZARD_DISP_MEM_READ_ADDR0		0x92#define BLIZZARD_POWER_SAVE			0xE6#define BLIZZARD_NDISP_CTRL_STATUS		0xE8/* Data source select *//* For S1D13745 */#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND	0x00#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE	0x01#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE	0x04#define BLIZZARD_SRC_DISABLE_OVERLAY		0x05/* For S1D13744 */#define BLIZZARD_SRC_WRITE_LCD			0x00#define BLIZZARD_SRC_BLT_LCD			0x06#define BLIZZARD_COLOR_RGB565			0x01#define BLIZZARD_COLOR_YUV420			0x09#define BLIZZARD_VERSION_S1D13745		0x01	/* Hailstorm */#define BLIZZARD_VERSION_S1D13744		0x02	/* Blizzard */#define BLIZZARD_AUTO_UPDATE_TIME		(HZ / 20)/* Reserve 4 request slots for requests in irq context */#define REQ_POOL_SIZE			24#define IRQ_REQ_POOL_SIZE		4#define REQ_FROM_IRQ_POOL 0x01#define REQ_COMPLETE	0#define REQ_PENDING	1struct blizzard_reg_list {	int	start;	int	end;};/* These need to be saved / restored separately from the rest. */static struct blizzard_reg_list blizzard_pll_regs[] = {	{		.start	= 0x04,		/* Don't save PLL ctrl (0x0C) */		.end	= 0x0a,	},	{		.start	= 0x0e,		/* Clock configuration */		.end	= 0x0e,	},};static struct blizzard_reg_list blizzard_gen_regs[] = {	{		.start	= 0x18,		/* SDRAM control */		.end	= 0x20,	},	{		.start	= 0x28,		/* LCD Panel configuration */		.end	= 0x5a,		/* HSSI interface, TV configuration */	},};static u8 blizzard_reg_cache[0x5a / 2];struct update_param {	int	plane;	int	x, y, width, height;	int	out_x, out_y;	int	out_width, out_height;	int	color_mode;	int	bpp;	int	flags;};struct blizzard_request {	struct list_head entry;	unsigned int	 flags;	int		 (*handler)(struct blizzard_request *req);	void		 (*complete)(void *data);	void		 *complete_data;	union {		struct update_param	update;		struct completion	*sync;	} par;};struct plane_info {	unsigned long offset;	int pos_x, pos_y;	int width, height;	int out_width, out_height;	int scr_width;	int color_mode;	int bpp;};struct blizzard_struct {	enum omapfb_update_mode	update_mode;	enum omapfb_update_mode	update_mode_before_suspend;	struct timer_list	auto_update_timer;	int			stop_auto_update;	struct omapfb_update_window	auto_update_window;	int			enabled_planes;	int			vid_nonstd_color;	int			vid_scaled;	int			last_color_mode;	int			zoom_on;	int			screen_width;	int			screen_height;	unsigned		te_connected:1;	unsigned		vsync_only:1;	struct plane_info	plane[OMAPFB_PLANE_NUM];	struct blizzard_request	req_pool[REQ_POOL_SIZE];	struct list_head	pending_req_list;	struct list_head	free_req_list;	struct semaphore	req_sema;	spinlock_t		req_lock;	unsigned long		sys_ck_rate;	struct extif_timings	reg_timings, lut_timings;	u32			max_transmit_size;	u32			extif_clk_period;	int			extif_clk_div;	unsigned long		pix_tx_time;	unsigned long		line_upd_time;	struct omapfb_device	*fbdev;	struct lcd_ctrl_extif	*extif;	struct lcd_ctrl		*int_ctrl;	void			(*power_up)(struct device *dev);	void			(*power_down)(struct device *dev);	int			version;} blizzard;struct lcd_ctrl blizzard_ctrl;static u8 blizzard_read_reg(u8 reg){	u8 data;	blizzard.extif->set_bits_per_cycle(8);	blizzard.extif->write_command(&reg, 1);	blizzard.extif->read_data(&data, 1);	return data;}static void blizzard_write_reg(u8 reg, u8 val){	blizzard.extif->set_bits_per_cycle(8);	blizzard.extif->write_command(&reg, 1);	blizzard.extif->write_data(&val, 1);}static void blizzard_restart_sdram(void){	unsigned long tmo;	blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 0);	udelay(50);	blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 1);	tmo = jiffies + msecs_to_jiffies(200);	while (!(blizzard_read_reg(BLIZZARD_MEM_BANK0_STATUS) & 0x01)) {		if (time_after(jiffies, tmo)) {			dev_err(blizzard.fbdev->dev,					"s1d1374x: SDRAM not ready\n");			break;		}		msleep(1);	}}static void blizzard_stop_sdram(void){	blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 0);}/* Wait until the last window was completely written into the controllers * SDRAM and we can start transferring the next window. */static void blizzard_wait_line_buffer(void){	unsigned long tmo = jiffies + msecs_to_jiffies(30);	while (blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS) & (1 << 7)) {		if (time_after(jiffies, tmo)) {			if (printk_ratelimit())				dev_err(blizzard.fbdev->dev,					"s1d1374x: line buffer not ready\n");			break;		}	}}/* Wait until the YYC color space converter is idle. */static void blizzard_wait_yyc(void){	unsigned long tmo = jiffies + msecs_to_jiffies(30);	while (blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS) & (1 << 4)) {		if (time_after(jiffies, tmo)) {			if (printk_ratelimit())				dev_err(blizzard.fbdev->dev,					"s1d1374x: YYC not ready\n");			break;		}	}}static void disable_overlay(void){	blizzard_write_reg(BLIZZARD_DATA_SOURCE_SELECT,				BLIZZARD_SRC_DISABLE_OVERLAY);}static void set_window_regs(int x_start, int y_start, int x_end, int y_end,			    int x_out_start, int y_out_start,			    int x_out_end, int y_out_end, int color_mode,			    int zoom_off, int flags){	u8 tmp[18];	u8 cmd;	x_end--;	y_end--;	tmp[0] = x_start;	tmp[1] = x_start >> 8;	tmp[2] = y_start;	tmp[3] = y_start >> 8;	tmp[4] = x_end;	tmp[5] = x_end >> 8;	tmp[6] = y_end;	tmp[7] = y_end >> 8;	x_out_end--;	y_out_end--;	tmp[8]  = x_out_start;	tmp[9]  = x_out_start >> 8;	tmp[10] = y_out_start;	tmp[11] = y_out_start >> 8;	tmp[12] = x_out_end;	tmp[13] = x_out_end >> 8;	tmp[14] = y_out_end;	tmp[15] = y_out_end >> 8;	tmp[16] = color_mode;	if (zoom_off && blizzard.version == BLIZZARD_VERSION_S1D13745)		tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND;	else if (flags & OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY)		tmp[17] = BLIZZARD_SRC_WRITE_OVERLAY_ENABLE;	else		tmp[17] = blizzard.version == BLIZZARD_VERSION_S1D13744 ?				BLIZZARD_SRC_WRITE_LCD :				BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;	blizzard.extif->set_bits_per_cycle(8);	cmd = BLIZZARD_INPUT_WIN_X_START_0;	blizzard.extif->write_command(&cmd, 1);	blizzard.extif->write_data(tmp, 18);}static void enable_tearsync(int y, int width, int height, int screen_height,			    int out_height, int force_vsync){	u8 b;	b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);	b |= 1 << 3;	blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b);	if (likely(blizzard.vsync_only || force_vsync)) {		blizzard.extif->enable_tearsync(1, 0);		return;	}	if (width * blizzard.pix_tx_time < blizzard.line_upd_time) {		blizzard.extif->enable_tearsync(1, 0);		return;	}	if ((width * blizzard.pix_tx_time / 1000) * height <	    (y + out_height) * (blizzard.line_upd_time / 1000)) {		blizzard.extif->enable_tearsync(1, 0);		return;	}	blizzard.extif->enable_tearsync(1, y + 1);}static void disable_tearsync(void){	u8 b;	blizzard.extif->enable_tearsync(0, 0);	b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);	b &= ~(1 << 3);	blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b);	b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);}static inline void set_extif_timings(const struct extif_timings *t);static inline struct blizzard_request *alloc_req(void){	unsigned long flags;	struct blizzard_request *req;	int req_flags = 0;	if (!in_interrupt())		down(&blizzard.req_sema);	else		req_flags = REQ_FROM_IRQ_POOL;	spin_lock_irqsave(&blizzard.req_lock, flags);	BUG_ON(list_empty(&blizzard.free_req_list));	req = list_entry(blizzard.free_req_list.next,			 struct blizzard_request, entry);	list_del(&req->entry);	spin_unlock_irqrestore(&blizzard.req_lock, flags);	INIT_LIST_HEAD(&req->entry);	req->flags = req_flags;	return req;}static inline void free_req(struct blizzard_request *req){	unsigned long flags;	spin_lock_irqsave(&blizzard.req_lock, flags);	list_del(&req->entry);	list_add(&req->entry, &blizzard.free_req_list);	if (!(req->flags & REQ_FROM_IRQ_POOL))		up(&blizzard.req_sema);	spin_unlock_irqrestore(&blizzard.req_lock, flags);}static void process_pending_requests(void){	unsigned long flags;	spin_lock_irqsave(&blizzard.req_lock, flags);	while (!list_empty(&blizzard.pending_req_list)) {		struct blizzard_request *req;		void (*complete)(void *);		void *complete_data;		req = list_entry(blizzard.pending_req_list.next,				 struct blizzard_request, entry);		spin_unlock_irqrestore(&blizzard.req_lock, flags);		if (req->handler(req) == REQ_PENDING)			return;		complete = req->complete;		complete_data = req->complete_data;		free_req(req);		if (complete)			complete(complete_data);		spin_lock_irqsave(&blizzard.req_lock, flags);	}	spin_unlock_irqrestore(&blizzard.req_lock, flags);}static void submit_req_list(struct list_head *head){	unsigned long flags;	int process = 1;	spin_lock_irqsave(&blizzard.req_lock, flags);	if (likely(!list_empty(&blizzard.pending_req_list)))		process = 0;	list_splice_init(head, blizzard.pending_req_list.prev);	spin_unlock_irqrestore(&blizzard.req_lock, flags);	if (process)		process_pending_requests();}static void request_complete(void *data){	struct blizzard_request	*req = (struct blizzard_request *)data;	void			(*complete)(void *);	void			*complete_data;	complete = req->complete;	complete_data = req->complete_data;	free_req(req);	if (complete)		complete(complete_data);	process_pending_requests();}static int do_full_screen_update(struct blizzard_request *req){	int i;	int flags;	for (i = 0; i < 3; i++) {		struct plane_info *p = &blizzard.plane[i];		if (!(blizzard.enabled_planes & (1 << i))) {			blizzard.int_ctrl->enable_plane(i, 0);			continue;		}		dev_dbg(blizzard.fbdev->dev, "pw %d ph %d\n",			p->width, p->height);		blizzard.int_ctrl->setup_plane(i,				OMAPFB_CHANNEL_OUT_LCD, p->offset,				p->scr_width, p->pos_x, p->pos_y,				p->width, p->height,				p->color_mode);		blizzard.int_ctrl->enable_plane(i, 1);	}	dev_dbg(blizzard.fbdev->dev, "sw %d sh %d\n",		blizzard.screen_width, blizzard.screen_height);	blizzard_wait_line_buffer();	flags = req->par.update.flags;	if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC)		enable_tearsync(0, blizzard.screen_width,				blizzard.screen_height,				blizzard.screen_height,				blizzard.screen_height,				flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC);	else		disable_tearsync();	set_window_regs(0, 0, blizzard.screen_width, blizzard.screen_height,			0, 0, blizzard.screen_width, blizzard.screen_height,			BLIZZARD_COLOR_RGB565, blizzard.zoom_on, flags);	blizzard.zoom_on = 0;	blizzard.extif->set_bits_per_cycle(16);	/* set_window_regs has left the register index at the right	 * place, so no need to set it here.	 */	blizzard.extif->transfer_area(blizzard.screen_width,				      blizzard.screen_height,				      request_complete, req);	return REQ_PENDING;}/* Setup all planes with an overlapping area with the update window. */static int do_partial_update(struct blizzard_request *req, int plane,			     int x, int y, int w, int h,			     int x_out, int y_out, int w_out, int h_out,			     int wnd_color_mode, int bpp){	int i;	int gx1, gy1, gx2, gy2;

⌨️ 快捷键说明

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