Lines Matching +full:isp +full:- +full:0

1 // SPDX-License-Identifier: GPL-2.0-only
3 * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
5 * FIMC-IS ISP video input and video output DMA interface driver
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>
33 #include "media-dev.h"
34 #include "fimc-is.h"
35 #include "fimc-isp-video.h"
36 #include "fimc-is-param.h"
42 struct fimc_isp *isp = vb2_get_drv_priv(vq); in isp_video_capture_queue_setup() local
43 const struct v4l2_pix_format_mplane *vid_fmt = &isp->video_capture.pixfmt; in isp_video_capture_queue_setup()
44 const struct fimc_fmt *fmt = isp->video_capture.format; in isp_video_capture_queue_setup()
47 wh = vid_fmt->width * vid_fmt->height; in isp_video_capture_queue_setup()
50 return -EINVAL; in isp_video_capture_queue_setup()
55 if (*num_planes != fmt->memplanes) in isp_video_capture_queue_setup()
56 return -EINVAL; in isp_video_capture_queue_setup()
57 for (i = 0; i < *num_planes; i++) in isp_video_capture_queue_setup()
58 if (sizes[i] < (wh * fmt->depth[i]) / 8) in isp_video_capture_queue_setup()
59 return -EINVAL; in isp_video_capture_queue_setup()
60 return 0; in isp_video_capture_queue_setup()
63 *num_planes = fmt->memplanes; in isp_video_capture_queue_setup()
65 for (i = 0; i < fmt->memplanes; i++) in isp_video_capture_queue_setup()
66 sizes[i] = (wh * fmt->depth[i]) / 8; in isp_video_capture_queue_setup()
68 return 0; in isp_video_capture_queue_setup()
73 return &__get_curr_is_config(is)->isp.dma2_output; in __get_isp_dma2()
79 struct fimc_isp *isp = vb2_get_drv_priv(q); in isp_video_capture_start_streaming() local
80 struct fimc_is *is = fimc_isp_to_is(isp); in isp_video_capture_start_streaming()
82 struct fimc_is_video *video = &isp->video_capture; in isp_video_capture_start_streaming()
85 if (!test_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state) || in isp_video_capture_start_streaming()
86 test_bit(ST_ISP_VID_CAP_STREAMING, &isp->state)) in isp_video_capture_start_streaming()
87 return 0; in isp_video_capture_start_streaming()
90 dma->cmd = DMA_OUTPUT_COMMAND_ENABLE; in isp_video_capture_start_streaming()
91 dma->notify_dma_done = DMA_OUTPUT_NOTIFY_DMA_DONE_ENABLE; in isp_video_capture_start_streaming()
92 dma->buffer_address = is->is_dma_p_region + in isp_video_capture_start_streaming()
94 dma->buffer_number = video->reqbufs_count; in isp_video_capture_start_streaming()
95 dma->dma_out_mask = video->buf_mask; in isp_video_capture_start_streaming()
97 isp_dbg(2, &video->ve.vdev, in isp_video_capture_start_streaming()
99 video->buf_count, video->format->memplanes, in isp_video_capture_start_streaming()
100 dma->buffer_address); in isp_video_capture_start_streaming()
108 if (ret < 0) in isp_video_capture_start_streaming()
111 ret = fimc_pipeline_call(&video->ve, set_stream, 1); in isp_video_capture_start_streaming()
112 if (ret < 0) in isp_video_capture_start_streaming()
115 set_bit(ST_ISP_VID_CAP_STREAMING, &isp->state); in isp_video_capture_start_streaming()
121 struct fimc_isp *isp = vb2_get_drv_priv(q); in isp_video_capture_stop_streaming() local
122 struct fimc_is *is = fimc_isp_to_is(isp); in isp_video_capture_stop_streaming()
126 ret = fimc_pipeline_call(&isp->video_capture.ve, set_stream, 0); in isp_video_capture_stop_streaming()
127 if (ret < 0) in isp_video_capture_stop_streaming()
130 dma->cmd = DMA_OUTPUT_COMMAND_DISABLE; in isp_video_capture_stop_streaming()
131 dma->notify_dma_done = DMA_OUTPUT_NOTIFY_DMA_DONE_DISABLE; in isp_video_capture_stop_streaming()
132 dma->buffer_number = 0; in isp_video_capture_stop_streaming()
133 dma->buffer_address = 0; in isp_video_capture_stop_streaming()
134 dma->dma_out_mask = 0; in isp_video_capture_stop_streaming()
140 if (ret < 0) in isp_video_capture_stop_streaming()
141 dev_warn(&is->pdev->dev, "%s: DMA stop failed\n", __func__); in isp_video_capture_stop_streaming()
143 fimc_is_hw_set_isp_buf_mask(is, 0); in isp_video_capture_stop_streaming()
145 clear_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state); in isp_video_capture_stop_streaming()
146 clear_bit(ST_ISP_VID_CAP_STREAMING, &isp->state); in isp_video_capture_stop_streaming()
148 isp->video_capture.buf_count = 0; in isp_video_capture_stop_streaming()
153 struct fimc_isp *isp = vb2_get_drv_priv(vb->vb2_queue); in isp_video_capture_buffer_prepare() local
154 struct fimc_is_video *video = &isp->video_capture; in isp_video_capture_buffer_prepare()
157 if (video->format == NULL) in isp_video_capture_buffer_prepare()
158 return -EINVAL; in isp_video_capture_buffer_prepare()
160 for (i = 0; i < video->format->memplanes; i++) { in isp_video_capture_buffer_prepare()
161 unsigned long size = video->pixfmt.plane_fmt[i].sizeimage; in isp_video_capture_buffer_prepare()
164 v4l2_err(&video->ve.vdev, in isp_video_capture_buffer_prepare()
167 return -EINVAL; in isp_video_capture_buffer_prepare()
173 if (test_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state)) { in isp_video_capture_buffer_prepare()
174 dma_addr_t dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0); in isp_video_capture_buffer_prepare()
177 for (i = 0; i < video->buf_count; i++) in isp_video_capture_buffer_prepare()
178 if (video->buffers[i]->dma_addr[0] == dma_addr) in isp_video_capture_buffer_prepare()
179 return 0; in isp_video_capture_buffer_prepare()
180 return -ENXIO; in isp_video_capture_buffer_prepare()
183 return 0; in isp_video_capture_buffer_prepare()
189 struct fimc_isp *isp = vb2_get_drv_priv(vb->vb2_queue); in isp_video_capture_buffer_queue() local
190 struct fimc_is_video *video = &isp->video_capture; in isp_video_capture_buffer_queue()
191 struct fimc_is *is = fimc_isp_to_is(isp); in isp_video_capture_buffer_queue()
196 if (test_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state)) { in isp_video_capture_buffer_queue()
197 spin_lock_irqsave(&is->slock, flags); in isp_video_capture_buffer_queue()
198 video->buf_mask |= BIT(ivb->index); in isp_video_capture_buffer_queue()
199 spin_unlock_irqrestore(&is->slock, flags); in isp_video_capture_buffer_queue()
201 unsigned int num_planes = video->format->memplanes; in isp_video_capture_buffer_queue()
203 ivb->index = video->buf_count; in isp_video_capture_buffer_queue()
204 video->buffers[ivb->index] = ivb; in isp_video_capture_buffer_queue()
206 for (i = 0; i < num_planes; i++) { in isp_video_capture_buffer_queue()
207 int buf_index = ivb->index * num_planes + i; in isp_video_capture_buffer_queue()
209 ivb->dma_addr[i] = vb2_dma_contig_plane_dma_addr(vb, i); in isp_video_capture_buffer_queue()
210 is->is_p_region->shared[32 + buf_index] = in isp_video_capture_buffer_queue()
211 ivb->dma_addr[i]; in isp_video_capture_buffer_queue()
213 isp_dbg(2, &video->ve.vdev, in isp_video_capture_buffer_queue()
215 buf_index, ivb->index, i, vb->index, in isp_video_capture_buffer_queue()
216 &ivb->dma_addr[i]); in isp_video_capture_buffer_queue()
219 if (++video->buf_count < video->reqbufs_count) in isp_video_capture_buffer_queue()
222 video->buf_mask = (1UL << video->buf_count) - 1; in isp_video_capture_buffer_queue()
223 set_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state); in isp_video_capture_buffer_queue()
226 if (!test_bit(ST_ISP_VID_CAP_STREAMING, &isp->state)) in isp_video_capture_buffer_queue()
227 isp_video_capture_start_streaming(vb->vb2_queue, 0); in isp_video_capture_buffer_queue()
231 * FIMC-IS ISP input and output DMA interface interrupt handler.
232 * Locking: called with is->slock spinlock held.
236 struct fimc_is_video *video = &is->isp.video_capture; in fimc_isp_video_irq_handler()
241 if (!test_bit(ST_ISP_VID_CAP_STREAMING, &is->isp.state)) in fimc_isp_video_irq_handler()
244 buf_index = (is->i2h_cmd.args[1] - 1) % video->buf_count; in fimc_isp_video_irq_handler()
245 vbuf = &video->buffers[buf_index]->vb; in fimc_isp_video_irq_handler()
247 vbuf->vb2_buf.timestamp = ktime_get_ns(); in fimc_isp_video_irq_handler()
248 vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_DONE); in fimc_isp_video_irq_handler()
250 video->buf_mask &= ~BIT(buf_index); in fimc_isp_video_irq_handler()
251 fimc_is_hw_set_isp_buf_mask(is, video->buf_mask); in fimc_isp_video_irq_handler()
264 struct fimc_isp *isp = video_drvdata(file); in isp_video_open() local
265 struct exynos_video_entity *ve = &isp->video_capture.ve; in isp_video_open()
266 struct media_entity *me = &ve->vdev.entity; in isp_video_open()
269 if (mutex_lock_interruptible(&isp->video_lock)) in isp_video_open()
270 return -ERESTARTSYS; in isp_video_open()
273 if (ret < 0) in isp_video_open()
276 ret = pm_runtime_resume_and_get(&isp->pdev->dev); in isp_video_open()
277 if (ret < 0) in isp_video_open()
281 mutex_lock(&me->graph_obj.mdev->graph_mutex); in isp_video_open()
286 if (ret == 0) in isp_video_open()
287 me->use_count++; in isp_video_open()
289 mutex_unlock(&me->graph_obj.mdev->graph_mutex); in isp_video_open()
296 mutex_unlock(&isp->video_lock); in isp_video_open()
302 struct fimc_isp *isp = video_drvdata(file); in isp_video_release() local
303 struct fimc_is_video *ivc = &isp->video_capture; in isp_video_release()
304 struct media_entity *entity = &ivc->ve.vdev.entity; in isp_video_release()
305 struct media_device *mdev = entity->graph_obj.mdev; in isp_video_release()
308 mutex_lock(&isp->video_lock); in isp_video_release()
312 if (is_singular_file && ivc->streaming) { in isp_video_release()
313 video_device_pipeline_stop(&ivc->ve.vdev); in isp_video_release()
314 ivc->streaming = 0; in isp_video_release()
320 fimc_pipeline_call(&ivc->ve, close); in isp_video_release()
322 mutex_lock(&mdev->graph_mutex); in isp_video_release()
323 entity->use_count--; in isp_video_release()
324 mutex_unlock(&mdev->graph_mutex); in isp_video_release()
327 pm_runtime_put(&isp->pdev->dev); in isp_video_release()
328 mutex_unlock(&isp->video_lock); in isp_video_release()
330 return 0; in isp_video_release()
348 struct fimc_isp *isp = video_drvdata(file); in isp_video_querycap() local
350 __fimc_vidioc_querycap(&isp->pdev->dev, cap); in isp_video_querycap()
351 return 0; in isp_video_querycap()
359 if (f->index >= FIMC_ISP_NUM_FORMATS) in isp_video_enum_fmt()
360 return -EINVAL; in isp_video_enum_fmt()
362 fmt = fimc_isp_find_format(NULL, NULL, f->index); in isp_video_enum_fmt()
364 return -EINVAL; in isp_video_enum_fmt()
366 f->pixelformat = fmt->fourcc; in isp_video_enum_fmt()
368 return 0; in isp_video_enum_fmt()
374 struct fimc_isp *isp = video_drvdata(file); in isp_video_g_fmt_mplane() local
376 f->fmt.pix_mp = isp->video_capture.pixfmt; in isp_video_g_fmt_mplane()
377 return 0; in isp_video_g_fmt_mplane()
380 static void __isp_video_try_fmt(struct fimc_isp *isp, in __isp_video_try_fmt() argument
386 __fmt = fimc_isp_find_format(&pixm->pixelformat, NULL, 2); in __isp_video_try_fmt()
391 pixm->colorspace = V4L2_COLORSPACE_SRGB; in __isp_video_try_fmt()
392 pixm->field = V4L2_FIELD_NONE; in __isp_video_try_fmt()
393 pixm->num_planes = __fmt->memplanes; in __isp_video_try_fmt()
394 pixm->pixelformat = __fmt->fourcc; in __isp_video_try_fmt()
399 v4l_bound_align_image(&pixm->width, FIMC_ISP_SOURCE_WIDTH_MIN, in __isp_video_try_fmt()
401 &pixm->height, FIMC_ISP_SOURCE_HEIGHT_MIN, in __isp_video_try_fmt()
402 FIMC_ISP_SOURCE_HEIGHT_MAX, 0, 0); in __isp_video_try_fmt()
408 struct fimc_isp *isp = video_drvdata(file); in isp_video_try_fmt_mplane() local
410 __isp_video_try_fmt(isp, &f->fmt.pix_mp, NULL); in isp_video_try_fmt_mplane()
411 return 0; in isp_video_try_fmt_mplane()
417 struct fimc_isp *isp = video_drvdata(file); in isp_video_s_fmt_mplane() local
418 struct fimc_is *is = fimc_isp_to_is(isp); in isp_video_s_fmt_mplane()
419 struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp; in isp_video_s_fmt_mplane()
423 __isp_video_try_fmt(isp, pixm, &ifmt); in isp_video_s_fmt_mplane()
426 return -EINVAL; in isp_video_s_fmt_mplane()
428 dma->format = DMA_OUTPUT_FORMAT_BAYER; in isp_video_s_fmt_mplane()
429 dma->order = DMA_OUTPUT_ORDER_GB_BG; in isp_video_s_fmt_mplane()
430 dma->plane = ifmt->memplanes; in isp_video_s_fmt_mplane()
431 dma->bitwidth = ifmt->depth[0]; in isp_video_s_fmt_mplane()
432 dma->width = pixm->width; in isp_video_s_fmt_mplane()
433 dma->height = pixm->height; in isp_video_s_fmt_mplane()
437 isp->video_capture.format = ifmt; in isp_video_s_fmt_mplane()
438 isp->video_capture.pixfmt = *pixm; in isp_video_s_fmt_mplane()
440 return 0; in isp_video_s_fmt_mplane()
445 * Return 0 if the formats match or -EPIPE otherwise.
447 static int isp_video_pipeline_validate(struct fimc_isp *isp) in isp_video_pipeline_validate() argument
449 struct v4l2_subdev *sd = &isp->subdev; in isp_video_pipeline_validate()
462 pad = &sd->entity.pads[0]; in isp_video_pipeline_validate()
463 if (!(pad->flags & MEDIA_PAD_FL_SINK)) in isp_video_pipeline_validate()
465 sink_fmt.pad = pad->index; in isp_video_pipeline_validate()
467 if (ret < 0 && ret != -ENOIOCTLCMD) in isp_video_pipeline_validate()
468 return -EPIPE; in isp_video_pipeline_validate()
472 if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) in isp_video_pipeline_validate()
475 sd = media_entity_to_v4l2_subdev(pad->entity); in isp_video_pipeline_validate()
476 src_fmt.pad = pad->index; in isp_video_pipeline_validate()
478 if (ret < 0 && ret != -ENOIOCTLCMD) in isp_video_pipeline_validate()
479 return -EPIPE; in isp_video_pipeline_validate()
484 return -EPIPE; in isp_video_pipeline_validate()
487 return 0; in isp_video_pipeline_validate()
493 struct fimc_isp *isp = video_drvdata(file); in isp_video_streamon() local
494 struct exynos_video_entity *ve = &isp->video_capture.ve; in isp_video_streamon()
497 ret = video_device_pipeline_start(&ve->vdev, &ve->pipe->mp); in isp_video_streamon()
498 if (ret < 0) in isp_video_streamon()
501 ret = isp_video_pipeline_validate(isp); in isp_video_streamon()
502 if (ret < 0) in isp_video_streamon()
506 if (ret < 0) in isp_video_streamon()
509 isp->video_capture.streaming = 1; in isp_video_streamon()
510 return 0; in isp_video_streamon()
512 video_device_pipeline_stop(&ve->vdev); in isp_video_streamon()
519 struct fimc_isp *isp = video_drvdata(file); in isp_video_streamoff() local
520 struct fimc_is_video *video = &isp->video_capture; in isp_video_streamoff()
524 if (ret < 0) in isp_video_streamoff()
527 video_device_pipeline_stop(&video->ve.vdev); in isp_video_streamoff()
528 video->streaming = 0; in isp_video_streamoff()
529 return 0; in isp_video_streamoff()
535 struct fimc_isp *isp = video_drvdata(file); in isp_video_reqbufs() local
539 if (ret < 0) in isp_video_reqbufs()
542 if (rb->count && rb->count < FIMC_ISP_REQ_BUFS_MIN) { in isp_video_reqbufs()
543 rb->count = 0; in isp_video_reqbufs()
545 ret = -ENOMEM; in isp_video_reqbufs()
548 isp->video_capture.reqbufs_count = rb->count; in isp_video_reqbufs()
568 int fimc_isp_video_device_register(struct fimc_isp *isp, in fimc_isp_video_device_register() argument
572 struct vb2_queue *q = &isp->video_capture.vb_queue; in fimc_isp_video_device_register()
578 iv = &isp->video_capture; in fimc_isp_video_device_register()
580 return -ENOSYS; in fimc_isp_video_device_register()
582 mutex_init(&isp->video_lock); in fimc_isp_video_device_register()
583 INIT_LIST_HEAD(&iv->pending_buf_q); in fimc_isp_video_device_register()
584 INIT_LIST_HEAD(&iv->active_buf_q); in fimc_isp_video_device_register()
585 iv->format = fimc_isp_find_format(NULL, NULL, 0); in fimc_isp_video_device_register()
586 iv->pixfmt.width = IS_DEFAULT_WIDTH; in fimc_isp_video_device_register()
587 iv->pixfmt.height = IS_DEFAULT_HEIGHT; in fimc_isp_video_device_register()
588 iv->pixfmt.pixelformat = iv->format->fourcc; in fimc_isp_video_device_register()
589 iv->pixfmt.colorspace = V4L2_COLORSPACE_SRGB; in fimc_isp_video_device_register()
590 iv->reqbufs_count = 0; in fimc_isp_video_device_register()
592 memset(q, 0, sizeof(*q)); in fimc_isp_video_device_register()
593 q->type = type; in fimc_isp_video_device_register()
594 q->io_modes = VB2_MMAP | VB2_USERPTR; in fimc_isp_video_device_register()
595 q->ops = &isp_video_capture_qops; in fimc_isp_video_device_register()
596 q->mem_ops = &vb2_dma_contig_memops; in fimc_isp_video_device_register()
597 q->buf_struct_size = sizeof(struct isp_video_buf); in fimc_isp_video_device_register()
598 q->drv_priv = isp; in fimc_isp_video_device_register()
599 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; in fimc_isp_video_device_register()
600 q->lock = &isp->video_lock; in fimc_isp_video_device_register()
601 q->dev = &isp->pdev->dev; in fimc_isp_video_device_register()
604 if (ret < 0) in fimc_isp_video_device_register()
607 vdev = &iv->ve.vdev; in fimc_isp_video_device_register()
608 memset(vdev, 0, sizeof(*vdev)); in fimc_isp_video_device_register()
609 strscpy(vdev->name, "fimc-is-isp.capture", sizeof(vdev->name)); in fimc_isp_video_device_register()
610 vdev->queue = q; in fimc_isp_video_device_register()
611 vdev->fops = &isp_video_fops; in fimc_isp_video_device_register()
612 vdev->ioctl_ops = &isp_video_ioctl_ops; in fimc_isp_video_device_register()
613 vdev->v4l2_dev = v4l2_dev; in fimc_isp_video_device_register()
614 vdev->minor = -1; in fimc_isp_video_device_register()
615 vdev->release = video_device_release_empty; in fimc_isp_video_device_register()
616 vdev->lock = &isp->video_lock; in fimc_isp_video_device_register()
617 vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE_MPLANE; in fimc_isp_video_device_register()
619 iv->pad.flags = MEDIA_PAD_FL_SINK; in fimc_isp_video_device_register()
620 ret = media_entity_pads_init(&vdev->entity, 1, &iv->pad); in fimc_isp_video_device_register()
621 if (ret < 0) in fimc_isp_video_device_register()
624 video_set_drvdata(vdev, isp); in fimc_isp_video_device_register()
626 ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); in fimc_isp_video_device_register()
627 if (ret < 0) { in fimc_isp_video_device_register()
628 media_entity_cleanup(&vdev->entity); in fimc_isp_video_device_register()
633 vdev->name, video_device_node_name(vdev)); in fimc_isp_video_device_register()
635 return 0; in fimc_isp_video_device_register()
638 void fimc_isp_video_device_unregister(struct fimc_isp *isp, in fimc_isp_video_device_unregister() argument
644 ve = &isp->video_capture.ve; in fimc_isp_video_device_unregister()
648 mutex_lock(&isp->video_lock); in fimc_isp_video_device_unregister()
650 if (video_is_registered(&ve->vdev)) { in fimc_isp_video_device_unregister()
651 video_unregister_device(&ve->vdev); in fimc_isp_video_device_unregister()
652 media_entity_cleanup(&ve->vdev.entity); in fimc_isp_video_device_unregister()
653 ve->pipe = NULL; in fimc_isp_video_device_unregister()
656 mutex_unlock(&isp->video_lock); in fimc_isp_video_device_unregister()