All of lore.kernel.org
 help / color / mirror / Atom feed
* vivid: Add HDMI (dis)connect emulation
@ 2019-05-28 17:19 johan.korsnes
  2019-05-28 17:19 ` [PATCH 1/8] media: vivid: make input dv_timings per-input johan.korsnes
                   ` (7 more replies)
  0 siblings, 8 replies; 12+ messages in thread
From: johan.korsnes @ 2019-05-28 17:19 UTC (permalink / raw)
  To: linux-media

This patch series makes vivid V4L2-compliant* by adding HDMI (dis)-
connect emulation. This is done by by adding a custom display_present
control to vivid output HDMI devices, along with the following standard
controls:

-ctrl_tx_edid_present
-ctrl_tx_hotplug
-ctrl_tx_rxsense
-ctrl_rx_power_present

* Fixes the following warning for HDMI input devices:
   -V4L2_CID_DV_RX_POWER_PRESENT not found for input n
  Fixes the following warnings for HDMI ouptut devices:
   -V4L2_CID_DV_TX_HOTPLUG not found for output n
   -V4L2_CID_DV_TX_EDID_PRESENT not found for output n

Johan Korsnes (8):
      media: vivid: make input dv_timings per-input
      media: vivid: make input std_signal per-input
      media: vivid: add display present control
      media: vivid: add number of HDMI ports to device state
      media: vivid: add HDMI (dis)connect TX emulation
      media: vivid: add HDMI (dis)connect RX emulation
      media: vivid: add CEC support to display present ctrl
      media: vivid.rst: describe display present control

Documentation/media/v4l-drivers/vivid.rst     |   5 +
drivers/media/platform/vivid/vivid-core.c     |  36 ++++--
drivers/media/platform/vivid/vivid-core.h     |  32 +++--
drivers/media/platform/vivid/vivid-ctrls.c    | 105 ++++++++++++++--
.../media/platform/vivid/vivid-kthread-cap.c  |   8 +-
drivers/media/platform/vivid/vivid-vbi-cap.c  |  16 +--
drivers/media/platform/vivid/vivid-vid-cap.c  | 119 +++++++++++-------
.../media/platform/vivid/vivid-vid-common.c   |   8 +-
drivers/media/platform/vivid/vivid-vid-out.c  |   6 +
9 files changed, 245 insertions(+), 90 deletions(-)



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

* [PATCH 1/8] media: vivid: make input dv_timings per-input
  2019-05-28 17:19 vivid: Add HDMI (dis)connect emulation johan.korsnes
@ 2019-05-28 17:19 ` johan.korsnes
  2019-05-28 17:19 ` [PATCH 2/8] media: vivid: make input std_signal per-input johan.korsnes
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: johan.korsnes @ 2019-05-28 17:19 UTC (permalink / raw)
  To: linux-media; +Cc: Johan Korsnes

From: Johan Korsnes <johan.korsnes@gmail.com>

Make the following properties per-input

-DV Timings Signal Mode
-DV Timings

These properties need to be per-input in order to implement proper
HDMI (dis)connect-behavior, where the signal mode will be used to
signify whether or not there is an input device connected.

Signed-off-by: Johan Korsnes <johan.korsnes@gmail.com>
---
 drivers/media/platform/vivid/vivid-core.c     | 12 +++-
 drivers/media/platform/vivid/vivid-core.h     | 11 ++--
 drivers/media/platform/vivid/vivid-ctrls.c    | 13 ++--
 .../media/platform/vivid/vivid-kthread-cap.c  |  2 +-
 drivers/media/platform/vivid/vivid-vid-cap.c  | 63 ++++++++++++-------
 .../media/platform/vivid/vivid-vid-common.c   |  2 +-
 6 files changed, 69 insertions(+), 34 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c
index 7047df6f0e0e..49cc3b429b48 100644
--- a/drivers/media/platform/vivid/vivid-core.c
+++ b/drivers/media/platform/vivid/vivid-core.c
@@ -1007,7 +1007,8 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
 		tvnorms_cap = V4L2_STD_ALL;
 	if (dev->output_type[0] == SVID)
 		tvnorms_out = V4L2_STD_ALL;
-	dev->dv_timings_cap = def_dv_timings;
+	for (i = 0; i < MAX_INPUTS; i++)
+		dev->dv_timings_cap[i] = def_dv_timings;
 	dev->dv_timings_out = def_dv_timings;
 	dev->tv_freq = 2804 /* 175.25 * 16 */;
 	dev->tv_audmode = V4L2_TUNER_MODE_STEREO;
@@ -1037,6 +1038,15 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
 	if (ret)
 		goto unreg_dev;
 
+	/* enable/disable interface specific controls */
+	if (dev->num_inputs && dev->input_type[0] != HDMI) {
+		v4l2_ctrl_activate(dev->ctrl_dv_timings_signal_mode, false);
+		v4l2_ctrl_activate(dev->ctrl_dv_timings, false);
+	} else if (dev->num_inputs && dev->input_type[0] == HDMI) {
+		v4l2_ctrl_activate(dev->ctrl_std_signal_mode, false);
+		v4l2_ctrl_activate(dev->ctrl_standard, false);
+	}
+
 	/*
 	 * update the capture and output formats to do a proper initial
 	 * configuration.
diff --git a/drivers/media/platform/vivid/vivid-core.h b/drivers/media/platform/vivid/vivid-core.h
index 6697c7009629..a77c548f47d8 100644
--- a/drivers/media/platform/vivid/vivid-core.h
+++ b/drivers/media/platform/vivid/vivid-core.h
@@ -304,18 +304,19 @@ struct vivid_dev {
 	v4l2_std_id			query_std;
 	enum tpg_video_aspect		std_aspect_ratio;
 
-	enum vivid_signal_mode		dv_timings_signal_mode;
+	enum vivid_signal_mode		dv_timings_signal_mode[MAX_INPUTS];
 	char				**query_dv_timings_qmenu;
 	char				*query_dv_timings_qmenu_strings;
 	unsigned			query_dv_timings_size;
-	unsigned			query_dv_timings_last;
-	unsigned			query_dv_timings;
-	enum tpg_video_aspect		dv_timings_aspect_ratio;
+	unsigned			query_dv_timings_last[MAX_INPUTS];
+	unsigned			query_dv_timings[MAX_INPUTS];
+	enum tpg_video_aspect		dv_timings_aspect_ratio[MAX_INPUTS];
 
 	/* Input */
 	unsigned			input;
 	v4l2_std_id			std_cap;
-	struct v4l2_dv_timings		dv_timings_cap;
+	struct v4l2_dv_timings		dv_timings_cap[MAX_INPUTS];
+	int				dv_timings_cap_sel[MAX_INPUTS];
 	u32				service_set_cap;
 	struct vivid_vbi_gen_data	vbi_gen;
 	u8				*edid;
diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c
index 4cd526ff248b..a3c9661caf95 100644
--- a/drivers/media/platform/vivid/vivid-ctrls.c
+++ b/drivers/media/platform/vivid/vivid-ctrls.c
@@ -467,16 +467,19 @@ static int vivid_vid_cap_s_ctrl(struct v4l2_ctrl *ctrl)
 		tpg_s_video_aspect(&dev->tpg, vivid_get_video_aspect(dev));
 		break;
 	case VIVID_CID_DV_TIMINGS_SIGNAL_MODE:
-		dev->dv_timings_signal_mode = dev->ctrl_dv_timings_signal_mode->val;
-		if (dev->dv_timings_signal_mode == SELECTED_DV_TIMINGS)
-			dev->query_dv_timings = dev->ctrl_dv_timings->val;
+		dev->dv_timings_signal_mode[dev->input] =
+			dev->ctrl_dv_timings_signal_mode->val;
+		dev->query_dv_timings[dev->input] = dev->ctrl_dv_timings->val;
+
 		v4l2_ctrl_activate(dev->ctrl_dv_timings,
-				dev->dv_timings_signal_mode == SELECTED_DV_TIMINGS);
+			dev->dv_timings_signal_mode[dev->input] ==
+				SELECTED_DV_TIMINGS);
+
 		vivid_update_quality(dev);
 		vivid_send_source_change(dev, HDMI);
 		break;
 	case VIVID_CID_DV_TIMINGS_ASPECT_RATIO:
-		dev->dv_timings_aspect_ratio = ctrl->val;
+		dev->dv_timings_aspect_ratio[dev->input] = ctrl->val;
 		tpg_s_video_aspect(&dev->tpg, vivid_get_video_aspect(dev));
 		break;
 	case VIVID_CID_TSTAMP_SRC:
diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c b/drivers/media/platform/vivid/vivid-kthread-cap.c
index f8006a30c12f..b4eee952e1c9 100644
--- a/drivers/media/platform/vivid/vivid-kthread-cap.c
+++ b/drivers/media/platform/vivid/vivid-kthread-cap.c
@@ -421,7 +421,7 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
 		((vivid_is_svid_cap(dev) &&
 		!VIVID_INVALID_SIGNAL(dev->std_signal_mode)) ||
 		(vivid_is_hdmi_cap(dev) &&
-		!VIVID_INVALID_SIGNAL(dev->dv_timings_signal_mode))))
+		!VIVID_INVALID_SIGNAL(dev->dv_timings_signal_mode[dev->input]))))
 		is_loop = true;
 
 	buf->vb.sequence = dev->vid_cap_seq_count;
diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c
index 530ac8decb25..f4354c800088 100644
--- a/drivers/media/platform/vivid/vivid-vid-cap.c
+++ b/drivers/media/platform/vivid/vivid-vid-cap.c
@@ -299,7 +299,8 @@ void vivid_update_quality(struct vivid_dev *dev)
 		tpg_s_quality(&dev->tpg, TPG_QUAL_NOISE, 0);
 		return;
 	}
-	if (vivid_is_hdmi_cap(dev) && VIVID_INVALID_SIGNAL(dev->dv_timings_signal_mode)) {
+	if (vivid_is_hdmi_cap(dev) &&
+	    VIVID_INVALID_SIGNAL(dev->dv_timings_signal_mode[dev->input])) {
 		tpg_s_quality(&dev->tpg, TPG_QUAL_NOISE, 0);
 		return;
 	}
@@ -361,7 +362,7 @@ enum tpg_video_aspect vivid_get_video_aspect(const struct vivid_dev *dev)
 		return dev->std_aspect_ratio;
 
 	if (vivid_is_hdmi_cap(dev))
-		return dev->dv_timings_aspect_ratio;
+		return dev->dv_timings_aspect_ratio[dev->input];
 
 	return TPG_VIDEO_ASPECT_IMAGE;
 }
@@ -386,7 +387,7 @@ static enum tpg_pixel_aspect vivid_get_pixel_aspect(const struct vivid_dev *dev)
  */
 void vivid_update_format_cap(struct vivid_dev *dev, bool keep_controls)
 {
-	struct v4l2_bt_timings *bt = &dev->dv_timings_cap.bt;
+	struct v4l2_bt_timings *bt = &dev->dv_timings_cap[dev->input].bt;
 	unsigned size;
 	u64 pixelclock;
 
@@ -486,8 +487,8 @@ static enum v4l2_field vivid_field_cap(struct vivid_dev *dev, enum v4l2_field fi
 		}
 	}
 	if (vivid_is_hdmi_cap(dev))
-		return dev->dv_timings_cap.bt.interlaced ? V4L2_FIELD_ALTERNATE :
-						       V4L2_FIELD_NONE;
+		return dev->dv_timings_cap[dev->input].bt.interlaced ?
+			V4L2_FIELD_ALTERNATE : V4L2_FIELD_NONE;
 	return V4L2_FIELD_NONE;
 }
 
@@ -1310,10 +1311,10 @@ int vidioc_enum_input(struct file *file, void *priv,
 				dev->input_name_counter[inp->index]);
 		inp->capabilities = V4L2_IN_CAP_DV_TIMINGS;
 		if (dev->edid_blocks == 0 ||
-		    dev->dv_timings_signal_mode == NO_SIGNAL)
+		    dev->dv_timings_signal_mode[dev->input] == NO_SIGNAL)
 			inp->status |= V4L2_IN_ST_NO_SIGNAL;
-		else if (dev->dv_timings_signal_mode == NO_LOCK ||
-			 dev->dv_timings_signal_mode == OUT_OF_RANGE)
+		else if (dev->dv_timings_signal_mode[dev->input] == NO_LOCK ||
+			 dev->dv_timings_signal_mode[dev->input] == OUT_OF_RANGE)
 			inp->status |= V4L2_IN_ST_NO_H_LOCK;
 		break;
 	}
@@ -1353,7 +1354,7 @@ int vidioc_g_input(struct file *file, void *priv, unsigned *i)
 int vidioc_s_input(struct file *file, void *priv, unsigned i)
 {
 	struct vivid_dev *dev = video_drvdata(file);
-	struct v4l2_bt_timings *bt = &dev->dv_timings_cap.bt;
+	struct v4l2_bt_timings *bt = &dev->dv_timings_cap[dev->input].bt;
 	unsigned brightness;
 
 	if (i >= dev->num_inputs)
@@ -1407,6 +1408,20 @@ int vidioc_s_input(struct file *file, void *priv, unsigned i)
 	v4l2_ctrl_modify_range(dev->brightness,
 			128 * i, 255 + 128 * i, 1, 128 + 128 * i);
 	v4l2_ctrl_s_ctrl(dev->brightness, brightness);
+
+	/* Restore per-input states. */
+	v4l2_ctrl_activate(dev->ctrl_dv_timings_signal_mode,
+			   vivid_is_hdmi_cap(dev));
+	v4l2_ctrl_activate(dev->ctrl_dv_timings, vivid_is_hdmi_cap(dev) &&
+			   dev->dv_timings_signal_mode[dev->input] ==
+			   SELECTED_DV_TIMINGS);
+	if (vivid_is_hdmi_cap(dev)) {
+		v4l2_ctrl_s_ctrl(dev->ctrl_dv_timings_signal_mode,
+				 dev->dv_timings_signal_mode[dev->input]);
+		v4l2_ctrl_s_ctrl(dev->ctrl_dv_timings,
+				 dev->query_dv_timings[dev->input]);
+	}
+
 	return 0;
 }
 
@@ -1676,12 +1691,13 @@ int vivid_vid_cap_s_dv_timings(struct file *file, void *_fh,
 	    !valid_cvt_gtf_timings(timings))
 		return -EINVAL;
 
-	if (v4l2_match_dv_timings(timings, &dev->dv_timings_cap, 0, false))
+	if (v4l2_match_dv_timings(timings, &dev->dv_timings_cap[dev->input],
+				  0, false))
 		return 0;
 	if (vb2_is_busy(&dev->vb_vid_cap_q))
 		return -EBUSY;
 
-	dev->dv_timings_cap = *timings;
+	dev->dv_timings_cap[dev->input] = *timings;
 	vivid_update_format_cap(dev, false);
 	return 0;
 }
