linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/12] Add c8sectpfe LinuxDVB demux driver
@ 2015-06-24 15:10 Peter Griffin
  2015-06-24 15:10 ` [PATCH 01/12] ARM: DT: STi: stihxxx-b2120: Add pulse-width properties to ssc2 & ssc3 Peter Griffin
                   ` (11 more replies)
  0 siblings, 12 replies; 32+ messages in thread
From: Peter Griffin @ 2015-06-24 15:10 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, srinivas.kandagatla,
	maxime.coquelin, patrice.chotard, mchehab
  Cc: peter.griffin, lee.jones, hugues.fruchet, linux-media, devicetree

Hi Maruro,

This patchset adds support for a LinuxDVB demux driver for the
ST STB stih407 family SoC's. It is what I spoke to you about
when we met at ELC-E in Dusseldorf last year.

One advantage of having a upstream demux driver implementation for ST
SoC's is that it will be easier to add support and maintain existing support
for the ST demodulators and tuners which are upstream. As this driver allows
ST NIM daughter boards (which typically have a tuner/demod combination)
to be used with a upstream kernel.

This initial patchset adds support for the following demux HW called c8sectpfe: -
* Input Block HW
* HW PID filtering
* memdma engine (moves TS from sram to RAM)

The driver creates one Linux DVB adapter, and each tsin channel which is
described in DT has a set of LDVB dev nodes.

Currently the driver supports 7 tsin channels. This driver has been tested with
the stih407-b2120 board and stih410-b2120 reference design boards, and currently
we support the following DVB fronend cards:
 - STMicroelectronics DVB-T B2100A (STV0367 + TDA18212)
 - STMicroelectronics DVB-T STV0367 PLL board (STV0367 + DTT7546X)
 - STMicroelectronics DVB-S/S2 STV0903 + STV6110 + LNBP24 board

There are also some small changes to dvb-pll.c and stv0367.c to get these
NIM daughterboards working correctly.

regards,

Peter.

p.s. The series which adds pinctrl config used by this driver is
https://lkml.org/lkml/2015/6/10/377

Peter Griffin (12):
  ARM: DT: STi: stihxxx-b2120: Add pulse-width properties to ssc2 & ssc3
  [media] dvb-pll: Add support for THOMSON DTT7546X tuner.
  [media] stv0367: Refine i2c error trace to include i2c address
  [media] stv0367: Add support for 16Mhz reference clock
  [media] tsin: c8sectpfe: Add DT bindings documentation for c8sectpfe
    driver.
  ARM: DT: STi: STiH407: Add c8sectpfe LinuxDVB DT node.
  [media] tsin: c8sectpfe: STiH407/10 Linux DVB demux support
  [media] tsin: c8sectpfe: Add LDVB helper functions.
  [media] tsin: c8sectpfe: Add support for various ST NIM cards.
  [media] tsin: c8sectpfe: Add c8sectpfe debugfs support.
  [media] tsin: c8sectpfe: Add Kconfig and Makefile for the driver.
  MAINTAINERS: Add c8sectpfe driver directory to STi section

 .../bindings/media/stih407-c8sectpfe.txt           |   90 ++
 MAINTAINERS                                        |    1 +
 arch/arm/boot/dts/stihxxx-b2120.dtsi               |   60 +-
 drivers/media/Kconfig                              |    1 +
 drivers/media/Makefile                             |    1 +
 drivers/media/dvb-frontends/dvb-pll.c              |   74 +-
 drivers/media/dvb-frontends/dvb-pll.h              |    1 +
 drivers/media/dvb-frontends/stv0367.c              |   17 +-
 drivers/media/tsin/c8sectpfe/Kconfig               |   26 +
 drivers/media/tsin/c8sectpfe/Makefile              |   11 +
 drivers/media/tsin/c8sectpfe/c8sectpfe-common.c    |  266 +++++
 drivers/media/tsin/c8sectpfe/c8sectpfe-common.h    |   66 ++
 drivers/media/tsin/c8sectpfe/c8sectpfe-core.c      | 1105 ++++++++++++++++++++
 drivers/media/tsin/c8sectpfe/c8sectpfe-core.h      |  288 +++++
 drivers/media/tsin/c8sectpfe/c8sectpfe-debugfs.c   |  271 +++++
 drivers/media/tsin/c8sectpfe/c8sectpfe-debugfs.h   |   26 +
 drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.c       |  296 ++++++
 drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.h       |   20 +
 include/dt-bindings/media/c8sectpfe.h              |   14 +
 19 files changed, 2617 insertions(+), 17 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/media/stih407-c8sectpfe.txt
 create mode 100644 drivers/media/tsin/c8sectpfe/Kconfig
 create mode 100644 drivers/media/tsin/c8sectpfe/Makefile
 create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-common.c
 create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-common.h
 create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-core.c
 create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-core.h
 create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-debugfs.c
 create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-debugfs.h
 create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.c
 create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.h
 create mode 100644 include/dt-bindings/media/c8sectpfe.h

-- 
1.9.1


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

* [PATCH 01/12] ARM: DT: STi: stihxxx-b2120: Add pulse-width properties to ssc2 & ssc3
  2015-06-24 15:10 [PATCH 00/12] Add c8sectpfe LinuxDVB demux driver Peter Griffin
@ 2015-06-24 15:10 ` Peter Griffin
  2015-06-24 15:11 ` [PATCH 02/12] [media] dvb-pll: Add support for THOMSON DTT7546X tuner Peter Griffin
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 32+ messages in thread
From: Peter Griffin @ 2015-06-24 15:10 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, srinivas.kandagatla,
	maxime.coquelin, patrice.chotard, mchehab
  Cc: peter.griffin, lee.jones, hugues.fruchet, linux-media, devicetree

Adding these properties makes the I2C bus to the demodulators much
more reliable, and we no longer suffer from I2C errors when tuning.

Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
---
 arch/arm/boot/dts/stihxxx-b2120.dtsi | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/stihxxx-b2120.dtsi b/arch/arm/boot/dts/stihxxx-b2120.dtsi
index c1d8590..1f27589 100644
--- a/arch/arm/boot/dts/stihxxx-b2120.dtsi
+++ b/arch/arm/boot/dts/stihxxx-b2120.dtsi
@@ -27,12 +27,18 @@
 			};
 		};
 
-		i2c@9842000 {
+		ssc2: i2c@9842000 {
 			status = "okay";
+			clock-frequency = <100000>;
+			st,i2c-min-scl-pulse-width-us = <0>;
+			st,i2c-min-sda-pulse-width-us = <5>;
 		};
 
-		i2c@9843000 {
+		ssc3: i2c@9843000 {
 			status = "okay";
+			clock-frequency = <100000>;
+			st,i2c-min-scl-pulse-width-us = <0>;
+			st,i2c-min-sda-pulse-width-us = <5>;
 		};
 
 		i2c@9844000 {
-- 
1.9.1


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

* [PATCH 02/12] [media] dvb-pll: Add support for THOMSON DTT7546X tuner.
  2015-06-24 15:10 [PATCH 00/12] Add c8sectpfe LinuxDVB demux driver Peter Griffin
  2015-06-24 15:10 ` [PATCH 01/12] ARM: DT: STi: stihxxx-b2120: Add pulse-width properties to ssc2 & ssc3 Peter Griffin
@ 2015-06-24 15:11 ` Peter Griffin
  2015-06-25  1:17   ` Joe Perches
  2015-07-22 17:10   ` Mauro Carvalho Chehab
  2015-06-24 15:11 ` [PATCH 03/12] [media] stv0367: Refine i2c error trace to include i2c address Peter Griffin
                   ` (9 subsequent siblings)
  11 siblings, 2 replies; 32+ messages in thread
From: Peter Griffin @ 2015-06-24 15:11 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, srinivas.kandagatla,
	maxime.coquelin, patrice.chotard, mchehab
  Cc: peter.griffin, lee.jones, hugues.fruchet, linux-media, devicetree

This is used in conjunction with the STV0367 demodulator on
the STV0367-NIM-V1.0 NIM card which can be used with the STi
STB SoC's.

This tuner has a fifth register, so some changes have been made
to accommodate this.

Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
---
 drivers/media/dvb-frontends/dvb-pll.c | 74 +++++++++++++++++++++++++++++------
 drivers/media/dvb-frontends/dvb-pll.h |  1 +
 2 files changed, 64 insertions(+), 11 deletions(-)

diff --git a/drivers/media/dvb-frontends/dvb-pll.c b/drivers/media/dvb-frontends/dvb-pll.c
index 6d8fe88..f7381c7 100644
--- a/drivers/media/dvb-frontends/dvb-pll.c
+++ b/drivers/media/dvb-frontends/dvb-pll.c
@@ -141,6 +141,35 @@ static struct dvb_pll_desc dvb_pll_thomson_dtt7520x = {
 	},
 };
 
+static void thomson_dtt7546x_bw(struct dvb_frontend *fe, u8 *buf)
+{
+	/* set CB2 reg - set ATC, XTO */
+	buf[4] = 0xc3;
+}
+
+static struct dvb_pll_desc dvb_pll_thomson_dtt7546x = {
+	.name  = "Thomson dtt7546x",
+	.min   = 44250000,
+	.max   = 863250000,
+	.set   = thomson_dtt7546x_bw,
+	.iffreq= 36166667,
+	.count = 12,
+	.entries = {
+		{  121000000, 166667, 0x88, 0x01 },
+		{  141000000, 166667, 0x88, 0x41 },
+		{  166000000, 166667, 0x88, 0x81 },
+		{  182000000, 166667, 0x88, 0xc1 },
+		{  286000000, 166667, 0x88, 0x02 },
+		{  386000000, 166667, 0x88, 0x42 },
+		{  446000000, 166667, 0x88, 0x82 },
+		{  466000000, 166667, 0x88, 0xc2 },
+		{  506000000, 166667, 0x88, 0x08 },
+		{  761000000, 166667, 0x88, 0x48 },
+		{  846000000, 166667, 0x88, 0x88 },
+		{  905000000, 166667, 0x88, 0xc8 },
+	},
+};
+
 static struct dvb_pll_desc dvb_pll_lg_z201 = {
 	.name  = "LG z201",
 	.min   = 174000000,
@@ -537,6 +566,7 @@ static struct dvb_pll_desc dvb_pll_alps_tdee4 = {
 static struct dvb_pll_desc *pll_list[] = {
 	[DVB_PLL_UNDEFINED]              = NULL,
 	[DVB_PLL_THOMSON_DTT7579]        = &dvb_pll_thomson_dtt7579,
+	[DVB_PLL_THOMSON_DTT7546X]       = &dvb_pll_thomson_dtt7546x,
 	[DVB_PLL_THOMSON_DTT759X]        = &dvb_pll_thomson_dtt759x,
 	[DVB_PLL_THOMSON_DTT7520X]       = &dvb_pll_thomson_dtt7520x,
 	[DVB_PLL_LG_Z201]                = &dvb_pll_lg_z201,
@@ -561,7 +591,7 @@ static struct dvb_pll_desc *pll_list[] = {
 /* code                                                        */
 
 static int dvb_pll_configure(struct dvb_frontend *fe, u8 *buf,
-			     const u32 frequency)
+			const u32 frequency, const u32 len)
 {
 	struct dvb_pll_priv *priv = fe->tuner_priv;
 	struct dvb_pll_desc *desc = priv->pll_desc;
@@ -593,11 +623,15 @@ static int dvb_pll_configure(struct dvb_frontend *fe, u8 *buf,
 	if (desc->set)
 		desc->set(fe, buf);
 
-	if (debug)
-		printk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n",
-		       desc->name, div, buf[0], buf[1], buf[2], buf[3]);
+	if (debug) {
+		printk(KERN_DEBUG "pll: %s: div=%d | buf=", desc->name, div);
+		for (i = 0; i < len; i++)
+			printk(KERN_DEBUG "0x%02x,", buf[i]);
 
-	// calculate the frequency we set it to
+		printk(KERN_DEBUG "\n");
+	}
+
+	/* calculate the frequency we set it to */
 	return (div * desc->entries[i].stepsize) - desc->iffreq;
 }
 
@@ -634,21 +668,39 @@ static int dvb_pll_sleep(struct dvb_frontend *fe)
 	return -EINVAL;
 }
 
+static int dvb_pll_get_num_regs(struct dvb_pll_priv *priv)
+{
+	int num_regs = 4;
+
+	if (strncmp(priv->pll_desc->name, "Thomson dtt7546x", 16) == 0)
+		num_regs = 5;
+
+	return num_regs;
+}
+
 static int dvb_pll_set_params(struct dvb_frontend *fe)
 {
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	struct dvb_pll_priv *priv = fe->tuner_priv;
-	u8 buf[4];
-	struct i2c_msg msg =
-		{ .addr = priv->pll_i2c_address, .flags = 0,
-		  .buf = buf, .len = sizeof(buf) };
+	struct i2c_msg msg;
+	u8 *bufp;
 	int result;
 	u32 frequency = 0;
 
+	bufp = kzalloc(dvb_pll_get_num_regs(priv), GFP_KERNEL);
+
+	if (!bufp)
+		return -ENOMEM;
+
+	msg.addr = priv->pll_i2c_address;
+	msg.flags = 0;
+	msg.buf = bufp;
+	msg.len = dvb_pll_get_num_regs(priv);
+
 	if (priv->i2c == NULL)
 		return -EINVAL;
 
-	result = dvb_pll_configure(fe, buf, c->frequency);
+	result = dvb_pll_configure(fe, bufp, c->frequency, msg.len);
 	if (result < 0)
 		return result;
 	else
@@ -677,7 +729,7 @@ static int dvb_pll_calc_regs(struct dvb_frontend *fe,
 	if (buf_len < 5)
 		return -EINVAL;
 
-	result = dvb_pll_configure(fe, buf + 1, c->frequency);
+	result = dvb_pll_configure(fe, buf + 1, c->frequency, buf_len - 1);
 	if (result < 0)
 		return result;
 	else
diff --git a/drivers/media/dvb-frontends/dvb-pll.h b/drivers/media/dvb-frontends/dvb-pll.h
index bf9602a..f523f42 100644
--- a/drivers/media/dvb-frontends/dvb-pll.h
+++ b/drivers/media/dvb-frontends/dvb-pll.h
@@ -28,6 +28,7 @@
 #define DVB_PLL_SAMSUNG_TBMU24112      17
 #define DVB_PLL_TDEE4		       18
 #define DVB_PLL_THOMSON_DTT7520X       19
+#define DVB_PLL_THOMSON_DTT7546X       20
 
 /**
  * Attach a dvb-pll to the supplied frontend structure.
-- 
1.9.1


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

* [PATCH 03/12] [media] stv0367: Refine i2c error trace to include i2c address
  2015-06-24 15:10 [PATCH 00/12] Add c8sectpfe LinuxDVB demux driver Peter Griffin
  2015-06-24 15:10 ` [PATCH 01/12] ARM: DT: STi: stihxxx-b2120: Add pulse-width properties to ssc2 & ssc3 Peter Griffin
  2015-06-24 15:11 ` [PATCH 02/12] [media] dvb-pll: Add support for THOMSON DTT7546X tuner Peter Griffin
@ 2015-06-24 15:11 ` Peter Griffin
  2015-06-24 15:11 ` [PATCH 04/12] [media] stv0367: Add support for 16Mhz reference clock Peter Griffin
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 32+ messages in thread
From: Peter Griffin @ 2015-06-24 15:11 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, srinivas.kandagatla,
	maxime.coquelin, patrice.chotard, mchehab
  Cc: peter.griffin, lee.jones, hugues.fruchet, linux-media, devicetree

When using stv0367 demodulator with STi STB platforms,
we can have easily have four or more stv0367 demods running
in the system at one time.

As typically the b2120 reference design ships with a b2004a daughter
board, which can accept two dvb NIM cards, and each b2100A NIM
has 2x stv0367 demods and 2x NXPs tuner on it.

In such circumstances it is useful to print the i2c address
on error messages to know which one is failing due to I2C issues.

Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
---
 drivers/media/dvb-frontends/stv0367.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/media/dvb-frontends/stv0367.c b/drivers/media/dvb-frontends/stv0367.c
index b31ff26..c3b7e6c 100644
--- a/drivers/media/dvb-frontends/stv0367.c
+++ b/drivers/media/dvb-frontends/stv0367.c
@@ -791,11 +791,13 @@ int stv0367_writeregs(struct stv0367_state *state, u16 reg, u8 *data, int len)
 	memcpy(buf + 2, data, len);
 
 	if (i2cdebug)
-		printk(KERN_DEBUG "%s: %02x: %02x\n", __func__, reg, buf[2]);
+		printk(KERN_DEBUG "%s: [%02x] %02x: %02x\n", __func__,
+			state->config->demod_address, reg, buf[2]);
 
 	ret = i2c_transfer(state->i2c, &msg, 1);
 	if (ret != 1)
-		printk(KERN_ERR "%s: i2c write error!\n", __func__);
+		printk(KERN_ERR "%s: i2c write error! ([%02x] %02x: %02x)\n",
+			__func__, state->config->demod_address, reg, buf[2]);
 
 	return (ret != 1) ? -EREMOTEIO : 0;
 }
@@ -829,10 +831,12 @@ static u8 stv0367_readreg(struct stv0367_state *state, u16 reg)
 
 	ret = i2c_transfer(state->i2c, msg, 2);
 	if (ret != 2)
-		printk(KERN_ERR "%s: i2c read error\n", __func__);
+		printk(KERN_ERR "%s: i2c read error ([%02x] %02x: %02x)\n",
+			__func__, state->config->demod_address, reg, b1[0]);
 
 	if (i2cdebug)
-		printk(KERN_DEBUG "%s: %02x: %02x\n", __func__, reg, b1[0]);
+		printk(KERN_DEBUG "%s: [%02x] %02x: %02x\n", __func__,
+			state->config->demod_address, reg, b1[0]);
 
 	return b1[0];
 }
-- 
1.9.1


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

* [PATCH 04/12] [media] stv0367: Add support for 16Mhz reference clock
  2015-06-24 15:10 [PATCH 00/12] Add c8sectpfe LinuxDVB demux driver Peter Griffin
                   ` (2 preceding siblings ...)
  2015-06-24 15:11 ` [PATCH 03/12] [media] stv0367: Refine i2c error trace to include i2c address Peter Griffin
@ 2015-06-24 15:11 ` Peter Griffin
  2015-06-24 15:11 ` [PATCH 05/12] [media] tsin: c8sectpfe: Add DT bindings documentation for c8sectpfe driver Peter Griffin
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 32+ messages in thread
From: Peter Griffin @ 2015-06-24 15:11 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, srinivas.kandagatla,
	maxime.coquelin, patrice.chotard, mchehab
  Cc: peter.griffin, lee.jones, hugues.fruchet, linux-media, devicetree

The B2100A dvb NIM card from ST has 2x stv0367 demodulators
and 2x TDA18212 silicon tuners, with a 16Mhz crystal. To
get this working properly with the upstream driver we need
to add support for the 16Mhz reference clock.

Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
---
 drivers/media/dvb-frontends/stv0367.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/media/dvb-frontends/stv0367.c b/drivers/media/dvb-frontends/stv0367.c
index c3b7e6c..ad7cab7 100644
--- a/drivers/media/dvb-frontends/stv0367.c
+++ b/drivers/media/dvb-frontends/stv0367.c
@@ -1554,6 +1554,11 @@ static int stv0367ter_init(struct dvb_frontend *fe)
 
 	switch (state->config->xtal) {
 		/*set internal freq to 53.125MHz */
+	case 16000000:
+		stv0367_writereg(state, R367TER_PLLMDIV, 0x2);
+		stv0367_writereg(state, R367TER_PLLNDIV, 0x1b);
+		stv0367_writereg(state, R367TER_PLLSETUP, 0x18);
+		break;
 	case 25000000:
 		stv0367_writereg(state, R367TER_PLLMDIV, 0xa);
 		stv0367_writereg(state, R367TER_PLLNDIV, 0x55);
-- 
1.9.1


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

* [PATCH 05/12] [media] tsin: c8sectpfe: Add DT bindings documentation for c8sectpfe driver.
  2015-06-24 15:10 [PATCH 00/12] Add c8sectpfe LinuxDVB demux driver Peter Griffin
                   ` (3 preceding siblings ...)
  2015-06-24 15:11 ` [PATCH 04/12] [media] stv0367: Add support for 16Mhz reference clock Peter Griffin
@ 2015-06-24 15:11 ` Peter Griffin
  2015-06-24 15:11 ` [PATCH 06/12] ARM: DT: STi: STiH407: Add c8sectpfe LinuxDVB DT node Peter Griffin
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 32+ messages in thread
From: Peter Griffin @ 2015-06-24 15:11 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, srinivas.kandagatla,
	maxime.coquelin, patrice.chotard, mchehab
  Cc: peter.griffin, lee.jones, hugues.fruchet, linux-media, devicetree

This patch adds the DT bindings documentation for the c8sectpfe LinuxDVB
demux driver whose IP is in the STiH407 family silicon SoC's.

Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
---
 .../bindings/media/stih407-c8sectpfe.txt           | 90 ++++++++++++++++++++++
 include/dt-bindings/media/c8sectpfe.h              | 14 ++++
 2 files changed, 104 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/stih407-c8sectpfe.txt
 create mode 100644 include/dt-bindings/media/c8sectpfe.h

diff --git a/Documentation/devicetree/bindings/media/stih407-c8sectpfe.txt b/Documentation/devicetree/bindings/media/stih407-c8sectpfe.txt
new file mode 100644
index 0000000..1ed4b12
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/stih407-c8sectpfe.txt
@@ -0,0 +1,90 @@
+STMicroelectronics STi c8sectpfe binding
+============================================
+
+This document describes the c8sectpfe device bindings that is used to get transport
+stream data into the SoC on the TS pins, and into DDR for further processing.
+
+It is typically used in conjunction with one or more demodulator and tuner devices
+which converts from the RF to digital domain. Demodulators and tuners are usually
+located on an external DVB frontend card connected to SoC TS input pins.
+
+Currently 7 TS input (tsin) channels are supported on the stih407 family SoC.
+
+Required properties (controller (parent) node):
+- compatible	: Should be "stih407-c8sectpfe"
+
+- reg		: Address and length of register sets for each device in
+		  "reg-names"
+
+- reg-names	: The names of the register addresses corresponding to the
+		  registers filled in "reg":
+			- c8sectpfe: c8sectpfe registers
+			- c8sectpfe-ram: c8sectpfe internal sram
+
+- clocks	: phandle list of c8sectpfe clocks
+- clock-names	: should be "c8sectpfe"
+See: Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+- pinctrl-names	: a pinctrl state named tsin%d-serial or tsin%d-parallel (where %d is tsin-num)
+		   must be defined for each tsin child node.
+- pinctrl-0	: phandle referencing pin configuration for this tsin configuration
+See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
+
+
+Required properties (tsin (child) node):
+
+- tsin-num	: tsin id of the InputBlock (must be between 0 to 6)
+- i2c-bus	: phandle to the I2C bus DT node which the demodulators & tuners on this tsin channel are connected.
+- rst-gpio	: reset gpio for this tsin channel.
+
+Optional properties (tsin (child) node):
+
+- invert-ts-clk		: Bool property to control sense of ts input clock (data stored on falling edge of clk).
+- serial-not-parallel	: Bool property to configure input bus width (serial on ts_data<7>).
+- async-not-sync	: Bool property to control if data is received in asynchronous mode
+			   (all bits/bytes with ts_valid or ts_packet asserted are valid).
+
+- dvb-card		: Describes the NIM card connected to this tsin channel.
+
+Example:
+
+/* stih410 SoC b2120 + b2004a + stv0367-pll(NIMB) + stv0367-tda18212 (NIMA) DT example) */
+
+	c8sectpfe@08a20000 {
+		compatible = "st,stih407-c8sectpfe";
+		status = "okay";
+		reg = <0x08a20000 0x10000>, <0x08a00000 0x4000>;
+		reg-names = "stfe", "stfe-ram";
+		interrupts = <0 34 0>, <0 35 0>;
+		interrupt-names = "stfe-error-irq", "stfe-idle-irq";
+
+		pinctrl-names	= "tsin0-serial", "tsin0-parallel", "tsin3-serial",
+				"tsin4-serial", "tsin5-serial";
+
+		pinctrl-0	= <&pinctrl_tsin0_serial>;
+		pinctrl-1	= <&pinctrl_tsin0_parallel>;
+		pinctrl-2	= <&pinctrl_tsin3_serial>;
+		pinctrl-3	= <&pinctrl_tsin4_serial_alt3>;
+		pinctrl-4	= <&pinctrl_tsin5_serial_alt1>;
+
+		clocks = <&clk_s_c0_flexgen CLK_PROC_STFE>;
+		clock-names = "stfe";
+
+		/* tsin0 is TSA on NIMA */
+		tsin0: port@0 {
+			tsin-num		= <0>;
+			serial-not-parallel;
+			i2c-bus			= <&ssc2>;
+			rst-gpio		= <&pio15 4 0>;
+			dvb-card		= <STV0367_TDA18212_NIMA_1>;
+		};
+
+		/* tsin3 is TSB on NIMB */
+		tsin3: port@3 {
+			tsin-num		= <3>;
+			serial-not-parallel;
+			i2c-bus			= <&ssc3>;
+			rst-gpio		= <&pio15 7 0>;
+			dvb-card		= <STV0367_PLL_BOARD_NIMB>;
+		};
+	};
diff --git a/include/dt-bindings/media/c8sectpfe.h b/include/dt-bindings/media/c8sectpfe.h
new file mode 100644
index 0000000..45ad009
--- /dev/null
+++ b/include/dt-bindings/media/c8sectpfe.h
@@ -0,0 +1,14 @@
+#ifndef __DT_C8SECTPFE_H
+#define __DT_C8SECTPFE_H
+
+#define STV0367_PLL_BOARD_NIMA	0
+#define STV0367_PLL_BOARD_NIMB	1
+#define STV0367_TDA18212_NIMA_1	2
+#define STV0367_TDA18212_NIMA_2	3
+#define STV0367_TDA18212_NIMB_1	4
+#define STV0367_TDA18212_NIMB_2	5
+
+#define STV0903_6110_LNB24_NIMA	6
+#define STV0903_6110_LNB24_NIMB	7
+
+#endif /* __DT_C8SECTPFE_H */
-- 
1.9.1


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

* [PATCH 06/12] ARM: DT: STi: STiH407: Add c8sectpfe LinuxDVB DT node.
  2015-06-24 15:10 [PATCH 00/12] Add c8sectpfe LinuxDVB demux driver Peter Griffin
                   ` (4 preceding siblings ...)
  2015-06-24 15:11 ` [PATCH 05/12] [media] tsin: c8sectpfe: Add DT bindings documentation for c8sectpfe driver Peter Griffin
@ 2015-06-24 15:11 ` Peter Griffin
  2015-06-24 15:11 ` [PATCH 07/12] [media] tsin: c8sectpfe: STiH407/10 Linux DVB demux support Peter Griffin
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 32+ messages in thread
From: Peter Griffin @ 2015-06-24 15:11 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, srinivas.kandagatla,
	maxime.coquelin, patrice.chotard, mchehab
  Cc: peter.griffin, lee.jones, hugues.fruchet, linux-media, devicetree

This patch adds in the required DT node for the c8sectpfe
Linux DVB demux driver which allows the tsin channels
to be used on an upstream kernel.

Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
---
 arch/arm/boot/dts/stihxxx-b2120.dtsi | 50 ++++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/arch/arm/boot/dts/stihxxx-b2120.dtsi b/arch/arm/boot/dts/stihxxx-b2120.dtsi
index 1f27589..ece2ede 100644
--- a/arch/arm/boot/dts/stihxxx-b2120.dtsi
+++ b/arch/arm/boot/dts/stihxxx-b2120.dtsi
@@ -6,6 +6,10 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+
+#include <dt-bindings/clock/stih407-clks.h>
+#include <dt-bindings/media/c8sectpfe.h>
+
 / {
 	soc {
 		sbc_serial0: serial@9530000 {
@@ -72,5 +76,51 @@
 				st,osc-force-ext;
 			};
 		};
+
+		c8sectpfe@08a20000 {
+			compatible = "st,stih407-c8sectpfe";
+			status = "okay";
+			reg = <0x08a20000 0x10000>, <0x08a00000 0x4000>;
+			reg-names = "c8sectpfe", "c8sectpfe-ram";
+
+			interrupts = <0 34 0>, <0 35 0>;
+			interrupt-names = "c8sectpfe-error-irq",
+					  "c8sectpfe-idle-irq";
+
+			pinctrl-names	= "tsin0-serial", "tsin0-parallel",
+					  "tsin3-serial", "tsin4-serial",
+					  "tsin5-serial";
+
+			pinctrl-0	= <&pinctrl_tsin0_serial>;
+			pinctrl-1	= <&pinctrl_tsin0_parallel>;
+			pinctrl-2	= <&pinctrl_tsin3_serial>;
+			pinctrl-3	= <&pinctrl_tsin4_serial_alt3>;
+			pinctrl-4	= <&pinctrl_tsin5_serial_alt1>;
+
+			clocks = <&clk_s_c0_flexgen CLK_PROC_STFE>;
+			clock-names = "c8sectpfe";
+
+			/* tsin0 is TSA on NIMA */
+			tsin0: port@0 {
+
+				tsin-num = <0>;
+				serial-not-parallel;
+				i2c-bus = <&ssc2>;
+				rst-gpio = <&pio15 4 0>;
+
+				dvb-card = <STV0367_TDA18212_NIMA_1>;
+			};
+
+			/* tsin3 is TSB on NIMB */
+			tsin3: port@3 {
+
+				tsin-num = <3>;
+				serial-not-parallel;
+				i2c-bus = <&ssc3>;
+				rst-gpio = <&pio15 7 0>;
+
+				dvb-card = <STV0367_PLL_BOARD_NIMB>;
+			};
+		};
 	};
 };
-- 
1.9.1


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

* [PATCH 07/12] [media] tsin: c8sectpfe: STiH407/10 Linux DVB demux support
  2015-06-24 15:10 [PATCH 00/12] Add c8sectpfe LinuxDVB demux driver Peter Griffin
                   ` (5 preceding siblings ...)
  2015-06-24 15:11 ` [PATCH 06/12] ARM: DT: STi: STiH407: Add c8sectpfe LinuxDVB DT node Peter Griffin
@ 2015-06-24 15:11 ` Peter Griffin
  2015-07-22 21:46   ` Mauro Carvalho Chehab
  2015-06-24 15:11 ` [PATCH 08/12] [media] tsin: c8sectpfe: Add LDVB helper functions Peter Griffin
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 32+ messages in thread
From: Peter Griffin @ 2015-06-24 15:11 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, srinivas.kandagatla,
	maxime.coquelin, patrice.chotard, mchehab
  Cc: peter.griffin, lee.jones, hugues.fruchet, linux-media, devicetree

This patch adds support for the c8sectpfe input HW found on
STiH407/410 SoC's.

It currently supports the TS input block, memdma engine
and hw PID filtering blocks of the C8SECTPFE subsystem.

The driver creates one LinuxDVB adapter, and a
demux/dvr/frontend set of devices for each tsin channel
which is specificed in the DT. It has been tested with
multiple tsin channels tuned, locked, and grabbing TS
simultaneously.

Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
---
 drivers/media/tsin/c8sectpfe/c8sectpfe-core.c | 1105 +++++++++++++++++++++++++
 drivers/media/tsin/c8sectpfe/c8sectpfe-core.h |  288 +++++++
 2 files changed, 1393 insertions(+)
 create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-core.c
 create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-core.h

diff --git a/drivers/media/tsin/c8sectpfe/c8sectpfe-core.c b/drivers/media/tsin/c8sectpfe/c8sectpfe-core.c
new file mode 100644
index 0000000..fbbe323
--- /dev/null
+++ b/drivers/media/tsin/c8sectpfe/c8sectpfe-core.c
@@ -0,0 +1,1105 @@
+/*
+ * c8sectpfe-core.c - C8SECTPFE STi DVB driver
+ *
+ * Copyright (c) STMicroelectronics 2015
+ *
+ *   Author:Peter Bennett <peter.bennett@st.com>
+ *	    Peter Griffin <peter.griffin@linaro.org>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License as
+ *	published by the Free Software Foundation; either version 2 of
+ *	the License, or (at your option) any later version.
+ */
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/dvb/dmx.h>
+#include <linux/dvb/frontend.h>
+#include <linux/errno.h>
+#include <linux/firmware.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/usb.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/version.h>
+#include <linux/wait.h>
+
+#include "c8sectpfe-core.h"
+#include "c8sectpfe-common.h"
+#include "c8sectpfe-debugfs.h"
+#include "dmxdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#define FIRMWARE_MEMDMA "pti_memdma_h407.elf"
+MODULE_FIRMWARE(FIRMWARE_MEMDMA);
+
+#define PID_TABLE_SIZE 1024
+#define POLL_20_HZ_DIV 20 /* poll at 20 Hz */
+
+static int load_slim_core_fw(struct c8sectpfei *fei);
+
+#define TS_PKT_SIZE 188
+#define HEADER_SIZE (4)
+#define PACKET_SIZE (TS_PKT_SIZE+HEADER_SIZE)
+
+#define FEI_ALIGNMENT (32)
+/* hw requires minimum of 8*PACKET_SIZE and padded to 8byte boundary */
+#define FEI_BUFFER_SIZE (8*PACKET_SIZE*340)
+
+#define FIFO_LEN 1024
+
+static void c8sectpfe_timer_interrupt(unsigned long ac8sectpfei)
+{
+	struct c8sectpfei *fei = (struct c8sectpfei *)ac8sectpfei;
+	struct channel_info *channel;
+	int chan_num;
+
+	/* iterate through input block channels */
+	for (chan_num = 0; chan_num < fei->tsin_count; chan_num++) {
+		channel = fei->channel_data[chan_num];
+
+		/* is this descriptor initialised and TP enabled */
+		if (channel->irec && readl((void __iomem *)
+						&channel->irec->tp_enable))
+			tasklet_schedule(&channel->tsklet);
+	}
+
+	fei->timer.expires = jiffies + (HZ / POLL_20_HZ_DIV);
+	add_timer(&fei->timer);
+}
+
+static void channel_swdemux_tsklet(unsigned long data)
+{
+	struct channel_info *channel = (struct channel_info *)data;
+	struct c8sectpfei *fei = channel->fei;
+	struct tpentry *ptrblk;
+	unsigned long wp, rp;
+	int pos, num_packets, n, size;
+	u8 *buf;
+
+	BUG_ON(!channel);
+	BUG_ON(!channel->irec);
+
+	ptrblk = &channel->irec->ptr_data[0];
+
+	wp = readl((void __iomem *)&ptrblk->dma_bus_wp);
+	rp = readl((void __iomem *)&ptrblk->dma_bus_rp);
+
+	pos = rp - channel->back_buffer_busaddr;
+
+	/* has it wrapped */
+	if (wp < rp)
+		wp = channel->back_buffer_busaddr + FEI_BUFFER_SIZE;
+
+	size = wp - rp;
+	num_packets = size / PACKET_SIZE;
+
+	/* manage cache so data is visible to CPU */
+	dma_sync_single_for_cpu(fei->dev,
+				rp,
+				size,
+				DMA_FROM_DEVICE);
+
+	buf = (u8 *) channel->back_buffer_aligned;
+
+	dev_dbg(fei->dev,
+		"chan=%d channel=%p num_packets = %d, buf = %p, pos = 0x%x\n\t"
+		"rp=0x%lx, wp=0x%lx\n",
+		channel->tsin_id, channel, num_packets, buf, pos, rp, wp);
+
+	for (n = 0; n < num_packets; n++) {
+		dvb_dmx_swfilter_packets(
+			&fei->c8sectpfe[0]->
+				demux[channel->demux_mapping].dvb_demux,
+			&buf[pos], 1);
+
+		pos += PACKET_SIZE;
+	}
+
+	/* advance the read pointer */
+	if (wp == (channel->back_buffer_busaddr + FEI_BUFFER_SIZE))
+		writel(channel->back_buffer_busaddr,
+			(void __iomem *)&ptrblk->dma_bus_rp);
+	else
+		writel(wp, (void __iomem *)&ptrblk->dma_bus_rp);
+}
+
+static int c8sectpfe_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct dvb_demux *demux = dvbdmxfeed->demux;
+	struct stdemux *stdemux = (struct stdemux *)demux->priv;
+	struct c8sectpfei *fei = stdemux->c8sectpfei;
+	struct channel_info *channel;
+	struct tpentry *ptrblk;
+	u32 tmp;
+	unsigned long *bitmap;
+
+	switch (dvbdmxfeed->type) {
+	case DMX_TYPE_TS:
+		break;
+	case DMX_TYPE_SEC:
+		break;
+	default:
+		dev_err(fei->dev, "%s:%d Error bailing\n"
+			, __func__, __LINE__);
+		return -EINVAL;
+	}
+
+	if (dvbdmxfeed->type == DMX_TYPE_TS) {
+		switch (dvbdmxfeed->pes_type) {
+		case DMX_PES_VIDEO:
+		case DMX_PES_AUDIO:
+		case DMX_PES_TELETEXT:
+		case DMX_PES_PCR:
+		case DMX_PES_OTHER:
+			break;
+		default:
+			dev_err(fei->dev, "%s:%d Error bailing\n"
+				, __func__, __LINE__);
+			return -EINVAL;
+		}
+	}
+
+	mutex_lock(&fei->lock);
+
+	channel = fei->channel_data[stdemux->tsin_index];
+
+	bitmap = (unsigned long *) channel->pid_buffer_aligned;
+
+	bitmap_set(bitmap, dvbdmxfeed->pid, 1);
+
+	/* manage cache so PID bitmap is visible to HW */
+	dma_sync_single_for_device(fei->dev,
+					channel->pid_buffer_busaddr,
+					PID_TABLE_SIZE,
+					DMA_TO_DEVICE);
+
+	channel->active = 1;
+
+	if (fei->global_feed_count == 0) {
+		fei->timer.expires = jiffies + (HZ / POLL_20_HZ_DIV);
+		add_timer(&fei->timer);
+	}
+
+	if (stdemux->running_feed_count == 0) {
+
+		dev_dbg(fei->dev, "Starting channel=%p\n", channel);
+
+		tasklet_init(&channel->tsklet, channel_swdemux_tsklet,
+			     (unsigned long) channel);
+
+		/* Reset the internal inputblock sram pointers */
+		writel(channel->fifo,
+			fei->io + C8SECTPFE_IB_BUFF_STRT(channel->tsin_id));
+		writel(channel->fifo + FIFO_LEN - 1,
+			fei->io + C8SECTPFE_IB_BUFF_END(channel->tsin_id));
+
+		writel(channel->fifo,
+			fei->io + C8SECTPFE_IB_READ_PNT(channel->tsin_id));
+		writel(channel->fifo,
+			fei->io + C8SECTPFE_IB_WRT_PNT(channel->tsin_id));
+
+
+		/* reset read / write memdma ptrs for this channel */
+		ptrblk = &channel->irec->ptr_data[0];
+		writel(channel->back_buffer_busaddr,
+			(void __iomem *)&ptrblk->dma_busbase);
+
+		tmp = channel->back_buffer_busaddr + FEI_BUFFER_SIZE - 1;
+		writel(tmp, (void __iomem *)&ptrblk->dma_bustop);
+
+		writel(channel->back_buffer_busaddr,
+			(void __iomem *)&ptrblk->dma_bus_wp);
+
+		/* Issue a reset and enable InputBlock */
+		writel(C8SECTPFE_SYS_ENABLE | C8SECTPFE_SYS_RESET
+			, fei->io + C8SECTPFE_IB_SYS(channel->tsin_id));
+
+		/* and enable the tp */
+		writel(0x1, (void __iomem *)&channel->irec->tp_enable);
+
+		dev_dbg(fei->dev, "%s:%d Starting DMA feed on stdemux=%p\n"
+			, __func__, __LINE__, stdemux);
+	}
+
+	stdemux->running_feed_count++;
+	fei->global_feed_count++;
+
+	mutex_unlock(&fei->lock);
+
+	return 0;
+}
+
+static int c8sectpfe_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+
+	struct dvb_demux *demux = dvbdmxfeed->demux;
+	struct stdemux *stdemux = (struct stdemux *)demux->priv;
+	struct c8sectpfei *fei = stdemux->c8sectpfei;
+	struct channel_info *channel;
+	struct tpentry *ptrblk;
+	int idlereq;
+	u32 tmp;
+	int ret;
+	unsigned long *bitmap;
+
+	mutex_lock(&fei->lock);
+
+	channel = fei->channel_data[stdemux->tsin_index];
+
+	bitmap = (unsigned long *) channel->pid_buffer_aligned;
+	bitmap_clear(bitmap, dvbdmxfeed->pid, 1);
+
+	/* manage cache so data is visible to HW */
+	dma_sync_single_for_device(fei->dev,
+					channel->pid_buffer_busaddr,
+					PID_TABLE_SIZE,
+					DMA_TO_DEVICE);
+
+	if (--stdemux->running_feed_count == 0) {
+
+		channel = fei->channel_data[stdemux->tsin_index];
+		ptrblk = &channel->irec->ptr_data[0];
+
+		/* TP re-configuration on page 168 */
+
+		/* disable IB (prevents more TS data going to memdma) */
+		writel(0, fei->io + C8SECTPFE_IB_SYS(channel->tsin_id));
+
+		/* disable this channels descriptor */
+		writel(0, (void __iomem *)&channel->irec->tp_enable);
+
+		tasklet_disable(&channel->tsklet);
+
+		/* now request memdma channel goes idle */
+		idlereq = (1 << channel->tsin_id) | IDLEREQ;
+		writel(idlereq, fei->io + DMA_IDLE_REQ);
+
+		/* wait for idle irq handler to signal completion */
+		ret = wait_for_completion_timeout(&channel->idle_completion,
+						msecs_to_jiffies(100));
+
+		if (ret == 0)
+			dev_warn(fei->dev,
+				"Timeout waiting for idle irq on tsin%d\n",
+				channel->tsin_id);
+
+		reinit_completion(&channel->idle_completion);
+
+		/* reset read / write ptrs for this channel */
+		writel(channel->back_buffer_busaddr,
+			(void __iomem *)&ptrblk->dma_busbase);
+
+		tmp = channel->back_buffer_busaddr + FEI_BUFFER_SIZE - 1;
+		writel(tmp, (void __iomem *)&ptrblk->dma_bustop);
+
+		writel(channel->back_buffer_busaddr,
+			(void __iomem *)&ptrblk->dma_bus_wp);
+
+		dev_dbg(fei->dev,
+			"%s:%d stopping DMA feed on stdemux=%p channel=%d\n",
+			__func__, __LINE__, stdemux, channel->tsin_id);
+
+		/* turn off all PIDS in the bitmap*/
+		memset((void *)channel->pid_buffer_aligned
+			, 0x00, PID_TABLE_SIZE);
+
+		/* manage cache so data is visible to HW */
+		dma_sync_single_for_device(fei->dev,
+					channel->pid_buffer_busaddr,
+					PID_TABLE_SIZE,
+					DMA_TO_DEVICE);
+
+		channel->active = 0;
+	}
+
+	if (--fei->global_feed_count == 0) {
+		dev_dbg(fei->dev, "%s:%d global_feed_count=%d\n"
+			, __func__, __LINE__, fei->global_feed_count);
+
+		del_timer(&fei->timer);
+	}
+
+	mutex_unlock(&fei->lock);
+
+	return 0;
+}
+
+static struct channel_info *find_channel(struct c8sectpfei *fei, int tsin_num)
+{
+	int i;
+
+	for (i = 0; i < C8SECTPFE_MAXCHANNEL; i++) {
+		if (!fei->channel_data[i])
+			continue;
+
+		if (fei->channel_data[i]->tsin_id == tsin_num)
+			return fei->channel_data[i];
+	}
+
+	return NULL;
+}
+
+static void c8sectpfe_getconfig(struct c8sectpfei *fei)
+{
+	struct c8sectpfe_hw *hw = &fei->hw_stats;
+
+	hw->num_ib = readl(fei->io + SYS_CFG_NUM_IB);
+	hw->num_mib = readl(fei->io + SYS_CFG_NUM_MIB);
+	hw->num_swts = readl(fei->io + SYS_CFG_NUM_SWTS);
+	hw->num_tsout = readl(fei->io + SYS_CFG_NUM_TSOUT);
+	hw->num_ccsc = readl(fei->io + SYS_CFG_NUM_CCSC);
+	hw->num_ram = readl(fei->io + SYS_CFG_NUM_RAM);
+	hw->num_tp = readl(fei->io + SYS_CFG_NUM_TP);
+
+	dev_info(fei->dev, "C8SECTPFE hw supports the following:\n");
+	dev_info(fei->dev, "Input Blocks: %d\n", hw->num_ib);
+	dev_info(fei->dev, "Merged Input Blocks: %d\n", hw->num_mib);
+	dev_info(fei->dev, "Software Transport Stream Inputs: %d\n"
+				, hw->num_swts);
+	dev_info(fei->dev, "Transport Stream Output: %d\n", hw->num_tsout);
+	dev_info(fei->dev, "Cable Card Converter: %d\n", hw->num_ccsc);
+	dev_info(fei->dev, "RAMs supported by C8SECTPFE: %d\n", hw->num_ram);
+	dev_info(fei->dev, "Tango TPs supported by C8SECTPFE: %d\n"
+			, hw->num_tp);
+}
+
+static irqreturn_t c8sectpfe_idle_irq_handler(int irq, void *priv)
+{
+	struct c8sectpfei *fei = priv;
+	struct channel_info *chan;
+	int bit;
+	unsigned long tmp = readl(fei->io + DMA_IDLE_REQ);
+
+	/* page 168 of functional spec: Clear the idle request
+	   by writing 0 to the C8SECTPFE_DMA_IDLE_REQ register. */
+
+	/* signal idle completion */
+	for_each_set_bit(bit, &tmp, fei->hw_stats.num_ib) {
+
+		chan = find_channel(fei, bit);
+
+		if (chan)
+			complete(&chan->idle_completion);
+	}
+
+	writel(0, fei->io + DMA_IDLE_REQ);
+
+	return IRQ_HANDLED;
+}
+
+
+static void free_input_block(struct c8sectpfei *fei, struct channel_info *tsin)
+{
+	BUG_ON(!fei);
+	BUG_ON(!tsin);
+
+	if (tsin->back_buffer_busaddr)
+		if (!dma_mapping_error(fei->dev, tsin->back_buffer_busaddr))
+			dma_unmap_single(fei->dev, tsin->back_buffer_busaddr,
+				FEI_BUFFER_SIZE, DMA_BIDIRECTIONAL);
+
+	kfree(tsin->back_buffer_start);
+
+	if (tsin->pid_buffer_busaddr)
+		if (!dma_mapping_error(fei->dev, tsin->pid_buffer_busaddr))
+			dma_unmap_single(fei->dev, tsin->pid_buffer_busaddr,
+				PID_TABLE_SIZE, DMA_BIDIRECTIONAL);
+
+	kfree(tsin->pid_buffer_start);
+}
+
+#define MAX_NAME 20
+
+static int configure_input_block(struct c8sectpfei *fei,
+				struct channel_info *tsin)
+{
+	int ret;
+	u32 tmp = 0;
+	struct tpentry *ptrblk;
+	char tsin_pin_name[MAX_NAME];
+
+	BUG_ON(!fei);
+	BUG_ON(!tsin);
+
+	dev_dbg(fei->dev, "%s:%d Configuring channel=%p tsin=%d\n"
+		, __func__, __LINE__, tsin, tsin->tsin_id);
+
+	init_completion(&tsin->idle_completion);
+
+	tsin->back_buffer_start = kzalloc(FEI_BUFFER_SIZE +
+					FEI_ALIGNMENT, GFP_KERNEL);
+
+	if (!tsin->back_buffer_start) {
+		ret = -ENOMEM;
+		goto err_unmap;
+	}
+
+	/* Ensure backbuffer is 32byte aligned */
+	tsin->back_buffer_aligned = tsin->back_buffer_start
+		+ FEI_ALIGNMENT;
+
+	tsin->back_buffer_aligned = (void *)
+		(((uintptr_t) tsin->back_buffer_aligned) & ~0x1F);
+
+	tsin->back_buffer_busaddr = dma_map_single(fei->dev,
+					(void *)tsin->back_buffer_aligned,
+					FEI_BUFFER_SIZE,
+					DMA_BIDIRECTIONAL);
+
+	if (dma_mapping_error(fei->dev, tsin->back_buffer_busaddr)) {
+		dev_err(fei->dev, "failed to map back_buffer\n");
+		ret = -EFAULT;
+		goto err_unmap;
+	}
+
+	/*
+	 * The pid buffer can be configured (in hw) for byte or bit
+	 * per pid. By powers of deduction we conclude stih407 family
+	 * is configured (at SoC design stage) for bit per pid.
+	 */
+	tsin->pid_buffer_start = kzalloc(2048, GFP_KERNEL);
+
+	if (!tsin->pid_buffer_start) {
+		ret = -ENOMEM;
+		goto err_unmap;
+	}
+
+	/*
+	 * PID buffer needs to be aligned to size of the pid table
+	 * which at bit per pid is 1024 bytes (8192 pids / 8).
+	 * PIDF_BASE register enforces this alignment when writing
+	 * the register.
+	 */
+
+	tsin->pid_buffer_aligned = tsin->pid_buffer_start +
+		PID_TABLE_SIZE;
+
+	tsin->pid_buffer_aligned = (void *)
+		(((uintptr_t) tsin->pid_buffer_aligned) & ~0x3ff);
+
+	tsin->pid_buffer_busaddr = dma_map_single(fei->dev,
+						tsin->pid_buffer_aligned,
+						PID_TABLE_SIZE,
+						DMA_BIDIRECTIONAL);
+
+	if (dma_mapping_error(fei->dev, tsin->pid_buffer_busaddr)) {
+		dev_err(fei->dev, "failed to map pid_bitmap\n");
+		ret = -EFAULT;
+		goto err_unmap;
+	}
+
+	/* manage cache so pid bitmap is visible to HW */
+	dma_sync_single_for_device(fei->dev,
+				tsin->pid_buffer_busaddr,
+				PID_TABLE_SIZE,
+				DMA_TO_DEVICE);
+
+	snprintf(tsin_pin_name, MAX_NAME, "tsin%d-%s", tsin->tsin_id,
+		(tsin->serial_not_parallel ? "serial" : "parallel"));
+
+	tsin->pstate = pinctrl_lookup_state(fei->pinctrl, tsin_pin_name);
+	if (IS_ERR(tsin->pstate)) {
+		dev_err(fei->dev, "%s: pinctrl_lookup_state couldn't find %s state\n"
+			, __func__, tsin_pin_name);
+		ret = PTR_ERR(tsin->pstate);
+		goto err_unmap;
+	}
+
+	ret = pinctrl_select_state(fei->pinctrl, tsin->pstate);
+
+	if (ret) {
+		dev_err(fei->dev, "%s: pinctrl_select_state failed\n"
+			, __func__);
+		goto err_unmap;
+	}
+
+	/* Enable this input block */
+	tmp = readl(fei->io + SYS_INPUT_CLKEN);
+	tmp |= BIT(tsin->tsin_id);
+	writel(tmp, fei->io + SYS_INPUT_CLKEN);
+
+	if (tsin->serial_not_parallel)
+		tmp |= C8SECTPFE_SERIAL_NOT_PARALLEL;
+
+	if (tsin->invert_ts_clk)
+		tmp |= C8SECTPFE_INVERT_TSCLK;
+
+	if (tsin->async_not_sync)
+		tmp |= C8SECTPFE_ASYNC_NOT_SYNC;
+
+	tmp |= C8SECTPFE_ALIGN_BYTE_SOP | C8SECTPFE_BYTE_ENDIANNESS_MSB;
+
+	writel(tmp, fei->io + C8SECTPFE_IB_IP_FMT_CFG(tsin->tsin_id));
+
+	writel(C8SECTPFE_SYNC(0x9) |
+		C8SECTPFE_DROP(0x9) |
+		C8SECTPFE_TOKEN(0x47),
+		fei->io + C8SECTPFE_IB_SYNCLCKDRP_CFG(tsin->tsin_id));
+
+	writel(TS_PKT_SIZE, fei->io + C8SECTPFE_IB_PKT_LEN(tsin->tsin_id));
+
+	/* Place the FIFO's at the end of the irec descriptors */
+
+	tsin->fifo = (tsin->tsin_id * FIFO_LEN);
+
+	writel(tsin->fifo, fei->io + C8SECTPFE_IB_BUFF_STRT(tsin->tsin_id));
+	writel(tsin->fifo + FIFO_LEN - 1,
+		fei->io + C8SECTPFE_IB_BUFF_END(tsin->tsin_id));
+
+	writel(tsin->fifo, fei->io + C8SECTPFE_IB_READ_PNT(tsin->tsin_id));
+	writel(tsin->fifo, fei->io + C8SECTPFE_IB_WRT_PNT(tsin->tsin_id));
+
+	writel(tsin->pid_buffer_busaddr,
+		fei->io + PIDF_BASE(tsin->tsin_id));
+
+	dev_dbg(fei->dev, "chan=%d PIDF_BASE=0x%x pid_bus_addr=0x%x\n",
+		tsin->tsin_id, readl(fei->io + PIDF_BASE(tsin->tsin_id)),
+		tsin->pid_buffer_busaddr);
+
+	/* Configure and enable HW PID filtering */
+
+	/*
+	 * The PID value is created by assembling the first 8 bytes of
+	 * the TS packet into a 64-bit word in big-endian format. A
+	 * slice of that 64-bit word is taken from
+	 * (PID_OFFSET+PID_NUM_BITS-1) to PID_OFFSET.
+	 */
+	tmp = (C8SECTPFE_PID_ENABLE | C8SECTPFE_PID_NUMBITS(13)
+		| C8SECTPFE_PID_OFFSET(40));
+
+	writel(tmp, fei->io + C8SECTPFE_IB_PID_SET(tsin->tsin_id));
+
+	dev_dbg(fei->dev, "chan=%d setting wp: %d, rp: %d, buf: %d-%d\n",
+		tsin->tsin_id,
+		readl(fei->io + C8SECTPFE_IB_WRT_PNT(tsin->tsin_id)),
+		readl(fei->io + C8SECTPFE_IB_READ_PNT(tsin->tsin_id)),
+		readl(fei->io + C8SECTPFE_IB_BUFF_STRT(tsin->tsin_id)),
+		readl(fei->io + C8SECTPFE_IB_BUFF_END(tsin->tsin_id)));
+
+	/*
+	 * Base address of pointer record block relative to
+	 * base address of DMEM
+	 */
+	fei->irec = fei->io + DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET +
+			readl(fei->io + DMA_PTRREC_BASE);
+
+	tsin->irec = fei->irec += tsin->tsin_id;
+
+	ptrblk = &tsin->irec->ptr_data[0];
+
+	writel(tsin->fifo,
+		(void __iomem *)&tsin->irec->dma_membase);
+
+	writel(tsin->fifo + FIFO_LEN - 1,
+		(void __iomem *)&tsin->irec->dma_memtop);
+
+	writel((188 + 7)&~7,
+		(void __iomem *)&tsin->irec->dma_ts_pktsize);
+
+	writel(0x1, (void __iomem *)&tsin->irec->tp_enable);
+
+	/* read/write pointers with physical bus address */
+	writel(tsin->back_buffer_busaddr,
+		(void __iomem *)&ptrblk->dma_busbase);
+
+	tmp = tsin->back_buffer_busaddr + FEI_BUFFER_SIZE - 1;
+	writel(tmp, (void __iomem *)&ptrblk->dma_bustop);
+
+	writel(tsin->back_buffer_busaddr,
+		(void __iomem *)&ptrblk->dma_bus_wp);
+
+	writel(tsin->back_buffer_busaddr,
+		(void __iomem *)&ptrblk->dma_bus_rp);
+
+	/* initialize tasklet */
+	tasklet_init(&tsin->tsklet, channel_swdemux_tsklet,
+		(unsigned long) tsin);
+
+	return 0;
+
+err_unmap:
+	free_input_block(fei, tsin);
+	return ret;
+}
+
+static irqreturn_t c8sectpfe_error_irq_handler(int irq, void *priv)
+{
+	struct c8sectpfei *fei = priv;
+
+	dev_err(fei->dev, "%s: error handling not yet implemented\n"
+		, __func__);
+
+	/*
+	 * TODO FIXME we should detect some error conditions here
+	 * and ideally so something about them!
+	 */
+
+	return IRQ_HANDLED;
+}
+
+static int c8sectpfe_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *child, *np = dev->of_node;
+	struct c8sectpfei *fei;
+	struct resource *res;
+	int ret, n;
+	struct channel_info *tsin;
+
+	/* Allocate the c8sectpfei structure */
+	fei = devm_kzalloc(dev, sizeof(struct c8sectpfei), GFP_KERNEL);
+	if (!fei)
+		return -ENOMEM;
+
+	fei->dev = dev;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "c8sectpfe");
+	fei->io = devm_ioremap_resource(dev, res);
+	if (IS_ERR(fei->io))
+		return PTR_ERR(fei->io);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+					"c8sectpfe-ram");
+	fei->sram = devm_ioremap_resource(dev, res);
+	if (IS_ERR(fei->sram))
+		return PTR_ERR(fei->sram);
+
+	fei->sram_size = res->end - res->start;
+
+	fei->idle_irq = platform_get_irq_byname(pdev, "c8sectpfe-idle-irq");
+	if (fei->idle_irq < 0) {
+		dev_err(dev, "Can't get c8sectpfe-idle-irq\n");
+		return fei->idle_irq;
+	}
+
+	fei->error_irq = platform_get_irq_byname(pdev, "c8sectpfe-error-irq");
+	if (fei->error_irq < 0) {
+		dev_err(dev, "Can't get c8sectpfe-error-irq\n");
+		return fei->error_irq;
+	}
+
+	platform_set_drvdata(pdev, fei);
+
+	fei->c8sectpfeclk = devm_clk_get(dev, "c8sectpfe");
+	if (IS_ERR(fei->c8sectpfeclk)) {
+		dev_err(dev, "c8sectpfe clk not found\n");
+		return PTR_ERR(fei->c8sectpfeclk);
+	}
+
+	ret = clk_prepare_enable(fei->c8sectpfeclk);
+	if (ret) {
+		dev_err(dev, "Failed to enable c8sectpfe clock\n");
+		return ret;
+	}
+
+	/* to save power disable all IP's (on by default) */
+	writel(0, fei->io + SYS_INPUT_CLKEN);
+
+	/* Enable memdma clock */
+	writel(MEMDMAENABLE, fei->io + SYS_OTHER_CLKEN);
+
+	/* clear internal sram */
+	memset_io(fei->sram, 0x0, fei->sram_size);
+
+	c8sectpfe_getconfig(fei);
+
+	ret = load_slim_core_fw(fei);
+	if (ret) {
+		dev_err(dev, "Couldn't load slim core firmware\n");
+		goto err_clk_disable;
+	}
+
+	ret = devm_request_irq(dev, fei->idle_irq, c8sectpfe_idle_irq_handler,
+			0, "c8sectpfe-idle-irq", fei);
+	if (ret) {
+		dev_err(dev, "Can't register c8sectpfe-idle-irq IRQ.\n");
+		goto err_clk_disable;
+	}
+
+	ret = devm_request_irq(dev, fei->error_irq,
+				c8sectpfe_error_irq_handler, 0,
+				"c8sectpfe-error-irq", fei);
+	if (ret) {
+		dev_err(dev, "Can't register c8sectpfe-error-irq IRQ.\n");
+		goto err_clk_disable;
+	}
+
+	fei->tsin_count = of_get_child_count(np);
+
+	if (fei->tsin_count > C8SECTPFE_MAX_TSIN_CHAN ||
+		fei->tsin_count > fei->hw_stats.num_ib) {
+
+		dev_err(dev, "More tsin declared than exist on SoC!\n");
+		ret = -EINVAL;
+		goto err_clk_disable;
+	}
+
+	fei->pinctrl = devm_pinctrl_get(dev);
+
+	if (IS_ERR(fei->pinctrl)) {
+		dev_err(dev, "Error getting tsin pins\n");
+		ret = PTR_ERR(fei->pinctrl);
+		goto err_clk_disable;
+	}
+
+	n = 0;
+	for_each_child_of_node(np, child) {
+		struct device_node *i2c_bus;
+
+		fei->channel_data[n] = devm_kzalloc(dev,
+						sizeof(struct channel_info),
+						GFP_KERNEL);
+
+		if (!fei->channel_data[n]) {
+			ret = -ENOMEM;
+			goto err_clk_disable;
+		}
+
+		tsin = fei->channel_data[n];
+
+		tsin->fei = fei;
+
+		ret = of_property_read_u32(child, "tsin-num", &tsin->tsin_id);
+		if (ret) {
+			dev_err(&pdev->dev, "No tsin_num found\n");
+			goto err_clk_disable;
+		}
+
+		/* sanity check value */
+		if (tsin->tsin_id > fei->hw_stats.num_ib) {
+			dev_err(&pdev->dev,
+				"tsin-num %d specified greater than number\n\t"
+				"of input block hw in SoC! (%d)",
+				tsin->tsin_id, fei->hw_stats.num_ib);
+			ret = -EINVAL;
+			goto err_clk_disable;
+		}
+
+		tsin->invert_ts_clk = of_property_read_bool(child,
+							"invert-ts-clk");
+
+		tsin->serial_not_parallel = of_property_read_bool(child,
+							"serial-not-parallel");
+
+		tsin->async_not_sync = of_property_read_bool(child,
+							"async-not-sync");
+
+		ret = of_property_read_u32(child, "dvb-card",
+					&tsin->dvb_card);
+		if (ret) {
+			dev_err(&pdev->dev, "No dvb-card found\n");
+			goto err_clk_disable;
+		}
+
+		i2c_bus = of_parse_phandle(child, "i2c-bus", 0);
+		if (!i2c_bus) {
+			dev_err(&pdev->dev, "No i2c-bus found\n");
+			goto err_clk_disable;
+		}
+		tsin->i2c_adapter =
+			of_find_i2c_adapter_by_node(i2c_bus);
+		if (!tsin->i2c_adapter) {
+			dev_err(&pdev->dev, "No i2c adapter found\n");
+			of_node_put(i2c_bus);
+			goto err_clk_disable;
+		}
+		of_node_put(i2c_bus);
+
+		tsin->rst_gpio = of_get_named_gpio(child, "rst-gpio", 0);
+
+		ret = gpio_is_valid(tsin->rst_gpio);
+		if (!ret) {
+			dev_err(dev,
+				"reset gpio for tsin%d not valid (gpio=%d)\n",
+				tsin->tsin_id, tsin->rst_gpio);
+			goto err_clk_disable;
+		}
+
+		ret = devm_gpio_request_one(dev, tsin->rst_gpio,
+					GPIOF_OUT_INIT_LOW, "NIM reset");
+		if (ret && ret != -EBUSY) {
+			dev_err(dev, "Can't request tsin%d reset gpio\n"
+				, fei->channel_data[n]->tsin_id);
+			goto err_clk_disable;
+		}
+
+		if (!ret) {
+			/* toggle reset lines */
+			gpio_direction_output(tsin->rst_gpio, 0);
+			msleep(1);
+			gpio_direction_output(tsin->rst_gpio, 1);
+			msleep(1);
+		}
+
+		tsin->demux_mapping = n;
+
+		dev_dbg(fei->dev,
+			"channel=%p n=%d tsin_num=%d, invert-ts-clk=%d\n\t"
+			"serial-not-parallel=%d pkt-clk-valid=%d dvb-card=%d\n",
+			fei->channel_data[n], n,
+			tsin->tsin_id, tsin->invert_ts_clk,
+			tsin->serial_not_parallel, tsin->async_not_sync,
+			tsin->dvb_card);
+
+		ret = configure_input_block(fei, fei->channel_data[n]);
+
+		if (ret) {
+			dev_err(fei->dev,
+				"configure_input_block tsin=%d failed\n",
+				fei->channel_data[n]->tsin_id);
+			goto err_unmap;
+		}
+
+		n++;
+	}
+
+	/* Setup timer interrupt */
+	init_timer(&fei->timer);
+	fei->timer.function = c8sectpfe_timer_interrupt;
+	fei->timer.data = (unsigned long)fei;
+
+	mutex_init(&fei->lock);
+
+	/* Get the configuration information about the tuners */
+	ret = c8sectpfe_tuner_register_frontend(&fei->c8sectpfe[0],
+					(void *)fei,
+					c8sectpfe_start_feed,
+					c8sectpfe_stop_feed);
+	if (ret)
+		goto err_unmap;
+
+	/*
+	 * STBus target port can access IMEM and DMEM ports
+	 * without waiting for CPU
+	 */
+	writel(0x1, fei->io + DMA_PER_STBUS_SYNC);
+
+	dev_info(dev, "Boot the memdma SLIM core\n");
+	writel(0x1,  fei->io + DMA_CPU_RUN);
+
+	c8sectpfe_debugfs_init(fei);
+
+	return 0;
+
+err_unmap:
+	for (n = 0; n < fei->tsin_count; n++) {
+		tsin = fei->channel_data[n];
+
+		if (tsin)
+			free_input_block(fei, tsin);
+	}
+
+err_clk_disable:
+	/* TODO uncomment when upstream has taken a reference on this clk */
+	/*clk_disable_unprepare(fei->c8sectpfeclk);*/
+	return ret;
+}
+
+static int c8sectpfe_remove(struct platform_device *pdev)
+{
+	struct c8sectpfei *fei = platform_get_drvdata(pdev);
+	struct channel_info *channel;
+	unsigned int n;
+
+	c8sectpfe_tuner_unregister_frontend(fei->c8sectpfe[0], fei);
+
+	/*
+	 * Now loop through and un-configure each of the InputBlock resources
+	 */
+	for (n = 0; n < fei->tsin_count; n++) {
+		channel = fei->channel_data[n];
+		if (channel)
+			free_input_block(fei, channel);
+	}
+
+	c8sectpfe_debugfs_exit(fei);
+
+	dev_info(fei->dev, "Stopping memdma SLIM core\n");
+	if (readl(fei->io + DMA_CPU_RUN))
+		writel(0x0,  fei->io + DMA_CPU_RUN);
+
+	/* unclock all internal IP's */
+	if (readl(fei->io + SYS_INPUT_CLKEN))
+		writel(0, fei->io + SYS_INPUT_CLKEN);
+	if (readl(fei->io + SYS_OTHER_CLKEN))
+		writel(0, fei->io + SYS_OTHER_CLKEN);
+
+	/* TODO uncomment when upstream has taken a reference on this clk */
+	/*
+	if (fei->c8sectpfeclk)
+		clk_disable_unprepare(fei->c8sectpfeclk);
+	*/
+
+	return 0;
+}
+
+static int load_slim_core_fw(struct c8sectpfei *fei)
+{
+	const struct firmware *fw = NULL;
+	unsigned char *pImem = NULL;
+	unsigned char *pDmem = NULL;
+	Elf32_Ehdr *ehdr;
+	Elf32_Phdr *phdr;
+	int err = 0;
+	int i;
+
+	dev_info(fei->dev, "Loading firmware: %s\n", FIRMWARE_MEMDMA);
+
+	err = request_firmware(&fw, FIRMWARE_MEMDMA, fei->dev);
+	if (err) {
+		dev_err(fei->dev, "Failed to load %s, %d.\n",
+			FIRMWARE_MEMDMA, err);
+		return -EINVAL;
+	}
+
+	/* Check ELF magic */
+	ehdr = (Elf32_Ehdr *)fw->data;
+	if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
+	    ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
+	    ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
+	    ehdr->e_ident[EI_MAG3] != ELFMAG3) {
+		dev_err(fei->dev, "Invalid ELF magic\n");
+		err = -ENODEV;
+		goto done;
+	} else {
+		dev_dbg(fei->dev, "Valid ELF header found\n");
+	}
+
+	/* Check program headers are within firmware size */
+	if (ehdr->e_phoff + (ehdr->e_phnum * sizeof(Elf32_Phdr)) > fw->size) {
+		dev_err(fei->dev, "Program headers outside of firmware file\n");
+		err = -ENODEV;
+		goto done;
+	}
+
+	pImem = (unsigned char *) fei->io + DMA_MEMDMA_OFFSET + DMA_IMEM_OFFSET;
+	pDmem = (unsigned char *) fei->io + DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET;
+
+	phdr = (Elf32_Phdr *)(fw->data + ehdr->e_phoff);
+
+	/* go through the available ELF segments */
+	for (i = 0; i < ehdr->e_phnum && !err; i++, phdr++) {
+		unsigned char *dest;
+		int imem = 0;
+
+		/* Only consider LOAD segments */
+		if (phdr->p_type != PT_LOAD)
+			continue;
+
+		/*
+		 * Check segment is contained within the fw->data buffer
+		 */
+		if (phdr->p_offset + phdr->p_filesz > fw->size) {
+			dev_err(fei->dev,
+				"Segment %d is outside of firmware file\n", i);
+			err = -EINVAL;
+			break;
+		}
+
+		/*
+		 * MEMDMA IMEM has executable flag set, otherwise load
+		 * this segment to DMEM.
+		 */
+
+		if (phdr->p_flags & PF_X) {
+			dest = pImem;
+			imem = 1;
+		} else {
+			dest = pDmem;
+		}
+
+		/*
+		 * The Slim ELF file uses 32-bit word addressing for
+		 * load offsets.
+		 */
+
+		dest += (phdr->p_paddr & 0xFFFFF) * sizeof(unsigned int);
+
+		/*
+		 * For DMEM segments copy the segment data from the ELF
+		 * file and pad segment with zeroes
+		 *
+		 * For IMEM segments, the segment contains 24-bit
+		 * instructions which must be padded to 32-bit
+		 * instructions before being written. The written
+		 * segment is padded with NOP instructions.
+		 */
+
+		if (!imem) {
+			dev_dbg(fei->dev,
+				"Loading DMEM segment %d 0x%08x\n\t"
+				"(0x%x bytes) -> 0x%08x (0x%x bytes)\n",
+				i, phdr->p_paddr, phdr->p_filesz,
+				(unsigned int)dest, phdr->p_memsz);
+
+			memcpy((void *)dest, (void *)fw->data + phdr->p_offset,
+				phdr->p_filesz);
+
+			memset((void *)dest + phdr->p_filesz, 0,
+				phdr->p_memsz - phdr->p_filesz);
+		} else {
+			const unsigned char *imem_src = fw->data
+				+ phdr->p_offset;
+			unsigned char *imem_dest = dest;
+			int j;
+
+			dev_dbg(fei->dev,
+				"Loading IMEM segment %d 0x%08x\n\t"
+				" (0x%x bytes) -> 0x%08x (0x%x bytes)\n", i,
+				phdr->p_paddr, phdr->p_filesz,
+				(unsigned int)dest,
+				phdr->p_memsz + phdr->p_memsz / 3);
+
+			for (j = 0; j < phdr->p_filesz; j++) {
+				*imem_dest = *imem_src;
+
+				/* Every 3 bytes, add an additional
+				 * padding zero in destination */
+				if (j % 3 == 2) {
+					imem_dest++;
+					*imem_dest = 0x00;
+				}
+				imem_dest++;
+				imem_src++;
+			}
+		}
+	}
+
+done:
+	release_firmware(fw);
+	return err;
+}
+
+static const struct of_device_id c8sectpfe_match[] = {
+	{ .compatible = "st,stih407-c8sectpfe" },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, c8sectpfe_match);
+
+static struct platform_driver c8sectpfe_driver = {
+	.driver = {
+		.name = "c8sectpfe",
+		.of_match_table = of_match_ptr(c8sectpfe_match),
+	},
+	.probe	= c8sectpfe_probe,
+	.remove	= c8sectpfe_remove,
+};
+
+module_platform_driver(c8sectpfe_driver);
+
+MODULE_AUTHOR("Peter Bennett <peter.bennett@st.com>");
+MODULE_AUTHOR("Peter Griffin <peter.griffin@linaro.org>");
+MODULE_DESCRIPTION("C8SECTPFE STi DVB Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/tsin/c8sectpfe/c8sectpfe-core.h b/drivers/media/tsin/c8sectpfe/c8sectpfe-core.h
new file mode 100644
index 0000000..3466303
--- /dev/null
+++ b/drivers/media/tsin/c8sectpfe/c8sectpfe-core.h
@@ -0,0 +1,288 @@
+/*
+ * c8sectpfe-core.h - C8SECTPFE STi DVB driver
+ *
+ * Copyright (c) STMicroelectronics 2015
+ *
+ *   Author:Peter Bennett <peter.bennett@st.com>
+ *	    Peter Griffin <peter.griffin@linaro.org>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License as
+ *	published by the Free Software Foundation; either version 2 of
+ *	the License, or (at your option) any later version.
+ */
+#ifndef _C8SECTPFE_CORE_H_
+#define _C8SECTPFE_CORE_H_
+
+#define C8SECTPFEI_MAXCHANNEL 16
+#define C8SECTPFEI_MAXADAPTER 3
+
+#define C8SECTPFE_MAX_TSIN_CHAN 8
+
+struct channel_info {
+
+	int tsin_id;
+	bool invert_ts_clk;
+	bool serial_not_parallel;
+	bool async_not_sync;
+	int i2c;
+	int dvb_card;
+
+	int rst_gpio;
+
+	struct i2c_adapter  *i2c_adapter;
+	struct i2c_adapter  *tuner_i2c;
+	struct i2c_adapter  *lnb_i2c;
+	struct i2c_client   *i2c_client;
+	struct dvb_frontend *frontend;
+
+	struct pinctrl_state *pstate;
+
+	int demux_mapping;
+	int active;
+
+	void *back_buffer_start;
+	void *back_buffer_aligned;
+	dma_addr_t back_buffer_busaddr;
+
+	void *pid_buffer_start;
+	void *pid_buffer_aligned;
+	dma_addr_t pid_buffer_busaddr;
+
+	unsigned long  fifo;
+
+	struct completion idle_completion;
+	struct tasklet_struct tsklet;
+
+	struct c8sectpfei *fei;
+	struct c8sectpfe_input_record *irec;
+
+};
+
+struct c8sectpfe_hw {
+	int num_ib;
+	int num_mib;
+	int num_swts;
+	int num_tsout;
+	int num_ccsc;
+	int num_ram;
+	int num_tp;
+};
+
+struct c8sectpfei {
+
+	struct device *dev;
+	struct pinctrl *pinctrl;
+
+	struct dentry *root;
+	struct debugfs_regset32	*regset;
+
+	int tsin_count;
+
+	struct c8sectpfe_hw hw_stats;
+
+	struct c8sectpfe *c8sectpfe[C8SECTPFEI_MAXADAPTER];
+
+	int mapping[C8SECTPFEI_MAXCHANNEL];
+
+	struct mutex lock;
+
+	struct timer_list timer;	/* timer interrupts for outputs */
+
+	void __iomem *io;
+	void __iomem *sram;
+
+	unsigned long sram_size;
+
+	struct channel_info *channel_data[C8SECTPFE_MAX_TSIN_CHAN];
+
+	struct clk *c8sectpfeclk;
+	int nima_rst_gpio;
+	int nimb_rst_gpio;
+
+	int idle_irq;
+	int error_irq;
+
+	int global_feed_count;
+
+	struct c8sectpfe_input_record *irec;
+};
+
+/* C8SECTPFE SYS Regs list */
+
+#define SYS_INPUT_ERR_STATUS	0x0
+#define SYS_OTHER_ERR_STATUS	0x8
+#define SYS_INPUT_ERR_MASK	0x10
+#define SYS_OTHER_ERR_MASK	0x18
+#define SYS_DMA_ROUTE		0x20
+#define SYS_INPUT_CLKEN		0x30
+#define IBENABLE_MASK			0x7F
+
+#define SYS_OTHER_CLKEN		0x38
+#define TSDMAENABLE			BIT(1)
+#define MEMDMAENABLE			BIT(0)
+
+#define SYS_CFG_NUM_IB		0x200
+#define SYS_CFG_NUM_MIB		0x204
+#define SYS_CFG_NUM_SWTS	0x208
+#define SYS_CFG_NUM_TSOUT	0x20C
+#define SYS_CFG_NUM_CCSC	0x210
+#define SYS_CFG_NUM_RAM		0x214
+#define SYS_CFG_NUM_TP		0x218
+
+/* Input Block Regs */
+
+#define C8SECTPFE_INPUTBLK_OFFSET	0x1000
+#define C8SECTPFE_CHANNEL_OFFSET(x)	((x*0x40) + C8SECTPFE_INPUTBLK_OFFSET)
+
+#define C8SECTPFE_IB_IP_FMT_CFG(x)      (C8SECTPFE_CHANNEL_OFFSET(x) + 0x00)
+#define C8SECTPFE_IGNORE_ERR_AT_SOP     BIT(7)
+#define C8SECTPFE_IGNORE_ERR_IN_PKT     BIT(6)
+#define C8SECTPFE_IGNORE_ERR_IN_BYTE    BIT(5)
+#define C8SECTPFE_INVERT_TSCLK          BIT(4)
+#define C8SECTPFE_ALIGN_BYTE_SOP        BIT(3)
+#define C8SECTPFE_ASYNC_NOT_SYNC        BIT(2)
+#define C8SECTPFE_BYTE_ENDIANNESS_MSB    BIT(1)
+#define C8SECTPFE_SERIAL_NOT_PARALLEL   BIT(0)
+
+#define C8SECTPFE_IB_SYNCLCKDRP_CFG(x)   (C8SECTPFE_CHANNEL_OFFSET(x) + 0x04)
+#define C8SECTPFE_SYNC(x)                (x & 0xf)
+#define C8SECTPFE_DROP(x)                ((x<<4) & 0xf)
+#define C8SECTPFE_TOKEN(x)               ((x<<8) & 0xff00)
+#define C8SECTPFE_SLDENDIANNESS          BIT(16)
+
+#define C8SECTPFE_IB_TAGBYTES_CFG(x)     (C8SECTPFE_CHANNEL_OFFSET(x) + 0x08)
+#define C8SECTPFE_TAG_HEADER(x)          (x << 16)
+#define C8SECTPFE_TAG_COUNTER(x)         ((x<<1) & 0x7fff)
+#define C8SECTPFE_TAG_ENABLE             BIT(0)
+
+#define C8SECTPFE_IB_PID_SET(x)          (C8SECTPFE_CHANNEL_OFFSET(x) + 0x0C)
+#define C8SECTPFE_PID_OFFSET(x)          (x & 0x3f)
+#define C8SECTPFE_PID_NUMBITS(x)         ((x << 6) & 0xfff)
+#define C8SECTPFE_PID_ENABLE             BIT(31)
+
+#define C8SECTPFE_IB_PKT_LEN(x)          (C8SECTPFE_CHANNEL_OFFSET(x) + 0x10)
+
+#define C8SECTPFE_IB_BUFF_STRT(x)        (C8SECTPFE_CHANNEL_OFFSET(x) + 0x14)
+#define C8SECTPFE_IB_BUFF_END(x)         (C8SECTPFE_CHANNEL_OFFSET(x) + 0x18)
+#define C8SECTPFE_IB_READ_PNT(x)         (C8SECTPFE_CHANNEL_OFFSET(x) + 0x1C)
+#define C8SECTPFE_IB_WRT_PNT(x)          (C8SECTPFE_CHANNEL_OFFSET(x) + 0x20)
+
+#define C8SECTPFE_IB_PRI_THRLD(x)        (C8SECTPFE_CHANNEL_OFFSET(x) + 0x24)
+#define C8SECTPFE_PRI_VALUE(x)           (x & 0x7fffff)
+#define C8SECTPFE_PRI_LOWPRI(x)          ((x & 0xf) << 24)
+#define C8SECTPFE_PRI_HIGHPRI(x)         ((x & 0xf) << 28)
+
+#define C8SECTPFE_IB_STAT(x)             (C8SECTPFE_CHANNEL_OFFSET(x) + 0x28)
+#define C8SECTPFE_STAT_FIFO_OVERFLOW(x)  (x & 0x1)
+#define C8SECTPFE_STAT_BUFFER_OVERFLOW(x) (x & 0x2)
+#define C8SECTPFE_STAT_OUTOFORDERRP(x)   (x & 0x4)
+#define C8SECTPFE_STAT_PID_OVERFLOW(x)   (x & 0x8)
+#define C8SECTPFE_STAT_PKT_OVERFLOW(x)   (x & 0x10)
+#define C8SECTPFE_STAT_ERROR_PACKETS(x)  ((x >> 8) & 0xf)
+#define C8SECTPFE_STAT_SHORT_PACKETS(x)  ((x >> 12) & 0xf)
+
+#define C8SECTPFE_IB_MASK(x)             (C8SECTPFE_CHANNEL_OFFSET(x) + 0x2C)
+#define C8SECTPFE_MASK_FIFO_OVERFLOW     BIT(0)
+#define C8SECTPFE_MASK_BUFFER_OVERFLOW   BIT(1)
+#define C8SECTPFE_MASK_OUTOFORDERRP(x)   BIT(2)
+#define C8SECTPFE_MASK_PID_OVERFLOW(x)   BIT(3)
+#define C8SECTPFE_MASK_PKT_OVERFLOW(x)   BIT(4)
+#define C8SECTPFE_MASK_ERROR_PACKETS(x)  ((x & 0xf) << 8)
+#define C8SECTPFE_MASK_SHORT_PACKETS(x)  ((x & 0xf) >> 12)
+
+#define C8SECTPFE_IB_SYS(x)              (C8SECTPFE_CHANNEL_OFFSET(x) + 0x30)
+#define C8SECTPFE_SYS_RESET              BIT(1)
+#define C8SECTPFE_SYS_ENABLE             BIT(0)
+
+/*
+ * Ponter record data structure required for each input block
+ * see Table 82 on page 167
+ */
+
+struct tpentry {
+	/* The following entries are bus addresses for memdma */
+	unsigned long dma_busbase;
+	unsigned long dma_bustop;
+	unsigned long dma_bus_wp;
+	unsigned long dma_bus_rp;
+};
+
+struct c8sectpfe_input_record {
+	unsigned long dma_membase; /* Internal sram base address */
+	unsigned long dma_memtop;  /* Internal sram top address */
+
+	/*
+	 * TS packet size, including tag bytes added by input block,
+	 * rounded up to the next multiple of 8 bytes. The packet size,
+	 * including any tagging bytes and rounded up to the nearest
+	 * multiple of 8 bytes must be less than 255 bytes.
+	 */
+	unsigned long dma_ts_pktsize;
+	unsigned long tp_enable;
+	struct tpentry ptr_data[1];
+};
+
+#define DMA_MEMDMA_OFFSET	0x4000
+#define DMA_IMEM_OFFSET		0x0
+#define DMA_DMEM_OFFSET		0x4000
+#define DMA_CPU			0x8000
+#define DMA_PER_OFFSET		0xb000
+
+/* XP70 Slim core regs */
+#define DMA_CPU_ID	(DMA_MEMDMA_OFFSET + DMA_CPU + 0x0)
+#define DMA_CPU_VCR	(DMA_MEMDMA_OFFSET + DMA_CPU + 0x4)
+#define DMA_CPU_RUN	(DMA_MEMDMA_OFFSET + DMA_CPU + 0x8)
+#define DMA_CPU_CLOCKGATE	(DMA_MEMDMA_OFFSET + DMA_CPU + 0xc)
+#define DMA_CPU_PC	(DMA_MEMDMA_OFFSET + DMA_CPU + 0x20)
+
+/* Enable Interrupt for a IB */
+#define DMA_PER_TPn_DREQ_MASK	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xd00)
+/* Ack interrupt by setting corresponding bit */
+#define DMA_PER_TPn_DACK_SET	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xd80)
+#define DMA_PER_TPn_DREQ	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xe00)
+#define DMA_PER_TPn_DACK	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xe80)
+#define DMA_PER_DREQ_MODE	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xf80)
+#define DMA_PER_STBUS_SYNC	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xf88)
+#define DMA_PER_STBUS_ACCESS	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xf8c)
+#define DMA_PER_STBUS_ADDRESS	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xf90)
+#define DMA_PER_IDLE_INT	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfa8)
+#define DMA_PER_PRIORITY	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfac)
+#define DMA_PER_MAX_OPCODE	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfb0)
+#define DMA_PER_MAX_CHUNK	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfb4)
+#define DMA_PER_PAGE_SIZE	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfbc)
+#define DMA_PER_MBOX_STATUS	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfc0)
+#define DMA_PER_MBOX_SET	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfc8)
+#define DMA_PER_MBOX_CLEAR	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfd0)
+#define DMA_PER_MBOX_MASK	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfd8)
+#define DMA_PER_INJECT_PKT_SRC	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfe0)
+#define DMA_PER_INJECT_PKT_DEST	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfe4)
+#define DMA_PER_INJECT_PKT_ADDR	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfe8)
+#define DMA_PER_INJECT_PKT	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfec)
+#define DMA_PER_PAT_PTR_INIT	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xff0)
+#define DMA_PER_PAT_PTR		(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xff4)
+#define DMA_PER_SLEEP_MASK	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xff8)
+#define DMA_PER_SLEEP_COUNTER	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xffc)
+/* #define DMA_RF_CPUREGn	DMA_RFBASEADDR n=0 to 15) slim regsa */
+
+/* The following are from DMA_DMEM_BaseAddress */
+#define DMA_FIRMWARE_VERSION	(DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET + 0x0)
+#define DMA_PTRREC_BASE		(DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET + 0x4)
+#define DMA_PTRREC_INPUT_OFFSET	(DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET + 0x8)
+#define DMA_ERRREC_BASE		(DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET + 0xc)
+#define DMA_ERROR_RECORD(n)	((n*4) + DMA_ERRREC_BASE + 0x4)
+#define DMA_IDLE_REQ		(DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET + 0x10)
+#define IDLEREQ			BIT(31)
+
+#define DMA_FIRMWARE_CONFIG	(DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET + 0x14)
+
+/* Regs for PID Filter */
+
+#define PIDF_OFFSET		0x2800
+#define PIDF_BASE(n)		((n*4) + PIDF_OFFSET)
+#define PIDF_LEAK_ENABLE	(PIDF_OFFSET + 0x100)
+#define PIDF_LEAK_STATUS	(PIDF_OFFSET + 0x108)
+#define PIDF_LEAK_COUNT_RESET	(PIDF_OFFSET + 0x110)
+#define PIDF_LEAK_COUNTER	(PIDF_OFFSET + 0x114)
+
+#endif /* _C8SECTPFE_CORE_H_ */
-- 
1.9.1


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

* [PATCH 08/12] [media] tsin: c8sectpfe: Add LDVB helper functions.
  2015-06-24 15:10 [PATCH 00/12] Add c8sectpfe LinuxDVB demux driver Peter Griffin
                   ` (6 preceding siblings ...)
  2015-06-24 15:11 ` [PATCH 07/12] [media] tsin: c8sectpfe: STiH407/10 Linux DVB demux support Peter Griffin
@ 2015-06-24 15:11 ` Peter Griffin
  2015-06-24 15:11 ` [PATCH 09/12] [media] tsin: c8sectpfe: Add support for various ST NIM cards Peter Griffin
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 32+ messages in thread
From: Peter Griffin @ 2015-06-24 15:11 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, srinivas.kandagatla,
	maxime.coquelin, patrice.chotard, mchehab
  Cc: peter.griffin, lee.jones, hugues.fruchet, linux-media, devicetree

These functions are used by the core code for creating the LDVB
devices and adapter.

Addtionally some older SoC's (and potentially newer ones) have different
frontend HW which would allow those devices to be easily supported
in the future by keeping the code specific to the IP separate from the
more generic code.

Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
---
 drivers/media/tsin/c8sectpfe/c8sectpfe-common.c | 266 ++++++++++++++++++++++++
 drivers/media/tsin/c8sectpfe/c8sectpfe-common.h |  66 ++++++
 2 files changed, 332 insertions(+)
 create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-common.c
 create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-common.h

diff --git a/drivers/media/tsin/c8sectpfe/c8sectpfe-common.c b/drivers/media/tsin/c8sectpfe/c8sectpfe-common.c
new file mode 100644
index 0000000..c8d607d
--- /dev/null
+++ b/drivers/media/tsin/c8sectpfe/c8sectpfe-common.c
@@ -0,0 +1,266 @@
+/*
+ * c8sectpfe-common.c - C8SECTPFE STi DVB driver
+ *
+ * Copyright (c) STMicroelectronics 2015
+ *
+ *   Author: Peter Griffin <peter.griffin@linaro.org>
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License as
+ *      published by the Free Software Foundation; either version 2 of
+ *      the License, or (at your option) any later version.
+ */
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dvb/dmx.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/wait.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "c8sectpfe-common.h"
+#include "c8sectpfe-core.h"
+#include "c8sectpfe-dvb.h"
+
+static int register_dvb(struct stdemux *demux, struct dvb_adapter *adap,
+				void *start_feed, void *stop_feed,
+				struct c8sectpfei *fei)
+{
+	int result;
+
+	demux->dvb_demux.dmx.capabilities = DMX_TS_FILTERING |
+					DMX_SECTION_FILTERING |
+					DMX_MEMORY_BASED_FILTERING;
+
+	demux->dvb_demux.priv = demux;
+	demux->dvb_demux.filternum = C8SECTPFE_MAXCHANNEL;
+	demux->dvb_demux.feednum = C8SECTPFE_MAXCHANNEL;
+
+	demux->dvb_demux.start_feed = start_feed;
+	demux->dvb_demux.stop_feed = stop_feed;
+	demux->dvb_demux.write_to_decoder = NULL;
+
+	result = dvb_dmx_init(&demux->dvb_demux);
+	if (result < 0) {
+		dev_err(fei->dev, "dvb_dmx_init failed (errno = %d)\n",
+			result);
+		goto err_dmx;
+	}
+
+	demux->dmxdev.filternum = demux->dvb_demux.filternum;
+	demux->dmxdev.demux = &demux->dvb_demux.dmx;
+	demux->dmxdev.capabilities = 0;
+
+	result = dvb_dmxdev_init(&demux->dmxdev, adap);
+	if (result < 0) {
+		dev_err(fei->dev, "dvb_dmxdev_init failed (errno = %d)\n",
+			result);
+
+		goto err_dmxdev;
+	}
+
+	demux->hw_frontend.source = DMX_FRONTEND_0 + demux->tsin_index;
+
+	result = demux->dvb_demux.dmx.add_frontend(&demux->dvb_demux.dmx,
+						&demux->hw_frontend);
+	if (result < 0) {
+		dev_err(fei->dev, "add_frontend failed (errno = %d)\n", result);
+		goto err_fe_hw;
+	}
+
+	demux->mem_frontend.source = DMX_MEMORY_FE;
+	result = demux->dvb_demux.dmx.add_frontend(&demux->dvb_demux.dmx,
+						&demux->mem_frontend);
+	if (result < 0) {
+		dev_err(fei->dev, "add_frontend failed (%d)\n", result);
+		goto err_fe_mem;
+	}
+
+	result = demux->dvb_demux.dmx.connect_frontend(&demux->dvb_demux.dmx,
+							&demux->hw_frontend);
+	if (result < 0) {
+		dev_err(fei->dev, "connect_frontend (%d)\n", result);
+		goto err_fe_con;
+	}
+
+	return 0;
+
+err_fe_con:
+	demux->dvb_demux.dmx.remove_frontend(&demux->dvb_demux.dmx,
+						     &demux->mem_frontend);
+err_fe_mem:
+	demux->dvb_demux.dmx.remove_frontend(&demux->dvb_demux.dmx,
+						     &demux->hw_frontend);
+err_fe_hw:
+	dvb_dmxdev_release(&demux->dmxdev);
+err_dmxdev:
+	dvb_dmx_release(&demux->dvb_demux);
+err_dmx:
+	return result;
+
+}
+
+static void unregister_dvb(struct stdemux *demux)
+{
+
+	demux->dvb_demux.dmx.remove_frontend(&demux->dvb_demux.dmx,
+						     &demux->mem_frontend);
+
+	demux->dvb_demux.dmx.remove_frontend(&demux->dvb_demux.dmx,
+						     &demux->hw_frontend);
+
+	dvb_dmxdev_release(&demux->dmxdev);
+
+	dvb_dmx_release(&demux->dvb_demux);
+}
+
+static struct c8sectpfe *c8sectpfe_create(struct c8sectpfei *fei,
+				void *start_feed,
+				void *stop_feed)
+{
+	struct c8sectpfe *c8sectpfe;
+	int result;
+	int i, j;
+
+	short int ids[] = { -1 };
+
+	c8sectpfe = kzalloc(sizeof(struct c8sectpfe), GFP_KERNEL);
+	if (!c8sectpfe)
+		goto err1;
+
+	mutex_init(&c8sectpfe->lock);
+
+	c8sectpfe->device = fei->dev;
+
+	result = dvb_register_adapter(&c8sectpfe->adapter, "STi c8sectpfe",
+					THIS_MODULE, fei->dev, ids);
+	if (result < 0) {
+		dev_err(fei->dev, "dvb_register_adapter failed (errno = %d)\n",
+			result);
+		goto err2;
+	}
+
+	c8sectpfe->adapter.priv = fei;
+
+	for (i = 0; i < fei->tsin_count; i++) {
+
+		c8sectpfe->demux[i].tsin_index = i;
+		c8sectpfe->demux[i].tsm_channel = fei->channel_data[i]->tsin_id;
+		c8sectpfe->demux[i].c8sectpfei = fei;
+
+		result = register_dvb(&c8sectpfe->demux[i], &c8sectpfe->adapter,
+				start_feed, stop_feed, fei);
+		if (result < 0) {
+			dev_err(fei->dev,
+				"register_dvb feed=%d failed (errno = %d)\n",
+				result, i);
+
+			/* we take a all or nothing approach */
+			for (j = 0; j < i; j++)
+				unregister_dvb(&c8sectpfe->demux[j]);
+			goto err3;
+		}
+	}
+
+	c8sectpfe->num_feeds = fei->tsin_count;
+
+	return c8sectpfe;
+err3:
+	dvb_unregister_adapter(&c8sectpfe->adapter);
+err2:
+	kfree(c8sectpfe);
+err1:
+	return NULL;
+};
+
+static void c8sectpfe_delete(struct c8sectpfe *c8sectpfe)
+{
+	int i;
+
+	if (!c8sectpfe)
+		return;
+
+	for (i = 0; i < c8sectpfe->num_feeds; i++)
+		unregister_dvb(&c8sectpfe->demux[i]);
+
+	dvb_unregister_adapter(&c8sectpfe->adapter);
+
+	kfree(c8sectpfe);
+};
+
+void c8sectpfe_tuner_unregister_frontend(struct c8sectpfe *c8sectpfe,
+					struct c8sectpfei *fei)
+{
+	int n;
+	struct channel_info *tsin;
+
+	for (n = 0; n < fei->tsin_count; n++) {
+
+		tsin = fei->channel_data[n];
+
+		if (tsin && tsin->frontend) {
+			dvb_unregister_frontend(tsin->frontend);
+			dvb_frontend_detach(tsin->frontend);
+		}
+
+		if (tsin && tsin->i2c_adapter)
+			i2c_put_adapter(tsin->i2c_adapter);
+
+		if (tsin && tsin->i2c_client) {
+			if (tsin->i2c_client->dev.driver->owner)
+				module_put(tsin->i2c_client->dev.driver->owner);
+			i2c_unregister_device(tsin->i2c_client);
+		}
+	}
+
+	c8sectpfe_delete(c8sectpfe);
+};
+
+int c8sectpfe_tuner_register_frontend(struct c8sectpfe **c8sectpfe,
+				struct c8sectpfei *fei,
+				void *start_feed,
+				void *stop_feed)
+{
+	struct channel_info *tsin;
+	struct dvb_frontend *frontend;
+	int n, res;
+
+	*c8sectpfe = c8sectpfe_create(fei, start_feed, stop_feed);
+	if (!*c8sectpfe)
+		return -ENOMEM;
+
+	for (n = 0; n < fei->tsin_count; n++) {
+		tsin = fei->channel_data[n];
+
+		res = c8sectpfe_frontend_attach(&frontend, *c8sectpfe, tsin, n);
+		if (res)
+			goto err;
+
+		res = dvb_register_frontend(&c8sectpfe[0]->adapter, frontend);
+		if (res < 0) {
+			dev_err(fei->dev, "dvb_register_frontend failed (%d)\n",
+				res);
+			goto err;
+		}
+
+		tsin->frontend = frontend;
+	}
+
+	return 0;
+
+err:
+	c8sectpfe_tuner_unregister_frontend(*c8sectpfe, fei);
+	return res;
+}
diff --git a/drivers/media/tsin/c8sectpfe/c8sectpfe-common.h b/drivers/media/tsin/c8sectpfe/c8sectpfe-common.h
new file mode 100644
index 0000000..03beed5
--- /dev/null
+++ b/drivers/media/tsin/c8sectpfe/c8sectpfe-common.h
@@ -0,0 +1,66 @@
+/*
+ * c8sectpfe-common.h - C8SECTPFE STi DVB driver
+ *
+ * Copyright (c) STMicroelectronics 2015
+ *
+ *   Author: Peter Griffin <peter.griffin@linaro.org>
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License as
+ *      published by the Free Software Foundation; either version 2 of
+ *      the License, or (at your option) any later version.
+ */
+#ifndef _C8SECTPFE_COMMON_H_
+#define _C8SECTPFE_COMMON_H_
+
+#include <linux/dvb/dmx.h>
+#include <linux/dvb/frontend.h>
+#include <linux/gpio.h>
+#include <linux/version.h>
+
+#include "dmxdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+/* Maximum number of channels */
+#define C8SECTPFE_MAXADAPTER (4)
+#define C8SECTPFE_MAXCHANNEL 64
+#define STPTI_MAXCHANNEL 64
+
+#define MAX_INPUTBLOCKS 7
+
+struct c8sectpfe;
+struct stdemux;
+
+struct stdemux {
+	struct dvb_demux	dvb_demux;
+	struct dmxdev		dmxdev;
+	struct dmx_frontend	hw_frontend;
+	struct dmx_frontend	mem_frontend;
+	int			tsm_channel;
+	int			stream_channel;
+	int			tsin_index;
+	int			running_feed_count;
+	struct			c8sectpfei *c8sectpfei;
+};
+
+struct c8sectpfe {
+	struct stdemux demux[MAX_INPUTBLOCKS];
+	struct mutex lock;
+	struct dvb_adapter adapter;
+	struct device *device;
+	int mapping;
+	int num_feeds;
+};
+
+/* Channel registration */
+int c8sectpfe_tuner_register_frontend(struct c8sectpfe **c8sectpfe,
+					struct c8sectpfei *fei,
+					void *start_feed,
+					void *stop_feed);
+
+void c8sectpfe_tuner_unregister_frontend(struct c8sectpfe *c8sectpfe,
+						struct c8sectpfei *fei);
+
+#endif
-- 
1.9.1


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

* [PATCH 09/12] [media] tsin: c8sectpfe: Add support for various ST NIM cards.
  2015-06-24 15:10 [PATCH 00/12] Add c8sectpfe LinuxDVB demux driver Peter Griffin
                   ` (7 preceding siblings ...)
  2015-06-24 15:11 ` [PATCH 08/12] [media] tsin: c8sectpfe: Add LDVB helper functions Peter Griffin
@ 2015-06-24 15:11 ` Peter Griffin
  2015-07-22 21:53   ` Mauro Carvalho Chehab
  2015-06-24 15:11 ` [PATCH 10/12] [media] tsin: c8sectpfe: Add c8sectpfe debugfs support Peter Griffin
                   ` (2 subsequent siblings)
  11 siblings, 1 reply; 32+ messages in thread
From: Peter Griffin @ 2015-06-24 15:11 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, srinivas.kandagatla,
	maxime.coquelin, patrice.chotard, mchehab
  Cc: peter.griffin, lee.jones, hugues.fruchet, linux-media, devicetree

This patch adds support for the following 3 NIM cards: -
1) STV0367-NIM (stv0367 demod with Thompson PLL)
2) B2100A (2x stv0367 demods & 2x NXP tda18212 tuners)
3) STV0903-6110NIM (stv0903 demod + 6110 tuner, lnb24)

Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
---
 drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.c | 296 +++++++++++++++++++++++++++
 drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.h |  20 ++
 2 files changed, 316 insertions(+)
 create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.c
 create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.h

diff --git a/drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.c b/drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.c
new file mode 100644
index 0000000..5c4ecb4
--- /dev/null
+++ b/drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.c
@@ -0,0 +1,296 @@
+/*
+ *  c8sectpfe-dvb.c - C8SECTPFE STi DVB driver
+ *
+ * Copyright (c) STMicroelectronics 2015
+ *
+ *  Author Peter Griffin <peter.griffin@linaro.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ */
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/version.h>
+
+#include <dt-bindings/media/c8sectpfe.h>
+
+#include "c8sectpfe-common.h"
+#include "c8sectpfe-core.h"
+#include "c8sectpfe-dvb.h"
+
+#include "dvb-pll.h"
+#include "lnbh24.h"
+#include "stv0367.h"
+#include "stv0367_priv.h"
+#include "stv6110x.h"
+#include "stv090x.h"
+#include "tda18212.h"
+
+static inline const char *dvb_card_str(unsigned int c)
+{
+	switch (c) {
+	case STV0367_PLL_BOARD_NIMA:	return "STV0367_PLL_BOARD_NIMA";
+	case STV0367_PLL_BOARD_NIMB:	return "STV0367_PLL_BOARD_NIMB";
+	case STV0367_TDA18212_NIMA_1:	return "STV0367_TDA18212_NIMA_1";
+	case STV0367_TDA18212_NIMA_2:	return "STV0367_TDA18212_NIMA_2";
+	case STV0367_TDA18212_NIMB_1:	return "STV0367_TDA18212_NIMB_1";
+	case STV0367_TDA18212_NIMB_2:	return "STV0367_TDA18212_NIMB_2";
+	case STV0903_6110_LNB24_NIMA:	return "STV0903_6110_LNB24_NIMA";
+	case STV0903_6110_LNB24_NIMB:	return "STV0903_6110_LNB24_NIMB";
+	default:			return "unknown dvb frontend card";
+	}
+}
+
+static struct stv090x_config stv090x_config = {
+	.device                 = STV0903,
+	.demod_mode             = STV090x_SINGLE,
+	.clk_mode               = STV090x_CLK_EXT,
+	.xtal                   = 16000000,
+	.address                = 0x69,
+
+	.ts1_mode               = STV090x_TSMODE_SERIAL_CONTINUOUS,
+	.ts2_mode               = STV090x_TSMODE_SERIAL_CONTINUOUS,
+
+	.repeater_level         = STV090x_RPTLEVEL_64,
+
+	.tuner_init             = NULL,
+	.tuner_set_mode         = NULL,
+	.tuner_set_frequency    = NULL,
+	.tuner_get_frequency    = NULL,
+	.tuner_set_bandwidth    = NULL,
+	.tuner_get_bandwidth    = NULL,
+	.tuner_set_bbgain       = NULL,
+	.tuner_get_bbgain       = NULL,
+	.tuner_set_refclk       = NULL,
+	.tuner_get_status       = NULL,
+};
+
+static struct stv6110x_config stv6110x_config = {
+	.addr                   = 0x60,
+	.refclk                 = 16000000,
+};
+
+#define NIMA 0
+#define NIMB 1
+
+static struct stv0367_config stv0367_pll_config[] = {
+	{
+		.demod_address = 0x1c,
+		.xtal = 27000000,
+		.if_khz = 36166,
+		.if_iq_mode = FE_TER_NORMAL_IF_TUNER,
+		.ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
+		.clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
+	}, {
+		.demod_address = 0x1d,
+		.xtal = 27000000,
+		.if_khz = 36166,
+		.if_iq_mode = FE_TER_NORMAL_IF_TUNER,
+		.ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
+		.clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
+	},
+};
+
+static struct stv0367_config stv0367_tda18212_config[] = {
+	{
+		.demod_address = 0x1c,
+		.xtal = 16000000,
+		.if_khz = 4500,
+		.if_iq_mode = FE_TER_NORMAL_IF_TUNER,
+		.ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
+		.clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
+	}, {
+		.demod_address = 0x1d,
+		.xtal = 16000000,
+		.if_khz = 4500,
+		.if_iq_mode = FE_TER_NORMAL_IF_TUNER,
+		.ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
+		.clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
+	}, {
+		.demod_address = 0x1e,
+		.xtal = 16000000,
+		.if_khz = 4500,
+		.if_iq_mode = FE_TER_NORMAL_IF_TUNER,
+		.ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
+		.clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
+	},
+};
+
+static struct tda18212_config tda18212_conf = {
+	.if_dvbt_6 = 4150,
+	.if_dvbt_7 = 4150,
+	.if_dvbt_8 = 4500,
+	.if_dvbc = 5000,
+};
+
+int c8sectpfe_frontend_attach(struct dvb_frontend **fe,
+		struct c8sectpfe *c8sectpfe,
+		struct channel_info *tsin, int chan_num)
+{
+	struct tda18212_config *tda18212;
+	struct stv6110x_devctl *fe2;
+	struct i2c_client *client;
+	struct i2c_board_info tda18212_info = {
+		.type = "tda18212",
+		.addr = 0x60,
+	};
+
+	BUG_ON(!tsin);
+
+	switch (tsin->dvb_card) {
+
+	case STV0367_PLL_BOARD_NIMA:
+	case STV0367_PLL_BOARD_NIMB:
+		if (tsin->dvb_card == STV0367_PLL_BOARD_NIMA)
+			*fe = dvb_attach(stv0367ter_attach,
+				 &stv0367_pll_config[NIMA], tsin->i2c_adapter);
+		else
+			*fe = dvb_attach(stv0367ter_attach,
+				 &stv0367_pll_config[NIMB], tsin->i2c_adapter);
+
+		if (!*fe) {
+			dev_err(c8sectpfe->device,
+				"%s: stv0367ter_attach failed for NIM card %s\n"
+				, __func__, dvb_card_str(tsin->dvb_card));
+			return -ENODEV;
+		};
+
+		/*
+		 * init the demod so that i2c gate_ctrl
+		 * to the tuner works correctly
+		 */
+		(*fe)->ops.init(*fe);
+
+		if (!dvb_attach(dvb_pll_attach, *fe, 0x60,
+			tsin->i2c_adapter, DVB_PLL_THOMSON_DTT7546X)) {
+
+			dev_err(c8sectpfe->device,
+				"%s: DVB_PLL_THOMSON_DTT7546X attach failed\n\t"
+				"for NIM card %s\n",
+				__func__, dvb_card_str(tsin->dvb_card));
+			return -ENODEV;
+		}
+		break;
+
+	case STV0367_TDA18212_NIMA_1:
+	case STV0367_TDA18212_NIMA_2:
+	case STV0367_TDA18212_NIMB_1:
+	case STV0367_TDA18212_NIMB_2:
+		if (tsin->dvb_card == STV0367_TDA18212_NIMA_1)
+			*fe = dvb_attach(stv0367ter_attach,
+				 &stv0367_tda18212_config[0],
+					tsin->i2c_adapter);
+		else if (tsin->dvb_card == STV0367_TDA18212_NIMB_1)
+			*fe = dvb_attach(stv0367ter_attach,
+				 &stv0367_tda18212_config[1],
+					tsin->i2c_adapter);
+		else
+			*fe = dvb_attach(stv0367ter_attach,
+				 &stv0367_tda18212_config[2],
+					tsin->i2c_adapter);
+
+		if (!*fe) {
+			dev_err(c8sectpfe->device,
+				"%s: stv0367ter_attach failed for NIM card %s\n"
+				, __func__, dvb_card_str(tsin->dvb_card));
+			return -ENODEV;
+		};
+
+		/*
+		 * init the demod so that i2c gate_ctrl
+		 * to the tuner works correctly
+		 */
+		(*fe)->ops.init(*fe);
+
+		/* Allocate the tda18212 structure */
+		tda18212 = devm_kzalloc(c8sectpfe->device,
+					sizeof(struct tda18212_config),
+					GFP_KERNEL);
+		if (!tda18212) {
+			dev_err(c8sectpfe->device,
+				"%s: devm_kzalloc failed\n", __func__);
+			return -ENOMEM;
+		}
+
+		memcpy(tda18212, &tda18212_conf,
+			sizeof(struct tda18212_config));
+
+		tda18212->fe = (*fe);
+
+		tda18212_info.platform_data = tda18212;
+
+		/* attach tuner */
+		request_module("tda18212");
+		client = i2c_new_device(tsin->i2c_adapter, &tda18212_info);
+		if (!client || !client->dev.driver) {
+			dvb_frontend_detach(*fe);
+			return -ENODEV;
+		}
+
+		if (!try_module_get(client->dev.driver->owner)) {
+			i2c_unregister_device(client);
+			dvb_frontend_detach(*fe);
+			return -ENODEV;
+		}
+
+		tsin->i2c_client = client;
+
+		break;
+
+	case STV0903_6110_LNB24_NIMA:
+		*fe = dvb_attach(stv090x_attach,	&stv090x_config,
+				tsin->i2c_adapter, STV090x_DEMODULATOR_0);
+		if (!*fe) {
+			dev_err(c8sectpfe->device, "%s: stv090x_attach failed\n"
+				"\tfor NIM card %s\n",
+				__func__, dvb_card_str(tsin->dvb_card));
+			return -ENODEV;
+		}
+
+		fe2 = dvb_attach(stv6110x_attach, *fe,
+					&stv6110x_config, tsin->i2c_adapter);
+		if (!fe2) {
+			dev_err(c8sectpfe->device,
+				"%s: stv6110x_attach failed for NIM card %s\n"
+				, __func__, dvb_card_str(tsin->dvb_card));
+			return -ENODEV;
+		};
+
+		stv090x_config.tuner_init = fe2->tuner_init;
+		stv090x_config.tuner_set_mode = fe2->tuner_set_mode;
+		stv090x_config.tuner_set_frequency = fe2->tuner_set_frequency;
+		stv090x_config.tuner_get_frequency = fe2->tuner_get_frequency;
+		stv090x_config.tuner_set_bandwidth = fe2->tuner_set_bandwidth;
+		stv090x_config.tuner_get_bandwidth = fe2->tuner_get_bandwidth;
+		stv090x_config.tuner_set_bbgain = fe2->tuner_set_bbgain;
+		stv090x_config.tuner_get_bbgain = fe2->tuner_get_bbgain;
+		stv090x_config.tuner_set_refclk = fe2->tuner_set_refclk;
+		stv090x_config.tuner_get_status = fe2->tuner_get_status;
+
+		dvb_attach(lnbh24_attach, *fe, tsin->i2c_adapter, 0, 0, 0x9);
+		break;
+
+	default:
+		dev_err(c8sectpfe->device,
+			"%s: DVB frontend card %s not yet supported\n",
+			__func__, dvb_card_str(tsin->dvb_card));
+		return -ENODEV;
+	}
+
+	(*fe)->id = chan_num;
+
+	dev_info(c8sectpfe->device,
+			"DVB frontend card %s successfully attached",
+			dvb_card_str(tsin->dvb_card));
+	return 0;
+}
diff --git a/drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.h b/drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.h
new file mode 100644
index 0000000..bd366db
--- /dev/null
+++ b/drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.h
@@ -0,0 +1,20 @@
+/*
+ * c8sectpfe-common.h - C8SECTPFE STi DVB driver
+ *
+ * Copyright (c) STMicroelectronics 2015
+ *
+ *   Author: Peter Griffin <peter.griffin@linaro.org>
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License as
+ *      published by the Free Software Foundation; either version 2 of
+ *      the License, or (at your option) any later version.
+ */
+#ifndef _C8SECTPFE_DVB_H_
+#define _C8SECTPFE_DVB_H_
+
+int c8sectpfe_frontend_attach(struct dvb_frontend **fe,
+			struct c8sectpfe *c8sectpfe, struct channel_info *tsin,
+			int chan_num);
+
+#endif
-- 
1.9.1


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

* [PATCH 10/12] [media] tsin: c8sectpfe: Add c8sectpfe debugfs support.
  2015-06-24 15:10 [PATCH 00/12] Add c8sectpfe LinuxDVB demux driver Peter Griffin
                   ` (8 preceding siblings ...)
  2015-06-24 15:11 ` [PATCH 09/12] [media] tsin: c8sectpfe: Add support for various ST NIM cards Peter Griffin
@ 2015-06-24 15:11 ` Peter Griffin
  2015-06-24 15:11 ` [PATCH 11/12] [media] tsin: c8sectpfe: Add Kconfig and Makefile for the driver Peter Griffin
  2015-06-24 15:11 ` [PATCH 12/12] MAINTAINERS: Add c8sectpfe driver directory to STi section Peter Griffin
  11 siblings, 0 replies; 32+ messages in thread
From: Peter Griffin @ 2015-06-24 15:11 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, srinivas.kandagatla,
	maxime.coquelin, patrice.chotard, mchehab
  Cc: peter.griffin, lee.jones, hugues.fruchet, linux-media, devicetree

Some basic debugfs support to dump the IP registers. Further
statistics could easily be added in the future for example for
each enabled tsin channel we could expose number of corrupt packets
received etc.

Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
---
 drivers/media/tsin/c8sectpfe/c8sectpfe-debugfs.c | 271 +++++++++++++++++++++++
 drivers/media/tsin/c8sectpfe/c8sectpfe-debugfs.h |  26 +++
 2 files changed, 297 insertions(+)
 create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-debugfs.c
 create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-debugfs.h

diff --git a/drivers/media/tsin/c8sectpfe/c8sectpfe-debugfs.c b/drivers/media/tsin/c8sectpfe/c8sectpfe-debugfs.c
new file mode 100644
index 0000000..e9ba13d
--- /dev/null
+++ b/drivers/media/tsin/c8sectpfe/c8sectpfe-debugfs.c
@@ -0,0 +1,271 @@
+/*
+ * c8sectpfe-debugfs.c - C8SECTPFE STi DVB driver
+ *
+ * Copyright (c) STMicroelectronics 2015
+ *
+ * Author: Peter Griffin <peter.griffin@linaro.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "c8sectpfe-debugfs.h"
+
+#define dump_register(nm ...)			\
+{						\
+	.name	= #nm,				\
+	.offset	= nm,				\
+}
+
+static const struct debugfs_reg32 fei_sys_regs[] = {
+	dump_register(SYS_INPUT_ERR_STATUS),
+	dump_register(SYS_OTHER_ERR_STATUS),
+	dump_register(SYS_INPUT_ERR_MASK),
+	dump_register(SYS_DMA_ROUTE),
+	dump_register(SYS_INPUT_CLKEN),
+	dump_register(IBENABLE_MASK),
+	dump_register(SYS_OTHER_CLKEN),
+	dump_register(SYS_CFG_NUM_IB),
+	dump_register(SYS_CFG_NUM_MIB),
+	dump_register(SYS_CFG_NUM_SWTS),
+	dump_register(SYS_CFG_NUM_TSOUT),
+	dump_register(SYS_CFG_NUM_CCSC),
+	dump_register(SYS_CFG_NUM_RAM),
+	dump_register(SYS_CFG_NUM_TP),
+
+	dump_register(C8SECTPFE_IB_IP_FMT_CFG(0)),
+	dump_register(C8SECTPFE_IB_TAGBYTES_CFG(0)),
+	dump_register(C8SECTPFE_IB_PID_SET(0)),
+	dump_register(C8SECTPFE_IB_PKT_LEN(0)),
+	dump_register(C8SECTPFE_IB_BUFF_STRT(0)),
+	dump_register(C8SECTPFE_IB_BUFF_END(0)),
+	dump_register(C8SECTPFE_IB_READ_PNT(0)),
+	dump_register(C8SECTPFE_IB_WRT_PNT(0)),
+	dump_register(C8SECTPFE_IB_PRI_THRLD(0)),
+	dump_register(C8SECTPFE_IB_STAT(0)),
+	dump_register(C8SECTPFE_IB_MASK(0)),
+	dump_register(C8SECTPFE_IB_SYS(0)),
+
+	dump_register(C8SECTPFE_IB_IP_FMT_CFG(1)),
+	dump_register(C8SECTPFE_IB_TAGBYTES_CFG(1)),
+	dump_register(C8SECTPFE_IB_PID_SET(1)),
+	dump_register(C8SECTPFE_IB_PKT_LEN(1)),
+	dump_register(C8SECTPFE_IB_BUFF_STRT(1)),
+	dump_register(C8SECTPFE_IB_BUFF_END(1)),
+	dump_register(C8SECTPFE_IB_READ_PNT(1)),
+	dump_register(C8SECTPFE_IB_WRT_PNT(1)),
+	dump_register(C8SECTPFE_IB_PRI_THRLD(1)),
+	dump_register(C8SECTPFE_IB_STAT(1)),
+	dump_register(C8SECTPFE_IB_MASK(1)),
+	dump_register(C8SECTPFE_IB_SYS(1)),
+
+	dump_register(C8SECTPFE_IB_IP_FMT_CFG(2)),
+	dump_register(C8SECTPFE_IB_TAGBYTES_CFG(2)),
+	dump_register(C8SECTPFE_IB_PID_SET(2)),
+	dump_register(C8SECTPFE_IB_PKT_LEN(2)),
+	dump_register(C8SECTPFE_IB_BUFF_STRT(2)),
+	dump_register(C8SECTPFE_IB_BUFF_END(2)),
+	dump_register(C8SECTPFE_IB_READ_PNT(2)),
+	dump_register(C8SECTPFE_IB_WRT_PNT(2)),
+	dump_register(C8SECTPFE_IB_PRI_THRLD(2)),
+	dump_register(C8SECTPFE_IB_STAT(2)),
+	dump_register(C8SECTPFE_IB_MASK(2)),
+	dump_register(C8SECTPFE_IB_SYS(2)),
+
+	dump_register(C8SECTPFE_IB_IP_FMT_CFG(3)),
+	dump_register(C8SECTPFE_IB_TAGBYTES_CFG(3)),
+	dump_register(C8SECTPFE_IB_PID_SET(3)),
+	dump_register(C8SECTPFE_IB_PKT_LEN(3)),
+	dump_register(C8SECTPFE_IB_BUFF_STRT(3)),
+	dump_register(C8SECTPFE_IB_BUFF_END(3)),
+	dump_register(C8SECTPFE_IB_READ_PNT(3)),
+	dump_register(C8SECTPFE_IB_WRT_PNT(3)),
+	dump_register(C8SECTPFE_IB_PRI_THRLD(3)),
+	dump_register(C8SECTPFE_IB_STAT(3)),
+	dump_register(C8SECTPFE_IB_MASK(3)),
+	dump_register(C8SECTPFE_IB_SYS(3)),
+
+	dump_register(C8SECTPFE_IB_IP_FMT_CFG(4)),
+	dump_register(C8SECTPFE_IB_TAGBYTES_CFG(4)),
+	dump_register(C8SECTPFE_IB_PID_SET(4)),
+	dump_register(C8SECTPFE_IB_PKT_LEN(4)),
+	dump_register(C8SECTPFE_IB_BUFF_STRT(4)),
+	dump_register(C8SECTPFE_IB_BUFF_END(4)),
+	dump_register(C8SECTPFE_IB_READ_PNT(4)),
+	dump_register(C8SECTPFE_IB_WRT_PNT(4)),
+	dump_register(C8SECTPFE_IB_PRI_THRLD(4)),
+	dump_register(C8SECTPFE_IB_STAT(4)),
+	dump_register(C8SECTPFE_IB_MASK(4)),
+	dump_register(C8SECTPFE_IB_SYS(4)),
+
+	dump_register(C8SECTPFE_IB_IP_FMT_CFG(5)),
+	dump_register(C8SECTPFE_IB_TAGBYTES_CFG(5)),
+	dump_register(C8SECTPFE_IB_PID_SET(5)),
+	dump_register(C8SECTPFE_IB_PKT_LEN(5)),
+	dump_register(C8SECTPFE_IB_BUFF_STRT(5)),
+	dump_register(C8SECTPFE_IB_BUFF_END(5)),
+	dump_register(C8SECTPFE_IB_READ_PNT(5)),
+	dump_register(C8SECTPFE_IB_WRT_PNT(5)),
+	dump_register(C8SECTPFE_IB_PRI_THRLD(5)),
+	dump_register(C8SECTPFE_IB_STAT(5)),
+	dump_register(C8SECTPFE_IB_MASK(5)),
+	dump_register(C8SECTPFE_IB_SYS(5)),
+
+	dump_register(C8SECTPFE_IB_IP_FMT_CFG(6)),
+	dump_register(C8SECTPFE_IB_TAGBYTES_CFG(6)),
+	dump_register(C8SECTPFE_IB_PID_SET(6)),
+	dump_register(C8SECTPFE_IB_PKT_LEN(6)),
+	dump_register(C8SECTPFE_IB_BUFF_STRT(6)),
+	dump_register(C8SECTPFE_IB_BUFF_END(6)),
+	dump_register(C8SECTPFE_IB_READ_PNT(6)),
+	dump_register(C8SECTPFE_IB_WRT_PNT(6)),
+	dump_register(C8SECTPFE_IB_PRI_THRLD(6)),
+	dump_register(C8SECTPFE_IB_STAT(6)),
+	dump_register(C8SECTPFE_IB_MASK(6)),
+	dump_register(C8SECTPFE_IB_SYS(6)),
+
+	dump_register(DMA_CPU_ID),
+	dump_register(DMA_CPU_VCR),
+	dump_register(DMA_CPU_RUN),
+	dump_register(DMA_CPU_PC),
+
+	dump_register(DMA_PER_TPn_DREQ_MASK),
+	dump_register(DMA_PER_TPn_DACK_SET),
+	dump_register(DMA_PER_TPn_DREQ),
+	dump_register(DMA_PER_TPn_DACK),
+	dump_register(DMA_PER_DREQ_MODE),
+	dump_register(DMA_PER_STBUS_SYNC),
+	dump_register(DMA_PER_STBUS_ACCESS),
+	dump_register(DMA_PER_STBUS_ADDRESS),
+	dump_register(DMA_PER_IDLE_INT),
+	dump_register(DMA_PER_PRIORITY),
+	dump_register(DMA_PER_MAX_OPCODE),
+	dump_register(DMA_PER_MAX_CHUNK),
+	dump_register(DMA_PER_PAGE_SIZE),
+	dump_register(DMA_PER_MBOX_STATUS),
+	dump_register(DMA_PER_MBOX_SET),
+	dump_register(DMA_PER_MBOX_CLEAR),
+	dump_register(DMA_PER_MBOX_MASK),
+	dump_register(DMA_PER_INJECT_PKT_SRC),
+	dump_register(DMA_PER_INJECT_PKT_DEST),
+	dump_register(DMA_PER_INJECT_PKT_ADDR),
+	dump_register(DMA_PER_INJECT_PKT),
+	dump_register(DMA_PER_PAT_PTR_INIT),
+	dump_register(DMA_PER_PAT_PTR),
+	dump_register(DMA_PER_SLEEP_MASK),
+	dump_register(DMA_PER_SLEEP_COUNTER),
+
+	dump_register(DMA_FIRMWARE_VERSION),
+	dump_register(DMA_PTRREC_BASE),
+	dump_register(DMA_PTRREC_INPUT_OFFSET),
+	dump_register(DMA_ERRREC_BASE),
+
+	dump_register(DMA_ERROR_RECORD(0)),
+	dump_register(DMA_ERROR_RECORD(1)),
+	dump_register(DMA_ERROR_RECORD(2)),
+	dump_register(DMA_ERROR_RECORD(3)),
+	dump_register(DMA_ERROR_RECORD(4)),
+	dump_register(DMA_ERROR_RECORD(5)),
+	dump_register(DMA_ERROR_RECORD(6)),
+	dump_register(DMA_ERROR_RECORD(7)),
+	dump_register(DMA_ERROR_RECORD(8)),
+	dump_register(DMA_ERROR_RECORD(9)),
+	dump_register(DMA_ERROR_RECORD(10)),
+	dump_register(DMA_ERROR_RECORD(11)),
+	dump_register(DMA_ERROR_RECORD(12)),
+	dump_register(DMA_ERROR_RECORD(13)),
+	dump_register(DMA_ERROR_RECORD(14)),
+	dump_register(DMA_ERROR_RECORD(15)),
+	dump_register(DMA_ERROR_RECORD(16)),
+	dump_register(DMA_ERROR_RECORD(17)),
+	dump_register(DMA_ERROR_RECORD(18)),
+	dump_register(DMA_ERROR_RECORD(19)),
+	dump_register(DMA_ERROR_RECORD(20)),
+	dump_register(DMA_ERROR_RECORD(21)),
+	dump_register(DMA_ERROR_RECORD(22)),
+
+	dump_register(DMA_IDLE_REQ),
+	dump_register(DMA_FIRMWARE_CONFIG),
+
+	dump_register(PIDF_BASE(0)),
+	dump_register(PIDF_BASE(1)),
+	dump_register(PIDF_BASE(2)),
+	dump_register(PIDF_BASE(3)),
+	dump_register(PIDF_BASE(4)),
+	dump_register(PIDF_BASE(5)),
+	dump_register(PIDF_BASE(6)),
+	dump_register(PIDF_BASE(7)),
+	dump_register(PIDF_BASE(8)),
+	dump_register(PIDF_BASE(9)),
+	dump_register(PIDF_BASE(10)),
+	dump_register(PIDF_BASE(11)),
+	dump_register(PIDF_BASE(12)),
+	dump_register(PIDF_BASE(13)),
+	dump_register(PIDF_BASE(14)),
+	dump_register(PIDF_BASE(15)),
+	dump_register(PIDF_BASE(16)),
+	dump_register(PIDF_BASE(17)),
+	dump_register(PIDF_BASE(18)),
+	dump_register(PIDF_BASE(19)),
+	dump_register(PIDF_BASE(20)),
+	dump_register(PIDF_BASE(21)),
+	dump_register(PIDF_BASE(22)),
+	dump_register(PIDF_LEAK_ENABLE),
+	dump_register(PIDF_LEAK_STATUS),
+	dump_register(PIDF_LEAK_COUNT_RESET),
+	dump_register(PIDF_LEAK_COUNTER),
+};
+
+void c8sectpfe_debugfs_init(struct c8sectpfei *fei)
+{
+	struct dentry		*root;
+	struct dentry		*file;
+
+	root = debugfs_create_dir("c8sectpfe", NULL);
+	if (!root)
+		goto err;
+
+	fei->root = root;
+
+	fei->regset =  devm_kzalloc(fei->dev, sizeof(*fei->regset), GFP_KERNEL);
+	if (!fei->regset)
+		goto err;
+
+	fei->regset->regs = fei_sys_regs;
+	fei->regset->nregs = ARRAY_SIZE(fei_sys_regs);
+	fei->regset->base = fei->io;
+
+	file = debugfs_create_regset32("registers", S_IRUGO, root,
+				fei->regset);
+	if (!file) {
+		dev_err(fei->dev,
+			"%s not able to create 'registers' debugfs\n"
+			, __func__);
+		goto err;
+	}
+
+	return;
+
+err:
+	debugfs_remove_recursive(root);
+}
+
+void c8sectpfe_debugfs_exit(struct c8sectpfei *fei)
+{
+	debugfs_remove_recursive(fei->root);
+	fei->root = NULL;
+}
diff --git a/drivers/media/tsin/c8sectpfe/c8sectpfe-debugfs.h b/drivers/media/tsin/c8sectpfe/c8sectpfe-debugfs.h
new file mode 100644
index 0000000..8af1ac1
--- /dev/null
+++ b/drivers/media/tsin/c8sectpfe/c8sectpfe-debugfs.h
@@ -0,0 +1,26 @@
+/**
+ * c8sectpfe-debugfs.h - C8SECTPFE STi DVB driver debugfs header
+ *
+ * Copyright (c) STMicroelectronics 2015
+ *
+ * Authors: Peter Griffin <peter.griffin@linaro.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __C8SECTPFE_DEBUG_H
+#define __C8SECTPFE_DEBUG_H
+
+#include "c8sectpfe-core.h"
+
+void c8sectpfe_debugfs_init(struct c8sectpfei *);
+void c8sectpfe_debugfs_exit(struct c8sectpfei *);
+
+#endif /* __C8SECTPFE_DEBUG_H */
-- 
1.9.1


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

* [PATCH 11/12] [media] tsin: c8sectpfe: Add Kconfig and Makefile for the driver.
  2015-06-24 15:10 [PATCH 00/12] Add c8sectpfe LinuxDVB demux driver Peter Griffin
                   ` (9 preceding siblings ...)
  2015-06-24 15:11 ` [PATCH 10/12] [media] tsin: c8sectpfe: Add c8sectpfe debugfs support Peter Griffin
@ 2015-06-24 15:11 ` Peter Griffin
  2015-06-25  7:23   ` Paul Bolle
  2015-07-22 21:56   ` Mauro Carvalho Chehab
  2015-06-24 15:11 ` [PATCH 12/12] MAINTAINERS: Add c8sectpfe driver directory to STi section Peter Griffin
  11 siblings, 2 replies; 32+ messages in thread
From: Peter Griffin @ 2015-06-24 15:11 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, srinivas.kandagatla,
	maxime.coquelin, patrice.chotard, mchehab
  Cc: peter.griffin, lee.jones, hugues.fruchet, linux-media, devicetree

This patch adds the Kconfig and Makefile for the c8sectpfe driver
so it will be built. It also selects additional demodulator and tuners
which are required by the supported NIM cards.

Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
---
 drivers/media/Kconfig                 |  1 +
 drivers/media/Makefile                |  1 +
 drivers/media/tsin/c8sectpfe/Kconfig  | 26 ++++++++++++++++++++++++++
 drivers/media/tsin/c8sectpfe/Makefile | 11 +++++++++++
 4 files changed, 39 insertions(+)
 create mode 100644 drivers/media/tsin/c8sectpfe/Kconfig
 create mode 100644 drivers/media/tsin/c8sectpfe/Makefile

diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index 1570992..82bc1dc 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -170,6 +170,7 @@ source "drivers/media/pci/Kconfig"
 source "drivers/media/platform/Kconfig"
 source "drivers/media/mmc/Kconfig"
 source "drivers/media/radio/Kconfig"
+source "drivers/media/tsin/c8sectpfe/Kconfig"
 
 comment "Supported FireWire (IEEE 1394) Adapters"
 	depends on DVB_CORE && FIREWIRE
diff --git a/drivers/media/Makefile b/drivers/media/Makefile
index e608bbc..0a567b8 100644
--- a/drivers/media/Makefile
+++ b/drivers/media/Makefile
@@ -29,5 +29,6 @@ obj-y += rc/
 #
 
 obj-y += common/ platform/ pci/ usb/ mmc/ firewire/
+obj-$(CONFIG_DVB_C8SECTPFE) += tsin/c8sectpfe/
 obj-$(CONFIG_VIDEO_DEV) += radio/
 
diff --git a/drivers/media/tsin/c8sectpfe/Kconfig b/drivers/media/tsin/c8sectpfe/Kconfig
new file mode 100644
index 0000000..8d99a87
--- /dev/null
+++ b/drivers/media/tsin/c8sectpfe/Kconfig
@@ -0,0 +1,26 @@
+config DVB_C8SECTPFE
+	tristate "STMicroelectronics C8SECTPFE DVB support"
+	depends on DVB_CORE && I2C && (ARCH_STI || ARCH_MULTIPLATFORM)
+	select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STV6110 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STV0900 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STV0367 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_TDA18212 if MEDIA_SUBDRV_AUTOSELECT
+
+	---help---
+	  This adds support for DVB front-end cards connected
+	  to TS inputs of STiH407/410 SoC.
+
+	  The driver currently supports C8SECTPFE's TS input block,
+	  memdma engine, and HW PID filtering.
+
+	  Supported DVB front-end cards are:
+	  - STMicroelectronics DVB-T B2100A (STV0367 + TDA18212)
+	  - STMicroelectronics DVB-T STV0367 PLL board (STV0367 + DTT7546X)
+	  - STMicroelectronics DVB-S/S2 STV0903 + STV6110 + LNBP24 board
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called c8sectpfe.
diff --git a/drivers/media/tsin/c8sectpfe/Makefile b/drivers/media/tsin/c8sectpfe/Makefile
new file mode 100644
index 0000000..777f06d
--- /dev/null
+++ b/drivers/media/tsin/c8sectpfe/Makefile
@@ -0,0 +1,11 @@
+c8sectpfe-y += c8sectpfe-core.o c8sectpfe-common.o c8sectpfe-dvb.o
+
+obj-$(CONFIG_DVB_C8SECTPFE) += c8sectpfe.o
+
+ifneq ($(CONFIG_DVB_C8SECTPFE),)
+	c8sectpfe-y += c8sectpfe-debugfs.o
+endif
+
+ccflags-y += -Idrivers/media/i2c
+ccflags-y += -Idrivers/media/common
+ccflags-y += -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends/ -Idrivers/media/tuners/
-- 
1.9.1


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

* [PATCH 12/12] MAINTAINERS: Add c8sectpfe driver directory to STi section
  2015-06-24 15:10 [PATCH 00/12] Add c8sectpfe LinuxDVB demux driver Peter Griffin
                   ` (10 preceding siblings ...)
  2015-06-24 15:11 ` [PATCH 11/12] [media] tsin: c8sectpfe: Add Kconfig and Makefile for the driver Peter Griffin
@ 2015-06-24 15:11 ` Peter Griffin
  11 siblings, 0 replies; 32+ messages in thread
From: Peter Griffin @ 2015-06-24 15:11 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, srinivas.kandagatla,
	maxime.coquelin, patrice.chotard, mchehab
  Cc: peter.griffin, lee.jones, hugues.fruchet, linux-media, devicetree

Add the new c8sectpfe demux driver to the STi section of the
MAINTAINERS file.

Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index d8afd29..49c8963 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1481,6 +1481,7 @@ F:	arch/arm/boot/dts/sti*
 F:	drivers/clocksource/arm_global_timer.c
 F:	drivers/i2c/busses/i2c-st.c
 F:	drivers/media/rc/st_rc.c
+F:	drivers/media/tsin/c8sectpfe/
 F:	drivers/mmc/host/sdhci-st.c
 F:	drivers/phy/phy-miphy28lp.c
 F:	drivers/phy/phy-miphy365x.c
-- 
1.9.1


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

* Re: [PATCH 02/12] [media] dvb-pll: Add support for THOMSON DTT7546X tuner.
  2015-06-24 15:11 ` [PATCH 02/12] [media] dvb-pll: Add support for THOMSON DTT7546X tuner Peter Griffin
@ 2015-06-25  1:17   ` Joe Perches
  2015-07-22 21:58     ` Mauro Carvalho Chehab
  2015-07-22 17:10   ` Mauro Carvalho Chehab
  1 sibling, 1 reply; 32+ messages in thread
From: Joe Perches @ 2015-06-25  1:17 UTC (permalink / raw)
  To: Peter Griffin
  Cc: linux-arm-kernel, linux-kernel, srinivas.kandagatla,
	maxime.coquelin, patrice.chotard, mchehab, lee.jones,
	hugues.fruchet, linux-media, devicetree

On Wed, 2015-06-24 at 16:11 +0100, Peter Griffin wrote:
> This is used in conjunction with the STV0367 demodulator on
> the STV0367-NIM-V1.0 NIM card which can be used with the STi
> STB SoC's.

Barely associated to this specific patch, but for
dvb-pll.c, another thing that seems possible is to
convert the struct dvb_pll_desc uses to const and
change the "entries" fixed array size from 12 to []

It'd save a couple KB overall and remove ~5KB of data.

$ size drivers/media/dvb-frontends/dvb-pll.o*
   text	   data	    bss	    dec	    hex	filename
   8520	   1552	   2120	  12192	   2fa0	drivers/media/dvb-frontends/dvb-pll.o.new
   5624	   6363	   2120	  14107	   371b	drivers/media/dvb-frontends/dvb-pll.o.old
---
 drivers/media/dvb-frontends/dvb-pll.c | 50 +++++++++++++++++------------------
 1 file changed, 25 insertions(+), 25 deletions(-)

diff --git a/drivers/media/dvb-frontends/dvb-pll.c b/drivers/media/dvb-frontends/dvb-pll.c
index 6d8fe88..53089e1 100644
--- a/drivers/media/dvb-frontends/dvb-pll.c
+++ b/drivers/media/dvb-frontends/dvb-pll.c
@@ -34,7 +34,7 @@ struct dvb_pll_priv {
 	struct i2c_adapter *i2c;
 
 	/* the PLL descriptor */
-	struct dvb_pll_desc *pll_desc;
+	const struct dvb_pll_desc *pll_desc;
 
 	/* cached frequency/bandwidth */
 	u32 frequency;
@@ -57,7 +57,7 @@ MODULE_PARM_DESC(id, "force pll id to use (DEBUG ONLY)");
 /* ----------------------------------------------------------- */
 
 struct dvb_pll_desc {
-	char *name;
+	const char *name;
 	u32  min;
 	u32  max;
 	u32  iffreq;
@@ -71,13 +71,13 @@ struct dvb_pll_desc {
 		u32 stepsize;
 		u8  config;
 		u8  cb;
-	} entries[12];
+	} entries[];
 };
 
 /* ----------------------------------------------------------- */
 /* descriptions                                                */
 
-static struct dvb_pll_desc dvb_pll_thomson_dtt7579 = {
+static const struct dvb_pll_desc dvb_pll_thomson_dtt7579 = {
 	.name  = "Thomson dtt7579",
 	.min   = 177000000,
 	.max   = 858000000,
@@ -99,7 +99,7 @@ static void thomson_dtt759x_bw(struct dvb_frontend *fe, u8 *buf)
 		buf[3] |= 0x10;
 }
 
-static struct dvb_pll_desc dvb_pll_thomson_dtt759x = {
+static const struct dvb_pll_desc dvb_pll_thomson_dtt759x = {
 	.name  = "Thomson dtt759x",
 	.min   = 177000000,
 	.max   = 896000000,
@@ -123,7 +123,7 @@ static void thomson_dtt7520x_bw(struct dvb_frontend *fe, u8 *buf)
 		buf[3] ^= 0x10;
 }
 
-static struct dvb_pll_desc dvb_pll_thomson_dtt7520x = {
+static const struct dvb_pll_desc dvb_pll_thomson_dtt7520x = {
 	.name  = "Thomson dtt7520x",
 	.min   = 185000000,
 	.max   = 900000000,
@@ -141,7 +141,7 @@ static struct dvb_pll_desc dvb_pll_thomson_dtt7520x = {
 	},
 };
 
-static struct dvb_pll_desc dvb_pll_lg_z201 = {
+static const struct dvb_pll_desc dvb_pll_lg_z201 = {
 	.name  = "LG z201",
 	.min   = 174000000,
 	.max   = 862000000,
@@ -157,7 +157,7 @@ static struct dvb_pll_desc dvb_pll_lg_z201 = {
 	},
 };
 
-static struct dvb_pll_desc dvb_pll_unknown_1 = {
+static const struct dvb_pll_desc dvb_pll_unknown_1 = {
 	.name  = "unknown 1", /* used by dntv live dvb-t */
 	.min   = 174000000,
 	.max   = 862000000,
@@ -179,7 +179,7 @@ static struct dvb_pll_desc dvb_pll_unknown_1 = {
 /* Infineon TUA6010XS
  * used in Thomson Cable Tuner
  */
-static struct dvb_pll_desc dvb_pll_tua6010xs = {
+static const struct dvb_pll_desc dvb_pll_tua6010xs = {
 	.name  = "Infineon TUA6010XS",
 	.min   =  44250000,
 	.max   = 858000000,
@@ -193,7 +193,7 @@ static struct dvb_pll_desc dvb_pll_tua6010xs = {
 };
 
 /* Panasonic env57h1xd5 (some Philips PLL ?) */
-static struct dvb_pll_desc dvb_pll_env57h1xd5 = {
+static const struct dvb_pll_desc dvb_pll_env57h1xd5 = {
 	.name  = "Panasonic ENV57H1XD5",
 	.min   =  44250000,
 	.max   = 858000000,
@@ -217,7 +217,7 @@ static void tda665x_bw(struct dvb_frontend *fe, u8 *buf)
 		buf[3] |= 0x08;
 }
 
-static struct dvb_pll_desc dvb_pll_tda665x = {
+static const struct dvb_pll_desc dvb_pll_tda665x = {
 	.name  = "Philips TDA6650/TDA6651",
 	.min   =  44250000,
 	.max   = 858000000,
@@ -251,7 +251,7 @@ static void tua6034_bw(struct dvb_frontend *fe, u8 *buf)
 		buf[3] |= 0x08;
 }
 
-static struct dvb_pll_desc dvb_pll_tua6034 = {
+static const struct dvb_pll_desc dvb_pll_tua6034 = {
 	.name  = "Infineon TUA6034",
 	.min   =  44250000,
 	.max   = 858000000,
@@ -275,7 +275,7 @@ static void tded4_bw(struct dvb_frontend *fe, u8 *buf)
 		buf[3] |= 0x04;
 }
 
-static struct dvb_pll_desc dvb_pll_tded4 = {
+static const struct dvb_pll_desc dvb_pll_tded4 = {
 	.name = "ALPS TDED4",
 	.min = 47000000,
 	.max = 863000000,
@@ -293,7 +293,7 @@ static struct dvb_pll_desc dvb_pll_tded4 = {
 /* ALPS TDHU2
  * used in AverTVHD MCE A180
  */
-static struct dvb_pll_desc dvb_pll_tdhu2 = {
+static const struct dvb_pll_desc dvb_pll_tdhu2 = {
 	.name = "ALPS TDHU2",
 	.min = 54000000,
 	.max = 864000000,
@@ -310,7 +310,7 @@ static struct dvb_pll_desc dvb_pll_tdhu2 = {
 /* Samsung TBMV30111IN / TBMV30712IN1
  * used in Air2PC ATSC - 2nd generation (nxt2002)
  */
-static struct dvb_pll_desc dvb_pll_samsung_tbmv = {
+static const struct dvb_pll_desc dvb_pll_samsung_tbmv = {
 	.name = "Samsung TBMV30111IN / TBMV30712IN1",
 	.min = 54000000,
 	.max = 860000000,
@@ -329,7 +329,7 @@ static struct dvb_pll_desc dvb_pll_samsung_tbmv = {
 /*
  * Philips SD1878 Tuner.
  */
-static struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = {
+static const struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = {
 	.name  = "Philips SD1878",
 	.min   =  950000,
 	.max   = 2150000,
@@ -395,7 +395,7 @@ static void opera1_bw(struct dvb_frontend *fe, u8 *buf)
 	return;
 }
 
-static struct dvb_pll_desc dvb_pll_opera1 = {
+static const struct dvb_pll_desc dvb_pll_opera1 = {
 	.name  = "Opera Tuner",
 	.min   =  900000,
 	.max   = 2250000,
@@ -442,7 +442,7 @@ static void samsung_dtos403ih102a_set(struct dvb_frontend *fe, u8 *buf)
 }
 
 /* unknown pll used in Samsung DTOS403IH102A DVB-C tuner */
-static struct dvb_pll_desc dvb_pll_samsung_dtos403ih102a = {
+static const struct dvb_pll_desc dvb_pll_samsung_dtos403ih102a = {
 	.name   = "Samsung DTOS403IH102A",
 	.min    =  44250000,
 	.max    = 858000000,
@@ -462,7 +462,7 @@ static struct dvb_pll_desc dvb_pll_samsung_dtos403ih102a = {
 };
 
 /* Samsung TDTC9251DH0 DVB-T NIM, as used on AirStar 2 */
-static struct dvb_pll_desc dvb_pll_samsung_tdtc9251dh0 = {
+static const struct dvb_pll_desc dvb_pll_samsung_tdtc9251dh0 = {
 	.name	= "Samsung TDTC9251DH0",
 	.min	=  48000000,
 	.max	= 863000000,
@@ -476,7 +476,7 @@ static struct dvb_pll_desc dvb_pll_samsung_tdtc9251dh0 = {
 };
 
 /* Samsung TBDU18132 DVB-S NIM with TSA5059 PLL, used in SkyStar2 DVB-S 2.3 */
-static struct dvb_pll_desc dvb_pll_samsung_tbdu18132 = {
+static const struct dvb_pll_desc dvb_pll_samsung_tbdu18132 = {
 	.name = "Samsung TBDU18132",
 	.min	=  950000,
 	.max	= 2150000, /* guesses */
@@ -497,7 +497,7 @@ static struct dvb_pll_desc dvb_pll_samsung_tbdu18132 = {
 };
 
 /* Samsung TBMU24112 DVB-S NIM with SL1935 zero-IF tuner */
-static struct dvb_pll_desc dvb_pll_samsung_tbmu24112 = {
+static const struct dvb_pll_desc dvb_pll_samsung_tbmu24112 = {
 	.name = "Samsung TBMU24112",
 	.min	=  950000,
 	.max	= 2150000, /* guesses */
@@ -518,7 +518,7 @@ static struct dvb_pll_desc dvb_pll_samsung_tbmu24112 = {
  * 153 - 430   0  *  0   0   0   0   1   0   0x02
  * 430 - 822   0  *  0   0   1   0   0   0   0x08
  * 822 - 862   1  *  0   0   1   0   0   0   0x88 */
-static struct dvb_pll_desc dvb_pll_alps_tdee4 = {
+static const struct dvb_pll_desc dvb_pll_alps_tdee4 = {
 	.name = "ALPS TDEE4",
 	.min	=  47000000,
 	.max	= 862000000,
@@ -534,7 +534,7 @@ static struct dvb_pll_desc dvb_pll_alps_tdee4 = {
 
 /* ----------------------------------------------------------- */
 
-static struct dvb_pll_desc *pll_list[] = {
+static const struct dvb_pll_desc *pll_list[] = {
 	[DVB_PLL_UNDEFINED]              = NULL,
 	[DVB_PLL_THOMSON_DTT7579]        = &dvb_pll_thomson_dtt7579,
 	[DVB_PLL_THOMSON_DTT759X]        = &dvb_pll_thomson_dtt759x,
@@ -564,7 +564,7 @@ static int dvb_pll_configure(struct dvb_frontend *fe, u8 *buf,
 			     const u32 frequency)
 {
 	struct dvb_pll_priv *priv = fe->tuner_priv;
-	struct dvb_pll_desc *desc = priv->pll_desc;
+	const struct dvb_pll_desc *desc = priv->pll_desc;
 	u32 div;
 	int i;
 
@@ -758,7 +758,7 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
 			       .buf = b1, .len = 1 };
 	struct dvb_pll_priv *priv = NULL;
 	int ret;
-	struct dvb_pll_desc *desc;
+	const struct dvb_pll_desc *desc;
 
 	if ((id[dvb_pll_devcount] > DVB_PLL_UNDEFINED) &&
 	    (id[dvb_pll_devcount] < ARRAY_SIZE(pll_list)))



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

* Re: [PATCH 11/12] [media] tsin: c8sectpfe: Add Kconfig and Makefile for the driver.
  2015-06-24 15:11 ` [PATCH 11/12] [media] tsin: c8sectpfe: Add Kconfig and Makefile for the driver Peter Griffin
@ 2015-06-25  7:23   ` Paul Bolle
  2015-07-22  7:38     ` Peter Griffin
  2015-07-22 21:56   ` Mauro Carvalho Chehab
  1 sibling, 1 reply; 32+ messages in thread
From: Paul Bolle @ 2015-06-25  7:23 UTC (permalink / raw)
  To: Peter Griffin, linux-arm-kernel, linux-kernel,
	srinivas.kandagatla, maxime.coquelin, patrice.chotard, mchehab
  Cc: lee.jones, hugues.fruchet, linux-media, devicetree

On Wed, 2015-06-24 at 16:11 +0100, Peter Griffin wrote:
> --- /dev/null
> +++ b/drivers/media/tsin/c8sectpfe/Makefile

> +c8sectpfe-y += c8sectpfe-core.o c8sectpfe-common.o c8sectpfe-dvb.o
> +
> +obj-$(CONFIG_DVB_C8SECTPFE) += c8sectpfe.o
> +
> +ifneq ($(CONFIG_DVB_C8SECTPFE),)
> +	c8sectpfe-y += c8sectpfe-debugfs.o
> +endif

Isn't the above equivalent to
    c8sectpfe-y += c8sectpfe-core.o c8sectpfe-common.o c8sectpfe-dvb.o c8sectpfe-debugfs.o

    obj-$(CONFIG_DVB_C8SECTPFE) += c8sectpfe.o

Or am I missing something subtle here?


Paul Bolle

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

* Re: [PATCH 11/12] [media] tsin: c8sectpfe: Add Kconfig and Makefile for the driver.
  2015-06-25  7:23   ` Paul Bolle
@ 2015-07-22  7:38     ` Peter Griffin
  0 siblings, 0 replies; 32+ messages in thread
From: Peter Griffin @ 2015-07-22  7:38 UTC (permalink / raw)
  To: Paul Bolle
  Cc: linux-arm-kernel, linux-kernel, srinivas.kandagatla,
	maxime.coquelin, patrice.chotard, mchehab, lee.jones,
	hugues.fruchet, linux-media, devicetree

Hi Paul,

Thanks for reviewing.

On Thu, 25 Jun 2015, Paul Bolle wrote:

> On Wed, 2015-06-24 at 16:11 +0100, Peter Griffin wrote:
> > --- /dev/null
> > +++ b/drivers/media/tsin/c8sectpfe/Makefile
> 
> > +c8sectpfe-y += c8sectpfe-core.o c8sectpfe-common.o c8sectpfe-dvb.o
> > +
> > +obj-$(CONFIG_DVB_C8SECTPFE) += c8sectpfe.o
> > +
> > +ifneq ($(CONFIG_DVB_C8SECTPFE),)
> > +	c8sectpfe-y += c8sectpfe-debugfs.o
> > +endif
> 
> Isn't the above equivalent to
>     c8sectpfe-y += c8sectpfe-core.o c8sectpfe-common.o c8sectpfe-dvb.o c8sectpfe-debugfs.o
> 
>     obj-$(CONFIG_DVB_C8SECTPFE) += c8sectpfe.o
> 
> Or am I missing something subtle here?

No I think I just messed up. Will fix in v2.

I suspect what happened  was I was starting to add a CONFIG_DVB_C8SECTPFE_DEBUGFS
Kconfig option, and then forgot ;)

In v2 I have added a "select DEBUG_FS" to Kconfig for the driver, and put it all on one
line. Also at the same time fixing some other Kconfig dependencies I noticed so
it now has 'select LIBELF_32' and 'select FW_LOADER'.

regards,

Peter.



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

* Re: [PATCH 02/12] [media] dvb-pll: Add support for THOMSON DTT7546X tuner.
  2015-06-24 15:11 ` [PATCH 02/12] [media] dvb-pll: Add support for THOMSON DTT7546X tuner Peter Griffin
  2015-06-25  1:17   ` Joe Perches
@ 2015-07-22 17:10   ` Mauro Carvalho Chehab
  2015-07-30  9:46     ` Peter Griffin
  1 sibling, 1 reply; 32+ messages in thread
From: Mauro Carvalho Chehab @ 2015-07-22 17:10 UTC (permalink / raw)
  To: Peter Griffin
  Cc: linux-arm-kernel, linux-kernel, srinivas.kandagatla,
	maxime.coquelin, patrice.chotard, lee.jones, hugues.fruchet,
	linux-media, devicetree

Em Wed, 24 Jun 2015 16:11:00 +0100
Peter Griffin <peter.griffin@linaro.org> escreveu:

> This is used in conjunction with the STV0367 demodulator on
> the STV0367-NIM-V1.0 NIM card which can be used with the STi
> STB SoC's.
> 
> This tuner has a fifth register, so some changes have been made
> to accommodate this.
> 
> Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
> ---
>  drivers/media/dvb-frontends/dvb-pll.c | 74 +++++++++++++++++++++++++++++------
>  drivers/media/dvb-frontends/dvb-pll.h |  1 +
>  2 files changed, 64 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/media/dvb-frontends/dvb-pll.c b/drivers/media/dvb-frontends/dvb-pll.c
> index 6d8fe88..f7381c7 100644
> --- a/drivers/media/dvb-frontends/dvb-pll.c
> +++ b/drivers/media/dvb-frontends/dvb-pll.c
> @@ -141,6 +141,35 @@ static struct dvb_pll_desc dvb_pll_thomson_dtt7520x = {
>  	},
>  };
>  
> +static void thomson_dtt7546x_bw(struct dvb_frontend *fe, u8 *buf)
> +{
> +	/* set CB2 reg - set ATC, XTO */
> +	buf[4] = 0xc3;
> +}
> +
> +static struct dvb_pll_desc dvb_pll_thomson_dtt7546x = {
> +	.name  = "Thomson dtt7546x",
> +	.min   = 44250000,
> +	.max   = 863250000,
> +	.set   = thomson_dtt7546x_bw,
> +	.iffreq= 36166667,

Whitespace is missing. Please check the patchs with scripts/checkpatch.pl.

> +	.count = 12,
> +	.entries = {
> +		{  121000000, 166667, 0x88, 0x01 },
> +		{  141000000, 166667, 0x88, 0x41 },
> +		{  166000000, 166667, 0x88, 0x81 },
> +		{  182000000, 166667, 0x88, 0xc1 },
> +		{  286000000, 166667, 0x88, 0x02 },
> +		{  386000000, 166667, 0x88, 0x42 },
> +		{  446000000, 166667, 0x88, 0x82 },
> +		{  466000000, 166667, 0x88, 0xc2 },
> +		{  506000000, 166667, 0x88, 0x08 },
> +		{  761000000, 166667, 0x88, 0x48 },
> +		{  846000000, 166667, 0x88, 0x88 },
> +		{  905000000, 166667, 0x88, 0xc8 },
> +	},
> +};
> +
>  static struct dvb_pll_desc dvb_pll_lg_z201 = {
>  	.name  = "LG z201",
>  	.min   = 174000000,
> @@ -537,6 +566,7 @@ static struct dvb_pll_desc dvb_pll_alps_tdee4 = {
>  static struct dvb_pll_desc *pll_list[] = {
>  	[DVB_PLL_UNDEFINED]              = NULL,
>  	[DVB_PLL_THOMSON_DTT7579]        = &dvb_pll_thomson_dtt7579,
> +	[DVB_PLL_THOMSON_DTT7546X]       = &dvb_pll_thomson_dtt7546x,
>  	[DVB_PLL_THOMSON_DTT759X]        = &dvb_pll_thomson_dtt759x,
>  	[DVB_PLL_THOMSON_DTT7520X]       = &dvb_pll_thomson_dtt7520x,
>  	[DVB_PLL_LG_Z201]                = &dvb_pll_lg_z201,
> @@ -561,7 +591,7 @@ static struct dvb_pll_desc *pll_list[] = {
>  /* code                                                        */
>  
>  static int dvb_pll_configure(struct dvb_frontend *fe, u8 *buf,
> -			     const u32 frequency)
> +			const u32 frequency, const u32 len)
>  {
>  	struct dvb_pll_priv *priv = fe->tuner_priv;
>  	struct dvb_pll_desc *desc = priv->pll_desc;
> @@ -593,11 +623,15 @@ static int dvb_pll_configure(struct dvb_frontend *fe, u8 *buf,
>  	if (desc->set)
>  		desc->set(fe, buf);
>  
> -	if (debug)
> -		printk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n",
> -		       desc->name, div, buf[0], buf[1], buf[2], buf[3]);
> +	if (debug) {
> +		printk(KERN_DEBUG "pll: %s: div=%d | buf=", desc->name, div);
> +		for (i = 0; i < len; i++)
> +			printk(KERN_DEBUG "0x%02x,", buf[i]);
>  
> -	// calculate the frequency we set it to
> +		printk(KERN_DEBUG "\n");
> +	}

Please use, instead, the Documentation/printk-formats.txt macros to
print an hex buffer:

	"Raw buffer as a hex string:
		%*ph	00 01 02  ...  3f
		%*phC	00:01:02: ... :3f
		%*phD	00-01-02- ... -3f
		%*phN	000102 ... 3f"


> +
> +	/* calculate the frequency we set it to */
>  	return (div * desc->entries[i].stepsize) - desc->iffreq;
>  }
>  
> @@ -634,21 +668,39 @@ static int dvb_pll_sleep(struct dvb_frontend *fe)
>  	return -EINVAL;
>  }
>  
> +static int dvb_pll_get_num_regs(struct dvb_pll_priv *priv)
> +{
> +	int num_regs = 4;
> +
> +	if (strncmp(priv->pll_desc->name, "Thomson dtt7546x", 16) == 0)
> +		num_regs = 5;
> +
> +	return num_regs;
> +}
> +
>  static int dvb_pll_set_params(struct dvb_frontend *fe)
>  {
>  	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
>  	struct dvb_pll_priv *priv = fe->tuner_priv;
> -	u8 buf[4];
> -	struct i2c_msg msg =
> -		{ .addr = priv->pll_i2c_address, .flags = 0,
> -		  .buf = buf, .len = sizeof(buf) };
> +	struct i2c_msg msg;
> +	u8 *bufp;
>  	int result;
>  	u32 frequency = 0;
>  
> +	bufp = kzalloc(dvb_pll_get_num_regs(priv), GFP_KERNEL);
> +
> +	if (!bufp)
> +		return -ENOMEM;
> +
> +	msg.addr = priv->pll_i2c_address;
> +	msg.flags = 0;
> +	msg.buf = bufp;
> +	msg.len = dvb_pll_get_num_regs(priv);
> +
>  	if (priv->i2c == NULL)
>  		return -EINVAL;
>  
> -	result = dvb_pll_configure(fe, buf, c->frequency);
> +	result = dvb_pll_configure(fe, bufp, c->frequency, msg.len);
>  	if (result < 0)
>  		return result;
>  	else
> @@ -677,7 +729,7 @@ static int dvb_pll_calc_regs(struct dvb_frontend *fe,
>  	if (buf_len < 5)
>  		return -EINVAL;
>  
> -	result = dvb_pll_configure(fe, buf + 1, c->frequency);
> +	result = dvb_pll_configure(fe, buf + 1, c->frequency, buf_len - 1);
>  	if (result < 0)
>  		return result;
>  	else
> diff --git a/drivers/media/dvb-frontends/dvb-pll.h b/drivers/media/dvb-frontends/dvb-pll.h
> index bf9602a..f523f42 100644
> --- a/drivers/media/dvb-frontends/dvb-pll.h
> +++ b/drivers/media/dvb-frontends/dvb-pll.h
> @@ -28,6 +28,7 @@
>  #define DVB_PLL_SAMSUNG_TBMU24112      17
>  #define DVB_PLL_TDEE4		       18
>  #define DVB_PLL_THOMSON_DTT7520X       19
> +#define DVB_PLL_THOMSON_DTT7546X       20
>  
>  /**
>   * Attach a dvb-pll to the supplied frontend structure.

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

* Re: [PATCH 07/12] [media] tsin: c8sectpfe: STiH407/10 Linux DVB demux support
  2015-06-24 15:11 ` [PATCH 07/12] [media] tsin: c8sectpfe: STiH407/10 Linux DVB demux support Peter Griffin
@ 2015-07-22 21:46   ` Mauro Carvalho Chehab
  2015-07-30 11:08     ` Peter Griffin
  0 siblings, 1 reply; 32+ messages in thread
From: Mauro Carvalho Chehab @ 2015-07-22 21:46 UTC (permalink / raw)
  To: Peter Griffin
  Cc: linux-arm-kernel, linux-kernel, srinivas.kandagatla,
	maxime.coquelin, patrice.chotard, lee.jones, hugues.fruchet,
	linux-media, devicetree

Em Wed, 24 Jun 2015 16:11:05 +0100
Peter Griffin <peter.griffin@linaro.org> escreveu:

> This patch adds support for the c8sectpfe input HW found on
> STiH407/410 SoC's.
> 
> It currently supports the TS input block, memdma engine
> and hw PID filtering blocks of the C8SECTPFE subsystem.
> 
> The driver creates one LinuxDVB adapter, and a
> demux/dvr/frontend set of devices for each tsin channel
> which is specificed in the DT. It has been tested with
> multiple tsin channels tuned, locked, and grabbing TS
> simultaneously.
> 
> Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
> ---
>  drivers/media/tsin/c8sectpfe/c8sectpfe-core.c | 1105 +++++++++++++++++++++++++
>  drivers/media/tsin/c8sectpfe/c8sectpfe-core.h |  288 +++++++
>  2 files changed, 1393 insertions(+)
>  create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-core.c
>  create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-core.h
> 
> diff --git a/drivers/media/tsin/c8sectpfe/c8sectpfe-core.c b/drivers/media/tsin/c8sectpfe/c8sectpfe-core.c
> new file mode 100644
> index 0000000..fbbe323
> --- /dev/null
> +++ b/drivers/media/tsin/c8sectpfe/c8sectpfe-core.c
> @@ -0,0 +1,1105 @@
> +/*
> + * c8sectpfe-core.c - C8SECTPFE STi DVB driver
> + *
> + * Copyright (c) STMicroelectronics 2015
> + *
> + *   Author:Peter Bennett <peter.bennett@st.com>
> + *	    Peter Griffin <peter.griffin@linaro.org>
> + *
> + *	This program is free software; you can redistribute it and/or
> + *	modify it under the terms of the GNU General Public License as
> + *	published by the Free Software Foundation; either version 2 of
> + *	the License, or (at your option) any later version.
> + */
> +#include <linux/clk.h>
> +#include <linux/completion.h>
> +#include <linux/delay.h>
> +#include <linux/device.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/dvb/dmx.h>
> +#include <linux/dvb/frontend.h>
> +#include <linux/errno.h>
> +#include <linux/firmware.h>
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of_gpio.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/usb.h>
> +#include <linux/slab.h>
> +#include <linux/time.h>
> +#include <linux/version.h>
> +#include <linux/wait.h>
> +
> +#include "c8sectpfe-core.h"
> +#include "c8sectpfe-common.h"
> +#include "c8sectpfe-debugfs.h"
> +#include "dmxdev.h"
> +#include "dvb_demux.h"
> +#include "dvb_frontend.h"
> +#include "dvb_net.h"
> +
> +#define FIRMWARE_MEMDMA "pti_memdma_h407.elf"
> +MODULE_FIRMWARE(FIRMWARE_MEMDMA);
> +
> +#define PID_TABLE_SIZE 1024
> +#define POLL_20_HZ_DIV 20 /* poll at 20 Hz */
> +
> +static int load_slim_core_fw(struct c8sectpfei *fei);
> +
> +#define TS_PKT_SIZE 188
> +#define HEADER_SIZE (4)
> +#define PACKET_SIZE (TS_PKT_SIZE+HEADER_SIZE)
> +
> +#define FEI_ALIGNMENT (32)
> +/* hw requires minimum of 8*PACKET_SIZE and padded to 8byte boundary */
> +#define FEI_BUFFER_SIZE (8*PACKET_SIZE*340)
> +
> +#define FIFO_LEN 1024
> +
> +static void c8sectpfe_timer_interrupt(unsigned long ac8sectpfei)
> +{
> +	struct c8sectpfei *fei = (struct c8sectpfei *)ac8sectpfei;
> +	struct channel_info *channel;
> +	int chan_num;
> +
> +	/* iterate through input block channels */
> +	for (chan_num = 0; chan_num < fei->tsin_count; chan_num++) {
> +		channel = fei->channel_data[chan_num];
> +
> +		/* is this descriptor initialised and TP enabled */
> +		if (channel->irec && readl((void __iomem *)
> +						&channel->irec->tp_enable))
> +			tasklet_schedule(&channel->tsklet);
> +	}
> +
> +	fei->timer.expires = jiffies + (HZ / POLL_20_HZ_DIV);

Please use the macros for jiffies conversions. In this case, I guess
you want to use ms_to_jiffies(), right?

> +	add_timer(&fei->timer);
> +}
> +
> +static void channel_swdemux_tsklet(unsigned long data)
> +{
> +	struct channel_info *channel = (struct channel_info *)data;
> +	struct c8sectpfei *fei = channel->fei;
> +	struct tpentry *ptrblk;
> +	unsigned long wp, rp;
> +	int pos, num_packets, n, size;
> +	u8 *buf;
> +
> +	BUG_ON(!channel);
> +	BUG_ON(!channel->irec);

Please avoid using BUG_ON() except when the machine will be on some
unstable state. In this case, I guess you could just do:

	if (unlikely(!channel || !channel->irec)
		return;

> +
> +	ptrblk = &channel->irec->ptr_data[0];
> +
> +	wp = readl((void __iomem *)&ptrblk->dma_bus_wp);
> +	rp = readl((void __iomem *)&ptrblk->dma_bus_rp);

Why do you need those typecasts? We try to avoid typecasts in the Kernel,
doing it only where really needed. Same for other usages. You should
probably declare those DMA buffers as __iomem *, and avoid the casts.

> +
> +	pos = rp - channel->back_buffer_busaddr;
> +
> +	/* has it wrapped */
> +	if (wp < rp)
> +		wp = channel->back_buffer_busaddr + FEI_BUFFER_SIZE;
> +
> +	size = wp - rp;
> +	num_packets = size / PACKET_SIZE;
> +
> +	/* manage cache so data is visible to CPU */
> +	dma_sync_single_for_cpu(fei->dev,
> +				rp,
> +				size,
> +				DMA_FROM_DEVICE);
> +
> +	buf = (u8 *) channel->back_buffer_aligned;
> +
> +	dev_dbg(fei->dev,
> +		"chan=%d channel=%p num_packets = %d, buf = %p, pos = 0x%x\n\t"
> +		"rp=0x%lx, wp=0x%lx\n",
> +		channel->tsin_id, channel, num_packets, buf, pos, rp, wp);
> +
> +	for (n = 0; n < num_packets; n++) {
> +		dvb_dmx_swfilter_packets(
> +			&fei->c8sectpfe[0]->
> +				demux[channel->demux_mapping].dvb_demux,
> +			&buf[pos], 1);
> +
> +		pos += PACKET_SIZE;
> +	}

Hmm... why not call it, instead, without the loop, e. g.:

	dvb_dmx_swfilter_packets(
		&fei->c8sectpfe[0]->
				demux[channel->demux_mapping].dvb_demux,
			&buf[pos], num_packets);


> +
> +	/* advance the read pointer */
> +	if (wp == (channel->back_buffer_busaddr + FEI_BUFFER_SIZE))
> +		writel(channel->back_buffer_busaddr,
> +			(void __iomem *)&ptrblk->dma_bus_rp);
> +	else
> +		writel(wp, (void __iomem *)&ptrblk->dma_bus_rp);
> +}
> +
> +static int c8sectpfe_start_feed(struct dvb_demux_feed *dvbdmxfeed)
> +{
> +	struct dvb_demux *demux = dvbdmxfeed->demux;
> +	struct stdemux *stdemux = (struct stdemux *)demux->priv;
> +	struct c8sectpfei *fei = stdemux->c8sectpfei;
> +	struct channel_info *channel;
> +	struct tpentry *ptrblk;
> +	u32 tmp;
> +	unsigned long *bitmap;
> +
> +	switch (dvbdmxfeed->type) {
> +	case DMX_TYPE_TS:
> +		break;
> +	case DMX_TYPE_SEC:
> +		break;
> +	default:
> +		dev_err(fei->dev, "%s:%d Error bailing\n"
> +			, __func__, __LINE__);
> +		return -EINVAL;
> +	}
> +
> +	if (dvbdmxfeed->type == DMX_TYPE_TS) {
> +		switch (dvbdmxfeed->pes_type) {
> +		case DMX_PES_VIDEO:
> +		case DMX_PES_AUDIO:
> +		case DMX_PES_TELETEXT:
> +		case DMX_PES_PCR:
> +		case DMX_PES_OTHER:
> +			break;
> +		default:
> +			dev_err(fei->dev, "%s:%d Error bailing\n"
> +				, __func__, __LINE__);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	mutex_lock(&fei->lock);
> +
> +	channel = fei->channel_data[stdemux->tsin_index];
> +
> +	bitmap = (unsigned long *) channel->pid_buffer_aligned;
> +
> +	bitmap_set(bitmap, dvbdmxfeed->pid, 1);
> +
> +	/* manage cache so PID bitmap is visible to HW */
> +	dma_sync_single_for_device(fei->dev,
> +					channel->pid_buffer_busaddr,
> +					PID_TABLE_SIZE,
> +					DMA_TO_DEVICE);
> +
> +	channel->active = 1;
> +
> +	if (fei->global_feed_count == 0) {
> +		fei->timer.expires = jiffies + (HZ / POLL_20_HZ_DIV);

Please use ms_to_jiffies().

> +		add_timer(&fei->timer);
> +	}
> +
> +	if (stdemux->running_feed_count == 0) {
> +
> +		dev_dbg(fei->dev, "Starting channel=%p\n", channel);
> +
> +		tasklet_init(&channel->tsklet, channel_swdemux_tsklet,
> +			     (unsigned long) channel);
> +
> +		/* Reset the internal inputblock sram pointers */
> +		writel(channel->fifo,
> +			fei->io + C8SECTPFE_IB_BUFF_STRT(channel->tsin_id));
> +		writel(channel->fifo + FIFO_LEN - 1,
> +			fei->io + C8SECTPFE_IB_BUFF_END(channel->tsin_id));
> +
> +		writel(channel->fifo,
> +			fei->io + C8SECTPFE_IB_READ_PNT(channel->tsin_id));
> +		writel(channel->fifo,
> +			fei->io + C8SECTPFE_IB_WRT_PNT(channel->tsin_id));
> +
> +
> +		/* reset read / write memdma ptrs for this channel */
> +		ptrblk = &channel->irec->ptr_data[0];
> +		writel(channel->back_buffer_busaddr,
> +			(void __iomem *)&ptrblk->dma_busbase);
> +
> +		tmp = channel->back_buffer_busaddr + FEI_BUFFER_SIZE - 1;
> +		writel(tmp, (void __iomem *)&ptrblk->dma_bustop);
> +
> +		writel(channel->back_buffer_busaddr,
> +			(void __iomem *)&ptrblk->dma_bus_wp);
> +
> +		/* Issue a reset and enable InputBlock */
> +		writel(C8SECTPFE_SYS_ENABLE | C8SECTPFE_SYS_RESET
> +			, fei->io + C8SECTPFE_IB_SYS(channel->tsin_id));
> +
> +		/* and enable the tp */
> +		writel(0x1, (void __iomem *)&channel->irec->tp_enable);
> +
> +		dev_dbg(fei->dev, "%s:%d Starting DMA feed on stdemux=%p\n"
> +			, __func__, __LINE__, stdemux);
> +	}
> +
> +	stdemux->running_feed_count++;
> +	fei->global_feed_count++;
> +
> +	mutex_unlock(&fei->lock);
> +
> +	return 0;
> +}
> +
> +static int c8sectpfe_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
> +{
> +
> +	struct dvb_demux *demux = dvbdmxfeed->demux;
> +	struct stdemux *stdemux = (struct stdemux *)demux->priv;
> +	struct c8sectpfei *fei = stdemux->c8sectpfei;
> +	struct channel_info *channel;
> +	struct tpentry *ptrblk;
> +	int idlereq;
> +	u32 tmp;
> +	int ret;
> +	unsigned long *bitmap;
> +
> +	mutex_lock(&fei->lock);
> +
> +	channel = fei->channel_data[stdemux->tsin_index];
> +
> +	bitmap = (unsigned long *) channel->pid_buffer_aligned;
> +	bitmap_clear(bitmap, dvbdmxfeed->pid, 1);
> +
> +	/* manage cache so data is visible to HW */
> +	dma_sync_single_for_device(fei->dev,
> +					channel->pid_buffer_busaddr,
> +					PID_TABLE_SIZE,
> +					DMA_TO_DEVICE);
> +
> +	if (--stdemux->running_feed_count == 0) {
> +
> +		channel = fei->channel_data[stdemux->tsin_index];
> +		ptrblk = &channel->irec->ptr_data[0];
> +
> +		/* TP re-configuration on page 168 */

Page 168 of what?

> +
> +		/* disable IB (prevents more TS data going to memdma) */
> +		writel(0, fei->io + C8SECTPFE_IB_SYS(channel->tsin_id));
> +
> +		/* disable this channels descriptor */
> +		writel(0, (void __iomem *)&channel->irec->tp_enable);
> +
> +		tasklet_disable(&channel->tsklet);
> +
> +		/* now request memdma channel goes idle */
> +		idlereq = (1 << channel->tsin_id) | IDLEREQ;
> +		writel(idlereq, fei->io + DMA_IDLE_REQ);
> +
> +		/* wait for idle irq handler to signal completion */
> +		ret = wait_for_completion_timeout(&channel->idle_completion,
> +						msecs_to_jiffies(100));
> +
> +		if (ret == 0)
> +			dev_warn(fei->dev,
> +				"Timeout waiting for idle irq on tsin%d\n",
> +				channel->tsin_id);
> +
> +		reinit_completion(&channel->idle_completion);
> +
> +		/* reset read / write ptrs for this channel */
> +		writel(channel->back_buffer_busaddr,
> +			(void __iomem *)&ptrblk->dma_busbase);
> +
> +		tmp = channel->back_buffer_busaddr + FEI_BUFFER_SIZE - 1;
> +		writel(tmp, (void __iomem *)&ptrblk->dma_bustop);
> +
> +		writel(channel->back_buffer_busaddr,
> +			(void __iomem *)&ptrblk->dma_bus_wp);
> +
> +		dev_dbg(fei->dev,
> +			"%s:%d stopping DMA feed on stdemux=%p channel=%d\n",
> +			__func__, __LINE__, stdemux, channel->tsin_id);
> +
> +		/* turn off all PIDS in the bitmap*/
> +		memset((void *)channel->pid_buffer_aligned
> +			, 0x00, PID_TABLE_SIZE);
> +
> +		/* manage cache so data is visible to HW */
> +		dma_sync_single_for_device(fei->dev,
> +					channel->pid_buffer_busaddr,
> +					PID_TABLE_SIZE,
> +					DMA_TO_DEVICE);
> +
> +		channel->active = 0;
> +	}
> +
> +	if (--fei->global_feed_count == 0) {
> +		dev_dbg(fei->dev, "%s:%d global_feed_count=%d\n"
> +			, __func__, __LINE__, fei->global_feed_count);
> +
> +		del_timer(&fei->timer);
> +	}
> +
> +	mutex_unlock(&fei->lock);
> +
> +	return 0;
> +}
> +
> +static struct channel_info *find_channel(struct c8sectpfei *fei, int tsin_num)
> +{
> +	int i;
> +
> +	for (i = 0; i < C8SECTPFE_MAXCHANNEL; i++) {
> +		if (!fei->channel_data[i])
> +			continue;
> +
> +		if (fei->channel_data[i]->tsin_id == tsin_num)
> +			return fei->channel_data[i];
> +	}
> +
> +	return NULL;
> +}
> +
> +static void c8sectpfe_getconfig(struct c8sectpfei *fei)
> +{
> +	struct c8sectpfe_hw *hw = &fei->hw_stats;
> +
> +	hw->num_ib = readl(fei->io + SYS_CFG_NUM_IB);
> +	hw->num_mib = readl(fei->io + SYS_CFG_NUM_MIB);
> +	hw->num_swts = readl(fei->io + SYS_CFG_NUM_SWTS);
> +	hw->num_tsout = readl(fei->io + SYS_CFG_NUM_TSOUT);
> +	hw->num_ccsc = readl(fei->io + SYS_CFG_NUM_CCSC);
> +	hw->num_ram = readl(fei->io + SYS_CFG_NUM_RAM);
> +	hw->num_tp = readl(fei->io + SYS_CFG_NUM_TP);
> +
> +	dev_info(fei->dev, "C8SECTPFE hw supports the following:\n");
> +	dev_info(fei->dev, "Input Blocks: %d\n", hw->num_ib);
> +	dev_info(fei->dev, "Merged Input Blocks: %d\n", hw->num_mib);
> +	dev_info(fei->dev, "Software Transport Stream Inputs: %d\n"
> +				, hw->num_swts);
> +	dev_info(fei->dev, "Transport Stream Output: %d\n", hw->num_tsout);
> +	dev_info(fei->dev, "Cable Card Converter: %d\n", hw->num_ccsc);
> +	dev_info(fei->dev, "RAMs supported by C8SECTPFE: %d\n", hw->num_ram);
> +	dev_info(fei->dev, "Tango TPs supported by C8SECTPFE: %d\n"
> +			, hw->num_tp);
> +}
> +
> +static irqreturn_t c8sectpfe_idle_irq_handler(int irq, void *priv)
> +{
> +	struct c8sectpfei *fei = priv;
> +	struct channel_info *chan;
> +	int bit;
> +	unsigned long tmp = readl(fei->io + DMA_IDLE_REQ);
> +
> +	/* page 168 of functional spec: Clear the idle request
> +	   by writing 0 to the C8SECTPFE_DMA_IDLE_REQ register. */
> +
> +	/* signal idle completion */
> +	for_each_set_bit(bit, &tmp, fei->hw_stats.num_ib) {
> +
> +		chan = find_channel(fei, bit);
> +
> +		if (chan)
> +			complete(&chan->idle_completion);
> +	}
> +
> +	writel(0, fei->io + DMA_IDLE_REQ);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +
> +static void free_input_block(struct c8sectpfei *fei, struct channel_info *tsin)
> +{
> +	BUG_ON(!fei);
> +	BUG_ON(!tsin);

Again, BUG_ON() don't make much sense here. Just return if those vars are
NULL.

> +
> +	if (tsin->back_buffer_busaddr)
> +		if (!dma_mapping_error(fei->dev, tsin->back_buffer_busaddr))
> +			dma_unmap_single(fei->dev, tsin->back_buffer_busaddr,
> +				FEI_BUFFER_SIZE, DMA_BIDIRECTIONAL);
> +
> +	kfree(tsin->back_buffer_start);
> +
> +	if (tsin->pid_buffer_busaddr)
> +		if (!dma_mapping_error(fei->dev, tsin->pid_buffer_busaddr))
> +			dma_unmap_single(fei->dev, tsin->pid_buffer_busaddr,
> +				PID_TABLE_SIZE, DMA_BIDIRECTIONAL);
> +
> +	kfree(tsin->pid_buffer_start);
> +}
> +
> +#define MAX_NAME 20
> +
> +static int configure_input_block(struct c8sectpfei *fei,
> +				struct channel_info *tsin)
> +{
> +	int ret;
> +	u32 tmp = 0;
> +	struct tpentry *ptrblk;
> +	char tsin_pin_name[MAX_NAME];
> +
> +	BUG_ON(!fei);
> +	BUG_ON(!tsin);

Same here: BUG_ON() seems too severe.

> +
> +	dev_dbg(fei->dev, "%s:%d Configuring channel=%p tsin=%d\n"
> +		, __func__, __LINE__, tsin, tsin->tsin_id);
> +
> +	init_completion(&tsin->idle_completion);
> +
> +	tsin->back_buffer_start = kzalloc(FEI_BUFFER_SIZE +
> +					FEI_ALIGNMENT, GFP_KERNEL);
> +
> +	if (!tsin->back_buffer_start) {
> +		ret = -ENOMEM;
> +		goto err_unmap;
> +	}
> +
> +	/* Ensure backbuffer is 32byte aligned */
> +	tsin->back_buffer_aligned = tsin->back_buffer_start
> +		+ FEI_ALIGNMENT;
> +
> +	tsin->back_buffer_aligned = (void *)
> +		(((uintptr_t) tsin->back_buffer_aligned) & ~0x1F);
> +
> +	tsin->back_buffer_busaddr = dma_map_single(fei->dev,
> +					(void *)tsin->back_buffer_aligned,
> +					FEI_BUFFER_SIZE,
> +					DMA_BIDIRECTIONAL);
> +
> +	if (dma_mapping_error(fei->dev, tsin->back_buffer_busaddr)) {
> +		dev_err(fei->dev, "failed to map back_buffer\n");
> +		ret = -EFAULT;
> +		goto err_unmap;
> +	}
> +
> +	/*
> +	 * The pid buffer can be configured (in hw) for byte or bit
> +	 * per pid. By powers of deduction we conclude stih407 family
> +	 * is configured (at SoC design stage) for bit per pid.
> +	 */
> +	tsin->pid_buffer_start = kzalloc(2048, GFP_KERNEL);
> +
> +	if (!tsin->pid_buffer_start) {
> +		ret = -ENOMEM;
> +		goto err_unmap;
> +	}
> +
> +	/*
> +	 * PID buffer needs to be aligned to size of the pid table
> +	 * which at bit per pid is 1024 bytes (8192 pids / 8).
> +	 * PIDF_BASE register enforces this alignment when writing
> +	 * the register.
> +	 */
> +
> +	tsin->pid_buffer_aligned = tsin->pid_buffer_start +
> +		PID_TABLE_SIZE;
> +
> +	tsin->pid_buffer_aligned = (void *)
> +		(((uintptr_t) tsin->pid_buffer_aligned) & ~0x3ff);
> +
> +	tsin->pid_buffer_busaddr = dma_map_single(fei->dev,
> +						tsin->pid_buffer_aligned,
> +						PID_TABLE_SIZE,
> +						DMA_BIDIRECTIONAL);
> +
> +	if (dma_mapping_error(fei->dev, tsin->pid_buffer_busaddr)) {
> +		dev_err(fei->dev, "failed to map pid_bitmap\n");
> +		ret = -EFAULT;
> +		goto err_unmap;
> +	}
> +
> +	/* manage cache so pid bitmap is visible to HW */
> +	dma_sync_single_for_device(fei->dev,
> +				tsin->pid_buffer_busaddr,
> +				PID_TABLE_SIZE,
> +				DMA_TO_DEVICE);
> +
> +	snprintf(tsin_pin_name, MAX_NAME, "tsin%d-%s", tsin->tsin_id,
> +		(tsin->serial_not_parallel ? "serial" : "parallel"));
> +
> +	tsin->pstate = pinctrl_lookup_state(fei->pinctrl, tsin_pin_name);
> +	if (IS_ERR(tsin->pstate)) {
> +		dev_err(fei->dev, "%s: pinctrl_lookup_state couldn't find %s state\n"
> +			, __func__, tsin_pin_name);
> +		ret = PTR_ERR(tsin->pstate);
> +		goto err_unmap;
> +	}
> +
> +	ret = pinctrl_select_state(fei->pinctrl, tsin->pstate);
> +
> +	if (ret) {
> +		dev_err(fei->dev, "%s: pinctrl_select_state failed\n"
> +			, __func__);
> +		goto err_unmap;
> +	}
> +
> +	/* Enable this input block */
> +	tmp = readl(fei->io + SYS_INPUT_CLKEN);
> +	tmp |= BIT(tsin->tsin_id);
> +	writel(tmp, fei->io + SYS_INPUT_CLKEN);
> +
> +	if (tsin->serial_not_parallel)
> +		tmp |= C8SECTPFE_SERIAL_NOT_PARALLEL;
> +
> +	if (tsin->invert_ts_clk)
> +		tmp |= C8SECTPFE_INVERT_TSCLK;
> +
> +	if (tsin->async_not_sync)
> +		tmp |= C8SECTPFE_ASYNC_NOT_SYNC;
> +
> +	tmp |= C8SECTPFE_ALIGN_BYTE_SOP | C8SECTPFE_BYTE_ENDIANNESS_MSB;
> +
> +	writel(tmp, fei->io + C8SECTPFE_IB_IP_FMT_CFG(tsin->tsin_id));
> +
> +	writel(C8SECTPFE_SYNC(0x9) |
> +		C8SECTPFE_DROP(0x9) |
> +		C8SECTPFE_TOKEN(0x47),
> +		fei->io + C8SECTPFE_IB_SYNCLCKDRP_CFG(tsin->tsin_id));
> +
> +	writel(TS_PKT_SIZE, fei->io + C8SECTPFE_IB_PKT_LEN(tsin->tsin_id));
> +
> +	/* Place the FIFO's at the end of the irec descriptors */
> +
> +	tsin->fifo = (tsin->tsin_id * FIFO_LEN);
> +
> +	writel(tsin->fifo, fei->io + C8SECTPFE_IB_BUFF_STRT(tsin->tsin_id));
> +	writel(tsin->fifo + FIFO_LEN - 1,
> +		fei->io + C8SECTPFE_IB_BUFF_END(tsin->tsin_id));
> +
> +	writel(tsin->fifo, fei->io + C8SECTPFE_IB_READ_PNT(tsin->tsin_id));
> +	writel(tsin->fifo, fei->io + C8SECTPFE_IB_WRT_PNT(tsin->tsin_id));
> +
> +	writel(tsin->pid_buffer_busaddr,
> +		fei->io + PIDF_BASE(tsin->tsin_id));
> +
> +	dev_dbg(fei->dev, "chan=%d PIDF_BASE=0x%x pid_bus_addr=0x%x\n",
> +		tsin->tsin_id, readl(fei->io + PIDF_BASE(tsin->tsin_id)),
> +		tsin->pid_buffer_busaddr);
> +
> +	/* Configure and enable HW PID filtering */
> +
> +	/*
> +	 * The PID value is created by assembling the first 8 bytes of
> +	 * the TS packet into a 64-bit word in big-endian format. A
> +	 * slice of that 64-bit word is taken from
> +	 * (PID_OFFSET+PID_NUM_BITS-1) to PID_OFFSET.
> +	 */
> +	tmp = (C8SECTPFE_PID_ENABLE | C8SECTPFE_PID_NUMBITS(13)
> +		| C8SECTPFE_PID_OFFSET(40));
> +
> +	writel(tmp, fei->io + C8SECTPFE_IB_PID_SET(tsin->tsin_id));
> +
> +	dev_dbg(fei->dev, "chan=%d setting wp: %d, rp: %d, buf: %d-%d\n",
> +		tsin->tsin_id,
> +		readl(fei->io + C8SECTPFE_IB_WRT_PNT(tsin->tsin_id)),
> +		readl(fei->io + C8SECTPFE_IB_READ_PNT(tsin->tsin_id)),
> +		readl(fei->io + C8SECTPFE_IB_BUFF_STRT(tsin->tsin_id)),
> +		readl(fei->io + C8SECTPFE_IB_BUFF_END(tsin->tsin_id)));
> +
> +	/*
> +	 * Base address of pointer record block relative to
> +	 * base address of DMEM
> +	 */
> +	fei->irec = fei->io + DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET +
> +			readl(fei->io + DMA_PTRREC_BASE);
> +
> +	tsin->irec = fei->irec += tsin->tsin_id;
> +
> +	ptrblk = &tsin->irec->ptr_data[0];
> +
> +	writel(tsin->fifo,
> +		(void __iomem *)&tsin->irec->dma_membase);
> +
> +	writel(tsin->fifo + FIFO_LEN - 1,
> +		(void __iomem *)&tsin->irec->dma_memtop);
> +
> +	writel((188 + 7)&~7,
> +		(void __iomem *)&tsin->irec->dma_ts_pktsize);
> +
> +	writel(0x1, (void __iomem *)&tsin->irec->tp_enable);
> +
> +	/* read/write pointers with physical bus address */
> +	writel(tsin->back_buffer_busaddr,
> +		(void __iomem *)&ptrblk->dma_busbase);
> +
> +	tmp = tsin->back_buffer_busaddr + FEI_BUFFER_SIZE - 1;
> +	writel(tmp, (void __iomem *)&ptrblk->dma_bustop);
> +
> +	writel(tsin->back_buffer_busaddr,
> +		(void __iomem *)&ptrblk->dma_bus_wp);
> +
> +	writel(tsin->back_buffer_busaddr,
> +		(void __iomem *)&ptrblk->dma_bus_rp);
> +
> +	/* initialize tasklet */
> +	tasklet_init(&tsin->tsklet, channel_swdemux_tsklet,
> +		(unsigned long) tsin);
> +
> +	return 0;
> +
> +err_unmap:
> +	free_input_block(fei, tsin);
> +	return ret;
> +}
> +
> +static irqreturn_t c8sectpfe_error_irq_handler(int irq, void *priv)
> +{
> +	struct c8sectpfei *fei = priv;
> +
> +	dev_err(fei->dev, "%s: error handling not yet implemented\n"
> +		, __func__);
> +
> +	/*
> +	 * TODO FIXME we should detect some error conditions here
> +	 * and ideally so something about them!
> +	 */
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int c8sectpfe_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct device_node *child, *np = dev->of_node;
> +	struct c8sectpfei *fei;
> +	struct resource *res;
> +	int ret, n;
> +	struct channel_info *tsin;
> +
> +	/* Allocate the c8sectpfei structure */
> +	fei = devm_kzalloc(dev, sizeof(struct c8sectpfei), GFP_KERNEL);
> +	if (!fei)
> +		return -ENOMEM;
> +
> +	fei->dev = dev;
> +
> +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "c8sectpfe");
> +	fei->io = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(fei->io))
> +		return PTR_ERR(fei->io);
> +
> +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> +					"c8sectpfe-ram");
> +	fei->sram = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(fei->sram))
> +		return PTR_ERR(fei->sram);
> +
> +	fei->sram_size = res->end - res->start;
> +
> +	fei->idle_irq = platform_get_irq_byname(pdev, "c8sectpfe-idle-irq");
> +	if (fei->idle_irq < 0) {
> +		dev_err(dev, "Can't get c8sectpfe-idle-irq\n");
> +		return fei->idle_irq;
> +	}
> +
> +	fei->error_irq = platform_get_irq_byname(pdev, "c8sectpfe-error-irq");
> +	if (fei->error_irq < 0) {
> +		dev_err(dev, "Can't get c8sectpfe-error-irq\n");
> +		return fei->error_irq;
> +	}
> +
> +	platform_set_drvdata(pdev, fei);
> +
> +	fei->c8sectpfeclk = devm_clk_get(dev, "c8sectpfe");
> +	if (IS_ERR(fei->c8sectpfeclk)) {
> +		dev_err(dev, "c8sectpfe clk not found\n");
> +		return PTR_ERR(fei->c8sectpfeclk);
> +	}
> +
> +	ret = clk_prepare_enable(fei->c8sectpfeclk);
> +	if (ret) {
> +		dev_err(dev, "Failed to enable c8sectpfe clock\n");
> +		return ret;
> +	}
> +
> +	/* to save power disable all IP's (on by default) */
> +	writel(0, fei->io + SYS_INPUT_CLKEN);
> +
> +	/* Enable memdma clock */
> +	writel(MEMDMAENABLE, fei->io + SYS_OTHER_CLKEN);
> +
> +	/* clear internal sram */
> +	memset_io(fei->sram, 0x0, fei->sram_size);
> +
> +	c8sectpfe_getconfig(fei);
> +
> +	ret = load_slim_core_fw(fei);
> +	if (ret) {
> +		dev_err(dev, "Couldn't load slim core firmware\n");
> +		goto err_clk_disable;
> +	}
> +
> +	ret = devm_request_irq(dev, fei->idle_irq, c8sectpfe_idle_irq_handler,
> +			0, "c8sectpfe-idle-irq", fei);
> +	if (ret) {
> +		dev_err(dev, "Can't register c8sectpfe-idle-irq IRQ.\n");
> +		goto err_clk_disable;
> +	}
> +
> +	ret = devm_request_irq(dev, fei->error_irq,
> +				c8sectpfe_error_irq_handler, 0,
> +				"c8sectpfe-error-irq", fei);
> +	if (ret) {
> +		dev_err(dev, "Can't register c8sectpfe-error-irq IRQ.\n");
> +		goto err_clk_disable;
> +	}
> +
> +	fei->tsin_count = of_get_child_count(np);
> +
> +	if (fei->tsin_count > C8SECTPFE_MAX_TSIN_CHAN ||
> +		fei->tsin_count > fei->hw_stats.num_ib) {
> +
> +		dev_err(dev, "More tsin declared than exist on SoC!\n");
> +		ret = -EINVAL;
> +		goto err_clk_disable;
> +	}
> +
> +	fei->pinctrl = devm_pinctrl_get(dev);
> +
> +	if (IS_ERR(fei->pinctrl)) {
> +		dev_err(dev, "Error getting tsin pins\n");
> +		ret = PTR_ERR(fei->pinctrl);
> +		goto err_clk_disable;
> +	}
> +
> +	n = 0;
> +	for_each_child_of_node(np, child) {
> +		struct device_node *i2c_bus;
> +
> +		fei->channel_data[n] = devm_kzalloc(dev,
> +						sizeof(struct channel_info),
> +						GFP_KERNEL);
> +
> +		if (!fei->channel_data[n]) {
> +			ret = -ENOMEM;
> +			goto err_clk_disable;
> +		}
> +
> +		tsin = fei->channel_data[n];
> +
> +		tsin->fei = fei;
> +
> +		ret = of_property_read_u32(child, "tsin-num", &tsin->tsin_id);
> +		if (ret) {
> +			dev_err(&pdev->dev, "No tsin_num found\n");
> +			goto err_clk_disable;
> +		}
> +
> +		/* sanity check value */
> +		if (tsin->tsin_id > fei->hw_stats.num_ib) {
> +			dev_err(&pdev->dev,
> +				"tsin-num %d specified greater than number\n\t"
> +				"of input block hw in SoC! (%d)",
> +				tsin->tsin_id, fei->hw_stats.num_ib);
> +			ret = -EINVAL;
> +			goto err_clk_disable;
> +		}
> +
> +		tsin->invert_ts_clk = of_property_read_bool(child,
> +							"invert-ts-clk");
> +
> +		tsin->serial_not_parallel = of_property_read_bool(child,
> +							"serial-not-parallel");
> +
> +		tsin->async_not_sync = of_property_read_bool(child,
> +							"async-not-sync");
> +
> +		ret = of_property_read_u32(child, "dvb-card",
> +					&tsin->dvb_card);
> +		if (ret) {
> +			dev_err(&pdev->dev, "No dvb-card found\n");
> +			goto err_clk_disable;
> +		}
> +
> +		i2c_bus = of_parse_phandle(child, "i2c-bus", 0);
> +		if (!i2c_bus) {
> +			dev_err(&pdev->dev, "No i2c-bus found\n");
> +			goto err_clk_disable;
> +		}
> +		tsin->i2c_adapter =
> +			of_find_i2c_adapter_by_node(i2c_bus);
> +		if (!tsin->i2c_adapter) {
> +			dev_err(&pdev->dev, "No i2c adapter found\n");
> +			of_node_put(i2c_bus);
> +			goto err_clk_disable;
> +		}
> +		of_node_put(i2c_bus);
> +
> +		tsin->rst_gpio = of_get_named_gpio(child, "rst-gpio", 0);
> +
> +		ret = gpio_is_valid(tsin->rst_gpio);
> +		if (!ret) {
> +			dev_err(dev,
> +				"reset gpio for tsin%d not valid (gpio=%d)\n",
> +				tsin->tsin_id, tsin->rst_gpio);
> +			goto err_clk_disable;
> +		}
> +
> +		ret = devm_gpio_request_one(dev, tsin->rst_gpio,
> +					GPIOF_OUT_INIT_LOW, "NIM reset");
> +		if (ret && ret != -EBUSY) {
> +			dev_err(dev, "Can't request tsin%d reset gpio\n"
> +				, fei->channel_data[n]->tsin_id);
> +			goto err_clk_disable;
> +		}
> +
> +		if (!ret) {
> +			/* toggle reset lines */
> +			gpio_direction_output(tsin->rst_gpio, 0);
> +			msleep(1);
> +			gpio_direction_output(tsin->rst_gpio, 1);
> +			msleep(1);

WARNING: msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt

msleep(1) doesn't work nice, as it may sleep up to 20 ms, depending on
how HZ is configured. Is that what you want?

> +		}
> +
> +		tsin->demux_mapping = n;
> +
> +		dev_dbg(fei->dev,
> +			"channel=%p n=%d tsin_num=%d, invert-ts-clk=%d\n\t"
> +			"serial-not-parallel=%d pkt-clk-valid=%d dvb-card=%d\n",
> +			fei->channel_data[n], n,
> +			tsin->tsin_id, tsin->invert_ts_clk,
> +			tsin->serial_not_parallel, tsin->async_not_sync,
> +			tsin->dvb_card);
> +
> +		ret = configure_input_block(fei, fei->channel_data[n]);
> +
> +		if (ret) {
> +			dev_err(fei->dev,
> +				"configure_input_block tsin=%d failed\n",
> +				fei->channel_data[n]->tsin_id);
> +			goto err_unmap;
> +		}
> +
> +		n++;
> +	}
> +
> +	/* Setup timer interrupt */
> +	init_timer(&fei->timer);
> +	fei->timer.function = c8sectpfe_timer_interrupt;
> +	fei->timer.data = (unsigned long)fei;
> +
> +	mutex_init(&fei->lock);
> +
> +	/* Get the configuration information about the tuners */
> +	ret = c8sectpfe_tuner_register_frontend(&fei->c8sectpfe[0],
> +					(void *)fei,
> +					c8sectpfe_start_feed,
> +					c8sectpfe_stop_feed);
> +	if (ret)
> +		goto err_unmap;
> +
> +	/*
> +	 * STBus target port can access IMEM and DMEM ports
> +	 * without waiting for CPU
> +	 */
> +	writel(0x1, fei->io + DMA_PER_STBUS_SYNC);
> +
> +	dev_info(dev, "Boot the memdma SLIM core\n");
> +	writel(0x1,  fei->io + DMA_CPU_RUN);
> +
> +	c8sectpfe_debugfs_init(fei);
> +
> +	return 0;
> +
> +err_unmap:
> +	for (n = 0; n < fei->tsin_count; n++) {
> +		tsin = fei->channel_data[n];
> +
> +		if (tsin)
> +			free_input_block(fei, tsin);
> +	}
> +
> +err_clk_disable:
> +	/* TODO uncomment when upstream has taken a reference on this clk */
> +	/*clk_disable_unprepare(fei->c8sectpfeclk);*/

Hmm... what's the above? Why is it commented?

> +	return ret;
> +}
> +
> +static int c8sectpfe_remove(struct platform_device *pdev)
> +{
> +	struct c8sectpfei *fei = platform_get_drvdata(pdev);
> +	struct channel_info *channel;
> +	unsigned int n;
> +
> +	c8sectpfe_tuner_unregister_frontend(fei->c8sectpfe[0], fei);
> +
> +	/*
> +	 * Now loop through and un-configure each of the InputBlock resources
> +	 */
> +	for (n = 0; n < fei->tsin_count; n++) {
> +		channel = fei->channel_data[n];
> +		if (channel)
> +			free_input_block(fei, channel);
> +	}
> +
> +	c8sectpfe_debugfs_exit(fei);
> +
> +	dev_info(fei->dev, "Stopping memdma SLIM core\n");
> +	if (readl(fei->io + DMA_CPU_RUN))
> +		writel(0x0,  fei->io + DMA_CPU_RUN);
> +
> +	/* unclock all internal IP's */
> +	if (readl(fei->io + SYS_INPUT_CLKEN))
> +		writel(0, fei->io + SYS_INPUT_CLKEN);
> +	if (readl(fei->io + SYS_OTHER_CLKEN))
> +		writel(0, fei->io + SYS_OTHER_CLKEN);
> +
> +	/* TODO uncomment when upstream has taken a reference on this clk */
> +	/*
> +	if (fei->c8sectpfeclk)
> +		clk_disable_unprepare(fei->c8sectpfeclk);
> +	*/

Hmm... what's the above? Why is it commented?

> +
> +	return 0;
> +}
> +
> +static int load_slim_core_fw(struct c8sectpfei *fei)
> +{
> +	const struct firmware *fw = NULL;
> +	unsigned char *pImem = NULL;
> +	unsigned char *pDmem = NULL;
> +	Elf32_Ehdr *ehdr;
> +	Elf32_Phdr *phdr;
> +	int err = 0;
> +	int i;
> +
> +	dev_info(fei->dev, "Loading firmware: %s\n", FIRMWARE_MEMDMA);
> +
> +	err = request_firmware(&fw, FIRMWARE_MEMDMA, fei->dev);
> +	if (err) {
> +		dev_err(fei->dev, "Failed to load %s, %d.\n",
> +			FIRMWARE_MEMDMA, err);
> +		return -EINVAL;
> +	}
> +
> +	/* Check ELF magic */
> +	ehdr = (Elf32_Ehdr *)fw->data;
> +	if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
> +	    ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
> +	    ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
> +	    ehdr->e_ident[EI_MAG3] != ELFMAG3) {
> +		dev_err(fei->dev, "Invalid ELF magic\n");
> +		err = -ENODEV;
> +		goto done;
> +	} else {
> +		dev_dbg(fei->dev, "Valid ELF header found\n");
> +	}
> +
> +	/* Check program headers are within firmware size */
> +	if (ehdr->e_phoff + (ehdr->e_phnum * sizeof(Elf32_Phdr)) > fw->size) {
> +		dev_err(fei->dev, "Program headers outside of firmware file\n");
> +		err = -ENODEV;
> +		goto done;
> +	}
> +
> +	pImem = (unsigned char *) fei->io + DMA_MEMDMA_OFFSET + DMA_IMEM_OFFSET;
> +	pDmem = (unsigned char *) fei->io + DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET;
> +
> +	phdr = (Elf32_Phdr *)(fw->data + ehdr->e_phoff);
> +
> +	/* go through the available ELF segments */
> +	for (i = 0; i < ehdr->e_phnum && !err; i++, phdr++) {
> +		unsigned char *dest;
> +		int imem = 0;
> +
> +		/* Only consider LOAD segments */
> +		if (phdr->p_type != PT_LOAD)
> +			continue;
> +
> +		/*
> +		 * Check segment is contained within the fw->data buffer
> +		 */
> +		if (phdr->p_offset + phdr->p_filesz > fw->size) {
> +			dev_err(fei->dev,
> +				"Segment %d is outside of firmware file\n", i);
> +			err = -EINVAL;
> +			break;
> +		}
> +
> +		/*
> +		 * MEMDMA IMEM has executable flag set, otherwise load
> +		 * this segment to DMEM.
> +		 */
> +
> +		if (phdr->p_flags & PF_X) {
> +			dest = pImem;
> +			imem = 1;
> +		} else {
> +			dest = pDmem;
> +		}
> +
> +		/*
> +		 * The Slim ELF file uses 32-bit word addressing for
> +		 * load offsets.
> +		 */
> +
> +		dest += (phdr->p_paddr & 0xFFFFF) * sizeof(unsigned int);
> +
> +		/*
> +		 * For DMEM segments copy the segment data from the ELF
> +		 * file and pad segment with zeroes
> +		 *
> +		 * For IMEM segments, the segment contains 24-bit
> +		 * instructions which must be padded to 32-bit
> +		 * instructions before being written. The written
> +		 * segment is padded with NOP instructions.
> +		 */
> +
> +		if (!imem) {
> +			dev_dbg(fei->dev,
> +				"Loading DMEM segment %d 0x%08x\n\t"
> +				"(0x%x bytes) -> 0x%08x (0x%x bytes)\n",
> +				i, phdr->p_paddr, phdr->p_filesz,
> +				(unsigned int)dest, phdr->p_memsz);
> +
> +			memcpy((void *)dest, (void *)fw->data + phdr->p_offset,
> +				phdr->p_filesz);
> +
> +			memset((void *)dest + phdr->p_filesz, 0,
> +				phdr->p_memsz - phdr->p_filesz);
> +		} else {
> +			const unsigned char *imem_src = fw->data
> +				+ phdr->p_offset;
> +			unsigned char *imem_dest = dest;
> +			int j;
> +
> +			dev_dbg(fei->dev,
> +				"Loading IMEM segment %d 0x%08x\n\t"
> +				" (0x%x bytes) -> 0x%08x (0x%x bytes)\n", i,
> +				phdr->p_paddr, phdr->p_filesz,
> +				(unsigned int)dest,
> +				phdr->p_memsz + phdr->p_memsz / 3);
> +
> +			for (j = 0; j < phdr->p_filesz; j++) {
> +				*imem_dest = *imem_src;
> +
> +				/* Every 3 bytes, add an additional
> +				 * padding zero in destination */
> +				if (j % 3 == 2) {
> +					imem_dest++;
> +					*imem_dest = 0x00;
> +				}
> +				imem_dest++;
> +				imem_src++;
> +			}
> +		}
> +	}
> +
> +done:
> +	release_firmware(fw);
> +	return err;
> +}
> +
> +static const struct of_device_id c8sectpfe_match[] = {
> +	{ .compatible = "st,stih407-c8sectpfe" },
> +	{ /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, c8sectpfe_match);
> +
> +static struct platform_driver c8sectpfe_driver = {
> +	.driver = {
> +		.name = "c8sectpfe",
> +		.of_match_table = of_match_ptr(c8sectpfe_match),
> +	},
> +	.probe	= c8sectpfe_probe,
> +	.remove	= c8sectpfe_remove,
> +};
> +
> +module_platform_driver(c8sectpfe_driver);
> +
> +MODULE_AUTHOR("Peter Bennett <peter.bennett@st.com>");
> +MODULE_AUTHOR("Peter Griffin <peter.griffin@linaro.org>");
> +MODULE_DESCRIPTION("C8SECTPFE STi DVB Driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/media/tsin/c8sectpfe/c8sectpfe-core.h b/drivers/media/tsin/c8sectpfe/c8sectpfe-core.h
> new file mode 100644
> index 0000000..3466303
> --- /dev/null
> +++ b/drivers/media/tsin/c8sectpfe/c8sectpfe-core.h
> @@ -0,0 +1,288 @@
> +/*
> + * c8sectpfe-core.h - C8SECTPFE STi DVB driver
> + *
> + * Copyright (c) STMicroelectronics 2015
> + *
> + *   Author:Peter Bennett <peter.bennett@st.com>
> + *	    Peter Griffin <peter.griffin@linaro.org>
> + *
> + *	This program is free software; you can redistribute it and/or
> + *	modify it under the terms of the GNU General Public License as
> + *	published by the Free Software Foundation; either version 2 of
> + *	the License, or (at your option) any later version.
> + */
> +#ifndef _C8SECTPFE_CORE_H_
> +#define _C8SECTPFE_CORE_H_
> +
> +#define C8SECTPFEI_MAXCHANNEL 16
> +#define C8SECTPFEI_MAXADAPTER 3
> +
> +#define C8SECTPFE_MAX_TSIN_CHAN 8
> +
> +struct channel_info {
> +
> +	int tsin_id;
> +	bool invert_ts_clk;
> +	bool serial_not_parallel;
> +	bool async_not_sync;
> +	int i2c;
> +	int dvb_card;
> +
> +	int rst_gpio;
> +
> +	struct i2c_adapter  *i2c_adapter;
> +	struct i2c_adapter  *tuner_i2c;
> +	struct i2c_adapter  *lnb_i2c;
> +	struct i2c_client   *i2c_client;
> +	struct dvb_frontend *frontend;
> +
> +	struct pinctrl_state *pstate;
> +
> +	int demux_mapping;
> +	int active;
> +
> +	void *back_buffer_start;
> +	void *back_buffer_aligned;
> +	dma_addr_t back_buffer_busaddr;
> +
> +	void *pid_buffer_start;
> +	void *pid_buffer_aligned;
> +	dma_addr_t pid_buffer_busaddr;
> +
> +	unsigned long  fifo;
> +
> +	struct completion idle_completion;
> +	struct tasklet_struct tsklet;
> +
> +	struct c8sectpfei *fei;
> +	struct c8sectpfe_input_record *irec;
> +
> +};
> +
> +struct c8sectpfe_hw {
> +	int num_ib;
> +	int num_mib;
> +	int num_swts;
> +	int num_tsout;
> +	int num_ccsc;
> +	int num_ram;
> +	int num_tp;
> +};
> +
> +struct c8sectpfei {
> +
> +	struct device *dev;
> +	struct pinctrl *pinctrl;
> +
> +	struct dentry *root;
> +	struct debugfs_regset32	*regset;
> +
> +	int tsin_count;
> +
> +	struct c8sectpfe_hw hw_stats;
> +
> +	struct c8sectpfe *c8sectpfe[C8SECTPFEI_MAXADAPTER];
> +
> +	int mapping[C8SECTPFEI_MAXCHANNEL];
> +
> +	struct mutex lock;
> +
> +	struct timer_list timer;	/* timer interrupts for outputs */
> +
> +	void __iomem *io;
> +	void __iomem *sram;
> +
> +	unsigned long sram_size;
> +
> +	struct channel_info *channel_data[C8SECTPFE_MAX_TSIN_CHAN];
> +
> +	struct clk *c8sectpfeclk;
> +	int nima_rst_gpio;
> +	int nimb_rst_gpio;
> +
> +	int idle_irq;
> +	int error_irq;
> +
> +	int global_feed_count;
> +
> +	struct c8sectpfe_input_record *irec;
> +};
> +
> +/* C8SECTPFE SYS Regs list */
> +
> +#define SYS_INPUT_ERR_STATUS	0x0
> +#define SYS_OTHER_ERR_STATUS	0x8
> +#define SYS_INPUT_ERR_MASK	0x10
> +#define SYS_OTHER_ERR_MASK	0x18
> +#define SYS_DMA_ROUTE		0x20
> +#define SYS_INPUT_CLKEN		0x30
> +#define IBENABLE_MASK			0x7F
> +
> +#define SYS_OTHER_CLKEN		0x38
> +#define TSDMAENABLE			BIT(1)
> +#define MEMDMAENABLE			BIT(0)
> +
> +#define SYS_CFG_NUM_IB		0x200
> +#define SYS_CFG_NUM_MIB		0x204
> +#define SYS_CFG_NUM_SWTS	0x208
> +#define SYS_CFG_NUM_TSOUT	0x20C
> +#define SYS_CFG_NUM_CCSC	0x210
> +#define SYS_CFG_NUM_RAM		0x214
> +#define SYS_CFG_NUM_TP		0x218
> +
> +/* Input Block Regs */
> +
> +#define C8SECTPFE_INPUTBLK_OFFSET	0x1000
> +#define C8SECTPFE_CHANNEL_OFFSET(x)	((x*0x40) + C8SECTPFE_INPUTBLK_OFFSET)
> +
> +#define C8SECTPFE_IB_IP_FMT_CFG(x)      (C8SECTPFE_CHANNEL_OFFSET(x) + 0x00)
> +#define C8SECTPFE_IGNORE_ERR_AT_SOP     BIT(7)
> +#define C8SECTPFE_IGNORE_ERR_IN_PKT     BIT(6)
> +#define C8SECTPFE_IGNORE_ERR_IN_BYTE    BIT(5)
> +#define C8SECTPFE_INVERT_TSCLK          BIT(4)
> +#define C8SECTPFE_ALIGN_BYTE_SOP        BIT(3)
> +#define C8SECTPFE_ASYNC_NOT_SYNC        BIT(2)
> +#define C8SECTPFE_BYTE_ENDIANNESS_MSB    BIT(1)
> +#define C8SECTPFE_SERIAL_NOT_PARALLEL   BIT(0)
> +
> +#define C8SECTPFE_IB_SYNCLCKDRP_CFG(x)   (C8SECTPFE_CHANNEL_OFFSET(x) + 0x04)
> +#define C8SECTPFE_SYNC(x)                (x & 0xf)
> +#define C8SECTPFE_DROP(x)                ((x<<4) & 0xf)
> +#define C8SECTPFE_TOKEN(x)               ((x<<8) & 0xff00)
> +#define C8SECTPFE_SLDENDIANNESS          BIT(16)
> +
> +#define C8SECTPFE_IB_TAGBYTES_CFG(x)     (C8SECTPFE_CHANNEL_OFFSET(x) + 0x08)
> +#define C8SECTPFE_TAG_HEADER(x)          (x << 16)
> +#define C8SECTPFE_TAG_COUNTER(x)         ((x<<1) & 0x7fff)
> +#define C8SECTPFE_TAG_ENABLE             BIT(0)
> +
> +#define C8SECTPFE_IB_PID_SET(x)          (C8SECTPFE_CHANNEL_OFFSET(x) + 0x0C)
> +#define C8SECTPFE_PID_OFFSET(x)          (x & 0x3f)
> +#define C8SECTPFE_PID_NUMBITS(x)         ((x << 6) & 0xfff)
> +#define C8SECTPFE_PID_ENABLE             BIT(31)
> +
> +#define C8SECTPFE_IB_PKT_LEN(x)          (C8SECTPFE_CHANNEL_OFFSET(x) + 0x10)
> +
> +#define C8SECTPFE_IB_BUFF_STRT(x)        (C8SECTPFE_CHANNEL_OFFSET(x) + 0x14)
> +#define C8SECTPFE_IB_BUFF_END(x)         (C8SECTPFE_CHANNEL_OFFSET(x) + 0x18)
> +#define C8SECTPFE_IB_READ_PNT(x)         (C8SECTPFE_CHANNEL_OFFSET(x) + 0x1C)
> +#define C8SECTPFE_IB_WRT_PNT(x)          (C8SECTPFE_CHANNEL_OFFSET(x) + 0x20)
> +
> +#define C8SECTPFE_IB_PRI_THRLD(x)        (C8SECTPFE_CHANNEL_OFFSET(x) + 0x24)
> +#define C8SECTPFE_PRI_VALUE(x)           (x & 0x7fffff)
> +#define C8SECTPFE_PRI_LOWPRI(x)          ((x & 0xf) << 24)
> +#define C8SECTPFE_PRI_HIGHPRI(x)         ((x & 0xf) << 28)
> +
> +#define C8SECTPFE_IB_STAT(x)             (C8SECTPFE_CHANNEL_OFFSET(x) + 0x28)
> +#define C8SECTPFE_STAT_FIFO_OVERFLOW(x)  (x & 0x1)
> +#define C8SECTPFE_STAT_BUFFER_OVERFLOW(x) (x & 0x2)
> +#define C8SECTPFE_STAT_OUTOFORDERRP(x)   (x & 0x4)
> +#define C8SECTPFE_STAT_PID_OVERFLOW(x)   (x & 0x8)
> +#define C8SECTPFE_STAT_PKT_OVERFLOW(x)   (x & 0x10)
> +#define C8SECTPFE_STAT_ERROR_PACKETS(x)  ((x >> 8) & 0xf)
> +#define C8SECTPFE_STAT_SHORT_PACKETS(x)  ((x >> 12) & 0xf)
> +
> +#define C8SECTPFE_IB_MASK(x)             (C8SECTPFE_CHANNEL_OFFSET(x) + 0x2C)
> +#define C8SECTPFE_MASK_FIFO_OVERFLOW     BIT(0)
> +#define C8SECTPFE_MASK_BUFFER_OVERFLOW   BIT(1)
> +#define C8SECTPFE_MASK_OUTOFORDERRP(x)   BIT(2)
> +#define C8SECTPFE_MASK_PID_OVERFLOW(x)   BIT(3)
> +#define C8SECTPFE_MASK_PKT_OVERFLOW(x)   BIT(4)
> +#define C8SECTPFE_MASK_ERROR_PACKETS(x)  ((x & 0xf) << 8)
> +#define C8SECTPFE_MASK_SHORT_PACKETS(x)  ((x & 0xf) >> 12)
> +
> +#define C8SECTPFE_IB_SYS(x)              (C8SECTPFE_CHANNEL_OFFSET(x) + 0x30)
> +#define C8SECTPFE_SYS_RESET              BIT(1)
> +#define C8SECTPFE_SYS_ENABLE             BIT(0)
> +
> +/*
> + * Ponter record data structure required for each input block
> + * see Table 82 on page 167
> + */
> +
> +struct tpentry {
> +	/* The following entries are bus addresses for memdma */
> +	unsigned long dma_busbase;
> +	unsigned long dma_bustop;
> +	unsigned long dma_bus_wp;
> +	unsigned long dma_bus_rp;
> +};
> +
> +struct c8sectpfe_input_record {
> +	unsigned long dma_membase; /* Internal sram base address */
> +	unsigned long dma_memtop;  /* Internal sram top address */
> +
> +	/*
> +	 * TS packet size, including tag bytes added by input block,
> +	 * rounded up to the next multiple of 8 bytes. The packet size,
> +	 * including any tagging bytes and rounded up to the nearest
> +	 * multiple of 8 bytes must be less than 255 bytes.
> +	 */
> +	unsigned long dma_ts_pktsize;
> +	unsigned long tp_enable;
> +	struct tpentry ptr_data[1];
> +};
> +
> +#define DMA_MEMDMA_OFFSET	0x4000
> +#define DMA_IMEM_OFFSET		0x0
> +#define DMA_DMEM_OFFSET		0x4000
> +#define DMA_CPU			0x8000
> +#define DMA_PER_OFFSET		0xb000
> +
> +/* XP70 Slim core regs */
> +#define DMA_CPU_ID	(DMA_MEMDMA_OFFSET + DMA_CPU + 0x0)
> +#define DMA_CPU_VCR	(DMA_MEMDMA_OFFSET + DMA_CPU + 0x4)
> +#define DMA_CPU_RUN	(DMA_MEMDMA_OFFSET + DMA_CPU + 0x8)
> +#define DMA_CPU_CLOCKGATE	(DMA_MEMDMA_OFFSET + DMA_CPU + 0xc)
> +#define DMA_CPU_PC	(DMA_MEMDMA_OFFSET + DMA_CPU + 0x20)
> +
> +/* Enable Interrupt for a IB */
> +#define DMA_PER_TPn_DREQ_MASK	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xd00)
> +/* Ack interrupt by setting corresponding bit */
> +#define DMA_PER_TPn_DACK_SET	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xd80)
> +#define DMA_PER_TPn_DREQ	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xe00)
> +#define DMA_PER_TPn_DACK	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xe80)
> +#define DMA_PER_DREQ_MODE	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xf80)
> +#define DMA_PER_STBUS_SYNC	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xf88)
> +#define DMA_PER_STBUS_ACCESS	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xf8c)
> +#define DMA_PER_STBUS_ADDRESS	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xf90)
> +#define DMA_PER_IDLE_INT	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfa8)
> +#define DMA_PER_PRIORITY	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfac)
> +#define DMA_PER_MAX_OPCODE	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfb0)
> +#define DMA_PER_MAX_CHUNK	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfb4)
> +#define DMA_PER_PAGE_SIZE	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfbc)
> +#define DMA_PER_MBOX_STATUS	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfc0)
> +#define DMA_PER_MBOX_SET	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfc8)
> +#define DMA_PER_MBOX_CLEAR	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfd0)
> +#define DMA_PER_MBOX_MASK	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfd8)
> +#define DMA_PER_INJECT_PKT_SRC	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfe0)
> +#define DMA_PER_INJECT_PKT_DEST	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfe4)
> +#define DMA_PER_INJECT_PKT_ADDR	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfe8)
> +#define DMA_PER_INJECT_PKT	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfec)
> +#define DMA_PER_PAT_PTR_INIT	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xff0)
> +#define DMA_PER_PAT_PTR		(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xff4)
> +#define DMA_PER_SLEEP_MASK	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xff8)
> +#define DMA_PER_SLEEP_COUNTER	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xffc)
> +/* #define DMA_RF_CPUREGn	DMA_RFBASEADDR n=0 to 15) slim regsa */
> +
> +/* The following are from DMA_DMEM_BaseAddress */
> +#define DMA_FIRMWARE_VERSION	(DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET + 0x0)
> +#define DMA_PTRREC_BASE		(DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET + 0x4)
> +#define DMA_PTRREC_INPUT_OFFSET	(DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET + 0x8)
> +#define DMA_ERRREC_BASE		(DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET + 0xc)
> +#define DMA_ERROR_RECORD(n)	((n*4) + DMA_ERRREC_BASE + 0x4)
> +#define DMA_IDLE_REQ		(DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET + 0x10)
> +#define IDLEREQ			BIT(31)
> +
> +#define DMA_FIRMWARE_CONFIG	(DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET + 0x14)
> +
> +/* Regs for PID Filter */
> +
> +#define PIDF_OFFSET		0x2800
> +#define PIDF_BASE(n)		((n*4) + PIDF_OFFSET)
> +#define PIDF_LEAK_ENABLE	(PIDF_OFFSET + 0x100)
> +#define PIDF_LEAK_STATUS	(PIDF_OFFSET + 0x108)
> +#define PIDF_LEAK_COUNT_RESET	(PIDF_OFFSET + 0x110)
> +#define PIDF_LEAK_COUNTER	(PIDF_OFFSET + 0x114)
> +
> +#endif /* _C8SECTPFE_CORE_H_ */

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

* Re: [PATCH 09/12] [media] tsin: c8sectpfe: Add support for various ST NIM cards.
  2015-06-24 15:11 ` [PATCH 09/12] [media] tsin: c8sectpfe: Add support for various ST NIM cards Peter Griffin
@ 2015-07-22 21:53   ` Mauro Carvalho Chehab
  2015-07-30  9:43     ` Peter Griffin
  0 siblings, 1 reply; 32+ messages in thread
From: Mauro Carvalho Chehab @ 2015-07-22 21:53 UTC (permalink / raw)
  To: Peter Griffin
  Cc: linux-arm-kernel, linux-kernel, srinivas.kandagatla,
	maxime.coquelin, patrice.chotard, lee.jones, hugues.fruchet,
	linux-media, devicetree

Em Wed, 24 Jun 2015 16:11:07 +0100
Peter Griffin <peter.griffin@linaro.org> escreveu:

> This patch adds support for the following 3 NIM cards: -
> 1) STV0367-NIM (stv0367 demod with Thompson PLL)
> 2) B2100A (2x stv0367 demods & 2x NXP tda18212 tuners)
> 3) STV0903-6110NIM (stv0903 demod + 6110 tuner, lnb24)
> 
> Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
> ---
>  drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.c | 296 +++++++++++++++++++++++++++
>  drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.h |  20 ++
>  2 files changed, 316 insertions(+)
>  create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.c
>  create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.h
> 
> diff --git a/drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.c b/drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.c
> new file mode 100644
> index 0000000..5c4ecb4
> --- /dev/null
> +++ b/drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.c
> @@ -0,0 +1,296 @@
> +/*
> + *  c8sectpfe-dvb.c - C8SECTPFE STi DVB driver
> + *
> + * Copyright (c) STMicroelectronics 2015
> + *
> + *  Author Peter Griffin <peter.griffin@linaro.org>
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation; either version 2 of the License, or
> + *  (at your option) any later version.
> + *
> + *  This program is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *
> + *  GNU General Public License for more details.
> + */
> +#include <linux/completion.h>
> +#include <linux/delay.h>
> +#include <linux/i2c.h>
> +#include <linux/interrupt.h>
> +#include <linux/version.h>
> +
> +#include <dt-bindings/media/c8sectpfe.h>
> +
> +#include "c8sectpfe-common.h"
> +#include "c8sectpfe-core.h"
> +#include "c8sectpfe-dvb.h"
> +
> +#include "dvb-pll.h"
> +#include "lnbh24.h"
> +#include "stv0367.h"
> +#include "stv0367_priv.h"
> +#include "stv6110x.h"
> +#include "stv090x.h"
> +#include "tda18212.h"
> +
> +static inline const char *dvb_card_str(unsigned int c)
> +{
> +	switch (c) {
> +	case STV0367_PLL_BOARD_NIMA:	return "STV0367_PLL_BOARD_NIMA";
> +	case STV0367_PLL_BOARD_NIMB:	return "STV0367_PLL_BOARD_NIMB";
> +	case STV0367_TDA18212_NIMA_1:	return "STV0367_TDA18212_NIMA_1";
> +	case STV0367_TDA18212_NIMA_2:	return "STV0367_TDA18212_NIMA_2";
> +	case STV0367_TDA18212_NIMB_1:	return "STV0367_TDA18212_NIMB_1";
> +	case STV0367_TDA18212_NIMB_2:	return "STV0367_TDA18212_NIMB_2";
> +	case STV0903_6110_LNB24_NIMA:	return "STV0903_6110_LNB24_NIMA";
> +	case STV0903_6110_LNB24_NIMB:	return "STV0903_6110_LNB24_NIMB";
> +	default:			return "unknown dvb frontend card";
> +	}
> +}
> +
> +static struct stv090x_config stv090x_config = {
> +	.device                 = STV0903,
> +	.demod_mode             = STV090x_SINGLE,
> +	.clk_mode               = STV090x_CLK_EXT,
> +	.xtal                   = 16000000,
> +	.address                = 0x69,
> +
> +	.ts1_mode               = STV090x_TSMODE_SERIAL_CONTINUOUS,
> +	.ts2_mode               = STV090x_TSMODE_SERIAL_CONTINUOUS,
> +
> +	.repeater_level         = STV090x_RPTLEVEL_64,
> +
> +	.tuner_init             = NULL,
> +	.tuner_set_mode         = NULL,
> +	.tuner_set_frequency    = NULL,
> +	.tuner_get_frequency    = NULL,
> +	.tuner_set_bandwidth    = NULL,
> +	.tuner_get_bandwidth    = NULL,
> +	.tuner_set_bbgain       = NULL,
> +	.tuner_get_bbgain       = NULL,
> +	.tuner_set_refclk       = NULL,
> +	.tuner_get_status       = NULL,
> +};
> +
> +static struct stv6110x_config stv6110x_config = {
> +	.addr                   = 0x60,
> +	.refclk                 = 16000000,
> +};
> +
> +#define NIMA 0
> +#define NIMB 1
> +
> +static struct stv0367_config stv0367_pll_config[] = {
> +	{
> +		.demod_address = 0x1c,
> +		.xtal = 27000000,
> +		.if_khz = 36166,
> +		.if_iq_mode = FE_TER_NORMAL_IF_TUNER,
> +		.ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
> +		.clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
> +	}, {
> +		.demod_address = 0x1d,
> +		.xtal = 27000000,
> +		.if_khz = 36166,
> +		.if_iq_mode = FE_TER_NORMAL_IF_TUNER,
> +		.ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
> +		.clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
> +	},
> +};
> +
> +static struct stv0367_config stv0367_tda18212_config[] = {
> +	{
> +		.demod_address = 0x1c,
> +		.xtal = 16000000,
> +		.if_khz = 4500,
> +		.if_iq_mode = FE_TER_NORMAL_IF_TUNER,
> +		.ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
> +		.clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
> +	}, {
> +		.demod_address = 0x1d,
> +		.xtal = 16000000,
> +		.if_khz = 4500,
> +		.if_iq_mode = FE_TER_NORMAL_IF_TUNER,
> +		.ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
> +		.clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
> +	}, {
> +		.demod_address = 0x1e,
> +		.xtal = 16000000,
> +		.if_khz = 4500,
> +		.if_iq_mode = FE_TER_NORMAL_IF_TUNER,
> +		.ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
> +		.clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
> +	},
> +};
> +
> +static struct tda18212_config tda18212_conf = {
> +	.if_dvbt_6 = 4150,
> +	.if_dvbt_7 = 4150,
> +	.if_dvbt_8 = 4500,
> +	.if_dvbc = 5000,
> +};
> +
> +int c8sectpfe_frontend_attach(struct dvb_frontend **fe,
> +		struct c8sectpfe *c8sectpfe,
> +		struct channel_info *tsin, int chan_num)
> +{
> +	struct tda18212_config *tda18212;
> +	struct stv6110x_devctl *fe2;
> +	struct i2c_client *client;
> +	struct i2c_board_info tda18212_info = {
> +		.type = "tda18212",
> +		.addr = 0x60,
> +	};
> +
> +	BUG_ON(!tsin);

Just return an error if !tsin.

> +
> +	switch (tsin->dvb_card) {
> +
> +	case STV0367_PLL_BOARD_NIMA:
> +	case STV0367_PLL_BOARD_NIMB:
> +		if (tsin->dvb_card == STV0367_PLL_BOARD_NIMA)
> +			*fe = dvb_attach(stv0367ter_attach,
> +				 &stv0367_pll_config[NIMA], tsin->i2c_adapter);
> +		else
> +			*fe = dvb_attach(stv0367ter_attach,
> +				 &stv0367_pll_config[NIMB], tsin->i2c_adapter);
> +
> +		if (!*fe) {
> +			dev_err(c8sectpfe->device,
> +				"%s: stv0367ter_attach failed for NIM card %s\n"
> +				, __func__, dvb_card_str(tsin->dvb_card));
> +			return -ENODEV;
> +		};
> +
> +		/*
> +		 * init the demod so that i2c gate_ctrl
> +		 * to the tuner works correctly
> +		 */
> +		(*fe)->ops.init(*fe);
> +
> +		if (!dvb_attach(dvb_pll_attach, *fe, 0x60,
> +			tsin->i2c_adapter, DVB_PLL_THOMSON_DTT7546X)) {
> +
> +			dev_err(c8sectpfe->device,
> +				"%s: DVB_PLL_THOMSON_DTT7546X attach failed\n\t"
> +				"for NIM card %s\n",
> +				__func__, dvb_card_str(tsin->dvb_card));
> +			return -ENODEV;
> +		}
> +		break;
> +
> +	case STV0367_TDA18212_NIMA_1:
> +	case STV0367_TDA18212_NIMA_2:
> +	case STV0367_TDA18212_NIMB_1:
> +	case STV0367_TDA18212_NIMB_2:
> +		if (tsin->dvb_card == STV0367_TDA18212_NIMA_1)
> +			*fe = dvb_attach(stv0367ter_attach,
> +				 &stv0367_tda18212_config[0],
> +					tsin->i2c_adapter);
> +		else if (tsin->dvb_card == STV0367_TDA18212_NIMB_1)
> +			*fe = dvb_attach(stv0367ter_attach,
> +				 &stv0367_tda18212_config[1],
> +					tsin->i2c_adapter);
> +		else
> +			*fe = dvb_attach(stv0367ter_attach,
> +				 &stv0367_tda18212_config[2],
> +					tsin->i2c_adapter);
> +
> +		if (!*fe) {
> +			dev_err(c8sectpfe->device,
> +				"%s: stv0367ter_attach failed for NIM card %s\n"
> +				, __func__, dvb_card_str(tsin->dvb_card));
> +			return -ENODEV;
> +		};
> +
> +		/*
> +		 * init the demod so that i2c gate_ctrl
> +		 * to the tuner works correctly
> +		 */
> +		(*fe)->ops.init(*fe);
> +
> +		/* Allocate the tda18212 structure */
> +		tda18212 = devm_kzalloc(c8sectpfe->device,
> +					sizeof(struct tda18212_config),
> +					GFP_KERNEL);
> +		if (!tda18212) {
> +			dev_err(c8sectpfe->device,
> +				"%s: devm_kzalloc failed\n", __func__);
> +			return -ENOMEM;
> +		}
> +
> +		memcpy(tda18212, &tda18212_conf,
> +			sizeof(struct tda18212_config));
> +
> +		tda18212->fe = (*fe);
> +
> +		tda18212_info.platform_data = tda18212;
> +
> +		/* attach tuner */
> +		request_module("tda18212");
> +		client = i2c_new_device(tsin->i2c_adapter, &tda18212_info);
> +		if (!client || !client->dev.driver) {
> +			dvb_frontend_detach(*fe);
> +			return -ENODEV;
> +		}
> +
> +		if (!try_module_get(client->dev.driver->owner)) {
> +			i2c_unregister_device(client);
> +			dvb_frontend_detach(*fe);
> +			return -ENODEV;
> +		}
> +
> +		tsin->i2c_client = client;
> +
> +		break;
> +
> +	case STV0903_6110_LNB24_NIMA:
> +		*fe = dvb_attach(stv090x_attach,	&stv090x_config,
> +				tsin->i2c_adapter, STV090x_DEMODULATOR_0);
> +		if (!*fe) {
> +			dev_err(c8sectpfe->device, "%s: stv090x_attach failed\n"
> +				"\tfor NIM card %s\n",
> +				__func__, dvb_card_str(tsin->dvb_card));
> +			return -ENODEV;
> +		}
> +
> +		fe2 = dvb_attach(stv6110x_attach, *fe,
> +					&stv6110x_config, tsin->i2c_adapter);
> +		if (!fe2) {
> +			dev_err(c8sectpfe->device,
> +				"%s: stv6110x_attach failed for NIM card %s\n"
> +				, __func__, dvb_card_str(tsin->dvb_card));
> +			return -ENODEV;
> +		};
> +
> +		stv090x_config.tuner_init = fe2->tuner_init;
> +		stv090x_config.tuner_set_mode = fe2->tuner_set_mode;
> +		stv090x_config.tuner_set_frequency = fe2->tuner_set_frequency;
> +		stv090x_config.tuner_get_frequency = fe2->tuner_get_frequency;
> +		stv090x_config.tuner_set_bandwidth = fe2->tuner_set_bandwidth;
> +		stv090x_config.tuner_get_bandwidth = fe2->tuner_get_bandwidth;
> +		stv090x_config.tuner_set_bbgain = fe2->tuner_set_bbgain;
> +		stv090x_config.tuner_get_bbgain = fe2->tuner_get_bbgain;
> +		stv090x_config.tuner_set_refclk = fe2->tuner_set_refclk;
> +		stv090x_config.tuner_get_status = fe2->tuner_get_status;
> +
> +		dvb_attach(lnbh24_attach, *fe, tsin->i2c_adapter, 0, 0, 0x9);
> +		break;
> +
> +	default:
> +		dev_err(c8sectpfe->device,
> +			"%s: DVB frontend card %s not yet supported\n",
> +			__func__, dvb_card_str(tsin->dvb_card));
> +		return -ENODEV;
> +	}
> +
> +	(*fe)->id = chan_num;
> +
> +	dev_info(c8sectpfe->device,
> +			"DVB frontend card %s successfully attached",
> +			dvb_card_str(tsin->dvb_card));
> +	return 0;
> +}
> diff --git a/drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.h b/drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.h
> new file mode 100644
> index 0000000..bd366db
> --- /dev/null
> +++ b/drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.h
> @@ -0,0 +1,20 @@
> +/*
> + * c8sectpfe-common.h - C8SECTPFE STi DVB driver
> + *
> + * Copyright (c) STMicroelectronics 2015
> + *
> + *   Author: Peter Griffin <peter.griffin@linaro.org>
> + *
> + *      This program is free software; you can redistribute it and/or
> + *      modify it under the terms of the GNU General Public License as
> + *      published by the Free Software Foundation; either version 2 of
> + *      the License, or (at your option) any later version.
> + */
> +#ifndef _C8SECTPFE_DVB_H_
> +#define _C8SECTPFE_DVB_H_
> +
> +int c8sectpfe_frontend_attach(struct dvb_frontend **fe,
> +			struct c8sectpfe *c8sectpfe, struct channel_info *tsin,
> +			int chan_num);
> +
> +#endif

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

* Re: [PATCH 11/12] [media] tsin: c8sectpfe: Add Kconfig and Makefile for the driver.
  2015-06-24 15:11 ` [PATCH 11/12] [media] tsin: c8sectpfe: Add Kconfig and Makefile for the driver Peter Griffin
  2015-06-25  7:23   ` Paul Bolle
@ 2015-07-22 21:56   ` Mauro Carvalho Chehab
  2015-07-30  9:39     ` Peter Griffin
  1 sibling, 1 reply; 32+ messages in thread
From: Mauro Carvalho Chehab @ 2015-07-22 21:56 UTC (permalink / raw)
  To: Peter Griffin
  Cc: linux-arm-kernel, linux-kernel, srinivas.kandagatla,
	maxime.coquelin, patrice.chotard, lee.jones, hugues.fruchet,
	linux-media, devicetree

Em Wed, 24 Jun 2015 16:11:09 +0100
Peter Griffin <peter.griffin@linaro.org> escreveu:

> This patch adds the Kconfig and Makefile for the c8sectpfe driver
> so it will be built. It also selects additional demodulator and tuners
> which are required by the supported NIM cards.
> 
> Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
> ---
>  drivers/media/Kconfig                 |  1 +
>  drivers/media/Makefile                |  1 +
>  drivers/media/tsin/c8sectpfe/Kconfig  | 26 ++++++++++++++++++++++++++
>  drivers/media/tsin/c8sectpfe/Makefile | 11 +++++++++++
>  4 files changed, 39 insertions(+)
>  create mode 100644 drivers/media/tsin/c8sectpfe/Kconfig
>  create mode 100644 drivers/media/tsin/c8sectpfe/Makefile
> 
> diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
> index 1570992..82bc1dc 100644
> --- a/drivers/media/Kconfig
> +++ b/drivers/media/Kconfig
> @@ -170,6 +170,7 @@ source "drivers/media/pci/Kconfig"
>  source "drivers/media/platform/Kconfig"
>  source "drivers/media/mmc/Kconfig"
>  source "drivers/media/radio/Kconfig"
> +source "drivers/media/tsin/c8sectpfe/Kconfig"
>  
>  comment "Supported FireWire (IEEE 1394) Adapters"
>  	depends on DVB_CORE && FIREWIRE
> diff --git a/drivers/media/Makefile b/drivers/media/Makefile
> index e608bbc..0a567b8 100644
> --- a/drivers/media/Makefile
> +++ b/drivers/media/Makefile
> @@ -29,5 +29,6 @@ obj-y += rc/
>  #
>  
>  obj-y += common/ platform/ pci/ usb/ mmc/ firewire/
> +obj-$(CONFIG_DVB_C8SECTPFE) += tsin/c8sectpfe/

Hmm... why are you adding it at a new "tsin" directory? We're putting
those SoC platform drivers under platform/.

>  obj-$(CONFIG_VIDEO_DEV) += radio/
>  
> diff --git a/drivers/media/tsin/c8sectpfe/Kconfig b/drivers/media/tsin/c8sectpfe/Kconfig
> new file mode 100644
> index 0000000..8d99a87
> --- /dev/null
> +++ b/drivers/media/tsin/c8sectpfe/Kconfig
> @@ -0,0 +1,26 @@
> +config DVB_C8SECTPFE
> +	tristate "STMicroelectronics C8SECTPFE DVB support"
> +	depends on DVB_CORE && I2C && (ARCH_STI || ARCH_MULTIPLATFORM)
> +	select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT
> +	select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT
> +	select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT
> +	select DVB_STV6110 if MEDIA_SUBDRV_AUTOSELECT
> +	select DVB_STV0900 if MEDIA_SUBDRV_AUTOSELECT
> +	select DVB_STV0367 if MEDIA_SUBDRV_AUTOSELECT
> +	select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
> +	select MEDIA_TUNER_TDA18212 if MEDIA_SUBDRV_AUTOSELECT
> +
> +	---help---
> +	  This adds support for DVB front-end cards connected
> +	  to TS inputs of STiH407/410 SoC.
> +
> +	  The driver currently supports C8SECTPFE's TS input block,
> +	  memdma engine, and HW PID filtering.
> +
> +	  Supported DVB front-end cards are:
> +	  - STMicroelectronics DVB-T B2100A (STV0367 + TDA18212)
> +	  - STMicroelectronics DVB-T STV0367 PLL board (STV0367 + DTT7546X)
> +	  - STMicroelectronics DVB-S/S2 STV0903 + STV6110 + LNBP24 board
> +
> +	  To compile this driver as a module, choose M here: the
> +	  module will be called c8sectpfe.
> diff --git a/drivers/media/tsin/c8sectpfe/Makefile b/drivers/media/tsin/c8sectpfe/Makefile
> new file mode 100644
> index 0000000..777f06d
> --- /dev/null
> +++ b/drivers/media/tsin/c8sectpfe/Makefile
> @@ -0,0 +1,11 @@
> +c8sectpfe-y += c8sectpfe-core.o c8sectpfe-common.o c8sectpfe-dvb.o
> +
> +obj-$(CONFIG_DVB_C8SECTPFE) += c8sectpfe.o
> +
> +ifneq ($(CONFIG_DVB_C8SECTPFE),)
> +	c8sectpfe-y += c8sectpfe-debugfs.o
> +endif
> +
> +ccflags-y += -Idrivers/media/i2c
> +ccflags-y += -Idrivers/media/common
> +ccflags-y += -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends/ -Idrivers/media/tuners/

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

* Re: [PATCH 02/12] [media] dvb-pll: Add support for THOMSON DTT7546X tuner.
  2015-06-25  1:17   ` Joe Perches
@ 2015-07-22 21:58     ` Mauro Carvalho Chehab
  2015-07-30  9:47       ` Peter Griffin
  0 siblings, 1 reply; 32+ messages in thread
From: Mauro Carvalho Chehab @ 2015-07-22 21:58 UTC (permalink / raw)
  To: Peter Griffin
  Cc: Joe Perches, linux-arm-kernel, linux-kernel, srinivas.kandagatla,
	maxime.coquelin, patrice.chotard, lee.jones, hugues.fruchet,
	linux-media, devicetree

Em Wed, 24 Jun 2015 18:17:37 -0700
Joe Perches <joe@perches.com> escreveu:

> On Wed, 2015-06-24 at 16:11 +0100, Peter Griffin wrote:
> > This is used in conjunction with the STV0367 demodulator on
> > the STV0367-NIM-V1.0 NIM card which can be used with the STi
> > STB SoC's.
> 
> Barely associated to this specific patch, but for
> dvb-pll.c, another thing that seems possible is to
> convert the struct dvb_pll_desc uses to const and
> change the "entries" fixed array size from 12 to []
> 
> It'd save a couple KB overall and remove ~5KB of data.
> 
> $ size drivers/media/dvb-frontends/dvb-pll.o*
>    text	   data	    bss	    dec	    hex	filename
>    8520	   1552	   2120	  12192	   2fa0	drivers/media/dvb-frontends/dvb-pll.o.new
>    5624	   6363	   2120	  14107	   371b	drivers/media/dvb-frontends/dvb-pll.o.old

Peter,

Please add this patch on the next patch series you submit.

Regards,
Mauro

> ---
>  drivers/media/dvb-frontends/dvb-pll.c | 50 +++++++++++++++++------------------
>  1 file changed, 25 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/media/dvb-frontends/dvb-pll.c b/drivers/media/dvb-frontends/dvb-pll.c
> index 6d8fe88..53089e1 100644
> --- a/drivers/media/dvb-frontends/dvb-pll.c
> +++ b/drivers/media/dvb-frontends/dvb-pll.c
> @@ -34,7 +34,7 @@ struct dvb_pll_priv {
>  	struct i2c_adapter *i2c;
>  
>  	/* the PLL descriptor */
> -	struct dvb_pll_desc *pll_desc;
> +	const struct dvb_pll_desc *pll_desc;
>  
>  	/* cached frequency/bandwidth */
>  	u32 frequency;
> @@ -57,7 +57,7 @@ MODULE_PARM_DESC(id, "force pll id to use (DEBUG ONLY)");
>  /* ----------------------------------------------------------- */
>  
>  struct dvb_pll_desc {
> -	char *name;
> +	const char *name;
>  	u32  min;
>  	u32  max;
>  	u32  iffreq;
> @@ -71,13 +71,13 @@ struct dvb_pll_desc {
>  		u32 stepsize;
>  		u8  config;
>  		u8  cb;
> -	} entries[12];
> +	} entries[];
>  };
>  
>  /* ----------------------------------------------------------- */
>  /* descriptions                                                */
>  
> -static struct dvb_pll_desc dvb_pll_thomson_dtt7579 = {
> +static const struct dvb_pll_desc dvb_pll_thomson_dtt7579 = {
>  	.name  = "Thomson dtt7579",
>  	.min   = 177000000,
>  	.max   = 858000000,
> @@ -99,7 +99,7 @@ static void thomson_dtt759x_bw(struct dvb_frontend *fe, u8 *buf)
>  		buf[3] |= 0x10;
>  }
>  
> -static struct dvb_pll_desc dvb_pll_thomson_dtt759x = {
> +static const struct dvb_pll_desc dvb_pll_thomson_dtt759x = {
>  	.name  = "Thomson dtt759x",
>  	.min   = 177000000,
>  	.max   = 896000000,
> @@ -123,7 +123,7 @@ static void thomson_dtt7520x_bw(struct dvb_frontend *fe, u8 *buf)
>  		buf[3] ^= 0x10;
>  }
>  
> -static struct dvb_pll_desc dvb_pll_thomson_dtt7520x = {
> +static const struct dvb_pll_desc dvb_pll_thomson_dtt7520x = {
>  	.name  = "Thomson dtt7520x",
>  	.min   = 185000000,
>  	.max   = 900000000,
> @@ -141,7 +141,7 @@ static struct dvb_pll_desc dvb_pll_thomson_dtt7520x = {
>  	},
>  };
>  
> -static struct dvb_pll_desc dvb_pll_lg_z201 = {
> +static const struct dvb_pll_desc dvb_pll_lg_z201 = {
>  	.name  = "LG z201",
>  	.min   = 174000000,
>  	.max   = 862000000,
> @@ -157,7 +157,7 @@ static struct dvb_pll_desc dvb_pll_lg_z201 = {
>  	},
>  };
>  
> -static struct dvb_pll_desc dvb_pll_unknown_1 = {
> +static const struct dvb_pll_desc dvb_pll_unknown_1 = {
>  	.name  = "unknown 1", /* used by dntv live dvb-t */
>  	.min   = 174000000,
>  	.max   = 862000000,
> @@ -179,7 +179,7 @@ static struct dvb_pll_desc dvb_pll_unknown_1 = {
>  /* Infineon TUA6010XS
>   * used in Thomson Cable Tuner
>   */
> -static struct dvb_pll_desc dvb_pll_tua6010xs = {
> +static const struct dvb_pll_desc dvb_pll_tua6010xs = {
>  	.name  = "Infineon TUA6010XS",
>  	.min   =  44250000,
>  	.max   = 858000000,
> @@ -193,7 +193,7 @@ static struct dvb_pll_desc dvb_pll_tua6010xs = {
>  };
>  
>  /* Panasonic env57h1xd5 (some Philips PLL ?) */
> -static struct dvb_pll_desc dvb_pll_env57h1xd5 = {
> +static const struct dvb_pll_desc dvb_pll_env57h1xd5 = {
>  	.name  = "Panasonic ENV57H1XD5",
>  	.min   =  44250000,
>  	.max   = 858000000,
> @@ -217,7 +217,7 @@ static void tda665x_bw(struct dvb_frontend *fe, u8 *buf)
>  		buf[3] |= 0x08;
>  }
>  
> -static struct dvb_pll_desc dvb_pll_tda665x = {
> +static const struct dvb_pll_desc dvb_pll_tda665x = {
>  	.name  = "Philips TDA6650/TDA6651",
>  	.min   =  44250000,
>  	.max   = 858000000,
> @@ -251,7 +251,7 @@ static void tua6034_bw(struct dvb_frontend *fe, u8 *buf)
>  		buf[3] |= 0x08;
>  }
>  
> -static struct dvb_pll_desc dvb_pll_tua6034 = {
> +static const struct dvb_pll_desc dvb_pll_tua6034 = {
>  	.name  = "Infineon TUA6034",
>  	.min   =  44250000,
>  	.max   = 858000000,
> @@ -275,7 +275,7 @@ static void tded4_bw(struct dvb_frontend *fe, u8 *buf)
>  		buf[3] |= 0x04;
>  }
>  
> -static struct dvb_pll_desc dvb_pll_tded4 = {
> +static const struct dvb_pll_desc dvb_pll_tded4 = {
>  	.name = "ALPS TDED4",
>  	.min = 47000000,
>  	.max = 863000000,
> @@ -293,7 +293,7 @@ static struct dvb_pll_desc dvb_pll_tded4 = {
>  /* ALPS TDHU2
>   * used in AverTVHD MCE A180
>   */
> -static struct dvb_pll_desc dvb_pll_tdhu2 = {
> +static const struct dvb_pll_desc dvb_pll_tdhu2 = {
>  	.name = "ALPS TDHU2",
>  	.min = 54000000,
>  	.max = 864000000,
> @@ -310,7 +310,7 @@ static struct dvb_pll_desc dvb_pll_tdhu2 = {
>  /* Samsung TBMV30111IN / TBMV30712IN1
>   * used in Air2PC ATSC - 2nd generation (nxt2002)
>   */
> -static struct dvb_pll_desc dvb_pll_samsung_tbmv = {
> +static const struct dvb_pll_desc dvb_pll_samsung_tbmv = {
>  	.name = "Samsung TBMV30111IN / TBMV30712IN1",
>  	.min = 54000000,
>  	.max = 860000000,
> @@ -329,7 +329,7 @@ static struct dvb_pll_desc dvb_pll_samsung_tbmv = {
>  /*
>   * Philips SD1878 Tuner.
>   */
> -static struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = {
> +static const struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = {
>  	.name  = "Philips SD1878",
>  	.min   =  950000,
>  	.max   = 2150000,
> @@ -395,7 +395,7 @@ static void opera1_bw(struct dvb_frontend *fe, u8 *buf)
>  	return;
>  }
>  
> -static struct dvb_pll_desc dvb_pll_opera1 = {
> +static const struct dvb_pll_desc dvb_pll_opera1 = {
>  	.name  = "Opera Tuner",
>  	.min   =  900000,
>  	.max   = 2250000,
> @@ -442,7 +442,7 @@ static void samsung_dtos403ih102a_set(struct dvb_frontend *fe, u8 *buf)
>  }
>  
>  /* unknown pll used in Samsung DTOS403IH102A DVB-C tuner */
> -static struct dvb_pll_desc dvb_pll_samsung_dtos403ih102a = {
> +static const struct dvb_pll_desc dvb_pll_samsung_dtos403ih102a = {
>  	.name   = "Samsung DTOS403IH102A",
>  	.min    =  44250000,
>  	.max    = 858000000,
> @@ -462,7 +462,7 @@ static struct dvb_pll_desc dvb_pll_samsung_dtos403ih102a = {
>  };
>  
>  /* Samsung TDTC9251DH0 DVB-T NIM, as used on AirStar 2 */
> -static struct dvb_pll_desc dvb_pll_samsung_tdtc9251dh0 = {
> +static const struct dvb_pll_desc dvb_pll_samsung_tdtc9251dh0 = {
>  	.name	= "Samsung TDTC9251DH0",
>  	.min	=  48000000,
>  	.max	= 863000000,
> @@ -476,7 +476,7 @@ static struct dvb_pll_desc dvb_pll_samsung_tdtc9251dh0 = {
>  };
>  
>  /* Samsung TBDU18132 DVB-S NIM with TSA5059 PLL, used in SkyStar2 DVB-S 2.3 */
> -static struct dvb_pll_desc dvb_pll_samsung_tbdu18132 = {
> +static const struct dvb_pll_desc dvb_pll_samsung_tbdu18132 = {
>  	.name = "Samsung TBDU18132",
>  	.min	=  950000,
>  	.max	= 2150000, /* guesses */
> @@ -497,7 +497,7 @@ static struct dvb_pll_desc dvb_pll_samsung_tbdu18132 = {
>  };
>  
>  /* Samsung TBMU24112 DVB-S NIM with SL1935 zero-IF tuner */
> -static struct dvb_pll_desc dvb_pll_samsung_tbmu24112 = {
> +static const struct dvb_pll_desc dvb_pll_samsung_tbmu24112 = {
>  	.name = "Samsung TBMU24112",
>  	.min	=  950000,
>  	.max	= 2150000, /* guesses */
> @@ -518,7 +518,7 @@ static struct dvb_pll_desc dvb_pll_samsung_tbmu24112 = {
>   * 153 - 430   0  *  0   0   0   0   1   0   0x02
>   * 430 - 822   0  *  0   0   1   0   0   0   0x08
>   * 822 - 862   1  *  0   0   1   0   0   0   0x88 */
> -static struct dvb_pll_desc dvb_pll_alps_tdee4 = {
> +static const struct dvb_pll_desc dvb_pll_alps_tdee4 = {
>  	.name = "ALPS TDEE4",
>  	.min	=  47000000,
>  	.max	= 862000000,
> @@ -534,7 +534,7 @@ static struct dvb_pll_desc dvb_pll_alps_tdee4 = {
>  
>  /* ----------------------------------------------------------- */
>  
> -static struct dvb_pll_desc *pll_list[] = {
> +static const struct dvb_pll_desc *pll_list[] = {
>  	[DVB_PLL_UNDEFINED]              = NULL,
>  	[DVB_PLL_THOMSON_DTT7579]        = &dvb_pll_thomson_dtt7579,
>  	[DVB_PLL_THOMSON_DTT759X]        = &dvb_pll_thomson_dtt759x,
> @@ -564,7 +564,7 @@ static int dvb_pll_configure(struct dvb_frontend *fe, u8 *buf,
>  			     const u32 frequency)
>  {
>  	struct dvb_pll_priv *priv = fe->tuner_priv;
> -	struct dvb_pll_desc *desc = priv->pll_desc;
> +	const struct dvb_pll_desc *desc = priv->pll_desc;
>  	u32 div;
>  	int i;
>  
> @@ -758,7 +758,7 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
>  			       .buf = b1, .len = 1 };
>  	struct dvb_pll_priv *priv = NULL;
>  	int ret;
> -	struct dvb_pll_desc *desc;
> +	const struct dvb_pll_desc *desc;
>  
>  	if ((id[dvb_pll_devcount] > DVB_PLL_UNDEFINED) &&
>  	    (id[dvb_pll_devcount] < ARRAY_SIZE(pll_list)))
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 11/12] [media] tsin: c8sectpfe: Add Kconfig and Makefile for the driver.
  2015-07-22 21:56   ` Mauro Carvalho Chehab
@ 2015-07-30  9:39     ` Peter Griffin
  0 siblings, 0 replies; 32+ messages in thread
From: Peter Griffin @ 2015-07-30  9:39 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: linux-arm-kernel, linux-kernel, srinivas.kandagatla,
	maxime.coquelin, patrice.chotard, lee.jones, hugues.fruchet,
	linux-media, devicetree

Hi Mauro,

Thanks for reviewing. Sending my reply again, as it looks like I dropped the
CC list on my first reply, and my second reply bounced on the mailing lists :-(

On Wed, 22 Jul 2015, Mauro Carvalho Chehab wrote:

> Em Wed, 24 Jun 2015 16:11:09 +0100
> Peter Griffin <peter.griffin@linaro.org> escreveu:
> 
> > This patch adds the Kconfig and Makefile for the c8sectpfe driver
> > so it will be built. It also selects additional demodulator and tuners
> > which are required by the supported NIM cards.
> > 
> > Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
> > ---
> >  drivers/media/Kconfig                 |  1 +
> >  drivers/media/Makefile                |  1 +
> >  drivers/media/tsin/c8sectpfe/Kconfig  | 26 ++++++++++++++++++++++++++
> >  drivers/media/tsin/c8sectpfe/Makefile | 11 +++++++++++
> >  4 files changed, 39 insertions(+)
> >  create mode 100644 drivers/media/tsin/c8sectpfe/Kconfig
> >  create mode 100644 drivers/media/tsin/c8sectpfe/Makefile
> > 
> > diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
> > index 1570992..82bc1dc 100644
> > --- a/drivers/media/Kconfig
> > +++ b/drivers/media/Kconfig
> > @@ -170,6 +170,7 @@ source "drivers/media/pci/Kconfig"
> >  source "drivers/media/platform/Kconfig"
> >  source "drivers/media/mmc/Kconfig"
> >  source "drivers/media/radio/Kconfig"
> > +source "drivers/media/tsin/c8sectpfe/Kconfig"
> >  
> >  comment "Supported FireWire (IEEE 1394) Adapters"
> >  	depends on DVB_CORE && FIREWIRE
> > diff --git a/drivers/media/Makefile b/drivers/media/Makefile
> > index e608bbc..0a567b8 100644
> > --- a/drivers/media/Makefile
> > +++ b/drivers/media/Makefile
> > @@ -29,5 +29,6 @@ obj-y += rc/
> >  #
> >  
> >  obj-y += common/ platform/ pci/ usb/ mmc/ firewire/
> > +obj-$(CONFIG_DVB_C8SECTPFE) += tsin/c8sectpfe/
> 
> Hmm... why are you adding it at a new "tsin" directory? We're putting
> those SoC platform drivers under platform/.

I didn't realise that. I will move this under there in the V2 patchset then?

The rationale behind a new 'tsin' directory was that all the current DVB
drivers seemed to be grouped by the underlying bus on which TS
data enters the system (e.g. pci / usb).

As this didn't fit in with that scheme I created a new tsin directory for SoC's
which have dedicated hardware for Transport Stream INput (tsin) into the SoC.

regards,

Peter.

p.s. Mauro - appologies again for spaming you

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

* Re: [PATCH 09/12] [media] tsin: c8sectpfe: Add support for various ST NIM cards.
  2015-07-22 21:53   ` Mauro Carvalho Chehab
@ 2015-07-30  9:43     ` Peter Griffin
  0 siblings, 0 replies; 32+ messages in thread
From: Peter Griffin @ 2015-07-30  9:43 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: linux-arm-kernel, linux-kernel, srinivas.kandagatla,
	maxime.coquelin, patrice.chotard, lee.jones, hugues.fruchet,
	linux-media, devicetree

Hi Mauro,

On Wed, 22 Jul 2015, Mauro Carvalho Chehab wrote:

> Em Wed, 24 Jun 2015 16:11:07 +0100
> Peter Griffin <peter.griffin@linaro.org> escreveu:
> 
> > This patch adds support for the following 3 NIM cards: -
> > 1) STV0367-NIM (stv0367 demod with Thompson PLL)
> > 2) B2100A (2x stv0367 demods & 2x NXP tda18212 tuners)
> > 3) STV0903-6110NIM (stv0903 demod + 6110 tuner, lnb24)
> > 
> > Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
> > ---
> >  drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.c | 296 +++++++++++++++++++++++++++
> >  drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.h |  20 ++
> >  2 files changed, 316 insertions(+)
> >  create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.c
> >  create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.h
> > 
> > diff --git a/drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.c b/drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.c
> > new file mode 100644
> > index 0000000..5c4ecb4
> > --- /dev/null
> > +++ b/drivers/media/tsin/c8sectpfe/c8sectpfe-dvb.c
> > @@ -0,0 +1,296 @@
> > +/*
> > + *  c8sectpfe-dvb.c - C8SECTPFE STi DVB driver
> > + *
> > + * Copyright (c) STMicroelectronics 2015
> > + *
> > + *  Author Peter Griffin <peter.griffin@linaro.org>
> > + *
> > + *  This program is free software; you can redistribute it and/or modify
> > + *  it under the terms of the GNU General Public License as published by
> > + *  the Free Software Foundation; either version 2 of the License, or
> > + *  (at your option) any later version.
> > + *
> > + *  This program is distributed in the hope that it will be useful,
> > + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + *
> > + *  GNU General Public License for more details.
> > + */
> > +#include <linux/completion.h>
> > +#include <linux/delay.h>
> > +#include <linux/i2c.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/version.h>
> > +
> > +#include <dt-bindings/media/c8sectpfe.h>
> > +
> > +#include "c8sectpfe-common.h"
> > +#include "c8sectpfe-core.h"
> > +#include "c8sectpfe-dvb.h"
> > +
> > +#include "dvb-pll.h"
> > +#include "lnbh24.h"
> > +#include "stv0367.h"
> > +#include "stv0367_priv.h"
> > +#include "stv6110x.h"
> > +#include "stv090x.h"
> > +#include "tda18212.h"
> > +
> > +static inline const char *dvb_card_str(unsigned int c)
> > +{
> > +	switch (c) {
> > +	case STV0367_PLL_BOARD_NIMA:	return "STV0367_PLL_BOARD_NIMA";
> > +	case STV0367_PLL_BOARD_NIMB:	return "STV0367_PLL_BOARD_NIMB";
> > +	case STV0367_TDA18212_NIMA_1:	return "STV0367_TDA18212_NIMA_1";
> > +	case STV0367_TDA18212_NIMA_2:	return "STV0367_TDA18212_NIMA_2";
> > +	case STV0367_TDA18212_NIMB_1:	return "STV0367_TDA18212_NIMB_1";
> > +	case STV0367_TDA18212_NIMB_2:	return "STV0367_TDA18212_NIMB_2";
> > +	case STV0903_6110_LNB24_NIMA:	return "STV0903_6110_LNB24_NIMA";
> > +	case STV0903_6110_LNB24_NIMB:	return "STV0903_6110_LNB24_NIMB";
> > +	default:			return "unknown dvb frontend card";
> > +	}
> > +}
> > +
> > +static struct stv090x_config stv090x_config = {
> > +	.device                 = STV0903,
> > +	.demod_mode             = STV090x_SINGLE,
> > +	.clk_mode               = STV090x_CLK_EXT,
> > +	.xtal                   = 16000000,
> > +	.address                = 0x69,
> > +
> > +	.ts1_mode               = STV090x_TSMODE_SERIAL_CONTINUOUS,
> > +	.ts2_mode               = STV090x_TSMODE_SERIAL_CONTINUOUS,
> > +
> > +	.repeater_level         = STV090x_RPTLEVEL_64,
> > +
> > +	.tuner_init             = NULL,
> > +	.tuner_set_mode         = NULL,
> > +	.tuner_set_frequency    = NULL,
> > +	.tuner_get_frequency    = NULL,
> > +	.tuner_set_bandwidth    = NULL,
> > +	.tuner_get_bandwidth    = NULL,
> > +	.tuner_set_bbgain       = NULL,
> > +	.tuner_get_bbgain       = NULL,
> > +	.tuner_set_refclk       = NULL,
> > +	.tuner_get_status       = NULL,
> > +};
> > +
> > +static struct stv6110x_config stv6110x_config = {
> > +	.addr                   = 0x60,
> > +	.refclk                 = 16000000,
> > +};
> > +
> > +#define NIMA 0
> > +#define NIMB 1
> > +
> > +static struct stv0367_config stv0367_pll_config[] = {
> > +	{
> > +		.demod_address = 0x1c,
> > +		.xtal = 27000000,
> > +		.if_khz = 36166,
> > +		.if_iq_mode = FE_TER_NORMAL_IF_TUNER,
> > +		.ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
> > +		.clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
> > +	}, {
> > +		.demod_address = 0x1d,
> > +		.xtal = 27000000,
> > +		.if_khz = 36166,
> > +		.if_iq_mode = FE_TER_NORMAL_IF_TUNER,
> > +		.ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
> > +		.clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
> > +	},
> > +};
> > +
> > +static struct stv0367_config stv0367_tda18212_config[] = {
> > +	{
> > +		.demod_address = 0x1c,
> > +		.xtal = 16000000,
> > +		.if_khz = 4500,
> > +		.if_iq_mode = FE_TER_NORMAL_IF_TUNER,
> > +		.ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
> > +		.clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
> > +	}, {
> > +		.demod_address = 0x1d,
> > +		.xtal = 16000000,
> > +		.if_khz = 4500,
> > +		.if_iq_mode = FE_TER_NORMAL_IF_TUNER,
> > +		.ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
> > +		.clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
> > +	}, {
> > +		.demod_address = 0x1e,
> > +		.xtal = 16000000,
> > +		.if_khz = 4500,
> > +		.if_iq_mode = FE_TER_NORMAL_IF_TUNER,
> > +		.ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
> > +		.clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
> > +	},
> > +};
> > +
> > +static struct tda18212_config tda18212_conf = {
> > +	.if_dvbt_6 = 4150,
> > +	.if_dvbt_7 = 4150,
> > +	.if_dvbt_8 = 4500,
> > +	.if_dvbc = 5000,
> > +};
> > +
> > +int c8sectpfe_frontend_attach(struct dvb_frontend **fe,
> > +		struct c8sectpfe *c8sectpfe,
> > +		struct channel_info *tsin, int chan_num)
> > +{
> > +	struct tda18212_config *tda18212;
> > +	struct stv6110x_devctl *fe2;
> > +	struct i2c_client *client;
> > +	struct i2c_board_info tda18212_info = {
> > +		.type = "tda18212",
> > +		.addr = 0x60,
> > +	};
> > +
> > +	BUG_ON(!tsin);
> 
> Just return an error if !tsin.

Ok will fix in V2

regards,

Peter.

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

* Re: [PATCH 02/12] [media] dvb-pll: Add support for THOMSON DTT7546X tuner.
  2015-07-22 17:10   ` Mauro Carvalho Chehab
@ 2015-07-30  9:46     ` Peter Griffin
  0 siblings, 0 replies; 32+ messages in thread
From: Peter Griffin @ 2015-07-30  9:46 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: linux-arm-kernel, linux-kernel, srinivas.kandagatla,
	maxime.coquelin, patrice.chotard, lee.jones, hugues.fruchet,
	linux-media, devicetree

Hi Mauro,

On Wed, 22 Jul 2015, Mauro Carvalho Chehab wrote:

> Em Wed, 24 Jun 2015 16:11:00 +0100
> Peter Griffin <peter.griffin@linaro.org> escreveu:
> 
> > This is used in conjunction with the STV0367 demodulator on
> > the STV0367-NIM-V1.0 NIM card which can be used with the STi
> > STB SoC's.
> > 
> > This tuner has a fifth register, so some changes have been made
> > to accommodate this.
> > 
> > Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
> > ---
> >  drivers/media/dvb-frontends/dvb-pll.c | 74 +++++++++++++++++++++++++++++------
> >  drivers/media/dvb-frontends/dvb-pll.h |  1 +
> >  2 files changed, 64 insertions(+), 11 deletions(-)
> > 
> > diff --git a/drivers/media/dvb-frontends/dvb-pll.c b/drivers/media/dvb-frontends/dvb-pll.c
> > index 6d8fe88..f7381c7 100644
> > --- a/drivers/media/dvb-frontends/dvb-pll.c
> > +++ b/drivers/media/dvb-frontends/dvb-pll.c
> > @@ -141,6 +141,35 @@ static struct dvb_pll_desc dvb_pll_thomson_dtt7520x = {
> >  	},
> >  };
> >  
> > +static void thomson_dtt7546x_bw(struct dvb_frontend *fe, u8 *buf)
> > +{
> > +	/* set CB2 reg - set ATC, XTO */
> > +	buf[4] = 0xc3;
> > +}
> > +
> > +static struct dvb_pll_desc dvb_pll_thomson_dtt7546x = {
> > +	.name  = "Thomson dtt7546x",
> > +	.min   = 44250000,
> > +	.max   = 863250000,
> > +	.set   = thomson_dtt7546x_bw,
> > +	.iffreq= 36166667,
> 
> Whitespace is missing. Please check the patchs with scripts/checkpatch.pl.

Will fix in V2.

regards,

Peter.

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

* Re: [PATCH 02/12] [media] dvb-pll: Add support for THOMSON DTT7546X tuner.
  2015-07-22 21:58     ` Mauro Carvalho Chehab
@ 2015-07-30  9:47       ` Peter Griffin
  2015-07-30 10:08         ` Joe Perches
  0 siblings, 1 reply; 32+ messages in thread
From: Peter Griffin @ 2015-07-30  9:47 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Joe Perches, linux-arm-kernel, linux-kernel, srinivas.kandagatla,
	maxime.coquelin, patrice.chotard, lee.jones, hugues.fruchet,
	linux-media, devicetree

Hi Mauro / Joe,

On Wed, 22 Jul 2015, Mauro Carvalho Chehab wrote:

> Em Wed, 24 Jun 2015 18:17:37 -0700
> Joe Perches <joe@perches.com> escreveu:
> 
> > On Wed, 2015-06-24 at 16:11 +0100, Peter Griffin wrote:
> > > This is used in conjunction with the STV0367 demodulator on
> > > the STV0367-NIM-V1.0 NIM card which can be used with the STi
> > > STB SoC's.
> > 
> > Barely associated to this specific patch, but for
> > dvb-pll.c, another thing that seems possible is to
> > convert the struct dvb_pll_desc uses to const and
> > change the "entries" fixed array size from 12 to []
> > 
> > It'd save a couple KB overall and remove ~5KB of data.
> > 
> > $ size drivers/media/dvb-frontends/dvb-pll.o*
> >    text	   data	    bss	    dec	    hex	filename
> >    8520	   1552	   2120	  12192	   2fa0	drivers/media/dvb-frontends/dvb-pll.o.new
> >    5624	   6363	   2120	  14107	   371b	drivers/media/dvb-frontends/dvb-pll.o.old
> 
> Peter,
> 
> Please add this patch on the next patch series you submit.

Ok will do, I've added this patch with a slightly updated commit message
to my series.

Joe - Can I add your signed-off-by?

regards,

Peter.

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

* Re: [PATCH 02/12] [media] dvb-pll: Add support for THOMSON DTT7546X tuner.
  2015-07-30  9:47       ` Peter Griffin
@ 2015-07-30 10:08         ` Joe Perches
  2015-07-30 11:14           ` Michael Ira Krufky
  0 siblings, 1 reply; 32+ messages in thread
From: Joe Perches @ 2015-07-30 10:08 UTC (permalink / raw)
  To: Peter Griffin
  Cc: Mauro Carvalho Chehab, linux-arm-kernel, linux-kernel,
	srinivas.kandagatla, maxime.coquelin, patrice.chotard, lee.jones,
	hugues.fruchet, linux-media, devicetree

On Thu, 2015-07-30 at 10:47 +0100, Peter Griffin wrote:
> Hi Mauro / Joe,
> 
> On Wed, 22 Jul 2015, Mauro Carvalho Chehab wrote:
> 
> > Em Wed, 24 Jun 2015 18:17:37 -0700
> > Joe Perches <joe@perches.com> escreveu:
> > 
> > > On Wed, 2015-06-24 at 16:11 +0100, Peter Griffin wrote:
> > > > This is used in conjunction with the STV0367 demodulator on
> > > > the STV0367-NIM-V1.0 NIM card which can be used with the STi
> > > > STB SoC's.
> > > 
> > > Barely associated to this specific patch, but for
> > > dvb-pll.c, another thing that seems possible is to
> > > convert the struct dvb_pll_desc uses to const and
> > > change the "entries" fixed array size from 12 to []
> > > 
> > > It'd save a couple KB overall and remove ~5KB of data.
> > > 
> > > $ size drivers/media/dvb-frontends/dvb-pll.o*
> > >    text	   data	    bss	    dec	    hex	filename
> > >    8520	   1552	   2120	  12192	   2fa0	drivers/media/dvb-frontends/dvb-pll.o.new
> > >    5624	   6363	   2120	  14107	   371b	drivers/media/dvb-frontends/dvb-pll.o.old
> > 
> > Peter,
> > 
> > Please add this patch on the next patch series you submit.
> 
> Ok will do, I've added this patch with a slightly updated commit message
> to my series.
> 
> Joe - Can I add your signed-off-by?

Signed-off-by: Joe Perches <joe@perches.com>


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

* Re: [PATCH 07/12] [media] tsin: c8sectpfe: STiH407/10 Linux DVB demux support
  2015-07-22 21:46   ` Mauro Carvalho Chehab
@ 2015-07-30 11:08     ` Peter Griffin
  0 siblings, 0 replies; 32+ messages in thread
From: Peter Griffin @ 2015-07-30 11:08 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: linux-arm-kernel, linux-kernel, srinivas.kandagatla,
	maxime.coquelin, patrice.chotard, lee.jones, hugues.fruchet,
	linux-media, devicetree

Hi Mauro,

Thanks for reviewing.

On Wed, 22 Jul 2015, Mauro Carvalho Chehab wrote:

> Em Wed, 24 Jun 2015 16:11:05 +0100
> Peter Griffin <peter.griffin@linaro.org> escreveu:
> 
> > This patch adds support for the c8sectpfe input HW found on
> > STiH407/410 SoC's.
> > 
> > It currently supports the TS input block, memdma engine
> > and hw PID filtering blocks of the C8SECTPFE subsystem.
> > 
> > The driver creates one LinuxDVB adapter, and a
> > demux/dvr/frontend set of devices for each tsin channel
> > which is specificed in the DT. It has been tested with
> > multiple tsin channels tuned, locked, and grabbing TS
> > simultaneously.
> > 
> > Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
> > ---
> >  drivers/media/tsin/c8sectpfe/c8sectpfe-core.c | 1105 +++++++++++++++++++++++++
> >  drivers/media/tsin/c8sectpfe/c8sectpfe-core.h |  288 +++++++
> >  2 files changed, 1393 insertions(+)
> >  create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-core.c
> >  create mode 100644 drivers/media/tsin/c8sectpfe/c8sectpfe-core.h
> > 
> > diff --git a/drivers/media/tsin/c8sectpfe/c8sectpfe-core.c b/drivers/media/tsin/c8sectpfe/c8sectpfe-core.c
> > new file mode 100644
> > index 0000000..fbbe323
> > --- /dev/null
> > +++ b/drivers/media/tsin/c8sectpfe/c8sectpfe-core.c
> > @@ -0,0 +1,1105 @@
> > +/*
> > + * c8sectpfe-core.c - C8SECTPFE STi DVB driver
> > + *
> > + * Copyright (c) STMicroelectronics 2015
> > + *
> > + *   Author:Peter Bennett <peter.bennett@st.com>
> > + *	    Peter Griffin <peter.griffin@linaro.org>
> > + *
> > + *	This program is free software; you can redistribute it and/or
> > + *	modify it under the terms of the GNU General Public License as
> > + *	published by the Free Software Foundation; either version 2 of
> > + *	the License, or (at your option) any later version.
> > + */
> > +#include <linux/clk.h>
> > +#include <linux/completion.h>
> > +#include <linux/delay.h>
> > +#include <linux/device.h>
> > +#include <linux/dma-mapping.h>
> > +#include <linux/dvb/dmx.h>
> > +#include <linux/dvb/frontend.h>
> > +#include <linux/errno.h>
> > +#include <linux/firmware.h>
> > +#include <linux/init.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/io.h>
> > +#include <linux/module.h>
> > +#include <linux/of_gpio.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/usb.h>
> > +#include <linux/slab.h>
> > +#include <linux/time.h>
> > +#include <linux/version.h>
> > +#include <linux/wait.h>
> > +
> > +#include "c8sectpfe-core.h"
> > +#include "c8sectpfe-common.h"
> > +#include "c8sectpfe-debugfs.h"
> > +#include "dmxdev.h"
> > +#include "dvb_demux.h"
> > +#include "dvb_frontend.h"
> > +#include "dvb_net.h"
> > +
> > +#define FIRMWARE_MEMDMA "pti_memdma_h407.elf"
> > +MODULE_FIRMWARE(FIRMWARE_MEMDMA);
> > +
> > +#define PID_TABLE_SIZE 1024
> > +#define POLL_20_HZ_DIV 20 /* poll at 20 Hz */
> > +
> > +static int load_slim_core_fw(struct c8sectpfei *fei);
> > +
> > +#define TS_PKT_SIZE 188
> > +#define HEADER_SIZE (4)
> > +#define PACKET_SIZE (TS_PKT_SIZE+HEADER_SIZE)
> > +
> > +#define FEI_ALIGNMENT (32)
> > +/* hw requires minimum of 8*PACKET_SIZE and padded to 8byte boundary */
> > +#define FEI_BUFFER_SIZE (8*PACKET_SIZE*340)
> > +
> > +#define FIFO_LEN 1024
> > +
> > +static void c8sectpfe_timer_interrupt(unsigned long ac8sectpfei)
> > +{
> > +	struct c8sectpfei *fei = (struct c8sectpfei *)ac8sectpfei;
> > +	struct channel_info *channel;
> > +	int chan_num;
> > +
> > +	/* iterate through input block channels */
> > +	for (chan_num = 0; chan_num < fei->tsin_count; chan_num++) {
> > +		channel = fei->channel_data[chan_num];
> > +
> > +		/* is this descriptor initialised and TP enabled */
> > +		if (channel->irec && readl((void __iomem *)
> > +						&channel->irec->tp_enable))
> > +			tasklet_schedule(&channel->tsklet);
> > +	}
> > +
> > +	fei->timer.expires = jiffies + (HZ / POLL_20_HZ_DIV);
> 
> Please use the macros for jiffies conversions. In this case, I guess
> you want to use ms_to_jiffies(), right?

Fixed in V2.

> 
> > +	add_timer(&fei->timer);
> > +}
> > +
> > +static void channel_swdemux_tsklet(unsigned long data)
> > +{
> > +	struct channel_info *channel = (struct channel_info *)data;
> > +	struct c8sectpfei *fei = channel->fei;
> > +	struct tpentry *ptrblk;
> > +	unsigned long wp, rp;
> > +	int pos, num_packets, n, size;
> > +	u8 *buf;
> > +
> > +	BUG_ON(!channel);
> > +	BUG_ON(!channel->irec);
> 
> Please avoid using BUG_ON() except when the machine will be on some
> unstable state. In this case, I guess you could just do:
> 
> 	if (unlikely(!channel || !channel->irec)
> 		return;

Yes ok, I have removed the BUG_ON's in v2

> 
> > +
> > +	ptrblk = &channel->irec->ptr_data[0];
> > +
> > +	wp = readl((void __iomem *)&ptrblk->dma_bus_wp);
> > +	rp = readl((void __iomem *)&ptrblk->dma_bus_rp);
> 
> Why do you need those typecasts? We try to avoid typecasts in the Kernel,
> doing it only where really needed. Same for other usages. You should
> probably declare those DMA buffers as __iomem *, and avoid the casts.

Ok, I've fixed this in V2.

> 
> > +
> > +	pos = rp - channel->back_buffer_busaddr;
> > +
> > +	/* has it wrapped */
> > +	if (wp < rp)
> > +		wp = channel->back_buffer_busaddr + FEI_BUFFER_SIZE;
> > +
> > +	size = wp - rp;
> > +	num_packets = size / PACKET_SIZE;
> > +
> > +	/* manage cache so data is visible to CPU */
> > +	dma_sync_single_for_cpu(fei->dev,
> > +				rp,
> > +				size,
> > +				DMA_FROM_DEVICE);
> > +
> > +	buf = (u8 *) channel->back_buffer_aligned;
> > +
> > +	dev_dbg(fei->dev,
> > +		"chan=%d channel=%p num_packets = %d, buf = %p, pos = 0x%x\n\t"
> > +		"rp=0x%lx, wp=0x%lx\n",
> > +		channel->tsin_id, channel, num_packets, buf, pos, rp, wp);
> > +
> > +	for (n = 0; n < num_packets; n++) {
> > +		dvb_dmx_swfilter_packets(
> > +			&fei->c8sectpfe[0]->
> > +				demux[channel->demux_mapping].dvb_demux,
> > +			&buf[pos], 1);
> > +
> > +		pos += PACKET_SIZE;
> > +	}
> 
> Hmm... why not call it, instead, without the loop, e. g.:
> 
> 	dvb_dmx_swfilter_packets(
> 		&fei->c8sectpfe[0]->
> 				demux[channel->demux_mapping].dvb_demux,
> 			&buf[pos], num_packets);

The InputBlock hardware outputs in multiples of 8 bytes, so we are actually
incrementing by 192 bytes in this loop, for each 188 byte TS packet.

These additional bytes can be used for timestamping TS packets on arrival
and then using this for clock recovery, although that isn't enabled atm.

I notice in dvb_demux.c you have a dvb_dmx_swfilter_204 as well as
dvb_dmx_swfilter, so we could maybe add a dvb_dmx_swfilter_192?

Although I thought this was most likely a ST specific thing, so didn't
change the core code, and handled it within the driver.

> 
> 
> > +
> > +	/* advance the read pointer */
> > +	if (wp == (channel->back_buffer_busaddr + FEI_BUFFER_SIZE))
> > +		writel(channel->back_buffer_busaddr,
> > +			(void __iomem *)&ptrblk->dma_bus_rp);
> > +	else
> > +		writel(wp, (void __iomem *)&ptrblk->dma_bus_rp);
> > +}
> > +
> > +static int c8sectpfe_start_feed(struct dvb_demux_feed *dvbdmxfeed)
> > +{
> > +	struct dvb_demux *demux = dvbdmxfeed->demux;
> > +	struct stdemux *stdemux = (struct stdemux *)demux->priv;
> > +	struct c8sectpfei *fei = stdemux->c8sectpfei;
> > +	struct channel_info *channel;
> > +	struct tpentry *ptrblk;
> > +	u32 tmp;
> > +	unsigned long *bitmap;
> > +
> > +	switch (dvbdmxfeed->type) {
> > +	case DMX_TYPE_TS:
> > +		break;
> > +	case DMX_TYPE_SEC:
> > +		break;
> > +	default:
> > +		dev_err(fei->dev, "%s:%d Error bailing\n"
> > +			, __func__, __LINE__);
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (dvbdmxfeed->type == DMX_TYPE_TS) {
> > +		switch (dvbdmxfeed->pes_type) {
> > +		case DMX_PES_VIDEO:
> > +		case DMX_PES_AUDIO:
> > +		case DMX_PES_TELETEXT:
> > +		case DMX_PES_PCR:
> > +		case DMX_PES_OTHER:
> > +			break;
> > +		default:
> > +			dev_err(fei->dev, "%s:%d Error bailing\n"
> > +				, __func__, __LINE__);
> > +			return -EINVAL;
> > +		}
> > +	}
> > +
> > +	mutex_lock(&fei->lock);
> > +
> > +	channel = fei->channel_data[stdemux->tsin_index];
> > +
> > +	bitmap = (unsigned long *) channel->pid_buffer_aligned;
> > +
> > +	bitmap_set(bitmap, dvbdmxfeed->pid, 1);
> > +
> > +	/* manage cache so PID bitmap is visible to HW */
> > +	dma_sync_single_for_device(fei->dev,
> > +					channel->pid_buffer_busaddr,
> > +					PID_TABLE_SIZE,
> > +					DMA_TO_DEVICE);
> > +
> > +	channel->active = 1;
> > +
> > +	if (fei->global_feed_count == 0) {
> > +		fei->timer.expires = jiffies + (HZ / POLL_20_HZ_DIV);
> 
> Please use ms_to_jiffies().

Fixed in v2.

> 
> > +		add_timer(&fei->timer);
> > +	}
> > +
> > +	if (stdemux->running_feed_count == 0) {
> > +
> > +		dev_dbg(fei->dev, "Starting channel=%p\n", channel);
> > +
> > +		tasklet_init(&channel->tsklet, channel_swdemux_tsklet,
> > +			     (unsigned long) channel);
> > +
> > +		/* Reset the internal inputblock sram pointers */
> > +		writel(channel->fifo,
> > +			fei->io + C8SECTPFE_IB_BUFF_STRT(channel->tsin_id));
> > +		writel(channel->fifo + FIFO_LEN - 1,
> > +			fei->io + C8SECTPFE_IB_BUFF_END(channel->tsin_id));
> > +
> > +		writel(channel->fifo,
> > +			fei->io + C8SECTPFE_IB_READ_PNT(channel->tsin_id));
> > +		writel(channel->fifo,
> > +			fei->io + C8SECTPFE_IB_WRT_PNT(channel->tsin_id));
> > +
> > +
> > +		/* reset read / write memdma ptrs for this channel */
> > +		ptrblk = &channel->irec->ptr_data[0];
> > +		writel(channel->back_buffer_busaddr,
> > +			(void __iomem *)&ptrblk->dma_busbase);
> > +
> > +		tmp = channel->back_buffer_busaddr + FEI_BUFFER_SIZE - 1;
> > +		writel(tmp, (void __iomem *)&ptrblk->dma_bustop);
> > +
> > +		writel(channel->back_buffer_busaddr,
> > +			(void __iomem *)&ptrblk->dma_bus_wp);
> > +
> > +		/* Issue a reset and enable InputBlock */
> > +		writel(C8SECTPFE_SYS_ENABLE | C8SECTPFE_SYS_RESET
> > +			, fei->io + C8SECTPFE_IB_SYS(channel->tsin_id));
> > +
> > +		/* and enable the tp */
> > +		writel(0x1, (void __iomem *)&channel->irec->tp_enable);
> > +
> > +		dev_dbg(fei->dev, "%s:%d Starting DMA feed on stdemux=%p\n"
> > +			, __func__, __LINE__, stdemux);
> > +	}
> > +
> > +	stdemux->running_feed_count++;
> > +	fei->global_feed_count++;
> > +
> > +	mutex_unlock(&fei->lock);
> > +
> > +	return 0;
> > +}
> > +
> > +static int c8sectpfe_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
> > +{
> > +
> > +	struct dvb_demux *demux = dvbdmxfeed->demux;
> > +	struct stdemux *stdemux = (struct stdemux *)demux->priv;
> > +	struct c8sectpfei *fei = stdemux->c8sectpfei;
> > +	struct channel_info *channel;
> > +	struct tpentry *ptrblk;
> > +	int idlereq;
> > +	u32 tmp;
> > +	int ret;
> > +	unsigned long *bitmap;
> > +
> > +	mutex_lock(&fei->lock);
> > +
> > +	channel = fei->channel_data[stdemux->tsin_index];
> > +
> > +	bitmap = (unsigned long *) channel->pid_buffer_aligned;
> > +	bitmap_clear(bitmap, dvbdmxfeed->pid, 1);
> > +
> > +	/* manage cache so data is visible to HW */
> > +	dma_sync_single_for_device(fei->dev,
> > +					channel->pid_buffer_busaddr,
> > +					PID_TABLE_SIZE,
> > +					DMA_TO_DEVICE);
> > +
> > +	if (--stdemux->running_feed_count == 0) {
> > +
> > +		channel = fei->channel_data[stdemux->tsin_index];
> > +		ptrblk = &channel->irec->ptr_data[0];
> > +
> > +		/* TP re-configuration on page 168 */
> 
> Page 168 of what?

functional spec. I've updated the comment in V2.

> 
> > +
> > +		/* disable IB (prevents more TS data going to memdma) */
> > +		writel(0, fei->io + C8SECTPFE_IB_SYS(channel->tsin_id));
> > +
> > +		/* disable this channels descriptor */
> > +		writel(0, (void __iomem *)&channel->irec->tp_enable);
> > +
> > +		tasklet_disable(&channel->tsklet);
> > +
> > +		/* now request memdma channel goes idle */
> > +		idlereq = (1 << channel->tsin_id) | IDLEREQ;
> > +		writel(idlereq, fei->io + DMA_IDLE_REQ);
> > +
> > +		/* wait for idle irq handler to signal completion */
> > +		ret = wait_for_completion_timeout(&channel->idle_completion,
> > +						msecs_to_jiffies(100));
> > +
> > +		if (ret == 0)
> > +			dev_warn(fei->dev,
> > +				"Timeout waiting for idle irq on tsin%d\n",
> > +				channel->tsin_id);
> > +
> > +		reinit_completion(&channel->idle_completion);
> > +
> > +		/* reset read / write ptrs for this channel */
> > +		writel(channel->back_buffer_busaddr,
> > +			(void __iomem *)&ptrblk->dma_busbase);
> > +
> > +		tmp = channel->back_buffer_busaddr + FEI_BUFFER_SIZE - 1;
> > +		writel(tmp, (void __iomem *)&ptrblk->dma_bustop);
> > +
> > +		writel(channel->back_buffer_busaddr,
> > +			(void __iomem *)&ptrblk->dma_bus_wp);
> > +
> > +		dev_dbg(fei->dev,
> > +			"%s:%d stopping DMA feed on stdemux=%p channel=%d\n",
> > +			__func__, __LINE__, stdemux, channel->tsin_id);
> > +
> > +		/* turn off all PIDS in the bitmap*/
> > +		memset((void *)channel->pid_buffer_aligned
> > +			, 0x00, PID_TABLE_SIZE);
> > +
> > +		/* manage cache so data is visible to HW */
> > +		dma_sync_single_for_device(fei->dev,
> > +					channel->pid_buffer_busaddr,
> > +					PID_TABLE_SIZE,
> > +					DMA_TO_DEVICE);
> > +
> > +		channel->active = 0;
> > +	}
> > +
> > +	if (--fei->global_feed_count == 0) {
> > +		dev_dbg(fei->dev, "%s:%d global_feed_count=%d\n"
> > +			, __func__, __LINE__, fei->global_feed_count);
> > +
> > +		del_timer(&fei->timer);
> > +	}
> > +
> > +	mutex_unlock(&fei->lock);
> > +
> > +	return 0;
> > +}
> > +
> > +static struct channel_info *find_channel(struct c8sectpfei *fei, int tsin_num)
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < C8SECTPFE_MAXCHANNEL; i++) {
> > +		if (!fei->channel_data[i])
> > +			continue;
> > +
> > +		if (fei->channel_data[i]->tsin_id == tsin_num)
> > +			return fei->channel_data[i];
> > +	}
> > +
> > +	return NULL;
> > +}
> > +
> > +static void c8sectpfe_getconfig(struct c8sectpfei *fei)
> > +{
> > +	struct c8sectpfe_hw *hw = &fei->hw_stats;
> > +
> > +	hw->num_ib = readl(fei->io + SYS_CFG_NUM_IB);
> > +	hw->num_mib = readl(fei->io + SYS_CFG_NUM_MIB);
> > +	hw->num_swts = readl(fei->io + SYS_CFG_NUM_SWTS);
> > +	hw->num_tsout = readl(fei->io + SYS_CFG_NUM_TSOUT);
> > +	hw->num_ccsc = readl(fei->io + SYS_CFG_NUM_CCSC);
> > +	hw->num_ram = readl(fei->io + SYS_CFG_NUM_RAM);
> > +	hw->num_tp = readl(fei->io + SYS_CFG_NUM_TP);
> > +
> > +	dev_info(fei->dev, "C8SECTPFE hw supports the following:\n");
> > +	dev_info(fei->dev, "Input Blocks: %d\n", hw->num_ib);
> > +	dev_info(fei->dev, "Merged Input Blocks: %d\n", hw->num_mib);
> > +	dev_info(fei->dev, "Software Transport Stream Inputs: %d\n"
> > +				, hw->num_swts);
> > +	dev_info(fei->dev, "Transport Stream Output: %d\n", hw->num_tsout);
> > +	dev_info(fei->dev, "Cable Card Converter: %d\n", hw->num_ccsc);
> > +	dev_info(fei->dev, "RAMs supported by C8SECTPFE: %d\n", hw->num_ram);
> > +	dev_info(fei->dev, "Tango TPs supported by C8SECTPFE: %d\n"
> > +			, hw->num_tp);
> > +}
> > +
> > +static irqreturn_t c8sectpfe_idle_irq_handler(int irq, void *priv)
> > +{
> > +	struct c8sectpfei *fei = priv;
> > +	struct channel_info *chan;
> > +	int bit;
> > +	unsigned long tmp = readl(fei->io + DMA_IDLE_REQ);
> > +
> > +	/* page 168 of functional spec: Clear the idle request
> > +	   by writing 0 to the C8SECTPFE_DMA_IDLE_REQ register. */
> > +
> > +	/* signal idle completion */
> > +	for_each_set_bit(bit, &tmp, fei->hw_stats.num_ib) {
> > +
> > +		chan = find_channel(fei, bit);
> > +
> > +		if (chan)
> > +			complete(&chan->idle_completion);
> > +	}
> > +
> > +	writel(0, fei->io + DMA_IDLE_REQ);
> > +
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +
> > +static void free_input_block(struct c8sectpfei *fei, struct channel_info *tsin)
> > +{
> > +	BUG_ON(!fei);
> > +	BUG_ON(!tsin);
> 
> Again, BUG_ON() don't make much sense here. Just return if those vars are
> NULL.

I've removed the BUG_ON in V2

> 
> > +
> > +	if (tsin->back_buffer_busaddr)
> > +		if (!dma_mapping_error(fei->dev, tsin->back_buffer_busaddr))
> > +			dma_unmap_single(fei->dev, tsin->back_buffer_busaddr,
> > +				FEI_BUFFER_SIZE, DMA_BIDIRECTIONAL);
> > +
> > +	kfree(tsin->back_buffer_start);
> > +
> > +	if (tsin->pid_buffer_busaddr)
> > +		if (!dma_mapping_error(fei->dev, tsin->pid_buffer_busaddr))
> > +			dma_unmap_single(fei->dev, tsin->pid_buffer_busaddr,
> > +				PID_TABLE_SIZE, DMA_BIDIRECTIONAL);
> > +
> > +	kfree(tsin->pid_buffer_start);
> > +}
> > +
> > +#define MAX_NAME 20
> > +
> > +static int configure_input_block(struct c8sectpfei *fei,
> > +				struct channel_info *tsin)
> > +{
> > +	int ret;
> > +	u32 tmp = 0;
> > +	struct tpentry *ptrblk;
> > +	char tsin_pin_name[MAX_NAME];
> > +
> > +	BUG_ON(!fei);
> > +	BUG_ON(!tsin);
> 
> Same here: BUG_ON() seems too severe.

Removed in V2.

> 
> > +
> > +	dev_dbg(fei->dev, "%s:%d Configuring channel=%p tsin=%d\n"
> > +		, __func__, __LINE__, tsin, tsin->tsin_id);
> > +
> > +	init_completion(&tsin->idle_completion);
> > +
> > +	tsin->back_buffer_start = kzalloc(FEI_BUFFER_SIZE +
> > +					FEI_ALIGNMENT, GFP_KERNEL);
> > +
> > +	if (!tsin->back_buffer_start) {
> > +		ret = -ENOMEM;
> > +		goto err_unmap;
> > +	}
> > +
> > +	/* Ensure backbuffer is 32byte aligned */
> > +	tsin->back_buffer_aligned = tsin->back_buffer_start
> > +		+ FEI_ALIGNMENT;
> > +
> > +	tsin->back_buffer_aligned = (void *)
> > +		(((uintptr_t) tsin->back_buffer_aligned) & ~0x1F);
> > +
> > +	tsin->back_buffer_busaddr = dma_map_single(fei->dev,
> > +					(void *)tsin->back_buffer_aligned,
> > +					FEI_BUFFER_SIZE,
> > +					DMA_BIDIRECTIONAL);
> > +
> > +	if (dma_mapping_error(fei->dev, tsin->back_buffer_busaddr)) {
> > +		dev_err(fei->dev, "failed to map back_buffer\n");
> > +		ret = -EFAULT;
> > +		goto err_unmap;
> > +	}
> > +
> > +	/*
> > +	 * The pid buffer can be configured (in hw) for byte or bit
> > +	 * per pid. By powers of deduction we conclude stih407 family
> > +	 * is configured (at SoC design stage) for bit per pid.
> > +	 */
> > +	tsin->pid_buffer_start = kzalloc(2048, GFP_KERNEL);
> > +
> > +	if (!tsin->pid_buffer_start) {
> > +		ret = -ENOMEM;
> > +		goto err_unmap;
> > +	}
> > +
> > +	/*
> > +	 * PID buffer needs to be aligned to size of the pid table
> > +	 * which at bit per pid is 1024 bytes (8192 pids / 8).
> > +	 * PIDF_BASE register enforces this alignment when writing
> > +	 * the register.
> > +	 */
> > +
> > +	tsin->pid_buffer_aligned = tsin->pid_buffer_start +
> > +		PID_TABLE_SIZE;
> > +
> > +	tsin->pid_buffer_aligned = (void *)
> > +		(((uintptr_t) tsin->pid_buffer_aligned) & ~0x3ff);
> > +
> > +	tsin->pid_buffer_busaddr = dma_map_single(fei->dev,
> > +						tsin->pid_buffer_aligned,
> > +						PID_TABLE_SIZE,
> > +						DMA_BIDIRECTIONAL);
> > +
> > +	if (dma_mapping_error(fei->dev, tsin->pid_buffer_busaddr)) {
> > +		dev_err(fei->dev, "failed to map pid_bitmap\n");
> > +		ret = -EFAULT;
> > +		goto err_unmap;
> > +	}
> > +
> > +	/* manage cache so pid bitmap is visible to HW */
> > +	dma_sync_single_for_device(fei->dev,
> > +				tsin->pid_buffer_busaddr,
> > +				PID_TABLE_SIZE,
> > +				DMA_TO_DEVICE);
> > +
> > +	snprintf(tsin_pin_name, MAX_NAME, "tsin%d-%s", tsin->tsin_id,
> > +		(tsin->serial_not_parallel ? "serial" : "parallel"));
> > +
> > +	tsin->pstate = pinctrl_lookup_state(fei->pinctrl, tsin_pin_name);
> > +	if (IS_ERR(tsin->pstate)) {
> > +		dev_err(fei->dev, "%s: pinctrl_lookup_state couldn't find %s state\n"
> > +			, __func__, tsin_pin_name);
> > +		ret = PTR_ERR(tsin->pstate);
> > +		goto err_unmap;
> > +	}
> > +
> > +	ret = pinctrl_select_state(fei->pinctrl, tsin->pstate);
> > +
> > +	if (ret) {
> > +		dev_err(fei->dev, "%s: pinctrl_select_state failed\n"
> > +			, __func__);
> > +		goto err_unmap;
> > +	}
> > +
> > +	/* Enable this input block */
> > +	tmp = readl(fei->io + SYS_INPUT_CLKEN);
> > +	tmp |= BIT(tsin->tsin_id);
> > +	writel(tmp, fei->io + SYS_INPUT_CLKEN);
> > +
> > +	if (tsin->serial_not_parallel)
> > +		tmp |= C8SECTPFE_SERIAL_NOT_PARALLEL;
> > +
> > +	if (tsin->invert_ts_clk)
> > +		tmp |= C8SECTPFE_INVERT_TSCLK;
> > +
> > +	if (tsin->async_not_sync)
> > +		tmp |= C8SECTPFE_ASYNC_NOT_SYNC;
> > +
> > +	tmp |= C8SECTPFE_ALIGN_BYTE_SOP | C8SECTPFE_BYTE_ENDIANNESS_MSB;
> > +
> > +	writel(tmp, fei->io + C8SECTPFE_IB_IP_FMT_CFG(tsin->tsin_id));
> > +
> > +	writel(C8SECTPFE_SYNC(0x9) |
> > +		C8SECTPFE_DROP(0x9) |
> > +		C8SECTPFE_TOKEN(0x47),
> > +		fei->io + C8SECTPFE_IB_SYNCLCKDRP_CFG(tsin->tsin_id));
> > +
> > +	writel(TS_PKT_SIZE, fei->io + C8SECTPFE_IB_PKT_LEN(tsin->tsin_id));
> > +
> > +	/* Place the FIFO's at the end of the irec descriptors */
> > +
> > +	tsin->fifo = (tsin->tsin_id * FIFO_LEN);
> > +
> > +	writel(tsin->fifo, fei->io + C8SECTPFE_IB_BUFF_STRT(tsin->tsin_id));
> > +	writel(tsin->fifo + FIFO_LEN - 1,
> > +		fei->io + C8SECTPFE_IB_BUFF_END(tsin->tsin_id));
> > +
> > +	writel(tsin->fifo, fei->io + C8SECTPFE_IB_READ_PNT(tsin->tsin_id));
> > +	writel(tsin->fifo, fei->io + C8SECTPFE_IB_WRT_PNT(tsin->tsin_id));
> > +
> > +	writel(tsin->pid_buffer_busaddr,
> > +		fei->io + PIDF_BASE(tsin->tsin_id));
> > +
> > +	dev_dbg(fei->dev, "chan=%d PIDF_BASE=0x%x pid_bus_addr=0x%x\n",
> > +		tsin->tsin_id, readl(fei->io + PIDF_BASE(tsin->tsin_id)),
> > +		tsin->pid_buffer_busaddr);
> > +
> > +	/* Configure and enable HW PID filtering */
> > +
> > +	/*
> > +	 * The PID value is created by assembling the first 8 bytes of
> > +	 * the TS packet into a 64-bit word in big-endian format. A
> > +	 * slice of that 64-bit word is taken from
> > +	 * (PID_OFFSET+PID_NUM_BITS-1) to PID_OFFSET.
> > +	 */
> > +	tmp = (C8SECTPFE_PID_ENABLE | C8SECTPFE_PID_NUMBITS(13)
> > +		| C8SECTPFE_PID_OFFSET(40));
> > +
> > +	writel(tmp, fei->io + C8SECTPFE_IB_PID_SET(tsin->tsin_id));
> > +
> > +	dev_dbg(fei->dev, "chan=%d setting wp: %d, rp: %d, buf: %d-%d\n",
> > +		tsin->tsin_id,
> > +		readl(fei->io + C8SECTPFE_IB_WRT_PNT(tsin->tsin_id)),
> > +		readl(fei->io + C8SECTPFE_IB_READ_PNT(tsin->tsin_id)),
> > +		readl(fei->io + C8SECTPFE_IB_BUFF_STRT(tsin->tsin_id)),
> > +		readl(fei->io + C8SECTPFE_IB_BUFF_END(tsin->tsin_id)));
> > +
> > +	/*
> > +	 * Base address of pointer record block relative to
> > +	 * base address of DMEM
> > +	 */
> > +	fei->irec = fei->io + DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET +
> > +			readl(fei->io + DMA_PTRREC_BASE);
> > +
> > +	tsin->irec = fei->irec += tsin->tsin_id;
> > +
> > +	ptrblk = &tsin->irec->ptr_data[0];
> > +
> > +	writel(tsin->fifo,
> > +		(void __iomem *)&tsin->irec->dma_membase);
> > +
> > +	writel(tsin->fifo + FIFO_LEN - 1,
> > +		(void __iomem *)&tsin->irec->dma_memtop);
> > +
> > +	writel((188 + 7)&~7,
> > +		(void __iomem *)&tsin->irec->dma_ts_pktsize);
> > +
> > +	writel(0x1, (void __iomem *)&tsin->irec->tp_enable);
> > +
> > +	/* read/write pointers with physical bus address */
> > +	writel(tsin->back_buffer_busaddr,
> > +		(void __iomem *)&ptrblk->dma_busbase);
> > +
> > +	tmp = tsin->back_buffer_busaddr + FEI_BUFFER_SIZE - 1;
> > +	writel(tmp, (void __iomem *)&ptrblk->dma_bustop);
> > +
> > +	writel(tsin->back_buffer_busaddr,
> > +		(void __iomem *)&ptrblk->dma_bus_wp);
> > +
> > +	writel(tsin->back_buffer_busaddr,
> > +		(void __iomem *)&ptrblk->dma_bus_rp);
> > +
> > +	/* initialize tasklet */
> > +	tasklet_init(&tsin->tsklet, channel_swdemux_tsklet,
> > +		(unsigned long) tsin);
> > +
> > +	return 0;
> > +
> > +err_unmap:
> > +	free_input_block(fei, tsin);
> > +	return ret;
> > +}
> > +
> > +static irqreturn_t c8sectpfe_error_irq_handler(int irq, void *priv)
> > +{
> > +	struct c8sectpfei *fei = priv;
> > +
> > +	dev_err(fei->dev, "%s: error handling not yet implemented\n"
> > +		, __func__);
> > +
> > +	/*
> > +	 * TODO FIXME we should detect some error conditions here
> > +	 * and ideally so something about them!
> > +	 */
> > +
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +static int c8sectpfe_probe(struct platform_device *pdev)
> > +{
> > +	struct device *dev = &pdev->dev;
> > +	struct device_node *child, *np = dev->of_node;
> > +	struct c8sectpfei *fei;
> > +	struct resource *res;
> > +	int ret, n;
> > +	struct channel_info *tsin;
> > +
> > +	/* Allocate the c8sectpfei structure */
> > +	fei = devm_kzalloc(dev, sizeof(struct c8sectpfei), GFP_KERNEL);
> > +	if (!fei)
> > +		return -ENOMEM;
> > +
> > +	fei->dev = dev;
> > +
> > +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "c8sectpfe");
> > +	fei->io = devm_ioremap_resource(dev, res);
> > +	if (IS_ERR(fei->io))
> > +		return PTR_ERR(fei->io);
> > +
> > +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> > +					"c8sectpfe-ram");
> > +	fei->sram = devm_ioremap_resource(dev, res);
> > +	if (IS_ERR(fei->sram))
> > +		return PTR_ERR(fei->sram);
> > +
> > +	fei->sram_size = res->end - res->start;
> > +
> > +	fei->idle_irq = platform_get_irq_byname(pdev, "c8sectpfe-idle-irq");
> > +	if (fei->idle_irq < 0) {
> > +		dev_err(dev, "Can't get c8sectpfe-idle-irq\n");
> > +		return fei->idle_irq;
> > +	}
> > +
> > +	fei->error_irq = platform_get_irq_byname(pdev, "c8sectpfe-error-irq");
> > +	if (fei->error_irq < 0) {
> > +		dev_err(dev, "Can't get c8sectpfe-error-irq\n");
> > +		return fei->error_irq;
> > +	}
> > +
> > +	platform_set_drvdata(pdev, fei);
> > +
> > +	fei->c8sectpfeclk = devm_clk_get(dev, "c8sectpfe");
> > +	if (IS_ERR(fei->c8sectpfeclk)) {
> > +		dev_err(dev, "c8sectpfe clk not found\n");
> > +		return PTR_ERR(fei->c8sectpfeclk);
> > +	}
> > +
> > +	ret = clk_prepare_enable(fei->c8sectpfeclk);
> > +	if (ret) {
> > +		dev_err(dev, "Failed to enable c8sectpfe clock\n");
> > +		return ret;
> > +	}
> > +
> > +	/* to save power disable all IP's (on by default) */
> > +	writel(0, fei->io + SYS_INPUT_CLKEN);
> > +
> > +	/* Enable memdma clock */
> > +	writel(MEMDMAENABLE, fei->io + SYS_OTHER_CLKEN);
> > +
> > +	/* clear internal sram */
> > +	memset_io(fei->sram, 0x0, fei->sram_size);
> > +
> > +	c8sectpfe_getconfig(fei);
> > +
> > +	ret = load_slim_core_fw(fei);
> > +	if (ret) {
> > +		dev_err(dev, "Couldn't load slim core firmware\n");
> > +		goto err_clk_disable;
> > +	}
> > +
> > +	ret = devm_request_irq(dev, fei->idle_irq, c8sectpfe_idle_irq_handler,
> > +			0, "c8sectpfe-idle-irq", fei);
> > +	if (ret) {
> > +		dev_err(dev, "Can't register c8sectpfe-idle-irq IRQ.\n");
> > +		goto err_clk_disable;
> > +	}
> > +
> > +	ret = devm_request_irq(dev, fei->error_irq,
> > +				c8sectpfe_error_irq_handler, 0,
> > +				"c8sectpfe-error-irq", fei);
> > +	if (ret) {
> > +		dev_err(dev, "Can't register c8sectpfe-error-irq IRQ.\n");
> > +		goto err_clk_disable;
> > +	}
> > +
> > +	fei->tsin_count = of_get_child_count(np);
> > +
> > +	if (fei->tsin_count > C8SECTPFE_MAX_TSIN_CHAN ||
> > +		fei->tsin_count > fei->hw_stats.num_ib) {
> > +
> > +		dev_err(dev, "More tsin declared than exist on SoC!\n");
> > +		ret = -EINVAL;
> > +		goto err_clk_disable;
> > +	}
> > +
> > +	fei->pinctrl = devm_pinctrl_get(dev);
> > +
> > +	if (IS_ERR(fei->pinctrl)) {
> > +		dev_err(dev, "Error getting tsin pins\n");
> > +		ret = PTR_ERR(fei->pinctrl);
> > +		goto err_clk_disable;
> > +	}
> > +
> > +	n = 0;
> > +	for_each_child_of_node(np, child) {
> > +		struct device_node *i2c_bus;
> > +
> > +		fei->channel_data[n] = devm_kzalloc(dev,
> > +						sizeof(struct channel_info),
> > +						GFP_KERNEL);
> > +
> > +		if (!fei->channel_data[n]) {
> > +			ret = -ENOMEM;
> > +			goto err_clk_disable;
> > +		}
> > +
> > +		tsin = fei->channel_data[n];
> > +
> > +		tsin->fei = fei;
> > +
> > +		ret = of_property_read_u32(child, "tsin-num", &tsin->tsin_id);
> > +		if (ret) {
> > +			dev_err(&pdev->dev, "No tsin_num found\n");
> > +			goto err_clk_disable;
> > +		}
> > +
> > +		/* sanity check value */
> > +		if (tsin->tsin_id > fei->hw_stats.num_ib) {
> > +			dev_err(&pdev->dev,
> > +				"tsin-num %d specified greater than number\n\t"
> > +				"of input block hw in SoC! (%d)",
> > +				tsin->tsin_id, fei->hw_stats.num_ib);
> > +			ret = -EINVAL;
> > +			goto err_clk_disable;
> > +		}
> > +
> > +		tsin->invert_ts_clk = of_property_read_bool(child,
> > +							"invert-ts-clk");
> > +
> > +		tsin->serial_not_parallel = of_property_read_bool(child,
> > +							"serial-not-parallel");
> > +
> > +		tsin->async_not_sync = of_property_read_bool(child,
> > +							"async-not-sync");
> > +
> > +		ret = of_property_read_u32(child, "dvb-card",
> > +					&tsin->dvb_card);
> > +		if (ret) {
> > +			dev_err(&pdev->dev, "No dvb-card found\n");
> > +			goto err_clk_disable;
> > +		}
> > +
> > +		i2c_bus = of_parse_phandle(child, "i2c-bus", 0);
> > +		if (!i2c_bus) {
> > +			dev_err(&pdev->dev, "No i2c-bus found\n");
> > +			goto err_clk_disable;
> > +		}
> > +		tsin->i2c_adapter =
> > +			of_find_i2c_adapter_by_node(i2c_bus);
> > +		if (!tsin->i2c_adapter) {
> > +			dev_err(&pdev->dev, "No i2c adapter found\n");
> > +			of_node_put(i2c_bus);
> > +			goto err_clk_disable;
> > +		}
> > +		of_node_put(i2c_bus);
> > +
> > +		tsin->rst_gpio = of_get_named_gpio(child, "rst-gpio", 0);
> > +
> > +		ret = gpio_is_valid(tsin->rst_gpio);
> > +		if (!ret) {
> > +			dev_err(dev,
> > +				"reset gpio for tsin%d not valid (gpio=%d)\n",
> > +				tsin->tsin_id, tsin->rst_gpio);
> > +			goto err_clk_disable;
> > +		}
> > +
> > +		ret = devm_gpio_request_one(dev, tsin->rst_gpio,
> > +					GPIOF_OUT_INIT_LOW, "NIM reset");
> > +		if (ret && ret != -EBUSY) {
> > +			dev_err(dev, "Can't request tsin%d reset gpio\n"
> > +				, fei->channel_data[n]->tsin_id);
> > +			goto err_clk_disable;
> > +		}
> > +
> > +		if (!ret) {
> > +			/* toggle reset lines */
> > +			gpio_direction_output(tsin->rst_gpio, 0);
> > +			msleep(1);
> > +			gpio_direction_output(tsin->rst_gpio, 1);
> > +			msleep(1);
> 
> WARNING: msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt
> 
> msleep(1) doesn't work nice, as it may sleep up to 20 ms, depending on
> how HZ is configured. Is that what you want?

Umm. ok I've updated it in v2 to use: -

usleep_range(3500, 5000);

This code is toggling the reset line to the demod. Checking the stv900 demod datasheet
it should be asserted for at least 3ms. The STV0367 demod doesn't specify any
timings in the datasheet.
> 
> > +		}
> > +
> > +		tsin->demux_mapping = n;
> > +
> > +		dev_dbg(fei->dev,
> > +			"channel=%p n=%d tsin_num=%d, invert-ts-clk=%d\n\t"
> > +			"serial-not-parallel=%d pkt-clk-valid=%d dvb-card=%d\n",
> > +			fei->channel_data[n], n,
> > +			tsin->tsin_id, tsin->invert_ts_clk,
> > +			tsin->serial_not_parallel, tsin->async_not_sync,
> > +			tsin->dvb_card);
> > +
> > +		ret = configure_input_block(fei, fei->channel_data[n]);
> > +
> > +		if (ret) {
> > +			dev_err(fei->dev,
> > +				"configure_input_block tsin=%d failed\n",
> > +				fei->channel_data[n]->tsin_id);
> > +			goto err_unmap;
> > +		}
> > +
> > +		n++;
> > +	}
> > +
> > +	/* Setup timer interrupt */
> > +	init_timer(&fei->timer);
> > +	fei->timer.function = c8sectpfe_timer_interrupt;
> > +	fei->timer.data = (unsigned long)fei;
> > +
> > +	mutex_init(&fei->lock);
> > +
> > +	/* Get the configuration information about the tuners */
> > +	ret = c8sectpfe_tuner_register_frontend(&fei->c8sectpfe[0],
> > +					(void *)fei,
> > +					c8sectpfe_start_feed,
> > +					c8sectpfe_stop_feed);
> > +	if (ret)
> > +		goto err_unmap;
> > +
> > +	/*
> > +	 * STBus target port can access IMEM and DMEM ports
> > +	 * without waiting for CPU
> > +	 */
> > +	writel(0x1, fei->io + DMA_PER_STBUS_SYNC);
> > +
> > +	dev_info(dev, "Boot the memdma SLIM core\n");
> > +	writel(0x1,  fei->io + DMA_CPU_RUN);
> > +
> > +	c8sectpfe_debugfs_init(fei);
> > +
> > +	return 0;
> > +
> > +err_unmap:
> > +	for (n = 0; n < fei->tsin_count; n++) {
> > +		tsin = fei->channel_data[n];
> > +
> > +		if (tsin)
> > +			free_input_block(fei, tsin);
> > +	}
> > +
> > +err_clk_disable:
> > +	/* TODO uncomment when upstream has taken a reference on this clk */
> > +	/*clk_disable_unprepare(fei->c8sectpfeclk);*/
> 
> Hmm... what's the above? Why is it commented?

The STFE clock has a peculiar property in that once it has been enabled,
it can't be turned off, otherwise it causes the stih407/10 SoC to hang.

Currently this platform is waiting for Lees critical clocks series here: -
https://lkml.org/lkml/2015/7/22/311
to be merged, so the STFE clock can be marked as critical. Once that is
in place, this clk_disable can be uncommented.

I consider this a silicon bug which will hopefully be fixed, so
wish to keep the knowledge of this clock bug away from the c8sectpfe driver
and have the driver issue balanced enable/disable calls. However this
can't happen until the above series is merged, as the system will hang
when you remove the module, or if probe fails.

Another temp workaround would be to issue clk_prepare_enable twice, and
uncomment the disables (if you prefer that to what I have currently).

> 
> > +	return ret;
> > +}
> > +
> > +static int c8sectpfe_remove(struct platform_device *pdev)
> > +{
> > +	struct c8sectpfei *fei = platform_get_drvdata(pdev);
> > +	struct channel_info *channel;
> > +	unsigned int n;
> > +
> > +	c8sectpfe_tuner_unregister_frontend(fei->c8sectpfe[0], fei);
> > +
> > +	/*
> > +	 * Now loop through and un-configure each of the InputBlock resources
> > +	 */
> > +	for (n = 0; n < fei->tsin_count; n++) {
> > +		channel = fei->channel_data[n];
> > +		if (channel)
> > +			free_input_block(fei, channel);
> > +	}
> > +
> > +	c8sectpfe_debugfs_exit(fei);
> > +
> > +	dev_info(fei->dev, "Stopping memdma SLIM core\n");
> > +	if (readl(fei->io + DMA_CPU_RUN))
> > +		writel(0x0,  fei->io + DMA_CPU_RUN);
> > +
> > +	/* unclock all internal IP's */
> > +	if (readl(fei->io + SYS_INPUT_CLKEN))
> > +		writel(0, fei->io + SYS_INPUT_CLKEN);
> > +	if (readl(fei->io + SYS_OTHER_CLKEN))
> > +		writel(0, fei->io + SYS_OTHER_CLKEN);
> > +
> > +	/* TODO uncomment when upstream has taken a reference on this clk */
> > +	/*
> > +	if (fei->c8sectpfeclk)
> > +		clk_disable_unprepare(fei->c8sectpfeclk);
> > +	*/
> 
> Hmm... what's the above? Why is it commented?

See comment above about this being a critical clock on stih407/10.

> 
> > +
> > +	return 0;
> > +}
> > +
> > +static int load_slim_core_fw(struct c8sectpfei *fei)
> > +{
> > +	const struct firmware *fw = NULL;
> > +	unsigned char *pImem = NULL;
> > +	unsigned char *pDmem = NULL;
> > +	Elf32_Ehdr *ehdr;
> > +	Elf32_Phdr *phdr;
> > +	int err = 0;
> > +	int i;
> > +
> > +	dev_info(fei->dev, "Loading firmware: %s\n", FIRMWARE_MEMDMA);
> > +
> > +	err = request_firmware(&fw, FIRMWARE_MEMDMA, fei->dev);
> > +	if (err) {
> > +		dev_err(fei->dev, "Failed to load %s, %d.\n",
> > +			FIRMWARE_MEMDMA, err);
> > +		return -EINVAL;
> > +	}
> > +
> > +	/* Check ELF magic */
> > +	ehdr = (Elf32_Ehdr *)fw->data;
> > +	if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
> > +	    ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
> > +	    ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
> > +	    ehdr->e_ident[EI_MAG3] != ELFMAG3) {
> > +		dev_err(fei->dev, "Invalid ELF magic\n");
> > +		err = -ENODEV;
> > +		goto done;
> > +	} else {
> > +		dev_dbg(fei->dev, "Valid ELF header found\n");
> > +	}
> > +
> > +	/* Check program headers are within firmware size */
> > +	if (ehdr->e_phoff + (ehdr->e_phnum * sizeof(Elf32_Phdr)) > fw->size) {
> > +		dev_err(fei->dev, "Program headers outside of firmware file\n");
> > +		err = -ENODEV;
> > +		goto done;
> > +	}
> > +
> > +	pImem = (unsigned char *) fei->io + DMA_MEMDMA_OFFSET + DMA_IMEM_OFFSET;
> > +	pDmem = (unsigned char *) fei->io + DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET;
> > +
> > +	phdr = (Elf32_Phdr *)(fw->data + ehdr->e_phoff);
> > +
> > +	/* go through the available ELF segments */
> > +	for (i = 0; i < ehdr->e_phnum && !err; i++, phdr++) {
> > +		unsigned char *dest;
> > +		int imem = 0;
> > +
> > +		/* Only consider LOAD segments */
> > +		if (phdr->p_type != PT_LOAD)
> > +			continue;
> > +
> > +		/*
> > +		 * Check segment is contained within the fw->data buffer
> > +		 */
> > +		if (phdr->p_offset + phdr->p_filesz > fw->size) {
> > +			dev_err(fei->dev,
> > +				"Segment %d is outside of firmware file\n", i);
> > +			err = -EINVAL;
> > +			break;
> > +		}
> > +
> > +		/*
> > +		 * MEMDMA IMEM has executable flag set, otherwise load
> > +		 * this segment to DMEM.
> > +		 */
> > +
> > +		if (phdr->p_flags & PF_X) {
> > +			dest = pImem;
> > +			imem = 1;
> > +		} else {
> > +			dest = pDmem;
> > +		}
> > +
> > +		/*
> > +		 * The Slim ELF file uses 32-bit word addressing for
> > +		 * load offsets.
> > +		 */
> > +
> > +		dest += (phdr->p_paddr & 0xFFFFF) * sizeof(unsigned int);
> > +
> > +		/*
> > +		 * For DMEM segments copy the segment data from the ELF
> > +		 * file and pad segment with zeroes
> > +		 *
> > +		 * For IMEM segments, the segment contains 24-bit
> > +		 * instructions which must be padded to 32-bit
> > +		 * instructions before being written. The written
> > +		 * segment is padded with NOP instructions.
> > +		 */
> > +
> > +		if (!imem) {
> > +			dev_dbg(fei->dev,
> > +				"Loading DMEM segment %d 0x%08x\n\t"
> > +				"(0x%x bytes) -> 0x%08x (0x%x bytes)\n",
> > +				i, phdr->p_paddr, phdr->p_filesz,
> > +				(unsigned int)dest, phdr->p_memsz);
> > +
> > +			memcpy((void *)dest, (void *)fw->data + phdr->p_offset,
> > +				phdr->p_filesz);
> > +
> > +			memset((void *)dest + phdr->p_filesz, 0,
> > +				phdr->p_memsz - phdr->p_filesz);
> > +		} else {
> > +			const unsigned char *imem_src = fw->data
> > +				+ phdr->p_offset;
> > +			unsigned char *imem_dest = dest;
> > +			int j;
> > +
> > +			dev_dbg(fei->dev,
> > +				"Loading IMEM segment %d 0x%08x\n\t"
> > +				" (0x%x bytes) -> 0x%08x (0x%x bytes)\n", i,
> > +				phdr->p_paddr, phdr->p_filesz,
> > +				(unsigned int)dest,
> > +				phdr->p_memsz + phdr->p_memsz / 3);
> > +
> > +			for (j = 0; j < phdr->p_filesz; j++) {
> > +				*imem_dest = *imem_src;
> > +
> > +				/* Every 3 bytes, add an additional
> > +				 * padding zero in destination */
> > +				if (j % 3 == 2) {
> > +					imem_dest++;
> > +					*imem_dest = 0x00;
> > +				}
> > +				imem_dest++;
> > +				imem_src++;
> > +			}
> > +		}
> > +	}
> > +
> > +done:
> > +	release_firmware(fw);
> > +	return err;
> > +}
> > +
> > +static const struct of_device_id c8sectpfe_match[] = {
> > +	{ .compatible = "st,stih407-c8sectpfe" },
> > +	{ /* sentinel */ },
> > +};
> > +MODULE_DEVICE_TABLE(of, c8sectpfe_match);
> > +
> > +static struct platform_driver c8sectpfe_driver = {
> > +	.driver = {
> > +		.name = "c8sectpfe",
> > +		.of_match_table = of_match_ptr(c8sectpfe_match),
> > +	},
> > +	.probe	= c8sectpfe_probe,
> > +	.remove	= c8sectpfe_remove,
> > +};
> > +
> > +module_platform_driver(c8sectpfe_driver);
> > +
> > +MODULE_AUTHOR("Peter Bennett <peter.bennett@st.com>");
> > +MODULE_AUTHOR("Peter Griffin <peter.griffin@linaro.org>");
> > +MODULE_DESCRIPTION("C8SECTPFE STi DVB Driver");
> > +MODULE_LICENSE("GPL");
> > diff --git a/drivers/media/tsin/c8sectpfe/c8sectpfe-core.h b/drivers/media/tsin/c8sectpfe/c8sectpfe-core.h
> > new file mode 100644
> > index 0000000..3466303
> > --- /dev/null
> > +++ b/drivers/media/tsin/c8sectpfe/c8sectpfe-core.h
> > @@ -0,0 +1,288 @@
> > +/*
> > + * c8sectpfe-core.h - C8SECTPFE STi DVB driver
> > + *
> > + * Copyright (c) STMicroelectronics 2015
> > + *
> > + *   Author:Peter Bennett <peter.bennett@st.com>
> > + *	    Peter Griffin <peter.griffin@linaro.org>
> > + *
> > + *	This program is free software; you can redistribute it and/or
> > + *	modify it under the terms of the GNU General Public License as
> > + *	published by the Free Software Foundation; either version 2 of
> > + *	the License, or (at your option) any later version.
> > + */
> > +#ifndef _C8SECTPFE_CORE_H_
> > +#define _C8SECTPFE_CORE_H_
> > +
> > +#define C8SECTPFEI_MAXCHANNEL 16
> > +#define C8SECTPFEI_MAXADAPTER 3
> > +
> > +#define C8SECTPFE_MAX_TSIN_CHAN 8
> > +
> > +struct channel_info {
> > +
> > +	int tsin_id;
> > +	bool invert_ts_clk;
> > +	bool serial_not_parallel;
> > +	bool async_not_sync;
> > +	int i2c;
> > +	int dvb_card;
> > +
> > +	int rst_gpio;
> > +
> > +	struct i2c_adapter  *i2c_adapter;
> > +	struct i2c_adapter  *tuner_i2c;
> > +	struct i2c_adapter  *lnb_i2c;
> > +	struct i2c_client   *i2c_client;
> > +	struct dvb_frontend *frontend;
> > +
> > +	struct pinctrl_state *pstate;
> > +
> > +	int demux_mapping;
> > +	int active;
> > +
> > +	void *back_buffer_start;
> > +	void *back_buffer_aligned;
> > +	dma_addr_t back_buffer_busaddr;
> > +
> > +	void *pid_buffer_start;
> > +	void *pid_buffer_aligned;
> > +	dma_addr_t pid_buffer_busaddr;
> > +
> > +	unsigned long  fifo;
> > +
> > +	struct completion idle_completion;
> > +	struct tasklet_struct tsklet;
> > +
> > +	struct c8sectpfei *fei;
> > +	struct c8sectpfe_input_record *irec;
> > +
> > +};
> > +
> > +struct c8sectpfe_hw {
> > +	int num_ib;
> > +	int num_mib;
> > +	int num_swts;
> > +	int num_tsout;
> > +	int num_ccsc;
> > +	int num_ram;
> > +	int num_tp;
> > +};
> > +
> > +struct c8sectpfei {
> > +
> > +	struct device *dev;
> > +	struct pinctrl *pinctrl;
> > +
> > +	struct dentry *root;
> > +	struct debugfs_regset32	*regset;
> > +
> > +	int tsin_count;
> > +
> > +	struct c8sectpfe_hw hw_stats;
> > +
> > +	struct c8sectpfe *c8sectpfe[C8SECTPFEI_MAXADAPTER];
> > +
> > +	int mapping[C8SECTPFEI_MAXCHANNEL];
> > +
> > +	struct mutex lock;
> > +
> > +	struct timer_list timer;	/* timer interrupts for outputs */
> > +
> > +	void __iomem *io;
> > +	void __iomem *sram;
> > +
> > +	unsigned long sram_size;
> > +
> > +	struct channel_info *channel_data[C8SECTPFE_MAX_TSIN_CHAN];
> > +
> > +	struct clk *c8sectpfeclk;
> > +	int nima_rst_gpio;
> > +	int nimb_rst_gpio;
> > +
> > +	int idle_irq;
> > +	int error_irq;
> > +
> > +	int global_feed_count;
> > +
> > +	struct c8sectpfe_input_record *irec;
> > +};
> > +
> > +/* C8SECTPFE SYS Regs list */
> > +
> > +#define SYS_INPUT_ERR_STATUS	0x0
> > +#define SYS_OTHER_ERR_STATUS	0x8
> > +#define SYS_INPUT_ERR_MASK	0x10
> > +#define SYS_OTHER_ERR_MASK	0x18
> > +#define SYS_DMA_ROUTE		0x20
> > +#define SYS_INPUT_CLKEN		0x30
> > +#define IBENABLE_MASK			0x7F
> > +
> > +#define SYS_OTHER_CLKEN		0x38
> > +#define TSDMAENABLE			BIT(1)
> > +#define MEMDMAENABLE			BIT(0)
> > +
> > +#define SYS_CFG_NUM_IB		0x200
> > +#define SYS_CFG_NUM_MIB		0x204
> > +#define SYS_CFG_NUM_SWTS	0x208
> > +#define SYS_CFG_NUM_TSOUT	0x20C
> > +#define SYS_CFG_NUM_CCSC	0x210
> > +#define SYS_CFG_NUM_RAM		0x214
> > +#define SYS_CFG_NUM_TP		0x218
> > +
> > +/* Input Block Regs */
> > +
> > +#define C8SECTPFE_INPUTBLK_OFFSET	0x1000
> > +#define C8SECTPFE_CHANNEL_OFFSET(x)	((x*0x40) + C8SECTPFE_INPUTBLK_OFFSET)
> > +
> > +#define C8SECTPFE_IB_IP_FMT_CFG(x)      (C8SECTPFE_CHANNEL_OFFSET(x) + 0x00)
> > +#define C8SECTPFE_IGNORE_ERR_AT_SOP     BIT(7)
> > +#define C8SECTPFE_IGNORE_ERR_IN_PKT     BIT(6)
> > +#define C8SECTPFE_IGNORE_ERR_IN_BYTE    BIT(5)
> > +#define C8SECTPFE_INVERT_TSCLK          BIT(4)
> > +#define C8SECTPFE_ALIGN_BYTE_SOP        BIT(3)
> > +#define C8SECTPFE_ASYNC_NOT_SYNC        BIT(2)
> > +#define C8SECTPFE_BYTE_ENDIANNESS_MSB    BIT(1)
> > +#define C8SECTPFE_SERIAL_NOT_PARALLEL   BIT(0)
> > +
> > +#define C8SECTPFE_IB_SYNCLCKDRP_CFG(x)   (C8SECTPFE_CHANNEL_OFFSET(x) + 0x04)
> > +#define C8SECTPFE_SYNC(x)                (x & 0xf)
> > +#define C8SECTPFE_DROP(x)                ((x<<4) & 0xf)
> > +#define C8SECTPFE_TOKEN(x)               ((x<<8) & 0xff00)
> > +#define C8SECTPFE_SLDENDIANNESS          BIT(16)
> > +
> > +#define C8SECTPFE_IB_TAGBYTES_CFG(x)     (C8SECTPFE_CHANNEL_OFFSET(x) + 0x08)
> > +#define C8SECTPFE_TAG_HEADER(x)          (x << 16)
> > +#define C8SECTPFE_TAG_COUNTER(x)         ((x<<1) & 0x7fff)
> > +#define C8SECTPFE_TAG_ENABLE             BIT(0)
> > +
> > +#define C8SECTPFE_IB_PID_SET(x)          (C8SECTPFE_CHANNEL_OFFSET(x) + 0x0C)
> > +#define C8SECTPFE_PID_OFFSET(x)          (x & 0x3f)
> > +#define C8SECTPFE_PID_NUMBITS(x)         ((x << 6) & 0xfff)
> > +#define C8SECTPFE_PID_ENABLE             BIT(31)
> > +
> > +#define C8SECTPFE_IB_PKT_LEN(x)          (C8SECTPFE_CHANNEL_OFFSET(x) + 0x10)
> > +
> > +#define C8SECTPFE_IB_BUFF_STRT(x)        (C8SECTPFE_CHANNEL_OFFSET(x) + 0x14)
> > +#define C8SECTPFE_IB_BUFF_END(x)         (C8SECTPFE_CHANNEL_OFFSET(x) + 0x18)
> > +#define C8SECTPFE_IB_READ_PNT(x)         (C8SECTPFE_CHANNEL_OFFSET(x) + 0x1C)
> > +#define C8SECTPFE_IB_WRT_PNT(x)          (C8SECTPFE_CHANNEL_OFFSET(x) + 0x20)
> > +
> > +#define C8SECTPFE_IB_PRI_THRLD(x)        (C8SECTPFE_CHANNEL_OFFSET(x) + 0x24)
> > +#define C8SECTPFE_PRI_VALUE(x)           (x & 0x7fffff)
> > +#define C8SECTPFE_PRI_LOWPRI(x)          ((x & 0xf) << 24)
> > +#define C8SECTPFE_PRI_HIGHPRI(x)         ((x & 0xf) << 28)
> > +
> > +#define C8SECTPFE_IB_STAT(x)             (C8SECTPFE_CHANNEL_OFFSET(x) + 0x28)
> > +#define C8SECTPFE_STAT_FIFO_OVERFLOW(x)  (x & 0x1)
> > +#define C8SECTPFE_STAT_BUFFER_OVERFLOW(x) (x & 0x2)
> > +#define C8SECTPFE_STAT_OUTOFORDERRP(x)   (x & 0x4)
> > +#define C8SECTPFE_STAT_PID_OVERFLOW(x)   (x & 0x8)
> > +#define C8SECTPFE_STAT_PKT_OVERFLOW(x)   (x & 0x10)
> > +#define C8SECTPFE_STAT_ERROR_PACKETS(x)  ((x >> 8) & 0xf)
> > +#define C8SECTPFE_STAT_SHORT_PACKETS(x)  ((x >> 12) & 0xf)
> > +
> > +#define C8SECTPFE_IB_MASK(x)             (C8SECTPFE_CHANNEL_OFFSET(x) + 0x2C)
> > +#define C8SECTPFE_MASK_FIFO_OVERFLOW     BIT(0)
> > +#define C8SECTPFE_MASK_BUFFER_OVERFLOW   BIT(1)
> > +#define C8SECTPFE_MASK_OUTOFORDERRP(x)   BIT(2)
> > +#define C8SECTPFE_MASK_PID_OVERFLOW(x)   BIT(3)
> > +#define C8SECTPFE_MASK_PKT_OVERFLOW(x)   BIT(4)
> > +#define C8SECTPFE_MASK_ERROR_PACKETS(x)  ((x & 0xf) << 8)
> > +#define C8SECTPFE_MASK_SHORT_PACKETS(x)  ((x & 0xf) >> 12)
> > +
> > +#define C8SECTPFE_IB_SYS(x)              (C8SECTPFE_CHANNEL_OFFSET(x) + 0x30)
> > +#define C8SECTPFE_SYS_RESET              BIT(1)
> > +#define C8SECTPFE_SYS_ENABLE             BIT(0)
> > +
> > +/*
> > + * Ponter record data structure required for each input block
> > + * see Table 82 on page 167
> > + */
> > +
> > +struct tpentry {
> > +	/* The following entries are bus addresses for memdma */
> > +	unsigned long dma_busbase;
> > +	unsigned long dma_bustop;
> > +	unsigned long dma_bus_wp;
> > +	unsigned long dma_bus_rp;
> > +};
> > +
> > +struct c8sectpfe_input_record {
> > +	unsigned long dma_membase; /* Internal sram base address */
> > +	unsigned long dma_memtop;  /* Internal sram top address */
> > +
> > +	/*
> > +	 * TS packet size, including tag bytes added by input block,
> > +	 * rounded up to the next multiple of 8 bytes. The packet size,
> > +	 * including any tagging bytes and rounded up to the nearest
> > +	 * multiple of 8 bytes must be less than 255 bytes.
> > +	 */
> > +	unsigned long dma_ts_pktsize;
> > +	unsigned long tp_enable;
> > +	struct tpentry ptr_data[1];
> > +};
> > +
> > +#define DMA_MEMDMA_OFFSET	0x4000
> > +#define DMA_IMEM_OFFSET		0x0
> > +#define DMA_DMEM_OFFSET		0x4000
> > +#define DMA_CPU			0x8000
> > +#define DMA_PER_OFFSET		0xb000
> > +
> > +/* XP70 Slim core regs */
> > +#define DMA_CPU_ID	(DMA_MEMDMA_OFFSET + DMA_CPU + 0x0)
> > +#define DMA_CPU_VCR	(DMA_MEMDMA_OFFSET + DMA_CPU + 0x4)
> > +#define DMA_CPU_RUN	(DMA_MEMDMA_OFFSET + DMA_CPU + 0x8)
> > +#define DMA_CPU_CLOCKGATE	(DMA_MEMDMA_OFFSET + DMA_CPU + 0xc)
> > +#define DMA_CPU_PC	(DMA_MEMDMA_OFFSET + DMA_CPU + 0x20)
> > +
> > +/* Enable Interrupt for a IB */
> > +#define DMA_PER_TPn_DREQ_MASK	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xd00)
> > +/* Ack interrupt by setting corresponding bit */
> > +#define DMA_PER_TPn_DACK_SET	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xd80)
> > +#define DMA_PER_TPn_DREQ	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xe00)
> > +#define DMA_PER_TPn_DACK	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xe80)
> > +#define DMA_PER_DREQ_MODE	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xf80)
> > +#define DMA_PER_STBUS_SYNC	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xf88)
> > +#define DMA_PER_STBUS_ACCESS	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xf8c)
> > +#define DMA_PER_STBUS_ADDRESS	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xf90)
> > +#define DMA_PER_IDLE_INT	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfa8)
> > +#define DMA_PER_PRIORITY	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfac)
> > +#define DMA_PER_MAX_OPCODE	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfb0)
> > +#define DMA_PER_MAX_CHUNK	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfb4)
> > +#define DMA_PER_PAGE_SIZE	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfbc)
> > +#define DMA_PER_MBOX_STATUS	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfc0)
> > +#define DMA_PER_MBOX_SET	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfc8)
> > +#define DMA_PER_MBOX_CLEAR	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfd0)
> > +#define DMA_PER_MBOX_MASK	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfd8)
> > +#define DMA_PER_INJECT_PKT_SRC	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfe0)
> > +#define DMA_PER_INJECT_PKT_DEST	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfe4)
> > +#define DMA_PER_INJECT_PKT_ADDR	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfe8)
> > +#define DMA_PER_INJECT_PKT	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xfec)
> > +#define DMA_PER_PAT_PTR_INIT	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xff0)
> > +#define DMA_PER_PAT_PTR		(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xff4)
> > +#define DMA_PER_SLEEP_MASK	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xff8)
> > +#define DMA_PER_SLEEP_COUNTER	(DMA_MEMDMA_OFFSET + DMA_PER_OFFSET + 0xffc)
> > +/* #define DMA_RF_CPUREGn	DMA_RFBASEADDR n=0 to 15) slim regsa */
> > +
> > +/* The following are from DMA_DMEM_BaseAddress */
> > +#define DMA_FIRMWARE_VERSION	(DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET + 0x0)
> > +#define DMA_PTRREC_BASE		(DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET + 0x4)
> > +#define DMA_PTRREC_INPUT_OFFSET	(DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET + 0x8)
> > +#define DMA_ERRREC_BASE		(DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET + 0xc)
> > +#define DMA_ERROR_RECORD(n)	((n*4) + DMA_ERRREC_BASE + 0x4)
> > +#define DMA_IDLE_REQ		(DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET + 0x10)
> > +#define IDLEREQ			BIT(31)
> > +
> > +#define DMA_FIRMWARE_CONFIG	(DMA_MEMDMA_OFFSET + DMA_DMEM_OFFSET + 0x14)
> > +
> > +/* Regs for PID Filter */
> > +
> > +#define PIDF_OFFSET		0x2800
> > +#define PIDF_BASE(n)		((n*4) + PIDF_OFFSET)
> > +#define PIDF_LEAK_ENABLE	(PIDF_OFFSET + 0x100)
> > +#define PIDF_LEAK_STATUS	(PIDF_OFFSET + 0x108)
> > +#define PIDF_LEAK_COUNT_RESET	(PIDF_OFFSET + 0x110)
> > +#define PIDF_LEAK_COUNTER	(PIDF_OFFSET + 0x114)
> > +
> > +#endif /* _C8SECTPFE_CORE_H_ */

regards,

Peter.

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

* Re: [PATCH 02/12] [media] dvb-pll: Add support for THOMSON DTT7546X tuner.
  2015-07-30 10:08         ` Joe Perches
@ 2015-07-30 11:14           ` Michael Ira Krufky
  2015-07-30 11:17             ` Michael Ira Krufky
  2015-07-30 11:37             ` Michael Ira Krufky
  0 siblings, 2 replies; 32+ messages in thread
From: Michael Ira Krufky @ 2015-07-30 11:14 UTC (permalink / raw)
  To: Joe Perches
  Cc: Peter Griffin, Mauro Carvalho Chehab, linux-arm-kernel, LKML,
	srinivas.kandagatla, maxime.coquelin, patrice.chotard, lee.jones,
	hugues.fruchet, linux-media, devicetree

On Thu, Jul 30, 2015 at 6:08 AM, Joe Perches <joe@perches.com> wrote:
> On Thu, 2015-07-30 at 10:47 +0100, Peter Griffin wrote:
>> Hi Mauro / Joe,
>>
>> On Wed, 22 Jul 2015, Mauro Carvalho Chehab wrote:
>>
>> > Em Wed, 24 Jun 2015 18:17:37 -0700
>> > Joe Perches <joe@perches.com> escreveu:
>> >
>> > > On Wed, 2015-06-24 at 16:11 +0100, Peter Griffin wrote:
>> > > > This is used in conjunction with the STV0367 demodulator on
>> > > > the STV0367-NIM-V1.0 NIM card which can be used with the STi
>> > > > STB SoC's.
>> > >
>> > > Barely associated to this specific patch, but for
>> > > dvb-pll.c, another thing that seems possible is to
>> > > convert the struct dvb_pll_desc uses to const and
>> > > change the "entries" fixed array size from 12 to []
>> > >
>> > > It'd save a couple KB overall and remove ~5KB of data.
>> > >
>> > > $ size drivers/media/dvb-frontends/dvb-pll.o*
>> > >    text      data     bss     dec     hex filename
>> > >    8520      1552    2120   12192    2fa0 drivers/media/dvb-frontends/dvb-pll.o.new
>> > >    5624      6363    2120   14107    371b drivers/media/dvb-frontends/dvb-pll.o.old
>> >
>> > Peter,
>> >
>> > Please add this patch on the next patch series you submit.
>>
>> Ok will do, I've added this patch with a slightly updated commit message
>> to my series.
>>
>> Joe - Can I add your signed-off-by?
>
> Signed-off-by: Joe Perches <joe@perches.com>

Reviewed-by: Michael Ira Krufky <mkrufky@samsung.com>

Joe, nice optimization - thanks for that.

With regards to Peter's patch, is this a digital-only tuner, or is it
a hybrid tuner?

The 5th byte that you send to the THOMSON DTT7546X seems to resemble
the 'auxiliary byte' that gets set in tuner-simple.c

I'm not sure that dvb-pll is the right place for this tuner
definition, if this is the case.  Maybe this definition belongs in
tuner-simple instead, if the pattern matches better there.

Mauro, can we hold off on merging Peter's patch until we resolve this?

-Michael Ira Krufky

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

* Re: [PATCH 02/12] [media] dvb-pll: Add support for THOMSON DTT7546X tuner.
  2015-07-30 11:14           ` Michael Ira Krufky
@ 2015-07-30 11:17             ` Michael Ira Krufky
  2015-07-30 14:33               ` Peter Griffin
  2015-07-30 11:37             ` Michael Ira Krufky
  1 sibling, 1 reply; 32+ messages in thread
From: Michael Ira Krufky @ 2015-07-30 11:17 UTC (permalink / raw)
  To: Joe Perches
  Cc: Peter Griffin, Mauro Carvalho Chehab, linux-arm-kernel, LKML,
	srinivas.kandagatla, maxime.coquelin, patrice.chotard, lee.jones,
	hugues.fruchet, linux-media, devicetree

On Thu, Jul 30, 2015 at 7:14 AM, Michael Ira Krufky <mkrufky@linuxtv.org> wrote:
> On Thu, Jul 30, 2015 at 6:08 AM, Joe Perches <joe@perches.com> wrote:
>> On Thu, 2015-07-30 at 10:47 +0100, Peter Griffin wrote:
>>> Hi Mauro / Joe,
>>>
>>> On Wed, 22 Jul 2015, Mauro Carvalho Chehab wrote:
>>>
>>> > Em Wed, 24 Jun 2015 18:17:37 -0700
>>> > Joe Perches <joe@perches.com> escreveu:
>>> >
>>> > > On Wed, 2015-06-24 at 16:11 +0100, Peter Griffin wrote:
>>> > > > This is used in conjunction with the STV0367 demodulator on
>>> > > > the STV0367-NIM-V1.0 NIM card which can be used with the STi
>>> > > > STB SoC's.
>>> > >
>>> > > Barely associated to this specific patch, but for
>>> > > dvb-pll.c, another thing that seems possible is to
>>> > > convert the struct dvb_pll_desc uses to const and
>>> > > change the "entries" fixed array size from 12 to []
>>> > >
>>> > > It'd save a couple KB overall and remove ~5KB of data.
>>> > >
>>> > > $ size drivers/media/dvb-frontends/dvb-pll.o*
>>> > >    text      data     bss     dec     hex filename
>>> > >    8520      1552    2120   12192    2fa0 drivers/media/dvb-frontends/dvb-pll.o.new
>>> > >    5624      6363    2120   14107    371b drivers/media/dvb-frontends/dvb-pll.o.old
>>> >
>>> > Peter,
>>> >
>>> > Please add this patch on the next patch series you submit.
>>>
>>> Ok will do, I've added this patch with a slightly updated commit message
>>> to my series.
>>>
>>> Joe - Can I add your signed-off-by?
>>
>> Signed-off-by: Joe Perches <joe@perches.com>
>
> Reviewed-by: Michael Ira Krufky <m.krufky@samsung.com>
>
> Joe, nice optimization - thanks for that.
>
> With regards to Peter's patch, is this a digital-only tuner, or is it
> a hybrid tuner?
>
> The 5th byte that you send to the THOMSON DTT7546X seems to resemble
> the 'auxiliary byte' that gets set in tuner-simple.c
>
> I'm not sure that dvb-pll is the right place for this tuner
> definition, if this is the case.  Maybe this definition belongs in
> tuner-simple instead, if the pattern matches better there.
>
> Mauro, can we hold off on merging Peter's patch until we resolve this?
>
> -Michael Ira Krufky

eek!  I mispelled my own email address.


With regards to Joe's patch - I'd like to see that merged.  ...and
here is my correctly spelled email address:


Reviewed-by: Michael Ira Krufky <m.krufky@samsung.com>

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

* Re: [PATCH 02/12] [media] dvb-pll: Add support for THOMSON DTT7546X tuner.
  2015-07-30 11:14           ` Michael Ira Krufky
  2015-07-30 11:17             ` Michael Ira Krufky
@ 2015-07-30 11:37             ` Michael Ira Krufky
  2015-07-30 14:34               ` Peter Griffin
  1 sibling, 1 reply; 32+ messages in thread
From: Michael Ira Krufky @ 2015-07-30 11:37 UTC (permalink / raw)
  To: Joe Perches
  Cc: Peter Griffin, Mauro Carvalho Chehab, linux-arm-kernel, LKML,
	srinivas.kandagatla, maxime.coquelin, patrice.chotard, lee.jones,
	hugues.fruchet, linux-media, devicetree

On Thu, Jul 30, 2015 at 7:14 AM, Michael Ira Krufky <mkrufky@linuxtv.org> wrote:
> On Thu, Jul 30, 2015 at 6:08 AM, Joe Perches <joe@perches.com> wrote:
>> On Thu, 2015-07-30 at 10:47 +0100, Peter Griffin wrote:
>>> Hi Mauro / Joe,
>>>
>>> On Wed, 22 Jul 2015, Mauro Carvalho Chehab wrote:
>>>
>>> > Em Wed, 24 Jun 2015 18:17:37 -0700
>>> > Joe Perches <joe@perches.com> escreveu:
>>> >
>>> > > On Wed, 2015-06-24 at 16:11 +0100, Peter Griffin wrote:
>>> > > > This is used in conjunction with the STV0367 demodulator on
>>> > > > the STV0367-NIM-V1.0 NIM card which can be used with the STi
>>> > > > STB SoC's.
>>> > >
>>> > > Barely associated to this specific patch, but for
>>> > > dvb-pll.c, another thing that seems possible is to
>>> > > convert the struct dvb_pll_desc uses to const and
>>> > > change the "entries" fixed array size from 12 to []
>>> > >
>>> > > It'd save a couple KB overall and remove ~5KB of data.
>>> > >
>>> > > $ size drivers/media/dvb-frontends/dvb-pll.o*
>>> > >    text      data     bss     dec     hex filename
>>> > >    8520      1552    2120   12192    2fa0 drivers/media/dvb-frontends/dvb-pll.o.new
>>> > >    5624      6363    2120   14107    371b drivers/media/dvb-frontends/dvb-pll.o.old
>>> >
>>> > Peter,
>>> >
>>> > Please add this patch on the next patch series you submit.
>>>
>>> Ok will do, I've added this patch with a slightly updated commit message
>>> to my series.
>>>
>>> Joe - Can I add your signed-off-by?
>>
>> Signed-off-by: Joe Perches <joe@perches.com>
>
> Reviewed-by: Michael Ira Krufky <m.krufky@samsung.com>
>
> Joe, nice optimization - thanks for that.
>
> With regards to Peter's patch, is this a digital-only tuner, or is it
> a hybrid tuner?
>
> The 5th byte that you send to the THOMSON DTT7546X seems to resemble
> the 'auxiliary byte' that gets set in tuner-simple.c
>
> I'm not sure that dvb-pll is the right place for this tuner
> definition, if this is the case.  Maybe this definition belongs in
> tuner-simple instead, if the pattern matches better there.
>
> Mauro, can we hold off on merging Peter's patch until we resolve this?

This code block, specifically, I would rather not see added into dvb-pll:

+static int dvb_pll_get_num_regs(struct dvb_pll_priv *priv)
+{
+       int num_regs = 4;
+
+       if (strncmp(priv->pll_desc->name, "Thomson dtt7546x", 16) == 0)
+               num_regs = 5;
+
+       return num_regs;
+}
+

tuner-simple provides an infrastructure that allows this tuner to be
added in a more elegant way without the need to add special cases to
otherwise generic code, as done in the above.

I'm sorry, Peter.  Can you take a look at tuner-simple and consider
sending a new patch?

-Michael Ira Krufky

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

* Re: [PATCH 02/12] [media] dvb-pll: Add support for THOMSON DTT7546X tuner.
  2015-07-30 11:17             ` Michael Ira Krufky
@ 2015-07-30 14:33               ` Peter Griffin
  0 siblings, 0 replies; 32+ messages in thread
From: Peter Griffin @ 2015-07-30 14:33 UTC (permalink / raw)
  To: Michael Ira Krufky
  Cc: Joe Perches, Mauro Carvalho Chehab, linux-arm-kernel, LKML,
	srinivas.kandagatla, maxime.coquelin, patrice.chotard, lee.jones,
	hugues.fruchet, linux-media, devicetree

Hi Michael,

On Thu, 30 Jul 2015, Michael Ira Krufky wrote:

> On Thu, Jul 30, 2015 at 7:14 AM, Michael Ira Krufky <mkrufky@linuxtv.org> wrote:
> > On Thu, Jul 30, 2015 at 6:08 AM, Joe Perches <joe@perches.com> wrote:
> >> On Thu, 2015-07-30 at 10:47 +0100, Peter Griffin wrote:
> >>> Hi Mauro / Joe,
> >>>
> >>> On Wed, 22 Jul 2015, Mauro Carvalho Chehab wrote:
> >>>
> >>> > Em Wed, 24 Jun 2015 18:17:37 -0700
> >>> > Joe Perches <joe@perches.com> escreveu:
> >>> >
> >>> > > On Wed, 2015-06-24 at 16:11 +0100, Peter Griffin wrote:
> >>> > > > This is used in conjunction with the STV0367 demodulator on
> >>> > > > the STV0367-NIM-V1.0 NIM card which can be used with the STi
> >>> > > > STB SoC's.
> >>> > >
> >>> > > Barely associated to this specific patch, but for
> >>> > > dvb-pll.c, another thing that seems possible is to
> >>> > > convert the struct dvb_pll_desc uses to const and
> >>> > > change the "entries" fixed array size from 12 to []
> >>> > >
> >>> > > It'd save a couple KB overall and remove ~5KB of data.
> >>> > >
> >>> > > $ size drivers/media/dvb-frontends/dvb-pll.o*
> >>> > >    text      data     bss     dec     hex filename
> >>> > >    8520      1552    2120   12192    2fa0 drivers/media/dvb-frontends/dvb-pll.o.new
> >>> > >    5624      6363    2120   14107    371b drivers/media/dvb-frontends/dvb-pll.o.old
> >>> >
> >>> > Peter,
> >>> >
> >>> > Please add this patch on the next patch series you submit.
> >>>
> >>> Ok will do, I've added this patch with a slightly updated commit message
> >>> to my series.
> >>>
> >>> Joe - Can I add your signed-off-by?
> >>
> >> Signed-off-by: Joe Perches <joe@perches.com>
> >
> > Reviewed-by: Michael Ira Krufky <m.krufky@samsung.com>
> >
> > Joe, nice optimization - thanks for that.
> >
> > With regards to Peter's patch, is this a digital-only tuner, or is it
> > a hybrid tuner?
> >
> > The 5th byte that you send to the THOMSON DTT7546X seems to resemble
> > the 'auxiliary byte' that gets set in tuner-simple.c
> >
> > I'm not sure that dvb-pll is the right place for this tuner
> > definition, if this is the case.  Maybe this definition belongs in
> > tuner-simple instead, if the pattern matches better there.
> >
> > Mauro, can we hold off on merging Peter's patch until we resolve this?
> >
> > -Michael Ira Krufky
> 
> eek!  I mispelled my own email address.
> 
> 
> With regards to Joe's patch - I'd like to see that merged.  ...and
> here is my correctly spelled email address:
> 
> 
> Reviewed-by: Michael Ira Krufky <m.krufky@samsung.com>

Ok I will add your reviewed-by and include it in my v2.

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

* Re: [PATCH 02/12] [media] dvb-pll: Add support for THOMSON DTT7546X tuner.
  2015-07-30 11:37             ` Michael Ira Krufky
@ 2015-07-30 14:34               ` Peter Griffin
  0 siblings, 0 replies; 32+ messages in thread
From: Peter Griffin @ 2015-07-30 14:34 UTC (permalink / raw)
  To: Michael Ira Krufky
  Cc: Joe Perches, Mauro Carvalho Chehab, linux-arm-kernel, LKML,
	srinivas.kandagatla, maxime.coquelin, patrice.chotard, lee.jones,
	hugues.fruchet, linux-media, devicetree

Hi Michael,

On Thu, 30 Jul 2015, Michael Ira Krufky wrote:

> On Thu, Jul 30, 2015 at 7:14 AM, Michael Ira Krufky <mkrufky@linuxtv.org> wrote:
> > On Thu, Jul 30, 2015 at 6:08 AM, Joe Perches <joe@perches.com> wrote:
> >> On Thu, 2015-07-30 at 10:47 +0100, Peter Griffin wrote:
> >>> Hi Mauro / Joe,
> >>>
> >>> On Wed, 22 Jul 2015, Mauro Carvalho Chehab wrote:
> >>>
> >>> > Em Wed, 24 Jun 2015 18:17:37 -0700
> >>> > Joe Perches <joe@perches.com> escreveu:
> >>> >
> >>> > > On Wed, 2015-06-24 at 16:11 +0100, Peter Griffin wrote:
> >>> > > > This is used in conjunction with the STV0367 demodulator on
> >>> > > > the STV0367-NIM-V1.0 NIM card which can be used with the STi
> >>> > > > STB SoC's.
> >>> > >
> >>> > > Barely associated to this specific patch, but for
> >>> > > dvb-pll.c, another thing that seems possible is to
> >>> > > convert the struct dvb_pll_desc uses to const and
> >>> > > change the "entries" fixed array size from 12 to []
> >>> > >
> >>> > > It'd save a couple KB overall and remove ~5KB of data.
> >>> > >
> >>> > > $ size drivers/media/dvb-frontends/dvb-pll.o*
> >>> > >    text      data     bss     dec     hex filename
> >>> > >    8520      1552    2120   12192    2fa0 drivers/media/dvb-frontends/dvb-pll.o.new
> >>> > >    5624      6363    2120   14107    371b drivers/media/dvb-frontends/dvb-pll.o.old
> >>> >
> >>> > Peter,
> >>> >
> >>> > Please add this patch on the next patch series you submit.
> >>>
> >>> Ok will do, I've added this patch with a slightly updated commit message
> >>> to my series.
> >>>
> >>> Joe - Can I add your signed-off-by?
> >>
> >> Signed-off-by: Joe Perches <joe@perches.com>
> >
> > Reviewed-by: Michael Ira Krufky <m.krufky@samsung.com>
> >
> > Joe, nice optimization - thanks for that.
> >
> > With regards to Peter's patch, is this a digital-only tuner, or is it
> > a hybrid tuner?
> >
> > The 5th byte that you send to the THOMSON DTT7546X seems to resemble
> > the 'auxiliary byte' that gets set in tuner-simple.c
> >
> > I'm not sure that dvb-pll is the right place for this tuner
> > definition, if this is the case.  Maybe this definition belongs in
> > tuner-simple instead, if the pattern matches better there.
> >
> > Mauro, can we hold off on merging Peter's patch until we resolve this?
> 
> This code block, specifically, I would rather not see added into dvb-pll:
> 
> +static int dvb_pll_get_num_regs(struct dvb_pll_priv *priv)
> +{
> +       int num_regs = 4;
> +
> +       if (strncmp(priv->pll_desc->name, "Thomson dtt7546x", 16) == 0)
> +               num_regs = 5;
> +
> +       return num_regs;
> +}
> +
> 
> tuner-simple provides an infrastructure that allows this tuner to be
> added in a more elegant way without the need to add special cases to
> otherwise generic code, as done in the above.
> 
> I'm sorry, Peter.  Can you take a look at tuner-simple and consider
> sending a new patch?

Yes sure. I wasn't actually aware that tuner-simple existed. From what I
can see briefly looking at it, it does look a more suitable way of adding
support for this tuner.

The dtt7546x is a dual tuner in that it supports dvb-t and dvb-c, however
I have only tested it with DVB-T as that is the only feed I have to my home office.

As I have a V2 incorporating all of Mauro's changes ready to send, and I'm 
on holiday for 3 weeks from Friday, I will temporarily drop support for this
tuner and NIM card in V2, and migrate over to the new driver when I return end
of August.

regards,

Peter.

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

end of thread, other threads:[~2015-07-30 14:34 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-24 15:10 [PATCH 00/12] Add c8sectpfe LinuxDVB demux driver Peter Griffin
2015-06-24 15:10 ` [PATCH 01/12] ARM: DT: STi: stihxxx-b2120: Add pulse-width properties to ssc2 & ssc3 Peter Griffin
2015-06-24 15:11 ` [PATCH 02/12] [media] dvb-pll: Add support for THOMSON DTT7546X tuner Peter Griffin
2015-06-25  1:17   ` Joe Perches
2015-07-22 21:58     ` Mauro Carvalho Chehab
2015-07-30  9:47       ` Peter Griffin
2015-07-30 10:08         ` Joe Perches
2015-07-30 11:14           ` Michael Ira Krufky
2015-07-30 11:17             ` Michael Ira Krufky
2015-07-30 14:33               ` Peter Griffin
2015-07-30 11:37             ` Michael Ira Krufky
2015-07-30 14:34               ` Peter Griffin
2015-07-22 17:10   ` Mauro Carvalho Chehab
2015-07-30  9:46     ` Peter Griffin
2015-06-24 15:11 ` [PATCH 03/12] [media] stv0367: Refine i2c error trace to include i2c address Peter Griffin
2015-06-24 15:11 ` [PATCH 04/12] [media] stv0367: Add support for 16Mhz reference clock Peter Griffin
2015-06-24 15:11 ` [PATCH 05/12] [media] tsin: c8sectpfe: Add DT bindings documentation for c8sectpfe driver Peter Griffin
2015-06-24 15:11 ` [PATCH 06/12] ARM: DT: STi: STiH407: Add c8sectpfe LinuxDVB DT node Peter Griffin
2015-06-24 15:11 ` [PATCH 07/12] [media] tsin: c8sectpfe: STiH407/10 Linux DVB demux support Peter Griffin
2015-07-22 21:46   ` Mauro Carvalho Chehab
2015-07-30 11:08     ` Peter Griffin
2015-06-24 15:11 ` [PATCH 08/12] [media] tsin: c8sectpfe: Add LDVB helper functions Peter Griffin
2015-06-24 15:11 ` [PATCH 09/12] [media] tsin: c8sectpfe: Add support for various ST NIM cards Peter Griffin
2015-07-22 21:53   ` Mauro Carvalho Chehab
2015-07-30  9:43     ` Peter Griffin
2015-06-24 15:11 ` [PATCH 10/12] [media] tsin: c8sectpfe: Add c8sectpfe debugfs support Peter Griffin
2015-06-24 15:11 ` [PATCH 11/12] [media] tsin: c8sectpfe: Add Kconfig and Makefile for the driver Peter Griffin
2015-06-25  7:23   ` Paul Bolle
2015-07-22  7:38     ` Peter Griffin
2015-07-22 21:56   ` Mauro Carvalho Chehab
2015-07-30  9:39     ` Peter Griffin
2015-06-24 15:11 ` [PATCH 12/12] MAINTAINERS: Add c8sectpfe driver directory to STi section Peter Griffin

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).