]> rtime.felk.cvut.cz Git - hercules2020/nv-tegra/linux-4.4.git/commitdiff
vivid: Support Variable frame rate
authorBhanu Murthy V <bmurthyv@nvidia.com>
Thu, 2 Feb 2017 21:09:01 +0000 (13:09 -0800)
committermobile promotions <svcmobile_promotions@nvidia.com>
Tue, 14 Feb 2017 20:25:15 +0000 (12:25 -0800)
Adapt framerate based on the frame length control.
This is needed to support VFR feature of the
source.

Bug 1787461
Bug 1829605

Change-Id: Ic5a2863941bb23784df3fc532a7ba5d8bc46d91f
Signed-off-by: Bhanu Murthy V <bmurthyv@nvidia.com>
Reviewed-on: http://git-master/r/1298228
GVS: Gerrit_Virtual_Submit
Reviewed-by: Amit Purwar <apurwar@nvidia.com>
Reviewed-by: Jihoon Bang <jbang@nvidia.com>
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-kthread-out.c
drivers/media/platform/vivid/vivid-vid-cap.c
drivers/media/platform/vivid/vivid-vid-cap.h

index dface005641327fb0f1f862ca6c056649d8d96c1..1f23013f11d262ee7aaf9fa4e844fd2922dab4f6 100644 (file)
@@ -989,6 +989,11 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
        memcpy(dev->edid, vivid_hdmi_edid, sizeof(vivid_hdmi_edid));
        ktime_get_ts(&dev->radio_rds_init_ts);
 
+       /* initialize locks */
+       spin_lock_init(&dev->slock);
+       mutex_init(&dev->mutex);
+       mutex_init(&dev->mutex_framerate);
+
        /* create all controls */
        ret = vivid_create_controls(dev, ccs_cap == -1, ccs_out == -1, no_error_inj,
                        in_type_counter[TV] || in_type_counter[SVID] ||
@@ -1019,10 +1024,6 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
        dev->fb_cap.fmt.bytesperline = dev->src_rect.width * tpg_g_twopixelsize(&dev->tpg, 0) / 2;
        dev->fb_cap.fmt.sizeimage = dev->src_rect.height * dev->fb_cap.fmt.bytesperline;
 
-       /* initialize locks */
-       spin_lock_init(&dev->slock);
-       mutex_init(&dev->mutex);
-
        /* init dma queues */
        INIT_LIST_HEAD(&dev->vid_cap_active);
        INIT_LIST_HEAD(&dev->vid_out_active);
index 8367fccf7eef87e3fbbb2409ad6b608c3c0dc2fe..30557fdb10e8a96660ff789c76a57da43a57431d 100644 (file)
@@ -157,6 +157,7 @@ struct vivid_dev {
        struct v4l2_ctrl_handler        ctrl_hdl_sdr_cap;
        spinlock_t                      slock;
        struct mutex                    mutex;
+       struct mutex                    mutex_framerate;
 
        /* capabilities */
        u32                             vid_cap_caps;
@@ -217,6 +218,7 @@ struct vivid_dev {
        struct v4l2_ctrl                *colorspace;
        struct v4l2_ctrl                *rgb_range_cap;
        struct v4l2_ctrl                *real_rgb_range_cap;
+       struct v4l2_ctrl                *framelength;
        struct {
                /* std_signal_mode/standard cluster */
                struct v4l2_ctrl        *ctrl_std_signal_mode;
index 0cf42e10643c55dd070497370a6785bcc85dbe22..33819a7a9582ce8b4daebc111816f2cdd7318050 100644 (file)
@@ -479,6 +479,9 @@ static int vivid_vid_cap_s_ctrl(struct v4l2_ctrl *ctrl)
                if (dev->edid_blocks > dev->edid_max_blocks)
                        dev->edid_blocks = dev->edid_max_blocks;
                break;
+       case VIVID_CID_FRAME_LENGTH:
+               vivid_update_timeperframe(dev, ctrl->val);
+               break;
        }
        return 0;
 }
@@ -1518,7 +1521,8 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap,
                v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_ycbcr_enc, NULL);
                v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_quantization, NULL);
                v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_alpha_mode, NULL);
-               v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_framelength, NULL);
+               dev->framelength = v4l2_ctrl_new_custom(hdl_vid_cap,
+                       &vivid_ctrl_framelength, NULL);
                v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_coarsetime, NULL);
                v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_coarsetime_short, NULL);
                v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_grouphold, NULL);
index 3a06e0b91f81f3b6d27b4bf93414893937f0c4fc..7e66c9ea47333b39e580fcaae8b82e03603db2cc 100644 (file)
@@ -777,6 +777,7 @@ static int vivid_thread_vid_cap(void *data)
                        break;
 
                mutex_lock(&dev->mutex);
