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/


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: [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(>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)
  /**

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 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(>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-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/


[GIT PULL] af9013/af9015 improvements

2018-03-19 Thread Antti Palosaari

The following changes since commit 3f127ce11353fd1071cae9b65bc13add6aec6b90:

  media: em28xx-cards: fix em28xx_duplicate_dev() (2018-03-08 06:06:51 
-0500)


are available in the Git repository at:

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

for you to fetch changes up to 3a11388095b992f0da01238adaec8b68cbad5c09:

  af9015: correct some coding style issues (2018-03-14 01:32:56 +0200)


Antti Palosaari (18):
  af9013: change lock detection slightly
  af9013: dvbv5 signal strength
  af9013: dvbv5 cnr
  af9013: dvbv5 ber and per
  af9013: wrap dvbv3 statistics via dvbv5
  af9015: fix logging
  af9013: convert inittabs suitable for regmap_update_bits
  af9013: add i2c mux adapter for tuner bus
  af9015: attach demod using i2c binding
  af9013: remove all legacy media attach releated stuff
  af9013: add pid filter support
  af9015: use af9013 demod pid filters
  af9015: refactor firmware download
  af9015: refactor copy firmware to slave demod
  af9015: enhance streaming config
  dvb-usb-v2: add probe/disconnect callbacks
  af9015: convert to regmap api
  af9015: correct some coding style issues

 drivers/media/dvb-frontends/Kconfig |2 +-
 drivers/media/dvb-frontends/af9013.c|  909 
+---

 drivers/media/dvb-frontends/af9013.h|   48 ++---
 drivers/media/dvb-frontends/af9013_priv.h   | 1558 
++---

 drivers/media/usb/dvb-usb-v2/Kconfig|1 +
 drivers/media/usb/dvb-usb-v2/af9015.c   |  985 
--

 drivers/media/usb/dvb-usb-v2/af9015.h   |   20 +-
 drivers/media/usb/dvb-usb-v2/dvb_usb.h  |4 +
 drivers/media/usb/dvb-usb-v2/dvb_usb_core.c |   24 ++-
 9 files changed, 1778 insertions(+), 1773 deletions(-)

--
http://palosaari.fi/


[PATCH 07/18] af9013: convert inittabs suitable for regmap_update_bits

2018-03-13 Thread Antti Palosaari
Convert inttabs to format (reg, mask, val) which are suitable
parameters to pass directly for regmap_update_bits.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/dvb-frontends/af9013.c  |   62 +-
 drivers/media/dvb-frontends/af9013_priv.h | 1488 +++--
 2 files changed, 782 insertions(+), 768 deletions(-)

diff --git a/drivers/media/dvb-frontends/af9013.c 
b/drivers/media/dvb-frontends/af9013.c
index e81dc827e1b8..87a55cd67e03 100644
--- a/drivers/media/dvb-frontends/af9013.c
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -843,7 +843,7 @@ static int af9013_init(struct dvb_frontend *fe)
int ret, i, len;
unsigned int utmp;
u8 buf[3];
-   const struct af9013_reg_bit *init;
+   const struct af9013_reg_mask_val *tab;
 
dev_dbg(>dev, "\n");
 
@@ -898,72 +898,66 @@ static int af9013_init(struct dvb_frontend *fe)
if (ret)
goto err;
 
-   /* load OFSM settings */
-   dev_dbg(>dev, "load ofsm settings\n");
-   len = ARRAY_SIZE(ofsm_init);
-   init = ofsm_init;
+   /* Demod core settings */
+   dev_dbg(>dev, "load demod core settings\n");
+   len = ARRAY_SIZE(demod_init_tab);
+   tab = demod_init_tab;
for (i = 0; i < len; i++) {
-   u16 reg = init[i].addr;
-   u8 mask = GENMASK(init[i].pos + init[i].len - 1, init[i].pos);
-   u8 val = init[i].val << init[i].pos;
-
-   ret = regmap_update_bits(state->regmap, reg, mask, val);
+   ret = regmap_update_bits(state->regmap, tab[i].reg, tab[i].mask,
+tab[i].val);
if (ret)
goto err;
}
 
-   /* load tuner specific settings */
+   /* Demod tuner specific settings */
dev_dbg(>dev, "load tuner specific settings\n");
switch (state->tuner) {
case AF9013_TUNER_MXL5003D:
-   len = ARRAY_SIZE(tuner_init_mxl5003d);
-   init = tuner_init_mxl5003d;
+   len = ARRAY_SIZE(tuner_init_tab_mxl5003d);
+   tab = tuner_init_tab_mxl5003d;
break;
case AF9013_TUNER_MXL5005D:
case AF9013_TUNER_MXL5005R:
case AF9013_TUNER_MXL5007T:
-   len = ARRAY_SIZE(tuner_init_mxl5005);
-   init = tuner_init_mxl5005;
+   len = ARRAY_SIZE(tuner_init_tab_mxl5005);
+   tab = tuner_init_tab_mxl5005;
break;
case AF9013_TUNER_ENV77H11D5:
-   len = ARRAY_SIZE(tuner_init_env77h11d5);
-   init = tuner_init_env77h11d5;
+   len = ARRAY_SIZE(tuner_init_tab_env77h11d5);
+   tab = tuner_init_tab_env77h11d5;
break;
case AF9013_TUNER_MT2060:
-   len = ARRAY_SIZE(tuner_init_mt2060);
-   init = tuner_init_mt2060;
+   len = ARRAY_SIZE(tuner_init_tab_mt2060);
+   tab = tuner_init_tab_mt2060;
break;
case AF9013_TUNER_MC44S803:
-   len = ARRAY_SIZE(tuner_init_mc44s803);
-   init = tuner_init_mc44s803;
+   len = ARRAY_SIZE(tuner_init_tab_mc44s803);
+   tab = tuner_init_tab_mc44s803;
break;
case AF9013_TUNER_QT1010:
case AF9013_TUNER_QT1010A:
-   len = ARRAY_SIZE(tuner_init_qt1010);
-   init = tuner_init_qt1010;
+   len = ARRAY_SIZE(tuner_init_tab_qt1010);
+   tab = tuner_init_tab_qt1010;
break;
case AF9013_TUNER_MT2060_2:
-   len = ARRAY_SIZE(tuner_init_mt2060_2);
-   init = tuner_init_mt2060_2;
+   len = ARRAY_SIZE(tuner_init_tab_mt2060_2);
+   tab = tuner_init_tab_mt2060_2;
break;
case AF9013_TUNER_TDA18271:
case AF9013_TUNER_TDA18218:
-   len = ARRAY_SIZE(tuner_init_tda18271);
-   init = tuner_init_tda18271;
+   len = ARRAY_SIZE(tuner_init_tab_tda18271);
+   tab = tuner_init_tab_tda18271;
break;
case AF9013_TUNER_UNKNOWN:
default:
-   len = ARRAY_SIZE(tuner_init_unknown);
-   init = tuner_init_unknown;
+   len = ARRAY_SIZE(tuner_init_tab_unknown);
+   tab = tuner_init_tab_unknown;
break;
}
 
for (i = 0; i < len; i++) {
-   u16 reg = init[i].addr;
-   u8 mask = GENMASK(init[i].pos + init[i].len - 1, init[i].pos);
-   u8 val = init[i].val << init[i].pos;
-
-   ret = regmap_update_bits(state->regmap, reg, mask, val);
+   ret = regmap_update_bits(state->regmap, tab[i].reg, tab[i].mask,
+tab[i].val);
if (ret)
  

[PATCH 14/18] af9015: refactor copy firmware to slave demod

2018-03-13 Thread Antti Palosaari
Small improvements.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/usb/dvb-usb-v2/af9015.c | 88 +--
 1 file changed, 44 insertions(+), 44 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c 
b/drivers/media/usb/dvb-usb-v2/af9015.c
index ffd4b225e439..1f352307a00a 100644
--- a/drivers/media/usb/dvb-usb-v2/af9015.c
+++ b/drivers/media/usb/dvb-usb-v2/af9015.c
@@ -720,79 +720,79 @@ static int af9015_copy_firmware(struct dvb_usb_device *d)
struct af9015_state *state = d_to_priv(d);
struct usb_interface *intf = d->intf;
int ret;
-   u8 fw_params[4];
-   u8 val, i;
-   struct req_t req = {COPY_FIRMWARE, 0, 0x5100, 0, 0, sizeof(fw_params),
-   fw_params };
+   unsigned long timeout;
+   u8 val, firmware_info[4];
+   struct req_t req = {COPY_FIRMWARE, 0, 0x5100, 0, 0, 4, firmware_info};
 
dev_dbg(>dev, "\n");
 
-   fw_params[0] = state->firmware_size >> 8;
-   fw_params[1] = state->firmware_size & 0xff;
-   fw_params[2] = state->firmware_checksum >> 8;
-   fw_params[3] = state->firmware_checksum & 0xff;
+   firmware_info[0] = (state->firmware_size >> 8) & 0xff;
+   firmware_info[1] = (state->firmware_size >> 0) & 0xff;
+   firmware_info[2] = (state->firmware_checksum >> 8) & 0xff;
+   firmware_info[3] = (state->firmware_checksum >> 0) & 0xff;
 
-   ret = af9015_read_reg_i2c(d, state->af9013_i2c_addr[1],
-   0x98be, );
+   /* Check whether firmware is already running */
+   ret = af9015_read_reg_i2c(d, state->af9013_i2c_addr[1], 0x98be, );
if (ret)
-   goto error;
-   else
-   dev_dbg(>dev, "firmware status %02x\n", val);
+   goto err;
 
-   if (val == 0x0c) /* fw is running, no need for download */
-   goto exit;
+   dev_dbg(>dev, "firmware status %02x\n", val);
 
-   /* set I2C master clock to fast (to speed up firmware copy) */
-   ret = af9015_write_reg(d, 0xd416, 0x04); /* 0x04 * 400ns */
-   if (ret)
-   goto error;
+   if (val == 0x0c)
+   return 0;
 
-   msleep(50);
+   /* Set i2c clock to 625kHz to speed up firmware copy */
+   ret = af9015_write_reg(d, 0xd416, 0x04);
+   if (ret)
+   goto err;
 
-   /* copy firmware */
+   /* Copy firmware from master demod to slave demod */
ret = af9015_ctrl_msg(d, );
-   if (ret)
+   if (ret) {
dev_err(>dev, "firmware copy cmd failed %d\n", ret);
+   goto err;
+   }
 
-   dev_dbg(>dev, "firmware copy done\n");
-
-   /* set I2C master clock back to normal */
-   ret = af9015_write_reg(d, 0xd416, 0x14); /* 0x14 * 400ns */
+   /* Set i2c clock to 125kHz */
+   ret = af9015_write_reg(d, 0xd416, 0x14);
if (ret)
-   goto error;
+   goto err;
 
-   /* request boot firmware */
-   ret = af9015_write_reg_i2c(d, state->af9013_i2c_addr[1],
-   0xe205, 1);
-   dev_dbg(>dev, "firmware boot cmd status %d\n", ret);
+   /* Boot firmware */
+   ret = af9015_write_reg_i2c(d, state->af9013_i2c_addr[1], 0xe205, 0x01);
if (ret)
-   goto error;
+   goto err;
 
-   for (i = 0; i < 15; i++) {
-   msleep(100);
+   /* Poll firmware ready */
+   for (val = 0x00, timeout = jiffies + msecs_to_jiffies(1000);
+!time_after(jiffies, timeout) && val != 0x0c && val != 0x04;) {
+   msleep(20);
 
-   /* check firmware status */
+   /* Check firmware status. 0c=OK, 04=fail */
ret = af9015_read_reg_i2c(d, state->af9013_i2c_addr[1],
-   0x98be, );
-   dev_dbg(>dev, "firmware status cmd status %d, firmware 
status %02x\n",
-   ret, val);
+ 0x98be, );
if (ret)
-   goto error;
+   goto err;
 
-   if (val == 0x0c || val == 0x04) /* success or fail */
-   break;
+   dev_dbg(>dev, "firmware status %02x\n", val);
}
 
+   dev_dbg(>dev, "firmware boot took %u ms\n",
+   jiffies_to_msecs(jiffies) - (jiffies_to_msecs(timeout) - 1000));
+
if (val == 0x04) {
-   ret = -ETIMEDOUT;
+   ret = -ENODEV;
dev_err(>dev, "firmware did not run\n");
+   goto err;
} else if (val != 0x0c) {
ret = -ETIMEDOUT;
dev_err(>dev, "firmware boot timeout\n");
+   goto err;
}
 
-error:
-exit:
+   return 0;
+err:
+   dev_dbg(>dev, "failed %d\n", ret);
return ret;
 }
 
-- 
2.14.3



[PATCH 03/18] af9013: dvbv5 cnr

2018-03-13 Thread Antti Palosaari
Implement dvbv5 cnr.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/dvb-frontends/af9013.c  | 88 +--
 drivers/media/dvb-frontends/af9013_priv.h |  1 +
 2 files changed, 84 insertions(+), 5 deletions(-)

diff --git a/drivers/media/dvb-frontends/af9013.c 
b/drivers/media/dvb-frontends/af9013.c
index 4cb6371572c5..b3d08e437478 100644
--- a/drivers/media/dvb-frontends/af9013.c
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -46,6 +46,7 @@ struct af9013_state {
unsigned long set_frontend_jiffies;
unsigned long read_status_jiffies;
unsigned long strength_jiffies;
+   unsigned long cnr_jiffies;
bool first_tune;
bool i2c_gate_state;
unsigned int statistics_step:3;
@@ -179,7 +180,6 @@ 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 = >dtv_property_cache;
int ret, i, len;
unsigned int utmp;
u8 buf[3];
@@ -235,9 +235,6 @@ 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(>dev, "failed %d\n", ret);
@@ -757,7 +754,7 @@ static int af9013_read_status(struct dvb_frontend *fe, enum 
fe_status *status)
struct dtv_frontend_properties *c = >dtv_property_cache;
int ret, stmp1;
unsigned int utmp, utmp1, utmp2, utmp3, utmp4;
-   u8 buf[2];
+   u8 buf[3];
 
dev_dbg(>dev, "\n");
 
@@ -869,6 +866,87 @@ static int af9013_read_status(struct dvb_frontend *fe, 
enum fe_status *status)
break;
}
 
+   /* CNR */
+   switch (state->fe_status & FE_HAS_VITERBI) {
+   case FE_HAS_VITERBI:
+   if (time_is_after_jiffies(state->cnr_jiffies + 
msecs_to_jiffies(2000)))
+   break;
+
+   /* Check if cnr ready */
+   ret = regmap_read(state->regmap, 0xd2e1, );
+   if (ret)
+   goto err;
+
+   if (!((utmp >> 3) & 0x01)) {
+   dev_dbg(>dev, "cnr not ready\n");
+   break;
+   }
+
+   /* Read value */
+   ret = regmap_bulk_read(state->regmap, 0xd2e3, buf, 3);
+   if (ret)
+   goto err;
+
+   utmp1 = buf[2] << 16 | buf[1] << 8 | buf[0] << 0;
+
+   /* Read current modulation */
+   ret = regmap_read(state->regmap, 0xd3c1, );
+   if (ret)
+   goto err;
+
+   switch ((utmp >> 6) & 3) {
+   case 0:
+   /*
+* QPSK
+* CNR[dB] 13 * -log10((169 - value) / value) + 2.6
+* value [653799, 168], 2.6 / 13 = 3355443
+*/
+   utmp1 = clamp(utmp1, 653799U, 168U);
+   utmp1 = ((u64)(intlog10(utmp1)
+   - intlog10(169 - utmp1)
+   + 3355443) * 13 * 1000) >> 24;
+   break;
+   case 1:
+   /*
+* QAM-16
+* CNR[dB] 6 * log10((value - 37) / (828000 - 
value)) + 15.7
+* value [371105, 827999], 15.7 / 6 = 43900382
+*/
+   utmp1 = clamp(utmp1, 371105U, 827999U);
+   utmp1 = ((u64)(intlog10(utmp1 - 37)
+   - intlog10(828000 - utmp1)
+   + 43900382) * 6 * 1000) >> 24;
+   break;
+   case 2:
+   /*
+* QAM-64
+* CNR[dB] 8 * log10((value - 193000) / (425000 - 
value)) + 23.8
+* value [193246, 424999], 23.8 / 8 = 49912218
+*/
+   utmp1 = clamp(utmp1, 193246U, 424999U);
+   utmp1 = ((u64)(intlog10(utmp1 - 193000)
+   - intlog10(425000 - utmp1)
+   + 49912218) * 8 * 1000) >> 24;
+   break;
+   default:
+   dev_dbg(>dev, "invalid modulation %u\n",
+   (utmp >> 6) & 3);
+   utmp1 = 0;
+   break;
+   }
+
+   dev_dbg(>dev, "cnr %u\n", utmp1);
+
+   state->cnr_jiffies = jiffies;
+

[PATCH 10/18] af9013: remove all legacy media attach releated stuff

2018-03-13 Thread Antti Palosaari
No one is binding that driver through media attach so remove it and
all related dead code.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/dvb-frontends/af9013.c | 80 
 drivers/media/dvb-frontends/af9013.h | 42 ---
 2 files changed, 7 insertions(+), 115 deletions(-)

diff --git a/drivers/media/dvb-frontends/af9013.c 
b/drivers/media/dvb-frontends/af9013.c
index d55c5f67ce0f..15af3e9482df 100644
--- a/drivers/media/dvb-frontends/af9013.c
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -48,7 +48,6 @@ struct af9013_state {
u32 dvbv3_ber;
u32 dvbv3_ucblocks;
bool first_tune;
-   bool i2c_gate_state;
 };
 
 static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval)
@@ -1031,45 +1030,6 @@ static int af9013_sleep(struct dvb_frontend *fe)
return ret;
 }
 
-static int af9013_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-   int ret;
-   struct af9013_state *state = fe->demodulator_priv;
-   struct i2c_client *client = state->client;
-
-   dev_dbg(>dev, "enable %d\n", enable);
-
-   /* gate already open or close */
-   if (state->i2c_gate_state == enable)
-   return 0;
-
-   if (state->ts_mode == AF9013_TS_MODE_USB)
-   ret = regmap_update_bits(state->regmap, 0xd417, 0x08,
-enable << 3);
-   else
-   ret = regmap_update_bits(state->regmap, 0xd607, 0x04,
-enable << 2);
-   if (ret)
-   goto err;
-
-   state->i2c_gate_state = enable;
-
-   return 0;
-err:
-   dev_dbg(>dev, "failed %d\n", ret);
-   return ret;
-}
-
-static void af9013_release(struct dvb_frontend *fe)
-{
-   struct af9013_state *state = fe->demodulator_priv;
-   struct i2c_client *client = state->client;
-
-   dev_dbg(>dev, "\n");
-
-   i2c_unregister_device(client);
-}
-
 static const struct dvb_frontend_ops af9013_ops;
 
 static int af9013_download_firmware(struct af9013_state *state)
@@ -1172,40 +1132,6 @@ static int af9013_download_firmware(struct af9013_state 
*state)
return ret;
 }
 
