linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/12] ngene-updates: Hardware support, TS buffer shift fix
@ 2018-02-25 12:31 Daniel Scheller
  2018-02-25 12:31 ` [PATCH v2 01/12] [media] ngene: add two additional PCI IDs Daniel Scheller
                   ` (11 more replies)
  0 siblings, 12 replies; 16+ messages in thread
From: Daniel Scheller @ 2018-02-25 12:31 UTC (permalink / raw)
  To: linux-media, mchehab, mchehab

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

Sorry for this quick V2 of this series and thus sorry for the traffic,
spam and noise. V1 missed a 188-byte clamping in tsin_find_offset() and
a recheck for the remaining size of the TS buffer to copy after offset
correction.

Some love for the ngene driver, which runs the older Micronas nGene
based cards from Digital Devices like the cineS2 v5.5.

This series changes:

- Two more PCI IDs for more supported PCIe bridge hardware
- Conversion of all printk() to more proper dev_*() based logging (the
  module_init rather uses pr_*() logging since there's no *dev available
  yet).
- Support for all available DuoFlex addon modules from that vendor. All
  addon modules are electrically compatible and use the same interface,
  and the addons work very well on the aging ngene hardware.
- Check for CXD2099AR addon modules before blindly trying to attach them,
  removing unnecessary and maybe irritating error logging if such module
  isn't present.
- Workaround a hardware quirk in conjunction with the CXD2099AR module,
  CA modules and CAM control communication, causing the TS input buffer
  to shift albeit different communication paths are ought to be in use.

This series is based on the CXD2099 regmap conversion series, see [1].
Especially [2] is required for the STV0367 enablement patch (and the
following ones) since the use of the TDA18212 I2C tuner client relies
on the i2c_client variable to be present, which is added in the
forementioned CXD2099 series.

Please pick this up and merge.

[1] https://www.spinics.net/lists/linux-media/msg129183.html
[2] https://www.spinics.net/lists/linux-media/msg129187.html

Changes since v1:
- TS buffer offset correction missed a check for the remaining buffer
  length before copying the next full 188-byte block, which might could
  have caused out-of-bound-reads from void *buf. Also, tsin_find_offset
  returns it's offset clamped to 188 byte boundaries to not accidentally
  skip over valid TS data. Few typos in the commit message were fixed
  and a note for the modparam was added, too.

Daniel Scheller (12):
  [media] ngene: add two additional PCI IDs
  [media] ngene: convert kernellog printing from printk() to dev_*()
    macros
  [media] ngene: use defines to identify the demod_type
  [media] ngene: support STV0367 DVB-C/T DuoFlex addons
  [media] ngene: add XO2 module support
  [media] ngene: add support for Sony CXD28xx-based DuoFlex modules
  [media] ngene: add support for DuoFlex S2 V4 addon modules
  [media] ngene: deduplicate I2C adapter evaluation
  [media] ngene: check for CXD2099AR presence before attaching
  [media] ngene: don't treat non-existing demods as error
  [media] ngene: move the tsin_exchange() stripcopy block into a
    function
  [media] ngene: compensate for TS buffer offset shifts

 drivers/media/pci/ngene/Kconfig       |   6 +
 drivers/media/pci/ngene/ngene-cards.c | 590 ++++++++++++++++++++++++++++++----
 drivers/media/pci/ngene/ngene-core.c  | 101 +++---
 drivers/media/pci/ngene/ngene-dvb.c   | 133 ++++++--
 drivers/media/pci/ngene/ngene.h       |  23 ++
 5 files changed, 732 insertions(+), 121 deletions(-)

-- 
2.16.1

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

* [PATCH v2 01/12] [media] ngene: add two additional PCI IDs
  2018-02-25 12:31 [PATCH v2 00/12] ngene-updates: Hardware support, TS buffer shift fix Daniel Scheller
@ 2018-02-25 12:31 ` Daniel Scheller
  2018-02-25 12:31 ` [PATCH v2 02/12] [media] ngene: convert kernellog printing from printk() to dev_*() macros Daniel Scheller
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Daniel Scheller @ 2018-02-25 12:31 UTC (permalink / raw)
  To: linux-media, mchehab, mchehab

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

Add two more device IDs for cards supported by the ngene driver.

Signed-off-by: Daniel Scheller <d.scheller@gmx.net>
---
 drivers/media/pci/ngene/ngene-cards.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/media/pci/ngene/ngene-cards.c b/drivers/media/pci/ngene/ngene-cards.c
