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

📄 saa7121.c

📁 SAA7121 Linux 驱动源码,此设备驱动依赖于Linux总线驱动。
💻 C
📖 第 1 页 / 共 2 页
字号:
static struct miscdevice saa7121_MiscDev = {     .minor =   MISC_DYNAMIC_MINOR,     .name  =   DEVNAME,     .fops  =   &saa7121_fops};static inline intsaa7121_read (struct i2c_client *client,u8 reg){	return i2c_smbus_read_byte_data(client,reg);}static intsaa7121_write (struct i2c_client *client,	       u8                 reg,	       u8                 value){	struct saa7121 *encoder = i2c_get_clientdata(client);	//dprintk(1, KERN_DEBUG "SAA7121: %02x set to %02x\n", reg, value);	encoder->reg[reg] = value;	return i2c_smbus_write_byte_data(client, reg, value);}static intsaa7121_write_block (struct i2c_client *client,		     const u8          *data,		     unsigned int       len){	int ret = -1;	u8 reg;	/*测试是否支持I2C_FUNC_I2C*/	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {		/* do raw I2C, not smbus compatible */		struct saa7121 *encoder = i2c_get_clientdata(client);		struct i2c_msg msg;		u8 block_data[32];		msg.addr = client->addr;		msg.flags = 0;		while (len >= 2) {			msg.buf = (char *) block_data;			msg.len = 0;			block_data[msg.len++] = reg = data[0];			do {				block_data[msg.len++] =				    encoder->reg[reg++] = data[1];				len -= 2;				data += 2;			} while (len >= 2 && data[0] == reg &&				 msg.len < 32);			if ((ret = i2c_transfer(client->adapter,						&msg, 1)) < 0)				break;		}	} else {		/* do some slow I2C emulation kind of thing */		while (len >= 2) {			reg = *data++;			if ((ret = saa7121_write(client, reg,						 *data++)) < 0)				break;			len -= 2;			//printk("Writing Reg[%02x], wait 1/4 second...\n",reg);			//mdelay(250);		}	}	return ret;}/* ----------------------------------------------------------------------- */static intsaa7121_command (struct i2c_client *client,		 unsigned int       cmd,		 void              *arg){	struct saa7121 *encoder = i2c_get_clientdata(client);	switch (cmd) {	case 0:		saa7121_write_block(client, init_common,				    sizeof(init_common));		switch (encoder->norm) {		case VIDEO_MODE_NTSC:			saa7121_write_block(client, init_ntsc,					    sizeof(init_ntsc));			printk("saa7121 set output mode : NTSC\n");			break;		case VIDEO_MODE_PAL:			saa7121_write_block(client, init_pal,					    sizeof(init_pal));			printk("saa7121 set output mode : PAL\n");			break;		}		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[] = { I2C_SAA7121 >> 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 saa7121_i2c_id = 0;static struct i2c_driver i2c_driver_saa7121;static intsaa7121_detect_client (struct i2c_adapter *adapter,		       int                 address,		       int                 kind){	int i = 0;	//int j = 0;	//struct i2c_client *client;	struct saa7121 *encoder;	//saa7121_client = client;	dprintk(1,		KERN_INFO		"saa7121.c: detecting saa7121 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;	saa7121_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);	if (saa7121_client == 0)		return -ENOMEM;	memset(saa7121_client, 0, sizeof(struct i2c_client));	saa7121_client->addr = address;	saa7121_client->adapter = adapter;	saa7121_client->driver = &i2c_driver_saa7121;	saa7121_client->flags = I2C_CLIENT_ALLOW_USE;	saa7121_client->id = saa7121_i2c_id++;	snprintf(I2C_NAME(saa7121_client), sizeof(I2C_NAME(saa7121_client)) - 1,		"saa7121[%d]", saa7121_client->id);	encoder = kmalloc(sizeof(struct saa7121), GFP_KERNEL);	if (encoder == NULL) {		kfree(saa7121_client);		return -ENOMEM;	}	memset(encoder, 0, sizeof(struct saa7121));	encoder->norm = VIDEO_MODE_PAL;	encoder->enable = 1;	i2c_set_clientdata(saa7121_client, encoder);	i = i2c_attach_client(saa7121_client);	if (i) {		kfree(saa7121_client);		kfree(encoder);		return i;	}	/*测试寄存器的数据*/	/*	for (i=0; i<64; i++){		for (j=0; j<4; j++)	{			dprintk(1,			"B_REG[%02x] = 0x%02x",			i*4+j, saa7121_read(saa7121_client,i*4+j)			);		}		dprintk(1,"\n");	}	*/				i = saa7121_write_block(saa7121_client, init_common, sizeof(init_common));	if (i >= 0) {		 	 	if(strcmp(mode_option,"pal")==0) 	{	  printk("output format is : pal\n");	  i = saa7121_write_block(saa7121_client, init_pal,sizeof(init_pal)); 	} 	else 	{	  printk("output format is : ntsc\n");	  i = saa7121_write_block(saa7121_client, init_ntsc,sizeof(init_ntsc)); 	} 			}	if (i < 0) {		dprintk(1, KERN_ERR "%s_attach: init error %d\n",			I2C_NAME(saa7121_client), i);	} else {		dprintk(1,			KERN_INFO			"%s_attach: chip version %d at address 0x%x\n",			I2C_NAME(saa7121_client), saa7121_read(saa7121_client,0) >> 5,			saa7121_client->addr << 1);	}    /* Register a misc device called "saa7121". */    i = misc_register( &saa7121_MiscDev );    if (i < 0)    {        dprintk(1, KERN_INFO "can't register misc device (minor %d)!\n", saa7121_MiscDev.minor );        return i;    }	return 0;}static intsaa7121_attach_adapter (struct i2c_adapter *adapter){	dprintk(1,		KERN_INFO		"saa7121.c: starting probe for adapter %s (0x%x)\n",		I2C_NAME(adapter), adapter->id);	return i2c_probe(adapter, &addr_data, &saa7121_detect_client);}static intsaa7121_detach_client (struct i2c_client *client){	struct saa7121 *encoder = i2c_get_clientdata(client);	int err;	err = i2c_detach_client(client);	if (err) {		return err;	}	saa7121_write(client, 0x61, (encoder->reg[0x61]) | 0x40);	/* SW: output off is active */	//saa7121_write(client, 0x3a, (encoder->reg[0x3a]) | 0x80); /* SW: color bar */	kfree(encoder);	kfree(client);	return 0;}/* ----------------------------------------------------------------------- */static struct i2c_driver i2c_driver_saa7121 = {	.owner = THIS_MODULE,	.name = "saa7121",	.id = I2C_DRIVERID_SAA7121,	.flags = I2C_DF_NOTIFY,	.attach_adapter = saa7121_attach_adapter,	.detach_client = saa7121_detach_client,	.command = saa7121_command,};static int __initsaa7121_init (void){    /*设置QVCP 5L的输出格式*///   QVCP5L的输出格式是双D1模式,8bit。//	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_saa7121);}static void __exitsaa7121_exit (void){    if (misc_deregister(&saa7121_MiscDev)!=0)    {        dprintk(1, KERN_INFO "saa7121: could not misc_deregister the device\n");    }	i2c_del_driver(&i2c_driver_saa7121);}module_init(saa7121_init);module_exit(saa7121_exit);MODULE_DESCRIPTION("Philips SAA7121 Video Encoder Driver");MODULE_AUTHOR("Wu WenBin");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -