Version:  2.0.40 2.2.26 2.4.37 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7

Linux/drivers/media/platform/soc_camera/atmel-isi.c

  1 /*
  2  * Copyright (c) 2011 Atmel Corporation
  3  * Josh Wu, <josh.wu@atmel.com>
  4  *
  5  * Based on previous work by Lars Haring, <lars.haring@atmel.com>
  6  * and Sedji Gaouaou
  7  * Based on the bttv driver for Bt848 with respective copyright holders
  8  *
  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.
 12  */
 13 
 14 #include <linux/clk.h>
 15 #include <linux/completion.h>
 16 #include <linux/delay.h>
 17 #include <linux/fs.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>
 25 
 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>
 30 
 31 #include "atmel-isi.h"
 32 
 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)
 39 
 40 /* Frame buffer descriptor */
 41 struct fbd {
 42         /* Physical address of the frame buffer */
 43         u32 fb_address;
 44         /* DMA Control Register(only in HISI2) */
 45         u32 dma_ctrl;
 46         /* Physical address of the next fbd */
 47         u32 next_fbd_address;
 48 };
 49 
 50 static void set_dma_ctrl(struct fbd *fb_desc, u32 ctrl)
 51 {
 52         fb_desc->dma_ctrl = ctrl;
 53 }
 54 
 55 struct isi_dma_desc {
 56         struct list_head list;
 57         struct fbd *p_fbd;
 58         dma_addr_t fbd_phys;
 59 };
 60 
 61 /* Frame buffer data */
 62 struct frame_buffer {
 63         struct vb2_v4l2_buffer vb;
 64         struct isi_dma_desc *p_dma_desc;
 65         struct list_head list;
 66 };
 67 
 68 struct atmel_isi {
 69         /* Protects the access of variables shared with the ISR */
 70         spinlock_t                      lock;
 71         void __iomem                    *regs;
 72 
 73         int                             sequence;
 74 
 75         struct vb2_alloc_ctx            *alloc_ctx;
 76 
 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;
 83 
 84         struct completion               complete;
 85         /* ISI peripherial clock */
 86         struct clk                      *pclk;
 87         unsigned int                    irq;
 88 
 89         struct isi_platform_data        pdata;
 90         u16                             width_flags;    /* max 12 bits */
 91 
 92         struct list_head                video_buffer_list;
 93         struct frame_buffer             *active;
 94 
 95         struct soc_camera_host          soc_host;
 96 };
 97 
 98 static void isi_writel(struct atmel_isi *isi, u32 reg, u32 val)
 99 {
100         writel(val, isi->regs + reg);
101 }
102 static u32 isi_readl(struct atmel_isi *isi, u32 reg)
103 {
104         return readl(isi->regs + reg);
105 }
106 
107 static u32 setup_cfg2_yuv_swap(struct atmel_isi *isi,
108                 const struct soc_camera_format_xlate *xlate)
109 {
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;
119                 }
120         } else if (xlate->host_fmt->fourcc == V4L2_PIX_FMT_RGB565) {
121                 /*
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.
125                  */
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;
133                 }
134         }
135 
136         /*
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.
141          */
142         return ISI_CFG2_YCC_SWAP_DEFAULT;
143 }
144 
145 static void configure_geometry(struct atmel_isi *isi, u32 width,
146                 u32 height, const struct soc_camera_format_xlate *xlate)
147 {
148         u32 cfg2, psize;
149         u32 fourcc = xlate->host_fmt->fourcc;
150 
151         isi->enable_preview_path = fourcc == V4L2_PIX_FMT_RGB565 ||
152                                    fourcc == V4L2_PIX_FMT_RGB32;
153 
154         /* According to sensor's output format to set cfg2 */
155         switch (xlate->code) {
156         default:
157         /* Grey */
158         case MEDIA_BUS_FMT_Y8_1X8:
159                 cfg2 = ISI_CFG2_GRAYSCALE | ISI_CFG2_COL_SPACE_YCbCr;
160                 break;
161         /* YUV */
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);
168                 break;
169         /* RGB, TODO */
170         }
171 
172         isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS);
173         /* Set width */
174         cfg2 |= ((width - 1) << ISI_CFG2_IM_HSIZE_OFFSET) &
175                         ISI_CFG2_IM_HSIZE_MASK;
176         /* Set height */
177         cfg2 |= ((height - 1) << ISI_CFG2_IM_VSIZE_OFFSET)
178                         & ISI_CFG2_IM_VSIZE_MASK;
179         isi_writel(isi, ISI_CFG2, cfg2);
180 
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);
188 
189         return;
190 }
191 
192 static bool is_supported(struct soc_camera_device *icd,
193                 const u32 pixformat)
194 {
195         switch (pixformat) {
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:
202         /* RGB */
203         case V4L2_PIX_FMT_RGB565:
204                 return true;
205         default:
206                 return false;
207         }
208 }
209 
210 static irqreturn_t atmel_isi_handle_streaming(struct atmel_isi *isi)
211 {
212         if (isi->active) {
213                 struct vb2_v4l2_buffer *vbuf = &isi->active->vb;
214                 struct frame_buffer *buf = isi->active;
215 
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);
220         }
221 
222         if (list_empty(&isi->video_buffer_list)) {
223                 isi->active = NULL;
224         } else {
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);
234                 } else {
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);
240                 }
241         }
242         return IRQ_HANDLED;
243 }
244 
245 /* ISI interrupt service routine */
246 static irqreturn_t isi_interrupt(int irq, void *dev_id)
247 {
248         struct atmel_isi *isi = dev_id;
249         u32 status, mask, pending;
250         irqreturn_t ret = IRQ_NONE;
251 
252         spin_lock(&isi->lock);
253 
254         status = isi_readl(isi, ISI_STATUS);
255         mask = isi_readl(isi, ISI_INTMASK);
256         pending = status & mask;
257 
258         if (pending & ISI_CTRL_SRST) {
259                 complete(&isi->complete);
260                 isi_writel(isi, ISI_INTDIS, ISI_CTRL_SRST);
261                 ret = IRQ_HANDLED;
262         } else if (pending & ISI_CTRL_DIS) {
263                 complete(&isi->complete);
264                 isi_writel(isi, ISI_INTDIS, ISI_CTRL_DIS);
265                 ret = IRQ_HANDLED;
266         } else {
267                 if (likely(pending & ISI_SR_CXFR_DONE) ||
268                                 likely(pending & ISI_SR_PXFR_DONE))
269                         ret = atmel_isi_handle_streaming(isi);
270         }
271 
272         spin_unlock(&isi->lock);
273         return ret;
274 }
275 
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)
279 {
280         unsigned long timeout;
281         /*
282          * The reset or disable will only succeed if we have a
283          * pixel clock from the camera.
284          */
285         init_completion(&isi->complete);
286 
287         if (wait_reset) {
288                 isi_writel(isi, ISI_INTEN, ISI_CTRL_SRST);
289                 isi_writel(isi, ISI_CTRL, ISI_CTRL_SRST);
290         } else {
291                 isi_writel(isi, ISI_INTEN, ISI_CTRL_DIS);
292                 isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS);
293         }
294 
295         timeout = wait_for_completion_timeout(&isi->complete,
296                         msecs_to_jiffies(500));
297         if (timeout == 0)
298                 return -ETIMEDOUT;
299 
300         return 0;
301 }
302 
303 /* ------------------------------------------------------------------
304         Videobuf operations
305    ------------------------------------------------------------------*/
306 static int queue_setup(struct vb2_queue *vq,
307                                 unsigned int *nbuffers, unsigned int *nplanes,
308                                 unsigned int sizes[], void *alloc_ctxs[])
309 {
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;
313         unsigned long size;
314 
315         size = icd->sizeimage;
316 
317         if (!*nbuffers || *nbuffers > MAX_BUFFER_NUM)
318                 *nbuffers = MAX_BUFFER_NUM;
319 
320         if (size * *nbuffers > VID_LIMIT_BYTES)
321                 *nbuffers = VID_LIMIT_BYTES / size;
322 
323         *nplanes = 1;
324         sizes[0] = size;
325         alloc_ctxs[0] = isi->alloc_ctx;
326 
327         isi->sequence = 0;
328         isi->active = NULL;
329 
330         dev_dbg(icd->parent, "%s, count=%d, size=%ld\n", __func__,
331                 *nbuffers, size);
332 
333         return 0;
334 }
335 
336 static int buffer_init(struct vb2_buffer *vb)
337 {
338         struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
339         struct frame_buffer *buf = container_of(vbuf, struct frame_buffer, vb);
340 
341         buf->p_dma_desc = NULL;
342         INIT_LIST_HEAD(&buf->list);
343 
344         return 0;
345 }
346 
347 static int buffer_prepare(struct vb2_buffer *vb)
348 {
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;
354         unsigned long size;
355         struct isi_dma_desc *desc;
356 
357         size = icd->sizeimage;
358 
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);
362                 return -EINVAL;
363         }
364 
365         vb2_set_plane_payload(vb, 0, size);
366 
367         if (!buf->p_dma_desc) {
368                 if (list_empty(&isi->dma_desc_head)) {
369                         dev_err(icd->parent, "Not enough dma descriptors.\n");
370                         return -EINVAL;
371                 } else {
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);
377 
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);
383 
384                         buf->p_dma_desc = desc;
385                 }
386         }
387         return 0;
388 }
389 
390 static void buffer_cleanup(struct vb2_buffer *vb)
391 {
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);
397 
398         /* This descriptor is available now and we add to head list */
399         if (buf->p_dma_desc)
400                 list_add(&buf->p_dma_desc->list, &isi->dma_desc_head);
401 }
402 
403 static void start_dma(struct atmel_isi *isi, struct frame_buffer *buffer)
404 {
405         u32 ctrl, cfg1;
406 
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);
411 
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");
416                         return;
417                 }
418 
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);
424         } else {
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);
430         }
431 
432         cfg1 &= ~ISI_CFG1_FRATE_DIV_MASK;
433         /* Enable linked list */
434         cfg1 |= isi->pdata.frate | ISI_CFG1_DISCR;
435 
436         /* Enable ISI */
437         ctrl = ISI_CTRL_EN;
438 
439         if (!isi->enable_preview_path)
440                 ctrl |= ISI_CTRL_CDC;
441 
442         isi_writel(isi, ISI_CTRL, ctrl);
443         isi_writel(isi, ISI_CFG1, cfg1);
444 }
445 
446 static void buffer_queue(struct vb2_buffer *vb)
447 {
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;
454 
455         spin_lock_irqsave(&isi->lock, flags);
456         list_add_tail(&buf->list, &isi->video_buffer_list);
457 
458         if (isi->active == NULL) {
459                 isi->active = buf;
460                 if (vb2_is_streaming(vb->vb2_queue))
461                         start_dma(isi, buf);
462         }
463         spin_unlock_irqrestore(&isi->lock, flags);
464 }
465 
466 static int start_streaming(struct vb2_queue *vq, unsigned int count)
467 {
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;
471         int ret;
472 
473         pm_runtime_get_sync(ici->v4l2_dev.dev);
474 
475         /* Reset ISI */
476         ret = atmel_isi_wait_status(isi, WAIT_ISI_RESET);
477         if (ret < 0) {
478                 dev_err(icd->parent, "Reset ISI timed out\n");
479                 pm_runtime_put(ici->v4l2_dev.dev);
480                 return ret;
481         }
482         /* Disable all interrupts */
483         isi_writel(isi, ISI_INTDIS, (u32)~0UL);
484 
485         configure_geometry(isi, icd->user_width, icd->user_height,
486                                 icd->current_fmt);
487 
488         spin_lock_irq(&isi->lock);
489         /* Clear any pending interrupt */
490         isi_readl(isi, ISI_STATUS);
491 
492         if (count)
493                 start_dma(isi, isi->active);
494         spin_unlock_irq(&isi->lock);
495 
496         return 0;
497 }
498 
499 /* abort streaming and wait for last buffer */
500 static void stop_streaming(struct vb2_queue *vq)
501 {
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;
506         int ret = 0;
507         unsigned long timeout;
508 
509         spin_lock_irq(&isi->lock);
510         isi->active = NULL;
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);
515         }
516         spin_unlock_irq(&isi->lock);
517 
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))
523                         msleep(1);
524 
525                 if (time_after(jiffies, timeout))
526                         dev_err(icd->parent,
527                                 "Timeout waiting for finishing codec request\n");
528         }
529 
530         /* Disable interrupts */
531         isi_writel(isi, ISI_INTDIS,
532                         ISI_SR_CXFR_DONE | ISI_SR_PXFR_DONE);
533 
534         /* Disable ISI and wait for it is done */
535         ret = atmel_isi_wait_status(isi, WAIT_ISI_DISABLE);
536         if (ret < 0)
537                 dev_err(icd->parent, "Disable ISI timed out\n");
538 
539         pm_runtime_put(ici->v4l2_dev.dev);
540 }
541 
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,
552 };
553 
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)
559 {
560         struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
561 
562         q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
563         q->io_modes = VB2_MMAP;
564         q->drv_priv = icd;
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;
570 
571         return vb2_queue_init(q);
572 }
573 
574 static int isi_camera_set_fmt(struct soc_camera_device *icd,
575                               struct v4l2_format *f)
576 {
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,
582         };
583         struct v4l2_mbus_framefmt *mf = &format.format;
584         int ret;
585 
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;
589 
590         xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
591         if (!xlate) {
592                 dev_warn(icd->parent, "Format %x not found\n",
593                          pix->pixelformat);
594                 return -EINVAL;
595         }
596 
597         dev_dbg(icd->parent, "Plan to set format %dx%d\n",
598                         pix->width, pix->height);
599 
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;
605 
606         ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &format);
607         if (ret < 0)
608                 return ret;
609 
610         if (mf->code != xlate->code)
611                 return -EINVAL;
612 
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;
618 
619         dev_dbg(icd->parent, "Finally set format %dx%d\n",
620                 pix->width, pix->height);
621 
622         return ret;
623 }
624 
625 static int isi_camera_try_fmt(struct soc_camera_device *icd,
626                               struct v4l2_format *f)
627 {
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,
634         };
635         struct v4l2_mbus_framefmt *mf = &format.format;
636         u32 pixfmt = pix->pixelformat;
637         int ret;
638 
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;
642 
643         xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
644         if (pixfmt && !xlate) {
645                 dev_warn(icd->parent, "Format %x not found\n", pixfmt);
646                 return -EINVAL;
647         }
648 
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;
654 
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;
661 
662         ret = v4l2_subdev_call(sd, pad, set_fmt, &pad_cfg, &format);
663         if (ret < 0)
664                 return ret;
665 
666         pix->width      = mf->width;
667         pix->height     = mf->height;
668         pix->colorspace = mf->colorspace;
669 
670         switch (mf->field) {
671         case V4L2_FIELD_ANY:
672                 pix->field = V4L2_FIELD_NONE;
673                 break;
674         case V4L2_FIELD_NONE:
675                 break;
676         default:
677                 dev_err(icd->parent, "Field type %d unsupported.\n",
678                         mf->field);
679                 ret = -EINVAL;
680         }
681 
682         return ret;
683 }
684 
685 static const struct soc_mbus_pixelfmt isi_camera_formats[] = {
686         {
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,
693         },
694         {
695                 .fourcc                 = V4L2_PIX_FMT_RGB565,
696                 .name                   = "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,
701         },
702 };
703 
704 /* This will be corrected as we get more formats */
705 static bool isi_camera_packing_supported(const struct soc_mbus_pixelfmt *fmt)
706 {
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);
712 }
713 
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)
722 
723 static int isi_camera_try_bus_param(struct soc_camera_device *icd,
724                                     unsigned char buswidth)
725 {
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;
731         int ret;
732 
733         ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
734         if (!ret) {
735                 common_flags = soc_mbus_config_compatible(&cfg,
736                                                           ISI_BUS_PARAM);
737                 if (!common_flags) {
738                         dev_warn(icd->parent,
739                                  "Flags incompatible: camera 0x%x, host 0x%x\n",
740                                  cfg.flags, ISI_BUS_PARAM);
741                         return -EINVAL;
742                 }
743         } else if (ret != -ENOIOCTLCMD) {
744                 return ret;
745         }
746 
747         if ((1 << (buswidth - 1)) & isi->width_flags)
748                 return 0;
749         return -EINVAL;
750 }
751 
752 
753 static int isi_camera_get_formats(struct soc_camera_device *icd,
754                                   unsigned int idx,
755                                   struct soc_camera_format_xlate *xlate)
756 {
757         struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
758         int formats = 0, ret, i, n;
759         /* sensor format */
760         struct v4l2_subdev_mbus_code_enum code = {
761                 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
762                 .index = idx,
763         };
764         /* soc camera host format */
765         const struct soc_mbus_pixelfmt *fmt;
766 
767         ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code);
768         if (ret < 0)
769                 /* No more formats */
770                 return 0;
771 
772         fmt = soc_mbus_get_fmtdesc(code.code);
773         if (!fmt) {
774                 dev_err(icd->parent,
775                         "Invalid format code #%u: %d\n", idx, code.code);
776                 return 0;
777         }
778 
779         /* This also checks support for the requested bits-per-sample */
780         ret = isi_camera_try_bus_param(icd, fmt->bits_per_sample);
781         if (ret < 0) {
782                 dev_err(icd->parent,
783                         "Fail to try the bus parameters.\n");
784                 return 0;
785         }
786 
787         switch (code.code) {
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);
793                 formats += n;
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);
799                 }
800                 break;
801         default:
802                 if (!isi_camera_packing_supported(fmt))
803                         return 0;
804                 if (xlate)
805                         dev_dbg(icd->parent,
806                                 "Providing format %s in pass-through mode\n",
807                                 fmt->name);
808         }
809 
810         /* Generic pass-through */
811         formats++;
812         if (xlate) {
813                 xlate->host_fmt = fmt;
814                 xlate->code     = code.code;
815                 xlate++;
816         }
817 
818         return formats;
819 }
820 
821 static int isi_camera_add_device(struct soc_camera_device *icd)
822 {
823         dev_dbg(icd->parent, "Atmel ISI Camera driver attached to camera %d\n",
824                  icd->devnum);
825 
826         return 0;
827 }
828 
829 static void isi_camera_remove_device(struct soc_camera_device *icd)
830 {
831         dev_dbg(icd->parent, "Atmel ISI Camera driver detached from camera %d\n",
832                  icd->devnum);
833 }
834 
835 static unsigned int isi_camera_poll(struct file *file, poll_table *pt)
836 {
837         struct soc_camera_device *icd = file->private_data;
838 
839         return vb2_poll(&icd->vb2_vidq, file, pt);
840 }
841 
842 static int isi_camera_querycap(struct soc_camera_host *ici,
843                                struct v4l2_capability *cap)
844 {
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;
849 
850         return 0;
851 }
852 
853 static int isi_camera_set_bus_param(struct soc_camera_device *icd)
854 {
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;
860         int ret;
861         u32 cfg1 = 0;
862 
863         ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
864         if (!ret) {
865                 common_flags = soc_mbus_config_compatible(&cfg,
866                                                           ISI_BUS_PARAM);
867                 if (!common_flags) {
868                         dev_warn(icd->parent,
869                                  "Flags incompatible: camera 0x%x, host 0x%x\n",
870                                  cfg.flags, ISI_BUS_PARAM);
871                         return -EINVAL;
872                 }
873         } else if (ret != -ENOIOCTLCMD) {
874                 return ret;
875         } else {
876                 common_flags = ISI_BUS_PARAM;
877         }
878         dev_dbg(icd->parent, "Flags cam: 0x%x host: 0x%x common: 0x%lx\n",
879                 cfg.flags, ISI_BUS_PARAM, common_flags);
880 
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;
886                 else
887                         common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
888         }
889 
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;
894                 else
895                         common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
896         }
897 
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;
902                 else
903                         common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
904         }
905 
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",
910                         common_flags, ret);
911                 return ret;
912         }
913 
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;
921 
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");
926 
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;
931 
932         cfg1 |= ISI_CFG1_THMASK_BEATS_16;
933 
934         /* Enable PM and peripheral clock before operate isi registers */
935         pm_runtime_get_sync(ici->v4l2_dev.dev);
936 
937         isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS);
938         isi_writel(isi, ISI_CFG1, cfg1);
939 
940         pm_runtime_put(ici->v4l2_dev.dev);
941 
942         return 0;
943 }
944 
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,
956 };
957 
958 /* -----------------------------------------------------------------------*/
959 static int atmel_isi_remove(struct platform_device *pdev)
960 {
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);
964 
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);
972 
973         return 0;
974 }
975 
976 static int atmel_isi_parse_dt(struct atmel_isi *isi,
977                         struct platform_device *pdev)
978 {
979         struct device_node *np= pdev->dev.of_node;
980         struct v4l2_of_endpoint ep;
981         int err;
982 
983         /* Default settings for ISI */
984         isi->pdata.full_mode = 1;
985         isi->pdata.frate = ISI_CFG1_FRATE_CAPTURE_ALL;
986 
987         np = of_graph_get_next_endpoint(np, NULL);
988         if (!np) {
989                 dev_err(&pdev->dev, "Could not find the endpoint\n");
990                 return -EINVAL;
991         }
992 
993         err = v4l2_of_parse_endpoint(np, &ep);
994         of_node_put(np);
995         if (err) {
996                 dev_err(&pdev->dev, "Could not parse the endpoint\n");
997                 return err;
998         }
999 
1000         switch (ep.bus.parallel.bus_width) {
1001         case 8:
1002                 isi->pdata.data_width_flags = ISI_DATAWIDTH_8;
1003                 break;
1004         case 10:
1005                 isi->pdata.data_width_flags =
1006                                 ISI_DATAWIDTH_8 | ISI_DATAWIDTH_10;
1007                 break;
1008         default:
1009                 dev_err(&pdev->dev, "Unsupported bus width: %d\n",
1010                                 ep.bus.parallel.bus_width);
1011                 return -EINVAL;
1012         }
1013 
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;
1020 
1021         if (ep.bus_type == V4L2_MBUS_BT656)
1022                 isi->pdata.has_emb_sync = true;
1023 
1024         return 0;
1025 }
1026 
1027 static int atmel_isi_probe(struct platform_device *pdev)
1028 {
1029         int irq;
1030         struct atmel_isi *isi;
1031         struct resource *regs;
1032         int ret, i;
1033         struct soc_camera_host *soc_host;
1034 
1035         isi = devm_kzalloc(&pdev->dev, sizeof(struct atmel_isi), GFP_KERNEL);
1036         if (!isi) {
1037                 dev_err(&pdev->dev, "Can't allocate interface!\n");
1038                 return -ENOMEM;
1039         }
1040 
1041         isi->pclk = devm_clk_get(&pdev->dev, "isi_clk");
1042         if (IS_ERR(isi->pclk))
1043                 return PTR_ERR(isi->pclk);
1044 
1045         ret = atmel_isi_parse_dt(isi, pdev);
1046         if (ret)
1047                 return ret;
1048 
1049         isi->active = NULL;
1050         spin_lock_init(&isi->lock);
1051         INIT_LIST_HEAD(&isi->video_buffer_list);
1052         INIT_LIST_HEAD(&isi->dma_desc_head);
1053 
1054         isi->p_fb_descriptors = dma_alloc_coherent(&pdev->dev,
1055                                 sizeof(struct fbd) * MAX_BUFFER_NUM,
1056                                 &isi->fb_descriptors_phys,
1057                                 GFP_KERNEL);
1058         if (!isi->p_fb_descriptors) {
1059                 dev_err(&pdev->dev, "Can't allocate descriptors!\n");
1060                 return -ENOMEM;
1061         }
1062 
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);
1068         }
1069 
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);
1073                 goto err_alloc_ctx;
1074         }
1075 
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);
1080                 goto err_ioremap;
1081         }
1082 
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;
1087 
1088         irq = platform_get_irq(pdev, 0);
1089         if (irq < 0) {
1090                 ret = irq;
1091                 goto err_req_irq;
1092         }
1093 
1094         ret = devm_request_irq(&pdev->dev, irq, isi_interrupt, 0, "isi", isi);
1095         if (ret) {
1096                 dev_err(&pdev->dev, "Unable to request irq %d\n", irq);
1097                 goto err_req_irq;
1098         }
1099         isi->irq = irq;
1100 
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;
1107 
1108         pm_suspend_ignore_children(&pdev->dev, true);
1109         pm_runtime_enable(&pdev->dev);
1110 
1111         ret = soc_camera_host_register(soc_host);
1112         if (ret) {
1113                 dev_err(&pdev->dev, "Unable to register soc camera host\n");
1114                 goto err_register_soc_camera_host;
1115         }
1116         return 0;
1117 
1118 err_register_soc_camera_host:
1119         pm_runtime_disable(&pdev->dev);
1120 err_req_irq:
1121 err_ioremap:
1122         vb2_dma_contig_cleanup_ctx(isi->alloc_ctx);
1123 err_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);
1128 
1129         return ret;
1130 }
1131 
1132 #ifdef CONFIG_PM
1133 static int atmel_isi_runtime_suspend(struct device *dev)
1134 {
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);
1138 
1139         clk_disable_unprepare(isi->pclk);
1140 
1141         return 0;
1142 }
1143 static int atmel_isi_runtime_resume(struct device *dev)
1144 {
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);
1148 
1149         return clk_prepare_enable(isi->pclk);
1150 }
1151 #endif /* CONFIG_PM */
1152 
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)
1156 };
1157 
1158 static const struct of_device_id atmel_isi_of_match[] = {
1159         { .compatible = "atmel,at91sam9g45-isi" },
1160         { }
1161 };
1162 MODULE_DEVICE_TABLE(of, atmel_isi_of_match);
1163 
1164 static struct platform_driver atmel_isi_driver = {
1165         .remove         = atmel_isi_remove,
1166         .driver         = {
1167                 .name = "atmel_isi",
1168                 .of_match_table = of_match_ptr(atmel_isi_of_match),
1169                 .pm     = &atmel_isi_dev_pm_ops,
1170         },
1171 };
1172 
1173 module_platform_driver_probe(atmel_isi_driver, atmel_isi_probe);
1174 
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");
1179 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us