media: vivid: make input dv_timings per-input
authorJohan Korsnes <johan.korsnes@gmail.com>
Tue, 18 Jun 2019 07:37:18 +0000 (03:37 -0400)
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>
Fri, 21 Jun 2019 21:26:21 +0000 (17:26 -0400)
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>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
drivers/media/platform/vivid/vivid-core.c
drivers/media/platform/vivid/vivid-core.h
drivers/media/platform/vivid/vivid-ctrls.c
drivers/media/platform/vivid/vivid-kthread-cap.c
drivers/media/platform/vivid/vivid-vid-cap.c
drivers/media/platform/vivid/vivid-vid-common.c

index beb2e566a43ca1930a9992317233776a015c10f4..f481f1768184a2ceb9c18c0ae690f36205efe381 100644 (file)
@@ -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.
index 18a9ba9d76e8683729f84f7ea26af1a287dd333d..713ed7e87f76b62a1cfdd64727f27fd6f0ea8ed3 100644 (file)
@@ -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;
index 4cd526ff248b526b15a2650409141d1291c6e21b..a3c9661caf95d9f79d39f0322bded52b8bd86322 100644 (file)
@@ -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:
index f8006a30c12fb7c2234b00ed70d2b02d1f4008aa..b4eee952e1c99a1a056bee601731f5799331df57 100644 (file)
@@ -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;
index 6e8c6de1465d5a8c977acb585f708318b77ff373..2f8db64e3e65784348e509517b57b2e179e1b3d9 100644 (file)
@@ -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;
 }
index 9307ce1cdd1641b161bcc0f772742fefb25d9ee8..98c0e5b4d391b1da26435703da0709e6b37e33cf 100644 (file)
@@ -823,7 +823,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;