You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							323 lines
						
					
					
						
							10 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							323 lines
						
					
					
						
							10 KiB
						
					
					
				| --- a/drivers/media/usb/dvb-usb/cxusb.c | |
| +++ b/drivers/media/usb/dvb-usb/cxusb.c | |
| @@ -1402,6 +1402,76 @@ | |
|  	return 0; | |
|  } | |
|   | |
| +static int cxusb_mygica_t230c_frontend_attach(struct dvb_usb_adapter *adap) | |
| +{ | |
| +	struct dvb_usb_device *d = adap->dev; | |
| +	struct cxusb_state *st = d->priv; | |
| +	struct i2c_adapter *adapter; | |
| +	struct i2c_client *client_demod; | |
| +	struct i2c_client *client_tuner; | |
| +	struct i2c_board_info info; | |
| +	struct si2168_config si2168_config; | |
| +	struct si2157_config si2157_config; | |
| + | |
| +	/* Select required USB configuration */ | |
| +	if (usb_set_interface(d->udev, 0, 0) < 0) | |
| +		err("set interface failed"); | |
| + | |
| +	/* Unblock all USB pipes */ | |
| +	usb_clear_halt(d->udev, | |
| +		usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint)); | |
| +	usb_clear_halt(d->udev, | |
| +		usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint)); | |
| +	usb_clear_halt(d->udev, | |
| +		usb_rcvbulkpipe(d->udev, d->props.adapter[0].fe[0].stream.endpoint)); | |
| + | |
| +	/* attach frontend */ | |
| +	memset(&si2168_config, 0, sizeof(si2168_config)); | |
| +	si2168_config.i2c_adapter = &adapter; | |
| +	si2168_config.fe = &adap->fe_adap[0].fe; | |
| +	si2168_config.ts_mode = SI2168_TS_PARALLEL; | |
| +	si2168_config.ts_clock_inv = 1; | |
| +	memset(&info, 0, sizeof(struct i2c_board_info)); | |
| +	strlcpy(info.type, "si2168", I2C_NAME_SIZE); | |
| +	info.addr = 0x64; | |
| +	info.platform_data = &si2168_config; | |
| +	request_module(info.type); | |
| +	client_demod = i2c_new_device(&d->i2c_adap, &info); | |
| +	if (client_demod == NULL || client_demod->dev.driver == NULL) | |
| +		return -ENODEV; | |
| + | |
| +	if (!try_module_get(client_demod->dev.driver->owner)) { | |
| +		i2c_unregister_device(client_demod); | |
| +		return -ENODEV; | |
| +	} | |
| + | |
| +	/* attach tuner */ | |
| +	memset(&si2157_config, 0, sizeof(si2157_config)); | |
| +	si2157_config.fe = adap->fe_adap[0].fe; | |
| +	memset(&info, 0, sizeof(struct i2c_board_info)); | |
| +	strlcpy(info.type, "si2141", I2C_NAME_SIZE); | |
| +	info.addr = 0x60; | |
| +	info.platform_data = &si2157_config; | |
| +	request_module("si2157"); | |
| +	client_tuner = i2c_new_device(adapter, &info); | |
| +	if (client_tuner == NULL || client_tuner->dev.driver == NULL) { | |
| +		module_put(client_demod->dev.driver->owner); | |
| +		i2c_unregister_device(client_demod); | |
| +		return -ENODEV; | |
| +	} | |
| +	if (!try_module_get(client_tuner->dev.driver->owner)) { | |
| +		i2c_unregister_device(client_tuner); | |
| +		module_put(client_demod->dev.driver->owner); | |
| +		i2c_unregister_device(client_demod); | |
| +		return -ENODEV; | |
| +	} | |
| + | |
| +	st->i2c_client_demod = client_demod; | |
| +	st->i2c_client_tuner = client_tuner; | |
| + | |
| +	return 0; | |
| +} | |
| + | |
|  /* | |
|   * DViCO has shipped two devices with the same USB ID, but only one of them | |
|   * needs a firmware download.  Check the device class details to see if they | |
| @@ -1484,6 +1554,7 @@ | |
|  static struct dvb_usb_device_properties cxusb_d680_dmb_properties; | |
|  static struct dvb_usb_device_properties cxusb_mygica_d689_properties; | |
|  static struct dvb_usb_device_properties cxusb_mygica_t230_properties; | |
| +static struct dvb_usb_device_properties cxusb_mygica_t230c_properties; | |
|   | |
|  static int cxusb_probe(struct usb_interface *intf, | |
|  		       const struct usb_device_id *id) | |
| @@ -1516,6 +1587,8 @@ | |
|  				     THIS_MODULE, NULL, adapter_nr) || | |
|  	    0 == dvb_usb_device_init(intf, &cxusb_mygica_t230_properties, | |
|  				     THIS_MODULE, NULL, adapter_nr) || | |
| +	    0 == dvb_usb_device_init(intf, &cxusb_mygica_t230c_properties, | |
| +				     THIS_MODULE, NULL, adapter_nr) || | |
|  	    0) | |
|  		return 0; | |
|   | |
| @@ -1567,6 +1640,8 @@ | |
|  	CONEXANT_D680_DMB, | |
|  	MYGICA_D689, | |
|  	MYGICA_T230, | |
| +	MYGICA_T230C, | |
| +	MYGICA_T230C2, | |
|  	NR__cxusb_table_index | |
|  }; | |
|   | |
| @@ -1633,6 +1708,12 @@ | |
|  	}, | |
|  	[MYGICA_T230] = { | |
|  		USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230) | |
| +	}, | |
| +	[MYGICA_T230C] = { | |
| +		USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230+1) | |
| +	}, | |
| +	[MYGICA_T230C2] = { | |
| +		USB_DEVICE(0x0572, 0xc68a) | |
|  	}, | |
|  	{}		/* Terminating entry */ | |
|  }; | |
| @@ -2333,6 +2414,66 @@ | |
|  	} | |
|  }; | |
|   | |
| +static struct dvb_usb_device_properties cxusb_mygica_t230c_properties = { | |
| +	.caps = DVB_USB_IS_AN_I2C_ADAPTER, | |
| + | |
| +	.usb_ctrl         = CYPRESS_FX2, | |
| + | |
| +	.size_of_priv     = sizeof(struct cxusb_state), | |
| + | |
| +	.num_adapters = 1, | |
| +	.adapter = { | |
| +		{ | |
| +		.num_frontends = 1, | |
| +		.fe = {{ | |
| +			.streaming_ctrl   = cxusb_streaming_ctrl, | |
| +			.frontend_attach  = cxusb_mygica_t230c_frontend_attach, | |
| + | |
| +			/* parameter for the MPEG2-data transfer */ | |
| +			.stream = { | |
| +				.type = USB_BULK, | |
| +				.count = 5, | |
| +				.endpoint = 0x02, | |
| +				.u = { | |
| +					.bulk = { | |
| +						.buffersize = 8192, | |
| +					} | |
| +				} | |
| +			}, | |
| +		} }, | |
| +		}, | |
| +	}, | |
| + | |
| +	.power_ctrl       = cxusb_d680_dmb_power_ctrl, | |
| + | |
| +	.i2c_algo         = &cxusb_i2c_algo, | |
| + | |
| +	.generic_bulk_ctrl_endpoint = 0x01, | |
| + | |
| +#if 0 /* FIXME: crash dump kernel - dvb_usb_nec_rc_key_to_event */ | |
| +	.rc.legacy = { | |
| +		.rc_interval	= 100, | |
| +		.rc_map_table     = rc_map_d680_dmb_table, | |
| +		.rc_map_size      = ARRAY_SIZE(rc_map_d680_dmb_table), | |
| +		.rc_query         = cxusb_d680_dmb_rc_query, | |
| +	}, | |
| +#endif | |
| + | |
| +	.num_device_descs = 2, | |
| +	.devices = { | |
| +		{ | |
| +			"Mygica T230C DVB-T/T2/C", | |
| +			{ NULL }, | |
| +			{ &cxusb_table[MYGICA_T230C], NULL }, | |
| +		}, | |
| +		{ | |
| +			"Mygica T230C2 DVB-T/T2/C", | |
| +			{ NULL }, | |
| +			{ &cxusb_table[MYGICA_T230C2], NULL }, | |
| +		}, | |
| +	} | |
| +}; | |
| + | |
|  static struct usb_driver cxusb_driver = { | |
|  	.name		= "dvb_usb_cxusb", | |
|  	.probe		= cxusb_probe, | |
| diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c | |
| index 57b250847cd3..e35b1faf0ddc 100644 | |
| --- a/drivers/media/tuners/si2157.c | |
| +++ b/drivers/media/tuners/si2157.c | |
| @@ -106,6 +106,9 @@ static int si2157_init(struct dvb_frontend *fe) | |
|  	if (dev->chiptype == SI2157_CHIPTYPE_SI2146) { | |
|  		memcpy(cmd.args, "\xc0\x05\x01\x00\x00\x0b\x00\x00\x01", 9); | |
|  		cmd.wlen = 9; | |
| +	} else if (dev->chiptype == SI2157_CHIPTYPE_SI2141) { | |
| +		memcpy(cmd.args, "\xc0\x00\x0d\x0e\x00\x01\x01\x01\x01\x03", 10); | |
| +		cmd.wlen = 10; | |
|  	} else { | |
|  		memcpy(cmd.args, "\xc0\x00\x0c\x00\x00\x01\x01\x01\x01\x01\x01\x02\x00\x00\x01", 15); | |
|  		cmd.wlen = 15; | |
| @@ -115,6 +118,15 @@ static int si2157_init(struct dvb_frontend *fe) | |
|  	if (ret) | |
|  		goto err; | |
|   | |
| +	/* Si2141 needs a second command before it answers the revision query */ | |
| +	if (dev->chiptype == SI2157_CHIPTYPE_SI2141) { | |
| +		memcpy(cmd.args, "\xc0\x08\x01\x02\x00\x00\x01", 7); | |
| +		cmd.wlen = 7; | |
| +		ret = si2157_cmd_execute(client, &cmd); | |
| +		if (ret) | |
| +			goto err; | |
| +	} | |
| + | |
|  	/* query chip revision */ | |
|  	memcpy(cmd.args, "\x02", 1); | |
|  	cmd.wlen = 1; | |
| @@ -131,12 +143,16 @@ static int si2157_init(struct dvb_frontend *fe) | |
|  	#define SI2157_A30 ('A' << 24 | 57 << 16 | '3' << 8 | '0' << 0) | |
|  	#define SI2147_A30 ('A' << 24 | 47 << 16 | '3' << 8 | '0' << 0) | |
|  	#define SI2146_A10 ('A' << 24 | 46 << 16 | '1' << 8 | '0' << 0) | |
| +	#define SI2141_A10 ('A' << 24 | 41 << 16 | '1' << 8 | '0' << 0) | |
|   | |
|  	switch (chip_id) { | |
|  	case SI2158_A20: | |
|  	case SI2148_A20: | |
|  		fw_name = SI2158_A20_FIRMWARE; | |
|  		break; | |
| +	case SI2141_A10: | |
| +		fw_name = SI2141_A10_FIRMWARE; | |
| +		break; | |
|  	case SI2157_A30: | |
|  	case SI2147_A30: | |
|  	case SI2146_A10: | |
| @@ -371,7 +387,7 @@ static int si2157_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) | |
|   | |
|  static const struct dvb_tuner_ops si2157_ops = { | |
|  	.info = { | |
| -		.name           = "Silicon Labs Si2146/2147/2148/2157/2158", | |
| +		.name           = "Silicon Labs Si2141/Si2146/2147/2148/2157/2158", | |
|  		.frequency_min  = 42000000, | |
|  		.frequency_max  = 870000000, | |
|  	}, | |
| @@ -471,6 +487,7 @@ static int si2157_probe(struct i2c_client *client, | |
|  #endif | |
|   | |
|  	dev_info(&client->dev, "Silicon Labs %s successfully attached\n", | |
| +			dev->chiptype == SI2157_CHIPTYPE_SI2141 ?  "Si2141" : | |
|  			dev->chiptype == SI2157_CHIPTYPE_SI2146 ? | |
|  			"Si2146" : "Si2147/2148/2157/2158"); | |
|   | |
| @@ -508,6 +525,7 @@ static int si2157_remove(struct i2c_client *client) | |
|  static const struct i2c_device_id si2157_id_table[] = { | |
|  	{"si2157", SI2157_CHIPTYPE_SI2157}, | |
|  	{"si2146", SI2157_CHIPTYPE_SI2146}, | |
| +	{"si2141", SI2157_CHIPTYPE_SI2141}, | |
|  	{} | |
|  }; | |
|  MODULE_DEVICE_TABLE(i2c, si2157_id_table); | |
| @@ -524,7 +542,8 @@ static struct i2c_driver si2157_driver = { | |
|   | |
|  module_i2c_driver(si2157_driver); | |
|   | |
| -MODULE_DESCRIPTION("Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner driver"); | |
| +MODULE_DESCRIPTION("Silicon Labs Si2141/Si2146/2147/2148/2157/2158 silicon tuner driver"); | |
|  MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | |
|  MODULE_LICENSE("GPL"); | |
|  MODULE_FIRMWARE(SI2158_A20_FIRMWARE); | |
| +MODULE_FIRMWARE(SI2141_A10_FIRMWARE); | |
| diff --git a/drivers/media/tuners/si2157_priv.h b/drivers/media/tuners/si2157_priv.h | |
| index d6b2c7b44053..e6436f74abaa 100644 | |
| --- a/drivers/media/tuners/si2157_priv.h | |
| +++ b/drivers/media/tuners/si2157_priv.h | |
| @@ -42,6 +42,7 @@ struct si2157_dev { | |
|   | |
|  #define SI2157_CHIPTYPE_SI2157 0 | |
|  #define SI2157_CHIPTYPE_SI2146 1 | |
| +#define SI2157_CHIPTYPE_SI2141 2 | |
|   | |
|  /* firmware command struct */ | |
|  #define SI2157_ARGLEN      30 | |
| @@ -52,5 +53,6 @@ struct si2157_cmd { | |
|  }; | |
|   | |
|  #define SI2158_A20_FIRMWARE "dvb-tuner-si2158-a20-01.fw" | |
| +#define SI2141_A10_FIRMWARE "dvb-tuner-si2141-a10-01.fw" | |
|   | |
|  #endif | |
| --- a/drivers/media/dvb-frontends/si2168.c | |
| +++ b/drivers/media/dvb-frontends/si2168.c | |
| @@ -674,6 +674,9 @@ static int si2168_probe(struct i2c_client *client, | |
|  	case SI2168_CHIP_ID_B40: | |
|  		dev->firmware_name = SI2168_B40_FIRMWARE; | |
|  		break; | |
| +	case SI2168_CHIP_ID_D60: | |
| +		dev->firmware_name = SI2168_D60_FIRMWARE; | |
| +		break; | |
|  	default: | |
|  		dev_dbg(&client->dev, "unknown chip version Si21%d-%c%c%c\n", | |
|  			cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]); | |
| @@ -761,3 +764,4 @@ MODULE_LICENSE("GPL"); | |
|  MODULE_FIRMWARE(SI2168_A20_FIRMWARE); | |
|  MODULE_FIRMWARE(SI2168_A30_FIRMWARE); | |
|  MODULE_FIRMWARE(SI2168_B40_FIRMWARE); | |
| +MODULE_FIRMWARE(SI2168_D60_FIRMWARE); | |
| diff --git a/drivers/media/dvb-frontends/si2168_priv.h b/drivers/media/dvb-frontends/si2168_priv.h | |
| index 7843ccb448a0..4baa95b7d648 100644 | |
| --- a/drivers/media/dvb-frontends/si2168_priv.h | |
| +++ b/drivers/media/dvb-frontends/si2168_priv.h | |
| @@ -25,6 +25,7 @@ | |
|  #define SI2168_A20_FIRMWARE "dvb-demod-si2168-a20-01.fw" | |
|  #define SI2168_A30_FIRMWARE "dvb-demod-si2168-a30-01.fw" | |
|  #define SI2168_B40_FIRMWARE "dvb-demod-si2168-b40-01.fw" | |
| +#define SI2168_D60_FIRMWARE "dvb-demod-si2168-d60-01.fw" | |
|  #define SI2168_B40_FIRMWARE_FALLBACK "dvb-demod-si2168-02.fw" | |
|   | |
|  /* state struct */ | |
| @@ -37,6 +38,7 @@ struct si2168_dev { | |
|  	#define SI2168_CHIP_ID_A20 ('A' << 24 | 68 << 16 | '2' << 8 | '0' << 0) | |
|  	#define SI2168_CHIP_ID_A30 ('A' << 24 | 68 << 16 | '3' << 8 | '0' << 0) | |
|  	#define SI2168_CHIP_ID_B40 ('B' << 24 | 68 << 16 | '4' << 8 | '0' << 0) | |
| +	#define SI2168_CHIP_ID_D60 ('D' << 24 | 68 << 16 | '6' << 8 | '0' << 0) | |
|  	unsigned int chip_id; | |
|  	unsigned int version; | |
|  	const char *firmware_name;
 | |
| 
 |