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

📄 tw2834.c

📁 TW2834 的Linux驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
    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 + -