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

📄 pvx522.c

📁 PVX522 视频转换器的Linux驱动程序
💻 C
字号:
/* *  VGA drivers for pvx522.c *   2007.4.1  set qvcp  	outl(0x01380016, PCI_BASE | 0x10e008);	//0x139=313; 0x016=22; *    must set this,or VGA cann't work well! */    #include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/init.h>#include <linux/device.h>#include <linux/errno.h>#include <linux/fs.h>#include <asm/io.h>#include <linux/types.h>#include <linux/miscdevice.h>#include <asm/uaccess.h>#include <linux/i2c.h>#include <linux/moduleparam.h>#include <linux/string.h>#include "pvx522.h"#define I2C_NAME(s) (s)->name#define MODULE_NAME                           "PVX522  DRIVER"#define VER_NO                                1.1#define DEBUG                                 1 #define PCI_BASE                  0x1be00000#define PAL_FRAME_BUFFER_HEIGHT     576#define NTSC_FRAME_BUFFER_HEIGHT    480#define FRAME_BUFFER_WIDTH          720  static char *mode_option = "pal";		//please use this to set default modemodule_param(mode_option,charp,0);static char *output_format = "SVGA";		//please use this to set default modemodule_param(output_format,charp,0);static struct i2c_client *pvx522_client;#define   DEVNAME                             "pvx522"#define   pvx522_addr   		      0x2e#define   I2C_DRIVERID_PVX522                 0x01int j = 0;static int debug = 8;#define dprintk(num, format, args...) \	do { \		if (debug >= num) \			printk(format, ##args); \	} while (0)/* ----------------------------------------------------------------------- */struct pvx522 {	unsigned char reg[256];	int mode;            };static inline int pvx522_read (struct i2c_client *client,unsigned char  reg);static inline int pvx522_write (struct i2c_client *client, unsigned char  reg, unsigned char  value);static int pvx522_ioctl( struct inode  *inode, struct file   *file, unsigned int   cmd,   unsigned long  arg);/* ----------------------------------------------------------------------- */static struct file_operations   pvx522_fops    =   {    .owner          =   THIS_MODULE,    .read           =   NULL,//pvx522_read,    .write          =   NULL,//pvx522_write,    .open           =   NULL,    .release        =   NULL,    .ioctl          =   pvx522_ioctl,};static struct miscdevice pvx522_MiscDev = {     .minor =   MISC_DYNAMIC_MINOR,     .name  =   DEVNAME,     .fops  =   &pvx522_fops};static inline void set_qvcp(int pal){ 	/*  set qvcp output  */	if(pal) 	{	  //outl(0x035f0137, PCI_BASE | 0x10e000);	//0x35f=863; 0x137=311; 0x270=625;	  //outl(0x02d0035f, PCI_BASE | 0x10e004);	//0x2d0=720;	  outl(0x01380015, PCI_BASE | 0x10e008);	//0x139=313; 0x016=22;	  //outl(0x02ff0350, PCI_BASE | 0x10e00c);	//0x2dd=733; 0x350=848;	  //outl(0x0001000b, PCI_BASE | 0x10e010);	//0x001= 01; 0x00b=11;	  //outl(0x00af0136, PCI_BASE | 0x10e014);	//0x0af=175; 0x137=311;	}	else	{		  //outl(0x03590105, PCI_BASE | 0x10e000);	//0x35f=863; 0x137=311; 0x270=625;	  //outl(0x02d00359, PCI_BASE | 0x10e004);	//0x2d0=720;	  outl(0x01060011, PCI_BASE | 0x10e008);	//0x139=313; 0x016=22;	  //outl(0x02dd034a, PCI_BASE | 0x10e00c);	//0x2dd=733; 0x350=848;	  //outl(0x0004000b, PCI_BASE | 0x10e010);	//0x001= 01; 0x00b=11;	  //outl(0x00950105, PCI_BASE | 0x10e014);		   	}	}static inline intpvx522_read (struct i2c_client *client,unsigned char  reg){  	return i2c_smbus_read_byte_data(client,reg);}static inline intpvx522_write (struct i2c_client *client,	       unsigned char                  reg,	       unsigned char                  value){   	struct pvx522 *encoder = i2c_get_clientdata(client);	dprintk(1, KERN_DEBUG "PVX522: %02x set to %02x\n", reg, value);	encoder->reg[reg] = value;	return i2c_smbus_write_byte_data(client, reg, value);}static inline int			 /* not suport write addr increase ,must write one by one */pvx522_write_block (struct i2c_client *client,             u8                    reg,             const u8          *value,             unsigned int       len){    int ret = -1;    while(len)    {        if ((ret = pvx522_write(client,reg,*value)) < 0)        {            dprintk(1, KERN_DEBUG "pvx522 write err!\n");            break;        }        reg++;        value++;        len--;    }    return ret;}/* ----------------------------------------------------------------------- */static int pvx522_ioctl( struct inode  *inode, struct file   *file,                              unsigned int   cmd,   unsigned long  arg){	unsigned char reg;	unsigned char value;	unsigned long setting;	//int i,j;      unsigned int *iarg = (unsigned int *)arg;//------------------------------------------------------------------------------------	struct pvx522 *encoder = i2c_get_clientdata(pvx522_client);	        //printk("in : %x,%x,%x\n",iarg[1],iarg[2],iarg[3]);	switch (cmd) {         case GET_REG_VAL:                value = pvx522_read(pvx522_client,iarg[0]);              put_user(value,(unsigned char *)arg);	      break;         case SET_REG_VAL:              get_user(setting,(unsigned long *)arg);              reg = (setting>>8)&0xff;               value = setting&0xff;              pvx522_write(pvx522_client,reg,value);              break;	 case SET_OUTPUT_FORMAT:	       {		unsigned long iarg ;		if( get_user(iarg, (unsigned long *)arg) == 0){	 	 switch (iarg) {		 	  	case VIDEO_MODE_VGA_PAL:			      pvx522_write_block (pvx522_client, 0,VGA60_PAL,sizeof(VGA60_PAL));			      printk(KERN_INFO"pvx522 set input mode : PAL,output mode is VGA60_PAL\n");						   			      break;			 case VIDEO_MODE_VGA_NTSC:			      pvx522_write_block (pvx522_client, 0,VGA60_NTSC,sizeof(VGA60_NTSC));			      printk(KERN_INFO"pvx522 set input mode : NTSC,output mode is VGA60_NTSC\n");					      break;			      						 case VIDEO_MODE_SVGA_PAL:			      pvx522_write_block (pvx522_client, 0,SVGA60_PAL,sizeof(SVGA60_PAL));			      printk(KERN_INFO"pvx522 set input mode : PAL,output mode is SVGA60_PAL\n");						   			      break;			 case VIDEO_MODE_SVGA_NTSC:			      pvx522_write_block (pvx522_client, 0,SVGA60_NTSC,sizeof(SVGA60_NTSC));			      printk(KERN_INFO"pvx522 set input mode : NTSC,output mode is SVGA60_NTSC\n");					      break;				 			 case VIDEO_MODE_XGA_PAL:			      pvx522_write_block (pvx522_client, 0,XGA60_PAL,sizeof(XGA60_PAL));			      printk(KERN_INFO"pvx522 set input mode : PAL,output mode is XGA60_PAL\n");			      break;			 case VIDEO_MODE_XGA_NTSC:			      pvx522_write_block (pvx522_client, 0,XGA60_NTSC,sizeof(XGA60_NTSC));			      printk(KERN_INFO"pvx522 set input mode : NTSC,output mode is XGA60_NTSC\n");		 			      break;				 			 case VIDEO_MODE_SXGA_PAL:			      pvx522_write_block (pvx522_client, 0,SXGA60_PAL,sizeof(SXGA60_PAL));			      printk(KERN_INFO"pvx522 set input mode : PAL,output mode is SXGA60_PAL\n"); 			      break;			 case VIDEO_MODE_SXGA_NTSC:			      pvx522_write_block (pvx522_client, 0,SXGA60_NTSC,sizeof(SXGA60_NTSC));			      printk(KERN_INFO"pvx522 set input mode : NTSC,output mode is SXGA60_NTSC\n");				      break;			default:				return -EINVAL;			 }		  }		encoder->mode = iarg;	       }		break;	default:		return -EINVAL;    	}	return 0;} /* ----------------------------------------------------------------------- *//* * Generic i2c probe * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' */static unsigned short normal_i2c[] = { pvx522_addr>>1,I2C_CLIENT_END };static unsigned short normal_i2c_range[] = { I2C_CLIENT_END  ,I2C_CLIENT_END };static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };static unsigned short probe_range[2] = { I2C_CLIENT_END , I2C_CLIENT_END };static unsigned short ignore[2] = { I2C_CLIENT_END , I2C_CLIENT_END  };static unsigned short ignore_range[2] = { I2C_CLIENT_END , I2C_CLIENT_END  };static unsigned short force[2] = {I2C_CLIENT_END  ,I2C_CLIENT_END };static struct i2c_client_address_data addr_data = {	.normal_i2c		= normal_i2c,	.normal_i2c_range	= normal_i2c_range,	.probe			= probe,	.probe_range		= probe_range,	.ignore			= ignore,	.ignore_range		= ignore_range,	.force			= force};static int pvx522_i2c_id = 0;static struct i2c_driver i2c_driver_pvx522;static intpvx522_detect_client (struct i2c_adapter *adapter,		       int                 address,		       int                 kind){	int i = 0;		//struct i2c_client *client;	struct pvx522 *encoder;	dprintk(1,		KERN_INFO		"pvx522.c: detecting pvx522 client on address 0x%x\n",		address << 1);	/* Check if the adapter supports the needed features */	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))		return 0;	pvx522_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);	if (pvx522_client == 0)		return -ENOMEM;	memset(pvx522_client, 0, sizeof(struct i2c_client));	pvx522_client->addr = address;	pvx522_client->adapter = adapter;	pvx522_client->driver = &i2c_driver_pvx522;	pvx522_client->flags = I2C_CLIENT_ALLOW_USE;	pvx522_client->id = pvx522_i2c_id++;	snprintf(I2C_NAME(pvx522_client), sizeof(I2C_NAME(pvx522_client)) - 1,		"pvx522[%d]", pvx522_client->id);	encoder = kmalloc(sizeof(struct pvx522), GFP_KERNEL);	if (encoder == NULL) {		kfree(pvx522_client);		return -ENOMEM;	}	memset(encoder, 0, sizeof(struct pvx522));	encoder->mode = VIDEO_MODE_VGA_PAL;	i2c_set_clientdata(pvx522_client, encoder);	i = i2c_attach_client(pvx522_client);	if (i) {		kfree(pvx522_client);		kfree(encoder);		return i;	} 	/* 	 	 	for(i=0;i<0xff;i++) 	{ 	 	if(i!=0) 	{if(i%16==0) 	 printk("  //0x%02x \n",i-16); 	 } 	printk("0x%02x, ",pvx522_read(pvx522_client,i)); 	 }*/ 	 	if(strcmp(mode_option,"pal")==0) 	{ 	  set_qvcp(1);	    if(strcmp(output_format,"SVGA")==0)	     {	      i = pvx522_write_block (pvx522_client, 0,SVGA60_PAL,sizeof(SVGA60_PAL));	      }	    if(strcmp(output_format,"XGA")==0)	    {	      i = pvx522_write_block (pvx522_client, 0,XGA60_PAL,sizeof(XGA60_PAL));	      }	    if(strcmp(output_format,"SXGA")==0)	      i = pvx522_write_block (pvx522_client, 0,SXGA60_PAL,sizeof(SXGA60_PAL));	    printk("output format is : pal %s\n",output_format); 	} 	else 	{ 	  set_qvcp(0);	    if(strcmp(output_format,"SVGA")==0)	      i = pvx522_write_block (pvx522_client, 0,SVGA60_NTSC,sizeof(SVGA60_NTSC));	    if(strcmp(output_format,"XGA")==0)	      i = pvx522_write_block (pvx522_client, 0,XGA60_NTSC,sizeof(XGA60_NTSC));	    if(strcmp(output_format,"SXGA")==0)	      i = pvx522_write_block (pvx522_client, 0,SXGA60_NTSC,sizeof(SXGA60_NTSC));		    printk("output format is : ntsc %s\n",output_format); 	} 	 	pvx522_write(pvx522_client,0x44,0x08);		if (i < 0) {		dprintk(1, KERN_ERR "%s_attach: init error %d\n",			I2C_NAME(pvx522_client), i);	}         else {		dprintk(1,			KERN_INFO			"%s_attach: chip version %d at address 0x%x\n",			I2C_NAME(pvx522_client), pvx522_read(pvx522_client,0) >> 5,			pvx522_client->addr << 1);	}    /* Register a misc device called "pvx522". */        i = misc_register( &pvx522_MiscDev );      if (i < 0)    {        dprintk(1, KERN_INFO "can't register misc device (minor %d)!\n", pvx522_MiscDev.minor );        return i;    }      else       dprintk(1, KERN_INFO "Register misc device (minor %d)!\n", pvx522_MiscDev.minor );    return 0;}static intpvx522_attach_adapter (struct i2c_adapter *adapter){	dprintk(1,		KERN_INFO		"pvx522.c: starting probe for adapter %s (0x%x)\n",		I2C_NAME(adapter), adapter->id);	return i2c_probe(adapter, &addr_data, &pvx522_detect_client);}static intpvx522_detach_client (struct i2c_client *client){	struct pvx522 *encoder = i2c_get_clientdata(client);	int err;	err = i2c_detach_client(client);	if (err) {		return err;	}	kfree(encoder);	kfree(client);	return 0;}/* ----------------------------------------------------------------------- */static struct i2c_driver i2c_driver_pvx522 = {	.owner = THIS_MODULE,	.name = "pvx522",	.id = I2C_DRIVERID_PVX522,	.flags = I2C_DF_NOTIFY,	.attach_adapter = pvx522_attach_adapter,	.detach_client = pvx522_detach_client,};static int __initpvx522_init (void){    //	out_ctrl_value = inl(QVCP5L_ONSH_CTRL);//	printk("QVCP 5L onsh control register(0x10e070) value= 0x%X\n",out_ctrl_value);//	out_ctrl_value = inl(QVCP5L_OUT_CTRL);//	printk("Old QVCP 5L control register(0x10e03C) value= 0x%X\n",out_ctrl_value);	//	out_ctrl_value &= QVCP5L_OUT_CTRL_MSK;//	out_ctrl_value |= QVCP5L_OUT_CTRL_SET;//	printk("New QVCP 5L control register value= 0x%X\n",out_ctrl_value);//	outl(out_ctrl_value,QVCP5L_OUT_CTRL);	return i2c_add_driver(&i2c_driver_pvx522);}static void __exitpvx522_exit (void){    if (misc_deregister(&pvx522_MiscDev)!=0)    {        dprintk(1, KERN_INFO "pvx522: could not misc_deregister the device\n");    }    printk("exit module pvx522!\n");	i2c_del_driver(&i2c_driver_pvx522);}module_init(pvx522_init);module_exit(pvx522_exit);MODULE_DESCRIPTION("Powerview PVX522 Video for VGA");MODULE_AUTHOR("Wang Dy");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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