+               mutex_lock(&dev->mutex_framerate);
                cur_jiffies = jiffies;
                if (dev->cap_seq_resync) {
                        dev->jiffies_vid_cap = cur_jiffies;
@@ -824,6 +825,7 @@ static int vivid_thread_vid_cap(void *data)
                /* And the number of jiffies since we started */
                jiffies_since_start = jiffies - dev->jiffies_vid_cap;
 
+               mutex_unlock(&dev->mutex_framerate);
                mutex_unlock(&dev->mutex);
 
                /*
index c2c46dcdbe95acb3b79c02004d7d38594c4d18a3..6c8ffc7c72131c25134b6443a6f6f81776035d15 100644 (file)
@@ -148,6 +148,7 @@ static int vivid_thread_vid_out(void *data)
                        break;
 
                mutex_lock(&dev->mutex);
+               mutex_lock(&dev->mutex_framerate);
                cur_jiffies = jiffies;
                if (dev->out_seq_resync) {
                        dev->jiffies_vid_out = cur_jiffies;
@@ -184,6 +185,7 @@ static int vivid_thread_vid_out(void *data)
                dev->vbi_out_seq_count = dev->out_seq_count - dev->vbi_out_seq_start;
 
                vivid_thread_vid_out_tick(dev);
+               mutex_unlock(&dev->mutex_framerate);
                mutex_unlock(&dev->mutex);
 
                /*
index cf656db1e31bcc9ac9f0f0a99759661791f3aec3..362f7be5e84cb64184d2a8acf2826625d1344a81 100644 (file)
@@ -406,6 +406,29 @@ static enum tpg_pixel_aspect vivid_get_pixel_aspect(const struct vivid_dev *dev)
        return TPG_PIXEL_ASPECT_SQUARE;
 }
 
+void vivid_update_timeperframe(struct vivid_dev *dev, u32 frame_length)
+{
+       struct v4l2_bt_timings *bt = &dev->dv_timings_cap.bt;
+       unsigned size;
+
+       mutex_lock(&dev->mutex_framerate);
+
+       dev->cap_seq_resync = true;
+       size = V4L2_DV_BT_FRAME_WIDTH(bt) * frame_length;
+       dev->timeperframe_vid_cap = (struct v4l2_fract) {
+               size / 100, (u32)bt->pixelclock / 100
+       };
+
+       if (dev->loop_video) {
+               dev->out_seq_resync = true;
+               dev->timeperframe_vid_out = (struct v4l2_fract) {
+                       size / 100, (u32)bt->pixelclock / 100
+               };
+       }
+
+       mutex_unlock(&dev->mutex_framerate);
+}
+
 /*
  * Called whenever the format has to be reset which can occur when
  * changing inputs, standard, timings, etc.
@@ -769,6 +792,9 @@ int vivid_s_fmt_vid_cap(struct file *file, void *priv,
                dev->tv_field_cap = mp->field;
         dev->fmt_cap->data_offset[0] = mp->width * dev->embedded_data_height;
        tpg_update_mv_step(&dev->tpg);
+       // update framelength control to control framerate
+       v4l2_ctrl_s_ctrl(dev->framelength,
+               V4L2_DV_BT_FRAME_HEIGHT(&dev->dv_timings_cap.bt));
        return 0;
 }
 
@@ -1679,6 +1705,9 @@ int vivid_vid_cap_s_dv_timings(struct file *file, void *_fh,
 
        dev->dv_timings_cap = *timings;
        vivid_update_format_cap(dev, false);
+       // update framelength control to control framerate
+       v4l2_ctrl_s_ctrl(dev->framelength,
+               V4L2_DV_BT_FRAME_HEIGHT(&dev->dv_timings_cap.bt));
        return 0;
 }
 
index 94079815dbc274e69f6ca8709a143c6cfd0f1aef..3817f06654d46dbabcc5eaaa41c188797529da80 100644 (file)
@@ -67,5 +67,6 @@ int vidioc_enum_framesizes(struct file *file, void *fh, struct v4l2_frmsizeenum
 int vidioc_enum_frameintervals(struct file *file, void *priv, struct v4l2_frmivalenum *fival);
 int vivid_vid_cap_g_parm(struct file *file, void *priv, struct v4l2_streamparm *parm);
 int vivid_vid_cap_s_parm(struct file *file, void *priv, struct v4l2_streamparm *parm);
+void vivid_update_timeperframe(struct vivid_dev *dev, u32 frame_length);
 
 #endif