diff options
author | Vandana BN <bnvandana@gmail.com> | 2019-10-15 07:40:17 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab+samsung@kernel.org> | 2019-10-24 11:46:36 -0300 |
commit | 746facd39370cc10038eba695f37269c6a401fda (patch) | |
tree | 91f574097d33347095590cfd3d35d9a0e7c2f6a8 /drivers/media/platform/vivid/vivid-core.c | |
parent | 78892b6ba3ba7a6c20bc21548ee90fc980fdfbf4 (diff) |
media: vivid: Add metadata output support
Support metadata output in vivid driver.
Metadata output is used to set brightness, contrast, saturation
and hue.
Adds new files for metadata output.
Signed-off-by: Vandana BN <bnvandana@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Diffstat (limited to 'drivers/media/platform/vivid/vivid-core.c')
-rw-r--r-- | drivers/media/platform/vivid/vivid-core.c | 98 |
1 files changed, 93 insertions, 5 deletions
diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c index a44984536ad0..dadfc59c92c5 100644 --- a/drivers/media/platform/vivid/vivid-core.c +++ b/drivers/media/platform/vivid/vivid-core.c @@ -38,6 +38,7 @@ #include "vivid-cec.h" #include "vivid-ctrls.h" #include "vivid-meta-cap.h" +#include "vivid-meta-out.h" #define VIVID_MODULE_NAME "vivid" @@ -84,6 +85,10 @@ static int meta_cap_nr[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 }; module_param_array(meta_cap_nr, int, NULL, 0444); MODULE_PARM_DESC(meta_cap_nr, " videoX start number, -1 is autodetect"); +static int meta_out_nr[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 }; +module_param_array(meta_out_nr, int, NULL, 0444); +MODULE_PARM_DESC(meta_out_nr, " videoX start number, -1 is autodetect"); + static int ccs_cap_mode[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = -1 }; module_param_array(ccs_cap_mode, int, NULL, 0444); MODULE_PARM_DESC(ccs_cap_mode, " capture crop/compose/scale mode:\n" @@ -105,10 +110,10 @@ MODULE_PARM_DESC(multiplanar, " 1 (default) creates a single planar device, 2 cr * vbi-out + vid-out + meta-cap */ static unsigned int node_types[VIVID_MAX_DEVS] = { - [0 ... (VIVID_MAX_DEVS - 1)] = 0x21d3d + [0 ... (VIVID_MAX_DEVS - 1)] = 0x61d3d }; module_param_array(node_types, uint, NULL, 0444); -MODULE_PARM_DESC(node_types, " node types, default is 0x21d3d. Bitmask with the following meaning:\n" +MODULE_PARM_DESC(node_types, " node types, default is 0x61d3d. Bitmask with the following meaning:\n" "\t\t bit 0: Video Capture node\n" "\t\t bit 2-3: VBI Capture node: 0 = none, 1 = raw vbi, 2 = sliced vbi, 3 = both\n" "\t\t bit 4: Radio Receiver node\n" @@ -117,7 +122,8 @@ MODULE_PARM_DESC(node_types, " node types, default is 0x21d3d. Bitmask with the "\t\t bit 10-11: VBI Output node: 0 = none, 1 = raw vbi, 2 = sliced vbi, 3 = both\n" "\t\t bit 12: Radio Transmitter node\n" "\t\t bit 16: Framebuffer for testing overlays\n" - "\t\t bit 17: Metadata Capture node\n"); + "\t\t bit 17: Metadata Capture node\n" + "\t\t bit 18: Metadata Output node\n"); /* Default: 4 inputs */ static unsigned num_inputs[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = 4 }; @@ -216,7 +222,8 @@ static int vidioc_querycap(struct file *file, void *priv, cap->capabilities = dev->vid_cap_caps | dev->vid_out_caps | dev->vbi_cap_caps | dev->vbi_out_caps | dev->radio_rx_caps | dev->radio_tx_caps | - dev->sdr_cap_caps | dev->meta_cap_caps | V4L2_CAP_DEVICE_CAPS; + dev->sdr_cap_caps | dev->meta_cap_caps | + dev->meta_out_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -445,7 +452,8 @@ static bool vivid_is_last_user(struct vivid_dev *dev) vivid_is_in_use(&dev->sdr_cap_dev) + vivid_is_in_use(&dev->radio_rx_dev) + vivid_is_in_use(&dev->radio_tx_dev) + - vivid_is_in_use(&dev->meta_cap_dev); + vivid_is_in_use(&dev->meta_cap_dev) + + vivid_is_in_use(&dev->meta_out_dev); return uses == 1; } @@ -472,6 +480,7 @@ static int vivid_fop_release(struct file *file) set_bit(V4L2_FL_REGISTERED, &dev->radio_rx_dev.flags); set_bit(V4L2_FL_REGISTERED, &dev->radio_tx_dev.flags); set_bit(V4L2_FL_REGISTERED, &dev->meta_cap_dev.flags); + set_bit(V4L2_FL_REGISTERED, &dev->meta_out_dev.flags); } mutex_unlock(&dev->mutex); if (file->private_data == dev->overlay_cap_owner) @@ -622,6 +631,11 @@ static const struct v4l2_ioctl_ops vivid_ioctl_ops = { .vidioc_g_fmt_meta_cap = vidioc_g_fmt_meta_cap, .vidioc_s_fmt_meta_cap = vidioc_g_fmt_meta_cap, .vidioc_try_fmt_meta_cap = vidioc_g_fmt_meta_cap, + + .vidioc_enum_fmt_meta_out = vidioc_enum_fmt_meta_out, + .vidioc_g_fmt_meta_out = vidioc_g_fmt_meta_out, + .vidioc_s_fmt_meta_out = vidioc_g_fmt_meta_out, + .vidioc_try_fmt_meta_out = vidioc_g_fmt_meta_out, }; /* ----------------------------------------------------------------- @@ -839,6 +853,9 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) /* do we create a meta capture device */ dev->has_meta_cap = node_type & 0x20000; + /* do we create a metadata output device */ + dev->has_meta_out = node_type & 0x40000; + /* end detecting feature set */ if (dev->has_vid_cap) { @@ -905,6 +922,13 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) if (in_type_counter[TV]) dev->meta_cap_caps |= V4L2_CAP_TUNER; } + /* set up the capabilities of meta output device */ + if (dev->has_meta_out) { + dev->meta_out_caps = V4L2_CAP_META_OUTPUT | + V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; + if (dev->has_audio_outputs) + dev->meta_out_caps |= V4L2_CAP_AUDIO; + } ret = -ENOMEM; /* initialize the test pattern generator */ @@ -976,6 +1000,9 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) v4l2_disable_ioctl(&dev->vbi_out_dev, VIDIOC_S_AUDOUT); v4l2_disable_ioctl(&dev->vbi_out_dev, VIDIOC_G_AUDOUT); v4l2_disable_ioctl(&dev->vbi_out_dev, VIDIOC_ENUMAUDOUT); + v4l2_disable_ioctl(&dev->meta_out_dev, VIDIOC_S_AUDOUT); + v4l2_disable_ioctl(&dev->meta_out_dev, VIDIOC_G_AUDOUT); + v4l2_disable_ioctl(&dev->meta_out_dev, VIDIOC_ENUMAUDOUT); } if (!in_type_counter[TV] && !in_type_counter[SVID]) { v4l2_disable_ioctl(&dev->vid_cap_dev, VIDIOC_S_STD); @@ -1035,6 +1062,8 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) v4l2_disable_ioctl(&dev->vid_out_dev, VIDIOC_ENUM_FRAMEINTERVALS); v4l2_disable_ioctl(&dev->vbi_out_dev, VIDIOC_S_FREQUENCY); v4l2_disable_ioctl(&dev->vbi_out_dev, VIDIOC_G_FREQUENCY); + v4l2_disable_ioctl(&dev->meta_out_dev, VIDIOC_S_FREQUENCY); + v4l2_disable_ioctl(&dev->meta_out_dev, VIDIOC_G_FREQUENCY); /* configure internal data */ dev->fmt_cap = &vivid_formats[0]; @@ -1118,6 +1147,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) INIT_LIST_HEAD(&dev->vbi_out_active); INIT_LIST_HEAD(&dev->sdr_cap_active); INIT_LIST_HEAD(&dev->meta_cap_active); + INIT_LIST_HEAD(&dev->meta_out_active); INIT_LIST_HEAD(&dev->cec_work_list); spin_lock_init(&dev->cec_slock); @@ -1286,6 +1316,27 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) goto unreg_dev; } + if (dev->has_meta_out) { + /* initialize meta_out queue */ + q = &dev->vb_meta_out_q; + q->type = V4L2_BUF_TYPE_META_OUTPUT; + q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_WRITE; + if (!allocator) + q->io_modes |= VB2_USERPTR; + q->drv_priv = dev; + q->buf_struct_size = sizeof(struct vivid_buffer); + q->ops = &vivid_meta_out_qops; + q->mem_ops = vivid_mem_ops[allocator]; + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->min_buffers_needed = 1; + q->lock = &dev->mutex; + q->dev = dev->v4l2_dev.dev; + q->supports_requests = true; + ret = vb2_queue_init(q); + if (ret) + goto unreg_dev; + } + #ifdef CONFIG_VIDEO_VIVID_CEC if (dev->has_vid_cap && in_type_counter[HDMI]) { struct cec_adapter *adap; @@ -1327,6 +1378,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) v4l2_ctrl_handler_setup(&dev->ctrl_hdl_radio_tx); v4l2_ctrl_handler_setup(&dev->ctrl_hdl_sdr_cap); v4l2_ctrl_handler_setup(&dev->ctrl_hdl_meta_cap); + v4l2_ctrl_handler_setup(&dev->ctrl_hdl_meta_out); /* finally start creating the device nodes */ if (dev->has_vid_cap) { @@ -1583,6 +1635,36 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) video_device_node_name(vfd)); } + if (dev->has_meta_out) { + vfd = &dev->meta_out_dev; + snprintf(vfd->name, sizeof(vfd->name), + "vivid-%03d-meta-out", inst); + vfd->vfl_dir = VFL_DIR_TX; + vfd->fops = &vivid_fops; + vfd->ioctl_ops = &vivid_ioctl_ops; + vfd->device_caps = dev->meta_out_caps; + vfd->release = video_device_release_empty; + vfd->v4l2_dev = &dev->v4l2_dev; + vfd->queue = &dev->vb_meta_out_q; + vfd->lock = &dev->mutex; + vfd->tvnorms = tvnorms_out; + video_set_drvdata(vfd, dev); +#ifdef CONFIG_MEDIA_CONTROLLER + dev->meta_out_pad.flags = MEDIA_PAD_FL_SOURCE; + ret = media_entity_pads_init(&vfd->entity, 1, + &dev->meta_out_pad); + if (ret) + goto unreg_dev; +#endif + ret = video_register_device(vfd, VFL_TYPE_GRABBER, + meta_out_nr[inst]); + if (ret < 0) + goto unreg_dev; + v4l2_info(&dev->v4l2_dev, + "V4L2 metadata output device registered as %s\n", + video_device_node_name(vfd)); + } + #ifdef CONFIG_MEDIA_CONTROLLER /* Register the media device */ ret = media_device_register(&dev->mdev); @@ -1599,6 +1681,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) return 0; unreg_dev: + video_unregister_device(&dev->meta_out_dev); video_unregister_device(&dev->meta_cap_dev); video_unregister_device(&dev->radio_tx_dev); video_unregister_device(&dev->radio_rx_dev); @@ -1721,6 +1804,11 @@ static int vivid_remove(struct platform_device *pdev) video_device_node_name(&dev->meta_cap_dev)); video_unregister_device(&dev->meta_cap_dev); } + if (dev->has_meta_out) { + v4l2_info(&dev->v4l2_dev, "unregistering %s\n", + video_device_node_name(&dev->meta_out_dev)); + video_unregister_device(&dev->meta_out_dev); + } cec_unregister_adapter(dev->cec_rx_adap); for (j = 0; j < MAX_OUTPUTS; j++) cec_unregister_adapter(dev->cec_tx_adap[j]); |