📄 tw2815.c
字号:
/**************************************************************************** ENI2C Client & Driver ****************************************************************************/static struct i2c_driver i2c_driver_tw2815;static int tw2815_detect_client(struct i2c_adapter *adapter, int address, int kind){ struct i2c_client *client; struct tw2815 *decoder; int rv; printk("tw2815.c: detecting tw2815 client on address 0x%x\n", address<<1); if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return 0; client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); if (client == 0) return -ENOMEM; client->addr = address; client->adapter = adapter; client->driver = &i2c_driver_tw2815; strlcpy(I2C_NAME(client), tw2815_name, sizeof(I2C_NAME(client))); decoder = kzalloc(sizeof(struct tw2815), GFP_KERNEL); if (decoder == NULL) { kfree(client); return -ENOMEM; } decoder->norm = VIDEO_MODE_PAL; decoder->enable = 1; decoder->bright = 128; decoder->contrast = 128; decoder->hue = 128; decoder->sat = 128; i2c_set_clientdata(client, decoder); tw2815_default_vedio_write(client,TELECAST_PAL_MODE); rv = i2c_attach_client(client); if (rv) { kfree(client); kfree(decoder); return rv; } return 0;}static int tw2815_attach_adapter(struct i2c_adapter *adapter){ return i2c_probe(adapter, &addr_data, &tw2815_detect_client);}static int tw2815_detach_client(struct i2c_client *client){ struct tw2815 *decoder = i2c_get_clientdata(client); int err; err = i2c_detach_client(client); if (err) return err; kfree(decoder); kfree(client); return 0;}static struct i2c_driver i2c_driver_tw2815= { .driver = { .name = "tw2815", }, .id = I2C_DRIVERID_TW2815, .attach_adapter = tw2815_attach_adapter, .detach_client = tw2815_detach_client, .command = tw2815_command,};/* for appl*/static ssize_t tw2815_read (struct file *file, char __user *buf, size_t count, loff_t *offset){ char *tmp; int ret; struct i2c_client *client = (struct i2c_client *)file->private_data; if (count > 8192) count = 8192; tmp = kmalloc(count,GFP_KERNEL); if (tmp==NULL) return -ENOMEM; ret = i2c_master_recv(client,tmp,count); if (ret >= 0) ret = copy_to_user(buf,tmp,count)?-EFAULT:ret; kfree(tmp); return ret;}static ssize_t tw2815_write (struct file *file, const char __user *buf, size_t count,loff_t *offset){ int ret; char *tmp; struct i2c_client *client = (struct i2c_client *)file->private_data; if (count > 8192) count = 8192; tmp = kmalloc(count,GFP_KERNEL); if (tmp==NULL) return -ENOMEM; if (copy_from_user(tmp,buf,count)) { kfree(tmp); return -EFAULT; } ret = i2c_master_send(client,tmp,count); kfree(tmp); return ret;}static int tw2815_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg){ struct i2c_client *client = (struct i2c_client *)file->private_data; if(cmd>10) return -1; switch ( cmd ) { case GET_TW2815_REG_VALUE: { char *tmp; char start_addr,length; int ret; tmp = kmalloc(2,GFP_KERNEL); if (tmp==NULL) return -ENOMEM; if (copy_from_user(tmp,(char _user *)arg,2)) { kfree(tmp); return -EFAULT; } start_addr = *tmp++; length = *tmp; kfree(tmp); tmp = kmalloc(length,GFP_KERNEL); if (tmp==NULL) return -ENOMEM; tw2815_block_read(client,start_addr,tmp,length); ret = copy_to_user((char _user *)arg,tmp,length)?-EFAULT:ret; kfree(tmp); } break; case SET_TW2815_REG_VALUE: { char *tmp; char start_addr,value; int ret; tmp = kmalloc(2,GFP_KERNEL); if (tmp==NULL) return -ENOMEM; if (copy_from_user(tmp,(char _user *)arg,2)) { kfree(tmp); return -EFAULT; } start_addr = *tmp++; value = *tmp; kfree(tmp); tw2815_single_write(client,start_addr,value); } break; case TW2815_DEFAULT_CONFIG_PAL: tw2815_mPAL_vedio_write(client); break; case TW2815_DEFAULT_CONFIG_NTSC: tw2815_mNTSC_vedio_write(client); break; case TW2815_HUE_CONFIG: { char value,ch_num; char *tmp; tmp = kmalloc(2,GFP_KERNEL); if (tmp==NULL) return -ENOMEM; if (copy_from_user(tmp,(char _user *)arg,2)) { kfree(tmp); return -EFAULT; } value = *tmp++; ch_num = *tmp; kfree(tmp); switch(ch_num) { case ALL_CH: tw2815_single_write(client,CH1_HUE_REG,value); tw2815_single_write(client,CH2_HUE_REG,value); tw2815_single_write(client,CH3_HUE_REG,value); tw2815_single_write(client,CH4_HUE_REG,value); break; case CH_NUM1: tw2815_single_write(client,CH1_HUE_REG,value); break; case CH_NUM2: tw2815_single_write(client,CH2_HUE_REG,value); break; case CH_NUM3: tw2815_single_write(client,CH3_HUE_REG,value); break; case CH_NUM4: tw2815_single_write(client,CH4_HUE_REG,value); break; } } break; case TW2815_SAT_CONFIG: { char value,ch_num; char *tmp; tmp = kmalloc(2,GFP_KERNEL); if (tmp==NULL) return -ENOMEM; if (copy_from_user(tmp,(char _user *)arg,2)) { kfree(tmp); return -EFAULT; } value = *tmp++; ch_num = *tmp; kfree(tmp); switch(ch_num) { case ALL_CH: tw2815_single_write(client,CH1_SAT_REG,value); tw2815_single_write(client,CH2_SAT_REG,value); tw2815_single_write(client,CH3_SAT_REG,value); tw2815_single_write(client,CH4_SAT_REG,value); break; case CH_NUM1: tw2815_single_write(client,CH1_SAT_REG,value); break; case CH_NUM2: tw2815_single_write(client,CH2_SAT_REG,value); break; case CH_NUM3: tw2815_single_write(client,CH3_SAT_REG,value); break; case CH_NUM4: tw2815_single_write(client,CH4_SAT_REG,value); break; } } break; case TW2815_CONT_CONFIG: { char value,ch_num; char *tmp; tmp = kmalloc(2,GFP_KERNEL); if (tmp==NULL) return -ENOMEM; if (copy_from_user(tmp,(char _user *)arg,2)) { kfree(tmp); return -EFAULT; } value = *tmp++; ch_num = *tmp; kfree(tmp); switch(ch_num) { case ALL_CH: tw2815_single_write(client,CH1_CONT_REG,value); tw2815_single_write(client,CH2_CONT_REG,value); tw2815_single_write(client,CH3_CONT_REG,value); tw2815_single_write(client,CH4_CONT_REG,value); break; case CH_NUM1: tw2815_single_write(client,CH1_CONT_REG,value); break; case CH_NUM2: tw2815_single_write(client,CH2_CONT_REG,value); break; case CH_NUM3: tw2815_single_write(client,CH3_CONT_REG,value); break; case CH_NUM4: tw2815_single_write(client,CH4_CONT_REG,value); break; } } break; case TW2815_BRT_CONFIG: { char value,ch_num; char *tmp; tmp = kmalloc(2,GFP_KERNEL); if (tmp==NULL) return -ENOMEM; if (copy_from_user(tmp,(char _user *)arg,2)) { kfree(tmp); return -EFAULT; } value = *tmp++; ch_num = *tmp; kfree(tmp); switch(ch_num) { case ALL_CH: tw2815_single_write(client,CH1_BRT_REG,value); tw2815_single_write(client,CH2_BRT_REG,value); tw2815_single_write(client,CH3_BRT_REG,value); tw2815_single_write(client,CH4_BRT_REG,value); break; case CH_NUM1: tw2815_single_write(client,CH1_BRT_REG,value); break; case CH_NUM2: tw2815_single_write(client,CH2_BRT_REG,value); break; case CH_NUM3: tw2815_single_write(client,CH3_BRT_REG,value); break; case CH_NUM4: tw2815_single_write(client,CH4_BRT_REG,value); break; } } break; case TW2815_UGAIN_CONFIG: char value; __get_user(value, (char __user *)arg); tw2815_single_write(client,VGAIN_REG,value); break; case TW2815_VGAIN_CONFIG: char value; __get_user(value, (char __user *)arg); tw2815_single_write(client,VGAIN_REG,value); break; } return 0;}static int tw2815_open(struct inode *inode, struct file *file){ unsigned int minor = iminor(inode); struct i2c_client *client; struct i2c_adapter *adap; struct i2c_dev *i2c_dev; i2c_dev = i2c_dev_get_by_minor(minor); if (!i2c_dev) return -ENODEV; adap = i2c_get_adapter(i2c_dev->adap->nr); if (!adap) return -ENODEV; client = kzalloc(sizeof(*client), GFP_KERNEL); if (!client) { i2c_put_adapter(adap); return -ENOMEM; } snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr); client->driver = &i2c_driver_tw2815; /* registered with adapter, passed as client to user */ client->adapter = adap; file->private_data = client; return 0;}static int tw2815_release(struct inode *inode, struct file *file){ struct i2c_client *client = file->private_data; i2c_put_adapter(client->adapter); kfree(client); file->private_data = NULL; return 0;}static struct file_operations i2c_tw2815_fops ={ .owner = THIS_MODULE, .llseek = NULL, .read = tw2815_read, .write = tw2815_write, .ioctl = tw2815_ioctl, .release = tw2815_release, .open = tw2815_open,};static struct class *i2c_tw2815_class;static int __init tw2815_init(void){ int res; printk(KERN_INFO "i2c /dev entries driver\n"); res = register_chrdev(I2C_MAJOR, "tw2815", &i2c_tw2815_fops); if (res) goto out; i2c_tw2815_class = class_create(THIS_MODULE, "tw2815-dev"); if (IS_ERR(i2c_tw2815_class)) goto out_unreg_chrdev; res = i2c_add_driver(&i2c_driver_tw2815); if (res) goto out_unreg_class; return 0;out_unreg_class: class_destroy(i2c_tw2815_class);out_unreg_chrdev: unregister_chrdev(I2C_MAJOR, "tw2815");out: printk(KERN_ERR "%s: TW2815 Driver Initialisation failed\n", __FILE__); return res;}static void __exit tw2815_exit(void){ i2c_del_driver(&i2c_driver_tw2815); class_destroy(i2c_tw2815_class); unregister_chrdev(I2C_MAJOR,"tw2815");}module_init(tw2815_init);module_exit(t2815_exit);MODULE_DESCRIPTION("Analog Devices TW2815 video encoder driver");MODULE_AUTHOR("Agui<Agui@163.com>");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -