[PATCH 5/9] cxd2820r: wrap legacy DVBv3 statistics via DVBv5 statistics

2016-09-02 Thread Antti Palosaari
Return DVBv5 statistics via legacy DVBv3 API.

Signed-off-by: Antti Palosaari 
---
 drivers/media/dvb-frontends/cxd2820r_c.c| 108 
 drivers/media/dvb-frontends/cxd2820r_core.c |  85 ++
 drivers/media/dvb-frontends/cxd2820r_priv.h |  25 +--
 drivers/media/dvb-frontends/cxd2820r_t.c|  94 
 drivers/media/dvb-frontends/cxd2820r_t2.c   |  87 --
 5 files changed, 22 insertions(+), 377 deletions(-)

diff --git a/drivers/media/dvb-frontends/cxd2820r_c.c 
b/drivers/media/dvb-frontends/cxd2820r_c.c
index 7cdcd55..82df944 100644
--- a/drivers/media/dvb-frontends/cxd2820r_c.c
+++ b/drivers/media/dvb-frontends/cxd2820r_c.c
@@ -149,114 +149,6 @@ error:
return ret;
 }
 
-int cxd2820r_read_ber_c(struct dvb_frontend *fe, u32 *ber)
-{
-   struct cxd2820r_priv *priv = fe->demodulator_priv;
-   int ret;
-   u8 buf[3], start_ber = 0;
-   *ber = 0;
-
-   if (priv->ber_running) {
-   ret = cxd2820r_rd_regs(priv, 0x10076, buf, sizeof(buf));
-   if (ret)
-   goto error;
-
-   if ((buf[2] >> 7) & 0x01 || (buf[2] >> 4) & 0x01) {
-   *ber = (buf[2] & 0x0f) << 16 | buf[1] << 8 | buf[0];
-   start_ber = 1;
-   }
-   } else {
-   priv->ber_running = true;
-   start_ber = 1;
-   }
-
-   if (start_ber) {
-   /* (re)start BER */
-   ret = cxd2820r_wr_reg(priv, 0x10079, 0x01);
-   if (ret)
-   goto error;
-   }
-
-   return ret;
-error:
-   dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-   return ret;
-}
-
-int cxd2820r_read_signal_strength_c(struct dvb_frontend *fe,
-   u16 *strength)
-{
-   struct cxd2820r_priv *priv = fe->demodulator_priv;
-   int ret;
-   u8 buf[2];
-   u16 tmp;
-
-   ret = cxd2820r_rd_regs(priv, 0x10049, buf, sizeof(buf));
-   if (ret)
-   goto error;
-
-   tmp = (buf[0] & 0x03) << 8 | buf[1];
-   tmp = (~tmp & 0x03ff);
-
-   if (tmp == 512)
-   /* ~no signal */
-   tmp = 0;
-   else if (tmp > 350)
-   tmp = 350;
-
-   /* scale value to 0x-0x */
-   *strength = tmp * 0x / (350-0);
-
-   return ret;
-error:
-   dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-   return ret;
-}
-
-int cxd2820r_read_snr_c(struct dvb_frontend *fe, u16 *snr)
-{
-   struct cxd2820r_priv *priv = fe->demodulator_priv;
-   int ret;
-   u8 tmp;
-   unsigned int A, B;
-   /* report SNR in dB * 10 */
-
-   ret = cxd2820r_rd_reg(priv, 0x10019, &tmp);
-   if (ret)
-   goto error;
-
-   if (((tmp >> 0) & 0x03) % 2) {
-   A = 875;
-   B = 650;
-   } else {
-   A = 950;
-   B = 760;
-   }
-
-   ret = cxd2820r_rd_reg(priv, 0x1004d, &tmp);
-   if (ret)
-   goto error;
-
-   #define CXD2820R_LOG2_E_24 24204406 /* log2(e) << 24 */
-   if (tmp)
-   *snr = A * (intlog2(B / tmp) >> 5) / (CXD2820R_LOG2_E_24 >> 5)
-   / 10;
-   else
-   *snr = 0;
-
-   return ret;
-error:
-   dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-   return ret;
-}
-
-int cxd2820r_read_ucblocks_c(struct dvb_frontend *fe, u32 *ucblocks)
-{
-   *ucblocks = 0;
-   /* no way to read ? */
-   return 0;
-}
-
 int cxd2820r_read_status_c(struct dvb_frontend *fe, enum fe_status *status)
 {
struct cxd2820r_priv *priv = fe->demodulator_priv;
diff --git a/drivers/media/dvb-frontends/cxd2820r_core.c 
b/drivers/media/dvb-frontends/cxd2820r_core.c
index 314d3b8..66da821 100644
--- a/drivers/media/dvb-frontends/cxd2820r_core.c
+++ b/drivers/media/dvb-frontends/cxd2820r_core.c
@@ -345,101 +345,58 @@ static int cxd2820r_get_frontend(struct dvb_frontend *fe,
 static int cxd2820r_read_ber(struct dvb_frontend *fe, u32 *ber)
 {
struct cxd2820r_priv *priv = fe->demodulator_priv;
-   int ret;
 
dev_dbg(&priv->i2c->dev, "%s: delsys=%d\n", __func__,
fe->dtv_property_cache.delivery_system);
 
-   switch (fe->dtv_property_cache.delivery_system) {
-   case SYS_DVBT:
-   ret = cxd2820r_read_ber_t(fe, ber);
-   break;
-   case SYS_DVBT2:
-   ret = cxd2820r_read_ber_t2(fe, ber);
-   break;
-   case SYS_DVBC_ANNEX_A:
-   ret = cxd2820r_read_ber_c(fe, ber);
-   break;
-   default:
-   ret = -EINVAL;
-   break;
-   }
-   return ret;
+   *ber =

[PATCH 6/9] cxd2820r: add I2C driver bindings

2016-09-02 Thread Antti Palosaari
Add I2C driver bindings in order to support proper I2C driver
registration with driver core.

Signed-off-by: Antti Palosaari 
---
 drivers/media/dvb-frontends/cxd2820r.h  |  26 
 drivers/media/dvb-frontends/cxd2820r_c.c|   6 +-
 drivers/media/dvb-frontends/cxd2820r_core.c | 190 ++--
 drivers/media/dvb-frontends/cxd2820r_priv.h |   7 +-
 drivers/media/dvb-frontends/cxd2820r_t.c|   6 +-
 drivers/media/dvb-frontends/cxd2820r_t2.c   |   8 +-
 6 files changed, 191 insertions(+), 52 deletions(-)

diff --git a/drivers/media/dvb-frontends/cxd2820r.h 
b/drivers/media/dvb-frontends/cxd2820r.h
index 56d4276..d77afe0 100644
--- a/drivers/media/dvb-frontends/cxd2820r.h
+++ b/drivers/media/dvb-frontends/cxd2820r.h
@@ -37,6 +37,32 @@
 #define CXD2820R_TS_PARALLEL  0x30
 #define CXD2820R_TS_PARALLEL_MSB  0x70
 
+/*
+ * I2C address: 0x6c, 0x6d
+ */
+
+/**
+ * struct cxd2820r_platform_data - Platform data for the cxd2820r driver
+ * @ts_mode: TS mode.
+ * @ts_clk_inv: TS clock inverted.
+ * @if_agc_polarity: IF AGC polarity.
+ * @spec_inv: Input spectrum inverted.
+ * @gpio_chip_base: GPIO.
+ * @get_dvb_frontend: Get DVB frontend.
+ */
+
+struct cxd2820r_platform_data {
+   u8 ts_mode;
+   bool ts_clk_inv;
+   bool if_agc_polarity;
+   bool spec_inv;
+   int **gpio_chip_base;
+
+   struct dvb_frontend* (*get_dvb_frontend)(struct i2c_client *);
+/* private: For legacy media attach wrapper. Do not set value. */
+   bool attach_in_use;
+};
+
 struct cxd2820r_config {
/* Demodulator I2C address.
 * Driver determines DVB-C slave I2C address automatically from master
diff --git a/drivers/media/dvb-frontends/cxd2820r_c.c 
b/drivers/media/dvb-frontends/cxd2820r_c.c
index 82df944..0d036e1 100644
--- a/drivers/media/dvb-frontends/cxd2820r_c.c
+++ b/drivers/media/dvb-frontends/cxd2820r_c.c
@@ -42,9 +42,9 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
{ 0x10059, 0x50, 0xff },
{ 0x10087, 0x0c, 0x3c },
{ 0x1008b, 0x07, 0xff },
-   { 0x1001f, priv->cfg.if_agc_polarity << 7, 0x80 },
-   { 0x10070, priv->cfg.ts_mode, 0xff },
-   { 0x10071, !priv->cfg.ts_clock_inv << 4, 0x10 },
+   { 0x1001f, priv->if_agc_polarity << 7, 0x80 },
+   { 0x10070, priv->ts_mode, 0xff },
+   { 0x10071, !priv->ts_clk_inv << 4, 0x10 },
};
 
dev_dbg(&priv->i2c->dev, "%s: frequency=%d symbol_rate=%d\n", __func__,
diff --git a/drivers/media/dvb-frontends/cxd2820r_core.c 
b/drivers/media/dvb-frontends/cxd2820r_core.c
index 66da821..cf5eed4 100644
--- a/drivers/media/dvb-frontends/cxd2820r_core.c
+++ b/drivers/media/dvb-frontends/cxd2820r_core.c
@@ -49,7 +49,7 @@ static int cxd2820r_wr_regs_i2c(struct cxd2820r_priv *priv, 
u8 i2c, u8 reg,
buf[0] = reg;
memcpy(&buf[1], val, len);
 
-   ret = i2c_transfer(priv->i2c, msg, 1);
+   ret = i2c_transfer(priv->client[0]->adapter, msg, 1);
if (ret == 1) {
ret = 0;
} else {
@@ -87,7 +87,7 @@ static int cxd2820r_rd_regs_i2c(struct cxd2820r_priv *priv, 
u8 i2c, u8 reg,
return -EINVAL;
}
 
-   ret = i2c_transfer(priv->i2c, msg, 2);
+   ret = i2c_transfer(priv->client[0]->adapter, msg, 2);
if (ret == 2) {
memcpy(val, buf, len);
ret = 0;
@@ -112,9 +112,9 @@ int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 
reginfo, u8 *val,
 
/* select I2C */
if (i2c)
-   i2c_addr = priv->cfg.i2c_address | (1 << 1); /* DVB-C */
+   i2c_addr = priv->client[1]->addr; /* DVB-C */
else
-   i2c_addr = priv->cfg.i2c_address; /* DVB-T/T2 */
+   i2c_addr = priv->client[0]->addr; /* DVB-T/T2 */
 
/* switch bank if needed */
if (bank != priv->bank[i2c]) {
@@ -138,9 +138,9 @@ int cxd2820r_rd_regs(struct cxd2820r_priv *priv, u32 
reginfo, u8 *val,
 
/* select I2C */
if (i2c)
-   i2c_addr = priv->cfg.i2c_address | (1 << 1); /* DVB-C */
+   i2c_addr = priv->client[1]->addr; /* DVB-C */
else
-   i2c_addr = priv->cfg.i2c_address; /* DVB-T/T2 */
+   i2c_addr = priv->client[0]->addr; /* DVB-T/T2 */
 
/* switch bank if needed */
if (bank != priv->bank[i2c]) {
@@ -537,16 +537,12 @@ static int cxd2820r_get_frontend_algo(struct dvb_frontend 
*fe)
 static void cxd2820r_release(struct dvb_frontend *fe)
 {
struct cxd2820r_priv *priv = fe->demodulator_priv;
+   struct i2c_client *client = priv->client[0];
 
dev_dbg(&priv->i2c->dev, "%s\n", __func__);
 
-#ifdef CONFIG_GPIOLIB
-   /* remove GPIOs */
-   if (priv->gpio_chip.label)
-   g

[PATCH 1/9] cxd2820r: improve IF frequency setting

2016-09-02 Thread Antti Palosaari
Use 64-bit calculation.

Return error if tuner does not provide get_if_frequency() callback.
All currently used tuners has it.

Signed-off-by: Antti Palosaari 
---
 drivers/media/dvb-frontends/cxd2820r_c.c| 26 +++
 drivers/media/dvb-frontends/cxd2820r_priv.h |  2 ++
 drivers/media/dvb-frontends/cxd2820r_t.c| 27 ---
 drivers/media/dvb-frontends/cxd2820r_t2.c   | 33 ++---
 4 files changed, 43 insertions(+), 45 deletions(-)

diff --git a/drivers/media/dvb-frontends/cxd2820r_c.c 
b/drivers/media/dvb-frontends/cxd2820r_c.c
index a674a63..957ec94 100644
--- a/drivers/media/dvb-frontends/cxd2820r_c.c
+++ b/drivers/media/dvb-frontends/cxd2820r_c.c
@@ -26,10 +26,9 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
struct cxd2820r_priv *priv = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret, i;
+   unsigned int utmp;
u8 buf[2];
-   u32 if_freq;
-   u16 if_ctl;
-   u64 num;
+   u32 if_frequency;
struct reg_val_mask tab[] = {
{ 0x00080, 0x01, 0xff },
{ 0x00081, 0x05, 0xff },
@@ -69,20 +68,19 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
 
/* program IF frequency */
if (fe->ops.tuner_ops.get_if_frequency) {
-   ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
+   ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
if (ret)
goto error;
-   } else
-   if_freq = 0;
-
-   dev_dbg(&priv->i2c->dev, "%s: if_freq=%d\n", __func__, if_freq);
-
-   num = if_freq / 1000; /* Hz => kHz */
-   num *= 0x4000;
-   if_ctl = 0x4000 - DIV_ROUND_CLOSEST_ULL(num, 41000);
-   buf[0] = (if_ctl >> 8) & 0x3f;
-   buf[1] = (if_ctl >> 0) & 0xff;
+   dev_dbg(&priv->i2c->dev, "%s: if_frequency=%u\n", __func__,
+   if_frequency);
+   } else {
+   ret = -EINVAL;
+   goto error;
+   }
 
+   utmp = 0x4000 - DIV_ROUND_CLOSEST_ULL((u64)if_frequency * 0x4000, 
CXD2820R_CLK);
+   buf[0] = (utmp >> 8) & 0xff;
+   buf[1] = (utmp >> 0) & 0xff;
ret = cxd2820r_wr_regs(priv, 0x10042, buf, 2);
if (ret)
goto error;
diff --git a/drivers/media/dvb-frontends/cxd2820r_priv.h 
b/drivers/media/dvb-frontends/cxd2820r_priv.h
index e31c48e..acfae17 100644
--- a/drivers/media/dvb-frontends/cxd2820r_priv.h
+++ b/drivers/media/dvb-frontends/cxd2820r_priv.h
@@ -34,6 +34,8 @@ struct reg_val_mask {
u8  mask;
 };
 
+#define CXD2820R_CLK 4100
+
 struct cxd2820r_priv {
struct i2c_adapter *i2c;
struct dvb_frontend fe;
diff --git a/drivers/media/dvb-frontends/cxd2820r_t.c 
b/drivers/media/dvb-frontends/cxd2820r_t.c
index 75ce7d8..67cc33b 100644
--- a/drivers/media/dvb-frontends/cxd2820r_t.c
+++ b/drivers/media/dvb-frontends/cxd2820r_t.c
@@ -26,8 +26,8 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe)
struct cxd2820r_priv *priv = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret, i, bw_i;
-   u32 if_freq, if_ctl;
-   u64 num;
+   unsigned int utmp;
+   u32 if_frequency;
u8 buf[3], bw_param;
u8 bw_params1[][5] = {
{ 0x17, 0xea, 0xaa, 0xaa, 0xaa }, /* 6 MHz */
@@ -93,21 +93,20 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe)
 
/* program IF frequency */
if (fe->ops.tuner_ops.get_if_frequency) {
-   ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
+   ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
if (ret)
goto error;
-   } else
-   if_freq = 0;
-
-   dev_dbg(&priv->i2c->dev, "%s: if_freq=%d\n", __func__, if_freq);
-
-   num = if_freq / 1000; /* Hz => kHz */
-   num *= 0x100;
-   if_ctl = DIV_ROUND_CLOSEST_ULL(num, 41000);
-   buf[0] = ((if_ctl >> 16) & 0xff);
-   buf[1] = ((if_ctl >>  8) & 0xff);
-   buf[2] = ((if_ctl >>  0) & 0xff);
+   dev_dbg(&priv->i2c->dev, "%s: if_frequency=%u\n", __func__,
+   if_frequency);
+   } else {
+   ret = -EINVAL;
+   goto error;
+   }
 
+   utmp = DIV_ROUND_CLOSEST_ULL((u64)if_frequency * 0x100, 
CXD2820R_CLK);
+   buf[0] = (utmp >> 16) & 0xff;
+   buf[1] = (utmp >>  8) & 0xff;
+   buf[2] = (utmp >>  0) & 0xff;
ret = cxd2820r_wr_regs(priv, 0x000b6, buf, 3);
if (ret)
goto error;
diff --git a/drivers/media/dvb-frontends/cxd2820r_t2.c 
b/drivers/media/

[PATCH 8/9] cxd2820r: improve lock detection

2016-09-02 Thread Antti Palosaari
Check demod and ts locks and report lock status according to those.

Signed-off-by: Antti Palosaari 
---
 drivers/media/dvb-frontends/cxd2820r_c.c  | 29 
 drivers/media/dvb-frontends/cxd2820r_t.c  | 44 ---
 drivers/media/dvb-frontends/cxd2820r_t2.c | 26 ++
 3 files changed, 50 insertions(+), 49 deletions(-)

diff --git a/drivers/media/dvb-frontends/cxd2820r_c.c 
b/drivers/media/dvb-frontends/cxd2820r_c.c
index beb46a6..0f96add 100644
--- a/drivers/media/dvb-frontends/cxd2820r_c.c
+++ b/drivers/media/dvb-frontends/cxd2820r_c.c
@@ -160,25 +160,32 @@ int cxd2820r_read_status_c(struct dvb_frontend *fe, enum 
fe_status *status)
struct i2c_client *client = priv->client[0];
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret;
-   unsigned int utmp;
+   unsigned int utmp, utmp1, utmp2;
u8 buf[3];
-   *status = 0;
 
-   ret = cxd2820r_rd_regs(priv, 0x10088, buf, 2);
+   /* Lock detection */
+   ret = cxd2820r_rd_reg(priv, 0x10088, &buf[0]);
+   if (ret)
+   goto error;
+   ret = cxd2820r_rd_reg(priv, 0x10073, &buf[1]);
if (ret)
goto error;
 
-   if (((buf[0] >> 0) & 0x01) == 1) {
-   *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
-   FE_HAS_VITERBI | FE_HAS_SYNC;
+   utmp1 = (buf[0] >> 0) & 0x01;
+   utmp2 = (buf[1] >> 3) & 0x01;
 
-   if (((buf[1] >> 3) & 0x01) == 1) {
-   *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
-   FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
-   }
+   if (utmp1 == 1 && utmp2 == 1) {
+   *status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
+ FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+   } else if (utmp1 == 1 || utmp2 == 1) {
+   *status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
+ FE_HAS_VITERBI | FE_HAS_SYNC;
+   } else {
+   *status = 0;
}
 
-   dev_dbg(&client->dev, "lock=%*ph\n", 2, buf);
+   dev_dbg(&client->dev, "status=%02x raw=%*ph sync=%u ts=%u\n",
+   *status, 2, buf, utmp1, utmp2);
 
/* Signal strength */
if (*status & FE_HAS_SIGNAL) {
diff --git a/drivers/media/dvb-frontends/cxd2820r_t.c 
b/drivers/media/dvb-frontends/cxd2820r_t.c
index 174d916..19f72cd 100644
--- a/drivers/media/dvb-frontends/cxd2820r_t.c
+++ b/drivers/media/dvb-frontends/cxd2820r_t.c
@@ -265,42 +265,32 @@ int cxd2820r_read_status_t(struct dvb_frontend *fe, enum 
fe_status *status)
struct i2c_client *client = priv->client[0];
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret;
-   unsigned int utmp;
-   u8 buf[4];
-   *status = 0;
+   unsigned int utmp, utmp1, utmp2;
+   u8 buf[3];
 
+   /* Lock detection */
ret = cxd2820r_rd_reg(priv, 0x00010, &buf[0]);
if (ret)
goto error;
+   ret = cxd2820r_rd_reg(priv, 0x00073, &buf[1]);
+   if (ret)
+   goto error;
 
-   if ((buf[0] & 0x07) == 6) {
-   ret = cxd2820r_rd_reg(priv, 0x00073, &buf[1]);
-   if (ret)
-   goto error;
+   utmp1 = (buf[0] >> 0) & 0x07;
+   utmp2 = (buf[1] >> 3) & 0x01;
 
-   if (((buf[1] >> 3) & 0x01) == 1) {
-   *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
-   FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
-   } else {
-   *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
-   FE_HAS_VITERBI | FE_HAS_SYNC;
-   }
+   if (utmp1 == 6 && utmp2 == 1) {
+   *status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
+ FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+   } else if (utmp1 == 6 || utmp2 == 1) {
+   *status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
+ FE_HAS_VITERBI | FE_HAS_SYNC;
} else {
-   ret = cxd2820r_rd_reg(priv, 0x00014, &buf[2]);
-   if (ret)
-   goto error;
-
-   if ((buf[2] & 0x0f) >= 4) {
-   ret = cxd2820r_rd_reg(priv, 0x00a14, &buf[3]);
-   if (ret)
-   goto error;
-
-   if (((buf[3] >> 4) & 0x01) == 1)
-   *status |= FE_HAS_SIGNAL;
-   }
+   *status = 0;
}
 
-   dev_dbg(&client->dev, "lock=%*ph\n", 4, buf);
+   dev_dbg(&client->dev, "status=%02x raw=%*ph sync=%u ts=%u\n",
+   *status, 2, buf, utmp1, utmp2);
 
/* Signal s

[PATCH 2/9] cxd2820r: dvbv5 statistics for DVB-T

2016-09-02 Thread Antti Palosaari
Implement dvbv5 statistics for DVB-T.

Signed-off-by: Antti Palosaari 
---
 drivers/media/dvb-frontends/cxd2820r_priv.h |  2 +
 drivers/media/dvb-frontends/cxd2820r_t.c| 88 +
 2 files changed, 90 insertions(+)

diff --git a/drivers/media/dvb-frontends/cxd2820r_priv.h 
b/drivers/media/dvb-frontends/cxd2820r_priv.h
index acfae17..a97570b 100644
--- a/drivers/media/dvb-frontends/cxd2820r_priv.h
+++ b/drivers/media/dvb-frontends/cxd2820r_priv.h
@@ -27,6 +27,7 @@
 #include "dvb_math.h"
 #include "cxd2820r.h"
 #include 
+#include 
 
 struct reg_val_mask {
u32 reg;
@@ -40,6 +41,7 @@ struct cxd2820r_priv {
struct i2c_adapter *i2c;
struct dvb_frontend fe;
struct cxd2820r_config cfg;
+   u64 post_bit_error;
 
bool ber_running;
 
diff --git a/drivers/media/dvb-frontends/cxd2820r_t.c 
b/drivers/media/dvb-frontends/cxd2820r_t.c
index 67cc33b..d402ab6 100644
--- a/drivers/media/dvb-frontends/cxd2820r_t.c
+++ b/drivers/media/dvb-frontends/cxd2820r_t.c
@@ -351,7 +351,9 @@ int cxd2820r_read_ucblocks_t(struct dvb_frontend *fe, u32 
*ucblocks)
 int cxd2820r_read_status_t(struct dvb_frontend *fe, enum fe_status *status)
 {
struct cxd2820r_priv *priv = fe->demodulator_priv;
+   struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret;
+   unsigned int utmp;
u8 buf[4];
*status = 0;
 
@@ -388,6 +390,92 @@ int cxd2820r_read_status_t(struct dvb_frontend *fe, enum 
fe_status *status)
 
dev_dbg(&priv->i2c->dev, "%s: lock=%*ph\n", __func__, 4, buf);
 
+   /* Signal strength */
+   if (*status & FE_HAS_SIGNAL) {
+   unsigned int strength;
+
+   ret = cxd2820r_rd_regs(priv, 0x00026, buf, 2);
+   if (ret)
+   goto error;
+
+   utmp = buf[0] << 8 | buf[1] << 0;
+   utmp = ~utmp & 0x0fff;
+   /* Scale value to 0x-0x */
+   strength = utmp << 4 | utmp >> 8;
+
+   c->strength.len = 1;
+   c->strength.stat[0].scale = FE_SCALE_RELATIVE;
+   c->strength.stat[0].uvalue = strength;
+   } else {
+   c->strength.len = 1;
+   c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   }
+
+   /* CNR */
+   if (*status & FE_HAS_VITERBI) {
+   unsigned int cnr;
+
+   ret = cxd2820r_rd_regs(priv, 0x0002c, buf, 2);
+   if (ret)
+   goto error;
+
+   utmp = buf[0] << 8 | buf[1] << 0;
+   if (utmp)
+   cnr = div_u64((u64)(intlog10(utmp)
+ - intlog10(32000 - utmp) + 55532585)
+ * 1, (1 << 24));
+   else
+   cnr = 0;
+
+   c->cnr.len = 1;
+   c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+   c->cnr.stat[0].svalue = cnr;
+   } else {
+   c->cnr.len = 1;
+   c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   }
+
+   /* BER */
+   if (*status & FE_HAS_SYNC) {
+   unsigned int post_bit_error;
+   bool start_ber;
+
+   if (priv->ber_running) {
+   ret = cxd2820r_rd_regs(priv, 0x00076, buf, 3);
+   if (ret)
+   goto error;
+
+   if ((buf[2] >> 7) & 0x01) {
+   post_bit_error = buf[2] << 16 | buf[1] << 8 |
+buf[0] << 0;
+   post_bit_error &= 0x0f;
+   start_ber = true;
+   } else {
+   post_bit_error = 0;
+   start_ber = false;
+   }
+   } else {
+   post_bit_error = 0;
+   start_ber = true;
+   }
+
+   if (start_ber) {
+   ret = cxd2820r_wr_reg(priv, 0x00079, 0x01);
+   if (ret)
+   goto error;
+   priv->ber_running = true;
+   }
+
+   priv->post_bit_error += post_bit_error;
+
+   c->post_bit_error.len = 1;
+   c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+   c->post_bit_error.stat[0].uvalue = priv->post_bit_error;
+   } else {
+   c->post_bit_error.len = 1;
+   c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   }
+
return ret;
 error:
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-- 
http://palosaari.fi/

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 7/9] cxd2820r: correct logging

2016-09-02 Thread Antti Palosaari
Use correct device for logging functions as we now have it due to
proper I2C client bindings.

Signed-off-by: Antti Palosaari 
---
 drivers/media/dvb-frontends/cxd2820r_c.c|  33 +---
 drivers/media/dvb-frontends/cxd2820r_core.c | 115 +++-
 drivers/media/dvb-frontends/cxd2820r_t.c|  32 +---
 drivers/media/dvb-frontends/cxd2820r_t2.c   |  34 
 4 files changed, 123 insertions(+), 91 deletions(-)

diff --git a/drivers/media/dvb-frontends/cxd2820r_c.c 
b/drivers/media/dvb-frontends/cxd2820r_c.c
index 0d036e1..beb46a6 100644
--- a/drivers/media/dvb-frontends/cxd2820r_c.c
+++ b/drivers/media/dvb-frontends/cxd2820r_c.c
@@ -24,6 +24,7 @@
 int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
 {
struct cxd2820r_priv *priv = fe->demodulator_priv;
+   struct i2c_client *client = priv->client[0];
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret, i;
unsigned int utmp;
@@ -47,8 +48,10 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
{ 0x10071, !priv->ts_clk_inv << 4, 0x10 },
};
 
-   dev_dbg(&priv->i2c->dev, "%s: frequency=%d symbol_rate=%d\n", __func__,
-   c->frequency, c->symbol_rate);
+   dev_dbg(&client->dev,
+   "delivery_system=%d modulation=%d frequency=%u symbol_rate=%u 
inversion=%d\n",
+   c->delivery_system, c->modulation, c->frequency,
+   c->symbol_rate, c->inversion);
 
/* program tuner */
if (fe->ops.tuner_ops.set_params)
@@ -71,8 +74,7 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
if (ret)
goto error;
-   dev_dbg(&priv->i2c->dev, "%s: if_frequency=%u\n", __func__,
-   if_frequency);
+   dev_dbg(&client->dev, "if_frequency=%u\n", if_frequency);
} else {
ret = -EINVAL;
goto error;
@@ -95,7 +97,7 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
 
return ret;
 error:
-   dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+   dev_dbg(&client->dev, "failed=%d\n", ret);
return ret;
 }
 
@@ -103,9 +105,12 @@ int cxd2820r_get_frontend_c(struct dvb_frontend *fe,
struct dtv_frontend_properties *c)
 {
struct cxd2820r_priv *priv = fe->demodulator_priv;
+   struct i2c_client *client = priv->client[0];
int ret;
u8 buf[2];
 
+   dev_dbg(&client->dev, "\n");
+
ret = cxd2820r_rd_regs(priv, 0x1001a, buf, 2);
if (ret)
goto error;
@@ -145,13 +150,14 @@ int cxd2820r_get_frontend_c(struct dvb_frontend *fe,
 
return ret;
 error:
-   dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+   dev_dbg(&client->dev, "failed=%d\n", ret);
return ret;
 }
 
 int cxd2820r_read_status_c(struct dvb_frontend *fe, enum fe_status *status)
 {
struct cxd2820r_priv *priv = fe->demodulator_priv;
+   struct i2c_client *client = priv->client[0];
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret;
unsigned int utmp;
@@ -172,8 +178,7 @@ int cxd2820r_read_status_c(struct dvb_frontend *fe, enum 
fe_status *status)
}
}
 
-   dev_dbg(&priv->i2c->dev, "%s: lock=%02x %02x\n", __func__, buf[0],
-   buf[1]);
+   dev_dbg(&client->dev, "lock=%*ph\n", 2, buf);
 
/* Signal strength */
if (*status & FE_HAS_SIGNAL) {
@@ -275,28 +280,32 @@ int cxd2820r_read_status_c(struct dvb_frontend *fe, enum 
fe_status *status)
 
return ret;
 error:
-   dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+   dev_dbg(&client->dev, "failed=%d\n", ret);
return ret;
 }
 
 int cxd2820r_init_c(struct dvb_frontend *fe)
 {
struct cxd2820r_priv *priv = fe->demodulator_priv;
+   struct i2c_client *client = priv->client[0];
int ret;
 
+   dev_dbg(&client->dev, "\n");
+
ret = cxd2820r_wr_reg(priv, 0x00085, 0x07);
if (ret)
goto error;
 
return ret;
 error:
-   dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+   dev_dbg(&client->dev, "failed=%d\n", ret);
return ret;
 }
 
 int cxd2820r_sleep_c(struct dvb_frontend *fe)
 {
struct cxd2820r_priv *priv = fe->demodulator_priv;
+   struct i2c_client *client = priv->client[0];
int ret, i;
struct reg_val_mask tab[] = {
  

[PATCH 9/9] cxd2820r: convert to regmap api

2016-09-02 Thread Antti Palosaari
Use regmap for I2C register access.

Signed-off-by: Antti Palosaari 
---
 drivers/media/dvb-frontends/Kconfig |   1 +
 drivers/media/dvb-frontends/cxd2820r_c.c|  56 +++---
 drivers/media/dvb-frontends/cxd2820r_core.c | 259 ++--
 drivers/media/dvb-frontends/cxd2820r_priv.h |   6 +-
 drivers/media/dvb-frontends/cxd2820r_t.c|  55 +++---
 drivers/media/dvb-frontends/cxd2820r_t2.c   |  55 +++---
 6 files changed, 173 insertions(+), 259 deletions(-)

diff --git a/drivers/media/dvb-frontends/Kconfig 
b/drivers/media/dvb-frontends/Kconfig
index c645aa8..c4b67f7 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -463,6 +463,7 @@ config DVB_STV0367
 config DVB_CXD2820R
tristate "Sony CXD2820R"
depends on DVB_CORE && I2C
+   select REGMAP_I2C
default m if !MEDIA_SUBDRV_AUTOSELECT
help
  Say Y when you want to support this frontend.
diff --git a/drivers/media/dvb-frontends/cxd2820r_c.c 
b/drivers/media/dvb-frontends/cxd2820r_c.c
index 0f96add..d75b077 100644
--- a/drivers/media/dvb-frontends/cxd2820r_c.c
+++ b/drivers/media/dvb-frontends/cxd2820r_c.c
@@ -26,7 +26,7 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
struct cxd2820r_priv *priv = fe->demodulator_priv;
struct i2c_client *client = priv->client[0];
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-   int ret, i;
+   int ret;
unsigned int utmp;
u8 buf[2];
u32 if_frequency;
@@ -58,12 +58,9 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
fe->ops.tuner_ops.set_params(fe);
 
if (priv->delivery_system !=  SYS_DVBC_ANNEX_A) {
-   for (i = 0; i < ARRAY_SIZE(tab); i++) {
-   ret = cxd2820r_wr_reg_mask(priv, tab[i].reg,
-   tab[i].val, tab[i].mask);
-   if (ret)
-   goto error;
-   }
+   ret = cxd2820r_wr_reg_val_mask_tab(priv, tab, ARRAY_SIZE(tab));
+   if (ret)
+   goto error;
}
 
priv->delivery_system = SYS_DVBC_ANNEX_A;
@@ -83,15 +80,15 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
utmp = 0x4000 - DIV_ROUND_CLOSEST_ULL((u64)if_frequency * 0x4000, 
CXD2820R_CLK);
buf[0] = (utmp >> 8) & 0xff;
buf[1] = (utmp >> 0) & 0xff;
-   ret = cxd2820r_wr_regs(priv, 0x10042, buf, 2);
+   ret = regmap_bulk_write(priv->regmap[1], 0x0042, buf, 2);
if (ret)
goto error;
 
-   ret = cxd2820r_wr_reg(priv, 0x000ff, 0x08);
+   ret = regmap_write(priv->regmap[0], 0x00ff, 0x08);
if (ret)
goto error;
 
-   ret = cxd2820r_wr_reg(priv, 0x000fe, 0x01);
+   ret = regmap_write(priv->regmap[0], 0x00fe, 0x01);
if (ret)
goto error;
 
@@ -107,21 +104,22 @@ int cxd2820r_get_frontend_c(struct dvb_frontend *fe,
struct cxd2820r_priv *priv = fe->demodulator_priv;
struct i2c_client *client = priv->client[0];
int ret;
+   unsigned int utmp;
u8 buf[2];
 
dev_dbg(&client->dev, "\n");
 
-   ret = cxd2820r_rd_regs(priv, 0x1001a, buf, 2);
+   ret = regmap_bulk_read(priv->regmap[1], 0x001a, buf, 2);
if (ret)
goto error;
 
c->symbol_rate = 2500 * ((buf[0] & 0x0f) << 8 | buf[1]);
 
-   ret = cxd2820r_rd_reg(priv, 0x10019, &buf[0]);
+   ret = regmap_read(priv->regmap[1], 0x0019, &utmp);
if (ret)
goto error;
 
-   switch ((buf[0] >> 0) & 0x07) {
+   switch ((utmp >> 0) & 0x07) {
case 0:
c->modulation = QAM_16;
break;
@@ -139,7 +137,7 @@ int cxd2820r_get_frontend_c(struct dvb_frontend *fe,
break;
}
 
-   switch ((buf[0] >> 7) & 0x01) {
+   switch ((utmp >> 7) & 0x01) {
case 0:
c->inversion = INVERSION_OFF;
break;
@@ -164,10 +162,10 @@ int cxd2820r_read_status_c(struct dvb_frontend *fe, enum 
fe_status *status)
u8 buf[3];
 
/* Lock detection */
-   ret = cxd2820r_rd_reg(priv, 0x10088, &buf[0]);
+   ret = regmap_bulk_read(priv->regmap[1], 0x0088, &buf[0], 1);
if (ret)
goto error;
-   ret = cxd2820r_rd_reg(priv, 0x10073, &buf[1]);
+   ret = regmap_bulk_read(priv->regmap[1], 0x0073, &buf[1], 1);
if (ret)
goto error;
 
@@ -191,7 +189,7 @@ int cxd2820r_read_status_c(struct dvb_frontend *fe, enum 
fe_status *status)
if (*status & FE_HAS_SIGNAL) {
unsigned int strength;
 
-   ret = cxd2820r_rd_regs(priv, 0x10049, buf, 2);
+   ret = regmap_bu

[PATCH 3/9] cxd2820r: dvbv5 statistics for DVB-T2

2016-09-02 Thread Antti Palosaari
Implement dvbv5 statistics for DVB-T2.

Signed-off-by: Antti Palosaari 
---
 drivers/media/dvb-frontends/cxd2820r_t2.c | 77 ++-
 1 file changed, 76 insertions(+), 1 deletion(-)

diff --git a/drivers/media/dvb-frontends/cxd2820r_t2.c 
b/drivers/media/dvb-frontends/cxd2820r_t2.c
index 14c9a26..e2875f2 100644
--- a/drivers/media/dvb-frontends/cxd2820r_t2.c
+++ b/drivers/media/dvb-frontends/cxd2820r_t2.c
@@ -286,8 +286,10 @@ error:
 int cxd2820r_read_status_t2(struct dvb_frontend *fe, enum fe_status *status)
 {
struct cxd2820r_priv *priv = fe->demodulator_priv;
+   struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret;
-   u8 buf[1];
+   unsigned int utmp;
+   u8 buf[4];
*status = 0;
 
ret = cxd2820r_rd_reg(priv, 0x02010 , &buf[0]);
@@ -306,6 +308,79 @@ int cxd2820r_read_status_t2(struct dvb_frontend *fe, enum 
fe_status *status)
 
dev_dbg(&priv->i2c->dev, "%s: lock=%02x\n", __func__, buf[0]);
 
+   /* Signal strength */
+   if (*status & FE_HAS_SIGNAL) {
+   unsigned int strength;
+
+   ret = cxd2820r_rd_regs(priv, 0x02026, buf, 2);
+   if (ret)
+   goto error;
+
+   utmp = buf[0] << 8 | buf[1] << 0;
+   utmp = ~utmp & 0x0fff;
+   /* Scale value to 0x-0x */
+   strength = utmp << 4 | utmp >> 8;
+
+   c->strength.len = 1;
+   c->strength.stat[0].scale = FE_SCALE_RELATIVE;
+   c->strength.stat[0].uvalue = strength;
+   } else {
+   c->strength.len = 1;
+   c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   }
+
+   /* CNR */
+   if (*status & FE_HAS_VITERBI) {
+   unsigned int cnr;
+
+   ret = cxd2820r_rd_regs(priv, 0x02028, buf, 2);
+   if (ret)
+   goto error;
+
+   utmp = buf[0] << 8 | buf[1] << 0;
+   utmp = utmp & 0x0fff;
+   #define CXD2820R_LOG10_8_24 15151336 /* log10(8) << 24 */
+   if (utmp)
+   cnr = div_u64((u64)(intlog10(utmp)
+ - CXD2820R_LOG10_8_24) * 1,
+ (1 << 24));
+   else
+   cnr = 0;
+
+   c->cnr.len = 1;
+   c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+   c->cnr.stat[0].svalue = cnr;
+   } else {
+   c->cnr.len = 1;
+   c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   }
+
+   /* BER */
+   if (*status & FE_HAS_SYNC) {
+   unsigned int post_bit_error;
+
+   ret = cxd2820r_rd_regs(priv, 0x02039, buf, 4);
+   if (ret)
+   goto error;
+
+   if ((buf[0] >> 4) & 0x01) {
+   post_bit_error = buf[0] << 24 | buf[1] << 16 |
+buf[2] << 8 | buf[3] << 0;
+   post_bit_error &= 0x0fff;
+   } else {
+   post_bit_error = 0;
+   }
+
+   priv->post_bit_error += post_bit_error;
+
+   c->post_bit_error.len = 1;
+   c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+   c->post_bit_error.stat[0].uvalue = priv->post_bit_error;
+   } else {
+   c->post_bit_error.len = 1;
+   c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   }
+
return ret;
 error:
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-- 
http://palosaari.fi/

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/9] cxd2820r: dvbv5 statistics for DVB-C

2016-09-02 Thread Antti Palosaari
Implement dvbv5 statistics for DVB-C.

Signed-off-by: Antti Palosaari 
---
 drivers/media/dvb-frontends/cxd2820r_c.c | 104 ++-
 1 file changed, 102 insertions(+), 2 deletions(-)

diff --git a/drivers/media/dvb-frontends/cxd2820r_c.c 
b/drivers/media/dvb-frontends/cxd2820r_c.c
index 957ec94..7cdcd55 100644
--- a/drivers/media/dvb-frontends/cxd2820r_c.c
+++ b/drivers/media/dvb-frontends/cxd2820r_c.c
@@ -260,11 +260,13 @@ int cxd2820r_read_ucblocks_c(struct dvb_frontend *fe, u32 
*ucblocks)
 int cxd2820r_read_status_c(struct dvb_frontend *fe, enum fe_status *status)
 {
struct cxd2820r_priv *priv = fe->demodulator_priv;
+   struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret;
-   u8 buf[2];
+   unsigned int utmp;
+   u8 buf[3];
*status = 0;
 
-   ret = cxd2820r_rd_regs(priv, 0x10088, buf, sizeof(buf));
+   ret = cxd2820r_rd_regs(priv, 0x10088, buf, 2);
if (ret)
goto error;
 
@@ -281,6 +283,104 @@ int cxd2820r_read_status_c(struct dvb_frontend *fe, enum 
fe_status *status)
dev_dbg(&priv->i2c->dev, "%s: lock=%02x %02x\n", __func__, buf[0],
buf[1]);
 
+   /* Signal strength */
+   if (*status & FE_HAS_SIGNAL) {
+   unsigned int strength;
+
+   ret = cxd2820r_rd_regs(priv, 0x10049, buf, 2);
+   if (ret)
+   goto error;
+
+   utmp = buf[0] << 8 | buf[1] << 0;
+   utmp = 511 - sign_extend32(utmp, 9);
+   /* Scale value to 0x-0x */
+   strength = utmp << 6 | utmp >> 4;
+
+   c->strength.len = 1;
+   c->strength.stat[0].scale = FE_SCALE_RELATIVE;
+   c->strength.stat[0].uvalue = strength;
+   } else {
+   c->strength.len = 1;
+   c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   }
+
+   /* CNR */
+   if (*status & FE_HAS_VITERBI) {
+   unsigned int cnr, const_a, const_b;
+
+   ret = cxd2820r_rd_reg(priv, 0x10019, &buf[0]);
+   if (ret)
+   goto error;
+
+   if (((buf[0] >> 0) & 0x03) % 2) {
+   const_a = 8750;
+   const_b = 650;
+   } else {
+   const_a = 9500;
+   const_b = 760;
+   }
+
+   ret = cxd2820r_rd_reg(priv, 0x1004d, &buf[0]);
+   if (ret)
+   goto error;
+
+   utmp = buf[0] << 0;
+   #define CXD2820R_LOG2_E_24 24204406 /* log2(e) << 24 */
+   if (utmp)
+   cnr = div_u64((u64)(intlog2(const_b) - intlog2(utmp))
+ * const_a, CXD2820R_LOG2_E_24);
+   else
+   cnr = 0;
+
+   c->cnr.len = 1;
+   c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+   c->cnr.stat[0].svalue = cnr;
+   } else {
+   c->cnr.len = 1;
+   c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   }
+
+   /* BER */
+   if (*status & FE_HAS_SYNC) {
+   unsigned int post_bit_error;
+   bool start_ber;
+
+   if (priv->ber_running) {
+   ret = cxd2820r_rd_regs(priv, 0x10076, buf, 3);
+   if (ret)
+   goto error;
+
+   if ((buf[2] >> 7) & 0x01) {
+   post_bit_error = buf[2] << 16 | buf[1] << 8 |
+buf[0] << 0;
+   post_bit_error &= 0x0f;
+   start_ber = true;
+   } else {
+   post_bit_error = 0;
+   start_ber = false;
+   }
+   } else {
+   post_bit_error = 0;
+   start_ber = true;
+   }
+
+   if (start_ber) {
+   ret = cxd2820r_wr_reg(priv, 0x10079, 0x01);
+   if (ret)
+   goto error;
+   priv->ber_running = true;
+   }
+
+   priv->post_bit_error += post_bit_error;
+
+   c->post_bit_error.len = 1;
+   c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+   c->post_bit_error.stat[0].uvalue = priv->post_bit_error;
+   } else {
+   c->post_bit_error.len = 1;
+   c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   }
+
return ret;
 error:
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n&

[PATCH] af9035: fix dual tuner detection with PCTV 79e

2016-09-02 Thread Antti Palosaari
From: Stefan Pöschel 

The value 5 of the EEPROM_TS_MODE register (meaning dual tuner presence) is
only valid for AF9035 devices. For IT9135 devices it is invalid and led to a
false positive dual tuner mode detection with PCTV 79e.
Therefore on non-AF9035 devices and with value 5 the driver now defaults to
single tuner mode and outputs a regarding info message to log.

This fixes Bugzilla bug #118561.

(backport of 4.7)

Fixes: b8278f8b961a ("[media] af9035: add support for 2nd tuner of MSI DigiVox 
Diversity")
Cc:  # 4.6
Reported-by: Marc Duponcheel 
Signed-off-by: Stefan Pöschel 
Signed-off-by: Antti Palosaari 
---
 drivers/media/usb/dvb-usb-v2/af9035.c | 53 +++
 drivers/media/usb/dvb-usb-v2/af9035.h |  2 +-
 2 files changed, 36 insertions(+), 19 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c 
b/drivers/media/usb/dvb-usb-v2/af9035.c
index 2638e32..14dbfeb 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.c
+++ b/drivers/media/usb/dvb-usb-v2/af9035.c
@@ -475,7 +475,8 @@ static struct i2c_algorithm af9035_i2c_algo = {
 static int af9035_identify_state(struct dvb_usb_device *d, const char **name)
 {
struct state *state = d_to_priv(d);
-   int ret;
+   int ret, ts_mode_invalid;
+   u8 tmp;
u8 wbuf[1] = { 1 };
u8 rbuf[4];
struct usb_req req = { CMD_FW_QUERYINFO, 0, sizeof(wbuf), wbuf,
@@ -511,6 +512,38 @@ static int af9035_identify_state(struct dvb_usb_device *d, 
const char **name)
state->eeprom_addr = EEPROM_BASE_AF9035;
}
 
+
+   /* check for dual tuner mode */
+   ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_TS_MODE, &tmp);
+   if (ret < 0)
+   goto err;
+
+   ts_mode_invalid = 0;
+   switch (tmp) {
+   case 0:
+   break;
+   case 1:
+   case 3:
+   state->dual_mode = true;
+   break;
+   case 5:
+   if (state->chip_type != 0x9135 && state->chip_type != 0x9306)
+   state->dual_mode = true;/* AF9035 */
+   else
+   ts_mode_invalid = 1;
+   break;
+   default:
+   ts_mode_invalid = 1;
+   }
+
+   dev_dbg(&d->udev->dev, "%s: ts mode=%d dual mode=%d\n",
+   __func__, tmp, state->dual_mode);
+
+   if (ts_mode_invalid)
+   dev_info(&d->udev->dev, "%s: ts mode=%d not supported, 
defaulting to single tuner mode!",
+   __func__, tmp);
+
+
ret = af9035_ctrl_msg(d, &req);
if (ret < 0)
goto err;
@@ -680,11 +713,7 @@ static int af9035_download_firmware(struct dvb_usb_device 
*d,
 * which is done by master demod.
 * Master feeds also clock and controls power via GPIO.
 */
-   ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_TS_MODE, &tmp);
-   if (ret < 0)
-   goto err;
-
-   if (tmp == 1 || tmp == 3 || tmp == 5) {
+   if (state->dual_mode) {
/* configure gpioh1, reset & power slave demod */
ret = af9035_wr_reg_mask(d, 0x00d8b0, 0x01, 0x01);
if (ret < 0)
@@ -817,18 +846,6 @@ static int af9035_read_config(struct dvb_usb_device *d)
}
 
 
-
-   /* check if there is dual tuners */
-   ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_TS_MODE, &tmp);
-   if (ret < 0)
-   goto err;
-
-   if (tmp == 1 || tmp == 3 || tmp == 5)
-   state->dual_mode = true;
-
-   dev_dbg(&d->udev->dev, "%s: ts mode=%d dual mode=%d\n", __func__,
-   tmp, state->dual_mode);
-
if (state->dual_mode) {
/* read 2nd demodulator I2C address */
ret = af9035_rd_reg(d,
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.h 
b/drivers/media/usb/dvb-usb-v2/af9035.h
index df22001..d50ff15 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.h
+++ b/drivers/media/usb/dvb-usb-v2/af9035.h
@@ -112,7 +112,7 @@ static const u32 clock_lut_it9135[] = {
  * 0  TS
  * 1  DCA + PIP
  * 3  PIP
- * 5  DCA + PIP
+ * 5  DCA + PIP (AF9035 only)
  * n  DCA
  *
  * Values 0, 3 and 5 are seen to this day. 0 for single TS and 3/5 for dual TS.
-- 
http://palosaari.fi/

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[GIT PULL STABLE 4.6] af9035 regression

2016-09-02 Thread Antti Palosaari

The following changes since commit 2dcd0af568b0cf583645c8a317dd12e344b1c72a:

  Linux 4.6 (2016-05-15 15:43:13 -0700)

are available in the git repository at:

  git://linuxtv.org/anttip/media_tree.git af9035_fix

for you to fetch changes up to 7bb87ff5255defe87916f32cd1fcef163a489339:

  af9035: fix dual tuner detection with PCTV 79e (2016-09-03 02:23:44 
+0300)



Stefan Pöschel (1):
  af9035: fix dual tuner detection with PCTV 79e

 drivers/media/usb/dvb-usb-v2/af9035.c | 53 
+++--

 drivers/media/usb/dvb-usb-v2/af9035.h |  2 +-
 2 files changed, 36 insertions(+), 19 deletions(-)

--
http://palosaari.fi/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [GIT PULL STABLE 4.6] af9035 regression

2016-09-09 Thread Antti Palosaari

On 09/09/2016 05:49 PM, Mauro Carvalho Chehab wrote:

Hi Antti,

Em Sat, 3 Sep 2016 02:40:52 +0300
Antti Palosaari  escreveu:


The following changes since commit 2dcd0af568b0cf583645c8a317dd12e344b1c72a:

   Linux 4.6 (2016-05-15 15:43:13 -0700)


Is this patchset really meant to Kernel 4.6? if so, you should send
the path to sta...@vger.kernel.org, c/c the mailing list.

It helps to point the original patch that fixed the issue upstream,
as they won't apply the fix if it was not fixed upstream yet.


I think you already applied upstream patch, that one is just back-ported 
to 4.6.


It is that patch:
https://patchwork.linuxtv.org/patch/36795/

and it contains all the needed tags including Cc stable. Could you send 
it to stable?


Antti



Regards,
Mauro



are available in the git repository at:

   git://linuxtv.org/anttip/media_tree.git af9035_fix

for you to fetch changes up to 7bb87ff5255defe87916f32cd1fcef163a489339:

   af9035: fix dual tuner detection with PCTV 79e (2016-09-03 02:23:44
+0300)


Stefan Pöschel (1):
   af9035: fix dual tuner detection with PCTV 79e

  drivers/media/usb/dvb-usb-v2/af9035.c | 53
+++--
  drivers/media/usb/dvb-usb-v2/af9035.h |  2 +-
  2 files changed, 36 insertions(+), 19 deletions(-)





Thanks,
Mauro



--
http://palosaari.fi/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[GIT PULL] cxd2820r improvements

2016-09-10 Thread Antti Palosaari

The following changes since commit fb6609280db902bd5d34445fba1c926e95e63914:

  [media] dvb_frontend: Use memdup_user() rather than duplicating its 
implementation (2016-08-24 17:20:45 -0300)


are available in the git repository at:

  git://linuxtv.org/anttip/media_tree.git cxd2820r

for you to fetch changes up to 18905adf08ffc82417663539d1a703014505582f:

  cxd2820r: convert to regmap api (2016-09-03 01:30:22 +0300)


Antti Palosaari (9):
  cxd2820r: improve IF frequency setting
  cxd2820r: dvbv5 statistics for DVB-T
  cxd2820r: dvbv5 statistics for DVB-T2
  cxd2820r: dvbv5 statistics for DVB-C
  cxd2820r: wrap legacy DVBv3 statistics via DVBv5 statistics
  cxd2820r: add I2C driver bindings
  cxd2820r: correct logging
  cxd2820r: improve lock detection
  cxd2820r: convert to regmap api

 drivers/media/dvb-frontends/Kconfig |   1 +
 drivers/media/dvb-frontends/cxd2820r.h  |  26 ++
 drivers/media/dvb-frontends/cxd2820r_c.c| 302 
+++---
 drivers/media/dvb-frontends/cxd2820r_core.c | 597 
+-

 drivers/media/dvb-frontends/cxd2820r_priv.h |  42 --
 drivers/media/dvb-frontends/cxd2820r_t.c| 300 
++---
 drivers/media/dvb-frontends/cxd2820r_t2.c   | 278 
+++-

 7 files changed, 770 insertions(+), 776 deletions(-)

--
http://palosaari.fi/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] [media] staging/media/cec: fix coding style error

2016-09-11 Thread Antti Palosaari

On 09/11/2016 07:07 PM, Richard wrote:

Greetings Linux Kernel Developers,

This is Task 10 of the Eudyptula Challenge, i fix few line over 80
characters, hope you will accept this pacth.

/Richard

For the eudyptula challenge (http://eudyptula-challenge.org/).
Simple style fix for few line over 80 characters



-   if (!is_broadcast && !is_reply && !adap->follower_cnt &&
+   if (is_directed && !is_reply && !adap->follower_cnt &&


!!
Antti

--
http://palosaari.fi/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 00/26] Don't use stack for DMA transers on dvb-usb drivers

2016-10-10 Thread Antti Palosaari

Hello
If you use usb buffers from the state you will need add lock in order to 
protect concurrent access to buffer. There may have multiple concurrent 
operations from rc-polling/demux/frontend. Lets say you are reading ber 
and it sets data to buffer (state), then context switch to remote 
controller polling => buffer in state is overwritten, then context is 
changed back to ber reading and now there is bad data.


regards
Antti


On 10/07/2016 08:24 PM, Mauro Carvalho Chehab wrote:

Sending URB control messages from stack was never supported. Yet, on x86,
the stack was usually at a memory region that allows DMA transfer.

So, several drivers got it wrong. On Kernel 4.9, if VMAP_STACK=y, none of
those drivers will work, as the stack won't be on a DMA-able area anymore.

So, fix the dvb-usb drivers that requre it.

Please notice that, while all those patches compile, I don't have devices
using those drivers to test. So, I really appreciate if people with devices
using those drivers could test and report if they don't break anything.

Thanks!
Mauro

Mauro Carvalho Chehab (26):
  af9005: don't do DMA on stack
  cinergyT2-core: don't do DMA on stack
  cinergyT2-core:: handle error code on RC query
  cinergyT2-fe: cache stats at cinergyt2_fe_read_status()
  cinergyT2-fe: don't do DMA on stack
  cxusb: don't do DMA on stack
  dib0700: be sure that dib0700_ctrl_rd() users can do DMA
  dib0700_core: don't use stack on I2C reads
  dibusb: don't do DMA on stack
  dibusb: handle error code on RC query
  digitv: don't do DMA on stack
  dtt200u-fe: don't do DMA on stack
  dtt200u-fe: handle errors on USB control messages
  dtt200u: don't do DMA on stack
  dtt200u: handle USB control message errors
  dtv5100: : don't do DMA on stack
  gp8psk: don't do DMA on stack
  gp8psk: don't go past the buffer size
  nova-t-usb2: don't do DMA on stack
  pctv452e: don't do DMA on stack
  pctv452e: don't call BUG_ON() on non-fatal error
  technisat-usb2: use DMA buffers for I2C transfers
  dvb-usb: warn if return value for USB read/write routines is not
checked
  nova-t-usb2: handle error code on RC query
  dw2102: return error if su3000_power_ctrl() fails
  digitv: handle error code on RC query

 drivers/media/usb/dvb-usb/af9005.c  | 211 +++-
 drivers/media/usb/dvb-usb/cinergyT2-core.c  |  52 ---
 drivers/media/usb/dvb-usb/cinergyT2-fe.c|  91 
 drivers/media/usb/dvb-usb/cxusb.c   |  20 +--
 drivers/media/usb/dvb-usb/cxusb.h   |   5 +
 drivers/media/usb/dvb-usb/dib0700_core.c|  31 +++-
 drivers/media/usb/dvb-usb/dib0700_devices.c |  25 ++--
 drivers/media/usb/dvb-usb/dibusb-common.c   | 112 +++
 drivers/media/usb/dvb-usb/dibusb.h  |   5 +
 drivers/media/usb/dvb-usb/digitv.c  |  26 ++--
 drivers/media/usb/dvb-usb/digitv.h  |   3 +
 drivers/media/usb/dvb-usb/dtt200u-fe.c  |  90 
 drivers/media/usb/dvb-usb/dtt200u.c |  80 +++
 drivers/media/usb/dvb-usb/dtv5100.c |  10 +-
 drivers/media/usb/dvb-usb/dvb-usb.h |   6 +-
 drivers/media/usb/dvb-usb/dw2102.c  |   2 +-
 drivers/media/usb/dvb-usb/gp8psk.c  |  25 +++-
 drivers/media/usb/dvb-usb/nova-t-usb2.c |  25 +++-
 drivers/media/usb/dvb-usb/pctv452e.c| 118 
 drivers/media/usb/dvb-usb/technisat-usb2.c  |  16 ++-
 20 files changed, 577 insertions(+), 376 deletions(-)



--
http://palosaari.fi/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] [media] tda18212: fix use-after-free in tda18212_remove()

2017-12-15 Thread Antti Palosaari
ridge]
   [  154.028695]  ddb_remove+0x3c/0xb0 [ddbridge]
   [  154.028697]  pci_device_remove+0x93/0x1d0
   [  154.028700]  device_release_driver_internal+0x267/0x510
   [  154.028702]  driver_detach+0xb9/0x1b0
   [  154.028705]  bus_remove_driver+0xd0/0x1f0
   [  154.028707]  pci_unregister_driver+0x25/0x210
   [  154.028711]  module_exit_ddbridge+0xc/0x45 [ddbridge]
   [  154.028714]  SyS_delete_module+0x314/0x440
   [  154.028716]  do_syscall_64+0x179/0x4c0
   [  154.028718]  return_from_SYSCALL_64+0x0/0x65

   [  154.028729] The buggy address belongs to the object at 880108b55340
   which belongs to the cache kmalloc-2048 of size 2048
   [  154.028755] The buggy address is located 408 bytes inside of
   2048-byte region [880108b55340, 880108b55b40)
   [  154.028778] The buggy address belongs to the page:
   [  154.028792] page:ea00039e7a60 count:1 mapcount:0 
mapping:880108b54240 index:0x0 compound_mapcount: 0
   [  154.028814] flags: 0x80008100(slab|head)
   [  154.028830] raw: 80008100 880108b54240  
00010003
   [  154.028848] raw: ea00039e7310 ea00039e7bd0 88010b000800
   [  154.028862] page dumped because: kasan: bad access detected

   [  154.028883] Memory state around the buggy address:
   [  154.028896]  880108b55380: fb fb fb fb fb fb fb fb fb fb fb fb fb fb 
fb fb
   [  154.028913]  880108b55400: fb fb fb fb fb fb fb fb fb fb fb fb fb fb 
fb fb
   [  154.028929] >880108b55480: fb fb fb fb fb fb fb fb fb fb fb fb fb fb 
fb fb
   [  154.028945] ^
   [  154.028960]  880108b55500: fb fb fb fb fb fb fb fb fb fb fb fb fb fb 
fb fb
   [  154.028976]  880108b55580: fb fb fb fb fb fb fb fb fb fb fb fb fb fb 
fb fb
   [  154.028991] 
==
   [  154.029006] Disabling lock debugging due to kernel taint

Fix this by removing the memcpy and the NULL assign.

Cc: Antti Palosaari 
Signed-off-by: Daniel Scheller 
---
  drivers/media/tuners/tda18212.c | 5 -
  1 file changed, 5 deletions(-)

diff --git a/drivers/media/tuners/tda18212.c b/drivers/media/tuners/tda18212.c
index 7b8068354fea..ebccf8a8729d 100644
--- a/drivers/media/tuners/tda18212.c
+++ b/drivers/media/tuners/tda18212.c
@@ -258,12 +258,7 @@ static int tda18212_probe(struct i2c_client *client,
  static int tda18212_remove(struct i2c_client *client)
  {
struct tda18212_dev *dev = i2c_get_clientdata(client);
-   struct dvb_frontend *fe = dev->cfg.fe;
  
-	dev_dbg(&client->dev, "\n");

-
-   memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
-   fe->tuner_priv = NULL;
kfree(dev);
  
  	return 0;




--
http://palosaari.fi/


Re: [PATCH] [media] tda18212: fix use-after-free in tda18212_remove()

2017-12-15 Thread Antti Palosaari



On 12/15/2017 08:00 PM, Daniel Scheller wrote:

Hi,

On Fri, 15 Dec 2017 19:30:18 +0200
Antti Palosaari  wrote:

Thanks for your reply.


Hello
I think shared frontend structure, which is owned by demod driver,
should be there and valid on time tuner driver is removed. And thus
should not happen. Did you make driver unload on different order eg.
not just reverse order than driver load?

IMHO these should go always

on load:
1) load demod driver (which makes shared frontend structure where
also some tuner driver data lives)
2) load tuner driver
3) register frontend

on unload
1) unregister frontend
2) remove tuner driver
3) remove demod driver (frees shared data)


In ddbridge, we do (like in usb/em28xx and platform/sti/c8sectpfe, both
also use some demod+tda18212 combo):

dvb_unregister_frontend();
dvb_frontend_detach();
module_put(tda18212client->...owner);
i2c_unregister_device(tda18212client);

fe_detach() clears out the frontend references and frees/invalidates
the allocated resources. tuner_ops obviously isn't there then anymore.


yeah, but that's even ideally wrong. frontend design currently relies to 
shared data which is owned by demod driver and thus it should be last 
thing to be removed. Sure change like you did prevents issue, but 
logically it is still wrong and may not work on some other case.




The two mentioned drivers will very likely yield the same (or
similar) KASAN report. em28xx was even changed lately to do the teardown
the way ddbridge does in 910b0797fa9e8 ([1], cc'ing Matthias
here).

With that commit in mind I'm a bit unsure on what is correct or not.
OTOH, as dvb_frontend_detach() cleans up everything, IMHO there's no
need for the tuner driver to try to clean up further.

Please advise.

[1] https://git.linuxtv.org/media_tree.git/commit/?id=910b0797fa9e8.


em28xx does it currently just correct.
1) unregister frontend
2) remove I2C SEC
3) remove I2C tuner
4) remove I2C demod (frees shared frontend data)

regards
Antti

--
http://palosaari.fi/


Re: [PATCH] [media] tda18212: fix use-after-free in tda18212_remove()

2017-12-15 Thread Antti Palosaari



On 12/15/2017 08:40 PM, Daniel Scheller wrote:

On Fri, 15 Dec 2017 20:12:18 +0200
Antti Palosaari  wrote:


On 12/15/2017 08:00 PM, Daniel Scheller wrote:

Hi,

On Fri, 15 Dec 2017 19:30:18 +0200
Antti Palosaari  wrote:

Thanks for your reply.
   

Hello
I think shared frontend structure, which is owned by demod driver,
should be there and valid on time tuner driver is removed. And thus
should not happen. Did you make driver unload on different order
eg. not just reverse order than driver load?

IMHO these should go always

on load:
1) load demod driver (which makes shared frontend structure where
also some tuner driver data lives)
2) load tuner driver
3) register frontend

on unload
1) unregister frontend
2) remove tuner driver
3) remove demod driver (frees shared data)


In ddbridge, we do (like in usb/em28xx and platform/sti/c8sectpfe,
both also use some demod+tda18212 combo):

dvb_unregister_frontend();
dvb_frontend_detach();
module_put(tda18212client->...owner);
i2c_unregister_device(tda18212client);

fe_detach() clears out the frontend references and frees/invalidates
the allocated resources. tuner_ops obviously isn't there then
anymore.


yeah, but that's even ideally wrong. frontend design currently relies
to shared data which is owned by demod driver and thus it should be
last thing to be removed. Sure change like you did prevents issue,
but logically it is still wrong and may not work on some other case.



The two mentioned drivers will very likely yield the same (or
similar) KASAN report. em28xx was even changed lately to do the
teardown the way ddbridge does in 910b0797fa9e8 ([1], cc'ing
Matthias here).

With that commit in mind I'm a bit unsure on what is correct or not.
OTOH, as dvb_frontend_detach() cleans up everything, IMHO there's no
need for the tuner driver to try to clean up further.

Please advise.

[1]
https://git.linuxtv.org/media_tree.git/commit/?id=910b0797fa9e8.


em28xx does it currently just correct.
1) unregister frontend


Note that this is a call to em28xx_unregister_dvb(), which in turn does
dvb_unregister_frontend() and then dvb_frontend_detach() (at this
stage, fe resources are gone).


2) remove I2C SEC
3) remove I2C tuner
4) remove I2C demod (frees shared frontend data)


Yes, but ie. EM2874_BOARD_KWORLD_UB435Q_V3 is a combination of a
"legacy" demod frontend - lgdt3305 actually - plus the tda18212
i2cclient (just like in ddb with stv0367+tda18212 or
cxd2841er+tda18212), I'm sure this will yield the same report.

Maybe another approach: Implement the tuner_ops.release callback, and
then move the memset+NULL assignment right there (instead of just
removing it), but this likely will cause issues when the i2c client is
removed before detach if we don't keep track of this ie somewhere in
tda18212_dev (new state var - if _remove is called, check if the tuner
was released, and if not, call release (memset/set NULL), then
free). Still with the two other drivers in mind though. If they're
wrong aswell, I'll rather fix up ddbridge of course.


Whole memset thing could be removed from tda18212, there is something 
likely wrong if those are needed. But it is another issue.


Your main issue is somehow to get order of demod/tuner destroy correct. 
I don't even like idea whole shared frontend data is owned by the demod 
driver instance, but currently it is there and due to that this should 
be released lastly. General design goal is also do things like register 
things in order and unregister just reverse-order.


regards
Antti

--
http://palosaari.fi/


Re: [PATCH 3/7] si2157: Add hybrid tuner support

2018-01-15 Thread Antti Palosaari
stance) {
+   case 0:
+   goto fail;
+   case 1:
+   /* new tuner instance */
+   dev_dbg(&client->dev, "%s(): new instance for tuner @0x%02x\n",
+   __func__, addr);
+   dev->addr = addr;
+   i2c_set_clientdata(client, dev);
+
+   dev->fe = fe;
+   dev->chiptype = SI2157_CHIPTYPE_SI2157;
+   dev->if_frequency = 0;
+   dev->if_port   = cfg->if_port;
+   dev->inversion = cfg->inversion;
+
+   mutex_init(&dev->i2c_mutex);
+   INIT_DELAYED_WORK(&dev->stat_work, si2157_stat_work);
+
+   break;
+   default:
+   /* existing tuner instance */
+   dev_dbg(&client->dev,
+   "%s(): using existing instance for tuner 
@0x%02x\n",
+__func__, addr);
+   break;
+   }
+
+   /* check if the tuner is there */
+   cmd.wlen = 0;
+   cmd.rlen = 1;
+   ret = si2157_cmd_execute(client, &cmd);
+   /* verify no i2c error and CTS is set */
+   if (ret) {
+   dev_warn(&client->dev, "no HW found ret=%d\n", ret);
+   goto fail_instance;
+   }
+
+   memcpy(&fe->ops.tuner_ops, &si2157_ops, sizeof(struct dvb_tuner_ops));
+
+#ifdef CONFIG_MEDIA_CONTROLLER
+   if (instance == 1 && cfg->mdev) {
+   dev->mdev = cfg->mdev;
+
+   dev->ent.name = KBUILD_MODNAME;
+   dev->ent.function = MEDIA_ENT_F_TUNER;
+
+   dev->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK;
+   dev->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE;
+   dev->pad[TUNER_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE;
+
+   ret = media_entity_pads_init(&dev->ent, TUNER_NUM_PADS,
+&dev->pad[0]);
+
+   if (ret)
+   goto fail_instance;
+
+   ret = media_device_register_entity(cfg->mdev, &dev->ent);
+   if (ret) {
+   dev_warn(&client->dev,
+   "media_device_regiser_entity returns %d\n", 
ret);
+   media_entity_cleanup(&dev->ent);
+   goto fail_instance;
+   }
+   }
+#endif
+   mutex_unlock(&si2157_list_mutex);
+
+   if (instance != 1)
+   dev_info(&client->dev, "Silicon Labs %s successfully 
attached\n",
+   dev->chiptype == SI2157_CHIPTYPE_SI2141 ?  "Si2141" :
+   dev->chiptype == SI2157_CHIPTYPE_SI2146 ?
+   "Si2146" : "Si2147/2148/2157/2158");
+
+   return fe;
+fail_instance:
+   mutex_unlock(&si2157_list_mutex);
+
+   si2157_release(fe);
+fail:
+   dev_warn(&client->dev, "Attach failed\n");
+   return NULL;
+}
+EXPORT_SYMBOL(si2157_attach);
+
+MODULE_DESCRIPTION("Silicon Labs Si2141/2146/2147/2148/2157/2158 silicon tuner 
driver");
  MODULE_AUTHOR("Antti Palosaari ");
  MODULE_LICENSE("GPL");
  MODULE_FIRMWARE(SI2158_A20_FIRMWARE);
diff --git a/drivers/media/tuners/si2157.h b/drivers/media/tuners/si2157.h
index de597fa..26b94ca 100644
--- a/drivers/media/tuners/si2157.h
+++ b/drivers/media/tuners/si2157.h
@@ -46,4 +46,18 @@ struct si2157_config {
u8 if_port;
  };
  
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_SI2157)

+extern struct dvb_frontend *si2157_attach(struct dvb_frontend *fe, u8 addr,
+   struct i2c_adapter *i2c,
+   struct si2157_config *cfg);
+#else
+static inline struct dvb_frontend *si2157_attach(struct dvb_frontend *fe,
+  u8 addr,
+  struct i2c_adapter *i2c,
+  struct si2157_config *cfg)
+{
+   pr_err("%s: driver disabled by Kconfig\n", __func__);
+   return NULL;
+}
+#endif
  #endif
diff --git a/drivers/media/tuners/si2157_priv.h 
b/drivers/media/tuners/si2157_priv.h
index e6436f7..2801aaa 100644
--- a/drivers/media/tuners/si2157_priv.h
+++ b/drivers/media/tuners/si2157_priv.h
@@ -19,15 +19,20 @@
  
  #include 

  #include 
+#include "tuner-i2c.h"
  #include "si2157.h"
  
  /* state struct */

  struct si2157_dev {
+   struct list_head hybrid_tuner_instance_list;
+   struct tuner_i2c_props  i2c_props;
+
struct mutex i2c_mutex;
struct dvb_frontend *fe;
bool active;
bool inversion;
u8 chiptype;
+   u8 addr;
u8 if_port;
u32 if_frequency;
struct delayed_work stat_work;



--
http://palosaari.fi/


Re: [PATCH 4/7] si2168: Add ts bus coontrol, turn off bus on sleep

2018-01-15 Thread Antti Palosaari

Hello
And what is rationale here, is there some use case demod must be active 
and ts set to tristate (disabled)? Just put demod sleep when you don't 
use it.


regards
Antti

On 01/12/2018 06:19 PM, Brad Love wrote:

Includes a function to set TS MODE property os si2168. The function
either disables the TS output bus, or sets mode to config option.

When going to sleep the TS bus is turned off, this makes the driver
compatible with multiple frontend usage.

Signed-off-by: Brad Love 
---
  drivers/media/dvb-frontends/si2168.c | 38 
  drivers/media/dvb-frontends/si2168.h |  1 +
  2 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/drivers/media/dvb-frontends/si2168.c 
b/drivers/media/dvb-frontends/si2168.c
index 539399d..429c03a 100644
--- a/drivers/media/dvb-frontends/si2168.c
+++ b/drivers/media/dvb-frontends/si2168.c
@@ -409,6 +409,30 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
return ret;
  }
  
+static int si2168_ts_bus_ctrl(struct dvb_frontend *fe, int acquire)

+{
+   struct i2c_client *client = fe->demodulator_priv;
+   struct si2168_dev *dev = i2c_get_clientdata(client);
+   struct si2168_cmd cmd;
+   int ret = 0;
+
+   dev_dbg(&client->dev, "%s acquire: %d\n", __func__, acquire);
+
+   /* set TS_MODE property */
+   memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6);
+   if (acquire)
+   cmd.args[4] |= dev->ts_mode;
+   else
+   cmd.args[4] |= SI2168_TS_TRISTATE;
+   if (dev->ts_clock_gapped)
+   cmd.args[4] |= 0x40;
+   cmd.wlen = 6;
+   cmd.rlen = 4;
+   ret = si2168_cmd_execute(client, &cmd);
+
+   return ret;
+}
+
  static int si2168_init(struct dvb_frontend *fe)
  {
struct i2c_client *client = fe->demodulator_priv;
@@ -540,14 +564,7 @@ static int si2168_init(struct dvb_frontend *fe)
 dev->version >> 24 & 0xff, dev->version >> 16 & 0xff,
 dev->version >> 8 & 0xff, dev->version >> 0 & 0xff);
  
-	/* set ts mode */

-   memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6);
-   cmd.args[4] |= dev->ts_mode;
-   if (dev->ts_clock_gapped)
-   cmd.args[4] |= 0x40;
-   cmd.wlen = 6;
-   cmd.rlen = 4;
-   ret = si2168_cmd_execute(client, &cmd);
+   ret = si2168_ts_bus_ctrl(fe, 1);
if (ret)
goto err;
  
@@ -584,6 +601,9 @@ static int si2168_sleep(struct dvb_frontend *fe)
  
  	dev->active = false;
  
+	/* tri-state data bus */

+   si2168_ts_bus_ctrl(fe, 0);
+
/* Firmware B 4.0-11 or later loses warm state during sleep */
if (dev->version > ('B' << 24 | 4 << 16 | 0 << 8 | 11 << 0))
dev->warm = false;
@@ -681,6 +701,8 @@ static const struct dvb_frontend_ops si2168_ops = {
.init = si2168_init,
.sleep = si2168_sleep,
  
+	.ts_bus_ctrl  = si2168_ts_bus_ctrl,

+
.set_frontend = si2168_set_frontend,
  
  	.read_status = si2168_read_status,

diff --git a/drivers/media/dvb-frontends/si2168.h 
b/drivers/media/dvb-frontends/si2168.h
index 3225d0c..f48f0fb 100644
--- a/drivers/media/dvb-frontends/si2168.h
+++ b/drivers/media/dvb-frontends/si2168.h
@@ -38,6 +38,7 @@ struct si2168_config {
/* TS mode */
  #define SI2168_TS_PARALLEL0x06
  #define SI2168_TS_SERIAL  0x03
+#define SI2168_TS_TRISTATE 0x00
u8 ts_mode;
  
  	/* TS clock inverted */




--
http://palosaari.fi/


Re: [PATCH 6/7] si2168: Announce frontend creation failure

2018-01-15 Thread Antti Palosaari
hmmm, IIRC driver core even prints some error when driver probe fails? 
After that you could enable module debug logging to see more 
information. So I don't see point for that change.


regards
Antti

On 01/12/2018 06:19 PM, Brad Love wrote:

The driver outputs on success, but is silent on failure. Give
one message that probe failed.

Signed-off-by: Brad Love 
---
  drivers/media/dvb-frontends/si2168.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/dvb-frontends/si2168.c 
b/drivers/media/dvb-frontends/si2168.c
index 429c03a..c1a638c 100644
--- a/drivers/media/dvb-frontends/si2168.c
+++ b/drivers/media/dvb-frontends/si2168.c
@@ -810,7 +810,7 @@ static int si2168_probe(struct i2c_client *client,
  err_kfree:
kfree(dev);
  err:
-   dev_dbg(&client->dev, "failed=%d\n", ret);
+   dev_warn(&client->dev, "probe failed = %d\n", ret);
return ret;
  }
  



--
http://palosaari.fi/


Re: [PATCH 4/7] si2168: Add ts bus coontrol, turn off bus on sleep

2018-01-16 Thread Antti Palosaari

On 01/16/2018 07:31 PM, Brad Love wrote:


On 2018-01-15 23:07, Antti Palosaari wrote:

Hello
And what is rationale here, is there some use case demod must be
active and ts set to tristate (disabled)? Just put demod sleep when
you don't use it.

regards
Antti


Hello Antti,

Perhaps the .ts_bus_ctrl callback does not need to be included in ops,
but the function is necessary. The demod is already put to sleep when
not in use, but it leaves the ts bus open. The ts bus has no reason to
be open when the demod is put to sleep. Leaving the ts bus open during
sleep affects the other connected demod and nothing is received by it.
The lgdt3306a driver already tri states its ts bus when put to sleep,
the si2168 should as well.


Sounds possible, but unlikely as chip is firmware driven. When you put 
chip to sleep you usually want set ts pins to tristate (also other 
unused pins) in order to save energy. I haven't never tested it anyway 
though, so it could be possible it leaves those pins to some other state 
like random output at given time.


And if you cannot get stream from lgdt3306a, which is connected to same 
bus, it really sounds like ts bus pins are left some state (cannot work 
if same pin is driven high to other demod whilst other tries to drive it 
low.


Setting ts pins to tri-state during sleep should resolve your issue.


regards
Antti
--
http://palosaari.fi/


Re: [PATCH 4/7] si2168: Add ts bus coontrol, turn off bus on sleep

2018-01-16 Thread Antti Palosaari

On 01/16/2018 10:14 PM, Brad Love wrote:


On 2018-01-16 13:32, Antti Palosaari wrote:

On 01/16/2018 07:31 PM, Brad Love wrote:


On 2018-01-15 23:07, Antti Palosaari wrote:

Hello
And what is rationale here, is there some use case demod must be
active and ts set to tristate (disabled)? Just put demod sleep when
you don't use it.

regards
Antti


Hello Antti,

Perhaps the .ts_bus_ctrl callback does not need to be included in ops,
but the function is necessary. The demod is already put to sleep when
not in use, but it leaves the ts bus open. The ts bus has no reason to
be open when the demod is put to sleep. Leaving the ts bus open during
sleep affects the other connected demod and nothing is received by it.
The lgdt3306a driver already tri states its ts bus when put to sleep,
the si2168 should as well.


Sounds possible, but unlikely as chip is firmware driven. When you put
chip to sleep you usually want set ts pins to tristate (also other
unused pins) in order to save energy. I haven't never tested it anyway
though, so it could be possible it leaves those pins to some other
state like random output at given time.

And if you cannot get stream from lgdt3306a, which is connected to
same bus, it really sounds like ts bus pins are left some state
(cannot work if same pin is driven high to other demod whilst other
tries to drive it low.

Setting ts pins to tri-state during sleep should resolve your issue.


Hello Antti,

This patch fixes the issue I'm describing, hence why I submitted it. The
ts bus must be tristated before putting the chip to sleep for the other
demod to get a stream.



I can test tri-state using power meter on some day, but it may be so 
small current that it cannot be seen usb power meter I use (YZXstudio, 
very nice small power meter).


regards
Antti

--
http://palosaari.fi/


Re: [PATCH v2 1/2] si2168: Add spectrum inversion property

2018-01-17 Thread Antti Palosaari



On 01/17/2018 11:52 PM, Brad Love wrote:

Some tuners produce inverted spectrum, but the si2168 is not
currently set up to accept it. This adds an optional parameter
to set the frontend up to receive inverted spectrum.

Parameter is optional and only boards who enable inversion
will utilize this.

Signed-off-by: Brad Love 
---
Changes since v1:
- Embarassing build failure due to missing declaration.

  drivers/media/dvb-frontends/si2168.c | 3 +++
  drivers/media/dvb-frontends/si2168.h | 3 +++
  2 files changed, 6 insertions(+)

diff --git a/drivers/media/dvb-frontends/si2168.c 
b/drivers/media/dvb-frontends/si2168.c
index c041e79..048b815 100644
--- a/drivers/media/dvb-frontends/si2168.c
+++ b/drivers/media/dvb-frontends/si2168.c
@@ -213,6 +213,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
struct i2c_client *client = fe->demodulator_priv;
struct si2168_dev *dev = i2c_get_clientdata(client);
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+   struct si2168_config *config = client->dev.platform_data;


hmmm, are you sure platform data pointer points is const? I usually tend 
to store all config information to device state. Then there is no need 
to care if pointer is valid or not anymore.


And inversion happens when those wires are cross-connected


int ret;
struct si2168_cmd cmd;
u8 bandwidth, delivery_system;
@@ -339,6 +340,8 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
  
  	memcpy(cmd.args, "\x14\x00\x0a\x10\x00\x00", 6);

cmd.args[4] = delivery_system | bandwidth;
+   if (config->spectral_inversion)
+   cmd.args[5] |= 1;
cmd.wlen = 6;
cmd.rlen = 4;
ret = si2168_cmd_execute(client, &cmd);
diff --git a/drivers/media/dvb-frontends/si2168.h 
b/drivers/media/dvb-frontends/si2168.h
index f48f0fb..d519edd 100644
--- a/drivers/media/dvb-frontends/si2168.h
+++ b/drivers/media/dvb-frontends/si2168.h
@@ -46,6 +46,9 @@ struct si2168_config {
  
  	/* TS clock gapped */

bool ts_clock_gapped;
+
+   /* Inverted spectrum */
+   bool spectral_inversion;
  };
  
  #endif




--
http://palosaari.fi/


Re: [PATCH v2 1/2] si2168: Add spectrum inversion property

2018-01-17 Thread Antti Palosaari

On 01/18/2018 03:58 AM, Brad Love wrote:


On 2018-01-17 16:08, Brad Love wrote:

On 2018-01-17 16:02, Antti Palosaari wrote:


On 01/17/2018 11:52 PM, Brad Love wrote:

Some tuners produce inverted spectrum, but the si2168 is not
currently set up to accept it. This adds an optional parameter
to set the frontend up to receive inverted spectrum.

Parameter is optional and only boards who enable inversion
will utilize this.

Signed-off-by: Brad Love 
---
Changes since v1:
- Embarassing build failure due to missing declaration.

   drivers/media/dvb-frontends/si2168.c | 3 +++
   drivers/media/dvb-frontends/si2168.h | 3 +++
   2 files changed, 6 insertions(+)

diff --git a/drivers/media/dvb-frontends/si2168.c
b/drivers/media/dvb-frontends/si2168.c
index c041e79..048b815 100644
--- a/drivers/media/dvb-frontends/si2168.c
+++ b/drivers/media/dvb-frontends/si2168.c
@@ -213,6 +213,7 @@ static int si2168_set_frontend(struct
dvb_frontend *fe)
   struct i2c_client *client = fe->demodulator_priv;
   struct si2168_dev *dev = i2c_get_clientdata(client);
   struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+    struct si2168_config *config = client->dev.platform_data;

hmmm, are you sure platform data pointer points is const? I usually
tend to store all config information to device state. Then there is no
need to care if pointer is valid or not anymore.

And inversion happens when those wires are cross-connected

It just dawned on me that the platform_data is stack allocated and
therefore not safe to access outside of probe. I will fix this momentarily.

I was informed by one of our hardware guys that the two models in patch
2/2 are inverted spectrum, so I guess they have wires cross-connected. I
can verify this again to be sure.



Hello Antti,

I have confirmation. No 'cross-connected' / swapped differential pair
polarities (if that's what you meant) on the IF pins. The si2157
inverted spectrum output is configurable though, and Hauppauge
have the tuner set up to output inverted. Sounds like it was a decision
based on interoperability with older demods.


yeah, that was what I was thinking for. That board single tuner and two 
demods which other demod does not support if spectrum inversion?


If there is just si2168 and si2157, you can set both to invert or both 
to non-invert - the end result is same.


Antti

--
http://palosaari.fi/


Re: [PATCH 1/4] si2157: add detection of si2177 tuner

2019-01-09 Thread Antti Palosaari

On 12/20/18 11:57 PM, Brad Love wrote:

Works in ATSC and QAM as is, DVB is completely untested.

Firmware required.

Signed-off-by: Brad Love 
---
  drivers/media/tuners/si2157.c  | 6 ++
  drivers/media/tuners/si2157_priv.h | 3 ++-




  #define SI2158_A20_FIRMWARE "dvb-tuner-si2158-a20-01.fw"
  #define SI2141_A10_FIRMWARE "dvb-tuner-si2141-a10-01.fw"
-
+#define SI2157_A30_FIRMWARE "dvb-tuner-si2157-a30-05.fw"


Why you added 05 to that file name? I added that spare number for cases 
you have to replace firmware to another for some reason thus by default 
case it should be 01.


regards
Antti

--
http://palosaari.fi/


Re: [PATCH 02/13] si2157: Check error status bit on cmd execute

2019-01-09 Thread Antti Palosaari

On 12/29/18 7:51 PM, Brad Love wrote:

Check error status bit on command execute, if error bit is
set return -EAGAIN. Ignore -EAGAIN in probe during device check.

Signed-off-by: Brad Love 
---
  drivers/media/tuners/si2157.c | 12 +---
  1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c
index 4855448..3924c42 100644
--- a/drivers/media/tuners/si2157.c
+++ b/drivers/media/tuners/si2157.c
@@ -56,14 +56,20 @@ static int si2157_cmd_execute(struct i2c_client *client, 
struct si2157_cmd *cmd)
break;
}
  
-		dev_dbg(&client->dev, "cmd execution took %d ms\n",

+   dev_dbg(&client->dev, "cmd execution took %d ms, status=%x\n",
jiffies_to_msecs(jiffies) -
-   (jiffies_to_msecs(timeout) - TIMEOUT));
+   (jiffies_to_msecs(timeout) - TIMEOUT),
+   cmd->args[0]);
  
  		if (!((cmd->args[0] >> 7) & 0x01)) {

ret = -ETIMEDOUT;
goto err_mutex_unlock;
}
+   /* check error status bit */
+   if (cmd->args[0] & 0x40) {
+   ret = -EAGAIN;
+   goto err_mutex_unlock;
+   }
}
  
  	mutex_unlock(&dev->i2c_mutex);

@@ -477,7 +483,7 @@ static int si2157_probe(struct i2c_client *client,
cmd.wlen = 0;
cmd.rlen = 1;
ret = si2157_cmd_execute(client, &cmd);
-   if (ret)
+   if (ret && (ret != -EAGAIN))
goto err_kfree;
  
  	memcpy(&fe->ops.tuner_ops, &si2157_ops, sizeof(struct dvb_tuner_ops));




So you added check if firmware returns error during command execution, 
but that error is still skipped during probe, which does not feel 
correct. Chip should work during probe and ideally driver should ensure 
it is correct chip. At least you should read some property value or 
execute some other command without failure.


regards
Antti

--
http://palosaari.fi/


Re: [PATCH] media: m88ds3103: serialize reset messages in m88ds3103_set_frontend

2019-01-20 Thread Antti Palosaari

On 1/13/19 11:13 PM, James Hutchinson wrote:

Ref: https://bugzilla.kernel.org/show_bug.cgi?id=199323

Users are experiencing problems with the DVBSky S960/S960C USB devices
since the following commit:

9d659ae: ("locking/mutex: Add lock handoff to avoid starvation")

The device malfunctions after running for an indeterminable period of
time, and the problem can only be cleared by rebooting the machine.

It is possible to encourage the problem to surface by blocking the
signal to the LNB.

Further debugging revealed the cause of the problem.

In the following capture:
- thread #1325 is running m88ds3103_set_frontend
- thread #42 is running ts2020_stat_work

a> [1325] usb 1-1: dvb_usb_v2_generic_io: >>> 08 68 02 07 80
[1325] usb 1-1: dvb_usb_v2_generic_io: <<< 08
[42] usb 1-1: dvb_usb_v2_generic_io: >>> 09 01 01 68 3f
[42] usb 1-1: dvb_usb_v2_generic_io: <<< 08 ff
[42] usb 1-1: dvb_usb_v2_generic_io: >>> 08 68 02 03 11
[42] usb 1-1: dvb_usb_v2_generic_io: <<< 07
[42] usb 1-1: dvb_usb_v2_generic_io: >>> 09 01 01 60 3d
[42] usb 1-1: dvb_usb_v2_generic_io: <<< 07 ff
b> [1325] usb 1-1: dvb_usb_v2_generic_io: >>> 08 68 02 07 00
[1325] usb 1-1: dvb_usb_v2_generic_io: <<< 07
[42] usb 1-1: dvb_usb_v2_generic_io: >>> 08 68 02 03 11
[42] usb 1-1: dvb_usb_v2_generic_io: <<< 07
[42] usb 1-1: dvb_usb_v2_generic_io: >>> 09 01 01 60 21
[42] usb 1-1: dvb_usb_v2_generic_io: <<< 07 ff
[42] usb 1-1: dvb_usb_v2_generic_io: >>> 08 68 02 03 11
[42] usb 1-1: dvb_usb_v2_generic_io: <<< 07
[42] usb 1-1: dvb_usb_v2_generic_io: >>> 09 01 01 60 66
[42] usb 1-1: dvb_usb_v2_generic_io: <<< 07 ff
[1325] usb 1-1: dvb_usb_v2_generic_io: >>> 08 68 02 03 11
[1325] usb 1-1: dvb_usb_v2_generic_io: <<< 07
[1325] usb 1-1: dvb_usb_v2_generic_io: >>> 08 60 02 10 0b
[1325] usb 1-1: dvb_usb_v2_generic_io: <<< 07

Two i2c messages are sent to perform a reset in m88ds3103_set_frontend:

   a. 0x07, 0x80
   b. 0x07, 0x00

However, as shown in the capture, the regmap mutex is being handed over
to another thread (ts2020_stat_work) in between these two messages.


From here, the device responds to every i2c message with an 07 message,

and will only return to normal operation following a power cycle.

Use regmap_multi_reg_write to group the two reset messages, ensuring
both are processed before the regmap mutex is unlocked.


I tried to reproduce that issue with pctv 461e, which has em28xx 
usb-interface, but without success. Even when I added some sleep between 
reset commands and increased tuner statistic polling interval such that 
it polls all the time, it works correctly. Device has tuner is connected 
to demod i2c bus, which I think is same for your device (it calls demod 
i2c mux select for every tuner i2c access).


Taking into account tests I made it is probably issue with usb-interface 
i2c adapter instead - for some reason it stops working and starts 
returning 07 error all the time. Did any other I2C command succeed after 
failure? I mean is there any other i2c client on that bus you could test 
if it fails too on error situation?


All in all, fix should be done to usb-interface i2c adapter if possible 
unless it has proven issue is somewhere else. You could try to add some 
sleep or repeat to i2c adapter in order to see if it helps.


regards
Antti

--
http://palosaari.fi/


Re: [PATCH 04/13] si2157: Add clock and pin setup for si2141

2019-01-20 Thread Antti Palosaari



On 12/29/18 7:51 PM, Brad Love wrote:

Include some missing setup for si2141

Signed-off-by: Brad Love 
---
  drivers/media/tuners/si2157.c | 17 +
  1 file changed, 17 insertions(+)

diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c
index f3a60a1..1ad2d42 100644
--- a/drivers/media/tuners/si2157.c
+++ b/drivers/media/tuners/si2157.c
@@ -236,6 +236,23 @@ static int si2157_init(struct dvb_frontend *fe)
dev_info(&client->dev, "firmware version: %c.%c.%d\n",
cmd.args[6], cmd.args[7], cmd.args[8]);
  
+	if (dev->chiptype == SI2157_CHIPTYPE_SI2141) {

+   /* set clock */
+   memcpy(cmd.args, "\xc0\x00\x0d", 3);
+   cmd.wlen = 3;
+   cmd.rlen = 1;
+   ret = si2157_cmd_execute(client, &cmd);
+   if (ret)
+   goto err;
+   /* setup PIN */
+   memcpy(cmd.args, "\x12\x80\x80\x85\x00\x81\x00", 7);
+   cmd.wlen = 7;
+   cmd.rlen = 7;
+   ret = si2157_cmd_execute(client, &cmd);
+   if (ret)
+   goto err;
+   }
+
/* enable tuner status flags */
memcpy(cmd.args, "\x14\x00\x01\x05\x01\x00", 6);
cmd.wlen = 6;



Si2141 is working in my understanding, why these are required?


regards
Antti



--
http://palosaari.fi/


Re: [PATCH 12/13] si2157: add on-demand rf strength func

2019-01-20 Thread Antti Palosaari

On 12/29/18 7:51 PM, Brad Love wrote:

Add get_rf_strength callback to get RSSI from the tuner. DVBv5
stat cache is updated.

Signed-off-by: Brad Love 




---
  drivers/media/tuners/si2157.c | 38 +-
  1 file changed, 37 insertions(+), 1 deletion(-)

diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c
index 1737007..f28bf7f 100644
--- a/drivers/media/tuners/si2157.c
+++ b/drivers/media/tuners/si2157.c
@@ -752,6 +752,40 @@ static int si2157_get_if_frequency(struct dvb_frontend 
*fe, u32 *frequency)
return 0;
  }
  
+static int si2157_get_rf_strength(struct dvb_frontend *fe, u16 *rssi)

+{
+   struct i2c_client *client = fe->tuner_priv;
+   struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+   struct si2157_cmd cmd;
+   int ret;
+   int strength;
+
+   dev_dbg(&client->dev, "\n");
+
+   memcpy(cmd.args, "\x42\x00", 2);
+   cmd.wlen = 2;
+   cmd.rlen = 12;
+   ret = si2157_cmd_execute(client, &cmd);
+   if (ret)
+   goto err;
+
+   c->strength.stat[0].scale = FE_SCALE_DECIBEL;
+   c->strength.stat[0].svalue = (s8) cmd.args[3] * 1000;
+
+   strength = (s8)cmd.args[3];
+   strength = (strength > -80) ? (u16)(strength + 100) : 0;
+   strength = strength > 80 ? 100 : strength;
+
+   *rssi = (u16)(strength * 0x / 100);
+   dev_dbg(&client->dev, "%s: strength=%d rssi=%u\n",
+   __func__, (s8)cmd.args[3], *rssi);
+
+   return 0;
+err:
+   dev_dbg(&client->dev, "failed=%d\n", ret);
+   return ret;
+}
+
  static const struct dvb_tuner_ops si2157_ops = {
.info = {
.name = "Silicon Labs 
Si2141/Si2146/2147/2148/2157/2158",
@@ -765,7 +799,9 @@ static const struct dvb_tuner_ops si2157_ops = {
.set_analog_params = si2157_set_analog_params,
.get_frequency = si2157_get_frequency,
.get_bandwidth = si2157_get_bandwidth,
-   .get_if_frequency = si2157_get_if_frequency,
+   .get_if_frequency  = si2157_get_if_frequency,
+
+   .get_rf_strength   = si2157_get_rf_strength,
  };
  
  static void si2157_stat_work(struct work_struct *work)




Where that is called from?

It is also hard to read how you convert dBm RSSI value to some other 
scale. There is various clamp() macros for limiting value to desired range.


__func__ should not be passed to dev_ macros, check some manual how to use.

Driver already polls rssi for digital tv, but I assume that is somehow 
related to analog.



regards
Antti

--
http://palosaari.fi/


Re: [PATCH] media: m88ds3103: serialize reset messages in m88ds3103_set_frontend

2019-01-22 Thread Antti Palosaari




On 1/22/19 1:08 PM, James Hutchinson wrote:

On Sun, Jan 20, 2019 at 04:43:08PM +0200, Antti Palosaari wrote:

On 1/13/19 11:13 PM, James Hutchinson wrote:

Ref: https://bugzilla.kernel.org/show_bug.cgi?id=199323

Users are experiencing problems with the DVBSky S960/S960C USB devices
since the following commit:

9d659ae: ("locking/mutex: Add lock handoff to avoid starvation")

The device malfunctions after running for an indeterminable period of
time, and the problem can only be cleared by rebooting the machine.

It is possible to encourage the problem to surface by blocking the
signal to the LNB.

Further debugging revealed the cause of the problem.

In the following capture:
- thread #1325 is running m88ds3103_set_frontend
- thread #42 is running ts2020_stat_work

a> [1325] usb 1-1: dvb_usb_v2_generic_io: >>> 08 68 02 07 80
 [1325] usb 1-1: dvb_usb_v2_generic_io: <<< 08
 [42] usb 1-1: dvb_usb_v2_generic_io: >>> 09 01 01 68 3f
 [42] usb 1-1: dvb_usb_v2_generic_io: <<< 08 ff
 [42] usb 1-1: dvb_usb_v2_generic_io: >>> 08 68 02 03 11
 [42] usb 1-1: dvb_usb_v2_generic_io: <<< 07
 [42] usb 1-1: dvb_usb_v2_generic_io: >>> 09 01 01 60 3d
 [42] usb 1-1: dvb_usb_v2_generic_io: <<< 07 ff
b> [1325] usb 1-1: dvb_usb_v2_generic_io: >>> 08 68 02 07 00
 [1325] usb 1-1: dvb_usb_v2_generic_io: <<< 07
 [42] usb 1-1: dvb_usb_v2_generic_io: >>> 08 68 02 03 11
 [42] usb 1-1: dvb_usb_v2_generic_io: <<< 07
 [42] usb 1-1: dvb_usb_v2_generic_io: >>> 09 01 01 60 21
 [42] usb 1-1: dvb_usb_v2_generic_io: <<< 07 ff
 [42] usb 1-1: dvb_usb_v2_generic_io: >>> 08 68 02 03 11
 [42] usb 1-1: dvb_usb_v2_generic_io: <<< 07
 [42] usb 1-1: dvb_usb_v2_generic_io: >>> 09 01 01 60 66
 [42] usb 1-1: dvb_usb_v2_generic_io: <<< 07 ff
 [1325] usb 1-1: dvb_usb_v2_generic_io: >>> 08 68 02 03 11
 [1325] usb 1-1: dvb_usb_v2_generic_io: <<< 07
 [1325] usb 1-1: dvb_usb_v2_generic_io: >>> 08 60 02 10 0b
 [1325] usb 1-1: dvb_usb_v2_generic_io: <<< 07

Two i2c messages are sent to perform a reset in m88ds3103_set_frontend:

a. 0x07, 0x80
b. 0x07, 0x00

However, as shown in the capture, the regmap mutex is being handed over
to another thread (ts2020_stat_work) in between these two messages.


 From here, the device responds to every i2c message with an 07 message,

and will only return to normal operation following a power cycle.

Use regmap_multi_reg_write to group the two reset messages, ensuring
both are processed before the regmap mutex is unlocked.


I tried to reproduce that issue with pctv 461e, which has em28xx
usb-interface, but without success. Even when I added some sleep between
reset commands and increased tuner statistic polling interval such that it
polls all the time, it works correctly. Device has tuner is connected to
demod i2c bus, which I think is same for your device (it calls demod i2c mux
select for every tuner i2c access).

Taking into account tests I made it is probably issue with usb-interface i2c
adapter instead - for some reason it stops working and starts returning 07
error all the time. Did any other I2C command succeed after failure? I mean
is there any other i2c client on that bus you could test if it fails too on
error situation?

All in all, fix should be done to usb-interface i2c adapter if possible
unless it has proven issue is somewhere else. You could try to add some
sleep or repeat to i2c adapter in order to see if it helps.

regards
Antti

--
http://palosaari.fi/


Thanks for taking the time to review my patch.

My device is the dvbsky usb s960 which is a pretty popular device and hasn't
been working for several users since commit 9d659ae.

I did some further investigation and can now see that the issue likely only
affects adapters which use the m88ds3103_get_agc_pwm function to get the AGC
from the demodulator as part of ts2020_stat_work.

This is the 3f message in my original capture, which gets an ff response.
 [42] usb 1-1: dvb_usb_v2_generic_io: >>> 09 01 01 68 3f
 [42] usb 1-1: dvb_usb_v2_generic_io: <<< 08 ff

The m88ds3103_get_agc_pwm function looks to be used by a subset of devices and
their variants from the dvbsky usb-interface (s960 & s960c), and the cx23885-dvb
pci-interface (s950, s950c, s952).

The problem does NOT occur if I disable auto-gain correction by removing the
following line from dvbsky_s960_attach:

 ts2020_config.get_agc_pwm = m88ds3103_get_agc_pwm;

I then have the same experience as you; I can add a sleep between the reset
commands and increase the tuner statistic polling interval, and it still
works correctly.

I can also reproduce the issue on older kernels (pre-commit 9d659ae) by adding
a sleep between the two reset commands and leaving the agc re

Re: [PATCH] dvb_usb_dvbsky: Mygica T230C2 add support for T230C hw version 2

2019-06-11 Thread Antti Palosaari

On 6/8/19 5:49 AM, JP wrote:

I made the Mygica T230c2 work on kernel 5.1.7, but I have no idea

how to submit this. http://jpvw.nl/pub/test/dvb/linux-5.1.7-t230c2.patch


Please can someone help me out. It looks like the extra code in the

demodulator does not effect other drivers that use it. Tested with a

T230, they bothseem to work OK.


Jan Pieter van Woerkom



diff -ru a/drivers/media/dvb-frontends/si2168.c 
b/drivers/media/dvb-frontends/si2168.c
--- a/drivers/media/dvb-frontends/si2168.c    2019-06-04 
07:59:45.0 +0200
+++ b/drivers/media/dvb-frontends/si2168.c    2019-06-07 
22:49:21.226337473 +0200

@@ -91,8 +91,16 @@

  dev_dbg(&client->dev, "%s acquire: %d\n", __func__, acquire);

+    /* set ts clock freq to 10Mhz */
+       memcpy(cmd.args, "\x14\x00\x0d\x10\xe8\x03", 6);
+    cmd.wlen = 6;
+    cmd.rlen = 4;
+    ret = si2168_cmd_execute(client, &cmd);
+    if (ret) return ret;
+


0x03e8 is 1000 and value used is 10 000Hz steps ==> 10 000 000 = 10MHz. 
Which means 8bit parallel ts bus has capacity of 80Mbit/s which sounds 
correct max for DVB-T2. What is default value set to that property? Many 
times those default values are just correct.



  /* set TS_MODE property */
-    memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6);
+    memcpy(cmd.args, "\x14\x00\x01\x10\x00\x00", 6);
+    cmd.args[4] = dev->ts_mode & 0x30;
  if (acquire)
      cmd.args[4] |= dev->ts_mode;
  else


And that enables use of own value.

Anyhow, I don't like idea of piggybacking those "magic" bits on ts mode 
configuration variable. It is better to define own configuration value 
for ts clock on use it when it is set.



diff -ru a/drivers/media/usb/dvb-usb-v2/dvbsky.c 
b/drivers/media/usb/dvb-usb-v2/dvbsky.c
--- a/drivers/media/usb/dvb-usb-v2/dvbsky.c    2019-06-04 
07:59:45.0 +0200
+++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c    2019-06-07 
16:47:32.141530489 +0200

@@ -560,6 +560,9 @@
  si2168_config.i2c_adapter = &i2c_adapter;
  si2168_config.fe = &adap->fe[0];
  si2168_config.ts_mode = SI2168_TS_PARALLEL;
+    if (d->udev->descriptor.idProduct == USB_PID_MYGICA_T230C2)
+        si2168_config.ts_mode |= 0x20;
  si2168_config.ts_clock_inv = 1;

  state->i2c_client_demod = dvb_module_probe("si2168", NULL,
@@ -799,6 +802,9 @@
  { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C,
      &mygica_t230c_props, "MyGica Mini DVB-T2 USB Stick T230C",
      RC_MAP_TOTAL_MEDIA_IN_HAND_02) },
+    { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C2,
+    &mygica_t230c_props, "MyGica Mini DVB-T2 USB Stick T230C2",
+    RC_MAP_TOTAL_MEDIA_IN_HAND_02) },
  { }
  };
  MODULE_DEVICE_TABLE(usb, dvbsky_id_table);
diff -ru a/include/media/dvb-usb-ids.h b/include/media/dvb-usb-ids.h
--- a/include/media/dvb-usb-ids.h    2019-06-04 07:59:45.0 +0200
+++ b/include/media/dvb-usb-ids.h    2019-06-06 17:32:32.159187000 +0200
@@ -387,6 +387,7 @@
  #define USB_PID_MYGICA_D689                0xd811
  #define USB_PID_MYGICA_T230                0xc688
  #define USB_PID_MYGICA_T230C                0xc689
+#define USB_PID_MYGICA_T230C2                0xc68a
  #define USB_PID_ELGATO_EYETV_DIVERSITY            0x0011
  #define USB_PID_ELGATO_EYETV_DTT            0x0021
  #define USB_PID_ELGATO_EYETV_DTT_2            0x003f



What is that T230C2 stick? Naming sounds like a DVB-C2 capable, but I 
found only T230C model from MyGica site. Where I can get one?


And also patch should be split to two logical parts, first add manual ts 
frequency support to si2168 and then other patch which adds device itself.


And which are tuner and demod versions/revisions used for that device?

regards
Antti

--
http://palosaari.fi/


Re: [PATCH] dvb_usb_dvbsky: Mygica T230C2 add support for T230C hw version 2

2019-06-11 Thread Antti Palosaari




On 6/12/19 2:27 AM, JP wrote:



On 6/12/19 12:28 AM, Antti Palosaari wrote:

On 6/8/19 5:49 AM, JP wrote:

I made the Mygica T230c2 work on kernel 5.1.7, but I have no idea

how to submit this. http://jpvw.nl/pub/test/dvb/linux-5.1.7-t230c2.patch


Please can someone help me out. It looks like the extra code in the

demodulator does not effect other drivers that use it. Tested with a

T230, they bothseem to work OK.


Jan Pieter van Woerkom



diff -ru a/drivers/media/dvb-frontends/si2168.c 
b/drivers/media/dvb-frontends/si2168.c
--- a/drivers/media/dvb-frontends/si2168.c    2019-06-04 
07:59:45.0 +0200
+++ b/drivers/media/dvb-frontends/si2168.c    2019-06-07 
22:49:21.226337473 +0200

@@ -91,8 +91,16 @@

  dev_dbg(&client->dev, "%s acquire: %d\n", __func__, acquire);

+    /* set ts clock freq to 10Mhz */
+       memcpy(cmd.args, "\x14\x00\x0d\x10\xe8\x03", 6);
+    cmd.wlen = 6;
+    cmd.rlen = 4;
+    ret = si2168_cmd_execute(client, &cmd);
+    if (ret) return ret;
+


0x03e8 is 1000 and value used is 10 000Hz steps ==> 10 000 000 = 
10MHz. Which means 8bit parallel ts bus has capacity of 80Mbit/s which 
sounds correct max for DVB-T2. What is default value set to that 
property? Many times those default values are just correct.


The default value *is* 10Mhz. On all other si2168 hardware this does not 
need to be set but for some reason, on this hardware it needs to be set 
manually. The actual value has been scanned from the running windows 
driver by means of a USB logger. My best guess is that this whole si2168 
driver has been written with the help of such a logger.


If the default value is already 10MHz then there is no need to set it at 
all. I am a bit too lazy to start dumping that default value out from 
the chip atm.



  /* set TS_MODE property */
-    memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6);
+    memcpy(cmd.args, "\x14\x00\x01\x10\x00\x00", 6);
+    cmd.args[4] = dev->ts_mode & 0x30;
  if (acquire)
      cmd.args[4] |= dev->ts_mode;
  else


And that enables use of own value.

Anyhow, I don't like idea of piggybacking those "magic" bits on ts 
mode configuration variable. It is better to define own configuration 
value for ts clock on use it when it is set.




In other cases I immediately would agree, but actually, all bits in the 
hw register correspond with the bits in the ts mode configuration 
variable. When I discovered that, I could not resist making use of it. 
The code is very compact this way. But all right, you convinced me. I 
guess :-)


You may also define flag for TS_MODE_PARALLEL_10MHZ or so. IIRC, 
(haven't been there for a while), it is 10 and 16MHz used widely for 
parallel ts. So freely configurable ts clock may be a bit overkill still :]


Own media/dvb wide datatype for ts settings could be nice if someone 
ever wants to implement such.


diff -ru a/drivers/media/usb/dvb-usb-v2/dvbsky.c 
b/drivers/media/usb/dvb-usb-v2/dvbsky.c
--- a/drivers/media/usb/dvb-usb-v2/dvbsky.c    2019-06-04 
07:59:45.0 +0200
+++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c    2019-06-07 
16:47:32.141530489 +0200

@@ -560,6 +560,9 @@
  si2168_config.i2c_adapter = &i2c_adapter;
  si2168_config.fe = &adap->fe[0];
  si2168_config.ts_mode = SI2168_TS_PARALLEL;
+    if (d->udev->descriptor.idProduct == USB_PID_MYGICA_T230C2)
+        si2168_config.ts_mode |= 0x20;
  si2168_config.ts_clock_inv = 1;

  state->i2c_client_demod = dvb_module_probe("si2168", NULL,
@@ -799,6 +802,9 @@
  { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C,
      &mygica_t230c_props, "MyGica Mini DVB-T2 USB Stick T230C",
      RC_MAP_TOTAL_MEDIA_IN_HAND_02) },
+    { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C2,
+    &mygica_t230c_props, "MyGica Mini DVB-T2 USB Stick T230C2",
+    RC_MAP_TOTAL_MEDIA_IN_HAND_02) },
  { }
  };
  MODULE_DEVICE_TABLE(usb, dvbsky_id_table);
diff -ru a/include/media/dvb-usb-ids.h b/include/media/dvb-usb-ids.h
--- a/include/media/dvb-usb-ids.h    2019-06-04 07:59:45.0 +0200
+++ b/include/media/dvb-usb-ids.h    2019-06-06 17:32:32.159187000 +0200
@@ -387,6 +387,7 @@
  #define USB_PID_MYGICA_D689                0xd811
  #define USB_PID_MYGICA_T230                0xc688
  #define USB_PID_MYGICA_T230C                0xc689
+#define USB_PID_MYGICA_T230C2                0xc68a
  #define USB_PID_ELGATO_EYETV_DIVERSITY            0x0011
  #define USB_PID_ELGATO_EYETV_DTT            0x0021
  #define USB_PID_ELGATO_EYETV_DTT_2            0x003f



What is that T230C2 stick? Naming sounds like a DVB-C2 capable, but I 
found only T230C model from MyGica site. Where I can get one?
The T230C2 is sold as T230C. Apart from that it needs the TS clock be 
set they both are exactly the same. I bought it from China. Aliexpress. 
The old T230C is out of stock.


And al

Re: [PATCH] dvb_usb_dvbsky: Mygica T230C2 add support for T230C hw version 2

2019-06-11 Thread Antti Palosaari

On 6/12/19 2:49 AM, Antti Palosaari wrote:

+    /* set ts clock freq to 10Mhz */
+       memcpy(cmd.args, "\x14\x00\x0d\x10\xe8\x03", 6);
+    cmd.wlen = 6;
+    cmd.rlen = 4;
+    ret = si2168_cmd_execute(client, &cmd);
+    if (ret) return ret;
+


0x03e8 is 1000 and value used is 10 000Hz steps ==> 10 000 000 = 
10MHz. Which means 8bit parallel ts bus has capacity of 80Mbit/s 
which sounds correct max for DVB-T2. What is default value set to 
that property? Many times those default values are just correct.


The default value *is* 10Mhz. On all other si2168 hardware this does 
not need to be set but for some reason, on this hardware it needs to 
be set manually. The actual value has been scanned from the running 
windows driver by means of a USB logger. My best guess is that this 
whole si2168 driver has been written with the help of such a logger.


If the default value is already 10MHz then there is no need to set it at 
all. I am a bit too lazy to start dumping that default value out from 
the chip atm.


Looked from the pctv 292e sniffs, and it seems default is set to 7.2MHz.

$ grep -A1 "\\\x14\\\x00\\\x0d\\\x10" l.c
i2c_master_send_DEMOD(s->client, "\x14\x00\x0d\x10\xd0\x02", 6); //014597
i2c_master_recv_DEMOD(s->client, buf, 4); //014598 "\x80\x00\xd0\x02"


T230C windows driver does not touch that value at all. In theory default 
may be different on different chip revisions, but I haven't never seen 
such case so I suspect it is still 7.2MHz on your device.


regards
Antti

--
http://palosaari.fi/


Re: [PATCH] dvb_usb_dvbsky: Mygica T230C2 add support for T230C hw version 2

2019-06-13 Thread Antti Palosaari

On 6/13/19 4:15 AM, JP wrote:
And according to old usb sniffs from pctv 292e [Si2168B] default 
manual ts clock is set to 7.2MHz, which means 57.6Mbit/s datarate, it 
should be quite optimal for DVB-T2 max. In theory it could be a 
little higher only when 10MHz channel bandwidth and most less error 
correction FEC in use. And currently driver is using some config that 
uses dynamic ts clock which clocks only when there is data to feed. 
For some reason, usb-ts-bridge does not understand that and manual 
configuration is needed (ts valid or ts-sync connection?). If 
possible use 7.2MHz, if not: set to 10MHz.


That's perfectly alright with me. I'm now testing that 7.2Mhz value. 
Hold on.
The driver crashes with the 7.2Mhz value! That was totally not what I 
ever expected.
Recompiled the whole kernel: crashes again. Then tried on debian kernel 
4.19: same thing.

Food for thought?


It should sure never crash the kernel. Changing a ts bitrate no, no, no, 
you trapped a hidden bug. Found where it is :]


regards
Antti

--
http://palosaari.fi/


Re: [PATCH] dvb_usb_dvbsky: Mygica T230C2 add support for T230C hw version 2

2019-06-13 Thread Antti Palosaari

On 6/12/19 11:07 PM, Frantisek Rysanek wrote:

On 12 Jun 2019 at 1:28, Antti Palosaari wrote:
[...]


What is that T230C2 stick?

JP has already explained the details, how that name was arrived at.
As previously suggested, I can call it T230C v2 in the descriptive
texts. I'd suggest keeping T230C2 in the USB ID macro (or suggest
a more appropriate name for the macro).

Here in CZ, a company called Abacus imports and distributes consumer
electronics gadgets under a private brand "EvolveO" - and this is how
the "rebadged OEM Mygica" has reached me.
   http://m.evolveo.com/cz/sigma-t2
This particular T2 dongle is "allover the place" around here, no
other dongle is this broadly available. (Well on our modest market.
We're a nation of 10M people.)


Naming sounds like a DVB-C2 capable, but I
found only T230C model from MyGica site.


The local brand's site only mentions DVB-T2.
The 2-page "brief datasheet" of the si2168 that's publically
available only mentions DVB-C, apart from T/T2.


And also patch should be split to two logical parts, first add manual ts
frequency support to si2168 and then other patch which adds device itself.


I'll try to find some time and massage that approach into the code.
I have read all the past attempts (example patches) and the
maintainer's polite objections.


And which are tuner and demod versions/revisions used for that device?


That's reported in dmesg if memory serves... I'll try to find the
answer.

Frank Rysanek



Yeah, all-in-all:
1) name it T230C v2
2) use manual ts clock speed

And according to old usb sniffs from pctv 292e [Si2168B] default manual 
ts clock is set to 7.2MHz, which means 57.6Mbit/s datarate, it should be 
quite optimal for DVB-T2 max. In theory it could be a little higher only 
when 10MHz channel bandwidth and most less error correction FEC in use. 
And currently driver is using some config that uses dynamic ts clock 
which clocks only when there is data to feed. For some reason, 
usb-ts-bridge does not understand that and manual configuration is 
needed (ts valid or ts-sync connection?). If possible use 7.2MHz, if 
not: set to 10MHz.


regards
Antti
--
http://palosaari.fi/


Re: si2168 gapped clock

2019-06-24 Thread Antti Palosaari

Hello,

On 6/18/19 7:47 PM, Marc Gonzalez wrote:

Hello,

In the qcom SoC, the TS interface has two modes of operation.

- with 3 signals (clk, valid, data)
- with 4 signals (clk, valid, data, sync)

In the si2168 short datasheet, I can see a diagram with these
4 signals.

My question is: how do we configure the si2168 demod to be
in the first mode or the second mode?

Is it the ts_clock_gapped parameter?

ts_clock_gapped=0 means no sync
ts_clock_gapped=1 means with sync ???

Regards.



In general for mpeg ts you will need:
data + clock + valid : when clock is running continuously
or
data + clock : when clock is running only when there is data


Valid is used to tell there is new data when clock is running 
continuously - when valid signal is not set there is no data even clock 
is running.


When only data and clock lines are used, clock is ran only when there is 
data.


Sync signal is set for beginning of every TS packet (and it is not 
hardly needed if you parse ts data by software for example).


Thus ts_clock_gapped means demod will flip clock only when there is data 
to feed ==> no need for valid signal.


Configuring demod to first *or* second mode should be just 
ts_clock_gapped=false.


regards
Antti

--
http://palosaari.fi/


Re: [PATCH 1/2] dvbsky: add support for "Mygica T230C v2"

2019-06-25 Thread Antti Palosaari




On 6/25/19 6:41 PM, JP wrote:



On 6/25/19 1:16 PM, Sean Young wrote:

On Sun, Jun 16, 2019 at 02:39:29AM +0200, Jan Pieter van Woerkom wrote:

From: Jan Pieter van Woerkom 

Adds support for the "Mygica T230C v2" into the "dvbsky" driver.
A small enhancement is also needed in the si2168 demodulator
driver, and a USB device ID in dvb-usb-ids.h .

This is v3.3 of the proposed patch, based on feedback from Sean
Young and Antti Palosaari.
Tested by patch author on a T230C v2.
Tested by Frank Rysanek on a T230C v2: can tune into locally
available DVB-T and DVB-T2 muxes, video and audio playback works.
Applies cleanly against Linux 5.1.10 .

The T230C v2 hardware needs a mode of the si2168 chip to be
set for which the si2168 driver previously had no support.
This patch uses a specific measure to configure this on the
T230C v2 hardware only - see the flag passed via the ts_mode
attribute and its dependency on USB_PID_MYGICA_T230C2. Other
devices using the si2168 demodulator driver are not affected
in any way.

Signed-off-by: Jan Pieter van Woerkom 
Tested-by: Frank Rysanek 
---
diff -ru a/drivers/media/dvb-frontends/si2168.c 
b/drivers/media/dvb-frontends/si2168.c
--- a/drivers/media/dvb-frontends/si2168.c    2019-06-04 
07:59:45.0 +0200
+++ b/drivers/media/dvb-frontends/si2168.c    2019-06-08 
19:47:32.385526558 +0200

@@ -91,8 +91,18 @@
  dev_dbg(&client->dev, "%s acquire: %d\n", __func__, acquire);
+    /* set manual value */
+    if (dev->ts_mode | SI2168_TS_CLK_MANUAL) {

This looks wrong. Should it not be "dev->ts_mode & SI2168_TS_CLK_MANUAL"?
Now the expression is always true.

You're absolutely right. Silly me.

What now? Correct and repost?


yes, and next indentation looks also wrong





+    memcpy(cmd.args, "\x14\x00\x0d\x10\xe8\x03", 6);
+    cmd.wlen = 6;
+    cmd.rlen = 4;
+    ret = si2168_cmd_execute(client, &cmd);
+    if (ret)
+    return ret;
+    }
  /* set TS_MODE property */
-    memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6);
+    memcpy(cmd.args, "\x14\x00\x01\x10\x00\x00", 6);
+    cmd.args[4] = dev->ts_mode & 
(SI2168_TS_CLK_AUTO|SI2168_TS_CLK_MANUAL);

  if (acquire)
  cmd.args[4] |= dev->ts_mode;
  else
diff -ru a/drivers/media/dvb-frontends/si2168.h 
b/drivers/media/dvb-frontends/si2168.h
--- a/drivers/media/dvb-frontends/si2168.h    2019-06-04 
07:59:45.0 +0200
+++ b/drivers/media/dvb-frontends/si2168.h    2019-06-08 
19:32:52.400320490 +0200

@@ -39,6 +39,8 @@
  #define SI2168_TS_PARALLEL    0x06
  #define SI2168_TS_SERIAL    0x03
  #define SI2168_TS_TRISTATE    0x00
+#define SI2168_TS_CLK_AUTO    0x10
+#define SI2168_TS_CLK_MANUAL    0x20
  u8 ts_mode;
  /* TS clock inverted */

Thanks,
Sean


Thank you,
Jan Pieter.


regards
Antti

--
http://palosaari.fi/


Re: [PATCH] media: tm6000: Spelling s/diconencted/diconnected/

2019-07-31 Thread Antti Palosaari

On 7/31/19 4:41 PM, Geert Uytterhoeven wrote:

Signed-off-by: Geert Uytterhoeven 
---
  drivers/media/usb/tm6000/tm6000-cards.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/usb/tm6000/tm6000-cards.c 
b/drivers/media/usb/tm6000/tm6000-cards.c
index 23df50aa0a4af6da..9a0ffe678524987c 100644
--- a/drivers/media/usb/tm6000/tm6000-cards.c
+++ b/drivers/media/usb/tm6000/tm6000-cards.c
@@ -1328,7 +1328,7 @@ static int tm6000_usb_probe(struct usb_interface 
*interface,
  
  /*

   * tm6000_usb_disconnect()
- * called when the device gets diconencted
+ * called when the device gets diconnected


disconnected ?

For the both patches.


   * video device will be unregistered on v4l2_close in case it is still open
   */
  static void tm6000_usb_disconnect(struct usb_interface *interface)




regards
Antti

--
http://palosaari.fi/


Re: [PATCH v4] dvb-usb/friio, dvb-usb-v2/gl861: decompose friio and merge with gl861

2018-03-27 Thread Antti Palosaari

On 03/27/2018 08:47 PM, tsk...@gmail.com wrote:

From: Akihiro Tsukada 

Friio device contains "gl861" bridge and "tc90522" demod,
for which the separate drivers are already in the kernel.
But friio driver was monolithic and did not use them,
practically copying those features.
This patch decomposes friio driver into sub drivers and
re-uses existing ones, thus reduces some code.

It adds some features to gl861,
to support the friio-specific init/config of the devices
and implement i2c communications to the tuner via demod
with USB vendor requests.


You should implement i2c adapter to demod driver and not add such glue 
to that USB-bridge. I mean that "relayed" stuff, i2c communication to 
tuner via demod. I2C-mux may not work I think as there is no gate-style 
multiplexing so you probably need plain i2c adapter. There is few 
examples already on some demod drivers.


regards
Antti

--
http://palosaari.fi/


Re: [PATCH v3 1/5] dvb-frontends/dvb-pll: add i2c driver support

2018-03-27 Thread Antti Palosaari

On 03/26/2018 09:06 PM, tsk...@gmail.com wrote:

From: Akihiro Tsukada 

registers the module as an i2c driver,
but keeps dvb_pll_attach() untouched for compatibility.

Signed-off-by: Akihiro Tsukada 
---
  drivers/media/dvb-frontends/dvb-pll.c | 49 +++
  drivers/media/dvb-frontends/dvb-pll.h |  6 +
  2 files changed, 55 insertions(+)

diff --git a/drivers/media/dvb-frontends/dvb-pll.c 
b/drivers/media/dvb-frontends/dvb-pll.c
index 5553b89b804..614a5ea3b00 100644
--- a/drivers/media/dvb-frontends/dvb-pll.c
+++ b/drivers/media/dvb-frontends/dvb-pll.c
@@ -827,6 +827,55 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend 
*fe, int pll_addr,
  }
  EXPORT_SYMBOL(dvb_pll_attach);
  
+

+static int
+dvb_pll_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+   struct dvb_pll_config *cfg;
+   struct dvb_frontend *fe;
+   unsigned int desc_id;
+
+   cfg = client->dev.platform_data;
+   fe = cfg->fe;
+   i2c_set_clientdata(client, fe);
+   desc_id = cfg->desc_id;
+
+   if (!dvb_pll_attach(fe, client->addr, client->adapter, desc_id))
+   return -ENOMEM;
+
+   dev_info(&client->dev, "DVB Simple Tuner attached.\n");
+   return 0;
+}
+
+static int dvb_pll_remove(struct i2c_client *client)
+{
+   struct dvb_frontend *fe;
+
+   fe = i2c_get_clientdata(client);
+   dvb_pll_release(fe);
+   return 0;
+}
+
+
+static const struct i2c_device_id dvb_pll_id[] = {
+   {"dvb_pll", 0},
+   {}
+};
+
+
+MODULE_DEVICE_TABLE(i2c, dvb_pll_id);
+
+static struct i2c_driver dvb_pll_driver = {
+   .driver = {
+   .name = "dvb_pll",
+   },
+   .probe= dvb_pll_probe,
+   .remove   = dvb_pll_remove,
+   .id_table = dvb_pll_id,
+};
+
+module_i2c_driver(dvb_pll_driver);
+
  MODULE_DESCRIPTION("dvb pll library");
  MODULE_AUTHOR("Gerd Knorr");
  MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/dvb-pll.h 
b/drivers/media/dvb-frontends/dvb-pll.h
index ca885e71d2f..15bda0d0c15 100644
--- a/drivers/media/dvb-frontends/dvb-pll.h
+++ b/drivers/media/dvb-frontends/dvb-pll.h
@@ -30,6 +30,12 @@
  #define DVB_PLL_TDEE418
  #define DVB_PLL_THOMSON_DTT7520X   19
  
+struct dvb_pll_config {

+   struct dvb_frontend *fe;
+
+   unsigned int desc_id;
+};
+
  #if IS_REACHABLE(CONFIG_DVB_PLL)
  /**
   * Attach a dvb-pll to the supplied frontend structure.



Hello
Idea is correct, but I would use pll chip names for passing correct pll 
type for driver - that field is just for that.


Like that:
static const struct i2c_device_id dvb_pll_id[] = {
{"PLL-NAME1", 0},
{"PLL-NAME2", 1},
{"PLL-NAME3", 2},
{}
};

See si2157 for example.

regards
Antti


--
http://palosaari.fi/


Re: [PATCH v4] dvb-usb/friio, dvb-usb-v2/gl861: decompose friio and merge with gl861

2018-03-28 Thread Antti Palosaari



On 03/28/2018 03:37 PM, Akihiro TSUKADA wrote:

Hi,
thanks for the comment.


You should implement i2c adapter to demod driver and not add such glue
to that USB-bridge. I mean that "relayed" stuff, i2c communication to
tuner via demod. I2C-mux may not work I think as there is no gate-style
multiplexing so you probably need plain i2c adapter. There is few
examples already on some demod drivers.


I am afraid that the glue is actually necessary.

host - USB -> gl861 - I2C(1) -> tc90522 (addr:X)
   \- I2C(2) -> tua6034 (addr:Y)

To send an i2c read message to tua6034,
one has to issue two transactions:
  1. write via I2C(1) to addr:X, [ reg:0xfe, val: Y ]
  2. read via I2C(1) from addr:X, [ out_data0, out_data1, ]

The problem is that the transaction 1 is (somehow) implemented with
the different USB request than the other i2c transactions on I2C(1).
(this is confirmed by a packet capture on Windows box).

Although tc90522 already creats the i2c adapter for I2C(2),
tc90522 cannot know/control the USB implementation of I2C(1),
only the bridge driver can do this.


I simply cannot see why it cannot work. Just add i2c adapter and 
suitable logic there. Transaction on your example is simply and there is 
no problem to implement that kind of logic to demod i2c adapter.


If gl861 driver i2c adapter logic is broken it can be fixed easily too. 
It seems to support only i2c writes with len 1 and 2 bytes, but fixing 
it should be easy if you has some sniffs.




Antti

--
http://palosaari.fi/


Re: [PATCH v4 1/5] dvb-frontends/dvb-pll: add i2c driver support

2018-03-28 Thread Antti Palosaari

On 03/28/2018 08:00 PM, tsk...@gmail.com wrote:

From: Akihiro Tsukada 

registers the module as an i2c driver,
but keeps dvb_pll_attach() untouched for compatibility.

Signed-off-by: Akihiro Tsukada 
---
Changes since v3:
- use standard i2c_device_id instead of dvb_pll_config

  drivers/media/dvb-frontends/dvb-pll.c | 67 +++
  drivers/media/dvb-frontends/dvb-pll.h | 24 +
  2 files changed, 91 insertions(+)

diff --git a/drivers/media/dvb-frontends/dvb-pll.c 
b/drivers/media/dvb-frontends/dvb-pll.c
index 5553b89b804..e2a93aae04f 100644
--- a/drivers/media/dvb-frontends/dvb-pll.c
+++ b/drivers/media/dvb-frontends/dvb-pll.c
@@ -827,6 +827,73 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend 
*fe, int pll_addr,
  }
  EXPORT_SYMBOL(dvb_pll_attach);
  
+

+static int
+dvb_pll_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+   struct dvb_pll_config *cfg;
+   struct dvb_frontend *fe;
+   unsigned int desc_id;
+
+   cfg = client->dev.platform_data;
+   fe = cfg->fe;
+   i2c_set_clientdata(client, fe);
+   desc_id = (unsigned int) id->driver_data;
+
+   if (!dvb_pll_attach(fe, client->addr, client->adapter, desc_id))
+   return -ENOMEM;
+
+   dev_info(&client->dev, "DVB Simple Tuner attached.\n");


Print used pll chip name here


+   return 0;
+}
+
+static int dvb_pll_remove(struct i2c_client *client)
+{
+   struct dvb_frontend *fe;
+
+   fe = i2c_get_clientdata(client);
+   dvb_pll_release(fe);
+   return 0;
+}
+
+
+static const struct i2c_device_id dvb_pll_id[] = {
+   {DVB_PLL_THOMSON_DTT7579_NAME,DVB_PLL_THOMSON_DTT7579},
+   {DVB_PLL_THOMSON_DTT759X_NAME,DVB_PLL_THOMSON_DTT759X},
+   {DVB_PLL_LG_Z201_NAME,DVB_PLL_LG_Z201},
+   {DVB_PLL_UNKNOWN_1_NAME,  DVB_PLL_UNKNOWN_1},
+   {DVB_PLL_TUA6010XS_NAME,  DVB_PLL_TUA6010XS},
+   {DVB_PLL_ENV57H1XD5_NAME, DVB_PLL_ENV57H1XD5},
+   {DVB_PLL_TUA6034_NAME,DVB_PLL_TUA6034},
+   {DVB_PLL_TDA665X_NAME,DVB_PLL_TDA665X},
+   {DVB_PLL_TDED4_NAME,  DVB_PLL_TDED4},
+   {DVB_PLL_TDHU2_NAME,  DVB_PLL_TDHU2},
+   {DVB_PLL_SAMSUNG_TBMV_NAME,   DVB_PLL_SAMSUNG_TBMV},
+   {DVB_PLL_PHILIPS_SD1878_TDA8261_NAME, DVB_PLL_PHILIPS_SD1878_TDA8261},
+   {DVB_PLL_OPERA1_NAME, DVB_PLL_OPERA1},
+   {DVB_PLL_SAMSUNG_DTOS403IH102A_NAME,  DVB_PLL_SAMSUNG_DTOS403IH102A},
+   {DVB_PLL_SAMSUNG_TDTC9251DH0_NAME,DVB_PLL_SAMSUNG_TDTC9251DH0},
+   {DVB_PLL_SAMSUNG_TBDU18132_NAME,  DVB_PLL_SAMSUNG_TBDU18132},
+   {DVB_PLL_SAMSUNG_TBMU24112_NAME,  DVB_PLL_SAMSUNG_TBMU24112},
+   {DVB_PLL_TDEE4_NAME,  DVB_PLL_TDEE4},
+   {DVB_PLL_THOMSON_DTT7520X_NAME,   DVB_PLL_THOMSON_DTT7520X},
+   {}
+};
+
+
+MODULE_DEVICE_TABLE(i2c, dvb_pll_id);
+
+static struct i2c_driver dvb_pll_driver = {
+   .driver = {
+   .name = "dvb_pll",
+   },
+   .probe= dvb_pll_probe,
+   .remove   = dvb_pll_remove,
+   .id_table = dvb_pll_id,
+};
+
+module_i2c_driver(dvb_pll_driver);
+
  MODULE_DESCRIPTION("dvb pll library");
  MODULE_AUTHOR("Gerd Knorr");
  MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/dvb-pll.h 
b/drivers/media/dvb-frontends/dvb-pll.h
index ca885e71d2f..e96994bf668 100644
--- a/drivers/media/dvb-frontends/dvb-pll.h
+++ b/drivers/media/dvb-frontends/dvb-pll.h
@@ -30,6 +30,30 @@
  #define DVB_PLL_TDEE418
  #define DVB_PLL_THOMSON_DTT7520X   19
  
+#define DVB_PLL_THOMSON_DTT7579_NAME	"dtt7579"

+#define DVB_PLL_THOMSON_DTT759X_NAME"dtt759x"
+#define DVB_PLL_LG_Z201_NAME"z201"
+#define DVB_PLL_UNKNOWN_1_NAME  "unknown_1"
+#define DVB_PLL_TUA6010XS_NAME  "tua6010xs"
+#define DVB_PLL_ENV57H1XD5_NAME "env57h1xd5"
+#define DVB_PLL_TUA6034_NAME"tua6034"
+#define DVB_PLL_TDA665X_NAME"tda665x"
+#define DVB_PLL_TDED4_NAME  "tded4"
+#define DVB_PLL_TDHU2_NAME  "tdhu2"
+#define DVB_PLL_SAMSUNG_TBMV_NAME   "tbmv"
+#define DVB_PLL_PHILIPS_SD1878_TDA8261_NAME "sd1878_tda8261"
+#define DVB_PLL_OPERA1_NAME "opera1"
+#define DVB_PLL_SAMSUNG_DTOS403IH102A_NAME  "dtos403ih102a"
+#define DVB_PLL_SAMSUNG_TDTC9251DH0_NAME"tdtc9251dh0"
+#define DVB_PLL_SAMSUNG_TBDU18132_NAME  "tbdu18132"
+#define DVB_PLL_SAMSUNG_TBMU24112_NAME  "tbmu24112"
+#define DVB_PLL_TDEE4_NAME  "tdee4"
+#define DVB_PLL_THOMSON_DTT7520X_NAME   "dtt7520x"


Defining these names like that does not give any value. IMHO better to 
just add those chip names directly to chip id table.



+
+struct dvb_pll_config {
+   struct dvb_frontend *fe;
+};
+
  #if IS_REACHABLE(CONFIG_DVB_PLL)
  /**
   * Attach a dvb-pll to the

Re: [PATCH v4] dvb-usb/friio, dvb-usb-v2/gl861: decompose friio and merge with gl861

2018-03-30 Thread Antti Palosaari



On 03/30/2018 04:21 PM, Akihiro TSUKADA wrote:

I simply cannot see why it cannot work. Just add i2c adapter and
suitable logic there. Transaction on your example is simply and there is
no problem to implement that kind of logic to demod i2c adapter.


I might be totally wrong, but...

i2c transactions to a tuner must use:
1. usb_control_msg(request:3) for the first half (write) of reads
2. usb_control_msg(request:1) for the other writes
3. usb_control_msg(request:2) for (all) reads

How can the demod driver control the 'request' argument of USB messages
that are sent to its parent (not to the demod itself),
when the bridge of tc90522 cannot be limited to gl861 (or even to USB) ?


I don't understand those control message parts and it is bit too hard to 
read i2c adapter implementation to get understanding. Could you offer 
simple 2 sniff examples, register write to demod and register write to 
tuner.


Anyhow, demod i2c adapter gets request from tuner and then does some 
demod specific i2c algo stuff and then pass proper request to usb-bridge 
i2c adapter.


IIR it was somehing like

write_tuner_reg(0xaa, 0xbb);
 ==> demod i2c algo:
 * write_demod_reg(0xfe, 0x60) // set tuner i2c addr + start i2c write
 * write_demod_reg(0xaa, 0xbb)

so those command now goes to i2c-bridge i2c algo which uses gl861 i2c algo


regards
Antti

--
http://palosaari.fi/


Re: Regression: DVBSky S960 USB tuner doesn't work in 4.10 or newer

2018-04-18 Thread Antti Palosaari


On 04/18/2018 07:49 AM, Olli Salonen wrote:

Thank you for your response Peter!

Indeed, it seems strange. dvbsky.c driver seems to use mutex_lock in
very much the same way as many other drivers. I've now confirmed that
I can get a 4.10 kernel with working DVBSky S960 by reverting the
following 4 patches:

549bdd3 Revert "locking/mutex: Add lock handoff to avoid starvation"
3210f31 Revert "locking/mutex: Restructure wait loop"
418a170 Revert "locking/mutex: Simplify some ww_mutex code in
__mutex_lock_common()"
0b1fb8f Revert "locking/mutex: Enable optimistic spinning of woken waiter"
c470abd Linux 4.10


These kind of issues tend to be timing issues very often. Just add some 
sleeps to i2c adapter algo / usb control messages and test.


regards
Antti




--
http://palosaari.fi/


[PATCH] msi2500: assign SPI bus number dynamically

2019-08-16 Thread Antti Palosaari
SPI bus number must be assigned dynamically for each device, otherwise it
will crash when multiple devices are plugged to system.

Cc: sta...@vger.kernel.org
Reported-and-tested-by: syzbot+c60ddb60b685777d9...@syzkaller.appspotmail.com
Signed-off-by: Antti Palosaari 
---
 drivers/media/usb/msi2500/msi2500.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/usb/msi2500/msi2500.c 
b/drivers/media/usb/msi2500/msi2500.c
index 65be6f140fe8..1c60dfb647e5 100644
--- a/drivers/media/usb/msi2500/msi2500.c
+++ b/drivers/media/usb/msi2500/msi2500.c
@@ -1230,7 +1230,7 @@ static int msi2500_probe(struct usb_interface *intf,
}
 
dev->master = master;
-   master->bus_num = 0;
+   master->bus_num = -1;
master->num_chipselect = 1;
master->transfer_one_message = msi2500_transfer_one_message;
spi_master_set_devdata(master, dev);
-- 
2.21.0



Re: [PATCH] dvb-usb-v2/gl861: fix wrong memcpy

2019-08-21 Thread Antti Palosaari



On 8/17/19 4:22 PM, Akihiro TSUKADA wrote:

Could you please test the patch and check if the return results are
now consistent and that it won't break anything?


I have tested the patch and it worked without problems.

Testd-by: Akihiro Tsukada 

I could not noticed the bug because
the device was registered without any error messages,
and it seemed to work even with the bug.
(Though actually I was wrong and missed that
  the device does not work after reboot or re-plugging).

After applying this patch, I have confirmed that the device
now works after reboot/re-plugging without any problems.

note:
The patched func: gl861_i2c_read_ex was used in device's early init,
called from d->props->power_ctrl (from dvb_usbv2_init).
But dvb_usbv2_init does not check the return value of it,
and if the device had been initialized previously
it can work even with the interrupted init process in power_ctrl().



I suspect all whole friio_reset() function is not needed as it has 
worked even I/O has been broken.


Also tuner I2C adapter is implemented wrong (I think I mentioned that 
earlier). As tuner sits behind demod I2C-adapter/gate that whole logic 
should be on demod driver.


regards
Antti



--
http://palosaari.fi/


Re: [PATCH] dvb-usb-v2/gl861: fix wrong memcpy

2019-08-21 Thread Antti Palosaari




On 8/22/19 5:00 AM, Akihiro TSUKADA wrote:

Hi,


I suspect all whole friio_reset() function is not needed as it has
worked even I/O has been broken.


It worked because the old driver
(that I rmmod'ed before installing the testing driver)
properly init'ed the device.
If I re-plug it (or reboot), it does not work.
So it is needed.


Also tuner I2C adapter is implemented wrong (I think I mentioned that
earlier). As tuner sits behind demod I2C-adapter/gate that whole logic
should be on demod driver.


But according to USB packet capture logs of the windows version,
it makes eccentric use of USB messages ('bRequest' field),
that (I believe) necessitates the current implementation,
as I mentioned in the past thread.


That is because it has 2 i2c write methods - one using only 
usb_control_msg() header and other header + payload data. When 1 or 2 
byte long i2c message is send it is wise to use only "header" to reduce 
IO as it could carry needed data.


Anyhow, I will send patch soon which adds needed logic to i2c adapter. 
Then it is easier to understand.


regards
Antti


--
http://palosaari.fi/


[PATCH] gl861: re-implement i2c adapter logic

2019-08-21 Thread Antti Palosaari
Device I2C adapter is capable of writing and reading large messages.
For I2C writes there is 2 methods: simple for max 2 byte messages and
usb_control_msg() with payload data for larger I2C messages. Add I2C
adapter logic which selects suitable method according to message size.

Cc: Akihiro TSUKADA 
Signed-off-by: Antti Palosaari 
---
 drivers/media/usb/dvb-usb-v2/gl861.c | 206 +++
 1 file changed, 149 insertions(+), 57 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/gl861.c 
b/drivers/media/usb/dvb-usb-v2/gl861.c
index b784d9da1a82..b8358cd2e4b7 100644
--- a/drivers/media/usb/dvb-usb-v2/gl861.c
+++ b/drivers/media/usb/dvb-usb-v2/gl861.c
@@ -14,6 +14,144 @@
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
+struct gl861 {
+   /* USB control message buffer */
+   u8 buf[16];
+
+   struct i2c_adapter *demod_sub_i2c;
+   struct i2c_client  *i2c_client_demod;
+   struct i2c_client  *i2c_client_tuner;
+   struct i2c_adapter tuner_adap;
+};
+
+#define CMD_WRITE_SHORT 0x01
+#define CMD_READ0x02
+#define CMD_WRITE   0x03
+
+static int gl861_ctrl_msg(struct dvb_usb_device *d, u8 request, u16 value,
+ u16 index, void *data, u16 size)
+{
+   struct gl861 *ctx = d_to_priv(d);
+   struct usb_interface *intf = d->intf;
+   int ret;
+   unsigned int pipe;
+   u8 requesttype;
+
+   mutex_lock(&d->usb_mutex);
+
+   switch (request) {
+   case CMD_WRITE_SHORT:
+   pipe = usb_sndctrlpipe(d->udev, 0);
+   requesttype = USB_TYPE_VENDOR | USB_DIR_OUT;
+   break;
+   case CMD_READ:
+   pipe = usb_rcvctrlpipe(d->udev, 0);
+   requesttype = USB_TYPE_VENDOR | USB_DIR_IN;
+   break;
+   case CMD_WRITE:
+   pipe = usb_sndctrlpipe(d->udev, 0);
+   requesttype = USB_TYPE_VENDOR | USB_DIR_OUT;
+   memcpy(ctx->buf, data, size);
+   break;
+   default:
+   ret = -EINVAL;
+   goto err_mutex_unlock;
+   }
+
+   ret = usb_control_msg(d->udev, pipe, request, requesttype, value,
+ index, ctx->buf, size, 200);
+   dev_dbg(&intf->dev, "%d | %02x %02x %*ph %*ph %*ph %s %*ph\n",
+   ret, requesttype, request, 2, &value, 2, &index, 2, &size,
+   (requesttype & USB_DIR_IN) ? "<<<" : ">>>", size, ctx->buf);
+   if (ret < 0)
+   goto err_mutex_unlock;
+
+   if (request == CMD_READ)
+   memcpy(data, ctx->buf, size);
+
+   usleep_range(1000, 2000); /* Avoid I2C errors */
+
+   mutex_unlock(&d->usb_mutex);
+
+   return 0;
+
+err_mutex_unlock:
+   mutex_unlock(&d->usb_mutex);
+   dev_dbg(&intf->dev, "failed %d\n", ret);
+   return ret;
+}
+
+static int gl861_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg 
msg[],
+int num)
+{
+   struct dvb_usb_device *d = i2c_get_adapdata(adap);
+   struct usb_interface *intf = d->intf;
+   struct gl861 *ctx = d_to_priv(d);
+   int ret;
+   u8 request, *data;
+   u16 value, index, size;
+
+   /* XXX: I2C adapter maximum data lengths are not tested */
+   if (num == 1 && !(msg[0].flags & I2C_M_RD)) {
+   /* I2C write */
+   if (msg[0].len < 2 || msg[0].len > sizeof(ctx->buf)) {
+   ret = -EOPNOTSUPP;
+   goto err;
+   }
+
+   value = (msg[0].addr << 1) << 8;
+   index = msg[0].buf[0];
+
+   if (msg[0].len == 2) {
+   request = CMD_WRITE_SHORT;
+   value |= msg[0].buf[1];
+   size = 0;
+   data = NULL;
+   } else {
+   request = CMD_WRITE;
+   size = msg[0].len - 1;
+   data = &msg[0].buf[1];
+   }
+
+   ret = gl861_ctrl_msg(d, request, value, index, data, size);
+   } else if (num == 2 && !(msg[0].flags & I2C_M_RD) &&
+  (msg[1].flags & I2C_M_RD)) {
+   /* I2C write + read */
+   if (msg[0].len > 1 || msg[1].len > sizeof(ctx->buf)) {
+   ret = -EOPNOTSUPP;
+   goto err;
+   }
+
+   value = (msg[0].addr << 1) << 8;
+   index = msg[0].buf[0];
+   request = CMD_READ;
+
+   ret = gl861_ctrl_msg(d, request, value, index,
+msg[1].buf, msg[1].len);
+   } else {
+   /* Unsupported I2C message */
+   dev_dbg(&intf->dev, "

Re: [PATCH] gl861: re-implement i2c adapter logic

2019-08-21 Thread Antti Palosaari

On 8/22/19 8:34 AM, Antti Palosaari wrote:

Device I2C adapter is capable of writing and reading large messages.
For I2C writes there is 2 methods: simple for max 2 byte messages and
usb_control_msg() with payload data for larger I2C messages. Add I2C
adapter logic which selects suitable method according to message size.


Here is debug log I tested multibyte i2c writes using zl10353 demod. All 
returned bytes are not same, but it due to write only register bits I think.


dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 50 00 01 00 <<< 03
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 51 00 01 00 <<< 44
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 52 00 01 00 <<< 46
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 53 00 01 00 <<< 15
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 54 00 01 00 <<< 0f
dvb_usb_gl861 1-13:1.0: 5 | 40 03 00 1e 50 00 05 00 >>> 0c 77 aa bb cc
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 50 00 01 00 <<< 0c
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 51 00 01 00 <<< 77
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 52 00 01 00 <<< aa
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 53 00 01 00 <<< 3b
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 54 00 01 00 <<< 4c


Now if you look your tuner i2c implementation...

buf[0] = msg->addr << 1;
memcpy(buf + 1, msg->buf, msg->len);
ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0), 
GL861_REQ_I2C_RAW, GL861_WRITE,

priv->i2c_client_demod->addr << (8 + 1), 0xFE, buf, msg->len + 1, 2000);

...it translates same.

It writes i2c message to demod which;
byte0 0xfe, demod register/cmd/mailbox for tuner i2c bus
byte1 tuner i2c address
byte2-n tuner i2c data


Antti


--
http://palosaari.fi/


Re: [PATCH] gl861: re-implement i2c adapter logic

2019-08-23 Thread Antti Palosaari




On 8/23/19 8:28 PM, Akihiro TSUKADA wrote:

Hi, thanks for the example patch.


Here is debug log I tested multibyte i2c writes using zl10353 demod. All
returned bytes are not same, but it due to write only register bits I
think.

dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 50 00 01 00 <<< 03
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 51 00 01 00 <<< 44
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 52 00 01 00 <<< 46
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 53 00 01 00 <<< 15
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 54 00 01 00 <<< 0f
dvb_usb_gl861 1-13:1.0: 5 | 40 03 00 1e 50 00 05 00 >>> 0c 77 aa bb cc
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 50 00 01 00 <<< 0c
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 51 00 01 00 <<< 77
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 52 00 01 00 <<< aa
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 53 00 01 00 <<< 3b
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 54 00 01 00 <<< 4c


Now if you look your tuner i2c implementation...

buf[0] = msg->addr << 1;
memcpy(buf + 1, msg->buf, msg->len);
ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
GL861_REQ_I2C_RAW, GL861_WRITE,
priv->i2c_client_demod->addr << (8 + 1), 0xFE, buf, msg->len + 1, 2000);

...it translates same.


Log of an 1-byte read from tuner in Friio looks like the following:
(re-formatted from my past post: https://patchwork.linuxtv.org/comment/92946/ )

40 03 00 30 fe 00 01 00 >>> c1  # command a read from the tuner@0x60 (hence 
0xc1)
c0 02 00 30 00 01 01 00 <<< 7c  # get the result (return value: 0x7c)

so,
- One read is composed of *two* USB messages.
   (note that friio_tuner_i2c_xfer() does NOT combine the two I2C messages
of one read, and issues separate USB message for each,
contrary to gl861_i2c_master_xfer()).
- The second USB message uses CMD_READ but
   'index'(demod register addr) value exceeds 8bit (0x0100),
   thus cannot use the normal gl861_i2c_master_xfer() as is.

It looks to me different.


It looks just read command done with 2 separate I2C messages (look I2C 
specs REPEATED START vs. STOP START).

OK, I will add support for bulk I2C READs for adapter too, no problem.


Antti

--
http://palosaari.fi/


[PATCH v2] gl861: re-implement I2C adapter logic

2019-08-23 Thread Antti Palosaari
Device I2C adapter is capable of writing and reading large messages.
For I2C writes there is 2 methods: simple for max 2 byte messages and
usb_control_msg() with payload data for larger I2C messages. Add I2C
adapter logic which selects suitable method according to message size.
Add also support for plain I2C read.

Cc: Akihiro TSUKADA 
Signed-off-by: Antti Palosaari 
---
 drivers/media/usb/dvb-usb-v2/gl861.c | 216 ---
 1 file changed, 159 insertions(+), 57 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/gl861.c 
b/drivers/media/usb/dvb-usb-v2/gl861.c
index b784d9da1a82..ead6268af7ad 100644
--- a/drivers/media/usb/dvb-usb-v2/gl861.c
+++ b/drivers/media/usb/dvb-usb-v2/gl861.c
@@ -14,6 +14,154 @@
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
+struct gl861 {
+   /* USB control message buffer */
+   u8 buf[16];
+
+   struct i2c_adapter *demod_sub_i2c;
+   struct i2c_client  *i2c_client_demod;
+   struct i2c_client  *i2c_client_tuner;
+   struct i2c_adapter tuner_adap;
+};
+
+#define CMD_WRITE_SHORT 0x01
+#define CMD_READ0x02
+#define CMD_WRITE   0x03
+
+static int gl861_ctrl_msg(struct dvb_usb_device *d, u8 request, u16 value,
+ u16 index, void *data, u16 size)
+{
+   struct gl861 *ctx = d_to_priv(d);
+   struct usb_interface *intf = d->intf;
+   int ret;
+   unsigned int pipe;
+   u8 requesttype;
+
+   mutex_lock(&d->usb_mutex);
+
+   switch (request) {
+   case CMD_WRITE:
+   memcpy(ctx->buf, data, size);
+   /* Fall through */
+   case CMD_WRITE_SHORT:
+   pipe = usb_sndctrlpipe(d->udev, 0);
+   requesttype = USB_TYPE_VENDOR | USB_DIR_OUT;
+   break;
+   case CMD_READ:
+   pipe = usb_rcvctrlpipe(d->udev, 0);
+   requesttype = USB_TYPE_VENDOR | USB_DIR_IN;
+   break;
+   default:
+   ret = -EINVAL;
+   goto err_mutex_unlock;
+   }
+
+   ret = usb_control_msg(d->udev, pipe, request, requesttype, value,
+ index, ctx->buf, size, 200);
+   dev_dbg(&intf->dev, "%d | %02x %02x %*ph %*ph %*ph %s %*ph\n",
+   ret, requesttype, request, 2, &value, 2, &index, 2, &size,
+   (requesttype & USB_DIR_IN) ? "<<<" : ">>>", size, ctx->buf);
+   if (ret < 0)
+   goto err_mutex_unlock;
+
+   if (request == CMD_READ)
+   memcpy(data, ctx->buf, size);
+
+   usleep_range(1000, 2000); /* Avoid I2C errors */
+
+   mutex_unlock(&d->usb_mutex);
+
+   return 0;
+
+err_mutex_unlock:
+   mutex_unlock(&d->usb_mutex);
+   dev_dbg(&intf->dev, "failed %d\n", ret);
+   return ret;
+}
+
+static int gl861_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg 
msg[],
+int num)
+{
+   struct dvb_usb_device *d = i2c_get_adapdata(adap);
+   struct usb_interface *intf = d->intf;
+   struct gl861 *ctx = d_to_priv(d);
+   int ret;
+   u8 request, *data;
+   u16 value, index, size;
+
+   /* XXX: I2C adapter maximum data lengths are not tested */
+   if (num == 1 && !(msg[0].flags & I2C_M_RD)) {
+   /* I2C write */
+   if (msg[0].len < 2 || msg[0].len > sizeof(ctx->buf)) {
+   ret = -EOPNOTSUPP;
+   goto err;
+   }
+
+   value = (msg[0].addr << 1) << 8;
+   index = msg[0].buf[0];
+
+   if (msg[0].len == 2) {
+   request = CMD_WRITE_SHORT;
+   value |= msg[0].buf[1];
+   size = 0;
+   data = NULL;
+   } else {
+   request = CMD_WRITE;
+   size = msg[0].len - 1;
+   data = &msg[0].buf[1];
+   }
+
+   ret = gl861_ctrl_msg(d, request, value, index, data, size);
+   } else if (num == 2 && !(msg[0].flags & I2C_M_RD) &&
+  (msg[1].flags & I2C_M_RD)) {
+   /* I2C write + read */
+   if (msg[0].len > 1 || msg[1].len > sizeof(ctx->buf)) {
+   ret = -EOPNOTSUPP;
+   goto err;
+   }
+
+   value = (msg[0].addr << 1) << 8;
+   index = msg[0].buf[0];
+   request = CMD_READ;
+
+   ret = gl861_ctrl_msg(d, request, value, index,
+msg[1].buf, msg[1].len);
+   } else if (num == 1 && (msg[0].flags & I2C_M_RD)) {
+   /* I2C read */
+   if (msg[0].len > sizeof(ctx->buf)) {
+   ret =

Re: [PATCH] gl861: re-implement i2c adapter logic

2019-08-23 Thread Antti Palosaari




On 8/24/19 2:33 AM, Antti Palosaari wrote:



On 8/23/19 8:28 PM, Akihiro TSUKADA wrote:

Hi, thanks for the example patch.


Here is debug log I tested multibyte i2c writes using zl10353 demod. All
returned bytes are not same, but it due to write only register bits I
think.

dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 50 00 01 00 <<< 03
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 51 00 01 00 <<< 44
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 52 00 01 00 <<< 46
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 53 00 01 00 <<< 15
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 54 00 01 00 <<< 0f
dvb_usb_gl861 1-13:1.0: 5 | 40 03 00 1e 50 00 05 00 >>> 0c 77 aa bb cc
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 50 00 01 00 <<< 0c
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 51 00 01 00 <<< 77
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 52 00 01 00 <<< aa
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 53 00 01 00 <<< 3b
dvb_usb_gl861 1-13:1.0: 1 | c0 02 00 1e 54 00 01 00 <<< 4c


Now if you look your tuner i2c implementation...

buf[0] = msg->addr << 1;
memcpy(buf + 1, msg->buf, msg->len);
ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
GL861_REQ_I2C_RAW, GL861_WRITE,
priv->i2c_client_demod->addr << (8 + 1), 0xFE, buf, msg->len + 1, 2000);

...it translates same.


Log of an 1-byte read from tuner in Friio looks like the following:
(re-formatted from my past post: 
https://patchwork.linuxtv.org/comment/92946/ )


40 03 00 30 fe 00 01 00 >>> c1  # command a read from the tuner@0x60 
(hence 0xc1)

c0 02 00 30 00 01 01 00 <<< 7c  # get the result (return value: 0x7c)

so,
- One read is composed of *two* USB messages.
   (note that friio_tuner_i2c_xfer() does NOT combine the two I2C 
messages

    of one read, and issues separate USB message for each,
    contrary to gl861_i2c_master_xfer()).
- The second USB message uses CMD_READ but
   'index'(demod register addr) value exceeds 8bit (0x0100),
   thus cannot use the normal gl861_i2c_master_xfer() as is.

It looks to me different.


It looks just read command done with 2 separate I2C messages (look I2C 
specs REPEATED START vs. STOP START).

OK, I will add support for bulk I2C READs for adapter too, no problem.


See updated patch on ml.

Tested it quickly against qt1010 tuner and results are expected:
dvb_usb_gl861 1-14:1.0: 0 | 40 01 1a 1e 62 00 00 00 >>>
dvb_usb_gl861 1-14:1.0: 1 | c0 02 00 c4 29 00 01 00 <<< 39
dvb_usb_gl861 1-14:1.0: 0 | 40 03 00 c4 29 00 00 00 >>>
dvb_usb_gl861 1-14:1.0: 1 | c0 02 00 c4 00 01 01 00 <<< 39
dvb_usb_gl861 1-14:1.0: 1 | c0 02 00 c4 00 01 01 00 <<< 39
dvb_usb_gl861 1-14:1.0: 1 | c0 02 00 c4 00 01 01 00 <<< 39
dvb_usb_gl861 1-14:1.0: 1 | c0 02 00 c4 00 01 01 00 <<< 39
dvb_usb_gl861 1-14:1.0: 0 | 40 01 0a 1e 62 00 00 00 >>>

Register 29 is likely chip id and its value is always 39. So it first 
makes normal write+write to that register which sets and leaves chip 
registers address counter to that. After that each plain I2C read 
request gives 39 which is correct content for that register.


Antti


--
http://palosaari.fi/


Re: Logilink VG0022A firmware/si2157 probe

2019-10-17 Thread Antti Palosaari

Hello,

On 10/17/19 12:08 PM, Sean Young wrote:

Hi Antti,

I have a Logilink VG0022A device which is an af9035.c type device (with
ITE 9xxx frontned). The probe of the si2146 tuner fails and returns 0xffs.

Now I would like to work on fixing this. Mauro suggested the firmware might
be incorrect. Any tips on extracting the firmware? I can try and dump
usb traffic from Windows and see what firmware is being used there. How did
you extract the firmware?

Any other suggestions for this device? You might be able to save me a lot
of time since you have experience with these types of devices, I do not.


Extracting firmware is done almost always by following steps:
1) take sniffs from the some bus (usb/i2c)
2) identify firmware download section, detect it starting point and 
ending point ~few first and last bytes

3) find that firmware binary located inside of binary driver
 * grep, hexeditor, etc
 * example LANG=C grep -obUaP "\x08\x05\x00" driver.sys
4) use dd command to copy firmware blob from binary driver to separate 
file (you need to know firmware location and length inside binary)



It is also possible to dump firmware to file from bus sniffs too, but it 
requires writing some simple script. Dumping it from the binary driver 
is usually still most easiest way.


At some point I downloaded bunch of drivers to find out multiple 
firmware versions for si2168 and made simple script to ease things. 
Script is attached.



After all, I suspect root of issue may be still be buggy i2c...


regards
Antti

--
http://palosaari.fi/
#!/usr/bin/env python
# Silicon Labs Si2168 firmware extractor.
# Copyright (C) 2015 Antti Palosaari 
# Usage: si2168_extract_firmware.py binary_driver_name.sys

import sys
import struct
import md5

fread = file(sys.argv[1], 'rb')
binary = fread.read()
offset = 0

# Known firmware md5 and its version
fw_ver_tab = {
'02c9b1e751f362621c649ea831410b61' : '4.0.7',
'b2670d8ae5e3369fc71edbb98cdd8f6e' : '4.0.11',
'8dfc2483d90282bbb05817fbbc282376' : '4.0.19',
'c8e089c351e9834060e962356f8697b8' : '4.0.25',
}

while True:
# Match 17-byte firmware header
# 04 01 00 00 00 00 9a 41 05 1b af 33 02 1b 3e 7d 2a | A20 (not supported)
# 08 05 00 xx xx xx xx xx xx 00 00 00 00 00 00 00 00 | B40
offset = binary.find('\x08\x05\x00', offset)
if offset == -1:
print "Done"
break

if (binary[offset + 9:offset + 17] != '\x00\x00\x00\x00\x00\x00\x00\x00'):
offset = offset + 1
continue

print "Possible 17-byte Si2168-B40 firmware header found at 0x%x" % (offset)

fw_filename = 'dvb-demod-si2168-b40-01.fw_' + str(offset)
fw_write = open(fw_filename, 'wb')
fw_md5 = md5.new()

while True:
fields = struct.unpack("B", binary[offset])
fw_data_len = fields[0]
# Firmware chunk first byte tells bytes to upload - 16 is max
if fw_data_len == 0 or fw_data_len > 16:
break

# Check remaining (unused) bytes on firmware 17-byte chunk are all zero
data_valid = True
for x in range(offset + fw_data_len + 1, offset + 17):
if (binary[x] != '\x00'):
data_valid = False
break

if data_valid == False:
break

# Firmware chunk validated, write it to file
fw_write.write(binary[offset + 0:offset + 17])
fw_md5.update(binary[offset + 0:offset + 17])
offset = offset + 17

fw_write.close()

if fw_md5.hexdigest() in fw_ver_tab:
fw_ver = fw_ver_tab[fw_md5.hexdigest()]
else:
fw_ver = ''

print "Firmware md5 '%s'" % (fw_md5.hexdigest())
print "Firmware version '%s'" % (fw_ver)
print "Firmware stored to file '%s'" % (fw_filename)

offset = offset + 1

fread.close()



Re: Logilink VG0022A firmware/si2157 probe

2019-10-17 Thread Antti Palosaari

On 10/17/19 4:46 PM, JP wrote:

Hi there,

On 10/17/19 2:15 PM, Antti Palosaari wrote:

Hello,

On 10/17/19 12:08 PM, Sean Young wrote:

Hi Antti,

I have a Logilink VG0022A device which is an af9035.c type device (with
ITE 9xxx frontned). The probe of the si2146 tuner fails and returns 
0xffs.


Now I would like to work on fixing this. Mauro suggested the firmware 
might

be incorrect. Any tips on extracting the firmware? I can try and dump
usb traffic from Windows and see what firmware is being used there. 
How did

you extract the firmware?
If the receiver has onboard firmware, isn't that the right one? Then the 
windows

driver has no need to load one. Or am I missing the point here?


Actually I am not even 100% sure what are used chips of that device, but 
I expect those are:

usb-interface: IT9303, needs firmware, cannot be loaded from the eeprom IIRC
demodulator: Si2168 (revision B or C?), chip has rom that contains 
firmware, but usually it is replaced newer by downloading
tuner: Si2157 or same family, similar firmware solution than Si2168. 
Si2157 I originally used didn't uploaded firmware update at all, later 
there was added more and more Silabs tuner versions and firmware 
downloading.


Si2168B could be started (and it worked at the time I tested) with 
default rom firmware by using that kind of stub firmware:


$ hexdump -C dvb-demod-si2168-b40-01.fw
  05 00 00 00 00 00 00 00   ||
0008

Not sure if that works any other than just Si2168B.




Any other suggestions for this device? You might be able to save me a 
lot

of time since you have experience with these types of devices, I do not.


Extracting firmware is done almost always by following steps:
1) take sniffs from the some bus (usb/i2c)
2) identify firmware download section, detect it starting point and 
ending point ~few first and last bytes

3) find that firmware binary located inside of binary driver
 * grep, hexeditor, etc
 * example LANG=C grep -obUaP "\x08\x05\x00" driver.sys
4) use dd command to copy firmware blob from binary driver to separate 
file (you need to know firmware location and length inside binary)



It is also possible to dump firmware to file from bus sniffs too, but 
it requires writing some simple script. Dumping it from the binary 
driver is usually still most easiest way.


At some point I downloaded bunch of drivers to find out multiple 
firmware versions for si2168 and made simple script to ease things. 
Script is attached.



After all, I suspect root of issue may be still be buggy i2c...

Me too.


Jan Pieter.


It could be interesting to see from the sniffs what kind of firmwares 
windows driver downloads to different chips AND if i2c communication is 
working properly.


regards
Antti

--
http://palosaari.fi/


Re: [PATCH 1/3] rtl2832: add support for slave ts pid filter

2015-12-20 Thread Antti Palosaari

Patch looks acceptable, but it is broken in a mean it does not apply :(

$ wget -O - https://patchwork.linuxtv.org/patch/32030/mbox/ | git am -3 -s
--2015-12-21 04:40:46--  https://patchwork.linuxtv.org/patch/32030/mbox/
Resolving patchwork.linuxtv.org (patchwork.linuxtv.org)... 130.149.80.248
Connecting to patchwork.linuxtv.org 
(patchwork.linuxtv.org)|130.149.80.248|:443... connected.

HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/plain]
Saving to: ‘STDOUT’

-   [ <=> 


  ]   2.73K  --.-KB/s   in 0s

2015-12-21 04:40:46 (60.4 MB/s) - written to stdout [2796]

Applying: rtl2832: add support for slave ts pid filter
fatal: corrupt patch at line 39
Repository lacks necessary blobs to fall back on 3-way merge.
Cannot fall back to three-way merge.
Patch failed at 0001 rtl2832: add support for slave ts pid filter
The copy of the patch that failed is found in:
   /home/crope/linuxtv/code/media_tree/.git/rebase-apply/patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
[crope@localhost media_tree]$ patch -p1 < .git/rebase-apply/patch
patching file drivers/media/dvb-frontends/rtl2832.c
patch:  malformed patch at line 39: @@ -1178,14 +1185,22 @@ static 
int rtl2832_pid_filter(struct dvb_frontend *fe, u8 index, u16 pid,


[crope@localhost media_tree]$ git am --abort
[crope@localhost media_tree]$ git am ~/\[PATCH\ 1_3\]\ rtl2832\:\ add\ 
support\ for\ slave\ ts\ pid\ filter.eml

Applying: rtl2832: add support for slave ts pid filter
fatal: corrupt patch at line 39
Patch failed at 0001 rtl2832: add support for slave ts pid filter
The copy of the patch that failed is found in:
   /home/crope/linuxtv/code/media_tree/.git/rebase-apply/patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
[crope@localhost media_tree]$ git am --abort

Antti

On 11/29/2015 04:10 AM, Benjamin Larsson wrote:

Signed-off-by: Benjamin Larsson 
---
  drivers/media/dvb-frontends/rtl2832.c  | 21 ++---
  drivers/media/dvb-frontends/rtl2832_priv.h |  1 +
  2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/media/dvb-frontends/rtl2832.c 
b/drivers/media/dvb-frontends/rtl2832.c
index 78b87b2..e054079 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -407,6 +407,7 @@ static int rtl2832_init(struct dvb_frontend *fe)
/* start statistics polling */
schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000));
dev->sleeping = false;
+   dev->slave_ts = false;

return 0;
  err:
@@ -1122,6 +1123,8 @@ static int rtl2832_enable_slave_ts(struct i2c_client 
*client)
if (ret)
goto err;

+   dev->slave_ts = true;
+
return 0;
  err:
dev_dbg(&client->dev, "failed=%d\n", ret);
@@ -1143,7 +1146,11 @@ static int rtl2832_pid_filter_ctrl(struct dvb_frontend 
*fe, int onoff)
else
u8tmp = 0x00;

-   ret = rtl2832_update_bits(client, 0x061, 0xc0, u8tmp);
+   if (dev->slave_ts)
+   ret = rtl2832_update_bits(client, 0x021, 0xc0, u8tmp);
+   else
+   ret = rtl2832_update_bits(client, 0x061, 0xc0, u8tmp);
if (ret)
goto err;

@@ -1178,14 +1185,22 @@ static int rtl2832_pid_filter(struct dvb_frontend *fe, 
u8 index, u16 pid,
buf[1] = (dev->filters >>  8) & 0xff;
buf[2] = (dev->filters >> 16) & 0xff;
buf[3] = (dev->filters >> 24) & 0xff;
-   ret = rtl2832_bulk_write(client, 0x062, buf, 4);
+
+   if (dev->slave_ts)
+   ret = rtl2832_bulk_write(client, 0x022, buf, 4);
+   else
+   ret = rtl2832_bulk_write(client, 0x062, buf, 4);
if (ret)
goto err;

/* add PID */
buf[0] = (pid >> 8) & 0xff;
buf[1] = (pid >> 0) & 0xff;
-   ret = rtl2832_bulk_write(client, 0x066 + 2 * index, buf, 2);
+
+   if (dev->slave_ts)
+   ret = rtl2832_bulk_write(client, 0x026 + 2 * index, buf, 2);
+   else
+   ret = rtl2832_bulk_write(client, 0x066 + 2 * index, buf, 2);
if (ret)
goto err;

diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h 
b/drivers/media/dvb-frontends/rtl2832_priv.h
index 5dcd3a4..efc230f 100644
--- a/drivers/media/dvb-frontends/rtl2832_priv.h
+++ b/drivers/media/dvb-frontends/rtl2832_priv.h
@@ -46,6 +46,7 @@ struct rtl2832_dev {
bool sleeping;
struct delayed_work i2c_gate_work;
unsigned long filters; /* PID filter */
+   bool slave_ts;
  };

  struct rtl2832_reg_entry {



--
http://palosaari.fi/
--
To unsubscribe from this list: send the line "unsubscribe linu

Re: [PATCH 2/3] mn88472: add work around for failing firmware loading

2015-12-20 Thread Antti Palosaari

Hello
I am not sure if problem is I2C adapter/bus or that demodulator I2C 
slave. If it is demod, then that workaround is correct place, but if it 
is not, then that is wrong and I2C adapter repeating logic should be used.


I did some testing again... Loading mn88472 firmware 1000 times, it failed:
61 times RC polling disabled
68 times RC polling enabled
83 times RC polling enabled, but repeated failed message due to that patch

I don't want apply that patch until I find some time myself to examine 
that problem - or someone else does some study to point out whats wrong. 
There is many things to test in order to get better understanding.


regards
Antti

On 11/29/2015 04:10 AM, Benjamin Larsson wrote:

Sometimes the firmware fails to load because of an i2c error.
Work around that by adding retry logic. This kind of logic
also exist in the binary driver and failures have been observed
there also. Thus this seems to be a property of the hardware
and a fix like this is needed.

Signed-off-by: Benjamin Larsson 
---
  drivers/staging/media/mn88472/mn88472.c | 15 ++-
  1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/media/mn88472/mn88472.c 
b/drivers/staging/media/mn88472/mn88472.c
index cf2e96b..80c5807 100644
--- a/drivers/staging/media/mn88472/mn88472.c
+++ b/drivers/staging/media/mn88472/mn88472.c
@@ -282,7 +282,7 @@ static int mn88472_init(struct dvb_frontend *fe)
int ret, len, remaining;
const struct firmware *fw = NULL;
u8 *fw_file = MN88472_FIRMWARE;
-   unsigned int tmp;
+   unsigned int tmp, retry_cnt;

dev_dbg(&client->dev, "\n");

@@ -330,9 +330,22 @@ static int mn88472_init(struct dvb_frontend *fe)
if (len > (dev->i2c_wr_max - 1))
len = dev->i2c_wr_max - 1;

+   /* I2C transfers during firmware load might fail sometimes,
+* just retry in that case. 4 consecutive failures have
+* been observed thus a retry limit of 20 is used.
+*/
+   retry_cnt = 20;
+retry:
ret = regmap_bulk_write(dev->regmap[0], 0xf6,
&fw->data[fw->size - remaining], len);
if (ret) {
+   if (retry_cnt) {
+   dev_dbg(&client->dev,
+   "i2c error, retry %d triggered\n", retry_cnt);
+   retry_cnt--;
+   usleep_range(200, 1);
+   goto retry;
+   }
dev_err(&client->dev,
"firmware download failed=%d\n", ret);
goto firmware_release;



--
http://palosaari.fi/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[GIT PULL 4.5] rtl2832u changes

2015-12-20 Thread Antti Palosaari

The following changes since commit 0aff8a894a2be4c22e6414db33061153a4b35bc9:

  [media] uvcvideo: small cleanup in uvc_video_clock_update() 
(2015-12-18 15:21:35 -0200)


are available in the git repository at:

  git://linuxtv.org/anttip/media_tree.git rtl2832u_pull

for you to fetch changes up to bbed859d68218c043fa88ccdd9785d9567d8fb5d:

  rtl2832: do not filter out slave TS null packets (2015-12-20 04:57:20 
+0200)



Antti Palosaari (3):
  rtl28xxu: return demod reg page from driver cache
  rtl2832: print reg number on error case
  rtl2832: do not filter out slave TS null packets

 drivers/media/dvb-frontends/rtl2832.c   | 21 ++---
 drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 16 +++-
 2 files changed, 17 insertions(+), 20 deletions(-)

--
http://palosaari.fi/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] si2168: use i2c controlled mux interface

2016-01-05 Thread Antti Palosaari
Recent i2c mux locking update offers support for i2c controlled i2c
muxes. Use it and get the rid of homemade hackish i2c adapter
locking code.

Cc: Peter Rosin 
Cc: Peter Rosin 
Signed-off-by: Antti Palosaari 
---
 drivers/media/dvb-frontends/si2168.c | 61 
 1 file changed, 6 insertions(+), 55 deletions(-)

diff --git a/drivers/media/dvb-frontends/si2168.c 
b/drivers/media/dvb-frontends/si2168.c
index ae217b5..d2a5608 100644
--- a/drivers/media/dvb-frontends/si2168.c
+++ b/drivers/media/dvb-frontends/si2168.c
@@ -18,48 +18,15 @@
 
 static const struct dvb_frontend_ops si2168_ops;
 
-/* Own I2C adapter locking is needed because of I2C gate logic. */
-static int si2168_i2c_master_send_unlocked(const struct i2c_client *client,
-  const char *buf, int count)
-{
-   int ret;
-   struct i2c_msg msg = {
-   .addr = client->addr,
-   .flags = 0,
-   .len = count,
-   .buf = (char *)buf,
-   };
-
-   ret = __i2c_transfer(client->adapter, &msg, 1);
-   return (ret == 1) ? count : ret;
-}
-
-static int si2168_i2c_master_recv_unlocked(const struct i2c_client *client,
-  char *buf, int count)
-{
-   int ret;
-   struct i2c_msg msg = {
-   .addr = client->addr,
-   .flags = I2C_M_RD,
-   .len = count,
-   .buf = buf,
-   };
-
-   ret = __i2c_transfer(client->adapter, &msg, 1);
-   return (ret == 1) ? count : ret;
-}
-
 /* execute firmware command */
-static int si2168_cmd_execute_unlocked(struct i2c_client *client,
-  struct si2168_cmd *cmd)
+static int si2168_cmd_execute(struct i2c_client *client, struct si2168_cmd 
*cmd)
 {
int ret;
unsigned long timeout;
 
if (cmd->wlen) {
/* write cmd and args for firmware */
-   ret = si2168_i2c_master_send_unlocked(client, cmd->args,
- cmd->wlen);
+   ret = i2c_master_send(client, cmd->args, cmd->wlen);
if (ret < 0) {
goto err;
} else if (ret != cmd->wlen) {
@@ -73,8 +40,7 @@ static int si2168_cmd_execute_unlocked(struct i2c_client 
*client,
#define TIMEOUT 70
timeout = jiffies + msecs_to_jiffies(TIMEOUT);
while (!time_after(jiffies, timeout)) {
-   ret = si2168_i2c_master_recv_unlocked(client, cmd->args,
- cmd->rlen);
+   ret = i2c_master_recv(client, cmd->args, cmd->rlen);
if (ret < 0) {
goto err;
} else if (ret != cmd->rlen) {
@@ -109,17 +75,6 @@ err:
return ret;
 }
 
-static int si2168_cmd_execute(struct i2c_client *client, struct si2168_cmd 
*cmd)
-{
-   int ret;
-
-   i2c_lock_adapter(client->adapter);
-   ret = si2168_cmd_execute_unlocked(client, cmd);
-   i2c_unlock_adapter(client->adapter);
-
-   return ret;
-}
-
 static int si2168_read_status(struct dvb_frontend *fe, enum fe_status *status)
 {
struct i2c_client *client = fe->demodulator_priv;
@@ -610,11 +565,6 @@ static int si2168_get_tune_settings(struct dvb_frontend 
*fe,
return 0;
 }
 
-/*
- * I2C gate logic
- * We must use unlocked I2C I/O because I2C adapter lock is already taken
- * by the caller (usually tuner driver).
- */
 static int si2168_select(struct i2c_mux_core *muxc, u32 chan)
 {
struct i2c_client *client = i2c_mux_priv(muxc);
@@ -625,7 +575,7 @@ static int si2168_select(struct i2c_mux_core *muxc, u32 
chan)
memcpy(cmd.args, "\xc0\x0d\x01", 3);
cmd.wlen = 3;
cmd.rlen = 0;
-   ret = si2168_cmd_execute_unlocked(client, &cmd);
+   ret = si2168_cmd_execute(client, &cmd);
if (ret)
goto err;
 
@@ -645,7 +595,7 @@ static int si2168_deselect(struct i2c_mux_core *muxc, u32 
chan)
memcpy(cmd.args, "\xc0\x0d\x00", 3);
cmd.wlen = 3;
cmd.rlen = 0;
-   ret = si2168_cmd_execute_unlocked(client, &cmd);
+   ret = si2168_cmd_execute(client, &cmd);
if (ret)
goto err;
 
@@ -717,6 +667,7 @@ static int si2168_probe(struct i2c_client *client,
dev->muxc->parent = client->adapter;
dev->muxc->select = si2168_select;
dev->muxc->deselect = si2168_deselect;
+   dev->muxc->i2c_controlled = true;
 
/* create mux i2c adapter for tuner */
ret = i2c_add_mux_adapter(dev->muxc, 0, 0, 0);
-- 
http://palosaari.fi/

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] si2168: use i2c controlled mux interface

2016-01-06 Thread Antti Palosaari

Moikka!

On 01/06/2016 09:14 AM, Peter Rosin wrote:

Hi Antti,

On 2016-01-06 06:42, Antti Palosaari wrote:

Recent i2c mux locking update offers support for i2c controlled i2c
muxes. Use it and get the rid of homemade hackish i2c adapter
locking code.


That looks good on a first glance, and I'm sure it felt good to get rid
of the locking workaround :-)


And I forgot mutext to protect si2168_cmd_execute()...


However, is this safe? From looking at the short datasheet of the si2168,
it seems that the mux is used to open up the channel to the tuner? But
what happens is there are two parallel accesses, one to the tuner and one
to the si2168 chip? With your change, it could happen that the access to
the si2168 happens while the gate to the tuner is open. Can that break
anything?

I.e.
 thread one  thread two
 --  --
open gate
 access si2168
 access tuner
 close gate

If that is safe, then I don't understand why the gate isn't left open
at all times? The short datasheet is too short to answer my questions...


It is often called I2C Gate or repeater, and yes it is there to block 
noise traveling to tuner. I think that noise could be unnecessary I2C 
traffic as well some digital noise travelling via I2C wires. Tuners are 
usually build using pure digital logic + analog circuits (RF mixers, RF 
filters, RF amplifiers). Leaving gate open usually does not harm and 
there is even some designs it is connected directly to main bus (but 
almost all demodulators still has that kind of gate to connect tuner).


All in all, I don't see it very big issue if only few unwanted I2C 
messages are sent to bus tuner is connected.



Also, my series needs some Tested-by (and Reviewed-by for that matter),
and I assume that you have tested it? Is it ok to add something like
that from you? I understand that you may only be able to test your
corner of the series, but that would still be very helpful. Thanks!


Yes it worked, but I haven't examined it care enough yet.

However, I think I see one problem: i2c muxes that deselects channel 
automatically, usually after the first i2c stop (P) condition is seen.


regards
Antti



Cheers,
Peter


Cc: Peter Rosin 
Cc: Peter Rosin 
Signed-off-by: Antti Palosaari 
---
  drivers/media/dvb-frontends/si2168.c | 61 
  1 file changed, 6 insertions(+), 55 deletions(-)

diff --git a/drivers/media/dvb-frontends/si2168.c 
b/drivers/media/dvb-frontends/si2168.c
index ae217b5..d2a5608 100644
--- a/drivers/media/dvb-frontends/si2168.c
+++ b/drivers/media/dvb-frontends/si2168.c
@@ -18,48 +18,15 @@

  static const struct dvb_frontend_ops si2168_ops;

-/* Own I2C adapter locking is needed because of I2C gate logic. */
-static int si2168_i2c_master_send_unlocked(const struct i2c_client *client,
-  const char *buf, int count)
-{
-   int ret;
-   struct i2c_msg msg = {
-   .addr = client->addr,
-   .flags = 0,
-   .len = count,
-   .buf = (char *)buf,
-   };
-
-   ret = __i2c_transfer(client->adapter, &msg, 1);
-   return (ret == 1) ? count : ret;
-}
-
-static int si2168_i2c_master_recv_unlocked(const struct i2c_client *client,
-  char *buf, int count)
-{
-   int ret;
-   struct i2c_msg msg = {
-   .addr = client->addr,
-   .flags = I2C_M_RD,
-   .len = count,
-   .buf = buf,
-   };
-
-   ret = __i2c_transfer(client->adapter, &msg, 1);
-   return (ret == 1) ? count : ret;
-}
-
  /* execute firmware command */
-static int si2168_cmd_execute_unlocked(struct i2c_client *client,
-  struct si2168_cmd *cmd)
+static int si2168_cmd_execute(struct i2c_client *client, struct si2168_cmd 
*cmd)
  {
int ret;
unsigned long timeout;

if (cmd->wlen) {
/* write cmd and args for firmware */
-   ret = si2168_i2c_master_send_unlocked(client, cmd->args,
- cmd->wlen);
+   ret = i2c_master_send(client, cmd->args, cmd->wlen);
if (ret < 0) {
goto err;
} else if (ret != cmd->wlen) {
@@ -73,8 +40,7 @@ static int si2168_cmd_execute_unlocked(struct i2c_client 
*client,
#define TIMEOUT 70
timeout = jiffies + msecs_to_jiffies(TIMEOUT);
while (!time_after(jiffies, timeout)) {
-   ret = si2168_i2c_master_recv_unlocked(client, cmd->args,
- cmd->rlen);
+   ret = i2c_master_recv(client, cmd->args, cmd->rlen);
 

Re: [PATCH v2 0/8] i2c mux cleanup and locking update

2016-01-06 Thread Antti Palosaari

On 01/05/2016 05:57 PM, Peter Rosin wrote:

From: Peter Rosin 

Hi!

I have a pair of boards with this i2c topology:

GPIO ---|  -- BAT1
 |  v /
I2C  -+--B---+ MUX
  |   \
EEPROM -- BAT2

(B denotes the boundary between the boards)


Handling of I2C muxes that close channel automatically, after the first 
I2C stop (P) is seen?


For example channel is selected to BAT1 => there is EEPROM write => mux 
closes channel BAT1 => access to BAT1 will fail. Is it possible to lock 
whole adapter, but allow only traffic to i2c mux client?


regards
Antti



The problem with this is that the GPIO controller sits on the same i2c bus
that it MUXes. For pca954x devices this is worked around by using unlocked
transfers when updating the MUX. I have no such luck as the GPIO is a general
purpose IO expander and the MUX is just a random bidirectional MUX, unaware
of the fact that it is muxing an i2c bus, and extending unlocked transfers
into the GPIO subsystem is too ugly to even think about. But the general hw
approach is sane in my opinion, with the number of connections between the
two boards minimized. To put is plainly, I need support for it.

So, I observe that while it is needed to have the i2c bus locked during the
actual MUX update in order to avoid random garbage on the slave side, it
is not strictly a must to have it locked over the whole sequence of a full
select-transfer-deselect operation. The MUX itself needs to be locked, so
transfers to clients behind the mux are serialized, and the MUX needs to be
stable during all i2c traffic (otherwise individual mux slave segments
might see garbage).

This series accomplishes this by adding a dt property to i2c-mux-gpio and
i2c-mux-pinctrl that can be used to state that the mux is updated by means
of the muxed master bus, and that the select-transfer-deselect operations
should be locked individually. When this holds, the i2c bus *is* locked
during muxing, since the muxing happens as part of i2c transfers. This
is true even if the MUX is updated with several transfers to the GPIO (at
least as long as *all* MUX changes are using the i2s master bus). A lock
is added to the mux so that transfers through the mux are serialized.

Concerns:
- The locking is perhaps too complex?
- I worry about the priority inheritance aspect of the adapter lock. When
   the transfers behind the mux are divided into select-transfer-deselect all
   locked individually, low priority transfers get more chances to interfere
   with high priority transfers.
- When doing an i2c_transfer() in_atomic() context of with irqs_disabled(),
   there is a higher possibility that the mux is not returned to its idle
   state after a failed (-EAGAIN) transfer due to trylock.

To summarize the series, there's some i2c-mux infrastructure cleanup work
first (I think that part stands by itself as desireable regardless), the
locking changes are in the last three patches of the series, with the real
meat in 8/8.

PS. needs a bunch of testing, I do not have access to all the involved hw

Changes since v1:
- Allocate mux core and (optional) priv in a combined allocation.
- Killed dev_err messages triggered by memory allocation failure.
- Fix the device specific i2c muxes that I had overlooked.
- Rebased on top of v4.4-rc8 (was based on v4.4-rc6 previously).

Cheers,
Peter

Peter Rosin (8):
   i2c-mux: add common core data for every mux instance
   i2c-mux: move select and deselect ops to i2c_mux_core
   i2c-mux: move the slave side adapter management to i2c_mux_core
   i2c-mux: remove the mux dev pointer from the mux per channel data
   i2c-mux: pinctrl: get rid of the driver private struct device pointer
   i2c: allow adapter drivers to override the adapter locking
   i2c: muxes always lock the parent adapter
   i2c-mux: relax locking of the top i2c adapter during i2c controlled
 muxing

  .../devicetree/bindings/i2c/i2c-mux-gpio.txt   |   2 +
  .../devicetree/bindings/i2c/i2c-mux-pinctrl.txt|   4 +
  drivers/i2c/i2c-core.c |  59 ++---
  drivers/i2c/i2c-mux.c  | 272 +
  drivers/i2c/muxes/i2c-arb-gpio-challenge.c |  46 ++--
  drivers/i2c/muxes/i2c-mux-gpio.c   |  58 ++---
  drivers/i2c/muxes/i2c-mux-pca9541.c|  58 +++--
  drivers/i2c/muxes/i2c-mux-pca954x.c|  66 ++---
  drivers/i2c/muxes/i2c-mux-pinctrl.c|  89 +++
  drivers/i2c/muxes/i2c-mux-reg.c|  63 ++---
  drivers/iio/imu/inv_mpu6050/inv_mpu_core.c |  33 +--
  drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h  |   2 +-
  drivers/media/dvb-frontends/m88ds3103.c|  23 +-
  drivers/media/dvb-frontends/m88ds3103_priv.h   |   2 +-
  drivers/media/dvb-frontends/rtl2830.c  |  24 +-
  drivers/media/dvb-frontends/rtl2830_p

[PATCH] rtl28xxu: retry failed i2c messages

2016-01-07 Thread Antti Palosaari
Sometimes i2c transfer fails. That happens especially when large
amount of data is written sequentially eg. firmware download.
Problem arises with both integrated rtl2832 demod and external
mn88472 demod, which is clear indicator it is busy i2c bus issue.
Use i2c core retry logic in order fix the issue by repeating failed
message. Another solution which also works is to add ~100us delay
between i2c messages - but repeating sounds more elegant and does
not cause any extra delay for success cases.

Signed-off-by: Antti Palosaari 
---
 drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c 
b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index eb5787a..c4c6e92 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -259,6 +259,10 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, 
struct i2c_msg msg[],
ret = -EOPNOTSUPP;
}
 
+   /* Retry failed I2C messages */
+   if (ret == -EPIPE)
+   ret = -EAGAIN;
+
 err_mutex_unlock:
mutex_unlock(&d->i2c_mutex);
 
@@ -619,6 +623,10 @@ static int rtl28xxu_identify_state(struct dvb_usb_device 
*d, const char **name)
}
dev_dbg(&d->intf->dev, "chip_id=%u\n", dev->chip_id);
 
+   /* Retry failed I2C messages */
+   d->i2c_adap.retries = 1;
+   d->i2c_adap.timeout = msecs_to_jiffies(10);
+
return WARM;
 err:
dev_dbg(&d->intf->dev, "failed=%d\n", ret);
-- 
http://palosaari.fi/

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[GIT PULL] mn88473: move out of staging

2016-03-03 Thread Antti Palosaari

Resend, just forgot [GIT PULL] subject prefix earlier.

The following changes since commit 210bd104c6acd31c3c6b8b075b3f12d4a9f6b60d:

  [media] xc2028: unlock on error in xc2028_set_config() (2016-02-04 
09:30:31 -0200)


are available in the git repository at:

  git://linuxtv.org/anttip/media_tree.git mn88473_pull

for you to fetch changes up to 05886118dd140b4d96cf4de5c76b4fb6155316f5:

  rtl2832: move stats polling to read status (2016-02-14 04:29:33 +0200)


Antti Palosaari (4):
  mn88473: move out of staging
  mn88473: finalize driver
  rtl2832: improve slave TS control
  rtl2832: move stats polling to read status

 MAINTAINERS |   4 +-
 drivers/media/dvb-frontends/Kconfig |   8 +++
 drivers/media/dvb-frontends/Makefile |   1 +
 drivers/{staging/media/mn88473 => media/dvb-frontends}/mn88473.c | 388 


 drivers/media/dvb-frontends/mn88473.h |  14 ++---
 drivers/{staging/media/mn88473 => media/dvb-frontends}/mn88473_priv.h 
|   7 +--
 drivers/media/dvb-frontends/rtl2832.c | 151 
+---

 drivers/media/dvb-frontends/rtl2832.h |   4 +-
 drivers/media/dvb-frontends/rtl2832_priv.h |   1 -
 drivers/media/usb/dvb-usb-v2/rtl28xxu.c |  24 +++
 drivers/staging/media/Kconfig |   2 -
 drivers/staging/media/Makefile |   1 -
 drivers/staging/media/mn88473/Kconfig |   7 ---
 drivers/staging/media/mn88473/Makefile |   5 --
 drivers/staging/media/mn88473/TODO |  21 ---
 15 files changed, 340 insertions(+), 298 deletions(-)
 rename drivers/{staging/media/mn88473 => 
media/dvb-frontends}/mn88473.c (61%)
 rename drivers/{staging/media/mn88473 => 
media/dvb-frontends}/mn88473_priv.h (89%)

 delete mode 100644 drivers/staging/media/mn88473/Kconfig
 delete mode 100644 drivers/staging/media/mn88473/Makefile
 delete mode 100644 drivers/staging/media/mn88473/TODO


--
http://palosaari.fi/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] si2168: add lock to cmd execute

2016-03-15 Thread Antti Palosaari
Mauro do not apply that patch, it is fix for Peter I2C-mux serie!

Peter, please meld that fix to main patch:
[media] si2168: declare that the i2c gate is self-locked

We need lock to make sure only single caller could execute firmware
command at the time. Earlier there was manual I2C locking which did
the same job.

Cc: Peter Rosin 
Signed-off-by: Antti Palosaari 
---
 drivers/media/dvb-frontends/si2168.c  | 21 ++---
 drivers/media/dvb-frontends/si2168_priv.h |  1 +
 2 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/drivers/media/dvb-frontends/si2168.c 
b/drivers/media/dvb-frontends/si2168.c
index 4a9b73b..786808f 100644
--- a/drivers/media/dvb-frontends/si2168.c
+++ b/drivers/media/dvb-frontends/si2168.c
@@ -21,17 +21,20 @@ static const struct dvb_frontend_ops si2168_ops;
 /* execute firmware command */
 static int si2168_cmd_execute(struct i2c_client *client, struct si2168_cmd 
*cmd)
 {
+   struct si2168_dev *dev = i2c_get_clientdata(client);
int ret;
unsigned long timeout;
 
+   mutex_lock(&dev->i2c_mutex);
+
if (cmd->wlen) {
/* write cmd and args for firmware */
ret = i2c_master_send(client, cmd->args, cmd->wlen);
if (ret < 0) {
-   goto err;
+   goto err_mutex_unlock;
} else if (ret != cmd->wlen) {
ret = -EREMOTEIO;
-   goto err;
+   goto err_mutex_unlock;
}
}
 
@@ -42,10 +45,10 @@ static int si2168_cmd_execute(struct i2c_client *client, 
struct si2168_cmd *cmd)
while (!time_after(jiffies, timeout)) {
ret = i2c_master_recv(client, cmd->args, cmd->rlen);
if (ret < 0) {
-   goto err;
+   goto err_mutex_unlock;
} else if (ret != cmd->rlen) {
ret = -EREMOTEIO;
-   goto err;
+   goto err_mutex_unlock;
}
 
/* firmware ready? */
@@ -60,17 +63,19 @@ static int si2168_cmd_execute(struct i2c_client *client, 
struct si2168_cmd *cmd)
/* error bit set? */
if ((cmd->args[0] >> 6) & 0x01) {
ret = -EREMOTEIO;
-   goto err;
+   goto err_mutex_unlock;
}
 
if (!((cmd->args[0] >> 7) & 0x01)) {
ret = -ETIMEDOUT;
-   goto err;
+   goto err_mutex_unlock;
}
}
 
+   mutex_unlock(&dev->i2c_mutex);
return 0;
-err:
+err_mutex_unlock:
+   mutex_unlock(&dev->i2c_mutex);
dev_dbg(&client->dev, "failed=%d\n", ret);
return ret;
 }
@@ -658,6 +663,8 @@ static int si2168_probe(struct i2c_client *client,
goto err;
}
 
+   mutex_init(&dev->i2c_mutex);
+
/* create mux i2c adapter for tuner */
dev->muxc = i2c_mux_one_adapter(client->adapter, &client->dev, 0,
I2C_MUX_SELF_LOCKED, 0, 0, 0,
diff --git a/drivers/media/dvb-frontends/si2168_priv.h 
b/drivers/media/dvb-frontends/si2168_priv.h
index 165bf14..8a1f36d 100644
--- a/drivers/media/dvb-frontends/si2168_priv.h
+++ b/drivers/media/dvb-frontends/si2168_priv.h
@@ -29,6 +29,7 @@
 
 /* state struct */
 struct si2168_dev {
+   struct mutex i2c_mutex;
struct i2c_mux_core *muxc;
struct dvb_frontend fe;
enum fe_delivery_system delivery_system;
-- 
http://palosaari.fi/

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4 00/18] i2c mux cleanup and locking update

2016-03-15 Thread Antti Palosaari

On 03/15/2016 04:09 PM, Peter Rosin wrote:


The series will be posted again for review. This is just a heads up.

v5 compared to v4:
- Rebase on top of v4.5-rc7.
- A new patch making me maintainer of i2c muxes (also sent separately).
- A new file Documentation/i2c/i2c-topology that describes various muxing
   issues.
- Rename "i2c-controlled" muxes "self-locked" instead, as it is perfectly
   reasonable to have i2c-controlled muxes that use the pre-existing locking
   scheme. The pre-existing locking scheme for i2c muxes is from here on
   called "parent-locked".
- Rename i2c-mux.c:i2c_mux_master_xfer to __i2c_mux_master_xfer since it
   calls __i2c_transfer, which leaves room for a new i2c_mux_master_xfer
   that calls i2c_transfer. Similar rename shuffle for i2c_mux_smbus_xfer.
- Use sizeof(*priv) instead of sizeof(struct i2c_mux_priv). One instance.
- Some follow-up patches that were posted in response to v2-v4 cleaning up
   and simplifying various i2c muxes outside drivers/i2c/, among those is
   an unrelated cleanup patch to drivers/media/dvb-frontends/rtl2832.c that
   I carry here since it conflicts (trivially) with this series. That
   unrelated patch is (currently) the last patch in the series.


The series looks like this now:

The following changes since commit f6cede5b49e822ebc41a099fe41ab4989f64e2cb:

   Linux 4.5-rc7 (2016-03-06 14:48:03 -0800)

are available in the git repository at:

   https://github.com/peda-r/i2c-mux.git mux-core-and-locking-5


I reviewed and tested these patches:

c1ef4a2 [media] rtl2832: regmap is aware of lockdep, drop local locking hack
6636178 [media] rtl2832_sdr: get rid of empty regmap wrappers
001ad6b [media] rtl2832: declare that the i2c gate is self-locked
e2e82e4 [media] si2168: declare that the i2c gate is self-locked
b52f766 [media] si2168: convert to use an explicit i2c mux core
4ba9115 [media] rtl2832: convert to use an explicit i2c mux core
3f1778b [media] rtl2830: convert to use an explicit i2c mux core
5c8bfc8 [media] m88ds3103: convert to use an explicit i2c mux core


Reviewed-by: Antti Palosaari 
Tested-by: Antti Palosaari 

regards
Antti

--
http://palosaari.fi/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] si2168: use i2c controlled mux interface

2016-04-05 Thread Antti Palosaari

On 03/23/2016 06:58 PM, Peter Rosin wrote:

On 2016-01-06 06:42, Antti Palosaari wrote:

Recent i2c mux locking update offers support for i2c controlled i2c
muxes. Use it and get the rid of homemade hackish i2c adapter
locking code.


[actual patch elided]

I had a 2nd look and it seems that the saa7164 driver has support for
a HVR2055 card with dual si2168 chips. These two chips appear to sit
on the same i2c-bus with different i2c-addresses (0x64 and 0x66) and
with gates (implemented as muxes) to two identical tuners with the
same i2c-address (0x60). Do I read it right?


saa7164 has 3 different I2C adapters.

saa7164 I2C bus #0:
* eeprom
* Si2157 #1

saa7164 I2C bus #1:
* Si2157 #2

saa7164 I2C bus #2:
* Si2168 #1
* Si2168 #2

So both of the Si2157 tuners could have same addresses.

(It is Hauppauge WinTV-HVR2205, not HVR-2055).


With the current i2c-mux-locking (parent-locked muxes), this works
fine as an access to one of the tuners locks the root i2c adapter
and thus the other tuner is also locked out. But with the upcoming
i2c-mux-locking for i2c-controlled muxes (self-locked muxes), the
root i2c adapter would no longer be locked for the full transaction
when one of the tuners is accessed. This means that accesses to the
two tuners may interleave and cause all kinds of trouble, should
both gates be open at the same time. So, is it really correct and
safe to change the si2168 driver to use a self-locked mux?

Unless there is some other mechanism that prevents the two tuners
from being accessed in parallel, I think not. But maybe there is such
a mechanism?


Good point. Actually there is pretty often this kind of configuration 
used for those dual tuner devices and it will cause problems... 
Currently all of those implements hackish i2c_gate_ctrl() callback to 
switch mux.


       
|I2C-adapter | |  I2C-mux   | | I2C-client |
|| || ||
|| | addr 0x1c  | | addr 0x60  |
|| || ||
||-+-I2C---|-/ -|---I2C---||
|| |   || ||
   |   
   |   |  I2C-mux   | | I2C-client |
   |   || ||
   |   | addr 0x1d  | | addr 0x60  |
   |   || ||
   +-I2C---|-/ -|---I2C---||
   || ||


regards
Antti

--
http://palosaari.fi/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: AVerMedia HD Volar (A867) AF9035 + MXL5007T driver issues

2016-04-05 Thread Antti Palosaari

On 04/02/2016 01:44 PM, Alessandro Radicati wrote:

Hi,
In trying to understand why my DVB USB tuner doesn't work with stock
kernel drivers (4.2.0), I decided to pull out my logic analyser and
sniff the I2C bus between the AF9035 and MXL5007T.  I seem to have
uncovered a couple of issues:

1) Attach fails because MXL5007T driver I2C soft reset fails.  This is
due to the preceding chip id read request that seems to hang the I2C
bus and cause subsequent I2C commands to fail.


In my understanding MXL5007T register read is done in a two 
transactions. First you should write wanted register to register 0xfb. 
After that single byte read from the chip returns value for register 
configured to 0xfb. Write+read with repeated start is not supported and 
driver is buggy as it request that which usually leads to bogus value.




2) AF9035 driver I2C master xfer incorrectly implements "Write read"
case.  The FW expects register address fields to be used to send the
I2C writes for register selection.  The current implementation ignores
these fields and the result is that only an I2C read is issued.
Therefore the "0x3f" returned by the MXL5007T chip id query is not
from the expected register.  This is what is seen on the I2C bus:

S | Read 0x60 + ACK | 0x3F + NAK | ...

After which SDA is held low for ~6sec; reason for subsequent commands failing.


You should use "S | W | P | S | R | P", no "S | W | S | R | P" == write 
read with repeated start condition.



3) After modifying the AF9035 driver to fix point 2 and use the
register address field, the following is seen on the I2C bus:

S | Write 0x60 + ACK | 0xFB + ACK | 0xD9 + ACK | P
S | Read 0x60 + ACK | 0x14 + NAK | ...


That is correct sequence. You are trying to read more than 1 byte and it 
fails?



This time we get an expected response, but the I2C bus still hangs
with SDA held low and no Stop sequence.  It seems that the MXL5007T is
holding SDA low since the AF9035 happily cycles SCL trying to execute
the subsequent writes.  Without a solution to this, it seems that
avoiding the I2C read is the best way to have the driver work
correctly.  There are no other tuner reads so point 2 above becomes
moot for at least this device.

Does anyone have any insight on the MXL5007T chip ID command and
whether it should be issued in certain conditions?  Any suggestions on
how to resolve this given the above?


I tried to fix it earlier:
http://www.spinics.net/lists/linux-media/msg62264.html

Feel free to fix! It should not be very hard as you could even sniff 
data from the I2C bus directly. I don't have any AF9035+MXL5007T device, 
but I have tested it with older AF9015+MXL5007T.


regards
Antti

--
http://palosaari.fi/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: AVerMedia HD Volar (A867) AF9035 + MXL5007T driver issues

2016-04-05 Thread Antti Palosaari
I found one stick having AF9035 + MXL5007T. It is HP branded A867, so it 
should be similar. It seems to work all three 12.13.15.0 6.20.15.0 
firmwares:

http://palosaari.fi/linux/v4l-dvb/firmware/af9035/

mxl5007t 5-0060: creating new instance
mxl5007t_get_chip_id: unknown rev (3f)
mxl5007t_get_chip_id: MxL5007T detected @ 5-0060

That is what AF9035 reports (with debug) as a chip version:
dvb_usb_af9035: prechip_version=00 chip_version=03 chip_type=3802


Do you have different chip version?

regards
Antti

--
http://palosaari.fi/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: AVerMedia HD Volar (A867) AF9035 + MXL5007T driver issues

2016-04-08 Thread Antti Palosaari

uh, how it could be so hard?

I just made few tests and found 3 ways to read it. OK, one is that 
Alessandro already pointed out and I don't feel it correct. But those 2 
are one for look. CMD_I2C_WR / CMD_I2C_RD with 1st priority, then 
CMD_GENERIC_I2C_WR / CMD_GENERIC_I2C_RD


{
u8 buf[MAX_XFER_SIZE];
struct usb_req req = {0, 0, 0, buf, 0, buf};
#if 0
req.cmd = CMD_GENERIC_I2C_WR;
req.wlen = 3 + 2;
req.rlen = 0;
buf[0] = 2; // write len
buf[1] = 0x02; /* I2C bus */ // NOK 3, 1, 0
buf[2] = 0x60 << 1; // I2C addr
buf[3] = 0xfb; /* reg addr MSB */
buf[4] = 0xd9; /* reg addr LSB */
ret = af9035_ctrl_msg(d, &req);
dev_dbg(&d->udev->dev, "1mxl5007t %02x\n", 0);

req.cmd = CMD_GENERIC_I2C_RD;
req.wlen = 3;
req.rlen = 1;
buf[0] = 1; // read len
buf[1] = 0x02; /* I2C bus */ // NOK 3, 1, 0
buf[2] = 0x60 << 1; // I2C addr
ret = af9035_ctrl_msg(d, &req);
dev_dbg(&d->udev->dev, "1mxl5007t %02x\n", buf[0]);
#endif

#if 0
req.cmd = CMD_I2C_RD;
req.wlen = 5;
req.rlen = 1;
buf[0] = 1; // read len
buf[1] = 0x60 << 1; // I2C addr
buf[2] = 2; /* reg addr len */
buf[3] = 0xfb; /* reg addr MSB */
buf[4] = 0xd9; /* reg addr LSB */
ret = af9035_ctrl_msg(d, &req);
dev_dbg(&d->udev->dev, "4mxl5007t %02x\n", buf[0]);
#endif

#if 1
req.cmd = CMD_I2C_WR;
req.wlen = 7;
req.rlen = 0;
buf[0] = 2; // write len msg[0].len;
buf[1] = 0x60 << 1; // I2C addr
buf[2] = 0x00; /* reg addr len */
buf[3] = 0x00; /* reg addr MSB */
buf[4] = 0x00; /* reg addr LSB */
buf[5] = 0xfb;
buf[6] = 0xd9;
ret = af9035_ctrl_msg(d, &req);
dev_dbg(&d->udev->dev, "9mxl5007t %02x\n", buf[0]);

req.cmd = CMD_I2C_RD;
req.wlen = 5;
req.rlen = 1;
buf[0] = 1; // read len
buf[1] = 0x60 << 1; // I2C addr
buf[2] = 0x00; /* reg addr len */
buf[3] = 0x00; /* reg addr MSB */
buf[4] = 0x00; /* reg addr LSB */
ret = af9035_ctrl_msg(d, &req);
dev_dbg(&d->udev->dev, "9mxl5007t %02x\n", buf[0]);
#endif
}




On 04/09/2016 02:59 AM, Alessandro Radicati wrote:

Jose, Antti,
The no_probe option or similar is the only fix I could find (in fact i
was going to propose a similar patch to what you have).  I've tried
all combinations of firmware and also tried issuing the read command
to the tuner in different states (e.g. sleep, just after soft/hard
reset) to no avail.  I've modified AverMedia's linux driver to probe
as well, and the same thing happens.  I found the following behavior
in further testing:

- I can arbitrarily read as many bytes as I want from any valid
register and the tuner will continue responding until the af9035
issues the expected NAK to signal the end of the read so that the
mxl5007t can release the bus.  The bus doesn't get released and it
stays stuck either high or low indefinitely so subsequent I2C commands
fail.
- Hard reset of the tuner by cycling af9035 GPIOH12 seems like the
only way to recover.  So mxl5007t is probably at fault.  Perhaps I2C
speed is too fast (SCL cycles at ~100KHz)?  Faulty hardware design of
the usb stick?
- Doesn't seem like the OEM drivers ever issue I2C read commands.
Maybe it's a known issue to them.

I'm pretty much out of ideas to test.  Suggestions are welcome.
Otherwise I'll try to push through a patch for just "no_probe".

Thanks,
Alessandro

On Sat, Apr 9, 2016 at 1:13 AM, Jose Alberto Reguero
 wrote:

I made a patch long time ago, but it was not accepted.

https://patchwork.linuxtv.org/patch/16242/

Jose Alberto

El 06/04/2016 01:00, Alessandro Radicati  escribió:


On Wed, Apr 6, 2016 at 12:33 AM, Antti Palosaari  wrote:

I found one stick having AF9035 + MXL5007T. It is HP branded A867, so it
should be similar. It seems to work all three 12.13.15.0 6.20.15.0
firmwares:
http://palosaari.fi/linux/v4l-dvb/firmware/af9035/

mxl5007t 5-0060: creating new instance
mxl5007t_get_chip_id: unknown rev (3f)
mxl5007t_get_chip_id: MxL5007T detected @ 5-0060

That is what AF9035 reports (with debug) as a chip version:
dvb_usb_af9035: prechip_version=00 chip_version=03 chip_type=3802


Do you have different chip version?



I have a Sky Italy DVB stick with the same chip version.  I see that
you get the 0x3f response as well... that should be fixed by the I2C
patch I proposed.  However, your stick seems to handle the read
properly and process subsequent I2C commands - something that doesn't
happen with mine.  The vendor drivers in linux and windows never seem
issue the USB I2C commands to read from the tuner.  I'll test with
other firmware versions to see if something changes.

Regards,
Alessandro
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


--
http://palosaari.fi/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: AVerMedia HD Volar (A867) AF9035 + MXL5007T driver issues

2016-04-08 Thread Antti Palosaari

Here is patches to test:
http://git.linuxtv.org/anttip/media_tree.git/log/?h=af9035

After that both af9015+mxl5007t and af9035+mxl5007t started working. 
Earlier both were returning bogus values for chip id read.


Also I am interested to known which kind of communication there is 
actually seen on I2C bus?


If it starts working then have to find out way to fix it properly so 
that any earlier device didn't broke.


regards
Antti

On 04/09/2016 03:50 AM, Antti Palosaari wrote:

uh, how it could be so hard?

I just made few tests and found 3 ways to read it. OK, one is that
Alessandro already pointed out and I don't feel it correct. But those 2
are one for look. CMD_I2C_WR / CMD_I2C_RD with 1st priority, then
CMD_GENERIC_I2C_WR / CMD_GENERIC_I2C_RD

{
u8 buf[MAX_XFER_SIZE];
struct usb_req req = {0, 0, 0, buf, 0, buf};
#if 0
req.cmd = CMD_GENERIC_I2C_WR;
req.wlen = 3 + 2;
req.rlen = 0;
buf[0] = 2; // write len
buf[1] = 0x02; /* I2C bus */ // NOK 3, 1, 0
buf[2] = 0x60 << 1; // I2C addr
buf[3] = 0xfb; /* reg addr MSB */
buf[4] = 0xd9; /* reg addr LSB */
ret = af9035_ctrl_msg(d, &req);
dev_dbg(&d->udev->dev, "1mxl5007t %02x\n", 0);

req.cmd = CMD_GENERIC_I2C_RD;
req.wlen = 3;
req.rlen = 1;
buf[0] = 1; // read len
buf[1] = 0x02; /* I2C bus */ // NOK 3, 1, 0
buf[2] = 0x60 << 1; // I2C addr
ret = af9035_ctrl_msg(d, &req);
dev_dbg(&d->udev->dev, "1mxl5007t %02x\n", buf[0]);
#endif

#if 0
req.cmd = CMD_I2C_RD;
req.wlen = 5;
req.rlen = 1;
buf[0] = 1; // read len
buf[1] = 0x60 << 1; // I2C addr
buf[2] = 2; /* reg addr len */
buf[3] = 0xfb; /* reg addr MSB */
buf[4] = 0xd9; /* reg addr LSB */
ret = af9035_ctrl_msg(d, &req);
dev_dbg(&d->udev->dev, "4mxl5007t %02x\n", buf[0]);
#endif

#if 1
req.cmd = CMD_I2C_WR;
req.wlen = 7;
req.rlen = 0;
buf[0] = 2; // write len msg[0].len;
buf[1] = 0x60 << 1; // I2C addr
buf[2] = 0x00; /* reg addr len */
buf[3] = 0x00; /* reg addr MSB */
buf[4] = 0x00; /* reg addr LSB */
buf[5] = 0xfb;
buf[6] = 0xd9;
ret = af9035_ctrl_msg(d, &req);
dev_dbg(&d->udev->dev, "9mxl5007t %02x\n", buf[0]);

req.cmd = CMD_I2C_RD;
req.wlen = 5;
req.rlen = 1;
buf[0] = 1; // read len
buf[1] = 0x60 << 1; // I2C addr
buf[2] = 0x00; /* reg addr len */
buf[3] = 0x00; /* reg addr MSB */
buf[4] = 0x00; /* reg addr LSB */
ret = af9035_ctrl_msg(d, &req);
dev_dbg(&d->udev->dev, "9mxl5007t %02x\n", buf[0]);
#endif
}




On 04/09/2016 02:59 AM, Alessandro Radicati wrote:

Jose, Antti,
The no_probe option or similar is the only fix I could find (in fact i
was going to propose a similar patch to what you have).  I've tried
all combinations of firmware and also tried issuing the read command
to the tuner in different states (e.g. sleep, just after soft/hard
reset) to no avail.  I've modified AverMedia's linux driver to probe
as well, and the same thing happens.  I found the following behavior
in further testing:

- I can arbitrarily read as many bytes as I want from any valid
register and the tuner will continue responding until the af9035
issues the expected NAK to signal the end of the read so that the
mxl5007t can release the bus.  The bus doesn't get released and it
stays stuck either high or low indefinitely so subsequent I2C commands
fail.
- Hard reset of the tuner by cycling af9035 GPIOH12 seems like the
only way to recover.  So mxl5007t is probably at fault.  Perhaps I2C
speed is too fast (SCL cycles at ~100KHz)?  Faulty hardware design of
the usb stick?
- Doesn't seem like the OEM drivers ever issue I2C read commands.
Maybe it's a known issue to them.

I'm pretty much out of ideas to test.  Suggestions are welcome.
Otherwise I'll try to push through a patch for just "no_probe".

Thanks,
Alessandro

On Sat, Apr 9, 2016 at 1:13 AM, Jose Alberto Reguero
 wrote:

I made a patch long time ago, but it was not accepted.

https://patchwork.linuxtv.org/patch/16242/

Jose Alberto

El 06/04/2016 01:00, Alessandro Radicati 
escribió:


On Wed, Apr 6, 2016 at 12:33 AM, Antti Palosaari  wrote:

I found one stick having AF9035 + MXL5007T. It is HP branded A867,
so it
should be similar. It seems to work all three 12.13.15.0 6.20.15.0
firmwares:
http://palosaari.fi/linux/v4l-dvb/firmware/af9035/

mxl5007t 5-0060: creating new instance
mxl5007t_get_chip_id: unknown rev (3f)
mxl5007t_get_chip_id: MxL5007T detected @ 5-0060

That is what AF9035 reports (with debug) as a chip version:
dvb_usb_af9035: prechip_version=00 chip_version=03 chip_type=3802


Do you have different chip version?



I have a Sky Italy DVB stick with the same chip version.  I see that
you get the 0x3f response as well... that should be fixed by the I2C
patch I proposed.  However, your stick seems to handle the read
properly and process subsequent I2C commands - something that doesn't
happen with mine.  The vendor drivers in linux and windows nev

Re: AVerMedia HD Volar (A867) AF9035 + MXL5007T driver issues

2016-04-08 Thread Antti Palosaari

On 04/09/2016 04:52 AM, Alessandro Radicati wrote:

On Sat, Apr 9, 2016 at 3:22 AM, Antti Palosaari  wrote:

Here is patches to test:
http://git.linuxtv.org/anttip/media_tree.git/log/?h=af9035



I've done this already in my testing, and it works for getting a
correct chip_id response, but only because it's avoiding the issue
with the write/read case in the af9035 driver.  Don't have an
af9015... perhaps there's a similar issue with that code or we are
dealing with two separate issues since af9035 never does a repeated
start?


I am pretty sure mxl5007t requires stop between read and write. Usually 
chips are not caring too much if it is repeated start or not, whilst 
datasheets are often register read is S Wr S Rw P.


Even af9035 i2c adapter implementation implements repeated start wrong, 
I would not like to add anymore hacks there. It is currently ugly and 
complex as hell. I should be re-written totally in any case. Those tuner 
I2C adapters should be moved to demod. Demod has 1 I2C adapter. 
USB-bridge has 2 adapters, one for each demod.


I have to find out af9015 datasheets and check how it is there. But I 
still remember one case where I implemented one FX2 firmware and that 
same issues raises there as well.



After that both af9015+mxl5007t and af9035+mxl5007t started working. Earlier
both were returning bogus values for chip id read.

Also I am interested to known which kind of communication there is actually
seen on I2C bus?


With this or the patch I proposed, you see exactly what you expect on
the I2C bus with repeated stops, as detailed in my previous mails.


So it is good?


If it starts working then have to find out way to fix it properly so that
any earlier device didn't broke.



I hope that by now I've made abundantly clear that my mxl5007t locks
up after *any* read.  It doesn't matter if we are reading the correct
register after any of the proposed patches.


So it still locks up after any read after the chip id read? And does not 
work then? On my devices I can add multiple mxl5007t_get_chip_id() calls 
and all are returning correct values.


Could you test what happens if you use that CMD_GENERIC_I2C_WR + 
CMD_GENERIC_I2C_RD ? I suspect it is lower level I2C xfer than those 
CMD_I2C_RD + CMD_I2C_WR, which are likely somehow handled by demod core.


regards
Antti

--
http://palosaari.fi/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: AVerMedia HD Volar (A867) AF9035 + MXL5007T driver issues

2016-04-09 Thread Antti Palosaari

On 04/09/2016 11:13 AM, Alessandro Radicati wrote:

On Sat, Apr 9, 2016 at 4:17 AM, Antti Palosaari  wrote:

On 04/09/2016 04:52 AM, Alessandro Radicati wrote:


On Sat, Apr 9, 2016 at 3:22 AM, Antti Palosaari  wrote:


Here is patches to test:
http://git.linuxtv.org/anttip/media_tree.git/log/?h=af9035



I've done this already in my testing, and it works for getting a
correct chip_id response, but only because it's avoiding the issue
with the write/read case in the af9035 driver.  Don't have an
af9015... perhaps there's a similar issue with that code or we are
dealing with two separate issues since af9035 never does a repeated
start?



I am pretty sure mxl5007t requires stop between read and write. Usually
chips are not caring too much if it is repeated start or not, whilst
datasheets are often register read is S Wr S Rw P.

Even af9035 i2c adapter implementation implements repeated start wrong, I


Where does the assumption that CMD_I2C_RD should issue a repeated
start sequence come from?  From the datasheet?  Maybe it was never
intended as repeated start.  Perhaps if there is another stick  with
mxl5007t and a chip that does repeated start, we can put this to bed.


Assumption was coming from it just does it as a single USB transaction. 
Datasheet says there is no repeated start. And kernel I2C API says all 
messages send using single i2c_transfer() should be send with repeated 
start, so now it is violating it, but that's not the biggest problem...



would not like to add anymore hacks there. It is currently ugly and complex


Bugfix != hack.  Don't see how putting the register address in the
address fields is a hack (perhaps semantics around the fact that 0xFB
is not really part of the address?); this is the only and intended way
to use that command for write/read.


I did bunch of testing and find it is really wrong. Dumped out registers 
from some tuner chips and those seems to be mostly off by one.


I think that skeleton is correct way (and it ends about same you did)
if (msg[0].len == 0) // probe message, payload 0
  buf[0] = msg[0].len;
  buf[1] = msg[0].addr << 1;
  buf[2] = 0x00; /* reg addr len */
  buf[3] = 0x00; /* reg addr MSB */
  buf[4] = 0x00; /* reg addr LSB */
else if (msg[0].len == 1)
  buf[0] = msg[0].len;
  buf[1] = msg[0].addr << 1;
  buf[2] = 1; /* reg addr len */
  buf[3] = 0x00; /* reg addr MSB */
  buf[4] = msg[0].buf[0]; /* reg addr LSB */
else if (msg[0].len == 2)
  buf[0] = msg[0].len;
  buf[1] = msg[0].addr << 1;
  buf[2] = 2; /* reg addr len */
  buf[3] = msg[0].buf[0]; /* reg addr MSB */
  buf[4] = msg[0].buf[1]; /* reg addr LSB */
else
  buf[0] = msg[0].len;
  buf[1] = msg[0].addr << 1;
  buf[2] = 2; /* reg addr len */
  buf[3] = msg[0].buf[0]; /* reg addr MSB */
  buf[4] = msg[0].buf[1]; /* reg addr LSB */
  memcpy(&buf[5], msg[2].buf, msg[0].len - 2);



as hell. I should be re-written totally in any case. Those tuner I2C
adapters should be moved to demod. Demod has 1 I2C adapter. USB-bridge has 2
adapters, one for each demod.



Agreed that it can be refactored and improved.  Also to support n
transactions with a simple while loop and only issuing single writes
and reads.  Only downside would be increased USB traffic for 2
commands vs 1 - hence negligible.


there is i2c_adapter_quirks nowadays for these adapters which could do 
only limited set of commands.

include/linux/i2c.h

In my understanding that is how those chips are wired:
+---+ ++
| I2C adapter-1 | --> | eeprom |
+---+ ++
+---+ +-+ +-+
| I2C adapter-2 | --> | demod-1 | --> | tuner-1 |
+---+ +-+ +-+
+---+ +-+ +-+
| I2C adapter-3 | --> | demod-2 | --> | tuner-2 |
+---+ +-+ +-+


I have to find out af9015 datasheets and check how it is there. But I still
remember one case where I implemented one FX2 firmware and that same issues
raises there as well.


After that both af9015+mxl5007t and af9035+mxl5007t started working.
Earlier
both were returning bogus values for chip id read.

Also I am interested to known which kind of communication there is
actually
seen on I2C bus?



With this or the patch I proposed, you see exactly what you expect on
the I2C bus with repeated stops, as detailed in my previous mails.



So it is good?



Yes, I2C looks good.


If it starts working then have to find out way to fix it properly so that
any earlier device didn't broke.



I hope that by now I've made abundantly clear that my mxl5007t locks
up after *any* read.  It doesn't matter if we are reading the correct
register after any of the proposed patches.



So it still locks up after any read after the chip id read? And does not
work then? On my devices I can add multiple mxl5007t_get_chip_id() calls and
all are returning correct values.



No

Re: AVerMedia HD Volar (A867) AF9035 + MXL5007T driver issues

2016-04-09 Thread Antti Palosaari



On 04/09/2016 07:11 PM, Alessandro Radicati wrote:

On Sat, Apr 9, 2016 at 4:25 PM, Antti Palosaari  wrote:

On 04/09/2016 11:13 AM, Alessandro Radicati wrote:


On Sat, Apr 9, 2016 at 4:17 AM, Antti Palosaari  wrote:


On 04/09/2016 04:52 AM, Alessandro Radicati wrote:



On Sat, Apr 9, 2016 at 3:22 AM, Antti Palosaari  wrote:



Here is patches to test:
http://git.linuxtv.org/anttip/media_tree.git/log/?h=af9035



I've done this already in my testing, and it works for getting a
correct chip_id response, but only because it's avoiding the issue
with the write/read case in the af9035 driver.  Don't have an
af9015... perhaps there's a similar issue with that code or we are
dealing with two separate issues since af9035 never does a repeated
start?




I am pretty sure mxl5007t requires stop between read and write. Usually
chips are not caring too much if it is repeated start or not, whilst
datasheets are often register read is S Wr S Rw P.

Even af9035 i2c adapter implementation implements repeated start wrong, I



Where does the assumption that CMD_I2C_RD should issue a repeated
start sequence come from?  From the datasheet?  Maybe it was never
intended as repeated start.  Perhaps if there is another stick  with
mxl5007t and a chip that does repeated start, we can put this to bed.



Assumption was coming from it just does it as a single USB transaction.
Datasheet says there is no repeated start. And kernel I2C API says all
messages send using single i2c_transfer() should be send with repeated
start, so now it is violating it, but that's not the biggest problem...



Unfortunately there is no way around that problem, but at least it
means that you can reduce the whole function to just read and write
since at the I2C level nothing changes.


would not like to add anymore hacks there. It is currently ugly and
complex



Bugfix != hack.  Don't see how putting the register address in the
address fields is a hack (perhaps semantics around the fact that 0xFB
is not really part of the address?); this is the only and intended way
to use that command for write/read.



I did bunch of testing and find it is really wrong. Dumped out registers
from some tuner chips and those seems to be mostly off by one.

I think that skeleton is correct way (and it ends about same you did)
if (msg[0].len == 0) // probe message, payload 0
   buf[0] = msg[0].len;
   buf[1] = msg[0].addr << 1;
   buf[2] = 0x00; /* reg addr len */
   buf[3] = 0x00; /* reg addr MSB */
   buf[4] = 0x00; /* reg addr LSB */
else if (msg[0].len == 1)
   buf[0] = msg[0].len;
   buf[1] = msg[0].addr << 1;
   buf[2] = 1; /* reg addr len */
   buf[3] = 0x00; /* reg addr MSB */
   buf[4] = msg[0].buf[0]; /* reg addr LSB */
else if (msg[0].len == 2)
   buf[0] = msg[0].len;
   buf[1] = msg[0].addr << 1;
   buf[2] = 2; /* reg addr len */
   buf[3] = msg[0].buf[0]; /* reg addr MSB */
   buf[4] = msg[0].buf[1]; /* reg addr LSB */
else
   buf[0] = msg[0].len;
   buf[1] = msg[0].addr << 1;
   buf[2] = 2; /* reg addr len */
   buf[3] = msg[0].buf[0]; /* reg addr MSB */
   buf[4] = msg[0].buf[1]; /* reg addr LSB */
   memcpy(&buf[5], msg[2].buf, msg[0].len - 2);



Yes, this is the same, except I kept the original behavior when write
len > 2.  Hence with my patch the I2C bus would only see a read
transaction.  With the above, you would write the first two bytes and
ignore the rest, then read.  This may be worse than just doing a read
because if a future tuner reg read setup/address is > 2 then you may
get into a strange situation.  If that case needs to be addressed,
then might as well get rid of the single write/read usb transaction
and just support write or read.


Last else branch should do it - but no idea if it works at all and none 
of tuners are using it and it is very unlikely there will never be.


It is easy to test, but I suspect if you write S Wr[11 11 12 13] P S Rw 
P it will return value from register 13 on a case chip supports writing 
multiple registers using reg address auto-increment as usually.



as hell. I should be re-written totally in any case. Those tuner I2C
adapters should be moved to demod. Demod has 1 I2C adapter. USB-bridge
has 2
adapters, one for each demod.



Agreed that it can be refactored and improved.  Also to support n
transactions with a simple while loop and only issuing single writes
and reads.  Only downside would be increased USB traffic for 2
commands vs 1 - hence negligible.



there is i2c_adapter_quirks nowadays for these adapters which could do only
limited set of commands.
include/linux/i2c.h


Perhaps just supporting write or read can be done with:

struct i2c_adapter_quirks just_rw = {
.flags=0,
.max_num_msgs=1,
.max_write_len=40,
.max_read_len=40,
};

Otherwise as is:

struct i2c_adapter_quirks as_is = {
.flags=I2C_AQ_COMB_WRITE_THEN_READ,
.max_num_msgs=2,
.max_write_len=40,
.max_read_len=40,
.max_comb_1st_msg_len=2,
.max_comb_2nd_msg_len

[GIT PULL 4.6] m88ds3103 fix

2016-04-10 Thread Antti Palosaari
That is actually bug fix for 3.19+, but according to my tests its effect 
is very minor, so no need for stable. It fixes demod carrier offset 
calculation.



The following changes since commit da470473c9cf9c4ebb40d046b306c76427b6df94:

  [media] media: au0828 fix to clear enable/disable/change source 
handlers (2016-03-13 10:12:53 -0300)


are available in the git repository at:

  git://linuxtv.org/anttip/media_tree.git m88ds3103_fix

for you to fetch changes up to d717c129756c46321e277045706c70f602595ba1:

  m88ds3103: fix undefined division (2016-04-11 01:07:59 +0300)


Peter Rosin (1):
  m88ds3103: fix undefined division

 drivers/media/dvb-frontends/m88ds3103_priv.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--
http://palosaari.fi/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Fwd: [Bug 116551] media_gobj_create NULL pointer dereference

2016-04-17 Thread Antti Palosaari

Can you look that bug as I think it is media controller related.

regards
Antti


 Forwarded Message 
Subject: [Bug 116551] media_gobj_create NULL pointer dereference
Date: Sat, 16 Apr 2016 20:40:18 +
From: bugzilla-dae...@bugzilla.kernel.org
To: cr...@iki.fi

https://bugzilla.kernel.org/show_bug.cgi?id=116551

Konstantin Nikiforov  changed:

   What|Removed |Added

 CC||cr...@iki.fi

--
You are receiving this mail because:
You are on the CC list for the bug.


--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] [media] af9035: fix for MXL5007T devices with I2C read issues

2016-04-19 Thread Antti Palosaari

Hello
I am not happy with that new module parameter as I cannot see real need 
for it. So get rid of it.


Better to compare both VID and PID when enabling that work-around. 
Driver supports currently quite many different USB IDs and there is 
still small risk duplicate PID will exists at some point enabling 
work-around for wrong device.


regards
Antti



On 04/15/2016 06:37 PM, Alessandro Radicati wrote:

The MXL5007T tuner will lock-up on some devices after an I2C read
transaction.  This patch adds a kernel module parameter "no_read" to work
around this issue by inhibiting such operations and emulating a 0x00
response.  The workaround is applied automatically to USB product IDs known
to exhibit this flaw, unless the kernel module parameter is specified.

Signed-off-by: Alessandro Radicati 
---
  drivers/media/usb/dvb-usb-v2/af9035.c | 27 +++
  drivers/media/usb/dvb-usb-v2/af9035.h |  1 +
  2 files changed, 28 insertions(+)

diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c 
b/drivers/media/usb/dvb-usb-v2/af9035.c
index 2638e32..8225403 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.c
+++ b/drivers/media/usb/dvb-usb-v2/af9035.c
@@ -24,6 +24,10 @@
  /* Max transfer size done by I2C transfer functions */
  #define MAX_XFER_SIZE  64

+static int dvb_usb_af9035_no_read = -1;
+module_param_named(no_read, dvb_usb_af9035_no_read, int, 0644);
+MODULE_PARM_DESC(no_read, "Emulate I2C reads for devices that do not support 
them.");
+
  DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);

  static u16 af9035_checksum(const u8 *buf, size_t len)
@@ -348,6 +352,9 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,

ret = af9035_rd_regs(d, reg, &msg[1].buf[0],
msg[1].len);
+   } else if (state->no_read) {
+   memset(msg[1].buf, 0, msg[1].len);
+   ret = 0;
} else {
/* I2C write + read */
u8 buf[MAX_XFER_SIZE];
@@ -421,6 +428,9 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
if (msg[0].len > 40) {
/* TODO: correct limits > 40 */
ret = -EOPNOTSUPP;
+   } else if (state->no_read) {
+   memset(msg[0].buf, 0, msg[0].len);
+   ret = 0;
} else {
/* I2C read */
u8 buf[5];
@@ -962,6 +972,23 @@ skip_eeprom:
state->af9033_config[i].clock = clock_lut_af9035[tmp];
}

+   /* Some MXL5007T devices cannot properly handle tuner I2C read ops. */
+   if (dvb_usb_af9035_no_read != -1) { /* Override with module param */
+   state->no_read = dvb_usb_af9035_no_read == 0 ? false : true;
+   } else {
+   switch (le16_to_cpu(d->udev->descriptor.idProduct)) {
+   case USB_PID_AVERMEDIA_A867:
+   case USB_PID_AVERMEDIA_TWINSTAR:
+   dev_info(&d->udev->dev,
+   "%s: Device may have issues with I2C read 
operations. Enabling fix.\n",
+   KBUILD_MODNAME);
+   state->no_read = true;
+   break;
+   default:
+   state->no_read = false;
+   }
+   }
+
return 0;

  err:
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.h 
b/drivers/media/usb/dvb-usb-v2/af9035.h
index df22001..a76dafa 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.h
+++ b/drivers/media/usb/dvb-usb-v2/af9035.h
@@ -62,6 +62,7 @@ struct state {
u8 chip_version;
u16 chip_type;
u8 dual_mode:1;
+   u8 no_read:1;
u16 eeprom_addr;
u8 af9033_i2c_addr[2];
struct af9033_config af9033_config[2];



--
http://palosaari.fi/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] [media] af9035: fix for MXL5007T devices with I2C read issues

2016-04-20 Thread Antti Palosaari

On 04/20/2016 12:13 PM, Alex Rad wrote:

On Wed, Apr 20, 2016 at 1:02 AM, Antti Palosaari  wrote:

Hello
I am not happy with that new module parameter as I cannot see real need for
it. So get rid of it.


My reasoning for this is:
1) We know of just two devices which may have the issue, but there are
probably more.  The module parameter allows a user to apply the
workaround to other devices we did not consider or test.  Should we
perhaps apply for all mxl5007t devices?


So what. It is easier for me add just new IDs to driver when problematic 
device is found than adding new module parameter which allows user to 
work-around issues and I will likely newer even hear about those issues.



2) Not all devices that match VID and PID have the issue, so it allows
the user to disable the workaround.


Due to that better to add three checks
1) it is Avermedia VID
2) it is known problematic Avermedia device PID
3) it has tuner MxL5007t

It is not surprise it is just only Avermedia which has this kind of 
problems. Not first time at all. I have added such Avermedia hacks for 
af9015 driver too and if you look af9035 there is tuner id hack - which 
was added also due to Avermedia.


Worst case there could be is some mxl5007t device having reference 
design ID. But even on that case returning fake values is pretty much OK.



regards
Antti



Better to compare both VID and PID when enabling that work-around. Driver
supports currently quite many different USB IDs and there is still small
risk duplicate PID will exists at some point enabling work-around for wrong
device.



OK.  Will wait for comments on above before a v2.

Thanks,
Alessandro


regards
Antti




On 04/15/2016 06:37 PM, Alessandro Radicati wrote:


The MXL5007T tuner will lock-up on some devices after an I2C read
transaction.  This patch adds a kernel module parameter "no_read" to work
around this issue by inhibiting such operations and emulating a 0x00
response.  The workaround is applied automatically to USB product IDs
known
to exhibit this flaw, unless the kernel module parameter is specified.

Signed-off-by: Alessandro Radicati 
---
   drivers/media/usb/dvb-usb-v2/af9035.c | 27 +++
   drivers/media/usb/dvb-usb-v2/af9035.h |  1 +
   2 files changed, 28 insertions(+)

diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c
b/drivers/media/usb/dvb-usb-v2/af9035.c
index 2638e32..8225403 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.c
+++ b/drivers/media/usb/dvb-usb-v2/af9035.c
@@ -24,6 +24,10 @@
   /* Max transfer size done by I2C transfer functions */
   #define MAX_XFER_SIZE  64

+static int dvb_usb_af9035_no_read = -1;
+module_param_named(no_read, dvb_usb_af9035_no_read, int, 0644);
+MODULE_PARM_DESC(no_read, "Emulate I2C reads for devices that do not
support them.");
+
   DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);

   static u16 af9035_checksum(const u8 *buf, size_t len)
@@ -348,6 +352,9 @@ static int af9035_i2c_master_xfer(struct i2c_adapter
*adap,

 ret = af9035_rd_regs(d, reg, &msg[1].buf[0],
 msg[1].len);
+   } else if (state->no_read) {
+   memset(msg[1].buf, 0, msg[1].len);
+   ret = 0;
 } else {
 /* I2C write + read */
 u8 buf[MAX_XFER_SIZE];
@@ -421,6 +428,9 @@ static int af9035_i2c_master_xfer(struct i2c_adapter
*adap,
 if (msg[0].len > 40) {
 /* TODO: correct limits > 40 */
 ret = -EOPNOTSUPP;
+   } else if (state->no_read) {
+   memset(msg[0].buf, 0, msg[0].len);
+   ret = 0;
 } else {
 /* I2C read */
 u8 buf[5];
@@ -962,6 +972,23 @@ skip_eeprom:
 state->af9033_config[i].clock =
clock_lut_af9035[tmp];
 }

+   /* Some MXL5007T devices cannot properly handle tuner I2C read
ops. */
+   if (dvb_usb_af9035_no_read != -1) { /* Override with module param
*/
+   state->no_read = dvb_usb_af9035_no_read == 0 ? false :
true;
+   } else {
+   switch (le16_to_cpu(d->udev->descriptor.idProduct)) {
+   case USB_PID_AVERMEDIA_A867:
+   case USB_PID_AVERMEDIA_TWINSTAR:
+   dev_info(&d->udev->dev,
+   "%s: Device may have issues with I2C read
operations. Enabling fix.\n",
+   KBUILD_MODNAME);
+   state->no_read = true;
+   break;
+   default:
+   state->no_read = false;
+   }
+   }
+
 return 0;

   err:
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.h
b/drivers/media/usb/dvb-usb-v2/af9035.h
index df22001..a76dafa 100644
--- a/drivers/media/us

Re: [PATCH v7 00/24] i2c mux cleanup and locking update

2016-04-20 Thread Antti Palosaari

On 04/20/2016 06:17 PM, Peter Rosin wrote:

Retested all the previously tested + now I tested also cx231xx with 
Hauppauge 930C HD device having eeprom other mux port and demod on the 
other port.



   [media] si2168: change the i2c gate to be mux-locked
   [media] m88ds3103: convert to use an explicit i2c mux core
   [media] rtl2830: convert to use an explicit i2c mux core
   [media] rtl2832: convert to use an explicit i2c mux core
   [media] si2168: convert to use an explicit i2c mux core
   [media] cx231xx: convert to use an explicit i2c mux core
   [media] rtl2832: change the i2c gate to be mux-locked
   [media] rtl2832_sdr: get rid of empty regmap wrappers
   [media] rtl2832: regmap is aware of lockdep, drop local locking hack


I really hope that this whole patch series will arrive asap to mainline.

regards
Antti

--
http://palosaari.fi/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] af9035: correct eeprom offsets

2016-04-27 Thread Antti Palosaari
Used memory mapped eeprom offsets were off-by 8 bytes.

Signed-off-by: Antti Palosaari 
---
 drivers/media/usb/dvb-usb-v2/af9035.h | 24 
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/af9035.h 
b/drivers/media/usb/dvb-usb-v2/af9035.h
index df22001..89e629a 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.h
+++ b/drivers/media/usb/dvb-usb-v2/af9035.h
@@ -118,20 +118,20 @@ static const u32 clock_lut_it9135[] = {
  * Values 0, 3 and 5 are seen to this day. 0 for single TS and 3/5 for dual TS.
  */
 
-#define EEPROM_BASE_AF90350x42fd
-#define EEPROM_BASE_IT91350x499c
+#define EEPROM_BASE_AF90350x42f5
+#define EEPROM_BASE_IT91350x4994
 #define EEPROM_SHIFT0x10
 
-#define EEPROM_IR_MODE  0x10
-#define EEPROM_TS_MODE  0x29
-#define EEPROM_2ND_DEMOD_ADDR   0x2a
-#define EEPROM_IR_TYPE  0x2c
-#define EEPROM_1_IF_L   0x30
-#define EEPROM_1_IF_H   0x31
-#define EEPROM_1_TUNER_ID   0x34
-#define EEPROM_2_IF_L   0x40
-#define EEPROM_2_IF_H   0x41
-#define EEPROM_2_TUNER_ID   0x44
+#define EEPROM_IR_MODE  0x18
+#define EEPROM_TS_MODE  0x31
+#define EEPROM_2ND_DEMOD_ADDR   0x32
+#define EEPROM_IR_TYPE  0x34
+#define EEPROM_1_IF_L   0x38
+#define EEPROM_1_IF_H   0x39
+#define EEPROM_1_TUNER_ID   0x3c
+#define EEPROM_2_IF_L   0x48
+#define EEPROM_2_IF_H   0x49
+#define EEPROM_2_TUNER_ID   0x4c
 
 /* USB commands */
 #define CMD_MEM_RD  0x00
-- 
http://palosaari.fi/

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [media-af9013] question about return value in function af9013_wr_regs()

2017-06-09 Thread Antti Palosaari

Gustavo A. R. Silva kirjoitti 2017-06-09 00:51:

Hello everybody,

While looking into Coverity ID 1227035 I ran into the following piece
of code at drivers/media/dvb-frontends/af9013.c:595:



The issue here is that the value stored in variable _ret_ at line 608,
 is not being evaluated as it happens at line 662, 667, 672 and 677.
Then after looking into function af9013_wr_regs(), I noticed that this
 function always returns zero, no matter what, as you can see below:

121static int af9013_wr_regs(struct af9013_state *priv, u16 reg, const  
u8 *val,

122int len)
123{
124int ret, i;
125u8 mbox = (0 << 7)|(0 << 6)|(1 << 1)|(1 << 0);
126
127if ((priv->config.ts_mode == AF9013_TS_USB) &&
128((reg & 0xff00) != 0xff00) && ((reg & 0xff00) != 
0xae00)) {

129mbox |= ((len - 1) << 2);
130ret = af9013_wr_regs_i2c(priv, mbox, reg, val, len);
131} else {
132for (i = 0; i < len; i++) {
133ret = af9013_wr_regs_i2c(priv, mbox, reg+i,
 val+i, 1);
134if (ret)
135goto err;
136}
137}
138
139err:
140return 0;
141}


That function should return error code on error case, not zero always.


regards
Antti




--
http://palosaari.fi/


Re: [PATCH] dvb-usb-af9035: load HID table

2017-06-10 Thread Antti Palosaari

Hello

Jaroslav Škarvada kirjoitti 2017-06-09 20:46:

Automatically load sniffed HID table from Windows driver if
USB_VID_ITETECH:USB_PID_ITETECH_IT9135_9006 device is present (e.g. 
Evolveo

Mars) or if module parameter force_hid_tab_load is set.


There is few issues I don't like this approach. Mostly that module 
parameter to select HID table. There is existing solution to select 
remote controller, it is ir-keytable and it should be used rather than 
defining device specific module parameter.


If you look that HID table you could see there is 4 bytes NEC code and 3 
bytes HID code. Remote controller seems to have 34 keys. Remote 
controller address bytes are 0x02bd, grepping existing remote controller 
keytables it could be Total Media In Hand remote controller 
(rc-total-media-in-hand.c). If not, then defining new keytable is 
needed.


I did some research about issue and found 2 better solutions.
1) Configure HID table dynamically. Remote controller keytable has some 
needed information, but those KEY_* events needed to be translated to 
HID codes somehow.
2) Kill HID and then use CMD_IR_GET to get remote controller scancodes 
by polling.


Solution 1 sounds most correct. No need to poll and decode by sw as hw 
does all the job. But it is most hardest to implement, I am not aware if 
anyone has done it yet.


regards
Antti


--
http://palosaari.fi/


[PATCH 04/15] af9033: use kernel 64-bit division

2017-06-14 Thread Antti Palosaari
Replace own binary division with 64-bit multiply and division.

Signed-off-by: Antti Palosaari 
---
 drivers/media/dvb-frontends/af9013.c  | 34 +++
 drivers/media/dvb-frontends/af9013_priv.h |  1 +
 2 files changed, 4 insertions(+), 31 deletions(-)

diff --git a/drivers/media/dvb-frontends/af9013.c 
b/drivers/media/dvb-frontends/af9013.c
index f644182..dd7ac0a 100644
--- a/drivers/media/dvb-frontends/af9013.c
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -277,33 +277,6 @@ static int af9013_set_gpio(struct af9013_state *state, u8 
gpio, u8 gpioval)
return ret;
 }
 
-static u32 af9013_div(struct af9013_state *state, u32 a, u32 b, u32 x)
-{
-   u32 r = 0, c = 0, i;
-
-   dev_dbg(&state->client->dev, "%s: a=%d b=%d x=%d\n", __func__, a, b, x);
-
-   if (a > b) {
-   c = a / b;
-   a = a - c * b;
-   }
-
-   for (i = 0; i < x; i++) {
-   if (a >= b) {
-   r += 1;
-   a -= b;
-   }
-   a <<= 1;
-   r <<= 1;
-   }
-   r = (c << (u32)x) + r;
-
-   dev_dbg(&state->client->dev, "%s: a=%d b=%d x=%d r=%d r=%x\n",
-   __func__, a, b, x, r, r);
-
-   return r;
-}
-
 static int af9013_power_ctrl(struct af9013_state *state, u8 onoff)
 {
int ret, i;
@@ -638,8 +611,8 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
spec_inv = !state->spec_inv;
}
 
-   freq_cw = af9013_div(state, sampling_freq, state->clk,
-   23);
+   freq_cw = DIV_ROUND_CLOSEST_ULL((u64)sampling_freq * 0x80,
+   state->clk);
 
if (spec_inv)
freq_cw = 0x80 - freq_cw;
@@ -1108,11 +1081,10 @@ static int af9013_init(struct dvb_frontend *fe)
return -EINVAL;
}
 
-   adc_cw = af9013_div(state, state->clk, 100ul, 19);
+   adc_cw = div_u64((u64)state->clk * 0x8, 100);
buf[0] = (adc_cw >>  0) & 0xff;
buf[1] = (adc_cw >>  8) & 0xff;
buf[2] = (adc_cw >> 16) & 0xff;
-
ret = af9013_wr_regs(state, 0xd180, buf, 3);
if (ret)
goto err;
diff --git a/drivers/media/dvb-frontends/af9013_priv.h 
b/drivers/media/dvb-frontends/af9013_priv.h
index 31d6538..97b5b0c 100644
--- a/drivers/media/dvb-frontends/af9013_priv.h
+++ b/drivers/media/dvb-frontends/af9013_priv.h
@@ -24,6 +24,7 @@
 #include "dvb_frontend.h"
 #include "af9013.h"
 #include 
+#include 
 
 #define AF9013_FIRMWARE "dvb-fe-af9013.fw"
 
-- 
http://palosaari.fi/



[PATCH 06/15] af9013: convert to regmap api

2017-06-14 Thread Antti Palosaari
Use regmap for register access. Own low level i2c read and write
routines for regmap is still needed because chip uses single command
byte in addition to typical i2c register access.

Signed-off-by: Antti Palosaari 
---
 drivers/media/dvb-frontends/Kconfig   |   1 +
 drivers/media/dvb-frontends/af9013.c  | 598 +++---
 drivers/media/dvb-frontends/af9013_priv.h |   1 +
 3 files changed, 294 insertions(+), 306 deletions(-)

diff --git a/drivers/media/dvb-frontends/Kconfig 
b/drivers/media/dvb-frontends/Kconfig
index e8c6554..3a260b8 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -436,6 +436,7 @@ config DVB_TDA10048
 config DVB_AF9013
tristate "Afatech AF9013 demodulator"
depends on DVB_CORE && I2C
+   select REGMAP
default m if !MEDIA_SUBDRV_AUTOSELECT
help
  Say Y when you want to support this frontend.
diff --git a/drivers/media/dvb-frontends/af9013.c 
b/drivers/media/dvb-frontends/af9013.c
index 781e958..70102c1 100644
--- a/drivers/media/dvb-frontends/af9013.c
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -20,11 +20,9 @@
 
 #include "af9013_priv.h"
 
-/* Max transfer size done by I2C transfer functions */
-#define MAX_XFER_SIZE  64
-
 struct af9013_state {
struct i2c_client *client;
+   struct regmap *regmap;
struct dvb_frontend fe;
u32 clk;
u8 tuner;
@@ -50,181 +48,6 @@ struct af9013_state {
struct delayed_work statistics_work;
 };
 
-/* write multiple registers */
-static int af9013_wr_regs_i2c(struct af9013_state *state, u8 mbox, u16 reg,
-   const u8 *val, int len)
-{
-   struct i2c_client *client = state->client;
-   int ret;
-   u8 buf[MAX_XFER_SIZE];
-   struct i2c_msg msg[1] = {
-   {
-   .addr = state->client->addr,
-   .flags = 0,
-   .len = 3 + len,
-   .buf = buf,
-   }
-   };
-
-   if (3 + len > sizeof(buf)) {
-   dev_warn(&client->dev, "i2c wr reg %04x, len %d, is too big!\n",
-reg, len);
-   return -EINVAL;
-   }
-
-   buf[0] = (reg >> 8) & 0xff;
-   buf[1] = (reg >> 0) & 0xff;
-   buf[2] = mbox;
-   memcpy(&buf[3], val, len);
-
-   ret = i2c_transfer(state->client->adapter, msg, 1);
-   if (ret == 1) {
-   ret = 0;
-   } else {
-   dev_warn(&client->dev, "i2c wr failed %d, reg %04x, len %d\n",
-ret, reg, len);
-   ret = -EREMOTEIO;
-   }
-   return ret;
-}
-
-/* read multiple registers */
-static int af9013_rd_regs_i2c(struct af9013_state *state, u8 mbox, u16 reg,
-   u8 *val, int len)
-{
-   struct i2c_client *client = state->client;
-   int ret;
-   u8 buf[3];
-   struct i2c_msg msg[2] = {
-   {
-   .addr = state->client->addr,
-   .flags = 0,
-   .len = 3,
-   .buf = buf,
-   }, {
-   .addr = state->client->addr,
-   .flags = I2C_M_RD,
-   .len = len,
-   .buf = val,
-   }
-   };
-
-   buf[0] = (reg >> 8) & 0xff;
-   buf[1] = (reg >> 0) & 0xff;
-   buf[2] = mbox;
-
-   ret = i2c_transfer(state->client->adapter, msg, 2);
-   if (ret == 2) {
-   ret = 0;
-   } else {
-   dev_warn(&client->dev, "i2c rd failed %d, reg %04x, len %d\n",
-ret, reg, len);
-   ret = -EREMOTEIO;
-   }
-   return ret;
-}
-
-/* write multiple registers */
-static int af9013_wr_regs(struct af9013_state *state, u16 reg, const u8 *val,
-   int len)
-{
-   int ret, i;
-   u8 mbox = (0 << 7)|(0 << 6)|(1 << 1)|(1 << 0);
-
-   if ((state->ts_mode == AF9013_TS_USB) &&
-   ((reg & 0xff00) != 0xff00) && ((reg & 0xff00) != 0xae00)) {
-   mbox |= ((len - 1) << 2);
-   ret = af9013_wr_regs_i2c(state, mbox, reg, val, len);
-   } else {
-   for (i = 0; i < len; i++) {
-   ret = af9013_wr_regs_i2c(state, mbox, reg+i, val+i, 1);
-   if (ret)
-   goto err;
-   }
-   }
-
-err:
-   return 0;
-}
-
-/* read multiple registers */
-static int af9013_rd_regs(struct af9013_state *state, u16 reg, u8 *val, int 
len)
-{
-   int ret, i;
-   u8 mbox = (0 << 7)|(0 << 6)|(1 << 1)|(0 << 0);
-
-   if ((state->ts_mode == AF9013_TS_USB) &&
-   ((reg & 0xff00) != 0xff00)

[PATCH 12/15] af9013: remove unneeded register writes

2017-06-14 Thread Antti Palosaari
Removed register writes are already chip defaults, are not required,
are set later or belong to AF9015 USB interface.

Signed-off-by: Antti Palosaari 
---
 drivers/media/dvb-frontends/af9013.c | 42 
 1 file changed, 42 deletions(-)

diff --git a/drivers/media/dvb-frontends/af9013.c 
b/drivers/media/dvb-frontends/af9013.c
index 6b86437..63c532a 100644
--- a/drivers/media/dvb-frontends/af9013.c
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -894,11 +894,6 @@ static int af9013_init(struct dvb_frontend *fe)
if (ret)
goto err;
 
-   /* enable ADC */
-   ret = regmap_write(state->regmap, 0xd73a, 0xa4);
-   if (ret)
-   goto err;
-
/* write API version to firmware */
ret = regmap_bulk_write(state->regmap, 0x9bf2, state->api_version, 4);
if (ret)
@@ -935,43 +930,6 @@ static int af9013_init(struct dvb_frontend *fe)
if (ret)
goto err;
 
-   /* set I2C master clock */
-   ret = regmap_write(state->regmap, 0xd416, 0x14);
-   if (ret)
-   goto err;
-
-   /* set 16 embx */
-   ret = regmap_update_bits(state->regmap, 0xd700, 0x02, 0x02);
-   if (ret)
-   goto err;
-
-   /* set no trigger */
-   ret = regmap_update_bits(state->regmap, 0xd700, 0x04, 0x00);
-   if (ret)
-   goto err;
-
-   /* set read-update bit for constellation */
-   ret = regmap_update_bits(state->regmap, 0xd371, 0x02, 0x02);
-   if (ret)
-   goto err;
-
-   /* settings for mp2if */
-   if (state->ts_mode == AF9013_TS_MODE_USB) {
-   /* AF9015 split PSB to 1.5k + 0.5k */
-   ret = regmap_update_bits(state->regmap, 0xd50b, 0x04, 0x04);
-   if (ret)
-   goto err;
-   } else {
-   /* AF9013 set mpeg to full speed */
-   ret = regmap_update_bits(state->regmap, 0xd502, 0x10, 0x10);
-   if (ret)
-   goto err;
-   }
-
-   ret = regmap_update_bits(state->regmap, 0xd520, 0x10, 0x10);
-   if (ret)
-   goto err;
-
/* load OFSM settings */
dev_dbg(&client->dev, "load ofsm settings\n");
len = ARRAY_SIZE(ofsm_init);
-- 
http://palosaari.fi/



[PATCH 09/15] af9015: fix and refactor i2c adapter algo logic

2017-06-14 Thread Antti Palosaari
* fix write+read when write has more than one byte
* remove lock, not needed on that case
* remove useless i2c msg send loop, as we support only write, read and
write+read as one go and nothing more

Signed-off-by: Antti Palosaari 
---
 drivers/media/usb/dvb-usb-v2/af9015.c | 153 ++
 1 file changed, 79 insertions(+), 74 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c 
b/drivers/media/usb/dvb-usb-v2/af9015.c
index 138416c..54c1d47 100644
--- a/drivers/media/usb/dvb-usb-v2/af9015.c
+++ b/drivers/media/usb/dvb-usb-v2/af9015.c
@@ -205,9 +205,9 @@ static int af9015_i2c_xfer(struct i2c_adapter *adap, struct 
i2c_msg msg[],
 {
struct dvb_usb_device *d = i2c_get_adapdata(adap);
struct af9015_state *state = d_to_priv(d);
-   int ret = 0, i = 0;
+   int ret;
u16 addr;
-   u8 uninitialized_var(mbox), addr_len;
+   u8 mbox, addr_len;
struct req_t req;
 
 /*
@@ -232,84 +232,89 @@ Due to that the only way to select correct tuner is use 
demodulator I2C-gate.
| addr 0x3a  | |  addr 0xc6 |
|| ||
 */
-   if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-   return -EAGAIN;
 
-   while (i < num) {
-   if (msg[i].addr == state->af9013_config[0].i2c_addr ||
-   msg[i].addr == state->af9013_config[1].i2c_addr) {
-   addr = msg[i].buf[0] << 8;
-   addr += msg[i].buf[1];
-   mbox = msg[i].buf[2];
-   addr_len = 3;
-   } else {
-   addr = msg[i].buf[0];
-   addr_len = 1;
-   /* mbox is don't care in that case */
-   }
+   if (msg[0].len == 0 || msg[0].flags & I2C_M_RD) {
+   addr = 0x;
+   mbox = 0;
+   addr_len = 0;
+   } else if (msg[0].len == 1) {
+   addr = msg[0].buf[0];
+   mbox = 0;
+   addr_len = 1;
+   } else if (msg[0].len == 2) {
+   addr = msg[0].buf[0] << 8|msg[0].buf[1] << 0;
+   mbox = 0;
+   addr_len = 2;
+   } else {
+   addr = msg[0].buf[0] << 8|msg[0].buf[1] << 0;
+   mbox = msg[0].buf[2];
+   addr_len = 3;
+   }
 
-   if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
-   if (msg[i].len > 3 || msg[i+1].len > 61) {
-   ret = -EOPNOTSUPP;
-   goto error;
-   }
-   if (msg[i].addr == state->af9013_config[0].i2c_addr)
-   req.cmd = READ_MEMORY;
-   else
-   req.cmd = READ_I2C;
-   req.i2c_addr = msg[i].addr;
-   req.addr = addr;
-   req.mbox = mbox;
-   req.addr_len = addr_len;
-   req.data_len = msg[i+1].len;
-   req.data = &msg[i+1].buf[0];
-   ret = af9015_ctrl_msg(d, &req);
-   i += 2;
-   } else if (msg[i].flags & I2C_M_RD) {
-   if (msg[i].len > 61) {
-   ret = -EOPNOTSUPP;
-   goto error;
-   }
-   if (msg[i].addr == state->af9013_config[0].i2c_addr) {
-   ret = -EINVAL;
-   goto error;
-   }
+   if (num == 1 && !(msg[0].flags & I2C_M_RD)) {
+   /* i2c write */
+   if (msg[0].len > 21) {
+   ret = -EOPNOTSUPP;
+   goto err;
+   }
+   if (msg[0].addr == state->af9013_config[0].i2c_addr)
+   req.cmd = WRITE_MEMORY;
+   else
+   req.cmd = WRITE_I2C;
+   req.i2c_addr = msg[0].addr;
+   req.addr = addr;
+   req.mbox = mbox;
+   req.addr_len = addr_len;
+   req.data_len = msg[0].len-addr_len;
+   req.data = &msg[0].buf[addr_len];
+   ret = af9015_ctrl_msg(d, &req);
+   } else if (num == 2 && !(msg[0].flags & I2C_M_RD) &&
+  (msg[1].flags & I2C_M_RD)) {
+   /* i2c write + read */
+   if (msg[0].len > 3 || msg[1].len > 61) {
+   ret = -EOPNOTSUPP;
+   goto err;
+   }
+   if (msg[0].addr == state->af9013_config[0].i2c_addr)
+   req.cmd = READ_MEMOR

[PATCH 08/15] af9013: add dvbv5 cnr

2017-06-14 Thread Antti Palosaari
Add support for DVBv5 CNR.

Signed-off-by: Antti Palosaari 
---
 drivers/media/dvb-frontends/af9013.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/media/dvb-frontends/af9013.c 
b/drivers/media/dvb-frontends/af9013.c
index a6b88ae..68091f2 100644
--- a/drivers/media/dvb-frontends/af9013.c
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -228,6 +228,7 @@ static int af9013_statistics_snr_result(struct dvb_frontend 
*fe)
 {
struct af9013_state *state = fe->demodulator_priv;
struct i2c_client *client = state->client;
+   struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret, i, len;
unsigned int utmp;
u8 buf[3];
@@ -283,6 +284,9 @@ static int af9013_statistics_snr_result(struct dvb_frontend 
*fe)
}
state->snr = utmp * 10; /* dB/10 */
 
+   c->cnr.stat[0].svalue = 1000 * utmp;
+   c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+
return 0;
 err:
dev_dbg(&client->dev, "failed %d\n", ret);
@@ -1508,6 +1512,7 @@ static int af9013_probe(struct i2c_client *client,
 {
struct af9013_state *state;
struct af9013_platform_data *pdata = client->dev.platform_data;
+   struct dtv_frontend_properties *c;
int ret, i;
u8 firmware_version[4];
static const struct regmap_bus regmap_bus = {
@@ -1572,6 +1577,10 @@ static int af9013_probe(struct i2c_client *client,
/* Setup callbacks */
pdata->get_dvb_frontend = af9013_get_dvb_frontend;
 
+   /* Init stats to indicate which stats are supported */
+   c = &state->fe.dtv_property_cache;
+   c->cnr.len = 1;
+
dev_info(&client->dev, "Afatech AF9013 successfully attached\n");
dev_info(&client->dev, "firmware version: %d.%d.%d.%d\n",
 firmware_version[0], firmware_version[1],
-- 
http://palosaari.fi/



[PATCH 05/15] af9013: fix logging

2017-06-14 Thread Antti Palosaari
We can simplify logging as we now have a proper i2c client
to pass for kernel dev_* logging functions.

Signed-off-by: Antti Palosaari 
---
 drivers/media/dvb-frontends/af9013.c | 202 +--
 1 file changed, 100 insertions(+), 102 deletions(-)

diff --git a/drivers/media/dvb-frontends/af9013.c 
b/drivers/media/dvb-frontends/af9013.c
index dd7ac0a..781e958 100644
--- a/drivers/media/dvb-frontends/af9013.c
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -51,14 +51,15 @@ struct af9013_state {
 };
 
 /* write multiple registers */
-static int af9013_wr_regs_i2c(struct af9013_state *priv, u8 mbox, u16 reg,
+static int af9013_wr_regs_i2c(struct af9013_state *state, u8 mbox, u16 reg,
const u8 *val, int len)
 {
+   struct i2c_client *client = state->client;
int ret;
u8 buf[MAX_XFER_SIZE];
struct i2c_msg msg[1] = {
{
-   .addr = priv->client->addr,
+   .addr = state->client->addr,
.flags = 0,
.len = 3 + len,
.buf = buf,
@@ -66,9 +67,8 @@ static int af9013_wr_regs_i2c(struct af9013_state *priv, u8 
mbox, u16 reg,
};
 
if (3 + len > sizeof(buf)) {
-   dev_warn(&priv->client->dev,
-"%s: i2c wr reg=%04x: len=%d is too big!\n",
-KBUILD_MODNAME, reg, len);
+   dev_warn(&client->dev, "i2c wr reg %04x, len %d, is too big!\n",
+reg, len);
return -EINVAL;
}
 
@@ -77,31 +77,32 @@ static int af9013_wr_regs_i2c(struct af9013_state *priv, u8 
mbox, u16 reg,
buf[2] = mbox;
memcpy(&buf[3], val, len);
 
-   ret = i2c_transfer(priv->client->adapter, msg, 1);
+   ret = i2c_transfer(state->client->adapter, msg, 1);
if (ret == 1) {
ret = 0;
} else {
-   dev_warn(&priv->client->dev, "%s: i2c wr failed=%d reg=%04x " \
-   "len=%d\n", KBUILD_MODNAME, ret, reg, len);
+   dev_warn(&client->dev, "i2c wr failed %d, reg %04x, len %d\n",
+ret, reg, len);
ret = -EREMOTEIO;
}
return ret;
 }
 
 /* read multiple registers */
-static int af9013_rd_regs_i2c(struct af9013_state *priv, u8 mbox, u16 reg,
+static int af9013_rd_regs_i2c(struct af9013_state *state, u8 mbox, u16 reg,
u8 *val, int len)
 {
+   struct i2c_client *client = state->client;
int ret;
u8 buf[3];
struct i2c_msg msg[2] = {
{
-   .addr = priv->client->addr,
+   .addr = state->client->addr,
.flags = 0,
.len = 3,
.buf = buf,
}, {
-   .addr = priv->client->addr,
+   .addr = state->client->addr,
.flags = I2C_M_RD,
.len = len,
.buf = val,
@@ -112,31 +113,31 @@ static int af9013_rd_regs_i2c(struct af9013_state *priv, 
u8 mbox, u16 reg,
buf[1] = (reg >> 0) & 0xff;
buf[2] = mbox;
 
-   ret = i2c_transfer(priv->client->adapter, msg, 2);
+   ret = i2c_transfer(state->client->adapter, msg, 2);
if (ret == 2) {
ret = 0;
} else {
-   dev_warn(&priv->client->dev, "%s: i2c rd failed=%d reg=%04x " \
-   "len=%d\n", KBUILD_MODNAME, ret, reg, len);
+   dev_warn(&client->dev, "i2c rd failed %d, reg %04x, len %d\n",
+ret, reg, len);
ret = -EREMOTEIO;
}
return ret;
 }
 
 /* write multiple registers */
-static int af9013_wr_regs(struct af9013_state *priv, u16 reg, const u8 *val,
+static int af9013_wr_regs(struct af9013_state *state, u16 reg, const u8 *val,
int len)
 {
int ret, i;
u8 mbox = (0 << 7)|(0 << 6)|(1 << 1)|(1 << 0);
 
-   if ((priv->ts_mode == AF9013_TS_USB) &&
+   if ((state->ts_mode == AF9013_TS_USB) &&
((reg & 0xff00) != 0xff00) && ((reg & 0xff00) != 0xae00)) {
mbox |= ((len - 1) << 2);
-   ret = af9013_wr_regs_i2c(priv, mbox, reg, val, len);
+   ret = af9013_wr_regs_i2c(state, mbox, reg, val, len);
} else {
for (i = 0; i < len; i++) {
-   ret = af9013_wr_regs_i2c(priv, mbox, reg+i, val+i, 1);
+   ret = af9013_wr_regs_i2c(state, mbox, reg+i, val+i, 1);
if (ret)
goto err;

[PATCH 15/15] af9013: refactor power control

2017-06-14 Thread Antti Palosaari
Move power-up and power-down functionality to init/sleep ops and
get rid of old function.

Fixes and simplifies power-up functionality slightly.

Signed-off-by: Antti Palosaari 
---
 drivers/media/dvb-frontends/af9013.c | 93 ++--
 1 file changed, 36 insertions(+), 57 deletions(-)

diff --git a/drivers/media/dvb-frontends/af9013.c 
b/drivers/media/dvb-frontends/af9013.c
index 40fd2ea..128d915 100644
--- a/drivers/media/dvb-frontends/af9013.c
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -101,59 +101,6 @@ static int af9013_set_gpio(struct af9013_state *state, u8 
gpio, u8 gpioval)
return ret;
 }
 
-static int af9013_power_ctrl(struct af9013_state *state, u8 onoff)
-{
-   struct i2c_client *client = state->client;
-   int ret;
-   unsigned int utmp;
-
-   dev_dbg(&client->dev, "onoff %d\n", onoff);
-
-   /* enable reset */
-   ret = regmap_update_bits(state->regmap, 0xd417, 0x10, 0x10);
-   if (ret)
-   goto err;
-
-   /* start reset mechanism */
-   ret = regmap_write(state->regmap, 0xaeff, 0x01);
-   if (ret)
-   goto err;
-
-   /* wait reset performs */
-   ret = regmap_read_poll_timeout(state->regmap, 0xd417, utmp,
-  (utmp >> 1) & 0x01, 5000, 100);
-   if (ret)
-   goto err;
-
-   if (!((utmp >> 1) & 0x01))
-   return -ETIMEDOUT;
-
-   if (onoff) {
-   /* clear reset */
-   ret = regmap_update_bits(state->regmap, 0xd417, 0x02, 0x00);
-   if (ret)
-   goto err;
-   /* disable reset */
-   ret = regmap_update_bits(state->regmap, 0xd417, 0x10, 0x00);
-   if (ret)
-   goto err;
-   /* power on */
-   ret = regmap_update_bits(state->regmap, 0xd73a, 0x08, 0x00);
-   if (ret)
-   goto err;
-   } else {
-   /* power off */
-   ret = regmap_update_bits(state->regmap, 0xd73a, 0x08, 0x08);
-   if (ret)
-   goto err;
-   }
-
-   return 0;
-err:
-   dev_dbg(&client->dev, "failed %d\n", ret);
-   return ret;
-}
-
 static int af9013_statistics_ber_unc_start(struct dvb_frontend *fe)
 {
struct af9013_state *state = fe->demodulator_priv;
@@ -889,8 +836,18 @@ static int af9013_init(struct dvb_frontend *fe)
 
dev_dbg(&client->dev, "\n");
 
-   /* power on */
-   ret = af9013_power_ctrl(state, 1);
+   /* ADC on */
+   ret = regmap_update_bits(state->regmap, 0xd73a, 0x08, 0x00);
+   if (ret)
+   goto err;
+
+   /* Clear reset */
+   ret = regmap_update_bits(state->regmap, 0xd417, 0x02, 0x00);
+   if (ret)
+   goto err;
+
+   /* Disable reset */
+   ret = regmap_update_bits(state->regmap, 0xd417, 0x10, 0x00);
if (ret)
goto err;
 
@@ -1070,6 +1027,7 @@ static int af9013_sleep(struct dvb_frontend *fe)
struct af9013_state *state = fe->demodulator_priv;
struct i2c_client *client = state->client;
int ret;
+   unsigned int utmp;
 
dev_dbg(&client->dev, "\n");
 
@@ -1081,8 +1039,29 @@ static int af9013_sleep(struct dvb_frontend *fe)
if (ret)
goto err;
 
-   /* power off */
-   ret = af9013_power_ctrl(state, 0);
+   /* Enable reset */
+   ret = regmap_update_bits(state->regmap, 0xd417, 0x10, 0x10);
+   if (ret)
+   goto err;
+
+   /* Start reset execution */
+   ret = regmap_write(state->regmap, 0xaeff, 0x01);
+   if (ret)
+   goto err;
+
+   /* Wait reset performs */
+   ret = regmap_read_poll_timeout(state->regmap, 0xd417, utmp,
+  (utmp >> 1) & 0x01, 5000, 100);
+   if (ret)
+   goto err;
+
+   if (!((utmp >> 1) & 0x01)) {
+   ret = -ETIMEDOUT;
+   goto err;
+   }
+
+   /* ADC off */
+   ret = regmap_update_bits(state->regmap, 0xd73a, 0x08, 0x08);
if (ret)
goto err;
 
-- 
http://palosaari.fi/



[PATCH 02/15] af9013: move config values directly under driver state

2017-06-14 Thread Antti Palosaari
It shorten, as typed chars, access to config values as there is one
pointer less. Also, when config/platform data is passed to driver there
could be some values that are not relevant to store state as such or
not needed to store at all.

Signed-off-by: Antti Palosaari 
---
 drivers/media/dvb-frontends/af9013.c | 62 ++--
 1 file changed, 38 insertions(+), 24 deletions(-)

diff --git a/drivers/media/dvb-frontends/af9013.c 
b/drivers/media/dvb-frontends/af9013.c
index b978002..7880a63 100644
--- a/drivers/media/dvb-frontends/af9013.c
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -26,7 +26,14 @@
 struct af9013_state {
struct i2c_adapter *i2c;
struct dvb_frontend fe;
-   struct af9013_config config;
+   u8 i2c_addr;
+   u32 clk;
+   u8 tuner;
+   u32 if_frequency;
+   u8 ts_mode;
+   bool spec_inv;
+   u8 api_version[4];
+   u8 gpio[4];
 
/* tuner/demod RF and IF AGC limits used for signal strength calc */
u8 signal_strength_en, rf_50, rf_80, if_50, if_80;
@@ -52,7 +59,7 @@ static int af9013_wr_regs_i2c(struct af9013_state *priv, u8 
mbox, u16 reg,
u8 buf[MAX_XFER_SIZE];
struct i2c_msg msg[1] = {
{
-   .addr = priv->config.i2c_addr,
+   .addr = priv->i2c_addr,
.flags = 0,
.len = 3 + len,
.buf = buf,
@@ -90,12 +97,12 @@ static int af9013_rd_regs_i2c(struct af9013_state *priv, u8 
mbox, u16 reg,
u8 buf[3];
struct i2c_msg msg[2] = {
{
-   .addr = priv->config.i2c_addr,
+   .addr = priv->i2c_addr,
.flags = 0,
.len = 3,
.buf = buf,
}, {
-   .addr = priv->config.i2c_addr,
+   .addr = priv->i2c_addr,
.flags = I2C_M_RD,
.len = len,
.buf = val,
@@ -124,7 +131,7 @@ static int af9013_wr_regs(struct af9013_state *priv, u16 
reg, const u8 *val,
int ret, i;
u8 mbox = (0 << 7)|(0 << 6)|(1 << 1)|(1 << 0);
 
-   if ((priv->config.ts_mode == AF9013_TS_USB) &&
+   if ((priv->ts_mode == AF9013_TS_USB) &&
((reg & 0xff00) != 0xff00) && ((reg & 0xff00) != 0xae00)) {
mbox |= ((len - 1) << 2);
ret = af9013_wr_regs_i2c(priv, mbox, reg, val, len);
@@ -146,7 +153,7 @@ static int af9013_rd_regs(struct af9013_state *priv, u16 
reg, u8 *val, int len)
int ret, i;
u8 mbox = (0 << 7)|(0 << 6)|(1 << 1)|(0 << 0);
 
-   if ((priv->config.ts_mode == AF9013_TS_USB) &&
+   if ((priv->ts_mode == AF9013_TS_USB) &&
((reg & 0xff00) != 0xff00) && ((reg & 0xff00) != 0xae00)) {
mbox |= ((len - 1) << 2);
ret = af9013_rd_regs_i2c(priv, mbox, reg, val, len);
@@ -595,7 +602,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
/* program CFOE coefficients */
if (c->bandwidth_hz != state->bandwidth_hz) {
for (i = 0; i < ARRAY_SIZE(coeff_lut); i++) {
-   if (coeff_lut[i].clock == state->config.clock &&
+   if (coeff_lut[i].clock == state->clk &&
coeff_lut[i].bandwidth_hz == c->bandwidth_hz) {
break;
}
@@ -615,24 +622,24 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
if (fe->ops.tuner_ops.get_if_frequency)
fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
else
-   if_frequency = state->config.if_frequency;
+   if_frequency = state->if_frequency;
 
dev_dbg(&state->i2c->dev, "%s: if_frequency=%d\n",
__func__, if_frequency);
 
sampling_freq = if_frequency;
 
-   while (sampling_freq > (state->config.clock / 2))
-   sampling_freq -= state->config.clock;
+   while (sampling_freq > (state->clk / 2))
+   sampling_freq -= state->clk;
 
if (sampling_freq < 0) {
sampling_freq *= -1;
-   spec_inv = state->config.spec_inv;
+   spec_inv = state->spec_inv;
} else {
-   spec_inv = !state->config.spec_inv;
+   spec_inv = !state->spec_inv;
}
 
-   freq_cw = af9013_div(state, sampling_freq, state->config.clock,

[PATCH 14/15] af9013: refactor firmware download routine

2017-06-14 Thread Antti Palosaari
Refactor firmware download routine.

Signed-off-by: Antti Palosaari 
---
 drivers/media/dvb-frontends/af9013.c | 65 +---
 1 file changed, 30 insertions(+), 35 deletions(-)

diff --git a/drivers/media/dvb-frontends/af9013.c 
b/drivers/media/dvb-frontends/af9013.c
index 63c532a..40fd2ea 100644
--- a/drivers/media/dvb-frontends/af9013.c
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -1136,64 +1136,59 @@ static const struct dvb_frontend_ops af9013_ops;
 static int af9013_download_firmware(struct af9013_state *state)
 {
struct i2c_client *client = state->client;
-   int ret, i, len, remaining;
+   int ret, i, len, rem;
unsigned int utmp;
-   const struct firmware *fw;
+   u8 buf[4];
u16 checksum = 0;
-   u8 fw_params[4];
-   u8 *fw_file = AF9013_FIRMWARE;
+   const struct firmware *firmware;
+   const char *name = AF9013_FIRMWARE;
 
-   msleep(100);
-   /* check whether firmware is already running */
+   dev_dbg(&client->dev, "\n");
+
+   /* Check whether firmware is already running */
ret = regmap_read(state->regmap, 0x98be, &utmp);
if (ret)
goto err;
 
dev_dbg(&client->dev, "firmware status %02x\n", utmp);
 
-   if (utmp == 0x0c) /* fw is running, no need for download */
+   if (utmp == 0x0c)
return 0;
 
dev_info(&client->dev, "found a '%s' in cold state, will try to load a 
firmware\n",
 af9013_ops.info.name);
 
-   /* request the firmware, this will block and timeout */
-   ret = request_firmware(&fw, fw_file, &client->dev);
+   /* Request the firmware, will block and timeout */
+   ret = request_firmware(&firmware, name, &client->dev);
if (ret) {
dev_info(&client->dev, "firmware file '%s' not found %d\n",
-fw_file, ret);
+name, ret);
goto err;
}
 
dev_info(&client->dev, "downloading firmware from file '%s'\n",
-fw_file);
-
-   /* calc checksum */
-   for (i = 0; i < fw->size; i++)
-   checksum += fw->data[i];
+name);
 
-   fw_params[0] = checksum >> 8;
-   fw_params[1] = checksum & 0xff;
-   fw_params[2] = fw->size >> 8;
-   fw_params[3] = fw->size & 0xff;
-
-   /* write fw checksum & size */
-   ret = regmap_bulk_write(state->regmap, 0x50fc, fw_params,
-   sizeof(fw_params));
+   /* Write firmware checksum & size */
+   for (i = 0; i < firmware->size; i++)
+   checksum += firmware->data[i];
 
+   buf[0] = (checksum >> 8) & 0xff;
+   buf[1] = (checksum >> 0) & 0xff;
+   buf[2] = (firmware->size >> 8) & 0xff;
+   buf[3] = (firmware->size >> 0) & 0xff;
+   ret = regmap_bulk_write(state->regmap, 0x50fc, buf, 4);
if (ret)
goto err_release_firmware;
 
-   #define FW_ADDR 0x5100 /* firmware start address */
-   #define LEN_MAX 16 /* max packet size */
-   for (remaining = fw->size; remaining > 0; remaining -= LEN_MAX) {
-   len = remaining;
-   if (len > LEN_MAX)
-   len = LEN_MAX;
-
+   /* Download firmware */
+   #define LEN_MAX 16
+   for (rem = firmware->size; rem > 0; rem -= LEN_MAX) {
+   len = min(LEN_MAX, rem);
ret = regmap_bulk_write(state->regmap,
-   FW_ADDR + fw->size - remaining,
-   &fw->data[fw->size - remaining], len);
+   0x5100 + firmware->size - rem,
+   &firmware->data[firmware->size - rem],
+   len);
if (ret) {
dev_err(&client->dev, "firmware download failed %d\n",
ret);
@@ -1201,9 +1196,9 @@ static int af9013_download_firmware(struct af9013_state 
*state)
}
}
 
-   release_firmware(fw);
+   release_firmware(firmware);
 
-   /* request boot firmware */
+   /* Boot firmware */
ret = regmap_write(state->regmap, 0xe205, 0x01);
if (ret)
goto err;
@@ -1232,7 +1227,7 @@ static int af9013_download_firmware(struct af9013_state 
*state)
 
return 0;
 err_release_firmware:
-   release_firmware(fw);
+   release_firmware(firmware);
 err:
dev_dbg(&client->dev, "failed %d\n", ret);
return ret;
-- 
http://palosaari.fi/



[PATCH 01/15] af9015: use correct 7-bit i2c addresses

2017-06-14 Thread Antti Palosaari
Driver was using wrong "8-bit" i2c addresses for demods and tuners.
Internal demod i2c address was not set at all. These are needed
to be fixed before proper i2c client binding is used.

Signed-off-by: Antti Palosaari 
---
 drivers/media/usb/dvb-usb-v2/af9015.c | 24 +---
 drivers/media/usb/dvb-usb-v2/af9015.h |  4 ++--
 2 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c 
b/drivers/media/usb/dvb-usb-v2/af9015.c
index caa1e61..138416c 100644
--- a/drivers/media/usb/dvb-usb-v2/af9015.c
+++ b/drivers/media/usb/dvb-usb-v2/af9015.c
@@ -36,7 +36,7 @@ static int af9015_ctrl_msg(struct dvb_usb_device *d, struct 
req_t *req)
 
state->buf[0] = req->cmd;
state->buf[1] = state->seq++;
-   state->buf[2] = req->i2c_addr;
+   state->buf[2] = req->i2c_addr << 1;
state->buf[3] = req->addr >> 8;
state->buf[4] = req->addr & 0xff;
state->buf[5] = req->mbox;
@@ -471,6 +471,8 @@ static int af9015_read_config(struct dvb_usb_device *d)
if (d->udev->speed == USB_SPEED_FULL)
state->dual_mode = 0;
 
+   state->af9013_config[0].i2c_addr = AF9015_I2C_DEMOD;
+
if (state->dual_mode) {
/* read 2nd demodulator I2C address */
req.addr = AF9015_EEPROM_DEMOD2_I2C;
@@ -478,7 +480,7 @@ static int af9015_read_config(struct dvb_usb_device *d)
if (ret)
goto error;
 
-   state->af9013_config[1].i2c_addr = val;
+   state->af9013_config[1].i2c_addr = val >> 1;
}
 
for (i = 0; i < state->dual_mode + 1; i++) {
@@ -870,12 +872,12 @@ static int af9015_af9013_frontend_attach(struct 
dvb_usb_adapter *adap)
 }
 
 static struct mt2060_config af9015_mt2060_config = {
-   .i2c_address = 0xc0,
+   .i2c_address = 0x60,
.clock_out = 0,
 };
 
 static struct qt1010_config af9015_qt1010_config = {
-   .i2c_address = 0xc4,
+   .i2c_address = 0x62,
 };
 
 static struct tda18271_config af9015_tda18271_config = {
@@ -884,7 +886,7 @@ static struct tda18271_config af9015_tda18271_config = {
 };
 
 static struct mxl5005s_config af9015_mxl5003_config = {
-   .i2c_address = 0xc6,
+   .i2c_address = 0x63,
.if_freq = IF_FREQ_457HZ,
.xtal_freq   = CRYSTAL_FREQ_1600HZ,
.agc_mode= MXL_SINGLE_AGC,
@@ -901,7 +903,7 @@ static struct mxl5005s_config af9015_mxl5003_config = {
 };
 
 static struct mxl5005s_config af9015_mxl5005_config = {
-   .i2c_address = 0xc6,
+   .i2c_address = 0x63,
.if_freq = IF_FREQ_457HZ,
.xtal_freq   = CRYSTAL_FREQ_1600HZ,
.agc_mode= MXL_SINGLE_AGC,
@@ -918,12 +920,12 @@ static struct mxl5005s_config af9015_mxl5005_config = {
 };
 
 static struct mc44s803_config af9015_mc44s803_config = {
-   .i2c_address = 0xc0,
+   .i2c_address = 0x60,
.dig_out = 1,
 };
 
 static struct tda18218_config af9015_tda18218_config = {
-   .i2c_address = 0xc0,
+   .i2c_address = 0x60,
.i2c_wr_max = 21, /* max wr bytes AF9015 I2C adap can handle at once */
 };
 
@@ -954,7 +956,7 @@ static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
&af9015_qt1010_config) == NULL ? -ENODEV : 0;
break;
case AF9013_TUNER_TDA18271:
-   ret = dvb_attach(tda18271_attach, adap->fe[0], 0xc0,
+   ret = dvb_attach(tda18271_attach, adap->fe[0], 0x60,
&adap_to_d(adap)->i2c_adap,
&af9015_tda18271_config) == NULL ? -ENODEV : 0;
break;
@@ -975,7 +977,7 @@ static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
&af9015_mxl5005_config) == NULL ? -ENODEV : 0;
break;
case AF9013_TUNER_ENV77H11D5:
-   ret = dvb_attach(dvb_pll_attach, adap->fe[0], 0xc0,
+   ret = dvb_attach(dvb_pll_attach, adap->fe[0], 0x60,
&adap_to_d(adap)->i2c_adap,
DVB_PLL_TDA665X) == NULL ? -ENODEV : 0;
break;
@@ -987,7 +989,7 @@ static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
case AF9013_TUNER_MXL5007T:
ret = dvb_attach(mxl5007t_attach, adap->fe[0],
&adap_to_d(adap)->i2c_adap,
-   0xc0, &af9015_mxl5007t_config) == NULL ? -ENODEV : 0;
+   0x60, &af9015_mxl5007t_config) == NULL ? -ENODEV : 0;
break;
case AF9013_TUNER_UNKNOWN:
default:
diff --git a/drivers/media/usb/dvb-usb-v2/af9015.h 
b/drivers/media/usb/dvb-usb-v2/af9015.h
index 2dd9231..3a9d981 100644
--- a/drivers/media/usb/dvb-usb-v2/af9015.h
+++ b/drivers/media/usb/dv

[PATCH 10/15] af9015: enable 2nd TS flow control when dual mode

2017-06-14 Thread Antti Palosaari
It needs to be enabled in order to get stream from slave af9013 demod.

Signed-off-by: Antti Palosaari 
---
 drivers/media/usb/dvb-usb-v2/af9015.c | 15 +--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c 
b/drivers/media/usb/dvb-usb-v2/af9015.c
index 54c1d47..ee0e354 100644
--- a/drivers/media/usb/dvb-usb-v2/af9015.c
+++ b/drivers/media/usb/dvb-usb-v2/af9015.c
@@ -1131,10 +1131,21 @@ static int af9015_init_endpoint(struct dvb_usb_device 
*d)
}
 
/* enable / disable mp2if2 */
-   if (state->dual_mode)
+   if (state->dual_mode) {
ret = af9015_set_reg_bit(d, 0xd50b, 0);
-   else
+   if (ret)
+   goto error;
+   ret = af9015_set_reg_bit(d, 0xd520, 4);
+   if (ret)
+   goto error;
+   } else {
ret = af9015_clear_reg_bit(d, 0xd50b, 0);
+   if (ret)
+   goto error;
+   ret = af9015_clear_reg_bit(d, 0xd520, 4);
+   if (ret)
+   goto error;
+   }
 
 error:
if (ret)
-- 
http://palosaari.fi/



[PATCH 07/15] af9013: fix error handling

2017-06-14 Thread Antti Palosaari
Use typical (return 0/goto err/return err) error handling everywhere.
Add missing error handling where missing.

Signed-off-by: Antti Palosaari 
---
 drivers/media/dvb-frontends/af9013.c | 86 +---
 1 file changed, 51 insertions(+), 35 deletions(-)

diff --git a/drivers/media/dvb-frontends/af9013.c 
b/drivers/media/dvb-frontends/af9013.c
index 70102c1..a6b88ae 100644
--- a/drivers/media/dvb-frontends/af9013.c
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -94,7 +94,7 @@ static int af9013_set_gpio(struct af9013_state *state, u8 
gpio, u8 gpioval)
if (ret)
goto err;
 
-   return ret;
+   return 0;
 err:
dev_dbg(&client->dev, "failed %d\n", ret);
return ret;
@@ -147,7 +147,7 @@ static int af9013_power_ctrl(struct af9013_state *state, u8 
onoff)
goto err;
}
 
-   return ret;
+   return 0;
 err:
dev_dbg(&client->dev, "failed %d\n", ret);
return ret;
@@ -166,7 +166,7 @@ static int af9013_statistics_ber_unc_start(struct 
dvb_frontend *fe)
if (ret)
goto err;
 
-   return ret;
+   return 0;
 err:
dev_dbg(&client->dev, "failed %d\n", ret);
return ret;
@@ -199,7 +199,7 @@ static int af9013_statistics_ber_unc_result(struct 
dvb_frontend *fe)
state->ber = (buf[2] << 16) | (buf[1] << 8) | buf[0];
state->ucblocks += (buf[4] << 8) | buf[3];
 
-   return ret;
+   return 0;
 err:
dev_dbg(&client->dev, "failed %d\n", ret);
return ret;
@@ -218,7 +218,7 @@ static int af9013_statistics_snr_start(struct dvb_frontend 
*fe)
if (ret)
goto err;
 
-   return ret;
+   return 0;
 err:
dev_dbg(&client->dev, "failed %d\n", ret);
return ret;
@@ -283,7 +283,7 @@ static int af9013_statistics_snr_result(struct dvb_frontend 
*fe)
}
state->snr = utmp * 10; /* dB/10 */
 
-   return ret;
+   return 0;
 err:
dev_dbg(&client->dev, "failed %d\n", ret);
return ret;
@@ -321,7 +321,7 @@ static int af9013_statistics_signal_strength(struct 
dvb_frontend *fe)
 
state->signal_strength = signal_strength;
 
-   return ret;
+   return 0;
 err:
dev_dbg(&client->dev, "failed %d\n", ret);
return ret;
@@ -398,8 +398,11 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
c->frequency, c->bandwidth_hz);
 
/* program tuner */
-   if (fe->ops.tuner_ops.set_params)
-   fe->ops.tuner_ops.set_params(fe);
+   if (fe->ops.tuner_ops.set_params) {
+   ret = fe->ops.tuner_ops.set_params(fe);
+   if (ret)
+   goto err;
+   }
 
/* program CFOE coefficients */
if (c->bandwidth_hz != state->bandwidth_hz) {
@@ -411,20 +414,28 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
}
 
/* Return an error if can't find bandwidth or the right clock */
-   if (i == ARRAY_SIZE(coeff_lut))
-   return -EINVAL;
+   if (i == ARRAY_SIZE(coeff_lut)) {
+   ret = -EINVAL;
+   goto err;
+   }
 
ret = regmap_bulk_write(state->regmap, 0xae00, coeff_lut[i].val,
sizeof(coeff_lut[i].val));
+   if (ret)
+   goto err;
}
 
/* program frequency control */
if (c->bandwidth_hz != state->bandwidth_hz || state->first_tune) {
/* get used IF frequency */
-   if (fe->ops.tuner_ops.get_if_frequency)
-   fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
-   else
+   if (fe->ops.tuner_ops.get_if_frequency) {
+   ret = fe->ops.tuner_ops.get_if_frequency(fe,
+&if_frequency);
+   if (ret)
+   goto err;
+   } else {
if_frequency = state->if_frequency;
+   }
 
dev_dbg(&client->dev, "if_frequency %u\n", if_frequency);
 
@@ -659,7 +670,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
state->set_frontend_jiffies = jiffies;
state->first_tune = false;
 
-   return ret;
+   return 0;
 err:
dev_dbg(&client->dev, "failed %d\n", ret);
return ret;
@@ -777,7 +788,7 @@ static int af9013_get_frontend(struct dvb_frontend *fe,
break;
}
 
-   return ret;
+   return 0;
 err:
dev_dbg(&client->dev, "failed %d\n", ret);
 

[PATCH 13/15] af9015: move 2nd demod power-up wait different location

2017-06-14 Thread Antti Palosaari
We need to wait 2nd demod power-up before download firmware. Move
that wait to more correct location.

Signed-off-by: Antti Palosaari 
---
 drivers/media/usb/dvb-usb-v2/af9015.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c 
b/drivers/media/usb/dvb-usb-v2/af9015.c
index ee0e354..53d478d 100644
--- a/drivers/media/usb/dvb-usb-v2/af9015.c
+++ b/drivers/media/usb/dvb-usb-v2/af9015.c
@@ -740,9 +740,6 @@ static int af9015_copy_firmware(struct dvb_usb_device *d)
fw_params[2] = state->firmware_checksum >> 8;
fw_params[3] = state->firmware_checksum & 0xff;
 
-   /* wait 2nd demodulator ready */
-   msleep(100);
-
ret = af9015_read_reg_i2c(d, state->af9013_config[1].i2c_addr,
0x98be, &val);
if (ret)
@@ -830,6 +827,9 @@ static int af9015_af9013_frontend_attach(struct 
dvb_usb_adapter *adap)
 
/* copy firmware to 2nd demodulator */
if (state->dual_mode) {
+   /* Wait 2nd demodulator ready */
+   msleep(100);
+
ret = af9015_copy_firmware(adap_to_d(adap));
if (ret) {
dev_err(&adap_to_d(adap)->udev->dev,
-- 
http://palosaari.fi/



[PATCH 11/15] af9013: add configurable TS output pin

2017-06-14 Thread Antti Palosaari
On serial TS mode output pin could be selected from D0 or D7.
Add configuration option to for it.

Rename TS mode config option prefix from AF9013_TS_ to AF9013_TS_MODE_.

Signed-off-by: Antti Palosaari 
---
 drivers/media/dvb-frontends/af9013.c | 27 ++-
 drivers/media/dvb-frontends/af9013.h |  2 ++
 2 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/drivers/media/dvb-frontends/af9013.c 
b/drivers/media/dvb-frontends/af9013.c
index 68091f2..6b86437 100644
--- a/drivers/media/dvb-frontends/af9013.c
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -28,6 +28,7 @@ struct af9013_state {
u8 tuner;
u32 if_frequency;
u8 ts_mode;
+   u8 ts_output_pin;
bool spec_inv;
u8 api_version[4];
u8 gpio[4];
@@ -955,17 +956,12 @@ static int af9013_init(struct dvb_frontend *fe)
goto err;
 
/* settings for mp2if */
-   if (state->ts_mode == AF9013_TS_USB) {
+   if (state->ts_mode == AF9013_TS_MODE_USB) {
/* AF9015 split PSB to 1.5k + 0.5k */
ret = regmap_update_bits(state->regmap, 0xd50b, 0x04, 0x04);
if (ret)
goto err;
} else {
-   /* AF9013 change the output bit to data7 */
-   ret = regmap_update_bits(state->regmap, 0xd500, 0x08, 0x08);
-   if (ret)
-   goto err;
-
/* AF9013 set mpeg to full speed */
ret = regmap_update_bits(state->regmap, 0xd502, 0x10, 0x10);
if (ret)
@@ -1046,9 +1042,12 @@ static int af9013_init(struct dvb_frontend *fe)
goto err;
}
 
-   /* TS mode */
-   ret = regmap_update_bits(state->regmap, 0xd500, 0x06,
-state->ts_mode << 1);
+   /* TS interface */
+   if (state->ts_output_pin == 7)
+   utmp = 1 << 3 | state->ts_mode << 1;
+   else
+   utmp = 0 << 3 | state->ts_mode << 1;
+   ret = regmap_update_bits(state->regmap, 0xd500, 0x0e, utmp);
if (ret)
goto err;
 
@@ -1147,7 +1146,7 @@ static int af9013_i2c_gate_ctrl(struct dvb_frontend *fe, 
int enable)
if (state->i2c_gate_state == enable)
return 0;
 
-   if (state->ts_mode == AF9013_TS_USB)
+   if (state->ts_mode == AF9013_TS_MODE_USB)
ret = regmap_update_bits(state->regmap, 0xd417, 0x08,
 enable << 3);
else
@@ -1297,6 +1296,7 @@ struct dvb_frontend *af9013_attach(const struct 
af9013_config *config,
pdata.tuner = config->tuner;
pdata.if_frequency = config->if_frequency;
pdata.ts_mode = config->ts_mode;
+   pdata.ts_output_pin = 7;
pdata.spec_inv = config->spec_inv;
memcpy(&pdata.api_version, config->api_version, 
sizeof(pdata.api_version));
memcpy(&pdata.gpio, config->gpio, sizeof(pdata.gpio));
@@ -1450,7 +1450,7 @@ static int af9013_regmap_write(void *context, const void 
*data, size_t count)
u8 *val = &((u8 *)data)[2];
const unsigned int len = count - 2;
 
-   if (state->ts_mode == AF9013_TS_USB && (reg & 0xff00) != 0xae00) {
+   if (state->ts_mode == AF9013_TS_MODE_USB && (reg & 0xff00) != 0xae00) {
cmd = 0 << 7|0 << 6|(len - 1) << 2|1 << 1|1 << 0;
ret = af9013_wregs(client, cmd, reg, val, len);
if (ret)
@@ -1487,7 +1487,7 @@ static int af9013_regmap_read(void *context, const void 
*reg_buf,
u8 *val = &((u8 *)val_buf)[0];
const unsigned int len = val_size;
 
-   if (state->ts_mode == AF9013_TS_USB && (reg & 0xff00) != 0xae00) {
+   if (state->ts_mode == AF9013_TS_MODE_USB && (reg & 0xff00) != 0xae00) {
cmd = 0 << 7|0 << 6|(len - 1) << 2|1 << 1|0 << 0;
ret = af9013_rregs(client, cmd, reg, val_buf, len);
if (ret)
@@ -1537,6 +1537,7 @@ static int af9013_probe(struct i2c_client *client,
state->tuner = pdata->tuner;
state->if_frequency = pdata->if_frequency;
state->ts_mode = pdata->ts_mode;
+   state->ts_output_pin = pdata->ts_output_pin;
state->spec_inv = pdata->spec_inv;
memcpy(&state->api_version, pdata->api_version, 
sizeof(state->api_version));
memcpy(&state->gpio, pdata->gpio, sizeof(state->gpio));
@@ -1549,7 +1550,7 @@ static int af9013_probe(struct i2c_client *client,
}
 
/* Download firmware */
-   if (state->ts_mode != AF9013_TS_USB) {
+   if (state->ts_mode != AF9013_TS_MODE_USB) {
ret = af9013_download_firmware(state);
if (ret)
 

[PATCH 03/15] af9013: add i2c client bindings

2017-06-14 Thread Antti Palosaari
Add kernel i2c driver bindings.
That allows dev_* logging, regmap and more.

Signed-off-by: Antti Palosaari 
---
 drivers/media/dvb-frontends/af9013.c | 321 ++-
 drivers/media/dvb-frontends/af9013.h |  84 +
 2 files changed, 241 insertions(+), 164 deletions(-)

diff --git a/drivers/media/dvb-frontends/af9013.c 
b/drivers/media/dvb-frontends/af9013.c
index 7880a63..f644182 100644
--- a/drivers/media/dvb-frontends/af9013.c
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -24,9 +24,8 @@
 #define MAX_XFER_SIZE  64
 
 struct af9013_state {
-   struct i2c_adapter *i2c;
+   struct i2c_client *client;
struct dvb_frontend fe;
-   u8 i2c_addr;
u32 clk;
u8 tuner;
u32 if_frequency;
@@ -59,7 +58,7 @@ static int af9013_wr_regs_i2c(struct af9013_state *priv, u8 
mbox, u16 reg,
u8 buf[MAX_XFER_SIZE];
struct i2c_msg msg[1] = {
{
-   .addr = priv->i2c_addr,
+   .addr = priv->client->addr,
.flags = 0,
.len = 3 + len,
.buf = buf,
@@ -67,7 +66,7 @@ static int af9013_wr_regs_i2c(struct af9013_state *priv, u8 
mbox, u16 reg,
};
 
if (3 + len > sizeof(buf)) {
-   dev_warn(&priv->i2c->dev,
+   dev_warn(&priv->client->dev,
 "%s: i2c wr reg=%04x: len=%d is too big!\n",
 KBUILD_MODNAME, reg, len);
return -EINVAL;
@@ -78,11 +77,11 @@ static int af9013_wr_regs_i2c(struct af9013_state *priv, u8 
mbox, u16 reg,
buf[2] = mbox;
memcpy(&buf[3], val, len);
 
-   ret = i2c_transfer(priv->i2c, msg, 1);
+   ret = i2c_transfer(priv->client->adapter, msg, 1);
if (ret == 1) {
ret = 0;
} else {
-   dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%04x " \
+   dev_warn(&priv->client->dev, "%s: i2c wr failed=%d reg=%04x " \
"len=%d\n", KBUILD_MODNAME, ret, reg, len);
ret = -EREMOTEIO;
}
@@ -97,12 +96,12 @@ static int af9013_rd_regs_i2c(struct af9013_state *priv, u8 
mbox, u16 reg,
u8 buf[3];
struct i2c_msg msg[2] = {
{
-   .addr = priv->i2c_addr,
+   .addr = priv->client->addr,
.flags = 0,
.len = 3,
.buf = buf,
}, {
-   .addr = priv->i2c_addr,
+   .addr = priv->client->addr,
.flags = I2C_M_RD,
.len = len,
.buf = val,
@@ -113,11 +112,11 @@ static int af9013_rd_regs_i2c(struct af9013_state *priv, 
u8 mbox, u16 reg,
buf[1] = (reg >> 0) & 0xff;
buf[2] = mbox;
 
-   ret = i2c_transfer(priv->i2c, msg, 2);
+   ret = i2c_transfer(priv->client->adapter, msg, 2);
if (ret == 2) {
ret = 0;
} else {
-   dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%04x " \
+   dev_warn(&priv->client->dev, "%s: i2c rd failed=%d reg=%04x " \
"len=%d\n", KBUILD_MODNAME, ret, reg, len);
ret = -EREMOTEIO;
}
@@ -231,7 +230,7 @@ static int af9013_set_gpio(struct af9013_state *state, u8 
gpio, u8 gpioval)
u8 pos;
u16 addr;
 
-   dev_dbg(&state->i2c->dev, "%s: gpio=%d gpioval=%02x\n",
+   dev_dbg(&state->client->dev, "%s: gpio=%d gpioval=%02x\n",
__func__, gpio, gpioval);
 
/*
@@ -250,7 +249,7 @@ static int af9013_set_gpio(struct af9013_state *state, u8 
gpio, u8 gpioval)
break;
 
default:
-   dev_err(&state->i2c->dev, "%s: invalid gpio=%d\n",
+   dev_err(&state->client->dev, "%s: invalid gpio=%d\n",
KBUILD_MODNAME, gpio);
ret = -EINVAL;
goto err;
@@ -274,7 +273,7 @@ static int af9013_set_gpio(struct af9013_state *state, u8 
gpio, u8 gpioval)
 
return ret;
 err:
-   dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+   dev_dbg(&state->client->dev, "%s: failed=%d\n", __func__, ret);
return ret;
 }
 
@@ -282,7 +281,7 @@ static u32 af9013_div(struct af9013_state *state, u32 a, 
u32 b, u32 x)
 {
u32 r = 0, c = 0, i;
 
-   dev_dbg(&state->i2c->dev, "%s: a=%d b=%d x=%d\n", __func__, a, b, x);
+   dev_dbg(&state->client->dev, "%s: a=%d b=%d x=%

[GIT PULL 4.13] af9015/af9013 changes

2017-06-20 Thread Antti Palosaari

The following changes since commit 3622d3e77ecef090b5111e3c5423313f11711dfa:

  [media] ov2640: print error if devm_*_optional*() fails (2017-04-25 
07:08:21 -0300)


are available in the git repository at:

  git://linuxtv.org/anttip/media_tree.git af9015_pull

for you to fetch changes up to 2a32db020ab01e3ac99febad90a42112aa28b2ee:

  af9013: refactor power control (2017-06-18 05:42:25 +0300)


Antti Palosaari (15):
  af9015: use correct 7-bit i2c addresses
  af9013: move config values directly under driver state
  af9013: add i2c client bindings
  af9013: use kernel 64-bit division
  af9013: fix logging
  af9013: convert to regmap api
  af9013: fix error handling
  af9013: add dvbv5 cnr
  af9015: fix and refactor i2c adapter algo logic
  af9015: enable 2nd TS flow control when dual mode
  af9013: add configurable TS output pin
  af9013: remove unneeded register writes
  af9015: move 2nd demod power-up wait different location
  af9013: refactor firmware download routine
  af9013: refactor power control

Gustavo A. R. Silva (1):
  af9013: add check on af9013_wr_regs() return value

 drivers/media/dvb-frontends/Kconfig   |1 +
 drivers/media/dvb-frontends/af9013.c  | 1185 
++-

 drivers/media/dvb-frontends/af9013.h  |   86 +--
 drivers/media/dvb-frontends/af9013_priv.h |2 +
 drivers/media/usb/dvb-usb-v2/af9015.c |  198 +---
 drivers/media/usb/dvb-usb-v2/af9015.h |4 +-
 6 files changed, 752 insertions(+), 724 deletions(-)

--
http://palosaari.fi/


Re: [PATCH] [media] ddbridge: use pr_* macros in favor of printk

2017-06-20 Thread Antti Palosaari

On 06/20/2017 08:44 PM, Daniel Scheller wrote:

From: Daniel Scheller 

Side effect: KERN_DEBUG messages aren't written to the kernel log anymore.
This also improves the tda18212_ping reporting a bit so users know that if
pinging wasn't successful, bad things might happen.


It is device, not library, thus you should really use dev_ logging 
instead. With dev_ logging system could print better info, bus id etc.



regards
Antti


--
http://palosaari.fi/


Re: [PATCH 1/4] [media] dvb-frontends/stv0367: initial DDB DVBv5 stats, implement ucblocks

2017-06-20 Thread Antti Palosaari



On 06/20/2017 08:45 PM, Daniel Scheller wrote:

From: Daniel Scheller 

This adds the basics to stv0367ddb_get_frontend() to be able to properly
provide signal statistics in DVBv5 format. Also adds UCB readout and
provides those values.

Signed-off-by: Daniel Scheller 
---
  drivers/media/dvb-frontends/stv0367.c | 59 ---
  1 file changed, 55 insertions(+), 4 deletions(-)

diff --git a/drivers/media/dvb-frontends/stv0367.c 
b/drivers/media/dvb-frontends/stv0367.c
index e726c2e00460..5374d4eaabd6 100644
--- a/drivers/media/dvb-frontends/stv0367.c
+++ b/drivers/media/dvb-frontends/stv0367.c
@@ -2997,21 +2997,64 @@ static int stv0367ddb_read_status(struct dvb_frontend 
*fe,
return -EINVAL;
  }
  
+static void stv0367ddb_read_ucblocks(struct dvb_frontend *fe)

+{
+   struct stv0367_state *state = fe->demodulator_priv;
+   struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+   u32 ucblocks = 0;
+
+   switch (state->activedemod) {
+   case demod_ter:
+   stv0367ter_read_ucblocks(fe, &ucblocks);
+   break;
+   case demod_cab:
+   stv0367cab_read_ucblcks(fe, &ucblocks);
+   break;
+   default:
+   p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   return;
+   }
+
+   p->block_error.stat[0].scale = FE_SCALE_COUNTER;
+   p->block_error.stat[0].uvalue = ucblocks;
+}
+
  static int stv0367ddb_get_frontend(struct dvb_frontend *fe,
   struct dtv_frontend_properties *p)
  {
struct stv0367_state *state = fe->demodulator_priv;
+   int ret = -EINVAL;
+   enum fe_status status = 0;
  
  	switch (state->activedemod) {

case demod_ter:
-   return stv0367ter_get_frontend(fe, p);
+   ret = stv0367ter_get_frontend(fe, p);
+   break;
case demod_cab:
-   return stv0367cab_get_frontend(fe, p);
-   default:
+   ret = stv0367cab_get_frontend(fe, p);
break;
+   default:
+   p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   return ret;
}
  
-	return -EINVAL;

+   /* read fe lock status */
+   if (!ret)
+   ret = stv0367ddb_read_status(fe, &status);
+
+   /* stop if get_frontend failed or if demod isn't locked */
+   if (ret || !(status & FE_HAS_LOCK)) {
+   p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   return ret;
+   }


Requiring LOCK for strength and cnr sounds wrong. Demod usually 
calculates strength from IF and RF AGC and those are available even 
there is no signal at all (demod set those gains to max on that case). 
CNR is pretty often available when inner FEC (viterbi, LDPC) is on sync.


And for ber and per you need outer fec (reed-solomon, bch) too which is 
FE_HAS_SYNC flag on api. ber is error bit and count after inner fec, per 
is error packet and count after outer fec. Usually ber is counted as a 
bits and per is counted as a 204 ts packets.


Also having that statistics stuff updated inside a get_frontend() sounds 
wrong. I think that callback is optional and is not called unless 
userspace polls it.




+
+   stv0367ddb_read_ucblocks(fe);
+
+   return 0;
  }
  
  static int stv0367ddb_sleep(struct dvb_frontend *fe)

@@ -3035,6 +3078,7 @@ static int stv0367ddb_sleep(struct dvb_frontend *fe)
  static int stv0367ddb_init(struct stv0367_state *state)
  {
struct stv0367ter_state *ter_state = state->ter_state;
+   struct dtv_frontend_properties *p = &state->fe.dtv_property_cache;
  
  	stv0367_writereg(state, R367TER_TOPCTRL, 0x10);
  
@@ -3109,6 +3153,13 @@ static int stv0367ddb_init(struct stv0367_state *state)

ter_state->first_lock = 0;
ter_state->unlock_counter = 2;
  
+	p->strength.len = 1;

+   p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   p->cnr.len = 1;
+   p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   p->block_error.len = 1;
+   p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
return 0;
  }
  



regards
Antti

--
http://palosaari.fi/


Re: [PATCH 3/4] [media] dvb-frontends/stv0367: SNR DVBv5 statistics for DVB-C and T

2017-06-20 Thread Antti Palosaari



On 06/20/2017 08:45 PM, Daniel Scheller wrote:

From: Daniel Scheller 

Add signal-to-noise-ratio as provided by the demodulator in decibel scale.
QAM/DVB-C needs some intlog calculation to have usable dB values, OFDM/
DVB-T values from the demod look alright already and are provided as-is.

Signed-off-by: Daniel Scheller 
---
  drivers/media/dvb-frontends/stv0367.c | 33 +
  1 file changed, 33 insertions(+)

diff --git a/drivers/media/dvb-frontends/stv0367.c 
b/drivers/media/dvb-frontends/stv0367.c
index bb498f942ebd..0b13a407df23 100644
--- a/drivers/media/dvb-frontends/stv0367.c
+++ b/drivers/media/dvb-frontends/stv0367.c
@@ -25,6 +25,8 @@
  #include 
  #include 
  
+#include "dvb_math.h"

+
  #include "stv0367.h"
  #include "stv0367_defs.h"
  #include "stv0367_regs.h"
@@ -33,6 +35,9 @@
  /* Max transfer size done by I2C transfer functions */
  #define MAX_XFER_SIZE  64
  
+/* snr logarithmic calc */

+#define INTLOG10X100(x) ((u32) (((u64) intlog10(x) * 100) >> 24))
+
  static int stvdebug;
  module_param_named(debug, stvdebug, int, 0644);
  
@@ -3013,6 +3018,33 @@ static int stv0367ddb_read_status(struct dvb_frontend *fe,

return -EINVAL;
  }
  
+static void stv0367ddb_read_snr(struct dvb_frontend *fe)

+{
+   struct stv0367_state *state = fe->demodulator_priv;
+   struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+   int cab_pwr;
+   u32 regval, tmpval, snrval = 0;
+
+   switch (state->activedemod) {
+   case demod_ter:
+   snrval = stv0367ter_snr_readreg(fe);
+   break;
+   case demod_cab:
+   cab_pwr = stv0367cab_snr_power(fe);
+   regval = stv0367cab_snr_readreg(fe, 0);
+
+   tmpval = (cab_pwr * 320) / regval;
+   snrval = ((tmpval != 0) ? INTLOG10X100(tmpval) : 0) * 100;


How much there will be rounding errors due to that signal/noise 
division? I would convert it to calculation of sums (tip logarithm 
calculation rules).


Also, that INTLOG10X100 is pretty much useless. Use just what 
intlog10/intlog2 offers without yet again another conversion.





+   break;
+   default:
+   p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   return;
+   }
+
+   p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+   p->cnr.stat[0].uvalue = snrval;
+}
+
  static void stv0367ddb_read_ucblocks(struct dvb_frontend *fe)
  {
struct stv0367_state *state = fe->demodulator_priv;
@@ -3069,6 +3101,7 @@ static int stv0367ddb_get_frontend(struct dvb_frontend 
*fe,
}
  
  	stv0367ddb_read_ucblocks(fe);

+   stv0367ddb_read_snr(fe);
  
  	return 0;

  }



regards
Antti

--
http://palosaari.fi/


  1   2   3   4   5   6   7   8   9   10   >