diff --git a/bcwc_drv.c b/bcwc_drv.c index f534a9b..9be638d 100644 --- a/bcwc_drv.c +++ b/bcwc_drv.c @@ -424,6 +424,7 @@ static int bcwc_pci_probe(struct pci_dev *pdev, if (ret) goto fail_work; + dev_priv->frametime = 40; /* 25 fps */ ret = bcwc_v4l2_register(dev_priv); if (ret) goto fail_work; diff --git a/bcwc_drv.h b/bcwc_drv.h index 2e4a8eb..5f7b2a7 100644 --- a/bcwc_drv.h +++ b/bcwc_drv.h @@ -131,6 +131,7 @@ struct bcwc_private { struct vb2_alloc_ctx *alloc_ctx; struct h2t_buf_ctx h2t_bufs[BCWC_BUFFERS]; + int frametime; }; #endif diff --git a/bcwc_isp.c b/bcwc_isp.c index 2733f17..1f5ab3e 100644 --- a/bcwc_isp.c +++ b/bcwc_isp.c @@ -1016,10 +1016,10 @@ int bcwc_start_channel(struct bcwc_private *dev_priv, int channel) ret = bcwc_isp_cmd_channel_face_detection_start(dev_priv, 0); if (ret) return ret; - ret = bcwc_isp_cmd_channel_frame_rate_max(dev_priv, 0, 7672); + ret = bcwc_isp_cmd_channel_frame_rate_max(dev_priv, 0, dev_priv->frametime * 256); if (ret) return ret; - ret = bcwc_isp_cmd_channel_frame_rate_min(dev_priv, 0, 3072); + ret = bcwc_isp_cmd_channel_frame_rate_min(dev_priv, 0, dev_priv->frametime * 256); if (ret) return ret; ret = bcwc_isp_cmd_channel_temporal_filter_start(dev_priv, 0); diff --git a/bcwc_v4l2.c b/bcwc_v4l2.c index 5c7d5c9..e140a23 100644 --- a/bcwc_v4l2.c +++ b/bcwc_v4l2.c @@ -374,7 +374,7 @@ static int bcwc_v4l2_ioctl_querycap(struct file *filp, void *priv, strcpy(cap->driver, "bcwc"); strcpy(cap->card, "Apple Facetime HD"); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; + V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | V4L2_CAP_TIMEPERFRAME; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -476,15 +476,42 @@ static int bcwc_v4l2_ioctl_s_fmt_vid_cap(struct file *filp, void *priv, static int bcwc_v4l2_ioctl_g_parm(struct file *filp, void *priv, struct v4l2_streamparm *parm) { - pr_debug("%s\n", __FUNCTION__); - return -ENODEV; + struct bcwc_private *priv_dev = video_drvdata(filp); + struct v4l2_fract timeperframe = { + .numerator = priv_dev->frametime, + .denominator = 1000, + }; + + if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + parm->parm.capture.readbuffers = 2; + parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; + parm->parm.capture.timeperframe = timeperframe; + return 0; } static int bcwc_v4l2_ioctl_s_parm(struct file *filp, void *priv, struct v4l2_streamparm *parm) { - pr_debug("%s\n", __FUNCTION__); - return -ENODEV; + + struct bcwc_private *dev_priv = video_drvdata(filp); + struct v4l2_fract *timeperframe; + + if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + timeperframe = &parm->parm.capture.timeperframe; + + if(timeperframe->denominator == 0) { + timeperframe->numerator = 20; + timeperframe->denominator = 1000; + } + + dev_priv->frametime = clamp_t(unsigned int, timeperframe->numerator * 1000 / + timeperframe->denominator, 20, 500); + + return bcwc_v4l2_ioctl_g_parm(filp, priv, parm); } static int bcwc_v4l2_ioctl_enum_framesizes(struct file *filp, void *priv, @@ -504,6 +531,18 @@ static int bcwc_v4l2_ioctl_enum_frameintervals(struct file *filp, void *priv, struct v4l2_frmivalenum *interval) { pr_debug("%s\n", __FUNCTION__); + + if (interval->pixel_format != V4L2_PIX_FMT_YUYV && + interval->pixel_format != V4L2_PIX_FMT_YVYU && + interval->pixel_format != V4L2_PIX_FMT_NV16) + return -EINVAL; + + interval->type = V4L2_FRMIVAL_TYPE_STEPWISE; + interval->stepwise.min.numerator = 33; + interval->stepwise.min.denominator = 1000; + interval->stepwise.max.numerator = 500; + interval->stepwise.max.denominator = 1000; + return -ENODEV; }