linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [media 0/6] DVB driver for Earthsoft PT3, PLEX PX-Q3PE ISDB-S/T PCIE cards & PX-BCUD ISDB-S USB dongle
@ 2016-04-04 17:03 info
  2016-04-04 17:04 ` [media 1/6] Raise adapter number limit info
                   ` (5 more replies)
  0 siblings, 6 replies; 10+ messages in thread
From: info @ 2016-04-04 17:03 UTC (permalink / raw)
  To: linux-media
  Cc: Буди
	Романто,
	AreMa Inc, linux-kernel, crope, m.chehab, mchehab, hdegoede,
	laurent.pinchart, mkrufky, sylvester.nawrocki, g.liakhovetski,
	peter.senna

From: Буди Романто, AreMa Inc <knightrider@are.ma>


DVB driver for Earthsoft PT3, PLEX PX-Q3PE ISDB-S/T PCIE cards & PX-BCUD ISDB-S USB dongle
==========================================================================================

Status: stable

Features:
1. in addition to the real frequency:
        ISDB-S : freq. channel ID
        ISDB-T : freq# (I/O# +128), ch#, ch# +64 for CATV
2. in addition to TSID:
        ISDB-S : slot#

Supported Cards & Main components:
A. EarthSoft PT3:
1. Altera       EP4CGX15BF14C8N : customized FPGA PCI bridge
2. Toshiba      TC90522XBG      : quad demodulator (2ch OFDM + 2ch 8PSK)
3. Sharp        VA4M6JC2103     : contains 2 ISDB-S + 2 ISDB-T tuners
        ISDB-S : Sharp QM1D1C0042 RF-IC, chip ver. 0x48
        ISDB-T : MaxLinear CMOS Hybrid TV MxL301RF

B. PLEX PX-Q3PE:
1. ASICEN       ASV5220         : PCI-E bridge
2. Toshiba      TC90522XBG      : quad demodulator (2ch OFDM + 2ch 8PSK)
3. NXP Semiconductors TDA20142  : ISDB-S tuner
4. Newport Media NM120          : ISDB-T tuner
5. ASICEN       ASIE5606X8      : crypting controller

C. PLEX PX-BCUD (ISDB-S USB dongle)
1. Empia        EM28178         : USB I/F (courtesy of Nagahama Satoshi)
2. Toshiba      TC90532         : demodulator (using TC90522 driver)
3. Sharp        QM1D1C0045_2    : ISDB-S RF-IC, chip ver. 0x68

Notes:
This is a complex but smartly polished driver package containing 2 (dual head)
PCI-E bridge I/F drivers, single demodulator frontend, and 4 (quad tail) tuner drivers,
plus, simplified Nagahama's patch for PLEX PX-BCUD (ISDB-S USB dongle).
Generic registration related procedures (subdevices, frontend, etc.) summarized in
ptx_common.c are very useful also for other DVB drivers, and would be very handy if
inserted into the core (e.g. dvb_frontend.c & dvb_frontend.h).

For example, currently, the entity of struct dvb_frontend is created sometimes in
demodulators, some in tuners, or even in the parent (bridge) drivers. IMHO, this entity
should be provided by dvb_core. ptx_register_fe() included in ptx_common.c simplifies
the tasks and in fact, significantly reduces coding & kernel size.

Also, currently dvb_frontend's .demodulator_priv & .tuner_priv are of type (void *).
These should be changed to (struct i2c_client *), IMHO. Private data for demodulator
or tuner should be attached under i2c_client, using i2c_set_clientdata() for instance.

FILENAME        SUPPORTED CHIPS
========        ===============
tc90522.c       TC90522XBG, TC90532XBG,...
tda2014x.c      TDA20142
qm1d1c004x.c    QM1D1C0042, QM1D1C0045, QM1D1C0045_2
nm131.c         NM131, NM130, NM120
mxl301rf.c      MxL301RF
pt3_pci.c       EP4CGX15BF14C8N
pxq3pe_pci.c    ASV5220

Full package:
- URL:  https://github.com/knight-rider/ptx


Буди Романто, AreMa Inc (6):
  Raise adapter number limit
  drop backstabbing drivers
  Demodulator for Earthsoft PT3, PLEX PX-Q3PE ISDB-S/T PCIE cards &
    PX-BCUD ISDB-S USB dongle
  Tuners for Earthsoft PT3, PLEX PX-Q3PE ISDB-S/T PCIE cards & PX-BCUD
    ISDB-S USB dongle
  PCIE bridge driver for PT3 & PX-Q3PE
  Bridge driver for PLEX PX-BCUD ISDB-S USB dongle

 drivers/media/Kconfig                   |   5 +-
 drivers/media/dvb-core/Kconfig          |   4 +-
 drivers/media/dvb-core/dvbdev.h         |   2 +-
 drivers/media/dvb-frontends/tc90522.c   | 964 +++++++-------------------------
 drivers/media/dvb-frontends/tc90522.h   |  36 +-
 drivers/media/pci/Kconfig               |   2 +-
 drivers/media/pci/Makefile              |   2 +-
 drivers/media/pci/pt3/Kconfig           |  10 -
 drivers/media/pci/pt3/Makefile          |   8 -
 drivers/media/pci/pt3/pt3.c             | 874 -----------------------------
 drivers/media/pci/pt3/pt3.h             | 186 ------
 drivers/media/pci/pt3/pt3_dma.c         | 225 --------
 drivers/media/pci/pt3/pt3_i2c.c         | 240 --------
 drivers/media/pci/ptx/Kconfig           |  23 +
 drivers/media/pci/ptx/Makefile          |   6 +
 drivers/media/pci/ptx/pt3.c             | 426 ++++++++++++++
 drivers/media/pci/ptx/ptx_common.c      | 266 +++++++++
 drivers/media/pci/ptx/ptx_common.h      |  76 +++
 drivers/media/pci/ptx/pxq3pe.c          | 585 +++++++++++++++++++
 drivers/media/tuners/Kconfig            |  21 +-
 drivers/media/tuners/Makefile           |   4 +-
 drivers/media/tuners/mxl301rf.c         | 471 ++++++----------
 drivers/media/tuners/mxl301rf.h         |  19 +-
 drivers/media/tuners/nm131.c            | 248 ++++++++
 drivers/media/tuners/nm131.h            |  13 +
 drivers/media/tuners/qm1d1c0042.c       | 448 ---------------
 drivers/media/tuners/qm1d1c0042.h       |  37 --
 drivers/media/tuners/qm1d1c004x.c       | 242 ++++++++
 drivers/media/tuners/qm1d1c004x.h       |  23 +
 drivers/media/tuners/tda2014x.c         | 358 ++++++++++++
 drivers/media/tuners/tda2014x.h         |  13 +
 drivers/media/usb/em28xx/Kconfig        |   3 +
 drivers/media/usb/em28xx/Makefile       |   1 +
 drivers/media/usb/em28xx/em28xx-cards.c |  27 +
 drivers/media/usb/em28xx/em28xx-dvb.c   |  81 ++-
 drivers/media/usb/em28xx/em28xx.h       |   1 +
 36 files changed, 2794 insertions(+), 3156 deletions(-)
 delete mode 100644 drivers/media/pci/pt3/Kconfig
 delete mode 100644 drivers/media/pci/pt3/Makefile
 delete mode 100644 drivers/media/pci/pt3/pt3.c
 delete mode 100644 drivers/media/pci/pt3/pt3.h
 delete mode 100644 drivers/media/pci/pt3/pt3_dma.c
 delete mode 100644 drivers/media/pci/pt3/pt3_i2c.c
 create mode 100644 drivers/media/pci/ptx/Kconfig
 create mode 100644 drivers/media/pci/ptx/Makefile
 create mode 100644 drivers/media/pci/ptx/pt3.c
 create mode 100644 drivers/media/pci/ptx/ptx_common.c
 create mode 100644 drivers/media/pci/ptx/ptx_common.h
 create mode 100644 drivers/media/pci/ptx/pxq3pe.c
 create mode 100644 drivers/media/tuners/nm131.c
 create mode 100644 drivers/media/tuners/nm131.h
 delete mode 100644 drivers/media/tuners/qm1d1c0042.c
 delete mode 100644 drivers/media/tuners/qm1d1c0042.h
 create mode 100644 drivers/media/tuners/qm1d1c004x.c
 create mode 100644 drivers/media/tuners/qm1d1c004x.h
 create mode 100644 drivers/media/tuners/tda2014x.c
 create mode 100644 drivers/media/tuners/tda2014x.h

-- 
2.7.4

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

* [media 1/6] Raise adapter number limit
  2016-04-04 17:03 [media 0/6] DVB driver for Earthsoft PT3, PLEX PX-Q3PE ISDB-S/T PCIE cards & PX-BCUD ISDB-S USB dongle info
@ 2016-04-04 17:04 ` info
  2016-04-04 17:04 ` [media 2/6] drop backstabbing drivers info
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: info @ 2016-04-04 17:04 UTC (permalink / raw)
  To: linux-media
  Cc: Буди
	Романто,
	AreMa Inc, linux-kernel, crope, m.chehab, mchehab, hdegoede,
	laurent.pinchart, mkrufky, sylvester.nawrocki, g.liakhovetski,
	peter.senna

From: Буди Романто, AreMa Inc <knightrider@are.ma>

The current limit is too low for latest cards with 8+ tuners on a single slot.
IMHO, the most appropriate minimum default is 16.

Signed-off-by: Буди Романто, AreMa Inc <knightrider@are.ma>
---
 drivers/media/dvb-core/Kconfig  | 4 ++--
 drivers/media/dvb-core/dvbdev.h | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/media/dvb-core/Kconfig b/drivers/media/dvb-core/Kconfig
index fa7a249..91732a9 100644
--- a/drivers/media/dvb-core/Kconfig
+++ b/drivers/media/dvb-core/Kconfig
@@ -5,7 +5,7 @@
 config DVB_MAX_ADAPTERS
 	int "maximum number of DVB/ATSC adapters"
 	depends on DVB_CORE
-	default 8
+	default 16
 	range 1 255
 	help
 	  Maximum number of DVB/ATSC adapters. Increasing this number
@@ -13,7 +13,7 @@ config DVB_MAX_ADAPTERS
 	  if a much lower number of DVB/ATSC adapters is present.
 	  Only values in the range 4-32 are tested.
 
-	  If you are unsure about this, use the default value 8
+	  If you are unsure about this, use the default value 16
 
 config DVB_DYNAMIC_MINORS
 	bool "Dynamic DVB minor allocation"
diff --git a/drivers/media/dvb-core/dvbdev.h b/drivers/media/dvb-core/dvbdev.h
index 4aff7bd..ae4e0a2 100644
--- a/drivers/media/dvb-core/dvbdev.h
+++ b/drivers/media/dvb-core/dvbdev.h
@@ -34,7 +34,7 @@
 #if defined(CONFIG_DVB_MAX_ADAPTERS) && CONFIG_DVB_MAX_ADAPTERS > 0
   #define DVB_MAX_ADAPTERS CONFIG_DVB_MAX_ADAPTERS
 #else
-  #define DVB_MAX_ADAPTERS 8
+  #define DVB_MAX_ADAPTERS 16
 #endif
 
 #define DVB_UNSET (-1)
-- 
2.7.4

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

* [media 2/6] drop backstabbing drivers
  2016-04-04 17:03 [media 0/6] DVB driver for Earthsoft PT3, PLEX PX-Q3PE ISDB-S/T PCIE cards & PX-BCUD ISDB-S USB dongle info
  2016-04-04 17:04 ` [media 1/6] Raise adapter number limit info
@ 2016-04-04 17:04 ` info
  2016-04-04 17:04 ` [media 3/6] Demodulator for Earthsoft PT3, PLEX PX-Q3PE ISDB-S/T PCIE cards & PX-BCUD ISDB-S USB dongle info
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: info @ 2016-04-04 17:04 UTC (permalink / raw)
  To: linux-media
  Cc: Буди
	Романто,
	AreMa Inc, linux-kernel, crope, m.chehab, mchehab, hdegoede,
	laurent.pinchart, mkrufky, sylvester.nawrocki, g.liakhovetski,
	peter.senna

From: Буди Романто, AreMa Inc <knightrider@are.ma>

Obsoleted & superseded, please read cover letter for details.

Signed-off-by: Буди Романто, AreMa Inc <knightrider@are.ma>
---
 drivers/media/dvb-frontends/tc90522.c | 840 --------------------------------
 drivers/media/dvb-frontends/tc90522.h |  42 --
 drivers/media/pci/pt3/Kconfig         |  10 -
 drivers/media/pci/pt3/Makefile        |   8 -
 drivers/media/pci/pt3/pt3.c           | 874 ----------------------------------
 drivers/media/pci/pt3/pt3.h           | 186 --------
 drivers/media/pci/pt3/pt3_dma.c       | 225 ---------
 drivers/media/pci/pt3/pt3_i2c.c       | 240 ----------
 drivers/media/tuners/mxl301rf.c       | 349 --------------
 drivers/media/tuners/mxl301rf.h       |  26 -
 drivers/media/tuners/qm1d1c0042.c     | 448 -----------------
 drivers/media/tuners/qm1d1c0042.h     |  37 --
 12 files changed, 3285 deletions(-)
 delete mode 100644 drivers/media/dvb-frontends/tc90522.c
 delete mode 100644 drivers/media/dvb-frontends/tc90522.h
 delete mode 100644 drivers/media/pci/pt3/Kconfig
 delete mode 100644 drivers/media/pci/pt3/Makefile
 delete mode 100644 drivers/media/pci/pt3/pt3.c
 delete mode 100644 drivers/media/pci/pt3/pt3.h
 delete mode 100644 drivers/media/pci/pt3/pt3_dma.c
 delete mode 100644 drivers/media/pci/pt3/pt3_i2c.c
 delete mode 100644 drivers/media/tuners/mxl301rf.c
 delete mode 100644 drivers/media/tuners/mxl301rf.h
 delete mode 100644 drivers/media/tuners/qm1d1c0042.c
 delete mode 100644 drivers/media/tuners/qm1d1c0042.h

diff --git a/drivers/media/dvb-frontends/tc90522.c b/drivers/media/dvb-frontends/tc90522.c
deleted file mode 100644
index 31cd325..0000000
--- a/drivers/media/dvb-frontends/tc90522.c
+++ /dev/null
@@ -1,840 +0,0 @@
-/*
- * Toshiba TC90522 Demodulator
- *
- * Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com>
- *
- * 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.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-/*
- * NOTICE:
- * This driver is incomplete and lacks init/config of the chips,
- * as the necessary info is not disclosed.
- * It assumes that users of this driver (such as a PCI bridge of
- * DTV receiver cards) properly init and configure the chip
- * via I2C *before* calling this driver's init() function.
- *
- * Currently, PT3 driver is the only one that uses this driver,
- * and contains init/config code in its firmware.
- * Thus some part of the code might be dependent on PT3 specific config.
- */
-
-#include <linux/kernel.h>
-#include <linux/math64.h>
-#include <linux/dvb/frontend.h>
-#include "dvb_math.h"
-#include "tc90522.h"
-
-#define TC90522_I2C_THRU_REG 0xfe
-
-#define TC90522_MODULE_IDX(addr) (((u8)(addr) & 0x02U) >> 1)
-
-struct tc90522_state {
-	struct tc90522_config cfg;
-	struct dvb_frontend fe;
-	struct i2c_client *i2c_client;
-	struct i2c_adapter tuner_i2c;
-
-	bool lna;
-};
-
-struct reg_val {
-	u8 reg;
-	u8 val;
-};
-
-static int
-reg_write(struct tc90522_state *state, const struct reg_val *regs, int num)
-{
-	int i, ret;
-	struct i2c_msg msg;
-
-	ret = 0;
-	msg.addr = state->i2c_client->addr;
-	msg.flags = 0;
-	msg.len = 2;
-	for (i = 0; i < num; i++) {
-		msg.buf = (u8 *)&regs[i];
-		ret = i2c_transfer(state->i2c_client->adapter, &msg, 1);
-		if (ret == 0)
-			ret = -EIO;
-		if (ret < 0)
-			return ret;
-	}
-	return 0;
-}
-
-static int reg_read(struct tc90522_state *state, u8 reg, u8 *val, u8 len)
-{
-	struct i2c_msg msgs[2] = {
-		{
-			.addr = state->i2c_client->addr,
-			.flags = 0,
-			.buf = &reg,
-			.len = 1,
-		},
-		{
-			.addr = state->i2c_client->addr,
-			.flags = I2C_M_RD,
-			.buf = val,
-			.len = len,
-		},
-	};
-	int ret;
-
-	ret = i2c_transfer(state->i2c_client->adapter, msgs, ARRAY_SIZE(msgs));
-	if (ret == ARRAY_SIZE(msgs))
-		ret = 0;
-	else if (ret >= 0)
-		ret = -EIO;
-	return ret;
-}
-
-static struct tc90522_state *cfg_to_state(struct tc90522_config *c)
-{
-	return container_of(c, struct tc90522_state, cfg);
-}
-
-
-static int tc90522s_set_tsid(struct dvb_frontend *fe)
-{
-	struct reg_val set_tsid[] = {
-		{ 0x8f, 00 },
-		{ 0x90, 00 }
-	};
-
-	set_tsid[0].val = (fe->dtv_property_cache.stream_id & 0xff00) >> 8;
-	set_tsid[1].val = fe->dtv_property_cache.stream_id & 0xff;
-	return reg_write(fe->demodulator_priv, set_tsid, ARRAY_SIZE(set_tsid));
-}
-
-static int tc90522t_set_layers(struct dvb_frontend *fe)
-{
-	struct reg_val rv;
-	u8 laysel;
-
-	laysel = ~fe->dtv_property_cache.isdbt_layer_enabled & 0x07;
-	laysel = (laysel & 0x01) << 2 | (laysel & 0x02) | (laysel & 0x04) >> 2;
-	rv.reg = 0x71;
-	rv.val = laysel;
-	return reg_write(fe->demodulator_priv, &rv, 1);
-}
-
-/* frontend ops */
-
-static int tc90522s_read_status(struct dvb_frontend *fe, enum fe_status *status)
-{
-	struct tc90522_state *state;
-	int ret;
-	u8 reg;
-
-	state = fe->demodulator_priv;
-	ret = reg_read(state, 0xc3, &reg, 1);
-	if (ret < 0)
-		return ret;
-
-	*status = 0;
-	if (reg & 0x80) /* input level under min ? */
-		return 0;
-	*status |= FE_HAS_SIGNAL;
-
-	if (reg & 0x60) /* carrier? */
-		return 0;
-	*status |= FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC;
-
-	if (reg & 0x10)
-		return 0;
-	if (reg_read(state, 0xc5, &reg, 1) < 0 || !(reg & 0x03))
-		return 0;
-	*status |= FE_HAS_LOCK;
-	return 0;
-}
-
-static int tc90522t_read_status(struct dvb_frontend *fe, enum fe_status *status)
-{
-	struct tc90522_state *state;
-	int ret;
-	u8 reg;
-
-	state = fe->demodulator_priv;
-	ret = reg_read(state, 0x96, &reg, 1);
-	if (ret < 0)
-		return ret;
-
-	*status = 0;
-	if (reg & 0xe0) {
-		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI
-				| FE_HAS_SYNC | FE_HAS_LOCK;
-		return 0;
-	}
-
-	ret = reg_read(state, 0x80, &reg, 1);
-	if (ret < 0)
-		return ret;
-
-	if (reg & 0xf0)
-		return 0;
-	*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
-
-	if (reg & 0x0c)
-		return 0;
-	*status |= FE_HAS_SYNC | FE_HAS_VITERBI;
-
-	if (reg & 0x02)
-		return 0;
-	*status |= FE_HAS_LOCK;
-	return 0;
-}
-
-static const enum fe_code_rate fec_conv_sat[] = {
-	FEC_NONE, /* unused */
-	FEC_1_2, /* for BPSK */
-	FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_7_8, /* for QPSK */
-	FEC_2_3, /* for 8PSK. (trellis code) */
-};
-
-static int tc90522s_get_frontend(struct dvb_frontend *fe,
-				 struct dtv_frontend_properties *c)
-{
-	struct tc90522_state *state;
-	struct dtv_fe_stats *stats;
-	int ret, i;
-	int layers;
-	u8 val[10];
-	u32 cndat;
-
-	state = fe->demodulator_priv;
-	c->delivery_system = SYS_ISDBS;
-	c->symbol_rate = 28860000;
-
-	layers = 0;
-	ret = reg_read(state, 0xe6, val, 5);
-	if (ret == 0) {
-		u8 v;
-
-		c->stream_id = val[0] << 8 | val[1];
-
-		/* high/single layer */
-		v = (val[2] & 0x70) >> 4;
-		c->modulation = (v == 7) ? PSK_8 : QPSK;
-		c->fec_inner = fec_conv_sat[v];
-		c->layer[0].fec = c->fec_inner;
-		c->layer[0].modulation = c->modulation;
-		c->layer[0].segment_count = val[3] & 0x3f; /* slots */
-
-		/* low layer */
-		v = (val[2] & 0x07);
-		c->layer[1].fec = fec_conv_sat[v];
-		if (v == 0)  /* no low layer */
-			c->layer[1].segment_count = 0;
-		else
-			c->layer[1].segment_count = val[4] & 0x3f; /* slots */
-		/*
-		 * actually, BPSK if v==1, but not defined in
-		 * enum fe_modulation
-		 */
-		c->layer[1].modulation = QPSK;
-		layers = (v > 0) ? 2 : 1;
-	}
-
-	/* statistics */
-
-	stats = &c->strength;
-	stats->len = 0;
-	/* let the connected tuner set RSSI property cache */
-	if (fe->ops.tuner_ops.get_rf_strength) {
-		u16 dummy;
-
-		fe->ops.tuner_ops.get_rf_strength(fe, &dummy);
-	}
-
-	stats = &c->cnr;
-	stats->len = 1;
-	stats->stat[0].scale = FE_SCALE_NOT_AVAILABLE;
-	cndat = 0;
-	ret = reg_read(state, 0xbc, val, 2);
-	if (ret == 0)
-		cndat = val[0] << 8 | val[1];
-	if (cndat >= 3000) {
-		u32 p, p4;
-		s64 cn;
-
-		cndat -= 3000;  /* cndat: 4.12 fixed point float */
-		/*
-		 * cnr[mdB] = -1634.6 * P^5 + 14341 * P^4 - 50259 * P^3
-		 *                 + 88977 * P^2 - 89565 * P + 58857
-		 *  (P = sqrt(cndat) / 64)
-		 */
-		/* p := sqrt(cndat) << 8 = P << 14, 2.14 fixed  point float */
-		/* cn = cnr << 3 */
-		p = int_sqrt(cndat << 16);
-		p4 = cndat * cndat;
-		cn = div64_s64(-16346LL * p4 * p, 10) >> 35;
-		cn += (14341LL * p4) >> 21;
-		cn -= (50259LL * cndat * p) >> 23;
-		cn += (88977LL * cndat) >> 9;
-		cn -= (89565LL * p) >> 11;
-		cn += 58857  << 3;
-		stats->stat[0].svalue = cn >> 3;
-		stats->stat[0].scale = FE_SCALE_DECIBEL;
-	}
-
-	/* per-layer post viterbi BER (or PER? config dependent?) */
-	stats = &c->post_bit_error;
-	memset(stats, 0, sizeof(*stats));
-	stats->len = layers;
-	ret = reg_read(state, 0xeb, val, 10);
-	if (ret < 0)
-		for (i = 0; i < layers; i++)
-			stats->stat[i].scale = FE_SCALE_NOT_AVAILABLE;
-	else {
-		for (i = 0; i < layers; i++) {
-			stats->stat[i].scale = FE_SCALE_COUNTER;
-			stats->stat[i].uvalue = val[i * 5] << 16
-				| val[i * 5 + 1] << 8 | val[i * 5 + 2];
-		}
-	}
-	stats = &c->post_bit_count;
-	memset(stats, 0, sizeof(*stats));
-	stats->len = layers;
-	if (ret < 0)
-		for (i = 0; i < layers; i++)
-			stats->stat[i].scale = FE_SCALE_NOT_AVAILABLE;
-	else {
-		for (i = 0; i < layers; i++) {
-			stats->stat[i].scale = FE_SCALE_COUNTER;
-			stats->stat[i].uvalue =
-				val[i * 5 + 3] << 8 | val[i * 5 + 4];
-			stats->stat[i].uvalue *= 204 * 8;
-		}
-	}
-
-	return 0;
-}
-
-
-static const enum fe_transmit_mode tm_conv[] = {
-	TRANSMISSION_MODE_2K,
-	TRANSMISSION_MODE_4K,
-	TRANSMISSION_MODE_8K,
-	0
-};
-
-static const enum fe_code_rate fec_conv_ter[] = {
-	FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_7_8, 0, 0, 0
-};
-
-static const enum fe_modulation mod_conv[] = {
-	DQPSK, QPSK, QAM_16, QAM_64, 0, 0, 0, 0
-};
-
-static int tc90522t_get_frontend(struct dvb_frontend *fe,
-				 struct dtv_frontend_properties *c)
-{
-	struct tc90522_state *state;
-	struct dtv_fe_stats *stats;
-	int ret, i;
-	int layers;
-	u8 val[15], mode;
-	u32 cndat;
-
-	state = fe->demodulator_priv;
-	c->delivery_system = SYS_ISDBT;
-	c->bandwidth_hz = 6000000;
-	mode = 1;
-	ret = reg_read(state, 0xb0, val, 1);
-	if (ret == 0) {
-		mode = (val[0] & 0xc0) >> 2;
-		c->transmission_mode = tm_conv[mode];
-		c->guard_interval = (val[0] & 0x30) >> 4;
-	}
-
-	ret = reg_read(state, 0xb2, val, 6);
-	layers = 0;
-	if (ret == 0) {
-		u8 v;
-
-		c->isdbt_partial_reception = val[0] & 0x01;
-		c->isdbt_sb_mode = (val[0] & 0xc0) == 0x40;
-
-		/* layer A */
-		v = (val[2] & 0x78) >> 3;
-		if (v == 0x0f)
-			c->layer[0].segment_count = 0;
-		else {
-			layers++;
-			c->layer[0].segment_count = v;
-			c->layer[0].fec = fec_conv_ter[(val[1] & 0x1c) >> 2];
-			c->layer[0].modulation = mod_conv[(val[1] & 0xe0) >> 5];
-			v = (val[1] & 0x03) << 1 | (val[2] & 0x80) >> 7;
-			c->layer[0].interleaving = v;
-		}
-
-		/* layer B */
-		v = (val[3] & 0x03) << 1 | (val[4] & 0xc0) >> 6;
-		if (v == 0x0f)
-			c->layer[1].segment_count = 0;
-		else {
-			layers++;
-			c->layer[1].segment_count = v;
-			c->layer[1].fec = fec_conv_ter[(val[3] & 0xe0) >> 5];
-			c->layer[1].modulation = mod_conv[(val[2] & 0x07)];
-			c->layer[1].interleaving = (val[3] & 0x1c) >> 2;
-		}
-
-		/* layer C */
-		v = (val[5] & 0x1e) >> 1;
-		if (v == 0x0f)
-			c->layer[2].segment_count = 0;
-		else {
-			layers++;
-			c->layer[2].segment_count = v;
-			c->layer[2].fec = fec_conv_ter[(val[4] & 0x07)];
-			c->layer[2].modulation = mod_conv[(val[4] & 0x38) >> 3];
-			c->layer[2].interleaving = (val[5] & 0xe0) >> 5;
-		}
-	}
-
-	/* statistics */
-
-	stats = &c->strength;
-	stats->len = 0;
-	/* let the connected tuner set RSSI property cache */
-	if (fe->ops.tuner_ops.get_rf_strength) {
-		u16 dummy;
-
-		fe->ops.tuner_ops.get_rf_strength(fe, &dummy);
-	}
-
-	stats = &c->cnr;
-	stats->len = 1;
-	stats->stat[0].scale = FE_SCALE_NOT_AVAILABLE;
-	cndat = 0;
-	ret = reg_read(state, 0x8b, val, 3);
-	if (ret == 0)
-		cndat = val[0] << 16 | val[1] << 8 | val[2];
-	if (cndat != 0) {
-		u32 p, tmp;
-		s64 cn;
-
-		/*
-		 * cnr[mdB] = 0.024 P^4 - 1.6 P^3 + 39.8 P^2 + 549.1 P + 3096.5
-		 * (P = 10log10(5505024/cndat))
-		 */
-		/* cn = cnr << 3 (61.3 fixed point float */
-		/* p = 10log10(5505024/cndat) << 24  (8.24 fixed point float)*/
-		p = intlog10(5505024) - intlog10(cndat);
-		p *= 10;
-
-		cn = 24772;
-		cn += div64_s64(43827LL * p, 10) >> 24;
-		tmp = p >> 8;
-		cn += div64_s64(3184LL * tmp * tmp, 10) >> 32;
-		tmp = p >> 13;
-		cn -= div64_s64(128LL * tmp * tmp * tmp, 10) >> 33;
-		tmp = p >> 18;
-		cn += div64_s64(192LL * tmp * tmp * tmp * tmp, 1000) >> 24;
-
-		stats->stat[0].svalue = cn >> 3;
-		stats->stat[0].scale = FE_SCALE_DECIBEL;
-	}
-
-	/* per-layer post viterbi BER (or PER? config dependent?) */
-	stats = &c->post_bit_error;
-	memset(stats, 0, sizeof(*stats));
-	stats->len = layers;
-	ret = reg_read(state, 0x9d, val, 15);
-	if (ret < 0)
-		for (i = 0; i < layers; i++)
-			stats->stat[i].scale = FE_SCALE_NOT_AVAILABLE;
-	else {
-		for (i = 0; i < layers; i++) {
-			stats->stat[i].scale = FE_SCALE_COUNTER;
-			stats->stat[i].uvalue = val[i * 3] << 16
-				| val[i * 3 + 1] << 8 | val[i * 3 + 2];
-		}
-	}
-	stats = &c->post_bit_count;
-	memset(stats, 0, sizeof(*stats));
-	stats->len = layers;
-	if (ret < 0)
-		for (i = 0; i < layers; i++)
-			stats->stat[i].scale = FE_SCALE_NOT_AVAILABLE;
-	else {
-		for (i = 0; i < layers; i++) {
-			stats->stat[i].scale = FE_SCALE_COUNTER;
-			stats->stat[i].uvalue =
-				val[9 + i * 2] << 8 | val[9 + i * 2 + 1];
-			stats->stat[i].uvalue *= 204 * 8;
-		}
-	}
-
-	return 0;
-}
-
-static const struct reg_val reset_sat = { 0x03, 0x01 };
-static const struct reg_val reset_ter = { 0x01, 0x40 };
-
-static int tc90522_set_frontend(struct dvb_frontend *fe)
-{
-	struct tc90522_state *state;
-	int ret;
-
-	state = fe->demodulator_priv;
-
-	if (fe->ops.tuner_ops.set_params)
-		ret = fe->ops.tuner_ops.set_params(fe);
-	else
-		ret = -ENODEV;
-	if (ret < 0)
-		goto failed;
-
-	if (fe->ops.delsys[0] == SYS_ISDBS) {
-		ret = tc90522s_set_tsid(fe);
-		if (ret < 0)
-			goto failed;
-		ret = reg_write(state, &reset_sat, 1);
-	} else {
-		ret = tc90522t_set_layers(fe);
-		if (ret < 0)
-			goto failed;
-		ret = reg_write(state, &reset_ter, 1);
-	}
-	if (ret < 0)
-		goto failed;
-
-	return 0;
-
-failed:
-	dev_warn(&state->tuner_i2c.dev, "(%s) failed. [adap%d-fe%d]\n",
-			__func__, fe->dvb->num, fe->id);
-	return ret;
-}
-
-static int tc90522_get_tune_settings(struct dvb_frontend *fe,
-	struct dvb_frontend_tune_settings *settings)
-{
-	if (fe->ops.delsys[0] == SYS_ISDBS) {
-		settings->min_delay_ms = 250;
-		settings->step_size = 1000;
-		settings->max_drift = settings->step_size * 2;
-	} else {
-		settings->min_delay_ms = 400;
-		settings->step_size = 142857;
-		settings->max_drift = settings->step_size;
-	}
-	return 0;
-}
-
-static int tc90522_set_if_agc(struct dvb_frontend *fe, bool on)
-{
-	struct reg_val agc_sat[] = {
-		{ 0x0a, 0x00 },
-		{ 0x10, 0x30 },
-		{ 0x11, 0x00 },
-		{ 0x03, 0x01 },
-	};
-	struct reg_val agc_ter[] = {
-		{ 0x25, 0x00 },
-		{ 0x23, 0x4c },
-		{ 0x01, 0x40 },
-	};
-	struct tc90522_state *state;
-	struct reg_val *rv;
-	int num;
-
-	state = fe->demodulator_priv;
-	if (fe->ops.delsys[0] == SYS_ISDBS) {
-		agc_sat[0].val = on ? 0xff : 0x00;
-		agc_sat[1].val |= 0x80;
-		agc_sat[1].val |= on ? 0x01 : 0x00;
-		agc_sat[2].val |= on ? 0x40 : 0x00;
-		rv = agc_sat;
-		num = ARRAY_SIZE(agc_sat);
-	} else {
-		agc_ter[0].val = on ? 0x40 : 0x00;
-		agc_ter[1].val |= on ? 0x00 : 0x01;
-		rv = agc_ter;
-		num = ARRAY_SIZE(agc_ter);
-	}
-	return reg_write(state, rv, num);
-}
-
-static const struct reg_val sleep_sat = { 0x17, 0x01 };
-static const struct reg_val sleep_ter = { 0x03, 0x90 };
-
-static int tc90522_sleep(struct dvb_frontend *fe)
-{
-	struct tc90522_state *state;
-	int ret;
-
-	state = fe->demodulator_priv;
-	if (fe->ops.delsys[0] == SYS_ISDBS)
-		ret = reg_write(state, &sleep_sat, 1);
-	else {
-		ret = reg_write(state, &sleep_ter, 1);
-		if (ret == 0 && fe->ops.set_lna &&
-		    fe->dtv_property_cache.lna == LNA_AUTO) {
-			fe->dtv_property_cache.lna = 0;
-			ret = fe->ops.set_lna(fe);
-			fe->dtv_property_cache.lna = LNA_AUTO;
-		}
-	}
-	if (ret < 0)
-		dev_warn(&state->tuner_i2c.dev,
-			"(%s) failed. [adap%d-fe%d]\n",
-			__func__, fe->dvb->num, fe->id);
-	return ret;
-}
-
-static const struct reg_val wakeup_sat = { 0x17, 0x00 };
-static const struct reg_val wakeup_ter = { 0x03, 0x80 };
-
-static int tc90522_init(struct dvb_frontend *fe)
-{
-	struct tc90522_state *state;
-	int ret;
-
-	/*
-	 * Because the init sequence is not public,
-	 * the parent device/driver should have init'ed the device before.
-	 * just wake up the device here.
-	 */
-
-	state = fe->demodulator_priv;
-	if (fe->ops.delsys[0] == SYS_ISDBS)
-		ret = reg_write(state, &wakeup_sat, 1);
-	else {
-		ret = reg_write(state, &wakeup_ter, 1);
-		if (ret == 0 && fe->ops.set_lna &&
-		    fe->dtv_property_cache.lna == LNA_AUTO) {
-			fe->dtv_property_cache.lna = 1;
-			ret = fe->ops.set_lna(fe);
-			fe->dtv_property_cache.lna = LNA_AUTO;
-		}
-	}
-	if (ret < 0) {
-		dev_warn(&state->tuner_i2c.dev,
-			"(%s) failed. [adap%d-fe%d]\n",
-			__func__, fe->dvb->num, fe->id);
-		return ret;
-	}
-
-	/* prefer 'all-layers' to 'none' as a default */
-	if (fe->dtv_property_cache.isdbt_layer_enabled == 0)
-		fe->dtv_property_cache.isdbt_layer_enabled = 7;
-	return tc90522_set_if_agc(fe, true);
-}
-
-
-/*
- * tuner I2C adapter functions
- */
-
-static int
-tc90522_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
-{
-	struct tc90522_state *state;
-	struct i2c_msg *new_msgs;
-	int i, j;
-	int ret, rd_num;
-	u8 wbuf[256];
-	u8 *p, *bufend;
-
-	if (num <= 0)
-		return -EINVAL;
-
-	rd_num = 0;
-	for (i = 0; i < num; i++)
-		if (msgs[i].flags & I2C_M_RD)
-			rd_num++;
-	new_msgs = kmalloc(sizeof(*new_msgs) * (num + rd_num), GFP_KERNEL);
-	if (!new_msgs)
-		return -ENOMEM;
-
-	state = i2c_get_adapdata(adap);
-	p = wbuf;
-	bufend = wbuf + sizeof(wbuf);
-	for (i = 0, j = 0; i < num; i++, j++) {
-		new_msgs[j].addr = state->i2c_client->addr;
-		new_msgs[j].flags = msgs[i].flags;
-
-		if (msgs[i].flags & I2C_M_RD) {
-			new_msgs[j].flags &= ~I2C_M_RD;
-			if (p + 2 > bufend)
-				break;
-			p[0] = TC90522_I2C_THRU_REG;
-			p[1] = msgs[i].addr << 1 | 0x01;
-			new_msgs[j].buf = p;
-			new_msgs[j].len = 2;
-			p += 2;
-			j++;
-			new_msgs[j].addr = state->i2c_client->addr;
-			new_msgs[j].flags = msgs[i].flags;
-			new_msgs[j].buf = msgs[i].buf;
-			new_msgs[j].len = msgs[i].len;
-			continue;
-		}
-
-		if (p + msgs[i].len + 2 > bufend)
-			break;
-		p[0] = TC90522_I2C_THRU_REG;
-		p[1] = msgs[i].addr << 1;
-		memcpy(p + 2, msgs[i].buf, msgs[i].len);
-		new_msgs[j].buf = p;
-		new_msgs[j].len = msgs[i].len + 2;
-		p += new_msgs[j].len;
-	}
-
-	if (i < num)
-		ret = -ENOMEM;
-	else
-		ret = i2c_transfer(state->i2c_client->adapter, new_msgs, j);
-	if (ret >= 0 && ret < j)
-		ret = -EIO;
-	kfree(new_msgs);
-	return (ret == j) ? num : ret;
-}
-
-static u32 tc90522_functionality(struct i2c_adapter *adap)
-{
-	return I2C_FUNC_I2C;
-}
-
-static const struct i2c_algorithm tc90522_tuner_i2c_algo = {
-	.master_xfer   = &tc90522_master_xfer,
-	.functionality = &tc90522_functionality,
-};
-
-
-/*
- * I2C driver functions
- */
-
-static const struct dvb_frontend_ops tc90522_ops_sat = {
-	.delsys = { SYS_ISDBS },
-	.info = {
-		.name = "Toshiba TC90522 ISDB-S module",
-		.frequency_min =  950000,
-		.frequency_max = 2150000,
-		.caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO |
-			FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO,
-	},
-
-	.init = tc90522_init,
-	.sleep = tc90522_sleep,
-	.set_frontend = tc90522_set_frontend,
-	.get_tune_settings = tc90522_get_tune_settings,
-
-	.get_frontend = tc90522s_get_frontend,
-	.read_status = tc90522s_read_status,
-};
-
-static const struct dvb_frontend_ops tc90522_ops_ter = {
-	.delsys = { SYS_ISDBT },
-	.info = {
-		.name = "Toshiba TC90522 ISDB-T module",
-		.frequency_min = 470000000,
-		.frequency_max = 770000000,
-		.frequency_stepsize = 142857,
-		.caps = FE_CAN_INVERSION_AUTO |
-			FE_CAN_FEC_1_2  | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
-			FE_CAN_FEC_5_6  | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
-			FE_CAN_QPSK     | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
-			FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER |
-			FE_CAN_HIERARCHY_AUTO,
-	},
-
-	.init = tc90522_init,
-	.sleep = tc90522_sleep,
-	.set_frontend = tc90522_set_frontend,
-	.get_tune_settings = tc90522_get_tune_settings,
-
-	.get_frontend = tc90522t_get_frontend,
-	.read_status = tc90522t_read_status,
-};
-
-
-static int tc90522_probe(struct i2c_client *client,
-			 const struct i2c_device_id *id)
-{
-	struct tc90522_state *state;
-	struct tc90522_config *cfg;
-	const struct dvb_frontend_ops *ops;
-	struct i2c_adapter *adap;
-	int ret;
-
-	state = kzalloc(sizeof(*state), GFP_KERNEL);
-	if (!state)
-		return -ENOMEM;
-	state->i2c_client = client;
-
-	cfg = client->dev.platform_data;
-	memcpy(&state->cfg, cfg, sizeof(state->cfg));
-	cfg->fe = state->cfg.fe = &state->fe;
-	ops =  id->driver_data == 0 ? &tc90522_ops_sat : &tc90522_ops_ter;
-	memcpy(&state->fe.ops, ops, sizeof(*ops));
-	state->fe.demodulator_priv = state;
-
-	adap = &state->tuner_i2c;
-	adap->owner = THIS_MODULE;
-	adap->algo = &tc90522_tuner_i2c_algo;
-	adap->dev.parent = &client->dev;
-	strlcpy(adap->name, "tc90522_sub", sizeof(adap->name));
-	i2c_set_adapdata(adap, state);
-	ret = i2c_add_adapter(adap);
-	if (ret < 0)
-		goto err;
-	cfg->tuner_i2c = state->cfg.tuner_i2c = adap;
-
-	i2c_set_clientdata(client, &state->cfg);
-	dev_info(&client->dev, "Toshiba TC90522 attached.\n");
-	return 0;
-
-err:
-	kfree(state);
-	return ret;
-}
-
-static int tc90522_remove(struct i2c_client *client)
-{
-	struct tc90522_state *state;
-
-	state = cfg_to_state(i2c_get_clientdata(client));
-	i2c_del_adapter(&state->tuner_i2c);
-	kfree(state);
-	return 0;
-}
-
-
-static const struct i2c_device_id tc90522_id[] = {
-	{ TC90522_I2C_DEV_SAT, 0 },
-	{ TC90522_I2C_DEV_TER, 1 },
-	{}
-};
-MODULE_DEVICE_TABLE(i2c, tc90522_id);
-
-static struct i2c_driver tc90522_driver = {
-	.driver = {
-		.name	= "tc90522",
-	},
-	.probe		= tc90522_probe,
-	.remove		= tc90522_remove,
-	.id_table	= tc90522_id,
-};
-
-module_i2c_driver(tc90522_driver);
-
-MODULE_DESCRIPTION("Toshiba TC90522 frontend");
-MODULE_AUTHOR("Akihiro TSUKADA");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/tc90522.h b/drivers/media/dvb-frontends/tc90522.h
deleted file mode 100644
index b1cbddf..0000000
--- a/drivers/media/dvb-frontends/tc90522.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Toshiba TC90522 Demodulator
- *
- * Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com>
- *
- * 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.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-/*
- * The demod has 4 input (2xISDB-T and 2xISDB-S),
- * and provides independent sub modules for each input.
- * As the sub modules work in parallel and have the separate i2c addr's,
- * this driver treats each sub module as one demod device.
- */
-
-#ifndef TC90522_H
-#define TC90522_H
-
-#include <linux/i2c.h>
-#include "dvb_frontend.h"
-
-/* I2C device types */
-#define TC90522_I2C_DEV_SAT "tc90522sat"
-#define TC90522_I2C_DEV_TER "tc90522ter"
-
-struct tc90522_config {
-	/* [OUT] frontend returned by driver */
-	struct dvb_frontend *fe;
-
-	/* [OUT] tuner I2C adapter returned by driver */
-	struct i2c_adapter *tuner_i2c;
-};
-
-#endif /* TC90522_H */
diff --git a/drivers/media/pci/pt3/Kconfig b/drivers/media/pci/pt3/Kconfig
deleted file mode 100644
index 16c208a..0000000
--- a/drivers/media/pci/pt3/Kconfig
+++ /dev/null
@@ -1,10 +0,0 @@
-config DVB_PT3
-	tristate "Earthsoft PT3 cards"
-	depends on DVB_CORE && PCI && I2C
-	select DVB_TC90522 if MEDIA_SUBDRV_AUTOSELECT
-	select MEDIA_TUNER_QM1D1C0042 if MEDIA_SUBDRV_AUTOSELECT
-	select MEDIA_TUNER_MXL301RF if MEDIA_SUBDRV_AUTOSELECT
-	help
-	  Support for Earthsoft PT3 PCIe cards.
-
-	  Say Y or M if you own such a device and want to use it.
diff --git a/drivers/media/pci/pt3/Makefile b/drivers/media/pci/pt3/Makefile
deleted file mode 100644
index 396f146..0000000
--- a/drivers/media/pci/pt3/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-
-earth-pt3-objs += pt3.o pt3_i2c.o pt3_dma.o
-
-obj-$(CONFIG_DVB_PT3) += earth-pt3.o
-
-ccflags-y += -Idrivers/media/dvb-core
-ccflags-y += -Idrivers/media/dvb-frontends
-ccflags-y += -Idrivers/media/tuners
diff --git a/drivers/media/pci/pt3/pt3.c b/drivers/media/pci/pt3/pt3.c
deleted file mode 100644
index eff5e9f..0000000
--- a/drivers/media/pci/pt3/pt3.c
+++ /dev/null
@@ -1,874 +0,0 @@
-/*
- * Earthsoft PT3 driver
- *
- * Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com>
- *
- * 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.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/freezer.h>
-#include <linux/kernel.h>
-#include <linux/kthread.h>
-#include <linux/mutex.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/string.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-
-#include "pt3.h"
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static bool one_adapter;
-module_param(one_adapter, bool, 0444);
-MODULE_PARM_DESC(one_adapter, "Place FE's together under one adapter.");
-
-static int num_bufs = 4;
-module_param(num_bufs, int, 0444);
-MODULE_PARM_DESC(num_bufs, "Number of DMA buffer (188KiB) per FE.");
-
-
-static const struct i2c_algorithm pt3_i2c_algo = {
-	.master_xfer   = &pt3_i2c_master_xfer,
-	.functionality = &pt3_i2c_functionality,
-};
-
-static const struct pt3_adap_config adap_conf[PT3_NUM_FE] = {
-	{
-		.demod_info = {
-			I2C_BOARD_INFO(TC90522_I2C_DEV_SAT, 0x11),
-		},
-		.tuner_info = {
-			I2C_BOARD_INFO("qm1d1c0042", 0x63),
-		},
-		.tuner_cfg.qm1d1c0042 = {
-			.lpf = 1,
-		},
-		.init_freq = 1049480 - 300,
-	},
-	{
-		.demod_info = {
-			I2C_BOARD_INFO(TC90522_I2C_DEV_TER, 0x10),
-		},
-		.tuner_info = {
-			I2C_BOARD_INFO("mxl301rf", 0x62),
-		},
-		.init_freq = 515142857,
-	},
-	{
-		.demod_info = {
-			I2C_BOARD_INFO(TC90522_I2C_DEV_SAT, 0x13),
-		},
-		.tuner_info = {
-			I2C_BOARD_INFO("qm1d1c0042", 0x60),
-		},
-		.tuner_cfg.qm1d1c0042 = {
-			.lpf = 1,
-		},
-		.init_freq = 1049480 + 300,
-	},
-	{
-		.demod_info = {
-			I2C_BOARD_INFO(TC90522_I2C_DEV_TER, 0x12),
-		},
-		.tuner_info = {
-			I2C_BOARD_INFO("mxl301rf", 0x61),
-		},
-		.init_freq = 521142857,
-	},
-};
-
-
-struct reg_val {
-	u8 reg;
-	u8 val;
-};
-
-static int
-pt3_demod_write(struct pt3_adapter *adap, const struct reg_val *data, int num)
-{
-	struct i2c_msg msg;
-	int i, ret;
-
-	ret = 0;
-	msg.addr = adap->i2c_demod->addr;
-	msg.flags = 0;
-	msg.len = 2;
-	for (i = 0; i < num; i++) {
-		msg.buf = (u8 *)&data[i];
-		ret = i2c_transfer(adap->i2c_demod->adapter, &msg, 1);
-		if (ret == 0)
-			ret = -EREMOTE;
-		if (ret < 0)
-			return ret;
-	}
-	return 0;
-}
-
-static inline void pt3_lnb_ctrl(struct pt3_board *pt3, bool on)
-{
-	iowrite32((on ? 0x0f : 0x0c), pt3->regs[0] + REG_SYSTEM_W);
-}
-
-static inline struct pt3_adapter *pt3_find_adapter(struct dvb_frontend *fe)
-{
-	struct pt3_board *pt3;
-	int i;
-
-	if (one_adapter) {
-		pt3 = fe->dvb->priv;
-		for (i = 0; i < PT3_NUM_FE; i++)
-			if (pt3->adaps[i]->fe == fe)
-				return pt3->adaps[i];
-	}
-	return container_of(fe->dvb, struct pt3_adapter, dvb_adap);
-}
-
-/*
- * all 4 tuners in PT3 are packaged in a can module (Sharp VA4M6JC2103).
- * it seems that they share the power lines and Amp power line and
- * adaps[3] controls those powers.
- */
-static int
-pt3_set_tuner_power(struct pt3_board *pt3, bool tuner_on, bool amp_on)
-{
-	struct reg_val rv = { 0x1e, 0x99 };
-
-	if (tuner_on)
-		rv.val |= 0x40;
-	if (amp_on)
-		rv.val |= 0x04;
-	return pt3_demod_write(pt3->adaps[PT3_NUM_FE - 1], &rv, 1);
-}
-
-static int pt3_set_lna(struct dvb_frontend *fe)
-{
-	struct pt3_adapter *adap;
-	struct pt3_board *pt3;
-	u32 val;
-	int ret;
-
-	/* LNA is shared btw. 2 TERR-tuners */
-
-	adap = pt3_find_adapter(fe);
-	val = fe->dtv_property_cache.lna;
-	if (val == LNA_AUTO || val == adap->cur_lna)
-		return 0;
-
-	pt3 = adap->dvb_adap.priv;
-	if (mutex_lock_interruptible(&pt3->lock))
-		return -ERESTARTSYS;
-	if (val)
-		pt3->lna_on_cnt++;
-	else
-		pt3->lna_on_cnt--;
-
-	if (val && pt3->lna_on_cnt <= 1) {
-		pt3->lna_on_cnt = 1;
-		ret = pt3_set_tuner_power(pt3, true, true);
-	} else if (!val && pt3->lna_on_cnt <= 0) {
-		pt3->lna_on_cnt = 0;
-		ret = pt3_set_tuner_power(pt3, true, false);
-	} else
-		ret = 0;
-	mutex_unlock(&pt3->lock);
-	adap->cur_lna = (val != 0);
-	return ret;
-}
-
-static int pt3_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage volt)
-{
-	struct pt3_adapter *adap;
-	struct pt3_board *pt3;
-	bool on;
-
-	/* LNB power is shared btw. 2 SAT-tuners */
-
-	adap = pt3_find_adapter(fe);
-	on = (volt != SEC_VOLTAGE_OFF);
-	if (on == adap->cur_lnb)
-		return 0;
-	adap->cur_lnb = on;
-	pt3 = adap->dvb_adap.priv;
-	if (mutex_lock_interruptible(&pt3->lock))
-		return -ERESTARTSYS;
-	if (on)
-		pt3->lnb_on_cnt++;
-	else
-		pt3->lnb_on_cnt--;
-
-	if (on && pt3->lnb_on_cnt <= 1) {
-		pt3->lnb_on_cnt = 1;
-		pt3_lnb_ctrl(pt3, true);
-	} else if (!on && pt3->lnb_on_cnt <= 0) {
-		pt3->lnb_on_cnt = 0;
-		pt3_lnb_ctrl(pt3, false);
-	}
-	mutex_unlock(&pt3->lock);
-	return 0;
-}
-
-/* register values used in pt3_fe_init() */
-
-static const struct reg_val init0_sat[] = {
-	{ 0x03, 0x01 },
-	{ 0x1e, 0x10 },
-};
-static const struct reg_val init0_ter[] = {
-	{ 0x01, 0x40 },
-	{ 0x1c, 0x10 },
-};
-static const struct reg_val cfg_sat[] = {
-	{ 0x1c, 0x15 },
-	{ 0x1f, 0x04 },
-};
-static const struct reg_val cfg_ter[] = {
-	{ 0x1d, 0x01 },
-};
-
-/*
- * pt3_fe_init: initialize demod sub modules and ISDB-T tuners all at once.
- *
- * As for demod IC (TC90522) and ISDB-T tuners (MxL301RF),
- * the i2c sequences for init'ing them are not public and hidden in a ROM,
- * and include the board specific configurations as well.
- * They are stored in a lump and cannot be taken out / accessed separately,
- * thus cannot be moved to the FE/tuner driver.
- */
-static int pt3_fe_init(struct pt3_board *pt3)
-{
-	int i, ret;
-	struct dvb_frontend *fe;
-
-	pt3_i2c_reset(pt3);
-	ret = pt3_init_all_demods(pt3);
-	if (ret < 0) {
-		dev_warn(&pt3->pdev->dev, "Failed to init demod chips\n");
-		return ret;
-	}
-
-	/* additional config? */
-	for (i = 0; i < PT3_NUM_FE; i++) {
-		fe = pt3->adaps[i]->fe;
-
-		if (fe->ops.delsys[0] == SYS_ISDBS)
-			ret = pt3_demod_write(pt3->adaps[i],
-					      init0_sat, ARRAY_SIZE(init0_sat));
-		else
-			ret = pt3_demod_write(pt3->adaps[i],
-					      init0_ter, ARRAY_SIZE(init0_ter));
-		if (ret < 0) {
-			dev_warn(&pt3->pdev->dev,
-				 "demod[%d] failed in init sequence0\n", i);
-			return ret;
-		}
-		ret = fe->ops.init(fe);
-		if (ret < 0)
-			return ret;
-	}
-
-	usleep_range(2000, 4000);
-	ret = pt3_set_tuner_power(pt3, true, false);
-	if (ret < 0) {
-		dev_warn(&pt3->pdev->dev, "Failed to control tuner module\n");
-		return ret;
-	}
-
-	/* output pin configuration */
-	for (i = 0; i < PT3_NUM_FE; i++) {
-		fe = pt3->adaps[i]->fe;
-		if (fe->ops.delsys[0] == SYS_ISDBS)
-			ret = pt3_demod_write(pt3->adaps[i],
-						cfg_sat, ARRAY_SIZE(cfg_sat));
-		else
-			ret = pt3_demod_write(pt3->adaps[i],
-						cfg_ter, ARRAY_SIZE(cfg_ter));
-		if (ret < 0) {
-			dev_warn(&pt3->pdev->dev,
-				 "demod[%d] failed in init sequence1\n", i);
-			return ret;
-		}
-	}
-	usleep_range(4000, 6000);
-
-	for (i = 0; i < PT3_NUM_FE; i++) {
-		fe = pt3->adaps[i]->fe;
-		if (fe->ops.delsys[0] != SYS_ISDBS)
-			continue;
-		/* init and wake-up ISDB-S tuners */
-		ret = fe->ops.tuner_ops.init(fe);
-		if (ret < 0) {
-			dev_warn(&pt3->pdev->dev,
-				 "Failed to init SAT-tuner[%d]\n", i);
-			return ret;
-		}
-	}
-	ret = pt3_init_all_mxl301rf(pt3);
-	if (ret < 0) {
-		dev_warn(&pt3->pdev->dev, "Failed to init TERR-tuners\n");
-		return ret;
-	}
-
-	ret = pt3_set_tuner_power(pt3, true, true);
-	if (ret < 0) {
-		dev_warn(&pt3->pdev->dev, "Failed to control tuner module\n");
-		return ret;
-	}
-
-	/* Wake up all tuners and make an initial tuning,
-	 * in order to avoid interference among the tuners in the module,
-	 * according to the doc from the manufacturer.
-	 */
-	for (i = 0; i < PT3_NUM_FE; i++) {
-		fe = pt3->adaps[i]->fe;
-		ret = 0;
-		if (fe->ops.delsys[0] == SYS_ISDBT)
-			ret = fe->ops.tuner_ops.init(fe);
-		/* set only when called from pt3_probe(), not resume() */
-		if (ret == 0 && fe->dtv_property_cache.frequency == 0) {
-			fe->dtv_property_cache.frequency =
-						adap_conf[i].init_freq;
-			ret = fe->ops.tuner_ops.set_params(fe);
-		}
-		if (ret < 0) {
-			dev_warn(&pt3->pdev->dev,
-				 "Failed in initial tuning of tuner[%d]\n", i);
-			return ret;
-		}
-	}
-
-	/* and sleep again, waiting to be opened by users. */
-	for (i = 0; i < PT3_NUM_FE; i++) {
-		fe = pt3->adaps[i]->fe;
-		if (fe->ops.tuner_ops.sleep)
-			ret = fe->ops.tuner_ops.sleep(fe);
-		if (ret < 0)
-			break;
-		if (fe->ops.sleep)
-			ret = fe->ops.sleep(fe);
-		if (ret < 0)
-			break;
-		if (fe->ops.delsys[0] == SYS_ISDBS)
-			fe->ops.set_voltage = &pt3_set_voltage;
-		else
-			fe->ops.set_lna = &pt3_set_lna;
-	}
-	if (i < PT3_NUM_FE) {
-		dev_warn(&pt3->pdev->dev, "FE[%d] failed to standby\n", i);
-		return ret;
-	}
-	return 0;
-}
-
-
-static int pt3_attach_fe(struct pt3_board *pt3, int i)
-{
-	struct i2c_board_info info;
-	struct tc90522_config cfg;
-	struct i2c_client *cl;
-	struct dvb_adapter *dvb_adap;
-	int ret;
-
-	info = adap_conf[i].demod_info;
-	cfg = adap_conf[i].demod_cfg;
-	cfg.tuner_i2c = NULL;
-	info.platform_data = &cfg;
-
-	ret = -ENODEV;
-	request_module("tc90522");
-	cl = i2c_new_device(&pt3->i2c_adap, &info);
-	if (!cl || !cl->dev.driver)
-		return -ENODEV;
-	pt3->adaps[i]->i2c_demod = cl;
-	if (!try_module_get(cl->dev.driver->owner))
-		goto err_demod_i2c_unregister_device;
-
-	if (!strncmp(cl->name, TC90522_I2C_DEV_SAT,
-		     strlen(TC90522_I2C_DEV_SAT))) {
-		struct qm1d1c0042_config tcfg;
-
-		tcfg = adap_conf[i].tuner_cfg.qm1d1c0042;
-		tcfg.fe = cfg.fe;
-		info = adap_conf[i].tuner_info;
-		info.platform_data = &tcfg;
-		request_module("qm1d1c0042");
-		cl = i2c_new_device(cfg.tuner_i2c, &info);
-	} else {
-		struct mxl301rf_config tcfg;
-
-		tcfg = adap_conf[i].tuner_cfg.mxl301rf;
-		tcfg.fe = cfg.fe;
-		info = adap_conf[i].tuner_info;
-		info.platform_data = &tcfg;
-		request_module("mxl301rf");
-		cl = i2c_new_device(cfg.tuner_i2c, &info);
-	}
-	if (!cl || !cl->dev.driver)
-		goto err_demod_module_put;
-	pt3->adaps[i]->i2c_tuner = cl;
-	if (!try_module_get(cl->dev.driver->owner))
-		goto err_tuner_i2c_unregister_device;
-
-	dvb_adap = &pt3->adaps[one_adapter ? 0 : i]->dvb_adap;
-	ret = dvb_register_frontend(dvb_adap, cfg.fe);
-	if (ret < 0)
-		goto err_tuner_module_put;
-	pt3->adaps[i]->fe = cfg.fe;
-	return 0;
-
-err_tuner_module_put:
-	module_put(pt3->adaps[i]->i2c_tuner->dev.driver->owner);
-err_tuner_i2c_unregister_device:
-	i2c_unregister_device(pt3->adaps[i]->i2c_tuner);
-err_demod_module_put:
-	module_put(pt3->adaps[i]->i2c_demod->dev.driver->owner);
-err_demod_i2c_unregister_device:
-	i2c_unregister_device(pt3->adaps[i]->i2c_demod);
-
-	return ret;
-}
-
-
-static int pt3_fetch_thread(void *data)
-{
-	struct pt3_adapter *adap = data;
-	ktime_t delay;
-	bool was_frozen;
-
-#define PT3_INITIAL_BUF_DROPS 4
-#define PT3_FETCH_DELAY 10
-#define PT3_FETCH_DELAY_DELTA 2
-
-	pt3_init_dmabuf(adap);
-	adap->num_discard = PT3_INITIAL_BUF_DROPS;
-
-	dev_dbg(adap->dvb_adap.device, "PT3: [%s] started\n",
-		adap->thread->comm);
-	set_freezable();
-	while (!kthread_freezable_should_stop(&was_frozen)) {
-		if (was_frozen)
-			adap->num_discard = PT3_INITIAL_BUF_DROPS;
-
-		pt3_proc_dma(adap);
-
-		delay = ktime_set(0, PT3_FETCH_DELAY * NSEC_PER_MSEC);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		freezable_schedule_hrtimeout_range(&delay,
-					PT3_FETCH_DELAY_DELTA * NSEC_PER_MSEC,
-					HRTIMER_MODE_REL);
-	}
-	dev_dbg(adap->dvb_adap.device, "PT3: [%s] exited\n",
-		adap->thread->comm);
-	adap->thread = NULL;
-	return 0;
-}
-
-static int pt3_start_streaming(struct pt3_adapter *adap)
-{
-	struct task_struct *thread;
-
-	/* start fetching thread */
-	thread = kthread_run(pt3_fetch_thread, adap, "pt3-ad%i-dmx%i",
-				adap->dvb_adap.num, adap->dmxdev.dvbdev->id);
-	if (IS_ERR(thread)) {
-		int ret = PTR_ERR(thread);
-
-		dev_warn(adap->dvb_adap.device,
-			 "PT3 (adap:%d, dmx:%d): failed to start kthread\n",
-			 adap->dvb_adap.num, adap->dmxdev.dvbdev->id);
-		return ret;
-	}
-	adap->thread = thread;
-
-	return pt3_start_dma(adap);
-}
-
-static int pt3_stop_streaming(struct pt3_adapter *adap)
-{
-	int ret;
-
-	ret = pt3_stop_dma(adap);
-	if (ret)
-		dev_warn(adap->dvb_adap.device,
-			 "PT3: failed to stop streaming of adap:%d/FE:%d\n",
-			 adap->dvb_adap.num, adap->fe->id);
-
-	/* kill the fetching thread */
-	ret = kthread_stop(adap->thread);
-	return ret;
-}
-
-static int pt3_start_feed(struct dvb_demux_feed *feed)
-{
-	struct pt3_adapter *adap;
-
-	if (signal_pending(current))
-		return -EINTR;
-
-	adap = container_of(feed->demux, struct pt3_adapter, demux);
-	adap->num_feeds++;
-	if (adap->thread)
-		return 0;
-	if (adap->num_feeds != 1) {
-		dev_warn(adap->dvb_adap.device,
-			 "%s: unmatched start/stop_feed in adap:%i/dmx:%i\n",
-			 __func__, adap->dvb_adap.num, adap->dmxdev.dvbdev->id);
-		adap->num_feeds = 1;
-	}
-
-	return pt3_start_streaming(adap);
-
-}
-
-static int pt3_stop_feed(struct dvb_demux_feed *feed)
-{
-	struct pt3_adapter *adap;
-
-	adap = container_of(feed->demux, struct pt3_adapter, demux);
-
-	adap->num_feeds--;
-	if (adap->num_feeds > 0 || !adap->thread)
-		return 0;
-	adap->num_feeds = 0;
-
-	return pt3_stop_streaming(adap);
-}
-
-
-static int pt3_alloc_adapter(struct pt3_board *pt3, int index)
-{
-	int ret;
-	struct pt3_adapter *adap;
-	struct dvb_adapter *da;
-
-	adap = kzalloc(sizeof(*adap), GFP_KERNEL);
-	if (!adap)
-		return -ENOMEM;
-
-	pt3->adaps[index] = adap;
-	adap->adap_idx = index;
-
-	if (index == 0 || !one_adapter) {
-		ret = dvb_register_adapter(&adap->dvb_adap, "PT3 DVB",
-				THIS_MODULE, &pt3->pdev->dev, adapter_nr);
-		if (ret < 0) {
-			dev_err(&pt3->pdev->dev,
-				"failed to register adapter dev\n");
-			goto err_mem;
-		}
-		da = &adap->dvb_adap;
-	} else
-		da = &pt3->adaps[0]->dvb_adap;
-
-	adap->dvb_adap.priv = pt3;
-	adap->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
-	adap->demux.priv = adap;
-	adap->demux.feednum = 256;
-	adap->demux.filternum = 256;
-	adap->demux.start_feed = pt3_start_feed;
-	adap->demux.stop_feed = pt3_stop_feed;
-	ret = dvb_dmx_init(&adap->demux);
-	if (ret < 0) {
-		dev_err(&pt3->pdev->dev, "failed to init dmx dev\n");
-		goto err_adap;
-	}
-
-	adap->dmxdev.filternum = 256;
-	adap->dmxdev.demux = &adap->demux.dmx;
-	ret = dvb_dmxdev_init(&adap->dmxdev, da);
-	if (ret < 0) {
-		dev_err(&pt3->pdev->dev, "failed to init dmxdev\n");
-		goto err_demux;
-	}
-
-	ret = pt3_alloc_dmabuf(adap);
-	if (ret) {
-		dev_err(&pt3->pdev->dev, "failed to alloc DMA buffers\n");
-		goto err_dmabuf;
-	}
-
-	return 0;
-
-err_dmabuf:
-	pt3_free_dmabuf(adap);
-	dvb_dmxdev_release(&adap->dmxdev);
-err_demux:
-	dvb_dmx_release(&adap->demux);
-err_adap:
-	if (index == 0 || !one_adapter)
-		dvb_unregister_adapter(da);
-err_mem:
-	kfree(adap);
-	pt3->adaps[index] = NULL;
-	return ret;
-}
-
-static void pt3_cleanup_adapter(struct pt3_board *pt3, int index)
-{
-	struct pt3_adapter *adap;
-	struct dmx_demux *dmx;
-
-	adap = pt3->adaps[index];
-	if (adap == NULL)
-		return;
-
-	/* stop demux kthread */
-	if (adap->thread)
-		pt3_stop_streaming(adap);
-
-	dmx = &adap->demux.dmx;
-	dmx->close(dmx);
-	if (adap->fe) {
-		adap->fe->callback = NULL;
-		if (adap->fe->frontend_priv)
-			dvb_unregister_frontend(adap->fe);
-		if (adap->i2c_tuner) {
-			module_put(adap->i2c_tuner->dev.driver->owner);
-			i2c_unregister_device(adap->i2c_tuner);
-		}
-		if (adap->i2c_demod) {
-			module_put(adap->i2c_demod->dev.driver->owner);
-			i2c_unregister_device(adap->i2c_demod);
-		}
-	}
-	pt3_free_dmabuf(adap);
-	dvb_dmxdev_release(&adap->dmxdev);
-	dvb_dmx_release(&adap->demux);
-	if (index == 0 || !one_adapter)
-		dvb_unregister_adapter(&adap->dvb_adap);
-	kfree(adap);
-	pt3->adaps[index] = NULL;
-}
-
-#ifdef CONFIG_PM_SLEEP
-
-static int pt3_suspend(struct device *dev)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-	struct pt3_board *pt3 = pci_get_drvdata(pdev);
-	int i;
-	struct pt3_adapter *adap;
-
-	for (i = 0; i < PT3_NUM_FE; i++) {
-		adap = pt3->adaps[i];
-		if (adap->num_feeds > 0)
-			pt3_stop_dma(adap);
-		dvb_frontend_suspend(adap->fe);
-		pt3_free_dmabuf(adap);
-	}
-
-	pt3_lnb_ctrl(pt3, false);
-	pt3_set_tuner_power(pt3, false, false);
-	return 0;
-}
-
-static int pt3_resume(struct device *dev)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-	struct pt3_board *pt3 = pci_get_drvdata(pdev);
-	int i, ret;
-	struct pt3_adapter *adap;
-
-	ret = pt3_fe_init(pt3);
-	if (ret)
-		return ret;
-
-	if (pt3->lna_on_cnt > 0)
-		pt3_set_tuner_power(pt3, true, true);
-	if (pt3->lnb_on_cnt > 0)
-		pt3_lnb_ctrl(pt3, true);
-
-	for (i = 0; i < PT3_NUM_FE; i++) {
-		adap = pt3->adaps[i];
-		dvb_frontend_resume(adap->fe);
-		ret = pt3_alloc_dmabuf(adap);
-		if (ret) {
-			dev_err(&pt3->pdev->dev, "failed to alloc DMA bufs\n");
-			continue;
-		}
-		if (adap->num_feeds > 0)
-			pt3_start_dma(adap);
-	}
-
-	return 0;
-}
-
-#endif /* CONFIG_PM_SLEEP */
-
-
-static void pt3_remove(struct pci_dev *pdev)
-{
-	struct pt3_board *pt3;
-	int i;
-
-	pt3 = pci_get_drvdata(pdev);
-	for (i = PT3_NUM_FE - 1; i >= 0; i--)
-		pt3_cleanup_adapter(pt3, i);
-	i2c_del_adapter(&pt3->i2c_adap);
-	kfree(pt3->i2c_buf);
-	pci_iounmap(pt3->pdev, pt3->regs[0]);
-	pci_iounmap(pt3->pdev, pt3->regs[1]);
-	pci_release_regions(pdev);
-	pci_disable_device(pdev);
-	kfree(pt3);
-}
-
-static int pt3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	u8 rev;
-	u32 ver;
-	int i, ret;
-	struct pt3_board *pt3;
-	struct i2c_adapter *i2c;
-
-	if (pci_read_config_byte(pdev, PCI_REVISION_ID, &rev) || rev != 1)
-		return -ENODEV;
-
-	ret = pci_enable_device(pdev);
-	if (ret < 0)
-		return -ENODEV;
-	pci_set_master(pdev);
-
-	ret = pci_request_regions(pdev, DRV_NAME);
-	if (ret < 0)
-		goto err_disable_device;
-
-	ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
-	if (ret == 0)
-		dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
-	else {
-		ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
-		if (ret == 0)
-			dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
-		else {
-			dev_err(&pdev->dev, "Failed to set DMA mask\n");
-			goto err_release_regions;
-		}
-		dev_info(&pdev->dev, "Use 32bit DMA\n");
-	}
-
-	pt3 = kzalloc(sizeof(*pt3), GFP_KERNEL);
-	if (!pt3) {
-		ret = -ENOMEM;
-		goto err_release_regions;
-	}
-	pci_set_drvdata(pdev, pt3);
-	pt3->pdev = pdev;
-	mutex_init(&pt3->lock);
-	pt3->regs[0] = pci_ioremap_bar(pdev, 0);
-	pt3->regs[1] = pci_ioremap_bar(pdev, 2);
-	if (pt3->regs[0] == NULL || pt3->regs[1] == NULL) {
-		dev_err(&pdev->dev, "Failed to ioremap\n");
-		ret = -ENOMEM;
-		goto err_kfree;
-	}
-
-	ver = ioread32(pt3->regs[0] + REG_VERSION);
-	if ((ver >> 16) != 0x0301) {
-		dev_warn(&pdev->dev, "PT%d, I/F-ver.:%d not supported\n",
-			 ver >> 24, (ver & 0x00ff0000) >> 16);
-		ret = -ENODEV;
-		goto err_iounmap;
-	}
-
-	pt3->num_bufs = clamp_val(num_bufs, MIN_DATA_BUFS, MAX_DATA_BUFS);
-
-	pt3->i2c_buf = kmalloc(sizeof(*pt3->i2c_buf), GFP_KERNEL);
-	if (pt3->i2c_buf == NULL) {
-		ret = -ENOMEM;
-		goto err_iounmap;
-	}
-	i2c = &pt3->i2c_adap;
-	i2c->owner = THIS_MODULE;
-	i2c->algo = &pt3_i2c_algo;
-	i2c->algo_data = NULL;
-	i2c->dev.parent = &pdev->dev;
-	strlcpy(i2c->name, DRV_NAME, sizeof(i2c->name));
-	i2c_set_adapdata(i2c, pt3);
-	ret = i2c_add_adapter(i2c);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Failed to add i2c adapter\n");
-		goto err_i2cbuf;
-	}
-
-	for (i = 0; i < PT3_NUM_FE; i++) {
-		ret = pt3_alloc_adapter(pt3, i);
-		if (ret < 0)
-			break;
-
-		ret = pt3_attach_fe(pt3, i);
-		if (ret < 0)
-			break;
-	}
-	if (i < PT3_NUM_FE) {
-		dev_err(&pdev->dev, "Failed to create FE%d\n", i);
-		goto err_cleanup_adapters;
-	}
-
-	ret = pt3_fe_init(pt3);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Failed to init frontends\n");
-		i = PT3_NUM_FE - 1;
-		goto err_cleanup_adapters;
-	}
-
-	dev_info(&pdev->dev,
-		 "successfully init'ed PT%d (fw:0x%02x, I/F:0x%02x)\n",
-		 ver >> 24, (ver >> 8) & 0xff, (ver >> 16) & 0xff);
-	return 0;
-
-err_cleanup_adapters:
-	while (i >= 0)
-		pt3_cleanup_adapter(pt3, i--);
-	i2c_del_adapter(i2c);
-err_i2cbuf:
-	kfree(pt3->i2c_buf);
-err_iounmap:
-	if (pt3->regs[0])
-		pci_iounmap(pdev, pt3->regs[0]);
-	if (pt3->regs[1])
-		pci_iounmap(pdev, pt3->regs[1]);
-err_kfree:
-	kfree(pt3);
-err_release_regions:
-	pci_release_regions(pdev);
-err_disable_device:
-	pci_disable_device(pdev);
-	return ret;
-
-}
-
-static const struct pci_device_id pt3_id_table[] = {
-	{ PCI_DEVICE_SUB(0x1172, 0x4c15, 0xee8d, 0x0368) },
-	{ },
-};
-MODULE_DEVICE_TABLE(pci, pt3_id_table);
-
-static SIMPLE_DEV_PM_OPS(pt3_pm_ops, pt3_suspend, pt3_resume);
-
-static struct pci_driver pt3_driver = {
-	.name		= DRV_NAME,
-	.probe		= pt3_probe,
-	.remove		= pt3_remove,
-	.id_table	= pt3_id_table,
-
-	.driver.pm	= &pt3_pm_ops,
-};
-
-module_pci_driver(pt3_driver);
-
-MODULE_DESCRIPTION("Earthsoft PT3 Driver");
-MODULE_AUTHOR("Akihiro TSUKADA");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/pt3/pt3.h b/drivers/media/pci/pt3/pt3.h
deleted file mode 100644
index 1b3f2ad..0000000
--- a/drivers/media/pci/pt3/pt3.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Earthsoft PT3 driver
- *
- * Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com>
- *
- * 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.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef PT3_H
-#define PT3_H
-
-#include <linux/atomic.h>
-#include <linux/types.h>
-
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dmxdev.h"
-
-#include "tc90522.h"
-#include "mxl301rf.h"
-#include "qm1d1c0042.h"
-
-#define DRV_NAME KBUILD_MODNAME
-
-#define PT3_NUM_FE 4
-
-/*
- * register index of the FPGA chip
- */
-#define REG_VERSION	0x00
-#define REG_BUS		0x04
-#define REG_SYSTEM_W	0x08
-#define REG_SYSTEM_R	0x0c
-#define REG_I2C_W	0x10
-#define REG_I2C_R	0x14
-#define REG_RAM_W	0x18
-#define REG_RAM_R	0x1c
-#define REG_DMA_BASE	0x40	/* regs for FE[i] = REG_DMA_BASE + 0x18 * i */
-#define OFST_DMA_DESC_L	0x00
-#define OFST_DMA_DESC_H	0x04
-#define OFST_DMA_CTL	0x08
-#define OFST_TS_CTL	0x0c
-#define OFST_STATUS	0x10
-#define OFST_TS_ERR	0x14
-
-/*
- * internal buffer for I2C
- */
-#define PT3_I2C_MAX 4091
-struct pt3_i2cbuf {
-	u8  data[PT3_I2C_MAX];
-	u8  tmp;
-	u32 num_cmds;
-};
-
-/*
- * DMA things
- */
-#define TS_PACKET_SZ  188
-/* DMA transfers must not cross 4GiB, so use one page / transfer */
-#define DATA_XFER_SZ   4096
-#define DATA_BUF_XFERS 47
-/* (num_bufs * DATA_BUF_SZ) % TS_PACKET_SZ must be 0 */
-#define DATA_BUF_SZ    (DATA_BUF_XFERS * DATA_XFER_SZ)
-#define MAX_DATA_BUFS  16
-#define MIN_DATA_BUFS   2
-
-#define DESCS_IN_PAGE (PAGE_SIZE / sizeof(struct xfer_desc))
-#define MAX_NUM_XFERS (MAX_DATA_BUFS * DATA_BUF_XFERS)
-#define MAX_DESC_BUFS DIV_ROUND_UP(MAX_NUM_XFERS, DESCS_IN_PAGE)
-
-/* DMA transfer description.
- * device is passed a pointer to this struct, dma-reads it,
- * and gets the DMA buffer ring for storing TS data.
- */
-struct xfer_desc {
-	u32 addr_l; /* bus address of target data buffer */
-	u32 addr_h;
-	u32 size;
-	u32 next_l; /* bus adddress of the next xfer_desc */
-	u32 next_h;
-};
-
-/* A DMA mapping of a page containing xfer_desc's */
-struct xfer_desc_buffer {
-	dma_addr_t b_addr;
-	struct xfer_desc *descs; /* PAGE_SIZE (xfer_desc[DESCS_IN_PAGE]) */
-};
-
-/* A DMA mapping of a data buffer */
-struct dma_data_buffer {
-	dma_addr_t b_addr;
-	u8 *data; /* size: u8[PAGE_SIZE] */
-};
-
-/*
- * device things
- */
-struct pt3_adap_config {
-	struct i2c_board_info demod_info;
-	struct tc90522_config demod_cfg;
-
-	struct i2c_board_info tuner_info;
-	union tuner_config {
-		struct qm1d1c0042_config qm1d1c0042;
-		struct mxl301rf_config   mxl301rf;
-	} tuner_cfg;
-	u32 init_freq;
-};
-
-struct pt3_adapter {
-	struct dvb_adapter  dvb_adap;  /* dvb_adap.priv => struct pt3_board */
-	int adap_idx;
-
-	struct dvb_demux    demux;
-	struct dmxdev       dmxdev;
-	struct dvb_frontend *fe;
-	struct i2c_client   *i2c_demod;
-	struct i2c_client   *i2c_tuner;
-
-	/* data fetch thread */
-	struct task_struct *thread;
-	int num_feeds;
-
-	bool cur_lna;
-	bool cur_lnb; /* current LNB power status (on/off) */
-
-	/* items below are for DMA */
-	struct dma_data_buffer buffer[MAX_DATA_BUFS];
-	int buf_idx;
-	int buf_ofs;
-	int num_bufs;  /* == pt3_board->num_bufs */
-	int num_discard; /* how many access units to discard initially */
-
-	struct xfer_desc_buffer desc_buf[MAX_DESC_BUFS];
-	int num_desc_bufs;  /* == num_bufs * DATA_BUF_XFERS / DESCS_IN_PAGE */
-};
-
-
-struct pt3_board {
-	struct pci_dev *pdev;
-	void __iomem *regs[2];
-	/* regs[0]: registers, regs[1]: internal memory, used for I2C */
-
-	struct mutex lock;
-
-	/* LNB power shared among sat-FEs */
-	int lnb_on_cnt; /* LNB power on count */
-
-	/* LNA shared among terr-FEs */
-	int lna_on_cnt; /* booster enabled count */
-
-	int num_bufs;  /* number of DMA buffers allocated/mapped per FE */
-
-	struct i2c_adapter i2c_adap;
-	struct pt3_i2cbuf *i2c_buf;
-
-	struct pt3_adapter *adaps[PT3_NUM_FE];
-};
-
-
-/*
- * prototypes
- */
-extern int  pt3_alloc_dmabuf(struct pt3_adapter *adap);
-extern void pt3_init_dmabuf(struct pt3_adapter *adap);
-extern void pt3_free_dmabuf(struct pt3_adapter *adap);
-extern int  pt3_start_dma(struct pt3_adapter *adap);
-extern int  pt3_stop_dma(struct pt3_adapter *adap);
-extern int  pt3_proc_dma(struct pt3_adapter *adap);
-
-extern int  pt3_i2c_master_xfer(struct i2c_adapter *adap,
-				struct i2c_msg *msgs, int num);
-extern u32  pt3_i2c_functionality(struct i2c_adapter *adap);
-extern void pt3_i2c_reset(struct pt3_board *pt3);
-extern int  pt3_init_all_demods(struct pt3_board *pt3);
-extern int  pt3_init_all_mxl301rf(struct pt3_board *pt3);
-#endif /* PT3_H */
diff --git a/drivers/media/pci/pt3/pt3_dma.c b/drivers/media/pci/pt3/pt3_dma.c
deleted file mode 100644
index f0ce904..0000000
--- a/drivers/media/pci/pt3/pt3_dma.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Earthsoft PT3 driver
- *
- * Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com>
- *
- * 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.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#include <linux/dma-mapping.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-
-#include "pt3.h"
-
-#define PT3_ACCESS_UNIT (TS_PACKET_SZ * 128)
-#define PT3_BUF_CANARY  (0x74)
-
-static u32 get_dma_base(int idx)
-{
-	int i;
-
-	i = (idx == 1 || idx == 2) ? 3 - idx : idx;
-	return REG_DMA_BASE + 0x18 * i;
-}
-
-int pt3_stop_dma(struct pt3_adapter *adap)
-{
-	struct pt3_board *pt3 = adap->dvb_adap.priv;
-	u32 base;
-	u32 stat;
-	int retry;
-
-	base = get_dma_base(adap->adap_idx);
-	stat = ioread32(pt3->regs[0] + base + OFST_STATUS);
-	if (!(stat & 0x01))
-		return 0;
-
-	iowrite32(0x02, pt3->regs[0] + base + OFST_DMA_CTL);
-	for (retry = 0; retry < 5; retry++) {
-		stat = ioread32(pt3->regs[0] + base + OFST_STATUS);
-		if (!(stat & 0x01))
-			return 0;
-		msleep(50);
-	}
-	return -EIO;
-}
-
-int pt3_start_dma(struct pt3_adapter *adap)
-{
-	struct pt3_board *pt3 = adap->dvb_adap.priv;
-	u32 base = get_dma_base(adap->adap_idx);
-
-	iowrite32(0x02, pt3->regs[0] + base + OFST_DMA_CTL);
-	iowrite32(lower_32_bits(adap->desc_buf[0].b_addr),
-			pt3->regs[0] + base + OFST_DMA_DESC_L);
-	iowrite32(upper_32_bits(adap->desc_buf[0].b_addr),
-			pt3->regs[0] + base + OFST_DMA_DESC_H);
-	iowrite32(0x01, pt3->regs[0] + base + OFST_DMA_CTL);
-	return 0;
-}
-
-
-static u8 *next_unit(struct pt3_adapter *adap, int *idx, int *ofs)
-{
-	*ofs += PT3_ACCESS_UNIT;
-	if (*ofs >= DATA_BUF_SZ) {
-		*ofs -= DATA_BUF_SZ;
-		(*idx)++;
-		if (*idx == adap->num_bufs)
-			*idx = 0;
-	}
-	return &adap->buffer[*idx].data[*ofs];
-}
-
-int pt3_proc_dma(struct pt3_adapter *adap)
-{
-	int idx, ofs;
-
-	idx = adap->buf_idx;
-	ofs = adap->buf_ofs;
-
-	if (adap->buffer[idx].data[ofs] == PT3_BUF_CANARY)
-		return 0;
-
-	while (*next_unit(adap, &idx, &ofs) != PT3_BUF_CANARY) {
-		u8 *p;
-
-		p = &adap->buffer[adap->buf_idx].data[adap->buf_ofs];
-		if (adap->num_discard > 0)
-			adap->num_discard--;
-		else if (adap->buf_ofs + PT3_ACCESS_UNIT > DATA_BUF_SZ) {
-			dvb_dmx_swfilter_packets(&adap->demux, p,
-				(DATA_BUF_SZ - adap->buf_ofs) / TS_PACKET_SZ);
-			dvb_dmx_swfilter_packets(&adap->demux,
-				adap->buffer[idx].data, ofs / TS_PACKET_SZ);
-		} else
-			dvb_dmx_swfilter_packets(&adap->demux, p,
-				PT3_ACCESS_UNIT / TS_PACKET_SZ);
-
-		*p = PT3_BUF_CANARY;
-		adap->buf_idx = idx;
-		adap->buf_ofs = ofs;
-	}
-	return 0;
-}
-
-void pt3_init_dmabuf(struct pt3_adapter *adap)
-{
-	int idx, ofs;
-	u8 *p;
-
-	idx = 0;
-	ofs = 0;
-	p = adap->buffer[0].data;
-	/* mark the whole buffers as "not written yet" */
-	while (idx < adap->num_bufs) {
-		p[ofs] = PT3_BUF_CANARY;
-		ofs += PT3_ACCESS_UNIT;
-		if (ofs >= DATA_BUF_SZ) {
-			ofs -= DATA_BUF_SZ;
-			idx++;
-			p = adap->buffer[idx].data;
-		}
-	}
-	adap->buf_idx = 0;
-	adap->buf_ofs = 0;
-}
-
-void pt3_free_dmabuf(struct pt3_adapter *adap)
-{
-	struct pt3_board *pt3;
-	int i;
-
-	pt3 = adap->dvb_adap.priv;
-	for (i = 0; i < adap->num_bufs; i++)
-		dma_free_coherent(&pt3->pdev->dev, DATA_BUF_SZ,
-			adap->buffer[i].data, adap->buffer[i].b_addr);
-	adap->num_bufs = 0;
-
-	for (i = 0; i < adap->num_desc_bufs; i++)
-		dma_free_coherent(&pt3->pdev->dev, PAGE_SIZE,
-			adap->desc_buf[i].descs, adap->desc_buf[i].b_addr);
-	adap->num_desc_bufs = 0;
-}
-
-
-int pt3_alloc_dmabuf(struct pt3_adapter *adap)
-{
-	struct pt3_board *pt3;
-	void *p;
-	int i, j;
-	int idx, ofs;
-	int num_desc_bufs;
-	dma_addr_t data_addr, desc_addr;
-	struct xfer_desc *d;
-
-	pt3 = adap->dvb_adap.priv;
-	adap->num_bufs = 0;
-	adap->num_desc_bufs = 0;
-	for (i = 0; i < pt3->num_bufs; i++) {
-		p = dma_alloc_coherent(&pt3->pdev->dev, DATA_BUF_SZ,
-					&adap->buffer[i].b_addr, GFP_KERNEL);
-		if (p == NULL)
-			goto failed;
-		adap->buffer[i].data = p;
-		adap->num_bufs++;
-	}
-	pt3_init_dmabuf(adap);
-
-	/* build circular-linked pointers (xfer_desc) to the data buffers*/
-	idx = 0;
-	ofs = 0;
-	num_desc_bufs =
-		DIV_ROUND_UP(adap->num_bufs * DATA_BUF_XFERS, DESCS_IN_PAGE);
-	for (i = 0; i < num_desc_bufs; i++) {
-		p = dma_alloc_coherent(&pt3->pdev->dev, PAGE_SIZE,
-					&desc_addr, GFP_KERNEL);
-		if (p == NULL)
-			goto failed;
-		adap->num_desc_bufs++;
-		adap->desc_buf[i].descs = p;
-		adap->desc_buf[i].b_addr = desc_addr;
-
-		if (i > 0) {
-			d = &adap->desc_buf[i - 1].descs[DESCS_IN_PAGE - 1];
-			d->next_l = lower_32_bits(desc_addr);
-			d->next_h = upper_32_bits(desc_addr);
-		}
-		for (j = 0; j < DESCS_IN_PAGE; j++) {
-			data_addr = adap->buffer[idx].b_addr + ofs;
-			d = &adap->desc_buf[i].descs[j];
-			d->addr_l = lower_32_bits(data_addr);
-			d->addr_h = upper_32_bits(data_addr);
-			d->size = DATA_XFER_SZ;
-
-			desc_addr += sizeof(struct xfer_desc);
-			d->next_l = lower_32_bits(desc_addr);
-			d->next_h = upper_32_bits(desc_addr);
-
-			ofs += DATA_XFER_SZ;
-			if (ofs >= DATA_BUF_SZ) {
-				ofs -= DATA_BUF_SZ;
-				idx++;
-				if (idx >= adap->num_bufs) {
-					desc_addr = adap->desc_buf[0].b_addr;
-					d->next_l = lower_32_bits(desc_addr);
-					d->next_h = upper_32_bits(desc_addr);
-					return 0;
-				}
-			}
-		}
-	}
-	return 0;
-
-failed:
-	pt3_free_dmabuf(adap);
-	return -ENOMEM;
-}
diff --git a/drivers/media/pci/pt3/pt3_i2c.c b/drivers/media/pci/pt3/pt3_i2c.c
deleted file mode 100644
index ec6a8a2..0000000
--- a/drivers/media/pci/pt3/pt3_i2c.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Earthsoft PT3 driver
- *
- * Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com>
- *
- * 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.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/i2c.h>
-#include <linux/io.h>
-#include <linux/pci.h>
-
-#include "pt3.h"
-
-#define PT3_I2C_BASE  2048
-#define PT3_CMD_ADDR_NORMAL 0
-#define PT3_CMD_ADDR_INIT_DEMOD  4096
-#define PT3_CMD_ADDR_INIT_TUNER  (4096 + 2042)
-
-/* masks for I2C status register */
-#define STAT_SEQ_RUNNING 0x1
-#define STAT_SEQ_ERROR   0x6
-#define STAT_NO_SEQ      0x8
-
-#define PT3_I2C_RUN   (1 << 16)
-#define PT3_I2C_RESET (1 << 17)
-
-enum ctl_cmd {
-	I_END,
-	I_ADDRESS,
-	I_CLOCK_L,
-	I_CLOCK_H,
-	I_DATA_L,
-	I_DATA_H,
-	I_RESET,
-	I_SLEEP,
-	I_DATA_L_NOP  = 0x08,
-	I_DATA_H_NOP  = 0x0c,
-	I_DATA_H_READ = 0x0d,
-	I_DATA_H_ACK0 = 0x0e,
-	I_DATA_H_ACK1 = 0x0f,
-};
-
-
-static void cmdbuf_add(struct pt3_i2cbuf *cbuf, enum ctl_cmd cmd)
-{
-	int buf_idx;
-
-	if ((cbuf->num_cmds % 2) == 0)
-		cbuf->tmp = cmd;
-	else {
-		cbuf->tmp |= cmd << 4;
-		buf_idx = cbuf->num_cmds / 2;
-		if (buf_idx < ARRAY_SIZE(cbuf->data))
-			cbuf->data[buf_idx] = cbuf->tmp;
-	}
-	cbuf->num_cmds++;
-}
-
-static void put_end(struct pt3_i2cbuf *cbuf)
-{
-	cmdbuf_add(cbuf, I_END);
-	if (cbuf->num_cmds % 2)
-		cmdbuf_add(cbuf, I_END);
-}
-
-static void put_start(struct pt3_i2cbuf *cbuf)
-{
-	cmdbuf_add(cbuf, I_DATA_H);
-	cmdbuf_add(cbuf, I_CLOCK_H);
-	cmdbuf_add(cbuf, I_DATA_L);
-	cmdbuf_add(cbuf, I_CLOCK_L);
-}
-
-static void put_byte_write(struct pt3_i2cbuf *cbuf, u8 val)
-{
-	u8 mask;
-
-	mask = 0x80;
-	for (mask = 0x80; mask > 0; mask >>= 1)
-		cmdbuf_add(cbuf, (val & mask) ? I_DATA_H_NOP : I_DATA_L_NOP);
-	cmdbuf_add(cbuf, I_DATA_H_ACK0);
-}
-
-static void put_byte_read(struct pt3_i2cbuf *cbuf, u32 size)
-{
-	int i, j;
-
-	for (i = 0; i < size; i++) {
-		for (j = 0; j < 8; j++)
-			cmdbuf_add(cbuf, I_DATA_H_READ);
-		cmdbuf_add(cbuf, (i == size - 1) ? I_DATA_H_NOP : I_DATA_L_NOP);
-	}
-}
-
-static void put_stop(struct pt3_i2cbuf *cbuf)
-{
-	cmdbuf_add(cbuf, I_DATA_L);
-	cmdbuf_add(cbuf, I_CLOCK_H);
-	cmdbuf_add(cbuf, I_DATA_H);
-}
-
-
-/* translates msgs to internal commands for bit-banging */
-static void translate(struct pt3_i2cbuf *cbuf, struct i2c_msg *msgs, int num)
-{
-	int i, j;
-	bool rd;
-
-	cbuf->num_cmds = 0;
-	for (i = 0; i < num; i++) {
-		rd = !!(msgs[i].flags & I2C_M_RD);
-		put_start(cbuf);
-		put_byte_write(cbuf, msgs[i].addr << 1 | rd);
-		if (rd)
-			put_byte_read(cbuf, msgs[i].len);
-		else
-			for (j = 0; j < msgs[i].len; j++)
-				put_byte_write(cbuf, msgs[i].buf[j]);
-	}
-	if (num > 0) {
-		put_stop(cbuf);
-		put_end(cbuf);
-	}
-}
-
-static int wait_i2c_result(struct pt3_board *pt3, u32 *result, int max_wait)
-{
-	int i;
-	u32 v;
-
-	for (i = 0; i < max_wait; i++) {
-		v = ioread32(pt3->regs[0] + REG_I2C_R);
-		if (!(v & STAT_SEQ_RUNNING))
-			break;
-		usleep_range(500, 750);
-	}
-	if (i >= max_wait)
-		return -EIO;
-	if (result)
-		*result = v;
-	return 0;
-}
-
-/* send [pre-]translated i2c msgs stored at addr */
-static int send_i2c_cmd(struct pt3_board *pt3, u32 addr)
-{
-	u32 ret;
-
-	/* make sure that previous transactions had finished */
-	if (wait_i2c_result(pt3, NULL, 50)) {
-		dev_warn(&pt3->pdev->dev, "(%s) prev. transaction stalled\n",
-				__func__);
-		return -EIO;
-	}
-
-	iowrite32(PT3_I2C_RUN | addr, pt3->regs[0] + REG_I2C_W);
-	usleep_range(200, 300);
-	/* wait for the current transaction to finish */
-	if (wait_i2c_result(pt3, &ret, 500) || (ret & STAT_SEQ_ERROR)) {
-		dev_warn(&pt3->pdev->dev, "(%s) failed.\n", __func__);
-		return -EIO;
-	}
-	return 0;
-}
-
-
-/* init commands for each demod are combined into one transaction
- *  and hidden in ROM with the address PT3_CMD_ADDR_INIT_DEMOD.
- */
-int  pt3_init_all_demods(struct pt3_board *pt3)
-{
-	ioread32(pt3->regs[0] + REG_I2C_R);
-	return send_i2c_cmd(pt3, PT3_CMD_ADDR_INIT_DEMOD);
-}
-
-/* init commands for two ISDB-T tuners are hidden in ROM. */
-int  pt3_init_all_mxl301rf(struct pt3_board *pt3)
-{
-	usleep_range(1000, 2000);
-	return send_i2c_cmd(pt3, PT3_CMD_ADDR_INIT_TUNER);
-}
-
-void pt3_i2c_reset(struct pt3_board *pt3)
-{
-	iowrite32(PT3_I2C_RESET, pt3->regs[0] + REG_I2C_W);
-}
-
-/*
- * I2C algorithm
- */
-int
-pt3_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
-{
-	struct pt3_board *pt3;
-	struct pt3_i2cbuf *cbuf;
-	int i;
-	void __iomem *p;
-
-	pt3 = i2c_get_adapdata(adap);
-	cbuf = pt3->i2c_buf;
-
-	for (i = 0; i < num; i++)
-		if (msgs[i].flags & I2C_M_RECV_LEN) {
-			dev_warn(&pt3->pdev->dev,
-				"(%s) I2C_M_RECV_LEN not supported.\n",
-				__func__);
-			return -EINVAL;
-		}
-
-	translate(cbuf, msgs, num);
-	memcpy_toio(pt3->regs[1] + PT3_I2C_BASE + PT3_CMD_ADDR_NORMAL / 2,
-			cbuf->data, cbuf->num_cmds);
-
-	if (send_i2c_cmd(pt3, PT3_CMD_ADDR_NORMAL) < 0)
-		return -EIO;
-
-	p = pt3->regs[1] + PT3_I2C_BASE;
-	for (i = 0; i < num; i++)
-		if ((msgs[i].flags & I2C_M_RD) && msgs[i].len > 0) {
-			memcpy_fromio(msgs[i].buf, p, msgs[i].len);
-			p += msgs[i].len;
-		}
-
-	return num;
-}
-
-u32 pt3_i2c_functionality(struct i2c_adapter *adap)
-{
-	return I2C_FUNC_I2C;
-}
diff --git a/drivers/media/tuners/mxl301rf.c b/drivers/media/tuners/mxl301rf.c
deleted file mode 100644
index 1575a5d..0000000
--- a/drivers/media/tuners/mxl301rf.c
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * MaxLinear MxL301RF OFDM tuner driver
- *
- * Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com>
- *
- * 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.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-/*
- * NOTICE:
- * This driver is incomplete and lacks init/config of the chips,
- * as the necessary info is not disclosed.
- * Other features like get_if_frequency() are missing as well.
- * It assumes that users of this driver (such as a PCI bridge of
- * DTV receiver cards) properly init and configure the chip
- * via I2C *before* calling this driver's init() function.
- *
- * Currently, PT3 driver is the only one that uses this driver,
- * and contains init/config code in its firmware.
- * Thus some part of the code might be dependent on PT3 specific config.
- */
-
-#include <linux/kernel.h>
-#include "mxl301rf.h"
-
-struct mxl301rf_state {
-	struct mxl301rf_config cfg;
-	struct i2c_client *i2c;
-};
-
-static struct mxl301rf_state *cfg_to_state(struct mxl301rf_config *c)
-{
-	return container_of(c, struct mxl301rf_state, cfg);
-}
-
-static int raw_write(struct mxl301rf_state *state, const u8 *buf, int len)
-{
-	int ret;
-
-	ret = i2c_master_send(state->i2c, buf, len);
-	if (ret >= 0 && ret < len)
-		ret = -EIO;
-	return (ret == len) ? 0 : ret;
-}
-
-static int reg_write(struct mxl301rf_state *state, u8 reg, u8 val)
-{
-	u8 buf[2] = { reg, val };
-
-	return raw_write(state, buf, 2);
-}
-
-static int reg_read(struct mxl301rf_state *state, u8 reg, u8 *val)
-{
-	u8 wbuf[2] = { 0xfb, reg };
-	int ret;
-
-	ret = raw_write(state, wbuf, sizeof(wbuf));
-	if (ret == 0)
-		ret = i2c_master_recv(state->i2c, val, 1);
-	if (ret >= 0 && ret < 1)
-		ret = -EIO;
-	return (ret == 1) ? 0 : ret;
-}
-
-/* tuner_ops */
-
-/* get RSSI and update propery cache, set to *out in % */
-static int mxl301rf_get_rf_strength(struct dvb_frontend *fe, u16 *out)
-{
-	struct mxl301rf_state *state;
-	int ret;
-	u8  rf_in1, rf_in2, rf_off1, rf_off2;
-	u16 rf_in, rf_off;
-	s64 level;
-	struct dtv_fe_stats *rssi;
-
-	rssi = &fe->dtv_property_cache.strength;
-	rssi->len = 1;
-	rssi->stat[0].scale = FE_SCALE_NOT_AVAILABLE;
-	*out = 0;
-
-	state = fe->tuner_priv;
-	ret = reg_write(state, 0x14, 0x01);
-	if (ret < 0)
-		return ret;
-	usleep_range(1000, 2000);
-
-	ret = reg_read(state, 0x18, &rf_in1);
-	if (ret == 0)
-		ret = reg_read(state, 0x19, &rf_in2);
-	if (ret == 0)
-		ret = reg_read(state, 0xd6, &rf_off1);
-	if (ret == 0)
-		ret = reg_read(state, 0xd7, &rf_off2);
-	if (ret != 0)
-		return ret;
-
-	rf_in = (rf_in2 & 0x07) << 8 | rf_in1;
-	rf_off = (rf_off2 & 0x0f) << 5 | (rf_off1 >> 3);
-	level = rf_in - rf_off - (113 << 3); /* x8 dBm */
-	level = level * 1000 / 8;
-	rssi->stat[0].svalue = level;
-	rssi->stat[0].scale = FE_SCALE_DECIBEL;
-	/* *out = (level - min) * 100 / (max - min) */
-	*out = (rf_in - rf_off + (1 << 9) - 1) * 100 / ((5 << 9) - 2);
-	return 0;
-}
-
-/* spur shift parameters */
-struct shf {
-	u32	freq;		/* Channel center frequency */
-	u32	ofst_th;	/* Offset frequency threshold */
-	u8	shf_val;	/* Spur shift value */
-	u8	shf_dir;	/* Spur shift direction */
-};
-
-static const struct shf shf_tab[] = {
-	{  64500, 500, 0x92, 0x07 },
-	{ 191500, 300, 0xe2, 0x07 },
-	{ 205500, 500, 0x2c, 0x04 },
-	{ 212500, 500, 0x1e, 0x04 },
-	{ 226500, 500, 0xd4, 0x07 },
-	{  99143, 500, 0x9c, 0x07 },
-	{ 173143, 500, 0xd4, 0x07 },
-	{ 191143, 300, 0xd4, 0x07 },
-	{ 207143, 500, 0xce, 0x07 },
-	{ 225143, 500, 0xce, 0x07 },
-	{ 243143, 500, 0xd4, 0x07 },
-	{ 261143, 500, 0xd4, 0x07 },
-	{ 291143, 500, 0xd4, 0x07 },
-	{ 339143, 500, 0x2c, 0x04 },
-	{ 117143, 500, 0x7a, 0x07 },
-	{ 135143, 300, 0x7a, 0x07 },
-	{ 153143, 500, 0x01, 0x07 }
-};
-
-struct reg_val {
-	u8 reg;
-	u8 val;
-} __attribute__ ((__packed__));
-
-static const struct reg_val set_idac[] = {
-	{ 0x0d, 0x00 },
-	{ 0x0c, 0x67 },
-	{ 0x6f, 0x89 },
-	{ 0x70, 0x0c },
-	{ 0x6f, 0x8a },
-	{ 0x70, 0x0e },
-	{ 0x6f, 0x8b },
-	{ 0x70, 0x1c },
-};
-
-static int mxl301rf_set_params(struct dvb_frontend *fe)
-{
-	struct reg_val tune0[] = {
-		{ 0x13, 0x00 },		/* abort tuning */
-		{ 0x3b, 0xc0 },
-		{ 0x3b, 0x80 },
-		{ 0x10, 0x95 },		/* BW */
-		{ 0x1a, 0x05 },
-		{ 0x61, 0x00 },		/* spur shift value (placeholder) */
-		{ 0x62, 0xa0 }		/* spur shift direction (placeholder) */
-	};
-
-	struct reg_val tune1[] = {
-		{ 0x11, 0x40 },		/* RF frequency L (placeholder) */
-		{ 0x12, 0x0e },		/* RF frequency H (placeholder) */
-		{ 0x13, 0x01 }		/* start tune */
-	};
-
-	struct mxl301rf_state *state;
-	u32 freq;
-	u16 f;
-	u32 tmp, div;
-	int i, ret;
-
-	state = fe->tuner_priv;
-	freq = fe->dtv_property_cache.frequency;
-
-	/* spur shift function (for analog) */
-	for (i = 0; i < ARRAY_SIZE(shf_tab); i++) {
-		if (freq >= (shf_tab[i].freq - shf_tab[i].ofst_th) * 1000 &&
-		    freq <= (shf_tab[i].freq + shf_tab[i].ofst_th) * 1000) {
-			tune0[5].val = shf_tab[i].shf_val;
-			tune0[6].val = 0xa0 | shf_tab[i].shf_dir;
-			break;
-		}
-	}
-	ret = raw_write(state, (u8 *) tune0, sizeof(tune0));
-	if (ret < 0)
-		goto failed;
-	usleep_range(3000, 4000);
-
-	/* convert freq to 10.6 fixed point float [MHz] */
-	f = freq / 1000000;
-	tmp = freq % 1000000;
-	div = 1000000;
-	for (i = 0; i < 6; i++) {
-		f <<= 1;
-		div >>= 1;
-		if (tmp > div) {
-			tmp -= div;
-			f |= 1;
-		}
-	}
-	if (tmp > 7812)
-		f++;
-	tune1[0].val = f & 0xff;
-	tune1[1].val = f >> 8;
-	ret = raw_write(state, (u8 *) tune1, sizeof(tune1));
-	if (ret < 0)
-		goto failed;
-	msleep(31);
-
-	ret = reg_write(state, 0x1a, 0x0d);
-	if (ret < 0)
-		goto failed;
-	ret = raw_write(state, (u8 *) set_idac, sizeof(set_idac));
-	if (ret < 0)
-		goto failed;
-	return 0;
-
-failed:
-	dev_warn(&state->i2c->dev, "(%s) failed. [adap%d-fe%d]\n",
-		__func__, fe->dvb->num, fe->id);
-	return ret;
-}
-
-static const struct reg_val standby_data[] = {
-	{ 0x01, 0x00 },
-	{ 0x13, 0x00 }
-};
-
-static int mxl301rf_sleep(struct dvb_frontend *fe)
-{
-	struct mxl301rf_state *state;
-	int ret;
-
-	state = fe->tuner_priv;
-	ret = raw_write(state, (u8 *)standby_data, sizeof(standby_data));
-	if (ret < 0)
-		dev_warn(&state->i2c->dev, "(%s) failed. [adap%d-fe%d]\n",
-			__func__, fe->dvb->num, fe->id);
-	return ret;
-}
-
-
-/* init sequence is not public.
- * the parent must have init'ed the device.
- * just wake up here.
- */
-static int mxl301rf_init(struct dvb_frontend *fe)
-{
-	struct mxl301rf_state *state;
-	int ret;
-
-	state = fe->tuner_priv;
-
-	ret = reg_write(state, 0x01, 0x01);
-	if (ret < 0) {
-		dev_warn(&state->i2c->dev, "(%s) failed. [adap%d-fe%d]\n",
-			 __func__, fe->dvb->num, fe->id);
-		return ret;
-	}
-	return 0;
-}
-
-/* I2C driver functions */
-
-static const struct dvb_tuner_ops mxl301rf_ops = {
-	.info = {
-		.name = "MaxLinear MxL301RF",
-
-		.frequency_min =  93000000,
-		.frequency_max = 803142857,
-	},
-
-	.init = mxl301rf_init,
-	.sleep = mxl301rf_sleep,
-
-	.set_params = mxl301rf_set_params,
-	.get_rf_strength = mxl301rf_get_rf_strength,
-};
-
-
-static int mxl301rf_probe(struct i2c_client *client,
-			  const struct i2c_device_id *id)
-{
-	struct mxl301rf_state *state;
-	struct mxl301rf_config *cfg;
-	struct dvb_frontend *fe;
-
-	state = kzalloc(sizeof(*state), GFP_KERNEL);
-	if (!state)
-		return -ENOMEM;
-
-	state->i2c = client;
-	cfg = client->dev.platform_data;
-
-	memcpy(&state->cfg, cfg, sizeof(state->cfg));
-	fe = cfg->fe;
-	fe->tuner_priv = state;
-	memcpy(&fe->ops.tuner_ops, &mxl301rf_ops, sizeof(mxl301rf_ops));
-
-	i2c_set_clientdata(client, &state->cfg);
-	dev_info(&client->dev, "MaxLinear MxL301RF attached.\n");
-	return 0;
-}
-
-static int mxl301rf_remove(struct i2c_client *client)
-{
-	struct mxl301rf_state *state;
-
-	state = cfg_to_state(i2c_get_clientdata(client));
-	state->cfg.fe->tuner_priv = NULL;
-	kfree(state);
-	return 0;
-}
-
-
-static const struct i2c_device_id mxl301rf_id[] = {
-	{"mxl301rf", 0},
-	{}
-};
-MODULE_DEVICE_TABLE(i2c, mxl301rf_id);
-
-static struct i2c_driver mxl301rf_driver = {
-	.driver = {
-		.name	= "mxl301rf",
-	},
-	.probe		= mxl301rf_probe,
-	.remove		= mxl301rf_remove,
-	.id_table	= mxl301rf_id,
-};
-
-module_i2c_driver(mxl301rf_driver);
-
-MODULE_DESCRIPTION("MaxLinear MXL301RF tuner");
-MODULE_AUTHOR("Akihiro TSUKADA");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/tuners/mxl301rf.h b/drivers/media/tuners/mxl301rf.h
deleted file mode 100644
index 19e6840..0000000
--- a/drivers/media/tuners/mxl301rf.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * MaxLinear MxL301RF OFDM tuner driver
- *
- * Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com>
- *
- * 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.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef MXL301RF_H
-#define MXL301RF_H
-
-#include "dvb_frontend.h"
-
-struct mxl301rf_config {
-	struct dvb_frontend *fe;
-};
-
-#endif /* MXL301RF_H */
diff --git a/drivers/media/tuners/qm1d1c0042.c b/drivers/media/tuners/qm1d1c0042.c
deleted file mode 100644
index 18bc745..0000000
--- a/drivers/media/tuners/qm1d1c0042.c
+++ /dev/null
@@ -1,448 +0,0 @@
-/*
- * Sharp QM1D1C0042 8PSK tuner driver
- *
- * Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com>
- *
- * 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.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-/*
- * NOTICE:
- * As the disclosed information on the chip is very limited,
- * this driver lacks some features, including chip config like IF freq.
- * It assumes that users of this driver (such as a PCI bridge of
- * DTV receiver cards) know the relevant info and
- * configure the chip via I2C if necessary.
- *
- * Currently, PT3 driver is the only one that uses this driver,
- * and contains init/config code in its firmware.
- * Thus some part of the code might be dependent on PT3 specific config.
- */
-
-#include <linux/kernel.h>
-#include <linux/math64.h>
-#include "qm1d1c0042.h"
-
-#define QM1D1C0042_NUM_REGS 0x20
-
-static const u8 reg_initval[QM1D1C0042_NUM_REGS] = {
-	0x48, 0x1c, 0xa0, 0x10, 0xbc, 0xc5, 0x20, 0x33,
-	0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
-	0x00, 0xff, 0xf3, 0x00, 0x2a, 0x64, 0xa6, 0x86,
-	0x8c, 0xcf, 0xb8, 0xf1, 0xa8, 0xf2, 0x89, 0x00
-};
-
-static const struct qm1d1c0042_config default_cfg = {
-	.xtal_freq = 16000,
-	.lpf = 1,
-	.fast_srch = 0,
-	.lpf_wait = 20,
-	.fast_srch_wait = 4,
-	.normal_srch_wait = 15,
-};
-
-struct qm1d1c0042_state {
-	struct qm1d1c0042_config cfg;
-	struct i2c_client *i2c;
-	u8 regs[QM1D1C0042_NUM_REGS];
-};
-
-static struct qm1d1c0042_state *cfg_to_state(struct qm1d1c0042_config *c)
-{
-	return container_of(c, struct qm1d1c0042_state, cfg);
-}
-
-static int reg_write(struct qm1d1c0042_state *state, u8 reg, u8 val)
-{
-	u8 wbuf[2] = { reg, val };
-	int ret;
-
-	ret = i2c_master_send(state->i2c, wbuf, sizeof(wbuf));
-	if (ret >= 0 && ret < sizeof(wbuf))
-		ret = -EIO;
-	return (ret == sizeof(wbuf)) ? 0 : ret;
-}
-
-static int reg_read(struct qm1d1c0042_state *state, u8 reg, u8 *val)
-{
-	struct i2c_msg msgs[2] = {
-		{
-			.addr = state->i2c->addr,
-			.flags = 0,
-			.buf = &reg,
-			.len = 1,
-		},
-		{
-			.addr = state->i2c->addr,
-			.flags = I2C_M_RD,
-			.buf = val,
-			.len = 1,
-		},
-	};
-	int ret;
-
-	ret = i2c_transfer(state->i2c->adapter, msgs, ARRAY_SIZE(msgs));
-	if (ret >= 0 && ret < ARRAY_SIZE(msgs))
-		ret = -EIO;
-	return (ret == ARRAY_SIZE(msgs)) ? 0 : ret;
-}
-
-
-static int qm1d1c0042_set_srch_mode(struct qm1d1c0042_state *state, bool fast)
-{
-	if (fast)
-		state->regs[0x03] |= 0x01; /* set fast search mode */
-	else
-		state->regs[0x03] &= ~0x01 & 0xff;
-
-	return reg_write(state, 0x03, state->regs[0x03]);
-}
-
-static int qm1d1c0042_wakeup(struct qm1d1c0042_state *state)
-{
-	int ret;
-
-	state->regs[0x01] |= 1 << 3;             /* BB_Reg_enable */
-	state->regs[0x01] &= (~(1 << 0)) & 0xff; /* NORMAL (wake-up) */
-	state->regs[0x05] &= (~(1 << 3)) & 0xff; /* pfd_rst NORMAL */
-	ret = reg_write(state, 0x01, state->regs[0x01]);
-	if (ret == 0)
-		ret = reg_write(state, 0x05, state->regs[0x05]);
-
-	if (ret < 0)
-		dev_warn(&state->i2c->dev, "(%s) failed. [adap%d-fe%d]\n",
-			__func__, state->cfg.fe->dvb->num, state->cfg.fe->id);
-	return ret;
-}
-
-/* tuner_ops */
-
-static int qm1d1c0042_set_config(struct dvb_frontend *fe, void *priv_cfg)
-{
-	struct qm1d1c0042_state *state;
-	struct qm1d1c0042_config *cfg;
-
-	state = fe->tuner_priv;
-	cfg = priv_cfg;
-
-	if (cfg->fe)
-		state->cfg.fe = cfg->fe;
-
-	if (cfg->xtal_freq != QM1D1C0042_CFG_XTAL_DFLT)
-		dev_warn(&state->i2c->dev,
-			"(%s) changing xtal_freq not supported. ", __func__);
-	state->cfg.xtal_freq = default_cfg.xtal_freq;
-
-	state->cfg.lpf = cfg->lpf;
-	state->cfg.fast_srch = cfg->fast_srch;
-
-	if (cfg->lpf_wait != QM1D1C0042_CFG_WAIT_DFLT)
-		state->cfg.lpf_wait = cfg->lpf_wait;
-	else
-		state->cfg.lpf_wait = default_cfg.lpf_wait;
-
-	if (cfg->fast_srch_wait != QM1D1C0042_CFG_WAIT_DFLT)
-		state->cfg.fast_srch_wait = cfg->fast_srch_wait;
-	else
-		state->cfg.fast_srch_wait = default_cfg.fast_srch_wait;
-
-	if (cfg->normal_srch_wait != QM1D1C0042_CFG_WAIT_DFLT)
-		state->cfg.normal_srch_wait = cfg->normal_srch_wait;
-	else
-		state->cfg.normal_srch_wait = default_cfg.normal_srch_wait;
-	return 0;
-}
-
-/* divisor, vco_band parameters */
-/*  {maxfreq,  param1(band?), param2(div?) */
-static const u32 conv_table[9][3] = {
-	{ 2151000, 1, 7 },
-	{ 1950000, 1, 6 },
-	{ 1800000, 1, 5 },
-	{ 1600000, 1, 4 },
-	{ 1450000, 1, 3 },
-	{ 1250000, 1, 2 },
-	{ 1200000, 0, 7 },
-	{  975000, 0, 6 },
-	{  950000, 0, 0 }
-};
-
-static int qm1d1c0042_set_params(struct dvb_frontend *fe)
-{
-	struct qm1d1c0042_state *state;
-	u32 freq;
-	int i, ret;
-	u8 val, mask;
-	u32 a, sd;
-	s32 b;
-
-	state = fe->tuner_priv;
-	freq = fe->dtv_property_cache.frequency;
-
-	state->regs[0x08] &= 0xf0;
-	state->regs[0x08] |= 0x09;
-
-	state->regs[0x13] &= 0x9f;
-	state->regs[0x13] |= 0x20;
-
-	/* div2/vco_band */
-	val = state->regs[0x02] & 0x0f;
-	for (i = 0; i < 8; i++)
-		if (freq < conv_table[i][0] && freq >= conv_table[i + 1][0]) {
-			val |= conv_table[i][1] << 7;
-			val |= conv_table[i][2] << 4;
-			break;
-		}
-	ret = reg_write(state, 0x02, val);
-	if (ret < 0)
-		return ret;
-
-	a = (freq + state->cfg.xtal_freq / 2) / state->cfg.xtal_freq;
-
-	state->regs[0x06] &= 0x40;
-	state->regs[0x06] |= (a - 12) / 4;
-	ret = reg_write(state, 0x06, state->regs[0x06]);
-	if (ret < 0)
-		return ret;
-
-	state->regs[0x07] &= 0xf0;
-	state->regs[0x07] |= (a - 4 * ((a - 12) / 4 + 1) - 5) & 0x0f;
-	ret = reg_write(state, 0x07, state->regs[0x07]);
-	if (ret < 0)
-		return ret;
-
-	/* LPF */
-	val = state->regs[0x08];
-	if (state->cfg.lpf) {
-		/* LPF_CLK, LPF_FC */
-		val &= 0xf0;
-		val |= 0x02;
-	}
-	ret = reg_write(state, 0x08, val);
-	if (ret < 0)
-		return ret;
-
-	/*
-	 * b = (freq / state->cfg.xtal_freq - a) << 20;
-	 * sd = b          (b >= 0)
-	 *      1<<22 + b  (b < 0)
-	 */
-	b = (s32)div64_s64(((s64) freq) << 20, state->cfg.xtal_freq)
-			   - (((s64) a) << 20);
-
-	if (b >= 0)
-		sd = b;
-	else
-		sd = (1 << 22) + b;
-
-	state->regs[0x09] &= 0xc0;
-	state->regs[0x09] |= (sd >> 16) & 0x3f;
-	state->regs[0x0a] = (sd >> 8) & 0xff;
-	state->regs[0x0b] = sd & 0xff;
-	ret = reg_write(state, 0x09, state->regs[0x09]);
-	if (ret == 0)
-		ret = reg_write(state, 0x0a, state->regs[0x0a]);
-	if (ret == 0)
-		ret = reg_write(state, 0x0b, state->regs[0x0b]);
-	if (ret != 0)
-		return ret;
-
-	if (!state->cfg.lpf) {
-		/* CSEL_Offset */
-		ret = reg_write(state, 0x13, state->regs[0x13]);
-		if (ret < 0)
-			return ret;
-	}
-
-	/* VCO_TM, LPF_TM */
-	mask = state->cfg.lpf ? 0x3f : 0x7f;
-	val = state->regs[0x0c] & mask;
-	ret = reg_write(state, 0x0c, val);
-	if (ret < 0)
-		return ret;
-	usleep_range(2000, 3000);
-	val = state->regs[0x0c] | ~mask;
-	ret = reg_write(state, 0x0c, val);
-	if (ret < 0)
-		return ret;
-
-	if (state->cfg.lpf)
-		msleep(state->cfg.lpf_wait);
-	else if (state->regs[0x03] & 0x01)
-		msleep(state->cfg.fast_srch_wait);
-	else
-		msleep(state->cfg.normal_srch_wait);
-
-	if (state->cfg.lpf) {
-		/* LPF_FC */
-		ret = reg_write(state, 0x08, 0x09);
-		if (ret < 0)
-			return ret;
-
-		/* CSEL_Offset */
-		ret = reg_write(state, 0x13, state->regs[0x13]);
-		if (ret < 0)
-			return ret;
-	}
-	return 0;
-}
-
-static int qm1d1c0042_sleep(struct dvb_frontend *fe)
-{
-	struct qm1d1c0042_state *state;
-	int ret;
-
-	state = fe->tuner_priv;
-	state->regs[0x01] &= (~(1 << 3)) & 0xff; /* BB_Reg_disable */
-	state->regs[0x01] |= 1 << 0;             /* STDBY */
-	state->regs[0x05] |= 1 << 3;             /* pfd_rst STANDBY */
-	ret = reg_write(state, 0x05, state->regs[0x05]);
-	if (ret == 0)
-		ret = reg_write(state, 0x01, state->regs[0x01]);
-	if (ret < 0)
-		dev_warn(&state->i2c->dev, "(%s) failed. [adap%d-fe%d]\n",
-			__func__, fe->dvb->num, fe->id);
-	return ret;
-}
-
-static int qm1d1c0042_init(struct dvb_frontend *fe)
-{
-	struct qm1d1c0042_state *state;
-	u8 val;
-	int i, ret;
-
-	state = fe->tuner_priv;
-	memcpy(state->regs, reg_initval, sizeof(reg_initval));
-
-	reg_write(state, 0x01, 0x0c);
-	reg_write(state, 0x01, 0x0c);
-
-	ret = reg_write(state, 0x01, 0x0c); /* soft reset on */
-	if (ret < 0)
-		goto failed;
-	usleep_range(2000, 3000);
-
-	val = state->regs[0x01] | 0x10;
-	ret = reg_write(state, 0x01, val); /* soft reset off */
-	if (ret < 0)
-		goto failed;
-
-	/* check ID */
-	ret = reg_read(state, 0x00, &val);
-	if (ret < 0 || val != 0x48)
-		goto failed;
-	usleep_range(2000, 3000);
-
-	state->regs[0x0c] |= 0x40;
-	ret = reg_write(state, 0x0c, state->regs[0x0c]);
-	if (ret < 0)
-		goto failed;
-	msleep(state->cfg.lpf_wait);
-
-	/* set all writable registers */
-	for (i = 1; i <= 0x0c ; i++) {
-		ret = reg_write(state, i, state->regs[i]);
-		if (ret < 0)
-			goto failed;
-	}
-	for (i = 0x11; i < QM1D1C0042_NUM_REGS; i++) {
-		ret = reg_write(state, i, state->regs[i]);
-		if (ret < 0)
-			goto failed;
-	}
-
-	ret = qm1d1c0042_wakeup(state);
-	if (ret < 0)
-		goto failed;
-
-	ret = qm1d1c0042_set_srch_mode(state, state->cfg.fast_srch);
-	if (ret < 0)
-		goto failed;
-
-	return ret;
-
-failed:
-	dev_warn(&state->i2c->dev, "(%s) failed. [adap%d-fe%d]\n",
-		__func__, fe->dvb->num, fe->id);
-	return ret;
-}
-
-/* I2C driver functions */
-
-static const struct dvb_tuner_ops qm1d1c0042_ops = {
-	.info = {
-		.name = "Sharp QM1D1C0042",
-
-		.frequency_min =  950000,
-		.frequency_max = 2150000,
-	},
-
-	.init = qm1d1c0042_init,
-	.sleep = qm1d1c0042_sleep,
-	.set_config = qm1d1c0042_set_config,
-	.set_params = qm1d1c0042_set_params,
-};
-
-
-static int qm1d1c0042_probe(struct i2c_client *client,
-			    const struct i2c_device_id *id)
-{
-	struct qm1d1c0042_state *state;
-	struct qm1d1c0042_config *cfg;
-	struct dvb_frontend *fe;
-
-	state = kzalloc(sizeof(*state), GFP_KERNEL);
-	if (!state)
-		return -ENOMEM;
-	state->i2c = client;
-
-	cfg = client->dev.platform_data;
-	fe = cfg->fe;
-	fe->tuner_priv = state;
-	qm1d1c0042_set_config(fe, cfg);
-	memcpy(&fe->ops.tuner_ops, &qm1d1c0042_ops, sizeof(qm1d1c0042_ops));
-
-	i2c_set_clientdata(client, &state->cfg);
-	dev_info(&client->dev, "Sharp QM1D1C0042 attached.\n");
-	return 0;
-}
-
-static int qm1d1c0042_remove(struct i2c_client *client)
-{
-	struct qm1d1c0042_state *state;
-
-	state = cfg_to_state(i2c_get_clientdata(client));
-	state->cfg.fe->tuner_priv = NULL;
-	kfree(state);
-	return 0;
-}
-
-
-static const struct i2c_device_id qm1d1c0042_id[] = {
-	{"qm1d1c0042", 0},
-	{}
-};
-MODULE_DEVICE_TABLE(i2c, qm1d1c0042_id);
-
-static struct i2c_driver qm1d1c0042_driver = {
-	.driver = {
-		.name	= "qm1d1c0042",
-	},
-	.probe		= qm1d1c0042_probe,
-	.remove		= qm1d1c0042_remove,
-	.id_table	= qm1d1c0042_id,
-};
-
-module_i2c_driver(qm1d1c0042_driver);
-
-MODULE_DESCRIPTION("Sharp QM1D1C0042 tuner");
-MODULE_AUTHOR("Akihiro TSUKADA");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/tuners/qm1d1c0042.h b/drivers/media/tuners/qm1d1c0042.h
deleted file mode 100644
index 4f5c188..0000000
--- a/drivers/media/tuners/qm1d1c0042.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Sharp QM1D1C0042 8PSK tuner driver
- *
- * Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com>
- *
- * 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.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef QM1D1C0042_H
-#define QM1D1C0042_H
-
-#include "dvb_frontend.h"
-
-
-struct qm1d1c0042_config {
-	struct dvb_frontend *fe;
-
-	u32  xtal_freq;    /* [kHz] */ /* currently ignored */
-	bool lpf;          /* enable LPF */
-	bool fast_srch;    /* enable fast search mode, no LPF */
-	u32  lpf_wait;         /* wait in tuning with LPF enabled. [ms] */
-	u32  fast_srch_wait;   /* with fast-search mode, no LPF. [ms] */
-	u32  normal_srch_wait; /* with no LPF/fast-search mode. [ms] */
-};
-/* special values indicating to use the default in qm1d1c0042_config */
-#define QM1D1C0042_CFG_XTAL_DFLT 0
-#define QM1D1C0042_CFG_WAIT_DFLT 0
-
-#endif /* QM1D1C0042_H */
-- 
2.7.4

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

* [media 3/6] Demodulator for Earthsoft PT3, PLEX PX-Q3PE ISDB-S/T PCIE cards & PX-BCUD ISDB-S USB dongle
  2016-04-04 17:03 [media 0/6] DVB driver for Earthsoft PT3, PLEX PX-Q3PE ISDB-S/T PCIE cards & PX-BCUD ISDB-S USB dongle info
  2016-04-04 17:04 ` [media 1/6] Raise adapter number limit info
  2016-04-04 17:04 ` [media 2/6] drop backstabbing drivers info
@ 2016-04-04 17:04 ` info
  2016-04-04 17:04 ` [media 4/6] Tuners " info
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: info @ 2016-04-04 17:04 UTC (permalink / raw)
  To: linux-media
  Cc: Буди
	Романто,
	AreMa Inc, linux-kernel, crope, m.chehab, mchehab, hdegoede,
	laurent.pinchart, mkrufky, sylvester.nawrocki, g.liakhovetski,
	peter.senna

From: Буди Романто, AreMa Inc <knightrider@are.ma>

Toshiba TC905xx demodulator driver for PT3, PX-Q3PE & PX-BCUD

Signed-off-by: Буди Романто, AreMa Inc <knightrider@are.ma>
---
 drivers/media/dvb-frontends/tc90522.c | 254 ++++++++++++++++++++++++++++++++++
 drivers/media/dvb-frontends/tc90522.h |  18 +++
 2 files changed, 272 insertions(+)
 create mode 100644 drivers/media/dvb-frontends/tc90522.c
 create mode 100644 drivers/media/dvb-frontends/tc90522.h

diff --git a/drivers/media/dvb-frontends/tc90522.c b/drivers/media/dvb-frontends/tc90522.c
new file mode 100644
index 0000000..c1c48e5
--- /dev/null
+++ b/drivers/media/dvb-frontends/tc90522.c
@@ -0,0 +1,254 @@
+/*
+	Toshiba TC90522XBG 2ch OFDM(ISDB-T) + 2ch 8PSK(ISDB-S) demodulator
+
+	Copyright (C) Budi Rachmanto, AreMa Inc. <info@are.ma>
+
+	CHIP		CARDS
+	TC90522XBG	Earthsoft PT3, PLEX PX-Q3PE
+	TC90532		PLEX PX-BCUD
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+ */
+
+#include "dvb_math.h"
+#include "dvb_frontend.h"
+#include "tc90522.h"
+
+bool tc90522_r(struct i2c_client *d, u8 slvadr, u8 *buf, u8 len)
+{
+	struct i2c_msg msg[] = {
+		{.addr = d->addr,	.flags = 0,		.buf = &slvadr,	.len = 1,},
+		{.addr = d->addr,	.flags = I2C_M_RD,	.buf = buf,	.len = len,},
+	};
+	return i2c_transfer(d->adapter, msg, 2) == 2;
+}
+
+bool tc90522_w(struct i2c_client *d, u8 slvadr, u8 dat)
+{
+	u8 buf[] = {slvadr, dat};
+	struct i2c_msg msg[] = {
+		{.addr = d->addr,	.flags = 0,	.buf = buf,	.len = 2,},
+	};
+	return i2c_transfer(d->adapter, msg, 1) == 1;
+}
+
+u64 tc90522_n2int(const u8 *data, u8 n)		/* convert n_bytes data from stream (network byte order) to integer */
+{						/* can't use <arpa/inet.h>'s ntoh*() as sometimes n = 3,5,...       */
+	u32 i, val = 0;
+
+	for (i = 0; i < n; i++) {
+		val <<= 8;
+		val |= data[i];
+	}
+	return val;
+}
+
+int tc90522_cn_raw(struct dvb_frontend *fe, u16 *raw)	/* for DVBv3 compatibility	*/
+{
+	u8	buf[3],
+		len	= fe->dtv_property_cache.delivery_system == SYS_ISDBS ? 2 : 3,
+		adr	= fe->dtv_property_cache.delivery_system == SYS_ISDBS ? 0xbc : 0x8b;
+	bool	ok	= tc90522_r(fe->demodulator_priv, adr, buf, len);
+	int	cn	= tc90522_n2int(buf, len);
+
+	if (!ok)
+		return -EIO;
+	*raw = cn;
+	return cn;
+}
+
+int tc90522_status(struct dvb_frontend *fe, enum fe_status *stat)
+{
+	enum fe_status			*festat	= i2c_get_clientdata(fe->demodulator_priv);
+	struct dtv_frontend_properties	*c	= &fe->dtv_property_cache;
+	u16	v16;
+	s64	raw	= tc90522_cn_raw(fe, &v16),
+		x,
+		y;
+
+	s64 cn_s(void)	/* @ .0001 dB */
+	{
+		raw -= 3000;
+		if (raw < 0)
+			raw = 0;
+		x = int_sqrt(raw << 20);
+		y = 16346ll * x - (143410ll << 16);
+		y = ((x * y) >> 16) + (502590ll << 16);
+		y = ((x * y) >> 16) - (889770ll << 16);
+		y = ((x * y) >> 16) + (895650ll << 16);
+		y = (588570ll << 16) - ((x * y) >> 16);
+		return y < 0 ? 0 : y >> 16;
+	}
+
+	s64 cn_t(void)	/* @ .0001 dB */
+	{
+		if (!raw)
+			return 0;
+		x = (1130911733ll - 10ll * intlog10(raw)) >> 2;
+		y = (x >> 2) - (x >> 6) + (x >> 8) + (x >> 9) - (x >> 10) + (x >> 11) + (x >> 12) - (16ll << 22);
+		y = ((x * y) >> 22) + (398ll << 22);
+		y = ((x * y) >> 22) + (5491ll << 22);
+		y = ((x * y) >> 22) + (30965ll << 22);
+		return y >> 22;
+	}
+
+	c->cnr.len		= 1;
+	c->cnr.stat[0].svalue	= fe->dtv_property_cache.delivery_system == SYS_ISDBS ? cn_s() : cn_t();
+	c->cnr.stat[0].scale	= FE_SCALE_DECIBEL;
+	*stat = *festat;
+	return *festat;
+}
+
+int tc90522_get_frontend_algo(struct dvb_frontend *fe)
+{
+	return DVBFE_ALGO_HW;
+}
+
+int tc90522_tune(struct dvb_frontend *fe, bool retune, u32 mode_flags, u32 *delay, enum fe_status *stat)
+{
+	u32 fno2kHz(u32 fno)
+	{
+		if (fno < 12)
+			return 1049480 + 38360 * fno;		/* BS		*/
+		else if (fno < 24)
+			return 1613000 + 40000 * (fno - 12);	/* CS110 right	*/
+		return 1593000 + 40000 * (fno - 24);		/* CS110 left	*/
+	}
+
+	void s_kHz(u32 *f)
+	{
+		*f =	*f > 3000000 ? fno2kHz(14)	:	/* max kHz, CNN	*/
+			*f >= 1049480 ? *f		:	/* min real kHz	*/
+			*f > 48 ? fno2kHz(4)		:	/* BS11 etc.	*/
+			fno2kHz(*f - 1);
+	}
+
+	u32 fno2Hz(u32 fno)
+	{
+		return	(fno > 112 ? 557 : 93 + 6 * fno + (fno < 12 ? 0 : fno < 17 ? 2 : fno < 63 ? 0 : 2)) * 1000000 + 142857;
+	}
+
+	void t_Hz(u32 *f)
+	{
+		*f =	*f >= 90000000	? *f			:	/* real_freq Hz	*/
+			*f > 255	? fno2Hz(77)		:	/* NHK		*/
+			*f > 127	? fno2Hz(*f - 128)	:	/* freqno (IO#)	*/
+			*f > 63	? (*f -= 64,				/* CATV		*/
+				*f > 22	? fno2Hz(*f - 1)	:	/* C23-C62	*/
+				*f > 12	? fno2Hz(*f - 10)	:	/* C13-C22	*/
+				fno2Hz(77))			:
+			*f > 62	? fno2Hz(77)			:
+			*f > 12	? fno2Hz(*f + 50)		:	/* 13-62	*/
+			*f > 3	? fno2Hz(*f +  9)		:	/*  4-12	*/
+			*f		? fno2Hz(*f -  1)	:	/*  1-3		*/
+			fno2Hz(77);
+	}
+	struct i2c_client	*d	= fe->demodulator_priv;
+	enum fe_status		*festat	= i2c_get_clientdata(d);
+	u16			set_id	= fe->dtv_property_cache.stream_id,
+				i	= 999;
+	u8			data[16];
+
+	if (!retune)		/* once is enough */
+		return 0;
+	*festat = 0;
+	if (fe->dtv_property_cache.delivery_system == SYS_ISDBT)
+		goto ISDBT;
+
+	s_kHz(&fe->dtv_property_cache.frequency);
+	if (fe->ops.tuner_ops.set_params(fe))
+		return -EIO;
+	while (i--) {
+		if	((tc90522_r(d, 0xC3, data, 1), !(data[0] & 0x10))	&&	/* locked	*/
+			(tc90522_r(d, 0xCE, data, 2), *(u16 *)data != 0)	&&	/* valid TSID	*/
+			tc90522_r(d, 0xC3, data, 1)				&&
+			tc90522_r(d, 0xCE, data, 16))
+			break;
+		msleep_interruptible(5);
+	}
+	if (!i)
+		goto ERR;
+	for (i = 0; i < 8; i++) {
+		u16 tsid = tc90522_n2int(data + i*2, 2);
+
+		if ((tsid == set_id || set_id == i)	&&
+			tc90522_w(d, 0x8F, tsid >> 8)	&&
+			tc90522_w(d, 0x90, tsid & 0xFF)	&&
+			tc90522_r(d, 0xE6, data, 2)	&&
+			tc90522_n2int(data, 2) == tsid)
+			goto LOCK;
+	}
+	goto ERR;
+ISDBT:
+	t_Hz(&fe->dtv_property_cache.frequency);
+	if (fe->ops.tuner_ops.set_params(fe))
+		return -EIO;
+	while (i--) {
+		bool	retryov,
+			lock0,
+			lock1;
+		if (!tc90522_r(d, 0x80, data, 1) || !tc90522_r(d, 0xB0, data + 1, 1))
+			break;
+		retryov	= data[0] & 0b10000000 ? true : false;
+		lock0	= data[0] & 0b00001000 ? false : true;
+		lock1	= data[1] & 0b00001000 ? true : false;
+		if (lock0 && lock1) {
+LOCK:
+			*festat = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK;
+			*stat = *festat;
+			return 0;
+		}
+		if (retryov)
+			break;
+		msleep_interruptible(1);
+	}
+ERR:
+	*stat = *festat;
+	return -ETIMEDOUT;
+}
+
+static struct dvb_frontend_ops tc90522_ops = {
+	.info = {
+		.name = TC90522_MODNAME,
+		.caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_MULTISTREAM |
+			FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO,
+		.frequency_min	= 1,		/* actual limit settings are set by .tune */
+		.frequency_max	= 770000000,
+	},
+	.get_frontend_algo = tc90522_get_frontend_algo,
+	.read_snr	= tc90522_cn_raw,
+	.read_status	= tc90522_status,
+	.tune		= tc90522_tune,
+};
+
+int tc90522_probe(struct i2c_client *d, const struct i2c_device_id *id)
+{
+	struct dvb_frontend	*fe	= d->dev.platform_data;
+	static enum fe_status	festat;
+
+	memcpy(&fe->ops, &tc90522_ops, sizeof(struct dvb_frontend_ops));
+	festat = 0;
+	i2c_set_clientdata(d, &festat);
+	return 0;
+}
+
+static struct i2c_device_id tc90522_id[] = {
+	{TC90522_MODNAME, 0},
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, tc90522_id);
+
+static struct i2c_driver tc90522_driver = {
+	.driver.name	= tc90522_id->name,
+	.probe		= tc90522_probe,
+	.id_table	= tc90522_id,
+};
+module_i2c_driver(tc90522_driver);
+
+MODULE_AUTHOR("Budi Rachmanto, AreMa Inc. <knightrider(@)are.ma>");
+MODULE_DESCRIPTION("Toshiba TC90522 8PSK(ISDB-S)/OFDM(ISDB-T) quad demodulator");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/media/dvb-frontends/tc90522.h b/drivers/media/dvb-frontends/tc90522.h
new file mode 100644
index 0000000..b6ee014
--- /dev/null
+++ b/drivers/media/dvb-frontends/tc90522.h
@@ -0,0 +1,18 @@
+/*
+ * Toshiba TC90522XBG 2ch OFDM(ISDB-T) + 2ch 8PSK(ISDB-S) demodulator
+ *
+ * Copyright (C) Budi Rachmanto, AreMa Inc. <info@are.ma>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef	TC90522_H
+#define	TC90522_H
+
+#define TC90522_MODNAME "tc90522"
+
+#endif
+
-- 
2.7.4

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

* [media 4/6] Tuners for Earthsoft PT3, PLEX PX-Q3PE ISDB-S/T PCIE cards & PX-BCUD ISDB-S USB dongle
  2016-04-04 17:03 [media 0/6] DVB driver for Earthsoft PT3, PLEX PX-Q3PE ISDB-S/T PCIE cards & PX-BCUD ISDB-S USB dongle info
                   ` (2 preceding siblings ...)
  2016-04-04 17:04 ` [media 3/6] Demodulator for Earthsoft PT3, PLEX PX-Q3PE ISDB-S/T PCIE cards & PX-BCUD ISDB-S USB dongle info
@ 2016-04-04 17:04 ` info
  2016-04-04 17:04 ` [media 5/6] PCIE bridge driver for PT3 & PX-Q3PE info
  2016-04-04 17:04 ` [media 6/6] Bridge driver for PLEX PX-BCUD ISDB-S USB dongle info
  5 siblings, 0 replies; 10+ messages in thread
