#include "adv7180_hyc.h"
#define DEVICE_NAME "matt_test"
#define I2C_adv7180a 0x40
static int init_adv7180a(void);
static struct i2c_board_info hi_info =
{
I2C_BOARD_INFO("adv7180", 0x40),
};
static struct i2c_client* tlv_client;
static int MAJOR_DEV_NUM =1;
int adv7180_write(unsigned char chip_addr, unsigned char reg_addr, unsigned char value)
{
int ret;
unsigned char buf[2];
struct i2c_client* client = tlv_client;
buf[0] = reg_addr;
buf[1] = value;
ret = i2c_master_send(client, buf, 2);
return ret;
}
int adv7180_read(unsigned char chip_addr, char reg_addr)
{
int ret;
char *tmp=NULL;
tmp=®_addr;
struct i2c_client* client = tlv_client;
ret = i2c_master_recv(client, tmp, 1);
printk("matt-ret1=%d,val=%x\n",ret,*tmp);
return ret;
}
void adv7180_Reset(void)
{
writel(0x00000000, IO_ADDRESS(0x200f00f4));
writel(0x00000008, IO_ADDRESS(0x201f0400));
writel(0x00000000, IO_ADDRESS(0x201f0020));
msleep(10);
writel(0x000000FF, IO_ADDRESS(0x201f0020));
}
static int init_adv7180a(void)
{
unsigned char regvalue1;
regvalue1 = adv7180_read(0x40,0x01);
printk("read adv7180 register is %x\n",regvalue1);
adv7180_write(0x40,0x08, regvalue1);
regvalue1 = adv7180_read(0x40,0x11);
/* Set adv7180 cvbs input mode */
adv7180_write(0x40, 0x00, 0x00);
adv7180_write(0x40, 0xf3, 0x07);//change
adv7180_write(0x40, 0xf4, 0x19);//
adv7180_write(0x40, 0x04, 0xd7);//
adv7180_write(0x40, 0x07, 0x7f);//
adv7180_write(0x40, 0x17, 0x41);
adv7180_write(0x40, 0x31, 0x02);
adv7180_write(0x40, 0x3d, 0xa2);
adv7180_write(0x40, 0x3e, 0x6a);
adv7180_write(0x40, 0x3f, 0xa0);
adv7180_write(0x40, 0x1d, 0x00);
//adv7180_write(0x40, 0x0e, 0x80);//
adv7180_write(0x40, 0x55, 0x00);//
adv7180_write(0x40, 0x0e, 0x00);
/* for bright, contrast, hue, etc... */
adv7180_write(0x40, 0x0a, 0xff);
adv7180_write(0x40, 0x0b, 0x00);
adv7180_write(0x40, 0x08, 0x7f);//
adv7180_write(0x40, 0xe3, 0x7f);//
adv7180_write(0x40, 0xe4, 0x7f);//
adv7180_write(0x40, 0xfb, 0x40);//
adv7180_write(0x40, 0x3d, 0xa2);//
return 0;
}
static int adv7180a_device_init(void)
{
if(init_adv7180a() == 0)
return 0;
else
return -1;
}
static int newchar_open(struct inode *inode, struct file *filep)
{
printk( "======== matt_open ");
return 0;
}
static int newchar_release(struct inode *inode, struct file *filep)
{
printk( "======== matt_release \n");
return 0;
}
ssize_t newchar_write (struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{
printk( "======== matt_write\n ");
return 0;
}
static long newchar_ioctl(struct file *filep,
unsigned long cmd, unsigned long arg)
{
long val= 0;
int ret=0;
unsigned norm_flag;
unsigned status=0;
void __user *argp = (void __user *)arg;
if (copy_from_user(&val, argp, sizeof(val)))
{
printk("\tADV7180_ERROR: WRONG cpy val is %lu\n",val);
return -EFAULT;
}
switch(cmd)
{
/*set the value of contrast*/
case ADV7180_REINIT:
{
if( 0 == init_adv7180a() ) return 0;
else return -EFAULT;
}
case ADV7180_GET_MODE:
{
status = adv7180_read(I2C_adv7180a,0x10);
status = status & 0x70;
if (status == 0x40) norm_flag = VIDEO_NORM_PAL;
else norm_flag = VIDEO_NORM_NTSC;
ret = copy_to_user((int *)arg, &norm_flag,
sizeof(norm_flag)) ? -EFAULT : 0;
}
break;
case ADV7180_GET_LOCK:
{
status = adv7180_read(I2C_adv7180a,0x10);
norm_flag = status & 1;
ret = copy_to_user((int *)arg, &norm_flag,
sizeof(norm_flag)) ? -EFAULT : 0;
}
break;
case ADV7180_SET_CONTRAST:
{
int chn;
unsigned char cont;
chn = (unsigned char)(val & 0xff);
cont = (unsigned char)((val & 0xff00) >> 8);
if(chn != 0)
return -EINVAL;
adv7180_write(I2C_adv7180a, 0x08,cont);
return 0;
}
/*set the value of hue*/
case ADV7180_SET_HUE:
{
int chn;
unsigned char hue;
printk("matt-ADV7180_SET_HUE\n");
chn = (unsigned char)(val & 0xff);
hue = (unsigned char)((val & 0xff00) >> 8);
if(chn != 0)
return -EINVAL;
adv7180_write(I2C_adv7180a,0x0b,hue);
return 0;
}
case ADV7180_SET_SAT:
{
int chn;
unsigned char sat;
chn = (unsigned char)(val & 0xff);
sat = (unsigned char)((val & 0xff00) >> 8);
if(chn != 0)
return -EINVAL;
adv7180_write(I2C_adv7180a,0xe3,sat);
adv7180_write(I2C_adv7180a,0xe4,sat);
return 0;
}
case ADV7180_SET_REG:
{
int reg,value;
reg = (unsigned char)((val & 0xff00) >> 8);
value = (unsigned char)(val & 0xff);
printk("set reg 0x%02x to value:0x%02x\n",reg,value);
adv7180_write(I2C_adv7180a, reg,value);
return 0;
}
default:
printk("Unrecongnised command.\n");
ret = -EINVAL;
break;
}
return ret;
}
static const struct file_operations newchar_fops = {
.owner = THIS_MODULE,
.write = newchar_write,
.unlocked_ioctl = newchar_ioctl,
.open = newchar_open,
.release = newchar_release,
};
static dev_t first; // Global variable for the first device number
static struct cdev c_dev; // Global variable for the character device structure
static struct class *cl; // Global variable for the device class
static int __init first_drv_init(void)
{
struct i2c_adapter* i2c_adap=NULL;
printk("matt-adv7180_init+1\n");
if ((cl = class_create(THIS_MODULE, DEVICE_NAME)) == NULL) //这样的module被加载时,udev daemon就会自动在/dev下创建my_device设备文件。
{
printk("matt erro1");
return 1;
}
if (alloc_chrdev_region(&first, 0, 1, DEVICE_NAME) < 0)//可以动态分配设备编号
{
printk("matt erro2");
class_destroy(cl);
return 1;
}
if (device_create(cl, NULL, first, NULL, DEVICE_NAME) == NULL)//创建一个设备并注册到内核驱动架构...
{
printk("matt erro3");
unregister_chrdev_region(first, 1);
class_destroy(cl);
return 1;
}
cdev_init(&c_dev, &newchar_fops);//初始化 cdev 后,需要把它添加到系统中去。为此可以调用 cdev_add() 函数。
if (cdev_add(&c_dev, first, 1) == -1)
{
printk("matt erro4");
device_destroy(cl, first);
unregister_chrdev_region(first, 1);
class_destroy(cl);
return 1;
}
adv7180_Reset();
i2c_adap = i2c_get_adapter(2);
tlv_client = i2c_new_device(i2c_adap, &hi_info);
i2c_put_adapter(i2c_adap);
if(adv7180a_device_init()<0)
{
i2c_unregister_device(tlv_client);
printk("adv7180a driver init fail for device init error!\n");
return -1;
}
printk( "======== matt finish \n");
return 0; //
}
void first_drv_exit(void)
{
printk( "End cdevdemo");
device_destroy(cl, first);
cdev_del(&c_dev);
unregister_chrdev_region(first, 1);
class_destroy(cl);
i2c_unregister_device(tlv_client);
printk("rmmod adv7180.ko for Hi3516A ok!\n");
}
MODULE_LICENSE("Dual BSD/GPL");
module_param(MAJOR_DEV_NUM, int, S_IRUGO);
module_init(first_drv_init);
module_exit(first_drv_exit);