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