-/*
- * XXX: That is wrapper to af9013_probe() via driver core in order to provide
- * proper I2C client for legacy media attach binding.
- * New users must use I2C client binding directly!
- */
-struct dvb_frontend *af9013_attach(const struct af9013_config *config,
-  struct i2c_adapter *i2c)
-{
-   struct i2c_client *client;
-   struct i2c_board_info board_info;
-   struct af9013_platform_data pdata;
-
-   pdata.clk = config->clock;
-   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(_version, config->api_version, 
sizeof(pdata.api_version));
-   memcpy(, config->gpio, sizeof(pdata.gpio));
-   pdata.attach_in_use = true;
-
-   memset(_info, 0, sizeof(board_info));
-   strlcpy(board_info.type, "af9013", sizeof(board_info.type));
-   board_info.addr = config->i2c_addr;
-   board_info.platform_data = 
-   client = i2c_new_device(i2c, _info);
-   if (!client || !client->dev.driver)
-   return NULL;
-
-   return pdata.get_dvb_frontend(client);
-}
-EXPORT_SYMBOL(af9013_attach);
-
 static const struct dvb_frontend_ops af9013_ops = {
.delsys = { SYS_DVBT },
.info = {
@@ -1231,8 +1157,6 @@ static const struct dvb_frontend_ops af9013_ops = {
FE_CAN_MUTE_TS
},
 
-   .release = af9013_release,
-
.init = af9013_init,
.sleep = af9013_sleep,
 
@@ -1245,8 +1169,6 @@ static const struct dvb_frontend_ops af9013_ops = {
.read_signal_strength = af9013_read_signal_strength,
.read_ber = af9013_read_ber,
.read_ucblocks = af9013_read_ucblocks,
-
-   .i2c_gate_ctrl = af9013_i2c_gate_ctrl,
 };
 
 static struct dvb_frontend *af9013_get_dvb_frontend(struct i2c_client *client)
@@ -1546,8 +1468,6 @@ static int af9013_probe(struct i2c_client *client,
 
/* Create dvb frontend */
memcpy(>fe.ops, _ops, sizeof(state->fe.ops));
-   if (!pdata->attach_in_use)
-   state->fe.ops.release = NULL;
state->fe.demodulator_priv = state;
 
/* Setup callbacks */
diff --git a/drivers/media/dvb-frontends/af9013.h 
b/drivers/media/dvb-frontends/af9013.h
index ea63ff9242f2..8144d4270b58 100644
--- a/drivers/media/dvb-frontends/af9013.h
+++ b/drivers/media/dvb-frontends/af9013.h
@@ -38,13 +38,6 @@
  * @api_version: Firmware API version.
  * @gpio: GPIOs.
  * @get_dvb_frontend: Get DVB frontend callback.
- *
- * AF9013/5 GPIOs (mostly guessed):
-

[PATCH 05/18] af9013: wrap dvbv3 statistics via dvbv5

2018-03-13 Thread Antti Palosaari
Driver has calculated dvbv5 statistics, so use those as a base for
legacy dvbv3 statistics. Wrap and convert needed values to dvbv3,
remove old dvbv3 statistic implementations.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/dvb-frontends/af9013.c  | 306 +++---
 drivers/media/dvb-frontends/af9013_priv.h |  68 ---
 2 files changed, 22 insertions(+), 352 deletions(-)

diff --git a/drivers/media/dvb-frontends/af9013.c 
b/drivers/media/dvb-frontends/af9013.c
index a054e39510e0..e81dc827e1b8 100644
--- a/drivers/media/dvb-frontends/af9013.c
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -33,12 +33,6 @@ struct af9013_state {
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;
-   u16 signal_strength;
-   u32 ber;
-   u32 ucblocks;
-   u16 snr;
u32 bandwidth_hz;
enum fe_status fe_status;
/* RF and IF AGC limits used for signal strength calc */
@@ -48,10 +42,12 @@ struct af9013_state {
unsigned long strength_jiffies;
unsigned long cnr_jiffies;
unsigned long ber_ucb_jiffies;
+   u16 dvbv3_snr;
+   u16 dvbv3_strength;
+   u32 dvbv3_ber;
+   u32 dvbv3_ucblocks;
bool first_tune;
bool i2c_gate_state;
-   unsigned int statistics_step:3;
-   struct delayed_work statistics_work;
 };
 
 static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval)
@@ -106,228 +102,6 @@ static int af9013_set_gpio(struct af9013_state *state, u8 
gpio, u8 gpioval)
return ret;
 }
 
-static int af9013_statistics_ber_unc_start(struct dvb_frontend *fe)
-{
-   struct af9013_state *state = fe->demodulator_priv;
-   struct i2c_client *client = state->client;
-   int ret;
-
-   dev_dbg(>dev, "\n");
-
-   /* reset and start BER counter */
-   ret = regmap_update_bits(state->regmap, 0xd391, 0x10, 0x10);
-   if (ret)
-   goto err;
-
-   return 0;
-err:
-   dev_dbg(>dev, "failed %d\n", ret);
-   return ret;
-}
-
-static int af9013_statistics_ber_unc_result(struct dvb_frontend *fe)
-{
-   struct af9013_state *state = fe->demodulator_priv;
-   struct i2c_client *client = state->client;
-   int ret;
-   unsigned int utmp;
-   u8 buf[5];
-
-   dev_dbg(>dev, "\n");
-
-   /* check if error bit count is ready */
-   ret = regmap_read(state->regmap, 0xd391, );
-   if (ret)
-   goto err;
-
-   if (!((utmp >> 4) & 0x01)) {
-   dev_dbg(>dev, "not ready\n");
-   return 0;
-   }
-
-   ret = regmap_bulk_read(state->regmap, 0xd387, buf, 5);
-   if (ret)
-   goto err;
-
-   state->ber = (buf[2] << 16) | (buf[1] << 8) | buf[0];
-   state->ucblocks += (buf[4] << 8) | buf[3];
-
-   return 0;
-err:
-   dev_dbg(>dev, "failed %d\n", ret);
-   return ret;
-}
-
-static int af9013_statistics_snr_start(struct dvb_frontend *fe)
-{
-   struct af9013_state *state = fe->demodulator_priv;
-   struct i2c_client *client = state->client;
-   int ret;
-
-   dev_dbg(>dev, "\n");
-
-   /* start SNR meas */
-   ret = regmap_update_bits(state->regmap, 0xd2e1, 0x08, 0x08);
-   if (ret)
-   goto err;
-
-   return 0;
-err:
-   dev_dbg(>dev, "failed %d\n", ret);
-   return ret;
-}
-
-static int af9013_statistics_snr_result(struct dvb_frontend *fe)
-{
-   struct af9013_state *state = fe->demodulator_priv;
-   struct i2c_client *client = state->client;
-   int ret, i, len;
-   unsigned int utmp;
-   u8 buf[3];
-   u32 snr_val;
-   const struct af9013_snr *uninitialized_var(snr_lut);
-
-   dev_dbg(>dev, "\n");
-
-   /* check if SNR ready */
-   ret = regmap_read(state->regmap, 0xd2e1, );
-   if (ret)
-   goto err;
-
-   if (!((utmp >> 3) & 0x01)) {
-   dev_dbg(>dev, "not ready\n");
-   return 0;
-   }
-
-   /* read value */
-   ret = regmap_bulk_read(state->regmap, 0xd2e3, buf, 3);
-   if (ret)
-   goto err;
-
-   snr_val = (buf[2] << 16) | (buf[1] << 8) | buf[0];
-
-   /* read current modulation */
-   ret = regmap_read(state->regmap, 0xd3c1, );
-   if (ret)
-   goto err;
-
-   switch ((utmp >> 6) & 3) {
-   case 0:
-   len = ARRAY_SIZE(qpsk_snr_lut);
-   snr_lut = qpsk_snr_lut;
-   break;
-   case 1:
-   len = ARRAY_SIZE(qam16_snr_lut);
-   snr_lut = qam16_snr_lut;
-   break;
-   case 2:
-  

[PATCH 15/18] af9015: enhance streaming config

2018-03-13 Thread Antti Palosaari
Replace static stream settings by one which enables and disables
stream interface when needed (TS streaming control).

1) Configure both TS IF and USB endpoints according to current use case

2) Disable streaming USB endpoints when streaming is stopped and
enable when streaming is started. Reduces sleep power consumption
slightly.

3) Reduce USB buffersize slightly, from 130848 to 98136 bytes

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/usb/dvb-usb-v2/af9015.c | 220 ++
 drivers/media/usb/dvb-usb-v2/af9015.h |  14 +--
 2 files changed, 115 insertions(+), 119 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c 
b/drivers/media/usb/dvb-usb-v2/af9015.c
index 1f352307a00a..99e3b14d493e 100644
--- a/drivers/media/usb/dvb-usb-v2/af9015.c
+++ b/drivers/media/usb/dvb-usb-v2/af9015.c
@@ -607,11 +607,121 @@ static int af9015_get_stream_config(struct dvb_frontend 
*fe, u8 *ts_type,
dev_dbg(>dev, "adap %u\n", fe_to_adap(fe)->id);
 
if (d->udev->speed == USB_SPEED_FULL)
-   stream->u.bulk.buffersize = TS_USB11_FRAME_SIZE;
+   stream->u.bulk.buffersize = 5 * 188;
 
return 0;
 }
 
+static int af9015_streaming_ctrl(struct dvb_frontend *fe, int onoff)
+{
+   struct dvb_usb_device *d = fe_to_d(fe);
+   struct af9015_state *state = d_to_priv(d);
+   struct usb_interface *intf = d->intf;
+   int ret;
+   unsigned int utmp1, utmp2, reg1, reg2;
+   u8 buf[2];
+   const unsigned int adap_id = fe_to_adap(fe)->id;
+
+   dev_dbg(>dev, "adap id %d, onoff %d\n", adap_id, onoff);
+
+   if (state->usb_ts_if_configured[adap_id] == false) {
+   dev_dbg(>dev, "set usb and ts interface\n");
+
+   /* USB IF stream settings */
+   utmp1 = (d->udev->speed == USB_SPEED_FULL ? 5 : 87) * 188 / 4;
+   utmp2 = (d->udev->speed == USB_SPEED_FULL ? 64 : 512) / 4;
+
+   buf[0] = (utmp1 >> 0) & 0xff;
+   buf[1] = (utmp1 >> 8) & 0xff;
+   if (adap_id == 0) {
+   /* 1st USB IF (EP4) stream settings */
+   reg1 = 0xdd88;
+   reg2 = 0xdd0c;
+   } else {
+   /* 2nd USB IF (EP5) stream settings */
+   reg1 = 0xdd8a;
+   reg2 = 0xdd0d;
+   }
+
+   ret = af9015_write_regs(d, reg1, buf, 2);
+   if (ret)
+   goto err;
+   ret = af9015_write_reg(d, reg2, utmp2);
+   if (ret)
+   goto err;
+
+   /* TS IF settings */
+   if (state->dual_mode) {
+   ret = af9015_set_reg_bit(d, 0xd50b, 0);
+   if (ret)
+   goto err;
+   ret = af9015_set_reg_bit(d, 0xd520, 4);
+   if (ret)
+   goto err;
+   } else {
+   ret = af9015_clear_reg_bit(d, 0xd50b, 0);
+   if (ret)
+   goto err;
+   ret = af9015_clear_reg_bit(d, 0xd520, 4);
+   if (ret)
+   goto err;
+   }
+
+   state->usb_ts_if_configured[adap_id] = true;
+   }
+
+   if (adap_id == 0 && onoff) {
+   /* Adapter 0 stream on. EP4: clear NAK, enable, clear reset */
+   ret = af9015_clear_reg_bit(d, 0xdd13, 5);
+   if (ret)
+   goto err;
+   ret = af9015_set_reg_bit(d, 0xdd11, 5);
+   if (ret)
+   goto err;
+   ret = af9015_clear_reg_bit(d, 0xd507, 2);
+   if (ret)
+   goto err;
+   } else if (adap_id == 1 && onoff) {
+   /* Adapter 1 stream on. EP5: clear NAK, enable, clear reset */
+   ret = af9015_clear_reg_bit(d, 0xdd13, 6);
+   if (ret)
+   goto err;
+   ret = af9015_set_reg_bit(d, 0xdd11, 6);
+   if (ret)
+   goto err;
+   ret = af9015_clear_reg_bit(d, 0xd50b, 1);
+   if (ret)
+   goto err;
+   } else if (adap_id == 0 && !onoff) {
+   /* Adapter 0 stream off. EP4: set reset, disable, set NAK */
+   ret = af9015_set_reg_bit(d, 0xd507, 2);
+   if (ret)
+   goto err;
+   ret = af9015_clear_reg_bit(d, 0xdd11, 5);
+   if (ret)
+   goto err;
+   ret = af9015_set_reg_bit(d, 0xdd13, 5);
+   if (ret)
+   goto err;
+   } else if (adap_id == 1 && !

[PATCH 04/18] af9013: dvbv5 ber and per

2018-03-13 Thread Antti Palosaari
Implement dvbv5 ber and per.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/dvb-frontends/af9013.c | 73 +++-
 1 file changed, 72 insertions(+), 1 deletion(-)

diff --git a/drivers/media/dvb-frontends/af9013.c 
b/drivers/media/dvb-frontends/af9013.c
index b3d08e437478..a054e39510e0 100644
--- a/drivers/media/dvb-frontends/af9013.c
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -47,6 +47,7 @@ struct af9013_state {
unsigned long read_status_jiffies;
unsigned long strength_jiffies;
unsigned long cnr_jiffies;
+   unsigned long ber_ucb_jiffies;
bool first_tune;
bool i2c_gate_state;
unsigned int statistics_step:3;
@@ -754,7 +755,7 @@ static int af9013_read_status(struct dvb_frontend *fe, enum 
fe_status *status)
struct dtv_frontend_properties *c = >dtv_property_cache;
int ret, stmp1;
unsigned int utmp, utmp1, utmp2, utmp3, utmp4;
-   u8 buf[3];
+   u8 buf[7];
 
dev_dbg(>dev, "\n");
 
@@ -947,6 +948,72 @@ static int af9013_read_status(struct dvb_frontend *fe, 
enum fe_status *status)
break;
}
 
+   /* BER / PER */
+   switch (state->fe_status & FE_HAS_SYNC) {
+   case FE_HAS_SYNC:
+   if (time_is_after_jiffies(state->ber_ucb_jiffies + 
msecs_to_jiffies(2000)))
+   break;
+
+   /* Check if ber / ucb is ready */
+   ret = regmap_read(state->regmap, 0xd391, );
+   if (ret)
+   goto err;
+
+   if (!((utmp >> 4) & 0x01)) {
+   dev_dbg(>dev, "ber not ready\n");
+   break;
+   }
+
+   /* Read value */
+   ret = regmap_bulk_read(state->regmap, 0xd385, buf, 7);
+   if (ret)
+   goto err;
+
+   utmp1 = buf[4] << 16 | buf[3] << 8 | buf[2] << 0;
+   utmp2 = (buf[1] << 8 | buf[0] << 0) * 204 * 8;
+   utmp3 = buf[6] << 8 | buf[5] << 0;
+   utmp4 = buf[1] << 8 | buf[0] << 0;
+
+   /* Use 1 TS packets for measure */
+   if (utmp4 != 1) {
+   buf[0] = (1 >> 0) & 0xff;
+   buf[1] = (1 >> 8) & 0xff;
+   ret = regmap_bulk_write(state->regmap, 0xd385, buf, 2);
+   if (ret)
+   goto err;
+   }
+
+   /* Reset ber / ucb counter */
+   ret = regmap_update_bits(state->regmap, 0xd391, 0x20, 0x20);
+   if (ret)
+   goto err;
+
+   dev_dbg(>dev, "post_bit_error %u, post_bit_count %u\n",
+   utmp1, utmp2);
+   dev_dbg(>dev, "block_error %u, block_count %u\n",
+   utmp3, utmp4);
+
+   state->ber_ucb_jiffies = jiffies;
+
+   c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+   c->post_bit_error.stat[0].uvalue += utmp1;
+   c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+   c->post_bit_count.stat[0].uvalue += utmp2;
+
+   c->block_error.stat[0].scale = FE_SCALE_COUNTER;
+   c->block_error.stat[0].uvalue += utmp3;
+   c->block_count.stat[0].scale = FE_SCALE_COUNTER;
+   c->block_count.stat[0].uvalue += utmp4;
+   break;
+   default:
+   c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+   c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   break;
+   }
+
return 0;
 err:
dev_dbg(>dev, "failed %d\n", ret);
@@ -1670,6 +1737,10 @@ static int af9013_probe(struct i2c_client *client,
c = >fe.dtv_property_cache;
c->strength.len = 1;
c->cnr.len = 1;
+   c->post_bit_error.len = 1;
+   c->post_bit_count.len = 1;
+   c->block_error.len = 1;
+   c->block_count.len = 1;
 
dev_info(>dev, "Afatech AF9013 successfully attached\n");
dev_info(>dev, "firmware version: %d.%d.%d.%d\n",
-- 
2.14.3



[PATCH 18/18] af9015: correct some coding style issues

2018-03-13 Thread Antti Palosaari
Correct coding style issues reported mostly by checkpatch.pl.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/usb/dvb-usb-v2/af9015.c | 172 +-
 1 file changed, 88 insertions(+), 84 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c 
b/drivers/media/usb/dvb-usb-v2/af9015.c
index 8379ef164fad..39f9ffce3caa 100644
--- a/drivers/media/usb/dvb-usb-v2/af9015.c
+++ b/drivers/media/usb/dvb-usb-v2/af9015.c
@@ -72,17 +72,19 @@ static int af9015_ctrl_msg(struct dvb_usb_device *d, struct 
req_t *req)
goto error;
}
 
-   /* buffer overflow check */
+   /* Buffer overflow check */
if ((write && (req->data_len > BUF_LEN - REQ_HDR_LEN)) ||
-   (!write && (req->data_len > BUF_LEN - ACK_HDR_LEN))) {
+   (!write && (req->data_len > BUF_LEN - ACK_HDR_LEN))) {
dev_err(>dev, "too much data, cmd %u, len %u\n",
req->cmd, req->data_len);
ret = -EINVAL;
goto error;
}
 
-   /* write receives seq + status = 2 bytes
-  read receives seq + status + data = 2 + N bytes */
+   /*
+* Write receives seq + status = 2 bytes
+* Read receives seq + status + data = 2 + N bytes
+*/
wlen = REQ_HDR_LEN;
rlen = ACK_HDR_LEN;
if (write) {
@@ -96,8 +98,8 @@ static int af9015_ctrl_msg(struct dvb_usb_device *d, struct 
req_t *req)
if (req->cmd == DOWNLOAD_FIRMWARE || req->cmd == RECONNECT_USB)
rlen = 0;
 
-   ret = dvb_usbv2_generic_rw_locked(d,
-   state->buf, wlen, state->buf, rlen);
+   ret = dvb_usbv2_generic_rw_locked(d, state->buf, wlen,
+ state->buf, rlen);
if (ret)
goto error;
 
@@ -118,7 +120,7 @@ static int af9015_ctrl_msg(struct dvb_usb_device *d, struct 
req_t *req)
 }
 
 static int af9015_write_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg,
-   u8 val)
+   u8 val)
 {
struct af9015_state *state = d_to_priv(d);
struct req_t req = {WRITE_I2C, addr, reg, 1, 1, 1, };
@@ -131,7 +133,7 @@ static int af9015_write_reg_i2c(struct dvb_usb_device *d, 
u8 addr, u16 reg,
 }
 
 static int af9015_read_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg,
-   u8 *val)
+  u8 *val)
 {
struct af9015_state *state = d_to_priv(d);
struct req_t req = {READ_I2C, addr, reg, 0, 1, 1, val};
@@ -144,7 +146,7 @@ static int af9015_read_reg_i2c(struct dvb_usb_device *d, u8 
addr, u16 reg,
 }
 
 static int af9015_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
-   int num)
+  int num)
 {
struct dvb_usb_device *d = i2c_get_adapdata(adap);
struct af9015_state *state = d_to_priv(d);
@@ -154,28 +156,29 @@ static int af9015_i2c_xfer(struct i2c_adapter *adap, 
struct i2c_msg msg[],
u8 mbox, addr_len;
struct req_t req;
 
-/*
-The bus lock is needed because there is two tuners both using same I2C-address.
-Due to that the only way to select correct tuner is use demodulator I2C-gate.
-
-
-. AF9015 includes integrated AF9013 demodulator.
-.      .
-.| uC | |   demod| .   |tuner   |
-.|| || .   ||
-.|   AF9015   | |  AF9013/5  | .   |   MXL5003  |
-.||--+I2C---|-/ -|-.-I2C---||
-.||  |  | addr 0x38  | .   |  addr 0xc6 |
-.||  |  || .   ||
-.|..
-|      
-|  |   demod| |tuner   |
-|  || ||
-|  |   AF9013   | |   MXL5003  |
-+I2C---|-/ -|---I2C---||
-   | addr 0x3a  | |  addr 0xc6 |
-   || ||
-*/
+   /*
+* I2C multiplexing:
+* There could be two tuners, both using same I2C address. Demodulator
+* I2C-gate is only possibility to select correct tuner.
+*
+* ...
+* . AF9015 integrates AF9013 demodulator.
+* .     . ___

[PATCH 06/18] af9015: fix logging

2018-03-13 Thread Antti Palosaari
Pass correct device to dev_* logging functions, which allows us to
remove redundant KBUILD_MODNAME and __func__ parameters from log format.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/usb/dvb-usb-v2/af9015.c | 160 +-
 1 file changed, 81 insertions(+), 79 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c 
b/drivers/media/usb/dvb-usb-v2/af9015.c
index 8013659c41b1..7e4cce05b911 100644
--- a/drivers/media/usb/dvb-usb-v2/af9015.c
+++ b/drivers/media/usb/dvb-usb-v2/af9015.c
@@ -29,6 +29,7 @@ static int af9015_ctrl_msg(struct dvb_usb_device *d, struct 
req_t *req)
 #define REQ_HDR_LEN 8 /* send header size */
 #define ACK_HDR_LEN 2 /* rece header size */
struct af9015_state *state = d_to_priv(d);
+   struct usb_interface *intf = d->intf;
int ret, wlen, rlen;
u8 write = 1;
 
@@ -66,8 +67,7 @@ static int af9015_ctrl_msg(struct dvb_usb_device *d, struct 
req_t *req)
case BOOT:
break;
default:
-   dev_err(>udev->dev, "%s: unknown command=%d\n",
-   KBUILD_MODNAME, req->cmd);
+   dev_err(>dev, "unknown cmd %d\n", req->cmd);
ret = -EIO;
goto error;
}
@@ -75,8 +75,8 @@ static int af9015_ctrl_msg(struct dvb_usb_device *d, struct 
req_t *req)
/* buffer overflow check */
if ((write && (req->data_len > BUF_LEN - REQ_HDR_LEN)) ||
(!write && (req->data_len > BUF_LEN - ACK_HDR_LEN))) {
-   dev_err(>udev->dev, "%s: too much data; cmd=%d len=%d\n",
-   KBUILD_MODNAME, req->cmd, req->data_len);
+   dev_err(>dev, "too much data, cmd %u, len %u\n",
+   req->cmd, req->data_len);
ret = -EINVAL;
goto error;
}
@@ -103,8 +103,7 @@ static int af9015_ctrl_msg(struct dvb_usb_device *d, struct 
req_t *req)
 
/* check status */
if (rlen && state->buf[1]) {
-   dev_err(>udev->dev, "%s: command failed=%d\n",
-   KBUILD_MODNAME, state->buf[1]);
+   dev_err(>dev, "cmd failed %u\n", state->buf[1]);
ret = -EIO;
goto error;
}
@@ -206,6 +205,7 @@ 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);
+   struct usb_interface *intf = d->intf;
int ret;
u16 addr;
u8 mbox, addr_len;
@@ -307,15 +307,14 @@ Due to that the only way to select correct tuner is use 
demodulator I2C-gate.
ret = af9015_ctrl_msg(d, );
} else {
ret = -EOPNOTSUPP;
-   dev_dbg(>udev->dev, "%s: unknown msg, num %u\n",
-   __func__, num);
+   dev_dbg(>dev, "unknown msg, num %u\n", num);
}
if (ret)
goto err;
 
return num;
 err:
-   dev_dbg(>udev->dev, "%s: failed %d\n", __func__, ret);
+   dev_dbg(>dev, "failed %d\n", ret);
return ret;
 }
 
