/*
 * Copyright 2004 Freescale Semiconductor, Inc. All Rights Reserved.
 */

/* 
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 * 
 * http://www.opensource.org/licenses/gpl-license.html 
 * http://www.gnu.org/copyleft/gpl.html
 */

/*!
 * @file mxc_v4l2_capture.h
 * 
 * @brief mxc V4L2 capture device API  Header file  
 *
 * It include all the defines for frame operations, also three structure defines
 * use case ops structure, common v4l2 driver structure and frame structure.
 *
 * @ingroup IPU
 */
#ifndef mxc_v4l2_capture_h
#define mxc_v4l2_capture_h

#include <asm/uaccess.h>
#include <linux/videodev.h>
#include <linux/list.h>
#include <linux/smp_lock.h>
#include "../../../drivers/mxc/ipu/ipu.h"

#ifdef CONFIG_FB_MXC_16BPP
#define GRAPHIC_BPP     16
#elif CONFIG_FB_MXC_24BPP
#define GRAPHIC_BPP     24
#elif CONFIG_FB_MXC_32BPP
#define GRAPHIC_BPP     32
#endif

#define FRAME_NUM 3	

#define V4L2_CID_MXC_ENC_ROT       (V4L2_CID_PRIVATE_BASE+0)

/*!
 * The flag enum for the chained buffer management
 */
enum 
{
        FRAME_QUEUED,    /*!< Ready to grab into */
        FRAME_GRABBED,   /*!< Have been grabbed into */
        FRAME_UNUSED,    /*!< Unused */
};

/*!
 *  Use case ops structure.
 */
struct mxc_v4l_camera_ops
{
        /*!
         * open sets privdata to point to structure for this camera.
         * Returns negative value on error, otherwise 0.
         */
        int (*open)(void *privdata);

        /*!
         * streamStart initiates stream capture mode.
         * Returns negative value on error, otherwise 0.
         */
        int (*streamStart)(void *privdata);

        /*!
         * streamStop terminates stream capture mode.
         * Returns negative value on error, otherwise 0.
         */
        int (*streamStop)(void *privdata);
    
        /*
         * streamRead reads a frame from the camera.  buffer points to a
         * buffer large enough to hold a complete frame in kernel space.
         * noblock indicates if this should be a non blocking read.
         * Returns the number of bytes read, or negative value on error.
         */
        int (*streamRead)(void *privdata, u8 *buffer, int noblock);

        /*!
         * close disables the device until open() is called again.
         * Returns negative value on error, otherwise 0.
         */
        int (*close)(void *privdata);

        struct module *owner;
};

typedef struct _MXC_YUV_PTR
{
        u32 y;      /* Y data (line align8) */
        u32 u;      /* U data (line align4) */
        u32 v;      /* V data (line align4) */
        u32 qp;     /* Quantization (line align4) */
} MXC_YUV_PTR;

/*!
 * v4l2 frame structure.
 */
struct mxc_v4l_frame
{
        MXC_YUV_PTR data;           /*!< Physical Address */
        int count;
        int width;
        int height;
        /*! 
         * Frame flag FRAME_QUEUED/FRAME_GRABBED/FRAME_UNUSED 
         */
        volatile int state;	
        struct v4l2_buffer buffer; 
};

/*!
 * common v4l2 driver structure.
 */
typedef struct _cam_data
{
        struct video_device *video_dev;

        /*!
         * semaphore guard against SMP multithreading 
         */
        struct semaphore busy_lock;     

        /*! 
         * number of process that have camera open 
         */
        int open_count;

        /*! 
         * params lock for this camera 
         */
        struct semaphore param_lock;    

        int headFrame;               
        int tailFrame;               
        int ping_pong_csi;
        int ping_pong_rot;
        spinlock_t int_lock;

        /*! 
         * FRAME_NUM-buffering, so we need a array 
         */
        struct mxc_v4l_frame frame[FRAME_NUM]; 

        int skip_frame;
        /*! 
         * Poll wait queue 
         */
        wait_queue_head_t enc_queue;			  
        int enc_counter;

        enum v4l2_buf_type type;

        /*! 
         * v4l2 format
         */
        struct v4l2_format v2f;
        ipu_rotate_mode_t rotation;

        /* V4l2 control bit */ 
        int bright;
        int hue;
        int contrast;
        int saturation;

        void *rot_vf_bufs[2];
        void *rot_enc_bufs[2];

        /* still image capture */
        wait_queue_head_t still_queue;			  
        int still_counter;
        void *still_buf;

        /*! 
         * video overlay
         */
        struct v4l2_window win;
        struct v4l2_framebuffer ovbuf;
        enum v4l2_field ovfield;
        struct v4l2_clip clips[8];
        unsigned int nclips;
        void *vf_bufs[2];
        bool overlay_active;
        int output;

        /* standart */
        struct v4l2_streamparm streamparm;
        struct v4l2_standard standard;

        /* crop */
        struct v4l2_rect crop_bounds;
        struct v4l2_rect crop_defrect;
        struct v4l2_rect crop_current;

        void (*enc_update_eba)(u32 eba, int *bufferNum);
        void (*enc_enable)(void *private);
        void (*enc_disable)(void *private);
        void (*vf_start_adc)(void *private);
        void (*vf_stop_adc)(void *private);
        void (*vf_start_sdc)(void *private);
        void (*vf_stop_sdc)(void *private);
        void (*csi_start)(void *private);
        void (*csi_stop)(void *private);
        
        /* status flag */
        bool overlay_on;
        bool capture_on;
        bool low_power;           
        wait_queue_head_t power_queue;			  
}cam_data;

int camera_init(void);
void camera_exit(void);
void camera_callback(u32 mask, void *dev);
void prp_enc_select(void *private);
void prp_enc_deselect(void *private);
void prp_vf_adc_select(void *private);
void prp_vf_sdc_select(void *private);
void prp_vf_adc_deselect(void *private);
void prp_vf_sdc_deselect(void *private);
void prp_still_select(void *private);
void prp_still_deselect(void *private);

#endif /* mxc_v4l2_capture_h */
