diff options
Diffstat (limited to 'drivers/media/video/s5p-fimc/fimc-core.h')
-rw-r--r-- | drivers/media/video/s5p-fimc/fimc-core.h | 180 |
1 files changed, 96 insertions, 84 deletions
diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h index 4f047d35f8a..3beb1e5320c 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.h +++ b/drivers/media/video/s5p-fimc/fimc-core.h @@ -14,29 +14,27 @@ /*#define DEBUG*/ #include <linux/sched.h> +#include <linux/spinlock.h> #include <linux/types.h> #include <linux/videodev2.h> -#include <media/videobuf-core.h> +#include <linux/io.h> +#include <media/videobuf2-core.h> #include <media/v4l2-device.h> #include <media/v4l2-mem2mem.h> #include <media/v4l2-mediabus.h> -#include <media/s3c_fimc.h> +#include <media/s5p_fimc.h> #include "regs-fimc.h" #define err(fmt, args...) \ printk(KERN_ERR "%s:%d: " fmt "\n", __func__, __LINE__, ##args) -#ifdef DEBUG #define dbg(fmt, args...) \ - printk(KERN_DEBUG "%s:%d: " fmt "\n", __func__, __LINE__, ##args) -#else -#define dbg(fmt, args...) -#endif + pr_debug("%s:%d: " fmt "\n", __func__, __LINE__, ##args) /* Time to wait for next frame VSYNC interrupt while stopping operation. */ #define FIMC_SHUTDOWN_TIMEOUT ((100*HZ)/1000) -#define NUM_FIMC_CLOCKS 2 +#define MAX_FIMC_CLOCKS 3 #define MODULE_NAME "s5p-fimc" #define FIMC_MAX_DEVS 4 #define FIMC_MAX_OUT_BUFS 4 @@ -44,7 +42,13 @@ #define SCALER_MAX_VRATIO 64 #define DMA_MIN_SIZE 8 -/* FIMC device state flags */ +/* indices to the clocks array */ +enum { + CLK_BUS, + CLK_GATE, + CLK_CAM, +}; + enum fimc_dev_flags { /* for m2m node */ ST_IDLE, @@ -63,20 +67,6 @@ enum fimc_dev_flags { #define fimc_capture_running(dev) test_bit(ST_CAPT_RUN, &(dev)->state) #define fimc_capture_pending(dev) test_bit(ST_CAPT_PEND, &(dev)->state) -#define fimc_capture_active(dev) \ - (test_bit(ST_CAPT_RUN, &(dev)->state) || \ - test_bit(ST_CAPT_PEND, &(dev)->state)) - -#define fimc_capture_streaming(dev) \ - test_bit(ST_CAPT_STREAM, &(dev)->state) - -#define fimc_buf_finish(dev, vid_buf) do { \ - spin_lock(&(dev)->irqlock); \ - (vid_buf)->vb.state = VIDEOBUF_DONE; \ - spin_unlock(&(dev)->irqlock); \ - wake_up(&(vid_buf)->vb.done); \ -} while (0) - enum fimc_datapath { FIMC_CAMERA, FIMC_DMA, @@ -90,7 +80,6 @@ enum fimc_color_fmt { S5P_FIMC_RGB888, S5P_FIMC_RGB30_LOCAL, S5P_FIMC_YCBCR420 = 0x20, - S5P_FIMC_YCBCR422, S5P_FIMC_YCBYCR422, S5P_FIMC_YCRYCB422, S5P_FIMC_CBYCRY422, @@ -100,18 +89,6 @@ enum fimc_color_fmt { #define fimc_fmt_is_rgb(x) ((x) & 0x10) -/* Y/Cb/Cr components order at DMA output for 1 plane YCbCr 4:2:2 formats. */ -#define S5P_FIMC_OUT_CRYCBY S5P_CIOCTRL_ORDER422_CRYCBY -#define S5P_FIMC_OUT_CBYCRY S5P_CIOCTRL_ORDER422_YCRYCB -#define S5P_FIMC_OUT_YCRYCB S5P_CIOCTRL_ORDER422_CBYCRY -#define S5P_FIMC_OUT_YCBYCR S5P_CIOCTRL_ORDER422_YCBYCR - -/* Input Y/Cb/Cr components order for 1 plane YCbCr 4:2:2 color formats. */ -#define S5P_FIMC_IN_CRYCBY S5P_MSCTRL_ORDER422_CRYCBY -#define S5P_FIMC_IN_CBYCRY S5P_MSCTRL_ORDER422_YCRYCB -#define S5P_FIMC_IN_YCRYCB S5P_MSCTRL_ORDER422_CBYCRY -#define S5P_FIMC_IN_YCBYCR S5P_MSCTRL_ORDER422_YCBYCR - /* 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 @@ -131,6 +108,7 @@ enum fimc_color_fmt { #define FIMC_DST_FMT (1 << 4) #define FIMC_CTX_M2M (1 << 5) #define FIMC_CTX_CAP (1 << 6) +#define FIMC_CTX_SHUT (1 << 7) /* Image conversion flags */ #define FIMC_IN_DMA_ACCESS_TILED (1 << 0) @@ -157,18 +135,18 @@ enum fimc_color_fmt { * @name: format description * @fourcc: the fourcc code for this format, 0 if not applicable * @color: the corresponding fimc_color_fmt - * @depth: driver's private 'number of bits per pixel' - * @buff_cnt: number of physically non-contiguous data planes - * @planes_cnt: number of physically contiguous data planes + * @depth: per plane driver's private 'number of bits per pixel' + * @memplanes: number of physically non-contiguous data planes + * @colplanes: number of physically contiguous data planes */ struct fimc_fmt { enum v4l2_mbus_pixelcode mbus_code; char *name; u32 fourcc; u32 color; - u16 buff_cnt; - u16 planes_cnt; - u16 depth; + u16 memplanes; + u16 colplanes; + u8 depth[VIDEO_MAX_PLANES]; u16 flags; #define FMT_FLAGS_CAM (1 << 0) #define FMT_FLAGS_M2M (1 << 1) @@ -260,7 +238,8 @@ struct fimc_addr { * @index: buffer index for the output DMA engine */ struct fimc_vid_buffer { - struct videobuf_buffer vb; + struct vb2_buffer vb; + struct list_head list; struct fimc_addr paddr; int index; }; @@ -277,7 +256,7 @@ struct fimc_vid_buffer { * @height: image pixel weight * @paddr: image frame buffer physical addresses * @buf_cnt: number of buffers depending on a color format - * @size: image size in bytes + * @payload: image size in bytes (w x h x bpp) * @color: color format * @dma_offset: DMA offset in bytes */ @@ -290,7 +269,7 @@ struct fimc_frame { u32 offs_v; u32 width; u32 height; - u32 size; + unsigned long payload[VIDEO_MAX_PLANES]; struct fimc_addr paddr; struct fimc_dma_offset dma_offset; struct fimc_fmt *fmt; @@ -331,13 +310,14 @@ struct fimc_m2m_device { */ struct fimc_vid_cap { struct fimc_ctx *ctx; + struct vb2_alloc_ctx *alloc_ctx; struct video_device *vfd; struct v4l2_device v4l2_dev; - struct v4l2_subdev *sd; + struct v4l2_subdev *sd;; struct v4l2_mbus_framefmt fmt; struct list_head pending_buf_q; struct list_head active_buf_q; - struct videobuf_queue vbq; + struct vb2_queue vbq; int active_buf_cnt; int buf_index; unsigned int frame_count; @@ -372,6 +352,8 @@ struct fimc_pix_limit { * @has_inp_rot: set if has input rotator * @has_out_rot: set if has output rotator * @has_cistatus2: 1 if CISTATUS2 register is present in this IP revision + * @has_mainscaler_ext: 1 if extended mainscaler ratios in CIEXTEN register + * are present in this IP revision * @pix_limit: pixel size constraints for the scaler * @min_inp_pixsize: minimum input pixel size * @min_out_pixsize: minimum output pixel size @@ -383,6 +365,7 @@ struct samsung_fimc_variant { unsigned int has_inp_rot:1; unsigned int has_out_rot:1; unsigned int has_cistatus2:1; + unsigned int has_mainscaler_ext:1; struct fimc_pix_limit *pix_limit; u16 min_inp_pixsize; u16 min_out_pixsize; @@ -412,12 +395,12 @@ struct fimc_ctx; * @lock: the mutex protecting this data structure * @pdev: pointer to the FIMC platform device * @pdata: pointer to the device platform data - * @id: FIMC device index (0..2) + * @id: FIMC device index (0..FIMC_MAX_DEVS) + * @num_clocks: the number of clocks managed by this device instance * @clock[]: the clocks required for FIMC operation * @regs: the mapped hardware registers * @regs_res: the resource claimed for IO registers * @irq: interrupt number of the FIMC subdevice - * @irqlock: spinlock protecting videobuffer queue * @irq_queue: * @m2m: memory-to-memory V4L2 device information * @vid_cap: camera capture device information @@ -427,18 +410,19 @@ struct fimc_dev { spinlock_t slock; struct mutex lock; struct platform_device *pdev; - struct s3c_platform_fimc *pdata; + struct s5p_platform_fimc *pdata; struct samsung_fimc_variant *variant; - int id; - struct clk *clock[NUM_FIMC_CLOCKS]; + u16 id; + u16 num_clocks; + struct clk *clock[MAX_FIMC_CLOCKS]; void __iomem *regs; struct resource *regs_res; int irq; - spinlock_t irqlock; wait_queue_head_t irq_queue; struct fimc_m2m_device m2m; struct fimc_vid_cap vid_cap; unsigned long state; + struct vb2_alloc_ctx *alloc_ctx; }; /** @@ -482,11 +466,41 @@ struct fimc_ctx { struct v4l2_m2m_ctx *m2m_ctx; }; -extern struct videobuf_queue_ops fimc_qops; +static inline bool fimc_capture_active(struct fimc_dev *fimc) +{ + unsigned long flags; + bool ret; + + spin_lock_irqsave(&fimc->slock, flags); + ret = !!(fimc->state & (1 << ST_CAPT_RUN) || + fimc->state & (1 << ST_CAPT_PEND)); + spin_unlock_irqrestore(&fimc->slock, flags); + return ret; +} + +static inline void fimc_ctx_state_lock_set(u32 state, struct fimc_ctx *ctx) +{ + unsigned long flags; + + spin_lock_irqsave(&ctx->slock, flags); + ctx->state |= state; + spin_unlock_irqrestore(&ctx->slock, flags); +} + +static inline bool fimc_ctx_state_is_set(u32 mask, struct fimc_ctx *ctx) +{ + unsigned long flags; + bool ret; + + spin_lock_irqsave(&ctx->slock, flags); + ret = (ctx->state & mask) == mask; + spin_unlock_irqrestore(&ctx->slock, flags); + return ret; +} static inline int tiled_fmt(struct fimc_fmt *fmt) { - return 0; + return fmt->fourcc == V4L2_PIX_FMT_NV12MT; } static inline void fimc_hw_clear_irq(struct fimc_dev *dev) @@ -542,12 +556,12 @@ static inline struct fimc_frame *ctx_get_frame(struct fimc_ctx *ctx, { struct fimc_frame *frame; - if (V4L2_BUF_TYPE_VIDEO_OUTPUT == type) { - if (ctx->state & FIMC_CTX_M2M) + if (V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == type) { + if (fimc_ctx_state_is_set(FIMC_CTX_M2M, ctx)) frame = &ctx->s_frame; else return ERR_PTR(-EINVAL); - } else if (V4L2_BUF_TYPE_VIDEO_CAPTURE == type) { + } else if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == type) { frame = &ctx->d_frame; } else { v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev, @@ -581,7 +595,8 @@ void fimc_hw_set_target_format(struct fimc_ctx *ctx); void fimc_hw_set_out_dma(struct fimc_ctx *ctx); void fimc_hw_en_lastirq(struct fimc_dev *fimc, int enable); void fimc_hw_en_irq(struct fimc_dev *fimc, int enable); -void fimc_hw_set_scaler(struct fimc_ctx *ctx); +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_in_dma(struct fimc_ctx *ctx); @@ -589,23 +604,23 @@ void fimc_hw_set_input_path(struct fimc_ctx *ctx); void fimc_hw_set_output_path(struct fimc_ctx *ctx); void fimc_hw_set_input_addr(struct fimc_dev *fimc, struct fimc_addr *paddr); void fimc_hw_set_output_addr(struct fimc_dev *fimc, struct fimc_addr *paddr, - int index); + int index); int fimc_hw_set_camera_source(struct fimc_dev *fimc, - struct s3c_fimc_isp_info *cam); + struct s5p_fimc_isp_info *cam); int fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f); int fimc_hw_set_camera_polarity(struct fimc_dev *fimc, - struct s3c_fimc_isp_info *cam); + struct s5p_fimc_isp_info *cam); int fimc_hw_set_camera_type(struct fimc_dev *fimc, - struct s3c_fimc_isp_info *cam); + struct s5p_fimc_isp_info *cam); /* -----------------------------------------------------*/ /* fimc-core.c */ -int fimc_vidioc_enum_fmt(struct file *file, void *priv, - struct v4l2_fmtdesc *f); -int fimc_vidioc_g_fmt(struct file *file, void *priv, - struct v4l2_format *f); -int fimc_vidioc_try_fmt(struct file *file, void *priv, - struct v4l2_format *f); +int fimc_vidioc_enum_fmt_mplane(struct file *file, void *priv, + struct v4l2_fmtdesc *f); +int fimc_vidioc_g_fmt_mplane(struct file *file, void *priv, + struct v4l2_format *f); +int fimc_vidioc_try_fmt_mplane(struct file *file, void *priv, + struct v4l2_format *f); int fimc_vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc); int fimc_vidioc_g_ctrl(struct file *file, void *priv, @@ -619,10 +634,10 @@ 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(struct v4l2_rect *r, struct fimc_frame *f); +int fimc_check_scaler_ratio(int sw, int sh, int dw, int dh, int rot); 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 fimc_vid_buffer *buf, +int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb, struct fimc_frame *frame, struct fimc_addr *paddr); /* -----------------------------------------------------*/ @@ -649,28 +664,27 @@ static inline void fimc_deactivate_capture(struct fimc_dev *fimc) } /* - * Add video buffer to the active buffers queue. - * The caller holds irqlock spinlock. + * Add buf to the capture active buffers queue. + * Locking: Need to be called with fimc_dev::slock held. */ static inline void active_queue_add(struct fimc_vid_cap *vid_cap, - struct fimc_vid_buffer *buf) + struct fimc_vid_buffer *buf) { - buf->vb.state = VIDEOBUF_ACTIVE; - list_add_tail(&buf->vb.queue, &vid_cap->active_buf_q); + 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 dev->slock held. + * Locking: Need to be called with fimc_dev::slock held. */ static inline struct fimc_vid_buffer * active_queue_pop(struct fimc_vid_cap *vid_cap) { struct fimc_vid_buffer *buf; buf = list_entry(vid_cap->active_buf_q.next, - struct fimc_vid_buffer, vb.queue); - list_del(&buf->vb.queue); + struct fimc_vid_buffer, list); + list_del(&buf->list); vid_cap->active_buf_cnt--; return buf; } @@ -679,8 +693,7 @@ active_queue_pop(struct fimc_vid_cap *vid_cap) static inline void fimc_pending_queue_add(struct fimc_vid_cap *vid_cap, struct fimc_vid_buffer *buf) { - buf->vb.state = VIDEOBUF_QUEUED; - list_add_tail(&buf->vb.queue, &vid_cap->pending_buf_q); + list_add_tail(&buf->list, &vid_cap->pending_buf_q); } /* Add video buffer to the capture pending buffers queue */ @@ -689,10 +702,9 @@ pending_queue_pop(struct fimc_vid_cap *vid_cap) { struct fimc_vid_buffer *buf; buf = list_entry(vid_cap->pending_buf_q.next, - struct fimc_vid_buffer, vb.queue); - list_del(&buf->vb.queue); + struct fimc_vid_buffer, list); + list_del(&buf->list); return buf; } - #endif /* FIMC_CORE_H_ */ |