From: info @ 2016-04-04 17:04 UTC (permalink / raw)
  To: linux-media
  Cc: Буди
	Романто,
	AreMa Inc, linux-kernel, crope, m.chehab, mchehab, hdegoede,
	laurent.pinchart, mkrufky, sylvester.nawrocki, g.liakhovetski,
	peter.senna

From: Буди Романто, AreMa Inc <knightrider@are.ma>

tda2014x.c      TDA20142				PX-Q3PE
qm1d1c004x.c    QM1D1C0042, QM1D1C0045, QM1D1C0045_2	PX-BCUD, PT3
nm131.c         NM131, NM130, NM120			PX-Q3PE
mxl301rf.c      MxL301RF				PT3

Signed-off-by: Буди Романто, AreMa Inc <knightrider@are.ma>
---
 drivers/media/tuners/Kconfig      |  21 ++-
 drivers/media/tuners/Makefile     |   4 +-
 drivers/media/tuners/mxl301rf.c   | 220 +++++++++++++++++++++++
 drivers/media/tuners/mxl301rf.h   |  23 +++
 drivers/media/tuners/nm131.c      | 248 ++++++++++++++++++++++++++
 drivers/media/tuners/nm131.h      |  13 ++
 drivers/media/tuners/qm1d1c004x.c | 242 ++++++++++++++++++++++++++
 drivers/media/tuners/qm1d1c004x.h |  23 +++
 drivers/media/tuners/tda2014x.c   | 358 ++++++++++++++++++++++++++++++++++++++
 drivers/media/tuners/tda2014x.h   |  13 ++
 10 files changed, 1161 insertions(+), 4 deletions(-)
 create mode 100644 drivers/media/tuners/mxl301rf.c
 create mode 100644 drivers/media/tuners/mxl301rf.h
 create mode 100644 drivers/media/tuners/nm131.c
 create mode 100644 drivers/media/tuners/nm131.h
 create mode 100644 drivers/media/tuners/qm1d1c004x.c
 create mode 100644 drivers/media/tuners/qm1d1c004x.h
 create mode 100644 drivers/media/tuners/tda2014x.c
 create mode 100644 drivers/media/tuners/tda2014x.h

diff --git a/drivers/media/tuners/Kconfig b/drivers/media/tuners/Kconfig
index 05998f0..a7f044b 100644
--- a/drivers/media/tuners/Kconfig
+++ b/drivers/media/tuners/Kconfig
@@ -271,10 +271,25 @@ config MEDIA_TUNER_MXL301RF
 	help
 	  MaxLinear MxL301RF OFDM tuner driver.
 
-config MEDIA_TUNER_QM1D1C0042
-	tristate "Sharp QM1D1C0042 tuner"
+config MEDIA_TUNER_QM1D1C004X
+	tristate "Sharp QM1D1C004x tuner"
 	depends on MEDIA_SUPPORT && I2C
 	default m if !MEDIA_SUBDRV_AUTOSELECT
 	help
-	  Sharp QM1D1C0042 trellis coded 8PSK tuner driver.
+	  Sharp trellis coded 8PSK tuner driver.
+	  Supported chips: QM1D1C0042, QM1D1C0045
+
+config MEDIA_TUNER_NM131
+	tristate "Newport Media tuners NM131, NM130 and NM120"
+	depends on MEDIA_SUPPORT && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  Newport Media NM131, NM130 and NM120 tuner driver.
+
+config MEDIA_TUNER_TDA2014X
+	tristate "NXP Semiconductors TDA2014x tuner"
+	depends on MEDIA_SUPPORT && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  NXP Semiconductor TDA2014x tuner driver.
 endmenu
diff --git a/drivers/media/tuners/Makefile b/drivers/media/tuners/Makefile
index 06a9ab6..6a2b52a 100644
--- a/drivers/media/tuners/Makefile
+++ b/drivers/media/tuners/Makefile
@@ -39,8 +39,10 @@ obj-$(CONFIG_MEDIA_TUNER_FC0013) += fc0013.o
 obj-$(CONFIG_MEDIA_TUNER_IT913X) += it913x.o
 obj-$(CONFIG_MEDIA_TUNER_R820T) += r820t.o
 obj-$(CONFIG_MEDIA_TUNER_MXL301RF) += mxl301rf.o
-obj-$(CONFIG_MEDIA_TUNER_QM1D1C0042) += qm1d1c0042.o
+obj-$(CONFIG_MEDIA_TUNER_QM1D1C004X) += qm1d1c004x.o
 obj-$(CONFIG_MEDIA_TUNER_M88RS6000T) += m88rs6000t.o
+obj-$(CONFIG_MEDIA_TUNER_NM131) += nm131.o
+obj-$(CONFIG_MEDIA_TUNER_TDA2014X) += tda2014x.o
 
 ccflags-y += -I$(srctree)/drivers/media/dvb-core
 ccflags-y += -I$(srctree)/drivers/media/dvb-frontends
