All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 0/5] dvb-usb-friio: decompose friio and merge with gl861
@ 2018-04-08 17:21 tskd08
  2018-04-08 17:21 ` [PATCH v5 1/5] dvb-frontends/dvb-pll: add i2c driver support tskd08
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: tskd08 @ 2018-04-08 17:21 UTC (permalink / raw)
  To: linux-media; +Cc: mchehab, Akihiro Tsukada, crope

From: Akihiro Tsukada <tskd08@gmail.com>

This series decomposes dvb-usb-friio into sub drivers
and merge the bridge driver with dvb-usb-gl861.
As to the demod & tuner drivers, existing drivers are re-used.

Changes since v4:
- dvb-pll,gl861: do not #define chip name constants
- i2c algo of gl861 is not (yet?) changed as proposed by Antti,
  (which is to move the special case handling to demod driver),
  since I do not yet understand
  whether it should/can be really moved or not.

Changes since v3:
- dvb-pll,gl681: use i2c_device_id/i2c_board_info to specify pll_desc

Changes since v2:
- used the new i2c binding helpers instead of my own one
- extends dvb-pll instead of creating a new tuner driver
- merged gl861-friio.c with gl861.c
- improved module counting
- made i2c communications on USB robust (regarding DMA)

Replaces:
patch #27927, dvb: tua6034: add a new driver for Infineon tua6034 tuner
patch #27928, dvb-usb-friio: split and merge into dvb-usbv2-gl861

Akihiro Tsukada (5):
  dvb-frontends/dvb-pll: add i2c driver support
  dvb-frontends/dvb-pll: add tua6034 ISDB-T tuner used in Friio
  dvb-usb/friio, dvb-usb-v2/gl861: decompose friio and merge with gl861
  dvb-usb-v2/gl861: use usleep_range() for short delay
  dvb-usb-v2/gl861: ensure  USB message buffers DMA'able

 drivers/media/dvb-frontends/dvb-pll.c |  86 +++++
 drivers/media/dvb-frontends/dvb-pll.h |   5 +
 drivers/media/usb/dvb-usb-v2/Kconfig  |   5 +-
 drivers/media/usb/dvb-usb-v2/gl861.c  | 485 +++++++++++++++++++++++-
 drivers/media/usb/dvb-usb-v2/gl861.h  |   1 +
 drivers/media/usb/dvb-usb/Kconfig     |   6 -
 drivers/media/usb/dvb-usb/Makefile    |   3 -
 drivers/media/usb/dvb-usb/friio-fe.c  | 441 ----------------------
 drivers/media/usb/dvb-usb/friio.c     | 522 --------------------------
 drivers/media/usb/dvb-usb/friio.h     |  99 -----
 10 files changed, 570 insertions(+), 1083 deletions(-)
 delete mode 100644 drivers/media/usb/dvb-usb/friio-fe.c
 delete mode 100644 drivers/media/usb/dvb-usb/friio.c
 delete mode 100644 drivers/media/usb/dvb-usb/friio.h

-- 
2.17.0

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v5 1/5] dvb-frontends/dvb-pll: add i2c driver support
  2018-04-08 17:21 [PATCH v5 0/5] dvb-usb-friio: decompose friio and merge with gl861 tskd08
@ 2018-04-08 17:21 ` tskd08
  2018-04-08 17:21 ` [PATCH v5 2/5] dvb-frontends/dvb-pll: add tua6034 ISDB-T tuner used in Friio tskd08
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 11+ messages in thread
From: tskd08 @ 2018-04-08 17:21 UTC (permalink / raw)
  To: linux-media; +Cc: mchehab, Akihiro Tsukada, crope

From: Akihiro Tsukada <tskd08@gmail.com>

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

Signed-off-by: Akihiro Tsukada <tskd08@gmail.com>
---
Changes since v4:
- do not #define chip name constants

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 |  4 ++
 2 files changed, 71 insertions(+)

diff --git a/drivers/media/dvb-frontends/dvb-pll.c b/drivers/media/dvb-frontends/dvb-pll.c
index 5553b89b804..ff0f477276a 100644
--- a/drivers/media/dvb-frontends/dvb-pll.c
+++ b/drivers/media/dvb-frontends/dvb-pll.c
@@ -827,6 +827,73 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
 }
 EXPORT_SYMBOL(dvb_pll_attach);
 
+
+static int
+dvb_pll_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	struct dvb_pll_config *cfg;
+	struct dvb_frontend *fe;
+	unsigned int desc_id;
+
+	cfg = client->dev.platform_data;
+	fe = cfg->fe;
+	i2c_set_clientdata(client, fe);
+	desc_id = (unsigned int) id->driver_data;
+
+	if (!dvb_pll_attach(fe, client->addr, client->adapter, desc_id))
+		return -ENOMEM;
+
+	dev_info(&client->dev, "DVB Simple Tuner attached.\n");
+	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[] = {
+	{"dtt7579",		DVB_PLL_THOMSON_DTT7579},
+	{"dtt759x",		DVB_PLL_THOMSON_DTT759X},
+	{"z201",		DVB_PLL_LG_Z201},
+	{"unknown_1",		DVB_PLL_UNKNOWN_1},
+	{"tua6010xs",		DVB_PLL_TUA6010XS},
+	{"env57h1xd5",		DVB_PLL_ENV57H1XD5},
+	{"tua6034",		DVB_PLL_TUA6034},
+	{"tda665x",		DVB_PLL_TDA665X},
+	{"tded4",		DVB_PLL_TDED4},
+	{"tdhu2",		DVB_PLL_TDHU2},
+	{"tbmv",		DVB_PLL_SAMSUNG_TBMV},
+	{"sd1878_tda8261",	DVB_PLL_PHILIPS_SD1878_TDA8261},
+	{"opera1",		DVB_PLL_OPERA1},
+	{"dtos403ih102a",	DVB_PLL_SAMSUNG_DTOS403IH102A},
+	{"tdtc9251dh0",		DVB_PLL_SAMSUNG_TDTC9251DH0},
+	{"tbdu18132",		DVB_PLL_SAMSUNG_TBDU18132},
+	{"tbmu24112",		DVB_PLL_SAMSUNG_TBMU24112},
+	{"tdee4",		DVB_PLL_TDEE4},
+	{"dtt7520x",		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..101537ae4ef 100644
--- a/drivers/media/dvb-frontends/dvb-pll.h
+++ b/drivers/media/dvb-frontends/dvb-pll.h
@@ -30,6 +30,10 @@
 #define DVB_PLL_TDEE4		       18
 #define DVB_PLL_THOMSON_DTT7520X       19
 
+struct dvb_pll_config {
+	struct dvb_frontend *fe;
+};
+
 #if IS_REACHABLE(CONFIG_DVB_PLL)
 /**
  * Attach a dvb-pll to the supplied frontend structure.
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v5 2/5] dvb-frontends/dvb-pll: add tua6034 ISDB-T tuner used in Friio
  2018-04-08 17:21 [PATCH v5 0/5] dvb-usb-friio: decompose friio and merge with gl861 tskd08
  2018-04-08 17:21 ` [PATCH v5 1/5] dvb-frontends/dvb-pll: add i2c driver support tskd08
@ 2018-04-08 17:21 ` tskd08
  2018-04-08 17:21 ` [PATCH v6 3/5] dvb-usb/friio, dvb-usb-v2/gl861: decompose friio and merge with gl861 tskd08
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 11+ messages in thread
From: tskd08 @ 2018-04-08 17:21 UTC (permalink / raw)
  To: linux-media; +Cc: mchehab, Akihiro Tsukada, crope

From: Akihiro Tsukada <tskd08@gmail.com>

This driver already contains tua6034-based device settings,
but they are not for ISDB-T and have different parameters.

Signed-off-by: Akihiro Tsukada <tskd08@gmail.com>
---
Changes since v4:
- do not #define chip name constant

Changes since v3:
- rebase on the new style of specifying pll_desc

Changes since v2:
(patch #27927 dvb: tua6034: add a new driver for Infineon tua6034 tuner)
- extends dvb-pll instead of creating a new driver

 drivers/media/dvb-frontends/dvb-pll.c | 19 +++++++++++++++++++
 drivers/media/dvb-frontends/dvb-pll.h |  1 +
 2 files changed, 20 insertions(+)

diff --git a/drivers/media/dvb-frontends/dvb-pll.c b/drivers/media/dvb-frontends/dvb-pll.c
index ff0f477276a..f7d444d09cf 100644
--- a/drivers/media/dvb-frontends/dvb-pll.c
+++ b/drivers/media/dvb-frontends/dvb-pll.c
@@ -533,6 +533,23 @@ static const struct dvb_pll_desc dvb_pll_alps_tdee4 = {
 	}
 };
 
+/* Infineon TUA6034 ISDB-T, used in Friio */
+/* CP cur. 50uA, AGC takeover: 103dBuV, PORT3 on */
+static const struct dvb_pll_desc dvb_pll_tua6034_friio = {
+	.name   = "Infineon TUA6034 ISDB-T (Friio)",
+	.min    =  90000000,
+	.max    = 770000000,
+	.iffreq =  57000000,
+	.initdata = (u8[]){ 4, 0x9a, 0x50, 0xb2, 0x08 },
+	.sleepdata = (u8[]){ 4, 0x9a, 0x70, 0xb3, 0x0b },
+	.count = 3,
+	.entries = {
+		{ 170000000, 142857, 0xba, 0x09 },
+		{ 470000000, 142857, 0xba, 0x0a },
+		{ 770000000, 142857, 0xb2, 0x08 },
+	}
+};
+
 /* ----------------------------------------------------------- */
 
 static const struct dvb_pll_desc *pll_list[] = {
@@ -556,6 +573,7 @@ static const struct dvb_pll_desc *pll_list[] = {
 	[DVB_PLL_SAMSUNG_TDTC9251DH0]    = &dvb_pll_samsung_tdtc9251dh0,
 	[DVB_PLL_SAMSUNG_TBDU18132]	 = &dvb_pll_samsung_tbdu18132,
 	[DVB_PLL_SAMSUNG_TBMU24112]      = &dvb_pll_samsung_tbmu24112,
+	[DVB_PLL_TUA6034_FRIIO]          = &dvb_pll_tua6034_friio,
 };
 
 /* ----------------------------------------------------------- */
@@ -877,6 +895,7 @@ static const struct i2c_device_id dvb_pll_id[] = {
 	{"tbmu24112",		DVB_PLL_SAMSUNG_TBMU24112},
 	{"tdee4",		DVB_PLL_TDEE4},
 	{"dtt7520x",		DVB_PLL_THOMSON_DTT7520X},
+	{"tua6034_friio",	DVB_PLL_TUA6034_FRIIO},
 	{}
 };
 
diff --git a/drivers/media/dvb-frontends/dvb-pll.h b/drivers/media/dvb-frontends/dvb-pll.h
index 101537ae4ef..7555407c2cc 100644
--- a/drivers/media/dvb-frontends/dvb-pll.h
+++ b/drivers/media/dvb-frontends/dvb-pll.h
@@ -29,6 +29,7 @@
 #define DVB_PLL_SAMSUNG_TBMU24112      17
 #define DVB_PLL_TDEE4		       18
 #define DVB_PLL_THOMSON_DTT7520X       19
+#define DVB_PLL_TUA6034_FRIIO          20
 
 struct dvb_pll_config {
 	struct dvb_frontend *fe;
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v6 3/5] dvb-usb/friio, dvb-usb-v2/gl861: decompose friio and merge with gl861
  2018-04-08 17:21 [PATCH v5 0/5] dvb-usb-friio: decompose friio and merge with gl861 tskd08
  2018-04-08 17:21 ` [PATCH v5 1/5] dvb-frontends/dvb-pll: add i2c driver support tskd08
  2018-04-08 17:21 ` [PATCH v5 2/5] dvb-frontends/dvb-pll: add tua6034 ISDB-T tuner used in Friio tskd08
@ 2018-04-08 17:21 ` tskd08
  2018-05-05 11:12   ` Mauro Carvalho Chehab
  2018-04-08 17:21 ` [PATCH v5 4/5] dvb-usb-v2/gl861: use usleep_range() for short delay tskd08
  2018-04-08 17:21 ` [PATCH v5 5/5] dvb-usb-v2/gl861: ensure USB message buffers DMA'able tskd08
  4 siblings, 1 reply; 11+ messages in thread
From: tskd08 @ 2018-04-08 17:21 UTC (permalink / raw)
  To: linux-media; +Cc: mchehab, Akihiro Tsukada, crope

From: Akihiro Tsukada <tskd08@gmail.com>

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.

Signed-off-by: Akihiro Tsukada <tskd08@gmail.com>
---
Changes since v5:
- specify chip name literally
- i2c algo of gl861 is not (yet?) changed as proposed by Antti,
  (which is to move the special case handling to demod driver),
  since I do not yet understand
  whether it should/can be really moved or not.

Changes since v4:
- use new style of specifying pll_desc id of the tuner driver

Changes since v3:
- make dvb_usb_device_properties static

Changes since v2:
(patch #27928, dvb-usb-friio: split and merge into dvb-usbv2-gl861)
 - used the new i2c binding helpers instead of my own one
 - merged gl861-friio.c with gl861.c

 drivers/media/usb/dvb-usb-v2/Kconfig |   5 +-
 drivers/media/usb/dvb-usb-v2/gl861.c | 465 +++++++++++++++++++++++-
 drivers/media/usb/dvb-usb-v2/gl861.h |   1 +
 drivers/media/usb/dvb-usb/Kconfig    |   6 -
 drivers/media/usb/dvb-usb/Makefile   |   3 -
 drivers/media/usb/dvb-usb/friio-fe.c | 441 ----------------------
 drivers/media/usb/dvb-usb/friio.c    | 522 ---------------------------
 drivers/media/usb/dvb-usb/friio.h    |  99 -----
 8 files changed, 462 insertions(+), 1080 deletions(-)
 delete mode 100644 drivers/media/usb/dvb-usb/friio-fe.c
 delete mode 100644 drivers/media/usb/dvb-usb/friio.c
 delete mode 100644 drivers/media/usb/dvb-usb/friio.h

diff --git a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig
index 0e4944b2b0f..e0a1f377295 100644
--- a/drivers/media/usb/dvb-usb-v2/Kconfig
+++ b/drivers/media/usb/dvb-usb-v2/Kconfig
@@ -95,10 +95,13 @@ config DVB_USB_GL861
 	tristate "Genesys Logic GL861 USB2.0 support"
 	depends on DVB_USB_V2
 	select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_TC90522 if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
 	help
 	  Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0
-	  receiver with USB ID 0db0:5581.
+	  receiver with USB ID 0db0:5581, Friio White ISDB-T receiver
+	  with USB ID 0x7a69:0001.
 
 config DVB_USB_LME2510
 	tristate "LME DM04/QQBOX DVB-S USB2.0 support"
diff --git a/drivers/media/usb/dvb-usb-v2/gl861.c b/drivers/media/usb/dvb-usb-v2/gl861.c
index b1b09c54786..ecff0062bfb 100644
--- a/drivers/media/usb/dvb-usb-v2/gl861.c
+++ b/drivers/media/usb/dvb-usb-v2/gl861.c
@@ -10,6 +10,8 @@
 
 #include "zl10353.h"
 #include "qt1010.h"
+#include "tc90522.h"
+#include "dvb-pll.h"
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
@@ -49,6 +51,80 @@ static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
 			       value, index, rbuf, rlen, 2000);
 }
 
+/* Friio specific I2C read/write */
+/* special USB request is used in Friio's init/config */
+static int
+gl861_i2c_rawwrite(struct dvb_usb_device *d, u8 addr, u8 *wbuf, u16 wlen)
+{
+	u8 *buf;
+	int ret;
+
+	buf = kmalloc(wlen, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	usleep_range(1000, 2000); /* avoid I2C errors */
+	memcpy(buf, wbuf, wlen);
+	ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
+				 GL861_REQ_I2C_RAW, GL861_WRITE,
+				 addr << (8 + 1), 0x0100, buf, wlen, 2000);
+	kfree(buf);
+	return ret;
+}
+
+/*
+ * In Friio,
+ * I2C commnucations to the tuner are relay'ed via the demod (via the bridge),
+ * so its encapsulation to USB message is different from the one to the demod.
+ */
+static int
+gl861_i2c_rawread(struct dvb_usb_device *d, u8 addr, u8 *rbuf, u16 rlen)
+{
+	u8 *buf;
+	int ret;
+
+	buf = kmalloc(rlen, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	usleep_range(1000, 2000); /* avoid I2C errors */
+
+	ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
+				 GL861_REQ_I2C_READ, GL861_READ,
+				 addr << (8 + 1), 0x0100, buf, rlen, 2000);
+	if (ret > 0 && rbuf)
+		memcpy(rbuf, buf, rlen);
+	kfree(buf);
+
+	return ret;
+}
+
+static int
+gl861_i2c_relay_write(struct dvb_usb_device *d, struct i2c_msg *msg)
+{
+	u8 *buf;
+	int ret;
+
+	if (msg->flags & I2C_M_RD)
+		return -EINVAL;
+	if (msg->len < 2)
+		return -EINVAL;
+
+	buf = kmalloc(msg->len - 1, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	memcpy(buf, msg->buf + 1, msg->len - 1);
+
+	usleep_range(1000, 2000); /* avoid I2C errors */
+
+	ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
+				 GL861_REQ_I2C_RAW, GL861_WRITE,
+				 msg->addr << (8 + 1), msg->buf[0],
+				 buf, msg->len - 1, 2000);
+	kfree(buf);
+	return ret;
+}
+
 /* I2C */
 static int gl861_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
 			  int num)
@@ -63,16 +139,35 @@ static int gl861_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
 		return -EAGAIN;
 
 	for (i = 0; i < num; i++) {
-		/* write/read request */
-		if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
-			if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf,
-				msg[i].len, msg[i+1].buf, msg[i+1].len) < 0)
-				break;
+		int ret;
+
+		/*
+		 * relay'ed reads (from tuner) are implemented by two i2c_msg's:
+		 *   1) write the tuner reg addr & value to demod reg:0xFE
+		 *   2) read from demod for the result
+		 * Special USB requests are used for the messages.
+		 * This means that those two messages cannot be combined to
+		 * one URB like the other i2c reads, and if msg[i] is an
+		 * uncombined read message, then it is a relayed read.
+		 */
+		if (msg[i].flags & I2C_M_RD)
+			ret = gl861_i2c_rawread(d, msg[i].addr,
+						msg[i].buf, msg[i].len);
+
+		/* write to reg:0xFE means a relay'ed write (to tuner) */
+		else if (msg[i].buf[0] == 0xfe)
+			ret = gl861_i2c_relay_write(d, &msg[i]);
+
+		else if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
+			ret = gl861_i2c_msg(d, msg[i].addr, msg[i].buf,
+				msg[i].len, msg[i+1].buf, msg[i+1].len);
 			i++;
 		} else
-			if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf,
-					  msg[i].len, NULL, 0) < 0)
-				break;
+			ret = gl861_i2c_msg(d, msg[i].addr, msg[i].buf,
+					    msg[i].len, NULL, 0);
+
+		if (ret < 0)
+			break;
 	}
 
 	mutex_unlock(&d->i2c_mutex);
@@ -89,6 +184,332 @@ static struct i2c_algorithm gl861_i2c_algo = {
 	.functionality = gl861_i2c_func,
 };
 