@@ -1690,26 +1706,31 @@ int vidioc_query_dv_timings(struct file *file, void *_fh,
 				    struct v4l2_dv_timings *timings)
 {
 	struct vivid_dev *dev = video_drvdata(file);
+	unsigned input = dev->input;
 
 	if (!vivid_is_hdmi_cap(dev))
 		return -ENODATA;
-	if (dev->dv_timings_signal_mode == NO_SIGNAL ||
+	if (dev->dv_timings_signal_mode[input] == NO_SIGNAL ||
 	    dev->edid_blocks == 0)
 		return -ENOLINK;
-	if (dev->dv_timings_signal_mode == NO_LOCK)
+	if (dev->dv_timings_signal_mode[input] == NO_LOCK)
 		return -ENOLCK;
-	if (dev->dv_timings_signal_mode == OUT_OF_RANGE) {
+	if (dev->dv_timings_signal_mode[input] == OUT_OF_RANGE) {
 		timings->bt.pixelclock = vivid_dv_timings_cap.bt.max_pixelclock * 2;
 		return -ERANGE;
 	}
-	if (dev->dv_timings_signal_mode == CURRENT_DV_TIMINGS) {
-		*timings = dev->dv_timings_cap;
-	} else if (dev->dv_timings_signal_mode == SELECTED_DV_TIMINGS) {
-		*timings = v4l2_dv_timings_presets[dev->query_dv_timings];
+	if (dev->dv_timings_signal_mode[input] == CURRENT_DV_TIMINGS) {
+		*timings = dev->dv_timings_cap[input];
+	} else if (dev->dv_timings_signal_mode[input] ==
+		   SELECTED_DV_TIMINGS) {
+		*timings =
+			v4l2_dv_timings_presets[dev->query_dv_timings[input]];
 	} else {
-		*timings = v4l2_dv_timings_presets[dev->query_dv_timings_last];
-		dev->query_dv_timings_last = (dev->query_dv_timings_last + 1) %
-						dev->query_dv_timings_size;
+		*timings =
+			v4l2_dv_timings_presets[dev->query_dv_timings_last[input]];
+		dev->query_dv_timings_last[input] =
+			(dev->query_dv_timings_last[input] + 1) %
+			dev->query_dv_timings_size;
 	}
 	return 0;
 }
diff --git a/drivers/media/platform/vivid/vivid-vid-common.c b/drivers/media/platform/vivid/vivid-vid-common.c
index 74b83bcc6119..1d6576ac539b 100644
--- a/drivers/media/platform/vivid/vivid-vid-common.c
+++ b/drivers/media/platform/vivid/vivid-vid-common.c
@@ -843,7 +843,7 @@ int vidioc_g_dv_timings(struct file *file, void *_fh,
 	if (vdev->vfl_dir == VFL_DIR_RX) {
 		if (!vivid_is_hdmi_cap(dev))
 			return -ENODATA;
-		*timings = dev->dv_timings_cap;
+		*timings = dev->dv_timings_cap[dev->input];
 	} else {
 		if (!vivid_is_hdmi_out(dev))
 			return -ENODATA;
-- 
2.17.1


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

* [PATCH 2/8] media: vivid: make input std_signal per-input
  2019-05-28 17:19 vivid: Add HDMI (dis)connect emulation johan.korsnes
  2019-05-28 17:19 ` [PATCH 1/8] media: vivid: make input dv_timings per-input johan.korsnes
@ 2019-05-28 17:19 ` johan.korsnes
  2019-05-28 17:19 ` [PATCH 3/8] media: vivid: add display present control johan.korsnes
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: johan.korsnes @ 2019-05-28 17:19 UTC (permalink / raw)
  To: linux-media; +Cc: Johan Korsnes

From: Johan Korsnes <johan.korsnes@gmail.com>

Make the following properties per-input:

-Standard Signal Mode
-Standard

These properties need to be per-input in order to implement proper HDMI
(dis)connect-behavior, where the signal mode will be used to signify
whether or not there is an inpute device connected.

Signed-off-by: Johan Korsnes <johan.korsnes@gmail.com>
---
 drivers/media/platform/vivid/vivid-core.c     |  5 +-
 drivers/media/platform/vivid/vivid-core.h     | 10 ++--
 drivers/media/platform/vivid/vivid-ctrls.c    | 13 +++--
 .../media/platform/vivid/vivid-kthread-cap.c  |  6 +--
 drivers/media/platform/vivid/vivid-vbi-cap.c  | 16 +++---
 drivers/media/platform/vivid/vivid-vid-cap.c  | 50 +++++++++++--------
 .../media/platform/vivid/vivid-vid-common.c   |  4 +-
 7 files changed, 59 insertions(+), 45 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c
index 49cc3b429b48..c4c31d0e006a 100644
--- a/drivers/media/platform/vivid/vivid-core.c
+++ b/drivers/media/platform/vivid/vivid-core.c
@@ -1001,14 +1001,15 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
 	dev->webcam_size_idx = 1;
 	dev->webcam_ival_idx = 3;
 	tpg_s_fourcc(&dev->tpg, dev->fmt_cap->fourcc);
-	dev->std_cap = V4L2_STD_PAL;
 	dev->std_out = V4L2_STD_PAL;
 	if (dev->input_type[0] == TV || dev->input_type[0] == SVID)
 		tvnorms_cap = V4L2_STD_ALL;
 	if (dev->output_type[0] == SVID)
 		tvnorms_out = V4L2_STD_ALL;
-	for (i = 0; i < MAX_INPUTS; i++)
+	for (i = 0; i < MAX_INPUTS; i++) {
 		dev->dv_timings_cap[i] = def_dv_timings;
+		dev->std_cap[i] = V4L2_STD_PAL;
+	}
 	dev->dv_timings_out = def_dv_timings;
 	dev->tv_freq = 2804 /* 175.25 * 16 */;
 	dev->tv_audmode = V4L2_TUNER_MODE_STEREO;
diff --git a/drivers/media/platform/vivid/vivid-core.h b/drivers/media/platform/vivid/vivid-core.h
index a77c548f47d8..a18fd19215b6 100644
--- a/drivers/media/platform/vivid/vivid-core.h
+++ b/drivers/media/platform/vivid/vivid-core.h
@@ -299,10 +299,10 @@ struct vivid_dev {
 	bool				time_wrap;
 	u64				time_wrap_offset;
 	unsigned			perc_dropped_buffers;
-	enum vivid_signal_mode		std_signal_mode;
-	unsigned			query_std_last;
-	v4l2_std_id			query_std;
-	enum tpg_video_aspect		std_aspect_ratio;
+	enum vivid_signal_mode		std_signal_mode[MAX_INPUTS];
+	unsigned			query_std_last[MAX_INPUTS];
+	v4l2_std_id			query_std[MAX_INPUTS];
+	enum tpg_video_aspect		std_aspect_ratio[MAX_INPUTS];
 
 	enum vivid_signal_mode		dv_timings_signal_mode[MAX_INPUTS];
 	char				**query_dv_timings_qmenu;
@@ -314,7 +314,7 @@ struct vivid_dev {
 
 	/* Input */
 	unsigned			input;
-	v4l2_std_id			std_cap;
+	v4l2_std_id			std_cap[MAX_INPUTS];
 	struct v4l2_dv_timings		dv_timings_cap[MAX_INPUTS];
 	int				dv_timings_cap_sel[MAX_INPUTS];
 	u32				service_set_cap;
diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c
index a3c9661caf95..74b2c92fbfa0 100644
--- a/drivers/media/platform/vivid/vivid-ctrls.c
+++ b/drivers/media/platform/vivid/vivid-ctrls.c
@@ -463,7 +463,7 @@ static int vivid_vid_cap_s_ctrl(struct v4l2_ctrl *ctrl)
 		tpg_s_show_square(&dev->tpg, ctrl->val);
 		break;
 	case VIVID_CID_STD_ASPECT_RATIO:
-		dev->std_aspect_ratio = ctrl->val;
+		dev->std_aspect_ratio[dev->input] = ctrl->val;
 		tpg_s_video_aspect(&dev->tpg, vivid_get_video_aspect(dev));
 		break;
 	case VIVID_CID_DV_TIMINGS_SIGNAL_MODE:
@@ -1130,10 +1130,13 @@ static int vivid_sdtv_cap_s_ctrl(struct v4l2_ctrl *ctrl)
 
 	switch (ctrl->id) {
 	case VIVID_CID_STD_SIGNAL_MODE:
-		dev->std_signal_mode = dev->ctrl_std_signal_mode->val;
-		if (dev->std_signal_mode == SELECTED_STD)
-			dev->query_std = vivid_standard[dev->ctrl_standard->val];
-		v4l2_ctrl_activate(dev->ctrl_standard, dev->std_signal_mode == SELECTED_STD);
+		dev->std_signal_mode[dev->input] = dev->ctrl_std_signal_mode->val;
+		if (dev->std_signal_mode[dev->input] == SELECTED_STD)
+			dev->query_std[dev->input] =
+				vivid_standard[dev->ctrl_standard->val];
+		v4l2_ctrl_activate(dev->ctrl_standard,
+				   dev->std_signal_mode[dev->input] ==
+					SELECTED_STD);
 		vivid_update_quality(dev);
 		vivid_send_source_change(dev, TV);
 		vivid_send_source_change(dev, SVID);
diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c b/drivers/media/platform/vivid/vivid-kthread-cap.c
index b4eee952e1c9..6cf495a7d5cc 100644
--- a/drivers/media/platform/vivid/vivid-kthread-cap.c
+++ b/drivers/media/platform/vivid/vivid-kthread-cap.c
@@ -43,7 +43,7 @@
 static inline v4l2_std_id vivid_get_std_cap(const struct vivid_dev *dev)
 {
 	if (vivid_is_sdtv_cap(dev))
-		return dev->std_cap;
+		return dev->std_cap[dev->input];
 	return 0;
 }
 
@@ -408,7 +408,7 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
 	unsigned factor = V4L2_FIELD_HAS_T_OR_B(dev->field_cap) ? 2 : 1;
 	unsigned line_height = 16 / factor;
 	bool is_tv = vivid_is_sdtv_cap(dev);
-	bool is_60hz = is_tv && (dev->std_cap & V4L2_STD_525_60);
+	bool is_60hz = is_tv && (dev->std_cap[dev->input] & V4L2_STD_525_60);
 	unsigned p;
 	int line = 1;
 	u8 *basep[TPG_MAX_PLANES][2];
@@ -419,7 +419,7 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
 
 	if (dev->loop_video && dev->can_loop_video &&
 		((vivid_is_svid_cap(dev) &&
-		!VIVID_INVALID_SIGNAL(dev->std_signal_mode)) ||
+		!VIVID_INVALID_SIGNAL(dev->std_signal_mode[dev->input])) ||
 		(vivid_is_hdmi_cap(dev) &&
 		!VIVID_INVALID_SIGNAL(dev->dv_timings_signal_mode[dev->input]))))
 		is_loop = true;
diff --git a/drivers/media/platform/vivid/vivid-vbi-cap.c b/drivers/media/platform/vivid/vivid-vbi-cap.c
index 40ecd7902b56..1a9348eea781 100644
--- a/drivers/media/platform/vivid/vivid-vbi-cap.c
+++ b/drivers/media/platform/vivid/vivid-vbi-cap.c
@@ -18,7 +18,7 @@
 static void vivid_sliced_vbi_cap_fill(struct vivid_dev *dev, unsigned seqnr)
 {
 	struct vivid_vbi_gen_data *vbi_gen = &dev->vbi_gen;
-	bool is_60hz = dev->std_cap & V4L2_STD_525_60;
+	bool is_60hz = dev->std_cap[dev->input] & V4L2_STD_525_60;
 
 	vivid_vbi_gen_sliced(vbi_gen, is_60hz, seqnr);
 
@@ -65,7 +65,7 @@ static void vivid_sliced_vbi_cap_fill(struct vivid_dev *dev, unsigned seqnr)
 
 static void vivid_g_fmt_vbi_cap(struct vivid_dev *dev, struct v4l2_vbi_format *vbi)
 {
-	bool is_60hz = dev->std_cap & V4L2_STD_525_60;
+	bool is_60hz = dev->std_cap[dev->input] & V4L2_STD_525_60;
 
 	vbi->sampling_rate = 27000000;
 	vbi->offset = 24;
@@ -93,7 +93,7 @@ void vivid_raw_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
 
 	memset(vbuf, 0x10, vb2_plane_size(&buf->vb.vb2_buf, 0));
 
-	if (!VIVID_INVALID_SIGNAL(dev->std_signal_mode))
+	if (!VIVID_INVALID_SIGNAL(dev->std_signal_mode[dev->input]))
 		vivid_vbi_gen_raw(&dev->vbi_gen, &vbi, vbuf);
 }
 
@@ -111,7 +111,7 @@ void vivid_sliced_vbi_cap_process(struct vivid_dev *dev,
 	vivid_sliced_vbi_cap_fill(dev, buf->vb.sequence);
 
 	memset(vbuf, 0, vb2_plane_size(&buf->vb.vb2_buf, 0));
-	if (!VIVID_INVALID_SIGNAL(dev->std_signal_mode)) {
+	if (!VIVID_INVALID_SIGNAL(dev->std_signal_mode[dev->input])) {
 		unsigned i;
 
 		for (i = 0; i < 25; i++)
@@ -124,7 +124,7 @@ static int vbi_cap_queue_setup(struct vb2_queue *vq,
 		       unsigned sizes[], struct device *alloc_devs[])
 {
 	struct vivid_dev *dev = vb2_get_drv_priv(vq);
-	bool is_60hz = dev->std_cap & V4L2_STD_525_60;
+	bool is_60hz = dev->std_cap[dev->input] & V4L2_STD_525_60;
 	unsigned size = vq->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE ?
 		36 * sizeof(struct v4l2_sliced_vbi_data) :
 		1440 * 2 * (is_60hz ? 12 : 18);
@@ -144,7 +144,7 @@ static int vbi_cap_queue_setup(struct vb2_queue *vq,
 static int vbi_cap_buf_prepare(struct vb2_buffer *vb)
 {
 	struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
-	bool is_60hz = dev->std_cap & V4L2_STD_525_60;
+	bool is_60hz = dev->std_cap[dev->input] & V4L2_STD_525_60;
 	unsigned size = vb->vb2_queue->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE ?
 		36 * sizeof(struct v4l2_sliced_vbi_data) :
 		1440 * 2 * (is_60hz ? 12 : 18);
@@ -302,7 +302,7 @@ int vidioc_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_forma
 {
 	struct vivid_dev *dev = video_drvdata(file);
 	struct v4l2_sliced_vbi_format *vbi = &fmt->fmt.sliced;
-	bool is_60hz = dev->std_cap & V4L2_STD_525_60;
+	bool is_60hz = dev->std_cap[dev->input] & V4L2_STD_525_60;
 	u32 service_set = vbi->service_set;
 
 	if (!vivid_is_sdtv_cap(dev) || !dev->has_sliced_vbi_cap)
@@ -337,7 +337,7 @@ int vidioc_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_
 	bool is_60hz;
 
 	if (vdev->vfl_dir == VFL_DIR_RX) {
-		is_60hz = dev->std_cap & V4L2_STD_525_60;
+		is_60hz = dev->std_cap[dev->input] & V4L2_STD_525_60;
 		if (!vivid_is_sdtv_cap(dev) || !dev->has_sliced_vbi_cap ||
 		    cap->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
 			return -EINVAL;
diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c
index f4354c800088..ca15c13abf6c 100644
--- a/drivers/media/platform/vivid/vivid-vid-cap.c
+++ b/drivers/media/platform/vivid/vivid-vid-cap.c
@@ -196,7 +196,7 @@ static void vid_cap_buf_finish(struct vb2_buffer *vb)
 	 * test this.
 	 */
 	vbuf->flags |= V4L2_BUF_FLAG_TIMECODE;
-	if (dev->std_cap & V4L2_STD_525_60)
+	if (dev->std_cap[dev->input] & V4L2_STD_525_60)
 		fps = 30;
 	tc->type = (fps == 30) ? V4L2_TC_TYPE_30FPS : V4L2_TC_TYPE_25FPS;
 	tc->flags = 0;
@@ -304,7 +304,8 @@ void vivid_update_quality(struct vivid_dev *dev)
 		tpg_s_quality(&dev->tpg, TPG_QUAL_NOISE, 0);
 		return;
 	}
-	if (vivid_is_sdtv_cap(dev) && VIVID_INVALID_SIGNAL(dev->std_signal_mode)) {
+	if (vivid_is_sdtv_cap(dev) &&
+	    VIVID_INVALID_SIGNAL(dev->std_signal_mode[dev->input])) {
 		tpg_s_quality(&dev->tpg, TPG_QUAL_NOISE, 0);
 		return;
 	}
@@ -359,7 +360,7 @@ static enum tpg_quality vivid_get_quality(struct vivid_dev *dev, s32 *afc)
 enum tpg_video_aspect vivid_get_video_aspect(const struct vivid_dev *dev)
 {
 	if (vivid_is_sdtv_cap(dev))
-		return dev->std_aspect_ratio;
+		return dev->std_aspect_ratio[dev->input];
 
 	if (vivid_is_hdmi_cap(dev))
 		return dev->dv_timings_aspect_ratio[dev->input];
@@ -370,7 +371,7 @@ enum tpg_video_aspect vivid_get_video_aspect(const struct vivid_dev *dev)
 static enum tpg_pixel_aspect vivid_get_pixel_aspect(const struct vivid_dev *dev)
 {
 	if (vivid_is_sdtv_cap(dev))
-		return (dev->std_cap & V4L2_STD_525_60) ?
+		return (dev->std_cap[dev->input] & V4L2_STD_525_60) ?
 			TPG_PIXEL_ASPECT_NTSC : TPG_PIXEL_ASPECT_PAL;
 
 	if (vivid_is_hdmi_cap(dev) &&
@@ -404,7 +405,7 @@ void vivid_update_format_cap(struct vivid_dev *dev, bool keep_controls)
 	case SVID:
 		dev->field_cap = dev->tv_field_cap;
 		dev->src_rect.width = 720;
-		if (dev->std_cap & V4L2_STD_525_60) {
+		if (dev->std_cap[dev->input] & V4L2_STD_525_60) {
 			dev->src_rect.height = 480;
 			dev->timeperframe_vid_cap = (struct v4l2_fract) { 1001, 30000 };
 			dev->service_set_cap = V4L2_SLICED_CAPTION_525;
@@ -587,7 +588,7 @@ int vivid_try_fmt_vid_cap(struct file *file, void *priv,
 		h = sz->height;
 	} else if (vivid_is_sdtv_cap(dev)) {
 		w = 720;
-		h = (dev->std_cap & V4L2_STD_525_60) ? 480 : 576;
+		h = (dev->std_cap[dev->input] & V4L2_STD_525_60) ? 480 : 576;
 	} else {
 		w = dev->src_rect.width;
 		h = dev->src_rect.height;
@@ -1323,9 +1324,9 @@ int vidioc_enum_input(struct file *file, void *priv,
 	if (dev->sensor_vflip)
 		inp->status |= V4L2_IN_ST_VFLIP;
 	if (dev->input == inp->index && vivid_is_sdtv_cap(dev)) {
-		if (dev->std_signal_mode == NO_SIGNAL) {
+		if (dev->std_signal_mode[dev->input] == NO_SIGNAL) {
 			inp->status |= V4L2_IN_ST_NO_SIGNAL;
-		} else if (dev->std_signal_mode == NO_LOCK) {
+		} else if (dev->std_signal_mode[dev->input] == NO_LOCK) {
 			inp->status |= V4L2_IN_ST_NO_H_LOCK;
 		} else if (vivid_is_tv_cap(dev)) {
 			switch (tpg_g_quality(&dev->tpg)) {
@@ -1415,11 +1416,20 @@ int vidioc_s_input(struct file *file, void *priv, unsigned i)
 	v4l2_ctrl_activate(dev->ctrl_dv_timings, vivid_is_hdmi_cap(dev) &&
 			   dev->dv_timings_signal_mode[dev->input] ==
 			   SELECTED_DV_TIMINGS);
+	v4l2_ctrl_activate(dev->ctrl_std_signal_mode, vivid_is_sdtv_cap(dev));
+	v4l2_ctrl_activate(dev->ctrl_standard, vivid_is_sdtv_cap(dev) &&
+			   dev->std_signal_mode[dev->input]);
+
 	if (vivid_is_hdmi_cap(dev)) {
 		v4l2_ctrl_s_ctrl(dev->ctrl_dv_timings_signal_mode,
 				 dev->dv_timings_signal_mode[dev->input]);
 		v4l2_ctrl_s_ctrl(dev->ctrl_dv_timings,
 				 dev->query_dv_timings[dev->input]);
+	} else if (vivid_is_sdtv_cap(dev)) {
+		v4l2_ctrl_s_ctrl(dev->ctrl_std_signal_mode,
+				 dev->std_signal_mode[dev->input]);
+		v4l2_ctrl_s_ctrl(dev->ctrl_standard,
+				 dev->std_signal_mode[dev->input]);
 	}
 
 	return 0;
@@ -1515,7 +1525,7 @@ int vivid_video_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
 		vt->rxsubchans = V4L2_TUNER_SUB_MONO;
 	} else {
 		unsigned channel_nr = dev->tv_freq / (6 * 16);
-		unsigned options = (dev->std_cap & V4L2_STD_NTSC_M) ? 4 : 3;
+		unsigned options = (dev->std_cap[dev->input] & V4L2_STD_NTSC_M) ? 4 : 3;
 
 		switch (channel_nr % options) {
 		case 0:
@@ -1525,7 +1535,7 @@ int vivid_video_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
 			vt->rxsubchans = V4L2_TUNER_SUB_STEREO;
 			break;
 		case 2:
-			if (dev->std_cap & V4L2_STD_NTSC_M)
+			if (dev->std_cap[dev->input] & V4L2_STD_NTSC_M)
 				vt->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_SAP;
 			else
 				vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
@@ -1585,20 +1595,20 @@ int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *id)
 
 	if (!vivid_is_sdtv_cap(dev))
 		return -ENODATA;
-	if (dev->std_signal_mode == NO_SIGNAL ||
-	    dev->std_signal_mode == NO_LOCK) {
+	if (dev->std_signal_mode[dev->input] == NO_SIGNAL ||
+	    dev->std_signal_mode[dev->input] == NO_LOCK) {
 		*id = V4L2_STD_UNKNOWN;
 		return 0;
 	}
 	if (vivid_is_tv_cap(dev) && tpg_g_quality(&dev->tpg) == TPG_QUAL_NOISE) {
 		*id = V4L2_STD_UNKNOWN;
-	} else if (dev->std_signal_mode == CURRENT_STD) {
-		*id = dev->std_cap;
-	} else if (dev->std_signal_mode == SELECTED_STD) {
-		*id = dev->query_std;
+	} else if (dev->std_signal_mode[dev->input] == CURRENT_STD) {
+		*id = dev->std_cap[dev->input];
+	} else if (dev->std_signal_mode[dev->input] == SELECTED_STD) {
+		*id = dev->query_std[dev->input];
 	} else {
-		*id = vivid_standard[dev->query_std_last];
-		dev->query_std_last = (dev->query_std_last + 1) % ARRAY_SIZE(vivid_standard);
+		*id = vivid_standard[dev->query_std_last[dev->input]];
+		dev->query_std_last[dev->input] = (dev->query_std_last[dev->input] + 1) % ARRAY_SIZE(vivid_standard);
 	}
 
 	return 0;
@@ -1610,11 +1620,11 @@ int vivid_vid_cap_s_std(struct file *file, void *priv, v4l2_std_id id)
 
 	if (!vivid_is_sdtv_cap(dev))
 		return -ENODATA;
-	if (dev->std_cap == id)
+	if (dev->std_cap[dev->input] == id)
 		return 0;
 	if (vb2_is_busy(&dev->vb_vid_cap_q) || vb2_is_busy(&dev->vb_vbi_cap_q))
 		return -EBUSY;
-	dev->std_cap = id;
+	dev->std_cap[dev->input] = id;
 	vivid_update_format_cap(dev, false);
 	return 0;
 }
diff --git a/drivers/media/platform/vivid/vivid-vid-common.c b/drivers/media/platform/vivid/vivid-vid-common.c
index 1d6576ac539b..b6882426fc12 100644
--- a/drivers/media/platform/vivid/vivid-vid-common.c
+++ b/drivers/media/platform/vivid/vivid-vid-common.c
@@ -645,7 +645,7 @@ bool vivid_vid_can_loop(struct vivid_dev *dev)
 	    dev->field_cap == V4L2_FIELD_SEQ_BT)
 		return false;
 	if (vivid_is_svid_cap(dev) && vivid_is_svid_out(dev)) {
-		if (!(dev->std_cap & V4L2_STD_525_60) !=
+		if (!(dev->std_cap[dev->input] & V4L2_STD_525_60) !=
 		    !(dev->std_out & V4L2_STD_525_60))
 			return false;
 		return true;
@@ -825,7 +825,7 @@ int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
 	if (vdev->vfl_dir == VFL_DIR_RX) {
 		if (!vivid_is_sdtv_cap(dev))
 			return -ENODATA;
-		*id = dev->std_cap;
+		*id = dev->std_cap[dev->input];
 	} else {
 		if (!vivid_is_svid_out(dev))
 			return -ENODATA;
-- 
2.17.1


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

* [PATCH 3/8] media: vivid: add display present control
  2019-05-28 17:19 vivid: Add HDMI (dis)connect emulation johan.korsnes
  2019-05-28 17:19 ` [PATCH 1/8] media: vivid: make input dv_timings per-input johan.korsnes
  2019-05-28 17:19 ` [PATCH 2/8] media: vivid: make input std_signal per-input johan.korsnes
@ 2019-05-28 17:19 ` johan.korsnes
  2019-05-28 17:19 ` [PATCH 4/8] media: vivid: add number of HDMI ports to device state johan.korsnes
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: johan.korsnes @ 2019-05-28 17:19 UTC (permalink / raw)
  To: linux-media; +Cc: Johan Korsnes

From: Johan Korsnes <johan.korsnes@gmail.com>

Add a custom control for selecting the presence of a display connected
to the active output. This control is part of an effort to implement
proper HDMI (dis)connect behavior for vivid.

Signed-off-by: Johan Korsnes <johan.korsnes@gmail.com>
---
 drivers/media/platform/vivid/vivid-core.c    |  3 +++
 drivers/media/platform/vivid/vivid-core.h    |  2 ++
 drivers/media/platform/vivid/vivid-ctrls.c   | 18 ++++++++++++++++++
 drivers/media/platform/vivid/vivid-vid-out.c |  6 ++++++
 4 files changed, 29 insertions(+)

diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c
index c4c31d0e006a..20a0dcebd783 100644
--- a/drivers/media/platform/vivid/vivid-core.c
+++ b/drivers/media/platform/vivid/vivid-core.c
@@ -732,6 +732,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
 	for (i = 0; i < dev->num_outputs; i++) {
 		dev->output_type[i] = ((output_types[inst] >> i) & 1) ? HDMI : SVID;
 		dev->output_name_counter[i] = out_type_counter[dev->output_type[i]]++;
+		dev->display_present[i] = true;
 	}
 	dev->has_audio_outputs = out_type_counter[SVID];
 	if (out_type_counter[HDMI] == 16) {
@@ -1040,6 +1041,8 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
 		goto unreg_dev;
 
 	/* enable/disable interface specific controls */
+	if (dev->num_outputs && dev->output_type[0] != HDMI)
+		v4l2_ctrl_activate(dev->ctrl_display_present, false);
 	if (dev->num_inputs && dev->input_type[0] != HDMI) {
 		v4l2_ctrl_activate(dev->ctrl_dv_timings_signal_mode, false);
 		v4l2_ctrl_activate(dev->ctrl_dv_timings, false);
diff --git a/drivers/media/platform/vivid/vivid-core.h b/drivers/media/platform/vivid/vivid-core.h
index a18fd19215b6..24104df6c444 100644
--- a/drivers/media/platform/vivid/vivid-core.h
+++ b/drivers/media/platform/vivid/vivid-core.h
@@ -237,6 +237,7 @@ struct vivid_dev {
 		struct v4l2_ctrl	*ctrl_dv_timings_signal_mode;
 		struct v4l2_ctrl	*ctrl_dv_timings;
 	};
+	struct v4l2_ctrl		*ctrl_display_present;
 	struct v4l2_ctrl		*ctrl_has_crop_cap;
 	struct v4l2_ctrl		*ctrl_has_compose_cap;
 	struct v4l2_ctrl		*ctrl_has_scaler_cap;
@@ -361,6 +362,7 @@ struct vivid_dev {
 	u8				*scaled_line;
 	u8				*blended_line;
 	unsigned			cur_scaled_line;
+	bool				display_present[MAX_OUTPUTS];
 
 	/* Output Overlay */
 	void				*fb_vbase_out;
diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c
index 74b2c92fbfa0..67a330f15552 100644
--- a/drivers/media/platform/vivid/vivid-ctrls.c
+++ b/drivers/media/platform/vivid/vivid-ctrls.c
@@ -68,6 +68,7 @@
 #define VIVID_CID_PERCENTAGE_FILL	(VIVID_CID_VIVID_BASE + 41)
 #define VIVID_CID_REDUCED_FPS		(VIVID_CID_VIVID_BASE + 42)
 #define VIVID_CID_HSV_ENC		(VIVID_CID_VIVID_BASE + 43)
+#define VIVID_CID_DISPLAY_PRESENT	(VIVID_CID_VIVID_BASE + 44)
 
 #define VIVID_CID_STD_SIGNAL_MODE	(VIVID_CID_VIVID_BASE + 60)
 #define VIVID_CID_STANDARD		(VIVID_CID_VIVID_BASE + 61)
@@ -944,6 +945,12 @@ static int vivid_vid_out_s_ctrl(struct v4l2_ctrl *ctrl)
 		if (dev->loop_video)
 			vivid_send_source_change(dev, HDMI);
 		break;
+	case VIVID_CID_DISPLAY_PRESENT:
+		if (dev->output_type[dev->output] != HDMI)
+			break;
+
+		dev->display_present[dev->output] = ctrl->val;
+		break;
 	}
 	return 0;
 }
@@ -982,6 +989,15 @@ static const struct v4l2_ctrl_config vivid_ctrl_has_scaler_out = {
 	.step = 1,
 };
 
+static const struct v4l2_ctrl_config vivid_ctrl_display_present = {
+	.ops = &vivid_vid_out_ctrl_ops,
+	.id = VIVID_CID_DISPLAY_PRESENT,
+	.name = "Display Present",
+	.type = V4L2_CTRL_TYPE_BOOLEAN,
+	.max = 1,
+	.def = 1,
+	.step = 1,
+};
 
 /* Streaming Controls */
 
@@ -1587,6 +1603,8 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap,
 		dev->ctrl_tx_mode = v4l2_ctrl_new_std_menu(hdl_vid_out, NULL,
 			V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI,
 			0, V4L2_DV_TX_MODE_HDMI);
+		dev->ctrl_display_present = v4l2_ctrl_new_custom(hdl_vid_out,
+			&vivid_ctrl_display_present, NULL);
 	}
 	if ((dev->has_vid_cap && dev->has_vid_out) ||
 	    (dev->has_vbi_cap && dev->has_vbi_out))
diff --git a/drivers/media/platform/vivid/vivid-vid-out.c b/drivers/media/platform/vivid/vivid-vid-out.c
index 9350ca65dd91..148b663a6075 100644
--- a/drivers/media/platform/vivid/vivid-vid-out.c
+++ b/drivers/media/platform/vivid/vivid-vid-out.c
@@ -1094,6 +1094,12 @@ int vidioc_s_output(struct file *file, void *priv, unsigned o)
 
 	dev->vbi_out_dev.tvnorms = dev->vid_out_dev.tvnorms;
 	vivid_update_format_out(dev);
+
+	v4l2_ctrl_activate(dev->ctrl_display_present, vivid_is_hdmi_out(dev));
+	if (vivid_is_hdmi_out(dev))
+		v4l2_ctrl_s_ctrl(dev->ctrl_display_present,
+				 dev->display_present[dev->output]);
+
 	return 0;
 }
 
-- 
2.17.1


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

* [PATCH 4/8] media: vivid: add number of HDMI ports to device state
  2019-05-28 17:19 vivid: Add HDMI (dis)connect emulation johan.korsnes
                   ` (2 preceding siblings ...)
  2019-05-28 17:19 ` [PATCH 3/8] media: vivid: add display present control johan.korsnes
@ 2019-05-28 17:19 ` johan.korsnes
  2019-05-28 17:19 ` [PATCH 5/8] media: vivid: add HDMI (dis)connect TX emulation johan.korsnes
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: johan.korsnes @ 2019-05-28 17:19 UTC (permalink / raw)
  To: linux-media; +Cc: Johan Korsnes

From: Johan Korsnes <johan.korsnes@gmail.com>

This will be used for HDMI-specific controls such as hotplug detection
and power present.

Signed-off-by: Johan Korsnes <johan.korsnes@gmail.com>
---
 drivers/media/platform/vivid/vivid-core.c | 2 ++
 drivers/media/platform/vivid/vivid-core.h | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c
index 20a0dcebd783..b2b4ee48cef0 100644
--- a/drivers/media/platform/vivid/vivid-core.c
+++ b/drivers/media/platform/vivid/vivid-core.c
@@ -722,6 +722,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
 		in_type_counter[HDMI]--;
 		dev->num_inputs--;
 	}
+	dev->num_hdmi_inputs = in_type_counter[HDMI];
 
 	/* how many outputs do we have and of what type? */
 	dev->num_outputs = num_outputs[inst];
@@ -744,6 +745,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
 		out_type_counter[HDMI]--;
 		dev->num_outputs--;
 	}
+	dev->num_hdmi_outputs = out_type_counter[HDMI];
 
 	/* do we create a video capture device? */
 	dev->has_vid_cap = node_type & 0x0001;
diff --git a/drivers/media/platform/vivid/vivid-core.h b/drivers/media/platform/vivid/vivid-core.h
index 24104df6c444..1d04b7209f2b 100644
--- a/drivers/media/platform/vivid/vivid-core.h
+++ b/drivers/media/platform/vivid/vivid-core.h
@@ -180,9 +180,11 @@ struct vivid_dev {
 	/* supported features */
 	bool				multiplanar;
 	unsigned			num_inputs;
+	unsigned			num_hdmi_inputs;
 	u8				input_type[MAX_INPUTS];
 	u8				input_name_counter[MAX_INPUTS];
 	unsigned			num_outputs;
+	unsigned			num_hdmi_outputs;
 	u8				output_type[MAX_OUTPUTS];
 	u8				output_name_counter[MAX_OUTPUTS];
 	bool				has_audio_inputs;
-- 
2.17.1


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

* [PATCH 5/8] media: vivid: add HDMI (dis)connect TX emulation
  2019-05-28 17:19 vivid: Add HDMI (dis)connect emulation johan.korsnes
                   ` (3 preceding siblings ...)
  2019-05-28 17:19 ` [PATCH 4/8] media: vivid: add number of HDMI ports to device state johan.korsnes
@ 2019-05-28 17:19 ` johan.korsnes
  2019-05-28 17:19 ` [PATCH 6/8] media: vivid: add HDMI (dis)connect RX emulation johan.korsnes
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: johan.korsnes @ 2019-05-28 17:19 UTC (permalink / raw)
  To: linux-media; +Cc: Johan Korsnes

From: Johan Korsnes <johan.korsnes@gmail.com>

Adds the following bitmask controls:
-V4L2_CID_DV_TX_EDID_PRESENT
-V4L2_CID_DV_TX_HOTPLUG
-V4L2_CID_DV_TX_RXSENSE

The bitmasks are all set based on the custom vivid DISPLAY_PRESENT
control. This also removes 2/2 v4l2-compliance warnings for vivid
output device.

Signed-off-by: Johan Korsnes <johan.korsnes@gmail.com>
---
 drivers/media/platform/vivid/vivid-core.h  |  3 +++
 drivers/media/platform/vivid/vivid-ctrls.c | 25 +++++++++++++++++++++-
 2 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/vivid/vivid-core.h b/drivers/media/platform/vivid/vivid-core.h
index 1d04b7209f2b..b7307cbba2a5 100644
--- a/drivers/media/platform/vivid/vivid-core.h
+++ b/drivers/media/platform/vivid/vivid-core.h
@@ -248,6 +248,9 @@ struct vivid_dev {
 	struct v4l2_ctrl		*ctrl_has_scaler_out;
 	struct v4l2_ctrl		*ctrl_tx_mode;
 	struct v4l2_ctrl		*ctrl_tx_rgb_range;
+	struct v4l2_ctrl		*ctrl_tx_edid_present;
+	struct v4l2_ctrl		*ctrl_tx_hotplug;
+	struct v4l2_ctrl		*ctrl_tx_rxsense;
 
 	struct v4l2_ctrl		*radio_tx_rds_pi;
 	struct v4l2_ctrl		*radio_tx_rds_pty;
diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c
index 67a330f15552..5cb7232a8278 100644
--- a/drivers/media/platform/vivid/vivid-ctrls.c
+++ b/drivers/media/platform/vivid/vivid-ctrls.c
@@ -912,6 +912,8 @@ static int vivid_vid_out_s_ctrl(struct v4l2_ctrl *ctrl)
 {
 	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vid_out);
 	struct v4l2_bt_timings *bt = &dev->dv_timings_out.bt;
+	u32 display_present = 0;
+	unsigned i, j;
 
 	switch (ctrl->id) {
 	case VIVID_CID_HAS_CROP_OUT:
@@ -950,6 +952,15 @@ static int vivid_vid_out_s_ctrl(struct v4l2_ctrl *ctrl)
 			break;
 
 		dev->display_present[dev->output] = ctrl->val;
+
+		for (i = 0, j = 0; i < dev->num_outputs; i++)
+			if (dev->output_type[i] == HDMI)
+				display_present |=
+					dev->display_present[i] << j++;
+
+		__v4l2_ctrl_s_ctrl(dev->ctrl_tx_hotplug, display_present);
+		__v4l2_ctrl_s_ctrl(dev->ctrl_tx_rxsense, display_present);
+		__v4l2_ctrl_s_ctrl(dev->ctrl_tx_edid_present, display_present);
 		break;
 	}
 	return 0;
@@ -1592,7 +1603,7 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap,
 			V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
 			0, V4L2_DV_RGB_RANGE_AUTO);
 	}
-	if (has_hdmi && dev->has_vid_out) {
+	if (dev->num_hdmi_outputs) {
 		/*
 		 * We aren't doing anything with this at the moment, but
 		 * HDMI outputs typically have this controls.
@@ -1605,6 +1616,18 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap,
 			0, V4L2_DV_TX_MODE_HDMI);
 		dev->ctrl_display_present = v4l2_ctrl_new_custom(hdl_vid_out,
 			&vivid_ctrl_display_present, NULL);
+		dev->ctrl_tx_hotplug = v4l2_ctrl_new_std(hdl_vid_out,
+			NULL, V4L2_CID_DV_TX_HOTPLUG, 0,
+			(2 << (dev->num_hdmi_outputs - 1)) - 1, 0,
+			(2 << (dev->num_hdmi_outputs - 1)) - 1);
+		dev->ctrl_tx_rxsense = v4l2_ctrl_new_std(hdl_vid_out,
+			NULL, V4L2_CID_DV_TX_RXSENSE, 0,
+			(2 << (dev->num_hdmi_outputs - 1)) - 1, 0,
+			(2 << (dev->num_hdmi_outputs - 1)) - 1);
+		dev->ctrl_tx_edid_present = v4l2_ctrl_new_std(hdl_vid_out,
+			NULL, V4L2_CID_DV_TX_EDID_PRESENT, 0,
+			(2 << (dev->num_hdmi_outputs - 1)) - 1, 0,
+			(2 << (dev->num_hdmi_outputs - 1)) - 1);
 	}
 	if ((dev->has_vid_cap && dev->has_vid_out) ||
 	    (dev->has_vbi_cap && dev->has_vbi_out))
-- 
2.17.1


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

* [PATCH 6/8] media: vivid: add HDMI (dis)connect RX emulation
  2019-05-28 17:19 vivid: Add HDMI (dis)connect emulation johan.korsnes
                   ` (4 preceding siblings ...)
  2019-05-28 17:19 ` [PATCH 5/8] media: vivid: add HDMI (dis)connect TX emulation johan.korsnes
@ 2019-05-28 17:19 ` johan.korsnes
  2019-05-28 17:19 ` [PATCH 7/8] media: vivid: add CEC support to display present ctrl johan.korsnes
  2019-05-28 17:19 ` [PATCH 8/8] media: vivid.rst: describe display present control johan.korsnes
  7 siblings, 0 replies; 12+ messages in thread
From: johan.korsnes @ 2019-05-28 17:19 UTC (permalink / raw)
  To: linux-media; +Cc: Johan Korsnes

From: Johan Korsnes <johan.korsnes@gmail.com>

Adds the following bitmask control:
-V4L2_CID_DV_RX_POWER_PRESENT

The RX_POWER_PRESENT bitmask is set based on the digital video timings
signal mode. This also removes 1/1 warnings for v4l2-compliance test on
vivid instance with HDMI input.

Signed-off-by: Johan Korsnes <johan.korsnes@gmail.com>
---
 drivers/media/platform/vivid/vivid-core.h  |  4 ++++
 drivers/media/platform/vivid/vivid-ctrls.c | 19 +++++++++++++++++--
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-core.h b/drivers/media/platform/vivid/vivid-core.h
index b7307cbba2a5..f5ad92c376f7 100644
--- a/drivers/media/platform/vivid/vivid-core.h
+++ b/drivers/media/platform/vivid/vivid-core.h
@@ -252,6 +252,8 @@ struct vivid_dev {
 	struct v4l2_ctrl		*ctrl_tx_hotplug;
 	struct v4l2_ctrl		*ctrl_tx_rxsense;
 
+	struct v4l2_ctrl		*ctrl_rx_power_present;
+
 	struct v4l2_ctrl		*radio_tx_rds_pi;
 	struct v4l2_ctrl		*radio_tx_rds_pty;
 	struct v4l2_ctrl		*radio_tx_rds_mono_stereo;
@@ -335,6 +337,8 @@ struct vivid_dev {
 	unsigned			tv_field_cap;
 	unsigned			tv_audio_input;
 
+	u32				power_present;
+
 	/* Capture Overlay */
 	struct v4l2_framebuffer		fb_cap;
 	struct v4l2_fh			*overlay_cap_owner;
diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c
index 5cb7232a8278..ae3690fd1b52 100644
--- a/drivers/media/platform/vivid/vivid-ctrls.c
+++ b/drivers/media/platform/vivid/vivid-ctrls.c
@@ -358,7 +358,7 @@ static int vivid_vid_cap_s_ctrl(struct v4l2_ctrl *ctrl)
 		V4L2_COLORSPACE_470_SYSTEM_BG,
 	};
 	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vid_cap);
-	unsigned i;
+	unsigned i, j;
 
 	switch (ctrl->id) {
 	case VIVID_CID_TEST_PATTERN:
@@ -472,6 +472,16 @@ static int vivid_vid_cap_s_ctrl(struct v4l2_ctrl *ctrl)
 			dev->ctrl_dv_timings_signal_mode->val;
 		dev->query_dv_timings[dev->input] = dev->ctrl_dv_timings->val;
 
+		dev->power_present = 0;
+		for (i = 0, j = 0; i < ARRAY_SIZE(dev->dv_timings_signal_mode); i++)
+			if (dev->input_type[i] == HDMI) {
+				if (dev->dv_timings_signal_mode[i] != NO_SIGNAL)
+					dev->power_present |= (1 << j);
+				j++;
+			}
+		__v4l2_ctrl_s_ctrl(dev->ctrl_rx_power_present,
+				   dev->power_present);
+
 		v4l2_ctrl_activate(dev->ctrl_dv_timings,
 			dev->dv_timings_signal_mode[dev->input] ==
 				SELECTED_DV_TIMINGS);
@@ -1582,7 +1592,7 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap,
 			v4l2_ctrl_new_custom(hdl_vbi_cap, &vivid_ctrl_vbi_cap_interlaced, NULL);
 	}
 
-	if (has_hdmi && dev->has_vid_cap) {
+	if (dev->num_hdmi_inputs) {
 		dev->ctrl_dv_timings_signal_mode = v4l2_ctrl_new_custom(hdl_vid_cap,
 					&vivid_ctrl_dv_timings_signal_mode, NULL);
 
@@ -1602,6 +1612,11 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap,
 			&vivid_vid_cap_ctrl_ops,
 			V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
 			0, V4L2_DV_RGB_RANGE_AUTO);
+		dev->ctrl_rx_power_present = v4l2_ctrl_new_std(hdl_vid_cap,
+			NULL, V4L2_CID_DV_RX_POWER_PRESENT, 0,
+			(2 << (dev->num_hdmi_inputs - 1)) - 1, 0,
+			(2 << (dev->num_hdmi_inputs - 1)) - 1);
+
 	}
 	if (dev->num_hdmi_outputs) {
 		/*
-- 
2.17.1


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

* [PATCH 7/8] media: vivid: add CEC support to display present ctrl
  2019-05-28 17:19 vivid: Add HDMI (dis)connect emulation johan.korsnes
                   ` (5 preceding siblings ...)
  2019-05-28 17:19 ` [PATCH 6/8] media: vivid: add HDMI (dis)connect RX emulation johan.korsnes
@ 2019-05-28 17:19 ` johan.korsnes
  2019-05-29  7:39   ` Hans Verkuil
  2019-05-28 17:19 ` [PATCH 8/8] media: vivid.rst: describe display present control johan.korsnes
  7 siblings, 1 reply; 12+ messages in thread
From: johan.korsnes @ 2019-05-28 17:19 UTC (permalink / raw)
  To: linux-media; +Cc: Johan Korsnes

From: Johan Korsnes <johan.korsnes@gmail.com>

Set/invalidate physical addresses based on the configuration of the
display present control. This is relevant not only when the display
present control is modified, but also when the Vivid instance EDID is
set/cleared.

Signed-off-by: Johan Korsnes <johan.korsnes@gmail.com>
---
 drivers/media/platform/vivid/vivid-core.c     | 16 ++++++------
 drivers/media/platform/vivid/vivid-ctrls.c    | 25 ++++++++++++++++---
 drivers/media/platform/vivid/vivid-vid-cap.c  |  6 ++++-
 .../media/platform/vivid/vivid-vid-common.c   |  2 ++
 4 files changed, 36 insertions(+), 13 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c
index b2b4ee48cef0..ca46ac24f51e 100644
--- a/drivers/media/platform/vivid/vivid-core.c
+++ b/drivers/media/platform/vivid/vivid-core.c
@@ -1060,14 +1060,6 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
 	vivid_update_format_cap(dev, false);
 	vivid_update_format_out(dev);
 
-	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vid_cap);
-	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vid_out);
-	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vbi_cap);
-	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vbi_out);
-	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_radio_rx);
-	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_radio_tx);
-	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_sdr_cap);
-
 	/* initialize overlay */
 	dev->fb_cap.fmt.width = dev->src_rect.width;
 	dev->fb_cap.fmt.height = dev->src_rect.height;
@@ -1488,6 +1480,14 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
 	}
 #endif
 
+	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vid_cap);
+	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vid_out);
+	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vbi_cap);
+	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vbi_out);
+	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_radio_rx);
+	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_radio_tx);
+	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_sdr_cap);
+
 	/* Now that everything is fine, let's add it to device list */
 	vivid_devs[inst] = dev;
 
diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c
index ae3690fd1b52..e4758a2837e6 100644
--- a/drivers/media/platform/vivid/vivid-ctrls.c
+++ b/drivers/media/platform/vivid/vivid-ctrls.c
@@ -18,6 +18,7 @@
 #include "vivid-radio-common.h"
 #include "vivid-osd.h"
 #include "vivid-ctrls.h"
+#include "vivid-cec.h"
 
 #define VIVID_CID_CUSTOM_BASE		(V4L2_CID_USER_BASE | 0xf000)
 #define VIVID_CID_BUTTON		(VIVID_CID_CUSTOM_BASE + 0)
@@ -923,7 +924,7 @@ static int vivid_vid_out_s_ctrl(struct v4l2_ctrl *ctrl)
 	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vid_out);
 	struct v4l2_bt_timings *bt = &dev->dv_timings_out.bt;
 	u32 display_present = 0;
-	unsigned i, j;
+	unsigned i, j, bus_idx;
 
 	switch (ctrl->id) {
 	case VIVID_CID_HAS_CROP_OUT:
@@ -962,15 +963,31 @@ static int vivid_vid_out_s_ctrl(struct v4l2_ctrl *ctrl)
 			break;
 
 		dev->display_present[dev->output] = ctrl->val;
-
 		for (i = 0, j = 0; i < dev->num_outputs; i++)
 			if (dev->output_type[i] == HDMI)
 				display_present |=
 					dev->display_present[i] << j++;
 
-		__v4l2_ctrl_s_ctrl(dev->ctrl_tx_hotplug, display_present);
 		__v4l2_ctrl_s_ctrl(dev->ctrl_tx_rxsense, display_present);
-		__v4l2_ctrl_s_ctrl(dev->ctrl_tx_edid_present, display_present);
+
+		if (dev->edid_blocks) {
+			__v4l2_ctrl_s_ctrl(dev->ctrl_tx_edid_present,
+					   display_present);
+			__v4l2_ctrl_s_ctrl(dev->ctrl_tx_hotplug,
+					   display_present);
+		}
+
+		if (dev->cec_tx_adap == NULL)
+			break;
+
+		bus_idx = dev->cec_output2bus_map[dev->output];
+		if (ctrl->val && dev->edid_blocks)
+			cec_s_phys_addr(dev->cec_tx_adap[bus_idx],
+					dev->cec_tx_adap[bus_idx]->phys_addr,
+					false);
+		else
+			cec_phys_addr_invalidate(dev->cec_tx_adap[bus_idx]);
+
 		break;
 	}
 	return 0;
diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c
index ca15c13abf6c..920be638da83 100644
--- a/drivers/media/platform/vivid/vivid-vid-cap.c
+++ b/drivers/media/platform/vivid/vivid-vid-cap.c
@@ -1760,6 +1760,7 @@ int vidioc_s_edid(struct file *file, void *_fh,
 		return -EINVAL;
 	if (edid->blocks == 0) {
 		dev->edid_blocks = 0;
+		v4l2_ctrl_s_ctrl(dev->ctrl_tx_edid_present, false);
 		phys_addr = CEC_PHYS_ADDR_INVALID;
 		goto set_phys_addr;
 	}
@@ -1777,6 +1778,7 @@ int vidioc_s_edid(struct file *file, void *_fh,
 
 	dev->edid_blocks = edid->blocks;
 	memcpy(dev->edid, edid->edid, edid->blocks * 128);
+	v4l2_ctrl_s_ctrl(dev->ctrl_tx_edid_present, true);
 
 set_phys_addr:
 	/* TODO: a proper hotplug detect cycle should be emulated here */
@@ -1784,7 +1786,9 @@ int vidioc_s_edid(struct file *file, void *_fh,
 
 	for (i = 0; i < MAX_OUTPUTS && dev->cec_tx_adap[i]; i++)
 		cec_s_phys_addr(dev->cec_tx_adap[i],
-				v4l2_phys_addr_for_input(phys_addr, i + 1),
+				dev->display_present[i] ?
+				v4l2_phys_addr_for_input(phys_addr, i + 1) :
+				CEC_PHYS_ADDR_INVALID,
 				false);
 	return 0;
 }
diff --git a/drivers/media/platform/vivid/vivid-vid-common.c b/drivers/media/platform/vivid/vivid-vid-common.c
index b6882426fc12..0addf8ef7dbf 100644
--- a/drivers/media/platform/vivid/vivid-vid-common.c
+++ b/drivers/media/platform/vivid/vivid-vid-common.c
@@ -907,6 +907,8 @@ int vidioc_g_edid(struct file *file, void *_fh,
 			return -EINVAL;
 		if (dev->output_type[edid->pad] != HDMI)
 			return -EINVAL;
+		if (!dev->display_present[dev->output])
+			return -ENODATA;
 		bus_idx = dev->cec_output2bus_map[edid->pad];
 		adap = dev->cec_tx_adap[bus_idx];
 	}
-- 
2.17.1


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

* [PATCH 8/8] media: vivid.rst: describe display present control
  2019-05-28 17:19 vivid: Add HDMI (dis)connect emulation johan.korsnes
                   ` (6 preceding siblings ...)
  2019-05-28 17:19 ` [PATCH 7/8] media: vivid: add CEC support to display present ctrl johan.korsnes
@ 2019-05-28 17:19 ` johan.korsnes
  7 siblings, 0 replies; 12+ messages in thread
From: johan.korsnes @ 2019-05-28 17:19 UTC (permalink / raw)
  To: linux-media; +Cc: Johan Korsnes

From: Johan Korsnes <johan.korsnes@gmail.com>

Signed-off-by: Johan Korsnes <johan.korsnes@gmail.com>
---
 Documentation/media/v4l-drivers/vivid.rst | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/media/v4l-drivers/vivid.rst b/Documentation/media/v4l-drivers/vivid.rst
index edb6f33e029c..7082fec4075d 100644
--- a/Documentation/media/v4l-drivers/vivid.rst
+++ b/Documentation/media/v4l-drivers/vivid.rst
@@ -941,6 +941,11 @@ Digital Video Controls
 	affects the reported colorspace since DVI_D outputs will always use
 	sRGB.
 
+- Display Present:
+
+	sets the presence of a "display" on the HDMI output. This affects
+	the tx_edid_present, tx_hotplug and tx_rxsense controls.
+
 
 FM Radio Receiver Controls
 ~~~~~~~~~~~~~~~~~~~~~~~~~~
-- 
2.17.1


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

* Re: [PATCH 7/8] media: vivid: add CEC support to display present ctrl
  2019-05-28 17:19 ` [PATCH 7/8] media: vivid: add CEC support to display present ctrl johan.korsnes
@ 2019-05-29  7:39   ` Hans Verkuil
  2019-06-11 20:25     ` Johan Korsnes
  0 siblings, 1 reply; 12+ messages in thread
From: Hans Verkuil @ 2019-05-29  7:39 UTC (permalink / raw)
  To: johan.korsnes, linux-media

Hi Johan,

Thanks for this patch series!

The previous patches all look good, but this one needs a bit more work:

On 5/28/19 7:19 PM, johan.korsnes@gmail.com wrote:
> From: Johan Korsnes <johan.korsnes@gmail.com>
> 
> Set/invalidate physical addresses based on the configuration of the
> display present control. This is relevant not only when the display
> present control is modified, but also when the Vivid instance EDID is
> set/cleared.
> 
> Signed-off-by: Johan Korsnes <johan.korsnes@gmail.com>
> ---
>  drivers/media/platform/vivid/vivid-core.c     | 16 ++++++------
>  drivers/media/platform/vivid/vivid-ctrls.c    | 25 ++++++++++++++++---
>  drivers/media/platform/vivid/vivid-vid-cap.c  |  6 ++++-
>  .../media/platform/vivid/vivid-vid-common.c   |  2 ++
>  4 files changed, 36 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c
> index b2b4ee48cef0..ca46ac24f51e 100644
> --- a/drivers/media/platform/vivid/vivid-core.c
> +++ b/drivers/media/platform/vivid/vivid-core.c
> @@ -1060,14 +1060,6 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
>  	vivid_update_format_cap(dev, false);
>  	vivid_update_format_out(dev);
>  
> -	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vid_cap);
> -	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vid_out);
> -	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vbi_cap);
> -	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vbi_out);
> -	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_radio_rx);
> -	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_radio_tx);
> -	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_sdr_cap);
> -
>  	/* initialize overlay */
>  	dev->fb_cap.fmt.width = dev->src_rect.width;
>  	dev->fb_cap.fmt.height = dev->src_rect.height;
> @@ -1488,6 +1480,14 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
>  	}
>  #endif
>  
> +	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vid_cap);
> +	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vid_out);
> +	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vbi_cap);
> +	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vbi_out);
> +	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_radio_rx);
> +	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_radio_tx);
> +	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_sdr_cap);
> +
>  	/* Now that everything is fine, let's add it to device list */
>  	vivid_devs[inst] = dev;
>  

