18 changed files with 12060 additions and 11 deletions
			
			
		| @ -0,0 +1,24 @@ | |||||
|  | --- a/drivers/hisilicon/atags/tag-chiptrim.c
 | ||||
|  | +++ b/drivers/hisilicon/atags/tag-chiptrim.c
 | ||||
|  | @@ -59,7 +59,7 @@ static int __init parse_chiptrim(const struct tag *tag, void *fdt)
 | ||||
|  |  	int ix; | ||||
|  |  	int ret; | ||||
|  |  	int node; | ||||
|  | -	char buf[12];
 | ||||
|  | +	char buf[20];
 | ||||
|  |   | ||||
|  |  	if (tag->hdr.size <= (sizeof(struct tag_header) >> 2)) { | ||||
|  |  		pr_err("%s: bad tag format.\n", __func__); | ||||
|  | --- a/drivers/hisilicon/atags/tag-net.c	2020-03-25 11:27:19.138225245 +0000
 | ||||
|  | +++ b/drivers/hisilicon/atags/tag-net.c	2020-03-25 11:27:02.498266476 +0000
 | ||||
|  | @@ -91,7 +91,7 @@
 | ||||
|  |  { | ||||
|  |  	int err; | ||||
|  |  	int node, index = 0; | ||||
|  | -	char path[16];
 | ||||
|  | +	char path[20];
 | ||||
|  |  	char phy_intf[16]; | ||||
|  |  	char *str, *nxt; | ||||
|  |  	int count; | ||||
|  | -- 
 | ||||
|  | 2.17.1 | ||||
| @ -0,0 +1,238 @@ | |||||
|  | ---
 | ||||
|  |  drivers/media/dvb-core/dvb-usb-ids.h        |   2 + | ||||
|  |  drivers/media/usb/dvb-usb/Kconfig           |   2 + | ||||
|  |  drivers/media/usb/dvb-usb/dib0700.h         |   2 + | ||||
|  |  drivers/media/usb/dvb-usb/dib0700_core.c    |  25 ++++- | ||||
|  |  drivers/media/usb/dvb-usb/dib0700_devices.c | 105 ++++++++++++++++++++ | ||||
|  |  5 files changed, 135 insertions(+), 1 deletion(-) | ||||
|  | 
 | ||||
|  | diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h
 | ||||
|  | index 0a46580b..512275c7 100644
 | ||||
|  | --- a/drivers/media/dvb-core/dvb-usb-ids.h
 | ||||
|  | +++ b/drivers/media/dvb-core/dvb-usb-ids.h
 | ||||
|  | @@ -70,6 +70,7 @@
 | ||||
|  |  #define USB_VID_EVOLUTEPC			0x1e59 | ||||
|  |  #define USB_VID_AZUREWAVE			0x13d3 | ||||
|  |  #define USB_VID_TECHNISAT			0x14f7 | ||||
|  | +#define USB_VID_MICROSOFT			0x045e
 | ||||
|  |   | ||||
|  |  /* Product IDs */ | ||||
|  |  #define USB_PID_ADSTECH_USB2_COLD			0xa333 | ||||
|  | @@ -389,4 +390,5 @@
 | ||||
|  |  #define USB_PID_PCTV_2002E_SE                           0x025d | ||||
|  |  #define USB_PID_SVEON_STV27                             0xd3af | ||||
|  |  #define USB_PID_TURBOX_DTT_2000                         0xd3a4 | ||||
|  | +#define USB_PID_XBOX_ONE_TUNER                          0x02d5
 | ||||
|  |  #endif | ||||
|  | diff --git a/drivers/media/usb/dvb-usb/Kconfig b/drivers/media/usb/dvb-usb/Kconfig
 | ||||
|  | index 128eee61..d8e3106d 100644
 | ||||
|  | --- a/drivers/media/usb/dvb-usb/Kconfig
 | ||||
|  | +++ b/drivers/media/usb/dvb-usb/Kconfig
 | ||||
|  | @@ -75,6 +75,7 @@ config DVB_USB_DIB0700
 | ||||
|  |  	select DVB_DIB3000MC if MEDIA_SUBDRV_AUTOSELECT | ||||
|  |  	select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT | ||||
|  |  	select DVB_LGDT3305 if MEDIA_SUBDRV_AUTOSELECT | ||||
|  | +	select DVB_MN88472 if MEDIA_SUBDRV_AUTOSELECT
 | ||||
|  |  	select DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT | ||||
|  |  	select DVB_TUNER_DIB0090 if MEDIA_SUBDRV_AUTOSELECT | ||||
|  |  	select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT | ||||
|  | @@ -83,6 +84,7 @@ config DVB_USB_DIB0700
 | ||||
|  |  	select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT | ||||
|  |  	select MEDIA_TUNER_XC4000 if MEDIA_SUBDRV_AUTOSELECT | ||||
|  |  	select MEDIA_TUNER_MXL5007T if MEDIA_SUBDRV_AUTOSELECT | ||||
|  | +	select MEDIA_TUNER_TDA18250 if MEDIA_SUBDRV_AUTOSELECT
 | ||||
|  |  	help | ||||
|  |  	  Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The | ||||
|  |  	  USB bridge is also present in devices having the DiB7700 DVB-T-USB | ||||
|  | diff --git a/drivers/media/usb/dvb-usb/dib0700.h b/drivers/media/usb/dvb-usb/dib0700.h
 | ||||
|  | index 8fd8f5b4..5f291284 100644
 | ||||
|  | --- a/drivers/media/usb/dvb-usb/dib0700.h
 | ||||
|  | +++ b/drivers/media/usb/dvb-usb/dib0700.h
 | ||||
|  | @@ -51,6 +51,8 @@ struct dib0700_state {
 | ||||
|  |  	int (*read_status)(struct dvb_frontend *, enum fe_status *); | ||||
|  |  	int (*sleep)(struct dvb_frontend* fe); | ||||
|  |  	u8 buf[255]; | ||||
|  | +	struct i2c_client *i2c_client_demod;
 | ||||
|  | +	struct i2c_client *i2c_client_tuner;
 | ||||
|  |  }; | ||||
|  |   | ||||
|  |  extern int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, | ||||
|  | diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c
 | ||||
|  | index 49dd3ea2..e4f3793a 100644
 | ||||
|  | --- a/drivers/media/usb/dvb-usb/dib0700_core.c
 | ||||
|  | +++ b/drivers/media/usb/dvb-usb/dib0700_core.c
 | ||||
|  | @@ -872,10 +872,33 @@ static int dib0700_probe(struct usb_interface *intf,
 | ||||
|  |  	return -ENODEV; | ||||
|  |  } | ||||
|  |   | ||||
|  | +static void dib0700_disconnect(struct usb_interface *intf)
 | ||||
|  | +{
 | ||||
|  | +	struct dvb_usb_device *d = usb_get_intfdata(intf);
 | ||||
|  | +	struct dib0700_state *st = d->priv;
 | ||||
|  | +	struct i2c_client *client;
 | ||||
|  | +
 | ||||
|  | +	/* remove I2C client for tuner */
 | ||||
|  | +	client = st->i2c_client_tuner;
 | ||||
|  | +	if (client) {
 | ||||
|  | +		module_put(client->dev.driver->owner);
 | ||||
|  | +		i2c_unregister_device(client);
 | ||||
|  | +	}
 | ||||
|  | +
 | ||||
|  | +	/* remove I2C client for demodulator */
 | ||||
|  | +	client = st->i2c_client_demod;
 | ||||
|  | +	if (client) {
 | ||||
|  | +		module_put(client->dev.driver->owner);
 | ||||
|  | +		i2c_unregister_device(client);
 | ||||
|  | +	}
 | ||||
|  | +
 | ||||
|  | +	dvb_usb_device_exit(intf);
 | ||||
|  | +}
 | ||||
|  | +
 | ||||
|  |  static struct usb_driver dib0700_driver = { | ||||
|  |  	.name       = "dvb_usb_dib0700", | ||||
|  |  	.probe      = dib0700_probe, | ||||
|  | -	.disconnect = dvb_usb_device_exit,
 | ||||
|  | +	.disconnect = dib0700_disconnect,
 | ||||
|  |  	.id_table   = dib0700_usb_id_table, | ||||
|  |  }; | ||||
|  |   | ||||
|  | diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c
 | ||||
|  | index e1316c7b..2b6c9d3c 100644
 | ||||
|  | --- a/drivers/media/usb/dvb-usb/dib0700_devices.c
 | ||||
|  | +++ b/drivers/media/usb/dvb-usb/dib0700_devices.c
 | ||||
|  | @@ -23,6 +23,8 @@
 | ||||
|  |  #include "dib0090.h" | ||||
|  |  #include "lgdt3305.h" | ||||
|  |  #include "mxl5007t.h" | ||||
|  | +#include "mn88472.h"
 | ||||
|  | +#include "tda18250.h"
 | ||||
|  |   | ||||
|  |  static int force_lna_activation; | ||||
|  |  module_param(force_lna_activation, int, 0644); | ||||
|  | @@ -3705,6 +3708,89 @@
 | ||||
|  |  			  &hcw_mxl5007t_config) == NULL ? -ENODEV : 0; | ||||
|  |  } | ||||
|  |   | ||||
|  | +static int xbox_one_attach(struct dvb_usb_adapter *adap)
 | ||||
|  | +{
 | ||||
|  | +	struct dib0700_state *st = adap->dev->priv;
 | ||||
|  | +	struct i2c_client *client_demod, *client_tuner;
 | ||||
|  | +	struct dvb_usb_device *d = adap->dev;
 | ||||
|  | +	struct mn88472_config mn88472_config = { };
 | ||||
|  | +	struct tda18250_config tda18250_config;
 | ||||
|  | +	struct i2c_board_info info;
 | ||||
|  | +
 | ||||
|  | +	st->fw_use_new_i2c_api = 1;
 | ||||
|  | +	st->disable_streaming_master_mode = 1;
 | ||||
|  | +
 | ||||
|  | +	/* fe power enable */
 | ||||
|  | +	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
 | ||||
|  | +	msleep(30);
 | ||||
|  | +	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
 | ||||
|  | +	msleep(30);
 | ||||
|  | +
 | ||||
|  | +	/* demod reset */
 | ||||
|  | +	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
 | ||||
|  | +	msleep(30);
 | ||||
|  | +	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
 | ||||
|  | +	msleep(30);
 | ||||
|  | +	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
 | ||||
|  | +	msleep(30);
 | ||||
|  | +
 | ||||
|  | +	/* attach demod */
 | ||||
|  | +	mn88472_config.fe = &adap->fe_adap[0].fe;
 | ||||
|  | +	mn88472_config.i2c_wr_max = 22;
 | ||||
|  | +	mn88472_config.xtal = 20500000;
 | ||||
|  | +	mn88472_config.ts_mode = PARALLEL_TS_MODE;
 | ||||
|  | +	mn88472_config.ts_clock = FIXED_TS_CLOCK;
 | ||||
|  | +	memset(&info, 0, sizeof(struct i2c_board_info));
 | ||||
|  | +	strlcpy(info.type, "mn88472", I2C_NAME_SIZE);
 | ||||
|  | +	info.addr = 0x18;
 | ||||
|  | +	info.platform_data = &mn88472_config;
 | ||||
|  | +	request_module(info.type);
 | ||||
|  | +	client_demod = i2c_new_device(&d->i2c_adap, &info);
 | ||||
|  | +	if (client_demod == NULL || client_demod->dev.driver == NULL)
 | ||||
|  | +		goto fail_demod_device;
 | ||||
|  | +	if (!try_module_get(client_demod->dev.driver->owner))
 | ||||
|  | +		goto fail_demod_module;
 | ||||
|  | +
 | ||||
|  | +	st->i2c_client_demod = client_demod;
 | ||||
|  | +
 | ||||
|  | +	adap->fe_adap[0].fe = mn88472_config.get_dvb_frontend(client_demod);
 | ||||
|  | +
 | ||||
|  | +	/* attach tuner */
 | ||||
|  | +	memset(&tda18250_config, 0, sizeof(tda18250_config));
 | ||||
|  | +	tda18250_config.if_dvbt_6 = 3950;
 | ||||
|  | +	tda18250_config.if_dvbt_7 = 4450;
 | ||||
|  | +	tda18250_config.if_dvbt_8 = 4950;
 | ||||
|  | +	tda18250_config.if_dvbc_6 = 4950;
 | ||||
|  | +	tda18250_config.if_dvbc_8 = 4950;
 | ||||
|  | +	tda18250_config.if_atsc = 4079;
 | ||||
|  | +	tda18250_config.loopthrough = true;
 | ||||
|  | +	tda18250_config.xtal_freq = TDA18250_XTAL_FREQ_27MHZ;
 | ||||
|  | +	tda18250_config.fe = adap->fe_adap[0].fe;
 | ||||
|  | +
 | ||||
|  | +	memset(&info, 0, sizeof(struct i2c_board_info));
 | ||||
|  | +	strlcpy(info.type, "tda18250", I2C_NAME_SIZE);
 | ||||
|  | +	info.addr = 0x60;
 | ||||
|  | +	info.platform_data = &tda18250_config;
 | ||||
|  | +
 | ||||
|  | +	request_module(info.type);
 | ||||
|  | +	client_tuner = i2c_new_device(&adap->dev->i2c_adap, &info);
 | ||||
|  | +	if (client_tuner == NULL || client_tuner->dev.driver == NULL)
 | ||||
|  | +		goto fail_tuner_device;
 | ||||
|  | +	if (!try_module_get(client_tuner->dev.driver->owner))
 | ||||
|  | +		goto fail_tuner_module;
 | ||||
|  | +
 | ||||
|  | +	st->i2c_client_tuner = client_tuner;
 | ||||
|  | +	return 0;
 | ||||
|  | +
 | ||||
|  | +fail_tuner_module:
 | ||||
|  | +	i2c_unregister_device(client_tuner);
 | ||||
|  | +fail_tuner_device:
 | ||||
|  | +	module_put(client_demod->dev.driver->owner);
 | ||||
|  | +fail_demod_module:
 | ||||
|  | +	i2c_unregister_device(client_demod);
 | ||||
|  | +fail_demod_device:
 | ||||
|  | +	return -ENODEV;
 | ||||
|  | +}
 | ||||
|  |   | ||||
|  |  /* DVB-USB and USB stuff follows */ | ||||
|  |  struct usb_device_id dib0700_usb_id_table[] = { | ||||
|  | @@ -3794,6 +3880,7 @@
 | ||||
|  |  /* 80 */{ USB_DEVICE(USB_VID_ELGATO,	USB_PID_ELGATO_EYETV_DTT_2) }, | ||||
|  |  	{ USB_DEVICE(USB_VID_PCTV,      USB_PID_PCTV_2002E) }, | ||||
|  |  	{ USB_DEVICE(USB_VID_PCTV,      USB_PID_PCTV_2002E_SE) }, | ||||
|  | +	{ USB_DEVICE(USB_VID_MICROSOFT,	USB_PID_XBOX_ONE_TUNER) },
 | ||||
|  |  	{ 0 }		/* Terminating entry */ | ||||
|  |  }; | ||||
|  |  MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); | ||||
|  | @@ -4959,6 +5046,25 @@
 | ||||
|  |  					    RC_BIT_NEC, | ||||
|  |  			.change_protocol  = dib0700_change_protocol, | ||||
|  |  		}, | ||||
|  | +	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 | ||||
|  | +		.num_adapters = 1,
 | ||||
|  | +		.adapter = {
 | ||||
|  | +			{
 | ||||
|  | +				.num_frontends = 1,
 | ||||
|  | +				.fe = {{
 | ||||
|  | +					.frontend_attach = xbox_one_attach,
 | ||||
|  | +
 | ||||
|  | +					DIB0700_DEFAULT_STREAMING_CONFIG(0x82),
 | ||||
|  | +				} },
 | ||||
|  | +			},
 | ||||
|  | +		},
 | ||||
|  | +		.num_device_descs = 1,
 | ||||
|  | +		.devices = {
 | ||||
|  | +			{ "Microsoft Xbox One Digital TV Tuner",
 | ||||
|  | +				{ &dib0700_usb_id_table[83], NULL },
 | ||||
|  | +				{ NULL },
 | ||||
|  | +			},
 | ||||
|  | +		},
 | ||||
|  |  	}, | ||||
|  |  }; | ||||
|  |   | ||||
|  | -- 
 | ||||
|  | 2.17.1 | ||||
|  | 
 | ||||
								
									
										File diff suppressed because it is too large
									
								
							
						
					| @ -0,0 +1,834 @@ | |||||
|  | ---
 | ||||
|  |  drivers/media/dvb-frontends/mn88472.h        |  45 +- | ||||
|  |  drivers/staging/media/mn88472/mn88472.c      | 525 ++++++++++--------- | ||||
|  |  drivers/staging/media/mn88472/mn88472_priv.h |  11 +- | ||||
|  |  3 files changed, 310 insertions(+), 271 deletions(-) | ||||
|  | 
 | ||||
