dw2102.c

来自「trident tm5600的linux驱动」· C语言 代码 · 共 829 行 · 第 1/2 页

C
829
字号
	struct dvb_usb_adapter *udev_adap =		(struct dvb_usb_adapter *)(fe->dvb->priv);	if (voltage == SEC_VOLTAGE_18)		msg[0].buf = command_18v;	i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1);	return 0;}static struct stv0299_config sharp_z0194a_config = {	.demod_address = 0x68,	.inittab = sharp_z0194a_inittab,	.mclk = 88000000UL,	.invert = 1,	.skip_reinit = 0,	.lock_output = STV0299_LOCKOUTPUT_1,	.volt13_op0_op1 = STV0299_VOLT13_OP1,	.min_delay_ms = 100,	.set_symbol_rate = sharp_z0194a_set_symbol_rate,};static struct cx24116_config dw2104_config = {	.demod_address = 0x55,	.mpg_clk_pos_pol = 0x01,};static struct si21xx_config serit_sp1511lhb_config = {	.demod_address = 0x68,	.min_delay_ms = 100,};static int dw2104_frontend_attach(struct dvb_usb_adapter *d){	if ((d->fe = dvb_attach(cx24116_attach, &dw2104_config,			&d->dev->i2c_adap)) != NULL) {		d->fe->ops.set_voltage = dw210x_set_voltage;		info("Attached cx24116!\n");		return 0;	}	return -EIO;}static struct dvb_usb_device_properties dw2102_properties;static int dw2102_frontend_attach(struct dvb_usb_adapter *d){	if (dw2102_properties.i2c_algo == &dw2102_serit_i2c_algo) {		/*dw2102_properties.adapter->tuner_attach = NULL;*/		d->fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config,					&d->dev->i2c_adap);		if (d->fe != NULL) {			d->fe->ops.set_voltage = dw210x_set_voltage;			info("Attached si21xx!\n");			return 0;		}	}	if (dw2102_properties.i2c_algo == &dw2102_earda_i2c_algo) {		/*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/		d->fe = dvb_attach(stv0288_attach, &earda_config,					&d->dev->i2c_adap);		if (d->fe != NULL) {			d->fe->ops.set_voltage = dw210x_set_voltage;			info("Attached stv0288!\n");			return 0;		}	}	if (dw2102_properties.i2c_algo == &dw2102_i2c_algo) {		/*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/		d->fe = dvb_attach(stv0299_attach, &sharp_z0194a_config,					&d->dev->i2c_adap);		if (d->fe != NULL) {			d->fe->ops.set_voltage = dw210x_set_voltage;			info("Attached stv0299!\n");			return 0;		}	}	return -EIO;}static int dw2102_tuner_attach(struct dvb_usb_adapter *adap){	dvb_attach(dvb_pll_attach, adap->fe, 0x60,		&adap->dev->i2c_adap, DVB_PLL_OPERA1);	return 0;}static int dw2102_earda_tuner_attach(struct dvb_usb_adapter *adap){	dvb_attach(stb6000_attach, adap->fe, 0x61,		&adap->dev->i2c_adap);	return 0;}static struct dvb_usb_rc_key dw210x_rc_keys[] = {	{ 0xf8,	0x0a, KEY_Q },		/*power*/	{ 0xf8,	0x0c, KEY_M },		/*mute*/	{ 0xf8,	0x11, KEY_1 },	{ 0xf8,	0x12, KEY_2 },	{ 0xf8,	0x13, KEY_3 },	{ 0xf8,	0x14, KEY_4 },	{ 0xf8,	0x15, KEY_5 },	{ 0xf8,	0x16, KEY_6 },	{ 0xf8,	0x17, KEY_7 },	{ 0xf8,	0x18, KEY_8 },	{ 0xf8,	0x19, KEY_9 },	{ 0xf8, 0x10, KEY_0 },	{ 0xf8, 0x1c, KEY_PAGEUP },	/*ch+*/	{ 0xf8, 0x0f, KEY_PAGEDOWN },	/*ch-*/	{ 0xf8, 0x1a, KEY_O },		/*vol+*/	{ 0xf8, 0x0e, KEY_Z },		/*vol-*/	{ 0xf8, 0x04, KEY_R },		/*rec*/	{ 0xf8, 0x09, KEY_D },		/*fav*/	{ 0xf8, 0x08, KEY_BACKSPACE },	/*rewind*/	{ 0xf8, 0x07, KEY_A },		/*fast*/	{ 0xf8, 0x0b, KEY_P },		/*pause*/	{ 0xf8, 0x02, KEY_ESC },	/*cancel*/	{ 0xf8, 0x03, KEY_G },		/*tab*/	{ 0xf8, 0x00, KEY_UP },		/*up*/	{ 0xf8, 0x1f, KEY_ENTER },	/*ok*/	{ 0xf8, 0x01, KEY_DOWN },	/*down*/	{ 0xf8, 0x05, KEY_C },		/*cap*/	{ 0xf8, 0x06, KEY_S },		/*stop*/	{ 0xf8, 0x40, KEY_F },		/*full*/	{ 0xf8, 0x1e, KEY_W },		/*tvmode*/	{ 0xf8, 0x1b, KEY_B },		/*recall*/};static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state){	struct dw210x_state *st = d->priv;	u8 key[2];	struct i2c_msg msg[] = {		{.addr = DW2102_RC_QUERY, .flags = I2C_M_RD, .buf = key,		.len = 2},	};	int i;	*state = REMOTE_NO_KEY_PRESSED;	if (dw2102_i2c_transfer(&d->i2c_adap, msg, 1) == 1) {		for (i = 0; i < ARRAY_SIZE(dw210x_rc_keys); i++) {			if (dw210x_rc_keys[i].data == msg[0].buf[0]) {				*state = REMOTE_KEY_PRESSED;				*event = dw210x_rc_keys[i].event;				st->last_key_pressed =					dw210x_rc_keys[i].event;				break;			}		st->last_key_pressed = 0;		}	}	/* info("key: %x %x\n",key[0],key[1]); */	return 0;}static struct usb_device_id dw2102_table[] = {	{USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)},	{USB_DEVICE(USB_VID_CYPRESS, 0x2101)},	{USB_DEVICE(USB_VID_CYPRESS, 0x2104)},	{USB_DEVICE(0x9022, 0xd650)},	{ }};MODULE_DEVICE_TABLE(usb, dw2102_table);static int dw2102_load_firmware(struct usb_device *dev,			const struct firmware *frmwr){	u8 *b, *p;	int ret = 0, i;	u8 reset;	u8 reset16[] = {0, 0, 0, 0, 0, 0, 0};	const struct firmware *fw;	const char *filename = "dvb-usb-dw2101.fw";	switch (dev->descriptor.idProduct) {	case 0x2101:		ret = request_firmware(&fw, filename, &dev->dev);		if (ret != 0) {			err("did not find the firmware file. (%s) "			"Please see linux/Documentation/dvb/ for more details "			"on firmware-problems.", filename);			return ret;		}		break;	default:		fw = frmwr;		break;	}	info("start downloading DW210X firmware");	p = kmalloc(fw->size, GFP_KERNEL);	reset = 1;	/*stop the CPU*/	dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, DW210X_WRITE_MSG);	dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, DW210X_WRITE_MSG);	if (p != NULL) {		memcpy(p, fw->data, fw->size);		for (i = 0; i < fw->size; i += 0x40) {			b = (u8 *) p + i;			if (dw210x_op_rw(dev, 0xa0, i, 0, b , 0x40,					DW210X_WRITE_MSG) != 0x40) {				err("error while transferring firmware");				ret = -EINVAL;				break;			}		}		/* restart the CPU */		reset = 0;		if (ret || dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,					DW210X_WRITE_MSG) != 1) {			err("could not restart the USB controller CPU.");			ret = -EINVAL;		}		if (ret || dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,					DW210X_WRITE_MSG) != 1) {			err("could not restart the USB controller CPU.");			ret = -EINVAL;		}		/* init registers */		switch (dev->descriptor.idProduct) {		case USB_PID_DW2104:		case 0xd650:			reset = 1;			dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1,					DW210X_WRITE_MSG);			reset = 0;			dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,					DW210X_WRITE_MSG);			break;		case USB_PID_DW2102:			dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,					DW210X_WRITE_MSG);			dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2,					DW210X_READ_MSG);			/* check STV0299 frontend  */			dw210x_op_rw(dev, 0xb5, 0, 0, &reset16[0], 2,					DW210X_READ_MSG);			if (reset16[0] == 0xa1) {				dw2102_properties.i2c_algo = &dw2102_i2c_algo;				dw2102_properties.adapter->tuner_attach = &dw2102_tuner_attach;				break;			} else {				/* check STV0288 frontend  */				reset16[0] = 0xd0;				reset16[1] = 1;				reset16[2] = 0;				dw210x_op_rw(dev, 0xc2, 0, 0, &reset16[0], 3,						DW210X_WRITE_MSG);				dw210x_op_rw(dev, 0xc3, 0xd1, 0, &reset16[0], 3,						DW210X_READ_MSG);				if (reset16[2] == 0x11) {					dw2102_properties.i2c_algo = &dw2102_earda_i2c_algo;					dw2102_properties.adapter->tuner_attach = &dw2102_earda_tuner_attach;					break;				}			}		case 0x2101:			dw210x_op_rw(dev, 0xbc, 0x0030, 0, &reset16[0], 2,					DW210X_READ_MSG);			dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7,					DW210X_READ_MSG);			dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7,					DW210X_READ_MSG);			dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2,					DW210X_READ_MSG);			break;		}		msleep(100);		kfree(p);	}	return ret;}static struct dvb_usb_device_properties dw2102_properties = {	.caps = DVB_USB_IS_AN_I2C_ADAPTER,	.usb_ctrl = DEVICE_SPECIFIC,	.firmware = "dvb-usb-dw2102.fw",	.size_of_priv = sizeof(struct dw210x_state),	.no_reconnect = 1,	.i2c_algo = &dw2102_serit_i2c_algo,	.rc_key_map = dw210x_rc_keys,	.rc_key_map_size = ARRAY_SIZE(dw210x_rc_keys),	.rc_interval = 150,	.rc_query = dw2102_rc_query,	.generic_bulk_ctrl_endpoint = 0x81,	/* parameter for the MPEG2-data transfer */	.num_adapters = 1,	.download_firmware = dw2102_load_firmware,	.read_mac_address = dw210x_read_mac_address,		.adapter = {		{			.frontend_attach = dw2102_frontend_attach,			.streaming_ctrl = NULL,			.tuner_attach = NULL,			.stream = {				.type = USB_BULK,				.count = 8,				.endpoint = 0x82,				.u = {					.bulk = {						.buffersize = 4096,					}				}			},		}	},	.num_device_descs = 2,	.devices = {		{"DVBWorld DVB-S 2102 USB2.0",			{&dw2102_table[0], NULL},			{NULL},		},		{"DVBWorld DVB-S 2101 USB2.0",			{&dw2102_table[1], NULL},			{NULL},		},	}};static struct dvb_usb_device_properties dw2104_properties = {	.caps = DVB_USB_IS_AN_I2C_ADAPTER,	.usb_ctrl = DEVICE_SPECIFIC,	.firmware = "dvb-usb-dw2104.fw",	.size_of_priv = sizeof(struct dw210x_state),	.no_reconnect = 1,	.i2c_algo = &dw2104_i2c_algo,	.rc_key_map = dw210x_rc_keys,	.rc_key_map_size = ARRAY_SIZE(dw210x_rc_keys),	.rc_interval = 150,	.rc_query = dw2102_rc_query,	.generic_bulk_ctrl_endpoint = 0x81,	/* parameter for the MPEG2-data transfer */	.num_adapters = 1,	.download_firmware = dw2102_load_firmware,	.read_mac_address = dw210x_read_mac_address,	.adapter = {		{			.frontend_attach = dw2104_frontend_attach,			.streaming_ctrl = NULL,			/*.tuner_attach = dw2104_tuner_attach,*/			.stream = {				.type = USB_BULK,				.count = 8,				.endpoint = 0x82,				.u = {					.bulk = {						.buffersize = 4096,					}				}			},		}	},	.num_device_descs = 2,	.devices = {		{ "DVBWorld DW2104 USB2.0",			{&dw2102_table[2], NULL},			{NULL},		},		{ "TeVii S650 USB2.0",			{&dw2102_table[3], NULL},			{NULL},		},	}};static int dw2102_probe(struct usb_interface *intf,		const struct usb_device_id *id){	if (0 == dvb_usb_device_init(intf, &dw2102_properties,			THIS_MODULE, NULL, adapter_nr) ||	    0 == dvb_usb_device_init(intf, &dw2104_properties,			THIS_MODULE, NULL, adapter_nr)) {		return 0;	}	return -ENODEV;}static struct usb_driver dw2102_driver = {	.name = "dw2102",	.probe = dw2102_probe,	.disconnect = dvb_usb_device_exit,	.id_table = dw2102_table,};static int __init dw2102_module_init(void){	int ret =  usb_register(&dw2102_driver);	if (ret)		err("usb_register failed. Error number %d", ret);	return ret;}static void __exit dw2102_module_exit(void){	usb_deregister(&dw2102_driver);}module_init(dw2102_module_init);module_exit(dw2102_module_exit);MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by");MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104 USB2.0 device");MODULE_VERSION("0.1");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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