@@ -331,6 +330,7 @@ static struct i2c_algorithm af9015_i2c_algo = {
 
 static int af9015_identify_state(struct dvb_usb_device *d, const char **name)
 {
+   struct usb_interface *intf = d->intf;
int ret;
u8 reply;
struct req_t req = {GET_CONFIG, 0, 0, 0, 0, 1, };
@@ -339,7 +339,7 @@ static int af9015_identify_state(struct dvb_usb_device *d, 
const char **name)
if (ret)
return ret;
 
-   dev_dbg(>udev->dev, "%s: reply=%02x\n", __func__, reply);
+   dev_dbg(>dev, "reply %02x\n", reply);
 
if (reply == 0x02)
ret = WARM;
@@ -353,10 +353,12 @@ static int af9015_download_firmware(struct dvb_usb_device 
*d,
const struct firmware *fw)
 {
struct af9015_state *state = d_to_priv(d);
+   struct usb_interface *intf = d->intf;
int i, len, remaining, ret;
struct req_t req = {DOWNLOAD_FIRMWARE, 0, 0, 0, 0, 0, NULL};
u16 checksum = 0;
-   dev_dbg(>udev->dev, "%s:\n", __func__);
+
+   dev_dbg(>dev, "\n");
 
/* calc checksum */
for (i = 0; i < fw->size; i++)
@@ -378,9 +380,8 @@ static int af9015_download_firmware(struct dvb_usb_device 
*d,
 
ret = af9015_ctrl_msg(d, );
if (ret) {
-   dev_err(>udev->dev,
-   "%s: firmware download failed=%d\n",
-   KBUILD_MODNAME, ret);
+   dev_err(>dev, "firmwar

[PATCH 12/18] af9015: use af9013 demod pid filters

2018-03-13 Thread Antti Palosaari
PID filters are moved to af9013 demod driver as those are property of
demod. As pid filters are now implemented correctly by demod driver,
we could enable pid filter support for possible slave demod too on
dual tuner configuration.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/usb/dvb-usb-v2/af9015.c | 49 +--
 1 file changed, 18 insertions(+), 31 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c 
b/drivers/media/usb/dvb-usb-v2/af9015.c
index f07aa42535e5..8e2f704c6ca5 100644
--- a/drivers/media/usb/dvb-usb-v2/af9015.c
+++ b/drivers/media/usb/dvb-usb-v2/af9015.c
@@ -474,10 +474,6 @@ static int af9015_read_config(struct dvb_usb_device *d)
state->dual_mode = val;
dev_dbg(>dev, "ts mode %02x\n", state->dual_mode);
 
-   /* disable 2nd adapter because we don't have PID-filters */
-   if (d->udev->speed == USB_SPEED_FULL)
-   state->dual_mode = 0;
-
state->af9013_i2c_addr[0] = AF9015_I2C_DEMOD;
 
if (state->dual_mode) {
@@ -1045,43 +1041,28 @@ static int af9015_tuner_attach(struct dvb_usb_adapter 
*adap)
 
 static int af9015_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
 {
-   struct dvb_usb_device *d = adap_to_d(adap);
-   struct usb_interface *intf = d->intf;
+   struct af9015_state *state = adap_to_priv(adap);
+   struct af9013_platform_data *pdata = >af9013_pdata[adap->id];
int ret;
 
-   dev_dbg(>dev, "onoff %d\n", onoff);
-
-   if (onoff)
-   ret = af9015_set_reg_bit(d, 0xd503, 0);
-   else
-   ret = af9015_clear_reg_bit(d, 0xd503, 0);
+   mutex_lock(>fe_mutex);
+   ret = pdata->pid_filter_ctrl(adap->fe[0], onoff);
+   mutex_unlock(>fe_mutex);
 
return ret;
 }
 
-static int af9015_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
-   int onoff)
+static int af9015_pid_filter(struct dvb_usb_adapter *adap, int index,
+u16 pid, int onoff)
 {
-   struct dvb_usb_device *d = adap_to_d(adap);
-   struct usb_interface *intf = d->intf;
+   struct af9015_state *state = adap_to_priv(adap);
+   struct af9013_platform_data *pdata = >af9013_pdata[adap->id];
int ret;
-   u8 idx;
-
-   dev_dbg(>dev, "index %d, pid %04x, onoff %d\n",
-   index, pid, onoff);
 
-   ret = af9015_write_reg(d, 0xd505, (pid & 0xff));
-   if (ret)
-   goto error;
-
-   ret = af9015_write_reg(d, 0xd506, (pid >> 8));
-   if (ret)
-   goto error;
-
-   idx = ((index & 0x1f) | (1 << 5));
-   ret = af9015_write_reg(d, 0xd504, idx);
+   mutex_lock(>fe_mutex);
+   ret = pdata->pid_filter(adap->fe[0], index, pid, onoff);
+   mutex_unlock(>fe_mutex);
 
-error:
return ret;
 }
 
@@ -1448,6 +1429,12 @@ static struct dvb_usb_device_properties af9015_props = {
 
.stream = DVB_USB_STREAM_BULK(0x84, 8, 
TS_USB20_FRAME_SIZE),
}, {
+   .caps = DVB_USB_ADAP_HAS_PID_FILTER |
+   DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+   .pid_filter_count = 32,
+   .pid_filter = af9015_pid_filter,
+   .pid_filter_ctrl = af9015_pid_filter_ctrl,
+
.stream = DVB_USB_STREAM_BULK(0x85, 8, 
TS_USB20_FRAME_SIZE),
},
},
-- 
2.14.3



[PATCH 08/18] af9013: add i2c mux adapter for tuner bus

2018-03-13 Thread Antti Palosaari
Add muxed i2c adapter for demod tuner i2c bus gate control.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/dvb-frontends/Kconfig   |   2 +-
 drivers/media/dvb-frontends/af9013.c  | 126 +-
 drivers/media/dvb-frontends/af9013.h  |   1 +
 drivers/media/dvb-frontends/af9013_priv.h |   1 +
 4 files changed, 111 insertions(+), 19 deletions(-)

diff --git a/drivers/media/dvb-frontends/Kconfig 
b/drivers/media/dvb-frontends/Kconfig
index 687086cdb870..0712069fd9fe 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -462,7 +462,7 @@ config DVB_TDA10048
 
 config DVB_AF9013
tristate "Afatech AF9013 demodulator"
-   depends on DVB_CORE && I2C
+   depends on DVB_CORE && I2C && I2C_MUX
select REGMAP
default m if !MEDIA_SUBDRV_AUTOSELECT
help
diff --git a/drivers/media/dvb-frontends/af9013.c 
b/drivers/media/dvb-frontends/af9013.c
index 87a55cd67e03..d55c5f67ce0f 100644
--- a/drivers/media/dvb-frontends/af9013.c
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -23,6 +23,7 @@
 struct af9013_state {
struct i2c_client *client;
struct regmap *regmap;
+   struct i2c_mux_core *muxc;
struct dvb_frontend fe;
u32 clk;
u8 tuner;
@@ -1257,9 +1258,65 @@ static struct dvb_frontend 
*af9013_get_dvb_frontend(struct i2c_client *client)
return >fe;
 }
 
+static struct i2c_adapter *af9013_get_i2c_adapter(struct i2c_client *client)
+{
+   struct af9013_state *state = i2c_get_clientdata(client);
+
+   dev_dbg(>dev, "\n");
+
+   return state->muxc->adapter[0];
+}
+
+/*
+ * XXX: Hackish solution. We use virtual register, reg bit 16, to carry info
+ * about i2c adapter locking. Own locking is needed because i2c mux call has
+ * already locked i2c adapter.
+ */
+static int af9013_select(struct i2c_mux_core *muxc, u32 chan)
+{
+   struct af9013_state *state = i2c_mux_priv(muxc);
+   struct i2c_client *client = state->client;
+   int ret;
+
+   dev_dbg(>dev, "\n");
+
+   if (state->ts_mode == AF9013_TS_MODE_USB)
+   ret = regmap_update_bits(state->regmap, 0x1d417, 0x08, 0x08);
+   else
+   ret = regmap_update_bits(state->regmap, 0x1d607, 0x04, 0x04);
+   if (ret)
+   goto err;
+
+   return 0;
+err:
+   dev_dbg(>dev, "failed %d\n", ret);
+   return ret;
+}
+
+static int af9013_deselect(struct i2c_mux_core *muxc, u32 chan)
+{
+   struct af9013_state *state = i2c_mux_priv(muxc);
+   struct i2c_client *client = state->client;
+   int ret;
+
+   dev_dbg(>dev, "\n");
+
+   if (state->ts_mode == AF9013_TS_MODE_USB)
+   ret = regmap_update_bits(state->regmap, 0x1d417, 0x08, 0x00);
+   else
+   ret = regmap_update_bits(state->regmap, 0x1d607, 0x04, 0x00);
+   if (ret)
+   goto err;
+
+   return 0;
+err:
+   dev_dbg(>dev, "failed %d\n", ret);
+   return ret;
+}
+
 /* Own I2C access routines needed for regmap as chip uses extra command byte */
 static int af9013_wregs(struct i2c_client *client, u8 cmd, u16 reg,
-   const u8 *val, int len)
+   const u8 *val, int len, u8 lock)
 {
int ret;
u8 buf[21];
@@ -1281,7 +1338,12 @@ static int af9013_wregs(struct i2c_client *client, u8 
cmd, u16 reg,
buf[1] = (reg >> 0) & 0xff;
buf[2] = cmd;
memcpy([3], val, len);
-   ret = i2c_transfer(client->adapter, msg, 1);
+
+   if (lock)
+   i2c_lock_adapter(client->adapter);
+   ret = __i2c_transfer(client->adapter, msg, 1);
+   if (lock)
+   i2c_unlock_adapter(client->adapter);
if (ret < 0) {
goto err;
} else if (ret != 1) {
@@ -1296,7 +1358,7 @@ static int af9013_wregs(struct i2c_client *client, u8 
cmd, u16 reg,
 }
 
 static int af9013_rregs(struct i2c_client *client, u8 cmd, u16 reg,
-   u8 *val, int len)
+   u8 *val, int len, u8 lock)
 {
int ret;
u8 buf[3];
@@ -1317,7 +1379,12 @@ static int af9013_rregs(struct i2c_client *client, u8 
cmd, u16 reg,
buf[0] = (reg >> 8) & 0xff;
buf[1] = (reg >> 0) & 0xff;
buf[2] = cmd;
-   ret = i2c_transfer(client->adapter, msg, 2);
+
+   if (lock)
+   i2c_lock_adapter(client->adapter);
+   ret = __i2c_transfer(client->adapter, msg, 2);
+   if (lock)
+   i2c_unlock_adapter(client->adapter);
if (ret < 0) {
goto err;
} else if (ret != 2) {
@@ -1337,25 +1404,27 @@ static int af9013_regmap_write(void *context, const 
void *data, size_t count)
struct af9013_state *state = i2c_get_clientdata(cli

[PATCH 09/18] af9015: attach demod using i2c binding

2018-03-13 Thread Antti Palosaari
af9013 demod driver has i2c binding. Use it.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/usb/dvb-usb-v2/af9015.c | 158 --
 drivers/media/usb/dvb-usb-v2/af9015.h |   4 +-
 2 files changed, 96 insertions(+), 66 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c 
b/drivers/media/usb/dvb-usb-v2/af9015.c
index 7e4cce05b911..f07aa42535e5 100644
--- a/drivers/media/usb/dvb-usb-v2/af9015.c
+++ b/drivers/media/usb/dvb-usb-v2/af9015.c
@@ -148,8 +148,8 @@ static int af9015_write_reg_i2c(struct dvb_usb_device *d, 
u8 addr, u16 reg,
struct af9015_state *state = d_to_priv(d);
struct req_t req = {WRITE_I2C, addr, reg, 1, 1, 1, };
 
-   if (addr == state->af9013_config[0].i2c_addr ||
-   addr == state->af9013_config[1].i2c_addr)
+   if (addr == state->af9013_i2c_addr[0] ||
+   addr == state->af9013_i2c_addr[1])
req.addr_len = 3;
 
return af9015_ctrl_msg(d, );
@@ -161,8 +161,8 @@ static int af9015_read_reg_i2c(struct dvb_usb_device *d, u8 
addr, u16 reg,
struct af9015_state *state = d_to_priv(d);
struct req_t req = {READ_I2C, addr, reg, 0, 1, 1, val};
 
-   if (addr == state->af9013_config[0].i2c_addr ||
-   addr == state->af9013_config[1].i2c_addr)
+   if (addr == state->af9013_i2c_addr[0] ||
+   addr == state->af9013_i2c_addr[1])
req.addr_len = 3;
 
return af9015_ctrl_msg(d, );
@@ -258,7 +258,7 @@ Due to that the only way to select correct tuner is use 
demodulator I2C-gate.
ret = -EOPNOTSUPP;
goto err;
}
-   if (msg[0].addr == state->af9013_config[0].i2c_addr)
+   if (msg[0].addr == state->af9013_i2c_addr[0])
req.cmd = WRITE_MEMORY;
else
req.cmd = WRITE_I2C;
@@ -276,7 +276,7 @@ Due to that the only way to select correct tuner is use 
demodulator I2C-gate.
ret = -EOPNOTSUPP;
goto err;
}
-   if (msg[0].addr == state->af9013_config[0].i2c_addr)
+   if (msg[0].addr == state->af9013_i2c_addr[0])
req.cmd = READ_MEMORY;
else
req.cmd = READ_I2C;
@@ -293,7 +293,7 @@ Due to that the only way to select correct tuner is use 
demodulator I2C-gate.
ret = -EOPNOTSUPP;
goto err;
}
-   if (msg[0].addr == state->af9013_config[0].i2c_addr) {
+   if (msg[0].addr == state->af9013_i2c_addr[0]) {
ret = -EINVAL;
goto err;
}
@@ -478,7 +478,7 @@ 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;
+   state->af9013_i2c_addr[0] = AF9015_I2C_DEMOD;
 
if (state->dual_mode) {
/* read 2nd demodulator I2C address */
@@ -487,7 +487,7 @@ static int af9015_read_config(struct dvb_usb_device *d)
if (ret)
goto error;
 
-   state->af9013_config[1].i2c_addr = val >> 1;
+   state->af9013_i2c_addr[1] = val >> 1;
}
 
for (i = 0; i < state->dual_mode + 1; i++) {
@@ -500,20 +500,20 @@ static int af9015_read_config(struct dvb_usb_device *d)
goto error;
switch (val) {
case 0:
-   state->af9013_config[i].clock = 2880;
+   state->af9013_pdata[i].clk = 2880;
break;
case 1:
-   state->af9013_config[i].clock = 2048;
+   state->af9013_pdata[i].clk = 2048;
break;
case 2:
-   state->af9013_config[i].clock = 2800;
+   state->af9013_pdata[i].clk = 2800;
break;
case 3:
-   state->af9013_config[i].clock = 2500;
+   state->af9013_pdata[i].clk = 2500;
break;
}
-   dev_dbg(>dev, "[%d] xtal %02x, clock %u\n",
-   i, val, state->af9013_config[i].clock);
+   dev_dbg(>dev, "[%d] xtal %02x, clk %u\n",
+   i, val, state->af9013_pdata[i].clk);
 
/* IF frequency */
req.addr = AF9015_EEPROM_IF1H + offset;
@@ -521,17 +521,17 @@ static int af9015_read_config(struct dvb_usb_device *d)
if (ret)
goto error;
 
-

[PATCH 02/18] af9013: dvbv5 signal strength

2018-03-13 Thread Antti Palosaari
Implement dvbv5 signal strength estimate. We know tuner dependent
-80dBm and -50dBm agc values, construct line equation and use it to
map agc value to signal strength estimate.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/dvb-frontends/af9013.c | 83 +++-
 1 file changed, 81 insertions(+), 2 deletions(-)

diff --git a/drivers/media/dvb-frontends/af9013.c 
b/drivers/media/dvb-frontends/af9013.c
index 30cf837058da..4cb6371572c5 100644
--- a/drivers/media/dvb-frontends/af9013.c
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -41,8 +41,11 @@ struct af9013_state {
u16 snr;
u32 bandwidth_hz;
enum fe_status fe_status;
+   /* RF and IF AGC limits used for signal strength calc */
+   u8 strength_en, rf_agc_50, rf_agc_80, if_agc_50, if_agc_80;
unsigned long set_frontend_jiffies;
unsigned long read_status_jiffies;
+   unsigned long strength_jiffies;
bool first_tune;
bool i2c_gate_state;
unsigned int statistics_step:3;
@@ -751,8 +754,12 @@ static int af9013_read_status(struct dvb_frontend *fe, 
enum fe_status *status)
 {
struct af9013_state *state = fe->demodulator_priv;
struct i2c_client *client = state->client;
-   int ret;
-   unsigned int utmp, utmp1;
+   struct dtv_frontend_properties *c = >dtv_property_cache;
+   int ret, stmp1;
+   unsigned int utmp, utmp1, utmp2, utmp3, utmp4;
+   u8 buf[2];
+
+   dev_dbg(>dev, "\n");
 
/*
 * Return status from the cache if it is younger than 2000ms with the
@@ -791,6 +798,77 @@ static int af9013_read_status(struct dvb_frontend *fe, 
enum fe_status *status)
*status = utmp1;
}
 
+   /* Signal strength */
+   switch (state->strength_en) {
+   case 0:
+   /* Check if we support signal strength */
+   ret = regmap_read(state->regmap, 0x9bee, );
+   if (ret)
+   goto err;
+
+   if ((utmp >> 0) & 0x01) {
+   /* Read agc values for signal strength estimation */
+   ret = regmap_read(state->regmap, 0x9bbd, );
+   if (ret)
+   goto err;
+   ret = regmap_read(state->regmap, 0x9bd0, );
+   if (ret)
+   goto err;
+   ret = regmap_read(state->regmap, 0x9be2, );
+   if (ret)
+   goto err;
+   ret = regmap_read(state->regmap, 0x9be4, );
+   if (ret)
+   goto err;
+
+   state->rf_agc_50 = utmp1;
+   state->rf_agc_80 = utmp2;
+   state->if_agc_50 = utmp3;
+   state->if_agc_80 = utmp4;
+   dev_dbg(>dev,
+   "rf_agc_50 %u, rf_agc_80 %u, if_agc_50 %u, 
if_agc_80 %u\n",
+   utmp1, utmp2, utmp3, utmp4);
+
+   state->strength_en = 1;
+   } else {
+   /* Signal strength is not supported */
+   state->strength_en = 2;
+   break;
+   }
+   /* Fall through */
+   case 1:
+   if (time_is_after_jiffies(state->strength_jiffies + 
msecs_to_jiffies(2000)))
+   break;
+
+   /* Read value */
+   ret = regmap_bulk_read(state->regmap, 0xd07c, buf, 2);
+   if (ret)
+   goto err;
+
+   /*
+* Construct line equation from tuner dependent -80/-50 dBm agc
+* limits and use it to map current agc value to dBm estimate
+*/
+   #define agc_gain (buf[0] + buf[1])
+   #define agc_gain_50dbm (state->rf_agc_50 + state->if_agc_50)
+   #define agc_gain_80dbm (state->rf_agc_80 + state->if_agc_80)
+   stmp1 = 3 * (agc_gain - agc_gain_80dbm) /
+   (agc_gain_50dbm - agc_gain_80dbm) - 8;
+
+   dev_dbg(>dev,
+   "strength %d, agc_gain %d, agc_gain_50dbm %d, 
agc_gain_80dbm %d\n",
+   stmp1, agc_gain, agc_gain_50dbm, agc_gain_80dbm);
+
+   state->strength_jiffies = jiffies;
+
+   c->strength.stat[0].scale = FE_SCALE_DECIBEL;
+   c->strength.stat[0].svalue = stmp1;
+   break;
+   default:
+   c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   break;
+   }
+
return 0;
 err:
dev_dbg(>dev, "failed %d\n", ret);
@@ -1512,6 +1590,7 @@ static int af9013_probe(struct i2c_client *clie

[PATCH 13/18] af9015: refactor firmware download

2018-03-13 Thread Antti Palosaari
Small revise, no functional changes.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/usb/dvb-usb-v2/af9015.c | 39 +++
 1 file changed, 17 insertions(+), 22 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c 
b/drivers/media/usb/dvb-usb-v2/af9015.c
index 8e2f704c6ca5..ffd4b225e439 100644
--- a/drivers/media/usb/dvb-usb-v2/af9015.c
+++ b/drivers/media/usb/dvb-usb-v2/af9015.c
@@ -350,52 +350,47 @@ static int af9015_identify_state(struct dvb_usb_device 
*d, const char **name)
 }
 
 static int af9015_download_firmware(struct dvb_usb_device *d,
-   const struct firmware *fw)
+   const struct firmware *firmware)
 {
struct af9015_state *state = d_to_priv(d);
struct usb_interface *intf = d->intf;
-   int i, len, remaining, ret;
+   int ret, i, rem;
struct req_t req = {DOWNLOAD_FIRMWARE, 0, 0, 0, 0, 0, NULL};
-   u16 checksum = 0;
+   u16 checksum;
 
dev_dbg(>dev, "\n");
 
-   /* calc checksum */
-   for (i = 0; i < fw->size; i++)
-   checksum += fw->data[i];
+   /* Calc checksum, we need it when copy firmware to slave demod */
+   for (i = 0, checksum = 0; i < firmware->size; i++)
+   checksum += firmware->data[i];
 
-   state->firmware_size = fw->size;
+   state->firmware_size = firmware->size;
state->firmware_checksum = checksum;
 
-   #define FW_ADDR 0x5100 /* firmware start address */
-   #define LEN_MAX 55 /* max packet size */
-   for (remaining = fw->size; remaining > 0; remaining -= LEN_MAX) {
-   len = remaining;
-   if (len > LEN_MAX)
-   len = LEN_MAX;
-
-   req.data_len = len;
-   req.data = (u8 *) >data[fw->size - remaining];
-   req.addr = FW_ADDR + fw->size - remaining;
-
+   #define LEN_MAX (BUF_LEN - REQ_HDR_LEN) /* Max payload size */
+   for (rem = firmware->size; rem > 0; rem -= LEN_MAX) {
+   req.data_len = min(LEN_MAX, rem);
+   req.data = (u8 *) >data[firmware->size - rem];
+   req.addr = 0x5100 + firmware->size - rem;
ret = af9015_ctrl_msg(d, );
if (ret) {
dev_err(>dev, "firmware download failed %d\n",
ret);
-   goto error;
+   goto err;
}
}
 
-   /* firmware loaded, request boot */
req.cmd = BOOT;
req.data_len = 0;
ret = af9015_ctrl_msg(d, );
if (ret) {
dev_err(>dev, "firmware boot failed %d\n", ret);
-   goto error;
+   goto err;
}
 
-error:
+   return 0;
+err:
+   dev_dbg(>dev, "failed %d\n", ret);
return ret;
 }
 
-- 
2.14.3



[PATCH 01/18] af9013: change lock detection slightly

2018-03-13 Thread Antti Palosaari
Whilst rewritten largely, the basic logic remains same with one
exception: do not return immediately on success case. We are going to
add statistics that function and cannot return too early.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/dvb-frontends/af9013.c | 55 ++--
 1 file changed, 27 insertions(+), 28 deletions(-)

diff --git a/drivers/media/dvb-frontends/af9013.c 
b/drivers/media/dvb-frontends/af9013.c
index b8f3ebfc3e27..30cf837058da 100644
--- a/drivers/media/dvb-frontends/af9013.c
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -752,45 +752,44 @@ static int af9013_read_status(struct dvb_frontend *fe, 
enum fe_status *status)
struct af9013_state *state = fe->demodulator_priv;
struct i2c_client *client = state->client;
int ret;
-   unsigned int utmp;
+   unsigned int utmp, utmp1;
 
/*
 * Return status from the cache if it is younger than 2000ms with the
 * exception of last tune is done during 4000ms.
 */
-   if (time_is_after_jiffies(
-   state->read_status_jiffies + msecs_to_jiffies(2000)) &&
-   time_is_before_jiffies(
-   state->set_frontend_jiffies + msecs_to_jiffies(4000))
-   ) {
-   *status = state->fe_status;
-   return 0;
+   if (time_is_after_jiffies(state->read_status_jiffies + 
msecs_to_jiffies(2000)) &&
+   time_is_before_jiffies(state->set_frontend_jiffies + 
msecs_to_jiffies(4000))) {
+   *status = state->fe_status;
} else {
-   *status = 0;
-   }
+   /* MPEG2 lock */
+   ret = regmap_read(state->regmap, 0xd507, );
+   if (ret)
+   goto err;
 
-   /* MPEG2 lock */
-   ret = regmap_read(state->regmap, 0xd507, );
-   if (ret)
-   goto err;
+   if ((utmp >> 6) & 0x01) {
+   utmp1 = FE_HAS_SIGNAL | FE_HAS_CARRIER |
+   FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+   } else {
+   /* TPS lock */
+   ret = regmap_read(state->regmap, 0xd330, );
+   if (ret)
+   goto err;
 
-   if ((utmp >> 6) & 0x01)
-   *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
-   FE_HAS_SYNC | FE_HAS_LOCK;
+   if ((utmp >> 3) & 0x01)
+   utmp1 = FE_HAS_SIGNAL | FE_HAS_CARRIER |
+   FE_HAS_VITERBI;
+   else
+   utmp1 = 0;
+   }
 
-   if (!*status) {
-   /* TPS lock */
-   ret = regmap_read(state->regmap, 0xd330, );
-   if (ret)
-   goto err;
+   dev_dbg(>dev, "fe_status %02x\n", utmp1);
 
-   if ((utmp >> 3) & 0x01)
-   *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
-   FE_HAS_VITERBI;
-   }
+   state->read_status_jiffies = jiffies;
 
-   state->fe_status = *status;
-   state->read_status_jiffies = jiffies;
+   state->fe_status = utmp1;
+   *status = utmp1;
+   }
 
return 0;
 err:
-- 
2.14.3



[PATCH 17/18] af9015: convert to regmap api

2018-03-13 Thread Antti Palosaari
Use regmap for chip register access.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/usb/dvb-usb-v2/Kconfig  |   1 +
 drivers/media/usb/dvb-usb-v2/af9015.c | 209 ++
 drivers/media/usb/dvb-usb-v2/af9015.h |   2 +
 3 files changed, 115 insertions(+), 97 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/Kconfig 
b/drivers/media/usb/dvb-usb-v2/Kconfig
index 0e4944b2b0f4..09a52aae299a 100644
--- a/drivers/media/usb/dvb-usb-v2/Kconfig
+++ b/drivers/media/usb/dvb-usb-v2/Kconfig
@@ -16,6 +16,7 @@ config DVB_USB_V2
 config DVB_USB_AF9015
tristate "Afatech AF9015 DVB-T USB2.0 support"
depends on DVB_USB_V2
+   select REGMAP
select DVB_AF9013
select DVB_PLL  if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_MT2060   if MEDIA_SUBDRV_AUTOSELECT
diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c 
b/drivers/media/usb/dvb-usb-v2/af9015.c
index 99e3b14d493e..8379ef164fad 100644
--- a/drivers/media/usb/dvb-usb-v2/af9015.c
+++ b/drivers/media/usb/dvb-usb-v2/af9015.c
@@ -117,31 +117,6 @@ static int af9015_ctrl_msg(struct dvb_usb_device *d, 
struct req_t *req)
return ret;
 }
 
-static int af9015_write_regs(struct dvb_usb_device *d, u16 addr, u8 *val,
-   u8 len)
-{
-   struct req_t req = {WRITE_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, len,
-   val};
-   return af9015_ctrl_msg(d, );
-}
-
-static int af9015_read_regs(struct dvb_usb_device *d, u16 addr, u8 *val, u8 
len)
-{
-   struct req_t req = {READ_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, len,
-   val};
-   return af9015_ctrl_msg(d, );
-}
-
-static int af9015_write_reg(struct dvb_usb_device *d, u16 addr, u8 val)
-{
-   return af9015_write_regs(d, addr, , 1);
-}
-
-static int af9015_read_reg(struct dvb_usb_device *d, u16 addr, u8 *val)
-{
-   return af9015_read_regs(d, addr, val, 1);
-}
-
 static int af9015_write_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg,
u8 val)
 {
@@ -168,38 +143,6 @@ static int af9015_read_reg_i2c(struct dvb_usb_device *d, 
u8 addr, u16 reg,
return af9015_ctrl_msg(d, );
 }
 
-static int af9015_do_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit, u8 op)
-{
-   int ret;
-   u8 val, mask = 0x01;
-
-   ret = af9015_read_reg(d, addr, );
-   if (ret)
-   return ret;
-
-   mask <<= bit;
-   if (op) {
-   /* set bit */
-   val |= mask;
-   } else {
-   /* clear bit */
-   mask ^= 0xff;
-   val &= mask;
-   }
-
-   return af9015_write_reg(d, addr, val);
-}
-
-static int af9015_set_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit)
-{
-   return af9015_do_reg_bit(d, addr, bit, 1);
-}
-
-static int af9015_clear_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit)
-{
-   return af9015_do_reg_bit(d, addr, bit, 0);
-}
-
 static int af9015_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
int num)
 {
@@ -642,76 +585,73 @@ static int af9015_streaming_ctrl(struct dvb_frontend *fe, 
int onoff)
reg1 = 0xdd8a;
reg2 = 0xdd0d;
}
-
-   ret = af9015_write_regs(d, reg1, buf, 2);
+   ret = regmap_bulk_write(state->regmap, reg1, buf, 2);
if (ret)
goto err;
-   ret = af9015_write_reg(d, reg2, utmp2);
+   ret = regmap_write(state->regmap, reg2, utmp2);
if (ret)
goto err;
 
/* TS IF settings */
if (state->dual_mode) {
-   ret = af9015_set_reg_bit(d, 0xd50b, 0);
-   if (ret)
-   goto err;
-   ret = af9015_set_reg_bit(d, 0xd520, 4);
-   if (ret)
-   goto err;
+   utmp1 = 0x01;
+   utmp2 = 0x10;
} else {
-   ret = af9015_clear_reg_bit(d, 0xd50b, 0);
-   if (ret)
-   goto err;
-   ret = af9015_clear_reg_bit(d, 0xd520, 4);
-   if (ret)
-   goto err;
+   utmp1 = 0x00;
+   utmp2 = 0x00;
}
+   ret = regmap_update_bits(state->regmap, 0xd50b, 0x01, utmp1);
+   if (ret)
+   goto err;
+   ret = regmap_update_bits(state->regmap, 0xd520, 0x10, utmp2);
+   if (ret)
+   goto err;
 
state->usb_ts_if_configured[adap_id] = true;
}
 
if (adap_id == 0 && onoff) {
/* Adapter 0 stream on. EP4: clear NAK, enable, clear reset */
-   ret = af9015_clear_reg_bit(d, 0xdd13, 5);
+   ret = 

[PATCH 16/18] dvb-usb-v2: add probe/disconnect callbacks

2018-03-13 Thread Antti Palosaari
Add probe and disconnect callbacks that behaves similarly than ones
used commonly on Linux driver model. We need those to get early / late
access to driver in order to use normal probe time stuff, like regmap,
extra bus adapters and so.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/usb/dvb-usb-v2/dvb_usb.h  |  4 
 drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | 24 
 2 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb.h 
b/drivers/media/usb/dvb-usb-v2/dvb_usb.h
index d2e80537b2f7..3fd6cc0d6340 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb.h
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb.h
@@ -203,6 +203,8 @@ struct dvb_usb_adapter_properties {
  * @generic_bulk_ctrl_endpoint_response: bulk control endpoint number for
  *  receive
  * @generic_bulk_ctrl_delay: delay between bulk control sent and receive 
message
+ * @probe: like probe on driver model
+ * @disconnect: like disconnect on driver model
  * @identify_state: called to determine the firmware state (cold or warm) and
  *  return possible firmware file name to be loaded
  * @firmware: name of the firmware file to be loaded
@@ -239,6 +241,8 @@ struct dvb_usb_device_properties {
u8 generic_bulk_ctrl_endpoint_response;
unsigned int generic_bulk_ctrl_delay;
 
+   int (*probe)(struct dvb_usb_device *);
+   void (*disconnect)(struct dvb_usb_device *);
 #define WARM  0
 #define COLD  1
int (*identify_state) (struct dvb_usb_device *, const char **);
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c 
b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
index 2bf3bd81280a..afdcdbf005e9 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
@@ -854,8 +854,6 @@ static int dvb_usbv2_exit(struct dvb_usb_device *d)
dvb_usbv2_remote_exit(d);
dvb_usbv2_adapter_exit(d);
dvb_usbv2_i2c_exit(d);
-   kfree(d->priv);
-   kfree(d);
 
return 0;
 }
@@ -934,7 +932,7 @@ int dvb_usbv2_probe(struct usb_interface *intf,
if (intf->cur_altsetting->desc.bInterfaceNumber !=
d->props->bInterfaceNumber) {
ret = -ENODEV;
-   goto err_free_all;
+   goto err_kfree_d;
}
 
mutex_init(>usb_mutex);
@@ -946,10 +944,16 @@ int dvb_usbv2_probe(struct usb_interface *intf,
dev_err(>udev->dev, "%s: kzalloc() failed\n",
KBUILD_MODNAME);
ret = -ENOMEM;
-   goto err_free_all;
+   goto err_kfree_d;
}
}
 
+   if (d->props->probe) {
+   ret = d->props->probe(d);
+   if (ret)
+   goto err_kfree_priv;
+   }
+
if (d->props->identify_state) {
const char *name = NULL;
ret = d->props->identify_state(d, );
@@ -1001,6 +1005,12 @@ int dvb_usbv2_probe(struct usb_interface *intf,
return 0;
 err_free_all:
dvb_usbv2_exit(d);
+   if (d->props->disconnect)
+   d->props->disconnect(d);
+err_kfree_priv:
+   kfree(d->priv);
+err_kfree_d:
+   kfree(d);
 err:
dev_dbg(>dev, "%s: failed=%d\n", __func__, ret);
return ret;
@@ -1021,6 +1031,12 @@ void dvb_usbv2_disconnect(struct usb_interface *intf)
 
dvb_usbv2_exit(d);
 
+   if (d->props->disconnect)
+   d->props->disconnect(d);
+
+   kfree(d->priv);
+   kfree(d);
+
pr_info("%s: '%s:%s' successfully deinitialized and disconnected\n",
KBUILD_MODNAME, drvname, devname);
kfree(devname);
-- 
2.14.3



[PATCH 11/18] af9013: add pid filter support

2018-03-13 Thread Antti Palosaari
af9013 demod has pid filter. Add support for it.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/dvb-frontends/af9013.c | 52 
 drivers/media/dvb-frontends/af9013.h |  5 
 2 files changed, 57 insertions(+)

diff --git a/drivers/media/dvb-frontends/af9013.c 
b/drivers/media/dvb-frontends/af9013.c
index 15af3e9482df..482bce49819a 100644
--- a/drivers/media/dvb-frontends/af9013.c
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -1171,6 +1171,56 @@ static const struct dvb_frontend_ops af9013_ops = {
.read_ucblocks = af9013_read_ucblocks,
 };
 
+static int af9013_pid_filter_ctrl(struct dvb_frontend *fe, int onoff)
+{
+   struct af9013_state *state = fe->demodulator_priv;
+   struct i2c_client *client = state->client;
+   int ret;
+
+   dev_dbg(>dev, "onoff %d\n", onoff);
+
+   ret = regmap_update_bits(state->regmap, 0xd503, 0x01, onoff);
+   if (ret)
+   goto err;
+
+   return 0;
+err:
+   dev_dbg(>dev, "failed %d\n", ret);
+   return ret;
+}
+
+static int af9013_pid_filter(struct dvb_frontend *fe, u8 index, u16 pid,
+int onoff)
+{
+   struct af9013_state *state = fe->demodulator_priv;
+   struct i2c_client *client = state->client;
+   int ret;
+   u8 buf[2];
+
+   dev_dbg(>dev, "index %d, pid %04x, onoff %d\n",
+   index, pid, onoff);
+
+   if (pid > 0x1fff) {
+   /* 0x2000 is kernel virtual pid for whole ts (all pids) */
+   ret = 0;
+   goto err;
+   }
+
+   buf[0] = (pid >> 0) & 0xff;
+   buf[1] = (pid >> 8) & 0xff;
+   ret = regmap_bulk_write(state->regmap, 0xd505, buf, 2);
+   if (ret)
+   goto err;
+   ret = regmap_write(state->regmap, 0xd504, onoff << 5 | index << 0);
+   if (ret)
+   goto err;
+
+   return 0;
+err:
+   dev_dbg(>dev, "failed %d\n", ret);
+   return ret;
+}
+
 static struct dvb_frontend *af9013_get_dvb_frontend(struct i2c_client *client)
 {
struct af9013_state *state = i2c_get_clientdata(client);
@@ -1473,6 +1523,8 @@ static int af9013_probe(struct i2c_client *client,
/* Setup callbacks */
pdata->get_dvb_frontend = af9013_get_dvb_frontend;
pdata->get_i2c_adapter = af9013_get_i2c_adapter;
+   pdata->pid_filter = af9013_pid_filter;
+   pdata->pid_filter_ctrl = af9013_pid_filter_ctrl;
 
/* Init stats to indicate which stats are supported */
c = >fe.dtv_property_cache;
diff --git a/drivers/media/dvb-frontends/af9013.h 
b/drivers/media/dvb-frontends/af9013.h
index 8144d4270b58..165ae29ccac4 100644
--- a/drivers/media/dvb-frontends/af9013.h
+++ b/drivers/media/dvb-frontends/af9013.h
@@ -38,6 +38,9 @@
  * @api_version: Firmware API version.
  * @gpio: GPIOs.
  * @get_dvb_frontend: Get DVB frontend callback.
+ * @get_i2c_adapter: Get I2C adapter.
+ * @pid_filter_ctrl: Control PID filter.
+ * @pid_filter: Set PID to PID filter.
  */
 struct af9013_platform_data {
/*
@@ -78,6 +81,8 @@ struct af9013_platform_data {
 
struct dvb_frontend* (*get_dvb_frontend)(struct i2c_client *);
struct i2c_adapter* (*get_i2c_adapter)(struct i2c_client *);
+   int (*pid_filter_ctrl)(struct dvb_frontend *, int);
+   int (*pid_filter)(struct dvb_frontend *, u8, u16, int);
 };
 
 /*
-- 
2.14.3



Re: [PATCH] media: dvb-usb-v2: stop using coherent memory for URBs

2018-03-13 Thread Antti Palosaari

On 03/08/2018 09:09 PM, Mauro Carvalho Chehab wrote:

There's no need to use coherent buffers there. So, let the
DVB core do the allocation. That should give some performance
gain outside x86.


Hello! I am not familiar with that change, but I think you know what you 
do. Feel free to apply!


regards
Antti




Signed-off-by: Mauro Carvalho Chehab 
---
  drivers/media/usb/dvb-usb-v2/usb_urb.c | 17 -
  1 file changed, 4 insertions(+), 13 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/usb_urb.c 
b/drivers/media/usb/dvb-usb-v2/usb_urb.c
index dce2b97efce4..b0499f95ec45 100644
--- a/drivers/media/usb/dvb-usb-v2/usb_urb.c
+++ b/drivers/media/usb/dvb-usb-v2/usb_urb.c
@@ -155,8 +155,7 @@ static int usb_urb_alloc_bulk_urbs(struct usb_data_stream 
*stream)
stream->props.u.bulk.buffersize,
usb_urb_complete, stream);
  
-		stream->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;

-   stream->urb_list[i]->transfer_dma = stream->dma_addr[i];
+   stream->urb_list[i]->transfer_flags = URB_FREE_BUFFER;
stream->urbs_initialized++;
}
return 0;
@@ -187,13 +186,12 @@ static int usb_urb_alloc_isoc_urbs(struct usb_data_stream 
*stream)
urb->complete = usb_urb_complete;
urb->pipe = usb_rcvisocpipe(stream->udev,
stream->props.endpoint);
-   urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+   urb->transfer_flags = URB_ISO_ASAP | URB_FREE_BUFFER;
urb->interval = stream->props.u.isoc.interval;
urb->number_of_packets = stream->props.u.isoc.framesperurb;
urb->transfer_buffer_length = stream->props.u.isoc.framesize *
stream->props.u.isoc.framesperurb;
urb->transfer_buffer = stream->buf_list[i];
-   urb->transfer_dma = stream->dma_addr[i];
  
  		for (j = 0; j < stream->props.u.isoc.framesperurb; j++) {

urb->iso_frame_desc[j].offset = frame_offset;
@@ -212,11 +210,7 @@ static int usb_free_stream_buffers(struct usb_data_stream 
*stream)
if (stream->state & USB_STATE_URB_BUF) {
while (stream->buf_num) {
stream->buf_num--;
-   dev_dbg(>udev->dev, "%s: free buf=%d\n",
-   __func__, stream->buf_num);
-   usb_free_coherent(stream->udev, stream->buf_size,
- stream->buf_list[stream->buf_num],
- stream->dma_addr[stream->buf_num]);
+   stream->buf_list[stream->buf_num] = NULL;
}
}
  
@@ -236,9 +230,7 @@ static int usb_alloc_stream_buffers(struct usb_data_stream *stream, int num,

__func__,  num * size);
  
  	for (stream->buf_num = 0; stream->buf_num < num; stream->buf_num++) {

-   stream->buf_list[stream->buf_num] = usb_alloc_coherent(
-   stream->udev, size, GFP_ATOMIC,
-   >dma_addr[stream->buf_num]);
+   stream->buf_list[stream->buf_num] = kzalloc(size, GFP_ATOMIC);
if (!stream->buf_list[stream->buf_num]) {
dev_dbg(>udev->dev, "%s: alloc buf=%d failed\n",
__func__, stream->buf_num);
@@ -250,7 +242,6 @@ static int usb_alloc_stream_buffers(struct usb_data_stream 
*stream, int num,
__func__, stream->buf_num,
stream->buf_list[stream->buf_num],
(long long)stream->dma_addr[stream->buf_num]);
-   memset(stream->buf_list[stream->buf_num], 0, size);
stream->state |= USB_STATE_URB_BUF;
}
  



--
http://palosaari.fi/


Re: [PATCH] Fix for hanging si2168 in PCTV 292e, making code match

2018-03-07 Thread Antti Palosaari

On 03/07/2018 06:39 PM, Ron Economos wrote:
I'm almost 100% sure that the patch I submitted (and was committed in 
Linux 4.16-rc1) for the si2168 fixes Nigel's issue. I would suggest that 
Nigel's patch be retired.


https://github.com/torvalds/linux/blob/master/drivers/media/dvb-frontends/si2168.c

media: [RESEND] media: dvb-frontends: Add delay to Si2168 restart

On faster CPUs a delay is required after the resume command and the 
restart command. Without the delay, the restart command often returns 
-EREMOTEIO and the Si2168 does not restart. Note that this patch fixes 
the same issue as https://patchwork.linuxtv.org/patch/44304/, but I 
believe my udelay() fix addresses the actual problem.


Signed-off-by: Ron Economos 
Signed-off-by: Mauro Carvalho Chehab 

Ron



Yes, you are likely correct!

Patch is already applied, but however I think it should be something 
like usleep_range(100, ~0) in order to allow scheduler optimize 
resources as upper limit of delay is not critical at all. See 
Documentation/timers/timers-howto.txt



regards
Antti


--
http://palosaari.fi/


Re: [PATCH] Fix for hanging si2168 in PCTV 292e, making the code match

2018-03-07 Thread Antti Palosaari

On 12/14/2017 04:48 PM, Mauro Carvalho Chehab wrote:

Em Tue, 19 Sep 2017 13:13:52 +0100
Nigel Kettlewell  escreveu:


[re-sending as plain text]

Fix for hanging si2168 in PCTV 292e USB, making the code match the comment.

Using firmware v4.0.11 the 292e would work once and then hang on
subsequent attempts to view DVB channels, until physically unplugged and
plugged back in.

With this patch, the warm state is reset for v4.0.11 and it appears to
work both on the first attempt and on subsequent attempts.


It is comment which is wrong. With firmware 4.0.11 it works well without 
need of download it every time. But firmware 4.0.19 needs to be 
downloaded every time after device is put to sleep.

Probably your issue is coming from some other reason.




(Patch basis Linux 4.11.9 f82a53b87594f460f2dd9983eeb851a5840e8df8)


Patch is missing a Signed-off-by. See:
https://elinux.org/Developer_Certificate_Of_Origin).




---
   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 680ba06..523acd1 100644
--- a/drivers/media/dvb-frontends/si2168.c
+++ b/drivers/media/dvb-frontends/si2168.c
@@ -582,7 +582,7 @@ static int si2168_sleep(struct dvb_frontend *fe)
  dev->active = false;

  /* Firmware B 4.0-11 or later loses warm state during sleep */
-   if (dev->version > ('B' << 24 | 4 << 16 | 0 << 8 | 11 << 0))
+   if (dev->version >= ('B' << 24 | 4 << 16 | 0 << 8 | 11 << 0))
  dev->warm = false;

  memcpy(cmd.args, "\x13", 1);
--
2.9.4





Thanks,
Mauro



regards
Antti

--
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 <b...@nextdimension.cc>
---
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 = >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 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 = >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, );
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 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 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 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(>dev, "failed=%d\n", ret);
+   dev_warn(>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-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(>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, );
+
+   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, );
+   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 3/7] si2157: Add hybrid tuner support

2018-01-15 Thread Antti Palosaari
 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(>i2c_mutex);
+   INIT_DELAYED_WORK(>stat_work, si2157_stat_work);
+
+   break;
+   default:
+   /* existing tuner instance */
+   dev_dbg(>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, );
+   /* verify no i2c error and CTS is set */
+   if (ret) {
+   dev_warn(>dev, "no HW found ret=%d\n", ret);
+   goto fail_instance;
+   }
+
+   memcpy(>ops.tuner_ops, _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(>ent, TUNER_NUM_PADS,
+>pad[0]);
+
+   if (ret)
+   goto fail_instance;
+
+   ret = media_device_register_entity(cfg->mdev, >ent);
+   if (ret) {
+   dev_warn(>dev,
+   "media_device_regiser_entity returns %d\n", 
ret);
+   media_entity_cleanup(>ent);
+   goto fail_instance;
+   }
+   }
+#endif
+   mutex_unlock(_list_mutex);
+
+   if (instance != 1)
+   dev_info(>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(_list_mutex);
+
+   si2157_release(fe);
+fail:
+   dev_warn(>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 <cr...@iki.fi>");
  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] [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 <cr...@iki.fi> wrote:


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

Hi,

On Fri, 15 Dec 2017 19:30:18 +0200
Antti Palosaari <cr...@iki.fi> 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] [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 <cr...@iki.fi> 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
/0x630 [ddbridge]
   [  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 <cr...@iki.fi>
Signed-off-by: Daniel Scheller <d.schel...@gmx.net>
---
  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(>dev, "\n");

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




--
http://palosaari.fi/


Re: rc-core: how to use hid (hardware) decoder?

2017-07-15 Thread Antti Palosaari

On 07/15/2017 12:05 PM, Sean Young wrote:

Hello,

On Fri, Jul 14, 2017 at 04:14:05AM +0300, Antti Palosaari wrote:

Moikka!
Some remote controller receivers uses HID interface. I looked rc-core
implementation, but failed to find how it could be used for hid. I need
somehow get scancodes and keycodes out from rc-core and write those to
hardware which then generate hid events. Also, I am not sure if kernel
keycodes are same than HID codes, but if not then those should be translated
somehow.

There is rc_g_keycode_from_table() function, which could be used to dump
current scancode:keycode mapping, but calling it in a loop millions of times
is not surely correctly :]


Possibly you could use rc_map_get() to get the entire array. However you
would be limited to rc keymaps which are compiled into the kernel.

It be good to expose an interface to userspace which allows you to read and
write the mapping from IR protocol + scancode to hid usage codes; you could
then have an ir-keytable-like tool to change the keymap.


That was just the plan. I added callback to ir_update_mapping() in order 
to get info and new rc_map every-time when it was changed. Then driver 
configures hid table accordingly.


I ran some issues:
* HID has very limited set of keys used for remote controllers compared 
to linux. So mapping from Linux remote controller to HID went hard.


* NEC 16/24/32 mess. rc_map used by rc-core was typed as NEC16, even 
there was NEC24 scancodes. So more self-made heuristics as hw wants NEC32.


So I given it up. I can configure that remote both polling mode via 
rc-core and HID. rc-core gives much more flexibility, mainly due to 
limited keymap of HID (hw supports only HID page 7, keyboard).


regards
Antti

--
http://palosaari.fi/


rc-core: how to use hid (hardware) decoder?

2017-07-13 Thread Antti Palosaari

Moikka!
Some remote controller receivers uses HID interface. I looked rc-core 
implementation, but failed to find how it could be used for hid. I need 
somehow get scancodes and keycodes out from rc-core and write those to 
hardware which then generate hid events. Also, I am not sure if kernel 
keycodes are same than HID codes, but if not then those should be 
translated somehow.


There is rc_g_keycode_from_table() function, which could be used to dump 
current scancode:keycode mapping, but calling it in a loop millions of 
times is not surely correctly :]


Any ideas?

regards
Antti


--
http://palosaari.fi/


Re: [PATCH V2 4/9] [media] dvb-core/dvb_ca_en50221.c: Fixed block comments

2017-07-12 Thread Antti Palosaari



On 07/13/2017 03:04 AM, Antti Palosaari wrote:

On 07/13/2017 02:45 AM, Jasmin J. wrote:

Hello Antti!


Have you ever looked that coding style doc?

Yes I read it several times already and used it in my daily work in my
previous company.

Beside the Multi-line comment style, which I will fix in a follow up,
you mentioned other issues.
Please can you tell me which one you mean, so that I can check the series
for those things.


eh, OK, here short list from my head:
* you fixed comments, but left //-comments

* many cases where if (ret != 0), which generally should be written as 
if (ret). If you expect it is just error ret value, then prefer if 
(ret), but if ret has some other meaning like it returns number of bytes 
then if you expect 0-bytes returned (ret != 0) is also valid.


* unnecessary looking line split like that:
if (a
   & b)

* logical continuous line split wrong (I think I have seen checkpatch 
reported that kind of mistakes, dunno why not now)

if (a
 && b)
== >
if (a &&
 b)


actually it reports, when run --strict mode:

+   if (a
+   && b) {
+   foo(a);
+   foo(b);
+   }
+

CHECK: Logical continuations should be on the previous line
#11: FILE: drivers/media/usb/dvb-usb-v2/af9035.c:2135:
+   if (a
+   && b) {


Antti
--
http://palosaari.fi/


Re: [PATCH V2 4/9] [media] dvb-core/dvb_ca_en50221.c: Fixed block comments

2017-07-12 Thread Antti Palosaari

On 07/13/2017 02:45 AM, Jasmin J. wrote:

Hello Antti!


Have you ever looked that coding style doc?

Yes I read it several times already and used it in my daily work in my
previous company.

Beside the Multi-line comment style, which I will fix in a follow up,
you mentioned other issues.
Please can you tell me which one you mean, so that I can check the series
for those things.


eh, OK, here short list from my head:
* you fixed comments, but left //-comments

* many cases where if (ret != 0), which generally should be written as 
if (ret). If you expect it is just error ret value, then prefer if 
(ret), but if ret has some other meaning like it returns number of bytes 
then if you expect 0-bytes returned (ret != 0) is also valid.


* unnecessary looking line split like that:
if (a
  & b)

* logical continuous line split wrong (I think I have seen checkpatch 
reported that kind of mistakes, dunno why not now)

if (a
&& b)
== >
if (a &&
b)


Antti

--
http://palosaari.fi/


Re: [PATCH V2 4/9] [media] dvb-core/dvb_ca_en50221.c: Fixed block comments

2017-07-12 Thread Antti Palosaari

On 07/13/2017 02:23 AM, Jasmin J. wrote:

Hello Antti!


Quickly looking this patch serie I noticed few other coding style mistakes.
You should read kernel coding style documentation first, and then make
changes according to doc.

In fact I used checkpatch.pl to find the issues and fixed them. All the patches
are 100% checkpatch.pl tested and did not have one single error or warning.

So please can you point me to those issues you mean.


Have you ever looked that coding style doc? Maybe better to start 
reading it first. Checkpatch is only a tool, it is nothing which makes 
100% decision which is correct or not.


Multi-line comment style is explained on section 8 on kernel coding 
style doc.


Antti


--
http://palosaari.fi/


Re: [PATCH] Added support for the TerraTec T1 DVB-T USB tuner [IT9135 chipset]

2017-07-12 Thread Antti Palosaari

On 06/29/2017 08:55 PM, Nuno Henriques wrote:

Signed-off-by: Nuno Henriques 
---
  drivers/media/dvb-core/dvb-usb-ids.h  | 1 +
  drivers/media/usb/dvb-usb-v2/af9035.c | 2 ++
  2 files changed, 3 insertions(+)

diff --git a/drivers/media/dvb-core/dvb-usb-ids.h 
b/drivers/media/dvb-core/dvb-usb-ids.h
index e200aa6f2d2f..5b6041d462bc 100644
--- a/drivers/media/dvb-core/dvb-usb-ids.h
+++ b/drivers/media/dvb-core/dvb-usb-ids.h
@@ -279,6 +279,7 @@
  #define USB_PID_TERRATEC_H7   0x10b4
  #define USB_PID_TERRATEC_H7_2 0x10a3
  #define USB_PID_TERRATEC_H7_3 0x10a5
+#define USB_PID_TERRATEC_T10x10ae
  #define USB_PID_TERRATEC_T3   0x10a0
  #define USB_PID_TERRATEC_T5   0x10a1
  #define USB_PID_NOXON_DAB_STICK   0x00b3
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c 
b/drivers/media/usb/dvb-usb-v2/af9035.c
index 4df9486e19b9..ccf4a5c68877 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.c
+++ b/drivers/media/usb/dvb-usb-v2/af9035.c
@@ -2108,6 +2108,8 @@ static const struct usb_device_id af9035_id_table[] = {
{ DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CTVDIGDUAL_V2,
_props, "Digital Dual TV Receiver CTVDIGDUAL_V2",
RC_MAP_IT913X_V1) },
+   { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_T1,
+   _props, "TerraTec T1", RC_MAP_IT913X_V1) },
/* XXX: that same ID [0ccd:0099] is used by af9015 driver too */
{ DVB_USB_DEVICE(USB_VID_TERRATEC, 0x0099,
_props, "TerraTec Cinergy T Stick Dual RC (rev. 2)",




Does this stick has a remote? I see always red when I see someone adds 
RC_MAP_IT913X_V1 remote controller as there is now too many simply 
totally wrongly defined remote controllers on that driver.


Commit message is missing, even it is very trivial patch there should be 
something like It is IT9135BX device having USB ID : and remote 
controller model is x..


Use git log to see other commit messages where new usb id is added.

regards
Antti

--
http://palosaari.fi/


Re: [PATCH V2 4/9] [media] dvb-core/dvb_ca_en50221.c: Fixed block comments

2017-07-12 Thread Antti Palosaari

On 07/13/2017 02:00 AM, Jasmin J. wrote:

From: Jasmin Jessich 

Fixed all:
   WARNING: Block comments use * on subsequent lines


Also multiline comments should be written like this:
/*
 * Comment.
 */

Quickly looking this patch serie I noticed few other coding style 
mistakes. You should read kernel coding style documentation first, and 
then make changes according to doc.


regards
Antti

--
http://palosaari.fi/


Re: [PATCH 3/4] [media] dvb-frontends/stv0367: SNR DVBv5 statistics for DVB-C and T

2017-06-21 Thread Antti Palosaari



On 06/21/2017 06:50 PM, Daniel Scheller wrote:

Am Wed, 21 Jun 2017 09:30:27 +0300
schrieb Antti Palosaari <cr...@iki.fi>:


On 06/20/2017 08:45 PM, Daniel Scheller wrote:

From: Daniel Scheller <d.schel...@gmx.net>

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 <d.schel...@gmx.net>
---
   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 = >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).


This is taken from stv0367dd aswell, the reported and calculated values are in 0.1dB 
precision. This and to not diverge any more from the "source" driver, I'd 
prefer to keep it how it is. These are just simple tuner cards anyway and by no means 
professional measurement gear, and should only give a more or less rough estimate on 
reception quality. E.g. my stv0367 cards report around 36dB SNR, whereas the cxd2841er 
reports ~37dB, compared to my DOCSIS modem, which reports 34dB on DOCSIS channels 
(another variant I had earlier even reported 39dB on the same channels), so... Even, we 
get way more precision than on the relative scale calc on the cab_read_snr functions 
which is in 10%-steps...


Also, that INTLOG10X100 is pretty much useless. Use just what
intlog10/intlog2 offers without yet again another conversion.


Will check and experiment. Again, taken from stv0367dd :-)


You should understand that there is no floating points on kernel, thus 
that kind of divisions needs special attention. It should be written 
log10(signal) - log10(noise) in order to minimize rounding errors. Lets 
say as example if you divide 2 by 3 you will get 0, not 0.666... So 
depending on actual numbers used on calculation, there is more or less 
rounding errors which are easily avoidable.




Antti

--
http://palosaari.fi/


Re: [PATCH] [media] ddbridge: use dev_* macros in favor of printk

2017-06-21 Thread Antti Palosaari



On 06/21/2017 08:20 PM, Mauro Carvalho Chehab wrote:

Em Wed, 21 Jun 2017 19:14:40 +0200
Daniel Scheller  escreveu:


Am Wed, 21 Jun 2017 14:08:08 -0300
schrieb Mauro Carvalho Chehab :


Em Wed, 21 Jun 2017 18:53:47 +0200
Daniel Scheller  escreveu:
   

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 will happen.

Since in module_init_ddbridge() there's no dev yet, pr_info is used
instead.

Signed-off-by: Daniel Scheller 
---
  drivers/media/pci/ddbridge/ddbridge-core.c | 78 ++
  1 file changed, 46 insertions(+), 32 deletions(-)

diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c 
b/drivers/media/pci/ddbridge/ddbridge-core.c
index 9420479bee9a..540a121eadd6 100644
--- a/drivers/media/pci/ddbridge/ddbridge-core.c
+++ b/drivers/media/pci/ddbridge/ddbridge-core.c
@@ -17,6 +17,8 @@
   * http://www.gnu.org/copyleft/gpl.html
   */
  
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

+


I guess this is a left over from the old patch. When you use dev_foo,
it will get the driver's name from dev->name. So, no need to do the
above.


I intentionally left this in for the pr_info used in module_init_ddbridge(). If 
you prefer, we can ofc probably also leave this as printk like

printk(KERN_INFO KBUILD_MODNAME ": Digital...");


Ah, OK!


But why you even need it? Probe should be first place you need to print 
something and there is always proper device pointer.


Antti

--
http://palosaari.fi/


Re: [PATCH 3/4] [media] dvb-frontends/stv0367: SNR DVBv5 statistics for DVB-C and T

2017-06-21 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 = >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/


Re: [PATCH 1/4] [media] dvb-frontends/stv0367: initial DDB DVBv5 stats, implement ucblocks

2017-06-21 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 = >dtv_property_cache;
+   u32 ucblocks = 0;
+
+   switch (state->activedemod) {
+   case demod_ter:
+   stv0367ter_read_ucblocks(fe, );
+   break;
+   case demod_cab:
+   stv0367cab_read_ucblcks(fe, );
+   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, );
+
+   /* 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 = >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] [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/


[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/


[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 <cr...@iki.fi>
---
 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(_version, config->api_version, 
sizeof(pdata.api_version));
memcpy(, 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(>api_version, pdata->api_version, 
sizeof(state->api_version));
memcpy(>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)
goto e

[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 <cr...@iki.fi>
---
 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(>i2c->dev,
+   dev_warn(>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([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(>i2c->dev, "%s: i2c wr failed=%d reg=%04x " \
+   dev_warn(>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(>i2c->dev, "%s: i2c rd failed=%d reg=%04x " \
+   dev_warn(>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(>i2c->dev, "%s: gpio=%d gpioval=%02x\n",
+   dev_dbg(>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(>i2c->dev, "%s: invalid gpio=%d\n",
+   dev_err(>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(>i2c->dev, "%s: failed=%d\n", __func__, ret);
+   dev_dbg(>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(>i2c->dev, "%s: a=%d b=%d x=%d\n", __func__, a, b, x);
+   dev_dbg(>client->dev, "%s: a=%d b=%d x=%d\n", __func__, a, b, x);
 
if (a > b) {
c = a / b;
@@ -299,7 +298,7 @@ static u32 af9013_div(struct af9013_state *state, u32 a, 

[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 <cr...@iki.fi>
---
 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, );
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(_to_d(adap)->udev->dev,
-- 
http://palosaari.fi/



[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 <cr...@iki.fi>
---
 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 <cr...@iki.fi>
---
 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(>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(>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(>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(>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(>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(>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(>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, _frequency);
-   else
+   if (fe->ops.tuner_ops.get_if_frequency) {
+   ret = fe->ops.tuner_ops.get_if_frequency(fe,
+_frequency);
+   if (ret)
+   goto err;
+   } else {
if_frequency = state->if_frequency;
+   }
 
dev_dbg(>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(>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(>dev, "failed %d\n", ret);
return ret;
@@ -828,7 +839,7 @@ static int af9013_read_status(struct dvb_frontend *fe, enum 
fe_status *status)

[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 <cr...@iki.fi>
---
 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(>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(>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(>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(>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 <cr...@iki.fi>
---
 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, _frequency);
else
-   if_frequency = state->config.if_frequency;
+   if_frequency = state->if_frequency;
 
dev_dbg(>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 <cr...@iki.fi>
---
 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(>dev, "\n");
+
+   /* Check whether firmware is already running */
ret = regmap_read(state->regmap, 0x98be, );
if (ret)
goto err;
 
dev_dbg(>dev, "firmware status %02x\n", utmp);
 
-   if (utmp == 0x0c) /* fw is running, no need for download */
+   if (utmp == 0x0c)
return 0;
 
dev_info(>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_file, >dev);
+   /* Request the firmware, will block and timeout */
+   ret = request_firmware(, name, >dev);
if (ret) {
dev_info(>dev, "firmware file '%s' not found %d\n",
-fw_file, ret);
+name, ret);
goto err;
}
 
dev_info(>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,
-   >data[fw->size - remaining], len);
+   0x5100 + firmware->size - rem,
+   >data[firmware->size - rem],
+   len);
if (ret) {
dev_err(>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(>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 <cr...@iki.fi>
---
 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)
_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,
_to_d(adap)->i2c_adap,
_tda18271_config) == NULL ? -ENODEV : 0;
break;
@@ -975,7 +977,7 @@ static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
_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,
_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],
_to_d(adap)->i2c_adap,
-   0xc0, _mxl5007t_config) == NULL ? -ENODEV : 0;
+   0x60, _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/dvb-usb-v2/af9015.h
@@ -47,8 +47,8 @@
 #define TS_USB20_MAX_P

[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 <cr...@iki.fi>
---
 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(>dev, "load ofsm settings\n");
len = ARRAY_SIZE(ofsm_init);
-- 
http://palosaari.fi/



[PATCH 08/15] af9013: add dvbv5 cnr

2017-06-14 Thread Antti Palosaari
Add support for DVBv5 CNR.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 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 = >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(>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 = >fe.dtv_property_cache;
+   c->cnr.len = 1;
+
dev_info(>dev, "Afatech AF9013 successfully attached\n");
dev_info(>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 <cr...@iki.fi>
---
 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(>client->dev,
-"%s: i2c wr reg=%04x: len=%d is too big!\n",
-KBUILD_MODNAME, reg, len);
+   dev_warn(>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([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(>client->dev, "%s: i2c wr failed=%d reg=%04x " \
-   "len=%d\n", KBUILD_MODNAME, ret, reg, len);
+   dev_warn(>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(>client->dev, "%s: i2c rd failed=%d reg=%04x " \
-   "len=%d\n", KBUILD_MODNAME, ret, reg, len);
+   dev_warn(>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;
}
@@ -147,18 +148,18 @@ static int af

[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 <cr...@iki.fi>
---
 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(>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(>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 <cr...@iki.fi>
---
 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(>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([3], val, len);
-
-   ret = i2c_transfer(state->client->adapter, msg, 1);
-   if (ret == 1) {
-   ret = 0;
-   } else {
-   dev_warn(>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(>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) && ((reg & 0xff

[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 <cr...@iki.fi>
---
 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(>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 = [i+1].buf[0];
-   ret = af9015_ctrl_msg(d, );
-   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 = [0].buf[addr_len];
+   ret = af9015_ctrl_msg(d, );
+   } 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_MEMORY;
+   

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/


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 1/3] [media] si2157: get chip id during probing

2017-05-24 Thread Antti Palosaari

On 05/15/2017 11:28 PM, Andreas Kemnade wrote:

Hi,

On Sun, 23 Apr 2017 15:19:21 +0300
Antti Palosaari <cr...@iki.fi> wrote:


On 03/16/2017 12:22 AM, Andreas Kemnade wrote:

If the si2157 is behind a e.g. si2168, the si2157 will
at least in some situations not be readable after the si268
got the command 0101. It still accepts commands but the answer
is just ff. So read the chip id before that so the
information is not lost.

The following line in kernel output is a symptome
of that problem:
si2157 7-0063: unknown chip version Si21255-\x\x\x

That is hackish solution :( Somehow I2C reads should be get working
rather than making this kind of work-around. Returning 0xff to i2c reads
means that signal strength also shows some wrong static value?


Also this is needed for the Terratec CinergyTC2.
I see the ff even on windows. So it cannot be solved by usb-sniffing of
a working system, so, again how should we proceed?

a) not support dvb sticks which do not work with your preferred
order of initialization.

b) change order of initialisation (maybe optionally add a flag like
INIT_TUNER_BEFORE_DEMOD to avoid risk of breaking other things)

c) something like the current patch.

d) while(!i2c_readable(tuner)) {
  write_random_data_to_demod();
  write_random_data_it9306_bridge();
}
remember_random_data();


There was not much feedback here.


If it is not possible to fix i2c communication then better to add some 
device specific logic to i2c adapter in order to meet demod/tuner 
requirements.





An excerpt from my windows sniff logs:
ep: 02 l:   15 GEN_I2C_WR 00 0603c61201
ep: 02 l:0
ep: 81 l:0
ep: 81 l:5 042300dcff
ep: 02 l:9 GEN_I2C_RD 00 0603c6
ep: 02 l:0
ep: 81 l:0
ep: 81 l:   11 0a240080ff5b02
ep: 02 l:   15 GEN_I2C_WR 00 0603c6140011070300
ep: 02 l:0
ep: 81 l:0
ep: 81 l:5 042500daff
ep: 02 l:9 GEN_I2C_RD 00 0403c6
ep: 02 l:0
ep: 81 l:0
ep: 81 l:9 08260080ff5901

here you see all the  from the device.



Regards,
Andreas



regards
Antti



--
http://palosaari.fi/


Re: [PATCH 1/3] [media] si2157: get chip id during probing

2017-04-23 Thread Antti Palosaari

On 03/16/2017 12:22 AM, Andreas Kemnade wrote:

If the si2157 is behind a e.g. si2168, the si2157 will
at least in some situations not be readable after the si268
got the command 0101. It still accepts commands but the answer
is just ff. So read the chip id before that so the
information is not lost.

The following line in kernel output is a symptome
of that problem:
si2157 7-0063: unknown chip version Si21255-\x\x\x
That is hackish solution :( Somehow I2C reads should be get working 
rather than making this kind of work-around. Returning 0xff to i2c reads 
means that signal strength also shows some wrong static value?


regards
Antti

--
http://palosaari.fi/


[GIT PULL 4.12] si2157: Si2141 tuner support

2017-04-10 Thread Antti Palosaari
That patch set replaces existing si2146 support with new one, that looks 
more correct for my eyes.


Antti

The following changes since commit 7ca0ef3da09888b303991edb80cd0283ee641c9e:

  Merge tag 'v4.11-rc5' into patchwork (2017-04-04 11:11:43 -0300)

are available in the git repository at:

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

for you to fetch changes up to c9110a61811b9349ac64c3e50fd927c580e2eacd:

  si2157: Add support for Si2141-A10 (2017-04-06 16:48:52 +0300)


Antti Palosaari (1):
  si2157: revert si2157: Si2141/2151 tuner support

Stefan Brüns (1):
  si2157: Add support for Si2141-A10

 drivers/media/tuners/si2157.c | 85 
+++--

 1 file changed, 23 insertions(+), 62 deletions(-)

--
http://palosaari.fi/


[PATCH 1/2] si2157: revert si2157: Si2141/2151 tuner support

2017-04-06 Thread Antti Palosaari
'Reset' loop does not look correct. I tested it very many times and
it never repeated those commands. If problem, it tries to solve,
really occurs on some situations better solution should be find out.

There is another patch which does not have such hackish looking loop.
Lets change to it.

Cc: Evgeny Plehov <evgenyple...@ukr.net>
Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/tuners/si2157.c  | 70 --
 drivers/media/tuners/si2157_priv.h |  2 --
 2 files changed, 6 insertions(+), 66 deletions(-)

diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c
index b46b149..57b2508 100644
--- a/drivers/media/tuners/si2157.c
+++ b/drivers/media/tuners/si2157.c
@@ -1,5 +1,5 @@
 /*
- * Silicon Labs Si2141/2146/2147/2148/2151/2157/2158 silicon tuner driver
+ * Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner driver
  *
  * Copyright (C) 2014 Antti Palosaari <cr...@iki.fi>
  *
@@ -75,7 +75,6 @@ static int si2157_cmd_execute(struct i2c_client *client, 
struct si2157_cmd *cmd)
return ret;
 }
 
-#define MAX_RESET_ATTEMPTS 10
 static int si2157_init(struct dvb_frontend *fe)
 {
struct i2c_client *client = fe->tuner_priv;
@@ -85,7 +84,7 @@ static int si2157_init(struct dvb_frontend *fe)
struct si2157_cmd cmd;
const struct firmware *fw;
const char *fw_name;
-   unsigned int uitmp, chip_id, i;
+   unsigned int uitmp, chip_id;
 
dev_dbg(>dev, "\n");
 
@@ -103,44 +102,14 @@ static int si2157_init(struct dvb_frontend *fe)
if (uitmp == dev->if_frequency / 1000)
goto warm;
 
-   if (dev->chiptype == SI2157_CHIPTYPE_SI2141) {
-   for (i = 0; i < MAX_RESET_ATTEMPTS; i++)  {
-   /* reset */
-   memcpy(cmd.args, "\xc0\x05\x00\x00", 4);
-   cmd.wlen = 4;
-   cmd.rlen = 1;
-   ret = si2157_cmd_execute(client, );
-   if (ret)
-   goto err;
-
-   memcpy(cmd.args, 
"\xc0\x00\x0d\x0e\x00\x01\x01\x01\x01\x03", 10);
-   cmd.wlen = 10;
-   cmd.rlen = 1;
-   ret = si2157_cmd_execute(client, );
-   if (ret)
-   goto err;
-   if (cmd.args[0] != 0xfe)
-   break;
-   }
-   if (i >= MAX_RESET_ATTEMPTS)
-   goto err;
-   }
-
/* power up */
-   switch (dev->chiptype) {
-   case SI2157_CHIPTYPE_SI2146:
+   if (dev->chiptype == SI2157_CHIPTYPE_SI2146) {
memcpy(cmd.args, "\xc0\x05\x01\x00\x00\x0b\x00\x00\x01", 9);
cmd.wlen = 9;
-   break;
-   case SI2157_CHIPTYPE_SI2141:
-   memcpy(cmd.args, "\xc0\x08\x01\x02\x00\x08\x01", 7);
-   cmd.wlen = 7;
-   break;
-   default:
+   } else {
memcpy(cmd.args, 
"\xc0\x00\x0c\x00\x00\x01\x01\x01\x01\x01\x01\x02\x00\x00\x01", 15);
cmd.wlen = 15;
}
-
cmd.rlen = 1;
ret = si2157_cmd_execute(client, );
if (ret)
@@ -162,8 +131,6 @@ static int si2157_init(struct dvb_frontend *fe)
#define SI2157_A30 ('A' << 24 | 57 << 16 | '3' << 8 | '0' << 0)
#define SI2147_A30 ('A' << 24 | 47 << 16 | '3' << 8 | '0' << 0)
#define SI2146_A10 ('A' << 24 | 46 << 16 | '1' << 8 | '0' << 0)
-   #define SI2141_A10 ('A' << 24 | 41 << 16 | '1' << 8 | '0' << 0)
-   #define SI2151_A10 ('A' << 24 | 51 << 16 | '1' << 8 | '0' << 0)
 
switch (chip_id) {
case SI2158_A20:
@@ -175,10 +142,6 @@ static int si2157_init(struct dvb_frontend *fe)
case SI2146_A10:
fw_name = NULL;
break;
-   case SI2141_A10:
-   case SI2151_A10:
-   fw_name = SI2141_A10_FIRMWARE;
-   break;
default:
dev_err(>dev, "unknown chip version Si21%d-%c%c%c\n",
cmd.args[2], cmd.args[1],
@@ -251,23 +214,6 @@ static int si2157_init(struct dvb_frontend *fe)
 
dev_info(>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, );
-   if (ret)
-   goto err;
-   /* setup PIN */
-   memcpy(cmd.args, "

[PATCH 2/2] si2157: Add support for Si2141-A10

2017-04-06 Thread Antti Palosaari
From: Stefan Brüns <stefan.bru...@rwth-aachen.de>

The Si2141 needs two distinct commands for powerup/reset, otherwise it
will not respond to chip revision requests. It also needs a firmware
to run properly.

Cc: Evgeny Plehov <evgenyple...@ukr.net>
Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/tuners/si2157.c  | 23 +--
 drivers/media/tuners/si2157_priv.h |  2 ++
 2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c
index 57b2508..e35b1fa 100644
--- a/drivers/media/tuners/si2157.c
+++ b/drivers/media/tuners/si2157.c
@@ -106,6 +106,9 @@ static int si2157_init(struct dvb_frontend *fe)
if (dev->chiptype == SI2157_CHIPTYPE_SI2146) {
memcpy(cmd.args, "\xc0\x05\x01\x00\x00\x0b\x00\x00\x01", 9);
cmd.wlen = 9;
+   } else if (dev->chiptype == SI2157_CHIPTYPE_SI2141) {
+   memcpy(cmd.args, "\xc0\x00\x0d\x0e\x00\x01\x01\x01\x01\x03", 
10);
+   cmd.wlen = 10;
} else {
memcpy(cmd.args, 
"\xc0\x00\x0c\x00\x00\x01\x01\x01\x01\x01\x01\x02\x00\x00\x01", 15);
cmd.wlen = 15;
@@ -115,6 +118,15 @@ static int si2157_init(struct dvb_frontend *fe)
if (ret)
goto err;
 
+   /* Si2141 needs a second command before it answers the revision query */
+   if (dev->chiptype == SI2157_CHIPTYPE_SI2141) {
+   memcpy(cmd.args, "\xc0\x08\x01\x02\x00\x00\x01", 7);
+   cmd.wlen = 7;
+   ret = si2157_cmd_execute(client, );
+   if (ret)
+   goto err;
+   }
+
/* query chip revision */
memcpy(cmd.args, "\x02", 1);
cmd.wlen = 1;
@@ -131,12 +143,16 @@ static int si2157_init(struct dvb_frontend *fe)
#define SI2157_A30 ('A' << 24 | 57 << 16 | '3' << 8 | '0' << 0)
#define SI2147_A30 ('A' << 24 | 47 << 16 | '3' << 8 | '0' << 0)
#define SI2146_A10 ('A' << 24 | 46 << 16 | '1' << 8 | '0' << 0)
+   #define SI2141_A10 ('A' << 24 | 41 << 16 | '1' << 8 | '0' << 0)
 
switch (chip_id) {
case SI2158_A20:
case SI2148_A20:
fw_name = SI2158_A20_FIRMWARE;
break;
+   case SI2141_A10:
+   fw_name = SI2141_A10_FIRMWARE;
+   break;
case SI2157_A30:
case SI2147_A30:
case SI2146_A10:
@@ -371,7 +387,7 @@ static int si2157_get_if_frequency(struct dvb_frontend *fe, 
u32 *frequency)
 
 static const struct dvb_tuner_ops si2157_ops = {
.info = {
-   .name   = "Silicon Labs Si2146/2147/2148/2157/2158",
+   .name   = "Silicon Labs 
Si2141/Si2146/2147/2148/2157/2158",
.frequency_min  = 4200,
.frequency_max  = 87000,
},
@@ -471,6 +487,7 @@ static int si2157_probe(struct i2c_client *client,
 #endif
 
dev_info(>dev, "Silicon Labs %s successfully attached\n",
+   dev->chiptype == SI2157_CHIPTYPE_SI2141 ?  "Si2141" :
dev->chiptype == SI2157_CHIPTYPE_SI2146 ?
"Si2146" : "Si2147/2148/2157/2158");
 
@@ -508,6 +525,7 @@ static int si2157_remove(struct i2c_client *client)
 static const struct i2c_device_id si2157_id_table[] = {
{"si2157", SI2157_CHIPTYPE_SI2157},
{"si2146", SI2157_CHIPTYPE_SI2146},
+   {"si2141", SI2157_CHIPTYPE_SI2141},
{}
 };
 MODULE_DEVICE_TABLE(i2c, si2157_id_table);
@@ -524,7 +542,8 @@ static struct i2c_driver si2157_driver = {
 
 module_i2c_driver(si2157_driver);
 
-MODULE_DESCRIPTION("Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner 
driver");
+MODULE_DESCRIPTION("Silicon Labs Si2141/Si2146/2147/2148/2157/2158 silicon 
tuner driver");
 MODULE_AUTHOR("Antti Palosaari <cr...@iki.fi>");
 MODULE_LICENSE("GPL");
 MODULE_FIRMWARE(SI2158_A20_FIRMWARE);
+MODULE_FIRMWARE(SI2141_A10_FIRMWARE);
diff --git a/drivers/media/tuners/si2157_priv.h 
b/drivers/media/tuners/si2157_priv.h
index d6b2c7b..e6436f7 100644
--- a/drivers/media/tuners/si2157_priv.h
+++ b/drivers/media/tuners/si2157_priv.h
@@ -42,6 +42,7 @@ struct si2157_dev {
 
 #define SI2157_CHIPTYPE_SI2157 0
 #define SI2157_CHIPTYPE_SI2146 1
+#define SI2157_CHIPTYPE_SI2141 2
 
 /* firmware command struct */
 #define SI2157_ARGLEN  30
@@ -52,5 +53,6 @@ struct si2157_cmd {
 };
 
 #define SI2158_A20_FIRMWARE "dvb-tuner-si2158-a20-01.fw"
+#define SI2141_A10_FIRMWARE "dvb-tuner-si2141-a10-01.fw"
 
 #endif
-- 
http://palosaari.fi/



[GIT PULL 4.12] mn88472 statistics

2017-04-06 Thread Antti Palosaari

The following changes since commit 700ea5e0e0dd70420a04e703ff264cc133834cba:

  Merge tag 'v4.11-rc1' into patchwork (2017-03-06 06:49:34 -0300)

are available in the git repository at:

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

for you to fetch changes up to ea003f23ec598c46a31ad9bfe0e4d258f04edc0b:

  mn88472: implement PER statistics (2017-03-17 18:45:48 +0200)


Antti Palosaari (3):
  mn88472: implement signal strength statistics
  mn88472: implement cnr statistics
  mn88472: implement PER statistics

 drivers/media/dvb-frontends/mn88472.c  | 134 
--

 drivers/media/dvb-frontends/mn88472_priv.h |   1 +
 2 files changed, 133 insertions(+), 2 deletions(-)

--
http://palosaari.fi/


[PATCH 3/3] mn88472: implement PER statistics

2017-03-17 Thread Antti Palosaari
Implement DVBv5 PER.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/dvb-frontends/mn88472.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/media/dvb-frontends/mn88472.c 
b/drivers/media/dvb-frontends/mn88472.c
index c7e5f63..f6938f96 100644
--- a/drivers/media/dvb-frontends/mn88472.c
+++ b/drivers/media/dvb-frontends/mn88472.c
@@ -179,6 +179,26 @@ static int mn88472_read_status(struct dvb_frontend *fe, 
enum fe_status *status)
c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
}
 
+   /* PER */
+   if (*status & FE_HAS_SYNC) {
+   ret = regmap_bulk_read(dev->regmap[0], 0xe1, buf, 4);
+   if (ret)
+   goto err;
+
+   utmp1 = buf[0] << 8 | buf[1] << 0;
+   utmp2 = buf[2] << 8 | buf[3] << 0;
+   dev_dbg(>dev, "block_error=%u block_count=%u\n",
+   utmp1, utmp2);
+
+   c->block_error.stat[0].scale = FE_SCALE_COUNTER;
+   c->block_error.stat[0].uvalue += utmp1;
+   c->block_count.stat[0].scale = FE_SCALE_COUNTER;
+   c->block_count.stat[0].uvalue += utmp2;
+   } else {
+   c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   }
+
return 0;
 err:
dev_dbg(>dev, "failed=%d\n", ret);
@@ -654,6 +674,8 @@ static int mn88472_probe(struct i2c_client *client,
c = >fe.dtv_property_cache;
c->strength.len = 1;
c->cnr.len = 1;
+   c->block_error.len = 1;
+   c->block_count.len = 1;
 
/* Setup callbacks */
pdata->get_dvb_frontend = mn88472_get_dvb_frontend;
-- 
http://palosaari.fi/



[PATCH 1/3] mn88472: implement signal strength statistics

2017-03-17 Thread Antti Palosaari
Implement DVBv5 signal strength on relative scale.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/dvb-frontends/mn88472.c | 28 ++--
 1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/drivers/media/dvb-frontends/mn88472.c 
b/drivers/media/dvb-frontends/mn88472.c
index 29dd13b..25dd742 100644
--- a/drivers/media/dvb-frontends/mn88472.c
+++ b/drivers/media/dvb-frontends/mn88472.c
@@ -28,8 +28,9 @@ static int mn88472_read_status(struct dvb_frontend *fe, enum 
fe_status *status)
struct i2c_client *client = fe->demodulator_priv;
struct mn88472_dev *dev = i2c_get_clientdata(client);
struct dtv_frontend_properties *c = >dtv_property_cache;
-   int ret;
-   unsigned int utmp;
+   int ret, i;
+   unsigned int utmp, utmp1;
+   u8 buf[2];
 
if (!dev->active) {
ret = -EAGAIN;
@@ -77,6 +78,24 @@ static int mn88472_read_status(struct dvb_frontend *fe, enum 
fe_status *status)
goto err;
}
 
+   /* Signal strength */
+   if (*status & FE_HAS_SIGNAL) {
+   for (i = 0; i < 2; i++) {
+   ret = regmap_bulk_read(dev->regmap[2], 0x8e + i,
+  [i], 1);
+   if (ret)
+   goto err;
+   }
+
+   utmp1 = buf[0] << 8 | buf[1] << 0 | buf[0] >> 2;
+   dev_dbg(>dev, "strength=%u\n", utmp1);
+
+   c->strength.stat[0].scale = FE_SCALE_RELATIVE;
+   c->strength.stat[0].uvalue = utmp1;
+   } else {
+   c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   }
+
return 0;
 err:
dev_dbg(>dev, "failed=%d\n", ret);
@@ -462,6 +481,7 @@ static int mn88472_probe(struct i2c_client *client,
 {
struct mn88472_config *pdata = client->dev.platform_data;
struct mn88472_dev *dev;
+   struct dtv_frontend_properties *c;
int ret;
unsigned int utmp;
static const struct regmap_config regmap_config = {
@@ -547,6 +567,10 @@ static int mn88472_probe(struct i2c_client *client,
*pdata->fe = >fe;
i2c_set_clientdata(client, dev);
 
+   /* Init stats to indicate which stats are supported */
+   c = >fe.dtv_property_cache;
+   c->strength.len = 1;
+
/* Setup callbacks */
pdata->get_dvb_frontend = mn88472_get_dvb_frontend;
 
-- 
http://palosaari.fi/



[PATCH 2/3] mn88472: implement cnr statistics

2017-03-17 Thread Antti Palosaari
Implement DVBv5 CNR.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/dvb-frontends/mn88472.c  | 90 +-
 drivers/media/dvb-frontends/mn88472_priv.h |  1 +
 2 files changed, 88 insertions(+), 3 deletions(-)

diff --git a/drivers/media/dvb-frontends/mn88472.c 
b/drivers/media/dvb-frontends/mn88472.c
index 25dd742..c7e5f63 100644
--- a/drivers/media/dvb-frontends/mn88472.c
+++ b/drivers/media/dvb-frontends/mn88472.c
@@ -28,9 +28,9 @@ static int mn88472_read_status(struct dvb_frontend *fe, enum 
fe_status *status)
struct i2c_client *client = fe->demodulator_priv;
struct mn88472_dev *dev = i2c_get_clientdata(client);
struct dtv_frontend_properties *c = >dtv_property_cache;
-   int ret, i;
-   unsigned int utmp, utmp1;
-   u8 buf[2];
+   int ret, i, stmp;
+   unsigned int utmp, utmp1, utmp2;
+   u8 buf[5];
 
if (!dev->active) {
ret = -EAGAIN;
@@ -96,6 +96,89 @@ static int mn88472_read_status(struct dvb_frontend *fe, enum 
fe_status *status)
c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
}
 
+   /* CNR */
+   if (*status & FE_HAS_VITERBI && c->delivery_system == SYS_DVBT) {
+   /* DVB-T CNR */
+   ret = regmap_bulk_read(dev->regmap[0], 0x9c, buf, 2);
+   if (ret)
+   goto err;
+
+   utmp = buf[0] << 8 | buf[1] << 0;
+   if (utmp) {
+   /* CNR[dB]: 10 * log10(65536 / value) + 2 */
+   /* log10(65536) = 80807124, 0.2 = 3355443 */
+   stmp = ((u64)80807124 - intlog10(utmp) + 3355443)
+  * 1 >> 24;
+
+   dev_dbg(>dev, "cnr=%d value=%u\n", stmp, utmp);
+   } else {
+   stmp = 0;
+   }
+
+   c->cnr.stat[0].svalue = stmp;
+   c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+   } else if (*status & FE_HAS_VITERBI &&
+  c->delivery_system == SYS_DVBT2) {
+   /* DVB-T2 CNR */
+   for (i = 0; i < 3; i++) {
+   ret = regmap_bulk_read(dev->regmap[2], 0xbc + i,
+  [i], 1);
+   if (ret)
+   goto err;
+   }
+
+   utmp = buf[1] << 8 | buf[2] << 0;
+   utmp1 = (buf[0] >> 2) & 0x01; /* 0=SISO, 1=MISO */
+   if (utmp) {
+   if (utmp1) {
+   /* CNR[dB]: 10 * log10(16384 / value) - 6 */
+   /* log10(16384) = 70706234, 0.6 = 10066330 */
+   stmp = ((u64)70706234 - intlog10(utmp)
+  - 10066330) * 1 >> 24;
+   dev_dbg(>dev, "cnr=%d value=%u MISO\n",
+   stmp, utmp);
+   } else {
+   /* CNR[dB]: 10 * log10(65536 / value) + 2 */
+   /* log10(65536) = 80807124, 0.2 = 3355443 */
+   stmp = ((u64)80807124 - intlog10(utmp)
+  + 3355443) * 1 >> 24;
+
+   dev_dbg(>dev, "cnr=%d value=%u SISO\n",
+   stmp, utmp);
+   }
+   } else {
+   stmp = 0;
+   }
+
+   c->cnr.stat[0].svalue = stmp;
+   c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+   } else if (*status & FE_HAS_VITERBI &&
+  c->delivery_system == SYS_DVBC_ANNEX_A) {
+   /* DVB-C CNR */
+   ret = regmap_bulk_read(dev->regmap[1], 0xa1, buf, 4);
+   if (ret)
+   goto err;
+
+   utmp1 = buf[0] << 8 | buf[1] << 0; /* signal */
+   utmp2 = buf[2] << 8 | buf[3] << 0; /* noise */
+   if (utmp1 && utmp2) {
+   /* CNR[dB]: 10 * log10(8 * (signal / noise)) */
+   /* log10(8) = 15151336 */
+   stmp = ((u64)15151336 + intlog10(utmp1)
+  - intlog10(utmp2)) * 1 >> 24;
+
+   dev_dbg(>dev, "cnr=%d signal=%u noise=%u\n",
+   stmp, utmp1, utmp2);
+   } else {
+   stmp = 0;
+   }
+
+   c->cnr.stat[0].svalue = stmp;
+   c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+   } else {
+   c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+   }
+
r

Re: [PATCH 12/13] [media] tuners/tda18212: add flag for retrying tuner init on failure

2017-03-13 Thread Antti Palosaari

On 03/07/2017 08:57 PM, Daniel Scheller wrote:

From: Daniel Scheller 

Taken from tda18212dd, first read after cold reset sometimes fails on some
cards, trying twice shall do the trick. This is the case with the STV0367
demods soldered on the CineCTv6 bridge boards and older DuoFlex CT modules.

All other users (configs) of the tda18212 are updated as well to be sure
they won't be affected at all by this change.


That sounds like a i2c adapter problem and fix should be there, no hack 
on a tuner driver.


Antti



Signed-off-by: Daniel Scheller 
---
 drivers/media/platform/sti/c8sectpfe/c8sectpfe-dvb.c | 1 +
 drivers/media/tuners/tda18212.c  | 5 +
 drivers/media/tuners/tda18212.h  | 7 +++
 drivers/media/usb/dvb-usb-v2/anysee.c| 2 ++
 drivers/media/usb/em28xx/em28xx-dvb.c| 1 +
 5 files changed, 16 insertions(+)

diff --git a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-dvb.c 
b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-dvb.c
index 2c0015b..03688ee 100644
--- a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-dvb.c
+++ b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-dvb.c
@@ -111,6 +111,7 @@ static struct tda18212_config tda18212_conf = {
.if_dvbt_7 = 4150,
.if_dvbt_8 = 4500,
.if_dvbc = 5000,
+   .init_flags = 0,
 };

 int c8sectpfe_frontend_attach(struct dvb_frontend **fe,
diff --git a/drivers/media/tuners/tda18212.c b/drivers/media/tuners/tda18212.c
index 7b80683..2488537 100644
--- a/drivers/media/tuners/tda18212.c
+++ b/drivers/media/tuners/tda18212.c
@@ -220,6 +220,11 @@ static int tda18212_probe(struct i2c_client *client,
fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */

ret = regmap_read(dev->regmap, 0x00, _id);
+
+   /* retry probe if desired */
+   if (ret && (cfg->init_flags & TDA18212_INIT_RETRY))
+   ret = regmap_read(dev->regmap, 0x00, _id);
+
dev_dbg(>client->dev, "chip_id=%02x\n", chip_id);

if (fe->ops.i2c_gate_ctrl)
diff --git a/drivers/media/tuners/tda18212.h b/drivers/media/tuners/tda18212.h
index 6391daf..717aa2c 100644
--- a/drivers/media/tuners/tda18212.h
+++ b/drivers/media/tuners/tda18212.h
@@ -23,6 +23,8 @@

 #include "dvb_frontend.h"

+#define TDA18212_INIT_RETRY(1 << 0)
+
 struct tda18212_config {
u16 if_dvbt_6;
u16 if_dvbt_7;
@@ -36,6 +38,11 @@ struct tda18212_config {
u16 if_atsc_qam;

/*
+* flags for tuner init control
+*/
+   u32 init_flags;
+
+   /*
 * pointer to DVB frontend
 */
struct dvb_frontend *fe;
diff --git a/drivers/media/usb/dvb-usb-v2/anysee.c 
b/drivers/media/usb/dvb-usb-v2/anysee.c
index 6795c0c..c35b66e 100644
--- a/drivers/media/usb/dvb-usb-v2/anysee.c
+++ b/drivers/media/usb/dvb-usb-v2/anysee.c
@@ -332,6 +332,7 @@ static struct tda18212_config anysee_tda18212_config = {
.if_dvbt_7 = 4150,
.if_dvbt_8 = 4150,
.if_dvbc = 5000,
+   .init_flags = 0,
 };

 static struct tda18212_config anysee_tda18212_config2 = {
@@ -342,6 +343,7 @@ static struct tda18212_config anysee_tda18212_config2 = {
.if_dvbt2_7 = 4000,
.if_dvbt2_8 = 4000,
.if_dvbc = 5000,
+   .init_flags = 0,
 };

 static struct cx24116_config anysee_cx24116_config = {
diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c 
b/drivers/media/usb/em28xx/em28xx-dvb.c
index 82edd37..143efb0 100644
--- a/drivers/media/usb/em28xx/em28xx-dvb.c
+++ b/drivers/media/usb/em28xx/em28xx-dvb.c
@@ -380,6 +380,7 @@ static struct tda18271_config kworld_ub435q_v2_config = {
 static struct tda18212_config kworld_ub435q_v3_config = {
.if_atsc_vsb= 3600,
.if_atsc_qam= 3600,
+   .init_flags = 0,
 };

 static struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = {



--
http://palosaari.fi/


Re: [PATCH v3 0/3] Add support for MyGica T230C DVB-T2 stick

2017-03-03 Thread Antti Palosaari

On 03/03/2017 08:35 PM, Brüns, Stefan wrote:

On Fr, 2017-02-17 at 01:55 +0100, Stefan Brüns wrote:

The required command sequence for the new tuner (Si2141) was traced
from the
current Windows driver and verified with a small python
script/libusb.
The changes to the Si2168 and dvbsky driver are mostly additions of
the
required IDs and some glue code.

Stefan Brüns (3):
  [media] si2157: Add support for Si2141-A10
  [media] si2168: add support for Si2168-D60
  [media] dvbsky: MyGica T230C support

 drivers/media/dvb-core/dvb-usb-ids.h  |  1 +
 drivers/media/dvb-frontends/si2168.c  |  4 ++
 drivers/media/dvb-frontends/si2168_priv.h |  2 +
 drivers/media/tuners/si2157.c | 23 +++-
 drivers/media/tuners/si2157_priv.h|  2 +
 drivers/media/usb/dvb-usb-v2/dvbsky.c | 88
+++
 6 files changed, 118 insertions(+), 2 deletions(-)


Instead of this series, a different patchset was accepted, although
Antti raised concerns about at least 2 of the 3 patches accpeted, more
specifically the si2157 patch contains some bogus initialization code,
and the T230C support were better added to the dvbsky driver instead of
 cxusb.


Patch set looks good. I ordered that device and it arrived yesterday. I 
will handle that during 2 weeks - it is now skiing holiday and I am at 
France alps whole next week. So just wait :)


regards
Antti

--
http://palosaari.fi/


Re: [PATCH v2 3/3] [media] dvbsky: MyGica T230C support

2017-02-16 Thread Antti Palosaari

On 02/16/2017 10:48 AM, Antti Palosaari wrote:

On 02/16/2017 01:31 AM, Stefan Bruens wrote:



+/* attach demod */
+memset(_config, 0, sizeof(si2168_config));


prefer sizeof dst


You mean sizeof(struct si2168_config) ?


yeah. See chapter 14 from kernel coding style documentation, it handles
issue slightly.


argh, I looked wrong! It is *correct*, do not change it. It is just as 
it should. Sorry about noise.


regards
Antti




--
http://palosaari.fi/


Re: [PATCH v2 3/3] [media] dvbsky: MyGica T230C support

2017-02-16 Thread Antti Palosaari

Hello

On 02/16/2017 01:31 AM, Stefan Bruens wrote:

Hi Antti,

first thanks for for the review. Note the t230c_attach is mostly a copy of the
t330_attach (which is very similar to the t680c_attach), so any of your
comments should probably applied to the other attach functions to have a
common coding style.


Old code could be bad, but imho you could make new code better even it 
makes existing diver coding style slightly inconsistent.




On Mittwoch, 15. Februar 2017 10:27:09 CET Antti Palosaari wrote:

On 02/15/2017 03:51 AM, Stefan Brüns wrote:

[...]

diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c
b/drivers/media/usb/dvb-usb-v2/dvbsky.c index 02dbc6c45423..729496e5a52e
100644
--- a/drivers/media/usb/dvb-usb-v2/dvbsky.c
+++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c
@@ -665,6 +665,68 @@ static int dvbsky_t330_attach(struct dvb_usb_adapter
*adap)>
return ret;

 }

+static int dvbsky_mygica_t230c_attach(struct dvb_usb_adapter *adap)
+{
+   struct dvbsky_state *state = adap_to_priv(adap);
+   struct dvb_usb_device *d = adap_to_d(adap);
+   int ret = 0;


you could return ret completely as you don't assign its value runtime


Sure, so something like:

  ...
  return 0;
fail_foo:
  xxx;
fail bar:
  yyy;
  return -ENODEV;

Some of the other attach functions assign ret = -ENODEV and then goto one of
the fail_foo: labels.



+   struct i2c_adapter *i2c_adapter;
+   struct i2c_client *client_demod, *client_tuner;
+   struct i2c_board_info info;
+   struct si2168_config si2168_config;
+   struct si2157_config si2157_config;
+
+   /* attach demod */
+   memset(_config, 0, sizeof(si2168_config));


prefer sizeof dst


You mean sizeof(struct si2168_config) ?


yeah. See chapter 14 from kernel coding style documentation, it handles 
issue slightly.





+   si2168_config.i2c_adapter = _adapter;
+   si2168_config.fe = >fe[0];
+   si2168_config.ts_mode = SI2168_TS_PARALLEL;
+   si2168_config.ts_clock_inv = 1;


it has boolean type


Sure


+   memset(, 0, sizeof(struct i2c_board_info));
+   strlcpy(info.type, "si2168", I2C_NAME_SIZE);


I would prefer sizeof dst here too.


Most occurences of similar code in media/usb/ use I2C_NAME_SIZE, found two
occurences of "strlcpy(buf, ..., sizeof(buf)), but of course I can change
this.


+   info.addr = 0x64;
+   info.platform_data = _config;
+
+   request_module(info.type);


Use module name here. Even it is same than device id on that case, it is
not always the case.


While si2157 driver has several supported chip types, si2168 only supports
si2168 (several revisions). Both request_module("foobar") and
request_module(info.type) are common in media/usb/. Change nevertheless?


+   client_demod = i2c_new_device(>i2c_adap, );
+   if (client_demod == NULL ||
+   client_demod->dev.driver == NULL)


You did not ran checkpatch.pl for that patch? or doesn't it complain
anymore about these?


Checkpatch did not complain.


Indentation seem seems to be wrong (see again coding style doc). Also 
those might fit into single line. And not sure comparing even to NULL, 
at least some point preferred style was !foo, but personally I don't mind.




[...]

@@ -858,6 +946,9 @@ static const struct usb_device_id dvbsky_id_table[] =
{

{ DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R4,

_s960_props, "Terratec Cinergy S2 Rev.4",
RC_MAP_DVBSKY) },

+   { DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C,
+   _t230c_props, "Mygica T230C DVB-T/T2/C",


Drop supported DTV standard names from device name. Also it is MyGica
not Mygica.


The print on the stick says: "MyGica(R) DVB-T2", label on the backside says
"T230C". According to the USB descriptors it is a "Geniatech"
"EyeTV Stick". According to the box it is a "MyGica(R)" "Mini DVB-T2 USB Stick
T230C"

Would "MyGica DVB-T2 T230C" be ok?


I would just use device commercial name, which one seems to be most 
official. Geniatech is manufacturer, but commercial brand they sell 
these is MyGica so at least it is not Geniatech EyeTV Stick which is 
something like design name.


regards
Antti

--
http://palosaari.fi/


Re: [PATCH v2 3/3] [media] dvbsky: MyGica T230C support

2017-02-15 Thread Antti Palosaari

On 02/15/2017 03:51 AM, Stefan Brüns wrote:

Mygica T230 DVB-T/T2/C USB stick support. It uses the same FX2/Si2168
bridge/demodulator combo as the other devices supported by the driver,
but uses the Si2141 tuner.
Several DVB-T (MPEG2) and DVB-T2 (H.265) channels were tested, as well as
the include remote control.

Signed-off-by: Stefan Brüns 
---
v2: add support to the dvbsky driver instead of cxusb, correct RC
model
---
 drivers/media/dvb-core/dvb-usb-ids.h  |  1 +
 drivers/media/usb/dvb-usb-v2/dvbsky.c | 91 +++
 2 files changed, 92 insertions(+)

diff --git a/drivers/media/dvb-core/dvb-usb-ids.h 
b/drivers/media/dvb-core/dvb-usb-ids.h
index a7a4674ccc40..ce4a3d574dd7 100644
--- a/drivers/media/dvb-core/dvb-usb-ids.h
+++ b/drivers/media/dvb-core/dvb-usb-ids.h
@@ -380,6 +380,7 @@
 #define USB_PID_SONY_PLAYTV0x0003
 #define USB_PID_MYGICA_D6890xd811
 #define USB_PID_MYGICA_T2300xc688
+#define USB_PID_MYGICA_T230C   0xc689
 #define USB_PID_ELGATO_EYETV_DIVERSITY 0x0011
 #define USB_PID_ELGATO_EYETV_DTT   0x0021
 #define USB_PID_ELGATO_EYETV_DTT_2 0x003f
diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c 
b/drivers/media/usb/dvb-usb-v2/dvbsky.c
index 02dbc6c45423..729496e5a52e 100644
--- a/drivers/media/usb/dvb-usb-v2/dvbsky.c
+++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c
@@ -665,6 +665,68 @@ static int dvbsky_t330_attach(struct dvb_usb_adapter *adap)
return ret;
 }

+static int dvbsky_mygica_t230c_attach(struct dvb_usb_adapter *adap)
+{
+   struct dvbsky_state *state = adap_to_priv(adap);
+   struct dvb_usb_device *d = adap_to_d(adap);
+   int ret = 0;


you could return ret completely as you don't assign its value runtime


+   struct i2c_adapter *i2c_adapter;
+   struct i2c_client *client_demod, *client_tuner;
+   struct i2c_board_info info;
+   struct si2168_config si2168_config;
+   struct si2157_config si2157_config;
+
+   /* attach demod */
+   memset(_config, 0, sizeof(si2168_config));


prefer sizeof dst


+   si2168_config.i2c_adapter = _adapter;
+   si2168_config.fe = >fe[0];
+   si2168_config.ts_mode = SI2168_TS_PARALLEL;
+   si2168_config.ts_clock_inv = 1;

it has boolean type


+   memset(, 0, sizeof(struct i2c_board_info));
+   strlcpy(info.type, "si2168", I2C_NAME_SIZE);

I would prefer sizeof dst here too.


+   info.addr = 0x64;
+   info.platform_data = _config;
+
+   request_module(info.type);
Use module name here. Even it is same than device id on that case, it is 
not always the case.



+   client_demod = i2c_new_device(>i2c_adap, );
+   if (client_demod == NULL ||
+   client_demod->dev.driver == NULL)


You did not ran checkpatch.pl for that patch? or doesn't it complain 
anymore about these?



+   goto fail_demod_device;
+   if (!try_module_get(client_demod->dev.driver->owner))
+   goto fail_demod_module;
+
+   /* attach tuner */
+   memset(_config, 0, sizeof(si2157_config));
+   si2157_config.fe = adap->fe[0];
+   si2157_config.if_port = 0;
+   memset(, 0, sizeof(struct i2c_board_info));
+   strlcpy(info.type, "si2141", I2C_NAME_SIZE);
+   info.addr = 0x60;
+   info.platform_data = _config;
+
+   request_module("si2157");
+   client_tuner = i2c_new_device(i2c_adapter, );
+   if (client_tuner == NULL ||
+   client_tuner->dev.driver == NULL)
+   goto fail_tuner_device;
+   if (!try_module_get(client_tuner->dev.driver->owner))
+   goto fail_tuner_module;
+
+   state->i2c_client_demod = client_demod;
+   state->i2c_client_tuner = client_tuner;
+   return ret;
+fail_tuner_module:
+   i2c_unregister_device(client_tuner);
+fail_tuner_device:
+   module_put(client_demod->dev.driver->owner);
+fail_demod_module:
+   i2c_unregister_device(client_demod);
+fail_demod_device:
+   ret = -ENODEV;
+   return ret;
+}
+
+
 static int dvbsky_identify_state(struct dvb_usb_device *d, const char **name)
 {
dvbsky_gpio_ctrl(d, 0x04, 1);
@@ -830,6 +892,32 @@ static struct dvb_usb_device_properties dvbsky_t330_props 
= {
}
 };

+static struct dvb_usb_device_properties mygica_t230c_props = {
+   .driver_name = KBUILD_MODNAME,
+   .owner = THIS_MODULE,
+   .adapter_nr = adapter_nr,
+   .size_of_priv = sizeof(struct dvbsky_state),
+
+   .generic_bulk_ctrl_endpoint = 0x01,
+   .generic_bulk_ctrl_endpoint_response = 0x81,
+   .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
+
+   .i2c_algo = _i2c_algo,
+   .frontend_attach  = dvbsky_mygica_t230c_attach,
+   .init = dvbsky_init,
+   .get_rc_config= dvbsky_get_rc_config,
+   .streaming_ctrl   = 

Re: [PATCH 2/3] si2157: Si2141/2151 tuner support.

2017-02-12 Thread Antti Palosaari

Hello
You still didn't addressed the issues I pointed. For example that 
repeating loop looks simply wrong and you don't even care to add comment 
why this kind of ugly looking hack is there.


Stefan sent yesterday new set of patches for this device and those looks 
correct. There is not even that kind of strange reset loop.


regards
Antti


On 02/07/2017 11:35 PM, CrazyCat wrote:

Support for new tuner version.

Signed-off-by: Evgeny Plehov <evgenyple...@ukr.net>
---
 drivers/media/tuners/si2157.c  | 70 ++
 drivers/media/tuners/si2157_priv.h |  2 ++
 2 files changed, 66 insertions(+), 6 deletions(-)

diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c
index 57b2508..b46b149 100644
--- a/drivers/media/tuners/si2157.c
+++ b/drivers/media/tuners/si2157.c
@@ -1,5 +1,5 @@
 /*
- * Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner driver
+ * Silicon Labs Si2141/2146/2147/2148/2151/2157/2158 silicon tuner driver
  *
  * Copyright (C) 2014 Antti Palosaari <cr...@iki.fi>
  *
@@ -75,6 +75,7 @@ static int si2157_cmd_execute(struct i2c_client *client, 
struct si2157_cmd *cmd)
return ret;
 }

+#define MAX_RESET_ATTEMPTS 10
 static int si2157_init(struct dvb_frontend *fe)
 {
struct i2c_client *client = fe->tuner_priv;
@@ -84,7 +85,7 @@ static int si2157_init(struct dvb_frontend *fe)
struct si2157_cmd cmd;
const struct firmware *fw;
const char *fw_name;
-   unsigned int uitmp, chip_id;
+   unsigned int uitmp, chip_id, i;

dev_dbg(>dev, "\n");

@@ -102,14 +103,44 @@ static int si2157_init(struct dvb_frontend *fe)
if (uitmp == dev->if_frequency / 1000)
goto warm;

+   if (dev->chiptype == SI2157_CHIPTYPE_SI2141) {
+   for (i = 0; i < MAX_RESET_ATTEMPTS; i++)  {
+   /* reset */
+   memcpy(cmd.args, "\xc0\x05\x00\x00", 4);
+   cmd.wlen = 4;
+   cmd.rlen = 1;
+   ret = si2157_cmd_execute(client, );
+   if (ret)
+   goto err;
+
+   memcpy(cmd.args, 
"\xc0\x00\x0d\x0e\x00\x01\x01\x01\x01\x03", 10);
+   cmd.wlen = 10;
+   cmd.rlen = 1;
+   ret = si2157_cmd_execute(client, );
+   if (ret)
+   goto err;
+   if (cmd.args[0] != 0xfe)
+   break;
+   }
+   if (i >= MAX_RESET_ATTEMPTS)
+   goto err;
+   }
+
/* power up */
-   if (dev->chiptype == SI2157_CHIPTYPE_SI2146) {
+   switch (dev->chiptype) {
+   case SI2157_CHIPTYPE_SI2146:
memcpy(cmd.args, "\xc0\x05\x01\x00\x00\x0b\x00\x00\x01", 9);
cmd.wlen = 9;
-   } else {
+   break;
+   case SI2157_CHIPTYPE_SI2141:
+   memcpy(cmd.args, "\xc0\x08\x01\x02\x00\x08\x01", 7);
+   cmd.wlen = 7;
+   break;
+   default:
memcpy(cmd.args, 
"\xc0\x00\x0c\x00\x00\x01\x01\x01\x01\x01\x01\x02\x00\x00\x01", 15);
cmd.wlen = 15;
}
+
cmd.rlen = 1;
ret = si2157_cmd_execute(client, );
if (ret)
@@ -131,6 +162,8 @@ static int si2157_init(struct dvb_frontend *fe)
#define SI2157_A30 ('A' << 24 | 57 << 16 | '3' << 8 | '0' << 0)
#define SI2147_A30 ('A' << 24 | 47 << 16 | '3' << 8 | '0' << 0)
#define SI2146_A10 ('A' << 24 | 46 << 16 | '1' << 8 | '0' << 0)
+   #define SI2141_A10 ('A' << 24 | 41 << 16 | '1' << 8 | '0' << 0)
+   #define SI2151_A10 ('A' << 24 | 51 << 16 | '1' << 8 | '0' << 0)

switch (chip_id) {
case SI2158_A20:
@@ -142,6 +175,10 @@ static int si2157_init(struct dvb_frontend *fe)
case SI2146_A10:
fw_name = NULL;
break;
+   case SI2141_A10:
+   case SI2151_A10:
+   fw_name = SI2141_A10_FIRMWARE;
+   break;
default:
dev_err(>dev, "unknown chip version Si21%d-%c%c%c\n",
cmd.args[2], cmd.args[1],
@@ -214,6 +251,23 @@ static int si2157_init(struct dvb_frontend *fe)

dev_info(>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, );
+   if (ret)
+  

Re: [PATCH 0/3] Add support for MyGica T230C DVB-T2 stick

2017-02-12 Thread Antti Palosaari

On 02/12/2017 05:26 PM, Stefan Brüns wrote:

The required command sequence for the new tuner (Si2141) was traced from the
current Windows driver and verified with a small python script/libusb.
The changes to the Si2168 and cxusb driver are mostly addition of the
required IDs and some glue code.

Stefan Brüns (3):
  [media] si2157: Add support for Si2141-A10
  [media] si2168: add support for Si2168-D60
  [media] cxusb: MyGica T230C support

 drivers/media/dvb-core/dvb-usb-ids.h  |  1 +
 drivers/media/dvb-frontends/si2168.c  |  4 ++
 drivers/media/dvb-frontends/si2168_priv.h |  2 +
 drivers/media/tuners/si2157.c | 23 -
 drivers/media/tuners/si2157_priv.h|  2 +
 drivers/media/usb/dvb-usb/cxusb.c | 80 +--
 6 files changed, 106 insertions(+), 6 deletions(-)



Patch set looks pretty correct, but remote controller is something I 
hope you could fix. Old T230 did it wrong and defined 
rc_map_d680_dmb_table whilst proper map is 
RC_MAP_TOTAL_MEDIA_IN_HAND_02. Secondly it should be converted to 
rc-core. Even those are wrong for old revision, for new devices those 
should be done correct.


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


Re: [PATCH 2/2] [media] cx231xx: Fix I2C on Internal Master 3 Bus

2017-02-12 Thread Antti Palosaari

On 02/07/2017 09:35 PM, Oleh Kravchenko wrote:

Internal Master 3 Bus can send and receive only 4 bytes per time.

Signed-off-by: Oleh Kravchenko 
---
 drivers/media/usb/cx231xx/cx231xx-core.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c 
b/drivers/media/usb/cx231xx/cx231xx-core.c
index 550ec93..46646ec 100644
--- a/drivers/media/usb/cx231xx/cx231xx-core.c
+++ b/drivers/media/usb/cx231xx/cx231xx-core.c
@@ -355,7 +355,12 @@ int cx231xx_send_vendor_cmd(struct cx231xx *dev,
 */
if ((ven_req->wLength > 4) && ((ven_req->bRequest == 0x4) ||
(ven_req->bRequest == 0x5) ||
-   (ven_req->bRequest == 0x6))) {
+   (ven_req->bRequest == 0x6) ||
+
+   /* Internal Master 3 Bus can send
+* and receive only 4 bytes per time
+*/
+   (ven_req->bRequest == 0x2))) {
unsend_size = 0;
pdata = ven_req->pBuff;




Good that you finally got i2c fixed properly and get rid of that ugly 
device specific hack.


That new comment still does not open for me, why you call i2c bus tuner 
sits as internal?


There is now commands 2, 4, 5, and 6 that should be split to 4 byte 
long, is there any vendor command that could be longer? Maybe you could 
just add single comment which states what all those 4 commands are.


Your patches are still on wrong order - you should first fix i2c and 
after that add device support.


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


Re: rtl2832_sdr and /dev/swradio0

2017-02-01 Thread Antti Palosaari

On 01/31/2017 07:50 PM, Russel Winder wrote:

Hi,

Is anyone actively working on the rtl2832_sdr driver?

I am particularly interested in anyone who has code for turning the
byte stream from /dev/swradio0 into an ETI stream. Or failing that
getting enough data about the API for using /dev/swradio0 so as to
write a byte sequence to ETI driver based on the dab2eti program in
DABtool (which uses the librtlsdr mechanism instead of the
/dev/swradio0 one).



Easiest way to test it just use v4l2-ctl to configure device and then 
read data from device file.


$ #set ADC 2M
$ v4l2-ctl -d /dev/swradio0 --tuner=0 --set-freq=2.000
Frequency for tuner 0 set to 200 (2.00 MHz)
$ #set rf tuner 98.1MHz
$ v4l2-ctl -d /dev/swradio0 --tuner=1 --set-freq=98.1
Frequency for tuner 1 set to 9810 (98.10 MHz)
$ # dump 32 I/Q samples
$ cat /dev/swradio0 |hexdump -n 64 -C
  80 80 7e 7d 84 84 70 71  a8 5f 74 9f 6e 53 b4 9d 
|..~}..pq._t.nS..|
0010  53 8f 9e 4c 71 b8 75 28  a1 8a 57 8c 9d 46 73 c7 
|S..Lq.u(..W..Fs.|
0020  79 60 a6 ae 36 82 94 60  6c bf 7e 6a a7 9e 55 73 
|y`..6..`l.~j..Us|
0030  a8 72 5c a6 7f 35 a2 a2  61 54 ce 8a 57 b3 8e 50 
|.r\..5..aT..W..P|

0040
$

Looking v4l2-ctl code could give some ideas how to use control IOCTLs. 
Data can be read both read() or mmap() method.



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


[GIT PULL 4.11] drop unused hd29l2 driver

2017-02-01 Thread Antti Palosaari

The following changes since commit d183e4efcae8d88a2f252e546978658ca6d273cc:

  [media] v4l: tvp5150: Add missing break in set control handler 
(2016-12-12 07:49:58 -0200)


are available in the git repository at:

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

for you to fetch changes up to aacb6916b411c17d8372a5da46f94b39c5fd297a:

  hd29l2: remove unused driver (2017-01-27 19:25:19 +0200)


Antti Palosaari (2):
  MAINTAINERS: remove hd29l2
  hd29l2: remove unused driver

 MAINTAINERS   |  10 --
 drivers/media/dvb-frontends/Kconfig   |   7 --
 drivers/media/dvb-frontends/Makefile  |   1 -
 drivers/media/dvb-frontends/hd29l2.c  | 870 


 drivers/media/dvb-frontends/hd29l2.h  |  65 ---
 drivers/media/dvb-frontends/hd29l2_priv.h | 301 
-

 6 files changed, 1254 deletions(-)
 delete mode 100644 drivers/media/dvb-frontends/hd29l2.c
 delete mode 100644 drivers/media/dvb-frontends/hd29l2.h
 delete mode 100644 drivers/media/dvb-frontends/hd29l2_priv.h

--
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.11] zd1301 usb interface + dvb-t demod driver

2017-02-01 Thread Antti Palosaari

The following changes since commit c739c0a7c3c2472d7562b8f802cdce44d2597c8b:

  [media] s5k4ecgx: select CRC32 helper (2016-12-21 07:33:40 -0200)

are available in the git repository at:

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

for you to fetch changes up to 3b58fcff6d2578f83be4eb018274d6e82fcef426:

  mt2060: implement sleep (2017-01-27 18:44:37 +0200)


Antti Palosaari (7):
  mt2060: add i2c bindings
  mt2060: add param to split long i2c writes
  zd1301_demod: ZyDAS ZD1301 DVB-T demodulator driver
  MAINTAINERS: add zd1301_demod driver
  zd1301: ZyDAS ZD1301 DVB USB interface driver
  MAINTAINERS: add zd1301 DVB USB interface driver
  mt2060: implement sleep

 MAINTAINERS|  18 +
 drivers/media/dvb-core/dvb-usb-ids.h   |   1 +
 drivers/media/dvb-frontends/Kconfig|   7 ++
 drivers/media/dvb-frontends/Makefile   |   1 +
 drivers/media/dvb-frontends/zd1301_demod.c | 551 
+++

 drivers/media/dvb-frontends/zd1301_demod.h |  55 ++
 drivers/media/tuners/mt2060.c  | 125 
++--

 drivers/media/tuners/mt2060.h  |  23 ++
 drivers/media/tuners/mt2060_priv.h |  11 +++
 drivers/media/usb/dvb-usb-v2/Kconfig   |   8 +++
 drivers/media/usb/dvb-usb-v2/Makefile  |   3 +
 drivers/media/usb/dvb-usb-v2/zd1301.c  | 294 
++

 12 files changed, 1093 insertions(+), 4 deletions(-)
 create mode 100644 drivers/media/dvb-frontends/zd1301_demod.c
 create mode 100644 drivers/media/dvb-frontends/zd1301_demod.h
 create mode 100644 drivers/media/usb/dvb-usb-v2/zd1301.c

--
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.11] af9035 misc changes

2017-01-27 Thread Antti Palosaari

The following changes since commit d183e4efcae8d88a2f252e546978658ca6d273cc:

  [media] v4l: tvp5150: Add missing break in set control handler 
(2016-12-12 07:49:58 -0200)


are available in the git repository at:

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

for you to fetch changes up to 935e7e49e1cdf6f4c9beb1366c060fb1226c23ae:

  af9033: estimate cnr from formula (2016-12-19 18:38:23 +0200)


Antti Palosaari (10):
  af9035: read and store whole eeprom
  af9033: convert to regmap api
  af9033: use 64-bit div macro where possible
  af9033: style related and minor changes
  af9033: return regmap for integrated IT913x tuner driver
  it913x: change driver model from i2c to platform
  af9035: register it9133 tuner using platform binding
  it913x: add chip device ids for binding
  af9035: correct demod i2c addresses
  af9033: estimate cnr from formula

 drivers/media/dvb-frontends/Kconfig   |   1 +
 drivers/media/dvb-frontends/af9033.c  | 837 


 drivers/media/dvb-frontends/af9033.h  |  13 ++-
 drivers/media/dvb-frontends/af9033_priv.h | 185 
+++

 drivers/media/tuners/it913x.c |  92 +++-
 drivers/media/tuners/it913x.h |  26 ++---
 drivers/media/usb/dvb-usb-v2/af9035.c | 267 
+

 drivers/media/usb/dvb-usb-v2/af9035.h |   7 +-
 8 files changed, 582 insertions(+), 846 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


[GIT PULL 4.11] si2168 ber and ucb statistics

2017-01-27 Thread Antti Palosaari

The following changes since commit d183e4efcae8d88a2f252e546978658ca6d273cc:

  [media] v4l: tvp5150: Add missing break in set control handler 
(2016-12-12 07:49:58 -0200)


are available in the git repository at:

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

for you to fetch changes up to 7a6d7b07e36a8161b56924d7e18a00f1b7e2436a:

  si2168: implement ucb statistics (2016-12-19 19:55:15 +0200)


Antti Palosaari (2):
  si2168: implement ber statistics
  si2168: implement ucb statistics

 drivers/media/dvb-frontends/si2168.c  | 70 
--

 drivers/media/dvb-frontends/si2168_priv.h |  1 +
 2 files changed, 69 insertions(+), 2 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 1/2] MAINTAINERS: remove hd29l2

2017-01-27 Thread Antti Palosaari
Drop unused driver.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 MAINTAINERS | 10 --
 1 file changed, 10 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 52cc077..761a3cc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5595,16 +5595,6 @@ L:   linux-par...@vger.kernel.org
 S: Maintained
 F: sound/parisc/harmony.*
 
-HD29L2 MEDIA DRIVER
-M: Antti Palosaari <cr...@iki.fi>
-L: linux-media@vger.kernel.org
-W: https://linuxtv.org
-W: http://palosaari.fi/linux/
-Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
-S: Maintained
-F: drivers/media/dvb-frontends/hd29l2*
-
 HEWLETT PACKARD ENTERPRISE ILO NMI WATCHDOG DRIVER
 M: Brian Boylston <brian.boyls...@hpe.com>
 S: Supported
-- 
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 2/2] hd29l2: remove unused driver

2017-01-27 Thread Antti Palosaari
Remove unused demod driver. Device that used it never went public.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/dvb-frontends/Kconfig   |   7 -
 drivers/media/dvb-frontends/Makefile  |   1 -
 drivers/media/dvb-frontends/hd29l2.c  | 870 --
 drivers/media/dvb-frontends/hd29l2.h  |  65 ---
 drivers/media/dvb-frontends/hd29l2_priv.h | 301 ---
 5 files changed, 1244 deletions(-)
 delete mode 100644 drivers/media/dvb-frontends/hd29l2.c
 delete mode 100644 drivers/media/dvb-frontends/hd29l2.h
 delete mode 100644 drivers/media/dvb-frontends/hd29l2_priv.h

diff --git a/drivers/media/dvb-frontends/Kconfig 
b/drivers/media/dvb-frontends/Kconfig
index c841fa1..1221e2a 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -447,13 +447,6 @@ config DVB_EC100
help
  Say Y when you want to support this frontend.
 
-config DVB_HD29L2
-   tristate "HDIC HD29L2"
-   depends on DVB_CORE && I2C
-   default m if !MEDIA_SUBDRV_AUTOSELECT
-   help
- Say Y when you want to support this frontend.
-
 config DVB_STV0367
tristate "ST STV0367 based"
depends on DVB_CORE && I2C
diff --git a/drivers/media/dvb-frontends/Makefile 
b/drivers/media/dvb-frontends/Makefile
index 93921a4..bfed0f63 100644
--- a/drivers/media/dvb-frontends/Makefile
+++ b/drivers/media/dvb-frontends/Makefile
@@ -99,7 +99,6 @@ obj-$(CONFIG_DVB_MN88472) += mn88472.o
 obj-$(CONFIG_DVB_MN88473) += mn88473.o
 obj-$(CONFIG_DVB_ISL6423) += isl6423.o
 obj-$(CONFIG_DVB_EC100) += ec100.o
-obj-$(CONFIG_DVB_HD29L2) += hd29l2.o
 obj-$(CONFIG_DVB_DS3000) += ds3000.o
 obj-$(CONFIG_DVB_TS2020) += ts2020.o
 obj-$(CONFIG_DVB_MB86A16) += mb86a16.o
diff --git a/drivers/media/dvb-frontends/hd29l2.c 
b/drivers/media/dvb-frontends/hd29l2.c
deleted file mode 100644
index 8b53633..000
--- a/drivers/media/dvb-frontends/hd29l2.c
+++ /dev/null
@@ -1,870 +0,0 @@
-/*
- * HDIC HD29L2 DMB-TH demodulator driver
- *
- * Copyright (C) 2011 Metropolia University of Applied Sciences, Electria R
- *
- * Author: Antti Palosaari <cr...@iki.fi>
- *
- *This program is free software; you can redistribute it and/or modify
- *it under the terms of the GNU General Public License as published by
- *the Free Software Foundation; either version 2 of the License, or
- *(at your option) any later version.
- *
- *This program is distributed in the hope that it will be useful,
- *but WITHOUT ANY WARRANTY; without even the implied warranty of
- *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *GNU General Public License for more details.
- *
- *You should have received a copy of the GNU General Public License
- *along with this program; if not, write to the Free Software
- *Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "hd29l2_priv.h"
-
-#define HD29L2_MAX_LEN (3)
-
-/* write multiple registers */
-static int hd29l2_wr_regs(struct hd29l2_priv *priv, u8 reg, u8 *val, int len)
-{
-   int ret;
-   u8 buf[2 + HD29L2_MAX_LEN];
-   struct i2c_msg msg[1] = {
-   {
-   .addr = priv->cfg.i2c_addr,
-   .flags = 0,
-   .len = 2 + len,
-   .buf = buf,
-   }
-   };
-
-   if (len > HD29L2_MAX_LEN)
-   return -EINVAL;
-   buf[0] = 0x00;
-   buf[1] = reg;
-   memcpy([2], val, len);
-
-   ret = i2c_transfer(priv->i2c, msg, 1);
-   if (ret == 1) {
-   ret = 0;
-   } else {
-   dev_warn(>i2c->dev,
-   "%s: i2c wr failed=%d reg=%02x len=%d\n",
-   KBUILD_MODNAME, ret, reg, len);
-   ret = -EREMOTEIO;
-   }
-
-   return ret;
-}
-
-/* read multiple registers */
-static int hd29l2_rd_regs(struct hd29l2_priv *priv, u8 reg, u8 *val, int len)
-{
-   int ret;
-   u8 buf[2] = { 0x00, reg };
-   struct i2c_msg msg[2] = {
-   {
-   .addr = priv->cfg.i2c_addr,
-   .flags = 0,
-   .len = 2,
-   .buf = buf,
-   }, {
-   .addr = priv->cfg.i2c_addr,
-   .flags = I2C_M_RD,
-   .len = len,
-   .buf = val,
-   }
-   };
-
-   ret = i2c_transfer(priv->i2c, msg, 2);
-   if (ret == 2) {
-   ret = 0;
-   } else {
-   dev_warn(>i2c->dev,
-   "%s: i2c rd failed=%d reg=%02x len=%d\n",
-   KBUILD_MODNAME, ret, reg, len);
-   ret = -EREMOTEIO;
-   }
-
-   return ret;
-}
-
-/* write single register */
-static int hd29l2_wr_r

[PATCH v3 3/7] zd1301_demod: ZyDAS ZD1301 DVB-T demodulator driver

2017-01-27 Thread Antti Palosaari
ZyDAS ZD1301 is chip having USB interface and DVB-T demodulator
integrated. This driver is for demodulator part.
Driver is very reduced, just basic demodulator functionality, no
statistics at all. It registers as a platform driver to driver core.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/dvb-frontends/Kconfig|   7 +
 drivers/media/dvb-frontends/Makefile   |   1 +
 drivers/media/dvb-frontends/zd1301_demod.c | 551 +
 drivers/media/dvb-frontends/zd1301_demod.h |  55 +++
 4 files changed, 614 insertions(+)
 create mode 100644 drivers/media/dvb-frontends/zd1301_demod.c
 create mode 100644 drivers/media/dvb-frontends/zd1301_demod.h

diff --git a/drivers/media/dvb-frontends/Kconfig 
b/drivers/media/dvb-frontends/Kconfig
index c841fa1..043b089 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -513,6 +513,13 @@ config DVB_AS102_FE
depends on DVB_CORE
default DVB_AS102
 
+config DVB_ZD1301_DEMOD
+   tristate "ZyDAS ZD1301"
+   depends on DVB_CORE && I2C
+   default m if !MEDIA_SUBDRV_AUTOSELECT
+   help
+ Say Y when you want to support this frontend.
+
 config DVB_GP8PSK_FE
tristate
depends on DVB_CORE
diff --git a/drivers/media/dvb-frontends/Makefile 
b/drivers/media/dvb-frontends/Makefile
index 93921a4..1ccdf5d 100644
--- a/drivers/media/dvb-frontends/Makefile
+++ b/drivers/media/dvb-frontends/Makefile
@@ -126,3 +126,4 @@ obj-$(CONFIG_DVB_TC90522) += tc90522.o
 obj-$(CONFIG_DVB_HORUS3A) += horus3a.o
 obj-$(CONFIG_DVB_ASCOT2E) += ascot2e.o
 obj-$(CONFIG_DVB_HELENE) += helene.o
+obj-$(CONFIG_DVB_ZD1301_DEMOD) += zd1301_demod.o
diff --git a/drivers/media/dvb-frontends/zd1301_demod.c 
b/drivers/media/dvb-frontends/zd1301_demod.c
new file mode 100644
index 000..fcf5f69
--- /dev/null
+++ b/drivers/media/dvb-frontends/zd1301_demod.c
@@ -0,0 +1,551 @@
+/*
+ * ZyDAS ZD1301 driver (demodulator)
+ *
+ * Copyright (C) 2015 Antti Palosaari <cr...@iki.fi>
+ *
+ *This program is free software; you can redistribute it and/or modify
+ *it under the terms of the GNU General Public License as published by
+ *the Free Software Foundation; either version 2 of the License, or
+ *(at your option) any later version.
+ *
+ *This program is distributed in the hope that it will be useful,
+ *but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *GNU General Public License for more details.
+ */
+
+#include "zd1301_demod.h"
+
+static u8 zd1301_demod_gain = 0x38;
+module_param_named(gain, zd1301_demod_gain, byte, 0644);
+MODULE_PARM_DESC(gain, "gain (value: 0x00 - 0x70, default: 0x38)");
+
+struct zd1301_demod_dev {
+   struct platform_device *pdev;
+   struct dvb_frontend frontend;
+   struct i2c_adapter adapter;
+   u8 gain;
+};
+
+static int zd1301_demod_wreg(struct zd1301_demod_dev *dev, u16 reg, u8 val)
+{
+   struct platform_device *pdev = dev->pdev;
+   struct zd1301_demod_platform_data *pdata = pdev->dev.platform_data;
+
+   return pdata->reg_write(pdata->reg_priv, reg, val);
+}
+
+static int zd1301_demod_rreg(struct zd1301_demod_dev *dev, u16 reg, u8 *val)
+{
+   struct platform_device *pdev = dev->pdev;
+   struct zd1301_demod_platform_data *pdata = pdev->dev.platform_data;
+
+   return pdata->reg_read(pdata->reg_priv, reg, val);
+}
+
+static int zd1301_demod_set_frontend(struct dvb_frontend *fe)
+{
+   struct zd1301_demod_dev *dev = fe->demodulator_priv;
+   struct platform_device *pdev = dev->pdev;
+   struct dtv_frontend_properties *c = >dtv_property_cache;
+   int ret;
+   u32 if_frequency;
+   u8 r6a50_val;
+
+   dev_dbg(>dev, "frequency=%u bandwidth_hz=%u\n",
+   c->frequency, c->bandwidth_hz);
+
+   /* Program tuner */
+   if (fe->ops.tuner_ops.set_params &&
+   fe->ops.tuner_ops.get_if_frequency) {
+   ret = fe->ops.tuner_ops.set_params(fe);
+   if (ret)
+   goto err;
+   ret = fe->ops.tuner_ops.get_if_frequency(fe, _frequency);
+   if (ret)
+   goto err;
+   } else {
+   ret = -EINVAL;
+   goto err;
+   }
+
+   dev_dbg(>dev, "if_frequency=%u\n", if_frequency);
+   if (if_frequency != 3615) {
+   ret = -EINVAL;
+   goto err;
+   }
+
+   switch (c->bandwidth_hz) {
+   case 600:
+   r6a50_val = 0x78;
+   break;
+   case 700:
+   r6a50_val = 0x68;
+   break;
+   case 800:
+   r6a50_val = 0x58;
+   break;
+   default:
+   ret = -EINVAL;
+ 

[PATCH v3 6/7] MAINTAINERS: add zd1301 DVB USB interface driver

2017-01-27 Thread Antti Palosaari
DVB USB interface driver for ZyDAS ZD1301 chip.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 MAINTAINERS | 9 +
 1 file changed, 9 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 26ae0ac..101be59 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13389,6 +13389,15 @@ Q: 
https://patchwork.linuxtv.org/project/linux-media/list/
 S: Maintained
 F: drivers/media/dvb-frontends/zd1301_demod*
 
+ZD1301 MEDIA DRIVER
+M: Antti Palosaari <cr...@iki.fi>
+L: linux-media@vger.kernel.org
+W: https://linuxtv.org/
+W: http://palosaari.fi/linux/
+Q: https://patchwork.linuxtv.org/project/linux-media/list/
+S: Maintained
+F: drivers/media/usb/dvb-usb-v2/zd1301*
+
 ZPOOL COMPRESSED PAGE STORAGE API
 M: Dan Streetman <ddstr...@ieee.org>
 L: linux...@kvack.org
-- 
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 v3 7/7] mt2060: implement sleep

2017-01-27 Thread Antti Palosaari
I saw from ZyDAS ZD1301 sniffs it sets chip sleeping by using
REG_MISC_CTRL. That has very huge effect for power management, around
0.9W. Sleep is still disabled for all the old hardware just to avoid
possible regression as meaning of register bits are unknown.

I tested it also with some other devices and it seems to be working,
but I still consider it to be too risky to change it default.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/tuners/mt2060.c  | 25 +++--
 drivers/media/tuners/mt2060_priv.h |  8 
 2 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/drivers/media/tuners/mt2060.c b/drivers/media/tuners/mt2060.c
index 9775ded..6d404d5 100644
--- a/drivers/media/tuners/mt2060.c
+++ b/drivers/media/tuners/mt2060.c
@@ -317,9 +317,16 @@ static int mt2060_init(struct dvb_frontend *fe)
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
 
+   if (priv->sleep) {
+   ret = mt2060_writereg(priv, REG_MISC_CTRL, 0x20);
+   if (ret)
+   goto err_i2c_gate_ctrl;
+   }
+
ret = mt2060_writereg(priv, REG_VGAG,
  (priv->cfg->clock_out << 6) | 0x33);
 
+err_i2c_gate_ctrl:
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
 
@@ -336,7 +343,13 @@ static int mt2060_sleep(struct dvb_frontend *fe)
 
ret = mt2060_writereg(priv, REG_VGAG,
  (priv->cfg->clock_out << 6) | 0x30);
+   if (ret)
+   goto err_i2c_gate_ctrl;
+
+   if (priv->sleep)
+   ret = mt2060_writereg(priv, REG_MISC_CTRL, 0xe8);
 
+err_i2c_gate_ctrl:
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
 
@@ -439,6 +452,7 @@ static int mt2060_probe(struct i2c_client *client,
dev->if1_freq = pdata->if1 ? pdata->if1 : 1220;
dev->client = client;
dev->i2c_max_regs = pdata->i2c_write_max ? pdata->i2c_write_max - 1 : 
~0;
+   dev->sleep = true;
 
ret = mt2060_readreg(dev, REG_PART_REV, _id);
if (ret) {
@@ -453,14 +467,21 @@ static int mt2060_probe(struct i2c_client *client,
goto err;
}
 
+   /* Power on, calibrate, sleep */
+   ret = mt2060_writereg(dev, REG_MISC_CTRL, 0x20);
+   if (ret)
+   goto err;
+   mt2060_calibrate(dev);
+   ret = mt2060_writereg(dev, REG_MISC_CTRL, 0xe8);
+   if (ret)
+   goto err;
+
dev_info(>dev, "Microtune MT2060 successfully identified\n");
memcpy(>ops.tuner_ops, _tuner_ops, 
sizeof(fe->ops.tuner_ops));
fe->ops.tuner_ops.release = NULL;
fe->tuner_priv = dev;
i2c_set_clientdata(client, dev);
 
-   mt2060_calibrate(dev);
-
return 0;
 err:
dev_dbg(>dev, "failed=%d\n", ret);
diff --git a/drivers/media/tuners/mt2060_priv.h 
b/drivers/media/tuners/mt2060_priv.h
index f0fdb83..c0dac80 100644
--- a/drivers/media/tuners/mt2060_priv.h
+++ b/drivers/media/tuners/mt2060_priv.h
@@ -102,6 +102,14 @@ struct mt2060_priv {
u32 frequency;
u16 if1_freq;
u8  fmfreq;
+
+   /*
+* Use REG_MISC_CTRL register for sleep. That drops sleep power usage
+* about 0.9W (huge!). Register bit meanings are unknown, so let it be
+* disabled by default to avoid possible regression. Convert driver to
+* i2c model in order to enable it.
+*/
+   bool sleep;
 };
 
 #endif
-- 
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 v3 5/7] zd1301: ZyDAS ZD1301 DVB USB interface driver

2017-01-27 Thread Antti Palosaari
ZyDAS ZD1301 is chip having USB interface and DVB-T demodulator
integrated. This driver is for USB interface part.

Device has USB ID 0ace:13a1. Used tuner is MT2060.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/dvb-core/dvb-usb-ids.h  |   1 +
 drivers/media/usb/dvb-usb-v2/Kconfig  |   8 +
 drivers/media/usb/dvb-usb-v2/Makefile |   3 +
 drivers/media/usb/dvb-usb-v2/zd1301.c | 294 ++
 4 files changed, 306 insertions(+)
 create mode 100644 drivers/media/usb/dvb-usb-v2/zd1301.c

diff --git a/drivers/media/dvb-core/dvb-usb-ids.h 
b/drivers/media/dvb-core/dvb-usb-ids.h
index 779f422..55acd11 100644
--- a/drivers/media/dvb-core/dvb-usb-ids.h
+++ b/drivers/media/dvb-core/dvb-usb-ids.h
@@ -73,6 +73,7 @@
 #define USB_VID_GIGABYTE   0x1044
 #define USB_VID_YUAN   0x1164
 #define USB_VID_XTENSIONS  0x1ae7
+#define USB_VID_ZYDAS  0x0ace
 #define USB_VID_HUMAX_COEX 0x10b9
 #define USB_VID_7740x7a69
 #define USB_VID_EVOLUTEPC  0x1e59
diff --git a/drivers/media/usb/dvb-usb-v2/Kconfig 
b/drivers/media/usb/dvb-usb-v2/Kconfig
index 524533d..0e4944b 100644
--- a/drivers/media/usb/dvb-usb-v2/Kconfig
+++ b/drivers/media/usb/dvb-usb-v2/Kconfig
@@ -156,3 +156,11 @@ config DVB_USB_DVBSKY
select DVB_SP2 if MEDIA_SUBDRV_AUTOSELECT
help
  Say Y here to support the USB receivers from DVBSky.
+
+config DVB_USB_ZD1301
+   tristate "ZyDAS ZD1301"
+   depends on DVB_USB_V2
+   select DVB_ZD1301_DEMOD if MEDIA_SUBDRV_AUTOSELECT
+   select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT
+   help
+ Say Y here to support the ZyDAS ZD1301 DVB USB receiver.
diff --git a/drivers/media/usb/dvb-usb-v2/Makefile 
b/drivers/media/usb/dvb-usb-v2/Makefile
index f10d4df..969f68e 100644
--- a/drivers/media/usb/dvb-usb-v2/Makefile
+++ b/drivers/media/usb/dvb-usb-v2/Makefile
@@ -40,6 +40,9 @@ obj-$(CONFIG_DVB_USB_RTL28XXU) += dvb-usb-rtl28xxu.o
 dvb-usb-dvbsky-objs := dvbsky.o
 obj-$(CONFIG_DVB_USB_DVBSKY) += dvb-usb-dvbsky.o
 
+dvb-usb-zd1301-objs := zd1301.o
+obj-$(CONFIG_DVB_USB_ZD1301) += zd1301.o
+
 ccflags-y += -I$(srctree)/drivers/media/dvb-core
 ccflags-y += -I$(srctree)/drivers/media/dvb-frontends
 ccflags-y += -I$(srctree)/drivers/media/tuners
diff --git a/drivers/media/usb/dvb-usb-v2/zd1301.c 
b/drivers/media/usb/dvb-usb-v2/zd1301.c
new file mode 100644
index 000..563e50c
--- /dev/null
+++ b/drivers/media/usb/dvb-usb-v2/zd1301.c
@@ -0,0 +1,294 @@
+/*
+ * ZyDAS ZD1301 driver (USB interface)
+ *
+ * Copyright (C) 2015 Antti Palosaari <cr...@iki.fi>
+ *
+ *This program is free software; you can redistribute it and/or modify
+ *it under the terms of the GNU General Public License as published by
+ *the Free Software Foundation; either version 2 of the License, or
+ *(at your option) any later version.
+ *
+ *This program is distributed in the hope that it will be useful,
+ *but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *GNU General Public License for more details.
+ */
+
+#include "dvb_usb.h"
+#include "zd1301_demod.h"
+#include "mt2060.h"
+#include 
+#include 
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+struct zd1301_dev {
+   #define BUF_LEN 8
+   u8 buf[BUF_LEN]; /* bulk USB control message */
+   struct zd1301_demod_platform_data demod_pdata;
+   struct mt2060_platform_data mt2060_pdata;
+   struct platform_device *platform_device_demod;
+   struct i2c_client *i2c_client_tuner;
+};
+
+static int zd1301_ctrl_msg(struct dvb_usb_device *d, const u8 *wbuf,
+  unsigned int wlen, u8 *rbuf, unsigned int rlen)
+{
+   struct zd1301_dev *dev = d_to_priv(d);
+   struct usb_interface *intf = d->intf;
+   int ret, actual_length;
+
+   mutex_lock(>usb_mutex);
+
+   memcpy(>buf, wbuf, wlen);
+
+   dev_dbg(>dev, ">>> %*ph\n", wlen, dev->buf);
+
+   ret = usb_bulk_msg(d->udev, usb_sndbulkpipe(d->udev, 0x04), dev->buf,
+  wlen, _length, 1000);
+   if (ret) {
+   dev_err(>dev, "1st usb_bulk_msg() failed %d\n", ret);
+   goto err_mutex_unlock;
+   }
+
+   if (rlen) {
+   ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, 0x83),
+  dev->buf, rlen, _length, 1000);
+   if (ret) {
+   dev_err(>dev,
+   "2nd usb_bulk_msg() failed %d\n", ret);
+   goto err_mutex_unlock;
+   }
+
+   dev_dbg(>dev, "<<< %*ph\n", actual_length, dev->buf);

[PATCH v3 4/7] MAINTAINERS: add zd1301_demod driver

2017-01-27 Thread Antti Palosaari
DVB-T demodulator driver for ZyDAS ZD1301 chip.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 MAINTAINERS | 9 +
 1 file changed, 9 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 52cc077..26ae0ac 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13380,6 +13380,15 @@ L: zd1211-d...@lists.sourceforge.net 
(subscribers-only)
 S: Maintained
 F: drivers/net/wireless/zydas/zd1211rw/
 
+ZD1301_DEMOD MEDIA DRIVER
+M: Antti Palosaari <cr...@iki.fi>
+L: linux-media@vger.kernel.org
+W: https://linuxtv.org/
+W: http://palosaari.fi/linux/
+Q: https://patchwork.linuxtv.org/project/linux-media/list/
+S: Maintained
+F: drivers/media/dvb-frontends/zd1301_demod*
+
 ZPOOL COMPRESSED PAGE STORAGE API
 M: Dan Streetman <ddstr...@ieee.org>
 L: linux...@kvack.org
-- 
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 v3 1/7] mt2060: add i2c bindings

2017-01-27 Thread Antti Palosaari
Add proper i2c driver model bindings.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/tuners/mt2060.c  | 83 ++
 drivers/media/tuners/mt2060.h  | 20 +
 drivers/media/tuners/mt2060_priv.h |  2 +
 3 files changed, 105 insertions(+)

diff --git a/drivers/media/tuners/mt2060.c b/drivers/media/tuners/mt2060.c
index 94077ea..dc4f9a9 100644
--- a/drivers/media/tuners/mt2060.c
+++ b/drivers/media/tuners/mt2060.c
@@ -396,6 +396,89 @@ struct dvb_frontend * mt2060_attach(struct dvb_frontend 
*fe, struct i2c_adapter
 }
 EXPORT_SYMBOL(mt2060_attach);
 
+static int mt2060_probe(struct i2c_client *client,
+   const struct i2c_device_id *id)
+{
+   struct mt2060_platform_data *pdata = client->dev.platform_data;
+   struct dvb_frontend *fe;
+   struct mt2060_priv *dev;
+   int ret;
+   u8 chip_id;
+
+   dev_dbg(>dev, "\n");
+
+   if (!pdata) {
+   dev_err(>dev, "Cannot proceed without platform data\n");
+   ret = -EINVAL;
+   goto err;
+   }
+
+   dev = devm_kzalloc(>dev, sizeof(*dev), GFP_KERNEL);
+   if (!dev) {
+   ret = -ENOMEM;
+   goto err;
+   }
+
+   fe = pdata->dvb_frontend;
+   dev->config.i2c_address = client->addr;
+   dev->config.clock_out = pdata->clock_out;
+   dev->cfg = >config;
+   dev->i2c = client->adapter;
+   dev->if1_freq = pdata->if1 ? pdata->if1 : 1220;
+   dev->client = client;
+
+   ret = mt2060_readreg(dev, REG_PART_REV, _id);
+   if (ret) {
+   ret = -ENODEV;
+   goto err;
+   }
+
+   dev_dbg(>dev, "chip id=%02x\n", chip_id);
+
+   if (chip_id != PART_REV) {
+   ret = -ENODEV;
+   goto err;
+   }
+
+   dev_info(>dev, "Microtune MT2060 successfully identified\n");
+   memcpy(>ops.tuner_ops, _tuner_ops, 
sizeof(fe->ops.tuner_ops));
+   fe->ops.tuner_ops.release = NULL;
+   fe->tuner_priv = dev;
+   i2c_set_clientdata(client, dev);
+
+   mt2060_calibrate(dev);
+
+   return 0;
+err:
+   dev_dbg(>dev, "failed=%d\n", ret);
+   return ret;
+}
+
+static int mt2060_remove(struct i2c_client *client)
+{
+   dev_dbg(>dev, "\n");
+
+   return 0;
+}
+
+static const struct i2c_device_id mt2060_id_table[] = {
+   {"mt2060", 0},
+   {}
+};
+MODULE_DEVICE_TABLE(i2c, mt2060_id_table);
+
+static struct i2c_driver mt2060_driver = {
+   .driver = {
+   .name = "mt2060",
+   .suppress_bind_attrs = true,
+   },
+   .probe  = mt2060_probe,
+   .remove = mt2060_remove,
+   .id_table   = mt2060_id_table,
+};
+
+module_i2c_driver(mt2060_driver);
+
 MODULE_AUTHOR("Olivier DANET");
 MODULE_DESCRIPTION("Microtune MT2060 silicon tuner driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/media/tuners/mt2060.h b/drivers/media/tuners/mt2060.h
index 6efed35..05c0d55 100644
--- a/drivers/media/tuners/mt2060.h
+++ b/drivers/media/tuners/mt2060.h
@@ -25,6 +25,26 @@
 struct dvb_frontend;
 struct i2c_adapter;
 
+/*
+ * I2C address
+ * 0x60, ...
+ */
+
+/**
+ * struct mt2060_platform_data - Platform data for the mt2060 driver
+ * @clock_out: Clock output setting. 0 = off, 1 = CLK/4, 2 = CLK/2, 3 = CLK/1.
+ * @if1: First IF used [MHz]. 0 defaults to 1220.
+ * @dvb_frontend: DVB frontend.
+ */
+
+struct mt2060_platform_data {
+   u8 clock_out;
+   u16 if1;
+   struct dvb_frontend *dvb_frontend;
+};
+
+
+/* configuration struct for mt2060_attach() */
 struct mt2060_config {
u8 i2c_address;
u8 clock_out; /* 0 = off, 1 = CLK/4, 2 = CLK/2, 3 = CLK/1 */
diff --git a/drivers/media/tuners/mt2060_priv.h 
b/drivers/media/tuners/mt2060_priv.h
index 2b60de6..dfc4a06 100644
--- a/drivers/media/tuners/mt2060_priv.h
+++ b/drivers/media/tuners/mt2060_priv.h
@@ -95,6 +95,8 @@
 struct mt2060_priv {
struct mt2060_config *cfg;
struct i2c_adapter   *i2c;
+   struct i2c_client *client;
+   struct mt2060_config config;
 
u32 frequency;
u16 if1_freq;
-- 
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 v3 2/7] mt2060: add param to split long i2c writes

2017-01-27 Thread Antti Palosaari
Add configuration parameter to split long i2c writes as some I2C
adapters cannot write 10 bytes used as a one go.

Signed-off-by: Antti Palosaari <cr...@iki.fi>
---
 drivers/media/tuners/mt2060.c  | 21 +
 drivers/media/tuners/mt2060.h  |  3 +++
 drivers/media/tuners/mt2060_priv.h |  1 +
 3 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/drivers/media/tuners/mt2060.c b/drivers/media/tuners/mt2060.c
index dc4f9a9..9775ded 100644
--- a/drivers/media/tuners/mt2060.c
+++ b/drivers/media/tuners/mt2060.c
@@ -71,13 +71,24 @@ static int mt2060_writereg(struct mt2060_priv *priv, u8 
reg, u8 val)
 // Writes a set of consecutive registers
 static int mt2060_writeregs(struct mt2060_priv *priv,u8 *buf, u8 len)
 {
+   int rem, val_len;
+   u8 xfer_buf[16];
struct i2c_msg msg = {
-   .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = 
len
+   .addr = priv->cfg->i2c_address, .flags = 0, .buf = xfer_buf
};
-   if (i2c_transfer(priv->i2c, , 1) != 1) {
-   printk(KERN_WARNING "mt2060 I2C write failed 
(len=%i)\n",(int)len);
-   return -EREMOTEIO;
+
+   for (rem = len - 1; rem > 0; rem -= priv->i2c_max_regs) {
+   val_len = min_t(int, rem, priv->i2c_max_regs);
+   msg.len = 1 + val_len;
+   xfer_buf[0] = buf[0] + len - 1 - rem;
+   memcpy(_buf[1], [1 + len - 1 - rem], val_len);
+
+   if (i2c_transfer(priv->i2c, , 1) != 1) {
+   printk(KERN_WARNING "mt2060 I2C write failed 
(len=%i)\n", val_len);
+   return -EREMOTEIO;
+   }
}
+
return 0;
 }
 
@@ -369,6 +380,7 @@ struct dvb_frontend * mt2060_attach(struct dvb_frontend 
*fe, struct i2c_adapter
priv->cfg  = cfg;
priv->i2c  = i2c;
priv->if1_freq = if1;
+   priv->i2c_max_regs = ~0;
 
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
@@ -426,6 +438,7 @@ static int mt2060_probe(struct i2c_client *client,
dev->i2c = client->adapter;
dev->if1_freq = pdata->if1 ? pdata->if1 : 1220;
dev->client = client;
+   dev->i2c_max_regs = pdata->i2c_write_max ? pdata->i2c_write_max - 1 : 
~0;
 
ret = mt2060_readreg(dev, REG_PART_REV, _id);
if (ret) {
diff --git a/drivers/media/tuners/mt2060.h b/drivers/media/tuners/mt2060.h
index 05c0d55..f0572ac 100644
--- a/drivers/media/tuners/mt2060.h
+++ b/drivers/media/tuners/mt2060.h
@@ -34,12 +34,15 @@ struct i2c_adapter;
  * struct mt2060_platform_data - Platform data for the mt2060 driver
  * @clock_out: Clock output setting. 0 = off, 1 = CLK/4, 2 = CLK/2, 3 = CLK/1.
  * @if1: First IF used [MHz]. 0 defaults to 1220.
+ * @i2c_write_max: Maximum number of bytes I2C adapter can write at once.
+ *  0 defaults to maximum.
  * @dvb_frontend: DVB frontend.
  */
 
 struct mt2060_platform_data {
u8 clock_out;
u16 if1;
+   unsigned int i2c_write_max:5;
struct dvb_frontend *dvb_frontend;
 };
 
diff --git a/drivers/media/tuners/mt2060_priv.h 
b/drivers/media/tuners/mt2060_priv.h
index dfc4a06..f0fdb83 100644
--- a/drivers/media/tuners/mt2060_priv.h
+++ b/drivers/media/tuners/mt2060_priv.h
@@ -98,6 +98,7 @@ struct mt2060_priv {
struct i2c_client *client;
struct mt2060_config config;
 
+   u8 i2c_max_regs;
u32 frequency;
u16 if1_freq;
u8  fmfreq;
-- 
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.10] fix cxd2820r 4.9 regression

2017-01-23 Thread Antti Palosaari

The following changes since commit d183e4efcae8d88a2f252e546978658ca6d273cc:

  [media] v4l: tvp5150: Add missing break in set control handler 
(2016-12-12 07:49:58 -0200)


are available in the git repository at:

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

for you to fetch changes up to 783d933cf02e970b49e0dcb586a76207aa6fa331:

  cxd2820r: fix gpio null pointer dereference (2017-01-23 10:40:17 +0200)


Antti Palosaari (1):
  cxd2820r: fix gpio null pointer dereference

 drivers/media/dvb-frontends/cxd2820r_core.c | 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


  1   2   3   4   5   6   7   8   9   10   >