398 lines · c
1/* SPDX-License-Identifier: GPL-2.0-only */2/*3 * s3c24xx/s3c64xx SoC series Camera Interface (CAMIF) driver4 *5 * Copyright (C) 2012 Sylwester Nawrocki <sylvester.nawrocki@gmail.com>6 * Copyright (C) 2012 Tomasz Figa <tomasz.figa@gmail.com>7*/8 9#ifndef CAMIF_CORE_H_10#define CAMIF_CORE_H_11 12#include <linux/io.h>13#include <linux/irq.h>14#include <linux/platform_device.h>15#include <linux/sched.h>16#include <linux/spinlock.h>17#include <linux/types.h>18#include <linux/videodev2.h>19 20#include <media/media-entity.h>21#include <media/v4l2-ctrls.h>22#include <media/v4l2-dev.h>23#include <media/v4l2-device.h>24#include <media/v4l2-mediabus.h>25#include <media/videobuf2-v4l2.h>26#include <media/drv-intf/s3c_camif.h>27 28#define S3C_CAMIF_DRIVER_NAME "s3c-camif"29#define CAMIF_REQ_BUFS_MIN 330#define CAMIF_MAX_OUT_BUFS 431#define CAMIF_MAX_PIX_WIDTH 409632#define CAMIF_MAX_PIX_HEIGHT 409633#define SCALER_MAX_RATIO 6434#define CAMIF_DEF_WIDTH 64035#define CAMIF_DEF_HEIGHT 48036#define CAMIF_STOP_TIMEOUT 1500 /* ms */37 38#define S3C244X_CAMIF_IP_REV 0x20 /* 2.0 */39#define S3C2450_CAMIF_IP_REV 0x30 /* 3.0 - not implemented, not tested */40#define S3C6400_CAMIF_IP_REV 0x31 /* 3.1 - not implemented, not tested */41#define S3C6410_CAMIF_IP_REV 0x32 /* 3.2 */42 43/* struct camif_vp::state */44 45#define ST_VP_PENDING (1 << 0)46#define ST_VP_RUNNING (1 << 1)47#define ST_VP_STREAMING (1 << 2)48#define ST_VP_SENSOR_STREAMING (1 << 3)49 50#define ST_VP_ABORTING (1 << 4)51#define ST_VP_OFF (1 << 5)52#define ST_VP_LASTIRQ (1 << 6)53 54#define ST_VP_CONFIG (1 << 8)55 56#define CAMIF_SD_PAD_SINK 057#define CAMIF_SD_PAD_SOURCE_C 158#define CAMIF_SD_PAD_SOURCE_P 259#define CAMIF_SD_PADS_NUM 360 61enum img_fmt {62 IMG_FMT_RGB565 = 0x0010,63 IMG_FMT_RGB666,64 IMG_FMT_XRGB8888,65 IMG_FMT_YCBCR420 = 0x0020,66 IMG_FMT_YCRCB420,67 IMG_FMT_YCBCR422P,68 IMG_FMT_YCBYCR422 = 0x0040,69 IMG_FMT_YCRYCB422,70 IMG_FMT_CBYCRY422,71 IMG_FMT_CRYCBY422,72};73 74#define img_fmt_is_rgb(x) ((x) & 0x10)75#define img_fmt_is_ycbcr(x) ((x) & 0x60)76 77/* Possible values for struct camif_fmt::flags */78#define FMT_FL_S3C24XX_CODEC (1 << 0)79#define FMT_FL_S3C24XX_PREVIEW (1 << 1)80#define FMT_FL_S3C64XX (1 << 2)81 82/**83 * struct camif_fmt - pixel format description84 * @fourcc: fourcc code for this format, 0 if not applicable85 * @color: a corresponding enum img_fmt86 * @colplanes: number of physically contiguous data planes87 * @flags: indicate for which SoCs revisions this format is valid88 * @depth: bits per pixel (total)89 * @ybpp: number of luminance bytes per pixel90 */91struct camif_fmt {92 u32 fourcc;93 u32 color;94 u16 colplanes;95 u16 flags;96 u8 depth;97 u8 ybpp;98};99 100/**101 * struct camif_dma_offset - pixel offset information for DMA102 * @initial: offset (in pixels) to first pixel103 * @line: offset (in pixels) from end of line to start of next line104 */105struct camif_dma_offset {106 int initial;107 int line;108};109 110/**111 * struct camif_frame - source/target frame properties112 * @f_width: full pixel width113 * @f_height: full pixel height114 * @rect: crop/composition rectangle115 * @dma_offset: DMA offset configuration116 */117struct camif_frame {118 u16 f_width;119 u16 f_height;120 struct v4l2_rect rect;121 struct camif_dma_offset dma_offset;122};123 124/* CAMIF clocks enumeration */125enum {126 CLK_GATE,127 CLK_CAM,128 CLK_MAX_NUM,129};130 131struct vp_pix_limits {132 u16 max_out_width;133 u16 max_sc_out_width;134 u16 out_width_align;135 u16 max_height;136 u8 min_out_width;137 u16 out_hor_offset_align;138};139 140struct camif_pix_limits {141 u16 win_hor_offset_align;142};143 144/**145 * struct s3c_camif_variant - CAMIF variant structure146 * @vp_pix_limits: pixel limits for the codec and preview paths147 * @pix_limits: pixel limits for the camera input interface148 * @ip_revision: the CAMIF IP revision: 0x20 for s3c244x, 0x32 for s3c6410149 * @has_img_effect: supports image effects150 * @vp_offset: register offset151 */152struct s3c_camif_variant {153 struct vp_pix_limits vp_pix_limits[2];154 struct camif_pix_limits pix_limits;155 u8 ip_revision;156 u8 has_img_effect;157 unsigned int vp_offset;158};159 160struct s3c_camif_drvdata {161 const struct s3c_camif_variant *variant;162 unsigned long bus_clk_freq;163};164 165struct camif_scaler {166 u8 scaleup_h;167 u8 scaleup_v;168 u8 copy;169 u8 enable;170 u32 h_shift;171 u32 v_shift;172 u32 pre_h_ratio;173 u32 pre_v_ratio;174 u32 pre_dst_width;175 u32 pre_dst_height;176 u32 main_h_ratio;177 u32 main_v_ratio;178};179 180struct camif_dev;181 182/**183 * struct camif_vp - CAMIF data processing path structure (codec/preview)184 * @irq_queue: interrupt handling waitqueue185 * @irq: interrupt number for this data path186 * @camif: pointer to the camif structure187 * @pad: media pad for the video node188 * @vdev: video device189 * @ctrl_handler: video node controls handler190 * @owner: file handle that own the streaming191 * @vb_queue: vb2 buffer queue192 * @pending_buf_q: pending (empty) buffers queue head193 * @active_buf_q: active (being written) buffers queue head194 * @active_buffers: counter of buffer set up at the DMA engine195 * @buf_index: identifier of a last empty buffer set up in H/W196 * @frame_sequence: image frame sequence counter197 * @reqbufs_count: the number of buffers requested198 * @scaler: the scaler structure199 * @out_fmt: pixel format at this video path output200 * @payload: the output data frame payload size201 * @out_frame: the output pixel resolution202 * @state: the video path's state203 * @fmt_flags: flags determining supported pixel formats204 * @id: CAMIF id, 0 - codec, 1 - preview205 * @rotation: current image rotation value206 * @hflip: apply horizontal flip if set207 * @vflip: apply vertical flip if set208 * @offset: register offset209 */210struct camif_vp {211 wait_queue_head_t irq_queue;212 int irq;213 struct camif_dev *camif;214 struct media_pad pad;215 struct video_device vdev;216 struct v4l2_ctrl_handler ctrl_handler;217 struct v4l2_fh *owner;218 struct vb2_queue vb_queue;219 struct list_head pending_buf_q;220 struct list_head active_buf_q;221 unsigned int active_buffers;222 unsigned int buf_index;223 unsigned int frame_sequence;224 unsigned int reqbufs_count;225 struct camif_scaler scaler;226 const struct camif_fmt *out_fmt;227 unsigned int payload;228 struct camif_frame out_frame;229 unsigned int state;230 u16 fmt_flags;231 u8 id;232 u16 rotation;233 u8 hflip;234 u8 vflip;235 unsigned int offset;236};237 238/* Video processing path enumeration */239#define VP_CODEC 0240#define VP_PREVIEW 1241#define CAMIF_VP_NUM 2242 243/**244 * struct camif_dev - the CAMIF driver private data structure245 * @media_dev: top-level media device structure246 * @v4l2_dev: root v4l2_device247 * @subdev: camera interface ("catchcam") subdev248 * @mbus_fmt: camera input media bus format249 * @camif_crop: camera input interface crop rectangle250 * @pads: the camif subdev's media pads251 * @stream_count: the camera interface streaming reference counter252 * @sensor: image sensor data structure253 * @m_pipeline: video entity pipeline description254 * @ctrl_handler: v4l2 control handler (owned by @subdev)255 * @ctrl_test_pattern: V4L2_CID_TEST_PATTERN control256 * @ctrl_colorfx: V4L2_CID_COLORFX control257 * @ctrl_colorfx_cbcr: V4L2_CID_COLORFX_CBCR control258 * @test_pattern: test pattern259 * @colorfx: color effect260 * @colorfx_cb: Cb value for V4L2_COLORFX_SET_CBCR261 * @colorfx_cr: Cr value for V4L2_COLORFX_SET_CBCR262 * @vp: video path (DMA) description (codec/preview)263 * @variant: variant information for this device264 * @dev: pointer to the CAMIF device struct265 * @pdata: a copy of the driver's platform data266 * @clock: clocks required for the CAMIF operation267 * @lock: mutex protecting this data structure268 * @slock: spinlock protecting CAMIF registers269 * @io_base: start address of the mmapped CAMIF registers270 */271struct camif_dev {272 struct media_device media_dev;273 struct v4l2_device v4l2_dev;274 struct v4l2_subdev subdev;275 struct v4l2_mbus_framefmt mbus_fmt;276 struct v4l2_rect camif_crop;277 struct media_pad pads[CAMIF_SD_PADS_NUM];278 int stream_count;279 280 struct cam_sensor {281 struct v4l2_subdev *sd;282 short power_count;283 short stream_count;284 } sensor;285 struct media_pipeline *m_pipeline;286 287 struct v4l2_ctrl_handler ctrl_handler;288 struct v4l2_ctrl *ctrl_test_pattern;289 struct {290 struct v4l2_ctrl *ctrl_colorfx;291 struct v4l2_ctrl *ctrl_colorfx_cbcr;292 };293 u8 test_pattern;294 u8 colorfx;295 u8 colorfx_cb;296 u8 colorfx_cr;297 298 struct camif_vp vp[CAMIF_VP_NUM];299 300 const struct s3c_camif_variant *variant;301 struct device *dev;302 struct s3c_camif_plat_data pdata;303 struct clk *clock[CLK_MAX_NUM];304 struct mutex lock;305 spinlock_t slock;306 void __iomem *io_base;307};308 309/**310 * struct camif_addr - Y/Cb/Cr DMA start address structure311 * @y: luminance plane dma address312 * @cb: Cb plane dma address313 * @cr: Cr plane dma address314 */315struct camif_addr {316 dma_addr_t y;317 dma_addr_t cb;318 dma_addr_t cr;319};320 321/**322 * struct camif_buffer - the camif video buffer structure323 * @vb: vb2 buffer324 * @list: list head for the buffers queue325 * @paddr: DMA start addresses326 * @index: an identifier of this buffer at the DMA engine327 */328struct camif_buffer {329 struct vb2_v4l2_buffer vb;330 struct list_head list;331 struct camif_addr paddr;332 unsigned int index;333};334 335const struct camif_fmt *s3c_camif_find_format(struct camif_vp *vp,336 const u32 *pixelformat, int index);337int s3c_camif_register_video_node(struct camif_dev *camif, int idx);338void s3c_camif_unregister_video_node(struct camif_dev *camif, int idx);339irqreturn_t s3c_camif_irq_handler(int irq, void *priv);340int s3c_camif_create_subdev(struct camif_dev *camif);341void s3c_camif_unregister_subdev(struct camif_dev *camif);342int s3c_camif_set_defaults(struct camif_dev *camif);343int s3c_camif_get_scaler_config(struct camif_vp *vp,344 struct camif_scaler *scaler);345 346static inline void camif_active_queue_add(struct camif_vp *vp,347 struct camif_buffer *buf)348{349 list_add_tail(&buf->list, &vp->active_buf_q);350 vp->active_buffers++;351}352 353static inline struct camif_buffer *camif_active_queue_pop(354 struct camif_vp *vp)355{356 struct camif_buffer *buf = list_first_entry(&vp->active_buf_q,357 struct camif_buffer, list);358 list_del(&buf->list);359 vp->active_buffers--;360 return buf;361}362 363static inline struct camif_buffer *camif_active_queue_peek(364 struct camif_vp *vp, int index)365{366 struct camif_buffer *tmp, *buf;367 368 if (WARN_ON(list_empty(&vp->active_buf_q)))369 return NULL;370 371 list_for_each_entry_safe(buf, tmp, &vp->active_buf_q, list) {372 if (buf->index == index) {373 list_del(&buf->list);374 vp->active_buffers--;375 return buf;376 }377 }378 379 return NULL;380}381 382static inline void camif_pending_queue_add(struct camif_vp *vp,383 struct camif_buffer *buf)384{385 list_add_tail(&buf->list, &vp->pending_buf_q);386}387 388static inline struct camif_buffer *camif_pending_queue_pop(389 struct camif_vp *vp)390{391 struct camif_buffer *buf = list_first_entry(&vp->pending_buf_q,392 struct camif_buffer, list);393 list_del(&buf->list);394 return buf;395}396 397#endif /* CAMIF_CORE_H_ */398