Subject: [media 0/8] DVB driver for Earthsoft PT3, PLEX PX-Q3PE ISDB-S/T PCIE cards & PX-BCUD ISDB-S USB dongle

From: Буди Романто, AreMa Inc <[email protected]>

MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
To: [email protected]
Cc: [email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected]

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 (8):
The current limit is too low for latest cards with 8+ tuners on a
single slot, change to 64.
NXP tda2014x & Newport Media nm120/130/131 tuner drivers for PLEX
PX-Q3PE
Obsoleted & superseded, please read cover letter for details.
Toshiba TC905xx demodulator driver for PT3, PX-Q3PE & PX-BCUD
MaxLinear MxL301RF ISDB-T tuner
Sharp QM1D1C004x ISDB-S tuner driver for PT3 and PX-BCUD
PCIE bridge driver for PT3 & PX-Q3PE Please read cover letter for
details.
Support for PLEX PX-BCUD (ISDB-S usb dongle) Nagahama's patch
simplified...

drivers/media/dvb-core/dvbdev.h | 2 +-
drivers/media/dvb-frontends/tc90522.c | 965 +++++++-------------------------
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 | 21 +
drivers/media/pci/ptx/Makefile | 8 +
drivers/media/pci/ptx/pt3_pci.c | 425 ++++++++++++++
drivers/media/pci/ptx/ptx_common.c | 252 +++++++++
drivers/media/pci/ptx/ptx_common.h | 74 +++
drivers/media/pci/ptx/pxq3pe_pci.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 | 342 +++++++++++
drivers/media/tuners/tda2014x.h | 13 +
drivers/media/usb/em28xx/Kconfig | 2 +
drivers/media/usb/em28xx/em28xx-cards.c | 27 +
drivers/media/usb/em28xx/em28xx-dvb.c | 79 ++-
drivers/media/usb/em28xx/em28xx.h | 1 +
33 files changed, 2752 insertions(+), 3153 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_pci.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_pci.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


Subject: [media 1/8] raise adapter number limit

From: Буди Романто, AreMa Inc <[email protected]>

The current limit is too low for latest cards with 8+ tuners on a single slot, change to 64.

Signed-off-by: Буди Романто, AreMa Inc <[email protected]>
---
drivers/media/dvb-core/dvbdev.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/dvb-core/dvbdev.h b/drivers/media/dvb-core/dvbdev.h
index 4aff7bd..950decd 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 64
#endif

#define DVB_UNSET (-1)
--
2.7.4

Subject: [media 2/8] NXP tda2014x & Newport Media nm120/130/131 tuner (PXQ3PE)

From: Буди Романто, AreMa Inc <[email protected]>

NXP tda2014x & Newport Media nm120/130/131 tuner drivers for PLEX PX-Q3PE