+
+/*
+ * Friio specific stuff
+ */
+
+struct friio_priv {
+	struct i2c_adapter *demod_sub_i2c;
+	struct i2c_client  *i2c_client_demod;
+	struct i2c_client  *i2c_client_tuner;
+};
+
+struct friio_config {
+	struct i2c_board_info demod_info;
+	struct tc90522_config demod_cfg;
+
+	struct i2c_board_info tuner_info;
+	struct dvb_pll_config tuner_cfg;
+};
+
+static const struct friio_config friio_config = {
+	.demod_info = { I2C_BOARD_INFO(TC90522_I2C_DEV_TER, 0x18), },
+	.tuner_info = { I2C_BOARD_INFO("tua6034_friio", 0x60), },
+};
+
+/*
+ * Utility functions for Friio
+ */
+
+/* GPIO control in Friio */
+
+#define FRIIO_CTL_LNB (1 << 0)
+#define FRIIO_CTL_STROBE (1 << 1)
+#define FRIIO_CTL_CLK (1 << 2)
+#define FRIIO_CTL_LED (1 << 3)
+
+#define FRIIO_LED_RUNNING 0x6400ff64
+#define FRIIO_LED_STOPPED 0x96ff00ff
+
+/* control PIC16F676 attached to Friio */
+static int friio_ext_ctl(struct dvb_usb_device *d,
+			    u32 sat_color, int power_on)
+{
+	int i, ret;
+	struct i2c_msg msg;
+	u8 *buf;
+	u32 mask;
+	u8 power = (power_on) ? FRIIO_CTL_LNB : 0;
+
+	buf = kmalloc(2, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	msg.addr = 0x00;
+	msg.flags = 0;
+	msg.len = 2;
+	msg.buf = buf;
+	buf[0] = 0x00;
+
+	/* send 2bit header (&B10) */
+	buf[1] = power | FRIIO_CTL_LED | FRIIO_CTL_STROBE;
+	ret = i2c_transfer(&d->i2c_adap, &msg, 1);
+	buf[1] |= FRIIO_CTL_CLK;
+	ret += i2c_transfer(&d->i2c_adap, &msg, 1);
+
+	buf[1] = power | FRIIO_CTL_STROBE;
+	ret += i2c_transfer(&d->i2c_adap, &msg, 1);
+	buf[1] |= FRIIO_CTL_CLK;
+	ret += i2c_transfer(&d->i2c_adap, &msg, 1);
+
+	/* send 32bit(satur, R, G, B) data in serial */
+	mask = 1 << 31;
+	for (i = 0; i < 32; i++) {
+		buf[1] = power | FRIIO_CTL_STROBE;
+		if (sat_color & mask)
+			buf[1] |= FRIIO_CTL_LED;
+		ret += i2c_transfer(&d->i2c_adap, &msg, 1);
+		buf[1] |= FRIIO_CTL_CLK;
+		ret += i2c_transfer(&d->i2c_adap, &msg, 1);
+		mask >>= 1;
+	}
+
+	/* set the strobe off */
+	buf[1] = power;
+	ret += i2c_transfer(&d->i2c_adap, &msg, 1);
+	buf[1] |= FRIIO_CTL_CLK;
+	ret += i2c_transfer(&d->i2c_adap, &msg, 1);
+
+	kfree(buf);
+	return (ret == 70) ? 0 : -EREMOTEIO;
+}
+
+/* init/config of Friio demod chip(?) */
+static int friio_reset(struct dvb_usb_device *d)
+{
+	int i, ret;
+	u8 wbuf[2], rbuf[2];
+
+	static const u8 friio_init_cmds[][2] = {
+		{0x33, 0x08}, {0x37, 0x40}, {0x3a, 0x1f}, {0x3b, 0xff},
+		{0x3c, 0x1f}, {0x3d, 0xff}, {0x38, 0x00}, {0x35, 0x00},
+		{0x39, 0x00}, {0x36, 0x00},
+	};
+
+	ret = usb_set_interface(d->udev, 0, 0);
+	if (ret < 0)
+		return ret;
+
+	wbuf[0] = 0x11;
+	wbuf[1] = 0x02;
+	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
+	if (ret < 0)
+		return ret;
+	usleep_range(2000, 3000);
+
+	wbuf[0] = 0x11;
+	wbuf[1] = 0x00;
+	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
+	if (ret < 0)
+		return ret;
+	usleep_range(1000, 2000);
+
+	/*
+	 * Check if the dev is really a Friio White, since it might be
+	 * another device, Friio Black, with the same VID/PID.
+	 */
+
+	wbuf[0] = 0x03;
+	wbuf[1] = 0x80;
+	ret = gl861_i2c_rawwrite(d, 0x09, wbuf, 2);
+	if (ret < 0)
+		return ret;
+
+	usleep_range(2000, 3000);
+	ret = gl861_i2c_rawread(d, 0x09, rbuf, 2);
+	if (ret < 0)
+		return ret;
+	if (rbuf[0] != 0xff || rbuf[1] != 0xff)
+		return -ENODEV;
+
+
+	ret = gl861_i2c_rawwrite(d, 0x48, wbuf, 2);
+	if (ret < 0)
+		return ret;
+	usleep_range(2000, 3000);
+
+	ret = gl861_i2c_rawread(d, 0x48, rbuf, 2);
+	if (ret < 0)
+		return ret;
+	if (rbuf[0] != 0xff || rbuf[1] != 0xff)
+		return -ENODEV;
+
+	usleep_range(1000, 2000);
+
+	wbuf[0] = 0x30;
+	wbuf[1] = 0x04;
+	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
+	if (ret < 0)
+		return ret;
+	usleep_range(2000, 3000);
+
+	wbuf[0] = 0x00;
+	wbuf[1] = 0x01;
+	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
+	if (ret < 0)
+		return ret;
+
+	wbuf[0] = 0x06;
+	wbuf[1] = 0x0f;
+	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
+	if (ret < 0)
+		return ret;
+
+	usleep_range(10000, 11000);
+	for (i = 0; i < ARRAY_SIZE(friio_init_cmds); i++) {
+		ret = gl861_i2c_msg(d, 0x00, (u8 *)friio_init_cmds[i], 2,
+				      NULL, 0);
+		if (ret < 0)
+			return ret;
+		usleep_range(1000, 2000);
+	}
+	return 0;
+}
+
+/*
+ * DVB callbacks for Friio
+ */
+
+static int friio_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	return onoff ? friio_reset(d) : 0;
+}
+
+static int friio_frontend_attach(struct dvb_usb_adapter *adap)
+{
+	const struct i2c_board_info *info;
+	struct tc90522_config cfg;
+	struct i2c_client *cl;
+	struct friio_priv *priv;
+
+	info = &friio_config.demod_info;
+	cl = dvb_module_probe("tc90522", info->type,
+			      &adap_to_d(adap)->i2c_adap, info->addr, &cfg);
+	if (!cl)
+		return -ENODEV;
+	adap->fe[0] = cfg.fe;
+
+	priv = adap_to_priv(adap);
+	priv->i2c_client_demod = cl;
+	priv->demod_sub_i2c = cfg.tuner_i2c;
+	return 0;
+}
+
+static int friio_frontend_detach(struct dvb_usb_adapter *adap)
+{
+	struct friio_priv *priv;
+
+	priv = adap_to_priv(adap);
+	dvb_module_release(priv->i2c_client_demod);
+	return 0;
+}
+
+static int friio_tuner_attach(struct dvb_usb_adapter *adap)
+{
+	const struct i2c_board_info *info;
+	struct dvb_pll_config cfg;
+	struct i2c_client *cl;
+	struct friio_priv *priv;
+
+	priv = adap_to_priv(adap);
+	info = &friio_config.tuner_info;
+	cfg = friio_config.tuner_cfg;
+	cfg.fe = adap->fe[0];
+
+	cl = dvb_module_probe("dvb_pll", info->type,
+			      priv->demod_sub_i2c, info->addr, &cfg);
+	if (!cl)
+		return -ENODEV;
+	priv->i2c_client_tuner = cl;
+	return 0;
+}
+
+static int friio_tuner_detach(struct dvb_usb_adapter *adap)
+{
+	struct friio_priv *priv;
+
+	priv = adap_to_priv(adap);
+#ifndef CONFIG_MEDIA_ATTACH
+	/* Note:
+	 * When CONFIG_MEDIA_ATTACH is defined,
+	 * the tuner module is already "put" by the following call trace:
+	 *
+	 * symbol_put_addr(fe->ops.tuner_ops.release)
+	 * dvb_frontend_invoke_release(fe, fe->ops.tuner_ops.release)
+	 * dvb_frontend_detach(fe)
+	 * dvb_usbv2_adapter_frontend_exit(adap)
+	 * dvb_usbv2_adapter_exit(d)
+	 * dvb_usbv2_exit(d)
+	 * dvb_usbv2_disconnect(intf)
+	 *
+	 * Since the tuner driver of Friio (dvb-pll) has .release defined,
+	 * dvb_module_release() should be skipped if CONFIG_MEDIA_ATTACH,
+	 * to avoid double-putting the module.
+	 * Even without dvb_module_release(),
+	 * the tuner i2c device is automatically unregistered
+	 * when its i2c adapter is unregistered with the demod i2c device.
+	 *
+	 * The same "double-putting" can happen to the demod module as well,
+	 * but tc90522 does not define any _invoke_release()'ed functions,
+	 * thus Friio is not affected.
+	 */
+	dvb_module_release(priv->i2c_client_tuner);
+#endif
+	return 0;
+}
+
+static int friio_init(struct dvb_usb_device *d)
+{
+	int i;
+	int ret;
+	struct friio_priv *priv;
+
+	static const u8 demod_init[][2] = {
+		{0x01, 0x40}, {0x04, 0x38}, {0x05, 0x40}, {0x07, 0x40},
+		{0x0f, 0x4f}, {0x11, 0x21}, {0x12, 0x0b}, {0x13, 0x2f},
+		{0x14, 0x31}, {0x16, 0x02}, {0x21, 0xc4}, {0x22, 0x20},
+		{0x2c, 0x79}, {0x2d, 0x34}, {0x2f, 0x00}, {0x30, 0x28},
+		{0x31, 0x31}, {0x32, 0xdf}, {0x38, 0x01}, {0x39, 0x78},
+		{0x3b, 0x33}, {0x3c, 0x33}, {0x48, 0x90}, {0x51, 0x68},
+		{0x5e, 0x38}, {0x71, 0x00}, {0x72, 0x08}, {0x77, 0x00},
+		{0xc0, 0x21}, {0xc1, 0x10}, {0xe4, 0x1a}, {0xea, 0x1f},
+		{0x77, 0x00}, {0x71, 0x00}, {0x71, 0x00}, {0x76, 0x0c},
+	};
+
+	/* power on LNA? */
+	ret = friio_ext_ctl(d, FRIIO_LED_STOPPED, true);
+	if (ret < 0)
+		return ret;
+	msleep(20);
+
+	/* init/config demod */
+	priv = d_to_priv(d);
+	for (i = 0; i < ARRAY_SIZE(demod_init); i++) {
+		int ret;
+
+		ret = i2c_master_send(priv->i2c_client_demod, demod_init[i], 2);
+		if (ret < 0)
+			return ret;
+	}
+	msleep(100);
+	return 0;
+}
+
+static void friio_exit(struct dvb_usb_device *d)
+{
+	friio_ext_ctl(d, FRIIO_LED_STOPPED, false);
+}
+
+static int friio_streaming_ctrl(struct dvb_frontend *fe, int onoff)
+{
+	u32 led_color;
+
+	led_color = onoff ? FRIIO_LED_RUNNING : FRIIO_LED_STOPPED;
+	return friio_ext_ctl(fe_to_d(fe), led_color, true);
+}
+
+
 /* Callbacks for DVB USB */
 static struct zl10353_config gl861_zl10353_config = {
 	.demod_address = 0x0f,
@@ -148,11 +569,39 @@ static struct dvb_usb_device_properties gl861_props = {
 	}
 };
 
+static struct dvb_usb_device_properties friio_props = {
+	.driver_name = KBUILD_MODNAME,
+	.owner = THIS_MODULE,
+	.adapter_nr = adapter_nr,
+
+	.size_of_priv = sizeof(struct friio_priv),
+
+	.i2c_algo = &gl861_i2c_algo,
+	.power_ctrl = friio_power_ctrl,
+	.frontend_attach = friio_frontend_attach,
+	.frontend_detach = friio_frontend_detach,
+	.tuner_attach = friio_tuner_attach,
+	.tuner_detach = friio_tuner_detach,
+	.init = friio_init,
+	.exit = friio_exit,
+	.streaming_ctrl = friio_streaming_ctrl,
+
+	.num_adapters = 1,
+	.adapter = {
+		{
+			.stream = DVB_USB_STREAM_BULK(0x01, 8, 16384),
+		}
+	}
+};
+
+
 static const struct usb_device_id gl861_id_table[] = {
 	{ DVB_USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580_55801,
 		&gl861_props, "MSI Mega Sky 55801 DVB-T USB2.0", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_ALINK, USB_VID_ALINK_DTU,
 		&gl861_props, "A-LINK DTU DVB-T USB2.0", NULL) },
+	{ DVB_USB_DEVICE(USB_VID_774, USB_PID_FRIIO_WHITE,
+		&friio_props, "774 Friio White ISDB-T USB2.0", NULL) },
 	{ }
 };
 MODULE_DEVICE_TABLE(usb, gl861_id_table);
diff --git a/drivers/media/usb/dvb-usb-v2/gl861.h b/drivers/media/usb/dvb-usb-v2/gl861.h
index b651b857e03..02c00e10748 100644
--- a/drivers/media/usb/dvb-usb-v2/gl861.h
+++ b/drivers/media/usb/dvb-usb-v2/gl861.h
@@ -9,5 +9,6 @@
 
 #define GL861_REQ_I2C_WRITE	0x01
 #define GL861_REQ_I2C_READ	0x02
+#define GL861_REQ_I2C_RAW	0x03
 
 #endif
diff --git a/drivers/media/usb/dvb-usb/Kconfig b/drivers/media/usb/dvb-usb/Kconfig
index 2651ae27734..1990d1c975e 100644
--- a/drivers/media/usb/dvb-usb/Kconfig
+++ b/drivers/media/usb/dvb-usb/Kconfig
@@ -312,12 +312,6 @@ config DVB_USB_DTV5100
 	help
 	  Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver.
 
-config DVB_USB_FRIIO
-	tristate "Friio ISDB-T USB2.0 Receiver support"
-	depends on DVB_USB
-	help
-	  Say Y here to support the Japanese DTV receiver Friio.
-
 config DVB_USB_AZ6027
 	tristate "Azurewave DVB-S/S2 USB2.0 AZ6027 support"
 	depends on DVB_USB
diff --git a/drivers/media/usb/dvb-usb/Makefile b/drivers/media/usb/dvb-usb/Makefile
index 9ad2618408e..407d90ca8be 100644
--- a/drivers/media/usb/dvb-usb/Makefile
+++ b/drivers/media/usb/dvb-usb/Makefile
@@ -71,9 +71,6 @@ obj-$(CONFIG_DVB_USB_DTV5100) += dvb-usb-dtv5100.o
 dvb-usb-cinergyT2-objs := cinergyT2-core.o cinergyT2-fe.o
 obj-$(CONFIG_DVB_USB_CINERGY_T2) += dvb-usb-cinergyT2.o
 
-dvb-usb-friio-objs := friio.o friio-fe.o
-obj-$(CONFIG_DVB_USB_FRIIO) += dvb-usb-friio.o
-
 dvb-usb-az6027-objs := az6027.o
 obj-$(CONFIG_DVB_USB_AZ6027) += dvb-usb-az6027.o
 
