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

📄 tveeprom.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 2 页
字号:
		/* 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. */			tvee->audio_processor = eeprom_data[i+2] & 0x7f;			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);			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. */			tvee->audio_processor = eeprom_data[i+1] & 0x7f;			break;		case 0x06:                        /* tag 'ModelRev' */			tvee->model =				eeprom_data[i+1] +				(eeprom_data[i+2] << 8);			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_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);	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);        }	tveeprom_info("audio processor is %s (idx %d)\n",		   STRM(audioIC, tvee->audio_processor),		   tvee->audio_processor);        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()                        */#ifndef I2C_DRIVERID_TVEEPROM# define I2C_DRIVERID_TVEEPROM I2C_DRIVERID_EXP2#endifstatic 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 + -