Update to 3.4-final.
[linux-flexiantxendom0-3.2.10.git] / drivers / media / video / s5p-fimc / fimc-core.h
index 87a89f1..84fd835 100644 (file)
@@ -43,6 +43,7 @@
 #define SCALER_MAX_HRATIO      64
 #define SCALER_MAX_VRATIO      64
 #define DMA_MIN_SIZE           8
+#define FIMC_CAMIF_MAX_HEIGHT  0x2000
 
 /* indices to the clocks array */
 enum {
@@ -61,9 +62,12 @@ enum fimc_dev_flags {
        ST_CAPT_PEND,
        ST_CAPT_RUN,
        ST_CAPT_STREAM,
+       ST_CAPT_ISP_STREAM,
+       ST_CAPT_SUSPENDED,
        ST_CAPT_SHUT,
        ST_CAPT_BUSY,
        ST_CAPT_APPLY_CFG,
+       ST_CAPT_JPEG,
 };
 
 #define fimc_m2m_active(dev) test_bit(ST_M2M_RUN, &(dev)->state)
@@ -81,7 +85,9 @@ enum fimc_datapath {
 };
 
 enum fimc_color_fmt {
-       S5P_FIMC_RGB565 = 0x10,
+       S5P_FIMC_RGB444 = 0x10,
+       S5P_FIMC_RGB555,
+       S5P_FIMC_RGB565,
        S5P_FIMC_RGB666,
        S5P_FIMC_RGB888,
        S5P_FIMC_RGB30_LOCAL,
@@ -91,9 +97,14 @@ enum fimc_color_fmt {
        S5P_FIMC_CBYCRY422,
        S5P_FIMC_CRYCBY422,
        S5P_FIMC_YCBCR444_LOCAL,
+       S5P_FIMC_JPEG = 0x40,
 };
 
-#define fimc_fmt_is_rgb(x) ((x) & 0x10)
+#define fimc_fmt_is_rgb(x) (!!((x) & 0x10))
+#define fimc_fmt_is_jpeg(x) (!!((x) & 0x40))
+
+#define IS_M2M(__strt) ((__strt) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE || \
+                       __strt == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
 
 /* Cb/Cr chrominance components order for 2 plane Y/CbCr 4:2:2 formats. */
 #define        S5P_FIMC_LSB_CRCB       S5P_CIOCTRL_ORDER422_2P_LSB_CRCB
@@ -112,9 +123,10 @@ enum fimc_color_fmt {
 #define        FIMC_DST_ADDR           (1 << 2)
 #define        FIMC_SRC_FMT            (1 << 3)
 #define        FIMC_DST_FMT            (1 << 4)
-#define        FIMC_CTX_M2M            (1 << 5)
-#define        FIMC_CTX_CAP            (1 << 6)
-#define        FIMC_CTX_SHUT           (1 << 7)
+#define        FIMC_DST_CROP           (1 << 5)
+#define        FIMC_CTX_M2M            (1 << 16)
+#define        FIMC_CTX_CAP            (1 << 17)
+#define        FIMC_CTX_SHUT           (1 << 18)
 
 /* Image conversion flags */
 #define        FIMC_IN_DMA_ACCESS_TILED        (1 << 0)
@@ -150,8 +162,11 @@ struct fimc_fmt {
        u16     colplanes;
        u8      depth[VIDEO_MAX_PLANES];
        u16     flags;
-#define FMT_FLAGS_CAM  (1 << 0)
-#define FMT_FLAGS_M2M  (1 << 1)
+#define FMT_FLAGS_CAM          (1 << 0)
+#define FMT_FLAGS_M2M_IN       (1 << 1)
+#define FMT_FLAGS_M2M_OUT      (1 << 2)
+#define FMT_FLAGS_M2M          (1 << 1 | 1 << 2)
+#define FMT_HAS_ALPHA          (1 << 3)
 };
 
 /**
@@ -273,6 +288,7 @@ struct fimc_frame {
        struct fimc_addr        paddr;
        struct fimc_dma_offset  dma_offset;
        struct fimc_fmt         *fmt;
+       u8                      alpha;
 };
 
 /**
@@ -289,13 +305,18 @@ struct fimc_m2m_device {
        int                     refcnt;
 };
 
+#define FIMC_SD_PAD_SINK       0
+#define FIMC_SD_PAD_SOURCE     1
+#define FIMC_SD_PADS_NUM       2
+
 /**
  * struct fimc_vid_cap - camera capture device information
  * @ctx: hardware context data
  * @vfd: video device node for camera capture mode
- * @sd: pointer to camera sensor subdevice currently in use
+ * @subdev: subdev exposing the FIMC processing block
  * @vd_pad: fimc video capture node pad
- * @fmt: Media Bus format configured at selected image sensor
+ * @sd_pads: fimc video processing block pads
+ * @mf: media bus format at the FIMC camera input (and the scaler output) pad
  * @pending_buf_q: the pending buffer queue head
  * @active_buf_q: the queue head of buffers scheduled in hardware
  * @vbq: the capture am video buffer queue
@@ -312,9 +333,10 @@ struct fimc_vid_cap {
        struct fimc_ctx                 *ctx;
        struct vb2_alloc_ctx            *alloc_ctx;
        struct video_device             *vfd;
-       struct v4l2_subdev              *sd;;
+       struct v4l2_subdev              *subdev;
        struct media_pad                vd_pad;
-       struct v4l2_mbus_framefmt       fmt;
+       struct v4l2_mbus_framefmt       mf;
+       struct media_pad                sd_pads[FIMC_SD_PADS_NUM];
        struct list_head                pending_buf_q;
        struct list_head                active_buf_q;
        struct vb2_queue                vbq;
@@ -361,6 +383,7 @@ struct fimc_pix_limit {
  * @min_inp_pixsize: minimum input pixel size
  * @min_out_pixsize: minimum output pixel size
  * @hor_offs_align: horizontal pixel offset aligment
+ * @min_vsize_align: minimum vertical pixel size alignment
  * @out_buf_count: the number of buffers in output DMA sequence
  */
 struct samsung_fimc_variant {
@@ -370,10 +393,12 @@ struct samsung_fimc_variant {
        unsigned int    has_cistatus2:1;
        unsigned int    has_mainscaler_ext:1;
        unsigned int    has_cam_if:1;
+       unsigned int    has_alpha:1;
        struct fimc_pix_limit *pix_limit;
        u16             min_inp_pixsize;
        u16             min_out_pixsize;
        u16             hor_offs_align;
+       u16             min_vsize_align;
        u16             out_buf_count;
 };
 
@@ -409,7 +434,6 @@ struct fimc_ctx;
  * @num_clocks: the number of clocks managed by this device instance
  * @clock:     clocks required for FIMC operation
  * @regs:      the mapped hardware registers
- * @regs_res:  the resource claimed for IO registers
  * @irq:       FIMC interrupt number
  * @irq_queue: interrupt handler waitqueue
  * @v4l2_dev:  root v4l2_device
@@ -429,7 +453,6 @@ struct fimc_dev {
        u16                             num_clocks;
        struct clk                      *clock[MAX_FIMC_CLOCKS];
        void __iomem                    *regs;
-       struct resource                 *regs_res;
        int                             irq;
        wait_queue_head_t               irq_queue;
        struct v4l2_device              *v4l2_dev;
@@ -464,7 +487,8 @@ struct fimc_dev {
  * @ctrl_handler:      v4l2 controls handler
  * @ctrl_rotate                image rotation control
  * @ctrl_hflip         horizontal flip control
- * @ctrl_vflip         vartical flip control
+ * @ctrl_vflip         vertical flip control
+ * @ctrl_alpha         RGB alpha control
  * @ctrls_rdy:         true if the control handler is initialized
  */
 struct fimc_ctx {
@@ -491,11 +515,39 @@ struct fimc_ctx {
        struct v4l2_ctrl        *ctrl_rotate;
        struct v4l2_ctrl        *ctrl_hflip;
        struct v4l2_ctrl        *ctrl_vflip;
+       struct v4l2_ctrl        *ctrl_alpha;
        bool                    ctrls_rdy;
 };
 
 #define fh_to_ctx(__fh) container_of(__fh, struct fimc_ctx, fh)
 
+static inline void set_frame_bounds(struct fimc_frame *f, u32 width, u32 height)
+{
+       f->o_width  = width;
+       f->o_height = height;
+       f->f_width  = width;
+       f->f_height = height;
+}
+
+static inline void set_frame_crop(struct fimc_frame *f,
+                                 u32 left, u32 top, u32 width, u32 height)
+{
+       f->offs_h = left;
+       f->offs_v = top;
+       f->width  = width;
+       f->height = height;
+}
+
+static inline u32 fimc_get_format_depth(struct fimc_fmt *ff)
+{
+       u32 i, depth = 0;
+
+       if (ff != NULL)
+               for (i = 0; i < ff->colplanes; i++)
+                       depth += ff->depth[i];
+       return depth;
+}
+
 static inline bool fimc_capture_active(struct fimc_dev *fimc)
 {
        unsigned long flags;
@@ -533,6 +585,17 @@ static inline int tiled_fmt(struct fimc_fmt *fmt)
        return fmt->fourcc == V4L2_PIX_FMT_NV12MT;
 }
 
+/* Return the alpha component bit mask */
+static inline int fimc_get_alpha_mask(struct fimc_fmt *fmt)
+{
+       switch (fmt->color) {
+       case S5P_FIMC_RGB444:   return 0x0f;
+       case S5P_FIMC_RGB555:   return 0x01;
+       case S5P_FIMC_RGB888:   return 0xff;
+       default:                return 0;
+       };
+}
+
 static inline void fimc_hw_clear_irq(struct fimc_dev *dev)
 {
        u32 cfg = readl(dev->regs + S5P_CIGCTRL);
@@ -628,7 +691,8 @@ void fimc_hw_en_irq(struct fimc_dev *fimc, int enable);
 void fimc_hw_set_prescaler(struct fimc_ctx *ctx);
 void fimc_hw_set_mainscaler(struct fimc_ctx *ctx);
 void fimc_hw_en_capture(struct fimc_ctx *ctx);
-void fimc_hw_set_effect(struct fimc_ctx *ctx);
+void fimc_hw_set_effect(struct fimc_ctx *ctx, bool active);
+void fimc_hw_set_rgb_alpha(struct fimc_ctx *ctx);
 void fimc_hw_set_in_dma(struct fimc_ctx *ctx);
 void fimc_hw_set_input_path(struct fimc_ctx *ctx);
 void fimc_hw_set_output_path(struct fimc_ctx *ctx);
@@ -647,22 +711,27 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc,
 /* fimc-core.c */
 int fimc_vidioc_enum_fmt_mplane(struct file *file, void *priv,
                                struct v4l2_fmtdesc *f);
-int fimc_try_fmt_mplane(struct fimc_ctx *ctx, struct v4l2_format *f);
-int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr);
 int fimc_ctrls_create(struct fimc_ctx *ctx);
 void fimc_ctrls_delete(struct fimc_ctx *ctx);
 void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active);
+void fimc_alpha_ctrl_update(struct fimc_ctx *ctx);
 int fimc_fill_format(struct fimc_frame *frame, struct v4l2_format *f);
+void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height,
+                              struct v4l2_pix_format_mplane *pix);
+struct fimc_fmt *fimc_find_format(const u32 *pixelformat, const u32 *mbus_code,
+                                 unsigned int mask, int index);
 
-struct fimc_fmt *find_format(struct v4l2_format *f, unsigned int mask);
-struct fimc_fmt *find_mbus_format(struct v4l2_mbus_framefmt *f,
-                                 unsigned int mask);
-
-int fimc_check_scaler_ratio(int sw, int sh, int dw, int dh, int rot);
+int fimc_check_scaler_ratio(struct fimc_ctx *ctx, int sw, int sh,
+                           int dw, int dh, int rotation);
 int fimc_set_scaler_info(struct fimc_ctx *ctx);
 int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags);
 int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb,
                      struct fimc_frame *frame, struct fimc_addr *paddr);
+void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f);
+void fimc_set_yuv_order(struct fimc_ctx *ctx);
+void fimc_fill_frame(struct fimc_frame *frame, struct v4l2_format *f);
+void fimc_capture_irq_handler(struct fimc_dev *fimc, bool done);
+
 int fimc_register_m2m_device(struct fimc_dev *fimc,
                             struct v4l2_device *v4l2_dev);
 void fimc_unregister_m2m_device(struct fimc_dev *fimc);
@@ -677,8 +746,11 @@ void fimc_unregister_capture_device(struct fimc_dev *fimc);
 int fimc_capture_ctrls_create(struct fimc_dev *fimc);
 int fimc_vid_cap_buf_queue(struct fimc_dev *fimc,
                             struct fimc_vid_buffer *fimc_vb);
+void fimc_sensor_notify(struct v4l2_subdev *sd, unsigned int notification,
+                       void *arg);
 int fimc_capture_suspend(struct fimc_dev *fimc);
 int fimc_capture_resume(struct fimc_dev *fimc);
+int fimc_capture_config_update(struct fimc_ctx *ctx);
 
 /* Locking: the caller holds fimc->slock */
 static inline void fimc_activate_capture(struct fimc_ctx *ctx)
@@ -696,22 +768,27 @@ static inline void fimc_deactivate_capture(struct fimc_dev *fimc)
 }
 
 /*
- * Add buf to the capture active buffers queue.
- * Locking: Need to be called with fimc_dev::slock held.
+ * Buffer list manipulation functions. Must be called with fimc.slock held.
  */
-static inline void active_queue_add(struct fimc_vid_cap *vid_cap,
-                                   struct fimc_vid_buffer *buf)
+
+/**
+ * fimc_active_queue_add - add buffer to the capture active buffers queue
+ * @buf: buffer to add to the active buffers list
+ */
+static inline void fimc_active_queue_add(struct fimc_vid_cap *vid_cap,
+                                        struct fimc_vid_buffer *buf)
 {
        list_add_tail(&buf->list, &vid_cap->active_buf_q);
        vid_cap->active_buf_cnt++;
 }
 
-/*
- * Pop a video buffer from the capture active buffers queue
- * Locking: Need to be called with fimc_dev::slock held.
+/**
+ * fimc_active_queue_pop - pop buffer from the capture active buffers queue
+ *
+ * The caller must assure the active_buf_q list is not empty.
  */
-static inline struct fimc_vid_buffer *
-active_queue_pop(struct fimc_vid_cap *vid_cap)
+static inline struct fimc_vid_buffer *fimc_active_queue_pop(
+                                   struct fimc_vid_cap *vid_cap)
 {
        struct fimc_vid_buffer *buf;
        buf = list_entry(vid_cap->active_buf_q.next,
@@ -721,16 +798,23 @@ active_queue_pop(struct fimc_vid_cap *vid_cap)
        return buf;
 }
 
-/* Add video buffer to the capture pending buffers queue */
+/**
+ * fimc_pending_queue_add - add buffer to the capture pending buffers queue
+ * @buf: buffer to add to the pending buffers list
+ */
 static inline void fimc_pending_queue_add(struct fimc_vid_cap *vid_cap,
                                          struct fimc_vid_buffer *buf)
 {
        list_add_tail(&buf->list, &vid_cap->pending_buf_q);
 }
 
-/* Add video buffer to the capture pending buffers queue */
-static inline struct fimc_vid_buffer *
-pending_queue_pop(struct fimc_vid_cap *vid_cap)
+/**
+ * fimc_pending_queue_pop - pop buffer from the capture pending buffers queue
+ *
+ * The caller must assure the pending_buf_q list is not empty.
+ */
+static inline struct fimc_vid_buffer *fimc_pending_queue_pop(
+                                    struct fimc_vid_cap *vid_cap)
 {
        struct fimc_vid_buffer *buf;
        buf = list_entry(vid_cap->pending_buf_q.next,