📄 pvx522.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 + -