index bb49620540c5..49f78bb31537 100644
--- a/drivers/media/pci/ngene/ngene-cards.c
+++ b/drivers/media/pci/ngene/ngene-cards.c
@@ -749,6 +749,8 @@ static const struct ngene_info ngene_info_terratec = {
 /****************************************************************************/
 
 static const struct pci_device_id ngene_id_tbl[] = {
+	NGENE_ID(0x18c3, 0xab04, ngene_info_cineS2),
+	NGENE_ID(0x18c3, 0xab05, ngene_info_cineS2v5),
 	NGENE_ID(0x18c3, 0xabc3, ngene_info_cineS2),
 	NGENE_ID(0x18c3, 0xabc4, ngene_info_cineS2),
 	NGENE_ID(0x18c3, 0xdb01, ngene_info_satixS2),
-- 
2.16.1

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

* [PATCH v2 02/12] [media] ngene: convert kernellog printing from printk() to dev_*() macros
  2018-02-25 12:31 [PATCH v2 00/12] ngene-updates: Hardware support, TS buffer shift fix Daniel Scheller
  2018-02-25 12:31 ` [PATCH v2 01/12] [media] ngene: add two additional PCI IDs Daniel Scheller
@ 2018-02-25 12:31 ` Daniel Scheller
  2018-02-25 12:31 ` [PATCH v2 03/12] [media] ngene: use defines to identify the demod_type Daniel Scheller
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Daniel Scheller @ 2018-02-25 12:31 UTC (permalink / raw)
  To: linux-media, mchehab, mchehab

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

Convert all printk() and pr_*() kernel log printing to rather use the
dev_*() macros. Not only is it discouraged to use printk() (checkpatch
even complains about that), but also this helps identifying the exact PCI
device for any printed event, and it makes almost all printing shorter
in terms of code style since there's no need to use KERN_* DEVICE_NAME
any more (dev_*() will take care of this).

Since the dprintk macro define isn't used anymore, remove it.

Signed-off-by: Daniel Scheller <d.scheller@gmx.net>
---
 drivers/media/pci/ngene/ngene-cards.c | 75 ++++++++++++++++++++---------------
 drivers/media/pci/ngene/ngene-core.c  | 75 +++++++++++++++++------------------
 drivers/media/pci/ngene/ngene-dvb.c   |  4 +-
 3 files changed, 84 insertions(+), 70 deletions(-)

diff --git a/drivers/media/pci/ngene/ngene-cards.c b/drivers/media/pci/ngene/ngene-cards.c
index 49f78bb31537..16666de8cbee 100644
--- a/drivers/media/pci/ngene/ngene-cards.c
+++ b/drivers/media/pci/ngene/ngene-cards.c
@@ -23,6 +23,8 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/pci.h>
@@ -48,6 +50,7 @@
 
 static int tuner_attach_stv6110(struct ngene_channel *chan)
 {
+	struct device *pdev = &chan->dev->pci_dev->dev;
 	struct i2c_adapter *i2c;
 	struct stv090x_config *feconf = (struct stv090x_config *)
 		chan->dev->card_info->fe_config[chan->number];
@@ -63,7 +66,7 @@ static int tuner_attach_stv6110(struct ngene_channel *chan)
 
 	ctl = dvb_attach(stv6110x_attach, chan->fe, tunerconf, i2c);
 	if (ctl == NULL) {
-		printk(KERN_ERR	DEVICE_NAME ": No STV6110X found!\n");
+		dev_err(pdev, "No STV6110X found!\n");
 		return -ENODEV;
 	}
 
@@ -100,6 +103,7 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
 
 static int tuner_attach_tda18271(struct ngene_channel *chan)
 {
+	struct device *pdev = &chan->dev->pci_dev->dev;
 	struct i2c_adapter *i2c;
 	struct dvb_frontend *fe;
 
@@ -110,7 +114,7 @@ static int tuner_attach_tda18271(struct ngene_channel *chan)
 	if (chan->fe->ops.i2c_gate_ctrl)
 		chan->fe->ops.i2c_gate_ctrl(chan->fe, 0);
 	if (!fe) {
-		printk(KERN_ERR "No TDA18271 found!\n");
+		dev_err(pdev, "No TDA18271 found!\n");
 		return -ENODEV;
 	}
 
@@ -128,6 +132,7 @@ static int tuner_attach_probe(struct ngene_channel *chan)
 
 static int demod_attach_stv0900(struct ngene_channel *chan)
 {
+	struct device *pdev = &chan->dev->pci_dev->dev;
 	struct i2c_adapter *i2c;
 	struct stv090x_config *feconf = (struct stv090x_config *)
 		chan->dev->card_info->fe_config[chan->number];
@@ -144,7 +149,7 @@ static int demod_attach_stv0900(struct ngene_channel *chan)
 			(chan->number & 1) == 0 ? STV090x_DEMODULATOR_0
 						: STV090x_DEMODULATOR_1);
 	if (chan->fe == NULL) {
-		printk(KERN_ERR	DEVICE_NAME ": No STV0900 found!\n");
+		dev_err(pdev, "No STV0900 found!\n");
 		return -ENODEV;
 	}
 
@@ -154,7 +159,7 @@ static int demod_attach_stv0900(struct ngene_channel *chan)
 
 	if (!dvb_attach(lnbh24_attach, chan->fe, i2c, 0,
 			0, chan->dev->card_info->lnb[chan->number])) {
-		printk(KERN_ERR DEVICE_NAME ": No LNBH24 found!\n");
+		dev_err(pdev, "No LNBH24 found!\n");
 		dvb_frontend_detach(chan->fe);
 		chan->fe = NULL;
 		return -ENODEV;
@@ -211,6 +216,7 @@ static int port_has_drxk(struct i2c_adapter *i2c, int port)
 static int demod_attach_drxk(struct ngene_channel *chan,
 			     struct i2c_adapter *i2c)
 {
+	struct device *pdev = &chan->dev->pci_dev->dev;
 	struct drxk_config config;
 
 	memset(&config, 0, sizeof(config));
@@ -220,7 +226,7 @@ static int demod_attach_drxk(struct ngene_channel *chan,
 
 	chan->fe = dvb_attach(drxk_attach, &config, i2c);
 	if (!chan->fe) {
-		printk(KERN_ERR "No DRXK found!\n");
+		dev_err(pdev, "No DRXK found!\n");
 		return -ENODEV;
 	}
 	chan->fe->sec_priv = chan;
@@ -231,6 +237,7 @@ static int demod_attach_drxk(struct ngene_channel *chan,
 
 static int cineS2_probe(struct ngene_channel *chan)
 {
+	struct device *pdev = &chan->dev->pci_dev->dev;
 	struct i2c_adapter *i2c;
 	struct stv090x_config *fe_conf;
 	u8 buf[3];
@@ -269,14 +276,14 @@ static int cineS2_probe(struct ngene_channel *chan)
 		}
 		rc = i2c_transfer(i2c, &i2c_msg, 1);
 		if (rc != 1) {
-			printk(KERN_ERR DEVICE_NAME ": could not setup DPNx\n");
+			dev_err(pdev, "Could not setup DPNx\n");
 			return -EIO;
 		}
 	} else if (port_has_drxk(i2c, chan->number^2)) {
 		chan->demod_type = 1;
 		demod_attach_drxk(chan, i2c);
 	} else {
-		printk(KERN_ERR "No demod found on chan %d\n", chan->number);
+		dev_err(pdev, "No demod found on chan %d\n", chan->number);
 		return -ENODEV;
 	}
 	return 0;
@@ -299,9 +306,11 @@ static struct mt2131_config m780_tunerconfig = {
  */
 static int demod_attach_lg330x(struct ngene_channel *chan)
 {
+	struct device *pdev = &chan->dev->pci_dev->dev;
+
 	chan->fe = dvb_attach(lgdt330x_attach, &aver_m780, &chan->i2c_adapter);
 	if (chan->fe == NULL) {
-		printk(KERN_ERR	DEVICE_NAME ": No LGDT330x found!\n");
+		dev_err(pdev, "No LGDT330x found!\n");
 		return -ENODEV;
 	}
 
@@ -313,6 +322,7 @@ static int demod_attach_lg330x(struct ngene_channel *chan)
 
 static int demod_attach_drxd(struct ngene_channel *chan)
 {
+	struct device *pdev = &chan->dev->pci_dev->dev;
 	struct drxd_config *feconf;
 
 	feconf = chan->dev->card_info->fe_config[chan->number];
@@ -320,7 +330,7 @@ static int demod_attach_drxd(struct ngene_channel *chan)
 	chan->fe = dvb_attach(drxd_attach, feconf, chan,
 			&chan->i2c_adapter, &chan->dev->pci_dev->dev);
 	if (!chan->fe) {
-		pr_err("No DRXD found!\n");
+		dev_err(pdev, "No DRXD found!\n");
 		return -ENODEV;
 	}
 	return 0;
@@ -328,6 +338,7 @@ static int demod_attach_drxd(struct ngene_channel *chan)
 
 static int tuner_attach_dtt7520x(struct ngene_channel *chan)
 {
+	struct device *pdev = &chan->dev->pci_dev->dev;
 	struct drxd_config *feconf;
 
 	feconf = chan->dev->card_info->fe_config[chan->number];
@@ -335,7 +346,7 @@ static int tuner_attach_dtt7520x(struct ngene_channel *chan)
 	if (!dvb_attach(dvb_pll_attach, chan->fe, feconf->pll_address,
 			&chan->i2c_adapter,
 			feconf->pll_type)) {
-		pr_err("No pll(%d) found!\n", feconf->pll_type);
+		dev_err(pdev, "No pll(%d) found!\n", feconf->pll_type);
 		return -ENODEV;
 	}
 	return 0;
@@ -371,12 +382,13 @@ static int tuner_attach_dtt7520x(struct ngene_channel *chan)
 static int i2c_write_eeprom(struct i2c_adapter *adapter,
 			    u8 adr, u16 reg, u8 data)
 {
+	struct device *pdev = adapter->dev.parent;
 	u8 m[3] = {(reg >> 8), (reg & 0xff), data};
 	struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m,
 			      .len = sizeof(m)};
 
 	if (i2c_transfer(adapter, &msg, 1) != 1) {
-		pr_err(DEVICE_NAME ": Error writing EEPROM!\n");
+		dev_err(pdev, "Error writing EEPROM!\n");
 		return -EIO;
 	}
 	return 0;
@@ -385,6 +397,7 @@ static int i2c_write_eeprom(struct i2c_adapter *adapter,
 static int i2c_read_eeprom(struct i2c_adapter *adapter,
 			   u8 adr, u16 reg, u8 *data, int len)
 {
+	struct device *pdev = adapter->dev.parent;
 	u8 msg[2] = {(reg >> 8), (reg & 0xff)};
 	struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
 				   .buf = msg, .len = 2 },
@@ -392,7 +405,7 @@ static int i2c_read_eeprom(struct i2c_adapter *adapter,
 				   .buf = data, .len = len} };
 
 	if (i2c_transfer(adapter, msgs, 2) != 2) {
-		pr_err(DEVICE_NAME ": Error reading EEPROM\n");
+		dev_err(pdev, "Error reading EEPROM\n");
 		return -EIO;
 	}
 	return 0;
@@ -401,6 +414,7 @@ static int i2c_read_eeprom(struct i2c_adapter *adapter,
 static int ReadEEProm(struct i2c_adapter *adapter,
 		      u16 Tag, u32 MaxLen, u8 *data, u32 *pLength)
 {
+	struct device *pdev = adapter->dev.parent;
 	int status = 0;
 	u16 Addr = MICNG_EE_START, Length, tag = 0;
 	u8  EETag[3];
@@ -416,9 +430,8 @@ static int ReadEEProm(struct i2c_adapter *adapter,
 		Addr += sizeof(u16) + 1 + EETag[2];
 	}
 	if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) {
-		pr_err(DEVICE_NAME
-		       ": Reached EOEE @ Tag = %04x Length = %3d\n",
-		       tag, EETag[2]);
+		dev_err(pdev, "Reached EOEE @ Tag = %04x Length = %3d\n",
+			tag, EETag[2]);
 		return -1;
 	}
 	Length = EETag[2];
@@ -441,6 +454,7 @@ static int ReadEEProm(struct i2c_adapter *adapter,
 static int WriteEEProm(struct i2c_adapter *adapter,
 		       u16 Tag, u32 Length, u8 *data)
 {
+	struct device *pdev = adapter->dev.parent;
 	int status = 0;
 	u16 Addr = MICNG_EE_START;
 	u8 EETag[3];
@@ -458,9 +472,8 @@ static int WriteEEProm(struct i2c_adapter *adapter,
 		Addr += sizeof(u16) + 1 + EETag[2];
 	}
 	if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) {
-		pr_err(DEVICE_NAME
-		       ": Reached EOEE @ Tag = %04x Length = %3d\n",
-		       tag, EETag[2]);
+		dev_err(pdev, "Reached EOEE @ Tag = %04x Length = %3d\n",
+			tag, EETag[2]);
 		return -1;
 	}
 
@@ -487,13 +500,11 @@ static int WriteEEProm(struct i2c_adapter *adapter,
 			if (status)
 				break;
 			if (Tmp != data[i])
-				pr_err(DEVICE_NAME
-				       "eeprom write error\n");
+				dev_err(pdev, "eeprom write error\n");
 			retry -= 1;
 		}
 		if (status) {
-			pr_err(DEVICE_NAME
-			       ": Timeout polling eeprom\n");
+			dev_err(pdev, "Timeout polling eeprom\n");
 			break;
 		}
 	}
@@ -532,19 +543,20 @@ static int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag, u16 data)
 static s16 osc_deviation(void *priv, s16 deviation, int flag)
 {
 	struct ngene_channel *chan = priv;
+	struct device *pdev = &chan->dev->pci_dev->dev;
 	struct i2c_adapter *adap = &chan->i2c_adapter;
 	u16 data = 0;
 
 	if (flag) {
 		data = (u16) deviation;
-		pr_info(DEVICE_NAME ": write deviation %d\n",
-		       deviation);
+		dev_info(pdev, "write deviation %d\n",
+			 deviation);
 		eeprom_write_ushort(adap, 0x1000 + chan->number, data);
 	} else {
 		if (eeprom_read_ushort(adap, 0x1000 + chan->number, &data))
 			data = 0;
-		pr_info(DEVICE_NAME ": read deviation %d\n",
-		       (s16) data);
+		dev_info(pdev, "read deviation %d\n",
+			 (s16)data);
 	}
 
 	return (s16) data;
@@ -771,7 +783,7 @@ MODULE_DEVICE_TABLE(pci, ngene_id_tbl);
 static pci_ers_result_t ngene_error_detected(struct pci_dev *dev,
 					     enum pci_channel_state state)
 {
-	printk(KERN_ERR DEVICE_NAME ": PCI error\n");
+	dev_err(&dev->dev, "PCI error\n");
 	if (state == pci_channel_io_perm_failure)
 		return PCI_ERS_RESULT_DISCONNECT;
 	if (state == pci_channel_io_frozen)
@@ -781,13 +793,13 @@ static pci_ers_result_t ngene_error_detected(struct pci_dev *dev,
 
 static pci_ers_result_t ngene_slot_reset(struct pci_dev *dev)
 {
-	printk(KERN_INFO DEVICE_NAME ": slot reset\n");
+	dev_info(&dev->dev, "slot reset\n");
 	return 0;
 }
 
 static void ngene_resume(struct pci_dev *dev)
 {
-	printk(KERN_INFO DEVICE_NAME ": resume\n");
+	dev_info(&dev->dev, "resume\n");
 }
 
 static const struct pci_error_handlers ngene_errors = {
@@ -807,8 +819,9 @@ static struct pci_driver ngene_pci_driver = {
 
 static __init int module_init_ngene(void)
 {
-	printk(KERN_INFO
-	       "nGene PCIE bridge driver, Copyright (C) 2005-2007 Micronas\n");
+	/* pr_*() since we don't have a device to use with dev_*() yet */
+	pr_info("nGene PCIE bridge driver, Copyright (C) 2005-2007 Micronas\n");
+
 	return pci_register_driver(&ngene_pci_driver);
 }
 
diff --git a/drivers/media/pci/ngene/ngene-core.c b/drivers/media/pci/ngene/ngene-core.c
index 80db777cb7ec..a63f019fb62f 100644
--- a/drivers/media/pci/ngene/ngene-core.c
+++ b/drivers/media/pci/ngene/ngene-core.c
@@ -51,8 +51,6 @@ MODULE_PARM_DESC(debug, "Print debugging information.");
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
-#define dprintk	if (debug) printk
-
 #define ngwriteb(dat, adr)         writeb((dat), dev->iomem + (adr))
 #define ngwritel(dat, adr)         writel((dat), dev->iomem + (adr))
 #define ngwriteb(dat, adr)         writeb((dat), dev->iomem + (adr))
@@ -86,6 +84,7 @@ static void event_tasklet(unsigned long data)
 static void demux_tasklet(unsigned long data)
 {
 	struct ngene_channel *chan = (struct ngene_channel *)data;
+	struct device *pdev = &chan->dev->pci_dev->dev;
 	struct SBufferHeader *Cur = chan->nextBuffer;
 
 	spin_lock_irq(&chan->state_lock);
@@ -124,16 +123,15 @@ static void demux_tasklet(unsigned long data)
 					chan->HWState = HWSTATE_RUN;
 				}
 			} else {
-				printk(KERN_ERR DEVICE_NAME ": OOPS\n");
+				dev_err(pdev, "OOPS\n");
 				if (chan->HWState == HWSTATE_RUN) {
 					Cur->ngeneBuffer.SR.Flags &= ~0x40;
 					break;	/* Stop processing stream */
 				}
 			}
 			if (chan->AudioDTOUpdated) {
-				printk(KERN_INFO DEVICE_NAME
-				       ": Update AudioDTO = %d\n",
-				       chan->AudioDTOValue);
+				dev_info(pdev, "Update AudioDTO = %d\n",
+					 chan->AudioDTOValue);
 				Cur->ngeneBuffer.SR.DTOUpdate =
 					chan->AudioDTOValue;
 				chan->AudioDTOUpdated = 0;
@@ -173,6 +171,7 @@ static void demux_tasklet(unsigned long data)
 static irqreturn_t irq_handler(int irq, void *dev_id)
 {
 	struct ngene *dev = (struct ngene *)dev_id;
+	struct device *pdev = &dev->pci_dev->dev;
 	u32 icounts = 0;
 	irqreturn_t rc = IRQ_NONE;
 	u32 i = MAX_STREAM;
@@ -213,7 +212,7 @@ static irqreturn_t irq_handler(int irq, void *dev_id)
 				*(dev->EventBuffer);
 			dev->EventQueueWriteIndex = nextWriteIndex;
 		} else {
-			printk(KERN_ERR DEVICE_NAME ": event overflow\n");
+			dev_err(pdev, "event overflow\n");
 			dev->EventQueueOverflowCount += 1;
 			dev->EventQueueOverflowFlag = 1;
 		}
@@ -249,23 +248,25 @@ static irqreturn_t irq_handler(int irq, void *dev_id)
 
 static void dump_command_io(struct ngene *dev)
 {
+	struct device *pdev = &dev->pci_dev->dev;
 	u8 buf[8], *b;
 
 	ngcpyfrom(buf, HOST_TO_NGENE, 8);
-	printk(KERN_ERR "host_to_ngene (%04x): %*ph\n", HOST_TO_NGENE, 8, buf);
+	dev_err(pdev, "host_to_ngene (%04x): %*ph\n", HOST_TO_NGENE, 8, buf);
 
 	ngcpyfrom(buf, NGENE_TO_HOST, 8);
-	printk(KERN_ERR "ngene_to_host (%04x): %*ph\n", NGENE_TO_HOST, 8, buf);
+	dev_err(pdev, "ngene_to_host (%04x): %*ph\n", NGENE_TO_HOST, 8, buf);
 
 	b = dev->hosttongene;
-	printk(KERN_ERR "dev->hosttongene (%p): %*ph\n", b, 8, b);
+	dev_err(pdev, "dev->hosttongene (%p): %*ph\n", b, 8, b);
 
 	b = dev->ngenetohost;
-	printk(KERN_ERR "dev->ngenetohost (%p): %*ph\n", b, 8, b);
+	dev_err(pdev, "dev->ngenetohost (%p): %*ph\n", b, 8, b);
 }
 
 static int ngene_command_mutex(struct ngene *dev, struct ngene_command *com)
 {
+	struct device *pdev = &dev->pci_dev->dev;
 	int ret;
 	u8 *tmpCmdDoneByte;
 
@@ -313,9 +314,8 @@ static int ngene_command_mutex(struct ngene *dev, struct ngene_command *com)
 	if (!ret) {
 		/*ngwritel(0, FORCE_NMI);*/
 
-		printk(KERN_ERR DEVICE_NAME
-		       ": Command timeout cmd=%02x prev=%02x\n",
-		       com->cmd.hdr.Opcode, dev->prev_cmd);
+		dev_err(pdev, "Command timeout cmd=%02x prev=%02x\n",
+			com->cmd.hdr.Opcode, dev->prev_cmd);
 		dump_command_io(dev);
 		return -1;
 	}
@@ -553,6 +553,7 @@ static void clear_buffers(struct ngene_channel *chan)
 static int ngene_command_stream_control(struct ngene *dev, u8 stream,
 					u8 control, u8 mode, u8 flags)
 {
+	struct device *pdev = &dev->pci_dev->dev;
 	struct ngene_channel *chan = &dev->channel[stream];
 	struct ngene_command com;
 	u16 BsUVI = ((stream & 1) ? 0x9400 : 0x9300);
@@ -572,8 +573,7 @@ static int ngene_command_stream_control(struct ngene *dev, u8 stream,
 	com.in_len = sizeof(struct FW_STREAM_CONTROL);
 	com.out_len = 0;
 
-	dprintk(KERN_INFO DEVICE_NAME
-		": Stream=%02x, Control=%02x, Mode=%02x\n",
+	dev_dbg(pdev, "Stream=%02x, Control=%02x, Mode=%02x\n",
 		com.cmd.StreamControl.Stream, com.cmd.StreamControl.Control,
 		com.cmd.StreamControl.Mode);
 
@@ -695,23 +695,24 @@ static int ngene_command_stream_control(struct ngene *dev, u8 stream,
 
 void set_transfer(struct ngene_channel *chan, int state)
 {
+	struct device *pdev = &chan->dev->pci_dev->dev;
 	u8 control = 0, mode = 0, flags = 0;
 	struct ngene *dev = chan->dev;
 	int ret;
 
 	/*
-	printk(KERN_INFO DEVICE_NAME ": st %d\n", state);
+	dev_info(pdev, "st %d\n", state);
 	msleep(100);
 	*/
 
 	if (state) {
 		if (chan->running) {
-			printk(KERN_INFO DEVICE_NAME ": already running\n");
+			dev_info(pdev, "already running\n");
 			return;
 		}
 	} else {
 		if (!chan->running) {
-			printk(KERN_INFO DEVICE_NAME ": already stopped\n");
+			dev_info(pdev, "already stopped\n");
 			return;
 		}
 	}
@@ -722,7 +723,7 @@ void set_transfer(struct ngene_channel *chan, int state)
 	if (state) {
 		spin_lock_irq(&chan->state_lock);
 
-		/* printk(KERN_INFO DEVICE_NAME ": lock=%08x\n",
+		/* dev_info(pdev, "lock=%08x\n",
 			  ngreadl(0x9310)); */
 		dvb_ringbuffer_flush(&dev->tsout_rbuf);
 		control = 0x80;
@@ -740,7 +741,7 @@ void set_transfer(struct ngene_channel *chan, int state)
 			chan->pBufferExchange = tsin_exchange;
 		spin_unlock_irq(&chan->state_lock);
 	}
-		/* else printk(KERN_INFO DEVICE_NAME ": lock=%08x\n",
+		/* else dev_info(pdev, "lock=%08x\n",
 			   ngreadl(0x9310)); */
 
 	mutex_lock(&dev->stream_mutex);
@@ -751,8 +752,7 @@ void set_transfer(struct ngene_channel *chan, int state)
 	if (!ret)
 		chan->running = state;
 	else
-		printk(KERN_ERR DEVICE_NAME ": set_transfer %d failed\n",
-		       state);
+		dev_err(pdev, "%s %d failed\n", __func__, state);
 	if (!state) {
 		spin_lock_irq(&chan->state_lock);
 		chan->pBufferExchange = NULL;
@@ -1195,6 +1195,7 @@ static int ngene_get_buffers(struct ngene *dev)
 
 static void ngene_init(struct ngene *dev)
 {
+	struct device *pdev = &dev->pci_dev->dev;
 	int i;
 
 	tasklet_init(&dev->event_tasklet, event_tasklet, (unsigned long)dev);
@@ -1214,12 +1215,12 @@ static void ngene_init(struct ngene *dev)
 	dev->icounts = ngreadl(NGENE_INT_COUNTS);
 
 	dev->device_version = ngreadl(DEV_VER) & 0x0f;
-	printk(KERN_INFO DEVICE_NAME ": Device version %d\n",
-	       dev->device_version);
+	dev_info(pdev, "Device version %d\n", dev->device_version);
 }
 
 static int ngene_load_firm(struct ngene *dev)
 {
+	struct device *pdev = &dev->pci_dev->dev;
 	u32 size;
 	const struct firmware *fw = NULL;
 	u8 *ngene_fw;
@@ -1253,21 +1254,18 @@ static int ngene_load_firm(struct ngene *dev)
 	}
 
 	if (request_firmware(&fw, fw_name, &dev->pci_dev->dev) < 0) {
-		printk(KERN_ERR DEVICE_NAME
-			": Could not load firmware file %s.\n", fw_name);
-		printk(KERN_INFO DEVICE_NAME
-			": Copy %s to your hotplug directory!\n", fw_name);
+		dev_err(pdev, "Could not load firmware file %s.\n", fw_name);
+		dev_info(pdev, "Copy %s to your hotplug directory!\n",
+			 fw_name);
 		return -1;
 	}
 	if (size == 0)
 		size = fw->size;
 	if (size != fw->size) {
-		printk(KERN_ERR DEVICE_NAME
-			": Firmware %s has invalid size!", fw_name);
+		dev_err(pdev, "Firmware %s has invalid size!", fw_name);
 		err = -1;
 	} else {
-		printk(KERN_INFO DEVICE_NAME
-			": Loading firmware file %s.\n", fw_name);
+		dev_info(pdev, "Loading firmware file %s.\n", fw_name);
 		ngene_fw = (u8 *) fw->data;
 		err = ngene_command_load_firmware(dev, ngene_fw, size);
 	}
@@ -1327,6 +1325,7 @@ static int ngene_buffer_config(struct ngene *dev)
 
 static int ngene_start(struct ngene *dev)
 {
+	struct device *pdev = &dev->pci_dev->dev;
 	int stat;
 	int i;
 
@@ -1366,8 +1365,7 @@ static int ngene_start(struct ngene *dev)
 		free_irq(dev->pci_dev->irq, dev);
 		stat = pci_enable_msi(dev->pci_dev);
 		if (stat) {
-			printk(KERN_INFO DEVICE_NAME
-				": MSI not available\n");
+			dev_info(pdev, "MSI not available\n");
 			flags = IRQF_SHARED;
 		} else {
 			flags = 0;
@@ -1570,6 +1568,7 @@ static const struct cxd2099_cfg cxd_cfgtmpl = {
 
 static void cxd_attach(struct ngene *dev)
 {
+	struct device *pdev = &dev->pci_dev->dev;
 	struct ngene_ci *ci = &dev->ci;
 	struct cxd2099_cfg cxd_cfg = cxd_cfgtmpl;
 	struct i2c_client *client;
@@ -1600,7 +1599,7 @@ static void cxd_attach(struct ngene *dev)
 err_i2c:
 	i2c_unregister_device(client);
 err_ret:
-	printk(KERN_ERR DEVICE_NAME ": CXD2099AR attach failed\n");
+	dev_err(pdev, "CXD2099AR attach failed\n");
 	return;
 }
 
@@ -1648,7 +1647,7 @@ void ngene_shutdown(struct pci_dev *pdev)
 	if (!dev || !shutdown_workaround)
 		return;
 
-	printk(KERN_INFO DEVICE_NAME ": shutdown workaround...\n");
+	dev_info(&pdev->dev, "shutdown workaround...\n");
 	ngene_unlink(dev);
 	pci_disable_device(pdev);
 }
@@ -1688,7 +1687,7 @@ int ngene_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 
 	dev->pci_dev = pci_dev;
 	dev->card_info = (struct ngene_info *)id->driver_data;
-	printk(KERN_INFO DEVICE_NAME ": Found %s\n", dev->card_info->name);
+	dev_info(&pci_dev->dev, "Found %s\n", dev->card_info->name);
 
 	pci_set_drvdata(pci_dev, dev);
 
diff --git a/drivers/media/pci/ngene/ngene-dvb.c b/drivers/media/pci/ngene/ngene-dvb.c
index 03fc218a45e9..f71fd41c762c 100644
--- a/drivers/media/pci/ngene/ngene-dvb.c
+++ b/drivers/media/pci/ngene/ngene-dvb.c
@@ -152,7 +152,9 @@ void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
 				stripped++;
 
 			if (ok % 100 == 0 && overflow)
-				printk(KERN_WARNING "%s: ok %u overflow %u dropped %u\n", __func__, ok, overflow, stripped);
+				dev_warn(&dev->pci_dev->dev,
+					 "%s: ok %u overflow %u dropped %u\n",
+					 __func__, ok, overflow, stripped);
 #endif
 			buf += 188;
 			len -= 188;
-- 
2.16.1

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

* [PATCH v2 03/12] [media] ngene: use defines to identify the demod_type
  2018-02-25 12:31 [PATCH v2 00/12] ngene-updates: Hardware support, TS buffer shift fix Daniel Scheller
  2018-02-25 12:31 ` [PATCH v2 01/12] [media] ngene: add two additional PCI IDs Daniel Scheller
  2018-02-25 12:31 ` [PATCH v2 02/12] [media] ngene: convert kernellog printing from printk() to dev_*() macros Daniel Scheller
@ 2018-02-25 12:31 ` Daniel Scheller
  2018-02-25 12:31 ` [PATCH v2 04/12] [media] ngene: support STV0367 DVB-C/T DuoFlex addons Daniel Scheller
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Daniel Scheller @ 2018-02-25 12:31 UTC (permalink / raw)
  To: linux-media, mchehab, mchehab

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

Make it more clear which demod_type is used for which hardware by having
defines for the possible demod_type values. With that, change the
demod_type evaluation in tuner_attach_probe() to a switch-case instead
of an if() for each possible value.

Signed-off-by: Daniel Scheller <d.scheller@gmx.net>
---
 drivers/media/pci/ngene/ngene-cards.c | 11 +++++++----
 drivers/media/pci/ngene/ngene.h       |  3 +++
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/media/pci/ngene/ngene-cards.c b/drivers/media/pci/ngene/ngene-cards.c
index 16666de8cbee..065b83ee569b 100644
--- a/drivers/media/pci/ngene/ngene-cards.c
+++ b/drivers/media/pci/ngene/ngene-cards.c
@@ -123,10 +123,13 @@ static int tuner_attach_tda18271(struct ngene_channel *chan)
 
 static int tuner_attach_probe(struct ngene_channel *chan)
 {
-	if (chan->demod_type == 0)
+	switch (chan->demod_type) {
+	case DEMOD_TYPE_STV090X:
 		return tuner_attach_stv6110(chan);
-	if (chan->demod_type == 1)
+	case DEMOD_TYPE_DRXK:
 		return tuner_attach_tda18271(chan);
+	}
+
 	return -EINVAL;
 }
 
@@ -251,7 +254,7 @@ static int cineS2_probe(struct ngene_channel *chan)
 		i2c = &chan->dev->channel[1].i2c_adapter;
 
 	if (port_has_stv0900(i2c, chan->number)) {
-		chan->demod_type = 0;
+		chan->demod_type = DEMOD_TYPE_STV090X;
 		fe_conf = chan->dev->card_info->fe_config[chan->number];
 		/* demod found, attach it */
 		rc = demod_attach_stv0900(chan);
@@ -280,7 +283,7 @@ static int cineS2_probe(struct ngene_channel *chan)
 			return -EIO;
 		}
 	} else if (port_has_drxk(i2c, chan->number^2)) {
-		chan->demod_type = 1;
+		chan->demod_type = DEMOD_TYPE_DRXK;
 		demod_attach_drxk(chan, i2c);
 	} else {
 		dev_err(pdev, "No demod found on chan %d\n", chan->number);
diff --git a/drivers/media/pci/ngene/ngene.h b/drivers/media/pci/ngene/ngene.h
index caf8602c7459..9724701a3274 100644
--- a/drivers/media/pci/ngene/ngene.h
+++ b/drivers/media/pci/ngene/ngene.h
@@ -51,6 +51,9 @@
 #define VIDEO_CAP_MPEG4 512
 #endif
 
+#define DEMOD_TYPE_STV090X	0
+#define DEMOD_TYPE_DRXK		1
+
 enum STREAM {
 	STREAM_VIDEOIN1 = 0,        /* ITU656 or TS Input */
 	STREAM_VIDEOIN2,
-- 
2.16.1

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

* [PATCH v2 04/12] [media] ngene: support STV0367 DVB-C/T DuoFlex addons
  2018-02-25 12:31 [PATCH v2 00/12] ngene-updates: Hardware support, TS buffer shift fix Daniel Scheller
                   ` (2 preceding siblings ...)
  2018-02-25 12:31 ` [PATCH v2 03/12] [media] ngene: use defines to identify the demod_type Daniel Scheller
@ 2018-02-25 12:31 ` Daniel Scheller
  2018-02-25 12:31 ` [PATCH v2 05/12] [media] ngene: add XO2 module support Daniel Scheller
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Daniel Scheller @ 2018-02-25 12:31 UTC (permalink / raw)
  To: linux-media, mchehab, mchehab

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

Add support for STV0367+TDA18212 based DuoFlex CT addon modules. For this,
add a demod probe function and all necessary demod/tuner attach functions
which use existing auxiliary drivers (stv0367 and tda18212) to support
this hardware. As tda18212 is an I2C client driver, proper cleanup code
is added to the deregistration sequence in ngene-core. To not cause use-
after-free situations when there's a CXD2099 I2C client connected, which
is rather freed in ngene-core.c:cxd_detach(), add i2c_client_fe to struct
ngene_channel to keep track if the i2c_client was allocated by a frontend
driver, rather than the CI code paths. Also move the I2C access functions
to the top of the file and add the required read_regs() function for the
tda18212 ping to work.

This adds autoselection (if MEDIA_SUBDRV_AUTOSELECT) of the STV0367 demod
driver and TDA18212 tuner driver to Kconfig aswell.

Signed-off-by: Daniel Scheller <d.scheller@gmx.net>
---
 drivers/media/pci/ngene/Kconfig       |   2 +
 drivers/media/pci/ngene/ngene-cards.c | 194 ++++++++++++++++++++++++++++++----
 drivers/media/pci/ngene/ngene-core.c  |  12 +++
 drivers/media/pci/ngene/ngene.h       |   2 +
 4 files changed, 191 insertions(+), 19 deletions(-)

diff --git a/drivers/media/pci/ngene/Kconfig b/drivers/media/pci/ngene/Kconfig
index 390ed75fe438..c3254f9dc8ad 100644
--- a/drivers/media/pci/ngene/Kconfig
+++ b/drivers/media/pci/ngene/Kconfig
@@ -8,6 +8,8 @@ config DVB_NGENE
 	select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT
 	select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STV0367 if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_TDA18212 if MEDIA_SUBDRV_AUTOSELECT
 	select DVB_CXD2099 if MEDIA_SUBDRV_AUTOSELECT
 	---help---
 	  Support for Micronas PCI express cards with nGene bridge.
diff --git a/drivers/media/pci/ngene/ngene-cards.c b/drivers/media/pci/ngene/ngene-cards.c
index 065b83ee569b..7ec5f68b1ec7 100644
--- a/drivers/media/pci/ngene/ngene-cards.c
+++ b/drivers/media/pci/ngene/ngene-cards.c
@@ -42,8 +42,42 @@
 #include "drxk.h"
 #include "drxd.h"
 #include "dvb-pll.h"
+#include "stv0367.h"
+#include "stv0367_priv.h"
+#include "tda18212.h"
 
+/****************************************************************************/
+/* I2C transfer functions used for demod/tuner probing***********************/
+/****************************************************************************/
+
+static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
+{
+	struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
+				   .buf  = val,  .len   = 1 } };
+	return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
+}
+
+static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
+			  u16 reg, u8 *val)
+{
+	u8 msg[2] = {reg >> 8, reg & 0xff};
+	struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
+				   .buf  = msg, .len   = 2},
+				  {.addr = adr, .flags = I2C_M_RD,
+				   .buf  = val, .len   = 1} };
+	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
+}
 
+static int i2c_read_regs(struct i2c_adapter *adapter,
+			 u8 adr, u8 reg, u8 *val, u8 len)
+{
+	struct i2c_msg msgs[2] = {{.addr = adr,  .flags = 0,
+				   .buf  = &reg, .len   = 1},
+				  {.addr = adr,  .flags = I2C_M_RD,
+				   .buf  = val,  .len   = len} };
+
+	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
+}
 /****************************************************************************/
 /* Demod/tuner attachment ***************************************************/
 /****************************************************************************/
@@ -85,7 +119,6 @@ static int tuner_attach_stv6110(struct ngene_channel *chan)
 	return 0;
 }
 
-
 static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
 {
 	struct ngene_channel *chan = fe->sec_priv;
@@ -121,6 +154,89 @@ static int tuner_attach_tda18271(struct ngene_channel *chan)
 	return 0;
 }
 
+static int tuner_tda18212_ping(struct ngene_channel *chan,
+			       struct i2c_adapter *i2c,
+			       unsigned short adr)
+{
+	struct device *pdev = &chan->dev->pci_dev->dev;
+	u8 tda_id[2];
+	u8 subaddr = 0x00;
+
+	dev_dbg(pdev, "stv0367-tda18212 tuner ping\n");
+	if (chan->fe->ops.i2c_gate_ctrl)
+		chan->fe->ops.i2c_gate_ctrl(chan->fe, 1);
+
+	if (i2c_read_regs(i2c, adr, subaddr, tda_id, sizeof(tda_id)) < 0)
+		dev_dbg(pdev, "tda18212 ping 1 fail\n");
+	if (i2c_read_regs(i2c, adr, subaddr, tda_id, sizeof(tda_id)) < 0)
+		dev_warn(pdev, "tda18212 ping failed, expect problems\n");
+
+	if (chan->fe->ops.i2c_gate_ctrl)
+		chan->fe->ops.i2c_gate_ctrl(chan->fe, 0);
+
+	return 0;
+}
+
+static int tuner_attach_tda18212(struct ngene_channel *chan, u32 dmdtype)
+{
+	struct device *pdev = &chan->dev->pci_dev->dev;
+	struct i2c_adapter *i2c;
+	struct i2c_client *client;
+	struct tda18212_config config = {
+		.fe = chan->fe,
+		.if_dvbt_6 = 3550,
+		.if_dvbt_7 = 3700,
+		.if_dvbt_8 = 4150,
+		.if_dvbt2_6 = 3250,
+		.if_dvbt2_7 = 4000,
+		.if_dvbt2_8 = 4000,
+		.if_dvbc = 5000,
+	};
+	struct i2c_board_info board_info = {
+		.type = "tda18212",
+		.platform_data = &config,
+	};
+
+	if (chan->number & 1)
+		board_info.addr = 0x63;
+	else
+		board_info.addr = 0x60;
+
+	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
+	if (chan->number < 2)
+		i2c = &chan->dev->channel[0].i2c_adapter;
+	else
+		i2c = &chan->dev->channel[1].i2c_adapter;
+
+	/*
+	 * due to a hardware quirk with the I2C gate on the stv0367+tda18212
+	 * combo, the tda18212 must be probed by reading it's id _twice_ when
+	 * cold started, or it very likely will fail.
+	 */
+	if (dmdtype == DEMOD_TYPE_STV0367)
+		tuner_tda18212_ping(chan, i2c, board_info.addr);
+
+	request_module(board_info.type);
+
+	/* perform tuner init/attach */
+	client = i2c_new_device(i2c, &board_info);
+	if (!client || !client->dev.driver)
+		goto err;
+
+	if (!try_module_get(client->dev.driver->owner)) {
+		i2c_unregister_device(client);
+		goto err;
+	}
+
+	chan->i2c_client[0] = client;
+	chan->i2c_client_fe = 1;
+
+	return 0;
+err:
+	dev_err(pdev, "TDA18212 tuner not found. Device is not fully operational.\n");
+	return -ENODEV;
+}
+
 static int tuner_attach_probe(struct ngene_channel *chan)
 {
 	switch (chan->demod_type) {
@@ -128,6 +244,8 @@ static int tuner_attach_probe(struct ngene_channel *chan)
 		return tuner_attach_stv6110(chan);
 	case DEMOD_TYPE_DRXK:
 		return tuner_attach_tda18271(chan);
+	case DEMOD_TYPE_STV0367:
+		return tuner_attach_tda18212(chan, chan->demod_type);
 	}
 
 	return -EINVAL;
@@ -171,6 +289,43 @@ static int demod_attach_stv0900(struct ngene_channel *chan)
 	return 0;
 }
 
+static struct stv0367_config ddb_stv0367_config[] = {
+	{
+		.demod_address = 0x1f,
+		.xtal = 27000000,
+		.if_khz = 0,
+		.if_iq_mode = FE_TER_NORMAL_IF_TUNER,
+		.ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
+		.clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
+	}, {
+		.demod_address = 0x1e,
+		.xtal = 27000000,
+		.if_khz = 0,
+		.if_iq_mode = FE_TER_NORMAL_IF_TUNER,
+		.ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
+		.clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
+	},
+};
+
+static int demod_attach_stv0367(struct ngene_channel *chan,
+				struct i2c_adapter *i2c)
+{
+	struct device *pdev = &chan->dev->pci_dev->dev;
+
+	chan->fe = dvb_attach(stv0367ddb_attach,
+			      &ddb_stv0367_config[(chan->number & 1)], i2c);
+
+	if (!chan->fe) {
+		dev_err(pdev, "stv0367ddb_attach() failed!\n");
+		return -ENODEV;
+	}
+
+	chan->fe->sec_priv = chan;
+	chan->gate_ctrl = chan->fe->ops.i2c_gate_ctrl;
+	chan->fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
+	return 0;
+}
+
 static void cineS2_tuner_i2c_lock(struct dvb_frontend *fe, int lock)
 {
 	struct ngene_channel *chan = fe->analog_demod_priv;
@@ -181,24 +336,6 @@ static void cineS2_tuner_i2c_lock(struct dvb_frontend *fe, int lock)
 		up(&chan->dev->pll_mutex);
 }
 
-static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
-{
-	struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
-				   .buf  = val,  .len   = 1 } };
-	return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
-}
-
-static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
-			  u16 reg, u8 *val)
-{
-	u8 msg[2] = {reg>>8, reg&0xff};
-	struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
-				   .buf  = msg, .len   = 2},
-				  {.addr = adr, .flags = I2C_M_RD,
-				   .buf  = val, .len   = 1} };
-	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
-}
-
 static int port_has_stv0900(struct i2c_adapter *i2c, int port)
 {
 	u8 val;
@@ -216,6 +353,21 @@ static int port_has_drxk(struct i2c_adapter *i2c, int port)
 	return 1;
 }
 
+static int port_has_stv0367(struct i2c_adapter *i2c)
+{
+	u8 val;
+
+	if (i2c_read_reg16(i2c, 0x1e, 0xf000, &val) < 0)
+		return 0;
+	if (val != 0x60)
+		return 0;
+	if (i2c_read_reg16(i2c, 0x1f, 0xf000, &val) < 0)
+		return 0;
+	if (val != 0x60)
+		return 0;
+	return 1;
+}
+
 static int demod_attach_drxk(struct ngene_channel *chan,
 			     struct i2c_adapter *i2c)
 {
@@ -285,6 +437,10 @@ static int cineS2_probe(struct ngene_channel *chan)
 	} else if (port_has_drxk(i2c, chan->number^2)) {
 		chan->demod_type = DEMOD_TYPE_DRXK;
 		demod_attach_drxk(chan, i2c);
+	} else if (port_has_stv0367(i2c)) {
+		chan->demod_type = DEMOD_TYPE_STV0367;
+		dev_info(pdev, "STV0367 on channel %d\n", chan->number);
+		demod_attach_stv0367(chan, i2c);
 	} else {
 		dev_err(pdev, "No demod found on chan %d\n", chan->number);
 		return -ENODEV;
diff --git a/drivers/media/pci/ngene/ngene-core.c b/drivers/media/pci/ngene/ngene-core.c
index a63f019fb62f..526d0adfa427 100644
--- a/drivers/media/pci/ngene/ngene-core.c
+++ b/drivers/media/pci/ngene/ngene-core.c
@@ -1408,6 +1408,7 @@ static void release_channel(struct ngene_channel *chan)
 {
 	struct dvb_demux *dvbdemux = &chan->demux;
 	struct ngene *dev = chan->dev;
+	struct i2c_client *client;
 
 	if (chan->running)
 		set_transfer(chan, 0);
@@ -1424,6 +1425,16 @@ static void release_channel(struct ngene_channel *chan)
 
 	if (chan->fe) {
 		dvb_unregister_frontend(chan->fe);
+
+		/* release I2C client (tuner) if needed */
+		client = chan->i2c_client[0];
+		if (chan->i2c_client_fe && client) {
+			module_put(client->dev.driver->owner);
+			i2c_unregister_device(client);
+			chan->i2c_client[0] = NULL;
+			client = NULL;
+		}
+
 		dvb_frontend_detach(chan->fe);
 		chan->fe = NULL;
 	}
@@ -1459,6 +1470,7 @@ static int init_channel(struct ngene_channel *chan)
 	chan->users = 0;
 	chan->type = io;
 	chan->mode = chan->type;	/* for now only one mode */
+	chan->i2c_client_fe = 0;	/* be sure this is set to zero */
 
 	if (io & NGENE_IO_TSIN) {
 		chan->fe = NULL;
diff --git a/drivers/media/pci/ngene/ngene.h b/drivers/media/pci/ngene/ngene.h
index 9724701a3274..1b88a9aa7aac 100644
--- a/drivers/media/pci/ngene/ngene.h
+++ b/drivers/media/pci/ngene/ngene.h
@@ -53,6 +53,7 @@
 
 #define DEMOD_TYPE_STV090X	0
 #define DEMOD_TYPE_DRXK		1
+#define DEMOD_TYPE_STV0367	2
 
 enum STREAM {
 	STREAM_VIDEOIN1 = 0,        /* ITU656 or TS Input */
@@ -634,6 +635,7 @@ struct ngene_channel {
 	struct device         device;
 	struct i2c_adapter    i2c_adapter;
 	struct i2c_client    *i2c_client[1];
+	int                   i2c_client_fe;
 
 	struct ngene         *dev;
 	int                   number;
-- 
2.16.1

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

* [PATCH v2 05/12] [media] ngene: add XO2 module support
  2018-02-25 12:31 [PATCH v2 00/12] ngene-updates: Hardware support, TS buffer shift fix Daniel Scheller
                   ` (3 preceding siblings ...)
  2018-02-25 12:31 ` [PATCH v2 04/12] [media] ngene: support STV0367 DVB-C/T DuoFlex addons Daniel Scheller
@ 2018-02-25 12:31 ` Daniel Scheller
  2018-02-25 12:31 ` [PATCH v2 06/12] [media] ngene: add support for Sony CXD28xx-based DuoFlex modules Daniel Scheller
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Daniel Scheller @ 2018-02-25 12:31 UTC (permalink / raw)
  To: linux-media, mchehab, mchehab

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

Detect and initialise modules equipped with XO2 interfaces (Lattice
MachXO2). This requires a few more I2C transfer functions which this adds
aswell. Defines for the different possible (available) module types are
added to ngene.h. The support for the actual tuners contained on these
addon modules is kept separate from this commit and is being added with
the next commits.

The xo2names array is temporarily marked __maybe_unused to silence a
corresponding compiler warning at this stage.

Signed-off-by: Daniel Scheller <d.scheller@gmx.net>
---
 drivers/media/pci/ngene/ngene-cards.c | 144 +++++++++++++++++++++++++++++++++-
 drivers/media/pci/ngene/ngene.h       |  12 +++
 2 files changed, 155 insertions(+), 1 deletion(-)

diff --git a/drivers/media/pci/ngene/ngene-cards.c b/drivers/media/pci/ngene/ngene-cards.c
index 7ec5f68b1ec7..05b8e56999ec 100644
--- a/drivers/media/pci/ngene/ngene-cards.c
+++ b/drivers/media/pci/ngene/ngene-cards.c
@@ -50,6 +50,32 @@
 /* I2C transfer functions used for demod/tuner probing***********************/
 /****************************************************************************/
 
+static int i2c_io(struct i2c_adapter *adapter, u8 adr,
+		  u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen)
+{
+	struct i2c_msg msgs[2] = {{.addr = adr,  .flags = 0,
+				   .buf  = wbuf, .len   = wlen },
+				  {.addr = adr,  .flags = I2C_M_RD,
+				   .buf  = rbuf,  .len   = rlen } };
+	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
+}
+
+static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
+{
+	struct i2c_msg msg = {.addr = adr, .flags = 0,
+			      .buf = data, .len = len};
+
+	return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1;
+}
+
+static int i2c_write_reg(struct i2c_adapter *adap, u8 adr,
+			 u8 reg, u8 val)
+{
+	u8 msg[2] = {reg, val};
+
+	return i2c_write(adap, adr, msg, 2);
+}
+
 static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
 {
 	struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
@@ -78,6 +104,12 @@ static int i2c_read_regs(struct i2c_adapter *adapter,
 
 	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
 }
+
+static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val)
+{
+	return i2c_read_regs(adapter, adr, reg, val, 1);
+}
+
 /****************************************************************************/
 /* Demod/tuner attachment ***************************************************/
 /****************************************************************************/
@@ -390,12 +422,98 @@ static int demod_attach_drxk(struct ngene_channel *chan,
 	return 0;
 }
 
+/****************************************************************************/
+/* XO2 related lists and functions ******************************************/
+/****************************************************************************/
+
+static char __maybe_unused *xo2names[] = {
+	"DUAL DVB-S2",
+	"DUAL DVB-C/T/T2",
+	"DUAL DVB-ISDBT",
+	"DUAL DVB-C/C2/T/T2",
+	"DUAL ATSC",
+	"DUAL DVB-C/C2/T/T2/I",
+};
+
+static int init_xo2(struct ngene_channel *chan, struct i2c_adapter *i2c)
+{
+	struct device *pdev = &chan->dev->pci_dev->dev;
+	u8 addr = 0x10;
+	u8 val, data[2];
+	int res;
+
+	res = i2c_read_regs(i2c, addr, 0x04, data, 2);
+	if (res < 0)
+		return res;
+
+	if (data[0] != 0x01)  {
+		dev_info(pdev, "Invalid XO2 on channel %d\n", chan->number);
+		return -1;
+	}
+
+	i2c_read_reg(i2c, addr, 0x08, &val);
+	if (val != 0) {
+		i2c_write_reg(i2c, addr, 0x08, 0x00);
+		msleep(100);
+	}
+	/* Enable tuner power, disable pll, reset demods */
+	i2c_write_reg(i2c, addr, 0x08, 0x04);
+	usleep_range(2000, 3000);
+	/* Release demod resets */
+	i2c_write_reg(i2c, addr, 0x08, 0x07);
+
+	/*
+	 * speed: 0=55,1=75,2=90,3=104 MBit/s
+	 * Note: The ngene hardware must be run at 75 MBit/s compared
+	 * to more modern ddbridge hardware which runs at 90 MBit/s,
+	 * else there will be issues with the data transport and non-
+	 * working secondary/slave demods/tuners.
+	 */
+	i2c_write_reg(i2c, addr, 0x09, 1);
+
+	i2c_write_reg(i2c, addr, 0x0a, 0x01);
+	i2c_write_reg(i2c, addr, 0x0b, 0x01);
+
+	usleep_range(2000, 3000);
+	/* Start XO2 PLL */
+	i2c_write_reg(i2c, addr, 0x08, 0x87);
+
+	return 0;
+}
+
+static int port_has_xo2(struct i2c_adapter *i2c, u8 *type, u8 *id)
+{
+	u8 probe[1] = { 0x00 }, data[4];
+	u8 addr = 0x10;
+
+	*type = NGENE_XO2_TYPE_NONE;
+
+	if (i2c_io(i2c, addr, probe, 1, data, 4))
+		return 0;
+	if (data[0] == 'D' && data[1] == 'F') {
+		*id = data[2];
+		*type = NGENE_XO2_TYPE_DUOFLEX;
+		return 1;
+	}
+	if (data[0] == 'C' && data[1] == 'I') {
+		*id = data[2];
+		*type = NGENE_XO2_TYPE_CI;
+		return 1;
+	}
+	return 0;
+}
+
+/****************************************************************************/
+/* Probing and port/channel handling ****************************************/
+/****************************************************************************/
+
 static int cineS2_probe(struct ngene_channel *chan)
 {
 	struct device *pdev = &chan->dev->pci_dev->dev;
 	struct i2c_adapter *i2c;
 	struct stv090x_config *fe_conf;
 	u8 buf[3];
+	u8 xo2_type, xo2_id;
 	struct i2c_msg i2c_msg = { .flags = 0, .buf = buf };
 	int rc;
 
@@ -405,7 +523,31 @@ static int cineS2_probe(struct ngene_channel *chan)
 	else
 		i2c = &chan->dev->channel[1].i2c_adapter;
 
-	if (port_has_stv0900(i2c, chan->number)) {
+	if (port_has_xo2(i2c, &xo2_type, &xo2_id)) {
+		xo2_id >>= 2;
+		dev_dbg(pdev, "XO2 on channel %d (type %d, id %d)\n",
+			chan->number, xo2_type, xo2_id);
+
+		switch (xo2_type) {
+		case NGENE_XO2_TYPE_DUOFLEX:
+			if (chan->number & 1)
+				dev_dbg(pdev,
+					"skipping XO2 init on odd channel %d",
+					chan->number);
+			else
+				init_xo2(chan, i2c);
+
+			/* TODO: implement support for XO2 module types */
+			dev_warn(pdev, "XO2 not supported\n");
+			return -ENODEV;
+		case NGENE_XO2_TYPE_CI:
+			dev_info(pdev, "DuoFlex CI modules not supported\n");
+			return -ENODEV;
+		default:
+			dev_info(pdev, "Unsupported XO2 module type\n");
+			return -ENODEV;
+		}
+	} else if (port_has_stv0900(i2c, chan->number)) {
 		chan->demod_type = DEMOD_TYPE_STV090X;
 		fe_conf = chan->dev->card_info->fe_config[chan->number];
 		/* demod found, attach it */
diff --git a/drivers/media/pci/ngene/ngene.h b/drivers/media/pci/ngene/ngene.h
index 1b88a9aa7aac..72195f6552b3 100644
--- a/drivers/media/pci/ngene/ngene.h
+++ b/drivers/media/pci/ngene/ngene.h
@@ -55,6 +55,18 @@
 #define DEMOD_TYPE_DRXK		1
 #define DEMOD_TYPE_STV0367	2
 
+#define DEMOD_TYPE_XO2		32
+#define DEMOD_TYPE_STV0910	(DEMOD_TYPE_XO2 + 0)
+#define DEMOD_TYPE_SONY_CT2	(DEMOD_TYPE_XO2 + 1)
+#define DEMOD_TYPE_SONY_ISDBT	(DEMOD_TYPE_XO2 + 2)
+#define DEMOD_TYPE_SONY_C2T2	(DEMOD_TYPE_XO2 + 3)
+#define DEMOD_TYPE_ST_ATSC	(DEMOD_TYPE_XO2 + 4)
+#define DEMOD_TYPE_SONY_C2T2I	(DEMOD_TYPE_XO2 + 5)
+
+#define NGENE_XO2_TYPE_NONE	0
+#define NGENE_XO2_TYPE_DUOFLEX	1
+#define NGENE_XO2_TYPE_CI	2
+
 enum STREAM {
 	STREAM_VIDEOIN1 = 0,        /* ITU656 or TS Input */
 	STREAM_VIDEOIN2,
-- 
2.16.1

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

* [PATCH v2 06/12] [media] ngene: add support for Sony CXD28xx-based DuoFlex modules
  2018-02-25 12:31 [PATCH v2 00/12] ngene-updates: Hardware support, TS buffer shift fix Daniel Scheller
                   ` (4 preceding siblings ...)
  2018-02-25 12:31 ` [PATCH v2 05/12] [media] ngene: add XO2 module support Daniel Scheller
@ 2018-02-25 12:31 ` Daniel Scheller
  2018-02-25 12:31 ` [PATCH v2 07/12] [media] ngene: add support for DuoFlex S2 V4 addon modules Daniel Scheller
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Daniel Scheller @ 2018-02-25 12:31 UTC (permalink / raw)
  To: linux-media, mchehab, mchehab

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

Recognize (probe) and support (attach) all Sony CXD28xx based DuoFlex
addon modules/cards, namely the DuoFlex CT2 (CXD2837), ISDB-T (CXD2838),
C2T2 (CXD2843) and C2T2I (CXD2854). Since all these modules are equipped
with a MachXO2 interface, that support is required for the hardware to
work. This functionality utilises the auxiliary cxd2841er and tda18212
drivers.

This also adds autoselection (if MEDIA_SUBDRV_AUTOSELECT) of the CXD2841ER
demod driver to Kconfig. The __maybe_unused annotation can now be removed
from the xo2names array.

Signed-off-by: Daniel Scheller <d.scheller@gmx.net>
---
 drivers/media/pci/ngene/Kconfig       |  1 +
 drivers/media/pci/ngene/ngene-cards.c | 63 ++++++++++++++++++++++++++++++++---
 2 files changed, 59 insertions(+), 5 deletions(-)

diff --git a/drivers/media/pci/ngene/Kconfig b/drivers/media/pci/ngene/Kconfig
index c3254f9dc8ad..f717567f54a5 100644
--- a/drivers/media/pci/ngene/Kconfig
+++ b/drivers/media/pci/ngene/Kconfig
@@ -9,6 +9,7 @@ config DVB_NGENE
 	select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT
 	select DVB_STV0367 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_CXD2841ER if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_TDA18212 if MEDIA_SUBDRV_AUTOSELECT
 	select DVB_CXD2099 if MEDIA_SUBDRV_AUTOSELECT
 	---help---
diff --git a/drivers/media/pci/ngene/ngene-cards.c b/drivers/media/pci/ngene/ngene-cards.c
index 05b8e56999ec..cdc8db14c606 100644
--- a/drivers/media/pci/ngene/ngene-cards.c
+++ b/drivers/media/pci/ngene/ngene-cards.c
@@ -45,6 +45,7 @@
 #include "stv0367.h"
 #include "stv0367_priv.h"
 #include "tda18212.h"
+#include "cxd2841er.h"
 
 /****************************************************************************/
 /* I2C transfer functions used for demod/tuner probing***********************/
@@ -277,6 +278,10 @@ static int tuner_attach_probe(struct ngene_channel *chan)
 	case DEMOD_TYPE_DRXK:
 		return tuner_attach_tda18271(chan);
 	case DEMOD_TYPE_STV0367:
+	case DEMOD_TYPE_SONY_CT2:
+	case DEMOD_TYPE_SONY_ISDBT:
+	case DEMOD_TYPE_SONY_C2T2:
+	case DEMOD_TYPE_SONY_C2T2I:
 		return tuner_attach_tda18212(chan, chan->demod_type);
 	}
 
@@ -358,6 +363,34 @@ static int demod_attach_stv0367(struct ngene_channel *chan,
 	return 0;
 }
 
+static int demod_attach_cxd28xx(struct ngene_channel *chan,
+				struct i2c_adapter *i2c, int osc24)
+{
+	struct device *pdev = &chan->dev->pci_dev->dev;
+	struct cxd2841er_config cfg;
+
+	/* the cxd2841er driver expects 8bit/shifted I2C addresses */
+	cfg.i2c_addr = ((chan->number & 1) ? 0x6d : 0x6c) << 1;
+
+	cfg.xtal = osc24 ? SONY_XTAL_24000 : SONY_XTAL_20500;
+	cfg.flags = CXD2841ER_AUTO_IFHZ | CXD2841ER_EARLY_TUNE |
+		CXD2841ER_NO_WAIT_LOCK | CXD2841ER_NO_AGCNEG |
+		CXD2841ER_TSBITS | CXD2841ER_TS_SERIAL;
+
+	/* attach frontend */
+	chan->fe = dvb_attach(cxd2841er_attach_t_c, &cfg, i2c);
+
+	if (!chan->fe) {
+		dev_err(pdev, "CXD28XX attach failed!\n");
+		return -ENODEV;
+	}
+
+	chan->fe->sec_priv = chan;
+	chan->gate_ctrl = chan->fe->ops.i2c_gate_ctrl;
+	chan->fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
+	return 0;
+}
+
 static void cineS2_tuner_i2c_lock(struct dvb_frontend *fe, int lock)
 {
 	struct ngene_channel *chan = fe->analog_demod_priv;
@@ -426,7 +459,7 @@ static int demod_attach_drxk(struct ngene_channel *chan,
 /* XO2 related lists and functions ******************************************/
 /****************************************************************************/
 
-static char __maybe_unused *xo2names[] = {
+static char *xo2names[] = {
 	"DUAL DVB-S2",
 	"DUAL DVB-C/T/T2",
 	"DUAL DVB-ISDBT",
@@ -513,7 +546,8 @@ static int cineS2_probe(struct ngene_channel *chan)
 	struct i2c_adapter *i2c;
 	struct stv090x_config *fe_conf;
 	u8 buf[3];
-	u8 xo2_type, xo2_id;
+	u8 xo2_type, xo2_id, xo2_demodtype;
+	u8 sony_osc24 = 0;
 	struct i2c_msg i2c_msg = { .flags = 0, .buf = buf };
 	int rc;
 
@@ -537,9 +571,28 @@ static int cineS2_probe(struct ngene_channel *chan)
 			else
 				init_xo2(chan, i2c);
 
-			/* TODO: implement support for XO2 module types */
-			dev_warn(pdev, "XO2 not supported\n");
-			return -ENODEV;
+			xo2_demodtype = DEMOD_TYPE_XO2 + xo2_id;
+
+			switch (xo2_demodtype) {
+			case DEMOD_TYPE_SONY_CT2:
+			case DEMOD_TYPE_SONY_ISDBT:
+			case DEMOD_TYPE_SONY_C2T2:
+			case DEMOD_TYPE_SONY_C2T2I:
+				dev_info(pdev, "%s (XO2) on channel %d\n",
+					 xo2names[xo2_id], chan->number);
+				chan->demod_type = xo2_demodtype;
+				if (xo2_demodtype == DEMOD_TYPE_SONY_C2T2I)
+					sony_osc24 = 1;
+
+				demod_attach_cxd28xx(chan, i2c, sony_osc24);
+				break;
+			default:
+				dev_warn(pdev,
+					 "Unsupported XO2 module on channel %d\n",
+					 chan->number);
+				return -ENODEV;
+			}
+			break;
 		case NGENE_XO2_TYPE_CI:
 			dev_info(pdev, "DuoFlex CI modules not supported\n");
 			return -ENODEV;
-- 
2.16.1

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

* [PATCH v2 07/12] [media] ngene: add support for DuoFlex S2 V4 addon modules
  2018-02-25 12:31 [PATCH v2 00/12] ngene-updates: Hardware support, TS buffer shift fix Daniel Scheller
                   ` (5 preceding siblings ...)
  2018-02-25 12:31 ` [PATCH v2 06/12] [media] ngene: add support for Sony CXD28xx-based DuoFlex modules Daniel Scheller
@ 2018-02-25 12:31 ` Daniel Scheller
  2018-02-25 12:31 ` [PATCH v2 08/12] [media] ngene: deduplicate I2C adapter evaluation Daniel Scheller
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Daniel Scheller @ 2018-02-25 12:31 UTC (permalink / raw)
  To: linux-media, mchehab, mchehab

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

Add support for the STV0910/STV6111/LNBH25 based DuoFlex S2 V4 DVB-S2
addon modules by recognizing them from their XO2 type value and using
the auxiliary stv0910, stv6111 and lnbh25 driver to form a complete
DVB frontend.

This also adds autoselection (if MEDIA_SUBDRV_AUTOSELECT) of the STV0910,
STV6111 and LNBH25 demod/tuner/LNB-IC drivers to Kconfig.

Signed-off-by: Daniel Scheller <d.scheller@gmx.net>
---
 drivers/media/pci/ngene/Kconfig       |  3 ++
 drivers/media/pci/ngene/ngene-cards.c | 83 +++++++++++++++++++++++++++++++++++
 2 files changed, 86 insertions(+)

diff --git a/drivers/media/pci/ngene/Kconfig b/drivers/media/pci/ngene/Kconfig
index f717567f54a5..e06d019996f3 100644
--- a/drivers/media/pci/ngene/Kconfig
+++ b/drivers/media/pci/ngene/Kconfig
@@ -11,6 +11,9 @@ config DVB_NGENE
 	select DVB_STV0367 if MEDIA_SUBDRV_AUTOSELECT
 	select DVB_CXD2841ER if MEDIA_SUBDRV_AUTOSELECT
 	select MEDIA_TUNER_TDA18212 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STV0910 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STV6111 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_LNBH25 if MEDIA_SUBDRV_AUTOSELECT
 	select DVB_CXD2099 if MEDIA_SUBDRV_AUTOSELECT
 	---help---
 	  Support for Micronas PCI express cards with nGene bridge.
diff --git a/drivers/media/pci/ngene/ngene-cards.c b/drivers/media/pci/ngene/ngene-cards.c
index cdc8db14c606..00b100660784 100644
--- a/drivers/media/pci/ngene/ngene-cards.c
+++ b/drivers/media/pci/ngene/ngene-cards.c
@@ -46,6 +46,9 @@
 #include "stv0367_priv.h"
 #include "tda18212.h"
 #include "cxd2841er.h"
+#include "stv0910.h"
+#include "stv6111.h"
+#include "lnbh25.h"
 
 /****************************************************************************/
 /* I2C transfer functions used for demod/tuner probing***********************/
@@ -152,6 +155,30 @@ static int tuner_attach_stv6110(struct ngene_channel *chan)
 	return 0;
 }
 
+static int tuner_attach_stv6111(struct ngene_channel *chan)
+{
+	struct device *pdev = &chan->dev->pci_dev->dev;
+	struct i2c_adapter *i2c;
+	struct dvb_frontend *fe;
+	u8 adr = 4 + ((chan->number & 1) ? 0x63 : 0x60);
+
+	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
+	if (chan->number < 2)
+		i2c = &chan->dev->channel[0].i2c_adapter;
+	else
+		i2c = &chan->dev->channel[1].i2c_adapter;
+
+	fe = dvb_attach(stv6111_attach, chan->fe, i2c, adr);
+	if (!fe) {
+		fe = dvb_attach(stv6111_attach, chan->fe, i2c, adr & ~4);
+		if (!fe) {
+			dev_err(pdev, "stv6111_attach() failed!\n");
+			return -ENODEV;
+		}
+	}
+	return 0;
+}
+
 static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
 {
 	struct ngene_channel *chan = fe->sec_priv;
@@ -283,6 +310,8 @@ static int tuner_attach_probe(struct ngene_channel *chan)
 	case DEMOD_TYPE_SONY_C2T2:
 	case DEMOD_TYPE_SONY_C2T2I:
 		return tuner_attach_tda18212(chan, chan->demod_type);
+	case DEMOD_TYPE_STV0910:
+		return tuner_attach_stv6111(chan);
 	}
 
 	return -EINVAL;
@@ -326,6 +355,54 @@ static int demod_attach_stv0900(struct ngene_channel *chan)
 	return 0;
 }
 
+static struct stv0910_cfg stv0910_p = {
+	.adr      = 0x68,
+	.parallel = 1,
+	.rptlvl   = 4,
+	.clk      = 30000000,
+};
+
+static struct lnbh25_config lnbh25_cfg = {
+	.i2c_address = 0x0c << 1,
+	.data2_config = LNBH25_TEN
+};
+
+static int demod_attach_stv0910(struct ngene_channel *chan,
+				struct i2c_adapter *i2c)
+{
+	struct device *pdev = &chan->dev->pci_dev->dev;
+	struct stv0910_cfg cfg = stv0910_p;
+	struct lnbh25_config lnbcfg = lnbh25_cfg;
+
+	chan->fe = dvb_attach(stv0910_attach, i2c, &cfg, (chan->number & 1));
+	if (!chan->fe) {
+		cfg.adr = 0x6c;
+		chan->fe = dvb_attach(stv0910_attach, i2c,
+				      &cfg, (chan->number & 1));
+	}
+	if (!chan->fe) {
+		dev_err(pdev, "stv0910_attach() failed!\n");
+		return -ENODEV;
+	}
+
+	/*
+	 * attach lnbh25 - leftshift by one as the lnbh25 driver expects 8bit
+	 * i2c addresses
+	 */
+	lnbcfg.i2c_address = (((chan->number & 1) ? 0x0d : 0x0c) << 1);
+	if (!dvb_attach(lnbh25_attach, chan->fe, &lnbcfg, i2c)) {
+		lnbcfg.i2c_address = (((chan->number & 1) ? 0x09 : 0x08) << 1);
+		if (!dvb_attach(lnbh25_attach, chan->fe, &lnbcfg, i2c)) {
+			dev_err(pdev, "lnbh25_attach() failed!\n");
+			dvb_frontend_detach(chan->fe);
+			chan->fe = NULL;
+			return -ENODEV;
+		}
+	}
+
+	return 0;
+}
+
 static struct stv0367_config ddb_stv0367_config[] = {
 	{
 		.demod_address = 0x1f,
@@ -586,6 +663,12 @@ static int cineS2_probe(struct ngene_channel *chan)
 
 				demod_attach_cxd28xx(chan, i2c, sony_osc24);
 				break;
+			case DEMOD_TYPE_STV0910:
+				dev_info(pdev, "%s (XO2) on channel %d\n",
+					 xo2names[xo2_id], chan->number);
+				chan->demod_type = xo2_demodtype;
+				demod_attach_stv0910(chan, i2c);
+				break;
 			default:
 				dev_warn(pdev,
 					 "Unsupported XO2 module on channel %d\n",
-- 
2.16.1

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

* [PATCH v2 08/12] [media] ngene: deduplicate I2C adapter evaluation
  2018-02-25 12:31 [PATCH v2 00/12] ngene-updates: Hardware support, TS buffer shift fix Daniel Scheller
                   ` (6 preceding siblings ...)
  2018-02-25 12:31 ` [PATCH v2 07/12] [media] ngene: add support for DuoFlex S2 V4 addon modules Daniel Scheller
@ 2018-02-25 12:31 ` Daniel Scheller
  2018-03-06 16:06   ` Mauro Carvalho Chehab
  2018-02-25 12:31 ` [PATCH v2 09/12] [media] ngene: check for CXD2099AR presence before attaching Daniel Scheller
                   ` (3 subsequent siblings)
  11 siblings, 1 reply; 16+ messages in thread
From: Daniel Scheller @ 2018-02-25 12:31 UTC (permalink / raw)
  To: linux-media, mchehab, mchehab

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

The I2C adapter evaluation (based on chan->number) is duplicated at
several places (tuner_attach_() functions, demod_attach_stv0900() and
cineS2_probe()). Clean this up by wrapping that construct in a separate
function which all users of that can pass the ngene_channel pointer and
get the correct I2C adapter from.

Signed-off-by: Daniel Scheller <d.scheller@gmx.net>
---
 drivers/media/pci/ngene/ngene-cards.c | 41 +++++++++++++----------------------
 1 file changed, 15 insertions(+), 26 deletions(-)

diff --git a/drivers/media/pci/ngene/ngene-cards.c b/drivers/media/pci/ngene/ngene-cards.c
index 00b100660784..dff55c7c9f86 100644
--- a/drivers/media/pci/ngene/ngene-cards.c
+++ b/drivers/media/pci/ngene/ngene-cards.c
@@ -118,17 +118,25 @@ static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val)
 /* Demod/tuner attachment ***************************************************/
 /****************************************************************************/
 
+static struct i2c_adapter *i2c_adapter_from_chan(struct ngene_channel *chan)
+{
+	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
+	if (chan->number < 2)
+		return &chan->dev->channel[0].i2c_adapter;
+
+	return &chan->dev->channel[1].i2c_adapter;
+}
+
 static int tuner_attach_stv6110(struct ngene_channel *chan)
 {
 	struct device *pdev = &chan->dev->pci_dev->dev;
-	struct i2c_adapter *i2c;
+	struct i2c_adapter *i2c = i2c_adapter_from_chan(chan);
 	struct stv090x_config *feconf = (struct stv090x_config *)
 		chan->dev->card_info->fe_config[chan->number];
 	struct stv6110x_config *tunerconf = (struct stv6110x_config *)
 		chan->dev->card_info->tuner_config[chan->number];
 	const struct stv6110x_devctl *ctl;
 
-	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
 	if (chan->number < 2)
 		i2c = &chan->dev->channel[0].i2c_adapter;
 	else
@@ -158,16 +166,10 @@ static int tuner_attach_stv6110(struct ngene_channel *chan)
 static int tuner_attach_stv6111(struct ngene_channel *chan)
 {
 	struct device *pdev = &chan->dev->pci_dev->dev;
-	struct i2c_adapter *i2c;
+	struct i2c_adapter *i2c = i2c_adapter_from_chan(chan);
 	struct dvb_frontend *fe;
 	u8 adr = 4 + ((chan->number & 1) ? 0x63 : 0x60);
 
-	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
-	if (chan->number < 2)
-		i2c = &chan->dev->channel[0].i2c_adapter;
-	else
-		i2c = &chan->dev->channel[1].i2c_adapter;
-
 	fe = dvb_attach(stv6111_attach, chan->fe, i2c, adr);
 	if (!fe) {
 		fe = dvb_attach(stv6111_attach, chan->fe, i2c, adr & ~4);
@@ -197,10 +199,9 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
 static int tuner_attach_tda18271(struct ngene_channel *chan)
 {
 	struct device *pdev = &chan->dev->pci_dev->dev;
-	struct i2c_adapter *i2c;
+	struct i2c_adapter *i2c = i2c_adapter_from_chan(chan);
 	struct dvb_frontend *fe;
 
-	i2c = &chan->dev->channel[0].i2c_adapter;
 	if (chan->fe->ops.i2c_gate_ctrl)
 		chan->fe->ops.i2c_gate_ctrl(chan->fe, 1);
 	fe = dvb_attach(tda18271c2dd_attach, chan->fe, i2c, 0x60);
@@ -240,7 +241,7 @@ static int tuner_tda18212_ping(struct ngene_channel *chan,
 static int tuner_attach_tda18212(struct ngene_channel *chan, u32 dmdtype)
 {
 	struct device *pdev = &chan->dev->pci_dev->dev;
-	struct i2c_adapter *i2c;
+	struct i2c_adapter *i2c = i2c_adapter_from_chan(chan);
 	struct i2c_client *client;
 	struct tda18212_config config = {
 		.fe = chan->fe,
@@ -262,12 +263,6 @@ static int tuner_attach_tda18212(struct ngene_channel *chan, u32 dmdtype)
 	else
 		board_info.addr = 0x60;
 
-	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
-	if (chan->number < 2)
-		i2c = &chan->dev->channel[0].i2c_adapter;
-	else
-		i2c = &chan->dev->channel[1].i2c_adapter;
-
 	/*
 	 * due to a hardware quirk with the I2C gate on the stv0367+tda18212
 	 * combo, the tda18212 must be probed by reading it's id _twice_ when
@@ -320,7 +315,7 @@ static int tuner_attach_probe(struct ngene_channel *chan)
 static int demod_attach_stv0900(struct ngene_channel *chan)
 {
 	struct device *pdev = &chan->dev->pci_dev->dev;
-	struct i2c_adapter *i2c;
+	struct i2c_adapter *i2c = i2c_adapter_from_chan(chan);
 	struct stv090x_config *feconf = (struct stv090x_config *)
 		chan->dev->card_info->fe_config[chan->number];
 
@@ -620,7 +615,7 @@ static int port_has_xo2(struct i2c_adapter *i2c, u8 *type, u8 *id)
 static int cineS2_probe(struct ngene_channel *chan)
 {
 	struct device *pdev = &chan->dev->pci_dev->dev;
-	struct i2c_adapter *i2c;
+	struct i2c_adapter *i2c = i2c_adapter_from_chan(chan);
 	struct stv090x_config *fe_conf;
 	u8 buf[3];
 	u8 xo2_type, xo2_id, xo2_demodtype;
@@ -628,12 +623,6 @@ static int cineS2_probe(struct ngene_channel *chan)
 	struct i2c_msg i2c_msg = { .flags = 0, .buf = buf };
 	int rc;
 
-	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
-	if (chan->number < 2)
-		i2c = &chan->dev->channel[0].i2c_adapter;
-	else
-		i2c = &chan->dev->channel[1].i2c_adapter;
-
 	if (port_has_xo2(i2c, &xo2_type, &xo2_id)) {
 		xo2_id >>= 2;
 		dev_dbg(pdev, "XO2 on channel %d (type %d, id %d)\n",
-- 
2.16.1

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

* [PATCH v2 09/12] [media] ngene: check for CXD2099AR presence before attaching
  2018-02-25 12:31 [PATCH v2 00/12] ngene-updates: Hardware support, TS buffer shift fix Daniel Scheller
                   ` (7 preceding siblings ...)
  2018-02-25 12:31 ` [PATCH v2 08/12] [media] ngene: deduplicate I2C adapter evaluation Daniel Scheller
@ 2018-02-25 12:31 ` Daniel Scheller
  2018-02-25 12:31 ` [PATCH v2 10/12] [media] ngene: don't treat non-existing demods as error Daniel Scheller
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Daniel Scheller @ 2018-02-25 12:31 UTC (permalink / raw)
  To: linux-media, mchehab, mchehab

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

Currently, if there's no CXD2099AR attached to any expansion connector of
the ngene hardware, it will complain with this on every module load:

    cxd2099 1-0040: No CXD2099AR detected at 0x40
    cxd2099: probe of 1-0040 failed with error -5
    ngene 0000:02:00.0: CXD2099AR attach failed

This happens due to the logic assuming such hardware is always there and
blindly tries to attach the cxd2099 I2C driver. Rather add a probe
function (in ngene-cards.c with a prototype in ngene.h) to check for
the existence of such hardware before probing, and don't try further if
no CXD2099 was found.

Signed-off-by: Daniel Scheller <d.scheller@gmx.net>
---
 drivers/media/pci/ngene/ngene-cards.c | 19 +++++++++++++++++++
 drivers/media/pci/ngene/ngene-core.c  | 14 ++++++++++++++
 drivers/media/pci/ngene/ngene.h       |  3 +++
 3 files changed, 36 insertions(+)

diff --git a/drivers/media/pci/ngene/ngene-cards.c b/drivers/media/pci/ngene/ngene-cards.c
index dff55c7c9f86..d603d0af703e 100644
--- a/drivers/media/pci/ngene/ngene-cards.c
+++ b/drivers/media/pci/ngene/ngene-cards.c
@@ -505,6 +505,25 @@ static int port_has_stv0367(struct i2c_adapter *i2c)
 	return 1;
 }
 
+int ngene_port_has_cxd2099(struct i2c_adapter *i2c, u8 *type)
+{
+	u8 val;
+	u8 probe[4] = { 0xe0, 0x00, 0x00, 0x00 }, data[4];
+	struct i2c_msg msgs[2] = {{ .addr = 0x40,  .flags = 0,
+				    .buf  = probe, .len   = 4 },
+				  { .addr = 0x40,  .flags = I2C_M_RD,
+				    .buf  = data,  .len   = 4 } };
+	val = i2c_transfer(i2c, msgs, 2);
+	if (val != 2)
+		return 0;
+
+	if (data[0] == 0x02 && data[1] == 0x2b && data[3] == 0x43)
+		*type = 2;
+	else
+		*type = 1;
+	return 1;
+}
+
 static int demod_attach_drxk(struct ngene_channel *chan,
 			     struct i2c_adapter *i2c)
 {
diff --git a/drivers/media/pci/ngene/ngene-core.c b/drivers/media/pci/ngene/ngene-core.c
index 526d0adfa427..f69a8fc1ec2a 100644
--- a/drivers/media/pci/ngene/ngene-core.c
+++ b/drivers/media/pci/ngene/ngene-core.c
@@ -1589,6 +1589,20 @@ static void cxd_attach(struct ngene *dev)
 		.addr = 0x40,
 		.platform_data = &cxd_cfg,
 	};
+	int ret;
+	u8 type;
+
+	/* check for CXD2099AR presence before attaching */
+	ret = ngene_port_has_cxd2099(&dev->channel[0].i2c_adapter, &type);
+	if (!ret) {
+		dev_dbg(pdev, "No CXD2099AR found\n");
+		return;
+	}
+
+	if (type != 1) {
+		dev_warn(pdev, "CXD2099AR is uninitialized!\n");
+		return;
+	}
 
 	cxd_cfg.en = &ci->en;
 
diff --git a/drivers/media/pci/ngene/ngene.h b/drivers/media/pci/ngene/ngene.h
index 72195f6552b3..66d8eaa28549 100644
--- a/drivers/media/pci/ngene/ngene.h
+++ b/drivers/media/pci/ngene/ngene.h
@@ -909,6 +909,9 @@ int ngene_command_gpio_set(struct ngene *dev, u8 select, u8 level);
 void set_transfer(struct ngene_channel *chan, int state);
 void FillTSBuffer(void *Buffer, int Length, u32 Flags);
 
+/* Provided by ngene-cards.c */
+int ngene_port_has_cxd2099(struct i2c_adapter *i2c, u8 *type);
+
 /* Provided by ngene-i2c.c */
 int ngene_i2c_init(struct ngene *dev, int dev_nr);
 
-- 
2.16.1

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

* [PATCH v2 10/12] [media] ngene: don't treat non-existing demods as error
  2018-02-25 12:31 [PATCH v2 00/12] ngene-updates: Hardware support, TS buffer shift fix Daniel Scheller
                   ` (8 preceding siblings ...)
  2018-02-25 12:31 ` [PATCH v2 09/12] [media] ngene: check for CXD2099AR presence before attaching Daniel Scheller
@ 2018-02-25 12:31 ` Daniel Scheller
  2018-02-25 12:31 ` [PATCH v2 11/12] [media] ngene: move the tsin_exchange() stripcopy block into a function Daniel Scheller
  2018-02-25 12:31 ` [PATCH v2 12/12] [media] ngene: compensate for TS buffer offset shifts Daniel Scheller
  11 siblings, 0 replies; 16+ messages in thread
From: Daniel Scheller @ 2018-02-25 12:31 UTC (permalink / raw)
  To: linux-media, mchehab, mchehab

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

When probing the I2C busses in cineS2_probe(), it's no error when there's
no hardware connected to the probed expansion connector, so print this
informal message with info severity.

Signed-off-by: Daniel Scheller <d.scheller@gmx.net>
---
 drivers/media/pci/ngene/ngene-cards.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/pci/ngene/ngene-cards.c b/drivers/media/pci/ngene/ngene-cards.c
index d603d0af703e..37e9f0eb6d20 100644
--- a/drivers/media/pci/ngene/ngene-cards.c
+++ b/drivers/media/pci/ngene/ngene-cards.c
@@ -728,7 +728,7 @@ static int cineS2_probe(struct ngene_channel *chan)
 		dev_info(pdev, "STV0367 on channel %d\n", chan->number);
 		demod_attach_stv0367(chan, i2c);
 	} else {
-		dev_err(pdev, "No demod found on chan %d\n", chan->number);
+		dev_info(pdev, "No demod found on chan %d\n", chan->number);
 		return -ENODEV;
 	}
 	return 0;
-- 
2.16.1

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

* [PATCH v2 11/12] [media] ngene: move the tsin_exchange() stripcopy block into a function
  2018-02-25 12:31 [PATCH v2 00/12] ngene-updates: Hardware support, TS buffer shift fix Daniel Scheller
                   ` (9 preceding siblings ...)
  2018-02-25 12:31 ` [PATCH v2 10/12] [media] ngene: don't treat non-existing demods as error Daniel Scheller
@ 2018-02-25 12:31 ` Daniel Scheller
  2018-03-06 16:18   ` Mauro Carvalho Chehab
  2018-02-25 12:31 ` [PATCH v2 12/12] [media] ngene: compensate for TS buffer offset shifts Daniel Scheller
  11 siblings, 1 reply; 16+ messages in thread
From: Daniel Scheller @ 2018-02-25 12:31 UTC (permalink / raw)
  To: linux-media, mchehab, mchehab

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

Move the copy logic that will skip previously inserted TS NULL frames when
moving data to the DVB ring buffers into an own function. This is done to
not duplicate code all over the place with the following TS offset shift
fixup patch.

Signed-off-by: Daniel Scheller <d.scheller@gmx.net>
---
 drivers/media/pci/ngene/ngene-dvb.c | 48 +++++++++++++++++++++----------------
 1 file changed, 27 insertions(+), 21 deletions(-)

diff --git a/drivers/media/pci/ngene/ngene-dvb.c b/drivers/media/pci/ngene/ngene-dvb.c
index f71fd41c762c..6d72b9f69418 100644
--- a/drivers/media/pci/ngene/ngene-dvb.c
+++ b/drivers/media/pci/ngene/ngene-dvb.c
@@ -123,6 +123,32 @@ static u32 overflow;
 static u32 stripped;
 #endif
 
+static inline void tsin_copy_stripped(struct ngene *dev, void *buf)
+{
+	if (memcmp(buf, fill_ts, sizeof(fill_ts)) != 0) {
+		if (dvb_ringbuffer_free(&dev->tsin_rbuf) >= 188) {
+			dvb_ringbuffer_write(&dev->tsin_rbuf, buf, 188);
+			wake_up(&dev->tsin_rbuf.queue);
+#ifdef DEBUG_CI_XFER
+			ok++;
+#endif
+		}
+#ifdef DEBUG_CI_XFER
+		else
+			overflow++;
+#endif
+	}
+#ifdef DEBUG_CI_XFER
+	else
+		stripped++;
+
+	if (ok % 100 == 0 && overflow)
+		dev_warn(&dev->pci_dev->dev,
+			 "%s: ok %u overflow %u dropped %u\n",
+			 __func__, ok, overflow, stripped);
+#endif
+}
+
 void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
 {
 	struct ngene_channel *chan = priv;
@@ -134,28 +160,8 @@ void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
 
 	if (dev->ci.en && chan->number == 2) {
 		while (len >= 188) {
-			if (memcmp(buf, fill_ts, sizeof fill_ts) != 0) {
-				if (dvb_ringbuffer_free(&dev->tsin_rbuf) >= 188) {
-					dvb_ringbuffer_write(&dev->tsin_rbuf, buf, 188);
-					wake_up(&dev->tsin_rbuf.queue);
-#ifdef DEBUG_CI_XFER
-					ok++;
-#endif
-				}
-#ifdef DEBUG_CI_XFER
-				else
-					overflow++;
-#endif
-			}
-#ifdef DEBUG_CI_XFER
-			else
-				stripped++;
+			tsin_copy_stripped(dev, buf);
 
-			if (ok % 100 == 0 && overflow)
-				dev_warn(&dev->pci_dev->dev,
-					 "%s: ok %u overflow %u dropped %u\n",
-					 __func__, ok, overflow, stripped);
-#endif
 			buf += 188;
 			len -= 188;
 		}
-- 
2.16.1

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

* [PATCH v2 12/12] [media] ngene: compensate for TS buffer offset shifts
  2018-02-25 12:31 [PATCH v2 00/12] ngene-updates: Hardware support, TS buffer shift fix Daniel Scheller
                   ` (10 preceding siblings ...)
  2018-02-25 12:31 ` [PATCH v2 11/12] [media] ngene: move the tsin_exchange() stripcopy block into a function Daniel Scheller
@ 2018-02-25 12:31 ` Daniel Scheller
  11 siblings, 0 replies; 16+ messages in thread
From: Daniel Scheller @ 2018-02-25 12:31 UTC (permalink / raw)
  To: linux-media, mchehab, mchehab

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

A possible hardware bug was discovered when using CA addon hardware
attached to the ngene hardware, in that the TS input buffer much likely
will shift and thus become unaligned to 188 byte blocks (a full TS frame)
when things like CA module initialisation (which happens via differing
communication paths) take place. This causes the TS NULL removal in
tsin_exchange() to fail to detect this previously inserted data and thus
causes userspace applications to receive data they didn't sent beforehand
and ultimately cause troubles.

On driver load with an inserted CAM, buffers are fine at first (note that
the driver has to keep the communication running from/to the card by
inserting TS NULL frames, this is done in tsout_exchange() via
FillTSBuffer() - that data is simply sent back by the hardware):

  offset | 0    1   2   3   4   5 .... 188 189 190 191 192 193 .... 376
  data   | 47  1f  ff  10  6f  6f ....  47  1f  ff  10  6f  6f ....  47

After a few seconds, the CA module is recognised and initialised, which is
signalled by

  dvb_ca_en50221: dvb_ca adapter X: DVB CAM detected and initialised successfully

This is where the first shift happens (this is always four bytes), buffer
becomes like this:

  offset | 0    1   2   3   4   5 .... 188 189 190 191 192 193 .... 376
  data   | 6f  6f  6f  6f  47  1f ....  6f  6f  6f  6f  47  1f ....  6f

Next, VDR, TVHeadend or any other CI aware application is started, buffers
will shift by even more bytes. It is believed this is due to the hardware
not handling control and data bytes properly distinct, and control data
having an influence on the actual data stream, which we cannot properly
detect at the driver level.

Workaround this hardware quirk by adding a detection for the TS sync byte
0x47 before each TS frame copy, scan for a new SYNC byte and a TS NULL
packet if buffers become unaligned, take note of that offset and apply
that when copying data to the DVB ring buffers. The last <188 bytes from
the hardware buffers are stored in a temp buffer (tsin_buffer), for which
the remainder will be in the beginning of the next hardware buffer (next
iteration of tsin_exchange()). That remainder will be appended to the
temp buffer and finally sent to the DVB ring buffer. The resulting TS
stream is perfectly fine, and the TS NULL packets inserted by the driver
which are sent back are properly removed. The resulting offset is being
clamped to 188 byte segments (one TS packet). Though this can result in
a repeated TS packet if the overall offset grows beyond this (and it
will grow only on CA initialisation), this is still way better than
unaligned TS frames and data sent to userspace that just isn't supposed
to be there.

This compensation can be toggled by the ci_tsfix modparam, which defaults
to 1 (enabled). In the case of problems, this can be turned off by setting
the parameter to 0 to restore the old behaviour.

Signed-off-by: Daniel Scheller <d.scheller@gmx.net>
---
Changes since v1:
- TS buffer offset correction missed a check for the remaining buffer
  length before copying the next full 188-byte block, which might could
  have caused out-of-bound-reads from void *buf. Also, tsin_find_offset
  returns it's offset clamped to 188 byte boundaries to not accidentally
  skip over valid TS data. Few typos in the commit message were fixed
  and a note for the modparam was added, too.

 drivers/media/pci/ngene/ngene-dvb.c | 91 ++++++++++++++++++++++++++++++++++++-
 drivers/media/pci/ngene/ngene.h     |  3 ++
 2 files changed, 93 insertions(+), 1 deletion(-)

diff --git a/drivers/media/pci/ngene/ngene-dvb.c b/drivers/media/pci/ngene/ngene-dvb.c
index 6d72b9f69418..0f9759a4d124 100644
--- a/drivers/media/pci/ngene/ngene-dvb.c
+++ b/drivers/media/pci/ngene/ngene-dvb.c
@@ -38,6 +38,9 @@
 
 #include "ngene.h"
 
+static int ci_tsfix = 1;
+module_param(ci_tsfix, int, 0444);
+MODULE_PARM_DESC(ci_tsfix, "Detect and fix TS buffer offset shifs in conjunction with CI expansions (default: 1/enabled)");
 
 /****************************************************************************/
 /* COMMAND API interface ****************************************************/
@@ -123,6 +126,24 @@ static u32 overflow;
 static u32 stripped;
 #endif
 
+static int tsin_find_offset(void *buf, u32 len)
+{
+	int i, l;
+
+	l = len - sizeof(fill_ts);
+	if (l <= 0)
+		return -1;
+
+	for (i = 0; i < l; i++) {
+		if (((char *)buf)[i] == 0x47) {
+			if (!memcmp(buf + i, fill_ts, sizeof(fill_ts)))
+				return i % 188;
+		}
+	}
+
+	return -1;
+}
+
 static inline void tsin_copy_stripped(struct ngene *dev, void *buf)
 {
 	if (memcmp(buf, fill_ts, sizeof(fill_ts)) != 0) {
@@ -153,18 +174,86 @@ void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
 {
 	struct ngene_channel *chan = priv;
 	struct ngene *dev = chan->dev;
-
+	int tsoff;
 
 	if (flags & DF_SWAP32)
 		swap_buffer(buf, len);
 
 	if (dev->ci.en && chan->number == 2) {
+		/* blindly copy buffers if ci_tsfix is disabled */
+		if (!ci_tsfix) {
+			while (len >= 188) {
+				tsin_copy_stripped(dev, buf);
+
+				buf += 188;
+				len -= 188;
+			}
+			return NULL;
+		}
+
+		/* ci_tsfix = 1 */
+
+		/*
+		 * since the remainder of the TS packet which got cut off
+		 * in the previous tsin_exchange() run is at the beginning
+		 * of the new TS buffer, append this to the temp buffer and
+		 * send it to the DVB ringbuffer afterwards.
+		 */
+		if (chan->tsin_offset) {
+			memcpy(&chan->tsin_buffer[(188 - chan->tsin_offset)],
+			       buf, chan->tsin_offset);
+			tsin_copy_stripped(dev, &chan->tsin_buffer);
+
+			buf += chan->tsin_offset;
+			len -= chan->tsin_offset;
+		}
+
+		/*
+		 * copy TS packets to the DVB ringbuffer and detect new offset
+		 * shifts by checking for a valid TS SYNC byte
+		 */
 		while (len >= 188) {
+			if (*((char *)buf) != 0x47) {
+				/*
+				 * no SYNC header, find new offset shift
+				 * (max. 188 bytes, tsoff will be mod 188)
+				 */
+				tsoff = tsin_find_offset(buf, len);
+				if (tsoff > 0) {
+					chan->tsin_offset += tsoff;
+					chan->tsin_offset %= 188;
+
+					buf += tsoff;
+					len -= tsoff;
+
+					dev_info(&dev->pci_dev->dev,
+						 "%s(): tsin_offset shift by %d on channel %d\n",
+						 __func__, tsoff,
+						 chan->number);
+
+					/*
+					 * offset corrected. re-check remaining
+					 * len for a full TS frame, break and
+					 * skip to fragment handling if < 188.
+					 */
+					if (len < 188)
+						break;
+				}
+			}
+
 			tsin_copy_stripped(dev, buf);
 
 			buf += 188;
 			len -= 188;
 		}
+
+		/*
+		 * if a fragment is left, copy to temp buffer. The remainder
+		 * will be appended in the next tsin_exchange() iteration.
+		 */
+		if (len > 0 && len < 188)
+			memcpy(&chan->tsin_buffer, buf, len);
+
 		return NULL;
 	}
 
diff --git a/drivers/media/pci/ngene/ngene.h b/drivers/media/pci/ngene/ngene.h
index 66d8eaa28549..01d9f1b58fcb 100644
--- a/drivers/media/pci/ngene/ngene.h
+++ b/drivers/media/pci/ngene/ngene.h
@@ -732,6 +732,9 @@ struct ngene_channel {
 #endif
 
 	int running;
+
+	int tsin_offset;
+	u8  tsin_buffer[188];
 };
 
 
-- 
2.16.1

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

* Re: [PATCH v2 08/12] [media] ngene: deduplicate I2C adapter evaluation
  2018-02-25 12:31 ` [PATCH v2 08/12] [media] ngene: deduplicate I2C adapter evaluation Daniel Scheller
@ 2018-03-06 16:06   ` Mauro Carvalho Chehab
  2018-03-06 16:14     ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 16+ messages in thread
From: Mauro Carvalho Chehab @ 2018-03-06 16:06 UTC (permalink / raw)
  To: Daniel Scheller; +Cc: linux-media, mchehab

Em Sun, 25 Feb 2018 13:31:36 +0100
Daniel Scheller <d.scheller.oss@gmail.com> escreveu:

> From: Daniel Scheller <d.scheller@gmx.net>
> 
> The I2C adapter evaluation (based on chan->number) is duplicated at
> several places (tuner_attach_() functions, demod_attach_stv0900() and
> cineS2_probe()). Clean this up by wrapping that construct in a separate
> function which all users of that can pass the ngene_channel pointer and
> get the correct I2C adapter from.

This patch doesn't apply. 

Please rebase from this point at the top of the media tree.

PS.: Perhaps I ended by merging an older version of some of your
patches, as I noticed that some e-mails got lost either by me or
by patch work along those days.

> 
> Signed-off-by: Daniel Scheller <d.scheller@gmx.net>
> ---
>  drivers/media/pci/ngene/ngene-cards.c | 41 +++++++++++++----------------------
>  1 file changed, 15 insertions(+), 26 deletions(-)
> 
> diff --git a/drivers/media/pci/ngene/ngene-cards.c b/drivers/media/pci/ngene/ngene-cards.c
> index 00b100660784..dff55c7c9f86 100644
> --- a/drivers/media/pci/ngene/ngene-cards.c
> +++ b/drivers/media/pci/ngene/ngene-cards.c
> @@ -118,17 +118,25 @@ static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val)
>  /* Demod/tuner attachment ***************************************************/
>  /****************************************************************************/
>  
> +static struct i2c_adapter *i2c_adapter_from_chan(struct ngene_channel *chan)
> +{
> +	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
> +	if (chan->number < 2)
> +		return &chan->dev->channel[0].i2c_adapter;
> +
> +	return &chan->dev->channel[1].i2c_adapter;
> +}
> +
>  static int tuner_attach_stv6110(struct ngene_channel *chan)
>  {
>  	struct device *pdev = &chan->dev->pci_dev->dev;
> -	struct i2c_adapter *i2c;
> +	struct i2c_adapter *i2c = i2c_adapter_from_chan(chan);
>  	struct stv090x_config *feconf = (struct stv090x_config *)
>  		chan->dev->card_info->fe_config[chan->number];
>  	struct stv6110x_config *tunerconf = (struct stv6110x_config *)
>  		chan->dev->card_info->tuner_config[chan->number];
>  	const struct stv6110x_devctl *ctl;
>  
> -	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
>  	if (chan->number < 2)
>  		i2c = &chan->dev->channel[0].i2c_adapter;
>  	else
> @@ -158,16 +166,10 @@ static int tuner_attach_stv6110(struct ngene_channel *chan)
>  static int tuner_attach_stv6111(struct ngene_channel *chan)
>  {
>  	struct device *pdev = &chan->dev->pci_dev->dev;
> -	struct i2c_adapter *i2c;
> +	struct i2c_adapter *i2c = i2c_adapter_from_chan(chan);
>  	struct dvb_frontend *fe;
>  	u8 adr = 4 + ((chan->number & 1) ? 0x63 : 0x60);
>  
> -	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
> -	if (chan->number < 2)
> -		i2c = &chan->dev->channel[0].i2c_adapter;
> -	else
> -		i2c = &chan->dev->channel[1].i2c_adapter;
> -
>  	fe = dvb_attach(stv6111_attach, chan->fe, i2c, adr);
>  	if (!fe) {
>  		fe = dvb_attach(stv6111_attach, chan->fe, i2c, adr & ~4);
> @@ -197,10 +199,9 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
>  static int tuner_attach_tda18271(struct ngene_channel *chan)
>  {
>  	struct device *pdev = &chan->dev->pci_dev->dev;
> -	struct i2c_adapter *i2c;
> +	struct i2c_adapter *i2c = i2c_adapter_from_chan(chan);
>  	struct dvb_frontend *fe;
>  
> -	i2c = &chan->dev->channel[0].i2c_adapter;
>  	if (chan->fe->ops.i2c_gate_ctrl)
>  		chan->fe->ops.i2c_gate_ctrl(chan->fe, 1);
>  	fe = dvb_attach(tda18271c2dd_attach, chan->fe, i2c, 0x60);
> @@ -240,7 +241,7 @@ static int tuner_tda18212_ping(struct ngene_channel *chan,
>  static int tuner_attach_tda18212(struct ngene_channel *chan, u32 dmdtype)
>  {
>  	struct device *pdev = &chan->dev->pci_dev->dev;
> -	struct i2c_adapter *i2c;
> +	struct i2c_adapter *i2c = i2c_adapter_from_chan(chan);
>  	struct i2c_client *client;
>  	struct tda18212_config config = {
>  		.fe = chan->fe,
> @@ -262,12 +263,6 @@ static int tuner_attach_tda18212(struct ngene_channel *chan, u32 dmdtype)
>  	else
>  		board_info.addr = 0x60;
>  
> -	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
> -	if (chan->number < 2)
> -		i2c = &chan->dev->channel[0].i2c_adapter;
> -	else
> -		i2c = &chan->dev->channel[1].i2c_adapter;
> -
>  	/*
>  	 * due to a hardware quirk with the I2C gate on the stv0367+tda18212
>  	 * combo, the tda18212 must be probed by reading it's id _twice_ when
> @@ -320,7 +315,7 @@ static int tuner_attach_probe(struct ngene_channel *chan)
>  static int demod_attach_stv0900(struct ngene_channel *chan)
>  {
>  	struct device *pdev = &chan->dev->pci_dev->dev;
> -	struct i2c_adapter *i2c;
> +	struct i2c_adapter *i2c = i2c_adapter_from_chan(chan);
>  	struct stv090x_config *feconf = (struct stv090x_config *)
>  		chan->dev->card_info->fe_config[chan->number];
>  
> @@ -620,7 +615,7 @@ static int port_has_xo2(struct i2c_adapter *i2c, u8 *type, u8 *id)
>  static int cineS2_probe(struct ngene_channel *chan)
>  {
>  	struct device *pdev = &chan->dev->pci_dev->dev;
> -	struct i2c_adapter *i2c;
> +	struct i2c_adapter *i2c = i2c_adapter_from_chan(chan);
>  	struct stv090x_config *fe_conf;
>  	u8 buf[3];
>  	u8 xo2_type, xo2_id, xo2_demodtype;
> @@ -628,12 +623,6 @@ static int cineS2_probe(struct ngene_channel *chan)
>  	struct i2c_msg i2c_msg = { .flags = 0, .buf = buf };
>  	int rc;
>  
> -	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
> -	if (chan->number < 2)
> -		i2c = &chan->dev->channel[0].i2c_adapter;
> -	else
> -		i2c = &chan->dev->channel[1].i2c_adapter;
> -
>  	if (port_has_xo2(i2c, &xo2_type, &xo2_id)) {
>  		xo2_id >>= 2;
>  		dev_dbg(pdev, "XO2 on channel %d (type %d, id %d)\n",



Thanks,
Mauro

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

* Re: [PATCH v2 08/12] [media] ngene: deduplicate I2C adapter evaluation
  2018-03-06 16:06   ` Mauro Carvalho Chehab
@ 2018-03-06 16:14     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 16+ messages in thread
From: Mauro Carvalho Chehab @ 2018-03-06 16:14 UTC (permalink / raw)
  To: Daniel Scheller; +Cc: linux-media, mchehab

Em Tue, 6 Mar 2018 13:06:15 -0300
Mauro Carvalho Chehab <mchehab@kernel.org> escreveu:

> Em Sun, 25 Feb 2018 13:31:36 +0100
> Daniel Scheller <d.scheller.oss@gmail.com> escreveu:
> 
> > From: Daniel Scheller <d.scheller@gmx.net>
> > 
> > The I2C adapter evaluation (based on chan->number) is duplicated at
> > several places (tuner_attach_() functions, demod_attach_stv0900() and
> > cineS2_probe()). Clean this up by wrapping that construct in a separate
> > function which all users of that can pass the ngene_channel pointer and
> > get the correct I2C adapter from.
> 
> This patch doesn't apply. 

Forget that. Patch 7 was missing. After applying it, this one
merged OK.

> 
> Please rebase from this point at the top of the media tree.
> 
> PS.: Perhaps I ended by merging an older version of some of your
> patches, as I noticed that some e-mails got lost either by me or
> by patch work along those days.


> 
> > 
> > Signed-off-by: Daniel Scheller <d.scheller@gmx.net>
> > ---
> >  drivers/media/pci/ngene/ngene-cards.c | 41 +++++++++++++----------------------
> >  1 file changed, 15 insertions(+), 26 deletions(-)
> > 
> > diff --git a/drivers/media/pci/ngene/ngene-cards.c b/drivers/media/pci/ngene/ngene-cards.c
> > index 00b100660784..dff55c7c9f86 100644
> > --- a/drivers/media/pci/ngene/ngene-cards.c
> > +++ b/drivers/media/pci/ngene/ngene-cards.c
> > @@ -118,17 +118,25 @@ static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val)
> >  /* Demod/tuner attachment ***************************************************/
> >  /****************************************************************************/
> >  
> > +static struct i2c_adapter *i2c_adapter_from_chan(struct ngene_channel *chan)
> > +{
> > +	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
> > +	if (chan->number < 2)
> > +		return &chan->dev->channel[0].i2c_adapter;
> > +
> > +	return &chan->dev->channel[1].i2c_adapter;
> > +}
> > +
> >  static int tuner_attach_stv6110(struct ngene_channel *chan)
> >  {
> >  	struct device *pdev = &chan->dev->pci_dev->dev;
> > -	struct i2c_adapter *i2c;
> > +	struct i2c_adapter *i2c = i2c_adapter_from_chan(chan);
> >  	struct stv090x_config *feconf = (struct stv090x_config *)
> >  		chan->dev->card_info->fe_config[chan->number];
> >  	struct stv6110x_config *tunerconf = (struct stv6110x_config *)
> >  		chan->dev->card_info->tuner_config[chan->number];
> >  	const struct stv6110x_devctl *ctl;
> >  
> > -	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
> >  	if (chan->number < 2)
> >  		i2c = &chan->dev->channel[0].i2c_adapter;
> >  	else
> > @@ -158,16 +166,10 @@ static int tuner_attach_stv6110(struct ngene_channel *chan)
> >  static int tuner_attach_stv6111(struct ngene_channel *chan)
> >  {
> >  	struct device *pdev = &chan->dev->pci_dev->dev;
> > -	struct i2c_adapter *i2c;
> > +	struct i2c_adapter *i2c = i2c_adapter_from_chan(chan);
> >  	struct dvb_frontend *fe;
> >  	u8 adr = 4 + ((chan->number & 1) ? 0x63 : 0x60);
> >  
> > -	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
> > -	if (chan->number < 2)
> > -		i2c = &chan->dev->channel[0].i2c_adapter;
> > -	else
> > -		i2c = &chan->dev->channel[1].i2c_adapter;
> > -
> >  	fe = dvb_attach(stv6111_attach, chan->fe, i2c, adr);
> >  	if (!fe) {
> >  		fe = dvb_attach(stv6111_attach, chan->fe, i2c, adr & ~4);
> > @@ -197,10 +199,9 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
> >  static int tuner_attach_tda18271(struct ngene_channel *chan)
> >  {
> >  	struct device *pdev = &chan->dev->pci_dev->dev;
> > -	struct i2c_adapter *i2c;
> > +	struct i2c_adapter *i2c = i2c_adapter_from_chan(chan);
> >  	struct dvb_frontend *fe;
> >  
> > -	i2c = &chan->dev->channel[0].i2c_adapter;
> >  	if (chan->fe->ops.i2c_gate_ctrl)
> >  		chan->fe->ops.i2c_gate_ctrl(chan->fe, 1);
> >  	fe = dvb_attach(tda18271c2dd_attach, chan->fe, i2c, 0x60);
> > @@ -240,7 +241,7 @@ static int tuner_tda18212_ping(struct ngene_channel *chan,
> >  static int tuner_attach_tda18212(struct ngene_channel *chan, u32 dmdtype)
> >  {
> >  	struct device *pdev = &chan->dev->pci_dev->dev;
> > -	struct i2c_adapter *i2c;
> > +	struct i2c_adapter *i2c = i2c_adapter_from_chan(chan);
> >  	struct i2c_client *client;
> >  	struct tda18212_config config = {
> >  		.fe = chan->fe,
> > @@ -262,12 +263,6 @@ static int tuner_attach_tda18212(struct ngene_channel *chan, u32 dmdtype)
> >  	else
> >  		board_info.addr = 0x60;
> >  
> > -	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
> > -	if (chan->number < 2)
> > -		i2c = &chan->dev->channel[0].i2c_adapter;
> > -	else
> > -		i2c = &chan->dev->channel[1].i2c_adapter;
> > -
> >  	/*
> >  	 * due to a hardware quirk with the I2C gate on the stv0367+tda18212
> >  	 * combo, the tda18212 must be probed by reading it's id _twice_ when
> > @@ -320,7 +315,7 @@ static int tuner_attach_probe(struct ngene_channel *chan)
> >  static int demod_attach_stv0900(struct ngene_channel *chan)
> >  {
> >  	struct device *pdev = &chan->dev->pci_dev->dev;
> > -	struct i2c_adapter *i2c;
> > +	struct i2c_adapter *i2c = i2c_adapter_from_chan(chan);
> >  	struct stv090x_config *feconf = (struct stv090x_config *)
> >  		chan->dev->card_info->fe_config[chan->number];
> >  
> > @@ -620,7 +615,7 @@ static int port_has_xo2(struct i2c_adapter *i2c, u8 *type, u8 *id)
> >  static int cineS2_probe(struct ngene_channel *chan)
> >  {
> >  	struct device *pdev = &chan->dev->pci_dev->dev;
> > -	struct i2c_adapter *i2c;
> > +	struct i2c_adapter *i2c = i2c_adapter_from_chan(chan);
> >  	struct stv090x_config *fe_conf;
> >  	u8 buf[3];
> >  	u8 xo2_type, xo2_id, xo2_demodtype;
> > @@ -628,12 +623,6 @@ static int cineS2_probe(struct ngene_channel *chan)
> >  	struct i2c_msg i2c_msg = { .flags = 0, .buf = buf };
> >  	int rc;
> >  
> > -	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
> > -	if (chan->number < 2)
> > -		i2c = &chan->dev->channel[0].i2c_adapter;
> > -	else
> > -		i2c = &chan->dev->channel[1].i2c_adapter;
> > -
> >  	if (port_has_xo2(i2c, &xo2_type, &xo2_id)) {
> >  		xo2_id >>= 2;
> >  		dev_dbg(pdev, "XO2 on channel %d (type %d, id %d)\n",
> 
> 
> 
> Thanks,
> Mauro



Thanks,
Mauro

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

* Re: [PATCH v2 11/12] [media] ngene: move the tsin_exchange() stripcopy block into a function
  2018-02-25 12:31 ` [PATCH v2 11/12] [media] ngene: move the tsin_exchange() stripcopy block into a function Daniel Scheller
@ 2018-03-06 16:18   ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 16+ messages in thread
From: Mauro Carvalho Chehab @ 2018-03-06 16:18 UTC (permalink / raw)
  To: Daniel Scheller; +Cc: linux-media, mchehab

Em Sun, 25 Feb 2018 13:31:39 +0100
Daniel Scheller <d.scheller.oss@gmail.com> escreveu:

> From: Daniel Scheller <d.scheller@gmx.net>
> 
> Move the copy logic that will skip previously inserted TS NULL frames when
> moving data to the DVB ring buffers into an own function. This is done to
> not duplicate code all over the place with the following TS offset shift
> fixup patch.
> 
> Signed-off-by: Daniel Scheller <d.scheller@gmx.net>
> ---
>  drivers/media/pci/ngene/ngene-dvb.c | 48 +++++++++++++++++++++----------------
>  1 file changed, 27 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/media/pci/ngene/ngene-dvb.c b/drivers/media/pci/ngene/ngene-dvb.c
> index f71fd41c762c..6d72b9f69418 100644
> --- a/drivers/media/pci/ngene/ngene-dvb.c
> +++ b/drivers/media/pci/ngene/ngene-dvb.c
> @@ -123,6 +123,32 @@ static u32 overflow;
>  static u32 stripped;
>  #endif
>  
> +static inline void tsin_copy_stripped(struct ngene *dev, void *buf)
> +{
> +	if (memcmp(buf, fill_ts, sizeof(fill_ts)) != 0) {
> +		if (dvb_ringbuffer_free(&dev->tsin_rbuf) >= 188) {
> +			dvb_ringbuffer_write(&dev->tsin_rbuf, buf, 188);
> +			wake_up(&dev->tsin_rbuf.queue);
> +#ifdef DEBUG_CI_XFER
> +			ok++;
> +#endif
> +		}
> +#ifdef DEBUG_CI_XFER
> +		else
> +			overflow++;
> +#endif
> +	}
> +#ifdef DEBUG_CI_XFER
> +	else
> +		stripped++;
> +
> +	if (ok % 100 == 0 && overflow)
> +		dev_warn(&dev->pci_dev->dev,
> +			 "%s: ok %u overflow %u dropped %u\n",
> +			 __func__, ok, overflow, stripped);
> +#endif

Those blocks are ugly. Also, there's no Kconfig way to enable those
debug messages.

If they're meant only for your own consumption, just keep it
outside of upstream.

Otherwise, please change the logic in a way that it would
make the code harder to read/enable.

> +}
> +
>  void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
>  {
>  	struct ngene_channel *chan = priv;
> @@ -134,28 +160,8 @@ void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
>  
>  	if (dev->ci.en && chan->number == 2) {
>  		while (len >= 188) {
> -			if (memcmp(buf, fill_ts, sizeof fill_ts) != 0) {
> -				if (dvb_ringbuffer_free(&dev->tsin_rbuf) >= 188) {
> -					dvb_ringbuffer_write(&dev->tsin_rbuf, buf, 188);
> -					wake_up(&dev->tsin_rbuf.queue);
> -#ifdef DEBUG_CI_XFER
> -					ok++;
> -#endif
> -				}
> -#ifdef DEBUG_CI_XFER
> -				else
> -					overflow++;
> -#endif
> -			}
> -#ifdef DEBUG_CI_XFER
> -			else
> -				stripped++;
> +			tsin_copy_stripped(dev, buf);
>  
> -			if (ok % 100 == 0 && overflow)
> -				dev_warn(&dev->pci_dev->dev,
> -					 "%s: ok %u overflow %u dropped %u\n",
> -					 __func__, ok, overflow, stripped);
> -#endif
>  			buf += 188;
>  			len -= 188;
>  		}



Thanks,
Mauro

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

end of thread, other threads:[~2018-03-06 16:18 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-25 12:31 [PATCH v2 00/12] ngene-updates: Hardware support, TS buffer shift fix Daniel Scheller
2018-02-25 12:31 ` [PATCH v2 01/12] [media] ngene: add two additional PCI IDs Daniel Scheller
2018-02-25 12:31 ` [PATCH v2 02/12] [media] ngene: convert kernellog printing from printk() to dev_*() macros Daniel Scheller
2018-02-25 12:31 ` [PATCH v2 03/12] [media] ngene: use defines to identify the demod_type Daniel Scheller
2018-02-25 12:31 ` [PATCH v2 04/12] [media] ngene: support STV0367 DVB-C/T DuoFlex addons Daniel Scheller
2018-02-25 12:31 ` [PATCH v2 05/12] [media] ngene: add XO2 module support Daniel Scheller
2018-02-25 12:31 ` [PATCH v2 06/12] [media] ngene: add support for Sony CXD28xx-based DuoFlex modules Daniel Scheller
2018-02-25 12:31 ` [PATCH v2 07/12] [media] ngene: add support for DuoFlex S2 V4 addon modules Daniel Scheller
2018-02-25 12:31 ` [PATCH v2 08/12] [media] ngene: deduplicate I2C adapter evaluation Daniel Scheller
2018-03-06 16:06   ` Mauro Carvalho Chehab
2018-03-06 16:14     ` Mauro Carvalho Chehab
2018-02-25 12:31 ` [PATCH v2 09/12] [media] ngene: check for CXD2099AR presence before attaching Daniel Scheller
2018-02-25 12:31 ` [PATCH v2 10/12] [media] ngene: don't treat non-existing demods as error Daniel Scheller
2018-02-25 12:31 ` [PATCH v2 11/12] [media] ngene: move the tsin_exchange() stripcopy block into a function Daniel Scheller
2018-03-06 16:18   ` Mauro Carvalho Chehab
2018-02-25 12:31 ` [PATCH v2 12/12] [media] ngene: compensate for TS buffer offset shifts Daniel Scheller

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