diff --git a/drivers/media/tuners/mxl301rf.c b/drivers/media/tuners/mxl301rf.c
new file mode 100644
index 0000000..916b06f
--- /dev/null
+++ b/drivers/media/tuners/mxl301rf.c
@@ -0,0 +1,220 @@
+/*
+	Sharp VA4M6JC2103 - Earthsoft PT3 ISDB-T tuner MaxLinear CMOS Hybrid TV MxL301RF
+
+	Copyright (C) Budi Rachmanto, AreMa Inc. <info@are.ma>
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+*/
+
+#include "dvb_frontend.h"
+#include "mxl301rf.h"
+
+int mxl301rf_w(struct dvb_frontend *fe, u8 slvadr, const u8 *dat, int len)
+{
+	struct i2c_client	*d	= fe->demodulator_priv;
+	u8			buf[len + 1];
+	struct i2c_msg		msg[] = {
+		{.addr = d->addr,	.flags = 0,	.buf = buf,	.len = len + 1,},
+	};
+
+	buf[0] = slvadr;
+	memcpy(buf + 1, dat, len);
+	return i2c_transfer(d->adapter, msg, 1) == 1 ? 0 : -EIO;
+}
+
+int mxl301rf_w_tuner(struct dvb_frontend *fe, const u8 *dat, int len)
+{
+	u8 buf[len + 1];
+
+	buf[0] = ((struct i2c_client *)fe->tuner_priv)->addr << 1;
+	memcpy(buf + 1, dat, len);
+	return mxl301rf_w(fe, 0xFE, buf, len + 1);
+}
+
+u8 mxl301rf_r(struct dvb_frontend *fe, u8 regadr)
+{
+	struct i2c_client	*d	= fe->demodulator_priv,
+				*t	= fe->tuner_priv;
+	u8	wbuf[]	= {0xFB, regadr},
+		rbuf[]	= {0xFE, (t->addr << 1) | 1, 0};
+	struct i2c_msg msg[] = {
+		{.addr	= d->addr,	.flags	= 0,		.buf	= rbuf,		.len	= 2,},
+		{.addr	= d->addr,	.flags	= I2C_M_RD,	.buf	= rbuf + 2,	.len	= 1,},
+	};
+	mxl301rf_w_tuner(fe, wbuf, sizeof(wbuf));
+	return t->addr && (i2c_transfer(d->adapter, msg, 2) == 2) ? rbuf[2] : 0;
+}
+
+enum mxl301rf_agc {
+	MXL301RF_AGC_AUTO,
+	MXL301RF_AGC_MANUAL,
+};
+
+int mxl301rf_set_agc(struct dvb_frontend *fe, enum mxl301rf_agc agc)
+{
+	u8	dat	= agc == MXL301RF_AGC_AUTO ? 0x40 : 0x00,
+		imsrst	= 0x01 << 6;
+	int	err	= mxl301rf_w(fe, 0x25, &dat, 1);
+
+	dat = 0x4c | (agc == MXL301RF_AGC_AUTO ? 0 : 1);
+	return	err				||
+		mxl301rf_w(fe, 0x23, &dat, 1)	||
+		mxl301rf_w(fe, 0x01, &imsrst, 1);
+}
+
+int mxl301rf_sleep(struct dvb_frontend *fe)
+{
+	u8	buf	= (1 << 7) | (1 << 4),
+		dat[]	= {0x01, 0x00, 0x13, 0x00};
+	int	err	= mxl301rf_set_agc(fe, MXL301RF_AGC_MANUAL);
+
+	if (err)
+		return err;
+	mxl301rf_w_tuner(fe, dat, sizeof(dat));
+	return mxl301rf_w(fe, 0x03, &buf, 1);
+}
+
+int mxl301rf_tune(struct dvb_frontend *fe)
+{
+	struct shf_dvbt {
+		u32	freq,		/* Channel center frequency @ kHz	*/
+			freq_th;	/* Offset frequency threshold @ kHz	*/
+		u8	shf_val,	/* Spur shift value			*/
+			shf_dir;	/* Spur shift direction			*/
+	} shf_dvbt_tab[] = {
+		{ 64500, 500, 0x92, 0x07},
+		{191500, 300, 0xe2, 0x07},
+		{205500, 500, 0x2c, 0x04},
+		{212500, 500, 0x1e, 0x04},
+		{226500, 500, 0xd4, 0x07},
+		{ 99143, 500, 0x9c, 0x07},
+		{173143, 500, 0xd4, 0x07},
+		{191143, 300, 0xd4, 0x07},
+		{207143, 500, 0xce, 0x07},
+		{225143, 500, 0xce, 0x07},
+		{243143, 500, 0xd4, 0x07},
+		{261143, 500, 0xd4, 0x07},
+		{291143, 500, 0xd4, 0x07},
+		{339143, 500, 0x2c, 0x04},
+		{117143, 500, 0x7a, 0x07},
+		{135143, 300, 0x7a, 0x07},
+		{153143, 500, 0x01, 0x07}
+	};
+	u8 rf_dat[] = {
+		0x13, 0x00,	/* abort tune		*/
+		0x3b, 0xc0,
+		0x3b, 0x80,
+		0x10, 0x95,	/* BW			*/
+		0x1a, 0x05,
+		0x61, 0x00,
+		0x62, 0xa0,
+		0x11, 0x40,	/* 2 bytes to store RF	*/
+		0x12, 0x0e,	/* 2 bytes to store RF	*/
+		0x13, 0x01	/* start tune		*/
+	};
+	const u8 idac[] = {
+		0x0d, 0x00,
+		0x0c, 0x67,
+		0x6f, 0x89,
+		0x70, 0x0c,
+		0x6f, 0x8a,
+		0x70, 0x0e,
+		0x6f, 0x8b,
+		0x70, 0x10+12,
+	};
+	u8	dat[20];
+	int	err	= mxl301rf_set_agc(fe, MXL301RF_AGC_MANUAL);
+	u32	freq	= fe->dtv_property_cache.frequency,
+		kHz	= 1000,
+		MHz	= 1000000,
+		dig_rf	= freq / MHz,
+		tmp	= freq % MHz,
+		i,
+		fdiv	= 1000000;
+	unsigned long timeout;
+
+	if (err)
+		return err;
+	for (i = 0; i < 6; i++) {
+		dig_rf <<= 1;
+		fdiv /= 2;
+		if (tmp > fdiv) {
+			tmp -= fdiv;
+			dig_rf++;
+		}
+	}
+	if (tmp > 7812)
+		dig_rf++;
+	rf_dat[2 * 7 + 1]	= (u8)(dig_rf);
+	rf_dat[2 * 8 + 1]	= (u8)(dig_rf >> 8);
+	for (i = 0; i < ARRAY_SIZE(shf_dvbt_tab); i++) {
+		if ((freq >= (shf_dvbt_tab[i].freq - shf_dvbt_tab[i].freq_th) * kHz) &&
+				(freq <= (shf_dvbt_tab[i].freq + shf_dvbt_tab[i].freq_th) * kHz)) {
+			rf_dat[2 * 5 + 1] = shf_dvbt_tab[i].shf_val;
+			rf_dat[2 * 6 + 1] = 0xa0 | shf_dvbt_tab[i].shf_dir;
+			break;
+		}
+	}
+	memcpy(dat, rf_dat, sizeof(rf_dat));
+
+	mxl301rf_w_tuner(fe, dat, 14);
+	msleep_interruptible(1);
+	mxl301rf_w_tuner(fe, dat + 14, 6);
+	msleep_interruptible(1);
+	dat[0] = 0x1a;
+	dat[1] = 0x0d;
+	mxl301rf_w_tuner(fe, dat, 2);
+	mxl301rf_w_tuner(fe, idac, sizeof(idac));
+	timeout = jiffies + msecs_to_jiffies(100);
+	while (time_before(jiffies, timeout)) {
+		if ((mxl301rf_r(fe, 0x16) & 0x0c) == 0x0c && (mxl301rf_r(fe, 0x16) & 0x03) == 0x03)
+			return mxl301rf_set_agc(fe, MXL301RF_AGC_AUTO);
+		msleep_interruptible(1);
+	}
+	return -ETIMEDOUT;
+}
+
+int mxl301rf_wakeup(struct dvb_frontend *fe)
+{
+	u8	buf	= (1 << 7) | (0 << 4),
+		dat[2]	= {0x01, 0x01};
+	int	err	= mxl301rf_w(fe, 0x03, &buf, 1);
+
+	if (err)
+		return err;
+	mxl301rf_w_tuner(fe, dat, sizeof(dat));
+	return 0;
+}
+
+int mxl301rf_probe(struct i2c_client *t, const struct i2c_device_id *id)
+{
+	struct dvb_frontend	*fe	= t->dev.platform_data;
+	u8			d[]	= {0x10, 0x01};
+
+	fe->ops.tuner_ops.set_params	= mxl301rf_tune;
+	fe->ops.tuner_ops.sleep		= mxl301rf_sleep;
+	fe->ops.tuner_ops.init		= mxl301rf_wakeup;
+	return	mxl301rf_w(fe, 0x1c, d, 1)	||
+		mxl301rf_w(fe, 0x1d, d+1, 1);
+}
+
+static struct i2c_device_id mxl301rf_id[] = {
+	{MXL301RF_MODNAME, 0},
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, mxl301rf_id);
+
+static struct i2c_driver mxl301rf_driver = {
+	.driver.name	= mxl301rf_id->name,
+	.probe		= mxl301rf_probe,
+	.id_table	= mxl301rf_id,
+};
+module_i2c_driver(mxl301rf_driver);
+
+MODULE_AUTHOR("Budi Rachmanto, AreMa Inc. <knightrider(@)are.ma>");
+MODULE_DESCRIPTION("Earthsoft PT3 MxL301RF MaxLinear CMOS Hybrid TV ISDB-T tuner driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/media/tuners/mxl301rf.h b/drivers/media/tuners/mxl301rf.h
new file mode 100644
index 0000000..32a31b0
--- /dev/null
+++ b/drivers/media/tuners/mxl301rf.h
@@ -0,0 +1,23 @@
+/*
+ * Sharp VA4M6JC2103 - Earthsoft PT3 ISDB-T tuner MaxLinear CMOS Hybrid TV MxL301RF
+ *
+ * Copyright (C) 2014 Budi Rachmanto, AreMa Inc. <info@are.ma>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MXL301RF_H
+#define MXL301RF_H
+
+#define MXL301RF_MODNAME "mxl301rf"
+
+#endif
+
diff --git a/drivers/media/tuners/nm131.c b/drivers/media/tuners/nm131.c
new file mode 100644
index 0000000..817cf96
--- /dev/null
+++ b/drivers/media/tuners/nm131.c
@@ -0,0 +1,248 @@
+/*
+	Driver for Newport Media tuners NMI131, NMI130 and NMI120
+
+	Copyright (C) Budi Rachmanto, AreMa Inc. <info@are.ma>
+*/
+
+#include "dvb_frontend.h"
+#include "nm131.h"
+
+bool nm131_w(struct dvb_frontend *fe, u16 slvadr, u32 val, u32 sz)
+{
+	struct i2c_client	*d	= fe->demodulator_priv;
+	u8		buf[]	= {0xFE, 0xCE, slvadr >> 8, slvadr & 0xFF, 0, 0, 0, 0};
+	struct i2c_msg	msg[]	= {
+		{.addr = d->addr,	.flags = 0,	.buf = buf,	.len = sz + 4,},
+	};
+
+	*(u32 *)(buf + 4) = slvadr == 0x36 ? val & 0x7F : val;
+	return i2c_transfer(d->adapter, msg, 1) == 1;
+}
+
+bool nm131_w8(struct dvb_frontend *fe, u8 slvadr, u8 dat)
+{
+	struct i2c_client	*d	= fe->demodulator_priv;
+	u8		buf[]	= {slvadr, dat};
+	struct i2c_msg	msg[]	= {
+		{.addr = d->addr,	.flags = 0,	.buf = buf,	.len = 2,},
+	};
+	return i2c_transfer(d->adapter, msg, 1) == 1;
+}
+
+bool nm131_r(struct dvb_frontend *fe, u16 slvadr, u8 *dat, u32 sz)
+{
+	struct i2c_client	*d	= fe->demodulator_priv;
+	u8		rcmd[]	= {0xFE, 0xCF},
+			buf[sz];
+	struct i2c_msg	msg[]	= {
+		{.addr = d->addr,	.flags = 0,		.buf = rcmd,	.len = 2,},
+		{.addr = d->addr,	.flags = I2C_M_RD,	.buf = buf,	.len = sz,},
+	};
+	bool	ret = nm131_w(fe, slvadr, 0, 0) && i2c_transfer(d->adapter, msg, 2) == 2;
+
+	memcpy(dat, buf, sz);
+	return ret;
+}
+
+int nm131_tune(struct dvb_frontend *fe)
+{
+	struct vhf_filter_cutoff_codes_t {
+		u32	Hz;
+		u8	val8_0x08,
+			val8_0x09;
+	} const vhf_filter_cutoff_codes[] = {
+		{45000000, 167, 58},	{55000000, 151, 57},	{65000000, 100, 54},	{75000000, 83, 53},	{85000000, 82, 53},
+		{95000000, 65, 52},	{105000000, 64, 52},	{115000000, 64, 52},	{125000000, 0, 0}
+	};
+	const u8	v45[]		= {0, 1, 2, 3, 4, 6, 9, 12},
+			ACI_audio_lut	= 0,
+			aci_lut		= 1;
+	const u32	lo_freq_lut[]	= {0, 0, 434000000, 237000000, 214000000, 118000000, 79000000, 53000000},
+			*v11,
+			adec_ddfs_fq	= 126217,
+			ddfs_lut	= 0;
+	u8		rf_reg_0x05	= 0x87,
+			v15,
+			val;
+	int		i;
+	u32		tune_rf		= fe->dtv_property_cache.frequency,
+			clk_off_f	= tune_rf,
+			xo		= 24000,
+			lofreq,
+			rf,
+			v14,
+			v32;
+	bool		done		= false;
+
+	if (!(nm131_w8(fe, 1, 0x50)		&&
+		nm131_w8(fe, 0x47, 0x30)	&&
+		nm131_w8(fe, 0x25, 0)		&&
+		nm131_w8(fe, 0x20, 0)		&&
+		nm131_w8(fe, 0x23, 0x4D)))
+		return -EIO;
+	while (1) {
+		rf = clk_off_f;
+		val = rf > 120400000 ? 0x85 : 5;
+		if (rf_reg_0x05 != val) {
+			nm131_w(fe, 0x05, val, 1);
+			rf_reg_0x05 = val;
+		}
+		lofreq = rf;
+		v11 = &lo_freq_lut[6];
+		val = 6;
+		if (lofreq > 53000000) {
+			do {
+				if (*v11 >= lofreq)
+					break;
+				--val;
+				--v11;
+			} while (val != 1);
+		} else
+			val = 7;
+		i = 0;
+		do {
+			if (lofreq > vhf_filter_cutoff_codes[i].Hz && lofreq <= vhf_filter_cutoff_codes[i + 1].Hz)
+				break;
+			++i;
+		} while (i != 8);
+		nm131_w(fe, 8, vhf_filter_cutoff_codes[i].val8_0x08, 1);
+		nm131_w(fe, 9, vhf_filter_cutoff_codes[i].val8_0x09, 1);
+		v14 = lofreq / 1000 * 8 * v45[val];
+		nm131_r(fe, 0x21, &v15, 1);
+		v15 &= 3;
+		xo = v15 == 2 ? xo * 2 : v15 == 3 ? xo >> 1 : xo;
+		v32 = v14 / xo;
+		if (!((v14 % xo * (0x80000000 / xo) >> 12) & 0x7FFFF) || done)
+			break;
+		clk_off_f += 1000;
+		done = true;
+	}
+	xo = (v14 % xo * (0x80000000 / xo) >> 12) & 0x7FFFF;
+	clk_off_f = v14;
+	v14 /= 216000;
+	if (v14 > 31)
+		v14 = 31;
+	if (v14 < 16)
+		v14 = 16;
+	nm131_w(fe, 1, (u16)v32 >> 1, 1);
+	nm131_w(fe, 2, (v32 & 1) | 2 * xo, 1);
+	nm131_w(fe, 3, xo >> 7, 1);
+	nm131_w(fe, 4, (xo >> 15) | 16 * v14, 1);
+	nm131_r(fe, 0x1D, &v15, 1);
+	nm131_w(fe, 0x1D, 32 * val | (v15 & 0x1F), 1);
+	if (lofreq < 300000000) {
+		nm131_w(fe, 0x25, 0x78, 1);
+		nm131_w(fe, 0x27, 0x7F, 1);
+		nm131_w(fe, 0x29, 0x7F, 1);
+		nm131_w(fe, 0x2E, 0x12, 1);
+	} else {
+		nm131_w(fe, 0x25, 0xF4, 1);
+		nm131_w(fe, 0x27, 0xEF, 1);
+		nm131_w(fe, 0x29, 0x4F, 1);
+		nm131_w(fe, 0x2E, 0x34, 1);
+	}
+	nm131_w(fe, 0x36, lofreq < 150000000 ? 0x54 : 0x7C, 1);
+	nm131_w(fe, 0x37, lofreq < 155000000 ? 0x84 : lofreq < 300000000 ? 0x9C : 0x84, 1);
+	clk_off_f = (clk_off_f << 9) / v14 - 110592000;
+
+	nm131_w(fe, 0x164, tune_rf < 300000000 ? 0x600 : 0x500, 4);
+	rf = clk_off_f / 6750 + 16384;
+	nm131_w(fe, 0x230, (adec_ddfs_fq << 15) / rf | 0x80000, 4);
+	nm131_w(fe, 0x250, ACI_audio_lut, 4);
+	nm131_w(fe, 0x27C, 0x1010, 4);
+	nm131_w(fe, 0x1BC, (ddfs_lut << 14) / rf, 4);
+	nm131_r(fe, 0x21C, (u8 *)(&v32), 4);
+	nm131_w(fe, 0x21C, (((v32 & 0xFFC00000) | 524288000 / ((clk_off_f >> 14) + 6750)) & 0xC7BFFFFE) | 0x8000000, 4);
+	nm131_r(fe, 0x234, (u8 *)(&v32), 4);
+	nm131_w(fe, 0x234, v32 & 0xCFC00000, 4);
+	nm131_w(fe, 0x210, ((864 * (clk_off_f >> 5) - 1308983296) / 216000 & 0xFFFFFFF0) | 3, 4);
+	nm131_r(fe, 0x104, (u8 *)(&v32), 4);
+	v32 = ((((clk_off_f > 3686396 ? 2 : clk_off_f >= 1843193 ? 1 : 0) << 16) | (((((((v32 & 0x87FFFFC0) | 0x10000011)
+		& 0xFFFF87FF) | (aci_lut << 11)) & 0xFFFF7FFF) | 0x8000) & 0xFFF0FFFF)) & 0xFC0FFFFF) | 0xA00000;
+	nm131_w(fe, 0x104, v32, 4);
+	v32 = (v32 & 0xFFFFFFEF) | 0x20000020;
+	nm131_w(fe, 0x104, v32, 4);
+	nm131_r(fe, 0x328, (u8 *)(&v14), 4);
+	if (v14) {
+		v32 &= 0xFFFFFFDF;
+		nm131_w(fe, 0x104, v32, 4);
+		nm131_w(fe, 0x104, v32 | 0x20, 4);
+	}
+	return	nm131_w8(fe, 0x23, 0x4C)	&&
+		nm131_w8(fe, 1, 0x50)		&&
+		nm131_w8(fe, 0x71, 1)		&&
+		nm131_w8(fe, 0x72, 0x24)	?
+		0 : -EIO;
+}
+
+int nm131_probe(struct i2c_client *t, const struct i2c_device_id *id)
+{
+	struct tnr_rf_reg_t {
+		u8 slvadr;
+		u8 val;
+	} const
+	tnr_rf_defaults_lut[] = {
+		{6, 72},	{7, 64},	{10, 235},	{11, 17},	{12, 16},	{13, 136},
+		{16, 4},	{17, 48},	{18, 48},	{21, 170},	{22, 3},	{23, 128},
+		{24, 103},	{25, 212},	{26, 68},	{28, 16},	{29, 238},	{30, 153},
+		{33, 197},	{34, 145},	{36, 1},	{43, 145},	{45, 1},	{47, 128},
+		{49, 0},	{51, 0},	{56, 0},	{57, 47},	{58, 0},	{59, 0}
+	},
+	nm120_rf_defaults_lut[] = {
+		{14, 69},	{27, 14},	{35, 255},	{38, 130},	{40, 0},
+		{48, 223},	{50, 223},	{52, 104},	{53, 24}
+	};
+	struct tnr_bb_reg_t {
+		u16 slvadr;
+		u32 val;
+	} const
+	tnr_bb_defaults_lut[2] = {
+		{356, 2048},	{448, 764156359}
+	};
+	u8			i;
+	struct dvb_frontend	*fe	= t->dev.platform_data;
+
+	fe->ops.tuner_ops.set_params	= nm131_tune;
+	if (nm131_w8(fe, 0xB0, 0xA0)		&&
+		nm131_w8(fe, 0xB2, 0x3D)	&&
+		nm131_w8(fe, 0xB3, 0x25)	&&
+		nm131_w8(fe, 0xB4, 0x8B)	&&
+		nm131_w8(fe, 0xB5, 0x4B)	&&
+		nm131_w8(fe, 0xB6, 0x3F)	&&
+		nm131_w8(fe, 0xB7, 0xFF)	&&
+		nm131_w8(fe, 0xB8, 0xC0)	&&
+		nm131_w8(fe, 3, 0)		&&
+		nm131_w8(fe, 0x1D, 0)		&&
+		nm131_w8(fe, 0x1F, 0)) {
+		nm131_w8(fe, 0xE, 0x77);
+		nm131_w8(fe, 0xF, 0x13);
+		nm131_w8(fe, 0x75, 2);
+	}
+	for (i = 0; i < ARRAY_SIZE(tnr_rf_defaults_lut); i++)
+		nm131_w(fe, tnr_rf_defaults_lut[i].slvadr, tnr_rf_defaults_lut[i].val, 1);
+	nm131_r(fe, 0x36, &i, 1);
+	nm131_w(fe, 0x36, i & 0x7F, 1);	/* no LDO bypass */
+	nm131_w(fe, tnr_bb_defaults_lut[0].slvadr, tnr_bb_defaults_lut[0].val, 4);
+	nm131_w(fe, tnr_bb_defaults_lut[1].slvadr, tnr_bb_defaults_lut[1].val, 4);
+	for (i = 0; i < ARRAY_SIZE(nm120_rf_defaults_lut); i++)
+		nm131_w(fe, nm120_rf_defaults_lut[i].slvadr, nm120_rf_defaults_lut[i].val, 1);
+	nm131_w(fe, 0xA, 0xFB, 1);	/* ltgain */
+	return 0;
+}
+
+static struct i2c_device_id nm131_id[] = {
+	{NM131_MODNAME, 0},
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, nm131_id);
+
+static struct i2c_driver nm131_driver = {
+	.driver.name	= nm131_id->name,
+	.probe		= nm131_probe,
+	.id_table	= nm131_id,
+};
+module_i2c_driver(nm131_driver);
+
+MODULE_AUTHOR("Budi Rachmanto, AreMa Inc. <info@are.ma>");
+MODULE_DESCRIPTION("Driver for Newport Media tuners NMI131, NMI130 and NMI120");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/tuners/nm131.h b/drivers/media/tuners/nm131.h
new file mode 100644
index 0000000..21f3627
--- /dev/null
+++ b/drivers/media/tuners/nm131.h
@@ -0,0 +1,13 @@
+/*
+ * Driver for Newport Media tuners NMI131, NMI130 and NMI120
+ *
+ * Copyright (C) Budi Rachmanto, AreMa Inc. <info@are.ma>
+ */
+
+#ifndef	NM131_H
+#define	NM131_H
+
+#define NM131_MODNAME "nm131"
+
+#endif
+
diff --git a/drivers/media/tuners/qm1d1c004x.c b/drivers/media/tuners/qm1d1c004x.c
new file mode 100644
index 0000000..843cfb2
--- /dev/null
+++ b/drivers/media/tuners/qm1d1c004x.c
@@ -0,0 +1,242 @@
+/*
+	Sharp VA4M6JC2103 QM1D1C004x ISDB-S tuner driver
+
+	Copyright (C) Budi Rachmanto, AreMa Inc. <info@are.ma>
+
+	CHIP		VER.	CARD
+	QM1D1C0042	0x48	Earthsoft PT3
+	QM1D1C0045	0x58
+	QM1D1C0045_2	0x68	PLEX PX-BCUD
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+*/
+
+#include "dvb_frontend.h"
+#include "qm1d1c004x.h"
+
+struct qm1d1c004x {
+	u8 reg[32];
+};
+
+bool qm1d1c004x_r(struct dvb_frontend *fe, u8 slvadr, u8 *dat)
+{
+	struct i2c_client	*d	= fe->demodulator_priv,
+				*t	= fe->tuner_priv;
+	u8		buf[]	= {0xFE, t->addr << 1, slvadr, 0xFE, (t->addr << 1) | 1, 0};
+	struct i2c_msg	msg[]	= {
+		{.addr = d->addr,	.flags = 0,		.buf = buf,	.len = 3,},
+		{.addr = d->addr,	.flags = 0,		.buf = buf + 3,	.len = 2,},
+		{.addr = d->addr,	.flags = I2C_M_RD,	.buf = buf + 5,	.len = 1,},
+	};
+	bool	ret = i2c_transfer(d->adapter, msg, 3) == 3;
+
+	*dat = buf[5];
+	return ret;
+}
+
+int qm1d1c004x_w(struct dvb_frontend *fe, u8 slvadr, u8 *dat, int len)
+{
+	struct i2c_client	*d	= fe->demodulator_priv;
+	u8		buf[len + 1];
+	struct i2c_msg	msg[] = {
+		{.addr = d->addr,	.flags = 0,	.buf = buf,	.len = len + 1,},
+	};
+
+	buf[0] = slvadr;
+	memcpy(buf + 1, dat, len);
+	return i2c_transfer(d->adapter, msg, 1) == 1 ? 0 : -EIO;
+}
+
+int qm1d1c004x_w_tuner(struct dvb_frontend *fe, u8 adr, u8 dat)
+{
+	struct i2c_client	*t	= fe->tuner_priv;
+	struct qm1d1c004x	*q	= i2c_get_clientdata(t);
+	u8			buf[]	= {t->addr << 1, adr, dat};
+	int			err	= qm1d1c004x_w(fe, 0xFE, buf, 3);
+
+	q->reg[adr] = dat;
+	return err;
+}
+
+enum qm1d1c004x_agc {
+	QM1D1C004X_AGC_AUTO,
+	QM1D1C004X_AGC_MANUAL,
+};
+
+int qm1d1c004x_set_agc(struct dvb_frontend *fe, enum qm1d1c004x_agc agc)
+{
+	u8	dat		= (agc == QM1D1C004X_AGC_AUTO) ? 0xff : 0x00,
+		pskmsrst	= 0x01;
+	int	err		= qm1d1c004x_w(fe, 0x0a, &dat, 1);
+
+	if (err)
+		return err;
+	dat = 0xb0 | (agc == QM1D1C004X_AGC_AUTO ? 1 : 0);
+	err = qm1d1c004x_w(fe, 0x10, &dat, 1);
+	if (err)
+		return err;
+	dat = (agc == QM1D1C004X_AGC_AUTO) ? 0x40 : 0x00;
+	return	(err = qm1d1c004x_w(fe, 0x11, &dat, 1)) ?
+		err : qm1d1c004x_w(fe, 0x03, &pskmsrst, 1);
+}
+
+int qm1d1c004x_sleep(struct dvb_frontend *fe)
+{
+	u8	buf	= 1,
+		*reg	= ((struct qm1d1c004x *)fe->tuner_priv)->reg;
+
+	reg[0x01] &= (~(1 << 3)) & 0xff;
+	reg[0x01] |= 1 << 0;
+	reg[0x05] |= 1 << 3;
+	return	qm1d1c004x_set_agc(fe, QM1D1C004X_AGC_MANUAL)	||
+		qm1d1c004x_w_tuner(fe, 0x05, reg[0x05])		||
+		qm1d1c004x_w_tuner(fe, 0x01, reg[0x01])		||
+		qm1d1c004x_w(fe, 0x17, &buf, 1);
+}
+
+int qm1d1c004x_wakeup(struct dvb_frontend *fe)
+{
+	u8	regs[][32] = {
+			{	/* QM1D1C0042	Earthsoft PT3	*/
+			0x48, 0x1c, 0xa0, 0x10, 0xbc, 0xc5, 0x20, 0x33,	0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+			0x00, 0xff, 0xf3, 0x00, 0x2a, 0x64, 0xa6, 0x86,	0x8c, 0xcf, 0xb8, 0xf1, 0xa8, 0xf2, 0x89, 0x00,
+			}, {	/* QM1D1C0045	untested!	*/
+			0x58, 0x1C, 0xC0, 0x10, 0xBC, 0xC1, 0x15, 0x34, 0x06, 0x3e, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00,
+			0x11, 0xFF, 0xF3, 0x00, 0x3E, 0x25, 0x5C, 0xD6, 0x55, 0x8F, 0x95, 0xF6, 0x36, 0xF2, 0x09, 0x00,
+			}, {	/* QM1D1C0045_2	PLEX PX-BCUD	*/
+			0x68, 0x1c, 0xc0, 0x10, 0xbc, 0xc1, 0x11, 0x33,	0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+			0x00, 0xff, 0xf3, 0x00, 0x3f, 0x25, 0x5c, 0xd6,	0x55, 0xcf, 0x95, 0xf6, 0x36, 0xf2, 0x09, 0x00,
+			}
+		},
+		*reg	= ((struct qm1d1c004x *)i2c_get_clientdata(fe->tuner_priv))->reg,
+		dat	= 0,
+		i;
+
+	for (i = 0; i < ARRAY_SIZE(regs); i++) {
+		if (!qm1d1c004x_r(fe, 0, &dat))
+			return -EIO;
+		if (dat == regs[i][0])
+			break;
+	}
+	if (i == ARRAY_SIZE(regs))
+		return -ENOTSUPP;
+	memcpy(reg, regs[i], 32);
+	reg[0x01] |= 1 << 3;
+	reg[0x01] &= (~(1 << 0)) & 0xff;
+	reg[0x05] &= (~(1 << 3)) & 0xff;
+	dat = 0;
+	return	qm1d1c004x_w(fe, 0x17, &dat, 1)		||
+		qm1d1c004x_w_tuner(fe, 0x01, reg[0x01])	||
+		qm1d1c004x_w_tuner(fe, 0x05, reg[0x05]);
+}
+
+int qm1d1c004x_tune(struct dvb_frontend *fe)
+{
+	u32	fgap_tab[9][3]	= {
+		{2151000, 1, 7},	{1950000, 1, 6},	{1800000, 1, 5},
+		{1600000, 1, 4},	{1450000, 1, 3},	{1250000, 1, 2},
+		{1200000, 0, 7},	{ 975000, 0, 6},	{ 950000, 0, 0}
+	};
+	u8	*reg	= ((struct qm1d1c004x *)fe->tuner_priv)->reg;
+	u32	kHz	= fe->dtv_property_cache.frequency - 500,
+		XtalkHz	= 16000,
+		i	= ((kHz + XtalkHz / 2) / XtalkHz) * XtalkHz;
+	s64	b	= kHz - i;
+	u8	N	= i / (4 * XtalkHz) - 3,
+		A	= (i / XtalkHz) - 4 * (N + 1) - 5;
+	int	sd	= b < 0 ? (0x100000 / XtalkHz) * b + 0x400000 : (0x100000 / XtalkHz) * b,
+		err	= qm1d1c004x_set_agc(fe, QM1D1C004X_AGC_MANUAL);
+
+	if (err)
+		return -EIO;
+
+	/* div2/vco_band */
+	for (i = 0; i < 8; i++)
+		if ((fgap_tab[i+1][0] <= kHz) && (kHz < fgap_tab[i][0]))
+			qm1d1c004x_w_tuner(fe, 0x02, (reg[0x02] & 0x0f) | fgap_tab[i][1] << 7 | fgap_tab[i][2] << 4);
+
+	reg[0x06] &= 0x40;
+	reg[0x06] |= N;
+	reg[0x07] &= 0xf0;
+	reg[0x07] |= A & 0x0f;
+
+	/* LPF */
+	reg[0x08] &= 0xf0;
+	reg[0x08] |= 0x09;
+	reg[0x13] &= 0x9f;
+	reg[0x13] |= 0x20;
+	err =	qm1d1c004x_w_tuner(fe, 0x06, reg[0x06])	||
+		qm1d1c004x_w_tuner(fe, 0x07, reg[0x07])	||
+		qm1d1c004x_w_tuner(fe, 0x08, (reg[0x08] & 0xf0) | 2);
+	if (err)
+		return err;
+	reg[0x09] &= 0xc0;
+	reg[0x09] |= (sd >> 16) & 0x3f;
+	reg[0x0a] = (sd >> 8) & 0xff;
+	reg[0x0b] = (sd >> 0) & 0xff;
+	err =	qm1d1c004x_w_tuner(fe, 0x09, reg[0x09])	||
+		qm1d1c004x_w_tuner(fe, 0x0a, reg[0x0a])	||
+		qm1d1c004x_w_tuner(fe, 0x0b, reg[0x0b])	||
+		qm1d1c004x_w_tuner(fe, 0x0c, reg[0x0c] & 0x3f);
+	if (err)
+		return err;
+	msleep_interruptible(1);
+	err =	qm1d1c004x_w_tuner(fe, 0x0c, reg[0x0c] | 0xc0)	||
+		qm1d1c004x_w_tuner(fe, 0x08, 0x09)		||
+		qm1d1c004x_w_tuner(fe, 0x13, reg[0x13]);
+	if (err)
+		return err;
+	for (i = 0; i < 500; i++) {
+		if (!qm1d1c004x_r(fe, 0x0d, &reg[0x0d]))
+			return -EIO;
+		if (reg[0x0d] & 0x40)	/* locked */
+			return qm1d1c004x_set_agc(fe, QM1D1C004X_AGC_AUTO);
+		msleep_interruptible(1);
+	}
+	return -ETIMEDOUT;
+}
+
+int qm1d1c004x_remove(struct i2c_client *t)
+{
+	kfree(i2c_get_clientdata(t));
+	return 0;
+}
+
+int qm1d1c004x_probe(struct i2c_client *t, const struct i2c_device_id *id)
+{
+	struct dvb_frontend	*fe	= t->dev.platform_data;
+	struct qm1d1c004x	*q	= kzalloc(sizeof(struct qm1d1c004x), GFP_KERNEL);
+	u8			d[]	= {0x10, 0x15, 0x04};
+
+	if (!q)
+		return -ENOMEM;
+	i2c_set_clientdata(t, q);
+	fe->ops.tuner_ops.set_params	= qm1d1c004x_tune;
+	fe->ops.tuner_ops.sleep		= qm1d1c004x_sleep;
+	fe->ops.tuner_ops.init		= qm1d1c004x_wakeup;
+	return	qm1d1c004x_w(fe, 0x1e, d,   1)	||
+		qm1d1c004x_w(fe, 0x1c, d+1, 1)	||
+		qm1d1c004x_w(fe, 0x1f, d+2, 1);
+}
+
+static struct i2c_device_id qm1d1c004x_id[] = {
+	{QM1D1C004X_MODNAME, 0},
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, qm1d1c004x_id);
+
+static struct i2c_driver qm1d1c004x_driver = {
+	.driver.name	= qm1d1c004x_id->name,
+	.probe		= qm1d1c004x_probe,
+	.remove		= qm1d1c004x_remove,
+	.id_table	= qm1d1c004x_id,
+};
+module_i2c_driver(qm1d1c004x_driver);
+
+MODULE_AUTHOR("Budi Rachmanto, AreMa Inc. <knightrider(@)are.ma>");
+MODULE_DESCRIPTION("Earthsoft PT3 QM1D1C004X ISDB-S tuner driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/media/tuners/qm1d1c004x.h b/drivers/media/tuners/qm1d1c004x.h
new file mode 100644
index 0000000..2fdf9cb
--- /dev/null
+++ b/drivers/media/tuners/qm1d1c004x.h
@@ -0,0 +1,23 @@
+/*
+	Sharp VA4M6JC2103 QM1D1C004x ISDB-S tuner driver
+
+	Copyright (C) Budi Rachmanto, AreMa Inc. <info@are.ma>
+
+	CHIP		VER.	CARD
+	QM1D1C0042	0x48	Earthsoft PT3
+	QM1D1C0045	0x58
+	QM1D1C0045_2	0x68	PLEX PX-BCUD
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+*/
+
+#ifndef QM1D1C004X_H
+#define QM1D1C004X_H
+
+#define QM1D1C004X_MODNAME "qm1d1c004x"
+
+#endif
+
diff --git a/drivers/media/tuners/tda2014x.c b/drivers/media/tuners/tda2014x.c
new file mode 100644
index 0000000..1253896
--- /dev/null
+++ b/drivers/media/tuners/tda2014x.c
@@ -0,0 +1,358 @@
+/*
+	Driver for NXP Semiconductors tuner TDA2014x
+
+	Copyright (C) Budi Rachmanto, AreMa Inc. <info@are.ma>
+*/
+
+#include "dvb_frontend.h"
+#include "tda2014x.h"
+
+int tda2014x_r(struct dvb_frontend *fe, u8 slvadr)
+{
+	struct i2c_client	*d	= fe->demodulator_priv;
+	u8		buf[]	= {0xFE, 0xA8, slvadr},
+			rcmd[]	= {0xFE, 0xA9},
+			ret	= 0;
+	struct i2c_msg	msg[]	= {
+		{.addr = d->addr,	.flags = 0,		.buf = buf,	.len = 3,},
+		{.addr = d->addr,	.flags = 0,		.buf = rcmd,	.len = 2,},
+		{.addr = d->addr,	.flags = I2C_M_RD,	.buf = &ret,	.len = 1,},
+	};
+	return i2c_transfer(d->adapter, msg, 3) == 3 ? ret : -EIO;
+}
+
+bool tda2014x_r8(struct dvb_frontend *fe, u16 slvadr, u8 start_bit, u8 nbits, u8 *rdat)
+{
+	u8	mask	= nbits > 7 ? 0xFF : ((1 << nbits) - 1) << start_bit;
+	int	val	= tda2014x_r(fe, slvadr);
+
+	if (val < 0)
+		return false;
+	*rdat = (val & mask) >> start_bit;
+	return true;
+}
+
+bool tda2014x_w8(struct dvb_frontend *fe, u8 slvadr, u8 dat)
+{
+	struct i2c_client	*d	= fe->demodulator_priv;
+	u8		buf[]	= {slvadr, dat};
+	struct i2c_msg	msg[]	= {
+		{.addr = d->addr,	.flags = 0,	.buf = buf,	.len = 2,},
+	};
+	return i2c_transfer(d->adapter, msg, 1) == 1;
+}
+
+bool tda2014x_w16(struct dvb_frontend *fe, u16 slvadr, u8 start_bit, u8 nbits, u8 nbytes, bool rmw, u8 access, u16 wdat)
+{
+	struct i2c_client	*d	= fe->demodulator_priv;
+	u16	mask	= nbits > 15 ? 0xFFFF : ((1 << nbits) - 1) << start_bit,
+		val	= mask & (wdat << start_bit);
+	u8	*wval	= (u8 *)&val,
+		i;
+
+	for (i = 0, nbytes = !nbytes ? 1 : nbytes > 2 ? 2 : nbytes; access & 2 && nbytes; i++, nbytes--) {
+		u8	buf[]	= {0xFE, 0xA8, slvadr + i, 0};
+		int	ret	= tda2014x_r(fe, slvadr + i);
+		struct i2c_msg msg[] = {
+			{.addr = d->addr,	.flags = 0,	.buf = buf,	.len = 4,},
+		};
+
+		if (ret < 0)
+			return false;
+		if (rmw)
+			wval[nbytes - 1] |= ~(mask >> 8 * i) & ret;
+		buf[3] = wval[nbytes - 1];
+		if (i2c_transfer(d->adapter, msg, 1) != 1)
+			return false;
+	}
+	return true;
+}
+
+int tda2014x_tune(struct dvb_frontend *fe)
+{
+	u64 div10(u64 n, u8 pow)
+	{
+		u64	q, r;
+
+		while (pow--) {
+			q = (n >> 1) + (n >> 2);
+			q = q + (q >> 4);
+			q = q + (q >> 8);
+			q = q + (q >> 16);
+			q = q >> 3;
+			r = n - (((q << 2) + q) << 1);
+			n = q + (r > 9);
+		}
+		return n;
+	}
+
+	enum {
+		TDA2014X_LNA_GAIN_7dB	= 0x0,
+		TDA2014X_LNA_GAIN_10dB	= 0x1,
+		TDA2014X_LNA_GAIN_13dB	= 0x2,		/* default */
+		TDA2014X_LNA_GAIN_18dB	= 0x3,
+		TDA2014X_LNA_GAIN_NEGATIVE_11dB = 0x4,
+
+		TDA2014X_LPT_GAIN_NEGATIVE_8dB	= 0x0,
+		TDA2014X_LPT_GAIN_NEGATIVE_10dB	= 0x1,	/* default */
+		TDA2014X_LPT_GAIN_NEGATIVE_14dB	= 0x2,
+		TDA2014X_LPT_GAIN_NEGATIVE_16dB	= 0x3,
+
+		TDA2014X_AMPOUT_15DB	= 0x0,
+		TDA2014X_AMPOUT_18DB	= 0x1,
+		TDA2014X_AMPOUT_18DB_b	= 0x2,
+		TDA2014X_AMPOUT_21DB	= 0x3,		/* default */
+		TDA2014X_AMPOUT_24DB	= 0x6,		/* ok too */
+		TDA2014X_AMPOUT_27DB	= 0x7,
+		TDA2014X_AMPOUT_30DB	= 0xE,
+		TDA2014X_AMPOUT_33DB	= 0xF,
+	};
+	bool	bDoublerEnable[]		= {false, true, true, true, true},
+		bDcc1Enable[]			= {false, true, true, true, true},
+		bDcc2Enable[]			= {false, true, true, true, true},
+		bPpfEnable[]			= {false, true, true, true, true},
+		bDiv1ConfigInDivideBy3[]	= {false, true, false, true, false},
+		bDiv2ConfigInDivideBy3[]	= {false, true, true, false, false},
+		bSelectDivideBy4Or5Or6Or7Path[]	= {false, true, true, true, true},
+		bSelectDivideBy8Path[]		= {true, false, false, false, false},
+		bInputMuxEnable;
+	u8	PredividerRatio,
+		val;
+	u32	kHz = fe->dtv_property_cache.frequency;
+	u64	ResLsb,
+		CalcPow = 6,
+		Premain,
+		R,
+		kint,
+		Nint,
+		DsmFracInReg,
+		DsmIntInReg,
+		v15;
+	int	ePllRefClkRatio,
+		i = kHz <= 1075000 ? 0 : kHz <= 1228000 ? 1 : kHz <= 1433000 ? 2 : kHz <= 1720000 ? 3 : 4,
+		lna	= TDA2014X_LNA_GAIN_13dB,
+		gain	= (lna == TDA2014X_LNA_GAIN_18dB) | ((lna & 3) << 4) | (TDA2014X_LPT_GAIN_NEGATIVE_10dB << 1),
+		ampout	= TDA2014X_AMPOUT_21DB;
+
+	/* GetLoConfig */
+	if (!tda2014x_r8(fe, 0x25, 3, 1, &val))
+		return -EIO;
+	bInputMuxEnable = val;
+
+	/* SetLoConfig */
+	if (tda2014x_w16(fe, 0x22, 0, 8, 0, 0, 6,
+		(bDoublerEnable[i] << 7) | (bDcc1Enable[i] << 6) | (bDcc2Enable[i] << 5) | 0b11110 | bPpfEnable[i]) &&
+		tda2014x_r8(fe, 0x23, 0, 8, &val) &&
+		tda2014x_w16(fe, 0x23, 0, 8, 0, 0, 6, (bDiv1ConfigInDivideBy3[i] << 7) | (bDiv2ConfigInDivideBy3[i] << 5) |
+			(bSelectDivideBy4Or5Or6Or7Path[i] << 3) | (bSelectDivideBy8Path[i] << 2) | (val & 0b1010011)))
+		tda2014x_w16(fe, 0x25, 3, 1, 0, 1, 6, bInputMuxEnable);
+
+	ResLsb = (8 - i) * kHz * 1000UL / 27UL;	/* Xtal 27 MHz */
+	kint = ResLsb;
+	v15 = div10(ResLsb, 6);
+	R = 1;
+	Premain = 1;
+	Nint = (v15 * R) >> Premain;
+	if (Nint < 131) {
+		Premain = 0;
+		Nint = (v15 * R) >> Premain;
+		if (Nint > 251) {
+			R = 3;
+			Premain = 2;
+			goto LABEL_36;
+		}
+		if (Nint < 131) {
+			R = 3;
+			Premain = 1;
+			goto LABEL_36;
+		}
+	} else if (Nint > 251) {
+		Premain = 2;
+		Nint = (v15 * R) >> Premain;
+		if (Nint > 251) {
+			R = 3;
+			Premain = 2;
+		}
+LABEL_36:
+		Nint = (v15 * R) >> Premain;
+		if (Nint < 131 || Nint > 251)
+			return -ERANGE;
+	}
+	switch ((100 * R) >> Premain) {
+	case 25:
+		kint = ResLsb / 4;
+		break;
+	case 50:
+		kint = ResLsb / 2;
+		break;
+	case 75:
+		kint = ResLsb / 2 + ResLsb / 4;
+		break;
+	case 100:
+		break;
+	case 150:
+		kint = ResLsb / 2 + ResLsb;
+		break;
+	default:
+		return -ERANGE;
+	}
+	kint		= div10(kint, 1) * 10;
+	ePllRefClkRatio	= R == 2 ? 1 : R == 3 ? 2 : 0;
+	PredividerRatio	= Premain == 1 ? 0 : 1;
+	DsmIntInReg	= div10(kint, 6);
+	DsmFracInReg	= kint - 1000000 * DsmIntInReg;
+	for (i = 0; i < 16; i++) {
+		DsmFracInReg *= 2;
+		if (DsmFracInReg > 0xFFFFFFF && i != 15) {
+			DsmFracInReg = div10(DsmFracInReg, 1);
+			CalcPow--;
+		}
+	}
+	return	!(tda2014x_w16(fe, 3, 6, 2, 0, 1, 6, ePllRefClkRatio)	&&
+
+		/* SetPllDividerConfig */
+		tda2014x_w16(fe, 0x1A, 5, 1, 0, 1, 6, PredividerRatio)			&&
+		tda2014x_w16(fe, 0x1E, 0, 8, 0, 0, 6, DsmIntInReg - 128)		&&
+		tda2014x_w16(fe, 0x1F, 0, 0x10, 2, 0, 6, div10(DsmFracInReg, CalcPow))	&&
+
+		/* ProgramVcoChannelChange */
+		tda2014x_r8(fe, 0x12, 0, 8, &val)				&&
+		tda2014x_w16(fe, 0x12, 0, 8, 0, 0, 6, (val & 0x7F) | 0x40)	&&
+		tda2014x_w16(fe, 0x13, 0, 2, 0, 1, 6, 2)			&&
+		tda2014x_w16(fe, 0x13, 7, 1, 0, 1, 6, 0)			&&
+		tda2014x_w16(fe, 0x13, 5, 1, 0, 1, 6, 1)			&&
+		tda2014x_w16(fe, 0x13, 5, 1, 0, 1, 6, 1)			&&
+		tda2014x_w16(fe, 0x13, 7, 1, 0, 1, 6, 0)			&&
+		tda2014x_w16(fe, 0x13, 4, 1, 0, 1, 6, 1)			&&
+		((tda2014x_r8(fe, 0x15, 4, 1, &val) && val == 1)		||
+		(tda2014x_r8(fe, 0x15, 4, 1, &val) && val == 1))		&&
+		tda2014x_w16(fe, 0x13, 4, 1, 0, 1, 6, 0)			&&
+		tda2014x_r8(fe, 0x12, 0, 8, &val)				&&
+		tda2014x_w16(fe, 0x12, 0, 8, 0, 0, 6, val & 0x7F)		&&
+
+		/* SetFilterBandwidth */
+		tda2014x_w16(fe, 0xA, 0, 4, 0, 1, 6, 0xA)	&&
+		tda2014x_w16(fe, 0xB, 1, 7, 0, 1, 6, 0x7C)	&&
+
+		/* SetGainConfig */
+		tda2014x_r8(fe, 6, 0, 8, &val)					&&
+		tda2014x_w16(fe, 6, 0, 8, 0, 0, 6, (val & 0x48) | 0x80 | gain)	&&
+		tda2014x_r8(fe, 9, 0, 8, &val)					&&
+		tda2014x_w16(fe, 9, 0, 8, 0, 0, 6, 0b10110000 | (val & 3))	&&
+		tda2014x_w16(fe, 0xA, 5, 3, 0, 1, 6, 3)				&&
+		tda2014x_w16(fe, 0xC, 4, 4, 0, 1, 6, ampout)			&&
+
+		tda2014x_w8(fe, 0xA, 0xFF)	&&
+		tda2014x_w8(fe, 0x10, 0xB2)	&&
+		tda2014x_w8(fe, 0x11, 0)	&&
+		tda2014x_w8(fe, 3, 1)) * -EIO;
+}
+
+int tda2014x_probe(struct i2c_client *c, const struct i2c_device_id *id)
+{
+	u8			val	= 0;
+	struct dvb_frontend	*fe	= c->dev.platform_data;
+
+	fe->ops.tuner_ops.set_params	= tda2014x_tune;
+	fe->dtv_property_cache.frequency = 1318000;
+	return	!(tda2014x_w8(fe, 0x13, 0)	&&
+		tda2014x_w8(fe, 0x15, 0)	&&
+		tda2014x_w8(fe, 0x17, 0)	&&
+		tda2014x_w8(fe, 0x1C, 0)	&&
+		tda2014x_w8(fe, 0x1D, 0)	&&
+		tda2014x_w8(fe, 0x1F, 0)	&&
+		(tda2014x_w8(fe, 7, 0x31), tda2014x_w8(fe, 8, 0x77), tda2014x_w8(fe, 4, 2))	&&
+
+		/* SetPowerMode */
+		tda2014x_r8(fe, 2, 0, 8, &val)					&&
+		tda2014x_w16(fe, 2, 0, 8, 0, 0, 6, val | 0x81)			&&
+		tda2014x_r8(fe, 6, 0, 8, &val)					&&
+		tda2014x_w16(fe, 6, 0, 8, 0, 0, 6, (val | 0x39) & 0x7F)		&&
+		tda2014x_r8(fe, 7, 0, 8, &val)					&&
+		tda2014x_w16(fe, 7, 0, 8, 0, 0, 6, val | 0xAE)			&&
+		tda2014x_r8(fe, 0xF, 0, 8, &val)				&&
+		tda2014x_w16(fe, 0xF, 0, 8, 0, 0, 6, val | 0x80)		&&
+		tda2014x_r8(fe, 0x18, 0, 8, &val)				&&
+		tda2014x_w16(fe, 0x18, 0, 8, 0, 0, 6, val & 0x7F)		&&
+		tda2014x_r8(fe, 0x1A, 0, 8, &val)				&&
+		tda2014x_w16(fe, 0x1A, 0, 8, 0, 0, 6, val | 0xC0)		&&
+		tda2014x_w16(fe, 0x22, 0, 8, 0, 0, 6, 0xFF)			&&
+		tda2014x_r8(fe, 0x23, 0, 8, &val)				&&
+		tda2014x_w16(fe, 0x23, 0, 8, 0, 0, 6, val & 0xFE)		&&
+		tda2014x_r8(fe, 0x25, 0, 8, &val)				&&
+		tda2014x_w16(fe, 0x25, 0, 8, 0, 0, 6, val | 8)			&&
+		tda2014x_r8(fe, 0x27, 0, 8, &val)				&&
+		tda2014x_w16(fe, 0x27, 0, 8, 0, 0, 6, (val | 0xC0) & 0xDF)	&&
+		tda2014x_r8(fe, 0x24, 0, 8, &val)				&&
+		tda2014x_w16(fe, 0x24, 0, 8, 0, 0, 6, (val | 4) & 0xCF)		&&
+		tda2014x_r8(fe, 0xD, 0, 8, &val)				&&
+		tda2014x_w16(fe, 0xD, 0, 8, 0, 0, 6, val & 0xDF)		&&
+		tda2014x_r8(fe, 9, 0, 8, &val)					&&
+		tda2014x_w16(fe, 9, 0, 8, 0, 0, 6, (val | 0xB0) & 0xB1)		&&
+		tda2014x_r8(fe, 0xA, 0, 8, &val)				&&
+		tda2014x_w16(fe, 0xA, 0, 8, 0, 0, 6, (val | 0x6F) & 0x7F)	&&
+		tda2014x_r8(fe, 0xB, 0, 8, &val)				&&
+		tda2014x_w16(fe, 0xB, 0, 8, 0, 0, 6, (val | 0x7A) & 0x7B)	&&
+		tda2014x_w16(fe, 0xC, 0, 8, 0, 0, 6, 0)				&&
+		tda2014x_w16(fe, 0x19, 0, 8, 0, 0, 6, 0xFA)			&&
+		tda2014x_r8(fe, 0x1B, 0, 8, &val)				&&
+		tda2014x_w16(fe, 0x1B, 0, 8, 0, 0, 6, val & 0x7F)		&&
+		tda2014x_r8(fe, 0x21, 0, 8, &val)				&&
+		tda2014x_w16(fe, 0x21, 0, 8, 0, 0, 6, val | 0x40)		&&
+		tda2014x_r8(fe, 0x10, 0, 8, &val)				&&
+		tda2014x_w16(fe, 0x10, 0, 8, 0, 0, 6, (val | 0x90) & 0xBF)	&&
+		tda2014x_r8(fe, 0x14, 0, 8, &val)				&&
+		tda2014x_w16(fe, 0x14, 0, 8, 0, 0, 6, (val | 0x20) & 0xEF)	&&
+
+		/* ProgramPllPor */
+		tda2014x_w16(fe, 0x1A, 6, 1, 0, 1, 6, 1)	&&
+		tda2014x_w16(fe, 0x18, 0, 1, 0, 1, 6, 1)	&&
+		tda2014x_w16(fe, 0x18, 7, 1, 0, 1, 6, 1)	&&
+		tda2014x_w16(fe, 0x1B, 7, 1, 0, 1, 6, 1)	&&
+		tda2014x_w16(fe, 0x18, 0, 1, 0, 1, 6, 0)	&&
+
+		/* ProgramVcoPor */
+		tda2014x_r8(fe, 0xF, 0, 8, &val)						&&
+		(val = (val & 0x1F) | 0x80, tda2014x_w16(fe, 0xF, 0, 8, 0, 0, 6, val))		&&
+		tda2014x_r8(fe, 0x13, 0, 8, &val)						&&
+		(val = (val & 0xFFFFFFCF) | 0x20, tda2014x_w16(fe, 0x13, 0, 8, 0, 0, 6, val))	&&
+		tda2014x_r8(fe, 0x12, 0, 8, &val)				&&
+		(val |= 0xC0, tda2014x_w16(fe, 0x12, 0, 8, 0, 0, 6, val))	&&
+		tda2014x_w16(fe, 0x10, 5, 1, 0, 1, 6, 1)			&&
+		tda2014x_w16(fe, 0x10, 5, 1, 0, 1, 6, 1)			&&
+		tda2014x_w16(fe, 0xF, 5, 1, 0, 1, 6, 1)				&&
+		tda2014x_r8(fe, 0x11, 4, 1, &val)				&&
+		(val || tda2014x_r8(fe, 0x11, 4, 1, &val))			&&
+		(val || tda2014x_r8(fe, 0x11, 4, 1, &val))			&&
+		val								&&
+		tda2014x_r8(fe, 0x10, 0, 4, &val)				&&
+		tda2014x_w16(fe, 0xF, 0, 4, 0, 1, 6, val)			&&
+		tda2014x_w16(fe, 0xF, 6, 1, 0, 1, 6, 1)				&&
+		tda2014x_w16(fe, 0xF, 5, 1, 0, 1, 6, 0)				&&
+		tda2014x_r8(fe, 0x12, 0, 8, &val)				&&
+		(val &= 0x7F, tda2014x_w16(fe, 0x12, 0, 8, 0, 0, 6, val))	&&
+		tda2014x_w16(fe, 0xD, 5, 2, 0, 1, 6, 1)				&&
+
+		/* EnableLoopThrough */
+		tda2014x_r8(fe, 6, 0, 8, &val)					&&
+		tda2014x_w16(fe, 6, 0, 8, 0, 0, 6, (val & 0xF7) | 8)) * -EIO	||
+
+		tda2014x_tune(fe);
+}
+
+static struct i2c_device_id tda2014x_id[] = {
+	{TDA2014X_MODNAME, 0},
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, tda2014x_id);
+
+static struct i2c_driver tda2014x_driver = {
+	.driver.name	= tda2014x_id->name,
+	.probe		= tda2014x_probe,
+	.id_table	= tda2014x_id,
+};
+module_i2c_driver(tda2014x_driver);
+
+MODULE_AUTHOR("Budi Rachmanto, AreMa Inc. <info@are.ma>");
+MODULE_DESCRIPTION("Driver for NXP Semiconductors tuner TDA2014x");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/tuners/tda2014x.h b/drivers/media/tuners/tda2014x.h
new file mode 100644
index 0000000..36f8198
--- /dev/null
+++ b/drivers/media/tuners/tda2014x.h
@@ -0,0 +1,13 @@
+/*
+ * Driver for NXP Semiconductors tuner TDA2014x
+ *
+ * Copyright (C) Budi Rachmanto, AreMa Inc. <info@are.ma>
+ */
+
+#ifndef	TDA2014X_H
+#define	TDA2014X_H
+
+#define TDA2014X_MODNAME "tda2014x"
+
+#endif
+
-- 
2.7.4

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

* [media 5/6] PCIE bridge driver for PT3 & PX-Q3PE
  2016-04-04 17:03 [media 0/6] DVB driver for Earthsoft PT3, PLEX PX-Q3PE ISDB-S/T PCIE cards & PX-BCUD ISDB-S USB dongle info
                   ` (3 preceding siblings ...)
  2016-04-04 17:04 ` [media 4/6] Tuners " info
@ 2016-04-04 17:04 ` info
  2016-04-04 17:30   ` kbuild test robot
                     ` (2 more replies)
  2016-04-04 17:04 ` [media 6/6] Bridge driver for PLEX PX-BCUD ISDB-S USB dongle info
  5 siblings, 3 replies; 10+ messages in thread
From: info @ 2016-04-04 17:04 UTC (permalink / raw)
  To: linux-media
  Cc: Буди
	Романто,
	AreMa Inc, linux-kernel, crope, m.chehab, mchehab, hdegoede,
	laurent.pinchart, mkrufky, sylvester.nawrocki, g.liakhovetski,
	peter.senna

From: Буди Романто, AreMa Inc <knightrider@are.ma>

Please read cover letter for details.

Signed-off-by: Буди Романто, AreMa Inc <knightrider@are.ma>
---
 drivers/media/pci/Kconfig          |   2 +-
 drivers/media/pci/Makefile         |   2 +-
 drivers/media/pci/ptx/Kconfig      |  23 ++
 drivers/media/pci/ptx/Makefile     |   6 +
 drivers/media/pci/ptx/pt3.c        | 426 +++++++++++++++++++++++++++
 drivers/media/pci/ptx/ptx_common.c | 266 +++++++++++++++++
 drivers/media/pci/ptx/ptx_common.h |  76 +++++
 drivers/media/pci/ptx/pxq3pe.c     | 585 +++++++++++++++++++++++++++++++++++++
 8 files changed, 1384 insertions(+), 2 deletions(-)
 create mode 100644 drivers/media/pci/ptx/Kconfig
 create mode 100644 drivers/media/pci/ptx/Makefile
 create mode 100644 drivers/media/pci/ptx/pt3.c
 create mode 100644 drivers/media/pci/ptx/ptx_common.c
 create mode 100644 drivers/media/pci/ptx/ptx_common.h
 create mode 100644 drivers/media/pci/ptx/pxq3pe.c

diff --git a/drivers/media/pci/Kconfig b/drivers/media/pci/Kconfig
index 48a611b..9d63ad6 100644
--- a/drivers/media/pci/Kconfig
+++ b/drivers/media/pci/Kconfig
@@ -44,7 +44,7 @@ source "drivers/media/pci/b2c2/Kconfig"
 source "drivers/media/pci/pluto2/Kconfig"
 source "drivers/media/pci/dm1105/Kconfig"
 source "drivers/media/pci/pt1/Kconfig"
-source "drivers/media/pci/pt3/Kconfig"
+source "drivers/media/pci/ptx/Kconfig"
 source "drivers/media/pci/mantis/Kconfig"
 source "drivers/media/pci/ngene/Kconfig"
 source "drivers/media/pci/ddbridge/Kconfig"
diff --git a/drivers/media/pci/Makefile b/drivers/media/pci/Makefile
index 5f8aacb..984e37c 100644
--- a/drivers/media/pci/Makefile
+++ b/drivers/media/pci/Makefile
@@ -7,7 +7,7 @@ obj-y        +=	ttpci/		\
 		pluto2/		\
 		dm1105/		\
 		pt1/		\
-		pt3/		\
+		ptx/		\
 		mantis/		\
 		ngene/		\
 		ddbridge/	\
diff --git a/drivers/media/pci/ptx/Kconfig b/drivers/media/pci/ptx/Kconfig
new file mode 100644
index 0000000..53ec5ea
--- /dev/null
+++ b/drivers/media/pci/ptx/Kconfig
@@ -0,0 +1,23 @@
+config DVB_PT3
+	tristate "Earthsoft PT3 cards"
+	depends on DVB_CORE && PCI && I2C
+	select DVB_PTX_COMMON
+	select DVB_TC90522 if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_QM1D1C004X if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_MXL301RF if MEDIA_SUBDRV_AUTOSELECT
+	help
+	  Support for Earthsoft PT3 ISDB-S/T PCIe cards.
+
+	  Say Y or M if you own such a device and want to use it.
+
+config DVB_PXQ3PE
+	tristate "PLEX PX-Q3PE cards"
+	depends on DVB_CORE && PCI && I2C
+	select DVB_PTX_COMMON
+	select DVB_TC90522 if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_QM1D1C004X if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_MXL301RF if MEDIA_SUBDRV_AUTOSELECT
+	help
+	  Support for PLEX PX-Q3PE ISDB-S/T PCIe cards.
+
+	  Say Y or M if you own such a device and want to use it.
diff --git a/drivers/media/pci/ptx/Makefile b/drivers/media/pci/ptx/Makefile
new file mode 100644
index 0000000..9c41328
--- /dev/null
+++ b/drivers/media/pci/ptx/Makefile
@@ -0,0 +1,6 @@
+obj-$(CONFIG_DVB_PTX_COMMON)	+= ptx_common.o
+obj-$(CONFIG_DVB_PT3)		+= pt3.o
+obj-$(CONFIG_DVB_PXQ3PE)	+= pxq3pe.o
+
+ccflags-y += -Idrivers/media/dvb-core -Idrivers/media/dvb-frontends -Idrivers/media/tuners
+
diff --git a/drivers/media/pci/ptx/pt3.c b/drivers/media/pci/ptx/pt3.c
new file mode 100644
index 0000000..0b45504
--- /dev/null
+++ b/drivers/media/pci/ptx/pt3.c
@@ -0,0 +1,426 @@
+/*
+	DVB driver for Earthsoft PT3 ISDB-S/T PCIE bridge Altera Cyclone IV FPGA EP4CGX15BF14C8N
+
+	Copyright (C) Budi Rachmanto, AreMa Inc. <info@are.ma>
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+*/
+
+#include "tc90522.h"
+#include "qm1d1c004x.h"
+#include "mxl301rf.h"
+#include "ptx_common.h"
+
+MODULE_AUTHOR(PTX_AUTH);
+MODULE_DESCRIPTION("Earthsoft PT3 DVB Driver");
+MODULE_LICENSE("GPL");
+
+static struct pci_device_id pt3_id[] = {
+	{PCI_DEVICE(0x1172, 0x4c15)},
+	{},
+};
+MODULE_DEVICE_TABLE(pci, pt3_id);
+
+enum ePT3 {
+	PT3_REG_VERSION	= 0x00,	/*	R	Version		*/
+	PT3_REG_BUS	= 0x04,	/*	R	Bus		*/
+	PT3_REG_SYS_W	= 0x08,	/*	W	System		*/
+	PT3_REG_SYS_R	= 0x0c,	/*	R	System		*/
+	PT3_REG_I2C_W	= 0x10,	/*	W	I2C		*/
+	PT3_REG_I2C_R	= 0x14,	/*	R	I2C		*/
+	PT3_REG_RAM_W	= 0x18,	/*	W	RAM		*/
+	PT3_REG_RAM_R	= 0x1c,	/*	R	RAM		*/
+	PT3_DMA_BASE	= 0x40,	/* + 0x18*idx			*/
+	PT3_DMA_OFFSET	= 0x18,
+	PT3_DMA_DESC	= 0x00,	/*	W	DMA descriptor	*/
+	PT3_DMA_CTL	= 0x08,	/*	W	DMA		*/
+	PT3_TS_CTL	= 0x0c,	/*	W	TS		*/
+	PT3_STATUS	= 0x10,	/*	R	DMA/FIFO/TS	*/
+	PT3_TS_ERR	= 0x14,	/*	R	TS		*/
+
+	PT3_I2C_DATA_OFFSET	= 0x800,
+	PT3_I2C_START_ADDR	= 0x17fa,
+
+	PT3_PWR_OFF		= 0x00,
+	PT3_PWR_AMP_ON		= 0x04,
+	PT3_PWR_TUNER_ON	= 0x40,
+};
+
+struct pt3_card {
+	void __iomem	*bar_reg,
+			*bar_mem;
+};
+
+struct pt3_dma {
+	dma_addr_t	adr;
+	u8		*dat;
+	u32		sz;
+};
+
+struct pt3_adap {
+	u32	ts_blk_idx,
+		ts_blk_cnt,
+		desc_pg_cnt;
+	void __iomem	*dma_base;
+	struct pt3_dma	*ts_info,
+			*desc_info;
+};
+
+int pt3_i2c_flush(struct pt3_card *c, u32 start_addr)
+{
+	u32	val	= 0b0110,
+		i	= 999;
+
+	void i2c_wait(void)
+	{
+		while (1) {
+			val = readl(c->bar_reg + PT3_REG_I2C_R);
+
+			if (!(val & 1))						/* sequence stopped */
+				return;
+			msleep_interruptible(0);
+		}
+	}
+
+	while ((val & 0b0110) && i--) {						/* I2C bus is dirty */
+		i2c_wait();
+		writel(1 << 16 | start_addr, c->bar_reg + PT3_REG_I2C_W);	/* 0x00010000 start sequence */
+		i2c_wait();
+	}
+	return val & 0b0110 ? -EIO : 0;						/* ACK status */
+}
+
+int pt3_i2c_xfr(struct i2c_adapter *i2c, struct i2c_msg *msg, int sz)
+{
+	enum pt3_i2c_cmd {
+		I_END,
+		I_ADDRESS,
+		I_CLOCK_L,
+		I_CLOCK_H,
+		I_DATA_L,
+		I_DATA_H,
+		I_RESET,
+		I_SLEEP,
+		I_DATA_L_NOP	= 0x08,
+		I_DATA_H_NOP	= 0x0c,
+		I_DATA_H_READ	= 0x0d,
+		I_DATA_H_ACK0	= 0x0e,
+	};
+	struct ptx_card *card	= i2c_get_adapdata(i2c);
+	struct pt3_card *c	= card->priv;
+	u32	offset		= 0;
+	u8	buf;
+	bool	filled		= false;
+
+	void i2c_shoot(u8 dat)
+	{
+		if (filled) {
+			buf |= dat << 4;
+			writeb(buf, c->bar_mem + PT3_I2C_DATA_OFFSET + offset);
+			offset++;
+		} else
+			buf = dat;
+		filled ^= true;
+	}
+
+	void i2c_w(const u8 *dat, u32 size)
+	{
+		u32 i, j;
+
+		for (i = 0; i < size; i++) {
+			for (j = 0; j < 8; j++)
+				i2c_shoot((dat[i] >> (7 - j)) & 1 ? I_DATA_H_NOP : I_DATA_L_NOP);
+			i2c_shoot(I_DATA_H_ACK0);
+		}
+	}
+
+	void i2c_r(u32 size)
+	{
+		u32 i, j;
+
+		for (i = 0; i < size; i++) {
+			for (j = 0; j < 8; j++)
+				i2c_shoot(I_DATA_H_READ);
+			if (i == (size - 1))
+				i2c_shoot(I_DATA_H_NOP);
+			else
+				i2c_shoot(I_DATA_L_NOP);
+		}
+	}
+	int i, j;
+
+	if (sz < 1 || sz > 3 || !msg || msg[0].flags)		/* always write first */
+		return -ENOTSUPP;
+	mutex_lock(&card->lock);
+	for (i = 0; i < sz; i++) {
+		u8 byte = (msg[i].addr << 1) | (msg[i].flags & 1);
+
+		/* start */
+		i2c_shoot(I_DATA_H);
+		i2c_shoot(I_CLOCK_H);
+		i2c_shoot(I_DATA_L);
+		i2c_shoot(I_CLOCK_L);
+		i2c_w(&byte, 1);
+		if (msg[i].flags == I2C_M_RD)
+			i2c_r(msg[i].len);
+		else
+			i2c_w(msg[i].buf, msg[i].len);
+	}
+
+	/* stop */
+	i2c_shoot(I_DATA_L);
+	i2c_shoot(I_CLOCK_H);
+	i2c_shoot(I_DATA_H);
+	i2c_shoot(I_END);
+	if (filled)
+		i2c_shoot(I_END);
+	if (pt3_i2c_flush(c, 0))
+		sz = -EIO;
+	else
+		for (i = 1; i < sz; i++)
+			if (msg[i].flags == I2C_M_RD)
+				for (j = 0; j < msg[i].len; j++)
+					msg[i].buf[j] = readb(c->bar_mem + PT3_I2C_DATA_OFFSET + j);
+	mutex_unlock(&card->lock);
+	return sz;
+}
+
+static const struct i2c_algorithm pt3_i2c_algo = {
+	.functionality	= ptx_i2c_func,
+	.master_xfer	= pt3_i2c_xfr,
+};
+
+void pt3_lnb(struct ptx_card *card, bool lnb)
+{
+	struct pt3_card *c = card->priv;
+
+	writel(lnb ? 15 : 12, c->bar_reg + PT3_REG_SYS_W);
+}
+
+int pt3_power(struct dvb_frontend *fe, u8 pwr)
+{
+	struct i2c_client	*d	= fe->demodulator_priv;
+	u8		buf[]	= {0x1E, pwr | 0b10011001};
+	struct i2c_msg	msg[]	= {
+		{.addr = d->addr,	.flags = 0,	.buf = buf,	.len = 2,},
+	};
+
+	return i2c_transfer(d->adapter, msg, 1) == 1 ? 0 : -EIO;
+}
+
+int pt3_dma_run(struct ptx_adap *adap, bool ON)
+{
+	struct pt3_adap	*p	= adap->priv;
+	void __iomem	*base	= p->dma_base;
+	int		i	= 999;
+
+	if (ON) {
+		for (i = 0; i < p->ts_blk_cnt; i++)		/* 17 */
+			*p->ts_info[i].dat	= PTX_TS_NOT_SYNC;
+		p->ts_blk_idx = 0;
+		writel(2, base + PT3_DMA_CTL);			/* stop DMA */
+		writel(p->desc_info->adr & 0xffffffff, base + PT3_DMA_DESC);
+		writel((u64)p->desc_info->adr >> 32, base + PT3_DMA_DESC + 4);
+		writel(1, base + PT3_DMA_CTL);			/* start DMA */
+	} else {
+		writel(2, base + PT3_DMA_CTL);			/* stop DMA */
+		while (i--) {
+			if (!(readl(base + PT3_STATUS) & 1))
+				break;
+			msleep_interruptible(0);
+		}
+	}
+	return i ? 0 : -ETIMEDOUT;
+}
+
+int pt3_thread(void *dat)
+{
+	struct ptx_adap	*adap	= dat;
+	struct pt3_adap	*p	= adap->priv;
+	struct pt3_dma	*ts;
+
+	set_freezable();
+	while (!kthread_should_stop()) {
+		u32 next = (p->ts_blk_idx + 1) % p->ts_blk_cnt;
+
+		try_to_freeze();
+		ts = p->ts_info + next;
+		if (*ts->dat != PTX_TS_SYNC) {		/* wait until 1 TS block is full */
+			schedule_timeout_interruptible(0);
+			continue;
+		}
+		ts = p->ts_info + p->ts_blk_idx;
+		dvb_dmx_swfilter_packets(&adap->demux, ts->dat, ts->sz / PTX_TS_SIZE);
+		*ts->dat	= PTX_TS_NOT_SYNC;	/* mark as read */
+		p->ts_blk_idx	= next;
+	}
+	return 0;
+}
+
+void pt3_remove(struct pci_dev *pdev)
+{
+	struct ptx_card	*card	= pci_get_drvdata(pdev);
+	struct pt3_card	*c;
+	struct ptx_adap	*adap;
+	int		i;
+
+	if (!card)
+		return;
+	c	= card->priv;
+	adap	= card->adap;
+	for (i = 0; i < card->adapn; i++, adap++) {
+		struct pt3_adap	*p	= adap->priv;
+		struct pt3_dma	*page;
+		u32		j;
+
+		pt3_dma_run(adap, false);
+		if (p->ts_info) {
+			for (j = 0; j < p->ts_blk_cnt; j++) {
+				page = &p->ts_info[j];
+				if (page->dat)
+					pci_free_consistent(adap->card->pdev, page->sz, page->dat, page->adr);
+			}
+			kfree(p->ts_info);
+		}
+		if (p->desc_info) {
+			for (j = 0; j < p->desc_pg_cnt; j++) {
+				page = &p->desc_info[j];
+				if (page->dat)
+					pci_free_consistent(adap->card->pdev, page->sz, page->dat, page->adr);
+			}
+			kfree(p->desc_info);
+		}
+		if (adap->fe) {
+			ptx_sleep(adap->fe);
+			pt3_power(adap->fe, PT3_PWR_OFF);
+		}
+	}
+	ptx_unregister_adap(card);
+	if (c->bar_reg)
+		iounmap(c->bar_reg);
+	if (c->bar_mem)
+		iounmap(c->bar_mem);
+}
+
+int pt3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	struct ptx_adap	*adap;
+	struct pt3_card	*c;
+	struct ptx_subdev_info	pt3_subdev_info[] = {
+		{SYS_ISDBS, 0b00010001, TC90522_MODNAME, 0x63, QM1D1C004X_MODNAME},
+		{SYS_ISDBS, 0b00010011, TC90522_MODNAME, 0x60, QM1D1C004X_MODNAME},
+		{SYS_ISDBT, 0b00010000, TC90522_MODNAME, 0x62, MXL301RF_MODNAME},
+		{SYS_ISDBT, 0b00010010, TC90522_MODNAME, 0x61, MXL301RF_MODNAME},
+	};
+	struct ptx_card	*card	= ptx_alloc(pdev, KBUILD_MODNAME, ARRAY_SIZE(pt3_subdev_info),
+					sizeof(struct pt3_card), sizeof(struct pt3_adap), pt3_lnb);
+
+	bool dma_create(struct pt3_adap	*p)
+	{
+		struct dma_desc {
+			u64 page_addr;
+			u32 page_size;
+			u64 next_desc;
+		} __packed;		/* 20B */
+		enum {
+			DESC_SZ		= sizeof(struct dma_desc),		/* 20B	*/
+			DESC_MAX	= 4096 / DESC_SZ,			/* 204	*/
+			DESC_PAGE_SZ	= DESC_MAX * DESC_SZ,			/* 4080	*/
+			TS_PAGE_CNT	= PTX_TS_SIZE / 4,			/* 47	*/
+			TS_BLOCK_CNT	= 17,
+		};
+		struct pt3_dma	*descinfo;
+		struct dma_desc	*prev		= NULL,
+				*curr		= NULL;
+		u32		i,
+				j,
+				desc_todo	= 0,
+				desc_pg_idx	= 0;
+		u64		desc_addr	= 0;
+
+		p->ts_blk_cnt	= TS_BLOCK_CNT;							/* 17	*/
+		p->desc_pg_cnt	= roundup(TS_PAGE_CNT * p->ts_blk_cnt, DESC_MAX);		/* 4	*/
+		p->ts_info	= kcalloc(p->ts_blk_cnt, sizeof(struct pt3_dma), GFP_KERNEL);
+		p->desc_info	= kcalloc(p->desc_pg_cnt, sizeof(struct pt3_dma), GFP_KERNEL);
+		if (!p->ts_info || !p->desc_info)
+			return false;
+		for (i = 0; i < p->desc_pg_cnt; i++) {						/* 4	*/
+			p->desc_info[i].sz	= DESC_PAGE_SZ;					/* 4080B, max 204 * 4 = 816 descs */
+			p->desc_info[i].dat	= pci_alloc_consistent(card->pdev, p->desc_info[i].sz, &p->desc_info[i].adr);
+			if (!p->desc_info[i].dat)
+				return false;
+			memset(p->desc_info[i].dat, 0, p->desc_info[i].sz);
+		}
+		for (i = 0; i < p->ts_blk_cnt; i++) {						/* 17	*/
+			p->ts_info[i].sz	= DESC_PAGE_SZ * TS_PAGE_CNT;			/* 1020 pkts, 4080 * 47 = 191760B, total 3259920B */
+			p->ts_info[i].dat	= pci_alloc_consistent(card->pdev, p->ts_info[i].sz, &p->ts_info[i].adr);
+			if (!p->ts_info[i].dat)
+				return false;
+			for (j = 0; j < TS_PAGE_CNT; j++) {					/* 47, total 47 * 17 = 799 pages */
+				if (!desc_todo) {						/* 20	*/
+					descinfo	= p->desc_info + desc_pg_idx;		/* jump to next desc_pg */
+					curr		= (struct dma_desc *)descinfo->dat;
+					desc_addr	= descinfo->adr;
+					desc_todo	= DESC_MAX;				/* 204	*/
+					desc_pg_idx++;
+				}
+				if (prev)
+					prev->next_desc = desc_addr;
+				curr->page_addr = p->ts_info[i].adr + DESC_PAGE_SZ * j;
+				curr->page_size = DESC_PAGE_SZ;
+				curr->next_desc = p->desc_info->adr;				/* circular link */
+				prev		= curr;
+				curr++;
+				desc_addr	+= DESC_SZ;
+				desc_todo--;
+			}
+		}
+		return true;
+	}
+
+	u8	i;
+	int	ret	= !card || pci_read_config_byte(pdev, PCI_CLASS_REVISION, &i);
+
+	if (ret)
+		return ptx_abort(pdev, pt3_remove, ret, "PCI/DMA/memory error");
+	if (i != 1)
+		return ptx_abort(pdev, pt3_remove, -ENOTSUPP, "PCI Rev%d not supported", i);
+	pci_set_master(pdev);
+	c		= card->priv;
+	c->bar_reg	= pci_ioremap_bar(pdev, 0);
+	c->bar_mem	= pci_ioremap_bar(pdev, 2);
+	if (!c->bar_reg || !c->bar_mem)
+		return ptx_abort(pdev, pt3_remove, -EIO, "Failed pci_ioremap_bar");
+	ret = (readl(c->bar_reg + PT3_REG_VERSION) >> 8) & 0xFF00FF;
+	if (ret != 0x030004)
+		return ptx_abort(pdev, pt3_remove, -ENOTSUPP, "PT%d FPGA v%d not supported", ret >> 16, ret & 0xFF);
+	for (i = 0, adap = card->adap; i < card->adapn; i++, adap++) {
+		struct pt3_adap	*p	= adap->priv;
+
+		p->dma_base	= c->bar_reg + PT3_DMA_BASE + PT3_DMA_OFFSET * i;
+		if (!dma_create(p))
+			return ptx_abort(pdev, pt3_remove, -ENOMEM, "Failed dma_create");
+	}
+	adap--;
+	ret =	ptx_i2c_add_adapter(card, &pt3_i2c_algo)				||
+		pt3_i2c_flush(c, 0)							||
+		ptx_register_adap(card, pt3_subdev_info, pt3_thread, pt3_dma_run)	||
+		pt3_power(adap->fe, PT3_PWR_TUNER_ON)					||
+		pt3_i2c_flush(c, PT3_I2C_START_ADDR)					||
+		pt3_power(adap->fe, PT3_PWR_TUNER_ON | PT3_PWR_AMP_ON);
+	return	ret ?
+		ptx_abort(pdev, pt3_remove, ret, "Unable to register I2C/DVB adapter/frontend") :
+		0;
+}
+
+static struct pci_driver pt3_driver = {
+	.name		= KBUILD_MODNAME,
+	.id_table	= pt3_id,
+	.probe		= pt3_probe,
+	.remove		= pt3_remove,
+};
+module_pci_driver(pt3_driver);
+
diff --git a/drivers/media/pci/ptx/ptx_common.c b/drivers/media/pci/ptx/ptx_common.c
new file mode 100644
index 0000000..75cae15
--- /dev/null
+++ b/drivers/media/pci/ptx/ptx_common.c
@@ -0,0 +1,266 @@
+/*
+	Registration procedures for PT3, PX-Q3PE, PX-BCUD and other DVB drivers
+
+	Copyright (C) Budi Rachmanto, AreMa Inc. <info@are.ma>
+*/
+
+#include "ptx_common.h"
+
+MODULE_AUTHOR(PTX_AUTH);
+MODULE_DESCRIPTION("Common DVB registration procedures");
+MODULE_LICENSE("GPL");
+
+void ptx_lnb(struct ptx_card *card)
+{
+	struct ptx_adap	*adap;
+	int	i;
+	bool	lnb = false;
+
+	for (i = 0, adap = card->adap; adap->fe && i < card->adapn; i++, adap++)
+		if (adap->fe->dtv_property_cache.delivery_system == SYS_ISDBS && adap->ON) {
+			lnb = true;
+			break;
+	}
+	if (card->lnbON != lnb) {
+		card->lnb(card, lnb);
+		card->lnbON = lnb;
+	}
+}
+
+int ptx_sleep(struct dvb_frontend *fe)
+{
+	struct ptx_adap	*adap	= container_of(fe->dvb, struct ptx_adap, dvb);
+
+	adap->ON = false;
+	ptx_lnb(adap->card);
+	return adap->fe_sleep ? adap->fe_sleep(fe) : 0;
+}
+
+int ptx_wakeup(struct dvb_frontend *fe)
+{
+	struct ptx_adap	*adap	= container_of(fe->dvb, struct ptx_adap, dvb);
+
+	adap->ON = true;
+	ptx_lnb(adap->card);
+	return adap->fe_wakeup ? adap->fe_wakeup(fe) : 0;
+}
+
+int ptx_stop_feed(struct dvb_demux_feed *feed)
+{
+	struct ptx_adap	*adap	= container_of(feed->demux, struct ptx_adap, demux);
+
+	adap->card->dma(adap, false);
+	if (adap->kthread)
+		kthread_stop(adap->kthread);
+	return 0;
+}
+
+int ptx_start_feed(struct dvb_demux_feed *feed)
+{
+	struct ptx_adap	*adap	= container_of(feed->demux, struct ptx_adap, demux);
+
+	if (adap->card->thread)
+		adap->kthread = kthread_run(adap->card->thread, adap, "%s_%d%c", adap->dvb.name, adap->dvb.num,
+					adap->fe->dtv_property_cache.delivery_system == SYS_ISDBS ? 's' : 't');
+	return IS_ERR(adap->kthread) ? PTR_ERR(adap->kthread) : adap->card->dma(adap, true);
+}
+
+struct ptx_card *ptx_alloc(struct pci_dev *pdev, u8 *name, u8 adapn, u32 sz_card_priv, u32 sz_adap_priv,
+			void (*lnb)(struct ptx_card *, bool))
+{
+	u8 i;
+	struct ptx_card *card = kzalloc(sizeof(struct ptx_card) + sz_card_priv + adapn *
+					(sizeof(struct ptx_adap) + sz_adap_priv), GFP_KERNEL);
+	if (!card)
+		return NULL;
+	card->priv	= sz_card_priv ? &card[1] : NULL;
+	card->adap	= (struct ptx_adap *)((u8 *)&card[1] + sz_card_priv);
+	card->pdev	= pdev;
+	card->adapn	= adapn;
+	card->name	= name;
+	card->lnbON	= true;
+	card->lnb	= lnb;
+	for (i = 0; i < card->adapn; i++) {
+		struct ptx_adap *p = &card->adap[i];
+
+		p->card	= card;
+		p->priv	= sz_adap_priv ? (u8 *)&card->adap[card->adapn] + i * sz_adap_priv : NULL;
+	}
+	if (pci_enable_device(pdev)					||
+		pci_set_dma_mask(pdev, DMA_BIT_MASK(32))		||
+		pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))	||
+		pci_request_regions(pdev, name)) {
+		kfree(card);
+		return NULL;
+	}
+	pci_set_drvdata(pdev, card);
+	return card;
+}
+
+int ptx_i2c_add_adapter(struct ptx_card *card, const struct i2c_algorithm *algo)
+{
+	struct i2c_adapter *i2c = &card->i2c;
+
+	i2c->algo	= algo;
+	i2c->dev.parent	= &card->pdev->dev;
+	strcpy(i2c->name, card->name);
+	i2c_set_adapdata(i2c, card);
+	mutex_init(&card->lock);
+	return	i2c_add_adapter(i2c);
+}
+
+void ptx_unregister_subdev(struct i2c_client *c)
+{
+	if (!c)
+		return;
+	if (c->dev.driver)
+		module_put(c->dev.driver->owner);
+	i2c_unregister_device(c);
+}
+
+struct i2c_client *ptx_register_subdev(struct i2c_adapter *i2c, struct dvb_frontend *fe, u16 adr, char *name)
+{
+	struct i2c_client	*c;
+	struct i2c_board_info	info = {
+		.platform_data	= fe,
+		.addr		= adr,
+	};
+
+	strlcpy(info.type, name, I2C_NAME_SIZE);
+	request_module("%s", info.type);
+	c = i2c_new_device(i2c, &info);
+	if (!c)
+		return NULL;
+	if (c->dev.driver && try_module_get(c->dev.driver->owner))
+		return c;
+	ptx_unregister_subdev(c);
+	return NULL;
+}
+
+void ptx_unregister_fe(struct dvb_frontend *fe)
+{
+	if (!fe)
+		return;
+	if (fe->frontend_priv)
+		dvb_unregister_frontend(fe);
+	ptx_unregister_subdev(fe->tuner_priv);
+	ptx_unregister_subdev(fe->demodulator_priv);
+	kfree(fe);
+}
+
+struct dvb_frontend *ptx_register_fe(struct i2c_adapter *i2c, struct dvb_adapter *dvb, const struct ptx_subdev_info *info)
+{
+	struct dvb_frontend *fe = kzalloc(sizeof(struct dvb_frontend), GFP_KERNEL);
+
+	if (!fe)
+		return	NULL;
+	fe->demodulator_priv	= ptx_register_subdev(i2c, fe, info->demod_addr, info->demod_name);
+	fe->tuner_priv		= ptx_register_subdev(i2c, fe, info->tuner_addr, info->tuner_name);
+	if (info->type)
+		fe->ops.delsys[0] = info->type;
+	if (!fe->demodulator_priv || !fe->tuner_priv || (dvb && dvb_register_frontend(dvb, fe))) {
+		ptx_unregister_fe(fe);
+		return	NULL;
+	}
+	return fe;
+}
+
+void ptx_unregister_adap(struct ptx_card *card)
+{
+	int		i	= card->adapn - 1;
+	struct ptx_adap	*adap	= card->adap + i;
+
+	for (; i >= 0; i--, adap--) {
+		ptx_unregister_fe(adap->fe);
+		if (adap->demux.dmx.close)
+			adap->demux.dmx.close(&adap->demux.dmx);
+		if (adap->dmxdev.filter)
+			dvb_dmxdev_release(&adap->dmxdev);
+		if (adap->demux.cnt_storage)
+			dvb_dmx_release(&adap->demux);
+		if (adap->dvb.name)
+			dvb_unregister_adapter(&adap->dvb);
+	}
+	i2c_del_adapter(&card->i2c);
+	pci_release_regions(card->pdev);
+	pci_set_drvdata(card->pdev, NULL);
+	pci_disable_device(card->pdev);
+	kfree(card);
+}
+
+int ptx_register_adap(struct ptx_card *card, const struct ptx_subdev_info *info,
+			int (*thread)(void *), int (*dma)(struct ptx_adap *, bool))
+{
+	struct ptx_adap	*adap;
+	short	adap_no[DVB_MAX_ADAPTERS] = {};
+	u8	i;
+	int	err;
+
+	card->thread	= thread;
+	card->dma	= dma;
+	for (i = 0, adap = card->adap; i < card->adapn; i++, adap++) {
+		struct dvb_adapter	*dvb	= &adap->dvb;
+		struct dvb_demux	*demux	= &adap->demux;
+		struct dmxdev		*dmxdev	= &adap->dmxdev;
+
+		if (dvb_register_adapter(dvb, card->name, THIS_MODULE, &card->pdev->dev, adap_no) < 0)
+			return -ENFILE;
+		demux->dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
+		demux->feednum		= 1;
+		demux->filternum	= 1;
+		demux->start_feed	= ptx_start_feed;
+		demux->stop_feed	= ptx_stop_feed;
+		if (dvb_dmx_init(demux) < 0)
+			return -ENOMEM;
+		dmxdev->filternum	= 1;
+		dmxdev->demux		= &demux->dmx;
+		err			= dvb_dmxdev_init(dmxdev, dvb);
+		if (err)
+			return err;
+		adap->fe		= ptx_register_fe(&adap->card->i2c, &adap->dvb, &info[i]);
+		if (!adap->fe)
+			return -ENOMEM;
+		adap->fe_sleep		= adap->fe->ops.sleep;
+		adap->fe_wakeup		= adap->fe->ops.init;
+		adap->fe->ops.sleep	= ptx_sleep;
+		adap->fe->ops.init	= ptx_wakeup;
+		ptx_sleep(adap->fe);
+	}
+	return 0;
+}
+
+int ptx_abort(struct pci_dev *pdev, void remover(struct pci_dev *), int err, char *fmt, ...)
+{
+	va_list	ap;
+	char	*s = NULL;
+	int	slen;
+
+	va_start(ap, fmt);
+	slen	= vsnprintf(s, 0, fmt, ap) + 1;
+	s	= kzalloc(slen, GFP_ATOMIC);
+	if (s) {
+		vsnprintf(s, slen, fmt, ap);
+		dev_err(&pdev->dev, "%s", s);
+		kfree(s);
+	}
+	va_end(ap);
+	remover(pdev);
+	return err;
+}
+
+u32 ptx_i2c_func(struct i2c_adapter *i2c)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_NOSTART;
+}
+
+EXPORT_SYMBOL(ptx_alloc);
+EXPORT_SYMBOL(ptx_sleep);
+EXPORT_SYMBOL(ptx_wakeup);
+EXPORT_SYMBOL(ptx_i2c_add_adapter);
+EXPORT_SYMBOL(ptx_unregister_fe);
+EXPORT_SYMBOL(ptx_register_fe);
+EXPORT_SYMBOL(ptx_unregister_adap);
+EXPORT_SYMBOL(ptx_register_adap);
+EXPORT_SYMBOL(ptx_abort);
+EXPORT_SYMBOL(ptx_i2c_func);
+
diff --git a/drivers/media/pci/ptx/ptx_common.h b/drivers/media/pci/ptx/ptx_common.h
new file mode 100644
index 0000000..444b4b8
--- /dev/null
+++ b/drivers/media/pci/ptx/ptx_common.h
@@ -0,0 +1,76 @@
+/*
+	Definitions & prototypes for PT3, PX-Q3PE, PX-BCUD and other DVB drivers
+
+	Copyright (C) Budi Rachmanto, AreMa Inc. <info@are.ma>
+
+	This program is distributed in hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+*/
+
+#ifndef	PTX_COMMON_H
+#define PTX_COMMON_H
+
+#include <linux/freezer.h>
+#include <linux/kthread.h>
+#include <linux/pci.h>
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dmxdev.h"
+
+#define PTX_AUTH "Budi Rachmanto, AreMa Inc. <knightrider(@)are.ma>"
+
+enum ePTX {
+	PTX_TS_SIZE	= 188,
+	PTX_TS_SYNC	= 0x47,
+	PTX_TS_NOT_SYNC	= 0x74,
+};
+
+struct ptx_subdev_info {
+	enum fe_delivery_system	type;
+	u8	demod_addr,	*demod_name,
+		tuner_addr,	*tuner_name;
+};
+
+struct ptx_card {
+	struct ptx_adap		*adap;
+	struct mutex		lock;
+	struct i2c_adapter	i2c;
+	struct pci_dev		*pdev;
+	u8	*name,
+		adapn;
+	bool	lnbON;
+	void	*priv,
+		(*lnb)(struct ptx_card *card, bool lnb);
+	int	(*thread)(void *dat),
+		(*dma)(struct ptx_adap *adap, bool ON);
+};
+
+struct ptx_adap {
+	struct ptx_card		*card;
+	bool			ON;
+	struct dvb_adapter	dvb;
+	struct dvb_demux	demux;
+	struct dmxdev		dmxdev;
+	struct dvb_frontend	*fe;
+	struct task_struct	*kthread;
+	void			*priv;
+	int	(*fe_sleep)(struct dvb_frontend *),
+		(*fe_wakeup)(struct dvb_frontend *);
+};
+
+struct ptx_card *ptx_alloc(struct pci_dev *pdev, u8 *name, u8 adapn, u32 sz_card_priv, u32 sz_adap_priv,
+			void (*lnb)(struct ptx_card *, bool));
+int ptx_sleep(struct dvb_frontend *fe);
+int ptx_wakeup(struct dvb_frontend *fe);
+int ptx_i2c_add_adapter(struct ptx_card *card, const struct i2c_algorithm *algo);
+void ptx_unregister_fe(struct dvb_frontend *fe);
+struct dvb_frontend *ptx_register_fe(struct i2c_adapter *i2c, struct dvb_adapter *dvb, const struct ptx_subdev_info *info);
+void ptx_unregister_adap(struct ptx_card *card);
+int ptx_register_adap(struct ptx_card *card, const struct ptx_subdev_info *info,
+			int (*thread)(void *), int (*dma)(struct ptx_adap *, bool));
+int ptx_abort(struct pci_dev *pdev, void remover(struct pci_dev *), int err, char *fmt, ...);
+u32 ptx_i2c_func(struct i2c_adapter *i2c);
+
+#endif
diff --git a/drivers/media/pci/ptx/pxq3pe.c b/drivers/media/pci/ptx/pxq3pe.c
new file mode 100644
index 0000000..57165c8
--- /dev/null
+++ b/drivers/media/pci/ptx/pxq3pe.c
@@ -0,0 +1,585 @@
+/*
+	DVB driver for PLEX PX-Q3PE ISDB-S/T PCIE receiver
+
+	Copyright (C) Budi Rachmanto, AreMa Inc. <info@are.ma>
+
+	Main components:
+	ASIE5606X8	- controller
+	TC90522		- 2ch OFDM ISDB-T + 2ch 8PSK ISDB-S demodulator
+	TDA20142	- ISDB-S tuner
+	NM120		- ISDB-T tuner
+*/
+
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include "ptx_common.h"
+#include "tc90522.h"
+#include "tda2014x.h"
+#include "nm131.h"
+
+MODULE_AUTHOR(PTX_AUTH);
+MODULE_DESCRIPTION("PLEX PX-Q3PE Driver");
+MODULE_LICENSE("GPL");
+
+static char	*auth	= PTX_AUTH;
+static int	ni,
+		nx,
+		idx[8]	= {},
+		xor[4]	= {};
+module_param(auth, charp, 0);
+module_param_array(idx, int, &ni, 0);
+module_param_array(xor, int, &nx, 0);
+
+static struct pci_device_id pxq3pe_id_table[] = {
+	{0x188B, 0x5220, 0x0B06, 0x0002, 0, 0, 0},
+	{}
+};
+MODULE_DEVICE_TABLE(pci, pxq3pe_id_table);
+
+enum ePXQ3PE {
+	PKT_NUM		= 312,
+	PKT_BUFSZ	= PTX_TS_SIZE * PKT_NUM,
+
+	PXQ3PE_MOD_GPIO		= 0,
+	PXQ3PE_MOD_TUNER	= 1,
+	PXQ3PE_MOD_STAT		= 2,
+
+	PXQ3PE_IRQ_STAT		= 0x808,
+	PXQ3PE_IRQ_CLEAR	= 0x80C,
+	PXQ3PE_IRQ_ACTIVE	= 0x814,
+	PXQ3PE_IRQ_DISABLE	= 0x818,
+	PXQ3PE_IRQ_ENABLE	= 0x81C,
+
+	PXQ3PE_I2C_ADR_GPIO	= 0x4A,
+	PXQ3PE_I2C_CTL_STAT	= 0x940,
+	PXQ3PE_I2C_ADR		= 0x944,
+	PXQ3PE_I2C_SW_CTL	= 0x948,
+	PXQ3PE_I2C_FIFO_STAT	= 0x950,
+	PXQ3PE_I2C_FIFO_DATA	= 0x960,
+
+	PXQ3PE_DMA_OFFSET_PORT	= 0x140,
+	PXQ3PE_DMA_TSMODE	= 0xA00,
+	PXQ3PE_DMA_MGMT		= 0xAE0,
+	PXQ3PE_DMA_OFFSET_CH	= 0x10,
+	PXQ3PE_DMA_ADR_LO	= 0xAC0,
+	PXQ3PE_DMA_ADR_HI	= 0xAC4,
+	PXQ3PE_DMA_XFR_STAT	= 0xAC8,
+	PXQ3PE_DMA_CTL		= 0xACC,
+
+	PXQ3PE_MAX_LOOP		= 1000,
+};
+
+struct pxq3pe_card {
+	void __iomem		*bar;
+	struct {
+		dma_addr_t	adr;
+		u8		*dat;
+		u32		sz;
+		bool		ON[2];
+	} dma;
+};
+
+struct pxq3pe_adap {
+	u8	tBuf[PKT_BUFSZ],
+		*sBuf;
+	u32	tBufIdx,
+		sBufSize,
+		sBufStart,
+		sBufStop,
+		sBufByteCnt;
+};
+
+bool pxq3pe_i2c_clean(struct ptx_card *card)
+{
+	struct pxq3pe_card	*c	= card->priv;
+	void __iomem		*bar	= c->bar;
+
+	if ((readl(bar + PXQ3PE_I2C_FIFO_STAT) & 0x1F) != 0x10 || readl(bar + PXQ3PE_I2C_FIFO_STAT) & 0x1F00) {
+		u32 stat = readl(bar + PXQ3PE_I2C_SW_CTL) | 0x20;
+
+		writel(stat, bar + PXQ3PE_I2C_SW_CTL);
+		writel(stat & 0xFFFFFFDF, bar + PXQ3PE_I2C_SW_CTL);
+		if ((readl(bar + PXQ3PE_I2C_FIFO_STAT) & 0x1F) != 0x10) {
+			dev_err(&card->pdev->dev, "%s FIFO error", __func__);
+			return false;
+		}
+	}
+	writel(0, bar + PXQ3PE_I2C_CTL_STAT);
+	return true;
+}
+
+bool pxq3pe_w(struct ptx_card *card, u8 slvadr, u8 regadr, u8 *wdat, u8 bytelen, u8 mode)
+{
+	struct pxq3pe_card	*c	= card->priv;
+	void __iomem		*bar	= c->bar;
+	int	i,
+		j,
+		k;
+	u8	i2cCtlByte,
+		i2cFifoWSz;
+
+	if (!pxq3pe_i2c_clean(card))
+		return false;
+	switch (mode) {
+	case PXQ3PE_MOD_GPIO:
+		i2cCtlByte = 0xC0;
+		break;
+	case PXQ3PE_MOD_TUNER:
+		regadr = 0;
+		i2cCtlByte = 0x80;
+		break;
+	case PXQ3PE_MOD_STAT:
+		regadr = 0;
+		i2cCtlByte = 0x84;
+		break;
+	default:
+		return false;
+	}
+	writel((slvadr << 8) + regadr, bar + PXQ3PE_I2C_ADR);
+	for (i = 0; i < 16 && i < bytelen; i += 4) {
+		udelay(1000);
+		writel(*((u32 *)(wdat + i)), bar + PXQ3PE_I2C_FIFO_DATA);
+	}
+	writew((bytelen << 8) + i2cCtlByte, bar + PXQ3PE_I2C_CTL_STAT);
+	for (j = 0; j < PXQ3PE_MAX_LOOP; j++) {
+		if (i < bytelen) {
+			i2cFifoWSz = readb(bar + PXQ3PE_I2C_FIFO_STAT) & 0x1F;
+			for (k = 0; bytelen > 16 && k < PXQ3PE_MAX_LOOP && i2cFifoWSz < bytelen - 16; k++) {
+				i2cFifoWSz = readb(bar + PXQ3PE_I2C_FIFO_STAT) & 0x1F;
+				udelay(1000);
+			}
+			if (i2cFifoWSz & 3)
+				continue;
+			if (i2cFifoWSz) {
+				for (k = i; k < bytelen && k - i < i2cFifoWSz; k += 4)
+					writel(*((u32 *)(wdat + k)), bar + PXQ3PE_I2C_FIFO_DATA);
+				i = k;
+			}
+		}
+		udelay(10);
+		if (readl(bar + PXQ3PE_I2C_CTL_STAT) & 0x400000)
+			break;
+	}
+	return j < PXQ3PE_MAX_LOOP ? !(readl(bar + PXQ3PE_I2C_CTL_STAT) & 0x280000) : false;
+}
+
+bool pxq3pe_r(struct ptx_card *card, u8 slvadr, u8 regadr, u8 *rdat, u8 bytelen, u8 mode)
+{
+	struct pxq3pe_card	*c	= card->priv;
+	void __iomem		*bar	= c->bar;
+	u8	i2cCtlByte,
+		i2cStat,
+		i2cFifoRSz,
+		i2cByteCnt;
+	int	i		= 0,
+		j,
+		idx;
+	bool	ret		= false;
+
+	if (!pxq3pe_i2c_clean(card))
+		return false;
+	switch (mode) {
+	case PXQ3PE_MOD_GPIO:
+		i2cCtlByte = 0xE0;
+		break;
+	case PXQ3PE_MOD_TUNER:
+		regadr = 0;
+		i2cCtlByte = 0xA0;
+		break;
+	default:
+		return false;
+	}
+	writel((slvadr << 8) + regadr, bar + PXQ3PE_I2C_ADR);
+	writew(i2cCtlByte + (bytelen << 8), bar + PXQ3PE_I2C_CTL_STAT);
+	i2cByteCnt = bytelen;
+	j = 0;
+	while (j < PXQ3PE_MAX_LOOP) {
+		udelay(10);
+		i2cStat = (readl(bar + PXQ3PE_I2C_CTL_STAT) & 0xFF0000) >> 16;
+		if (i2cStat & 0x80) {
+			if (i2cStat & 0x28)
+				break;
+			ret = true;
+		}
+		i2cFifoRSz = (readl(bar + PXQ3PE_I2C_FIFO_STAT) & 0x1F00) >> 8;
+		if (i2cFifoRSz & 3) {
+			++j;
+			continue;
+		}
+		for (idx = i; i2cFifoRSz && idx < i2cByteCnt && idx - i < i2cFifoRSz; idx += 4)
+			*(u32 *)(rdat + idx) = readl(bar + PXQ3PE_I2C_FIFO_DATA);
+		i = idx;
+		if (i < bytelen) {
+			if (i2cFifoRSz)
+				i2cByteCnt -= i2cFifoRSz;
+			else
+				++j;
+			continue;
+		}
+		i2cStat = (readl(bar + PXQ3PE_I2C_CTL_STAT) & 0xFF0000) >> 16;
+		if (i2cStat & 0x80) {
+			if (i2cStat & 0x28)
+				break;
+			ret = true;
+			break;
+		}
+		++j;
+	}
+	return !(readl(bar + PXQ3PE_I2C_FIFO_STAT) & 0x1F00) && ret;
+}
+
+int pxq3pe_xfr(struct i2c_adapter *i2c, struct i2c_msg *msg, int sz)
+{
+	struct ptx_card	*card	= i2c_get_adapdata(i2c);
+	u8		i;
+	bool		ret	= true;
+
+	if (!i2c || !card || !msg)
+		return -EINVAL;
+	for (i = 0; i < sz && ret; i++, msg++) {
+		u8	slvadr	= msg->addr,
+			regadr	= msg->len ? *msg->buf : 0,
+			mode	= slvadr == PXQ3PE_I2C_ADR_GPIO	? PXQ3PE_MOD_GPIO
+				: sz > 1 && i == sz - 2		? PXQ3PE_MOD_STAT
+				: PXQ3PE_MOD_TUNER;
+
+		mutex_lock(&card->lock);
+		if (msg->flags & I2C_M_RD) {
+			u8 buf[sz];
+
+			ret = pxq3pe_r(card, slvadr, regadr, buf, msg->len, mode);
+			memcpy(msg->buf, buf, msg->len);
+		} else
+			ret = pxq3pe_w(card, slvadr, regadr, msg->buf, msg->len, mode);
+		mutex_unlock(&card->lock);
+	}
+	return i;
+}
+
+bool pxq3pe_w_gpio2(struct ptx_card *card, u8 dat, u8 mask)
+{
+	u8 val;
+
+	return	pxq3pe_r(card, PXQ3PE_I2C_ADR_GPIO, 0xB, &val, 1, PXQ3PE_MOD_GPIO)	&&
+		(val = (mask & dat) | (val & ~mask), pxq3pe_w(card, PXQ3PE_I2C_ADR_GPIO, 0xB, &val, 1, PXQ3PE_MOD_GPIO));
+}
+
+void pxq3pe_w_gpio1(struct ptx_card *card, u8 dat, u8 mask)
+{
+	struct pxq3pe_card *c = card->priv;
+
+	mask <<= 3;
+	writeb((readb(c->bar + 0x890) & ~mask) | ((dat << 3) & mask), c->bar + 0x890);
+}
+
+void pxq3pe_w_gpio0(struct ptx_card *card, u8 dat, u8 mask)
+{
+	struct pxq3pe_card *c = card->priv;
+
+	writeb((-(mask & 1) & 4 & -(dat & 1)) | (readb(c->bar + 0x890) & ~(-(mask & 1) & 4)), c->bar + 0x890);
+	writeb((mask & dat) | (readb(c->bar + 0x894) & ~mask), c->bar + 0x894);
+}
+
+void pxq3pe_power(struct ptx_card *card, bool ON)
+{
+	if (ON) {
+		pxq3pe_w_gpio0(card, 1, 1);
+		pxq3pe_w_gpio0(card, 0, 1);
+		pxq3pe_w_gpio0(card, 1, 1);
+		pxq3pe_w_gpio1(card, 1, 1);
+		pxq3pe_w_gpio1(card, 0, 1);
+		pxq3pe_w_gpio2(card, 2, 2);
+		pxq3pe_w_gpio2(card, 0, 2);
+		pxq3pe_w_gpio2(card, 2, 2);
+		pxq3pe_w_gpio2(card, 4, 4);
+		pxq3pe_w_gpio2(card, 0, 4);
+		pxq3pe_w_gpio2(card, 4, 4);
+	} else {
+		pxq3pe_w_gpio0(card, 0, 1);
+		pxq3pe_w_gpio0(card, 1, 1);
+		pxq3pe_w_gpio1(card, 1, 1);
+	}
+}
+
+irqreturn_t pxq3pe_irq(int irq, void *ctx)
+{
+	struct ptx_card		*card	= ctx;
+	struct pxq3pe_card	*c	= card->priv;
+	void __iomem		*bar	= c->bar;
+	u32	dmamgmt,
+		i,
+		irqstat = readl(bar + PXQ3PE_IRQ_STAT);
+	bool	ch	= irqstat & 0b0101 ? 0 : 1,
+		port	= irqstat & 0b0011 ? 0 : 1;
+	u8	*tbuf	= c->dma.dat + PKT_BUFSZ * (port * 2 + ch);
+
+	void pxq3pe_dma_put_stream(struct pxq3pe_adap *p)
+	{
+		u8	*src	= p->tBuf;
+		u32	len	= p->tBufIdx,
+			savesz	= len <= p->sBufSize - p->sBufStop ? len : p->sBufSize - p->sBufStop,
+			remain	= len - savesz;
+
+		memcpy(&p->sBuf[p->sBufStop], src, savesz);
+		if (remain)
+			memcpy(p->sBuf, &src[savesz], remain);
+		p->sBufStop = (p->sBufStop + len) % p->sBufSize;
+		if (p->sBufByteCnt == p->sBufSize)
+			p->sBufStart = p->sBufStop;
+		else {
+			if (p->sBufSize >= p->sBufByteCnt + len)
+				p->sBufByteCnt += len;
+			else {
+				p->sBufStart = p->sBufStop;
+				p->sBufByteCnt = p->sBufSize;
+			}
+		}
+	}
+
+	if (!(irqstat & 0b1111))
+		return IRQ_HANDLED;
+	writel(irqstat, bar + PXQ3PE_IRQ_CLEAR);
+	dmamgmt = readl(bar + PXQ3PE_DMA_OFFSET_PORT * port + PXQ3PE_DMA_MGMT);
+	if ((readl(bar + PXQ3PE_DMA_OFFSET_PORT * port + PXQ3PE_DMA_OFFSET_CH * ch + PXQ3PE_DMA_XFR_STAT) & 0x3FFFFF) == PKT_BUFSZ)
+		for (i = 0; i < PKT_BUFSZ; i += PTX_TS_SIZE) {
+			u8 idx = !port * 4 + (tbuf[i] == 0xC7 ? 0 : tbuf[i] == 0x47 ?
+					1 : tbuf[i] == 0x07 ? 2 : tbuf[i] == 0x87 ? 3 : card->adapn);
+			struct ptx_adap		*adap	= &card->adap[idx];
+			struct pxq3pe_adap	*p	= adap->priv;
+
+			if (idx < card->adapn && adap->ON) {
+				tbuf[i] = PTX_TS_SYNC;
+				memcpy(&p->tBuf[p->tBufIdx], &tbuf[i], PTX_TS_SIZE);
+				p->tBufIdx += PTX_TS_SIZE;
+				if (p->tBufIdx >= PKT_BUFSZ) {
+					pxq3pe_dma_put_stream(p);
+					p->tBufIdx = 0;
+				}
+			}
+		}
+	if (c->dma.ON[port])
+		writel(dmamgmt | (2 << (ch * 16)), bar + PXQ3PE_DMA_OFFSET_PORT * port + PXQ3PE_DMA_MGMT);
+	return IRQ_HANDLED;
+}
+
+int pxq3pe_thread(void *dat)
+{
+	struct ptx_adap		*adap	= dat;
+	struct pxq3pe_adap	*p	= adap->priv;
+
+	set_freezable();
+	while (!kthread_should_stop()) {
+		u8	*rbuf	= &p->sBuf[p->sBufStart];
+		int	i	= 0,
+			j	= 0,
+			k,
+			sz	= p->sBufSize - p->sBufStart;
+
+		try_to_freeze();
+		if (!p->sBufByteCnt) {
+			msleep_interruptible(0);
+			continue;
+		}
+		if (sz > p->sBufByteCnt)
+			sz = p->sBufByteCnt;
+		while (j < sz / PTX_TS_SIZE) {
+			j++;
+			i += 4;
+			while (i < j * PTX_TS_SIZE)
+				for (k = 0; k < 8; k++, i++)
+					rbuf[i] ^= xor[idx[k]];
+		}
+		dvb_dmx_swfilter(&adap->demux, rbuf, sz);
+		p->sBufStart	= (p->sBufStart + sz) % p->sBufSize;
+		p->sBufByteCnt -= sz;
+	}
+	return 0;
+}
+
+int pxq3pe_dma(struct ptx_adap *adap, bool ON)
+{
+	struct ptx_card		*card	= adap->card;
+	struct pxq3pe_card	*c	= card->priv;
+	struct pxq3pe_adap	*p	= adap->priv;
+	struct i2c_client	*d	= adap->fe->demodulator_priv;
+	u8			idx	= (d->addr / 2) & (card->adapn - 1),
+				i;
+	bool			port	= !(idx & 4);
+	u32			val	= 0b0011 << (port * 2);
+
+	if (!ON) {
+		for (i = 0; i < card->adapn; i++)
+			if (!c->dma.ON[port] || (idx != i && (i & 4) == (idx & 4) && c->dma.ON[port]))
+				return 0;
+
+		i = readb(c->bar + PXQ3PE_DMA_OFFSET_PORT * port + PXQ3PE_DMA_MGMT);
+		if ((i & 0b1100) == 4)
+			writeb(i & 0xFD, c->bar + PXQ3PE_DMA_OFFSET_PORT * port + PXQ3PE_DMA_MGMT);
+		writeb(0b0011 << (port * 2), c->bar + PXQ3PE_IRQ_DISABLE);
+		c->dma.ON[port] = false;
+		return 0;
+	}
+
+	p->sBufByteCnt	= 0;
+	p->sBufStop	= 0;
+	p->sBufStart	= 0;
+	if (c->dma.ON[port])
+		return 0;
+
+	/* SetTSMode */
+	i = readb(c->bar + PXQ3PE_DMA_OFFSET_PORT * port + PXQ3PE_DMA_TSMODE);
+	if ((i & 0x80) == 0)
+		writeb(i | 0x80, c->bar + PXQ3PE_DMA_OFFSET_PORT * port + PXQ3PE_DMA_TSMODE);
+
+	/* irq_enable */
+	writel(val, c->bar + PXQ3PE_IRQ_ENABLE);
+	if (val != (readl(c->bar + PXQ3PE_IRQ_ACTIVE) & val))
+		return -EIO;
+
+	/* cfg_dma */
+	for (i = 0; i < 2; i++) {
+		val		= readl(c->bar + PXQ3PE_DMA_OFFSET_PORT * port + PXQ3PE_DMA_MGMT);
+		writel(c->dma.adr + PKT_BUFSZ * (port * 2 + i),
+					c->bar + PXQ3PE_DMA_OFFSET_PORT * port + PXQ3PE_DMA_OFFSET_CH * i + PXQ3PE_DMA_ADR_LO);
+		writel(0,		c->bar + PXQ3PE_DMA_OFFSET_PORT * port + PXQ3PE_DMA_OFFSET_CH * i + PXQ3PE_DMA_ADR_HI);
+		writel(0x11C0E520,	c->bar + PXQ3PE_DMA_OFFSET_PORT * port + PXQ3PE_DMA_OFFSET_CH * i + PXQ3PE_DMA_CTL);
+		writel(val | 3 << (i * 16),
+					c->bar + PXQ3PE_DMA_OFFSET_PORT * port + PXQ3PE_DMA_MGMT);
+	}
+	c->dma.ON[port] = true;
+	return 0;
+}
+
+void pxq3pe_lnb(struct ptx_card *card, bool lnb)
+{
+	pxq3pe_w_gpio2(card, lnb ? 0x20 : 0, 0x20);
+}
+
+void pxq3pe_remove(struct pci_dev *pdev)
+{
+	struct ptx_card		*card	= pci_get_drvdata(pdev);
+	struct ptx_adap		*adap;
+	struct pxq3pe_card	*c;
+	u8	regctl = 0,
+		i;
+
+	if (!card)
+		return;
+	c	= card->priv;
+	for (i = 0, adap = card->adap; adap->fe && i < card->adapn; i++, adap++) {
+		pxq3pe_dma(adap, false);
+		ptx_sleep(adap->fe);
+	}
+	pxq3pe_w(card, PXQ3PE_I2C_ADR_GPIO, 0x80, &regctl, 1, PXQ3PE_MOD_GPIO);
+	pxq3pe_power(card, false);
+
+	/* dma_hw_unmap */
+	free_irq(pdev->irq, card);
+	if (c->dma.dat)
+		pci_free_consistent(card->pdev, c->dma.sz, c->dma.dat, c->dma.adr);
+	for (i = 0; i < card->adapn; i++) {
+		struct ptx_adap		*adap	= &card->adap[i];
+		struct pxq3pe_adap	*p	= adap->priv;
+
+		vfree(p->sBuf);
+	}
+	if (c->bar)
+		pci_iounmap(pdev, c->bar);
+	ptx_unregister_adap(card);
+}
+
+static const struct i2c_algorithm pxq3pe_algo = {
+	.functionality	= ptx_i2c_func,
+	.master_xfer	= pxq3pe_xfr,
+};
+
+static int pxq3pe_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+{
+	struct ptx_subdev_info	pxq3pe_subdev_info[] = {
+		{SYS_ISDBT, 0x20, TC90522_MODNAME, 0x10, NM131_MODNAME},
+		{SYS_ISDBS, 0x22, TC90522_MODNAME, 0x11, TDA2014X_MODNAME},
+		{SYS_ISDBT, 0x24, TC90522_MODNAME, 0x12, NM131_MODNAME},
+		{SYS_ISDBS, 0x26, TC90522_MODNAME, 0x13, TDA2014X_MODNAME},
+		{SYS_ISDBT, 0x28, TC90522_MODNAME, 0x14, NM131_MODNAME},
+		{SYS_ISDBS, 0x2A, TC90522_MODNAME, 0x15, TDA2014X_MODNAME},
+		{SYS_ISDBT, 0x2C, TC90522_MODNAME, 0x16, NM131_MODNAME},
+		{SYS_ISDBS, 0x2E, TC90522_MODNAME, 0x17, TDA2014X_MODNAME},
+	};
+	struct ptx_card		*card	= ptx_alloc(pdev, KBUILD_MODNAME, ARRAY_SIZE(pxq3pe_subdev_info),
+						sizeof(struct pxq3pe_card), sizeof(struct pxq3pe_adap), pxq3pe_lnb);
+	struct pxq3pe_card	*c;
+	u8	regctl	= 0xA0,
+		i;
+	u16	cfg;
+	int	err	= !card || pci_read_config_word(pdev, PCI_COMMAND, &cfg);
+
+	if (err)
+		return ptx_abort(pdev, pxq3pe_remove, err, "Memory/PCI error, card=%p", card);
+	c	= card->priv;
+	if (!(cfg & PCI_COMMAND_MASTER)) {
+		pci_set_master(pdev);
+		pci_read_config_word(pdev, PCI_COMMAND, &cfg);
+		if (!(cfg & PCI_COMMAND_MASTER))
+			return ptx_abort(pdev, pxq3pe_remove, -EIO, "Bus Mastering is disabled");
+	}
+	c->bar	= pci_iomap(pdev, 0, 0);
+	if (!c->bar)
+		return ptx_abort(pdev, pxq3pe_remove, -EIO, "I/O map failed");
+	if (ptx_i2c_add_adapter(card, &pxq3pe_algo))
+		return ptx_abort(pdev, pxq3pe_remove, -EIO, "Cannot add I2C");
+
+	for (i = 0; i < card->adapn; i++) {
+		struct ptx_adap		*adap	= &card->adap[i];
+		struct pxq3pe_adap	*p	= adap->priv;
+
+		p->sBufSize	= PTX_TS_SIZE * 100 << 9;
+		p->sBuf		= vzalloc(p->sBufSize);
+		if (!p->sBuf)
+			return ptx_abort(pdev, pxq3pe_remove, -ENOMEM, "No memory for stream buffer");
+	}
+
+	/* dma_map */
+	if (request_irq(pdev->irq, pxq3pe_irq, IRQF_SHARED, KBUILD_MODNAME, card))
+		return ptx_abort(pdev, pxq3pe_remove, -EIO, "IRQ failed");
+	c->dma.sz	= PKT_BUFSZ * 4;
+	c->dma.dat	= pci_alloc_consistent(card->pdev, c->dma.sz, &c->dma.adr);
+	if (!c->dma.dat)
+		return ptx_abort(pdev, pxq3pe_remove, -EIO, "DMA mapping failed");
+
+	/* hw_init */
+	writeb(readb(c->bar + 0x880) & 0xC0, c->bar + 0x880);
+	writel(0x3200C8, c->bar + 0x904);
+	writel(0x90,	 c->bar + 0x900);
+	writel(0x10000,	 c->bar + 0x880);
+	writel(0x0080,	 c->bar + PXQ3PE_DMA_TSMODE);				/* port 0 */
+	writel(0x0080,	 c->bar + PXQ3PE_DMA_TSMODE + PXQ3PE_DMA_OFFSET_PORT);	/* port 1 */
+	writel(0x0000,	 c->bar + 0x888);
+	writel(0x00CF,	 c->bar + 0x894);
+	writel(0x8000,	 c->bar + 0x88C);
+	writel(0x1004,	 c->bar + 0x890);
+	writel(0x0090,	 c->bar + 0x900);
+	writel(0x3200C8, c->bar + 0x904);
+	pxq3pe_w_gpio0(card, 8, 0xFF);
+	pxq3pe_w_gpio1(card, 0, 2);
+	pxq3pe_w_gpio1(card, 1, 1);
+	pxq3pe_w_gpio0(card, 1, 1);
+	pxq3pe_w_gpio0(card, 0, 1);
+	pxq3pe_w_gpio0(card, 1, 1);
+	for (i = 0; i < 16; i++)
+		if (!pxq3pe_w(card, PXQ3PE_I2C_ADR_GPIO, 0x10 + i, auth + i, 1, PXQ3PE_MOD_GPIO))
+			break;
+	if (i < 16 || !pxq3pe_w(card, PXQ3PE_I2C_ADR_GPIO, 5, &regctl, 1, PXQ3PE_MOD_GPIO))
+		return ptx_abort(pdev, pxq3pe_remove, -EIO, "hw_init failed i=%d", i);
+	pxq3pe_power(card, true);
+	err = ptx_register_adap(card, pxq3pe_subdev_info, pxq3pe_thread, pxq3pe_dma);
+	return err ? ptx_abort(pdev, pxq3pe_remove, err, "Unable to register DVB adapter & frontend") : 0;
+}
+
+static struct pci_driver pxq3pe_driver = {
+	.name		= KBUILD_MODNAME,
+	.id_table	= pxq3pe_id_table,
+	.probe		= pxq3pe_probe,
+	.remove		= pxq3pe_remove,
+};
+module_pci_driver(pxq3pe_driver);
+
-- 
2.7.4

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

