Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 | /* SPDX-License-Identifier: GPL-2.0-only */ /* * s3c24xx/s3c64xx SoC series Camera Interface (CAMIF) driver * * Copyright (C) 2012 Sylwester Nawrocki <sylvester.nawrocki@gmail.com> * Copyright (C) 2012 Tomasz Figa <tomasz.figa@gmail.com> */ #ifndef CAMIF_CORE_H_ #define CAMIF_CORE_H_ #include <linux/io.h> #include <linux/irq.h> #include <linux/platform_device.h> #include <linux/sched.h> #include <linux/spinlock.h> #include <linux/types.h> #include <linux/videodev2.h> #include <media/media-entity.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-dev.h> #include <media/v4l2-device.h> #include <media/v4l2-mediabus.h> #include <media/videobuf2-v4l2.h> #include <media/drv-intf/s3c_camif.h> #define S3C_CAMIF_DRIVER_NAME "s3c-camif" #define CAMIF_REQ_BUFS_MIN 3 #define CAMIF_MAX_OUT_BUFS 4 #define CAMIF_MAX_PIX_WIDTH 4096 #define CAMIF_MAX_PIX_HEIGHT 4096 #define SCALER_MAX_RATIO 64 #define CAMIF_DEF_WIDTH 640 #define CAMIF_DEF_HEIGHT 480 #define CAMIF_STOP_TIMEOUT 1500 /* ms */ #define S3C244X_CAMIF_IP_REV 0x20 /* 2.0 */ #define S3C2450_CAMIF_IP_REV 0x30 /* 3.0 - not implemented, not tested */ #define S3C6400_CAMIF_IP_REV 0x31 /* 3.1 - not implemented, not tested */ #define S3C6410_CAMIF_IP_REV 0x32 /* 3.2 */ /* struct camif_vp::state */ #define ST_VP_PENDING (1 << 0) #define ST_VP_RUNNING (1 << 1) #define ST_VP_STREAMING (1 << 2) #define ST_VP_SENSOR_STREAMING (1 << 3) #define ST_VP_ABORTING (1 << 4) #define ST_VP_OFF (1 << 5) #define ST_VP_LASTIRQ (1 << 6) #define ST_VP_CONFIG (1 << 8) #define CAMIF_SD_PAD_SINK 0 #define CAMIF_SD_PAD_SOURCE_C 1 #define CAMIF_SD_PAD_SOURCE_P 2 #define CAMIF_SD_PADS_NUM 3 enum img_fmt { IMG_FMT_RGB565 = 0x0010, IMG_FMT_RGB666, IMG_FMT_XRGB8888, IMG_FMT_YCBCR420 = 0x0020, IMG_FMT_YCRCB420, IMG_FMT_YCBCR422P, IMG_FMT_YCBYCR422 = 0x0040, IMG_FMT_YCRYCB422, IMG_FMT_CBYCRY422, IMG_FMT_CRYCBY422, }; #define img_fmt_is_rgb(x) ((x) & 0x10) #define img_fmt_is_ycbcr(x) ((x) & 0x60) /* Possible values for struct camif_fmt::flags */ #define FMT_FL_S3C24XX_CODEC (1 << 0) #define FMT_FL_S3C24XX_PREVIEW (1 << 1) #define FMT_FL_S3C64XX (1 << 2) /** * struct camif_fmt - pixel format description * @fourcc: fourcc code for this format, 0 if not applicable * @color: a corresponding enum img_fmt * @colplanes: number of physically contiguous data planes * @flags: indicate for which SoCs revisions this format is valid * @depth: bits per pixel (total) * @ybpp: number of luminance bytes per pixel */ struct camif_fmt { u32 fourcc; u32 color; u16 colplanes; u16 flags; u8 depth; u8 ybpp; }; /** * struct camif_dma_offset - pixel offset information for DMA * @initial: offset (in pixels) to first pixel * @line: offset (in pixels) from end of line to start of next line */ struct camif_dma_offset { int initial; int line; }; /** * struct camif_frame - source/target frame properties * @f_width: full pixel width * @f_height: full pixel height * @rect: crop/composition rectangle * @dma_offset: DMA offset configuration */ struct camif_frame { u16 f_width; u16 f_height; struct v4l2_rect rect; struct camif_dma_offset dma_offset; }; /* CAMIF clocks enumeration */ enum { CLK_GATE, CLK_CAM, CLK_MAX_NUM, }; struct vp_pix_limits { u16 max_out_width; u16 max_sc_out_width; u16 out_width_align; u16 max_height; u8 min_out_width; u16 out_hor_offset_align; }; struct camif_pix_limits { u16 win_hor_offset_align; }; /** * struct s3c_camif_variant - CAMIF variant structure * @vp_pix_limits: pixel limits for the codec and preview paths * @pix_limits: pixel limits for the camera input interface * @ip_revision: the CAMIF IP revision: 0x20 for s3c244x, 0x32 for s3c6410 * @has_img_effect: supports image effects * @vp_offset: register offset */ struct s3c_camif_variant { struct vp_pix_limits vp_pix_limits[2]; struct camif_pix_limits pix_limits; u8 ip_revision; u8 has_img_effect; unsigned int vp_offset; }; struct s3c_camif_drvdata { const struct s3c_camif_variant *variant; unsigned long bus_clk_freq; }; struct camif_scaler { u8 scaleup_h; u8 scaleup_v; u8 copy; u8 enable; u32 h_shift; u32 v_shift; u32 pre_h_ratio; u32 pre_v_ratio; u32 pre_dst_width; u32 pre_dst_height; u32 main_h_ratio; u32 main_v_ratio; }; struct camif_dev; /** * struct camif_vp - CAMIF data processing path structure (codec/preview) * @irq_queue: interrupt handling waitqueue * @irq: interrupt number for this data path * @camif: pointer to the camif structure * @pad: media pad for the video node * @vdev: video device * @ctrl_handler: video node controls handler * @owner: file handle that own the streaming * @vb_queue: vb2 buffer queue * @pending_buf_q: pending (empty) buffers queue head * @active_buf_q: active (being written) buffers queue head * @active_buffers: counter of buffer set up at the DMA engine * @buf_index: identifier of a last empty buffer set up in H/W * @frame_sequence: image frame sequence counter * @reqbufs_count: the number of buffers requested * @scaler: the scaler structure * @out_fmt: pixel format at this video path output * @payload: the output data frame payload size * @out_frame: the output pixel resolution * @state: the video path's state * @fmt_flags: flags determining supported pixel formats * @id: CAMIF id, 0 - codec, 1 - preview * @rotation: current image rotation value * @hflip: apply horizontal flip if set * @vflip: apply vertical flip if set * @offset: register offset */ struct camif_vp { wait_queue_head_t irq_queue; int irq; struct camif_dev *camif; struct media_pad pad; struct video_device vdev; struct v4l2_ctrl_handler ctrl_handler; struct v4l2_fh *owner; struct vb2_queue vb_queue; struct list_head pending_buf_q; struct list_head active_buf_q; unsigned int active_buffers; unsigned int buf_index; unsigned int frame_sequence; unsigned int reqbufs_count; struct camif_scaler scaler; const struct camif_fmt *out_fmt; unsigned int payload; struct camif_frame out_frame; unsigned int state; u16 fmt_flags; u8 id; u16 rotation; u8 hflip; u8 vflip; unsigned int offset; }; /* Video processing path enumeration */ #define VP_CODEC 0 #define VP_PREVIEW 1 #define CAMIF_VP_NUM 2 /** * struct camif_dev - the CAMIF driver private data structure * @media_dev: top-level media device structure * @v4l2_dev: root v4l2_device * @subdev: camera interface ("catchcam") subdev * @mbus_fmt: camera input media bus format * @camif_crop: camera input interface crop rectangle * @pads: the camif subdev's media pads * @stream_count: the camera interface streaming reference counter * @sensor: image sensor data structure * @m_pipeline: video entity pipeline description * @ctrl_handler: v4l2 control handler (owned by @subdev) * @ctrl_test_pattern: V4L2_CID_TEST_PATTERN control * @ctrl_colorfx: V4L2_CID_COLORFX control * @ctrl_colorfx_cbcr: V4L2_CID_COLORFX_CBCR control * @test_pattern: test pattern * @colorfx: color effect * @colorfx_cb: Cb value for V4L2_COLORFX_SET_CBCR * @colorfx_cr: Cr value for V4L2_COLORFX_SET_CBCR * @vp: video path (DMA) description (codec/preview) * @variant: variant information for this device * @dev: pointer to the CAMIF device struct * @pdata: a copy of the driver's platform data * @clock: clocks required for the CAMIF operation * @lock: mutex protecting this data structure * @slock: spinlock protecting CAMIF registers * @io_base: start address of the mmapped CAMIF registers */ struct camif_dev { struct media_device media_dev; struct v4l2_device v4l2_dev; struct v4l2_subdev subdev; struct v4l2_mbus_framefmt mbus_fmt; struct v4l2_rect camif_crop; struct media_pad pads[CAMIF_SD_PADS_NUM]; int stream_count; struct cam_sensor { struct v4l2_subdev *sd; short power_count; short stream_count; } sensor; struct media_pipeline *m_pipeline; struct v4l2_ctrl_handler ctrl_handler; struct v4l2_ctrl *ctrl_test_pattern; struct { struct v4l2_ctrl *ctrl_colorfx; struct v4l2_ctrl *ctrl_colorfx_cbcr; }; u8 test_pattern; u8 colorfx; u8 colorfx_cb; u8 colorfx_cr; struct camif_vp vp[CAMIF_VP_NUM]; const struct s3c_camif_variant *variant; struct device *dev; struct s3c_camif_plat_data pdata; struct clk *clock[CLK_MAX_NUM]; struct mutex lock; spinlock_t slock; void __iomem *io_base; }; /** * struct camif_addr - Y/Cb/Cr DMA start address structure * @y: luminance plane dma address * @cb: Cb plane dma address * @cr: Cr plane dma address */ struct camif_addr { dma_addr_t y; dma_addr_t cb; dma_addr_t cr; }; /** * struct camif_buffer - the camif video buffer structure * @vb: vb2 buffer * @list: list head for the buffers queue * @paddr: DMA start addresses * @index: an identifier of this buffer at the DMA engine */ struct camif_buffer { struct vb2_v4l2_buffer vb; struct list_head list; struct camif_addr paddr; unsigned int index; }; const struct camif_fmt *s3c_camif_find_format(struct camif_vp *vp, const u32 *pixelformat, int index); int s3c_camif_register_video_node(struct camif_dev *camif, int idx); void s3c_camif_unregister_video_node(struct camif_dev *camif, int idx); irqreturn_t s3c_camif_irq_handler(int irq, void *priv); int s3c_camif_create_subdev(struct camif_dev *camif); void s3c_camif_unregister_subdev(struct camif_dev *camif); int s3c_camif_set_defaults(struct camif_dev *camif); int s3c_camif_get_scaler_config(struct camif_vp *vp, struct camif_scaler *scaler); static inline void camif_active_queue_add(struct camif_vp *vp, struct camif_buffer *buf) { list_add_tail(&buf->list, &vp->active_buf_q); vp->active_buffers++; } static inline struct camif_buffer *camif_active_queue_pop( struct camif_vp *vp) { struct camif_buffer *buf = list_first_entry(&vp->active_buf_q, struct camif_buffer, list); list_del(&buf->list); vp->active_buffers--; return buf; } static inline struct camif_buffer *camif_active_queue_peek( struct camif_vp *vp, int index) { struct camif_buffer *tmp, *buf; if (WARN_ON(list_empty(&vp->active_buf_q))) return NULL; list_for_each_entry_safe(buf, tmp, &vp->active_buf_q, list) { if (buf->index == index) { list_del(&buf->list); vp->active_buffers--; return buf; } } return NULL; } static inline void camif_pending_queue_add(struct camif_vp *vp, struct camif_buffer *buf) { list_add_tail(&buf->list, &vp->pending_buf_q); } static inline struct camif_buffer *camif_pending_queue_pop( struct camif_vp *vp) { struct camif_buffer *buf = list_first_entry(&vp->pending_buf_q, struct camif_buffer, list); list_del(&buf->list); return buf; } #endif /* CAMIF_CORE_H_ */ |