2 * Copyright (c) 2011 Atmel Corporation
3 * Josh Wu, <josh.wu@atmel.com>
5 * Based on previous work by Lars Haring, <lars.haring@atmel.com>
7 * Based on the bttv driver for Bt848 with respective copyright holders
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
14 #include <linux/clk.h>
15 #include <linux/completion.h>
16 #include <linux/delay.h>
18 #include <linux/init.h>
19 #include <linux/interrupt.h>
20 #include <linux/kernel.h>
21 #include <linux/module.h>
22 #include <linux/platform_device.h>
23 #include <linux/pm_runtime.h>
24 #include <linux/slab.h>
26 #include <media/soc_camera.h>
27 #include <media/drv-intf/soc_mediabus.h>
28 #include <media/v4l2-of.h>
29 #include <media/videobuf2-dma-contig.h>
31 #include "atmel-isi.h"
33 #define MAX_BUFFER_NUM 32
34 #define MAX_SUPPORT_WIDTH 2048
35 #define MAX_SUPPORT_HEIGHT 2048
36 #define VID_LIMIT_BYTES (16 * 1024 * 1024)
37 #define MIN_FRAME_RATE 15
38 #define FRAME_INTERVAL_MILLI_SEC (1000 / MIN_FRAME_RATE)
40 /* Frame buffer descriptor */
42 /* Physical address of the frame buffer */
44 /* DMA Control Register(only in HISI2) */
46 /* Physical address of the next fbd */
50 static void set_dma_ctrl(struct fbd
*fb_desc
, u32 ctrl
)
52 fb_desc
->dma_ctrl
= ctrl
;
56 struct list_head list
;
61 /* Frame buffer data */
63 struct vb2_v4l2_buffer vb
;
64 struct isi_dma_desc
*p_dma_desc
;
65 struct list_head list
;
69 /* Protects the access of variables shared with the ISR */
75 struct vb2_alloc_ctx
*alloc_ctx
;
77 /* Allocate descriptors for dma buffer use */
78 struct fbd
*p_fb_descriptors
;
79 dma_addr_t fb_descriptors_phys
;
80 struct list_head dma_desc_head
;
81 struct isi_dma_desc dma_desc
[MAX_BUFFER_NUM
];
82 bool enable_preview_path
;
84 struct completion complete
;
85 /* ISI peripherial clock */
89 struct isi_platform_data pdata
;
90 u16 width_flags
; /* max 12 bits */
92 struct list_head video_buffer_list
;
93 struct frame_buffer
*active
;
95 struct soc_camera_host soc_host
;
98 static void isi_writel(struct atmel_isi
*isi
, u32 reg
, u32 val
)
100 writel(val
, isi
->regs
+ reg
);
102 static u32
isi_readl(struct atmel_isi
*isi
, u32 reg
)
104 return readl(isi
->regs
+ reg
);
107 static u32
setup_cfg2_yuv_swap(struct atmel_isi
*isi
,
108 const struct soc_camera_format_xlate
*xlate
)
110 if (xlate
->host_fmt
->fourcc
== V4L2_PIX_FMT_YUYV
) {
111 /* all convert to YUYV */
112 switch (xlate
->code
) {
113 case MEDIA_BUS_FMT_VYUY8_2X8
:
114 return ISI_CFG2_YCC_SWAP_MODE_3
;
115 case MEDIA_BUS_FMT_UYVY8_2X8
:
116 return ISI_CFG2_YCC_SWAP_MODE_2
;
117 case MEDIA_BUS_FMT_YVYU8_2X8
:
118 return ISI_CFG2_YCC_SWAP_MODE_1
;
120 } else if (xlate
->host_fmt
->fourcc
== V4L2_PIX_FMT_RGB565
) {
122 * Preview path is enabled, it will convert UYVY to RGB format.
123 * But if sensor output format is not UYVY, we need to set
124 * YCC_SWAP_MODE to convert it as UYVY.
126 switch (xlate
->code
) {
127 case MEDIA_BUS_FMT_VYUY8_2X8
:
128 return ISI_CFG2_YCC_SWAP_MODE_1
;
129 case MEDIA_BUS_FMT_YUYV8_2X8
:
130 return ISI_CFG2_YCC_SWAP_MODE_2
;
131 case MEDIA_BUS_FMT_YVYU8_2X8
:
132 return ISI_CFG2_YCC_SWAP_MODE_3
;
137 * By default, no swap for the codec path of Atmel ISI. So codec
138 * output is same as sensor's output.
139 * For instance, if sensor's output is YUYV, then codec outputs YUYV.
140 * And if sensor's output is UYVY, then codec outputs UYVY.
142 return ISI_CFG2_YCC_SWAP_DEFAULT
;
145 static void configure_geometry(struct atmel_isi
*isi
, u32 width
,
146 u32 height
, const struct soc_camera_format_xlate
*xlate
)
149 u32 fourcc
= xlate
->host_fmt
->fourcc
;
151 isi
->enable_preview_path
= fourcc
== V4L2_PIX_FMT_RGB565
||
152 fourcc
== V4L2_PIX_FMT_RGB32
;
154 /* According to sensor's output format to set cfg2 */
155 switch (xlate
->code
) {
158 case MEDIA_BUS_FMT_Y8_1X8
:
159 cfg2
= ISI_CFG2_GRAYSCALE
| ISI_CFG2_COL_SPACE_YCbCr
;
162 case MEDIA_BUS_FMT_VYUY8_2X8
:
163 case MEDIA_BUS_FMT_UYVY8_2X8
:
164 case MEDIA_BUS_FMT_YVYU8_2X8
:
165 case MEDIA_BUS_FMT_YUYV8_2X8
:
166 cfg2
= ISI_CFG2_COL_SPACE_YCbCr
|
167 setup_cfg2_yuv_swap(isi
, xlate
);
172 isi_writel(isi
, ISI_CTRL
, ISI_CTRL_DIS
);
174 cfg2
|= ((width
- 1) << ISI_CFG2_IM_HSIZE_OFFSET
) &
175 ISI_CFG2_IM_HSIZE_MASK
;
177 cfg2
|= ((height
- 1) << ISI_CFG2_IM_VSIZE_OFFSET
)
178 & ISI_CFG2_IM_VSIZE_MASK
;
179 isi_writel(isi
, ISI_CFG2
, cfg2
);
181 /* No down sampling, preview size equal to sensor output size */
182 psize
= ((width
- 1) << ISI_PSIZE_PREV_HSIZE_OFFSET
) &
183 ISI_PSIZE_PREV_HSIZE_MASK
;
184 psize
|= ((height
- 1) << ISI_PSIZE_PREV_VSIZE_OFFSET
) &
185 ISI_PSIZE_PREV_VSIZE_MASK
;
186 isi_writel(isi
, ISI_PSIZE
, psize
);
187 isi_writel(isi
, ISI_PDECF
, ISI_PDECF_NO_SAMPLING
);
192 static bool is_supported(struct soc_camera_device
*icd
,
196 /* YUV, including grey */
197 case V4L2_PIX_FMT_GREY
:
198 case V4L2_PIX_FMT_YUYV
:
199 case V4L2_PIX_FMT_UYVY
:
200 case V4L2_PIX_FMT_YVYU
:
201 case V4L2_PIX_FMT_VYUY
:
203 case V4L2_PIX_FMT_RGB565
:
210 static irqreturn_t
atmel_isi_handle_streaming(struct atmel_isi
*isi
)
213 struct vb2_v4l2_buffer
*vbuf
= &isi
->active
->vb
;
214 struct frame_buffer
*buf
= isi
->active
;
216 list_del_init(&buf
->list
);
217 vbuf
->vb2_buf
.timestamp
= ktime_get_ns();
218 vbuf
->sequence
= isi
->sequence
++;
219 vb2_buffer_done(&vbuf
->vb2_buf
, VB2_BUF_STATE_DONE
);
222 if (list_empty(&isi
->video_buffer_list
)) {
225 /* start next dma frame. */
226 isi
->active
= list_entry(isi
->video_buffer_list
.next
,
227 struct frame_buffer
, list
);
228 if (!isi
->enable_preview_path
) {
229 isi_writel(isi
, ISI_DMA_C_DSCR
,
230 (u32
)isi
->active
->p_dma_desc
->fbd_phys
);
231 isi_writel(isi
, ISI_DMA_C_CTRL
,
232 ISI_DMA_CTRL_FETCH
| ISI_DMA_CTRL_DONE
);
233 isi_writel(isi
, ISI_DMA_CHER
, ISI_DMA_CHSR_C_CH
);
235 isi_writel(isi
, ISI_DMA_P_DSCR
,
236 (u32
)isi
->active
->p_dma_desc
->fbd_phys
);
237 isi_writel(isi
, ISI_DMA_P_CTRL
,
238 ISI_DMA_CTRL_FETCH
| ISI_DMA_CTRL_DONE
);
239 isi_writel(isi
, ISI_DMA_CHER
, ISI_DMA_CHSR_P_CH
);
245 /* ISI interrupt service routine */
246 static irqreturn_t
isi_interrupt(int irq
, void *dev_id
)
248 struct atmel_isi
*isi
= dev_id
;
249 u32 status
, mask
, pending
;
250 irqreturn_t ret
= IRQ_NONE
;
252 spin_lock(&isi
->lock
);
254 status
= isi_readl(isi
, ISI_STATUS
);
255 mask
= isi_readl(isi
, ISI_INTMASK
);
256 pending
= status
& mask
;
258 if (pending
& ISI_CTRL_SRST
) {
259 complete(&isi
->complete
);
260 isi_writel(isi
, ISI_INTDIS
, ISI_CTRL_SRST
);
262 } else if (pending
& ISI_CTRL_DIS
) {
263 complete(&isi
->complete
);
264 isi_writel(isi
, ISI_INTDIS
, ISI_CTRL_DIS
);
267 if (likely(pending
& ISI_SR_CXFR_DONE
) ||
268 likely(pending
& ISI_SR_PXFR_DONE
))
269 ret
= atmel_isi_handle_streaming(isi
);
272 spin_unlock(&isi
->lock
);
276 #define WAIT_ISI_RESET 1
277 #define WAIT_ISI_DISABLE 0
278 static int atmel_isi_wait_status(struct atmel_isi
*isi
, int wait_reset
)
280 unsigned long timeout
;
282 * The reset or disable will only succeed if we have a
283 * pixel clock from the camera.
285 init_completion(&isi
->complete
);
288 isi_writel(isi
, ISI_INTEN
, ISI_CTRL_SRST
);
289 isi_writel(isi
, ISI_CTRL
, ISI_CTRL_SRST
);
291 isi_writel(isi
, ISI_INTEN
, ISI_CTRL_DIS
);
292 isi_writel(isi
, ISI_CTRL
, ISI_CTRL_DIS
);
295 timeout
= wait_for_completion_timeout(&isi
->complete
,
296 msecs_to_jiffies(500));
303 /* ------------------------------------------------------------------
305 ------------------------------------------------------------------*/
306 static int queue_setup(struct vb2_queue
*vq
,
307 unsigned int *nbuffers
, unsigned int *nplanes
,
308 unsigned int sizes
[], void *alloc_ctxs
[])
310 struct soc_camera_device
*icd
= soc_camera_from_vb2q(vq
);
311 struct soc_camera_host
*ici
= to_soc_camera_host(icd
->parent
);
312 struct atmel_isi
*isi
= ici
->priv
;
315 size
= icd
->sizeimage
;
317 if (!*nbuffers
|| *nbuffers
> MAX_BUFFER_NUM
)
318 *nbuffers
= MAX_BUFFER_NUM
;
320 if (size
* *nbuffers
> VID_LIMIT_BYTES
)
321 *nbuffers
= VID_LIMIT_BYTES
/ size
;
325 alloc_ctxs
[0] = isi
->alloc_ctx
;
330 dev_dbg(icd
->parent
, "%s, count=%d, size=%ld\n", __func__
,
336 static int buffer_init(struct vb2_buffer
*vb
)
338 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
339 struct frame_buffer
*buf
= container_of(vbuf
, struct frame_buffer
, vb
);
341 buf
->p_dma_desc
= NULL
;
342 INIT_LIST_HEAD(&buf
->list
);
347 static int buffer_prepare(struct vb2_buffer
*vb
)
349 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
350 struct soc_camera_device
*icd
= soc_camera_from_vb2q(vb
->vb2_queue
);
351 struct frame_buffer
*buf
= container_of(vbuf
, struct frame_buffer
, vb
);
352 struct soc_camera_host
*ici
= to_soc_camera_host(icd
->parent
);
353 struct atmel_isi
*isi
= ici
->priv
;
355 struct isi_dma_desc
*desc
;
357 size
= icd
->sizeimage
;
359 if (vb2_plane_size(vb
, 0) < size
) {
360 dev_err(icd
->parent
, "%s data will not fit into plane (%lu < %lu)\n",
361 __func__
, vb2_plane_size(vb
, 0), size
);
365 vb2_set_plane_payload(vb
, 0, size
);
367 if (!buf
->p_dma_desc
) {
368 if (list_empty(&isi
->dma_desc_head
)) {
369 dev_err(icd
->parent
, "Not enough dma descriptors.\n");
372 /* Get an available descriptor */
373 desc
= list_entry(isi
->dma_desc_head
.next
,
374 struct isi_dma_desc
, list
);
375 /* Delete the descriptor since now it is used */
376 list_del_init(&desc
->list
);
378 /* Initialize the dma descriptor */
379 desc
->p_fbd
->fb_address
=
380 vb2_dma_contig_plane_dma_addr(vb
, 0);
381 desc
->p_fbd
->next_fbd_address
= 0;
382 set_dma_ctrl(desc
->p_fbd
, ISI_DMA_CTRL_WB
);
384 buf
->p_dma_desc
= desc
;
390 static void buffer_cleanup(struct vb2_buffer
*vb
)
392 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
393 struct soc_camera_device
*icd
= soc_camera_from_vb2q(vb
->vb2_queue
);
394 struct soc_camera_host
*ici
= to_soc_camera_host(icd
->parent
);
395 struct atmel_isi
*isi
= ici
->priv
;
396 struct frame_buffer
*buf
= container_of(vbuf
, struct frame_buffer
, vb
);
398 /* This descriptor is available now and we add to head list */
400 list_add(&buf
->p_dma_desc
->list
, &isi
->dma_desc_head
);
403 static void start_dma(struct atmel_isi
*isi
, struct frame_buffer
*buffer
)
407 cfg1
= isi_readl(isi
, ISI_CFG1
);
408 /* Enable irq: cxfr for the codec path, pxfr for the preview path */
409 isi_writel(isi
, ISI_INTEN
,
410 ISI_SR_CXFR_DONE
| ISI_SR_PXFR_DONE
);
412 /* Check if already in a frame */
413 if (!isi
->enable_preview_path
) {
414 if (isi_readl(isi
, ISI_STATUS
) & ISI_CTRL_CDC
) {
415 dev_err(isi
->soc_host
.icd
->parent
, "Already in frame handling.\n");
419 isi_writel(isi
, ISI_DMA_C_DSCR
,
420 (u32
)buffer
->p_dma_desc
->fbd_phys
);
421 isi_writel(isi
, ISI_DMA_C_CTRL
,
422 ISI_DMA_CTRL_FETCH
| ISI_DMA_CTRL_DONE
);
423 isi_writel(isi
, ISI_DMA_CHER
, ISI_DMA_CHSR_C_CH
);
425 isi_writel(isi
, ISI_DMA_P_DSCR
,
426 (u32
)buffer
->p_dma_desc
->fbd_phys
);
427 isi_writel(isi
, ISI_DMA_P_CTRL
,
428 ISI_DMA_CTRL_FETCH
| ISI_DMA_CTRL_DONE
);
429 isi_writel(isi
, ISI_DMA_CHER
, ISI_DMA_CHSR_P_CH
);
432 cfg1
&= ~ISI_CFG1_FRATE_DIV_MASK
;
433 /* Enable linked list */
434 cfg1
|= isi
->pdata
.frate
| ISI_CFG1_DISCR
;
439 if (!isi
->enable_preview_path
)
440 ctrl
|= ISI_CTRL_CDC
;
442 isi_writel(isi
, ISI_CTRL
, ctrl
);
443 isi_writel(isi
, ISI_CFG1
, cfg1
);
446 static void buffer_queue(struct vb2_buffer
*vb
)
448 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
449 struct soc_camera_device
*icd
= soc_camera_from_vb2q(vb
->vb2_queue
);
450 struct soc_camera_host
*ici
= to_soc_camera_host(icd
->parent
);
451 struct atmel_isi
*isi
= ici
->priv
;
452 struct frame_buffer
*buf
= container_of(vbuf
, struct frame_buffer
, vb
);
453 unsigned long flags
= 0;
455 spin_lock_irqsave(&isi
->lock
, flags
);
456 list_add_tail(&buf
->list
, &isi
->video_buffer_list
);
458 if (isi
->active
== NULL
) {
460 if (vb2_is_streaming(vb
->vb2_queue
))
463 spin_unlock_irqrestore(&isi
->lock
, flags
);
466 static int start_streaming(struct vb2_queue
*vq
, unsigned int count
)
468 struct soc_camera_device
*icd
= soc_camera_from_vb2q(vq
);
469 struct soc_camera_host
*ici
= to_soc_camera_host(icd
->parent
);
470 struct atmel_isi
*isi
= ici
->priv
;
473 pm_runtime_get_sync(ici
->v4l2_dev
.dev
);
476 ret
= atmel_isi_wait_status(isi
, WAIT_ISI_RESET
);
478 dev_err(icd
->parent
, "Reset ISI timed out\n");
479 pm_runtime_put(ici
->v4l2_dev
.dev
);
482 /* Disable all interrupts */
483 isi_writel(isi
, ISI_INTDIS
, (u32
)~0UL);
485 configure_geometry(isi
, icd
->user_width
, icd
->user_height
,
488 spin_lock_irq(&isi
->lock
);
489 /* Clear any pending interrupt */
490 isi_readl(isi
, ISI_STATUS
);
493 start_dma(isi
, isi
->active
);
494 spin_unlock_irq(&isi
->lock
);
499 /* abort streaming and wait for last buffer */
500 static void stop_streaming(struct vb2_queue
*vq
)
502 struct soc_camera_device
*icd
= soc_camera_from_vb2q(vq
);
503 struct soc_camera_host
*ici
= to_soc_camera_host(icd
->parent
);
504 struct atmel_isi
*isi
= ici
->priv
;
505 struct frame_buffer
*buf
, *node
;
507 unsigned long timeout
;
509 spin_lock_irq(&isi
->lock
);
511 /* Release all active buffers */
512 list_for_each_entry_safe(buf
, node
, &isi
->video_buffer_list
, list
) {
513 list_del_init(&buf
->list
);
514 vb2_buffer_done(&buf
->vb
.vb2_buf
, VB2_BUF_STATE_ERROR
);
516 spin_unlock_irq(&isi
->lock
);
518 if (!isi
->enable_preview_path
) {
519 timeout
= jiffies
+ FRAME_INTERVAL_MILLI_SEC
* HZ
;
520 /* Wait until the end of the current frame. */
521 while ((isi_readl(isi
, ISI_STATUS
) & ISI_CTRL_CDC
) &&
522 time_before(jiffies
, timeout
))
525 if (time_after(jiffies
, timeout
))
527 "Timeout waiting for finishing codec request\n");
530 /* Disable interrupts */
531 isi_writel(isi
, ISI_INTDIS
,
532 ISI_SR_CXFR_DONE
| ISI_SR_PXFR_DONE
);
534 /* Disable ISI and wait for it is done */
535 ret
= atmel_isi_wait_status(isi
, WAIT_ISI_DISABLE
);
537 dev_err(icd
->parent
, "Disable ISI timed out\n");
539 pm_runtime_put(ici
->v4l2_dev
.dev
);
542 static struct vb2_ops isi_video_qops
= {
543 .queue_setup
= queue_setup
,
544 .buf_init
= buffer_init
,
545 .buf_prepare
= buffer_prepare
,
546 .buf_cleanup
= buffer_cleanup
,
547 .buf_queue
= buffer_queue
,
548 .start_streaming
= start_streaming
,
549 .stop_streaming
= stop_streaming
,
550 .wait_prepare
= vb2_ops_wait_prepare
,
551 .wait_finish
= vb2_ops_wait_finish
,
554 /* ------------------------------------------------------------------
555 SOC camera operations for the device
556 ------------------------------------------------------------------*/
557 static int isi_camera_init_videobuf(struct vb2_queue
*q
,
558 struct soc_camera_device
*icd
)
560 struct soc_camera_host
*ici
= to_soc_camera_host(icd
->parent
);
562 q
->type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
563 q
->io_modes
= VB2_MMAP
;
565 q
->buf_struct_size
= sizeof(struct frame_buffer
);
566 q
->ops
= &isi_video_qops
;
567 q
->mem_ops
= &vb2_dma_contig_memops
;
568 q
->timestamp_flags
= V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC
;
569 q
->lock
= &ici
->host_lock
;
571 return vb2_queue_init(q
);
574 static int isi_camera_set_fmt(struct soc_camera_device
*icd
,
575 struct v4l2_format
*f
)
577 struct v4l2_subdev
*sd
= soc_camera_to_subdev(icd
);
578 const struct soc_camera_format_xlate
*xlate
;
579 struct v4l2_pix_format
*pix
= &f
->fmt
.pix
;
580 struct v4l2_subdev_format format
= {
581 .which
= V4L2_SUBDEV_FORMAT_ACTIVE
,
583 struct v4l2_mbus_framefmt
*mf
= &format
.format
;
586 /* check with atmel-isi support format, if not support use YUYV */
587 if (!is_supported(icd
, pix
->pixelformat
))
588 pix
->pixelformat
= V4L2_PIX_FMT_YUYV
;
590 xlate
= soc_camera_xlate_by_fourcc(icd
, pix
->pixelformat
);
592 dev_warn(icd
->parent
, "Format %x not found\n",
597 dev_dbg(icd
->parent
, "Plan to set format %dx%d\n",
598 pix
->width
, pix
->height
);
600 mf
->width
= pix
->width
;
601 mf
->height
= pix
->height
;
602 mf
->field
= pix
->field
;
603 mf
->colorspace
= pix
->colorspace
;
604 mf
->code
= xlate
->code
;
606 ret
= v4l2_subdev_call(sd
, pad
, set_fmt
, NULL
, &format
);
610 if (mf
->code
!= xlate
->code
)
613 pix
->width
= mf
->width
;
614 pix
->height
= mf
->height
;
615 pix
->field
= mf
->field
;
616 pix
->colorspace
= mf
->colorspace
;
617 icd
->current_fmt
= xlate
;
619 dev_dbg(icd
->parent
, "Finally set format %dx%d\n",
620 pix
->width
, pix
->height
);
625 static int isi_camera_try_fmt(struct soc_camera_device
*icd
,
626 struct v4l2_format
*f
)
628 struct v4l2_subdev
*sd
= soc_camera_to_subdev(icd
);
629 const struct soc_camera_format_xlate
*xlate
;
630 struct v4l2_pix_format
*pix
= &f
->fmt
.pix
;
631 struct v4l2_subdev_pad_config pad_cfg
;
632 struct v4l2_subdev_format format
= {
633 .which
= V4L2_SUBDEV_FORMAT_TRY
,
635 struct v4l2_mbus_framefmt
*mf
= &format
.format
;
636 u32 pixfmt
= pix
->pixelformat
;
639 /* check with atmel-isi support format, if not support use YUYV */
640 if (!is_supported(icd
, pix
->pixelformat
))
641 pix
->pixelformat
= V4L2_PIX_FMT_YUYV
;
643 xlate
= soc_camera_xlate_by_fourcc(icd
, pixfmt
);
644 if (pixfmt
&& !xlate
) {
645 dev_warn(icd
->parent
, "Format %x not found\n", pixfmt
);
649 /* limit to Atmel ISI hardware capabilities */
650 if (pix
->height
> MAX_SUPPORT_HEIGHT
)
651 pix
->height
= MAX_SUPPORT_HEIGHT
;
652 if (pix
->width
> MAX_SUPPORT_WIDTH
)
653 pix
->width
= MAX_SUPPORT_WIDTH
;
655 /* limit to sensor capabilities */
656 mf
->width
= pix
->width
;
657 mf
->height
= pix
->height
;
658 mf
->field
= pix
->field
;
659 mf
->colorspace
= pix
->colorspace
;
660 mf
->code
= xlate
->code
;
662 ret
= v4l2_subdev_call(sd
, pad
, set_fmt
, &pad_cfg
, &format
);
666 pix
->width
= mf
->width
;
667 pix
->height
= mf
->height
;
668 pix
->colorspace
= mf
->colorspace
;
672 pix
->field
= V4L2_FIELD_NONE
;
674 case V4L2_FIELD_NONE
:
677 dev_err(icd
->parent
, "Field type %d unsupported.\n",
685 static const struct soc_mbus_pixelfmt isi_camera_formats
[] = {
687 .fourcc
= V4L2_PIX_FMT_YUYV
,
688 .name
= "Packed YUV422 16 bit",
689 .bits_per_sample
= 8,
690 .packing
= SOC_MBUS_PACKING_2X8_PADHI
,
691 .order
= SOC_MBUS_ORDER_LE
,
692 .layout
= SOC_MBUS_LAYOUT_PACKED
,
695 .fourcc
= V4L2_PIX_FMT_RGB565
,
697 .bits_per_sample
= 8,
698 .packing
= SOC_MBUS_PACKING_2X8_PADHI
,
699 .order
= SOC_MBUS_ORDER_LE
,
700 .layout
= SOC_MBUS_LAYOUT_PACKED
,
704 /* This will be corrected as we get more formats */
705 static bool isi_camera_packing_supported(const struct soc_mbus_pixelfmt
*fmt
)
707 return fmt
->packing
== SOC_MBUS_PACKING_NONE
||
708 (fmt
->bits_per_sample
== 8 &&
709 fmt
->packing
== SOC_MBUS_PACKING_2X8_PADHI
) ||
710 (fmt
->bits_per_sample
> 8 &&
711 fmt
->packing
== SOC_MBUS_PACKING_EXTEND16
);
714 #define ISI_BUS_PARAM (V4L2_MBUS_MASTER | \
715 V4L2_MBUS_HSYNC_ACTIVE_HIGH | \
716 V4L2_MBUS_HSYNC_ACTIVE_LOW | \
717 V4L2_MBUS_VSYNC_ACTIVE_HIGH | \
718 V4L2_MBUS_VSYNC_ACTIVE_LOW | \
719 V4L2_MBUS_PCLK_SAMPLE_RISING | \
720 V4L2_MBUS_PCLK_SAMPLE_FALLING | \
721 V4L2_MBUS_DATA_ACTIVE_HIGH)
723 static int isi_camera_try_bus_param(struct soc_camera_device
*icd
,
724 unsigned char buswidth
)
726 struct v4l2_subdev
*sd
= soc_camera_to_subdev(icd
);
727 struct soc_camera_host
*ici
= to_soc_camera_host(icd
->parent
);
728 struct atmel_isi
*isi
= ici
->priv
;
729 struct v4l2_mbus_config cfg
= {.type
= V4L2_MBUS_PARALLEL
,};
730 unsigned long common_flags
;
733 ret
= v4l2_subdev_call(sd
, video
, g_mbus_config
, &cfg
);
735 common_flags
= soc_mbus_config_compatible(&cfg
,
738 dev_warn(icd
->parent
,
739 "Flags incompatible: camera 0x%x, host 0x%x\n",
740 cfg
.flags
, ISI_BUS_PARAM
);
743 } else if (ret
!= -ENOIOCTLCMD
) {
747 if ((1 << (buswidth
- 1)) & isi
->width_flags
)
753 static int isi_camera_get_formats(struct soc_camera_device
*icd
,
755 struct soc_camera_format_xlate
*xlate
)
757 struct v4l2_subdev
*sd
= soc_camera_to_subdev(icd
);
758 int formats
= 0, ret
, i
, n
;
760 struct v4l2_subdev_mbus_code_enum code
= {
761 .which
= V4L2_SUBDEV_FORMAT_ACTIVE
,
764 /* soc camera host format */
765 const struct soc_mbus_pixelfmt
*fmt
;
767 ret
= v4l2_subdev_call(sd
, pad
, enum_mbus_code
, NULL
, &code
);
769 /* No more formats */
772 fmt
= soc_mbus_get_fmtdesc(code
.code
);
775 "Invalid format code #%u: %d\n", idx
, code
.code
);
779 /* This also checks support for the requested bits-per-sample */
780 ret
= isi_camera_try_bus_param(icd
, fmt
->bits_per_sample
);
783 "Fail to try the bus parameters.\n");
788 case MEDIA_BUS_FMT_UYVY8_2X8
:
789 case MEDIA_BUS_FMT_VYUY8_2X8
:
790 case MEDIA_BUS_FMT_YUYV8_2X8
:
791 case MEDIA_BUS_FMT_YVYU8_2X8
:
792 n
= ARRAY_SIZE(isi_camera_formats
);
794 for (i
= 0; xlate
&& i
< n
; i
++, xlate
++) {
795 xlate
->host_fmt
= &isi_camera_formats
[i
];
796 xlate
->code
= code
.code
;
797 dev_dbg(icd
->parent
, "Providing format %s using code %d\n",
798 xlate
->host_fmt
->name
, xlate
->code
);
802 if (!isi_camera_packing_supported(fmt
))
806 "Providing format %s in pass-through mode\n",
810 /* Generic pass-through */
813 xlate
->host_fmt
= fmt
;
814 xlate
->code
= code
.code
;
821 static int isi_camera_add_device(struct soc_camera_device
*icd
)
823 dev_dbg(icd
->parent
, "Atmel ISI Camera driver attached to camera %d\n",
829 static void isi_camera_remove_device(struct soc_camera_device
*icd
)
831 dev_dbg(icd
->parent
, "Atmel ISI Camera driver detached from camera %d\n",
835 static unsigned int isi_camera_poll(struct file
*file
, poll_table
*pt
)
837 struct soc_camera_device
*icd
= file
->private_data
;
839 return vb2_poll(&icd
->vb2_vidq
, file
, pt
);
842 static int isi_camera_querycap(struct soc_camera_host
*ici
,
843 struct v4l2_capability
*cap
)
845 strcpy(cap
->driver
, "atmel-isi");
846 strcpy(cap
->card
, "Atmel Image Sensor Interface");
847 cap
->device_caps
= V4L2_CAP_VIDEO_CAPTURE
| V4L2_CAP_STREAMING
;
848 cap
->capabilities
= cap
->device_caps
| V4L2_CAP_DEVICE_CAPS
;
853 static int isi_camera_set_bus_param(struct soc_camera_device
*icd
)
855 struct v4l2_subdev
*sd
= soc_camera_to_subdev(icd
);
856 struct soc_camera_host
*ici
= to_soc_camera_host(icd
->parent
);
857 struct atmel_isi
*isi
= ici
->priv
;
858 struct v4l2_mbus_config cfg
= {.type
= V4L2_MBUS_PARALLEL
,};
859 unsigned long common_flags
;
863 ret
= v4l2_subdev_call(sd
, video
, g_mbus_config
, &cfg
);
865 common_flags
= soc_mbus_config_compatible(&cfg
,
868 dev_warn(icd
->parent
,
869 "Flags incompatible: camera 0x%x, host 0x%x\n",
870 cfg
.flags
, ISI_BUS_PARAM
);
873 } else if (ret
!= -ENOIOCTLCMD
) {
876 common_flags
= ISI_BUS_PARAM
;
878 dev_dbg(icd
->parent
, "Flags cam: 0x%x host: 0x%x common: 0x%lx\n",
879 cfg
.flags
, ISI_BUS_PARAM
, common_flags
);
881 /* Make choises, based on platform preferences */
882 if ((common_flags
& V4L2_MBUS_HSYNC_ACTIVE_HIGH
) &&
883 (common_flags
& V4L2_MBUS_HSYNC_ACTIVE_LOW
)) {
884 if (isi
->pdata
.hsync_act_low
)
885 common_flags
&= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH
;
887 common_flags
&= ~V4L2_MBUS_HSYNC_ACTIVE_LOW
;
890 if ((common_flags
& V4L2_MBUS_VSYNC_ACTIVE_HIGH
) &&
891 (common_flags
& V4L2_MBUS_VSYNC_ACTIVE_LOW
)) {
892 if (isi
->pdata
.vsync_act_low
)
893 common_flags
&= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH
;
895 common_flags
&= ~V4L2_MBUS_VSYNC_ACTIVE_LOW
;
898 if ((common_flags
& V4L2_MBUS_PCLK_SAMPLE_RISING
) &&
899 (common_flags
& V4L2_MBUS_PCLK_SAMPLE_FALLING
)) {
900 if (isi
->pdata
.pclk_act_falling
)
901 common_flags
&= ~V4L2_MBUS_PCLK_SAMPLE_RISING
;
903 common_flags
&= ~V4L2_MBUS_PCLK_SAMPLE_FALLING
;
906 cfg
.flags
= common_flags
;
907 ret
= v4l2_subdev_call(sd
, video
, s_mbus_config
, &cfg
);
908 if (ret
< 0 && ret
!= -ENOIOCTLCMD
) {
909 dev_dbg(icd
->parent
, "camera s_mbus_config(0x%lx) returned %d\n",
914 /* set bus param for ISI */
915 if (common_flags
& V4L2_MBUS_HSYNC_ACTIVE_LOW
)
916 cfg1
|= ISI_CFG1_HSYNC_POL_ACTIVE_LOW
;
917 if (common_flags
& V4L2_MBUS_VSYNC_ACTIVE_LOW
)
918 cfg1
|= ISI_CFG1_VSYNC_POL_ACTIVE_LOW
;
919 if (common_flags
& V4L2_MBUS_PCLK_SAMPLE_FALLING
)
920 cfg1
|= ISI_CFG1_PIXCLK_POL_ACTIVE_FALLING
;
922 dev_dbg(icd
->parent
, "vsync active %s, hsync active %s, sampling on pix clock %s edge\n",
923 common_flags
& V4L2_MBUS_VSYNC_ACTIVE_LOW
? "low" : "high",
924 common_flags
& V4L2_MBUS_HSYNC_ACTIVE_LOW
? "low" : "high",
925 common_flags
& V4L2_MBUS_PCLK_SAMPLE_FALLING
? "falling" : "rising");
927 if (isi
->pdata
.has_emb_sync
)
928 cfg1
|= ISI_CFG1_EMB_SYNC
;
929 if (isi
->pdata
.full_mode
)
930 cfg1
|= ISI_CFG1_FULL_MODE
;
932 cfg1
|= ISI_CFG1_THMASK_BEATS_16
;
934 /* Enable PM and peripheral clock before operate isi registers */
935 pm_runtime_get_sync(ici
->v4l2_dev
.dev
);
937 isi_writel(isi
, ISI_CTRL
, ISI_CTRL_DIS
);
938 isi_writel(isi
, ISI_CFG1
, cfg1
);
940 pm_runtime_put(ici
->v4l2_dev
.dev
);
945 static struct soc_camera_host_ops isi_soc_camera_host_ops
= {
946 .owner
= THIS_MODULE
,
947 .add
= isi_camera_add_device
,
948 .remove
= isi_camera_remove_device
,
949 .set_fmt
= isi_camera_set_fmt
,
950 .try_fmt
= isi_camera_try_fmt
,
951 .get_formats
= isi_camera_get_formats
,
952 .init_videobuf2
= isi_camera_init_videobuf
,
953 .poll
= isi_camera_poll
,
954 .querycap
= isi_camera_querycap
,
955 .set_bus_param
= isi_camera_set_bus_param
,
958 /* -----------------------------------------------------------------------*/
959 static int atmel_isi_remove(struct platform_device
*pdev
)
961 struct soc_camera_host
*soc_host
= to_soc_camera_host(&pdev
->dev
);
962 struct atmel_isi
*isi
= container_of(soc_host
,
963 struct atmel_isi
, soc_host
);
965 soc_camera_host_unregister(soc_host
);
966 vb2_dma_contig_cleanup_ctx(isi
->alloc_ctx
);
967 dma_free_coherent(&pdev
->dev
,
968 sizeof(struct fbd
) * MAX_BUFFER_NUM
,
969 isi
->p_fb_descriptors
,
970 isi
->fb_descriptors_phys
);
971 pm_runtime_disable(&pdev
->dev
);
976 static int atmel_isi_parse_dt(struct atmel_isi
*isi
,
977 struct platform_device
*pdev
)
979 struct device_node
*np
= pdev
->dev
.of_node
;
980 struct v4l2_of_endpoint ep
;
983 /* Default settings for ISI */
984 isi
->pdata
.full_mode
= 1;
985 isi
->pdata
.frate
= ISI_CFG1_FRATE_CAPTURE_ALL
;
987 np
= of_graph_get_next_endpoint(np
, NULL
);
989 dev_err(&pdev
->dev
, "Could not find the endpoint\n");
993 err
= v4l2_of_parse_endpoint(np
, &ep
);
996 dev_err(&pdev
->dev
, "Could not parse the endpoint\n");
1000 switch (ep
.bus
.parallel
.bus_width
) {
1002 isi
->pdata
.data_width_flags
= ISI_DATAWIDTH_8
;
1005 isi
->pdata
.data_width_flags
=
1006 ISI_DATAWIDTH_8
| ISI_DATAWIDTH_10
;
1009 dev_err(&pdev
->dev
, "Unsupported bus width: %d\n",
1010 ep
.bus
.parallel
.bus_width
);
1014 if (ep
.bus
.parallel
.flags
& V4L2_MBUS_HSYNC_ACTIVE_LOW
)
1015 isi
->pdata
.hsync_act_low
= true;
1016 if (ep
.bus
.parallel
.flags
& V4L2_MBUS_VSYNC_ACTIVE_LOW
)
1017 isi
->pdata
.vsync_act_low
= true;
1018 if (ep
.bus
.parallel
.flags
& V4L2_MBUS_PCLK_SAMPLE_FALLING
)
1019 isi
->pdata
.pclk_act_falling
= true;
1021 if (ep
.bus_type
== V4L2_MBUS_BT656
)
1022 isi
->pdata
.has_emb_sync
= true;
1027 static int atmel_isi_probe(struct platform_device
*pdev
)
1030 struct atmel_isi
*isi
;
1031 struct resource
*regs
;
1033 struct soc_camera_host
*soc_host
;
1035 isi
= devm_kzalloc(&pdev
->dev
, sizeof(struct atmel_isi
), GFP_KERNEL
);
1037 dev_err(&pdev
->dev
, "Can't allocate interface!\n");
1041 isi
->pclk
= devm_clk_get(&pdev
->dev
, "isi_clk");
1042 if (IS_ERR(isi
->pclk
))
1043 return PTR_ERR(isi
->pclk
);
1045 ret
= atmel_isi_parse_dt(isi
, pdev
);
1050 spin_lock_init(&isi
->lock
);
1051 INIT_LIST_HEAD(&isi
->video_buffer_list
);
1052 INIT_LIST_HEAD(&isi
->dma_desc_head
);
1054 isi
->p_fb_descriptors
= dma_alloc_coherent(&pdev
->dev
,
1055 sizeof(struct fbd
) * MAX_BUFFER_NUM
,
1056 &isi
->fb_descriptors_phys
,
1058 if (!isi
->p_fb_descriptors
) {
1059 dev_err(&pdev
->dev
, "Can't allocate descriptors!\n");
1063 for (i
= 0; i
< MAX_BUFFER_NUM
; i
++) {
1064 isi
->dma_desc
[i
].p_fbd
= isi
->p_fb_descriptors
+ i
;
1065 isi
->dma_desc
[i
].fbd_phys
= isi
->fb_descriptors_phys
+
1066 i
* sizeof(struct fbd
);
1067 list_add(&isi
->dma_desc
[i
].list
, &isi
->dma_desc_head
);
1070 isi
->alloc_ctx
= vb2_dma_contig_init_ctx(&pdev
->dev
);
1071 if (IS_ERR(isi
->alloc_ctx
)) {
1072 ret
= PTR_ERR(isi
->alloc_ctx
);
1076 regs
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
1077 isi
->regs
= devm_ioremap_resource(&pdev
->dev
, regs
);
1078 if (IS_ERR(isi
->regs
)) {
1079 ret
= PTR_ERR(isi
->regs
);
1083 if (isi
->pdata
.data_width_flags
& ISI_DATAWIDTH_8
)
1084 isi
->width_flags
= 1 << 7;
1085 if (isi
->pdata
.data_width_flags
& ISI_DATAWIDTH_10
)
1086 isi
->width_flags
|= 1 << 9;
1088 irq
= platform_get_irq(pdev
, 0);
1094 ret
= devm_request_irq(&pdev
->dev
, irq
, isi_interrupt
, 0, "isi", isi
);
1096 dev_err(&pdev
->dev
, "Unable to request irq %d\n", irq
);
1101 soc_host
= &isi
->soc_host
;
1102 soc_host
->drv_name
= "isi-camera";
1103 soc_host
->ops
= &isi_soc_camera_host_ops
;
1104 soc_host
->priv
= isi
;
1105 soc_host
->v4l2_dev
.dev
= &pdev
->dev
;
1106 soc_host
->nr
= pdev
->id
;
1108 pm_suspend_ignore_children(&pdev
->dev
, true);
1109 pm_runtime_enable(&pdev
->dev
);
1111 ret
= soc_camera_host_register(soc_host
);
1113 dev_err(&pdev
->dev
, "Unable to register soc camera host\n");
1114 goto err_register_soc_camera_host
;
1118 err_register_soc_camera_host
:
1119 pm_runtime_disable(&pdev
->dev
);
1122 vb2_dma_contig_cleanup_ctx(isi
->alloc_ctx
);
1124 dma_free_coherent(&pdev
->dev
,
1125 sizeof(struct fbd
) * MAX_BUFFER_NUM
,
1126 isi
->p_fb_descriptors
,
1127 isi
->fb_descriptors_phys
);
1133 static int atmel_isi_runtime_suspend(struct device
*dev
)
1135 struct soc_camera_host
*soc_host
= to_soc_camera_host(dev
);
1136 struct atmel_isi
*isi
= container_of(soc_host
,
1137 struct atmel_isi
, soc_host
);
1139 clk_disable_unprepare(isi
->pclk
);
1143 static int atmel_isi_runtime_resume(struct device
*dev
)
1145 struct soc_camera_host
*soc_host
= to_soc_camera_host(dev
);
1146 struct atmel_isi
*isi
= container_of(soc_host
,
1147 struct atmel_isi
, soc_host
);
1149 return clk_prepare_enable(isi
->pclk
);
1151 #endif /* CONFIG_PM */
1153 static const struct dev_pm_ops atmel_isi_dev_pm_ops
= {
1154 SET_RUNTIME_PM_OPS(atmel_isi_runtime_suspend
,
1155 atmel_isi_runtime_resume
, NULL
)
1158 static const struct of_device_id atmel_isi_of_match
[] = {
1159 { .compatible
= "atmel,at91sam9g45-isi" },
1162 MODULE_DEVICE_TABLE(of
, atmel_isi_of_match
);
1164 static struct platform_driver atmel_isi_driver
= {
1165 .remove
= atmel_isi_remove
,
1167 .name
= "atmel_isi",
1168 .of_match_table
= of_match_ptr(atmel_isi_of_match
),
1169 .pm
= &atmel_isi_dev_pm_ops
,
1173 module_platform_driver_probe(atmel_isi_driver
, atmel_isi_probe
);
1175 MODULE_AUTHOR("Josh Wu <josh.wu@atmel.com>");
1176 MODULE_DESCRIPTION("The V4L2 driver for Atmel Linux");
1177 MODULE_LICENSE("GPL");
1178 MODULE_SUPPORTED_DEVICE("video");