Commit 448e1153 authored by Johan Korsnes's avatar Johan Korsnes Committed by Mauro Carvalho Chehab
Browse files

media: vivid: make input dv_timings per-input



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: default avatarJohan Korsnes <johan.korsnes@gmail.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent b1b9b7be
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -1005,7 +1005,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;
@@ -1035,6 +1036,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.
+6 −5
Original line number Diff line number Diff line
@@ -292,18 +292,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 int			query_dv_timings_last[MAX_INPUTS];
	unsigned int			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;
+8 −5
Original line number Diff line number Diff line
@@ -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:
+1 −1
Original line number Diff line number Diff line
@@ -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;
+42 −21
Original line number Diff line number Diff line
@@ -294,7 +294,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;
	}
@@ -356,7 +357,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;
}
@@ -381,7 +382,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;

@@ -481,8 +482,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;
}

@@ -1305,10 +1306,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;
	}
@@ -1348,7 +1349,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)
@@ -1402,6 +1403,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;
}

@@ -1671,12 +1686,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;
}
@@ -1685,26 +1701,31 @@ int vidioc_query_dv_timings(struct file *file, void *_fh,
				    struct v4l2_dv_timings *timings)
{
	struct vivid_dev *dev = video_drvdata(file);
	unsigned int input = dev->input;
	unsigned int last = dev->query_dv_timings_last[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[last];
		dev->query_dv_timings_last[input] =
			(last + 1) % dev->query_dv_timings_size;
	}
	return 0;
}
Loading