diff --git a/drivers/media/usb/dvb-usb/friio-fe.c b/drivers/media/usb/dvb-usb/friio-fe.c
deleted file mode 100644
index b2830c15754..00000000000
--- a/drivers/media/usb/dvb-usb/friio-fe.c
+++ /dev/null
@@ -1,441 +0,0 @@
-/* DVB USB compliant Linux driver for the Friio USB2.0 ISDB-T receiver.
- *
- * Copyright (C) 2009 Akihiro Tsukada <tskd2@yahoo.co.jp>
- *
- * This module is based off the the gl861 and vp702x modules.
- *
- * 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, version 2.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/kernel.h>
-
-#include "friio.h"
-
-struct jdvbt90502_state {
-	struct i2c_adapter *i2c;
-	struct dvb_frontend frontend;
-	struct jdvbt90502_config config;
-};
-
-/* NOTE: TC90502 has 16bit register-address? */
-/* register 0x0100 is used for reading PLL status, so reg is u16 here */
-static int jdvbt90502_reg_read(struct jdvbt90502_state *state,
-			       const u16 reg, u8 *buf, const size_t count)
-{
-	int ret;
-	u8 wbuf[3];
-	struct i2c_msg msg[2];
-
-	wbuf[0] = reg & 0xFF;
-	wbuf[1] = 0;
-	wbuf[2] = reg >> 8;
-
-	msg[0].addr = state->config.demod_address;
-	msg[0].flags = 0;
-	msg[0].buf = wbuf;
-	msg[0].len = sizeof(wbuf);
-
-	msg[1].addr = msg[0].addr;
-	msg[1].flags = I2C_M_RD;
-	msg[1].buf = buf;
-	msg[1].len = count;
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-	if (ret != 2) {
-		deb_fe(" reg read failed.\n");
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-/* currently 16bit register-address is not used, so reg is u8 here */
-static int jdvbt90502_single_reg_write(struct jdvbt90502_state *state,
-				       const u8 reg, const u8 val)
-{
-	struct i2c_msg msg;
-	u8 wbuf[2];
-
-	wbuf[0] = reg;
-	wbuf[1] = val;
-
-	msg.addr = state->config.demod_address;
-	msg.flags = 0;
-	msg.buf = wbuf;
-	msg.len = sizeof(wbuf);
-
-	if (i2c_transfer(state->i2c, &msg, 1) != 1) {
-		deb_fe(" reg write failed.");
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-static int _jdvbt90502_write(struct dvb_frontend *fe, const u8 buf[], int len)
-{
-	struct jdvbt90502_state *state = fe->demodulator_priv;
-	int err, i;
-	for (i = 0; i < len - 1; i++) {
-		err = jdvbt90502_single_reg_write(state,
-						  buf[0] + i, buf[i + 1]);
-		if (err)
-			return err;
-	}
-
-	return 0;
-}
-
-/* read pll status byte via the demodulator's I2C register */
-/* note: Win box reads it by 8B block at the I2C addr 0x30 from reg:0x80 */
-static int jdvbt90502_pll_read(struct jdvbt90502_state *state, u8 *result)
-{
-	int ret;
-
-	/* +1 for reading */
-	u8 pll_addr_byte = (state->config.pll_address << 1) + 1;
-
-	*result = 0;
-
-	ret = jdvbt90502_single_reg_write(state, JDVBT90502_2ND_I2C_REG,
-					  pll_addr_byte);
-	if (ret)
-		goto error;
-
-	ret = jdvbt90502_reg_read(state, 0x0100, result, 1);
-	if (ret)
-		goto error;
-
-	deb_fe("PLL read val:%02x\n", *result);
-	return 0;
-
-error:
-	deb_fe("%s:ret == %d\n", __func__, ret);
-	return -EREMOTEIO;
-}
-
-
-/* set pll frequency via the demodulator's I2C register */
-static int jdvbt90502_pll_set_freq(struct jdvbt90502_state *state, u32 freq)
-{
-	int ret;
-	int retry;
-	u8 res1;
-	u8 res2[9];
-
-	u8 pll_freq_cmd[PLL_CMD_LEN];
-	u8 pll_agc_cmd[PLL_CMD_LEN];
-	struct i2c_msg msg[2];
-	u32 f;
-
-	deb_fe("%s: freq=%d, step=%d\n", __func__, freq,
-	       state->frontend.ops.info.frequency_stepsize);
-	/* freq -> oscilator frequency conversion. */
-	/* freq: 473,000,000 + n*6,000,000 [+ 142857 (center freq. shift)] */
-	f = freq / state->frontend.ops.info.frequency_stepsize;
-	/* add 399[1/7 MHZ] = 57MHz for the IF  */
-	f += 399;
-	/* add center frequency shift if necessary */
-	if (f % 7 == 0)
-		f++;
-	pll_freq_cmd[DEMOD_REDIRECT_REG] = JDVBT90502_2ND_I2C_REG; /* 0xFE */
-	pll_freq_cmd[ADDRESS_BYTE] = state->config.pll_address << 1;
-	pll_freq_cmd[DIVIDER_BYTE1] = (f >> 8) & 0x7F;
-	pll_freq_cmd[DIVIDER_BYTE2] = f & 0xFF;
-	pll_freq_cmd[CONTROL_BYTE] = 0xB2; /* ref.divider:28, 4MHz/28=1/7MHz */
-	pll_freq_cmd[BANDSWITCH_BYTE] = 0x08;	/* UHF band */
-
-	msg[0].addr = state->config.demod_address;
-	msg[0].flags = 0;
-	msg[0].buf = pll_freq_cmd;
-	msg[0].len = sizeof(pll_freq_cmd);
-
-	ret = i2c_transfer(state->i2c, &msg[0], 1);
-	if (ret != 1)
-		goto error;
-
-	udelay(50);
-
-	pll_agc_cmd[DEMOD_REDIRECT_REG] = pll_freq_cmd[DEMOD_REDIRECT_REG];
-	pll_agc_cmd[ADDRESS_BYTE] = pll_freq_cmd[ADDRESS_BYTE];
-	pll_agc_cmd[DIVIDER_BYTE1] = pll_freq_cmd[DIVIDER_BYTE1];
-	pll_agc_cmd[DIVIDER_BYTE2] = pll_freq_cmd[DIVIDER_BYTE2];
-	pll_agc_cmd[CONTROL_BYTE] = 0x9A; /*  AGC_CTRL instead of BANDSWITCH */
-	pll_agc_cmd[AGC_CTRL_BYTE] = 0x50;
-	/* AGC Time Constant 2s, AGC take-over point:103dBuV(lowest) */
-
-	msg[1].addr = msg[0].addr;
-	msg[1].flags = 0;
-	msg[1].buf = pll_agc_cmd;
-	msg[1].len = sizeof(pll_agc_cmd);
-
-	ret = i2c_transfer(state->i2c, &msg[1], 1);
-	if (ret != 1)
-		goto error;
-
-	/* I don't know what these cmds are for,  */
-	/* but the USB log on a windows box contains them */
-	ret = jdvbt90502_single_reg_write(state, 0x01, 0x40);
-	ret |= jdvbt90502_single_reg_write(state, 0x01, 0x00);
-	if (ret)
-		goto error;
-	udelay(100);
-
-	/* wait for the demod to be ready? */
-#define RETRY_COUNT 5
-	for (retry = 0; retry < RETRY_COUNT; retry++) {
-		ret = jdvbt90502_reg_read(state, 0x0096, &res1, 1);
-		if (ret)
-			goto error;
-		/* if (res1 != 0x00) goto error; */
-		ret = jdvbt90502_reg_read(state, 0x00B0, res2, sizeof(res2));
-		if (ret)
-			goto error;
-		if (res2[0] >= 0xA7)
-			break;
-		msleep(100);
-	}
-	if (retry >= RETRY_COUNT) {
-		deb_fe("%s: FE does not get ready after freq setting.\n",
-		       __func__);
-		return -EREMOTEIO;
-	}
-
-	return 0;
-error:
-	deb_fe("%s:ret == %d\n", __func__, ret);
-	return -EREMOTEIO;
-}
-
-static int jdvbt90502_read_status(struct dvb_frontend *fe,
-				  enum fe_status *state)
-{
-	u8 result;
-	int ret;
-
-	*state = FE_HAS_SIGNAL;
-
-	ret = jdvbt90502_pll_read(fe->demodulator_priv, &result);
-	if (ret) {
-		deb_fe("%s:ret == %d\n", __func__, ret);
-		return -EREMOTEIO;
-	}
-
-	*state = FE_HAS_SIGNAL
-		| FE_HAS_CARRIER
-		| FE_HAS_VITERBI
-		| FE_HAS_SYNC;
-
-	if (result & PLL_STATUS_LOCKED)
-		*state |= FE_HAS_LOCK;
-
-	return 0;
-}
-
-static int jdvbt90502_read_signal_strength(struct dvb_frontend *fe,
-					   u16 *strength)
-{
-	int ret;
-	u8 rbuf[37];
-
-	*strength = 0;
-
-	/* status register (incl. signal strength) : 0x89  */
-	/* TODO: read just the necessary registers [0x8B..0x8D]? */
-	ret = jdvbt90502_reg_read(fe->demodulator_priv, 0x0089,
-				  rbuf, sizeof(rbuf));
-
-	if (ret) {
-		deb_fe("%s:ret == %d\n", __func__, ret);
-		return -EREMOTEIO;
-	}
-
-	/* signal_strength: rbuf[2-4] (24bit BE), use lower 16bit for now. */
-	*strength = (rbuf[3] << 8) + rbuf[4];
-	if (rbuf[2])
-		*strength = 0xffff;
-
-	return 0;
-}
-
-static int jdvbt90502_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-
-	/**
-	 * NOTE: ignore all the parameters except frequency.
-	 *       others should be fixed to the proper value for ISDB-T,
-	 *       but don't check here.
-	 */
-
-	struct jdvbt90502_state *state = fe->demodulator_priv;
-	int ret;
-
-	deb_fe("%s: Freq:%d\n", __func__, p->frequency);
-
-	/* This driver only works on auto mode */
-	p->inversion = INVERSION_AUTO;
-	p->bandwidth_hz = 6000000;
-	p->code_rate_HP = FEC_AUTO;
-	p->code_rate_LP = FEC_AUTO;
-	p->modulation = QAM_64;
-	p->transmission_mode = TRANSMISSION_MODE_AUTO;
-	p->guard_interval = GUARD_INTERVAL_AUTO;
-	p->hierarchy = HIERARCHY_AUTO;
-	p->delivery_system = SYS_ISDBT;
-
-	ret = jdvbt90502_pll_set_freq(state, p->frequency);
-	if (ret) {
-		deb_fe("%s:ret == %d\n", __func__, ret);
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-
-/*
- * (reg, val) commad list to initialize this module.
- *  captured on a Windows box.
- */
-static u8 init_code[][2] = {
-	{0x01, 0x40},
-	{0x04, 0x38},
-	{0x05, 0x40},
-	{0x07, 0x40},
-	{0x0F, 0x4F},
-	{0x11, 0x21},
-	{0x12, 0x0B},
-	{0x13, 0x2F},
-	{0x14, 0x31},
-	{0x16, 0x02},
-	{0x21, 0xC4},
-	{0x22, 0x20},
-	{0x2C, 0x79},
-	{0x2D, 0x34},
-	{0x2F, 0x00},
-	{0x30, 0x28},
-	{0x31, 0x31},
-	{0x32, 0xDF},
-	{0x38, 0x01},
-	{0x39, 0x78},
-	{0x3B, 0x33},
-	{0x3C, 0x33},
-	{0x48, 0x90},
-	{0x51, 0x68},
-	{0x5E, 0x38},
-	{0x71, 0x00},
-	{0x72, 0x08},
-	{0x77, 0x00},
-	{0xC0, 0x21},
-	{0xC1, 0x10},
-	{0xE4, 0x1A},
-	{0xEA, 0x1F},
-	{0x77, 0x00},
-	{0x71, 0x00},
-	{0x71, 0x00},
-	{0x76, 0x0C},
-};
-
-static int jdvbt90502_init(struct dvb_frontend *fe)
-{
-	int i = -1;
-	int ret;
-	struct i2c_msg msg;
-
-	struct jdvbt90502_state *state = fe->demodulator_priv;
-
-	deb_fe("%s called.\n", __func__);
-
-	msg.addr = state->config.demod_address;
-	msg.flags = 0;
-	msg.len = 2;
-	for (i = 0; i < ARRAY_SIZE(init_code); i++) {
-		msg.buf = init_code[i];
-		ret = i2c_transfer(state->i2c, &msg, 1);
-		if (ret != 1)
-			goto error;
-	}
-	fe->dtv_property_cache.delivery_system = SYS_ISDBT;
-	msleep(100);
-
-	return 0;
-
-error:
-	deb_fe("%s: init_code[%d] failed. ret==%d\n", __func__, i, ret);
-	return -EREMOTEIO;
-}
-
-
-static void jdvbt90502_release(struct dvb_frontend *fe)
-{
-	struct jdvbt90502_state *state = fe->demodulator_priv;
-	kfree(state);
-}
-
-
-static const struct dvb_frontend_ops jdvbt90502_ops;
-
-struct dvb_frontend *jdvbt90502_attach(struct dvb_usb_device *d)
-{
-	struct jdvbt90502_state *state = NULL;
-
-	deb_info("%s called.\n", __func__);
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct jdvbt90502_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	/* setup the state */
-	state->i2c = &d->i2c_adap;
-	state->config = friio_fe_config;
-
-	/* create dvb_frontend */
-	state->frontend.ops = jdvbt90502_ops;
-	state->frontend.demodulator_priv = state;
-
-	if (jdvbt90502_init(&state->frontend) < 0)
-		goto error;
-
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-
-static const struct dvb_frontend_ops jdvbt90502_ops = {
-	.delsys = { SYS_ISDBT },
-	.info = {
-		.name			= "Comtech JDVBT90502 ISDB-T",
-		.frequency_min		= 473000000, /* UHF 13ch, center */
-		.frequency_max		= 767142857, /* UHF 62ch, center */
-		.frequency_stepsize	= JDVBT90502_PLL_CLK / JDVBT90502_PLL_DIVIDER,
-		.frequency_tolerance	= 0,
-
-		/* NOTE: this driver ignores all parameters but frequency. */
-		.caps = FE_CAN_INVERSION_AUTO |
-			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
-			FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
-			FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
-			FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-			FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_HIERARCHY_AUTO,
-	},
-
-	.release = jdvbt90502_release,
-
-	.init = jdvbt90502_init,
-	.write = _jdvbt90502_write,
-
-	.set_frontend = jdvbt90502_set_frontend,
-
-	.read_status = jdvbt90502_read_status,
-	.read_signal_strength = jdvbt90502_read_signal_strength,
-};
diff --git a/drivers/media/usb/dvb-usb/friio.c b/drivers/media/usb/dvb-usb/friio.c
deleted file mode 100644
index 16875945e66..00000000000
--- a/drivers/media/usb/dvb-usb/friio.c
+++ /dev/null
@@ -1,522 +0,0 @@
-/* DVB USB compliant Linux driver for the Friio USB2.0 ISDB-T receiver.
- *
- * Copyright (C) 2009 Akihiro Tsukada <tskd2@yahoo.co.jp>
- *
- * This module is based off the the gl861 and vp702x modules.
- *
- * 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, version 2.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#include "friio.h"
-
-/* debug */
-int dvb_usb_friio_debug;
-module_param_named(debug, dvb_usb_friio_debug, int, 0644);
-MODULE_PARM_DESC(debug,
-		 "set debugging level (1=info,2=xfer,4=rc,8=fe (or-able))."
-		 DVB_USB_DEBUG_STATUS);
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-/*
- * Indirect I2C access to the PLL via FE.
- * whole I2C protocol data to the PLL is sent via the FE's I2C register.
- * This is done by a control msg to the FE with the I2C data accompanied, and
- * a specific USB request number is assigned for that purpose.
- *
- * this func sends wbuf[1..] to the I2C register wbuf[0] at addr (= at FE).
- * TODO: refoctored, smarter i2c functions.
- */
-static int gl861_i2c_ctrlmsg_data(struct dvb_usb_device *d, u8 addr,
-				  u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
-{
-	u16 index = wbuf[0];	/* must be JDVBT90502_2ND_I2C_REG(=0xFE) */
-	u16 value = addr << (8 + 1);
-	int wo = (rbuf == NULL || rlen == 0);	/* write only */
-	u8 req, type;
-
-	deb_xfer("write to PLL:0x%02x via FE reg:0x%02x, len:%d\n",
-		 wbuf[1], wbuf[0], wlen - 1);
-
-	if (wo && wlen >= 2) {
-		req = GL861_REQ_I2C_DATA_CTRL_WRITE;
-		type = GL861_WRITE;
-		udelay(20);
-		return usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
-				       req, type, value, index,
-				       &wbuf[1], wlen - 1, 2000);
-	}
-
-	deb_xfer("not supported ctrl-msg, aborting.");
-	return -EINVAL;
-}
-
-/* normal I2C access (without extra data arguments).
- * write to the register wbuf[0] at I2C address addr with the value wbuf[1],
- *  or read from the register wbuf[0].
- * register address can be 16bit (wbuf[2]<<8 | wbuf[0]) if wlen==3
- */
-static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
-			 u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
-{
-	u16 index;
-	u16 value = addr << (8 + 1);
-	int wo = (rbuf == NULL || rlen == 0);	/* write-only */
-	u8 req, type;
-	unsigned int pipe;
-
-	/* special case for the indirect I2C access to the PLL via FE, */
-	if (addr == friio_fe_config.demod_address &&
-	    wbuf[0] == JDVBT90502_2ND_I2C_REG)
-		return gl861_i2c_ctrlmsg_data(d, addr, wbuf, wlen, rbuf, rlen);
-
-	if (wo) {
-		req = GL861_REQ_I2C_WRITE;
-		type = GL861_WRITE;
-		pipe = usb_sndctrlpipe(d->udev, 0);
-	} else {		/* rw */
-		req = GL861_REQ_I2C_READ;
-		type = GL861_READ;
-		pipe = usb_rcvctrlpipe(d->udev, 0);
-	}
-
-	switch (wlen) {
-	case 1:
-		index = wbuf[0];
-		break;
-	case 2:
-		index = wbuf[0];
-		value = value + wbuf[1];
-		break;
-	case 3:
-		/* special case for 16bit register-address */
-		index = (wbuf[2] << 8) | wbuf[0];
-		value = value + wbuf[1];
-		break;
-	default:
-		deb_xfer("wlen = %x, aborting.", wlen);
-		return -EINVAL;
-	}
-	msleep(1);
-	return usb_control_msg(d->udev, pipe, req, type,
-			       value, index, rbuf, rlen, 2000);
-}
-
-/* I2C */
-static int gl861_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
-			  int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	int i;
-
-
-	if (num > 2)
-		return -EINVAL;
-
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	for (i = 0; i < num; i++) {
-		/* write/read request */
-		if (i + 1 < num && (msg[i + 1].flags & I2C_M_RD)) {
-			if (gl861_i2c_msg(d, msg[i].addr,
-					  msg[i].buf, msg[i].len,
-					  msg[i + 1].buf, msg[i + 1].len) < 0)
-				break;
-			i++;
-		} else
-			if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf,
-					  msg[i].len, NULL, 0) < 0)
-				break;
-	}
-
-	mutex_unlock(&d->i2c_mutex);
-	return i;
-}
-
-static u32 gl861_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static int friio_ext_ctl(struct dvb_usb_adapter *adap,
-			 u32 sat_color, int lnb_on)
-{
-	int i;
-	int ret;
-	struct i2c_msg msg;
-	u8 *buf;
-	u32 mask;
-	u8 lnb = (lnb_on) ? FRIIO_CTL_LNB : 0;
-
-	buf = kmalloc(2, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-
-	msg.addr = 0x00;
-	msg.flags = 0;
-	msg.len = 2;
-	msg.buf = buf;
-
-	buf[0] = 0x00;
-
-	/* send 2bit header (&B10) */
-	buf[1] = lnb | FRIIO_CTL_LED | FRIIO_CTL_STROBE;
-	ret = gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
-	buf[1] |= FRIIO_CTL_CLK;
-	ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
-
-	buf[1] = lnb | FRIIO_CTL_STROBE;
-	ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
-	buf[1] |= FRIIO_CTL_CLK;
-	ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
-
-	/* send 32bit(satur, R, G, B) data in serial */
-	mask = 1 << 31;
-	for (i = 0; i < 32; i++) {
-		buf[1] = lnb | FRIIO_CTL_STROBE;
-		if (sat_color & mask)
-			buf[1] |= FRIIO_CTL_LED;
-		ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
-		buf[1] |= FRIIO_CTL_CLK;
-		ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
-		mask >>= 1;
-	}
-
-	/* set the strobe off */
-	buf[1] = lnb;
-	ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
-	buf[1] |= FRIIO_CTL_CLK;
-	ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
-
-	kfree(buf);
-	return (ret == 70);
-}
-
-
-static int friio_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff);
-
-/* TODO: move these init cmds to the FE's init routine? */
-static u8 streaming_init_cmds[][2] = {
-	{0x33, 0x08},
-	{0x37, 0x40},
-	{0x3A, 0x1F},
-	{0x3B, 0xFF},
-	{0x3C, 0x1F},
-	{0x3D, 0xFF},
-	{0x38, 0x00},
-	{0x35, 0x00},
-	{0x39, 0x00},
-	{0x36, 0x00},
-};
-static int cmdlen = sizeof(streaming_init_cmds) / 2;
-
-/*
- * Command sequence in this init function is a replay
- *  of the captured USB commands from the Windows proprietary driver.
- */
-static int friio_initialize(struct dvb_usb_device *d)
-{
-	int ret;
-	int i;
-	int retry = 0;
-	u8 *rbuf, *wbuf;
-
-	deb_info("%s called.\n", __func__);
-
-	wbuf = kmalloc(3, GFP_KERNEL);
-	if (!wbuf)
-		return -ENOMEM;
-
-	rbuf = kmalloc(2, GFP_KERNEL);
-	if (!rbuf) {
-		kfree(wbuf);
-		return -ENOMEM;
-	}
-
-	/* use gl861_i2c_msg instead of gl861_i2c_xfer(), */
-	/* because the i2c device is not set up yet. */
-	wbuf[0] = 0x11;
-	wbuf[1] = 0x02;
-	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
-	if (ret < 0)
-		goto error;
-	msleep(2);
-
-	wbuf[0] = 0x11;
-	wbuf[1] = 0x00;
-	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
-	if (ret < 0)
-		goto error;
-	msleep(1);
-
-	/* following msgs should be in the FE's init code? */
-	/* cmd sequence to identify the device type? (friio black/white) */
-	wbuf[0] = 0x03;
-	wbuf[1] = 0x80;
-	/* can't use gl861_i2c_cmd, as the register-addr is 16bit(0x0100) */
-	ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
-			      GL861_REQ_I2C_DATA_CTRL_WRITE, GL861_WRITE,
-			      0x1200, 0x0100, wbuf, 2, 2000);
-	if (ret < 0)
-		goto error;
-
-	msleep(2);
-	wbuf[0] = 0x00;
-	wbuf[2] = 0x01;		/* reg.0x0100 */
-	wbuf[1] = 0x00;
-	ret = gl861_i2c_msg(d, 0x12 >> 1, wbuf, 3, rbuf, 2);
-	/* my Friio White returns 0xffff. */
-	if (ret < 0 || rbuf[0] != 0xff || rbuf[1] != 0xff)
-		goto error;
-
-	msleep(2);
-	wbuf[0] = 0x03;
-	wbuf[1] = 0x80;
-	ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
-			      GL861_REQ_I2C_DATA_CTRL_WRITE, GL861_WRITE,
-			      0x9000, 0x0100, wbuf, 2, 2000);
-	if (ret < 0)
-		goto error;
-
-	msleep(2);
-	wbuf[0] = 0x00;
-	wbuf[2] = 0x01;		/* reg.0x0100 */
-	wbuf[1] = 0x00;
-	ret = gl861_i2c_msg(d, 0x90 >> 1, wbuf, 3, rbuf, 2);
-	/* my Friio White returns 0xffff again. */
-	if (ret < 0 || rbuf[0] != 0xff || rbuf[1] != 0xff)
-		goto error;
-
-	msleep(1);
-
-restart:
-	/* ============ start DEMOD init cmds ================== */
-	/* read PLL status to clear the POR bit */
-	wbuf[0] = JDVBT90502_2ND_I2C_REG;
-	wbuf[1] = (FRIIO_PLL_ADDR << 1) + 1;	/* +1 for reading */
-	ret = gl861_i2c_msg(d, FRIIO_DEMOD_ADDR, wbuf, 2, NULL, 0);
-	if (ret < 0)
-		goto error;
-
-	msleep(5);
-	/* note: DEMODULATOR has 16bit register-address. */
-	wbuf[0] = 0x00;
-	wbuf[2] = 0x01;		/* reg addr: 0x0100 */
-	wbuf[1] = 0x00;		/* val: not used */
-	ret = gl861_i2c_msg(d, FRIIO_DEMOD_ADDR, wbuf, 3, rbuf, 1);
-	if (ret < 0)
-		goto error;
-/*
-	msleep(1);
-	wbuf[0] = 0x80;
-	wbuf[1] = 0x00;
-	ret = gl861_i2c_msg(d, FRIIO_DEMOD_ADDR, wbuf, 2, rbuf, 1);
-	if (ret < 0)
-		goto error;
- */
-	if (rbuf[0] & 0x80) {	/* still in PowerOnReset state? */
-		if (++retry > 3) {
-			deb_info("failed to get the correct FE demod status:0x%02x\n",
-				 rbuf[0]);
-			goto error;
-		}
-		msleep(100);
-		goto restart;
-	}
-
-	/* TODO: check return value in rbuf */
-	/* =========== end DEMOD init cmds ===================== */
-	msleep(1);
-
-	wbuf[0] = 0x30;
-	wbuf[1] = 0x04;
-	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
-	if (ret < 0)
-		goto error;
-
-	msleep(2);
-	/* following 2 cmds unnecessary? */
-	wbuf[0] = 0x00;
-	wbuf[1] = 0x01;
-	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
-	if (ret < 0)
-		goto error;
-
-	wbuf[0] = 0x06;
-	wbuf[1] = 0x0F;
-	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
-	if (ret < 0)
-		goto error;
-
-	/* some streaming ctl cmds (maybe) */
-	msleep(10);
-	for (i = 0; i < cmdlen; i++) {
-		ret = gl861_i2c_msg(d, 0x00, streaming_init_cmds[i], 2,
-				    NULL, 0);
-		if (ret < 0)
-			goto error;
-		msleep(1);
-	}
-	msleep(20);
-
-	/* change the LED color etc. */
-	ret = friio_streaming_ctrl(&d->adapter[0], 0);
-	if (ret < 0)
-		goto error;
-
-	return 0;
-
-error:
-	kfree(wbuf);
-	kfree(rbuf);
-	deb_info("%s:ret == %d\n", __func__, ret);
-	return -EIO;
-}
-
-/* Callbacks for DVB USB */
-
-static int friio_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	int ret;
-
-	deb_info("%s called.(%d)\n", __func__, onoff);
-
-	/* set the LED color and saturation (and LNB on) */
-	if (onoff)
-		ret = friio_ext_ctl(adap, 0x6400ff64, 1);
-	else
-		ret = friio_ext_ctl(adap, 0x96ff00ff, 1);
-
-	if (ret != 1) {
-		deb_info("%s failed to send cmdx. ret==%d\n", __func__, ret);
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-static int friio_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	if (friio_initialize(adap->dev) < 0)
-		return -EIO;
-
-	adap->fe_adap[0].fe = jdvbt90502_attach(adap->dev);
-	if (adap->fe_adap[0].fe == NULL)
-		return -EIO;
-
-	return 0;
-}
-
-/* DVB USB Driver stuff */
-static struct dvb_usb_device_properties friio_properties;
-
-static int friio_probe(struct usb_interface *intf,
-		       const struct usb_device_id *id)
-{
-	struct dvb_usb_device *d;
-	struct usb_host_interface *alt;
-	int ret;
-
-	if (intf->num_altsetting < GL861_ALTSETTING_COUNT)
-		return -ENODEV;
-
-	alt = usb_altnum_to_altsetting(intf, FRIIO_BULK_ALTSETTING);
-	if (alt == NULL) {
-		deb_rc("not alt found!\n");
-		return -ENODEV;
-	}
-	ret = usb_set_interface(interface_to_usbdev(intf),
-				alt->desc.bInterfaceNumber,
-				alt->desc.bAlternateSetting);
-	if (ret != 0) {
-		deb_rc("failed to set alt-setting!\n");
-		return ret;
-	}
-
-	ret = dvb_usb_device_init(intf, &friio_properties,
-				  THIS_MODULE, &d, adapter_nr);
-	if (ret == 0)
-		friio_streaming_ctrl(&d->adapter[0], 1);
-
-	return ret;
-}
-
-
-struct jdvbt90502_config friio_fe_config = {
-	.demod_address = FRIIO_DEMOD_ADDR,
-	.pll_address = FRIIO_PLL_ADDR,
-};
-
-static struct i2c_algorithm gl861_i2c_algo = {
-	.master_xfer   = gl861_i2c_xfer,
-	.functionality = gl861_i2c_func,
-};
-
-static struct usb_device_id friio_table[] = {
-	{ USB_DEVICE(USB_VID_774, USB_PID_FRIIO_WHITE) },
-	{ }		/* Terminating entry */
-};
-MODULE_DEVICE_TABLE(usb, friio_table);
-
-
-static struct dvb_usb_device_properties friio_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-	.usb_ctrl = DEVICE_SPECIFIC,
-
-	.size_of_priv = 0,
-
-	.num_adapters = 1,
-	.adapter = {
-		/* caps:0 =>  no pid filter, 188B TS packet */
-		/* GL861 has a HW pid filter, but no info available. */
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.caps  = 0,
-
-			.frontend_attach  = friio_frontend_attach,
-			.streaming_ctrl = friio_streaming_ctrl,
-
-			.stream = {
-				.type = USB_BULK,
-				/* count <= MAX_NO_URBS_FOR_DATA_STREAM(10) */
-				.count = 8,
-				.endpoint = 0x01,
-				.u = {
-					/* GL861 has 6KB buf inside */
-					.bulk = {
-						.buffersize = 16384,
-					}
-				}
-			},
-		}},
-		}
-	},
-	.i2c_algo = &gl861_i2c_algo,
-
-	.num_device_descs = 1,
-	.devices = {
-		{
-			.name = "774 Friio ISDB-T USB2.0",
-			.cold_ids = { NULL },
-			.warm_ids = { &friio_table[0], NULL },
-		},
-	}
-};
-
-static struct usb_driver friio_driver = {
-	.name		= "dvb_usb_friio",
-	.probe		= friio_probe,
-	.disconnect	= dvb_usb_device_exit,
-	.id_table	= friio_table,
-};
-
-module_usb_driver(friio_driver);
-
-MODULE_AUTHOR("Akihiro Tsukada <tskd2@yahoo.co.jp>");
-MODULE_DESCRIPTION("Driver for Friio ISDB-T USB2.0 Receiver");
-MODULE_VERSION("0.2");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/usb/dvb-usb/friio.h b/drivers/media/usb/dvb-usb/friio.h
deleted file mode 100644
index 0f461ca10cb..00000000000
--- a/drivers/media/usb/dvb-usb/friio.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* DVB USB compliant Linux driver for the Friio USB2.0 ISDB-T receiver.
- *
- * Copyright (C) 2009 Akihiro Tsukada <tskd2@yahoo.co.jp>
- *
- * This module is based off the the gl861 and vp702x modules.
- *
- * 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, version 2.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#ifndef _DVB_USB_FRIIO_H_
-#define _DVB_USB_FRIIO_H_
-
-/**
- *      Friio Components
- *       USB hub:                                AU4254
- *         USB controller(+ TS dmx & streaming): GL861
- *         Frontend:                             comtech JDVBT-90502
- *             (tuner PLL:                       tua6034, I2C addr:(0xC0 >> 1))
- *             (OFDM demodulator:                TC90502, I2C addr:(0x30 >> 1))
- *         LED x3 (+LNB) control:                PIC 16F676
- *         EEPROM:                               24C08
- *
- *        (USB smart card reader:                AU9522)
- *
- */
-
-#define DVB_USB_LOG_PREFIX "friio"
-#include "dvb-usb.h"
-
-extern int dvb_usb_friio_debug;
-#define deb_info(args...) dprintk(dvb_usb_friio_debug, 0x01, args)
-#define deb_xfer(args...) dprintk(dvb_usb_friio_debug, 0x02, args)
-#define deb_rc(args...)   dprintk(dvb_usb_friio_debug, 0x04, args)
-#define deb_fe(args...)   dprintk(dvb_usb_friio_debug, 0x08, args)
-
-/* Vendor requests */
-#define GL861_WRITE		0x40
-#define GL861_READ		0xc0
-
-/* command bytes */
-#define GL861_REQ_I2C_WRITE	0x01
-#define GL861_REQ_I2C_READ	0x02
-/* For control msg with data argument */
-/* Used for accessing the PLL on the secondary I2C bus of FE via GL861 */
-#define GL861_REQ_I2C_DATA_CTRL_WRITE	0x03
-
-#define GL861_ALTSETTING_COUNT	2
-#define FRIIO_BULK_ALTSETTING	0
-#define FRIIO_ISOC_ALTSETTING	1
-
-/* LED & LNB control via PIC. */
-/* basically, it's serial control with clock and strobe. */
-/* write the below 4bit control data to the reg 0x00 at the I2C addr 0x00 */
-/* when controlling the LEDs, 32bit(saturation, R, G, B) is sent on the bit3*/
-#define FRIIO_CTL_LNB (1 << 0)
-#define FRIIO_CTL_STROBE (1 << 1)
-#define FRIIO_CTL_CLK (1 << 2)
-#define FRIIO_CTL_LED (1 << 3)
-
-/* Front End related */
-
-#define FRIIO_DEMOD_ADDR  (0x30 >> 1)
-#define FRIIO_PLL_ADDR  (0xC0 >> 1)
-
-#define JDVBT90502_PLL_CLK	4000000
-#define JDVBT90502_PLL_DIVIDER	28
-
-#define JDVBT90502_2ND_I2C_REG 0xFE
-
-/* byte index for pll i2c command data structure*/
-/* see datasheet for tua6034 */
-#define DEMOD_REDIRECT_REG 0
-#define ADDRESS_BYTE       1
-#define DIVIDER_BYTE1      2
-#define DIVIDER_BYTE2      3
-#define CONTROL_BYTE       4
-#define BANDSWITCH_BYTE    5
-#define AGC_CTRL_BYTE      5
-#define PLL_CMD_LEN        6
-
-/* bit masks for PLL STATUS response */
-#define PLL_STATUS_POR_MODE   0x80 /* 1: Power on Reset (test) Mode */
-#define PLL_STATUS_LOCKED     0x40 /* 1: locked */
-#define PLL_STATUS_AGC_ACTIVE 0x08 /* 1:active */
-#define PLL_STATUS_TESTMODE   0x07 /* digital output level (5 level) */
-  /* 0.15Vcc step   0x00: < 0.15Vcc, ..., 0x04: >= 0.6Vcc (<= 1Vcc) */
-
-
-struct jdvbt90502_config {
-	u8 demod_address; /* i2c addr for demodulator IC */
-	u8 pll_address;   /* PLL addr on the secondary i2c*/
-};
-extern struct jdvbt90502_config friio_fe_config;
-
-extern struct dvb_frontend *jdvbt90502_attach(struct dvb_usb_device *d);
-#endif
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v5 4/5] dvb-usb-v2/gl861: use usleep_range() for short delay
  2018-04-08 17:21 [PATCH v5 0/5] dvb-usb-friio: decompose friio and merge with gl861 tskd08
                   ` (2 preceding siblings ...)
  2018-04-08 17:21 ` [PATCH v6 3/5] dvb-usb/friio, dvb-usb-v2/gl861: decompose friio and merge with gl861 tskd08
@ 2018-04-08 17:21 ` tskd08
  2018-05-05 11:14   ` Mauro Carvalho Chehab
  2018-04-08 17:21 ` [PATCH v5 5/5] dvb-usb-v2/gl861: ensure USB message buffers DMA'able tskd08
  4 siblings, 1 reply; 11+ messages in thread
From: tskd08 @ 2018-04-08 17:21 UTC (permalink / raw)
  To: linux-media; +Cc: mchehab, Akihiro Tsukada, crope

From: Akihiro Tsukada <tskd08@gmail.com>

As the kernel doc "timers-howto.txt" reads,
short delay with msleep() can take much longer.
In a case of raspbery-pi platform where CONFIG_HZ_100 was set,
it actually affected the init of Friio devices
since it issues lots of i2c transactions with short delay.

Signed-off-by: Akihiro Tsukada <tskd08@gmail.com>
---
Changes since v4:
- none

 drivers/media/usb/dvb-usb-v2/gl861.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/usb/dvb-usb-v2/gl861.c b/drivers/media/usb/dvb-usb-v2/gl861.c
index ecff0062bfb..cdd7bfcb883 100644
--- a/drivers/media/usb/dvb-usb-v2/gl861.c
+++ b/drivers/media/usb/dvb-usb-v2/gl861.c
@@ -45,7 +45,7 @@ static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
 		return -EINVAL;
 	}
 
-	msleep(1); /* avoid I2C errors */
+	usleep_range(1000, 2000); /* avoid I2C errors */
 
 	return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), req, type,
 			       value, index, rbuf, rlen, 2000);
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v5 5/5] dvb-usb-v2/gl861: ensure  USB message buffers DMA'able
  2018-04-08 17:21 [PATCH v5 0/5] dvb-usb-friio: decompose friio and merge with gl861 tskd08
                   ` (3 preceding siblings ...)
  2018-04-08 17:21 ` [PATCH v5 4/5] dvb-usb-v2/gl861: use usleep_range() for short delay tskd08
@ 2018-04-08 17:21 ` tskd08
  2018-05-05 11:17   ` Mauro Carvalho Chehab
  4 siblings, 1 reply; 11+ messages in thread
From: tskd08 @ 2018-04-08 17:21 UTC (permalink / raw)
  To: linux-media; +Cc: mchehab, Akihiro Tsukada, crope

From: Akihiro Tsukada <tskd08@gmail.com>

i2c message buf might be on stack.

Signed-off-by: Akihiro Tsukada <tskd08@gmail.com>
---
Changes since v4:
- none

 drivers/media/usb/dvb-usb-v2/gl861.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/drivers/media/usb/dvb-usb-v2/gl861.c b/drivers/media/usb/dvb-usb-v2/gl861.c
index cdd7bfcb883..47b614da807 100644
--- a/drivers/media/usb/dvb-usb-v2/gl861.c
+++ b/drivers/media/usb/dvb-usb-v2/gl861.c
@@ -22,6 +22,8 @@ static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
 	u16 value = addr << (8 + 1);
 	int wo = (rbuf == NULL || rlen == 0); /* write-only */
 	u8 req, type;
+	u8 *buf;
+	int ret;
 
 	if (wo) {
 		req = GL861_REQ_I2C_WRITE;
@@ -44,11 +46,23 @@ static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
 				KBUILD_MODNAME, wlen);
 		return -EINVAL;
 	}
-
+	buf = NULL;
+	if (rlen > 0) {
+		buf = kmalloc(rlen, GFP_KERNEL);
+		if (!buf)
+			return -ENOMEM;
+	}
 	usleep_range(1000, 2000); /* avoid I2C errors */
 
-	return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), req, type,
-			       value, index, rbuf, rlen, 2000);
+	ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), req, type,
+			      value, index, buf, rlen, 2000);
+	if (rlen > 0) {
+		if (ret > 0)
+			memcpy(rbuf, buf, rlen);
+		kfree(buf);
+	}
+
+	return ret;
 }
 
 /* Friio specific I2C read/write */
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH v6 3/5] dvb-usb/friio, dvb-usb-v2/gl861: decompose friio and merge with gl861
  2018-04-08 17:21 ` [PATCH v6 3/5] dvb-usb/friio, dvb-usb-v2/gl861: decompose friio and merge with gl861 tskd08
@ 2018-05-05 11:12   ` Mauro Carvalho Chehab
  2018-05-13 18:13     ` Akihiro TSUKADA
  0 siblings, 1 reply; 11+ messages in thread
From: Mauro Carvalho Chehab @ 2018-05-05 11:12 UTC (permalink / raw)
  To: tskd08; +Cc: linux-media, mchehab, crope

Em Mon,  9 Apr 2018 02:21:36 +0900
tskd08@gmail.com escreveu:

> From: Akihiro Tsukada <tskd08@gmail.com>
> 
> 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.

Hi Akihiro-san,

Patches 1 and 2 looked OK on my eyes. I'll be applying them.

I have comments to this one. See below. I won't apply the
remaining patches on this series, as they likely depend on it.

> 
> Signed-off-by: Akihiro Tsukada <tskd08@gmail.com>
> ---
> Changes since v5:
> - specify chip name literally
> - i2c algo of gl861 is not (yet?) changed as proposed by Antti,
>   (which is to move the special case handling to demod driver),
>   since I do not yet understand
>   whether it should/can be really moved or not.
> 
> Changes since v4:
> - use new style of specifying pll_desc id of the tuner driver
> 
> Changes since v3:
> - make dvb_usb_device_properties static
> 
> Changes since v2:
> (patch #27928, dvb-usb-friio: split and merge into dvb-usbv2-gl861)
>  - used the new i2c binding helpers instead of my own one
>  - merged gl861-friio.c with gl861.c
> 
>  drivers/media/usb/dvb-usb-v2/Kconfig |   5 +-
>  drivers/media/usb/dvb-usb-v2/gl861.c | 465 +++++++++++++++++++++++-
>  drivers/media/usb/dvb-usb-v2/gl861.h |   1 +
>  drivers/media/usb/dvb-usb/Kconfig    |   6 -
>  drivers/media/usb/dvb-usb/Makefile   |   3 -
>  drivers/media/usb/dvb-usb/friio-fe.c | 441 ----------------------
>  drivers/media/usb/dvb-usb/friio.c    | 522 ---------------------------
>  drivers/media/usb/dvb-usb/friio.h    |  99 -----
>  8 files changed, 462 insertions(+), 1080 deletions(-)
>  delete mode 100644 drivers/media/usb/dvb-usb/friio-fe.c
>  delete mode 100644 drivers/media/usb/dvb-usb/friio.c
>  delete mode 100644 drivers/media/usb/dvb-usb/friio.h
> 
> diff --git a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig
> index 0e4944b2b0f..e0a1f377295 100644
> --- a/drivers/media/usb/dvb-usb-v2/Kconfig
> +++ b/drivers/media/usb/dvb-usb-v2/Kconfig
> @@ -95,10 +95,13 @@ config DVB_USB_GL861
>  	tristate "Genesys Logic GL861 USB2.0 support"
>  	depends on DVB_USB_V2
>  	select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
> +	select DVB_TC90522 if MEDIA_SUBDRV_AUTOSELECT
>  	select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT
> +	select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
>  	help
>  	  Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0
> -	  receiver with USB ID 0db0:5581.
> +	  receiver with USB ID 0db0:5581, Friio White ISDB-T receiver
> +	  with USB ID 0x7a69:0001.
>  
>  config DVB_USB_LME2510
>  	tristate "LME DM04/QQBOX DVB-S USB2.0 support"
> diff --git a/drivers/media/usb/dvb-usb-v2/gl861.c b/drivers/media/usb/dvb-usb-v2/gl861.c
> index b1b09c54786..ecff0062bfb 100644
> --- a/drivers/media/usb/dvb-usb-v2/gl861.c
> +++ b/drivers/media/usb/dvb-usb-v2/gl861.c
> @@ -10,6 +10,8 @@
>  
>  #include "zl10353.h"
>  #include "qt1010.h"
> +#include "tc90522.h"
> +#include "dvb-pll.h"
>  
>  DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
>  
> @@ -49,6 +51,80 @@ static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
>  			       value, index, rbuf, rlen, 2000);
>  }
>  
> +/* Friio specific I2C read/write */
> +/* special USB request is used in Friio's init/config */
> +static int
> +gl861_i2c_rawwrite(struct dvb_usb_device *d, u8 addr, u8 *wbuf, u16 wlen)
> +{
> +	u8 *buf;
> +	int ret;
> +
> +	buf = kmalloc(wlen, GFP_KERNEL);
> +	if (!buf)
> +		return -ENOMEM;
> +
> +	usleep_range(1000, 2000); /* avoid I2C errors */

I guess this is probably also at the original code, but it seems really
weird to sleep here just after kmalloc().

I would move any need for sleeps to the i2c xfer function, where it
makes clearer why it is needed and where. Same applies to other
usleep_range() calls at the functions below.

> +	memcpy(buf, wbuf, wlen);
> +	ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
> +				 GL861_REQ_I2C_RAW, GL861_WRITE,
> +				 addr << (8 + 1), 0x0100, buf, wlen, 2000);
> +	kfree(buf);
> +	return ret;
> +}
> +
> +/*
> + * In Friio,
> + * I2C commnucations to the tuner are relay'ed via the demod (via the bridge),
> + * so its encapsulation to USB message is different from the one to the demod.

This is quite common. I guess the rationale of using the demod's I2C mux
is to avoid noise at the tuner when there are I2C traffic that aren't related
to it.

You should probably implement it via I2C_MUX support.

There are several examples about how to use I2C muxes. See, for example:
	4f75189024f4 ("[media] lgdt3306a: support i2c mux for use by em28xx")
	58d7b541dd96 ("[media] si2168: convert to use an explicit i2c mux core")
	05e0dfd0311b ("[media] cx231xx: convert to use an explicit i2c mux core")
	22e59e7204a4 ("media: af9013: add i2c mux adapter for tuner bus")



> + */
> +static int
> +gl861_i2c_rawread(struct dvb_usb_device *d, u8 addr, u8 *rbuf, u16 rlen)
> +{
> +	u8 *buf;
> +	int ret;
> +
> +	buf = kmalloc(rlen, GFP_KERNEL);
> +	if (!buf)
> +		return -ENOMEM;
> +
> +	usleep_range(1000, 2000); /* avoid I2C errors */
> +
> +	ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
> +				 GL861_REQ_I2C_READ, GL861_READ,
> +				 addr << (8 + 1), 0x0100, buf, rlen, 2000);
> +	if (ret > 0 && rbuf)
> +		memcpy(rbuf, buf, rlen);
> +	kfree(buf);
> +
> +	return ret;
> +}
> +
> +static int
> +gl861_i2c_relay_write(struct dvb_usb_device *d, struct i2c_msg *msg)
> +{
> +	u8 *buf;
> +	int ret;
> +
> +	if (msg->flags & I2C_M_RD)
> +		return -EINVAL;
> +	if (msg->len < 2)
> +		return -EINVAL;
> +
> +	buf = kmalloc(msg->len - 1, GFP_KERNEL);
> +	if (!buf)
> +		return -ENOMEM;
> +	memcpy(buf, msg->buf + 1, msg->len - 1);
> +
> +	usleep_range(1000, 2000); /* avoid I2C errors */
> +
> +	ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
> +				 GL861_REQ_I2C_RAW, GL861_WRITE,
> +				 msg->addr << (8 + 1), msg->buf[0],
> +				 buf, msg->len - 1, 2000);
> +	kfree(buf);
> +	return ret;
> +}
> +
>  /* I2C */
>  static int gl861_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
>  			  int num)
> @@ -63,16 +139,35 @@ static int gl861_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
>  		return -EAGAIN;
>  
>  	for (i = 0; i < num; i++) {
> -		/* write/read request */
> -		if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
> -			if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf,
> -				msg[i].len, msg[i+1].buf, msg[i+1].len) < 0)
> -				break;
> +		int ret;
> +
> +		/*
> +		 * relay'ed reads (from tuner) are implemented by two i2c_msg's:
> +		 *   1) write the tuner reg addr & value to demod reg:0xFE
> +		 *   2) read from demod for the result
> +		 * Special USB requests are used for the messages.
> +		 * This means that those two messages cannot be combined to
> +		 * one URB like the other i2c reads, and if msg[i] is an
> +		 * uncombined read message, then it is a relayed read.
> +		 */
> +		if (msg[i].flags & I2C_M_RD)
> +			ret = gl861_i2c_rawread(d, msg[i].addr,
> +						msg[i].buf, msg[i].len);
> +
> +		/* write to reg:0xFE means a relay'ed write (to tuner) */
> +		else if (msg[i].buf[0] == 0xfe)
> +			ret = gl861_i2c_relay_write(d, &msg[i]);
> +
> +		else if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
> +			ret = gl861_i2c_msg(d, msg[i].addr, msg[i].buf,
> +				msg[i].len, msg[i+1].buf, msg[i+1].len);
>  			i++;
>  		} else
> -			if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf,
> -					  msg[i].len, NULL, 0) < 0)
> -				break;
> +			ret = gl861_i2c_msg(d, msg[i].addr, msg[i].buf,
> +					    msg[i].len, NULL, 0);
> +
> +		if (ret < 0)
> +			break;
>  	}
>  
>  	mutex_unlock(&d->i2c_mutex);
> @@ -89,6 +184,332 @@ static struct i2c_algorithm gl861_i2c_algo = {
>  	.functionality = gl861_i2c_func,
>  };
>  
> +
> +/*
> + * Friio specific stuff
> + */
> +
> +struct friio_priv {
> +	struct i2c_adapter *demod_sub_i2c;
> +	struct i2c_client  *i2c_client_demod;
> +	struct i2c_client  *i2c_client_tuner;
> +};
> +
> +struct friio_config {
> +	struct i2c_board_info demod_info;
> +	struct tc90522_config demod_cfg;
> +
> +	struct i2c_board_info tuner_info;
> +	struct dvb_pll_config tuner_cfg;
> +};
> +
> +static const struct friio_config friio_config = {
> +	.demod_info = { I2C_BOARD_INFO(TC90522_I2C_DEV_TER, 0x18), },
> +	.tuner_info = { I2C_BOARD_INFO("tua6034_friio", 0x60), },
> +};
> +
> +/*
> + * Utility functions for Friio
> + */
> +
> +/* GPIO control in Friio */
> +
> +#define FRIIO_CTL_LNB (1 << 0)
> +#define FRIIO_CTL_STROBE (1 << 1)
> +#define FRIIO_CTL_CLK (1 << 2)
> +#define FRIIO_CTL_LED (1 << 3)
> +
> +#define FRIIO_LED_RUNNING 0x6400ff64
> +#define FRIIO_LED_STOPPED 0x96ff00ff
> +
> +/* control PIC16F676 attached to Friio */
> +static int friio_ext_ctl(struct dvb_usb_device *d,
> +			    u32 sat_color, int power_on)
> +{
> +	int i, ret;
> +	struct i2c_msg msg;
> +	u8 *buf;
> +	u32 mask;
> +	u8 power = (power_on) ? FRIIO_CTL_LNB : 0;
> +
> +	buf = kmalloc(2, GFP_KERNEL);
> +	if (!buf)
> +		return -ENOMEM;
> +
> +	msg.addr = 0x00;
> +	msg.flags = 0;
> +	msg.len = 2;
> +	msg.buf = buf;
> +	buf[0] = 0x00;
> +
> +	/* send 2bit header (&B10) */
> +	buf[1] = power | FRIIO_CTL_LED | FRIIO_CTL_STROBE;
> +	ret = i2c_transfer(&d->i2c_adap, &msg, 1);
> +	buf[1] |= FRIIO_CTL_CLK;
> +	ret += i2c_transfer(&d->i2c_adap, &msg, 1);
> +
> +	buf[1] = power | FRIIO_CTL_STROBE;
> +	ret += i2c_transfer(&d->i2c_adap, &msg, 1);
> +	buf[1] |= FRIIO_CTL_CLK;
> +	ret += i2c_transfer(&d->i2c_adap, &msg, 1);
> +
> +	/* send 32bit(satur, R, G, B) data in serial */
> +	mask = 1 << 31;
> +	for (i = 0; i < 32; i++) {
> +		buf[1] = power | FRIIO_CTL_STROBE;
> +		if (sat_color & mask)
> +			buf[1] |= FRIIO_CTL_LED;
> +		ret += i2c_transfer(&d->i2c_adap, &msg, 1);
> +		buf[1] |= FRIIO_CTL_CLK;
> +		ret += i2c_transfer(&d->i2c_adap, &msg, 1);
> +		mask >>= 1;
> +	}
> +
> +	/* set the strobe off */
> +	buf[1] = power;
> +	ret += i2c_transfer(&d->i2c_adap, &msg, 1);
> +	buf[1] |= FRIIO_CTL_CLK;
> +	ret += i2c_transfer(&d->i2c_adap, &msg, 1);
> +
> +	kfree(buf);
> +	return (ret == 70) ? 0 : -EREMOTEIO;
> +}
> +
> +/* init/config of Friio demod chip(?) */
> +static int friio_reset(struct dvb_usb_device *d)
> +{
> +	int i, ret;
> +	u8 wbuf[2], rbuf[2];
> +
> +	static const u8 friio_init_cmds[][2] = {
> +		{0x33, 0x08}, {0x37, 0x40}, {0x3a, 0x1f}, {0x3b, 0xff},
> +		{0x3c, 0x1f}, {0x3d, 0xff}, {0x38, 0x00}, {0x35, 0x00},
> +		{0x39, 0x00}, {0x36, 0x00},
> +	};
> +
> +	ret = usb_set_interface(d->udev, 0, 0);
> +	if (ret < 0)
> +		return ret;
> +
> +	wbuf[0] = 0x11;
> +	wbuf[1] = 0x02;
> +	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
> +	if (ret < 0)
> +		return ret;
> +	usleep_range(2000, 3000);
> +
> +	wbuf[0] = 0x11;
> +	wbuf[1] = 0x00;
> +	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
> +	if (ret < 0)
> +		return ret;
> +	usleep_range(1000, 2000);

Hmm... you had already usleeps() all over I2C xfer routines. Why adding
extra sleeps here?

Also, why isn't it calling i2c_transfer() instead of gl861_i2c_msg()?
Same applies to other similar calls.

> +
> +	/*
> +	 * Check if the dev is really a Friio White, since it might be
> +	 * another device, Friio Black, with the same VID/PID.
> +	 */
> +
> +	wbuf[0] = 0x03;
> +	wbuf[1] = 0x80;
> +	ret = gl861_i2c_rawwrite(d, 0x09, wbuf, 2);
> +	if (ret < 0)
> +		return ret;
> +
> +	usleep_range(2000, 3000);
> +	ret = gl861_i2c_rawread(d, 0x09, rbuf, 2);
> +	if (ret < 0)
> +		return ret;
> +	if (rbuf[0] != 0xff || rbuf[1] != 0xff)
> +		return -ENODEV;
> +
> +
> +	ret = gl861_i2c_rawwrite(d, 0x48, wbuf, 2);
> +	if (ret < 0)
> +		return ret;
> +	usleep_range(2000, 3000);
> +
> +	ret = gl861_i2c_rawread(d, 0x48, rbuf, 2);
> +	if (ret < 0)
> +		return ret;
> +	if (rbuf[0] != 0xff || rbuf[1] != 0xff)
> +		return -ENODEV;
> +
> +	usleep_range(1000, 2000);
> +
> +	wbuf[0] = 0x30;
> +	wbuf[1] = 0x04;
> +	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
> +	if (ret < 0)
> +		return ret;
> +	usleep_range(2000, 3000);
> +
> +	wbuf[0] = 0x00;
> +	wbuf[1] = 0x01;
> +	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
> +	if (ret < 0)
> +		return ret;
> +
> +	wbuf[0] = 0x06;
> +	wbuf[1] = 0x0f;
> +	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
> +	if (ret < 0)
> +		return ret;
> +
> +	usleep_range(10000, 11000);
> +	for (i = 0; i < ARRAY_SIZE(friio_init_cmds); i++) {
> +		ret = gl861_i2c_msg(d, 0x00, (u8 *)friio_init_cmds[i], 2,
> +				      NULL, 0);
> +		if (ret < 0)
> +			return ret;
> +		usleep_range(1000, 2000);
> +	}
> +	return 0;
> +}
> +
> +/*
> + * DVB callbacks for Friio
> + */
> +
> +static int friio_power_ctrl(struct dvb_usb_device *d, int onoff)
> +{
> +	return onoff ? friio_reset(d) : 0;
> +}
> +
> +static int friio_frontend_attach(struct dvb_usb_adapter *adap)
> +{
> +	const struct i2c_board_info *info;
> +	struct tc90522_config cfg;
> +	struct i2c_client *cl;
> +	struct friio_priv *priv;
> +
> +	info = &friio_config.demod_info;
> +	cl = dvb_module_probe("tc90522", info->type,
> +			      &adap_to_d(adap)->i2c_adap, info->addr, &cfg);
> +	if (!cl)
> +		return -ENODEV;
> +	adap->fe[0] = cfg.fe;
> +
> +	priv = adap_to_priv(adap);
> +	priv->i2c_client_demod = cl;
> +	priv->demod_sub_i2c = cfg.tuner_i2c;
> +	return 0;
> +}
> +
> +static int friio_frontend_detach(struct dvb_usb_adapter *adap)
> +{
> +	struct friio_priv *priv;
> +
> +	priv = adap_to_priv(adap);
> +	dvb_module_release(priv->i2c_client_demod);
> +	return 0;
> +}
> +
> +static int friio_tuner_attach(struct dvb_usb_adapter *adap)
> +{
> +	const struct i2c_board_info *info;
> +	struct dvb_pll_config cfg;
> +	struct i2c_client *cl;
> +	struct friio_priv *priv;
> +
> +	priv = adap_to_priv(adap);
> +	info = &friio_config.tuner_info;
> +	cfg = friio_config.tuner_cfg;
> +	cfg.fe = adap->fe[0];
> +
> +	cl = dvb_module_probe("dvb_pll", info->type,
> +			      priv->demod_sub_i2c, info->addr, &cfg);
> +	if (!cl)
> +		return -ENODEV;
> +	priv->i2c_client_tuner = cl;
> +	return 0;
> +}
> +
> +static int friio_tuner_detach(struct dvb_usb_adapter *adap)
> +{
> +	struct friio_priv *priv;
> +
> +	priv = adap_to_priv(adap);
> +#ifndef CONFIG_MEDIA_ATTACH
> +	/* Note:
> +	 * When CONFIG_MEDIA_ATTACH is defined,
> +	 * the tuner module is already "put" by the following call trace:
> +	 *
> +	 * symbol_put_addr(fe->ops.tuner_ops.release)
> +	 * dvb_frontend_invoke_release(fe, fe->ops.tuner_ops.release)
> +	 * dvb_frontend_detach(fe)
> +	 * dvb_usbv2_adapter_frontend_exit(adap)
> +	 * dvb_usbv2_adapter_exit(d)
> +	 * dvb_usbv2_exit(d)
> +	 * dvb_usbv2_disconnect(intf)
> +	 *
> +	 * Since the tuner driver of Friio (dvb-pll) has .release defined,
> +	 * dvb_module_release() should be skipped if CONFIG_MEDIA_ATTACH,
> +	 * to avoid double-putting the module.
> +	 * Even without dvb_module_release(),
> +	 * the tuner i2c device is automatically unregistered
> +	 * when its i2c adapter is unregistered with the demod i2c device.
> +	 *
> +	 * The same "double-putting" can happen to the demod module as well,
> +	 * but tc90522 does not define any _invoke_release()'ed functions,
> +	 * thus Friio is not affected.
> +	 */
> +	dvb_module_release(priv->i2c_client_tuner);
> +#endif

This looks really weird to me... why only at this driver we need this?
If we have some issues at the DVB core - or at dvb-usb-v2, the fix should
be there, and not here.

> +	return 0;
> +}
> +
> +static int friio_init(struct dvb_usb_device *d)
> +{
> +	int i;
> +	int ret;
> +	struct friio_priv *priv;
> +
> +	static const u8 demod_init[][2] = {
> +		{0x01, 0x40}, {0x04, 0x38}, {0x05, 0x40}, {0x07, 0x40},
> +		{0x0f, 0x4f}, {0x11, 0x21}, {0x12, 0x0b}, {0x13, 0x2f},
> +		{0x14, 0x31}, {0x16, 0x02}, {0x21, 0xc4}, {0x22, 0x20},
> +		{0x2c, 0x79}, {0x2d, 0x34}, {0x2f, 0x00}, {0x30, 0x28},
> +		{0x31, 0x31}, {0x32, 0xdf}, {0x38, 0x01}, {0x39, 0x78},
> +		{0x3b, 0x33}, {0x3c, 0x33}, {0x48, 0x90}, {0x51, 0x68},
> +		{0x5e, 0x38}, {0x71, 0x00}, {0x72, 0x08}, {0x77, 0x00},
> +		{0xc0, 0x21}, {0xc1, 0x10}, {0xe4, 0x1a}, {0xea, 0x1f},
> +		{0x77, 0x00}, {0x71, 0x00}, {0x71, 0x00}, {0x76, 0x0c},
> +	};
> +
> +	/* power on LNA? */
> +	ret = friio_ext_ctl(d, FRIIO_LED_STOPPED, true);
> +	if (ret < 0)
> +		return ret;
> +	msleep(20);
> +
> +	/* init/config demod */
> +	priv = d_to_priv(d);
> +	for (i = 0; i < ARRAY_SIZE(demod_init); i++) {
> +		int ret;
> +
> +		ret = i2c_master_send(priv->i2c_client_demod, demod_init[i], 2);
> +		if (ret < 0)
> +			return ret;
> +	}
> +	msleep(100);
> +	return 0;
> +}
> +
> +static void friio_exit(struct dvb_usb_device *d)
> +{
> +	friio_ext_ctl(d, FRIIO_LED_STOPPED, false);
> +}
> +
> +static int friio_streaming_ctrl(struct dvb_frontend *fe, int onoff)
> +{
> +	u32 led_color;
> +
> +	led_color = onoff ? FRIIO_LED_RUNNING : FRIIO_LED_STOPPED;
> +	return friio_ext_ctl(fe_to_d(fe), led_color, true);
> +}
> +
> +
>  /* Callbacks for DVB USB */
>  static struct zl10353_config gl861_zl10353_config = {
>  	.demod_address = 0x0f,
> @@ -148,11 +569,39 @@ static struct dvb_usb_device_properties gl861_props = {
>  	}
>  };
>  
> +static struct dvb_usb_device_properties friio_props = {
> +	.driver_name = KBUILD_MODNAME,
> +	.owner = THIS_MODULE,
> +	.adapter_nr = adapter_nr,
> +
> +	.size_of_priv = sizeof(struct friio_priv),
> +
> +	.i2c_algo = &gl861_i2c_algo,
> +	.power_ctrl = friio_power_ctrl,
> +	.frontend_attach = friio_frontend_attach,
> +	.frontend_detach = friio_frontend_detach,
> +	.tuner_attach = friio_tuner_attach,
> +	.tuner_detach = friio_tuner_detach,
> +	.init = friio_init,
> +	.exit = friio_exit,
> +	.streaming_ctrl = friio_streaming_ctrl,
> +
> +	.num_adapters = 1,
> +	.adapter = {
> +		{
> +			.stream = DVB_USB_STREAM_BULK(0x01, 8, 16384),
> +		}
> +	}
> +};
> +
> +
>  static const struct usb_device_id gl861_id_table[] = {
>  	{ DVB_USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580_55801,
>  		&gl861_props, "MSI Mega Sky 55801 DVB-T USB2.0", NULL) },
>  	{ DVB_USB_DEVICE(USB_VID_ALINK, USB_VID_ALINK_DTU,
>  		&gl861_props, "A-LINK DTU DVB-T USB2.0", NULL) },
> +	{ DVB_USB_DEVICE(USB_VID_774, USB_PID_FRIIO_WHITE,
> +		&friio_props, "774 Friio White ISDB-T USB2.0", NULL) },
>  	{ }
>  };
>  MODULE_DEVICE_TABLE(usb, gl861_id_table);
> diff --git a/drivers/media/usb/dvb-usb-v2/gl861.h b/drivers/media/usb/dvb-usb-v2/gl861.h
> index b651b857e03..02c00e10748 100644
> --- a/drivers/media/usb/dvb-usb-v2/gl861.h
> +++ b/drivers/media/usb/dvb-usb-v2/gl861.h
> @@ -9,5 +9,6 @@
>  
>  #define GL861_REQ_I2C_WRITE	0x01
>  #define GL861_REQ_I2C_READ	0x02
> +#define GL861_REQ_I2C_RAW	0x03
>  
>  #endif
> diff --git a/drivers/media/usb/dvb-usb/Kconfig b/drivers/media/usb/dvb-usb/Kconfig
> index 2651ae27734..1990d1c975e 100644
> --- a/drivers/media/usb/dvb-usb/Kconfig
> +++ b/drivers/media/usb/dvb-usb/Kconfig
> @@ -312,12 +312,6 @@ config DVB_USB_DTV5100
>  	help
>  	  Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver.
>  
> -config DVB_USB_FRIIO
> -	tristate "Friio ISDB-T USB2.0 Receiver support"
> -	depends on DVB_USB
> -	help
> -	  Say Y here to support the Japanese DTV receiver Friio.
> -
>  config DVB_USB_AZ6027
>  	tristate "Azurewave DVB-S/S2 USB2.0 AZ6027 support"
>  	depends on DVB_USB
> diff --git a/drivers/media/usb/dvb-usb/Makefile b/drivers/media/usb/dvb-usb/Makefile
> index 9ad2618408e..407d90ca8be 100644
> --- a/drivers/media/usb/dvb-usb/Makefile
> +++ b/drivers/media/usb/dvb-usb/Makefile
> @@ -71,9 +71,6 @@ obj-$(CONFIG_DVB_USB_DTV5100) += dvb-usb-dtv5100.o
>  dvb-usb-cinergyT2-objs := cinergyT2-core.o cinergyT2-fe.o
>  obj-$(CONFIG_DVB_USB_CINERGY_T2) += dvb-usb-cinergyT2.o
>  
> -dvb-usb-friio-objs := friio.o friio-fe.o
> -obj-$(CONFIG_DVB_USB_FRIIO) += dvb-usb-friio.o
> -
>  dvb-usb-az6027-objs := az6027.o
>  obj-$(CONFIG_DVB_USB_AZ6027) += dvb-usb-az6027.o
>  
> diff --git a/drivers/media/usb/dvb-usb/friio-fe.c b/drivers/media/usb/dvb-usb/friio-fe.c
> deleted file mode 100644
> index b2830c15754..00000000000
> --- a/drivers/media/usb/dvb-usb/friio-fe.c
> +++ /dev/null
> @@ -1,441 +0,0 @@
> -/* DVB USB compliant Linux driver for the Friio USB2.0 ISDB-T receiver.
> - *
> - * Copyright (C) 2009 Akihiro Tsukada <tskd2@yahoo.co.jp>
> - *
> - * This module is based off the the gl861 and vp702x modules.
> - *
> - * 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, version 2.
> - *
> - * see Documentation/dvb/README.dvb-usb for more information
> - */
> -#include <linux/init.h>
> -#include <linux/string.h>
> -#include <linux/slab.h>
> -#include <linux/kernel.h>
> -
> -#include "friio.h"
> -
> -struct jdvbt90502_state {
> -	struct i2c_adapter *i2c;
> -	struct dvb_frontend frontend;
> -	struct jdvbt90502_config config;
> -};
> -
> -/* NOTE: TC90502 has 16bit register-address? */
> -/* register 0x0100 is used for reading PLL status, so reg is u16 here */
> -static int jdvbt90502_reg_read(struct jdvbt90502_state *state,
> -			       const u16 reg, u8 *buf, const size_t count)
> -{
> -	int ret;
> -	u8 wbuf[3];
> -	struct i2c_msg msg[2];
> -
> -	wbuf[0] = reg & 0xFF;
> -	wbuf[1] = 0;
> -	wbuf[2] = reg >> 8;
> -
> -	msg[0].addr = state->config.demod_address;
> -	msg[0].flags = 0;
> -	msg[0].buf = wbuf;
> -	msg[0].len = sizeof(wbuf);
> -
> -	msg[1].addr = msg[0].addr;
> -	msg[1].flags = I2C_M_RD;
> -	msg[1].buf = buf;
> -	msg[1].len = count;
> -
> -	ret = i2c_transfer(state->i2c, msg, 2);
> -	if (ret != 2) {
> -		deb_fe(" reg read failed.\n");
> -		return -EREMOTEIO;
> -	}
> -	return 0;
> -}
> -
> -/* currently 16bit register-address is not used, so reg is u8 here */
> -static int jdvbt90502_single_reg_write(struct jdvbt90502_state *state,
> -				       const u8 reg, const u8 val)
> -{
> -	struct i2c_msg msg;
> -	u8 wbuf[2];
> -
> -	wbuf[0] = reg;
> -	wbuf[1] = val;
> -
> -	msg.addr = state->config.demod_address;
> -	msg.flags = 0;
> -	msg.buf = wbuf;
> -	msg.len = sizeof(wbuf);
> -
> -	if (i2c_transfer(state->i2c, &msg, 1) != 1) {
> -		deb_fe(" reg write failed.");
> -		return -EREMOTEIO;
> -	}
> -	return 0;
> -}
> -
> -static int _jdvbt90502_write(struct dvb_frontend *fe, const u8 buf[], int len)
> -{
> -	struct jdvbt90502_state *state = fe->demodulator_priv;
> -	int err, i;
> -	for (i = 0; i < len - 1; i++) {
> -		err = jdvbt90502_single_reg_write(state,
> -						  buf[0] + i, buf[i + 1]);
> -		if (err)
> -			return err;
> -	}
> -
> -	return 0;
> -}
> -
> -/* read pll status byte via the demodulator's I2C register */
> -/* note: Win box reads it by 8B block at the I2C addr 0x30 from reg:0x80 */
> -static int jdvbt90502_pll_read(struct jdvbt90502_state *state, u8 *result)
> -{
> -	int ret;
> -
> -	/* +1 for reading */
> -	u8 pll_addr_byte = (state->config.pll_address << 1) + 1;
> -
> -	*result = 0;
> -
> -	ret = jdvbt90502_single_reg_write(state, JDVBT90502_2ND_I2C_REG,
> -					  pll_addr_byte);
> -	if (ret)
> -		goto error;
> -
> -	ret = jdvbt90502_reg_read(state, 0x0100, result, 1);
> -	if (ret)
> -		goto error;
> -
> -	deb_fe("PLL read val:%02x\n", *result);
> -	return 0;
> -
> -error:
> -	deb_fe("%s:ret == %d\n", __func__, ret);
> -	return -EREMOTEIO;
> -}
> -
> -
> -/* set pll frequency via the demodulator's I2C register */
> -static int jdvbt90502_pll_set_freq(struct jdvbt90502_state *state, u32 freq)
> -{
> -	int ret;
> -	int retry;
> -	u8 res1;
> -	u8 res2[9];
> -
> -	u8 pll_freq_cmd[PLL_CMD_LEN];
> -	u8 pll_agc_cmd[PLL_CMD_LEN];
> -	struct i2c_msg msg[2];
> -	u32 f;
> -
> -	deb_fe("%s: freq=%d, step=%d\n", __func__, freq,
> -	       state->frontend.ops.info.frequency_stepsize);
> -	/* freq -> oscilator frequency conversion. */
> -	/* freq: 473,000,000 + n*6,000,000 [+ 142857 (center freq. shift)] */
> -	f = freq / state->frontend.ops.info.frequency_stepsize;
> -	/* add 399[1/7 MHZ] = 57MHz for the IF  */
> -	f += 399;
> -	/* add center frequency shift if necessary */
> -	if (f % 7 == 0)
> -		f++;
> -	pll_freq_cmd[DEMOD_REDIRECT_REG] = JDVBT90502_2ND_I2C_REG; /* 0xFE */
> -	pll_freq_cmd[ADDRESS_BYTE] = state->config.pll_address << 1;
> -	pll_freq_cmd[DIVIDER_BYTE1] = (f >> 8) & 0x7F;
> -	pll_freq_cmd[DIVIDER_BYTE2] = f & 0xFF;
> -	pll_freq_cmd[CONTROL_BYTE] = 0xB2; /* ref.divider:28, 4MHz/28=1/7MHz */
> -	pll_freq_cmd[BANDSWITCH_BYTE] = 0x08;	/* UHF band */
> -
> -	msg[0].addr = state->config.demod_address;
> -	msg[0].flags = 0;
> -	msg[0].buf = pll_freq_cmd;
> -	msg[0].len = sizeof(pll_freq_cmd);
> -
> -	ret = i2c_transfer(state->i2c, &msg[0], 1);
> -	if (ret != 1)
> -		goto error;
> -
> -	udelay(50);
> -
> -	pll_agc_cmd[DEMOD_REDIRECT_REG] = pll_freq_cmd[DEMOD_REDIRECT_REG];
> -	pll_agc_cmd[ADDRESS_BYTE] = pll_freq_cmd[ADDRESS_BYTE];
> -	pll_agc_cmd[DIVIDER_BYTE1] = pll_freq_cmd[DIVIDER_BYTE1];
> -	pll_agc_cmd[DIVIDER_BYTE2] = pll_freq_cmd[DIVIDER_BYTE2];
> -	pll_agc_cmd[CONTROL_BYTE] = 0x9A; /*  AGC_CTRL instead of BANDSWITCH */
> -	pll_agc_cmd[AGC_CTRL_BYTE] = 0x50;
> -	/* AGC Time Constant 2s, AGC take-over point:103dBuV(lowest) */
> -
> -	msg[1].addr = msg[0].addr;
> -	msg[1].flags = 0;
> -	msg[1].buf = pll_agc_cmd;
> -	msg[1].len = sizeof(pll_agc_cmd);
> -
> -	ret = i2c_transfer(state->i2c, &msg[1], 1);
> -	if (ret != 1)
> -		goto error;
> -
> -	/* I don't know what these cmds are for,  */
> -	/* but the USB log on a windows box contains them */
> -	ret = jdvbt90502_single_reg_write(state, 0x01, 0x40);
> -	ret |= jdvbt90502_single_reg_write(state, 0x01, 0x00);
> -	if (ret)
> -		goto error;
> -	udelay(100);
> -
> -	/* wait for the demod to be ready? */
> -#define RETRY_COUNT 5
> -	for (retry = 0; retry < RETRY_COUNT; retry++) {
> -		ret = jdvbt90502_reg_read(state, 0x0096, &res1, 1);
> -		if (ret)
> -			goto error;
> -		/* if (res1 != 0x00) goto error; */
> -		ret = jdvbt90502_reg_read(state, 0x00B0, res2, sizeof(res2));
> -		if (ret)
> -			goto error;
> -		if (res2[0] >= 0xA7)
> -			break;
> -		msleep(100);
> -	}
> -	if (retry >= RETRY_COUNT) {
> -		deb_fe("%s: FE does not get ready after freq setting.\n",
> -		       __func__);
> -		return -EREMOTEIO;
> -	}
> -
> -	return 0;
> -error:
> -	deb_fe("%s:ret == %d\n", __func__, ret);
> -	return -EREMOTEIO;
> -}
> -
> -static int jdvbt90502_read_status(struct dvb_frontend *fe,
> -				  enum fe_status *state)
> -{
> -	u8 result;
> -	int ret;
> -
> -	*state = FE_HAS_SIGNAL;
> -
> -	ret = jdvbt90502_pll_read(fe->demodulator_priv, &result);
> -	if (ret) {
> -		deb_fe("%s:ret == %d\n", __func__, ret);
> -		return -EREMOTEIO;
> -	}
> -
> -	*state = FE_HAS_SIGNAL
> -		| FE_HAS_CARRIER
> -		| FE_HAS_VITERBI
> -		| FE_HAS_SYNC;
> -
> -	if (result & PLL_STATUS_LOCKED)
> -		*state |= FE_HAS_LOCK;
> -
> -	return 0;
> -}
> -
> -static int jdvbt90502_read_signal_strength(struct dvb_frontend *fe,
> -					   u16 *strength)
> -{
> -	int ret;
> -	u8 rbuf[37];
> -
> -	*strength = 0;
> -
> -	/* status register (incl. signal strength) : 0x89  */
> -	/* TODO: read just the necessary registers [0x8B..0x8D]? */
> -	ret = jdvbt90502_reg_read(fe->demodulator_priv, 0x0089,
> -				  rbuf, sizeof(rbuf));
> -
> -	if (ret) {
> -		deb_fe("%s:ret == %d\n", __func__, ret);
> -		return -EREMOTEIO;
> -	}
> -
> -	/* signal_strength: rbuf[2-4] (24bit BE), use lower 16bit for now. */
> -	*strength = (rbuf[3] << 8) + rbuf[4];
> -	if (rbuf[2])
> -		*strength = 0xffff;
> -
> -	return 0;
> -}
> -
> -static int jdvbt90502_set_frontend(struct dvb_frontend *fe)
> -{
> -	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
> -
> -	/**
> -	 * NOTE: ignore all the parameters except frequency.
> -	 *       others should be fixed to the proper value for ISDB-T,
> -	 *       but don't check here.
> -	 */
> -
> -	struct jdvbt90502_state *state = fe->demodulator_priv;
> -	int ret;
> -
> -	deb_fe("%s: Freq:%d\n", __func__, p->frequency);
> -
> -	/* This driver only works on auto mode */
> -	p->inversion = INVERSION_AUTO;
> -	p->bandwidth_hz = 6000000;
> -	p->code_rate_HP = FEC_AUTO;
> -	p->code_rate_LP = FEC_AUTO;
> -	p->modulation = QAM_64;
> -	p->transmission_mode = TRANSMISSION_MODE_AUTO;
> -	p->guard_interval = GUARD_INTERVAL_AUTO;
> -	p->hierarchy = HIERARCHY_AUTO;
> -	p->delivery_system = SYS_ISDBT;
> -
> -	ret = jdvbt90502_pll_set_freq(state, p->frequency);
> -	if (ret) {
> -		deb_fe("%s:ret == %d\n", __func__, ret);
> -		return -EREMOTEIO;
> -	}
> -
> -	return 0;
> -}
> -
> -
> -/*
> - * (reg, val) commad list to initialize this module.
> - *  captured on a Windows box.
> - */
> -static u8 init_code[][2] = {
> -	{0x01, 0x40},
> -	{0x04, 0x38},
> -	{0x05, 0x40},
> -	{0x07, 0x40},
> -	{0x0F, 0x4F},
> -	{0x11, 0x21},
> -	{0x12, 0x0B},
> -	{0x13, 0x2F},
> -	{0x14, 0x31},
> -	{0x16, 0x02},
> -	{0x21, 0xC4},
> -	{0x22, 0x20},
> -	{0x2C, 0x79},
> -	{0x2D, 0x34},
> -	{0x2F, 0x00},
> -	{0x30, 0x28},
> -	{0x31, 0x31},
> -	{0x32, 0xDF},
> -	{0x38, 0x01},
> -	{0x39, 0x78},
> -	{0x3B, 0x33},
> -	{0x3C, 0x33},
> -	{0x48, 0x90},
> -	{0x51, 0x68},
> -	{0x5E, 0x38},
> -	{0x71, 0x00},
> -	{0x72, 0x08},
> -	{0x77, 0x00},
> -	{0xC0, 0x21},
> -	{0xC1, 0x10},
> -	{0xE4, 0x1A},
> -	{0xEA, 0x1F},
> -	{0x77, 0x00},
> -	{0x71, 0x00},
> -	{0x71, 0x00},
> -	{0x76, 0x0C},
> -};
> -
> -static int jdvbt90502_init(struct dvb_frontend *fe)
> -{
> -	int i = -1;
> -	int ret;
> -	struct i2c_msg msg;
> -
> -	struct jdvbt90502_state *state = fe->demodulator_priv;
> -
> -	deb_fe("%s called.\n", __func__);
> -
> -	msg.addr = state->config.demod_address;
> -	msg.flags = 0;
> -	msg.len = 2;
> -	for (i = 0; i < ARRAY_SIZE(init_code); i++) {
> -		msg.buf = init_code[i];
> -		ret = i2c_transfer(state->i2c, &msg, 1);
> -		if (ret != 1)
> -			goto error;
> -	}
> -	fe->dtv_property_cache.delivery_system = SYS_ISDBT;
> -	msleep(100);
> -
> -	return 0;
> -
> -error:
> -	deb_fe("%s: init_code[%d] failed. ret==%d\n", __func__, i, ret);
> -	return -EREMOTEIO;
> -}
> -
> -
> -static void jdvbt90502_release(struct dvb_frontend *fe)
> -{
> -	struct jdvbt90502_state *state = fe->demodulator_priv;
> -	kfree(state);
> -}
> -
> -
> -static const struct dvb_frontend_ops jdvbt90502_ops;
> -
> -struct dvb_frontend *jdvbt90502_attach(struct dvb_usb_device *d)
> -{
> -	struct jdvbt90502_state *state = NULL;
> -
> -	deb_info("%s called.\n", __func__);
> -
> -	/* allocate memory for the internal state */
> -	state = kzalloc(sizeof(struct jdvbt90502_state), GFP_KERNEL);
> -	if (state == NULL)
> -		goto error;
> -
> -	/* setup the state */
> -	state->i2c = &d->i2c_adap;
> -	state->config = friio_fe_config;
> -
> -	/* create dvb_frontend */
> -	state->frontend.ops = jdvbt90502_ops;
> -	state->frontend.demodulator_priv = state;
> -
> -	if (jdvbt90502_init(&state->frontend) < 0)
> -		goto error;
> -
> -	return &state->frontend;
> -
> -error:
> -	kfree(state);
> -	return NULL;
> -}
> -
> -static const struct dvb_frontend_ops jdvbt90502_ops = {
> -	.delsys = { SYS_ISDBT },
> -	.info = {
> -		.name			= "Comtech JDVBT90502 ISDB-T",
> -		.frequency_min		= 473000000, /* UHF 13ch, center */
> -		.frequency_max		= 767142857, /* UHF 62ch, center */
> -		.frequency_stepsize	= JDVBT90502_PLL_CLK / JDVBT90502_PLL_DIVIDER,
> -		.frequency_tolerance	= 0,
> -
> -		/* NOTE: this driver ignores all parameters but frequency. */
> -		.caps = FE_CAN_INVERSION_AUTO |
> -			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
> -			FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
> -			FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
> -			FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
> -			FE_CAN_TRANSMISSION_MODE_AUTO |
> -			FE_CAN_GUARD_INTERVAL_AUTO |
> -			FE_CAN_HIERARCHY_AUTO,
> -	},
> -
> -	.release = jdvbt90502_release,
> -
> -	.init = jdvbt90502_init,
> -	.write = _jdvbt90502_write,
> -
> -	.set_frontend = jdvbt90502_set_frontend,
> -
> -	.read_status = jdvbt90502_read_status,
> -	.read_signal_strength = jdvbt90502_read_signal_strength,
> -};
> diff --git a/drivers/media/usb/dvb-usb/friio.c b/drivers/media/usb/dvb-usb/friio.c
> deleted file mode 100644
> index 16875945e66..00000000000
> --- a/drivers/media/usb/dvb-usb/friio.c
> +++ /dev/null
> @@ -1,522 +0,0 @@
> -/* DVB USB compliant Linux driver for the Friio USB2.0 ISDB-T receiver.
> - *
> - * Copyright (C) 2009 Akihiro Tsukada <tskd2@yahoo.co.jp>
> - *
> - * This module is based off the the gl861 and vp702x modules.
> - *
> - * 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, version 2.
> - *
> - * see Documentation/dvb/README.dvb-usb for more information
> - */
> -#include "friio.h"
> -
> -/* debug */
> -int dvb_usb_friio_debug;
> -module_param_named(debug, dvb_usb_friio_debug, int, 0644);
> -MODULE_PARM_DESC(debug,
> -		 "set debugging level (1=info,2=xfer,4=rc,8=fe (or-able))."
> -		 DVB_USB_DEBUG_STATUS);
> -
> -DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
> -
> -/*
> - * Indirect I2C access to the PLL via FE.
> - * whole I2C protocol data to the PLL is sent via the FE's I2C register.
> - * This is done by a control msg to the FE with the I2C data accompanied, and
> - * a specific USB request number is assigned for that purpose.
> - *
> - * this func sends wbuf[1..] to the I2C register wbuf[0] at addr (= at FE).
> - * TODO: refoctored, smarter i2c functions.
> - */
> -static int gl861_i2c_ctrlmsg_data(struct dvb_usb_device *d, u8 addr,
> -				  u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
> -{
> -	u16 index = wbuf[0];	/* must be JDVBT90502_2ND_I2C_REG(=0xFE) */
> -	u16 value = addr << (8 + 1);
> -	int wo = (rbuf == NULL || rlen == 0);	/* write only */
> -	u8 req, type;
> -
> -	deb_xfer("write to PLL:0x%02x via FE reg:0x%02x, len:%d\n",
> -		 wbuf[1], wbuf[0], wlen - 1);
> -
> -	if (wo && wlen >= 2) {
> -		req = GL861_REQ_I2C_DATA_CTRL_WRITE;
> -		type = GL861_WRITE;
> -		udelay(20);
> -		return usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
> -				       req, type, value, index,
> -				       &wbuf[1], wlen - 1, 2000);
> -	}
> -
> -	deb_xfer("not supported ctrl-msg, aborting.");
> -	return -EINVAL;
> -}
> -
> -/* normal I2C access (without extra data arguments).
> - * write to the register wbuf[0] at I2C address addr with the value wbuf[1],
> - *  or read from the register wbuf[0].
> - * register address can be 16bit (wbuf[2]<<8 | wbuf[0]) if wlen==3
> - */
> -static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
> -			 u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
> -{
> -	u16 index;
> -	u16 value = addr << (8 + 1);
> -	int wo = (rbuf == NULL || rlen == 0);	/* write-only */
> -	u8 req, type;
> -	unsigned int pipe;
> -
> -	/* special case for the indirect I2C access to the PLL via FE, */
> -	if (addr == friio_fe_config.demod_address &&
> -	    wbuf[0] == JDVBT90502_2ND_I2C_REG)
> -		return gl861_i2c_ctrlmsg_data(d, addr, wbuf, wlen, rbuf, rlen);
> -
> -	if (wo) {
> -		req = GL861_REQ_I2C_WRITE;
> -		type = GL861_WRITE;
> -		pipe = usb_sndctrlpipe(d->udev, 0);
> -	} else {		/* rw */
> -		req = GL861_REQ_I2C_READ;
> -		type = GL861_READ;
> -		pipe = usb_rcvctrlpipe(d->udev, 0);
> -	}
> -
> -	switch (wlen) {
> -	case 1:
> -		index = wbuf[0];
> -		break;
> -	case 2:
> -		index = wbuf[0];
> -		value = value + wbuf[1];
> -		break;
> -	case 3:
> -		/* special case for 16bit register-address */
> -		index = (wbuf[2] << 8) | wbuf[0];
> -		value = value + wbuf[1];
> -		break;
> -	default:
> -		deb_xfer("wlen = %x, aborting.", wlen);
> -		return -EINVAL;
> -	}
> -	msleep(1);
> -	return usb_control_msg(d->udev, pipe, req, type,
> -			       value, index, rbuf, rlen, 2000);
> -}
> -
> -/* I2C */
> -static int gl861_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
> -			  int num)
> -{
> -	struct dvb_usb_device *d = i2c_get_adapdata(adap);
> -	int i;
> -
> -
> -	if (num > 2)
> -		return -EINVAL;
> -
> -	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
> -		return -EAGAIN;
> -
> -	for (i = 0; i < num; i++) {
> -		/* write/read request */
> -		if (i + 1 < num && (msg[i + 1].flags & I2C_M_RD)) {
> -			if (gl861_i2c_msg(d, msg[i].addr,
> -					  msg[i].buf, msg[i].len,
> -					  msg[i + 1].buf, msg[i + 1].len) < 0)
> -				break;
> -			i++;
> -		} else
> -			if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf,
> -					  msg[i].len, NULL, 0) < 0)
> -				break;
> -	}
> -
> -	mutex_unlock(&d->i2c_mutex);
> -	return i;
> -}
> -
> -static u32 gl861_i2c_func(struct i2c_adapter *adapter)
> -{
> -	return I2C_FUNC_I2C;
> -}
> -
> -static int friio_ext_ctl(struct dvb_usb_adapter *adap,
> -			 u32 sat_color, int lnb_on)
> -{
> -	int i;
> -	int ret;
> -	struct i2c_msg msg;
> -	u8 *buf;
> -	u32 mask;
> -	u8 lnb = (lnb_on) ? FRIIO_CTL_LNB : 0;
> -
> -	buf = kmalloc(2, GFP_KERNEL);
> -	if (!buf)
> -		return -ENOMEM;
> -
> -	msg.addr = 0x00;
> -	msg.flags = 0;
> -	msg.len = 2;
> -	msg.buf = buf;
> -
> -	buf[0] = 0x00;
> -
> -	/* send 2bit header (&B10) */
> -	buf[1] = lnb | FRIIO_CTL_LED | FRIIO_CTL_STROBE;
> -	ret = gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
> -	buf[1] |= FRIIO_CTL_CLK;
> -	ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
> -
> -	buf[1] = lnb | FRIIO_CTL_STROBE;
> -	ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
> -	buf[1] |= FRIIO_CTL_CLK;
> -	ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
> -
> -	/* send 32bit(satur, R, G, B) data in serial */
> -	mask = 1 << 31;
> -	for (i = 0; i < 32; i++) {
> -		buf[1] = lnb | FRIIO_CTL_STROBE;
> -		if (sat_color & mask)
> -			buf[1] |= FRIIO_CTL_LED;
> -		ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
> -		buf[1] |= FRIIO_CTL_CLK;
> -		ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
> -		mask >>= 1;
> -	}
> -
> -	/* set the strobe off */
> -	buf[1] = lnb;
> -	ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
> -	buf[1] |= FRIIO_CTL_CLK;
> -	ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
> -
> -	kfree(buf);
> -	return (ret == 70);
> -}
> -
> -
> -static int friio_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff);
> -
> -/* TODO: move these init cmds to the FE's init routine? */
> -static u8 streaming_init_cmds[][2] = {
> -	{0x33, 0x08},
> -	{0x37, 0x40},
> -	{0x3A, 0x1F},
> -	{0x3B, 0xFF},
> -	{0x3C, 0x1F},
> -	{0x3D, 0xFF},
> -	{0x38, 0x00},
> -	{0x35, 0x00},
> -	{0x39, 0x00},
> -	{0x36, 0x00},
> -};
> -static int cmdlen = sizeof(streaming_init_cmds) / 2;
> -
> -/*
> - * Command sequence in this init function is a replay
> - *  of the captured USB commands from the Windows proprietary driver.
> - */
> -static int friio_initialize(struct dvb_usb_device *d)
> -{
> -	int ret;
> -	int i;
> -	int retry = 0;
> -	u8 *rbuf, *wbuf;
> -
> -	deb_info("%s called.\n", __func__);
> -
> -	wbuf = kmalloc(3, GFP_KERNEL);
> -	if (!wbuf)
> -		return -ENOMEM;
> -
> -	rbuf = kmalloc(2, GFP_KERNEL);
> -	if (!rbuf) {
> -		kfree(wbuf);
> -		return -ENOMEM;
> -	}
> -
> -	/* use gl861_i2c_msg instead of gl861_i2c_xfer(), */
> -	/* because the i2c device is not set up yet. */
> -	wbuf[0] = 0x11;
> -	wbuf[1] = 0x02;
> -	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
> -	if (ret < 0)
> -		goto error;
> -	msleep(2);
> -
> -	wbuf[0] = 0x11;
> -	wbuf[1] = 0x00;
> -	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
> -	if (ret < 0)
> -		goto error;
> -	msleep(1);
> -
> -	/* following msgs should be in the FE's init code? */
> -	/* cmd sequence to identify the device type? (friio black/white) */
> -	wbuf[0] = 0x03;
> -	wbuf[1] = 0x80;
> -	/* can't use gl861_i2c_cmd, as the register-addr is 16bit(0x0100) */
> -	ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
> -			      GL861_REQ_I2C_DATA_CTRL_WRITE, GL861_WRITE,
> -			      0x1200, 0x0100, wbuf, 2, 2000);
> -	if (ret < 0)
> -		goto error;
> -
> -	msleep(2);
> -	wbuf[0] = 0x00;
> -	wbuf[2] = 0x01;		/* reg.0x0100 */
> -	wbuf[1] = 0x00;
> -	ret = gl861_i2c_msg(d, 0x12 >> 1, wbuf, 3, rbuf, 2);
> -	/* my Friio White returns 0xffff. */
> -	if (ret < 0 || rbuf[0] != 0xff || rbuf[1] != 0xff)
> -		goto error;
> -
> -	msleep(2);
> -	wbuf[0] = 0x03;
> -	wbuf[1] = 0x80;
> -	ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
> -			      GL861_REQ_I2C_DATA_CTRL_WRITE, GL861_WRITE,
> -			      0x9000, 0x0100, wbuf, 2, 2000);
> -	if (ret < 0)
> -		goto error;
> -
> -	msleep(2);
> -	wbuf[0] = 0x00;
> -	wbuf[2] = 0x01;		/* reg.0x0100 */
> -	wbuf[1] = 0x00;
> -	ret = gl861_i2c_msg(d, 0x90 >> 1, wbuf, 3, rbuf, 2);
> -	/* my Friio White returns 0xffff again. */
> -	if (ret < 0 || rbuf[0] != 0xff || rbuf[1] != 0xff)
> -		goto error;
> -
> -	msleep(1);
> -
> -restart:
> -	/* ============ start DEMOD init cmds ================== */
> -	/* read PLL status to clear the POR bit */
> -	wbuf[0] = JDVBT90502_2ND_I2C_REG;
> -	wbuf[1] = (FRIIO_PLL_ADDR << 1) + 1;	/* +1 for reading */
> -	ret = gl861_i2c_msg(d, FRIIO_DEMOD_ADDR, wbuf, 2, NULL, 0);
> -	if (ret < 0)
> -		goto error;
> -
> -	msleep(5);
> -	/* note: DEMODULATOR has 16bit register-address. */
> -	wbuf[0] = 0x00;
> -	wbuf[2] = 0x01;		/* reg addr: 0x0100 */
> -	wbuf[1] = 0x00;		/* val: not used */
> -	ret = gl861_i2c_msg(d, FRIIO_DEMOD_ADDR, wbuf, 3, rbuf, 1);
> -	if (ret < 0)
> -		goto error;
> -/*
> -	msleep(1);
> -	wbuf[0] = 0x80;
> -	wbuf[1] = 0x00;
> -	ret = gl861_i2c_msg(d, FRIIO_DEMOD_ADDR, wbuf, 2, rbuf, 1);
> -	if (ret < 0)
> -		goto error;
> - */
> -	if (rbuf[0] & 0x80) {	/* still in PowerOnReset state? */
> -		if (++retry > 3) {
> -			deb_info("failed to get the correct FE demod status:0x%02x\n",
> -				 rbuf[0]);
> -			goto error;
> -		}
> -		msleep(100);
> -		goto restart;
> -	}
> -
> -	/* TODO: check return value in rbuf */
> -	/* =========== end DEMOD init cmds ===================== */
> -	msleep(1);
> -
> -	wbuf[0] = 0x30;
> -	wbuf[1] = 0x04;
> -	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
> -	if (ret < 0)
> -		goto error;
> -
> -	msleep(2);
> -	/* following 2 cmds unnecessary? */
> -	wbuf[0] = 0x00;
> -	wbuf[1] = 0x01;
> -	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
> -	if (ret < 0)
> -		goto error;
> -
> -	wbuf[0] = 0x06;
> -	wbuf[1] = 0x0F;
> -	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
> -	if (ret < 0)
> -		goto error;
> -
> -	/* some streaming ctl cmds (maybe) */
> -	msleep(10);
> -	for (i = 0; i < cmdlen; i++) {
> -		ret = gl861_i2c_msg(d, 0x00, streaming_init_cmds[i], 2,
> -				    NULL, 0);
> -		if (ret < 0)
> -			goto error;
> -		msleep(1);
> -	}
> -	msleep(20);
> -
> -	/* change the LED color etc. */
> -	ret = friio_streaming_ctrl(&d->adapter[0], 0);
> -	if (ret < 0)
> -		goto error;
> -
> -	return 0;
> -
> -error:
> -	kfree(wbuf);
> -	kfree(rbuf);
> -	deb_info("%s:ret == %d\n", __func__, ret);
> -	return -EIO;
> -}
> -
> -/* Callbacks for DVB USB */
> -
> -static int friio_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
> -{
> -	int ret;
> -
> -	deb_info("%s called.(%d)\n", __func__, onoff);
> -
> -	/* set the LED color and saturation (and LNB on) */
> -	if (onoff)
> -		ret = friio_ext_ctl(adap, 0x6400ff64, 1);
> -	else
> -		ret = friio_ext_ctl(adap, 0x96ff00ff, 1);
> -
> -	if (ret != 1) {
> -		deb_info("%s failed to send cmdx. ret==%d\n", __func__, ret);
> -		return -EREMOTEIO;
> -	}
> -	return 0;
> -}
> -
> -static int friio_frontend_attach(struct dvb_usb_adapter *adap)
> -{
> -	if (friio_initialize(adap->dev) < 0)
> -		return -EIO;
> -
> -	adap->fe_adap[0].fe = jdvbt90502_attach(adap->dev);
> -	if (adap->fe_adap[0].fe == NULL)
> -		return -EIO;
> -
> -	return 0;
> -}
> -
> -/* DVB USB Driver stuff */
> -static struct dvb_usb_device_properties friio_properties;
> -
> -static int friio_probe(struct usb_interface *intf,
> -		       const struct usb_device_id *id)
> -{
> -	struct dvb_usb_device *d;
> -	struct usb_host_interface *alt;
> -	int ret;
> -
> -	if (intf->num_altsetting < GL861_ALTSETTING_COUNT)
> -		return -ENODEV;
> -
> -	alt = usb_altnum_to_altsetting(intf, FRIIO_BULK_ALTSETTING);
> -	if (alt == NULL) {
> -		deb_rc("not alt found!\n");
> -		return -ENODEV;
> -	}
> -	ret = usb_set_interface(interface_to_usbdev(intf),
> -				alt->desc.bInterfaceNumber,
> -				alt->desc.bAlternateSetting);
> -	if (ret != 0) {
> -		deb_rc("failed to set alt-setting!\n");
> -		return ret;
> -	}
> -
> -	ret = dvb_usb_device_init(intf, &friio_properties,
> -				  THIS_MODULE, &d, adapter_nr);
> -	if (ret == 0)
> -		friio_streaming_ctrl(&d->adapter[0], 1);
> -
> -	return ret;
> -}
> -
> -
> -struct jdvbt90502_config friio_fe_config = {
> -	.demod_address = FRIIO_DEMOD_ADDR,
> -	.pll_address = FRIIO_PLL_ADDR,
> -};
> -
> -static struct i2c_algorithm gl861_i2c_algo = {
> -	.master_xfer   = gl861_i2c_xfer,
> -	.functionality = gl861_i2c_func,
> -};
> -
> -static struct usb_device_id friio_table[] = {
> -	{ USB_DEVICE(USB_VID_774, USB_PID_FRIIO_WHITE) },
> -	{ }		/* Terminating entry */
> -};
> -MODULE_DEVICE_TABLE(usb, friio_table);
> -
> -
> -static struct dvb_usb_device_properties friio_properties = {
> -	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
> -	.usb_ctrl = DEVICE_SPECIFIC,
> -
> -	.size_of_priv = 0,
> -
> -	.num_adapters = 1,
> -	.adapter = {
> -		/* caps:0 =>  no pid filter, 188B TS packet */
> -		/* GL861 has a HW pid filter, but no info available. */
> -		{
> -		.num_frontends = 1,
> -		.fe = {{
> -			.caps  = 0,
> -
> -			.frontend_attach  = friio_frontend_attach,
> -			.streaming_ctrl = friio_streaming_ctrl,
> -
> -			.stream = {
> -				.type = USB_BULK,
> -				/* count <= MAX_NO_URBS_FOR_DATA_STREAM(10) */
> -				.count = 8,
> -				.endpoint = 0x01,
> -				.u = {
> -					/* GL861 has 6KB buf inside */
> -					.bulk = {
> -						.buffersize = 16384,
> -					}
> -				}
> -			},
> -		}},
> -		}
> -	},
> -	.i2c_algo = &gl861_i2c_algo,
> -
> -	.num_device_descs = 1,
> -	.devices = {
> -		{
> -			.name = "774 Friio ISDB-T USB2.0",
> -			.cold_ids = { NULL },
> -			.warm_ids = { &friio_table[0], NULL },
> -		},
> -	}
> -};
> -
> -static struct usb_driver friio_driver = {
> -	.name		= "dvb_usb_friio",
> -	.probe		= friio_probe,
> -	.disconnect	= dvb_usb_device_exit,
> -	.id_table	= friio_table,
> -};
> -
> -module_usb_driver(friio_driver);
> -
> -MODULE_AUTHOR("Akihiro Tsukada <tskd2@yahoo.co.jp>");
> -MODULE_DESCRIPTION("Driver for Friio ISDB-T USB2.0 Receiver");
> -MODULE_VERSION("0.2");
> -MODULE_LICENSE("GPL");
> diff --git a/drivers/media/usb/dvb-usb/friio.h b/drivers/media/usb/dvb-usb/friio.h
> deleted file mode 100644
> index 0f461ca10cb..00000000000
> --- a/drivers/media/usb/dvb-usb/friio.h
> +++ /dev/null
> @@ -1,99 +0,0 @@
> -/* DVB USB compliant Linux driver for the Friio USB2.0 ISDB-T receiver.
> - *
> - * Copyright (C) 2009 Akihiro Tsukada <tskd2@yahoo.co.jp>
> - *
> - * This module is based off the the gl861 and vp702x modules.
> - *
> - * 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, version 2.
> - *
> - * see Documentation/dvb/README.dvb-usb for more information
> - */
> -#ifndef _DVB_USB_FRIIO_H_
> -#define _DVB_USB_FRIIO_H_
> -
> -/**
> - *      Friio Components
> - *       USB hub:                                AU4254
> - *         USB controller(+ TS dmx & streaming): GL861
> - *         Frontend:                             comtech JDVBT-90502
> - *             (tuner PLL:                       tua6034, I2C addr:(0xC0 >> 1))
> - *             (OFDM demodulator:                TC90502, I2C addr:(0x30 >> 1))
> - *         LED x3 (+LNB) control:                PIC 16F676
> - *         EEPROM:                               24C08
> - *
> - *        (USB smart card reader:                AU9522)
> - *
> - */
> -
> -#define DVB_USB_LOG_PREFIX "friio"
> -#include "dvb-usb.h"
> -
> -extern int dvb_usb_friio_debug;
> -#define deb_info(args...) dprintk(dvb_usb_friio_debug, 0x01, args)
> -#define deb_xfer(args...) dprintk(dvb_usb_friio_debug, 0x02, args)
> -#define deb_rc(args...)   dprintk(dvb_usb_friio_debug, 0x04, args)
> -#define deb_fe(args...)   dprintk(dvb_usb_friio_debug, 0x08, args)
> -
> -/* Vendor requests */
> -#define GL861_WRITE		0x40
> -#define GL861_READ		0xc0
> -
> -/* command bytes */
> -#define GL861_REQ_I2C_WRITE	0x01
> -#define GL861_REQ_I2C_READ	0x02
> -/* For control msg with data argument */
> -/* Used for accessing the PLL on the secondary I2C bus of FE via GL861 */
> -#define GL861_REQ_I2C_DATA_CTRL_WRITE	0x03
> -
> -#define GL861_ALTSETTING_COUNT	2
> -#define FRIIO_BULK_ALTSETTING	0
> -#define FRIIO_ISOC_ALTSETTING	1
> -
> -/* LED & LNB control via PIC. */
> -/* basically, it's serial control with clock and strobe. */
> -/* write the below 4bit control data to the reg 0x00 at the I2C addr 0x00 */
> -/* when controlling the LEDs, 32bit(saturation, R, G, B) is sent on the bit3*/
> -#define FRIIO_CTL_LNB (1 << 0)
> -#define FRIIO_CTL_STROBE (1 << 1)
> -#define FRIIO_CTL_CLK (1 << 2)
> -#define FRIIO_CTL_LED (1 << 3)
> -
> -/* Front End related */
> -
> -#define FRIIO_DEMOD_ADDR  (0x30 >> 1)
> -#define FRIIO_PLL_ADDR  (0xC0 >> 1)
> -
> -#define JDVBT90502_PLL_CLK	4000000
> -#define JDVBT90502_PLL_DIVIDER	28
> -
> -#define JDVBT90502_2ND_I2C_REG 0xFE
> -
> -/* byte index for pll i2c command data structure*/
> -/* see datasheet for tua6034 */
> -#define DEMOD_REDIRECT_REG 0
> -#define ADDRESS_BYTE       1
> -#define DIVIDER_BYTE1      2
> -#define DIVIDER_BYTE2      3
> -#define CONTROL_BYTE       4
> -#define BANDSWITCH_BYTE    5
> -#define AGC_CTRL_BYTE      5
> -#define PLL_CMD_LEN        6
> -
> -/* bit masks for PLL STATUS response */
> -#define PLL_STATUS_POR_MODE   0x80 /* 1: Power on Reset (test) Mode */
> -#define PLL_STATUS_LOCKED     0x40 /* 1: locked */
> -#define PLL_STATUS_AGC_ACTIVE 0x08 /* 1:active */
> -#define PLL_STATUS_TESTMODE   0x07 /* digital output level (5 level) */
> -  /* 0.15Vcc step   0x00: < 0.15Vcc, ..., 0x04: >= 0.6Vcc (<= 1Vcc) */
> -
> -
> -struct jdvbt90502_config {
> -	u8 demod_address; /* i2c addr for demodulator IC */
> -	u8 pll_address;   /* PLL addr on the secondary i2c*/
> -};
> -extern struct jdvbt90502_config friio_fe_config;
> -
> -extern struct dvb_frontend *jdvbt90502_attach(struct dvb_usb_device *d);
> -#endif



Thanks,
Mauro

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v5 4/5] dvb-usb-v2/gl861: use usleep_range() for short delay
  2018-04-08 17:21 ` [PATCH v5 4/5] dvb-usb-v2/gl861: use usleep_range() for short delay tskd08
@ 2018-05-05 11:14   ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 11+ messages in thread
From: Mauro Carvalho Chehab @ 2018-05-05 11:14 UTC (permalink / raw)
  To: tskd08; +Cc: linux-media, mchehab, crope

Em Mon,  9 Apr 2018 02:21:37 +0900
tskd08@gmail.com escreveu:

> From: Akihiro Tsukada <tskd08@gmail.com>
> 
> As the kernel doc "timers-howto.txt" reads,
> short delay with msleep() can take much longer.
> In a case of raspbery-pi platform where CONFIG_HZ_100 was set,
> it actually affected the init of Friio devices
> since it issues lots of i2c transactions with short delay.
> 
> Signed-off-by: Akihiro Tsukada <tskd08@gmail.com>
> ---
> Changes since v4:
> - none
> 
>  drivers/media/usb/dvb-usb-v2/gl861.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/media/usb/dvb-usb-v2/gl861.c b/drivers/media/usb/dvb-usb-v2/gl861.c
> index ecff0062bfb..cdd7bfcb883 100644
> --- a/drivers/media/usb/dvb-usb-v2/gl861.c
> +++ b/drivers/media/usb/dvb-usb-v2/gl861.c
> @@ -45,7 +45,7 @@ static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
>  		return -EINVAL;
>  	}
>  
> -	msleep(1); /* avoid I2C errors */
> +	usleep_range(1000, 2000); /* avoid I2C errors */

Actually, this change is puntual and applies even without patch 3/5.

So, I'll apply this one too.

So, next time, just patches 3 and 5 will be needed.


>  
>  	return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), req, type,
>  			       value, index, rbuf, rlen, 2000);



Thanks,
Mauro

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v5 5/5] dvb-usb-v2/gl861: ensure  USB message buffers DMA'able
  2018-04-08 17:21 ` [PATCH v5 5/5] dvb-usb-v2/gl861: ensure USB message buffers DMA'able tskd08
@ 2018-05-05 11:17   ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 11+ messages in thread
From: Mauro Carvalho Chehab @ 2018-05-05 11:17 UTC (permalink / raw)
  To: tskd08; +Cc: linux-media, mchehab, crope

Em Mon,  9 Apr 2018 02:21:38 +0900
tskd08@gmail.com escreveu:

> From: Akihiro Tsukada <tskd08@gmail.com>
> 
> i2c message buf might be on stack.

That patch also applied without changes. So, just patch 3/5 was not applied.

> 
> Signed-off-by: Akihiro Tsukada <tskd08@gmail.com>
> ---
> Changes since v4:
> - none
> 
>  drivers/media/usb/dvb-usb-v2/gl861.c | 20 +++++++++++++++++---
>  1 file changed, 17 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/media/usb/dvb-usb-v2/gl861.c b/drivers/media/usb/dvb-usb-v2/gl861.c
> index cdd7bfcb883..47b614da807 100644
> --- a/drivers/media/usb/dvb-usb-v2/gl861.c
> +++ b/drivers/media/usb/dvb-usb-v2/gl861.c
> @@ -22,6 +22,8 @@ static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
>  	u16 value = addr << (8 + 1);
>  	int wo = (rbuf == NULL || rlen == 0); /* write-only */
>  	u8 req, type;
> +	u8 *buf;
> +	int ret;
>  
>  	if (wo) {
>  		req = GL861_REQ_I2C_WRITE;
> @@ -44,11 +46,23 @@ static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
>  				KBUILD_MODNAME, wlen);
>  		return -EINVAL;
>  	}
> -
> +	buf = NULL;
> +	if (rlen > 0) {
> +		buf = kmalloc(rlen, GFP_KERNEL);
> +		if (!buf)
> +			return -ENOMEM;
> +	}
>  	usleep_range(1000, 2000); /* avoid I2C errors */
>  
> -	return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), req, type,
> -			       value, index, rbuf, rlen, 2000);
> +	ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), req, type,
> +			      value, index, buf, rlen, 2000);
> +	if (rlen > 0) {
> +		if (ret > 0)
> +			memcpy(rbuf, buf, rlen);
> +		kfree(buf);
> +	}
> +
> +	return ret;
>  }
>  
>  /* Friio specific I2C read/write */



Thanks,
Mauro

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v6 3/5] dvb-usb/friio, dvb-usb-v2/gl861: decompose friio and merge with gl861
  2018-05-05 11:12   ` Mauro Carvalho Chehab
@ 2018-05-13 18:13     ` Akihiro TSUKADA
  2018-05-13 19:25       ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 11+ messages in thread
From: Akihiro TSUKADA @ 2018-05-13 18:13 UTC (permalink / raw)
  To: Mauro Carvalho Chehab; +Cc: linux-media, mchehab, crope

Hi,
thanks for the review.

>> +gl861_i2c_rawwrite(struct dvb_usb_device *d, u8 addr, u8 *wbuf, u16 wlen)>> +{>> +	u8 *buf;>> +	int ret;>> +>> +	buf = kmalloc(wlen, GFP_KERNEL);>> +	if (!buf)>> +		return -ENOMEM;>> +>> +	usleep_range(1000, 2000); /* avoid I2C errors */> > I guess this is probably also at the original code, but it seems really> weird to sleep here just after kmalloc().> > I would move any need for sleeps to the i2c xfer function, where it> makes clearer why it is needed and where. Same applies to other> usleep_range() calls at the functions below.
those sleeps are for placing time gap between consecutive i2c transactions,
but I agree that they should be moved to the i2c_xfer loop.
I'll fix them in the next version.

>> +/*
>> + * In Friio,
>> + * I2C commnucations to the tuner are relay'ed via the demod (via the bridge),
>> + * so its encapsulation to USB message is different from the one to the demod.
> 
> This is quite common. I guess the rationale of using the demod's I2C mux
> is to avoid noise at the tuner when there are I2C traffic that aren't related
> to it.
> 
> You should probably implement it via I2C_MUX support.

I know that the i2c bus structure is common,
but as I wrote to Antti before,
i2c transactions to the tuner use the different USB transactions with
different 'request' value from the one used in the other demod transactions.

Here is the packet log example (I posted to linux-media before):
"Re: [PATCH v4] dvb-usb/friio, dvb-usb-v2/gl861: decompose friio and merge with gl861"
Message ID: <f047a680-436b-bf40-ae0a-68279366b668@gmail.com>
Sent on: Sun, 1 Apr 2018 00:30:49 +0900

I still do not understand how this can be implemented with I2C_MUX,
or in the demod/tuner drivers.
i2c to the tuner does not need gating/arbitration/locking,
only needs to access via the demod reg,
which is already implemented in the adapter by the demod,
but it must be sent in the distinct USB transaction with its own 'request' value.

>> +/* init/config of Friio demod chip(?) */
>> +static int friio_reset(struct dvb_usb_device *d)
>> +{
>> +	int i, ret;
>> +	u8 wbuf[2], rbuf[2];
>> +
>> +	static const u8 friio_init_cmds[][2] = {
>> +		{0x33, 0x08}, {0x37, 0x40}, {0x3a, 0x1f}, {0x3b, 0xff},
>> +		{0x3c, 0x1f}, {0x3d, 0xff}, {0x38, 0x00}, {0x35, 0x00},
>> +		{0x39, 0x00}, {0x36, 0x00},
>> +	};
>> +
>> +	ret = usb_set_interface(d->udev, 0, 0);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	wbuf[0] = 0x11;
>> +	wbuf[1] = 0x02;
>> +	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
>> +	if (ret < 0)
>> +		return ret;
>> +	usleep_range(2000, 3000);
>> +
>> +	wbuf[0] = 0x11;
>> +	wbuf[1] = 0x00;
>> +	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
>> +	if (ret < 0)
>> +		return ret;
>> +	usleep_range(1000, 2000);
> 
> Hmm... you had already usleeps() all over I2C xfer routines. Why adding
> extra sleeps here?

Those sleeps were added to (roughly) simulate the timing
seen in the packet capture logs on a Windows box.
They certainly include the time for application processing,
but may include the necessary wait time after each command/i2c-transaction,
so they are kept for safety.

> Also, why isn't it calling i2c_transfer() instead of gl861_i2c_msg()?
> Same applies to other similar calls.

Because friio_reset can be called in the following trace:
friio_reset
friio_power_ctrl
d->props->power_ctrl
dvb_usbv2_device_power_ctrl
dvb_usbv2_init

and in dvb_usbv2_init, dvb_usbv2_device_power_ctrl is called
BEFORE i2c adapter initialization (dvb_usbv2_i2c_init).

>> +static int friio_tuner_detach(struct dvb_usb_adapter *adap)
>> +{
>> +	struct friio_priv *priv;
>> +
>> +	priv = adap_to_priv(adap);
>> +#ifndef CONFIG_MEDIA_ATTACH
>> +	/* Note:
>> +	 * When CONFIG_MEDIA_ATTACH is defined,
>> +	 * the tuner module is already "put" by the following call trace:
>> +	 *
>> +	 * symbol_put_addr(fe->ops.tuner_ops.release)
>> +	 * dvb_frontend_invoke_release(fe, fe->ops.tuner_ops.release)
>> +	 * dvb_frontend_detach(fe)
>> +	 * dvb_usbv2_adapter_frontend_exit(adap)
>> +	 * dvb_usbv2_adapter_exit(d)
>> +	 * dvb_usbv2_exit(d)
>> +	 * dvb_usbv2_disconnect(intf)
>> +	 *
>> +	 * Since the tuner driver of Friio (dvb-pll) has .release defined,
>> +	 * dvb_module_release() should be skipped if CONFIG_MEDIA_ATTACH,
>> +	 * to avoid double-putting the module.
>> +	 * Even without dvb_module_release(),
>> +	 * the tuner i2c device is automatically unregistered
>> +	 * when its i2c adapter is unregistered with the demod i2c device.
>> +	 *
>> +	 * The same "double-putting" can happen to the demod module as well,
>> +	 * but tc90522 does not define any _invoke_release()'ed functions,
>> +	 * thus Friio is not affected.
>> +	 */
>> +	dvb_module_release(priv->i2c_client_tuner);
>> +#endif
> 
> This looks really weird to me... why only at this driver we need this?
> If we have some issues at the DVB core - or at dvb-usb-v2, the fix should
> be there, and not here.

dvb-usb-v2 handles attach/detach of frontend/tuner driver modules
on behalf of each bridge driver.

While sub drivers are attached via d->props->{frontend, tuner}_attach,
they are implicitly 'dvb_detach'ed in dvb_frontend_detach() on disconnect,
not detached explicitly in d->props->{frontend, tuner}_detach().
But i2c drivers need to be 'dvb_module_release'ed in those *_detach(),
so any i2c drivers that define any 'implicitly detached' ops function
would be affected by this double-put problem.
(I suspect that even legacy dvb_attached drivers are also affected
if they define both ops{.detach, .release, ...} functions,
but there seems to be no such drivers currently.)

Fix in dvb-core/dvb-usb-v2 would be too complicated
for this (transient?) problem, since it will get unnecessary
once all dvb_attach's are replaced and removed.

so I am going to fix it in the tuner driver (dvb_pll) instead,
like af9013 or ts2020 drivers,
by clearing tuner_ops.release and moving its code to i2c .remove().

regards,
Akihiro

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v6 3/5] dvb-usb/friio, dvb-usb-v2/gl861: decompose friio and merge with gl861
  2018-05-13 18:13     ` Akihiro TSUKADA
@ 2018-05-13 19:25       ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 11+ messages in thread
From: Mauro Carvalho Chehab @ 2018-05-13 19:25 UTC (permalink / raw)
  To: Akihiro TSUKADA; +Cc: linux-media, mchehab, crope

Em Mon, 14 May 2018 03:13:44 +0900
Akihiro TSUKADA <tskd08@gmail.com> escreveu:

> Hi,
> thanks for the review.
> 
> >> +gl861_i2c_rawwrite(struct dvb_usb_device *d, u8 addr, u8 *wbuf, u16 wlen)>> +{>> +	u8 *buf;>> +	int ret;>> +>> +	buf = kmalloc(wlen, GFP_KERNEL);>> +	if (!buf)>> +		return -ENOMEM;>> +>> +	usleep_range(1000, 2000); /* avoid I2C errors */> > I guess this is probably also at the original code, but it seems really> weird to sleep here just after kmalloc().> > I would move any need for sleeps to the i2c xfer function, where it> makes clearer why it is needed and where. Same applies to other> usleep_range() calls at the functions below.  
> those sleeps are for placing time gap between consecutive i2c transactions,
> but I agree that they should be moved to the i2c_xfer loop.
> I'll fix them in the next version.

Ok, thanks!

> 
> >> +/*
> >> + * In Friio,
> >> + * I2C commnucations to the tuner are relay'ed via the demod (via the bridge),
> >> + * so its encapsulation to USB message is different from the one to the demod.  
> > 
> > This is quite common. I guess the rationale of using the demod's I2C mux
> > is to avoid noise at the tuner when there are I2C traffic that aren't related
> > to it.
> > 
> > You should probably implement it via I2C_MUX support.  
> 
> I know that the i2c bus structure is common,
> but as I wrote to Antti before,
> i2c transactions to the tuner use the different USB transactions with
> different 'request' value from the one used in the other demod transactions.
> 
> Here is the packet log example (I posted to linux-media before):
> "Re: [PATCH v4] dvb-usb/friio, dvb-usb-v2/gl861: decompose friio and merge with gl861"
> Message ID: <f047a680-436b-bf40-ae0a-68279366b668@gmail.com>
> Sent on: Sun, 1 Apr 2018 00:30:49 +0900
> 
> I still do not understand how this can be implemented with I2C_MUX,
> or in the demod/tuner drivers.
> i2c to the tuner does not need gating/arbitration/locking,
> only needs to access via the demod reg,
> which is already implemented in the adapter by the demod,
> but it must be sent in the distinct USB transaction with its own 'request' value.

So what? Take a look, for example, at em28xx implementation:
	drivers/media/usb/em28xx/em28xx-i2c.c

It has different functions for bus A (with is common on all em28xx
chipsets) and for bus B (with is present only on newer chips).

If you see at I2C xfer implementation, you'll see that the logic
there handles the bus:

static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
			   struct i2c_msg msgs[], int num)
{
...
	/* Switch I2C bus if needed */
	if (bus != dev->cur_i2c_bus &&
	    i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) {
		if (bus == 1)
			reg = EM2874_I2C_SECONDARY_BUS_SELECT;
		else
			reg = 0;
		em28xx_write_reg_bits(dev, EM28XX_R06_I2C_CLK, reg,
				      EM2874_I2C_SECONDARY_BUS_SELECT);
		dev->cur_i2c_bus = bus;
	}
...

		} else if (msgs[i].flags & I2C_M_RD) {
			/* read bytes */
			rc = i2c_recv_bytes(i2c_bus, msgs[i]);

There, not only the I2C bus need to be known by the routines,
but also switching from one bus to the other requires a register
write, depending on the device type (as can be seen when the I2C
buses are reigstered, at em28xx_cards.c:

	/* register i2c bus 0 */
	if (dev->board.is_em2800)
		retval = em28xx_i2c_register(dev, 0, EM28XX_I2C_ALGO_EM2800);
	else
		retval = em28xx_i2c_register(dev, 0, EM28XX_I2C_ALGO_EM28XX);
	if (retval < 0) {
		dev_err(&dev->intf->dev,
			"%s: em28xx_i2c_register bus 0 - error [%d]!\n",
		       __func__, retval);
		return retval;
	}

	/* register i2c bus 1 */
	if (dev->def_i2c_bus) {
		if (dev->is_em25xx)
			retval = em28xx_i2c_register(dev, 1,
						     EM28XX_I2C_ALGO_EM25XX_BUS_B);
		else
			retval = em28xx_i2c_register(dev, 1,
						     EM28XX_I2C_ALGO_EM28XX);
		if (retval < 0) {
			dev_err(&dev->intf->dev,
				"%s: em28xx_i2c_register bus 1 - error [%d]!\n",
				__func__, retval);

			em28xx_i2c_unregister(dev, 0);

			return retval;
		}
	}

> 
> >> +/* init/config of Friio demod chip(?) */
> >> +static int friio_reset(struct dvb_usb_device *d)
> >> +{
> >> +	int i, ret;
> >> +	u8 wbuf[2], rbuf[2];
> >> +
> >> +	static const u8 friio_init_cmds[][2] = {
> >> +		{0x33, 0x08}, {0x37, 0x40}, {0x3a, 0x1f}, {0x3b, 0xff},
> >> +		{0x3c, 0x1f}, {0x3d, 0xff}, {0x38, 0x00}, {0x35, 0x00},
> >> +		{0x39, 0x00}, {0x36, 0x00},
> >> +	};
> >> +
> >> +	ret = usb_set_interface(d->udev, 0, 0);
> >> +	if (ret < 0)
> >> +		return ret;
> >> +
> >> +	wbuf[0] = 0x11;
> >> +	wbuf[1] = 0x02;
> >> +	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
> >> +	if (ret < 0)
> >> +		return ret;
> >> +	usleep_range(2000, 3000);
> >> +
> >> +	wbuf[0] = 0x11;
> >> +	wbuf[1] = 0x00;
> >> +	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
> >> +	if (ret < 0)
> >> +		return ret;
> >> +	usleep_range(1000, 2000);  
> > 
> > Hmm... you had already usleeps() all over I2C xfer routines. Why adding
> > extra sleeps here?  
> 
> Those sleeps were added to (roughly) simulate the timing
> seen in the packet capture logs on a Windows box.
> They certainly include the time for application processing,
> but may include the necessary wait time after each command/i2c-transaction,
> so they are kept for safety.

Yes, but you have sleeps there and also at the I2C register setting
routines. Having both seems weird.

> 
> > Also, why isn't it calling i2c_transfer() instead of gl861_i2c_msg()?
> > Same applies to other similar calls.  
> 
> Because friio_reset can be called in the following trace:
> friio_reset
> friio_power_ctrl
> d->props->power_ctrl
> dvb_usbv2_device_power_ctrl
> dvb_usbv2_init
> 
> and in dvb_usbv2_init, dvb_usbv2_device_power_ctrl is called
> BEFORE i2c adapter initialization (dvb_usbv2_i2c_init).

Ah, I see. Please document it then.

> 
> >> +static int friio_tuner_detach(struct dvb_usb_adapter *adap)
> >> +{
> >> +	struct friio_priv *priv;
> >> +
> >> +	priv = adap_to_priv(adap);
> >> +#ifndef CONFIG_MEDIA_ATTACH
> >> +	/* Note:
> >> +	 * When CONFIG_MEDIA_ATTACH is defined,
> >> +	 * the tuner module is already "put" by the following call trace:
> >> +	 *
> >> +	 * symbol_put_addr(fe->ops.tuner_ops.release)
> >> +	 * dvb_frontend_invoke_release(fe, fe->ops.tuner_ops.release)
> >> +	 * dvb_frontend_detach(fe)
> >> +	 * dvb_usbv2_adapter_frontend_exit(adap)
> >> +	 * dvb_usbv2_adapter_exit(d)
> >> +	 * dvb_usbv2_exit(d)
> >> +	 * dvb_usbv2_disconnect(intf)
> >> +	 *
> >> +	 * Since the tuner driver of Friio (dvb-pll) has .release defined,
> >> +	 * dvb_module_release() should be skipped if CONFIG_MEDIA_ATTACH,
> >> +	 * to avoid double-putting the module.
> >> +	 * Even without dvb_module_release(),
> >> +	 * the tuner i2c device is automatically unregistered
> >> +	 * when its i2c adapter is unregistered with the demod i2c device.
> >> +	 *
> >> +	 * The same "double-putting" can happen to the demod module as well,
> >> +	 * but tc90522 does not define any _invoke_release()'ed functions,
> >> +	 * thus Friio is not affected.
> >> +	 */
> >> +	dvb_module_release(priv->i2c_client_tuner);
> >> +#endif  
> > 
> > This looks really weird to me... why only at this driver we need this?
> > If we have some issues at the DVB core - or at dvb-usb-v2, the fix should
> > be there, and not here.  
> 
> dvb-usb-v2 handles attach/detach of frontend/tuner driver modules
> on behalf of each bridge driver.
> 
> While sub drivers are attached via d->props->{frontend, tuner}_attach,
> they are implicitly 'dvb_detach'ed in dvb_frontend_detach() on disconnect,
> not detached explicitly in d->props->{frontend, tuner}_detach().
> But i2c drivers need to be 'dvb_module_release'ed in those *_detach(),
> so any i2c drivers that define any 'implicitly detached' ops function
> would be affected by this double-put problem.
> (I suspect that even legacy dvb_attached drivers are also affected
> if they define both ops{.detach, .release, ...} functions,
> but there seems to be no such drivers currently.)
> 
> Fix in dvb-core/dvb-usb-v2 would be too complicated
> for this (transient?) problem, since it will get unnecessary
> once all dvb_attach's are replaced and removed.
> 
> so I am going to fix it in the tuner driver (dvb_pll) instead,
> like af9013 or ts2020 drivers,
> by clearing tuner_ops.release and moving its code to i2c .remove().

Ok.

> 
> regards,
> Akihiro



Thanks,
Mauro

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2018-05-13 19:25 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-04-08 17:21 [PATCH v5 0/5] dvb-usb-friio: decompose friio and merge with gl861 tskd08
2018-04-08 17:21 ` [PATCH v5 1/5] dvb-frontends/dvb-pll: add i2c driver support tskd08
2018-04-08 17:21 ` [PATCH v5 2/5] dvb-frontends/dvb-pll: add tua6034 ISDB-T tuner used in Friio tskd08
2018-04-08 17:21 ` [PATCH v6 3/5] dvb-usb/friio, dvb-usb-v2/gl861: decompose friio and merge with gl861 tskd08
2018-05-05 11:12   ` Mauro Carvalho Chehab
2018-05-13 18:13     ` Akihiro TSUKADA
2018-05-13 19:25       ` Mauro Carvalho Chehab
2018-04-08 17:21 ` [PATCH v5 4/5] dvb-usb-v2/gl861: use usleep_range() for short delay tskd08
2018-05-05 11:14   ` Mauro Carvalho Chehab
2018-04-08 17:21 ` [PATCH v5 5/5] dvb-usb-v2/gl861: ensure USB message buffers DMA'able tskd08
2018-05-05 11:17   ` Mauro Carvalho Chehab

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.