* [media 6/6] Bridge driver for PLEX PX-BCUD ISDB-S USB dongle
  2016-04-04 17:03 [media 0/6] DVB driver for Earthsoft PT3, PLEX PX-Q3PE ISDB-S/T PCIE cards & PX-BCUD ISDB-S USB dongle info
                   ` (4 preceding siblings ...)
  2016-04-04 17:04 ` [media 5/6] PCIE bridge driver for PT3 & PX-Q3PE info
@ 2016-04-04 17:04 ` info
  5 siblings, 0 replies; 10+ messages in thread
From: info @ 2016-04-04 17:04 UTC (permalink / raw)
  To: linux-media
  Cc: Буди
	Романто,
	AreMa Inc, linux-kernel, crope, m.chehab, mchehab, hdegoede,
	laurent.pinchart, mkrufky, sylvester.nawrocki, g.liakhovetski,
	peter.senna

From: Буди Романто, AreMa Inc <knightrider@are.ma>

Support for PLEX PX-BCUD (ISDB-S usb dongle)
Nagahama's patch simplified...

Signed-off-by: Буди Романто, AreMa Inc <knightrider@are.ma>
---
 drivers/media/Kconfig                   |  5 +-
 drivers/media/usb/em28xx/Kconfig        |  3 ++
 drivers/media/usb/em28xx/Makefile       |  1 +
 drivers/media/usb/em28xx/em28xx-cards.c | 27 +++++++++++
 drivers/media/usb/em28xx/em28xx-dvb.c   | 81 ++++++++++++++++++++++++++++++++-
 drivers/media/usb/em28xx/em28xx.h       |  1 +
 6 files changed, 115 insertions(+), 3 deletions(-)

diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index a8518fb..37fae59 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -149,7 +149,10 @@ config DVB_NET
 	  You may want to disable the network support on embedded devices. If
 	  unsure say Y.
 
-# This Kconfig option is used by both PCI and USB drivers
+# Options used by both PCI and USB drivers
+config DVB_PTX_COMMON
+	tristate
+
 config TTPCI_EEPROM
 	tristate
 	depends on I2C
diff --git a/drivers/media/usb/em28xx/Kconfig b/drivers/media/usb/em28xx/Kconfig
index e382210..fc19edc 100644
--- a/drivers/media/usb/em28xx/Kconfig
+++ b/drivers/media/usb/em28xx/Kconfig
@@ -59,6 +59,9 @@ config VIDEO_EM28XX_DVB
 	select DVB_DRX39XYJ if MEDIA_SUBDRV_AUTOSELECT
 	select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_PTX_COMMON
+	select DVB_TC90522 if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_QM1D1C004X if MEDIA_SUBDRV_AUTOSELECT
 	---help---
 	  This adds support for DVB cards based on the
 	  Empiatech em28xx chips.
diff --git a/drivers/media/usb/em28xx/Makefile b/drivers/media/usb/em28xx/Makefile
index 3f850d5..1488829 100644
--- a/drivers/media/usb/em28xx/Makefile
+++ b/drivers/media/usb/em28xx/Makefile
@@ -14,3 +14,4 @@ ccflags-y += -Idrivers/media/i2c
 ccflags-y += -Idrivers/media/tuners
 ccflags-y += -Idrivers/media/dvb-core
 ccflags-y += -Idrivers/media/dvb-frontends
+ccflags-y += -Idrivers/media/pci/ptx
diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c
index 930e3e3..772a8f8 100644
--- a/drivers/media/usb/em28xx/em28xx-cards.c
+++ b/drivers/media/usb/em28xx/em28xx-cards.c
@@ -492,6 +492,20 @@ static struct em28xx_reg_seq terratec_t2_stick_hd[] = {
 	{-1,                             -1,   -1,     -1},
 };
 
+static struct em28xx_reg_seq plex_px_bcud[] = {
+	{EM2874_R80_GPIO_P0_CTRL,	0xff,	0xff,	0},
+	{0x0d,				0xff,	0xff,	0},
+	{EM2874_R50_IR_CONFIG,		0x01,	0xff,	0},
+	{EM28XX_R06_I2C_CLK,		0x40,	0xff,	0},
+	{EM2874_R80_GPIO_P0_CTRL,	0xfd,	0xff,	100},
+	{EM28XX_R12_VINENABLE,		0x20,	0x20,	0},
+	{0x0d,				0x42,	0xff,	1000},
+	{EM2874_R80_GPIO_P0_CTRL,	0xfc,	0xff,	10},
+	{EM2874_R80_GPIO_P0_CTRL,	0xfd,	0xff,	10},
+	{0x73,				0xfd,	0xff,	100},
+	{-1,				-1,	-1,	-1},
+};
+
 /*
  *  Button definitions
  */
@@ -2306,6 +2320,17 @@ struct em28xx_board em28xx_boards[] = {
 		.has_dvb       = 1,
 		.ir_codes      = RC_MAP_TERRATEC_SLIM_2,
 	},
+	/* 3275:0085 PLEX PX-BCUD.
+	 * Empia EM28178, TOSHIBA TC90532XBG, Sharp QM1D1C0042 */
+	[EM28178_BOARD_PLEX_PX_BCUD] = {
+		.name          = "PLEX PX-BCUD",
+		.xclk          = EM28XX_XCLK_FREQUENCY_4_3MHZ,
+		.def_i2c_bus   = 1,
+		.i2c_speed     = EM28XX_I2C_CLK_WAIT_ENABLE,
+		.tuner_type    = TUNER_ABSENT,
+		.tuner_gpio    = plex_px_bcud,
+		.has_dvb       = 1,
+	},
 };
 EXPORT_SYMBOL_GPL(em28xx_boards);
 
@@ -2495,6 +2520,8 @@ struct usb_device_id em28xx_id_table[] = {
 			.driver_info = EM2861_BOARD_LEADTEK_VC100 },
 	{ USB_DEVICE(0xeb1a, 0x8179),
 			.driver_info = EM28178_BOARD_TERRATEC_T2_STICK_HD },
+	{ USB_DEVICE(0x3275, 0x0085),
+			.driver_info = EM28178_BOARD_PLEX_PX_BCUD },
 	{ },
 };
 MODULE_DEVICE_TABLE(usb, em28xx_id_table);
diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c
index 5d209c7..c45112e 100644
--- a/drivers/media/usb/em28xx/em28xx-dvb.c
+++ b/drivers/media/usb/em28xx/em28xx-dvb.c
@@ -12,6 +12,10 @@
 
  (c) 2012 Frank Schäfer <fschaefer.oss@googlemail.com>
 
+ (c) 2016 Nagahama Satoshi <sattnag@aim.com>
+	  Budi Rachmanto, AreMa Inc. <info@are.ma>
+	- PLEX PX-BCUD support
+
  Based on cx88-dvb, saa7134-dvb and videobuf-dvb originally written by:
 	(c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
 	(c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
@@ -25,11 +29,10 @@
 #include <linux/slab.h>
 #include <linux/usb.h>
 
+#include "ptx_common.h"
 #include "em28xx.h"
 #include <media/v4l2-common.h>
-#include <dvb_demux.h>
 #include <dvb_net.h>
-#include <dmxdev.h>
 #include <media/tuner.h>
 #include "tuner-simple.h"
 #include <linux/gpio.h>
@@ -58,6 +61,8 @@
 #include "ts2020.h"
 #include "si2168.h"
 #include "si2157.h"
+#include "tc90522.h"
+#include "qm1d1c004x.h"
 
 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
 MODULE_LICENSE("GPL");
@@ -787,6 +792,65 @@ static int em28xx_mt352_terratec_xs_init(struct dvb_frontend *fe)
 	return 0;
 }
 
+static void px_bcud_init(struct em28xx *dev)
+{
+	int i;
+	struct {
+		unsigned char r[4];
+		int len;
+	} regs1[] = {
+		{{ 0x0e, 0x77 }, 2},
+		{{ 0x0f, 0x77 }, 2},
+		{{ 0x03, 0x90 }, 2},
+	}, regs2[] = {
+		{{ 0x07, 0x01 }, 2},
+		{{ 0x08, 0x10 }, 2},
+		{{ 0x13, 0x00 }, 2},
+		{{ 0x17, 0x00 }, 2},
+		{{ 0x03, 0x01 }, 2},
+		{{ 0x10, 0xb1 }, 2},
+		{{ 0x11, 0x40 }, 2},
+		{{ 0x85, 0x7a }, 2},
+		{{ 0x87, 0x04 }, 2},
+	};
+	static struct em28xx_reg_seq gpio[] = {
+		{EM28XX_R06_I2C_CLK,		0x40,	0xff,	300},
+		{EM2874_R80_GPIO_P0_CTRL,	0xfd,	0xff,	60},
+		{EM28XX_R15_RGAIN,		0x20,	0xff,	0},
+		{EM28XX_R16_GGAIN,		0x20,	0xff,	0},
+		{EM28XX_R17_BGAIN,		0x20,	0xff,	0},
+		{EM28XX_R18_ROFFSET,		0x00,	0xff,	0},
+		{EM28XX_R19_GOFFSET,		0x00,	0xff,	0},
+		{EM28XX_R1A_BOFFSET,		0x00,	0xff,	0},
+		{EM28XX_R23_UOFFSET,		0x00,	0xff,	0},
+		{EM28XX_R24_VOFFSET,		0x00,	0xff,	0},
+		{EM28XX_R26_COMPR,		0x00,	0xff,	0},
+		{0x13,				0x08,	0xff,	0},
+		{EM28XX_R12_VINENABLE,		0x27,	0xff,	0},
+		{EM28XX_R0C_USBSUSP,		0x10,	0xff,	0},
+		{EM28XX_R27_OUTFMT,		0x00,	0xff,	0},
+		{EM28XX_R10_VINMODE,		0x00,	0xff,	0},
+		{EM28XX_R11_VINCTRL,		0x11,	0xff,	0},
+		{EM2874_R50_IR_CONFIG,		0x01,	0xff,	0},
+		{EM2874_R5F_TS_ENABLE,		0x80,	0xff,	0},
+		{EM28XX_R06_I2C_CLK,		0x46,	0xff,	0},
+	};
+	em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x46);
+	/* sleeping ISDB-T */
+	dev->dvb->i2c_client_demod->addr = 0x14;
+	for (i = 0; i < ARRAY_SIZE(regs1); i++)
+		i2c_master_send(dev->dvb->i2c_client_demod, regs1[i].r, regs1[i].len);
+	/* sleeping ISDB-S */
+	dev->dvb->i2c_client_demod->addr = 0x15;
+	for (i = 0; i < ARRAY_SIZE(regs2); i++)
+		i2c_master_send(dev->dvb->i2c_client_demod, regs2[i].r, regs2[i].len);
+	for (i = 0; i < ARRAY_SIZE(gpio); i++) {
+		em28xx_write_reg_bits(dev, gpio[i].reg, gpio[i].val, gpio[i].mask);
+		if (gpio[i].sleep > 0)
+			msleep(gpio[i].sleep);
+	}
+};
+
 static struct mt352_config terratec_xs_mt352_cfg = {
 	.demod_address = (0x1e >> 1),
 	.no_tuner = 1,
@@ -1762,6 +1826,19 @@ static int em28xx_dvb_init(struct em28xx *dev)
 			dvb->i2c_client_tuner = client;
 		}
 		break;
+	case EM28178_BOARD_PLEX_PX_BCUD:
+		{
+			struct ptx_subdev_info	pxbcud_subdev_info =
+				{SYS_ISDBS, 0x15, TC90522_MODNAME, 0x61, QM1D1C004X_MODNAME};
+
+			dvb->fe[0] = ptx_register_fe(&dev->i2c_adap[dev->def_i2c_bus], NULL, &pxbcud_subdev_info);
+			if (!dvb->fe[0])
+                                goto out_free;
+			dvb->i2c_client_demod = dvb->fe[0]->demodulator_priv;
+                        dvb->i2c_client_tuner = dvb->fe[0]->tuner_priv;
+			px_bcud_init(dev);
+		}
+		break;
 	default:
 		em28xx_errdev("/2: The frontend of your DVB/ATSC card"
 				" isn't supported yet\n");
diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h
index 2674449..9ad1240 100644
--- a/drivers/media/usb/em28xx/em28xx.h
+++ b/drivers/media/usb/em28xx/em28xx.h
@@ -145,6 +145,7 @@
 #define EM2861_BOARD_LEADTEK_VC100                95
 #define EM28178_BOARD_TERRATEC_T2_STICK_HD        96
 #define EM2884_BOARD_ELGATO_EYETV_HYBRID_2008     97
+#define EM28178_BOARD_PLEX_PX_BCUD                98
 
 /* Limits minimum and default number of buffers */
 #define EM28XX_MIN_BUF 4
-- 
2.7.4

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

* Re: [media 5/6] PCIE bridge driver for PT3 & PX-Q3PE
  2016-04-04 17:04 ` [media 5/6] PCIE bridge driver for PT3 & PX-Q3PE info
