2011-06-11 14:46:43 -03:00
/*
* The Marvell camera core . This device appears in a number of settings ,
* so it needs platform - specific support outside of the core .
*
* Copyright 2011 Jonathan Corbet corbet @ lwn . net
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/fs.h>
# include <linux/mm.h>
# include <linux/i2c.h>
# include <linux/interrupt.h>
# include <linux/spinlock.h>
# include <linux/slab.h>
# include <linux/device.h>
# include <linux/wait.h>
# include <linux/list.h>
# include <linux/dma-mapping.h>
# include <linux/delay.h>
# include <linux/vmalloc.h>
# include <linux/io.h>
2011-06-20 16:14:37 -03:00
# include <linux/videodev2.h>
# include <media/v4l2-device.h>
# include <media/v4l2-ioctl.h>
# include <media/v4l2-chip-ident.h>
# include <media/ov7670.h>
# include <media/videobuf2-vmalloc.h>
2011-06-20 16:14:40 -03:00
# include <media/videobuf2-dma-contig.h>
2011-06-30 17:05:27 -03:00
# include <media/videobuf2-dma-sg.h>
2011-06-11 14:46:43 -03:00
# include "mcam-core.h"
2011-06-20 16:14:40 -03:00
/*
* Basic frame stats - to be deleted shortly
*/
static int frames ;
static int singles ;
static int delivered ;
2011-06-11 14:46:43 -03:00
/*
* Internal DMA buffer management . Since the controller cannot do S / G I / O ,
* we must have physically contiguous buffers to bring frames into .
* These parameters control how many buffers we use , whether we
* allocate them at load time ( better chance of success , but nails down
* memory ) or when somebody tries to use the camera ( riskier ) , and ,
* for load - time allocation , how big they should be .
*
* The controller can cycle through three buffers . We could use
* more by flipping pointers around , but it probably makes little
* sense .
*/
static int alloc_bufs_at_read ;
module_param ( alloc_bufs_at_read , bool , 0444 ) ;
MODULE_PARM_DESC ( alloc_bufs_at_read ,
" Non-zero value causes DMA buffers to be allocated when the "
" video capture device is read, rather than at module load "
" time. This saves memory, but decreases the chances of "
2011-06-20 16:14:40 -03:00
" successfully getting those buffers. This parameter is "
" only used in the vmalloc buffer mode " ) ;
2011-06-11 14:46:43 -03:00
static int n_dma_bufs = 3 ;
module_param ( n_dma_bufs , uint , 0644 ) ;
MODULE_PARM_DESC ( n_dma_bufs ,
" The number of DMA buffers to allocate. Can be either two "
" (saves memory, makes timing tighter) or three. " ) ;
static int dma_buf_size = VGA_WIDTH * VGA_HEIGHT * 2 ; /* Worst case */
module_param ( dma_buf_size , uint , 0444 ) ;
MODULE_PARM_DESC ( dma_buf_size ,
" The size of the allocated DMA buffers. If actual operating "
" parameters require larger buffers, an attempt to reallocate "
" will be made. " ) ;
static int min_buffers = 1 ;
module_param ( min_buffers , uint , 0644 ) ;
MODULE_PARM_DESC ( min_buffers ,
" The minimum number of streaming I/O buffers we are willing "
" to work with. " ) ;
static int max_buffers = 10 ;
module_param ( max_buffers , uint , 0644 ) ;
MODULE_PARM_DESC ( max_buffers ,
" The maximum number of streaming I/O buffers an application "
" will be allowed to allocate. These buffers are big and live "
" in vmalloc space. " ) ;
static int flip ;
module_param ( flip , bool , 0444 ) ;
MODULE_PARM_DESC ( flip ,
" If set, the sensor will be instructed to flip the image "
" vertically. " ) ;
2011-06-20 16:14:40 -03:00
static int buffer_mode = - 1 ;
module_param ( buffer_mode , int , 0444 ) ;
MODULE_PARM_DESC ( buffer_mode ,
" Set the buffer mode to be used; default is to go with what "
" the platform driver asks for. Set to 0 for vmalloc, 1 for "
" DMA contiguous. " ) ;
2011-06-11 14:46:43 -03:00
/*
* Status flags . Always manipulated with bit operations .
*/
# define CF_BUF0_VALID 0 /* Buffers valid - first three */
# define CF_BUF1_VALID 1
# define CF_BUF2_VALID 2
# define CF_DMA_ACTIVE 3 /* A frame is incoming */
# define CF_CONFIG_NEEDED 4 /* Must configure hardware */
2011-06-20 16:14:40 -03:00
# define CF_SINGLE_BUFFER 5 /* Running with a single buffer */
2011-06-30 17:05:27 -03:00
# define CF_SG_RESTART 6 /* SG restart needed */
2011-06-11 14:46:43 -03:00
# define sensor_call(cam, o, f, args...) \
v4l2_subdev_call ( cam - > sensor , o , f , # # args )
static struct mcam_format_struct {
__u8 * desc ;
__u32 pixelformat ;
int bpp ; /* Bytes per pixel */
enum v4l2_mbus_pixelcode mbus_code ;
} mcam_formats [ ] = {
{
. desc = " YUYV 4:2:2 " ,
. pixelformat = V4L2_PIX_FMT_YUYV ,
. mbus_code = V4L2_MBUS_FMT_YUYV8_2X8 ,
. bpp = 2 ,
} ,
{
. desc = " RGB 444 " ,
. pixelformat = V4L2_PIX_FMT_RGB444 ,
. mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE ,
. bpp = 2 ,
} ,
{
. desc = " RGB 565 " ,
. pixelformat = V4L2_PIX_FMT_RGB565 ,
. mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE ,
. bpp = 2 ,
} ,
{
. desc = " Raw RGB Bayer " ,
. pixelformat = V4L2_PIX_FMT_SBGGR8 ,
. mbus_code = V4L2_MBUS_FMT_SBGGR8_1X8 ,
. bpp = 1
} ,
} ;
# define N_MCAM_FMTS ARRAY_SIZE(mcam_formats)
static struct mcam_format_struct * mcam_find_format ( u32 pixelformat )
{
unsigned i ;
for ( i = 0 ; i < N_MCAM_FMTS ; i + + )
if ( mcam_formats [ i ] . pixelformat = = pixelformat )
return mcam_formats + i ;
/* Not found? Then return the first format. */
return mcam_formats ;
}
/*
* Start over with DMA buffers - dev_lock needed .
*/
static void mcam_reset_buffers ( struct mcam_camera * cam )
{
int i ;
cam - > next_buf = - 1 ;
for ( i = 0 ; i < cam - > nbufs ; i + + )
clear_bit ( i , & cam - > flags ) ;
}
static inline int mcam_needs_config ( struct mcam_camera * cam )
{
return test_bit ( CF_CONFIG_NEEDED , & cam - > flags ) ;
}
static void mcam_set_config_needed ( struct mcam_camera * cam , int needed )
{
if ( needed )
set_bit ( CF_CONFIG_NEEDED , & cam - > flags ) ;
else
clear_bit ( CF_CONFIG_NEEDED , & cam - > flags ) ;
}
2011-06-30 17:05:27 -03:00
/*
* The two - word DMA descriptor format used by the Armada 610 and like . There
* Is a three - word format as well ( set C1_DESC_3WORD ) where the third
* word is a pointer to the next descriptor , but we don ' t use it . Two - word
* descriptors have to be contiguous in memory .
*/
struct mcam_dma_desc {
u32 dma_addr ;
u32 segment_len ;
} ;
2011-06-20 16:14:36 -03:00
/*
* Our buffer type for working with videobuf2 . Note that the vb2
* developers have decreed that struct vb2_buffer must be at the
* beginning of this structure .
*/
struct mcam_vb_buffer {
struct vb2_buffer vb_buf ;
struct list_head queue ;
2011-06-30 17:05:27 -03:00
struct mcam_dma_desc * dma_desc ; /* Descriptor virtual address */
dma_addr_t dma_desc_pa ; /* Descriptor physical address */
int dma_desc_nent ; /* Number of mapped descriptors */
2011-06-20 16:14:36 -03:00
} ;
static inline struct mcam_vb_buffer * vb_to_mvb ( struct vb2_buffer * vb )
{
return container_of ( vb , struct mcam_vb_buffer , vb_buf ) ;
}
2011-06-11 14:46:43 -03:00
/*
2011-06-11 14:46:49 -03:00
* Debugging and related .
2011-06-11 14:46:43 -03:00
*/
# define cam_err(cam, fmt, arg...) \
dev_err ( ( cam ) - > dev , fmt , # # arg ) ;
# define cam_warn(cam, fmt, arg...) \
dev_warn ( ( cam ) - > dev , fmt , # # arg ) ;
# define cam_dbg(cam, fmt, arg...) \
dev_dbg ( ( cam ) - > dev , fmt , # # arg ) ;
/* ------------------------------------------------------------------- */
/*
* Deal with the controller .
*/
/*
2011-06-20 16:14:40 -03:00
* Set up DMA buffers when operating in vmalloc mode
2011-06-11 14:46:43 -03:00
*/
2011-06-20 16:14:40 -03:00
static void mcam_ctlr_dma_vmalloc ( struct mcam_camera * cam )
2011-06-11 14:46:43 -03:00
{
/*
* Store the first two Y buffers ( we aren ' t supporting
* planar formats for now , so no UV bufs ) . Then either
* set the third if it exists , or tell the controller
* to just use two .
*/
mcam_reg_write ( cam , REG_Y0BAR , cam - > dma_handles [ 0 ] ) ;
mcam_reg_write ( cam , REG_Y1BAR , cam - > dma_handles [ 1 ] ) ;
if ( cam - > nbufs > 2 ) {
mcam_reg_write ( cam , REG_Y2BAR , cam - > dma_handles [ 2 ] ) ;
mcam_reg_clear_bit ( cam , REG_CTRL1 , C1_TWOBUFS ) ;
} else
mcam_reg_set_bit ( cam , REG_CTRL1 , C1_TWOBUFS ) ;
2011-06-11 14:46:49 -03:00
if ( cam - > chip_id = = V4L2_IDENT_CAFE )
mcam_reg_write ( cam , REG_UBAR , 0 ) ; /* 32 bits only */
2011-06-11 14:46:43 -03:00
}
2011-06-20 16:14:40 -03:00
/*
* Set up a contiguous buffer for the given frame . Here also is where
* the underrun strategy is set : if there is no buffer available , reuse
* the buffer from the other BAR and set the CF_SINGLE_BUFFER flag to
* keep the interrupt handler from giving that buffer back to user
* space . In this way , we always have a buffer to DMA to and don ' t
* have to try to play games stopping and restarting the controller .
*/
static void mcam_set_contig_buffer ( struct mcam_camera * cam , int frame )
{
struct mcam_vb_buffer * buf ;
/*
* If there are no available buffers , go into single mode
*/
if ( list_empty ( & cam - > buffers ) ) {
buf = cam - > vb_bufs [ frame ^ 0x1 ] ;
cam - > vb_bufs [ frame ] = buf ;
mcam_reg_write ( cam , frame = = 0 ? REG_Y0BAR : REG_Y1BAR ,
vb2_dma_contig_plane_paddr ( & buf - > vb_buf , 0 ) ) ;
set_bit ( CF_SINGLE_BUFFER , & cam - > flags ) ;
singles + + ;
return ;
}
/*
* OK , we have a buffer we can use .
*/
buf = list_first_entry ( & cam - > buffers , struct mcam_vb_buffer , queue ) ;
list_del_init ( & buf - > queue ) ;
mcam_reg_write ( cam , frame = = 0 ? REG_Y0BAR : REG_Y1BAR ,
vb2_dma_contig_plane_paddr ( & buf - > vb_buf , 0 ) ) ;
cam - > vb_bufs [ frame ] = buf ;
clear_bit ( CF_SINGLE_BUFFER , & cam - > flags ) ;
}
2011-06-30 17:05:27 -03:00
/*
* Initial B_DMA_contig setup .
*/
2011-06-20 16:14:40 -03:00
static void mcam_ctlr_dma_contig ( struct mcam_camera * cam )
{
mcam_reg_set_bit ( cam , REG_CTRL1 , C1_TWOBUFS ) ;
cam - > nbufs = 2 ;
mcam_set_contig_buffer ( cam , 0 ) ;
mcam_set_contig_buffer ( cam , 1 ) ;
}
2011-06-30 17:05:27 -03:00
/*
* Set up the next buffer for S / G I / O ; caller should be sure that
* the controller is stopped and a buffer is available .
*/
static void mcam_sg_next_buffer ( struct mcam_camera * cam )
2011-06-20 16:14:40 -03:00
{
2011-06-30 17:05:27 -03:00
struct mcam_vb_buffer * buf ;
buf = list_first_entry ( & cam - > buffers , struct mcam_vb_buffer , queue ) ;
list_del_init ( & buf - > queue ) ;
mcam_reg_write ( cam , REG_DMA_DESC_Y , buf - > dma_desc_pa ) ;
mcam_reg_write ( cam , REG_DESC_LEN_Y ,
buf - > dma_desc_nent * sizeof ( struct mcam_dma_desc ) ) ;
mcam_reg_write ( cam , REG_DESC_LEN_U , 0 ) ;
mcam_reg_write ( cam , REG_DESC_LEN_V , 0 ) ;
cam - > vb_bufs [ 0 ] = buf ;
2011-06-20 16:14:40 -03:00
}
2011-06-30 17:05:27 -03:00
/*
* Initial B_DMA_sg setup
*/
static void mcam_ctlr_dma_sg ( struct mcam_camera * cam )
{
mcam_reg_clear_bit ( cam , REG_CTRL1 , C1_DESC_3WORD ) ;
mcam_sg_next_buffer ( cam ) ;
mcam_reg_set_bit ( cam , REG_CTRL1 , C1_DESC_ENA ) ;
cam - > nbufs = 3 ;
}
/*
* Image format setup , independent of DMA scheme .
*/
2011-06-11 14:46:43 -03:00
static void mcam_ctlr_image ( struct mcam_camera * cam )
{
int imgsz ;
struct v4l2_pix_format * fmt = & cam - > pix_format ;
imgsz = ( ( fmt - > height < < IMGSZ_V_SHIFT ) & IMGSZ_V_MASK ) |
( fmt - > bytesperline & IMGSZ_H_MASK ) ;
mcam_reg_write ( cam , REG_IMGSIZE , imgsz ) ;
mcam_reg_write ( cam , REG_IMGOFFSET , 0 ) ;
/* YPITCH just drops the last two bits */
mcam_reg_write_mask ( cam , REG_IMGPITCH , fmt - > bytesperline ,
IMGP_YP_MASK ) ;
/*
* Tell the controller about the image format we are using .
*/
switch ( cam - > pix_format . pixelformat ) {
case V4L2_PIX_FMT_YUYV :
mcam_reg_write_mask ( cam , REG_CTRL0 ,
C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_YUYV ,
C0_DF_MASK ) ;
break ;
case V4L2_PIX_FMT_RGB444 :
mcam_reg_write_mask ( cam , REG_CTRL0 ,
C0_DF_RGB | C0_RGBF_444 | C0_RGB4_XRGB ,
C0_DF_MASK ) ;
/* Alpha value? */
break ;
case V4L2_PIX_FMT_RGB565 :
mcam_reg_write_mask ( cam , REG_CTRL0 ,
C0_DF_RGB | C0_RGBF_565 | C0_RGB5_BGGR ,
C0_DF_MASK ) ;
break ;
default :
cam_err ( cam , " Unknown format %x \n " , cam - > pix_format . pixelformat ) ;
break ;
}
/*
* Make sure it knows we want to use hsync / vsync .
*/
mcam_reg_write_mask ( cam , REG_CTRL0 , C0_SIF_HVSYNC ,
C0_SIFM_MASK ) ;
}
/*
* Configure the controller for operation ; caller holds the
* device mutex .
*/
static int mcam_ctlr_configure ( struct mcam_camera * cam )
{
unsigned long flags ;
spin_lock_irqsave ( & cam - > dev_lock , flags ) ;
2011-06-30 17:05:27 -03:00
switch ( cam - > buffer_mode ) {
case B_vmalloc :
mcam_ctlr_dma_vmalloc ( cam ) ;
break ;
case B_DMA_contig :
mcam_ctlr_dma_contig ( cam ) ;
break ;
case B_DMA_sg :
mcam_ctlr_dma_sg ( cam ) ;
break ;
}
2011-06-11 14:46:43 -03:00
mcam_ctlr_image ( cam ) ;
mcam_set_config_needed ( cam , 0 ) ;
2011-06-30 17:05:27 -03:00
clear_bit ( CF_SG_RESTART , & cam - > flags ) ;
2011-06-11 14:46:43 -03:00
spin_unlock_irqrestore ( & cam - > dev_lock , flags ) ;
return 0 ;
}
static void mcam_ctlr_irq_enable ( struct mcam_camera * cam )
{
/*
* Clear any pending interrupts , since we do not
* expect to have I / O active prior to enabling .
*/
mcam_reg_write ( cam , REG_IRQSTAT , FRAMEIRQS ) ;
mcam_reg_set_bit ( cam , REG_IRQMASK , FRAMEIRQS ) ;
}
static void mcam_ctlr_irq_disable ( struct mcam_camera * cam )
{
mcam_reg_clear_bit ( cam , REG_IRQMASK , FRAMEIRQS ) ;
}
/*
* Make the controller start grabbing images . Everything must
* be set up before doing this .
*/
static void mcam_ctlr_start ( struct mcam_camera * cam )
{
/* set_bit performs a read, so no other barrier should be
needed here */
mcam_reg_set_bit ( cam , REG_CTRL0 , C0_ENABLE ) ;
}
static void mcam_ctlr_stop ( struct mcam_camera * cam )
{
mcam_reg_clear_bit ( cam , REG_CTRL0 , C0_ENABLE ) ;
}
2011-06-30 17:05:27 -03:00
/*
* Scatter / gather mode requires stopping the controller between
* frames so we can put in a new DMA descriptor array . If no new
* buffer exists at frame completion , the controller is left stopped ;
* this function is charged with gettig things going again .
*/
static void mcam_sg_restart ( struct mcam_camera * cam )
{
mcam_ctlr_dma_sg ( cam ) ;
mcam_ctlr_start ( cam ) ;
clear_bit ( CF_SG_RESTART , & cam - > flags ) ;
}
2011-06-11 14:46:43 -03:00
static void mcam_ctlr_init ( struct mcam_camera * cam )
{
unsigned long flags ;
spin_lock_irqsave ( & cam - > dev_lock , flags ) ;
/*
* Make sure it ' s not powered down .
*/
mcam_reg_clear_bit ( cam , REG_CTRL1 , C1_PWRDWN ) ;
/*
* Turn off the enable bit . It sure should be off anyway ,
* but it ' s good to be sure .
*/
mcam_reg_clear_bit ( cam , REG_CTRL0 , C0_ENABLE ) ;
/*
* Clock the sensor appropriately . Controller clock should
* be 48 MHz , sensor " typical " value is half that .
*/
mcam_reg_write_mask ( cam , REG_CLKCTRL , 2 , CLK_DIV_MASK ) ;
spin_unlock_irqrestore ( & cam - > dev_lock , flags ) ;
}
/*
* Stop the controller , and don ' t return until we ' re really sure that no
* further DMA is going on .
*/
static void mcam_ctlr_stop_dma ( struct mcam_camera * cam )
{
unsigned long flags ;
/*
* Theory : stop the camera controller ( whether it is operating
* or not ) . Delay briefly just in case we race with the SOF
* interrupt , then wait until no DMA is active .
*/
spin_lock_irqsave ( & cam - > dev_lock , flags ) ;
2011-06-30 17:05:27 -03:00
clear_bit ( CF_SG_RESTART , & cam - > flags ) ;
2011-06-11 14:46:43 -03:00
mcam_ctlr_stop ( cam ) ;
2011-06-30 17:05:27 -03:00
cam - > state = S_IDLE ;
2011-06-11 14:46:43 -03:00
spin_unlock_irqrestore ( & cam - > dev_lock , flags ) ;
2011-06-30 17:05:27 -03:00
msleep ( 40 ) ;
2011-06-11 14:46:43 -03:00
if ( test_bit ( CF_DMA_ACTIVE , & cam - > flags ) )
cam_err ( cam , " Timeout waiting for DMA to end \n " ) ;
/* This would be bad news - what now? */
spin_lock_irqsave ( & cam - > dev_lock , flags ) ;
mcam_ctlr_irq_disable ( cam ) ;
spin_unlock_irqrestore ( & cam - > dev_lock , flags ) ;
}
/*
* Power up and down .
*/
static void mcam_ctlr_power_up ( struct mcam_camera * cam )
{
unsigned long flags ;
spin_lock_irqsave ( & cam - > dev_lock , flags ) ;
cam - > plat_power_up ( cam ) ;
2011-06-11 14:46:49 -03:00
mcam_reg_clear_bit ( cam , REG_CTRL1 , C1_PWRDWN ) ;
2011-06-11 14:46:43 -03:00
spin_unlock_irqrestore ( & cam - > dev_lock , flags ) ;
msleep ( 5 ) ; /* Just to be sure */
}
static void mcam_ctlr_power_down ( struct mcam_camera * cam )
{
unsigned long flags ;
spin_lock_irqsave ( & cam - > dev_lock , flags ) ;
2011-06-11 14:46:49 -03:00
/*
* School of hard knocks department : be sure we do any register
* twiddling on the controller * before * calling the platform
* power down routine .
*/
2011-06-11 14:46:43 -03:00
mcam_reg_set_bit ( cam , REG_CTRL1 , C1_PWRDWN ) ;
2011-06-11 14:46:49 -03:00
cam - > plat_power_down ( cam ) ;
2011-06-11 14:46:43 -03:00
spin_unlock_irqrestore ( & cam - > dev_lock , flags ) ;
}
/* -------------------------------------------------------------------- */
/*
* Communications with the sensor .
*/
static int __mcam_cam_reset ( struct mcam_camera * cam )
{
return sensor_call ( cam , core , reset , 0 ) ;
}
/*
* We have found the sensor on the i2c . Let ' s try to have a
* conversation .
*/
static int mcam_cam_init ( struct mcam_camera * cam )
{
struct v4l2_dbg_chip_ident chip ;
int ret ;
mutex_lock ( & cam - > s_mutex ) ;
if ( cam - > state ! = S_NOTREADY )
cam_warn ( cam , " Cam init with device in funky state %d " ,
cam - > state ) ;
ret = __mcam_cam_reset ( cam ) ;
if ( ret )
goto out ;
chip . ident = V4L2_IDENT_NONE ;
chip . match . type = V4L2_CHIP_MATCH_I2C_ADDR ;
chip . match . addr = cam - > sensor_addr ;
ret = sensor_call ( cam , core , g_chip_ident , & chip ) ;
if ( ret )
goto out ;
cam - > sensor_type = chip . ident ;
if ( cam - > sensor_type ! = V4L2_IDENT_OV7670 ) {
cam_err ( cam , " Unsupported sensor type 0x%x " , cam - > sensor_type ) ;
ret = - EINVAL ;
goto out ;
}
/* Get/set parameters? */
ret = 0 ;
cam - > state = S_IDLE ;
out :
mcam_ctlr_power_down ( cam ) ;
mutex_unlock ( & cam - > s_mutex ) ;
return ret ;
}
/*
* Configure the sensor to match the parameters we have . Caller should
* hold s_mutex
*/
static int mcam_cam_set_flip ( struct mcam_camera * cam )
{
struct v4l2_control ctrl ;
memset ( & ctrl , 0 , sizeof ( ctrl ) ) ;
ctrl . id = V4L2_CID_VFLIP ;
ctrl . value = flip ;
return sensor_call ( cam , core , s_ctrl , & ctrl ) ;
}
static int mcam_cam_configure ( struct mcam_camera * cam )
{
struct v4l2_mbus_framefmt mbus_fmt ;
int ret ;
v4l2_fill_mbus_format ( & mbus_fmt , & cam - > pix_format , cam - > mbus_code ) ;
ret = sensor_call ( cam , core , init , 0 ) ;
if ( ret = = 0 )
ret = sensor_call ( cam , video , s_mbus_fmt , & mbus_fmt ) ;
/*
* OV7670 does weird things if flip is set * before * format . . .
*/
ret + = mcam_cam_set_flip ( cam ) ;
return ret ;
}
/* -------------------------------------------------------------------- */
/*
* DMA buffer management . These functions need s_mutex held .
*/
2011-06-30 17:05:27 -03:00
/*
* Allocate in - kernel DMA buffers for vmalloc mode .
2011-06-11 14:46:43 -03:00
*/
static int mcam_alloc_dma_bufs ( struct mcam_camera * cam , int loadtime )
{
int i ;
mcam_set_config_needed ( cam , 1 ) ;
if ( loadtime )
cam - > dma_buf_size = dma_buf_size ;
else
cam - > dma_buf_size = cam - > pix_format . sizeimage ;
if ( n_dma_bufs > 3 )
n_dma_bufs = 3 ;
cam - > nbufs = 0 ;
for ( i = 0 ; i < n_dma_bufs ; i + + ) {
cam - > dma_bufs [ i ] = dma_alloc_coherent ( cam - > dev ,
cam - > dma_buf_size , cam - > dma_handles + i ,
GFP_KERNEL ) ;
if ( cam - > dma_bufs [ i ] = = NULL ) {
cam_warn ( cam , " Failed to allocate DMA buffer \n " ) ;
break ;
}
( cam - > nbufs ) + + ;
}
switch ( cam - > nbufs ) {
case 1 :
dma_free_coherent ( cam - > dev , cam - > dma_buf_size ,
cam - > dma_bufs [ 0 ] , cam - > dma_handles [ 0 ] ) ;
cam - > nbufs = 0 ;
case 0 :
cam_err ( cam , " Insufficient DMA buffers, cannot operate \n " ) ;
return - ENOMEM ;
case 2 :
if ( n_dma_bufs > 2 )
cam_warn ( cam , " Will limp along with only 2 buffers \n " ) ;
break ;
}
return 0 ;
}
static void mcam_free_dma_bufs ( struct mcam_camera * cam )
{
int i ;
for ( i = 0 ; i < cam - > nbufs ; i + + ) {
dma_free_coherent ( cam - > dev , cam - > dma_buf_size ,
cam - > dma_bufs [ i ] , cam - > dma_handles [ i ] ) ;
cam - > dma_bufs [ i ] = NULL ;
}
cam - > nbufs = 0 ;
}
/* ----------------------------------------------------------------------- */
/*
* Here starts the V4L2 interface code .
*/
/*
* Get everything ready , and start grabbing frames .
*/
2011-06-20 16:14:40 -03:00
static int mcam_read_setup ( struct mcam_camera * cam )
2011-06-11 14:46:43 -03:00
{
int ret ;
unsigned long flags ;
/*
* Configuration . If we still don ' t have DMA buffers ,
* make one last , desperate attempt .
*/
2011-06-20 16:14:40 -03:00
if ( cam - > buffer_mode = = B_vmalloc & & cam - > nbufs = = 0 & &
mcam_alloc_dma_bufs ( cam , 0 ) )
return - ENOMEM ;
2011-06-11 14:46:43 -03:00
if ( mcam_needs_config ( cam ) ) {
mcam_cam_configure ( cam ) ;
ret = mcam_ctlr_configure ( cam ) ;
if ( ret )
return ret ;
}
/*
* Turn it loose .
*/
spin_lock_irqsave ( & cam - > dev_lock , flags ) ;
mcam_reset_buffers ( cam ) ;
mcam_ctlr_irq_enable ( cam ) ;
2011-06-20 16:14:40 -03:00
cam - > state = S_STREAMING ;
2011-06-11 14:46:43 -03:00
mcam_ctlr_start ( cam ) ;
spin_unlock_irqrestore ( & cam - > dev_lock , flags ) ;
return 0 ;
}
2011-06-20 16:14:36 -03:00
/* ----------------------------------------------------------------------- */
/*
* Videobuf2 interface code .
*/
2011-06-11 14:46:43 -03:00
2011-06-20 16:14:36 -03:00
static int mcam_vb_queue_setup ( struct vb2_queue * vq , unsigned int * nbufs ,
unsigned int * num_planes , unsigned long sizes [ ] ,
void * alloc_ctxs [ ] )
2011-06-11 14:46:43 -03:00
{
2011-06-20 16:14:36 -03:00
struct mcam_camera * cam = vb2_get_drv_priv ( vq ) ;
2011-06-30 17:05:27 -03:00
int minbufs = ( cam - > buffer_mode = = B_DMA_contig ) ? 3 : 2 ;
2011-06-20 16:14:36 -03:00
sizes [ 0 ] = cam - > pix_format . sizeimage ;
* num_planes = 1 ; /* Someday we have to support planar formats... */
2011-06-30 17:05:27 -03:00
if ( * nbufs < minbufs )
* nbufs = minbufs ;
2011-06-20 16:14:40 -03:00
if ( cam - > buffer_mode = = B_DMA_contig )
alloc_ctxs [ 0 ] = cam - > vb_alloc_ctx ;
2011-06-20 16:14:36 -03:00
return 0 ;
}
2011-06-30 17:05:27 -03:00
/* DMA_sg only */
static int mcam_vb_sg_buf_init ( struct vb2_buffer * vb )
{
struct mcam_vb_buffer * mvb = vb_to_mvb ( vb ) ;
struct mcam_camera * cam = vb2_get_drv_priv ( vb - > vb2_queue ) ;
int ndesc = cam - > pix_format . sizeimage / PAGE_SIZE + 1 ;
mvb - > dma_desc = dma_alloc_coherent ( cam - > dev ,
ndesc * sizeof ( struct mcam_dma_desc ) ,
& mvb - > dma_desc_pa , GFP_KERNEL ) ;
if ( mvb - > dma_desc = = NULL ) {
cam_err ( cam , " Unable to get DMA descriptor array \n " ) ;
return - ENOMEM ;
}
return 0 ;
}
static int mcam_vb_sg_buf_prepare ( struct vb2_buffer * vb )
2011-06-20 16:14:36 -03:00
{
struct mcam_vb_buffer * mvb = vb_to_mvb ( vb ) ;
2011-06-30 17:05:27 -03:00
struct mcam_camera * cam = vb2_get_drv_priv ( vb - > vb2_queue ) ;
struct vb2_dma_sg_desc * sgd = vb2_dma_sg_plane_desc ( vb , 0 ) ;
struct mcam_dma_desc * desc = mvb - > dma_desc ;
struct scatterlist * sg ;
int i ;
2011-06-20 16:14:36 -03:00
2011-06-30 17:05:27 -03:00
mvb - > dma_desc_nent = dma_map_sg ( cam - > dev , sgd - > sglist , sgd - > num_pages ,
DMA_FROM_DEVICE ) ;
if ( mvb - > dma_desc_nent < = 0 )
return - EIO ; /* Not sure what's right here */
for_each_sg ( sgd - > sglist , sg , mvb - > dma_desc_nent , i ) {
desc - > dma_addr = sg_dma_address ( sg ) ;
desc - > segment_len = sg_dma_len ( sg ) ;
desc + + ;
}
2011-06-20 16:14:36 -03:00
return 0 ;
}
2011-06-30 17:05:27 -03:00
2011-06-20 16:14:36 -03:00
static void mcam_vb_buf_queue ( struct vb2_buffer * vb )
{
struct mcam_vb_buffer * mvb = vb_to_mvb ( vb ) ;
struct mcam_camera * cam = vb2_get_drv_priv ( vb - > vb2_queue ) ;
unsigned long flags ;
2011-06-20 16:14:40 -03:00
int start ;
2011-06-20 16:14:36 -03:00
spin_lock_irqsave ( & cam - > dev_lock , flags ) ;
2011-06-20 16:14:40 -03:00
start = ( cam - > state = = S_BUFWAIT ) & & ! list_empty ( & cam - > buffers ) ;
list_add ( & mvb - > queue , & cam - > buffers ) ;
2011-06-30 17:05:27 -03:00
if ( test_bit ( CF_SG_RESTART , & cam - > flags ) )
mcam_sg_restart ( cam ) ;
2011-06-20 16:14:36 -03:00
spin_unlock_irqrestore ( & cam - > dev_lock , flags ) ;
2011-06-20 16:14:40 -03:00
if ( start )
mcam_read_setup ( cam ) ;
2011-06-20 16:14:36 -03:00
}
2011-06-30 17:05:27 -03:00
static int mcam_vb_sg_buf_finish ( struct vb2_buffer * vb )
{
struct mcam_camera * cam = vb2_get_drv_priv ( vb - > vb2_queue ) ;
struct vb2_dma_sg_desc * sgd = vb2_dma_sg_plane_desc ( vb , 0 ) ;
dma_unmap_sg ( cam - > dev , sgd - > sglist , sgd - > num_pages , DMA_FROM_DEVICE ) ;
return 0 ;
}
static void mcam_vb_sg_buf_cleanup ( struct vb2_buffer * vb )
{
struct mcam_camera * cam = vb2_get_drv_priv ( vb - > vb2_queue ) ;
struct mcam_vb_buffer * mvb = vb_to_mvb ( vb ) ;
int ndesc = cam - > pix_format . sizeimage / PAGE_SIZE + 1 ;
dma_free_coherent ( cam - > dev , ndesc * sizeof ( struct mcam_dma_desc ) ,
mvb - > dma_desc , mvb - > dma_desc_pa ) ;
}
2011-06-20 16:14:36 -03:00
/*
* vb2 uses these to release the mutex when waiting in dqbuf . I ' m
* not actually sure we need to do this ( I ' m not sure that vb2_dqbuf ( ) needs
* to be called with the mutex held ) , but better safe than sorry .
*/
static void mcam_vb_wait_prepare ( struct vb2_queue * vq )
{
struct mcam_camera * cam = vb2_get_drv_priv ( vq ) ;
mutex_unlock ( & cam - > s_mutex ) ;
}
static void mcam_vb_wait_finish ( struct vb2_queue * vq )
{
struct mcam_camera * cam = vb2_get_drv_priv ( vq ) ;
2011-06-11 14:46:43 -03:00
mutex_lock ( & cam - > s_mutex ) ;
2011-06-20 16:14:36 -03:00
}
2011-06-11 14:46:43 -03:00
2011-06-20 16:14:36 -03:00
/*
* These need to be called with the mutex held from vb2
*/
static int mcam_vb_start_streaming ( struct vb2_queue * vq )
{
struct mcam_camera * cam = vb2_get_drv_priv ( vq ) ;
2011-06-11 14:46:43 -03:00
2011-06-20 16:14:40 -03:00
if ( cam - > state ! = S_IDLE )
return - EINVAL ;
cam - > sequence = 0 ;
/*
* Videobuf2 sneakily hoards all the buffers and won ' t
* give them to us until * after * streaming starts . But
* we can ' t actually start streaming until we have a
* destination . So go into a wait state and hope they
* give us buffers soon .
*/
if ( cam - > buffer_mode ! = B_vmalloc & & list_empty ( & cam - > buffers ) ) {
cam - > state = S_BUFWAIT ;
return 0 ;
2011-06-11 14:46:43 -03:00
}
2011-06-20 16:14:40 -03:00
return mcam_read_setup ( cam ) ;
2011-06-20 16:14:36 -03:00
}
static int mcam_vb_stop_streaming ( struct vb2_queue * vq )
{
struct mcam_camera * cam = vb2_get_drv_priv ( vq ) ;
unsigned long flags ;
2011-06-20 16:14:40 -03:00
if ( cam - > state = = S_BUFWAIT ) {
/* They never gave us buffers */
cam - > state = S_IDLE ;
return 0 ;
}
2011-06-20 16:14:36 -03:00
if ( cam - > state ! = S_STREAMING )
return - EINVAL ;
mcam_ctlr_stop_dma ( cam ) ;
2011-06-11 14:46:43 -03:00
/*
2011-06-20 16:14:36 -03:00
* VB2 reclaims the buffers , so we need to forget
* about them .
2011-06-11 14:46:43 -03:00
*/
2011-06-20 16:14:36 -03:00
spin_lock_irqsave ( & cam - > dev_lock , flags ) ;
INIT_LIST_HEAD ( & cam - > buffers ) ;
spin_unlock_irqrestore ( & cam - > dev_lock , flags ) ;
return 0 ;
2011-06-11 14:46:43 -03:00
}
2011-06-20 16:14:36 -03:00
static const struct vb2_ops mcam_vb2_ops = {
. queue_setup = mcam_vb_queue_setup ,
. buf_queue = mcam_vb_buf_queue ,
. start_streaming = mcam_vb_start_streaming ,
. stop_streaming = mcam_vb_stop_streaming ,
. wait_prepare = mcam_vb_wait_prepare ,
. wait_finish = mcam_vb_wait_finish ,
} ;
2011-06-11 14:46:43 -03:00
2011-06-30 17:05:27 -03:00
/*
* Scatter / gather mode complicates things somewhat .
*/
static const struct vb2_ops mcam_vb2_sg_ops = {
. queue_setup = mcam_vb_queue_setup ,
. buf_init = mcam_vb_sg_buf_init ,
. buf_prepare = mcam_vb_sg_buf_prepare ,
. buf_queue = mcam_vb_buf_queue ,
. buf_finish = mcam_vb_sg_buf_finish ,
. buf_cleanup = mcam_vb_sg_buf_cleanup ,
. start_streaming = mcam_vb_start_streaming ,
. stop_streaming = mcam_vb_stop_streaming ,
. wait_prepare = mcam_vb_wait_prepare ,
. wait_finish = mcam_vb_wait_finish ,
} ;
2011-06-20 16:14:36 -03:00
static int mcam_setup_vb2 ( struct mcam_camera * cam )
{
struct vb2_queue * vq = & cam - > vb_queue ;
2011-06-11 14:46:43 -03:00
2011-06-20 16:14:36 -03:00
memset ( vq , 0 , sizeof ( * vq ) ) ;
vq - > type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
vq - > drv_priv = cam ;
2011-06-30 17:05:27 -03:00
INIT_LIST_HEAD ( & cam - > buffers ) ;
switch ( cam - > buffer_mode ) {
case B_DMA_contig :
vq - > ops = & mcam_vb2_ops ;
2011-06-20 16:14:40 -03:00
vq - > mem_ops = & vb2_dma_contig_memops ;
cam - > vb_alloc_ctx = vb2_dma_contig_init_ctx ( cam - > dev ) ;
2011-06-30 17:05:27 -03:00
vq - > io_modes = VB2_MMAP | VB2_USERPTR ;
break ;
case B_DMA_sg :
vq - > ops = & mcam_vb2_sg_ops ;
vq - > mem_ops = & vb2_dma_sg_memops ;
vq - > io_modes = VB2_MMAP | VB2_USERPTR ;
break ;
case B_vmalloc :
vq - > ops = & mcam_vb2_ops ;
2011-06-20 16:14:40 -03:00
vq - > mem_ops = & vb2_vmalloc_memops ;
2011-06-30 17:05:27 -03:00
vq - > buf_struct_size = sizeof ( struct mcam_vb_buffer ) ;
vq - > io_modes = VB2_MMAP ;
break ;
}
2011-06-20 16:14:36 -03:00
return vb2_queue_init ( vq ) ;
}
static void mcam_cleanup_vb2 ( struct mcam_camera * cam )
{
vb2_queue_release ( & cam - > vb_queue ) ;
2011-06-20 16:14:40 -03:00
if ( cam - > buffer_mode = = B_DMA_contig )
vb2_dma_contig_cleanup_ctx ( cam - > vb_alloc_ctx ) ;
2011-06-20 16:14:36 -03:00
}
static ssize_t mcam_v4l_read ( struct file * filp ,
char __user * buffer , size_t len , loff_t * pos )
{
struct mcam_camera * cam = filp - > private_data ;
int ret ;
mutex_lock ( & cam - > s_mutex ) ;
ret = vb2_read ( & cam - > vb_queue , buffer , len , pos ,
filp - > f_flags & O_NONBLOCK ) ;
mutex_unlock ( & cam - > s_mutex ) ;
return ret ;
}
2011-06-11 14:46:43 -03:00
/*
* Streaming I / O support .
*/
static int mcam_vidioc_streamon ( struct file * filp , void * priv ,
enum v4l2_buf_type type )
{
struct mcam_camera * cam = filp - > private_data ;
2011-06-20 16:14:36 -03:00
int ret ;
2011-06-11 14:46:43 -03:00
mutex_lock ( & cam - > s_mutex ) ;
2011-06-20 16:14:36 -03:00
ret = vb2_streamon ( & cam - > vb_queue , type ) ;
2011-06-11 14:46:43 -03:00
mutex_unlock ( & cam - > s_mutex ) ;
return ret ;
}
static int mcam_vidioc_streamoff ( struct file * filp , void * priv ,
enum v4l2_buf_type type )
{
struct mcam_camera * cam = filp - > private_data ;
2011-06-20 16:14:36 -03:00
int ret ;
2011-06-11 14:46:43 -03:00
mutex_lock ( & cam - > s_mutex ) ;
2011-06-20 16:14:36 -03:00
ret = vb2_streamoff ( & cam - > vb_queue , type ) ;
2011-06-11 14:46:43 -03:00
mutex_unlock ( & cam - > s_mutex ) ;
return ret ;
}
static int mcam_vidioc_reqbufs ( struct file * filp , void * priv ,
struct v4l2_requestbuffers * req )
{
struct mcam_camera * cam = filp - > private_data ;
2011-06-20 16:14:36 -03:00
int ret ;
2011-06-11 14:46:43 -03:00
mutex_lock ( & cam - > s_mutex ) ;
2011-06-20 16:14:36 -03:00
ret = vb2_reqbufs ( & cam - > vb_queue , req ) ;
2011-06-11 14:46:43 -03:00
mutex_unlock ( & cam - > s_mutex ) ;
return ret ;
}
static int mcam_vidioc_querybuf ( struct file * filp , void * priv ,
struct v4l2_buffer * buf )
{
struct mcam_camera * cam = filp - > private_data ;
2011-06-20 16:14:36 -03:00
int ret ;
2011-06-11 14:46:43 -03:00
mutex_lock ( & cam - > s_mutex ) ;
2011-06-20 16:14:36 -03:00
ret = vb2_querybuf ( & cam - > vb_queue , buf ) ;
2011-06-11 14:46:43 -03:00
mutex_unlock ( & cam - > s_mutex ) ;
return ret ;
}
static int mcam_vidioc_qbuf ( struct file * filp , void * priv ,
struct v4l2_buffer * buf )
{
struct mcam_camera * cam = filp - > private_data ;
2011-06-20 16:14:36 -03:00
int ret ;
2011-06-11 14:46:43 -03:00
mutex_lock ( & cam - > s_mutex ) ;
2011-06-20 16:14:36 -03:00
ret = vb2_qbuf ( & cam - > vb_queue , buf ) ;
2011-06-11 14:46:43 -03:00
mutex_unlock ( & cam - > s_mutex ) ;
return ret ;
}
static int mcam_vidioc_dqbuf ( struct file * filp , void * priv ,
struct v4l2_buffer * buf )
{
struct mcam_camera * cam = filp - > private_data ;
2011-06-20 16:14:36 -03:00
int ret ;
2011-06-11 14:46:43 -03:00
mutex_lock ( & cam - > s_mutex ) ;
2011-06-20 16:14:36 -03:00
ret = vb2_dqbuf ( & cam - > vb_queue , buf , filp - > f_flags & O_NONBLOCK ) ;
2011-06-11 14:46:43 -03:00
mutex_unlock ( & cam - > s_mutex ) ;
return ret ;
}
static int mcam_v4l_mmap ( struct file * filp , struct vm_area_struct * vma )
{
struct mcam_camera * cam = filp - > private_data ;
2011-06-20 16:14:36 -03:00
int ret ;
2011-06-11 14:46:43 -03:00
mutex_lock ( & cam - > s_mutex ) ;
2011-06-20 16:14:36 -03:00
ret = vb2_mmap ( & cam - > vb_queue , vma ) ;
2011-06-11 14:46:43 -03:00
mutex_unlock ( & cam - > s_mutex ) ;
return ret ;
}
static int mcam_v4l_open ( struct file * filp )
{
struct mcam_camera * cam = video_drvdata ( filp ) ;
2011-06-20 16:14:36 -03:00
int ret = 0 ;
2011-06-11 14:46:43 -03:00
filp - > private_data = cam ;
2011-06-20 16:14:40 -03:00
frames = singles = delivered = 0 ;
2011-06-11 14:46:43 -03:00
mutex_lock ( & cam - > s_mutex ) ;
if ( cam - > users = = 0 ) {
2011-06-20 16:14:36 -03:00
ret = mcam_setup_vb2 ( cam ) ;
if ( ret )
goto out ;
2011-06-11 14:46:43 -03:00
mcam_ctlr_power_up ( cam ) ;
__mcam_cam_reset ( cam ) ;
mcam_set_config_needed ( cam , 1 ) ;
}
( cam - > users ) + + ;
2011-06-20 16:14:36 -03:00
out :
2011-06-11 14:46:43 -03:00
mutex_unlock ( & cam - > s_mutex ) ;
2011-06-20 16:14:36 -03:00
return ret ;
2011-06-11 14:46:43 -03:00
}
static int mcam_v4l_release ( struct file * filp )
{
struct mcam_camera * cam = filp - > private_data ;
2011-06-20 16:14:40 -03:00
cam_err ( cam , " Release, %d frames, %d singles, %d delivered \n " , frames ,
singles , delivered ) ;
2011-06-11 14:46:43 -03:00
mutex_lock ( & cam - > s_mutex ) ;
( cam - > users ) - - ;
if ( filp = = cam - > owner ) {
mcam_ctlr_stop_dma ( cam ) ;
cam - > owner = NULL ;
}
if ( cam - > users = = 0 ) {
2011-06-20 16:14:36 -03:00
mcam_cleanup_vb2 ( cam ) ;
2011-06-11 14:46:43 -03:00
mcam_ctlr_power_down ( cam ) ;
2011-06-20 16:14:40 -03:00
if ( cam - > buffer_mode = = B_vmalloc & & alloc_bufs_at_read )
2011-06-11 14:46:43 -03:00
mcam_free_dma_bufs ( cam ) ;
}
mutex_unlock ( & cam - > s_mutex ) ;
return 0 ;
}
static unsigned int mcam_v4l_poll ( struct file * filp ,
struct poll_table_struct * pt )
{
struct mcam_camera * cam = filp - > private_data ;
2011-06-20 16:14:36 -03:00
int ret ;
2011-06-11 14:46:43 -03:00
2011-06-20 16:14:36 -03:00
mutex_lock ( & cam - > s_mutex ) ;
ret = vb2_poll ( & cam - > vb_queue , filp , pt ) ;
mutex_unlock ( & cam - > s_mutex ) ;
return ret ;
2011-06-11 14:46:43 -03:00
}
static int mcam_vidioc_queryctrl ( struct file * filp , void * priv ,
struct v4l2_queryctrl * qc )
{
struct mcam_camera * cam = priv ;
int ret ;
mutex_lock ( & cam - > s_mutex ) ;
ret = sensor_call ( cam , core , queryctrl , qc ) ;
mutex_unlock ( & cam - > s_mutex ) ;
return ret ;
}
static int mcam_vidioc_g_ctrl ( struct file * filp , void * priv ,
struct v4l2_control * ctrl )
{
struct mcam_camera * cam = priv ;
int ret ;
mutex_lock ( & cam - > s_mutex ) ;
ret = sensor_call ( cam , core , g_ctrl , ctrl ) ;
mutex_unlock ( & cam - > s_mutex ) ;
return ret ;
}
static int mcam_vidioc_s_ctrl ( struct file * filp , void * priv ,
struct v4l2_control * ctrl )
{
struct mcam_camera * cam = priv ;
int ret ;
mutex_lock ( & cam - > s_mutex ) ;
ret = sensor_call ( cam , core , s_ctrl , ctrl ) ;
mutex_unlock ( & cam - > s_mutex ) ;
return ret ;
}
static int mcam_vidioc_querycap ( struct file * file , void * priv ,
struct v4l2_capability * cap )
{
strcpy ( cap - > driver , " marvell_ccic " ) ;
strcpy ( cap - > card , " marvell_ccic " ) ;
cap - > version = 1 ;
cap - > capabilities = V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_READWRITE | V4L2_CAP_STREAMING ;
return 0 ;
}
/*
* The default format we use until somebody says otherwise .
*/
static const struct v4l2_pix_format mcam_def_pix_format = {
. width = VGA_WIDTH ,
. height = VGA_HEIGHT ,
. pixelformat = V4L2_PIX_FMT_YUYV ,
. field = V4L2_FIELD_NONE ,
. bytesperline = VGA_WIDTH * 2 ,
. sizeimage = VGA_WIDTH * VGA_HEIGHT * 2 ,
} ;
static const enum v4l2_mbus_pixelcode mcam_def_mbus_code =
V4L2_MBUS_FMT_YUYV8_2X8 ;
static int mcam_vidioc_enum_fmt_vid_cap ( struct file * filp ,
void * priv , struct v4l2_fmtdesc * fmt )
{
if ( fmt - > index > = N_MCAM_FMTS )
return - EINVAL ;
strlcpy ( fmt - > description , mcam_formats [ fmt - > index ] . desc ,
sizeof ( fmt - > description ) ) ;
fmt - > pixelformat = mcam_formats [ fmt - > index ] . pixelformat ;
return 0 ;
}
static int mcam_vidioc_try_fmt_vid_cap ( struct file * filp , void * priv ,
struct v4l2_format * fmt )
{
struct mcam_camera * cam = priv ;
struct mcam_format_struct * f ;
struct v4l2_pix_format * pix = & fmt - > fmt . pix ;
struct v4l2_mbus_framefmt mbus_fmt ;
int ret ;
f = mcam_find_format ( pix - > pixelformat ) ;
pix - > pixelformat = f - > pixelformat ;
v4l2_fill_mbus_format ( & mbus_fmt , pix , f - > mbus_code ) ;
mutex_lock ( & cam - > s_mutex ) ;
ret = sensor_call ( cam , video , try_mbus_fmt , & mbus_fmt ) ;
mutex_unlock ( & cam - > s_mutex ) ;
v4l2_fill_pix_format ( pix , & mbus_fmt ) ;
pix - > bytesperline = pix - > width * f - > bpp ;
pix - > sizeimage = pix - > height * pix - > bytesperline ;
return ret ;
}
static int mcam_vidioc_s_fmt_vid_cap ( struct file * filp , void * priv ,
struct v4l2_format * fmt )
{
struct mcam_camera * cam = priv ;
struct mcam_format_struct * f ;
int ret ;
/*
* Can ' t do anything if the device is not idle
* Also can ' t if there are streaming buffers in place .
*/
2011-06-20 16:14:36 -03:00
if ( cam - > state ! = S_IDLE | | cam - > vb_queue . num_buffers > 0 )
2011-06-11 14:46:43 -03:00
return - EBUSY ;
f = mcam_find_format ( fmt - > fmt . pix . pixelformat ) ;
/*
* See if the formatting works in principle .
*/
ret = mcam_vidioc_try_fmt_vid_cap ( filp , priv , fmt ) ;
if ( ret )
return ret ;
/*
* Now we start to change things for real , so let ' s do it
* under lock .
*/
mutex_lock ( & cam - > s_mutex ) ;
cam - > pix_format = fmt - > fmt . pix ;
cam - > mbus_code = f - > mbus_code ;
/*
* Make sure we have appropriate DMA buffers .
*/
ret = - ENOMEM ;
2011-06-20 16:14:40 -03:00
if ( cam - > buffer_mode = = B_vmalloc ) {
if ( cam - > nbufs > 0 & &
cam - > dma_buf_size < cam - > pix_format . sizeimage )
mcam_free_dma_bufs ( cam ) ;
if ( cam - > nbufs = = 0 ) {
if ( mcam_alloc_dma_bufs ( cam , 0 ) )
goto out ;
}
2011-06-11 14:46:43 -03:00
}
2011-06-20 16:14:40 -03:00
mcam_set_config_needed ( cam , 1 ) ;
ret = 0 ;
2011-06-11 14:46:43 -03:00
out :
mutex_unlock ( & cam - > s_mutex ) ;
return ret ;
}
/*
* Return our stored notion of how the camera is / should be configured .
* The V4l2 spec wants us to be smarter , and actually get this from
* the camera ( and not mess with it at open time ) . Someday .
*/
static int mcam_vidioc_g_fmt_vid_cap ( struct file * filp , void * priv ,
struct v4l2_format * f )
{
struct mcam_camera * cam = priv ;
f - > fmt . pix = cam - > pix_format ;
return 0 ;
}
/*
* We only have one input - the sensor - so minimize the nonsense here .
*/
static int mcam_vidioc_enum_input ( struct file * filp , void * priv ,
struct v4l2_input * input )
{
if ( input - > index ! = 0 )
return - EINVAL ;
input - > type = V4L2_INPUT_TYPE_CAMERA ;
input - > std = V4L2_STD_ALL ; /* Not sure what should go here */
strcpy ( input - > name , " Camera " ) ;
return 0 ;
}
static int mcam_vidioc_g_input ( struct file * filp , void * priv , unsigned int * i )
{
* i = 0 ;
return 0 ;
}
static int mcam_vidioc_s_input ( struct file * filp , void * priv , unsigned int i )
{
if ( i ! = 0 )
return - EINVAL ;
return 0 ;
}
/* from vivi.c */
static int mcam_vidioc_s_std ( struct file * filp , void * priv , v4l2_std_id * a )
{
return 0 ;
}
/*
* G / S_PARM . Most of this is done by the sensor , but we are
* the level which controls the number of read buffers .
*/
static int mcam_vidioc_g_parm ( struct file * filp , void * priv ,
struct v4l2_streamparm * parms )
{
struct mcam_camera * cam = priv ;
int ret ;
mutex_lock ( & cam - > s_mutex ) ;
ret = sensor_call ( cam , video , g_parm , parms ) ;
mutex_unlock ( & cam - > s_mutex ) ;
parms - > parm . capture . readbuffers = n_dma_bufs ;
return ret ;
}
static int mcam_vidioc_s_parm ( struct file * filp , void * priv ,
struct v4l2_streamparm * parms )
{
struct mcam_camera * cam = priv ;
int ret ;
mutex_lock ( & cam - > s_mutex ) ;
ret = sensor_call ( cam , video , s_parm , parms ) ;
mutex_unlock ( & cam - > s_mutex ) ;
parms - > parm . capture . readbuffers = n_dma_bufs ;
return ret ;
}
static int mcam_vidioc_g_chip_ident ( struct file * file , void * priv ,
struct v4l2_dbg_chip_ident * chip )
{
struct mcam_camera * cam = priv ;
chip - > ident = V4L2_IDENT_NONE ;
chip - > revision = 0 ;
if ( v4l2_chip_match_host ( & chip - > match ) ) {
chip - > ident = cam - > chip_id ;
return 0 ;
}
return sensor_call ( cam , core , g_chip_ident , chip ) ;
}
static int mcam_vidioc_enum_framesizes ( struct file * filp , void * priv ,
struct v4l2_frmsizeenum * sizes )
{
struct mcam_camera * cam = priv ;
int ret ;
mutex_lock ( & cam - > s_mutex ) ;
ret = sensor_call ( cam , video , enum_framesizes , sizes ) ;
mutex_unlock ( & cam - > s_mutex ) ;
return ret ;
}
static int mcam_vidioc_enum_frameintervals ( struct file * filp , void * priv ,
struct v4l2_frmivalenum * interval )
{
struct mcam_camera * cam = priv ;
int ret ;
mutex_lock ( & cam - > s_mutex ) ;
ret = sensor_call ( cam , video , enum_frameintervals , interval ) ;
mutex_unlock ( & cam - > s_mutex ) ;
return ret ;
}
# ifdef CONFIG_VIDEO_ADV_DEBUG
static int mcam_vidioc_g_register ( struct file * file , void * priv ,
struct v4l2_dbg_register * reg )
{
struct mcam_camera * cam = priv ;
if ( v4l2_chip_match_host ( & reg - > match ) ) {
reg - > val = mcam_reg_read ( cam , reg - > reg ) ;
reg - > size = 4 ;
return 0 ;
}
return sensor_call ( cam , core , g_register , reg ) ;
}
static int mcam_vidioc_s_register ( struct file * file , void * priv ,
struct v4l2_dbg_register * reg )
{
struct mcam_camera * cam = priv ;
if ( v4l2_chip_match_host ( & reg - > match ) ) {
mcam_reg_write ( cam , reg - > reg , reg - > val ) ;
return 0 ;
}
return sensor_call ( cam , core , s_register , reg ) ;
}
# endif
/*
* This template device holds all of those v4l2 methods ; we
* clone it for specific real devices .
*/
static const struct v4l2_file_operations mcam_v4l_fops = {
. owner = THIS_MODULE ,
. open = mcam_v4l_open ,
. release = mcam_v4l_release ,
. read = mcam_v4l_read ,
. poll = mcam_v4l_poll ,
. mmap = mcam_v4l_mmap ,
. unlocked_ioctl = video_ioctl2 ,
} ;
static const struct v4l2_ioctl_ops mcam_v4l_ioctl_ops = {
. vidioc_querycap = mcam_vidioc_querycap ,
. vidioc_enum_fmt_vid_cap = mcam_vidioc_enum_fmt_vid_cap ,
. vidioc_try_fmt_vid_cap = mcam_vidioc_try_fmt_vid_cap ,
. vidioc_s_fmt_vid_cap = mcam_vidioc_s_fmt_vid_cap ,
. vidioc_g_fmt_vid_cap = mcam_vidioc_g_fmt_vid_cap ,
. vidioc_enum_input = mcam_vidioc_enum_input ,
. vidioc_g_input = mcam_vidioc_g_input ,
. vidioc_s_input = mcam_vidioc_s_input ,
. vidioc_s_std = mcam_vidioc_s_std ,
. vidioc_reqbufs = mcam_vidioc_reqbufs ,
. vidioc_querybuf = mcam_vidioc_querybuf ,
. vidioc_qbuf = mcam_vidioc_qbuf ,
. vidioc_dqbuf = mcam_vidioc_dqbuf ,
. vidioc_streamon = mcam_vidioc_streamon ,
. vidioc_streamoff = mcam_vidioc_streamoff ,
. vidioc_queryctrl = mcam_vidioc_queryctrl ,
. vidioc_g_ctrl = mcam_vidioc_g_ctrl ,
. vidioc_s_ctrl = mcam_vidioc_s_ctrl ,
. vidioc_g_parm = mcam_vidioc_g_parm ,
. vidioc_s_parm = mcam_vidioc_s_parm ,
. vidioc_enum_framesizes = mcam_vidioc_enum_framesizes ,
. vidioc_enum_frameintervals = mcam_vidioc_enum_frameintervals ,
. vidioc_g_chip_ident = mcam_vidioc_g_chip_ident ,
# ifdef CONFIG_VIDEO_ADV_DEBUG
. vidioc_g_register = mcam_vidioc_g_register ,
. vidioc_s_register = mcam_vidioc_s_register ,
# endif
} ;
static struct video_device mcam_v4l_template = {
. name = " mcam " ,
. tvnorms = V4L2_STD_NTSC_M ,
. current_norm = V4L2_STD_NTSC_M , /* make mplayer happy */
. fops = & mcam_v4l_fops ,
. ioctl_ops = & mcam_v4l_ioctl_ops ,
. release = video_device_release_empty ,
} ;
/* ---------------------------------------------------------------------- */
/*
* Interrupt handler stuff
*/
2011-06-20 16:14:40 -03:00
static void mcam_buffer_done ( struct mcam_camera * cam , int frame ,
struct vb2_buffer * vbuf )
{
vbuf - > v4l2_buf . bytesused = cam - > pix_format . sizeimage ;
vbuf - > v4l2_buf . sequence = cam - > buf_seq [ frame ] ;
vb2_set_plane_payload ( vbuf , 0 , cam - > pix_format . sizeimage ) ;
vb2_buffer_done ( vbuf , VB2_BUF_STATE_DONE ) ;
}
2011-06-11 14:46:43 -03:00
2011-06-20 16:14:40 -03:00
/*
* Copy data out to user space in the vmalloc case
*/
2011-06-11 14:46:43 -03:00
static void mcam_frame_tasklet ( unsigned long data )
{
struct mcam_camera * cam = ( struct mcam_camera * ) data ;
int i ;
unsigned long flags ;
2011-06-20 16:14:36 -03:00
struct mcam_vb_buffer * buf ;
2011-06-11 14:46:43 -03:00
spin_lock_irqsave ( & cam - > dev_lock , flags ) ;
for ( i = 0 ; i < cam - > nbufs ; i + + ) {
int bufno = cam - > next_buf ;
2011-06-20 16:14:36 -03:00
if ( cam - > state ! = S_STREAMING | | bufno < 0 )
break ; /* I/O got stopped */
2011-06-11 14:46:43 -03:00
if ( + + ( cam - > next_buf ) > = cam - > nbufs )
cam - > next_buf = 0 ;
if ( ! test_bit ( bufno , & cam - > flags ) )
continue ;
2011-06-20 16:14:40 -03:00
if ( list_empty ( & cam - > buffers ) ) {
singles + + ;
2011-06-11 14:46:43 -03:00
break ; /* Leave it valid, hope for better later */
2011-06-20 16:14:40 -03:00
}
delivered + + ;
2011-06-11 14:46:43 -03:00
clear_bit ( bufno , & cam - > flags ) ;
2011-06-20 16:14:36 -03:00
buf = list_first_entry ( & cam - > buffers , struct mcam_vb_buffer ,
queue ) ;
list_del_init ( & buf - > queue ) ;
2011-06-11 14:46:43 -03:00
/*
* Drop the lock during the big copy . This * should * be safe . . .
*/
spin_unlock_irqrestore ( & cam - > dev_lock , flags ) ;
2011-06-20 16:14:36 -03:00
memcpy ( vb2_plane_vaddr ( & buf - > vb_buf , 0 ) , cam - > dma_bufs [ bufno ] ,
2011-06-11 14:46:43 -03:00
cam - > pix_format . sizeimage ) ;
2011-06-20 16:14:40 -03:00
mcam_buffer_done ( cam , bufno , & buf - > vb_buf ) ;
2011-06-11 14:46:43 -03:00
spin_lock_irqsave ( & cam - > dev_lock , flags ) ;
}
spin_unlock_irqrestore ( & cam - > dev_lock , flags ) ;
}
2011-06-20 16:14:40 -03:00
/*
* For direct DMA , mark the buffer ready and set up another one .
*/
2011-06-30 17:05:27 -03:00
static void mcam_dma_contig_done ( struct mcam_camera * cam , int frame )
2011-06-20 16:14:40 -03:00
{
struct mcam_vb_buffer * buf = cam - > vb_bufs [ frame ] ;
if ( ! test_bit ( CF_SINGLE_BUFFER , & cam - > flags ) ) {
delivered + + ;
mcam_buffer_done ( cam , frame , & buf - > vb_buf ) ;
}
mcam_set_contig_buffer ( cam , frame ) ;
}
2011-06-11 14:46:43 -03:00
2011-06-30 17:05:27 -03:00
/*
* Frame completion with S / G is trickier . We can ' t muck with
* a descriptor chain on the fly , since the controller buffers it
* internally . So we have to actually stop and restart ; Marvell
* says this is the way to do it .
*
* Of course , stopping is easier said than done ; experience shows
* that the controller can start a frame * after * C0_ENABLE has been
* cleared . So when running in S / G mode , the controller is " stopped "
* on receipt of the start - of - frame interrupt . That means we can
* safely change the DMA descriptor array here and restart things
* ( assuming there ' s another buffer waiting to go ) .
*/
static void mcam_dma_sg_done ( struct mcam_camera * cam , int frame )
{
struct mcam_vb_buffer * buf = cam - > vb_bufs [ 0 ] ;
/*
* Very Bad Not Good Things happen if you don ' t clear
* C1_DESC_ENA before making any descriptor changes .
*/
mcam_reg_clear_bit ( cam , REG_CTRL1 , C1_DESC_ENA ) ;
/*
* If we have another buffer available , put it in and
* restart the engine .
*/
if ( ! list_empty ( & cam - > buffers ) ) {
mcam_sg_next_buffer ( cam ) ;
mcam_reg_set_bit ( cam , REG_CTRL1 , C1_DESC_ENA ) ;
mcam_ctlr_start ( cam ) ;
/*
* Otherwise set CF_SG_RESTART and the controller will
* be restarted once another buffer shows up .
*/
} else {
set_bit ( CF_SG_RESTART , & cam - > flags ) ;
singles + + ;
}
/*
* Now we can give the completed frame back to user space .
*/
delivered + + ;
mcam_buffer_done ( cam , frame , & buf - > vb_buf ) ;
}
2011-06-11 14:46:43 -03:00
static void mcam_frame_complete ( struct mcam_camera * cam , int frame )
{
/*
* Basic frame housekeeping .
*/
set_bit ( frame , & cam - > flags ) ;
clear_bit ( CF_DMA_ACTIVE , & cam - > flags ) ;
2011-06-20 16:14:40 -03:00
cam - > next_buf = frame ;
2011-06-11 14:46:43 -03:00
cam - > buf_seq [ frame ] = + + ( cam - > sequence ) ;
2011-06-20 16:14:40 -03:00
cam - > last_delivered = frame ;
frames + + ;
2011-06-11 14:46:43 -03:00
/*
2011-06-30 17:05:27 -03:00
* " This should never happen "
2011-06-11 14:46:43 -03:00
*/
2011-06-30 17:05:27 -03:00
if ( cam - > state ! = S_STREAMING )
return ;
/*
* Process the frame and set up the next one .
*/
switch ( cam - > buffer_mode ) {
case B_vmalloc :
tasklet_schedule ( & cam - > s_tasklet ) ;
break ;
case B_DMA_contig :
mcam_dma_contig_done ( cam , frame ) ;
break ;
case B_DMA_sg :
mcam_dma_sg_done ( cam , frame ) ;
break ;
2011-06-11 14:46:43 -03:00
}
}
int mccic_irq ( struct mcam_camera * cam , unsigned int irqs )
{
unsigned int frame , handled = 0 ;
mcam_reg_write ( cam , REG_IRQSTAT , FRAMEIRQS ) ; /* Clear'em all */
/*
* Handle any frame completions . There really should
* not be more than one of these , or we have fallen
* far behind .
2011-06-30 17:05:27 -03:00
*
* When running in S / G mode , the frame number lacks any
* real meaning - there ' s only one descriptor array - but
* the controller still picks a different one to signal
* each time .
2011-06-11 14:46:43 -03:00
*/
for ( frame = 0 ; frame < cam - > nbufs ; frame + + )
if ( irqs & ( IRQ_EOF0 < < frame ) ) {
mcam_frame_complete ( cam , frame ) ;
handled = 1 ;
}
/*
* If a frame starts , note that we have DMA active . This
* code assumes that we won ' t get multiple frame interrupts
* at once ; may want to rethink that .
*/
if ( irqs & ( IRQ_SOF0 | IRQ_SOF1 | IRQ_SOF2 ) ) {
set_bit ( CF_DMA_ACTIVE , & cam - > flags ) ;
handled = 1 ;
2011-06-30 17:05:27 -03:00
if ( cam - > buffer_mode = = B_DMA_sg )
mcam_ctlr_stop ( cam ) ;
2011-06-11 14:46:43 -03:00
}
return handled ;
}
/*
* Registration and such .
*/
static struct ov7670_config sensor_cfg = {
/*
* Exclude QCIF mode , because it only captures a tiny portion
* of the sensor FOV
*/
. min_width = 320 ,
. min_height = 240 ,
} ;
int mccic_register ( struct mcam_camera * cam )
{
struct i2c_board_info ov7670_info = {
. type = " ov7670 " ,
2011-06-11 14:46:47 -03:00
. addr = 0x42 > > 1 ,
2011-06-11 14:46:43 -03:00
. platform_data = & sensor_cfg ,
} ;
int ret ;
/*
* Register with V4L
*/
ret = v4l2_device_register ( cam - > dev , & cam - > v4l2_dev ) ;
if ( ret )
return ret ;
mutex_init ( & cam - > s_mutex ) ;
cam - > state = S_NOTREADY ;
mcam_set_config_needed ( cam , 1 ) ;
cam - > pix_format = mcam_def_pix_format ;
cam - > mbus_code = mcam_def_mbus_code ;
INIT_LIST_HEAD ( & cam - > dev_list ) ;
2011-06-20 16:14:36 -03:00
INIT_LIST_HEAD ( & cam - > buffers ) ;
2011-06-11 14:46:43 -03:00
tasklet_init ( & cam - > s_tasklet , mcam_frame_tasklet , ( unsigned long ) cam ) ;
2011-06-20 16:14:40 -03:00
/*
* User space may want to override the asked - for buffer mode ;
* here ' s hoping they know what they ' re doing .
*/
if ( buffer_mode = = 0 )
cam - > buffer_mode = B_vmalloc ;
else if ( buffer_mode = = 1 )
cam - > buffer_mode = B_DMA_contig ;
2011-06-30 17:05:27 -03:00
else if ( buffer_mode = = 2 ) {
if ( cam - > chip_id = = V4L2_IDENT_ARMADA610 )
cam - > buffer_mode = B_DMA_sg ;
else {
printk ( KERN_ERR " marvell-cam: Cafe can't do S/G I/O \n " ) ;
cam - > buffer_mode = B_vmalloc ;
}
} else if ( buffer_mode ! = - 1 )
printk ( KERN_ERR " marvell-cam: "
2011-06-20 16:14:40 -03:00
" Strange module buffer mode %d - ignoring \n " ,
buffer_mode ) ;
2011-06-11 14:46:43 -03:00
mcam_ctlr_init ( cam ) ;
/*
* Try to find the sensor .
*/
2011-06-11 14:46:44 -03:00
sensor_cfg . clock_speed = cam - > clock_speed ;
sensor_cfg . use_smbus = cam - > use_smbus ;
2011-06-11 14:46:43 -03:00
cam - > sensor_addr = ov7670_info . addr ;
cam - > sensor = v4l2_i2c_new_subdev_board ( & cam - > v4l2_dev ,
2011-06-11 14:46:48 -03:00
cam - > i2c_adapter , & ov7670_info , NULL ) ;
2011-06-11 14:46:43 -03:00
if ( cam - > sensor = = NULL ) {
ret = - ENODEV ;
goto out_unregister ;
}
ret = mcam_cam_init ( cam ) ;
if ( ret )
goto out_unregister ;
/*
* Get the v4l2 setup done .
*/
mutex_lock ( & cam - > s_mutex ) ;
cam - > vdev = mcam_v4l_template ;
cam - > vdev . debug = 0 ;
cam - > vdev . v4l2_dev = & cam - > v4l2_dev ;
ret = video_register_device ( & cam - > vdev , VFL_TYPE_GRABBER , - 1 ) ;
if ( ret )
goto out ;
video_set_drvdata ( & cam - > vdev , cam ) ;
/*
* If so requested , try to get our DMA buffers now .
*/
2011-06-20 16:14:40 -03:00
if ( cam - > buffer_mode = = B_vmalloc & & ! alloc_bufs_at_read ) {
2011-06-11 14:46:43 -03:00
if ( mcam_alloc_dma_bufs ( cam , 1 ) )
cam_warn ( cam , " Unable to alloc DMA buffers at load "
" will try again later. " ) ;
}
out :
mutex_unlock ( & cam - > s_mutex ) ;
return ret ;
out_unregister :
v4l2_device_unregister ( & cam - > v4l2_dev ) ;
return ret ;
}
void mccic_shutdown ( struct mcam_camera * cam )
{
2011-06-11 14:46:49 -03:00
/*
* If we have no users ( and we really , really should have no
* users ) the device will already be powered down . Trying to
* take it down again will wedge the machine , which is frowned
* upon .
*/
if ( cam - > users > 0 ) {
2011-06-11 14:46:43 -03:00
cam_warn ( cam , " Removing a device with users! \n " ) ;
2011-06-11 14:46:49 -03:00
mcam_ctlr_power_down ( cam ) ;
}
2011-06-20 16:14:36 -03:00
vb2_queue_release ( & cam - > vb_queue ) ;
2011-06-20 16:14:40 -03:00
if ( cam - > buffer_mode = = B_vmalloc )
mcam_free_dma_bufs ( cam ) ;
2011-06-11 14:46:43 -03:00
video_unregister_device ( & cam - > vdev ) ;
v4l2_device_unregister ( & cam - > v4l2_dev ) ;
}
/*
* Power management
*/
# ifdef CONFIG_PM
void mccic_suspend ( struct mcam_camera * cam )
{
enum mcam_state cstate = cam - > state ;
mcam_ctlr_stop_dma ( cam ) ;
mcam_ctlr_power_down ( cam ) ;
cam - > state = cstate ;
}
int mccic_resume ( struct mcam_camera * cam )
{
int ret = 0 ;
mutex_lock ( & cam - > s_mutex ) ;
if ( cam - > users > 0 ) {
mcam_ctlr_power_up ( cam ) ;
__mcam_cam_reset ( cam ) ;
} else {
mcam_ctlr_power_down ( cam ) ;
}
mutex_unlock ( & cam - > s_mutex ) ;
set_bit ( CF_CONFIG_NEEDED , & cam - > flags ) ;
2011-06-20 16:14:36 -03:00
if ( cam - > state = = S_STREAMING )
2011-06-20 16:14:40 -03:00
ret = mcam_read_setup ( cam ) ;
2011-06-11 14:46:43 -03:00
return ret ;
}
# endif /* CONFIG_PM */