📄 tw2834.c
字号:
tw2834_set_xpath_position_table(tw2834_client, 3,16,3);
//slaver1:
tw2834_client->addr = slaver1_addr >> 1;
tw2834_set_xpath_position_table(tw2834_client, 0,16,4);
tw2834_set_xpath_position_table(tw2834_client, 1,16,5);
tw2834_set_xpath_position_table(tw2834_client, 2,16,6);
tw2834_set_xpath_position_table(tw2834_client, 3,16,7);
//slaver2:
tw2834_client->addr = slaver2_addr >> 1;
tw2834_set_xpath_position_table(tw2834_client, 0,16,8);
tw2834_set_xpath_position_table(tw2834_client, 1,16,9);
tw2834_set_xpath_position_table(tw2834_client, 2,16,10);
tw2834_set_xpath_position_table(tw2834_client, 3,16,11);
}
static inline void tw2834_four_chip(void)
{
//slaver3:
tw2834_client->addr = slaver3_addr >> 1;
//set_standard(tw2834_client); //
tw2834_set_xpath_position_table(tw2834_client, 0,16,12);
tw2834_set_xpath_position_table(tw2834_client, 1,16,13);
tw2834_set_xpath_position_table(tw2834_client, 2,16,14);
tw2834_set_xpath_position_table(tw2834_client, 3,16,15);
}
static inline void set_standard(struct i2c_client * client)
{
struct tw2834 *decoder;
decoder = i2c_get_clientdata(client);
if (decoder->norm == PAL_STD)
tw2834_set_standard(client, PAL_STD);
else
tw2834_set_standard(client, NTSC_STD);
}
//******************************************************************************
static inline void tw2834_all_channel_disable(struct i2c_client * client)
{
int i;
for(i=0; i<4; i++)
tw2834_write(client, 1, 0x10+i*8, 0x10+i);
}
static char get_video_status(struct i2c_client * client)
{
unsigned char readtemp;
unsigned char readdata;
readtemp = tw2834_read(client,1,0x7b); //irq flag bits
readdata = tw2834_read(client,1,0x7b); //irq flag bits
if( (readtemp&0xf0)!= (readdata&0xf0) )
{
readtemp= tw2834_read(client,1,0x7b); //irq flag bits
readdata = tw2834_read(client,1,0x7b); //irq flag bits
readdata = (readdata|readtemp); /* because sometimes video status hopping from signal to nosignale; */
}
//printk("readdata from 1x7b = 0x%02x\n",readdata); //the first four bits :1==no signal,0==signal
return ((~readdata)&0xf0)>>4; /*1==signal; 0==no signal
bit0 ==channel 0;bit1 == channel 1; bit2 == channel 2; bit3 ==channel 3;copy to user */
}
static int tw2834_command ( struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct tw2834 *decoder;
unsigned int buf[4];
unsigned int *iarg =(unsigned int *)arg;
unsigned int num,i,j;
struct tw2834_dev *dev;
copy_from_user(buf,(unsigned int *)arg,16);
if(down_interruptible(&tw2834_ioctl_sem)) /* Notice: copying date from user must place before down_interruptible; */
return -ERESTARTSYS;
dev = container_of(inode->i_cdev,struct tw2834_dev,cdev);
file->private_data =dev;
tw2834_client->addr = dev->addr;
num = MINOR(inode->i_rdev);
//dprintk(1, KERN_DEBUG "This is chip[%d] addr is:(0x%02x)\n",num,tw2834_client->addr << 1);
/**********************************************************************************
date: 2006.12.11
founction: for four chips tw2834; is :0,1,2,3
arg[0] is channel (0,1,2,3);
***********************************************************************************/
decoder = i2c_get_clientdata(tw2834_client);
//dprintk(1, KERN_DEBUG "addr is 0x%02x\n",tw2834_client->addr<<1);
switch(cmd)
{
case GET_STANDARD:
*iarg = decoder->norm;
put_user( *iarg,(unsigned int *)arg);
break;
case GET_CHIP_NUMBER:
*iarg = chip_number;
put_user( *iarg,(unsigned int *)arg);
break;
case GET_VIDEO_SIGNAL:
*iarg = get_video_status(tw2834_client);
put_user( *iarg,(unsigned char *)arg);
break;
case NTSC_STD:
if(decoder->norm != NTSC_STD)
{
decoder->norm =NTSC_STD;
dprintk(1,"NTSC\n");
tw2834_chip_config();
}else
dprintk(1,"Already is NTSC,so not changed!\n");
break;
case PAL_STD:
if(decoder->norm != PAL_STD)
{
decoder->norm =PAL_STD;
dprintk(1,"PAL\n");
tw2834_chip_config();
}else
dprintk(1,"Already is PAL,not changed!\n");
break;
case SET_BRIGHTNESS:
tw2834_set_brightness(tw2834_client,buf[0],buf[1]); /* device_no and val */
break;
case SET_CONTRAST: /* device_no==channel,iarg[0]>4,is all;iarg[1] is val */
tw2834_set_contrast(tw2834_client,buf[0],buf[1]); /* device_no and val */
break;
case SET_HUE:
tw2834_set_hue(tw2834_client,buf[0],buf[1]); /* device_no and val */
break;
case SET_SATURATION:
tw2834_set_saturation(tw2834_client,buf[0],buf[1]); /* device_no and val */
break;
case SET_REGISTER: /*test only*/
tw2834_set_register(tw2834_client, buf[0],buf[1],buf[2]); /*device_no,val,REG_addr*/
break;
case SET_PREVIEW:
tw2834_write(tw2834_client, 1, 0x10+buf[0]*8, 0x80+buf[0]); /* CH_EN:enable ch_no*/
//dprintk(1, KERN_DEBUG "Preview the channel CH%d\n",iarg[2]+4*num);/*please call SET_PREVIEW */
break;
case SET_CLOSE_PREVIEW:
tw2834_write(tw2834_client, 1, 0x10+buf[0]*8, 0x00+buf[0]); /* disable */
break;
case SET_FULLSCREEN: /* iarg[2] is channel(0,1,2,3) nummber*/
//tw2834_set_xpath_fullscreen(tw2834_client, iarg[0]);/*only for one channel*/
tw2834_set_xpath_position_table (tw2834_client, buf[0],1,0);
//printk(KERN_INFO "Set fullscreen the channel CH%d\n",iarg[0]+4*num);
break;
case SET_DEFAULT:
tw2834_default_split();
break;
case SET_SPLIT:
tw2834_set_xpath_position_table (tw2834_client, buf[0], buf[1],buf[2]);
break;
case SET_REG:
tw2834_write(tw2834_client, buf[0], buf[1], buf[2]);
printk("Set reg[%dx%02x]=0x%x\n",buf[0],buf[1],buf[2]);
break;
case GET_REG:
printk("read from %dx%x =0x%x\n",buf[0],buf[1],tw2834_read(tw2834_client, buf[0], buf[1]));
if(buf[1] == 0 )
{
for (i=0; i<32; i++){
for (j=0; j<8; j++) {
dprintk(1,
"[%dx%02x]=0x%02x ",buf[0],i*8+j, tw2834_read(tw2834_client,buf[0],i*8+j)
);
}
dprintk(1,"\n");
}
}
break;
case SET_ALL_CHANNEL_DISABLE:
tw2834_all_channel_disable(tw2834_client); /* please disable all channels before split */
break;
default:
up(&tw2834_ioctl_sem);
return -EINVAL;
}
//out:
up(&tw2834_ioctl_sem);
return 0;
}
/* ----------------------------------------------------------------------- */
/*
* Generic i2c probe
* concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
*/
static unsigned short normal_i2c[] =
{ master0_addr >> 1, slaver1_addr >> 1,slaver2_addr>>1,slaver3_addr>>1,I2C_CLIENT_END };
static unsigned short normal_i2c_range[] = { 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 tw2834_i2c_id = 0;
static struct i2c_driver i2c_driver_tw2834;
static int
tw2834_detect_client (struct i2c_adapter *adapter,
int address,
int kind)
{
int err;
struct tw2834 *decoder;
dprintk(1,
KERN_INFO
"tw2834.c: detecting tw2834 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;
tw2834_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (tw2834_client == 0)
return -ENOMEM;
memset(tw2834_client, 0, sizeof(struct i2c_client));
tw2834_client->addr = address;
tw2834_client->adapter = adapter;
tw2834_client->driver = &i2c_driver_tw2834;
tw2834_client->flags = I2C_CLIENT_ALLOW_USE;
tw2834_client->id = tw2834_i2c_id++;
snprintf(I2C_NAME(tw2834_client), sizeof(I2C_NAME(tw2834_client)) - 1,
"tw2834[%d]", tw2834_client->id);
decoder = kmalloc(sizeof(struct tw2834), GFP_KERNEL);
if (decoder == NULL)
{
kfree(tw2834_client);
return -ENOMEM;
}
/* Init tw2834 to mode_option standard */
if(strcmp(mode_option,"pal")==0)
{
//printk("Input format is : pal\n");
decoder->norm = PAL_STD;
i2c_set_clientdata(tw2834_client, decoder);
tw2834_set_standard(tw2834_client,PAL_STD);
}
else
{
//printk("Input format is : ntsc\n");
decoder->norm = NTSC_STD;
i2c_set_clientdata(tw2834_client, decoder);
tw2834_set_standard(tw2834_client,NTSC_STD);
}
err = i2c_attach_client(tw2834_client);
if (err)
{
kfree(tw2834_client);
kfree(decoder);
return err;
}
chip_number +=1;
return 0;
}
static int
tw2834_attach_adapter (struct i2c_adapter *adapter)
{
dprintk(1,
KERN_INFO
"tw2834: starting probe for adapter %s (0x%x)\n",
I2C_NAME(adapter), adapter->id);
return i2c_probe(adapter, &addr_data, &tw2834_detect_client);
}
static int
tw2834_detach_client (struct i2c_client *client)
{
struct tw2834 *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_tw2834 = {
.owner = THIS_MODULE,
.name = "tw2834",
.id = I2C_DRIVERID_EXP0,
.flags = I2C_DF_NOTIFY,
.attach_adapter = tw2834_attach_adapter,
.detach_client = tw2834_detach_client,
};
int tw2834_trim(struct tw2834_dev *dev)
{
memset(dev->data, 0, TW2834_DATA_SIZE);
dev->size = 0;
return 0;
}
void tw2834_cleanup_module(void)
{
int i;
dev_t devno = MKDEV(tw2834_major, tw2834_minor);
/* Get rid of our char dev entries */
if (tw2834_devices) {
for (i = 0; i < chip_number+1; i++) {
tw2834_trim(tw2834_devices + i);
cdev_del(&tw2834_devices[i].cdev);
class_simple_device_remove(MKDEV(tw2834_major, i));
}
kfree(tw2834_devices);
}
class_simple_destroy(tw2834_class);
/* cleanup_module is never called if registering failed */
unregister_chrdev_region(devno, tw2834_nr_devs);
i2c_del_driver(&i2c_driver_tw2834);
}
static void tw2834_setup_cdev(struct tw2834_dev *dev, int index)
{
int err, devno = MKDEV(tw2834_major, tw2834_minor + index);
//printk("major %d minor %d\n",tw2834_major,tw2834_minor+ index);
if (index ==0 )
{ dev->addr = master0_addr>>1;
printk(KERN_INFO"This is the first chip : the master chip!(0x%02x)\n",dev->addr << 1);}
if (index ==1 )
{ dev->addr = slaver1_addr>>1;
printk(KERN_INFO"This is the second chip : the slaver1 chip!(0x%02x)\n",dev->addr << 1);}
if (index ==2 )
{ dev->addr = slaver2_addr>>1;
printk(KERN_INFO"This is the third chip : the slaver2 chip!(0x%02x)\n",dev->addr << 1);}
if (index ==3 )
{ dev->addr = slaver3_addr>>1;
printk(KERN_INFO"This is the forth chip : the slaver3 chip!(0x%02x)\n",dev->addr << 1);}
cdev_init(&dev->cdev, &tw2834_fops);
dev->cdev.owner = THIS_MODULE;
dev->cdev.ops = &tw2834_fops;
err = cdev_add (&dev->cdev, devno, 1);
sprintf(DEVNAME,"tw2834%d",index);
class_simple_device_add(tw2834_class, MKDEV(tw2834_major, index), NULL, DEVNAME);
/* Fail gracefully if need be */
if (err) printk(KERN_NOTICE "Error %d adding tw2834 %d", err, index);
}
int tw2834_init_module(void)
{
int result, i;
dev_t dev = 0;
i2c_add_driver(&i2c_driver_tw2834);
if (tw2834_major) {
dev = MKDEV(tw2834_major, tw2834_minor);
result = register_chrdev_region(dev, tw2834_nr_devs, DEVNAME); //
} else {
result = alloc_chrdev_region(&dev, tw2834_minor, tw2834_nr_devs,
DEVNAME);
tw2834_major = MAJOR(dev);
}
if (result < 0) {
printk(KERN_WARNING "tw2834: can't get major %d\n", tw2834_major);
return result;
}
tw2834_devices = kmalloc(tw2834_nr_devs * sizeof(struct tw2834_dev), GFP_KERNEL);
if (!tw2834_devices) {
result = -ENOMEM;
goto fail; /* Make this more graceful */
}
memset(tw2834_devices, 0, tw2834_nr_devs * sizeof(struct tw2834_dev));
tw2834_class = class_simple_create(THIS_MODULE, DEVNAME);
/* Initialize each device. */
for (i = 0; i < chip_number+1; i++) {
init_MUTEX(&tw2834_devices[i].sem);
//printk("sem is %d\n",tw2834_devices[i].sem.count);
tw2834_setup_cdev(&tw2834_devices[i], i);
}
init_MUTEX(&tw2834_ioctl_sem);
tw2834_chip_config(); /*init all the chips */
return 0; /* succeed */
fail:
tw2834_cleanup_module();
return result;
}
module_init(tw2834_init_module);
module_exit(tw2834_cleanup_module);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -