vanhofen
3 years ago
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