@ 2016-04-04 17:30   ` kbuild test robot
  2016-04-04 21:48   ` kbuild test robot
  2016-04-04 22:20   ` kbuild test robot
  2 siblings, 0 replies; 10+ messages in thread
From: kbuild test robot @ 2016-04-04 17:30 UTC (permalink / raw)
  To: info
  Cc: kbuild-all, linux-media,
	Буди
	Романто,
	AreMa Inc, linux-kernel, crope, m.chehab, mchehab, hdegoede,
	laurent.pinchart, mkrufky, sylvester.nawrocki, g.liakhovetski,
	peter.senna

[-- Attachment #1: Type: text/plain, Size: 3569 bytes --]

Hi Буди,

[auto build test WARNING on linuxtv-media/master]
[also build test WARNING on v4.6-rc2 next-20160404]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/info-are-ma/DVB-driver-for-Earthsoft-PT3-PLEX-PX-Q3PE-ISDB-S-T-PCIE-cards-PX-BCUD-ISDB-S-USB-dongle/20160405-011100
base:   git://linuxtv.org/media_tree.git master
config: s390-allyesconfig (attached as .config)
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=s390 

All warnings (new ones prefixed by >>):

   drivers/media/tuners/mxl301rf.c: In function 'mxl301rf_w':
>> drivers/media/tuners/mxl301rf.c:26:1: warning: 'mxl301rf_w' uses dynamic stack allocation
    }
    ^
   drivers/media/tuners/mxl301rf.c: In function 'mxl301rf_w_tuner':
>> drivers/media/tuners/mxl301rf.c:35:1: warning: 'mxl301rf_w_tuner' uses dynamic stack allocation
    }
    ^
--
   drivers/media/tuners/qm1d1c004x.c: In function 'qm1d1c004x_w':
>> drivers/media/tuners/qm1d1c004x.c:51:1: warning: 'qm1d1c004x_w' uses dynamic stack allocation
    }
    ^
--
   drivers/media/tuners/nm131.c: In function 'nm131_r':
>> drivers/media/tuners/nm131.c:45:1: warning: 'nm131_r' uses dynamic stack allocation
    }
    ^

vim +/mxl301rf_w +26 drivers/media/tuners/mxl301rf.c

8be8684f Буди Романто, AreMa Inc 2016-04-05  20  		{.addr = d->addr,	.flags = 0,	.buf = buf,	.len = len + 1,},
8be8684f Буди Романто, AreMa Inc 2016-04-05  21  	};
8be8684f Буди Романто, AreMa Inc 2016-04-05  22  
8be8684f Буди Романто, AreMa Inc 2016-04-05  23  	buf[0] = slvadr;
8be8684f Буди Романто, AreMa Inc 2016-04-05  24  	memcpy(buf + 1, dat, len);
8be8684f Буди Романто, AreMa Inc 2016-04-05  25  	return i2c_transfer(d->adapter, msg, 1) == 1 ? 0 : -EIO;
8be8684f Буди Романто, AreMa Inc 2016-04-05 @26  }
8be8684f Буди Романто, AreMa Inc 2016-04-05  27  
8be8684f Буди Романто, AreMa Inc 2016-04-05  28  int mxl301rf_w_tuner(struct dvb_frontend *fe, const u8 *dat, int len)
8be8684f Буди Романто, AreMa Inc 2016-04-05  29  {
8be8684f Буди Романто, AreMa Inc 2016-04-05  30  	u8 buf[len + 1];
8be8684f Буди Романто, AreMa Inc 2016-04-05  31  
8be8684f Буди Романто, AreMa Inc 2016-04-05  32  	buf[0] = ((struct i2c_client *)fe->tuner_priv)->addr << 1;
8be8684f Буди Романто, AreMa Inc 2016-04-05  33  	memcpy(buf + 1, dat, len);
8be8684f Буди Романто, AreMa Inc 2016-04-05  34  	return mxl301rf_w(fe, 0xFE, buf, len + 1);
8be8684f Буди Романто, AreMa Inc 2016-04-05 @35  }
8be8684f Буди Романто, AreMa Inc 2016-04-05  36  
8be8684f Буди Романто, AreMa Inc 2016-04-05  37  u8 mxl301rf_r(struct dvb_frontend *fe, u8 regadr)
8be8684f Буди Романто, AreMa Inc 2016-04-05  38  {

:::::: The code at line 26 was first introduced by commit
:::::: 8be8684ff9906c489dc94d4d9b0fadab97c4a3af Tuners for Earthsoft PT3, PLEX PX-Q3PE ISDB-S/T PCIE cards & PX-BCUD ISDB-S USB dongle

:::::: TO: Буди Романто, AreMa Inc <knightrider@are.ma>
:::::: CC: 0day robot <fengguang.wu@intel.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 40612 bytes --]

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

* Re: [media 5/6] PCIE bridge driver for PT3 & PX-Q3PE
  2016-04-04 17:04 ` [media 5/6] PCIE bridge driver for PT3 & PX-Q3PE info
  2016-04-04 17:30   ` kbuild test robot
@ 2016-04-04 21:48   ` kbuild test robot
  2016-04-04 22:20   ` kbuild test robot
  2 siblings, 0 replies; 10+ messages in thread
From: kbuild test robot @ 2016-04-04 21:48 UTC (permalink / raw)
  To: info
  Cc: kbuild-all, linux-media,
	Буди
	Романто,
	AreMa Inc, linux-kernel, crope, m.chehab, mchehab, hdegoede,
	laurent.pinchart, mkrufky, sylvester.nawrocki, g.liakhovetski,
	peter.senna

[-- Attachment #1: Type: text/plain, Size: 2049 bytes --]

Hi Буди,

[auto build test WARNING on linuxtv-media/master]
[also build test WARNING on v4.6-rc2 next-20160404]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/info-are-ma/DVB-driver-for-Earthsoft-PT3-PLEX-PX-Q3PE-ISDB-S-T-PCIE-cards-PX-BCUD-ISDB-S-USB-dongle/20160405-011100
base:   git://linuxtv.org/media_tree.git master
config: s390-allmodconfig (attached as .config)
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=s390 

All warnings (new ones prefixed by >>):

   drivers/media/pci/ptx/pxq3pe.c: In function 'pxq3pe_xfr':
>> drivers/media/pci/ptx/pxq3pe.c:257:1: warning: 'pxq3pe_xfr' uses dynamic stack allocation
    }
    ^

vim +/pxq3pe_xfr +257 drivers/media/pci/ptx/pxq3pe.c

   241				regadr	= msg->len ? *msg->buf : 0,
   242				mode	= slvadr == PXQ3PE_I2C_ADR_GPIO	? PXQ3PE_MOD_GPIO
   243					: sz > 1 && i == sz - 2		? PXQ3PE_MOD_STAT
   244					: PXQ3PE_MOD_TUNER;
   245	
   246			mutex_lock(&card->lock);
   247			if (msg->flags & I2C_M_RD) {
   248				u8 buf[sz];
   249	
   250				ret = pxq3pe_r(card, slvadr, regadr, buf, msg->len, mode);
   251				memcpy(msg->buf, buf, msg->len);
   252			} else
   253				ret = pxq3pe_w(card, slvadr, regadr, msg->buf, msg->len, mode);
   254			mutex_unlock(&card->lock);
   255		}
   256		return i;
 > 257	}
   258	
   259	bool pxq3pe_w_gpio2(struct ptx_card *card, u8 dat, u8 mask)
   260	{
   261		u8 val;
   262	
   263		return	pxq3pe_r(card, PXQ3PE_I2C_ADR_GPIO, 0xB, &val, 1, PXQ3PE_MOD_GPIO)	&&
   264			(val = (mask & dat) | (val & ~mask), pxq3pe_w(card, PXQ3PE_I2C_ADR_GPIO, 0xB, &val, 1, PXQ3PE_MOD_GPIO));
   265	}

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 40572 bytes --]

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

* Re: [media 5/6] PCIE bridge driver for PT3 & PX-Q3PE
  2016-04-04 17:04 ` [media 5/6] PCIE bridge driver for PT3 & PX-Q3PE info
  2016-04-04 17:30   ` kbuild test robot
  2016-04-04 21:48   ` kbuild test robot
