All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/21] TVP5150 fixes and new features
@ 2018-06-28 16:20 Marco Felsch
  2018-06-28 16:20 ` [PATCH 01/22] [media] tvp5150: fix width alignment during set_selection() Marco Felsch
                   ` (22 more replies)
  0 siblings, 23 replies; 70+ messages in thread
From: Marco Felsch @ 2018-06-28 16:20 UTC (permalink / raw)
  To: mchehab, robh+dt, mark.rutland
  Cc: p.zabel, afshin.nasser, javierm, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

First some fixes were made which may possibly interesting for other
kernel versions.

Then I picked most of the patches from Philipp [1] and ported them
to the recent media_tree master branch [3].

But the main purpose of this series is to convert the proprietary
connector DT property into the generic input port property. I picked commit
('partial revert of "[media] tvp5150: add HW input connectors support"')
to have a clean working base and used the results of the discussion [2].

[1] https://patchwork.linuxtv.org/patch/33464/
[2] https://patchwork.linuxtv.org/patch/33852/
[3] https://git.linuxtv.org/media_tree.git/log/

Javier Martinez Canillas (1):
  partial revert of "[media] tvp5150: add HW input connectors support"

Marco Felsch (10):
  [media] tvp5150: fix width alignment during set_selection()
  [media] tvp5150: fix switch exit in set control handler
  [media] tvp5150: make use of regmap_update_bits
  [media] v4l2-rect.h: add position and equal helpers
  [media] tvp5150: add FORMAT_TRY support for get/set selection handlers
  [media] tvp5150: add default format helper
  [media] tvp5150: add g_std callback
  [media] tvp5150: add input source selection of_graph support
  [media] tvp5150: Add input port connectors DT bindings
  [media] tvp5150: Change default input source selection behaviour

Michael Tretter (1):
  [media] tvp5150: initialize subdev before parsing device tree

Philipp Zabel (10):
  [media] tvp5150: convert register access to regmap
  [media] tvp5150: trigger autodetection on subdev open to reset
    cropping
  [media] tvp5150: fix standard autodetection
  [media] tvp5150: split reset/enable routine
  [media] tvp5150: remove pin configuration from initialization tables
  [media] tvp5150: Add sync lock interrupt handling
  [media] tvp5150: disable output while signal not locked
  [media] tvp5150: issue source change events
  [media] tvp5150: add sync lock/loss signal debug messages
  [media] tvp5150: add querystd

 .../devicetree/bindings/media/i2c/tvp5150.txt | 118 ++-
 drivers/media/i2c/tvp5150.c                   | 959 ++++++++++++------
 drivers/media/i2c/tvp5150_reg.h               |   3 +
 include/dt-bindings/media/tvp5150.h           |   2 -
 include/media/v4l2-rect.h                     |  27 +
 5 files changed, 812 insertions(+), 297 deletions(-)

-- 
2.17.1

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

* [PATCH 01/22] [media] tvp5150: fix width alignment during set_selection()
  2018-06-28 16:20 [PATCH 00/21] TVP5150 fixes and new features Marco Felsch
@ 2018-06-28 16:20 ` Marco Felsch
  2018-06-28 16:20 ` [PATCH 02/22] [media] tvp5150: fix switch exit in set control handler Marco Felsch
                   ` (21 subsequent siblings)
  22 siblings, 0 replies; 70+ messages in thread
From: Marco Felsch @ 2018-06-28 16:20 UTC (permalink / raw)
  To: mchehab, robh+dt, mark.rutland
  Cc: p.zabel, afshin.nasser, javierm, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

The driver ignored the width alignment which exists due to the UYVY
colorspace format. Fix the width alignment and make use of the the
provided v4l2 helper function to set the width, height and all
alignments in one.

Fixes: 963ddc63e20d ("[media] media: tvp5150: Add cropping support")
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/media/i2c/tvp5150.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index 76e6bed5a1da..da7ad455d4a8 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -901,9 +901,6 @@ static int tvp5150_set_selection(struct v4l2_subdev *sd,
 
 	/* tvp5150 has some special limits */
 	rect.left = clamp(rect.left, 0, TVP5150_MAX_CROP_LEFT);
-	rect.width = clamp_t(unsigned int, rect.width,
-			     TVP5150_H_MAX - TVP5150_MAX_CROP_LEFT - rect.left,
-			     TVP5150_H_MAX - rect.left);
 	rect.top = clamp(rect.top, 0, TVP5150_MAX_CROP_TOP);
 
 	/* Calculate height based on current standard */
@@ -917,9 +914,16 @@ static int tvp5150_set_selection(struct v4l2_subdev *sd,
 	else
 		hmax = TVP5150_V_MAX_OTHERS;
 
-	rect.height = clamp_t(unsigned int, rect.height,
+	/*
+	 * alignments:
+	 *  - width = 2 due to UYVY colorspace
+	 *  - height, image = no special alignment
+	 */
+	v4l_bound_align_image(&rect.width,
+			      TVP5150_H_MAX - TVP5150_MAX_CROP_LEFT - rect.left,
+			      TVP5150_H_MAX - rect.left, 1, &rect.height,
 			      hmax - TVP5150_MAX_CROP_TOP - rect.top,
-			      hmax - rect.top);
+			      hmax - rect.top, 0, 0);
 
 	tvp5150_write(sd, TVP5150_VERT_BLANKING_START, rect.top);
 	tvp5150_write(sd, TVP5150_VERT_BLANKING_STOP,
-- 
2.17.1

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

* [PATCH 02/22] [media] tvp5150: fix switch exit in set control handler
  2018-06-28 16:20 [PATCH 00/21] TVP5150 fixes and new features Marco Felsch
  2018-06-28 16:20 ` [PATCH 01/22] [media] tvp5150: fix width alignment during set_selection() Marco Felsch
@ 2018-06-28 16:20 ` Marco Felsch
  2018-06-28 16:20 ` [PATCH 03/22] [media] tvp5150: convert register access to regmap Marco Felsch
                   ` (20 subsequent siblings)
  22 siblings, 0 replies; 70+ messages in thread
From: Marco Felsch @ 2018-06-28 16:20 UTC (permalink / raw)
  To: mchehab, robh+dt, mark.rutland
  Cc: p.zabel, afshin.nasser, javierm, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

The function only consists of a single switch case block without a
default case. Unsupported control requests are indicated by the -EINVAL
return code trough the last return statement at the end of the function. So
exiting just the switch case block returns the -EINVAL error code but the
hue control is supported and a zero should be returned instead.

Replace the break by a 'return 0' to fix this behaviour.

Fixes: d183e4efcae8 ("[media] v4l: tvp5150: Add missing break in set
control handler")
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/media/i2c/tvp5150.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index da7ad455d4a8..509ac243ea97 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -828,7 +828,7 @@ static int tvp5150_s_ctrl(struct v4l2_ctrl *ctrl)
 		return 0;
 	case V4L2_CID_HUE:
 		tvp5150_write(sd, TVP5150_HUE_CTL, ctrl->val);
-		break;
+		return 0;
 	case V4L2_CID_TEST_PATTERN:
 		decoder->enable = ctrl->val ? false : true;
 		tvp5150_selmux(sd);
-- 
2.17.1

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

* [PATCH 03/22] [media] tvp5150: convert register access to regmap
  2018-06-28 16:20 [PATCH 00/21] TVP5150 fixes and new features Marco Felsch
  2018-06-28 16:20 ` [PATCH 01/22] [media] tvp5150: fix width alignment during set_selection() Marco Felsch
  2018-06-28 16:20 ` [PATCH 02/22] [media] tvp5150: fix switch exit in set control handler Marco Felsch
@ 2018-06-28 16:20 ` Marco Felsch
  2018-06-28 16:20 ` [PATCH 04/22] [media] tvp5150: make use of regmap_update_bits Marco Felsch
                   ` (19 subsequent siblings)
  22 siblings, 0 replies; 70+ messages in thread
From: Marco Felsch @ 2018-06-28 16:20 UTC (permalink / raw)
  To: mchehab, robh+dt, mark.rutland
  Cc: p.zabel, afshin.nasser, javierm, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

From: Philipp Zabel <p.zabel@pengutronix.de>

Regmap provides built in debugging, caching and provides dedicated
accessors for bit manipulations in registers, which make the following
changes a lot simpler.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/media/i2c/tvp5150.c | 199 ++++++++++++++++++++++++------------
 1 file changed, 136 insertions(+), 63 deletions(-)

diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index 509ac243ea97..b3c7b65606fd 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -12,6 +12,7 @@
 #include <linux/gpio/consumer.h>
 #include <linux/module.h>
 #include <linux/of_graph.h>
+#include <linux/regmap.h>
 #include <media/v4l2-async.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ctrls.h>
@@ -47,6 +48,7 @@ struct tvp5150 {
 #endif
 	struct v4l2_ctrl_handler hdl;
 	struct v4l2_rect rect;
+	struct regmap *regmap;
 
 	v4l2_std_id norm;	/* Current set standard */
 	u32 input;
@@ -71,32 +73,14 @@ static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
 
 static int tvp5150_read(struct v4l2_subdev *sd, unsigned char addr)
 {
-	struct i2c_client *c = v4l2_get_subdevdata(sd);
-	int rc;
-
-	rc = i2c_smbus_read_byte_data(c, addr);
-	if (rc < 0) {
-		dev_err(sd->dev, "i2c i/o error: rc == %d\n", rc);
-		return rc;
-	}
-
-	dev_dbg_lvl(sd->dev, 2, debug, "tvp5150: read 0x%02x = %02x\n", addr, rc);
-
-	return rc;
-}
-
-static int tvp5150_write(struct v4l2_subdev *sd, unsigned char addr,
-				 unsigned char value)
-{
-	struct i2c_client *c = v4l2_get_subdevdata(sd);
-	int rc;
+	struct tvp5150 *decoder = to_tvp5150(sd);
+	int ret, val;
 
-	dev_dbg_lvl(sd->dev, 2, debug, "tvp5150: writing %02x %02x\n", addr, value);
-	rc = i2c_smbus_write_byte_data(c, addr, value);
-	if (rc < 0)
-		dev_err(sd->dev, "i2c i/o error: rc == %d\n", rc);
+	ret = regmap_read(decoder->regmap, addr, &val);
+	if (ret < 0)
+		return ret;
 
-	return rc;
+	return val;
 }
 
 static void dump_reg_range(struct v4l2_subdev *sd, char *s, u8 init,
@@ -288,8 +272,8 @@ static void tvp5150_selmux(struct v4l2_subdev *sd)
 			decoder->input, decoder->output,
 			input, opmode);
 
-	tvp5150_write(sd, TVP5150_OP_MODE_CTL, opmode);
-	tvp5150_write(sd, TVP5150_VD_IN_SRC_SEL_1, input);
+	regmap_write(decoder->regmap, TVP5150_OP_MODE_CTL, opmode);
+	regmap_write(decoder->regmap, TVP5150_VD_IN_SRC_SEL_1, input);
 
 	/*
 	 * Setup the FID/GLCO/VLK/HVLK and INTREQ/GPCL/VBLK output signals. For
@@ -308,7 +292,7 @@ static void tvp5150_selmux(struct v4l2_subdev *sd)
 		val = (val & ~TVP5150_MISC_CTL_GPCL) | TVP5150_MISC_CTL_HVLK;
 	else
 		val = (val & ~TVP5150_MISC_CTL_HVLK) | TVP5150_MISC_CTL_GPCL;
-	tvp5150_write(sd, TVP5150_MISC_CTL, val);
+	regmap_write(decoder->regmap, TVP5150_MISC_CTL, val);
 };
 
 struct i2c_reg_value {
@@ -583,8 +567,10 @@ static struct i2c_vbi_ram_value vbi_ram_default[] = {
 static int tvp5150_write_inittab(struct v4l2_subdev *sd,
 				const struct i2c_reg_value *regs)
 {
+	struct tvp5150 *decoder = to_tvp5150(sd);
+
 	while (regs->reg != 0xff) {
-		tvp5150_write(sd, regs->reg, regs->value);
+		regmap_write(decoder->regmap, regs->reg, regs->value);
 		regs++;
 	}
 	return 0;
@@ -592,15 +578,17 @@ static int tvp5150_write_inittab(struct v4l2_subdev *sd,
 
 static int tvp5150_vdp_init(struct v4l2_subdev *sd)
 {
+	struct tvp5150 *decoder = to_tvp5150(sd);
+	struct regmap *map = decoder->regmap;
 	unsigned int i;
 	int j;
 
 	/* Disable Full Field */
-	tvp5150_write(sd, TVP5150_FULL_FIELD_ENA, 0);
+	regmap_write(map, TVP5150_FULL_FIELD_ENA, 0);
 
 	/* Before programming, Line mode should be at 0xff */
 	for (i = TVP5150_LINE_MODE_INI; i <= TVP5150_LINE_MODE_END; i++)
-		tvp5150_write(sd, i, 0xff);
+		regmap_write(map, i, 0xff);
 
 	/* Load Ram Table */
 	for (j = 0; j < ARRAY_SIZE(vbi_ram_default); j++) {
@@ -609,11 +597,12 @@ static int tvp5150_vdp_init(struct v4l2_subdev *sd)
 		if (!regs->type.vbi_type)
 			continue;
 
-		tvp5150_write(sd, TVP5150_CONF_RAM_ADDR_HIGH, regs->reg >> 8);
-		tvp5150_write(sd, TVP5150_CONF_RAM_ADDR_LOW, regs->reg);
+		regmap_write(map, TVP5150_CONF_RAM_ADDR_HIGH, regs->reg >> 8);
+		regmap_write(map, TVP5150_CONF_RAM_ADDR_LOW, regs->reg);
 
 		for (i = 0; i < 16; i++)
-			tvp5150_write(sd, TVP5150_VDP_CONF_RAM_DATA, regs->values[i]);
+			regmap_write(map, TVP5150_VDP_CONF_RAM_DATA,
+				     regs->values[i]);
 	}
 	return 0;
 }
@@ -693,10 +682,10 @@ static int tvp5150_set_vbi(struct v4l2_subdev *sd,
 	reg = ((line - 6) << 1) + TVP5150_LINE_MODE_INI;
 
 	if (fields & 1)
-		tvp5150_write(sd, reg, type);
+		regmap_write(decoder->regmap, reg, type);
 
 	if (fields & 2)
-		tvp5150_write(sd, reg + 1, type);
+		regmap_write(decoder->regmap, reg + 1, type);
 
 	return type;
 }
@@ -763,7 +752,7 @@ static int tvp5150_set_std(struct v4l2_subdev *sd, v4l2_std_id std)
 	}
 
 	dev_dbg_lvl(sd->dev, 1, debug, "Set video std register to %d.\n", fmt);
-	tvp5150_write(sd, TVP5150_VIDEO_STD, fmt);
+	regmap_write(decoder->regmap, TVP5150_VIDEO_STD, fmt);
 	return 0;
 }
 
@@ -806,7 +795,7 @@ static int tvp5150_reset(struct v4l2_subdev *sd, u32 val)
 	tvp5150_set_std(sd, decoder->norm);
 
 	if (decoder->mbus_type == V4L2_MBUS_PARALLEL)
-		tvp5150_write(sd, TVP5150_DATA_RATE_SEL, 0x40);
+		regmap_write(decoder->regmap, TVP5150_DATA_RATE_SEL, 0x40);
 
 	return 0;
 };
@@ -818,16 +807,17 @@ static int tvp5150_s_ctrl(struct v4l2_ctrl *ctrl)
 
 	switch (ctrl->id) {
 	case V4L2_CID_BRIGHTNESS:
-		tvp5150_write(sd, TVP5150_BRIGHT_CTL, ctrl->val);
+		regmap_write(decoder->regmap, TVP5150_BRIGHT_CTL, ctrl->val);
 		return 0;
 	case V4L2_CID_CONTRAST:
-		tvp5150_write(sd, TVP5150_CONTRAST_CTL, ctrl->val);
+		regmap_write(decoder->regmap, TVP5150_CONTRAST_CTL, ctrl->val);
 		return 0;
 	case V4L2_CID_SATURATION:
-		tvp5150_write(sd, TVP5150_SATURATION_CTL, ctrl->val);
+		regmap_write(decoder->regmap, TVP5150_SATURATION_CTL,
+			     ctrl->val);
 		return 0;
 	case V4L2_CID_HUE:
-		tvp5150_write(sd, TVP5150_HUE_CTL, ctrl->val);
+		regmap_write(decoder->regmap, TVP5150_HUE_CTL, ctrl->val);
 		return 0;
 	case V4L2_CID_TEST_PATTERN:
 		decoder->enable = ctrl->val ? false : true;
@@ -925,17 +915,17 @@ static int tvp5150_set_selection(struct v4l2_subdev *sd,
 			      hmax - TVP5150_MAX_CROP_TOP - rect.top,
 			      hmax - rect.top, 0, 0);
 
-	tvp5150_write(sd, TVP5150_VERT_BLANKING_START, rect.top);
-	tvp5150_write(sd, TVP5150_VERT_BLANKING_STOP,
+	regmap_write(decoder->regmap, TVP5150_VERT_BLANKING_START, rect.top);
+	regmap_write(decoder->regmap, TVP5150_VERT_BLANKING_STOP,
 		      rect.top + rect.height - hmax);
-	tvp5150_write(sd, TVP5150_ACT_VD_CROP_ST_MSB,
+	regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_ST_MSB,
 		      rect.left >> TVP5150_CROP_SHIFT);
-	tvp5150_write(sd, TVP5150_ACT_VD_CROP_ST_LSB,
+	regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_ST_LSB,
 		      rect.left | (1 << TVP5150_CROP_SHIFT));
-	tvp5150_write(sd, TVP5150_ACT_VD_CROP_STP_MSB,
+	regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_STP_MSB,
 		      (rect.left + rect.width - TVP5150_MAX_CROP_LEFT) >>
 		      TVP5150_CROP_SHIFT);
-	tvp5150_write(sd, TVP5150_ACT_VD_CROP_STP_LSB,
+	regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_STP_LSB,
 		      rect.left + rect.width - TVP5150_MAX_CROP_LEFT);
 
 	decoder->rect = rect;
@@ -1083,7 +1073,7 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
 			val |= TVP5150_MISC_CTL_SYNC_OE;
 	}
 
-	tvp5150_write(sd, TVP5150_MISC_CTL, val);
+	regmap_write(decoder->regmap, TVP5150_MISC_CTL, val);
 
 	return 0;
 }
@@ -1107,6 +1097,8 @@ static int tvp5150_s_routing(struct v4l2_subdev *sd,
 
 static int tvp5150_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
 {
+	struct tvp5150 *decoder = to_tvp5150(sd);
+
 	/*
 	 * this is for capturing 36 raw vbi lines
 	 * if there's a way to cut off the beginning 2 vbi lines
@@ -1116,16 +1108,18 @@ static int tvp5150_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt
 	 */
 
 	if (fmt->sample_format == V4L2_PIX_FMT_GREY)
-		tvp5150_write(sd, TVP5150_LUMA_PROC_CTL_1, 0x70);
+		regmap_write(decoder->regmap, TVP5150_LUMA_PROC_CTL_1, 0x70);
 	if (fmt->count[0] == 18 && fmt->count[1] == 18) {
-		tvp5150_write(sd, TVP5150_VERT_BLANKING_START, 0x00);
-		tvp5150_write(sd, TVP5150_VERT_BLANKING_STOP, 0x01);
+		regmap_write(decoder->regmap, TVP5150_VERT_BLANKING_START,
+			     0x00);
+		regmap_write(decoder->regmap, TVP5150_VERT_BLANKING_STOP, 0x01);
 	}
 	return 0;
 }
 
 static int tvp5150_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
 {
+	struct tvp5150 *decoder = to_tvp5150(sd);
 	int i;
 
 	if (svbi->service_set != 0) {
@@ -1136,17 +1130,17 @@ static int tvp5150_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f
 						0xf0, i, 3);
 		}
 		/* Enables FIFO */
-		tvp5150_write(sd, TVP5150_FIFO_OUT_CTRL, 1);
+		regmap_write(decoder->regmap, TVP5150_FIFO_OUT_CTRL, 1);
 	} else {
 		/* Disables FIFO*/
-		tvp5150_write(sd, TVP5150_FIFO_OUT_CTRL, 0);
+		regmap_write(decoder->regmap, TVP5150_FIFO_OUT_CTRL, 0);
 
 		/* Disable Full Field */
-		tvp5150_write(sd, TVP5150_FULL_FIELD_ENA, 0);
+		regmap_write(decoder->regmap, TVP5150_FULL_FIELD_ENA, 0);
 
 		/* Disable Line modes */
 		for (i = TVP5150_LINE_MODE_INI; i <= TVP5150_LINE_MODE_END; i++)
-			tvp5150_write(sd, i, 0xff);
+			regmap_write(decoder->regmap, i, 0xff);
 	}
 	return 0;
 }
@@ -1184,7 +1178,9 @@ static int tvp5150_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *
 
 static int tvp5150_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
 {
-	return tvp5150_write(sd, reg->reg & 0xff, reg->val & 0xff);
+	struct tvp5150 *decoder = to_tvp5150(sd);
+
+	return regmap_write(decoder->regmap, reg->reg & 0xff, reg->val & 0xff);
 }
 #endif
 
@@ -1291,11 +1287,83 @@ static const struct v4l2_subdev_internal_ops tvp5150_internal_ops = {
 			I2C Client & Driver
  ****************************************************************************/
 
+static const struct regmap_range tvp5150_readable_ranges[] = {
+	{
+		.range_min = TVP5150_VD_IN_SRC_SEL_1,
+		.range_max = TVP5150_AUTOSW_MSK,
+	}, {
+		.range_min = TVP5150_COLOR_KIL_THSH_CTL,
+		.range_max = TVP5150_CONF_SHARED_PIN,
+	}, {
+		.range_min = TVP5150_ACT_VD_CROP_ST_MSB,
+		.range_max = TVP5150_HORIZ_SYNC_START,
+	}, {
+		.range_min = TVP5150_VERT_BLANKING_START,
+		.range_max = TVP5150_INTT_CONFIG_REG_B,
+	}, {
+		.range_min = TVP5150_VIDEO_STD,
+		.range_max = TVP5150_VIDEO_STD,
+	}, {
+		.range_min = TVP5150_CB_GAIN_FACT,
+		.range_max = TVP5150_REV_SELECT,
+	}, {
+		.range_min = TVP5150_MSB_DEV_ID,
+		.range_max = TVP5150_STATUS_REG_5,
+	}, {
+		.range_min = TVP5150_CC_DATA_INI,
+		.range_max = TVP5150_TELETEXT_FIL_ENA,
+	}, {
+		.range_min = TVP5150_INT_STATUS_REG_A,
+		.range_max = TVP5150_FIFO_OUT_CTRL,
+	}, {
+		.range_min = TVP5150_FULL_FIELD_ENA,
+		.range_max = TVP5150_FULL_FIELD_MODE_REG,
+	},
+};
+
+bool tvp5150_volatile_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case TVP5150_VERT_LN_COUNT_MSB:
+	case TVP5150_VERT_LN_COUNT_LSB:
+	case TVP5150_INT_STATUS_REG_A:
+	case TVP5150_INT_STATUS_REG_B:
+	case TVP5150_INT_ACTIVE_REG_B:
+	case TVP5150_STATUS_REG_1:
+	case TVP5150_STATUS_REG_2:
+	case TVP5150_STATUS_REG_3:
+	case TVP5150_STATUS_REG_4:
+	case TVP5150_STATUS_REG_5:
+	/* CC, WSS, VPS, VITC data? */
+	case TVP5150_VBI_FIFO_READ_DATA:
+	case TVP5150_VDP_STATUS_REG:
+	case TVP5150_FIFO_WORD_COUNT:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static const struct regmap_access_table tvp5150_readable_table = {
+	.yes_ranges = tvp5150_readable_ranges,
+	.n_yes_ranges = ARRAY_SIZE(tvp5150_readable_ranges),
+};
+
+static struct regmap_config tvp5150_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = 0xff,
+
+	.cache_type = REGCACHE_RBTREE,
+
+	.rd_table = &tvp5150_readable_table,
+	.volatile_reg = tvp5150_volatile_reg,
+};
+
 static int tvp5150_detect_version(struct tvp5150 *core)
 {
 	struct v4l2_subdev *sd = &core->sd;
 	struct i2c_client *c = v4l2_get_subdevdata(sd);
-	unsigned int i;
 	u8 regs[4];
 	int res;
 
@@ -1303,11 +1371,10 @@ static int tvp5150_detect_version(struct tvp5150 *core)
 	 * Read consequent registers - TVP5150_MSB_DEV_ID, TVP5150_LSB_DEV_ID,
 	 * TVP5150_ROM_MAJOR_VER, TVP5150_ROM_MINOR_VER
 	 */
-	for (i = 0; i < 4; i++) {
-		res = tvp5150_read(sd, TVP5150_MSB_DEV_ID + i);
-		if (res < 0)
-			return res;
-		regs[i] = res;
+	res = regmap_bulk_read(core->regmap, TVP5150_MSB_DEV_ID, regs, 4);
+	if (res < 0) {
+		dev_err(&c->dev, "reading ID registers failed: %d\n", res);
+		return res;
 	}
 
 	core->dev_id = (regs[0] << 8) | regs[1];
@@ -1323,7 +1390,7 @@ static int tvp5150_detect_version(struct tvp5150 *core)
 		dev_info(sd->dev, "tvp5150am1 detected.\n");
 
 		/* ITU-T BT.656.4 timing */
-		tvp5150_write(sd, TVP5150_REV_SELECT, 0);
+		regmap_write(core->regmap, TVP5150_REV_SELECT, 0);
 	} else if (core->dev_id == 0x5151 && core->rom_ver == 0x0100) {
 		dev_info(sd->dev, "tvp5151 detected.\n");
 	} else {
@@ -1470,6 +1537,7 @@ static int tvp5150_probe(struct i2c_client *c,
 	struct tvp5150 *core;
 	struct v4l2_subdev *sd;
 	struct device_node *np = c->dev.of_node;
+	struct regmap *map;
 	int res;
 
 	/* Check if the adapter supports the needed features */
@@ -1485,6 +1553,11 @@ static int tvp5150_probe(struct i2c_client *c,
 	if (!core)
 		return -ENOMEM;
 
+	map = devm_regmap_init_i2c(c, &tvp5150_config);
+	if (IS_ERR(map))
+		return PTR_ERR(map);
+
+	core->regmap = map;
 	sd = &core->sd;
 
 	if (IS_ENABLED(CONFIG_OF) && np) {
-- 
2.17.1

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

* [PATCH 04/22] [media] tvp5150: make use of regmap_update_bits
  2018-06-28 16:20 [PATCH 00/21] TVP5150 fixes and new features Marco Felsch
                   ` (2 preceding siblings ...)
  2018-06-28 16:20 ` [PATCH 03/22] [media] tvp5150: convert register access to regmap Marco Felsch
@ 2018-06-28 16:20 ` Marco Felsch
  2018-06-28 16:20 ` [PATCH 05/22] [media] v4l2-rect.h: add position and equal helpers Marco Felsch
                   ` (18 subsequent siblings)
  22 siblings, 0 replies; 70+ messages in thread
From: Marco Felsch @ 2018-06-28 16:20 UTC (permalink / raw)
  To: mchehab, robh+dt, mark.rutland
  Cc: p.zabel, afshin.nasser, javierm, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

Since commit a27e33e3dd27 ("[media] tvp5150: convert register access to
regmap") the driver supports regmap. Now we can drop the handmade bit
update sequence and move to the regmap provided helpers.

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/media/i2c/tvp5150.c | 34 +++++++++++++---------------------
 1 file changed, 13 insertions(+), 21 deletions(-)

diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index b3c7b65606fd..d150487cc2d1 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -246,8 +246,8 @@ static void tvp5150_selmux(struct v4l2_subdev *sd)
 {
 	int opmode = 0;
 	struct tvp5150 *decoder = to_tvp5150(sd);
+	unsigned int mask, val;
 	int input = 0;
-	int val;
 
 	/* Only tvp5150am1 and tvp5151 have signal generator support */
 	if ((decoder->dev_id == 0x5150 && decoder->rom_ver == 0x0400) ||
@@ -282,17 +282,12 @@ static void tvp5150_selmux(struct v4l2_subdev *sd)
 	 * field indicator (FID) signal on FID/GLCO/VLK/HVLK and set
 	 * INTREQ/GPCL/VBLK to logic 1.
 	 */
-	val = tvp5150_read(sd, TVP5150_MISC_CTL);
-	if (val < 0) {
-		dev_err(sd->dev, "%s: failed with error = %d\n", __func__, val);
-		return;
-	}
-
+	mask = TVP5150_MISC_CTL_GPCL | TVP5150_MISC_CTL_HVLK;
 	if (decoder->input == TVP5150_SVIDEO)
-		val = (val & ~TVP5150_MISC_CTL_GPCL) | TVP5150_MISC_CTL_HVLK;
+		val = TVP5150_MISC_CTL_HVLK;
 	else
-		val = (val & ~TVP5150_MISC_CTL_HVLK) | TVP5150_MISC_CTL_GPCL;
-	regmap_write(decoder->regmap, TVP5150_MISC_CTL, val);
+		val = TVP5150_MISC_CTL_GPCL;
+	regmap_update_bits(decoder->regmap, TVP5150_MISC_CTL, mask, val);
 };
 
 struct i2c_reg_value {
@@ -795,7 +790,9 @@ static int tvp5150_reset(struct v4l2_subdev *sd, u32 val)
 	tvp5150_set_std(sd, decoder->norm);
 
 	if (decoder->mbus_type == V4L2_MBUS_PARALLEL)
-		regmap_write(decoder->regmap, TVP5150_DATA_RATE_SEL, 0x40);
+		/* 8-bit 4:2:2 YUV with discrete sync output */
+		regmap_update_bits(decoder->regmap, TVP5150_DATA_RATE_SEL,
+				   0x7, 0x0);
 
 	return 0;
 };
@@ -1053,27 +1050,22 @@ static const struct media_entity_operations tvp5150_sd_media_ops = {
 static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
 {
 	struct tvp5150 *decoder = to_tvp5150(sd);
-	int val;
-
-	/* Enable or disable the video output signals. */
-	val = tvp5150_read(sd, TVP5150_MISC_CTL);
-	if (val < 0)
-		return val;
+	unsigned int mask, val = 0;
 
-	val &= ~(TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_SYNC_OE |
-		 TVP5150_MISC_CTL_CLOCK_OE);
+	mask = TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_SYNC_OE |
+	       TVP5150_MISC_CTL_CLOCK_OE;
 
 	if (enable) {
 		/*
 		 * Enable the YCbCr and clock outputs. In discrete sync mode
 		 * (non-BT.656) additionally enable the the sync outputs.
 		 */
-		val |= TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_CLOCK_OE;
+		val = TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_CLOCK_OE;
 		if (decoder->mbus_type == V4L2_MBUS_PARALLEL)
 			val |= TVP5150_MISC_CTL_SYNC_OE;
 	}
 
-	regmap_write(decoder->regmap, TVP5150_MISC_CTL, val);
+	regmap_update_bits(decoder->regmap, TVP5150_MISC_CTL, mask, val);
 
 	return 0;
 }
-- 
2.17.1

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

* [PATCH 05/22] [media] v4l2-rect.h: add position and equal helpers
  2018-06-28 16:20 [PATCH 00/21] TVP5150 fixes and new features Marco Felsch
                   ` (3 preceding siblings ...)
  2018-06-28 16:20 ` [PATCH 04/22] [media] tvp5150: make use of regmap_update_bits Marco Felsch
@ 2018-06-28 16:20 ` Marco Felsch
  2018-06-29 14:12   ` Sakari Ailus
  2018-06-28 16:20 ` [PATCH 06/22] [media] tvp5150: add FORMAT_TRY support for get/set selection handlers Marco Felsch
                   ` (17 subsequent siblings)
  22 siblings, 1 reply; 70+ messages in thread
From: Marco Felsch @ 2018-06-28 16:20 UTC (permalink / raw)
  To: mchehab, robh+dt, mark.rutland
  Cc: p.zabel, afshin.nasser, javierm, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

Add two helper functions to check if two rectangles have the same
position (top/left) and if two rectangles equals (same size and
same position).

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 include/media/v4l2-rect.h | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/include/media/v4l2-rect.h b/include/media/v4l2-rect.h
index 595c3ba05f23..1ae25f599a6f 100644
--- a/include/media/v4l2-rect.h
+++ b/include/media/v4l2-rect.h
@@ -82,6 +82,33 @@ static inline bool v4l2_rect_same_size(const struct v4l2_rect *r1,
 	return r1->width == r2->width && r1->height == r2->height;
 }
 
+/**
+ * v4l2_rect_same_position() - return true if r1 has the same position as r2
+ * @r1: rectangle.
+ * @r2: rectangle.
+ *
+ * Return true if both rectangles have the same position
+ */
+static inline bool v4l2_rect_same_position(const struct v4l2_rect *r1,
+					   const struct v4l2_rect *r2)
+{
+	return r1->top == r2->top && r1->left == r2->left;
+
+}
+
+/**
+ * v4l2_rect_equal() - return true if r1 equals r2
+ * @r1: rectangle.
+ * @r2: rectangle.
+ *
+ * Return true if both rectangles have the same size and position.
+ */
+static inline bool v4l2_rect_equal(const struct v4l2_rect *r1,
+				   const struct v4l2_rect *r2)
+{
+	return v4l2_rect_same_size(r1, r2) && v4l2_rect_same_position(r1, r2);
+}
+
 /**
  * v4l2_rect_intersect() - calculate the intersection of two rects.
  * @r: intersection of @r1 and @r2.
-- 
2.17.1

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

* [PATCH 06/22] [media] tvp5150: add FORMAT_TRY support for get/set selection handlers
  2018-06-28 16:20 [PATCH 00/21] TVP5150 fixes and new features Marco Felsch
                   ` (4 preceding siblings ...)
  2018-06-28 16:20 ` [PATCH 05/22] [media] v4l2-rect.h: add position and equal helpers Marco Felsch
@ 2018-06-28 16:20 ` Marco Felsch
  2018-07-31  0:01   ` Mauro Carvalho Chehab
  2018-06-28 16:20 ` [PATCH 07/22] [media] tvp5150: add default format helper Marco Felsch
                   ` (16 subsequent siblings)
  22 siblings, 1 reply; 70+ messages in thread
From: Marco Felsch @ 2018-06-28 16:20 UTC (permalink / raw)
  To: mchehab, robh+dt, mark.rutland
  Cc: p.zabel, afshin.nasser, javierm, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

Since commit 10d5509c8d50 ("[media] v4l2: remove g/s_crop from video ops")
the 'which' field for set/get_selection must be FORMAT_ACTIVE. There is
no way to try different selections. The patch adds a helper function to
select the correct selection memory space (sub-device file handle or
driver state) which will be set/returned.

The TVP5150 AVID will be updated if the 'which' field is FORMAT_ACTIVE
and the requested selection rectangle differs from the already set one.

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/media/i2c/tvp5150.c | 107 ++++++++++++++++++++++++------------
 1 file changed, 73 insertions(+), 34 deletions(-)

diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index d150487cc2d1..29eaf8166f25 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -18,6 +18,7 @@
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-fwnode.h>
 #include <media/v4l2-mc.h>
+#include <media/v4l2-rect.h>
 
 #include "tvp5150_reg.h"
 
@@ -846,20 +847,38 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
 	}
 }
 
+static struct v4l2_rect *
+__tvp5150_get_pad_crop(struct tvp5150 *decoder,
+		       struct v4l2_subdev_pad_config *cfg, unsigned int pad,
+		       enum v4l2_subdev_format_whence which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_crop(&decoder->sd, cfg, pad);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &decoder->rect;
+	default:
+		return NULL;
+	}
+}
+
 static int tvp5150_fill_fmt(struct v4l2_subdev *sd,
 		struct v4l2_subdev_pad_config *cfg,
 		struct v4l2_subdev_format *format)
 {
 	struct v4l2_mbus_framefmt *f;
+	struct v4l2_rect *__crop;
 	struct tvp5150 *decoder = to_tvp5150(sd);
 
 	if (!format || (format->pad != DEMOD_PAD_VID_OUT))
 		return -EINVAL;
 
 	f = &format->format;
+	__crop = __tvp5150_get_pad_crop(decoder, cfg, format->pad,
+					format->which);
 
-	f->width = decoder->rect.width;
-	f->height = decoder->rect.height / 2;
+	f->width = __crop->width;
+	f->height = __crop->height / 2;
 
 	f->code = MEDIA_BUS_FMT_UYVY8_2X8;
 	f->field = V4L2_FIELD_ALTERNATE;
@@ -870,17 +889,51 @@ static int tvp5150_fill_fmt(struct v4l2_subdev *sd,
 	return 0;
 }
 
+unsigned int tvp5150_get_hmax(struct v4l2_subdev *sd)
+{
+	struct tvp5150 *decoder = to_tvp5150(sd);
+	v4l2_std_id std;
+
+	/* Calculate height based on current standard */
+	if (decoder->norm == V4L2_STD_ALL)
+		std = tvp5150_read_std(sd);
+	else
+		std = decoder->norm;
+
+	return (std & V4L2_STD_525_60) ?
+		TVP5150_V_MAX_525_60 : TVP5150_V_MAX_OTHERS;
+}
+
+static inline void
+__tvp5150_set_selection(struct v4l2_subdev *sd, struct v4l2_rect rect)
+{
+	struct tvp5150 *decoder = to_tvp5150(sd);
+	unsigned int hmax = tvp5150_get_hmax(sd);
+
+	regmap_write(decoder->regmap, TVP5150_VERT_BLANKING_START, rect.top);
+	regmap_write(decoder->regmap, TVP5150_VERT_BLANKING_STOP,
+		     rect.top + rect.height - hmax);
+	regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_ST_MSB,
+		     rect.left >> TVP5150_CROP_SHIFT);
+	regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_ST_LSB,
+		     rect.left | (1 << TVP5150_CROP_SHIFT));
+	regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_STP_MSB,
+		     (rect.left + rect.width - TVP5150_MAX_CROP_LEFT) >>
+		     TVP5150_CROP_SHIFT);
+	regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_STP_LSB,
+		     rect.left + rect.width - TVP5150_MAX_CROP_LEFT);
+}
+
 static int tvp5150_set_selection(struct v4l2_subdev *sd,
 				 struct v4l2_subdev_pad_config *cfg,
 				 struct v4l2_subdev_selection *sel)
 {
 	struct tvp5150 *decoder = to_tvp5150(sd);
 	struct v4l2_rect rect = sel->r;
-	v4l2_std_id std;
-	int hmax;
+	struct v4l2_rect *__crop;
+	unsigned int hmax;
 
-	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
-	    sel->target != V4L2_SEL_TGT_CROP)
+	if (sel->target != V4L2_SEL_TGT_CROP)
 		return -EINVAL;
 
 	dev_dbg_lvl(sd->dev, 1, debug, "%s left=%d, top=%d, width=%d, height=%d\n",
@@ -889,17 +942,7 @@ static int tvp5150_set_selection(struct v4l2_subdev *sd,
 	/* tvp5150 has some special limits */
 	rect.left = clamp(rect.left, 0, TVP5150_MAX_CROP_LEFT);
 	rect.top = clamp(rect.top, 0, TVP5150_MAX_CROP_TOP);
-
-	/* Calculate height based on current standard */
-	if (decoder->norm == V4L2_STD_ALL)
-		std = tvp5150_read_std(sd);
-	else
-		std = decoder->norm;
-
-	if (std & V4L2_STD_525_60)
-		hmax = TVP5150_V_MAX_525_60;
-	else
-		hmax = TVP5150_V_MAX_OTHERS;
+	hmax = tvp5150_get_hmax(sd);
 
 	/*
 	 * alignments:
@@ -912,20 +955,18 @@ static int tvp5150_set_selection(struct v4l2_subdev *sd,
 			      hmax - TVP5150_MAX_CROP_TOP - rect.top,
 			      hmax - rect.top, 0, 0);
 
-	regmap_write(decoder->regmap, TVP5150_VERT_BLANKING_START, rect.top);
-	regmap_write(decoder->regmap, TVP5150_VERT_BLANKING_STOP,
-		      rect.top + rect.height - hmax);
-	regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_ST_MSB,
-		      rect.left >> TVP5150_CROP_SHIFT);
-	regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_ST_LSB,
-		      rect.left | (1 << TVP5150_CROP_SHIFT));
-	regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_STP_MSB,
-		      (rect.left + rect.width - TVP5150_MAX_CROP_LEFT) >>
-		      TVP5150_CROP_SHIFT);
-	regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_STP_LSB,
-		      rect.left + rect.width - TVP5150_MAX_CROP_LEFT);
+	__crop = __tvp5150_get_pad_crop(decoder, cfg, sel->pad,
+						  sel->which);
+
+	/*
+	 * Update output image size if the selection (crop) rectangle size or
+	 * position has been modified.
+	 */
+	if (!v4l2_rect_equal(&rect, __crop))
+		if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+			__tvp5150_set_selection(sd, rect);
 
-	decoder->rect = rect;
+	*__crop = rect;
 
 	return 0;
 }
@@ -937,9 +978,6 @@ static int tvp5150_get_selection(struct v4l2_subdev *sd,
 	struct tvp5150 *decoder = container_of(sd, struct tvp5150, sd);
 	v4l2_std_id std;
 
-	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
-		return -EINVAL;
-
 	switch (sel->target) {
 	case V4L2_SEL_TGT_CROP_BOUNDS:
 	case V4L2_SEL_TGT_CROP_DEFAULT:
@@ -958,7 +996,8 @@ static int tvp5150_get_selection(struct v4l2_subdev *sd,
 			sel->r.height = TVP5150_V_MAX_OTHERS;
 		return 0;
 	case V4L2_SEL_TGT_CROP:
-		sel->r = decoder->rect;
+		sel->r = *__tvp5150_get_pad_crop(decoder, cfg, sel->pad,
+						      sel->which);
 		return 0;
 	default:
 		return -EINVAL;
-- 
2.17.1

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

* [PATCH 07/22] [media] tvp5150: add default format helper
  2018-06-28 16:20 [PATCH 00/21] TVP5150 fixes and new features Marco Felsch
                   ` (5 preceding siblings ...)
  2018-06-28 16:20 ` [PATCH 06/22] [media] tvp5150: add FORMAT_TRY support for get/set selection handlers Marco Felsch
@ 2018-06-28 16:20 ` Marco Felsch
  2018-06-28 16:20 ` [PATCH 08/22] [media] tvp5150: trigger autodetection on subdev open to reset cropping Marco Felsch
                   ` (15 subsequent siblings)
  22 siblings, 0 replies; 70+ messages in thread
From: Marco Felsch @ 2018-06-28 16:20 UTC (permalink / raw)
  To: mchehab, robh+dt, mark.rutland
  Cc: p.zabel, afshin.nasser, javierm, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

The patch adds three macros to bundle the mbus_framefmt default
values and a helper function to set the the default crop and
mbus_framefmt values.

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/media/i2c/tvp5150.c | 42 ++++++++++++++++++++++---------------
 1 file changed, 25 insertions(+), 17 deletions(-)

diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index 29eaf8166f25..c73536cfcc62 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -28,6 +28,9 @@
 #define TVP5150_MAX_CROP_LEFT	511
 #define TVP5150_MAX_CROP_TOP	127
 #define TVP5150_CROP_SHIFT	2
+#define TVP5150_MBUS_FMT	MEDIA_BUS_FMT_UYVY8_2X8
+#define TVP5150_FIELD		V4L2_FIELD_ALTERNATE
+#define TVP5150_COLORSPACE	V4L2_COLORSPACE_SMPTE170M
 
 MODULE_DESCRIPTION("Texas Instruments TVP5150A/TVP5150AM1/TVP5151 video decoder driver");
 MODULE_AUTHOR("Mauro Carvalho Chehab");
@@ -847,6 +850,18 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
 	}
 }
 
+static void tvp5150_set_default(v4l2_std_id std, struct v4l2_rect *crop)
+{
+	/* Default is no cropping */
+	crop->top = 0;
+	crop->left = 0;
+	crop->width = TVP5150_H_MAX;
+	if (std & V4L2_STD_525_60)
+		crop->height = TVP5150_V_MAX_525_60;
+	else
+		crop->height = TVP5150_V_MAX_OTHERS;
+}
+
 static struct v4l2_rect *
 __tvp5150_get_pad_crop(struct tvp5150 *decoder,
 		       struct v4l2_subdev_pad_config *cfg, unsigned int pad,
@@ -863,8 +878,8 @@ __tvp5150_get_pad_crop(struct tvp5150 *decoder,
 }
 
 static int tvp5150_fill_fmt(struct v4l2_subdev *sd,
-		struct v4l2_subdev_pad_config *cfg,
-		struct v4l2_subdev_format *format)
+			    struct v4l2_subdev_pad_config *cfg,
+			    struct v4l2_subdev_format *format)
 {
 	struct v4l2_mbus_framefmt *f;
 	struct v4l2_rect *__crop;
@@ -880,12 +895,12 @@ static int tvp5150_fill_fmt(struct v4l2_subdev *sd,
 	f->width = __crop->width;
 	f->height = __crop->height / 2;
 
-	f->code = MEDIA_BUS_FMT_UYVY8_2X8;
-	f->field = V4L2_FIELD_ALTERNATE;
-	f->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	f->code = TVP5150_MBUS_FMT;
+	f->field = TVP5150_FIELD;
+	f->colorspace = TVP5150_COLORSPACE;
 
 	dev_dbg_lvl(sd->dev, 1, debug, "width = %d, height = %d\n", f->width,
-			f->height);
+		    f->height);
 	return 0;
 }
 
@@ -1026,7 +1041,7 @@ static int tvp5150_enum_mbus_code(struct v4l2_subdev *sd,
 	if (code->pad || code->index)
 		return -EINVAL;
 
-	code->code = MEDIA_BUS_FMT_UYVY8_2X8;
+	code->code = TVP5150_MBUS_FMT;
 	return 0;
 }
 
@@ -1036,10 +1051,10 @@ static int tvp5150_enum_frame_size(struct v4l2_subdev *sd,
 {
 	struct tvp5150 *decoder = to_tvp5150(sd);
 
-	if (fse->index >= 8 || fse->code != MEDIA_BUS_FMT_UYVY8_2X8)
+	if (fse->index >= 8 || fse->code != TVP5150_MBUS_FMT)
 		return -EINVAL;
 
-	fse->code = MEDIA_BUS_FMT_UYVY8_2X8;
+	fse->code = TVP5150_MBUS_FMT;
 	fse->min_width = decoder->rect.width;
 	fse->max_width = decoder->rect.width;
 	fse->min_height = decoder->rect.height / 2;
@@ -1650,14 +1665,7 @@ static int tvp5150_probe(struct i2c_client *c,
 		goto err;
 	}
 
-	/* Default is no cropping */
-	core->rect.top = 0;
-	if (tvp5150_read_std(sd) & V4L2_STD_525_60)
-		core->rect.height = TVP5150_V_MAX_525_60;
-	else
-		core->rect.height = TVP5150_V_MAX_OTHERS;
-	core->rect.left = 0;
-	core->rect.width = TVP5150_H_MAX;
+	tvp5150_set_default(tvp5150_read_std(sd), &core->rect);
 
 	tvp5150_reset(sd, 0);	/* Calls v4l2_ctrl_handler_setup() */
 
-- 
2.17.1

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

* [PATCH 08/22] [media] tvp5150: trigger autodetection on subdev open to reset cropping
  2018-06-28 16:20 [PATCH 00/21] TVP5150 fixes and new features Marco Felsch
                   ` (6 preceding siblings ...)
  2018-06-28 16:20 ` [PATCH 07/22] [media] tvp5150: add default format helper Marco Felsch
@ 2018-06-28 16:20 ` Marco Felsch
  2018-06-28 16:20 ` [PATCH 09/22] [media] tvp5150: fix standard autodetection Marco Felsch
                   ` (14 subsequent siblings)
  22 siblings, 0 replies; 70+ messages in thread
From: Marco Felsch @ 2018-06-28 16:20 UTC (permalink / raw)
  To: mchehab, robh+dt, mark.rutland
  Cc: p.zabel, afshin.nasser, javierm, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

From: Philipp Zabel <p.zabel@pengutronix.de>

If cropping isn't set explicitly by userspace, reset it to the maximum
possible rectangle in subdevice open if a standard change is detected.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
[m.felsch@pengutronix.de: move code from internal_ops.open() to pad_ops.init_cfg()]
[m.felsch@pengutronix.de: make use of tvp5150_set_default() helper]
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/media/i2c/tvp5150.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index c73536cfcc62..dbfc56c87434 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -55,6 +55,7 @@ struct tvp5150 {
 	struct regmap *regmap;
 
 	v4l2_std_id norm;	/* Current set standard */
+	v4l2_std_id detected_norm;
 	u32 input;
 	u32 output;
 	int enable;
@@ -1034,6 +1035,27 @@ static int tvp5150_g_mbus_config(struct v4l2_subdev *sd,
 /****************************************************************************
 			V4L2 subdev pad ops
  ****************************************************************************/
+static int tvp5150_init_cfg(struct v4l2_subdev *sd,
+			    struct v4l2_subdev_pad_config *cfg)
+{
+	struct tvp5150 *decoder = to_tvp5150(sd);
+	v4l2_std_id std;
+
+	/*
+	 * Reset selection to maximum on subdev_open() if autodetection is on
+	 * and a standard change is detected.
+	 */
+	if (decoder->norm == V4L2_STD_ALL) {
+		std = tvp5150_read_std(sd);
+		if (std != decoder->detected_norm) {
+			decoder->detected_norm = std;
+			tvp5150_set_default(std, &decoder->rect);
+		}
+	}
+
+	return 0;
+}
+
 static int tvp5150_enum_mbus_code(struct v4l2_subdev *sd,
 		struct v4l2_subdev_pad_config *cfg,
 		struct v4l2_subdev_mbus_code_enum *code)
@@ -1308,6 +1330,7 @@ static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = {
 };
 
 static const struct v4l2_subdev_pad_ops tvp5150_pad_ops = {
+	.init_cfg = tvp5150_init_cfg,
 	.enum_mbus_code = tvp5150_enum_mbus_code,
 	.enum_frame_size = tvp5150_enum_frame_size,
 	.set_fmt = tvp5150_fill_fmt,
@@ -1640,6 +1663,7 @@ static int tvp5150_probe(struct i2c_client *c,
 		return res;
 
 	core->norm = V4L2_STD_ALL;	/* Default is autodetect */
+	core->detected_norm = V4L2_STD_UNKNOWN;
 	core->input = TVP5150_COMPOSITE1;
 	core->enable = true;
 
-- 
2.17.1

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

* [PATCH 09/22] [media] tvp5150: fix standard autodetection
  2018-06-28 16:20 [PATCH 00/21] TVP5150 fixes and new features Marco Felsch
                   ` (7 preceding siblings ...)
  2018-06-28 16:20 ` [PATCH 08/22] [media] tvp5150: trigger autodetection on subdev open to reset cropping Marco Felsch
@ 2018-06-28 16:20 ` Marco Felsch
  2018-06-28 16:20 ` [PATCH 10/22] [media] tvp5150: split reset/enable routine Marco Felsch
                   ` (13 subsequent siblings)
  22 siblings, 0 replies; 70+ messages in thread
From: Marco Felsch @ 2018-06-28 16:20 UTC (permalink / raw)
  To: mchehab, robh+dt, mark.rutland
  Cc: p.zabel, afshin.nasser, javierm, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

From: Philipp Zabel <p.zabel@pengutronix.de>

Make sure to not overwrite decoder->norm when setting the standard
in hardware, but only when instructed by V4L2 API calls.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/media/i2c/tvp5150.c | 56 ++++++++++++++++++++-----------------
 1 file changed, 31 insertions(+), 25 deletions(-)

diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index dbfc56c87434..895bc2bfb1d1 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -731,8 +731,6 @@ static int tvp5150_set_std(struct v4l2_subdev *sd, v4l2_std_id std)
 	struct tvp5150 *decoder = to_tvp5150(sd);
 	int fmt = 0;
 
-	decoder->norm = std;
-
 	/* First tests should be against specific std */
 
 	if (std == V4L2_STD_NTSC_443) {
@@ -769,13 +767,37 @@ static int tvp5150_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
 	else
 		decoder->rect.height = TVP5150_V_MAX_OTHERS;
 
+	decoder->norm = std;
 
 	return tvp5150_set_std(sd, std);
 }
 
+static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
+{
+	int val = tvp5150_read(sd, TVP5150_STATUS_REG_5);
+
+	switch (val & 0x0F) {
+	case 0x01:
+		return V4L2_STD_NTSC;
+	case 0x03:
+		return V4L2_STD_PAL;
+	case 0x05:
+		return V4L2_STD_PAL_M;
+	case 0x07:
+		return V4L2_STD_PAL_N | V4L2_STD_PAL_Nc;
+	case 0x09:
+		return V4L2_STD_NTSC_443;
+	case 0xb:
+		return V4L2_STD_SECAM;
+	default:
+		return V4L2_STD_UNKNOWN;
+	}
+}
+
 static int tvp5150_reset(struct v4l2_subdev *sd, u32 val)
 {
 	struct tvp5150 *decoder = to_tvp5150(sd);
+	v4l2_std_id std;
 
 	/* Initializes TVP5150 to its default values */
 	tvp5150_write_inittab(sd, tvp5150_init_default);
@@ -792,7 +814,13 @@ static int tvp5150_reset(struct v4l2_subdev *sd, u32 val)
 	/* Initialize image preferences */
 	v4l2_ctrl_handler_setup(&decoder->hdl);
 
-	tvp5150_set_std(sd, decoder->norm);
+	if (decoder->norm == V4L2_STD_ALL)
+		std = tvp5150_read_std(sd);
+	else
+		std = decoder->norm;
+
+	/* Disable autoswitch mode */
+	tvp5150_set_std(sd, std);
 
 	if (decoder->mbus_type == V4L2_MBUS_PARALLEL)
 		/* 8-bit 4:2:2 YUV with discrete sync output */
@@ -829,28 +857,6 @@ static int tvp5150_s_ctrl(struct v4l2_ctrl *ctrl)
 	return -EINVAL;
 }
 
-static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
-{
-	int val = tvp5150_read(sd, TVP5150_STATUS_REG_5);
-
-	switch (val & 0x0F) {
-	case 0x01:
-		return V4L2_STD_NTSC;
-	case 0x03:
-		return V4L2_STD_PAL;
-	case 0x05:
-		return V4L2_STD_PAL_M;
-	case 0x07:
-		return V4L2_STD_PAL_N | V4L2_STD_PAL_Nc;
-	case 0x09:
-		return V4L2_STD_NTSC_443;
-	case 0xb:
-		return V4L2_STD_SECAM;
-	default:
-		return V4L2_STD_UNKNOWN;
-	}
-}
-
 static void tvp5150_set_default(v4l2_std_id std, struct v4l2_rect *crop)
 {
 	/* Default is no cropping */
-- 
2.17.1

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

* [PATCH 10/22] [media] tvp5150: split reset/enable routine
  2018-06-28 16:20 [PATCH 00/21] TVP5150 fixes and new features Marco Felsch
                   ` (8 preceding siblings ...)
  2018-06-28 16:20 ` [PATCH 09/22] [media] tvp5150: fix standard autodetection Marco Felsch
@ 2018-06-28 16:20 ` Marco Felsch
  2018-06-28 16:20 ` [PATCH 11/22] [media] tvp5150: remove pin configuration from initialization tables Marco Felsch
                   ` (12 subsequent siblings)
  22 siblings, 0 replies; 70+ messages in thread
From: Marco Felsch @ 2018-06-28 16:20 UTC (permalink / raw)
  To: mchehab, robh+dt, mark.rutland
  Cc: p.zabel, afshin.nasser, javierm, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

From: Philipp Zabel <p.zabel@pengutronix.de>

To trigger standard autodetection only the reset part of the routine
is necessary during probe(). Split this out to make it callable on its own.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
[m.felsch@pengutronix.de: adapt commit message]
[m.felsch@pengutronix.de: add tvp5150_enable() to tvp5150_s_stream()]
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/media/i2c/tvp5150.c | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index 895bc2bfb1d1..284694c21556 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -796,9 +796,6 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
 
 static int tvp5150_reset(struct v4l2_subdev *sd, u32 val)
 {
-	struct tvp5150 *decoder = to_tvp5150(sd);
-	v4l2_std_id std;
-
 	/* Initializes TVP5150 to its default values */
 	tvp5150_write_inittab(sd, tvp5150_init_default);
 
@@ -808,12 +805,20 @@ static int tvp5150_reset(struct v4l2_subdev *sd, u32 val)
 	/* Selects decoder input */
 	tvp5150_selmux(sd);
 
-	/* Initializes TVP5150 to stream enabled values */
-	tvp5150_write_inittab(sd, tvp5150_init_enable);
-
 	/* Initialize image preferences */
 	v4l2_ctrl_handler_setup(&decoder->hdl);
 
+	return 0;
+}
+
+static int tvp5150_enable(struct v4l2_subdev *sd)
+{
+	struct tvp5150 *decoder = to_tvp5150(sd);
+	v4l2_std_id std;
+
+	/* Initializes TVP5150 to stream enabled values */
+	tvp5150_write_inittab(sd, tvp5150_init_enable);
+
 	if (decoder->norm == V4L2_STD_ALL)
 		std = tvp5150_read_std(sd);
 	else
@@ -1138,6 +1143,8 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
 	       TVP5150_MISC_CTL_CLOCK_OE;
 
 	if (enable) {
+		tvp5150_enable(sd);
+
 		/*
 		 * Enable the YCbCr and clock outputs. In discrete sync mode
 		 * (non-BT.656) additionally enable the the sync outputs.
-- 
2.17.1

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

* [PATCH 11/22] [media] tvp5150: remove pin configuration from initialization tables
  2018-06-28 16:20 [PATCH 00/21] TVP5150 fixes and new features Marco Felsch
                   ` (9 preceding siblings ...)
  2018-06-28 16:20 ` [PATCH 10/22] [media] tvp5150: split reset/enable routine Marco Felsch
@ 2018-06-28 16:20 ` Marco Felsch
  2018-06-28 16:20 ` [PATCH 12/22] [media] tvp5150: Add sync lock interrupt handling Marco Felsch
                   ` (11 subsequent siblings)
  22 siblings, 0 replies; 70+ messages in thread
From: Marco Felsch @ 2018-06-28 16:20 UTC (permalink / raw)
  To: mchehab, robh+dt, mark.rutland
  Cc: p.zabel, afshin.nasser, javierm, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

From: Philipp Zabel <p.zabel@pengutronix.de>

To allow optional interrupt support, we want to configure the pin settings
dynamically. Move those register accesses out of the static initialization
tables.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
[m.felsch@pengutronix.de: drop init_default register remove]
[m.felsch@pengutronix.de: fix regmap access during reset()]
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/media/i2c/tvp5150.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index 284694c21556..c66a962d873a 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -438,9 +438,7 @@ static const struct i2c_reg_value tvp5150_init_default[] = {
 
 /* Default values as sugested at TVP5150AM1 datasheet */
 static const struct i2c_reg_value tvp5150_init_enable[] = {
-	{
-		TVP5150_CONF_SHARED_PIN, 2
-	}, {	/* Automatic offset and AGC enabled */
+	{	/* Automatic offset and AGC enabled */
 		TVP5150_ANAL_CHL_CTL, 0x15
 	}, {	/* Activate YCrCb output 0x9 or 0xd ? */
 		TVP5150_MISC_CTL, TVP5150_MISC_CTL_GPCL |
@@ -796,9 +794,15 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
 
 static int tvp5150_reset(struct v4l2_subdev *sd, u32 val)
 {
+	struct tvp5150 *decoder = to_tvp5150(sd);
+	struct regmap *map = decoder->regmap;
+
 	/* Initializes TVP5150 to its default values */
 	tvp5150_write_inittab(sd, tvp5150_init_default);
 
+	/* Configure pins: FID, VSYNC, GPCL/VBLK, SCLK */
+	regmap_write(map, TVP5150_CONF_SHARED_PIN, 0x2);
+
 	/* Initializes VDP registers */
 	tvp5150_vdp_init(sd);
 
-- 
2.17.1

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

* [PATCH 12/22] [media] tvp5150: Add sync lock interrupt handling
  2018-06-28 16:20 [PATCH 00/21] TVP5150 fixes and new features Marco Felsch
                   ` (10 preceding siblings ...)
  2018-06-28 16:20 ` [PATCH 11/22] [media] tvp5150: remove pin configuration from initialization tables Marco Felsch
@ 2018-06-28 16:20 ` Marco Felsch
  2018-06-28 16:20 ` [PATCH 13/22] [media] tvp5150: disable output while signal not locked Marco Felsch
                   ` (10 subsequent siblings)
  22 siblings, 0 replies; 70+ messages in thread
From: Marco Felsch @ 2018-06-28 16:20 UTC (permalink / raw)
  To: mchehab, robh+dt, mark.rutland
  Cc: p.zabel, afshin.nasser, javierm, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

From: Philipp Zabel <p.zabel@pengutronix.de>

This patch adds an optional interrupt handler to handle the sync
lock interrupt and sync lock status.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
[m.felsch@pengutronix.de: move added .g_std callback to separate patch]
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/media/i2c/tvp5150.c     | 63 +++++++++++++++++++++++++++++++--
 drivers/media/i2c/tvp5150_reg.h |  3 ++
 2 files changed, 63 insertions(+), 3 deletions(-)

diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index c66a962d873a..d8bdbedd8826 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -10,6 +10,7 @@
 #include <linux/videodev2.h>
 #include <linux/delay.h>
 #include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/of_graph.h>
 #include <linux/regmap.h>
@@ -53,12 +54,14 @@ struct tvp5150 {
 	struct v4l2_ctrl_handler hdl;
 	struct v4l2_rect rect;
 	struct regmap *regmap;
+	int irq;
 
 	v4l2_std_id norm;	/* Current set standard */
 	v4l2_std_id detected_norm;
 	u32 input;
 	u32 output;
 	int enable;
+	bool lock;
 
 	u16 dev_id;
 	u16 rom_ver;
@@ -792,6 +795,33 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
 	}
 }
 
+static irqreturn_t tvp5150_isr(int irq, void *dev_id)
+{
+	struct tvp5150 *decoder = dev_id;
+	struct regmap *map = decoder->regmap;
+	unsigned int active = 0, status = 0;
+
+	regmap_read(map, TVP5150_INT_STATUS_REG_A, &status);
+	if (status) {
+		regmap_write(map, TVP5150_INT_STATUS_REG_A, status);
+
+		if (status & TVP5150_INT_A_LOCK)
+			decoder->lock = !!(status & TVP5150_INT_A_LOCK_STATUS);
+
+		return IRQ_HANDLED;
+	}
+
+	regmap_read(map, TVP5150_INT_ACTIVE_REG_B, &active);
+	if (active) {
+		status = 0;
+		regmap_read(map, TVP5150_INT_STATUS_REG_B, &status);
+		if (status)
+			regmap_write(map, TVP5150_INT_RESET_REG_B, status);
+	}
+
+	return IRQ_HANDLED;
+}
+
 static int tvp5150_reset(struct v4l2_subdev *sd, u32 val)
 {
 	struct tvp5150 *decoder = to_tvp5150(sd);
@@ -800,8 +830,19 @@ static int tvp5150_reset(struct v4l2_subdev *sd, u32 val)
 	/* Initializes TVP5150 to its default values */
 	tvp5150_write_inittab(sd, tvp5150_init_default);
 
-	/* Configure pins: FID, VSYNC, GPCL/VBLK, SCLK */
-	regmap_write(map, TVP5150_CONF_SHARED_PIN, 0x2);
+	if (decoder->irq) {
+		/* Configure pins: FID, VSYNC, INTREQ, SCLK */
+		regmap_write(map, TVP5150_CONF_SHARED_PIN, 0x0);
+		/* Set interrupt polarity to active high */
+		regmap_write(map, TVP5150_INT_CONF, TVP5150_VDPOE | 0x1);
+		regmap_write(map, TVP5150_INTT_CONFIG_REG_B, 0x1);
+	} else {
+		/* Configure pins: FID, VSYNC, GPCL/VBLK, SCLK */
+		regmap_write(map, TVP5150_CONF_SHARED_PIN, 0x2);
+		/* Keep interrupt polarity active low */
+		regmap_write(map, TVP5150_INT_CONF, TVP5150_VDPOE);
+		regmap_write(map, TVP5150_INTT_CONFIG_REG_B, 0x0);
+	}
 
 	/* Initializes VDP registers */
 	tvp5150_vdp_init(sd);
@@ -1141,7 +1182,7 @@ static const struct media_entity_operations tvp5150_sd_media_ops = {
 static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
 {
 	struct tvp5150 *decoder = to_tvp5150(sd);
-	unsigned int mask, val = 0;
+	unsigned int mask, val = 0, int_val = 0;
 
 	mask = TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_SYNC_OE |
 	       TVP5150_MISC_CTL_CLOCK_OE;
@@ -1156,9 +1197,15 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
 		val = TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_CLOCK_OE;
 		if (decoder->mbus_type == V4L2_MBUS_PARALLEL)
 			val |= TVP5150_MISC_CTL_SYNC_OE;
+
+		int_val = TVP5150_INT_A_LOCK;
 	}
 
 	regmap_update_bits(decoder->regmap, TVP5150_MISC_CTL, mask, val);
+	if (decoder->irq)
+		/* Enable / Disable lock interrupt */
+		regmap_update_bits(decoder->regmap, TVP5150_INT_ENABLE_REG_A,
+				   TVP5150_INT_A_LOCK, int_val);
 
 	return 0;
 }
@@ -1708,7 +1755,17 @@ static int tvp5150_probe(struct i2c_client *c,
 
 	tvp5150_set_default(tvp5150_read_std(sd), &core->rect);
 
+	core->irq = c->irq;
 	tvp5150_reset(sd, 0);	/* Calls v4l2_ctrl_handler_setup() */
+	if (c->irq) {
+		res = devm_request_threaded_irq(&c->dev, c->irq, NULL,
+						tvp5150_isr, IRQF_TRIGGER_HIGH |
+						IRQF_ONESHOT, "tvp5150", core);
+		if (res)
+			return res;
+	} else {
+		core->lock = true;
+	}
 
 	res = v4l2_async_register_subdev(sd);
 	if (res < 0)
diff --git a/drivers/media/i2c/tvp5150_reg.h b/drivers/media/i2c/tvp5150_reg.h
index d3a764cae1a0..9088186c24d1 100644
--- a/drivers/media/i2c/tvp5150_reg.h
+++ b/drivers/media/i2c/tvp5150_reg.h
@@ -125,8 +125,11 @@
 #define TVP5150_TELETEXT_FIL_ENA    0xbb /* Teletext filter enable */
 /* Reserved	BCh-BFh */
 #define TVP5150_INT_STATUS_REG_A    0xc0 /* Interrupt status register A */
+#define   TVP5150_INT_A_LOCK_STATUS BIT(7)
+#define   TVP5150_INT_A_LOCK        BIT(6)
 #define TVP5150_INT_ENABLE_REG_A    0xc1 /* Interrupt enable register A */
 #define TVP5150_INT_CONF            0xc2 /* Interrupt configuration */
+#define   TVP5150_VDPOE             BIT(2)
 #define TVP5150_VDP_CONF_RAM_DATA   0xc3 /* VDP configuration RAM data */
 #define TVP5150_CONF_RAM_ADDR_LOW   0xc4 /* Configuration RAM address low byte */
 #define TVP5150_CONF_RAM_ADDR_HIGH  0xc5 /* Configuration RAM address high byte */
-- 
2.17.1

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

* [PATCH 13/22] [media] tvp5150: disable output while signal not locked
  2018-06-28 16:20 [PATCH 00/21] TVP5150 fixes and new features Marco Felsch
                   ` (11 preceding siblings ...)
  2018-06-28 16:20 ` [PATCH 12/22] [media] tvp5150: Add sync lock interrupt handling Marco Felsch
@ 2018-06-28 16:20 ` Marco Felsch
  2018-07-30 18:00   ` Mauro Carvalho Chehab
  2018-06-28 16:20 ` [PATCH 14/22] [media] tvp5150: issue source change events Marco Felsch
                   ` (9 subsequent siblings)
  22 siblings, 1 reply; 70+ messages in thread
From: Marco Felsch @ 2018-06-28 16:20 UTC (permalink / raw)
  To: mchehab, robh+dt, mark.rutland
  Cc: p.zabel, afshin.nasser, javierm, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

From: Philipp Zabel <p.zabel@pengutronix.de>

To avoid short frames on stream start, keep output pins at high impedance
while we are not properly locked onto the input signal.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/media/i2c/tvp5150.c | 39 ++++++++++++++++++++++++++-----------
 1 file changed, 28 insertions(+), 11 deletions(-)

diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index d8bdbedd8826..27cfd08be3d2 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -60,6 +60,7 @@ struct tvp5150 {
 	v4l2_std_id detected_norm;
 	u32 input;
 	u32 output;
+	u32 oe;
 	int enable;
 	bool lock;
 
@@ -799,14 +800,20 @@ static irqreturn_t tvp5150_isr(int irq, void *dev_id)
 {
 	struct tvp5150 *decoder = dev_id;
 	struct regmap *map = decoder->regmap;
-	unsigned int active = 0, status = 0;
+	unsigned int mask, active = 0, status = 0;
+
+	mask = TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_SYNC_OE |
+	       TVP5150_MISC_CTL_CLOCK_OE;
 
 	regmap_read(map, TVP5150_INT_STATUS_REG_A, &status);
 	if (status) {
 		regmap_write(map, TVP5150_INT_STATUS_REG_A, status);
 
-		if (status & TVP5150_INT_A_LOCK)
+		if (status & TVP5150_INT_A_LOCK) {
 			decoder->lock = !!(status & TVP5150_INT_A_LOCK_STATUS);
+			regmap_update_bits(map, TVP5150_MISC_CTL, mask,
+					   decoder->lock ? decoder->oe : 0);
+		}
 
 		return IRQ_HANDLED;
 	}
@@ -872,10 +879,26 @@ static int tvp5150_enable(struct v4l2_subdev *sd)
 	/* Disable autoswitch mode */
 	tvp5150_set_std(sd, std);
 
-	if (decoder->mbus_type == V4L2_MBUS_PARALLEL)
+	/*
+	 * Enable the YCbCr and clock outputs. In discrete sync mode
+	 * (non-BT.656) additionally enable the the sync outputs.
+	 */
+	switch (decoder->mbus_type) {
+	case V4L2_MBUS_PARALLEL:
 		/* 8-bit 4:2:2 YUV with discrete sync output */
 		regmap_update_bits(decoder->regmap, TVP5150_DATA_RATE_SEL,
 				   0x7, 0x0);
+		decoder->oe = TVP5150_MISC_CTL_YCBCR_OE |
+			      TVP5150_MISC_CTL_CLOCK_OE |
+			      TVP5150_MISC_CTL_SYNC_OE;
+		break;
+	case V4L2_MBUS_BT656:
+		decoder->oe = TVP5150_MISC_CTL_YCBCR_OE |
+			      TVP5150_MISC_CTL_CLOCK_OE;
+		break;
+	default:
+		return -EINVAL;
+	}
 
 	return 0;
 };
@@ -1190,14 +1213,8 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
 	if (enable) {
 		tvp5150_enable(sd);
 
-		/*
-		 * Enable the YCbCr and clock outputs. In discrete sync mode
-		 * (non-BT.656) additionally enable the the sync outputs.
-		 */
-		val = TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_CLOCK_OE;
-		if (decoder->mbus_type == V4L2_MBUS_PARALLEL)
-			val |= TVP5150_MISC_CTL_SYNC_OE;
-
+		/* Enable outputs if decoder is locked */
+		val = decoder->lock ? decoder->oe : 0;
 		int_val = TVP5150_INT_A_LOCK;
 	}
 
-- 
2.17.1

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

* [PATCH 14/22] [media] tvp5150: issue source change events
  2018-06-28 16:20 [PATCH 00/21] TVP5150 fixes and new features Marco Felsch
                   ` (12 preceding siblings ...)
  2018-06-28 16:20 ` [PATCH 13/22] [media] tvp5150: disable output while signal not locked Marco Felsch
@ 2018-06-28 16:20 ` Marco Felsch
  2018-06-28 16:20 ` [PATCH 15/22] [media] tvp5150: add sync lock/loss signal debug messages Marco Felsch
                   ` (8 subsequent siblings)
  22 siblings, 0 replies; 70+ messages in thread
From: Marco Felsch @ 2018-06-28 16:20 UTC (permalink / raw)
  To: mchehab, robh+dt, mark.rutland
  Cc: p.zabel, afshin.nasser, javierm, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

From: Philipp Zabel <p.zabel@pengutronix.de>

Issue a V4L2_EVENT_SOURCE_CHANGE notification when the TVP5150 locks
onto a signal and when it loses the lock.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
[m.felsch@pengutronix.de: partly mainline part port]
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/media/i2c/tvp5150.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index 27cfd08be3d2..6296c68ac816 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -796,6 +796,11 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
 	}
 }
 
+static const struct v4l2_event tvp5150_ev_fmt = {
+	.type = V4L2_EVENT_SOURCE_CHANGE,
+	.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
+};
+
 static irqreturn_t tvp5150_isr(int irq, void *dev_id)
 {
 	struct tvp5150 *decoder = dev_id;
@@ -811,6 +816,7 @@ static irqreturn_t tvp5150_isr(int irq, void *dev_id)
 
 		if (status & TVP5150_INT_A_LOCK) {
 			decoder->lock = !!(status & TVP5150_INT_A_LOCK_STATUS);
+			v4l2_subdev_notify_event(&decoder->sd, &tvp5150_ev_fmt);
 			regmap_update_bits(map, TVP5150_MISC_CTL, mask,
 					   decoder->lock ? decoder->oe : 0);
 		}
@@ -1216,6 +1222,7 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
 		/* Enable outputs if decoder is locked */
 		val = decoder->lock ? decoder->oe : 0;
 		int_val = TVP5150_INT_A_LOCK;
+		v4l2_subdev_notify_event(&decoder->sd, &tvp5150_ev_fmt);
 	}
 
 	regmap_update_bits(decoder->regmap, TVP5150_MISC_CTL, mask, val);
@@ -1432,7 +1439,6 @@ static const struct v4l2_subdev_internal_ops tvp5150_internal_ops = {
 	.registered = tvp5150_registered,
 };
 
-
 /****************************************************************************
 			I2C Client & Driver
  ****************************************************************************/
-- 
2.17.1

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

* [PATCH 15/22] [media] tvp5150: add sync lock/loss signal debug messages
  2018-06-28 16:20 [PATCH 00/21] TVP5150 fixes and new features Marco Felsch
                   ` (13 preceding siblings ...)
  2018-06-28 16:20 ` [PATCH 14/22] [media] tvp5150: issue source change events Marco Felsch
@ 2018-06-28 16:20 ` Marco Felsch
  2018-06-28 16:20 ` [PATCH 16/22] [media] tvp5150: add querystd Marco Felsch
                   ` (7 subsequent siblings)
  22 siblings, 0 replies; 70+ messages in thread
From: Marco Felsch @ 2018-06-28 16:20 UTC (permalink / raw)
  To: mchehab, robh+dt, mark.rutland
  Cc: p.zabel, afshin.nasser, javierm, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

From: Philipp Zabel <p.zabel@pengutronix.de>

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/media/i2c/tvp5150.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index 6296c68ac816..99d887936ea0 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -816,6 +816,9 @@ static irqreturn_t tvp5150_isr(int irq, void *dev_id)
 
 		if (status & TVP5150_INT_A_LOCK) {
 			decoder->lock = !!(status & TVP5150_INT_A_LOCK_STATUS);
+			dev_dbg_lvl(decoder->sd.dev, 1, debug,
+				    "sync lo%s signal\n",
+				    decoder->lock ? "ck" : "ss");
 			v4l2_subdev_notify_event(&decoder->sd, &tvp5150_ev_fmt);
 			regmap_update_bits(map, TVP5150_MISC_CTL, mask,
 					   decoder->lock ? decoder->oe : 0);
-- 
2.17.1

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

* [PATCH 16/22] [media] tvp5150: add querystd
  2018-06-28 16:20 [PATCH 00/21] TVP5150 fixes and new features Marco Felsch
                   ` (14 preceding siblings ...)
  2018-06-28 16:20 ` [PATCH 15/22] [media] tvp5150: add sync lock/loss signal debug messages Marco Felsch
@ 2018-06-28 16:20 ` Marco Felsch
  2018-07-30 18:09   ` Mauro Carvalho Chehab
  2018-06-28 16:20 ` [PATCH 17/22] [media] tvp5150: add g_std callback Marco Felsch
                   ` (6 subsequent siblings)
  22 siblings, 1 reply; 70+ messages in thread
From: Marco Felsch @ 2018-06-28 16:20 UTC (permalink / raw)
  To: mchehab, robh+dt, mark.rutland
  Cc: p.zabel, afshin.nasser, javierm, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

From: Philipp Zabel <p.zabel@pengutronix.de>

Add the querystd video_op and make it return V4L2_STD_UNKNOWN while the
TVP5150 is not locked to a signal.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/media/i2c/tvp5150.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index 99d887936ea0..1990aaa17749 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -796,6 +796,15 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
 	}
 }
 
+static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
+{
+	struct tvp5150 *decoder = to_tvp5150(sd);
+
+	*std_id = decoder->lock ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
+
+	return 0;
+}
+
 static const struct v4l2_event tvp5150_ev_fmt = {
 	.type = V4L2_EVENT_SOURCE_CHANGE,
 	.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
@@ -1408,6 +1417,7 @@ static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = {
 
 static const struct v4l2_subdev_video_ops tvp5150_video_ops = {
 	.s_std = tvp5150_s_std,
+	.querystd = tvp5150_querystd,
 	.s_stream = tvp5150_s_stream,
 	.s_routing = tvp5150_s_routing,
 	.g_mbus_config = tvp5150_g_mbus_config,
-- 
2.17.1

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

* [PATCH 17/22] [media] tvp5150: add g_std callback
  2018-06-28 16:20 [PATCH 00/21] TVP5150 fixes and new features Marco Felsch
                   ` (15 preceding siblings ...)
  2018-06-28 16:20 ` [PATCH 16/22] [media] tvp5150: add querystd Marco Felsch
@ 2018-06-28 16:20 ` Marco Felsch
  2018-06-28 16:20 ` [PATCH 18/22] partial revert of "[media] tvp5150: add HW input connectors support" Marco Felsch
                   ` (5 subsequent siblings)
  22 siblings, 0 replies; 70+ messages in thread
From: Marco Felsch @ 2018-06-28 16:20 UTC (permalink / raw)
  To: mchehab, robh+dt, mark.rutland
  Cc: p.zabel, afshin.nasser, javierm, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

Add callback to retrieve the current set norm.

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/media/i2c/tvp5150.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index 1990aaa17749..3b51b6b67736 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -756,6 +756,15 @@ static int tvp5150_set_std(struct v4l2_subdev *sd, v4l2_std_id std)
 	return 0;
 }
 
+static int tvp5150_g_std(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+	struct tvp5150 *decoder = to_tvp5150(sd);
+
+	*std = decoder->norm;
+
+	return 0;
+}
+
 static int tvp5150_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
 {
 	struct tvp5150 *decoder = to_tvp5150(sd);
@@ -1417,6 +1426,7 @@ static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = {
 
 static const struct v4l2_subdev_video_ops tvp5150_video_ops = {
 	.s_std = tvp5150_s_std,
+	.g_std = tvp5150_g_std,
 	.querystd = tvp5150_querystd,
 	.s_stream = tvp5150_s_stream,
 	.s_routing = tvp5150_s_routing,
-- 
2.17.1

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

* [PATCH 18/22] partial revert of "[media] tvp5150: add HW input connectors support"
  2018-06-28 16:20 [PATCH 00/21] TVP5150 fixes and new features Marco Felsch
                   ` (16 preceding siblings ...)
  2018-06-28 16:20 ` [PATCH 17/22] [media] tvp5150: add g_std callback Marco Felsch
@ 2018-06-28 16:20 ` Marco Felsch
  2018-07-03 23:19   ` Rob Herring
  2018-07-30 18:18   ` Mauro Carvalho Chehab
  2018-06-28 16:20 ` [PATCH 19/22] [media] tvp5150: add input source selection of_graph support Marco Felsch
                   ` (4 subsequent siblings)
  22 siblings, 2 replies; 70+ messages in thread
From: Marco Felsch @ 2018-06-28 16:20 UTC (permalink / raw)
  To: mchehab, robh+dt, mark.rutland
  Cc: p.zabel, afshin.nasser, javierm, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

From: Javier Martinez Canillas <javierm@redhat.com>

Commit f7b4b54e6364 ("[media] tvp5150: add HW input connectors support")
added input signals support for the tvp5150, but the approach was found
to be incorrect so the corresponding DT binding commit 82c2ffeb217a
("[media] tvp5150: document input connectors DT bindings") was reverted.

This left the driver with an undocumented (and wrong) DT parsing logic,
so lets get rid of this code as well until the input connectors support
is implemented properly.

It's a partial revert due other patches added on top of mentioned commit
not allowing the commit to be reverted cleanly anymore. But all the code
related to the DT parsing logic and input entities creation are removed.

Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
[m.felsch@pengutronix.de: rm TVP5150_INPUT_NUM define]
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/media/i2c/tvp5150.c         | 141 ----------------------------
 include/dt-bindings/media/tvp5150.h |   2 -
 2 files changed, 143 deletions(-)

diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index 3b51b6b67736..a6fec569a610 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -48,8 +48,6 @@ struct tvp5150 {
 	struct v4l2_subdev sd;
 #ifdef CONFIG_MEDIA_CONTROLLER
 	struct media_pad pads[DEMOD_NUM_PADS];
-	struct media_entity input_ent[TVP5150_INPUT_NUM];
-	struct media_pad input_pad[TVP5150_INPUT_NUM];
 #endif
 	struct v4l2_ctrl_handler hdl;
 	struct v4l2_rect rect;
@@ -1191,40 +1189,6 @@ static int tvp5150_enum_frame_size(struct v4l2_subdev *sd,
 	return 0;
 }
 
-/****************************************************************************
-			Media entity ops
- ****************************************************************************/
-
-#ifdef CONFIG_MEDIA_CONTROLLER
-static int tvp5150_link_setup(struct media_entity *entity,
-			      const struct media_pad *local,
-			      const struct media_pad *remote, u32 flags)
-{
-	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
-	struct tvp5150 *decoder = to_tvp5150(sd);
-	int i;
-
-	for (i = 0; i < TVP5150_INPUT_NUM; i++) {
-		if (remote->entity == &decoder->input_ent[i])
-			break;
-	}
-
-	/* Do nothing for entities that are not input connectors */
-	if (i == TVP5150_INPUT_NUM)
-		return 0;
-
-	decoder->input = i;
-
-	tvp5150_selmux(sd);
-
-	return 0;
-}
-
-static const struct media_entity_operations tvp5150_sd_media_ops = {
-	.link_setup = tvp5150_link_setup,
-};
-#endif
-
 /****************************************************************************
 			I2C Command
  ****************************************************************************/
@@ -1369,42 +1333,6 @@ static int tvp5150_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
 	return 0;
 }
 
-static int tvp5150_registered(struct v4l2_subdev *sd)
-{
-#ifdef CONFIG_MEDIA_CONTROLLER
-	struct tvp5150 *decoder = to_tvp5150(sd);
-	int ret = 0;
-	int i;
-
-	for (i = 0; i < TVP5150_INPUT_NUM; i++) {
-		struct media_entity *input = &decoder->input_ent[i];
-		struct media_pad *pad = &decoder->input_pad[i];
-
-		if (!input->name)
-			continue;
-
-		decoder->input_pad[i].flags = MEDIA_PAD_FL_SOURCE;
-
-		ret = media_entity_pads_init(input, 1, pad);
-		if (ret < 0)
-			return ret;
-
-		ret = media_device_register_entity(sd->v4l2_dev->mdev, input);
-		if (ret < 0)
-			return ret;
-
-		ret = media_create_pad_link(input, 0, &sd->entity,
-					    DEMOD_PAD_IF_INPUT, 0);
-		if (ret < 0) {
-			media_device_unregister_entity(input);
-			return ret;
-		}
-	}
-#endif
-
-	return 0;
-}
-
 /* ----------------------------------------------------------------------- */
 
 static const struct v4l2_ctrl_ops tvp5150_ctrl_ops = {
@@ -1458,10 +1386,6 @@ static const struct v4l2_subdev_ops tvp5150_ops = {
 	.pad = &tvp5150_pad_ops,
 };
 
-static const struct v4l2_subdev_internal_ops tvp5150_internal_ops = {
-	.registered = tvp5150_registered,
-};
-
 /****************************************************************************
 			I2C Client & Driver
  ****************************************************************************/
@@ -1614,12 +1538,6 @@ static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np)
 {
 	struct v4l2_fwnode_endpoint bus_cfg;
 	struct device_node *ep;
-#ifdef CONFIG_MEDIA_CONTROLLER
-	struct device_node *connectors, *child;
-	struct media_entity *input;
-	const char *name;
-	u32 input_type;
-#endif
 	unsigned int flags;
 	int ret = 0;
 
@@ -1643,63 +1561,6 @@ static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np)
 
 	decoder->mbus_type = bus_cfg.bus_type;
 
-#ifdef CONFIG_MEDIA_CONTROLLER
-	connectors = of_get_child_by_name(np, "connectors");
-
-	if (!connectors)
-		goto err;
-
-	for_each_available_child_of_node(connectors, child) {
-		ret = of_property_read_u32(child, "input", &input_type);
-		if (ret) {
-			dev_err(decoder->sd.dev,
-				 "missing type property in node %s\n",
-				 child->name);
-			goto err_connector;
-		}
-
-		if (input_type >= TVP5150_INPUT_NUM) {
-			ret = -EINVAL;
-			goto err_connector;
-		}
-
-		input = &decoder->input_ent[input_type];
-
-		/* Each input connector can only be defined once */
-		if (input->name) {
-			dev_err(decoder->sd.dev,
-				 "input %s with same type already exists\n",
-				 input->name);
-			ret = -EINVAL;
-			goto err_connector;
-		}
-
-		switch (input_type) {
-		case TVP5150_COMPOSITE0:
-		case TVP5150_COMPOSITE1:
-			input->function = MEDIA_ENT_F_CONN_COMPOSITE;
-			break;
-		case TVP5150_SVIDEO:
-			input->function = MEDIA_ENT_F_CONN_SVIDEO;
-			break;
-		}
-
-		input->flags = MEDIA_ENT_FL_CONNECTOR;
-
-		ret = of_property_read_string(child, "label", &name);
-		if (ret < 0) {
-			dev_err(decoder->sd.dev,
-				 "missing label property in node %s\n",
-				 child->name);
-			goto err_connector;
-		}
-
-		input->name = name;
-	}
-
-err_connector:
-	of_node_put(connectors);
-#endif
 err:
 	of_node_put(ep);
 	return ret;
@@ -1751,7 +1612,6 @@ static int tvp5150_probe(struct i2c_client *c,
 	}
 
 	v4l2_i2c_subdev_init(sd, c, &tvp5150_ops);
-	sd->internal_ops = &tvp5150_internal_ops;
 	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 
 #if defined(CONFIG_MEDIA_CONTROLLER)
@@ -1765,7 +1625,6 @@ static int tvp5150_probe(struct i2c_client *c,
 	if (res < 0)
 		return res;
 
-	sd->entity.ops = &tvp5150_sd_media_ops;
 #endif
 
 	res = tvp5150_detect_version(core);
diff --git a/include/dt-bindings/media/tvp5150.h b/include/dt-bindings/media/tvp5150.h
index c852a35e916e..8637910aae76 100644
--- a/include/dt-bindings/media/tvp5150.h
+++ b/include/dt-bindings/media/tvp5150.h
@@ -26,8 +26,6 @@
 #define TVP5150_COMPOSITE1 1
 #define TVP5150_SVIDEO     2
 
-#define TVP5150_INPUT_NUM  3
-
 /* TVP5150 HW outputs */
 #define TVP5150_NORMAL       0
 #define TVP5150_BLACK_SCREEN 1
-- 
2.17.1

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

* [PATCH 19/22] [media] tvp5150: add input source selection of_graph support
  2018-06-28 16:20 [PATCH 00/21] TVP5150 fixes and new features Marco Felsch
                   ` (17 preceding siblings ...)
  2018-06-28 16:20 ` [PATCH 18/22] partial revert of "[media] tvp5150: add HW input connectors support" Marco Felsch
@ 2018-06-28 16:20 ` Marco Felsch
  2018-07-30 18:29   ` Mauro Carvalho Chehab
  2018-06-28 16:20 ` [PATCH 20/22] [media] tvp5150: Add input port connectors DT bindings Marco Felsch
                   ` (3 subsequent siblings)
  22 siblings, 1 reply; 70+ messages in thread
From: Marco Felsch @ 2018-06-28 16:20 UTC (permalink / raw)
  To: mchehab, robh+dt, mark.rutland
  Cc: p.zabel, afshin.nasser, javierm, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

The currrent driver layout had the following layout:
               +----------------+
 +-------+     |    TVP5150     |
 | Comp0 +--+  |                |
 +-------+  |  |          +-----+
 +-------+  |  +------+   | Src |
 | Comp1 +--+--|Sink  |   +-----+
 +-------+  |  +------+   +-----+
+--------+  |  |          | Src |
| SVideo +--+  |          +-----+
+--------+     +----------------+

Since the device tree abstracts the real hardware this layout is not
correct, because the TVP5150 has 3 physical ports (2 input, 1 output).
Furthermore this layout assumes that there is an additional external mux
in front of the TVP5150. This is not correct because the TVP5150 does
the muxing work. The corresponding of_graph layout will look like:
	tvp5150 {
		....
		port {
			reg = <0>;
			endpoint@0 {...};
			endpoint@1 {...};
			endpoint@2 {...};
		};

	};

This patch change the layout to:
             +----------------+
             |    TVP5150     |
 +-------+   +------+         |
 | Comp0 +---+ Sink |         |
 +-------+   +------+         |
 +-------+   +------+   +-----+
 | Comp1 +---+ Sink |   | Src |
 +-------+   +------+   +-----+
+--------+   +------+         |
| SVideo +---+ Sink |         |
+--------+   +------+         |
             +----------------+

To keep things easy an additional 'virtual' S-Video port is added. More
information about the port mapping can be found in the device tree
binding documentation. The connector entities Comp0/1, SVideo are created
only if they are connected to the correct port. If more than one connector
is available the media_entity_operations.link_setup() callback ensures that
only one connector is active. To change the input src the link between
the TVP5150 pad and the connector must be disabled, then a new link can
be enabled.

The patch tries to reduce the '#ifdef CONFIG_MEDIA_CONTROLLER' usage to
a minimum.

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/media/i2c/tvp5150.c | 322 ++++++++++++++++++++++++++++++++----
 1 file changed, 287 insertions(+), 35 deletions(-)

diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index a6fec569a610..6ac29c62d99b 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -44,10 +44,30 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
 
 #define dprintk0(__dev, __arg...) dev_dbg_lvl(__dev, 0, 0, __arg)
 
+enum tvp5150_ports {
+	TVP5150_PORT_AIP1A = TVP5150_COMPOSITE0,
+	TVP5150_PORT_AIP1B,
+	/* s-video port is a virtual port */
+	TVP5150_PORT_SVIDEO,
+	TVP5150_PORT_YOUT,
+	TVP5150_PORT_NUM,
+};
+
+#ifdef CONFIG_MEDIA_CONTROLLER
+struct tvp5150_connector {
+	struct media_entity con;
+	struct media_pad pad;
+	unsigned int port_num;
+};
+#endif
+
 struct tvp5150 {
 	struct v4l2_subdev sd;
+	struct device_node *endpoints[TVP5150_PORT_NUM];
 #ifdef CONFIG_MEDIA_CONTROLLER
-	struct media_pad pads[DEMOD_NUM_PADS];
+	struct media_pad pads[TVP5150_PORT_NUM];
+	struct tvp5150_connector *connectors;
+	int active;
 #endif
 	struct v4l2_ctrl_handler hdl;
 	struct v4l2_rect rect;
@@ -990,7 +1010,7 @@ static int tvp5150_fill_fmt(struct v4l2_subdev *sd,
 	struct v4l2_rect *__crop;
 	struct tvp5150 *decoder = to_tvp5150(sd);
 
-	if (!format || (format->pad != DEMOD_PAD_VID_OUT))
+	if (!format || (format->pad != TVP5150_PORT_YOUT))
 		return -EINVAL;
 
 	f = &format->format;
@@ -1189,6 +1209,62 @@ static int tvp5150_enum_frame_size(struct v4l2_subdev *sd,
 	return 0;
 }
 
+/****************************************************************************
+ *			Media entity ops
+ ****************************************************************************/
+#ifdef CONFIG_MEDIA_CONTROLLER
+static int tvp5150_s_routing(struct v4l2_subdev *sd, u32 input, u32 output,
+			     u32 config);
+static int tvp5150_link_setup(struct media_entity *entity,
+			      const struct media_pad *local,
+			      const struct media_pad *remote, u32 flags)
+{
+	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+	struct tvp5150 *decoder = to_tvp5150(sd);
+	int ret = 0;
+
+	/*
+	 * The tvp state is determined by the enabled sink pad link.
+	 * Enabling or disabling the source pad link has no effect.
+	 */
+	if (local->flags & MEDIA_PAD_FL_SOURCE)
+		return 0;
+
+	dev_dbg(sd->dev, "link setup '%s':%d->'%s':%d[%d]",
+		remote->entity->name, remote->index, local->entity->name,
+		local->index, flags & MEDIA_LNK_FL_ENABLED);
+
+	if (flags & MEDIA_LNK_FL_ENABLED) {
+		if (decoder->active == local->index)
+			goto out;
+		if (decoder->active >= 0) {
+			ret = -EBUSY;
+			goto out;
+		}
+
+		dev_dbg(sd->dev, "Setting %d active\n", local->index);
+		decoder->active = local->index;
+		tvp5150_s_routing(sd, local->index, TVP5150_NORMAL, 0);
+	} else {
+		if (decoder->active != local->index)
+			goto out;
+
+		dev_dbg(sd->dev, "going inactive\n");
+		decoder->active = -1;
+		/*
+		 * Output black screen for deselected input if TVP5150 variant
+		 * supports this.
+		 */
+		tvp5150_s_routing(sd, local->index, TVP5150_BLACK_SCREEN, 0);
+	}
+out:
+	return ret;
+}
+
+static const struct media_entity_operations tvp5150_sd_media_ops = {
+	.link_setup = tvp5150_link_setup,
+};
+#endif
 /****************************************************************************
 			I2C Command
  ****************************************************************************/
@@ -1333,6 +1409,50 @@ static int tvp5150_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
 	return 0;
 }
 
+static int tvp5150_get_con_num(struct tvp5150 *decoder)
+{
+	unsigned int i, num = 0;
+
+	for (i = 0; i < TVP5150_PORT_NUM - 1; i++)
+		if (decoder->endpoints[i])
+			num++;
+	return num;
+}
+
+static int tvp5150_registered(struct v4l2_subdev *sd)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER
+	struct tvp5150 *decoder = to_tvp5150(sd);
+	unsigned int i, con_num;
+	int ret;
+
+	con_num = tvp5150_get_con_num(decoder);
+	for (i = 0; i < con_num; i++) {
+		struct media_entity *con = &decoder->connectors[i].con;
+		struct media_pad *pad = &decoder->connectors[i].pad;
+		unsigned int port = decoder->connectors[i].port_num;
+
+		pad->flags = MEDIA_PAD_FL_SOURCE;
+		ret = media_entity_pads_init(con, 1, pad);
+		if (ret < 0)
+			return ret;
+
+		ret = media_device_register_entity(sd->v4l2_dev->mdev, con);
+		if (ret < 0)
+			return ret;
+
+		ret = media_create_pad_link(con, 0, &sd->entity, port, 0);
+		if (ret < 0) {
+			media_device_unregister_entity(con);
+			return ret;
+		}
+
+	}
+#endif
+	return 0;
+}
+
+
 /* ----------------------------------------------------------------------- */
 
 static const struct v4l2_ctrl_ops tvp5150_ctrl_ops = {
@@ -1386,6 +1506,10 @@ static const struct v4l2_subdev_ops tvp5150_ops = {
 	.pad = &tvp5150_pad_ops,
 };
 
+static const struct v4l2_subdev_internal_ops tvp5150_internal_ops = {
+	.registered = tvp5150_registered,
+};
+
 /****************************************************************************
 			I2C Client & Driver
  ****************************************************************************/
@@ -1534,38 +1658,171 @@ static int tvp5150_init(struct i2c_client *c)
 	return 0;
 }
 
+static int tvp5150_mc_init(struct v4l2_subdev *sd)
+{
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	struct tvp5150 *decoder = to_tvp5150(sd);
+	struct device *dev = decoder->sd.dev;
+	struct device_node *rp;
+	unsigned int con_num = 0;
+	unsigned int i, j;
+	int ret;
+
+	sd->entity.ops = &tvp5150_sd_media_ops;
+	sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
+
+	/* Initialize all TVP5150 pads */
+	for (i = 0; i < TVP5150_PORT_NUM; i++)
+		decoder->pads[i].flags = (i < TVP5150_PORT_NUM - 1) ?
+							MEDIA_PAD_FL_SINK :
+							MEDIA_PAD_FL_SOURCE;
+	ret = media_entity_pads_init(&sd->entity, TVP5150_PORT_NUM,
+				     decoder->pads);
+	if (ret < 0)
+		return ret;
+
+	/* Allocate and initialize all available input connectors */
+	con_num = tvp5150_get_con_num(decoder);
+	if (!con_num)
+		return 0;
+	decoder->connectors = devm_kcalloc(dev, con_num,
+					   sizeof(*decoder->connectors),
+					   GFP_KERNEL);
+	if (!decoder->connectors)
+		return -ENOMEM;
+
+	for (i = 0, j = 0; i < TVP5150_PORT_NUM - 1; i++) {
+		if (!decoder->endpoints[i])
+			continue;
+
+		switch (i) {
+		case TVP5150_PORT_AIP1A:
+		case TVP5150_PORT_AIP1B:
+			decoder->connectors[j].con.function =
+						MEDIA_ENT_F_CONN_COMPOSITE;
+			break;
+		case TVP5150_PORT_SVIDEO:
+			decoder->connectors[j].con.function =
+						MEDIA_ENT_F_CONN_SVIDEO;
+			break;
+		}
+
+		decoder->connectors[j].con.flags = MEDIA_ENT_FL_CONNECTOR;
+		rp = of_graph_get_remote_port_parent(decoder->endpoints[i]);
+		ret = of_property_read_string(rp, "label",
+					      &decoder->connectors[j].con.name);
+		if (ret < 0)
+			return ret;
+		decoder->connectors[j].port_num = i;
+
+		j++;
+	}
+#endif
+	return 0;
+}
+
+static bool tvp5150_valid_input(struct device_node *endpoint,
+				unsigned int port)
+{
+	struct device_node *rp = of_graph_get_remote_port_parent(endpoint);
+	const char *input;
+	int ret;
+
+	switch (port) {
+	case TVP5150_PORT_AIP1A:
+	case TVP5150_PORT_AIP1B:
+		ret = of_device_is_compatible(rp, "composite-video-connector");
+		if (!ret)
+			return false;
+		break;
+	case TVP5150_PORT_SVIDEO:
+		ret = of_device_is_compatible(rp, "svideo-connector");
+		if (!ret)
+			return false;
+	}
+
+	ret = of_property_read_string(rp, "label", &input);
+	if (ret < 0)
+		return false;
+
+	return true;
+}
+
 static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np)
 {
+	struct device *dev = decoder->sd.dev;
 	struct v4l2_fwnode_endpoint bus_cfg;
-	struct device_node *ep;
+	struct device_node *ep_np;
 	unsigned int flags;
-	int ret = 0;
+	int ret;
+	bool found = false;
 
-	ep = of_graph_get_next_endpoint(np, NULL);
-	if (!ep)
-		return -EINVAL;
+	for_each_endpoint_of_node(np, ep_np) {
+		struct of_endpoint ep;
 
-	ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &bus_cfg);
-	if (ret)
-		goto err;
-
-	flags = bus_cfg.bus.parallel.flags;
+		of_graph_parse_endpoint(ep_np, &ep);
+		if (decoder->endpoints[ep.port]) {
+			dev_warn(dev,
+				 "Multiple port endpoints are not supported\n");
+			continue;
+		}
 
-	if (bus_cfg.bus_type == V4L2_MBUS_PARALLEL &&
-	    !(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH &&
-	      flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH &&
-	      flags & V4L2_MBUS_FIELD_EVEN_LOW)) {
-		ret = -EINVAL;
-		goto err;
-	}
+		switch (ep.port) {
+		     /* Use common tvp5150_valid_input() for all inputs */
+		case TVP5150_PORT_AIP1A:
+		case TVP5150_PORT_AIP1B:
+		case TVP5150_PORT_SVIDEO:
+			if (!tvp5150_valid_input(ep_np, ep.port)) {
+				dev_err(dev,
+					"Invalid endpoint %pOF on port %d\n",
+					ep.local_node, ep.port);
+				ret = -EINVAL;
+				goto err;
+			}
+			break;
+		case TVP5150_PORT_YOUT:
+			ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_np),
+							 &bus_cfg);
+			if (ret)
+				goto err;
+
+			flags = bus_cfg.bus.parallel.flags;
+
+			if (bus_cfg.bus_type == V4L2_MBUS_PARALLEL &&
+			    !(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH &&
+			      flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH &&
+			      flags & V4L2_MBUS_FIELD_EVEN_LOW)) {
+				ret = -EINVAL;
+				goto err;
+			}
+
+			decoder->mbus_type = bus_cfg.bus_type;
+			break;
+		default:
+			dev_err(dev, "Invalid port %d for endpoint %pOF\n",
+				ep.port, ep.local_node);
+			ret = -EINVAL;
+			goto err;
+		}
 
-	decoder->mbus_type = bus_cfg.bus_type;
+		of_node_get(ep_np);
+		decoder->endpoints[ep.port] = ep_np;
 
+		found = true;
+	}
+	return found ? 0 : -ENODEV;
 err:
-	of_node_put(ep);
 	return ret;
 }
 
+static void tvp5150_dt_cleanup(struct tvp5150 *decoder)
+{
+	unsigned int i;
+
+	for (i = 0; i < TVP5150_PORT_NUM; i++)
+		of_node_put(decoder->endpoints[i]);
+}
+
 static const char * const tvp5150_test_patterns[2] = {
 	"Disabled",
 	"Black screen"
@@ -1604,7 +1861,7 @@ static int tvp5150_probe(struct i2c_client *c,
 		res = tvp5150_parse_dt(core, np);
 		if (res) {
 			dev_err(sd->dev, "DT parsing error: %d\n", res);
-			return res;
+			goto err_cleanup_dt;
 		}
 	} else {
 		/* Default to BT.656 embedded sync */
@@ -1612,24 +1869,16 @@ static int tvp5150_probe(struct i2c_client *c,
 	}
 
 	v4l2_i2c_subdev_init(sd, c, &tvp5150_ops);
+	sd->internal_ops = &tvp5150_internal_ops;
 	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 
-#if defined(CONFIG_MEDIA_CONTROLLER)
-	core->pads[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
-	core->pads[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
-	core->pads[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE;
-
-	sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
-
-	res = media_entity_pads_init(&sd->entity, DEMOD_NUM_PADS, core->pads);
-	if (res < 0)
-		return res;
-
-#endif
+	res = tvp5150_mc_init(sd);
+	if (res)
+		goto err_cleanup_dt;
 
 	res = tvp5150_detect_version(core);
 	if (res < 0)
-		return res;
+		goto err_cleanup_dt;
 
 	core->norm = V4L2_STD_ALL;	/* Default is autodetect */
 	core->detected_norm = V4L2_STD_UNKNOWN;
@@ -1683,6 +1932,9 @@ static int tvp5150_probe(struct i2c_client *c,
 err:
 	v4l2_ctrl_handler_free(&core->hdl);
 	return res;
+err_cleanup_dt:
+	tvp5150_dt_cleanup(core);
+	return res;
 }
 
 static int tvp5150_remove(struct i2c_client *c)
-- 
2.17.1

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

* [PATCH 20/22] [media] tvp5150: Add input port connectors DT bindings
  2018-06-28 16:20 [PATCH 00/21] TVP5150 fixes and new features Marco Felsch
                   ` (18 preceding siblings ...)
  2018-06-28 16:20 ` [PATCH 19/22] [media] tvp5150: add input source selection of_graph support Marco Felsch
@ 2018-06-28 16:20 ` Marco Felsch
  2018-07-03 23:23   ` Rob Herring
  2018-06-28 16:20 ` [PATCH 21/22] [media] tvp5150: initialize subdev before parsing device tree Marco Felsch
                   ` (2 subsequent siblings)
  22 siblings, 1 reply; 70+ messages in thread
From: Marco Felsch @ 2018-06-28 16:20 UTC (permalink / raw)
  To: mchehab, robh+dt, mark.rutland
  Cc: p.zabel, afshin.nasser, javierm, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

The TVP5150/1 decoders support different video input sources to their
AIP1A/B pins.

Possible configurations are as follows:
  - Analog Composite signal connected to AIP1A.
  - Analog Composite signal connected to AIP1B.
  - Analog S-Video Y (luminance) and C (chrominance)
    signals connected to AIP1A and AIP1B respectively.

This patch extends the device tree bindings documentation to describe
how the input connectors for these devices should be defined in a DT.

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 .../devicetree/bindings/media/i2c/tvp5150.txt | 118 +++++++++++++++++-
 1 file changed, 113 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/i2c/tvp5150.txt b/Documentation/devicetree/bindings/media/i2c/tvp5150.txt
index 8c0fc1a26bf0..feed8c911c5e 100644
--- a/Documentation/devicetree/bindings/media/i2c/tvp5150.txt
+++ b/Documentation/devicetree/bindings/media/i2c/tvp5150.txt
@@ -12,11 +12,23 @@ Optional Properties:
 - pdn-gpios: phandle for the GPIO connected to the PDN pin, if any.
 - reset-gpios: phandle for the GPIO connected to the RESETB pin, if any.
 
-The device node must contain one 'port' child node for its digital output
-video port, in accordance with the video interface bindings defined in
-Documentation/devicetree/bindings/media/video-interfaces.txt.
+The device node must contain one 'port' child node per device input and output
+port, in accordance with the video interface bindings defined in
+Documentation/devicetree/bindings/media/video-interfaces.txt. The port nodes
+are numbered as follows
 
-Required Endpoint Properties for parallel synchronization:
+	  Name		Type		Port
+	--------------------------------------
+	  AIP1A		sink		0
+	  AIP1B		sink		1
+	  S-VIDEO	sink		2
+	  Y-OUT		src		3
+
+The device node must contain at least the Y-OUT port. Each input port must be
+linked to an endpoint defined in
+Documentation/devicetree/bindings/display/connector/analog-tv-connector.txt.
+
+Required Endpoint Properties for parallel synchronization on output port:
 
 - hsync-active: active state of the HSYNC signal. Must be <1> (HIGH).
 - vsync-active: active state of the VSYNC signal. Must be <1> (HIGH).
@@ -26,7 +38,9 @@ Required Endpoint Properties for parallel synchronization:
 If none of hsync-active, vsync-active and field-even-active is specified,
 the endpoint is assumed to use embedded BT.656 synchronization.
 
-Example:
+Examples:
+
+Only Output:
 
 &i2c2 {
 	...
@@ -37,6 +51,100 @@ Example:
 		reset-gpios = <&gpio6 7 GPIO_ACTIVE_LOW>;
 
 		port {
+			reg = <3>;
+			tvp5150_1: endpoint {
+				remote-endpoint = <&ccdc_ep>;
+			};
+		};
+	};
+};
+
+One Input:
+
+connector@0 {
+	compatible = "composite-video-connector";
+	label = "Composite0";
+
+	port {
+		comp0_out: endpoint {
+			remote-endpoint = <&tvp5150_comp0_in>;
+		};
+	};
+};
+
+&i2c2 {
+	...
+	tvp5150@5c {
+		compatible = "ti,tvp5150";
+		reg = <0x5c>;
+		pdn-gpios = <&gpio4 30 GPIO_ACTIVE_LOW>;
+		reset-gpios = <&gpio6 7 GPIO_ACTIVE_LOW>;
+
+		port@0 {
+			reg = <0>;
+			tvp5150_comp0_in: endpoint {
+				remote-endpoint = <&comp0_out>;
+			};
+		};
+
+		port@3 {
+			reg = <3>;
+			tvp5150_1: endpoint {
+				remote-endpoint = <&ccdc_ep>;
+			};
+		};
+	};
+};
+
+
+Two Inputs, different connector 12 on input AIP1A:
+
+connector@1 {
+	compatible = "svideo-connector";
+	label = "S-Video";
+
+	port {
+		svideo_out: endpoint {
+			remote-endpoint = <&tvp5150_svideo_in>;
+		};
+	};
+};
+
+connector@12 {
+	compatible = "composite-video-connector";
+	label = "Composite12";
+
+	port {
+		comp12_out: endpoint {
+			remote-endpoint = <&tvp5150_comp12_in>;
+		};
+	};
+};
+
+&i2c2 {
+	...
+	tvp5150@5c {
+		compatible = "ti,tvp5150";
+		reg = <0x5c>;
+		pdn-gpios = <&gpio4 30 GPIO_ACTIVE_LOW>;
+		reset-gpios = <&gpio6 7 GPIO_ACTIVE_LOW>;
+
+		port@0 {
+			reg = <0>;
+			tvp5150_comp12_in: endpoint {
+				remote-endpoint = <&comp12_out>;
+			};
+		};
+
+		port@2 {
+			reg = <2>;
+			tvp5150_svideo_in: endpoint {
+				remote-endpoint = <&svideo_out>;
+			};
+		};
+
+		port@3 {
+			reg = <3>;
 			tvp5150_1: endpoint {
 				remote-endpoint = <&ccdc_ep>;
 			};
-- 
2.17.1

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

* [PATCH 21/22] [media] tvp5150: initialize subdev before parsing device tree
  2018-06-28 16:20 [PATCH 00/21] TVP5150 fixes and new features Marco Felsch
                   ` (19 preceding siblings ...)
  2018-06-28 16:20 ` [PATCH 20/22] [media] tvp5150: Add input port connectors DT bindings Marco Felsch
@ 2018-06-28 16:20 ` Marco Felsch
  2018-06-28 16:20 ` [PATCH 22/22] [media] tvp5150: Change default input source selection behaviour Marco Felsch
  2018-06-28 20:57 ` [PATCH 00/21] TVP5150 fixes and new features Javier Martinez Canillas
  22 siblings, 0 replies; 70+ messages in thread
From: Marco Felsch @ 2018-06-28 16:20 UTC (permalink / raw)
  To: mchehab, robh+dt, mark.rutland
  Cc: p.zabel, afshin.nasser, javierm, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

From: Michael Tretter <m.tretter@pengutronix.de>

There are several debug prints in the tvp5150_parse_dt() function, which
do not print the prefix, because the v4l2_subdev is not initialized, yet.

Initialize the v4l2_subdev before parsing the device tree to fix the
debug messages.

Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/media/i2c/tvp5150.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index 6ac29c62d99b..3645d1166118 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -1856,6 +1856,9 @@ static int tvp5150_probe(struct i2c_client *c,
 
 	core->regmap = map;
 	sd = &core->sd;
+	v4l2_i2c_subdev_init(sd, c, &tvp5150_ops);
+	sd->internal_ops = &tvp5150_internal_ops;
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 
 	if (IS_ENABLED(CONFIG_OF) && np) {
 		res = tvp5150_parse_dt(core, np);
@@ -1868,10 +1871,6 @@ static int tvp5150_probe(struct i2c_client *c,
 		core->mbus_type = V4L2_MBUS_BT656;
 	}
 
-	v4l2_i2c_subdev_init(sd, c, &tvp5150_ops);
-	sd->internal_ops = &tvp5150_internal_ops;
-	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
-
 	res = tvp5150_mc_init(sd);
 	if (res)
 		goto err_cleanup_dt;
-- 
2.17.1

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

* [PATCH 22/22] [media] tvp5150: Change default input source selection behaviour
  2018-06-28 16:20 [PATCH 00/21] TVP5150 fixes and new features Marco Felsch
                   ` (20 preceding siblings ...)
  2018-06-28 16:20 ` [PATCH 21/22] [media] tvp5150: initialize subdev before parsing device tree Marco Felsch
@ 2018-06-28 16:20 ` Marco Felsch
  2018-06-28 20:57 ` [PATCH 00/21] TVP5150 fixes and new features Javier Martinez Canillas
  22 siblings, 0 replies; 70+ messages in thread
From: Marco Felsch @ 2018-06-28 16:20 UTC (permalink / raw)
  To: mchehab, robh+dt, mark.rutland
  Cc: p.zabel, afshin.nasser, javierm, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

The default input is still TVP5150_COMPOSITE1, but if the platform
supports DT the default will be changed to the first valid connector.
First in this context means the connector at the lowest port number.

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/media/i2c/tvp5150.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index 3645d1166118..8b40cf721853 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -1835,7 +1835,7 @@ static int tvp5150_probe(struct i2c_client *c,
 	struct v4l2_subdev *sd;
 	struct device_node *np = c->dev.of_node;
 	struct regmap *map;
-	int res;
+	int res, i;
 
 	/* Check if the adapter supports the needed features */
 	if (!i2c_check_functionality(c->adapter,
@@ -1881,7 +1881,16 @@ static int tvp5150_probe(struct i2c_client *c,
 
 	core->norm = V4L2_STD_ALL;	/* Default is autodetect */
 	core->detected_norm = V4L2_STD_UNKNOWN;
+	/*
+	 * Default is TVP5150_COMPOSITE1.
+	 * In case of OF support, default is first valid port
+	 */
 	core->input = TVP5150_COMPOSITE1;
+	for (i = 0; i < TVP5150_PORT_NUM - 1; i++)
+		if (core->endpoints[i]) {
+			core->input = i;
+			break;
+		}
 	core->enable = true;
 
 	v4l2_ctrl_handler_init(&core->hdl, 5);
-- 
2.17.1

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

* Re: [PATCH 00/21] TVP5150 fixes and new features
  2018-06-28 16:20 [PATCH 00/21] TVP5150 fixes and new features Marco Felsch
                   ` (21 preceding siblings ...)
  2018-06-28 16:20 ` [PATCH 22/22] [media] tvp5150: Change default input source selection behaviour Marco Felsch
@ 2018-06-28 20:57 ` Javier Martinez Canillas
  22 siblings, 0 replies; 70+ messages in thread
From: Javier Martinez Canillas @ 2018-06-28 20:57 UTC (permalink / raw)
  To: Marco Felsch, mchehab, robh+dt, mark.rutland
  Cc: p.zabel, afshin.nasser, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

Hi Marco,

On 06/28/2018 06:20 PM, Marco Felsch wrote:
> First some fixes were made which may possibly interesting for other
> kernel versions.
> 
> Then I picked most of the patches from Philipp [1] and ported them
> to the recent media_tree master branch [3].
> 
> But the main purpose of this series is to convert the proprietary
> connector DT property into the generic input port property. I picked commit
> ('partial revert of "[media] tvp5150: add HW input connectors support"')
> to have a clean working base and used the results of the discussion [2].
> 

Thanks for working on this! I've felt guilty that I never re-worked my
patch-set after the discussion from [2].

I'll try to review these patches next week.

Best regards,
-- 
Javier Martinez Canillas
Software Engineer - Desktop Hardware Enablement
Red Hat

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

* Re: [PATCH 05/22] [media] v4l2-rect.h: add position and equal helpers
  2018-06-28 16:20 ` [PATCH 05/22] [media] v4l2-rect.h: add position and equal helpers Marco Felsch
@ 2018-06-29 14:12   ` Sakari Ailus
  0 siblings, 0 replies; 70+ messages in thread
From: Sakari Ailus @ 2018-06-29 14:12 UTC (permalink / raw)
  To: Marco Felsch
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser, javierm,
	laurent.pinchart, linux-media, devicetree, kernel

On Thu, Jun 28, 2018 at 06:20:37PM +0200, Marco Felsch wrote:
> Add two helper functions to check if two rectangles have the same
> position (top/left) and if two rectangles equals (same size and
> same position).
> 
> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>

Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>

-- 
Sakari Ailus
sakari.ailus@linux.intel.com

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

* Re: [PATCH 18/22] partial revert of "[media] tvp5150: add HW input connectors support"
  2018-06-28 16:20 ` [PATCH 18/22] partial revert of "[media] tvp5150: add HW input connectors support" Marco Felsch
@ 2018-07-03 23:19   ` Rob Herring
  2018-07-30 18:18   ` Mauro Carvalho Chehab
  1 sibling, 0 replies; 70+ messages in thread
From: Rob Herring @ 2018-07-03 23:19 UTC (permalink / raw)
  To: Marco Felsch
  Cc: mchehab, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

On Thu, Jun 28, 2018 at 06:20:50PM +0200, Marco Felsch wrote:
> From: Javier Martinez Canillas <javierm@redhat.com>
> 
> Commit f7b4b54e6364 ("[media] tvp5150: add HW input connectors support")
> added input signals support for the tvp5150, but the approach was found
> to be incorrect so the corresponding DT binding commit 82c2ffeb217a
> ("[media] tvp5150: document input connectors DT bindings") was reverted.
> 
> This left the driver with an undocumented (and wrong) DT parsing logic,
> so lets get rid of this code as well until the input connectors support
> is implemented properly.
> 
> It's a partial revert due other patches added on top of mentioned commit
> not allowing the commit to be reverted cleanly anymore. But all the code
> related to the DT parsing logic and input entities creation are removed.
> 
> Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> [m.felsch@pengutronix.de: rm TVP5150_INPUT_NUM define]
> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> ---
>  drivers/media/i2c/tvp5150.c         | 141 ----------------------------

>  include/dt-bindings/media/tvp5150.h |   2 -

Acked-by: Rob Herring <robh@kernel.org>

>  2 files changed, 143 deletions(-)

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

* Re: [PATCH 20/22] [media] tvp5150: Add input port connectors DT bindings
  2018-06-28 16:20 ` [PATCH 20/22] [media] tvp5150: Add input port connectors DT bindings Marco Felsch
@ 2018-07-03 23:23   ` Rob Herring
  2018-07-11  8:50     ` Marco Felsch
  2018-08-03  7:29     ` Marco Felsch
  0 siblings, 2 replies; 70+ messages in thread
From: Rob Herring @ 2018-07-03 23:23 UTC (permalink / raw)
  To: Marco Felsch
  Cc: mchehab, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

On Thu, Jun 28, 2018 at 06:20:52PM +0200, Marco Felsch wrote:
> The TVP5150/1 decoders support different video input sources to their
> AIP1A/B pins.
> 
> Possible configurations are as follows:
>   - Analog Composite signal connected to AIP1A.
>   - Analog Composite signal connected to AIP1B.
>   - Analog S-Video Y (luminance) and C (chrominance)
>     signals connected to AIP1A and AIP1B respectively.
> 
> This patch extends the device tree bindings documentation to describe
> how the input connectors for these devices should be defined in a DT.
> 
> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> ---
>  .../devicetree/bindings/media/i2c/tvp5150.txt | 118 +++++++++++++++++-
>  1 file changed, 113 insertions(+), 5 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/media/i2c/tvp5150.txt b/Documentation/devicetree/bindings/media/i2c/tvp5150.txt
> index 8c0fc1a26bf0..feed8c911c5e 100644
> --- a/Documentation/devicetree/bindings/media/i2c/tvp5150.txt
> +++ b/Documentation/devicetree/bindings/media/i2c/tvp5150.txt
> @@ -12,11 +12,23 @@ Optional Properties:
>  - pdn-gpios: phandle for the GPIO connected to the PDN pin, if any.
>  - reset-gpios: phandle for the GPIO connected to the RESETB pin, if any.
>  
> -The device node must contain one 'port' child node for its digital output
> -video port, in accordance with the video interface bindings defined in
> -Documentation/devicetree/bindings/media/video-interfaces.txt.
> +The device node must contain one 'port' child node per device input and output
> +port, in accordance with the video interface bindings defined in
> +Documentation/devicetree/bindings/media/video-interfaces.txt. The port nodes
> +are numbered as follows
>  
> -Required Endpoint Properties for parallel synchronization:
> +	  Name		Type		Port
> +	--------------------------------------
> +	  AIP1A		sink		0
> +	  AIP1B		sink		1
> +	  S-VIDEO	sink		2
> +	  Y-OUT		src		3
> +
> +The device node must contain at least the Y-OUT port. Each input port must be
> +linked to an endpoint defined in
> +Documentation/devicetree/bindings/display/connector/analog-tv-connector.txt.
> +
> +Required Endpoint Properties for parallel synchronization on output port:
>  
>  - hsync-active: active state of the HSYNC signal. Must be <1> (HIGH).
>  - vsync-active: active state of the VSYNC signal. Must be <1> (HIGH).
> @@ -26,7 +38,9 @@ Required Endpoint Properties for parallel synchronization:
>  If none of hsync-active, vsync-active and field-even-active is specified,
>  the endpoint is assumed to use embedded BT.656 synchronization.
>  
> -Example:
> +Examples:
> +
> +Only Output:
>  
>  &i2c2 {
>  	...
> @@ -37,6 +51,100 @@ Example:
>  		reset-gpios = <&gpio6 7 GPIO_ACTIVE_LOW>;
>  
>  		port {
> +			reg = <3>;
> +			tvp5150_1: endpoint {
> +				remote-endpoint = <&ccdc_ep>;
> +			};
> +		};
> +	};
> +};
> +
> +One Input:
> +
> +connector@0 {

Drop the unit-address as there is no reg property.

> +	compatible = "composite-video-connector";
> +	label = "Composite0";
> +
> +	port {
> +		comp0_out: endpoint {
> +			remote-endpoint = <&tvp5150_comp0_in>;
> +		};
> +	};
> +};
> +
> +&i2c2 {
> +	...
> +	tvp5150@5c {
> +		compatible = "ti,tvp5150";
> +		reg = <0x5c>;
> +		pdn-gpios = <&gpio4 30 GPIO_ACTIVE_LOW>;
> +		reset-gpios = <&gpio6 7 GPIO_ACTIVE_LOW>;
> +
> +		port@0 {
> +			reg = <0>;
> +			tvp5150_comp0_in: endpoint {
> +				remote-endpoint = <&comp0_out>;
> +			};
> +		};
> +
> +		port@3 {
> +			reg = <3>;
> +			tvp5150_1: endpoint {
> +				remote-endpoint = <&ccdc_ep>;
> +			};
> +		};
> +	};
> +};
> +
> +
> +Two Inputs, different connector 12 on input AIP1A:
> +
> +connector@1 {

ditto

> +	compatible = "svideo-connector";
> +	label = "S-Video";
> +
> +	port {
> +		svideo_out: endpoint {
> +			remote-endpoint = <&tvp5150_svideo_in>;
> +		};
> +	};
> +};
> +
> +connector@12 {

ditto

> +	compatible = "composite-video-connector";
> +	label = "Composite12";
> +
> +	port {
> +		comp12_out: endpoint {
> +			remote-endpoint = <&tvp5150_comp12_in>;
> +		};
> +	};
> +};
> +
> +&i2c2 {
> +	...
> +	tvp5150@5c {
> +		compatible = "ti,tvp5150";
> +		reg = <0x5c>;
> +		pdn-gpios = <&gpio4 30 GPIO_ACTIVE_LOW>;
> +		reset-gpios = <&gpio6 7 GPIO_ACTIVE_LOW>;
> +
> +		port@0 {
> +			reg = <0>;
> +			tvp5150_comp12_in: endpoint {
> +				remote-endpoint = <&comp12_out>;
> +			};
> +		};
> +
> +		port@2 {
> +			reg = <2>;
> +			tvp5150_svideo_in: endpoint {
> +				remote-endpoint = <&svideo_out>;
> +			};
> +		};
> +
> +		port@3 {
> +			reg = <3>;
>  			tvp5150_1: endpoint {
>  				remote-endpoint = <&ccdc_ep>;
>  			};
> -- 
> 2.17.1
> 

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

* Re: [PATCH 20/22] [media] tvp5150: Add input port connectors DT bindings
  2018-07-03 23:23   ` Rob Herring
@ 2018-07-11  8:50     ` Marco Felsch
  2018-08-03  7:29     ` Marco Felsch
  1 sibling, 0 replies; 70+ messages in thread
From: Marco Felsch @ 2018-07-11  8:50 UTC (permalink / raw)
  To: Rob Herring
  Cc: mchehab, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Hi Rob,

On 18-07-03 17:23, Rob Herring wrote:
> On Thu, Jun 28, 2018 at 06:20:52PM +0200, Marco Felsch wrote:
> > The TVP5150/1 decoders support different video input sources to their
> > AIP1A/B pins.
> > 
> > Possible configurations are as follows:
> >   - Analog Composite signal connected to AIP1A.
> >   - Analog Composite signal connected to AIP1B.
> >   - Analog S-Video Y (luminance) and C (chrominance)
> >     signals connected to AIP1A and AIP1B respectively.
> > 
> > This patch extends the device tree bindings documentation to describe
> > how the input connectors for these devices should be defined in a DT.
> > 
> > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > ---
> >  .../devicetree/bindings/media/i2c/tvp5150.txt | 118 +++++++++++++++++-
> >  1 file changed, 113 insertions(+), 5 deletions(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/media/i2c/tvp5150.txt b/Documentation/devicetree/bindings/media/i2c/tvp5150.txt
> > index 8c0fc1a26bf0..feed8c911c5e 100644
> > --- a/Documentation/devicetree/bindings/media/i2c/tvp5150.txt
> > +++ b/Documentation/devicetree/bindings/media/i2c/tvp5150.txt
> > @@ -12,11 +12,23 @@ Optional Properties:
> >  - pdn-gpios: phandle for the GPIO connected to the PDN pin, if any.
> >  - reset-gpios: phandle for the GPIO connected to the RESETB pin, if any.
> >  
> > -The device node must contain one 'port' child node for its digital output
> > -video port, in accordance with the video interface bindings defined in
> > -Documentation/devicetree/bindings/media/video-interfaces.txt.
> > +The device node must contain one 'port' child node per device input and output
> > +port, in accordance with the video interface bindings defined in
> > +Documentation/devicetree/bindings/media/video-interfaces.txt. The port nodes
> > +are numbered as follows
> >  
> > -Required Endpoint Properties for parallel synchronization:
> > +	  Name		Type		Port
> > +	--------------------------------------
> > +	  AIP1A		sink		0
> > +	  AIP1B		sink		1
> > +	  S-VIDEO	sink		2
> > +	  Y-OUT		src		3
> > +
> > +The device node must contain at least the Y-OUT port. Each input port must be
> > +linked to an endpoint defined in
> > +Documentation/devicetree/bindings/display/connector/analog-tv-connector.txt.
> > +
> > +Required Endpoint Properties for parallel synchronization on output port:
> >  
> >  - hsync-active: active state of the HSYNC signal. Must be <1> (HIGH).
> >  - vsync-active: active state of the VSYNC signal. Must be <1> (HIGH).
> > @@ -26,7 +38,9 @@ Required Endpoint Properties for parallel synchronization:
> >  If none of hsync-active, vsync-active and field-even-active is specified,
> >  the endpoint is assumed to use embedded BT.656 synchronization.
> >  
> > -Example:
> > +Examples:
> > +
> > +Only Output:
> >  
> >  &i2c2 {
> >  	...
> > @@ -37,6 +51,100 @@ Example:
> >  		reset-gpios = <&gpio6 7 GPIO_ACTIVE_LOW>;
> >  
> >  		port {
> > +			reg = <3>;
> > +			tvp5150_1: endpoint {
> > +				remote-endpoint = <&ccdc_ep>;
> > +			};
> > +		};
> > +	};
> > +};
> > +
> > +One Input:
> > +
> > +connector@0 {
> 
> Drop the unit-address as there is no reg property.

Yes, I will fix this and the others below in v2. Still wait for more
feedback from the media maintainers.

Regards,
Marco

> > +	compatible = "composite-video-connector";
> > +	label = "Composite0";
> > +
> > +	port {
> > +		comp0_out: endpoint {
> > +			remote-endpoint = <&tvp5150_comp0_in>;
> > +		};
> > +	};
> > +};
> > +
> > +&i2c2 {
> > +	...
> > +	tvp5150@5c {
> > +		compatible = "ti,tvp5150";
> > +		reg = <0x5c>;
> > +		pdn-gpios = <&gpio4 30 GPIO_ACTIVE_LOW>;
> > +		reset-gpios = <&gpio6 7 GPIO_ACTIVE_LOW>;
> > +
> > +		port@0 {
> > +			reg = <0>;
> > +			tvp5150_comp0_in: endpoint {
> > +				remote-endpoint = <&comp0_out>;
> > +			};
> > +		};
> > +
> > +		port@3 {
> > +			reg = <3>;
> > +			tvp5150_1: endpoint {
> > +				remote-endpoint = <&ccdc_ep>;
> > +			};
> > +		};
> > +	};
> > +};
> > +
> > +
> > +Two Inputs, different connector 12 on input AIP1A:
> > +
> > +connector@1 {
> 
> ditto
> 
> > +	compatible = "svideo-connector";
> > +	label = "S-Video";
> > +
> > +	port {
> > +		svideo_out: endpoint {
> > +			remote-endpoint = <&tvp5150_svideo_in>;
> > +		};
> > +	};
> > +};
> > +
> > +connector@12 {
> 
> ditto
> 
> > +	compatible = "composite-video-connector";
> > +	label = "Composite12";
> > +
> > +	port {
> > +		comp12_out: endpoint {
> > +			remote-endpoint = <&tvp5150_comp12_in>;
> > +		};
> > +	};
> > +};
> > +
> > +&i2c2 {
> > +	...
> > +	tvp5150@5c {
> > +		compatible = "ti,tvp5150";
> > +		reg = <0x5c>;
> > +		pdn-gpios = <&gpio4 30 GPIO_ACTIVE_LOW>;
> > +		reset-gpios = <&gpio6 7 GPIO_ACTIVE_LOW>;
> > +
> > +		port@0 {
> > +			reg = <0>;
> > +			tvp5150_comp12_in: endpoint {
> > +				remote-endpoint = <&comp12_out>;
> > +			};
> > +		};
> > +
> > +		port@2 {
> > +			reg = <2>;
> > +			tvp5150_svideo_in: endpoint {
> > +				remote-endpoint = <&svideo_out>;
> > +			};
> > +		};
> > +
> > +		port@3 {
> > +			reg = <3>;
> >  			tvp5150_1: endpoint {
> >  				remote-endpoint = <&ccdc_ep>;
> >  			};
> > -- 
> > 2.17.1
> > 
> 

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

* Re: [PATCH 13/22] [media] tvp5150: disable output while signal not locked
  2018-06-28 16:20 ` [PATCH 13/22] [media] tvp5150: disable output while signal not locked Marco Felsch
@ 2018-07-30 18:00   ` Mauro Carvalho Chehab
  2018-07-30 18:06     ` Mauro Carvalho Chehab
  2018-07-31  6:02     ` Marco Felsch
  0 siblings, 2 replies; 70+ messages in thread
From: Mauro Carvalho Chehab @ 2018-07-30 18:00 UTC (permalink / raw)
  To: Marco Felsch
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Em Thu, 28 Jun 2018 18:20:45 +0200
Marco Felsch <m.felsch@pengutronix.de> escreveu:

> From: Philipp Zabel <p.zabel@pengutronix.de>
> 
> To avoid short frames on stream start, keep output pins at high impedance
> while we are not properly locked onto the input signal.
> 
> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> ---
>  drivers/media/i2c/tvp5150.c | 39 ++++++++++++++++++++++++++-----------
>  1 file changed, 28 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> index d8bdbedd8826..27cfd08be3d2 100644
> --- a/drivers/media/i2c/tvp5150.c
> +++ b/drivers/media/i2c/tvp5150.c
> @@ -60,6 +60,7 @@ struct tvp5150 {
>  	v4l2_std_id detected_norm;
>  	u32 input;
>  	u32 output;
> +	u32 oe;
>  	int enable;
>  	bool lock;
>  
> @@ -799,14 +800,20 @@ static irqreturn_t tvp5150_isr(int irq, void *dev_id)
>  {
>  	struct tvp5150 *decoder = dev_id;
>  	struct regmap *map = decoder->regmap;
> -	unsigned int active = 0, status = 0;
> +	unsigned int mask, active = 0, status = 0;
> +
> +	mask = TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_SYNC_OE |
> +	       TVP5150_MISC_CTL_CLOCK_OE;
>  
>  	regmap_read(map, TVP5150_INT_STATUS_REG_A, &status);
>  	if (status) {
>  		regmap_write(map, TVP5150_INT_STATUS_REG_A, status);
>  
> -		if (status & TVP5150_INT_A_LOCK)
> +		if (status & TVP5150_INT_A_LOCK) {
>  			decoder->lock = !!(status & TVP5150_INT_A_LOCK_STATUS);
> +			regmap_update_bits(map, TVP5150_MISC_CTL, mask,
> +					   decoder->lock ? decoder->oe : 0);
> +		}
>  
>  		return IRQ_HANDLED;
>  	}
> @@ -872,10 +879,26 @@ static int tvp5150_enable(struct v4l2_subdev *sd)
>  	/* Disable autoswitch mode */
>  	tvp5150_set_std(sd, std);
>  
> -	if (decoder->mbus_type == V4L2_MBUS_PARALLEL)
> +	/*
> +	 * Enable the YCbCr and clock outputs. In discrete sync mode
> +	 * (non-BT.656) additionally enable the the sync outputs.
> +	 */
> +	switch (decoder->mbus_type) {
> +	case V4L2_MBUS_PARALLEL:
>  		/* 8-bit 4:2:2 YUV with discrete sync output */
>  		regmap_update_bits(decoder->regmap, TVP5150_DATA_RATE_SEL,
>  				   0x7, 0x0);
> +		decoder->oe = TVP5150_MISC_CTL_YCBCR_OE |
> +			      TVP5150_MISC_CTL_CLOCK_OE |
> +			      TVP5150_MISC_CTL_SYNC_OE;
> +		break;
> +	case V4L2_MBUS_BT656:
> +		decoder->oe = TVP5150_MISC_CTL_YCBCR_OE |
> +			      TVP5150_MISC_CTL_CLOCK_OE;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
>  
>  	return 0;
>  };
> @@ -1190,14 +1213,8 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
>  	if (enable) {
>  		tvp5150_enable(sd);
>  
> -		/*
> -		 * Enable the YCbCr and clock outputs. In discrete sync mode
> -		 * (non-BT.656) additionally enable the the sync outputs.
> -		 */
> -		val = TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_CLOCK_OE;
> -		if (decoder->mbus_type == V4L2_MBUS_PARALLEL)
> -			val |= TVP5150_MISC_CTL_SYNC_OE;
> -
> +		/* Enable outputs if decoder is locked */
> +		val = decoder->lock ? decoder->oe : 0;

Hmm... this only works if the tvp5150 has the interrupts enabled.

The code should be, instead:

	if (c->irq)
		val = decoder->lock ? decoder->oe : 0;
	else
		val = decoder->oe;


>  		int_val = TVP5150_INT_A_LOCK;
>  	}
>  



Thanks,
Mauro

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

* Re: [PATCH 13/22] [media] tvp5150: disable output while signal not locked
  2018-07-30 18:00   ` Mauro Carvalho Chehab
@ 2018-07-30 18:06     ` Mauro Carvalho Chehab
  2018-07-31  6:02     ` Marco Felsch
  1 sibling, 0 replies; 70+ messages in thread
From: Mauro Carvalho Chehab @ 2018-07-30 18:06 UTC (permalink / raw)
  To: Marco Felsch
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Em Mon, 30 Jul 2018 15:00:58 -0300
Mauro Carvalho Chehab <mchehab+samsung@kernel.org> escreveu:

> Em Thu, 28 Jun 2018 18:20:45 +0200
> Marco Felsch <m.felsch@pengutronix.de> escreveu:
> 
> > From: Philipp Zabel <p.zabel@pengutronix.de>
> > 
> > To avoid short frames on stream start, keep output pins at high impedance
> > while we are not properly locked onto the input signal.
> > 
> > Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > ---
> >  drivers/media/i2c/tvp5150.c | 39 ++++++++++++++++++++++++++-----------
> >  1 file changed, 28 insertions(+), 11 deletions(-)
> > 
> > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > index d8bdbedd8826..27cfd08be3d2 100644
> > --- a/drivers/media/i2c/tvp5150.c
> > +++ b/drivers/media/i2c/tvp5150.c
> > @@ -60,6 +60,7 @@ struct tvp5150 {
> >  	v4l2_std_id detected_norm;
> >  	u32 input;
> >  	u32 output;
> > +	u32 oe;
> >  	int enable;
> >  	bool lock;
> >  
> > @@ -799,14 +800,20 @@ static irqreturn_t tvp5150_isr(int irq, void *dev_id)
> >  {
> >  	struct tvp5150 *decoder = dev_id;
> >  	struct regmap *map = decoder->regmap;
> > -	unsigned int active = 0, status = 0;
> > +	unsigned int mask, active = 0, status = 0;
> > +
> > +	mask = TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_SYNC_OE |
> > +	       TVP5150_MISC_CTL_CLOCK_OE;
> >  
> >  	regmap_read(map, TVP5150_INT_STATUS_REG_A, &status);
> >  	if (status) {
> >  		regmap_write(map, TVP5150_INT_STATUS_REG_A, status);
> >  
> > -		if (status & TVP5150_INT_A_LOCK)
> > +		if (status & TVP5150_INT_A_LOCK) {
> >  			decoder->lock = !!(status & TVP5150_INT_A_LOCK_STATUS);
> > +			regmap_update_bits(map, TVP5150_MISC_CTL, mask,
> > +					   decoder->lock ? decoder->oe : 0);
> > +		}
> >  
> >  		return IRQ_HANDLED;
> >  	}
> > @@ -872,10 +879,26 @@ static int tvp5150_enable(struct v4l2_subdev *sd)
> >  	/* Disable autoswitch mode */
> >  	tvp5150_set_std(sd, std);
> >  
> > -	if (decoder->mbus_type == V4L2_MBUS_PARALLEL)
> > +	/*
> > +	 * Enable the YCbCr and clock outputs. In discrete sync mode
> > +	 * (non-BT.656) additionally enable the the sync outputs.
> > +	 */
> > +	switch (decoder->mbus_type) {
> > +	case V4L2_MBUS_PARALLEL:
> >  		/* 8-bit 4:2:2 YUV with discrete sync output */
> >  		regmap_update_bits(decoder->regmap, TVP5150_DATA_RATE_SEL,
> >  				   0x7, 0x0);
> > +		decoder->oe = TVP5150_MISC_CTL_YCBCR_OE |
> > +			      TVP5150_MISC_CTL_CLOCK_OE |
> > +			      TVP5150_MISC_CTL_SYNC_OE;
> > +		break;
> > +	case V4L2_MBUS_BT656:
> > +		decoder->oe = TVP5150_MISC_CTL_YCBCR_OE |
> > +			      TVP5150_MISC_CTL_CLOCK_OE;
> > +		break;
> > +	default:
> > +		return -EINVAL;
> > +	}
> >  
> >  	return 0;
> >  };
> > @@ -1190,14 +1213,8 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
> >  	if (enable) {
> >  		tvp5150_enable(sd);
> >  
> > -		/*
> > -		 * Enable the YCbCr and clock outputs. In discrete sync mode
> > -		 * (non-BT.656) additionally enable the the sync outputs.
> > -		 */
> > -		val = TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_CLOCK_OE;
> > -		if (decoder->mbus_type == V4L2_MBUS_PARALLEL)
> > -			val |= TVP5150_MISC_CTL_SYNC_OE;
> > -
> > +		/* Enable outputs if decoder is locked */
> > +		val = decoder->lock ? decoder->oe : 0;
> 
> Hmm... this only works if the tvp5150 has the interrupts enabled.
> 
> The code should be, instead:
> 
> 	if (c->irq)
> 		val = decoder->lock ? decoder->oe : 0;
> 	else
> 		val = decoder->oe;
> 
> 
> >  		int_val = TVP5150_INT_A_LOCK;
> >  	}
> >  

In other words, I believe we need the enclosed patch to avoid causing
regressions on existing drivers.

I intend to run a test here with this tvp5150 series before merging,
in order to be sure that em28xx+tvp5150 devices will keep working.

Regards,
Mauro


[PATCH] tvp5150: if IRQ is not enabled, don't disable inputs at s_stream

The new IRQ logic sets decoder->lock if signal is locked.
That should work fine when IRQ is used, but not all tvp5150
clients set it.

So, keep the previous logic if IRQ is not enabled for tvp5150.

Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>

diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index f7c9203a3923..777e0e16787e 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -1214,7 +1214,10 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
 		tvp5150_enable(sd);
 
 		/* Enable outputs if decoder is locked */
-		val = decoder->lock ? decoder->oe : 0;
+		if (decoder->irq)
+			val = decoder->lock ? decoder->oe : 0;
+		else
+			val = decoder->oe;
 		int_val = TVP5150_INT_A_LOCK;
 	}
 


Thanks,
Mauro

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

* Re: [PATCH 16/22] [media] tvp5150: add querystd
  2018-06-28 16:20 ` [PATCH 16/22] [media] tvp5150: add querystd Marco Felsch
@ 2018-07-30 18:09   ` Mauro Carvalho Chehab
  2018-08-01 13:21     ` Marco Felsch
  0 siblings, 1 reply; 70+ messages in thread
From: Mauro Carvalho Chehab @ 2018-07-30 18:09 UTC (permalink / raw)
  To: Marco Felsch
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Em Thu, 28 Jun 2018 18:20:48 +0200
Marco Felsch <m.felsch@pengutronix.de> escreveu:

> From: Philipp Zabel <p.zabel@pengutronix.de>
> 
> Add the querystd video_op and make it return V4L2_STD_UNKNOWN while the
> TVP5150 is not locked to a signal.
> 
> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> ---
>  drivers/media/i2c/tvp5150.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> index 99d887936ea0..1990aaa17749 100644
> --- a/drivers/media/i2c/tvp5150.c
> +++ b/drivers/media/i2c/tvp5150.c
> @@ -796,6 +796,15 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
>  	}
>  }
>  
> +static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
> +{
> +	struct tvp5150 *decoder = to_tvp5150(sd);
> +
> +	*std_id = decoder->lock ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;

This patch requires rework. What happens when a device doesn't have
IRQ enabled? Perhaps it should, instead, read some register in order
to check for the locking status, as this would work on both cases.

> +
> +	return 0;
> +}
> +
>  static const struct v4l2_event tvp5150_ev_fmt = {
>  	.type = V4L2_EVENT_SOURCE_CHANGE,
>  	.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
> @@ -1408,6 +1417,7 @@ static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = {
>  
>  static const struct v4l2_subdev_video_ops tvp5150_video_ops = {
>  	.s_std = tvp5150_s_std,
> +	.querystd = tvp5150_querystd,
>  	.s_stream = tvp5150_s_stream,
>  	.s_routing = tvp5150_s_routing,
>  	.g_mbus_config = tvp5150_g_mbus_config,



Thanks,
Mauro

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

* Re: [PATCH 18/22] partial revert of "[media] tvp5150: add HW input connectors support"
  2018-06-28 16:20 ` [PATCH 18/22] partial revert of "[media] tvp5150: add HW input connectors support" Marco Felsch
  2018-07-03 23:19   ` Rob Herring
@ 2018-07-30 18:18   ` Mauro Carvalho Chehab
  2018-07-31  7:01     ` Marco Felsch
  2018-07-31  8:52     ` Javier Martinez Canillas
  1 sibling, 2 replies; 70+ messages in thread
From: Mauro Carvalho Chehab @ 2018-07-30 18:18 UTC (permalink / raw)
  To: Marco Felsch
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Em Thu, 28 Jun 2018 18:20:50 +0200
Marco Felsch <m.felsch@pengutronix.de> escreveu:

> From: Javier Martinez Canillas <javierm@redhat.com>
> 
> Commit f7b4b54e6364 ("[media] tvp5150: add HW input connectors support")
> added input signals support for the tvp5150, but the approach was found
> to be incorrect so the corresponding DT binding commit 82c2ffeb217a
> ("[media] tvp5150: document input connectors DT bindings") was reverted.
> 
> This left the driver with an undocumented (and wrong) DT parsing logic,
> so lets get rid of this code as well until the input connectors support
> is implemented properly.
> 
> It's a partial revert due other patches added on top of mentioned commit
> not allowing the commit to be reverted cleanly anymore. But all the code
> related to the DT parsing logic and input entities creation are removed.
> 
> Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> [m.felsch@pengutronix.de: rm TVP5150_INPUT_NUM define]
> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> ---

...

> -static int tvp5150_registered(struct v4l2_subdev *sd)
> -{
> -#ifdef CONFIG_MEDIA_CONTROLLER
> -	struct tvp5150 *decoder = to_tvp5150(sd);
> -	int ret = 0;
> -	int i;
> -
> -	for (i = 0; i < TVP5150_INPUT_NUM; i++) {
> -		struct media_entity *input = &decoder->input_ent[i];
> -		struct media_pad *pad = &decoder->input_pad[i];
> -
> -		if (!input->name)
> -			continue;
> -
> -		decoder->input_pad[i].flags = MEDIA_PAD_FL_SOURCE;
> -
> -		ret = media_entity_pads_init(input, 1, pad);
> -		if (ret < 0)
> -			return ret;
> -
> -		ret = media_device_register_entity(sd->v4l2_dev->mdev, input);
> -		if (ret < 0)
> -			return ret;
> -
> -		ret = media_create_pad_link(input, 0, &sd->entity,
> -					    DEMOD_PAD_IF_INPUT, 0);
> -		if (ret < 0) {
> -			media_device_unregister_entity(input);
> -			return ret;
> -		}
> -	}
> -#endif

Hmm... I suspect that reverting this part may cause problems for drivers
like em28xx when compiled with MC, as they rely that the supported demods
will have 3 pads (DEMOD_NUM_PADS).

Thanks,
Mauro

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

* Re: [PATCH 19/22] [media] tvp5150: add input source selection of_graph support
  2018-06-28 16:20 ` [PATCH 19/22] [media] tvp5150: add input source selection of_graph support Marco Felsch
@ 2018-07-30 18:29   ` Mauro Carvalho Chehab
  2018-08-08 15:29     ` Marco Felsch
  0 siblings, 1 reply; 70+ messages in thread
From: Mauro Carvalho Chehab @ 2018-07-30 18:29 UTC (permalink / raw)
  To: Marco Felsch
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Em Thu, 28 Jun 2018 18:20:51 +0200
Marco Felsch <m.felsch@pengutronix.de> escreveu:

> The currrent driver layout had the following layout:
>                +----------------+
>  +-------+     |    TVP5150     |
>  | Comp0 +--+  |                |
>  +-------+  |  |          +-----+
>  +-------+  |  +------+   | Src |
>  | Comp1 +--+--|Sink  |   +-----+
>  +-------+  |  +------+   +-----+
> +--------+  |  |          | Src |
> | SVideo +--+  |          +-----+
> +--------+     +----------------+
> 
> Since the device tree abstracts the real hardware this layout is not
> correct, because the TVP5150 has 3 physical ports (2 input, 1 output).
> Furthermore this layout assumes that there is an additional external mux
> in front of the TVP5150. This is not correct because the TVP5150 does
> the muxing work. The corresponding of_graph layout will look like:
> 	tvp5150 {
> 		....
> 		port {
> 			reg = <0>;
> 			endpoint@0 {...};
> 			endpoint@1 {...};
> 			endpoint@2 {...};
> 		};
> 
> 	};
> 
> This patch change the layout to:
>              +----------------+
>              |    TVP5150     |
>  +-------+   +------+         |
>  | Comp0 +---+ Sink |         |
>  +-------+   +------+         |
>  +-------+   +------+   +-----+
>  | Comp1 +---+ Sink |   | Src |
>  +-------+   +------+   +-----+
> +--------+   +------+         |
> | SVideo +---+ Sink |         |
> +--------+   +------+         |
>              +----------------+
> 
> To keep things easy an additional 'virtual' S-Video port is added. More
> information about the port mapping can be found in the device tree
> binding documentation. The connector entities Comp0/1, SVideo are created
> only if they are connected to the correct port. If more than one connector
> is available the media_entity_operations.link_setup() callback ensures that
> only one connector is active. To change the input src the link between
> the TVP5150 pad and the connector must be disabled, then a new link can
> be enabled.
> 
> The patch tries to reduce the '#ifdef CONFIG_MEDIA_CONTROLLER' usage to
> a minimum.
> 
> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> ---
>  drivers/media/i2c/tvp5150.c | 322 ++++++++++++++++++++++++++++++++----
>  1 file changed, 287 insertions(+), 35 deletions(-)
> 
> diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> index a6fec569a610..6ac29c62d99b 100644
> --- a/drivers/media/i2c/tvp5150.c
> +++ b/drivers/media/i2c/tvp5150.c
> @@ -44,10 +44,30 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
>  
>  #define dprintk0(__dev, __arg...) dev_dbg_lvl(__dev, 0, 0, __arg)
>  
> +enum tvp5150_ports {
> +	TVP5150_PORT_AIP1A = TVP5150_COMPOSITE0,
> +	TVP5150_PORT_AIP1B,
> +	/* s-video port is a virtual port */
> +	TVP5150_PORT_SVIDEO,
> +	TVP5150_PORT_YOUT,
> +	TVP5150_PORT_NUM,
> +};
> +
> +#ifdef CONFIG_MEDIA_CONTROLLER
> +struct tvp5150_connector {
> +	struct media_entity con;
> +	struct media_pad pad;
> +	unsigned int port_num;
> +};
> +#endif
> +
>  struct tvp5150 {
>  	struct v4l2_subdev sd;
> +	struct device_node *endpoints[TVP5150_PORT_NUM];
>  #ifdef CONFIG_MEDIA_CONTROLLER
> -	struct media_pad pads[DEMOD_NUM_PADS];
> +	struct media_pad pads[TVP5150_PORT_NUM];

This will cause problems with the current code.

When we designed the MC version 2 code, the idea were to allow
set properties to entities and to the inputs, but the code
was never submitted upstream.

A decoder may have several different types of inputs and outputs.
Several designs allow using different types of decoders, being
saa711x and tvp5150 the most popular ones. Well, depending on
the device, the number of PADs and the signals they carry can
be different.

Without a way to "taint" a pad to the signal it contains, 
while waiting for the properties API, we added a code that
"fixed" the PADs to a certain number. This way, Kernelspace could
use the pad "number" as a way to identify the type of signal a
PAD carries.

The PC consumer drivers use those numbers in order to build the
MC graph[1].

A change on this would require adding a property to the pad, in
order to indicate the type of signal it provides (RF, luminance IF,
chroma IF, audio IF, I2S audio, ...), and to change
v4l2_mc_create_media_graph() accordingly.


[1] See drivers/media/v4l2-core/v4l2-mc.c at v4l2_mc_create_media_graph() func.



> +	struct tvp5150_connector *connectors;
> +	int active;
>  #endif
>  	struct v4l2_ctrl_handler hdl;
>  	struct v4l2_rect rect;
> @@ -990,7 +1010,7 @@ static int tvp5150_fill_fmt(struct v4l2_subdev *sd,
>  	struct v4l2_rect *__crop;
>  	struct tvp5150 *decoder = to_tvp5150(sd);
>  
> -	if (!format || (format->pad != DEMOD_PAD_VID_OUT))
> +	if (!format || (format->pad != TVP5150_PORT_YOUT))
>  		return -EINVAL;
>  
>  	f = &format->format;
> @@ -1189,6 +1209,62 @@ static int tvp5150_enum_frame_size(struct v4l2_subdev *sd,
>  	return 0;
>  }
>  
> +/****************************************************************************
> + *			Media entity ops
> + ****************************************************************************/
> +#ifdef CONFIG_MEDIA_CONTROLLER
> +static int tvp5150_s_routing(struct v4l2_subdev *sd, u32 input, u32 output,
> +			     u32 config);
> +static int tvp5150_link_setup(struct media_entity *entity,
> +			      const struct media_pad *local,
> +			      const struct media_pad *remote, u32 flags)
> +{
> +	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
> +	struct tvp5150 *decoder = to_tvp5150(sd);
> +	int ret = 0;
> +
> +	/*
> +	 * The tvp state is determined by the enabled sink pad link.
> +	 * Enabling or disabling the source pad link has no effect.
> +	 */
> +	if (local->flags & MEDIA_PAD_FL_SOURCE)
> +		return 0;
> +
> +	dev_dbg(sd->dev, "link setup '%s':%d->'%s':%d[%d]",
> +		remote->entity->name, remote->index, local->entity->name,
> +		local->index, flags & MEDIA_LNK_FL_ENABLED);
> +
> +	if (flags & MEDIA_LNK_FL_ENABLED) {
> +		if (decoder->active == local->index)
> +			goto out;
> +		if (decoder->active >= 0) {
> +			ret = -EBUSY;
> +			goto out;
> +		}
> +
> +		dev_dbg(sd->dev, "Setting %d active\n", local->index);
> +		decoder->active = local->index;
> +		tvp5150_s_routing(sd, local->index, TVP5150_NORMAL, 0);
> +	} else {
> +		if (decoder->active != local->index)
> +			goto out;
> +
> +		dev_dbg(sd->dev, "going inactive\n");
> +		decoder->active = -1;
> +		/*
> +		 * Output black screen for deselected input if TVP5150 variant
> +		 * supports this.
> +		 */
> +		tvp5150_s_routing(sd, local->index, TVP5150_BLACK_SCREEN, 0);
> +	}
> +out:
> +	return ret;
> +}
> +
> +static const struct media_entity_operations tvp5150_sd_media_ops = {
> +	.link_setup = tvp5150_link_setup,
> +};
> +#endif
>  /****************************************************************************
>  			I2C Command
>   ****************************************************************************/
> @@ -1333,6 +1409,50 @@ static int tvp5150_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
>  	return 0;
>  }
>  
> +static int tvp5150_get_con_num(struct tvp5150 *decoder)
> +{
> +	unsigned int i, num = 0;
> +
> +	for (i = 0; i < TVP5150_PORT_NUM - 1; i++)
> +		if (decoder->endpoints[i])
> +			num++;
> +	return num;
> +}
> +
> +static int tvp5150_registered(struct v4l2_subdev *sd)
> +{
> +#ifdef CONFIG_MEDIA_CONTROLLER
> +	struct tvp5150 *decoder = to_tvp5150(sd);
> +	unsigned int i, con_num;
> +	int ret;
> +
> +	con_num = tvp5150_get_con_num(decoder);
> +	for (i = 0; i < con_num; i++) {
> +		struct media_entity *con = &decoder->connectors[i].con;
> +		struct media_pad *pad = &decoder->connectors[i].pad;
> +		unsigned int port = decoder->connectors[i].port_num;
> +
> +		pad->flags = MEDIA_PAD_FL_SOURCE;
> +		ret = media_entity_pads_init(con, 1, pad);
> +		if (ret < 0)
> +			return ret;
> +
> +		ret = media_device_register_entity(sd->v4l2_dev->mdev, con);
> +		if (ret < 0)
> +			return ret;
> +
> +		ret = media_create_pad_link(con, 0, &sd->entity, port, 0);
> +		if (ret < 0) {
> +			media_device_unregister_entity(con);
> +			return ret;
> +		}
> +
> +	}
> +#endif
> +	return 0;
> +}
> +
> +
>  /* ----------------------------------------------------------------------- */
>  
>  static const struct v4l2_ctrl_ops tvp5150_ctrl_ops = {
> @@ -1386,6 +1506,10 @@ static const struct v4l2_subdev_ops tvp5150_ops = {
>  	.pad = &tvp5150_pad_ops,
>  };
>  
> +static const struct v4l2_subdev_internal_ops tvp5150_internal_ops = {
> +	.registered = tvp5150_registered,
> +};
> +
>  /****************************************************************************
>  			I2C Client & Driver
>   ****************************************************************************/
> @@ -1534,38 +1658,171 @@ static int tvp5150_init(struct i2c_client *c)
>  	return 0;
>  }
>  
> +static int tvp5150_mc_init(struct v4l2_subdev *sd)
> +{
> +#if defined(CONFIG_MEDIA_CONTROLLER)
> +	struct tvp5150 *decoder = to_tvp5150(sd);
> +	struct device *dev = decoder->sd.dev;
> +	struct device_node *rp;
> +	unsigned int con_num = 0;
> +	unsigned int i, j;
> +	int ret;
> +
> +	sd->entity.ops = &tvp5150_sd_media_ops;
> +	sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
> +
> +	/* Initialize all TVP5150 pads */
> +	for (i = 0; i < TVP5150_PORT_NUM; i++)
> +		decoder->pads[i].flags = (i < TVP5150_PORT_NUM - 1) ?
> +							MEDIA_PAD_FL_SINK :
> +							MEDIA_PAD_FL_SOURCE;
> +	ret = media_entity_pads_init(&sd->entity, TVP5150_PORT_NUM,
> +				     decoder->pads);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Allocate and initialize all available input connectors */
> +	con_num = tvp5150_get_con_num(decoder);
> +	if (!con_num)
> +		return 0;
> +	decoder->connectors = devm_kcalloc(dev, con_num,
> +					   sizeof(*decoder->connectors),
> +					   GFP_KERNEL);
> +	if (!decoder->connectors)
> +		return -ENOMEM;
> +
> +	for (i = 0, j = 0; i < TVP5150_PORT_NUM - 1; i++) {
> +		if (!decoder->endpoints[i])
> +			continue;
> +
> +		switch (i) {
> +		case TVP5150_PORT_AIP1A:
> +		case TVP5150_PORT_AIP1B:
> +			decoder->connectors[j].con.function =
> +						MEDIA_ENT_F_CONN_COMPOSITE;
> +			break;
> +		case TVP5150_PORT_SVIDEO:
> +			decoder->connectors[j].con.function =
> +						MEDIA_ENT_F_CONN_SVIDEO;
> +			break;
> +		}
> +
> +		decoder->connectors[j].con.flags = MEDIA_ENT_FL_CONNECTOR;
> +		rp = of_graph_get_remote_port_parent(decoder->endpoints[i]);
> +		ret = of_property_read_string(rp, "label",
> +					      &decoder->connectors[j].con.name);
> +		if (ret < 0)
> +			return ret;
> +		decoder->connectors[j].port_num = i;
> +
> +		j++;
> +	}
> +#endif
> +	return 0;
> +}
> +
> +static bool tvp5150_valid_input(struct device_node *endpoint,
> +				unsigned int port)
> +{
> +	struct device_node *rp = of_graph_get_remote_port_parent(endpoint);
> +	const char *input;
> +	int ret;
> +
> +	switch (port) {
> +	case TVP5150_PORT_AIP1A:
> +	case TVP5150_PORT_AIP1B:
> +		ret = of_device_is_compatible(rp, "composite-video-connector");
> +		if (!ret)
> +			return false;
> +		break;
> +	case TVP5150_PORT_SVIDEO:
> +		ret = of_device_is_compatible(rp, "svideo-connector");
> +		if (!ret)
> +			return false;
> +	}
> +
> +	ret = of_property_read_string(rp, "label", &input);
> +	if (ret < 0)
> +		return false;
> +
> +	return true;
> +}
> +
>  static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np)
>  {
> +	struct device *dev = decoder->sd.dev;
>  	struct v4l2_fwnode_endpoint bus_cfg;
> -	struct device_node *ep;
> +	struct device_node *ep_np;
>  	unsigned int flags;
> -	int ret = 0;
> +	int ret;
> +	bool found = false;
>  
> -	ep = of_graph_get_next_endpoint(np, NULL);
> -	if (!ep)
> -		return -EINVAL;
> +	for_each_endpoint_of_node(np, ep_np) {
> +		struct of_endpoint ep;
>  
> -	ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &bus_cfg);
> -	if (ret)
> -		goto err;
> -
> -	flags = bus_cfg.bus.parallel.flags;
> +		of_graph_parse_endpoint(ep_np, &ep);
> +		if (decoder->endpoints[ep.port]) {
> +			dev_warn(dev,
> +				 "Multiple port endpoints are not supported\n");
> +			continue;
> +		}
>  
> -	if (bus_cfg.bus_type == V4L2_MBUS_PARALLEL &&
> -	    !(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH &&
> -	      flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH &&
> -	      flags & V4L2_MBUS_FIELD_EVEN_LOW)) {
> -		ret = -EINVAL;
> -		goto err;
> -	}
> +		switch (ep.port) {
> +		     /* Use common tvp5150_valid_input() for all inputs */
> +		case TVP5150_PORT_AIP1A:
> +		case TVP5150_PORT_AIP1B:
> +		case TVP5150_PORT_SVIDEO:
> +			if (!tvp5150_valid_input(ep_np, ep.port)) {
> +				dev_err(dev,
> +					"Invalid endpoint %pOF on port %d\n",
> +					ep.local_node, ep.port);
> +				ret = -EINVAL;
> +				goto err;
> +			}
> +			break;
> +		case TVP5150_PORT_YOUT:
> +			ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_np),
> +							 &bus_cfg);
> +			if (ret)
> +				goto err;
> +
> +			flags = bus_cfg.bus.parallel.flags;
> +
> +			if (bus_cfg.bus_type == V4L2_MBUS_PARALLEL &&
> +			    !(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH &&
> +			      flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH &&
> +			      flags & V4L2_MBUS_FIELD_EVEN_LOW)) {
> +				ret = -EINVAL;
> +				goto err;
> +			}
> +
> +			decoder->mbus_type = bus_cfg.bus_type;
> +			break;
> +		default:
> +			dev_err(dev, "Invalid port %d for endpoint %pOF\n",
> +				ep.port, ep.local_node);
> +			ret = -EINVAL;
> +			goto err;
> +		}
>  
> -	decoder->mbus_type = bus_cfg.bus_type;
> +		of_node_get(ep_np);
> +		decoder->endpoints[ep.port] = ep_np;
>  
> +		found = true;
> +	}
> +	return found ? 0 : -ENODEV;
>  err:
> -	of_node_put(ep);
>  	return ret;
>  }
>  
> +static void tvp5150_dt_cleanup(struct tvp5150 *decoder)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < TVP5150_PORT_NUM; i++)
> +		of_node_put(decoder->endpoints[i]);
> +}
> +
>  static const char * const tvp5150_test_patterns[2] = {
>  	"Disabled",
>  	"Black screen"
> @@ -1604,7 +1861,7 @@ static int tvp5150_probe(struct i2c_client *c,
>  		res = tvp5150_parse_dt(core, np);
>  		if (res) {
>  			dev_err(sd->dev, "DT parsing error: %d\n", res);
> -			return res;
> +			goto err_cleanup_dt;
>  		}
>  	} else {
>  		/* Default to BT.656 embedded sync */
> @@ -1612,24 +1869,16 @@ static int tvp5150_probe(struct i2c_client *c,
>  	}
>  
>  	v4l2_i2c_subdev_init(sd, c, &tvp5150_ops);
> +	sd->internal_ops = &tvp5150_internal_ops;
>  	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
>  
> -#if defined(CONFIG_MEDIA_CONTROLLER)
> -	core->pads[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
> -	core->pads[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
> -	core->pads[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE;
> -
> -	sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
> -
> -	res = media_entity_pads_init(&sd->entity, DEMOD_NUM_PADS, core->pads);
> -	if (res < 0)
> -		return res;
> -
> -#endif
> +	res = tvp5150_mc_init(sd);
> +	if (res)
> +		goto err_cleanup_dt;
>  
>  	res = tvp5150_detect_version(core);
>  	if (res < 0)
> -		return res;
> +		goto err_cleanup_dt;
>  
>  	core->norm = V4L2_STD_ALL;	/* Default is autodetect */
>  	core->detected_norm = V4L2_STD_UNKNOWN;
> @@ -1683,6 +1932,9 @@ static int tvp5150_probe(struct i2c_client *c,
>  err:
>  	v4l2_ctrl_handler_free(&core->hdl);
>  	return res;
> +err_cleanup_dt:
> +	tvp5150_dt_cleanup(core);
> +	return res;
>  }
>  
>  static int tvp5150_remove(struct i2c_client *c)



Thanks,
Mauro

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

* Re: [PATCH 06/22] [media] tvp5150: add FORMAT_TRY support for get/set selection handlers
  2018-06-28 16:20 ` [PATCH 06/22] [media] tvp5150: add FORMAT_TRY support for get/set selection handlers Marco Felsch
@ 2018-07-31  0:01   ` Mauro Carvalho Chehab
  2018-08-09 13:52     ` Marco Felsch
  0 siblings, 1 reply; 70+ messages in thread
From: Mauro Carvalho Chehab @ 2018-07-31  0:01 UTC (permalink / raw)
  To: Marco Felsch
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Em Thu, 28 Jun 2018 18:20:38 +0200
Marco Felsch <m.felsch@pengutronix.de> escreveu:

> Since commit 10d5509c8d50 ("[media] v4l2: remove g/s_crop from video ops")
> the 'which' field for set/get_selection must be FORMAT_ACTIVE. There is
> no way to try different selections. The patch adds a helper function to
> select the correct selection memory space (sub-device file handle or
> driver state) which will be set/returned.
> 
> The TVP5150 AVID will be updated if the 'which' field is FORMAT_ACTIVE
> and the requested selection rectangle differs from the already set one.
> 
> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> ---
>  drivers/media/i2c/tvp5150.c | 107 ++++++++++++++++++++++++------------
>  1 file changed, 73 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> index d150487cc2d1..29eaf8166f25 100644
> --- a/drivers/media/i2c/tvp5150.c
> +++ b/drivers/media/i2c/tvp5150.c
> @@ -18,6 +18,7 @@
>  #include <media/v4l2-ctrls.h>
>  #include <media/v4l2-fwnode.h>
>  #include <media/v4l2-mc.h>
> +#include <media/v4l2-rect.h>
>  
>  #include "tvp5150_reg.h"
>  
> @@ -846,20 +847,38 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
>  	}
>  }
>  
> +static struct v4l2_rect *
> +__tvp5150_get_pad_crop(struct tvp5150 *decoder,
> +		       struct v4l2_subdev_pad_config *cfg, unsigned int pad,
> +		       enum v4l2_subdev_format_whence which)
> +{
> +	switch (which) {
> +	case V4L2_SUBDEV_FORMAT_TRY:
> +		return v4l2_subdev_get_try_crop(&decoder->sd, cfg, pad);

This is not ok. It causes compilation breakage if the subdev API is not
selected:

drivers/media/i2c/tvp5150.c: In function ‘__tvp5150_get_pad_crop’:
drivers/media/i2c/tvp5150.c:857:10: error: implicit declaration of function ‘v4l2_subdev_get_try_crop’; did you mean ‘v4l2_subdev_has_op’? [-Werror=implicit-function-declaration]
   return v4l2_subdev_get_try_crop(&decoder->sd, cfg, pad);
          ^~~~~~~~~~~~~~~~~~~~~~~~
          v4l2_subdev_has_op
drivers/media/i2c/tvp5150.c:857:10: warning: returning ‘int’ from a function with return type ‘struct v4l2_rect *’ makes pointer from integer without a cast [-Wint-conversion]
   return v4l2_subdev_get_try_crop(&decoder->sd, cfg, pad);
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The logic should keep working both with and without subdev API.


> +	case V4L2_SUBDEV_FORMAT_ACTIVE:
> +		return &decoder->rect;
> +	default:
> +		return NULL;
> +	}
> +}
> +
>  static int tvp5150_fill_fmt(struct v4l2_subdev *sd,
>  		struct v4l2_subdev_pad_config *cfg,
>  		struct v4l2_subdev_format *format)
>  {
>  	struct v4l2_mbus_framefmt *f;
> +	struct v4l2_rect *__crop;
>  	struct tvp5150 *decoder = to_tvp5150(sd);
>  
>  	if (!format || (format->pad != DEMOD_PAD_VID_OUT))
>  		return -EINVAL;
>  
>  	f = &format->format;
> +	__crop = __tvp5150_get_pad_crop(decoder, cfg, format->pad,
> +					format->which);
>  
> -	f->width = decoder->rect.width;
> -	f->height = decoder->rect.height / 2;
> +	f->width = __crop->width;
> +	f->height = __crop->height / 2;
>  
>  	f->code = MEDIA_BUS_FMT_UYVY8_2X8;
>  	f->field = V4L2_FIELD_ALTERNATE;
> @@ -870,17 +889,51 @@ static int tvp5150_fill_fmt(struct v4l2_subdev *sd,
>  	return 0;
>  }
>  
> +unsigned int tvp5150_get_hmax(struct v4l2_subdev *sd)
> +{
> +	struct tvp5150 *decoder = to_tvp5150(sd);
> +	v4l2_std_id std;
> +
> +	/* Calculate height based on current standard */
> +	if (decoder->norm == V4L2_STD_ALL)
> +		std = tvp5150_read_std(sd);
> +	else
> +		std = decoder->norm;
> +
> +	return (std & V4L2_STD_525_60) ?
> +		TVP5150_V_MAX_525_60 : TVP5150_V_MAX_OTHERS;
> +}
> +
> +static inline void
> +__tvp5150_set_selection(struct v4l2_subdev *sd, struct v4l2_rect rect)
> +{
> +	struct tvp5150 *decoder = to_tvp5150(sd);
> +	unsigned int hmax = tvp5150_get_hmax(sd);
> +
> +	regmap_write(decoder->regmap, TVP5150_VERT_BLANKING_START, rect.top);
> +	regmap_write(decoder->regmap, TVP5150_VERT_BLANKING_STOP,
> +		     rect.top + rect.height - hmax);
> +	regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_ST_MSB,
> +		     rect.left >> TVP5150_CROP_SHIFT);
> +	regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_ST_LSB,
> +		     rect.left | (1 << TVP5150_CROP_SHIFT));
> +	regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_STP_MSB,
> +		     (rect.left + rect.width - TVP5150_MAX_CROP_LEFT) >>
> +		     TVP5150_CROP_SHIFT);
> +	regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_STP_LSB,
> +		     rect.left + rect.width - TVP5150_MAX_CROP_LEFT);
> +}
> +
>  static int tvp5150_set_selection(struct v4l2_subdev *sd,
>  				 struct v4l2_subdev_pad_config *cfg,
>  				 struct v4l2_subdev_selection *sel)
>  {
>  	struct tvp5150 *decoder = to_tvp5150(sd);
>  	struct v4l2_rect rect = sel->r;
> -	v4l2_std_id std;
> -	int hmax;
> +	struct v4l2_rect *__crop;
> +	unsigned int hmax;
>  
> -	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
> -	    sel->target != V4L2_SEL_TGT_CROP)
> +	if (sel->target != V4L2_SEL_TGT_CROP)
>  		return -EINVAL;
>  
>  	dev_dbg_lvl(sd->dev, 1, debug, "%s left=%d, top=%d, width=%d, height=%d\n",
> @@ -889,17 +942,7 @@ static int tvp5150_set_selection(struct v4l2_subdev *sd,
>  	/* tvp5150 has some special limits */
>  	rect.left = clamp(rect.left, 0, TVP5150_MAX_CROP_LEFT);
>  	rect.top = clamp(rect.top, 0, TVP5150_MAX_CROP_TOP);
> -
> -	/* Calculate height based on current standard */
> -	if (decoder->norm == V4L2_STD_ALL)
> -		std = tvp5150_read_std(sd);
> -	else
> -		std = decoder->norm;
> -
> -	if (std & V4L2_STD_525_60)
> -		hmax = TVP5150_V_MAX_525_60;
> -	else
> -		hmax = TVP5150_V_MAX_OTHERS;
> +	hmax = tvp5150_get_hmax(sd);
>  
>  	/*
>  	 * alignments:
> @@ -912,20 +955,18 @@ static int tvp5150_set_selection(struct v4l2_subdev *sd,
>  			      hmax - TVP5150_MAX_CROP_TOP - rect.top,
>  			      hmax - rect.top, 0, 0);
>  
> -	regmap_write(decoder->regmap, TVP5150_VERT_BLANKING_START, rect.top);
> -	regmap_write(decoder->regmap, TVP5150_VERT_BLANKING_STOP,
> -		      rect.top + rect.height - hmax);
> -	regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_ST_MSB,
> -		      rect.left >> TVP5150_CROP_SHIFT);
> -	regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_ST_LSB,
> -		      rect.left | (1 << TVP5150_CROP_SHIFT));
> -	regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_STP_MSB,
> -		      (rect.left + rect.width - TVP5150_MAX_CROP_LEFT) >>
> -		      TVP5150_CROP_SHIFT);
> -	regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_STP_LSB,
> -		      rect.left + rect.width - TVP5150_MAX_CROP_LEFT);
> +	__crop = __tvp5150_get_pad_crop(decoder, cfg, sel->pad,
> +						  sel->which);
> +
> +	/*
> +	 * Update output image size if the selection (crop) rectangle size or
> +	 * position has been modified.
> +	 */
> +	if (!v4l2_rect_equal(&rect, __crop))
> +		if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE)
> +			__tvp5150_set_selection(sd, rect);
>  
> -	decoder->rect = rect;
> +	*__crop = rect;
>  
>  	return 0;
>  }
> @@ -937,9 +978,6 @@ static int tvp5150_get_selection(struct v4l2_subdev *sd,
>  	struct tvp5150 *decoder = container_of(sd, struct tvp5150, sd);
>  	v4l2_std_id std;
>  
> -	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
> -		return -EINVAL;
> -
>  	switch (sel->target) {
>  	case V4L2_SEL_TGT_CROP_BOUNDS:
>  	case V4L2_SEL_TGT_CROP_DEFAULT:
> @@ -958,7 +996,8 @@ static int tvp5150_get_selection(struct v4l2_subdev *sd,
>  			sel->r.height = TVP5150_V_MAX_OTHERS;
>  		return 0;
>  	case V4L2_SEL_TGT_CROP:
> -		sel->r = decoder->rect;
> +		sel->r = *__tvp5150_get_pad_crop(decoder, cfg, sel->pad,
> +						      sel->which);
>  		return 0;
>  	default:
>  		return -EINVAL;



Thanks,
Mauro

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

* Re: [PATCH 13/22] [media] tvp5150: disable output while signal not locked
  2018-07-30 18:00   ` Mauro Carvalho Chehab
  2018-07-30 18:06     ` Mauro Carvalho Chehab
@ 2018-07-31  6:02     ` Marco Felsch
  1 sibling, 0 replies; 70+ messages in thread
From: Marco Felsch @ 2018-07-31  6:02 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Hi Mauro,

thanks for your feedback.

On 18-07-30 15:00, Mauro Carvalho Chehab wrote:
> Em Thu, 28 Jun 2018 18:20:45 +0200
> Marco Felsch <m.felsch@pengutronix.de> escreveu:
> 
> > From: Philipp Zabel <p.zabel@pengutronix.de>
> > 
> > To avoid short frames on stream start, keep output pins at high impedance
> > while we are not properly locked onto the input signal.
> > 
> > Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > ---
> >  drivers/media/i2c/tvp5150.c | 39 ++++++++++++++++++++++++++-----------
> >  1 file changed, 28 insertions(+), 11 deletions(-)
> > 
> > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > index d8bdbedd8826..27cfd08be3d2 100644
> > --- a/drivers/media/i2c/tvp5150.c
> > +++ b/drivers/media/i2c/tvp5150.c
> > @@ -60,6 +60,7 @@ struct tvp5150 {
> >  	v4l2_std_id detected_norm;
> >  	u32 input;
> >  	u32 output;
> > +	u32 oe;
> >  	int enable;
> >  	bool lock;
> >  
> > @@ -799,14 +800,20 @@ static irqreturn_t tvp5150_isr(int irq, void *dev_id)
> >  {
> >  	struct tvp5150 *decoder = dev_id;
> >  	struct regmap *map = decoder->regmap;
> > -	unsigned int active = 0, status = 0;
> > +	unsigned int mask, active = 0, status = 0;
> > +
> > +	mask = TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_SYNC_OE |
> > +	       TVP5150_MISC_CTL_CLOCK_OE;
> >  
> >  	regmap_read(map, TVP5150_INT_STATUS_REG_A, &status);
> >  	if (status) {
> >  		regmap_write(map, TVP5150_INT_STATUS_REG_A, status);
> >  
> > -		if (status & TVP5150_INT_A_LOCK)
> > +		if (status & TVP5150_INT_A_LOCK) {
> >  			decoder->lock = !!(status & TVP5150_INT_A_LOCK_STATUS);
> > +			regmap_update_bits(map, TVP5150_MISC_CTL, mask,
> > +					   decoder->lock ? decoder->oe : 0);
> > +		}
> >  
> >  		return IRQ_HANDLED;
> >  	}
> > @@ -872,10 +879,26 @@ static int tvp5150_enable(struct v4l2_subdev *sd)
> >  	/* Disable autoswitch mode */
> >  	tvp5150_set_std(sd, std);
> >  
> > -	if (decoder->mbus_type == V4L2_MBUS_PARALLEL)
> > +	/*
> > +	 * Enable the YCbCr and clock outputs. In discrete sync mode
> > +	 * (non-BT.656) additionally enable the the sync outputs.
> > +	 */
> > +	switch (decoder->mbus_type) {
> > +	case V4L2_MBUS_PARALLEL:
> >  		/* 8-bit 4:2:2 YUV with discrete sync output */
> >  		regmap_update_bits(decoder->regmap, TVP5150_DATA_RATE_SEL,
> >  				   0x7, 0x0);
> > +		decoder->oe = TVP5150_MISC_CTL_YCBCR_OE |
> > +			      TVP5150_MISC_CTL_CLOCK_OE |
> > +			      TVP5150_MISC_CTL_SYNC_OE;
> > +		break;
> > +	case V4L2_MBUS_BT656:
> > +		decoder->oe = TVP5150_MISC_CTL_YCBCR_OE |
> > +			      TVP5150_MISC_CTL_CLOCK_OE;
> > +		break;
> > +	default:
> > +		return -EINVAL;
> > +	}
> >  
> >  	return 0;
> >  };
> > @@ -1190,14 +1213,8 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
> >  	if (enable) {
> >  		tvp5150_enable(sd);
> >  
> > -		/*
> > -		 * Enable the YCbCr and clock outputs. In discrete sync mode
> > -		 * (non-BT.656) additionally enable the the sync outputs.
> > -		 */
> > -		val = TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_CLOCK_OE;
> > -		if (decoder->mbus_type == V4L2_MBUS_PARALLEL)
> > -			val |= TVP5150_MISC_CTL_SYNC_OE;
> > -
> > +		/* Enable outputs if decoder is locked */
> > +		val = decoder->lock ? decoder->oe : 0;
> 
> Hmm... this only works if the tvp5150 has the interrupts enabled.
> 
> The code should be, instead:
> 
> 	if (c->irq)
> 		val = decoder->lock ? decoder->oe : 0;
> 	else
> 		val = decoder->oe;

The previous patch "[media] tvp5150: Add sync lock interrupt handling"
adds the look mechanism. As you can see the lock will be always true
if there is no interrupt support during probe():

core->irq = c->irq;
tvp5150_reset(sd, 0);   /* Calls v4l2_ctrl_handler_setup() */
if (c->irq) {
	res = devm_request_threaded_irq(&c->dev, c->irq,
			NULL,
			tvp5150_isr,
			IRQF_TRIGGER_HIGH |
			IRQF_ONESHOT,
			"tvp5150", core);
	if (res)
		return res;
} else {
	core->lock = true;
}

I'am with you that your s_stream version looks a bit nicer but adds the
check again.

Regards,
Marco

> 
> >  		int_val = TVP5150_INT_A_LOCK;
> >  	}
> >  
> 
> 
> 
> Thanks,
> Mauro
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

* Re: [PATCH 18/22] partial revert of "[media] tvp5150: add HW input connectors support"
  2018-07-30 18:18   ` Mauro Carvalho Chehab
@ 2018-07-31  7:01     ` Marco Felsch
  2018-07-31  8:52     ` Javier Martinez Canillas
  1 sibling, 0 replies; 70+ messages in thread
From: Marco Felsch @ 2018-07-31  7:01 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Hi Mauro,

On 18-07-30 15:18, Mauro Carvalho Chehab wrote:
> Em Thu, 28 Jun 2018 18:20:50 +0200
> Marco Felsch <m.felsch@pengutronix.de> escreveu:
> 
> > From: Javier Martinez Canillas <javierm@redhat.com>
> > 
> > Commit f7b4b54e6364 ("[media] tvp5150: add HW input connectors support")
> > added input signals support for the tvp5150, but the approach was found
> > to be incorrect so the corresponding DT binding commit 82c2ffeb217a
> > ("[media] tvp5150: document input connectors DT bindings") was reverted.
> > 
> > This left the driver with an undocumented (and wrong) DT parsing logic,
> > so lets get rid of this code as well until the input connectors support
> > is implemented properly.
> > 
> > It's a partial revert due other patches added on top of mentioned commit
> > not allowing the commit to be reverted cleanly anymore. But all the code
> > related to the DT parsing logic and input entities creation are removed.
> > 
> > Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
> > Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > [m.felsch@pengutronix.de: rm TVP5150_INPUT_NUM define]
> > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > ---
> 
> ...
> 
> > -static int tvp5150_registered(struct v4l2_subdev *sd)
> > -{
> > -#ifdef CONFIG_MEDIA_CONTROLLER
> > -	struct tvp5150 *decoder = to_tvp5150(sd);
> > -	int ret = 0;
> > -	int i;
> > -
> > -	for (i = 0; i < TVP5150_INPUT_NUM; i++) {
> > -		struct media_entity *input = &decoder->input_ent[i];
> > -		struct media_pad *pad = &decoder->input_pad[i];
> > -
> > -		if (!input->name)
> > -			continue;
> > -
> > -		decoder->input_pad[i].flags = MEDIA_PAD_FL_SOURCE;
> > -
> > -		ret = media_entity_pads_init(input, 1, pad);
> > -		if (ret < 0)
> > -			return ret;
> > -
> > -		ret = media_device_register_entity(sd->v4l2_dev->mdev, input);
> > -		if (ret < 0)
> > -			return ret;
> > -
> > -		ret = media_create_pad_link(input, 0, &sd->entity,
> > -					    DEMOD_PAD_IF_INPUT, 0);
> > -		if (ret < 0) {
> > -			media_device_unregister_entity(input);
> > -			return ret;
> > -		}
> > -	}
> > -#endif
> 
> Hmm... I suspect that reverting this part may cause problems for drivers
> like em28xx when compiled with MC, as they rely that the supported demods
> will have 3 pads (DEMOD_NUM_PADS).

Please, can you test this for me? I have no such usb device.
Using the DEMOD_NUM_PADS looked wrong to me since the tvp5150 has more
than one input pad.

Thanks,
Marco

> Thanks,
> Mauro
> 

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

* Re: [PATCH 18/22] partial revert of "[media] tvp5150: add HW input connectors support"
  2018-07-30 18:18   ` Mauro Carvalho Chehab
  2018-07-31  7:01     ` Marco Felsch
@ 2018-07-31  8:52     ` Javier Martinez Canillas
  2018-07-31 10:06       ` Mauro Carvalho Chehab
  1 sibling, 1 reply; 70+ messages in thread
From: Javier Martinez Canillas @ 2018-07-31  8:52 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Marco Felsch
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Hello Mauro,

On 07/30/2018 08:18 PM, Mauro Carvalho Chehab wrote:
> Em Thu, 28 Jun 2018 18:20:50 +0200
> Marco Felsch <m.felsch@pengutronix.de> escreveu:
> 
>> From: Javier Martinez Canillas <javierm@redhat.com>
>>
>> Commit f7b4b54e6364 ("[media] tvp5150: add HW input connectors support")
>> added input signals support for the tvp5150, but the approach was found
>> to be incorrect so the corresponding DT binding commit 82c2ffeb217a
>> ("[media] tvp5150: document input connectors DT bindings") was reverted.
>>
>> This left the driver with an undocumented (and wrong) DT parsing logic,
>> so lets get rid of this code as well until the input connectors support
>> is implemented properly.
>>
>> It's a partial revert due other patches added on top of mentioned commit
>> not allowing the commit to be reverted cleanly anymore. But all the code
>> related to the DT parsing logic and input entities creation are removed.
>>
>> Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
>> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>> [m.felsch@pengutronix.de: rm TVP5150_INPUT_NUM define]
>> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
>> ---
> 
> ...
> 
>> -static int tvp5150_registered(struct v4l2_subdev *sd)
>> -{
>> -#ifdef CONFIG_MEDIA_CONTROLLER
>> -	struct tvp5150 *decoder = to_tvp5150(sd);
>> -	int ret = 0;
>> -	int i;
>> -
>> -	for (i = 0; i < TVP5150_INPUT_NUM; i++) {
>> -		struct media_entity *input = &decoder->input_ent[i];
>> -		struct media_pad *pad = &decoder->input_pad[i];
>> -
>> -		if (!input->name)
>> -			continue;
>> -
>> -		decoder->input_pad[i].flags = MEDIA_PAD_FL_SOURCE;
>> -
>> -		ret = media_entity_pads_init(input, 1, pad);
>> -		if (ret < 0)
>> -			return ret;
>> -
>> -		ret = media_device_register_entity(sd->v4l2_dev->mdev, input);
>> -		if (ret < 0)
>> -			return ret;
>> -
>> -		ret = media_create_pad_link(input, 0, &sd->entity,
>> -					    DEMOD_PAD_IF_INPUT, 0);
>> -		if (ret < 0) {
>> -			media_device_unregister_entity(input);
>> -			return ret;
>> -		}
>> -	}
>> -#endif
> 
> Hmm... I suspect that reverting this part may cause problems for drivers
> like em28xx when compiled with MC, as they rely that the supported demods
> will have 3 pads (DEMOD_NUM_PADS).
>

I don't see how this change could affect em28xx and other drivers. The function
tvp5150_registered() being removed here, only register the media entity and add
a link if input->name was set. This is set in tvp5150_parse_dt() and only if a
input connector as defined in the Device Tree file.

In other words, all the code removed by this patch is DT-only and isn't used by
any media driver that makes use of the tvp5151.

As mentioned in the commit message, this code has never been used (besides from
my testings) and should had been removed when the DT binding was reverted, but
for some reasons the first patch landed and the second didn't at the time.

> Thanks,
> Mauro
> 

Best regards,
-- 
Javier Martinez Canillas
Software Engineer - Desktop Hardware Enablement
Red Hat

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

* Re: [PATCH 18/22] partial revert of "[media] tvp5150: add HW input connectors support"
  2018-07-31  8:52     ` Javier Martinez Canillas
@ 2018-07-31 10:06       ` Mauro Carvalho Chehab
  2018-07-31 11:26         ` Javier Martinez Canillas
  2018-07-31 13:22         ` Mauro Carvalho Chehab
  0 siblings, 2 replies; 70+ messages in thread
From: Mauro Carvalho Chehab @ 2018-07-31 10:06 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: Marco Felsch, mchehab, robh+dt, mark.rutland, p.zabel,
	afshin.nasser, sakari.ailus, laurent.pinchart, linux-media,
	devicetree, kernel

Em Tue, 31 Jul 2018 10:52:56 +0200
Javier Martinez Canillas <javierm@redhat.com> escreveu:

> Hello Mauro,
> 
> On 07/30/2018 08:18 PM, Mauro Carvalho Chehab wrote:
> > Em Thu, 28 Jun 2018 18:20:50 +0200
> > Marco Felsch <m.felsch@pengutronix.de> escreveu:
> >   
> >> From: Javier Martinez Canillas <javierm@redhat.com>
> >>
> >> Commit f7b4b54e6364 ("[media] tvp5150: add HW input connectors support")
> >> added input signals support for the tvp5150, but the approach was found
> >> to be incorrect so the corresponding DT binding commit 82c2ffeb217a
> >> ("[media] tvp5150: document input connectors DT bindings") was reverted.
> >>
> >> This left the driver with an undocumented (and wrong) DT parsing logic,
> >> so lets get rid of this code as well until the input connectors support
> >> is implemented properly.
> >>
> >> It's a partial revert due other patches added on top of mentioned commit
> >> not allowing the commit to be reverted cleanly anymore. But all the code
> >> related to the DT parsing logic and input entities creation are removed.
> >>
> >> Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
> >> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >> [m.felsch@pengutronix.de: rm TVP5150_INPUT_NUM define]
> >> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> >> ---  
> > 
> > ...
> >   
> >> -static int tvp5150_registered(struct v4l2_subdev *sd)
> >> -{
> >> -#ifdef CONFIG_MEDIA_CONTROLLER
> >> -	struct tvp5150 *decoder = to_tvp5150(sd);
> >> -	int ret = 0;
> >> -	int i;
> >> -
> >> -	for (i = 0; i < TVP5150_INPUT_NUM; i++) {
> >> -		struct media_entity *input = &decoder->input_ent[i];
> >> -		struct media_pad *pad = &decoder->input_pad[i];
> >> -
> >> -		if (!input->name)
> >> -			continue;
> >> -
> >> -		decoder->input_pad[i].flags = MEDIA_PAD_FL_SOURCE;
> >> -
> >> -		ret = media_entity_pads_init(input, 1, pad);
> >> -		if (ret < 0)
> >> -			return ret;
> >> -
> >> -		ret = media_device_register_entity(sd->v4l2_dev->mdev, input);
> >> -		if (ret < 0)
> >> -			return ret;
> >> -
> >> -		ret = media_create_pad_link(input, 0, &sd->entity,
> >> -					    DEMOD_PAD_IF_INPUT, 0);
> >> -		if (ret < 0) {
> >> -			media_device_unregister_entity(input);
> >> -			return ret;
> >> -		}
> >> -	}
> >> -#endif  
> > 
> > Hmm... I suspect that reverting this part may cause problems for drivers
> > like em28xx when compiled with MC, as they rely that the supported demods
> > will have 3 pads (DEMOD_NUM_PADS).
> >  
> 
> I don't see how this change could affect em28xx and other drivers. The function
> tvp5150_registered() being removed here, only register the media entity and add
> a link if input->name was set. This is set in tvp5150_parse_dt() and only if a
> input connector as defined in the Device Tree file.
> 
> In other words, all the code removed by this patch is DT-only and isn't used by
> any media driver that makes use of the tvp5151.
> 
> As mentioned in the commit message, this code has never been used (besides from
> my testings) and should had been removed when the DT binding was reverted, but
> for some reasons the first patch landed and the second didn't at the time.

Short answer: 

Yeah, you're right. Yet, patch 19/22 will cause regressions.

Long answer:

That's easy enough to test.

Without this patch, a em28xx-based board (Terratec Grabster AV350) reports:

$ ./mc_nextgen_test -D
digraph board {
	rankdir=TB
	colorscheme=x11
	labelloc="t"
	label="Grabster AV 350
 driver:em28xx, bus: usb-0000:00:14.0-2
"
	intf_devnode_7 [label="intf_devnode_7\nvideo\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
	intf_devnode_10 [label="intf_devnode_10\nvbi\n/dev/vbi0", shape=box, style=filled, fillcolor=yellow]
	entity_1 [label="{{<pad_2> 0} | entity_1\nATV decoder\ntvp5150 0-005c | {<pad_3> 1 | <pad_4> 2}}", shape=Mrecord, style=filled, fillcolor=lightblue]
	entity_6 [label="{{<pad_12> 0} | entity_6\nV4L I/O\n2-2:1.0 video}", shape=Mrecord, style=filled, fillcolor=aquamarine]
	entity_9 [label="{{<pad_13> 0} | entity_9\nVBI I/O\n2-2:1.0 vbi}", shape=Mrecord, style=filled, fillcolor=aquamarine]
	entity_14 [label="{entity_14\nunknown entity type\nComposite | {<pad_15> 0}}", shape=Mrecord, style=filled, fillcolor=cadetblue]
	entity_16 [label="{entity_16\nunknown entity type\nS-Video | {<pad_17> 0}}", shape=Mrecord, style=filled, fillcolor=cadetblue]
	intf_devnode_7 -> entity_6 [dir="none" color="orange"]
	intf_devnode_10 -> entity_9 [dir="none" color="orange"]
	entity_1:pad_3 -> entity_6:pad_12 [color=blue]
	entity_1:pad_4 -> entity_9:pad_13 [color=blue]
	entity_14:pad_15 -> entity_1:pad_2 [color=blue]
	entity_16:pad_17 -> entity_1:pad_2 [color=blue style="dashed"]
}

tvp5150 reports 3 pads (one input, two output pads), and media core
properly connects the source pads.

With patch 18/22, I got the same graph. So, yeah, applying this patch
won't cause regressions.

However, when we apply patch 19/22:

$ mc_nextgen_test -D
digraph board {
	rankdir=TB
	colorscheme=x11
	labelloc="t"
	label="Grabster AV 350
 driver:em28xx, bus: usb-0000:00:14.0-2
"
	intf_devnode_7 [label="intf_devnode_7\nvideo\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
	intf_devnode_10 [label="intf_devnode_10\nvbi\n/dev/vbi0", shape=box, style=filled, fillcolor=yellow]
	entity_1 [label="{{<pad_2> 0 | <pad_3> 1 | <pad_4> 2} | entity_1\nATV decoder\ntvp5150 0-005c | {<pad_5> 3}}", shape=Mrecord, style=filled, fillcolor=lightblue]
	entity_6 [label="{{<pad_12> 0} | entity_6\nV4L I/O\n2-2:1.0 video}", shape=Mrecord, style=filled, fillcolor=aquamarine]
	entity_9 [label="{{<pad_13> 0} | entity_9\nVBI I/O\n2-2:1.0 vbi}", shape=Mrecord, style=filled, fillcolor=aquamarine]
	entity_14 [label="{entity_14\nunknown entity type\nComposite | {<pad_15> 0}}", shape=Mrecord, style=filled, fillcolor=cadetblue]
	entity_16 [label="{entity_16\nunknown entity type\nS-Video | {<pad_17> 0}}", shape=Mrecord, style=filled, fillcolor=cadetblue]
	intf_devnode_7 -> entity_6 [dir="none" color="orange"]
	intf_devnode_10 -> entity_9 [dir="none" color="orange"]
	entity_1:pad_3 -> entity_6:pad_12 [color=blue]
	entity_1:pad_4 -> entity_9:pad_13 [color=blue]
	entity_14:pad_15 -> entity_1:pad_2 [color=blue]
	entity_16:pad_17 -> entity_1:pad_2 [color=blue style="dashed"]
}

The graph is not built correct, as it is linking tvp5150's input pads as
if they were output ones.

The problem is that now you need to teach drivers/media/v4l2-core/v4l2-mc.c
to do the proper wiring for tvp5150.

I suspect that fixing v4l2-mc for doing that is not hard, but it may
require changes at the other demods. Thankfully there aren't many
demod drivers, but such patch should be applied before patch 19/22.

In the specific case of demods that don't support sliced VBI (or
where sliced VBI is not coded), there should be just one source pad.

On demods with sliced VBI, there are actually two source pads,
although, for simplicity, maybe we could map them as just one.

If we map as just one source pad, it is probably easy to change the
code at v4l2-mc to do the right thing.

I'll do some tests here and try to code it.

Thanks,
Mauro

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

* Re: [PATCH 18/22] partial revert of "[media] tvp5150: add HW input connectors support"
  2018-07-31 10:06       ` Mauro Carvalho Chehab
@ 2018-07-31 11:26         ` Javier Martinez Canillas
  2018-07-31 12:36           ` Marco Felsch
  2018-07-31 13:22         ` Mauro Carvalho Chehab
  1 sibling, 1 reply; 70+ messages in thread
From: Javier Martinez Canillas @ 2018-07-31 11:26 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Marco Felsch, mchehab, robh+dt, mark.rutland, p.zabel,
	afshin.nasser, sakari.ailus, laurent.pinchart, linux-media,
	devicetree, kernel

Hi Mauro,

On 07/31/2018 12:06 PM, Mauro Carvalho Chehab wrote:
> Em Tue, 31 Jul 2018 10:52:56 +0200
> Javier Martinez Canillas <javierm@redhat.com> escreveu:
> 
>> Hello Mauro,
>>
>> On 07/30/2018 08:18 PM, Mauro Carvalho Chehab wrote:
>>> Em Thu, 28 Jun 2018 18:20:50 +0200
>>> Marco Felsch <m.felsch@pengutronix.de> escreveu:
>>>   
>>>> From: Javier Martinez Canillas <javierm@redhat.com>
>>>>
>>>> Commit f7b4b54e6364 ("[media] tvp5150: add HW input connectors support")
>>>> added input signals support for the tvp5150, but the approach was found
>>>> to be incorrect so the corresponding DT binding commit 82c2ffeb217a
>>>> ("[media] tvp5150: document input connectors DT bindings") was reverted.
>>>>
>>>> This left the driver with an undocumented (and wrong) DT parsing logic,
>>>> so lets get rid of this code as well until the input connectors support
>>>> is implemented properly.
>>>>
>>>> It's a partial revert due other patches added on top of mentioned commit
>>>> not allowing the commit to be reverted cleanly anymore. But all the code
>>>> related to the DT parsing logic and input entities creation are removed.
>>>>
>>>> Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>>>> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
>>>> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>>>> [m.felsch@pengutronix.de: rm TVP5150_INPUT_NUM define]
>>>> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
>>>> ---  
>>>
>>> ...
>>>   
>>>> -static int tvp5150_registered(struct v4l2_subdev *sd)
>>>> -{
>>>> -#ifdef CONFIG_MEDIA_CONTROLLER
>>>> -	struct tvp5150 *decoder = to_tvp5150(sd);
>>>> -	int ret = 0;
>>>> -	int i;
>>>> -
>>>> -	for (i = 0; i < TVP5150_INPUT_NUM; i++) {
>>>> -		struct media_entity *input = &decoder->input_ent[i];
>>>> -		struct media_pad *pad = &decoder->input_pad[i];
>>>> -
>>>> -		if (!input->name)
>>>> -			continue;
>>>> -
>>>> -		decoder->input_pad[i].flags = MEDIA_PAD_FL_SOURCE;
>>>> -
>>>> -		ret = media_entity_pads_init(input, 1, pad);
>>>> -		if (ret < 0)
>>>> -			return ret;
>>>> -
>>>> -		ret = media_device_register_entity(sd->v4l2_dev->mdev, input);
>>>> -		if (ret < 0)
>>>> -			return ret;
>>>> -
>>>> -		ret = media_create_pad_link(input, 0, &sd->entity,
>>>> -					    DEMOD_PAD_IF_INPUT, 0);
>>>> -		if (ret < 0) {
>>>> -			media_device_unregister_entity(input);
>>>> -			return ret;
>>>> -		}
>>>> -	}
>>>> -#endif  
>>>
>>> Hmm... I suspect that reverting this part may cause problems for drivers
>>> like em28xx when compiled with MC, as they rely that the supported demods
>>> will have 3 pads (DEMOD_NUM_PADS).
>>>  
>>
>> I don't see how this change could affect em28xx and other drivers. The function
>> tvp5150_registered() being removed here, only register the media entity and add
>> a link if input->name was set. This is set in tvp5150_parse_dt() and only if a
>> input connector as defined in the Device Tree file.
>>
>> In other words, all the code removed by this patch is DT-only and isn't used by
>> any media driver that makes use of the tvp5151.
>>
>> As mentioned in the commit message, this code has never been used (besides from
>> my testings) and should had been removed when the DT binding was reverted, but
>> for some reasons the first patch landed and the second didn't at the time.
> 
> Short answer: 
> 
> Yeah, you're right. Yet, patch 19/22 will cause regressions.
>
> Long answer:
> 
> That's easy enough to test.
> 
> Without this patch, a em28xx-based board (Terratec Grabster AV350) reports:
> 
> $ ./mc_nextgen_test -D
> digraph board {
> 	rankdir=TB
> 	colorscheme=x11
> 	labelloc="t"
> 	label="Grabster AV 350
>  driver:em28xx, bus: usb-0000:00:14.0-2
> "
> 	intf_devnode_7 [label="intf_devnode_7\nvideo\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
> 	intf_devnode_10 [label="intf_devnode_10\nvbi\n/dev/vbi0", shape=box, style=filled, fillcolor=yellow]
> 	entity_1 [label="{{<pad_2> 0} | entity_1\nATV decoder\ntvp5150 0-005c | {<pad_3> 1 | <pad_4> 2}}", shape=Mrecord, style=filled, fillcolor=lightblue]
> 	entity_6 [label="{{<pad_12> 0} | entity_6\nV4L I/O\n2-2:1.0 video}", shape=Mrecord, style=filled, fillcolor=aquamarine]
> 	entity_9 [label="{{<pad_13> 0} | entity_9\nVBI I/O\n2-2:1.0 vbi}", shape=Mrecord, style=filled, fillcolor=aquamarine]
> 	entity_14 [label="{entity_14\nunknown entity type\nComposite | {<pad_15> 0}}", shape=Mrecord, style=filled, fillcolor=cadetblue]
> 	entity_16 [label="{entity_16\nunknown entity type\nS-Video | {<pad_17> 0}}", shape=Mrecord, style=filled, fillcolor=cadetblue]
> 	intf_devnode_7 -> entity_6 [dir="none" color="orange"]
> 	intf_devnode_10 -> entity_9 [dir="none" color="orange"]
> 	entity_1:pad_3 -> entity_6:pad_12 [color=blue]
> 	entity_1:pad_4 -> entity_9:pad_13 [color=blue]
> 	entity_14:pad_15 -> entity_1:pad_2 [color=blue]
> 	entity_16:pad_17 -> entity_1:pad_2 [color=blue style="dashed"]
> }
> 
> tvp5150 reports 3 pads (one input, two output pads), and media core
> properly connects the source pads.
> 
> With patch 18/22, I got the same graph. So, yeah, applying this patch
> won't cause regressions.
>

Yes, I didn't have time to review the other patches in the set yet. I was just
referring to patch 18/22 that it is really a standalone change and I've posted
it several times already. So I think that one is safe to merge.

> However, when we apply patch 19/22:
> 
> $ mc_nextgen_test -D
> digraph board {
> 	rankdir=TB
> 	colorscheme=x11
> 	labelloc="t"
> 	label="Grabster AV 350
>  driver:em28xx, bus: usb-0000:00:14.0-2
> "
> 	intf_devnode_7 [label="intf_devnode_7\nvideo\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
> 	intf_devnode_10 [label="intf_devnode_10\nvbi\n/dev/vbi0", shape=box, style=filled, fillcolor=yellow]
> 	entity_1 [label="{{<pad_2> 0 | <pad_3> 1 | <pad_4> 2} | entity_1\nATV decoder\ntvp5150 0-005c | {<pad_5> 3}}", shape=Mrecord, style=filled, fillcolor=lightblue]
> 	entity_6 [label="{{<pad_12> 0} | entity_6\nV4L I/O\n2-2:1.0 video}", shape=Mrecord, style=filled, fillcolor=aquamarine]
> 	entity_9 [label="{{<pad_13> 0} | entity_9\nVBI I/O\n2-2:1.0 vbi}", shape=Mrecord, style=filled, fillcolor=aquamarine]
> 	entity_14 [label="{entity_14\nunknown entity type\nComposite | {<pad_15> 0}}", shape=Mrecord, style=filled, fillcolor=cadetblue]
> 	entity_16 [label="{entity_16\nunknown entity type\nS-Video | {<pad_17> 0}}", shape=Mrecord, style=filled, fillcolor=cadetblue]
> 	intf_devnode_7 -> entity_6 [dir="none" color="orange"]
> 	intf_devnode_10 -> entity_9 [dir="none" color="orange"]
> 	entity_1:pad_3 -> entity_6:pad_12 [color=blue]
> 	entity_1:pad_4 -> entity_9:pad_13 [color=blue]
> 	entity_14:pad_15 -> entity_1:pad_2 [color=blue]
> 	entity_16:pad_17 -> entity_1:pad_2 [color=blue style="dashed"]
> }
> 
> The graph is not built correct, as it is linking tvp5150's input pads as
> if they were output ones.
> 
> The problem is that now you need to teach drivers/media/v4l2-core/v4l2-mc.c
> to do the proper wiring for tvp5150.
> 
> I suspect that fixing v4l2-mc for doing that is not hard, but it may
> require changes at the other demods. Thankfully there aren't many
> demod drivers, but such patch should be applied before patch 19/22.
> 
> In the specific case of demods that don't support sliced VBI (or
> where sliced VBI is not coded), there should be just one source pad.
> 
> On demods with sliced VBI, there are actually two source pads,
> although, for simplicity, maybe we could map them as just one.
> 
> If we map as just one source pad, it is probably easy to change the
> code at v4l2-mc to do the right thing.
> 
> I'll do some tests here and try to code it.
>

Yes, another thing that patch 19/22 should take into account is DTs that
don't have input connectors defined. So probably TVP5150_PORT_YOUT should
be 0 instead of TVP5150_PORT_NUM - 1 as is the case in the current patch.

In other words, it should work both when input connectors are defined in
the DT and when these are not defined and only an output port is defined.

> Thanks,
> Mauro
> 

Best regards,
-- 
Javier Martinez Canillas
Software Engineer - Desktop Hardware Enablement
Red Hat

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

* Re: [PATCH 18/22] partial revert of "[media] tvp5150: add HW input connectors support"
  2018-07-31 11:26         ` Javier Martinez Canillas
@ 2018-07-31 12:36           ` Marco Felsch
  2018-07-31 12:52             ` Javier Martinez Canillas
  2018-07-31 13:01             ` Mauro Carvalho Chehab
  0 siblings, 2 replies; 70+ messages in thread
From: Marco Felsch @ 2018-07-31 12:36 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: Mauro Carvalho Chehab, mchehab, robh+dt, mark.rutland, p.zabel,
	afshin.nasser, sakari.ailus, laurent.pinchart, linux-media,
	devicetree, kernel

Hi Javier,
Hi Mauro,

On 18-07-31 13:26, Javier Martinez Canillas wrote:
> Hi Mauro,
> 
> On 07/31/2018 12:06 PM, Mauro Carvalho Chehab wrote:
> > Em Tue, 31 Jul 2018 10:52:56 +0200
> > Javier Martinez Canillas <javierm@redhat.com> escreveu:
> > 
> >> Hello Mauro,
> >>
> >> On 07/30/2018 08:18 PM, Mauro Carvalho Chehab wrote:
> >>> Em Thu, 28 Jun 2018 18:20:50 +0200
> >>> Marco Felsch <m.felsch@pengutronix.de> escreveu:
> >>>   
> >>>> From: Javier Martinez Canillas <javierm@redhat.com>
> >>>>
> >>>> Commit f7b4b54e6364 ("[media] tvp5150: add HW input connectors support")
> >>>> added input signals support for the tvp5150, but the approach was found
> >>>> to be incorrect so the corresponding DT binding commit 82c2ffeb217a
> >>>> ("[media] tvp5150: document input connectors DT bindings") was reverted.
> >>>>
> >>>> This left the driver with an undocumented (and wrong) DT parsing logic,
> >>>> so lets get rid of this code as well until the input connectors support
> >>>> is implemented properly.
> >>>>
> >>>> It's a partial revert due other patches added on top of mentioned commit
> >>>> not allowing the commit to be reverted cleanly anymore. But all the code
> >>>> related to the DT parsing logic and input entities creation are removed.
> >>>>
> >>>> Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >>>> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
> >>>> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >>>> [m.felsch@pengutronix.de: rm TVP5150_INPUT_NUM define]
> >>>> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> >>>> ---  
> >>>
> >>> ...
> >>>   
> >>>> -static int tvp5150_registered(struct v4l2_subdev *sd)
> >>>> -{
> >>>> -#ifdef CONFIG_MEDIA_CONTROLLER
> >>>> -	struct tvp5150 *decoder = to_tvp5150(sd);
> >>>> -	int ret = 0;
> >>>> -	int i;
> >>>> -
> >>>> -	for (i = 0; i < TVP5150_INPUT_NUM; i++) {
> >>>> -		struct media_entity *input = &decoder->input_ent[i];
> >>>> -		struct media_pad *pad = &decoder->input_pad[i];
> >>>> -
> >>>> -		if (!input->name)
> >>>> -			continue;
> >>>> -
> >>>> -		decoder->input_pad[i].flags = MEDIA_PAD_FL_SOURCE;
> >>>> -
> >>>> -		ret = media_entity_pads_init(input, 1, pad);
> >>>> -		if (ret < 0)
> >>>> -			return ret;
> >>>> -
> >>>> -		ret = media_device_register_entity(sd->v4l2_dev->mdev, input);
> >>>> -		if (ret < 0)
> >>>> -			return ret;
> >>>> -
> >>>> -		ret = media_create_pad_link(input, 0, &sd->entity,
> >>>> -					    DEMOD_PAD_IF_INPUT, 0);
> >>>> -		if (ret < 0) {
> >>>> -			media_device_unregister_entity(input);
> >>>> -			return ret;
> >>>> -		}
> >>>> -	}
> >>>> -#endif  
> >>>
> >>> Hmm... I suspect that reverting this part may cause problems for drivers
> >>> like em28xx when compiled with MC, as they rely that the supported demods
> >>> will have 3 pads (DEMOD_NUM_PADS).
> >>>  
> >>
> >> I don't see how this change could affect em28xx and other drivers. The function
> >> tvp5150_registered() being removed here, only register the media entity and add
> >> a link if input->name was set. This is set in tvp5150_parse_dt() and only if a
> >> input connector as defined in the Device Tree file.
> >>
> >> In other words, all the code removed by this patch is DT-only and isn't used by
> >> any media driver that makes use of the tvp5151.
> >>
> >> As mentioned in the commit message, this code has never been used (besides from
> >> my testings) and should had been removed when the DT binding was reverted, but
> >> for some reasons the first patch landed and the second didn't at the time.
> > 
> > Short answer: 
> > 
> > Yeah, you're right. Yet, patch 19/22 will cause regressions.
> >
> > Long answer:
> > 
> > That's easy enough to test.
> > 
> > Without this patch, a em28xx-based board (Terratec Grabster AV350) reports:
> > 
> > $ ./mc_nextgen_test -D
> > digraph board {
> > 	rankdir=TB
> > 	colorscheme=x11
> > 	labelloc="t"
> > 	label="Grabster AV 350
> >  driver:em28xx, bus: usb-0000:00:14.0-2
> > "
> > 	intf_devnode_7 [label="intf_devnode_7\nvideo\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
> > 	intf_devnode_10 [label="intf_devnode_10\nvbi\n/dev/vbi0", shape=box, style=filled, fillcolor=yellow]
> > 	entity_1 [label="{{<pad_2> 0} | entity_1\nATV decoder\ntvp5150 0-005c | {<pad_3> 1 | <pad_4> 2}}", shape=Mrecord, style=filled, fillcolor=lightblue]
> > 	entity_6 [label="{{<pad_12> 0} | entity_6\nV4L I/O\n2-2:1.0 video}", shape=Mrecord, style=filled, fillcolor=aquamarine]
> > 	entity_9 [label="{{<pad_13> 0} | entity_9\nVBI I/O\n2-2:1.0 vbi}", shape=Mrecord, style=filled, fillcolor=aquamarine]
> > 	entity_14 [label="{entity_14\nunknown entity type\nComposite | {<pad_15> 0}}", shape=Mrecord, style=filled, fillcolor=cadetblue]
> > 	entity_16 [label="{entity_16\nunknown entity type\nS-Video | {<pad_17> 0}}", shape=Mrecord, style=filled, fillcolor=cadetblue]
> > 	intf_devnode_7 -> entity_6 [dir="none" color="orange"]
> > 	intf_devnode_10 -> entity_9 [dir="none" color="orange"]
> > 	entity_1:pad_3 -> entity_6:pad_12 [color=blue]
> > 	entity_1:pad_4 -> entity_9:pad_13 [color=blue]
> > 	entity_14:pad_15 -> entity_1:pad_2 [color=blue]
> > 	entity_16:pad_17 -> entity_1:pad_2 [color=blue style="dashed"]
> > }
> > 
> > tvp5150 reports 3 pads (one input, two output pads), and media core
> > properly connects the source pads.
> > 
> > With patch 18/22, I got the same graph. So, yeah, applying this patch
> > won't cause regressions.
> >
> 
> Yes, I didn't have time to review the other patches in the set yet. I was just
> referring to patch 18/22 that it is really a standalone change and I've posted
> it several times already. So I think that one is safe to merge.
> 
> > However, when we apply patch 19/22:
> > 
> > $ mc_nextgen_test -D
> > digraph board {
> > 	rankdir=TB
> > 	colorscheme=x11
> > 	labelloc="t"
> > 	label="Grabster AV 350
> >  driver:em28xx, bus: usb-0000:00:14.0-2
> > "
> > 	intf_devnode_7 [label="intf_devnode_7\nvideo\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
> > 	intf_devnode_10 [label="intf_devnode_10\nvbi\n/dev/vbi0", shape=box, style=filled, fillcolor=yellow]
> > 	entity_1 [label="{{<pad_2> 0 | <pad_3> 1 | <pad_4> 2} | entity_1\nATV decoder\ntvp5150 0-005c | {<pad_5> 3}}", shape=Mrecord, style=filled, fillcolor=lightblue]
> > 	entity_6 [label="{{<pad_12> 0} | entity_6\nV4L I/O\n2-2:1.0 video}", shape=Mrecord, style=filled, fillcolor=aquamarine]
> > 	entity_9 [label="{{<pad_13> 0} | entity_9\nVBI I/O\n2-2:1.0 vbi}", shape=Mrecord, style=filled, fillcolor=aquamarine]
> > 	entity_14 [label="{entity_14\nunknown entity type\nComposite | {<pad_15> 0}}", shape=Mrecord, style=filled, fillcolor=cadetblue]
> > 	entity_16 [label="{entity_16\nunknown entity type\nS-Video | {<pad_17> 0}}", shape=Mrecord, style=filled, fillcolor=cadetblue]
> > 	intf_devnode_7 -> entity_6 [dir="none" color="orange"]
> > 	intf_devnode_10 -> entity_9 [dir="none" color="orange"]
> > 	entity_1:pad_3 -> entity_6:pad_12 [color=blue]
> > 	entity_1:pad_4 -> entity_9:pad_13 [color=blue]
> > 	entity_14:pad_15 -> entity_1:pad_2 [color=blue]
> > 	entity_16:pad_17 -> entity_1:pad_2 [color=blue style="dashed"]
> > }
> > 
> > The graph is not built correct, as it is linking tvp5150's input pads as
> > if they were output ones.

Maybe I misunderstand the mc-pads. I tought the pads represents the
physical ports. So I mapped these two things togehter.

> > 
> > The problem is that now you need to teach drivers/media/v4l2-core/v4l2-mc.c
> > to do the proper wiring for tvp5150.
> > 
> > I suspect that fixing v4l2-mc for doing that is not hard, but it may
> > require changes at the other demods. Thankfully there aren't many
> > demod drivers, but such patch should be applied before patch 19/22.
> > 
> > In the specific case of demods that don't support sliced VBI (or
> > where sliced VBI is not coded), there should be just one source pad.
> > 
> > On demods with sliced VBI, there are actually two source pads,
> > although, for simplicity, maybe we could map them as just one.
> > 
> > If we map as just one source pad, it is probably easy to change the
> > code at v4l2-mc to do the right thing.
> > 
> > I'll do some tests here and try to code it.
> >
> 
> Yes, another thing that patch 19/22 should take into account is DTs that
> don't have input connectors defined. So probably TVP5150_PORT_YOUT should
> be 0 instead of TVP5150_PORT_NUM - 1 as is the case in the current patch.
> 
> In other words, it should work both when input connectors are defined in
> the DT and when these are not defined and only an output port is defined.

Yes, it would be a approach to map the output port dynamicaly to the
highest port number. I tried to keep things easy by a static mapping.
Maybe a follow up patch can change this behaviour.

Anyway, input connectors aren't required. There must be at least one
port child node with a correct port-number in the DT.

Regards,
Marco

> > Thanks,
> > Mauro
> > 
> 
> Best regards,

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

* Re: [PATCH 18/22] partial revert of "[media] tvp5150: add HW input connectors support"
  2018-07-31 12:36           ` Marco Felsch
@ 2018-07-31 12:52             ` Javier Martinez Canillas
  2018-07-31 13:30               ` Marco Felsch
  2018-07-31 13:01             ` Mauro Carvalho Chehab
  1 sibling, 1 reply; 70+ messages in thread
From: Javier Martinez Canillas @ 2018-07-31 12:52 UTC (permalink / raw)
  To: Marco Felsch
  Cc: Mauro Carvalho Chehab, mchehab, robh+dt, mark.rutland, p.zabel,
	afshin.nasser, sakari.ailus, laurent.pinchart, linux-media,
	devicetree, kernel

Hi Marco,

On 07/31/2018 02:36 PM, Marco Felsch wrote:

[snip]

>>
>> Yes, another thing that patch 19/22 should take into account is DTs that
>> don't have input connectors defined. So probably TVP5150_PORT_YOUT should
>> be 0 instead of TVP5150_PORT_NUM - 1 as is the case in the current patch.
>>
>> In other words, it should work both when input connectors are defined in
>> the DT and when these are not defined and only an output port is defined.
> 
> Yes, it would be a approach to map the output port dynamicaly to the
> highest port number. I tried to keep things easy by a static mapping.
> Maybe a follow up patch can change this behaviour.
> 
> Anyway, input connectors aren't required. There must be at least one
> port child node with a correct port-number in the DT.
>

Yes, that was my point. But your patch uses the port child reg property as
the index for the struct device_node *endpoints[TVP5150_PORT_NUM] array.

If there's only one port child (for the output) then the DT binding says
that the reg property isn't required, so this will be 0 and your patch will
wrongly map it to TVP5150_PORT_AIP1A. That's why I said that the output port
should be the first one in your enum tvp5150_ports and not the last one.

> Regards,
> Marco
> 

Best regards,
-- 
Javier Martinez Canillas
Software Engineer - Desktop Hardware Enablement
Red Hat

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

* Re: [PATCH 18/22] partial revert of "[media] tvp5150: add HW input connectors support"
  2018-07-31 12:36           ` Marco Felsch
  2018-07-31 12:52             ` Javier Martinez Canillas
@ 2018-07-31 13:01             ` Mauro Carvalho Chehab
  1 sibling, 0 replies; 70+ messages in thread
From: Mauro Carvalho Chehab @ 2018-07-31 13:01 UTC (permalink / raw)
  To: Marco Felsch
  Cc: Javier Martinez Canillas, mchehab, robh+dt, mark.rutland,
	p.zabel, afshin.nasser, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

Em Tue, 31 Jul 2018 14:36:52 +0200
Marco Felsch <m.felsch@pengutronix.de> escreveu:

> Hi Javier,
> Hi Mauro,
> 
> On 18-07-31 13:26, Javier Martinez Canillas wrote:
> > Hi Mauro,
> > 
> > On 07/31/2018 12:06 PM, Mauro Carvalho Chehab wrote:  
> > > Em Tue, 31 Jul 2018 10:52:56 +0200
> > > Javier Martinez Canillas <javierm@redhat.com> escreveu:
> > >   
> > >> Hello Mauro,
> > >>
> > >> On 07/30/2018 08:18 PM, Mauro Carvalho Chehab wrote:  
> > >>> Em Thu, 28 Jun 2018 18:20:50 +0200
> > >>> Marco Felsch <m.felsch@pengutronix.de> escreveu:
> > >>>     
> > >>>> From: Javier Martinez Canillas <javierm@redhat.com>
> > >>>>
> > >>>> Commit f7b4b54e6364 ("[media] tvp5150: add HW input connectors support")
> > >>>> added input signals support for the tvp5150, but the approach was found
> > >>>> to be incorrect so the corresponding DT binding commit 82c2ffeb217a
> > >>>> ("[media] tvp5150: document input connectors DT bindings") was reverted.
> > >>>>
> > >>>> This left the driver with an undocumented (and wrong) DT parsing logic,
> > >>>> so lets get rid of this code as well until the input connectors support
> > >>>> is implemented properly.
> > >>>>
> > >>>> It's a partial revert due other patches added on top of mentioned commit
> > >>>> not allowing the commit to be reverted cleanly anymore. But all the code
> > >>>> related to the DT parsing logic and input entities creation are removed.
> > >>>>
> > >>>> Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > >>>> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
> > >>>> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > >>>> [m.felsch@pengutronix.de: rm TVP5150_INPUT_NUM define]
> > >>>> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > >>>> ---    
> > >>>
> > >>> ...
> > >>>     
> > >>>> -static int tvp5150_registered(struct v4l2_subdev *sd)
> > >>>> -{
> > >>>> -#ifdef CONFIG_MEDIA_CONTROLLER
> > >>>> -	struct tvp5150 *decoder = to_tvp5150(sd);
> > >>>> -	int ret = 0;
> > >>>> -	int i;
> > >>>> -
> > >>>> -	for (i = 0; i < TVP5150_INPUT_NUM; i++) {
> > >>>> -		struct media_entity *input = &decoder->input_ent[i];
> > >>>> -		struct media_pad *pad = &decoder->input_pad[i];
> > >>>> -
> > >>>> -		if (!input->name)
> > >>>> -			continue;
> > >>>> -
> > >>>> -		decoder->input_pad[i].flags = MEDIA_PAD_FL_SOURCE;
> > >>>> -
> > >>>> -		ret = media_entity_pads_init(input, 1, pad);
> > >>>> -		if (ret < 0)
> > >>>> -			return ret;
> > >>>> -
> > >>>> -		ret = media_device_register_entity(sd->v4l2_dev->mdev, input);
> > >>>> -		if (ret < 0)
> > >>>> -			return ret;
> > >>>> -
> > >>>> -		ret = media_create_pad_link(input, 0, &sd->entity,
> > >>>> -					    DEMOD_PAD_IF_INPUT, 0);
> > >>>> -		if (ret < 0) {
> > >>>> -			media_device_unregister_entity(input);
> > >>>> -			return ret;
> > >>>> -		}
> > >>>> -	}
> > >>>> -#endif    
> > >>>
> > >>> Hmm... I suspect that reverting this part may cause problems for drivers
> > >>> like em28xx when compiled with MC, as they rely that the supported demods
> > >>> will have 3 pads (DEMOD_NUM_PADS).
> > >>>    
> > >>
> > >> I don't see how this change could affect em28xx and other drivers. The function
> > >> tvp5150_registered() being removed here, only register the media entity and add
> > >> a link if input->name was set. This is set in tvp5150_parse_dt() and only if a
> > >> input connector as defined in the Device Tree file.
> > >>
> > >> In other words, all the code removed by this patch is DT-only and isn't used by
> > >> any media driver that makes use of the tvp5151.
> > >>
> > >> As mentioned in the commit message, this code has never been used (besides from
> > >> my testings) and should had been removed when the DT binding was reverted, but
> > >> for some reasons the first patch landed and the second didn't at the time.  
> > > 
> > > Short answer: 
> > > 
> > > Yeah, you're right. Yet, patch 19/22 will cause regressions.
> > >
> > > Long answer:
> > > 
> > > That's easy enough to test.
> > > 
> > > Without this patch, a em28xx-based board (Terratec Grabster AV350) reports:
> > > 
> > > $ ./mc_nextgen_test -D
> > > digraph board {
> > > 	rankdir=TB
> > > 	colorscheme=x11
> > > 	labelloc="t"
> > > 	label="Grabster AV 350
> > >  driver:em28xx, bus: usb-0000:00:14.0-2
> > > "
> > > 	intf_devnode_7 [label="intf_devnode_7\nvideo\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
> > > 	intf_devnode_10 [label="intf_devnode_10\nvbi\n/dev/vbi0", shape=box, style=filled, fillcolor=yellow]
> > > 	entity_1 [label="{{<pad_2> 0} | entity_1\nATV decoder\ntvp5150 0-005c | {<pad_3> 1 | <pad_4> 2}}", shape=Mrecord, style=filled, fillcolor=lightblue]
> > > 	entity_6 [label="{{<pad_12> 0} | entity_6\nV4L I/O\n2-2:1.0 video}", shape=Mrecord, style=filled, fillcolor=aquamarine]
> > > 	entity_9 [label="{{<pad_13> 0} | entity_9\nVBI I/O\n2-2:1.0 vbi}", shape=Mrecord, style=filled, fillcolor=aquamarine]
> > > 	entity_14 [label="{entity_14\nunknown entity type\nComposite | {<pad_15> 0}}", shape=Mrecord, style=filled, fillcolor=cadetblue]
> > > 	entity_16 [label="{entity_16\nunknown entity type\nS-Video | {<pad_17> 0}}", shape=Mrecord, style=filled, fillcolor=cadetblue]
> > > 	intf_devnode_7 -> entity_6 [dir="none" color="orange"]
> > > 	intf_devnode_10 -> entity_9 [dir="none" color="orange"]
> > > 	entity_1:pad_3 -> entity_6:pad_12 [color=blue]
> > > 	entity_1:pad_4 -> entity_9:pad_13 [color=blue]
> > > 	entity_14:pad_15 -> entity_1:pad_2 [color=blue]
> > > 	entity_16:pad_17 -> entity_1:pad_2 [color=blue style="dashed"]
> > > }
> > > 
> > > tvp5150 reports 3 pads (one input, two output pads), and media core
> > > properly connects the source pads.
> > > 
> > > With patch 18/22, I got the same graph. So, yeah, applying this patch
> > > won't cause regressions.
> > >  
> > 
> > Yes, I didn't have time to review the other patches in the set yet. I was just
> > referring to patch 18/22 that it is really a standalone change and I've posted
> > it several times already. So I think that one is safe to merge.
> >   
> > > However, when we apply patch 19/22:
> > > 
> > > $ mc_nextgen_test -D
> > > digraph board {
> > > 	rankdir=TB
> > > 	colorscheme=x11
> > > 	labelloc="t"
> > > 	label="Grabster AV 350
> > >  driver:em28xx, bus: usb-0000:00:14.0-2
> > > "
> > > 	intf_devnode_7 [label="intf_devnode_7\nvideo\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
> > > 	intf_devnode_10 [label="intf_devnode_10\nvbi\n/dev/vbi0", shape=box, style=filled, fillcolor=yellow]
> > > 	entity_1 [label="{{<pad_2> 0 | <pad_3> 1 | <pad_4> 2} | entity_1\nATV decoder\ntvp5150 0-005c | {<pad_5> 3}}", shape=Mrecord, style=filled, fillcolor=lightblue]
> > > 	entity_6 [label="{{<pad_12> 0} | entity_6\nV4L I/O\n2-2:1.0 video}", shape=Mrecord, style=filled, fillcolor=aquamarine]
> > > 	entity_9 [label="{{<pad_13> 0} | entity_9\nVBI I/O\n2-2:1.0 vbi}", shape=Mrecord, style=filled, fillcolor=aquamarine]
> > > 	entity_14 [label="{entity_14\nunknown entity type\nComposite | {<pad_15> 0}}", shape=Mrecord, style=filled, fillcolor=cadetblue]
> > > 	entity_16 [label="{entity_16\nunknown entity type\nS-Video | {<pad_17> 0}}", shape=Mrecord, style=filled, fillcolor=cadetblue]
> > > 	intf_devnode_7 -> entity_6 [dir="none" color="orange"]
> > > 	intf_devnode_10 -> entity_9 [dir="none" color="orange"]
> > > 	entity_1:pad_3 -> entity_6:pad_12 [color=blue]
> > > 	entity_1:pad_4 -> entity_9:pad_13 [color=blue]
> > > 	entity_14:pad_15 -> entity_1:pad_2 [color=blue]
> > > 	entity_16:pad_17 -> entity_1:pad_2 [color=blue style="dashed"]
> > > }
> > > 
> > > The graph is not built correct, as it is linking tvp5150's input pads as
> > > if they were output ones.  
> 
> Maybe I misunderstand the mc-pads. I tought the pads represents the
> physical ports. So I mapped these two things togehter.

We had a long discussion about that on IRC and at the ML some time ago.

There are different ways to map it, and different opinions if either a
PAD is a physical or a logical port.

In the case of tvp5150, from the logical standpoint, there's just one
input port (as it can't stream from multiple ports at the same time)
and two physical ports (AIP1A and AIP1B).

Internally, tvp5150 has a switch that allows 3 possible configurations:
	- composite 0 - switching to AIP1A
	- composite 1 - switching to AIP1B
	- s-video - using both AIP1A and AIP1B

So, depending on the way you see, it may have 1, 2 or 3 pads.

We ended by mapping it to just 1 pad. The idea is that, when a link is
created from a connector to it, it will set the input switch.

We did a mistake at the mapping, as VBI and video is actually a single
output pad, with can be connected to two different entities: one that
does the video stream and the other one that filters just some rows of
the video, in order to stream it trough the vbi interface.

If we ever implement a sliced VBI interface - with is now possible with
the interrupt handler - then we'll have a second output pad with sliced
VBI output.

> > > 
> > > The problem is that now you need to teach drivers/media/v4l2-core/v4l2-mc.c
> > > to do the proper wiring for tvp5150.
> > > 
> > > I suspect that fixing v4l2-mc for doing that is not hard, but it may
> > > require changes at the other demods. Thankfully there aren't many
> > > demod drivers, but such patch should be applied before patch 19/22.
> > > 
> > > In the specific case of demods that don't support sliced VBI (or
> > > where sliced VBI is not coded), there should be just one source pad.
> > > 
> > > On demods with sliced VBI, there are actually two source pads,
> > > although, for simplicity, maybe we could map them as just one.
> > > 
> > > If we map as just one source pad, it is probably easy to change the
> > > code at v4l2-mc to do the right thing.
> > > 
> > > I'll do some tests here and try to code it.
> > >  
> > 
> > Yes, another thing that patch 19/22 should take into account is DTs that
> > don't have input connectors defined. So probably TVP5150_PORT_YOUT should
> > be 0 instead of TVP5150_PORT_NUM - 1 as is the case in the current patch.
> > 
> > In other words, it should work both when input connectors are defined in
> > the DT and when these are not defined and only an output port is defined.  
> 
> Yes, it would be a approach to map the output port dynamicaly to the
> highest port number. I tried to keep things easy by a static mapping.
> Maybe a follow up patch can change this behaviour.
> 
> Anyway, input connectors aren't required. There must be at least one
> port child node with a correct port-number in the DT.

If we want to switch the input connector via MC, then it is required.

There are some OMAP3-based boards with 2 composite inputs and tvp5151
(with is almost identical, from software standpoint, to tvp5150).

Thanks,
Mauro

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

* Re: [PATCH 18/22] partial revert of "[media] tvp5150: add HW input connectors support"
  2018-07-31 10:06       ` Mauro Carvalho Chehab
  2018-07-31 11:26         ` Javier Martinez Canillas
@ 2018-07-31 13:22         ` Mauro Carvalho Chehab
  1 sibling, 0 replies; 70+ messages in thread
From: Mauro Carvalho Chehab @ 2018-07-31 13:22 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: Marco Felsch, mchehab, robh+dt, mark.rutland, p.zabel,
	afshin.nasser, sakari.ailus, laurent.pinchart, linux-media,
	devicetree, kernel

Em Tue, 31 Jul 2018 07:06:59 -0300
Mauro Carvalho Chehab <mchehab+samsung@kernel.org> escreveu:

> Em Tue, 31 Jul 2018 10:52:56 +0200
> Javier Martinez Canillas <javierm@redhat.com> escreveu:
> 

> The graph is not built correct, as it is linking tvp5150's input pads as
> if they were output ones.
> 
> The problem is that now you need to teach drivers/media/v4l2-core/v4l2-mc.c
> to do the proper wiring for tvp5150.
> 
> I suspect that fixing v4l2-mc for doing that is not hard, but it may
> require changes at the other demods. Thankfully there aren't many
> demod drivers, but such patch should be applied before patch 19/22.
> 
> In the specific case of demods that don't support sliced VBI (or
> where sliced VBI is not coded), there should be just one source pad.
> 
> On demods with sliced VBI, there are actually two source pads,
> although, for simplicity, maybe we could map them as just one.
> 
> If we map as just one source pad, it is probably easy to change the
> code at v4l2-mc to do the right thing.
> 
> I'll do some tests here and try to code it.

Ok, did some coding. The way to make it more robust and allow having
a different number of PADs for different demods/tuners is with an
approach like the one below.

This is just a RFC sort of patch, as it is incomplete, not covering the
dvbdev.c pipeline setup logic.

Anyway, it should be useful for further discussions, but some work
is needed.

Regards,
Mauro


[RFC] media: v4l2: taint pads with the signal types for consumer devices

Consumer devices are provided with a wide diferent range of types
supported by the same driver, allowing different configutations.

In order to make easier to setup media controller links, "taint"
pads with the signal type it carries.

While here, get rid of DEMOD_PAD_VBI_OUT, as the signal it carries
is actually the same as the normal video output.

The difference happens at the video/VBI interface:
        - for VBI, only the hidden lines are streamed;
        - for video, the stream is usually cropped to hide the
          vbi lines.

Compile-tested only and incomplete: the dvbdev.c should have a similar
change like the one done at v4l2-mc.c.

Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>

diff --git a/drivers/media/dvb-frontends/au8522_decoder.c b/drivers/media/dvb-frontends/au8522_decoder.c
index 343dc92ef54e..f4df9ab3d8b0 100644
--- a/drivers/media/dvb-frontends/au8522_decoder.c
+++ b/drivers/media/dvb-frontends/au8522_decoder.c
@@ -721,9 +721,11 @@ static int au8522_probe(struct i2c_client *client,
 #if defined(CONFIG_MEDIA_CONTROLLER)
 
 	state->pads[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
+	state->pads[DEMOD_PAD_IF_INPUT].sig_type = PAD_SIGNAL_RF;
 	state->pads[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
-	state->pads[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE;
+	state->pads[DEMOD_PAD_VID_OUT].sig_type = PAD_SIGNAL_ATV_VIDEO;
 	state->pads[DEMOD_PAD_AUDIO_OUT].flags = MEDIA_PAD_FL_SOURCE;
+	state->pads[DEMOD_PAD_AUDIO_OUT].sig_type = PAD_SIGNAL_AUDIO;
 	sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
 
 	ret = media_entity_pads_init(&sd->entity, ARRAY_SIZE(state->pads),
diff --git a/drivers/media/i2c/msp3400-driver.c b/drivers/media/i2c/msp3400-driver.c
index 3db966db83eb..3b9c729fbd52 100644
--- a/drivers/media/i2c/msp3400-driver.c
+++ b/drivers/media/i2c/msp3400-driver.c
@@ -704,7 +704,9 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
 #if defined(CONFIG_MEDIA_CONTROLLER)
 	state->pads[IF_AUD_DEC_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
+	state->pads[IF_AUD_DEC_PAD_IF_INPUT].sig_type = PAD_SIGNAL_AUDIO;
 	state->pads[IF_AUD_DEC_PAD_OUT].flags = MEDIA_PAD_FL_SOURCE;
+	state->pads[IF_AUD_DEC_PAD_OUT].sig_type = PAD_SIGNAL_AUDIO;
 
 	sd->entity.function = MEDIA_ENT_F_IF_AUD_DECODER;
 
diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c
index b07114b5efb2..0b298aa34a7c 100644
--- a/drivers/media/i2c/saa7115.c
+++ b/drivers/media/i2c/saa7115.c
@@ -1835,8 +1835,9 @@ static int saa711x_probe(struct i2c_client *client,
 
 #if defined(CONFIG_MEDIA_CONTROLLER)
 	state->pads[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
+	state->pads[DEMOD_PAD_IF_INPUT].sig_type = PAD_SIGNAL_RF;
 	state->pads[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
-	state->pads[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE;
+	state->pads[DEMOD_PAD_VID_OUT].sig_type = PAD_SIGNAL_ATV_VIDEO;
 
 	sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
 
diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index 1734ed4ede33..dab83a774e73 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -1495,8 +1495,9 @@ static int tvp5150_probe(struct i2c_client *c,
 
 #if defined(CONFIG_MEDIA_CONTROLLER)
 	core->pads[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
+	core->pads[DEMOD_PAD_IF_INPUT].sig_type = PAD_SIGNAL_RF;
 	core->pads[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
-	core->pads[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE;
+	core->pads[DEMOD_PAD_VID_OUT].sig_type = PAD_SIGNAL_ATV_VIDEO;
 
 	sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
 
diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c
index 9e76de2411ae..322e2ac00066 100644
--- a/drivers/media/pci/saa7134/saa7134-core.c
+++ b/drivers/media/pci/saa7134/saa7134-core.c
@@ -846,8 +846,9 @@ static void saa7134_create_entities(struct saa7134_dev *dev)
 	if (!decoder) {
 		dev->demod.name = "saa713x";
 		dev->demod_pad[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
+		dev->demod_pad[DEMOD_PAD_IF_INPUT].sig_type = PAD_SIGNAL_RF;
 		dev->demod_pad[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
-		dev->demod_pad[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE;
+		dev->demod_pad[DEMOD_PAD_VID_OUT].sig_type = PAD_SIGNAL_ATV_VIDEO;
 		dev->demod.function = MEDIA_ENT_F_ATV_DECODER;
 
 		ret = media_entity_pads_init(&dev->demod, DEMOD_NUM_PADS,
diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c
index 9e34d31d724d..85e9ea9059a3 100644
--- a/drivers/media/tuners/si2157.c
+++ b/drivers/media/tuners/si2157.c
@@ -469,8 +469,11 @@ static int si2157_probe(struct i2c_client *client,
 		dev->ent.function = MEDIA_ENT_F_TUNER;
 
 		dev->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK;
+		dev->pad[TUNER_PAD_RF_INPUT].sig_type = PAD_SIGNAL_RF;
 		dev->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE;
+		dev->pad[TUNER_PAD_OUTPUT].sig_type = PAD_SIGNAL_CARRIERS;
 		dev->pad[TUNER_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE;
+		dev->pad[TUNER_PAD_AUD_OUT].sig_type = PAD_SIGNAL_AUDIO;
 
 		ret = media_entity_pads_init(&dev->ent, TUNER_NUM_PADS,
 					     &dev->pad[0]);
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
index 67953360fda5..9161064b7718 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
@@ -893,7 +893,9 @@ static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap)
 	state->tuner.function = MEDIA_ENT_F_TUNER;
 	state->tuner.name = "mxl111sf tuner";
 	state->tuner_pads[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK;
+	state->tuner_pads[TUNER_PAD_RF_INPUT].sig_type = PAD_SIGNAL_RF;
 	state->tuner_pads[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE;
+	state->tuner_pads[TUNER_PAD_OUTPUT].sig_type = PAD_SIGNAL_CARRIERS;
 
 	ret = media_entity_pads_init(&state->tuner,
 				     TUNER_NUM_PADS, state->tuner_pads);
diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c
index 7f858c39753c..4c09c30e6ea1 100644
--- a/drivers/media/v4l2-core/tuner-core.c
+++ b/drivers/media/v4l2-core/tuner-core.c
@@ -685,15 +685,20 @@ static int tuner_probe(struct i2c_client *client,
 	 */
 	if (t->type == TUNER_TDA9887) {
 		t->pad[IF_VID_DEC_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
+		t->pad[IF_VID_DEC_PAD_IF_INPUT].sig_type = PAD_SIGNAL_RF;
 		t->pad[IF_VID_DEC_PAD_OUT].flags = MEDIA_PAD_FL_SOURCE;
+		t->pad[IF_VID_DEC_PAD_OUT].sig_type = PAD_SIGNAL_ATV_VIDEO;
 		ret = media_entity_pads_init(&t->sd.entity,
 					     IF_VID_DEC_PAD_NUM_PADS,
 					     &t->pad[0]);
 		t->sd.entity.function = MEDIA_ENT_F_IF_VID_DECODER;
 	} else {
 		t->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK;
+		t->pad[TUNER_PAD_RF_INPUT].sig_type = PAD_SIGNAL_RF;
 		t->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE;
+		t->pad[TUNER_PAD_OUTPUT].sig_type = PAD_SIGNAL_CARRIERS;
 		t->pad[TUNER_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE;
+		t->pad[TUNER_PAD_AUD_OUT].sig_type = PAD_SIGNAL_AUDIO;
 		ret = media_entity_pads_init(&t->sd.entity, TUNER_NUM_PADS,
 					     &t->pad[0]);
 		t->sd.entity.function = MEDIA_ENT_F_TUNER;
diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c
index 0fc185a2ce90..982bab3530f6 100644
--- a/drivers/media/v4l2-core/v4l2-mc.c
+++ b/drivers/media/v4l2-core/v4l2-mc.c
@@ -147,7 +147,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev)
 	}
 
 	if (io_vbi) {
-		ret = media_create_pad_link(decoder, DEMOD_PAD_VBI_OUT,
+		ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT,
 					    io_vbi, 0,
 					    MEDIA_LNK_FL_ENABLED);
 		if (ret)
diff --git a/include/media/media-entity.h b/include/media/media-entity.h
index a732af1dbba0..bf0604d315ef 100644
--- a/include/media/media-entity.h
+++ b/include/media/media-entity.h
@@ -155,6 +155,38 @@ struct media_link {
 	bool is_backlink;
 };
 
+/**
+ * struct media_pad_signal_type - type of the signal inside a media pad
+ *
+ * @PAD_SIGNAL_DEFAULT
+ *	Default signal. Use this when all inputs or all outputs are
+ *	uniquely identified by just its number and all carries the same
+ *	signal type
+ * @PAD_SIGNAL_RF
+ *	The pad contains a Radio Frequency, Intermediate Frequency or
+ *	baseband signal.
+ *	All Tuner sinks should use it.
+ *	On tuner sources, this is used for digital TV demodulators and for
+ *	IF-PLL demodulator like tda9887.
+ * @PAD_SIGNAL_CARRIERS
+ *	The pad contains analog signals carrying either a digital or an analog
+ *	modulated (or baseband) signal. This is provided by tuner source
+ *	pads and used by analog TV standard decoders and by digital tv demods.
+ * @PAD_SIGNAL_ATV_VIDEO
+ *	Contains a bitstream of samples from an analog TV video source, with
+ *	usually contains the VBI data on it.
+ * @PAD_SIGNAL_AUDIO
+ *	Contains an Intermediate Frequency analog signal from an audio
+ *	sub-carrier or an audio bitstream. Provided by tuners and consumed by audio AM/FM decoders.
+ */
+enum media_pad_signal_type {
+	PAD_SIGNAL_DEFAULT = 0,
+	PAD_SIGNAL_RF,
+	PAD_SIGNAL_CARRIERS,
+	PAD_SIGNAL_ATV_VIDEO,
+	PAD_SIGNAL_AUDIO,
+};
+
 /**
  * struct media_pad - A media pad graph object.
  *
@@ -169,6 +201,7 @@ struct media_pad {
 	struct media_gobj graph_obj;	/* must be first field in struct */
 	struct media_entity *entity;
 	u16 index;
+	enum media_pad_signal_type sig_type;
 	unsigned long flags;
 };
 
diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h
index 2634d9dc9916..7c9c781b16a9 100644
--- a/include/media/v4l2-mc.h
+++ b/include/media/v4l2-mc.h
@@ -89,14 +89,12 @@ enum if_aud_dec_pad_index {
  *
  * @DEMOD_PAD_IF_INPUT:	IF input sink pad.
  * @DEMOD_PAD_VID_OUT:	Video output source pad.
- * @DEMOD_PAD_VBI_OUT:	Vertical Blank Interface (VBI) output source pad.
  * @DEMOD_PAD_AUDIO_OUT: Audio output source pad.
  * @DEMOD_NUM_PADS:	Maximum number of output pads.
  */
 enum demod_pad_index {
 	DEMOD_PAD_IF_INPUT,
 	DEMOD_PAD_VID_OUT,
-	DEMOD_PAD_VBI_OUT,
 	DEMOD_PAD_AUDIO_OUT,
 	DEMOD_NUM_PADS
 };





Thanks,
Mauro

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

* Re: [PATCH 18/22] partial revert of "[media] tvp5150: add HW input connectors support"
  2018-07-31 12:52             ` Javier Martinez Canillas
@ 2018-07-31 13:30               ` Marco Felsch
  2018-07-31 19:56                 ` Mauro Carvalho Chehab
  2018-08-01 15:49                 ` Marco Felsch
  0 siblings, 2 replies; 70+ messages in thread
From: Marco Felsch @ 2018-07-31 13:30 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: Mauro Carvalho Chehab, mchehab, robh+dt, mark.rutland, p.zabel,
	afshin.nasser, sakari.ailus, laurent.pinchart, linux-media,
	devicetree, kernel

Hi Javier,

On 18-07-31 14:52, Javier Martinez Canillas wrote:
> Hi Marco,
> 
> On 07/31/2018 02:36 PM, Marco Felsch wrote:
> 
> [snip]
> 
> >>
> >> Yes, another thing that patch 19/22 should take into account is DTs that
> >> don't have input connectors defined. So probably TVP5150_PORT_YOUT should
> >> be 0 instead of TVP5150_PORT_NUM - 1 as is the case in the current patch.
> >>
> >> In other words, it should work both when input connectors are defined in
> >> the DT and when these are not defined and only an output port is defined.
> > 
> > Yes, it would be a approach to map the output port dynamicaly to the
> > highest port number. I tried to keep things easy by a static mapping.
> > Maybe a follow up patch can change this behaviour.
> > 
> > Anyway, input connectors aren't required. There must be at least one
> > port child node with a correct port-number in the DT.
> >
> 
> Yes, that was my point. But your patch uses the port child reg property as
> the index for the struct device_node *endpoints[TVP5150_PORT_NUM] array.
> 
> If there's only one port child (for the output) then the DT binding says
> that the reg property isn't required, so this will be 0 and your patch will
> wrongly map it to TVP5150_PORT_AIP1A. That's why I said that the output port
> should be the first one in your enum tvp5150_ports and not the last one.

Yes, now I got you. I implemted this in such a way in my first apporach.
But at the moment I don't know why I changed this. Maybe to keep the
decoder->input number in sync with the em28xx devices, which will set the
port by the s_routing() callback.

Let me check this.

Best Regards,
Marco

> > Regards,
> > Marco
> > 
> 
> Best regards,

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

* Re: [PATCH 18/22] partial revert of "[media] tvp5150: add HW input connectors support"
  2018-07-31 13:30               ` Marco Felsch
@ 2018-07-31 19:56                 ` Mauro Carvalho Chehab
  2018-08-01 12:10                   ` Marco Felsch
  2018-08-01 15:49                 ` Marco Felsch
  1 sibling, 1 reply; 70+ messages in thread
From: Mauro Carvalho Chehab @ 2018-07-31 19:56 UTC (permalink / raw)
  To: Marco Felsch
  Cc: Javier Martinez Canillas, mchehab, robh+dt, mark.rutland,
	p.zabel, afshin.nasser, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

Em Tue, 31 Jul 2018 15:30:56 +0200
Marco Felsch <m.felsch@pengutronix.de> escreveu:

> Hi Javier,
> 
> On 18-07-31 14:52, Javier Martinez Canillas wrote:
> > Hi Marco,
> > 
> > On 07/31/2018 02:36 PM, Marco Felsch wrote:
> > 
> > [snip]
> >   
> > >>
> > >> Yes, another thing that patch 19/22 should take into account is DTs that
> > >> don't have input connectors defined. So probably TVP5150_PORT_YOUT should
> > >> be 0 instead of TVP5150_PORT_NUM - 1 as is the case in the current patch.
> > >>
> > >> In other words, it should work both when input connectors are defined in
> > >> the DT and when these are not defined and only an output port is defined.  
> > > 
> > > Yes, it would be a approach to map the output port dynamicaly to the
> > > highest port number. I tried to keep things easy by a static mapping.
> > > Maybe a follow up patch can change this behaviour.
> > > 
> > > Anyway, input connectors aren't required. There must be at least one
> > > port child node with a correct port-number in the DT.
> > >  
> > 
> > Yes, that was my point. But your patch uses the port child reg property as
> > the index for the struct device_node *endpoints[TVP5150_PORT_NUM] array.
> > 
> > If there's only one port child (for the output) then the DT binding says
> > that the reg property isn't required, so this will be 0 and your patch will
> > wrongly map it to TVP5150_PORT_AIP1A. That's why I said that the output port
> > should be the first one in your enum tvp5150_ports and not the last one.  
> 
> Yes, now I got you. I implemted this in such a way in my first apporach.
> But at the moment I don't know why I changed this. Maybe to keep the
> decoder->input number in sync with the em28xx devices, which will set the
> port by the s_routing() callback.
> 
> Let me check this.

Anyway, with the patchset I sent (with one fix), it will do the right
thing with regards to the pad output:
	https://git.linuxtv.org/mchehab/experimental.git/log/?h=tvp5150


$ mc_nextgen_test -D 
digraph board {
	rankdir=TB
	colorscheme=x11
	labelloc="t"
	label="Grabster AV 350
 driver:em28xx, bus: usb-0000:00:14.0-2
"
	intf_devnode_7 [label="intf_devnode_7\nvideo\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
	intf_devnode_10 [label="intf_devnode_10\nvbi\n/dev/vbi0", shape=box, style=filled, fillcolor=yellow]
	entity_1 [label="{{<pad_2> 0 | <pad_3> 1 | <pad_4> 2} | entity_1\nATV decoder\ntvp5150 0-005c | {<pad_5> 3}}", shape=Mrecord, style=filled, fillcolor=lightblue]
	entity_6 [label="{{<pad_12> 0} | entity_6\nV4L I/O\n2-2:1.0 video}", shape=Mrecord, style=filled, fillcolor=aquamarine]
	entity_9 [label="{{<pad_13> 0} | entity_9\nVBI I/O\n2-2:1.0 vbi}", shape=Mrecord, style=filled, fillcolor=aquamarine]
	entity_14 [label="{entity_14\nunknown entity type\nComposite | {<pad_15> 0}}", shape=Mrecord, style=filled, fillcolor=cadetblue]
	entity_16 [label="{entity_16\nunknown entity type\nS-Video | {<pad_17> 0}}", shape=Mrecord, style=filled, fillcolor=cadetblue]
	intf_devnode_7 -> entity_6 [dir="none" color="orange"]
	intf_devnode_10 -> entity_9 [dir="none" color="orange"]
	entity_1:pad_5 -> entity_6:pad_12 [color=blue]
	entity_1:pad_5 -> entity_9:pad_13 [color=blue]
	entity_14:pad_15 -> entity_1:pad_2 [color=blue]
	entity_16:pad_17 -> entity_1:pad_2 [color=blue style="dashed"]
}

It won't do the right thing with regards to the input, though, as
the code at v4l2-mc.c expects just one input. So, both composite and
S-Video connectors (created outside tvp5150, based on the input entries
at em28xx cards table) are linked to pad 0. 

Thanks,
Mauro

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

* Re: [PATCH 18/22] partial revert of "[media] tvp5150: add HW input connectors support"
  2018-07-31 19:56                 ` Mauro Carvalho Chehab
@ 2018-08-01 12:10                   ` Marco Felsch
  2018-08-01 13:32                     ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 70+ messages in thread
From: Marco Felsch @ 2018-08-01 12:10 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Javier Martinez Canillas, mchehab, robh+dt, mark.rutland,
	p.zabel, afshin.nasser, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

Hi Mauro,

On 18-07-31 16:56, Mauro Carvalho Chehab wrote:
> Em Tue, 31 Jul 2018 15:30:56 +0200
> Marco Felsch <m.felsch@pengutronix.de> escreveu:
> 
> > Hi Javier,
> > 
> > On 18-07-31 14:52, Javier Martinez Canillas wrote:
> > > Hi Marco,
> > > 
> > > On 07/31/2018 02:36 PM, Marco Felsch wrote:
> > > 
> > > [snip]
> > >   
> > > >>
> > > >> Yes, another thing that patch 19/22 should take into account is DTs that
> > > >> don't have input connectors defined. So probably TVP5150_PORT_YOUT should
> > > >> be 0 instead of TVP5150_PORT_NUM - 1 as is the case in the current patch.
> > > >>
> > > >> In other words, it should work both when input connectors are defined in
> > > >> the DT and when these are not defined and only an output port is defined.  
> > > > 
> > > > Yes, it would be a approach to map the output port dynamicaly to the
> > > > highest port number. I tried to keep things easy by a static mapping.
> > > > Maybe a follow up patch can change this behaviour.
> > > > 
> > > > Anyway, input connectors aren't required. There must be at least one
> > > > port child node with a correct port-number in the DT.
> > > >  
> > > 
> > > Yes, that was my point. But your patch uses the port child reg property as
> > > the index for the struct device_node *endpoints[TVP5150_PORT_NUM] array.
> > > 
> > > If there's only one port child (for the output) then the DT binding says
> > > that the reg property isn't required, so this will be 0 and your patch will
> > > wrongly map it to TVP5150_PORT_AIP1A. That's why I said that the output port
> > > should be the first one in your enum tvp5150_ports and not the last one.  
> > 
> > Yes, now I got you. I implemted this in such a way in my first apporach.
> > But at the moment I don't know why I changed this. Maybe to keep the
> > decoder->input number in sync with the em28xx devices, which will set the
> > port by the s_routing() callback.
> > 
> > Let me check this.

I will prepare a follow up patch wich fix this behaviour, if possible.

> 
> Anyway, with the patchset I sent (with one fix), it will do the right
> thing with regards to the pad output:
> 	https://git.linuxtv.org/mchehab/experimental.git/log/?h=tvp5150

Thanks for your work :)
I have just one question. Is it correct to set the .sig_type only for the
tvp5150 'main' entity or should it be set for the dynamical connector
entities too?

> 
> $ mc_nextgen_test -D 
> digraph board {
> 	rankdir=TB
> 	colorscheme=x11
> 	labelloc="t"
> 	label="Grabster AV 350
>  driver:em28xx, bus: usb-0000:00:14.0-2
> "
> 	intf_devnode_7 [label="intf_devnode_7\nvideo\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
> 	intf_devnode_10 [label="intf_devnode_10\nvbi\n/dev/vbi0", shape=box, style=filled, fillcolor=yellow]
> 	entity_1 [label="{{<pad_2> 0 | <pad_3> 1 | <pad_4> 2} | entity_1\nATV decoder\ntvp5150 0-005c | {<pad_5> 3}}", shape=Mrecord, style=filled, fillcolor=lightblue]
> 	entity_6 [label="{{<pad_12> 0} | entity_6\nV4L I/O\n2-2:1.0 video}", shape=Mrecord, style=filled, fillcolor=aquamarine]
> 	entity_9 [label="{{<pad_13> 0} | entity_9\nVBI I/O\n2-2:1.0 vbi}", shape=Mrecord, style=filled, fillcolor=aquamarine]
> 	entity_14 [label="{entity_14\nunknown entity type\nComposite | {<pad_15> 0}}", shape=Mrecord, style=filled, fillcolor=cadetblue]
> 	entity_16 [label="{entity_16\nunknown entity type\nS-Video | {<pad_17> 0}}", shape=Mrecord, style=filled, fillcolor=cadetblue]
> 	intf_devnode_7 -> entity_6 [dir="none" color="orange"]
> 	intf_devnode_10 -> entity_9 [dir="none" color="orange"]
> 	entity_1:pad_5 -> entity_6:pad_12 [color=blue]
> 	entity_1:pad_5 -> entity_9:pad_13 [color=blue]
> 	entity_14:pad_15 -> entity_1:pad_2 [color=blue]
> 	entity_16:pad_17 -> entity_1:pad_2 [color=blue style="dashed"]
> }
> 
> It won't do the right thing with regards to the input, though, as
> the code at v4l2-mc.c expects just one input. So, both composite and
> S-Video connectors (created outside tvp5150, based on the input entries
> at em28xx cards table) are linked to pad 0. 

Should we add comment for this behaviour in v4l2-mc.c? Since the
MEDIA_ENT_F_CONN_RF case updates the pad number.

> 
> Thanks,
> Mauro
> 

Regards,
Marco

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

* Re: [PATCH 16/22] [media] tvp5150: add querystd
  2018-07-30 18:09   ` Mauro Carvalho Chehab
@ 2018-08-01 13:21     ` Marco Felsch
  2018-08-01 14:22       ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 70+ messages in thread
From: Marco Felsch @ 2018-08-01 13:21 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Hi Mauro,

On 18-07-30 15:09, Mauro Carvalho Chehab wrote:
> Em Thu, 28 Jun 2018 18:20:48 +0200
> Marco Felsch <m.felsch@pengutronix.de> escreveu:
> 
> > From: Philipp Zabel <p.zabel@pengutronix.de>
> > 
> > Add the querystd video_op and make it return V4L2_STD_UNKNOWN while the
> > TVP5150 is not locked to a signal.
> > 
> > Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > ---
> >  drivers/media/i2c/tvp5150.c | 10 ++++++++++
> >  1 file changed, 10 insertions(+)
> > 
> > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > index 99d887936ea0..1990aaa17749 100644
> > --- a/drivers/media/i2c/tvp5150.c
> > +++ b/drivers/media/i2c/tvp5150.c
> > @@ -796,6 +796,15 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
> >  	}
> >  }
> >  
> > +static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
> > +{
> > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > +
> > +	*std_id = decoder->lock ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
> 
> This patch requires rework. What happens when a device doesn't have
> IRQ enabled? Perhaps it should, instead, read some register in order
> to check for the locking status, as this would work on both cases.

If IRQ isn't enabled, decoder->lock is set to always true during
probe(). So this case should be fine.

Regards,
Marco

> > +
> > +	return 0;
> > +}
> > +
> >  static const struct v4l2_event tvp5150_ev_fmt = {
> >  	.type = V4L2_EVENT_SOURCE_CHANGE,
> >  	.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
> > @@ -1408,6 +1417,7 @@ static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = {
> >  
> >  static const struct v4l2_subdev_video_ops tvp5150_video_ops = {
> >  	.s_std = tvp5150_s_std,
> > +	.querystd = tvp5150_querystd,
> >  	.s_stream = tvp5150_s_stream,
> >  	.s_routing = tvp5150_s_routing,
> >  	.g_mbus_config = tvp5150_g_mbus_config,
> 
> 
> 
> Thanks,
> Mauro
> 

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

* Re: [PATCH 18/22] partial revert of "[media] tvp5150: add HW input connectors support"
  2018-08-01 12:10                   ` Marco Felsch
@ 2018-08-01 13:32                     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 70+ messages in thread
From: Mauro Carvalho Chehab @ 2018-08-01 13:32 UTC (permalink / raw)
  To: Marco Felsch
  Cc: Javier Martinez Canillas, mchehab, robh+dt, mark.rutland,
	p.zabel, afshin.nasser, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

Em Wed, 1 Aug 2018 14:10:47 +0200
Marco Felsch <m.felsch@pengutronix.de> escreveu:

> Hi Mauro,
> 
> On 18-07-31 16:56, Mauro Carvalho Chehab wrote:
> > Em Tue, 31 Jul 2018 15:30:56 +0200
> > Marco Felsch <m.felsch@pengutronix.de> escreveu:
> >   
> > > Hi Javier,
> > > 
> > > On 18-07-31 14:52, Javier Martinez Canillas wrote:  
> > > > Hi Marco,
> > > > 
> > > > On 07/31/2018 02:36 PM, Marco Felsch wrote:
> > > > 
> > > > [snip]
> > > >     
> > > > >>
> > > > >> Yes, another thing that patch 19/22 should take into account is DTs that
> > > > >> don't have input connectors defined. So probably TVP5150_PORT_YOUT should
> > > > >> be 0 instead of TVP5150_PORT_NUM - 1 as is the case in the current patch.
> > > > >>
> > > > >> In other words, it should work both when input connectors are defined in
> > > > >> the DT and when these are not defined and only an output port is defined.    
> > > > > 
> > > > > Yes, it would be a approach to map the output port dynamicaly to the
> > > > > highest port number. I tried to keep things easy by a static mapping.
> > > > > Maybe a follow up patch can change this behaviour.
> > > > > 
> > > > > Anyway, input connectors aren't required. There must be at least one
> > > > > port child node with a correct port-number in the DT.
> > > > >    
> > > > 
> > > > Yes, that was my point. But your patch uses the port child reg property as
> > > > the index for the struct device_node *endpoints[TVP5150_PORT_NUM] array.
> > > > 
> > > > If there's only one port child (for the output) then the DT binding says
> > > > that the reg property isn't required, so this will be 0 and your patch will
> > > > wrongly map it to TVP5150_PORT_AIP1A. That's why I said that the output port
> > > > should be the first one in your enum tvp5150_ports and not the last one.    
> > > 
> > > Yes, now I got you. I implemted this in such a way in my first apporach.
> > > But at the moment I don't know why I changed this. Maybe to keep the
> > > decoder->input number in sync with the em28xx devices, which will set the
> > > port by the s_routing() callback.
> > > 
> > > Let me check this.  
> 
> I will prepare a follow up patch wich fix this behaviour, if possible.
> 
> > 
> > Anyway, with the patchset I sent (with one fix), it will do the right
> > thing with regards to the pad output:
> > 	https://git.linuxtv.org/mchehab/experimental.git/log/?h=tvp5150  
> 
> Thanks for your work :)
> I have just one question. Is it correct to set the .sig_type only for the
> tvp5150 'main' entity or should it be set for the dynamical connector
> entities too?

It should be needed only for entities with multiple pads, when
the pad index is not enough to uniquely identify what's there at
the pad. I don't think this applies to typical connectors
(although it might make sense on HDMI, where it may contain
different signals besides video, like CEC and ethernet).

> 
> > 
> > $ mc_nextgen_test -D 
> > digraph board {
> > 	rankdir=TB
> > 	colorscheme=x11
> > 	labelloc="t"
> > 	label="Grabster AV 350
> >  driver:em28xx, bus: usb-0000:00:14.0-2
> > "
> > 	intf_devnode_7 [label="intf_devnode_7\nvideo\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
> > 	intf_devnode_10 [label="intf_devnode_10\nvbi\n/dev/vbi0", shape=box, style=filled, fillcolor=yellow]
> > 	entity_1 [label="{{<pad_2> 0 | <pad_3> 1 | <pad_4> 2} | entity_1\nATV decoder\ntvp5150 0-005c | {<pad_5> 3}}", shape=Mrecord, style=filled, fillcolor=lightblue]
> > 	entity_6 [label="{{<pad_12> 0} | entity_6\nV4L I/O\n2-2:1.0 video}", shape=Mrecord, style=filled, fillcolor=aquamarine]
> > 	entity_9 [label="{{<pad_13> 0} | entity_9\nVBI I/O\n2-2:1.0 vbi}", shape=Mrecord, style=filled, fillcolor=aquamarine]
> > 	entity_14 [label="{entity_14\nunknown entity type\nComposite | {<pad_15> 0}}", shape=Mrecord, style=filled, fillcolor=cadetblue]
> > 	entity_16 [label="{entity_16\nunknown entity type\nS-Video | {<pad_17> 0}}", shape=Mrecord, style=filled, fillcolor=cadetblue]
> > 	intf_devnode_7 -> entity_6 [dir="none" color="orange"]
> > 	intf_devnode_10 -> entity_9 [dir="none" color="orange"]
> > 	entity_1:pad_5 -> entity_6:pad_12 [color=blue]
> > 	entity_1:pad_5 -> entity_9:pad_13 [color=blue]
> > 	entity_14:pad_15 -> entity_1:pad_2 [color=blue]
> > 	entity_16:pad_17 -> entity_1:pad_2 [color=blue style="dashed"]
> > }
> > 
> > It won't do the right thing with regards to the input, though, as
> > the code at v4l2-mc.c expects just one input. So, both composite and
> > S-Video connectors (created outside tvp5150, based on the input entries
> > at em28xx cards table) are linked to pad 0.   
> 
> Should we add comment for this behaviour in v4l2-mc.c? Since the
> MEDIA_ENT_F_CONN_RF case updates the pad number.

I don't think so... The stuff at v4l2-mc are there to help setting the
pipelines for devnode-based devices that also exposes their internal
wiring via MC. For those, it is up to the Kernel to create and manage
the pipelines. It is not used by MC-based devices, as, for those, 
the pipelines should be created by userspace via the MC device node.

Thanks,
Mauro

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

* Re: [PATCH 16/22] [media] tvp5150: add querystd
  2018-08-01 13:21     ` Marco Felsch
@ 2018-08-01 14:22       ` Mauro Carvalho Chehab
  2018-08-01 14:49         ` Marco Felsch
  0 siblings, 1 reply; 70+ messages in thread
From: Mauro Carvalho Chehab @ 2018-08-01 14:22 UTC (permalink / raw)
  To: Marco Felsch
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Em Wed, 1 Aug 2018 15:21:25 +0200
Marco Felsch <m.felsch@pengutronix.de> escreveu:

> Hi Mauro,
> 
> On 18-07-30 15:09, Mauro Carvalho Chehab wrote:
> > Em Thu, 28 Jun 2018 18:20:48 +0200
> > Marco Felsch <m.felsch@pengutronix.de> escreveu:
> >   
> > > From: Philipp Zabel <p.zabel@pengutronix.de>
> > > 
> > > Add the querystd video_op and make it return V4L2_STD_UNKNOWN while the
> > > TVP5150 is not locked to a signal.
> > > 
> > > Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> > > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > > ---
> > >  drivers/media/i2c/tvp5150.c | 10 ++++++++++
> > >  1 file changed, 10 insertions(+)
> > > 
> > > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > > index 99d887936ea0..1990aaa17749 100644
> > > --- a/drivers/media/i2c/tvp5150.c
> > > +++ b/drivers/media/i2c/tvp5150.c
> > > @@ -796,6 +796,15 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
> > >  	}
> > >  }
> > >  
> > > +static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
> > > +{
> > > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > > +
> > > +	*std_id = decoder->lock ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;  
> > 
> > This patch requires rework. What happens when a device doesn't have
> > IRQ enabled? Perhaps it should, instead, read some register in order
> > to check for the locking status, as this would work on both cases.  
> 
> If IRQ isn't enabled, decoder->lock is set to always true during
> probe(). So this case should be fine.

Not sure if tvp5150_read_std() will do the right thing. If it does,
the above could simply be:
	std_id = tvp5150_read_std(sd);

But, as there are 3 variants of this chipset, it sounds safer to check
if the device is locked before calling tvp5150_read_std().

IMHO, the best would be to have a patch like the one below.

Regards,
Mauro

[PATCH] media: tvp5150: implement decoder lock when irq is not used

When irq is used, the lock is set via IRQ code. When it isn't,
the driver just assumes it is always locked. Instead, read the
lock status from the status register.

Compile-tested only.

Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>

diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index 75e5ffc6573d..e07020d4053d 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -811,11 +811,24 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
 	}
 }
 
+static int query_lock(struct v4l2_subdev *sd)
+{
+	struct tvp5150 *decoder = to_tvp5150(sd);
+	int status;
+
+	if (decoder->irq)
+		return decoder->lock;
+
+	regmap_read(map, TVP5150_INT_STATUS_REG_A, &status);
+
+	return (status & 0x06) == 0x06;
+}
+
 static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
 {
 	struct tvp5150 *decoder = to_tvp5150(sd);
 
-	*std_id = decoder->lock ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
+	*std_id = query_lock(sd) ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
 
 	return 0;
 }
@@ -1247,7 +1260,7 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
 		tvp5150_enable(sd);
 
 		/* Enable outputs if decoder is locked */
-		val = decoder->lock ? decoder->oe : 0;
+		val = query_lock(sd) ? decoder->oe : 0;
 		int_val = TVP5150_INT_A_LOCK;
 		v4l2_subdev_notify_event(&decoder->sd, &tvp5150_ev_fmt);
 	}
@@ -1816,8 +1829,6 @@ static int tvp5150_probe(struct i2c_client *c,
 						IRQF_ONESHOT, "tvp5150", core);
 		if (res)
 			return res;
-	} else {
-		core->lock = true;
 	}
 
 	res = v4l2_async_register_subdev(sd);

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

* Re: [PATCH 16/22] [media] tvp5150: add querystd
  2018-08-01 14:22       ` Mauro Carvalho Chehab
@ 2018-08-01 14:49         ` Marco Felsch
  2018-08-01 15:50           ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 70+ messages in thread
From: Marco Felsch @ 2018-08-01 14:49 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Hi Mauro,

On 18-08-01 11:22, Mauro Carvalho Chehab wrote:
> Em Wed, 1 Aug 2018 15:21:25 +0200
> Marco Felsch <m.felsch@pengutronix.de> escreveu:
> 
> > Hi Mauro,
> > 
> > On 18-07-30 15:09, Mauro Carvalho Chehab wrote:
> > > Em Thu, 28 Jun 2018 18:20:48 +0200
> > > Marco Felsch <m.felsch@pengutronix.de> escreveu:
> > >   
> > > > From: Philipp Zabel <p.zabel@pengutronix.de>
> > > > 
> > > > Add the querystd video_op and make it return V4L2_STD_UNKNOWN while the
> > > > TVP5150 is not locked to a signal.
> > > > 
> > > > Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> > > > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > > > ---
> > > >  drivers/media/i2c/tvp5150.c | 10 ++++++++++
> > > >  1 file changed, 10 insertions(+)
> > > > 
> > > > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > > > index 99d887936ea0..1990aaa17749 100644
> > > > --- a/drivers/media/i2c/tvp5150.c
> > > > +++ b/drivers/media/i2c/tvp5150.c
> > > > @@ -796,6 +796,15 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
> > > >  	}
> > > >  }
> > > >  
> > > > +static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
> > > > +{
> > > > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > > > +
> > > > +	*std_id = decoder->lock ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;  
> > > 
> > > This patch requires rework. What happens when a device doesn't have
> > > IRQ enabled? Perhaps it should, instead, read some register in order
> > > to check for the locking status, as this would work on both cases.  
> > 
> > If IRQ isn't enabled, decoder->lock is set to always true during
> > probe(). So this case should be fine.
> 
> Not sure if tvp5150_read_std() will do the right thing. If it does,
> the above could simply be:
> 	std_id = tvp5150_read_std(sd);
> 
> But, as there are 3 variants of this chipset, it sounds safer to check
> if the device is locked before calling tvp5150_read_std().

Yes, I'm with you.

> 
> IMHO, the best would be to have a patch like the one below.
> 
> Regards,
> Mauro
> 
> [PATCH] media: tvp5150: implement decoder lock when irq is not used
> 
> When irq is used, the lock is set via IRQ code. When it isn't,
> the driver just assumes it is always locked. Instead, read the
> lock status from the status register.

Yes, that is a better solution.

> 
> Compile-tested only.
> 
> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
> 
> diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> index 75e5ffc6573d..e07020d4053d 100644
> --- a/drivers/media/i2c/tvp5150.c
> +++ b/drivers/media/i2c/tvp5150.c
> @@ -811,11 +811,24 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
>  	}
>  }
>  
> +static int query_lock(struct v4l2_subdev *sd)
> +{
> +	struct tvp5150 *decoder = to_tvp5150(sd);
> +	int status;
> +
> +	if (decoder->irq)
> +		return decoder->lock;
> +
> +	regmap_read(map, TVP5150_INT_STATUS_REG_A, &status);
> +
> +	return (status & 0x06) == 0x06;

Typo? It should be 0x80, as described in the datasheet (SLES209E) or
just use the TVP5150_INT_A_LOCK_STATUS define. This avoid datasheet
cross check during reading.

> +}
> +
>  static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
>  {
>  	struct tvp5150 *decoder = to_tvp5150(sd);
>  
> -	*std_id = decoder->lock ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
> +	*std_id = query_lock(sd) ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
>  
>  	return 0;
>  }
> @@ -1247,7 +1260,7 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
>  		tvp5150_enable(sd);
>  
>  		/* Enable outputs if decoder is locked */
> -		val = decoder->lock ? decoder->oe : 0;
> +		val = query_lock(sd) ? decoder->oe : 0;
>  		int_val = TVP5150_INT_A_LOCK;
>  		v4l2_subdev_notify_event(&decoder->sd, &tvp5150_ev_fmt);
>  	}
> @@ -1816,8 +1829,6 @@ static int tvp5150_probe(struct i2c_client *c,
>  						IRQF_ONESHOT, "tvp5150", core);
>  		if (res)
>  			return res;
> -	} else {
> -		core->lock = true;
>  	}
>  
>  	res = v4l2_async_register_subdev(sd);
> 
> 
> 

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

* Re: [PATCH 18/22] partial revert of "[media] tvp5150: add HW input connectors support"
  2018-07-31 13:30               ` Marco Felsch
  2018-07-31 19:56                 ` Mauro Carvalho Chehab
@ 2018-08-01 15:49                 ` Marco Felsch
  2018-08-01 16:23                   ` Javier Martinez Canillas
  1 sibling, 1 reply; 70+ messages in thread
From: Marco Felsch @ 2018-08-01 15:49 UTC (permalink / raw)
  To: Javier Martinez Canillas
  Cc: Mauro Carvalho Chehab, mchehab, robh+dt, mark.rutland, p.zabel,
	afshin.nasser, sakari.ailus, laurent.pinchart, linux-media,
	devicetree, kernel

Hi Javier,

On 18-07-31 15:30, Marco Felsch wrote:
> Hi Javier,
> 
> On 18-07-31 14:52, Javier Martinez Canillas wrote:
> > Hi Marco,
> > 
> > On 07/31/2018 02:36 PM, Marco Felsch wrote:
> > 
> > [snip]
> > 
> > >>
> > >> Yes, another thing that patch 19/22 should take into account is DTs that
> > >> don't have input connectors defined. So probably TVP5150_PORT_YOUT should
> > >> be 0 instead of TVP5150_PORT_NUM - 1 as is the case in the current patch.
> > >>
> > >> In other words, it should work both when input connectors are defined in
> > >> the DT and when these are not defined and only an output port is defined.
> > > 
> > > Yes, it would be a approach to map the output port dynamicaly to the
> > > highest port number. I tried to keep things easy by a static mapping.
> > > Maybe a follow up patch can change this behaviour.
> > > 
> > > Anyway, input connectors aren't required. There must be at least one
> > > port child node with a correct port-number in the DT.
> > >
> > 
> > Yes, that was my point. But your patch uses the port child reg property as
> > the index for the struct device_node *endpoints[TVP5150_PORT_NUM] array.
> > 
> > If there's only one port child (for the output) then the DT binding says
> > that the reg property isn't required, so this will be 0 and your patch will
> > wrongly map it to TVP5150_PORT_AIP1A. That's why I said that the output port
> > should be the first one in your enum tvp5150_ports and not the last one.
> 
> Yes, now I got you. I implemted this in such a way in my first apporach.
> But at the moment I don't know why I changed this. Maybe to keep the
> decoder->input number in sync with the em28xx devices, which will set the
> port by the s_routing() callback.
> 
> Let me check this.

I checked it again. Your're right, it should be doable but IMHO it isn't
the right solution. I checked some drivers which use of_graph and all of
them put the output at the end. So the tvp5150 will be the only one
which maps the out put to the first pad and it isn't intuitive.

I discused it with a colleague. We think a better solution would be to fix
the v4l2-core parser code to allow a independent dt-port<->pad mapping.
Since now the pad's correspond to the port number. This mapping should
be done by a driver callback, so each driver can do it's own custom
mapping.

Regards,
Marco

> 
> Best Regards,
> Marco
> 
> > > Regards,
> > > Marco
> > > 
> > 
> > Best regards,
> 

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

* Re: [PATCH 16/22] [media] tvp5150: add querystd
  2018-08-01 14:49         ` Marco Felsch
@ 2018-08-01 15:50           ` Mauro Carvalho Chehab
  2018-08-02  8:01             ` Marco Felsch
  0 siblings, 1 reply; 70+ messages in thread
From: Mauro Carvalho Chehab @ 2018-08-01 15:50 UTC (permalink / raw)
  To: Marco Felsch
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Em Wed, 1 Aug 2018 16:49:26 +0200
Marco Felsch <m.felsch@pengutronix.de> escreveu:

> Hi Mauro,
> 
> On 18-08-01 11:22, Mauro Carvalho Chehab wrote:
> > Em Wed, 1 Aug 2018 15:21:25 +0200
> > Marco Felsch <m.felsch@pengutronix.de> escreveu:
> >   
> > > Hi Mauro,
> > > 
> > > On 18-07-30 15:09, Mauro Carvalho Chehab wrote:  
> > > > Em Thu, 28 Jun 2018 18:20:48 +0200
> > > > Marco Felsch <m.felsch@pengutronix.de> escreveu:
> > > >     
> > > > > From: Philipp Zabel <p.zabel@pengutronix.de>
> > > > > 
> > > > > Add the querystd video_op and make it return V4L2_STD_UNKNOWN while the
> > > > > TVP5150 is not locked to a signal.
> > > > > 
> > > > > Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> > > > > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > > > > ---
> > > > >  drivers/media/i2c/tvp5150.c | 10 ++++++++++
> > > > >  1 file changed, 10 insertions(+)
> > > > > 
> > > > > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > > > > index 99d887936ea0..1990aaa17749 100644
> > > > > --- a/drivers/media/i2c/tvp5150.c
> > > > > +++ b/drivers/media/i2c/tvp5150.c
> > > > > @@ -796,6 +796,15 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
> > > > >  	}
> > > > >  }
> > > > >  
> > > > > +static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
> > > > > +{
> > > > > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > > > > +
> > > > > +	*std_id = decoder->lock ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;    
> > > > 
> > > > This patch requires rework. What happens when a device doesn't have
> > > > IRQ enabled? Perhaps it should, instead, read some register in order
> > > > to check for the locking status, as this would work on both cases.    
> > > 
> > > If IRQ isn't enabled, decoder->lock is set to always true during
> > > probe(). So this case should be fine.  
> > 
> > Not sure if tvp5150_read_std() will do the right thing. If it does,
> > the above could simply be:
> > 	std_id = tvp5150_read_std(sd);
> > 
> > But, as there are 3 variants of this chipset, it sounds safer to check
> > if the device is locked before calling tvp5150_read_std().  
> 
> Yes, I'm with you.
> 
> > 
> > IMHO, the best would be to have a patch like the one below.
> > 
> > Regards,
> > Mauro
> > 
> > [PATCH] media: tvp5150: implement decoder lock when irq is not used
> > 
> > When irq is used, the lock is set via IRQ code. When it isn't,
> > the driver just assumes it is always locked. Instead, read the
> > lock status from the status register.  
> 
> Yes, that is a better solution.
> 
> > 
> > Compile-tested only.
> > 
> > Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
> > 
> > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > index 75e5ffc6573d..e07020d4053d 100644
> > --- a/drivers/media/i2c/tvp5150.c
> > +++ b/drivers/media/i2c/tvp5150.c
> > @@ -811,11 +811,24 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
> >  	}
> >  }
> >  
> > +static int query_lock(struct v4l2_subdev *sd)
> > +{
> > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > +	int status;
> > +
> > +	if (decoder->irq)
> > +		return decoder->lock;
> > +
> > +	regmap_read(map, TVP5150_INT_STATUS_REG_A, &status);
> > +
> > +	return (status & 0x06) == 0x06;  
> 
> Typo? It should be 0x80, as described in the datasheet (SLES209E) or
> just use the TVP5150_INT_A_LOCK_STATUS define. This avoid datasheet
> cross check during reading.

Yes, it is a typo, but at the other line... I meant to use the register
0x88, e. g.:

	regmap_read(decoder->regmap, TVP5150_STATUS_REG_1, &status);

I ran some tests here: the int status reg is not updated.

Also, after thinking a little bit, I opted to not use the query_lock()
at s_stream. It makes no sense there without adding a status polling
logic. I also opted to remove initializing decoder->lock to true, as
this is very counter-intuitive. Instead, I'm adding a test at s_stream
if decoder->irq is set. This makes easier to understand the code.

Btw, on my tests here, I noticed a problem with S-Video... at least with
AV-350 grabber, composite is only working when S-Video is connected.

This bug also happens before your patchset, so this is not a regression
caused by your patches.

Anyway, patch enclosed. I added it together with my patch series at:

	https://git.linuxtv.org/mchehab/experimental.git/log/?h=tvp5150-2

I'll keep doing more tests here.

> 
> > +}
> > +
> >  static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
> >  {
> >  	struct tvp5150 *decoder = to_tvp5150(sd);
> >  
> > -	*std_id = decoder->lock ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
> > +	*std_id = query_lock(sd) ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
> >  
> >  	return 0;
> >  }
> > @@ -1247,7 +1260,7 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
> >  		tvp5150_enable(sd);
> >  
> >  		/* Enable outputs if decoder is locked */
> > -		val = decoder->lock ? decoder->oe : 0;
> > +		val = query_lock(sd) ? decoder->oe : 0;
> >  		int_val = TVP5150_INT_A_LOCK;
> >  		v4l2_subdev_notify_event(&decoder->sd, &tvp5150_ev_fmt);
> >  	}
> > @@ -1816,8 +1829,6 @@ static int tvp5150_probe(struct i2c_client *c,
> >  						IRQF_ONESHOT, "tvp5150", core);
> >  		if (res)
> >  			return res;
> > -	} else {
> > -		core->lock = true;
> >  	}
> >  
> >  	res = v4l2_async_register_subdev(sd);
> > 
> > 
> >   

[PATCH] media: tvp5150: implement decoder lock when irq is not used

When irq is used, the lock is set via IRQ code. When it isn't,
the driver just assumes it is always locked. Instead, read the
lock status from the status register.

Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>

diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index efc441df7cac..e74af68be2eb 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -810,11 +810,25 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
 	}
 }
 
+static int query_lock(struct v4l2_subdev *sd)
+{
+	struct tvp5150 *decoder = to_tvp5150(sd);
+	int status;
+
+	if (decoder->irq)
+		return decoder->lock;
+
+	regmap_read(decoder->regmap, TVP5150_STATUS_REG_1, &status);
+
+	/* For standard detection, we need the 3 locks */
+	return (status & 0x0e) == 0x0e;
+}
+
 static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
 {
 	struct tvp5150 *decoder = to_tvp5150(sd);
 
-	*std_id = decoder->lock ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
+	*std_id = query_lock(sd) ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
 
 	return 0;
 }
@@ -1208,7 +1222,10 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
 		tvp5150_enable(sd);
 
 		/* Enable outputs if decoder is locked */
-		val = decoder->lock ? decoder->oe : 0;
+		if (decoder->irq)
+			val = decoder->lock ? decoder->oe : 0;
+		else
+			val = decoder->oe;
 		int_val = TVP5150_INT_A_LOCK;
 		v4l2_subdev_notify_event(&decoder->sd, &tvp5150_ev_fmt);
 	}
@@ -1777,8 +1794,6 @@ static int tvp5150_probe(struct i2c_client *c,
 						IRQF_ONESHOT, "tvp5150", core);
 		if (res)
 			return res;
-	} else {
-		core->lock = true;
 	}
 
 	res = v4l2_async_register_subdev(sd);



Thanks,
Mauro

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

* Re: [PATCH 18/22] partial revert of "[media] tvp5150: add HW input connectors support"
  2018-08-01 15:49                 ` Marco Felsch
@ 2018-08-01 16:23                   ` Javier Martinez Canillas
  0 siblings, 0 replies; 70+ messages in thread
From: Javier Martinez Canillas @ 2018-08-01 16:23 UTC (permalink / raw)
  To: Marco Felsch
  Cc: Mauro Carvalho Chehab, mchehab, robh+dt, mark.rutland, p.zabel,
	afshin.nasser, sakari.ailus, laurent.pinchart, linux-media,
	devicetree, kernel

Hi Marco,

On 08/01/2018 05:49 PM, Marco Felsch wrote:
> Hi Javier,
> 
> On 18-07-31 15:30, Marco Felsch wrote:
>> Hi Javier,
>>
>> On 18-07-31 14:52, Javier Martinez Canillas wrote:
>>> Hi Marco,
>>>
>>> On 07/31/2018 02:36 PM, Marco Felsch wrote:
>>>
>>> [snip]
>>>
>>>>>
>>>>> Yes, another thing that patch 19/22 should take into account is DTs that
>>>>> don't have input connectors defined. So probably TVP5150_PORT_YOUT should
>>>>> be 0 instead of TVP5150_PORT_NUM - 1 as is the case in the current patch.
>>>>>
>>>>> In other words, it should work both when input connectors are defined in
>>>>> the DT and when these are not defined and only an output port is defined.
>>>>
>>>> Yes, it would be a approach to map the output port dynamicaly to the
>>>> highest port number. I tried to keep things easy by a static mapping.
>>>> Maybe a follow up patch can change this behaviour.
>>>>
>>>> Anyway, input connectors aren't required. There must be at least one
>>>> port child node with a correct port-number in the DT.
>>>>
>>>
>>> Yes, that was my point. But your patch uses the port child reg property as
>>> the index for the struct device_node *endpoints[TVP5150_PORT_NUM] array.
>>>
>>> If there's only one port child (for the output) then the DT binding says
>>> that the reg property isn't required, so this will be 0 and your patch will
>>> wrongly map it to TVP5150_PORT_AIP1A. That's why I said that the output port
>>> should be the first one in your enum tvp5150_ports and not the last one.
>>
>> Yes, now I got you. I implemted this in such a way in my first apporach.
>> But at the moment I don't know why I changed this. Maybe to keep the
>> decoder->input number in sync with the em28xx devices, which will set the
>> port by the s_routing() callback.
>>
>> Let me check this.
> 
> I checked it again. Your're right, it should be doable but IMHO it isn't
> the right solution. I checked some drivers which use of_graph and all of
> them put the output at the end. So the tvp5150 will be the only one
> which maps the out put to the first pad and it isn't intuitive.
> 

Ah, I didn't notice that the tvp5150 was the exception. I just mentioned due
DT maintainers always ask for driver changes to be DTB backward compatible.

> I discused it with a colleague. We think a better solution would be to fix
> the v4l2-core parser code to allow a independent dt-port<->pad mapping.
> Since now the pad's correspond to the port number. This mapping should
> be done by a driver callback, so each driver can do it's own custom
> mapping.
>

That sounds good to me.
 
> Regards,
> Marco
> 

Best regards,
-- 
Javier Martinez Canillas
Software Engineer - Desktop Hardware Enablement
Red Hat

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

* Re: [PATCH 16/22] [media] tvp5150: add querystd
  2018-08-01 15:50           ` Mauro Carvalho Chehab
@ 2018-08-02  8:01             ` Marco Felsch
  2018-08-02  9:49               ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 70+ messages in thread
From: Marco Felsch @ 2018-08-02  8:01 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Hi Mauro,

On 18-08-01 12:50, Mauro Carvalho Chehab wrote:
> Em Wed, 1 Aug 2018 16:49:26 +0200
> Marco Felsch <m.felsch@pengutronix.de> escreveu:
> 
> > Hi Mauro,
> > 
> > On 18-08-01 11:22, Mauro Carvalho Chehab wrote:
> > > Em Wed, 1 Aug 2018 15:21:25 +0200
> > > Marco Felsch <m.felsch@pengutronix.de> escreveu:
> > >   
> > > > Hi Mauro,
> > > > 
> > > > On 18-07-30 15:09, Mauro Carvalho Chehab wrote:  
> > > > > Em Thu, 28 Jun 2018 18:20:48 +0200
> > > > > Marco Felsch <m.felsch@pengutronix.de> escreveu:
> > > > >     
> > > > > > From: Philipp Zabel <p.zabel@pengutronix.de>
> > > > > > 
> > > > > > Add the querystd video_op and make it return V4L2_STD_UNKNOWN while the
> > > > > > TVP5150 is not locked to a signal.
> > > > > > 
> > > > > > Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> > > > > > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > > > > > ---
> > > > > >  drivers/media/i2c/tvp5150.c | 10 ++++++++++
> > > > > >  1 file changed, 10 insertions(+)
> > > > > > 
> > > > > > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > > > > > index 99d887936ea0..1990aaa17749 100644
> > > > > > --- a/drivers/media/i2c/tvp5150.c
> > > > > > +++ b/drivers/media/i2c/tvp5150.c
> > > > > > @@ -796,6 +796,15 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
> > > > > >  	}
> > > > > >  }
> > > > > >  
> > > > > > +static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
> > > > > > +{
> > > > > > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > > > > > +
> > > > > > +	*std_id = decoder->lock ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;    
> > > > > 
> > > > > This patch requires rework. What happens when a device doesn't have
> > > > > IRQ enabled? Perhaps it should, instead, read some register in order
> > > > > to check for the locking status, as this would work on both cases.    
> > > > 
> > > > If IRQ isn't enabled, decoder->lock is set to always true during
> > > > probe(). So this case should be fine.  
> > > 
> > > Not sure if tvp5150_read_std() will do the right thing. If it does,
> > > the above could simply be:
> > > 	std_id = tvp5150_read_std(sd);
> > > 
> > > But, as there are 3 variants of this chipset, it sounds safer to check
> > > if the device is locked before calling tvp5150_read_std().  
> > 
> > Yes, I'm with you.
> > 
> > > 
> > > IMHO, the best would be to have a patch like the one below.
> > > 
> > > Regards,
> > > Mauro
> > > 
> > > [PATCH] media: tvp5150: implement decoder lock when irq is not used
> > > 
> > > When irq is used, the lock is set via IRQ code. When it isn't,
> > > the driver just assumes it is always locked. Instead, read the
> > > lock status from the status register.  
> > 
> > Yes, that is a better solution.
> > 
> > > 
> > > Compile-tested only.
> > > 
> > > Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
> > > 
> > > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > > index 75e5ffc6573d..e07020d4053d 100644
> > > --- a/drivers/media/i2c/tvp5150.c
> > > +++ b/drivers/media/i2c/tvp5150.c
> > > @@ -811,11 +811,24 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
> > >  	}
> > >  }
> > >  
> > > +static int query_lock(struct v4l2_subdev *sd)
> > > +{
> > > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > > +	int status;
> > > +
> > > +	if (decoder->irq)
> > > +		return decoder->lock;
> > > +
> > > +	regmap_read(map, TVP5150_INT_STATUS_REG_A, &status);
> > > +
> > > +	return (status & 0x06) == 0x06;  
> > 
> > Typo? It should be 0x80, as described in the datasheet (SLES209E) or
> > just use the TVP5150_INT_A_LOCK_STATUS define. This avoid datasheet
> > cross check during reading.
> 
> Yes, it is a typo, but at the other line... I meant to use the register
> 0x88, e. g.:
> 
> 	regmap_read(decoder->regmap, TVP5150_STATUS_REG_1, &status);

During my development I tried this status register too, as descibed on
the community website [1]. But that wasn't that good, because the look
will be lost very often. Bit7 of Interrupt Status Reg A (0xc0) is more
robust for that kind of work, since it covers the whole signal.

[1] http://e2e.ti.com/support/data_converters/videoconverters/f/918/p/ \
	617120/2273276?keyMatch=tvp5150%20lock%20lost&tisearch=Search-EN-Support
> 
> I ran some tests here: the int status reg is not updated.
> 
> Also, after thinking a little bit, I opted to not use the query_lock()
> at s_stream. It makes no sense there without adding a status polling
> logic. I also opted to remove initializing decoder->lock to true, as
> this is very counter-intuitive. Instead, I'm adding a test at s_stream
> if decoder->irq is set. This makes easier to understand the code.

Yes, you're right.

> Btw, on my tests here, I noticed a problem with S-Video... at least with
> AV-350 grabber, composite is only working when S-Video is connected.

Unfortunately I have only a custom board with one composite connection.

> 
> This bug also happens before your patchset, so this is not a regression
> caused by your patches.
> 
> Anyway, patch enclosed. I added it together with my patch series at:
> 
> 	https://git.linuxtv.org/mchehab/experimental.git/log/?h=tvp5150-2

Did you drop the DT of_graph support patch? It was there on your first
tvp5150 branch. 

> 
> I'll keep doing more tests here.
> 
> > 
> > > +}
> > > +
> > >  static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
> > >  {
> > >  	struct tvp5150 *decoder = to_tvp5150(sd);
> > >  
> > > -	*std_id = decoder->lock ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
> > > +	*std_id = query_lock(sd) ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
> > >  
> > >  	return 0;
> > >  }
> > > @@ -1247,7 +1260,7 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
> > >  		tvp5150_enable(sd);
> > >  
> > >  		/* Enable outputs if decoder is locked */
> > > -		val = decoder->lock ? decoder->oe : 0;
> > > +		val = query_lock(sd) ? decoder->oe : 0;
> > >  		int_val = TVP5150_INT_A_LOCK;
> > >  		v4l2_subdev_notify_event(&decoder->sd, &tvp5150_ev_fmt);
> > >  	}
> > > @@ -1816,8 +1829,6 @@ static int tvp5150_probe(struct i2c_client *c,
> > >  						IRQF_ONESHOT, "tvp5150", core);
> > >  		if (res)
> > >  			return res;
> > > -	} else {
> > > -		core->lock = true;
> > >  	}
> > >  
> > >  	res = v4l2_async_register_subdev(sd);
> > > 
> > > 
> > >   
> 
> [PATCH] media: tvp5150: implement decoder lock when irq is not used
> 
> When irq is used, the lock is set via IRQ code. When it isn't,
> the driver just assumes it is always locked. Instead, read the
> lock status from the status register.
> 
> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
> 
> diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> index efc441df7cac..e74af68be2eb 100644
> --- a/drivers/media/i2c/tvp5150.c
> +++ b/drivers/media/i2c/tvp5150.c
> @@ -810,11 +810,25 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
>  	}
>  }
>  
> +static int query_lock(struct v4l2_subdev *sd)
> +{
> +	struct tvp5150 *decoder = to_tvp5150(sd);
> +	int status;
> +
> +	if (decoder->irq)
> +		return decoder->lock;
> +
> +	regmap_read(decoder->regmap, TVP5150_STATUS_REG_1, &status);
> +
> +	/* For standard detection, we need the 3 locks */
> +	return (status & 0x0e) == 0x0e;
> +}
> +
>  static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
>  {
>  	struct tvp5150 *decoder = to_tvp5150(sd);

We should drop the decoder var here and not in the cleanup patch "media:
tvp5150: get rid of some warnings". There are always two version of the
patch that remove the 'static' warning [2,3].

[2] https://www.spinics.net/lists/linux-media/msg138318.html
[3] https://www.spinics.net/lists/linux-media/msg138363.html

Regards,
Marco
>  
> -	*std_id = decoder->lock ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
> +	*std_id = query_lock(sd) ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
>  
>  	return 0;
>  }
> @@ -1208,7 +1222,10 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
>  		tvp5150_enable(sd);
>  
>  		/* Enable outputs if decoder is locked */
> -		val = decoder->lock ? decoder->oe : 0;
> +		if (decoder->irq)
> +			val = decoder->lock ? decoder->oe : 0;
> +		else
> +			val = decoder->oe;
>  		int_val = TVP5150_INT_A_LOCK;
>  		v4l2_subdev_notify_event(&decoder->sd, &tvp5150_ev_fmt);
>  	}
> @@ -1777,8 +1794,6 @@ static int tvp5150_probe(struct i2c_client *c,
>  						IRQF_ONESHOT, "tvp5150", core);
>  		if (res)
>  			return res;
> -	} else {
> -		core->lock = true;
>  	}
>  
>  	res = v4l2_async_register_subdev(sd);
> 
> 
> 
> Thanks,
> Mauro
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

* Re: [PATCH 16/22] [media] tvp5150: add querystd
  2018-08-02  8:01             ` Marco Felsch
@ 2018-08-02  9:49               ` Mauro Carvalho Chehab
  2018-08-02 10:16                 ` Marco Felsch
  2018-08-02 10:54                 ` Ian Arkver
  0 siblings, 2 replies; 70+ messages in thread
From: Mauro Carvalho Chehab @ 2018-08-02  9:49 UTC (permalink / raw)
  To: Marco Felsch
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Em Thu, 2 Aug 2018 10:01:01 +0200
Marco Felsch <m.felsch@pengutronix.de> escreveu:

> Hi Mauro,
> 
> On 18-08-01 12:50, Mauro Carvalho Chehab wrote:
> > Em Wed, 1 Aug 2018 16:49:26 +0200
> > Marco Felsch <m.felsch@pengutronix.de> escreveu:
> >   
> > > Hi Mauro,
> > > 
> > > On 18-08-01 11:22, Mauro Carvalho Chehab wrote:  
> > > > Em Wed, 1 Aug 2018 15:21:25 +0200
> > > > Marco Felsch <m.felsch@pengutronix.de> escreveu:
> > > >     
> > > > > Hi Mauro,
> > > > > 
> > > > > On 18-07-30 15:09, Mauro Carvalho Chehab wrote:    
> > > > > > Em Thu, 28 Jun 2018 18:20:48 +0200
> > > > > > Marco Felsch <m.felsch@pengutronix.de> escreveu:
> > > > > >       
> > > > > > > From: Philipp Zabel <p.zabel@pengutronix.de>
> > > > > > > 
> > > > > > > Add the querystd video_op and make it return V4L2_STD_UNKNOWN while the
> > > > > > > TVP5150 is not locked to a signal.
> > > > > > > 
> > > > > > > Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> > > > > > > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > > > > > > ---
> > > > > > >  drivers/media/i2c/tvp5150.c | 10 ++++++++++
> > > > > > >  1 file changed, 10 insertions(+)
> > > > > > > 
> > > > > > > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > > > > > > index 99d887936ea0..1990aaa17749 100644
> > > > > > > --- a/drivers/media/i2c/tvp5150.c
> > > > > > > +++ b/drivers/media/i2c/tvp5150.c
> > > > > > > @@ -796,6 +796,15 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
> > > > > > >  	}
> > > > > > >  }
> > > > > > >  
> > > > > > > +static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
> > > > > > > +{
> > > > > > > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > > > > > > +
> > > > > > > +	*std_id = decoder->lock ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;      
> > > > > > 
> > > > > > This patch requires rework. What happens when a device doesn't have
> > > > > > IRQ enabled? Perhaps it should, instead, read some register in order
> > > > > > to check for the locking status, as this would work on both cases.      
> > > > > 
> > > > > If IRQ isn't enabled, decoder->lock is set to always true during
> > > > > probe(). So this case should be fine.    
> > > > 
> > > > Not sure if tvp5150_read_std() will do the right thing. If it does,
> > > > the above could simply be:
> > > > 	std_id = tvp5150_read_std(sd);
> > > > 
> > > > But, as there are 3 variants of this chipset, it sounds safer to check
> > > > if the device is locked before calling tvp5150_read_std().    
> > > 
> > > Yes, I'm with you.
> > >   
> > > > 
> > > > IMHO, the best would be to have a patch like the one below.
> > > > 
> > > > Regards,
> > > > Mauro
> > > > 
> > > > [PATCH] media: tvp5150: implement decoder lock when irq is not used
> > > > 
> > > > When irq is used, the lock is set via IRQ code. When it isn't,
> > > > the driver just assumes it is always locked. Instead, read the
> > > > lock status from the status register.    
> > > 
> > > Yes, that is a better solution.
> > >   
> > > > 
> > > > Compile-tested only.
> > > > 
> > > > Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
> > > > 
> > > > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > > > index 75e5ffc6573d..e07020d4053d 100644
> > > > --- a/drivers/media/i2c/tvp5150.c
> > > > +++ b/drivers/media/i2c/tvp5150.c
> > > > @@ -811,11 +811,24 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
> > > >  	}
> > > >  }
> > > >  
> > > > +static int query_lock(struct v4l2_subdev *sd)
> > > > +{
> > > > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > > > +	int status;
> > > > +
> > > > +	if (decoder->irq)
> > > > +		return decoder->lock;
> > > > +
> > > > +	regmap_read(map, TVP5150_INT_STATUS_REG_A, &status);
> > > > +
> > > > +	return (status & 0x06) == 0x06;    
> > > 
> > > Typo? It should be 0x80, as described in the datasheet (SLES209E) or
> > > just use the TVP5150_INT_A_LOCK_STATUS define. This avoid datasheet
> > > cross check during reading.  
> > 
> > Yes, it is a typo, but at the other line... I meant to use the register
> > 0x88, e. g.:
> > 
> > 	regmap_read(decoder->regmap, TVP5150_STATUS_REG_1, &status);  
> 
> During my development I tried this status register too, as descibed on
> the community website [1]. But that wasn't that good, because the look
> will be lost very often. Bit7 of Interrupt Status Reg A (0xc0) is more
> robust for that kind of work, since it covers the whole signal.
> 
> [1] http://e2e.ti.com/support/data_converters/videoconverters/f/918/p/ \
> 	617120/2273276?keyMatch=tvp5150%20lock%20lost&tisearch=Search-EN-Support

Bit 4 is not reliable for such purpose, but, on my tests, when video is
present, bits 1, 2 and 3 are present when there is a proper signal. 
Basically, all the times I issued a std query ioctl, it reads 0x1e.

When the signal is removed, I get a 0x00.

Here, reading int status reg A returns 0x40 with or without signal,
probably because IRQ is not enabled. See, for USB devices like em28xx,
we don't have direct access to tvp5051 IRQ line. If the IRQ lines is
somewhat wired to em28xx, it could be possible that the em28xx would
handle it, but we would need to know a way to setup em28xx to handle irqs.
I don't know if this is possible, and, if so, how em28xx would be
notifying such interrupts via some URB packet.

> > 
> > I ran some tests here: the int status reg is not updated.
> > 
> > Also, after thinking a little bit, I opted to not use the query_lock()
> > at s_stream. It makes no sense there without adding a status polling
> > logic. I also opted to remove initializing decoder->lock to true, as
> > this is very counter-intuitive. Instead, I'm adding a test at s_stream
> > if decoder->irq is set. This makes easier to understand the code.  
> 
> Yes, you're right.
> 
> > Btw, on my tests here, I noticed a problem with S-Video... at least with
> > AV-350 grabber, composite is only working when S-Video is connected.  
> 
> Unfortunately I have only a custom board with one composite connection.
> 
> > 
> > This bug also happens before your patchset, so this is not a regression
> > caused by your patches.
> > 
> > Anyway, patch enclosed. I added it together with my patch series at:
> > 
> > 	https://git.linuxtv.org/mchehab/experimental.git/log/?h=tvp5150-2  
> 
> Did you drop the DT of_graph support patch? It was there on your first
> tvp5150 branch. 

Yes. As discussed, I'm waiting for a replacement patch from you. So,
after testing, I removed it, in order to make simpler to add your
replacement patch.

IMO, the proper mapping is one input linked to (up to) 3 connectors.

Please notice that I'm also waiting for a replacement for patch 06/22
(and a rebase for the not-yet-applied patches). 

Feel free to send those patches against 
	https://git.linuxtv.org/mchehab/experimental.git/log/?h=tvp5150-3

(no changes on tvp5051 patches here - it is just rebased on the top of
 pad-fix-3 branch)

> 
> > 
> > I'll keep doing more tests here.
> >   
> > >   
> > > > +}
> > > > +
> > > >  static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
> > > >  {
> > > >  	struct tvp5150 *decoder = to_tvp5150(sd);
> > > >  
> > > > -	*std_id = decoder->lock ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
> > > > +	*std_id = query_lock(sd) ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
> > > >  
> > > >  	return 0;
> > > >  }
> > > > @@ -1247,7 +1260,7 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
> > > >  		tvp5150_enable(sd);
> > > >  
> > > >  		/* Enable outputs if decoder is locked */
> > > > -		val = decoder->lock ? decoder->oe : 0;
> > > > +		val = query_lock(sd) ? decoder->oe : 0;
> > > >  		int_val = TVP5150_INT_A_LOCK;
> > > >  		v4l2_subdev_notify_event(&decoder->sd, &tvp5150_ev_fmt);
> > > >  	}
> > > > @@ -1816,8 +1829,6 @@ static int tvp5150_probe(struct i2c_client *c,
> > > >  						IRQF_ONESHOT, "tvp5150", core);
> > > >  		if (res)
> > > >  			return res;
> > > > -	} else {
> > > > -		core->lock = true;
> > > >  	}
> > > >  
> > > >  	res = v4l2_async_register_subdev(sd);
> > > > 
> > > > 
> > > >     
> > 
> > [PATCH] media: tvp5150: implement decoder lock when irq is not used
> > 
> > When irq is used, the lock is set via IRQ code. When it isn't,
> > the driver just assumes it is always locked. Instead, read the
> > lock status from the status register.
> > 
> > Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
> > 
> > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > index efc441df7cac..e74af68be2eb 100644
> > --- a/drivers/media/i2c/tvp5150.c
> > +++ b/drivers/media/i2c/tvp5150.c
> > @@ -810,11 +810,25 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
> >  	}
> >  }
> >  
> > +static int query_lock(struct v4l2_subdev *sd)
> > +{
> > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > +	int status;
> > +
> > +	if (decoder->irq)
> > +		return decoder->lock;
> > +
> > +	regmap_read(decoder->regmap, TVP5150_STATUS_REG_1, &status);
> > +
> > +	/* For standard detection, we need the 3 locks */
> > +	return (status & 0x0e) == 0x0e;
> > +}
> > +
> >  static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
> >  {
> >  	struct tvp5150 *decoder = to_tvp5150(sd);  
> 
> We should drop the decoder var here and not in the cleanup patch "media:
> tvp5150: get rid of some warnings". 

I don't like the idea of merging stuff with different things together.
One patch per logical change.

> There are always two version of the
> patch that remove the 'static' warning [2,3].
> 
> [2] https://www.spinics.net/lists/linux-media/msg138318.html
> [3] https://www.spinics.net/lists/linux-media/msg138363.html

I'll likely just fold the static change with the patch that added
the warning when applying mainstream, adding a notice there at the
patch's description.

> 
> Regards,
> Marco
> >  
> > -	*std_id = decoder->lock ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
> > +	*std_id = query_lock(sd) ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
> >  
> >  	return 0;
> >  }
> > @@ -1208,7 +1222,10 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
> >  		tvp5150_enable(sd);
> >  
> >  		/* Enable outputs if decoder is locked */
> > -		val = decoder->lock ? decoder->oe : 0;
> > +		if (decoder->irq)
> > +			val = decoder->lock ? decoder->oe : 0;
> > +		else
> > +			val = decoder->oe;
> >  		int_val = TVP5150_INT_A_LOCK;
> >  		v4l2_subdev_notify_event(&decoder->sd, &tvp5150_ev_fmt);
> >  	}
> > @@ -1777,8 +1794,6 @@ static int tvp5150_probe(struct i2c_client *c,
> >  						IRQF_ONESHOT, "tvp5150", core);
> >  		if (res)
> >  			return res;
> > -	} else {
> > -		core->lock = true;
> >  	}
> >  
> >  	res = v4l2_async_register_subdev(sd);
> > 
> > 
> > 
> > Thanks,
> > Mauro
> >   
> 



Thanks,
Mauro

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

* Re: [PATCH 16/22] [media] tvp5150: add querystd
  2018-08-02  9:49               ` Mauro Carvalho Chehab
@ 2018-08-02 10:16                 ` Marco Felsch
  2018-08-02 14:38                   ` Mauro Carvalho Chehab
  2018-08-02 10:54                 ` Ian Arkver
  1 sibling, 1 reply; 70+ messages in thread
From: Marco Felsch @ 2018-08-02 10:16 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Hi Mauro,

On 18-08-02 06:49, Mauro Carvalho Chehab wrote:
> Em Thu, 2 Aug 2018 10:01:01 +0200
> Marco Felsch <m.felsch@pengutronix.de> escreveu:
> 
> > Hi Mauro,
> > 
> > On 18-08-01 12:50, Mauro Carvalho Chehab wrote:
> > > Em Wed, 1 Aug 2018 16:49:26 +0200
> > > Marco Felsch <m.felsch@pengutronix.de> escreveu:
> > >   
> > > > Hi Mauro,
> > > > 
> > > > On 18-08-01 11:22, Mauro Carvalho Chehab wrote:  
> > > > > Em Wed, 1 Aug 2018 15:21:25 +0200
> > > > > Marco Felsch <m.felsch@pengutronix.de> escreveu:
> > > > >     
> > > > > > Hi Mauro,
> > > > > > 
> > > > > > On 18-07-30 15:09, Mauro Carvalho Chehab wrote:    
> > > > > > > Em Thu, 28 Jun 2018 18:20:48 +0200
> > > > > > > Marco Felsch <m.felsch@pengutronix.de> escreveu:
> > > > > > >       
> > > > > > > > From: Philipp Zabel <p.zabel@pengutronix.de>
> > > > > > > > 
> > > > > > > > Add the querystd video_op and make it return V4L2_STD_UNKNOWN while the
> > > > > > > > TVP5150 is not locked to a signal.
> > > > > > > > 
> > > > > > > > Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> > > > > > > > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > > > > > > > ---
> > > > > > > >  drivers/media/i2c/tvp5150.c | 10 ++++++++++
> > > > > > > >  1 file changed, 10 insertions(+)
> > > > > > > > 
> > > > > > > > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > > > > > > > index 99d887936ea0..1990aaa17749 100644
> > > > > > > > --- a/drivers/media/i2c/tvp5150.c
> > > > > > > > +++ b/drivers/media/i2c/tvp5150.c
> > > > > > > > @@ -796,6 +796,15 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
> > > > > > > >  	}
> > > > > > > >  }
> > > > > > > >  
> > > > > > > > +static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
> > > > > > > > +{
> > > > > > > > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > > > > > > > +
> > > > > > > > +	*std_id = decoder->lock ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;      
> > > > > > > 
> > > > > > > This patch requires rework. What happens when a device doesn't have
> > > > > > > IRQ enabled? Perhaps it should, instead, read some register in order
> > > > > > > to check for the locking status, as this would work on both cases.      
> > > > > > 
> > > > > > If IRQ isn't enabled, decoder->lock is set to always true during
> > > > > > probe(). So this case should be fine.    
> > > > > 
> > > > > Not sure if tvp5150_read_std() will do the right thing. If it does,
> > > > > the above could simply be:
> > > > > 	std_id = tvp5150_read_std(sd);
> > > > > 
> > > > > But, as there are 3 variants of this chipset, it sounds safer to check
> > > > > if the device is locked before calling tvp5150_read_std().    
> > > > 
> > > > Yes, I'm with you.
> > > >   
> > > > > 
> > > > > IMHO, the best would be to have a patch like the one below.
> > > > > 
> > > > > Regards,
> > > > > Mauro
> > > > > 
> > > > > [PATCH] media: tvp5150: implement decoder lock when irq is not used
> > > > > 
> > > > > When irq is used, the lock is set via IRQ code. When it isn't,
> > > > > the driver just assumes it is always locked. Instead, read the
> > > > > lock status from the status register.    
> > > > 
> > > > Yes, that is a better solution.
> > > >   
> > > > > 
> > > > > Compile-tested only.
> > > > > 
> > > > > Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
> > > > > 
> > > > > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > > > > index 75e5ffc6573d..e07020d4053d 100644
> > > > > --- a/drivers/media/i2c/tvp5150.c
> > > > > +++ b/drivers/media/i2c/tvp5150.c
> > > > > @@ -811,11 +811,24 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
> > > > >  	}
> > > > >  }
> > > > >  
> > > > > +static int query_lock(struct v4l2_subdev *sd)
> > > > > +{
> > > > > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > > > > +	int status;
> > > > > +
> > > > > +	if (decoder->irq)
> > > > > +		return decoder->lock;
> > > > > +
> > > > > +	regmap_read(map, TVP5150_INT_STATUS_REG_A, &status);
> > > > > +
> > > > > +	return (status & 0x06) == 0x06;    
> > > > 
> > > > Typo? It should be 0x80, as described in the datasheet (SLES209E) or
> > > > just use the TVP5150_INT_A_LOCK_STATUS define. This avoid datasheet
> > > > cross check during reading.  
> > > 
> > > Yes, it is a typo, but at the other line... I meant to use the register
> > > 0x88, e. g.:
> > > 
> > > 	regmap_read(decoder->regmap, TVP5150_STATUS_REG_1, &status);  
> > 
> > During my development I tried this status register too, as descibed on
> > the community website [1]. But that wasn't that good, because the look
> > will be lost very often. Bit7 of Interrupt Status Reg A (0xc0) is more
> > robust for that kind of work, since it covers the whole signal.
> > 
> > [1] http://e2e.ti.com/support/data_converters/videoconverters/f/918/p/ \
> > 	617120/2273276?keyMatch=tvp5150%20lock%20lost&tisearch=Search-EN-Support
> 
> Bit 4 is not reliable for such purpose, but, on my tests, when video is
> present, bits 1, 2 and 3 are present when there is a proper signal. 
> Basically, all the times I issued a std query ioctl, it reads 0x1e.
> 
> When the signal is removed, I get a 0x00.

Ah, okay.

> 
> Here, reading int status reg A returns 0x40 with or without signal,
> probably because IRQ is not enabled. See, for USB devices like em28xx,
> we don't have direct access to tvp5051 IRQ line. If the IRQ lines is
> somewhat wired to em28xx, it could be possible that the em28xx would
> handle it, but we would need to know a way to setup em28xx to handle irqs.
> I don't know if this is possible, and, if so, how em28xx would be
> notifying such interrupts via some URB packet.
> 
> > > 
> > > I ran some tests here: the int status reg is not updated.
> > > 
> > > Also, after thinking a little bit, I opted to not use the query_lock()
> > > at s_stream. It makes no sense there without adding a status polling
> > > logic. I also opted to remove initializing decoder->lock to true, as
> > > this is very counter-intuitive. Instead, I'm adding a test at s_stream
> > > if decoder->irq is set. This makes easier to understand the code.  
> > 
> > Yes, you're right.
> > 
> > > Btw, on my tests here, I noticed a problem with S-Video... at least with
> > > AV-350 grabber, composite is only working when S-Video is connected.  
> > 
> > Unfortunately I have only a custom board with one composite connection.
> > 
> > > 
> > > This bug also happens before your patchset, so this is not a regression
> > > caused by your patches.
> > > 
> > > Anyway, patch enclosed. I added it together with my patch series at:
> > > 
> > > 	https://git.linuxtv.org/mchehab/experimental.git/log/?h=tvp5150-2  
> > 
> > Did you drop the DT of_graph support patch? It was there on your first
> > tvp5150 branch. 
> 
> Yes. As discussed, I'm waiting for a replacement patch from you. So,
> after testing, I removed it, in order to make simpler to add your
> replacement patch.
> 
> IMO, the proper mapping is one input linked to (up to) 3 connectors.

I tought it would be okay to have more than 1 input pad since the
.sig_type pad property. So the tvp5150 media entity can be represented
like the physical tvp5150 chip.

I will fix it, if it isn't the right way.

> 
> Please notice that I'm also waiting for a replacement for patch 06/22
> (and a rebase for the not-yet-applied patches). 

Yes, I did the rework yesterday. Just wait for your changes. Instead of
using the v4l2_subdev_get_try_crop() helper, I copied the helper code to
the tvp driver.

> 
> Feel free to send those patches against 
> 	https://git.linuxtv.org/mchehab/experimental.git/log/?h=tvp5150-3
> 
> (no changes on tvp5051 patches here - it is just rebased on the top of
>  pad-fix-3 branch)
> 
> > 
> > > 
> > > I'll keep doing more tests here.
> > >   
> > > >   
> > > > > +}
> > > > > +
> > > > >  static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
> > > > >  {
> > > > >  	struct tvp5150 *decoder = to_tvp5150(sd);
> > > > >  
> > > > > -	*std_id = decoder->lock ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
> > > > > +	*std_id = query_lock(sd) ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
> > > > >  
> > > > >  	return 0;
> > > > >  }
> > > > > @@ -1247,7 +1260,7 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
> > > > >  		tvp5150_enable(sd);
> > > > >  
> > > > >  		/* Enable outputs if decoder is locked */
> > > > > -		val = decoder->lock ? decoder->oe : 0;
> > > > > +		val = query_lock(sd) ? decoder->oe : 0;
> > > > >  		int_val = TVP5150_INT_A_LOCK;
> > > > >  		v4l2_subdev_notify_event(&decoder->sd, &tvp5150_ev_fmt);
> > > > >  	}
> > > > > @@ -1816,8 +1829,6 @@ static int tvp5150_probe(struct i2c_client *c,
> > > > >  						IRQF_ONESHOT, "tvp5150", core);
> > > > >  		if (res)
> > > > >  			return res;
> > > > > -	} else {
> > > > > -		core->lock = true;
> > > > >  	}
> > > > >  
> > > > >  	res = v4l2_async_register_subdev(sd);
> > > > > 
> > > > > 
> > > > >     
> > > 
> > > [PATCH] media: tvp5150: implement decoder lock when irq is not used
> > > 
> > > When irq is used, the lock is set via IRQ code. When it isn't,
> > > the driver just assumes it is always locked. Instead, read the
> > > lock status from the status register.
> > > 
> > > Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
> > > 
> > > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > > index efc441df7cac..e74af68be2eb 100644
> > > --- a/drivers/media/i2c/tvp5150.c
> > > +++ b/drivers/media/i2c/tvp5150.c
> > > @@ -810,11 +810,25 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
> > >  	}
> > >  }
> > >  
> > > +static int query_lock(struct v4l2_subdev *sd)
> > > +{
> > > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > > +	int status;
> > > +
> > > +	if (decoder->irq)
> > > +		return decoder->lock;
> > > +
> > > +	regmap_read(decoder->regmap, TVP5150_STATUS_REG_1, &status);
> > > +
> > > +	/* For standard detection, we need the 3 locks */
> > > +	return (status & 0x0e) == 0x0e;
> > > +}
> > > +
> > >  static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
> > >  {
> > >  	struct tvp5150 *decoder = to_tvp5150(sd);  
> > 
> > We should drop the decoder var here and not in the cleanup patch "media:
> > tvp5150: get rid of some warnings". 
> 
> I don't like the idea of merging stuff with different things together.
> One patch per logical change.
> 
> > There are always two version of the
> > patch that remove the 'static' warning [2,3].
> > 
> > [2] https://www.spinics.net/lists/linux-media/msg138318.html
> > [3] https://www.spinics.net/lists/linux-media/msg138363.html
> 
> I'll likely just fold the static change with the patch that added
> the warning when applying mainstream, adding a notice there at the
> patch's description.
> 
> > 
> > Regards,
> > Marco
> > >  
> > > -	*std_id = decoder->lock ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
> > > +	*std_id = query_lock(sd) ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
> > >  
> > >  	return 0;
> > >  }
> > > @@ -1208,7 +1222,10 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
> > >  		tvp5150_enable(sd);
> > >  
> > >  		/* Enable outputs if decoder is locked */
> > > -		val = decoder->lock ? decoder->oe : 0;
> > > +		if (decoder->irq)
> > > +			val = decoder->lock ? decoder->oe : 0;
> > > +		else
> > > +			val = decoder->oe;
> > >  		int_val = TVP5150_INT_A_LOCK;
> > >  		v4l2_subdev_notify_event(&decoder->sd, &tvp5150_ev_fmt);
> > >  	}
> > > @@ -1777,8 +1794,6 @@ static int tvp5150_probe(struct i2c_client *c,
> > >  						IRQF_ONESHOT, "tvp5150", core);
> > >  		if (res)
> > >  			return res;
> > > -	} else {
> > > -		core->lock = true;
> > >  	}
> > >  
> > >  	res = v4l2_async_register_subdev(sd);
> > > 
> > > 
> > > 
> > > Thanks,
> > > Mauro
> > >   
> > 
> 
> 
> 
> Thanks,
> Mauro
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

* Re: [PATCH 16/22] [media] tvp5150: add querystd
  2018-08-02  9:49               ` Mauro Carvalho Chehab
  2018-08-02 10:16                 ` Marco Felsch
@ 2018-08-02 10:54                 ` Ian Arkver
  2018-08-02 11:58                   ` Marco Felsch
  1 sibling, 1 reply; 70+ messages in thread
From: Ian Arkver @ 2018-08-02 10:54 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Marco Felsch
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

On 02/08/18 10:49, Mauro Carvalho Chehab wrote:
> Em Thu, 2 Aug 2018 10:01:01 +0200
> Marco Felsch <m.felsch@pengutronix.de> escreveu:
> 
>> Hi Mauro,
>>
>> On 18-08-01 12:50, Mauro Carvalho Chehab wrote:
>>> Em Wed, 1 Aug 2018 16:49:26 +0200
>>> Marco Felsch <m.felsch@pengutronix.de> escreveu:
>>>    
>>>> Hi Mauro,
>>>>
>>>> On 18-08-01 11:22, Mauro Carvalho Chehab wrote:
>>>>> Em Wed, 1 Aug 2018 15:21:25 +0200
>>>>> Marco Felsch <m.felsch@pengutronix.de> escreveu:
>>>>>      
>>>>>> Hi Mauro,
>>>>>>
>>>>>> On 18-07-30 15:09, Mauro Carvalho Chehab wrote:
>>>>>>> Em Thu, 28 Jun 2018 18:20:48 +0200
>>>>>>> Marco Felsch <m.felsch@pengutronix.de> escreveu:
>>>>>>>        
>>>>>>>> From: Philipp Zabel <p.zabel@pengutronix.de>
>>>>>>>>
>>>>>>>> Add the querystd video_op and make it return V4L2_STD_UNKNOWN while the
>>>>>>>> TVP5150 is not locked to a signal.
>>>>>>>>
>>>>>>>> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
>>>>>>>> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
>>>>>>>> ---
>>>>>>>>   drivers/media/i2c/tvp5150.c | 10 ++++++++++
>>>>>>>>   1 file changed, 10 insertions(+)
>>>>>>>>
>>>>>>>> diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
>>>>>>>> index 99d887936ea0..1990aaa17749 100644
>>>>>>>> --- a/drivers/media/i2c/tvp5150.c
>>>>>>>> +++ b/drivers/media/i2c/tvp5150.c
>>>>>>>> @@ -796,6 +796,15 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
>>>>>>>>   	}
>>>>>>>>   }
>>>>>>>>   
>>>>>>>> +static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
>>>>>>>> +{
>>>>>>>> +	struct tvp5150 *decoder = to_tvp5150(sd);
>>>>>>>> +
>>>>>>>> +	*std_id = decoder->lock ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
>>>>>>>
>>>>>>> This patch requires rework. What happens when a device doesn't have
>>>>>>> IRQ enabled? Perhaps it should, instead, read some register in order
>>>>>>> to check for the locking status, as this would work on both cases.
>>>>>>
>>>>>> If IRQ isn't enabled, decoder->lock is set to always true during
>>>>>> probe(). So this case should be fine.
>>>>>
>>>>> Not sure if tvp5150_read_std() will do the right thing. If it does,
>>>>> the above could simply be:
>>>>> 	std_id = tvp5150_read_std(sd);
>>>>>
>>>>> But, as there are 3 variants of this chipset, it sounds safer to check
>>>>> if the device is locked before calling tvp5150_read_std().
>>>>
>>>> Yes, I'm with you.
>>>>    
>>>>>
>>>>> IMHO, the best would be to have a patch like the one below.
>>>>>
>>>>> Regards,
>>>>> Mauro
>>>>>
>>>>> [PATCH] media: tvp5150: implement decoder lock when irq is not used
>>>>>
>>>>> When irq is used, the lock is set via IRQ code. When it isn't,
>>>>> the driver just assumes it is always locked. Instead, read the
>>>>> lock status from the status register.
>>>>
>>>> Yes, that is a better solution.
>>>>    
>>>>>
>>>>> Compile-tested only.
>>>>>
>>>>> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
>>>>>
>>>>> diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
>>>>> index 75e5ffc6573d..e07020d4053d 100644
>>>>> --- a/drivers/media/i2c/tvp5150.c
>>>>> +++ b/drivers/media/i2c/tvp5150.c
>>>>> @@ -811,11 +811,24 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
>>>>>   	}
>>>>>   }
>>>>>   
>>>>> +static int query_lock(struct v4l2_subdev *sd)
>>>>> +{
>>>>> +	struct tvp5150 *decoder = to_tvp5150(sd);
>>>>> +	int status;
>>>>> +
>>>>> +	if (decoder->irq)
>>>>> +		return decoder->lock;
>>>>> +
>>>>> +	regmap_read(map, TVP5150_INT_STATUS_REG_A, &status);
>>>>> +
>>>>> +	return (status & 0x06) == 0x06;
>>>>
>>>> Typo? It should be 0x80, as described in the datasheet (SLES209E) or
>>>> just use the TVP5150_INT_A_LOCK_STATUS define. This avoid datasheet
>>>> cross check during reading.
>>>
>>> Yes, it is a typo, but at the other line... I meant to use the register
>>> 0x88, e. g.:
>>>
>>> 	regmap_read(decoder->regmap, TVP5150_STATUS_REG_1, &status);
>>
>> During my development I tried this status register too, as descibed on
>> the community website [1]. But that wasn't that good, because the look
>> will be lost very often. Bit7 of Interrupt Status Reg A (0xc0) is more
>> robust for that kind of work, since it covers the whole signal.
>>
>> [1] http://e2e.ti.com/support/data_converters/videoconverters/f/918/p/ \
>> 	617120/2273276?keyMatch=tvp5150%20lock%20lost&tisearch=Search-EN-Support
> 
> Bit 4 is not reliable for such purpose, but, on my tests, when video is
> present, bits 1, 2 and 3 are present when there is a proper signal.
> Basically, all the times I issued a std query ioctl, it reads 0x1e.
> 
> When the signal is removed, I get a 0x00.
> 
> Here, reading int status reg A returns 0x40 with or without signal,
> probably because IRQ is not enabled. See, for USB devices like em28xx,
> we don't have direct access to tvp5051 IRQ line. If the IRQ lines is
> somewhat wired to em28xx, it could be possible that the em28xx would
> handle it, but we would need to know a way to setup em28xx to handle irqs.
> I don't know if this is possible, and, if so, how em28xx would be
> notifying such interrupts via some URB packet.

The interrupt status register bits are latched and need a 1 written to 
clear them. Normally this would be done by the interrupt handler. Maybe 
this is why you're seeing the LOCK bit stuck?

Regards,
Ian

> 
>>>
>>> I ran some tests here: the int status reg is not updated.
>>>
>>> Also, after thinking a little bit, I opted to not use the query_lock()
>>> at s_stream. It makes no sense there without adding a status polling
>>> logic. I also opted to remove initializing decoder->lock to true, as
>>> this is very counter-intuitive. Instead, I'm adding a test at s_stream
>>> if decoder->irq is set. This makes easier to understand the code.
>>
>> Yes, you're right.
>>
>>> Btw, on my tests here, I noticed a problem with S-Video... at least with
>>> AV-350 grabber, composite is only working when S-Video is connected.
>>
>> Unfortunately I have only a custom board with one composite connection.
>>
>>>
>>> This bug also happens before your patchset, so this is not a regression
>>> caused by your patches.
>>>
>>> Anyway, patch enclosed. I added it together with my patch series at:
>>>
>>> 	https://git.linuxtv.org/mchehab/experimental.git/log/?h=tvp5150-2
>>
>> Did you drop the DT of_graph support patch? It was there on your first
>> tvp5150 branch.
> 
> Yes. As discussed, I'm waiting for a replacement patch from you. So,
> after testing, I removed it, in order to make simpler to add your
> replacement patch.
> 
> IMO, the proper mapping is one input linked to (up to) 3 connectors.
> 
> Please notice that I'm also waiting for a replacement for patch 06/22
> (and a rebase for the not-yet-applied patches).
> 
> Feel free to send those patches against
> 	https://git.linuxtv.org/mchehab/experimental.git/log/?h=tvp5150-3
> 
> (no changes on tvp5051 patches here - it is just rebased on the top of
>   pad-fix-3 branch)
> 
>>
>>>
>>> I'll keep doing more tests here.
>>>    
>>>>    
>>>>> +}
>>>>> +
>>>>>   static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
>>>>>   {
>>>>>   	struct tvp5150 *decoder = to_tvp5150(sd);
>>>>>   
>>>>> -	*std_id = decoder->lock ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
>>>>> +	*std_id = query_lock(sd) ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
>>>>>   
>>>>>   	return 0;
>>>>>   }
>>>>> @@ -1247,7 +1260,7 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
>>>>>   		tvp5150_enable(sd);
>>>>>   
>>>>>   		/* Enable outputs if decoder is locked */
>>>>> -		val = decoder->lock ? decoder->oe : 0;
>>>>> +		val = query_lock(sd) ? decoder->oe : 0;
>>>>>   		int_val = TVP5150_INT_A_LOCK;
>>>>>   		v4l2_subdev_notify_event(&decoder->sd, &tvp5150_ev_fmt);
>>>>>   	}
>>>>> @@ -1816,8 +1829,6 @@ static int tvp5150_probe(struct i2c_client *c,
>>>>>   						IRQF_ONESHOT, "tvp5150", core);
>>>>>   		if (res)
>>>>>   			return res;
>>>>> -	} else {
>>>>> -		core->lock = true;
>>>>>   	}
>>>>>   
>>>>>   	res = v4l2_async_register_subdev(sd);
>>>>>
>>>>>
>>>>>      
>>>
>>> [PATCH] media: tvp5150: implement decoder lock when irq is not used
>>>
>>> When irq is used, the lock is set via IRQ code. When it isn't,
>>> the driver just assumes it is always locked. Instead, read the
>>> lock status from the status register.
>>>
>>> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
>>>
>>> diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
>>> index efc441df7cac..e74af68be2eb 100644
>>> --- a/drivers/media/i2c/tvp5150.c
>>> +++ b/drivers/media/i2c/tvp5150.c
>>> @@ -810,11 +810,25 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
>>>   	}
>>>   }
>>>   
>>> +static int query_lock(struct v4l2_subdev *sd)
>>> +{
>>> +	struct tvp5150 *decoder = to_tvp5150(sd);
>>> +	int status;
>>> +
>>> +	if (decoder->irq)
>>> +		return decoder->lock;
>>> +
>>> +	regmap_read(decoder->regmap, TVP5150_STATUS_REG_1, &status);
>>> +
>>> +	/* For standard detection, we need the 3 locks */
>>> +	return (status & 0x0e) == 0x0e;
>>> +}
>>> +
>>>   static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
>>>   {
>>>   	struct tvp5150 *decoder = to_tvp5150(sd);
>>
>> We should drop the decoder var here and not in the cleanup patch "media:
>> tvp5150: get rid of some warnings".
> 
> I don't like the idea of merging stuff with different things together.
> One patch per logical change.
> 
>> There are always two version of the
>> patch that remove the 'static' warning [2,3].
>>
>> [2] https://www.spinics.net/lists/linux-media/msg138318.html
>> [3] https://www.spinics.net/lists/linux-media/msg138363.html
> 
> I'll likely just fold the static change with the patch that added
> the warning when applying mainstream, adding a notice there at the
> patch's description.
> 
>>
>> Regards,
>> Marco
>>>   
>>> -	*std_id = decoder->lock ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
>>> +	*std_id = query_lock(sd) ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
>>>   
>>>   	return 0;
>>>   }
>>> @@ -1208,7 +1222,10 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
>>>   		tvp5150_enable(sd);
>>>   
>>>   		/* Enable outputs if decoder is locked */
>>> -		val = decoder->lock ? decoder->oe : 0;
>>> +		if (decoder->irq)
>>> +			val = decoder->lock ? decoder->oe : 0;
>>> +		else
>>> +			val = decoder->oe;
>>>   		int_val = TVP5150_INT_A_LOCK;
>>>   		v4l2_subdev_notify_event(&decoder->sd, &tvp5150_ev_fmt);
>>>   	}
>>> @@ -1777,8 +1794,6 @@ static int tvp5150_probe(struct i2c_client *c,
>>>   						IRQF_ONESHOT, "tvp5150", core);
>>>   		if (res)
>>>   			return res;
>>> -	} else {
>>> -		core->lock = true;
>>>   	}
>>>   
>>>   	res = v4l2_async_register_subdev(sd);
>>>
>>>
>>>
>>> Thanks,
>>> Mauro
>>>    
>>
> 
> 
> 
> Thanks,
> Mauro
> 

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

* Re: [PATCH 16/22] [media] tvp5150: add querystd
  2018-08-02 10:54                 ` Ian Arkver
@ 2018-08-02 11:58                   ` Marco Felsch
  0 siblings, 0 replies; 70+ messages in thread
From: Marco Felsch @ 2018-08-02 11:58 UTC (permalink / raw)
  To: Ian Arkver
  Cc: Mauro Carvalho Chehab, mchehab, robh+dt, mark.rutland, p.zabel,
	afshin.nasser, javierm, sakari.ailus, laurent.pinchart,
	linux-media, devicetree, kernel

Hi Ian,

On 18-08-02 11:54, Ian Arkver wrote:
> On 02/08/18 10:49, Mauro Carvalho Chehab wrote:
> > Em Thu, 2 Aug 2018 10:01:01 +0200
> > Marco Felsch <m.felsch@pengutronix.de> escreveu:
> > 
> > > Hi Mauro,
> > > 
> > > On 18-08-01 12:50, Mauro Carvalho Chehab wrote:
> > > > Em Wed, 1 Aug 2018 16:49:26 +0200
> > > > Marco Felsch <m.felsch@pengutronix.de> escreveu:
> > > > > Hi Mauro,
> > > > > 
> > > > > On 18-08-01 11:22, Mauro Carvalho Chehab wrote:
> > > > > > Em Wed, 1 Aug 2018 15:21:25 +0200
> > > > > > Marco Felsch <m.felsch@pengutronix.de> escreveu:
> > > > > > > Hi Mauro,
> > > > > > > 
> > > > > > > On 18-07-30 15:09, Mauro Carvalho Chehab wrote:
> > > > > > > > Em Thu, 28 Jun 2018 18:20:48 +0200
> > > > > > > > Marco Felsch <m.felsch@pengutronix.de> escreveu:
> > > > > > > > > From: Philipp Zabel <p.zabel@pengutronix.de>
> > > > > > > > > 
> > > > > > > > > Add the querystd video_op and make it return V4L2_STD_UNKNOWN while the
> > > > > > > > > TVP5150 is not locked to a signal.
> > > > > > > > > 
> > > > > > > > > Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> > > > > > > > > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > > > > > > > > ---
> > > > > > > > >   drivers/media/i2c/tvp5150.c | 10 ++++++++++
> > > > > > > > >   1 file changed, 10 insertions(+)
> > > > > > > > > 
> > > > > > > > > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > > > > > > > > index 99d887936ea0..1990aaa17749 100644
> > > > > > > > > --- a/drivers/media/i2c/tvp5150.c
> > > > > > > > > +++ b/drivers/media/i2c/tvp5150.c
> > > > > > > > > @@ -796,6 +796,15 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
> > > > > > > > >   	}
> > > > > > > > >   }
> > > > > > > > > +static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
> > > > > > > > > +{
> > > > > > > > > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > > > > > > > > +
> > > > > > > > > +	*std_id = decoder->lock ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
> > > > > > > > 
> > > > > > > > This patch requires rework. What happens when a device doesn't have
> > > > > > > > IRQ enabled? Perhaps it should, instead, read some register in order
> > > > > > > > to check for the locking status, as this would work on both cases.
> > > > > > > 
> > > > > > > If IRQ isn't enabled, decoder->lock is set to always true during
> > > > > > > probe(). So this case should be fine.
> > > > > > 
> > > > > > Not sure if tvp5150_read_std() will do the right thing. If it does,
> > > > > > the above could simply be:
> > > > > > 	std_id = tvp5150_read_std(sd);
> > > > > > 
> > > > > > But, as there are 3 variants of this chipset, it sounds safer to check
> > > > > > if the device is locked before calling tvp5150_read_std().
> > > > > 
> > > > > Yes, I'm with you.
> > > > > > 
> > > > > > IMHO, the best would be to have a patch like the one below.
> > > > > > 
> > > > > > Regards,
> > > > > > Mauro
> > > > > > 
> > > > > > [PATCH] media: tvp5150: implement decoder lock when irq is not used
> > > > > > 
> > > > > > When irq is used, the lock is set via IRQ code. When it isn't,
> > > > > > the driver just assumes it is always locked. Instead, read the
> > > > > > lock status from the status register.
> > > > > 
> > > > > Yes, that is a better solution.
> > > > > > 
> > > > > > Compile-tested only.
> > > > > > 
> > > > > > Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
> > > > > > 
> > > > > > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > > > > > index 75e5ffc6573d..e07020d4053d 100644
> > > > > > --- a/drivers/media/i2c/tvp5150.c
> > > > > > +++ b/drivers/media/i2c/tvp5150.c
> > > > > > @@ -811,11 +811,24 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
> > > > > >   	}
> > > > > >   }
> > > > > > +static int query_lock(struct v4l2_subdev *sd)
> > > > > > +{
> > > > > > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > > > > > +	int status;
> > > > > > +
> > > > > > +	if (decoder->irq)
> > > > > > +		return decoder->lock;
> > > > > > +
> > > > > > +	regmap_read(map, TVP5150_INT_STATUS_REG_A, &status);
> > > > > > +
> > > > > > +	return (status & 0x06) == 0x06;
> > > > > 
> > > > > Typo? It should be 0x80, as described in the datasheet (SLES209E) or
> > > > > just use the TVP5150_INT_A_LOCK_STATUS define. This avoid datasheet
> > > > > cross check during reading.
> > > > 
> > > > Yes, it is a typo, but at the other line... I meant to use the register
> > > > 0x88, e. g.:
> > > > 
> > > > 	regmap_read(decoder->regmap, TVP5150_STATUS_REG_1, &status);
> > > 
> > > During my development I tried this status register too, as descibed on
> > > the community website [1]. But that wasn't that good, because the look
> > > will be lost very often. Bit7 of Interrupt Status Reg A (0xc0) is more
> > > robust for that kind of work, since it covers the whole signal.
> > > 
> > > [1] http://e2e.ti.com/support/data_converters/videoconverters/f/918/p/ \
> > > 	617120/2273276?keyMatch=tvp5150%20lock%20lost&tisearch=Search-EN-Support
> > 
> > Bit 4 is not reliable for such purpose, but, on my tests, when video is
> > present, bits 1, 2 and 3 are present when there is a proper signal.
> > Basically, all the times I issued a std query ioctl, it reads 0x1e.
> > 
> > When the signal is removed, I get a 0x00.
> > 
> > Here, reading int status reg A returns 0x40 with or without signal,
> > probably because IRQ is not enabled. See, for USB devices like em28xx,
> > we don't have direct access to tvp5051 IRQ line. If the IRQ lines is
> > somewhat wired to em28xx, it could be possible that the em28xx would
> > handle it, but we would need to know a way to setup em28xx to handle irqs.
> > I don't know if this is possible, and, if so, how em28xx would be
> > notifying such interrupts via some URB packet.
> 
> The interrupt status register bits are latched and need a 1 written to clear
> them. Normally this would be done by the interrupt handler. Maybe this is
> why you're seeing the LOCK bit stuck?

Yes, you're right. I forgot that behaviour but anyway, 0x40 just
indicates there was a lock change. Using that bit for a lock check
requires the status register #1 to check the dedicated locks.

Regards,
Marco

> 
> Regards,
> Ian
> 
> > 
> > > > 
> > > > I ran some tests here: the int status reg is not updated.
> > > > 
> > > > Also, after thinking a little bit, I opted to not use the query_lock()
> > > > at s_stream. It makes no sense there without adding a status polling
> > > > logic. I also opted to remove initializing decoder->lock to true, as
> > > > this is very counter-intuitive. Instead, I'm adding a test at s_stream
> > > > if decoder->irq is set. This makes easier to understand the code.
> > > 
> > > Yes, you're right.
> > > 
> > > > Btw, on my tests here, I noticed a problem with S-Video... at least with
> > > > AV-350 grabber, composite is only working when S-Video is connected.
> > > 
> > > Unfortunately I have only a custom board with one composite connection.
> > > 
> > > > 
> > > > This bug also happens before your patchset, so this is not a regression
> > > > caused by your patches.
> > > > 
> > > > Anyway, patch enclosed. I added it together with my patch series at:
> > > > 
> > > > 	https://git.linuxtv.org/mchehab/experimental.git/log/?h=tvp5150-2
> > > 
> > > Did you drop the DT of_graph support patch? It was there on your first
> > > tvp5150 branch.
> > 
> > Yes. As discussed, I'm waiting for a replacement patch from you. So,
> > after testing, I removed it, in order to make simpler to add your
> > replacement patch.
> > 
> > IMO, the proper mapping is one input linked to (up to) 3 connectors.
> > 
> > Please notice that I'm also waiting for a replacement for patch 06/22
> > (and a rebase for the not-yet-applied patches).
> > 
> > Feel free to send those patches against
> > 	https://git.linuxtv.org/mchehab/experimental.git/log/?h=tvp5150-3
> > 
> > (no changes on tvp5051 patches here - it is just rebased on the top of
> >   pad-fix-3 branch)
> > 
> > > 
> > > > 
> > > > I'll keep doing more tests here.
> > > > > > +}
> > > > > > +
> > > > > >   static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
> > > > > >   {
> > > > > >   	struct tvp5150 *decoder = to_tvp5150(sd);
> > > > > > -	*std_id = decoder->lock ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
> > > > > > +	*std_id = query_lock(sd) ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
> > > > > >   	return 0;
> > > > > >   }
> > > > > > @@ -1247,7 +1260,7 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
> > > > > >   		tvp5150_enable(sd);
> > > > > >   		/* Enable outputs if decoder is locked */
> > > > > > -		val = decoder->lock ? decoder->oe : 0;
> > > > > > +		val = query_lock(sd) ? decoder->oe : 0;
> > > > > >   		int_val = TVP5150_INT_A_LOCK;
> > > > > >   		v4l2_subdev_notify_event(&decoder->sd, &tvp5150_ev_fmt);
> > > > > >   	}
> > > > > > @@ -1816,8 +1829,6 @@ static int tvp5150_probe(struct i2c_client *c,
> > > > > >   						IRQF_ONESHOT, "tvp5150", core);
> > > > > >   		if (res)
> > > > > >   			return res;
> > > > > > -	} else {
> > > > > > -		core->lock = true;
> > > > > >   	}
> > > > > >   	res = v4l2_async_register_subdev(sd);
> > > > > > 
> > > > > > 
> > > > 
> > > > [PATCH] media: tvp5150: implement decoder lock when irq is not used
> > > > 
> > > > When irq is used, the lock is set via IRQ code. When it isn't,
> > > > the driver just assumes it is always locked. Instead, read the
> > > > lock status from the status register.
> > > > 
> > > > Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
> > > > 
> > > > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > > > index efc441df7cac..e74af68be2eb 100644
> > > > --- a/drivers/media/i2c/tvp5150.c
> > > > +++ b/drivers/media/i2c/tvp5150.c
> > > > @@ -810,11 +810,25 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
> > > >   	}
> > > >   }
> > > > +static int query_lock(struct v4l2_subdev *sd)
> > > > +{
> > > > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > > > +	int status;
> > > > +
> > > > +	if (decoder->irq)
> > > > +		return decoder->lock;
> > > > +
> > > > +	regmap_read(decoder->regmap, TVP5150_STATUS_REG_1, &status);
> > > > +
> > > > +	/* For standard detection, we need the 3 locks */
> > > > +	return (status & 0x0e) == 0x0e;
> > > > +}
> > > > +
> > > >   static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
> > > >   {
> > > >   	struct tvp5150 *decoder = to_tvp5150(sd);
> > > 
> > > We should drop the decoder var here and not in the cleanup patch "media:
> > > tvp5150: get rid of some warnings".
> > 
> > I don't like the idea of merging stuff with different things together.
> > One patch per logical change.
> > 
> > > There are always two version of the
> > > patch that remove the 'static' warning [2,3].
> > > 
> > > [2] https://www.spinics.net/lists/linux-media/msg138318.html
> > > [3] https://www.spinics.net/lists/linux-media/msg138363.html
> > 
> > I'll likely just fold the static change with the patch that added
> > the warning when applying mainstream, adding a notice there at the
> > patch's description.
> > 
> > > 
> > > Regards,
> > > Marco
> > > > -	*std_id = decoder->lock ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
> > > > +	*std_id = query_lock(sd) ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN;
> > > >   	return 0;
> > > >   }
> > > > @@ -1208,7 +1222,10 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
> > > >   		tvp5150_enable(sd);
> > > >   		/* Enable outputs if decoder is locked */
> > > > -		val = decoder->lock ? decoder->oe : 0;
> > > > +		if (decoder->irq)
> > > > +			val = decoder->lock ? decoder->oe : 0;
> > > > +		else
> > > > +			val = decoder->oe;
> > > >   		int_val = TVP5150_INT_A_LOCK;
> > > >   		v4l2_subdev_notify_event(&decoder->sd, &tvp5150_ev_fmt);
> > > >   	}
> > > > @@ -1777,8 +1794,6 @@ static int tvp5150_probe(struct i2c_client *c,
> > > >   						IRQF_ONESHOT, "tvp5150", core);
> > > >   		if (res)
> > > >   			return res;
> > > > -	} else {
> > > > -		core->lock = true;
> > > >   	}
> > > >   	res = v4l2_async_register_subdev(sd);
> > > > 
> > > > 
> > > > 
> > > > Thanks,
> > > > Mauro
> > > 
> > 
> > 
> > 
> > Thanks,
> > Mauro
> > 
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

* Re: [PATCH 16/22] [media] tvp5150: add querystd
  2018-08-02 10:16                 ` Marco Felsch
@ 2018-08-02 14:38                   ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 70+ messages in thread
From: Mauro Carvalho Chehab @ 2018-08-02 14:38 UTC (permalink / raw)
  To: Marco Felsch
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Em Thu, 2 Aug 2018 12:16:41 +0200
Marco Felsch <m.felsch@pengutronix.de> escreveu:

> > > Did you drop the DT of_graph support patch? It was there on your first
> > > tvp5150 branch.   
> > 
> > Yes. As discussed, I'm waiting for a replacement patch from you. So,
> > after testing, I removed it, in order to make simpler to add your
> > replacement patch.
> > 
> > IMO, the proper mapping is one input linked to (up to) 3 connectors.  
> 
> I tought it would be okay to have more than 1 input pad since the
> .sig_type pad property. So the tvp5150 media entity can be represented
> like the physical tvp5150 chip.

As I said, tvp5150 has internally two physical inputs only: AIP1A and AIP1B.

IMO, it should be creating 3 PADS (two inputs and the output one), e. g.
something like (names here are just a suggestion):

	TVP5150_PAD_IN_AIP1A,
	TVP5150_PAD_IN_AIP1B,
	TVP5150_PAD_OUT

The S-video connector (if present) should be linked to both inputs.

I discussed this with other core maintainers: we all have the same
opinion about that.

I'll post a separate e-mail from the discussions for you and others to
comment.

It would need some logic that will enforce that just one connector link
will be active on any given time (e. g. when a link is enabled, 
it should disable the other links).

> 
> I will fix it, if it isn't the right way.

Ok.

Thanks,
Mauro

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

* Re: [PATCH 20/22] [media] tvp5150: Add input port connectors DT bindings
  2018-07-03 23:23   ` Rob Herring
  2018-07-11  8:50     ` Marco Felsch
@ 2018-08-03  7:29     ` Marco Felsch
  2018-08-03 17:30       ` Mauro Carvalho Chehab
  1 sibling, 1 reply; 70+ messages in thread
From: Marco Felsch @ 2018-08-03  7:29 UTC (permalink / raw)
  To: Rob Herring
  Cc: mchehab, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Hi Rob,

first of all, thanks for the review. After some discussion with the
media guys I have a question about the dt-bindings.

On 18-07-03 17:23, Rob Herring wrote:
> On Thu, Jun 28, 2018 at 06:20:52PM +0200, Marco Felsch wrote:
> > The TVP5150/1 decoders support different video input sources to their
> > AIP1A/B pins.
> > 
> > Possible configurations are as follows:
> >   - Analog Composite signal connected to AIP1A.
> >   - Analog Composite signal connected to AIP1B.
> >   - Analog S-Video Y (luminance) and C (chrominance)
> >     signals connected to AIP1A and AIP1B respectively.
> > 
> > This patch extends the device tree bindings documentation to describe
> > how the input connectors for these devices should be defined in a DT.
> > 
> > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > ---
> >  .../devicetree/bindings/media/i2c/tvp5150.txt | 118 +++++++++++++++++-
> >  1 file changed, 113 insertions(+), 5 deletions(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/media/i2c/tvp5150.txt b/Documentation/devicetree/bindings/media/i2c/tvp5150.txt
> > index 8c0fc1a26bf0..feed8c911c5e 100644
> > --- a/Documentation/devicetree/bindings/media/i2c/tvp5150.txt
> > +++ b/Documentation/devicetree/bindings/media/i2c/tvp5150.txt
> > @@ -12,11 +12,23 @@ Optional Properties:
> >  - pdn-gpios: phandle for the GPIO connected to the PDN pin, if any.
> >  - reset-gpios: phandle for the GPIO connected to the RESETB pin, if any.
> >  
> > -The device node must contain one 'port' child node for its digital output
> > -video port, in accordance with the video interface bindings defined in
> > -Documentation/devicetree/bindings/media/video-interfaces.txt.
> > +The device node must contain one 'port' child node per device input and output
> > +port, in accordance with the video interface bindings defined in
> > +Documentation/devicetree/bindings/media/video-interfaces.txt. The port nodes
> > +are numbered as follows
> >  
> > -Required Endpoint Properties for parallel synchronization:
> > +	  Name		Type		Port
> > +	--------------------------------------
> > +	  AIP1A		sink		0
> > +	  AIP1B		sink		1
> > +	  S-VIDEO	sink		2
> > +	  Y-OUT		src		3

Do you think it's correct to have a seperate port for each binding?
Since the S-Video port is a combination of AIP1A and AIP1B. After a
discussion with Mauro [1] the TVP5150 should have only 3 pads. Since the
pads are directly mappped to the dt-ports this will correspond to three
ports (2 in, 1 out). Now the svideo connector will be mapped to a second
endpoint in each port:

port@0			
	endpoint@0 -----------> Comp0-Con
	endpoint@1 -----+-----> Svideo-Con
port@1			|
	endpoint@0 -----|-----> Comp1-Con
	endpoint@1 -----+
port@2
	endpoint

I don't like that solution that much, since the mapping is now signal
based. We also don't map each line of a parallel port.

A quick grep shows that currently each device using a svideo connector
seperates them in a own port as I did. IMHO this is a uncomplicate
solution, but don't abstract the HW correctly. What is your opinion
about that? Is it correct to have seperate (virtual) port or should I
map the svideo connector as shown above?

[1] https://www.spinics.net/lists/devicetree/msg242825.html

Regards,
Marco

> > +
> > +The device node must contain at least the Y-OUT port. Each input port must be
> > +linked to an endpoint defined in
> > +Documentation/devicetree/bindings/display/connector/analog-tv-connector.txt.
> > +
> > +Required Endpoint Properties for parallel synchronization on output port:
> >  
> >  - hsync-active: active state of the HSYNC signal. Must be <1> (HIGH).
> >  - vsync-active: active state of the VSYNC signal. Must be <1> (HIGH).
> > @@ -26,7 +38,9 @@ Required Endpoint Properties for parallel synchronization:
> >  If none of hsync-active, vsync-active and field-even-active is specified,
> >  the endpoint is assumed to use embedded BT.656 synchronization.
> >  
> > -Example:
> > +Examples:
> > +
> > +Only Output:
> >  
> >  &i2c2 {
> >  	...
> > @@ -37,6 +51,100 @@ Example:
> >  		reset-gpios = <&gpio6 7 GPIO_ACTIVE_LOW>;
> >  
> >  		port {
> > +			reg = <3>;
> > +			tvp5150_1: endpoint {
> > +				remote-endpoint = <&ccdc_ep>;
> > +			};
> > +		};
> > +	};
> > +};
> > +
> > +One Input:
> > +
> > +connector@0 {
> 
> Drop the unit-address as there is no reg property.
> 
> > +	compatible = "composite-video-connector";
> > +	label = "Composite0";
> > +
> > +	port {
> > +		comp0_out: endpoint {
> > +			remote-endpoint = <&tvp5150_comp0_in>;
> > +		};
> > +	};
> > +};
> > +
> > +&i2c2 {
> > +	...
> > +	tvp5150@5c {
> > +		compatible = "ti,tvp5150";
> > +		reg = <0x5c>;
> > +		pdn-gpios = <&gpio4 30 GPIO_ACTIVE_LOW>;
> > +		reset-gpios = <&gpio6 7 GPIO_ACTIVE_LOW>;
> > +
> > +		port@0 {
> > +			reg = <0>;
> > +			tvp5150_comp0_in: endpoint {
> > +				remote-endpoint = <&comp0_out>;
> > +			};
> > +		};
> > +
> > +		port@3 {
> > +			reg = <3>;
> > +			tvp5150_1: endpoint {
> > +				remote-endpoint = <&ccdc_ep>;
> > +			};
> > +		};
> > +	};
> > +};
> > +
> > +
> > +Two Inputs, different connector 12 on input AIP1A:
> > +
> > +connector@1 {
> 
> ditto
> 
> > +	compatible = "svideo-connector";
> > +	label = "S-Video";
> > +
> > +	port {
> > +		svideo_out: endpoint {
> > +			remote-endpoint = <&tvp5150_svideo_in>;
> > +		};
> > +	};
> > +};
> > +
> > +connector@12 {
> 
> ditto
> 
> > +	compatible = "composite-video-connector";
> > +	label = "Composite12";
> > +
> > +	port {
> > +		comp12_out: endpoint {
> > +			remote-endpoint = <&tvp5150_comp12_in>;
> > +		};
> > +	};
> > +};
> > +
> > +&i2c2 {
> > +	...
> > +	tvp5150@5c {
> > +		compatible = "ti,tvp5150";
> > +		reg = <0x5c>;
> > +		pdn-gpios = <&gpio4 30 GPIO_ACTIVE_LOW>;
> > +		reset-gpios = <&gpio6 7 GPIO_ACTIVE_LOW>;
> > +
> > +		port@0 {
> > +			reg = <0>;
> > +			tvp5150_comp12_in: endpoint {
> > +				remote-endpoint = <&comp12_out>;
> > +			};
> > +		};
> > +
> > +		port@2 {
> > +			reg = <2>;
> > +			tvp5150_svideo_in: endpoint {
> > +				remote-endpoint = <&svideo_out>;
> > +			};
> > +		};
> > +
> > +		port@3 {
> > +			reg = <3>;
> >  			tvp5150_1: endpoint {
> >  				remote-endpoint = <&ccdc_ep>;
> >  			};
> > -- 
> > 2.17.1
> > 
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-5082 |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

* Re: [PATCH 20/22] [media] tvp5150: Add input port connectors DT bindings
  2018-08-03  7:29     ` Marco Felsch
@ 2018-08-03 17:30       ` Mauro Carvalho Chehab
  2018-08-04  9:04         ` Marco Felsch
  0 siblings, 1 reply; 70+ messages in thread
From: Mauro Carvalho Chehab @ 2018-08-03 17:30 UTC (permalink / raw)
  To: Marco Felsch
  Cc: Rob Herring, mchehab, mark.rutland, p.zabel, afshin.nasser,
	javierm, sakari.ailus, laurent.pinchart, linux-media, devicetree,
	kernel

Em Fri, 3 Aug 2018 09:29:53 +0200
Marco Felsch <m.felsch@pengutronix.de> escreveu:

> Hi Rob,
> 
> first of all, thanks for the review. After some discussion with the
> media guys I have a question about the dt-bindings.
> 
> On 18-07-03 17:23, Rob Herring wrote:
> > On Thu, Jun 28, 2018 at 06:20:52PM +0200, Marco Felsch wrote:  
> > > The TVP5150/1 decoders support different video input sources to their
> > > AIP1A/B pins.
> > > 
> > > Possible configurations are as follows:
> > >   - Analog Composite signal connected to AIP1A.
> > >   - Analog Composite signal connected to AIP1B.
> > >   - Analog S-Video Y (luminance) and C (chrominance)
> > >     signals connected to AIP1A and AIP1B respectively.
> > > 
> > > This patch extends the device tree bindings documentation to describe
> > > how the input connectors for these devices should be defined in a DT.
> > > 
> > > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > > ---
> > >  .../devicetree/bindings/media/i2c/tvp5150.txt | 118 +++++++++++++++++-
> > >  1 file changed, 113 insertions(+), 5 deletions(-)
> > > 
> > > diff --git a/Documentation/devicetree/bindings/media/i2c/tvp5150.txt b/Documentation/devicetree/bindings/media/i2c/tvp5150.txt
> > > index 8c0fc1a26bf0..feed8c911c5e 100644
> > > --- a/Documentation/devicetree/bindings/media/i2c/tvp5150.txt
> > > +++ b/Documentation/devicetree/bindings/media/i2c/tvp5150.txt
> > > @@ -12,11 +12,23 @@ Optional Properties:
> > >  - pdn-gpios: phandle for the GPIO connected to the PDN pin, if any.
> > >  - reset-gpios: phandle for the GPIO connected to the RESETB pin, if any.
> > >  
> > > -The device node must contain one 'port' child node for its digital output
> > > -video port, in accordance with the video interface bindings defined in
> > > -Documentation/devicetree/bindings/media/video-interfaces.txt.
> > > +The device node must contain one 'port' child node per device input and output
> > > +port, in accordance with the video interface bindings defined in
> > > +Documentation/devicetree/bindings/media/video-interfaces.txt. The port nodes
> > > +are numbered as follows
> > >  
> > > -Required Endpoint Properties for parallel synchronization:
> > > +	  Name		Type		Port
> > > +	--------------------------------------
> > > +	  AIP1A		sink		0
> > > +	  AIP1B		sink		1
> > > +	  S-VIDEO	sink		2
> > > +	  Y-OUT		src		3  
> 
> Do you think it's correct to have a seperate port for each binding?
> Since the S-Video port is a combination of AIP1A and AIP1B. After a
> discussion with Mauro [1] the TVP5150 should have only 3 pads. Since the
> pads are directly mappped to the dt-ports this will correspond to three
> ports (2 in, 1 out). Now the svideo connector will be mapped to a second
> endpoint in each port:
> 
> port@0			
> 	endpoint@0 -----------> Comp0-Con
> 	endpoint@1 -----+-----> Svideo-Con
> port@1		|
> 	endpoint@0 -----|-----> Comp1-Con
> 	endpoint@1 -----+
> port@2
> 	endpoint

For tvp5150, the model is like the above, so just one port at the
S-video connector.

Yet, for more complex devices that would allow switching the
endpoints at the Svideo connector, the model would be:

port@0			
	endpoint@0 (AIP1A) -----------> Comp0-Con
	endpoint@1 (AIP1B) -----------> Svideo-Con  port@0 (luminance)
port@1
	endpoint@0 (AIP1A) -----------> Comp1-Con
	endpoint@1 (AIP1B) -----------> Svideo-Con  port@1 (chrominance)
port@2
	endpoint   (video bitstream output)

E. g. the S-Video connector will also have two ports, one for the
chrominance signal and another one for the luminance one.

> I don't like that solution that much, since the mapping is now signal
> based. We also don't map each line of a parallel port.
> 
> A quick grep shows that currently each device using a svideo connector
> seperates them in a own port as I did.

No. I've no idea about how you did the grep, but this is not how other
drivers handle it currently.

Right now, on all hardware where connectors are mapped, there is just one
input port and multiple connectors linked to it. You can see some examples
here:

	https://www.infradead.org/~mchehab/mc-next-gen/au0828_hvr950q.png
	https://www.infradead.org/~mchehab/mc-next-gen/cx231xx_hvr930c_hd.png
	https://www.infradead.org/~mchehab/mc-next-gen/em28xx_hvr950.png
	https://www.infradead.org/~mchehab/mc-next-gen/playtv_usb.png
	https://www.infradead.org/~mchehab/mc-next-gen/saa7134-asus-p7131-dual.png
	https://www.infradead.org/~mchehab/mc-next-gen/wintv_usb2.png

The problem with this approach is that it doesn't reflect how the
hardware is actually wired. On some hardware similar to tvp5150,
it may be possible, for example, to wire the S-Video both ways,
e. g., something equivalent to (using tvp5150 terminology):

	Luminance   -> AIP1A
	Chrominance -> AIP1B
or
	Luminance   -> AIP1B
	Chrominance -> AIP1A

So, just one pad wouldn't allow this kind of config.

Having three pads is equally wrong, as there's no S-Video port on
tvp5150. All it has physically are two inputs: AIP1A and AIP1B.

If you want to see the discussions we had, they are at:
	https://linuxtv.org/irc/irclogger_log/media-maint?date=2018-08-02,Thu

I'm preparing right now a summary of them. will copy you once I
finish it.

> IMHO this is a uncomplicate
> solution, but don't abstract the HW correctly. What is your opinion
> about that? Is it correct to have seperate (virtual) port or should I
> map the svideo connector as shown above?
> 
> [1] https://www.spinics.net/lists/devicetree/msg242825.html

Anyway, I'm writing a summary of our discussions 

Thanks,
Mauro

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

* Re: [PATCH 20/22] [media] tvp5150: Add input port connectors DT bindings
  2018-08-03 17:30       ` Mauro Carvalho Chehab
@ 2018-08-04  9:04         ` Marco Felsch
  0 siblings, 0 replies; 70+ messages in thread
From: Marco Felsch @ 2018-08-04  9:04 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Rob Herring, mchehab, mark.rutland, p.zabel, afshin.nasser,
	javierm, sakari.ailus, laurent.pinchart, linux-media, devicetree,
	kernel

Hi Mauro,

On 18-08-03 14:30, Mauro Carvalho Chehab wrote:
> Em Fri, 3 Aug 2018 09:29:53 +0200
> Marco Felsch <m.felsch@pengutronix.de> escreveu:
> 
> > Hi Rob,
> > 
> > first of all, thanks for the review. After some discussion with the
> > media guys I have a question about the dt-bindings.
> > 
> > On 18-07-03 17:23, Rob Herring wrote:
> > > On Thu, Jun 28, 2018 at 06:20:52PM +0200, Marco Felsch wrote:  
> > > > The TVP5150/1 decoders support different video input sources to their
> > > > AIP1A/B pins.
> > > > 
> > > > Possible configurations are as follows:
> > > >   - Analog Composite signal connected to AIP1A.
> > > >   - Analog Composite signal connected to AIP1B.
> > > >   - Analog S-Video Y (luminance) and C (chrominance)
> > > >     signals connected to AIP1A and AIP1B respectively.
> > > > 
> > > > This patch extends the device tree bindings documentation to describe
> > > > how the input connectors for these devices should be defined in a DT.
> > > > 
> > > > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > > > ---
> > > >  .../devicetree/bindings/media/i2c/tvp5150.txt | 118 +++++++++++++++++-
> > > >  1 file changed, 113 insertions(+), 5 deletions(-)
> > > > 
> > > > diff --git a/Documentation/devicetree/bindings/media/i2c/tvp5150.txt b/Documentation/devicetree/bindings/media/i2c/tvp5150.txt
> > > > index 8c0fc1a26bf0..feed8c911c5e 100644
> > > > --- a/Documentation/devicetree/bindings/media/i2c/tvp5150.txt
> > > > +++ b/Documentation/devicetree/bindings/media/i2c/tvp5150.txt
> > > > @@ -12,11 +12,23 @@ Optional Properties:
> > > >  - pdn-gpios: phandle for the GPIO connected to the PDN pin, if any.
> > > >  - reset-gpios: phandle for the GPIO connected to the RESETB pin, if any.
> > > >  
> > > > -The device node must contain one 'port' child node for its digital output
> > > > -video port, in accordance with the video interface bindings defined in
> > > > -Documentation/devicetree/bindings/media/video-interfaces.txt.
> > > > +The device node must contain one 'port' child node per device input and output
> > > > +port, in accordance with the video interface bindings defined in
> > > > +Documentation/devicetree/bindings/media/video-interfaces.txt. The port nodes
> > > > +are numbered as follows
> > > >  
> > > > -Required Endpoint Properties for parallel synchronization:
> > > > +	  Name		Type		Port
> > > > +	--------------------------------------
> > > > +	  AIP1A		sink		0
> > > > +	  AIP1B		sink		1
> > > > +	  S-VIDEO	sink		2
> > > > +	  Y-OUT		src		3  
> > 
> > Do you think it's correct to have a seperate port for each binding?
> > Since the S-Video port is a combination of AIP1A and AIP1B. After a
> > discussion with Mauro [1] the TVP5150 should have only 3 pads. Since the
> > pads are directly mappped to the dt-ports this will correspond to three
> > ports (2 in, 1 out). Now the svideo connector will be mapped to a second
> > endpoint in each port:
> > 
> > port@0			
> > 	endpoint@0 -----------> Comp0-Con
> > 	endpoint@1 -----+-----> Svideo-Con
> > port@1		|
> > 	endpoint@0 -----|-----> Comp1-Con
> > 	endpoint@1 -----+
> > port@2
> > 	endpoint
> 
> For tvp5150, the model is like the above, so just one port at the
> S-video connector.

Okay, but this won't work. I tested it yesterday. Since the svideo port
is linked to two endpoints and the DTC will throw an error
"ERROR (duplicate_label)". Which make sens, but I covered it to late...

So we have two opportunities: 1) the one you described below or 2) we
map only port@0/port@1 to the svideo connector.

Anyway, should endpoint@1 always refer to the svideo connector or should
it be independent (in case of 1xcomp-con and 1xsvideo-con)?

> 
> Yet, for more complex devices that would allow switching the
> endpoints at the Svideo connector, the model would be:
> 
> port@0			
> 	endpoint@0 (AIP1A) -----------> Comp0-Con
> 	endpoint@1 (AIP1B) -----------> Svideo-Con  port@0 (luminance)
> port@1
> 	endpoint@0 (AIP1A) -----------> Comp1-Con
> 	endpoint@1 (AIP1B) -----------> Svideo-Con  port@1 (chrominance)
> port@2
> 	endpoint   (video bitstream output)
> 
> E. g. the S-Video connector will also have two ports, one for the
> chrominance signal and another one for the luminance one.
> 
> > I don't like that solution that much, since the mapping is now signal
> > based. We also don't map each line of a parallel port.
> > 
> > A quick grep shows that currently each device using a svideo connector
> > seperates them in a own port as I did.
> 
> No. I've no idea about how you did the grep, but this is not how other
> drivers handle it currently.

Sorry for that. My grep only covered the dt related connectors and not the
connectors within the mc framework.

> 
> Right now, on all hardware where connectors are mapped, there is just one
> input port and multiple connectors linked to it. You can see some examples
> here:
> 
> 	https://www.infradead.org/~mchehab/mc-next-gen/au0828_hvr950q.png
> 	https://www.infradead.org/~mchehab/mc-next-gen/cx231xx_hvr930c_hd.png
> 	https://www.infradead.org/~mchehab/mc-next-gen/em28xx_hvr950.png
> 	https://www.infradead.org/~mchehab/mc-next-gen/playtv_usb.png
> 	https://www.infradead.org/~mchehab/mc-next-gen/saa7134-asus-p7131-dual.png
> 	https://www.infradead.org/~mchehab/mc-next-gen/wintv_usb2.png
> 
> The problem with this approach is that it doesn't reflect how the
> hardware is actually wired. On some hardware similar to tvp5150,
> it may be possible, for example, to wire the S-Video both ways,
> e. g., something equivalent to (using tvp5150 terminology):
> 
> 	Luminance   -> AIP1A
> 	Chrominance -> AIP1B
> or
> 	Luminance   -> AIP1B
> 	Chrominance -> AIP1A
> 
> So, just one pad wouldn't allow this kind of config.
> 
> Having three pads is equally wrong, as there's no S-Video port on
> tvp5150. All it has physically are two inputs: AIP1A and AIP1B.
> 
> If you want to see the discussions we had, they are at:
> 	https://linuxtv.org/irc/irclogger_log/media-maint?date=2018-08-02,Thu
> 
> I'm preparing right now a summary of them. will copy you once I
> finish it.

I read the channel and your RFC patch, thanks for the discussion. One
thing I missed is to enable the svideo-link. I think hans wanted to
enable the links seperatly, but what about the "easy" use-case (no
chroma/luma seperation). If the user wants to enable svideo,
this pad should be linked to both tvp5150 input-pads and both links
should be enabled simultaneous. Should this be handeld by a pad flag?

Thanks,
Marco

> 
> > IMHO this is a uncomplicate
> > solution, but don't abstract the HW correctly. What is your opinion
> > about that? Is it correct to have seperate (virtual) port or should I
> > map the svideo connector as shown above?
> > 
> > [1] https://www.spinics.net/lists/devicetree/msg242825.html
> 
> Anyway, I'm writing a summary of our discussions 
> 
> Thanks,
> Mauro
> 

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

* Re: [PATCH 19/22] [media] tvp5150: add input source selection of_graph support
  2018-07-30 18:29   ` Mauro Carvalho Chehab
@ 2018-08-08 15:29     ` Marco Felsch
  2018-08-08 18:52       ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 70+ messages in thread
From: Marco Felsch @ 2018-08-08 15:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Hi Mauro,

the discussion about the correct binding was spread around some patches.
So I will try use the correct thread for that theme. I did my rework for
the of_graph support on your suggestions [1] and [2]. I attached my work
as RFC patch. Can you review it, so I can prepare a v2?

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

On 18-07-30 15:29, Mauro Carvalho Chehab wrote:
> Em Thu, 28 Jun 2018 18:20:51 +0200
> Marco Felsch <m.felsch@pengutronix.de> escreveu:
> 
> > The currrent driver layout had the following layout:
> >                +----------------+
> >  +-------+     |    TVP5150     |
> >  | Comp0 +--+  |                |
> >  +-------+  |  |          +-----+
> >  +-------+  |  +------+   | Src |
> >  | Comp1 +--+--|Sink  |   +-----+
> >  +-------+  |  +------+   +-----+
> > +--------+  |  |          | Src |
> > | SVideo +--+  |          +-----+
> > +--------+     +----------------+
> > 
> > Since the device tree abstracts the real hardware this layout is not
> > correct, because the TVP5150 has 3 physical ports (2 input, 1 output).
> > Furthermore this layout assumes that there is an additional external mux
> > in front of the TVP5150. This is not correct because the TVP5150 does
> > the muxing work. The corresponding of_graph layout will look like:
> > 	tvp5150 {
> > 		....
> > 		port {
> > 			reg = <0>;
> > 			endpoint@0 {...};
> > 			endpoint@1 {...};
> > 			endpoint@2 {...};
> > 		};
> > 
> > 	};
> > 
> > This patch change the layout to:
> >              +----------------+
> >              |    TVP5150     |
> >  +-------+   +------+         |
> >  | Comp0 +---+ Sink |         |
> >  +-------+   +------+         |
> >  +-------+   +------+   +-----+
> >  | Comp1 +---+ Sink |   | Src |
> >  +-------+   +------+   +-----+
> > +--------+   +------+         |
> > | SVideo +---+ Sink |         |
> > +--------+   +------+         |
> >              +----------------+
> > 
> > To keep things easy an additional 'virtual' S-Video port is added. More
> > information about the port mapping can be found in the device tree
> > binding documentation. The connector entities Comp0/1, SVideo are created
> > only if they are connected to the correct port. If more than one connector
> > is available the media_entity_operations.link_setup() callback ensures that
> > only one connector is active. To change the input src the link between
> > the TVP5150 pad and the connector must be disabled, then a new link can
> > be enabled.
> > 
> > The patch tries to reduce the '#ifdef CONFIG_MEDIA_CONTROLLER' usage to
> > a minimum.
> > 
> > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > ---
> >  drivers/media/i2c/tvp5150.c | 322 ++++++++++++++++++++++++++++++++----
> >  1 file changed, 287 insertions(+), 35 deletions(-)
> > 
> > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > index a6fec569a610..6ac29c62d99b 100644
> > --- a/drivers/media/i2c/tvp5150.c
> > +++ b/drivers/media/i2c/tvp5150.c
> > @@ -44,10 +44,30 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
> >  
> >  #define dprintk0(__dev, __arg...) dev_dbg_lvl(__dev, 0, 0, __arg)
> >  
> > +enum tvp5150_ports {
> > +	TVP5150_PORT_AIP1A = TVP5150_COMPOSITE0,
> > +	TVP5150_PORT_AIP1B,
> > +	/* s-video port is a virtual port */
> > +	TVP5150_PORT_SVIDEO,
> > +	TVP5150_PORT_YOUT,
> > +	TVP5150_PORT_NUM,
> > +};
> > +
> > +#ifdef CONFIG_MEDIA_CONTROLLER
> > +struct tvp5150_connector {
> > +	struct media_entity con;
> > +	struct media_pad pad;
> > +	unsigned int port_num;
> > +};
> > +#endif
> > +
> >  struct tvp5150 {
> >  	struct v4l2_subdev sd;
> > +	struct device_node *endpoints[TVP5150_PORT_NUM];
> >  #ifdef CONFIG_MEDIA_CONTROLLER
> > -	struct media_pad pads[DEMOD_NUM_PADS];
> > +	struct media_pad pads[TVP5150_PORT_NUM];
> 
> This will cause problems with the current code.
> 
> When we designed the MC version 2 code, the idea were to allow
> set properties to entities and to the inputs, but the code
> was never submitted upstream.
> 
> A decoder may have several different types of inputs and outputs.
> Several designs allow using different types of decoders, being
> saa711x and tvp5150 the most popular ones. Well, depending on
> the device, the number of PADs and the signals they carry can
> be different.
> 
> Without a way to "taint" a pad to the signal it contains, 
> while waiting for the properties API, we added a code that
> "fixed" the PADs to a certain number. This way, Kernelspace could
> use the pad "number" as a way to identify the type of signal a
> PAD carries.
> 
> The PC consumer drivers use those numbers in order to build the
> MC graph[1].
> 
> A change on this would require adding a property to the pad, in
> order to indicate the type of signal it provides (RF, luminance IF,
> chroma IF, audio IF, I2S audio, ...), and to change
> v4l2_mc_create_media_graph() accordingly.
> 
> 
> [1] See drivers/media/v4l2-core/v4l2-mc.c at v4l2_mc_create_media_graph() func.
> 
> 

[ snip ]

>From d3eb8a7de65fe2f8dd10ced85e4baca8e7898434 Mon Sep 17 00:00:00 2001
From: Marco Felsch <m.felsch@pengutronix.de>
Date: Thu, 28 Jun 2018 18:20:51 +0200
Subject: [RFC] [media] tvp5150: add input source selection of_graph
 support

This patch adds the of_graph support to describe the tvp connections.
Physical the TVP5150 has three ports: AIP1A, AIP1B and YOUT. As result
of discussion [1],[2] the device-tree maps these ports 1:1 with one
deviation. The svideo connector must be conneted to port@0/endpoint@1,
look at the Documentation for more information. Since the TVP5150 is a
converter the device-tree must contain at least 1-input and 1-output port.
The mc-connectors and mc-links are only created if the device-tree
contains the corresponding connector nodes. If more than one connector is
available the media_entity_operations.link_setup() callback ensures that
only one connector is active. To change the input src the active link must
disabled first, then a new link can be established.

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

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>

---
Changelog:

v2:
- adapt commit message
- mc: use 2-input and 1-output pad
- mc: enable svideo on tvp only if both tvp-input pads have a active
      link to the svideo src pad
- mc: disable svideo on tvp only if both tvp-input pads are inactive
- dt-support: drop svideo dt port
- dt-support: move svideo connector to port@0/endpoint@1
- dt-support: require at least 1-in and 1-out endpoint
---
 drivers/media/i2c/tvp5150.c | 413 ++++++++++++++++++++++++++++++++----
 1 file changed, 377 insertions(+), 36 deletions(-)

diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index b5d44c25d1da..be755c5e63a9 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -43,16 +43,38 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
 
 #define dprintk0(__dev, __arg...) dev_dbg_lvl(__dev, 0, 0, __arg)
 
+#ifdef CONFIG_MEDIA_CONTROLLER
 enum tvp5150_pads {
-       TVP5150_PAD_IF_INPUT,
-       TVP5150_PAD_VID_OUT,
-       TVP5150_NUM_PADS
+	TVP5150_PAD_AIP1A = TVP5150_COMPOSITE0,
+	TVP5150_PAD_AIP1B,
+	TVP5150_PAD_VID_OUT,
+	TVP5150_NUM_PADS
+};
+
+enum tvp5150_pads_state {
+	TVP5150_PAD_INACTIVE,
+	TVP5150_PAD_ACTIVE_COMPOSITE,
+	TVP5150_PAD_ACTIVE_SVIDEO,
+};
+
+struct tvp5150_connector {
+	struct media_entity ent;
+	struct media_pad pad;
+	unsigned int port_num;
+	bool is_svideo;
 };
+#endif
 
 struct tvp5150 {
 	struct v4l2_subdev sd;
+	/* additional additional endpoint for the svideo connector */
+	struct device_node *endpoints[TVP5150_NUM_PADS + 1];
+	unsigned int endpoints_num;
 #ifdef CONFIG_MEDIA_CONTROLLER
 	struct media_pad pads[TVP5150_NUM_PADS];
+	int pads_state[TVP5150_NUM_PADS];
+	struct tvp5150_connector *connectors;
+	int connectors_num;
 #endif
 	struct v4l2_ctrl_handler hdl;
 	struct v4l2_rect rect;
@@ -1168,6 +1190,135 @@ static int tvp5150_enum_frame_size(struct v4l2_subdev *sd,
 	return 0;
 }
 
+/****************************************************************************
+ *			Media entity ops
+ ****************************************************************************/
+#ifdef CONFIG_MEDIA_CONTROLLER
+static int tvp5150_s_routing(struct v4l2_subdev *sd, u32 input, u32 output,
+			     u32 config);
+static int tvp5150_link_setup(struct media_entity *entity,
+			      const struct media_pad *local,
+			      const struct media_pad *remote, u32 flags)
+{
+	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+	struct tvp5150 *decoder = to_tvp5150(sd);
+	int *pad_state = &decoder->pads_state[0];
+	int i, ret = 0, active_pad = -1;
+	bool is_svideo = false;
+
+	/*
+	 * The tvp state is determined by the enabled sink pad link.
+	 * Enabling or disabling the source pad link has no effect.
+	 */
+	if (local->flags & MEDIA_PAD_FL_SOURCE)
+		return 0;
+
+	/* check if the svideo connector should be enabled */
+	for (i = 0; i < decoder->connectors_num; i++) {
+		if (remote->entity == &decoder->connectors[i].ent) {
+			is_svideo = decoder->connectors[i].is_svideo;
+			break;
+		}
+	}
+
+	/* check if there is enabled link */
+	for (i = 0; i < TVP5150_NUM_PADS - 1; i++) {
+		if ((pad_state[i] == TVP5150_PAD_ACTIVE_COMPOSITE) ||
+		    (pad_state[i] == TVP5150_PAD_ACTIVE_SVIDEO)) {
+			active_pad = i;
+			break;
+		}
+	}
+
+	dev_dbg(sd->dev, "link setup '%s':%d->'%s':%d[%d]",
+		remote->entity->name, remote->index, local->entity->name,
+		local->index, flags & MEDIA_LNK_FL_ENABLED);
+
+	if (flags & MEDIA_LNK_FL_ENABLED) {
+		/*
+		 * Composite activation: all links must be inactive.
+		 * Svideo activation: one link can be active if it is a svideo
+		 * link. Return error in case of a active composite link or both
+		 * svideo links are active.
+		 */
+		if (active_pad >= 0 && !is_svideo) {
+			ret = -EBUSY;
+			goto out;
+		} else if (active_pad >= 0 && is_svideo &&
+			   pad_state[active_pad] ==
+			   TVP5150_PAD_ACTIVE_COMPOSITE) {
+			ret = -EBUSY;
+			goto out;
+		} else if (active_pad >= 0) {
+			/* check if 2nd svideo link is active too */
+			for (i = 0; i < TVP5150_NUM_PADS - 1; i++) {
+				if (pad_state[i] == TVP5150_PAD_ACTIVE_SVIDEO) {
+					if (i != active_pad) {
+						ret = -EBUSY;
+						goto out;
+					}
+				}
+			}
+		}
+
+		dev_dbg(sd->dev, "Setting %d active [%s]\n", local->index,
+			is_svideo ? "svideo": "composite");
+		pad_state[local->index] = is_svideo ?
+			TVP5150_PAD_ACTIVE_SVIDEO : TVP5150_PAD_ACTIVE_COMPOSITE;
+
+		if (is_svideo) {
+			unsigned int active_link_cnt = 0;
+
+			/* enable svideo only if we have two active links */
+			for (i = 0; i > TVP5150_NUM_PADS - 1; i++)
+				if (pad_state[i] == TVP5150_PAD_ACTIVE_SVIDEO)
+					active_link_cnt++;
+			if (active_link_cnt == 2)
+				tvp5150_s_routing(sd, TVP5150_SVIDEO,
+						  TVP5150_NORMAL, 0);
+		} else {
+			tvp5150_s_routing(sd, local->index, TVP5150_NORMAL, 0);
+		}
+	} else {
+		/*
+		 * Svideo streams on two pads and user can disable AIP1A or
+		 * AIP1B first. So check only if user wants to disable a not
+		 * enabled composite pad.
+		 */
+		if (!is_svideo && active_pad != local->index)
+				goto out;
+
+		dev_dbg(sd->dev, "going inactive\n");
+		pad_state[local->index] = TVP5150_PAD_INACTIVE;
+
+		/*
+		 * Output black screen for deselected input if TVP5150 variant
+		 * supports this.
+		 */
+		if (is_svideo) {
+			unsigned int inactive_link_cnt = 0;
+
+			/* disable svideo only if we have two inactive links */
+			for (i = 0; i > TVP5150_NUM_PADS - 1; i++)
+				if (pad_state[i] == TVP5150_PAD_INACTIVE)
+					inactive_link_cnt++;
+			if (inactive_link_cnt == 2)
+				tvp5150_s_routing(sd, TVP5150_SVIDEO,
+						  TVP5150_BLACK_SCREEN, 0);
+
+		} else {
+			tvp5150_s_routing(sd, local->index,
+					  TVP5150_BLACK_SCREEN, 0);
+		}
+	}
+out:
+	return ret;
+}
+
+static const struct media_entity_operations tvp5150_sd_media_ops = {
+	.link_setup = tvp5150_link_setup,
+};
+#endif
 /****************************************************************************
 			I2C Command
  ****************************************************************************/
@@ -1315,6 +1466,50 @@ static int tvp5150_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
 	return 0;
 }
 
+static int tvp5150_registered(struct v4l2_subdev *sd)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER
+	struct tvp5150 *decoder = to_tvp5150(sd);
+	unsigned int i;
+	int ret;
+
+	for (i = 0; i < decoder->connectors_num; i++) {
+		struct media_entity *con = &decoder->connectors[i].ent;
+		struct media_pad *pad = &decoder->connectors[i].pad;
+		unsigned int port = decoder->connectors[i].port_num;
+		bool is_svideo = decoder->connectors[i].is_svideo;
+
+		pad->flags = MEDIA_PAD_FL_SOURCE;
+		ret = media_entity_pads_init(con, 1, pad);
+		if (ret < 0)
+			return ret;
+
+		ret = media_device_register_entity(sd->v4l2_dev->mdev, con);
+		if (ret < 0)
+			return ret;
+
+		ret = media_create_pad_link(con, 0, &sd->entity, port, 0);
+		if (ret < 0) {
+			media_device_unregister_entity(con);
+			return ret;
+		}
+
+		if (is_svideo) {
+			/* svideo links to both aip1a and aip1b */
+			ret = media_create_pad_link(con, 0, &sd->entity,
+						    port + 1, 0);
+			if (ret < 0) {
+				media_device_unregister_entity(con);
+				return ret;
+			}
+		}
+
+	}
+#endif
+	return 0;
+}
+
+
 /* ----------------------------------------------------------------------- */
 
 static const struct v4l2_ctrl_ops tvp5150_ctrl_ops = {
@@ -1368,6 +1563,10 @@ static const struct v4l2_subdev_ops tvp5150_ops = {
 	.pad = &tvp5150_pad_ops,
 };
 
+static const struct v4l2_subdev_internal_ops tvp5150_internal_ops = {
+	.registered = tvp5150_registered,
+};
+
 /****************************************************************************
 			I2C Client & Driver
  ****************************************************************************/
@@ -1516,38 +1715,186 @@ static int tvp5150_init(struct i2c_client *c)
 	return 0;
 }
 
-static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np)
+static int tvp5150_mc_init(struct v4l2_subdev *sd)
 {
-	struct v4l2_fwnode_endpoint bus_cfg;
-	struct device_node *ep;
-	unsigned int flags;
-	int ret = 0;
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	struct tvp5150 *decoder = to_tvp5150(sd);
+	struct device *dev = decoder->sd.dev;
+	unsigned int i;
+	int ret;
 
-	ep = of_graph_get_next_endpoint(np, NULL);
-	if (!ep)
-		return -EINVAL;
+	sd->entity.ops = &tvp5150_sd_media_ops;
+	sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
 
-	ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &bus_cfg);
-	if (ret)
-		goto err;
+	/* Initialize all TVP5150 pads */
+	for (i = 0; i < TVP5150_NUM_PADS; i++) {
+		if (i < TVP5150_NUM_PADS - 1) {
+			decoder->pads[i].flags = MEDIA_PAD_FL_SINK;
+			decoder->pads[i].sig_type = PAD_SIGNAL_ANALOG;
+		} else {
+			decoder->pads[i].flags = MEDIA_PAD_FL_SOURCE;
+			decoder->pads[i].sig_type = PAD_SIGNAL_DV;
+		}
+	}
+	ret = media_entity_pads_init(&sd->entity, TVP5150_NUM_PADS,
+				     decoder->pads);
+	if (ret < 0)
+		return ret;
+
+	/* in case of no oftree support */
+	if (!decoder->endpoints[0])
+		return 0;
+
+	/* Allocate and initialize all available input connectors */
+	decoder->connectors = devm_kcalloc(dev, decoder->connectors_num,
+					   sizeof(*decoder->connectors),
+					   GFP_KERNEL);
+	if (!decoder->connectors)
+		return -ENOMEM;
+
+	for (i = 0; i < decoder->connectors_num; i++) {
+		struct device_node *rp;
+		struct of_endpoint ep;
+
+		rp = of_graph_get_remote_port_parent(decoder->endpoints[i]);
+		of_graph_parse_endpoint(decoder->endpoints[i], &ep);
+		decoder->connectors[i].port_num = ep.port;
+		decoder->connectors[i].is_svideo = !!of_device_is_compatible(rp,
+							    "svideo-connector");
+
+		if (decoder->connectors[i].is_svideo)
+			decoder->connectors[i].ent.function =
+						MEDIA_ENT_F_CONN_SVIDEO;
+		else
+			decoder->connectors[i].ent.function =
+						MEDIA_ENT_F_CONN_COMPOSITE;
+
+		decoder->connectors[i].ent.flags = MEDIA_ENT_FL_CONNECTOR;
+		ret = of_property_read_string(rp, "label",
+					      &decoder->connectors[i].ent.name);
+		if (ret < 0)
+			return ret;
+	}
+#endif
+	return 0;
+}
+
+static bool tvp5150_valid_input(struct device_node *endpoint,
+				unsigned int port, unsigned int id)
+{
+	struct device_node *rp = of_graph_get_remote_port_parent(endpoint);
+	const char *input;
+	int ret;
+
+	/* perform some basic checks needed for later mc_init */
+	switch (port) {
+	case TVP5150_PAD_AIP1A:
+		/* svideo must be connected to endpoint@1  */
+		ret = id ? of_device_is_compatible(rp, "svideo-connector") :
+			   of_device_is_compatible(rp, "composite-video-connector");
+		if (!ret)
+			return false;
+		break;
+	case TVP5150_PAD_AIP1B:
+		ret = of_device_is_compatible(rp, "composite-video-connector");
+		if (!ret)
+			return false;
+		break;
+	}
+
+	ret = of_property_read_string(rp, "label", &input);
+	if (ret < 0)
+		return false;
+
+	return true;
+}
 
-	flags = bus_cfg.bus.parallel.flags;
+static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np)
+{
+	struct device *dev = decoder->sd.dev;
+	struct v4l2_fwnode_endpoint bus_cfg;
+	struct device_node *ep_np;
+	unsigned int flags;
+	int ret, i = 0, in = 0;
+	bool found = false;
 
-	if (bus_cfg.bus_type == V4L2_MBUS_PARALLEL &&
-	    !(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH &&
-	      flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH &&
-	      flags & V4L2_MBUS_FIELD_EVEN_LOW)) {
+	/* at least 1 output and 1 input */
+	decoder->endpoints_num = of_graph_get_endpoint_count(np);
+	if (decoder->endpoints_num < 2 || decoder->endpoints_num > 4) {
 		ret = -EINVAL;
 		goto err;
 	}
 
-	decoder->mbus_type = bus_cfg.bus_type;
+	for_each_endpoint_of_node(np, ep_np) {
+		struct of_endpoint ep;
 
+		of_graph_parse_endpoint(ep_np, &ep);
+		if (decoder->endpoints[i]) {
+			/* this should never happen */
+			dev_err(dev, "Invalid endpoint %pOF on port %d\n",
+				ep.local_node, ep.port);
+				ret = -EINVAL;
+				goto err;
+		}
+
+		switch (ep.port) {
+		case TVP5150_PAD_AIP1A:
+		case TVP5150_PAD_AIP1B:
+			if (!tvp5150_valid_input(ep_np, ep.port, ep.id)) {
+				dev_err(dev,
+					"Invalid endpoint %pOF on port %d\n",
+					ep.local_node, ep.port);
+				ret = -EINVAL;
+				goto err;
+			}
+			in++;
+			break;
+		case TVP5150_PAD_VID_OUT:
+			ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_np),
+							 &bus_cfg);
+			if (ret)
+				goto err;
+
+			flags = bus_cfg.bus.parallel.flags;
+
+			if (bus_cfg.bus_type == V4L2_MBUS_PARALLEL &&
+			    !(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH &&
+			      flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH &&
+			      flags & V4L2_MBUS_FIELD_EVEN_LOW)) {
+				ret = -EINVAL;
+				goto err;
+			}
+
+			decoder->mbus_type = bus_cfg.bus_type;
+			break;
+		default:
+			dev_err(dev, "Invalid port %d for endpoint %pOF\n",
+				ep.port, ep.local_node);
+			ret = -EINVAL;
+			goto err;
+		}
+
+		of_node_get(ep_np);
+		decoder->endpoints[i] = ep_np;
+		i++;
+
+		found = true;
+	}
+
+	decoder->connectors_num = in;
+	return found ? 0 : -ENODEV;
 err:
-	of_node_put(ep);
 	return ret;
 }
 
+static void tvp5150_dt_cleanup(struct tvp5150 *decoder)
+{
+	unsigned int i;
+
+	for (i = 0; i < TVP5150_NUM_PADS; i++)
+		of_node_put(decoder->endpoints[i]);
+}
+
 static const char * const tvp5150_test_patterns[2] = {
 	"Disabled",
 	"Black screen"
@@ -1586,7 +1933,7 @@ static int tvp5150_probe(struct i2c_client *c,
 		res = tvp5150_parse_dt(core, np);
 		if (res) {
 			dev_err(sd->dev, "DT parsing error: %d\n", res);
-			return res;
+			goto err_cleanup_dt;
 		}
 	} else {
 		/* Default to BT.656 embedded sync */
@@ -1594,25 +1941,16 @@ static int tvp5150_probe(struct i2c_client *c,
 	}
 
 	v4l2_i2c_subdev_init(sd, c, &tvp5150_ops);
+	sd->internal_ops = &tvp5150_internal_ops;
 	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 
-#if defined(CONFIG_MEDIA_CONTROLLER)
-	core->pads[TVP5150_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
-	core->pads[TVP5150_PAD_IF_INPUT].sig_type = PAD_SIGNAL_ANALOG;
-	core->pads[TVP5150_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
-	core->pads[TVP5150_PAD_VID_OUT].sig_type = PAD_SIGNAL_DV;
-
-	sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
-
-	res = media_entity_pads_init(&sd->entity, TVP5150_NUM_PADS, core->pads);
-	if (res < 0)
-		return res;
-
-#endif
+	res = tvp5150_mc_init(sd);
+	if (res)
+		goto err_cleanup_dt;
 
 	res = tvp5150_detect_version(core);
 	if (res < 0)
-		return res;
+		goto err_cleanup_dt;
 
 	core->norm = V4L2_STD_ALL;	/* Default is autodetect */
 	core->detected_norm = V4L2_STD_UNKNOWN;
@@ -1664,6 +2002,9 @@ static int tvp5150_probe(struct i2c_client *c,
 err:
 	v4l2_ctrl_handler_free(&core->hdl);
 	return res;
+err_cleanup_dt:
+	tvp5150_dt_cleanup(core);
+	return res;
 }
 
 static int tvp5150_remove(struct i2c_client *c)
-- 
2.18.0

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

* Re: [PATCH 19/22] [media] tvp5150: add input source selection of_graph support
  2018-08-08 15:29     ` Marco Felsch
@ 2018-08-08 18:52       ` Mauro Carvalho Chehab
  2018-08-09 12:55         ` Marco Felsch
  0 siblings, 1 reply; 70+ messages in thread
From: Mauro Carvalho Chehab @ 2018-08-08 18:52 UTC (permalink / raw)
  To: Marco Felsch
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Em Wed, 8 Aug 2018 17:29:49 +0200
Marco Felsch <m.felsch@pengutronix.de> escreveu:

> Hi Mauro,
> 
> the discussion about the correct binding was spread around some patches.
> So I will try use the correct thread for that theme. I did my rework for
> the of_graph support on your suggestions [1] and [2]. I attached my work
> as RFC patch. Can you review it, so I can prepare a v2?
> 
> [1] https://www.spinics.net/lists/linux-media/msg138545.html
> [2] https://www.spinics.net/lists/linux-media/msg138546.html

Thanks for the patch.

Added my comments below.

> 
> On 18-07-30 15:29, Mauro Carvalho Chehab wrote:
> > Em Thu, 28 Jun 2018 18:20:51 +0200
> > Marco Felsch <m.felsch@pengutronix.de> escreveu:
> > 
> > > The currrent driver layout had the following layout:
> > >                +----------------+
> > >  +-------+     |    TVP5150     |
> > >  | Comp0 +--+  |                |
> > >  +-------+  |  |          +-----+
> > >  +-------+  |  +------+   | Src |
> > >  | Comp1 +--+--|Sink  |   +-----+
> > >  +-------+  |  +------+   +-----+
> > > +--------+  |  |          | Src |
> > > | SVideo +--+  |          +-----+
> > > +--------+     +----------------+
> > > 
> > > Since the device tree abstracts the real hardware this layout is not
> > > correct, because the TVP5150 has 3 physical ports (2 input, 1 output).
> > > Furthermore this layout assumes that there is an additional external mux
> > > in front of the TVP5150. This is not correct because the TVP5150 does
> > > the muxing work. The corresponding of_graph layout will look like:
> > > 	tvp5150 {
> > > 		....
> > > 		port {
> > > 			reg = <0>;
> > > 			endpoint@0 {...};
> > > 			endpoint@1 {...};
> > > 			endpoint@2 {...};
> > > 		};
> > > 
> > > 	};
> > > 
> > > This patch change the layout to:
> > >              +----------------+
> > >              |    TVP5150     |
> > >  +-------+   +------+         |
> > >  | Comp0 +---+ Sink |         |
> > >  +-------+   +------+         |
> > >  +-------+   +------+   +-----+
> > >  | Comp1 +---+ Sink |   | Src |
> > >  +-------+   +------+   +-----+
> > > +--------+   +------+         |
> > > | SVideo +---+ Sink |         |
> > > +--------+   +------+         |
> > >              +----------------+
> > > 
> > > To keep things easy an additional 'virtual' S-Video port is added. More
> > > information about the port mapping can be found in the device tree
> > > binding documentation. The connector entities Comp0/1, SVideo are created
> > > only if they are connected to the correct port. If more than one connector
> > > is available the media_entity_operations.link_setup() callback ensures that
> > > only one connector is active. To change the input src the link between
> > > the TVP5150 pad and the connector must be disabled, then a new link can
> > > be enabled.
> > > 
> > > The patch tries to reduce the '#ifdef CONFIG_MEDIA_CONTROLLER' usage to
> > > a minimum.
> > > 
> > > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > > ---
> > >  drivers/media/i2c/tvp5150.c | 322 ++++++++++++++++++++++++++++++++----
> > >  1 file changed, 287 insertions(+), 35 deletions(-)
> > > 
> > > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > > index a6fec569a610..6ac29c62d99b 100644
> > > --- a/drivers/media/i2c/tvp5150.c
> > > +++ b/drivers/media/i2c/tvp5150.c
> > > @@ -44,10 +44,30 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
> > >  
> > >  #define dprintk0(__dev, __arg...) dev_dbg_lvl(__dev, 0, 0, __arg)
> > >  
> > > +enum tvp5150_ports {
> > > +	TVP5150_PORT_AIP1A = TVP5150_COMPOSITE0,
> > > +	TVP5150_PORT_AIP1B,
> > > +	/* s-video port is a virtual port */
> > > +	TVP5150_PORT_SVIDEO,
> > > +	TVP5150_PORT_YOUT,
> > > +	TVP5150_PORT_NUM,
> > > +};
> > > +
> > > +#ifdef CONFIG_MEDIA_CONTROLLER
> > > +struct tvp5150_connector {
> > > +	struct media_entity con;
> > > +	struct media_pad pad;
> > > +	unsigned int port_num;
> > > +};
> > > +#endif
> > > +
> > >  struct tvp5150 {
> > >  	struct v4l2_subdev sd;
> > > +	struct device_node *endpoints[TVP5150_PORT_NUM];
> > >  #ifdef CONFIG_MEDIA_CONTROLLER
> > > -	struct media_pad pads[DEMOD_NUM_PADS];
> > > +	struct media_pad pads[TVP5150_PORT_NUM];
> > 
> > This will cause problems with the current code.
> > 
> > When we designed the MC version 2 code, the idea were to allow
> > set properties to entities and to the inputs, but the code
> > was never submitted upstream.
> > 
> > A decoder may have several different types of inputs and outputs.
> > Several designs allow using different types of decoders, being
> > saa711x and tvp5150 the most popular ones. Well, depending on
> > the device, the number of PADs and the signals they carry can
> > be different.
> > 
> > Without a way to "taint" a pad to the signal it contains, 
> > while waiting for the properties API, we added a code that
> > "fixed" the PADs to a certain number. This way, Kernelspace could
> > use the pad "number" as a way to identify the type of signal a
> > PAD carries.
> > 
> > The PC consumer drivers use those numbers in order to build the
> > MC graph[1].
> > 
> > A change on this would require adding a property to the pad, in
> > order to indicate the type of signal it provides (RF, luminance IF,
> > chroma IF, audio IF, I2S audio, ...), and to change
> > v4l2_mc_create_media_graph() accordingly.
> > 
> > 
> > [1] See drivers/media/v4l2-core/v4l2-mc.c at v4l2_mc_create_media_graph() func.
> > 
> > 
> 
> [ snip ]
> 
> From d3eb8a7de65fe2f8dd10ced85e4baca8e7898434 Mon Sep 17 00:00:00 2001
> From: Marco Felsch <m.felsch@pengutronix.de>
> Date: Thu, 28 Jun 2018 18:20:51 +0200
> Subject: [RFC] [media] tvp5150: add input source selection of_graph
>  support
> 
> This patch adds the of_graph support to describe the tvp connections.
> Physical the TVP5150 has three ports: AIP1A, AIP1B and YOUT. As result
> of discussion [1],[2] the device-tree maps these ports 1:1 with one
> deviation. The svideo connector must be conneted to port@0/endpoint@1,
> look at the Documentation for more information. Since the TVP5150 is a
> converter the device-tree must contain at least 1-input and 1-output port.
> The mc-connectors and mc-links are only created if the device-tree
> contains the corresponding connector nodes. If more than one connector is
> available the media_entity_operations.link_setup() callback ensures that
> only one connector is active. To change the input src the active link must
> disabled first, then a new link can be established.
> 
> [1] https://www.spinics.net/lists/linux-media/msg138545.html
> [2] https://www.spinics.net/lists/linux-media/msg138546.html
> 
> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> 
> ---
> Changelog:
> 
> v2:
> - adapt commit message
> - mc: use 2-input and 1-output pad
> - mc: enable svideo on tvp only if both tvp-input pads have a active
>       link to the svideo src pad
> - mc: disable svideo on tvp only if both tvp-input pads are inactive
> - dt-support: drop svideo dt port
> - dt-support: move svideo connector to port@0/endpoint@1
> - dt-support: require at least 1-in and 1-out endpoint
> ---
>  drivers/media/i2c/tvp5150.c | 413 ++++++++++++++++++++++++++++++++----
>  1 file changed, 377 insertions(+), 36 deletions(-)
> 
> diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> index b5d44c25d1da..be755c5e63a9 100644
> --- a/drivers/media/i2c/tvp5150.c
> +++ b/drivers/media/i2c/tvp5150.c
> @@ -43,16 +43,38 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
>  
>  #define dprintk0(__dev, __arg...) dev_dbg_lvl(__dev, 0, 0, __arg)
>  
> +#ifdef CONFIG_MEDIA_CONTROLLER
>  enum tvp5150_pads {
> -       TVP5150_PAD_IF_INPUT,
> -       TVP5150_PAD_VID_OUT,
> -       TVP5150_NUM_PADS
> +	TVP5150_PAD_AIP1A = TVP5150_COMPOSITE0,
> +	TVP5150_PAD_AIP1B,
> +	TVP5150_PAD_VID_OUT,
> +	TVP5150_NUM_PADS
> +};
> +
> +enum tvp5150_pads_state {
> +	TVP5150_PAD_INACTIVE,
> +	TVP5150_PAD_ACTIVE_COMPOSITE,
> +	TVP5150_PAD_ACTIVE_SVIDEO,
> +};
> +
> +struct tvp5150_connector {
> +	struct media_entity ent;
> +	struct media_pad pad;
> +	unsigned int port_num;
> +	bool is_svideo;
>  };
> +#endif
>  
>  struct tvp5150 {
>  	struct v4l2_subdev sd;
> +	/* additional additional endpoint for the svideo connector */
> +	struct device_node *endpoints[TVP5150_NUM_PADS + 1];
> +	unsigned int endpoints_num;
>  #ifdef CONFIG_MEDIA_CONTROLLER
>  	struct media_pad pads[TVP5150_NUM_PADS];
> +	int pads_state[TVP5150_NUM_PADS];
> +	struct tvp5150_connector *connectors;
> +	int connectors_num;
>  #endif
>  	struct v4l2_ctrl_handler hdl;
>  	struct v4l2_rect rect;
> @@ -1168,6 +1190,135 @@ static int tvp5150_enum_frame_size(struct v4l2_subdev *sd,
>  	return 0;
>  }
>  
> +/****************************************************************************
> + *			Media entity ops
> + ****************************************************************************/
> +#ifdef CONFIG_MEDIA_CONTROLLER
> +static int tvp5150_s_routing(struct v4l2_subdev *sd, u32 input, u32 output,
> +			     u32 config);
> +static int tvp5150_link_setup(struct media_entity *entity,
> +			      const struct media_pad *local,
> +			      const struct media_pad *remote, u32 flags)
> +{
> +	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
> +	struct tvp5150 *decoder = to_tvp5150(sd);
> +	int *pad_state = &decoder->pads_state[0];
> +	int i, ret = 0, active_pad = -1;
> +	bool is_svideo = false;
> +
> +	/*
> +	 * The tvp state is determined by the enabled sink pad link.
> +	 * Enabling or disabling the source pad link has no effect.
> +	 */
> +	if (local->flags & MEDIA_PAD_FL_SOURCE)
> +		return 0;
> +
> +	/* check if the svideo connector should be enabled */
> +	for (i = 0; i < decoder->connectors_num; i++) {
> +		if (remote->entity == &decoder->connectors[i].ent) {
> +			is_svideo = decoder->connectors[i].is_svideo;
> +			break;
> +		}
> +	}
> +
> +	/* check if there is enabled link */
> +	for (i = 0; i < TVP5150_NUM_PADS - 1; i++) {
> +		if ((pad_state[i] == TVP5150_PAD_ACTIVE_COMPOSITE) ||
> +		    (pad_state[i] == TVP5150_PAD_ACTIVE_SVIDEO)) {
> +			active_pad = i;
> +			break;
> +		}
> +	}
> +
> +	dev_dbg(sd->dev, "link setup '%s':%d->'%s':%d[%d]",
> +		remote->entity->name, remote->index, local->entity->name,
> +		local->index, flags & MEDIA_LNK_FL_ENABLED);

Hmm... the remote is the connector, right? I would switch the
print message to point from the connector to tvp5150, as this is
the signal flow.

Btw, it would likely be better to call it "connector" or "conn_entity",
to make it clearer.

> +
> +	if (flags & MEDIA_LNK_FL_ENABLED) {
> +		/*
> +		 * Composite activation: all links must be inactive.
> +		 * Svideo activation: one link can be active if it is a svideo
> +		 * link. Return error in case of a active composite link or both
> +		 * svideo links are active.
> +		 */
> +		if (active_pad >= 0 && !is_svideo) {
> +			ret = -EBUSY;
> +			goto out;
> +		} else if (active_pad >= 0 && is_svideo &&
> +			   pad_state[active_pad] ==
> +			   TVP5150_PAD_ACTIVE_COMPOSITE) {
> +			ret = -EBUSY;
> +			goto out;
> +		} else if (active_pad >= 0) {
> +			/* check if 2nd svideo link is active too */
> +			for (i = 0; i < TVP5150_NUM_PADS - 1; i++) {
> +				if (pad_state[i] == TVP5150_PAD_ACTIVE_SVIDEO) {
> +					if (i != active_pad) {
> +						ret = -EBUSY;
> +						goto out;
> +					}
> +				}
> +			}
> +		}

That may require some additional discussions.

I guess this is not the way it should be. I mean, it should be possible
to change the routing while streaming, without disabling the video
output. That's the behavior that TV generic applications like tvtime,
xawtv, etc rely on.

So, probably, the right thing to do here is to disable the active_pad
and  enable the newer one, if there is an active pad.

This way, it would work both if the userspace first disables the link
and then enables a new one, or if it switches without explicitly
disabling the previous one.

> +
> +		dev_dbg(sd->dev, "Setting %d active [%s]\n", local->index,
> +			is_svideo ? "svideo": "composite");
> +		pad_state[local->index] = is_svideo ?
> +			TVP5150_PAD_ACTIVE_SVIDEO : TVP5150_PAD_ACTIVE_COMPOSITE;
> +
> +		if (is_svideo) {
> +			unsigned int active_link_cnt = 0;
> +
> +			/* enable svideo only if we have two active links */
> +			for (i = 0; i > TVP5150_NUM_PADS - 1; i++)
> +				if (pad_state[i] == TVP5150_PAD_ACTIVE_SVIDEO)
> +					active_link_cnt++;
> +			if (active_link_cnt == 2)
> +				tvp5150_s_routing(sd, TVP5150_SVIDEO,
> +						  TVP5150_NORMAL, 0);
> +		} else {
> +			tvp5150_s_routing(sd, local->index, TVP5150_NORMAL, 0);
> +		}
> +	} else {
> +		/*
> +		 * Svideo streams on two pads and user can disable AIP1A or
> +		 * AIP1B first. So check only if user wants to disable a not
> +		 * enabled composite pad.
> +		 */
> +		if (!is_svideo && active_pad != local->index)
> +				goto out;
> +
> +		dev_dbg(sd->dev, "going inactive\n");
> +		pad_state[local->index] = TVP5150_PAD_INACTIVE;
> +
> +		/*
> +		 * Output black screen for deselected input if TVP5150 variant
> +		 * supports this.
> +		 */
> +		if (is_svideo) {
> +			unsigned int inactive_link_cnt = 0;
> +
> +			/* disable svideo only if we have two inactive links */
> +			for (i = 0; i > TVP5150_NUM_PADS - 1; i++)
> +				if (pad_state[i] == TVP5150_PAD_INACTIVE)
> +					inactive_link_cnt++;
> +			if (inactive_link_cnt == 2)
> +				tvp5150_s_routing(sd, TVP5150_SVIDEO,
> +						  TVP5150_BLACK_SCREEN, 0);
> +
> +		} else {
> +			tvp5150_s_routing(sd, local->index,
> +					  TVP5150_BLACK_SCREEN, 0);
> +		}
> +	}
> +out:
> +	return ret;
> +}
> +
> +static const struct media_entity_operations tvp5150_sd_media_ops = {
> +	.link_setup = tvp5150_link_setup,
> +};
> +#endif
>  /****************************************************************************
>  			I2C Command
>   ****************************************************************************/
> @@ -1315,6 +1466,50 @@ static int tvp5150_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
>  	return 0;
>  }
>  
> +static int tvp5150_registered(struct v4l2_subdev *sd)
> +{
> +#ifdef CONFIG_MEDIA_CONTROLLER
> +	struct tvp5150 *decoder = to_tvp5150(sd);
> +	unsigned int i;
> +	int ret;
> +
> +	for (i = 0; i < decoder->connectors_num; i++) {
> +		struct media_entity *con = &decoder->connectors[i].ent;
> +		struct media_pad *pad = &decoder->connectors[i].pad;
> +		unsigned int port = decoder->connectors[i].port_num;
> +		bool is_svideo = decoder->connectors[i].is_svideo;
> +
> +		pad->flags = MEDIA_PAD_FL_SOURCE;
> +		ret = media_entity_pads_init(con, 1, pad);
> +		if (ret < 0)
> +			return ret;
> +
> +		ret = media_device_register_entity(sd->v4l2_dev->mdev, con);
> +		if (ret < 0)
> +			return ret;
> +
> +		ret = media_create_pad_link(con, 0, &sd->entity, port, 0);
> +		if (ret < 0) {
> +			media_device_unregister_entity(con);
> +			return ret;
> +		}
> +
> +		if (is_svideo) {
> +			/* svideo links to both aip1a and aip1b */
> +			ret = media_create_pad_link(con, 0, &sd->entity,
> +						    port + 1, 0);
> +			if (ret < 0) {
> +				media_device_unregister_entity(con);
> +				return ret;
> +			}
> +		}
> +
> +	}

IMO, it should route to the first available connector.

> +#endif
> +	return 0;
> +}
> +
> +
>  /* ----------------------------------------------------------------------- */
>  
>  static const struct v4l2_ctrl_ops tvp5150_ctrl_ops = {
> @@ -1368,6 +1563,10 @@ static const struct v4l2_subdev_ops tvp5150_ops = {
>  	.pad = &tvp5150_pad_ops,
>  };
>  
> +static const struct v4l2_subdev_internal_ops tvp5150_internal_ops = {
> +	.registered = tvp5150_registered,
> +};
> +
>  /****************************************************************************
>  			I2C Client & Driver
>   ****************************************************************************/
> @@ -1516,38 +1715,186 @@ static int tvp5150_init(struct i2c_client *c)
>  	return 0;
>  }
>  
> -static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np)
> +static int tvp5150_mc_init(struct v4l2_subdev *sd)
>  {
> -	struct v4l2_fwnode_endpoint bus_cfg;
> -	struct device_node *ep;
> -	unsigned int flags;
> -	int ret = 0;
> +#if defined(CONFIG_MEDIA_CONTROLLER)
> +	struct tvp5150 *decoder = to_tvp5150(sd);
> +	struct device *dev = decoder->sd.dev;
> +	unsigned int i;
> +	int ret;
>  
> -	ep = of_graph_get_next_endpoint(np, NULL);
> -	if (!ep)
> -		return -EINVAL;
> +	sd->entity.ops = &tvp5150_sd_media_ops;
> +	sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
>  
> -	ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &bus_cfg);
> -	if (ret)
> -		goto err;
> +	/* Initialize all TVP5150 pads */
> +	for (i = 0; i < TVP5150_NUM_PADS; i++) {
> +		if (i < TVP5150_NUM_PADS - 1) {
> +			decoder->pads[i].flags = MEDIA_PAD_FL_SINK;
> +			decoder->pads[i].sig_type = PAD_SIGNAL_ANALOG;
> +		} else {
> +			decoder->pads[i].flags = MEDIA_PAD_FL_SOURCE;
> +			decoder->pads[i].sig_type = PAD_SIGNAL_DV;
> +		}
> +	}
> +	ret = media_entity_pads_init(&sd->entity, TVP5150_NUM_PADS,
> +				     decoder->pads);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* in case of no oftree support */
> +	if (!decoder->endpoints[0])
> +		return 0;

Hmm...

> +
> +	/* Allocate and initialize all available input connectors */
> +	decoder->connectors = devm_kcalloc(dev, decoder->connectors_num,
> +					   sizeof(*decoder->connectors),
> +					   GFP_KERNEL);
> +	if (!decoder->connectors)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < decoder->connectors_num; i++) {
> +		struct device_node *rp;
> +		struct of_endpoint ep;
> +
> +		rp = of_graph_get_remote_port_parent(decoder->endpoints[i]);
> +		of_graph_parse_endpoint(decoder->endpoints[i], &ep);
> +		decoder->connectors[i].port_num = ep.port;
> +		decoder->connectors[i].is_svideo = !!of_device_is_compatible(rp,
> +							    "svideo-connector");
> +
> +		if (decoder->connectors[i].is_svideo)
> +			decoder->connectors[i].ent.function =
> +						MEDIA_ENT_F_CONN_SVIDEO;
> +		else
> +			decoder->connectors[i].ent.function =
> +						MEDIA_ENT_F_CONN_COMPOSITE;
> +
> +		decoder->connectors[i].ent.flags = MEDIA_ENT_FL_CONNECTOR;
> +		ret = of_property_read_string(rp, "label",
> +					      &decoder->connectors[i].ent.name);
> +		if (ret < 0)
> +			return ret;

I would prefer, instead, to have a separate routine for OF. I'll probably
use something like the above for the non-DT devices (e. g. the ones using
em28xx driver).

> +	}
> +#endif
> +	return 0;
> +}
> +
> +static bool tvp5150_valid_input(struct device_node *endpoint,
> +				unsigned int port, unsigned int id)

Please call it as tvp5150_of_valid_input(). We may need something similar
for devices based on em28xx (passing info via platform_data).

> +{
> +	struct device_node *rp = of_graph_get_remote_port_parent(endpoint);
> +	const char *input;
> +	int ret;
> +
> +	/* perform some basic checks needed for later mc_init */
> +	switch (port) {
> +	case TVP5150_PAD_AIP1A:
> +		/* svideo must be connected to endpoint@1  */
> +		ret = id ? of_device_is_compatible(rp, "svideo-connector") :
> +			   of_device_is_compatible(rp, "composite-video-connector");
> +		if (!ret)
> +			return false;
> +		break;
> +	case TVP5150_PAD_AIP1B:
> +		ret = of_device_is_compatible(rp, "composite-video-connector");
> +		if (!ret)
> +			return false;
> +		break;
> +	}
> +
> +	ret = of_property_read_string(rp, "label", &input);
> +	if (ret < 0)
> +		return false;
> +
> +	return true;
> +}
>  
> -	flags = bus_cfg.bus.parallel.flags;
> +static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np)
> +{
> +	struct device *dev = decoder->sd.dev;
> +	struct v4l2_fwnode_endpoint bus_cfg;
> +	struct device_node *ep_np;
> +	unsigned int flags;
> +	int ret, i = 0, in = 0;
> +	bool found = false;
>  
> -	if (bus_cfg.bus_type == V4L2_MBUS_PARALLEL &&
> -	    !(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH &&
> -	      flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH &&
> -	      flags & V4L2_MBUS_FIELD_EVEN_LOW)) {
> +	/* at least 1 output and 1 input */
> +	decoder->endpoints_num = of_graph_get_endpoint_count(np);
> +	if (decoder->endpoints_num < 2 || decoder->endpoints_num > 4) {
>  		ret = -EINVAL;
>  		goto err;
>  	}
>  
> -	decoder->mbus_type = bus_cfg.bus_type;
> +	for_each_endpoint_of_node(np, ep_np) {
> +		struct of_endpoint ep;
>  
> +		of_graph_parse_endpoint(ep_np, &ep);
> +		if (decoder->endpoints[i]) {
> +			/* this should never happen */
> +			dev_err(dev, "Invalid endpoint %pOF on port %d\n",
> +				ep.local_node, ep.port);
> +				ret = -EINVAL;
> +				goto err;
> +		}
> +
> +		switch (ep.port) {
> +		case TVP5150_PAD_AIP1A:
> +		case TVP5150_PAD_AIP1B:
> +			if (!tvp5150_valid_input(ep_np, ep.port, ep.id)) {
> +				dev_err(dev,
> +					"Invalid endpoint %pOF on port %d\n",
> +					ep.local_node, ep.port);
> +				ret = -EINVAL;
> +				goto err;
> +			}
> +			in++;
> +			break;
> +		case TVP5150_PAD_VID_OUT:
> +			ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_np),
> +							 &bus_cfg);
> +			if (ret)
> +				goto err;
> +
> +			flags = bus_cfg.bus.parallel.flags;
> +
> +			if (bus_cfg.bus_type == V4L2_MBUS_PARALLEL &&
> +			    !(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH &&
> +			      flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH &&
> +			      flags & V4L2_MBUS_FIELD_EVEN_LOW)) {
> +				ret = -EINVAL;
> +				goto err;
> +			}
> +
> +			decoder->mbus_type = bus_cfg.bus_type;
> +			break;
> +		default:
> +			dev_err(dev, "Invalid port %d for endpoint %pOF\n",
> +				ep.port, ep.local_node);
> +			ret = -EINVAL;
> +			goto err;
> +		}
> +
> +		of_node_get(ep_np);
> +		decoder->endpoints[i] = ep_np;
> +		i++;
> +
> +		found = true;
> +	}
> +
> +	decoder->connectors_num = in;
> +	return found ? 0 : -ENODEV;
>  err:
> -	of_node_put(ep);
>  	return ret;
>  }
>  
> +static void tvp5150_dt_cleanup(struct tvp5150 *decoder)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < TVP5150_NUM_PADS; i++)
> +		of_node_put(decoder->endpoints[i]);
> +}
> +
>  static const char * const tvp5150_test_patterns[2] = {
>  	"Disabled",
>  	"Black screen"
> @@ -1586,7 +1933,7 @@ static int tvp5150_probe(struct i2c_client *c,
>  		res = tvp5150_parse_dt(core, np);
>  		if (res) {
>  			dev_err(sd->dev, "DT parsing error: %d\n", res);
> -			return res;
> +			goto err_cleanup_dt;
>  		}
>  	} else {
>  		/* Default to BT.656 embedded sync */
> @@ -1594,25 +1941,16 @@ static int tvp5150_probe(struct i2c_client *c,
>  	}
>  
>  	v4l2_i2c_subdev_init(sd, c, &tvp5150_ops);
> +	sd->internal_ops = &tvp5150_internal_ops;
>  	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
>  
> -#if defined(CONFIG_MEDIA_CONTROLLER)
> -	core->pads[TVP5150_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
> -	core->pads[TVP5150_PAD_IF_INPUT].sig_type = PAD_SIGNAL_ANALOG;
> -	core->pads[TVP5150_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
> -	core->pads[TVP5150_PAD_VID_OUT].sig_type = PAD_SIGNAL_DV;
> -
> -	sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
> -
> -	res = media_entity_pads_init(&sd->entity, TVP5150_NUM_PADS, core->pads);
> -	if (res < 0)
> -		return res;
> -
> -#endif
> +	res = tvp5150_mc_init(sd);
> +	if (res)
> +		goto err_cleanup_dt;
>  
>  	res = tvp5150_detect_version(core);
>  	if (res < 0)
> -		return res;
> +		goto err_cleanup_dt;
>  
>  	core->norm = V4L2_STD_ALL;	/* Default is autodetect */
>  	core->detected_norm = V4L2_STD_UNKNOWN;
> @@ -1664,6 +2002,9 @@ static int tvp5150_probe(struct i2c_client *c,
>  err:
>  	v4l2_ctrl_handler_free(&core->hdl);
>  	return res;
> +err_cleanup_dt:
> +	tvp5150_dt_cleanup(core);
> +	return res;
>  }
>  
>  static int tvp5150_remove(struct i2c_client *c)



Thanks,
Mauro

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

* Re: [PATCH 19/22] [media] tvp5150: add input source selection of_graph support
  2018-08-08 18:52       ` Mauro Carvalho Chehab
@ 2018-08-09 12:55         ` Marco Felsch
  2018-08-09 13:36           ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 70+ messages in thread
From: Marco Felsch @ 2018-08-09 12:55 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Hi Mauro,

On 18-08-08 15:52, Mauro Carvalho Chehab wrote:
> Em Wed, 8 Aug 2018 17:29:49 +0200
> Marco Felsch <m.felsch@pengutronix.de> escreveu:
> 
> > Hi Mauro,
> > 
> > the discussion about the correct binding was spread around some patches.
> > So I will try use the correct thread for that theme. I did my rework for
> > the of_graph support on your suggestions [1] and [2]. I attached my work
> > as RFC patch. Can you review it, so I can prepare a v2?
> > 
> > [1] https://www.spinics.net/lists/linux-media/msg138545.html
> > [2] https://www.spinics.net/lists/linux-media/msg138546.html
> 
> Thanks for the patch.
> 
> Added my comments below.

Thanks for your quick response.

I integrated the most of your comments and added some more comments below.

> 
> > 
> > On 18-07-30 15:29, Mauro Carvalho Chehab wrote:
> > > Em Thu, 28 Jun 2018 18:20:51 +0200
> > > Marco Felsch <m.felsch@pengutronix.de> escreveu:
> > > 
> > > > The currrent driver layout had the following layout:
> > > >                +----------------+
> > > >  +-------+     |    TVP5150     |
> > > >  | Comp0 +--+  |                |
> > > >  +-------+  |  |          +-----+
> > > >  +-------+  |  +------+   | Src |
> > > >  | Comp1 +--+--|Sink  |   +-----+
> > > >  +-------+  |  +------+   +-----+
> > > > +--------+  |  |          | Src |
> > > > | SVideo +--+  |          +-----+
> > > > +--------+     +----------------+
> > > > 
> > > > Since the device tree abstracts the real hardware this layout is not
> > > > correct, because the TVP5150 has 3 physical ports (2 input, 1 output).
> > > > Furthermore this layout assumes that there is an additional external mux
> > > > in front of the TVP5150. This is not correct because the TVP5150 does
> > > > the muxing work. The corresponding of_graph layout will look like:
> > > > 	tvp5150 {
> > > > 		....
> > > > 		port {
> > > > 			reg = <0>;
> > > > 			endpoint@0 {...};
> > > > 			endpoint@1 {...};
> > > > 			endpoint@2 {...};
> > > > 		};
> > > > 
> > > > 	};
> > > > 
> > > > This patch change the layout to:
> > > >              +----------------+
> > > >              |    TVP5150     |
> > > >  +-------+   +------+         |
> > > >  | Comp0 +---+ Sink |         |
> > > >  +-------+   +------+         |
> > > >  +-------+   +------+   +-----+
> > > >  | Comp1 +---+ Sink |   | Src |
> > > >  +-------+   +------+   +-----+
> > > > +--------+   +------+         |
> > > > | SVideo +---+ Sink |         |
> > > > +--------+   +------+         |
> > > >              +----------------+
> > > > 
> > > > To keep things easy an additional 'virtual' S-Video port is added. More
> > > > information about the port mapping can be found in the device tree
> > > > binding documentation. The connector entities Comp0/1, SVideo are created
> > > > only if they are connected to the correct port. If more than one connector
> > > > is available the media_entity_operations.link_setup() callback ensures that
> > > > only one connector is active. To change the input src the link between
> > > > the TVP5150 pad and the connector must be disabled, then a new link can
> > > > be enabled.
> > > > 
> > > > The patch tries to reduce the '#ifdef CONFIG_MEDIA_CONTROLLER' usage to
> > > > a minimum.
> > > > 
> > > > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > > > ---
> > > >  drivers/media/i2c/tvp5150.c | 322 ++++++++++++++++++++++++++++++++----
> > > >  1 file changed, 287 insertions(+), 35 deletions(-)
> > > > 
> > > > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > > > index a6fec569a610..6ac29c62d99b 100644
> > > > --- a/drivers/media/i2c/tvp5150.c
> > > > +++ b/drivers/media/i2c/tvp5150.c
> > > > @@ -44,10 +44,30 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
> > > >  
> > > >  #define dprintk0(__dev, __arg...) dev_dbg_lvl(__dev, 0, 0, __arg)
> > > >  
> > > > +enum tvp5150_ports {
> > > > +	TVP5150_PORT_AIP1A = TVP5150_COMPOSITE0,
> > > > +	TVP5150_PORT_AIP1B,
> > > > +	/* s-video port is a virtual port */
> > > > +	TVP5150_PORT_SVIDEO,
> > > > +	TVP5150_PORT_YOUT,
> > > > +	TVP5150_PORT_NUM,
> > > > +};
> > > > +
> > > > +#ifdef CONFIG_MEDIA_CONTROLLER
> > > > +struct tvp5150_connector {
> > > > +	struct media_entity con;
> > > > +	struct media_pad pad;
> > > > +	unsigned int port_num;
> > > > +};
> > > > +#endif
> > > > +
> > > >  struct tvp5150 {
> > > >  	struct v4l2_subdev sd;
> > > > +	struct device_node *endpoints[TVP5150_PORT_NUM];
> > > >  #ifdef CONFIG_MEDIA_CONTROLLER
> > > > -	struct media_pad pads[DEMOD_NUM_PADS];
> > > > +	struct media_pad pads[TVP5150_PORT_NUM];
> > > 
> > > This will cause problems with the current code.
> > > 
> > > When we designed the MC version 2 code, the idea were to allow
> > > set properties to entities and to the inputs, but the code
> > > was never submitted upstream.
> > > 
> > > A decoder may have several different types of inputs and outputs.
> > > Several designs allow using different types of decoders, being
> > > saa711x and tvp5150 the most popular ones. Well, depending on
> > > the device, the number of PADs and the signals they carry can
> > > be different.
> > > 
> > > Without a way to "taint" a pad to the signal it contains, 
> > > while waiting for the properties API, we added a code that
> > > "fixed" the PADs to a certain number. This way, Kernelspace could
> > > use the pad "number" as a way to identify the type of signal a
> > > PAD carries.
> > > 
> > > The PC consumer drivers use those numbers in order to build the
> > > MC graph[1].
> > > 
> > > A change on this would require adding a property to the pad, in
> > > order to indicate the type of signal it provides (RF, luminance IF,
> > > chroma IF, audio IF, I2S audio, ...), and to change
> > > v4l2_mc_create_media_graph() accordingly.
> > > 
> > > 
> > > [1] See drivers/media/v4l2-core/v4l2-mc.c at v4l2_mc_create_media_graph() func.
> > > 
> > > 
> > 
> > [ snip ]
> > 
> > From d3eb8a7de65fe2f8dd10ced85e4baca8e7898434 Mon Sep 17 00:00:00 2001
> > From: Marco Felsch <m.felsch@pengutronix.de>
> > Date: Thu, 28 Jun 2018 18:20:51 +0200
> > Subject: [RFC] [media] tvp5150: add input source selection of_graph
> >  support
> > 
> > This patch adds the of_graph support to describe the tvp connections.
> > Physical the TVP5150 has three ports: AIP1A, AIP1B and YOUT. As result
> > of discussion [1],[2] the device-tree maps these ports 1:1 with one
> > deviation. The svideo connector must be conneted to port@0/endpoint@1,
> > look at the Documentation for more information. Since the TVP5150 is a
> > converter the device-tree must contain at least 1-input and 1-output port.
> > The mc-connectors and mc-links are only created if the device-tree
> > contains the corresponding connector nodes. If more than one connector is
> > available the media_entity_operations.link_setup() callback ensures that
> > only one connector is active. To change the input src the active link must
> > disabled first, then a new link can be established.
> > 
> > [1] https://www.spinics.net/lists/linux-media/msg138545.html
> > [2] https://www.spinics.net/lists/linux-media/msg138546.html
> > 
> > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > 
> > ---
> > Changelog:
> > 
> > v2:
> > - adapt commit message
> > - mc: use 2-input and 1-output pad
> > - mc: enable svideo on tvp only if both tvp-input pads have a active
> >       link to the svideo src pad
> > - mc: disable svideo on tvp only if both tvp-input pads are inactive
> > - dt-support: drop svideo dt port
> > - dt-support: move svideo connector to port@0/endpoint@1
> > - dt-support: require at least 1-in and 1-out endpoint
> > ---
> >  drivers/media/i2c/tvp5150.c | 413 ++++++++++++++++++++++++++++++++----
> >  1 file changed, 377 insertions(+), 36 deletions(-)
> > 
> > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > index b5d44c25d1da..be755c5e63a9 100644
> > --- a/drivers/media/i2c/tvp5150.c
> > +++ b/drivers/media/i2c/tvp5150.c
> > @@ -43,16 +43,38 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
> >  
> >  #define dprintk0(__dev, __arg...) dev_dbg_lvl(__dev, 0, 0, __arg)
> >  
> > +#ifdef CONFIG_MEDIA_CONTROLLER
> >  enum tvp5150_pads {
> > -       TVP5150_PAD_IF_INPUT,
> > -       TVP5150_PAD_VID_OUT,
> > -       TVP5150_NUM_PADS
> > +	TVP5150_PAD_AIP1A = TVP5150_COMPOSITE0,
> > +	TVP5150_PAD_AIP1B,
> > +	TVP5150_PAD_VID_OUT,
> > +	TVP5150_NUM_PADS
> > +};
> > +
> > +enum tvp5150_pads_state {
> > +	TVP5150_PAD_INACTIVE,
> > +	TVP5150_PAD_ACTIVE_COMPOSITE,
> > +	TVP5150_PAD_ACTIVE_SVIDEO,
> > +};
> > +
> > +struct tvp5150_connector {
> > +	struct media_entity ent;
> > +	struct media_pad pad;
> > +	unsigned int port_num;
> > +	bool is_svideo;
> >  };
> > +#endif
> >  
> >  struct tvp5150 {
> >  	struct v4l2_subdev sd;
> > +	/* additional additional endpoint for the svideo connector */
> > +	struct device_node *endpoints[TVP5150_NUM_PADS + 1];
> > +	unsigned int endpoints_num;
> >  #ifdef CONFIG_MEDIA_CONTROLLER
> >  	struct media_pad pads[TVP5150_NUM_PADS];
> > +	int pads_state[TVP5150_NUM_PADS];
> > +	struct tvp5150_connector *connectors;
> > +	int connectors_num;
> >  #endif
> >  	struct v4l2_ctrl_handler hdl;
> >  	struct v4l2_rect rect;
> > @@ -1168,6 +1190,135 @@ static int tvp5150_enum_frame_size(struct v4l2_subdev *sd,
> >  	return 0;
> >  }
> >  
> > +/****************************************************************************
> > + *			Media entity ops
> > + ****************************************************************************/
> > +#ifdef CONFIG_MEDIA_CONTROLLER
> > +static int tvp5150_s_routing(struct v4l2_subdev *sd, u32 input, u32 output,
> > +			     u32 config);
> > +static int tvp5150_link_setup(struct media_entity *entity,
> > +			      const struct media_pad *local,
> > +			      const struct media_pad *remote, u32 flags)
> > +{
> > +	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
> > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > +	int *pad_state = &decoder->pads_state[0];
> > +	int i, ret = 0, active_pad = -1;
> > +	bool is_svideo = false;
> > +
> > +	/*
> > +	 * The tvp state is determined by the enabled sink pad link.
> > +	 * Enabling or disabling the source pad link has no effect.
> > +	 */
> > +	if (local->flags & MEDIA_PAD_FL_SOURCE)
> > +		return 0;
> > +
> > +	/* check if the svideo connector should be enabled */
> > +	for (i = 0; i < decoder->connectors_num; i++) {
> > +		if (remote->entity == &decoder->connectors[i].ent) {
> > +			is_svideo = decoder->connectors[i].is_svideo;
> > +			break;
> > +		}
> > +	}
> > +
> > +	/* check if there is enabled link */
> > +	for (i = 0; i < TVP5150_NUM_PADS - 1; i++) {
> > +		if ((pad_state[i] == TVP5150_PAD_ACTIVE_COMPOSITE) ||
> > +		    (pad_state[i] == TVP5150_PAD_ACTIVE_SVIDEO)) {
> > +			active_pad = i;
> > +			break;
> > +		}
> > +	}
> > +
> > +	dev_dbg(sd->dev, "link setup '%s':%d->'%s':%d[%d]",
> > +		remote->entity->name, remote->index, local->entity->name,
> > +		local->index, flags & MEDIA_LNK_FL_ENABLED);
> 
> Hmm... the remote is the connector, right? I would switch the
> print message to point from the connector to tvp5150, as this is
> the signal flow.

I don't know what you mean, I tought that's what I'm already do. If I
change it it will print something like: tvp5150 2-005d :0 -> Comp0 :0[1]

> 
> Btw, it would likely be better to call it "connector" or "conn_entity",
> to make it clearer.

I tought remote is the common nomenclature. Also the remote mustn't be a
connector. In my case it's a soldered camera. With this in mind, you think
it should be still changed?

> 
> > +
> > +	if (flags & MEDIA_LNK_FL_ENABLED) {
> > +		/*
> > +		 * Composite activation: all links must be inactive.
> > +		 * Svideo activation: one link can be active if it is a svideo
> > +		 * link. Return error in case of a active composite link or both
> > +		 * svideo links are active.
> > +		 */
> > +		if (active_pad >= 0 && !is_svideo) {
> > +			ret = -EBUSY;
> > +			goto out;
> > +		} else if (active_pad >= 0 && is_svideo &&
> > +			   pad_state[active_pad] ==
> > +			   TVP5150_PAD_ACTIVE_COMPOSITE) {
> > +			ret = -EBUSY;
> > +			goto out;
> > +		} else if (active_pad >= 0) {
> > +			/* check if 2nd svideo link is active too */
> > +			for (i = 0; i < TVP5150_NUM_PADS - 1; i++) {
> > +				if (pad_state[i] == TVP5150_PAD_ACTIVE_SVIDEO) {
> > +					if (i != active_pad) {
> > +						ret = -EBUSY;
> > +						goto out;
> > +					}
> > +				}
> > +			}
> > +		}
> 
> That may require some additional discussions.
> 
> I guess this is not the way it should be. I mean, it should be possible
> to change the routing while streaming, without disabling the video
> output. That's the behavior that TV generic applications like tvtime,
> xawtv, etc rely on.
> 
> So, probably, the right thing to do here is to disable the active_pad
> and  enable the newer one, if there is an active pad.
> 
> This way, it would work both if the userspace first disables the link
> and then enables a new one, or if it switches without explicitly
> disabling the previous one.

Okay I change this behaviour.

> 
> > +
> > +		dev_dbg(sd->dev, "Setting %d active [%s]\n", local->index,
> > +			is_svideo ? "svideo": "composite");
> > +		pad_state[local->index] = is_svideo ?
> > +			TVP5150_PAD_ACTIVE_SVIDEO : TVP5150_PAD_ACTIVE_COMPOSITE;
> > +
> > +		if (is_svideo) {
> > +			unsigned int active_link_cnt = 0;
> > +
> > +			/* enable svideo only if we have two active links */
> > +			for (i = 0; i > TVP5150_NUM_PADS - 1; i++)
> > +				if (pad_state[i] == TVP5150_PAD_ACTIVE_SVIDEO)
> > +					active_link_cnt++;
> > +			if (active_link_cnt == 2)
> > +				tvp5150_s_routing(sd, TVP5150_SVIDEO,
> > +						  TVP5150_NORMAL, 0);
> > +		} else {
> > +			tvp5150_s_routing(sd, local->index, TVP5150_NORMAL, 0);
> > +		}
> > +	} else {
> > +		/*
> > +		 * Svideo streams on two pads and user can disable AIP1A or
> > +		 * AIP1B first. So check only if user wants to disable a not
> > +		 * enabled composite pad.
> > +		 */
> > +		if (!is_svideo && active_pad != local->index)
> > +				goto out;
> > +
> > +		dev_dbg(sd->dev, "going inactive\n");
> > +		pad_state[local->index] = TVP5150_PAD_INACTIVE;
> > +
> > +		/*
> > +		 * Output black screen for deselected input if TVP5150 variant
> > +		 * supports this.
> > +		 */
> > +		if (is_svideo) {
> > +			unsigned int inactive_link_cnt = 0;
> > +
> > +			/* disable svideo only if we have two inactive links */
> > +			for (i = 0; i > TVP5150_NUM_PADS - 1; i++)
> > +				if (pad_state[i] == TVP5150_PAD_INACTIVE)
> > +					inactive_link_cnt++;
> > +			if (inactive_link_cnt == 2)
> > +				tvp5150_s_routing(sd, TVP5150_SVIDEO,
> > +						  TVP5150_BLACK_SCREEN, 0);
> > +
> > +		} else {
> > +			tvp5150_s_routing(sd, local->index,
> > +					  TVP5150_BLACK_SCREEN, 0);
> > +		}
> > +	}
> > +out:
> > +	return ret;
> > +}
> > +
> > +static const struct media_entity_operations tvp5150_sd_media_ops = {
> > +	.link_setup = tvp5150_link_setup,
> > +};
> > +#endif
> >  /****************************************************************************
> >  			I2C Command
> >   ****************************************************************************/
> > @@ -1315,6 +1466,50 @@ static int tvp5150_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
> >  	return 0;
> >  }
> >  
> > +static int tvp5150_registered(struct v4l2_subdev *sd)
> > +{
> > +#ifdef CONFIG_MEDIA_CONTROLLER
> > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > +	unsigned int i;
> > +	int ret;
> > +
> > +	for (i = 0; i < decoder->connectors_num; i++) {
> > +		struct media_entity *con = &decoder->connectors[i].ent;
> > +		struct media_pad *pad = &decoder->connectors[i].pad;
> > +		unsigned int port = decoder->connectors[i].port_num;
> > +		bool is_svideo = decoder->connectors[i].is_svideo;
> > +
> > +		pad->flags = MEDIA_PAD_FL_SOURCE;
> > +		ret = media_entity_pads_init(con, 1, pad);
> > +		if (ret < 0)
> > +			return ret;
> > +
> > +		ret = media_device_register_entity(sd->v4l2_dev->mdev, con);
> > +		if (ret < 0)
> > +			return ret;
> > +
> > +		ret = media_create_pad_link(con, 0, &sd->entity, port, 0);
> > +		if (ret < 0) {
> > +			media_device_unregister_entity(con);
> > +			return ret;
> > +		}
> > +
> > +		if (is_svideo) {
> > +			/* svideo links to both aip1a and aip1b */
> > +			ret = media_create_pad_link(con, 0, &sd->entity,
> > +						    port + 1, 0);
> > +			if (ret < 0) {
> > +				media_device_unregister_entity(con);
> > +				return ret;
> > +			}
> > +		}
> > +
> > +	}
> 
> IMO, it should route to the first available connector.

Did you mean to set the link status to enabled? If so I have one
question else can you tell me what you mean?

Should I use the media_entity_setup_link() helper or should I mark it as
enabled during media_create_pad_link()? Now I did something like:

if (i == 0) {
	list_for_each_entry(link, &con->links, list) {
		media_entity_setup_link(link, MEDIA_LNK_FL_ENABLED);
	}
}

> 
> > +#endif
> > +	return 0;
> > +}
> > +
> > +
> >  /* ----------------------------------------------------------------------- */
> >  
> >  static const struct v4l2_ctrl_ops tvp5150_ctrl_ops = {
> > @@ -1368,6 +1563,10 @@ static const struct v4l2_subdev_ops tvp5150_ops = {
> >  	.pad = &tvp5150_pad_ops,
> >  };
> >  
> > +static const struct v4l2_subdev_internal_ops tvp5150_internal_ops = {
> > +	.registered = tvp5150_registered,
> > +};
> > +
> >  /****************************************************************************
> >  			I2C Client & Driver
> >   ****************************************************************************/
> > @@ -1516,38 +1715,186 @@ static int tvp5150_init(struct i2c_client *c)
> >  	return 0;
> >  }
> >  
> > -static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np)
> > +static int tvp5150_mc_init(struct v4l2_subdev *sd)
> >  {
> > -	struct v4l2_fwnode_endpoint bus_cfg;
> > -	struct device_node *ep;
> > -	unsigned int flags;
> > -	int ret = 0;
> > +#if defined(CONFIG_MEDIA_CONTROLLER)
> > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > +	struct device *dev = decoder->sd.dev;
> > +	unsigned int i;
> > +	int ret;
> >  
> > -	ep = of_graph_get_next_endpoint(np, NULL);
> > -	if (!ep)
> > -		return -EINVAL;
> > +	sd->entity.ops = &tvp5150_sd_media_ops;
> > +	sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
> >  
> > -	ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &bus_cfg);
> > -	if (ret)
> > -		goto err;
> > +	/* Initialize all TVP5150 pads */
> > +	for (i = 0; i < TVP5150_NUM_PADS; i++) {
> > +		if (i < TVP5150_NUM_PADS - 1) {
> > +			decoder->pads[i].flags = MEDIA_PAD_FL_SINK;
> > +			decoder->pads[i].sig_type = PAD_SIGNAL_ANALOG;
> > +		} else {
> > +			decoder->pads[i].flags = MEDIA_PAD_FL_SOURCE;
> > +			decoder->pads[i].sig_type = PAD_SIGNAL_DV;
> > +		}
> > +	}
> > +	ret = media_entity_pads_init(&sd->entity, TVP5150_NUM_PADS,
> > +				     decoder->pads);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	/* in case of no oftree support */
> > +	if (!decoder->endpoints[0])
> > +		return 0;
> 
> Hmm...
> 
> > +
> > +	/* Allocate and initialize all available input connectors */
> > +	decoder->connectors = devm_kcalloc(dev, decoder->connectors_num,
> > +					   sizeof(*decoder->connectors),
> > +					   GFP_KERNEL);
> > +	if (!decoder->connectors)
> > +		return -ENOMEM;
> > +
> > +	for (i = 0; i < decoder->connectors_num; i++) {
> > +		struct device_node *rp;
> > +		struct of_endpoint ep;
> > +
> > +		rp = of_graph_get_remote_port_parent(decoder->endpoints[i]);
> > +		of_graph_parse_endpoint(decoder->endpoints[i], &ep);
> > +		decoder->connectors[i].port_num = ep.port;
> > +		decoder->connectors[i].is_svideo = !!of_device_is_compatible(rp,
> > +							    "svideo-connector");
> > +
> > +		if (decoder->connectors[i].is_svideo)
> > +			decoder->connectors[i].ent.function =
> > +						MEDIA_ENT_F_CONN_SVIDEO;
> > +		else
> > +			decoder->connectors[i].ent.function =
> > +						MEDIA_ENT_F_CONN_COMPOSITE;
> > +
> > +		decoder->connectors[i].ent.flags = MEDIA_ENT_FL_CONNECTOR;
> > +		ret = of_property_read_string(rp, "label",
> > +					      &decoder->connectors[i].ent.name);
> > +		if (ret < 0)
> > +			return ret;
> 
> I would prefer, instead, to have a separate routine for OF. I'll probably
> use something like the above for the non-DT devices (e. g. the ones using
> em28xx driver).

Okay, I refactored it.

> 
> > +	}
> > +#endif
> > +	return 0;
> > +}
> > +
> > +static bool tvp5150_valid_input(struct device_node *endpoint,
> > +				unsigned int port, unsigned int id)
> 
> Please call it as tvp5150_of_valid_input(). We may need something similar
> for devices based on em28xx (passing info via platform_data).

Okay, I changed it.

> 
> > +{
> > +	struct device_node *rp = of_graph_get_remote_port_parent(endpoint);
> > +	const char *input;
> > +	int ret;
> > +
> > +	/* perform some basic checks needed for later mc_init */
> > +	switch (port) {
> > +	case TVP5150_PAD_AIP1A:
> > +		/* svideo must be connected to endpoint@1  */
> > +		ret = id ? of_device_is_compatible(rp, "svideo-connector") :
> > +			   of_device_is_compatible(rp, "composite-video-connector");
> > +		if (!ret)
> > +			return false;
> > +		break;
> > +	case TVP5150_PAD_AIP1B:
> > +		ret = of_device_is_compatible(rp, "composite-video-connector");
> > +		if (!ret)
> > +			return false;
> > +		break;
> > +	}
> > +
> > +	ret = of_property_read_string(rp, "label", &input);
> > +	if (ret < 0)
> > +		return false;
> > +
> > +	return true;
> > +}
> >  
> > -	flags = bus_cfg.bus.parallel.flags;
> > +static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np)
> > +{
> > +	struct device *dev = decoder->sd.dev;
> > +	struct v4l2_fwnode_endpoint bus_cfg;
> > +	struct device_node *ep_np;
> > +	unsigned int flags;
> > +	int ret, i = 0, in = 0;
> > +	bool found = false;
> >  
> > -	if (bus_cfg.bus_type == V4L2_MBUS_PARALLEL &&
> > -	    !(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH &&
> > -	      flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH &&
> > -	      flags & V4L2_MBUS_FIELD_EVEN_LOW)) {
> > +	/* at least 1 output and 1 input */
> > +	decoder->endpoints_num = of_graph_get_endpoint_count(np);
> > +	if (decoder->endpoints_num < 2 || decoder->endpoints_num > 4) {
> >  		ret = -EINVAL;
> >  		goto err;
> >  	}
> >  
> > -	decoder->mbus_type = bus_cfg.bus_type;
> > +	for_each_endpoint_of_node(np, ep_np) {
> > +		struct of_endpoint ep;
> >  
> > +		of_graph_parse_endpoint(ep_np, &ep);
> > +		if (decoder->endpoints[i]) {
> > +			/* this should never happen */
> > +			dev_err(dev, "Invalid endpoint %pOF on port %d\n",
> > +				ep.local_node, ep.port);
> > +				ret = -EINVAL;
> > +				goto err;
> > +		}
> > +
> > +		switch (ep.port) {
> > +		case TVP5150_PAD_AIP1A:
> > +		case TVP5150_PAD_AIP1B:
> > +			if (!tvp5150_valid_input(ep_np, ep.port, ep.id)) {
> > +				dev_err(dev,
> > +					"Invalid endpoint %pOF on port %d\n",
> > +					ep.local_node, ep.port);
> > +				ret = -EINVAL;
> > +				goto err;
> > +			}
> > +			in++;
> > +			break;
> > +		case TVP5150_PAD_VID_OUT:
> > +			ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_np),
> > +							 &bus_cfg);
> > +			if (ret)
> > +				goto err;
> > +
> > +			flags = bus_cfg.bus.parallel.flags;
> > +
> > +			if (bus_cfg.bus_type == V4L2_MBUS_PARALLEL &&
> > +			    !(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH &&
> > +			      flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH &&
> > +			      flags & V4L2_MBUS_FIELD_EVEN_LOW)) {
> > +				ret = -EINVAL;
> > +				goto err;
> > +			}
> > +
> > +			decoder->mbus_type = bus_cfg.bus_type;
> > +			break;
> > +		default:
> > +			dev_err(dev, "Invalid port %d for endpoint %pOF\n",
> > +				ep.port, ep.local_node);
> > +			ret = -EINVAL;
> > +			goto err;
> > +		}
> > +
> > +		of_node_get(ep_np);
> > +		decoder->endpoints[i] = ep_np;
> > +		i++;
> > +
> > +		found = true;
> > +	}
> > +
> > +	decoder->connectors_num = in;
> > +	return found ? 0 : -ENODEV;
> >  err:
> > -	of_node_put(ep);
> >  	return ret;
> >  }
> >  
> > +static void tvp5150_dt_cleanup(struct tvp5150 *decoder)
> > +{
> > +	unsigned int i;
> > +
> > +	for (i = 0; i < TVP5150_NUM_PADS; i++)
> > +		of_node_put(decoder->endpoints[i]);
> > +}
> > +
> >  static const char * const tvp5150_test_patterns[2] = {
> >  	"Disabled",
> >  	"Black screen"
> > @@ -1586,7 +1933,7 @@ static int tvp5150_probe(struct i2c_client *c,
> >  		res = tvp5150_parse_dt(core, np);
> >  		if (res) {
> >  			dev_err(sd->dev, "DT parsing error: %d\n", res);
> > -			return res;
> > +			goto err_cleanup_dt;
> >  		}
> >  	} else {
> >  		/* Default to BT.656 embedded sync */
> > @@ -1594,25 +1941,16 @@ static int tvp5150_probe(struct i2c_client *c,
> >  	}
> >  
> >  	v4l2_i2c_subdev_init(sd, c, &tvp5150_ops);
> > +	sd->internal_ops = &tvp5150_internal_ops;
> >  	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
> >  
> > -#if defined(CONFIG_MEDIA_CONTROLLER)
> > -	core->pads[TVP5150_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
> > -	core->pads[TVP5150_PAD_IF_INPUT].sig_type = PAD_SIGNAL_ANALOG;
> > -	core->pads[TVP5150_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
> > -	core->pads[TVP5150_PAD_VID_OUT].sig_type = PAD_SIGNAL_DV;
> > -
> > -	sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
> > -
> > -	res = media_entity_pads_init(&sd->entity, TVP5150_NUM_PADS, core->pads);
> > -	if (res < 0)
> > -		return res;
> > -
> > -#endif
> > +	res = tvp5150_mc_init(sd);
> > +	if (res)
> > +		goto err_cleanup_dt;
> >  
> >  	res = tvp5150_detect_version(core);
> >  	if (res < 0)
> > -		return res;
> > +		goto err_cleanup_dt;
> >  
> >  	core->norm = V4L2_STD_ALL;	/* Default is autodetect */
> >  	core->detected_norm = V4L2_STD_UNKNOWN;
> > @@ -1664,6 +2002,9 @@ static int tvp5150_probe(struct i2c_client *c,
> >  err:
> >  	v4l2_ctrl_handler_free(&core->hdl);
> >  	return res;
> > +err_cleanup_dt:
> > +	tvp5150_dt_cleanup(core);
> > +	return res;
> >  }
> >  
> >  static int tvp5150_remove(struct i2c_client *c)
> 
> 
> 
> Thanks,
> Mauro

Regards,
Marco

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

* Re: [PATCH 19/22] [media] tvp5150: add input source selection of_graph support
  2018-08-09 12:55         ` Marco Felsch
@ 2018-08-09 13:36           ` Mauro Carvalho Chehab
  2018-08-09 14:35             ` Marco Felsch
  0 siblings, 1 reply; 70+ messages in thread
From: Mauro Carvalho Chehab @ 2018-08-09 13:36 UTC (permalink / raw)
  To: Marco Felsch
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Em Thu, 9 Aug 2018 14:55:07 +0200
Marco Felsch <m.felsch@pengutronix.de> escreveu:

> Hi Mauro,
> 
> On 18-08-08 15:52, Mauro Carvalho Chehab wrote:
> > Em Wed, 8 Aug 2018 17:29:49 +0200
> > Marco Felsch <m.felsch@pengutronix.de> escreveu:
> >   
> > > Hi Mauro,
> > > 
> > > the discussion about the correct binding was spread around some patches.
> > > So I will try use the correct thread for that theme. I did my rework for
> > > the of_graph support on your suggestions [1] and [2]. I attached my work
> > > as RFC patch. Can you review it, so I can prepare a v2?
> > > 
> > > [1] https://www.spinics.net/lists/linux-media/msg138545.html
> > > [2] https://www.spinics.net/lists/linux-media/msg138546.html  
> > 
> > Thanks for the patch.
> > 
> > Added my comments below.  
> 
> Thanks for your quick response.
> 
> I integrated the most of your comments and added some more comments below.
> 
> >   
> > > 
> > > On 18-07-30 15:29, Mauro Carvalho Chehab wrote:  
> > > > Em Thu, 28 Jun 2018 18:20:51 +0200
> > > > Marco Felsch <m.felsch@pengutronix.de> escreveu:
> > > >   
> > > > > The currrent driver layout had the following layout:
> > > > >                +----------------+
> > > > >  +-------+     |    TVP5150     |
> > > > >  | Comp0 +--+  |                |
> > > > >  +-------+  |  |          +-----+
> > > > >  +-------+  |  +------+   | Src |
> > > > >  | Comp1 +--+--|Sink  |   +-----+
> > > > >  +-------+  |  +------+   +-----+
> > > > > +--------+  |  |          | Src |
> > > > > | SVideo +--+  |          +-----+
> > > > > +--------+     +----------------+
> > > > > 
> > > > > Since the device tree abstracts the real hardware this layout is not
> > > > > correct, because the TVP5150 has 3 physical ports (2 input, 1 output).
> > > > > Furthermore this layout assumes that there is an additional external mux
> > > > > in front of the TVP5150. This is not correct because the TVP5150 does
> > > > > the muxing work. The corresponding of_graph layout will look like:
> > > > > 	tvp5150 {
> > > > > 		....
> > > > > 		port {
> > > > > 			reg = <0>;
> > > > > 			endpoint@0 {...};
> > > > > 			endpoint@1 {...};
> > > > > 			endpoint@2 {...};
> > > > > 		};
> > > > > 
> > > > > 	};
> > > > > 
> > > > > This patch change the layout to:
> > > > >              +----------------+
> > > > >              |    TVP5150     |
> > > > >  +-------+   +------+         |
> > > > >  | Comp0 +---+ Sink |         |
> > > > >  +-------+   +------+         |
> > > > >  +-------+   +------+   +-----+
> > > > >  | Comp1 +---+ Sink |   | Src |
> > > > >  +-------+   +------+   +-----+
> > > > > +--------+   +------+         |
> > > > > | SVideo +---+ Sink |         |
> > > > > +--------+   +------+         |
> > > > >              +----------------+
> > > > > 
> > > > > To keep things easy an additional 'virtual' S-Video port is added. More
> > > > > information about the port mapping can be found in the device tree
> > > > > binding documentation. The connector entities Comp0/1, SVideo are created
> > > > > only if they are connected to the correct port. If more than one connector
> > > > > is available the media_entity_operations.link_setup() callback ensures that
> > > > > only one connector is active. To change the input src the link between
> > > > > the TVP5150 pad and the connector must be disabled, then a new link can
> > > > > be enabled.
> > > > > 
> > > > > The patch tries to reduce the '#ifdef CONFIG_MEDIA_CONTROLLER' usage to
> > > > > a minimum.
> > > > > 
> > > > > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > > > > ---
> > > > >  drivers/media/i2c/tvp5150.c | 322 ++++++++++++++++++++++++++++++++----
> > > > >  1 file changed, 287 insertions(+), 35 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > > > > index a6fec569a610..6ac29c62d99b 100644
> > > > > --- a/drivers/media/i2c/tvp5150.c
> > > > > +++ b/drivers/media/i2c/tvp5150.c
> > > > > @@ -44,10 +44,30 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
> > > > >  
> > > > >  #define dprintk0(__dev, __arg...) dev_dbg_lvl(__dev, 0, 0, __arg)
> > > > >  
> > > > > +enum tvp5150_ports {
> > > > > +	TVP5150_PORT_AIP1A = TVP5150_COMPOSITE0,
> > > > > +	TVP5150_PORT_AIP1B,
> > > > > +	/* s-video port is a virtual port */
> > > > > +	TVP5150_PORT_SVIDEO,
> > > > > +	TVP5150_PORT_YOUT,
> > > > > +	TVP5150_PORT_NUM,
> > > > > +};
> > > > > +
> > > > > +#ifdef CONFIG_MEDIA_CONTROLLER
> > > > > +struct tvp5150_connector {
> > > > > +	struct media_entity con;
> > > > > +	struct media_pad pad;
> > > > > +	unsigned int port_num;
> > > > > +};
> > > > > +#endif
> > > > > +
> > > > >  struct tvp5150 {
> > > > >  	struct v4l2_subdev sd;
> > > > > +	struct device_node *endpoints[TVP5150_PORT_NUM];
> > > > >  #ifdef CONFIG_MEDIA_CONTROLLER
> > > > > -	struct media_pad pads[DEMOD_NUM_PADS];
> > > > > +	struct media_pad pads[TVP5150_PORT_NUM];  
> > > > 
> > > > This will cause problems with the current code.
> > > > 
> > > > When we designed the MC version 2 code, the idea were to allow
> > > > set properties to entities and to the inputs, but the code
> > > > was never submitted upstream.
> > > > 
> > > > A decoder may have several different types of inputs and outputs.
> > > > Several designs allow using different types of decoders, being
> > > > saa711x and tvp5150 the most popular ones. Well, depending on
> > > > the device, the number of PADs and the signals they carry can
> > > > be different.
> > > > 
> > > > Without a way to "taint" a pad to the signal it contains, 
> > > > while waiting for the properties API, we added a code that
> > > > "fixed" the PADs to a certain number. This way, Kernelspace could
> > > > use the pad "number" as a way to identify the type of signal a
> > > > PAD carries.
> > > > 
> > > > The PC consumer drivers use those numbers in order to build the
> > > > MC graph[1].
> > > > 
> > > > A change on this would require adding a property to the pad, in
> > > > order to indicate the type of signal it provides (RF, luminance IF,
> > > > chroma IF, audio IF, I2S audio, ...), and to change
> > > > v4l2_mc_create_media_graph() accordingly.
> > > > 
> > > > 
> > > > [1] See drivers/media/v4l2-core/v4l2-mc.c at v4l2_mc_create_media_graph() func.
> > > > 
> > > >   
> > > 
> > > [ snip ]
> > > 
> > > From d3eb8a7de65fe2f8dd10ced85e4baca8e7898434 Mon Sep 17 00:00:00 2001
> > > From: Marco Felsch <m.felsch@pengutronix.de>
> > > Date: Thu, 28 Jun 2018 18:20:51 +0200
> > > Subject: [RFC] [media] tvp5150: add input source selection of_graph
> > >  support
> > > 
> > > This patch adds the of_graph support to describe the tvp connections.
> > > Physical the TVP5150 has three ports: AIP1A, AIP1B and YOUT. As result
> > > of discussion [1],[2] the device-tree maps these ports 1:1 with one
> > > deviation. The svideo connector must be conneted to port@0/endpoint@1,
> > > look at the Documentation for more information. Since the TVP5150 is a
> > > converter the device-tree must contain at least 1-input and 1-output port.
> > > The mc-connectors and mc-links are only created if the device-tree
> > > contains the corresponding connector nodes. If more than one connector is
> > > available the media_entity_operations.link_setup() callback ensures that
> > > only one connector is active. To change the input src the active link must
> > > disabled first, then a new link can be established.
> > > 
> > > [1] https://www.spinics.net/lists/linux-media/msg138545.html
> > > [2] https://www.spinics.net/lists/linux-media/msg138546.html
> > > 
> > > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > > 
> > > ---
> > > Changelog:
> > > 
> > > v2:
> > > - adapt commit message
> > > - mc: use 2-input and 1-output pad
> > > - mc: enable svideo on tvp only if both tvp-input pads have a active
> > >       link to the svideo src pad
> > > - mc: disable svideo on tvp only if both tvp-input pads are inactive
> > > - dt-support: drop svideo dt port
> > > - dt-support: move svideo connector to port@0/endpoint@1
> > > - dt-support: require at least 1-in and 1-out endpoint
> > > ---
> > >  drivers/media/i2c/tvp5150.c | 413 ++++++++++++++++++++++++++++++++----
> > >  1 file changed, 377 insertions(+), 36 deletions(-)
> > > 
> > > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > > index b5d44c25d1da..be755c5e63a9 100644
> > > --- a/drivers/media/i2c/tvp5150.c
> > > +++ b/drivers/media/i2c/tvp5150.c
> > > @@ -43,16 +43,38 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
> > >  
> > >  #define dprintk0(__dev, __arg...) dev_dbg_lvl(__dev, 0, 0, __arg)
> > >  
> > > +#ifdef CONFIG_MEDIA_CONTROLLER
> > >  enum tvp5150_pads {
> > > -       TVP5150_PAD_IF_INPUT,
> > > -       TVP5150_PAD_VID_OUT,
> > > -       TVP5150_NUM_PADS
> > > +	TVP5150_PAD_AIP1A = TVP5150_COMPOSITE0,
> > > +	TVP5150_PAD_AIP1B,
> > > +	TVP5150_PAD_VID_OUT,
> > > +	TVP5150_NUM_PADS
> > > +};
> > > +
> > > +enum tvp5150_pads_state {
> > > +	TVP5150_PAD_INACTIVE,
> > > +	TVP5150_PAD_ACTIVE_COMPOSITE,
> > > +	TVP5150_PAD_ACTIVE_SVIDEO,
> > > +};
> > > +
> > > +struct tvp5150_connector {
> > > +	struct media_entity ent;
> > > +	struct media_pad pad;
> > > +	unsigned int port_num;
> > > +	bool is_svideo;
> > >  };
> > > +#endif
> > >  
> > >  struct tvp5150 {
> > >  	struct v4l2_subdev sd;
> > > +	/* additional additional endpoint for the svideo connector */
> > > +	struct device_node *endpoints[TVP5150_NUM_PADS + 1];
> > > +	unsigned int endpoints_num;
> > >  #ifdef CONFIG_MEDIA_CONTROLLER
> > >  	struct media_pad pads[TVP5150_NUM_PADS];
> > > +	int pads_state[TVP5150_NUM_PADS];
> > > +	struct tvp5150_connector *connectors;
> > > +	int connectors_num;
> > >  #endif
> > >  	struct v4l2_ctrl_handler hdl;
> > >  	struct v4l2_rect rect;
> > > @@ -1168,6 +1190,135 @@ static int tvp5150_enum_frame_size(struct v4l2_subdev *sd,
> > >  	return 0;
> > >  }
> > >  
> > > +/****************************************************************************
> > > + *			Media entity ops
> > > + ****************************************************************************/
> > > +#ifdef CONFIG_MEDIA_CONTROLLER
> > > +static int tvp5150_s_routing(struct v4l2_subdev *sd, u32 input, u32 output,
> > > +			     u32 config);
> > > +static int tvp5150_link_setup(struct media_entity *entity,
> > > +			      const struct media_pad *local,
> > > +			      const struct media_pad *remote, u32 flags)
> > > +{
> > > +	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
> > > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > > +	int *pad_state = &decoder->pads_state[0];
> > > +	int i, ret = 0, active_pad = -1;
> > > +	bool is_svideo = false;
> > > +
> > > +	/*
> > > +	 * The tvp state is determined by the enabled sink pad link.
> > > +	 * Enabling or disabling the source pad link has no effect.
> > > +	 */
> > > +	if (local->flags & MEDIA_PAD_FL_SOURCE)
> > > +		return 0;
> > > +
> > > +	/* check if the svideo connector should be enabled */
> > > +	for (i = 0; i < decoder->connectors_num; i++) {
> > > +		if (remote->entity == &decoder->connectors[i].ent) {
> > > +			is_svideo = decoder->connectors[i].is_svideo;
> > > +			break;
> > > +		}
> > > +	}
> > > +
> > > +	/* check if there is enabled link */
> > > +	for (i = 0; i < TVP5150_NUM_PADS - 1; i++) {
> > > +		if ((pad_state[i] == TVP5150_PAD_ACTIVE_COMPOSITE) ||
> > > +		    (pad_state[i] == TVP5150_PAD_ACTIVE_SVIDEO)) {
> > > +			active_pad = i;
> > > +			break;
> > > +		}
> > > +	}
> > > +
> > > +	dev_dbg(sd->dev, "link setup '%s':%d->'%s':%d[%d]",
> > > +		remote->entity->name, remote->index, local->entity->name,
> > > +		local->index, flags & MEDIA_LNK_FL_ENABLED);  
> > 
> > Hmm... the remote is the connector, right? I would switch the
> > print message to point from the connector to tvp5150, as this is
> > the signal flow.  
> 
> I don't know what you mean, I tought that's what I'm already do. If I
> change it it will print something like: tvp5150 2-005d :0 -> Comp0 :0[1]

Hmm... then "local" actually means the connector and "remote"
is the tvp5150?

> 
> > 
> > Btw, it would likely be better to call it "connector" or "conn_entity",
> > to make it clearer.  
> 
> I tought remote is the common nomenclature. Also the remote mustn't be a
> connector. In my case it's a soldered camera. With this in mind, you think
> it should be still changed?

I see your point.

Yeah, remote is a common nomenclature. Yet, as it can be seen from
the above comment (and your answer), common nomenclature may lead
in to mistakes :-)

It would be good to have either one of sides better named (either
the connectors side or the tvp5150 side - or both), in order to be
clearer and avoid confusion of someone else touches that part of
the code.

In this specific case, both connectors and tvp5150 are created by
the tvp5150, so both are "local" in the sense that both are
created by this driver.

> 
> >   
> > > +
> > > +	if (flags & MEDIA_LNK_FL_ENABLED) {
> > > +		/*
> > > +		 * Composite activation: all links must be inactive.
> > > +		 * Svideo activation: one link can be active if it is a svideo
> > > +		 * link. Return error in case of a active composite link or both
> > > +		 * svideo links are active.
> > > +		 */
> > > +		if (active_pad >= 0 && !is_svideo) {
> > > +			ret = -EBUSY;
> > > +			goto out;
> > > +		} else if (active_pad >= 0 && is_svideo &&
> > > +			   pad_state[active_pad] ==
> > > +			   TVP5150_PAD_ACTIVE_COMPOSITE) {
> > > +			ret = -EBUSY;
> > > +			goto out;
> > > +		} else if (active_pad >= 0) {
> > > +			/* check if 2nd svideo link is active too */
> > > +			for (i = 0; i < TVP5150_NUM_PADS - 1; i++) {
> > > +				if (pad_state[i] == TVP5150_PAD_ACTIVE_SVIDEO) {
> > > +					if (i != active_pad) {
> > > +						ret = -EBUSY;
> > > +						goto out;
> > > +					}
> > > +				}
> > > +			}
> > > +		}  
> > 
> > That may require some additional discussions.
> > 
> > I guess this is not the way it should be. I mean, it should be possible
> > to change the routing while streaming, without disabling the video
> > output. That's the behavior that TV generic applications like tvtime,
> > xawtv, etc rely on.
> > 
> > So, probably, the right thing to do here is to disable the active_pad
> > and  enable the newer one, if there is an active pad.
> > 
> > This way, it would work both if the userspace first disables the link
> > and then enables a new one, or if it switches without explicitly
> > disabling the previous one.  
> 
> Okay I change this behaviour.
> 
> >   
> > > +
> > > +		dev_dbg(sd->dev, "Setting %d active [%s]\n", local->index,
> > > +			is_svideo ? "svideo": "composite");
> > > +		pad_state[local->index] = is_svideo ?
> > > +			TVP5150_PAD_ACTIVE_SVIDEO : TVP5150_PAD_ACTIVE_COMPOSITE;
> > > +
> > > +		if (is_svideo) {
> > > +			unsigned int active_link_cnt = 0;
> > > +
> > > +			/* enable svideo only if we have two active links */
> > > +			for (i = 0; i > TVP5150_NUM_PADS - 1; i++)
> > > +				if (pad_state[i] == TVP5150_PAD_ACTIVE_SVIDEO)
> > > +					active_link_cnt++;
> > > +			if (active_link_cnt == 2)
> > > +				tvp5150_s_routing(sd, TVP5150_SVIDEO,
> > > +						  TVP5150_NORMAL, 0);
> > > +		} else {
> > > +			tvp5150_s_routing(sd, local->index, TVP5150_NORMAL, 0);
> > > +		}
> > > +	} else {
> > > +		/*
> > > +		 * Svideo streams on two pads and user can disable AIP1A or
> > > +		 * AIP1B first. So check only if user wants to disable a not
> > > +		 * enabled composite pad.
> > > +		 */
> > > +		if (!is_svideo && active_pad != local->index)
> > > +				goto out;
> > > +
> > > +		dev_dbg(sd->dev, "going inactive\n");
> > > +		pad_state[local->index] = TVP5150_PAD_INACTIVE;
> > > +
> > > +		/*
> > > +		 * Output black screen for deselected input if TVP5150 variant
> > > +		 * supports this.
> > > +		 */
> > > +		if (is_svideo) {
> > > +			unsigned int inactive_link_cnt = 0;
> > > +
> > > +			/* disable svideo only if we have two inactive links */
> > > +			for (i = 0; i > TVP5150_NUM_PADS - 1; i++)
> > > +				if (pad_state[i] == TVP5150_PAD_INACTIVE)
> > > +					inactive_link_cnt++;
> > > +			if (inactive_link_cnt == 2)
> > > +				tvp5150_s_routing(sd, TVP5150_SVIDEO,
> > > +						  TVP5150_BLACK_SCREEN, 0);
> > > +
> > > +		} else {
> > > +			tvp5150_s_routing(sd, local->index,
> > > +					  TVP5150_BLACK_SCREEN, 0);
> > > +		}
> > > +	}
> > > +out:
> > > +	return ret;
> > > +}
> > > +
> > > +static const struct media_entity_operations tvp5150_sd_media_ops = {
> > > +	.link_setup = tvp5150_link_setup,
> > > +};
> > > +#endif
> > >  /****************************************************************************
> > >  			I2C Command
> > >   ****************************************************************************/
> > > @@ -1315,6 +1466,50 @@ static int tvp5150_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
> > >  	return 0;
> > >  }
> > >  
> > > +static int tvp5150_registered(struct v4l2_subdev *sd)
> > > +{
> > > +#ifdef CONFIG_MEDIA_CONTROLLER
> > > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > > +	unsigned int i;
> > > +	int ret;
> > > +
> > > +	for (i = 0; i < decoder->connectors_num; i++) {
> > > +		struct media_entity *con = &decoder->connectors[i].ent;
> > > +		struct media_pad *pad = &decoder->connectors[i].pad;
> > > +		unsigned int port = decoder->connectors[i].port_num;
> > > +		bool is_svideo = decoder->connectors[i].is_svideo;
> > > +
> > > +		pad->flags = MEDIA_PAD_FL_SOURCE;
> > > +		ret = media_entity_pads_init(con, 1, pad);
> > > +		if (ret < 0)
> > > +			return ret;
> > > +
> > > +		ret = media_device_register_entity(sd->v4l2_dev->mdev, con);
> > > +		if (ret < 0)
> > > +			return ret;
> > > +
> > > +		ret = media_create_pad_link(con, 0, &sd->entity, port, 0);
> > > +		if (ret < 0) {
> > > +			media_device_unregister_entity(con);
> > > +			return ret;
> > > +		}
> > > +
> > > +		if (is_svideo) {
> > > +			/* svideo links to both aip1a and aip1b */
> > > +			ret = media_create_pad_link(con, 0, &sd->entity,
> > > +						    port + 1, 0);
> > > +			if (ret < 0) {
> > > +				media_device_unregister_entity(con);
> > > +				return ret;
> > > +			}
> > > +		}
> > > +
> > > +	}  
> > 
> > IMO, it should route to the first available connector.  
> 
> Did you mean to set the link status to enabled? 

Yes.

> If so I have one
> question else can you tell me what you mean?
> 
> Should I use the media_entity_setup_link() helper or should I mark it as
> enabled during media_create_pad_link()? Now I did something like:
> 
> if (i == 0) {
> 	list_for_each_entry(link, &con->links, list) {
> 		media_entity_setup_link(link, MEDIA_LNK_FL_ENABLED);
> 	}
> }

yeah, I guess this should work for both the cases where the first
connector is a comp or a svideo input.

I would prefer coding it differently, e. g. something like:

	
	for (i = 0; i < decoder->connectors_num; i++) {
		int flags = i ? 0 : MEDIA_LNK_FL_ENABLED;

and then use the flags var as the last argument for media_create_pad_link()
calls. That would avoid an extra loop and would likely reduce a little bit
the code size.

> > > +#endif
> > > +	return 0;
> > > +}
> > > +
> > > +
> > >  /* ----------------------------------------------------------------------- */
> > >  
> > >  static const struct v4l2_ctrl_ops tvp5150_ctrl_ops = {
> > > @@ -1368,6 +1563,10 @@ static const struct v4l2_subdev_ops tvp5150_ops = {
> > >  	.pad = &tvp5150_pad_ops,
> > >  };
> > >  
> > > +static const struct v4l2_subdev_internal_ops tvp5150_internal_ops = {
> > > +	.registered = tvp5150_registered,
> > > +};
> > > +
> > >  /****************************************************************************
> > >  			I2C Client & Driver
> > >   ****************************************************************************/
> > > @@ -1516,38 +1715,186 @@ static int tvp5150_init(struct i2c_client *c)
> > >  	return 0;
> > >  }
> > >  
> > > -static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np)
> > > +static int tvp5150_mc_init(struct v4l2_subdev *sd)
> > >  {
> > > -	struct v4l2_fwnode_endpoint bus_cfg;
> > > -	struct device_node *ep;
> > > -	unsigned int flags;
> > > -	int ret = 0;
> > > +#if defined(CONFIG_MEDIA_CONTROLLER)
> > > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > > +	struct device *dev = decoder->sd.dev;
> > > +	unsigned int i;
> > > +	int ret;
> > >  
> > > -	ep = of_graph_get_next_endpoint(np, NULL);
> > > -	if (!ep)
> > > -		return -EINVAL;
> > > +	sd->entity.ops = &tvp5150_sd_media_ops;
> > > +	sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
> > >  
> > > -	ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &bus_cfg);
> > > -	if (ret)
> > > -		goto err;
> > > +	/* Initialize all TVP5150 pads */
> > > +	for (i = 0; i < TVP5150_NUM_PADS; i++) {
> > > +		if (i < TVP5150_NUM_PADS - 1) {
> > > +			decoder->pads[i].flags = MEDIA_PAD_FL_SINK;
> > > +			decoder->pads[i].sig_type = PAD_SIGNAL_ANALOG;
> > > +		} else {
> > > +			decoder->pads[i].flags = MEDIA_PAD_FL_SOURCE;
> > > +			decoder->pads[i].sig_type = PAD_SIGNAL_DV;
> > > +		}
> > > +	}
> > > +	ret = media_entity_pads_init(&sd->entity, TVP5150_NUM_PADS,
> > > +				     decoder->pads);
> > > +	if (ret < 0)
> > > +		return ret;
> > > +
> > > +	/* in case of no oftree support */
> > > +	if (!decoder->endpoints[0])
> > > +		return 0;  
> > 
> > Hmm...
> >   
> > > +
> > > +	/* Allocate and initialize all available input connectors */
> > > +	decoder->connectors = devm_kcalloc(dev, decoder->connectors_num,
> > > +					   sizeof(*decoder->connectors),
> > > +					   GFP_KERNEL);
> > > +	if (!decoder->connectors)
> > > +		return -ENOMEM;
> > > +
> > > +	for (i = 0; i < decoder->connectors_num; i++) {
> > > +		struct device_node *rp;
> > > +		struct of_endpoint ep;
> > > +
> > > +		rp = of_graph_get_remote_port_parent(decoder->endpoints[i]);
> > > +		of_graph_parse_endpoint(decoder->endpoints[i], &ep);
> > > +		decoder->connectors[i].port_num = ep.port;
> > > +		decoder->connectors[i].is_svideo = !!of_device_is_compatible(rp,
> > > +							    "svideo-connector");
> > > +
> > > +		if (decoder->connectors[i].is_svideo)
> > > +			decoder->connectors[i].ent.function =
> > > +						MEDIA_ENT_F_CONN_SVIDEO;
> > > +		else
> > > +			decoder->connectors[i].ent.function =
> > > +						MEDIA_ENT_F_CONN_COMPOSITE;
> > > +
> > > +		decoder->connectors[i].ent.flags = MEDIA_ENT_FL_CONNECTOR;
> > > +		ret = of_property_read_string(rp, "label",
> > > +					      &decoder->connectors[i].ent.name);
> > > +		if (ret < 0)
> > > +			return ret;  
> > 
> > I would prefer, instead, to have a separate routine for OF. I'll probably
> > use something like the above for the non-DT devices (e. g. the ones using
> > em28xx driver).  
> 
> Okay, I refactored it.
> 
> >   
> > > +	}
> > > +#endif
> > > +	return 0;
> > > +}
> > > +
> > > +static bool tvp5150_valid_input(struct device_node *endpoint,
> > > +				unsigned int port, unsigned int id)  
> > 
> > Please call it as tvp5150_of_valid_input(). We may need something similar
> > for devices based on em28xx (passing info via platform_data).  
> 
> Okay, I changed it.
> 
> >   
> > > +{
> > > +	struct device_node *rp = of_graph_get_remote_port_parent(endpoint);
> > > +	const char *input;
> > > +	int ret;
> > > +
> > > +	/* perform some basic checks needed for later mc_init */
> > > +	switch (port) {
> > > +	case TVP5150_PAD_AIP1A:
> > > +		/* svideo must be connected to endpoint@1  */
> > > +		ret = id ? of_device_is_compatible(rp, "svideo-connector") :
> > > +			   of_device_is_compatible(rp, "composite-video-connector");
> > > +		if (!ret)
> > > +			return false;
> > > +		break;
> > > +	case TVP5150_PAD_AIP1B:
> > > +		ret = of_device_is_compatible(rp, "composite-video-connector");
> > > +		if (!ret)
> > > +			return false;
> > > +		break;
> > > +	}
> > > +
> > > +	ret = of_property_read_string(rp, "label", &input);
> > > +	if (ret < 0)
> > > +		return false;
> > > +
> > > +	return true;
> > > +}
> > >  
> > > -	flags = bus_cfg.bus.parallel.flags;
> > > +static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np)
> > > +{
> > > +	struct device *dev = decoder->sd.dev;
> > > +	struct v4l2_fwnode_endpoint bus_cfg;
> > > +	struct device_node *ep_np;
> > > +	unsigned int flags;
> > > +	int ret, i = 0, in = 0;
> > > +	bool found = false;
> > >  
> > > -	if (bus_cfg.bus_type == V4L2_MBUS_PARALLEL &&
> > > -	    !(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH &&
> > > -	      flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH &&
> > > -	      flags & V4L2_MBUS_FIELD_EVEN_LOW)) {
> > > +	/* at least 1 output and 1 input */
> > > +	decoder->endpoints_num = of_graph_get_endpoint_count(np);
> > > +	if (decoder->endpoints_num < 2 || decoder->endpoints_num > 4) {
> > >  		ret = -EINVAL;
> > >  		goto err;
> > >  	}
> > >  
> > > -	decoder->mbus_type = bus_cfg.bus_type;
> > > +	for_each_endpoint_of_node(np, ep_np) {
> > > +		struct of_endpoint ep;
> > >  
> > > +		of_graph_parse_endpoint(ep_np, &ep);
> > > +		if (decoder->endpoints[i]) {
> > > +			/* this should never happen */
> > > +			dev_err(dev, "Invalid endpoint %pOF on port %d\n",
> > > +				ep.local_node, ep.port);
> > > +				ret = -EINVAL;
> > > +				goto err;
> > > +		}
> > > +
> > > +		switch (ep.port) {
> > > +		case TVP5150_PAD_AIP1A:
> > > +		case TVP5150_PAD_AIP1B:
> > > +			if (!tvp5150_valid_input(ep_np, ep.port, ep.id)) {
> > > +				dev_err(dev,
> > > +					"Invalid endpoint %pOF on port %d\n",
> > > +					ep.local_node, ep.port);
> > > +				ret = -EINVAL;
> > > +				goto err;
> > > +			}
> > > +			in++;
> > > +			break;
> > > +		case TVP5150_PAD_VID_OUT:
> > > +			ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_np),
> > > +							 &bus_cfg);
> > > +			if (ret)
> > > +				goto err;
> > > +
> > > +			flags = bus_cfg.bus.parallel.flags;
> > > +
> > > +			if (bus_cfg.bus_type == V4L2_MBUS_PARALLEL &&
> > > +			    !(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH &&
> > > +			      flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH &&
> > > +			      flags & V4L2_MBUS_FIELD_EVEN_LOW)) {
> > > +				ret = -EINVAL;
> > > +				goto err;
> > > +			}
> > > +
> > > +			decoder->mbus_type = bus_cfg.bus_type;
> > > +			break;
> > > +		default:
> > > +			dev_err(dev, "Invalid port %d for endpoint %pOF\n",
> > > +				ep.port, ep.local_node);
> > > +			ret = -EINVAL;
> > > +			goto err;
> > > +		}
> > > +
> > > +		of_node_get(ep_np);
> > > +		decoder->endpoints[i] = ep_np;
> > > +		i++;
> > > +
> > > +		found = true;
> > > +	}
> > > +
> > > +	decoder->connectors_num = in;
> > > +	return found ? 0 : -ENODEV;
> > >  err:
> > > -	of_node_put(ep);
> > >  	return ret;
> > >  }
> > >  
> > > +static void tvp5150_dt_cleanup(struct tvp5150 *decoder)
> > > +{
> > > +	unsigned int i;
> > > +
> > > +	for (i = 0; i < TVP5150_NUM_PADS; i++)
> > > +		of_node_put(decoder->endpoints[i]);
> > > +}
> > > +
> > >  static const char * const tvp5150_test_patterns[2] = {
> > >  	"Disabled",
> > >  	"Black screen"
> > > @@ -1586,7 +1933,7 @@ static int tvp5150_probe(struct i2c_client *c,
> > >  		res = tvp5150_parse_dt(core, np);
> > >  		if (res) {
> > >  			dev_err(sd->dev, "DT parsing error: %d\n", res);
> > > -			return res;
> > > +			goto err_cleanup_dt;
> > >  		}
> > >  	} else {
> > >  		/* Default to BT.656 embedded sync */
> > > @@ -1594,25 +1941,16 @@ static int tvp5150_probe(struct i2c_client *c,
> > >  	}
> > >  
> > >  	v4l2_i2c_subdev_init(sd, c, &tvp5150_ops);
> > > +	sd->internal_ops = &tvp5150_internal_ops;
> > >  	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
> > >  
> > > -#if defined(CONFIG_MEDIA_CONTROLLER)
> > > -	core->pads[TVP5150_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
> > > -	core->pads[TVP5150_PAD_IF_INPUT].sig_type = PAD_SIGNAL_ANALOG;
> > > -	core->pads[TVP5150_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
> > > -	core->pads[TVP5150_PAD_VID_OUT].sig_type = PAD_SIGNAL_DV;
> > > -
> > > -	sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
> > > -
> > > -	res = media_entity_pads_init(&sd->entity, TVP5150_NUM_PADS, core->pads);
> > > -	if (res < 0)
> > > -		return res;
> > > -
> > > -#endif
> > > +	res = tvp5150_mc_init(sd);
> > > +	if (res)
> > > +		goto err_cleanup_dt;
> > >  
> > >  	res = tvp5150_detect_version(core);
> > >  	if (res < 0)
> > > -		return res;
> > > +		goto err_cleanup_dt;
> > >  
> > >  	core->norm = V4L2_STD_ALL;	/* Default is autodetect */
> > >  	core->detected_norm = V4L2_STD_UNKNOWN;
> > > @@ -1664,6 +2002,9 @@ static int tvp5150_probe(struct i2c_client *c,
> > >  err:
> > >  	v4l2_ctrl_handler_free(&core->hdl);
> > >  	return res;
> > > +err_cleanup_dt:
> > > +	tvp5150_dt_cleanup(core);
> > > +	return res;
> > >  }
> > >  
> > >  static int tvp5150_remove(struct i2c_client *c)  
> > 
> > 
> > 
> > Thanks,
> > Mauro  
> 
> Regards,
> Marco



Thanks,
Mauro

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

* Re: [PATCH 06/22] [media] tvp5150: add FORMAT_TRY support for get/set selection handlers
  2018-07-31  0:01   ` Mauro Carvalho Chehab
@ 2018-08-09 13:52     ` Marco Felsch
  0 siblings, 0 replies; 70+ messages in thread
From: Marco Felsch @ 2018-08-09 13:52 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: mchehab, p.zabel, afshin.nasser, javierm, sakari.ailus,
	laurent.pinchart, linux-media, kernel

Hi Mauro,

during my work for a v2 series, I prepared two patches which fix this in a
common way. The first will fix the compiler break and the second will
fix a missing dependency, since those helper functions require the
media_entity which is only available if MEDIA_CONTROLLER is enabled.

I attached both inline as an RFC, can give me your feedback?

I removed the devicetree guys to aviod noise.

On 18-07-30 21:01, Mauro Carvalho Chehab wrote:
> Em Thu, 28 Jun 2018 18:20:38 +0200
> Marco Felsch <m.felsch@pengutronix.de> escreveu:
> 
> > Since commit 10d5509c8d50 ("[media] v4l2: remove g/s_crop from video ops")
> > the 'which' field for set/get_selection must be FORMAT_ACTIVE. There is
> > no way to try different selections. The patch adds a helper function to
> > select the correct selection memory space (sub-device file handle or
> > driver state) which will be set/returned.
> > 
> > The TVP5150 AVID will be updated if the 'which' field is FORMAT_ACTIVE
> > and the requested selection rectangle differs from the already set one.
> > 
> > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > ---
> >  drivers/media/i2c/tvp5150.c | 107 ++++++++++++++++++++++++------------
> >  1 file changed, 73 insertions(+), 34 deletions(-)
> > 
> > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > index d150487cc2d1..29eaf8166f25 100644
> > --- a/drivers/media/i2c/tvp5150.c
> > +++ b/drivers/media/i2c/tvp5150.c
> > @@ -18,6 +18,7 @@
> >  #include <media/v4l2-ctrls.h>
> >  #include <media/v4l2-fwnode.h>
> >  #include <media/v4l2-mc.h>
> > +#include <media/v4l2-rect.h>
> >  
> >  #include "tvp5150_reg.h"
> >  
> > @@ -846,20 +847,38 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
> >  	}
> >  }
> >  
> > +static struct v4l2_rect *
> > +__tvp5150_get_pad_crop(struct tvp5150 *decoder,
> > +		       struct v4l2_subdev_pad_config *cfg, unsigned int pad,
> > +		       enum v4l2_subdev_format_whence which)
> > +{
> > +	switch (which) {
> > +	case V4L2_SUBDEV_FORMAT_TRY:
> > +		return v4l2_subdev_get_try_crop(&decoder->sd, cfg, pad);
> 
> This is not ok. It causes compilation breakage if the subdev API is not
> selected:
> 
> drivers/media/i2c/tvp5150.c: In function ‘__tvp5150_get_pad_crop’:
> drivers/media/i2c/tvp5150.c:857:10: error: implicit declaration of function ‘v4l2_subdev_get_try_crop’; did you mean ‘v4l2_subdev_has_op’? [-Werror=implicit-function-declaration]
>    return v4l2_subdev_get_try_crop(&decoder->sd, cfg, pad);
>           ^~~~~~~~~~~~~~~~~~~~~~~~
>           v4l2_subdev_has_op
> drivers/media/i2c/tvp5150.c:857:10: warning: returning ‘int’ from a function with return type ‘struct v4l2_rect *’ makes pointer from integer without a cast [-Wint-conversion]
>    return v4l2_subdev_get_try_crop(&decoder->sd, cfg, pad);
>           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 
> The logic should keep working both with and without subdev API.
> 

[ snip ]

>From d87554df5d1c6d609e44852a1cb998a6f5d99601 Mon Sep 17 00:00:00 2001
From: Marco Felsch <m.felsch@pengutronix.de>
Date: Wed, 8 Aug 2018 14:27:46 +0200
Subject: [RFC] [media] v4l2-subdev: add stubs for v4l2_subdev_get_try_*

In case of missing CONFIG_VIDEO_V4L2_SUBDEV_API those helpers aren't
available. So each driver have to add ifdefs around those helpers or
add the CONFIG_VIDEO_V4L2_SUBDEV_API as dependcy.

Make these helpers available in case of CONFIG_VIDEO_V4L2_SUBDEV_API
isn't set to avoid ifdefs. This approach is less error prone too.

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 include/media/v4l2-subdev.h | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 9102d6ca566e..ce48f1fcf295 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -912,8 +912,6 @@ struct v4l2_subdev_fh {
 #define to_v4l2_subdev_fh(fh)	\
 	container_of(fh, struct v4l2_subdev_fh, vfh)
 
-#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
-
 /**
  * v4l2_subdev_get_try_format - ancillary routine to call
  *	&struct v4l2_subdev_pad_config->try_fmt
@@ -927,9 +925,13 @@ static inline struct v4l2_mbus_framefmt
 			    struct v4l2_subdev_pad_config *cfg,
 			    unsigned int pad)
 {
+#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
 	if (WARN_ON(pad >= sd->entity.num_pads))
 		pad = 0;
 	return &cfg[pad].try_fmt;
+#else
+	return NULL;
+#endif
 }
 
 /**
@@ -945,9 +947,13 @@ static inline struct v4l2_rect
 			  struct v4l2_subdev_pad_config *cfg,
 			  unsigned int pad)
 {
+#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
 	if (WARN_ON(pad >= sd->entity.num_pads))
 		pad = 0;
 	return &cfg[pad].try_crop;
+#else
+	return NULL;
+#endif
 }
 
 /**
@@ -963,11 +969,14 @@ static inline struct v4l2_rect
 			     struct v4l2_subdev_pad_config *cfg,
 			     unsigned int pad)
 {
+#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
 	if (WARN_ON(pad >= sd->entity.num_pads))
 		pad = 0;
 	return &cfg[pad].try_compose;
-}
+#else
+	return NULL;
 #endif
+}
 
 extern const struct v4l2_file_operations v4l2_subdev_fops;
 
-- 
2.18.0

>From 6abc7599fe6bdb2b8bef84fd90417d69aafb4a33 Mon Sep 17 00:00:00 2001
From: Marco Felsch <m.felsch@pengutronix.de>
Date: Wed, 8 Aug 2018 14:47:44 +0200
Subject: [RFC] [media] v4l2-subdev: fix v4l2_subdev_get_try_* dependency

These helpers make us of the media-controller entity which is only
available if the CONFIG_MEDIA_CONTROLLER is enabled.

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 include/media/v4l2-subdev.h | 100 ++++++++++++++++++------------------
 1 file changed, 50 insertions(+), 50 deletions(-)

diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index ce48f1fcf295..79c066934ad2 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -912,6 +912,56 @@ struct v4l2_subdev_fh {
 #define to_v4l2_subdev_fh(fh)	\
 	container_of(fh, struct v4l2_subdev_fh, vfh)
 
+extern const struct v4l2_file_operations v4l2_subdev_fops;
+
+/**
+ * v4l2_set_subdevdata - Sets V4L2 dev private device data
+ *
+ * @sd: pointer to &struct v4l2_subdev
+ * @p: pointer to the private device data to be stored.
+ */
+static inline void v4l2_set_subdevdata(struct v4l2_subdev *sd, void *p)
+{
+	sd->dev_priv = p;
+}
+
+/**
+ * v4l2_get_subdevdata - Gets V4L2 dev private device data
+ *
+ * @sd: pointer to &struct v4l2_subdev
+ *
+ * Returns the pointer to the private device data to be stored.
+ */
+static inline void *v4l2_get_subdevdata(const struct v4l2_subdev *sd)
+{
+	return sd->dev_priv;
+}
+
+/**
+ * v4l2_set_subdev_hostdata - Sets V4L2 dev private host data
+ *
+ * @sd: pointer to &struct v4l2_subdev
+ * @p: pointer to the private data to be stored.
+ */
+static inline void v4l2_set_subdev_hostdata(struct v4l2_subdev *sd, void *p)
+{
+	sd->host_priv = p;
+}
+
+/**
+ * v4l2_get_subdev_hostdata - Gets V4L2 dev private data
+ *
+ * @sd: pointer to &struct v4l2_subdev
+ *
+ * Returns the pointer to the private host data to be stored.
+ */
+static inline void *v4l2_get_subdev_hostdata(const struct v4l2_subdev *sd)
+{
+	return sd->host_priv;
+}
+
+#ifdef CONFIG_MEDIA_CONTROLLER
+
 /**
  * v4l2_subdev_get_try_format - ancillary routine to call
  *	&struct v4l2_subdev_pad_config->try_fmt
@@ -978,56 +1028,6 @@ static inline struct v4l2_rect
 #endif
 }
 
-extern const struct v4l2_file_operations v4l2_subdev_fops;
-
-/**
- * v4l2_set_subdevdata - Sets V4L2 dev private device data
- *
- * @sd: pointer to &struct v4l2_subdev
- * @p: pointer to the private device data to be stored.
- */
-static inline void v4l2_set_subdevdata(struct v4l2_subdev *sd, void *p)
-{
-	sd->dev_priv = p;
-}
-
-/**
- * v4l2_get_subdevdata - Gets V4L2 dev private device data
- *
- * @sd: pointer to &struct v4l2_subdev
- *
- * Returns the pointer to the private device data to be stored.
- */
-static inline void *v4l2_get_subdevdata(const struct v4l2_subdev *sd)
-{
-	return sd->dev_priv;
-}
-
-/**
- * v4l2_set_subdev_hostdata - Sets V4L2 dev private host data
- *
- * @sd: pointer to &struct v4l2_subdev
- * @p: pointer to the private data to be stored.
- */
-static inline void v4l2_set_subdev_hostdata(struct v4l2_subdev *sd, void *p)
-{
-	sd->host_priv = p;
-}
-
-/**
- * v4l2_get_subdev_hostdata - Gets V4L2 dev private data
- *
- * @sd: pointer to &struct v4l2_subdev
- *
- * Returns the pointer to the private host data to be stored.
- */
-static inline void *v4l2_get_subdev_hostdata(const struct v4l2_subdev *sd)
-{
-	return sd->host_priv;
-}
-
-#ifdef CONFIG_MEDIA_CONTROLLER
-
 /**
  * v4l2_subdev_link_validate_default - validates a media link
  *
-- 
2.18.0

Kind regards,
Marco

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

* Re: [PATCH 19/22] [media] tvp5150: add input source selection of_graph support
  2018-08-09 13:36           ` Mauro Carvalho Chehab
@ 2018-08-09 14:35             ` Marco Felsch
  2018-08-09 16:04               ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 70+ messages in thread
From: Marco Felsch @ 2018-08-09 14:35 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Hi Mauro,

Thanks for your feedback.

On 18-08-09 10:36, Mauro Carvalho Chehab wrote:
> Em Thu, 9 Aug 2018 14:55:07 +0200
> Marco Felsch <m.felsch@pengutronix.de> escreveu:
> 
> > Hi Mauro,
> > 
> > On 18-08-08 15:52, Mauro Carvalho Chehab wrote:
> > > Em Wed, 8 Aug 2018 17:29:49 +0200
> > > Marco Felsch <m.felsch@pengutronix.de> escreveu:
> > >   
> > > > Hi Mauro,
> > > > 
> > > > the discussion about the correct binding was spread around some patches.
> > > > So I will try use the correct thread for that theme. I did my rework for
> > > > the of_graph support on your suggestions [1] and [2]. I attached my work
> > > > as RFC patch. Can you review it, so I can prepare a v2?
> > > > 
> > > > [1] https://www.spinics.net/lists/linux-media/msg138545.html
> > > > [2] https://www.spinics.net/lists/linux-media/msg138546.html  
> > > 
> > > Thanks for the patch.
> > > 
> > > Added my comments below.  
> > 
> > Thanks for your quick response.
> > 
> > I integrated the most of your comments and added some more comments below.
> > 
> > >   
> > > > 
> > > > On 18-07-30 15:29, Mauro Carvalho Chehab wrote:  
> > > > > Em Thu, 28 Jun 2018 18:20:51 +0200
> > > > > Marco Felsch <m.felsch@pengutronix.de> escreveu:
> > > > >   
> > > > > > The currrent driver layout had the following layout:
> > > > > >                +----------------+
> > > > > >  +-------+     |    TVP5150     |
> > > > > >  | Comp0 +--+  |                |
> > > > > >  +-------+  |  |          +-----+
> > > > > >  +-------+  |  +------+   | Src |
> > > > > >  | Comp1 +--+--|Sink  |   +-----+
> > > > > >  +-------+  |  +------+   +-----+
> > > > > > +--------+  |  |          | Src |
> > > > > > | SVideo +--+  |          +-----+
> > > > > > +--------+     +----------------+
> > > > > > 
> > > > > > Since the device tree abstracts the real hardware this layout is not
> > > > > > correct, because the TVP5150 has 3 physical ports (2 input, 1 output).
> > > > > > Furthermore this layout assumes that there is an additional external mux
> > > > > > in front of the TVP5150. This is not correct because the TVP5150 does
> > > > > > the muxing work. The corresponding of_graph layout will look like:
> > > > > > 	tvp5150 {
> > > > > > 		....
> > > > > > 		port {
> > > > > > 			reg = <0>;
> > > > > > 			endpoint@0 {...};
> > > > > > 			endpoint@1 {...};
> > > > > > 			endpoint@2 {...};
> > > > > > 		};
> > > > > > 
> > > > > > 	};
> > > > > > 
> > > > > > This patch change the layout to:
> > > > > >              +----------------+
> > > > > >              |    TVP5150     |
> > > > > >  +-------+   +------+         |
> > > > > >  | Comp0 +---+ Sink |         |
> > > > > >  +-------+   +------+         |
> > > > > >  +-------+   +------+   +-----+
> > > > > >  | Comp1 +---+ Sink |   | Src |
> > > > > >  +-------+   +------+   +-----+
> > > > > > +--------+   +------+         |
> > > > > > | SVideo +---+ Sink |         |
> > > > > > +--------+   +------+         |
> > > > > >              +----------------+
> > > > > > 
> > > > > > To keep things easy an additional 'virtual' S-Video port is added. More
> > > > > > information about the port mapping can be found in the device tree
> > > > > > binding documentation. The connector entities Comp0/1, SVideo are created
> > > > > > only if they are connected to the correct port. If more than one connector
> > > > > > is available the media_entity_operations.link_setup() callback ensures that
> > > > > > only one connector is active. To change the input src the link between
> > > > > > the TVP5150 pad and the connector must be disabled, then a new link can
> > > > > > be enabled.
> > > > > > 
> > > > > > The patch tries to reduce the '#ifdef CONFIG_MEDIA_CONTROLLER' usage to
> > > > > > a minimum.
> > > > > > 
> > > > > > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > > > > > ---
> > > > > >  drivers/media/i2c/tvp5150.c | 322 ++++++++++++++++++++++++++++++++----
> > > > > >  1 file changed, 287 insertions(+), 35 deletions(-)
> > > > > > 
> > > > > > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > > > > > index a6fec569a610..6ac29c62d99b 100644
> > > > > > --- a/drivers/media/i2c/tvp5150.c
> > > > > > +++ b/drivers/media/i2c/tvp5150.c
> > > > > > @@ -44,10 +44,30 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
> > > > > >  
> > > > > >  #define dprintk0(__dev, __arg...) dev_dbg_lvl(__dev, 0, 0, __arg)
> > > > > >  
> > > > > > +enum tvp5150_ports {
> > > > > > +	TVP5150_PORT_AIP1A = TVP5150_COMPOSITE0,
> > > > > > +	TVP5150_PORT_AIP1B,
> > > > > > +	/* s-video port is a virtual port */
> > > > > > +	TVP5150_PORT_SVIDEO,
> > > > > > +	TVP5150_PORT_YOUT,
> > > > > > +	TVP5150_PORT_NUM,
> > > > > > +};
> > > > > > +
> > > > > > +#ifdef CONFIG_MEDIA_CONTROLLER
> > > > > > +struct tvp5150_connector {
> > > > > > +	struct media_entity con;
> > > > > > +	struct media_pad pad;
> > > > > > +	unsigned int port_num;
> > > > > > +};
> > > > > > +#endif
> > > > > > +
> > > > > >  struct tvp5150 {
> > > > > >  	struct v4l2_subdev sd;
> > > > > > +	struct device_node *endpoints[TVP5150_PORT_NUM];
> > > > > >  #ifdef CONFIG_MEDIA_CONTROLLER
> > > > > > -	struct media_pad pads[DEMOD_NUM_PADS];
> > > > > > +	struct media_pad pads[TVP5150_PORT_NUM];  
> > > > > 
> > > > > This will cause problems with the current code.
> > > > > 
> > > > > When we designed the MC version 2 code, the idea were to allow
> > > > > set properties to entities and to the inputs, but the code
> > > > > was never submitted upstream.
> > > > > 
> > > > > A decoder may have several different types of inputs and outputs.
> > > > > Several designs allow using different types of decoders, being
> > > > > saa711x and tvp5150 the most popular ones. Well, depending on
> > > > > the device, the number of PADs and the signals they carry can
> > > > > be different.
> > > > > 
> > > > > Without a way to "taint" a pad to the signal it contains, 
> > > > > while waiting for the properties API, we added a code that
> > > > > "fixed" the PADs to a certain number. This way, Kernelspace could
> > > > > use the pad "number" as a way to identify the type of signal a
> > > > > PAD carries.
> > > > > 
> > > > > The PC consumer drivers use those numbers in order to build the
> > > > > MC graph[1].
> > > > > 
> > > > > A change on this would require adding a property to the pad, in
> > > > > order to indicate the type of signal it provides (RF, luminance IF,
> > > > > chroma IF, audio IF, I2S audio, ...), and to change
> > > > > v4l2_mc_create_media_graph() accordingly.
> > > > > 
> > > > > 
> > > > > [1] See drivers/media/v4l2-core/v4l2-mc.c at v4l2_mc_create_media_graph() func.
> > > > > 
> > > > >   
> > > > 
> > > > [ snip ]
> > > > 
> > > > From d3eb8a7de65fe2f8dd10ced85e4baca8e7898434 Mon Sep 17 00:00:00 2001
> > > > From: Marco Felsch <m.felsch@pengutronix.de>
> > > > Date: Thu, 28 Jun 2018 18:20:51 +0200
> > > > Subject: [RFC] [media] tvp5150: add input source selection of_graph
> > > >  support
> > > > 
> > > > This patch adds the of_graph support to describe the tvp connections.
> > > > Physical the TVP5150 has three ports: AIP1A, AIP1B and YOUT. As result
> > > > of discussion [1],[2] the device-tree maps these ports 1:1 with one
> > > > deviation. The svideo connector must be conneted to port@0/endpoint@1,
> > > > look at the Documentation for more information. Since the TVP5150 is a
> > > > converter the device-tree must contain at least 1-input and 1-output port.
> > > > The mc-connectors and mc-links are only created if the device-tree
> > > > contains the corresponding connector nodes. If more than one connector is
> > > > available the media_entity_operations.link_setup() callback ensures that
> > > > only one connector is active. To change the input src the active link must
> > > > disabled first, then a new link can be established.
> > > > 
> > > > [1] https://www.spinics.net/lists/linux-media/msg138545.html
> > > > [2] https://www.spinics.net/lists/linux-media/msg138546.html
> > > > 
> > > > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > > > 
> > > > ---
> > > > Changelog:
> > > > 
> > > > v2:
> > > > - adapt commit message
> > > > - mc: use 2-input and 1-output pad
> > > > - mc: enable svideo on tvp only if both tvp-input pads have a active
> > > >       link to the svideo src pad
> > > > - mc: disable svideo on tvp only if both tvp-input pads are inactive
> > > > - dt-support: drop svideo dt port
> > > > - dt-support: move svideo connector to port@0/endpoint@1
> > > > - dt-support: require at least 1-in and 1-out endpoint
> > > > ---
> > > >  drivers/media/i2c/tvp5150.c | 413 ++++++++++++++++++++++++++++++++----
> > > >  1 file changed, 377 insertions(+), 36 deletions(-)
> > > > 
> > > > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > > > index b5d44c25d1da..be755c5e63a9 100644
> > > > --- a/drivers/media/i2c/tvp5150.c
> > > > +++ b/drivers/media/i2c/tvp5150.c
> > > > @@ -43,16 +43,38 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
> > > >  
> > > >  #define dprintk0(__dev, __arg...) dev_dbg_lvl(__dev, 0, 0, __arg)
> > > >  
> > > > +#ifdef CONFIG_MEDIA_CONTROLLER
> > > >  enum tvp5150_pads {
> > > > -       TVP5150_PAD_IF_INPUT,
> > > > -       TVP5150_PAD_VID_OUT,
> > > > -       TVP5150_NUM_PADS
> > > > +	TVP5150_PAD_AIP1A = TVP5150_COMPOSITE0,
> > > > +	TVP5150_PAD_AIP1B,
> > > > +	TVP5150_PAD_VID_OUT,
> > > > +	TVP5150_NUM_PADS
> > > > +};
> > > > +
> > > > +enum tvp5150_pads_state {
> > > > +	TVP5150_PAD_INACTIVE,
> > > > +	TVP5150_PAD_ACTIVE_COMPOSITE,
> > > > +	TVP5150_PAD_ACTIVE_SVIDEO,
> > > > +};
> > > > +
> > > > +struct tvp5150_connector {
> > > > +	struct media_entity ent;
> > > > +	struct media_pad pad;
> > > > +	unsigned int port_num;
> > > > +	bool is_svideo;
> > > >  };
> > > > +#endif
> > > >  
> > > >  struct tvp5150 {
> > > >  	struct v4l2_subdev sd;
> > > > +	/* additional additional endpoint for the svideo connector */
> > > > +	struct device_node *endpoints[TVP5150_NUM_PADS + 1];
> > > > +	unsigned int endpoints_num;
> > > >  #ifdef CONFIG_MEDIA_CONTROLLER
> > > >  	struct media_pad pads[TVP5150_NUM_PADS];
> > > > +	int pads_state[TVP5150_NUM_PADS];
> > > > +	struct tvp5150_connector *connectors;
> > > > +	int connectors_num;
> > > >  #endif
> > > >  	struct v4l2_ctrl_handler hdl;
> > > >  	struct v4l2_rect rect;
> > > > @@ -1168,6 +1190,135 @@ static int tvp5150_enum_frame_size(struct v4l2_subdev *sd,
> > > >  	return 0;
> > > >  }
> > > >  
> > > > +/****************************************************************************
> > > > + *			Media entity ops
> > > > + ****************************************************************************/
> > > > +#ifdef CONFIG_MEDIA_CONTROLLER
> > > > +static int tvp5150_s_routing(struct v4l2_subdev *sd, u32 input, u32 output,
> > > > +			     u32 config);
> > > > +static int tvp5150_link_setup(struct media_entity *entity,
> > > > +			      const struct media_pad *local,
> > > > +			      const struct media_pad *remote, u32 flags)
> > > > +{
> > > > +	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
> > > > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > > > +	int *pad_state = &decoder->pads_state[0];
> > > > +	int i, ret = 0, active_pad = -1;
> > > > +	bool is_svideo = false;
> > > > +
> > > > +	/*
> > > > +	 * The tvp state is determined by the enabled sink pad link.
> > > > +	 * Enabling or disabling the source pad link has no effect.
> > > > +	 */
> > > > +	if (local->flags & MEDIA_PAD_FL_SOURCE)
> > > > +		return 0;
> > > > +
> > > > +	/* check if the svideo connector should be enabled */
> > > > +	for (i = 0; i < decoder->connectors_num; i++) {
> > > > +		if (remote->entity == &decoder->connectors[i].ent) {
> > > > +			is_svideo = decoder->connectors[i].is_svideo;
> > > > +			break;
> > > > +		}
> > > > +	}
> > > > +
> > > > +	/* check if there is enabled link */
> > > > +	for (i = 0; i < TVP5150_NUM_PADS - 1; i++) {
> > > > +		if ((pad_state[i] == TVP5150_PAD_ACTIVE_COMPOSITE) ||
> > > > +		    (pad_state[i] == TVP5150_PAD_ACTIVE_SVIDEO)) {
> > > > +			active_pad = i;
> > > > +			break;
> > > > +		}
> > > > +	}
> > > > +
> > > > +	dev_dbg(sd->dev, "link setup '%s':%d->'%s':%d[%d]",
> > > > +		remote->entity->name, remote->index, local->entity->name,
> > > > +		local->index, flags & MEDIA_LNK_FL_ENABLED);  
> > > 
> > > Hmm... the remote is the connector, right? I would switch the
> > > print message to point from the connector to tvp5150, as this is
> > > the signal flow.  
> > 
> > I don't know what you mean, I tought that's what I'm already do. If I
> > change it it will print something like: tvp5150 2-005d :0 -> Comp0 :0[1]
> 
> Hmm... then "local" actually means the connector and "remote"
> is the tvp5150?

Nope, local is the tvp and remote is the connector. Actual the output
looks as follows

[   26.339939] tvp5150 2-005d: link setup 'Comp0':0->'tvp5150 2-005d':0[1]
[   26.346606] tvp5150 2-005d: Setting 0 active [composite]

I think this is what you mean with '... point from the connector to
tvp5150 ...'.

> 
> > 
> > > 
> > > Btw, it would likely be better to call it "connector" or "conn_entity",
> > > to make it clearer.  
> > 
> > I tought remote is the common nomenclature. Also the remote mustn't be a
> > connector. In my case it's a soldered camera. With this in mind, you think
> > it should be still changed?
> 
> I see your point.
> 
> Yeah, remote is a common nomenclature. Yet, as it can be seen from
> the above comment (and your answer), common nomenclature may lead
> in to mistakes :-)

Yeah, I know what you mean ^^

> 
> It would be good to have either one of sides better named (either
> the connectors side or the tvp5150 side - or both), in order to be
> clearer and avoid confusion of someone else touches that part of
> the code.

Yes, I'm with you. Since the local always points to the tvp5150, I will
change the local to tvp5150 or tvp5150_pad. Renaming the remote isn't
that good since it can be anything.

> 
> In this specific case, both connectors and tvp5150 are created by
> the tvp5150, so both are "local" in the sense that both are
> created by this driver.
>

I know.. Maybe there should be a 'common' svideo-/composite-connector
code and some helpers to create and link those. Then we can drop the
'local' connectors.

> > 
> > >   
> > > > +
> > > > +	if (flags & MEDIA_LNK_FL_ENABLED) {
> > > > +		/*
> > > > +		 * Composite activation: all links must be inactive.
> > > > +		 * Svideo activation: one link can be active if it is a svideo
> > > > +		 * link. Return error in case of a active composite link or both
> > > > +		 * svideo links are active.
> > > > +		 */
> > > > +		if (active_pad >= 0 && !is_svideo) {
> > > > +			ret = -EBUSY;
> > > > +			goto out;
> > > > +		} else if (active_pad >= 0 && is_svideo &&
> > > > +			   pad_state[active_pad] ==
> > > > +			   TVP5150_PAD_ACTIVE_COMPOSITE) {
> > > > +			ret = -EBUSY;
> > > > +			goto out;
> > > > +		} else if (active_pad >= 0) {
> > > > +			/* check if 2nd svideo link is active too */
> > > > +			for (i = 0; i < TVP5150_NUM_PADS - 1; i++) {
> > > > +				if (pad_state[i] == TVP5150_PAD_ACTIVE_SVIDEO) {
> > > > +					if (i != active_pad) {
> > > > +						ret = -EBUSY;
> > > > +						goto out;
> > > > +					}
> > > > +				}
> > > > +			}
> > > > +		}  
> > > 
> > > That may require some additional discussions.
> > > 
> > > I guess this is not the way it should be. I mean, it should be possible
> > > to change the routing while streaming, without disabling the video
> > > output. That's the behavior that TV generic applications like tvtime,
> > > xawtv, etc rely on.
> > > 
> > > So, probably, the right thing to do here is to disable the active_pad
> > > and  enable the newer one, if there is an active pad.
> > > 
> > > This way, it would work both if the userspace first disables the link
> > > and then enables a new one, or if it switches without explicitly
> > > disabling the previous one.  
> > 
> > Okay I change this behaviour.
> > 
> > >   
> > > > +
> > > > +		dev_dbg(sd->dev, "Setting %d active [%s]\n", local->index,
> > > > +			is_svideo ? "svideo": "composite");
> > > > +		pad_state[local->index] = is_svideo ?
> > > > +			TVP5150_PAD_ACTIVE_SVIDEO : TVP5150_PAD_ACTIVE_COMPOSITE;
> > > > +
> > > > +		if (is_svideo) {
> > > > +			unsigned int active_link_cnt = 0;
> > > > +
> > > > +			/* enable svideo only if we have two active links */
> > > > +			for (i = 0; i > TVP5150_NUM_PADS - 1; i++)
> > > > +				if (pad_state[i] == TVP5150_PAD_ACTIVE_SVIDEO)
> > > > +					active_link_cnt++;
> > > > +			if (active_link_cnt == 2)
> > > > +				tvp5150_s_routing(sd, TVP5150_SVIDEO,
> > > > +						  TVP5150_NORMAL, 0);
> > > > +		} else {
> > > > +			tvp5150_s_routing(sd, local->index, TVP5150_NORMAL, 0);
> > > > +		}
> > > > +	} else {
> > > > +		/*
> > > > +		 * Svideo streams on two pads and user can disable AIP1A or
> > > > +		 * AIP1B first. So check only if user wants to disable a not
> > > > +		 * enabled composite pad.
> > > > +		 */
> > > > +		if (!is_svideo && active_pad != local->index)
> > > > +				goto out;
> > > > +
> > > > +		dev_dbg(sd->dev, "going inactive\n");
> > > > +		pad_state[local->index] = TVP5150_PAD_INACTIVE;
> > > > +
> > > > +		/*
> > > > +		 * Output black screen for deselected input if TVP5150 variant
> > > > +		 * supports this.
> > > > +		 */
> > > > +		if (is_svideo) {
> > > > +			unsigned int inactive_link_cnt = 0;
> > > > +
> > > > +			/* disable svideo only if we have two inactive links */
> > > > +			for (i = 0; i > TVP5150_NUM_PADS - 1; i++)
> > > > +				if (pad_state[i] == TVP5150_PAD_INACTIVE)
> > > > +					inactive_link_cnt++;
> > > > +			if (inactive_link_cnt == 2)
> > > > +				tvp5150_s_routing(sd, TVP5150_SVIDEO,
> > > > +						  TVP5150_BLACK_SCREEN, 0);
> > > > +
> > > > +		} else {
> > > > +			tvp5150_s_routing(sd, local->index,
> > > > +					  TVP5150_BLACK_SCREEN, 0);
> > > > +		}
> > > > +	}
> > > > +out:
> > > > +	return ret;
> > > > +}
> > > > +
> > > > +static const struct media_entity_operations tvp5150_sd_media_ops = {
> > > > +	.link_setup = tvp5150_link_setup,
> > > > +};
> > > > +#endif
> > > >  /****************************************************************************
> > > >  			I2C Command
> > > >   ****************************************************************************/
> > > > @@ -1315,6 +1466,50 @@ static int tvp5150_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
> > > >  	return 0;
> > > >  }
> > > >  
> > > > +static int tvp5150_registered(struct v4l2_subdev *sd)
> > > > +{
> > > > +#ifdef CONFIG_MEDIA_CONTROLLER
> > > > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > > > +	unsigned int i;
> > > > +	int ret;
> > > > +
> > > > +	for (i = 0; i < decoder->connectors_num; i++) {
> > > > +		struct media_entity *con = &decoder->connectors[i].ent;
> > > > +		struct media_pad *pad = &decoder->connectors[i].pad;
> > > > +		unsigned int port = decoder->connectors[i].port_num;
> > > > +		bool is_svideo = decoder->connectors[i].is_svideo;
> > > > +
> > > > +		pad->flags = MEDIA_PAD_FL_SOURCE;
> > > > +		ret = media_entity_pads_init(con, 1, pad);
> > > > +		if (ret < 0)
> > > > +			return ret;
> > > > +
> > > > +		ret = media_device_register_entity(sd->v4l2_dev->mdev, con);
> > > > +		if (ret < 0)
> > > > +			return ret;
> > > > +
> > > > +		ret = media_create_pad_link(con, 0, &sd->entity, port, 0);
> > > > +		if (ret < 0) {
> > > > +			media_device_unregister_entity(con);
> > > > +			return ret;
> > > > +		}
> > > > +
> > > > +		if (is_svideo) {
> > > > +			/* svideo links to both aip1a and aip1b */
> > > > +			ret = media_create_pad_link(con, 0, &sd->entity,
> > > > +						    port + 1, 0);
> > > > +			if (ret < 0) {
> > > > +				media_device_unregister_entity(con);
> > > > +				return ret;
> > > > +			}
> > > > +		}
> > > > +
> > > > +	}  
> > > 
> > > IMO, it should route to the first available connector.  
> > 
> > Did you mean to set the link status to enabled? 
> 
> Yes.
> 
> > If so I have one
> > question else can you tell me what you mean?
> > 
> > Should I use the media_entity_setup_link() helper or should I mark it as
> > enabled during media_create_pad_link()? Now I did something like:
> > 
> > if (i == 0) {
> > 	list_for_each_entry(link, &con->links, list) {
> > 		media_entity_setup_link(link, MEDIA_LNK_FL_ENABLED);
> > 	}
> > }
> 
> yeah, I guess this should work for both the cases where the first
> connector is a comp or a svideo input.
> 
> I would prefer coding it differently, e. g. something like:
> 
> 	
> 	for (i = 0; i < decoder->connectors_num; i++) {
> 		int flags = i ? 0 : MEDIA_LNK_FL_ENABLED;
> 
> and then use the flags var as the last argument for media_create_pad_link()
> calls. That would avoid an extra loop and would likely reduce a little bit
> the code size.

Sorry for the ambiguous code example. I did the 'if (i == 0)' in the same
loop, so no extra loop. I can do it your way, but than unnecessary
media_entity_setup_link() are made.

> 
> > > > +#endif
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +
> > > >  /* ----------------------------------------------------------------------- */
> > > >  
> > > >  static const struct v4l2_ctrl_ops tvp5150_ctrl_ops = {
> > > > @@ -1368,6 +1563,10 @@ static const struct v4l2_subdev_ops tvp5150_ops = {
> > > >  	.pad = &tvp5150_pad_ops,
> > > >  };
> > > >  
> > > > +static const struct v4l2_subdev_internal_ops tvp5150_internal_ops = {
> > > > +	.registered = tvp5150_registered,
> > > > +};
> > > > +
> > > >  /****************************************************************************
> > > >  			I2C Client & Driver
> > > >   ****************************************************************************/
> > > > @@ -1516,38 +1715,186 @@ static int tvp5150_init(struct i2c_client *c)
> > > >  	return 0;
> > > >  }
> > > >  
> > > > -static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np)
> > > > +static int tvp5150_mc_init(struct v4l2_subdev *sd)
> > > >  {
> > > > -	struct v4l2_fwnode_endpoint bus_cfg;
> > > > -	struct device_node *ep;
> > > > -	unsigned int flags;
> > > > -	int ret = 0;
> > > > +#if defined(CONFIG_MEDIA_CONTROLLER)
> > > > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > > > +	struct device *dev = decoder->sd.dev;
> > > > +	unsigned int i;
> > > > +	int ret;
> > > >  
> > > > -	ep = of_graph_get_next_endpoint(np, NULL);
> > > > -	if (!ep)
> > > > -		return -EINVAL;
> > > > +	sd->entity.ops = &tvp5150_sd_media_ops;
> > > > +	sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
> > > >  
> > > > -	ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &bus_cfg);
> > > > -	if (ret)
> > > > -		goto err;
> > > > +	/* Initialize all TVP5150 pads */
> > > > +	for (i = 0; i < TVP5150_NUM_PADS; i++) {
> > > > +		if (i < TVP5150_NUM_PADS - 1) {
> > > > +			decoder->pads[i].flags = MEDIA_PAD_FL_SINK;
> > > > +			decoder->pads[i].sig_type = PAD_SIGNAL_ANALOG;
> > > > +		} else {
> > > > +			decoder->pads[i].flags = MEDIA_PAD_FL_SOURCE;
> > > > +			decoder->pads[i].sig_type = PAD_SIGNAL_DV;
> > > > +		}
> > > > +	}
> > > > +	ret = media_entity_pads_init(&sd->entity, TVP5150_NUM_PADS,
> > > > +				     decoder->pads);
> > > > +	if (ret < 0)
> > > > +		return ret;
> > > > +
> > > > +	/* in case of no oftree support */
> > > > +	if (!decoder->endpoints[0])
> > > > +		return 0;  
> > > 
> > > Hmm...
> > >   
> > > > +
> > > > +	/* Allocate and initialize all available input connectors */
> > > > +	decoder->connectors = devm_kcalloc(dev, decoder->connectors_num,
> > > > +					   sizeof(*decoder->connectors),
> > > > +					   GFP_KERNEL);
> > > > +	if (!decoder->connectors)
> > > > +		return -ENOMEM;
> > > > +
> > > > +	for (i = 0; i < decoder->connectors_num; i++) {
> > > > +		struct device_node *rp;
> > > > +		struct of_endpoint ep;
> > > > +
> > > > +		rp = of_graph_get_remote_port_parent(decoder->endpoints[i]);
> > > > +		of_graph_parse_endpoint(decoder->endpoints[i], &ep);
> > > > +		decoder->connectors[i].port_num = ep.port;
> > > > +		decoder->connectors[i].is_svideo = !!of_device_is_compatible(rp,
> > > > +							    "svideo-connector");
> > > > +
> > > > +		if (decoder->connectors[i].is_svideo)
> > > > +			decoder->connectors[i].ent.function =
> > > > +						MEDIA_ENT_F_CONN_SVIDEO;
> > > > +		else
> > > > +			decoder->connectors[i].ent.function =
> > > > +						MEDIA_ENT_F_CONN_COMPOSITE;
> > > > +
> > > > +		decoder->connectors[i].ent.flags = MEDIA_ENT_FL_CONNECTOR;
> > > > +		ret = of_property_read_string(rp, "label",
> > > > +					      &decoder->connectors[i].ent.name);
> > > > +		if (ret < 0)
> > > > +			return ret;  
> > > 
> > > I would prefer, instead, to have a separate routine for OF. I'll probably
> > > use something like the above for the non-DT devices (e. g. the ones using
> > > em28xx driver).  
> > 
> > Okay, I refactored it.
> > 
> > >   
> > > > +	}
> > > > +#endif
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +static bool tvp5150_valid_input(struct device_node *endpoint,
> > > > +				unsigned int port, unsigned int id)  
> > > 
> > > Please call it as tvp5150_of_valid_input(). We may need something similar
> > > for devices based on em28xx (passing info via platform_data).  
> > 
> > Okay, I changed it.
> > 
> > >   
> > > > +{
> > > > +	struct device_node *rp = of_graph_get_remote_port_parent(endpoint);
> > > > +	const char *input;
> > > > +	int ret;
> > > > +
> > > > +	/* perform some basic checks needed for later mc_init */
> > > > +	switch (port) {
> > > > +	case TVP5150_PAD_AIP1A:
> > > > +		/* svideo must be connected to endpoint@1  */
> > > > +		ret = id ? of_device_is_compatible(rp, "svideo-connector") :
> > > > +			   of_device_is_compatible(rp, "composite-video-connector");
> > > > +		if (!ret)
> > > > +			return false;
> > > > +		break;
> > > > +	case TVP5150_PAD_AIP1B:
> > > > +		ret = of_device_is_compatible(rp, "composite-video-connector");
> > > > +		if (!ret)
> > > > +			return false;
> > > > +		break;
> > > > +	}
> > > > +
> > > > +	ret = of_property_read_string(rp, "label", &input);
> > > > +	if (ret < 0)
> > > > +		return false;
> > > > +
> > > > +	return true;
> > > > +}
> > > >  
> > > > -	flags = bus_cfg.bus.parallel.flags;
> > > > +static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np)
> > > > +{
> > > > +	struct device *dev = decoder->sd.dev;
> > > > +	struct v4l2_fwnode_endpoint bus_cfg;
> > > > +	struct device_node *ep_np;
> > > > +	unsigned int flags;
> > > > +	int ret, i = 0, in = 0;
> > > > +	bool found = false;
> > > >  
> > > > -	if (bus_cfg.bus_type == V4L2_MBUS_PARALLEL &&
> > > > -	    !(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH &&
> > > > -	      flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH &&
> > > > -	      flags & V4L2_MBUS_FIELD_EVEN_LOW)) {
> > > > +	/* at least 1 output and 1 input */
> > > > +	decoder->endpoints_num = of_graph_get_endpoint_count(np);
> > > > +	if (decoder->endpoints_num < 2 || decoder->endpoints_num > 4) {
> > > >  		ret = -EINVAL;
> > > >  		goto err;
> > > >  	}
> > > >  
> > > > -	decoder->mbus_type = bus_cfg.bus_type;
> > > > +	for_each_endpoint_of_node(np, ep_np) {
> > > > +		struct of_endpoint ep;
> > > >  
> > > > +		of_graph_parse_endpoint(ep_np, &ep);
> > > > +		if (decoder->endpoints[i]) {
> > > > +			/* this should never happen */
> > > > +			dev_err(dev, "Invalid endpoint %pOF on port %d\n",
> > > > +				ep.local_node, ep.port);
> > > > +				ret = -EINVAL;
> > > > +				goto err;
> > > > +		}
> > > > +
> > > > +		switch (ep.port) {
> > > > +		case TVP5150_PAD_AIP1A:
> > > > +		case TVP5150_PAD_AIP1B:
> > > > +			if (!tvp5150_valid_input(ep_np, ep.port, ep.id)) {
> > > > +				dev_err(dev,
> > > > +					"Invalid endpoint %pOF on port %d\n",
> > > > +					ep.local_node, ep.port);
> > > > +				ret = -EINVAL;
> > > > +				goto err;
> > > > +			}
> > > > +			in++;
> > > > +			break;
> > > > +		case TVP5150_PAD_VID_OUT:
> > > > +			ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_np),
> > > > +							 &bus_cfg);
> > > > +			if (ret)
> > > > +				goto err;
> > > > +
> > > > +			flags = bus_cfg.bus.parallel.flags;
> > > > +
> > > > +			if (bus_cfg.bus_type == V4L2_MBUS_PARALLEL &&
> > > > +			    !(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH &&
> > > > +			      flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH &&
> > > > +			      flags & V4L2_MBUS_FIELD_EVEN_LOW)) {
> > > > +				ret = -EINVAL;
> > > > +				goto err;
> > > > +			}
> > > > +
> > > > +			decoder->mbus_type = bus_cfg.bus_type;
> > > > +			break;
> > > > +		default:
> > > > +			dev_err(dev, "Invalid port %d for endpoint %pOF\n",
> > > > +				ep.port, ep.local_node);
> > > > +			ret = -EINVAL;
> > > > +			goto err;
> > > > +		}
> > > > +
> > > > +		of_node_get(ep_np);
> > > > +		decoder->endpoints[i] = ep_np;
> > > > +		i++;
> > > > +
> > > > +		found = true;
> > > > +	}
> > > > +
> > > > +	decoder->connectors_num = in;
> > > > +	return found ? 0 : -ENODEV;
> > > >  err:
> > > > -	of_node_put(ep);
> > > >  	return ret;
> > > >  }
> > > >  
> > > > +static void tvp5150_dt_cleanup(struct tvp5150 *decoder)
> > > > +{
> > > > +	unsigned int i;
> > > > +
> > > > +	for (i = 0; i < TVP5150_NUM_PADS; i++)
> > > > +		of_node_put(decoder->endpoints[i]);
> > > > +}
> > > > +
> > > >  static const char * const tvp5150_test_patterns[2] = {
> > > >  	"Disabled",
> > > >  	"Black screen"
> > > > @@ -1586,7 +1933,7 @@ static int tvp5150_probe(struct i2c_client *c,
> > > >  		res = tvp5150_parse_dt(core, np);
> > > >  		if (res) {
> > > >  			dev_err(sd->dev, "DT parsing error: %d\n", res);
> > > > -			return res;
> > > > +			goto err_cleanup_dt;
> > > >  		}
> > > >  	} else {
> > > >  		/* Default to BT.656 embedded sync */
> > > > @@ -1594,25 +1941,16 @@ static int tvp5150_probe(struct i2c_client *c,
> > > >  	}
> > > >  
> > > >  	v4l2_i2c_subdev_init(sd, c, &tvp5150_ops);
> > > > +	sd->internal_ops = &tvp5150_internal_ops;
> > > >  	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
> > > >  
> > > > -#if defined(CONFIG_MEDIA_CONTROLLER)
> > > > -	core->pads[TVP5150_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
> > > > -	core->pads[TVP5150_PAD_IF_INPUT].sig_type = PAD_SIGNAL_ANALOG;
> > > > -	core->pads[TVP5150_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
> > > > -	core->pads[TVP5150_PAD_VID_OUT].sig_type = PAD_SIGNAL_DV;
> > > > -
> > > > -	sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
> > > > -
> > > > -	res = media_entity_pads_init(&sd->entity, TVP5150_NUM_PADS, core->pads);
> > > > -	if (res < 0)
> > > > -		return res;
> > > > -
> > > > -#endif
> > > > +	res = tvp5150_mc_init(sd);
> > > > +	if (res)
> > > > +		goto err_cleanup_dt;
> > > >  
> > > >  	res = tvp5150_detect_version(core);
> > > >  	if (res < 0)
> > > > -		return res;
> > > > +		goto err_cleanup_dt;
> > > >  
> > > >  	core->norm = V4L2_STD_ALL;	/* Default is autodetect */
> > > >  	core->detected_norm = V4L2_STD_UNKNOWN;
> > > > @@ -1664,6 +2002,9 @@ static int tvp5150_probe(struct i2c_client *c,
> > > >  err:
> > > >  	v4l2_ctrl_handler_free(&core->hdl);
> > > >  	return res;
> > > > +err_cleanup_dt:
> > > > +	tvp5150_dt_cleanup(core);
> > > > +	return res;
> > > >  }
> > > >  
> > > >  static int tvp5150_remove(struct i2c_client *c)  
> > > 
> > > 
> > > 
> > > Thanks,
> > > Mauro  
> > 
> > Regards,
> > Marco
> 
> 
> 
> Thanks,
> Mauro

Regards,
Marco

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

* Re: [PATCH 19/22] [media] tvp5150: add input source selection of_graph support
  2018-08-09 14:35             ` Marco Felsch
@ 2018-08-09 16:04               ` Mauro Carvalho Chehab
  2018-08-09 16:34                 ` Marco Felsch
  0 siblings, 1 reply; 70+ messages in thread
From: Mauro Carvalho Chehab @ 2018-08-09 16:04 UTC (permalink / raw)
  To: Marco Felsch
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Em Thu, 9 Aug 2018 16:35:20 +0200
Marco Felsch <m.felsch@pengutronix.de> escreveu:

> Hi Mauro,
> 
> Thanks for your feedback.

> > > > > +	dev_dbg(sd->dev, "link setup '%s':%d->'%s':%d[%d]",
> > > > > +		remote->entity->name, remote->index, local->entity->name,
> > > > > +		local->index, flags & MEDIA_LNK_FL_ENABLED);    
> > > > 
> > > > Hmm... the remote is the connector, right? I would switch the
> > > > print message to point from the connector to tvp5150, as this is
> > > > the signal flow.    
> > > 
> > > I don't know what you mean, I tought that's what I'm already do. If I
> > > change it it will print something like: tvp5150 2-005d :0 -> Comp0 :0[1]  
> > 
> > Hmm... then "local" actually means the connector and "remote"
> > is the tvp5150?  
> 
> Nope, local is the tvp and remote is the connector. Actual the output
> looks as follows
> 
> [   26.339939] tvp5150 2-005d: link setup 'Comp0':0->'tvp5150 2-005d':0[1]
> [   26.346606] tvp5150 2-005d: Setting 0 active [composite]
> 
> I think this is what you mean with '... point from the connector to
> tvp5150 ...'.

Yes.

> 
> >   
> > >   
> > > > 
> > > > Btw, it would likely be better to call it "connector" or "conn_entity",
> > > > to make it clearer.    
> > > 
> > > I tought remote is the common nomenclature. Also the remote mustn't be a
> > > connector. In my case it's a soldered camera. With this in mind, you think
> > > it should be still changed?  
> > 
> > I see your point.
> > 
> > Yeah, remote is a common nomenclature. Yet, as it can be seen from
> > the above comment (and your answer), common nomenclature may lead
> > in to mistakes :-)  
> 
> Yeah, I know what you mean ^^
> 
> > 
> > It would be good to have either one of sides better named (either
> > the connectors side or the tvp5150 side - or both), in order to be
> > clearer and avoid confusion of someone else touches that part of
> > the code.  
> 
> Yes, I'm with you. Since the local always points to the tvp5150, I will
> change the local to tvp5150 or tvp5150_pad. Renaming the remote isn't
> that good since it can be anything.

OK!

> 
> > 
> > In this specific case, both connectors and tvp5150 are created by
> > the tvp5150, so both are "local" in the sense that both are
> > created by this driver.
> >  
> 
> I know.. Maybe there should be a 'common' svideo-/composite-connector
> code and some helpers to create and link those. Then we can drop the
> 'local' connectors.

Yeah, that could be a good idea.

> > > > > +static int tvp5150_registered(struct v4l2_subdev *sd)
> > > > > +{
> > > > > +#ifdef CONFIG_MEDIA_CONTROLLER
> > > > > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > > > > +	unsigned int i;
> > > > > +	int ret;
> > > > > +
> > > > > +	for (i = 0; i < decoder->connectors_num; i++) {
> > > > > +		struct media_entity *con = &decoder->connectors[i].ent;
> > > > > +		struct media_pad *pad = &decoder->connectors[i].pad;
> > > > > +		unsigned int port = decoder->connectors[i].port_num;
> > > > > +		bool is_svideo = decoder->connectors[i].is_svideo;
> > > > > +
> > > > > +		pad->flags = MEDIA_PAD_FL_SOURCE;
> > > > > +		ret = media_entity_pads_init(con, 1, pad);
> > > > > +		if (ret < 0)
> > > > > +			return ret;
> > > > > +
> > > > > +		ret = media_device_register_entity(sd->v4l2_dev->mdev, con);
> > > > > +		if (ret < 0)
> > > > > +			return ret;
> > > > > +
> > > > > +		ret = media_create_pad_link(con, 0, &sd->entity, port, 0);
> > > > > +		if (ret < 0) {
> > > > > +			media_device_unregister_entity(con);
> > > > > +			return ret;
> > > > > +		}
> > > > > +
> > > > > +		if (is_svideo) {
> > > > > +			/* svideo links to both aip1a and aip1b */
> > > > > +			ret = media_create_pad_link(con, 0, &sd->entity,
> > > > > +						    port + 1, 0);
> > > > > +			if (ret < 0) {
> > > > > +				media_device_unregister_entity(con);
> > > > > +				return ret;
> > > > > +			}
> > > > > +		}
> > > > > +
> > > > > +	}    
> > > > 
> > > > IMO, it should route to the first available connector.    
> > > 
> > > Did you mean to set the link status to enabled?   
> > 
> > Yes.
> >   
> > > If so I have one
> > > question else can you tell me what you mean?
> > > 
> > > Should I use the media_entity_setup_link() helper or should I mark it as
> > > enabled during media_create_pad_link()? Now I did something like:
> > > 
> > > if (i == 0) {
> > > 	list_for_each_entry(link, &con->links, list) {
> > > 		media_entity_setup_link(link, MEDIA_LNK_FL_ENABLED);
> > > 	}
> > > }  
> > 
> > yeah, I guess this should work for both the cases where the first
> > connector is a comp or a svideo input.
> > 
> > I would prefer coding it differently, e. g. something like:
> > 
> > 	
> > 	for (i = 0; i < decoder->connectors_num; i++) {
> > 		int flags = i ? 0 : MEDIA_LNK_FL_ENABLED;
> > 
> > and then use the flags var as the last argument for media_create_pad_link()
> > calls. That would avoid an extra loop and would likely reduce a little bit
> > the code size.  
> 
> Sorry for the ambiguous code example. I did the 'if (i == 0)' in the same
> loop, so no extra loop. I can do it your way, but than unnecessary
> media_entity_setup_link() are made.

I got that, but:

	list_for_each_entry(link, &con->links, list) {
		media_entity_setup_link(link, MEDIA_LNK_FL_ENABLED);
	}

would be a second loop inside it :-)

What do you mean by an unnecessary media_entity_setup_link()?

What I was thinking is something like:

	static int tvp5150_registered(struct v4l2_subdev *sd)
	{
	#ifdef CONFIG_MEDIA_CONTROLLER
		struct tvp5150 *decoder = to_tvp5150(sd);
		unsigned int i;
		int ret;

		for (i = 0; i < decoder->connectors_num; i++) {
			struct media_entity *con = &decoder->connectors[i].ent;
			struct media_pad *pad = &decoder->connectors[i].pad;
			unsigned int port = decoder->connectors[i].port_num;
			bool is_svideo = decoder->connectors[i].is_svideo;
+			int link_flags = i ? 0 : MEDIA_LNK_FL_ENABLED;

			pad->flags = MEDIA_PAD_FL_SOURCE;
			ret = media_entity_pads_init(con, 1, pad);
			if (ret < 0)
				return ret;

			ret = media_device_register_entity(sd->v4l2_dev->mdev, con);
			if (ret < 0)
				return ret;

-			ret = media_create_pad_link(con, 0, &sd->entity, port, 0);
+			ret = media_create_pad_link(con, 0, &sd->entity, port, link_flags);
			if (ret < 0) {
				media_device_unregister_entity(con);
				return ret;
			}

			if (is_svideo) {
				/* svideo links to both aip1a and aip1b */
				ret = media_create_pad_link(con, 0, &sd->entity,
-							    port + 1, 0);
+							    port + 1, link_flags);
				if (ret < 0) {
					media_device_unregister_entity(con);
					return ret;
				}
			}
		}    


Thanks,
Mauro

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

* Re: [PATCH 19/22] [media] tvp5150: add input source selection of_graph support
  2018-08-09 16:04               ` Mauro Carvalho Chehab
@ 2018-08-09 16:34                 ` Marco Felsch
  0 siblings, 0 replies; 70+ messages in thread
From: Marco Felsch @ 2018-08-09 16:34 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: mchehab, robh+dt, mark.rutland, p.zabel, afshin.nasser, javierm,
	sakari.ailus, laurent.pinchart, linux-media, devicetree, kernel

Hi Mauro,

On 18-08-09 13:04, Mauro Carvalho Chehab wrote:
> Em Thu, 9 Aug 2018 16:35:20 +0200
> Marco Felsch <m.felsch@pengutronix.de> escreveu:
> 
> > Hi Mauro,
> > 
> > Thanks for your feedback.
> 
> > > > > > +	dev_dbg(sd->dev, "link setup '%s':%d->'%s':%d[%d]",
> > > > > > +		remote->entity->name, remote->index, local->entity->name,
> > > > > > +		local->index, flags & MEDIA_LNK_FL_ENABLED);    
> > > > > 
> > > > > Hmm... the remote is the connector, right? I would switch the
> > > > > print message to point from the connector to tvp5150, as this is
> > > > > the signal flow.    
> > > > 
> > > > I don't know what you mean, I tought that's what I'm already do. If I
> > > > change it it will print something like: tvp5150 2-005d :0 -> Comp0 :0[1]  
> > > 
> > > Hmm... then "local" actually means the connector and "remote"
> > > is the tvp5150?  
> > 
> > Nope, local is the tvp and remote is the connector. Actual the output
> > looks as follows
> > 
> > [   26.339939] tvp5150 2-005d: link setup 'Comp0':0->'tvp5150 2-005d':0[1]
> > [   26.346606] tvp5150 2-005d: Setting 0 active [composite]
> > 
> > I think this is what you mean with '... point from the connector to
> > tvp5150 ...'.
> 
> Yes.
> 
> > 
> > >   
> > > >   
> > > > > 
> > > > > Btw, it would likely be better to call it "connector" or "conn_entity",
> > > > > to make it clearer.    
> > > > 
> > > > I tought remote is the common nomenclature. Also the remote mustn't be a
> > > > connector. In my case it's a soldered camera. With this in mind, you think
> > > > it should be still changed?  
> > > 
> > > I see your point.
> > > 
> > > Yeah, remote is a common nomenclature. Yet, as it can be seen from
> > > the above comment (and your answer), common nomenclature may lead
> > > in to mistakes :-)  
> > 
> > Yeah, I know what you mean ^^
> > 
> > > 
> > > It would be good to have either one of sides better named (either
> > > the connectors side or the tvp5150 side - or both), in order to be
> > > clearer and avoid confusion of someone else touches that part of
> > > the code.  
> > 
> > Yes, I'm with you. Since the local always points to the tvp5150, I will
> > change the local to tvp5150 or tvp5150_pad. Renaming the remote isn't
> > that good since it can be anything.
> 
> OK!
> 
> > 
> > > 
> > > In this specific case, both connectors and tvp5150 are created by
> > > the tvp5150, so both are "local" in the sense that both are
> > > created by this driver.
> > >  
> > 
> > I know.. Maybe there should be a 'common' svideo-/composite-connector
> > code and some helpers to create and link those. Then we can drop the
> > 'local' connectors.
> 
> Yeah, that could be a good idea.
> 
> > > > > > +static int tvp5150_registered(struct v4l2_subdev *sd)
> > > > > > +{
> > > > > > +#ifdef CONFIG_MEDIA_CONTROLLER
> > > > > > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > > > > > +	unsigned int i;
> > > > > > +	int ret;
> > > > > > +
> > > > > > +	for (i = 0; i < decoder->connectors_num; i++) {
> > > > > > +		struct media_entity *con = &decoder->connectors[i].ent;
> > > > > > +		struct media_pad *pad = &decoder->connectors[i].pad;
> > > > > > +		unsigned int port = decoder->connectors[i].port_num;
> > > > > > +		bool is_svideo = decoder->connectors[i].is_svideo;
> > > > > > +
> > > > > > +		pad->flags = MEDIA_PAD_FL_SOURCE;
> > > > > > +		ret = media_entity_pads_init(con, 1, pad);
> > > > > > +		if (ret < 0)
> > > > > > +			return ret;
> > > > > > +
> > > > > > +		ret = media_device_register_entity(sd->v4l2_dev->mdev, con);
> > > > > > +		if (ret < 0)
> > > > > > +			return ret;
> > > > > > +
> > > > > > +		ret = media_create_pad_link(con, 0, &sd->entity, port, 0);
> > > > > > +		if (ret < 0) {
> > > > > > +			media_device_unregister_entity(con);
> > > > > > +			return ret;
> > > > > > +		}
> > > > > > +
> > > > > > +		if (is_svideo) {
> > > > > > +			/* svideo links to both aip1a and aip1b */
> > > > > > +			ret = media_create_pad_link(con, 0, &sd->entity,
> > > > > > +						    port + 1, 0);
> > > > > > +			if (ret < 0) {
> > > > > > +				media_device_unregister_entity(con);
> > > > > > +				return ret;
> > > > > > +			}
> > > > > > +		}
> > > > > > +
> > > > > > +	}    
> > > > > 
> > > > > IMO, it should route to the first available connector.    
> > > > 
> > > > Did you mean to set the link status to enabled?   
> > > 
> > > Yes.
> > >   
> > > > If so I have one
> > > > question else can you tell me what you mean?
> > > > 
> > > > Should I use the media_entity_setup_link() helper or should I mark it as
> > > > enabled during media_create_pad_link()? Now I did something like:
> > > > 
> > > > if (i == 0) {
> > > > 	list_for_each_entry(link, &con->links, list) {
> > > > 		media_entity_setup_link(link, MEDIA_LNK_FL_ENABLED);
> > > > 	}
> > > > }  
> > > 
> > > yeah, I guess this should work for both the cases where the first
> > > connector is a comp or a svideo input.
> > > 
> > > I would prefer coding it differently, e. g. something like:
> > > 
> > > 	
> > > 	for (i = 0; i < decoder->connectors_num; i++) {
> > > 		int flags = i ? 0 : MEDIA_LNK_FL_ENABLED;
> > > 
> > > and then use the flags var as the last argument for media_create_pad_link()
> > > calls. That would avoid an extra loop and would likely reduce a little bit
> > > the code size.  
> > 
> > Sorry for the ambiguous code example. I did the 'if (i == 0)' in the same
> > loop, so no extra loop. I can do it your way, but than unnecessary
> > media_entity_setup_link() are made.
> 
> I got that, but:
> 
> 	list_for_each_entry(link, &con->links, list) {
> 		media_entity_setup_link(link, MEDIA_LNK_FL_ENABLED);
> 	}
> 
> would be a second loop inside it :-)
> 
> What do you mean by an unnecessary media_entity_setup_link()?
> 
> What I was thinking is something like:

Oh, okay I tought you mean I should at the link_flags to the
media_entity_setup_link() call inside the list_for_each_entry(). Now I
got you, I will enable the link the during the media_create_pad_link()
call. This answers my initial question :)

> 
> 	static int tvp5150_registered(struct v4l2_subdev *sd)
> 	{
> 	#ifdef CONFIG_MEDIA_CONTROLLER
> 		struct tvp5150 *decoder = to_tvp5150(sd);
> 		unsigned int i;
> 		int ret;
> 
> 		for (i = 0; i < decoder->connectors_num; i++) {
> 			struct media_entity *con = &decoder->connectors[i].ent;
> 			struct media_pad *pad = &decoder->connectors[i].pad;
> 			unsigned int port = decoder->connectors[i].port_num;
> 			bool is_svideo = decoder->connectors[i].is_svideo;
> +			int link_flags = i ? 0 : MEDIA_LNK_FL_ENABLED;
> 
> 			pad->flags = MEDIA_PAD_FL_SOURCE;
> 			ret = media_entity_pads_init(con, 1, pad);
> 			if (ret < 0)
> 				return ret;
> 
> 			ret = media_device_register_entity(sd->v4l2_dev->mdev, con);
> 			if (ret < 0)
> 				return ret;
> 
> -			ret = media_create_pad_link(con, 0, &sd->entity, port, 0);
> +			ret = media_create_pad_link(con, 0, &sd->entity, port, link_flags);
> 			if (ret < 0) {
> 				media_device_unregister_entity(con);
> 				return ret;
> 			}
> 
> 			if (is_svideo) {
> 				/* svideo links to both aip1a and aip1b */
> 				ret = media_create_pad_link(con, 0, &sd->entity,
> -							    port + 1, 0);
> +							    port + 1, link_flags);
> 				if (ret < 0) {
> 					media_device_unregister_entity(con);
> 					return ret;
> 				}
> 			}
> 		}    
> 
> 
> Thanks,
> Mauro
> 

Thanks a lot for your feedback :) I will prepare the v2. This v2 will
only contain those patches which aren't applied to your tvp5150-3 branch.
Is that okay?

Regards,
Marco

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

end of thread, other threads:[~2018-08-09 16:34 UTC | newest]

Thread overview: 70+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-28 16:20 [PATCH 00/21] TVP5150 fixes and new features Marco Felsch
2018-06-28 16:20 ` [PATCH 01/22] [media] tvp5150: fix width alignment during set_selection() Marco Felsch
2018-06-28 16:20 ` [PATCH 02/22] [media] tvp5150: fix switch exit in set control handler Marco Felsch
2018-06-28 16:20 ` [PATCH 03/22] [media] tvp5150: convert register access to regmap Marco Felsch
2018-06-28 16:20 ` [PATCH 04/22] [media] tvp5150: make use of regmap_update_bits Marco Felsch
2018-06-28 16:20 ` [PATCH 05/22] [media] v4l2-rect.h: add position and equal helpers Marco Felsch
2018-06-29 14:12   ` Sakari Ailus
2018-06-28 16:20 ` [PATCH 06/22] [media] tvp5150: add FORMAT_TRY support for get/set selection handlers Marco Felsch
2018-07-31  0:01   ` Mauro Carvalho Chehab
2018-08-09 13:52     ` Marco Felsch
2018-06-28 16:20 ` [PATCH 07/22] [media] tvp5150: add default format helper Marco Felsch
2018-06-28 16:20 ` [PATCH 08/22] [media] tvp5150: trigger autodetection on subdev open to reset cropping Marco Felsch
2018-06-28 16:20 ` [PATCH 09/22] [media] tvp5150: fix standard autodetection Marco Felsch
2018-06-28 16:20 ` [PATCH 10/22] [media] tvp5150: split reset/enable routine Marco Felsch
2018-06-28 16:20 ` [PATCH 11/22] [media] tvp5150: remove pin configuration from initialization tables Marco Felsch
2018-06-28 16:20 ` [PATCH 12/22] [media] tvp5150: Add sync lock interrupt handling Marco Felsch
2018-06-28 16:20 ` [PATCH 13/22] [media] tvp5150: disable output while signal not locked Marco Felsch
2018-07-30 18:00   ` Mauro Carvalho Chehab
2018-07-30 18:06     ` Mauro Carvalho Chehab
2018-07-31  6:02     ` Marco Felsch
2018-06-28 16:20 ` [PATCH 14/22] [media] tvp5150: issue source change events Marco Felsch
2018-06-28 16:20 ` [PATCH 15/22] [media] tvp5150: add sync lock/loss signal debug messages Marco Felsch
2018-06-28 16:20 ` [PATCH 16/22] [media] tvp5150: add querystd Marco Felsch
2018-07-30 18:09   ` Mauro Carvalho Chehab
2018-08-01 13:21     ` Marco Felsch
2018-08-01 14:22       ` Mauro Carvalho Chehab
2018-08-01 14:49         ` Marco Felsch
2018-08-01 15:50           ` Mauro Carvalho Chehab
2018-08-02  8:01             ` Marco Felsch
2018-08-02  9:49               ` Mauro Carvalho Chehab
2018-08-02 10:16                 ` Marco Felsch
2018-08-02 14:38                   ` Mauro Carvalho Chehab
2018-08-02 10:54                 ` Ian Arkver
2018-08-02 11:58                   ` Marco Felsch
2018-06-28 16:20 ` [PATCH 17/22] [media] tvp5150: add g_std callback Marco Felsch
2018-06-28 16:20 ` [PATCH 18/22] partial revert of "[media] tvp5150: add HW input connectors support" Marco Felsch
2018-07-03 23:19   ` Rob Herring
2018-07-30 18:18   ` Mauro Carvalho Chehab
2018-07-31  7:01     ` Marco Felsch
2018-07-31  8:52     ` Javier Martinez Canillas
2018-07-31 10:06       ` Mauro Carvalho Chehab
2018-07-31 11:26         ` Javier Martinez Canillas
2018-07-31 12:36           ` Marco Felsch
2018-07-31 12:52             ` Javier Martinez Canillas
2018-07-31 13:30               ` Marco Felsch
2018-07-31 19:56                 ` Mauro Carvalho Chehab
2018-08-01 12:10                   ` Marco Felsch
2018-08-01 13:32                     ` Mauro Carvalho Chehab
2018-08-01 15:49                 ` Marco Felsch
2018-08-01 16:23                   ` Javier Martinez Canillas
2018-07-31 13:01             ` Mauro Carvalho Chehab
2018-07-31 13:22         ` Mauro Carvalho Chehab
2018-06-28 16:20 ` [PATCH 19/22] [media] tvp5150: add input source selection of_graph support Marco Felsch
2018-07-30 18:29   ` Mauro Carvalho Chehab
2018-08-08 15:29     ` Marco Felsch
2018-08-08 18:52       ` Mauro Carvalho Chehab
2018-08-09 12:55         ` Marco Felsch
2018-08-09 13:36           ` Mauro Carvalho Chehab
2018-08-09 14:35             ` Marco Felsch
2018-08-09 16:04               ` Mauro Carvalho Chehab
2018-08-09 16:34                 ` Marco Felsch
2018-06-28 16:20 ` [PATCH 20/22] [media] tvp5150: Add input port connectors DT bindings Marco Felsch
2018-07-03 23:23   ` Rob Herring
2018-07-11  8:50     ` Marco Felsch
2018-08-03  7:29     ` Marco Felsch
2018-08-03 17:30       ` Mauro Carvalho Chehab
2018-08-04  9:04         ` Marco Felsch
2018-06-28 16:20 ` [PATCH 21/22] [media] tvp5150: initialize subdev before parsing device tree Marco Felsch
2018-06-28 16:20 ` [PATCH 22/22] [media] tvp5150: Change default input source selection behaviour Marco Felsch
2018-06-28 20:57 ` [PATCH 00/21] TVP5150 fixes and new features Javier Martinez Canillas

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