This change should be in a patch of its own.

It also needs more work. The reason for this change is that v4l2_ctrl_handler_setup()
expects that the cec adapters are up and running, so moving these calls until after
the creation of the adapters fixes that.

However, that now means that controls change after the creation of the video devices,
which isn't right.

If you look at the probe() function you'll see that things are done in two stages:
first all the vb2 queues are created, and only if that succeeded are the video devices
created.

The same should be done for the CEC adapters: they should be allocated (vivid_cec_alloc_adap)
in the first stage, then call v4l2_ctrl_handler_setup(), and finally create the actual
device nodes (cec_register_adapter).

That way the controls are configured correctly before any device nodes are created.

> diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c
> index ae3690fd1b52..e4758a2837e6 100644
> --- a/drivers/media/platform/vivid/vivid-ctrls.c
> +++ b/drivers/media/platform/vivid/vivid-ctrls.c
> @@ -18,6 +18,7 @@
>  #include "vivid-radio-common.h"
>  #include "vivid-osd.h"
>  #include "vivid-ctrls.h"
> +#include "vivid-cec.h"
>  
>  #define VIVID_CID_CUSTOM_BASE		(V4L2_CID_USER_BASE | 0xf000)
>  #define VIVID_CID_BUTTON		(VIVID_CID_CUSTOM_BASE + 0)
> @@ -923,7 +924,7 @@ static int vivid_vid_out_s_ctrl(struct v4l2_ctrl *ctrl)
>  	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vid_out);
>  	struct v4l2_bt_timings *bt = &dev->dv_timings_out.bt;
>  	u32 display_present = 0;
> -	unsigned i, j;
> +	unsigned i, j, bus_idx;
>  
>  	switch (ctrl->id) {
>  	case VIVID_CID_HAS_CROP_OUT:
> @@ -962,15 +963,31 @@ static int vivid_vid_out_s_ctrl(struct v4l2_ctrl *ctrl)
>  			break;
>  
>  		dev->display_present[dev->output] = ctrl->val;
> -
>  		for (i = 0, j = 0; i < dev->num_outputs; i++)
>  			if (dev->output_type[i] == HDMI)
>  				display_present |=
>  					dev->display_present[i] << j++;
>  
> -		__v4l2_ctrl_s_ctrl(dev->ctrl_tx_hotplug, display_present);
>  		__v4l2_ctrl_s_ctrl(dev->ctrl_tx_rxsense, display_present);
> -		__v4l2_ctrl_s_ctrl(dev->ctrl_tx_edid_present, display_present);
> +
> +		if (dev->edid_blocks) {
> +			__v4l2_ctrl_s_ctrl(dev->ctrl_tx_edid_present,
> +					   display_present);
> +			__v4l2_ctrl_s_ctrl(dev->ctrl_tx_hotplug,
> +					   display_present);
> +		}
> +
> +		if (dev->cec_tx_adap == NULL)
> +			break;
> +
> +		bus_idx = dev->cec_output2bus_map[dev->output];
> +		if (ctrl->val && dev->edid_blocks)
> +			cec_s_phys_addr(dev->cec_tx_adap[bus_idx],
> +					dev->cec_tx_adap[bus_idx]->phys_addr,
> +					false);
> +		else
> +			cec_phys_addr_invalidate(dev->cec_tx_adap[bus_idx]);
> +
>  		break;
>  	}
>  	return 0;
> diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c
> index ca15c13abf6c..920be638da83 100644
> --- a/drivers/media/platform/vivid/vivid-vid-cap.c
> +++ b/drivers/media/platform/vivid/vivid-vid-cap.c
> @@ -1760,6 +1760,7 @@ int vidioc_s_edid(struct file *file, void *_fh,
>  		return -EINVAL;
>  	if (edid->blocks == 0) {
>  		dev->edid_blocks = 0;
> +		v4l2_ctrl_s_ctrl(dev->ctrl_tx_edid_present, false);

false should be 0 (it's a bitmask control).
The tx_hotplug control should be set to 0 as well.

>  		phys_addr = CEC_PHYS_ADDR_INVALID;
>  		goto set_phys_addr;
>  	}
> @@ -1777,6 +1778,7 @@ int vidioc_s_edid(struct file *file, void *_fh,
>  
>  	dev->edid_blocks = edid->blocks;
>  	memcpy(dev->edid, edid->edid, edid->blocks * 128);
> +	v4l2_ctrl_s_ctrl(dev->ctrl_tx_edid_present, true);

true should be a display_present mask. And the tx_hotplug control should
be set as well with the same mask.

It's probably best to just recalculate the display_present mask, just as
you did in vivid_vid_out_s_ctrl().

>  
>  set_phys_addr:
>  	/* TODO: a proper hotplug detect cycle should be emulated here */
> @@ -1784,7 +1786,9 @@ int vidioc_s_edid(struct file *file, void *_fh,
>  
>  	for (i = 0; i < MAX_OUTPUTS && dev->cec_tx_adap[i]; i++)
>  		cec_s_phys_addr(dev->cec_tx_adap[i],
> -				v4l2_phys_addr_for_input(phys_addr, i + 1),
> +				dev->display_present[i] ?
> +				v4l2_phys_addr_for_input(phys_addr, i + 1) :
> +				CEC_PHYS_ADDR_INVALID,
>  				false);
>  	return 0;
>  }
> diff --git a/drivers/media/platform/vivid/vivid-vid-common.c b/drivers/media/platform/vivid/vivid-vid-common.c
> index b6882426fc12..0addf8ef7dbf 100644
> --- a/drivers/media/platform/vivid/vivid-vid-common.c
> +++ b/drivers/media/platform/vivid/vivid-vid-common.c
> @@ -907,6 +907,8 @@ int vidioc_g_edid(struct file *file, void *_fh,
>  			return -EINVAL;
>  		if (dev->output_type[edid->pad] != HDMI)
>  			return -EINVAL;
> +		if (!dev->display_present[dev->output])

dev->output should be edid->pad. VIDIOC_G_EDID gets the EDID of the specified
output, not of the current output.

> +			return -ENODATA;
>  		bus_idx = dev->cec_output2bus_map[edid->pad];
>  		adap = dev->cec_tx_adap[bus_idx];
>  	}
> 

Regards,

	Hans

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

* Re: [PATCH 7/8] media: vivid: add CEC support to display present ctrl
  2019-05-29  7:39   ` Hans Verkuil
@ 2019-06-11 20:25     ` Johan Korsnes
  2019-06-11 20:45       ` Hans Verkuil
  0 siblings, 1 reply; 12+ messages in thread
From: Johan Korsnes @ 2019-06-11 20:25 UTC (permalink / raw)
  To: Hans Verkuil, linux-media

Thank you for the review Hans. My comments are inline. A v2 of this
series is under way.

On 5/29/19 12:39 AM, Hans Verkuil wrote:
> Hi Johan,
> 
> Thanks for this patch series!
> 
> The previous patches all look good, but this one needs a bit more work:
> 
> On 5/28/19 7:19 PM, johan.korsnes@gmail.com wrote:
>> From: Johan Korsnes <johan.korsnes@gmail.com>
>>
>> Set/invalidate physical addresses based on the configuration of the
>> display present control. This is relevant not only when the display
>> present control is modified, but also when the Vivid instance EDID is
>> set/cleared.
>>
>> Signed-off-by: Johan Korsnes <johan.korsnes@gmail.com>
>> ---
>>  drivers/media/platform/vivid/vivid-core.c     | 16 ++++++------
>>  drivers/media/platform/vivid/vivid-ctrls.c    | 25 ++++++++++++++++---
>>  drivers/media/platform/vivid/vivid-vid-cap.c  |  6 ++++-
>>  .../media/platform/vivid/vivid-vid-common.c   |  2 ++
>>  4 files changed, 36 insertions(+), 13 deletions(-)
>>
>> diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c
>> index b2b4ee48cef0..ca46ac24f51e 100644
>> --- a/drivers/media/platform/vivid/vivid-core.c
>> +++ b/drivers/media/platform/vivid/vivid-core.c
>> @@ -1060,14 +1060,6 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
>>  	vivid_update_format_cap(dev, false);
>>  	vivid_update_format_out(dev);
>>  
>> -	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vid_cap);
>> -	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vid_out);
>> -	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vbi_cap);
>> -	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vbi_out);
>> -	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_radio_rx);
>> -	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_radio_tx);
>> -	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_sdr_cap);
>> -
>>  	/* initialize overlay */
>>  	dev->fb_cap.fmt.width = dev->src_rect.width;
>>  	dev->fb_cap.fmt.height = dev->src_rect.height;
>> @@ -1488,6 +1480,14 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
>>  	}
>>  #endif
>>  
>> +	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vid_cap);
>> +	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vid_out);
>> +	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vbi_cap);
>> +	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vbi_out);
>> +	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_radio_rx);
>> +	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_radio_tx);
>> +	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_sdr_cap);
>> +
>>  	/* Now that everything is fine, let's add it to device list */
>>  	vivid_devs[inst] = dev;
>>  
> 
> This change should be in a patch of its own.
> 
> It also needs more work. The reason for this change is that v4l2_ctrl_handler_setup()
> expects that the cec adapters are up and running, so moving these calls until after
> the creation of the adapters fixes that.
> 
> However, that now means that controls change after the creation of the video devices,
> which isn't right.
> 
> If you look at the probe() function you'll see that things are done in two stages:
> first all the vb2 queues are created, and only if that succeeded are the video devices
> created.
> 
> The same should be done for the CEC adapters: they should be allocated (vivid_cec_alloc_adap)
> in the first stage, then call v4l2_ctrl_handler_setup(), and finally create the actual
> device nodes (cec_register_adapter).
> 
> That way the controls are configured correctly before any device nodes are created.

I have split up the allocation and registration in v2. Why is this
order important? Some race condition with user space?

> 
>> diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c
>> index ae3690fd1b52..e4758a2837e6 100644
>> --- a/drivers/media/platform/vivid/vivid-ctrls.c
>> +++ b/drivers/media/platform/vivid/vivid-ctrls.c
>> @@ -18,6 +18,7 @@
>>  #include "vivid-radio-common.h"
>>  #include "vivid-osd.h"
>>  #include "vivid-ctrls.h"
>> +#include "vivid-cec.h"
>>  
>>  #define VIVID_CID_CUSTOM_BASE		(V4L2_CID_USER_BASE | 0xf000)
>>  #define VIVID_CID_BUTTON		(VIVID_CID_CUSTOM_BASE + 0)
>> @@ -923,7 +924,7 @@ static int vivid_vid_out_s_ctrl(struct v4l2_ctrl *ctrl)
>>  	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vid_out);
>>  	struct v4l2_bt_timings *bt = &dev->dv_timings_out.bt;
>>  	u32 display_present = 0;
>> -	unsigned i, j;
>> +	unsigned i, j, bus_idx;
>>  
>>  	switch (ctrl->id) {
>>  	case VIVID_CID_HAS_CROP_OUT:
>> @@ -962,15 +963,31 @@ static int vivid_vid_out_s_ctrl(struct v4l2_ctrl *ctrl)
>>  			break;
>>  
>>  		dev->display_present[dev->output] = ctrl->val;
>> -
>>  		for (i = 0, j = 0; i < dev->num_outputs; i++)
>>  			if (dev->output_type[i] == HDMI)
>>  				display_present |=
>>  					dev->display_present[i] << j++;
>>  
>> -		__v4l2_ctrl_s_ctrl(dev->ctrl_tx_hotplug, display_present);
>>  		__v4l2_ctrl_s_ctrl(dev->ctrl_tx_rxsense, display_present);
>> -		__v4l2_ctrl_s_ctrl(dev->ctrl_tx_edid_present, display_present);
>> +
>> +		if (dev->edid_blocks) {
>> +			__v4l2_ctrl_s_ctrl(dev->ctrl_tx_edid_present,
>> +					   display_present);
>> +			__v4l2_ctrl_s_ctrl(dev->ctrl_tx_hotplug,
>> +					   display_present);
>> +		}
>> +
>> +		if (dev->cec_tx_adap == NULL)
>> +			break;
>> +
>> +		bus_idx = dev->cec_output2bus_map[dev->output];
>> +		if (ctrl->val && dev->edid_blocks)
>> +			cec_s_phys_addr(dev->cec_tx_adap[bus_idx],
>> +					dev->cec_tx_adap[bus_idx]->phys_addr,
>> +					false);
>> +		else
>> +			cec_phys_addr_invalidate(dev->cec_tx_adap[bus_idx]);
>> +
>>  		break;
>>  	}
>>  	return 0;
>> diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c
>> index ca15c13abf6c..920be638da83 100644
>> --- a/drivers/media/platform/vivid/vivid-vid-cap.c
>> +++ b/drivers/media/platform/vivid/vivid-vid-cap.c
>> @@ -1760,6 +1760,7 @@ int vidioc_s_edid(struct file *file, void *_fh,
>>  		return -EINVAL;
>>  	if (edid->blocks == 0) {
>>  		dev->edid_blocks = 0;
>> +		v4l2_ctrl_s_ctrl(dev->ctrl_tx_edid_present, false);
> 
> false should be 0 (it's a bitmask control).
> The tx_hotplug control should be set to 0 as well.
> 
>>  		phys_addr = CEC_PHYS_ADDR_INVALID;
>>  		goto set_phys_addr;
>>  	}
>> @@ -1777,6 +1778,7 @@ int vidioc_s_edid(struct file *file, void *_fh,
>>  
>>  	dev->edid_blocks = edid->blocks;
>>  	memcpy(dev->edid, edid->edid, edid->blocks * 128);
>> +	v4l2_ctrl_s_ctrl(dev->ctrl_tx_edid_present, true);
> 
> true should be a display_present mask. And the tx_hotplug control should
> be set as well with the same mask.
> 
> It's probably best to just recalculate the display_present mask, just as
> you did in vivid_vid_out_s_ctrl().

Not sure what I was thinking here. Will fix!

> 
>>  
>>  set_phys_addr:
>>  	/* TODO: a proper hotplug detect cycle should be emulated here */
>> @@ -1784,7 +1786,9 @@ int vidioc_s_edid(struct file *file, void *_fh,
>>  
>>  	for (i = 0; i < MAX_OUTPUTS && dev->cec_tx_adap[i]; i++)
>>  		cec_s_phys_addr(dev->cec_tx_adap[i],
>> -				v4l2_phys_addr_for_input(phys_addr, i + 1),
>> +				dev->display_present[i] ?
>> +				v4l2_phys_addr_for_input(phys_addr, i + 1) :
>> +				CEC_PHYS_ADDR_INVALID,
>>  				false);
>>  	return 0;
>>  }
>> diff --git a/drivers/media/platform/vivid/vivid-vid-common.c b/drivers/media/platform/vivid/vivid-vid-common.c
>> index b6882426fc12..0addf8ef7dbf 100644
>> --- a/drivers/media/platform/vivid/vivid-vid-common.c
>> +++ b/drivers/media/platform/vivid/vivid-vid-common.c
>> @@ -907,6 +907,8 @@ int vidioc_g_edid(struct file *file, void *_fh,
>>  			return -EINVAL;
>>  		if (dev->output_type[edid->pad] != HDMI)
>>  			return -EINVAL;
>> +		if (!dev->display_present[dev->output])
> 
> dev->output should be edid->pad. VIDIOC_G_EDID gets the EDID of the specified
> output, not of the current output.
> 

Will fix this in v2.

>> +			return -ENODATA;
>>  		bus_idx = dev->cec_output2bus_map[edid->pad];
>>  		adap = dev->cec_tx_adap[bus_idx];
>>  	}
>>
> 
> Regards,
> 
> 	Hans
>

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

* Re: [PATCH 7/8] media: vivid: add CEC support to display present ctrl
  2019-06-11 20:25     ` Johan Korsnes
@ 2019-06-11 20:45       ` Hans Verkuil
  0 siblings, 0 replies; 12+ messages in thread
From: Hans Verkuil @ 2019-06-11 20:45 UTC (permalink / raw)
  To: Johan Korsnes, linux-media

On 6/11/19 10:25 PM, Johan Korsnes wrote:
> Thank you for the review Hans. My comments are inline. A v2 of this
> series is under way.
> 
> On 5/29/19 12:39 AM, Hans Verkuil wrote:
>> Hi Johan,
>>
>> Thanks for this patch series!
>>
>> The previous patches all look good, but this one needs a bit more work:
>>
>> On 5/28/19 7:19 PM, johan.korsnes@gmail.com wrote:
>>> From: Johan Korsnes <johan.korsnes@gmail.com>
>>>
>>> Set/invalidate physical addresses based on the configuration of the
>>> display present control. This is relevant not only when the display
>>> present control is modified, but also when the Vivid instance EDID is
>>> set/cleared.
>>>
>>> Signed-off-by: Johan Korsnes <johan.korsnes@gmail.com>
>>> ---
>>>  drivers/media/platform/vivid/vivid-core.c     | 16 ++++++------
>>>  drivers/media/platform/vivid/vivid-ctrls.c    | 25 ++++++++++++++++---
>>>  drivers/media/platform/vivid/vivid-vid-cap.c  |  6 ++++-
>>>  .../media/platform/vivid/vivid-vid-common.c   |  2 ++
>>>  4 files changed, 36 insertions(+), 13 deletions(-)
>>>
>>> diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c
>>> index b2b4ee48cef0..ca46ac24f51e 100644
>>> --- a/drivers/media/platform/vivid/vivid-core.c
>>> +++ b/drivers/media/platform/vivid/vivid-core.c
>>> @@ -1060,14 +1060,6 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
>>>  	vivid_update_format_cap(dev, false);
>>>  	vivid_update_format_out(dev);
>>>  
>>> -	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vid_cap);
>>> -	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vid_out);
>>> -	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vbi_cap);
>>> -	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vbi_out);
>>> -	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_radio_rx);
>>> -	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_radio_tx);
>>> -	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_sdr_cap);
>>> -
>>>  	/* initialize overlay */
>>>  	dev->fb_cap.fmt.width = dev->src_rect.width;
>>>  	dev->fb_cap.fmt.height = dev->src_rect.height;
>>> @@ -1488,6 +1480,14 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
>>>  	}
>>>  #endif
>>>  
>>> +	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vid_cap);
>>> +	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vid_out);
>>> +	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vbi_cap);
>>> +	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_vbi_out);
>>> +	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_radio_rx);
>>> +	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_radio_tx);
>>> +	v4l2_ctrl_handler_setup(&dev->ctrl_hdl_sdr_cap);
>>> +
>>>  	/* Now that everything is fine, let's add it to device list */
>>>  	vivid_devs[inst] = dev;
>>>  
>>
>> This change should be in a patch of its own.
>>
>> It also needs more work. The reason for this change is that v4l2_ctrl_handler_setup()
>> expects that the cec adapters are up and running, so moving these calls until after
>> the creation of the adapters fixes that.
>>
>> However, that now means that controls change after the creation of the video devices,
>> which isn't right.
>>
>> If you look at the probe() function you'll see that things are done in two stages:
>> first all the vb2 queues are created, and only if that succeeded are the video devices
>> created.
>>
>> The same should be done for the CEC adapters: they should be allocated (vivid_cec_alloc_adap)
>> in the first stage, then call v4l2_ctrl_handler_setup(), and finally create the actual
>> device nodes (cec_register_adapter).
>>
>> That way the controls are configured correctly before any device nodes are created.
> 
> I have split up the allocation and registration in v2. Why is this
> order important? Some race condition with user space?

Yes. Once a device node is created under /dev userspace can start to use it.
And in fact something like systemd can open it immediately after creation.

So the complete state of the device should be ready before you create the
device node. Still changing/adding things *after* device node creation
indeed creates a race condition.

Note that a lot of (mostly older) drivers do this wrong, but vivid, being
somewhat of a reference driver, should do this right.

Regards,

	Hans

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

end of thread, other threads:[~2019-06-11 20:45 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-28 17:19 vivid: Add HDMI (dis)connect emulation johan.korsnes
2019-05-28 17:19 ` [PATCH 1/8] media: vivid: make input dv_timings per-input johan.korsnes
2019-05-28 17:19 ` [PATCH 2/8] media: vivid: make input std_signal per-input johan.korsnes
2019-05-28 17:19 ` [PATCH 3/8] media: vivid: add display present control johan.korsnes
2019-05-28 17:19 ` [PATCH 4/8] media: vivid: add number of HDMI ports to device state johan.korsnes
2019-05-28 17:19 ` [PATCH 5/8] media: vivid: add HDMI (dis)connect TX emulation johan.korsnes
2019-05-28 17:19 ` [PATCH 6/8] media: vivid: add HDMI (dis)connect RX emulation johan.korsnes
2019-05-28 17:19 ` [PATCH 7/8] media: vivid: add CEC support to display present ctrl johan.korsnes
2019-05-29  7:39   ` Hans Verkuil
2019-06-11 20:25     ` Johan Korsnes
2019-06-11 20:45       ` Hans Verkuil
2019-05-28 17:19 ` [PATCH 8/8] media: vivid.rst: describe display present control johan.korsnes

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.