2011-06-07 22:40:19 -03:00
/*
* Copyright ( c ) 2011 Atmel Corporation
* Josh Wu , < josh . wu @ atmel . com >
*
* Based on previous work by Lars Haring , < lars . haring @ atmel . com >
* and Sedji Gaouaou
* Based on the bttv driver for Bt848 with respective copyright holders
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/clk.h>
# include <linux/completion.h>
# include <linux/delay.h>
# include <linux/fs.h>
# include <linux/init.h>
# include <linux/interrupt.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/platform_device.h>
2015-05-26 06:54:46 -03:00
# include <linux/pm_runtime.h>
2011-06-07 22:40:19 -03:00
# include <linux/slab.h>
# include <media/soc_camera.h>
2015-11-13 19:40:07 -02:00
# include <media/drv-intf/soc_mediabus.h>
2014-07-28 04:25:17 -03:00
# include <media/v4l2-of.h>
2011-06-07 22:40:19 -03:00
# include <media/videobuf2-dma-contig.h>
2015-08-01 06:22:54 -03:00
# include "atmel-isi.h"
2011-06-07 22:40:19 -03:00
# define MAX_BUFFER_NUM 32
# define MAX_SUPPORT_WIDTH 2048
# define MAX_SUPPORT_HEIGHT 2048
# define VID_LIMIT_BYTES (16 * 1024 * 1024)
# define MIN_FRAME_RATE 15
# define FRAME_INTERVAL_MILLI_SEC (1000 / MIN_FRAME_RATE)
/* Frame buffer descriptor */
struct fbd {
/* Physical address of the frame buffer */
u32 fb_address ;
/* DMA Control Register(only in HISI2) */
u32 dma_ctrl ;
/* Physical address of the next fbd */
u32 next_fbd_address ;
} ;
static void set_dma_ctrl ( struct fbd * fb_desc , u32 ctrl )
{
fb_desc - > dma_ctrl = ctrl ;
}
struct isi_dma_desc {
struct list_head list ;
struct fbd * p_fbd ;
2014-08-22 05:52:54 -05:00
dma_addr_t fbd_phys ;
2011-06-07 22:40:19 -03:00
} ;
/* Frame buffer data */
struct frame_buffer {
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
struct vb2_v4l2_buffer vb ;
2011-06-07 22:40:19 -03:00
struct isi_dma_desc * p_dma_desc ;
struct list_head list ;
} ;
struct atmel_isi {
/* Protects the access of variables shared with the ISR */
spinlock_t lock ;
void __iomem * regs ;
int sequence ;
struct vb2_alloc_ctx * alloc_ctx ;
/* Allocate descriptors for dma buffer use */
struct fbd * p_fb_descriptors ;
2014-08-22 05:52:54 -05:00
dma_addr_t fb_descriptors_phys ;
2011-06-07 22:40:19 -03:00
struct list_head dma_desc_head ;
struct isi_dma_desc dma_desc [ MAX_BUFFER_NUM ] ;
2015-11-03 03:45:09 -02:00
bool enable_preview_path ;
2011-06-07 22:40:19 -03:00
struct completion complete ;
2011-12-08 07:18:49 -03:00
/* ISI peripherial clock */
2011-06-07 22:40:19 -03:00
struct clk * pclk ;
unsigned int irq ;
2014-07-25 07:13:39 -03:00
struct isi_platform_data pdata ;
2011-07-27 12:18:37 -03:00
u16 width_flags ; /* max 12 bits */
2011-06-07 22:40:19 -03:00
struct list_head video_buffer_list ;
struct frame_buffer * active ;
struct soc_camera_host soc_host ;
} ;
static void isi_writel ( struct atmel_isi * isi , u32 reg , u32 val )
{
writel ( val , isi - > regs + reg ) ;
}
static u32 isi_readl ( struct atmel_isi * isi , u32 reg )
{
return readl ( isi - > regs + reg ) ;
}
2015-11-03 03:45:08 -02:00
static u32 setup_cfg2_yuv_swap ( struct atmel_isi * isi ,
const struct soc_camera_format_xlate * xlate )
{
if ( xlate - > host_fmt - > fourcc = = V4L2_PIX_FMT_YUYV ) {
/* all convert to YUYV */
switch ( xlate - > code ) {
case MEDIA_BUS_FMT_VYUY8_2X8 :
return ISI_CFG2_YCC_SWAP_MODE_3 ;
case MEDIA_BUS_FMT_UYVY8_2X8 :
return ISI_CFG2_YCC_SWAP_MODE_2 ;
case MEDIA_BUS_FMT_YVYU8_2X8 :
return ISI_CFG2_YCC_SWAP_MODE_1 ;
}
2015-11-03 03:45:11 -02:00
} else if ( xlate - > host_fmt - > fourcc = = V4L2_PIX_FMT_RGB565 ) {
/*
* Preview path is enabled , it will convert UYVY to RGB format .
* But if sensor output format is not UYVY , we need to set
* YCC_SWAP_MODE to convert it as UYVY .
*/
switch ( xlate - > code ) {
case MEDIA_BUS_FMT_VYUY8_2X8 :
return ISI_CFG2_YCC_SWAP_MODE_1 ;
case MEDIA_BUS_FMT_YUYV8_2X8 :
return ISI_CFG2_YCC_SWAP_MODE_2 ;
case MEDIA_BUS_FMT_YVYU8_2X8 :
return ISI_CFG2_YCC_SWAP_MODE_3 ;
}
2015-11-03 03:45:08 -02:00
}
/*
* By default , no swap for the codec path of Atmel ISI . So codec
* output is same as sensor ' s output .
* For instance , if sensor ' s output is YUYV , then codec outputs YUYV .
* And if sensor ' s output is UYVY , then codec outputs UYVY .
*/
return ISI_CFG2_YCC_SWAP_DEFAULT ;
}
2015-09-11 04:00:16 -03:00
static void configure_geometry ( struct atmel_isi * isi , u32 width ,
2015-11-03 03:45:08 -02:00
u32 height , const struct soc_camera_format_xlate * xlate )
2011-06-07 22:40:19 -03:00
{
2015-11-03 03:45:10 -02:00
u32 cfg2 , psize ;
2011-06-07 22:40:19 -03:00
2015-09-11 04:00:14 -03:00
/* According to sensor's output format to set cfg2 */
2015-11-03 03:45:08 -02:00
switch ( xlate - > code ) {
2015-09-11 04:00:16 -03:00
default :
/* Grey */
2014-11-10 14:28:31 -03:00
case MEDIA_BUS_FMT_Y8_1X8 :
2015-09-11 04:00:14 -03:00
cfg2 = ISI_CFG2_GRAYSCALE | ISI_CFG2_COL_SPACE_YCbCr ;
2011-06-07 22:40:19 -03:00
break ;
2015-09-11 04:00:16 -03:00
/* YUV */
2014-11-10 14:28:31 -03:00
case MEDIA_BUS_FMT_VYUY8_2X8 :
case MEDIA_BUS_FMT_UYVY8_2X8 :
case MEDIA_BUS_FMT_YVYU8_2X8 :
case MEDIA_BUS_FMT_YUYV8_2X8 :
2015-11-03 03:45:08 -02:00
cfg2 = ISI_CFG2_COL_SPACE_YCbCr |
setup_cfg2_yuv_swap ( isi , xlate ) ;
2011-06-07 22:40:19 -03:00
break ;
/* RGB, TODO */
}
isi_writel ( isi , ISI_CTRL , ISI_CTRL_DIS ) ;
/* Set width */
cfg2 | = ( ( width - 1 ) < < ISI_CFG2_IM_HSIZE_OFFSET ) &
ISI_CFG2_IM_HSIZE_MASK ;
/* Set height */
cfg2 | = ( ( height - 1 ) < < ISI_CFG2_IM_VSIZE_OFFSET )
& ISI_CFG2_IM_VSIZE_MASK ;
isi_writel ( isi , ISI_CFG2 , cfg2 ) ;
2015-11-03 03:45:10 -02:00
/* No down sampling, preview size equal to sensor output size */
psize = ( ( width - 1 ) < < ISI_PSIZE_PREV_HSIZE_OFFSET ) &
ISI_PSIZE_PREV_HSIZE_MASK ;
psize | = ( ( height - 1 ) < < ISI_PSIZE_PREV_VSIZE_OFFSET ) &
ISI_PSIZE_PREV_VSIZE_MASK ;
isi_writel ( isi , ISI_PSIZE , psize ) ;
isi_writel ( isi , ISI_PDECF , ISI_PDECF_NO_SAMPLING ) ;
return ;
2015-09-11 04:00:16 -03:00
}
2011-06-07 22:40:19 -03:00
2015-09-11 04:00:16 -03:00
static bool is_supported ( struct soc_camera_device * icd ,
const u32 pixformat )
{
switch ( pixformat ) {
/* YUV, including grey */
case V4L2_PIX_FMT_GREY :
case V4L2_PIX_FMT_YUYV :
case V4L2_PIX_FMT_UYVY :
case V4L2_PIX_FMT_YVYU :
case V4L2_PIX_FMT_VYUY :
return true ;
/* RGB, TODO */
default :
return false ;
}
2011-06-07 22:40:19 -03:00
}
static irqreturn_t atmel_isi_handle_streaming ( struct atmel_isi * isi )
{
if ( isi - > active ) {
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
struct vb2_v4l2_buffer * vbuf = & isi - > active - > vb ;
2011-06-07 22:40:19 -03:00
struct frame_buffer * buf = isi - > active ;
list_del_init ( & buf - > list ) ;
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
v4l2_get_timestamp ( & vbuf - > timestamp ) ;
vbuf - > sequence = isi - > sequence + + ;
vb2_buffer_done ( & vbuf - > vb2_buf , VB2_BUF_STATE_DONE ) ;
2011-06-07 22:40:19 -03:00
}
if ( list_empty ( & isi - > video_buffer_list ) ) {
isi - > active = NULL ;
} else {
/* start next dma frame. */
isi - > active = list_entry ( isi - > video_buffer_list . next ,
struct frame_buffer , list ) ;
2015-11-03 03:45:09 -02:00
if ( ! isi - > enable_preview_path ) {
isi_writel ( isi , ISI_DMA_C_DSCR ,
( u32 ) isi - > active - > p_dma_desc - > fbd_phys ) ;
isi_writel ( isi , ISI_DMA_C_CTRL ,
ISI_DMA_CTRL_FETCH | ISI_DMA_CTRL_DONE ) ;
isi_writel ( isi , ISI_DMA_CHER , ISI_DMA_CHSR_C_CH ) ;
} else {
isi_writel ( isi , ISI_DMA_P_DSCR ,
( u32 ) isi - > active - > p_dma_desc - > fbd_phys ) ;
isi_writel ( isi , ISI_DMA_P_CTRL ,
ISI_DMA_CTRL_FETCH | ISI_DMA_CTRL_DONE ) ;
isi_writel ( isi , ISI_DMA_CHER , ISI_DMA_CHSR_P_CH ) ;
}
2011-06-07 22:40:19 -03:00
}
return IRQ_HANDLED ;
}
/* ISI interrupt service routine */
static irqreturn_t isi_interrupt ( int irq , void * dev_id )
{
struct atmel_isi * isi = dev_id ;
u32 status , mask , pending ;
irqreturn_t ret = IRQ_NONE ;
spin_lock ( & isi - > lock ) ;
status = isi_readl ( isi , ISI_STATUS ) ;
mask = isi_readl ( isi , ISI_INTMASK ) ;
pending = status & mask ;
if ( pending & ISI_CTRL_SRST ) {
complete ( & isi - > complete ) ;
isi_writel ( isi , ISI_INTDIS , ISI_CTRL_SRST ) ;
ret = IRQ_HANDLED ;
} else if ( pending & ISI_CTRL_DIS ) {
complete ( & isi - > complete ) ;
isi_writel ( isi , ISI_INTDIS , ISI_CTRL_DIS ) ;
ret = IRQ_HANDLED ;
} else {
2015-11-03 03:45:09 -02:00
if ( likely ( pending & ISI_SR_CXFR_DONE ) | |
likely ( pending & ISI_SR_PXFR_DONE ) )
2011-06-07 22:40:19 -03:00
ret = atmel_isi_handle_streaming ( isi ) ;
}
spin_unlock ( & isi - > lock ) ;
return ret ;
}
# define WAIT_ISI_RESET 1
# define WAIT_ISI_DISABLE 0
static int atmel_isi_wait_status ( struct atmel_isi * isi , int wait_reset )
{
unsigned long timeout ;
/*
* The reset or disable will only succeed if we have a
* pixel clock from the camera .
*/
init_completion ( & isi - > complete ) ;
if ( wait_reset ) {
isi_writel ( isi , ISI_INTEN , ISI_CTRL_SRST ) ;
isi_writel ( isi , ISI_CTRL , ISI_CTRL_SRST ) ;
} else {
isi_writel ( isi , ISI_INTEN , ISI_CTRL_DIS ) ;
isi_writel ( isi , ISI_CTRL , ISI_CTRL_DIS ) ;
}
timeout = wait_for_completion_timeout ( & isi - > complete ,
2015-06-17 07:27:08 -03:00
msecs_to_jiffies ( 500 ) ) ;
2011-06-07 22:40:19 -03:00
if ( timeout = = 0 )
return - ETIMEDOUT ;
return 0 ;
}
/* ------------------------------------------------------------------
Videobuf operations
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2015-10-06 06:37:46 -03:00
static int queue_setup ( struct vb2_queue * vq , const void * parg ,
2011-08-24 10:30:21 -03:00
unsigned int * nbuffers , unsigned int * nplanes ,
unsigned int sizes [ ] , void * alloc_ctxs [ ] )
2011-06-07 22:40:19 -03:00
{
struct soc_camera_device * icd = soc_camera_from_vb2q ( vq ) ;
2011-07-15 20:03:38 -03:00
struct soc_camera_host * ici = to_soc_camera_host ( icd - > parent ) ;
2011-06-07 22:40:19 -03:00
struct atmel_isi * isi = ici - > priv ;
unsigned long size ;
2012-03-21 08:03:21 -03:00
size = icd - > sizeimage ;
2011-06-07 22:40:19 -03:00
if ( ! * nbuffers | | * nbuffers > MAX_BUFFER_NUM )
* nbuffers = MAX_BUFFER_NUM ;
if ( size * * nbuffers > VID_LIMIT_BYTES )
* nbuffers = VID_LIMIT_BYTES / size ;
* nplanes = 1 ;
sizes [ 0 ] = size ;
alloc_ctxs [ 0 ] = isi - > alloc_ctx ;
isi - > sequence = 0 ;
isi - > active = NULL ;
2011-07-15 20:03:38 -03:00
dev_dbg ( icd - > parent , " %s, count=%d, size=%ld \n " , __func__ ,
2011-06-07 22:40:19 -03:00
* nbuffers , size ) ;
return 0 ;
}
static int buffer_init ( struct vb2_buffer * vb )
{
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
struct vb2_v4l2_buffer * vbuf = to_vb2_v4l2_buffer ( vb ) ;
struct frame_buffer * buf = container_of ( vbuf , struct frame_buffer , vb ) ;
2011-06-07 22:40:19 -03:00
buf - > p_dma_desc = NULL ;
INIT_LIST_HEAD ( & buf - > list ) ;
return 0 ;
}
static int buffer_prepare ( struct vb2_buffer * vb )
{
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
struct vb2_v4l2_buffer * vbuf = to_vb2_v4l2_buffer ( vb ) ;
2011-06-07 22:40:19 -03:00
struct soc_camera_device * icd = soc_camera_from_vb2q ( vb - > vb2_queue ) ;
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
struct frame_buffer * buf = container_of ( vbuf , struct frame_buffer , vb ) ;
2011-07-15 20:03:38 -03:00
struct soc_camera_host * ici = to_soc_camera_host ( icd - > parent ) ;
2011-06-07 22:40:19 -03:00
struct atmel_isi * isi = ici - > priv ;
unsigned long size ;
struct isi_dma_desc * desc ;
2012-03-21 08:03:21 -03:00
size = icd - > sizeimage ;
2011-06-07 22:40:19 -03:00
if ( vb2_plane_size ( vb , 0 ) < size ) {
2011-07-15 20:03:38 -03:00
dev_err ( icd - > parent , " %s data will not fit into plane (%lu < %lu) \n " ,
2011-06-07 22:40:19 -03:00
__func__ , vb2_plane_size ( vb , 0 ) , size ) ;
return - EINVAL ;
}
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
vb2_set_plane_payload ( vb , 0 , size ) ;
2011-06-07 22:40:19 -03:00
if ( ! buf - > p_dma_desc ) {
if ( list_empty ( & isi - > dma_desc_head ) ) {
2011-07-15 20:03:38 -03:00
dev_err ( icd - > parent , " Not enough dma descriptors. \n " ) ;
2011-06-07 22:40:19 -03:00
return - EINVAL ;
} else {
/* Get an available descriptor */
desc = list_entry ( isi - > dma_desc_head . next ,
struct isi_dma_desc , list ) ;
/* Delete the descriptor since now it is used */
list_del_init ( & desc - > list ) ;
/* Initialize the dma descriptor */
desc - > p_fbd - > fb_address =
2011-08-29 03:20:56 -03:00
vb2_dma_contig_plane_dma_addr ( vb , 0 ) ;
2011-06-07 22:40:19 -03:00
desc - > p_fbd - > next_fbd_address = 0 ;
set_dma_ctrl ( desc - > p_fbd , ISI_DMA_CTRL_WB ) ;
buf - > p_dma_desc = desc ;
}
}
return 0 ;
}
static void buffer_cleanup ( struct vb2_buffer * vb )
{
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
struct vb2_v4l2_buffer * vbuf = to_vb2_v4l2_buffer ( vb ) ;
2011-06-07 22:40:19 -03:00
struct soc_camera_device * icd = soc_camera_from_vb2q ( vb - > vb2_queue ) ;
2011-07-15 20:03:38 -03:00
struct soc_camera_host * ici = to_soc_camera_host ( icd - > parent ) ;
2011-06-07 22:40:19 -03:00
struct atmel_isi * isi = ici - > priv ;
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
struct frame_buffer * buf = container_of ( vbuf , struct frame_buffer , vb ) ;
2011-06-07 22:40:19 -03:00
/* This descriptor is available now and we add to head list */
if ( buf - > p_dma_desc )
list_add ( & buf - > p_dma_desc - > list , & isi - > dma_desc_head ) ;
}
static void start_dma ( struct atmel_isi * isi , struct frame_buffer * buffer )
{
u32 ctrl , cfg1 ;
cfg1 = isi_readl ( isi , ISI_CFG1 ) ;
/* Enable irq: cxfr for the codec path, pxfr for the preview path */
isi_writel ( isi , ISI_INTEN ,
ISI_SR_CXFR_DONE | ISI_SR_PXFR_DONE ) ;
/* Check if already in a frame */
2015-11-03 03:45:09 -02:00
if ( ! isi - > enable_preview_path ) {
if ( isi_readl ( isi , ISI_STATUS ) & ISI_CTRL_CDC ) {
dev_err ( isi - > soc_host . icd - > parent , " Already in frame handling. \n " ) ;
return ;
}
2011-06-07 22:40:19 -03:00
2015-11-03 03:45:09 -02:00
isi_writel ( isi , ISI_DMA_C_DSCR ,
( u32 ) buffer - > p_dma_desc - > fbd_phys ) ;
isi_writel ( isi , ISI_DMA_C_CTRL ,
ISI_DMA_CTRL_FETCH | ISI_DMA_CTRL_DONE ) ;
isi_writel ( isi , ISI_DMA_CHER , ISI_DMA_CHSR_C_CH ) ;
} else {
isi_writel ( isi , ISI_DMA_P_DSCR ,
( u32 ) buffer - > p_dma_desc - > fbd_phys ) ;
isi_writel ( isi , ISI_DMA_P_CTRL ,
ISI_DMA_CTRL_FETCH | ISI_DMA_CTRL_DONE ) ;
isi_writel ( isi , ISI_DMA_CHER , ISI_DMA_CHSR_P_CH ) ;
}
2011-06-07 22:40:19 -03:00
2013-12-10 09:25:47 -03:00
cfg1 & = ~ ISI_CFG1_FRATE_DIV_MASK ;
2011-06-07 22:40:19 -03:00
/* Enable linked list */
2014-07-25 07:13:39 -03:00
cfg1 | = isi - > pdata . frate | ISI_CFG1_DISCR ;
2011-06-07 22:40:19 -03:00
2015-11-03 03:45:09 -02:00
/* Enable ISI */
ctrl = ISI_CTRL_EN ;
if ( ! isi - > enable_preview_path )
ctrl | = ISI_CTRL_CDC ;
2011-06-07 22:40:19 -03:00
isi_writel ( isi , ISI_CTRL , ctrl ) ;
isi_writel ( isi , ISI_CFG1 , cfg1 ) ;
}
static void buffer_queue ( struct vb2_buffer * vb )
{
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
struct vb2_v4l2_buffer * vbuf = to_vb2_v4l2_buffer ( vb ) ;
2011-06-07 22:40:19 -03:00
struct soc_camera_device * icd = soc_camera_from_vb2q ( vb - > vb2_queue ) ;
2011-07-15 20:03:38 -03:00
struct soc_camera_host * ici = to_soc_camera_host ( icd - > parent ) ;
2011-06-07 22:40:19 -03:00
struct atmel_isi * isi = ici - > priv ;
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
struct frame_buffer * buf = container_of ( vbuf , struct frame_buffer , vb ) ;
2011-06-07 22:40:19 -03:00
unsigned long flags = 0 ;
spin_lock_irqsave ( & isi - > lock , flags ) ;
list_add_tail ( & buf - > list , & isi - > video_buffer_list ) ;
if ( isi - > active = = NULL ) {
isi - > active = buf ;
2011-08-29 08:51:49 -03:00
if ( vb2_is_streaming ( vb - > vb2_queue ) )
start_dma ( isi , buf ) ;
2011-06-07 22:40:19 -03:00
}
spin_unlock_irqrestore ( & isi - > lock , flags ) ;
}
2011-08-29 08:51:49 -03:00
static int start_streaming ( struct vb2_queue * vq , unsigned int count )
2011-06-07 22:40:19 -03:00
{
struct soc_camera_device * icd = soc_camera_from_vb2q ( vq ) ;
2011-07-15 20:03:38 -03:00
struct soc_camera_host * ici = to_soc_camera_host ( icd - > parent ) ;
2011-06-07 22:40:19 -03:00
struct atmel_isi * isi = ici - > priv ;
2013-11-02 21:25:06 -03:00
int ret ;
2015-05-26 06:54:46 -03:00
pm_runtime_get_sync ( ici - > v4l2_dev . dev ) ;
2013-11-02 21:25:06 -03:00
/* Reset ISI */
ret = atmel_isi_wait_status ( isi , WAIT_ISI_RESET ) ;
if ( ret < 0 ) {
dev_err ( icd - > parent , " Reset ISI timed out \n " ) ;
2015-05-26 06:54:46 -03:00
pm_runtime_put ( ici - > v4l2_dev . dev ) ;
2013-11-02 21:25:06 -03:00
return ret ;
}
/* Disable all interrupts */
2014-08-22 05:53:27 -05:00
isi_writel ( isi , ISI_INTDIS , ( u32 ) ~ 0UL ) ;
2011-06-07 22:40:19 -03:00
2015-09-11 04:00:16 -03:00
configure_geometry ( isi , icd - > user_width , icd - > user_height ,
2015-11-03 03:45:08 -02:00
icd - > current_fmt ) ;
2015-09-11 04:00:15 -03:00
2011-06-07 22:40:19 -03:00
spin_lock_irq ( & isi - > lock ) ;
2013-10-24 04:27:11 -03:00
/* Clear any pending interrupt */
2014-08-26 11:21:43 -03:00
isi_readl ( isi , ISI_STATUS ) ;
2011-06-07 22:40:19 -03:00
2011-08-29 08:51:49 -03:00
if ( count )
start_dma ( isi , isi - > active ) ;
2011-06-07 22:40:19 -03:00
spin_unlock_irq ( & isi - > lock ) ;
return 0 ;
}
/* abort streaming and wait for last buffer */
2014-04-17 02:47:21 -03:00
static void stop_streaming ( struct vb2_queue * vq )
2011-06-07 22:40:19 -03:00
{
struct soc_camera_device * icd = soc_camera_from_vb2q ( vq ) ;
2011-07-15 20:03:38 -03:00
struct soc_camera_host * ici = to_soc_camera_host ( icd - > parent ) ;
2011-06-07 22:40:19 -03:00
struct atmel_isi * isi = ici - > priv ;
struct frame_buffer * buf , * node ;
int ret = 0 ;
unsigned long timeout ;
spin_lock_irq ( & isi - > lock ) ;
isi - > active = NULL ;
/* Release all active buffers */
list_for_each_entry_safe ( buf , node , & isi - > video_buffer_list , list ) {
list_del_init ( & buf - > list ) ;
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
vb2_buffer_done ( & buf - > vb . vb2_buf , VB2_BUF_STATE_ERROR ) ;
2011-06-07 22:40:19 -03:00
}
spin_unlock_irq ( & isi - > lock ) ;
2015-11-03 03:45:09 -02:00
if ( ! isi - > enable_preview_path ) {
timeout = jiffies + FRAME_INTERVAL_MILLI_SEC * HZ ;
/* Wait until the end of the current frame. */
while ( ( isi_readl ( isi , ISI_STATUS ) & ISI_CTRL_CDC ) & &
time_before ( jiffies , timeout ) )
msleep ( 1 ) ;
2011-06-07 22:40:19 -03:00
2015-11-03 03:45:09 -02:00
if ( time_after ( jiffies , timeout ) )
dev_err ( icd - > parent ,
" Timeout waiting for finishing codec request \n " ) ;
}
2011-06-07 22:40:19 -03:00
/* Disable interrupts */
isi_writel ( isi , ISI_INTDIS ,
ISI_SR_CXFR_DONE | ISI_SR_PXFR_DONE ) ;
/* Disable ISI and wait for it is done */
ret = atmel_isi_wait_status ( isi , WAIT_ISI_DISABLE ) ;
if ( ret < 0 )
2011-07-15 20:03:38 -03:00
dev_err ( icd - > parent , " Disable ISI timed out \n " ) ;
2015-05-26 06:54:46 -03:00
pm_runtime_put ( ici - > v4l2_dev . dev ) ;
2011-06-07 22:40:19 -03:00
}
static struct vb2_ops isi_video_qops = {
. queue_setup = queue_setup ,
. buf_init = buffer_init ,
. buf_prepare = buffer_prepare ,
. buf_cleanup = buffer_cleanup ,
. buf_queue = buffer_queue ,
. start_streaming = start_streaming ,
. stop_streaming = stop_streaming ,
2014-11-26 19:42:27 -03:00
. wait_prepare = vb2_ops_wait_prepare ,
. wait_finish = vb2_ops_wait_finish ,
2011-06-07 22:40:19 -03:00
} ;
/* ------------------------------------------------------------------
SOC camera operations for the device
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
static int isi_camera_init_videobuf ( struct vb2_queue * q ,
struct soc_camera_device * icd )
{
2014-11-26 19:42:27 -03:00
struct soc_camera_host * ici = to_soc_camera_host ( icd - > parent ) ;
2011-06-07 22:40:19 -03:00
q - > type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
q - > io_modes = VB2_MMAP ;
q - > drv_priv = icd ;
q - > buf_struct_size = sizeof ( struct frame_buffer ) ;
q - > ops = & isi_video_qops ;
q - > mem_ops = & vb2_dma_contig_memops ;
2014-02-25 19:12:19 -03:00
q - > timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC ;
2014-11-26 19:42:27 -03:00
q - > lock = & ici - > host_lock ;
2011-06-07 22:40:19 -03:00
return vb2_queue_init ( q ) ;
}
static int isi_camera_set_fmt ( struct soc_camera_device * icd ,
struct v4l2_format * f )
{
struct v4l2_subdev * sd = soc_camera_to_subdev ( icd ) ;
const struct soc_camera_format_xlate * xlate ;
struct v4l2_pix_format * pix = & f - > fmt . pix ;
2015-04-09 04:05:59 -03:00
struct v4l2_subdev_format format = {
. which = V4L2_SUBDEV_FORMAT_ACTIVE ,
} ;
struct v4l2_mbus_framefmt * mf = & format . format ;
2011-06-07 22:40:19 -03:00
int ret ;
2015-09-11 04:00:16 -03:00
/* check with atmel-isi support format, if not support use YUYV */
if ( ! is_supported ( icd , pix - > pixelformat ) )
pix - > pixelformat = V4L2_PIX_FMT_YUYV ;
2011-06-07 22:40:19 -03:00
xlate = soc_camera_xlate_by_fourcc ( icd , pix - > pixelformat ) ;
if ( ! xlate ) {
2011-07-15 20:03:38 -03:00
dev_warn ( icd - > parent , " Format %x not found \n " ,
2011-06-07 22:40:19 -03:00
pix - > pixelformat ) ;
return - EINVAL ;
}
2011-07-15 20:03:38 -03:00
dev_dbg ( icd - > parent , " Plan to set format %dx%d \n " ,
2011-06-07 22:40:19 -03:00
pix - > width , pix - > height ) ;
2015-04-09 04:05:59 -03:00
mf - > width = pix - > width ;
mf - > height = pix - > height ;
mf - > field = pix - > field ;
mf - > colorspace = pix - > colorspace ;
mf - > code = xlate - > code ;
2011-06-07 22:40:19 -03:00
2015-04-09 04:05:59 -03:00
ret = v4l2_subdev_call ( sd , pad , set_fmt , NULL , & format ) ;
2011-06-07 22:40:19 -03:00
if ( ret < 0 )
return ret ;
2015-04-09 04:05:59 -03:00
if ( mf - > code ! = xlate - > code )
2011-06-07 22:40:19 -03:00
return - EINVAL ;
2015-04-09 04:05:59 -03:00
pix - > width = mf - > width ;
pix - > height = mf - > height ;
pix - > field = mf - > field ;
pix - > colorspace = mf - > colorspace ;
2011-06-07 22:40:19 -03:00
icd - > current_fmt = xlate ;
2011-07-15 20:03:38 -03:00
dev_dbg ( icd - > parent , " Finally set format %dx%d \n " ,
2011-06-07 22:40:19 -03:00
pix - > width , pix - > height ) ;
return ret ;
}
static int isi_camera_try_fmt ( struct soc_camera_device * icd ,
struct v4l2_format * f )
{
struct v4l2_subdev * sd = soc_camera_to_subdev ( icd ) ;
const struct soc_camera_format_xlate * xlate ;
struct v4l2_pix_format * pix = & f - > fmt . pix ;
2015-04-09 04:05:35 -03:00
struct v4l2_subdev_pad_config pad_cfg ;
struct v4l2_subdev_format format = {
. which = V4L2_SUBDEV_FORMAT_TRY ,
} ;
struct v4l2_mbus_framefmt * mf = & format . format ;
2011-06-07 22:40:19 -03:00
u32 pixfmt = pix - > pixelformat ;
int ret ;
2015-09-11 04:00:16 -03:00
/* check with atmel-isi support format, if not support use YUYV */
if ( ! is_supported ( icd , pix - > pixelformat ) )
pix - > pixelformat = V4L2_PIX_FMT_YUYV ;
2011-06-07 22:40:19 -03:00
xlate = soc_camera_xlate_by_fourcc ( icd , pixfmt ) ;
if ( pixfmt & & ! xlate ) {
2011-07-15 20:03:38 -03:00
dev_warn ( icd - > parent , " Format %x not found \n " , pixfmt ) ;
2011-06-07 22:40:19 -03:00
return - EINVAL ;
}
/* limit to Atmel ISI hardware capabilities */
if ( pix - > height > MAX_SUPPORT_HEIGHT )
pix - > height = MAX_SUPPORT_HEIGHT ;
if ( pix - > width > MAX_SUPPORT_WIDTH )
pix - > width = MAX_SUPPORT_WIDTH ;
/* limit to sensor capabilities */
2015-04-09 04:05:35 -03:00
mf - > width = pix - > width ;
mf - > height = pix - > height ;
mf - > field = pix - > field ;
mf - > colorspace = pix - > colorspace ;
mf - > code = xlate - > code ;
2011-06-07 22:40:19 -03:00
2015-04-09 04:05:35 -03:00
ret = v4l2_subdev_call ( sd , pad , set_fmt , & pad_cfg , & format ) ;
2011-06-07 22:40:19 -03:00
if ( ret < 0 )
return ret ;
2015-04-09 04:05:35 -03:00
pix - > width = mf - > width ;
pix - > height = mf - > height ;
pix - > colorspace = mf - > colorspace ;
2011-06-07 22:40:19 -03:00
2015-04-09 04:05:35 -03:00
switch ( mf - > field ) {
2011-06-07 22:40:19 -03:00
case V4L2_FIELD_ANY :
pix - > field = V4L2_FIELD_NONE ;
break ;
case V4L2_FIELD_NONE :
break ;
default :
2011-07-15 20:03:38 -03:00
dev_err ( icd - > parent , " Field type %d unsupported. \n " ,
2015-04-09 04:05:35 -03:00
mf - > field ) ;
2011-06-07 22:40:19 -03:00
ret = - EINVAL ;
}
return ret ;
}
static const struct soc_mbus_pixelfmt isi_camera_formats [ ] = {
{
. fourcc = V4L2_PIX_FMT_YUYV ,
. name = " Packed YUV422 16 bit " ,
. bits_per_sample = 8 ,
. packing = SOC_MBUS_PACKING_2X8_PADHI ,
. order = SOC_MBUS_ORDER_LE ,
2012-03-21 08:03:23 -03:00
. layout = SOC_MBUS_LAYOUT_PACKED ,
2011-06-07 22:40:19 -03:00
} ,
} ;
/* This will be corrected as we get more formats */
static bool isi_camera_packing_supported ( const struct soc_mbus_pixelfmt * fmt )
{
return fmt - > packing = = SOC_MBUS_PACKING_NONE | |
( fmt - > bits_per_sample = = 8 & &
fmt - > packing = = SOC_MBUS_PACKING_2X8_PADHI ) | |
( fmt - > bits_per_sample > 8 & &
fmt - > packing = = SOC_MBUS_PACKING_EXTEND16 ) ;
}
2011-07-27 12:18:37 -03:00
# define ISI_BUS_PARAM (V4L2_MBUS_MASTER | \
V4L2_MBUS_HSYNC_ACTIVE_HIGH | \
V4L2_MBUS_HSYNC_ACTIVE_LOW | \
V4L2_MBUS_VSYNC_ACTIVE_HIGH | \
V4L2_MBUS_VSYNC_ACTIVE_LOW | \
V4L2_MBUS_PCLK_SAMPLE_RISING | \
V4L2_MBUS_PCLK_SAMPLE_FALLING | \
V4L2_MBUS_DATA_ACTIVE_HIGH )
2011-06-07 22:40:19 -03:00
static int isi_camera_try_bus_param ( struct soc_camera_device * icd ,
unsigned char buswidth )
{
2011-07-27 12:18:37 -03:00
struct v4l2_subdev * sd = soc_camera_to_subdev ( icd ) ;
2011-07-15 20:03:38 -03:00
struct soc_camera_host * ici = to_soc_camera_host ( icd - > parent ) ;
2011-06-07 22:40:19 -03:00
struct atmel_isi * isi = ici - > priv ;
2011-07-27 12:18:37 -03:00
struct v4l2_mbus_config cfg = { . type = V4L2_MBUS_PARALLEL , } ;
unsigned long common_flags ;
2011-06-07 22:40:19 -03:00
int ret ;
2011-07-27 12:18:37 -03:00
ret = v4l2_subdev_call ( sd , video , g_mbus_config , & cfg ) ;
if ( ! ret ) {
common_flags = soc_mbus_config_compatible ( & cfg ,
ISI_BUS_PARAM ) ;
if ( ! common_flags ) {
dev_warn ( icd - > parent ,
" Flags incompatible: camera 0x%x, host 0x%x \n " ,
cfg . flags , ISI_BUS_PARAM ) ;
return - EINVAL ;
}
} else if ( ret ! = - ENOIOCTLCMD ) {
return ret ;
}
if ( ( 1 < < ( buswidth - 1 ) ) & isi - > width_flags )
return 0 ;
return - EINVAL ;
2011-06-07 22:40:19 -03:00
}
static int isi_camera_get_formats ( struct soc_camera_device * icd ,
unsigned int idx ,
struct soc_camera_format_xlate * xlate )
{
struct v4l2_subdev * sd = soc_camera_to_subdev ( icd ) ;
int formats = 0 , ret ;
/* sensor format */
2015-04-09 04:01:33 -03:00
struct v4l2_subdev_mbus_code_enum code = {
. which = V4L2_SUBDEV_FORMAT_ACTIVE ,
. index = idx ,
} ;
2011-06-07 22:40:19 -03:00
/* soc camera host format */
const struct soc_mbus_pixelfmt * fmt ;
2015-04-09 04:01:33 -03:00
ret = v4l2_subdev_call ( sd , pad , enum_mbus_code , NULL , & code ) ;
2011-06-07 22:40:19 -03:00
if ( ret < 0 )
/* No more formats */
return 0 ;
2015-04-09 04:01:33 -03:00
fmt = soc_mbus_get_fmtdesc ( code . code ) ;
2011-06-07 22:40:19 -03:00
if ( ! fmt ) {
2011-07-15 20:03:38 -03:00
dev_err ( icd - > parent ,
2015-04-09 04:01:33 -03:00
" Invalid format code #%u: %d \n " , idx , code . code ) ;
2011-06-07 22:40:19 -03:00
return 0 ;
}
/* This also checks support for the requested bits-per-sample */
ret = isi_camera_try_bus_param ( icd , fmt - > bits_per_sample ) ;
if ( ret < 0 ) {
2011-07-15 20:03:38 -03:00
dev_err ( icd - > parent ,
2011-06-07 22:40:19 -03:00
" Fail to try the bus parameters. \n " ) ;
return 0 ;
}
2015-04-09 04:01:33 -03:00
switch ( code . code ) {
2014-11-10 14:28:31 -03:00
case MEDIA_BUS_FMT_UYVY8_2X8 :
case MEDIA_BUS_FMT_VYUY8_2X8 :
case MEDIA_BUS_FMT_YUYV8_2X8 :
case MEDIA_BUS_FMT_YVYU8_2X8 :
2011-06-07 22:40:19 -03:00
formats + + ;
if ( xlate ) {
xlate - > host_fmt = & isi_camera_formats [ 0 ] ;
2015-04-09 04:01:33 -03:00
xlate - > code = code . code ;
2011-06-07 22:40:19 -03:00
xlate + + ;
2011-07-15 20:03:38 -03:00
dev_dbg ( icd - > parent , " Providing format %s using code %d \n " ,
2015-04-09 04:01:33 -03:00
isi_camera_formats [ 0 ] . name , code . code ) ;
2011-06-07 22:40:19 -03:00
}
break ;
default :
if ( ! isi_camera_packing_supported ( fmt ) )
return 0 ;
if ( xlate )
2011-07-15 20:03:38 -03:00
dev_dbg ( icd - > parent ,
2011-06-07 22:40:19 -03:00
" Providing format %s in pass-through mode \n " ,
fmt - > name ) ;
}
/* Generic pass-through */
formats + + ;
if ( xlate ) {
xlate - > host_fmt = fmt ;
2015-04-09 04:01:33 -03:00
xlate - > code = code . code ;
2011-06-07 22:40:19 -03:00
xlate + + ;
}
return formats ;
}
static int isi_camera_add_device ( struct soc_camera_device * icd )
{
2013-04-04 09:56:09 -03:00
dev_dbg ( icd - > parent , " Atmel ISI Camera driver attached to camera %d \n " ,
icd - > devnum ) ;
return 0 ;
}
static void isi_camera_remove_device ( struct soc_camera_device * icd )
{
dev_dbg ( icd - > parent , " Atmel ISI Camera driver detached from camera %d \n " ,
icd - > devnum ) ;
}
2011-06-07 22:40:19 -03:00
static unsigned int isi_camera_poll ( struct file * file , poll_table * pt )
{
struct soc_camera_device * icd = file - > private_data ;
return vb2_poll ( & icd - > vb2_vidq , file , pt ) ;
}
static int isi_camera_querycap ( struct soc_camera_host * ici ,
struct v4l2_capability * cap )
{
strcpy ( cap - > driver , " atmel-isi " ) ;
strcpy ( cap - > card , " Atmel Image Sensor Interface " ) ;
2015-01-18 16:30:11 -03:00
cap - > device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING ;
cap - > capabilities = cap - > device_caps | V4L2_CAP_DEVICE_CAPS ;
2011-06-07 22:40:19 -03:00
return 0 ;
}
2011-09-21 17:52:51 -03:00
static int isi_camera_set_bus_param ( struct soc_camera_device * icd )
2011-06-07 22:40:19 -03:00
{
2011-07-27 12:18:37 -03:00
struct v4l2_subdev * sd = soc_camera_to_subdev ( icd ) ;
2011-07-15 20:03:38 -03:00
struct soc_camera_host * ici = to_soc_camera_host ( icd - > parent ) ;
2011-06-07 22:40:19 -03:00
struct atmel_isi * isi = ici - > priv ;
2011-07-27 12:18:37 -03:00
struct v4l2_mbus_config cfg = { . type = V4L2_MBUS_PARALLEL , } ;
unsigned long common_flags ;
2011-06-07 22:40:19 -03:00
int ret ;
u32 cfg1 = 0 ;
2011-07-27 12:18:37 -03:00
ret = v4l2_subdev_call ( sd , video , g_mbus_config , & cfg ) ;
if ( ! ret ) {
common_flags = soc_mbus_config_compatible ( & cfg ,
ISI_BUS_PARAM ) ;
if ( ! common_flags ) {
dev_warn ( icd - > parent ,
" Flags incompatible: camera 0x%x, host 0x%x \n " ,
cfg . flags , ISI_BUS_PARAM ) ;
return - EINVAL ;
}
} else if ( ret ! = - ENOIOCTLCMD ) {
return ret ;
} else {
common_flags = ISI_BUS_PARAM ;
}
dev_dbg ( icd - > parent , " Flags cam: 0x%x host: 0x%x common: 0x%lx \n " ,
cfg . flags , ISI_BUS_PARAM , common_flags ) ;
2011-06-07 22:40:19 -03:00
/* Make choises, based on platform preferences */
2011-07-27 12:18:37 -03:00
if ( ( common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH ) & &
( common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW ) ) {
2014-07-25 07:13:39 -03:00
if ( isi - > pdata . hsync_act_low )
2011-07-27 12:18:37 -03:00
common_flags & = ~ V4L2_MBUS_HSYNC_ACTIVE_HIGH ;
2011-06-07 22:40:19 -03:00
else
2011-07-27 12:18:37 -03:00
common_flags & = ~ V4L2_MBUS_HSYNC_ACTIVE_LOW ;
2011-06-07 22:40:19 -03:00
}
2011-07-27 12:18:37 -03:00
if ( ( common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH ) & &
( common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW ) ) {
2014-07-25 07:13:39 -03:00
if ( isi - > pdata . vsync_act_low )
2011-07-27 12:18:37 -03:00
common_flags & = ~ V4L2_MBUS_VSYNC_ACTIVE_HIGH ;
2011-06-07 22:40:19 -03:00
else
2011-07-27 12:18:37 -03:00
common_flags & = ~ V4L2_MBUS_VSYNC_ACTIVE_LOW ;
2011-06-07 22:40:19 -03:00
}
2011-07-27 12:18:37 -03:00
if ( ( common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING ) & &
( common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING ) ) {
2014-07-25 07:13:39 -03:00
if ( isi - > pdata . pclk_act_falling )
2011-07-27 12:18:37 -03:00
common_flags & = ~ V4L2_MBUS_PCLK_SAMPLE_RISING ;
2011-06-07 22:40:19 -03:00
else
2011-07-27 12:18:37 -03:00
common_flags & = ~ V4L2_MBUS_PCLK_SAMPLE_FALLING ;
2011-06-07 22:40:19 -03:00
}
2011-07-27 12:18:37 -03:00
cfg . flags = common_flags ;
ret = v4l2_subdev_call ( sd , video , s_mbus_config , & cfg ) ;
if ( ret < 0 & & ret ! = - ENOIOCTLCMD ) {
dev_dbg ( icd - > parent , " camera s_mbus_config(0x%lx) returned %d \n " ,
2011-06-07 22:40:19 -03:00
common_flags , ret ) ;
return ret ;
}
/* set bus param for ISI */
2011-07-27 12:18:37 -03:00
if ( common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW )
2011-06-07 22:40:19 -03:00
cfg1 | = ISI_CFG1_HSYNC_POL_ACTIVE_LOW ;
2011-07-27 12:18:37 -03:00
if ( common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW )
2011-06-07 22:40:19 -03:00
cfg1 | = ISI_CFG1_VSYNC_POL_ACTIVE_LOW ;
2011-07-27 12:18:37 -03:00
if ( common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING )
2011-06-07 22:40:19 -03:00
cfg1 | = ISI_CFG1_PIXCLK_POL_ACTIVE_FALLING ;
2015-08-04 06:37:49 -03:00
dev_dbg ( icd - > parent , " vsync active %s, hsync active %s, sampling on pix clock %s edge \n " ,
common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW ? " low " : " high " ,
common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW ? " low " : " high " ,
common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING ? " falling " : " rising " ) ;
2014-07-25 07:13:39 -03:00
if ( isi - > pdata . has_emb_sync )
2011-06-07 22:40:19 -03:00
cfg1 | = ISI_CFG1_EMB_SYNC ;
2014-07-25 07:13:39 -03:00
if ( isi - > pdata . full_mode )
2011-06-07 22:40:19 -03:00
cfg1 | = ISI_CFG1_FULL_MODE ;
2014-11-25 06:30:25 -03:00
cfg1 | = ISI_CFG1_THMASK_BEATS_16 ;
2015-05-26 06:54:46 -03:00
/* Enable PM and peripheral clock before operate isi registers */
pm_runtime_get_sync ( ici - > v4l2_dev . dev ) ;
2011-06-07 22:40:19 -03:00
isi_writel ( isi , ISI_CTRL , ISI_CTRL_DIS ) ;
isi_writel ( isi , ISI_CFG1 , cfg1 ) ;
2015-05-26 06:54:46 -03:00
pm_runtime_put ( ici - > v4l2_dev . dev ) ;
2011-06-07 22:40:19 -03:00
return 0 ;
}
static struct soc_camera_host_ops isi_soc_camera_host_ops = {
. owner = THIS_MODULE ,
. add = isi_camera_add_device ,
. remove = isi_camera_remove_device ,
. set_fmt = isi_camera_set_fmt ,
. try_fmt = isi_camera_try_fmt ,
. get_formats = isi_camera_get_formats ,
. init_videobuf2 = isi_camera_init_videobuf ,
. poll = isi_camera_poll ,
. querycap = isi_camera_querycap ,
. set_bus_param = isi_camera_set_bus_param ,
} ;
/* -----------------------------------------------------------------------*/
2012-12-21 13:17:53 -08:00
static int atmel_isi_remove ( struct platform_device * pdev )
2011-06-07 22:40:19 -03:00
{
struct soc_camera_host * soc_host = to_soc_camera_host ( & pdev - > dev ) ;
struct atmel_isi * isi = container_of ( soc_host ,
struct atmel_isi , soc_host ) ;
soc_camera_host_unregister ( soc_host ) ;
vb2_dma_contig_cleanup_ctx ( isi - > alloc_ctx ) ;
dma_free_coherent ( & pdev - > dev ,
sizeof ( struct fbd ) * MAX_BUFFER_NUM ,
isi - > p_fb_descriptors ,
isi - > fb_descriptors_phys ) ;
2015-05-26 06:54:46 -03:00
pm_runtime_disable ( & pdev - > dev ) ;
2011-06-07 22:40:19 -03:00
return 0 ;
}
2015-08-01 06:22:54 -03:00
static int atmel_isi_parse_dt ( struct atmel_isi * isi ,
2014-07-28 04:25:17 -03:00
struct platform_device * pdev )
{
struct device_node * np = pdev - > dev . of_node ;
struct v4l2_of_endpoint ep ;
int err ;
/* Default settings for ISI */
isi - > pdata . full_mode = 1 ;
isi - > pdata . frate = ISI_CFG1_FRATE_CAPTURE_ALL ;
np = of_graph_get_next_endpoint ( np , NULL ) ;
if ( ! np ) {
dev_err ( & pdev - > dev , " Could not find the endpoint \n " ) ;
return - EINVAL ;
}
err = v4l2_of_parse_endpoint ( np , & ep ) ;
2015-08-01 06:22:53 -03:00
of_node_put ( np ) ;
2014-07-28 04:25:17 -03:00
if ( err ) {
dev_err ( & pdev - > dev , " Could not parse the endpoint \n " ) ;
2015-08-01 06:22:53 -03:00
return err ;
2014-07-28 04:25:17 -03:00
}
switch ( ep . bus . parallel . bus_width ) {
case 8 :
isi - > pdata . data_width_flags = ISI_DATAWIDTH_8 ;
break ;
case 10 :
isi - > pdata . data_width_flags =
ISI_DATAWIDTH_8 | ISI_DATAWIDTH_10 ;
break ;
default :
dev_err ( & pdev - > dev , " Unsupported bus width: %d \n " ,
ep . bus . parallel . bus_width ) ;
2015-08-01 06:22:53 -03:00
return - EINVAL ;
2014-07-28 04:25:17 -03:00
}
2015-08-04 06:37:49 -03:00
if ( ep . bus . parallel . flags & V4L2_MBUS_HSYNC_ACTIVE_LOW )
isi - > pdata . hsync_act_low = true ;
if ( ep . bus . parallel . flags & V4L2_MBUS_VSYNC_ACTIVE_LOW )
isi - > pdata . vsync_act_low = true ;
if ( ep . bus . parallel . flags & V4L2_MBUS_PCLK_SAMPLE_FALLING )
isi - > pdata . pclk_act_falling = true ;
if ( ep . bus_type = = V4L2_MBUS_BT656 )
isi - > pdata . has_emb_sync = true ;
2015-08-01 06:22:53 -03:00
return 0 ;
2014-07-28 04:25:17 -03:00
}
2012-12-21 13:17:53 -08:00
static int atmel_isi_probe ( struct platform_device * pdev )
2011-06-07 22:40:19 -03:00
{
unsigned int irq ;
struct atmel_isi * isi ;
struct resource * regs ;
int ret , i ;
struct soc_camera_host * soc_host ;
2013-11-25 12:13:50 -03:00
isi = devm_kzalloc ( & pdev - > dev , sizeof ( struct atmel_isi ) , GFP_KERNEL ) ;
2011-06-07 22:40:19 -03:00
if ( ! isi ) {
dev_err ( & pdev - > dev , " Can't allocate interface! \n " ) ;
2013-11-25 12:13:50 -03:00
return - ENOMEM ;
2011-06-07 22:40:19 -03:00
}
2013-11-25 12:13:50 -03:00
isi - > pclk = devm_clk_get ( & pdev - > dev , " isi_clk " ) ;
if ( IS_ERR ( isi - > pclk ) )
return PTR_ERR ( isi - > pclk ) ;
2015-08-01 06:22:54 -03:00
ret = atmel_isi_parse_dt ( isi , pdev ) ;
if ( ret )
return ret ;
2014-07-28 04:25:17 -03:00
2011-06-07 22:40:19 -03:00
isi - > active = NULL ;
spin_lock_init ( & isi - > lock ) ;
INIT_LIST_HEAD ( & isi - > video_buffer_list ) ;
INIT_LIST_HEAD ( & isi - > dma_desc_head ) ;
isi - > p_fb_descriptors = dma_alloc_coherent ( & pdev - > dev ,
sizeof ( struct fbd ) * MAX_BUFFER_NUM ,
& isi - > fb_descriptors_phys ,
GFP_KERNEL ) ;
if ( ! isi - > p_fb_descriptors ) {
dev_err ( & pdev - > dev , " Can't allocate descriptors! \n " ) ;
2013-11-25 12:21:33 -03:00
return - ENOMEM ;
2011-06-07 22:40:19 -03:00
}
for ( i = 0 ; i < MAX_BUFFER_NUM ; i + + ) {
isi - > dma_desc [ i ] . p_fbd = isi - > p_fb_descriptors + i ;
isi - > dma_desc [ i ] . fbd_phys = isi - > fb_descriptors_phys +
i * sizeof ( struct fbd ) ;
list_add ( & isi - > dma_desc [ i ] . list , & isi - > dma_desc_head ) ;
}
isi - > alloc_ctx = vb2_dma_contig_init_ctx ( & pdev - > dev ) ;
if ( IS_ERR ( isi - > alloc_ctx ) ) {
ret = PTR_ERR ( isi - > alloc_ctx ) ;
goto err_alloc_ctx ;
}
2013-11-25 12:13:50 -03:00
regs = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
isi - > regs = devm_ioremap_resource ( & pdev - > dev , regs ) ;
if ( IS_ERR ( isi - > regs ) ) {
ret = PTR_ERR ( isi - > regs ) ;
2011-06-07 22:40:19 -03:00
goto err_ioremap ;
}
2014-07-25 07:13:39 -03:00
if ( isi - > pdata . data_width_flags & ISI_DATAWIDTH_8 )
2011-07-27 12:18:37 -03:00
isi - > width_flags = 1 < < 7 ;
2014-07-25 07:13:39 -03:00
if ( isi - > pdata . data_width_flags & ISI_DATAWIDTH_10 )
2011-07-27 12:18:37 -03:00
isi - > width_flags | = 1 < < 9 ;
2011-06-07 22:40:19 -03:00
irq = platform_get_irq ( pdev , 0 ) ;
2012-11-16 03:50:37 -03:00
if ( IS_ERR_VALUE ( irq ) ) {
2011-06-07 22:40:19 -03:00
ret = irq ;
goto err_req_irq ;
}
2013-11-25 12:13:50 -03:00
ret = devm_request_irq ( & pdev - > dev , irq , isi_interrupt , 0 , " isi " , isi ) ;
2011-06-07 22:40:19 -03:00
if ( ret ) {
dev_err ( & pdev - > dev , " Unable to request irq %d \n " , irq ) ;
goto err_req_irq ;
}
isi - > irq = irq ;
soc_host = & isi - > soc_host ;
soc_host - > drv_name = " isi-camera " ;
soc_host - > ops = & isi_soc_camera_host_ops ;
soc_host - > priv = isi ;
soc_host - > v4l2_dev . dev = & pdev - > dev ;
soc_host - > nr = pdev - > id ;
2015-05-26 06:54:46 -03:00
pm_suspend_ignore_children ( & pdev - > dev , true ) ;
pm_runtime_enable ( & pdev - > dev ) ;
2011-06-07 22:40:19 -03:00
ret = soc_camera_host_register ( soc_host ) ;
if ( ret ) {
dev_err ( & pdev - > dev , " Unable to register soc camera host \n " ) ;
goto err_register_soc_camera_host ;
}
return 0 ;
err_register_soc_camera_host :
2015-05-26 06:54:46 -03:00
pm_runtime_disable ( & pdev - > dev ) ;
2011-06-07 22:40:19 -03:00
err_req_irq :
err_ioremap :
vb2_dma_contig_cleanup_ctx ( isi - > alloc_ctx ) ;
err_alloc_ctx :
dma_free_coherent ( & pdev - > dev ,
sizeof ( struct fbd ) * MAX_BUFFER_NUM ,
isi - > p_fb_descriptors ,
isi - > fb_descriptors_phys ) ;
return ret ;
}
2015-09-06 07:08:49 -03:00
# ifdef CONFIG_PM
2015-05-26 06:54:46 -03:00
static int atmel_isi_runtime_suspend ( struct device * dev )
{
struct soc_camera_host * soc_host = to_soc_camera_host ( dev ) ;
struct atmel_isi * isi = container_of ( soc_host ,
struct atmel_isi , soc_host ) ;
clk_disable_unprepare ( isi - > pclk ) ;
return 0 ;
}
static int atmel_isi_runtime_resume ( struct device * dev )
{
struct soc_camera_host * soc_host = to_soc_camera_host ( dev ) ;
struct atmel_isi * isi = container_of ( soc_host ,
struct atmel_isi , soc_host ) ;
return clk_prepare_enable ( isi - > pclk ) ;
}
2015-09-06 07:08:49 -03:00
# endif /* CONFIG_PM */
2015-05-26 06:54:46 -03:00
static const struct dev_pm_ops atmel_isi_dev_pm_ops = {
SET_RUNTIME_PM_OPS ( atmel_isi_runtime_suspend ,
atmel_isi_runtime_resume , NULL )
} ;
2014-07-28 04:25:17 -03:00
static const struct of_device_id atmel_isi_of_match [ ] = {
{ . compatible = " atmel,at91sam9g45-isi " } ,
{ }
} ;
MODULE_DEVICE_TABLE ( of , atmel_isi_of_match ) ;
2011-06-07 22:40:19 -03:00
static struct platform_driver atmel_isi_driver = {
2012-12-21 13:17:53 -08:00
. remove = atmel_isi_remove ,
2011-06-07 22:40:19 -03:00
. driver = {
. name = " atmel_isi " ,
2014-07-28 04:25:17 -03:00
. of_match_table = of_match_ptr ( atmel_isi_of_match ) ,
2015-05-26 06:54:46 -03:00
. pm = & atmel_isi_dev_pm_ops ,
2011-06-07 22:40:19 -03:00
} ,
} ;
2013-03-14 14:09:31 -03:00
module_platform_driver_probe ( atmel_isi_driver , atmel_isi_probe ) ;
2011-06-07 22:40:19 -03:00
MODULE_AUTHOR ( " Josh Wu <josh.wu@atmel.com> " ) ;
MODULE_DESCRIPTION ( " The V4L2 driver for Atmel Linux " ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_SUPPORTED_DEVICE ( " video " ) ;