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

📄 tveeprom.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
				break;			}			len = eeprom_data[i] & 0x07;			++i;		} else {			tveeprom_warn("Encountered bad packet header [%02x]. "				"Corrupt or not a Hauppauge eeprom.\n", eeprom_data[i]);			return;		}		if (debug) {			tveeprom_info("Tag [%02x] + %d bytes:", eeprom_data[i], len - 1);			for(j = 1; j < len; j++) {				printk(" %02x", eeprom_data[i + j]);			}			printk("\n");		}		/* process by tag */		tag = eeprom_data[i];		switch (tag) {		case 0x00:			/* tag: 'Comprehensive' */			tuner1 = eeprom_data[i+6];			t_format1 = eeprom_data[i+5];			tvee->has_radio = eeprom_data[i+len-1];			/* old style tag, don't know how to detect			IR presence, mark as unknown. */			tvee->has_ir = 2;			tvee->model =				eeprom_data[i+8] +				(eeprom_data[i+9] << 8);			tvee->revision = eeprom_data[i+10] +				(eeprom_data[i+11] << 8) +				(eeprom_data[i+12] << 16);			break;		case 0x01:			/* tag: 'SerialID' */			tvee->serial_number =				eeprom_data[i+6] +				(eeprom_data[i+7] << 8) +				(eeprom_data[i+8] << 16);			break;		case 0x02:			/* tag 'AudioInfo'			Note mask with 0x7F, high bit used on some older models			to indicate 4052 mux was removed in favor of using MSP			inputs directly. */			audioic = eeprom_data[i+2] & 0x7f;			if (audioic < sizeof(audioIC)/sizeof(*audioIC))				tvee->audio_processor = audioIC[audioic].id;			else				tvee->audio_processor = AUDIO_CHIP_UNKNOWN;			break;		/* case 0x03: tag 'EEInfo' */		case 0x04:			/* tag 'SerialID2' */			tvee->serial_number =				eeprom_data[i+5] +				(eeprom_data[i+6] << 8) +				(eeprom_data[i+7] << 16);				if ( (eeprom_data[i + 8] && 0xf0) &&					(tvee->serial_number < 0xffffff) ) {					tvee->MAC_address[0] = 0x00;					tvee->MAC_address[1] = 0x0D;					tvee->MAC_address[2] = 0xFE;					tvee->MAC_address[3] = eeprom_data[i + 7];					tvee->MAC_address[4] = eeprom_data[i + 6];					tvee->MAC_address[5] = eeprom_data[i + 5];					tvee->has_MAC_address = 1;				}			break;		case 0x05:			/* tag 'Audio2'			Note mask with 0x7F, high bit used on some older models			to indicate 4052 mux was removed in favor of using MSP			inputs directly. */			audioic = eeprom_data[i+1] & 0x7f;			if (audioic < sizeof(audioIC)/sizeof(*audioIC))				tvee->audio_processor = audioIC[audioic].id;			else				tvee->audio_processor = AUDIO_CHIP_UNKNOWN;			break;		case 0x06:			/* tag 'ModelRev' */			tvee->model =				eeprom_data[i + 1] +				(eeprom_data[i + 2] << 8) +				(eeprom_data[i + 3] << 16) +				(eeprom_data[i + 4] << 24);			tvee->revision =				eeprom_data[i +5 ] +				(eeprom_data[i + 6] << 8) +				(eeprom_data[i + 7] << 16);			break;		case 0x07:			/* tag 'Details': according to Hauppauge not interesting			on any PCI-era or later boards. */			break;		/* there is no tag 0x08 defined */		case 0x09:			/* tag 'Video' */			tvee->decoder_processor = eeprom_data[i + 1];			break;		case 0x0a:			/* tag 'Tuner' */			if (beenhere == 0) {				tuner1 = eeprom_data[i+2];				t_format1 = eeprom_data[i+1];				beenhere = 1;			} else {				/* a second (radio) tuner may be present */				tuner2 = eeprom_data[i+2];				t_format2 = eeprom_data[i+1];				if (t_format2 == 0) {  /* not a TV tuner? */					tvee->has_radio = 1; /* must be radio */				}			}			break;		case 0x0b:			/* tag 'Inputs': according to Hauppauge this is specific			to each driver family, so no good assumptions can be			made. */			break;		/* case 0x0c: tag 'Balun' */		/* case 0x0d: tag 'Teletext' */		case 0x0e:			/* tag: 'Radio' */			tvee->has_radio = eeprom_data[i+1];			break;		case 0x0f:			/* tag 'IRInfo' */			tvee->has_ir = eeprom_data[i+1];			break;		/* case 0x10: tag 'VBIInfo' */		/* case 0x11: tag 'QCInfo' */		/* case 0x12: tag 'InfoBits' */		default:			tveeprom_dbg("Not sure what to do with tag [%02x]\n", tag);			/* dump the rest of the packet? */		}	}	if (!done) {		tveeprom_warn("Ran out of data!\n");		return;	}	if (tvee->revision != 0) {		tvee->rev_str[0] = 32 + ((tvee->revision >> 18) & 0x3f);		tvee->rev_str[1] = 32 + ((tvee->revision >> 12) & 0x3f);		tvee->rev_str[2] = 32 + ((tvee->revision >>  6) & 0x3f);		tvee->rev_str[3] = 32 + ( tvee->revision        & 0x3f);		tvee->rev_str[4] = 0;	}	if (hasRadioTuner(tuner1) && !tvee->has_radio) {		tveeprom_info("The eeprom says no radio is present, but the tuner type\n");		tveeprom_info("indicates otherwise. I will assume that radio is present.\n");		tvee->has_radio = 1;	}	if (tuner1 < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) {		tvee->tuner_type = hauppauge_tuner[tuner1].id;		t_name1 = hauppauge_tuner[tuner1].name;	} else {		t_name1 = "unknown";	}	if (tuner2 < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) {		tvee->tuner2_type = hauppauge_tuner[tuner2].id;		t_name2 = hauppauge_tuner[tuner2].name;	} else {		t_name2 = "unknown";	}	tvee->tuner_hauppauge_model = tuner1;	tvee->tuner2_hauppauge_model = tuner2;	tvee->tuner_formats = 0;	tvee->tuner2_formats = 0;	for (i = j = 0; i < 8; i++) {		if (t_format1 & (1 << i)) {			tvee->tuner_formats |= hauppauge_tuner_fmt[i].id;			t_fmt_name1[j++] = hauppauge_tuner_fmt[i].name;		}		if (t_format2 & (1 << i)) {			tvee->tuner2_formats |= hauppauge_tuner_fmt[i].id;			t_fmt_name2[j++] = hauppauge_tuner_fmt[i].name;		}	}	tveeprom_info("Hauppauge model %d, rev %s, serial# %d\n",		tvee->model, tvee->rev_str, tvee->serial_number);	if (tvee->has_MAC_address == 1) {		tveeprom_info("MAC address is %02X-%02X-%02X-%02X-%02X-%02X\n",			tvee->MAC_address[0], tvee->MAC_address[1],			tvee->MAC_address[2], tvee->MAC_address[3],			tvee->MAC_address[4], tvee->MAC_address[5]);	}	tveeprom_info("tuner model is %s (idx %d, type %d)\n",		t_name1, tuner1, tvee->tuner_type);	tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n",		t_fmt_name1[0], t_fmt_name1[1], t_fmt_name1[2], t_fmt_name1[3],		t_fmt_name1[4], t_fmt_name1[5], t_fmt_name1[6], t_fmt_name1[7],		t_format1);	if (tuner2) {		tveeprom_info("second tuner model is %s (idx %d, type %d)\n",					t_name2, tuner2, tvee->tuner2_type);	}	if (t_format2) {		tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n",			t_fmt_name2[0], t_fmt_name2[1], t_fmt_name2[2], t_fmt_name2[3],			t_fmt_name2[4], t_fmt_name2[5], t_fmt_name2[6], t_fmt_name2[7],			t_format2);	}	if (audioic<0) {		tveeprom_info("audio processor is unknown (no idx)\n");		tvee->audio_processor=AUDIO_CHIP_UNKNOWN;	} else {		if (audioic < sizeof(audioIC)/sizeof(*audioIC))			tveeprom_info("audio processor is %s (idx %d)\n",					audioIC[audioic].name,audioic);		else			tveeprom_info("audio processor is unknown (idx %d)\n",								audioic);	}	if (tvee->decoder_processor) {		tveeprom_info("decoder processor is %s (idx %d)\n",			STRM(decoderIC, tvee->decoder_processor),			tvee->decoder_processor);	}	if (tvee->has_ir == 2)		tveeprom_info("has %sradio\n",				tvee->has_radio ? "" : "no ");	else		tveeprom_info("has %sradio, has %sIR remote\n",				tvee->has_radio ? "" : "no ",				tvee->has_ir ? "" : "no ");}EXPORT_SYMBOL(tveeprom_hauppauge_analog);/* ----------------------------------------------------------------------- *//* generic helper functions                                                */int tveeprom_read(struct i2c_client *c, unsigned char *eedata, int len){	unsigned char buf;	int err;	buf = 0;	if (1 != (err = i2c_master_send(c, &buf, 1))) {		tveeprom_info("Huh, no eeprom present (err=%d)?\n", err);		return -1;	}	if (len != (err = i2c_master_recv(c, eedata, len))) {		tveeprom_warn("i2c eeprom read error (err=%d)\n", err);		return -1;	}	if (debug) {		int i;		tveeprom_info("full 256-byte eeprom dump:\n");		for (i = 0; i < len; i++) {			if (0 == (i % 16))				tveeprom_info("%02x:", i);			printk(" %02x", eedata[i]);			if (15 == (i % 16))				printk("\n");		}	}	return 0;}EXPORT_SYMBOL(tveeprom_read);/* ----------------------------------------------------------------------- *//* needed for ivtv.sf.net at the moment.  Should go away in the long       *//* run, just call the exported tveeprom_* directly, there is no point in   *//* using the indirect way via i2c_driver->command()                        */static unsigned short normal_i2c[] = {	0xa0 >> 1,	I2C_CLIENT_END,};I2C_CLIENT_INSMOD;static struct i2c_driver i2c_driver_tveeprom;static inttveeprom_command(struct i2c_client *client,		 unsigned int       cmd,		 void              *arg){	struct tveeprom eeprom;	u32 *eeprom_props = arg;	u8 *buf;	switch (cmd) {	case 0:		buf = kmalloc(256,GFP_KERNEL);		memset(buf,0,256);		tveeprom_read(client,buf,256);		tveeprom_hauppauge_analog(client, &eeprom,buf);		kfree(buf);		eeprom_props[0] = eeprom.tuner_type;		eeprom_props[1] = eeprom.tuner_formats;		eeprom_props[2] = eeprom.model;		eeprom_props[3] = eeprom.revision;		eeprom_props[4] = eeprom.has_radio;		break;	default:		return -EINVAL;	}	return 0;}static inttveeprom_detect_client(struct i2c_adapter *adapter,		       int                 address,		       int                 kind){	struct i2c_client *client;	client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);	if (NULL == client)		return -ENOMEM;	memset(client, 0, sizeof(struct i2c_client));	client->addr = address;	client->adapter = adapter;	client->driver = &i2c_driver_tveeprom;	client->flags = I2C_CLIENT_ALLOW_USE;	snprintf(client->name, sizeof(client->name), "tveeprom");	i2c_attach_client(client);	return 0;}static inttveeprom_attach_adapter (struct i2c_adapter *adapter){	if (adapter->id != I2C_HW_B_BT848)		return 0;	return i2c_probe(adapter, &addr_data, tveeprom_detect_client);}static inttveeprom_detach_client (struct i2c_client *client){	int err;	err = i2c_detach_client(client);	if (err < 0)		return err;	kfree(client);	return 0;}static struct i2c_driver i2c_driver_tveeprom = {	.owner          = THIS_MODULE,	.name           = "tveeprom",	.id             = I2C_DRIVERID_TVEEPROM,	.flags          = I2C_DF_NOTIFY,	.attach_adapter = tveeprom_attach_adapter,	.detach_client  = tveeprom_detach_client,	.command        = tveeprom_command,};static int __init tveeprom_init(void){	return i2c_add_driver(&i2c_driver_tveeprom);}static void __exit tveeprom_exit(void){	i2c_del_driver(&i2c_driver_tveeprom);}module_init(tveeprom_init);module_exit(tveeprom_exit);/* * Local variables: * c-basic-offset: 8 * End: */

⌨️ 快捷键说明

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