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

📄 sdum.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * drivers/video/pnx4008/sdum.c * * Display Update Master support * * Authors: Grigory Tolstolytkin <gtolstolytkin@ru.mvista.com> *          Vitaly Wool <vitalywool@gmail.com> * Based on Philips Semiconductors's code * * Copyrght (c) 2005-2006 MontaVista Software, Inc. * Copyright (c) 2005 Philips Semiconductors * 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>#include <linux/vmalloc.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/platform_device.h>#include <linux/fb.h>#include <linux/init.h>#include <linux/dma-mapping.h>#include <linux/clk.h>#include <asm/uaccess.h>#include <mach/gpio.h>#include "sdum.h"#include "fbcommon.h"#include "dum.h"/* Framebuffers we have */static struct pnx4008_fb_addr {	int fb_type;	long addr_offset;	long fb_length;} fb_addr[] = {	[0] = {		FB_TYPE_YUV, 0, 0xB0000	},	[1] = {		FB_TYPE_RGB, 0xB0000, 0x50000	},};static struct dum_data {	u32 lcd_phys_start;	u32 lcd_virt_start;	u32 slave_phys_base;	u32 *slave_virt_base;	int fb_owning_channel[MAX_DUM_CHANNELS];	struct dumchannel_uf chan_uf_store[MAX_DUM_CHANNELS];} dum_data;/* Different local helper functions */static u32 nof_pixels_dx(struct dum_ch_setup *ch_setup){	return (ch_setup->xmax - ch_setup->xmin + 1);}static u32 nof_pixels_dy(struct dum_ch_setup *ch_setup){	return (ch_setup->ymax - ch_setup->ymin + 1);}static u32 nof_pixels_dxy(struct dum_ch_setup *ch_setup){	return (nof_pixels_dx(ch_setup) * nof_pixels_dy(ch_setup));}static u32 nof_bytes(struct dum_ch_setup *ch_setup){	u32 r = nof_pixels_dxy(ch_setup);	switch (ch_setup->format) {	case RGB888:	case RGB666:		r *= 4;		break;	default:		r *= 2;		break;	}	return r;}static u32 build_command(int disp_no, u32 reg, u32 val){	return ((disp_no << 26) | BIT(25) | (val << 16) | (disp_no << 10) |		(reg << 0));}static u32 build_double_index(int disp_no, u32 val){	return ((disp_no << 26) | (val << 16) | (disp_no << 10) | (val << 0));}static void build_disp_window(struct dum_ch_setup * ch_setup, struct disp_window * dw){	dw->ymin = ch_setup->ymin;	dw->ymax = ch_setup->ymax;	dw->xmin_l = ch_setup->xmin & 0xFF;	dw->xmin_h = (ch_setup->xmin & BIT(8)) >> 8;	dw->xmax_l = ch_setup->xmax & 0xFF;	dw->xmax_h = (ch_setup->xmax & BIT(8)) >> 8;}static int put_channel(struct dumchannel chan){	int i = chan.channelnr;	if (i < 0 || i > MAX_DUM_CHANNELS)		return -EINVAL;	else {		DUM_CH_MIN(i) = chan.dum_ch_min;		DUM_CH_MAX(i) = chan.dum_ch_max;		DUM_CH_CONF(i) = chan.dum_ch_conf;		DUM_CH_CTRL(i) = chan.dum_ch_ctrl;	}	return 0;}static void clear_channel(int channr){	struct dumchannel chan;	chan.channelnr = channr;	chan.dum_ch_min = 0;	chan.dum_ch_max = 0;	chan.dum_ch_conf = 0;	chan.dum_ch_ctrl = 0;	put_channel(chan);}static int put_cmd_string(struct cmdstring cmds){	u16 *cmd_str_virtaddr;	u32 *cmd_ptr0_virtaddr;	u32 cmd_str_physaddr;	int i = cmds.channelnr;	if (i < 0 || i > MAX_DUM_CHANNELS)		return -EINVAL;	else if ((cmd_ptr0_virtaddr =		  (int *)ioremap_nocache(DUM_COM_BASE,					 sizeof(int) * MAX_DUM_CHANNELS)) ==		 NULL)		return -EIOREMAPFAILED;	else {		cmd_str_physaddr = ioread32(&cmd_ptr0_virtaddr[cmds.channelnr]);		if ((cmd_str_virtaddr =		     (u16 *) ioremap_nocache(cmd_str_physaddr,					     sizeof(cmds))) == NULL) {			iounmap(cmd_ptr0_virtaddr);			return -EIOREMAPFAILED;		} else {			int t;			for (t = 0; t < 8; t++)				iowrite16(*((u16 *)&cmds.prestringlen + t),					  cmd_str_virtaddr + t);			for (t = 0; t < cmds.prestringlen / 2; t++)				 iowrite16(*((u16 *)&cmds.precmd + t),					   cmd_str_virtaddr + t + 8);			for (t = 0; t < cmds.poststringlen / 2; t++)				iowrite16(*((u16 *)&cmds.postcmd + t),					  cmd_str_virtaddr + t + 8 +					  	cmds.prestringlen / 2);			iounmap(cmd_ptr0_virtaddr);			iounmap(cmd_str_virtaddr);		}	}	return 0;}static u32 dum_ch_setup(int ch_no, struct dum_ch_setup * ch_setup){	struct cmdstring cmds_c;	struct cmdstring *cmds = &cmds_c;	struct disp_window dw;	int standard;	u32 orientation = 0;	struct dumchannel chan = { 0 };	int ret;	if ((ch_setup->xmirror) || (ch_setup->ymirror) || (ch_setup->rotate)) {		standard = 0;		orientation = BIT(1);	/* always set 9-bit-bus */		if (ch_setup->xmirror)			orientation |= BIT(4);		if (ch_setup->ymirror)			orientation |= BIT(3);		if (ch_setup->rotate)			orientation |= BIT(0);	} else		standard = 1;	cmds->channelnr = ch_no;	/* build command string header */	if (standard) {		cmds->prestringlen = 32;		cmds->poststringlen = 0;	} else {		cmds->prestringlen = 48;		cmds->poststringlen = 16;	}	cmds->format =	    (u16) ((ch_setup->disp_no << 4) | (BIT(3)) | (ch_setup->format));	cmds->reserved = 0x0;	cmds->startaddr_low = (ch_setup->minadr & 0xFFFF);	cmds->startaddr_high = (ch_setup->minadr >> 16);	if ((ch_setup->minadr == 0) && (ch_setup->maxadr == 0)	    && (ch_setup->xmin == 0)	    && (ch_setup->ymin == 0) && (ch_setup->xmax == 0)	    && (ch_setup->ymax == 0)) {		cmds->pixdatlen_low = 0;		cmds->pixdatlen_high = 0;	} else {		u32 nbytes = nof_bytes(ch_setup);		cmds->pixdatlen_low = (nbytes & 0xFFFF);		cmds->pixdatlen_high = (nbytes >> 16);	}	if (ch_setup->slave_trans)		cmds->pixdatlen_high |= BIT(15);	/* build pre-string */	build_disp_window(ch_setup, &dw);	if (standard) {		cmds->precmd[0] =		    build_command(ch_setup->disp_no, DISP_XMIN_L_REG, 0x99);		cmds->precmd[1] =		    build_command(ch_setup->disp_no, DISP_XMIN_L_REG,				  dw.xmin_l);		cmds->precmd[2] =		    build_command(ch_setup->disp_no, DISP_XMIN_H_REG,				  dw.xmin_h);		cmds->precmd[3] =		    build_command(ch_setup->disp_no, DISP_YMIN_REG, dw.ymin);		cmds->precmd[4] =		    build_command(ch_setup->disp_no, DISP_XMAX_L_REG,				  dw.xmax_l);		cmds->precmd[5] =		    build_command(ch_setup->disp_no, DISP_XMAX_H_REG,				  dw.xmax_h);		cmds->precmd[6] =		    build_command(ch_setup->disp_no, DISP_YMAX_REG, dw.ymax);		cmds->precmd[7] =		    build_double_index(ch_setup->disp_no, DISP_PIXEL_REG);	} else {		if (dw.xmin_l == ch_no)			cmds->precmd[0] =			    build_command(ch_setup->disp_no, DISP_XMIN_L_REG,					  0x99);		else			cmds->precmd[0] =			    build_command(ch_setup->disp_no, DISP_XMIN_L_REG,					  ch_no);		cmds->precmd[1] =		    build_command(ch_setup->disp_no, DISP_XMIN_L_REG,				  dw.xmin_l);		cmds->precmd[2] =		    build_command(ch_setup->disp_no, DISP_XMIN_H_REG,				  dw.xmin_h);		cmds->precmd[3] =		    build_command(ch_setup->disp_no, DISP_YMIN_REG, dw.ymin);		cmds->precmd[4] =		    build_command(ch_setup->disp_no, DISP_XMAX_L_REG,				  dw.xmax_l);		cmds->precmd[5] =		    build_command(ch_setup->disp_no, DISP_XMAX_H_REG,				  dw.xmax_h);		cmds->precmd[6] =		    build_command(ch_setup->disp_no, DISP_YMAX_REG, dw.ymax);		cmds->precmd[7] =		    build_command(ch_setup->disp_no, DISP_1_REG, orientation);		cmds->precmd[8] =		    build_double_index(ch_setup->disp_no, DISP_PIXEL_REG);		cmds->precmd[9] =		    build_double_index(ch_setup->disp_no, DISP_PIXEL_REG);		cmds->precmd[0xA] =		    build_double_index(ch_setup->disp_no, DISP_PIXEL_REG);		cmds->precmd[0xB] =		    build_double_index(ch_setup->disp_no, DISP_PIXEL_REG);		cmds->postcmd[0] =		    build_command(ch_setup->disp_no, DISP_1_REG, BIT(1));		cmds->postcmd[1] =		    build_command(ch_setup->disp_no, DISP_DUMMY1_REG, 1);		cmds->postcmd[2] =		    build_command(ch_setup->disp_no, DISP_DUMMY1_REG, 2);		cmds->postcmd[3] =		    build_command(ch_setup->disp_no, DISP_DUMMY1_REG, 3);	}	if ((ret = put_cmd_string(cmds_c)) != 0) {		return ret;	}	chan.channelnr = cmds->channelnr;	chan.dum_ch_min = ch_setup->dirtybuffer + ch_setup->minadr;	chan.dum_ch_max = ch_setup->dirtybuffer + ch_setup->maxadr;	chan.dum_ch_conf = 0x002;	chan.dum_ch_ctrl = 0x04;	put_channel(chan);	return 0;}static u32 display_open(int ch_no, int auto_update, u32 * dirty_buffer,			u32 * frame_buffer, u32 xpos, u32 ypos, u32 w, u32 h){	struct dum_ch_setup k;	int ret;	/* keep width & height within display area */	if ((xpos + w) > DISP_MAX_X_SIZE)		w = DISP_MAX_X_SIZE - xpos;	if ((ypos + h) > DISP_MAX_Y_SIZE)		h = DISP_MAX_Y_SIZE - ypos;	/* assume 1 display only */	k.disp_no = 0;	k.xmin = xpos;	k.ymin = ypos;	k.xmax = xpos + (w - 1);	k.ymax = ypos + (h - 1);	/* adjust min and max values if necessary */	if (k.xmin > DISP_MAX_X_SIZE - 1)		k.xmin = DISP_MAX_X_SIZE - 1;	if (k.ymin > DISP_MAX_Y_SIZE - 1)		k.ymin = DISP_MAX_Y_SIZE - 1;	if (k.xmax > DISP_MAX_X_SIZE - 1)		k.xmax = DISP_MAX_X_SIZE - 1;	if (k.ymax > DISP_MAX_Y_SIZE - 1)		k.ymax = DISP_MAX_Y_SIZE - 1;	k.xmirror = 0;	k.ymirror = 0;	k.rotate = 0;	k.minadr = (u32) frame_buffer;	k.maxadr = (u32) frame_buffer + (((w - 1) << 10) | ((h << 2) - 2));	k.pad = PAD_1024;	k.dirtybuffer = (u32) dirty_buffer;	k.format = RGB888;	k.hwdirty = 0;	k.slave_trans = 0;	ret = dum_ch_setup(ch_no, &k);	return ret;}static void lcd_reset(void){	u32 *dum_pio_base = (u32 *)IO_ADDRESS(PNX4008_PIO_BASE);	udelay(1);	iowrite32(BIT(19), &dum_pio_base[2]);	udelay(1);	iowrite32(BIT(19), &dum_pio_base[1]);	udelay(1);}static int dum_init(struct platform_device *pdev){	struct clk *clk;	/* enable DUM clock */	clk = clk_get(&pdev->dev, "dum_ck");	if (IS_ERR(clk)) {		printk(KERN_ERR "pnx4008_dum: Unable to access DUM clock\n");		return PTR_ERR(clk);	}	clk_set_rate(clk, 1);	clk_put(clk);	DUM_CTRL = V_DUM_RESET;	/* set priority to "round-robin". All other params to "false" */	DUM_CONF = BIT(9);	/* Display 1 */	DUM_WTCFG1 = PNX4008_DUM_WT_CFG;	DUM_RTCFG1 = PNX4008_DUM_RT_CFG;	DUM_TCFG = PNX4008_DUM_T_CFG;	return 0;}static void dum_chan_init(void){	int i = 0, ch = 0;	u32 *cmdptrs;	u32 *cmdstrings;	DUM_COM_BASE =		CMDSTRING_BASEADDR + BYTES_PER_CMDSTRING * NR_OF_CMDSTRINGS;	if ((cmdptrs =	     (u32 *) ioremap_nocache(DUM_COM_BASE,				     sizeof(u32) * NR_OF_CMDSTRINGS)) == NULL)		return;	for (ch = 0; ch < NR_OF_CMDSTRINGS; ch++)		iowrite32(CMDSTRING_BASEADDR + BYTES_PER_CMDSTRING * ch,			  cmdptrs + ch);	for (ch = 0; ch < MAX_DUM_CHANNELS; ch++)		clear_channel(ch);

⌨️ 快捷键说明

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