1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2011 Atmel Corporation
4 * Josh Wu, <josh.wu@atmel.com>
6 * Based on previous work by Lars Haring, <lars.haring@atmel.com>
8 * Based on the bttv driver for Bt848 with respective copyright holders
11 #include <linux/clk.h>
12 #include <linux/completion.h>
13 #include <linux/delay.h>
15 #include <linux/init.h>
16 #include <linux/interrupt.h>
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/of_graph.h>
20 #include <linux/platform_device.h>
21 #include <linux/pm_runtime.h>
22 #include <linux/slab.h>
25 #include <linux/videodev2.h>
26 #include <media/v4l2-ctrls.h>
27 #include <media/v4l2-device.h>
28 #include <media/v4l2-dev.h>
29 #include <media/v4l2-ioctl.h>
30 #include <media/v4l2-event.h>
31 #include <media/v4l2-fwnode.h>
32 #include <media/videobuf2-dma-contig.h>
33 #include <media/v4l2-image-sizes.h>
35 #include "atmel-isi.h"
37 #define MAX_SUPPORT_WIDTH 2048U
38 #define MAX_SUPPORT_HEIGHT 2048U
39 #define MIN_FRAME_RATE 15
40 #define FRAME_INTERVAL_MILLI_SEC (1000 / MIN_FRAME_RATE)
42 /* Frame buffer descriptor */
44 /* Physical address of the frame buffer */
46 /* DMA Control Register(only in HISI2) */
48 /* Physical address of the next fbd */
52 static void set_dma_ctrl(struct fbd
*fb_desc
, u32 ctrl
)
54 fb_desc
->dma_ctrl
= ctrl
;
58 struct list_head list
;
63 /* Frame buffer data */
65 struct vb2_v4l2_buffer vb
;
66 struct isi_dma_desc
*p_dma_desc
;
67 struct list_head list
;
70 struct isi_graph_entity
{
71 struct device_node
*node
;
73 struct v4l2_async_subdev asd
;
74 struct v4l2_subdev
*subdev
;
78 * struct isi_format - ISI media bus format information
79 * @fourcc: Fourcc code for this format
80 * @mbus_code: V4L2 media bus format code.
81 * @bpp: Bytes per pixel (when stored in memory)
82 * @swap: Byte swap configuration value
83 * @support: Indicates format supported by subdev
84 * @skip: Skip duplicate format supported by subdev
95 /* Protects the access of variables shared with the ISR */
102 /* Allocate descriptors for dma buffer use */
103 struct fbd
*p_fb_descriptors
;
104 dma_addr_t fb_descriptors_phys
;
105 struct list_head dma_desc_head
;
106 struct isi_dma_desc dma_desc
[VIDEO_MAX_FRAME
];
107 bool enable_preview_path
;
109 struct completion complete
;
110 /* ISI peripheral clock */
114 struct isi_platform_data pdata
;
115 u16 width_flags
; /* max 12 bits */
117 struct list_head video_buffer_list
;
118 struct frame_buffer
*active
;
120 struct v4l2_device v4l2_dev
;
121 struct video_device
*vdev
;
122 struct v4l2_async_notifier notifier
;
123 struct isi_graph_entity entity
;
124 struct v4l2_format fmt
;
126 const struct isi_format
**user_formats
;
127 unsigned int num_user_formats
;
128 const struct isi_format
*current_fmt
;
131 struct vb2_queue queue
;
134 #define notifier_to_isi(n) container_of(n, struct atmel_isi, notifier)
136 static void isi_writel(struct atmel_isi
*isi
, u32 reg
, u32 val
)
138 writel(val
, isi
->regs
+ reg
);
140 static u32
isi_readl(struct atmel_isi
*isi
, u32 reg
)
142 return readl(isi
->regs
+ reg
);
145 static void configure_geometry(struct atmel_isi
*isi
)
148 u32 fourcc
= isi
->current_fmt
->fourcc
;
150 isi
->enable_preview_path
= fourcc
== V4L2_PIX_FMT_RGB565
||
151 fourcc
== V4L2_PIX_FMT_RGB32
||
152 fourcc
== V4L2_PIX_FMT_Y16
;
154 /* According to sensor's output format to set cfg2 */
155 cfg2
= isi
->current_fmt
->swap
;
157 isi_writel(isi
, ISI_CTRL
, ISI_CTRL_DIS
);
159 cfg2
|= ((isi
->fmt
.fmt
.pix
.width
- 1) << ISI_CFG2_IM_HSIZE_OFFSET
) &
160 ISI_CFG2_IM_HSIZE_MASK
;
162 cfg2
|= ((isi
->fmt
.fmt
.pix
.height
- 1) << ISI_CFG2_IM_VSIZE_OFFSET
)
163 & ISI_CFG2_IM_VSIZE_MASK
;
164 isi_writel(isi
, ISI_CFG2
, cfg2
);
166 /* No down sampling, preview size equal to sensor output size */
167 psize
= ((isi
->fmt
.fmt
.pix
.width
- 1) << ISI_PSIZE_PREV_HSIZE_OFFSET
) &
168 ISI_PSIZE_PREV_HSIZE_MASK
;
169 psize
|= ((isi
->fmt
.fmt
.pix
.height
- 1) << ISI_PSIZE_PREV_VSIZE_OFFSET
) &
170 ISI_PSIZE_PREV_VSIZE_MASK
;
171 isi_writel(isi
, ISI_PSIZE
, psize
);
172 isi_writel(isi
, ISI_PDECF
, ISI_PDECF_NO_SAMPLING
);
175 static irqreturn_t
atmel_isi_handle_streaming(struct atmel_isi
*isi
)
178 struct vb2_v4l2_buffer
*vbuf
= &isi
->active
->vb
;
179 struct frame_buffer
*buf
= isi
->active
;
181 list_del_init(&buf
->list
);
182 vbuf
->vb2_buf
.timestamp
= ktime_get_ns();
183 vbuf
->sequence
= isi
->sequence
++;
184 vbuf
->field
= V4L2_FIELD_NONE
;
185 vb2_buffer_done(&vbuf
->vb2_buf
, VB2_BUF_STATE_DONE
);
188 if (list_empty(&isi
->video_buffer_list
)) {
191 /* start next dma frame. */
192 isi
->active
= list_entry(isi
->video_buffer_list
.next
,
193 struct frame_buffer
, list
);
194 if (!isi
->enable_preview_path
) {
195 isi_writel(isi
, ISI_DMA_C_DSCR
,
196 (u32
)isi
->active
->p_dma_desc
->fbd_phys
);
197 isi_writel(isi
, ISI_DMA_C_CTRL
,
198 ISI_DMA_CTRL_FETCH
| ISI_DMA_CTRL_DONE
);
199 isi_writel(isi
, ISI_DMA_CHER
, ISI_DMA_CHSR_C_CH
);
201 isi_writel(isi
, ISI_DMA_P_DSCR
,
202 (u32
)isi
->active
->p_dma_desc
->fbd_phys
);
203 isi_writel(isi
, ISI_DMA_P_CTRL
,
204 ISI_DMA_CTRL_FETCH
| ISI_DMA_CTRL_DONE
);
205 isi_writel(isi
, ISI_DMA_CHER
, ISI_DMA_CHSR_P_CH
);
211 /* ISI interrupt service routine */
212 static irqreturn_t
isi_interrupt(int irq
, void *dev_id
)
214 struct atmel_isi
*isi
= dev_id
;
215 u32 status
, mask
, pending
;
216 irqreturn_t ret
= IRQ_NONE
;
218 spin_lock(&isi
->irqlock
);
220 status
= isi_readl(isi
, ISI_STATUS
);
221 mask
= isi_readl(isi
, ISI_INTMASK
);
222 pending
= status
& mask
;
224 if (pending
& ISI_CTRL_SRST
) {
225 complete(&isi
->complete
);
226 isi_writel(isi
, ISI_INTDIS
, ISI_CTRL_SRST
);
228 } else if (pending
& ISI_CTRL_DIS
) {
229 complete(&isi
->complete
);
230 isi_writel(isi
, ISI_INTDIS
, ISI_CTRL_DIS
);
233 if (likely(pending
& ISI_SR_CXFR_DONE
) ||
234 likely(pending
& ISI_SR_PXFR_DONE
))
235 ret
= atmel_isi_handle_streaming(isi
);
238 spin_unlock(&isi
->irqlock
);
242 #define WAIT_ISI_RESET 1
243 #define WAIT_ISI_DISABLE 0
244 static int atmel_isi_wait_status(struct atmel_isi
*isi
, int wait_reset
)
246 unsigned long timeout
;
248 * The reset or disable will only succeed if we have a
249 * pixel clock from the camera.
251 init_completion(&isi
->complete
);
254 isi_writel(isi
, ISI_INTEN
, ISI_CTRL_SRST
);
255 isi_writel(isi
, ISI_CTRL
, ISI_CTRL_SRST
);
257 isi_writel(isi
, ISI_INTEN
, ISI_CTRL_DIS
);
258 isi_writel(isi
, ISI_CTRL
, ISI_CTRL_DIS
);
261 timeout
= wait_for_completion_timeout(&isi
->complete
,
262 msecs_to_jiffies(500));
269 /* ------------------------------------------------------------------
271 ------------------------------------------------------------------*/
272 static int queue_setup(struct vb2_queue
*vq
,
273 unsigned int *nbuffers
, unsigned int *nplanes
,
274 unsigned int sizes
[], struct device
*alloc_devs
[])
276 struct atmel_isi
*isi
= vb2_get_drv_priv(vq
);
279 size
= isi
->fmt
.fmt
.pix
.sizeimage
;
281 /* Make sure the image size is large enough. */
283 return sizes
[0] < size
? -EINVAL
: 0;
290 dev_dbg(isi
->dev
, "%s, count=%d, size=%ld\n", __func__
,
296 static int buffer_init(struct vb2_buffer
*vb
)
298 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
299 struct frame_buffer
*buf
= container_of(vbuf
, struct frame_buffer
, vb
);
301 buf
->p_dma_desc
= NULL
;
302 INIT_LIST_HEAD(&buf
->list
);
307 static int buffer_prepare(struct vb2_buffer
*vb
)
309 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
310 struct frame_buffer
*buf
= container_of(vbuf
, struct frame_buffer
, vb
);
311 struct atmel_isi
*isi
= vb2_get_drv_priv(vb
->vb2_queue
);
313 struct isi_dma_desc
*desc
;
315 size
= isi
->fmt
.fmt
.pix
.sizeimage
;
317 if (vb2_plane_size(vb
, 0) < size
) {
318 dev_err(isi
->dev
, "%s data will not fit into plane (%lu < %lu)\n",
319 __func__
, vb2_plane_size(vb
, 0), size
);
323 vb2_set_plane_payload(vb
, 0, size
);
325 if (!buf
->p_dma_desc
) {
326 if (list_empty(&isi
->dma_desc_head
)) {
327 dev_err(isi
->dev
, "Not enough dma descriptors.\n");
330 /* Get an available descriptor */
331 desc
= list_entry(isi
->dma_desc_head
.next
,
332 struct isi_dma_desc
, list
);
333 /* Delete the descriptor since now it is used */
334 list_del_init(&desc
->list
);
336 /* Initialize the dma descriptor */
337 desc
->p_fbd
->fb_address
=
338 vb2_dma_contig_plane_dma_addr(vb
, 0);
339 desc
->p_fbd
->next_fbd_address
= 0;
340 set_dma_ctrl(desc
->p_fbd
, ISI_DMA_CTRL_WB
);
342 buf
->p_dma_desc
= desc
;
348 static void buffer_cleanup(struct vb2_buffer
*vb
)
350 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
351 struct atmel_isi
*isi
= vb2_get_drv_priv(vb
->vb2_queue
);
352 struct frame_buffer
*buf
= container_of(vbuf
, struct frame_buffer
, vb
);
354 /* This descriptor is available now and we add to head list */
356 list_add(&buf
->p_dma_desc
->list
, &isi
->dma_desc_head
);
359 static void start_dma(struct atmel_isi
*isi
, struct frame_buffer
*buffer
)
363 cfg1
= isi_readl(isi
, ISI_CFG1
);
364 /* Enable irq: cxfr for the codec path, pxfr for the preview path */
365 isi_writel(isi
, ISI_INTEN
,
366 ISI_SR_CXFR_DONE
| ISI_SR_PXFR_DONE
);
368 /* Check if already in a frame */
369 if (!isi
->enable_preview_path
) {
370 if (isi_readl(isi
, ISI_STATUS
) & ISI_CTRL_CDC
) {
371 dev_err(isi
->dev
, "Already in frame handling.\n");
375 isi_writel(isi
, ISI_DMA_C_DSCR
,
376 (u32
)buffer
->p_dma_desc
->fbd_phys
);
377 isi_writel(isi
, ISI_DMA_C_CTRL
,
378 ISI_DMA_CTRL_FETCH
| ISI_DMA_CTRL_DONE
);
379 isi_writel(isi
, ISI_DMA_CHER
, ISI_DMA_CHSR_C_CH
);
381 isi_writel(isi
, ISI_DMA_P_DSCR
,
382 (u32
)buffer
->p_dma_desc
->fbd_phys
);
383 isi_writel(isi
, ISI_DMA_P_CTRL
,
384 ISI_DMA_CTRL_FETCH
| ISI_DMA_CTRL_DONE
);
385 isi_writel(isi
, ISI_DMA_CHER
, ISI_DMA_CHSR_P_CH
);
388 cfg1
&= ~ISI_CFG1_FRATE_DIV_MASK
;
389 /* Enable linked list */
390 cfg1
|= isi
->pdata
.frate
| ISI_CFG1_DISCR
;
395 if (!isi
->enable_preview_path
)
396 ctrl
|= ISI_CTRL_CDC
;
398 isi_writel(isi
, ISI_CTRL
, ctrl
);
399 isi_writel(isi
, ISI_CFG1
, cfg1
);
402 static void buffer_queue(struct vb2_buffer
*vb
)
404 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
405 struct atmel_isi
*isi
= vb2_get_drv_priv(vb
->vb2_queue
);
406 struct frame_buffer
*buf
= container_of(vbuf
, struct frame_buffer
, vb
);
407 unsigned long flags
= 0;
409 spin_lock_irqsave(&isi
->irqlock
, flags
);
410 list_add_tail(&buf
->list
, &isi
->video_buffer_list
);
414 if (vb2_is_streaming(vb
->vb2_queue
))
417 spin_unlock_irqrestore(&isi
->irqlock
, flags
);
420 static int start_streaming(struct vb2_queue
*vq
, unsigned int count
)
422 struct atmel_isi
*isi
= vb2_get_drv_priv(vq
);
423 struct frame_buffer
*buf
, *node
;
426 pm_runtime_get_sync(isi
->dev
);
428 /* Enable stream on the sub device */
429 ret
= v4l2_subdev_call(isi
->entity
.subdev
, video
, s_stream
, 1);
430 if (ret
&& ret
!= -ENOIOCTLCMD
) {
431 dev_err(isi
->dev
, "stream on failed in subdev\n");
432 goto err_start_stream
;
436 ret
= atmel_isi_wait_status(isi
, WAIT_ISI_RESET
);
438 dev_err(isi
->dev
, "Reset ISI timed out\n");
441 /* Disable all interrupts */
442 isi_writel(isi
, ISI_INTDIS
, (u32
)~0UL);
445 configure_geometry(isi
);
447 spin_lock_irq(&isi
->irqlock
);
448 /* Clear any pending interrupt */
449 isi_readl(isi
, ISI_STATUS
);
451 start_dma(isi
, isi
->active
);
452 spin_unlock_irq(&isi
->irqlock
);
457 v4l2_subdev_call(isi
->entity
.subdev
, video
, s_stream
, 0);
460 pm_runtime_put(isi
->dev
);
462 spin_lock_irq(&isi
->irqlock
);
464 /* Release all active buffers */
465 list_for_each_entry_safe(buf
, node
, &isi
->video_buffer_list
, list
) {
466 list_del_init(&buf
->list
);
467 vb2_buffer_done(&buf
->vb
.vb2_buf
, VB2_BUF_STATE_QUEUED
);
469 spin_unlock_irq(&isi
->irqlock
);
474 /* abort streaming and wait for last buffer */
475 static void stop_streaming(struct vb2_queue
*vq
)
477 struct atmel_isi
*isi
= vb2_get_drv_priv(vq
);
478 struct frame_buffer
*buf
, *node
;
480 unsigned long timeout
;
482 /* Disable stream on the sub device */
483 ret
= v4l2_subdev_call(isi
->entity
.subdev
, video
, s_stream
, 0);
484 if (ret
&& ret
!= -ENOIOCTLCMD
)
485 dev_err(isi
->dev
, "stream off failed in subdev\n");
487 spin_lock_irq(&isi
->irqlock
);
489 /* Release all active buffers */
490 list_for_each_entry_safe(buf
, node
, &isi
->video_buffer_list
, list
) {
491 list_del_init(&buf
->list
);
492 vb2_buffer_done(&buf
->vb
.vb2_buf
, VB2_BUF_STATE_ERROR
);
494 spin_unlock_irq(&isi
->irqlock
);
496 if (!isi
->enable_preview_path
) {
497 timeout
= jiffies
+ (FRAME_INTERVAL_MILLI_SEC
* HZ
) / 1000;
498 /* Wait until the end of the current frame. */
499 while ((isi_readl(isi
, ISI_STATUS
) & ISI_CTRL_CDC
) &&
500 time_before(jiffies
, timeout
))
503 if (time_after(jiffies
, timeout
))
505 "Timeout waiting for finishing codec request\n");
508 /* Disable interrupts */
509 isi_writel(isi
, ISI_INTDIS
,
510 ISI_SR_CXFR_DONE
| ISI_SR_PXFR_DONE
);
512 /* Disable ISI and wait for it is done */
513 ret
= atmel_isi_wait_status(isi
, WAIT_ISI_DISABLE
);
515 dev_err(isi
->dev
, "Disable ISI timed out\n");
517 pm_runtime_put(isi
->dev
);
520 static const struct vb2_ops isi_video_qops
= {
521 .queue_setup
= queue_setup
,
522 .buf_init
= buffer_init
,
523 .buf_prepare
= buffer_prepare
,
524 .buf_cleanup
= buffer_cleanup
,
525 .buf_queue
= buffer_queue
,
526 .start_streaming
= start_streaming
,
527 .stop_streaming
= stop_streaming
,
528 .wait_prepare
= vb2_ops_wait_prepare
,
529 .wait_finish
= vb2_ops_wait_finish
,
532 static int isi_g_fmt_vid_cap(struct file
*file
, void *priv
,
533 struct v4l2_format
*fmt
)
535 struct atmel_isi
*isi
= video_drvdata(file
);
542 static const struct isi_format
*find_format_by_fourcc(struct atmel_isi
*isi
,
545 unsigned int num_formats
= isi
->num_user_formats
;
546 const struct isi_format
*fmt
;
549 for (i
= 0; i
< num_formats
; i
++) {
550 fmt
= isi
->user_formats
[i
];
551 if (fmt
->fourcc
== fourcc
)
558 static void isi_try_fse(struct atmel_isi
*isi
, const struct isi_format
*isi_fmt
,
559 struct v4l2_subdev_pad_config
*pad_cfg
)
562 struct v4l2_subdev_frame_size_enum fse
= {
563 .code
= isi_fmt
->mbus_code
,
564 .which
= V4L2_SUBDEV_FORMAT_TRY
,
567 ret
= v4l2_subdev_call(isi
->entity
.subdev
, pad
, enum_frame_size
,
570 * Attempt to obtain format size from subdev. If not available,
571 * just use the maximum ISI can receive.
574 pad_cfg
->try_crop
.width
= MAX_SUPPORT_WIDTH
;
575 pad_cfg
->try_crop
.height
= MAX_SUPPORT_HEIGHT
;
577 pad_cfg
->try_crop
.width
= fse
.max_width
;
578 pad_cfg
->try_crop
.height
= fse
.max_height
;
582 static int isi_try_fmt(struct atmel_isi
*isi
, struct v4l2_format
*f
,
583 const struct isi_format
**current_fmt
)
585 const struct isi_format
*isi_fmt
;
586 struct v4l2_pix_format
*pixfmt
= &f
->fmt
.pix
;
587 struct v4l2_subdev_pad_config pad_cfg
= {};
588 struct v4l2_subdev_format format
= {
589 .which
= V4L2_SUBDEV_FORMAT_TRY
,
593 isi_fmt
= find_format_by_fourcc(isi
, pixfmt
->pixelformat
);
595 isi_fmt
= isi
->user_formats
[isi
->num_user_formats
- 1];
596 pixfmt
->pixelformat
= isi_fmt
->fourcc
;
599 /* Limit to Atmel ISI hardware capabilities */
600 pixfmt
->width
= clamp(pixfmt
->width
, 0U, MAX_SUPPORT_WIDTH
);
601 pixfmt
->height
= clamp(pixfmt
->height
, 0U, MAX_SUPPORT_HEIGHT
);
603 v4l2_fill_mbus_format(&format
.format
, pixfmt
, isi_fmt
->mbus_code
);
605 isi_try_fse(isi
, isi_fmt
, &pad_cfg
);
607 ret
= v4l2_subdev_call(isi
->entity
.subdev
, pad
, set_fmt
,
612 v4l2_fill_pix_format(pixfmt
, &format
.format
);
614 pixfmt
->field
= V4L2_FIELD_NONE
;
615 pixfmt
->bytesperline
= pixfmt
->width
* isi_fmt
->bpp
;
616 pixfmt
->sizeimage
= pixfmt
->bytesperline
* pixfmt
->height
;
619 *current_fmt
= isi_fmt
;
624 static int isi_set_fmt(struct atmel_isi
*isi
, struct v4l2_format
*f
)
626 struct v4l2_subdev_format format
= {
627 .which
= V4L2_SUBDEV_FORMAT_ACTIVE
,
629 const struct isi_format
*current_fmt
;
632 ret
= isi_try_fmt(isi
, f
, ¤t_fmt
);
636 v4l2_fill_mbus_format(&format
.format
, &f
->fmt
.pix
,
637 current_fmt
->mbus_code
);
638 ret
= v4l2_subdev_call(isi
->entity
.subdev
, pad
,
639 set_fmt
, NULL
, &format
);
644 isi
->current_fmt
= current_fmt
;
649 static int isi_s_fmt_vid_cap(struct file
*file
, void *priv
,
650 struct v4l2_format
*f
)
652 struct atmel_isi
*isi
= video_drvdata(file
);
654 if (vb2_is_streaming(&isi
->queue
))
657 return isi_set_fmt(isi
, f
);
660 static int isi_try_fmt_vid_cap(struct file
*file
, void *priv
,
661 struct v4l2_format
*f
)
663 struct atmel_isi
*isi
= video_drvdata(file
);
665 return isi_try_fmt(isi
, f
, NULL
);
668 static int isi_enum_fmt_vid_cap(struct file
*file
, void *priv
,
669 struct v4l2_fmtdesc
*f
)
671 struct atmel_isi
*isi
= video_drvdata(file
);
673 if (f
->index
>= isi
->num_user_formats
)
676 f
->pixelformat
= isi
->user_formats
[f
->index
]->fourcc
;
680 static int isi_querycap(struct file
*file
, void *priv
,
681 struct v4l2_capability
*cap
)
683 strscpy(cap
->driver
, "atmel-isi", sizeof(cap
->driver
));
684 strscpy(cap
->card
, "Atmel Image Sensor Interface", sizeof(cap
->card
));
685 strscpy(cap
->bus_info
, "platform:isi", sizeof(cap
->bus_info
));
689 static int isi_enum_input(struct file
*file
, void *priv
,
690 struct v4l2_input
*i
)
695 i
->type
= V4L2_INPUT_TYPE_CAMERA
;
696 strscpy(i
->name
, "Camera", sizeof(i
->name
));
700 static int isi_g_input(struct file
*file
, void *priv
, unsigned int *i
)
706 static int isi_s_input(struct file
*file
, void *priv
, unsigned int i
)
713 static int isi_g_parm(struct file
*file
, void *fh
, struct v4l2_streamparm
*a
)
715 struct atmel_isi
*isi
= video_drvdata(file
);
717 return v4l2_g_parm_cap(video_devdata(file
), isi
->entity
.subdev
, a
);
720 static int isi_s_parm(struct file
*file
, void *fh
, struct v4l2_streamparm
*a
)
722 struct atmel_isi
*isi
= video_drvdata(file
);
724 return v4l2_s_parm_cap(video_devdata(file
), isi
->entity
.subdev
, a
);
727 static int isi_enum_framesizes(struct file
*file
, void *fh
,
728 struct v4l2_frmsizeenum
*fsize
)
730 struct atmel_isi
*isi
= video_drvdata(file
);
731 const struct isi_format
*isi_fmt
;
732 struct v4l2_subdev_frame_size_enum fse
= {
733 .index
= fsize
->index
,
734 .which
= V4L2_SUBDEV_FORMAT_ACTIVE
,
738 isi_fmt
= find_format_by_fourcc(isi
, fsize
->pixel_format
);
742 fse
.code
= isi_fmt
->mbus_code
;
744 ret
= v4l2_subdev_call(isi
->entity
.subdev
, pad
, enum_frame_size
,
749 fsize
->type
= V4L2_FRMSIZE_TYPE_DISCRETE
;
750 fsize
->discrete
.width
= fse
.max_width
;
751 fsize
->discrete
.height
= fse
.max_height
;
756 static int isi_enum_frameintervals(struct file
*file
, void *fh
,
757 struct v4l2_frmivalenum
*fival
)
759 struct atmel_isi
*isi
= video_drvdata(file
);
760 const struct isi_format
*isi_fmt
;
761 struct v4l2_subdev_frame_interval_enum fie
= {
762 .index
= fival
->index
,
763 .width
= fival
->width
,
764 .height
= fival
->height
,
765 .which
= V4L2_SUBDEV_FORMAT_ACTIVE
,
769 isi_fmt
= find_format_by_fourcc(isi
, fival
->pixel_format
);
773 fie
.code
= isi_fmt
->mbus_code
;
775 ret
= v4l2_subdev_call(isi
->entity
.subdev
, pad
,
776 enum_frame_interval
, NULL
, &fie
);
780 fival
->type
= V4L2_FRMIVAL_TYPE_DISCRETE
;
781 fival
->discrete
= fie
.interval
;
786 static void isi_camera_set_bus_param(struct atmel_isi
*isi
)
790 /* set bus param for ISI */
791 if (isi
->pdata
.hsync_act_low
)
792 cfg1
|= ISI_CFG1_HSYNC_POL_ACTIVE_LOW
;
793 if (isi
->pdata
.vsync_act_low
)
794 cfg1
|= ISI_CFG1_VSYNC_POL_ACTIVE_LOW
;
795 if (isi
->pdata
.pclk_act_falling
)
796 cfg1
|= ISI_CFG1_PIXCLK_POL_ACTIVE_FALLING
;
797 if (isi
->pdata
.has_emb_sync
)
798 cfg1
|= ISI_CFG1_EMB_SYNC
;
799 if (isi
->pdata
.full_mode
)
800 cfg1
|= ISI_CFG1_FULL_MODE
;
802 cfg1
|= ISI_CFG1_THMASK_BEATS_16
;
804 /* Enable PM and peripheral clock before operate isi registers */
805 pm_runtime_get_sync(isi
->dev
);
807 isi_writel(isi
, ISI_CTRL
, ISI_CTRL_DIS
);
808 isi_writel(isi
, ISI_CFG1
, cfg1
);
810 pm_runtime_put(isi
->dev
);
813 /* -----------------------------------------------------------------------*/
814 static int atmel_isi_parse_dt(struct atmel_isi
*isi
,
815 struct platform_device
*pdev
)
817 struct device_node
*np
= pdev
->dev
.of_node
;
818 struct v4l2_fwnode_endpoint ep
= { .bus_type
= 0 };
821 /* Default settings for ISI */
822 isi
->pdata
.full_mode
= 1;
823 isi
->pdata
.frate
= ISI_CFG1_FRATE_CAPTURE_ALL
;
825 np
= of_graph_get_next_endpoint(np
, NULL
);
827 dev_err(&pdev
->dev
, "Could not find the endpoint\n");
831 err
= v4l2_fwnode_endpoint_parse(of_fwnode_handle(np
), &ep
);
834 dev_err(&pdev
->dev
, "Could not parse the endpoint\n");
838 switch (ep
.bus
.parallel
.bus_width
) {
840 isi
->pdata
.data_width_flags
= ISI_DATAWIDTH_8
;
843 isi
->pdata
.data_width_flags
=
844 ISI_DATAWIDTH_8
| ISI_DATAWIDTH_10
;
847 dev_err(&pdev
->dev
, "Unsupported bus width: %d\n",
848 ep
.bus
.parallel
.bus_width
);
852 if (ep
.bus
.parallel
.flags
& V4L2_MBUS_HSYNC_ACTIVE_LOW
)
853 isi
->pdata
.hsync_act_low
= true;
854 if (ep
.bus
.parallel
.flags
& V4L2_MBUS_VSYNC_ACTIVE_LOW
)
855 isi
->pdata
.vsync_act_low
= true;
856 if (ep
.bus
.parallel
.flags
& V4L2_MBUS_PCLK_SAMPLE_FALLING
)
857 isi
->pdata
.pclk_act_falling
= true;
859 if (ep
.bus_type
== V4L2_MBUS_BT656
)
860 isi
->pdata
.has_emb_sync
= true;
865 static int isi_open(struct file
*file
)
867 struct atmel_isi
*isi
= video_drvdata(file
);
868 struct v4l2_subdev
*sd
= isi
->entity
.subdev
;
871 if (mutex_lock_interruptible(&isi
->lock
))
874 ret
= v4l2_fh_open(file
);
878 if (!v4l2_fh_is_singular_file(file
))
881 ret
= v4l2_subdev_call(sd
, core
, s_power
, 1);
882 if (ret
< 0 && ret
!= -ENOIOCTLCMD
)
885 ret
= isi_set_fmt(isi
, &isi
->fmt
);
887 v4l2_subdev_call(sd
, core
, s_power
, 0);
890 v4l2_fh_release(file
);
892 mutex_unlock(&isi
->lock
);
896 static int isi_release(struct file
*file
)
898 struct atmel_isi
*isi
= video_drvdata(file
);
899 struct v4l2_subdev
*sd
= isi
->entity
.subdev
;
903 mutex_lock(&isi
->lock
);
905 fh_singular
= v4l2_fh_is_singular_file(file
);
907 ret
= _vb2_fop_release(file
, NULL
);
910 v4l2_subdev_call(sd
, core
, s_power
, 0);
912 mutex_unlock(&isi
->lock
);
917 static const struct v4l2_ioctl_ops isi_ioctl_ops
= {
918 .vidioc_querycap
= isi_querycap
,
920 .vidioc_try_fmt_vid_cap
= isi_try_fmt_vid_cap
,
921 .vidioc_g_fmt_vid_cap
= isi_g_fmt_vid_cap
,
922 .vidioc_s_fmt_vid_cap
= isi_s_fmt_vid_cap
,
923 .vidioc_enum_fmt_vid_cap
= isi_enum_fmt_vid_cap
,
925 .vidioc_enum_input
= isi_enum_input
,
926 .vidioc_g_input
= isi_g_input
,
927 .vidioc_s_input
= isi_s_input
,
929 .vidioc_g_parm
= isi_g_parm
,
930 .vidioc_s_parm
= isi_s_parm
,
931 .vidioc_enum_framesizes
= isi_enum_framesizes
,
932 .vidioc_enum_frameintervals
= isi_enum_frameintervals
,
934 .vidioc_reqbufs
= vb2_ioctl_reqbufs
,
935 .vidioc_create_bufs
= vb2_ioctl_create_bufs
,
936 .vidioc_querybuf
= vb2_ioctl_querybuf
,
937 .vidioc_qbuf
= vb2_ioctl_qbuf
,
938 .vidioc_dqbuf
= vb2_ioctl_dqbuf
,
939 .vidioc_expbuf
= vb2_ioctl_expbuf
,
940 .vidioc_prepare_buf
= vb2_ioctl_prepare_buf
,
941 .vidioc_streamon
= vb2_ioctl_streamon
,
942 .vidioc_streamoff
= vb2_ioctl_streamoff
,
944 .vidioc_log_status
= v4l2_ctrl_log_status
,
945 .vidioc_subscribe_event
= v4l2_ctrl_subscribe_event
,
946 .vidioc_unsubscribe_event
= v4l2_event_unsubscribe
,
949 static const struct v4l2_file_operations isi_fops
= {
950 .owner
= THIS_MODULE
,
951 .unlocked_ioctl
= video_ioctl2
,
953 .release
= isi_release
,
954 .poll
= vb2_fop_poll
,
955 .mmap
= vb2_fop_mmap
,
956 .read
= vb2_fop_read
,
959 static int isi_set_default_fmt(struct atmel_isi
*isi
)
961 struct v4l2_format f
= {
962 .type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
,
965 .height
= VGA_HEIGHT
,
966 .field
= V4L2_FIELD_NONE
,
967 .pixelformat
= isi
->user_formats
[0]->fourcc
,
972 ret
= isi_try_fmt(isi
, &f
, NULL
);
975 isi
->current_fmt
= isi
->user_formats
[0];
980 static const struct isi_format isi_formats
[] = {
982 .fourcc
= V4L2_PIX_FMT_YUYV
,
983 .mbus_code
= MEDIA_BUS_FMT_YUYV8_2X8
,
985 .swap
= ISI_CFG2_YCC_SWAP_DEFAULT
,
987 .fourcc
= V4L2_PIX_FMT_YUYV
,
988 .mbus_code
= MEDIA_BUS_FMT_YVYU8_2X8
,
990 .swap
= ISI_CFG2_YCC_SWAP_MODE_1
,
992 .fourcc
= V4L2_PIX_FMT_YUYV
,
993 .mbus_code
= MEDIA_BUS_FMT_UYVY8_2X8
,
995 .swap
= ISI_CFG2_YCC_SWAP_MODE_2
,
997 .fourcc
= V4L2_PIX_FMT_YUYV
,
998 .mbus_code
= MEDIA_BUS_FMT_VYUY8_2X8
,
1000 .swap
= ISI_CFG2_YCC_SWAP_MODE_3
,
1002 .fourcc
= V4L2_PIX_FMT_RGB565
,
1003 .mbus_code
= MEDIA_BUS_FMT_YUYV8_2X8
,
1005 .swap
= ISI_CFG2_YCC_SWAP_MODE_2
,
1007 .fourcc
= V4L2_PIX_FMT_RGB565
,
1008 .mbus_code
= MEDIA_BUS_FMT_YVYU8_2X8
,
1010 .swap
= ISI_CFG2_YCC_SWAP_MODE_3
,
1012 .fourcc
= V4L2_PIX_FMT_RGB565
,
1013 .mbus_code
= MEDIA_BUS_FMT_UYVY8_2X8
,
1015 .swap
= ISI_CFG2_YCC_SWAP_DEFAULT
,
1017 .fourcc
= V4L2_PIX_FMT_RGB565
,
1018 .mbus_code
= MEDIA_BUS_FMT_VYUY8_2X8
,
1020 .swap
= ISI_CFG2_YCC_SWAP_MODE_1
,
1022 .fourcc
= V4L2_PIX_FMT_GREY
,
1023 .mbus_code
= MEDIA_BUS_FMT_Y10_1X10
,
1025 .swap
= ISI_CFG2_GS_MODE_2_PIXEL
| ISI_CFG2_GRAYSCALE
,
1027 .fourcc
= V4L2_PIX_FMT_Y16
,
1028 .mbus_code
= MEDIA_BUS_FMT_Y10_1X10
,
1030 .swap
= ISI_CFG2_GS_MODE_2_PIXEL
| ISI_CFG2_GRAYSCALE
,
1034 static int isi_formats_init(struct atmel_isi
*isi
)
1036 const struct isi_format
*isi_fmts
[ARRAY_SIZE(isi_formats
)];
1037 unsigned int num_fmts
= 0, i
, j
;
1038 struct v4l2_subdev
*subdev
= isi
->entity
.subdev
;
1039 struct v4l2_subdev_mbus_code_enum mbus_code
= {
1040 .which
= V4L2_SUBDEV_FORMAT_ACTIVE
,
1043 while (!v4l2_subdev_call(subdev
, pad
, enum_mbus_code
,
1044 NULL
, &mbus_code
)) {
1045 for (i
= 0; i
< ARRAY_SIZE(isi_formats
); i
++) {
1046 if (isi_formats
[i
].mbus_code
!= mbus_code
.code
)
1049 /* Code supported, have we got this fourcc yet? */
1050 for (j
= 0; j
< num_fmts
; j
++)
1051 if (isi_fmts
[j
]->fourcc
== isi_formats
[i
].fourcc
)
1052 /* Already available */
1056 isi_fmts
[num_fmts
++] = isi_formats
+ i
;
1064 isi
->num_user_formats
= num_fmts
;
1065 isi
->user_formats
= devm_kcalloc(isi
->dev
,
1066 num_fmts
, sizeof(struct isi_format
*),
1068 if (!isi
->user_formats
)
1071 memcpy(isi
->user_formats
, isi_fmts
,
1072 num_fmts
* sizeof(struct isi_format
*));
1073 isi
->current_fmt
= isi
->user_formats
[0];
1078 static int isi_graph_notify_complete(struct v4l2_async_notifier
*notifier
)
1080 struct atmel_isi
*isi
= notifier_to_isi(notifier
);
1083 isi
->vdev
->ctrl_handler
= isi
->entity
.subdev
->ctrl_handler
;
1084 ret
= isi_formats_init(isi
);
1086 dev_err(isi
->dev
, "No supported mediabus format found\n");
1089 isi_camera_set_bus_param(isi
);
1091 ret
= isi_set_default_fmt(isi
);
1093 dev_err(isi
->dev
, "Could not set default format\n");
1097 ret
= video_register_device(isi
->vdev
, VFL_TYPE_VIDEO
, -1);
1099 dev_err(isi
->dev
, "Failed to register video device\n");
1103 dev_dbg(isi
->dev
, "Device registered as %s\n",
1104 video_device_node_name(isi
->vdev
));
1108 static void isi_graph_notify_unbind(struct v4l2_async_notifier
*notifier
,
1109 struct v4l2_subdev
*sd
,
1110 struct v4l2_async_subdev
*asd
)
1112 struct atmel_isi
*isi
= notifier_to_isi(notifier
);
1114 dev_dbg(isi
->dev
, "Removing %s\n", video_device_node_name(isi
->vdev
));
1116 /* Checks internally if vdev have been init or not */
1117 video_unregister_device(isi
->vdev
);
1120 static int isi_graph_notify_bound(struct v4l2_async_notifier
*notifier
,
1121 struct v4l2_subdev
*subdev
,
1122 struct v4l2_async_subdev
*asd
)
1124 struct atmel_isi
*isi
= notifier_to_isi(notifier
);
1126 dev_dbg(isi
->dev
, "subdev %s bound\n", subdev
->name
);
1128 isi
->entity
.subdev
= subdev
;
1133 static const struct v4l2_async_notifier_operations isi_graph_notify_ops
= {
1134 .bound
= isi_graph_notify_bound
,
1135 .unbind
= isi_graph_notify_unbind
,
1136 .complete
= isi_graph_notify_complete
,
1139 static int isi_graph_parse(struct atmel_isi
*isi
, struct device_node
*node
)
1141 struct device_node
*ep
= NULL
;
1142 struct device_node
*remote
;
1144 ep
= of_graph_get_next_endpoint(node
, ep
);
1148 remote
= of_graph_get_remote_port_parent(ep
);
1153 /* Remote node to connect */
1154 isi
->entity
.node
= remote
;
1155 isi
->entity
.asd
.match_type
= V4L2_ASYNC_MATCH_FWNODE
;
1156 isi
->entity
.asd
.match
.fwnode
= of_fwnode_handle(remote
);
1160 static int isi_graph_init(struct atmel_isi
*isi
)
1164 /* Parse the graph to extract a list of subdevice DT nodes. */
1165 ret
= isi_graph_parse(isi
, isi
->dev
->of_node
);
1167 dev_err(isi
->dev
, "Graph parsing failed\n");
1171 v4l2_async_notifier_init(&isi
->notifier
);
1173 ret
= v4l2_async_notifier_add_subdev(&isi
->notifier
, &isi
->entity
.asd
);
1175 of_node_put(isi
->entity
.node
);
1179 isi
->notifier
.ops
= &isi_graph_notify_ops
;
1181 ret
= v4l2_async_notifier_register(&isi
->v4l2_dev
, &isi
->notifier
);
1183 dev_err(isi
->dev
, "Notifier registration failed\n");
1184 v4l2_async_notifier_cleanup(&isi
->notifier
);
1192 static int atmel_isi_probe(struct platform_device
*pdev
)
1195 struct atmel_isi
*isi
;
1196 struct vb2_queue
*q
;
1197 struct resource
*regs
;
1200 isi
= devm_kzalloc(&pdev
->dev
, sizeof(struct atmel_isi
), GFP_KERNEL
);
1204 isi
->pclk
= devm_clk_get(&pdev
->dev
, "isi_clk");
1205 if (IS_ERR(isi
->pclk
))
1206 return PTR_ERR(isi
->pclk
);
1208 ret
= atmel_isi_parse_dt(isi
, pdev
);
1213 isi
->dev
= &pdev
->dev
;
1214 mutex_init(&isi
->lock
);
1215 spin_lock_init(&isi
->irqlock
);
1216 INIT_LIST_HEAD(&isi
->video_buffer_list
);
1217 INIT_LIST_HEAD(&isi
->dma_desc_head
);
1221 /* Initialize the top-level structure */
1222 ret
= v4l2_device_register(&pdev
->dev
, &isi
->v4l2_dev
);
1226 isi
->vdev
= video_device_alloc();
1229 goto err_vdev_alloc
;
1233 isi
->vdev
->fops
= &isi_fops
;
1234 isi
->vdev
->v4l2_dev
= &isi
->v4l2_dev
;
1235 isi
->vdev
->queue
= &isi
->queue
;
1236 strscpy(isi
->vdev
->name
, KBUILD_MODNAME
, sizeof(isi
->vdev
->name
));
1237 isi
->vdev
->release
= video_device_release
;
1238 isi
->vdev
->ioctl_ops
= &isi_ioctl_ops
;
1239 isi
->vdev
->lock
= &isi
->lock
;
1240 isi
->vdev
->device_caps
= V4L2_CAP_VIDEO_CAPTURE
| V4L2_CAP_STREAMING
|
1242 video_set_drvdata(isi
->vdev
, isi
);
1245 q
->type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1246 q
->io_modes
= VB2_MMAP
| VB2_READ
| VB2_DMABUF
;
1247 q
->lock
= &isi
->lock
;
1249 q
->buf_struct_size
= sizeof(struct frame_buffer
);
1250 q
->ops
= &isi_video_qops
;
1251 q
->mem_ops
= &vb2_dma_contig_memops
;
1252 q
->timestamp_flags
= V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC
;
1253 q
->min_buffers_needed
= 2;
1254 q
->dev
= &pdev
->dev
;
1256 ret
= vb2_queue_init(q
);
1258 dev_err(&pdev
->dev
, "failed to initialize VB2 queue\n");
1261 isi
->p_fb_descriptors
= dma_alloc_coherent(&pdev
->dev
,
1262 sizeof(struct fbd
) * VIDEO_MAX_FRAME
,
1263 &isi
->fb_descriptors_phys
,
1265 if (!isi
->p_fb_descriptors
) {
1266 dev_err(&pdev
->dev
, "Can't allocate descriptors!\n");
1271 for (i
= 0; i
< VIDEO_MAX_FRAME
; i
++) {
1272 isi
->dma_desc
[i
].p_fbd
= isi
->p_fb_descriptors
+ i
;
1273 isi
->dma_desc
[i
].fbd_phys
= isi
->fb_descriptors_phys
+
1274 i
* sizeof(struct fbd
);
1275 list_add(&isi
->dma_desc
[i
].list
, &isi
->dma_desc_head
);
1278 regs
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
1279 isi
->regs
= devm_ioremap_resource(&pdev
->dev
, regs
);
1280 if (IS_ERR(isi
->regs
)) {
1281 ret
= PTR_ERR(isi
->regs
);
1285 if (isi
->pdata
.data_width_flags
& ISI_DATAWIDTH_8
)
1286 isi
->width_flags
= 1 << 7;
1287 if (isi
->pdata
.data_width_flags
& ISI_DATAWIDTH_10
)
1288 isi
->width_flags
|= 1 << 9;
1290 irq
= platform_get_irq(pdev
, 0);
1296 ret
= devm_request_irq(&pdev
->dev
, irq
, isi_interrupt
, 0, "isi", isi
);
1298 dev_err(&pdev
->dev
, "Unable to request irq %d\n", irq
);
1303 ret
= isi_graph_init(isi
);
1307 pm_suspend_ignore_children(&pdev
->dev
, true);
1308 pm_runtime_enable(&pdev
->dev
);
1309 platform_set_drvdata(pdev
, isi
);
1314 dma_free_coherent(&pdev
->dev
,
1315 sizeof(struct fbd
) * VIDEO_MAX_FRAME
,
1316 isi
->p_fb_descriptors
,
1317 isi
->fb_descriptors_phys
);
1320 video_device_release(isi
->vdev
);
1322 v4l2_device_unregister(&isi
->v4l2_dev
);
1327 static int atmel_isi_remove(struct platform_device
*pdev
)
1329 struct atmel_isi
*isi
= platform_get_drvdata(pdev
);
1331 dma_free_coherent(&pdev
->dev
,
1332 sizeof(struct fbd
) * VIDEO_MAX_FRAME
,
1333 isi
->p_fb_descriptors
,
1334 isi
->fb_descriptors_phys
);
1335 pm_runtime_disable(&pdev
->dev
);
1336 v4l2_async_notifier_unregister(&isi
->notifier
);
1337 v4l2_async_notifier_cleanup(&isi
->notifier
);
1338 v4l2_device_unregister(&isi
->v4l2_dev
);
1344 static int atmel_isi_runtime_suspend(struct device
*dev
)
1346 struct atmel_isi
*isi
= dev_get_drvdata(dev
);
1348 clk_disable_unprepare(isi
->pclk
);
1352 static int atmel_isi_runtime_resume(struct device
*dev
)
1354 struct atmel_isi
*isi
= dev_get_drvdata(dev
);
1356 return clk_prepare_enable(isi
->pclk
);
1358 #endif /* CONFIG_PM */
1360 static const struct dev_pm_ops atmel_isi_dev_pm_ops
= {
1361 SET_RUNTIME_PM_OPS(atmel_isi_runtime_suspend
,
1362 atmel_isi_runtime_resume
, NULL
)
1365 static const struct of_device_id atmel_isi_of_match
[] = {
1366 { .compatible
= "atmel,at91sam9g45-isi" },
1369 MODULE_DEVICE_TABLE(of
, atmel_isi_of_match
);
1371 static struct platform_driver atmel_isi_driver
= {
1373 .name
= "atmel_isi",
1374 .of_match_table
= of_match_ptr(atmel_isi_of_match
),
1375 .pm
= &atmel_isi_dev_pm_ops
,
1377 .probe
= atmel_isi_probe
,
1378 .remove
= atmel_isi_remove
,
1381 module_platform_driver(atmel_isi_driver
);
1383 MODULE_AUTHOR("Josh Wu <josh.wu@atmel.com>");
1384 MODULE_DESCRIPTION("The V4L2 driver for Atmel Linux");
1385 MODULE_LICENSE("GPL");
1386 MODULE_SUPPORTED_DEVICE("video");