Signed-off-by: Буди Романто, AreMa Inc <[email protected]>
---
drivers/media/tuners/Kconfig | 21 ++-
drivers/media/tuners/Makefile | 4 +-
drivers/media/tuners/nm131.c | 248 +++++++++++++++++++++++++++++
drivers/media/tuners/nm131.h | 13 ++
drivers/media/tuners/tda2014x.c | 342 ++++++++++++++++++++++++++++++++++++++++
drivers/media/tuners/tda2014x.h | 13 ++
6 files changed, 637 insertions(+), 4 deletions(-)
create mode 100644 drivers/media/tuners/nm131.c
create mode 100644 drivers/media/tuners/nm131.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/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. <[email protected]>
+*/
+
+#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. <[email protected]>");
+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. <[email protected]>
+ */
+
+#ifndef NM131_H
+#define NM131_H
+
+#define NM131_MODNAME "nm131"
+
+#endif
+
diff --git a/drivers/media/tuners/tda2014x.c b/drivers/media/tuners/tda2014x.c
new file mode 100644
index 0000000..bd54efc
--- /dev/null
+++ b/drivers/media/tuners/tda2014x.c
@@ -0,0 +1,342 @@
+/*
+ Driver for NXP Semiconductors tuner TDA2014x
+
+ Copyright (C) Budi Rachmanto, AreMa Inc. <[email protected]>
+*/
+
+#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)
+{
+ 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;
+ u64 kHz = fe->dtv_property_cache.frequency,
+ ResLsb,
+ Premain,
+ CalcPrecision = 1000000,
+ kint,
+ Nint,
+ R,
+ 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 * 1000 / 27; /* Xtal 27 MHz */
+ kint = ResLsb;
+ v15 = ResLsb / 1000000;
+ R = 1;
+ Premain = 2;
+ Nint = v15 * R / Premain;
+ if (Nint < 131) {
+ Premain = 1;
+ Nint = v15 * R / Premain;
+ if (Nint > 251) {
+ R = 3;
+ Premain = 4;
+ goto LABEL_36;
+ }
+ if (Nint < 131) {
+ R = 3;
+ Premain = 2;
+ goto LABEL_36;
+ }
+ } else if (Nint > 251) {
+ Premain = 4;
+ Nint = v15 * R / Premain;
+ if (Nint > 251) {
+ R = 3;
+ Premain = 4;
+ }
+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 = (kint / 10) * 10;
+ ePllRefClkRatio = R == 2 ? 1 : R == 3 ? 2 : 0;
+ PredividerRatio = Premain == 2 ? 0 : 1;
+ DsmIntInReg = kint / 1000000;
+ DsmFracInReg = kint - 1000000 * DsmIntInReg;
+ for (i = 0; i < 16; i++) {
+ DsmFracInReg *= 2;
+ if (DsmFracInReg > 0xFFFFFFF && i != 15) {
+ DsmFracInReg /= 10;
+ CalcPrecision /= 10;
+ }
+ }
+ 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, DsmFracInReg / CalcPrecision) &&
+
+ /* 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. <[email protected]>");
+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. <[email protected]>
+ */
+
+#ifndef TDA2014X_H
+#define TDA2014X_H
+
+#define TDA2014X_MODNAME "tda2014x"
+
+#endif
+
--
2.7.4

Subject: [media 6/8] Sharp QM1D1C004x ISDB-S tuner driver for PT3 and PX-BCUD

From: Буди Романто, AreMa Inc <[email protected]>

Signed-off-by: Буди Романто, AreMa Inc <[email protected]>
---
drivers/media/tuners/qm1d1c004x.c | 242 ++++++++++++++++++++++++++++++++++++++
drivers/media/tuners/qm1d1c004x.h | 23 ++++
2 files changed, 265 insertions(+)
create mode 100644 drivers/media/tuners/qm1d1c004x.c
create mode 100644 drivers/media/tuners/qm1d1c004x.h

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. <[email protected]>
+
+ 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. <[email protected]>
+
+ 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
+
--
2.7.4

Subject: [media 4/8] Toshiba TC905xx demodulator for PT3/PX-Q3PE/PX-BCUD

From: Буди Романто, AreMa Inc <[email protected]>

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

Signed-off-by: Буди Романто, AreMa Inc <[email protected]>
---
drivers/media/dvb-frontends/tc90522.c | 255 ++++++++++++++++++++++++++++++++++
drivers/media/dvb-frontends/tc90522.h | 18 +++
2 files changed, 273 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..97007ec
--- /dev/null
+++ b/drivers/media/dvb-frontends/tc90522.c
@@ -0,0 +1,255 @@
+/*
+ Toshiba TC90522XBG 2ch OFDM(ISDB-T) + 2ch 8PSK(ISDB-S) demodulator
+
+ Copyright (C) Budi Rachmanto, AreMa Inc. <[email protected]>
+
+ 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 <linux/pci.h>
+#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. <[email protected]>
+ *
+ * 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

Subject: [media 8/8] Support for PLEX PX-BCUD (ISDB-S usb dongle)

From: Буди Романто, AreMa Inc <[email protected]>

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

Signed-off-by: Буди Романто, AreMa Inc <[email protected]>
---
drivers/media/usb/em28xx/Kconfig | 2 +
drivers/media/usb/em28xx/em28xx-cards.c | 27 +++++++++++
drivers/media/usb/em28xx/em28xx-dvb.c | 79 ++++++++++++++++++++++++++++++++-
drivers/media/usb/em28xx/em28xx.h | 1 +
4 files changed, 107 insertions(+), 2 deletions(-)

diff --git a/drivers/media/usb/em28xx/Kconfig b/drivers/media/usb/em28xx/Kconfig
index e382210..b138939 100644
--- a/drivers/media/usb/em28xx/Kconfig
+++ b/drivers/media/usb/em28xx/Kconfig
@@ -59,6 +59,8 @@ 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_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/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..e6c5a97 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 <[email protected]>

+ (c) 2016 Nagahama Satoshi <[email protected]>
+ Budi Rachmanto, AreMa Inc. <[email protected]>
+ - PLEX PX-BCUD support
+
Based on cx88-dvb, saa7134-dvb and videobuf-dvb originally written by:
(c) 2004, 2005 Chris Pascoe <[email protected]>
(c) 2004 Gerd Knorr <[email protected]> [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>
@@ -787,6 +790,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 +1824,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

Subject: [media 7/8] PCIE bridge driver for PT3 & PX-Q3PE

From: Буди Романто, AreMa Inc <[email protected]>

PCIE bridge driver for PT3 & PX-Q3PE
Please read cover letter for details.

Signed-off-by: Буди Романто, AreMa Inc <[email protected]>
---
drivers/media/pci/Kconfig | 2 +-
drivers/media/pci/Makefile | 2 +-
drivers/media/pci/ptx/Kconfig | 21 ++
drivers/media/pci/ptx/Makefile | 8 +
drivers/media/pci/ptx/pt3_pci.c | 425 +++++++++++++++++++++++++++
drivers/media/pci/ptx/ptx_common.c | 252 ++++++++++++++++
drivers/media/pci/ptx/ptx_common.h | 74 +++++
drivers/media/pci/ptx/pxq3pe_pci.c | 585 +++++++++++++++++++++++++++++++++++++
8 files changed, 1367 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_pci.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_pci.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..792acfe
--- /dev/null
+++ b/drivers/media/pci/ptx/Kconfig
@@ -0,0 +1,21 @@
+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 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_TC90522 if MEDIA_SUBDRV_AUTOSELECT
+ select MEDIA_TUNER_QM1D1C0042 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..b10ad8a
--- /dev/null
+++ b/drivers/media/pci/ptx/Makefile
@@ -0,0 +1,8 @@
+pt3-objs := pt3_pci.o ptx_common.o
+pxq3pe-objs := pxq3pe_pci.o 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_pci.c b/drivers/media/pci/ptx/pt3_pci.c
new file mode 100644
index 0000000..07431da
--- /dev/null
+++ b/drivers/media/pci/ptx/pt3_pci.c
@@ -0,0 +1,425 @@
+/*
+ DVB driver for Earthsoft PT3 ISDB-S/T PCIE bridge Altera Cyclone IV FPGA EP4CGX15BF14C8N
+
+ Copyright (C) Budi Rachmanto, AreMa Inc. <[email protected]>
+
+ 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("Budi Rachmanto, AreMa Inc. <knightrider(@)are.ma>");
+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 */
+ writeq(p->desc_info->adr, base + PT3_DMA_DESC);
+ 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;
+ u32 i,
+ j,
+ desc_todo = 0,
+ desc_pg_idx = 0;
+ u64 desc_addr;
+
+ 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..90d697f
--- /dev/null
+++ b/drivers/media/pci/ptx/ptx_common.c
@@ -0,0 +1,252 @@
+/*
+ Common procedures for PT3, PX-Q3PE, and other DVB drivers
+
+ Copyright (C) Budi Rachmanto, AreMa Inc. <[email protected]>
+*/
+
+#include "ptx_common.h"
+
+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);
+}
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adap_no);
+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;
+ 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;
+}
+
+
diff --git a/drivers/media/pci/ptx/ptx_common.h b/drivers/media/pci/ptx/ptx_common.h
new file mode 100644
index 0000000..6aeb1b4
--- /dev/null
+++ b/drivers/media/pci/ptx/ptx_common.h
@@ -0,0 +1,74 @@
+/*
+ * Defs & procs for PT3 & PX-Q3PE DVB driver
+ *
+ * Copyright (C) Budi Rachmanto, AreMa Inc. <[email protected]>
+ *
+ * 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"
+
+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_pci.c b/drivers/media/pci/ptx/pxq3pe_pci.c
new file mode 100644
index 0000000..45590eb
--- /dev/null
+++ b/drivers/media/pci/ptx/pxq3pe_pci.c
@@ -0,0 +1,585 @@
+/*
+ DVB driver for PLEX PX-Q3PE ISDB-S/T PCIE receiver
+
+ Copyright (C) Budi Rachmanto, AreMa Inc. <[email protected]>
+
+ 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 "ptx_common.h"
+#include "tc90522.h"
+#include "tda2014x.h"
+#include "nm131.h"
+
+#define MOD_AUTH "Budi Rachmanto, AreMa Inc. <knightrider(@)are.ma>"
+MODULE_AUTHOR(MOD_AUTH);
+MODULE_DESCRIPTION("PLEX PX-Q3PE Driver");
+MODULE_LICENSE("GPL");
+
+static char *auth = MOD_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

Subject: [media 5/8] MaxLinear MxL301RF ISDB-T tuner

From: Буди Романто, AreMa Inc <[email protected]>

Signed-off-by: Буди Романто, AreMa Inc <[email protected]>
---
drivers/media/tuners/mxl301rf.c | 220 ++++++++++++++++++++++++++++++++++++++++
drivers/media/tuners/mxl301rf.h | 23 +++++
2 files changed, 243 insertions(+)
create mode 100644 drivers/media/tuners/mxl301rf.c
create mode 100644 drivers/media/tuners/mxl301rf.h

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. <[email protected]>
+
+ 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. <[email protected]>
+ *
+ * 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
+
--
2.7.4

Subject: [media 3/8] drop backstabbing drivers

From: Буди Романто, AreMa Inc <[email protected]>

Obsoleted & superseded, please read cover letter for details.

Signed-off-by: Буди Романто, AreMa Inc <[email protected]>
---
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 <[email protected]>
- *
- * 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 <[email protected]>
- *
- * 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 <[email protected]>
- *
- * 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 <[email protected]>
- *
- * 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 <[email protected]>
- *
- * 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 <[email protected]>
- *
- * 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 <[email protected]>
- *
- * 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 <[email protected]>
- *
- * 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 <[email protected]>
- *
- * 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 <[email protected]>
- *
- * 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

2016-04-01 03:47:46

by kernel test robot

[permalink] [raw]
Subject: Re: [media 7/8] PCIE bridge driver for PT3 & PX-Q3PE

Hi Буди,

[auto build test ERROR on linuxtv-media/master]
[also build test ERROR on v4.6-rc1 next-20160331]
[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/20160401-034740
base: git://linuxtv.org/media_tree.git master
config: i386-allyesconfig (attached as .config)
reproduce:
# save the attached .config to linux build tree
make ARCH=i386

All errors (new ones prefixed by >>):

>> drivers/media/pci/ptx/ptx_common.c:187:536: error: 'KBUILD_MODNAME' undeclared here (not in a function)
>> drivers/media/pci/ptx/ptx_common.c:187:551: error: expected ',' or ';' before string constant

vim +/KBUILD_MODNAME +187 drivers/media/pci/ptx/ptx_common.c

181 pci_release_regions(card->pdev);
182 pci_set_drvdata(card->pdev, NULL);
183 pci_disable_device(card->pdev);
184 kfree(card);
185 }
186
> 187 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adap_no);
188 int ptx_register_adap(struct ptx_card *card, const struct ptx_subdev_info *info,
189 int (*thread)(void *), int (*dma)(struct ptx_adap *, bool))
190 {

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


Attachments:
(No filename) (1.38 kB)
.config.gz (52.50 kB)
Download all attachments

2016-04-01 04:09:27

by kernel test robot

[permalink] [raw]
Subject: Re: [media 2/8] NXP tda2014x & Newport Media nm120/130/131 tuner (PXQ3PE)

Hi Буди,

[auto build test ERROR on linuxtv-media/master]
[also build test ERROR on v4.6-rc1 next-20160331]
[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/20160401-034740
base: git://linuxtv.org/media_tree.git master
config: x86_64-randconfig-s0-04011126 (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/20160401-034740 HEAD a28878c9675f849df56f4623c33ca431f03e240a builds fine.
It only hurts bisectibility.

All errors (new ones prefixed by >>):

>> make[4]: *** No rule to make target 'drivers/media/tuners/qm1d1c004x.o', needed by 'drivers/media/tuners/built-in.o'.
make[4]: Target '__build' not remade because of errors.

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


Attachments:
(No filename) (1.17 kB)
.config.gz (21.90 kB)
Download all attachments

2016-04-01 04:13:57

by kernel test robot

[permalink] [raw]
Subject: Re: [media 7/8] PCIE bridge driver for PT3 & PX-Q3PE

Hi Буди,

[auto build test WARNING on linuxtv-media/master]
[also build test WARNING on v4.6-rc1 next-20160331]
[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/20160401-034740
base: git://linuxtv.org/media_tree.git master
config: i386-allmodconfig (attached as .config)
reproduce:
# save the attached .config to linux build tree
make ARCH=i386

All warnings (new ones prefixed by >>):

drivers/media/pci/ptx/pxq3pe_pci.c: In function 'pxq3pe_remove':
drivers/media/pci/ptx/pxq3pe_pci.c:484:3: error: implicit declaration of function 'vfree' [-Werror=implicit-function-declaration]
vfree(p->sBuf);
^
drivers/media/pci/ptx/pxq3pe_pci.c: In function 'pxq3pe_probe':
drivers/media/pci/ptx/pxq3pe_pci.c:536:14: error: implicit declaration of function 'vzalloc' [-Werror=implicit-function-declaration]
p->sBuf = vzalloc(p->sBufSize);
^
>> drivers/media/pci/ptx/pxq3pe_pci.c:536:12: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
p->sBuf = vzalloc(p->sBufSize);
^
cc1: some warnings being treated as errors

vim +536 drivers/media/pci/ptx/pxq3pe_pci.c

478 if (c->dma.dat)
479 pci_free_consistent(card->pdev, c->dma.sz, c->dma.dat, c->dma.adr);
480 for (i = 0; i < card->adapn; i++) {
481 struct ptx_adap *adap = &card->adap[i];
482 struct pxq3pe_adap *p = adap->priv;
483
> 484 vfree(p->sBuf);
485 }
486 if (c->bar)
487 pci_iounmap(pdev, c->bar);
488 ptx_unregister_adap(card);
489 }
490
491 static const struct i2c_algorithm pxq3pe_algo = {
492 .functionality = ptx_i2c_func,
493 .master_xfer = pxq3pe_xfr,
494 };
495
496 static int pxq3pe_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
497 {
498 struct ptx_subdev_info pxq3pe_subdev_info[] = {
499 {SYS_ISDBT, 0x20, TC90522_MODNAME, 0x10, NM131_MODNAME},
500 {SYS_ISDBS, 0x22, TC90522_MODNAME, 0x11, TDA2014X_MODNAME},
501 {SYS_ISDBT, 0x24, TC90522_MODNAME, 0x12, NM131_MODNAME},
502 {SYS_ISDBS, 0x26, TC90522_MODNAME, 0x13, TDA2014X_MODNAME},
503 {SYS_ISDBT, 0x28, TC90522_MODNAME, 0x14, NM131_MODNAME},
504 {SYS_ISDBS, 0x2A, TC90522_MODNAME, 0x15, TDA2014X_MODNAME},
505 {SYS_ISDBT, 0x2C, TC90522_MODNAME, 0x16, NM131_MODNAME},
506 {SYS_ISDBS, 0x2E, TC90522_MODNAME, 0x17, TDA2014X_MODNAME},
507 };
508 struct ptx_card *card = ptx_alloc(pdev, KBUILD_MODNAME, ARRAY_SIZE(pxq3pe_subdev_info),
509 sizeof(struct pxq3pe_card), sizeof(struct pxq3pe_adap), pxq3pe_lnb);
510 struct pxq3pe_card *c;
511 u8 regctl = 0xA0,
512 i;
513 u16 cfg;
514 int err = !card || pci_read_config_word(pdev, PCI_COMMAND, &cfg);
515
516 if (err)
517 return ptx_abort(pdev, pxq3pe_remove, err, "Memory/PCI error, card=%p", card);
518 c = card->priv;
519 if (!(cfg & PCI_COMMAND_MASTER)) {
520 pci_set_master(pdev);
521 pci_read_config_word(pdev, PCI_COMMAND, &cfg);
522 if (!(cfg & PCI_COMMAND_MASTER))
523 return ptx_abort(pdev, pxq3pe_remove, -EIO, "Bus Mastering is disabled");
524 }
525 c->bar = pci_iomap(pdev, 0, 0);
526 if (!c->bar)
527 return ptx_abort(pdev, pxq3pe_remove, -EIO, "I/O map failed");
528 if (ptx_i2c_add_adapter(card, &pxq3pe_algo))
529 return ptx_abort(pdev, pxq3pe_remove, -EIO, "Cannot add I2C");
530
531 for (i = 0; i < card->adapn; i++) {
532 struct ptx_adap *adap = &card->adap[i];
533 struct pxq3pe_adap *p = adap->priv;
534
535 p->sBufSize = PTX_TS_SIZE * 100 << 9;
> 536 p->sBuf = vzalloc(p->sBufSize);
537 if (!p->sBuf)
538 return ptx_abort(pdev, pxq3pe_remove, -ENOMEM, "No memory for stream buffer");
539 }

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


Attachments:
(No filename) (4.05 kB)
.config.gz (53.15 kB)
Download all attachments

2016-04-01 04:20:47

by kernel test robot

[permalink] [raw]
Subject: Re: [media 2/8] NXP tda2014x & Newport Media nm120/130/131 tuner (PXQ3PE)

Hi Буди,

[auto build test ERROR on linuxtv-media/master]
[also build test ERROR on v4.6-rc1 next-20160331]
[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/20160401-034740
base: git://linuxtv.org/media_tree.git master
config: x86_64-randconfig-s5-04011138 (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/20160401-034740 HEAD a28878c9675f849df56f4623c33ca431f03e240a builds fine.
It only hurts bisectibility.

All errors (new ones prefixed by >>):

>> make[4]: *** No rule to make target 'drivers/media/tuners/qm1d1c004x.c', needed by 'drivers/media/tuners/qm1d1c004x.o'.
make[4]: Target '__build' not remade because of errors.

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


Attachments:
(No filename) (1.17 kB)
.config.gz (25.63 kB)
Download all attachments

2016-04-01 14:28:50

by kernel test robot

[permalink] [raw]
Subject: Re: [media 7/8] PCIE bridge driver for PT3 & PX-Q3PE

Hi Буди,

[auto build test ERROR on linuxtv-media/master]
[also build test ERROR on v4.6-rc1 next-20160401]
[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/20160401-034740
base: git://linuxtv.org/media_tree.git master
config: i386-allmodconfig (attached as .config)
reproduce:
# save the attached .config to linux build tree
make ARCH=i386

All errors (new ones prefixed by >>):

drivers/media/pci/ptx/pt3_pci.c: In function 'pt3_dma_run':
>> drivers/media/pci/ptx/pt3_pci.c:225:3: error: implicit declaration of function 'writeq' [-Werror=implicit-function-declaration]
writeq(p->desc_info->adr, base + PT3_DMA_DESC);
^
cc1: some warnings being treated as errors
--
drivers/media/pci/ptx/pxq3pe_pci.c: In function 'pxq3pe_remove':
>> drivers/media/pci/ptx/pxq3pe_pci.c:484:3: error: implicit declaration of function 'vfree' [-Werror=implicit-function-declaration]
vfree(p->sBuf);
^
drivers/media/pci/ptx/pxq3pe_pci.c: In function 'pxq3pe_probe':
>> drivers/media/pci/ptx/pxq3pe_pci.c:536:14: error: implicit declaration of function 'vzalloc' [-Werror=implicit-function-declaration]
p->sBuf = vzalloc(p->sBufSize);
^
drivers/media/pci/ptx/pxq3pe_pci.c:536:12: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
p->sBuf = vzalloc(p->sBufSize);
^
cc1: some warnings being treated as errors

vim +/writeq +225 drivers/media/pci/ptx/pt3_pci.c

219
220 if (ON) {
221 for (i = 0; i < p->ts_blk_cnt; i++) /* 17 */
222 *p->ts_info[i].dat = PTX_TS_NOT_SYNC;
223 p->ts_blk_idx = 0;
224 writel(2, base + PT3_DMA_CTL); /* stop DMA */
> 225 writeq(p->desc_info->adr, base + PT3_DMA_DESC);
226 writel(1, base + PT3_DMA_CTL); /* start DMA */
227 } else {
228 writel(2, base + PT3_DMA_CTL); /* stop DMA */

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


Attachments:
(No filename) (2.20 kB)
.config.gz (53.15 kB)
Download all attachments