@ 2016-04-04 22:20   ` kbuild test robot
  2 siblings, 0 replies; 10+ messages in thread
From: kbuild test robot @ 2016-04-04 22:20 UTC (permalink / raw)
  To: info
  Cc: kbuild-all, linux-media,
	Буди
	Романто,
	AreMa Inc, linux-kernel, crope, m.chehab, mchehab, hdegoede,
	laurent.pinchart, mkrufky, sylvester.nawrocki, g.liakhovetski,
	peter.senna

[-- Attachment #1: Type: text/plain, Size: 2175 bytes --]

Hi Буди,

[auto build test ERROR on linuxtv-media/master]
[also build test ERROR on v4.6-rc2 next-20160404]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/info-are-ma/DVB-driver-for-Earthsoft-PT3-PLEX-PX-Q3PE-ISDB-S-T-PCIE-cards-PX-BCUD-ISDB-S-USB-dongle/20160405-011100
base:   git://linuxtv.org/media_tree.git master
config: x86_64-randconfig-n0-04050300 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

Note: the linux-review/info-are-ma/DVB-driver-for-Earthsoft-PT3-PLEX-PX-Q3PE-ISDB-S-T-PCIE-cards-PX-BCUD-ISDB-S-USB-dongle/20160405-011100 HEAD b63c486d6d62c3611264e122cf14e0271d6e137a builds fine.
      It only hurts bisectibility.

All errors (new ones prefixed by >>):

   drivers/built-in.o: In function `pt3_remove':
>> (.text+0x24374c0): undefined reference to `ptx_unregister_adap'
   drivers/built-in.o: In function `pt3_remove':
>> (.text+0x2437883): undefined reference to `ptx_sleep'
   drivers/built-in.o: In function `pt3_probe':
>> (.text+0x2437d83): undefined reference to `ptx_alloc'
   drivers/built-in.o: In function `pt3_probe':
>> (.text+0x2437dfa): undefined reference to `ptx_abort'
   drivers/built-in.o: In function `pt3_probe':
   (.text+0x2437e7d): undefined reference to `ptx_abort'
   drivers/built-in.o: In function `pt3_probe':
   (.text+0x2437fe3): undefined reference to `ptx_abort'
   drivers/built-in.o: In function `pt3_probe':
   (.text+0x2438617): undefined reference to `ptx_abort'
   drivers/built-in.o: In function `pt3_probe':
   (.text+0x243863d): undefined reference to `ptx_abort'
   drivers/built-in.o: In function `pt3_probe':
>> (.text+0x2438b63): undefined reference to `ptx_i2c_add_adapter'
   drivers/built-in.o: In function `pt3_probe':
>> (.text+0x2438ba6): undefined reference to `ptx_register_adap'
>> drivers/built-in.o:(.rodata+0x5c4370): undefined reference to `ptx_i2c_func'

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 27259 bytes --]

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

end of thread, other threads:[~2016-04-04 22:22 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-04 17:03 [media 0/6] DVB driver for Earthsoft PT3, PLEX PX-Q3PE ISDB-S/T PCIE cards & PX-BCUD ISDB-S USB dongle info
2016-04-04 17:04 ` [media 1/6] Raise adapter number limit info
2016-04-04 17:04 ` [media 2/6] drop backstabbing drivers info
2016-04-04 17:04 ` [media 3/6] Demodulator for Earthsoft PT3, PLEX PX-Q3PE ISDB-S/T PCIE cards & PX-BCUD ISDB-S USB dongle info
2016-04-04 17:04 ` [media 4/6] Tuners " info
2016-04-04 17:04 ` [media 5/6] PCIE bridge driver for PT3 & PX-Q3PE info
2016-04-04 17:30   ` kbuild test robot
2016-04-04 21:48   ` kbuild test robot
2016-04-04 22:20   ` kbuild test robot
2016-04-04 17:04 ` [media 6/6] Bridge driver for PLEX PX-BCUD ISDB-S USB dongle info

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).