2 * s3c24xx/s3c64xx SoC series Camera Interface (CAMIF) driver
4 * Copyright (C) 2012 Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
5 * Copyright (C) 2012 Tomasz Figa <tomasz.figa@gmail.com>
7 * Based on drivers/media/platform/s5p-fimc,
8 * Copyright (C) 2010 - 2012 Samsung Electronics Co., Ltd.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
14 #define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
16 #include <linux/bug.h>
17 #include <linux/clk.h>
18 #include <linux/device.h>
19 #include <linux/errno.h>
20 #include <linux/i2c.h>
21 #include <linux/interrupt.h>
23 #include <linux/kernel.h>
24 #include <linux/list.h>
25 #include <linux/module.h>
26 #include <linux/platform_device.h>
27 #include <linux/pm_runtime.h>
28 #include <linux/ratelimit.h>
29 #include <linux/slab.h>
30 #include <linux/types.h>
31 #include <linux/videodev2.h>
33 #include <media/media-device.h>
34 #include <media/v4l2-ctrls.h>
35 #include <media/v4l2-event.h>
36 #include <media/v4l2-ioctl.h>
37 #include <media/videobuf2-core.h>
38 #include <media/videobuf2-dma-contig.h>
40 #include "camif-core.h"
41 #include "camif-regs.h"
44 module_param(debug
, int, 0644);
46 /* Locking: called with vp->camif->slock spinlock held */
47 static void camif_cfg_video_path(struct camif_vp
*vp
)
49 WARN_ON(s3c_camif_get_scaler_config(vp
, &vp
->scaler
));
50 camif_hw_set_scaler(vp
);
51 camif_hw_set_flip(vp
);
52 camif_hw_set_target_format(vp
);
53 camif_hw_set_output_dma(vp
);
56 static void camif_prepare_dma_offset(struct camif_vp
*vp
)
58 struct camif_frame
*f
= &vp
->out_frame
;
60 f
->dma_offset
.initial
= f
->rect
.top
* f
->f_width
+ f
->rect
.left
;
61 f
->dma_offset
.line
= f
->f_width
- (f
->rect
.left
+ f
->rect
.width
);
63 pr_debug("dma_offset: initial: %d, line: %d\n",
64 f
->dma_offset
.initial
, f
->dma_offset
.line
);
67 /* Locking: called with camif->slock spinlock held */
68 static int s3c_camif_hw_init(struct camif_dev
*camif
, struct camif_vp
*vp
)
70 const struct s3c_camif_variant
*variant
= camif
->variant
;
72 if (camif
->sensor
.sd
== NULL
|| vp
->out_fmt
== NULL
)
75 if (variant
->ip_revision
== S3C244X_CAMIF_IP_REV
)
76 camif_hw_clear_fifo_overflow(vp
);
77 camif_hw_set_camera_bus(camif
);
78 camif_hw_set_source_format(camif
);
79 camif_hw_set_camera_crop(camif
);
80 camif_hw_set_test_pattern(camif
, camif
->test_pattern
);
81 if (variant
->has_img_effect
)
82 camif_hw_set_effect(camif
, camif
->colorfx
,
83 camif
->colorfx_cb
, camif
->colorfx_cr
);
84 if (variant
->ip_revision
== S3C6410_CAMIF_IP_REV
)
85 camif_hw_set_input_path(vp
);
86 camif_cfg_video_path(vp
);
87 vp
->state
&= ~ST_VP_CONFIG
;
93 * Initialize the video path, only up from the scaler stage. The camera
94 * input interface set up is skipped. This is useful to enable one of the
95 * video paths when the other is already running.
96 * Locking: called with camif->slock spinlock held.
98 static int s3c_camif_hw_vp_init(struct camif_dev
*camif
, struct camif_vp
*vp
)
100 unsigned int ip_rev
= camif
->variant
->ip_revision
;
102 if (vp
->out_fmt
== NULL
)
105 camif_prepare_dma_offset(vp
);
106 if (ip_rev
== S3C244X_CAMIF_IP_REV
)
107 camif_hw_clear_fifo_overflow(vp
);
108 camif_cfg_video_path(vp
);
109 vp
->state
&= ~ST_VP_CONFIG
;
113 static int sensor_set_power(struct camif_dev
*camif
, int on
)
115 struct cam_sensor
*sensor
= &camif
->sensor
;
118 if (!on
== camif
->sensor
.power_count
)
119 err
= v4l2_subdev_call(sensor
->sd
, core
, s_power
, on
);
121 sensor
->power_count
+= on
? 1 : -1;
123 pr_debug("on: %d, power_count: %d, err: %d\n",
124 on
, sensor
->power_count
, err
);
129 static int sensor_set_streaming(struct camif_dev
*camif
, int on
)
131 struct cam_sensor
*sensor
= &camif
->sensor
;
134 if (!on
== camif
->sensor
.stream_count
)
135 err
= v4l2_subdev_call(sensor
->sd
, video
, s_stream
, on
);
137 sensor
->stream_count
+= on
? 1 : -1;
139 pr_debug("on: %d, stream_count: %d, err: %d\n",
140 on
, sensor
->stream_count
, err
);
146 * Reinitialize the driver so it is ready to start streaming again.
147 * Return any buffers to vb2, perform CAMIF software reset and
148 * turn off streaming at the data pipeline (sensor) if required.
150 static int camif_reinitialize(struct camif_vp
*vp
)
152 struct camif_dev
*camif
= vp
->camif
;
153 struct camif_buffer
*buf
;
157 spin_lock_irqsave(&camif
->slock
, flags
);
158 streaming
= vp
->state
& ST_VP_SENSOR_STREAMING
;
160 vp
->state
&= ~(ST_VP_PENDING
| ST_VP_RUNNING
| ST_VP_OFF
|
161 ST_VP_ABORTING
| ST_VP_STREAMING
|
162 ST_VP_SENSOR_STREAMING
| ST_VP_LASTIRQ
);
164 /* Release unused buffers */
165 while (!list_empty(&vp
->pending_buf_q
)) {
166 buf
= camif_pending_queue_pop(vp
);
167 vb2_buffer_done(&buf
->vb
, VB2_BUF_STATE_ERROR
);
170 while (!list_empty(&vp
->active_buf_q
)) {
171 buf
= camif_active_queue_pop(vp
);
172 vb2_buffer_done(&buf
->vb
, VB2_BUF_STATE_ERROR
);
175 spin_unlock_irqrestore(&camif
->slock
, flags
);
180 return sensor_set_streaming(camif
, 0);
183 static bool s3c_vp_active(struct camif_vp
*vp
)
185 struct camif_dev
*camif
= vp
->camif
;
189 spin_lock_irqsave(&camif
->slock
, flags
);
190 ret
= (vp
->state
& ST_VP_RUNNING
) || (vp
->state
& ST_VP_PENDING
);
191 spin_unlock_irqrestore(&camif
->slock
, flags
);
196 static bool camif_is_streaming(struct camif_dev
*camif
)
201 spin_lock_irqsave(&camif
->slock
, flags
);
202 status
= camif
->stream_count
> 0;
203 spin_unlock_irqrestore(&camif
->slock
, flags
);
208 static int camif_stop_capture(struct camif_vp
*vp
)
210 struct camif_dev
*camif
= vp
->camif
;
214 if (!s3c_vp_active(vp
))
217 spin_lock_irqsave(&camif
->slock
, flags
);
218 vp
->state
&= ~(ST_VP_OFF
| ST_VP_LASTIRQ
);
219 vp
->state
|= ST_VP_ABORTING
;
220 spin_unlock_irqrestore(&camif
->slock
, flags
);
222 ret
= wait_event_timeout(vp
->irq_queue
,
223 !(vp
->state
& ST_VP_ABORTING
),
224 msecs_to_jiffies(CAMIF_STOP_TIMEOUT
));
226 spin_lock_irqsave(&camif
->slock
, flags
);
228 if (ret
== 0 && !(vp
->state
& ST_VP_OFF
)) {
229 /* Timed out, forcibly stop capture */
230 vp
->state
&= ~(ST_VP_OFF
| ST_VP_ABORTING
|
233 camif_hw_disable_capture(vp
);
234 camif_hw_enable_scaler(vp
, false);
237 spin_unlock_irqrestore(&camif
->slock
, flags
);
239 return camif_reinitialize(vp
);
242 static int camif_prepare_addr(struct camif_vp
*vp
, struct vb2_buffer
*vb
,
243 struct camif_addr
*paddr
)
245 struct camif_frame
*frame
= &vp
->out_frame
;
248 if (vb
== NULL
|| frame
== NULL
)
251 pix_size
= frame
->rect
.width
* frame
->rect
.height
;
253 pr_debug("colplanes: %d, pix_size: %u\n",
254 vp
->out_fmt
->colplanes
, pix_size
);
256 paddr
->y
= vb2_dma_contig_plane_dma_addr(vb
, 0);
258 switch (vp
->out_fmt
->colplanes
) {
264 /* decompose Y into Y/Cb */
265 paddr
->cb
= (u32
)(paddr
->y
+ pix_size
);
269 paddr
->cb
= (u32
)(paddr
->y
+ pix_size
);
270 /* decompose Y into Y/Cb/Cr */
271 if (vp
->out_fmt
->color
== IMG_FMT_YCBCR422P
)
272 paddr
->cr
= (u32
)(paddr
->cb
+ (pix_size
>> 1));
274 paddr
->cr
= (u32
)(paddr
->cb
+ (pix_size
>> 2));
276 if (vp
->out_fmt
->color
== IMG_FMT_YCRCB420
)
277 swap(paddr
->cb
, paddr
->cr
);
283 pr_debug("DMA address: y: %#x cb: %#x cr: %#x\n",
284 paddr
->y
, paddr
->cb
, paddr
->cr
);
289 irqreturn_t
s3c_camif_irq_handler(int irq
, void *priv
)
291 struct camif_vp
*vp
= priv
;
292 struct camif_dev
*camif
= vp
->camif
;
293 unsigned int ip_rev
= camif
->variant
->ip_revision
;
296 spin_lock(&camif
->slock
);
298 if (ip_rev
== S3C6410_CAMIF_IP_REV
)
299 camif_hw_clear_pending_irq(vp
);
301 status
= camif_hw_get_status(vp
);
303 if (ip_rev
== S3C244X_CAMIF_IP_REV
&& (status
& CISTATUS_OVF_MASK
)) {
304 camif_hw_clear_fifo_overflow(vp
);
308 if (vp
->state
& ST_VP_ABORTING
) {
309 if (vp
->state
& ST_VP_OFF
) {
311 vp
->state
&= ~(ST_VP_OFF
| ST_VP_ABORTING
|
313 wake_up(&vp
->irq_queue
);
315 } else if (vp
->state
& ST_VP_LASTIRQ
) {
316 camif_hw_disable_capture(vp
);
317 camif_hw_enable_scaler(vp
, false);
318 camif_hw_set_lastirq(vp
, false);
319 vp
->state
|= ST_VP_OFF
;
321 /* Disable capture, enable last IRQ */
322 camif_hw_set_lastirq(vp
, true);
323 vp
->state
|= ST_VP_LASTIRQ
;
327 if (!list_empty(&vp
->pending_buf_q
) && (vp
->state
& ST_VP_RUNNING
) &&
328 !list_empty(&vp
->active_buf_q
)) {
330 struct camif_buffer
*vbuf
;
334 * Get previous DMA write buffer index:
335 * 0 => DMA buffer 0, 2;
336 * 1 => DMA buffer 1, 3.
338 index
= (CISTATUS_FRAMECNT(status
) + 2) & 1;
341 vbuf
= camif_active_queue_peek(vp
, index
);
343 if (!WARN_ON(vbuf
== NULL
)) {
344 /* Dequeue a filled buffer */
345 tv
= &vbuf
->vb
.v4l2_buf
.timestamp
;
346 tv
->tv_sec
= ts
.tv_sec
;
347 tv
->tv_usec
= ts
.tv_nsec
/ NSEC_PER_USEC
;
348 vbuf
->vb
.v4l2_buf
.sequence
= vp
->frame_sequence
++;
349 vb2_buffer_done(&vbuf
->vb
, VB2_BUF_STATE_DONE
);
351 /* Set up an empty buffer at the DMA engine */
352 vbuf
= camif_pending_queue_pop(vp
);
354 camif_hw_set_output_addr(vp
, &vbuf
->paddr
, index
);
355 camif_hw_set_output_addr(vp
, &vbuf
->paddr
, index
+ 2);
357 /* Scheduled in H/W, add to the queue */
358 camif_active_queue_add(vp
, vbuf
);
360 } else if (!(vp
->state
& ST_VP_ABORTING
) &&
361 (vp
->state
& ST_VP_PENDING
)) {
362 vp
->state
|= ST_VP_RUNNING
;
365 if (vp
->state
& ST_VP_CONFIG
) {
366 camif_prepare_dma_offset(vp
);
367 camif_hw_set_camera_crop(camif
);
368 camif_hw_set_scaler(vp
);
369 camif_hw_set_flip(vp
);
370 camif_hw_set_test_pattern(camif
, camif
->test_pattern
);
371 if (camif
->variant
->has_img_effect
)
372 camif_hw_set_effect(camif
, camif
->colorfx
,
373 camif
->colorfx_cb
, camif
->colorfx_cr
);
374 vp
->state
&= ~ST_VP_CONFIG
;
377 spin_unlock(&camif
->slock
);
381 static int start_streaming(struct vb2_queue
*vq
, unsigned int count
)
383 struct camif_vp
*vp
= vb2_get_drv_priv(vq
);
384 struct camif_dev
*camif
= vp
->camif
;
389 * We assume the codec capture path is always activated
390 * first, before the preview path starts streaming.
391 * This is required to avoid internal FIFO overflow and
392 * a need for CAMIF software reset.
394 spin_lock_irqsave(&camif
->slock
, flags
);
396 if (camif
->stream_count
== 0) {
397 camif_hw_reset(camif
);
398 ret
= s3c_camif_hw_init(camif
, vp
);
400 ret
= s3c_camif_hw_vp_init(camif
, vp
);
402 spin_unlock_irqrestore(&camif
->slock
, flags
);
405 camif_reinitialize(vp
);
409 spin_lock_irqsave(&camif
->slock
, flags
);
410 vp
->frame_sequence
= 0;
411 vp
->state
|= ST_VP_PENDING
;
413 if (!list_empty(&vp
->pending_buf_q
) &&
414 (!(vp
->state
& ST_VP_STREAMING
) ||
415 !(vp
->state
& ST_VP_SENSOR_STREAMING
))) {
417 camif_hw_enable_scaler(vp
, vp
->scaler
.enable
);
418 camif_hw_enable_capture(vp
);
419 vp
->state
|= ST_VP_STREAMING
;
421 if (!(vp
->state
& ST_VP_SENSOR_STREAMING
)) {
422 vp
->state
|= ST_VP_SENSOR_STREAMING
;
423 spin_unlock_irqrestore(&camif
->slock
, flags
);
424 ret
= sensor_set_streaming(camif
, 1);
426 v4l2_err(&vp
->vdev
, "Sensor s_stream failed\n");
428 camif_hw_dump_regs(camif
, __func__
);
434 spin_unlock_irqrestore(&camif
->slock
, flags
);
438 static int stop_streaming(struct vb2_queue
*vq
)
440 struct camif_vp
*vp
= vb2_get_drv_priv(vq
);
441 return camif_stop_capture(vp
);
444 static int queue_setup(struct vb2_queue
*vq
, const struct v4l2_format
*pfmt
,
445 unsigned int *num_buffers
, unsigned int *num_planes
,
446 unsigned int sizes
[], void *allocators
[])
448 const struct v4l2_pix_format
*pix
= NULL
;
449 struct camif_vp
*vp
= vb2_get_drv_priv(vq
);
450 struct camif_dev
*camif
= vp
->camif
;
451 struct camif_frame
*frame
= &vp
->out_frame
;
452 const struct camif_fmt
*fmt
= vp
->out_fmt
;
456 pix
= &pfmt
->fmt
.pix
;
457 fmt
= s3c_camif_find_format(vp
, &pix
->pixelformat
, -1);
458 size
= (pix
->width
* pix
->height
* fmt
->depth
) / 8;
460 size
= (frame
->f_width
* frame
->f_height
* fmt
->depth
) / 8;
468 sizes
[0] = max(size
, pix
->sizeimage
);
471 allocators
[0] = camif
->alloc_ctx
;
473 pr_debug("size: %u\n", sizes
[0]);
477 static int buffer_prepare(struct vb2_buffer
*vb
)
479 struct camif_vp
*vp
= vb2_get_drv_priv(vb
->vb2_queue
);
481 if (vp
->out_fmt
== NULL
)
484 if (vb2_plane_size(vb
, 0) < vp
->payload
) {
485 v4l2_err(&vp
->vdev
, "buffer too small: %lu, required: %u\n",
486 vb2_plane_size(vb
, 0), vp
->payload
);
489 vb2_set_plane_payload(vb
, 0, vp
->payload
);
494 static void buffer_queue(struct vb2_buffer
*vb
)
496 struct camif_buffer
*buf
= container_of(vb
, struct camif_buffer
, vb
);
497 struct camif_vp
*vp
= vb2_get_drv_priv(vb
->vb2_queue
);
498 struct camif_dev
*camif
= vp
->camif
;
501 spin_lock_irqsave(&camif
->slock
, flags
);
502 WARN_ON(camif_prepare_addr(vp
, &buf
->vb
, &buf
->paddr
));
504 if (!(vp
->state
& ST_VP_STREAMING
) && vp
->active_buffers
< 2) {
505 /* Schedule an empty buffer in H/W */
506 buf
->index
= vp
->buf_index
;
508 camif_hw_set_output_addr(vp
, &buf
->paddr
, buf
->index
);
509 camif_hw_set_output_addr(vp
, &buf
->paddr
, buf
->index
+ 2);
511 camif_active_queue_add(vp
, buf
);
512 vp
->buf_index
= !vp
->buf_index
;
514 camif_pending_queue_add(vp
, buf
);
517 if (vb2_is_streaming(&vp
->vb_queue
) && !list_empty(&vp
->pending_buf_q
)
518 && !(vp
->state
& ST_VP_STREAMING
)) {
520 vp
->state
|= ST_VP_STREAMING
;
521 camif_hw_enable_scaler(vp
, vp
->scaler
.enable
);
522 camif_hw_enable_capture(vp
);
523 spin_unlock_irqrestore(&camif
->slock
, flags
);
525 if (!(vp
->state
& ST_VP_SENSOR_STREAMING
)) {
526 if (sensor_set_streaming(camif
, 1) == 0)
527 vp
->state
|= ST_VP_SENSOR_STREAMING
;
529 v4l2_err(&vp
->vdev
, "Sensor s_stream failed\n");
532 camif_hw_dump_regs(camif
, __func__
);
536 spin_unlock_irqrestore(&camif
->slock
, flags
);
539 static void camif_lock(struct vb2_queue
*vq
)
541 struct camif_vp
*vp
= vb2_get_drv_priv(vq
);
542 mutex_lock(&vp
->camif
->lock
);
545 static void camif_unlock(struct vb2_queue
*vq
)
547 struct camif_vp
*vp
= vb2_get_drv_priv(vq
);
548 mutex_unlock(&vp
->camif
->lock
);
551 static const struct vb2_ops s3c_camif_qops
= {
552 .queue_setup
= queue_setup
,
553 .buf_prepare
= buffer_prepare
,
554 .buf_queue
= buffer_queue
,
555 .wait_prepare
= camif_unlock
,
556 .wait_finish
= camif_lock
,
557 .start_streaming
= start_streaming
,
558 .stop_streaming
= stop_streaming
,
561 static int s3c_camif_open(struct file
*file
)
563 struct camif_vp
*vp
= video_drvdata(file
);
564 struct camif_dev
*camif
= vp
->camif
;
567 pr_debug("[vp%d] state: %#x, owner: %p, pid: %d\n", vp
->id
,
568 vp
->state
, vp
->owner
, task_pid_nr(current
));
570 if (mutex_lock_interruptible(&camif
->lock
))
573 ret
= v4l2_fh_open(file
);
577 ret
= pm_runtime_get_sync(camif
->dev
);
581 ret
= sensor_set_power(camif
, 1);
585 pm_runtime_put(camif
->dev
);
587 v4l2_fh_release(file
);
589 mutex_unlock(&camif
->lock
);
593 static int s3c_camif_close(struct file
*file
)
595 struct camif_vp
*vp
= video_drvdata(file
);
596 struct camif_dev
*camif
= vp
->camif
;
599 pr_debug("[vp%d] state: %#x, owner: %p, pid: %d\n", vp
->id
,
600 vp
->state
, vp
->owner
, task_pid_nr(current
));
602 mutex_lock(&camif
->lock
);
604 if (vp
->owner
== file
->private_data
) {
605 camif_stop_capture(vp
);
606 vb2_queue_release(&vp
->vb_queue
);
610 sensor_set_power(camif
, 0);
612 pm_runtime_put(camif
->dev
);
613 ret
= v4l2_fh_release(file
);
615 mutex_unlock(&camif
->lock
);
619 static unsigned int s3c_camif_poll(struct file
*file
,
620 struct poll_table_struct
*wait
)
622 struct camif_vp
*vp
= video_drvdata(file
);
623 struct camif_dev
*camif
= vp
->camif
;
626 mutex_lock(&camif
->lock
);
627 if (vp
->owner
&& vp
->owner
!= file
->private_data
)
630 ret
= vb2_poll(&vp
->vb_queue
, file
, wait
);
632 mutex_unlock(&camif
->lock
);
636 static int s3c_camif_mmap(struct file
*file
, struct vm_area_struct
*vma
)
638 struct camif_vp
*vp
= video_drvdata(file
);
641 if (vp
->owner
&& vp
->owner
!= file
->private_data
)
644 ret
= vb2_mmap(&vp
->vb_queue
, vma
);
649 static const struct v4l2_file_operations s3c_camif_fops
= {
650 .owner
= THIS_MODULE
,
651 .open
= s3c_camif_open
,
652 .release
= s3c_camif_close
,
653 .poll
= s3c_camif_poll
,
654 .unlocked_ioctl
= video_ioctl2
,
655 .mmap
= s3c_camif_mmap
,
662 static int s3c_camif_vidioc_querycap(struct file
*file
, void *priv
,
663 struct v4l2_capability
*cap
)
665 struct camif_vp
*vp
= video_drvdata(file
);
667 strlcpy(cap
->driver
, S3C_CAMIF_DRIVER_NAME
, sizeof(cap
->driver
));
668 strlcpy(cap
->card
, S3C_CAMIF_DRIVER_NAME
, sizeof(cap
->card
));
669 snprintf(cap
->bus_info
, sizeof(cap
->bus_info
), "platform:%s.%d",
670 dev_name(vp
->camif
->dev
), vp
->id
);
672 cap
->device_caps
= V4L2_CAP_STREAMING
| V4L2_CAP_VIDEO_CAPTURE
;
673 cap
->capabilities
= cap
->device_caps
| V4L2_CAP_DEVICE_CAPS
;
678 static int s3c_camif_vidioc_enum_input(struct file
*file
, void *priv
,
679 struct v4l2_input
*input
)
681 struct camif_vp
*vp
= video_drvdata(file
);
682 struct v4l2_subdev
*sensor
= vp
->camif
->sensor
.sd
;
684 if (input
->index
|| sensor
== NULL
)
687 input
->type
= V4L2_INPUT_TYPE_CAMERA
;
688 strlcpy(input
->name
, sensor
->name
, sizeof(input
->name
));
692 static int s3c_camif_vidioc_s_input(struct file
*file
, void *priv
,
695 return i
== 0 ? 0 : -EINVAL
;
698 static int s3c_camif_vidioc_g_input(struct file
*file
, void *priv
,
705 static int s3c_camif_vidioc_enum_fmt(struct file
*file
, void *priv
,
706 struct v4l2_fmtdesc
*f
)
708 struct camif_vp
*vp
= video_drvdata(file
);
709 const struct camif_fmt
*fmt
;
711 fmt
= s3c_camif_find_format(vp
, NULL
, f
->index
);
715 strlcpy(f
->description
, fmt
->name
, sizeof(f
->description
));
716 f
->pixelformat
= fmt
->fourcc
;
718 pr_debug("fmt(%d): %s\n", f
->index
, f
->description
);
722 static int s3c_camif_vidioc_g_fmt(struct file
*file
, void *priv
,
723 struct v4l2_format
*f
)
725 struct camif_vp
*vp
= video_drvdata(file
);
726 struct v4l2_pix_format
*pix
= &f
->fmt
.pix
;
727 struct camif_frame
*frame
= &vp
->out_frame
;
728 const struct camif_fmt
*fmt
= vp
->out_fmt
;
730 pix
->bytesperline
= frame
->f_width
* fmt
->ybpp
;
731 pix
->sizeimage
= vp
->payload
;
733 pix
->pixelformat
= fmt
->fourcc
;
734 pix
->width
= frame
->f_width
;
735 pix
->height
= frame
->f_height
;
736 pix
->field
= V4L2_FIELD_NONE
;
737 pix
->colorspace
= V4L2_COLORSPACE_JPEG
;
742 static int __camif_video_try_format(struct camif_vp
*vp
,
743 struct v4l2_pix_format
*pix
,
744 const struct camif_fmt
**ffmt
)
746 struct camif_dev
*camif
= vp
->camif
;
747 struct v4l2_rect
*crop
= &camif
->camif_crop
;
748 unsigned int wmin
, hmin
, sc_hrmax
, sc_vrmax
;
749 const struct vp_pix_limits
*pix_lim
;
750 const struct camif_fmt
*fmt
;
752 fmt
= s3c_camif_find_format(vp
, &pix
->pixelformat
, 0);
754 if (WARN_ON(fmt
== NULL
))
760 pix_lim
= &camif
->variant
->vp_pix_limits
[vp
->id
];
762 pr_debug("fmt: %ux%u, crop: %ux%u, bytesperline: %u\n",
763 pix
->width
, pix
->height
, crop
->width
, crop
->height
,
766 * Calculate minimum width and height according to the configured
767 * camera input interface crop rectangle and the resizer's capabilities.
769 sc_hrmax
= min(SCALER_MAX_RATIO
, 1 << (ffs(crop
->width
) - 3));
770 sc_vrmax
= min(SCALER_MAX_RATIO
, 1 << (ffs(crop
->height
) - 1));
772 wmin
= max_t(u32
, pix_lim
->min_out_width
, crop
->width
/ sc_hrmax
);
773 wmin
= round_up(wmin
, pix_lim
->out_width_align
);
774 hmin
= max_t(u32
, 8, crop
->height
/ sc_vrmax
);
775 hmin
= round_up(hmin
, 8);
777 v4l_bound_align_image(&pix
->width
, wmin
, pix_lim
->max_sc_out_width
,
778 ffs(pix_lim
->out_width_align
) - 1,
779 &pix
->height
, hmin
, pix_lim
->max_height
, 0, 0);
781 pix
->bytesperline
= pix
->width
* fmt
->ybpp
;
782 pix
->sizeimage
= (pix
->width
* pix
->height
* fmt
->depth
) / 8;
783 pix
->pixelformat
= fmt
->fourcc
;
784 pix
->colorspace
= V4L2_COLORSPACE_JPEG
;
785 pix
->field
= V4L2_FIELD_NONE
;
787 pr_debug("%ux%u, wmin: %d, hmin: %d, sc_hrmax: %d, sc_vrmax: %d\n",
788 pix
->width
, pix
->height
, wmin
, hmin
, sc_hrmax
, sc_vrmax
);
793 static int s3c_camif_vidioc_try_fmt(struct file
*file
, void *priv
,
794 struct v4l2_format
*f
)
796 struct camif_vp
*vp
= video_drvdata(file
);
797 return __camif_video_try_format(vp
, &f
->fmt
.pix
, NULL
);
800 static int s3c_camif_vidioc_s_fmt(struct file
*file
, void *priv
,
801 struct v4l2_format
*f
)
803 struct v4l2_pix_format
*pix
= &f
->fmt
.pix
;
804 struct camif_vp
*vp
= video_drvdata(file
);
805 struct camif_frame
*out_frame
= &vp
->out_frame
;
806 const struct camif_fmt
*fmt
= NULL
;
809 pr_debug("[vp%d]\n", vp
->id
);
811 if (vb2_is_busy(&vp
->vb_queue
))
814 ret
= __camif_video_try_format(vp
, &f
->fmt
.pix
, &fmt
);
819 vp
->payload
= pix
->sizeimage
;
820 out_frame
->f_width
= pix
->width
;
821 out_frame
->f_height
= pix
->height
;
823 /* Reset composition rectangle */
824 out_frame
->rect
.width
= pix
->width
;
825 out_frame
->rect
.height
= pix
->height
;
826 out_frame
->rect
.left
= 0;
827 out_frame
->rect
.top
= 0;
829 if (vp
->owner
== NULL
)
832 pr_debug("%ux%u. payload: %u. fmt: %s. %d %d. sizeimage: %d. bpl: %d\n",
833 out_frame
->f_width
, out_frame
->f_height
, vp
->payload
, fmt
->name
,
834 pix
->width
* pix
->height
* fmt
->depth
, fmt
->depth
,
835 pix
->sizeimage
, pix
->bytesperline
);
840 /* Only check pixel formats at the sensor and the camif subdev pads */
841 static int camif_pipeline_validate(struct camif_dev
*camif
)
843 struct v4l2_subdev_format src_fmt
;
844 struct media_pad
*pad
;
847 /* Retrieve format at the sensor subdev source pad */
848 pad
= media_entity_remote_source(&camif
->pads
[0]);
849 if (!pad
|| media_entity_type(pad
->entity
) != MEDIA_ENT_T_V4L2_SUBDEV
)
852 src_fmt
.pad
= pad
->index
;
853 src_fmt
.which
= V4L2_SUBDEV_FORMAT_ACTIVE
;
854 ret
= v4l2_subdev_call(camif
->sensor
.sd
, pad
, get_fmt
, NULL
, &src_fmt
);
855 if (ret
< 0 && ret
!= -ENOIOCTLCMD
)
858 if (src_fmt
.format
.width
!= camif
->mbus_fmt
.width
||
859 src_fmt
.format
.height
!= camif
->mbus_fmt
.height
||
860 src_fmt
.format
.code
!= camif
->mbus_fmt
.code
)
866 static int s3c_camif_streamon(struct file
*file
, void *priv
,
867 enum v4l2_buf_type type
)
869 struct camif_vp
*vp
= video_drvdata(file
);
870 struct camif_dev
*camif
= vp
->camif
;
871 struct media_entity
*sensor
= &camif
->sensor
.sd
->entity
;
874 pr_debug("[vp%d]\n", vp
->id
);
876 if (type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
879 if (vp
->owner
&& vp
->owner
!= priv
)
882 if (s3c_vp_active(vp
))
885 ret
= media_entity_pipeline_start(sensor
, camif
->m_pipeline
);
889 ret
= camif_pipeline_validate(camif
);
891 media_entity_pipeline_stop(sensor
);
895 return vb2_streamon(&vp
->vb_queue
, type
);
898 static int s3c_camif_streamoff(struct file
*file
, void *priv
,
899 enum v4l2_buf_type type
)
901 struct camif_vp
*vp
= video_drvdata(file
);
902 struct camif_dev
*camif
= vp
->camif
;
905 pr_debug("[vp%d]\n", vp
->id
);
907 if (type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
910 if (vp
->owner
&& vp
->owner
!= priv
)
913 ret
= vb2_streamoff(&vp
->vb_queue
, type
);
915 media_entity_pipeline_stop(&camif
->sensor
.sd
->entity
);
919 static int s3c_camif_reqbufs(struct file
*file
, void *priv
,
920 struct v4l2_requestbuffers
*rb
)
922 struct camif_vp
*vp
= video_drvdata(file
);
925 pr_debug("[vp%d] rb count: %d, owner: %p, priv: %p\n",
926 vp
->id
, rb
->count
, vp
->owner
, priv
);
928 if (vp
->owner
&& vp
->owner
!= priv
)
932 rb
->count
= max_t(u32
, CAMIF_REQ_BUFS_MIN
, rb
->count
);
936 ret
= vb2_reqbufs(&vp
->vb_queue
, rb
);
940 if (rb
->count
&& rb
->count
< CAMIF_REQ_BUFS_MIN
) {
942 vb2_reqbufs(&vp
->vb_queue
, rb
);
946 vp
->reqbufs_count
= rb
->count
;
947 if (vp
->owner
== NULL
&& rb
->count
> 0)
953 static int s3c_camif_querybuf(struct file
*file
, void *priv
,
954 struct v4l2_buffer
*buf
)
956 struct camif_vp
*vp
= video_drvdata(file
);
957 return vb2_querybuf(&vp
->vb_queue
, buf
);
960 static int s3c_camif_qbuf(struct file
*file
, void *priv
,
961 struct v4l2_buffer
*buf
)
963 struct camif_vp
*vp
= video_drvdata(file
);
965 pr_debug("[vp%d]\n", vp
->id
);
967 if (vp
->owner
&& vp
->owner
!= priv
)
970 return vb2_qbuf(&vp
->vb_queue
, buf
);
973 static int s3c_camif_dqbuf(struct file
*file
, void *priv
,
974 struct v4l2_buffer
*buf
)
976 struct camif_vp
*vp
= video_drvdata(file
);
978 pr_debug("[vp%d] sequence: %d\n", vp
->id
, vp
->frame_sequence
);
980 if (vp
->owner
&& vp
->owner
!= priv
)
983 return vb2_dqbuf(&vp
->vb_queue
, buf
, file
->f_flags
& O_NONBLOCK
);
986 static int s3c_camif_create_bufs(struct file
*file
, void *priv
,
987 struct v4l2_create_buffers
*create
)
989 struct camif_vp
*vp
= video_drvdata(file
);
992 if (vp
->owner
&& vp
->owner
!= priv
)
995 create
->count
= max_t(u32
, 1, create
->count
);
996 ret
= vb2_create_bufs(&vp
->vb_queue
, create
);
998 if (!ret
&& vp
->owner
== NULL
)
1004 static int s3c_camif_prepare_buf(struct file
*file
, void *priv
,
1005 struct v4l2_buffer
*b
)
1007 struct camif_vp
*vp
= video_drvdata(file
);
1008 return vb2_prepare_buf(&vp
->vb_queue
, b
);
1011 static int s3c_camif_g_selection(struct file
*file
, void *priv
,
1012 struct v4l2_selection
*sel
)
1014 struct camif_vp
*vp
= video_drvdata(file
);
1016 if (sel
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1019 switch (sel
->target
) {
1020 case V4L2_SEL_TGT_COMPOSE_BOUNDS
:
1021 case V4L2_SEL_TGT_COMPOSE_DEFAULT
:
1024 sel
->r
.width
= vp
->out_frame
.f_width
;
1025 sel
->r
.height
= vp
->out_frame
.f_height
;
1028 case V4L2_SEL_TGT_COMPOSE
:
1029 sel
->r
= vp
->out_frame
.rect
;
1036 static void __camif_try_compose(struct camif_dev
*camif
, struct camif_vp
*vp
,
1037 struct v4l2_rect
*r
)
1039 /* s3c244x doesn't support composition */
1040 if (camif
->variant
->ip_revision
== S3C244X_CAMIF_IP_REV
) {
1041 *r
= vp
->out_frame
.rect
;
1048 static int s3c_camif_s_selection(struct file
*file
, void *priv
,
1049 struct v4l2_selection
*sel
)
1051 struct camif_vp
*vp
= video_drvdata(file
);
1052 struct camif_dev
*camif
= vp
->camif
;
1053 struct v4l2_rect rect
= sel
->r
;
1054 unsigned long flags
;
1056 if (sel
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
||
1057 sel
->target
!= V4L2_SEL_TGT_COMPOSE
)
1060 __camif_try_compose(camif
, vp
, &rect
);
1063 spin_lock_irqsave(&camif
->slock
, flags
);
1064 vp
->out_frame
.rect
= rect
;
1065 vp
->state
|= ST_VP_CONFIG
;
1066 spin_unlock_irqrestore(&camif
->slock
, flags
);
1068 pr_debug("type: %#x, target: %#x, flags: %#x, (%d,%d)/%dx%d\n",
1069 sel
->type
, sel
->target
, sel
->flags
,
1070 sel
->r
.left
, sel
->r
.top
, sel
->r
.width
, sel
->r
.height
);
1075 static const struct v4l2_ioctl_ops s3c_camif_ioctl_ops
= {
1076 .vidioc_querycap
= s3c_camif_vidioc_querycap
,
1077 .vidioc_enum_input
= s3c_camif_vidioc_enum_input
,
1078 .vidioc_g_input
= s3c_camif_vidioc_g_input
,
1079 .vidioc_s_input
= s3c_camif_vidioc_s_input
,
1080 .vidioc_enum_fmt_vid_cap
= s3c_camif_vidioc_enum_fmt
,
1081 .vidioc_try_fmt_vid_cap
= s3c_camif_vidioc_try_fmt
,
1082 .vidioc_s_fmt_vid_cap
= s3c_camif_vidioc_s_fmt
,
1083 .vidioc_g_fmt_vid_cap
= s3c_camif_vidioc_g_fmt
,
1084 .vidioc_g_selection
= s3c_camif_g_selection
,
1085 .vidioc_s_selection
= s3c_camif_s_selection
,
1086 .vidioc_reqbufs
= s3c_camif_reqbufs
,
1087 .vidioc_querybuf
= s3c_camif_querybuf
,
1088 .vidioc_prepare_buf
= s3c_camif_prepare_buf
,
1089 .vidioc_create_bufs
= s3c_camif_create_bufs
,
1090 .vidioc_qbuf
= s3c_camif_qbuf
,
1091 .vidioc_dqbuf
= s3c_camif_dqbuf
,
1092 .vidioc_streamon
= s3c_camif_streamon
,
1093 .vidioc_streamoff
= s3c_camif_streamoff
,
1094 .vidioc_subscribe_event
= v4l2_ctrl_subscribe_event
,
1095 .vidioc_unsubscribe_event
= v4l2_event_unsubscribe
,
1096 .vidioc_log_status
= v4l2_ctrl_log_status
,
1100 * Video node controls
1102 static int s3c_camif_video_s_ctrl(struct v4l2_ctrl
*ctrl
)
1104 struct camif_vp
*vp
= ctrl
->priv
;
1105 struct camif_dev
*camif
= vp
->camif
;
1106 unsigned long flags
;
1108 pr_debug("[vp%d] ctrl: %s, value: %d\n", vp
->id
,
1109 ctrl
->name
, ctrl
->val
);
1111 spin_lock_irqsave(&camif
->slock
, flags
);
1114 case V4L2_CID_HFLIP
:
1115 vp
->hflip
= ctrl
->val
;
1118 case V4L2_CID_VFLIP
:
1119 vp
->vflip
= ctrl
->val
;
1123 vp
->state
|= ST_VP_CONFIG
;
1124 spin_unlock_irqrestore(&camif
->slock
, flags
);
1128 /* Codec and preview video node control ops */
1129 static const struct v4l2_ctrl_ops s3c_camif_video_ctrl_ops
= {
1130 .s_ctrl
= s3c_camif_video_s_ctrl
,
1133 int s3c_camif_register_video_node(struct camif_dev
*camif
, int idx
)
1135 struct camif_vp
*vp
= &camif
->vp
[idx
];
1136 struct vb2_queue
*q
= &vp
->vb_queue
;
1137 struct video_device
*vfd
= &vp
->vdev
;
1138 struct v4l2_ctrl
*ctrl
;
1141 memset(vfd
, 0, sizeof(*vfd
));
1142 snprintf(vfd
->name
, sizeof(vfd
->name
), "camif-%s",
1143 vp
->id
== 0 ? "codec" : "preview");
1145 vfd
->fops
= &s3c_camif_fops
;
1146 vfd
->ioctl_ops
= &s3c_camif_ioctl_ops
;
1147 vfd
->v4l2_dev
= &camif
->v4l2_dev
;
1149 vfd
->release
= video_device_release_empty
;
1150 vfd
->lock
= &camif
->lock
;
1151 vp
->reqbufs_count
= 0;
1153 INIT_LIST_HEAD(&vp
->pending_buf_q
);
1154 INIT_LIST_HEAD(&vp
->active_buf_q
);
1156 memset(q
, 0, sizeof(*q
));
1157 q
->type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1158 q
->io_modes
= VB2_MMAP
| VB2_USERPTR
;
1159 q
->ops
= &s3c_camif_qops
;
1160 q
->mem_ops
= &vb2_dma_contig_memops
;
1161 q
->buf_struct_size
= sizeof(struct camif_buffer
);
1163 q
->timestamp_type
= V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC
;
1165 ret
= vb2_queue_init(q
);
1169 vp
->pad
.flags
= MEDIA_PAD_FL_SINK
;
1170 ret
= media_entity_init(&vfd
->entity
, 1, &vp
->pad
, 0);
1174 video_set_drvdata(vfd
, vp
);
1175 set_bit(V4L2_FL_USE_FH_PRIO
, &vfd
->flags
);
1177 v4l2_ctrl_handler_init(&vp
->ctrl_handler
, 1);
1178 ctrl
= v4l2_ctrl_new_std(&vp
->ctrl_handler
, &s3c_camif_video_ctrl_ops
,
1179 V4L2_CID_HFLIP
, 0, 1, 1, 0);
1182 ctrl
= v4l2_ctrl_new_std(&vp
->ctrl_handler
, &s3c_camif_video_ctrl_ops
,
1183 V4L2_CID_VFLIP
, 0, 1, 1, 0);
1187 ret
= vp
->ctrl_handler
.error
;
1189 goto err_me_cleanup
;
1191 vfd
->ctrl_handler
= &vp
->ctrl_handler
;
1193 ret
= video_register_device(vfd
, VFL_TYPE_GRABBER
, -1);
1195 goto err_ctrlh_free
;
1197 v4l2_info(&camif
->v4l2_dev
, "registered %s as /dev/%s\n",
1198 vfd
->name
, video_device_node_name(vfd
));
1202 v4l2_ctrl_handler_free(&vp
->ctrl_handler
);
1204 media_entity_cleanup(&vfd
->entity
);
1206 video_device_release(vfd
);
1210 void s3c_camif_unregister_video_node(struct camif_dev
*camif
, int idx
)
1212 struct video_device
*vfd
= &camif
->vp
[idx
].vdev
;
1214 if (video_is_registered(vfd
)) {
1215 video_unregister_device(vfd
);
1216 media_entity_cleanup(&vfd
->entity
);
1217 v4l2_ctrl_handler_free(vfd
->ctrl_handler
);
1221 /* Media bus pixel formats supported at the camif input */
1222 static const enum v4l2_mbus_pixelcode camif_mbus_formats
[] = {
1223 V4L2_MBUS_FMT_YUYV8_2X8
,
1224 V4L2_MBUS_FMT_YVYU8_2X8
,
1225 V4L2_MBUS_FMT_UYVY8_2X8
,
1226 V4L2_MBUS_FMT_VYUY8_2X8
,
1230 * Camera input interface subdev operations
1233 static int s3c_camif_subdev_enum_mbus_code(struct v4l2_subdev
*sd
,
1234 struct v4l2_subdev_fh
*fh
,
1235 struct v4l2_subdev_mbus_code_enum
*code
)
1237 if (code
->index
>= ARRAY_SIZE(camif_mbus_formats
))
1240 code
->code
= camif_mbus_formats
[code
->index
];
1244 static int s3c_camif_subdev_get_fmt(struct v4l2_subdev
*sd
,
1245 struct v4l2_subdev_fh
*fh
,
1246 struct v4l2_subdev_format
*fmt
)
1248 struct camif_dev
*camif
= v4l2_get_subdevdata(sd
);
1249 struct v4l2_mbus_framefmt
*mf
= &fmt
->format
;
1251 if (fmt
->which
== V4L2_SUBDEV_FORMAT_TRY
) {
1252 mf
= v4l2_subdev_get_try_format(fh
, fmt
->pad
);
1257 mutex_lock(&camif
->lock
);
1260 case CAMIF_SD_PAD_SINK
:
1261 /* full camera input pixel size */
1262 *mf
= camif
->mbus_fmt
;
1265 case CAMIF_SD_PAD_SOURCE_C
...CAMIF_SD_PAD_SOURCE_P
:
1266 /* crop rectangle at camera interface input */
1267 mf
->width
= camif
->camif_crop
.width
;
1268 mf
->height
= camif
->camif_crop
.height
;
1269 mf
->code
= camif
->mbus_fmt
.code
;
1273 mutex_unlock(&camif
->lock
);
1274 mf
->colorspace
= V4L2_COLORSPACE_JPEG
;
1278 static void __camif_subdev_try_format(struct camif_dev
*camif
,
1279 struct v4l2_mbus_framefmt
*mf
, int pad
)
1281 const struct s3c_camif_variant
*variant
= camif
->variant
;
1282 const struct vp_pix_limits
*pix_lim
;
1283 int i
= ARRAY_SIZE(camif_mbus_formats
);
1285 /* FIXME: constraints against codec or preview path ? */
1286 pix_lim
= &variant
->vp_pix_limits
[VP_CODEC
];
1289 if (camif_mbus_formats
[i
] == mf
->code
)
1292 mf
->code
= camif_mbus_formats
[i
];
1294 if (pad
== CAMIF_SD_PAD_SINK
) {
1295 v4l_bound_align_image(&mf
->width
, 8, CAMIF_MAX_PIX_WIDTH
,
1296 ffs(pix_lim
->out_width_align
) - 1,
1297 &mf
->height
, 8, CAMIF_MAX_PIX_HEIGHT
, 0,
1300 struct v4l2_rect
*crop
= &camif
->camif_crop
;
1301 v4l_bound_align_image(&mf
->width
, 8, crop
->width
,
1302 ffs(pix_lim
->out_width_align
) - 1,
1303 &mf
->height
, 8, crop
->height
,
1307 v4l2_dbg(1, debug
, &camif
->subdev
, "%ux%u\n", mf
->width
, mf
->height
);
1310 static int s3c_camif_subdev_set_fmt(struct v4l2_subdev
*sd
,
1311 struct v4l2_subdev_fh
*fh
,
1312 struct v4l2_subdev_format
*fmt
)
1314 struct camif_dev
*camif
= v4l2_get_subdevdata(sd
);
1315 struct v4l2_mbus_framefmt
*mf
= &fmt
->format
;
1316 struct v4l2_rect
*crop
= &camif
->camif_crop
;
1319 v4l2_dbg(1, debug
, sd
, "pad%d: code: 0x%x, %ux%u\n",
1320 fmt
->pad
, mf
->code
, mf
->width
, mf
->height
);
1322 mf
->colorspace
= V4L2_COLORSPACE_JPEG
;
1323 mutex_lock(&camif
->lock
);
1326 * No pixel format change at the camera input is allowed
1329 if (vb2_is_busy(&camif
->vp
[VP_CODEC
].vb_queue
) ||
1330 vb2_is_busy(&camif
->vp
[VP_PREVIEW
].vb_queue
)) {
1331 mutex_unlock(&camif
->lock
);
1335 __camif_subdev_try_format(camif
, mf
, fmt
->pad
);
1337 if (fmt
->which
== V4L2_SUBDEV_FORMAT_TRY
) {
1338 mf
= v4l2_subdev_get_try_format(fh
, fmt
->pad
);
1340 mutex_unlock(&camif
->lock
);
1345 case CAMIF_SD_PAD_SINK
:
1346 camif
->mbus_fmt
= *mf
;
1347 /* Reset sink crop rectangle. */
1348 crop
->width
= mf
->width
;
1349 crop
->height
= mf
->height
;
1353 * Reset source format (the camif's crop rectangle)
1354 * and the video output resolution.
1356 for (i
= 0; i
< CAMIF_VP_NUM
; i
++) {
1357 struct camif_frame
*frame
= &camif
->vp
[i
].out_frame
;
1358 frame
->rect
= *crop
;
1359 frame
->f_width
= mf
->width
;
1360 frame
->f_height
= mf
->height
;
1364 case CAMIF_SD_PAD_SOURCE_C
...CAMIF_SD_PAD_SOURCE_P
:
1365 /* Pixel format can be only changed on the sink pad. */
1366 mf
->code
= camif
->mbus_fmt
.code
;
1367 mf
->width
= crop
->width
;
1368 mf
->height
= crop
->height
;
1372 mutex_unlock(&camif
->lock
);
1376 static int s3c_camif_subdev_get_selection(struct v4l2_subdev
*sd
,
1377 struct v4l2_subdev_fh
*fh
,
1378 struct v4l2_subdev_selection
*sel
)
1380 struct camif_dev
*camif
= v4l2_get_subdevdata(sd
);
1381 struct v4l2_rect
*crop
= &camif
->camif_crop
;
1382 struct v4l2_mbus_framefmt
*mf
= &camif
->mbus_fmt
;
1384 if ((sel
->target
!= V4L2_SEL_TGT_CROP
&&
1385 sel
->target
!= V4L2_SEL_TGT_CROP_BOUNDS
) ||
1386 sel
->pad
!= CAMIF_SD_PAD_SINK
)
1389 if (sel
->which
== V4L2_SUBDEV_FORMAT_TRY
) {
1390 sel
->r
= *v4l2_subdev_get_try_crop(fh
, sel
->pad
);
1394 mutex_lock(&camif
->lock
);
1396 if (sel
->target
== V4L2_SEL_TGT_CROP
) {
1398 } else { /* crop bounds */
1399 sel
->r
.width
= mf
->width
;
1400 sel
->r
.height
= mf
->height
;
1405 mutex_unlock(&camif
->lock
);
1407 v4l2_dbg(1, debug
, sd
, "%s: crop: (%d,%d) %dx%d, size: %ux%u\n",
1408 __func__
, crop
->left
, crop
->top
, crop
->width
,
1409 crop
->height
, mf
->width
, mf
->height
);
1414 static void __camif_try_crop(struct camif_dev
*camif
, struct v4l2_rect
*r
)
1416 struct v4l2_mbus_framefmt
*mf
= &camif
->mbus_fmt
;
1417 const struct camif_pix_limits
*pix_lim
= &camif
->variant
->pix_limits
;
1418 unsigned int left
= 2 * r
->left
;
1419 unsigned int top
= 2 * r
->top
;
1422 * Following constraints must be met:
1423 * - r->width + 2 * r->left = mf->width;
1424 * - r->height + 2 * r->top = mf->height;
1425 * - crop rectangle size and position must be aligned
1426 * to 8 or 2 pixels, depending on SoC version.
1428 v4l_bound_align_image(&r
->width
, 0, mf
->width
,
1429 ffs(pix_lim
->win_hor_offset_align
) - 1,
1430 &r
->height
, 0, mf
->height
, 1, 0);
1432 v4l_bound_align_image(&left
, 0, mf
->width
- r
->width
,
1433 ffs(pix_lim
->win_hor_offset_align
),
1434 &top
, 0, mf
->height
- r
->height
, 2, 0);
1438 r
->width
= mf
->width
- left
;
1439 r
->height
= mf
->height
- top
;
1441 * Make sure we either downscale or upscale both the pixel
1442 * width and height. Just return current crop rectangle if
1443 * this scaler constraint is not met.
1445 if (camif
->variant
->ip_revision
== S3C244X_CAMIF_IP_REV
&&
1446 camif_is_streaming(camif
)) {
1449 for (i
= 0; i
< CAMIF_VP_NUM
; i
++) {
1450 struct v4l2_rect
*or = &camif
->vp
[i
].out_frame
.rect
;
1451 if ((or->width
> r
->width
) == (or->height
> r
->height
))
1453 *r
= camif
->camif_crop
;
1454 pr_debug("Width/height scaling direction limitation\n");
1459 v4l2_dbg(1, debug
, &camif
->v4l2_dev
, "crop: (%d,%d)/%dx%d, fmt: %ux%u\n",
1460 r
->left
, r
->top
, r
->width
, r
->height
, mf
->width
, mf
->height
);
1463 static int s3c_camif_subdev_set_selection(struct v4l2_subdev
*sd
,
1464 struct v4l2_subdev_fh
*fh
,
1465 struct v4l2_subdev_selection
*sel
)
1467 struct camif_dev
*camif
= v4l2_get_subdevdata(sd
);
1468 struct v4l2_rect
*crop
= &camif
->camif_crop
;
1469 struct camif_scaler scaler
;
1471 if (sel
->target
!= V4L2_SEL_TGT_CROP
|| sel
->pad
!= CAMIF_SD_PAD_SINK
)
1474 mutex_lock(&camif
->lock
);
1475 __camif_try_crop(camif
, &sel
->r
);
1477 if (sel
->which
== V4L2_SUBDEV_FORMAT_TRY
) {
1478 *v4l2_subdev_get_try_crop(fh
, sel
->pad
) = sel
->r
;
1480 unsigned long flags
;
1483 spin_lock_irqsave(&camif
->slock
, flags
);
1486 for (i
= 0; i
< CAMIF_VP_NUM
; i
++) {
1487 struct camif_vp
*vp
= &camif
->vp
[i
];
1488 scaler
= vp
->scaler
;
1489 if (s3c_camif_get_scaler_config(vp
, &scaler
))
1491 vp
->scaler
= scaler
;
1492 vp
->state
|= ST_VP_CONFIG
;
1495 spin_unlock_irqrestore(&camif
->slock
, flags
);
1497 mutex_unlock(&camif
->lock
);
1499 v4l2_dbg(1, debug
, sd
, "%s: (%d,%d) %dx%d, f_w: %u, f_h: %u\n",
1500 __func__
, crop
->left
, crop
->top
, crop
->width
, crop
->height
,
1501 camif
->mbus_fmt
.width
, camif
->mbus_fmt
.height
);
1506 static const struct v4l2_subdev_pad_ops s3c_camif_subdev_pad_ops
= {
1507 .enum_mbus_code
= s3c_camif_subdev_enum_mbus_code
,
1508 .get_selection
= s3c_camif_subdev_get_selection
,
1509 .set_selection
= s3c_camif_subdev_set_selection
,
1510 .get_fmt
= s3c_camif_subdev_get_fmt
,
1511 .set_fmt
= s3c_camif_subdev_set_fmt
,
1514 static struct v4l2_subdev_ops s3c_camif_subdev_ops
= {
1515 .pad
= &s3c_camif_subdev_pad_ops
,
1518 static int s3c_camif_subdev_s_ctrl(struct v4l2_ctrl
*ctrl
)
1520 struct camif_dev
*camif
= container_of(ctrl
->handler
, struct camif_dev
,
1522 unsigned long flags
;
1524 spin_lock_irqsave(&camif
->slock
, flags
);
1527 case V4L2_CID_COLORFX
:
1528 camif
->colorfx
= camif
->ctrl_colorfx
->val
;
1530 switch (ctrl
->val
) {
1531 case V4L2_COLORFX_SEPIA
:
1532 camif
->colorfx_cb
= 115;
1533 camif
->colorfx_cr
= 145;
1535 case V4L2_COLORFX_SET_CBCR
:
1536 camif
->colorfx_cb
= camif
->ctrl_colorfx_cbcr
->val
>> 8;
1537 camif
->colorfx_cr
= camif
->ctrl_colorfx_cbcr
->val
& 0xff;
1540 /* for V4L2_COLORFX_BW and others */
1541 camif
->colorfx_cb
= 128;
1542 camif
->colorfx_cr
= 128;
1545 case V4L2_CID_TEST_PATTERN
:
1546 camif
->test_pattern
= camif
->ctrl_test_pattern
->val
;
1552 camif
->vp
[VP_CODEC
].state
|= ST_VP_CONFIG
;
1553 camif
->vp
[VP_PREVIEW
].state
|= ST_VP_CONFIG
;
1554 spin_unlock_irqrestore(&camif
->slock
, flags
);
1559 static const struct v4l2_ctrl_ops s3c_camif_subdev_ctrl_ops
= {
1560 .s_ctrl
= s3c_camif_subdev_s_ctrl
,
1563 static const char * const s3c_camif_test_pattern_menu
[] = {
1566 "Horizontal increment",
1567 "Vertical increment",
1570 int s3c_camif_create_subdev(struct camif_dev
*camif
)
1572 struct v4l2_ctrl_handler
*handler
= &camif
->ctrl_handler
;
1573 struct v4l2_subdev
*sd
= &camif
->subdev
;
1576 v4l2_subdev_init(sd
, &s3c_camif_subdev_ops
);
1577 sd
->flags
|= V4L2_SUBDEV_FL_HAS_DEVNODE
;
1578 strlcpy(sd
->name
, "S3C-CAMIF", sizeof(sd
->name
));
1580 camif
->pads
[CAMIF_SD_PAD_SINK
].flags
= MEDIA_PAD_FL_SINK
;
1581 camif
->pads
[CAMIF_SD_PAD_SOURCE_C
].flags
= MEDIA_PAD_FL_SOURCE
;
1582 camif
->pads
[CAMIF_SD_PAD_SOURCE_P
].flags
= MEDIA_PAD_FL_SOURCE
;
1584 ret
= media_entity_init(&sd
->entity
, CAMIF_SD_PADS_NUM
,
1589 v4l2_ctrl_handler_init(handler
, 3);
1590 camif
->ctrl_test_pattern
= v4l2_ctrl_new_std_menu_items(handler
,
1591 &s3c_camif_subdev_ctrl_ops
, V4L2_CID_TEST_PATTERN
,
1592 ARRAY_SIZE(s3c_camif_test_pattern_menu
) - 1, 0, 0,
1593 s3c_camif_test_pattern_menu
);
1595 camif
->ctrl_colorfx
= v4l2_ctrl_new_std_menu(handler
,
1596 &s3c_camif_subdev_ctrl_ops
,
1597 V4L2_CID_COLORFX
, V4L2_COLORFX_SET_CBCR
,
1598 ~0x981f, V4L2_COLORFX_NONE
);
1600 camif
->ctrl_colorfx_cbcr
= v4l2_ctrl_new_std(handler
,
1601 &s3c_camif_subdev_ctrl_ops
,
1602 V4L2_CID_COLORFX_CBCR
, 0, 0xffff, 1, 0);
1603 if (handler
->error
) {
1604 v4l2_ctrl_handler_free(handler
);
1605 media_entity_cleanup(&sd
->entity
);
1606 return handler
->error
;
1609 v4l2_ctrl_auto_cluster(2, &camif
->ctrl_colorfx
,
1610 V4L2_COLORFX_SET_CBCR
, false);
1611 if (!camif
->variant
->has_img_effect
) {
1612 camif
->ctrl_colorfx
->flags
|= V4L2_CTRL_FLAG_DISABLED
;
1613 camif
->ctrl_colorfx_cbcr
->flags
|= V4L2_CTRL_FLAG_DISABLED
;
1615 sd
->ctrl_handler
= handler
;
1616 v4l2_set_subdevdata(sd
, camif
);
1621 void s3c_camif_unregister_subdev(struct camif_dev
*camif
)
1623 struct v4l2_subdev
*sd
= &camif
->subdev
;
1625 /* Return if not registered */
1626 if (v4l2_get_subdevdata(sd
) == NULL
)
1629 v4l2_device_unregister_subdev(sd
);
1630 media_entity_cleanup(&sd
->entity
);
1631 v4l2_ctrl_handler_free(&camif
->ctrl_handler
);
1632 v4l2_set_subdevdata(sd
, NULL
);
1635 int s3c_camif_set_defaults(struct camif_dev
*camif
)
1637 unsigned int ip_rev
= camif
->variant
->ip_revision
;
1640 for (i
= 0; i
< CAMIF_VP_NUM
; i
++) {
1641 struct camif_vp
*vp
= &camif
->vp
[i
];
1642 struct camif_frame
*f
= &vp
->out_frame
;
1646 vp
->offset
= camif
->variant
->vp_offset
;
1648 if (ip_rev
== S3C244X_CAMIF_IP_REV
)
1649 vp
->fmt_flags
= i
? FMT_FL_S3C24XX_PREVIEW
:
1650 FMT_FL_S3C24XX_CODEC
;
1652 vp
->fmt_flags
= FMT_FL_S3C64XX
;
1654 vp
->out_fmt
= s3c_camif_find_format(vp
, NULL
, 0);
1655 BUG_ON(vp
->out_fmt
== NULL
);
1657 memset(f
, 0, sizeof(*f
));
1658 f
->f_width
= CAMIF_DEF_WIDTH
;
1659 f
->f_height
= CAMIF_DEF_HEIGHT
;
1660 f
->rect
.width
= CAMIF_DEF_WIDTH
;
1661 f
->rect
.height
= CAMIF_DEF_HEIGHT
;
1663 /* Scaler is always enabled */
1664 vp
->scaler
.enable
= 1;
1666 vp
->payload
= (f
->f_width
* f
->f_height
*
1667 vp
->out_fmt
->depth
) / 8;
1670 memset(&camif
->mbus_fmt
, 0, sizeof(camif
->mbus_fmt
));
1671 camif
->mbus_fmt
.width
= CAMIF_DEF_WIDTH
;
1672 camif
->mbus_fmt
.height
= CAMIF_DEF_HEIGHT
;
1673 camif
->mbus_fmt
.code
= camif_mbus_formats
[0];
1675 memset(&camif
->camif_crop
, 0, sizeof(camif
->camif_crop
));
1676 camif
->camif_crop
.width
= CAMIF_DEF_WIDTH
;
1677 camif
->camif_crop
.height
= CAMIF_DEF_HEIGHT
;