From ad486d4522ca0c033d373cb8340f5ec899b06453 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Sat, 28 Nov 2015 16:10:34 +0100 Subject: [PATCH 1/7] facetimehd: remove cmd_ready variable instead evaluate the ringbuffer status. This allows to have more than one isp command in flight. --- fthd_drv.c | 1 - fthd_drv.h | 2 +- fthd_isp.c | 5 ++--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/fthd_drv.c b/fthd_drv.c index 09e343f..0acf8cd 100644 --- a/fthd_drv.c +++ b/fthd_drv.c @@ -199,7 +199,6 @@ static void fthd_handle_irq(struct fthd_private *dev_priv, struct fw_channel *ch } else if (chan == dev_priv->channel_buf_t2h) { buf_t2h_handler(dev_priv, chan, entry); } else if (chan == dev_priv->channel_io) { - dev_priv->cmd_ready = 1; wake_up_interruptible(&dev_priv->cmd_wq); } else if (chan == dev_priv->channel_io_t2h) { io_t2h_handler(dev_priv, chan, entry); diff --git a/fthd_drv.h b/fthd_drv.h index c6eae90..5675a76 100644 --- a/fthd_drv.h +++ b/fthd_drv.h @@ -76,7 +76,7 @@ struct fthd_private { /* waitqueue for signaling command completion */ wait_queue_head_t cmd_wq; - int cmd_ready; + /* Mapped PCI resources */ void __iomem *s2_io; u32 s2_io_len; diff --git a/fthd_isp.c b/fthd_isp.c index debced8..cf67698 100644 --- a/fthd_isp.c +++ b/fthd_isp.c @@ -310,7 +310,8 @@ static int fthd_isp_cmd(struct fthd_private *dev_priv, enum fthd_isp_cmds comman goto out; } - if (wait_event_interruptible_timeout(dev_priv->cmd_wq, dev_priv->cmd_ready, HZ) <= 0) { + if (wait_event_interruptible_timeout(dev_priv->cmd_wq, + FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS) & 1, HZ) <= 0) { dev_err(&dev_priv->pdev->dev, "timeout wait for command %d\n", cmd.opcode); fthd_channel_ringbuf_dump(dev_priv, dev_priv->channel_io); if (response_len) @@ -319,8 +320,6 @@ static int fthd_isp_cmd(struct fthd_private *dev_priv, enum fthd_isp_cmds comman goto out; } - dev_priv->cmd_ready = 0; - FTHD_S2_MEMCPY_FROMIO(&cmd, request->offset, sizeof(struct isp_cmd_hdr)); address = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS); request_size = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_REQUEST_SIZE); From b93fbfc22bed262595b4f21697673cd50cbeae95 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Sat, 28 Nov 2015 16:12:19 +0100 Subject: [PATCH 2/7] facetimehd: check index parameter in enum_framesizes()/enum_frameintervals() otherwise we might have callers trying all possible index value which takes a lot of time. --- fthd_v4l2.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fthd_v4l2.c b/fthd_v4l2.c index 6807f55..288b0b4 100644 --- a/fthd_v4l2.c +++ b/fthd_v4l2.c @@ -533,6 +533,9 @@ static int fthd_v4l2_ioctl_s_parm(struct file *filp, void *priv, static int fthd_v4l2_ioctl_enum_framesizes(struct file *filp, void *priv, struct v4l2_frmsizeenum *sizes) { + if (sizes->index) + return -EINVAL; + sizes->type = V4L2_FRMSIZE_TYPE_CONTINUOUS; sizes->stepwise.min_width = 320; sizes->stepwise.max_width = 2560; @@ -548,6 +551,9 @@ static int fthd_v4l2_ioctl_enum_frameintervals(struct file *filp, void *priv, { pr_debug("%s\n", __FUNCTION__); + if (interval->index) + return -EINVAL; + if (interval->pixel_format != V4L2_PIX_FMT_YUYV && interval->pixel_format != V4L2_PIX_FMT_YVYU && interval->pixel_format != V4L2_PIX_FMT_NV16) From affbf73f42890638fc78d48d7c73567b59887224 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Sat, 28 Nov 2015 16:15:39 +0100 Subject: [PATCH 3/7] facetimehd: add functions to set saturation and hue --- fthd_isp.c | 28 ++++++++++++++++++++++++++++ fthd_isp.h | 12 ++++++++++++ 2 files changed, 40 insertions(+) diff --git a/fthd_isp.c b/fthd_isp.c index cf67698..6b0ff32 100644 --- a/fthd_isp.c +++ b/fthd_isp.c @@ -1001,6 +1001,34 @@ int fthd_isp_cmd_channel_contrast_set(struct fthd_private *dev_priv, int channel return fthd_isp_cmd(dev_priv, CISP_CMD_CH_SCALER_CONTRAST_SET, &cmd, sizeof(cmd), &len); } +int fthd_isp_cmd_channel_saturation_set(struct fthd_private *dev_priv, int channel, int saturation) +{ + struct isp_cmd_channel_saturation_set cmd; + int len; + + pr_debug("set saturation %d\n", saturation); + + memset(&cmd, 0, sizeof(cmd)); + cmd.channel = channel; + cmd.contrast = saturation; + len = sizeof(cmd); + return fthd_isp_cmd(dev_priv, CISP_CMD_CH_SCALER_SATURATION_SET, &cmd, sizeof(cmd), &len); +} + +int fthd_isp_cmd_channel_hue_set(struct fthd_private *dev_priv, int channel, int hue) +{ + struct isp_cmd_channel_hue_set cmd; + int len; + + pr_debug("set hue %d\n", hue); + + memset(&cmd, 0, sizeof(cmd)); + cmd.channel = channel; + cmd.contrast = hue; + len = sizeof(cmd); + return fthd_isp_cmd(dev_priv, CISP_CMD_CH_SCALER_HUE_SET, &cmd, sizeof(cmd), &len); +} + int fthd_start_channel(struct fthd_private *dev_priv, int channel) { int ret, x1 = 0, x2 = 0, pixelformat; diff --git a/fthd_isp.h b/fthd_isp.h index 837a06b..5be97bf 100644 --- a/fthd_isp.h +++ b/fthd_isp.h @@ -661,6 +661,16 @@ struct isp_cmd_channel_contrast_set { u32 contrast; }; +struct isp_cmd_channel_saturation_set { + u32 channel; + u32 contrast; +}; + +struct isp_cmd_channel_hue_set { + u32 channel; + u32 contrast; +}; + struct isp_cmd_channel_buffer_return { u32 channel; }; @@ -714,6 +724,8 @@ extern int fthd_isp_cmd_channel_motion_history_stop(struct fthd_private *dev_pri extern int fthd_isp_cmd_channel_ae_metering_mode_set(struct fthd_private *dev_priv, int channel, int mode); extern int fthd_isp_cmd_channel_brightness_set(struct fthd_private *dev_priv, int channel, int brightness); extern int fthd_isp_cmd_channel_contrast_set(struct fthd_private *dev_priv, int channel, int contrast); +extern int fthd_isp_cmd_channel_saturation_set(struct fthd_private *dev_priv, int channel, int saturation); +extern int fthd_isp_cmd_channel_hue_set(struct fthd_private *dev_priv, int channel, int hue); extern int fthd_isp_cmd_channel_buffer_return(struct fthd_private *dev_priv, int channel); extern int fthd_start_channel(struct fthd_private *dev_priv, int channel); extern int fthd_stop_channel(struct fthd_private *dev_priv, int channel); From 9bc376510b1a3ce11d3efed5ab9b7a3cbfd99b87 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Sat, 28 Nov 2015 16:16:27 +0100 Subject: [PATCH 4/7] facetimehd: adjust logging level in fthd_v4l2_ioctl_try_fmt_vid_cap() --- fthd_v4l2.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fthd_v4l2.c b/fthd_v4l2.c index 288b0b4..5ab033c 100644 --- a/fthd_v4l2.c +++ b/fthd_v4l2.c @@ -411,8 +411,7 @@ static int fthd_v4l2_ioctl_try_fmt_vid_cap(struct file *filp, void *_priv, { struct fthd_private *dev_priv = video_drvdata(filp); - - pr_info("%s: %dx%d\n", __FUNCTION__, fmt->fmt.pix.width, fmt->fmt.pix.height); + pr_debug("%s: %dx%d\n", __FUNCTION__, fmt->fmt.pix.width, fmt->fmt.pix.height); dev_priv->fmt.fmt = fmt->fmt.pix; From 2e7af64e815512b3b333691a6fd5df6a049ea839 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Sat, 28 Nov 2015 16:17:11 +0100 Subject: [PATCH 5/7] facetimehd: add controls for brightness, contrast, saturation and hue --- fthd_drv.h | 2 ++ fthd_v4l2.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/fthd_drv.h b/fthd_drv.h index 5675a76..f967cf1 100644 --- a/fthd_drv.h +++ b/fthd_drv.h @@ -26,6 +26,7 @@ #include #include #include +#include #include "fthd_reg.h" #include "fthd_ringbuf.h" #include "fthd_buffer.h" @@ -133,6 +134,7 @@ struct fthd_private { struct vb2_alloc_ctx *alloc_ctx; struct h2t_buf_ctx h2t_bufs[FTHD_BUFFERS]; + struct v4l2_ctrl_handler v4l2_ctrl_handler; int frametime; }; diff --git a/fthd_v4l2.c b/fthd_v4l2.c index 5ab033c..6c8461f 100644 --- a/fthd_v4l2.c +++ b/fthd_v4l2.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "fthd_drv.h" #include "fthd_hw.h" @@ -596,6 +597,46 @@ static struct v4l2_ioctl_ops fthd_ioctl_ops = { .vidioc_enum_frameintervals = fthd_v4l2_ioctl_enum_frameintervals, }; +static int fthd_g_volatile_ctrl(struct v4l2_ctrl *ctrl) +{ + pr_debug("id = %x\n", ctrl->id); + return -EINVAL; +} + +static int fthd_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct fthd_private *dev_priv = container_of(ctrl->handler, struct fthd_private, v4l2_ctrl_handler); + int ret = -EINVAL; + + pr_info("id = %x, val = %d\n", ctrl->id, ctrl->val); + + switch(ctrl->id) { + case V4L2_CID_CONTRAST: + ret = fthd_isp_cmd_channel_contrast_set(dev_priv, 0, ctrl->val); + break; + case V4L2_CID_BRIGHTNESS: + ret = fthd_isp_cmd_channel_brightness_set(dev_priv, 0, ctrl->val); + break; + case V4L2_CID_SATURATION: + ret = fthd_isp_cmd_channel_saturation_set(dev_priv, 0, ctrl->val); + break; + case V4L2_CID_HUE: + ret = fthd_isp_cmd_channel_hue_set(dev_priv, 0, ctrl->val); + break; + + default: + break; + + } + pr_debug("ret = %d\n", ret); + return ret; +} + +static const struct v4l2_ctrl_ops fthd_ctrl_ops = { + .g_volatile_ctrl = fthd_g_volatile_ctrl, + .s_ctrl = fthd_s_ctrl, +}; + int fthd_v4l2_register(struct fthd_private *dev_priv) { struct v4l2_device *v4l2_dev = &dev_priv->v4l2_dev; @@ -631,6 +672,21 @@ int fthd_v4l2_register(struct fthd_private *dev_priv) if (ret) goto fail; + v4l2_ctrl_handler_init(&dev_priv->v4l2_ctrl_handler, 4); + v4l2_ctrl_new_std(&dev_priv->v4l2_ctrl_handler, &fthd_ctrl_ops, + V4L2_CID_BRIGHTNESS, 0, 0xff, 1, 0x80); + v4l2_ctrl_new_std(&dev_priv->v4l2_ctrl_handler, &fthd_ctrl_ops, + V4L2_CID_CONTRAST, 0, 0xff, 1, 0x80); + v4l2_ctrl_new_std(&dev_priv->v4l2_ctrl_handler, &fthd_ctrl_ops, + V4L2_CID_SATURATION, 0, 0xff, 1, 0x80); + v4l2_ctrl_new_std(&dev_priv->v4l2_ctrl_handler, &fthd_ctrl_ops, + V4L2_CID_HUE, 0, 0xff, 1, 0x80); + + if (dev_priv->v4l2_ctrl_handler.error) { + pr_err("failed to setup control handlers\n"); + v4l2_ctrl_handler_free(&dev_priv->v4l2_ctrl_handler); + goto fail; + } dev_priv->alloc_ctx = vb2_dma_sg_init_ctx(&dev_priv->pdev->dev); vdev->v4l2_dev = v4l2_dev; strcpy(vdev->name, "Apple Facetime HD"); // XXX: Length? @@ -639,19 +695,22 @@ int fthd_v4l2_register(struct fthd_private *dev_priv) vdev->ioctl_ops = &fthd_ioctl_ops; vdev->queue = q; vdev->release = video_device_release; - + vdev->ctrl_handler = &dev_priv->v4l2_ctrl_handler; video_set_drvdata(vdev, dev_priv); ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); if (ret) { video_device_release(vdev); - goto fail; + goto fail_vdev; } dev_priv->fmt.fmt.sizeimage = 1280 * 720 * 2; dev_priv->fmt.fmt.pixelformat = V4L2_PIX_FMT_YUYV; dev_priv->fmt.fmt.width = 1280; dev_priv->fmt.fmt.height = 720; + return 0; +fail_vdev: + v4l2_ctrl_handler_free(&dev_priv->v4l2_ctrl_handler); fail: v4l2_device_unregister(&dev_priv->v4l2_dev); return ret; @@ -660,6 +719,7 @@ fail: void fthd_v4l2_unregister(struct fthd_private *dev_priv) { + v4l2_ctrl_handler_free(&dev_priv->v4l2_ctrl_handler); vb2_dma_sg_cleanup_ctx(dev_priv->alloc_ctx); video_unregister_device(dev_priv->videodev); v4l2_device_unregister(&dev_priv->v4l2_dev); From 1af48495ad8920fcb9648b3672c4391038c78e33 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Sat, 28 Nov 2015 17:10:16 +0100 Subject: [PATCH 6/7] facetimehd: report correct amount of buffers --- fthd_v4l2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fthd_v4l2.c b/fthd_v4l2.c index 6c8461f..7ad91fb 100644 --- a/fthd_v4l2.c +++ b/fthd_v4l2.c @@ -501,7 +501,7 @@ static int fthd_v4l2_ioctl_g_parm(struct file *filp, void *priv, if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - parm->parm.capture.readbuffers = 2; + parm->parm.capture.readbuffers = FTHD_BUFFERS; parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; parm->parm.capture.timeperframe = timeperframe; return 0; From 2ff298739a4004cb7e3eae54d0bf8b7bca7af0c6 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Sat, 28 Nov 2015 17:15:42 +0100 Subject: [PATCH 7/7] facetimehd: set bus_info in v4l2 capabilities --- fthd_v4l2.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fthd_v4l2.c b/fthd_v4l2.c index 7ad91fb..4c5077a 100644 --- a/fthd_v4l2.c +++ b/fthd_v4l2.c @@ -388,8 +388,13 @@ static int fthd_v4l2_ioctl_g_std(struct file *filp, void *priv, v4l2_std_id *std static int fthd_v4l2_ioctl_querycap(struct file *filp, void *priv, struct v4l2_capability *cap) { + struct fthd_private *dev_priv = video_drvdata(filp); + strcpy(cap->driver, "bcwc"); strcpy(cap->card, "Apple Facetime HD"); + snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", + pci_name(dev_priv->pdev)); + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | V4L2_CAP_TIMEPERFRAME; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;