media: vivid: make input std_signal per-input
authorJohan Korsnes <johan.korsnes@gmail.com>
Tue, 18 Jun 2019 07:37:19 +0000 (03:37 -0400)
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>
Fri, 21 Jun 2019 21:28:25 +0000 (17:28 -0400)
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>
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-vbi-cap.c
drivers/media/platform/vivid/vivid-vid-cap.c
drivers/media/platform/vivid/vivid-vid-common.c

index f481f17..85e6aaf 100644 (file)
@@ -999,14 +999,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;
index 713ed7e..f9d26a4 100644 (file)
@@ -287,10 +287,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 int                    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;
@@ -302,7 +302,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;
index a3c9661..e27103f 100644 (file)
@@ -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,14 @@ 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);
index b4eee95..6cf495a 100644 (file)
@@ -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;
index 40ecd79..1a9348e 100644 (file)
@@ -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;
index 2f8db64..6edb032 100644 (file)
@@ -191,7 +191,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;
@@ -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_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;
        }
@@ -354,7 +355,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];
@@ -365,7 +366,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) &&
@@ -399,7 +400,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;
@@ -582,7 +583,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;
@@ -1318,9 +1319,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)) {
@@ -1410,11 +1411,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;
@@ -1509,8 +1519,9 @@ int vivid_video_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
        } else if (qual == TPG_QUAL_GRAY) {
                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 int channel_nr = dev->tv_freq / (6 * 16);
+               unsigned int options =
+                       (dev->std_cap[dev->input] & V4L2_STD_NTSC_M) ? 4 : 3;
 
                switch (channel_nr % options) {
                case 0:
@@ -1520,7 +1531,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;
@@ -1577,23 +1588,25 @@ const char * const vivid_ctrl_standard_strings[] = {
 int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *id)
 {
        struct vivid_dev *dev = video_drvdata(file);
+       unsigned int last = dev->query_std_last[dev->input];
 
        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[last];
+               dev->query_std_last[dev->input] =
+                       (last + 1) % ARRAY_SIZE(vivid_standard);
        }
 
        return 0;
@@ -1605,11 +1618,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;
 }
index 98c0e5b..10a344c 100644 (file)
@@ -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;
@@ -805,7 +805,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;