root/drivers/media/platform/exynos4-is/fimc-isp-video.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. isp_video_capture_queue_setup
  2. __get_isp_dma2
  3. isp_video_capture_start_streaming
  4. isp_video_capture_stop_streaming
  5. isp_video_capture_buffer_prepare
  6. isp_video_capture_buffer_queue
  7. fimc_isp_video_irq_handler
  8. isp_video_open
  9. isp_video_release
  10. isp_video_querycap
  11. isp_video_enum_fmt
  12. isp_video_g_fmt_mplane
  13. __isp_video_try_fmt
  14. isp_video_try_fmt_mplane
  15. isp_video_s_fmt_mplane
  16. isp_video_pipeline_validate
  17. isp_video_streamon
  18. isp_video_streamoff
  19. isp_video_reqbufs
  20. fimc_isp_video_device_register
  21. fimc_isp_video_device_unregister

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
   4  *
   5  * FIMC-IS ISP video input and video output DMA interface driver
   6  *
   7  * Copyright (C) 2013 Samsung Electronics Co., Ltd.
   8  * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
   9  *
  10  * The hardware handling code derived from a driver written by
  11  * Younghwan Joo <yhwan.joo@samsung.com>.
  12  */
  13 
  14 #include <linux/bitops.h>
  15 #include <linux/device.h>
  16 #include <linux/delay.h>
  17 #include <linux/errno.h>
  18 #include <linux/kernel.h>
  19 #include <linux/module.h>
  20 #include <linux/types.h>
  21 #include <linux/printk.h>
  22 #include <linux/pm_runtime.h>
  23 #include <linux/slab.h>
  24 #include <linux/videodev2.h>
  25 
  26 #include <media/v4l2-device.h>
  27 #include <media/v4l2-ioctl.h>
  28 #include <media/videobuf2-v4l2.h>
  29 #include <media/videobuf2-dma-contig.h>
  30 #include <media/drv-intf/exynos-fimc.h>
  31 
  32 #include "common.h"
  33 #include "media-dev.h"
  34 #include "fimc-is.h"
  35 #include "fimc-isp-video.h"
  36 #include "fimc-is-param.h"
  37 
  38 static int isp_video_capture_queue_setup(struct vb2_queue *vq,
  39                         unsigned int *num_buffers, unsigned int *num_planes,
  40                         unsigned int sizes[], struct device *alloc_devs[])
  41 {
  42         struct fimc_isp *isp = vb2_get_drv_priv(vq);
  43         struct v4l2_pix_format_mplane *vid_fmt = &isp->video_capture.pixfmt;
  44         const struct fimc_fmt *fmt = isp->video_capture.format;
  45         unsigned int wh, i;
  46 
  47         wh = vid_fmt->width * vid_fmt->height;
  48 
  49         if (fmt == NULL)
  50                 return -EINVAL;
  51 
  52         *num_buffers = clamp_t(u32, *num_buffers, FIMC_ISP_REQ_BUFS_MIN,
  53                                                 FIMC_ISP_REQ_BUFS_MAX);
  54         if (*num_planes) {
  55                 if (*num_planes != fmt->memplanes)
  56                         return -EINVAL;
  57                 for (i = 0; i < *num_planes; i++)
  58                         if (sizes[i] < (wh * fmt->depth[i]) / 8)
  59                                 return -EINVAL;
  60                 return 0;
  61         }
  62 
  63         *num_planes = fmt->memplanes;
  64 
  65         for (i = 0; i < fmt->memplanes; i++)
  66                 sizes[i] = (wh * fmt->depth[i]) / 8;
  67 
  68         return 0;
  69 }
  70 
  71 static inline struct param_dma_output *__get_isp_dma2(struct fimc_is *is)
  72 {
  73         return &__get_curr_is_config(is)->isp.dma2_output;
  74 }
  75 
  76 static int isp_video_capture_start_streaming(struct vb2_queue *q,
  77                                                 unsigned int count)
  78 {
  79         struct fimc_isp *isp = vb2_get_drv_priv(q);
  80         struct fimc_is *is = fimc_isp_to_is(isp);
  81         struct param_dma_output *dma = __get_isp_dma2(is);
  82         struct fimc_is_video *video = &isp->video_capture;
  83         int ret;
  84 
  85         if (!test_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state) ||
  86             test_bit(ST_ISP_VID_CAP_STREAMING, &isp->state))
  87                 return 0;
  88 
  89 
  90         dma->cmd = DMA_OUTPUT_COMMAND_ENABLE;
  91         dma->notify_dma_done = DMA_OUTPUT_NOTIFY_DMA_DONE_ENABLE;
  92         dma->buffer_address = is->is_dma_p_region +
  93                                 DMA2_OUTPUT_ADDR_ARRAY_OFFS;
  94         dma->buffer_number = video->reqbufs_count;
  95         dma->dma_out_mask = video->buf_mask;
  96 
  97         isp_dbg(2, &video->ve.vdev,
  98                 "buf_count: %d, planes: %d, dma addr table: %#x\n",
  99                 video->buf_count, video->format->memplanes,
 100                 dma->buffer_address);
 101 
 102         fimc_is_mem_barrier();
 103 
 104         fimc_is_set_param_bit(is, PARAM_ISP_DMA2_OUTPUT);
 105         __fimc_is_hw_update_param(is, PARAM_ISP_DMA2_OUTPUT);
 106 
 107         ret = fimc_is_itf_s_param(is, false);
 108         if (ret < 0)
 109                 return ret;
 110 
 111         ret = fimc_pipeline_call(&video->ve, set_stream, 1);
 112         if (ret < 0)
 113                 return ret;
 114 
 115         set_bit(ST_ISP_VID_CAP_STREAMING, &isp->state);
 116         return ret;
 117 }
 118 
 119 static void isp_video_capture_stop_streaming(struct vb2_queue *q)
 120 {
 121         struct fimc_isp *isp = vb2_get_drv_priv(q);
 122         struct fimc_is *is = fimc_isp_to_is(isp);
 123         struct param_dma_output *dma = __get_isp_dma2(is);
 124         int ret;
 125 
 126         ret = fimc_pipeline_call(&isp->video_capture.ve, set_stream, 0);
 127         if (ret < 0)
 128                 return;
 129 
 130         dma->cmd = DMA_OUTPUT_COMMAND_DISABLE;
 131         dma->notify_dma_done = DMA_OUTPUT_NOTIFY_DMA_DONE_DISABLE;
 132         dma->buffer_number = 0;
 133         dma->buffer_address = 0;
 134         dma->dma_out_mask = 0;
 135 
 136         fimc_is_set_param_bit(is, PARAM_ISP_DMA2_OUTPUT);
 137         __fimc_is_hw_update_param(is, PARAM_ISP_DMA2_OUTPUT);
 138 
 139         ret = fimc_is_itf_s_param(is, false);
 140         if (ret < 0)
 141                 dev_warn(&is->pdev->dev, "%s: DMA stop failed\n", __func__);
 142 
 143         fimc_is_hw_set_isp_buf_mask(is, 0);
 144 
 145         clear_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state);
 146         clear_bit(ST_ISP_VID_CAP_STREAMING, &isp->state);
 147 
 148         isp->video_capture.buf_count = 0;
 149 }
 150 
 151 static int isp_video_capture_buffer_prepare(struct vb2_buffer *vb)
 152 {
 153         struct fimc_isp *isp = vb2_get_drv_priv(vb->vb2_queue);
 154         struct fimc_is_video *video = &isp->video_capture;
 155         int i;
 156 
 157         if (video->format == NULL)
 158                 return -EINVAL;
 159 
 160         for (i = 0; i < video->format->memplanes; i++) {
 161                 unsigned long size = video->pixfmt.plane_fmt[i].sizeimage;
 162 
 163                 if (vb2_plane_size(vb, i) < size) {
 164                         v4l2_err(&video->ve.vdev,
 165                                  "User buffer too small (%ld < %ld)\n",
 166                                  vb2_plane_size(vb, i), size);
 167                         return -EINVAL;
 168                 }
 169                 vb2_set_plane_payload(vb, i, size);
 170         }
 171 
 172         /* Check if we get one of the already known buffers. */
 173         if (test_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state)) {
 174                 dma_addr_t dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
 175                 int i;
 176 
 177                 for (i = 0; i < video->buf_count; i++)
 178                         if (video->buffers[i]->dma_addr[0] == dma_addr)
 179                                 return 0;
 180                 return -ENXIO;
 181         }
 182 
 183         return 0;
 184 }
 185 
 186 static void isp_video_capture_buffer_queue(struct vb2_buffer *vb)
 187 {
 188         struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 189         struct fimc_isp *isp = vb2_get_drv_priv(vb->vb2_queue);
 190         struct fimc_is_video *video = &isp->video_capture;
 191         struct fimc_is *is = fimc_isp_to_is(isp);
 192         struct isp_video_buf *ivb = to_isp_video_buf(vbuf);
 193         unsigned long flags;
 194         unsigned int i;
 195 
 196         if (test_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state)) {
 197                 spin_lock_irqsave(&is->slock, flags);
 198                 video->buf_mask |= BIT(ivb->index);
 199                 spin_unlock_irqrestore(&is->slock, flags);
 200         } else {
 201                 unsigned int num_planes = video->format->memplanes;
 202 
 203                 ivb->index = video->buf_count;
 204                 video->buffers[ivb->index] = ivb;
 205 
 206                 for (i = 0; i < num_planes; i++) {
 207                         int buf_index = ivb->index * num_planes + i;
 208 
 209                         ivb->dma_addr[i] = vb2_dma_contig_plane_dma_addr(vb, i);
 210                         is->is_p_region->shared[32 + buf_index] =
 211                                                         ivb->dma_addr[i];
 212 
 213                         isp_dbg(2, &video->ve.vdev,
 214                                 "dma_buf %d (%d/%d/%d) addr: %pad\n",
 215                                 buf_index, ivb->index, i, vb->index,
 216                                 &ivb->dma_addr[i]);
 217                 }
 218 
 219                 if (++video->buf_count < video->reqbufs_count)
 220                         return;
 221 
 222                 video->buf_mask = (1UL << video->buf_count) - 1;
 223                 set_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state);
 224         }
 225 
 226         if (!test_bit(ST_ISP_VID_CAP_STREAMING, &isp->state))
 227                 isp_video_capture_start_streaming(vb->vb2_queue, 0);
 228 }
 229 
 230 /*
 231  * FIMC-IS ISP input and output DMA interface interrupt handler.
 232  * Locking: called with is->slock spinlock held.
 233  */
 234 void fimc_isp_video_irq_handler(struct fimc_is *is)
 235 {
 236         struct fimc_is_video *video = &is->isp.video_capture;
 237         struct vb2_v4l2_buffer *vbuf;
 238         int buf_index;
 239 
 240         /* TODO: Ensure the DMA is really stopped in stop_streaming callback */
 241         if (!test_bit(ST_ISP_VID_CAP_STREAMING, &is->isp.state))
 242                 return;
 243 
 244         buf_index = (is->i2h_cmd.args[1] - 1) % video->buf_count;
 245         vbuf = &video->buffers[buf_index]->vb;
 246 
 247         vbuf->vb2_buf.timestamp = ktime_get_ns();
 248         vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_DONE);
 249 
 250         video->buf_mask &= ~BIT(buf_index);
 251         fimc_is_hw_set_isp_buf_mask(is, video->buf_mask);
 252 }
 253 
 254 static const struct vb2_ops isp_video_capture_qops = {
 255         .queue_setup     = isp_video_capture_queue_setup,
 256         .buf_prepare     = isp_video_capture_buffer_prepare,
 257         .buf_queue       = isp_video_capture_buffer_queue,
 258         .wait_prepare    = vb2_ops_wait_prepare,
 259         .wait_finish     = vb2_ops_wait_finish,
 260         .start_streaming = isp_video_capture_start_streaming,
 261         .stop_streaming  = isp_video_capture_stop_streaming,
 262 };
 263 
 264 static int isp_video_open(struct file *file)
 265 {
 266         struct fimc_isp *isp = video_drvdata(file);
 267         struct exynos_video_entity *ve = &isp->video_capture.ve;
 268         struct media_entity *me = &ve->vdev.entity;
 269         int ret;
 270 
 271         if (mutex_lock_interruptible(&isp->video_lock))
 272                 return -ERESTARTSYS;
 273 
 274         ret = v4l2_fh_open(file);
 275         if (ret < 0)
 276                 goto unlock;
 277 
 278         ret = pm_runtime_get_sync(&isp->pdev->dev);
 279         if (ret < 0)
 280                 goto rel_fh;
 281 
 282         if (v4l2_fh_is_singular_file(file)) {
 283                 mutex_lock(&me->graph_obj.mdev->graph_mutex);
 284 
 285                 ret = fimc_pipeline_call(ve, open, me, true);
 286 
 287                 /* Mark the video pipeline as in use. */
 288                 if (ret == 0)
 289                         me->use_count++;
 290 
 291                 mutex_unlock(&me->graph_obj.mdev->graph_mutex);
 292         }
 293         if (!ret)
 294                 goto unlock;
 295 rel_fh:
 296         v4l2_fh_release(file);
 297 unlock:
 298         mutex_unlock(&isp->video_lock);
 299         return ret;
 300 }
 301 
 302 static int isp_video_release(struct file *file)
 303 {
 304         struct fimc_isp *isp = video_drvdata(file);
 305         struct fimc_is_video *ivc = &isp->video_capture;
 306         struct media_entity *entity = &ivc->ve.vdev.entity;
 307         struct media_device *mdev = entity->graph_obj.mdev;
 308 
 309         mutex_lock(&isp->video_lock);
 310 
 311         if (v4l2_fh_is_singular_file(file) && ivc->streaming) {
 312                 media_pipeline_stop(entity);
 313                 ivc->streaming = 0;
 314         }
 315 
 316         _vb2_fop_release(file, NULL);
 317 
 318         if (v4l2_fh_is_singular_file(file)) {
 319                 fimc_pipeline_call(&ivc->ve, close);
 320 
 321                 mutex_lock(&mdev->graph_mutex);
 322                 entity->use_count--;
 323                 mutex_unlock(&mdev->graph_mutex);
 324         }
 325 
 326         pm_runtime_put(&isp->pdev->dev);
 327         mutex_unlock(&isp->video_lock);
 328 
 329         return 0;
 330 }
 331 
 332 static const struct v4l2_file_operations isp_video_fops = {
 333         .owner          = THIS_MODULE,
 334         .open           = isp_video_open,
 335         .release        = isp_video_release,
 336         .poll           = vb2_fop_poll,
 337         .unlocked_ioctl = video_ioctl2,
 338         .mmap           = vb2_fop_mmap,
 339 };
 340 
 341 /*
 342  * Video node ioctl operations
 343  */
 344 static int isp_video_querycap(struct file *file, void *priv,
 345                                         struct v4l2_capability *cap)
 346 {
 347         struct fimc_isp *isp = video_drvdata(file);
 348 
 349         __fimc_vidioc_querycap(&isp->pdev->dev, cap);
 350         return 0;
 351 }
 352 
 353 static int isp_video_enum_fmt(struct file *file, void *priv,
 354                               struct v4l2_fmtdesc *f)
 355 {
 356         const struct fimc_fmt *fmt;
 357 
 358         if (f->index >= FIMC_ISP_NUM_FORMATS)
 359                 return -EINVAL;
 360 
 361         fmt = fimc_isp_find_format(NULL, NULL, f->index);
 362         if (WARN_ON(fmt == NULL))
 363                 return -EINVAL;
 364 
 365         f->pixelformat = fmt->fourcc;
 366 
 367         return 0;
 368 }
 369 
 370 static int isp_video_g_fmt_mplane(struct file *file, void *fh,
 371                                         struct v4l2_format *f)
 372 {
 373         struct fimc_isp *isp = video_drvdata(file);
 374 
 375         f->fmt.pix_mp = isp->video_capture.pixfmt;
 376         return 0;
 377 }
 378 
 379 static void __isp_video_try_fmt(struct fimc_isp *isp,
 380                                 struct v4l2_pix_format_mplane *pixm,
 381                                 const struct fimc_fmt **fmt)
 382 {
 383         const struct fimc_fmt *__fmt;
 384 
 385         __fmt = fimc_isp_find_format(&pixm->pixelformat, NULL, 2);
 386 
 387         if (fmt)
 388                 *fmt = __fmt;
 389 
 390         pixm->colorspace = V4L2_COLORSPACE_SRGB;
 391         pixm->field = V4L2_FIELD_NONE;
 392         pixm->num_planes = __fmt->memplanes;
 393         pixm->pixelformat = __fmt->fourcc;
 394         /*
 395          * TODO: double check with the docmentation these width/height
 396          * constraints are correct.
 397          */
 398         v4l_bound_align_image(&pixm->width, FIMC_ISP_SOURCE_WIDTH_MIN,
 399                               FIMC_ISP_SOURCE_WIDTH_MAX, 3,
 400                               &pixm->height, FIMC_ISP_SOURCE_HEIGHT_MIN,
 401                               FIMC_ISP_SOURCE_HEIGHT_MAX, 0, 0);
 402 }
 403 
 404 static int isp_video_try_fmt_mplane(struct file *file, void *fh,
 405                                         struct v4l2_format *f)
 406 {
 407         struct fimc_isp *isp = video_drvdata(file);
 408 
 409         __isp_video_try_fmt(isp, &f->fmt.pix_mp, NULL);
 410         return 0;
 411 }
 412 
 413 static int isp_video_s_fmt_mplane(struct file *file, void *priv,
 414                                         struct v4l2_format *f)
 415 {
 416         struct fimc_isp *isp = video_drvdata(file);
 417         struct fimc_is *is = fimc_isp_to_is(isp);
 418         struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp;
 419         const struct fimc_fmt *ifmt = NULL;
 420         struct param_dma_output *dma = __get_isp_dma2(is);
 421 
 422         __isp_video_try_fmt(isp, pixm, &ifmt);
 423 
 424         if (WARN_ON(ifmt == NULL))
 425                 return -EINVAL;
 426 
 427         dma->format = DMA_OUTPUT_FORMAT_BAYER;
 428         dma->order = DMA_OUTPUT_ORDER_GB_BG;
 429         dma->plane = ifmt->memplanes;
 430         dma->bitwidth = ifmt->depth[0];
 431         dma->width = pixm->width;
 432         dma->height = pixm->height;
 433 
 434         fimc_is_mem_barrier();
 435 
 436         isp->video_capture.format = ifmt;
 437         isp->video_capture.pixfmt = *pixm;
 438 
 439         return 0;
 440 }
 441 
 442 /*
 443  * Check for source/sink format differences at each link.
 444  * Return 0 if the formats match or -EPIPE otherwise.
 445  */
 446 static int isp_video_pipeline_validate(struct fimc_isp *isp)
 447 {
 448         struct v4l2_subdev *sd = &isp->subdev;
 449         struct v4l2_subdev_format sink_fmt, src_fmt;
 450         struct media_pad *pad;
 451         int ret;
 452 
 453         while (1) {
 454                 /* Retrieve format at the sink pad */
 455                 pad = &sd->entity.pads[0];
 456                 if (!(pad->flags & MEDIA_PAD_FL_SINK))
 457                         break;
 458                 sink_fmt.pad = pad->index;
 459                 sink_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
 460                 ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &sink_fmt);
 461                 if (ret < 0 && ret != -ENOIOCTLCMD)
 462                         return -EPIPE;
 463 
 464                 /* Retrieve format at the source pad */
 465                 pad = media_entity_remote_pad(pad);
 466                 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
 467                         break;
 468 
 469                 sd = media_entity_to_v4l2_subdev(pad->entity);
 470                 src_fmt.pad = pad->index;
 471                 src_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
 472                 ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &src_fmt);
 473                 if (ret < 0 && ret != -ENOIOCTLCMD)
 474                         return -EPIPE;
 475 
 476                 if (src_fmt.format.width != sink_fmt.format.width ||
 477                     src_fmt.format.height != sink_fmt.format.height ||
 478                     src_fmt.format.code != sink_fmt.format.code)
 479                         return -EPIPE;
 480         }
 481 
 482         return 0;
 483 }
 484 
 485 static int isp_video_streamon(struct file *file, void *priv,
 486                                       enum v4l2_buf_type type)
 487 {
 488         struct fimc_isp *isp = video_drvdata(file);
 489         struct exynos_video_entity *ve = &isp->video_capture.ve;
 490         struct media_entity *me = &ve->vdev.entity;
 491         int ret;
 492 
 493         ret = media_pipeline_start(me, &ve->pipe->mp);
 494         if (ret < 0)
 495                 return ret;
 496 
 497         ret = isp_video_pipeline_validate(isp);
 498         if (ret < 0)
 499                 goto p_stop;
 500 
 501         ret = vb2_ioctl_streamon(file, priv, type);
 502         if (ret < 0)
 503                 goto p_stop;
 504 
 505         isp->video_capture.streaming = 1;
 506         return 0;
 507 p_stop:
 508         media_pipeline_stop(me);
 509         return ret;
 510 }
 511 
 512 static int isp_video_streamoff(struct file *file, void *priv,
 513                                         enum v4l2_buf_type type)
 514 {
 515         struct fimc_isp *isp = video_drvdata(file);
 516         struct fimc_is_video *video = &isp->video_capture;
 517         int ret;
 518 
 519         ret = vb2_ioctl_streamoff(file, priv, type);
 520         if (ret < 0)
 521                 return ret;
 522 
 523         media_pipeline_stop(&video->ve.vdev.entity);
 524         video->streaming = 0;
 525         return 0;
 526 }
 527 
 528 static int isp_video_reqbufs(struct file *file, void *priv,
 529                                 struct v4l2_requestbuffers *rb)
 530 {
 531         struct fimc_isp *isp = video_drvdata(file);
 532         int ret;
 533 
 534         ret = vb2_ioctl_reqbufs(file, priv, rb);
 535         if (ret < 0)
 536                 return ret;
 537 
 538         if (rb->count && rb->count < FIMC_ISP_REQ_BUFS_MIN) {
 539                 rb->count = 0;
 540                 vb2_ioctl_reqbufs(file, priv, rb);
 541                 ret = -ENOMEM;
 542         }
 543 
 544         isp->video_capture.reqbufs_count = rb->count;
 545         return ret;
 546 }
 547 
 548 static const struct v4l2_ioctl_ops isp_video_ioctl_ops = {
 549         .vidioc_querycap                = isp_video_querycap,
 550         .vidioc_enum_fmt_vid_cap        = isp_video_enum_fmt,
 551         .vidioc_try_fmt_vid_cap_mplane  = isp_video_try_fmt_mplane,
 552         .vidioc_s_fmt_vid_cap_mplane    = isp_video_s_fmt_mplane,
 553         .vidioc_g_fmt_vid_cap_mplane    = isp_video_g_fmt_mplane,
 554         .vidioc_reqbufs                 = isp_video_reqbufs,
 555         .vidioc_querybuf                = vb2_ioctl_querybuf,
 556         .vidioc_prepare_buf             = vb2_ioctl_prepare_buf,
 557         .vidioc_create_bufs             = vb2_ioctl_create_bufs,
 558         .vidioc_qbuf                    = vb2_ioctl_qbuf,
 559         .vidioc_dqbuf                   = vb2_ioctl_dqbuf,
 560         .vidioc_streamon                = isp_video_streamon,
 561         .vidioc_streamoff               = isp_video_streamoff,
 562 };
 563 
 564 int fimc_isp_video_device_register(struct fimc_isp *isp,
 565                                    struct v4l2_device *v4l2_dev,
 566                                    enum v4l2_buf_type type)
 567 {
 568         struct vb2_queue *q = &isp->video_capture.vb_queue;
 569         struct fimc_is_video *iv;
 570         struct video_device *vdev;
 571         int ret;
 572 
 573         if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
 574                 iv = &isp->video_capture;
 575         else
 576                 return -ENOSYS;
 577 
 578         mutex_init(&isp->video_lock);
 579         INIT_LIST_HEAD(&iv->pending_buf_q);
 580         INIT_LIST_HEAD(&iv->active_buf_q);
 581         iv->format = fimc_isp_find_format(NULL, NULL, 0);
 582         iv->pixfmt.width = IS_DEFAULT_WIDTH;
 583         iv->pixfmt.height = IS_DEFAULT_HEIGHT;
 584         iv->pixfmt.pixelformat = iv->format->fourcc;
 585         iv->pixfmt.colorspace = V4L2_COLORSPACE_SRGB;
 586         iv->reqbufs_count = 0;
 587 
 588         memset(q, 0, sizeof(*q));
 589         q->type = type;
 590         q->io_modes = VB2_MMAP | VB2_USERPTR;
 591         q->ops = &isp_video_capture_qops;
 592         q->mem_ops = &vb2_dma_contig_memops;
 593         q->buf_struct_size = sizeof(struct isp_video_buf);
 594         q->drv_priv = isp;
 595         q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 596         q->lock = &isp->video_lock;
 597         q->dev = &isp->pdev->dev;
 598 
 599         ret = vb2_queue_init(q);
 600         if (ret < 0)
 601                 return ret;
 602 
 603         vdev = &iv->ve.vdev;
 604         memset(vdev, 0, sizeof(*vdev));
 605         strscpy(vdev->name, "fimc-is-isp.capture", sizeof(vdev->name));
 606         vdev->queue = q;
 607         vdev->fops = &isp_video_fops;
 608         vdev->ioctl_ops = &isp_video_ioctl_ops;
 609         vdev->v4l2_dev = v4l2_dev;
 610         vdev->minor = -1;
 611         vdev->release = video_device_release_empty;
 612         vdev->lock = &isp->video_lock;
 613         vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE_MPLANE;
 614 
 615         iv->pad.flags = MEDIA_PAD_FL_SINK;
 616         ret = media_entity_pads_init(&vdev->entity, 1, &iv->pad);
 617         if (ret < 0)
 618                 return ret;
 619 
 620         video_set_drvdata(vdev, isp);
 621 
 622         ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
 623         if (ret < 0) {
 624                 media_entity_cleanup(&vdev->entity);
 625                 return ret;
 626         }
 627 
 628         v4l2_info(v4l2_dev, "Registered %s as /dev/%s\n",
 629                   vdev->name, video_device_node_name(vdev));
 630 
 631         return 0;
 632 }
 633 
 634 void fimc_isp_video_device_unregister(struct fimc_isp *isp,
 635                                       enum v4l2_buf_type type)
 636 {
 637         struct exynos_video_entity *ve;
 638 
 639         if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
 640                 ve = &isp->video_capture.ve;
 641         else
 642                 return;
 643 
 644         mutex_lock(&isp->video_lock);
 645 
 646         if (video_is_registered(&ve->vdev)) {
 647                 video_unregister_device(&ve->vdev);
 648                 media_entity_cleanup(&ve->vdev.entity);
 649                 ve->pipe = NULL;
 650         }
 651 
 652         mutex_unlock(&isp->video_lock);
 653 }

/* [<][>][^][v][top][bottom][index][help] */