|  | diff --git a/drivers/media/dvb-frontends/mn88472.h b/drivers/media/dvb-frontends/mn88472.h
 | ||||
|  | index 095294d2..32363252 100644
 | ||||
|  | --- a/drivers/media/dvb-frontends/mn88472.h
 | ||||
|  | +++ b/drivers/media/dvb-frontends/mn88472.h
 | ||||
|  | @@ -19,23 +19,33 @@
 | ||||
|  |   | ||||
|  |  #include <linux/dvb/frontend.h> | ||||
|  |   | ||||
|  | -enum ts_clock {
 | ||||
|  | -	VARIABLE_TS_CLOCK,
 | ||||
|  | -	FIXED_TS_CLOCK,
 | ||||
|  | -};
 | ||||
|  | +/**
 | ||||
|  | + * struct mn88472_config - Platform data for the mn88472 driver
 | ||||
|  | + * @xtal: Clock frequency.
 | ||||
|  | + * @ts_mode: TS mode.
 | ||||
|  | + * @ts_clock: TS clock config.
 | ||||
|  | + * @i2c_wr_max: Max number of bytes driver writes to I2C at once.
 | ||||
|  | + * @get_dvb_frontend: Get DVB frontend.
 | ||||
|  | + */
 | ||||
|  |   | ||||
|  | -enum ts_mode {
 | ||||
|  | -	SERIAL_TS_MODE,
 | ||||
|  | -	PARALLEL_TS_MODE,
 | ||||
|  | -};
 | ||||
|  | +/* Define old names for backward compatibility */
 | ||||
|  | +#define VARIABLE_TS_CLOCK   MN88472_TS_CLK_VARIABLE
 | ||||
|  | +#define FIXED_TS_CLOCK      MN88472_TS_CLK_FIXED
 | ||||
|  | +#define SERIAL_TS_MODE      MN88472_TS_MODE_SERIAL
 | ||||
|  | +#define PARALLEL_TS_MODE    MN88472_TS_MODE_PARALLEL
 | ||||
|  |   | ||||
|  |  struct mn88472_config { | ||||
|  | -	/*
 | ||||
|  | -	 * Max num of bytes given I2C adapter could write at once.
 | ||||
|  | -	 * Default: none
 | ||||
|  | -	 */
 | ||||
|  | -	u16 i2c_wr_max;
 | ||||
|  | +	unsigned int xtal;
 | ||||
|  | +
 | ||||
|  | +#define MN88472_TS_MODE_SERIAL      0
 | ||||
|  | +#define MN88472_TS_MODE_PARALLEL    1
 | ||||
|  | +	int ts_mode;
 | ||||
|  |   | ||||
|  | +#define MN88472_TS_CLK_FIXED        0
 | ||||
|  | +#define MN88472_TS_CLK_VARIABLE     1
 | ||||
|  | +	int ts_clock;
 | ||||
|  | +
 | ||||
|  | +	u16 i2c_wr_max;
 | ||||
|  |   | ||||
|  |  	/* Everything after that is returned by the driver. */ | ||||
|  |   | ||||
|  | @@ -43,14 +53,7 @@ struct mn88472_config {
 | ||||
|  |  	 * DVB frontend. | ||||
|  |  	 */ | ||||
|  |  	struct dvb_frontend **fe; | ||||
|  | -
 | ||||
|  | -	/*
 | ||||
|  | -	 * Xtal frequency.
 | ||||
|  | -	 * Hz
 | ||||
|  | -	 */
 | ||||
|  | -	u32 xtal;
 | ||||
|  | -	int ts_mode;
 | ||||
|  | -	int ts_clock;
 | ||||
|  | +	struct dvb_frontend* (*get_dvb_frontend)(struct i2c_client *);
 | ||||
|  |  }; | ||||
|  |   | ||||
|  |  #endif | ||||
|  | diff --git a/drivers/staging/media/mn88472/mn88472.c b/drivers/staging/media/mn88472/mn88472.c
 | ||||
|  | index cf2e96bc..18fb2df1 100644
 | ||||
|  | --- a/drivers/staging/media/mn88472/mn88472.c
 | ||||
|  | +++ b/drivers/staging/media/mn88472/mn88472.c
 | ||||
|  | @@ -17,28 +17,90 @@
 | ||||
|  |  #include "mn88472_priv.h" | ||||
|  |   | ||||
|  |  static int mn88472_get_tune_settings(struct dvb_frontend *fe, | ||||
|  | -	struct dvb_frontend_tune_settings *s)
 | ||||
|  | +				     struct dvb_frontend_tune_settings *s)
 | ||||
|  |  { | ||||
|  | -	s->min_delay_ms = 800;
 | ||||
|  | +	s->min_delay_ms = 1000;
 | ||||
|  |  	return 0; | ||||
|  |  } | ||||
|  |   | ||||
|  | +static int mn88472_read_status(struct dvb_frontend *fe, enum fe_status *status)
 | ||||
|  | +{
 | ||||
|  | +	struct i2c_client *client = fe->demodulator_priv;
 | ||||
|  | +	struct mn88472_dev *dev = i2c_get_clientdata(client);
 | ||||
|  | +	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 | ||||
|  | +	int ret;
 | ||||
|  | +	unsigned int utmp;
 | ||||
|  | +
 | ||||
|  | +	if (!dev->active) {
 | ||||
|  | +		ret = -EAGAIN;
 | ||||
|  | +		goto err;
 | ||||
|  | +	}
 | ||||
|  | +
 | ||||
|  | +	switch (c->delivery_system) {
 | ||||
|  | +	case SYS_DVBT:
 | ||||
|  | +		ret = regmap_read(dev->regmap[0], 0x7f, &utmp);
 | ||||
|  | +		if (ret)
 | ||||
|  | +			goto err;
 | ||||
|  | +		if ((utmp & 0x0f) >= 0x09)
 | ||||
|  | +			*status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
 | ||||
|  | +				  FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
 | ||||
|  | +		else
 | ||||
|  | +			*status = 0;
 | ||||
|  | +		break;
 | ||||
|  | +	case SYS_DVBT2:
 | ||||
|  | +		ret = regmap_read(dev->regmap[2], 0x92, &utmp);
 | ||||
|  | +		if (ret)
 | ||||
|  | +			goto err;
 | ||||
|  | +		if ((utmp & 0x0f) >= 0x0d)
 | ||||
|  | +			*status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
 | ||||
|  | +				  FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
 | ||||
|  | +		else if ((utmp & 0x0f) >= 0x0a)
 | ||||
|  | +			*status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
 | ||||
|  | +				  FE_HAS_VITERBI;
 | ||||
|  | +		else if ((utmp & 0x0f) >= 0x07)
 | ||||
|  | +			*status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
 | ||||
|  | +		else
 | ||||
|  | +			*status = 0;
 | ||||
|  | +		break;
 | ||||
|  | +	case SYS_DVBC_ANNEX_A:
 | ||||
|  | +		ret = regmap_read(dev->regmap[1], 0x84, &utmp);
 | ||||
|  | +		if (ret)
 | ||||
|  | +			goto err;
 | ||||
|  | +		if ((utmp & 0x0f) >= 0x08)
 | ||||
|  | +			*status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
 | ||||
|  | +				  FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
 | ||||
|  | +		else
 | ||||
|  | +			*status = 0;
 | ||||
|  | +		break;
 | ||||
|  | +	default:
 | ||||
|  | +		ret = -EINVAL;
 | ||||
|  | +		goto err;
 | ||||
|  | +	}
 | ||||
|  | +
 | ||||
|  | +	return 0;
 | ||||
|  | +err:
 | ||||
|  | +	dev_dbg(&client->dev, "failed=%d\n", ret);
 | ||||
|  | +	return ret;
 | ||||
|  | +}
 | ||||
|  | +
 | ||||
|  |  static int mn88472_set_frontend(struct dvb_frontend *fe) | ||||
|  |  { | ||||
|  |  	struct i2c_client *client = fe->demodulator_priv; | ||||
|  |  	struct mn88472_dev *dev = i2c_get_clientdata(client); | ||||
|  |  	struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||||
|  |  	int ret, i; | ||||
|  | -	u32 if_frequency = 0;
 | ||||
|  | -	u64 tmp;
 | ||||
|  | -	u8 delivery_system_val, if_val[3], bw_val[7], bw_val2;
 | ||||
|  | +	unsigned int utmp;
 | ||||
|  | +	u32 if_frequency;
 | ||||
|  | +	u8 buf[3], delivery_system_val, bandwidth_val, *bandwidth_vals_ptr;
 | ||||
|  | +	u8 reg_bank0_b4_val, reg_bank0_cd_val, reg_bank0_d4_val;
 | ||||
|  | +	u8 reg_bank0_d6_val;
 | ||||
|  |   | ||||
|  |  	dev_dbg(&client->dev, | ||||
|  | -			"delivery_system=%d modulation=%d frequency=%d symbol_rate=%d inversion=%d\n",
 | ||||
|  | -			c->delivery_system, c->modulation,
 | ||||
|  | -			c->frequency, c->symbol_rate, c->inversion);
 | ||||
|  | +		"delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%d stream_id=%d\n",
 | ||||
|  | +		c->delivery_system, c->modulation, c->frequency,
 | ||||
|  | +		c->bandwidth_hz, c->symbol_rate, c->inversion, c->stream_id);
 | ||||
|  |   | ||||
|  | -	if (!dev->warm) {
 | ||||
|  | +	if (!dev->active) {
 | ||||
|  |  		ret = -EAGAIN; | ||||
|  |  		goto err; | ||||
|  |  	} | ||||
|  | @@ -46,39 +108,64 @@ static int mn88472_set_frontend(struct dvb_frontend *fe)
 | ||||
|  |  	switch (c->delivery_system) { | ||||
|  |  	case SYS_DVBT: | ||||
|  |  		delivery_system_val = 0x02; | ||||
|  | +		reg_bank0_b4_val = 0x00;
 | ||||
|  | +		reg_bank0_cd_val = 0x1f;
 | ||||
|  | +		reg_bank0_d4_val = 0x0a;
 | ||||
|  | +		reg_bank0_d6_val = 0x48;
 | ||||
|  |  		break; | ||||
|  |  	case SYS_DVBT2: | ||||
|  |  		delivery_system_val = 0x03; | ||||
|  | +		reg_bank0_b4_val = 0xf6;
 | ||||
|  | +		reg_bank0_cd_val = 0x01;
 | ||||
|  | +		reg_bank0_d4_val = 0x09;
 | ||||
|  | +		reg_bank0_d6_val = 0x46;
 | ||||
|  |  		break; | ||||
|  |  	case SYS_DVBC_ANNEX_A: | ||||
|  |  		delivery_system_val = 0x04; | ||||
|  | +		reg_bank0_b4_val = 0x00;
 | ||||
|  | +		reg_bank0_cd_val = 0x17;
 | ||||
|  | +		reg_bank0_d4_val = 0x09;
 | ||||
|  | +		reg_bank0_d6_val = 0x48;
 | ||||
|  |  		break; | ||||
|  |  	default: | ||||
|  |  		ret = -EINVAL; | ||||
|  |  		goto err; | ||||
|  |  	} | ||||
|  |   | ||||
|  | -	if (c->bandwidth_hz <= 5000000) {
 | ||||
|  | -		memcpy(bw_val, "\xe5\x99\x9a\x1b\xa9\x1b\xa9", 7);
 | ||||
|  | -		bw_val2 = 0x03;
 | ||||
|  | -	} else if (c->bandwidth_hz <= 6000000) {
 | ||||
|  | -		/* IF 3570000 Hz, BW 6000000 Hz */
 | ||||
|  | -		memcpy(bw_val, "\xbf\x55\x55\x15\x6b\x15\x6b", 7);
 | ||||
|  | -		bw_val2 = 0x02;
 | ||||
|  | -	} else if (c->bandwidth_hz <= 7000000) {
 | ||||
|  | -		/* IF 4570000 Hz, BW 7000000 Hz */
 | ||||
|  | -		memcpy(bw_val, "\xa4\x00\x00\x0f\x2c\x0f\x2c", 7);
 | ||||
|  | -		bw_val2 = 0x01;
 | ||||
|  | -	} else if (c->bandwidth_hz <= 8000000) {
 | ||||
|  | -		/* IF 4570000 Hz, BW 8000000 Hz */
 | ||||
|  | -		memcpy(bw_val, "\x8f\x80\x00\x08\xee\x08\xee", 7);
 | ||||
|  | -		bw_val2 = 0x00;
 | ||||
|  | -	} else {
 | ||||
|  | -		ret = -EINVAL;
 | ||||
|  | -		goto err;
 | ||||
|  | +	switch (c->delivery_system) {
 | ||||
|  | +	case SYS_DVBT:
 | ||||
|  | +	case SYS_DVBT2:
 | ||||
|  | +		switch (c->bandwidth_hz) {
 | ||||
|  | +		case 5000000:
 | ||||
|  | +			bandwidth_vals_ptr = "\xe5\x99\x9a\x1b\xa9\x1b\xa9";
 | ||||
|  | +			bandwidth_val = 0x03;
 | ||||
|  | +			break;
 | ||||
|  | +		case 6000000:
 | ||||
|  | +			bandwidth_vals_ptr = "\xbf\x55\x55\x15\x6b\x15\x6b";
 | ||||
|  | +			bandwidth_val = 0x02;
 | ||||
|  | +			break;
 | ||||
|  | +		case 7000000:
 | ||||
|  | +			bandwidth_vals_ptr = "\xa4\x00\x00\x0f\x2c\x0f\x2c";
 | ||||
|  | +			bandwidth_val = 0x01;
 | ||||
|  | +			break;
 | ||||
|  | +		case 8000000:
 | ||||
|  | +			bandwidth_vals_ptr = "\x8f\x80\x00\x08\xee\x08\xee";
 | ||||
|  | +			bandwidth_val = 0x00;
 | ||||
|  | +			break;
 | ||||
|  | +		default:
 | ||||
|  | +			ret = -EINVAL;
 | ||||
|  | +			goto err;
 | ||||
|  | +		}
 | ||||
|  | +		break;
 | ||||
|  | +	case SYS_DVBC_ANNEX_A:
 | ||||
|  | +		bandwidth_vals_ptr = NULL;
 | ||||
|  | +		bandwidth_val = 0x00;
 | ||||
|  | +		break;
 | ||||
|  | +	default:
 | ||||
|  | +		break;
 | ||||
|  |  	} | ||||
|  |   | ||||
|  | -	/* program tuner */
 | ||||
|  | +	/* Program tuner */
 | ||||
|  |  	if (fe->ops.tuner_ops.set_params) { | ||||
|  |  		ret = fe->ops.tuner_ops.set_params(fe); | ||||
|  |  		if (ret) | ||||
|  | @@ -91,20 +178,10 @@ static int mn88472_set_frontend(struct dvb_frontend *fe)
 | ||||
|  |  			goto err; | ||||
|  |   | ||||
|  |  		dev_dbg(&client->dev, "get_if_frequency=%d\n", if_frequency); | ||||
|  | -	}
 | ||||
|  | -
 | ||||
|  | -	/* Calculate IF registers ( (1<<24)*IF / Xtal ) */
 | ||||
|  | -	tmp =  div_u64(if_frequency * (u64)(1<<24) + (dev->xtal / 2),
 | ||||
|  | -				   dev->xtal);
 | ||||
|  | -	if_val[0] = ((tmp >> 16) & 0xff);
 | ||||
|  | -	if_val[1] = ((tmp >>  8) & 0xff);
 | ||||
|  | -	if_val[2] = ((tmp >>  0) & 0xff);
 | ||||
|  | -
 | ||||
|  | -	ret = regmap_write(dev->regmap[2], 0xfb, 0x13);
 | ||||
|  | -	ret = regmap_write(dev->regmap[2], 0xef, 0x13);
 | ||||
|  | -	ret = regmap_write(dev->regmap[2], 0xf9, 0x13);
 | ||||
|  | -	if (ret)
 | ||||
|  | +	} else {
 | ||||
|  | +		ret = -EINVAL;
 | ||||
|  |  		goto err; | ||||
|  | +	}
 | ||||
|  |   | ||||
|  |  	ret = regmap_write(dev->regmap[2], 0x00, 0x66); | ||||
|  |  	if (ret) | ||||
|  | @@ -118,157 +195,81 @@ static int mn88472_set_frontend(struct dvb_frontend *fe)
 | ||||
|  |  	ret = regmap_write(dev->regmap[2], 0x03, delivery_system_val); | ||||
|  |  	if (ret) | ||||
|  |  		goto err; | ||||
|  | -	ret = regmap_write(dev->regmap[2], 0x04, bw_val2);
 | ||||
|  | +	ret = regmap_write(dev->regmap[2], 0x04, bandwidth_val);
 | ||||
|  |  	if (ret) | ||||
|  |  		goto err; | ||||
|  |   | ||||
|  | -	for (i = 0; i < sizeof(if_val); i++) {
 | ||||
|  | -		ret = regmap_write(dev->regmap[2], 0x10 + i, if_val[i]);
 | ||||
|  | +	/* IF */
 | ||||
|  | +	utmp = DIV_ROUND_CLOSEST_ULL((u64)if_frequency * 0x1000000, dev->clk);
 | ||||
|  | +	buf[0] = (utmp >> 16) & 0xff;
 | ||||
|  | +	buf[1] = (utmp >>  8) & 0xff;
 | ||||
|  | +	buf[2] = (utmp >>  0) & 0xff;
 | ||||
|  | +	for (i = 0; i < 3; i++) {
 | ||||
|  | +		ret = regmap_write(dev->regmap[2], 0x10 + i, buf[i]);
 | ||||
|  |  		if (ret) | ||||
|  |  			goto err; | ||||
|  |  	} | ||||
|  |   | ||||
|  | -	for (i = 0; i < sizeof(bw_val); i++) {
 | ||||
|  | -		ret = regmap_write(dev->regmap[2], 0x13 + i, bw_val[i]);
 | ||||
|  | -		if (ret)
 | ||||
|  | -			goto err;
 | ||||
|  | +	/* Bandwidth */
 | ||||
|  | +	if (bandwidth_vals_ptr) {
 | ||||
|  | +		for (i = 0; i < 7; i++) {
 | ||||
|  | +			ret = regmap_write(dev->regmap[2], 0x13 + i,
 | ||||
|  | +					   bandwidth_vals_ptr[i]);
 | ||||
|  | +			if (ret)
 | ||||
|  | +				goto err;
 | ||||
|  | +		}
 | ||||
|  |  	} | ||||
|  |   | ||||
|  | +	ret = regmap_write(dev->regmap[0], 0xb4, reg_bank0_b4_val);
 | ||||
|  | +	if (ret)
 | ||||
|  | +		goto err;
 | ||||
|  | +	ret = regmap_write(dev->regmap[0], 0xcd, reg_bank0_cd_val);
 | ||||
|  | +	if (ret)
 | ||||
|  | +		goto err;
 | ||||
|  | +	ret = regmap_write(dev->regmap[0], 0xd4, reg_bank0_d4_val);
 | ||||
|  | +	if (ret)
 | ||||
|  | +		goto err;
 | ||||
|  | +	ret = regmap_write(dev->regmap[0], 0xd6, reg_bank0_d6_val);
 | ||||
|  | +	if (ret)
 | ||||
|  | +		goto err;
 | ||||
|  | +
 | ||||
|  |  	switch (c->delivery_system) { | ||||
|  |  	case SYS_DVBT: | ||||
|  |  		ret = regmap_write(dev->regmap[0], 0x07, 0x26); | ||||
|  | -		ret = regmap_write(dev->regmap[0], 0xb0, 0x0a);
 | ||||
|  | -		ret = regmap_write(dev->regmap[0], 0xb4, 0x00);
 | ||||
|  | -		ret = regmap_write(dev->regmap[0], 0xcd, 0x1f);
 | ||||
|  | -		ret = regmap_write(dev->regmap[0], 0xd4, 0x0a);
 | ||||
|  | -		ret = regmap_write(dev->regmap[0], 0xd6, 0x48);
 | ||||
|  | +		if (ret)
 | ||||
|  | +			goto err;
 | ||||
|  |  		ret = regmap_write(dev->regmap[0], 0x00, 0xba); | ||||
|  | +		if (ret)
 | ||||
|  | +			goto err;
 | ||||
|  |  		ret = regmap_write(dev->regmap[0], 0x01, 0x13); | ||||
|  |  		if (ret) | ||||
|  |  			goto err; | ||||
|  |  		break; | ||||
|  |  	case SYS_DVBT2: | ||||
|  |  		ret = regmap_write(dev->regmap[2], 0x2b, 0x13); | ||||
|  | +		if (ret)
 | ||||
|  | +			goto err;
 | ||||
|  |  		ret = regmap_write(dev->regmap[2], 0x4f, 0x05); | ||||
|  | +		if (ret)
 | ||||
|  | +			goto err;
 | ||||
|  |  		ret = regmap_write(dev->regmap[1], 0xf6, 0x05); | ||||
|  | -		ret = regmap_write(dev->regmap[0], 0xb0, 0x0a);
 | ||||
|  | -		ret = regmap_write(dev->regmap[0], 0xb4, 0xf6);
 | ||||
|  | -		ret = regmap_write(dev->regmap[0], 0xcd, 0x01);
 | ||||
|  | -		ret = regmap_write(dev->regmap[0], 0xd4, 0x09);
 | ||||
|  | -		ret = regmap_write(dev->regmap[0], 0xd6, 0x46);
 | ||||
|  | -		ret = regmap_write(dev->regmap[2], 0x30, 0x80);
 | ||||
|  | -		ret = regmap_write(dev->regmap[2], 0x32, 0x00);
 | ||||
|  |  		if (ret) | ||||
|  |  			goto err; | ||||
|  | -		break;
 | ||||
|  | -	case SYS_DVBC_ANNEX_A:
 | ||||
|  | -		ret = regmap_write(dev->regmap[0], 0xb0, 0x0b);
 | ||||
|  | -		ret = regmap_write(dev->regmap[0], 0xb4, 0x00);
 | ||||
|  | -		ret = regmap_write(dev->regmap[0], 0xcd, 0x17);
 | ||||
|  | -		ret = regmap_write(dev->regmap[0], 0xd4, 0x09);
 | ||||
|  | -		ret = regmap_write(dev->regmap[0], 0xd6, 0x48);
 | ||||
|  | -		ret = regmap_write(dev->regmap[1], 0x00, 0xb0);
 | ||||
|  | +		ret = regmap_write(dev->regmap[2], 0x32, c->stream_id);
 | ||||
|  |  		if (ret) | ||||
|  |  			goto err; | ||||
|  |  		break; | ||||
|  | -	default:
 | ||||
|  | -		ret = -EINVAL;
 | ||||
|  | -		goto err;
 | ||||
|  | -	}
 | ||||
|  | -
 | ||||
|  | -	ret = regmap_write(dev->regmap[0], 0x46, 0x00);
 | ||||
|  | -	ret = regmap_write(dev->regmap[0], 0xae, 0x00);
 | ||||
|  | -
 | ||||
|  | -	switch (dev->ts_mode) {
 | ||||
|  | -	case SERIAL_TS_MODE:
 | ||||
|  | -		ret = regmap_write(dev->regmap[2], 0x08, 0x1d);
 | ||||
|  | -		break;
 | ||||
|  | -	case PARALLEL_TS_MODE:
 | ||||
|  | -		ret = regmap_write(dev->regmap[2], 0x08, 0x00);
 | ||||
|  | +	case SYS_DVBC_ANNEX_A:
 | ||||
|  |  		break; | ||||
|  |  	default: | ||||
|  | -		dev_dbg(&client->dev, "ts_mode error: %d\n", dev->ts_mode);
 | ||||
|  | -		ret = -EINVAL;
 | ||||
|  | -		goto err;
 | ||||
|  | -	}
 | ||||
|  | -
 | ||||
|  | -	switch (dev->ts_clock) {
 | ||||
|  | -	case VARIABLE_TS_CLOCK:
 | ||||
|  | -		ret = regmap_write(dev->regmap[0], 0xd9, 0xe3);
 | ||||
|  |  		break; | ||||
|  | -	case FIXED_TS_CLOCK:
 | ||||
|  | -		ret = regmap_write(dev->regmap[0], 0xd9, 0xe1);
 | ||||
|  | -		break;
 | ||||
|  | -	default:
 | ||||
|  | -		dev_dbg(&client->dev, "ts_clock error: %d\n", dev->ts_clock);
 | ||||
|  | -		ret = -EINVAL;
 | ||||
|  | -		goto err;
 | ||||
|  |  	} | ||||
|  |   | ||||
|  | -	/* Reset demod */
 | ||||
|  | +	/* Reset FSM */
 | ||||
|  |  	ret = regmap_write(dev->regmap[2], 0xf8, 0x9f); | ||||
|  |  	if (ret) | ||||
|  |  		goto err; | ||||
|  |   | ||||
|  | -	dev->delivery_system = c->delivery_system;
 | ||||
|  | -
 | ||||
|  | -	return 0;
 | ||||
|  | -err:
 | ||||
|  | -	dev_dbg(&client->dev, "failed=%d\n", ret);
 | ||||
|  | -	return ret;
 | ||||
|  | -}
 | ||||
|  | -
 | ||||
|  | -static int mn88472_read_status(struct dvb_frontend *fe, enum fe_status *status)
 | ||||
|  | -{
 | ||||
|  | -	struct i2c_client *client = fe->demodulator_priv;
 | ||||
|  | -	struct mn88472_dev *dev = i2c_get_clientdata(client);
 | ||||
|  | -	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 | ||||
|  | -	int ret;
 | ||||
|  | -	unsigned int utmp;
 | ||||
|  | -	int lock = 0;
 | ||||
|  | -
 | ||||
|  | -	*status = 0;
 | ||||
|  | -
 | ||||
|  | -	if (!dev->warm) {
 | ||||
|  | -		ret = -EAGAIN;
 | ||||
|  | -		goto err;
 | ||||
|  | -	}
 | ||||
|  | -
 | ||||
|  | -	switch (c->delivery_system) {
 | ||||
|  | -	case SYS_DVBT:
 | ||||
|  | -		ret = regmap_read(dev->regmap[0], 0x7F, &utmp);
 | ||||
|  | -		if (ret)
 | ||||
|  | -			goto err;
 | ||||
|  | -		if ((utmp & 0xF) >= 0x09)
 | ||||
|  | -			lock = 1;
 | ||||
|  | -		break;
 | ||||
|  | -	case SYS_DVBT2:
 | ||||
|  | -		ret = regmap_read(dev->regmap[2], 0x92, &utmp);
 | ||||
|  | -		if (ret)
 | ||||
|  | -			goto err;
 | ||||
|  | -		if ((utmp & 0xF) >= 0x07)
 | ||||
|  | -			*status |= FE_HAS_SIGNAL;
 | ||||
|  | -		if ((utmp & 0xF) >= 0x0a)
 | ||||
|  | -			*status |= FE_HAS_CARRIER;
 | ||||
|  | -		if ((utmp & 0xF) >= 0x0d)
 | ||||
|  | -			*status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
 | ||||
|  | -		break;
 | ||||
|  | -	case SYS_DVBC_ANNEX_A:
 | ||||
|  | -		ret = regmap_read(dev->regmap[1], 0x84, &utmp);
 | ||||
|  | -		if (ret)
 | ||||
|  | -			goto err;
 | ||||
|  | -		if ((utmp & 0xF) >= 0x08)
 | ||||
|  | -			lock = 1;
 | ||||
|  | -		break;
 | ||||
|  | -	default:
 | ||||
|  | -		ret = -EINVAL;
 | ||||
|  | -		goto err;
 | ||||
|  | -	}
 | ||||
|  | -
 | ||||
|  | -	if (lock)
 | ||||
|  | -		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
 | ||||
|  | -				FE_HAS_SYNC | FE_HAS_LOCK;
 | ||||
|  | -
 | ||||
|  |  	return 0; | ||||
|  |  err: | ||||
|  |  	dev_dbg(&client->dev, "failed=%d\n", ret); | ||||
|  | @@ -279,93 +280,107 @@ static int mn88472_init(struct dvb_frontend *fe)
 | ||||
|  |  { | ||||
|  |  	struct i2c_client *client = fe->demodulator_priv; | ||||
|  |  	struct mn88472_dev *dev = i2c_get_clientdata(client); | ||||
|  | -	int ret, len, remaining;
 | ||||
|  | -	const struct firmware *fw = NULL;
 | ||||
|  | -	u8 *fw_file = MN88472_FIRMWARE;
 | ||||
|  | -	unsigned int tmp;
 | ||||
|  | +	int ret, len, rem;
 | ||||
|  | +	unsigned int utmp;
 | ||||
|  | +	const struct firmware *firmware;
 | ||||
|  | +	const char *name = MN88472_FIRMWARE;
 | ||||
|  |   | ||||
|  |  	dev_dbg(&client->dev, "\n"); | ||||
|  |   | ||||
|  | -	/* set cold state by default */
 | ||||
|  | -	dev->warm = false;
 | ||||
|  | -
 | ||||
|  | -	/* power on */
 | ||||
|  | +	/* Power up */
 | ||||
|  |  	ret = regmap_write(dev->regmap[2], 0x05, 0x00); | ||||
|  |  	if (ret) | ||||
|  |  		goto err; | ||||
|  | -
 | ||||
|  | -	ret = regmap_bulk_write(dev->regmap[2], 0x0b, "\x00\x00", 2);
 | ||||
|  | +	ret = regmap_write(dev->regmap[2], 0x0b, 0x00);
 | ||||
|  |  	if (ret) | ||||
|  |  		goto err; | ||||
|  | -
 | ||||
|  | -	/* check if firmware is already running */
 | ||||
|  | -	ret = regmap_read(dev->regmap[0], 0xf5, &tmp);
 | ||||
|  | +	ret = regmap_write(dev->regmap[2], 0x0c, 0x00);
 | ||||
|  |  	if (ret) | ||||
|  |  		goto err; | ||||
|  |   | ||||
|  | -	if (!(tmp & 0x1)) {
 | ||||
|  | -		dev_info(&client->dev, "firmware already running\n");
 | ||||
|  | -		dev->warm = true;
 | ||||
|  | -		return 0;
 | ||||
|  | -	}
 | ||||
|  | +	/* Check if firmware is already running */
 | ||||
|  | +	ret = regmap_read(dev->regmap[0], 0xf5, &utmp);
 | ||||
|  | +	if (ret)
 | ||||
|  | +		goto err;
 | ||||
|  | +	if (!(utmp & 0x01))
 | ||||
|  | +		goto warm;
 | ||||
|  |   | ||||
|  | -	/* request the firmware, this will block and timeout */
 | ||||
|  | -	ret = request_firmware(&fw, fw_file, &client->dev);
 | ||||
|  | +	ret = request_firmware(&firmware, name, &client->dev);
 | ||||
|  |  	if (ret) { | ||||
|  | -		dev_err(&client->dev, "firmare file '%s' not found\n",
 | ||||
|  | -				fw_file);
 | ||||
|  | +		dev_err(&client->dev, "firmware file '%s' not found\n", name);
 | ||||
|  |  		goto err; | ||||
|  |  	} | ||||
|  |   | ||||
|  | -	dev_info(&client->dev, "downloading firmware from file '%s'\n",
 | ||||
|  | -			fw_file);
 | ||||
|  | +	dev_info(&client->dev, "downloading firmware from file '%s'\n", name);
 | ||||
|  |   | ||||
|  |  	ret = regmap_write(dev->regmap[0], 0xf5, 0x03); | ||||
|  |  	if (ret) | ||||
|  | -		goto firmware_release;
 | ||||
|  | -
 | ||||
|  | -	for (remaining = fw->size; remaining > 0;
 | ||||
|  | -			remaining -= (dev->i2c_wr_max - 1)) {
 | ||||
|  | -		len = remaining;
 | ||||
|  | -		if (len > (dev->i2c_wr_max - 1))
 | ||||
|  | -			len = dev->i2c_wr_max - 1;
 | ||||
|  | +		goto err_release_firmware;
 | ||||
|  |   | ||||
|  | +	for (rem = firmware->size; rem > 0; rem -= (dev->i2c_write_max - 1)) {
 | ||||
|  | +		len = min(dev->i2c_write_max - 1, rem);
 | ||||
|  |  		ret = regmap_bulk_write(dev->regmap[0], 0xf6, | ||||
|  | -				&fw->data[fw->size - remaining], len);
 | ||||
|  | +					&firmware->data[firmware->size - rem],
 | ||||
|  | +					len);
 | ||||
|  |  		if (ret) { | ||||
|  | -			dev_err(&client->dev,
 | ||||
|  | -					"firmware download failed=%d\n", ret);
 | ||||
|  | -			goto firmware_release;
 | ||||
|  | +			dev_err(&client->dev, "firmware download failed %d\n",
 | ||||
|  | +				ret);
 | ||||
|  | +			goto err_release_firmware;
 | ||||
|  |  		} | ||||
|  |  	} | ||||
|  |   | ||||
|  | -	/* parity check of firmware */
 | ||||
|  | -	ret = regmap_read(dev->regmap[0], 0xf8, &tmp);
 | ||||
|  | -	if (ret) {
 | ||||
|  | -		dev_err(&client->dev,
 | ||||
|  | -				"parity reg read failed=%d\n", ret);
 | ||||
|  | -		goto firmware_release;
 | ||||
|  | -	}
 | ||||
|  | -	if (tmp & 0x10) {
 | ||||
|  | -		dev_err(&client->dev,
 | ||||
|  | -				"firmware parity check failed=0x%x\n", tmp);
 | ||||
|  | -		goto firmware_release;
 | ||||
|  | +	/* Parity check of firmware */
 | ||||
|  | +	ret = regmap_read(dev->regmap[0], 0xf8, &utmp);
 | ||||
|  | +	if (ret)
 | ||||
|  | +		goto err_release_firmware;
 | ||||
|  | +	if (utmp & 0x10) {
 | ||||
|  | +		ret = -EINVAL;
 | ||||
|  | +		dev_err(&client->dev, "firmware did not run\n");
 | ||||
|  | +		goto err_release_firmware;
 | ||||
|  |  	} | ||||
|  | -	dev_err(&client->dev, "firmware parity check succeeded=0x%x\n", tmp);
 | ||||
|  |   | ||||
|  |  	ret = regmap_write(dev->regmap[0], 0xf5, 0x00); | ||||
|  |  	if (ret) | ||||
|  | -		goto firmware_release;
 | ||||
|  | +		goto err_release_firmware;
 | ||||
|  | +
 | ||||
|  | +	release_firmware(firmware);
 | ||||
|  | +warm:
 | ||||
|  | +	/* TS config */
 | ||||
|  | +	switch (dev->ts_mode) {
 | ||||
|  | +	case SERIAL_TS_MODE:
 | ||||
|  | +		utmp = 0x1d;
 | ||||
|  | +		break;
 | ||||
|  | +	case PARALLEL_TS_MODE:
 | ||||
|  | +		utmp = 0x00;
 | ||||
|  | +		break;
 | ||||
|  | +	default:
 | ||||
|  | +		ret = -EINVAL;
 | ||||
|  | +		goto err;
 | ||||
|  | +	}
 | ||||
|  | +	ret = regmap_write(dev->regmap[2], 0x08, utmp);
 | ||||
|  | +	if (ret)
 | ||||
|  | +		goto err;
 | ||||
|  |   | ||||
|  | -	release_firmware(fw);
 | ||||
|  | -	fw = NULL;
 | ||||
|  | +	switch (dev->ts_clk) {
 | ||||
|  | +	case VARIABLE_TS_CLOCK:
 | ||||
|  | +		utmp = 0xe3;
 | ||||
|  | +		break;
 | ||||
|  | +	case FIXED_TS_CLOCK:
 | ||||
|  | +		utmp = 0xe1;
 | ||||
|  | +		break;
 | ||||
|  | +	default:
 | ||||
|  | +		ret = -EINVAL;
 | ||||
|  | +		goto err;
 | ||||
|  | +	}
 | ||||
|  | +	ret = regmap_write(dev->regmap[0], 0xd9, utmp);
 | ||||
|  | +	if (ret)
 | ||||
|  | +		goto err;
 | ||||
|  |   | ||||
|  | -	/* warm state */
 | ||||
|  | -	dev->warm = true;
 | ||||
|  | +	dev->active = true;
 | ||||
|  |   | ||||
|  |  	return 0; | ||||
|  | -firmware_release:
 | ||||
|  | -	release_firmware(fw);
 | ||||
|  | +err_release_firmware:
 | ||||
|  | +	release_firmware(firmware);
 | ||||
|  |  err: | ||||
|  |  	dev_dbg(&client->dev, "failed=%d\n", ret); | ||||
|  |  	return ret; | ||||
|  | @@ -379,18 +394,17 @@ static int mn88472_sleep(struct dvb_frontend *fe)
 | ||||
|  |   | ||||
|  |  	dev_dbg(&client->dev, "\n"); | ||||
|  |   | ||||
|  | -	/* power off */
 | ||||
|  | +	/* Power down */
 | ||||
|  | +	ret = regmap_write(dev->regmap[2], 0x0c, 0x30);
 | ||||
|  | +	if (ret)
 | ||||
|  | +		goto err;
 | ||||
|  |  	ret = regmap_write(dev->regmap[2], 0x0b, 0x30); | ||||
|  | -
 | ||||
|  |  	if (ret) | ||||
|  |  		goto err; | ||||
|  | -
 | ||||
|  |  	ret = regmap_write(dev->regmap[2], 0x05, 0x3e); | ||||
|  |  	if (ret) | ||||
|  |  		goto err; | ||||
|  |   | ||||
|  | -	dev->delivery_system = SYS_UNDEFINED;
 | ||||
|  | -
 | ||||
|  |  	return 0; | ||||
|  |  err: | ||||
|  |  	dev_dbg(&client->dev, "failed=%d\n", ret); | ||||
|  | @@ -434,10 +448,19 @@ static struct dvb_frontend_ops mn88472_ops = {
 | ||||
|  |  	.read_status = mn88472_read_status, | ||||
|  |  }; | ||||
|  |   | ||||
|  | +static struct dvb_frontend *mn88472_get_dvb_frontend(struct i2c_client *client)
 | ||||
|  | +{
 | ||||
|  | +	struct mn88472_dev *dev = i2c_get_clientdata(client);
 | ||||
|  | +
 | ||||
|  | +	dev_dbg(&client->dev, "\n");
 | ||||
|  | +
 | ||||
|  | +	return &dev->fe;
 | ||||
|  | +}
 | ||||
|  | +
 | ||||
|  |  static int mn88472_probe(struct i2c_client *client, | ||||
|  | -		const struct i2c_device_id *id)
 | ||||
|  | +			 const struct i2c_device_id *id)
 | ||||
|  |  { | ||||
|  | -	struct mn88472_config *config = client->dev.platform_data;
 | ||||
|  | +	struct mn88472_config *pdata = client->dev.platform_data;
 | ||||
|  |  	struct mn88472_dev *dev; | ||||
|  |  	int ret; | ||||
|  |  	unsigned int utmp; | ||||
|  | @@ -448,23 +471,16 @@ static int mn88472_probe(struct i2c_client *client,
 | ||||
|  |   | ||||
|  |  	dev_dbg(&client->dev, "\n"); | ||||
|  |   | ||||
|  | -	/* Caller really need to provide pointer for frontend we create. */
 | ||||
|  | -	if (config->fe == NULL) {
 | ||||
|  | -		dev_err(&client->dev, "frontend pointer not defined\n");
 | ||||
|  | -		ret = -EINVAL;
 | ||||
|  | -		goto err;
 | ||||
|  | -	}
 | ||||
|  | -
 | ||||
|  |  	dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||||
|  | -	if (dev == NULL) {
 | ||||
|  | +	if (!dev) {
 | ||||
|  |  		ret = -ENOMEM; | ||||
|  |  		goto err; | ||||
|  |  	} | ||||
|  |   | ||||
|  | -	dev->i2c_wr_max = config->i2c_wr_max;
 | ||||
|  | -	dev->xtal = config->xtal;
 | ||||
|  | -	dev->ts_mode = config->ts_mode;
 | ||||
|  | -	dev->ts_clock = config->ts_clock;
 | ||||
|  | +	dev->i2c_write_max = pdata->i2c_wr_max ? pdata->i2c_wr_max : ~0;
 | ||||
|  | +	dev->clk = pdata->xtal;
 | ||||
|  | +	dev->ts_mode = pdata->ts_mode;
 | ||||
|  | +	dev->ts_clk = pdata->ts_clock;
 | ||||
|  |  	dev->client[0] = client; | ||||
|  |  	dev->regmap[0] = regmap_init_i2c(dev->client[0], ®map_config); | ||||
|  |  	if (IS_ERR(dev->regmap[0])) { | ||||
|  | @@ -472,18 +488,28 @@ static int mn88472_probe(struct i2c_client *client,
 | ||||
|  |  		goto err_kfree; | ||||
|  |  	} | ||||
|  |   | ||||
|  | -	/* check demod answers to I2C */
 | ||||
|  | -	ret = regmap_read(dev->regmap[0], 0x00, &utmp);
 | ||||
|  | +	/* Check demod answers with correct chip id */
 | ||||
|  | +	ret = regmap_read(dev->regmap[0], 0xff, &utmp);
 | ||||
|  |  	if (ret) | ||||
|  |  		goto err_regmap_0_regmap_exit; | ||||
|  |   | ||||
|  | +	dev_dbg(&client->dev, "chip id=%02x\n", utmp);
 | ||||
|  | +
 | ||||
|  | +	if (utmp != 0x02) {
 | ||||
|  | +		ret = -ENODEV;
 | ||||
|  | +		goto err_regmap_0_regmap_exit;
 | ||||
|  | +	}
 | ||||
|  | +
 | ||||
|  |  	/* | ||||
|  | -	 * Chip has three I2C addresses for different register pages. Used
 | ||||
|  | +	 * Chip has three I2C addresses for different register banks. Used
 | ||||
|  |  	 * addresses are 0x18, 0x1a and 0x1c. We register two dummy clients, | ||||
|  | -	 * 0x1a and 0x1c, in order to get own I2C client for each register page.
 | ||||
|  | +	 * 0x1a and 0x1c, in order to get own I2C client for each register bank.
 | ||||
|  | +	 *
 | ||||
|  | +	 * Also, register bank 2 do not support sequential I/O. Only single
 | ||||
|  | +	 * register write or read is allowed to that bank.
 | ||||
|  |  	 */ | ||||
|  |  	dev->client[1] = i2c_new_dummy(client->adapter, 0x1a); | ||||
|  | -	if (dev->client[1] == NULL) {
 | ||||
|  | +	if (!dev->client[1]) {
 | ||||
|  |  		ret = -ENODEV; | ||||
|  |  		dev_err(&client->dev, "I2C registration failed\n"); | ||||
|  |  		if (ret) | ||||
|  | @@ -497,7 +523,7 @@ static int mn88472_probe(struct i2c_client *client,
 | ||||
|  |  	i2c_set_clientdata(dev->client[1], dev); | ||||
|  |   | ||||
|  |  	dev->client[2] = i2c_new_dummy(client->adapter, 0x1c); | ||||
|  | -	if (dev->client[2] == NULL) {
 | ||||
|  | +	if (!dev->client[2]) {
 | ||||
|  |  		ret = -ENODEV; | ||||
|  |  		dev_err(&client->dev, "2nd I2C registration failed\n"); | ||||
|  |  		if (ret) | ||||
|  | @@ -510,15 +536,25 @@ static int mn88472_probe(struct i2c_client *client,
 | ||||
|  |  	} | ||||
|  |  	i2c_set_clientdata(dev->client[2], dev); | ||||
|  |   | ||||
|  | -	/* create dvb_frontend */
 | ||||
|  | +	/* Sleep because chip is active by default */
 | ||||
|  | +	ret = regmap_write(dev->regmap[2], 0x05, 0x3e);
 | ||||
|  | +	if (ret)
 | ||||
|  | +		goto err_regmap_2_regmap_exit;
 | ||||
|  | +
 | ||||
|  | +	/* Create dvb frontend */
 | ||||
|  |  	memcpy(&dev->fe.ops, &mn88472_ops, sizeof(struct dvb_frontend_ops)); | ||||
|  |  	dev->fe.demodulator_priv = client; | ||||
|  | -	*config->fe = &dev->fe;
 | ||||
|  | +	*pdata->fe = &dev->fe;
 | ||||
|  |  	i2c_set_clientdata(client, dev); | ||||
|  |   | ||||
|  | -	dev_info(&client->dev, "Panasonic MN88472 successfully attached\n");
 | ||||
|  | -	return 0;
 | ||||
|  | +	/* Setup callbacks */
 | ||||
|  | +	pdata->get_dvb_frontend = mn88472_get_dvb_frontend;
 | ||||
|  |   | ||||
|  | +	dev_info(&client->dev, "Panasonic MN88472 successfully identified\n");
 | ||||
|  | +
 | ||||
|  | +	return 0;
 | ||||
|  | +err_regmap_2_regmap_exit:
 | ||||
|  | +	regmap_exit(dev->regmap[2]);
 | ||||
|  |  err_client_2_i2c_unregister_device: | ||||
|  |  	i2c_unregister_device(dev->client[2]); | ||||
|  |  err_regmap_1_regmap_exit: | ||||
|  | @@ -561,11 +597,12 @@ MODULE_DEVICE_TABLE(i2c, mn88472_id_table);
 | ||||
|  |   | ||||
|  |  static struct i2c_driver mn88472_driver = { | ||||
|  |  	.driver = { | ||||
|  | -		.name	= "mn88472",
 | ||||
|  | +		.name = "mn88472",
 | ||||
|  | +		.suppress_bind_attrs = true,
 | ||||
|  |  	}, | ||||
|  | -	.probe		= mn88472_probe,
 | ||||
|  | -	.remove		= mn88472_remove,
 | ||||
|  | -	.id_table	= mn88472_id_table,
 | ||||
|  | +	.probe    = mn88472_probe,
 | ||||
|  | +	.remove   = mn88472_remove,
 | ||||
|  | +	.id_table = mn88472_id_table,
 | ||||
|  |  }; | ||||
|  |   | ||||
|  |  module_i2c_driver(mn88472_driver); | ||||
|  | diff --git a/drivers/staging/media/mn88472/mn88472_priv.h b/drivers/staging/media/mn88472/mn88472_priv.h
 | ||||
|  | index 1a0de9e4..cdf2597a 100644
 | ||||
|  | --- a/drivers/staging/media/mn88472/mn88472_priv.h
 | ||||
|  | +++ b/drivers/staging/media/mn88472/mn88472_priv.h
 | ||||
|  | @@ -28,12 +28,11 @@ struct mn88472_dev {
 | ||||
|  |  	struct i2c_client *client[3]; | ||||
|  |  	struct regmap *regmap[3]; | ||||
|  |  	struct dvb_frontend fe; | ||||
|  | -	u16 i2c_wr_max;
 | ||||
|  | -	enum fe_delivery_system delivery_system;
 | ||||
|  | -	bool warm; /* FW running */
 | ||||
|  | -	u32 xtal;
 | ||||
|  | -	int ts_mode;
 | ||||
|  | -	int ts_clock;
 | ||||
|  | +	u16 i2c_write_max;
 | ||||
|  | +	unsigned int clk;
 | ||||
|  | +	unsigned int active:1;
 | ||||
|  | +	unsigned int ts_mode:1;
 | ||||
|  | +	unsigned int ts_clk:1;
 | ||||
|  |  }; | ||||
|  |   | ||||
|  |  #endif | ||||
|  | -- 
 | ||||
|  | 2.17.1 | ||||
|  | 
 | ||||
| @ -0,0 +1,629 @@ | |||||
|  | diff -Nur a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx
 | ||||
|  | --- a/Documentation/video4linux/CARDLIST.em28xx	2017-07-31 15:25:12.000000000 +0200
 | ||||
|  | +++ b/Documentation/video4linux/CARDLIST.em28xx	2019-04-02 08:35:00.919204500 +0200
 | ||||
|  | @@ -96,3 +96,5 @@
 | ||||
|  |   95 -> Leadtek VC100                            (em2861)        [0413:6f07] | ||||
|  |   96 -> Terratec Cinergy T2 Stick HD             (em28178) | ||||
|  |   97 -> Elgato EyeTV Hybrid 2008 INT             (em2884)        [0fd9:0018] | ||||
|  | + 98 -> Hauppauge WinTV-dualHD DVB               (em28174)       [2040:0265]
 | ||||
|  | + 
 | ||||
|  | diff -Nur a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h
 | ||||
|  | --- a/drivers/media/usb/em28xx/em28xx.h	2017-07-31 15:25:15.000000000 +0200
 | ||||
|  | +++ b/drivers/media/usb/em28xx/em28xx.h	2019-04-02 08:30:40.196114900 +0200
 | ||||
|  | @@ -145,6 +145,7 @@
 | ||||
|  |  #define EM2861_BOARD_LEADTEK_VC100                95 | ||||
|  |  #define EM28178_BOARD_TERRATEC_T2_STICK_HD        96 | ||||
|  |  #define EM2884_BOARD_ELGATO_EYETV_HYBRID_2008     97 | ||||
|  | +#define EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB  98
 | ||||
|  |   | ||||
|  |  /* Limits minimum and default number of buffers */ | ||||
|  |  #define EM28XX_MIN_BUF 4 | ||||
|  | @@ -213,6 +214,9 @@
 | ||||
|  |  /* max. number of button state polling addresses */ | ||||
|  |  #define EM28XX_NUM_BUTTON_ADDRESSES_MAX		5 | ||||
|  |   | ||||
|  | +#define PRIMARY_TS	0
 | ||||
|  | +#define SECONDARY_TS	1
 | ||||
|  | +
 | ||||
|  |  enum em28xx_mode { | ||||
|  |  	EM28XX_SUSPEND, | ||||
|  |  	EM28XX_ANALOG_MODE, | ||||
|  | @@ -412,6 +416,7 @@
 | ||||
|  |  enum em28xx_led_role { | ||||
|  |  	EM28XX_LED_ANALOG_CAPTURING = 0, | ||||
|  |  	EM28XX_LED_DIGITAL_CAPTURING, | ||||
|  | +	EM28XX_LED_DIGITAL_CAPTURING_TS2,
 | ||||
|  |  	EM28XX_LED_ILLUMINATION, | ||||
|  |  	EM28XX_NUM_LED_ROLES, /* must be the last */ | ||||
|  |  }; | ||||
|  | @@ -458,6 +463,7 @@
 | ||||
|  |  	unsigned int mts_firmware:1; | ||||
|  |  	unsigned int max_range_640_480:1; | ||||
|  |  	unsigned int has_dvb:1; | ||||
|  | +	unsigned int has_dual_ts:1;
 | ||||
|  |  	unsigned int is_webcam:1; | ||||
|  |  	unsigned int valid:1; | ||||
|  |  	unsigned int has_ir_i2c:1; | ||||
|  | @@ -608,7 +614,6 @@
 | ||||
|  |  	struct em28xx_IR *ir; | ||||
|  |   | ||||
|  |  	/* generic device properties */ | ||||
|  | -	char name[30];		/* name (including minor) of the device */
 | ||||
|  |  	int model;		/* index in the device_data struct */ | ||||
|  |  	int devno;		/* marks the number of this device */ | ||||
|  |  	enum em28xx_chip_id chip_id; | ||||
|  | @@ -619,6 +624,7 @@
 | ||||
|  |  	unsigned int is_audio_only:1; | ||||
|  |  	enum em28xx_int_audio_type int_audio_type; | ||||
|  |  	enum em28xx_usb_audio_type usb_audio_type; | ||||
|  | +	unsigned char name[32];
 | ||||
|  |   | ||||
|  |  	struct em28xx_board board; | ||||
|  |   | ||||
|  | @@ -677,9 +683,12 @@
 | ||||
|  |   | ||||
|  |  	/* usb transfer */ | ||||
|  |  	struct usb_device *udev;	/* the usb device */ | ||||
|  | +	struct usb_interface *intf;	// the usb interface
 | ||||
|  |  	u8 ifnum;		/* number of the assigned usb interface */ | ||||
|  |  	u8 analog_ep_isoc;	/* address of isoc endpoint for analog */ | ||||
|  |  	u8 analog_ep_bulk;	/* address of bulk endpoint for analog */ | ||||
|  | +	u8 dvb_ep_isoc_ts2;	/* address of isoc endpoint for DVB TS2*/
 | ||||
|  | +	u8 dvb_ep_bulk_ts2;	/* address of bulk endpoint for DVB TS2*/
 | ||||
|  |  	u8 dvb_ep_isoc;		/* address of isoc endpoint for DVB */ | ||||
|  |  	u8 dvb_ep_bulk;		/* address of bulk endpoint for DVB */ | ||||
|  |  	int alt;		/* alternate setting */ | ||||
|  | @@ -693,6 +702,8 @@
 | ||||
|  |  	int dvb_alt_isoc;	/* alternate setting for DVB isoc transfers */ | ||||
|  |  	unsigned int dvb_max_pkt_size_isoc;	/* isoc max packet size of the | ||||
|  |  						   selected DVB ep at dvb_alt */ | ||||
|  | +	unsigned int dvb_max_pkt_size_isoc_ts2;	/* isoc max packet size of the
 | ||||
|  | +						   selected DVB ep at dvb_alt */
 | ||||
|  |  	unsigned int dvb_xfer_bulk:1;		/* use bulk instead of isoc | ||||
|  |  						   transfers for DVB          */ | ||||
|  |  	char urb_buf[URB_MAX_CTRL_SIZE];	/* urb control msg buffer */ | ||||
|  | @@ -718,6 +729,15 @@
 | ||||
|  |  	/* Snapshot button input device */ | ||||
|  |  	char snapshot_button_path[30];	/* path of the input dev */ | ||||
|  |  	struct input_dev *sbutton_input_dev; | ||||
|  | +
 | ||||
|  | +#ifdef CONFIG_MEDIA_CONTROLLER
 | ||||
|  | +	struct media_device *media_dev;
 | ||||
|  | +	struct media_entity input_ent[MAX_EM28XX_INPUT];
 | ||||
|  | +	struct media_pad input_pad[MAX_EM28XX_INPUT];
 | ||||
|  | +#endif
 | ||||
|  | +
 | ||||
|  | +	struct em28xx	*dev_next;
 | ||||
|  | +	int ts;
 | ||||
|  |  }; | ||||
|  |   | ||||
|  |  #define kref_to_dev(d) container_of(d, struct em28xx, ref) | ||||
|  | diff -Nur a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c
 | ||||
|  | --- a/drivers/media/usb/em28xx/em28xx-cards.c	2017-07-31 15:25:15.000000000 +0200
 | ||||
|  | +++ b/drivers/media/usb/em28xx/em28xx-cards.c	2019-04-02 08:43:27.288403900 +0200
 | ||||
|  | @@ -491,6 +491,30 @@
 | ||||
|  |  	{-1,                             -1,   -1,     -1}, | ||||
|  |  }; | ||||
|  |   | ||||
|  | +/* 2040:0265 Hauppauge WinTV-dualHD DVB Isoc
 | ||||
|  | + * 2040:8265 Hauppauge WinTV-dualHD DVB Bulk
 | ||||
|  | + * reg 0x80/0x84:
 | ||||
|  | + * GPIO_0: Yellow LED tuner 1, 0=on, 1=off
 | ||||
|  | + * GPIO_1: Green LED tuner 1, 0=on, 1=off
 | ||||
|  | + * GPIO_2: Yellow LED tuner 2, 0=on, 1=off
 | ||||
|  | + * GPIO_3: Green LED tuner 2, 0=on, 1=off
 | ||||
|  | + * GPIO_5: Reset #2, 0=active
 | ||||
|  | + * GPIO_6: Reset #1, 0=active
 | ||||
|  | + */
 | ||||
|  | +static struct em28xx_reg_seq hauppauge_dualhd_dvb[] = {
 | ||||
|  | +	{EM2874_R80_GPIO_P0_CTRL,      0xff, 0xff,      0},
 | ||||
|  | +	{0x0d,                         0xff, 0xff,    200},
 | ||||
|  | +	{0x50,                         0x04, 0xff,    300},
 | ||||
|  | +	{EM2874_R80_GPIO_P0_CTRL,      0xbf, 0xff,    100}, /* demod 1 reset */
 | ||||
|  | +	{EM2874_R80_GPIO_P0_CTRL,      0xff, 0xff,    100},
 | ||||
|  | +	{EM2874_R80_GPIO_P0_CTRL,      0xdf, 0xff,    100}, /* demod 2 reset */
 | ||||
|  | +	{EM2874_R80_GPIO_P0_CTRL,      0xff, 0xff,    100},
 | ||||
|  | +	{EM2874_R5F_TS_ENABLE,         0x44, 0xff,     50},
 | ||||
|  | +	{EM2874_R5D_TS1_PKT_SIZE,      0x05, 0xff,     50},
 | ||||
|  | +	{EM2874_R5E_TS2_PKT_SIZE,      0x05, 0xff,     50},
 | ||||
|  | +	{-1,                             -1,   -1,     -1},
 | ||||
|  | +};
 | ||||
|  | +
 | ||||
|  |  /* | ||||
|  |   *  Button definitions | ||||
|  |   */ | ||||
|  | @@ -560,6 +584,22 @@
 | ||||
|  |  	{-1, 0, 0, 0}, | ||||
|  |  }; | ||||
|  |   | ||||
|  | +static struct em28xx_led hauppauge_dualhd_leds[] = {
 | ||||
|  | +	{
 | ||||
|  | +		.role      = EM28XX_LED_DIGITAL_CAPTURING,
 | ||||
|  | +		.gpio_reg  = EM2874_R80_GPIO_P0_CTRL,
 | ||||
|  | +		.gpio_mask = EM_GPIO_1,
 | ||||
|  | +		.inverted  = 1,
 | ||||
|  | +	},
 | ||||
|  | +	{
 | ||||
|  | +		.role      = EM28XX_LED_DIGITAL_CAPTURING_TS2,
 | ||||
|  | +		.gpio_reg  = EM2874_R80_GPIO_P0_CTRL,
 | ||||
|  | +		.gpio_mask = EM_GPIO_3,
 | ||||
|  | +		.inverted  = 1,
 | ||||
|  | +	},
 | ||||
|  | +	{-1, 0, 0, 0},
 | ||||
|  | +};
 | ||||
|  | +
 | ||||
|  |  /* | ||||
|  |   *  Board definitions | ||||
|  |   */ | ||||
|  | @@ -2288,6 +2328,20 @@
 | ||||
|  |  		.has_dvb       = 1, | ||||
|  |  		.ir_codes      = RC_MAP_TERRATEC_SLIM_2, | ||||
|  |  	}, | ||||
|  | +	/* 2040:0265 Hauppauge WinTV-dualHD (DVB version) Isoc.
 | ||||
|  | +	 * 2040:8265 Hauppauge WinTV-dualHD (DVB version) Bulk.
 | ||||
|  | +	 * Empia EM28274, 2x Silicon Labs Si2168, 2x Silicon Labs Si2157 */
 | ||||
|  | +	[EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB] = {
 | ||||
|  | +		.name          = "Hauppauge WinTV-dualHD DVB",
 | ||||
|  | +		.def_i2c_bus   = 1,
 | ||||
|  | +		.i2c_speed     = EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ,
 | ||||
|  | +		.tuner_type    = TUNER_ABSENT,
 | ||||
|  | +		.tuner_gpio    = hauppauge_dualhd_dvb,
 | ||||
|  | +		.has_dvb       = 1,
 | ||||
|  | +		.has_dual_ts   = 1,
 | ||||
|  | +		.ir_codes      = RC_MAP_HAUPPAUGE,
 | ||||
|  | +		.leds          = hauppauge_dualhd_leds,
 | ||||
|  | +	},
 | ||||
|  |  }; | ||||
|  |  EXPORT_SYMBOL_GPL(em28xx_boards); | ||||
|  |   | ||||
|  | @@ -2411,6 +2465,10 @@
 | ||||
|  |  			.driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 }, | ||||
|  |  	{ USB_DEVICE(0x2040, 0x651f), | ||||
|  |  			.driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 }, | ||||
|  | +	{ USB_DEVICE(0x2040, 0x0265),
 | ||||
|  | +			.driver_info = EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB },
 | ||||
|  | +	{ USB_DEVICE(0x2040, 0x8265),
 | ||||
|  | +			.driver_info = EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB },
 | ||||
|  |  	{ USB_DEVICE(0x0438, 0xb002), | ||||
|  |  			.driver_info = EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600 }, | ||||
|  |  	{ USB_DEVICE(0x2001, 0xf112), | ||||
|  | @@ -2804,6 +2862,7 @@
 | ||||
|  |  	case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: | ||||
|  |  	case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: | ||||
|  |  	case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C: | ||||
|  | +	case EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB:
 | ||||
|  |  	{ | ||||
|  |  		struct tveeprom tv; | ||||
|  |   | ||||
|  | @@ -3013,6 +3072,8 @@
 | ||||
|  |  */ | ||||
|  |  static void em28xx_release_resources(struct em28xx *dev) | ||||
|  |  { | ||||
|  | +	struct usb_device *udev = interface_to_usbdev(dev->intf);
 | ||||
|  | +	
 | ||||
|  |  	/*FIXME: I2C IR should be disconnected */ | ||||
|  |   | ||||
|  |  	mutex_lock(&dev->lock); | ||||
|  | @@ -3021,7 +3082,8 @@
 | ||||
|  |  		em28xx_i2c_unregister(dev, 1); | ||||
|  |  	em28xx_i2c_unregister(dev, 0); | ||||
|  |   | ||||
|  | -	usb_put_dev(dev->udev);
 | ||||
|  | +	if (dev->ts == PRIMARY_TS)
 | ||||
|  | +		usb_put_dev(udev);
 | ||||
|  |   | ||||
|  |  	/* Mark device as unused */ | ||||
|  |  	clear_bit(dev->devno, em28xx_devused); | ||||
|  | @@ -3063,6 +3125,7 @@
 | ||||
|  |  	const char *chip_name = default_chip_name; | ||||
|  |   | ||||
|  |  	dev->udev = udev; | ||||
|  | +	dev->intf = interface;
 | ||||
|  |  	mutex_init(&dev->ctrl_urb_lock); | ||||
|  |  	spin_lock_init(&dev->slock); | ||||
|  |   | ||||
|  | @@ -3220,6 +3283,35 @@
 | ||||
|  |  	return 0; | ||||
|  |  } | ||||
|  |   | ||||
|  | +int em28xx_duplicate_dev(struct em28xx *dev)
 | ||||
|  | +{
 | ||||
|  | +	int nr;
 | ||||
|  | +	struct em28xx *sec_dev = kzalloc(sizeof(*sec_dev), GFP_KERNEL);
 | ||||
|  | +
 | ||||
|  | +	if (sec_dev == NULL) {
 | ||||
|  | +		dev->dev_next = NULL;
 | ||||
|  | +		return -ENOMEM;
 | ||||
|  | +	}
 | ||||
|  | +	memcpy(sec_dev, dev, sizeof(sizeof(*sec_dev)));
 | ||||
|  | +	/* Check to see next free device and mark as used */
 | ||||
|  | +	do {
 | ||||
|  | +		nr = find_first_zero_bit(em28xx_devused, EM28XX_MAXBOARDS);
 | ||||
|  | +		if (nr >= EM28XX_MAXBOARDS) {
 | ||||
|  | +			/* No free device slots */
 | ||||
|  | +			printk(DRIVER_NAME ": Supports only %i em28xx boards.\n",
 | ||||
|  | +					EM28XX_MAXBOARDS);
 | ||||
|  | +			kfree(sec_dev);
 | ||||
|  | +			dev->dev_next = NULL;
 | ||||
|  | +			return -ENOMEM;
 | ||||
|  | +		}
 | ||||
|  | +	} while (test_and_set_bit(nr, em28xx_devused));
 | ||||
|  | +	sec_dev->devno = nr;
 | ||||
|  | +	snprintf(sec_dev->name, 28, "em28xx #%d", nr);
 | ||||
|  | +	sec_dev->dev_next = NULL;
 | ||||
|  | +	dev->dev_next = sec_dev;
 | ||||
|  | +	return 0;
 | ||||
|  | +}
 | ||||
|  | +
 | ||||
|  |  /* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */ | ||||
|  |  #define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) | ||||
|  |   | ||||
|  | @@ -3340,6 +3432,17 @@
 | ||||
|  |  						} | ||||
|  |  					} | ||||
|  |  					break; | ||||
|  | +				case 0x85:
 | ||||
|  | +					if (usb_endpoint_xfer_isoc(e)) {
 | ||||
|  | +						if (size > dev->dvb_max_pkt_size_isoc_ts2) {
 | ||||
|  | +							dev->dvb_ep_isoc_ts2 = e->bEndpointAddress;
 | ||||
|  | +							dev->dvb_max_pkt_size_isoc_ts2 = size;
 | ||||
|  | +							dev->dvb_alt_isoc = i;
 | ||||
|  | +						}
 | ||||
|  | +					} else {
 | ||||
|  | +						dev->dvb_ep_bulk_ts2 = e->bEndpointAddress;
 | ||||
|  | +					}
 | ||||
|  | +					break;
 | ||||
|  |  				} | ||||
|  |  			} | ||||
|  |  			/* NOTE: | ||||
|  | @@ -3354,6 +3457,8 @@
 | ||||
|  |  			 *  0x83	isoc*		=> audio | ||||
|  |  			 *  0x84	isoc		=> digital | ||||
|  |  			 *  0x84	bulk		=> analog or digital** | ||||
|  | +			 *  0x85	isoc		=> digital TS2
 | ||||
|  | +			 *  0x85	bulk		=> digital TS2
 | ||||
|  |  			 * (*: audio should always be isoc) | ||||
|  |  			 * (**: analog, if ep 0x82 is isoc, otherwise digital) | ||||
|  |  			 * | ||||
|  | @@ -3422,6 +3527,10 @@
 | ||||
|  |  	dev->has_video = has_video; | ||||
|  |  	dev->ifnum = ifnum; | ||||
|  |   | ||||
|  | +	dev->ts = PRIMARY_TS;
 | ||||
|  | +	snprintf(dev->name, 28, "em28xx");
 | ||||
|  | +	dev->dev_next = NULL;
 | ||||
|  | +
 | ||||
|  |  	if (has_vendor_audio) { | ||||
|  |  		printk(KERN_INFO DRIVER_NAME ": Audio interface %i found %s\n", | ||||
|  |  		       ifnum, "(Vendor Class)"); | ||||
|  | @@ -3491,6 +3600,65 @@
 | ||||
|  |  			    dev->dvb_xfer_bulk ? "bulk" : "isoc"); | ||||
|  |  	} | ||||
|  |   | ||||
|  | +	if (dev->board.has_dual_ts && em28xx_duplicate_dev(dev) == 0) {
 | ||||
|  | +		dev->dev_next->ts = SECONDARY_TS;
 | ||||
|  | +		dev->dev_next->alt   = -1;
 | ||||
|  | +		dev->dev_next->is_audio_only = has_vendor_audio &&
 | ||||
|  | +						!(has_video || has_dvb);
 | ||||
|  | +		dev->dev_next->has_video = false;
 | ||||
|  | +		dev->dev_next->ifnum = ifnum;
 | ||||
|  | +		dev->dev_next->model = id->driver_info;
 | ||||
|  | +
 | ||||
|  | +		mutex_init(&dev->dev_next->lock);
 | ||||
|  | +		retval = em28xx_init_dev(dev->dev_next, udev, interface,
 | ||||
|  | +					dev->dev_next->devno);
 | ||||
|  | +		if (retval)
 | ||||
|  | +			goto err_free;
 | ||||
|  | +
 | ||||
|  | +		dev->dev_next->board.ir_codes = NULL; /* No IR for 2nd tuner */
 | ||||
|  | +		dev->dev_next->board.has_ir_i2c = 0; /* No IR for 2nd tuner */
 | ||||
|  | +
 | ||||
|  | +		if (usb_xfer_mode < 0) {
 | ||||
|  | +			if (dev->dev_next->board.is_webcam)
 | ||||
|  | +				try_bulk = 1;
 | ||||
|  | +			else
 | ||||
|  | +				try_bulk = 0;
 | ||||
|  | +		} else {
 | ||||
|  | +			try_bulk = usb_xfer_mode > 0;
 | ||||
|  | +		}
 | ||||
|  | +
 | ||||
|  | +		/* Select USB transfer types to use */
 | ||||
|  | +		if (has_dvb) {
 | ||||
|  | +			if (!dev->dvb_ep_isoc_ts2 ||
 | ||||
|  | +			   (try_bulk && dev->dvb_ep_bulk_ts2))
 | ||||
|  | +				dev->dev_next->dvb_xfer_bulk = 1;
 | ||||
|  | +			printk(DRIVER_NAME "dvb ts2 set to %s mode.\n",
 | ||||
|  | +				dev->dev_next->dvb_xfer_bulk ? "bulk" : "isoc");
 | ||||
|  | +		}
 | ||||
|  | +
 | ||||
|  | +		dev->dev_next->dvb_ep_isoc = dev->dvb_ep_isoc_ts2;
 | ||||
|  | +		dev->dev_next->dvb_ep_bulk = dev->dvb_ep_bulk_ts2;
 | ||||
|  | +		dev->dev_next->dvb_max_pkt_size_isoc = dev->dvb_max_pkt_size_isoc_ts2;
 | ||||
|  | +		dev->dev_next->dvb_alt_isoc = dev->dvb_alt_isoc;
 | ||||
|  | +
 | ||||
|  | +		/* Configuare hardware to support TS2*/
 | ||||
|  | +		if (dev->dvb_xfer_bulk) {
 | ||||
|  | +			/* The ep4 and ep5 are configuared for BULK */
 | ||||
|  | +			em28xx_write_reg(dev, 0x0b, 0x96);
 | ||||
|  | +			mdelay(100);
 | ||||
|  | +			em28xx_write_reg(dev, 0x0b, 0x80);
 | ||||
|  | +			mdelay(100);
 | ||||
|  | +		} else {
 | ||||
|  | +			/* The ep4 and ep5 are configuared for ISO */
 | ||||
|  | +			em28xx_write_reg(dev, 0x0b, 0x96);
 | ||||
|  | +			mdelay(100);
 | ||||
|  | +			em28xx_write_reg(dev, 0x0b, 0x82);
 | ||||
|  | +			mdelay(100);
 | ||||
|  | +		}
 | ||||
|  | +
 | ||||
|  | +		kref_init(&dev->dev_next->ref);
 | ||||
|  | +	}
 | ||||
|  | +
 | ||||
|  |  	kref_init(&dev->ref); | ||||
|  |   | ||||
|  |  	request_modules(dev); | ||||
|  | @@ -3528,6 +3696,13 @@
 | ||||
|  |  	if (!dev) | ||||
|  |  		return; | ||||
|  |   | ||||
|  | +	if (dev->dev_next != NULL) {
 | ||||
|  | +		dev->dev_next->disconnected = 1;
 | ||||
|  | +		printk(DRIVER_NAME "Disconnecting %s\n",
 | ||||
|  | +			dev->dev_next->name);
 | ||||
|  | +		flush_request_modules(dev->dev_next);
 | ||||
|  | +	}
 | ||||
|  | +
 | ||||
|  |  	dev->disconnected = 1; | ||||
|  |   | ||||
|  |  	em28xx_info("Disconnecting %s\n", dev->name); | ||||
|  | @@ -3536,7 +3711,14 @@
 | ||||
|  |   | ||||
|  |  	em28xx_close_extension(dev); | ||||
|  |   | ||||
|  | +	if (dev->dev_next != NULL)
 | ||||
|  | +		em28xx_release_resources(dev->dev_next);
 | ||||
|  |  	em28xx_release_resources(dev); | ||||
|  | +
 | ||||
|  | +	if (dev->dev_next != NULL) {
 | ||||
|  | +		kref_put(&dev->dev_next->ref, em28xx_free_device);
 | ||||
|  | +		dev->dev_next = NULL;
 | ||||
|  | +	}
 | ||||
|  |  	kref_put(&dev->ref, em28xx_free_device); | ||||
|  |  } | ||||
|  |   | ||||
|  | diff -Nur a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c
 | ||||
|  | --- a/drivers/media/usb/em28xx/em28xx-core.c	2017-07-31 15:25:15.000000000 +0200
 | ||||
|  | +++ b/drivers/media/usb/em28xx/em28xx-core.c	2019-04-02 08:30:40.204091800 +0200
 | ||||
|  | @@ -636,10 +636,19 @@
 | ||||
|  |  	    dev->chip_id == CHIP_ID_EM28174 || | ||||
|  |  	    dev->chip_id == CHIP_ID_EM28178) { | ||||
|  |  		/* The Transport Stream Enable Register moved in em2874 */ | ||||
|  | -		rc = em28xx_write_reg_bits(dev, EM2874_R5F_TS_ENABLE,
 | ||||
|  | -					   start ?
 | ||||
|  | -					       EM2874_TS1_CAPTURE_ENABLE : 0x00,
 | ||||
|  | -					   EM2874_TS1_CAPTURE_ENABLE);
 | ||||
|  | +		if (dev->ts == PRIMARY_TS) {
 | ||||
|  | +			rc = em28xx_write_reg_bits(dev,
 | ||||
|  | +				EM2874_R5F_TS_ENABLE,
 | ||||
|  | +				start ?
 | ||||
|  | +				EM2874_TS1_CAPTURE_ENABLE : 0x00,
 | ||||
|  | +				EM2874_TS1_CAPTURE_ENABLE);
 | ||||
|  | +		} else {
 | ||||
|  | +			rc = em28xx_write_reg_bits(dev,
 | ||||
|  | +				EM2874_R5F_TS_ENABLE,
 | ||||
|  | +				start ?
 | ||||
|  | +				EM2874_TS2_CAPTURE_ENABLE : 0x00,
 | ||||
|  | +				EM2874_TS2_CAPTURE_ENABLE);
 | ||||
|  | +		}
 | ||||
|  |  	} else { | ||||
|  |  		/* FIXME: which is the best order? */ | ||||
|  |  		/* video registers are sampled by VREF */ | ||||
|  | @@ -1073,7 +1082,11 @@
 | ||||
|  |  	mutex_lock(&em28xx_devlist_mutex); | ||||
|  |  	list_add_tail(&ops->next, &em28xx_extension_devlist); | ||||
|  |  	list_for_each_entry(dev, &em28xx_devlist, devlist) { | ||||
|  | -		ops->init(dev);
 | ||||
|  | +		if (ops->init) {
 | ||||
|  | +			ops->init(dev);
 | ||||
|  | +			if (dev->dev_next != NULL)
 | ||||
|  | +				ops->init(dev->dev_next);
 | ||||
|  | +		}
 | ||||
|  |  	} | ||||
|  |  	mutex_unlock(&em28xx_devlist_mutex); | ||||
|  |  	printk(KERN_INFO "em28xx: Registered (%s) extension\n", ops->name); | ||||
|  | @@ -1087,7 +1100,11 @@
 | ||||
|  |   | ||||
|  |  	mutex_lock(&em28xx_devlist_mutex); | ||||
|  |  	list_for_each_entry(dev, &em28xx_devlist, devlist) { | ||||
|  | -		ops->fini(dev);
 | ||||
|  | +		if (ops->fini) {
 | ||||
|  | +			if (dev->dev_next != NULL)
 | ||||
|  | +				ops->fini(dev->dev_next);
 | ||||
|  | +			ops->fini(dev);
 | ||||
|  | +		}
 | ||||
|  |  	} | ||||
|  |  	list_del(&ops->next); | ||||
|  |  	mutex_unlock(&em28xx_devlist_mutex); | ||||
|  | @@ -1102,8 +1119,11 @@
 | ||||
|  |  	mutex_lock(&em28xx_devlist_mutex); | ||||
|  |  	list_add_tail(&dev->devlist, &em28xx_devlist); | ||||
|  |  	list_for_each_entry(ops, &em28xx_extension_devlist, next) { | ||||
|  | -		if (ops->init)
 | ||||
|  | -			ops->init(dev);
 | ||||
|  | +		if (ops->init) {
 | ||||
|  | + 			ops->init(dev);
 | ||||
|  | + 			if (dev->dev_next != NULL)
 | ||||
|  | +				ops->init(dev->dev_next);
 | ||||
|  | +		}
 | ||||
|  |  	} | ||||
|  |  	mutex_unlock(&em28xx_devlist_mutex); | ||||
|  |  } | ||||
|  | @@ -1114,8 +1134,11 @@
 | ||||
|  |   | ||||
|  |  	mutex_lock(&em28xx_devlist_mutex); | ||||
|  |  	list_for_each_entry(ops, &em28xx_extension_devlist, next) { | ||||
|  | -		if (ops->fini)
 | ||||
|  | -			ops->fini(dev);
 | ||||
|  | +		if (ops->fini) {
 | ||||
|  | + 			if (dev->dev_next != NULL)
 | ||||
|  | +				ops->fini(dev->dev_next);
 | ||||
|  | + 			ops->fini(dev);
 | ||||
|  | +		}
 | ||||
|  |  	} | ||||
|  |  	list_del(&dev->devlist); | ||||
|  |  	mutex_unlock(&em28xx_devlist_mutex); | ||||
|  | @@ -1130,6 +1153,8 @@
 | ||||
|  |  	list_for_each_entry(ops, &em28xx_extension_devlist, next) { | ||||
|  |  		if (ops->suspend) | ||||
|  |  			ops->suspend(dev); | ||||
|  | +		if (dev->dev_next != NULL)
 | ||||
|  | +			ops->suspend(dev->dev_next);
 | ||||
|  |  	} | ||||
|  |  	mutex_unlock(&em28xx_devlist_mutex); | ||||
|  |  	return 0; | ||||
|  | @@ -1144,6 +1169,8 @@
 | ||||
|  |  	list_for_each_entry(ops, &em28xx_extension_devlist, next) { | ||||
|  |  		if (ops->resume) | ||||
|  |  			ops->resume(dev); | ||||
|  | +		if (dev->dev_next != NULL)
 | ||||
|  | +			ops->resume(dev->dev_next);
 | ||||
|  |  	} | ||||
|  |  	mutex_unlock(&em28xx_devlist_mutex); | ||||
|  |  	return 0; | ||||
|  | diff -Nur a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c
 | ||||
|  | --- a/drivers/media/usb/em28xx/em28xx-dvb.c	2017-07-31 15:25:15.000000000 +0200
 | ||||
|  | +++ b/drivers/media/usb/em28xx/em28xx-dvb.c	2019-04-02 08:30:40.206087100 +0200
 | ||||
|  | @@ -211,7 +211,6 @@
 | ||||
|  |  		dvb_alt = dev->dvb_alt_isoc; | ||||
|  |  	} | ||||
|  |   | ||||
|  | -	usb_set_interface(dev->udev, dev->ifnum, dvb_alt);
 | ||||
|  |  	rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); | ||||
|  |  	if (rc < 0) | ||||
|  |  		return rc; | ||||
|  | @@ -1031,8 +1030,9 @@
 | ||||
|  |   | ||||
|  |  static int em28xx_dvb_init(struct em28xx *dev) | ||||
|  |  { | ||||
|  | -	int result = 0;
 | ||||
|  | +	int result = 0, dvb_alt = 0;
 | ||||
|  |  	struct em28xx_dvb *dvb; | ||||
|  | +	struct usb_device *udev;
 | ||||
|  |   | ||||
|  |  	if (dev->is_audio_only) { | ||||
|  |  		/* Shouldn't initialize IR for this interface */ | ||||
|  | @@ -1726,6 +1726,76 @@
 | ||||
|  |  			dvb->i2c_client_tuner = client; | ||||
|  |  		} | ||||
|  |  		break; | ||||
|  | +	case EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB:
 | ||||
|  | +		{
 | ||||
|  | +			struct i2c_adapter *adapter;
 | ||||
|  | +			struct i2c_client *client;
 | ||||
|  | +			struct i2c_board_info info;
 | ||||
|  | +			struct si2168_config si2168_config;
 | ||||
|  | +			struct si2157_config si2157_config;
 | ||||
|  | +
 | ||||
|  | +			/* attach demod */
 | ||||
|  | +			memset(&si2168_config, 0, sizeof(si2168_config));
 | ||||
|  | +			si2168_config.i2c_adapter = &adapter;
 | ||||
|  | +			si2168_config.fe = &dvb->fe[0];
 | ||||
|  | +			si2168_config.ts_mode = SI2168_TS_SERIAL;
 | ||||
|  | +			memset(&info, 0, sizeof(struct i2c_board_info));
 | ||||
|  | +			strlcpy(info.type, "si2168", I2C_NAME_SIZE);
 | ||||
|  | +			if (dev->ts == PRIMARY_TS)
 | ||||
|  | +				info.addr = 0x64;
 | ||||
|  | +			else
 | ||||
|  | +				info.addr = 0x67;
 | ||||
|  | +			info.platform_data = &si2168_config;
 | ||||
|  | +			request_module(info.type);
 | ||||
|  | +			client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info);
 | ||||
|  | +			if (client == NULL || client->dev.driver == NULL) {
 | ||||
|  | +				result = -ENODEV;
 | ||||
|  | +				goto out_free;
 | ||||
|  | +			}
 | ||||
|  | +
 | ||||
|  | +			if (!try_module_get(client->dev.driver->owner)) {
 | ||||
|  | +				i2c_unregister_device(client);
 | ||||
|  | +				result = -ENODEV;
 | ||||
|  | +				goto out_free;
 | ||||
|  | +			}
 | ||||
|  | +
 | ||||
|  | +			dvb->i2c_client_demod = client;
 | ||||
|  | +
 | ||||
|  | +			/* attach tuner */
 | ||||
|  | +			memset(&si2157_config, 0, sizeof(si2157_config));
 | ||||
|  | +			si2157_config.fe = dvb->fe[0];
 | ||||
|  | +			si2157_config.if_port = 1;
 | ||||
|  | +#ifdef CONFIG_MEDIA_CONTROLLER_DVB
 | ||||
|  | +			si2157_config.mdev = dev->media_dev;
 | ||||
|  | +#endif
 | ||||
|  | +			memset(&info, 0, sizeof(struct i2c_board_info));
 | ||||
|  | +			strlcpy(info.type, "si2157", I2C_NAME_SIZE);
 | ||||
|  | +			if (dev->ts == PRIMARY_TS)
 | ||||
|  | +				info.addr = 0x60;
 | ||||
|  | +			else
 | ||||
|  | +				info.addr = 0x63;
 | ||||
|  | +			info.platform_data = &si2157_config;
 | ||||
|  | +			request_module(info.type);
 | ||||
|  | +			client = i2c_new_device(adapter, &info);
 | ||||
|  | +			if (client == NULL || client->dev.driver == NULL) {
 | ||||
|  | +				module_put(dvb->i2c_client_demod->dev.driver->owner);
 | ||||
|  | +				i2c_unregister_device(dvb->i2c_client_demod);
 | ||||
|  | +				result = -ENODEV;
 | ||||
|  | +				goto out_free;
 | ||||
|  | +			}
 | ||||
|  | +
 | ||||
|  | +			if (!try_module_get(client->dev.driver->owner)) {
 | ||||
|  | +				i2c_unregister_device(client);
 | ||||
|  | +				module_put(dvb->i2c_client_demod->dev.driver->owner);
 | ||||
|  | +				i2c_unregister_device(dvb->i2c_client_demod);
 | ||||
|  | +				result = -ENODEV;
 | ||||
|  | +				goto out_free;
 | ||||
|  | +			}
 | ||||
|  | +
 | ||||
|  | +			dvb->i2c_client_tuner = client;
 | ||||
|  | +
 | ||||
|  | +		}
 | ||||
|  | +		break;
 | ||||
|  |  	default: | ||||
|  |  		em28xx_errdev("/2: The frontend of your DVB/ATSC card" | ||||
|  |  				" isn't supported yet\n"); | ||||
|  | @@ -1747,6 +1817,14 @@
 | ||||
|  |  	if (result < 0) | ||||
|  |  		goto out_free; | ||||
|  |   | ||||
|  | +	if (dev->dvb_xfer_bulk) {
 | ||||
|  | +		dvb_alt = 0;
 | ||||
|  | +	} else { /* isoc */
 | ||||
|  | +		dvb_alt = dev->dvb_alt_isoc;
 | ||||
|  | +	}
 | ||||
|  | +
 | ||||
|  | +	udev = interface_to_usbdev(dev->intf);
 | ||||
|  | +	usb_set_interface(udev, dev->ifnum, dvb_alt);
 | ||||
|  |  	em28xx_info("DVB extension successfully initialized\n"); | ||||
|  |   | ||||
|  |  	kref_get(&dev->ref); | ||||
|  | diff -Nur a/drivers/media/usb/em28xx/em28xx-reg.h b/drivers/media/usb/em28xx/em28xx-reg.h
 | ||||
|  | --- a/drivers/media/usb/em28xx/em28xx-reg.h	2017-07-31 15:25:15.000000000 +0200
 | ||||
|  | +++ b/drivers/media/usb/em28xx/em28xx-reg.h	2019-04-02 08:30:40.209080400 +0200
 | ||||
|  | @@ -193,6 +193,19 @@
 | ||||
|  |  /* em2874 registers */ | ||||
|  |  #define EM2874_R50_IR_CONFIG    0x50 | ||||
|  |  #define EM2874_R51_IR           0x51 | ||||
|  | +#define EM2874_R5D_TS1_PKT_SIZE 0x5d
 | ||||
|  | +#define EM2874_R5E_TS2_PKT_SIZE 0x5e
 | ||||
|  | +	/*
 | ||||
|  | +	 * For both TS1 and TS2, In isochronous mode:
 | ||||
|  | +	 *  0x01  188 bytes
 | ||||
|  | +	 *  0x02  376 bytes
 | ||||
|  | +	 *  0x03  564 bytes
 | ||||
|  | +	 *  0x04  752 bytes
 | ||||
|  | +	 *  0x05  940 bytes
 | ||||
|  | +	 * In bulk mode:
 | ||||
|  | +	 *  0x01..0xff  total packet count in 188-byte
 | ||||
|  | +	 */
 | ||||
|  | +
 | ||||
|  |  #define EM2874_R5F_TS_ENABLE    0x5f | ||||
|  |   | ||||
|  |  /* em2874/174/84, em25xx, em276x/7x/8x GPIO registers */ | ||||
| @ -0,0 +1,158 @@ | |||||
|  | diff -Nur a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c
 | ||||
|  | --- a/drivers/media/usb/dvb-usb/dib0700_core.c	2017-07-31 15:25:15.000000000 +0200
 | ||||
|  | +++ b/drivers/media/usb/dvb-usb/dib0700_core.c	2019-02-23 09:05:14.000000000 +0100
 | ||||
|  | @@ -783,6 +783,9 @@
 | ||||
|  |   | ||||
|  |  	/* Starting in firmware 1.20, the RC info is provided on a bulk pipe */ | ||||
|  |   | ||||
|  | +	if (intf->altsetting[0].desc.bNumEndpoints < rc_ep + 1)
 | ||||
|  | +		return -ENODEV;
 | ||||
|  | +
 | ||||
|  |  	purb = usb_alloc_urb(0, GFP_KERNEL); | ||||
|  |  	if (purb == NULL) { | ||||
|  |  		err("rc usb alloc urb failed"); | ||||
|  | diff -Nur a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c
 | ||||
|  | --- a/drivers/media/usb/dvb-usb/dib0700_devices.c	2017-07-31 15:25:15.000000000 +0200
 | ||||
|  | +++ b/drivers/media/usb/dvb-usb/dib0700_devices.c	2019-02-23 09:05:14.000000000 +0100
 | ||||
|  | @@ -294,7 +294,7 @@
 | ||||
|  |  					     stk7700d_dib7000p_mt2266_config) | ||||
|  |  		    != 0) { | ||||
|  |  			err("%s: state->dib7000p_ops.i2c_enumeration failed.  Cannot continue\n", __func__); | ||||
|  | -			dvb_detach(&state->dib7000p_ops);
 | ||||
|  | +			dvb_detach(state->dib7000p_ops.set_wbd_ref);
 | ||||
|  |  			return -ENODEV; | ||||
|  |  		} | ||||
|  |  	} | ||||
|  | @@ -328,7 +328,7 @@
 | ||||
|  |  					     stk7700d_dib7000p_mt2266_config) | ||||
|  |  		    != 0) { | ||||
|  |  			err("%s: state->dib7000p_ops.i2c_enumeration failed.  Cannot continue\n", __func__); | ||||
|  | -			dvb_detach(&state->dib7000p_ops);
 | ||||
|  | +			dvb_detach(state->dib7000p_ops.set_wbd_ref);
 | ||||
|  |  			return -ENODEV; | ||||
|  |  		} | ||||
|  |  	} | ||||
|  | @@ -433,6 +433,7 @@
 | ||||
|  |  		state->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1); | ||||
|  |  		break; | ||||
|  |  	case XC2028_RESET_CLK: | ||||
|  | +	case XC2028_I2C_FLUSH:
 | ||||
|  |  		break; | ||||
|  |  	default: | ||||
|  |  		err("%s: unknown command %d, arg %d\n", __func__, | ||||
|  | @@ -481,7 +482,7 @@
 | ||||
|  |  				     &stk7700ph_dib7700_xc3028_config) != 0) { | ||||
|  |  		err("%s: state->dib7000p_ops.i2c_enumeration failed.  Cannot continue\n", | ||||
|  |  		    __func__); | ||||
|  | -		dvb_detach(&state->dib7000p_ops);
 | ||||
|  | +		dvb_detach(state->dib7000p_ops.set_wbd_ref);
 | ||||
|  |  		return -ENODEV; | ||||
|  |  	} | ||||
|  |   | ||||
|  | @@ -1012,7 +1013,7 @@
 | ||||
|  |  				     &dib7070p_dib7000p_config) != 0) { | ||||
|  |  		err("%s: state->dib7000p_ops.i2c_enumeration failed.  Cannot continue\n", | ||||
|  |  		    __func__); | ||||
|  | -		dvb_detach(&state->dib7000p_ops);
 | ||||
|  | +		dvb_detach(state->dib7000p_ops.set_wbd_ref);
 | ||||
|  |  		return -ENODEV; | ||||
|  |  	} | ||||
|  |   | ||||
|  | @@ -1070,7 +1071,7 @@
 | ||||
|  |  				     &dib7770p_dib7000p_config) != 0) { | ||||
|  |  		err("%s: state->dib7000p_ops.i2c_enumeration failed.  Cannot continue\n", | ||||
|  |  		    __func__); | ||||
|  | -		dvb_detach(&state->dib7000p_ops);
 | ||||
|  | +		dvb_detach(state->dib7000p_ops.set_wbd_ref);
 | ||||
|  |  		return -ENODEV; | ||||
|  |  	} | ||||
|  |   | ||||
|  | @@ -3038,7 +3039,7 @@
 | ||||
|  |   | ||||
|  |  	if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, &nim7090_dib7000p_config) != 0) { | ||||
|  |  		err("%s: state->dib7000p_ops.i2c_enumeration failed.  Cannot continue\n", __func__); | ||||
|  | -		dvb_detach(&state->dib7000p_ops);
 | ||||
|  | +		dvb_detach(state->dib7000p_ops.set_wbd_ref);
 | ||||
|  |  		return -ENODEV; | ||||
|  |  	} | ||||
|  |  	adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80, &nim7090_dib7000p_config); | ||||
|  | @@ -3091,7 +3092,7 @@
 | ||||
|  |  	/* initialize IC 0 */ | ||||
|  |  	if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x20, &tfe7090pvr_dib7000p_config[0]) != 0) { | ||||
|  |  		err("%s: state->dib7000p_ops.i2c_enumeration failed.  Cannot continue\n", __func__); | ||||
|  | -		dvb_detach(&state->dib7000p_ops);
 | ||||
|  | +		dvb_detach(state->dib7000p_ops.set_wbd_ref);
 | ||||
|  |  		return -ENODEV; | ||||
|  |  	} | ||||
|  |   | ||||
|  | @@ -3121,7 +3122,7 @@
 | ||||
|  |  	i2c = state->dib7000p_ops.get_i2c_master(adap->dev->adapter[0].fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_6_7, 1); | ||||
|  |  	if (state->dib7000p_ops.i2c_enumeration(i2c, 1, 0x10, &tfe7090pvr_dib7000p_config[1]) != 0) { | ||||
|  |  		err("%s: state->dib7000p_ops.i2c_enumeration failed.  Cannot continue\n", __func__); | ||||
|  | -		dvb_detach(&state->dib7000p_ops);
 | ||||
|  | +		dvb_detach(state->dib7000p_ops.set_wbd_ref);
 | ||||
|  |  		return -ENODEV; | ||||
|  |  	} | ||||
|  |   | ||||
|  | @@ -3196,7 +3197,7 @@
 | ||||
|  |  				1, 0x10, &tfe7790p_dib7000p_config) != 0) { | ||||
|  |  		err("%s: state->dib7000p_ops.i2c_enumeration failed.  Cannot continue\n", | ||||
|  |  				__func__); | ||||
|  | -		dvb_detach(&state->dib7000p_ops);
 | ||||
|  | +		dvb_detach(state->dib7000p_ops.set_wbd_ref);
 | ||||
|  |  		return -ENODEV; | ||||
|  |  	} | ||||
|  |  	adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, | ||||
|  | @@ -3291,7 +3292,7 @@
 | ||||
|  |  				     stk7070pd_dib7000p_config) != 0) { | ||||
|  |  		err("%s: state->dib7000p_ops.i2c_enumeration failed.  Cannot continue\n", | ||||
|  |  		    __func__); | ||||
|  | -		dvb_detach(&state->dib7000p_ops);
 | ||||
|  | +		dvb_detach(state->dib7000p_ops.set_wbd_ref);
 | ||||
|  |  		return -ENODEV; | ||||
|  |  	} | ||||
|  |   | ||||
|  | @@ -3366,7 +3367,7 @@
 | ||||
|  |  					     stk7070pd_dib7000p_config) != 0) { | ||||
|  |  			err("%s: state->dib7000p_ops.i2c_enumeration failed.  Cannot continue\n", | ||||
|  |  			    __func__); | ||||
|  | -			dvb_detach(&state->dib7000p_ops);
 | ||||
|  | +			dvb_detach(state->dib7000p_ops.set_wbd_ref);
 | ||||
|  |  			return -ENODEV; | ||||
|  |  		} | ||||
|  |  	} | ||||
|  | @@ -3602,7 +3603,7 @@
 | ||||
|  |   | ||||
|  |  	if (state->dib7000p_ops.dib7000pc_detection(&adap->dev->i2c_adap) == 0) { | ||||
|  |  		/* Demodulator not found for some reason? */ | ||||
|  | -		dvb_detach(&state->dib7000p_ops);
 | ||||
|  | +		dvb_detach(state->dib7000p_ops.set_wbd_ref);
 | ||||
|  |  		return -ENODEV; | ||||
|  |  	} | ||||
|  |   | ||||
|  | diff -Nur a/drivers/media/usb/dvb-usb/dibusb-common.c b/drivers/media/usb/dvb-usb/dibusb-common.c
 | ||||
|  | --- a/drivers/media/usb/dvb-usb/dibusb-common.c	2017-07-31 15:25:15.000000000 +0200
 | ||||
|  | +++ b/drivers/media/usb/dvb-usb/dibusb-common.c	2019-02-23 09:05:14.000000000 +0100
 | ||||
|  | @@ -179,8 +179,20 @@
 | ||||
|  |   | ||||
|  |  int dibusb_read_eeprom_byte(struct dvb_usb_device *d, u8 offs, u8 *val) | ||||
|  |  { | ||||
|  | -	u8 wbuf[1] = { offs };
 | ||||
|  | -	return dibusb_i2c_msg(d, 0x50, wbuf, 1, val, 1);
 | ||||
|  | +	u8 *buf;
 | ||||
|  | +	int rc;
 | ||||
|  | +
 | ||||
|  | +	buf = kmalloc(2, GFP_KERNEL);
 | ||||
|  | +	if (!buf)
 | ||||
|  | +		return -ENOMEM;
 | ||||
|  | +
 | ||||
|  | +	buf[0] = offs;
 | ||||
|  | +
 | ||||
|  | +	rc = dibusb_i2c_msg(d, 0x50, &buf[0], 1, &buf[1], 1);
 | ||||
|  | +	*val = buf[1];
 | ||||
|  | +	kfree(buf);
 | ||||
|  | +
 | ||||
|  | +	return rc;
 | ||||
|  |  } | ||||
|  |  EXPORT_SYMBOL(dibusb_read_eeprom_byte); | ||||
|  |   | ||||
| @ -0,0 +1,67 @@ | |||||
|  | diff -Nur a/drivers/media/usb/dvb-usb/dvb-usb-firmware.c b/drivers/media/usb/dvb-usb/dvb-usb-firmware.c
 | ||||
|  | --- a/drivers/media/usb/dvb-usb/dvb-usb-firmware.c	2017-07-31 15:25:15.000000000 +0200
 | ||||
|  | +++ b/drivers/media/usb/dvb-usb/dvb-usb-firmware.c	2019-02-23 09:05:14.000000000 +0100
 | ||||
|  | @@ -35,42 +35,51 @@
 | ||||
|  |   | ||||
|  |  int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type) | ||||
|  |  { | ||||
|  | -	struct hexline hx;
 | ||||
|  | -	u8 reset;
 | ||||
|  | -	int ret,pos=0;
 | ||||
|  | +	struct hexline *hx;
 | ||||
|  | +	u8 *buf;
 | ||||
|  | +	int ret, pos = 0;
 | ||||
|  | +	u16 cpu_cs_register = cypress[type].cpu_cs_register;
 | ||||
|  | +
 | ||||
|  | +	buf = kmalloc(sizeof(*hx), GFP_KERNEL);
 | ||||
|  | +	if (!buf)
 | ||||
|  | +		return -ENOMEM;
 | ||||
|  | +	hx = (struct hexline *)buf;
 | ||||
|  |   | ||||
|  |  	/* stop the CPU */ | ||||
|  | -	reset = 1;
 | ||||
|  | -	if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1)
 | ||||
|  | +	buf[0] = 1;
 | ||||
|  | +	if (usb_cypress_writemem(udev, cpu_cs_register, buf, 1) != 1)
 | ||||
|  |  		err("could not stop the USB controller CPU."); | ||||
|  |   | ||||
|  | -	while ((ret = dvb_usb_get_hexline(fw,&hx,&pos)) > 0) {
 | ||||
|  | -		deb_fw("writing to address 0x%04x (buffer: 0x%02x %02x)\n",hx.addr,hx.len,hx.chk);
 | ||||
|  | -		ret = usb_cypress_writemem(udev,hx.addr,hx.data,hx.len);
 | ||||
|  | +	while ((ret = dvb_usb_get_hexline(fw, hx, &pos)) > 0) {
 | ||||
|  | +		deb_fw("writing to address 0x%04x (buffer: 0x%02x %02x)\n", hx->addr, hx->len, hx->chk);
 | ||||
|  | +		ret = usb_cypress_writemem(udev, hx->addr, hx->data, hx->len);
 | ||||
|  |   | ||||
|  | -		if (ret != hx.len) {
 | ||||
|  | +		if (ret != hx->len) {
 | ||||
|  |  			err("error while transferring firmware " | ||||
|  |  				"(transferred size: %d, block size: %d)", | ||||
|  | -				ret,hx.len);
 | ||||
|  | +				ret, hx->len);
 | ||||
|  |  			ret = -EINVAL; | ||||
|  |  			break; | ||||
|  |  		} | ||||
|  |  	} | ||||
|  |  	if (ret < 0) { | ||||
|  |  		err("firmware download failed at %d with %d",pos,ret); | ||||
|  | +		kfree(buf);
 | ||||
|  |  		return ret; | ||||
|  |  	} | ||||
|  |   | ||||
|  |  	if (ret == 0) { | ||||
|  |  		/* restart the CPU */ | ||||
|  | -		reset = 0;
 | ||||
|  | -		if (ret || usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1) != 1) {
 | ||||
|  | +		buf[0] = 0;
 | ||||
|  | +		if (usb_cypress_writemem(udev, cpu_cs_register, buf, 1) != 1) {
 | ||||
|  |  			err("could not restart the USB controller CPU."); | ||||
|  |  			ret = -EINVAL; | ||||
|  |  		} | ||||
|  |  	} else | ||||
|  |  		ret = -EIO; | ||||
|  |   | ||||
|  | +	kfree(buf);
 | ||||
|  | +
 | ||||
|  |  	return ret; | ||||
|  |  } | ||||
|  |  EXPORT_SYMBOL(usb_cypress_load_firmware); | ||||
								
									
										File diff suppressed because it is too large
									
								
							
						
					| @ -0,0 +1,36 @@ | |||||
|  | [SMB3] Improve security, move default dialect to SMB3 from old CIFS | ||||
|  | Due to recent publicity about security vulnerabilities in the | ||||
|  | much older CIFS dialect, move the default dialect to the | ||||
|  | widely accepted (and quite secure) SMB3.0 dialect from the | ||||
|  | old default of the CIFS dialect. | ||||
|  | 
 | ||||
|  | We do not want to be encouraging use of less secure dialects, | ||||
|  | and both Microsoft and CERT now strongly recommend not using the | ||||
|  | older CIFS dialect (SMB Security Best Practices | ||||
|  | "recommends disabling SMBv1"). | ||||
|  | 
 | ||||
|  | SMB3 is both secure and widely available: in Windows 8 and later, | ||||
|  | Samba and Macs. | ||||
|  | 
 | ||||
|  | Users can still choose to explicitly mount with the less secure | ||||
|  | dialect (for old servers) by choosing "vers=1.0" on the cifs | ||||
|  | mount | ||||
|  | 
 | ||||
|  | Signed-off-by: Steve French <smfrench@gmail.com> | ||||
|  | Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com> | ||||
|  | 
 | ||||
|  | --- a/fs/cifs/connect.c	2019-10-19 09:34:13.448215659 +0200
 | ||||
|  | +++ b/fs/cifs/connect.c	2019-10-19 09:41:22.938494534 +0200
 | ||||
|  | @@ -1274,9 +1274,9 @@
 | ||||
|  |   | ||||
|  |  	vol->actimeo = CIFS_DEF_ACTIMEO; | ||||
|  |   | ||||
|  | -	/* FIXME: add autonegotiation -- for now, SMB1 is default */
 | ||||
|  | -	vol->ops = &smb1_operations;
 | ||||
|  | -	vol->vals = &smb1_values;
 | ||||
|  | +	/* FIXME: add autonegotiation for SMB3 or later rather than just SMB3 */
 | ||||
|  | +	vol->ops = &smb30_operations; /* both secure and accepted widely */
 | ||||
|  | +	vol->vals = &smb302_values;
 | ||||
|  |   | ||||
|  |  	if (!mountdata) | ||||
|  |  		goto cifs_parse_mount_err; | ||||
| @ -0,0 +1,50 @@ | |||||
|  | From 89134f0918ec3bf4614ac2f9258543940e611f01 Mon Sep 17 00:00:00 2001 | ||||
|  | From: Arnd Bergmann <arnd@arndb.de> | ||||
|  | Date: Wed, 1 Feb 2017 18:00:14 +0100 | ||||
|  | Subject: modules: mark __inittest/__exittest as __maybe_unused | ||||
|  | 
 | ||||
|  | commit 1f318a8bafcfba9f0d623f4870c4e890fd22e659 upstream. | ||||
|  | 
 | ||||
|  | clang warns about unused inline functions by default: | ||||
|  | 
 | ||||
|  | arch/arm/crypto/aes-cipher-glue.c:68:1: warning: unused function '__inittest' [-Wunused-function] | ||||
|  | arch/arm/crypto/aes-cipher-glue.c:69:1: warning: unused function '__exittest' [-Wunused-function] | ||||
|  | 
 | ||||
|  | As these appear in every single module, let's just disable the warnings by marking the | ||||
|  | two functions as __maybe_unused. | ||||
|  | 
 | ||||
|  | Signed-off-by: Arnd Bergmann <arnd@arndb.de> | ||||
|  | Reviewed-by: Miroslav Benes <mbenes@suse.cz> | ||||
|  | Acked-by: Rusty Russell <rusty@rustcorp.com.au> | ||||
|  | Signed-off-by: Jessica Yu <jeyu@redhat.com> | ||||
|  | Signed-off-by: Nathan Chancellor <natechancellor@gmail.com> | ||||
|  | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | ||||
|  | ---
 | ||||
|  |  include/linux/module.h | 4 ++-- | ||||
|  |  1 file changed, 2 insertions(+), 2 deletions(-) | ||||
|  | 
 | ||||
|  | (limited to 'include/linux/module.h') | ||||
|  | 
 | ||||
|  | diff --git a/include/linux/module.h b/include/linux/module.h
 | ||||
|  | index c9f2f85017ad..dfe5c2e25ba1 100644
 | ||||
|  | --- a/include/linux/module.h
 | ||||
|  | +++ b/include/linux/module.h
 | ||||
|  | @@ -125,13 +125,13 @@ extern void cleanup_module(void);
 | ||||
|  |   | ||||
|  |  /* Each module must use one module_init(). */ | ||||
|  |  #define module_init(initfn)					\ | ||||
|  | -	static inline initcall_t __inittest(void)		\
 | ||||
|  | +	static inline initcall_t __maybe_unused __inittest(void)		\
 | ||||
|  |  	{ return initfn; }					\ | ||||
|  |  	int init_module(void) __attribute__((alias(#initfn))); | ||||
|  |   | ||||
|  |  /* This is only required if you want to be unloadable. */ | ||||
|  |  #define module_exit(exitfn)					\ | ||||
|  | -	static inline exitcall_t __exittest(void)		\
 | ||||
|  | +	static inline exitcall_t __maybe_unused __exittest(void)		\
 | ||||
|  |  	{ return exitfn; }					\ | ||||
|  |  	void cleanup_module(void) __attribute__((alias(#exitfn))); | ||||
|  |   | ||||
|  | -- 
 | ||||
|  | cgit 1.2-0.3.lf.el7 | ||||
|  | 
 | ||||
| @ -0,0 +1,84 @@ | |||||
|  | From 170051d60cf08f9ae2cf296fb8410afdf56a911f Mon Sep 17 00:00:00 2001 | ||||
|  | From: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com> | ||||
|  | Date: Sat, 19 Jan 2019 20:59:34 +0100 | ||||
|  | Subject: include/linux/module.h: copy __init/__exit attrs to | ||||
|  |  init/cleanup_module | ||||
|  | 
 | ||||
|  | [ Upstream commit a6e60d84989fa0e91db7f236eda40453b0e44afa ] | ||||
|  | 
 | ||||
|  | The upcoming GCC 9 release extends the -Wmissing-attributes warnings | ||||
|  | (enabled by -Wall) to C and aliases: it warns when particular function | ||||
|  | attributes are missing in the aliases but not in their target. | ||||
|  | 
 | ||||
|  | In particular, it triggers for all the init/cleanup_module | ||||
|  | aliases in the kernel (defined by the module_init/exit macros), | ||||
|  | ending up being very noisy. | ||||
|  | 
 | ||||
|  | These aliases point to the __init/__exit functions of a module, | ||||
|  | which are defined as __cold (among other attributes). However, | ||||
|  | the aliases themselves do not have the __cold attribute. | ||||
|  | 
 | ||||
|  | Since the compiler behaves differently when compiling a __cold | ||||
|  | function as well as when compiling paths leading to calls | ||||
|  | to __cold functions, the warning is trying to point out | ||||
|  | the possibly-forgotten attribute in the alias. | ||||
|  | 
 | ||||
|  | In order to keep the warning enabled, we decided to silence | ||||
|  | this case. Ideally, we would mark the aliases directly | ||||
|  | as __init/__exit. However, there are currently around 132 modules | ||||
|  | in the kernel which are missing __init/__exit in their init/cleanup | ||||
|  | functions (either because they are missing, or for other reasons, | ||||
|  | e.g. the functions being called from somewhere else); and | ||||
|  | a section mismatch is a hard error. | ||||
|  | 
 | ||||
|  | A conservative alternative was to mark the aliases as __cold only. | ||||
|  | However, since we would like to eventually enforce __init/__exit | ||||
|  | to be always marked,  we chose to use the new __copy function | ||||
|  | attribute (introduced by GCC 9 as well to deal with this). | ||||
|  | With it, we copy the attributes used by the target functions | ||||
|  | into the aliases. This way, functions that were not marked | ||||
|  | as __init/__exit won't have their aliases marked either, | ||||
|  | and therefore there won't be a section mismatch. | ||||
|  | 
 | ||||
|  | Note that the warning would go away marking either the extern | ||||
|  | declaration, the definition, or both. However, we only mark | ||||
|  | the definition of the alias, since we do not want callers | ||||
|  | (which only see the declaration) to be compiled as if the function | ||||
|  | was __cold (and therefore the paths leading to those calls | ||||
|  | would be assumed to be unlikely). | ||||
|  | 
 | ||||
|  | Link: https://lore.kernel.org/lkml/20190123173707.GA16603@gmail.com/ | ||||
|  | Link: https://lore.kernel.org/lkml/20190206175627.GA20399@gmail.com/ | ||||
|  | Suggested-by: Martin Sebor <msebor@gcc.gnu.org> | ||||
|  | Acked-by: Jessica Yu <jeyu@kernel.org> | ||||
|  | Signed-off-by: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com> | ||||
|  | Signed-off-by: Sasha Levin <sashal@kernel.org> | ||||
|  | ---
 | ||||
|  |  include/linux/module.h | 4 ++-- | ||||
|  |  1 file changed, 2 insertions(+), 2 deletions(-) | ||||
|  | 
 | ||||
|  | (limited to 'include/linux/module.h') | ||||
|  | 
 | ||||
|  | diff --git a/include/linux/module.h b/include/linux/module.h
 | ||||
|  | index dfe5c2e25ba1..d237d0574179 100644
 | ||||
|  | --- a/include/linux/module.h
 | ||||
|  | +++ b/include/linux/module.h
 | ||||
|  | @@ -127,13 +127,13 @@ extern void cleanup_module(void);
 | ||||
|  |  #define module_init(initfn)					\ | ||||
|  |  	static inline initcall_t __maybe_unused __inittest(void)		\ | ||||
|  |  	{ return initfn; }					\ | ||||
|  | -	int init_module(void) __attribute__((alias(#initfn)));
 | ||||
|  | +	int init_module(void) __copy(initfn) __attribute__((alias(#initfn)));
 | ||||
|  |   | ||||
|  |  /* This is only required if you want to be unloadable. */ | ||||
|  |  #define module_exit(exitfn)					\ | ||||
|  |  	static inline exitcall_t __maybe_unused __exittest(void)		\ | ||||
|  |  	{ return exitfn; }					\ | ||||
|  | -	void cleanup_module(void) __attribute__((alias(#exitfn)));
 | ||||
|  | +	void cleanup_module(void) __copy(exitfn) __attribute__((alias(#exitfn)));
 | ||||
|  |   | ||||
|  |  #endif | ||||
|  |   | ||||
|  | -- 
 | ||||
|  | cgit 1.2-0.3.lf.el7 | ||||
|  | 
 | ||||
| @ -0,0 +1,51 @@ | |||||
|  | From edc966de8725f9186cc9358214da89d335f0e0bd Mon Sep 17 00:00:00 2001 | ||||
|  | From: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com> | ||||
|  | Date: Fri, 2 Aug 2019 12:37:56 +0200 | ||||
|  | Subject: Backport minimal compiler_attributes.h to support GCC 9 | ||||
|  | 
 | ||||
|  | This adds support for __copy to v4.9.y so that we can use it in | ||||
|  | init/exit_module to avoid -Werror=missing-attributes errors on GCC 9. | ||||
|  | 
 | ||||
|  | Link: https://lore.kernel.org/lkml/259986242.BvXPX32bHu@devpool35/ | ||||
|  | Cc: <stable@vger.kernel.org> | ||||
|  | Suggested-by: Rolf Eike Beer <eb@emlix.com> | ||||
|  | Signed-off-by: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com> | ||||
|  | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | ||||
|  | 
 | ||||
|  | Signed-off-by: Sasha Levin <sashal@kernel.org> | ||||
|  | ---
 | ||||
|  |  include/linux/compiler.h | 16 ++++++++++++++++ | ||||
|  |  1 file changed, 16 insertions(+) | ||||
|  | 
 | ||||
|  | (limited to 'include/linux') | ||||
|  | 
 | ||||
|  | diff --git a/include/linux/compiler.h b/include/linux/compiler.h
 | ||||
|  | index ed772311ec1f..5508011cc0c7 100644
 | ||||
|  | --- a/include/linux/compiler.h
 | ||||
|  | +++ b/include/linux/compiler.h
 | ||||
|  | @@ -52,6 +52,22 @@ extern void __chk_io_ptr(const volatile void __iomem *);
 | ||||
|  |   | ||||
|  |  #ifdef __KERNEL__ | ||||
|  |   | ||||
|  | +/*
 | ||||
|  | + * Minimal backport of compiler_attributes.h to add support for __copy
 | ||||
|  | + * to v4.9.y so that we can use it in init/exit_module to avoid
 | ||||
|  | + * -Werror=missing-attributes errors on GCC 9.
 | ||||
|  | + */
 | ||||
|  | +#ifndef __has_attribute
 | ||||
|  | +# define __has_attribute(x) __GCC4_has_attribute_##x
 | ||||
|  | +# define __GCC4_has_attribute___copy__                0
 | ||||
|  | +#endif
 | ||||
|  | +
 | ||||
|  | +#if __has_attribute(__copy__)
 | ||||
|  | +# define __copy(symbol)                 __attribute__((__copy__(symbol)))
 | ||||
|  | +#else
 | ||||
|  | +# define __copy(symbol)
 | ||||
|  | +#endif
 | ||||
|  | +
 | ||||
|  |  #ifdef __GNUC__ | ||||
|  |  #include <linux/compiler-gcc.h> | ||||
|  |  #endif | ||||
|  | -- 
 | ||||
|  | cgit 1.2-0.3.lf.el7 | ||||
|  | 
 | ||||
| @ -0,0 +1,33 @@ | |||||
|  | From 07d45a42fa21b54d83e563565699d25bde9f8cbe Mon Sep 17 00:00:00 2001 | ||||
|  | From: Olli Salonen <olli.salonen@iki.fi> | ||||
|  | Date: Sun, 30 Jul 2017 08:34:48 -0400 | ||||
|  | Subject: media: mn88472: reset stream ID reg if no PLP given | ||||
|  | 
 | ||||
|  | If the PLP given is NO_STREAM_ID_FILTER (~0u) don't try to set that into the PLP register. Set PLP to 0 instead. | ||||
|  | 
 | ||||
|  | Signed-off-by: Olli Salonen <olli.salonen@iki.fi> | ||||
|  | Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> | ||||
|  | ---
 | ||||
|  |  drivers/media/dvb-frontends/mn88472.c | 4 +++- | ||||
|  |  1 file changed, 3 insertions(+), 1 deletion(-) | ||||
|  | 
 | ||||
|  | (limited to 'drivers/media/dvb-frontends/mn88472.c') | ||||
|  | 
 | ||||
|  | diff --git a/drivers/media/dvb-frontends/mn88472.c b/drivers/media/dvb-frontends/mn88472.c
 | ||||
|  | index f6938f9607ac..5e8fd63832e9 100644
 | ||||
|  | --- a/drivers/staging/media/mn88472/mn88472.c
 | ||||
|  | +++ b/drivers/staging/media/mn88472/mn88472.c
 | ||||
|  | @@ -255,7 +255,9 @@ static int mn88472_set_frontend(struct dvb_frontend *fe)
 | ||||
|  |  		ret = regmap_write(dev->regmap[1], 0xf6, 0x05); | ||||
|  |  		if (ret) | ||||
|  |  			goto err; | ||||
|  | -		ret = regmap_write(dev->regmap[2], 0x32, c->stream_id);
 | ||||
|  | +		ret = regmap_write(dev->regmap[2], 0x32,
 | ||||
|  | +				(c->stream_id == NO_STREAM_ID_FILTER) ? 0 :
 | ||||
|  | +				c->stream_id );
 | ||||
|  |  		if (ret) | ||||
|  |  			goto err; | ||||
|  |  		break; | ||||
|  | -- 
 | ||||
|  | cgit 1.2.3-1.el7 | ||||
|  | 
 | ||||
| @ -1,11 +0,0 @@ | |||||
| --- a/net/wireless/scan.c
 |  | ||||
| +++ b/net/wireless/scan.c
 |  | ||||
| @@ -56,7 +56,7 @@
 |  | ||||
|   * also linked into the probe response struct. |  | ||||
|   */ |  | ||||
|   |  | ||||
| -#define IEEE80211_SCAN_RESULT_EXPIRE	(7 * HZ)
 |  | ||||
| +#define IEEE80211_SCAN_RESULT_EXPIRE	(30 * HZ)
 |  | ||||
|   |  | ||||
|  static void bss_free(struct cfg80211_internal_bss *bss) |  | ||||
|  { |  | ||||
					Loading…
					
					
				
		Reference in new issue