aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/exynos4-is
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/exynos4-is')
-rw-r--r--drivers/media/platform/exynos4-is/Kconfig61
-rw-r--r--drivers/media/platform/exynos4-is/Makefile10
-rw-r--r--drivers/media/platform/exynos4-is/fimc-capture.c1893
-rw-r--r--drivers/media/platform/exynos4-is/fimc-core.c1311
-rw-r--r--drivers/media/platform/exynos4-is/fimc-core.h731
-rw-r--r--drivers/media/platform/exynos4-is/fimc-is-command.h137
-rw-r--r--drivers/media/platform/exynos4-is/fimc-is-errno.c272
-rw-r--r--drivers/media/platform/exynos4-is/fimc-is-errno.h248
-rw-r--r--drivers/media/platform/exynos4-is/fimc-is-i2c.c126
-rw-r--r--drivers/media/platform/exynos4-is/fimc-is-i2c.h15
-rw-r--r--drivers/media/platform/exynos4-is/fimc-is-param.c900
-rw-r--r--drivers/media/platform/exynos4-is/fimc-is-param.h1020
-rw-r--r--drivers/media/platform/exynos4-is/fimc-is-regs.c243
-rw-r--r--drivers/media/platform/exynos4-is/fimc-is-regs.h164
-rw-r--r--drivers/media/platform/exynos4-is/fimc-is-sensor.c305
-rw-r--r--drivers/media/platform/exynos4-is/fimc-is-sensor.h89
-rw-r--r--drivers/media/platform/exynos4-is/fimc-is.c1007
-rw-r--r--drivers/media/platform/exynos4-is/fimc-is.h345
-rw-r--r--drivers/media/platform/exynos4-is/fimc-isp.c703
-rw-r--r--drivers/media/platform/exynos4-is/fimc-isp.h181
-rw-r--r--drivers/media/platform/exynos4-is/fimc-lite-reg.c302
-rw-r--r--drivers/media/platform/exynos4-is/fimc-lite-reg.h150
-rw-r--r--drivers/media/platform/exynos4-is/fimc-lite.c1660
-rw-r--r--drivers/media/platform/exynos4-is/fimc-lite.h214
-rw-r--r--drivers/media/platform/exynos4-is/fimc-m2m.c865
-rw-r--r--drivers/media/platform/exynos4-is/fimc-reg.c841
-rw-r--r--drivers/media/platform/exynos4-is/fimc-reg.h338
-rw-r--r--drivers/media/platform/exynos4-is/media-dev.c1511
-rw-r--r--drivers/media/platform/exynos4-is/media-dev.h152
-rw-r--r--drivers/media/platform/exynos4-is/mipi-csis.c1019
-rw-r--r--drivers/media/platform/exynos4-is/mipi-csis.h26
31 files changed, 16839 insertions, 0 deletions
diff --git a/drivers/media/platform/exynos4-is/Kconfig b/drivers/media/platform/exynos4-is/Kconfig
new file mode 100644
index 000000000000..6ff99b5849f9
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/Kconfig
@@ -0,0 +1,61 @@
1
2config VIDEO_SAMSUNG_EXYNOS4_IS
3 bool "Samsung S5P/EXYNOS4 SoC series Camera Subsystem driver"
4 depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && PLAT_S5P && PM_RUNTIME
5 help
6 Say Y here to enable camera host interface devices for
7 Samsung S5P and EXYNOS SoC series.
8
9if VIDEO_SAMSUNG_EXYNOS4_IS
10
11config VIDEO_S5P_FIMC
12 tristate "S5P/EXYNOS4 FIMC/CAMIF camera interface driver"
13 depends on I2C
14 select VIDEOBUF2_DMA_CONTIG
15 select V4L2_MEM2MEM_DEV
16 select MFD_SYSCON if OF
17 help
18 This is a V4L2 driver for Samsung S5P and EXYNOS4 SoC camera host
19 interface and video postprocessor (FIMC) devices.
20
21 To compile this driver as a module, choose M here: the
22 module will be called s5p-fimc.
23
24config VIDEO_S5P_MIPI_CSIS
25 tristate "S5P/EXYNOS MIPI-CSI2 receiver (MIPI-CSIS) driver"
26 depends on REGULATOR
27 select S5P_SETUP_MIPIPHY
28 help
29 This is a V4L2 driver for Samsung S5P and EXYNOS4 SoC MIPI-CSI2
30 receiver (MIPI-CSIS) devices.
31
32 To compile this driver as a module, choose M here: the
33 module will be called s5p-csis.
34
35if SOC_EXYNOS4212 || SOC_EXYNOS4412 || SOC_EXYNOS5250
36
37config VIDEO_EXYNOS_FIMC_LITE
38 tristate "EXYNOS FIMC-LITE camera interface driver"
39 depends on I2C
40 select VIDEOBUF2_DMA_CONTIG
41 help
42 This is a V4L2 driver for Samsung EXYNOS4/5 SoC FIMC-LITE camera
43 host interface.
44
45 To compile this driver as a module, choose M here: the
46 module will be called exynos-fimc-lite.
47endif
48
49config VIDEO_EXYNOS4_FIMC_IS
50 tristate "EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver"
51 select VIDEOBUF2_DMA_CONTIG
52 depends on OF
53 select FW_LOADER
54 help
55 This is a V4L2 driver for Samsung EXYNOS4x12 SoC series
56 FIMC-IS (Imaging Subsystem).
57
58 To compile this driver as a module, choose M here: the
59 module will be called exynos4-fimc-is.
60
61endif # VIDEO_SAMSUNG_S5P_FIMC
diff --git a/drivers/media/platform/exynos4-is/Makefile b/drivers/media/platform/exynos4-is/Makefile
new file mode 100644
index 000000000000..f25f46377399
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/Makefile
@@ -0,0 +1,10 @@
1s5p-fimc-objs := fimc-core.o fimc-reg.o fimc-m2m.o fimc-capture.o media-dev.o
2exynos-fimc-lite-objs += fimc-lite-reg.o fimc-lite.o
3exynos-fimc-is-objs := fimc-is.o fimc-isp.o fimc-is-sensor.o fimc-is-regs.o
4exynos-fimc-is-objs += fimc-is-param.o fimc-is-errno.o fimc-is-i2c.o
5s5p-csis-objs := mipi-csis.o
6
7obj-$(CONFIG_VIDEO_S5P_MIPI_CSIS) += s5p-csis.o
8obj-$(CONFIG_VIDEO_EXYNOS_FIMC_LITE) += exynos-fimc-lite.o
9obj-$(CONFIG_VIDEO_EXYNOS4_FIMC_IS) += exynos-fimc-is.o
10obj-$(CONFIG_VIDEO_S5P_FIMC) += s5p-fimc.o
diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c
new file mode 100644
index 000000000000..528f41369364
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-capture.c
@@ -0,0 +1,1893 @@
1/*
2 * Samsung S5P/EXYNOS4 SoC series camera interface (camera capture) driver
3 *
4 * Copyright (C) 2010 - 2012 Samsung Electronics Co., Ltd.
5 * Sylwester Nawrocki <s.nawrocki@samsung.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#include <linux/module.h>
13#include <linux/kernel.h>
14#include <linux/types.h>
15#include <linux/errno.h>
16#include <linux/bug.h>
17#include <linux/interrupt.h>
18#include <linux/device.h>
19#include <linux/pm_runtime.h>
20#include <linux/list.h>
21#include <linux/slab.h>
22
23#include <linux/videodev2.h>
24#include <media/v4l2-device.h>
25#include <media/v4l2-ioctl.h>
26#include <media/v4l2-mem2mem.h>
27#include <media/videobuf2-core.h>
28#include <media/videobuf2-dma-contig.h>
29
30#include "media-dev.h"
31#include "fimc-core.h"
32#include "fimc-reg.h"
33
34static int fimc_capture_hw_init(struct fimc_dev *fimc)
35{
36 struct fimc_source_info *si = &fimc->vid_cap.source_config;
37 struct fimc_ctx *ctx = fimc->vid_cap.ctx;
38 int ret;
39 unsigned long flags;
40
41 if (ctx == NULL || ctx->s_frame.fmt == NULL)
42 return -EINVAL;
43
44 if (si->fimc_bus_type == FIMC_BUS_TYPE_ISP_WRITEBACK) {
45 ret = fimc_hw_camblk_cfg_writeback(fimc);
46 if (ret < 0)
47 return ret;
48 }
49
50 spin_lock_irqsave(&fimc->slock, flags);
51 fimc_prepare_dma_offset(ctx, &ctx->d_frame);
52 fimc_set_yuv_order(ctx);
53
54 fimc_hw_set_camera_polarity(fimc, si);
55 fimc_hw_set_camera_type(fimc, si);
56 fimc_hw_set_camera_source(fimc, si);
57 fimc_hw_set_camera_offset(fimc, &ctx->s_frame);
58
59 ret = fimc_set_scaler_info(ctx);
60 if (!ret) {
61 fimc_hw_set_input_path(ctx);
62 fimc_hw_set_prescaler(ctx);
63 fimc_hw_set_mainscaler(ctx);
64 fimc_hw_set_target_format(ctx);
65 fimc_hw_set_rotation(ctx);
66 fimc_hw_set_effect(ctx);
67 fimc_hw_set_output_path(ctx);
68 fimc_hw_set_out_dma(ctx);
69 if (fimc->drv_data->alpha_color)
70 fimc_hw_set_rgb_alpha(ctx);
71 clear_bit(ST_CAPT_APPLY_CFG, &fimc->state);
72 }
73 spin_unlock_irqrestore(&fimc->slock, flags);
74 return ret;
75}
76
77/*
78 * Reinitialize the driver so it is ready to start the streaming again.
79 * Set fimc->state to indicate stream off and the hardware shut down state.
80 * If not suspending (@suspend is false), return any buffers to videobuf2.
81 * Otherwise put any owned buffers onto the pending buffers queue, so they
82 * can be re-spun when the device is being resumed. Also perform FIMC
83 * software reset and disable streaming on the whole pipeline if required.
84 */
85static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend)
86{
87 struct fimc_vid_cap *cap = &fimc->vid_cap;
88 struct fimc_vid_buffer *buf;
89 unsigned long flags;
90 bool streaming;
91
92 spin_lock_irqsave(&fimc->slock, flags);
93 streaming = fimc->state & (1 << ST_CAPT_ISP_STREAM);
94
95 fimc->state &= ~(1 << ST_CAPT_RUN | 1 << ST_CAPT_SHUT |
96 1 << ST_CAPT_STREAM | 1 << ST_CAPT_ISP_STREAM);
97 if (suspend)
98 fimc->state |= (1 << ST_CAPT_SUSPENDED);
99 else
100 fimc->state &= ~(1 << ST_CAPT_PEND | 1 << ST_CAPT_SUSPENDED);
101
102 /* Release unused buffers */
103 while (!suspend && !list_empty(&cap->pending_buf_q)) {
104 buf = fimc_pending_queue_pop(cap);
105 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
106 }
107 /* If suspending put unused buffers onto pending queue */
108 while (!list_empty(&cap->active_buf_q)) {
109 buf = fimc_active_queue_pop(cap);
110 if (suspend)
111 fimc_pending_queue_add(cap, buf);
112 else
113 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
114 }
115
116 fimc_hw_reset(fimc);
117 cap->buf_index = 0;
118
119 spin_unlock_irqrestore(&fimc->slock, flags);
120
121 if (streaming)
122 return fimc_pipeline_call(fimc, set_stream,
123 &fimc->pipeline, 0);
124 else
125 return 0;
126}
127
128static int fimc_stop_capture(struct fimc_dev *fimc, bool suspend)
129{
130 unsigned long flags;
131
132 if (!fimc_capture_active(fimc))
133 return 0;
134
135 spin_lock_irqsave(&fimc->slock, flags);
136 set_bit(ST_CAPT_SHUT, &fimc->state);
137 fimc_deactivate_capture(fimc);
138 spin_unlock_irqrestore(&fimc->slock, flags);
139
140 wait_event_timeout(fimc->irq_queue,
141 !test_bit(ST_CAPT_SHUT, &fimc->state),
142 (2*HZ/10)); /* 200 ms */
143
144 return fimc_capture_state_cleanup(fimc, suspend);
145}
146
147/**
148 * fimc_capture_config_update - apply the camera interface configuration
149 *
150 * To be called from within the interrupt handler with fimc.slock
151 * spinlock held. It updates the camera pixel crop, rotation and
152 * image flip in H/W.
153 */
154static int fimc_capture_config_update(struct fimc_ctx *ctx)
155{
156 struct fimc_dev *fimc = ctx->fimc_dev;
157 int ret;
158
159 fimc_hw_set_camera_offset(fimc, &ctx->s_frame);
160
161 ret = fimc_set_scaler_info(ctx);
162 if (ret)
163 return ret;
164
165 fimc_hw_set_prescaler(ctx);
166 fimc_hw_set_mainscaler(ctx);
167 fimc_hw_set_target_format(ctx);
168 fimc_hw_set_rotation(ctx);
169 fimc_hw_set_effect(ctx);
170 fimc_prepare_dma_offset(ctx, &ctx->d_frame);
171 fimc_hw_set_out_dma(ctx);
172 if (fimc->drv_data->alpha_color)
173 fimc_hw_set_rgb_alpha(ctx);
174
175 clear_bit(ST_CAPT_APPLY_CFG, &fimc->state);
176 return ret;
177}
178
179void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf)
180{
181 struct v4l2_subdev *csis = fimc->pipeline.subdevs[IDX_CSIS];
182 struct fimc_vid_cap *cap = &fimc->vid_cap;
183 struct fimc_frame *f = &cap->ctx->d_frame;
184 struct fimc_vid_buffer *v_buf;
185 struct timeval *tv;
186 struct timespec ts;
187
188 if (test_and_clear_bit(ST_CAPT_SHUT, &fimc->state)) {
189 wake_up(&fimc->irq_queue);
190 goto done;
191 }
192
193 if (!list_empty(&cap->active_buf_q) &&
194 test_bit(ST_CAPT_RUN, &fimc->state) && deq_buf) {
195 ktime_get_real_ts(&ts);
196
197 v_buf = fimc_active_queue_pop(cap);
198
199 tv = &v_buf->vb.v4l2_buf.timestamp;
200 tv->tv_sec = ts.tv_sec;
201 tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
202 v_buf->vb.v4l2_buf.sequence = cap->frame_count++;
203
204 vb2_buffer_done(&v_buf->vb, VB2_BUF_STATE_DONE);
205 }
206
207 if (!list_empty(&cap->pending_buf_q)) {
208
209 v_buf = fimc_pending_queue_pop(cap);
210 fimc_hw_set_output_addr(fimc, &v_buf->paddr, cap->buf_index);
211 v_buf->index = cap->buf_index;
212
213 /* Move the buffer to the capture active queue */
214 fimc_active_queue_add(cap, v_buf);
215
216 dbg("next frame: %d, done frame: %d",
217 fimc_hw_get_frame_index(fimc), v_buf->index);
218
219 if (++cap->buf_index >= FIMC_MAX_OUT_BUFS)
220 cap->buf_index = 0;
221 }
222 /*
223 * Set up a buffer at MIPI-CSIS if current image format
224 * requires the frame embedded data capture.
225 */
226 if (f->fmt->mdataplanes && !list_empty(&cap->active_buf_q)) {
227 unsigned int plane = ffs(f->fmt->mdataplanes) - 1;
228 unsigned int size = f->payload[plane];
229 s32 index = fimc_hw_get_frame_index(fimc);
230 void *vaddr;
231
232 list_for_each_entry(v_buf, &cap->active_buf_q, list) {
233 if (v_buf->index != index)
234 continue;
235 vaddr = vb2_plane_vaddr(&v_buf->vb, plane);
236 v4l2_subdev_call(csis, video, s_rx_buffer,
237 vaddr, &size);
238 break;
239 }
240 }
241
242 if (cap->active_buf_cnt == 0) {
243 if (deq_buf)
244 clear_bit(ST_CAPT_RUN, &fimc->state);
245
246 if (++cap->buf_index >= FIMC_MAX_OUT_BUFS)
247 cap->buf_index = 0;
248 } else {
249 set_bit(ST_CAPT_RUN, &fimc->state);
250 }
251
252 if (test_bit(ST_CAPT_APPLY_CFG, &fimc->state))
253 fimc_capture_config_update(cap->ctx);
254done:
255 if (cap->active_buf_cnt == 1) {
256 fimc_deactivate_capture(fimc);
257 clear_bit(ST_CAPT_STREAM, &fimc->state);
258 }
259
260 dbg("frame: %d, active_buf_cnt: %d",
261 fimc_hw_get_frame_index(fimc), cap->active_buf_cnt);
262}
263
264
265static int start_streaming(struct vb2_queue *q, unsigned int count)
266{
267 struct fimc_ctx *ctx = q->drv_priv;
268 struct fimc_dev *fimc = ctx->fimc_dev;
269 struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
270 int min_bufs;
271 int ret;
272
273 vid_cap->frame_count = 0;
274
275 ret = fimc_capture_hw_init(fimc);
276 if (ret) {
277 fimc_capture_state_cleanup(fimc, false);
278 return ret;
279 }
280
281 set_bit(ST_CAPT_PEND, &fimc->state);
282
283 min_bufs = fimc->vid_cap.reqbufs_count > 1 ? 2 : 1;
284
285 if (vid_cap->active_buf_cnt >= min_bufs &&
286 !test_and_set_bit(ST_CAPT_STREAM, &fimc->state)) {
287 fimc_activate_capture(ctx);
288
289 if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state))
290 return fimc_pipeline_call(fimc, set_stream,
291 &fimc->pipeline, 1);
292 }
293
294 return 0;
295}
296
297static int stop_streaming(struct vb2_queue *q)
298{
299 struct fimc_ctx *ctx = q->drv_priv;
300 struct fimc_dev *fimc = ctx->fimc_dev;
301
302 if (!fimc_capture_active(fimc))
303 return -EINVAL;
304
305 return fimc_stop_capture(fimc, false);
306}
307
308int fimc_capture_suspend(struct fimc_dev *fimc)
309{
310 bool suspend = fimc_capture_busy(fimc);
311
312 int ret = fimc_stop_capture(fimc, suspend);
313 if (ret)
314 return ret;
315 return fimc_pipeline_call(fimc, close, &fimc->pipeline);
316}
317
318static void buffer_queue(struct vb2_buffer *vb);
319
320int fimc_capture_resume(struct fimc_dev *fimc)
321{
322 struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
323 struct fimc_vid_buffer *buf;
324 int i;
325
326 if (!test_and_clear_bit(ST_CAPT_SUSPENDED, &fimc->state))
327 return 0;
328
329 INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q);
330 vid_cap->buf_index = 0;
331 fimc_pipeline_call(fimc, open, &fimc->pipeline,
332 &vid_cap->vfd.entity, false);
333 fimc_capture_hw_init(fimc);
334
335 clear_bit(ST_CAPT_SUSPENDED, &fimc->state);
336
337 for (i = 0; i < vid_cap->reqbufs_count; i++) {
338 if (list_empty(&vid_cap->pending_buf_q))
339 break;
340 buf = fimc_pending_queue_pop(vid_cap);
341 buffer_queue(&buf->vb);
342 }
343 return 0;
344
345}
346
347static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
348 unsigned int *num_buffers, unsigned int *num_planes,
349 unsigned int sizes[], void *allocators[])
350{
351 const struct v4l2_pix_format_mplane *pixm = NULL;
352 struct fimc_ctx *ctx = vq->drv_priv;
353 struct fimc_frame *frame = &ctx->d_frame;
354 struct fimc_fmt *fmt = frame->fmt;
355 unsigned long wh;
356 int i;
357
358 if (pfmt) {
359 pixm = &pfmt->fmt.pix_mp;
360 fmt = fimc_find_format(&pixm->pixelformat, NULL,
361 FMT_FLAGS_CAM | FMT_FLAGS_M2M, -1);
362 wh = pixm->width * pixm->height;
363 } else {
364 wh = frame->f_width * frame->f_height;
365 }
366
367 if (fmt == NULL)
368 return -EINVAL;
369
370 *num_planes = fmt->memplanes;
371
372 for (i = 0; i < fmt->memplanes; i++) {
373 unsigned int size = (wh * fmt->depth[i]) / 8;
374 if (pixm)
375 sizes[i] = max(size, pixm->plane_fmt[i].sizeimage);
376 else if (fimc_fmt_is_user_defined(fmt->color))
377 sizes[i] = frame->payload[i];
378 else
379 sizes[i] = max_t(u32, size, frame->payload[i]);
380
381 allocators[i] = ctx->fimc_dev->alloc_ctx;
382 }
383
384 return 0;
385}
386
387static int buffer_prepare(struct vb2_buffer *vb)
388{
389 struct vb2_queue *vq = vb->vb2_queue;
390 struct fimc_ctx *ctx = vq->drv_priv;
391 int i;
392
393 if (ctx->d_frame.fmt == NULL)
394 return -EINVAL;
395
396 for (i = 0; i < ctx->d_frame.fmt->memplanes; i++) {
397 unsigned long size = ctx->d_frame.payload[i];
398
399 if (vb2_plane_size(vb, i) < size) {
400 v4l2_err(&ctx->fimc_dev->vid_cap.vfd,
401 "User buffer too small (%ld < %ld)\n",
402 vb2_plane_size(vb, i), size);
403 return -EINVAL;
404 }
405 vb2_set_plane_payload(vb, i, size);
406 }
407
408 return 0;
409}
410
411static void buffer_queue(struct vb2_buffer *vb)
412{
413 struct fimc_vid_buffer *buf
414 = container_of(vb, struct fimc_vid_buffer, vb);
415 struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
416 struct fimc_dev *fimc = ctx->fimc_dev;
417 struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
418 unsigned long flags;
419 int min_bufs;
420
421 spin_lock_irqsave(&fimc->slock, flags);
422 fimc_prepare_addr(ctx, &buf->vb, &ctx->d_frame, &buf->paddr);
423
424 if (!test_bit(ST_CAPT_SUSPENDED, &fimc->state) &&
425 !test_bit(ST_CAPT_STREAM, &fimc->state) &&
426 vid_cap->active_buf_cnt < FIMC_MAX_OUT_BUFS) {
427 /* Setup the buffer directly for processing. */
428 int buf_id = (vid_cap->reqbufs_count == 1) ? -1 :
429 vid_cap->buf_index;
430
431 fimc_hw_set_output_addr(fimc, &buf->paddr, buf_id);
432 buf->index = vid_cap->buf_index;
433 fimc_active_queue_add(vid_cap, buf);
434
435 if (++vid_cap->buf_index >= FIMC_MAX_OUT_BUFS)
436 vid_cap->buf_index = 0;
437 } else {
438 fimc_pending_queue_add(vid_cap, buf);
439 }
440
441 min_bufs = vid_cap->reqbufs_count > 1 ? 2 : 1;
442
443
444 if (vb2_is_streaming(&vid_cap->vbq) &&
445 vid_cap->active_buf_cnt >= min_bufs &&
446 !test_and_set_bit(ST_CAPT_STREAM, &fimc->state)) {
447 int ret;
448
449 fimc_activate_capture(ctx);
450 spin_unlock_irqrestore(&fimc->slock, flags);
451
452 if (test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state))
453 return;
454
455 ret = fimc_pipeline_call(fimc, set_stream, &fimc->pipeline, 1);
456 if (ret < 0)
457 v4l2_err(&vid_cap->vfd, "stream on failed: %d\n", ret);
458 return;
459 }
460 spin_unlock_irqrestore(&fimc->slock, flags);
461}
462
463static struct vb2_ops fimc_capture_qops = {
464 .queue_setup = queue_setup,
465 .buf_prepare = buffer_prepare,
466 .buf_queue = buffer_queue,
467 .wait_prepare = vb2_ops_wait_prepare,
468 .wait_finish = vb2_ops_wait_finish,
469 .start_streaming = start_streaming,
470 .stop_streaming = stop_streaming,
471};
472
473/**
474 * fimc_capture_ctrls_create - initialize the control handler
475 * Initialize the capture video node control handler and fill it
476 * with the FIMC controls. Inherit any sensor's controls if the
477 * 'user_subdev_api' flag is false (default behaviour).
478 * This function need to be called with the graph mutex held.
479 */
480int fimc_capture_ctrls_create(struct fimc_dev *fimc)
481{
482 struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
483 struct v4l2_subdev *sensor = fimc->pipeline.subdevs[IDX_SENSOR];
484 int ret;
485
486 if (WARN_ON(vid_cap->ctx == NULL))
487 return -ENXIO;
488 if (vid_cap->ctx->ctrls.ready)
489 return 0;
490
491 ret = fimc_ctrls_create(vid_cap->ctx);
492
493 if (ret || vid_cap->user_subdev_api || !sensor ||
494 !vid_cap->ctx->ctrls.ready)
495 return ret;
496
497 return v4l2_ctrl_add_handler(&vid_cap->ctx->ctrls.handler,
498 sensor->ctrl_handler, NULL);
499}
500
501static int fimc_capture_set_default_format(struct fimc_dev *fimc);
502
503static int fimc_capture_open(struct file *file)
504{
505 struct fimc_dev *fimc = video_drvdata(file);
506 int ret = -EBUSY;
507
508 dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state);
509
510 fimc_md_graph_lock(fimc);
511 mutex_lock(&fimc->lock);
512
513 if (fimc_m2m_active(fimc))
514 goto unlock;
515
516 set_bit(ST_CAPT_BUSY, &fimc->state);
517 ret = pm_runtime_get_sync(&fimc->pdev->dev);
518 if (ret < 0)
519 goto unlock;
520
521 ret = v4l2_fh_open(file);
522 if (ret) {
523 pm_runtime_put(&fimc->pdev->dev);
524 goto unlock;
525 }
526
527 if (v4l2_fh_is_singular_file(file)) {
528 ret = fimc_pipeline_call(fimc, open, &fimc->pipeline,
529 &fimc->vid_cap.vfd.entity, true);
530
531 if (!ret && !fimc->vid_cap.user_subdev_api)
532 ret = fimc_capture_set_default_format(fimc);
533
534 if (!ret)
535 ret = fimc_capture_ctrls_create(fimc);
536
537 if (ret < 0) {
538 clear_bit(ST_CAPT_BUSY, &fimc->state);
539 pm_runtime_put_sync(&fimc->pdev->dev);
540 v4l2_fh_release(file);
541 } else {
542 fimc->vid_cap.refcnt++;
543 }
544 }
545unlock:
546 mutex_unlock(&fimc->lock);
547 fimc_md_graph_unlock(fimc);
548 return ret;
549}
550
551static int fimc_capture_release(struct file *file)
552{
553 struct fimc_dev *fimc = video_drvdata(file);
554 struct fimc_vid_cap *vc = &fimc->vid_cap;
555 int ret;
556
557 dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state);
558
559 mutex_lock(&fimc->lock);
560
561 if (v4l2_fh_is_singular_file(file)) {
562 if (vc->streaming) {
563 media_entity_pipeline_stop(&vc->vfd.entity);
564 vc->streaming = false;
565 }
566 clear_bit(ST_CAPT_BUSY, &fimc->state);
567 fimc_stop_capture(fimc, false);
568 fimc_pipeline_call(fimc, close, &fimc->pipeline);
569 clear_bit(ST_CAPT_SUSPENDED, &fimc->state);
570 fimc->vid_cap.refcnt--;
571 }
572
573 pm_runtime_put(&fimc->pdev->dev);
574
575 if (v4l2_fh_is_singular_file(file))
576 fimc_ctrls_delete(fimc->vid_cap.ctx);
577
578 ret = vb2_fop_release(file);
579 mutex_unlock(&fimc->lock);
580
581 return ret;
582}
583
584static const struct v4l2_file_operations fimc_capture_fops = {
585 .owner = THIS_MODULE,
586 .open = fimc_capture_open,
587 .release = fimc_capture_release,
588 .poll = vb2_fop_poll,
589 .unlocked_ioctl = video_ioctl2,
590 .mmap = vb2_fop_mmap,
591};
592
593/*
594 * Format and crop negotiation helpers
595 */
596
597static struct fimc_fmt *fimc_capture_try_format(struct fimc_ctx *ctx,
598 u32 *width, u32 *height,
599 u32 *code, u32 *fourcc, int pad)
600{
601 bool rotation = ctx->rotation == 90 || ctx->rotation == 270;
602 struct fimc_dev *fimc = ctx->fimc_dev;
603 const struct fimc_variant *var = fimc->variant;
604 const struct fimc_pix_limit *pl = var->pix_limit;
605 struct fimc_frame *dst = &ctx->d_frame;
606 u32 depth, min_w, max_w, min_h, align_h = 3;
607 u32 mask = FMT_FLAGS_CAM;
608 struct fimc_fmt *ffmt;
609
610 /* Conversion from/to JPEG or User Defined format is not supported */
611 if (code && ctx->s_frame.fmt && pad == FIMC_SD_PAD_SOURCE &&
612 fimc_fmt_is_user_defined(ctx->s_frame.fmt->color))
613 *code = ctx->s_frame.fmt->mbus_code;
614
615 if (fourcc && *fourcc != V4L2_PIX_FMT_JPEG && pad == FIMC_SD_PAD_SOURCE)
616 mask |= FMT_FLAGS_M2M;
617
618 if (pad == FIMC_SD_PAD_SINK_FIFO)
619 mask = FMT_FLAGS_WRITEBACK;
620
621 ffmt = fimc_find_format(fourcc, code, mask, 0);
622 if (WARN_ON(!ffmt))
623 return NULL;
624
625 if (code)
626 *code = ffmt->mbus_code;
627 if (fourcc)
628 *fourcc = ffmt->fourcc;
629
630 if (pad != FIMC_SD_PAD_SOURCE) {
631 max_w = fimc_fmt_is_user_defined(ffmt->color) ?
632 pl->scaler_dis_w : pl->scaler_en_w;
633 /* Apply the camera input interface pixel constraints */
634 v4l_bound_align_image(width, max_t(u32, *width, 32), max_w, 4,
635 height, max_t(u32, *height, 32),
636 FIMC_CAMIF_MAX_HEIGHT,
637 fimc_fmt_is_user_defined(ffmt->color) ?
638 3 : 1,
639 0);
640 return ffmt;
641 }
642 /* Can't scale or crop in transparent (JPEG) transfer mode */
643 if (fimc_fmt_is_user_defined(ffmt->color)) {
644 *width = ctx->s_frame.f_width;
645 *height = ctx->s_frame.f_height;
646 return ffmt;
647 }
648 /* Apply the scaler and the output DMA constraints */
649 max_w = rotation ? pl->out_rot_en_w : pl->out_rot_dis_w;
650 if (ctx->state & FIMC_COMPOSE) {
651 min_w = dst->offs_h + dst->width;
652 min_h = dst->offs_v + dst->height;
653 } else {
654 min_w = var->min_out_pixsize;
655 min_h = var->min_out_pixsize;
656 }
657 if (var->min_vsize_align == 1 && !rotation)
658 align_h = fimc_fmt_is_rgb(ffmt->color) ? 0 : 1;
659
660 depth = fimc_get_format_depth(ffmt);
661 v4l_bound_align_image(width, min_w, max_w,
662 ffs(var->min_out_pixsize) - 1,
663 height, min_h, FIMC_CAMIF_MAX_HEIGHT,
664 align_h,
665 64/(ALIGN(depth, 8)));
666
667 dbg("pad%d: code: 0x%x, %dx%d. dst fmt: %dx%d",
668 pad, code ? *code : 0, *width, *height,
669 dst->f_width, dst->f_height);
670
671 return ffmt;
672}
673
674static void fimc_capture_try_selection(struct fimc_ctx *ctx,
675 struct v4l2_rect *r,
676 int target)
677{
678 bool rotate = ctx->rotation == 90 || ctx->rotation == 270;
679 struct fimc_dev *fimc = ctx->fimc_dev;
680 const struct fimc_variant *var = fimc->variant;
681 const struct fimc_pix_limit *pl = var->pix_limit;
682 struct fimc_frame *sink = &ctx->s_frame;
683 u32 max_w, max_h, min_w = 0, min_h = 0, min_sz;
684 u32 align_sz = 0, align_h = 4;
685 u32 max_sc_h, max_sc_v;
686
687 /* In JPEG transparent transfer mode cropping is not supported */
688 if (fimc_fmt_is_user_defined(ctx->d_frame.fmt->color)) {
689 r->width = sink->f_width;
690 r->height = sink->f_height;
691 r->left = r->top = 0;
692 return;
693 }
694 if (target == V4L2_SEL_TGT_COMPOSE) {
695 if (ctx->rotation != 90 && ctx->rotation != 270)
696 align_h = 1;
697 max_sc_h = min(SCALER_MAX_HRATIO, 1 << (ffs(sink->width) - 3));
698 max_sc_v = min(SCALER_MAX_VRATIO, 1 << (ffs(sink->height) - 1));
699 min_sz = var->min_out_pixsize;
700 } else {
701 u32 depth = fimc_get_format_depth(sink->fmt);
702 align_sz = 64/ALIGN(depth, 8);
703 min_sz = var->min_inp_pixsize;
704 min_w = min_h = min_sz;
705 max_sc_h = max_sc_v = 1;
706 }
707 /*
708 * For the compose rectangle the following constraints must be met:
709 * - it must fit in the sink pad format rectangle (f_width/f_height);
710 * - maximum downscaling ratio is 64;
711 * - maximum crop size depends if the rotator is used or not;
712 * - the sink pad format width/height must be 4 multiple of the
713 * prescaler ratios determined by sink pad size and source pad crop,
714 * the prescaler ratio is returned by fimc_get_scaler_factor().
715 */
716 max_w = min_t(u32,
717 rotate ? pl->out_rot_en_w : pl->out_rot_dis_w,
718 rotate ? sink->f_height : sink->f_width);
719 max_h = min_t(u32, FIMC_CAMIF_MAX_HEIGHT, sink->f_height);
720
721 if (target == V4L2_SEL_TGT_COMPOSE) {
722 min_w = min_t(u32, max_w, sink->f_width / max_sc_h);
723 min_h = min_t(u32, max_h, sink->f_height / max_sc_v);
724 if (rotate) {
725 swap(max_sc_h, max_sc_v);
726 swap(min_w, min_h);
727 }
728 }
729 v4l_bound_align_image(&r->width, min_w, max_w, ffs(min_sz) - 1,
730 &r->height, min_h, max_h, align_h,
731 align_sz);
732 /* Adjust left/top if crop/compose rectangle is out of bounds */
733 r->left = clamp_t(u32, r->left, 0, sink->f_width - r->width);
734 r->top = clamp_t(u32, r->top, 0, sink->f_height - r->height);
735 r->left = round_down(r->left, var->hor_offs_align);
736
737 dbg("target %#x: (%d,%d)/%dx%d, sink fmt: %dx%d",
738 target, r->left, r->top, r->width, r->height,
739 sink->f_width, sink->f_height);
740}
741
742/*
743 * The video node ioctl operations
744 */
745static int fimc_cap_querycap(struct file *file, void *priv,
746 struct v4l2_capability *cap)
747{
748 struct fimc_dev *fimc = video_drvdata(file);
749
750 __fimc_vidioc_querycap(&fimc->pdev->dev, cap, V4L2_CAP_STREAMING |
751 V4L2_CAP_VIDEO_CAPTURE_MPLANE);
752 return 0;
753}
754
755static int fimc_cap_enum_fmt_mplane(struct file *file, void *priv,
756 struct v4l2_fmtdesc *f)
757{
758 struct fimc_fmt *fmt;
759
760 fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM | FMT_FLAGS_M2M,
761 f->index);
762 if (!fmt)
763 return -EINVAL;
764 strncpy(f->description, fmt->name, sizeof(f->description) - 1);
765 f->pixelformat = fmt->fourcc;
766 if (fmt->fourcc == V4L2_MBUS_FMT_JPEG_1X8)
767 f->flags |= V4L2_FMT_FLAG_COMPRESSED;
768 return 0;
769}
770
771static struct media_entity *fimc_pipeline_get_head(struct media_entity *me)
772{
773 struct media_pad *pad = &me->pads[0];
774
775 while (!(pad->flags & MEDIA_PAD_FL_SOURCE)) {
776 pad = media_entity_remote_source(pad);
777 if (!pad)
778 break;
779 me = pad->entity;
780 pad = &me->pads[0];
781 }
782
783 return me;
784}
785
786/**
787 * fimc_pipeline_try_format - negotiate and/or set formats at pipeline
788 * elements
789 * @ctx: FIMC capture context
790 * @tfmt: media bus format to try/set on subdevs
791 * @fmt_id: fimc pixel format id corresponding to returned @tfmt (output)
792 * @set: true to set format on subdevs, false to try only
793 */
794static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
795 struct v4l2_mbus_framefmt *tfmt,
796 struct fimc_fmt **fmt_id,
797 bool set)
798{
799 struct fimc_dev *fimc = ctx->fimc_dev;
800 struct v4l2_subdev *sd = fimc->pipeline.subdevs[IDX_SENSOR];
801 struct v4l2_subdev_format sfmt;
802 struct v4l2_mbus_framefmt *mf = &sfmt.format;
803 struct media_entity *me;
804 struct fimc_fmt *ffmt;
805 struct media_pad *pad;
806 int ret, i = 1;
807 u32 fcc;
808
809 if (WARN_ON(!sd || !tfmt))
810 return -EINVAL;
811
812 memset(&sfmt, 0, sizeof(sfmt));
813 sfmt.format = *tfmt;
814 sfmt.which = set ? V4L2_SUBDEV_FORMAT_ACTIVE : V4L2_SUBDEV_FORMAT_TRY;
815
816 me = fimc_pipeline_get_head(&sd->entity);
817
818 while (1) {
819 ffmt = fimc_find_format(NULL, mf->code != 0 ? &mf->code : NULL,
820 FMT_FLAGS_CAM, i++);
821 if (ffmt == NULL) {
822 /*
823 * Notify user-space if common pixel code for
824 * host and sensor does not exist.
825 */
826 return -EINVAL;
827 }
828 mf->code = tfmt->code = ffmt->mbus_code;
829
830 /* set format on all pipeline subdevs */
831 while (me != &fimc->vid_cap.subdev.entity) {
832 sd = media_entity_to_v4l2_subdev(me);
833
834 sfmt.pad = 0;
835 ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &sfmt);
836 if (ret)
837 return ret;
838
839 if (me->pads[0].flags & MEDIA_PAD_FL_SINK) {
840 sfmt.pad = me->num_pads - 1;
841 mf->code = tfmt->code;
842 ret = v4l2_subdev_call(sd, pad, set_fmt, NULL,
843 &sfmt);
844 if (ret)
845 return ret;
846 }
847
848 pad = media_entity_remote_source(&me->pads[sfmt.pad]);
849 if (!pad)
850 return -EINVAL;
851 me = pad->entity;
852 }
853
854 if (mf->code != tfmt->code)
855 continue;
856
857 fcc = ffmt->fourcc;
858 tfmt->width = mf->width;
859 tfmt->height = mf->height;
860 ffmt = fimc_capture_try_format(ctx, &tfmt->width, &tfmt->height,
861 NULL, &fcc, FIMC_SD_PAD_SINK_CAM);
862 ffmt = fimc_capture_try_format(ctx, &tfmt->width, &tfmt->height,
863 NULL, &fcc, FIMC_SD_PAD_SOURCE);
864 if (ffmt && ffmt->mbus_code)
865 mf->code = ffmt->mbus_code;
866 if (mf->width != tfmt->width || mf->height != tfmt->height)
867 continue;
868 tfmt->code = mf->code;
869 break;
870 }
871
872 if (fmt_id && ffmt)
873 *fmt_id = ffmt;
874 *tfmt = *mf;
875
876 return 0;
877}
878
879/**
880 * fimc_get_sensor_frame_desc - query the sensor for media bus frame parameters
881 * @sensor: pointer to the sensor subdev
882 * @plane_fmt: provides plane sizes corresponding to the frame layout entries
883 * @try: true to set the frame parameters, false to query only
884 *
885 * This function is used by this driver only for compressed/blob data formats.
886 */
887static int fimc_get_sensor_frame_desc(struct v4l2_subdev *sensor,
888 struct v4l2_plane_pix_format *plane_fmt,
889 unsigned int num_planes, bool try)
890{
891 struct v4l2_mbus_frame_desc fd;
892 int i, ret;
893 int pad;
894
895 for (i = 0; i < num_planes; i++)
896 fd.entry[i].length = plane_fmt[i].sizeimage;
897
898 pad = sensor->entity.num_pads - 1;
899 if (try)
900 ret = v4l2_subdev_call(sensor, pad, set_frame_desc, pad, &fd);
901 else
902 ret = v4l2_subdev_call(sensor, pad, get_frame_desc, pad, &fd);
903
904 if (ret < 0)
905 return ret;
906
907 if (num_planes != fd.num_entries)
908 return -EINVAL;
909
910 for (i = 0; i < num_planes; i++)
911 plane_fmt[i].sizeimage = fd.entry[i].length;
912
913 if (fd.entry[0].length > FIMC_MAX_JPEG_BUF_SIZE) {
914 v4l2_err(sensor->v4l2_dev, "Unsupported buffer size: %u\n",
915 fd.entry[0].length);
916
917 return -EINVAL;
918 }
919
920 return 0;
921}
922
923static int fimc_cap_g_fmt_mplane(struct file *file, void *fh,
924 struct v4l2_format *f)
925{
926 struct fimc_dev *fimc = video_drvdata(file);
927
928 __fimc_get_format(&fimc->vid_cap.ctx->d_frame, f);
929 return 0;
930}
931
932static int fimc_cap_try_fmt_mplane(struct file *file, void *fh,
933 struct v4l2_format *f)
934{
935 struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
936 struct fimc_dev *fimc = video_drvdata(file);
937 struct fimc_ctx *ctx = fimc->vid_cap.ctx;
938 struct v4l2_mbus_framefmt mf;
939 struct fimc_fmt *ffmt = NULL;
940 int ret = 0;
941
942 fimc_md_graph_lock(fimc);
943 mutex_lock(&fimc->lock);
944
945 if (fimc_jpeg_fourcc(pix->pixelformat)) {
946 fimc_capture_try_format(ctx, &pix->width, &pix->height,
947 NULL, &pix->pixelformat,
948 FIMC_SD_PAD_SINK_CAM);
949 ctx->s_frame.f_width = pix->width;
950 ctx->s_frame.f_height = pix->height;
951 }
952 ffmt = fimc_capture_try_format(ctx, &pix->width, &pix->height,
953 NULL, &pix->pixelformat,
954 FIMC_SD_PAD_SOURCE);
955 if (!ffmt) {
956 ret = -EINVAL;
957 goto unlock;
958 }
959
960 if (!fimc->vid_cap.user_subdev_api) {
961 mf.width = pix->width;
962 mf.height = pix->height;
963 mf.code = ffmt->mbus_code;
964 fimc_pipeline_try_format(ctx, &mf, &ffmt, false);
965 pix->width = mf.width;
966 pix->height = mf.height;
967 if (ffmt)
968 pix->pixelformat = ffmt->fourcc;
969 }
970
971 fimc_adjust_mplane_format(ffmt, pix->width, pix->height, pix);
972
973 if (ffmt->flags & FMT_FLAGS_COMPRESSED)
974 fimc_get_sensor_frame_desc(fimc->pipeline.subdevs[IDX_SENSOR],
975 pix->plane_fmt, ffmt->memplanes, true);
976unlock:
977 mutex_unlock(&fimc->lock);
978 fimc_md_graph_unlock(fimc);
979
980 return ret;
981}
982
983static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx,
984 enum fimc_color_fmt color)
985{
986 bool jpeg = fimc_fmt_is_user_defined(color);
987
988 ctx->scaler.enabled = !jpeg;
989 fimc_ctrls_activate(ctx, !jpeg);
990
991 if (jpeg)
992 set_bit(ST_CAPT_JPEG, &ctx->fimc_dev->state);
993 else
994 clear_bit(ST_CAPT_JPEG, &ctx->fimc_dev->state);
995}
996
997static int __fimc_capture_set_format(struct fimc_dev *fimc,
998 struct v4l2_format *f)
999{
1000 struct fimc_ctx *ctx = fimc->vid_cap.ctx;
1001 struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
1002 struct v4l2_mbus_framefmt *mf = &fimc->vid_cap.ci_fmt;
1003 struct fimc_frame *ff = &ctx->d_frame;
1004 struct fimc_fmt *s_fmt = NULL;
1005 int ret, i;
1006
1007 if (vb2_is_busy(&fimc->vid_cap.vbq))
1008 return -EBUSY;
1009
1010 /* Pre-configure format at camera interface input, for JPEG only */
1011 if (fimc_jpeg_fourcc(pix->pixelformat)) {
1012 fimc_capture_try_format(ctx, &pix->width, &pix->height,
1013 NULL, &pix->pixelformat,
1014 FIMC_SD_PAD_SINK_CAM);
1015 ctx->s_frame.f_width = pix->width;
1016 ctx->s_frame.f_height = pix->height;
1017 }
1018 /* Try the format at the scaler and the DMA output */
1019 ff->fmt = fimc_capture_try_format(ctx, &pix->width, &pix->height,
1020 NULL, &pix->pixelformat,
1021 FIMC_SD_PAD_SOURCE);
1022 if (!ff->fmt)
1023 return -EINVAL;
1024
1025 /* Update RGB Alpha control state and value range */
1026 fimc_alpha_ctrl_update(ctx);
1027
1028 /* Try to match format at the host and the sensor */
1029 if (!fimc->vid_cap.user_subdev_api) {
1030 mf->code = ff->fmt->mbus_code;
1031 mf->width = pix->width;
1032 mf->height = pix->height;
1033 ret = fimc_pipeline_try_format(ctx, mf, &s_fmt, true);
1034 if (ret)
1035 return ret;
1036
1037 pix->width = mf->width;
1038 pix->height = mf->height;
1039 }
1040
1041 fimc_adjust_mplane_format(ff->fmt, pix->width, pix->height, pix);
1042
1043 if (ff->fmt->flags & FMT_FLAGS_COMPRESSED) {
1044 ret = fimc_get_sensor_frame_desc(fimc->pipeline.subdevs[IDX_SENSOR],
1045 pix->plane_fmt, ff->fmt->memplanes,
1046 true);
1047 if (ret < 0)
1048 return ret;
1049 }
1050
1051 for (i = 0; i < ff->fmt->memplanes; i++) {
1052 ff->bytesperline[i] = pix->plane_fmt[i].bytesperline;
1053 ff->payload[i] = pix->plane_fmt[i].sizeimage;
1054 }
1055
1056 set_frame_bounds(ff, pix->width, pix->height);
1057 /* Reset the composition rectangle if not yet configured */
1058 if (!(ctx->state & FIMC_COMPOSE))
1059 set_frame_crop(ff, 0, 0, pix->width, pix->height);
1060
1061 fimc_capture_mark_jpeg_xfer(ctx, ff->fmt->color);
1062
1063 /* Reset cropping and set format at the camera interface input */
1064 if (!fimc->vid_cap.user_subdev_api) {
1065 ctx->s_frame.fmt = s_fmt;
1066 set_frame_bounds(&ctx->s_frame, pix->width, pix->height);
1067 set_frame_crop(&ctx->s_frame, 0, 0, pix->width, pix->height);
1068 }
1069
1070 return ret;
1071}
1072
1073static int fimc_cap_s_fmt_mplane(struct file *file, void *priv,
1074 struct v4l2_format *f)
1075{
1076 struct fimc_dev *fimc = video_drvdata(file);
1077 int ret;
1078
1079 fimc_md_graph_lock(fimc);
1080 mutex_lock(&fimc->lock);
1081 /*
1082 * The graph is walked within __fimc_capture_set_format() to set
1083 * the format at subdevs thus the graph mutex needs to be held at
1084 * this point and acquired before the video mutex, to avoid AB-BA
1085 * deadlock when fimc_md_link_notify() is called by other thread.
1086 * Ideally the graph walking and setting format at the whole pipeline
1087 * should be removed from this driver and handled in userspace only.
1088 */
1089 ret = __fimc_capture_set_format(fimc, f);
1090
1091 mutex_unlock(&fimc->lock);
1092 fimc_md_graph_unlock(fimc);
1093 return ret;
1094}
1095
1096static int fimc_cap_enum_input(struct file *file, void *priv,
1097 struct v4l2_input *i)
1098{
1099 struct fimc_dev *fimc = video_drvdata(file);
1100 struct v4l2_subdev *sd = fimc->pipeline.subdevs[IDX_SENSOR];
1101
1102 if (i->index != 0)
1103 return -EINVAL;
1104
1105 i->type = V4L2_INPUT_TYPE_CAMERA;
1106 if (sd)
1107 strlcpy(i->name, sd->name, sizeof(i->name));
1108 return 0;
1109}
1110
1111static int fimc_cap_s_input(struct file *file, void *priv, unsigned int i)
1112{
1113 return i == 0 ? i : -EINVAL;
1114}
1115
1116static int fimc_cap_g_input(struct file *file, void *priv, unsigned int *i)
1117{
1118 *i = 0;
1119 return 0;
1120}
1121
1122/**
1123 * fimc_pipeline_validate - check for formats inconsistencies
1124 * between source and sink pad of each link
1125 *
1126 * Return 0 if all formats match or -EPIPE otherwise.
1127 */
1128static int fimc_pipeline_validate(struct fimc_dev *fimc)
1129{
1130 struct v4l2_subdev_format sink_fmt, src_fmt;
1131 struct fimc_vid_cap *vc = &fimc->vid_cap;
1132 struct v4l2_subdev *sd = &vc->subdev;
1133 struct media_pad *sink_pad, *src_pad;
1134 int i, ret;
1135
1136 while (1) {
1137 /*
1138 * Find current entity sink pad and any remote sink pad linked
1139 * to it. We stop if there is no sink pad in current entity or
1140 * it is not linked to any other remote entity.
1141 */
1142 src_pad = NULL;
1143
1144 for (i = 0; i < sd->entity.num_pads; i++) {
1145 struct media_pad *p = &sd->entity.pads[i];
1146
1147 if (p->flags & MEDIA_PAD_FL_SINK) {
1148 sink_pad = p;
1149 src_pad = media_entity_remote_source(sink_pad);
1150 if (src_pad)
1151 break;
1152 }
1153 }
1154
1155 if (src_pad == NULL ||
1156 media_entity_type(src_pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
1157 break;
1158
1159 /* Don't call FIMC subdev operation to avoid nested locking */
1160 if (sd == &vc->subdev) {
1161 struct fimc_frame *ff = &vc->ctx->s_frame;
1162 sink_fmt.format.width = ff->f_width;
1163 sink_fmt.format.height = ff->f_height;
1164 sink_fmt.format.code = ff->fmt ? ff->fmt->mbus_code : 0;
1165 } else {
1166 sink_fmt.pad = sink_pad->index;
1167 sink_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1168 ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &sink_fmt);
1169 if (ret < 0 && ret != -ENOIOCTLCMD)
1170 return -EPIPE;
1171 }
1172
1173 /* Retrieve format at the source pad */
1174 sd = media_entity_to_v4l2_subdev(src_pad->entity);
1175 src_fmt.pad = src_pad->index;
1176 src_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1177 ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &src_fmt);
1178 if (ret < 0 && ret != -ENOIOCTLCMD)
1179 return -EPIPE;
1180
1181 if (src_fmt.format.width != sink_fmt.format.width ||
1182 src_fmt.format.height != sink_fmt.format.height ||
1183 src_fmt.format.code != sink_fmt.format.code)
1184 return -EPIPE;
1185
1186 if (sd == fimc->pipeline.subdevs[IDX_SENSOR] &&
1187 fimc_user_defined_mbus_fmt(src_fmt.format.code)) {
1188 struct v4l2_plane_pix_format plane_fmt[FIMC_MAX_PLANES];
1189 struct fimc_frame *frame = &vc->ctx->d_frame;
1190 unsigned int i;
1191
1192 ret = fimc_get_sensor_frame_desc(sd, plane_fmt,
1193 frame->fmt->memplanes,
1194 false);
1195 if (ret < 0)
1196 return -EPIPE;
1197
1198 for (i = 0; i < frame->fmt->memplanes; i++)
1199 if (frame->payload[i] < plane_fmt[i].sizeimage)
1200 return -EPIPE;
1201 }
1202 }
1203 return 0;
1204}
1205
1206static int fimc_cap_streamon(struct file *file, void *priv,
1207 enum v4l2_buf_type type)
1208{
1209 struct fimc_dev *fimc = video_drvdata(file);
1210 struct fimc_pipeline *p = &fimc->pipeline;
1211 struct fimc_vid_cap *vc = &fimc->vid_cap;
1212 struct media_entity *entity = &vc->vfd.entity;
1213 struct fimc_source_info *si = NULL;
1214 struct v4l2_subdev *sd;
1215 int ret;
1216
1217 if (fimc_capture_active(fimc))
1218 return -EBUSY;
1219
1220 ret = media_entity_pipeline_start(entity, p->m_pipeline);
1221 if (ret < 0)
1222 return ret;
1223
1224 sd = p->subdevs[IDX_SENSOR];
1225 if (sd)
1226 si = v4l2_get_subdev_hostdata(sd);
1227
1228 if (si == NULL) {
1229 ret = -EPIPE;
1230 goto err_p_stop;
1231 }
1232 /*
1233 * Save configuration data related to currently attached image
1234 * sensor or other data source, e.g. FIMC-IS.
1235 */
1236 vc->source_config = *si;
1237
1238 if (vc->input == GRP_ID_FIMC_IS)
1239 vc->source_config.fimc_bus_type = FIMC_BUS_TYPE_ISP_WRITEBACK;
1240
1241 if (vc->user_subdev_api) {
1242 ret = fimc_pipeline_validate(fimc);
1243 if (ret < 0)
1244 goto err_p_stop;
1245 }
1246
1247 ret = vb2_ioctl_streamon(file, priv, type);
1248 if (!ret) {
1249 vc->streaming = true;
1250 return ret;
1251 }
1252
1253err_p_stop:
1254 media_entity_pipeline_stop(entity);
1255 return ret;
1256}
1257
1258static int fimc_cap_streamoff(struct file *file, void *priv,
1259 enum v4l2_buf_type type)
1260{
1261 struct fimc_dev *fimc = video_drvdata(file);
1262 int ret;
1263
1264 ret = vb2_ioctl_streamoff(file, priv, type);
1265 if (ret < 0)
1266 return ret;
1267
1268 media_entity_pipeline_stop(&fimc->vid_cap.vfd.entity);
1269 fimc->vid_cap.streaming = false;
1270 return 0;
1271}
1272
1273static int fimc_cap_reqbufs(struct file *file, void *priv,
1274 struct v4l2_requestbuffers *reqbufs)
1275{
1276 struct fimc_dev *fimc = video_drvdata(file);
1277 int ret;
1278
1279 ret = vb2_ioctl_reqbufs(file, priv, reqbufs);
1280
1281 if (!ret)
1282 fimc->vid_cap.reqbufs_count = reqbufs->count;
1283
1284 return ret;
1285}
1286
1287static int fimc_cap_g_selection(struct file *file, void *fh,
1288 struct v4l2_selection *s)
1289{
1290 struct fimc_dev *fimc = video_drvdata(file);
1291 struct fimc_ctx *ctx = fimc->vid_cap.ctx;
1292 struct fimc_frame *f = &ctx->s_frame;
1293
1294 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1295 return -EINVAL;
1296
1297 switch (s->target) {
1298 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
1299 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
1300 f = &ctx->d_frame;
1301 case V4L2_SEL_TGT_CROP_BOUNDS:
1302 case V4L2_SEL_TGT_CROP_DEFAULT:
1303 s->r.left = 0;
1304 s->r.top = 0;
1305 s->r.width = f->o_width;
1306 s->r.height = f->o_height;
1307 return 0;
1308
1309 case V4L2_SEL_TGT_COMPOSE:
1310 f = &ctx->d_frame;
1311 case V4L2_SEL_TGT_CROP:
1312 s->r.left = f->offs_h;
1313 s->r.top = f->offs_v;
1314 s->r.width = f->width;
1315 s->r.height = f->height;
1316 return 0;
1317 }
1318
1319 return -EINVAL;
1320}
1321
1322/* Return 1 if rectangle a is enclosed in rectangle b, or 0 otherwise. */
1323static int enclosed_rectangle(struct v4l2_rect *a, struct v4l2_rect *b)
1324{
1325 if (a->left < b->left || a->top < b->top)
1326 return 0;
1327 if (a->left + a->width > b->left + b->width)
1328 return 0;
1329 if (a->top + a->height > b->top + b->height)
1330 return 0;
1331
1332 return 1;
1333}
1334
1335static int fimc_cap_s_selection(struct file *file, void *fh,
1336 struct v4l2_selection *s)
1337{
1338 struct fimc_dev *fimc = video_drvdata(file);
1339 struct fimc_ctx *ctx = fimc->vid_cap.ctx;
1340 struct v4l2_rect rect = s->r;
1341 struct fimc_frame *f;
1342 unsigned long flags;
1343
1344 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1345 return -EINVAL;
1346
1347 if (s->target == V4L2_SEL_TGT_COMPOSE)
1348 f = &ctx->d_frame;
1349 else if (s->target == V4L2_SEL_TGT_CROP)
1350 f = &ctx->s_frame;
1351 else
1352 return -EINVAL;
1353
1354 fimc_capture_try_selection(ctx, &rect, s->target);
1355
1356 if (s->flags & V4L2_SEL_FLAG_LE &&
1357 !enclosed_rectangle(&rect, &s->r))
1358 return -ERANGE;
1359
1360 if (s->flags & V4L2_SEL_FLAG_GE &&
1361 !enclosed_rectangle(&s->r, &rect))
1362 return -ERANGE;
1363
1364 s->r = rect;
1365 spin_lock_irqsave(&fimc->slock, flags);
1366 set_frame_crop(f, s->r.left, s->r.top, s->r.width,
1367 s->r.height);
1368 spin_unlock_irqrestore(&fimc->slock, flags);
1369
1370 set_bit(ST_CAPT_APPLY_CFG, &fimc->state);
1371 return 0;
1372}
1373
1374static const struct v4l2_ioctl_ops fimc_capture_ioctl_ops = {
1375 .vidioc_querycap = fimc_cap_querycap,
1376
1377 .vidioc_enum_fmt_vid_cap_mplane = fimc_cap_enum_fmt_mplane,
1378 .vidioc_try_fmt_vid_cap_mplane = fimc_cap_try_fmt_mplane,
1379 .vidioc_s_fmt_vid_cap_mplane = fimc_cap_s_fmt_mplane,
1380 .vidioc_g_fmt_vid_cap_mplane = fimc_cap_g_fmt_mplane,
1381
1382 .vidioc_reqbufs = fimc_cap_reqbufs,
1383 .vidioc_querybuf = vb2_ioctl_querybuf,
1384 .vidioc_qbuf = vb2_ioctl_qbuf,
1385 .vidioc_dqbuf = vb2_ioctl_dqbuf,
1386 .vidioc_expbuf = vb2_ioctl_expbuf,
1387 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
1388 .vidioc_create_bufs = vb2_ioctl_create_bufs,
1389
1390 .vidioc_streamon = fimc_cap_streamon,
1391 .vidioc_streamoff = fimc_cap_streamoff,
1392
1393 .vidioc_g_selection = fimc_cap_g_selection,
1394 .vidioc_s_selection = fimc_cap_s_selection,
1395
1396 .vidioc_enum_input = fimc_cap_enum_input,
1397 .vidioc_s_input = fimc_cap_s_input,
1398 .vidioc_g_input = fimc_cap_g_input,
1399};
1400
1401/* Capture subdev media entity operations */
1402static int fimc_link_setup(struct media_entity *entity,
1403 const struct media_pad *local,
1404 const struct media_pad *remote, u32 flags)
1405{
1406 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
1407 struct fimc_dev *fimc = v4l2_get_subdevdata(sd);
1408
1409 if (media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
1410 return -EINVAL;
1411
1412 if (WARN_ON(fimc == NULL))
1413 return 0;
1414
1415 dbg("%s --> %s, flags: 0x%x. input: 0x%x",
1416 local->entity->name, remote->entity->name, flags,
1417 fimc->vid_cap.input);
1418
1419 if (flags & MEDIA_LNK_FL_ENABLED) {
1420 if (fimc->vid_cap.input != 0)
1421 return -EBUSY;
1422 fimc->vid_cap.input = sd->grp_id;
1423 return 0;
1424 }
1425
1426 fimc->vid_cap.input = 0;
1427 return 0;
1428}
1429
1430static const struct media_entity_operations fimc_sd_media_ops = {
1431 .link_setup = fimc_link_setup,
1432};
1433
1434/**
1435 * fimc_sensor_notify - v4l2_device notification from a sensor subdev
1436 * @sd: pointer to a subdev generating the notification
1437 * @notification: the notification type, must be S5P_FIMC_TX_END_NOTIFY
1438 * @arg: pointer to an u32 type integer that stores the frame payload value
1439 *
1440 * The End Of Frame notification sent by sensor subdev in its still capture
1441 * mode. If there is only a single VSYNC generated by the sensor at the
1442 * beginning of a frame transmission, FIMC does not issue the LastIrq
1443 * (end of frame) interrupt. And this notification is used to complete the
1444 * frame capture and returning a buffer to user-space. Subdev drivers should
1445 * call this notification from their last 'End of frame capture' interrupt.
1446 */
1447void fimc_sensor_notify(struct v4l2_subdev *sd, unsigned int notification,
1448 void *arg)
1449{
1450 struct fimc_source_info *si;
1451 struct fimc_vid_buffer *buf;
1452 struct fimc_md *fmd;
1453 struct fimc_dev *fimc;
1454 unsigned long flags;
1455
1456 if (sd == NULL)
1457 return;
1458
1459 si = v4l2_get_subdev_hostdata(sd);
1460 fmd = entity_to_fimc_mdev(&sd->entity);
1461
1462 spin_lock_irqsave(&fmd->slock, flags);
1463
1464 fimc = si ? source_to_sensor_info(si)->host : NULL;
1465
1466 if (fimc && arg && notification == S5P_FIMC_TX_END_NOTIFY &&
1467 test_bit(ST_CAPT_PEND, &fimc->state)) {
1468 unsigned long irq_flags;
1469 spin_lock_irqsave(&fimc->slock, irq_flags);
1470 if (!list_empty(&fimc->vid_cap.active_buf_q)) {
1471 buf = list_entry(fimc->vid_cap.active_buf_q.next,
1472 struct fimc_vid_buffer, list);
1473 vb2_set_plane_payload(&buf->vb, 0, *((u32 *)arg));
1474 }
1475 fimc_capture_irq_handler(fimc, 1);
1476 fimc_deactivate_capture(fimc);
1477 spin_unlock_irqrestore(&fimc->slock, irq_flags);
1478 }
1479 spin_unlock_irqrestore(&fmd->slock, flags);
1480}
1481
1482static int fimc_subdev_enum_mbus_code(struct v4l2_subdev *sd,
1483 struct v4l2_subdev_fh *fh,
1484 struct v4l2_subdev_mbus_code_enum *code)
1485{
1486 struct fimc_fmt *fmt;
1487
1488 fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM, code->index);
1489 if (!fmt)
1490 return -EINVAL;
1491 code->code = fmt->mbus_code;
1492 return 0;
1493}
1494
1495static int fimc_subdev_get_fmt(struct v4l2_subdev *sd,
1496 struct v4l2_subdev_fh *fh,
1497 struct v4l2_subdev_format *fmt)
1498{
1499 struct fimc_dev *fimc = v4l2_get_subdevdata(sd);
1500 struct fimc_ctx *ctx = fimc->vid_cap.ctx;
1501 struct fimc_frame *ff = &ctx->s_frame;
1502 struct v4l2_mbus_framefmt *mf;
1503
1504 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
1505 mf = v4l2_subdev_get_try_format(fh, fmt->pad);
1506 fmt->format = *mf;
1507 return 0;
1508 }
1509
1510 mf = &fmt->format;
1511 mutex_lock(&fimc->lock);
1512
1513 switch (fmt->pad) {
1514 case FIMC_SD_PAD_SOURCE:
1515 if (!WARN_ON(ff->fmt == NULL))
1516 mf->code = ff->fmt->mbus_code;
1517 /* Sink pads crop rectangle size */
1518 mf->width = ff->width;
1519 mf->height = ff->height;
1520 break;
1521 case FIMC_SD_PAD_SINK_FIFO:
1522 *mf = fimc->vid_cap.wb_fmt;
1523 break;
1524 case FIMC_SD_PAD_SINK_CAM:
1525 default:
1526 *mf = fimc->vid_cap.ci_fmt;
1527 break;
1528 }
1529
1530 mutex_unlock(&fimc->lock);
1531 mf->colorspace = V4L2_COLORSPACE_JPEG;
1532
1533 return 0;
1534}
1535
1536static int fimc_subdev_set_fmt(struct v4l2_subdev *sd,
1537 struct v4l2_subdev_fh *fh,
1538 struct v4l2_subdev_format *fmt)
1539{
1540 struct fimc_dev *fimc = v4l2_get_subdevdata(sd);
1541 struct v4l2_mbus_framefmt *mf = &fmt->format;
1542 struct fimc_vid_cap *vc = &fimc->vid_cap;
1543 struct fimc_ctx *ctx = vc->ctx;
1544 struct fimc_frame *ff;
1545 struct fimc_fmt *ffmt;
1546
1547 dbg("pad%d: code: 0x%x, %dx%d",
1548 fmt->pad, mf->code, mf->width, mf->height);
1549
1550 if (fmt->pad == FIMC_SD_PAD_SOURCE && vb2_is_busy(&vc->vbq))
1551 return -EBUSY;
1552
1553 mutex_lock(&fimc->lock);
1554 ffmt = fimc_capture_try_format(ctx, &mf->width, &mf->height,
1555 &mf->code, NULL, fmt->pad);
1556 mutex_unlock(&fimc->lock);
1557 mf->colorspace = V4L2_COLORSPACE_JPEG;
1558
1559 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
1560 mf = v4l2_subdev_get_try_format(fh, fmt->pad);
1561 *mf = fmt->format;
1562 return 0;
1563 }
1564 /* There must be a bug in the driver if this happens */
1565 if (WARN_ON(ffmt == NULL))
1566 return -EINVAL;
1567
1568 /* Update RGB Alpha control state and value range */
1569 fimc_alpha_ctrl_update(ctx);
1570
1571 fimc_capture_mark_jpeg_xfer(ctx, ffmt->color);
1572 if (fmt->pad == FIMC_SD_PAD_SOURCE) {
1573 ff = &ctx->d_frame;
1574 /* Sink pads crop rectangle size */
1575 mf->width = ctx->s_frame.width;
1576 mf->height = ctx->s_frame.height;
1577 } else {
1578 ff = &ctx->s_frame;
1579 }
1580
1581 mutex_lock(&fimc->lock);
1582 set_frame_bounds(ff, mf->width, mf->height);
1583
1584 if (fmt->pad == FIMC_SD_PAD_SINK_FIFO)
1585 vc->wb_fmt = *mf;
1586 else if (fmt->pad == FIMC_SD_PAD_SINK_CAM)
1587 vc->ci_fmt = *mf;
1588
1589 ff->fmt = ffmt;
1590
1591 /* Reset the crop rectangle if required. */
1592 if (!(fmt->pad == FIMC_SD_PAD_SOURCE && (ctx->state & FIMC_COMPOSE)))
1593 set_frame_crop(ff, 0, 0, mf->width, mf->height);
1594
1595 if (fmt->pad != FIMC_SD_PAD_SOURCE)
1596 ctx->state &= ~FIMC_COMPOSE;
1597
1598 mutex_unlock(&fimc->lock);
1599 return 0;
1600}
1601
1602static int fimc_subdev_get_selection(struct v4l2_subdev *sd,
1603 struct v4l2_subdev_fh *fh,
1604 struct v4l2_subdev_selection *sel)
1605{
1606 struct fimc_dev *fimc = v4l2_get_subdevdata(sd);
1607 struct fimc_ctx *ctx = fimc->vid_cap.ctx;
1608 struct fimc_frame *f = &ctx->s_frame;
1609 struct v4l2_rect *r = &sel->r;
1610 struct v4l2_rect *try_sel;
1611
1612 if (sel->pad == FIMC_SD_PAD_SOURCE)
1613 return -EINVAL;
1614
1615 mutex_lock(&fimc->lock);
1616
1617 switch (sel->target) {
1618 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
1619 f = &ctx->d_frame;
1620 case V4L2_SEL_TGT_CROP_BOUNDS:
1621 r->width = f->o_width;
1622 r->height = f->o_height;
1623 r->left = 0;
1624 r->top = 0;
1625 mutex_unlock(&fimc->lock);
1626 return 0;
1627
1628 case V4L2_SEL_TGT_CROP:
1629 try_sel = v4l2_subdev_get_try_crop(fh, sel->pad);
1630 break;
1631 case V4L2_SEL_TGT_COMPOSE:
1632 try_sel = v4l2_subdev_get_try_compose(fh, sel->pad);
1633 f = &ctx->d_frame;
1634 break;
1635 default:
1636 mutex_unlock(&fimc->lock);
1637 return -EINVAL;
1638 }
1639
1640 if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
1641 sel->r = *try_sel;
1642 } else {
1643 r->left = f->offs_h;
1644 r->top = f->offs_v;
1645 r->width = f->width;
1646 r->height = f->height;
1647 }
1648
1649 dbg("target %#x: l:%d, t:%d, %dx%d, f_w: %d, f_h: %d",
1650 sel->pad, r->left, r->top, r->width, r->height,
1651 f->f_width, f->f_height);
1652
1653 mutex_unlock(&fimc->lock);
1654 return 0;
1655}
1656
1657static int fimc_subdev_set_selection(struct v4l2_subdev *sd,
1658 struct v4l2_subdev_fh *fh,
1659 struct v4l2_subdev_selection *sel)
1660{
1661 struct fimc_dev *fimc = v4l2_get_subdevdata(sd);
1662 struct fimc_ctx *ctx = fimc->vid_cap.ctx;
1663 struct fimc_frame *f = &ctx->s_frame;
1664 struct v4l2_rect *r = &sel->r;
1665 struct v4l2_rect *try_sel;
1666 unsigned long flags;
1667
1668 if (sel->pad == FIMC_SD_PAD_SOURCE)
1669 return -EINVAL;
1670
1671 mutex_lock(&fimc->lock);
1672 fimc_capture_try_selection(ctx, r, V4L2_SEL_TGT_CROP);
1673
1674 switch (sel->target) {
1675 case V4L2_SEL_TGT_CROP:
1676 try_sel = v4l2_subdev_get_try_crop(fh, sel->pad);
1677 break;
1678 case V4L2_SEL_TGT_COMPOSE:
1679 try_sel = v4l2_subdev_get_try_compose(fh, sel->pad);
1680 f = &ctx->d_frame;
1681 break;
1682 default:
1683 mutex_unlock(&fimc->lock);
1684 return -EINVAL;
1685 }
1686
1687 if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
1688 *try_sel = sel->r;
1689 } else {
1690 spin_lock_irqsave(&fimc->slock, flags);
1691 set_frame_crop(f, r->left, r->top, r->width, r->height);
1692 set_bit(ST_CAPT_APPLY_CFG, &fimc->state);
1693 if (sel->target == V4L2_SEL_TGT_COMPOSE)
1694 ctx->state |= FIMC_COMPOSE;
1695 spin_unlock_irqrestore(&fimc->slock, flags);
1696 }
1697
1698 dbg("target %#x: (%d,%d)/%dx%d", sel->target, r->left, r->top,
1699 r->width, r->height);
1700
1701 mutex_unlock(&fimc->lock);
1702 return 0;
1703}
1704
1705static struct v4l2_subdev_pad_ops fimc_subdev_pad_ops = {
1706 .enum_mbus_code = fimc_subdev_enum_mbus_code,
1707 .get_selection = fimc_subdev_get_selection,
1708 .set_selection = fimc_subdev_set_selection,
1709 .get_fmt = fimc_subdev_get_fmt,
1710 .set_fmt = fimc_subdev_set_fmt,
1711};
1712
1713static struct v4l2_subdev_ops fimc_subdev_ops = {
1714 .pad = &fimc_subdev_pad_ops,
1715};
1716
1717/* Set default format at the sensor and host interface */
1718static int fimc_capture_set_default_format(struct fimc_dev *fimc)
1719{
1720 struct v4l2_format fmt = {
1721 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
1722 .fmt.pix_mp = {
1723 .width = 640,
1724 .height = 480,
1725 .pixelformat = V4L2_PIX_FMT_YUYV,
1726 .field = V4L2_FIELD_NONE,
1727 .colorspace = V4L2_COLORSPACE_JPEG,
1728 },
1729 };
1730
1731 return __fimc_capture_set_format(fimc, &fmt);
1732}
1733
1734/* fimc->lock must be already initialized */
1735static int fimc_register_capture_device(struct fimc_dev *fimc,
1736 struct v4l2_device *v4l2_dev)
1737{
1738 struct video_device *vfd = &fimc->vid_cap.vfd;
1739 struct vb2_queue *q = &fimc->vid_cap.vbq;
1740 struct fimc_ctx *ctx;
1741 struct fimc_vid_cap *vid_cap;
1742 int ret = -ENOMEM;
1743
1744 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
1745 if (!ctx)
1746 return -ENOMEM;
1747
1748 ctx->fimc_dev = fimc;
1749 ctx->in_path = FIMC_IO_CAMERA;
1750 ctx->out_path = FIMC_IO_DMA;
1751 ctx->state = FIMC_CTX_CAP;
1752 ctx->s_frame.fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM, 0);
1753 ctx->d_frame.fmt = ctx->s_frame.fmt;
1754
1755 memset(vfd, 0, sizeof(*vfd));
1756 snprintf(vfd->name, sizeof(vfd->name), "fimc.%d.capture", fimc->id);
1757
1758 vfd->fops = &fimc_capture_fops;
1759 vfd->ioctl_ops = &fimc_capture_ioctl_ops;
1760 vfd->v4l2_dev = v4l2_dev;
1761 vfd->minor = -1;
1762 vfd->release = video_device_release_empty;
1763 vfd->queue = q;
1764 vfd->lock = &fimc->lock;
1765
1766 video_set_drvdata(vfd, fimc);
1767 vid_cap = &fimc->vid_cap;
1768 vid_cap->active_buf_cnt = 0;
1769 vid_cap->reqbufs_count = 0;
1770 vid_cap->ctx = ctx;
1771
1772 INIT_LIST_HEAD(&vid_cap->pending_buf_q);
1773 INIT_LIST_HEAD(&vid_cap->active_buf_q);
1774
1775 memset(q, 0, sizeof(*q));
1776 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1777 q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
1778 q->drv_priv = ctx;
1779 q->ops = &fimc_capture_qops;
1780 q->mem_ops = &vb2_dma_contig_memops;
1781 q->buf_struct_size = sizeof(struct fimc_vid_buffer);
1782 q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1783 q->lock = &fimc->lock;
1784
1785 ret = vb2_queue_init(q);
1786 if (ret)
1787 goto err_ent;
1788
1789 vid_cap->vd_pad.flags = MEDIA_PAD_FL_SINK;
1790 ret = media_entity_init(&vfd->entity, 1, &vid_cap->vd_pad, 0);
1791 if (ret)
1792 goto err_ent;
1793 /*
1794 * For proper order of acquiring/releasing the video
1795 * and the graph mutex.
1796 */
1797 v4l2_disable_ioctl_locking(vfd, VIDIOC_TRY_FMT);
1798 v4l2_disable_ioctl_locking(vfd, VIDIOC_S_FMT);
1799
1800 ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
1801 if (ret)
1802 goto err_vd;
1803
1804 v4l2_info(v4l2_dev, "Registered %s as /dev/%s\n",
1805 vfd->name, video_device_node_name(vfd));
1806
1807 vfd->ctrl_handler = &ctx->ctrls.handler;
1808 return 0;
1809
1810err_vd:
1811 media_entity_cleanup(&vfd->entity);
1812err_ent:
1813 kfree(ctx);
1814 return ret;
1815}
1816
1817static int fimc_capture_subdev_registered(struct v4l2_subdev *sd)
1818{
1819 struct fimc_dev *fimc = v4l2_get_subdevdata(sd);
1820 int ret;
1821
1822 if (fimc == NULL)
1823 return -ENXIO;
1824
1825 ret = fimc_register_m2m_device(fimc, sd->v4l2_dev);
1826 if (ret)
1827 return ret;
1828
1829 fimc->pipeline_ops = v4l2_get_subdev_hostdata(sd);
1830
1831 ret = fimc_register_capture_device(fimc, sd->v4l2_dev);
1832 if (ret) {
1833 fimc_unregister_m2m_device(fimc);
1834 fimc->pipeline_ops = NULL;
1835 }
1836
1837 return ret;
1838}
1839
1840static void fimc_capture_subdev_unregistered(struct v4l2_subdev *sd)
1841{
1842 struct fimc_dev *fimc = v4l2_get_subdevdata(sd);
1843
1844 if (fimc == NULL)
1845 return;
1846
1847 fimc_unregister_m2m_device(fimc);
1848
1849 if (video_is_registered(&fimc->vid_cap.vfd)) {
1850 video_unregister_device(&fimc->vid_cap.vfd);
1851 media_entity_cleanup(&fimc->vid_cap.vfd.entity);
1852 fimc->pipeline_ops = NULL;
1853 }
1854 kfree(fimc->vid_cap.ctx);
1855 fimc->vid_cap.ctx = NULL;
1856}
1857
1858static const struct v4l2_subdev_internal_ops fimc_capture_sd_internal_ops = {
1859 .registered = fimc_capture_subdev_registered,
1860 .unregistered = fimc_capture_subdev_unregistered,
1861};
1862
1863int fimc_initialize_capture_subdev(struct fimc_dev *fimc)
1864{
1865 struct v4l2_subdev *sd = &fimc->vid_cap.subdev;
1866 int ret;
1867
1868 v4l2_subdev_init(sd, &fimc_subdev_ops);
1869 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1870 snprintf(sd->name, sizeof(sd->name), "FIMC.%d", fimc->id);
1871
1872 fimc->vid_cap.sd_pads[FIMC_SD_PAD_SINK_CAM].flags = MEDIA_PAD_FL_SINK;
1873 fimc->vid_cap.sd_pads[FIMC_SD_PAD_SINK_FIFO].flags = MEDIA_PAD_FL_SINK;
1874 fimc->vid_cap.sd_pads[FIMC_SD_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
1875 ret = media_entity_init(&sd->entity, FIMC_SD_PADS_NUM,
1876 fimc->vid_cap.sd_pads, 0);
1877 if (ret)
1878 return ret;
1879
1880 sd->entity.ops = &fimc_sd_media_ops;
1881 sd->internal_ops = &fimc_capture_sd_internal_ops;
1882 v4l2_set_subdevdata(sd, fimc);
1883 return 0;
1884}
1885
1886void fimc_unregister_capture_subdev(struct fimc_dev *fimc)
1887{
1888 struct v4l2_subdev *sd = &fimc->vid_cap.subdev;
1889
1890 v4l2_device_unregister_subdev(sd);
1891 media_entity_cleanup(&sd->entity);
1892 v4l2_set_subdevdata(sd, NULL);
1893}
diff --git a/drivers/media/platform/exynos4-is/fimc-core.c b/drivers/media/platform/exynos4-is/fimc-core.c
new file mode 100644
index 000000000000..379a5e9d52a7
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-core.c
@@ -0,0 +1,1311 @@
1/*
2 * Samsung S5P/EXYNOS4 SoC series FIMC (CAMIF) driver
3 *
4 * Copyright (C) 2010-2012 Samsung Electronics Co., Ltd.
5 * Sylwester Nawrocki <s.nawrocki@samsung.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 as published
9 * by the Free Software Foundation, either version 2 of the License,
10 * or (at your option) any later version.
11 */
12
13#include <linux/module.h>
14#include <linux/kernel.h>
15#include <linux/types.h>
16#include <linux/errno.h>
17#include <linux/bug.h>
18#include <linux/interrupt.h>
19#include <linux/device.h>
20#include <linux/platform_device.h>
21#include <linux/pm_runtime.h>
22#include <linux/list.h>
23#include <linux/mfd/syscon.h>
24#include <linux/io.h>
25#include <linux/of.h>
26#include <linux/of_device.h>
27#include <linux/slab.h>
28#include <linux/clk.h>
29#include <media/v4l2-ioctl.h>
30#include <media/videobuf2-core.h>
31#include <media/videobuf2-dma-contig.h>
32
33#include "fimc-core.h"
34#include "fimc-reg.h"
35#include "media-dev.h"
36
37static char *fimc_clocks[MAX_FIMC_CLOCKS] = {
38 "sclk_fimc", "fimc"
39};
40
41static struct fimc_fmt fimc_formats[] = {
42 {
43 .name = "RGB565",
44 .fourcc = V4L2_PIX_FMT_RGB565,
45 .depth = { 16 },
46 .color = FIMC_FMT_RGB565,
47 .memplanes = 1,
48 .colplanes = 1,
49 .flags = FMT_FLAGS_M2M,
50 }, {
51 .name = "BGR666",
52 .fourcc = V4L2_PIX_FMT_BGR666,
53 .depth = { 32 },
54 .color = FIMC_FMT_RGB666,
55 .memplanes = 1,
56 .colplanes = 1,
57 .flags = FMT_FLAGS_M2M,
58 }, {
59 .name = "ARGB8888, 32 bpp",
60 .fourcc = V4L2_PIX_FMT_RGB32,
61 .depth = { 32 },
62 .color = FIMC_FMT_RGB888,
63 .memplanes = 1,
64 .colplanes = 1,
65 .flags = FMT_FLAGS_M2M | FMT_HAS_ALPHA,
66 }, {
67 .name = "ARGB1555",
68 .fourcc = V4L2_PIX_FMT_RGB555,
69 .depth = { 16 },
70 .color = FIMC_FMT_RGB555,
71 .memplanes = 1,
72 .colplanes = 1,
73 .flags = FMT_FLAGS_M2M_OUT | FMT_HAS_ALPHA,
74 }, {
75 .name = "ARGB4444",
76 .fourcc = V4L2_PIX_FMT_RGB444,
77 .depth = { 16 },
78 .color = FIMC_FMT_RGB444,
79 .memplanes = 1,
80 .colplanes = 1,
81 .flags = FMT_FLAGS_M2M_OUT | FMT_HAS_ALPHA,
82 }, {
83 .name = "YUV 4:4:4",
84 .mbus_code = V4L2_MBUS_FMT_YUV10_1X30,
85 .flags = FMT_FLAGS_WRITEBACK,
86 }, {
87 .name = "YUV 4:2:2 packed, YCbYCr",
88 .fourcc = V4L2_PIX_FMT_YUYV,
89 .depth = { 16 },
90 .color = FIMC_FMT_YCBYCR422,
91 .memplanes = 1,
92 .colplanes = 1,
93 .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
94 .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM,
95 }, {
96 .name = "YUV 4:2:2 packed, CbYCrY",
97 .fourcc = V4L2_PIX_FMT_UYVY,
98 .depth = { 16 },
99 .color = FIMC_FMT_CBYCRY422,
100 .memplanes = 1,
101 .colplanes = 1,
102 .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8,
103 .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM,
104 }, {
105 .name = "YUV 4:2:2 packed, CrYCbY",
106 .fourcc = V4L2_PIX_FMT_VYUY,
107 .depth = { 16 },
108 .color = FIMC_FMT_CRYCBY422,
109 .memplanes = 1,
110 .colplanes = 1,
111 .mbus_code = V4L2_MBUS_FMT_VYUY8_2X8,
112 .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM,
113 }, {
114 .name = "YUV 4:2:2 packed, YCrYCb",
115 .fourcc = V4L2_PIX_FMT_YVYU,
116 .depth = { 16 },
117 .color = FIMC_FMT_YCRYCB422,
118 .memplanes = 1,
119 .colplanes = 1,
120 .mbus_code = V4L2_MBUS_FMT_YVYU8_2X8,
121 .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM,
122 }, {
123 .name = "YUV 4:2:2 planar, Y/Cb/Cr",
124 .fourcc = V4L2_PIX_FMT_YUV422P,
125 .depth = { 12 },
126 .color = FIMC_FMT_YCBYCR422,
127 .memplanes = 1,
128 .colplanes = 3,
129 .flags = FMT_FLAGS_M2M,
130 }, {
131 .name = "YUV 4:2:2 planar, Y/CbCr",
132 .fourcc = V4L2_PIX_FMT_NV16,
133 .depth = { 16 },
134 .color = FIMC_FMT_YCBYCR422,
135 .memplanes = 1,
136 .colplanes = 2,
137 .flags = FMT_FLAGS_M2M,
138 }, {
139 .name = "YUV 4:2:2 planar, Y/CrCb",
140 .fourcc = V4L2_PIX_FMT_NV61,
141 .depth = { 16 },
142 .color = FIMC_FMT_YCRYCB422,
143 .memplanes = 1,
144 .colplanes = 2,
145 .flags = FMT_FLAGS_M2M,
146 }, {
147 .name = "YUV 4:2:0 planar, YCbCr",
148 .fourcc = V4L2_PIX_FMT_YUV420,
149 .depth = { 12 },
150 .color = FIMC_FMT_YCBCR420,
151 .memplanes = 1,
152 .colplanes = 3,
153 .flags = FMT_FLAGS_M2M,
154 }, {
155 .name = "YUV 4:2:0 planar, Y/CbCr",
156 .fourcc = V4L2_PIX_FMT_NV12,
157 .depth = { 12 },
158 .color = FIMC_FMT_YCBCR420,
159 .memplanes = 1,
160 .colplanes = 2,
161 .flags = FMT_FLAGS_M2M,
162 }, {
163 .name = "YUV 4:2:0 non-contig. 2p, Y/CbCr",
164 .fourcc = V4L2_PIX_FMT_NV12M,
165 .color = FIMC_FMT_YCBCR420,
166 .depth = { 8, 4 },
167 .memplanes = 2,
168 .colplanes = 2,
169 .flags = FMT_FLAGS_M2M,
170 }, {
171 .name = "YUV 4:2:0 non-contig. 3p, Y/Cb/Cr",
172 .fourcc = V4L2_PIX_FMT_YUV420M,
173 .color = FIMC_FMT_YCBCR420,
174 .depth = { 8, 2, 2 },
175 .memplanes = 3,
176 .colplanes = 3,
177 .flags = FMT_FLAGS_M2M,
178 }, {
179 .name = "YUV 4:2:0 non-contig. 2p, tiled",
180 .fourcc = V4L2_PIX_FMT_NV12MT,
181 .color = FIMC_FMT_YCBCR420,
182 .depth = { 8, 4 },
183 .memplanes = 2,
184 .colplanes = 2,
185 .flags = FMT_FLAGS_M2M,
186 }, {
187 .name = "JPEG encoded data",
188 .fourcc = V4L2_PIX_FMT_JPEG,
189 .color = FIMC_FMT_JPEG,
190 .depth = { 8 },
191 .memplanes = 1,
192 .colplanes = 1,
193 .mbus_code = V4L2_MBUS_FMT_JPEG_1X8,
194 .flags = FMT_FLAGS_CAM | FMT_FLAGS_COMPRESSED,
195 }, {
196 .name = "S5C73MX interleaved UYVY/JPEG",
197 .fourcc = V4L2_PIX_FMT_S5C_UYVY_JPG,
198 .color = FIMC_FMT_YUYV_JPEG,
199 .depth = { 8 },
200 .memplanes = 2,
201 .colplanes = 1,
202 .mdataplanes = 0x2, /* plane 1 holds frame meta data */
203 .mbus_code = V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8,
204 .flags = FMT_FLAGS_CAM | FMT_FLAGS_COMPRESSED,
205 },
206};
207
208struct fimc_fmt *fimc_get_format(unsigned int index)
209{
210 if (index >= ARRAY_SIZE(fimc_formats))
211 return NULL;
212
213 return &fimc_formats[index];
214}
215
216void __fimc_vidioc_querycap(struct device *dev, struct v4l2_capability *cap,
217 unsigned int caps)
218{
219 strlcpy(cap->driver, dev->driver->name, sizeof(cap->driver));
220 strlcpy(cap->card, dev->driver->name, sizeof(cap->card));
221 snprintf(cap->bus_info, sizeof(cap->bus_info),
222 "platform:%s", dev_name(dev));
223 cap->device_caps = caps;
224 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
225}
226
227int fimc_check_scaler_ratio(struct fimc_ctx *ctx, int sw, int sh,
228 int dw, int dh, int rotation)
229{
230 if (rotation == 90 || rotation == 270)
231 swap(dw, dh);
232
233 if (!ctx->scaler.enabled)
234 return (sw == dw && sh == dh) ? 0 : -EINVAL;
235
236 if ((sw >= SCALER_MAX_HRATIO * dw) || (sh >= SCALER_MAX_VRATIO * dh))
237 return -EINVAL;
238
239 return 0;
240}
241
242static int fimc_get_scaler_factor(u32 src, u32 tar, u32 *ratio, u32 *shift)
243{
244 u32 sh = 6;
245
246 if (src >= 64 * tar)
247 return -EINVAL;
248
249 while (sh--) {
250 u32 tmp = 1 << sh;
251 if (src >= tar * tmp) {
252 *shift = sh, *ratio = tmp;
253 return 0;
254 }
255 }
256 *shift = 0, *ratio = 1;
257 return 0;
258}
259
260int fimc_set_scaler_info(struct fimc_ctx *ctx)
261{
262 const struct fimc_variant *variant = ctx->fimc_dev->variant;
263 struct device *dev = &ctx->fimc_dev->pdev->dev;
264 struct fimc_scaler *sc = &ctx->scaler;
265 struct fimc_frame *s_frame = &ctx->s_frame;
266 struct fimc_frame *d_frame = &ctx->d_frame;
267 int tx, ty, sx, sy;
268 int ret;
269
270 if (ctx->rotation == 90 || ctx->rotation == 270) {
271 ty = d_frame->width;
272 tx = d_frame->height;
273 } else {
274 tx = d_frame->width;
275 ty = d_frame->height;
276 }
277 if (tx <= 0 || ty <= 0) {
278 dev_err(dev, "Invalid target size: %dx%d\n", tx, ty);
279 return -EINVAL;
280 }
281
282 sx = s_frame->width;
283 sy = s_frame->height;
284 if (sx <= 0 || sy <= 0) {
285 dev_err(dev, "Invalid source size: %dx%d\n", sx, sy);
286 return -EINVAL;
287 }
288 sc->real_width = sx;
289 sc->real_height = sy;
290
291 ret = fimc_get_scaler_factor(sx, tx, &sc->pre_hratio, &sc->hfactor);
292 if (ret)
293 return ret;
294
295 ret = fimc_get_scaler_factor(sy, ty, &sc->pre_vratio, &sc->vfactor);
296 if (ret)
297 return ret;
298
299 sc->pre_dst_width = sx / sc->pre_hratio;
300 sc->pre_dst_height = sy / sc->pre_vratio;
301
302 if (variant->has_mainscaler_ext) {
303 sc->main_hratio = (sx << 14) / (tx << sc->hfactor);
304 sc->main_vratio = (sy << 14) / (ty << sc->vfactor);
305 } else {
306 sc->main_hratio = (sx << 8) / (tx << sc->hfactor);
307 sc->main_vratio = (sy << 8) / (ty << sc->vfactor);
308
309 }
310
311 sc->scaleup_h = (tx >= sx) ? 1 : 0;
312 sc->scaleup_v = (ty >= sy) ? 1 : 0;
313
314 /* check to see if input and output size/format differ */
315 if (s_frame->fmt->color == d_frame->fmt->color
316 && s_frame->width == d_frame->width
317 && s_frame->height == d_frame->height)
318 sc->copy_mode = 1;
319 else
320 sc->copy_mode = 0;
321
322 return 0;
323}
324
325static irqreturn_t fimc_irq_handler(int irq, void *priv)
326{
327 struct fimc_dev *fimc = priv;
328 struct fimc_ctx *ctx;
329
330 fimc_hw_clear_irq(fimc);
331
332 spin_lock(&fimc->slock);
333
334 if (test_and_clear_bit(ST_M2M_PEND, &fimc->state)) {
335 if (test_and_clear_bit(ST_M2M_SUSPENDING, &fimc->state)) {
336 set_bit(ST_M2M_SUSPENDED, &fimc->state);
337 wake_up(&fimc->irq_queue);
338 goto out;
339 }
340 ctx = v4l2_m2m_get_curr_priv(fimc->m2m.m2m_dev);
341 if (ctx != NULL) {
342 spin_unlock(&fimc->slock);
343 fimc_m2m_job_finish(ctx, VB2_BUF_STATE_DONE);
344
345 if (ctx->state & FIMC_CTX_SHUT) {
346 ctx->state &= ~FIMC_CTX_SHUT;
347 wake_up(&fimc->irq_queue);
348 }
349 return IRQ_HANDLED;
350 }
351 } else if (test_bit(ST_CAPT_PEND, &fimc->state)) {
352 int last_buf = test_bit(ST_CAPT_JPEG, &fimc->state) &&
353 fimc->vid_cap.reqbufs_count == 1;
354 fimc_capture_irq_handler(fimc, !last_buf);
355 }
356out:
357 spin_unlock(&fimc->slock);
358 return IRQ_HANDLED;
359}
360
361/* The color format (colplanes, memplanes) must be already configured. */
362int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb,
363 struct fimc_frame *frame, struct fimc_addr *paddr)
364{
365 int ret = 0;
366 u32 pix_size;
367
368 if (vb == NULL || frame == NULL)
369 return -EINVAL;
370
371 pix_size = frame->width * frame->height;
372
373 dbg("memplanes= %d, colplanes= %d, pix_size= %d",
374 frame->fmt->memplanes, frame->fmt->colplanes, pix_size);
375
376 paddr->y = vb2_dma_contig_plane_dma_addr(vb, 0);
377
378 if (frame->fmt->memplanes == 1) {
379 switch (frame->fmt->colplanes) {
380 case 1:
381 paddr->cb = 0;
382 paddr->cr = 0;
383 break;
384 case 2:
385 /* decompose Y into Y/Cb */
386 paddr->cb = (u32)(paddr->y + pix_size);
387 paddr->cr = 0;
388 break;
389 case 3:
390 paddr->cb = (u32)(paddr->y + pix_size);
391 /* decompose Y into Y/Cb/Cr */
392 if (FIMC_FMT_YCBCR420 == frame->fmt->color)
393 paddr->cr = (u32)(paddr->cb
394 + (pix_size >> 2));
395 else /* 422 */
396 paddr->cr = (u32)(paddr->cb
397 + (pix_size >> 1));
398 break;
399 default:
400 return -EINVAL;
401 }
402 } else if (!frame->fmt->mdataplanes) {
403 if (frame->fmt->memplanes >= 2)
404 paddr->cb = vb2_dma_contig_plane_dma_addr(vb, 1);
405
406 if (frame->fmt->memplanes == 3)
407 paddr->cr = vb2_dma_contig_plane_dma_addr(vb, 2);
408 }
409
410 dbg("PHYS_ADDR: y= 0x%X cb= 0x%X cr= 0x%X ret= %d",
411 paddr->y, paddr->cb, paddr->cr, ret);
412
413 return ret;
414}
415
416/* Set order for 1 and 2 plane YCBCR 4:2:2 formats. */
417void fimc_set_yuv_order(struct fimc_ctx *ctx)
418{
419 /* The one only mode supported in SoC. */
420 ctx->in_order_2p = FIMC_REG_CIOCTRL_ORDER422_2P_LSB_CRCB;
421 ctx->out_order_2p = FIMC_REG_CIOCTRL_ORDER422_2P_LSB_CRCB;
422
423 /* Set order for 1 plane input formats. */
424 switch (ctx->s_frame.fmt->color) {
425 case FIMC_FMT_YCRYCB422:
426 ctx->in_order_1p = FIMC_REG_MSCTRL_ORDER422_YCRYCB;
427 break;
428 case FIMC_FMT_CBYCRY422:
429 ctx->in_order_1p = FIMC_REG_MSCTRL_ORDER422_CBYCRY;
430 break;
431 case FIMC_FMT_CRYCBY422:
432 ctx->in_order_1p = FIMC_REG_MSCTRL_ORDER422_CRYCBY;
433 break;
434 case FIMC_FMT_YCBYCR422:
435 default:
436 ctx->in_order_1p = FIMC_REG_MSCTRL_ORDER422_YCBYCR;
437 break;
438 }
439 dbg("ctx->in_order_1p= %d", ctx->in_order_1p);
440
441 switch (ctx->d_frame.fmt->color) {
442 case FIMC_FMT_YCRYCB422:
443 ctx->out_order_1p = FIMC_REG_CIOCTRL_ORDER422_YCRYCB;
444 break;
445 case FIMC_FMT_CBYCRY422:
446 ctx->out_order_1p = FIMC_REG_CIOCTRL_ORDER422_CBYCRY;
447 break;
448 case FIMC_FMT_CRYCBY422:
449 ctx->out_order_1p = FIMC_REG_CIOCTRL_ORDER422_CRYCBY;
450 break;
451 case FIMC_FMT_YCBYCR422:
452 default:
453 ctx->out_order_1p = FIMC_REG_CIOCTRL_ORDER422_YCBYCR;
454 break;
455 }
456 dbg("ctx->out_order_1p= %d", ctx->out_order_1p);
457}
458
459void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f)
460{
461 bool pix_hoff = ctx->fimc_dev->drv_data->dma_pix_hoff;
462 u32 i, depth = 0;
463
464 for (i = 0; i < f->fmt->colplanes; i++)
465 depth += f->fmt->depth[i];
466
467 f->dma_offset.y_h = f->offs_h;
468 if (!pix_hoff)
469 f->dma_offset.y_h *= (depth >> 3);
470
471 f->dma_offset.y_v = f->offs_v;
472
473 f->dma_offset.cb_h = f->offs_h;
474 f->dma_offset.cb_v = f->offs_v;
475
476 f->dma_offset.cr_h = f->offs_h;
477 f->dma_offset.cr_v = f->offs_v;
478
479 if (!pix_hoff) {
480 if (f->fmt->colplanes == 3) {
481 f->dma_offset.cb_h >>= 1;
482 f->dma_offset.cr_h >>= 1;
483 }
484 if (f->fmt->color == FIMC_FMT_YCBCR420) {
485 f->dma_offset.cb_v >>= 1;
486 f->dma_offset.cr_v >>= 1;
487 }
488 }
489
490 dbg("in_offset: color= %d, y_h= %d, y_v= %d",
491 f->fmt->color, f->dma_offset.y_h, f->dma_offset.y_v);
492}
493
494static int fimc_set_color_effect(struct fimc_ctx *ctx, enum v4l2_colorfx colorfx)
495{
496 struct fimc_effect *effect = &ctx->effect;
497
498 switch (colorfx) {
499 case V4L2_COLORFX_NONE:
500 effect->type = FIMC_REG_CIIMGEFF_FIN_BYPASS;
501 break;
502 case V4L2_COLORFX_BW:
503 effect->type = FIMC_REG_CIIMGEFF_FIN_ARBITRARY;
504 effect->pat_cb = 128;
505 effect->pat_cr = 128;
506 break;
507 case V4L2_COLORFX_SEPIA:
508 effect->type = FIMC_REG_CIIMGEFF_FIN_ARBITRARY;
509 effect->pat_cb = 115;
510 effect->pat_cr = 145;
511 break;
512 case V4L2_COLORFX_NEGATIVE:
513 effect->type = FIMC_REG_CIIMGEFF_FIN_NEGATIVE;
514 break;
515 case V4L2_COLORFX_EMBOSS:
516 effect->type = FIMC_REG_CIIMGEFF_FIN_EMBOSSING;
517 break;
518 case V4L2_COLORFX_ART_FREEZE:
519 effect->type = FIMC_REG_CIIMGEFF_FIN_ARTFREEZE;
520 break;
521 case V4L2_COLORFX_SILHOUETTE:
522 effect->type = FIMC_REG_CIIMGEFF_FIN_SILHOUETTE;
523 break;
524 case V4L2_COLORFX_SET_CBCR:
525 effect->type = FIMC_REG_CIIMGEFF_FIN_ARBITRARY;
526 effect->pat_cb = ctx->ctrls.colorfx_cbcr->val >> 8;
527 effect->pat_cr = ctx->ctrls.colorfx_cbcr->val & 0xff;
528 break;
529 default:
530 return -EINVAL;
531 }
532
533 return 0;
534}
535
536/*
537 * V4L2 controls handling
538 */
539#define ctrl_to_ctx(__ctrl) \
540 container_of((__ctrl)->handler, struct fimc_ctx, ctrls.handler)
541
542static int __fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_ctrl *ctrl)
543{
544 struct fimc_dev *fimc = ctx->fimc_dev;
545 const struct fimc_variant *variant = fimc->variant;
546 int ret = 0;
547
548 if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)
549 return 0;
550
551 switch (ctrl->id) {
552 case V4L2_CID_HFLIP:
553 ctx->hflip = ctrl->val;
554 break;
555
556 case V4L2_CID_VFLIP:
557 ctx->vflip = ctrl->val;
558 break;
559
560 case V4L2_CID_ROTATE:
561 if (fimc_capture_pending(fimc)) {
562 ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width,
563 ctx->s_frame.height, ctx->d_frame.width,
564 ctx->d_frame.height, ctrl->val);
565 if (ret)
566 return -EINVAL;
567 }
568 if ((ctrl->val == 90 || ctrl->val == 270) &&
569 !variant->has_out_rot)
570 return -EINVAL;
571
572 ctx->rotation = ctrl->val;
573 break;
574
575 case V4L2_CID_ALPHA_COMPONENT:
576 ctx->d_frame.alpha = ctrl->val;
577 break;
578
579 case V4L2_CID_COLORFX:
580 ret = fimc_set_color_effect(ctx, ctrl->val);
581 if (ret)
582 return ret;
583 break;
584 }
585
586 ctx->state |= FIMC_PARAMS;
587 set_bit(ST_CAPT_APPLY_CFG, &fimc->state);
588 return 0;
589}
590
591static int fimc_s_ctrl(struct v4l2_ctrl *ctrl)
592{
593 struct fimc_ctx *ctx = ctrl_to_ctx(ctrl);
594 unsigned long flags;
595 int ret;
596
597 spin_lock_irqsave(&ctx->fimc_dev->slock, flags);
598 ret = __fimc_s_ctrl(ctx, ctrl);
599 spin_unlock_irqrestore(&ctx->fimc_dev->slock, flags);
600
601 return ret;
602}
603
604static const struct v4l2_ctrl_ops fimc_ctrl_ops = {
605 .s_ctrl = fimc_s_ctrl,
606};
607
608int fimc_ctrls_create(struct fimc_ctx *ctx)
609{
610 unsigned int max_alpha = fimc_get_alpha_mask(ctx->d_frame.fmt);
611 struct fimc_ctrls *ctrls = &ctx->ctrls;
612 struct v4l2_ctrl_handler *handler = &ctrls->handler;
613
614 if (ctx->ctrls.ready)
615 return 0;
616
617 v4l2_ctrl_handler_init(handler, 6);
618
619 ctrls->rotate = v4l2_ctrl_new_std(handler, &fimc_ctrl_ops,
620 V4L2_CID_ROTATE, 0, 270, 90, 0);
621 ctrls->hflip = v4l2_ctrl_new_std(handler, &fimc_ctrl_ops,
622 V4L2_CID_HFLIP, 0, 1, 1, 0);
623 ctrls->vflip = v4l2_ctrl_new_std(handler, &fimc_ctrl_ops,
624 V4L2_CID_VFLIP, 0, 1, 1, 0);
625
626 if (ctx->fimc_dev->drv_data->alpha_color)
627 ctrls->alpha = v4l2_ctrl_new_std(handler, &fimc_ctrl_ops,
628 V4L2_CID_ALPHA_COMPONENT,
629 0, max_alpha, 1, 0);
630 else
631 ctrls->alpha = NULL;
632
633 ctrls->colorfx = v4l2_ctrl_new_std_menu(handler, &fimc_ctrl_ops,
634 V4L2_CID_COLORFX, V4L2_COLORFX_SET_CBCR,
635 ~0x983f, V4L2_COLORFX_NONE);
636
637 ctrls->colorfx_cbcr = v4l2_ctrl_new_std(handler, &fimc_ctrl_ops,
638 V4L2_CID_COLORFX_CBCR, 0, 0xffff, 1, 0);
639
640 ctx->effect.type = FIMC_REG_CIIMGEFF_FIN_BYPASS;
641
642 if (!handler->error) {
643 v4l2_ctrl_cluster(2, &ctrls->colorfx);
644 ctrls->ready = true;
645 }
646
647 return handler->error;
648}
649
650void fimc_ctrls_delete(struct fimc_ctx *ctx)
651{
652 struct fimc_ctrls *ctrls = &ctx->ctrls;
653
654 if (ctrls->ready) {
655 v4l2_ctrl_handler_free(&ctrls->handler);
656 ctrls->ready = false;
657 ctrls->alpha = NULL;
658 }
659}
660
661void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active)
662{
663 unsigned int has_alpha = ctx->d_frame.fmt->flags & FMT_HAS_ALPHA;
664 struct fimc_ctrls *ctrls = &ctx->ctrls;
665
666 if (!ctrls->ready)
667 return;
668
669 mutex_lock(ctrls->handler.lock);
670 v4l2_ctrl_activate(ctrls->rotate, active);
671 v4l2_ctrl_activate(ctrls->hflip, active);
672 v4l2_ctrl_activate(ctrls->vflip, active);
673 v4l2_ctrl_activate(ctrls->colorfx, active);
674 if (ctrls->alpha)
675 v4l2_ctrl_activate(ctrls->alpha, active && has_alpha);
676
677 if (active) {
678 fimc_set_color_effect(ctx, ctrls->colorfx->cur.val);
679 ctx->rotation = ctrls->rotate->val;
680 ctx->hflip = ctrls->hflip->val;
681 ctx->vflip = ctrls->vflip->val;
682 } else {
683 ctx->effect.type = FIMC_REG_CIIMGEFF_FIN_BYPASS;
684 ctx->rotation = 0;
685 ctx->hflip = 0;
686 ctx->vflip = 0;
687 }
688 mutex_unlock(ctrls->handler.lock);
689}
690
691/* Update maximum value of the alpha color control */
692void fimc_alpha_ctrl_update(struct fimc_ctx *ctx)
693{
694 struct fimc_dev *fimc = ctx->fimc_dev;
695 struct v4l2_ctrl *ctrl = ctx->ctrls.alpha;
696
697 if (ctrl == NULL || !fimc->drv_data->alpha_color)
698 return;
699
700 v4l2_ctrl_lock(ctrl);
701 ctrl->maximum = fimc_get_alpha_mask(ctx->d_frame.fmt);
702
703 if (ctrl->cur.val > ctrl->maximum)
704 ctrl->cur.val = ctrl->maximum;
705
706 v4l2_ctrl_unlock(ctrl);
707}
708
709void __fimc_get_format(struct fimc_frame *frame, struct v4l2_format *f)
710{
711 struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp;
712 int i;
713
714 pixm->width = frame->o_width;
715 pixm->height = frame->o_height;
716 pixm->field = V4L2_FIELD_NONE;
717 pixm->pixelformat = frame->fmt->fourcc;
718 pixm->colorspace = V4L2_COLORSPACE_JPEG;
719 pixm->num_planes = frame->fmt->memplanes;
720
721 for (i = 0; i < pixm->num_planes; ++i) {
722 pixm->plane_fmt[i].bytesperline = frame->bytesperline[i];
723 pixm->plane_fmt[i].sizeimage = frame->payload[i];
724 }
725}
726
727/**
728 * fimc_adjust_mplane_format - adjust bytesperline/sizeimage for each plane
729 * @fmt: fimc pixel format description (input)
730 * @width: requested pixel width
731 * @height: requested pixel height
732 * @pix: multi-plane format to adjust
733 */
734void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height,
735 struct v4l2_pix_format_mplane *pix)
736{
737 u32 bytesperline = 0;
738 int i;
739
740 pix->colorspace = V4L2_COLORSPACE_JPEG;
741 pix->field = V4L2_FIELD_NONE;
742 pix->num_planes = fmt->memplanes;
743 pix->pixelformat = fmt->fourcc;
744 pix->height = height;
745 pix->width = width;
746
747 for (i = 0; i < pix->num_planes; ++i) {
748 struct v4l2_plane_pix_format *plane_fmt = &pix->plane_fmt[i];
749 u32 bpl = plane_fmt->bytesperline;
750
751 if (fmt->colplanes > 1 && (bpl == 0 || bpl < pix->width))
752 bpl = pix->width; /* Planar */
753
754 if (fmt->colplanes == 1 && /* Packed */
755 (bpl == 0 || ((bpl * 8) / fmt->depth[i]) < pix->width))
756 bpl = (pix->width * fmt->depth[0]) / 8;
757 /*
758 * Currently bytesperline for each plane is same, except
759 * V4L2_PIX_FMT_YUV420M format. This calculation may need
760 * to be changed when other multi-planar formats are added
761 * to the fimc_formats[] array.
762 */
763 if (i == 0)
764 bytesperline = bpl;
765 else if (i == 1 && fmt->memplanes == 3)
766 bytesperline /= 2;
767
768 plane_fmt->bytesperline = bytesperline;
769 plane_fmt->sizeimage = max((pix->width * pix->height *
770 fmt->depth[i]) / 8, plane_fmt->sizeimage);
771 }
772}
773
774/**
775 * fimc_find_format - lookup fimc color format by fourcc or media bus format
776 * @pixelformat: fourcc to match, ignored if null
777 * @mbus_code: media bus code to match, ignored if null
778 * @mask: the color flags to match
779 * @index: offset in the fimc_formats array, ignored if negative
780 */
781struct fimc_fmt *fimc_find_format(const u32 *pixelformat, const u32 *mbus_code,
782 unsigned int mask, int index)
783{
784 struct fimc_fmt *fmt, *def_fmt = NULL;
785 unsigned int i;
786 int id = 0;
787
788 if (index >= (int)ARRAY_SIZE(fimc_formats))
789 return NULL;
790
791 for (i = 0; i < ARRAY_SIZE(fimc_formats); ++i) {
792 fmt = &fimc_formats[i];
793 if (!(fmt->flags & mask))
794 continue;
795 if (pixelformat && fmt->fourcc == *pixelformat)
796 return fmt;
797 if (mbus_code && fmt->mbus_code == *mbus_code)
798 return fmt;
799 if (index == id)
800 def_fmt = fmt;
801 id++;
802 }
803 return def_fmt;
804}
805
806static void fimc_clk_put(struct fimc_dev *fimc)
807{
808 int i;
809 for (i = 0; i < MAX_FIMC_CLOCKS; i++) {
810 if (IS_ERR(fimc->clock[i]))
811 continue;
812 clk_unprepare(fimc->clock[i]);
813 clk_put(fimc->clock[i]);
814 fimc->clock[i] = ERR_PTR(-EINVAL);
815 }
816}
817
818static int fimc_clk_get(struct fimc_dev *fimc)
819{
820 int i, ret;
821
822 for (i = 0; i < MAX_FIMC_CLOCKS; i++)
823 fimc->clock[i] = ERR_PTR(-EINVAL);
824
825 for (i = 0; i < MAX_FIMC_CLOCKS; i++) {
826 fimc->clock[i] = clk_get(&fimc->pdev->dev, fimc_clocks[i]);
827 if (IS_ERR(fimc->clock[i])) {
828 ret = PTR_ERR(fimc->clock[i]);
829 goto err;
830 }
831 ret = clk_prepare(fimc->clock[i]);
832 if (ret < 0) {
833 clk_put(fimc->clock[i]);
834 fimc->clock[i] = ERR_PTR(-EINVAL);
835 goto err;
836 }
837 }
838 return 0;
839err:
840 fimc_clk_put(fimc);
841 dev_err(&fimc->pdev->dev, "failed to get clock: %s\n",
842 fimc_clocks[i]);
843 return -ENXIO;
844}
845
846static int fimc_m2m_suspend(struct fimc_dev *fimc)
847{
848 unsigned long flags;
849 int timeout;
850
851 spin_lock_irqsave(&fimc->slock, flags);
852 if (!fimc_m2m_pending(fimc)) {
853 spin_unlock_irqrestore(&fimc->slock, flags);
854 return 0;
855 }
856 clear_bit(ST_M2M_SUSPENDED, &fimc->state);
857 set_bit(ST_M2M_SUSPENDING, &fimc->state);
858 spin_unlock_irqrestore(&fimc->slock, flags);
859
860 timeout = wait_event_timeout(fimc->irq_queue,
861 test_bit(ST_M2M_SUSPENDED, &fimc->state),
862 FIMC_SHUTDOWN_TIMEOUT);
863
864 clear_bit(ST_M2M_SUSPENDING, &fimc->state);
865 return timeout == 0 ? -EAGAIN : 0;
866}
867
868static int fimc_m2m_resume(struct fimc_dev *fimc)
869{
870 struct fimc_ctx *ctx;
871 unsigned long flags;
872
873 spin_lock_irqsave(&fimc->slock, flags);
874 /* Clear for full H/W setup in first run after resume */
875 ctx = fimc->m2m.ctx;
876 fimc->m2m.ctx = NULL;
877 spin_unlock_irqrestore(&fimc->slock, flags);
878
879 if (test_and_clear_bit(ST_M2M_SUSPENDED, &fimc->state))
880 fimc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
881
882 return 0;
883}
884
885static const struct of_device_id fimc_of_match[];
886
887static int fimc_parse_dt(struct fimc_dev *fimc, u32 *clk_freq)
888{
889 struct device *dev = &fimc->pdev->dev;
890 struct device_node *node = dev->of_node;
891 const struct of_device_id *of_id;
892 struct fimc_variant *v;
893 struct fimc_pix_limit *lim;
894 u32 args[FIMC_PIX_LIMITS_MAX];
895 int ret;
896
897 if (of_property_read_bool(node, "samsung,lcd-wb"))
898 return -ENODEV;
899
900 v = devm_kzalloc(dev, sizeof(*v) + sizeof(*lim), GFP_KERNEL);
901 if (!v)
902 return -ENOMEM;
903
904 of_id = of_match_node(fimc_of_match, node);
905 if (!of_id)
906 return -EINVAL;
907 fimc->drv_data = of_id->data;
908 ret = of_property_read_u32_array(node, "samsung,pix-limits",
909 args, FIMC_PIX_LIMITS_MAX);
910 if (ret < 0)
911 return ret;
912
913 lim = (struct fimc_pix_limit *)&v[1];
914
915 lim->scaler_en_w = args[0];
916 lim->scaler_dis_w = args[1];
917 lim->out_rot_en_w = args[2];
918 lim->out_rot_dis_w = args[3];
919 v->pix_limit = lim;
920
921 ret = of_property_read_u32_array(node, "samsung,min-pix-sizes",
922 args, 2);
923 v->min_inp_pixsize = ret ? FIMC_DEF_MIN_SIZE : args[0];
924 v->min_out_pixsize = ret ? FIMC_DEF_MIN_SIZE : args[1];
925 ret = of_property_read_u32_array(node, "samsung,min-pix-alignment",
926 args, 2);
927 v->min_vsize_align = ret ? FIMC_DEF_HEIGHT_ALIGN : args[0];
928 v->hor_offs_align = ret ? FIMC_DEF_HOR_OFFS_ALIGN : args[1];
929
930 ret = of_property_read_u32(node, "samsung,rotators", &args[1]);
931 v->has_inp_rot = ret ? 1 : args[1] & 0x01;
932 v->has_out_rot = ret ? 1 : args[1] & 0x10;
933 v->has_mainscaler_ext = of_property_read_bool(node,
934 "samsung,mainscaler-ext");
935
936 v->has_isp_wb = of_property_read_bool(node, "samsung,isp-wb");
937 v->has_cam_if = of_property_read_bool(node, "samsung,cam-if");
938 of_property_read_u32(node, "clock-frequency", clk_freq);
939 fimc->id = of_alias_get_id(node, "fimc");
940
941 fimc->variant = v;
942 return 0;
943}
944
945static int fimc_probe(struct platform_device *pdev)
946{
947 struct device *dev = &pdev->dev;
948 u32 lclk_freq = 0;
949 struct fimc_dev *fimc;
950 struct resource *res;
951 int ret = 0;
952
953 fimc = devm_kzalloc(dev, sizeof(*fimc), GFP_KERNEL);
954 if (!fimc)
955 return -ENOMEM;
956
957 fimc->pdev = pdev;
958
959 if (dev->of_node) {
960 ret = fimc_parse_dt(fimc, &lclk_freq);
961 if (ret < 0)
962 return ret;
963 } else {
964 fimc->drv_data = fimc_get_drvdata(pdev);
965 fimc->id = pdev->id;
966 }
967 if (!fimc->drv_data || fimc->id >= fimc->drv_data->num_entities ||
968 fimc->id < 0) {
969 dev_err(dev, "Invalid driver data or device id (%d)\n",
970 fimc->id);
971 return -EINVAL;
972 }
973 if (!dev->of_node)
974 fimc->variant = fimc->drv_data->variant[fimc->id];
975
976 init_waitqueue_head(&fimc->irq_queue);
977 spin_lock_init(&fimc->slock);
978 mutex_init(&fimc->lock);
979
980 fimc->sysreg = fimc_get_sysreg_regmap(dev->of_node);
981 if (IS_ERR(fimc->sysreg))
982 return PTR_ERR(fimc->sysreg);
983
984 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
985 fimc->regs = devm_ioremap_resource(dev, res);
986 if (IS_ERR(fimc->regs))
987 return PTR_ERR(fimc->regs);
988
989 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
990 if (res == NULL) {
991 dev_err(dev, "Failed to get IRQ resource\n");
992 return -ENXIO;
993 }
994
995 ret = fimc_clk_get(fimc);
996 if (ret)
997 return ret;
998
999 if (lclk_freq == 0)
1000 lclk_freq = fimc->drv_data->lclk_frequency;
1001
1002 ret = clk_set_rate(fimc->clock[CLK_BUS], lclk_freq);
1003 if (ret < 0)
1004 return ret;
1005
1006 ret = clk_enable(fimc->clock[CLK_BUS]);
1007 if (ret < 0)
1008 return ret;
1009
1010 ret = devm_request_irq(dev, res->start, fimc_irq_handler,
1011 0, dev_name(dev), fimc);
1012 if (ret) {
1013 dev_err(dev, "failed to install irq (%d)\n", ret);
1014 goto err_clk;
1015 }
1016
1017 ret = fimc_initialize_capture_subdev(fimc);
1018 if (ret)
1019 goto err_clk;
1020
1021 platform_set_drvdata(pdev, fimc);
1022 pm_runtime_enable(dev);
1023 ret = pm_runtime_get_sync(dev);
1024 if (ret < 0)
1025 goto err_sd;
1026 /* Initialize contiguous memory allocator */
1027 fimc->alloc_ctx = vb2_dma_contig_init_ctx(dev);
1028 if (IS_ERR(fimc->alloc_ctx)) {
1029 ret = PTR_ERR(fimc->alloc_ctx);
1030 goto err_pm;
1031 }
1032
1033 dev_dbg(dev, "FIMC.%d registered successfully\n", fimc->id);
1034
1035 pm_runtime_put(dev);
1036 return 0;
1037err_pm:
1038 pm_runtime_put(dev);
1039err_sd:
1040 fimc_unregister_capture_subdev(fimc);
1041err_clk:
1042 clk_disable(fimc->clock[CLK_BUS]);
1043 fimc_clk_put(fimc);
1044 return ret;
1045}
1046
1047static int fimc_runtime_resume(struct device *dev)
1048{
1049 struct fimc_dev *fimc = dev_get_drvdata(dev);
1050
1051 dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state);
1052
1053 /* Enable clocks and perform basic initalization */
1054 clk_enable(fimc->clock[CLK_GATE]);
1055 fimc_hw_reset(fimc);
1056
1057 /* Resume the capture or mem-to-mem device */
1058 if (fimc_capture_busy(fimc))
1059 return fimc_capture_resume(fimc);
1060
1061 return fimc_m2m_resume(fimc);
1062}
1063
1064static int fimc_runtime_suspend(struct device *dev)
1065{
1066 struct fimc_dev *fimc = dev_get_drvdata(dev);
1067 int ret = 0;
1068
1069 if (fimc_capture_busy(fimc))
1070 ret = fimc_capture_suspend(fimc);
1071 else
1072 ret = fimc_m2m_suspend(fimc);
1073 if (!ret)
1074 clk_disable(fimc->clock[CLK_GATE]);
1075
1076 dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state);
1077 return ret;
1078}
1079
1080#ifdef CONFIG_PM_SLEEP
1081static int fimc_resume(struct device *dev)
1082{
1083 struct fimc_dev *fimc = dev_get_drvdata(dev);
1084 unsigned long flags;
1085
1086 dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state);
1087
1088 /* Do not resume if the device was idle before system suspend */
1089 spin_lock_irqsave(&fimc->slock, flags);
1090 if (!test_and_clear_bit(ST_LPM, &fimc->state) ||
1091 (!fimc_m2m_active(fimc) && !fimc_capture_busy(fimc))) {
1092 spin_unlock_irqrestore(&fimc->slock, flags);
1093 return 0;
1094 }
1095 fimc_hw_reset(fimc);
1096 spin_unlock_irqrestore(&fimc->slock, flags);
1097
1098 if (fimc_capture_busy(fimc))
1099 return fimc_capture_resume(fimc);
1100
1101 return fimc_m2m_resume(fimc);
1102}
1103
1104static int fimc_suspend(struct device *dev)
1105{
1106 struct fimc_dev *fimc = dev_get_drvdata(dev);
1107
1108 dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state);
1109
1110 if (test_and_set_bit(ST_LPM, &fimc->state))
1111 return 0;
1112 if (fimc_capture_busy(fimc))
1113 return fimc_capture_suspend(fimc);
1114
1115 return fimc_m2m_suspend(fimc);
1116}
1117#endif /* CONFIG_PM_SLEEP */
1118
1119static int fimc_remove(struct platform_device *pdev)
1120{
1121 struct fimc_dev *fimc = platform_get_drvdata(pdev);
1122
1123 pm_runtime_disable(&pdev->dev);
1124 pm_runtime_set_suspended(&pdev->dev);
1125
1126 fimc_unregister_capture_subdev(fimc);
1127 vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx);
1128
1129 clk_disable(fimc->clock[CLK_BUS]);
1130 fimc_clk_put(fimc);
1131
1132 dev_info(&pdev->dev, "driver unloaded\n");
1133 return 0;
1134}
1135
1136/* Image pixel limits, similar across several FIMC HW revisions. */
1137static const struct fimc_pix_limit s5p_pix_limit[4] = {
1138 [0] = {
1139 .scaler_en_w = 3264,
1140 .scaler_dis_w = 8192,
1141 .out_rot_en_w = 1920,
1142 .out_rot_dis_w = 4224,
1143 },
1144 [1] = {
1145 .scaler_en_w = 4224,
1146 .scaler_dis_w = 8192,
1147 .out_rot_en_w = 1920,
1148 .out_rot_dis_w = 4224,
1149 },
1150 [2] = {
1151 .scaler_en_w = 1920,
1152 .scaler_dis_w = 8192,
1153 .out_rot_en_w = 1280,
1154 .out_rot_dis_w = 1920,
1155 },
1156};
1157
1158static const struct fimc_variant fimc0_variant_s5p = {
1159 .has_inp_rot = 1,
1160 .has_out_rot = 1,
1161 .has_cam_if = 1,
1162 .min_inp_pixsize = 16,
1163 .min_out_pixsize = 16,
1164 .hor_offs_align = 8,
1165 .min_vsize_align = 16,
1166 .pix_limit = &s5p_pix_limit[0],
1167};
1168
1169static const struct fimc_variant fimc2_variant_s5p = {
1170 .has_cam_if = 1,
1171 .min_inp_pixsize = 16,
1172 .min_out_pixsize = 16,
1173 .hor_offs_align = 8,
1174 .min_vsize_align = 16,
1175 .pix_limit = &s5p_pix_limit[1],
1176};
1177
1178static const struct fimc_variant fimc0_variant_s5pv210 = {
1179 .has_inp_rot = 1,
1180 .has_out_rot = 1,
1181 .has_cam_if = 1,
1182 .min_inp_pixsize = 16,
1183 .min_out_pixsize = 16,
1184 .hor_offs_align = 8,
1185 .min_vsize_align = 16,
1186 .pix_limit = &s5p_pix_limit[1],
1187};
1188
1189static const struct fimc_variant fimc1_variant_s5pv210 = {
1190 .has_inp_rot = 1,
1191 .has_out_rot = 1,
1192 .has_cam_if = 1,
1193 .has_mainscaler_ext = 1,
1194 .min_inp_pixsize = 16,
1195 .min_out_pixsize = 16,
1196 .hor_offs_align = 1,
1197 .min_vsize_align = 1,
1198 .pix_limit = &s5p_pix_limit[2],
1199};
1200
1201static const struct fimc_variant fimc2_variant_s5pv210 = {
1202 .has_cam_if = 1,
1203 .min_inp_pixsize = 16,
1204 .min_out_pixsize = 16,
1205 .hor_offs_align = 8,
1206 .min_vsize_align = 16,
1207 .pix_limit = &s5p_pix_limit[2],
1208};
1209
1210/* S5PC100 */
1211static const struct fimc_drvdata fimc_drvdata_s5p = {
1212 .variant = {
1213 [0] = &fimc0_variant_s5p,
1214 [1] = &fimc0_variant_s5p,
1215 [2] = &fimc2_variant_s5p,
1216 },
1217 .num_entities = 3,
1218 .lclk_frequency = 133000000UL,
1219 .out_buf_count = 4,
1220};
1221
1222/* S5PV210, S5PC110 */
1223static const struct fimc_drvdata fimc_drvdata_s5pv210 = {
1224 .variant = {
1225 [0] = &fimc0_variant_s5pv210,
1226 [1] = &fimc1_variant_s5pv210,
1227 [2] = &fimc2_variant_s5pv210,
1228 },
1229 .num_entities = 3,
1230 .lclk_frequency = 166000000UL,
1231 .out_buf_count = 4,
1232 .dma_pix_hoff = 1,
1233};
1234
1235/* EXYNOS4210, S5PV310, S5PC210 */
1236static const struct fimc_drvdata fimc_drvdata_exynos4210 = {
1237 .num_entities = 4,
1238 .lclk_frequency = 166000000UL,
1239 .dma_pix_hoff = 1,
1240 .cistatus2 = 1,
1241 .alpha_color = 1,
1242 .out_buf_count = 32,
1243};
1244
1245/* EXYNOS4212, EXYNOS4412 */
1246static const struct fimc_drvdata fimc_drvdata_exynos4x12 = {
1247 .num_entities = 4,
1248 .lclk_frequency = 166000000UL,
1249 .dma_pix_hoff = 1,
1250 .cistatus2 = 1,
1251 .alpha_color = 1,
1252 .out_buf_count = 32,
1253};
1254
1255static const struct platform_device_id fimc_driver_ids[] = {
1256 {
1257 .name = "s5p-fimc",
1258 .driver_data = (unsigned long)&fimc_drvdata_s5p,
1259 }, {
1260 .name = "s5pv210-fimc",
1261 .driver_data = (unsigned long)&fimc_drvdata_s5pv210,
1262 }, {
1263 .name = "exynos4-fimc",
1264 .driver_data = (unsigned long)&fimc_drvdata_exynos4210,
1265 }, {
1266 .name = "exynos4x12-fimc",
1267 .driver_data = (unsigned long)&fimc_drvdata_exynos4x12,
1268 },
1269 { },
1270};
1271
1272static const struct of_device_id fimc_of_match[] = {
1273 {
1274 .compatible = "samsung,s5pv210-fimc",
1275 .data = &fimc_drvdata_s5pv210,
1276 }, {
1277 .compatible = "samsung,exynos4210-fimc",
1278 .data = &fimc_drvdata_exynos4210,
1279 }, {
1280 .compatible = "samsung,exynos4212-fimc",
1281 .data = &fimc_drvdata_exynos4x12,
1282 },
1283 { /* sentinel */ },
1284};
1285
1286static const struct dev_pm_ops fimc_pm_ops = {
1287 SET_SYSTEM_SLEEP_PM_OPS(fimc_suspend, fimc_resume)
1288 SET_RUNTIME_PM_OPS(fimc_runtime_suspend, fimc_runtime_resume, NULL)
1289};
1290
1291static struct platform_driver fimc_driver = {
1292 .probe = fimc_probe,
1293 .remove = fimc_remove,
1294 .id_table = fimc_driver_ids,
1295 .driver = {
1296 .of_match_table = fimc_of_match,
1297 .name = FIMC_DRIVER_NAME,
1298 .owner = THIS_MODULE,
1299 .pm = &fimc_pm_ops,
1300 }
1301};
1302
1303int __init fimc_register_driver(void)
1304{
1305 return platform_driver_register(&fimc_driver);
1306}
1307
1308void __exit fimc_unregister_driver(void)
1309{
1310 platform_driver_unregister(&fimc_driver);
1311}
diff --git a/drivers/media/platform/exynos4-is/fimc-core.h b/drivers/media/platform/exynos4-is/fimc-core.h
new file mode 100644
index 000000000000..539a3f71c16a
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-core.h
@@ -0,0 +1,731 @@
1/*
2 * Copyright (C) 2010 - 2012 Samsung Electronics Co., Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef FIMC_CORE_H_
10#define FIMC_CORE_H_
11
12/*#define DEBUG*/
13
14#include <linux/platform_device.h>
15#include <linux/regmap.h>
16#include <linux/sched.h>
17#include <linux/spinlock.h>
18#include <linux/mfd/syscon.h>
19#include <linux/types.h>
20#include <linux/videodev2.h>
21#include <linux/io.h>
22#include <linux/sizes.h>
23
24#include <media/media-entity.h>
25#include <media/videobuf2-core.h>
26#include <media/v4l2-ctrls.h>
27#include <media/v4l2-device.h>
28#include <media/v4l2-mem2mem.h>
29#include <media/v4l2-mediabus.h>
30#include <media/s5p_fimc.h>
31
32#define dbg(fmt, args...) \
33 pr_debug("%s:%d: " fmt "\n", __func__, __LINE__, ##args)
34
35/* Time to wait for next frame VSYNC interrupt while stopping operation. */
36#define FIMC_SHUTDOWN_TIMEOUT ((100*HZ)/1000)
37#define MAX_FIMC_CLOCKS 2
38#define FIMC_DRIVER_NAME "exynos4-fimc"
39#define FIMC_MAX_DEVS 4
40#define FIMC_MAX_OUT_BUFS 4
41#define SCALER_MAX_HRATIO 64
42#define SCALER_MAX_VRATIO 64
43#define DMA_MIN_SIZE 8
44#define FIMC_CAMIF_MAX_HEIGHT 0x2000
45#define FIMC_MAX_JPEG_BUF_SIZE (10 * SZ_1M)
46#define FIMC_MAX_PLANES 3
47#define FIMC_PIX_LIMITS_MAX 4
48#define FIMC_DEF_MIN_SIZE 16
49#define FIMC_DEF_HEIGHT_ALIGN 2
50#define FIMC_DEF_HOR_OFFS_ALIGN 1
51
52/* indices to the clocks array */
53enum {
54 CLK_BUS,
55 CLK_GATE,
56};
57
58enum fimc_dev_flags {
59 ST_LPM,
60 /* m2m node */
61 ST_M2M_RUN,
62 ST_M2M_PEND,
63 ST_M2M_SUSPENDING,
64 ST_M2M_SUSPENDED,
65 /* capture node */
66 ST_CAPT_PEND,
67 ST_CAPT_RUN,
68 ST_CAPT_STREAM,
69 ST_CAPT_ISP_STREAM,
70 ST_CAPT_SUSPENDED,
71 ST_CAPT_SHUT,
72 ST_CAPT_BUSY,
73 ST_CAPT_APPLY_CFG,
74 ST_CAPT_JPEG,
75};
76
77#define fimc_m2m_active(dev) test_bit(ST_M2M_RUN, &(dev)->state)
78#define fimc_m2m_pending(dev) test_bit(ST_M2M_PEND, &(dev)->state)
79
80#define fimc_capture_running(dev) test_bit(ST_CAPT_RUN, &(dev)->state)
81#define fimc_capture_pending(dev) test_bit(ST_CAPT_PEND, &(dev)->state)
82#define fimc_capture_busy(dev) test_bit(ST_CAPT_BUSY, &(dev)->state)
83
84enum fimc_datapath {
85 FIMC_IO_NONE,
86 FIMC_IO_CAMERA,
87 FIMC_IO_DMA,
88 FIMC_IO_LCDFIFO,
89 FIMC_IO_WRITEBACK,
90 FIMC_IO_ISP,
91};
92
93enum fimc_color_fmt {
94 FIMC_FMT_RGB444 = 0x10,
95 FIMC_FMT_RGB555,
96 FIMC_FMT_RGB565,
97 FIMC_FMT_RGB666,
98 FIMC_FMT_RGB888,
99 FIMC_FMT_RGB30_LOCAL,
100 FIMC_FMT_YCBCR420 = 0x20,
101 FIMC_FMT_YCBYCR422,
102 FIMC_FMT_YCRYCB422,
103 FIMC_FMT_CBYCRY422,
104 FIMC_FMT_CRYCBY422,
105 FIMC_FMT_YCBCR444_LOCAL,
106 FIMC_FMT_RAW8 = 0x40,
107 FIMC_FMT_RAW10,
108 FIMC_FMT_RAW12,
109 FIMC_FMT_JPEG = 0x80,
110 FIMC_FMT_YUYV_JPEG = 0x100,
111};
112
113#define fimc_fmt_is_user_defined(x) (!!((x) & 0x180))
114#define fimc_fmt_is_rgb(x) (!!((x) & 0x10))
115
116#define IS_M2M(__strt) ((__strt) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE || \
117 __strt == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
118
119/* The hardware context state. */
120#define FIMC_PARAMS (1 << 0)
121#define FIMC_COMPOSE (1 << 1)
122#define FIMC_CTX_M2M (1 << 16)
123#define FIMC_CTX_CAP (1 << 17)
124#define FIMC_CTX_SHUT (1 << 18)
125
126/* Image conversion flags */
127#define FIMC_IN_DMA_ACCESS_TILED (1 << 0)
128#define FIMC_IN_DMA_ACCESS_LINEAR (0 << 0)
129#define FIMC_OUT_DMA_ACCESS_TILED (1 << 1)
130#define FIMC_OUT_DMA_ACCESS_LINEAR (0 << 1)
131#define FIMC_SCAN_MODE_PROGRESSIVE (0 << 2)
132#define FIMC_SCAN_MODE_INTERLACED (1 << 2)
133/*
134 * YCbCr data dynamic range for RGB-YUV color conversion.
135 * Y/Cb/Cr: (0 ~ 255) */
136#define FIMC_COLOR_RANGE_WIDE (0 << 3)
137/* Y (16 ~ 235), Cb/Cr (16 ~ 240) */
138#define FIMC_COLOR_RANGE_NARROW (1 << 3)
139
140/**
141 * struct fimc_dma_offset - pixel offset information for DMA
142 * @y_h: y value horizontal offset
143 * @y_v: y value vertical offset
144 * @cb_h: cb value horizontal offset
145 * @cb_v: cb value vertical offset
146 * @cr_h: cr value horizontal offset
147 * @cr_v: cr value vertical offset
148 */
149struct fimc_dma_offset {
150 int y_h;
151 int y_v;
152 int cb_h;
153 int cb_v;
154 int cr_h;
155 int cr_v;
156};
157
158/**
159 * struct fimc_effect - color effect information
160 * @type: effect type
161 * @pat_cb: cr value when type is "arbitrary"
162 * @pat_cr: cr value when type is "arbitrary"
163 */
164struct fimc_effect {
165 u32 type;
166 u8 pat_cb;
167 u8 pat_cr;
168};
169
170/**
171 * struct fimc_scaler - the configuration data for FIMC inetrnal scaler
172 * @scaleup_h: flag indicating scaling up horizontally
173 * @scaleup_v: flag indicating scaling up vertically
174 * @copy_mode: flag indicating transparent DMA transfer (no scaling
175 * and color format conversion)
176 * @enabled: flag indicating if the scaler is used
177 * @hfactor: horizontal shift factor
178 * @vfactor: vertical shift factor
179 * @pre_hratio: horizontal ratio of the prescaler
180 * @pre_vratio: vertical ratio of the prescaler
181 * @pre_dst_width: the prescaler's destination width
182 * @pre_dst_height: the prescaler's destination height
183 * @main_hratio: the main scaler's horizontal ratio
184 * @main_vratio: the main scaler's vertical ratio
185 * @real_width: source pixel (width - offset)
186 * @real_height: source pixel (height - offset)
187 */
188struct fimc_scaler {
189 unsigned int scaleup_h:1;
190 unsigned int scaleup_v:1;
191 unsigned int copy_mode:1;
192 unsigned int enabled:1;
193 u32 hfactor;
194 u32 vfactor;
195 u32 pre_hratio;
196 u32 pre_vratio;
197 u32 pre_dst_width;
198 u32 pre_dst_height;
199 u32 main_hratio;
200 u32 main_vratio;
201 u32 real_width;
202 u32 real_height;
203};
204
205/**
206 * struct fimc_addr - the FIMC physical address set for DMA
207 * @y: luminance plane physical address
208 * @cb: Cb plane physical address
209 * @cr: Cr plane physical address
210 */
211struct fimc_addr {
212 u32 y;
213 u32 cb;
214 u32 cr;
215};
216
217/**
218 * struct fimc_vid_buffer - the driver's video buffer
219 * @vb: v4l videobuf buffer
220 * @list: linked list structure for buffer queue
221 * @paddr: precalculated physical address set
222 * @index: buffer index for the output DMA engine
223 */
224struct fimc_vid_buffer {
225 struct vb2_buffer vb;
226 struct list_head list;
227 struct fimc_addr paddr;
228 int index;
229};
230
231/**
232 * struct fimc_frame - source/target frame properties
233 * @f_width: image full width (virtual screen size)
234 * @f_height: image full height (virtual screen size)
235 * @o_width: original image width as set by S_FMT
236 * @o_height: original image height as set by S_FMT
237 * @offs_h: image horizontal pixel offset
238 * @offs_v: image vertical pixel offset
239 * @width: image pixel width
240 * @height: image pixel weight
241 * @payload: image size in bytes (w x h x bpp)
242 * @bytesperline: bytesperline value for each plane
243 * @paddr: image frame buffer physical addresses
244 * @dma_offset: DMA offset in bytes
245 * @fmt: fimc color format pointer
246 */
247struct fimc_frame {
248 u32 f_width;
249 u32 f_height;
250 u32 o_width;
251 u32 o_height;
252 u32 offs_h;
253 u32 offs_v;
254 u32 width;
255 u32 height;
256 unsigned int payload[VIDEO_MAX_PLANES];
257 unsigned int bytesperline[VIDEO_MAX_PLANES];
258 struct fimc_addr paddr;
259 struct fimc_dma_offset dma_offset;
260 struct fimc_fmt *fmt;
261 u8 alpha;
262};
263
264/**
265 * struct fimc_m2m_device - v4l2 memory-to-memory device data
266 * @vfd: the video device node for v4l2 m2m mode
267 * @m2m_dev: v4l2 memory-to-memory device data
268 * @ctx: hardware context data
269 * @refcnt: the reference counter
270 */
271struct fimc_m2m_device {
272 struct video_device vfd;
273 struct v4l2_m2m_dev *m2m_dev;
274 struct fimc_ctx *ctx;
275 int refcnt;
276};
277
278#define FIMC_SD_PAD_SINK_CAM 0
279#define FIMC_SD_PAD_SINK_FIFO 1
280#define FIMC_SD_PAD_SOURCE 2
281#define FIMC_SD_PADS_NUM 3
282
283/**
284 * struct fimc_vid_cap - camera capture device information
285 * @ctx: hardware context data
286 * @vfd: video device node for camera capture mode
287 * @subdev: subdev exposing the FIMC processing block
288 * @vd_pad: fimc video capture node pad
289 * @sd_pads: fimc video processing block pads
290 * @ci_fmt: image format at the FIMC camera input (and the scaler output)
291 * @wb_fmt: image format at the FIMC ISP Writeback input
292 * @source_config: external image source related configuration structure
293 * @pending_buf_q: the pending buffer queue head
294 * @active_buf_q: the queue head of buffers scheduled in hardware
295 * @vbq: the capture am video buffer queue
296 * @active_buf_cnt: number of video buffers scheduled in hardware
297 * @buf_index: index for managing the output DMA buffers
298 * @frame_count: the frame counter for statistics
299 * @reqbufs_count: the number of buffers requested in REQBUFS ioctl
300 * @input_index: input (camera sensor) index
301 * @refcnt: driver's private reference counter
302 * @input: capture input type, grp_id of the attached subdev
303 * @user_subdev_api: true if subdevs are not configured by the host driver
304 */
305struct fimc_vid_cap {
306 struct fimc_ctx *ctx;
307 struct vb2_alloc_ctx *alloc_ctx;
308 struct video_device vfd;
309 struct v4l2_subdev subdev;
310 struct media_pad vd_pad;
311 struct media_pad sd_pads[FIMC_SD_PADS_NUM];
312 struct v4l2_mbus_framefmt ci_fmt;
313 struct v4l2_mbus_framefmt wb_fmt;
314 struct fimc_source_info source_config;
315 struct list_head pending_buf_q;
316 struct list_head active_buf_q;
317 struct vb2_queue vbq;
318 int active_buf_cnt;
319 int buf_index;
320 unsigned int frame_count;
321 unsigned int reqbufs_count;
322 bool streaming;
323 int input_index;
324 int refcnt;
325 u32 input;
326 bool user_subdev_api;
327};
328
329/**
330 * struct fimc_pix_limit - image pixel size limits in various IP configurations
331 *
332 * @scaler_en_w: max input pixel width when the scaler is enabled
333 * @scaler_dis_w: max input pixel width when the scaler is disabled
334 * @in_rot_en_h: max input width with the input rotator is on
335 * @in_rot_dis_w: max input width with the input rotator is off
336 * @out_rot_en_w: max output width with the output rotator on
337 * @out_rot_dis_w: max output width with the output rotator off
338 */
339struct fimc_pix_limit {
340 u16 scaler_en_w;
341 u16 scaler_dis_w;
342 u16 in_rot_en_h;
343 u16 in_rot_dis_w;
344 u16 out_rot_en_w;
345 u16 out_rot_dis_w;
346};
347
348/**
349 * struct fimc_variant - FIMC device variant information
350 * @has_inp_rot: set if has input rotator
351 * @has_out_rot: set if has output rotator
352 * @has_mainscaler_ext: 1 if extended mainscaler ratios in CIEXTEN register
353 * are present in this IP revision
354 * @has_cam_if: set if this instance has a camera input interface
355 * @has_isp_wb: set if this instance has ISP writeback input
356 * @pix_limit: pixel size constraints for the scaler
357 * @min_inp_pixsize: minimum input pixel size
358 * @min_out_pixsize: minimum output pixel size
359 * @hor_offs_align: horizontal pixel offset aligment
360 * @min_vsize_align: minimum vertical pixel size alignment
361 */
362struct fimc_variant {
363 unsigned int has_inp_rot:1;
364 unsigned int has_out_rot:1;
365 unsigned int has_mainscaler_ext:1;
366 unsigned int has_cam_if:1;
367 unsigned int has_isp_wb:1;
368 const struct fimc_pix_limit *pix_limit;
369 u16 min_inp_pixsize;
370 u16 min_out_pixsize;
371 u16 hor_offs_align;
372 u16 min_vsize_align;
373};
374
375/**
376 * struct fimc_drvdata - per device type driver data
377 * @variant: variant information for this device
378 * @num_entities: number of fimc instances available in a SoC
379 * @lclk_frequency: local bus clock frequency
380 * @cistatus2: 1 if the FIMC IPs have CISTATUS2 register
381 * @dma_pix_hoff: the horizontal DMA offset unit: 1 - pixels, 0 - bytes
382 * @alpha_color: 1 if alpha color component is supported
383 * @out_buf_count: maximum number of output DMA buffers supported
384 */
385struct fimc_drvdata {
386 const struct fimc_variant *variant[FIMC_MAX_DEVS];
387 int num_entities;
388 unsigned long lclk_frequency;
389 /* Fields common to all FIMC IP instances */
390 u8 cistatus2;
391 u8 dma_pix_hoff;
392 u8 alpha_color;
393 u8 out_buf_count;
394};
395
396#define fimc_get_drvdata(_pdev) \
397 ((struct fimc_drvdata *) platform_get_device_id(_pdev)->driver_data)
398
399struct fimc_ctx;
400
401/**
402 * struct fimc_dev - abstraction for FIMC entity
403 * @slock: the spinlock protecting this data structure
404 * @lock: the mutex protecting this data structure
405 * @pdev: pointer to the FIMC platform device
406 * @pdata: pointer to the device platform data
407 * @sysreg: pointer to the SYSREG regmap
408 * @variant: the IP variant information
409 * @id: FIMC device index (0..FIMC_MAX_DEVS)
410 * @clock: clocks required for FIMC operation
411 * @regs: the mapped hardware registers
412 * @irq_queue: interrupt handler waitqueue
413 * @v4l2_dev: root v4l2_device
414 * @m2m: memory-to-memory V4L2 device information
415 * @vid_cap: camera capture device information
416 * @state: flags used to synchronize m2m and capture mode operation
417 * @alloc_ctx: videobuf2 memory allocator context
418 * @pipeline: fimc video capture pipeline data structure
419 */
420struct fimc_dev {
421 spinlock_t slock;
422 struct mutex lock;
423 struct platform_device *pdev;
424 struct s5p_platform_fimc *pdata;
425 struct regmap *sysreg;
426 const struct fimc_variant *variant;
427 const struct fimc_drvdata *drv_data;
428 int id;
429 struct clk *clock[MAX_FIMC_CLOCKS];
430 void __iomem *regs;
431 wait_queue_head_t irq_queue;
432 struct v4l2_device *v4l2_dev;
433 struct fimc_m2m_device m2m;
434 struct fimc_vid_cap vid_cap;
435 unsigned long state;
436 struct vb2_alloc_ctx *alloc_ctx;
437 struct fimc_pipeline pipeline;
438 const struct fimc_pipeline_ops *pipeline_ops;
439};
440
441/**
442 * struct fimc_ctrls - v4l2 controls structure
443 * @handler: the control handler
444 * @colorfx: image effect control
445 * @colorfx_cbcr: Cb/Cr coefficients control
446 * @rotate: image rotation control
447 * @hflip: horizontal flip control
448 * @vflip: vertical flip control
449 * @alpha: RGB alpha control
450 * @ready: true if @handler is initialized
451 */
452struct fimc_ctrls {
453 struct v4l2_ctrl_handler handler;
454 struct {
455 struct v4l2_ctrl *colorfx;
456 struct v4l2_ctrl *colorfx_cbcr;
457 };
458 struct v4l2_ctrl *rotate;
459 struct v4l2_ctrl *hflip;
460 struct v4l2_ctrl *vflip;
461 struct v4l2_ctrl *alpha;
462 bool ready;
463};
464
465/**
466 * fimc_ctx - the device context data
467 * @s_frame: source frame properties
468 * @d_frame: destination frame properties
469 * @out_order_1p: output 1-plane YCBCR order
470 * @out_order_2p: output 2-plane YCBCR order
471 * @in_order_1p input 1-plane YCBCR order
472 * @in_order_2p: input 2-plane YCBCR order
473 * @in_path: input mode (DMA or camera)
474 * @out_path: output mode (DMA or FIFO)
475 * @scaler: image scaler properties
476 * @effect: image effect
477 * @rotation: image clockwise rotation in degrees
478 * @hflip: indicates image horizontal flip if set
479 * @vflip: indicates image vertical flip if set
480 * @flags: additional flags for image conversion
481 * @state: flags to keep track of user configuration
482 * @fimc_dev: the FIMC device this context applies to
483 * @m2m_ctx: memory-to-memory device context
484 * @fh: v4l2 file handle
485 * @ctrls: v4l2 controls structure
486 */
487struct fimc_ctx {
488 struct fimc_frame s_frame;
489 struct fimc_frame d_frame;
490 u32 out_order_1p;
491 u32 out_order_2p;
492 u32 in_order_1p;
493 u32 in_order_2p;
494 enum fimc_datapath in_path;
495 enum fimc_datapath out_path;
496 struct fimc_scaler scaler;
497 struct fimc_effect effect;
498 int rotation;
499 unsigned int hflip:1;
500 unsigned int vflip:1;
501 u32 flags;
502 u32 state;
503 struct fimc_dev *fimc_dev;
504 struct v4l2_m2m_ctx *m2m_ctx;
505 struct v4l2_fh fh;
506 struct fimc_ctrls ctrls;
507};
508
509#define fh_to_ctx(__fh) container_of(__fh, struct fimc_ctx, fh)
510
511static inline void set_frame_bounds(struct fimc_frame *f, u32 width, u32 height)
512{
513 f->o_width = width;
514 f->o_height = height;
515 f->f_width = width;
516 f->f_height = height;
517}
518
519static inline void set_frame_crop(struct fimc_frame *f,
520 u32 left, u32 top, u32 width, u32 height)
521{
522 f->offs_h = left;
523 f->offs_v = top;
524 f->width = width;
525 f->height = height;
526}
527
528static inline u32 fimc_get_format_depth(struct fimc_fmt *ff)
529{
530 u32 i, depth = 0;
531
532 if (ff != NULL)
533 for (i = 0; i < ff->colplanes; i++)
534 depth += ff->depth[i];
535 return depth;
536}
537
538static inline bool fimc_capture_active(struct fimc_dev *fimc)
539{
540 unsigned long flags;
541 bool ret;
542
543 spin_lock_irqsave(&fimc->slock, flags);
544 ret = !!(fimc->state & (1 << ST_CAPT_RUN) ||
545 fimc->state & (1 << ST_CAPT_PEND));
546 spin_unlock_irqrestore(&fimc->slock, flags);
547 return ret;
548}
549
550static inline void fimc_ctx_state_set(u32 state, struct fimc_ctx *ctx)
551{
552 unsigned long flags;
553
554 spin_lock_irqsave(&ctx->fimc_dev->slock, flags);
555 ctx->state |= state;
556 spin_unlock_irqrestore(&ctx->fimc_dev->slock, flags);
557}
558
559static inline bool fimc_ctx_state_is_set(u32 mask, struct fimc_ctx *ctx)
560{
561 unsigned long flags;
562 bool ret;
563
564 spin_lock_irqsave(&ctx->fimc_dev->slock, flags);
565 ret = (ctx->state & mask) == mask;
566 spin_unlock_irqrestore(&ctx->fimc_dev->slock, flags);
567 return ret;
568}
569
570static inline int tiled_fmt(struct fimc_fmt *fmt)
571{
572 return fmt->fourcc == V4L2_PIX_FMT_NV12MT;
573}
574
575static inline bool fimc_jpeg_fourcc(u32 pixelformat)
576{
577 return (pixelformat == V4L2_PIX_FMT_JPEG ||
578 pixelformat == V4L2_PIX_FMT_S5C_UYVY_JPG);
579}
580
581static inline bool fimc_user_defined_mbus_fmt(u32 code)
582{
583 return (code == V4L2_MBUS_FMT_JPEG_1X8 ||
584 code == V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8);
585}
586
587/* Return the alpha component bit mask */
588static inline int fimc_get_alpha_mask(struct fimc_fmt *fmt)
589{
590 switch (fmt->color) {
591 case FIMC_FMT_RGB444: return 0x0f;
592 case FIMC_FMT_RGB555: return 0x01;
593 case FIMC_FMT_RGB888: return 0xff;
594 default: return 0;
595 };
596}
597
598static inline struct fimc_frame *ctx_get_frame(struct fimc_ctx *ctx,
599 enum v4l2_buf_type type)
600{
601 struct fimc_frame *frame;
602
603 if (V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == type) {
604 if (fimc_ctx_state_is_set(FIMC_CTX_M2M, ctx))
605 frame = &ctx->s_frame;
606 else
607 return ERR_PTR(-EINVAL);
608 } else if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == type) {
609 frame = &ctx->d_frame;
610 } else {
611 v4l2_err(ctx->fimc_dev->v4l2_dev,
612 "Wrong buffer/video queue type (%d)\n", type);
613 return ERR_PTR(-EINVAL);
614 }
615
616 return frame;
617}
618
619/* -----------------------------------------------------*/
620/* fimc-core.c */
621int fimc_vidioc_enum_fmt_mplane(struct file *file, void *priv,
622 struct v4l2_fmtdesc *f);
623void __fimc_vidioc_querycap(struct device *dev, struct v4l2_capability *cap,
624 unsigned int caps);
625int fimc_ctrls_create(struct fimc_ctx *ctx);
626void fimc_ctrls_delete(struct fimc_ctx *ctx);
627void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active);
628void fimc_alpha_ctrl_update(struct fimc_ctx *ctx);
629void __fimc_get_format(struct fimc_frame *frame, struct v4l2_format *f);
630void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height,
631 struct v4l2_pix_format_mplane *pix);
632struct fimc_fmt *fimc_find_format(const u32 *pixelformat, const u32 *mbus_code,
633 unsigned int mask, int index);
634struct fimc_fmt *fimc_get_format(unsigned int index);
635
636int fimc_check_scaler_ratio(struct fimc_ctx *ctx, int sw, int sh,
637 int dw, int dh, int rotation);
638int fimc_set_scaler_info(struct fimc_ctx *ctx);
639int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags);
640int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb,
641 struct fimc_frame *frame, struct fimc_addr *paddr);
642void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f);
643void fimc_set_yuv_order(struct fimc_ctx *ctx);
644void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf);
645
646int fimc_register_m2m_device(struct fimc_dev *fimc,
647 struct v4l2_device *v4l2_dev);
648void fimc_unregister_m2m_device(struct fimc_dev *fimc);
649int fimc_register_driver(void);
650void fimc_unregister_driver(void);
651
652#ifdef CONFIG_MFD_SYSCON
653static inline struct regmap * fimc_get_sysreg_regmap(struct device_node *node)
654{
655 return syscon_regmap_lookup_by_phandle(node, "samsung,sysreg");
656}
657#else
658#define fimc_get_sysreg_regmap(node) (NULL)
659#endif
660
661/* -----------------------------------------------------*/
662/* fimc-m2m.c */
663void fimc_m2m_job_finish(struct fimc_ctx *ctx, int vb_state);
664
665/* -----------------------------------------------------*/
666/* fimc-capture.c */
667int fimc_initialize_capture_subdev(struct fimc_dev *fimc);
668void fimc_unregister_capture_subdev(struct fimc_dev *fimc);
669int fimc_capture_ctrls_create(struct fimc_dev *fimc);
670void fimc_sensor_notify(struct v4l2_subdev *sd, unsigned int notification,
671 void *arg);
672int fimc_capture_suspend(struct fimc_dev *fimc);
673int fimc_capture_resume(struct fimc_dev *fimc);
674
675/*
676 * Buffer list manipulation functions. Must be called with fimc.slock held.
677 */
678
679/**
680 * fimc_active_queue_add - add buffer to the capture active buffers queue
681 * @buf: buffer to add to the active buffers list
682 */
683static inline void fimc_active_queue_add(struct fimc_vid_cap *vid_cap,
684 struct fimc_vid_buffer *buf)
685{
686 list_add_tail(&buf->list, &vid_cap->active_buf_q);
687 vid_cap->active_buf_cnt++;
688}
689
690/**
691 * fimc_active_queue_pop - pop buffer from the capture active buffers queue
692 *
693 * The caller must assure the active_buf_q list is not empty.
694 */
695static inline struct fimc_vid_buffer *fimc_active_queue_pop(
696 struct fimc_vid_cap *vid_cap)
697{
698 struct fimc_vid_buffer *buf;
699 buf = list_entry(vid_cap->active_buf_q.next,
700 struct fimc_vid_buffer, list);
701 list_del(&buf->list);
702 vid_cap->active_buf_cnt--;
703 return buf;
704}
705
706/**
707 * fimc_pending_queue_add - add buffer to the capture pending buffers queue
708 * @buf: buffer to add to the pending buffers list
709 */
710static inline void fimc_pending_queue_add(struct fimc_vid_cap *vid_cap,
711 struct fimc_vid_buffer *buf)
712{
713 list_add_tail(&buf->list, &vid_cap->pending_buf_q);
714}
715
716/**
717 * fimc_pending_queue_pop - pop buffer from the capture pending buffers queue
718 *
719 * The caller must assure the pending_buf_q list is not empty.
720 */
721static inline struct fimc_vid_buffer *fimc_pending_queue_pop(
722 struct fimc_vid_cap *vid_cap)
723{
724 struct fimc_vid_buffer *buf;
725 buf = list_entry(vid_cap->pending_buf_q.next,
726 struct fimc_vid_buffer, list);
727 list_del(&buf->list);
728 return buf;
729}
730
731#endif /* FIMC_CORE_H_ */
diff --git a/drivers/media/platform/exynos4-is/fimc-is-command.h b/drivers/media/platform/exynos4-is/fimc-is-command.h
new file mode 100644
index 000000000000..0d1f52e394b1
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-is-command.h
@@ -0,0 +1,137 @@
1/*
2 * Samsung Exynos4x12 FIMC-IS (Imaging Subsystem) driver
3 *
4 * FIMC-IS command set definitions
5 *
6 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
7 *
8 * Authors: Younghwan Joo <yhwan.joo@samsung.com>
9 * Sylwester Nawrocki <s.nawrocki@samsung.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15
16#ifndef FIMC_IS_CMD_H_
17#define FIMC_IS_CMD_H_
18
19#define FIMC_IS_COMMAND_VER 110 /* FIMC-IS command set version 1.10 */
20
21/* Enumeration of commands beetween the FIMC-IS and the host processor. */
22
23/* HOST to FIMC-IS */
24#define HIC_PREVIEW_STILL 0x0001
25#define HIC_PREVIEW_VIDEO 0x0002
26#define HIC_CAPTURE_STILL 0x0003
27#define HIC_CAPTURE_VIDEO 0x0004
28#define HIC_STREAM_ON 0x0005
29#define HIC_STREAM_OFF 0x0006
30#define HIC_SET_PARAMETER 0x0007
31#define HIC_GET_PARAMETER 0x0008
32#define HIC_SET_TUNE 0x0009
33#define HIC_GET_STATUS 0x000b
34/* Sensor part */
35#define HIC_OPEN_SENSOR 0x000c
36#define HIC_CLOSE_SENSOR 0x000d
37#define HIC_SIMMIAN_INIT 0x000e
38#define HIC_SIMMIAN_WRITE 0x000f
39#define HIC_SIMMIAN_READ 0x0010
40#define HIC_POWER_DOWN 0x0011
41#define HIC_GET_SET_FILE_ADDR 0x0012
42#define HIC_LOAD_SET_FILE 0x0013
43#define HIC_MSG_CONFIG 0x0014
44#define HIC_MSG_TEST 0x0015
45/* FIMC-IS to HOST */
46#define IHC_GET_SENSOR_NUM 0x1000
47#define IHC_SET_SHOT_MARK 0x1001
48/* parameter1: frame number */
49/* parameter2: confidence level (smile 0~100) */
50/* parameter3: confidence level (blink 0~100) */
51#define IHC_SET_FACE_MARK 0x1002
52/* parameter1: coordinate count */
53/* parameter2: coordinate buffer address */
54#define IHC_FRAME_DONE 0x1003
55/* parameter1: frame start number */
56/* parameter2: frame count */
57#define IHC_AA_DONE 0x1004
58#define IHC_NOT_READY 0x1005
59
60#define IH_REPLY_DONE 0x2000
61#define IH_REPLY_NOT_DONE 0x2001
62
63enum fimc_is_scenario {
64 IS_SC_PREVIEW_STILL,
65 IS_SC_PREVIEW_VIDEO,
66 IS_SC_CAPTURE_STILL,
67 IS_SC_CAPTURE_VIDEO,
68 IS_SC_MAX
69};
70
71enum fimc_is_sub_scenario {
72 IS_SC_SUB_DEFAULT,
73 IS_SC_SUB_PS_VTCALL,
74 IS_SC_SUB_CS_VTCALL,
75 IS_SC_SUB_PV_VTCALL,
76 IS_SC_SUB_CV_VTCALL,
77};
78
79struct is_common_regs {
80 u32 hicmd;
81 u32 hic_sensorid;
82 u32 hic_param[4];
83 u32 reserved1[4];
84
85 u32 ihcmd;
86 u32 ihc_sensorid;
87 u32 ihc_param[4];
88 u32 reserved2[4];
89
90 u32 isp_sensor_id;
91 u32 isp_param[2];
92 u32 reserved3[1];
93
94 u32 scc_sensor_id;
95 u32 scc_param[2];
96 u32 reserved4[1];
97
98 u32 dnr_sensor_id;
99 u32 dnr_param[2];
100 u32 reserved5[1];
101
102 u32 scp_sensor_id;
103 u32 scp_param[2];
104 u32 reserved6[29];
105} __packed;
106
107struct is_mcuctl_reg {
108 u32 mcuctl;
109 u32 bboar;
110
111 u32 intgr0;
112 u32 intcr0;
113 u32 intmr0;
114 u32 intsr0;
115 u32 intmsr0;
116
117 u32 intgr1;
118 u32 intcr1;
119 u32 intmr1;
120 u32 intsr1;
121 u32 intmsr1;
122
123 u32 intcr2;
124 u32 intmr2;
125 u32 intsr2;
126 u32 intmsr2;
127
128 u32 gpoctrl;
129 u32 cpoenctlr;
130 u32 gpictlr;
131
132 u32 reserved[0xd];
133
134 struct is_common_regs common;
135} __packed;
136
137#endif /* FIMC_IS_CMD_H_ */
diff --git a/drivers/media/platform/exynos4-is/fimc-is-errno.c b/drivers/media/platform/exynos4-is/fimc-is-errno.c
new file mode 100644
index 000000000000..e8519e151c1a
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-is-errno.c
@@ -0,0 +1,272 @@
1/*
2 * Samsung Exynos4 SoC series FIMC-IS slave interface driver
3 *
4 * Error log interface functions
5 *
6 * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd.
7 *
8 * Authors: Younghwan Joo <yhwan.joo@samsung.com>
9 * Sylwester Nawrocki <s.nawrocki@samsung.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15
16#include "fimc-is-errno.h"
17
18const char * const fimc_is_param_strerr(unsigned int error)
19{
20 switch (error) {
21 case ERROR_COMMON_CMD:
22 return "ERROR_COMMON_CMD: Invalid Command";
23 case ERROR_COMMON_PARAMETER:
24 return "ERROR_COMMON_PARAMETER: Invalid Parameter";
25 case ERROR_COMMON_SETFILE_LOAD:
26 return "ERROR_COMMON_SETFILE_LOAD: Illegal Setfile Loading";
27 case ERROR_COMMON_SETFILE_ADJUST:
28 return "ERROR_COMMON_SETFILE_ADJUST: Setfile isn't adjusted";
29 case ERROR_COMMON_SETFILE_INDEX:
30 return "ERROR_COMMON_SETFILE_INDEX: Invalid setfile index";
31 case ERROR_COMMON_INPUT_PATH:
32 return "ERROR_COMMON_INPUT_PATH: Input path can be changed in ready state";
33 case ERROR_COMMON_INPUT_INIT:
34 return "ERROR_COMMON_INPUT_INIT: IP can not start if input path is not set";
35 case ERROR_COMMON_OUTPUT_PATH:
36 return "ERROR_COMMON_OUTPUT_PATH: Output path can be changed in ready state (stop)";
37 case ERROR_COMMON_OUTPUT_INIT:
38 return "ERROR_COMMON_OUTPUT_INIT: IP can not start if output path is not set";
39 case ERROR_CONTROL_BYPASS:
40 return "ERROR_CONTROL_BYPASS";
41 case ERROR_OTF_INPUT_FORMAT:
42 return "ERROR_OTF_INPUT_FORMAT: Invalid format (DRC: YUV444, FD: YUV444, 422, 420)";
43 case ERROR_OTF_INPUT_WIDTH:
44 return "ERROR_OTF_INPUT_WIDTH: Invalid width (DRC: 128~8192, FD: 32~8190)";
45 case ERROR_OTF_INPUT_HEIGHT:
46 return "ERROR_OTF_INPUT_HEIGHT: Invalid bit-width (DRC: 8~12bits, FD: 8bit)";
47 case ERROR_OTF_INPUT_BIT_WIDTH:
48 return "ERROR_OTF_INPUT_BIT_WIDTH: Invalid bit-width (DRC: 8~12bits, FD: 8bit)";
49 case ERROR_DMA_INPUT_WIDTH:
50 return "ERROR_DMA_INPUT_WIDTH: Invalid width (DRC: 128~8192, FD: 32~8190)";
51 case ERROR_DMA_INPUT_HEIGHT:
52 return "ERROR_DMA_INPUT_HEIGHT: Invalid height (DRC: 64~8192, FD: 16~8190)";
53 case ERROR_DMA_INPUT_FORMAT:
54 return "ERROR_DMA_INPUT_FORMAT: Invalid format (DRC: YUV444 or YUV422, FD: YUV444,422,420)";
55 case ERROR_DMA_INPUT_BIT_WIDTH:
56 return "ERROR_DMA_INPUT_BIT_WIDTH: Invalid bit-width (DRC: 8~12bits, FD: 8bit)";
57 case ERROR_DMA_INPUT_ORDER:
58 return "ERROR_DMA_INPUT_ORDER: Invalid order(DRC: YYCbCr,YCbYCr,FD:NO,YYCbCr,YCbYCr,CbCr,CrCb)";
59 case ERROR_DMA_INPUT_PLANE:
60 return "ERROR_DMA_INPUT_PLANE: Invalid palne (DRC: 3, FD: 1, 2, 3)";
61 case ERROR_OTF_OUTPUT_WIDTH:
62 return "ERROR_OTF_OUTPUT_WIDTH: Invalid width (DRC: 128~8192)";
63 case ERROR_OTF_OUTPUT_HEIGHT:
64 return "ERROR_OTF_OUTPUT_HEIGHT: Invalid height (DRC: 64~8192)";
65 case ERROR_OTF_OUTPUT_FORMAT:
66 return "ERROR_OTF_OUTPUT_FORMAT: Invalid format (DRC: YUV444)";
67 case ERROR_OTF_OUTPUT_BIT_WIDTH:
68 return "ERROR_OTF_OUTPUT_BIT_WIDTH: Invalid bit-width (DRC: 8~12bits, FD: 8bit)";
69 case ERROR_DMA_OUTPUT_WIDTH:
70 return "ERROR_DMA_OUTPUT_WIDTH";
71 case ERROR_DMA_OUTPUT_HEIGHT:
72 return "ERROR_DMA_OUTPUT_HEIGHT";
73 case ERROR_DMA_OUTPUT_FORMAT:
74 return "ERROR_DMA_OUTPUT_FORMAT";
75 case ERROR_DMA_OUTPUT_BIT_WIDTH:
76 return "ERROR_DMA_OUTPUT_BIT_WIDTH";
77 case ERROR_DMA_OUTPUT_PLANE:
78 return "ERROR_DMA_OUTPUT_PLANE";
79 case ERROR_DMA_OUTPUT_ORDER:
80 return "ERROR_DMA_OUTPUT_ORDER";
81
82 /* Sensor Error(100~199) */
83 case ERROR_SENSOR_I2C_FAIL:
84 return "ERROR_SENSOR_I2C_FAIL";
85 case ERROR_SENSOR_INVALID_FRAMERATE:
86 return "ERROR_SENSOR_INVALID_FRAMERATE";
87 case ERROR_SENSOR_INVALID_EXPOSURETIME:
88 return "ERROR_SENSOR_INVALID_EXPOSURETIME";
89 case ERROR_SENSOR_INVALID_SIZE:
90 return "ERROR_SENSOR_INVALID_SIZE";
91 case ERROR_SENSOR_INVALID_SETTING:
92 return "ERROR_SENSOR_INVALID_SETTING";
93 case ERROR_SENSOR_ACTURATOR_INIT_FAIL:
94 return "ERROR_SENSOR_ACTURATOR_INIT_FAIL";
95 case ERROR_SENSOR_INVALID_AF_POS:
96 return "ERROR_SENSOR_INVALID_AF_POS";
97 case ERROR_SENSOR_UNSUPPORT_FUNC:
98 return "ERROR_SENSOR_UNSUPPORT_FUNC";
99 case ERROR_SENSOR_UNSUPPORT_PERI:
100 return "ERROR_SENSOR_UNSUPPORT_PERI";
101 case ERROR_SENSOR_UNSUPPORT_AF:
102 return "ERROR_SENSOR_UNSUPPORT_AF";
103
104 /* ISP Error (200~299) */
105 case ERROR_ISP_AF_BUSY:
106 return "ERROR_ISP_AF_BUSY";
107 case ERROR_ISP_AF_INVALID_COMMAND:
108 return "ERROR_ISP_AF_INVALID_COMMAND";
109 case ERROR_ISP_AF_INVALID_MODE:
110 return "ERROR_ISP_AF_INVALID_MODE";
111
112 /* DRC Error (300~399) */
113 /* FD Error (400~499) */
114 case ERROR_FD_CONFIG_MAX_NUMBER_STATE:
115 return "ERROR_FD_CONFIG_MAX_NUMBER_STATE";
116 case ERROR_FD_CONFIG_MAX_NUMBER_INVALID:
117 return "ERROR_FD_CONFIG_MAX_NUMBER_INVALID";
118 case ERROR_FD_CONFIG_YAW_ANGLE_STATE:
119 return "ERROR_FD_CONFIG_YAW_ANGLE_STATE";
120 case ERROR_FD_CONFIG_YAW_ANGLE_INVALID:
121 return "ERROR_FD_CONFIG_YAW_ANGLE_INVALID\n";
122 case ERROR_FD_CONFIG_ROLL_ANGLE_STATE:
123 return "ERROR_FD_CONFIG_ROLL_ANGLE_STATE";
124 case ERROR_FD_CONFIG_ROLL_ANGLE_INVALID:
125 return "ERROR_FD_CONFIG_ROLL_ANGLE_INVALID";
126 case ERROR_FD_CONFIG_SMILE_MODE_INVALID:
127 return "ERROR_FD_CONFIG_SMILE_MODE_INVALID";
128 case ERROR_FD_CONFIG_BLINK_MODE_INVALID:
129 return "ERROR_FD_CONFIG_BLINK_MODE_INVALID";
130 case ERROR_FD_CONFIG_EYES_DETECT_INVALID:
131 return "ERROR_FD_CONFIG_EYES_DETECT_INVALID";
132 case ERROR_FD_CONFIG_MOUTH_DETECT_INVALID:
133 return "ERROR_FD_CONFIG_MOUTH_DETECT_INVALID";
134 case ERROR_FD_CONFIG_ORIENTATION_STATE:
135 return "ERROR_FD_CONFIG_ORIENTATION_STATE";
136 case ERROR_FD_CONFIG_ORIENTATION_INVALID:
137 return "ERROR_FD_CONFIG_ORIENTATION_INVALID";
138 case ERROR_FD_CONFIG_ORIENTATION_VALUE_INVALID:
139 return "ERROR_FD_CONFIG_ORIENTATION_VALUE_INVALID";
140 case ERROR_FD_RESULT:
141 return "ERROR_FD_RESULT";
142 case ERROR_FD_MODE:
143 return "ERROR_FD_MODE";
144 default:
145 return "Unknown";
146 }
147}
148
149const char * const fimc_is_strerr(unsigned int error)
150{
151 error &= ~IS_ERROR_TIME_OUT_FLAG;
152
153 switch (error) {
154 /* General */
155 case IS_ERROR_INVALID_COMMAND:
156 return "IS_ERROR_INVALID_COMMAND";
157 case IS_ERROR_REQUEST_FAIL:
158 return "IS_ERROR_REQUEST_FAIL";
159 case IS_ERROR_INVALID_SCENARIO:
160 return "IS_ERROR_INVALID_SCENARIO";
161 case IS_ERROR_INVALID_SENSORID:
162 return "IS_ERROR_INVALID_SENSORID";
163 case IS_ERROR_INVALID_MODE_CHANGE:
164 return "IS_ERROR_INVALID_MODE_CHANGE";
165 case IS_ERROR_INVALID_MAGIC_NUMBER:
166 return "IS_ERROR_INVALID_MAGIC_NUMBER";
167 case IS_ERROR_INVALID_SETFILE_HDR:
168 return "IS_ERROR_INVALID_SETFILE_HDR";
169 case IS_ERROR_BUSY:
170 return "IS_ERROR_BUSY";
171 case IS_ERROR_SET_PARAMETER:
172 return "IS_ERROR_SET_PARAMETER";
173 case IS_ERROR_INVALID_PATH:
174 return "IS_ERROR_INVALID_PATH";
175 case IS_ERROR_OPEN_SENSOR_FAIL:
176 return "IS_ERROR_OPEN_SENSOR_FAIL";
177 case IS_ERROR_ENTRY_MSG_THREAD_DOWN:
178 return "IS_ERROR_ENTRY_MSG_THREAD_DOWN";
179 case IS_ERROR_ISP_FRAME_END_NOT_DONE:
180 return "IS_ERROR_ISP_FRAME_END_NOT_DONE";
181 case IS_ERROR_DRC_FRAME_END_NOT_DONE:
182 return "IS_ERROR_DRC_FRAME_END_NOT_DONE";
183 case IS_ERROR_SCALERC_FRAME_END_NOT_DONE:
184 return "IS_ERROR_SCALERC_FRAME_END_NOT_DONE";
185 case IS_ERROR_ODC_FRAME_END_NOT_DONE:
186 return "IS_ERROR_ODC_FRAME_END_NOT_DONE";
187 case IS_ERROR_DIS_FRAME_END_NOT_DONE:
188 return "IS_ERROR_DIS_FRAME_END_NOT_DONE";
189 case IS_ERROR_TDNR_FRAME_END_NOT_DONE:
190 return "IS_ERROR_TDNR_FRAME_END_NOT_DONE";
191 case IS_ERROR_SCALERP_FRAME_END_NOT_DONE:
192 return "IS_ERROR_SCALERP_FRAME_END_NOT_DONE";
193 case IS_ERROR_WAIT_STREAM_OFF_NOT_DONE:
194 return "IS_ERROR_WAIT_STREAM_OFF_NOT_DONE";
195 case IS_ERROR_NO_MSG_IS_RECEIVED:
196 return "IS_ERROR_NO_MSG_IS_RECEIVED";
197 case IS_ERROR_SENSOR_MSG_FAIL:
198 return "IS_ERROR_SENSOR_MSG_FAIL";
199 case IS_ERROR_ISP_MSG_FAIL:
200 return "IS_ERROR_ISP_MSG_FAIL";
201 case IS_ERROR_DRC_MSG_FAIL:
202 return "IS_ERROR_DRC_MSG_FAIL";
203 case IS_ERROR_LHFD_MSG_FAIL:
204 return "IS_ERROR_LHFD_MSG_FAIL";
205 case IS_ERROR_UNKNOWN:
206 return "IS_ERROR_UNKNOWN";
207
208 /* Sensor */
209 case IS_ERROR_SENSOR_PWRDN_FAIL:
210 return "IS_ERROR_SENSOR_PWRDN_FAIL";
211
212 /* ISP */
213 case IS_ERROR_ISP_PWRDN_FAIL:
214 return "IS_ERROR_ISP_PWRDN_FAIL";
215 case IS_ERROR_ISP_MULTIPLE_INPUT:
216 return "IS_ERROR_ISP_MULTIPLE_INPUT";
217 case IS_ERROR_ISP_ABSENT_INPUT:
218 return "IS_ERROR_ISP_ABSENT_INPUT";
219 case IS_ERROR_ISP_ABSENT_OUTPUT:
220 return "IS_ERROR_ISP_ABSENT_OUTPUT";
221 case IS_ERROR_ISP_NONADJACENT_OUTPUT:
222 return "IS_ERROR_ISP_NONADJACENT_OUTPUT";
223 case IS_ERROR_ISP_FORMAT_MISMATCH:
224 return "IS_ERROR_ISP_FORMAT_MISMATCH";
225 case IS_ERROR_ISP_WIDTH_MISMATCH:
226 return "IS_ERROR_ISP_WIDTH_MISMATCH";
227 case IS_ERROR_ISP_HEIGHT_MISMATCH:
228 return "IS_ERROR_ISP_HEIGHT_MISMATCH";
229 case IS_ERROR_ISP_BITWIDTH_MISMATCH:
230 return "IS_ERROR_ISP_BITWIDTH_MISMATCH";
231 case IS_ERROR_ISP_FRAME_END_TIME_OUT:
232 return "IS_ERROR_ISP_FRAME_END_TIME_OUT";
233
234 /* DRC */
235 case IS_ERROR_DRC_PWRDN_FAIL:
236 return "IS_ERROR_DRC_PWRDN_FAIL";
237 case IS_ERROR_DRC_MULTIPLE_INPUT:
238 return "IS_ERROR_DRC_MULTIPLE_INPUT";
239 case IS_ERROR_DRC_ABSENT_INPUT:
240 return "IS_ERROR_DRC_ABSENT_INPUT";
241 case IS_ERROR_DRC_NONADJACENT_INPUT:
242 return "IS_ERROR_DRC_NONADJACENT_INPUT";
243 case IS_ERROR_DRC_ABSENT_OUTPUT:
244 return "IS_ERROR_DRC_ABSENT_OUTPUT";
245 case IS_ERROR_DRC_NONADJACENT_OUTPUT:
246 return "IS_ERROR_DRC_NONADJACENT_OUTPUT";
247 case IS_ERROR_DRC_FORMAT_MISMATCH:
248 return "IS_ERROR_DRC_FORMAT_MISMATCH";
249 case IS_ERROR_DRC_WIDTH_MISMATCH:
250 return "IS_ERROR_DRC_WIDTH_MISMATCH";
251 case IS_ERROR_DRC_HEIGHT_MISMATCH:
252 return "IS_ERROR_DRC_HEIGHT_MISMATCH";
253 case IS_ERROR_DRC_BITWIDTH_MISMATCH:
254 return "IS_ERROR_DRC_BITWIDTH_MISMATCH";
255 case IS_ERROR_DRC_FRAME_END_TIME_OUT:
256 return "IS_ERROR_DRC_FRAME_END_TIME_OUT";
257
258 /* FD */
259 case IS_ERROR_FD_PWRDN_FAIL:
260 return "IS_ERROR_FD_PWRDN_FAIL";
261 case IS_ERROR_FD_MULTIPLE_INPUT:
262 return "IS_ERROR_FD_MULTIPLE_INPUT";
263 case IS_ERROR_FD_ABSENT_INPUT:
264 return "IS_ERROR_FD_ABSENT_INPUT";
265 case IS_ERROR_FD_NONADJACENT_INPUT:
266 return "IS_ERROR_FD_NONADJACENT_INPUT";
267 case IS_ERROR_LHFD_FRAME_END_TIME_OUT:
268 return "IS_ERROR_LHFD_FRAME_END_TIME_OUT";
269 default:
270 return "Unknown";
271 }
272}
diff --git a/drivers/media/platform/exynos4-is/fimc-is-errno.h b/drivers/media/platform/exynos4-is/fimc-is-errno.h
new file mode 100644
index 000000000000..3de6f6da6f87
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-is-errno.h
@@ -0,0 +1,248 @@
1/*
2 * Samsung Exynos4 SoC series FIMC-IS slave interface driver
3 *
4 * FIMC-IS error code definition
5 *
6 * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd.
7 *
8 * Authors: Younghwan Joo <yhwan.joo@samsung.com>
9 * Sylwester Nawrocki <s.nawrocki@samsung.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14*/
15
16#ifndef FIMC_IS_ERR_H_
17#define FIMC_IS_ERR_H_
18
19#define IS_ERROR_VER 011 /* IS ERROR VERSION 0.11 */
20
21enum {
22 IS_ERROR_NONE,
23
24 /* General 1 ~ 99 */
25 IS_ERROR_INVALID_COMMAND,
26 IS_ERROR_REQUEST_FAIL,
27 IS_ERROR_INVALID_SCENARIO,
28 IS_ERROR_INVALID_SENSORID,
29 IS_ERROR_INVALID_MODE_CHANGE,
30 IS_ERROR_INVALID_MAGIC_NUMBER,
31 IS_ERROR_INVALID_SETFILE_HDR,
32 IS_ERROR_BUSY,
33 IS_ERROR_SET_PARAMETER,
34 IS_ERROR_INVALID_PATH,
35 IS_ERROR_OPEN_SENSOR_FAIL,
36 IS_ERROR_ENTRY_MSG_THREAD_DOWN,
37 IS_ERROR_ISP_FRAME_END_NOT_DONE,
38 IS_ERROR_DRC_FRAME_END_NOT_DONE,
39 IS_ERROR_SCALERC_FRAME_END_NOT_DONE,
40 IS_ERROR_ODC_FRAME_END_NOT_DONE,
41 IS_ERROR_DIS_FRAME_END_NOT_DONE,
42 IS_ERROR_TDNR_FRAME_END_NOT_DONE,
43 IS_ERROR_SCALERP_FRAME_END_NOT_DONE,
44 IS_ERROR_WAIT_STREAM_OFF_NOT_DONE,
45 IS_ERROR_NO_MSG_IS_RECEIVED,
46 IS_ERROR_SENSOR_MSG_FAIL,
47 IS_ERROR_ISP_MSG_FAIL,
48 IS_ERROR_DRC_MSG_FAIL,
49 IS_ERROR_SCALERC_MSG_FAIL,
50 IS_ERROR_ODC_MSG_FAIL,
51 IS_ERROR_DIS_MSG_FAIL,
52 IS_ERROR_TDNR_MSG_FAIL,
53 IS_ERROR_SCALERP_MSG_FAIL,
54 IS_ERROR_LHFD_MSG_FAIL,
55 IS_ERROR_LHFD_INTERNAL_STOP,
56
57 /* Sensor 100 ~ 199 */
58 IS_ERROR_SENSOR_PWRDN_FAIL = 100,
59 IS_ERROR_SENSOR_STREAM_ON_FAIL,
60 IS_ERROR_SENSOR_STREAM_OFF_FAIL,
61
62 /* ISP 200 ~ 299 */
63 IS_ERROR_ISP_PWRDN_FAIL = 200,
64 IS_ERROR_ISP_MULTIPLE_INPUT,
65 IS_ERROR_ISP_ABSENT_INPUT,
66 IS_ERROR_ISP_ABSENT_OUTPUT,
67 IS_ERROR_ISP_NONADJACENT_OUTPUT,
68 IS_ERROR_ISP_FORMAT_MISMATCH,
69 IS_ERROR_ISP_WIDTH_MISMATCH,
70 IS_ERROR_ISP_HEIGHT_MISMATCH,
71 IS_ERROR_ISP_BITWIDTH_MISMATCH,
72 IS_ERROR_ISP_FRAME_END_TIME_OUT,
73
74 /* DRC 300 ~ 399 */
75 IS_ERROR_DRC_PWRDN_FAIL = 300,
76 IS_ERROR_DRC_MULTIPLE_INPUT,
77 IS_ERROR_DRC_ABSENT_INPUT,
78 IS_ERROR_DRC_NONADJACENT_INPUT,
79 IS_ERROR_DRC_ABSENT_OUTPUT,
80 IS_ERROR_DRC_NONADJACENT_OUTPUT,
81 IS_ERROR_DRC_FORMAT_MISMATCH,
82 IS_ERROR_DRC_WIDTH_MISMATCH,
83 IS_ERROR_DRC_HEIGHT_MISMATCH,
84 IS_ERROR_DRC_BITWIDTH_MISMATCH,
85 IS_ERROR_DRC_FRAME_END_TIME_OUT,
86
87 /* SCALERC 400 ~ 499 */
88 IS_ERROR_SCALERC_PWRDN_FAIL = 400,
89
90 /* ODC 500 ~ 599 */
91 IS_ERROR_ODC_PWRDN_FAIL = 500,
92
93 /* DIS 600 ~ 699 */
94 IS_ERROR_DIS_PWRDN_FAIL = 600,
95
96 /* TDNR 700 ~ 799 */
97 IS_ERROR_TDNR_PWRDN_FAIL = 700,
98
99 /* SCALERC 800 ~ 899 */
100 IS_ERROR_SCALERP_PWRDN_FAIL = 800,
101
102 /* FD 900 ~ 999 */
103 IS_ERROR_FD_PWRDN_FAIL = 900,
104 IS_ERROR_FD_MULTIPLE_INPUT,
105 IS_ERROR_FD_ABSENT_INPUT,
106 IS_ERROR_FD_NONADJACENT_INPUT,
107 IS_ERROR_LHFD_FRAME_END_TIME_OUT,
108
109 IS_ERROR_UNKNOWN = 1000,
110};
111
112#define IS_ERROR_TIME_OUT_FLAG 0x80000000
113
114/* Set parameter error enum */
115enum fimc_is_error {
116 /* Common error (0~99) */
117 ERROR_COMMON_NONE = 0,
118 ERROR_COMMON_CMD = 1, /* Invalid command */
119 ERROR_COMMON_PARAMETER = 2, /* Invalid parameter */
120 /* setfile is not loaded before adjusting */
121 ERROR_COMMON_SETFILE_LOAD = 3,
122 /* setfile is not Adjusted before runnng. */
123 ERROR_COMMON_SETFILE_ADJUST = 4,
124 /* Index of setfile is not valid (0~MAX_SETFILE_NUM-1) */
125 ERROR_COMMON_SETFILE_INDEX = 5,
126 /* Input path can be changed in ready state(stop) */
127 ERROR_COMMON_INPUT_PATH = 6,
128 /* IP can not start if input path is not set */
129 ERROR_COMMON_INPUT_INIT = 7,
130 /* Output path can be changed in ready state (stop) */
131 ERROR_COMMON_OUTPUT_PATH = 8,
132 /* IP can not start if output path is not set */
133 ERROR_COMMON_OUTPUT_INIT = 9,
134
135 ERROR_CONTROL_NONE = ERROR_COMMON_NONE,
136 ERROR_CONTROL_BYPASS = 11, /* Enable or Disable */
137
138 ERROR_OTF_INPUT_NONE = ERROR_COMMON_NONE,
139 ERROR_OTF_INPUT_CMD = 21,
140 /* invalid format (DRC: YUV444, FD: YUV444, 422, 420) */
141 ERROR_OTF_INPUT_FORMAT = 22,
142 /* invalid width (DRC: 128~8192, FD: 32~8190) */
143 ERROR_OTF_INPUT_WIDTH = 23,
144 /* invalid height (DRC: 64~8192, FD: 16~8190) */
145 ERROR_OTF_INPUT_HEIGHT = 24,
146 /* invalid bit-width (DRC: 8~12bits, FD: 8bit) */
147 ERROR_OTF_INPUT_BIT_WIDTH = 25,
148 /* invalid FrameTime for ISP */
149 ERROR_OTF_INPUT_USER_FRAMETIIME = 26,
150
151 ERROR_DMA_INPUT_NONE = ERROR_COMMON_NONE,
152 /* invalid width (DRC: 128~8192, FD: 32~8190) */
153 ERROR_DMA_INPUT_WIDTH = 31,
154 /* invalid height (DRC: 64~8192, FD: 16~8190) */
155 ERROR_DMA_INPUT_HEIGHT = 32,
156 /* invalid format (DRC: YUV444 or YUV422, FD: YUV444, 422, 420) */
157 ERROR_DMA_INPUT_FORMAT = 33,
158 /* invalid bit-width (DRC: 8~12bit, FD: 8bit) */
159 ERROR_DMA_INPUT_BIT_WIDTH = 34,
160 /* invalid order(DRC: YYCbCrorYCbYCr, FD:NO,YYCbCr,YCbYCr,CbCr,CrCb) */
161 ERROR_DMA_INPUT_ORDER = 35,
162 /* invalid palne (DRC: 3, FD: 1, 2, 3) */
163 ERROR_DMA_INPUT_PLANE = 36,
164
165 ERROR_OTF_OUTPUT_NONE = ERROR_COMMON_NONE,
166 /* invalid width (DRC: 128~8192) */
167 ERROR_OTF_OUTPUT_WIDTH = 41,
168 /* invalid height (DRC: 64~8192) */
169 ERROR_OTF_OUTPUT_HEIGHT = 42,
170 /* invalid format (DRC: YUV444) */
171 ERROR_OTF_OUTPUT_FORMAT = 43,
172 /* invalid bit-width (DRC: 8~12bits) */
173 ERROR_OTF_OUTPUT_BIT_WIDTH = 44,
174
175 ERROR_DMA_OUTPUT_NONE = ERROR_COMMON_NONE,
176 ERROR_DMA_OUTPUT_WIDTH = 51, /* invalid width */
177 ERROR_DMA_OUTPUT_HEIGHT = 52, /* invalid height */
178 ERROR_DMA_OUTPUT_FORMAT = 53, /* invalid format */
179 ERROR_DMA_OUTPUT_BIT_WIDTH = 54, /* invalid bit-width */
180 ERROR_DMA_OUTPUT_PLANE = 55, /* invalid plane */
181 ERROR_DMA_OUTPUT_ORDER = 56, /* invalid order */
182
183 ERROR_GLOBAL_SHOTMODE_NONE = ERROR_COMMON_NONE,
184
185 /* SENSOR Error(100~199) */
186 ERROR_SENSOR_NONE = ERROR_COMMON_NONE,
187 ERROR_SENSOR_I2C_FAIL = 101,
188 ERROR_SENSOR_INVALID_FRAMERATE,
189 ERROR_SENSOR_INVALID_EXPOSURETIME,
190 ERROR_SENSOR_INVALID_SIZE,
191 ERROR_SENSOR_INVALID_SETTING,
192 ERROR_SENSOR_ACTURATOR_INIT_FAIL,
193 ERROR_SENSOR_INVALID_AF_POS,
194 ERROR_SENSOR_UNSUPPORT_FUNC,
195 ERROR_SENSOR_UNSUPPORT_PERI,
196 ERROR_SENSOR_UNSUPPORT_AF,
197
198 /* ISP Error (200~299) */
199 ERROR_ISP_AF_NONE = ERROR_COMMON_NONE,
200 ERROR_ISP_AF_BUSY = 201,
201 ERROR_ISP_AF_INVALID_COMMAND = 202,
202 ERROR_ISP_AF_INVALID_MODE = 203,
203 ERROR_ISP_FLASH_NONE = ERROR_COMMON_NONE,
204 ERROR_ISP_AWB_NONE = ERROR_COMMON_NONE,
205 ERROR_ISP_IMAGE_EFFECT_NONE = ERROR_COMMON_NONE,
206 ERROR_ISP_ISO_NONE = ERROR_COMMON_NONE,
207 ERROR_ISP_ADJUST_NONE = ERROR_COMMON_NONE,
208 ERROR_ISP_METERING_NONE = ERROR_COMMON_NONE,
209 ERROR_ISP_AFC_NONE = ERROR_COMMON_NONE,
210
211 /* DRC Error (300~399) */
212
213 /* FD Error (400~499) */
214 ERROR_FD_NONE = ERROR_COMMON_NONE,
215 /* Invalid max number (1~16) */
216 ERROR_FD_CONFIG_MAX_NUMBER_STATE = 401,
217 ERROR_FD_CONFIG_MAX_NUMBER_INVALID = 402,
218 ERROR_FD_CONFIG_YAW_ANGLE_STATE = 403,
219 ERROR_FD_CONFIG_YAW_ANGLE_INVALID = 404,
220 ERROR_FD_CONFIG_ROLL_ANGLE_STATE = 405,
221 ERROR_FD_CONFIG_ROLL_ANGLE_INVALID = 406,
222 ERROR_FD_CONFIG_SMILE_MODE_INVALID = 407,
223 ERROR_FD_CONFIG_BLINK_MODE_INVALID = 408,
224 ERROR_FD_CONFIG_EYES_DETECT_INVALID = 409,
225 ERROR_FD_CONFIG_MOUTH_DETECT_INVALID = 410,
226 ERROR_FD_CONFIG_ORIENTATION_STATE = 411,
227 ERROR_FD_CONFIG_ORIENTATION_INVALID = 412,
228 ERROR_FD_CONFIG_ORIENTATION_VALUE_INVALID = 413,
229 /* PARAM_FdResultStr can be only applied in ready-state or stream off */
230 ERROR_FD_RESULT = 414,
231 /* PARAM_FdModeStr can be only applied in ready-state or stream off */
232 ERROR_FD_MODE = 415,
233 /* Scaler Error (500 ~ 599) */
234 ERROR_SCALER_NO_NONE = ERROR_COMMON_NONE,
235 ERROR_SCALER_DMA_OUTSEL = 501,
236 ERROR_SCALER_H_RATIO = 502,
237 ERROR_SCALER_V_RATIO = 503,
238
239 ERROR_SCALER_IMAGE_EFFECT = 510,
240
241 ERROR_SCALER_ROTATE = 520,
242 ERROR_SCALER_FLIP = 521,
243};
244
245const char * const fimc_is_strerr(unsigned int error);
246const char * const fimc_is_param_strerr(unsigned int error);
247
248#endif /* FIMC_IS_ERR_H_ */
diff --git a/drivers/media/platform/exynos4-is/fimc-is-i2c.c b/drivers/media/platform/exynos4-is/fimc-is-i2c.c
new file mode 100644
index 000000000000..c397777d7cbb
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-is-i2c.c
@@ -0,0 +1,126 @@
1/*
2 * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
3 *
4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
5 *
6 * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/clk.h>
14#include <linux/module.h>
15#include <linux/of_i2c.h>
16#include <linux/platform_device.h>
17#include <linux/pm_runtime.h>
18#include <linux/slab.h>
19#include "fimc-is-i2c.h"
20
21struct fimc_is_i2c {
22 struct i2c_adapter adapter;
23 struct clk *clock;
24};
25
26/*
27 * An empty algorithm is used as the actual I2C bus controller driver
28 * is implemented in the FIMC-IS subsystem firmware and the host CPU
29 * doesn't access the I2C bus controller.
30 */
31static const struct i2c_algorithm fimc_is_i2c_algorithm;
32
33static int fimc_is_i2c_probe(struct platform_device *pdev)
34{
35 struct device_node *node = pdev->dev.of_node;
36 struct fimc_is_i2c *isp_i2c;
37 struct i2c_adapter *i2c_adap;
38 int ret;
39
40 isp_i2c = devm_kzalloc(&pdev->dev, sizeof(*isp_i2c), GFP_KERNEL);
41 if (!isp_i2c)
42 return -ENOMEM;
43
44 isp_i2c->clock = devm_clk_get(&pdev->dev, "i2c_isp");
45 if (IS_ERR(isp_i2c->clock)) {
46 dev_err(&pdev->dev, "failed to get the clock\n");
47 return PTR_ERR(isp_i2c->clock);
48 }
49
50 i2c_adap = &isp_i2c->adapter;
51 i2c_adap->dev.of_node = node;
52 i2c_adap->dev.parent = &pdev->dev;
53 strlcpy(i2c_adap->name, "exynos4x12-isp-i2c", sizeof(i2c_adap->name));
54 i2c_adap->owner = THIS_MODULE;
55 i2c_adap->algo = &fimc_is_i2c_algorithm;
56 i2c_adap->class = I2C_CLASS_SPD;
57
58 ret = i2c_add_adapter(i2c_adap);
59 if (ret < 0) {
60 dev_err(&pdev->dev, "failed to add I2C bus %s\n",
61 node->full_name);
62 return ret;
63 }
64
65 platform_set_drvdata(pdev, isp_i2c);
66
67 pm_runtime_enable(&pdev->dev);
68 pm_runtime_enable(&i2c_adap->dev);
69
70 of_i2c_register_devices(i2c_adap);
71
72 return 0;
73}
74
75static int fimc_is_i2c_remove(struct platform_device *pdev)
76{
77 struct fimc_is_i2c *isp_i2c = platform_get_drvdata(pdev);
78
79 pm_runtime_disable(&isp_i2c->adapter.dev);
80 pm_runtime_disable(&pdev->dev);
81 i2c_del_adapter(&isp_i2c->adapter);
82
83 return 0;
84}
85
86static int fimc_is_i2c_suspend(struct device *dev)
87{
88 struct fimc_is_i2c *isp_i2c = dev_get_drvdata(dev);
89 clk_disable_unprepare(isp_i2c->clock);
90 return 0;
91}
92
93static int fimc_is_i2c_resume(struct device *dev)
94{
95 struct fimc_is_i2c *isp_i2c = dev_get_drvdata(dev);
96 return clk_prepare_enable(isp_i2c->clock);
97}
98
99UNIVERSAL_DEV_PM_OPS(fimc_is_i2c_pm_ops, fimc_is_i2c_suspend,
100 fimc_is_i2c_resume, NULL);
101
102static const struct of_device_id fimc_is_i2c_of_match[] = {
103 { .compatible = FIMC_IS_I2C_COMPATIBLE },
104 { },
105};
106
107static struct platform_driver fimc_is_i2c_driver = {
108 .probe = fimc_is_i2c_probe,
109 .remove = fimc_is_i2c_remove,
110 .driver = {
111 .of_match_table = fimc_is_i2c_of_match,
112 .name = "fimc-isp-i2c",
113 .owner = THIS_MODULE,
114 .pm = &fimc_is_i2c_pm_ops,
115 }
116};
117
118int fimc_is_register_i2c_driver(void)
119{
120 return platform_driver_register(&fimc_is_i2c_driver);
121}
122
123void fimc_is_unregister_i2c_driver(void)
124{
125 platform_driver_unregister(&fimc_is_i2c_driver);
126}
diff --git a/drivers/media/platform/exynos4-is/fimc-is-i2c.h b/drivers/media/platform/exynos4-is/fimc-is-i2c.h
new file mode 100644
index 000000000000..0d38d6bb963b
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-is-i2c.h
@@ -0,0 +1,15 @@
1/*
2 * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
3 *
4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
5 * Sylwester Nawrocki <s.nawrocki@samsung.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#define FIMC_IS_I2C_COMPATIBLE "samsung,exynos4212-i2c-isp"
13
14int fimc_is_register_i2c_driver(void);
15void fimc_is_unregister_i2c_driver(void);
diff --git a/drivers/media/platform/exynos4-is/fimc-is-param.c b/drivers/media/platform/exynos4-is/fimc-is-param.c
new file mode 100644
index 000000000000..53fe2a2b4db3
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-is-param.c
@@ -0,0 +1,900 @@
1/*
2 * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
3 *
4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
5 *
6 * Authors: Younghwan Joo <yhwan.joo@samsung.com>
7 * Sylwester Nawrocki <s.nawrocki@samsung.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
14
15#include <linux/bitops.h>
16#include <linux/bug.h>
17#include <linux/device.h>
18#include <linux/errno.h>
19#include <linux/kernel.h>
20#include <linux/module.h>
21#include <linux/platform_device.h>
22#include <linux/slab.h>
23#include <linux/types.h>
24#include <linux/videodev2.h>
25
26#include <media/v4l2-device.h>
27#include <media/v4l2-ioctl.h>
28
29#include "fimc-is.h"
30#include "fimc-is-command.h"
31#include "fimc-is-errno.h"
32#include "fimc-is-param.h"
33#include "fimc-is-regs.h"
34#include "fimc-is-sensor.h"
35
36static void __hw_param_copy(void *dst, void *src)
37{
38 memcpy(dst, src, FIMC_IS_PARAM_MAX_SIZE);
39}
40
41void __fimc_is_hw_update_param_global_shotmode(struct fimc_is *is)
42{
43 struct param_global_shotmode *dst, *src;
44
45 dst = &is->is_p_region->parameter.global.shotmode;
46 src = &is->config[is->config_index].global.shotmode;
47 __hw_param_copy(dst, src);
48}
49
50void __fimc_is_hw_update_param_sensor_framerate(struct fimc_is *is)
51{
52 struct param_sensor_framerate *dst, *src;
53
54 dst = &is->is_p_region->parameter.sensor.frame_rate;
55 src = &is->config[is->config_index].sensor.frame_rate;
56 __hw_param_copy(dst, src);
57}
58
59int __fimc_is_hw_update_param(struct fimc_is *is, u32 offset)
60{
61 struct is_param_region *par = &is->is_p_region->parameter;
62 struct chain_config *cfg = &is->config[is->config_index];
63
64 switch (offset) {
65 case PARAM_ISP_CONTROL:
66 __hw_param_copy(&par->isp.control, &cfg->isp.control);
67 break;
68
69 case PARAM_ISP_OTF_INPUT:
70 __hw_param_copy(&par->isp.otf_input, &cfg->isp.otf_input);
71 break;
72
73 case PARAM_ISP_DMA1_INPUT:
74 __hw_param_copy(&par->isp.dma1_input, &cfg->isp.dma1_input);
75 break;
76
77 case PARAM_ISP_DMA2_INPUT:
78 __hw_param_copy(&par->isp.dma2_input, &cfg->isp.dma2_input);
79 break;
80
81 case PARAM_ISP_AA:
82 __hw_param_copy(&par->isp.aa, &cfg->isp.aa);
83 break;
84
85 case PARAM_ISP_FLASH:
86 __hw_param_copy(&par->isp.flash, &cfg->isp.flash);
87 break;
88
89 case PARAM_ISP_AWB:
90 __hw_param_copy(&par->isp.awb, &cfg->isp.awb);
91 break;
92
93 case PARAM_ISP_IMAGE_EFFECT:
94 __hw_param_copy(&par->isp.effect, &cfg->isp.effect);
95 break;
96
97 case PARAM_ISP_ISO:
98 __hw_param_copy(&par->isp.iso, &cfg->isp.iso);
99 break;
100
101 case PARAM_ISP_ADJUST:
102 __hw_param_copy(&par->isp.adjust, &cfg->isp.adjust);
103 break;
104
105 case PARAM_ISP_METERING:
106 __hw_param_copy(&par->isp.metering, &cfg->isp.metering);
107 break;
108
109 case PARAM_ISP_AFC:
110 __hw_param_copy(&par->isp.afc, &cfg->isp.afc);
111 break;
112
113 case PARAM_ISP_OTF_OUTPUT:
114 __hw_param_copy(&par->isp.otf_output, &cfg->isp.otf_output);
115 break;
116
117 case PARAM_ISP_DMA1_OUTPUT:
118 __hw_param_copy(&par->isp.dma1_output, &cfg->isp.dma1_output);
119 break;
120
121 case PARAM_ISP_DMA2_OUTPUT:
122 __hw_param_copy(&par->isp.dma2_output, &cfg->isp.dma2_output);
123 break;
124
125 case PARAM_DRC_CONTROL:
126 __hw_param_copy(&par->drc.control, &cfg->drc.control);
127 break;
128
129 case PARAM_DRC_OTF_INPUT:
130 __hw_param_copy(&par->drc.otf_input, &cfg->drc.otf_input);
131 break;
132
133 case PARAM_DRC_DMA_INPUT:
134 __hw_param_copy(&par->drc.dma_input, &cfg->drc.dma_input);
135 break;
136
137 case PARAM_DRC_OTF_OUTPUT:
138 __hw_param_copy(&par->drc.otf_output, &cfg->drc.otf_output);
139 break;
140
141 case PARAM_FD_CONTROL:
142 __hw_param_copy(&par->fd.control, &cfg->fd.control);
143 break;
144
145 case PARAM_FD_OTF_INPUT:
146 __hw_param_copy(&par->fd.otf_input, &cfg->fd.otf_input);
147 break;
148
149 case PARAM_FD_DMA_INPUT:
150 __hw_param_copy(&par->fd.dma_input, &cfg->fd.dma_input);
151 break;
152
153 case PARAM_FD_CONFIG:
154 __hw_param_copy(&par->fd.config, &cfg->fd.config);
155 break;
156
157 default:
158 return -EINVAL;
159 }
160
161 return 0;
162}
163
164unsigned int __get_pending_param_count(struct fimc_is *is)
165{
166 struct chain_config *config = &is->config[is->config_index];
167 unsigned long flags;
168 unsigned int count;
169
170 spin_lock_irqsave(&is->slock, flags);
171 count = hweight32(config->p_region_index1);
172 count += hweight32(config->p_region_index2);
173 spin_unlock_irqrestore(&is->slock, flags);
174
175 return count;
176}
177
178int __is_hw_update_params(struct fimc_is *is)
179{
180 unsigned long *p_index1, *p_index2;
181 int i, id, ret = 0;
182
183 id = is->config_index;
184 p_index1 = &is->config[id].p_region_index1;
185 p_index2 = &is->config[id].p_region_index2;
186
187 if (test_bit(PARAM_GLOBAL_SHOTMODE, p_index1))
188 __fimc_is_hw_update_param_global_shotmode(is);
189
190 if (test_bit(PARAM_SENSOR_FRAME_RATE, p_index1))
191 __fimc_is_hw_update_param_sensor_framerate(is);
192
193 for (i = PARAM_ISP_CONTROL; i < PARAM_DRC_CONTROL; i++) {
194 if (test_bit(i, p_index1))
195 ret = __fimc_is_hw_update_param(is, i);
196 }
197
198 for (i = PARAM_DRC_CONTROL; i < PARAM_SCALERC_CONTROL; i++) {
199 if (test_bit(i, p_index1))
200 ret = __fimc_is_hw_update_param(is, i);
201 }
202
203 for (i = PARAM_FD_CONTROL; i <= PARAM_FD_CONFIG; i++) {
204 if (test_bit((i - 32), p_index2))
205 ret = __fimc_is_hw_update_param(is, i);
206 }
207
208 return ret;
209}
210
211void __is_get_frame_size(struct fimc_is *is, struct v4l2_mbus_framefmt *mf)
212{
213 struct isp_param *isp;
214
215 isp = &is->config[is->config_index].isp;
216 mf->width = isp->otf_input.width;
217 mf->height = isp->otf_input.height;
218}
219
220void __is_set_frame_size(struct fimc_is *is, struct v4l2_mbus_framefmt *mf)
221{
222 unsigned int index = is->config_index;
223 struct isp_param *isp;
224 struct drc_param *drc;
225 struct fd_param *fd;
226
227 isp = &is->config[index].isp;
228 drc = &is->config[index].drc;
229 fd = &is->config[index].fd;
230
231 /* Update isp size info (OTF only) */
232 isp->otf_input.width = mf->width;
233 isp->otf_input.height = mf->height;
234 isp->otf_output.width = mf->width;
235 isp->otf_output.height = mf->height;
236 /* Update drc size info (OTF only) */
237 drc->otf_input.width = mf->width;
238 drc->otf_input.height = mf->height;
239 drc->otf_output.width = mf->width;
240 drc->otf_output.height = mf->height;
241 /* Update fd size info (OTF only) */
242 fd->otf_input.width = mf->width;
243 fd->otf_input.height = mf->height;
244
245 if (test_bit(PARAM_ISP_OTF_INPUT,
246 &is->config[index].p_region_index1))
247 return;
248
249 /* Update field */
250 fimc_is_set_param_bit(is, PARAM_ISP_OTF_INPUT);
251 fimc_is_set_param_bit(is, PARAM_ISP_OTF_OUTPUT);
252 fimc_is_set_param_bit(is, PARAM_DRC_OTF_INPUT);
253 fimc_is_set_param_bit(is, PARAM_DRC_OTF_OUTPUT);
254 fimc_is_set_param_bit(is, PARAM_FD_OTF_INPUT);
255}
256
257int fimc_is_hw_get_sensor_max_framerate(struct fimc_is *is)
258{
259 switch (is->sensor->drvdata->id) {
260 case FIMC_IS_SENSOR_ID_S5K6A3:
261 return 30;
262 default:
263 return 15;
264 }
265}
266
267void __is_set_sensor(struct fimc_is *is, int fps)
268{
269 unsigned int index = is->config_index;
270 struct sensor_param *sensor;
271 struct isp_param *isp;
272
273 sensor = &is->config[index].sensor;
274 isp = &is->config[index].isp;
275
276 if (fps == 0) {
277 sensor->frame_rate.frame_rate =
278 fimc_is_hw_get_sensor_max_framerate(is);
279 isp->otf_input.frametime_min = 0;
280 isp->otf_input.frametime_max = 66666;
281 } else {
282 sensor->frame_rate.frame_rate = fps;
283 isp->otf_input.frametime_min = 0;
284 isp->otf_input.frametime_max = (u32)1000000 / fps;
285 }
286
287 fimc_is_set_param_bit(is, PARAM_SENSOR_FRAME_RATE);
288 fimc_is_set_param_bit(is, PARAM_ISP_OTF_INPUT);
289}
290
291void __is_set_init_isp_aa(struct fimc_is *is)
292{
293 struct isp_param *isp;
294
295 isp = &is->config[is->config_index].isp;
296
297 isp->aa.cmd = ISP_AA_COMMAND_START;
298 isp->aa.target = ISP_AA_TARGET_AF | ISP_AA_TARGET_AE |
299 ISP_AA_TARGET_AWB;
300 isp->aa.mode = 0;
301 isp->aa.scene = 0;
302 isp->aa.sleep = 0;
303 isp->aa.face = 0;
304 isp->aa.touch_x = 0;
305 isp->aa.touch_y = 0;
306 isp->aa.manual_af_setting = 0;
307 isp->aa.err = ISP_AF_ERROR_NONE;
308
309 fimc_is_set_param_bit(is, PARAM_ISP_AA);
310}
311
312void __is_set_isp_flash(struct fimc_is *is, u32 cmd, u32 redeye)
313{
314 unsigned int index = is->config_index;
315 struct isp_param *isp = &is->config[index].isp;
316
317 isp->flash.cmd = cmd;
318 isp->flash.redeye = redeye;
319 isp->flash.err = ISP_FLASH_ERROR_NONE;
320
321 fimc_is_set_param_bit(is, PARAM_ISP_FLASH);
322}
323
324void __is_set_isp_awb(struct fimc_is *is, u32 cmd, u32 val)
325{
326 unsigned int index = is->config_index;
327 struct isp_param *isp;
328
329 isp = &is->config[index].isp;
330
331 isp->awb.cmd = cmd;
332 isp->awb.illumination = val;
333 isp->awb.err = ISP_AWB_ERROR_NONE;
334
335 fimc_is_set_param_bit(is, PARAM_ISP_AWB);
336}
337
338void __is_set_isp_effect(struct fimc_is *is, u32 cmd)
339{
340 unsigned int index = is->config_index;
341 struct isp_param *isp;
342
343 isp = &is->config[index].isp;
344
345 isp->effect.cmd = cmd;
346 isp->effect.err = ISP_IMAGE_EFFECT_ERROR_NONE;
347
348 fimc_is_set_param_bit(is, PARAM_ISP_IMAGE_EFFECT);
349}
350
351void __is_set_isp_iso(struct fimc_is *is, u32 cmd, u32 val)
352{
353 unsigned int index = is->config_index;
354 struct isp_param *isp;
355
356 isp = &is->config[index].isp;
357
358 isp->iso.cmd = cmd;
359 isp->iso.value = val;
360 isp->iso.err = ISP_ISO_ERROR_NONE;
361
362 fimc_is_set_param_bit(is, PARAM_ISP_ISO);
363}
364
365void __is_set_isp_adjust(struct fimc_is *is, u32 cmd, u32 val)
366{
367 unsigned int index = is->config_index;
368 unsigned long *p_index;
369 struct isp_param *isp;
370
371 p_index = &is->config[index].p_region_index1;
372 isp = &is->config[index].isp;
373
374 switch (cmd) {
375 case ISP_ADJUST_COMMAND_MANUAL_CONTRAST:
376 isp->adjust.contrast = val;
377 break;
378 case ISP_ADJUST_COMMAND_MANUAL_SATURATION:
379 isp->adjust.saturation = val;
380 break;
381 case ISP_ADJUST_COMMAND_MANUAL_SHARPNESS:
382 isp->adjust.sharpness = val;
383 break;
384 case ISP_ADJUST_COMMAND_MANUAL_EXPOSURE:
385 isp->adjust.exposure = val;
386 break;
387 case ISP_ADJUST_COMMAND_MANUAL_BRIGHTNESS:
388 isp->adjust.brightness = val;
389 break;
390 case ISP_ADJUST_COMMAND_MANUAL_HUE:
391 isp->adjust.hue = val;
392 break;
393 case ISP_ADJUST_COMMAND_AUTO:
394 isp->adjust.contrast = 0;
395 isp->adjust.saturation = 0;
396 isp->adjust.sharpness = 0;
397 isp->adjust.exposure = 0;
398 isp->adjust.brightness = 0;
399 isp->adjust.hue = 0;
400 break;
401 }
402
403 if (!test_bit(PARAM_ISP_ADJUST, p_index)) {
404 isp->adjust.cmd = cmd;
405 isp->adjust.err = ISP_ADJUST_ERROR_NONE;
406 fimc_is_set_param_bit(is, PARAM_ISP_ADJUST);
407 } else {
408 isp->adjust.cmd |= cmd;
409 }
410}
411
412void __is_set_isp_metering(struct fimc_is *is, u32 id, u32 val)
413{
414 unsigned int index = is->config_index;
415 struct isp_param *isp;
416 unsigned long *p_index;
417
418 p_index = &is->config[index].p_region_index1;
419 isp = &is->config[index].isp;
420
421 switch (id) {
422 case IS_METERING_CONFIG_CMD:
423 isp->metering.cmd = val;
424 break;
425 case IS_METERING_CONFIG_WIN_POS_X:
426 isp->metering.win_pos_x = val;
427 break;
428 case IS_METERING_CONFIG_WIN_POS_Y:
429 isp->metering.win_pos_y = val;
430 break;
431 case IS_METERING_CONFIG_WIN_WIDTH:
432 isp->metering.win_width = val;
433 break;
434 case IS_METERING_CONFIG_WIN_HEIGHT:
435 isp->metering.win_height = val;
436 break;
437 default:
438 return;
439 }
440
441 if (!test_bit(PARAM_ISP_METERING, p_index)) {
442 isp->metering.err = ISP_METERING_ERROR_NONE;
443 fimc_is_set_param_bit(is, PARAM_ISP_METERING);
444 }
445}
446
447void __is_set_isp_afc(struct fimc_is *is, u32 cmd, u32 val)
448{
449 unsigned int index = is->config_index;
450 struct isp_param *isp;
451
452 isp = &is->config[index].isp;
453
454 isp->afc.cmd = cmd;
455 isp->afc.manual = val;
456 isp->afc.err = ISP_AFC_ERROR_NONE;
457
458 fimc_is_set_param_bit(is, PARAM_ISP_AFC);
459}
460
461void __is_set_drc_control(struct fimc_is *is, u32 val)
462{
463 unsigned int index = is->config_index;
464 struct drc_param *drc;
465
466 drc = &is->config[index].drc;
467
468 drc->control.bypass = val;
469
470 fimc_is_set_param_bit(is, PARAM_DRC_CONTROL);
471}
472
473void __is_set_fd_control(struct fimc_is *is, u32 val)
474{
475 unsigned int index = is->config_index;
476 struct fd_param *fd;
477 unsigned long *p_index;
478
479 p_index = &is->config[index].p_region_index2;
480 fd = &is->config[index].fd;
481
482 fd->control.cmd = val;
483
484 if (!test_bit((PARAM_FD_CONFIG - 32), p_index))
485 fimc_is_set_param_bit(is, PARAM_FD_CONTROL);
486}
487
488void __is_set_fd_config_maxface(struct fimc_is *is, u32 val)
489{
490 unsigned int index = is->config_index;
491 struct fd_param *fd;
492 unsigned long *p_index;
493
494 p_index = &is->config[index].p_region_index2;
495 fd = &is->config[index].fd;
496
497 fd->config.max_number = val;
498
499 if (!test_bit((PARAM_FD_CONFIG - 32), p_index)) {
500 fd->config.cmd = FD_CONFIG_COMMAND_MAXIMUM_NUMBER;
501 fd->config.err = ERROR_FD_NONE;
502 fimc_is_set_param_bit(is, PARAM_FD_CONFIG);
503 } else {
504 fd->config.cmd |= FD_CONFIG_COMMAND_MAXIMUM_NUMBER;
505 }
506}
507
508void __is_set_fd_config_rollangle(struct fimc_is *is, u32 val)
509{
510 unsigned int index = is->config_index;
511 struct fd_param *fd;
512 unsigned long *p_index;
513
514 p_index = &is->config[index].p_region_index2;
515 fd = &is->config[index].fd;
516
517 fd->config.roll_angle = val;
518
519 if (!test_bit((PARAM_FD_CONFIG - 32), p_index)) {
520 fd->config.cmd = FD_CONFIG_COMMAND_ROLL_ANGLE;
521 fd->config.err = ERROR_FD_NONE;
522 fimc_is_set_param_bit(is, PARAM_FD_CONFIG);
523 } else {
524 fd->config.cmd |= FD_CONFIG_COMMAND_ROLL_ANGLE;
525 }
526}
527
528void __is_set_fd_config_yawangle(struct fimc_is *is, u32 val)
529{
530 unsigned int index = is->config_index;
531 struct fd_param *fd;
532 unsigned long *p_index;
533
534 p_index = &is->config[index].p_region_index2;
535 fd = &is->config[index].fd;
536
537 fd->config.yaw_angle = val;
538
539 if (!test_bit((PARAM_FD_CONFIG - 32), p_index)) {
540 fd->config.cmd = FD_CONFIG_COMMAND_YAW_ANGLE;
541 fd->config.err = ERROR_FD_NONE;
542 fimc_is_set_param_bit(is, PARAM_FD_CONFIG);
543 } else {
544 fd->config.cmd |= FD_CONFIG_COMMAND_YAW_ANGLE;
545 }
546}
547
548void __is_set_fd_config_smilemode(struct fimc_is *is, u32 val)
549{
550 unsigned int index = is->config_index;
551 struct fd_param *fd;
552 unsigned long *p_index;
553
554 p_index = &is->config[index].p_region_index2;
555 fd = &is->config[index].fd;
556
557 fd->config.smile_mode = val;
558
559 if (!test_bit((PARAM_FD_CONFIG - 32), p_index)) {
560 fd->config.cmd = FD_CONFIG_COMMAND_SMILE_MODE;
561 fd->config.err = ERROR_FD_NONE;
562 fimc_is_set_param_bit(is, PARAM_FD_CONFIG);
563 } else {
564 fd->config.cmd |= FD_CONFIG_COMMAND_SMILE_MODE;
565 }
566}
567
568void __is_set_fd_config_blinkmode(struct fimc_is *is, u32 val)
569{
570 unsigned int index = is->config_index;
571 struct fd_param *fd;
572 unsigned long *p_index;
573
574 p_index = &is->config[index].p_region_index2;
575 fd = &is->config[index].fd;
576
577 fd->config.blink_mode = val;
578
579 if (!test_bit((PARAM_FD_CONFIG - 32), p_index)) {
580 fd->config.cmd = FD_CONFIG_COMMAND_BLINK_MODE;
581 fd->config.err = ERROR_FD_NONE;
582 fimc_is_set_param_bit(is, PARAM_FD_CONFIG);
583 } else {
584 fd->config.cmd |= FD_CONFIG_COMMAND_BLINK_MODE;
585 }
586}
587
588void __is_set_fd_config_eyedetect(struct fimc_is *is, u32 val)
589{
590 unsigned int index = is->config_index;
591 struct fd_param *fd;
592 unsigned long *p_index;
593
594 p_index = &is->config[index].p_region_index2;
595 fd = &is->config[index].fd;
596
597 fd->config.eye_detect = val;
598
599 if (!test_bit((PARAM_FD_CONFIG - 32), p_index)) {
600 fd->config.cmd = FD_CONFIG_COMMAND_EYES_DETECT;
601 fd->config.err = ERROR_FD_NONE;
602 fimc_is_set_param_bit(is, PARAM_FD_CONFIG);
603 } else {
604 fd->config.cmd |= FD_CONFIG_COMMAND_EYES_DETECT;
605 }
606}
607
608void __is_set_fd_config_mouthdetect(struct fimc_is *is, u32 val)
609{
610 unsigned int index = is->config_index;
611 struct fd_param *fd;
612 unsigned long *p_index;
613
614 p_index = &is->config[index].p_region_index2;
615 fd = &is->config[index].fd;
616
617 fd->config.mouth_detect = val;
618
619 if (!test_bit((PARAM_FD_CONFIG - 32), p_index)) {
620 fd->config.cmd = FD_CONFIG_COMMAND_MOUTH_DETECT;
621 fd->config.err = ERROR_FD_NONE;
622 fimc_is_set_param_bit(is, PARAM_FD_CONFIG);
623 } else {
624 fd->config.cmd |= FD_CONFIG_COMMAND_MOUTH_DETECT;
625 }
626}
627
628void __is_set_fd_config_orientation(struct fimc_is *is, u32 val)
629{
630 unsigned int index = is->config_index;
631 struct fd_param *fd;
632 unsigned long *p_index;
633
634 p_index = &is->config[index].p_region_index2;
635 fd = &is->config[index].fd;
636
637 fd->config.orientation = val;
638
639 if (!test_bit((PARAM_FD_CONFIG - 32), p_index)) {
640 fd->config.cmd = FD_CONFIG_COMMAND_ORIENTATION;
641 fd->config.err = ERROR_FD_NONE;
642 fimc_is_set_param_bit(is, PARAM_FD_CONFIG);
643 } else {
644 fd->config.cmd |= FD_CONFIG_COMMAND_ORIENTATION;
645 }
646}
647
648void __is_set_fd_config_orientation_val(struct fimc_is *is, u32 val)
649{
650 unsigned int index = is->config_index;
651 struct fd_param *fd;
652 unsigned long *p_index;
653
654 p_index = &is->config[index].p_region_index2;
655 fd = &is->config[index].fd;
656
657 fd->config.orientation_value = val;
658
659 if (!test_bit((PARAM_FD_CONFIG - 32), p_index)) {
660 fd->config.cmd = FD_CONFIG_COMMAND_ORIENTATION_VALUE;
661 fd->config.err = ERROR_FD_NONE;
662 fimc_is_set_param_bit(is, PARAM_FD_CONFIG);
663 } else {
664 fd->config.cmd |= FD_CONFIG_COMMAND_ORIENTATION_VALUE;
665 }
666}
667
668void fimc_is_set_initial_params(struct fimc_is *is)
669{
670 struct global_param *global;
671 struct sensor_param *sensor;
672 struct isp_param *isp;
673 struct drc_param *drc;
674 struct fd_param *fd;
675 unsigned long *p_index1, *p_index2;
676 unsigned int index;
677
678 index = is->config_index;
679 global = &is->config[index].global;
680 sensor = &is->config[index].sensor;
681 isp = &is->config[index].isp;
682 drc = &is->config[index].drc;
683 fd = &is->config[index].fd;
684 p_index1 = &is->config[index].p_region_index1;
685 p_index2 = &is->config[index].p_region_index2;
686
687 /* Global */
688 global->shotmode.cmd = 1;
689 fimc_is_set_param_bit(is, PARAM_GLOBAL_SHOTMODE);
690
691 /* ISP */
692 isp->control.cmd = CONTROL_COMMAND_START;
693 isp->control.bypass = CONTROL_BYPASS_DISABLE;
694 isp->control.err = CONTROL_ERROR_NONE;
695 fimc_is_set_param_bit(is, PARAM_ISP_CONTROL);
696
697 isp->otf_input.cmd = OTF_INPUT_COMMAND_ENABLE;
698 if (!test_bit(PARAM_ISP_OTF_INPUT, p_index1)) {
699 isp->otf_input.width = DEFAULT_PREVIEW_STILL_WIDTH;
700 isp->otf_input.height = DEFAULT_PREVIEW_STILL_HEIGHT;
701 fimc_is_set_param_bit(is, PARAM_ISP_OTF_INPUT);
702 }
703 if (is->sensor->test_pattern)
704 isp->otf_input.format = OTF_INPUT_FORMAT_STRGEN_COLORBAR_BAYER;
705 else
706 isp->otf_input.format = OTF_INPUT_FORMAT_BAYER;
707 isp->otf_input.bitwidth = 10;
708 isp->otf_input.order = OTF_INPUT_ORDER_BAYER_GR_BG;
709 isp->otf_input.crop_offset_x = 0;
710 isp->otf_input.crop_offset_y = 0;
711 isp->otf_input.err = OTF_INPUT_ERROR_NONE;
712
713 isp->dma1_input.cmd = DMA_INPUT_COMMAND_DISABLE;
714 isp->dma1_input.width = 0;
715 isp->dma1_input.height = 0;
716 isp->dma1_input.format = 0;
717 isp->dma1_input.bitwidth = 0;
718 isp->dma1_input.plane = 0;
719 isp->dma1_input.order = 0;
720 isp->dma1_input.buffer_number = 0;
721 isp->dma1_input.width = 0;
722 isp->dma1_input.err = DMA_INPUT_ERROR_NONE;
723 fimc_is_set_param_bit(is, PARAM_ISP_DMA1_INPUT);
724
725 isp->dma2_input.cmd = DMA_INPUT_COMMAND_DISABLE;
726 isp->dma2_input.width = 0;
727 isp->dma2_input.height = 0;
728 isp->dma2_input.format = 0;
729 isp->dma2_input.bitwidth = 0;
730 isp->dma2_input.plane = 0;
731 isp->dma2_input.order = 0;
732 isp->dma2_input.buffer_number = 0;
733 isp->dma2_input.width = 0;
734 isp->dma2_input.err = DMA_INPUT_ERROR_NONE;
735 fimc_is_set_param_bit(is, PARAM_ISP_DMA2_INPUT);
736
737 isp->aa.cmd = ISP_AA_COMMAND_START;
738 isp->aa.target = ISP_AA_TARGET_AE | ISP_AA_TARGET_AWB;
739 fimc_is_set_param_bit(is, PARAM_ISP_AA);
740
741 if (!test_bit(PARAM_ISP_FLASH, p_index1))
742 __is_set_isp_flash(is, ISP_FLASH_COMMAND_DISABLE,
743 ISP_FLASH_REDEYE_DISABLE);
744
745 if (!test_bit(PARAM_ISP_AWB, p_index1))
746 __is_set_isp_awb(is, ISP_AWB_COMMAND_AUTO, 0);
747
748 if (!test_bit(PARAM_ISP_IMAGE_EFFECT, p_index1))
749 __is_set_isp_effect(is, ISP_IMAGE_EFFECT_DISABLE);
750
751 if (!test_bit(PARAM_ISP_ISO, p_index1))
752 __is_set_isp_iso(is, ISP_ISO_COMMAND_AUTO, 0);
753
754 if (!test_bit(PARAM_ISP_ADJUST, p_index1)) {
755 __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_CONTRAST, 0);
756 __is_set_isp_adjust(is,
757 ISP_ADJUST_COMMAND_MANUAL_SATURATION, 0);
758 __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_SHARPNESS, 0);
759 __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_EXPOSURE, 0);
760 __is_set_isp_adjust(is,
761 ISP_ADJUST_COMMAND_MANUAL_BRIGHTNESS, 0);
762 __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_HUE, 0);
763 }
764
765 if (!test_bit(PARAM_ISP_METERING, p_index1)) {
766 __is_set_isp_metering(is, 0, ISP_METERING_COMMAND_CENTER);
767 __is_set_isp_metering(is, 1, 0);
768 __is_set_isp_metering(is, 2, 0);
769 __is_set_isp_metering(is, 3, 0);
770 __is_set_isp_metering(is, 4, 0);
771 }
772
773 if (!test_bit(PARAM_ISP_AFC, p_index1))
774 __is_set_isp_afc(is, ISP_AFC_COMMAND_AUTO, 0);
775
776 isp->otf_output.cmd = OTF_OUTPUT_COMMAND_ENABLE;
777 if (!test_bit(PARAM_ISP_OTF_OUTPUT, p_index1)) {
778 isp->otf_output.width = DEFAULT_PREVIEW_STILL_WIDTH;
779 isp->otf_output.height = DEFAULT_PREVIEW_STILL_HEIGHT;
780 fimc_is_set_param_bit(is, PARAM_ISP_OTF_OUTPUT);
781 }
782 isp->otf_output.format = OTF_OUTPUT_FORMAT_YUV444;
783 isp->otf_output.bitwidth = 12;
784 isp->otf_output.order = 0;
785 isp->otf_output.err = OTF_OUTPUT_ERROR_NONE;
786
787 if (!test_bit(PARAM_ISP_DMA1_OUTPUT, p_index1)) {
788 isp->dma1_output.cmd = DMA_OUTPUT_COMMAND_DISABLE;
789 isp->dma1_output.width = 0;
790 isp->dma1_output.height = 0;
791 isp->dma1_output.format = 0;
792 isp->dma1_output.bitwidth = 0;
793 isp->dma1_output.plane = 0;
794 isp->dma1_output.order = 0;
795 isp->dma1_output.buffer_number = 0;
796 isp->dma1_output.buffer_address = 0;
797 isp->dma1_output.notify_dma_done = 0;
798 isp->dma1_output.dma_out_mask = 0;
799 isp->dma1_output.err = DMA_OUTPUT_ERROR_NONE;
800 fimc_is_set_param_bit(is, PARAM_ISP_DMA1_OUTPUT);
801 }
802
803 if (!test_bit(PARAM_ISP_DMA2_OUTPUT, p_index1)) {
804 isp->dma2_output.cmd = DMA_OUTPUT_COMMAND_DISABLE;
805 isp->dma2_output.width = 0;
806 isp->dma2_output.height = 0;
807 isp->dma2_output.format = 0;
808 isp->dma2_output.bitwidth = 0;
809 isp->dma2_output.plane = 0;
810 isp->dma2_output.order = 0;
811 isp->dma2_output.buffer_number = 0;
812 isp->dma2_output.buffer_address = 0;
813 isp->dma2_output.notify_dma_done = 0;
814 isp->dma2_output.dma_out_mask = 0;
815 isp->dma2_output.err = DMA_OUTPUT_ERROR_NONE;
816 fimc_is_set_param_bit(is, PARAM_ISP_DMA2_OUTPUT);
817 }
818
819 /* Sensor */
820 if (!test_bit(PARAM_SENSOR_FRAME_RATE, p_index1)) {
821 if (is->config_index == 0)
822 __is_set_sensor(is, 0);
823 }
824
825 /* DRC */
826 drc->control.cmd = CONTROL_COMMAND_START;
827 __is_set_drc_control(is, CONTROL_BYPASS_ENABLE);
828
829 drc->otf_input.cmd = OTF_INPUT_COMMAND_ENABLE;
830 if (!test_bit(PARAM_DRC_OTF_INPUT, p_index1)) {
831 drc->otf_input.width = DEFAULT_PREVIEW_STILL_WIDTH;
832 drc->otf_input.height = DEFAULT_PREVIEW_STILL_HEIGHT;
833 fimc_is_set_param_bit(is, PARAM_DRC_OTF_INPUT);
834 }
835 drc->otf_input.format = OTF_INPUT_FORMAT_YUV444;
836 drc->otf_input.bitwidth = 12;
837 drc->otf_input.order = 0;
838 drc->otf_input.err = OTF_INPUT_ERROR_NONE;
839
840 drc->dma_input.cmd = DMA_INPUT_COMMAND_DISABLE;
841 drc->dma_input.width = 0;
842 drc->dma_input.height = 0;
843 drc->dma_input.format = 0;
844 drc->dma_input.bitwidth = 0;
845 drc->dma_input.plane = 0;
846 drc->dma_input.order = 0;
847 drc->dma_input.buffer_number = 0;
848 drc->dma_input.width = 0;
849 drc->dma_input.err = DMA_INPUT_ERROR_NONE;
850 fimc_is_set_param_bit(is, PARAM_DRC_DMA_INPUT);
851
852 drc->otf_output.cmd = OTF_OUTPUT_COMMAND_ENABLE;
853 if (!test_bit(PARAM_DRC_OTF_OUTPUT, p_index1)) {
854 drc->otf_output.width = DEFAULT_PREVIEW_STILL_WIDTH;
855 drc->otf_output.height = DEFAULT_PREVIEW_STILL_HEIGHT;
856 fimc_is_set_param_bit(is, PARAM_DRC_OTF_OUTPUT);
857 }
858 drc->otf_output.format = OTF_OUTPUT_FORMAT_YUV444;
859 drc->otf_output.bitwidth = 8;
860 drc->otf_output.order = 0;
861 drc->otf_output.err = OTF_OUTPUT_ERROR_NONE;
862
863 /* FD */
864 __is_set_fd_control(is, CONTROL_COMMAND_STOP);
865 fd->control.bypass = CONTROL_BYPASS_DISABLE;
866
867 fd->otf_input.cmd = OTF_INPUT_COMMAND_ENABLE;
868 if (!test_bit((PARAM_FD_OTF_INPUT - 32), p_index2)) {
869 fd->otf_input.width = DEFAULT_PREVIEW_STILL_WIDTH;
870 fd->otf_input.height = DEFAULT_PREVIEW_STILL_HEIGHT;
871 fimc_is_set_param_bit(is, PARAM_FD_OTF_INPUT);
872 }
873
874 fd->otf_input.format = OTF_INPUT_FORMAT_YUV444;
875 fd->otf_input.bitwidth = 8;
876 fd->otf_input.order = 0;
877 fd->otf_input.err = OTF_INPUT_ERROR_NONE;
878
879 fd->dma_input.cmd = DMA_INPUT_COMMAND_DISABLE;
880 fd->dma_input.width = 0;
881 fd->dma_input.height = 0;
882 fd->dma_input.format = 0;
883 fd->dma_input.bitwidth = 0;
884 fd->dma_input.plane = 0;
885 fd->dma_input.order = 0;
886 fd->dma_input.buffer_number = 0;
887 fd->dma_input.width = 0;
888 fd->dma_input.err = DMA_INPUT_ERROR_NONE;
889 fimc_is_set_param_bit(is, PARAM_FD_DMA_INPUT);
890
891 __is_set_fd_config_maxface(is, 5);
892 __is_set_fd_config_rollangle(is, FD_CONFIG_ROLL_ANGLE_FULL);
893 __is_set_fd_config_yawangle(is, FD_CONFIG_YAW_ANGLE_45_90);
894 __is_set_fd_config_smilemode(is, FD_CONFIG_SMILE_MODE_DISABLE);
895 __is_set_fd_config_blinkmode(is, FD_CONFIG_BLINK_MODE_DISABLE);
896 __is_set_fd_config_eyedetect(is, FD_CONFIG_EYES_DETECT_ENABLE);
897 __is_set_fd_config_mouthdetect(is, FD_CONFIG_MOUTH_DETECT_DISABLE);
898 __is_set_fd_config_orientation(is, FD_CONFIG_ORIENTATION_DISABLE);
899 __is_set_fd_config_orientation_val(is, 0);
900}
diff --git a/drivers/media/platform/exynos4-is/fimc-is-param.h b/drivers/media/platform/exynos4-is/fimc-is-param.h
new file mode 100644
index 000000000000..f9358c27ae2d
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-is-param.h
@@ -0,0 +1,1020 @@
1/*
2 * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
3 *
4 * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd.
5 *
6 * Authors: Younghwan Joo <yhwan.joo@samsung.com>
7 * Sylwester Nawrocki <s.nawrocki@samsung.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13#ifndef FIMC_IS_PARAM_H_
14#define FIMC_IS_PARAM_H_
15
16#include <linux/compiler.h>
17
18#define FIMC_IS_CONFIG_TIMEOUT 3000 /* ms */
19#define IS_DEFAULT_WIDTH 1280
20#define IS_DEFAULT_HEIGHT 720
21
22#define DEFAULT_PREVIEW_STILL_WIDTH IS_DEFAULT_WIDTH
23#define DEFAULT_PREVIEW_STILL_HEIGHT IS_DEFAULT_HEIGHT
24#define DEFAULT_CAPTURE_STILL_WIDTH IS_DEFAULT_WIDTH
25#define DEFAULT_CAPTURE_STILL_HEIGHT IS_DEFAULT_HEIGHT
26#define DEFAULT_PREVIEW_VIDEO_WIDTH IS_DEFAULT_WIDTH
27#define DEFAULT_PREVIEW_VIDEO_HEIGHT IS_DEFAULT_HEIGHT
28#define DEFAULT_CAPTURE_VIDEO_WIDTH IS_DEFAULT_WIDTH
29#define DEFAULT_CAPTURE_VIDEO_HEIGHT IS_DEFAULT_HEIGHT
30
31#define DEFAULT_PREVIEW_STILL_FRAMERATE 30
32#define DEFAULT_CAPTURE_STILL_FRAMERATE 15
33#define DEFAULT_PREVIEW_VIDEO_FRAMERATE 30
34#define DEFAULT_CAPTURE_VIDEO_FRAMERATE 30
35
36#define FIMC_IS_REGION_VER 124 /* IS REGION VERSION 1.24 */
37#define FIMC_IS_PARAM_SIZE (FIMC_IS_REGION_SIZE + 1)
38#define FIMC_IS_MAGIC_NUMBER 0x01020304
39#define FIMC_IS_PARAM_MAX_SIZE 64 /* in bytes */
40#define FIMC_IS_PARAM_MAX_ENTRIES (FIMC_IS_PARAM_MAX_SIZE / 4)
41
42/* The parameter bitmask bit definitions. */
43enum is_param_bit {
44 PARAM_GLOBAL_SHOTMODE,
45 PARAM_SENSOR_CONTROL,
46 PARAM_SENSOR_OTF_OUTPUT,
47 PARAM_SENSOR_FRAME_RATE,
48 PARAM_BUFFER_CONTROL,
49 PARAM_BUFFER_OTF_INPUT,
50 PARAM_BUFFER_OTF_OUTPUT,
51 PARAM_ISP_CONTROL,
52 PARAM_ISP_OTF_INPUT,
53 PARAM_ISP_DMA1_INPUT,
54 /* 10 */
55 PARAM_ISP_DMA2_INPUT,
56 PARAM_ISP_AA,
57 PARAM_ISP_FLASH,
58 PARAM_ISP_AWB,
59 PARAM_ISP_IMAGE_EFFECT,
60 PARAM_ISP_ISO,
61 PARAM_ISP_ADJUST,
62 PARAM_ISP_METERING,
63 PARAM_ISP_AFC,
64 PARAM_ISP_OTF_OUTPUT,
65 /* 20 */
66 PARAM_ISP_DMA1_OUTPUT,
67 PARAM_ISP_DMA2_OUTPUT,
68 PARAM_DRC_CONTROL,
69 PARAM_DRC_OTF_INPUT,
70 PARAM_DRC_DMA_INPUT,
71 PARAM_DRC_OTF_OUTPUT,
72 PARAM_SCALERC_CONTROL,
73 PARAM_SCALERC_OTF_INPUT,
74 PARAM_SCALERC_IMAGE_EFFECT,
75 PARAM_SCALERC_INPUT_CROP,
76 /* 30 */
77 PARAM_SCALERC_OUTPUT_CROP,
78 PARAM_SCALERC_OTF_OUTPUT,
79 PARAM_SCALERC_DMA_OUTPUT,
80 PARAM_ODC_CONTROL,
81 PARAM_ODC_OTF_INPUT,
82 PARAM_ODC_OTF_OUTPUT,
83 PARAM_DIS_CONTROL,
84 PARAM_DIS_OTF_INPUT,
85 PARAM_DIS_OTF_OUTPUT,
86 PARAM_TDNR_CONTROL,
87 /* 40 */
88 PARAM_TDNR_OTF_INPUT,
89 PARAM_TDNR_1ST_FRAME,
90 PARAM_TDNR_OTF_OUTPUT,
91 PARAM_TDNR_DMA_OUTPUT,
92 PARAM_SCALERP_CONTROL,
93 PARAM_SCALERP_OTF_INPUT,
94 PARAM_SCALERP_IMAGE_EFFECT,
95 PARAM_SCALERP_INPUT_CROP,
96 PARAM_SCALERP_OUTPUT_CROP,
97 PARAM_SCALERP_ROTATION,
98 /* 50 */
99 PARAM_SCALERP_FLIP,
100 PARAM_SCALERP_OTF_OUTPUT,
101 PARAM_SCALERP_DMA_OUTPUT,
102 PARAM_FD_CONTROL,
103 PARAM_FD_OTF_INPUT,
104 PARAM_FD_DMA_INPUT,
105 PARAM_FD_CONFIG,
106};
107
108/* Interrupt map */
109#define FIMC_IS_INT_GENERAL 0
110#define FIMC_IS_INT_FRAME_DONE_ISP 1
111
112/* Input */
113
114#define CONTROL_COMMAND_STOP 0
115#define CONTROL_COMMAND_START 1
116
117#define CONTROL_BYPASS_DISABLE 0
118#define CONTROL_BYPASS_ENABLE 1
119
120#define CONTROL_ERROR_NONE 0
121
122/* OTF (On-The-Fly) input interface commands */
123#define OTF_INPUT_COMMAND_DISABLE 0
124#define OTF_INPUT_COMMAND_ENABLE 1
125
126/* OTF input interface color formats */
127enum oft_input_fmt {
128 OTF_INPUT_FORMAT_BAYER = 0, /* 1 channel */
129 OTF_INPUT_FORMAT_YUV444 = 1, /* 3 channels */
130 OTF_INPUT_FORMAT_YUV422 = 2, /* 3 channels */
131 OTF_INPUT_FORMAT_YUV420 = 3, /* 3 channels */
132 OTF_INPUT_FORMAT_STRGEN_COLORBAR_BAYER = 10,
133 OTF_INPUT_FORMAT_BAYER_DMA = 11,
134};
135
136#define OTF_INPUT_ORDER_BAYER_GR_BG 0
137
138/* OTF input error codes */
139#define OTF_INPUT_ERROR_NONE 0 /* Input setting is done */
140
141/* DMA input commands */
142#define DMA_INPUT_COMMAND_DISABLE 0
143#define DMA_INPUT_COMMAND_ENABLE 1
144
145/* DMA input color formats */
146enum dma_input_fmt {
147 DMA_INPUT_FORMAT_BAYER = 0,
148 DMA_INPUT_FORMAT_YUV444 = 1,
149 DMA_INPUT_FORMAT_YUV422 = 2,
150 DMA_INPUT_FORMAT_YUV420 = 3,
151};
152
153enum dma_input_order {
154 /* (for DMA_INPUT_PLANE_3) */
155 DMA_INPUT_ORDER_NO = 0,
156 /* (only valid at DMA_INPUT_PLANE_2) */
157 DMA_INPUT_ORDER_CBCR = 1,
158 /* (only valid at DMA_INPUT_PLANE_2) */
159 DMA_INPUT_ORDER_CRCB = 2,
160 /* (only valid at DMA_INPUT_PLANE_1 & DMA_INPUT_FORMAT_YUV444) */
161 DMA_INPUT_ORDER_YCBCR = 3,
162 /* (only valid at DMA_INPUT_FORMAT_YUV422 & DMA_INPUT_PLANE_1) */
163 DMA_INPUT_ORDER_YYCBCR = 4,
164 /* (only valid at DMA_INPUT_FORMAT_YUV422 & DMA_INPUT_PLANE_1) */
165 DMA_INPUT_ORDER_YCBYCR = 5,
166 /* (only valid at DMA_INPUT_FORMAT_YUV422 & DMA_INPUT_PLANE_1) */
167 DMA_INPUT_ORDER_YCRYCB = 6,
168 /* (only valid at DMA_INPUT_FORMAT_YUV422 & DMA_INPUT_PLANE_1) */
169 DMA_INPUT_ORDER_CBYCRY = 7,
170 /* (only valid at DMA_INPUT_FORMAT_YUV422 & DMA_INPUT_PLANE_1) */
171 DMA_INPUT_ORDER_CRYCBY = 8,
172 /* (only valid at DMA_INPUT_FORMAT_BAYER) */
173 DMA_INPUT_ORDER_GR_BG = 9
174};
175
176#define DMA_INPUT_ERROR_NONE 0 /* DMA input setting
177 is done */
178/*
179 * Data output parameter definitions
180 */
181#define OTF_OUTPUT_CROP_DISABLE 0
182#define OTF_OUTPUT_CROP_ENABLE 1
183
184#define OTF_OUTPUT_COMMAND_DISABLE 0
185#define OTF_OUTPUT_COMMAND_ENABLE 1
186
187enum otf_output_fmt {
188 OTF_OUTPUT_FORMAT_YUV444 = 1,
189 OTF_OUTPUT_FORMAT_YUV422 = 2,
190 OTF_OUTPUT_FORMAT_YUV420 = 3,
191 OTF_OUTPUT_FORMAT_RGB = 4,
192};
193
194#define OTF_OUTPUT_ORDER_BAYER_GR_BG 0
195
196#define OTF_OUTPUT_ERROR_NONE 0 /* Output Setting is done */
197
198#define DMA_OUTPUT_COMMAND_DISABLE 0
199#define DMA_OUTPUT_COMMAND_ENABLE 1
200
201enum dma_output_fmt {
202 DMA_OUTPUT_FORMAT_BAYER = 0,
203 DMA_OUTPUT_FORMAT_YUV444 = 1,
204 DMA_OUTPUT_FORMAT_YUV422 = 2,
205 DMA_OUTPUT_FORMAT_YUV420 = 3,
206 DMA_OUTPUT_FORMAT_RGB = 4,
207};
208
209enum dma_output_order {
210 DMA_OUTPUT_ORDER_NO = 0,
211 /* for DMA_OUTPUT_PLANE_3 */
212 DMA_OUTPUT_ORDER_CBCR = 1,
213 /* only valid at DMA_INPUT_PLANE_2) */
214 DMA_OUTPUT_ORDER_CRCB = 2,
215 /* only valid at DMA_OUTPUT_PLANE_2) */
216 DMA_OUTPUT_ORDER_YYCBCR = 3,
217 /* only valid at DMA_OUTPUT_FORMAT_YUV422 & DMA_OUTPUT_PLANE_1 */
218 DMA_OUTPUT_ORDER_YCBYCR = 4,
219 /* only valid at DMA_OUTPUT_FORMAT_YUV422 & DMA_OUTPUT_PLANE_1 */
220 DMA_OUTPUT_ORDER_YCRYCB = 5,
221 /* only valid at DMA_OUTPUT_FORMAT_YUV422 & DMA_OUTPUT_PLANE_1 */
222 DMA_OUTPUT_ORDER_CBYCRY = 6,
223 /* only valid at DMA_OUTPUT_FORMAT_YUV422 & DMA_OUTPUT_PLANE_1 */
224 DMA_OUTPUT_ORDER_CRYCBY = 7,
225 /* only valid at DMA_OUTPUT_FORMAT_YUV422 & DMA_OUTPUT_PLANE_1 */
226 DMA_OUTPUT_ORDER_YCBCR = 8,
227 /* only valid at DMA_OUTPUT_FORMAT_YUV444 & DMA_OUPUT_PLANE_1 */
228 DMA_OUTPUT_ORDER_CRYCB = 9,
229 /* only valid at DMA_OUTPUT_FORMAT_YUV444 & DMA_OUPUT_PLANE_1 */
230 DMA_OUTPUT_ORDER_CRCBY = 10,
231 /* only valid at DMA_OUTPUT_FORMAT_YUV444 & DMA_OUPUT_PLANE_1 */
232 DMA_OUTPUT_ORDER_CBYCR = 11,
233 /* only valid at DMA_OUTPUT_FORMAT_YUV444 & DMA_OUPUT_PLANE_1 */
234 DMA_OUTPUT_ORDER_YCRCB = 12,
235 /* only valid at DMA_OUTPUT_FORMAT_YUV444 & DMA_OUPUT_PLANE_1 */
236 DMA_OUTPUT_ORDER_CBCRY = 13,
237 /* only valid at DMA_OUTPUT_FORMAT_YUV444 & DMA_OUPUT_PLANE_1 */
238 DMA_OUTPUT_ORDER_BGR = 14,
239 /* only valid at DMA_OUTPUT_FORMAT_RGB */
240 DMA_OUTPUT_ORDER_GB_BG = 15
241 /* only valid at DMA_OUTPUT_FORMAT_BAYER */
242};
243
244/* enum dma_output_notify_dma_done */
245#define DMA_OUTPUT_NOTIFY_DMA_DONE_DISABLE 0
246#define DMA_OUTPUT_NOTIFY_DMA_DONE_ENABLE 1
247
248/* DMA output error codes */
249#define DMA_OUTPUT_ERROR_NONE 0 /* DMA output setting
250 is done */
251
252/* ---------------------- Global ----------------------------------- */
253#define GLOBAL_SHOTMODE_ERROR_NONE 0 /* shot-mode setting
254 is done */
255/* 3A lock commands */
256#define ISP_AA_COMMAND_START 0
257#define ISP_AA_COMMAND_STOP 1
258
259/* 3A lock target */
260#define ISP_AA_TARGET_AF 1
261#define ISP_AA_TARGET_AE 2
262#define ISP_AA_TARGET_AWB 4
263
264enum isp_af_mode {
265 ISP_AF_MODE_MANUAL = 0,
266 ISP_AF_MODE_SINGLE = 1,
267 ISP_AF_MODE_CONTINUOUS = 2,
268 ISP_AF_MODE_TOUCH = 3,
269 ISP_AF_MODE_SLEEP = 4,
270 ISP_AF_MODE_INIT = 5,
271 ISP_AF_MODE_SET_CENTER_WINDOW = 6,
272 ISP_AF_MODE_SET_TOUCH_WINDOW = 7
273};
274
275/* Face AF commands */
276#define ISP_AF_FACE_DISABLE 0
277#define ISP_AF_FACE_ENABLE 1
278
279/* AF range */
280#define ISP_AF_RANGE_NORMAL 0
281#define ISP_AF_RANGE_MACRO 1
282
283/* AF sleep */
284#define ISP_AF_SLEEP_OFF 0
285#define ISP_AF_SLEEP_ON 1
286
287/* Continuous AF commands */
288#define ISP_AF_CONTINUOUS_DISABLE 0
289#define ISP_AF_CONTINUOUS_ENABLE 1
290
291/* ISP AF error codes */
292#define ISP_AF_ERROR_NONE 0 /* AF mode change is done */
293#define ISP_AF_ERROR_NONE_LOCK_DONE 1 /* AF lock is done */
294
295/* Flash commands */
296#define ISP_FLASH_COMMAND_DISABLE 0
297#define ISP_FLASH_COMMAND_MANUAL_ON 1 /* (forced flash) */
298#define ISP_FLASH_COMMAND_AUTO 2
299#define ISP_FLASH_COMMAND_TORCH 3 /* 3 sec */
300
301/* Flash red-eye commads */
302#define ISP_FLASH_REDEYE_DISABLE 0
303#define ISP_FLASH_REDEYE_ENABLE 1
304
305/* Flash error codes */
306#define ISP_FLASH_ERROR_NONE 0 /* Flash setting is done */
307
308/* -------------------------- AWB ------------------------------------ */
309enum isp_awb_command {
310 ISP_AWB_COMMAND_AUTO = 0,
311 ISP_AWB_COMMAND_ILLUMINATION = 1,
312 ISP_AWB_COMMAND_MANUAL = 2
313};
314
315enum isp_awb_illumination {
316 ISP_AWB_ILLUMINATION_DAYLIGHT = 0,
317 ISP_AWB_ILLUMINATION_CLOUDY = 1,
318 ISP_AWB_ILLUMINATION_TUNGSTEN = 2,
319 ISP_AWB_ILLUMINATION_FLUORESCENT = 3
320};
321
322/* ISP AWN error codes */
323#define ISP_AWB_ERROR_NONE 0 /* AWB setting is done */
324
325/* -------------------------- Effect ----------------------------------- */
326enum isp_imageeffect_command {
327 ISP_IMAGE_EFFECT_DISABLE = 0,
328 ISP_IMAGE_EFFECT_MONOCHROME = 1,
329 ISP_IMAGE_EFFECT_NEGATIVE_MONO = 2,
330 ISP_IMAGE_EFFECT_NEGATIVE_COLOR = 3,
331 ISP_IMAGE_EFFECT_SEPIA = 4
332};
333
334/* Image effect error codes */
335#define ISP_IMAGE_EFFECT_ERROR_NONE 0 /* Image effect setting
336 is done */
337/* ISO commands */
338#define ISP_ISO_COMMAND_AUTO 0
339#define ISP_ISO_COMMAND_MANUAL 1
340
341/* ISO error codes */
342#define ISP_ISO_ERROR_NONE 0 /* ISO setting is done */
343
344/* ISP adjust commands */
345#define ISP_ADJUST_COMMAND_AUTO (0 << 0)
346#define ISP_ADJUST_COMMAND_MANUAL_CONTRAST (1 << 0)
347#define ISP_ADJUST_COMMAND_MANUAL_SATURATION (1 << 1)
348#define ISP_ADJUST_COMMAND_MANUAL_SHARPNESS (1 << 2)
349#define ISP_ADJUST_COMMAND_MANUAL_EXPOSURE (1 << 3)
350#define ISP_ADJUST_COMMAND_MANUAL_BRIGHTNESS (1 << 4)
351#define ISP_ADJUST_COMMAND_MANUAL_HUE (1 << 5)
352#define ISP_ADJUST_COMMAND_MANUAL_ALL 0x7f
353
354/* ISP adjustment error codes */
355#define ISP_ADJUST_ERROR_NONE 0 /* Adjust setting is done */
356
357/*
358 * Exposure metering
359 */
360enum isp_metering_command {
361 ISP_METERING_COMMAND_AVERAGE = 0,
362 ISP_METERING_COMMAND_SPOT = 1,
363 ISP_METERING_COMMAND_MATRIX = 2,
364 ISP_METERING_COMMAND_CENTER = 3
365};
366
367/* ISP metering error codes */
368#define ISP_METERING_ERROR_NONE 0 /* Metering setting is done */
369
370/*
371 * AFC
372 */
373enum isp_afc_command {
374 ISP_AFC_COMMAND_DISABLE = 0,
375 ISP_AFC_COMMAND_AUTO = 1,
376 ISP_AFC_COMMAND_MANUAL = 2,
377};
378
379#define ISP_AFC_MANUAL_50HZ 50
380#define ISP_AFC_MANUAL_60HZ 60
381
382/* ------------------------ SCENE MODE--------------------------------- */
383enum isp_scene_mode {
384 ISP_SCENE_NONE = 0,
385 ISP_SCENE_PORTRAIT = 1,
386 ISP_SCENE_LANDSCAPE = 2,
387 ISP_SCENE_SPORTS = 3,
388 ISP_SCENE_PARTYINDOOR = 4,
389 ISP_SCENE_BEACHSNOW = 5,
390 ISP_SCENE_SUNSET = 6,
391 ISP_SCENE_DAWN = 7,
392 ISP_SCENE_FALL = 8,
393 ISP_SCENE_NIGHT = 9,
394 ISP_SCENE_AGAINSTLIGHTWLIGHT = 10,
395 ISP_SCENE_AGAINSTLIGHTWOLIGHT = 11,
396 ISP_SCENE_FIRE = 12,
397 ISP_SCENE_TEXT = 13,
398 ISP_SCENE_CANDLE = 14
399};
400
401/* AFC error codes */
402#define ISP_AFC_ERROR_NONE 0 /* AFC setting is done */
403
404/* ---------------------------- FD ------------------------------------- */
405enum fd_config_command {
406 FD_CONFIG_COMMAND_MAXIMUM_NUMBER = 0x1,
407 FD_CONFIG_COMMAND_ROLL_ANGLE = 0x2,
408 FD_CONFIG_COMMAND_YAW_ANGLE = 0x4,
409 FD_CONFIG_COMMAND_SMILE_MODE = 0x8,
410 FD_CONFIG_COMMAND_BLINK_MODE = 0x10,
411 FD_CONFIG_COMMAND_EYES_DETECT = 0x20,
412 FD_CONFIG_COMMAND_MOUTH_DETECT = 0x40,
413 FD_CONFIG_COMMAND_ORIENTATION = 0x80,
414 FD_CONFIG_COMMAND_ORIENTATION_VALUE = 0x100
415};
416
417enum fd_config_roll_angle {
418 FD_CONFIG_ROLL_ANGLE_BASIC = 0,
419 FD_CONFIG_ROLL_ANGLE_PRECISE_BASIC = 1,
420 FD_CONFIG_ROLL_ANGLE_SIDES = 2,
421 FD_CONFIG_ROLL_ANGLE_PRECISE_SIDES = 3,
422 FD_CONFIG_ROLL_ANGLE_FULL = 4,
423 FD_CONFIG_ROLL_ANGLE_PRECISE_FULL = 5,
424};
425
426enum fd_config_yaw_angle {
427 FD_CONFIG_YAW_ANGLE_0 = 0,
428 FD_CONFIG_YAW_ANGLE_45 = 1,
429 FD_CONFIG_YAW_ANGLE_90 = 2,
430 FD_CONFIG_YAW_ANGLE_45_90 = 3,
431};
432
433/* Smile mode configuration */
434#define FD_CONFIG_SMILE_MODE_DISABLE 0
435#define FD_CONFIG_SMILE_MODE_ENABLE 1
436
437/* Blink mode configuration */
438#define FD_CONFIG_BLINK_MODE_DISABLE 0
439#define FD_CONFIG_BLINK_MODE_ENABLE 1
440
441/* Eyes detection configuration */
442#define FD_CONFIG_EYES_DETECT_DISABLE 0
443#define FD_CONFIG_EYES_DETECT_ENABLE 1
444
445/* Mouth detection configuration */
446#define FD_CONFIG_MOUTH_DETECT_DISABLE 0
447#define FD_CONFIG_MOUTH_DETECT_ENABLE 1
448
449#define FD_CONFIG_ORIENTATION_DISABLE 0
450#define FD_CONFIG_ORIENTATION_ENABLE 1
451
452struct param_control {
453 u32 cmd;
454 u32 bypass;
455 u32 buffer_address;
456 u32 buffer_size;
457 u32 skip_frames; /* only valid at ISP */
458 u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 6];
459 u32 err;
460};
461
462struct param_otf_input {
463 u32 cmd;
464 u32 width;
465 u32 height;
466 u32 format;
467 u32 bitwidth;
468 u32 order;
469 u32 crop_offset_x;
470 u32 crop_offset_y;
471 u32 crop_width;
472 u32 crop_height;
473 u32 frametime_min;
474 u32 frametime_max;
475 u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 13];
476 u32 err;
477};
478
479struct param_dma_input {
480 u32 cmd;
481 u32 width;
482 u32 height;
483 u32 format;
484 u32 bitwidth;
485 u32 plane;
486 u32 order;
487 u32 buffer_number;
488 u32 buffer_address;
489 u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 10];
490 u32 err;
491};
492
493struct param_otf_output {
494 u32 cmd;
495 u32 width;
496 u32 height;
497 u32 format;
498 u32 bitwidth;
499 u32 order;
500 u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 7];
501 u32 err;
502};
503
504struct param_dma_output {
505 u32 cmd;
506 u32 width;
507 u32 height;
508 u32 format;
509 u32 bitwidth;
510 u32 plane;
511 u32 order;
512 u32 buffer_number;
513 u32 buffer_address;
514 u32 notify_dma_done;
515 u32 dma_out_mask;
516 u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 12];
517 u32 err;
518};
519
520struct param_global_shotmode {
521 u32 cmd;
522 u32 skip_frames;
523 u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 3];
524 u32 err;
525};
526
527struct param_sensor_framerate {
528 u32 frame_rate;
529 u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 2];
530 u32 err;
531};
532
533struct param_isp_aa {
534 u32 cmd;
535 u32 target;
536 u32 mode;
537 u32 scene;
538 u32 sleep;
539 u32 face;
540 u32 touch_x;
541 u32 touch_y;
542 u32 manual_af_setting;
543 u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 10];
544 u32 err;
545};
546
547struct param_isp_flash {
548 u32 cmd;
549 u32 redeye;
550 u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 3];
551 u32 err;
552};
553
554struct param_isp_awb {
555 u32 cmd;
556 u32 illumination;
557 u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 3];
558 u32 err;
559};
560
561struct param_isp_imageeffect {
562 u32 cmd;
563 u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 2];
564 u32 err;
565};
566
567struct param_isp_iso {
568 u32 cmd;
569 u32 value;
570 u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 3];
571 u32 err;
572};
573
574struct param_isp_adjust {
575 u32 cmd;
576 s32 contrast;
577 s32 saturation;
578 s32 sharpness;
579 s32 exposure;
580 s32 brightness;
581 s32 hue;
582 u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 8];
583 u32 err;
584};
585
586struct param_isp_metering {
587 u32 cmd;
588 u32 win_pos_x;
589 u32 win_pos_y;
590 u32 win_width;
591 u32 win_height;
592 u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 6];
593 u32 err;
594};
595
596struct param_isp_afc {
597 u32 cmd;
598 u32 manual;
599 u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 3];
600 u32 err;
601};
602
603struct param_scaler_imageeffect {
604 u32 cmd;
605 u32 arbitrary_cb;
606 u32 arbitrary_cr;
607 u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 4];
608 u32 err;
609};
610
611struct param_scaler_input_crop {
612 u32 cmd;
613 u32 crop_offset_x;
614 u32 crop_offset_y;
615 u32 crop_width;
616 u32 crop_height;
617 u32 in_width;
618 u32 in_height;
619 u32 out_width;
620 u32 out_height;
621 u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 10];
622 u32 err;
623};
624
625struct param_scaler_output_crop {
626 u32 cmd;
627 u32 crop_offset_x;
628 u32 crop_offset_y;
629 u32 crop_width;
630 u32 crop_height;
631 u32 out_format;
632 u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 7];
633 u32 err;
634};
635
636struct param_scaler_rotation {
637 u32 cmd;
638 u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 2];
639 u32 err;
640};
641
642struct param_scaler_flip {
643 u32 cmd;
644 u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 2];
645 u32 err;
646};
647
648struct param_3dnr_1stframe {
649 u32 cmd;
650 u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 2];
651 u32 err;
652};
653
654struct param_fd_config {
655 u32 cmd;
656 u32 max_number;
657 u32 roll_angle;
658 u32 yaw_angle;
659 u32 smile_mode;
660 u32 blink_mode;
661 u32 eye_detect;
662 u32 mouth_detect;
663 u32 orientation;
664 u32 orientation_value;
665 u32 reserved[FIMC_IS_PARAM_MAX_ENTRIES - 11];
666 u32 err;
667};
668
669struct global_param {
670 struct param_global_shotmode shotmode;
671};
672
673struct sensor_param {
674 struct param_control control;
675 struct param_otf_output otf_output;
676 struct param_sensor_framerate frame_rate;
677} __packed;
678
679struct buffer_param {
680 struct param_control control;
681 struct param_otf_input otf_input;
682 struct param_otf_output otf_output;
683} __packed;
684
685struct isp_param {
686 struct param_control control;
687 struct param_otf_input otf_input;
688 struct param_dma_input dma1_input;
689 struct param_dma_input dma2_input;
690 struct param_isp_aa aa;
691 struct param_isp_flash flash;
692 struct param_isp_awb awb;
693 struct param_isp_imageeffect effect;
694 struct param_isp_iso iso;
695 struct param_isp_adjust adjust;
696 struct param_isp_metering metering;
697 struct param_isp_afc afc;
698 struct param_otf_output otf_output;
699 struct param_dma_output dma1_output;
700 struct param_dma_output dma2_output;
701} __packed;
702
703struct drc_param {
704 struct param_control control;
705 struct param_otf_input otf_input;
706 struct param_dma_input dma_input;
707 struct param_otf_output otf_output;
708} __packed;
709
710struct scalerc_param {
711 struct param_control control;
712 struct param_otf_input otf_input;
713 struct param_scaler_imageeffect effect;
714 struct param_scaler_input_crop input_crop;
715 struct param_scaler_output_crop output_crop;
716 struct param_otf_output otf_output;
717 struct param_dma_output dma_output;
718} __packed;
719
720struct odc_param {
721 struct param_control control;
722 struct param_otf_input otf_input;
723 struct param_otf_output otf_output;
724} __packed;
725
726struct dis_param {
727 struct param_control control;
728 struct param_otf_output otf_input;
729 struct param_otf_output otf_output;
730} __packed;
731
732struct tdnr_param {
733 struct param_control control;
734 struct param_otf_input otf_input;
735 struct param_3dnr_1stframe frame;
736 struct param_otf_output otf_output;
737 struct param_dma_output dma_output;
738} __packed;
739
740struct scalerp_param {
741 struct param_control control;
742 struct param_otf_input otf_input;
743 struct param_scaler_imageeffect effect;
744 struct param_scaler_input_crop input_crop;
745 struct param_scaler_output_crop output_crop;
746 struct param_scaler_rotation rotation;
747 struct param_scaler_flip flip;
748 struct param_otf_output otf_output;
749 struct param_dma_output dma_output;
750} __packed;
751
752struct fd_param {
753 struct param_control control;
754 struct param_otf_input otf_input;
755 struct param_dma_input dma_input;
756 struct param_fd_config config;
757} __packed;
758
759struct is_param_region {
760 struct global_param global;
761 struct sensor_param sensor;
762 struct buffer_param buf;
763 struct isp_param isp;
764 struct drc_param drc;
765 struct scalerc_param scalerc;
766 struct odc_param odc;
767 struct dis_param dis;
768 struct tdnr_param tdnr;
769 struct scalerp_param scalerp;
770 struct fd_param fd;
771} __packed;
772
773#define NUMBER_OF_GAMMA_CURVE_POINTS 32
774
775struct is_tune_sensor {
776 u32 exposure;
777 u32 analog_gain;
778 u32 frame_rate;
779 u32 actuator_position;
780};
781
782struct is_tune_gammacurve {
783 u32 num_pts_x[NUMBER_OF_GAMMA_CURVE_POINTS];
784 u32 num_pts_y_r[NUMBER_OF_GAMMA_CURVE_POINTS];
785 u32 num_pts_y_g[NUMBER_OF_GAMMA_CURVE_POINTS];
786 u32 num_pts_y_b[NUMBER_OF_GAMMA_CURVE_POINTS];
787};
788
789struct is_tune_isp {
790 /* Brightness level: range 0...100, default 7. */
791 u32 brightness_level;
792 /* Contrast level: range -127...127, default 0. */
793 s32 contrast_level;
794 /* Saturation level: range -127...127, default 0. */
795 s32 saturation_level;
796 s32 gamma_level;
797 struct is_tune_gammacurve gamma_curve[4];
798 /* Hue: range -127...127, default 0. */
799 s32 hue;
800 /* Sharpness blur: range -127...127, default 0. */
801 s32 sharpness_blur;
802 /* Despeckle : range -127~127, default : 0 */
803 s32 despeckle;
804 /* Edge color supression: range -127...127, default 0. */
805 s32 edge_color_supression;
806 /* Noise reduction: range -127...127, default 0. */
807 s32 noise_reduction;
808 /* (32 * 4 + 9) * 4 = 548 bytes */
809} __packed;
810
811struct is_tune_region {
812 struct is_tune_sensor sensor;
813 struct is_tune_isp isp;
814} __packed;
815
816struct rational {
817 u32 num;
818 u32 den;
819};
820
821struct srational {
822 s32 num;
823 s32 den;
824};
825
826#define FLASH_FIRED_SHIFT 0
827#define FLASH_NOT_FIRED 0
828#define FLASH_FIRED 1
829
830#define FLASH_STROBE_SHIFT 1
831#define FLASH_STROBE_NO_DETECTION 0
832#define FLASH_STROBE_RESERVED 1
833#define FLASH_STROBE_RETURN_LIGHT_NOT_DETECTED 2
834#define FLASH_STROBE_RETURN_LIGHT_DETECTED 3
835
836#define FLASH_MODE_SHIFT 3
837#define FLASH_MODE_UNKNOWN 0
838#define FLASH_MODE_COMPULSORY_FLASH_FIRING 1
839#define FLASH_MODE_COMPULSORY_FLASH_SUPPRESSION 2
840#define FLASH_MODE_AUTO_MODE 3
841
842#define FLASH_FUNCTION_SHIFT 5
843#define FLASH_FUNCTION_PRESENT 0
844#define FLASH_FUNCTION_NONE 1
845
846#define FLASH_RED_EYE_SHIFT 6
847#define FLASH_RED_EYE_DISABLED 0
848#define FLASH_RED_EYE_SUPPORTED 1
849
850enum apex_aperture_value {
851 F1_0 = 0,
852 F1_4 = 1,
853 F2_0 = 2,
854 F2_8 = 3,
855 F4_0 = 4,
856 F5_6 = 5,
857 F8_9 = 6,
858 F11_0 = 7,
859 F16_0 = 8,
860 F22_0 = 9,
861 F32_0 = 10,
862};
863
864struct exif_attribute {
865 struct rational exposure_time;
866 struct srational shutter_speed;
867 u32 iso_speed_rating;
868 u32 flash;
869 struct srational brightness;
870} __packed;
871
872struct is_frame_header {
873 u32 valid;
874 u32 bad_mark;
875 u32 captured;
876 u32 frame_number;
877 struct exif_attribute exif;
878} __packed;
879
880struct is_fd_rect {
881 u32 offset_x;
882 u32 offset_y;
883 u32 width;
884 u32 height;
885};
886
887struct is_face_marker {
888 u32 frame_number;
889 struct is_fd_rect face;
890 struct is_fd_rect left_eye;
891 struct is_fd_rect right_eye;
892 struct is_fd_rect mouth;
893 u32 roll_angle;
894 u32 yaw_angle;
895 u32 confidence;
896 s32 smile_level;
897 s32 blink_level;
898} __packed;
899
900#define MAX_FRAME_COUNT 8
901#define MAX_FRAME_COUNT_PREVIEW 4
902#define MAX_FRAME_COUNT_CAPTURE 1
903#define MAX_FACE_COUNT 16
904#define MAX_SHARED_COUNT 500
905
906struct is_region {
907 struct is_param_region parameter;
908 struct is_tune_region tune;
909 struct is_frame_header header[MAX_FRAME_COUNT];
910 struct is_face_marker face[MAX_FACE_COUNT];
911 u32 shared[MAX_SHARED_COUNT];
912} __packed;
913
914struct is_debug_frame_descriptor {
915 u32 sensor_frame_time;
916 u32 sensor_exposure_time;
917 s32 sensor_analog_gain;
918 /* monitor for AA */
919 u32 req_lei;
920
921 u32 next_next_lei_exp;
922 u32 next_next_lei_a_gain;
923 u32 next_next_lei_d_gain;
924 u32 next_next_lei_statlei;
925 u32 next_next_lei_lei;
926
927 u32 dummy0;
928};
929
930#define MAX_FRAMEDESCRIPTOR_CONTEXT_NUM (30*20) /* 600 frames */
931#define MAX_VERSION_DISPLAY_BUF 32
932
933struct is_share_region {
934 u32 frame_time;
935 u32 exposure_time;
936 s32 analog_gain;
937
938 u32 r_gain;
939 u32 g_gain;
940 u32 b_gain;
941
942 u32 af_position;
943 u32 af_status;
944 /* 0 : SIRC_ISP_CAMERA_AUTOFOCUSMESSAGE_NOMESSAGE */
945 /* 1 : SIRC_ISP_CAMERA_AUTOFOCUSMESSAGE_REACHED */
946 /* 2 : SIRC_ISP_CAMERA_AUTOFOCUSMESSAGE_UNABLETOREACH */
947 /* 3 : SIRC_ISP_CAMERA_AUTOFOCUSMESSAGE_LOST */
948 /* default : unknown */
949 u32 af_scene_type;
950
951 u32 frame_descp_onoff_control;
952 u32 frame_descp_update_done;
953 u32 frame_descp_idx;
954 u32 frame_descp_max_idx;
955 struct is_debug_frame_descriptor
956 dbg_frame_descp_ctx[MAX_FRAMEDESCRIPTOR_CONTEXT_NUM];
957
958 u32 chip_id;
959 u32 chip_rev_no;
960 u8 isp_fw_ver_no[MAX_VERSION_DISPLAY_BUF];
961 u8 isp_fw_ver_date[MAX_VERSION_DISPLAY_BUF];
962 u8 sirc_sdk_ver_no[MAX_VERSION_DISPLAY_BUF];
963 u8 sirc_sdk_rev_no[MAX_VERSION_DISPLAY_BUF];
964 u8 sirc_sdk_rev_date[MAX_VERSION_DISPLAY_BUF];
965} __packed;
966
967struct is_debug_control {
968 u32 write_point; /* 0~ 500KB boundary */
969 u32 assert_flag; /* 0: Not invoked, 1: Invoked */
970 u32 pabort_flag; /* 0: Not invoked, 1: Invoked */
971 u32 dabort_flag; /* 0: Not invoked, 1: Invoked */
972};
973
974struct sensor_open_extended {
975 u32 actuator_type;
976 u32 mclk;
977 u32 mipi_lane_num;
978 u32 mipi_speed;
979 /* Skip setfile loading when fast_open_sensor is not 0 */
980 u32 fast_open_sensor;
981 /* Activating sensor self calibration mode (6A3) */
982 u32 self_calibration_mode;
983 /* This field is to adjust I2c clock based on ACLK200 */
984 /* This value is varied in case of rev 0.2 */
985 u32 i2c_sclk;
986};
987
988struct fimc_is;
989
990int fimc_is_hw_get_sensor_max_framerate(struct fimc_is *is);
991void fimc_is_set_initial_params(struct fimc_is *is);
992unsigned int __get_pending_param_count(struct fimc_is *is);
993
994int __is_hw_update_params(struct fimc_is *is);
995void __is_get_frame_size(struct fimc_is *is, struct v4l2_mbus_framefmt *mf);
996void __is_set_frame_size(struct fimc_is *is, struct v4l2_mbus_framefmt *mf);
997void __is_set_sensor(struct fimc_is *is, int fps);
998void __is_set_isp_aa_ae(struct fimc_is *is);
999void __is_set_isp_flash(struct fimc_is *is, u32 cmd, u32 redeye);
1000void __is_set_isp_awb(struct fimc_is *is, u32 cmd, u32 val);
1001void __is_set_isp_effect(struct fimc_is *is, u32 cmd);
1002void __is_set_isp_iso(struct fimc_is *is, u32 cmd, u32 val);
1003void __is_set_isp_adjust(struct fimc_is *is, u32 cmd, u32 val);
1004void __is_set_isp_metering(struct fimc_is *is, u32 id, u32 val);
1005void __is_set_isp_afc(struct fimc_is *is, u32 cmd, u32 val);
1006void __is_set_drc_control(struct fimc_is *is, u32 val);
1007void __is_set_fd_control(struct fimc_is *is, u32 val);
1008void __is_set_fd_config_maxface(struct fimc_is *is, u32 val);
1009void __is_set_fd_config_rollangle(struct fimc_is *is, u32 val);
1010void __is_set_fd_config_yawangle(struct fimc_is *is, u32 val);
1011void __is_set_fd_config_smilemode(struct fimc_is *is, u32 val);
1012void __is_set_fd_config_blinkmode(struct fimc_is *is, u32 val);
1013void __is_set_fd_config_eyedetect(struct fimc_is *is, u32 val);
1014void __is_set_fd_config_mouthdetect(struct fimc_is *is, u32 val);
1015void __is_set_fd_config_orientation(struct fimc_is *is, u32 val);
1016void __is_set_fd_config_orientation_val(struct fimc_is *is, u32 val);
1017void __is_set_isp_aa_af_mode(struct fimc_is *is, int cmd);
1018void __is_set_isp_aa_af_start_stop(struct fimc_is *is, int cmd);
1019
1020#endif
diff --git a/drivers/media/platform/exynos4-is/fimc-is-regs.c b/drivers/media/platform/exynos4-is/fimc-is-regs.c
new file mode 100644
index 000000000000..b0ff67bc1b05
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-is-regs.c
@@ -0,0 +1,243 @@
1/*
2 * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
3 *
4 * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd.
5 *
6 * Authors: Younghwan Joo <yhwan.joo@samsung.com>
7 * Sylwester Nawrocki <s.nawrocki@samsung.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13#include <linux/delay.h>
14
15#include "fimc-is.h"
16#include "fimc-is-command.h"
17#include "fimc-is-regs.h"
18#include "fimc-is-sensor.h"
19
20void fimc_is_fw_clear_irq1(struct fimc_is *is, unsigned int nr)
21{
22 mcuctl_write(1UL << nr, is, MCUCTL_REG_INTCR1);
23}
24
25void fimc_is_fw_clear_irq2(struct fimc_is *is)
26{
27 u32 cfg = mcuctl_read(is, MCUCTL_REG_INTSR2);
28 mcuctl_write(cfg, is, MCUCTL_REG_INTCR2);
29}
30
31void fimc_is_hw_set_intgr0_gd0(struct fimc_is *is)
32{
33 mcuctl_write(INTGR0_INTGD(0), is, MCUCTL_REG_INTGR0);
34}
35
36int fimc_is_hw_wait_intsr0_intsd0(struct fimc_is *is)
37{
38 unsigned int timeout = 2000;
39 u32 cfg, status;
40
41 cfg = mcuctl_read(is, MCUCTL_REG_INTSR0);
42 status = INTSR0_GET_INTSD(0, cfg);
43
44 while (status) {
45 cfg = mcuctl_read(is, MCUCTL_REG_INTSR0);
46 status = INTSR0_GET_INTSD(0, cfg);
47 if (timeout == 0) {
48 dev_warn(&is->pdev->dev, "%s timeout\n",
49 __func__);
50 return -ETIME;
51 }
52 timeout--;
53 udelay(1);
54 }
55 return 0;
56}
57
58int fimc_is_hw_wait_intmsr0_intmsd0(struct fimc_is *is)
59{
60 unsigned int timeout = 2000;
61 u32 cfg, status;
62
63 cfg = mcuctl_read(is, MCUCTL_REG_INTMSR0);
64 status = INTMSR0_GET_INTMSD(0, cfg);
65
66 while (status) {
67 cfg = mcuctl_read(is, MCUCTL_REG_INTMSR0);
68 status = INTMSR0_GET_INTMSD(0, cfg);
69 if (timeout == 0) {
70 dev_warn(&is->pdev->dev, "%s timeout\n",
71 __func__);
72 return -ETIME;
73 }
74 timeout--;
75 udelay(1);
76 }
77 return 0;
78}
79
80int fimc_is_hw_set_param(struct fimc_is *is)
81{
82 struct chain_config *config = &is->config[is->config_index];
83 unsigned int param_count = __get_pending_param_count(is);
84
85 fimc_is_hw_wait_intmsr0_intmsd0(is);
86
87 mcuctl_write(HIC_SET_PARAMETER, is, MCUCTL_REG_ISSR(0));
88 mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
89 mcuctl_write(is->config_index, is, MCUCTL_REG_ISSR(2));
90
91 mcuctl_write(param_count, is, MCUCTL_REG_ISSR(3));
92 mcuctl_write(config->p_region_index1, is, MCUCTL_REG_ISSR(4));
93 mcuctl_write(config->p_region_index2, is, MCUCTL_REG_ISSR(5));
94
95 fimc_is_hw_set_intgr0_gd0(is);
96 return 0;
97}
98
99int fimc_is_hw_set_tune(struct fimc_is *is)
100{
101 fimc_is_hw_wait_intmsr0_intmsd0(is);
102
103 mcuctl_write(HIC_SET_TUNE, is, MCUCTL_REG_ISSR(0));
104 mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
105 mcuctl_write(is->h2i_cmd.entry_id, is, MCUCTL_REG_ISSR(2));
106
107 fimc_is_hw_set_intgr0_gd0(is);
108 return 0;
109}
110
111#define FIMC_IS_MAX_PARAMS 4
112
113int fimc_is_hw_get_params(struct fimc_is *is, unsigned int num_args)
114{
115 int i;
116
117 if (num_args > FIMC_IS_MAX_PARAMS)
118 return -EINVAL;
119
120 is->i2h_cmd.num_args = num_args;
121
122 for (i = 0; i < FIMC_IS_MAX_PARAMS; i++) {
123 if (i < num_args)
124 is->i2h_cmd.args[i] = mcuctl_read(is,
125 MCUCTL_REG_ISSR(12 + i));
126 else
127 is->i2h_cmd.args[i] = 0;
128 }
129 return 0;
130}
131
132void fimc_is_hw_set_sensor_num(struct fimc_is *is)
133{
134 pr_debug("setting sensor index to: %d\n", is->sensor_index);
135
136 mcuctl_write(IH_REPLY_DONE, is, MCUCTL_REG_ISSR(0));
137 mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
138 mcuctl_write(IHC_GET_SENSOR_NUM, is, MCUCTL_REG_ISSR(2));
139 mcuctl_write(FIMC_IS_SENSOR_NUM, is, MCUCTL_REG_ISSR(3));
140}
141
142void fimc_is_hw_close_sensor(struct fimc_is *is, unsigned int index)
143{
144 if (is->sensor_index != index)
145 return;
146
147 fimc_is_hw_wait_intmsr0_intmsd0(is);
148 mcuctl_write(HIC_CLOSE_SENSOR, is, MCUCTL_REG_ISSR(0));
149 mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
150 mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(2));
151 fimc_is_hw_set_intgr0_gd0(is);
152}
153
154void fimc_is_hw_get_setfile_addr(struct fimc_is *is)
155{
156 fimc_is_hw_wait_intmsr0_intmsd0(is);
157 mcuctl_write(HIC_GET_SET_FILE_ADDR, is, MCUCTL_REG_ISSR(0));
158 mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
159 fimc_is_hw_set_intgr0_gd0(is);
160}
161
162void fimc_is_hw_load_setfile(struct fimc_is *is)
163{
164 fimc_is_hw_wait_intmsr0_intmsd0(is);
165 mcuctl_write(HIC_LOAD_SET_FILE, is, MCUCTL_REG_ISSR(0));
166 mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
167 fimc_is_hw_set_intgr0_gd0(is);
168}
169
170int fimc_is_hw_change_mode(struct fimc_is *is)
171{
172 const u8 cmd[] = {
173 HIC_PREVIEW_STILL, HIC_PREVIEW_VIDEO,
174 HIC_CAPTURE_STILL, HIC_CAPTURE_VIDEO,
175 };
176
177 if (WARN_ON(is->config_index > ARRAY_SIZE(cmd)))
178 return -EINVAL;
179
180 mcuctl_write(cmd[is->config_index], is, MCUCTL_REG_ISSR(0));
181 mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
182 mcuctl_write(is->setfile.sub_index, is, MCUCTL_REG_ISSR(2));
183 fimc_is_hw_set_intgr0_gd0(is);
184 return 0;
185}
186
187void fimc_is_hw_stream_on(struct fimc_is *is)
188{
189 fimc_is_hw_wait_intmsr0_intmsd0(is);
190 mcuctl_write(HIC_STREAM_ON, is, MCUCTL_REG_ISSR(0));
191 mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
192 mcuctl_write(0, is, MCUCTL_REG_ISSR(2));
193 fimc_is_hw_set_intgr0_gd0(is);
194}
195
196void fimc_is_hw_stream_off(struct fimc_is *is)
197{
198 fimc_is_hw_wait_intmsr0_intmsd0(is);
199 mcuctl_write(HIC_STREAM_OFF, is, MCUCTL_REG_ISSR(0));
200 mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
201 fimc_is_hw_set_intgr0_gd0(is);
202}
203
204void fimc_is_hw_subip_power_off(struct fimc_is *is)
205{
206 fimc_is_hw_wait_intmsr0_intmsd0(is);
207 mcuctl_write(HIC_POWER_DOWN, is, MCUCTL_REG_ISSR(0));
208 mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
209 fimc_is_hw_set_intgr0_gd0(is);
210}
211
212int fimc_is_itf_s_param(struct fimc_is *is, bool update)
213{
214 int ret;
215
216 if (update)
217 __is_hw_update_params(is);
218
219 fimc_is_mem_barrier();
220
221 clear_bit(IS_ST_BLOCK_CMD_CLEARED, &is->state);
222 fimc_is_hw_set_param(is);
223 ret = fimc_is_wait_event(is, IS_ST_BLOCK_CMD_CLEARED, 1,
224 FIMC_IS_CONFIG_TIMEOUT);
225 if (ret < 0)
226 dev_err(&is->pdev->dev, "%s() timeout\n", __func__);
227
228 return ret;
229}
230
231int fimc_is_itf_mode_change(struct fimc_is *is)
232{
233 int ret;
234
235 clear_bit(IS_ST_CHANGE_MODE, &is->state);
236 fimc_is_hw_change_mode(is);
237 ret = fimc_is_wait_event(is, IS_ST_CHANGE_MODE, 1,
238 FIMC_IS_CONFIG_TIMEOUT);
239 if (!ret < 0)
240 dev_err(&is->pdev->dev, "%s(): mode change (%d) timeout\n",
241 __func__, is->config_index);
242 return ret;
243}
diff --git a/drivers/media/platform/exynos4-is/fimc-is-regs.h b/drivers/media/platform/exynos4-is/fimc-is-regs.h
new file mode 100644
index 000000000000..5fa2fda46742
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-is-regs.h
@@ -0,0 +1,164 @@
1/*
2 * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
3 *
4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
5 *
6 * Authors: Sylwester Nawrocki <s.nawrocki@samsung.com>
7 * Younghwan Joo <yhwan.joo@samsung.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13#ifndef FIMC_IS_REG_H_
14#define FIMC_IS_REG_H_
15
16/* WDT_ISP register */
17#define REG_WDT_ISP 0x00170000
18
19/* MCUCTL registers base offset */
20#define MCUCTL_BASE 0x00180000
21
22/* MCU Controller Register */
23#define MCUCTL_REG_MCUCTRL (MCUCTL_BASE + 0x00)
24#define MCUCTRL_MSWRST (1 << 0)
25
26/* Boot Base Offset Address Register */
27#define MCUCTL_REG_BBOAR (MCUCTL_BASE + 0x04)
28
29/* Interrupt Generation Register 0 from Host CPU to VIC */
30#define MCUCTL_REG_INTGR0 (MCUCTL_BASE + 0x08)
31/* __n = 0...9 */
32#define INTGR0_INTGC(__n) (1 << ((__n) + 16))
33/* __n = 0...5 */
34#define INTGR0_INTGD(__n) (1 << (__n))
35
36/* Interrupt Clear Register 0 from Host CPU to VIC */
37#define MCUCTL_REG_INTCR0 (MCUCTL_BASE + 0x0c)
38/* __n = 0...9 */
39#define INTCR0_INTGC(__n) (1 << ((__n) + 16))
40/* __n = 0...5 */
41#define INTCR0_INTCD(__n) (1 << ((__n) + 16))
42
43/* Interrupt Mask Register 0 from Host CPU to VIC */
44#define MCUCTL_REG_INTMR0 (MCUCTL_BASE + 0x10)
45/* __n = 0...9 */
46#define INTMR0_INTMC(__n) (1 << ((__n) + 16))
47/* __n = 0...5 */
48#define INTMR0_INTMD(__n) (1 << (__n))
49
50/* Interrupt Status Register 0 from Host CPU to VIC */
51#define MCUCTL_REG_INTSR0 (MCUCTL_BASE + 0x14)
52/* __n (bit number) = 0...4 */
53#define INTSR0_GET_INTSD(x, __n) (((x) >> (__n)) & 0x1)
54/* __n (bit number) = 0...9 */
55#define INTSR0_GET_INTSC(x, __n) (((x) >> ((__n) + 16)) & 0x1)
56
57/* Interrupt Mask Status Register 0 from Host CPU to VIC */
58#define MCUCTL_REG_INTMSR0 (MCUCTL_BASE + 0x18)
59/* __n (bit number) = 0...4 */
60#define INTMSR0_GET_INTMSD(x, __n) (((x) >> (__n)) & 0x1)
61/* __n (bit number) = 0...9 */
62#define INTMSR0_GET_INTMSC(x, __n) (((x) >> ((__n) + 16)) & 0x1)
63
64/* Interrupt Generation Register 1 from ISP CPU to Host IC */
65#define MCUCTL_REG_INTGR1 (MCUCTL_BASE + 0x1c)
66/* __n = 0...9 */
67#define INTGR1_INTGC(__n) (1 << (__n))
68
69/* Interrupt Clear Register 1 from ISP CPU to Host IC */
70#define MCUCTL_REG_INTCR1 (MCUCTL_BASE + 0x20)
71/* __n = 0...9 */
72#define INTCR1_INTCC(__n) (1 << (__n))
73
74/* Interrupt Mask Register 1 from ISP CPU to Host IC */
75#define MCUCTL_REG_INTMR1 (MCUCTL_BASE + 0x24)
76/* __n = 0...9 */
77#define INTMR1_INTMC(__n) (1 << (__n))
78
79/* Interrupt Status Register 1 from ISP CPU to Host IC */
80#define MCUCTL_REG_INTSR1 (MCUCTL_BASE + 0x28)
81/* Interrupt Mask Status Register 1 from ISP CPU to Host IC */
82#define MCUCTL_REG_INTMSR1 (MCUCTL_BASE + 0x2c)
83
84/* Interrupt Clear Register 2 from ISP BLK's interrupts to Host IC */
85#define MCUCTL_REG_INTCR2 (MCUCTL_BASE + 0x30)
86/* __n = 0...5 */
87#define INTCR2_INTCC(__n) (1 << ((__n) + 16))
88
89/* Interrupt Mask Register 2 from ISP BLK's interrupts to Host IC */
90#define MCUCTL_REG_INTMR2 (MCUCTL_BASE + 0x34)
91/* __n = 0...25 */
92#define INTMR2_INTMCIS(__n) (1 << (__n))
93
94/* Interrupt Status Register 2 from ISP BLK's interrupts to Host IC */
95#define MCUCTL_REG_INTSR2 (MCUCTL_BASE + 0x38)
96/* Interrupt Mask Status Register 2 from ISP BLK's interrupts to Host IC */
97#define MCUCTL_REG_INTMSR2 (MCUCTL_BASE + 0x3c)
98
99/* General Purpose Output Control Register (0~17) */
100#define MCUCTL_REG_GPOCTLR (MCUCTL_BASE + 0x40)
101/* __n = 0...17 */
102#define GPOCTLR_GPOG(__n) (1 << (__n))
103
104/* General Purpose Pad Output Enable Register (0~17) */
105#define MCUCTL_REG_GPOENCTLR (MCUCTL_BASE + 0x44)
106/* __n = 0...17 */
107#define GPOENCTLR_GPOEN(__n) (1 << (__n))
108
109/* General Purpose Input Control Register (0~17) */
110#define MCUCTL_REG_GPICTLR (MCUCTL_BASE + 0x48)
111
112/* Shared registers between ISP CPU and the host CPU - ISSRxx */
113
114/* ISSR(1): Command Host -> IS */
115/* ISSR(1): Sensor ID for Command, ISSR2...5 = Parameter 1...4 */
116
117/* ISSR(10): Reply IS -> Host */
118/* ISSR(11): Sensor ID for Reply, ISSR12...15 = Parameter 1...4 */
119
120/* ISSR(20): ISP_FRAME_DONE : SENSOR ID */
121/* ISSR(21): ISP_FRAME_DONE : PARAMETER 1 */
122
123/* ISSR(24): SCALERC_FRAME_DONE : SENSOR ID */
124/* ISSR(25): SCALERC_FRAME_DONE : PARAMETER 1 */
125
126/* ISSR(28): 3DNR_FRAME_DONE : SENSOR ID */
127/* ISSR(29): 3DNR_FRAME_DONE : PARAMETER 1 */
128
129/* ISSR(32): SCALERP_FRAME_DONE : SENSOR ID */
130/* ISSR(33): SCALERP_FRAME_DONE : PARAMETER 1 */
131
132/* __n = 0...63 */
133#define MCUCTL_REG_ISSR(__n) (MCUCTL_BASE + 0x80 + ((__n) * 4))
134
135/* PMU ISP register offsets */
136#define REG_CMU_RESET_ISP_SYS_PWR_REG 0x1174
137#define REG_CMU_SYSCLK_ISP_SYS_PWR_REG 0x13b8
138#define REG_PMU_ISP_ARM_SYS 0x1050
139#define REG_PMU_ISP_ARM_CONFIGURATION 0x2280
140#define REG_PMU_ISP_ARM_STATUS 0x2284
141#define REG_PMU_ISP_ARM_OPTION 0x2288
142
143void fimc_is_fw_clear_irq1(struct fimc_is *is, unsigned int bit);
144void fimc_is_fw_clear_irq2(struct fimc_is *is);
145int fimc_is_hw_get_params(struct fimc_is *is, unsigned int num);
146
147void fimc_is_hw_set_intgr0_gd0(struct fimc_is *is);
148int fimc_is_hw_wait_intsr0_intsd0(struct fimc_is *is);
149int fimc_is_hw_wait_intmsr0_intmsd0(struct fimc_is *is);
150void fimc_is_hw_set_sensor_num(struct fimc_is *is);
151void fimc_is_hw_stream_on(struct fimc_is *is);
152void fimc_is_hw_stream_off(struct fimc_is *is);
153int fimc_is_hw_set_param(struct fimc_is *is);
154int fimc_is_hw_change_mode(struct fimc_is *is);
155
156void fimc_is_hw_close_sensor(struct fimc_is *is, unsigned int index);
157void fimc_is_hw_get_setfile_addr(struct fimc_is *is);
158void fimc_is_hw_load_setfile(struct fimc_is *is);
159void fimc_is_hw_subip_power_off(struct fimc_is *is);
160
161int fimc_is_itf_s_param(struct fimc_is *is, bool update);
162int fimc_is_itf_mode_change(struct fimc_is *is);
163
164#endif /* FIMC_IS_REG_H_ */
diff --git a/drivers/media/platform/exynos4-is/fimc-is-sensor.c b/drivers/media/platform/exynos4-is/fimc-is-sensor.c
new file mode 100644
index 000000000000..6647421e5d3a
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-is-sensor.c
@@ -0,0 +1,305 @@
1/*
2 * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
3 *
4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
5 *
6 * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12#include <linux/delay.h>
13#include <linux/device.h>
14#include <linux/errno.h>
15#include <linux/gpio.h>
16#include <linux/i2c.h>
17#include <linux/kernel.h>
18#include <linux/module.h>
19#include <linux/of_gpio.h>
20#include <linux/pm_runtime.h>
21#include <linux/regulator/consumer.h>
22#include <linux/slab.h>
23#include <media/v4l2-subdev.h>
24
25#include "fimc-is.h"
26#include "fimc-is-sensor.h"
27
28#define DRIVER_NAME "FIMC-IS-SENSOR"
29
30static const char * const sensor_supply_names[] = {
31 "svdda",
32 "svddio",
33};
34
35static const struct v4l2_mbus_framefmt fimc_is_sensor_formats[] = {
36 {
37 .code = V4L2_MBUS_FMT_SGRBG10_1X10,
38 .colorspace = V4L2_COLORSPACE_SRGB,
39 .field = V4L2_FIELD_NONE,
40 }
41};
42
43static const struct v4l2_mbus_framefmt *find_sensor_format(
44 struct v4l2_mbus_framefmt *mf)
45{
46 int i;
47
48 for (i = 0; i < ARRAY_SIZE(fimc_is_sensor_formats); i++)
49 if (mf->code == fimc_is_sensor_formats[i].code)
50 return &fimc_is_sensor_formats[i];
51
52 return &fimc_is_sensor_formats[0];
53}
54
55static int fimc_is_sensor_enum_mbus_code(struct v4l2_subdev *sd,
56 struct v4l2_subdev_fh *fh,
57 struct v4l2_subdev_mbus_code_enum *code)
58{
59 if (code->index >= ARRAY_SIZE(fimc_is_sensor_formats))
60 return -EINVAL;
61
62 code->code = fimc_is_sensor_formats[code->index].code;
63 return 0;
64}
65
66static void fimc_is_sensor_try_format(struct fimc_is_sensor *sensor,
67 struct v4l2_mbus_framefmt *mf)
68{
69 const struct sensor_drv_data *dd = sensor->drvdata;
70 const struct v4l2_mbus_framefmt *fmt;
71
72 fmt = find_sensor_format(mf);
73 mf->code = fmt->code;
74 v4l_bound_align_image(&mf->width, 16 + 8, dd->width, 0,
75 &mf->height, 12 + 8, dd->height, 0, 0);
76}
77
78static struct v4l2_mbus_framefmt *__fimc_is_sensor_get_format(
79 struct fimc_is_sensor *sensor, struct v4l2_subdev_fh *fh,
80 u32 pad, enum v4l2_subdev_format_whence which)
81{
82 if (which == V4L2_SUBDEV_FORMAT_TRY)
83 return fh ? v4l2_subdev_get_try_format(fh, pad) : NULL;
84
85 return &sensor->format;
86}
87
88static int fimc_is_sensor_set_fmt(struct v4l2_subdev *sd,
89 struct v4l2_subdev_fh *fh,
90 struct v4l2_subdev_format *fmt)
91{
92 struct fimc_is_sensor *sensor = sd_to_fimc_is_sensor(sd);
93 struct v4l2_mbus_framefmt *mf;
94
95 fimc_is_sensor_try_format(sensor, &fmt->format);
96
97 mf = __fimc_is_sensor_get_format(sensor, fh, fmt->pad, fmt->which);
98 if (mf) {
99 mutex_lock(&sensor->lock);
100 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
101 *mf = fmt->format;
102 mutex_unlock(&sensor->lock);
103 }
104 return 0;
105}
106
107static int fimc_is_sensor_get_fmt(struct v4l2_subdev *sd,
108 struct v4l2_subdev_fh *fh,
109 struct v4l2_subdev_format *fmt)
110{
111 struct fimc_is_sensor *sensor = sd_to_fimc_is_sensor(sd);
112 struct v4l2_mbus_framefmt *mf;
113
114 mf = __fimc_is_sensor_get_format(sensor, fh, fmt->pad, fmt->which);
115
116 mutex_lock(&sensor->lock);
117 fmt->format = *mf;
118 mutex_unlock(&sensor->lock);
119 return 0;
120}
121
122static struct v4l2_subdev_pad_ops fimc_is_sensor_pad_ops = {
123 .enum_mbus_code = fimc_is_sensor_enum_mbus_code,
124 .get_fmt = fimc_is_sensor_get_fmt,
125 .set_fmt = fimc_is_sensor_set_fmt,
126};
127
128static int fimc_is_sensor_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
129{
130 struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
131
132 *format = fimc_is_sensor_formats[0];
133 format->width = FIMC_IS_SENSOR_DEF_PIX_WIDTH;
134 format->height = FIMC_IS_SENSOR_DEF_PIX_HEIGHT;
135
136 return 0;
137}
138
139static const struct v4l2_subdev_internal_ops fimc_is_sensor_sd_internal_ops = {
140 .open = fimc_is_sensor_open,
141};
142
143static int fimc_is_sensor_s_power(struct v4l2_subdev *sd, int on)
144{
145 struct fimc_is_sensor *sensor = sd_to_fimc_is_sensor(sd);
146 int gpio = sensor->gpio_reset;
147 int ret;
148
149 if (on) {
150 ret = pm_runtime_get(sensor->dev);
151 if (ret < 0)
152 return ret;
153
154 ret = regulator_bulk_enable(SENSOR_NUM_SUPPLIES,
155 sensor->supplies);
156 if (ret < 0) {
157 pm_runtime_put(sensor->dev);
158 return ret;
159 }
160 if (gpio_is_valid(gpio)) {
161 gpio_set_value(gpio, 1);
162 usleep_range(600, 800);
163 gpio_set_value(gpio, 0);
164 usleep_range(10000, 11000);
165 gpio_set_value(gpio, 1);
166 }
167
168 /* A delay needed for the sensor initialization. */
169 msleep(20);
170 } else {
171 if (gpio_is_valid(gpio))
172 gpio_set_value(gpio, 0);
173
174 ret = regulator_bulk_disable(SENSOR_NUM_SUPPLIES,
175 sensor->supplies);
176 if (!ret)
177 pm_runtime_put(sensor->dev);
178 }
179
180 pr_info("%s:%d: on: %d, ret: %d\n", __func__, __LINE__, on, ret);
181
182 return ret;
183}
184
185static struct v4l2_subdev_core_ops fimc_is_sensor_core_ops = {
186 .s_power = fimc_is_sensor_s_power,
187};
188
189static struct v4l2_subdev_ops fimc_is_sensor_subdev_ops = {
190 .core = &fimc_is_sensor_core_ops,
191 .pad = &fimc_is_sensor_pad_ops,
192};
193
194static const struct of_device_id fimc_is_sensor_of_match[];
195
196static int fimc_is_sensor_probe(struct i2c_client *client,
197 const struct i2c_device_id *id)
198{
199 struct device *dev = &client->dev;
200 struct fimc_is_sensor *sensor;
201 const struct of_device_id *of_id;
202 struct v4l2_subdev *sd;
203 int gpio, i, ret;
204
205 sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
206 if (!sensor)
207 return -ENOMEM;
208
209 mutex_init(&sensor->lock);
210 sensor->gpio_reset = -EINVAL;
211
212 gpio = of_get_gpio_flags(dev->of_node, 0, NULL);
213 if (gpio_is_valid(gpio)) {
214 ret = devm_gpio_request_one(dev, gpio, GPIOF_OUT_INIT_LOW,
215 DRIVER_NAME);
216 if (ret < 0)
217 return ret;
218 }
219 sensor->gpio_reset = gpio;
220
221 for (i = 0; i < SENSOR_NUM_SUPPLIES; i++)
222 sensor->supplies[i].supply = sensor_supply_names[i];
223
224 ret = devm_regulator_bulk_get(&client->dev, SENSOR_NUM_SUPPLIES,
225 sensor->supplies);
226 if (ret < 0)
227 return ret;
228
229 of_id = of_match_node(fimc_is_sensor_of_match, dev->of_node);
230 if (!of_id)
231 return -ENODEV;
232
233 sensor->drvdata = of_id->data;
234 sensor->dev = dev;
235
236 sd = &sensor->subdev;
237 v4l2_i2c_subdev_init(sd, client, &fimc_is_sensor_subdev_ops);
238 snprintf(sd->name, sizeof(sd->name), sensor->drvdata->subdev_name);
239 sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
240
241 sensor->format.code = fimc_is_sensor_formats[0].code;
242 sensor->format.width = FIMC_IS_SENSOR_DEF_PIX_WIDTH;
243 sensor->format.height = FIMC_IS_SENSOR_DEF_PIX_HEIGHT;
244
245 sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
246 ret = media_entity_init(&sd->entity, 1, &sensor->pad, 0);
247 if (ret < 0)
248 return ret;
249
250 pm_runtime_no_callbacks(dev);
251 pm_runtime_enable(dev);
252
253 return ret;
254}
255
256static int fimc_is_sensor_remove(struct i2c_client *client)
257{
258 struct v4l2_subdev *sd = i2c_get_clientdata(client);
259 media_entity_cleanup(&sd->entity);
260 return 0;
261}
262
263static const struct i2c_device_id fimc_is_sensor_ids[] = {
264 { }
265};
266
267static const struct sensor_drv_data s5k6a3_drvdata = {
268 .id = FIMC_IS_SENSOR_ID_S5K6A3,
269 .subdev_name = "S5K6A3",
270 .width = S5K6A3_SENSOR_WIDTH,
271 .height = S5K6A3_SENSOR_HEIGHT,
272};
273
274static const struct of_device_id fimc_is_sensor_of_match[] = {
275 {
276 .compatible = "samsung,s5k6a3",
277 .data = &s5k6a3_drvdata,
278 },
279 { }
280};
281
282static struct i2c_driver fimc_is_sensor_driver = {
283 .driver = {
284 .of_match_table = fimc_is_sensor_of_match,
285 .name = DRIVER_NAME,
286 .owner = THIS_MODULE,
287 },
288 .probe = fimc_is_sensor_probe,
289 .remove = fimc_is_sensor_remove,
290 .id_table = fimc_is_sensor_ids,
291};
292
293int fimc_is_register_sensor_driver(void)
294{
295 return i2c_add_driver(&fimc_is_sensor_driver);
296}
297
298void fimc_is_unregister_sensor_driver(void)
299{
300 i2c_del_driver(&fimc_is_sensor_driver);
301}
302
303MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
304MODULE_DESCRIPTION("Exynos4x12 FIMC-IS image sensor subdev driver");
305MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/exynos4-is/fimc-is-sensor.h b/drivers/media/platform/exynos4-is/fimc-is-sensor.h
new file mode 100644
index 000000000000..6036d49a6c68
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-is-sensor.h
@@ -0,0 +1,89 @@
1/*
2 * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
3 *
4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
5 *
6 * Authors: Sylwester Nawrocki <s.nawrocki@samsung.com>
7 * Younghwan Joo <yhwan.joo@samsung.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13#ifndef FIMC_IS_SENSOR_H_
14#define FIMC_IS_SENSOR_H_
15
16#include <linux/clk.h>
17#include <linux/device.h>
18#include <linux/kernel.h>
19#include <linux/platform_device.h>
20#include <linux/regulator/consumer.h>
21#include <linux/videodev2.h>
22#include <media/v4l2-subdev.h>
23
24#define FIMC_IS_SENSOR_OPEN_TIMEOUT 2000 /* ms */
25
26#define FIMC_IS_SENSOR_DEF_PIX_WIDTH 1296
27#define FIMC_IS_SENSOR_DEF_PIX_HEIGHT 732
28
29#define S5K6A3_SENSOR_WIDTH 1392
30#define S5K6A3_SENSOR_HEIGHT 1392
31
32#define SENSOR_NUM_SUPPLIES 2
33
34enum fimc_is_sensor_id {
35 FIMC_IS_SENSOR_ID_S5K3H2 = 1,
36 FIMC_IS_SENSOR_ID_S5K6A3,
37 FIMC_IS_SENSOR_ID_S5K4E5,
38 FIMC_IS_SENSOR_ID_S5K3H7,
39 FIMC_IS_SENSOR_ID_CUSTOM,
40 FIMC_IS_SENSOR_ID_END
41};
42
43#define IS_SENSOR_CTRL_BUS_I2C0 0
44#define IS_SENSOR_CTRL_BUS_I2C1 1
45
46struct sensor_drv_data {
47 enum fimc_is_sensor_id id;
48 const char * const subdev_name;
49 unsigned int width;
50 unsigned int height;
51};
52
53/**
54 * struct fimc_is_sensor - fimc-is sensor data structure
55 * @dev: pointer to this I2C client device structure
56 * @subdev: the image sensor's v4l2 subdev
57 * @pad: subdev media source pad
58 * @supplies: image sensor's voltage regulator supplies
59 * @gpio_reset: GPIO connected to the sensor's reset pin
60 * @drvdata: a pointer to the sensor's parameters data structure
61 * @i2c_bus: ISP I2C bus index (0...1)
62 * @test_pattern: true to enable video test pattern
63 * @lock: mutex protecting the structure's members below
64 * @format: media bus format at the sensor's source pad
65 */
66struct fimc_is_sensor {
67 struct device *dev;
68 struct v4l2_subdev subdev;
69 struct media_pad pad;
70 struct regulator_bulk_data supplies[SENSOR_NUM_SUPPLIES];
71 int gpio_reset;
72 const struct sensor_drv_data *drvdata;
73 unsigned int i2c_bus;
74 bool test_pattern;
75
76 struct mutex lock;
77 struct v4l2_mbus_framefmt format;
78};
79
80static inline
81struct fimc_is_sensor *sd_to_fimc_is_sensor(struct v4l2_subdev *sd)
82{
83 return container_of(sd, struct fimc_is_sensor, subdev);
84}
85
86int fimc_is_register_sensor_driver(void);
87void fimc_is_unregister_sensor_driver(void);
88
89#endif /* FIMC_IS_SENSOR_H_ */
diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c
new file mode 100644
index 000000000000..47c6363d04e2
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-is.c
@@ -0,0 +1,1007 @@
1/*
2 * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
3 *
4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
5 *
6 * Authors: Sylwester Nawrocki <s.nawrocki@samsung.com>
7 * Younghwan Joo <yhwan.joo@samsung.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
14
15#include <linux/device.h>
16#include <linux/debugfs.h>
17#include <linux/delay.h>
18#include <linux/dma-contiguous.h>
19#include <linux/errno.h>
20#include <linux/firmware.h>
21#include <linux/interrupt.h>
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/of_i2c.h>
25#include <linux/of_irq.h>
26#include <linux/of_address.h>
27#include <linux/of_platform.h>
28#include <linux/platform_device.h>
29#include <linux/pm_runtime.h>
30#include <linux/slab.h>
31#include <linux/types.h>
32#include <linux/videodev2.h>
33#include <media/v4l2-of.h>
34#include <media/videobuf2-dma-contig.h>
35
36#include "media-dev.h"
37#include "fimc-is.h"
38#include "fimc-is-command.h"
39#include "fimc-is-errno.h"
40#include "fimc-is-i2c.h"
41#include "fimc-is-param.h"
42#include "fimc-is-regs.h"
43
44
45static char *fimc_is_clocks[ISS_CLKS_MAX] = {
46 [ISS_CLK_PPMUISPX] = "ppmuispx",
47 [ISS_CLK_PPMUISPMX] = "ppmuispmx",
48 [ISS_CLK_LITE0] = "lite0",
49 [ISS_CLK_LITE1] = "lite1",
50 [ISS_CLK_MPLL] = "mpll",
51 [ISS_CLK_SYSREG] = "sysreg",
52 [ISS_CLK_ISP] = "isp",
53 [ISS_CLK_DRC] = "drc",
54 [ISS_CLK_FD] = "fd",
55 [ISS_CLK_MCUISP] = "mcuisp",
56 [ISS_CLK_UART] = "uart",
57 [ISS_CLK_ISP_DIV0] = "ispdiv0",
58 [ISS_CLK_ISP_DIV1] = "ispdiv1",
59 [ISS_CLK_MCUISP_DIV0] = "mcuispdiv0",
60 [ISS_CLK_MCUISP_DIV1] = "mcuispdiv1",
61 [ISS_CLK_ACLK200] = "aclk200",
62 [ISS_CLK_ACLK200_DIV] = "div_aclk200",
63 [ISS_CLK_ACLK400MCUISP] = "aclk400mcuisp",
64 [ISS_CLK_ACLK400MCUISP_DIV] = "div_aclk400mcuisp",
65};
66
67static void fimc_is_put_clocks(struct fimc_is *is)
68{
69 int i;
70
71 for (i = 0; i < ISS_CLKS_MAX; i++) {
72 if (IS_ERR(is->clocks[i]))
73 continue;
74 clk_unprepare(is->clocks[i]);
75 clk_put(is->clocks[i]);
76 is->clocks[i] = ERR_PTR(-EINVAL);
77 }
78}
79
80static int fimc_is_get_clocks(struct fimc_is *is)
81{
82 int i, ret;
83
84 for (i = 0; i < ISS_CLKS_MAX; i++)
85 is->clocks[i] = ERR_PTR(-EINVAL);
86
87 for (i = 0; i < ISS_CLKS_MAX; i++) {
88 is->clocks[i] = clk_get(&is->pdev->dev, fimc_is_clocks[i]);
89 if (IS_ERR(is->clocks[i])) {
90 ret = PTR_ERR(is->clocks[i]);
91 goto err;
92 }
93 ret = clk_prepare(is->clocks[i]);
94 if (ret < 0) {
95 clk_put(is->clocks[i]);
96 is->clocks[i] = ERR_PTR(-EINVAL);
97 goto err;
98 }
99 }
100
101 return 0;
102err:
103 fimc_is_put_clocks(is);
104 dev_err(&is->pdev->dev, "failed to get clock: %s\n",
105 fimc_is_clocks[i]);
106 return -ENXIO;
107}
108
109static int fimc_is_setup_clocks(struct fimc_is *is)
110{
111 int ret;
112
113 ret = clk_set_parent(is->clocks[ISS_CLK_ACLK200],
114 is->clocks[ISS_CLK_ACLK200_DIV]);
115 if (ret < 0)
116 return ret;
117
118 ret = clk_set_parent(is->clocks[ISS_CLK_ACLK400MCUISP],
119 is->clocks[ISS_CLK_ACLK400MCUISP_DIV]);
120 if (ret < 0)
121 return ret;
122
123 ret = clk_set_rate(is->clocks[ISS_CLK_ISP_DIV0], ACLK_AXI_FREQUENCY);
124 if (ret < 0)
125 return ret;
126
127 ret = clk_set_rate(is->clocks[ISS_CLK_ISP_DIV1], ACLK_AXI_FREQUENCY);
128 if (ret < 0)
129 return ret;
130
131 ret = clk_set_rate(is->clocks[ISS_CLK_MCUISP_DIV0],
132 ATCLK_MCUISP_FREQUENCY);
133 if (ret < 0)
134 return ret;
135
136 return clk_set_rate(is->clocks[ISS_CLK_MCUISP_DIV1],
137 ATCLK_MCUISP_FREQUENCY);
138}
139
140int fimc_is_enable_clocks(struct fimc_is *is)
141{
142 int i, ret;
143
144 for (i = 0; i < ISS_GATE_CLKS_MAX; i++) {
145 if (IS_ERR(is->clocks[i]))
146 continue;
147 ret = clk_enable(is->clocks[i]);
148 if (ret < 0) {
149 dev_err(&is->pdev->dev, "clock %s enable failed\n",
150 fimc_is_clocks[i]);
151 for (--i; i >= 0; i--)
152 clk_disable(is->clocks[i]);
153 return ret;
154 }
155 pr_debug("enabled clock: %s\n", fimc_is_clocks[i]);
156 }
157 return 0;
158}
159
160void fimc_is_disable_clocks(struct fimc_is *is)
161{
162 int i;
163
164 for (i = 0; i < ISS_GATE_CLKS_MAX; i++) {
165 if (!IS_ERR(is->clocks[i])) {
166 clk_disable(is->clocks[i]);
167 pr_debug("disabled clock: %s\n", fimc_is_clocks[i]);
168 }
169 }
170}
171
172static int fimc_is_parse_sensor_config(struct fimc_is_sensor *sensor,
173 struct device_node *np)
174{
175 u32 tmp = 0;
176 int ret;
177
178 np = v4l2_of_get_next_endpoint(np, NULL);
179 if (!np)
180 return -ENXIO;
181 np = v4l2_of_get_remote_port(np);
182 if (!np)
183 return -ENXIO;
184
185 /* Use MIPI-CSIS channel id to determine the ISP I2C bus index. */
186 ret = of_property_read_u32(np, "reg", &tmp);
187 sensor->i2c_bus = tmp - FIMC_INPUT_MIPI_CSI2_0;
188
189 return ret;
190}
191
192static int fimc_is_register_subdevs(struct fimc_is *is)
193{
194 struct device_node *adapter, *child;
195 int ret;
196
197 ret = fimc_isp_subdev_create(&is->isp);
198 if (ret < 0)
199 return ret;
200
201 for_each_compatible_node(adapter, NULL, FIMC_IS_I2C_COMPATIBLE) {
202 if (!of_find_device_by_node(adapter)) {
203 of_node_put(adapter);
204 return -EPROBE_DEFER;
205 }
206
207 for_each_available_child_of_node(adapter, child) {
208 struct i2c_client *client;
209 struct v4l2_subdev *sd;
210
211 client = of_find_i2c_device_by_node(child);
212 if (!client)
213 goto e_retry;
214
215 sd = i2c_get_clientdata(client);
216 if (!sd)
217 goto e_retry;
218
219 /* FIXME: Add support for multiple sensors. */
220 if (WARN_ON(is->sensor))
221 continue;
222
223 is->sensor = sd_to_fimc_is_sensor(sd);
224
225 if (fimc_is_parse_sensor_config(is->sensor, child)) {
226 dev_warn(&is->pdev->dev, "DT parse error: %s\n",
227 child->full_name);
228 }
229 pr_debug("%s(): registered subdev: %p\n",
230 __func__, sd->name);
231 }
232 }
233 return 0;
234
235e_retry:
236 of_node_put(child);
237 return -EPROBE_DEFER;
238}
239
240static int fimc_is_unregister_subdevs(struct fimc_is *is)
241{
242 fimc_isp_subdev_destroy(&is->isp);
243 is->sensor = NULL;
244 return 0;
245}
246
247static int fimc_is_load_setfile(struct fimc_is *is, char *file_name)
248{
249 const struct firmware *fw;
250 void *buf;
251 int ret;
252
253 ret = request_firmware(&fw, file_name, &is->pdev->dev);
254 if (ret < 0) {
255 dev_err(&is->pdev->dev, "firmware request failed (%d)\n", ret);
256 return ret;
257 }
258 buf = is->memory.vaddr + is->setfile.base;
259 memcpy(buf, fw->data, fw->size);
260 fimc_is_mem_barrier();
261 is->setfile.size = fw->size;
262
263 pr_debug("mem vaddr: %p, setfile buf: %p\n", is->memory.vaddr, buf);
264
265 memcpy(is->fw.setfile_info,
266 fw->data + fw->size - FIMC_IS_SETFILE_INFO_LEN,
267 FIMC_IS_SETFILE_INFO_LEN - 1);
268
269 is->fw.setfile_info[FIMC_IS_SETFILE_INFO_LEN - 1] = '\0';
270 is->setfile.state = 1;
271
272 pr_debug("FIMC-IS setfile loaded: base: %#x, size: %zu B\n",
273 is->setfile.base, fw->size);
274
275 release_firmware(fw);
276 return ret;
277}
278
279int fimc_is_cpu_set_power(struct fimc_is *is, int on)
280{
281 unsigned int timeout = FIMC_IS_POWER_ON_TIMEOUT;
282
283 if (on) {
284 /* Disable watchdog */
285 mcuctl_write(0, is, REG_WDT_ISP);
286
287 /* Cortex-A5 start address setting */
288 mcuctl_write(is->memory.paddr, is, MCUCTL_REG_BBOAR);
289
290 /* Enable and start Cortex-A5 */
291 pmuisp_write(0x18000, is, REG_PMU_ISP_ARM_OPTION);
292 pmuisp_write(0x1, is, REG_PMU_ISP_ARM_CONFIGURATION);
293 } else {
294 /* A5 power off */
295 pmuisp_write(0x10000, is, REG_PMU_ISP_ARM_OPTION);
296 pmuisp_write(0x0, is, REG_PMU_ISP_ARM_CONFIGURATION);
297
298 while (pmuisp_read(is, REG_PMU_ISP_ARM_STATUS) & 1) {
299 if (timeout == 0)
300 return -ETIME;
301 timeout--;
302 udelay(1);
303 }
304 }
305
306 return 0;
307}
308
309/* Wait until @bit of @is->state is set to @state in the interrupt handler. */
310int fimc_is_wait_event(struct fimc_is *is, unsigned long bit,
311 unsigned int state, unsigned int timeout)
312{
313
314 int ret = wait_event_timeout(is->irq_queue,
315 !state ^ test_bit(bit, &is->state),
316 timeout);
317 if (ret == 0) {
318 dev_WARN(&is->pdev->dev, "%s() timed out\n", __func__);
319 return -ETIME;
320 }
321 return 0;
322}
323
324int fimc_is_start_firmware(struct fimc_is *is)
325{
326 struct device *dev = &is->pdev->dev;
327 int ret;
328
329 memcpy(is->memory.vaddr, is->fw.f_w->data, is->fw.f_w->size);
330 wmb();
331
332 ret = fimc_is_cpu_set_power(is, 1);
333 if (ret < 0)
334 return ret;
335
336 ret = fimc_is_wait_event(is, IS_ST_A5_PWR_ON, 1,
337 msecs_to_jiffies(FIMC_IS_FW_LOAD_TIMEOUT));
338 if (ret < 0)
339 dev_err(dev, "FIMC-IS CPU power on failed\n");
340
341 return ret;
342}
343
344/* Allocate working memory for the FIMC-IS CPU. */
345static int fimc_is_alloc_cpu_memory(struct fimc_is *is)
346{
347 struct device *dev = &is->pdev->dev;
348
349 is->memory.vaddr = dma_alloc_coherent(dev, FIMC_IS_CPU_MEM_SIZE,
350 &is->memory.paddr, GFP_KERNEL);
351 if (is->memory.vaddr == NULL)
352 return -ENOMEM;
353
354 is->memory.size = FIMC_IS_CPU_MEM_SIZE;
355 memset(is->memory.vaddr, 0, is->memory.size);
356
357 dev_info(dev, "FIMC-IS CPU memory base: %#x\n", (u32)is->memory.paddr);
358
359 if (((u32)is->memory.paddr) & FIMC_IS_FW_ADDR_MASK) {
360 dev_err(dev, "invalid firmware memory alignment: %#x\n",
361 (u32)is->memory.paddr);
362 dma_free_coherent(dev, is->memory.size, is->memory.vaddr,
363 is->memory.paddr);
364 return -EIO;
365 }
366
367 is->is_p_region = (struct is_region *)(is->memory.vaddr +
368 FIMC_IS_CPU_MEM_SIZE - FIMC_IS_REGION_SIZE);
369
370 is->is_dma_p_region = is->memory.paddr +
371 FIMC_IS_CPU_MEM_SIZE - FIMC_IS_REGION_SIZE;
372
373 is->is_shared_region = (struct is_share_region *)(is->memory.vaddr +
374 FIMC_IS_SHARED_REGION_OFFSET);
375 return 0;
376}
377
378static void fimc_is_free_cpu_memory(struct fimc_is *is)
379{
380 struct device *dev = &is->pdev->dev;
381
382 dma_free_coherent(dev, is->memory.size, is->memory.vaddr,
383 is->memory.paddr);
384}
385
386static void fimc_is_load_firmware(const struct firmware *fw, void *context)
387{
388 struct fimc_is *is = context;
389 struct device *dev = &is->pdev->dev;
390 void *buf;
391 int ret;
392
393 if (fw == NULL) {
394 dev_err(dev, "firmware request failed\n");
395 return;
396 }
397 mutex_lock(&is->lock);
398
399 if (fw->size < FIMC_IS_FW_SIZE_MIN || fw->size > FIMC_IS_FW_SIZE_MAX) {
400 dev_err(dev, "wrong firmware size: %d\n", fw->size);
401 goto done;
402 }
403
404 is->fw.size = fw->size;
405
406 ret = fimc_is_alloc_cpu_memory(is);
407 if (ret < 0) {
408 dev_err(dev, "failed to allocate FIMC-IS CPU memory\n");
409 goto done;
410 }
411
412 memcpy(is->memory.vaddr, fw->data, fw->size);
413 wmb();
414
415 /* Read firmware description. */
416 buf = (void *)(is->memory.vaddr + fw->size - FIMC_IS_FW_DESC_LEN);
417 memcpy(&is->fw.info, buf, FIMC_IS_FW_INFO_LEN);
418 is->fw.info[FIMC_IS_FW_INFO_LEN] = 0;
419
420 buf = (void *)(is->memory.vaddr + fw->size - FIMC_IS_FW_VER_LEN);
421 memcpy(&is->fw.version, buf, FIMC_IS_FW_VER_LEN);
422 is->fw.version[FIMC_IS_FW_VER_LEN - 1] = 0;
423
424 is->fw.state = 1;
425
426 dev_info(dev, "loaded firmware: %s, rev. %s\n",
427 is->fw.info, is->fw.version);
428 dev_dbg(dev, "FW size: %d, paddr: %#x\n", fw->size, is->memory.paddr);
429
430 is->is_shared_region->chip_id = 0xe4412;
431 is->is_shared_region->chip_rev_no = 1;
432
433 fimc_is_mem_barrier();
434
435 /*
436 * FIXME: The firmware is not being released for now, as it is
437 * needed around for copying to the IS working memory every
438 * time before the Cortex-A5 is restarted.
439 */
440 if (is->fw.f_w)
441 release_firmware(is->fw.f_w);
442 is->fw.f_w = fw;
443done:
444 mutex_unlock(&is->lock);
445}
446
447static int fimc_is_request_firmware(struct fimc_is *is, const char *fw_name)
448{
449 return request_firmware_nowait(THIS_MODULE,
450 FW_ACTION_HOTPLUG, fw_name, &is->pdev->dev,
451 GFP_KERNEL, is, fimc_is_load_firmware);
452}
453
454/* General IS interrupt handler */
455static void fimc_is_general_irq_handler(struct fimc_is *is)
456{
457 is->i2h_cmd.cmd = mcuctl_read(is, MCUCTL_REG_ISSR(10));
458
459 switch (is->i2h_cmd.cmd) {
460 case IHC_GET_SENSOR_NUM:
461 fimc_is_hw_get_params(is, 1);
462 fimc_is_hw_wait_intmsr0_intmsd0(is);
463 fimc_is_hw_set_sensor_num(is);
464 pr_debug("ISP FW version: %#x\n", is->i2h_cmd.args[0]);
465 break;
466 case IHC_SET_FACE_MARK:
467 case IHC_FRAME_DONE:
468 fimc_is_hw_get_params(is, 2);
469 break;
470 case IHC_SET_SHOT_MARK:
471 case IHC_AA_DONE:
472 case IH_REPLY_DONE:
473 fimc_is_hw_get_params(is, 3);
474 break;
475 case IH_REPLY_NOT_DONE:
476 fimc_is_hw_get_params(is, 4);
477 break;
478 case IHC_NOT_READY:
479 break;
480 default:
481 pr_info("unknown command: %#x\n", is->i2h_cmd.cmd);
482 }
483
484 fimc_is_fw_clear_irq1(is, FIMC_IS_INT_GENERAL);
485
486 switch (is->i2h_cmd.cmd) {
487 case IHC_GET_SENSOR_NUM:
488 fimc_is_hw_set_intgr0_gd0(is);
489 set_bit(IS_ST_A5_PWR_ON, &is->state);
490 break;
491
492 case IHC_SET_SHOT_MARK:
493 break;
494
495 case IHC_SET_FACE_MARK:
496 is->fd_header.count = is->i2h_cmd.args[0];
497 is->fd_header.index = is->i2h_cmd.args[1];
498 is->fd_header.offset = 0;
499 break;
500
501 case IHC_FRAME_DONE:
502 break;
503
504 case IHC_AA_DONE:
505 pr_debug("AA_DONE - %d, %d, %d\n", is->i2h_cmd.args[0],
506 is->i2h_cmd.args[1], is->i2h_cmd.args[2]);
507 break;
508
509 case IH_REPLY_DONE:
510 pr_debug("ISR_DONE: args[0]: %#x\n", is->i2h_cmd.args[0]);
511
512 switch (is->i2h_cmd.args[0]) {
513 case HIC_PREVIEW_STILL...HIC_CAPTURE_VIDEO:
514 /* Get CAC margin */
515 set_bit(IS_ST_CHANGE_MODE, &is->state);
516 is->isp.cac_margin_x = is->i2h_cmd.args[1];
517 is->isp.cac_margin_y = is->i2h_cmd.args[2];
518 pr_debug("CAC margin (x,y): (%d,%d)\n",
519 is->isp.cac_margin_x, is->isp.cac_margin_y);
520 break;
521
522 case HIC_STREAM_ON:
523 clear_bit(IS_ST_STREAM_OFF, &is->state);
524 set_bit(IS_ST_STREAM_ON, &is->state);
525 break;
526
527 case HIC_STREAM_OFF:
528 clear_bit(IS_ST_STREAM_ON, &is->state);
529 set_bit(IS_ST_STREAM_OFF, &is->state);
530 break;
531
532 case HIC_SET_PARAMETER:
533 is->config[is->config_index].p_region_index1 = 0;
534 is->config[is->config_index].p_region_index2 = 0;
535 set_bit(IS_ST_BLOCK_CMD_CLEARED, &is->state);
536 pr_debug("HIC_SET_PARAMETER\n");
537 break;
538
539 case HIC_GET_PARAMETER:
540 break;
541
542 case HIC_SET_TUNE:
543 break;
544
545 case HIC_GET_STATUS:
546 break;
547
548 case HIC_OPEN_SENSOR:
549 set_bit(IS_ST_OPEN_SENSOR, &is->state);
550 pr_debug("data lanes: %d, settle line: %d\n",
551 is->i2h_cmd.args[2], is->i2h_cmd.args[1]);
552 break;
553
554 case HIC_CLOSE_SENSOR:
555 clear_bit(IS_ST_OPEN_SENSOR, &is->state);
556 is->sensor_index = 0;
557 break;
558
559 case HIC_MSG_TEST:
560 pr_debug("config MSG level completed\n");
561 break;
562
563 case HIC_POWER_DOWN:
564 clear_bit(IS_ST_PWR_SUBIP_ON, &is->state);
565 break;
566
567 case HIC_GET_SET_FILE_ADDR:
568 is->setfile.base = is->i2h_cmd.args[1];
569 set_bit(IS_ST_SETFILE_LOADED, &is->state);
570 break;
571
572 case HIC_LOAD_SET_FILE:
573 set_bit(IS_ST_SETFILE_LOADED, &is->state);
574 break;
575 }
576 break;
577
578 case IH_REPLY_NOT_DONE:
579 pr_err("ISR_NDONE: %d: %#x, %s\n", is->i2h_cmd.args[0],
580 is->i2h_cmd.args[1],
581 fimc_is_strerr(is->i2h_cmd.args[1]));
582
583 if (is->i2h_cmd.args[1] & IS_ERROR_TIME_OUT_FLAG)
584 pr_err("IS_ERROR_TIME_OUT\n");
585
586 switch (is->i2h_cmd.args[1]) {
587 case IS_ERROR_SET_PARAMETER:
588 fimc_is_mem_barrier();
589 }
590
591 switch (is->i2h_cmd.args[0]) {
592 case HIC_SET_PARAMETER:
593 is->config[is->config_index].p_region_index1 = 0;
594 is->config[is->config_index].p_region_index2 = 0;
595 set_bit(IS_ST_BLOCK_CMD_CLEARED, &is->state);
596 break;
597 }
598 break;
599
600 case IHC_NOT_READY:
601 pr_err("IS control sequence error: Not Ready\n");
602 break;
603 }
604
605 wake_up(&is->irq_queue);
606}
607
608static irqreturn_t fimc_is_irq_handler(int irq, void *priv)
609{
610 struct fimc_is *is = priv;
611 unsigned long flags;
612 u32 status;
613
614 spin_lock_irqsave(&is->slock, flags);
615 status = mcuctl_read(is, MCUCTL_REG_INTSR1);
616
617 if (status & (1UL << FIMC_IS_INT_GENERAL))
618 fimc_is_general_irq_handler(is);
619
620 if (status & (1UL << FIMC_IS_INT_FRAME_DONE_ISP))
621 fimc_isp_irq_handler(is);
622
623 spin_unlock_irqrestore(&is->slock, flags);
624 return IRQ_HANDLED;
625}
626
627static int fimc_is_hw_open_sensor(struct fimc_is *is,
628 struct fimc_is_sensor *sensor)
629{
630 struct sensor_open_extended *soe = (void *)&is->is_p_region->shared;
631
632 fimc_is_hw_wait_intmsr0_intmsd0(is);
633
634 soe->self_calibration_mode = 1;
635 soe->actuator_type = 0;
636 soe->mipi_lane_num = 0;
637 soe->mclk = 0;
638 soe->mipi_speed = 0;
639 soe->fast_open_sensor = 0;
640 soe->i2c_sclk = 88000000;
641
642 fimc_is_mem_barrier();
643
644 mcuctl_write(HIC_OPEN_SENSOR, is, MCUCTL_REG_ISSR(0));
645 mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
646 mcuctl_write(sensor->drvdata->id, is, MCUCTL_REG_ISSR(2));
647 mcuctl_write(sensor->i2c_bus, is, MCUCTL_REG_ISSR(3));
648 mcuctl_write(is->is_dma_p_region, is, MCUCTL_REG_ISSR(4));
649
650 fimc_is_hw_set_intgr0_gd0(is);
651
652 return fimc_is_wait_event(is, IS_ST_OPEN_SENSOR, 1,
653 FIMC_IS_SENSOR_OPEN_TIMEOUT);
654}
655
656
657int fimc_is_hw_initialize(struct fimc_is *is)
658{
659 const int config_ids[] = {
660 IS_SC_PREVIEW_STILL, IS_SC_PREVIEW_VIDEO,
661 IS_SC_CAPTURE_STILL, IS_SC_CAPTURE_VIDEO
662 };
663 struct device *dev = &is->pdev->dev;
664 u32 prev_id;
665 int i, ret;
666
667 /* Sensor initialization. */
668 ret = fimc_is_hw_open_sensor(is, is->sensor);
669 if (ret < 0)
670 return ret;
671
672 /* Get the setfile address. */
673 fimc_is_hw_get_setfile_addr(is);
674
675 ret = fimc_is_wait_event(is, IS_ST_SETFILE_LOADED, 1,
676 FIMC_IS_CONFIG_TIMEOUT);
677 if (ret < 0) {
678 dev_err(dev, "get setfile address timed out\n");
679 return ret;
680 }
681 pr_debug("setfile.base: %#x\n", is->setfile.base);
682
683 /* Load the setfile. */
684 fimc_is_load_setfile(is, FIMC_IS_SETFILE_6A3);
685 clear_bit(IS_ST_SETFILE_LOADED, &is->state);
686 fimc_is_hw_load_setfile(is);
687 ret = fimc_is_wait_event(is, IS_ST_SETFILE_LOADED, 1,
688 FIMC_IS_CONFIG_TIMEOUT);
689 if (ret < 0) {
690 dev_err(dev, "loading setfile timed out\n");
691 return ret;
692 }
693
694 pr_debug("setfile: base: %#x, size: %d\n",
695 is->setfile.base, is->setfile.size);
696 pr_info("FIMC-IS Setfile info: %s\n", is->fw.setfile_info);
697
698 /* Check magic number. */
699 if (is->is_p_region->shared[MAX_SHARED_COUNT - 1] !=
700 FIMC_IS_MAGIC_NUMBER) {
701 dev_err(dev, "magic number error!\n");
702 return -EIO;
703 }
704
705 pr_debug("shared region: %#x, parameter region: %#x\n",
706 is->memory.paddr + FIMC_IS_SHARED_REGION_OFFSET,
707 is->is_dma_p_region);
708
709 is->setfile.sub_index = 0;
710
711 /* Stream off. */
712 fimc_is_hw_stream_off(is);
713 ret = fimc_is_wait_event(is, IS_ST_STREAM_OFF, 1,
714 FIMC_IS_CONFIG_TIMEOUT);
715 if (ret < 0) {
716 dev_err(dev, "stream off timeout\n");
717 return ret;
718 }
719
720 /* Preserve previous mode. */
721 prev_id = is->config_index;
722
723 /* Set initial parameter values. */
724 for (i = 0; i < ARRAY_SIZE(config_ids); i++) {
725 is->config_index = config_ids[i];
726 fimc_is_set_initial_params(is);
727 ret = fimc_is_itf_s_param(is, true);
728 if (ret < 0) {
729 is->config_index = prev_id;
730 return ret;
731 }
732 }
733 is->config_index = prev_id;
734
735 set_bit(IS_ST_INIT_DONE, &is->state);
736 dev_info(dev, "initialization sequence completed (%d)\n",
737 is->config_index);
738 return 0;
739}
740
741static int fimc_is_log_show(struct seq_file *s, void *data)
742{
743 struct fimc_is *is = s->private;
744 const u8 *buf = is->memory.vaddr + FIMC_IS_DEBUG_REGION_OFFSET;
745
746 if (is->memory.vaddr == NULL) {
747 dev_err(&is->pdev->dev, "firmware memory is not initialized\n");
748 return -EIO;
749 }
750
751 seq_printf(s, "%s\n", buf);
752 return 0;
753}
754
755static int fimc_is_debugfs_open(struct inode *inode, struct file *file)
756{
757 return single_open(file, fimc_is_log_show, inode->i_private);
758}
759
760static const struct file_operations fimc_is_debugfs_fops = {
761 .open = fimc_is_debugfs_open,
762 .read = seq_read,
763 .llseek = seq_lseek,
764 .release = single_release,
765};
766
767static void fimc_is_debugfs_remove(struct fimc_is *is)
768{
769 debugfs_remove_recursive(is->debugfs_entry);
770 is->debugfs_entry = NULL;
771}
772
773static int fimc_is_debugfs_create(struct fimc_is *is)
774{
775 struct dentry *dentry;
776
777 is->debugfs_entry = debugfs_create_dir("fimc_is", NULL);
778
779 dentry = debugfs_create_file("fw_log", S_IRUGO, is->debugfs_entry,
780 is, &fimc_is_debugfs_fops);
781 if (!dentry)
782 fimc_is_debugfs_remove(is);
783
784 return is->debugfs_entry == NULL ? -EIO : 0;
785}
786
787static int fimc_is_probe(struct platform_device *pdev)
788{
789 struct device *dev = &pdev->dev;
790 struct fimc_is *is;
791 struct resource res;
792 struct device_node *node;
793 int ret;
794
795 is = devm_kzalloc(&pdev->dev, sizeof(*is), GFP_KERNEL);
796 if (!is)
797 return -ENOMEM;
798
799 is->pdev = pdev;
800 is->isp.pdev = pdev;
801
802 init_waitqueue_head(&is->irq_queue);
803 spin_lock_init(&is->slock);
804 mutex_init(&is->lock);
805
806 ret = of_address_to_resource(dev->of_node, 0, &res);
807 if (ret < 0)
808 return ret;
809
810 is->regs = devm_ioremap_resource(dev, &res);
811 if (IS_ERR(is->regs))
812 return PTR_ERR(is->regs);
813
814 node = of_get_child_by_name(dev->of_node, "pmu");
815 if (!node)
816 return -ENODEV;
817
818 is->pmu_regs = of_iomap(node, 0);
819 if (!is->pmu_regs)
820 return -ENOMEM;
821
822 is->irq = irq_of_parse_and_map(dev->of_node, 0);
823 if (is->irq < 0) {
824 dev_err(dev, "no irq found\n");
825 return is->irq;
826 }
827
828 ret = fimc_is_get_clocks(is);
829 if (ret < 0)
830 return ret;
831
832 platform_set_drvdata(pdev, is);
833
834 ret = request_irq(is->irq, fimc_is_irq_handler, 0, dev_name(dev), is);
835 if (ret < 0) {
836 dev_err(dev, "irq request failed\n");
837 goto err_clk;
838 }
839 pm_runtime_enable(dev);
840 /*
841 * Enable only the ISP power domain, keep FIMC-IS clocks off until
842 * the whole clock tree is configured. The ISP power domain needs
843 * be active in order to acces any CMU_ISP clock registers.
844 */
845 ret = pm_runtime_get_sync(dev);
846 if (ret < 0)
847 goto err_irq;
848
849 ret = fimc_is_setup_clocks(is);
850 pm_runtime_put_sync(dev);
851
852 if (ret < 0)
853 goto err_irq;
854
855 is->clk_init = true;
856
857 is->alloc_ctx = vb2_dma_contig_init_ctx(dev);
858 if (IS_ERR(is->alloc_ctx)) {
859 ret = PTR_ERR(is->alloc_ctx);
860 goto err_irq;
861 }
862 /*
863 * Register FIMC-IS V4L2 subdevs to this driver. The video nodes
864 * will be created within the subdev's registered() callback.
865 */
866 ret = fimc_is_register_subdevs(is);
867 if (ret < 0)
868 goto err_vb;
869
870 ret = fimc_is_debugfs_create(is);
871 if (ret < 0)
872 goto err_sd;
873
874 ret = fimc_is_request_firmware(is, FIMC_IS_FW_FILENAME);
875 if (ret < 0)
876 goto err_dfs;
877
878 dev_dbg(dev, "FIMC-IS registered successfully\n");
879 return 0;
880
881err_dfs:
882 fimc_is_debugfs_remove(is);
883err_vb:
884 vb2_dma_contig_cleanup_ctx(is->alloc_ctx);
885err_sd:
886 fimc_is_unregister_subdevs(is);
887err_irq:
888 free_irq(is->irq, is);
889err_clk:
890 fimc_is_put_clocks(is);
891 return ret;
892}
893
894static int fimc_is_runtime_resume(struct device *dev)
895{
896 struct fimc_is *is = dev_get_drvdata(dev);
897
898 if (!is->clk_init)
899 return 0;
900
901 return fimc_is_enable_clocks(is);
902}
903
904static int fimc_is_runtime_suspend(struct device *dev)
905{
906 struct fimc_is *is = dev_get_drvdata(dev);
907
908 if (is->clk_init)
909 fimc_is_disable_clocks(is);
910
911 return 0;
912}
913
914#ifdef CONFIG_PM_SLEEP
915static int fimc_is_resume(struct device *dev)
916{
917 /* TODO: */
918 return 0;
919}
920
921static int fimc_is_suspend(struct device *dev)
922{
923 struct fimc_is *is = dev_get_drvdata(dev);
924
925 /* TODO: */
926 if (test_bit(IS_ST_A5_PWR_ON, &is->state))
927 return -EBUSY;
928
929 return 0;
930}
931#endif /* CONFIG_PM_SLEEP */
932
933static int fimc_is_remove(struct platform_device *pdev)
934{
935 struct fimc_is *is = platform_get_drvdata(pdev);
936
937 pm_runtime_disable(&pdev->dev);
938 pm_runtime_set_suspended(&pdev->dev);
939 free_irq(is->irq, is);
940 fimc_is_unregister_subdevs(is);
941 vb2_dma_contig_cleanup_ctx(is->alloc_ctx);
942 fimc_is_put_clocks(is);
943 fimc_is_debugfs_remove(is);
944 release_firmware(is->fw.f_w);
945 fimc_is_free_cpu_memory(is);
946
947 return 0;
948}
949
950static const struct of_device_id fimc_is_of_match[] = {
951 { .compatible = "samsung,exynos4212-fimc-is" },
952 { /* sentinel */ },
953};
954MODULE_DEVICE_TABLE(of, fimc_is_of_match);
955
956static const struct dev_pm_ops fimc_is_pm_ops = {
957 SET_SYSTEM_SLEEP_PM_OPS(fimc_is_suspend, fimc_is_resume)
958 SET_RUNTIME_PM_OPS(fimc_is_runtime_suspend, fimc_is_runtime_resume,
959 NULL)
960};
961
962static struct platform_driver fimc_is_driver = {
963 .probe = fimc_is_probe,
964 .remove = fimc_is_remove,
965 .driver = {
966 .of_match_table = fimc_is_of_match,
967 .name = FIMC_IS_DRV_NAME,
968 .owner = THIS_MODULE,
969 .pm = &fimc_is_pm_ops,
970 }
971};
972
973static int fimc_is_module_init(void)
974{
975 int ret;
976
977 ret = fimc_is_register_sensor_driver();
978 if (ret < 0)
979 return ret;
980
981 ret = fimc_is_register_i2c_driver();
982 if (ret < 0)
983 goto err_sens;
984
985 ret = platform_driver_register(&fimc_is_driver);
986 if (!ret)
987 return ret;
988
989 fimc_is_unregister_i2c_driver();
990err_sens:
991 fimc_is_unregister_sensor_driver();
992 return ret;
993}
994
995static void fimc_is_module_exit(void)
996{
997 fimc_is_unregister_sensor_driver();
998 fimc_is_unregister_i2c_driver();
999 platform_driver_unregister(&fimc_is_driver);
1000}
1001
1002module_init(fimc_is_module_init);
1003module_exit(fimc_is_module_exit);
1004
1005MODULE_ALIAS("platform:" FIMC_IS_DRV_NAME);
1006MODULE_AUTHOR("Younghwan Joo <yhwan.joo@samsung.com>");
1007MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
diff --git a/drivers/media/platform/exynos4-is/fimc-is.h b/drivers/media/platform/exynos4-is/fimc-is.h
new file mode 100644
index 000000000000..f5275a5b0156
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-is.h
@@ -0,0 +1,345 @@
1/*
2 * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
3 *
4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
5 *
6 * Authors: Younghwan Joo <yhwan.joo@samsung.com>
7 * Sylwester Nawrocki <s.nawrocki@samsung.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13#ifndef FIMC_IS_H_
14#define FIMC_IS_H_
15
16#include <asm/barrier.h>
17#include <linux/clk.h>
18#include <linux/device.h>
19#include <linux/kernel.h>
20#include <linux/pinctrl/consumer.h>
21#include <linux/platform_device.h>
22#include <linux/sizes.h>
23#include <linux/spinlock.h>
24#include <linux/types.h>
25#include <media/videobuf2-core.h>
26#include <media/v4l2-ctrls.h>
27
28#include "fimc-isp.h"
29#include "fimc-is-command.h"
30#include "fimc-is-sensor.h"
31#include "fimc-is-param.h"
32#include "fimc-is-regs.h"
33
34#define FIMC_IS_DRV_NAME "exynos4-fimc-is"
35
36#define FIMC_IS_FW_FILENAME "fimc_is_fw.bin"
37#define FIMC_IS_SETFILE_6A3 "setfile.bin"
38
39#define FIMC_IS_FW_LOAD_TIMEOUT 1000 /* ms */
40#define FIMC_IS_POWER_ON_TIMEOUT 1000 /* us */
41
42#define FIMC_IS_SENSOR_NUM 2
43
44/* Memory definitions */
45#define FIMC_IS_CPU_MEM_SIZE (0xa00000)
46#define FIMC_IS_CPU_BASE_MASK ((1 << 26) - 1)
47#define FIMC_IS_REGION_SIZE 0x5000
48
49#define FIMC_IS_DEBUG_REGION_OFFSET 0x0084b000
50#define FIMC_IS_SHARED_REGION_OFFSET 0x008c0000
51#define FIMC_IS_FW_INFO_LEN 31
52#define FIMC_IS_FW_VER_LEN 7
53#define FIMC_IS_FW_DESC_LEN (FIMC_IS_FW_INFO_LEN + \
54 FIMC_IS_FW_VER_LEN)
55#define FIMC_IS_SETFILE_INFO_LEN 39
56
57#define FIMC_IS_EXTRA_MEM_SIZE (FIMC_IS_EXTRA_FW_SIZE + \
58 FIMC_IS_EXTRA_SETFILE_SIZE + 0x1000)
59#define FIMC_IS_EXTRA_FW_SIZE 0x180000
60#define FIMC_IS_EXTRA_SETFILE_SIZE 0x4b000
61
62/* TODO: revisit */
63#define FIMC_IS_FW_ADDR_MASK ((1 << 26) - 1)
64#define FIMC_IS_FW_SIZE_MAX (SZ_4M)
65#define FIMC_IS_FW_SIZE_MIN (SZ_32K)
66
67#define ATCLK_MCUISP_FREQUENCY 100000000UL
68#define ACLK_AXI_FREQUENCY 100000000UL
69
70enum {
71 ISS_CLK_PPMUISPX,
72 ISS_CLK_PPMUISPMX,
73 ISS_CLK_LITE0,
74 ISS_CLK_LITE1,
75 ISS_CLK_MPLL,
76 ISS_CLK_SYSREG,
77 ISS_CLK_ISP,
78 ISS_CLK_DRC,
79 ISS_CLK_FD,
80 ISS_CLK_MCUISP,
81 ISS_CLK_UART,
82 ISS_GATE_CLKS_MAX,
83 ISS_CLK_ISP_DIV0 = ISS_GATE_CLKS_MAX,
84 ISS_CLK_ISP_DIV1,
85 ISS_CLK_MCUISP_DIV0,
86 ISS_CLK_MCUISP_DIV1,
87 ISS_CLK_ACLK200,
88 ISS_CLK_ACLK200_DIV,
89 ISS_CLK_ACLK400MCUISP,
90 ISS_CLK_ACLK400MCUISP_DIV,
91 ISS_CLKS_MAX
92};
93
94/* The driver's internal state flags */
95enum {
96 IS_ST_IDLE,
97 IS_ST_PWR_ON,
98 IS_ST_A5_PWR_ON,
99 IS_ST_FW_LOADED,
100 IS_ST_OPEN_SENSOR,
101 IS_ST_SETFILE_LOADED,
102 IS_ST_INIT_DONE,
103 IS_ST_STREAM_ON,
104 IS_ST_STREAM_OFF,
105 IS_ST_CHANGE_MODE,
106 IS_ST_BLOCK_CMD_CLEARED,
107 IS_ST_SET_ZOOM,
108 IS_ST_PWR_SUBIP_ON,
109 IS_ST_END,
110};
111
112enum af_state {
113 FIMC_IS_AF_IDLE = 0,
114 FIMC_IS_AF_SETCONFIG = 1,
115 FIMC_IS_AF_RUNNING = 2,
116 FIMC_IS_AF_LOCK = 3,
117 FIMC_IS_AF_ABORT = 4,
118 FIMC_IS_AF_FAILED = 5,
119};
120
121enum af_lock_state {
122 FIMC_IS_AF_UNLOCKED = 0,
123 FIMC_IS_AF_LOCKED = 2
124};
125
126enum ae_lock_state {
127 FIMC_IS_AE_UNLOCKED = 0,
128 FIMC_IS_AE_LOCKED = 1
129};
130
131enum awb_lock_state {
132 FIMC_IS_AWB_UNLOCKED = 0,
133 FIMC_IS_AWB_LOCKED = 1
134};
135
136enum {
137 IS_METERING_CONFIG_CMD,
138 IS_METERING_CONFIG_WIN_POS_X,
139 IS_METERING_CONFIG_WIN_POS_Y,
140 IS_METERING_CONFIG_WIN_WIDTH,
141 IS_METERING_CONFIG_WIN_HEIGHT,
142 IS_METERING_CONFIG_MAX
143};
144
145struct is_setfile {
146 const struct firmware *info;
147 int state;
148 u32 sub_index;
149 u32 base;
150 size_t size;
151};
152
153struct is_fd_result_header {
154 u32 offset;
155 u32 count;
156 u32 index;
157 u32 curr_index;
158 u32 width;
159 u32 height;
160};
161
162struct is_af_info {
163 u16 mode;
164 u32 af_state;
165 u32 af_lock_state;
166 u32 ae_lock_state;
167 u32 awb_lock_state;
168 u16 pos_x;
169 u16 pos_y;
170 u16 prev_pos_x;
171 u16 prev_pos_y;
172 u16 use_af;
173};
174
175struct fimc_is_firmware {
176 const struct firmware *f_w;
177
178 dma_addr_t paddr;
179 void *vaddr;
180 unsigned int size;
181
182 char info[FIMC_IS_FW_INFO_LEN + 1];
183 char version[FIMC_IS_FW_VER_LEN + 1];
184 char setfile_info[FIMC_IS_SETFILE_INFO_LEN + 1];
185 u8 state;
186};
187
188struct fimc_is_memory {
189 /* physical base address */
190 dma_addr_t paddr;
191 /* virtual base address */
192 void *vaddr;
193 /* total length */
194 unsigned int size;
195};
196
197#define FIMC_IS_I2H_MAX_ARGS 12
198
199struct i2h_cmd {
200 u32 cmd;
201 u32 sensor_id;
202 u16 num_args;
203 u32 args[FIMC_IS_I2H_MAX_ARGS];
204};
205
206struct h2i_cmd {
207 u16 cmd_type;
208 u32 entry_id;
209};
210
211#define FIMC_IS_DEBUG_MSG 0x3f
212#define FIMC_IS_DEBUG_LEVEL 3
213
214struct fimc_is_setfile {
215 const struct firmware *info;
216 unsigned int state;
217 unsigned int size;
218 u32 sub_index;
219 u32 base;
220};
221
222struct chain_config {
223 struct global_param global;
224 struct sensor_param sensor;
225 struct isp_param isp;
226 struct drc_param drc;
227 struct fd_param fd;
228
229 unsigned long p_region_index1;
230 unsigned long p_region_index2;
231};
232
233/**
234 * struct fimc_is - fimc-is data structure
235 * @pdev: pointer to FIMC-IS platform device
236 * @pctrl: pointer to pinctrl structure for this device
237 * @v4l2_dev: pointer to top the level v4l2_device
238 * @alloc_ctx: videobuf2 memory allocator context
239 * @lock: mutex serializing video device and the subdev operations
240 * @slock: spinlock protecting this data structure and the hw registers
241 * @clocks: FIMC-LITE gate clock
242 * @regs: MCUCTL mmapped registers region
243 * @pmu_regs: PMU ISP mmapped registers region
244 * @irq_queue: interrupt handling waitqueue
245 * @lpm: low power mode flag
246 * @state: internal driver's state flags
247 */
248struct fimc_is {
249 struct platform_device *pdev;
250 struct pinctrl *pctrl;
251 struct v4l2_device *v4l2_dev;
252
253 struct fimc_is_firmware fw;
254 struct fimc_is_memory memory;
255 struct firmware *f_w;
256
257 struct fimc_isp isp;
258 struct fimc_is_sensor *sensor;
259 struct fimc_is_setfile setfile;
260
261 struct vb2_alloc_ctx *alloc_ctx;
262 struct v4l2_ctrl_handler ctrl_handler;
263
264 struct mutex lock;
265 spinlock_t slock;
266
267 struct clk *clocks[ISS_CLKS_MAX];
268 bool clk_init;
269 void __iomem *regs;
270 void __iomem *pmu_regs;
271 int irq;
272 wait_queue_head_t irq_queue;
273 u8 lpm;
274
275 unsigned long state;
276 unsigned int sensor_index;
277
278 struct i2h_cmd i2h_cmd;
279 struct h2i_cmd h2i_cmd;
280 struct is_fd_result_header fd_header;
281
282 struct chain_config config[IS_SC_MAX];
283 unsigned config_index;
284
285 struct is_region *is_p_region;
286 dma_addr_t is_dma_p_region;
287 struct is_share_region *is_shared_region;
288 struct is_af_info af;
289
290 struct dentry *debugfs_entry;
291};
292
293static inline struct fimc_is *fimc_isp_to_is(struct fimc_isp *isp)
294{
295 return container_of(isp, struct fimc_is, isp);
296}
297
298static inline void fimc_is_mem_barrier(void)
299{
300 mb();
301}
302
303static inline void fimc_is_set_param_bit(struct fimc_is *is, int num)
304{
305 struct chain_config *cfg = &is->config[is->config_index];
306
307 if (num >= 32)
308 set_bit(num - 32, &cfg->p_region_index2);
309 else
310 set_bit(num, &cfg->p_region_index1);
311}
312
313static inline void fimc_is_set_param_ctrl_cmd(struct fimc_is *is, int cmd)
314{
315 is->is_p_region->parameter.isp.control.cmd = cmd;
316}
317
318static inline void mcuctl_write(u32 v, struct fimc_is *is, unsigned int offset)
319{
320 writel(v, is->regs + offset);
321}
322
323static inline u32 mcuctl_read(struct fimc_is *is, unsigned int offset)
324{
325 return readl(is->regs + offset);
326}
327
328static inline void pmuisp_write(u32 v, struct fimc_is *is, unsigned int offset)
329{
330 writel(v, is->pmu_regs + offset);
331}
332
333static inline u32 pmuisp_read(struct fimc_is *is, unsigned int offset)
334{
335 return readl(is->pmu_regs + offset);
336}
337
338int fimc_is_wait_event(struct fimc_is *is, unsigned long bit,
339 unsigned int state, unsigned int timeout);
340int fimc_is_cpu_set_power(struct fimc_is *is, int on);
341int fimc_is_start_firmware(struct fimc_is *is);
342int fimc_is_hw_initialize(struct fimc_is *is);
343void fimc_is_log_dump(const char *level, const void *buf, size_t len);
344
345#endif /* FIMC_IS_H_ */
diff --git a/drivers/media/platform/exynos4-is/fimc-isp.c b/drivers/media/platform/exynos4-is/fimc-isp.c
new file mode 100644
index 000000000000..d63947f7b302
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-isp.c
@@ -0,0 +1,703 @@
1/*
2 * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
3 *
4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
5 *
6 * Authors: Sylwester Nawrocki <s.nawrocki@samsung.com>
7 * Younghwan Joo <yhwan.joo@samsung.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
14
15#include <linux/device.h>
16#include <linux/errno.h>
17#include <linux/kernel.h>
18#include <linux/list.h>
19#include <linux/module.h>
20#include <linux/platform_device.h>
21#include <linux/printk.h>
22#include <linux/pm_runtime.h>
23#include <linux/slab.h>
24#include <linux/types.h>
25#include <media/v4l2-device.h>
26
27#include "media-dev.h"
28#include "fimc-is-command.h"
29#include "fimc-is-param.h"
30#include "fimc-is-regs.h"
31#include "fimc-is.h"
32
33static int debug;
34module_param_named(debug_isp, debug, int, S_IRUGO | S_IWUSR);
35
36static const struct fimc_fmt fimc_isp_formats[FIMC_ISP_NUM_FORMATS] = {
37 {
38 .name = "RAW8 (GRBG)",
39 .fourcc = V4L2_PIX_FMT_SGRBG8,
40 .depth = { 8 },
41 .color = FIMC_FMT_RAW8,
42 .memplanes = 1,
43 .mbus_code = V4L2_MBUS_FMT_SGRBG8_1X8,
44 }, {
45 .name = "RAW10 (GRBG)",
46 .fourcc = V4L2_PIX_FMT_SGRBG10,
47 .depth = { 10 },
48 .color = FIMC_FMT_RAW10,
49 .memplanes = 1,
50 .mbus_code = V4L2_MBUS_FMT_SGRBG10_1X10,
51 }, {
52 .name = "RAW12 (GRBG)",
53 .fourcc = V4L2_PIX_FMT_SGRBG12,
54 .depth = { 12 },
55 .color = FIMC_FMT_RAW12,
56 .memplanes = 1,
57 .mbus_code = V4L2_MBUS_FMT_SGRBG12_1X12,
58 },
59};
60
61/**
62 * fimc_isp_find_format - lookup color format by fourcc or media bus code
63 * @pixelformat: fourcc to match, ignored if null
64 * @mbus_code: media bus code to match, ignored if null
65 * @index: index to the fimc_isp_formats array, ignored if negative
66 */
67const struct fimc_fmt *fimc_isp_find_format(const u32 *pixelformat,
68 const u32 *mbus_code, int index)
69{
70 const struct fimc_fmt *fmt, *def_fmt = NULL;
71 unsigned int i;
72 int id = 0;
73
74 if (index >= (int)ARRAY_SIZE(fimc_isp_formats))
75 return NULL;
76
77 for (i = 0; i < ARRAY_SIZE(fimc_isp_formats); ++i) {
78 fmt = &fimc_isp_formats[i];
79 if (pixelformat && fmt->fourcc == *pixelformat)
80 return fmt;
81 if (mbus_code && fmt->mbus_code == *mbus_code)
82 return fmt;
83 if (index == id)
84 def_fmt = fmt;
85 id++;
86 }
87 return def_fmt;
88}
89
90void fimc_isp_irq_handler(struct fimc_is *is)
91{
92 is->i2h_cmd.args[0] = mcuctl_read(is, MCUCTL_REG_ISSR(20));
93 is->i2h_cmd.args[1] = mcuctl_read(is, MCUCTL_REG_ISSR(21));
94
95 fimc_is_fw_clear_irq1(is, FIMC_IS_INT_FRAME_DONE_ISP);
96
97 /* TODO: Complete ISP DMA interrupt handler */
98 wake_up(&is->irq_queue);
99}
100
101/* Capture subdev media entity operations */
102static int fimc_is_link_setup(struct media_entity *entity,
103 const struct media_pad *local,
104 const struct media_pad *remote, u32 flags)
105{
106 return 0;
107}
108
109static const struct media_entity_operations fimc_is_subdev_media_ops = {
110 .link_setup = fimc_is_link_setup,
111};
112
113static int fimc_is_subdev_enum_mbus_code(struct v4l2_subdev *sd,
114 struct v4l2_subdev_fh *fh,
115 struct v4l2_subdev_mbus_code_enum *code)
116{
117 const struct fimc_fmt *fmt;
118
119 fmt = fimc_isp_find_format(NULL, NULL, code->index);
120 if (!fmt)
121 return -EINVAL;
122 code->code = fmt->mbus_code;
123 return 0;
124}
125
126static int fimc_isp_subdev_get_fmt(struct v4l2_subdev *sd,
127 struct v4l2_subdev_fh *fh,
128 struct v4l2_subdev_format *fmt)
129{
130 struct fimc_isp *isp = v4l2_get_subdevdata(sd);
131 struct fimc_is *is = fimc_isp_to_is(isp);
132 struct v4l2_mbus_framefmt *mf = &fmt->format;
133 struct v4l2_mbus_framefmt cur_fmt;
134
135 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
136 mf = v4l2_subdev_get_try_format(fh, fmt->pad);
137 fmt->format = *mf;
138 return 0;
139 }
140
141 mf->colorspace = V4L2_COLORSPACE_JPEG;
142
143 mutex_lock(&isp->subdev_lock);
144 __is_get_frame_size(is, &cur_fmt);
145
146 if (fmt->pad == FIMC_ISP_SD_PAD_SINK) {
147 /* full camera input frame size */
148 mf->width = cur_fmt.width + FIMC_ISP_CAC_MARGIN_WIDTH;
149 mf->height = cur_fmt.height + FIMC_ISP_CAC_MARGIN_HEIGHT;
150 mf->code = V4L2_MBUS_FMT_SGRBG10_1X10;
151 } else {
152 /* crop size */
153 mf->width = cur_fmt.width;
154 mf->height = cur_fmt.height;
155 mf->code = V4L2_MBUS_FMT_YUV10_1X30;
156 }
157
158 mutex_unlock(&isp->subdev_lock);
159
160 v4l2_dbg(1, debug, sd, "%s: pad%d: fmt: 0x%x, %dx%d\n",
161 __func__, fmt->pad, mf->code, mf->width, mf->height);
162
163 return 0;
164}
165
166static void __isp_subdev_try_format(struct fimc_isp *isp,
167 struct v4l2_subdev_format *fmt)
168{
169 struct v4l2_mbus_framefmt *mf = &fmt->format;
170
171 if (fmt->pad == FIMC_ISP_SD_PAD_SINK) {
172 v4l_bound_align_image(&mf->width, FIMC_ISP_SINK_WIDTH_MIN,
173 FIMC_ISP_SINK_WIDTH_MAX, 0,
174 &mf->height, FIMC_ISP_SINK_HEIGHT_MIN,
175 FIMC_ISP_SINK_HEIGHT_MAX, 0, 0);
176 isp->subdev_fmt = *mf;
177 } else {
178 /* Allow changing format only on sink pad */
179 mf->width = isp->subdev_fmt.width - FIMC_ISP_CAC_MARGIN_WIDTH;
180 mf->height = isp->subdev_fmt.height - FIMC_ISP_CAC_MARGIN_HEIGHT;
181 mf->code = isp->subdev_fmt.code;
182 }
183}
184
185static int fimc_isp_subdev_set_fmt(struct v4l2_subdev *sd,
186 struct v4l2_subdev_fh *fh,
187 struct v4l2_subdev_format *fmt)
188{
189 struct fimc_isp *isp = v4l2_get_subdevdata(sd);
190 struct fimc_is *is = fimc_isp_to_is(isp);
191 struct v4l2_mbus_framefmt *mf = &fmt->format;
192 int ret = 0;
193
194 v4l2_dbg(1, debug, sd, "%s: pad%d: code: 0x%x, %dx%d\n",
195 __func__, fmt->pad, mf->code, mf->width, mf->height);
196
197 mf->colorspace = V4L2_COLORSPACE_JPEG;
198
199 mutex_lock(&isp->subdev_lock);
200 __isp_subdev_try_format(isp, fmt);
201
202 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
203 mf = v4l2_subdev_get_try_format(fh, fmt->pad);
204 *mf = fmt->format;
205 mutex_unlock(&isp->subdev_lock);
206 return 0;
207 }
208
209 if (sd->entity.stream_count == 0)
210 __is_set_frame_size(is, mf);
211 else
212 ret = -EBUSY;
213 mutex_unlock(&isp->subdev_lock);
214
215 return ret;
216}
217
218static int fimc_isp_subdev_s_stream(struct v4l2_subdev *sd, int on)
219{
220 struct fimc_isp *isp = v4l2_get_subdevdata(sd);
221 struct fimc_is *is = fimc_isp_to_is(isp);
222 int ret;
223
224 v4l2_dbg(1, debug, sd, "%s: on: %d\n", __func__, on);
225
226 if (!test_bit(IS_ST_INIT_DONE, &is->state))
227 return -EBUSY;
228
229 fimc_is_mem_barrier();
230
231 if (on) {
232 if (__get_pending_param_count(is)) {
233 ret = fimc_is_itf_s_param(is, true);
234 if (ret < 0)
235 return ret;
236 }
237
238 v4l2_dbg(1, debug, sd, "changing mode to %d\n",
239 is->config_index);
240 ret = fimc_is_itf_mode_change(is);
241 if (ret)
242 return -EINVAL;
243
244 clear_bit(IS_ST_STREAM_ON, &is->state);
245 fimc_is_hw_stream_on(is);
246 ret = fimc_is_wait_event(is, IS_ST_STREAM_ON, 1,
247 FIMC_IS_CONFIG_TIMEOUT);
248 if (ret < 0) {
249 v4l2_err(sd, "stream on timeout\n");
250 return ret;
251 }
252 } else {
253 clear_bit(IS_ST_STREAM_OFF, &is->state);
254 fimc_is_hw_stream_off(is);
255 ret = fimc_is_wait_event(is, IS_ST_STREAM_OFF, 1,
256 FIMC_IS_CONFIG_TIMEOUT);
257 if (ret < 0) {
258 v4l2_err(sd, "stream off timeout\n");
259 return ret;
260 }
261 is->setfile.sub_index = 0;
262 }
263
264 return 0;
265}
266
267static int fimc_isp_subdev_s_power(struct v4l2_subdev *sd, int on)
268{
269 struct fimc_isp *isp = v4l2_get_subdevdata(sd);
270 struct fimc_is *is = fimc_isp_to_is(isp);
271 int ret = 0;
272
273 pr_debug("on: %d\n", on);
274
275 if (on) {
276 ret = pm_runtime_get_sync(&is->pdev->dev);
277 if (ret < 0)
278 return ret;
279 set_bit(IS_ST_PWR_ON, &is->state);
280
281 ret = fimc_is_start_firmware(is);
282 if (ret < 0) {
283 v4l2_err(sd, "firmware booting failed\n");
284 pm_runtime_put(&is->pdev->dev);
285 return ret;
286 }
287 set_bit(IS_ST_PWR_SUBIP_ON, &is->state);
288
289 ret = fimc_is_hw_initialize(is);
290 } else {
291 /* Close sensor */
292 if (!test_bit(IS_ST_PWR_ON, &is->state)) {
293 fimc_is_hw_close_sensor(is, 0);
294
295 ret = fimc_is_wait_event(is, IS_ST_OPEN_SENSOR, 0,
296 FIMC_IS_CONFIG_TIMEOUT);
297 if (ret < 0) {
298 v4l2_err(sd, "sensor close timeout\n");
299 return ret;
300 }
301 }
302
303 /* SUB IP power off */
304 if (test_bit(IS_ST_PWR_SUBIP_ON, &is->state)) {
305 fimc_is_hw_subip_power_off(is);
306 ret = fimc_is_wait_event(is, IS_ST_PWR_SUBIP_ON, 0,
307 FIMC_IS_CONFIG_TIMEOUT);
308 if (ret < 0) {
309 v4l2_err(sd, "sub-IP power off timeout\n");
310 return ret;
311 }
312 }
313
314 fimc_is_cpu_set_power(is, 0);
315 pm_runtime_put_sync(&is->pdev->dev);
316
317 clear_bit(IS_ST_PWR_ON, &is->state);
318 clear_bit(IS_ST_INIT_DONE, &is->state);
319 is->state = 0;
320 is->config[is->config_index].p_region_index1 = 0;
321 is->config[is->config_index].p_region_index2 = 0;
322 set_bit(IS_ST_IDLE, &is->state);
323 wmb();
324 }
325
326 return ret;
327}
328
329static int fimc_isp_subdev_open(struct v4l2_subdev *sd,
330 struct v4l2_subdev_fh *fh)
331{
332 struct v4l2_mbus_framefmt fmt;
333 struct v4l2_mbus_framefmt *format;
334
335 format = v4l2_subdev_get_try_format(fh, FIMC_ISP_SD_PAD_SINK);
336
337 fmt.colorspace = V4L2_COLORSPACE_SRGB;
338 fmt.code = fimc_isp_formats[0].mbus_code;
339 fmt.width = DEFAULT_PREVIEW_STILL_WIDTH + FIMC_ISP_CAC_MARGIN_WIDTH;
340 fmt.height = DEFAULT_PREVIEW_STILL_HEIGHT + FIMC_ISP_CAC_MARGIN_HEIGHT;
341 fmt.field = V4L2_FIELD_NONE;
342 *format = fmt;
343
344 format = v4l2_subdev_get_try_format(fh, FIMC_ISP_SD_PAD_SRC_FIFO);
345 fmt.width = DEFAULT_PREVIEW_STILL_WIDTH;
346 fmt.height = DEFAULT_PREVIEW_STILL_HEIGHT;
347 *format = fmt;
348
349 format = v4l2_subdev_get_try_format(fh, FIMC_ISP_SD_PAD_SRC_DMA);
350 *format = fmt;
351
352 return 0;
353}
354
355static const struct v4l2_subdev_internal_ops fimc_is_subdev_internal_ops = {
356 .open = fimc_isp_subdev_open,
357};
358
359static const struct v4l2_subdev_pad_ops fimc_is_subdev_pad_ops = {
360 .enum_mbus_code = fimc_is_subdev_enum_mbus_code,
361 .get_fmt = fimc_isp_subdev_get_fmt,
362 .set_fmt = fimc_isp_subdev_set_fmt,
363};
364
365static const struct v4l2_subdev_video_ops fimc_is_subdev_video_ops = {
366 .s_stream = fimc_isp_subdev_s_stream,
367};
368
369static const struct v4l2_subdev_core_ops fimc_is_core_ops = {
370 .s_power = fimc_isp_subdev_s_power,
371};
372
373static struct v4l2_subdev_ops fimc_is_subdev_ops = {
374 .core = &fimc_is_core_ops,
375 .video = &fimc_is_subdev_video_ops,
376 .pad = &fimc_is_subdev_pad_ops,
377};
378
379static int __ctrl_set_white_balance(struct fimc_is *is, int value)
380{
381 switch (value) {
382 case V4L2_WHITE_BALANCE_AUTO:
383 __is_set_isp_awb(is, ISP_AWB_COMMAND_AUTO, 0);
384 break;
385 case V4L2_WHITE_BALANCE_DAYLIGHT:
386 __is_set_isp_awb(is, ISP_AWB_COMMAND_ILLUMINATION,
387 ISP_AWB_ILLUMINATION_DAYLIGHT);
388 break;
389 case V4L2_WHITE_BALANCE_CLOUDY:
390 __is_set_isp_awb(is, ISP_AWB_COMMAND_ILLUMINATION,
391 ISP_AWB_ILLUMINATION_CLOUDY);
392 break;
393 case V4L2_WHITE_BALANCE_INCANDESCENT:
394 __is_set_isp_awb(is, ISP_AWB_COMMAND_ILLUMINATION,
395 ISP_AWB_ILLUMINATION_TUNGSTEN);
396 break;
397 case V4L2_WHITE_BALANCE_FLUORESCENT:
398 __is_set_isp_awb(is, ISP_AWB_COMMAND_ILLUMINATION,
399 ISP_AWB_ILLUMINATION_FLUORESCENT);
400 break;
401 default:
402 return -EINVAL;
403 }
404
405 return 0;
406}
407
408static int __ctrl_set_aewb_lock(struct fimc_is *is,
409 struct v4l2_ctrl *ctrl)
410{
411 bool awb_lock = ctrl->val & V4L2_LOCK_WHITE_BALANCE;
412 bool ae_lock = ctrl->val & V4L2_LOCK_EXPOSURE;
413 struct isp_param *isp = &is->is_p_region->parameter.isp;
414 int cmd, ret;
415
416 cmd = ae_lock ? ISP_AA_COMMAND_STOP : ISP_AA_COMMAND_START;
417 isp->aa.cmd = cmd;
418 isp->aa.target = ISP_AA_TARGET_AE;
419 fimc_is_set_param_bit(is, PARAM_ISP_AA);
420 is->af.ae_lock_state = ae_lock;
421 wmb();
422
423 ret = fimc_is_itf_s_param(is, false);
424 if (ret < 0)
425 return ret;
426
427 cmd = awb_lock ? ISP_AA_COMMAND_STOP : ISP_AA_COMMAND_START;
428 isp->aa.cmd = cmd;
429 isp->aa.target = ISP_AA_TARGET_AE;
430 fimc_is_set_param_bit(is, PARAM_ISP_AA);
431 is->af.awb_lock_state = awb_lock;
432 wmb();
433
434 return fimc_is_itf_s_param(is, false);
435}
436
437/* Supported manual ISO values */
438static const s64 iso_qmenu[] = {
439 50, 100, 200, 400, 800,
440};
441
442static int __ctrl_set_iso(struct fimc_is *is, int value)
443{
444 unsigned int idx, iso;
445
446 if (value == V4L2_ISO_SENSITIVITY_AUTO) {
447 __is_set_isp_iso(is, ISP_ISO_COMMAND_AUTO, 0);
448 return 0;
449 }
450 idx = is->isp.ctrls.iso->val;
451 if (idx >= ARRAY_SIZE(iso_qmenu))
452 return -EINVAL;
453
454 iso = iso_qmenu[idx];
455 __is_set_isp_iso(is, ISP_ISO_COMMAND_MANUAL, iso);
456 return 0;
457}
458
459static int __ctrl_set_metering(struct fimc_is *is, unsigned int value)
460{
461 unsigned int val;
462
463 switch (value) {
464 case V4L2_EXPOSURE_METERING_AVERAGE:
465 val = ISP_METERING_COMMAND_AVERAGE;
466 break;
467 case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED:
468 val = ISP_METERING_COMMAND_CENTER;
469 break;
470 case V4L2_EXPOSURE_METERING_SPOT:
471 val = ISP_METERING_COMMAND_SPOT;
472 break;
473 case V4L2_EXPOSURE_METERING_MATRIX:
474 val = ISP_METERING_COMMAND_MATRIX;
475 break;
476 default:
477 return -EINVAL;
478 };
479
480 __is_set_isp_metering(is, IS_METERING_CONFIG_CMD, val);
481 return 0;
482}
483
484static int __ctrl_set_afc(struct fimc_is *is, int value)
485{
486 switch (value) {
487 case V4L2_CID_POWER_LINE_FREQUENCY_DISABLED:
488 __is_set_isp_afc(is, ISP_AFC_COMMAND_DISABLE, 0);
489 break;
490 case V4L2_CID_POWER_LINE_FREQUENCY_50HZ:
491 __is_set_isp_afc(is, ISP_AFC_COMMAND_MANUAL, 50);
492 break;
493 case V4L2_CID_POWER_LINE_FREQUENCY_60HZ:
494 __is_set_isp_afc(is, ISP_AFC_COMMAND_MANUAL, 60);
495 break;
496 case V4L2_CID_POWER_LINE_FREQUENCY_AUTO:
497 __is_set_isp_afc(is, ISP_AFC_COMMAND_AUTO, 0);
498 break;
499 default:
500 return -EINVAL;
501 }
502
503 return 0;
504}
505
506static int __ctrl_set_image_effect(struct fimc_is *is, int value)
507{
508 static const u8 effects[][2] = {
509 { V4L2_COLORFX_NONE, ISP_IMAGE_EFFECT_DISABLE },
510 { V4L2_COLORFX_BW, ISP_IMAGE_EFFECT_MONOCHROME },
511 { V4L2_COLORFX_SEPIA, ISP_IMAGE_EFFECT_SEPIA },
512 { V4L2_COLORFX_NEGATIVE, ISP_IMAGE_EFFECT_NEGATIVE_MONO },
513 { 16 /* TODO */, ISP_IMAGE_EFFECT_NEGATIVE_COLOR },
514 };
515 int i;
516
517 for (i = 0; i < ARRAY_SIZE(effects); i++) {
518 if (effects[i][0] != value)
519 continue;
520
521 __is_set_isp_effect(is, effects[i][1]);
522 return 0;
523 }
524
525 return -EINVAL;
526}
527
528static int fimc_is_s_ctrl(struct v4l2_ctrl *ctrl)
529{
530 struct fimc_isp *isp = ctrl_to_fimc_isp(ctrl);
531 struct fimc_is *is = fimc_isp_to_is(isp);
532 bool set_param = true;
533 int ret = 0;
534
535 switch (ctrl->id) {
536 case V4L2_CID_CONTRAST:
537 __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_CONTRAST,
538 ctrl->val);
539 break;
540
541 case V4L2_CID_SATURATION:
542 __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_SATURATION,
543 ctrl->val);
544 break;
545
546 case V4L2_CID_SHARPNESS:
547 __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_SHARPNESS,
548 ctrl->val);
549 break;
550
551 case V4L2_CID_EXPOSURE_ABSOLUTE:
552 __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_EXPOSURE,
553 ctrl->val);
554 break;
555
556 case V4L2_CID_BRIGHTNESS:
557 __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_BRIGHTNESS,
558 ctrl->val);
559 break;
560
561 case V4L2_CID_HUE:
562 __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_HUE,
563 ctrl->val);
564 break;
565
566 case V4L2_CID_EXPOSURE_METERING:
567 ret = __ctrl_set_metering(is, ctrl->val);
568 break;
569
570 case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE:
571 ret = __ctrl_set_white_balance(is, ctrl->val);
572 break;
573
574 case V4L2_CID_3A_LOCK:
575 ret = __ctrl_set_aewb_lock(is, ctrl);
576 set_param = false;
577 break;
578
579 case V4L2_CID_ISO_SENSITIVITY_AUTO:
580 ret = __ctrl_set_iso(is, ctrl->val);
581 break;
582
583 case V4L2_CID_POWER_LINE_FREQUENCY:
584 ret = __ctrl_set_afc(is, ctrl->val);
585 break;
586
587 case V4L2_CID_COLORFX:
588 __ctrl_set_image_effect(is, ctrl->val);
589 break;
590
591 default:
592 ret = -EINVAL;
593 break;
594 }
595
596 if (ret < 0) {
597 v4l2_err(&isp->subdev, "Failed to set control: %s (%d)\n",
598 ctrl->name, ctrl->val);
599 return ret;
600 }
601
602 if (set_param && test_bit(IS_ST_STREAM_ON, &is->state))
603 return fimc_is_itf_s_param(is, true);
604
605 return 0;
606}
607
608static const struct v4l2_ctrl_ops fimc_isp_ctrl_ops = {
609 .s_ctrl = fimc_is_s_ctrl,
610};
611
612int fimc_isp_subdev_create(struct fimc_isp *isp)
613{
614 const struct v4l2_ctrl_ops *ops = &fimc_isp_ctrl_ops;
615 struct v4l2_ctrl_handler *handler = &isp->ctrls.handler;
616 struct v4l2_subdev *sd = &isp->subdev;
617 struct fimc_isp_ctrls *ctrls = &isp->ctrls;
618 int ret;
619
620 mutex_init(&isp->subdev_lock);
621
622 v4l2_subdev_init(sd, &fimc_is_subdev_ops);
623 sd->grp_id = GRP_ID_FIMC_IS;
624 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
625 snprintf(sd->name, sizeof(sd->name), "FIMC-IS-ISP");
626
627 isp->subdev_pads[FIMC_ISP_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
628 isp->subdev_pads[FIMC_ISP_SD_PAD_SRC_FIFO].flags = MEDIA_PAD_FL_SOURCE;
629 isp->subdev_pads[FIMC_ISP_SD_PAD_SRC_DMA].flags = MEDIA_PAD_FL_SOURCE;
630 ret = media_entity_init(&sd->entity, FIMC_ISP_SD_PADS_NUM,
631 isp->subdev_pads, 0);
632 if (ret)
633 return ret;
634
635 v4l2_ctrl_handler_init(handler, 20);
636
637 ctrls->saturation = v4l2_ctrl_new_std(handler, ops, V4L2_CID_SATURATION,
638 -2, 2, 1, 0);
639 ctrls->brightness = v4l2_ctrl_new_std(handler, ops, V4L2_CID_BRIGHTNESS,
640 -4, 4, 1, 0);
641 ctrls->contrast = v4l2_ctrl_new_std(handler, ops, V4L2_CID_CONTRAST,
642 -2, 2, 1, 0);
643 ctrls->sharpness = v4l2_ctrl_new_std(handler, ops, V4L2_CID_SHARPNESS,
644 -2, 2, 1, 0);
645 ctrls->hue = v4l2_ctrl_new_std(handler, ops, V4L2_CID_HUE,
646 -2, 2, 1, 0);
647
648 ctrls->auto_wb = v4l2_ctrl_new_std_menu(handler, ops,
649 V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE,
650 8, ~0x14e, V4L2_WHITE_BALANCE_AUTO);
651
652 ctrls->exposure = v4l2_ctrl_new_std(handler, ops,
653 V4L2_CID_EXPOSURE_ABSOLUTE,
654 -4, 4, 1, 0);
655
656 ctrls->exp_metering = v4l2_ctrl_new_std_menu(handler, ops,
657 V4L2_CID_EXPOSURE_METERING, 3,
658 ~0xf, V4L2_EXPOSURE_METERING_AVERAGE);
659
660 v4l2_ctrl_new_std_menu(handler, ops, V4L2_CID_POWER_LINE_FREQUENCY,
661 V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0,
662 V4L2_CID_POWER_LINE_FREQUENCY_AUTO);
663 /* ISO sensitivity */
664 ctrls->auto_iso = v4l2_ctrl_new_std_menu(handler, ops,
665 V4L2_CID_ISO_SENSITIVITY_AUTO, 1, 0,
666 V4L2_ISO_SENSITIVITY_AUTO);
667
668 ctrls->iso = v4l2_ctrl_new_int_menu(handler, ops,
669 V4L2_CID_ISO_SENSITIVITY, ARRAY_SIZE(iso_qmenu) - 1,
670 ARRAY_SIZE(iso_qmenu)/2 - 1, iso_qmenu);
671
672 ctrls->aewb_lock = v4l2_ctrl_new_std(handler, ops,
673 V4L2_CID_3A_LOCK, 0, 0x3, 0, 0);
674
675 /* TODO: Add support for NEGATIVE_COLOR option */
676 ctrls->colorfx = v4l2_ctrl_new_std_menu(handler, ops, V4L2_CID_COLORFX,
677 V4L2_COLORFX_SET_CBCR + 1, ~0x1000f, V4L2_COLORFX_NONE);
678
679 if (handler->error) {
680 media_entity_cleanup(&sd->entity);
681 return handler->error;
682 }
683
684 v4l2_ctrl_auto_cluster(2, &ctrls->auto_iso,
685 V4L2_ISO_SENSITIVITY_MANUAL, false);
686
687 sd->ctrl_handler = handler;
688 sd->internal_ops = &fimc_is_subdev_internal_ops;
689 sd->entity.ops = &fimc_is_subdev_media_ops;
690 v4l2_set_subdevdata(sd, isp);
691
692 return 0;
693}
694
695void fimc_isp_subdev_destroy(struct fimc_isp *isp)
696{
697 struct v4l2_subdev *sd = &isp->subdev;
698
699 v4l2_device_unregister_subdev(sd);
700 media_entity_cleanup(&sd->entity);
701 v4l2_ctrl_handler_free(&isp->ctrls.handler);
702 v4l2_set_subdevdata(sd, NULL);
703}
diff --git a/drivers/media/platform/exynos4-is/fimc-isp.h b/drivers/media/platform/exynos4-is/fimc-isp.h
new file mode 100644
index 000000000000..800aba7ab4a7
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-isp.h
@@ -0,0 +1,181 @@
1/*
2 * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
3 *
4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
5 *
6 * Authors: Sylwester Nawrocki <s.nawrocki@samsung.com>
7 * Younghwan Joo <yhwan.joo@samsung.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13#ifndef FIMC_ISP_H_
14#define FIMC_ISP_H_
15
16#include <linux/io.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/videobuf2-core.h>
25#include <media/v4l2-device.h>
26#include <media/v4l2-mediabus.h>
27#include <media/s5p_fimc.h>
28
29/* FIXME: revisit these constraints */
30#define FIMC_ISP_SINK_WIDTH_MIN (16 + 8)
31#define FIMC_ISP_SINK_HEIGHT_MIN (12 + 8)
32#define FIMC_ISP_SOURCE_WIDTH_MIN 8
33#define FIMC_ISP_SOURC_HEIGHT_MIN 8
34#define FIMC_ISP_CAC_MARGIN_WIDTH 16
35#define FIMC_ISP_CAC_MARGIN_HEIGHT 12
36
37#define FIMC_ISP_SINK_WIDTH_MAX (4000 - 16)
38#define FIMC_ISP_SINK_HEIGHT_MAX (4000 + 12)
39#define FIMC_ISP_SOURCE_WIDTH_MAX 4000
40#define FIMC_ISP_SOURC_HEIGHT_MAX 4000
41
42#define FIMC_ISP_NUM_FORMATS 3
43#define FIMC_ISP_REQ_BUFS_MIN 2
44
45#define FIMC_ISP_SD_PAD_SINK 0
46#define FIMC_ISP_SD_PAD_SRC_FIFO 1
47#define FIMC_ISP_SD_PAD_SRC_DMA 2
48#define FIMC_ISP_SD_PADS_NUM 3
49#define FIMC_ISP_MAX_PLANES 1
50
51/**
52 * struct fimc_isp_frame - source/target frame properties
53 * @width: full image width
54 * @height: full image height
55 * @rect: crop/composition rectangle
56 */
57struct fimc_isp_frame {
58 u16 width;
59 u16 height;
60 struct v4l2_rect rect;
61};
62
63struct fimc_isp_ctrls {
64 struct v4l2_ctrl_handler handler;
65
66 /* Auto white balance */
67 struct v4l2_ctrl *auto_wb;
68 /* Auto ISO control cluster */
69 struct {
70 struct v4l2_ctrl *auto_iso;
71 struct v4l2_ctrl *iso;
72 };
73 /* Adjust - contrast */
74 struct v4l2_ctrl *contrast;
75 /* Adjust - saturation */
76 struct v4l2_ctrl *saturation;
77 /* Adjust - sharpness */
78 struct v4l2_ctrl *sharpness;
79 /* Adjust - brightness */
80 struct v4l2_ctrl *brightness;
81 /* Adjust - hue */
82 struct v4l2_ctrl *hue;
83
84 /* Auto/manual exposure */
85 struct v4l2_ctrl *auto_exp;
86 /* Manual exposure value */
87 struct v4l2_ctrl *exposure;
88 /* AE/AWB lock/unlock */
89 struct v4l2_ctrl *aewb_lock;
90 /* Exposure metering mode */
91 struct v4l2_ctrl *exp_metering;
92 /* AFC */
93 struct v4l2_ctrl *afc;
94 /* ISP image effect */
95 struct v4l2_ctrl *colorfx;
96};
97
98/**
99 * struct fimc_is_video - fimc-is video device structure
100 * @vdev: video_device structure
101 * @type: video device type (CAPTURE/OUTPUT)
102 * @pad: video device media (sink) pad
103 * @pending_buf_q: pending buffers queue head
104 * @active_buf_q: a queue head of buffers scheduled in hardware
105 * @vb_queue: vb2 buffer queue
106 * @active_buf_count: number of video buffers scheduled in hardware
107 * @frame_count: counter of frames dequeued to user space
108 * @reqbufs_count: number of buffers requested with REQBUFS ioctl
109 * @format: current pixel format
110 */
111struct fimc_is_video {
112 struct video_device vdev;
113 enum v4l2_buf_type type;
114 struct media_pad pad;
115 struct list_head pending_buf_q;
116 struct list_head active_buf_q;
117 struct vb2_queue vb_queue;
118 unsigned int frame_count;
119 unsigned int reqbufs_count;
120 int streaming;
121 unsigned long payload[FIMC_ISP_MAX_PLANES];
122 const struct fimc_fmt *format;
123};
124
125/**
126 * struct fimc_isp - FIMC-IS ISP data structure
127 * @pdev: pointer to FIMC-IS platform device
128 * @alloc_ctx: videobuf2 memory allocator context
129 * @subdev: ISP v4l2_subdev
130 * @subdev_pads: the ISP subdev media pads
131 * @ctrl_handler: v4l2 controls handler
132 * @test_pattern: test pattern controls
133 * @pipeline: video capture pipeline data structure
134 * @video_lock: mutex serializing video device and the subdev operations
135 * @fmt: pointer to color format description structure
136 * @payload: image size in bytes (w x h x bpp)
137 * @inp_frame: camera input frame structure
138 * @out_frame: DMA output frame structure
139 * @source_subdev_grp_id: group id of remote source subdev
140 * @cac_margin_x: horizontal CAC margin in pixels
141 * @cac_margin_y: vertical CAC margin in pixels
142 * @state: driver state flags
143 * @video_capture: the ISP block video capture device
144 */
145struct fimc_isp {
146 struct platform_device *pdev;
147 struct vb2_alloc_ctx *alloc_ctx;
148 struct v4l2_subdev subdev;
149 struct media_pad subdev_pads[FIMC_ISP_SD_PADS_NUM];
150 struct v4l2_mbus_framefmt subdev_fmt;
151 struct v4l2_ctrl *test_pattern;
152 struct fimc_isp_ctrls ctrls;
153
154 struct mutex video_lock;
155 struct mutex subdev_lock;
156
157 struct fimc_isp_frame inp_frame;
158 struct fimc_isp_frame out_frame;
159 unsigned int source_subdev_grp_id;
160
161 unsigned int cac_margin_x;
162 unsigned int cac_margin_y;
163
164 unsigned long state;
165
166 struct fimc_is_video video_capture;
167};
168
169#define ctrl_to_fimc_isp(_ctrl) \
170 container_of(ctrl->handler, struct fimc_isp, ctrls.handler)
171
172struct fimc_is;
173
174int fimc_isp_subdev_create(struct fimc_isp *isp);
175void fimc_isp_subdev_destroy(struct fimc_isp *isp);
176void fimc_isp_irq_handler(struct fimc_is *is);
177int fimc_is_create_controls(struct fimc_isp *isp);
178int fimc_is_delete_controls(struct fimc_isp *isp);
179const struct fimc_fmt *fimc_isp_find_format(const u32 *pixelformat,
180 const u32 *mbus_code, int index);
181#endif /* FIMC_ISP_H_ */
diff --git a/drivers/media/platform/exynos4-is/fimc-lite-reg.c b/drivers/media/platform/exynos4-is/fimc-lite-reg.c
new file mode 100644
index 000000000000..8cc0d39a2fea
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-lite-reg.c
@@ -0,0 +1,302 @@
1/*
2 * Register interface file for EXYNOS FIMC-LITE (camera interface) driver
3 *
4 * Copyright (C) 2012 Samsung Electronics Co., Ltd.
5 * Sylwester Nawrocki <s.nawrocki@samsung.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#include <linux/io.h>
13#include <linux/delay.h>
14#include <media/s5p_fimc.h>
15
16#include "fimc-lite-reg.h"
17#include "fimc-lite.h"
18#include "fimc-core.h"
19
20#define FLITE_RESET_TIMEOUT 50 /* in ms */
21
22void flite_hw_reset(struct fimc_lite *dev)
23{
24 unsigned long end = jiffies + msecs_to_jiffies(FLITE_RESET_TIMEOUT);
25 u32 cfg;
26
27 cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
28 cfg |= FLITE_REG_CIGCTRL_SWRST_REQ;
29 writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
30
31 while (time_is_after_jiffies(end)) {
32 cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
33 if (cfg & FLITE_REG_CIGCTRL_SWRST_RDY)
34 break;
35 usleep_range(1000, 5000);
36 }
37
38 cfg |= FLITE_REG_CIGCTRL_SWRST;
39 writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
40}
41
42void flite_hw_clear_pending_irq(struct fimc_lite *dev)
43{
44 u32 cfg = readl(dev->regs + FLITE_REG_CISTATUS);
45 cfg &= ~FLITE_REG_CISTATUS_IRQ_CAM;
46 writel(cfg, dev->regs + FLITE_REG_CISTATUS);
47}
48
49u32 flite_hw_get_interrupt_source(struct fimc_lite *dev)
50{
51 u32 intsrc = readl(dev->regs + FLITE_REG_CISTATUS);
52 return intsrc & FLITE_REG_CISTATUS_IRQ_MASK;
53}
54
55void flite_hw_clear_last_capture_end(struct fimc_lite *dev)
56{
57
58 u32 cfg = readl(dev->regs + FLITE_REG_CISTATUS2);
59 cfg &= ~FLITE_REG_CISTATUS2_LASTCAPEND;
60 writel(cfg, dev->regs + FLITE_REG_CISTATUS2);
61}
62
63void flite_hw_set_interrupt_mask(struct fimc_lite *dev)
64{
65 u32 cfg, intsrc;
66
67 /* Select interrupts to be enabled for each output mode */
68 if (atomic_read(&dev->out_path) == FIMC_IO_DMA) {
69 intsrc = FLITE_REG_CIGCTRL_IRQ_OVFEN |
70 FLITE_REG_CIGCTRL_IRQ_LASTEN |
71 FLITE_REG_CIGCTRL_IRQ_STARTEN;
72 } else {
73 /* An output to the FIMC-IS */
74 intsrc = FLITE_REG_CIGCTRL_IRQ_OVFEN |
75 FLITE_REG_CIGCTRL_IRQ_LASTEN;
76 }
77
78 cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
79 cfg |= FLITE_REG_CIGCTRL_IRQ_DISABLE_MASK;
80 cfg &= ~intsrc;
81 writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
82}
83
84void flite_hw_capture_start(struct fimc_lite *dev)
85{
86 u32 cfg = readl(dev->regs + FLITE_REG_CIIMGCPT);
87 cfg |= FLITE_REG_CIIMGCPT_IMGCPTEN;
88 writel(cfg, dev->regs + FLITE_REG_CIIMGCPT);
89}
90
91void flite_hw_capture_stop(struct fimc_lite *dev)
92{
93 u32 cfg = readl(dev->regs + FLITE_REG_CIIMGCPT);
94 cfg &= ~FLITE_REG_CIIMGCPT_IMGCPTEN;
95 writel(cfg, dev->regs + FLITE_REG_CIIMGCPT);
96}
97
98/*
99 * Test pattern (color bars) enable/disable. External sensor
100 * pixel clock must be active for the test pattern to work.
101 */
102void flite_hw_set_test_pattern(struct fimc_lite *dev, bool on)
103{
104 u32 cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
105 if (on)
106 cfg |= FLITE_REG_CIGCTRL_TEST_PATTERN_COLORBAR;
107 else
108 cfg &= ~FLITE_REG_CIGCTRL_TEST_PATTERN_COLORBAR;
109 writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
110}
111
112static const u32 src_pixfmt_map[8][3] = {
113 { V4L2_MBUS_FMT_YUYV8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_YCBYCR,
114 FLITE_REG_CIGCTRL_YUV422_1P },
115 { V4L2_MBUS_FMT_YVYU8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_YCRYCB,
116 FLITE_REG_CIGCTRL_YUV422_1P },
117 { V4L2_MBUS_FMT_UYVY8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_CBYCRY,
118 FLITE_REG_CIGCTRL_YUV422_1P },
119 { V4L2_MBUS_FMT_VYUY8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_CRYCBY,
120 FLITE_REG_CIGCTRL_YUV422_1P },
121 { V4L2_MBUS_FMT_SGRBG8_1X8, 0, FLITE_REG_CIGCTRL_RAW8 },
122 { V4L2_MBUS_FMT_SGRBG10_1X10, 0, FLITE_REG_CIGCTRL_RAW10 },
123 { V4L2_MBUS_FMT_SGRBG12_1X12, 0, FLITE_REG_CIGCTRL_RAW12 },
124 { V4L2_MBUS_FMT_JPEG_1X8, 0, FLITE_REG_CIGCTRL_USER(1) },
125};
126
127/* Set camera input pixel format and resolution */
128void flite_hw_set_source_format(struct fimc_lite *dev, struct flite_frame *f)
129{
130 enum v4l2_mbus_pixelcode pixelcode = f->fmt->mbus_code;
131 int i = ARRAY_SIZE(src_pixfmt_map);
132 u32 cfg;
133
134 while (--i >= 0) {
135 if (src_pixfmt_map[i][0] == pixelcode)
136 break;
137 }
138
139 if (i == 0 && src_pixfmt_map[i][0] != pixelcode) {
140 v4l2_err(&dev->vfd,
141 "Unsupported pixel code, falling back to %#08x\n",
142 src_pixfmt_map[i][0]);
143 }
144
145 cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
146 cfg &= ~FLITE_REG_CIGCTRL_FMT_MASK;
147 cfg |= src_pixfmt_map[i][2];
148 writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
149
150 cfg = readl(dev->regs + FLITE_REG_CISRCSIZE);
151 cfg &= ~(FLITE_REG_CISRCSIZE_ORDER422_MASK |
152 FLITE_REG_CISRCSIZE_SIZE_CAM_MASK);
153 cfg |= (f->f_width << 16) | f->f_height;
154 cfg |= src_pixfmt_map[i][1];
155 writel(cfg, dev->regs + FLITE_REG_CISRCSIZE);
156}
157
158/* Set the camera host input window offsets (cropping) */
159void flite_hw_set_window_offset(struct fimc_lite *dev, struct flite_frame *f)
160{
161 u32 hoff2, voff2;
162 u32 cfg;
163
164 cfg = readl(dev->regs + FLITE_REG_CIWDOFST);
165 cfg &= ~FLITE_REG_CIWDOFST_OFST_MASK;
166 cfg |= (f->rect.left << 16) | f->rect.top;
167 cfg |= FLITE_REG_CIWDOFST_WINOFSEN;
168 writel(cfg, dev->regs + FLITE_REG_CIWDOFST);
169
170 hoff2 = f->f_width - f->rect.width - f->rect.left;
171 voff2 = f->f_height - f->rect.height - f->rect.top;
172
173 cfg = (hoff2 << 16) | voff2;
174 writel(cfg, dev->regs + FLITE_REG_CIWDOFST2);
175}
176
177/* Select camera port (A, B) */
178static void flite_hw_set_camera_port(struct fimc_lite *dev, int id)
179{
180 u32 cfg = readl(dev->regs + FLITE_REG_CIGENERAL);
181 if (id == 0)
182 cfg &= ~FLITE_REG_CIGENERAL_CAM_B;
183 else
184 cfg |= FLITE_REG_CIGENERAL_CAM_B;
185 writel(cfg, dev->regs + FLITE_REG_CIGENERAL);
186}
187
188/* Select serial or parallel bus, camera port (A,B) and set signals polarity */
189void flite_hw_set_camera_bus(struct fimc_lite *dev,
190 struct fimc_source_info *si)
191{
192 u32 cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
193 unsigned int flags = si->flags;
194
195 if (si->sensor_bus_type != FIMC_BUS_TYPE_MIPI_CSI2) {
196 cfg &= ~(FLITE_REG_CIGCTRL_SELCAM_MIPI |
197 FLITE_REG_CIGCTRL_INVPOLPCLK |
198 FLITE_REG_CIGCTRL_INVPOLVSYNC |
199 FLITE_REG_CIGCTRL_INVPOLHREF);
200
201 if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
202 cfg |= FLITE_REG_CIGCTRL_INVPOLPCLK;
203
204 if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
205 cfg |= FLITE_REG_CIGCTRL_INVPOLVSYNC;
206
207 if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
208 cfg |= FLITE_REG_CIGCTRL_INVPOLHREF;
209 } else {
210 cfg |= FLITE_REG_CIGCTRL_SELCAM_MIPI;
211 }
212
213 writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
214
215 flite_hw_set_camera_port(dev, si->mux_id);
216}
217
218static void flite_hw_set_out_order(struct fimc_lite *dev, struct flite_frame *f)
219{
220 static const u32 pixcode[4][2] = {
221 { V4L2_MBUS_FMT_YUYV8_2X8, FLITE_REG_CIODMAFMT_YCBYCR },
222 { V4L2_MBUS_FMT_YVYU8_2X8, FLITE_REG_CIODMAFMT_YCRYCB },
223 { V4L2_MBUS_FMT_UYVY8_2X8, FLITE_REG_CIODMAFMT_CBYCRY },
224 { V4L2_MBUS_FMT_VYUY8_2X8, FLITE_REG_CIODMAFMT_CRYCBY },
225 };
226 u32 cfg = readl(dev->regs + FLITE_REG_CIODMAFMT);
227 int i = ARRAY_SIZE(pixcode);
228
229 while (--i >= 0)
230 if (pixcode[i][0] == f->fmt->mbus_code)
231 break;
232 cfg &= ~FLITE_REG_CIODMAFMT_YCBCR_ORDER_MASK;
233 writel(cfg | pixcode[i][1], dev->regs + FLITE_REG_CIODMAFMT);
234}
235
236void flite_hw_set_dma_window(struct fimc_lite *dev, struct flite_frame *f)
237{
238 u32 cfg;
239
240 /* Maximum output pixel size */
241 cfg = readl(dev->regs + FLITE_REG_CIOCAN);
242 cfg &= ~FLITE_REG_CIOCAN_MASK;
243 cfg = (f->f_height << 16) | f->f_width;
244 writel(cfg, dev->regs + FLITE_REG_CIOCAN);
245
246 /* DMA offsets */
247 cfg = readl(dev->regs + FLITE_REG_CIOOFF);
248 cfg &= ~FLITE_REG_CIOOFF_MASK;
249 cfg |= (f->rect.top << 16) | f->rect.left;
250 writel(cfg, dev->regs + FLITE_REG_CIOOFF);
251}
252
253/* Enable/disable output DMA, set output pixel size and offsets (composition) */
254void flite_hw_set_output_dma(struct fimc_lite *dev, struct flite_frame *f,
255 bool enable)
256{
257 u32 cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
258
259 if (!enable) {
260 cfg |= FLITE_REG_CIGCTRL_ODMA_DISABLE;
261 writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
262 return;
263 }
264
265 cfg &= ~FLITE_REG_CIGCTRL_ODMA_DISABLE;
266 writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
267
268 flite_hw_set_out_order(dev, f);
269 flite_hw_set_dma_window(dev, f);
270}
271
272void flite_hw_dump_regs(struct fimc_lite *dev, const char *label)
273{
274 struct {
275 u32 offset;
276 const char * const name;
277 } registers[] = {
278 { 0x00, "CISRCSIZE" },
279 { 0x04, "CIGCTRL" },
280 { 0x08, "CIIMGCPT" },
281 { 0x0c, "CICPTSEQ" },
282 { 0x10, "CIWDOFST" },
283 { 0x14, "CIWDOFST2" },
284 { 0x18, "CIODMAFMT" },
285 { 0x20, "CIOCAN" },
286 { 0x24, "CIOOFF" },
287 { 0x30, "CIOSA" },
288 { 0x40, "CISTATUS" },
289 { 0x44, "CISTATUS2" },
290 { 0xf0, "CITHOLD" },
291 { 0xfc, "CIGENERAL" },
292 };
293 u32 i;
294
295 v4l2_info(&dev->subdev, "--- %s ---\n", label);
296
297 for (i = 0; i < ARRAY_SIZE(registers); i++) {
298 u32 cfg = readl(dev->regs + registers[i].offset);
299 v4l2_info(&dev->subdev, "%9s: 0x%08x\n",
300 registers[i].name, cfg);
301 }
302}
diff --git a/drivers/media/platform/exynos4-is/fimc-lite-reg.h b/drivers/media/platform/exynos4-is/fimc-lite-reg.h
new file mode 100644
index 000000000000..390383941c19
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-lite-reg.h
@@ -0,0 +1,150 @@
1/*
2 * Copyright (C) 2012 Samsung Electronics Co., Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef FIMC_LITE_REG_H_
10#define FIMC_LITE_REG_H_
11
12#include "fimc-lite.h"
13
14/* Camera Source size */
15#define FLITE_REG_CISRCSIZE 0x00
16#define FLITE_REG_CISRCSIZE_ORDER422_IN_YCBYCR (0 << 14)
17#define FLITE_REG_CISRCSIZE_ORDER422_IN_YCRYCB (1 << 14)
18#define FLITE_REG_CISRCSIZE_ORDER422_IN_CBYCRY (2 << 14)
19#define FLITE_REG_CISRCSIZE_ORDER422_IN_CRYCBY (3 << 14)
20#define FLITE_REG_CISRCSIZE_ORDER422_MASK (0x3 << 14)
21#define FLITE_REG_CISRCSIZE_SIZE_CAM_MASK (0x3fff << 16 | 0x3fff)
22
23/* Global control */
24#define FLITE_REG_CIGCTRL 0x04
25#define FLITE_REG_CIGCTRL_YUV422_1P (0x1e << 24)
26#define FLITE_REG_CIGCTRL_RAW8 (0x2a << 24)
27#define FLITE_REG_CIGCTRL_RAW10 (0x2b << 24)
28#define FLITE_REG_CIGCTRL_RAW12 (0x2c << 24)
29#define FLITE_REG_CIGCTRL_RAW14 (0x2d << 24)
30/* User defined formats. x = 0...15 */
31#define FLITE_REG_CIGCTRL_USER(x) ((0x30 + x - 1) << 24)
32#define FLITE_REG_CIGCTRL_FMT_MASK (0x3f << 24)
33#define FLITE_REG_CIGCTRL_SHADOWMASK_DISABLE (1 << 21)
34#define FLITE_REG_CIGCTRL_ODMA_DISABLE (1 << 20)
35#define FLITE_REG_CIGCTRL_SWRST_REQ (1 << 19)
36#define FLITE_REG_CIGCTRL_SWRST_RDY (1 << 18)
37#define FLITE_REG_CIGCTRL_SWRST (1 << 17)
38#define FLITE_REG_CIGCTRL_TEST_PATTERN_COLORBAR (1 << 15)
39#define FLITE_REG_CIGCTRL_INVPOLPCLK (1 << 14)
40#define FLITE_REG_CIGCTRL_INVPOLVSYNC (1 << 13)
41#define FLITE_REG_CIGCTRL_INVPOLHREF (1 << 12)
42/* Interrupts mask bits (1 disables an interrupt) */
43#define FLITE_REG_CIGCTRL_IRQ_LASTEN (1 << 8)
44#define FLITE_REG_CIGCTRL_IRQ_ENDEN (1 << 7)
45#define FLITE_REG_CIGCTRL_IRQ_STARTEN (1 << 6)
46#define FLITE_REG_CIGCTRL_IRQ_OVFEN (1 << 5)
47#define FLITE_REG_CIGCTRL_IRQ_DISABLE_MASK (0xf << 5)
48#define FLITE_REG_CIGCTRL_SELCAM_MIPI (1 << 3)
49
50/* Image Capture Enable */
51#define FLITE_REG_CIIMGCPT 0x08
52#define FLITE_REG_CIIMGCPT_IMGCPTEN (1 << 31)
53#define FLITE_REG_CIIMGCPT_CPT_FREN (1 << 25)
54#define FLITE_REG_CIIMGCPT_CPT_MOD_FRCNT (1 << 18)
55#define FLITE_REG_CIIMGCPT_CPT_MOD_FREN (0 << 18)
56
57/* Capture Sequence */
58#define FLITE_REG_CICPTSEQ 0x0c
59
60/* Camera Window Offset */
61#define FLITE_REG_CIWDOFST 0x10
62#define FLITE_REG_CIWDOFST_WINOFSEN (1 << 31)
63#define FLITE_REG_CIWDOFST_CLROVIY (1 << 31)
64#define FLITE_REG_CIWDOFST_CLROVFICB (1 << 15)
65#define FLITE_REG_CIWDOFST_CLROVFICR (1 << 14)
66#define FLITE_REG_CIWDOFST_OFST_MASK ((0x1fff << 16) | 0x1fff)
67
68/* Camera Window Offset2 */
69#define FLITE_REG_CIWDOFST2 0x14
70
71/* Camera Output DMA Format */
72#define FLITE_REG_CIODMAFMT 0x18
73#define FLITE_REG_CIODMAFMT_RAW_CON (1 << 15)
74#define FLITE_REG_CIODMAFMT_PACK12 (1 << 14)
75#define FLITE_REG_CIODMAFMT_YCBYCR (0 << 4)
76#define FLITE_REG_CIODMAFMT_YCRYCB (1 << 4)
77#define FLITE_REG_CIODMAFMT_CBYCRY (2 << 4)
78#define FLITE_REG_CIODMAFMT_CRYCBY (3 << 4)
79#define FLITE_REG_CIODMAFMT_YCBCR_ORDER_MASK (0x3 << 4)
80
81/* Camera Output Canvas */
82#define FLITE_REG_CIOCAN 0x20
83#define FLITE_REG_CIOCAN_MASK ((0x3fff << 16) | 0x3fff)
84
85/* Camera Output DMA Offset */
86#define FLITE_REG_CIOOFF 0x24
87#define FLITE_REG_CIOOFF_MASK ((0x3fff << 16) | 0x3fff)
88
89/* Camera Output DMA Start Address */
90#define FLITE_REG_CIOSA 0x30
91
92/* Camera Status */
93#define FLITE_REG_CISTATUS 0x40
94#define FLITE_REG_CISTATUS_MIPI_VVALID (1 << 22)
95#define FLITE_REG_CISTATUS_MIPI_HVALID (1 << 21)
96#define FLITE_REG_CISTATUS_MIPI_DVALID (1 << 20)
97#define FLITE_REG_CISTATUS_ITU_VSYNC (1 << 14)
98#define FLITE_REG_CISTATUS_ITU_HREFF (1 << 13)
99#define FLITE_REG_CISTATUS_OVFIY (1 << 10)
100#define FLITE_REG_CISTATUS_OVFICB (1 << 9)
101#define FLITE_REG_CISTATUS_OVFICR (1 << 8)
102#define FLITE_REG_CISTATUS_IRQ_SRC_OVERFLOW (1 << 7)
103#define FLITE_REG_CISTATUS_IRQ_SRC_LASTCAPEND (1 << 6)
104#define FLITE_REG_CISTATUS_IRQ_SRC_FRMSTART (1 << 5)
105#define FLITE_REG_CISTATUS_IRQ_SRC_FRMEND (1 << 4)
106#define FLITE_REG_CISTATUS_IRQ_CAM (1 << 0)
107#define FLITE_REG_CISTATUS_IRQ_MASK (0xf << 4)
108
109/* Camera Status2 */
110#define FLITE_REG_CISTATUS2 0x44
111#define FLITE_REG_CISTATUS2_LASTCAPEND (1 << 1)
112#define FLITE_REG_CISTATUS2_FRMEND (1 << 0)
113
114/* Qos Threshold */
115#define FLITE_REG_CITHOLD 0xf0
116#define FLITE_REG_CITHOLD_W_QOS_EN (1 << 30)
117
118/* Camera General Purpose */
119#define FLITE_REG_CIGENERAL 0xfc
120/* b0: 1 - camera B, 0 - camera A */
121#define FLITE_REG_CIGENERAL_CAM_B (1 << 0)
122
123/* ----------------------------------------------------------------------------
124 * Function declarations
125 */
126void flite_hw_reset(struct fimc_lite *dev);
127void flite_hw_clear_pending_irq(struct fimc_lite *dev);
128u32 flite_hw_get_interrupt_source(struct fimc_lite *dev);
129void flite_hw_clear_last_capture_end(struct fimc_lite *dev);
130void flite_hw_set_interrupt_mask(struct fimc_lite *dev);
131void flite_hw_capture_start(struct fimc_lite *dev);
132void flite_hw_capture_stop(struct fimc_lite *dev);
133void flite_hw_set_camera_bus(struct fimc_lite *dev,
134 struct fimc_source_info *s_info);
135void flite_hw_set_camera_polarity(struct fimc_lite *dev,
136 struct fimc_source_info *cam);
137void flite_hw_set_window_offset(struct fimc_lite *dev, struct flite_frame *f);
138void flite_hw_set_source_format(struct fimc_lite *dev, struct flite_frame *f);
139
140void flite_hw_set_output_dma(struct fimc_lite *dev, struct flite_frame *f,
141 bool enable);
142void flite_hw_set_dma_window(struct fimc_lite *dev, struct flite_frame *f);
143void flite_hw_set_test_pattern(struct fimc_lite *dev, bool on);
144void flite_hw_dump_regs(struct fimc_lite *dev, const char *label);
145
146static inline void flite_hw_set_output_addr(struct fimc_lite *dev, u32 paddr)
147{
148 writel(paddr, dev->regs + FLITE_REG_CIOSA);
149}
150#endif /* FIMC_LITE_REG_H */
diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c
new file mode 100644
index 000000000000..14bb7bc8adbe
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-lite.c
@@ -0,0 +1,1660 @@
1/*
2 * Samsung EXYNOS FIMC-LITE (camera host interface) driver
3*
4 * Copyright (C) 2012 Samsung Electronics Co., Ltd.
5 * Sylwester Nawrocki <s.nawrocki@samsung.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#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
12
13#include <linux/bug.h>
14#include <linux/clk.h>
15#include <linux/device.h>
16#include <linux/errno.h>
17#include <linux/interrupt.h>
18#include <linux/kernel.h>
19#include <linux/list.h>
20#include <linux/module.h>
21#include <linux/of.h>
22#include <linux/types.h>
23#include <linux/platform_device.h>
24#include <linux/pm_runtime.h>
25#include <linux/slab.h>
26#include <linux/videodev2.h>
27
28#include <media/v4l2-device.h>
29#include <media/v4l2-ioctl.h>
30#include <media/v4l2-mem2mem.h>
31#include <media/videobuf2-core.h>
32#include <media/videobuf2-dma-contig.h>
33#include <media/s5p_fimc.h>
34
35#include "fimc-core.h"
36#include "fimc-lite.h"
37#include "fimc-lite-reg.h"
38
39static int debug;
40module_param(debug, int, 0644);
41
42static const struct fimc_fmt fimc_lite_formats[] = {
43 {
44 .name = "YUV 4:2:2 packed, YCbYCr",
45 .fourcc = V4L2_PIX_FMT_YUYV,
46 .depth = { 16 },
47 .color = FIMC_FMT_YCBYCR422,
48 .memplanes = 1,
49 .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
50 .flags = FMT_FLAGS_YUV,
51 }, {
52 .name = "YUV 4:2:2 packed, CbYCrY",
53 .fourcc = V4L2_PIX_FMT_UYVY,
54 .depth = { 16 },
55 .color = FIMC_FMT_CBYCRY422,
56 .memplanes = 1,
57 .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8,
58 .flags = FMT_FLAGS_YUV,
59 }, {
60 .name = "YUV 4:2:2 packed, CrYCbY",
61 .fourcc = V4L2_PIX_FMT_VYUY,
62 .depth = { 16 },
63 .color = FIMC_FMT_CRYCBY422,
64 .memplanes = 1,
65 .mbus_code = V4L2_MBUS_FMT_VYUY8_2X8,
66 .flags = FMT_FLAGS_YUV,
67 }, {
68 .name = "YUV 4:2:2 packed, YCrYCb",
69 .fourcc = V4L2_PIX_FMT_YVYU,
70 .depth = { 16 },
71 .color = FIMC_FMT_YCRYCB422,
72 .memplanes = 1,
73 .mbus_code = V4L2_MBUS_FMT_YVYU8_2X8,
74 .flags = FMT_FLAGS_YUV,
75 }, {
76 .name = "RAW8 (GRBG)",
77 .fourcc = V4L2_PIX_FMT_SGRBG8,
78 .depth = { 8 },
79 .color = FIMC_FMT_RAW8,
80 .memplanes = 1,
81 .mbus_code = V4L2_MBUS_FMT_SGRBG8_1X8,
82 .flags = FMT_FLAGS_RAW_BAYER,
83 }, {
84 .name = "RAW10 (GRBG)",
85 .fourcc = V4L2_PIX_FMT_SGRBG10,
86 .depth = { 10 },
87 .color = FIMC_FMT_RAW10,
88 .memplanes = 1,
89 .mbus_code = V4L2_MBUS_FMT_SGRBG10_1X10,
90 .flags = FMT_FLAGS_RAW_BAYER,
91 }, {
92 .name = "RAW12 (GRBG)",
93 .fourcc = V4L2_PIX_FMT_SGRBG12,
94 .depth = { 12 },
95 .color = FIMC_FMT_RAW12,
96 .memplanes = 1,
97 .mbus_code = V4L2_MBUS_FMT_SGRBG12_1X12,
98 .flags = FMT_FLAGS_RAW_BAYER,
99 },
100};
101
102/**
103 * fimc_lite_find_format - lookup fimc color format by fourcc or media bus code
104 * @pixelformat: fourcc to match, ignored if null
105 * @mbus_code: media bus code to match, ignored if null
106 * @mask: the color format flags to match
107 * @index: index to the fimc_lite_formats array, ignored if negative
108 */
109static const struct fimc_fmt *fimc_lite_find_format(const u32 *pixelformat,
110 const u32 *mbus_code, unsigned int mask, int index)
111{
112 const struct fimc_fmt *fmt, *def_fmt = NULL;
113 unsigned int i;
114 int id = 0;
115
116 if (index >= (int)ARRAY_SIZE(fimc_lite_formats))
117 return NULL;
118
119 for (i = 0; i < ARRAY_SIZE(fimc_lite_formats); ++i) {
120 fmt = &fimc_lite_formats[i];
121 if (mask && !(fmt->flags & mask))
122 continue;
123 if (pixelformat && fmt->fourcc == *pixelformat)
124 return fmt;
125 if (mbus_code && fmt->mbus_code == *mbus_code)
126 return fmt;
127 if (index == id)
128 def_fmt = fmt;
129 id++;
130 }
131 return def_fmt;
132}
133
134/* Called with the media graph mutex held or @me stream_count > 0. */
135static struct v4l2_subdev *__find_remote_sensor(struct media_entity *me)
136{
137 struct media_pad *pad = &me->pads[0];
138 struct v4l2_subdev *sd;
139
140 while (pad->flags & MEDIA_PAD_FL_SINK) {
141 /* source pad */
142 pad = media_entity_remote_source(pad);
143 if (pad == NULL ||
144 media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
145 break;
146
147 sd = media_entity_to_v4l2_subdev(pad->entity);
148
149 if (sd->grp_id == GRP_ID_FIMC_IS_SENSOR ||
150 sd->grp_id == GRP_ID_SENSOR)
151 return sd;
152 /* sink pad */
153 pad = &sd->entity.pads[0];
154 }
155 return NULL;
156}
157
158static int fimc_lite_hw_init(struct fimc_lite *fimc, bool isp_output)
159{
160 struct fimc_source_info *si;
161 unsigned long flags;
162
163 if (fimc->sensor == NULL)
164 return -ENXIO;
165
166 if (fimc->inp_frame.fmt == NULL || fimc->out_frame.fmt == NULL)
167 return -EINVAL;
168
169 /* Get sensor configuration data from the sensor subdev */
170 si = v4l2_get_subdev_hostdata(fimc->sensor);
171 if (!si)
172 return -EINVAL;
173
174 spin_lock_irqsave(&fimc->slock, flags);
175
176 flite_hw_set_camera_bus(fimc, si);
177 flite_hw_set_source_format(fimc, &fimc->inp_frame);
178 flite_hw_set_window_offset(fimc, &fimc->inp_frame);
179 flite_hw_set_output_dma(fimc, &fimc->out_frame, !isp_output);
180 flite_hw_set_interrupt_mask(fimc);
181 flite_hw_set_test_pattern(fimc, fimc->test_pattern->val);
182
183 if (debug > 0)
184 flite_hw_dump_regs(fimc, __func__);
185
186 spin_unlock_irqrestore(&fimc->slock, flags);
187 return 0;
188}
189
190/*
191 * Reinitialize the driver so it is ready to start the streaming again.
192 * Set fimc->state to indicate stream off and the hardware shut down state.
193 * If not suspending (@suspend is false), return any buffers to videobuf2.
194 * Otherwise put any owned buffers onto the pending buffers queue, so they
195 * can be re-spun when the device is being resumed. Also perform FIMC
196 * software reset and disable streaming on the whole pipeline if required.
197 */
198static int fimc_lite_reinit(struct fimc_lite *fimc, bool suspend)
199{
200 struct flite_buffer *buf;
201 unsigned long flags;
202 bool streaming;
203
204 spin_lock_irqsave(&fimc->slock, flags);
205 streaming = fimc->state & (1 << ST_SENSOR_STREAM);
206
207 fimc->state &= ~(1 << ST_FLITE_RUN | 1 << ST_FLITE_OFF |
208 1 << ST_FLITE_STREAM | 1 << ST_SENSOR_STREAM);
209 if (suspend)
210 fimc->state |= (1 << ST_FLITE_SUSPENDED);
211 else
212 fimc->state &= ~(1 << ST_FLITE_PENDING |
213 1 << ST_FLITE_SUSPENDED);
214
215 /* Release unused buffers */
216 while (!suspend && !list_empty(&fimc->pending_buf_q)) {
217 buf = fimc_lite_pending_queue_pop(fimc);
218 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
219 }
220 /* If suspending put unused buffers onto pending queue */
221 while (!list_empty(&fimc->active_buf_q)) {
222 buf = fimc_lite_active_queue_pop(fimc);
223 if (suspend)
224 fimc_lite_pending_queue_add(fimc, buf);
225 else
226 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
227 }
228
229 spin_unlock_irqrestore(&fimc->slock, flags);
230
231 flite_hw_reset(fimc);
232
233 if (!streaming)
234 return 0;
235
236 return fimc_pipeline_call(fimc, set_stream, &fimc->pipeline, 0);
237}
238
239static int fimc_lite_stop_capture(struct fimc_lite *fimc, bool suspend)
240{
241 unsigned long flags;
242
243 if (!fimc_lite_active(fimc))
244 return 0;
245
246 spin_lock_irqsave(&fimc->slock, flags);
247 set_bit(ST_FLITE_OFF, &fimc->state);
248 flite_hw_capture_stop(fimc);
249 spin_unlock_irqrestore(&fimc->slock, flags);
250
251 wait_event_timeout(fimc->irq_queue,
252 !test_bit(ST_FLITE_OFF, &fimc->state),
253 (2*HZ/10)); /* 200 ms */
254
255 return fimc_lite_reinit(fimc, suspend);
256}
257
258/* Must be called with fimc.slock spinlock held. */
259static void fimc_lite_config_update(struct fimc_lite *fimc)
260{
261 flite_hw_set_window_offset(fimc, &fimc->inp_frame);
262 flite_hw_set_dma_window(fimc, &fimc->out_frame);
263 flite_hw_set_test_pattern(fimc, fimc->test_pattern->val);
264 clear_bit(ST_FLITE_CONFIG, &fimc->state);
265}
266
267static irqreturn_t flite_irq_handler(int irq, void *priv)
268{
269 struct fimc_lite *fimc = priv;
270 struct flite_buffer *vbuf;
271 unsigned long flags;
272 struct timeval *tv;
273 struct timespec ts;
274 u32 intsrc;
275
276 spin_lock_irqsave(&fimc->slock, flags);
277
278 intsrc = flite_hw_get_interrupt_source(fimc);
279 flite_hw_clear_pending_irq(fimc);
280
281 if (test_and_clear_bit(ST_FLITE_OFF, &fimc->state)) {
282 wake_up(&fimc->irq_queue);
283 goto done;
284 }
285
286 if (intsrc & FLITE_REG_CISTATUS_IRQ_SRC_OVERFLOW) {
287 clear_bit(ST_FLITE_RUN, &fimc->state);
288 fimc->events.data_overflow++;
289 }
290
291 if (intsrc & FLITE_REG_CISTATUS_IRQ_SRC_LASTCAPEND) {
292 flite_hw_clear_last_capture_end(fimc);
293 clear_bit(ST_FLITE_STREAM, &fimc->state);
294 wake_up(&fimc->irq_queue);
295 }
296
297 if (atomic_read(&fimc->out_path) != FIMC_IO_DMA)
298 goto done;
299
300 if ((intsrc & FLITE_REG_CISTATUS_IRQ_SRC_FRMSTART) &&
301 test_bit(ST_FLITE_RUN, &fimc->state) &&
302 !list_empty(&fimc->active_buf_q) &&
303 !list_empty(&fimc->pending_buf_q)) {
304 vbuf = fimc_lite_active_queue_pop(fimc);
305 ktime_get_ts(&ts);
306 tv = &vbuf->vb.v4l2_buf.timestamp;
307 tv->tv_sec = ts.tv_sec;
308 tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
309 vbuf->vb.v4l2_buf.sequence = fimc->frame_count++;
310 vb2_buffer_done(&vbuf->vb, VB2_BUF_STATE_DONE);
311
312 vbuf = fimc_lite_pending_queue_pop(fimc);
313 flite_hw_set_output_addr(fimc, vbuf->paddr);
314 fimc_lite_active_queue_add(fimc, vbuf);
315 }
316
317 if (test_bit(ST_FLITE_CONFIG, &fimc->state))
318 fimc_lite_config_update(fimc);
319
320 if (list_empty(&fimc->pending_buf_q)) {
321 flite_hw_capture_stop(fimc);
322 clear_bit(ST_FLITE_STREAM, &fimc->state);
323 }
324done:
325 set_bit(ST_FLITE_RUN, &fimc->state);
326 spin_unlock_irqrestore(&fimc->slock, flags);
327 return IRQ_HANDLED;
328}
329
330static int start_streaming(struct vb2_queue *q, unsigned int count)
331{
332 struct fimc_lite *fimc = q->drv_priv;
333 int ret;
334
335 fimc->frame_count = 0;
336
337 ret = fimc_lite_hw_init(fimc, false);
338 if (ret) {
339 fimc_lite_reinit(fimc, false);
340 return ret;
341 }
342
343 set_bit(ST_FLITE_PENDING, &fimc->state);
344
345 if (!list_empty(&fimc->active_buf_q) &&
346 !test_and_set_bit(ST_FLITE_STREAM, &fimc->state)) {
347 flite_hw_capture_start(fimc);
348
349 if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state))
350 fimc_pipeline_call(fimc, set_stream,
351 &fimc->pipeline, 1);
352 }
353 if (debug > 0)
354 flite_hw_dump_regs(fimc, __func__);
355
356 return 0;
357}
358
359static int stop_streaming(struct vb2_queue *q)
360{
361 struct fimc_lite *fimc = q->drv_priv;
362
363 if (!fimc_lite_active(fimc))
364 return -EINVAL;
365
366 return fimc_lite_stop_capture(fimc, false);
367}
368
369static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
370 unsigned int *num_buffers, unsigned int *num_planes,
371 unsigned int sizes[], void *allocators[])
372{
373 const struct v4l2_pix_format_mplane *pixm = NULL;
374 struct fimc_lite *fimc = vq->drv_priv;
375 struct flite_frame *frame = &fimc->out_frame;
376 const struct fimc_fmt *fmt = frame->fmt;
377 unsigned long wh;
378 int i;
379
380 if (pfmt) {
381 pixm = &pfmt->fmt.pix_mp;
382 fmt = fimc_lite_find_format(&pixm->pixelformat, NULL, 0, -1);
383 wh = pixm->width * pixm->height;
384 } else {
385 wh = frame->f_width * frame->f_height;
386 }
387
388 if (fmt == NULL)
389 return -EINVAL;
390
391 *num_planes = fmt->memplanes;
392
393 for (i = 0; i < fmt->memplanes; i++) {
394 unsigned int size = (wh * fmt->depth[i]) / 8;
395 if (pixm)
396 sizes[i] = max(size, pixm->plane_fmt[i].sizeimage);
397 else
398 sizes[i] = size;
399 allocators[i] = fimc->alloc_ctx;
400 }
401
402 return 0;
403}
404
405static int buffer_prepare(struct vb2_buffer *vb)
406{
407 struct vb2_queue *vq = vb->vb2_queue;
408 struct fimc_lite *fimc = vq->drv_priv;
409 int i;
410
411 if (fimc->out_frame.fmt == NULL)
412 return -EINVAL;
413
414 for (i = 0; i < fimc->out_frame.fmt->memplanes; i++) {
415 unsigned long size = fimc->payload[i];
416
417 if (vb2_plane_size(vb, i) < size) {
418 v4l2_err(&fimc->vfd,
419 "User buffer too small (%ld < %ld)\n",
420 vb2_plane_size(vb, i), size);
421 return -EINVAL;
422 }
423 vb2_set_plane_payload(vb, i, size);
424 }
425
426 return 0;
427}
428
429static void buffer_queue(struct vb2_buffer *vb)
430{
431 struct flite_buffer *buf
432 = container_of(vb, struct flite_buffer, vb);
433 struct fimc_lite *fimc = vb2_get_drv_priv(vb->vb2_queue);
434 unsigned long flags;
435
436 spin_lock_irqsave(&fimc->slock, flags);
437 buf->paddr = vb2_dma_contig_plane_dma_addr(vb, 0);
438
439 if (!test_bit(ST_FLITE_SUSPENDED, &fimc->state) &&
440 !test_bit(ST_FLITE_STREAM, &fimc->state) &&
441 list_empty(&fimc->active_buf_q)) {
442 flite_hw_set_output_addr(fimc, buf->paddr);
443 fimc_lite_active_queue_add(fimc, buf);
444 } else {
445 fimc_lite_pending_queue_add(fimc, buf);
446 }
447
448 if (vb2_is_streaming(&fimc->vb_queue) &&
449 !list_empty(&fimc->pending_buf_q) &&
450 !test_and_set_bit(ST_FLITE_STREAM, &fimc->state)) {
451 flite_hw_capture_start(fimc);
452 spin_unlock_irqrestore(&fimc->slock, flags);
453
454 if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state))
455 fimc_pipeline_call(fimc, set_stream,
456 &fimc->pipeline, 1);
457 return;
458 }
459 spin_unlock_irqrestore(&fimc->slock, flags);
460}
461
462static const struct vb2_ops fimc_lite_qops = {
463 .queue_setup = queue_setup,
464 .buf_prepare = buffer_prepare,
465 .buf_queue = buffer_queue,
466 .wait_prepare = vb2_ops_wait_prepare,
467 .wait_finish = vb2_ops_wait_finish,
468 .start_streaming = start_streaming,
469 .stop_streaming = stop_streaming,
470};
471
472static void fimc_lite_clear_event_counters(struct fimc_lite *fimc)
473{
474 unsigned long flags;
475
476 spin_lock_irqsave(&fimc->slock, flags);
477 memset(&fimc->events, 0, sizeof(fimc->events));
478 spin_unlock_irqrestore(&fimc->slock, flags);
479}
480
481static int fimc_lite_open(struct file *file)
482{
483 struct fimc_lite *fimc = video_drvdata(file);
484 struct media_entity *me = &fimc->vfd.entity;
485 int ret;
486
487 mutex_lock(&me->parent->graph_mutex);
488
489 mutex_lock(&fimc->lock);
490 if (atomic_read(&fimc->out_path) != FIMC_IO_DMA) {
491 ret = -EBUSY;
492 goto unlock;
493 }
494
495 set_bit(ST_FLITE_IN_USE, &fimc->state);
496 ret = pm_runtime_get_sync(&fimc->pdev->dev);
497 if (ret < 0)
498 goto unlock;
499
500 ret = v4l2_fh_open(file);
501 if (ret < 0)
502 goto err_pm;
503
504 if (!v4l2_fh_is_singular_file(file) ||
505 atomic_read(&fimc->out_path) != FIMC_IO_DMA)
506 goto unlock;
507
508 ret = fimc_pipeline_call(fimc, open, &fimc->pipeline,
509 me, true);
510 if (!ret) {
511 fimc_lite_clear_event_counters(fimc);
512 fimc->ref_count++;
513 goto unlock;
514 }
515
516 v4l2_fh_release(file);
517err_pm:
518 pm_runtime_put_sync(&fimc->pdev->dev);
519 clear_bit(ST_FLITE_IN_USE, &fimc->state);
520unlock:
521 mutex_unlock(&fimc->lock);
522 mutex_unlock(&me->parent->graph_mutex);
523 return ret;
524}
525
526static int fimc_lite_release(struct file *file)
527{
528 struct fimc_lite *fimc = video_drvdata(file);
529
530 mutex_lock(&fimc->lock);
531
532 if (v4l2_fh_is_singular_file(file) &&
533 atomic_read(&fimc->out_path) == FIMC_IO_DMA) {
534 if (fimc->streaming) {
535 media_entity_pipeline_stop(&fimc->vfd.entity);
536 fimc->streaming = false;
537 }
538 clear_bit(ST_FLITE_IN_USE, &fimc->state);
539 fimc_lite_stop_capture(fimc, false);
540 fimc_pipeline_call(fimc, close, &fimc->pipeline);
541 fimc->ref_count--;
542 }
543
544 vb2_fop_release(file);
545 pm_runtime_put(&fimc->pdev->dev);
546 clear_bit(ST_FLITE_SUSPENDED, &fimc->state);
547
548 mutex_unlock(&fimc->lock);
549 return 0;
550}
551
552static const struct v4l2_file_operations fimc_lite_fops = {
553 .owner = THIS_MODULE,
554 .open = fimc_lite_open,
555 .release = fimc_lite_release,
556 .poll = vb2_fop_poll,
557 .unlocked_ioctl = video_ioctl2,
558 .mmap = vb2_fop_mmap,
559};
560
561/*
562 * Format and crop negotiation helpers
563 */
564
565static const struct fimc_fmt *fimc_lite_try_format(struct fimc_lite *fimc,
566 u32 *width, u32 *height,
567 u32 *code, u32 *fourcc, int pad)
568{
569 struct flite_drvdata *dd = fimc->dd;
570 const struct fimc_fmt *fmt;
571 unsigned int flags = 0;
572
573 if (pad == FLITE_SD_PAD_SINK) {
574 v4l_bound_align_image(width, 8, dd->max_width,
575 ffs(dd->out_width_align) - 1,
576 height, 0, dd->max_height, 0, 0);
577 } else {
578 v4l_bound_align_image(width, 8, fimc->inp_frame.rect.width,
579 ffs(dd->out_width_align) - 1,
580 height, 0, fimc->inp_frame.rect.height,
581 0, 0);
582 flags = fimc->inp_frame.fmt->flags;
583 }
584
585 fmt = fimc_lite_find_format(fourcc, code, flags, 0);
586 if (WARN_ON(!fmt))
587 return NULL;
588
589 if (code)
590 *code = fmt->mbus_code;
591 if (fourcc)
592 *fourcc = fmt->fourcc;
593
594 v4l2_dbg(1, debug, &fimc->subdev, "code: 0x%x, %dx%d\n",
595 code ? *code : 0, *width, *height);
596
597 return fmt;
598}
599
600static void fimc_lite_try_crop(struct fimc_lite *fimc, struct v4l2_rect *r)
601{
602 struct flite_frame *frame = &fimc->inp_frame;
603
604 v4l_bound_align_image(&r->width, 0, frame->f_width, 0,
605 &r->height, 0, frame->f_height, 0, 0);
606
607 /* Adjust left/top if cropping rectangle got out of bounds */
608 r->left = clamp_t(u32, r->left, 0, frame->f_width - r->width);
609 r->left = round_down(r->left, fimc->dd->win_hor_offs_align);
610 r->top = clamp_t(u32, r->top, 0, frame->f_height - r->height);
611
612 v4l2_dbg(1, debug, &fimc->subdev, "(%d,%d)/%dx%d, sink fmt: %dx%d\n",
613 r->left, r->top, r->width, r->height,
614 frame->f_width, frame->f_height);
615}
616
617static void fimc_lite_try_compose(struct fimc_lite *fimc, struct v4l2_rect *r)
618{
619 struct flite_frame *frame = &fimc->out_frame;
620 struct v4l2_rect *crop_rect = &fimc->inp_frame.rect;
621
622 /* Scaling is not supported so we enforce compose rectangle size
623 same as size of the sink crop rectangle. */
624 r->width = crop_rect->width;
625 r->height = crop_rect->height;
626
627 /* Adjust left/top if the composing rectangle got out of bounds */
628 r->left = clamp_t(u32, r->left, 0, frame->f_width - r->width);
629 r->left = round_down(r->left, fimc->dd->out_hor_offs_align);
630 r->top = clamp_t(u32, r->top, 0, fimc->out_frame.f_height - r->height);
631
632 v4l2_dbg(1, debug, &fimc->subdev, "(%d,%d)/%dx%d, source fmt: %dx%d\n",
633 r->left, r->top, r->width, r->height,
634 frame->f_width, frame->f_height);
635}
636
637/*
638 * Video node ioctl operations
639 */
640static int fimc_vidioc_querycap_capture(struct file *file, void *priv,
641 struct v4l2_capability *cap)
642{
643 strlcpy(cap->driver, FIMC_LITE_DRV_NAME, sizeof(cap->driver));
644 cap->bus_info[0] = 0;
645 cap->card[0] = 0;
646 cap->capabilities = V4L2_CAP_STREAMING;
647 return 0;
648}
649
650static int fimc_lite_enum_fmt_mplane(struct file *file, void *priv,
651 struct v4l2_fmtdesc *f)
652{
653 const struct fimc_fmt *fmt;
654
655 if (f->index >= ARRAY_SIZE(fimc_lite_formats))
656 return -EINVAL;
657
658 fmt = &fimc_lite_formats[f->index];
659 strlcpy(f->description, fmt->name, sizeof(f->description));
660 f->pixelformat = fmt->fourcc;
661
662 return 0;
663}
664
665static int fimc_lite_g_fmt_mplane(struct file *file, void *fh,
666 struct v4l2_format *f)
667{
668 struct fimc_lite *fimc = video_drvdata(file);
669 struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp;
670 struct v4l2_plane_pix_format *plane_fmt = &pixm->plane_fmt[0];
671 struct flite_frame *frame = &fimc->out_frame;
672 const struct fimc_fmt *fmt = frame->fmt;
673
674 plane_fmt->bytesperline = (frame->f_width * fmt->depth[0]) / 8;
675 plane_fmt->sizeimage = plane_fmt->bytesperline * frame->f_height;
676
677 pixm->num_planes = fmt->memplanes;
678 pixm->pixelformat = fmt->fourcc;
679 pixm->width = frame->f_width;
680 pixm->height = frame->f_height;
681 pixm->field = V4L2_FIELD_NONE;
682 pixm->colorspace = V4L2_COLORSPACE_JPEG;
683 return 0;
684}
685
686static int fimc_lite_try_fmt(struct fimc_lite *fimc,
687 struct v4l2_pix_format_mplane *pixm,
688 const struct fimc_fmt **ffmt)
689{
690 u32 bpl = pixm->plane_fmt[0].bytesperline;
691 struct flite_drvdata *dd = fimc->dd;
692 const struct fimc_fmt *inp_fmt = fimc->inp_frame.fmt;
693 const struct fimc_fmt *fmt;
694
695 if (WARN_ON(inp_fmt == NULL))
696 return -EINVAL;
697 /*
698 * We allow some flexibility only for YUV formats. In case of raw
699 * raw Bayer the FIMC-LITE's output format must match its camera
700 * interface input format.
701 */
702 if (inp_fmt->flags & FMT_FLAGS_YUV)
703 fmt = fimc_lite_find_format(&pixm->pixelformat, NULL,
704 inp_fmt->flags, 0);
705 else
706 fmt = inp_fmt;
707
708 if (WARN_ON(fmt == NULL))
709 return -EINVAL;
710 if (ffmt)
711 *ffmt = fmt;
712 v4l_bound_align_image(&pixm->width, 8, dd->max_width,
713 ffs(dd->out_width_align) - 1,
714 &pixm->height, 0, dd->max_height, 0, 0);
715
716 if ((bpl == 0 || ((bpl * 8) / fmt->depth[0]) < pixm->width))
717 pixm->plane_fmt[0].bytesperline = (pixm->width *
718 fmt->depth[0]) / 8;
719
720 if (pixm->plane_fmt[0].sizeimage == 0)
721 pixm->plane_fmt[0].sizeimage = (pixm->width * pixm->height *
722 fmt->depth[0]) / 8;
723 pixm->num_planes = fmt->memplanes;
724 pixm->pixelformat = fmt->fourcc;
725 pixm->colorspace = V4L2_COLORSPACE_JPEG;
726 pixm->field = V4L2_FIELD_NONE;
727 return 0;
728}
729
730static int fimc_lite_try_fmt_mplane(struct file *file, void *fh,
731 struct v4l2_format *f)
732{
733 struct fimc_lite *fimc = video_drvdata(file);
734 return fimc_lite_try_fmt(fimc, &f->fmt.pix_mp, NULL);
735}
736
737static int fimc_lite_s_fmt_mplane(struct file *file, void *priv,
738 struct v4l2_format *f)
739{
740 struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp;
741 struct fimc_lite *fimc = video_drvdata(file);
742 struct flite_frame *frame = &fimc->out_frame;
743 const struct fimc_fmt *fmt = NULL;
744 int ret;
745
746 if (vb2_is_busy(&fimc->vb_queue))
747 return -EBUSY;
748
749 ret = fimc_lite_try_fmt(fimc, &f->fmt.pix_mp, &fmt);
750 if (ret < 0)
751 return ret;
752
753 frame->fmt = fmt;
754 fimc->payload[0] = max((pixm->width * pixm->height * fmt->depth[0]) / 8,
755 pixm->plane_fmt[0].sizeimage);
756 frame->f_width = pixm->width;
757 frame->f_height = pixm->height;
758
759 return 0;
760}
761
762static int fimc_pipeline_validate(struct fimc_lite *fimc)
763{
764 struct v4l2_subdev *sd = &fimc->subdev;
765 struct v4l2_subdev_format sink_fmt, src_fmt;
766 struct media_pad *pad;
767 int ret;
768
769 while (1) {
770 /* Retrieve format at the sink pad */
771 pad = &sd->entity.pads[0];
772 if (!(pad->flags & MEDIA_PAD_FL_SINK))
773 break;
774 /* Don't call FIMC subdev operation to avoid nested locking */
775 if (sd == &fimc->subdev) {
776 struct flite_frame *ff = &fimc->out_frame;
777 sink_fmt.format.width = ff->f_width;
778 sink_fmt.format.height = ff->f_height;
779 sink_fmt.format.code = fimc->inp_frame.fmt->mbus_code;
780 } else {
781 sink_fmt.pad = pad->index;
782 sink_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
783 ret = v4l2_subdev_call(sd, pad, get_fmt, NULL,
784 &sink_fmt);
785 if (ret < 0 && ret != -ENOIOCTLCMD)
786 return -EPIPE;
787 }
788 /* Retrieve format at the source pad */
789 pad = media_entity_remote_source(pad);
790 if (pad == NULL ||
791 media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
792 break;
793
794 sd = media_entity_to_v4l2_subdev(pad->entity);
795 src_fmt.pad = pad->index;
796 src_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
797 ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &src_fmt);
798 if (ret < 0 && ret != -ENOIOCTLCMD)
799 return -EPIPE;
800
801 if (src_fmt.format.width != sink_fmt.format.width ||
802 src_fmt.format.height != sink_fmt.format.height ||
803 src_fmt.format.code != sink_fmt.format.code)
804 return -EPIPE;
805 }
806 return 0;
807}
808
809static int fimc_lite_streamon(struct file *file, void *priv,
810 enum v4l2_buf_type type)
811{
812 struct fimc_lite *fimc = video_drvdata(file);
813 struct media_entity *entity = &fimc->vfd.entity;
814 struct fimc_pipeline *p = &fimc->pipeline;
815 int ret;
816
817 if (fimc_lite_active(fimc))
818 return -EBUSY;
819
820 ret = media_entity_pipeline_start(entity, p->m_pipeline);
821 if (ret < 0)
822 return ret;
823
824 ret = fimc_pipeline_validate(fimc);
825 if (ret < 0)
826 goto err_p_stop;
827
828 fimc->sensor = __find_remote_sensor(&fimc->subdev.entity);
829
830 ret = vb2_ioctl_streamon(file, priv, type);
831 if (!ret) {
832 fimc->streaming = true;
833 return ret;
834 }
835
836err_p_stop:
837 media_entity_pipeline_stop(entity);
838 return 0;
839}
840
841static int fimc_lite_streamoff(struct file *file, void *priv,
842 enum v4l2_buf_type type)
843{
844 struct fimc_lite *fimc = video_drvdata(file);
845 int ret;
846
847 ret = vb2_ioctl_streamoff(file, priv, type);
848 if (ret < 0)
849 return ret;
850
851 media_entity_pipeline_stop(&fimc->vfd.entity);
852 fimc->streaming = false;
853 return 0;
854}
855
856static int fimc_lite_reqbufs(struct file *file, void *priv,
857 struct v4l2_requestbuffers *reqbufs)
858{
859 struct fimc_lite *fimc = video_drvdata(file);
860 int ret;
861
862 reqbufs->count = max_t(u32, FLITE_REQ_BUFS_MIN, reqbufs->count);
863 ret = vb2_ioctl_reqbufs(file, priv, reqbufs);
864 if (!ret)
865 fimc->reqbufs_count = reqbufs->count;
866
867 return ret;
868}
869
870/* Return 1 if rectangle a is enclosed in rectangle b, or 0 otherwise. */
871static int enclosed_rectangle(struct v4l2_rect *a, struct v4l2_rect *b)
872{
873 if (a->left < b->left || a->top < b->top)
874 return 0;
875 if (a->left + a->width > b->left + b->width)
876 return 0;
877 if (a->top + a->height > b->top + b->height)
878 return 0;
879
880 return 1;
881}
882
883static int fimc_lite_g_selection(struct file *file, void *fh,
884 struct v4l2_selection *sel)
885{
886 struct fimc_lite *fimc = video_drvdata(file);
887 struct flite_frame *f = &fimc->out_frame;
888
889 if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
890 return -EINVAL;
891
892 switch (sel->target) {
893 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
894 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
895 sel->r.left = 0;
896 sel->r.top = 0;
897 sel->r.width = f->f_width;
898 sel->r.height = f->f_height;
899 return 0;
900
901 case V4L2_SEL_TGT_COMPOSE:
902 sel->r = f->rect;
903 return 0;
904 }
905
906 return -EINVAL;
907}
908
909static int fimc_lite_s_selection(struct file *file, void *fh,
910 struct v4l2_selection *sel)
911{
912 struct fimc_lite *fimc = video_drvdata(file);
913 struct flite_frame *f = &fimc->out_frame;
914 struct v4l2_rect rect = sel->r;
915 unsigned long flags;
916
917 if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ||
918 sel->target != V4L2_SEL_TGT_COMPOSE)
919 return -EINVAL;
920
921 fimc_lite_try_compose(fimc, &rect);
922
923 if ((sel->flags & V4L2_SEL_FLAG_LE) &&
924 !enclosed_rectangle(&rect, &sel->r))
925 return -ERANGE;
926
927 if ((sel->flags & V4L2_SEL_FLAG_GE) &&
928 !enclosed_rectangle(&sel->r, &rect))
929 return -ERANGE;
930
931 sel->r = rect;
932 spin_lock_irqsave(&fimc->slock, flags);
933 f->rect = rect;
934 set_bit(ST_FLITE_CONFIG, &fimc->state);
935 spin_unlock_irqrestore(&fimc->slock, flags);
936
937 return 0;
938}
939
940static const struct v4l2_ioctl_ops fimc_lite_ioctl_ops = {
941 .vidioc_querycap = fimc_vidioc_querycap_capture,
942 .vidioc_enum_fmt_vid_cap_mplane = fimc_lite_enum_fmt_mplane,
943 .vidioc_try_fmt_vid_cap_mplane = fimc_lite_try_fmt_mplane,
944 .vidioc_s_fmt_vid_cap_mplane = fimc_lite_s_fmt_mplane,
945 .vidioc_g_fmt_vid_cap_mplane = fimc_lite_g_fmt_mplane,
946 .vidioc_g_selection = fimc_lite_g_selection,
947 .vidioc_s_selection = fimc_lite_s_selection,
948 .vidioc_reqbufs = fimc_lite_reqbufs,
949 .vidioc_querybuf = vb2_ioctl_querybuf,
950 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
951 .vidioc_create_bufs = vb2_ioctl_create_bufs,
952 .vidioc_qbuf = vb2_ioctl_qbuf,
953 .vidioc_dqbuf = vb2_ioctl_dqbuf,
954 .vidioc_streamon = fimc_lite_streamon,
955 .vidioc_streamoff = fimc_lite_streamoff,
956};
957
958/* Capture subdev media entity operations */
959static int fimc_lite_link_setup(struct media_entity *entity,
960 const struct media_pad *local,
961 const struct media_pad *remote, u32 flags)
962{
963 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
964 struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
965 unsigned int remote_ent_type = media_entity_type(remote->entity);
966 int ret = 0;
967
968 if (WARN_ON(fimc == NULL))
969 return 0;
970
971 v4l2_dbg(1, debug, sd, "%s: %s --> %s, flags: 0x%x. source_id: 0x%x\n",
972 __func__, remote->entity->name, local->entity->name,
973 flags, fimc->source_subdev_grp_id);
974
975 mutex_lock(&fimc->lock);
976
977 switch (local->index) {
978 case FLITE_SD_PAD_SINK:
979 if (remote_ent_type != MEDIA_ENT_T_V4L2_SUBDEV) {
980 ret = -EINVAL;
981 break;
982 }
983 if (flags & MEDIA_LNK_FL_ENABLED) {
984 if (fimc->source_subdev_grp_id == 0)
985 fimc->source_subdev_grp_id = sd->grp_id;
986 else
987 ret = -EBUSY;
988 } else {
989 fimc->source_subdev_grp_id = 0;
990 fimc->sensor = NULL;
991 }
992 break;
993
994 case FLITE_SD_PAD_SOURCE_DMA:
995 if (!(flags & MEDIA_LNK_FL_ENABLED))
996 atomic_set(&fimc->out_path, FIMC_IO_NONE);
997 else if (remote_ent_type == MEDIA_ENT_T_DEVNODE)
998 atomic_set(&fimc->out_path, FIMC_IO_DMA);
999 else
1000 ret = -EINVAL;
1001 break;
1002
1003 case FLITE_SD_PAD_SOURCE_ISP:
1004 if (!(flags & MEDIA_LNK_FL_ENABLED))
1005 atomic_set(&fimc->out_path, FIMC_IO_NONE);
1006 else if (remote_ent_type == MEDIA_ENT_T_V4L2_SUBDEV)
1007 atomic_set(&fimc->out_path, FIMC_IO_ISP);
1008 else
1009 ret = -EINVAL;
1010 break;
1011
1012 default:
1013 v4l2_err(sd, "Invalid pad index\n");
1014 ret = -EINVAL;
1015 }
1016 mb();
1017
1018 mutex_unlock(&fimc->lock);
1019 return ret;
1020}
1021
1022static const struct media_entity_operations fimc_lite_subdev_media_ops = {
1023 .link_setup = fimc_lite_link_setup,
1024};
1025
1026static int fimc_lite_subdev_enum_mbus_code(struct v4l2_subdev *sd,
1027 struct v4l2_subdev_fh *fh,
1028 struct v4l2_subdev_mbus_code_enum *code)
1029{
1030 const struct fimc_fmt *fmt;
1031
1032 fmt = fimc_lite_find_format(NULL, NULL, 0, code->index);
1033 if (!fmt)
1034 return -EINVAL;
1035 code->code = fmt->mbus_code;
1036 return 0;
1037}
1038
1039static int fimc_lite_subdev_get_fmt(struct v4l2_subdev *sd,
1040 struct v4l2_subdev_fh *fh,
1041 struct v4l2_subdev_format *fmt)
1042{
1043 struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
1044 struct v4l2_mbus_framefmt *mf = &fmt->format;
1045 struct flite_frame *f = &fimc->inp_frame;
1046
1047 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
1048 mf = v4l2_subdev_get_try_format(fh, fmt->pad);
1049 fmt->format = *mf;
1050 return 0;
1051 }
1052 mf->colorspace = V4L2_COLORSPACE_JPEG;
1053
1054 mutex_lock(&fimc->lock);
1055 mf->code = f->fmt->mbus_code;
1056
1057 if (fmt->pad == FLITE_SD_PAD_SINK) {
1058 /* full camera input frame size */
1059 mf->width = f->f_width;
1060 mf->height = f->f_height;
1061 } else {
1062 /* crop size */
1063 mf->width = f->rect.width;
1064 mf->height = f->rect.height;
1065 }
1066 mutex_unlock(&fimc->lock);
1067 return 0;
1068}
1069
1070static int fimc_lite_subdev_set_fmt(struct v4l2_subdev *sd,
1071 struct v4l2_subdev_fh *fh,
1072 struct v4l2_subdev_format *fmt)
1073{
1074 struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
1075 struct v4l2_mbus_framefmt *mf = &fmt->format;
1076 struct flite_frame *sink = &fimc->inp_frame;
1077 struct flite_frame *source = &fimc->out_frame;
1078 const struct fimc_fmt *ffmt;
1079
1080 v4l2_dbg(1, debug, sd, "pad%d: code: 0x%x, %dx%d\n",
1081 fmt->pad, mf->code, mf->width, mf->height);
1082
1083 mf->colorspace = V4L2_COLORSPACE_JPEG;
1084 mutex_lock(&fimc->lock);
1085
1086 if ((atomic_read(&fimc->out_path) == FIMC_IO_ISP &&
1087 sd->entity.stream_count > 0) ||
1088 (atomic_read(&fimc->out_path) == FIMC_IO_DMA &&
1089 vb2_is_busy(&fimc->vb_queue))) {
1090 mutex_unlock(&fimc->lock);
1091 return -EBUSY;
1092 }
1093
1094 ffmt = fimc_lite_try_format(fimc, &mf->width, &mf->height,
1095 &mf->code, NULL, fmt->pad);
1096
1097 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
1098 mf = v4l2_subdev_get_try_format(fh, fmt->pad);
1099 *mf = fmt->format;
1100 mutex_unlock(&fimc->lock);
1101 return 0;
1102 }
1103
1104 if (fmt->pad == FLITE_SD_PAD_SINK) {
1105 sink->f_width = mf->width;
1106 sink->f_height = mf->height;
1107 sink->fmt = ffmt;
1108 /* Set sink crop rectangle */
1109 sink->rect.width = mf->width;
1110 sink->rect.height = mf->height;
1111 sink->rect.left = 0;
1112 sink->rect.top = 0;
1113 /* Reset source format and crop rectangle */
1114 source->rect = sink->rect;
1115 source->f_width = mf->width;
1116 source->f_height = mf->height;
1117 } else {
1118 /* Allow changing format only on sink pad */
1119 mf->code = sink->fmt->mbus_code;
1120 mf->width = sink->rect.width;
1121 mf->height = sink->rect.height;
1122 }
1123
1124 mutex_unlock(&fimc->lock);
1125 return 0;
1126}
1127
1128static int fimc_lite_subdev_get_selection(struct v4l2_subdev *sd,
1129 struct v4l2_subdev_fh *fh,
1130 struct v4l2_subdev_selection *sel)
1131{
1132 struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
1133 struct flite_frame *f = &fimc->inp_frame;
1134
1135 if ((sel->target != V4L2_SEL_TGT_CROP &&
1136 sel->target != V4L2_SEL_TGT_CROP_BOUNDS) ||
1137 sel->pad != FLITE_SD_PAD_SINK)
1138 return -EINVAL;
1139
1140 if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
1141 sel->r = *v4l2_subdev_get_try_crop(fh, sel->pad);
1142 return 0;
1143 }
1144
1145 mutex_lock(&fimc->lock);
1146 if (sel->target == V4L2_SEL_TGT_CROP) {
1147 sel->r = f->rect;
1148 } else {
1149 sel->r.left = 0;
1150 sel->r.top = 0;
1151 sel->r.width = f->f_width;
1152 sel->r.height = f->f_height;
1153 }
1154 mutex_unlock(&fimc->lock);
1155
1156 v4l2_dbg(1, debug, sd, "%s: (%d,%d) %dx%d, f_w: %d, f_h: %d\n",
1157 __func__, f->rect.left, f->rect.top, f->rect.width,
1158 f->rect.height, f->f_width, f->f_height);
1159
1160 return 0;
1161}
1162
1163static int fimc_lite_subdev_set_selection(struct v4l2_subdev *sd,
1164 struct v4l2_subdev_fh *fh,
1165 struct v4l2_subdev_selection *sel)
1166{
1167 struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
1168 struct flite_frame *f = &fimc->inp_frame;
1169 int ret = 0;
1170
1171 if (sel->target != V4L2_SEL_TGT_CROP || sel->pad != FLITE_SD_PAD_SINK)
1172 return -EINVAL;
1173
1174 mutex_lock(&fimc->lock);
1175 fimc_lite_try_crop(fimc, &sel->r);
1176
1177 if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
1178 *v4l2_subdev_get_try_crop(fh, sel->pad) = sel->r;
1179 } else {
1180 unsigned long flags;
1181 spin_lock_irqsave(&fimc->slock, flags);
1182 f->rect = sel->r;
1183 /* Same crop rectangle on the source pad */
1184 fimc->out_frame.rect = sel->r;
1185 set_bit(ST_FLITE_CONFIG, &fimc->state);
1186 spin_unlock_irqrestore(&fimc->slock, flags);
1187 }
1188 mutex_unlock(&fimc->lock);
1189
1190 v4l2_dbg(1, debug, sd, "%s: (%d,%d) %dx%d, f_w: %d, f_h: %d\n",
1191 __func__, f->rect.left, f->rect.top, f->rect.width,
1192 f->rect.height, f->f_width, f->f_height);
1193
1194 return ret;
1195}
1196
1197static int fimc_lite_subdev_s_stream(struct v4l2_subdev *sd, int on)
1198{
1199 struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
1200 unsigned long flags;
1201 int ret;
1202
1203 /*
1204 * Find sensor subdev linked to FIMC-LITE directly or through
1205 * MIPI-CSIS. This is required for configuration where FIMC-LITE
1206 * is used as a subdev only and feeds data internally to FIMC-IS.
1207 * The pipeline links are protected through entity.stream_count
1208 * so there is no need to take the media graph mutex here.
1209 */
1210 fimc->sensor = __find_remote_sensor(&sd->entity);
1211
1212 if (atomic_read(&fimc->out_path) != FIMC_IO_ISP)
1213 return -ENOIOCTLCMD;
1214
1215 mutex_lock(&fimc->lock);
1216 if (on) {
1217 flite_hw_reset(fimc);
1218 ret = fimc_lite_hw_init(fimc, true);
1219 if (!ret) {
1220 spin_lock_irqsave(&fimc->slock, flags);
1221 flite_hw_capture_start(fimc);
1222 spin_unlock_irqrestore(&fimc->slock, flags);
1223 }
1224 } else {
1225 set_bit(ST_FLITE_OFF, &fimc->state);
1226
1227 spin_lock_irqsave(&fimc->slock, flags);
1228 flite_hw_capture_stop(fimc);
1229 spin_unlock_irqrestore(&fimc->slock, flags);
1230
1231 ret = wait_event_timeout(fimc->irq_queue,
1232 !test_bit(ST_FLITE_OFF, &fimc->state),
1233 msecs_to_jiffies(200));
1234 if (ret == 0)
1235 v4l2_err(sd, "s_stream(0) timeout\n");
1236 clear_bit(ST_FLITE_RUN, &fimc->state);
1237 }
1238
1239 mutex_unlock(&fimc->lock);
1240 return ret;
1241}
1242
1243static int fimc_lite_log_status(struct v4l2_subdev *sd)
1244{
1245 struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
1246
1247 flite_hw_dump_regs(fimc, __func__);
1248 return 0;
1249}
1250
1251static int fimc_lite_subdev_registered(struct v4l2_subdev *sd)
1252{
1253 struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
1254 struct vb2_queue *q = &fimc->vb_queue;
1255 struct video_device *vfd = &fimc->vfd;
1256 int ret;
1257
1258 memset(vfd, 0, sizeof(*vfd));
1259
1260 fimc->inp_frame.fmt = &fimc_lite_formats[0];
1261 fimc->out_frame.fmt = &fimc_lite_formats[0];
1262 atomic_set(&fimc->out_path, FIMC_IO_DMA);
1263
1264 snprintf(vfd->name, sizeof(vfd->name), "fimc-lite.%d.capture",
1265 fimc->index);
1266
1267 vfd->fops = &fimc_lite_fops;
1268 vfd->ioctl_ops = &fimc_lite_ioctl_ops;
1269 vfd->v4l2_dev = sd->v4l2_dev;
1270 vfd->minor = -1;
1271 vfd->release = video_device_release_empty;
1272 vfd->queue = q;
1273 fimc->reqbufs_count = 0;
1274
1275 INIT_LIST_HEAD(&fimc->pending_buf_q);
1276 INIT_LIST_HEAD(&fimc->active_buf_q);
1277
1278 memset(q, 0, sizeof(*q));
1279 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1280 q->io_modes = VB2_MMAP | VB2_USERPTR;
1281 q->ops = &fimc_lite_qops;
1282 q->mem_ops = &vb2_dma_contig_memops;
1283 q->buf_struct_size = sizeof(struct flite_buffer);
1284 q->drv_priv = fimc;
1285 q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1286 q->lock = &fimc->lock;
1287
1288 ret = vb2_queue_init(q);
1289 if (ret < 0)
1290 return ret;
1291
1292 fimc->vd_pad.flags = MEDIA_PAD_FL_SINK;
1293 ret = media_entity_init(&vfd->entity, 1, &fimc->vd_pad, 0);
1294 if (ret < 0)
1295 return ret;
1296
1297 video_set_drvdata(vfd, fimc);
1298 fimc->pipeline_ops = v4l2_get_subdev_hostdata(sd);
1299
1300 ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
1301 if (ret < 0) {
1302 media_entity_cleanup(&vfd->entity);
1303 fimc->pipeline_ops = NULL;
1304 return ret;
1305 }
1306
1307 v4l2_info(sd->v4l2_dev, "Registered %s as /dev/%s\n",
1308 vfd->name, video_device_node_name(vfd));
1309 return 0;
1310}
1311
1312static void fimc_lite_subdev_unregistered(struct v4l2_subdev *sd)
1313{
1314 struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
1315
1316 if (fimc == NULL)
1317 return;
1318
1319 if (video_is_registered(&fimc->vfd)) {
1320 video_unregister_device(&fimc->vfd);
1321 media_entity_cleanup(&fimc->vfd.entity);
1322 fimc->pipeline_ops = NULL;
1323 }
1324}
1325
1326static const struct v4l2_subdev_internal_ops fimc_lite_subdev_internal_ops = {
1327 .registered = fimc_lite_subdev_registered,
1328 .unregistered = fimc_lite_subdev_unregistered,
1329};
1330
1331static const struct v4l2_subdev_pad_ops fimc_lite_subdev_pad_ops = {
1332 .enum_mbus_code = fimc_lite_subdev_enum_mbus_code,
1333 .get_selection = fimc_lite_subdev_get_selection,
1334 .set_selection = fimc_lite_subdev_set_selection,
1335 .get_fmt = fimc_lite_subdev_get_fmt,
1336 .set_fmt = fimc_lite_subdev_set_fmt,
1337};
1338
1339static const struct v4l2_subdev_video_ops fimc_lite_subdev_video_ops = {
1340 .s_stream = fimc_lite_subdev_s_stream,
1341};
1342
1343static const struct v4l2_subdev_core_ops fimc_lite_core_ops = {
1344 .log_status = fimc_lite_log_status,
1345};
1346
1347static struct v4l2_subdev_ops fimc_lite_subdev_ops = {
1348 .core = &fimc_lite_core_ops,
1349 .video = &fimc_lite_subdev_video_ops,
1350 .pad = &fimc_lite_subdev_pad_ops,
1351};
1352
1353static int fimc_lite_s_ctrl(struct v4l2_ctrl *ctrl)
1354{
1355 struct fimc_lite *fimc = container_of(ctrl->handler, struct fimc_lite,
1356 ctrl_handler);
1357 set_bit(ST_FLITE_CONFIG, &fimc->state);
1358 return 0;
1359}
1360
1361static const struct v4l2_ctrl_ops fimc_lite_ctrl_ops = {
1362 .s_ctrl = fimc_lite_s_ctrl,
1363};
1364
1365static const struct v4l2_ctrl_config fimc_lite_ctrl = {
1366 .ops = &fimc_lite_ctrl_ops,
1367 .id = V4L2_CTRL_CLASS_USER | 0x1001,
1368 .type = V4L2_CTRL_TYPE_BOOLEAN,
1369 .name = "Test Pattern 640x480",
1370 .step = 1,
1371};
1372
1373static int fimc_lite_create_capture_subdev(struct fimc_lite *fimc)
1374{
1375 struct v4l2_ctrl_handler *handler = &fimc->ctrl_handler;
1376 struct v4l2_subdev *sd = &fimc->subdev;
1377 int ret;
1378
1379 v4l2_subdev_init(sd, &fimc_lite_subdev_ops);
1380 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1381 snprintf(sd->name, sizeof(sd->name), "FIMC-LITE.%d", fimc->index);
1382
1383 fimc->subdev_pads[FLITE_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1384 fimc->subdev_pads[FLITE_SD_PAD_SOURCE_DMA].flags = MEDIA_PAD_FL_SOURCE;
1385 fimc->subdev_pads[FLITE_SD_PAD_SOURCE_ISP].flags = MEDIA_PAD_FL_SOURCE;
1386 ret = media_entity_init(&sd->entity, FLITE_SD_PADS_NUM,
1387 fimc->subdev_pads, 0);
1388 if (ret)
1389 return ret;
1390
1391 v4l2_ctrl_handler_init(handler, 1);
1392 fimc->test_pattern = v4l2_ctrl_new_custom(handler, &fimc_lite_ctrl,
1393 NULL);
1394 if (handler->error) {
1395 media_entity_cleanup(&sd->entity);
1396 return handler->error;
1397 }
1398
1399 sd->ctrl_handler = handler;
1400 sd->internal_ops = &fimc_lite_subdev_internal_ops;
1401 sd->entity.ops = &fimc_lite_subdev_media_ops;
1402 sd->owner = THIS_MODULE;
1403 v4l2_set_subdevdata(sd, fimc);
1404
1405 return 0;
1406}
1407
1408static void fimc_lite_unregister_capture_subdev(struct fimc_lite *fimc)
1409{
1410 struct v4l2_subdev *sd = &fimc->subdev;
1411
1412 v4l2_device_unregister_subdev(sd);
1413 media_entity_cleanup(&sd->entity);
1414 v4l2_ctrl_handler_free(&fimc->ctrl_handler);
1415 v4l2_set_subdevdata(sd, NULL);
1416}
1417
1418static void fimc_lite_clk_put(struct fimc_lite *fimc)
1419{
1420 if (IS_ERR_OR_NULL(fimc->clock))
1421 return;
1422
1423 clk_unprepare(fimc->clock);
1424 clk_put(fimc->clock);
1425 fimc->clock = NULL;
1426}
1427
1428static int fimc_lite_clk_get(struct fimc_lite *fimc)
1429{
1430 int ret;
1431
1432 fimc->clock = clk_get(&fimc->pdev->dev, FLITE_CLK_NAME);
1433 if (IS_ERR(fimc->clock))
1434 return PTR_ERR(fimc->clock);
1435
1436 ret = clk_prepare(fimc->clock);
1437 if (ret < 0) {
1438 clk_put(fimc->clock);
1439 fimc->clock = NULL;
1440 }
1441 return ret;
1442}
1443
1444static const struct of_device_id flite_of_match[];
1445
1446static int fimc_lite_probe(struct platform_device *pdev)
1447{
1448 struct flite_drvdata *drv_data = NULL;
1449 struct device *dev = &pdev->dev;
1450 const struct of_device_id *of_id;
1451 struct fimc_lite *fimc;
1452 struct resource *res;
1453 int ret;
1454
1455 fimc = devm_kzalloc(dev, sizeof(*fimc), GFP_KERNEL);
1456 if (!fimc)
1457 return -ENOMEM;
1458
1459 if (dev->of_node) {
1460 of_id = of_match_node(flite_of_match, dev->of_node);
1461 if (of_id)
1462 drv_data = (struct flite_drvdata *)of_id->data;
1463 fimc->index = of_alias_get_id(dev->of_node, "fimc-lite");
1464 } else {
1465 drv_data = fimc_lite_get_drvdata(pdev);
1466 fimc->index = pdev->id;
1467 }
1468
1469 if (!drv_data || fimc->index < 0 || fimc->index >= FIMC_LITE_MAX_DEVS)
1470 return -EINVAL;
1471
1472 fimc->dd = drv_data;
1473 fimc->pdev = pdev;
1474
1475 init_waitqueue_head(&fimc->irq_queue);
1476 spin_lock_init(&fimc->slock);
1477 mutex_init(&fimc->lock);
1478
1479 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1480 fimc->regs = devm_ioremap_resource(dev, res);
1481 if (IS_ERR(fimc->regs))
1482 return PTR_ERR(fimc->regs);
1483
1484 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1485 if (res == NULL) {
1486 dev_err(dev, "Failed to get IRQ resource\n");
1487 return -ENXIO;
1488 }
1489
1490 ret = fimc_lite_clk_get(fimc);
1491 if (ret)
1492 return ret;
1493
1494 ret = devm_request_irq(dev, res->start, flite_irq_handler,
1495 0, dev_name(dev), fimc);
1496 if (ret) {
1497 dev_err(dev, "Failed to install irq (%d)\n", ret);
1498 goto err_clk;
1499 }
1500
1501 /* The video node will be created within the subdev's registered() op */
1502 ret = fimc_lite_create_capture_subdev(fimc);
1503 if (ret)
1504 goto err_clk;
1505
1506 platform_set_drvdata(pdev, fimc);
1507 pm_runtime_enable(dev);
1508 ret = pm_runtime_get_sync(dev);
1509 if (ret < 0)
1510 goto err_sd;
1511
1512 fimc->alloc_ctx = vb2_dma_contig_init_ctx(dev);
1513 if (IS_ERR(fimc->alloc_ctx)) {
1514 ret = PTR_ERR(fimc->alloc_ctx);
1515 goto err_pm;
1516 }
1517 pm_runtime_put(dev);
1518
1519 dev_dbg(dev, "FIMC-LITE.%d registered successfully\n",
1520 fimc->index);
1521 return 0;
1522err_pm:
1523 pm_runtime_put(dev);
1524err_sd:
1525 fimc_lite_unregister_capture_subdev(fimc);
1526err_clk:
1527 fimc_lite_clk_put(fimc);
1528 return ret;
1529}
1530
1531static int fimc_lite_runtime_resume(struct device *dev)
1532{
1533 struct fimc_lite *fimc = dev_get_drvdata(dev);
1534
1535 clk_enable(fimc->clock);
1536 return 0;
1537}
1538
1539static int fimc_lite_runtime_suspend(struct device *dev)
1540{
1541 struct fimc_lite *fimc = dev_get_drvdata(dev);
1542
1543 clk_disable(fimc->clock);
1544 return 0;
1545}
1546
1547#ifdef CONFIG_PM_SLEEP
1548static int fimc_lite_resume(struct device *dev)
1549{
1550 struct fimc_lite *fimc = dev_get_drvdata(dev);
1551 struct flite_buffer *buf;
1552 unsigned long flags;
1553 int i;
1554
1555 spin_lock_irqsave(&fimc->slock, flags);
1556 if (!test_and_clear_bit(ST_LPM, &fimc->state) ||
1557 !test_bit(ST_FLITE_IN_USE, &fimc->state)) {
1558 spin_unlock_irqrestore(&fimc->slock, flags);
1559 return 0;
1560 }
1561 flite_hw_reset(fimc);
1562 spin_unlock_irqrestore(&fimc->slock, flags);
1563
1564 if (!test_and_clear_bit(ST_FLITE_SUSPENDED, &fimc->state))
1565 return 0;
1566
1567 INIT_LIST_HEAD(&fimc->active_buf_q);
1568 fimc_pipeline_call(fimc, open, &fimc->pipeline,
1569 &fimc->vfd.entity, false);
1570 fimc_lite_hw_init(fimc, atomic_read(&fimc->out_path) == FIMC_IO_ISP);
1571 clear_bit(ST_FLITE_SUSPENDED, &fimc->state);
1572
1573 for (i = 0; i < fimc->reqbufs_count; i++) {
1574 if (list_empty(&fimc->pending_buf_q))
1575 break;
1576 buf = fimc_lite_pending_queue_pop(fimc);
1577 buffer_queue(&buf->vb);
1578 }
1579 return 0;
1580}
1581
1582static int fimc_lite_suspend(struct device *dev)
1583{
1584 struct fimc_lite *fimc = dev_get_drvdata(dev);
1585 bool suspend = test_bit(ST_FLITE_IN_USE, &fimc->state);
1586 int ret;
1587
1588 if (test_and_set_bit(ST_LPM, &fimc->state))
1589 return 0;
1590
1591 ret = fimc_lite_stop_capture(fimc, suspend);
1592 if (ret < 0 || !fimc_lite_active(fimc))
1593 return ret;
1594
1595 return fimc_pipeline_call(fimc, close, &fimc->pipeline);
1596}
1597#endif /* CONFIG_PM_SLEEP */
1598
1599static int fimc_lite_remove(struct platform_device *pdev)
1600{
1601 struct fimc_lite *fimc = platform_get_drvdata(pdev);
1602 struct device *dev = &pdev->dev;
1603
1604 pm_runtime_disable(dev);
1605 pm_runtime_set_suspended(dev);
1606 fimc_lite_unregister_capture_subdev(fimc);
1607 vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx);
1608 fimc_lite_clk_put(fimc);
1609
1610 dev_info(dev, "Driver unloaded\n");
1611 return 0;
1612}
1613
1614static const struct dev_pm_ops fimc_lite_pm_ops = {
1615 SET_SYSTEM_SLEEP_PM_OPS(fimc_lite_suspend, fimc_lite_resume)
1616 SET_RUNTIME_PM_OPS(fimc_lite_runtime_suspend, fimc_lite_runtime_resume,
1617 NULL)
1618};
1619
1620/* EXYNOS4212, EXYNOS4412 */
1621static struct flite_drvdata fimc_lite_drvdata_exynos4 = {
1622 .max_width = 8192,
1623 .max_height = 8192,
1624 .out_width_align = 8,
1625 .win_hor_offs_align = 2,
1626 .out_hor_offs_align = 8,
1627};
1628
1629static struct platform_device_id fimc_lite_driver_ids[] = {
1630 {
1631 .name = "exynos-fimc-lite",
1632 .driver_data = (unsigned long)&fimc_lite_drvdata_exynos4,
1633 },
1634 { /* sentinel */ },
1635};
1636MODULE_DEVICE_TABLE(platform, fimc_lite_driver_ids);
1637
1638static const struct of_device_id flite_of_match[] = {
1639 {
1640 .compatible = "samsung,exynos4212-fimc-lite",
1641 .data = &fimc_lite_drvdata_exynos4,
1642 },
1643 { /* sentinel */ },
1644};
1645MODULE_DEVICE_TABLE(of, flite_of_match);
1646
1647static struct platform_driver fimc_lite_driver = {
1648 .probe = fimc_lite_probe,
1649 .remove = fimc_lite_remove,
1650 .id_table = fimc_lite_driver_ids,
1651 .driver = {
1652 .of_match_table = flite_of_match,
1653 .name = FIMC_LITE_DRV_NAME,
1654 .owner = THIS_MODULE,
1655 .pm = &fimc_lite_pm_ops,
1656 }
1657};
1658module_platform_driver(fimc_lite_driver);
1659MODULE_LICENSE("GPL");
1660MODULE_ALIAS("platform:" FIMC_LITE_DRV_NAME);
diff --git a/drivers/media/platform/exynos4-is/fimc-lite.h b/drivers/media/platform/exynos4-is/fimc-lite.h
new file mode 100644
index 000000000000..47da5e049247
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-lite.h
@@ -0,0 +1,214 @@
1/*
2 * Copyright (C) 2012 Samsung Electronics Co., Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef FIMC_LITE_H_
10#define FIMC_LITE_H_
11
12#include <linux/sizes.h>
13#include <linux/io.h>
14#include <linux/irqreturn.h>
15#include <linux/platform_device.h>
16#include <linux/sched.h>
17#include <linux/spinlock.h>
18#include <linux/types.h>
19#include <linux/videodev2.h>
20
21#include <media/media-entity.h>
22#include <media/videobuf2-core.h>
23#include <media/v4l2-ctrls.h>
24#include <media/v4l2-device.h>
25#include <media/v4l2-mediabus.h>
26#include <media/s5p_fimc.h>
27
28#define FIMC_LITE_DRV_NAME "exynos-fimc-lite"
29#define FLITE_CLK_NAME "flite"
30#define FIMC_LITE_MAX_DEVS 2
31#define FLITE_REQ_BUFS_MIN 2
32
33/* Bit index definitions for struct fimc_lite::state */
34enum {
35 ST_FLITE_LPM,
36 ST_FLITE_PENDING,
37 ST_FLITE_RUN,
38 ST_FLITE_STREAM,
39 ST_FLITE_SUSPENDED,
40 ST_FLITE_OFF,
41 ST_FLITE_IN_USE,
42 ST_FLITE_CONFIG,
43 ST_SENSOR_STREAM,
44};
45
46#define FLITE_SD_PAD_SINK 0
47#define FLITE_SD_PAD_SOURCE_DMA 1
48#define FLITE_SD_PAD_SOURCE_ISP 2
49#define FLITE_SD_PADS_NUM 3
50
51struct flite_drvdata {
52 unsigned short max_width;
53 unsigned short max_height;
54 unsigned short out_width_align;
55 unsigned short win_hor_offs_align;
56 unsigned short out_hor_offs_align;
57};
58
59#define fimc_lite_get_drvdata(_pdev) \
60 ((struct flite_drvdata *) platform_get_device_id(_pdev)->driver_data)
61
62struct fimc_lite_events {
63 unsigned int data_overflow;
64};
65
66#define FLITE_MAX_PLANES 1
67
68/**
69 * struct flite_frame - source/target frame properties
70 * @f_width: full pixel width
71 * @f_height: full pixel height
72 * @rect: crop/composition rectangle
73 * @fmt: pointer to pixel format description data structure
74 */
75struct flite_frame {
76 u16 f_width;
77 u16 f_height;
78 struct v4l2_rect rect;
79 const struct fimc_fmt *fmt;
80};
81
82/**
83 * struct flite_buffer - video buffer structure
84 * @vb: vb2 buffer
85 * @list: list head for the buffers queue
86 * @paddr: precalculated physical address
87 */
88struct flite_buffer {
89 struct vb2_buffer vb;
90 struct list_head list;
91 dma_addr_t paddr;
92};
93
94/**
95 * struct fimc_lite - fimc lite structure
96 * @pdev: pointer to FIMC-LITE platform device
97 * @dd: SoC specific driver data structure
98 * @v4l2_dev: pointer to top the level v4l2_device
99 * @vfd: video device node
100 * @fh: v4l2 file handle
101 * @alloc_ctx: videobuf2 memory allocator context
102 * @subdev: FIMC-LITE subdev
103 * @vd_pad: media (sink) pad for the capture video node
104 * @subdev_pads: the subdev media pads
105 * @sensor: sensor subdev attached to FIMC-LITE directly or through MIPI-CSIS
106 * @ctrl_handler: v4l2 control handler
107 * @test_pattern: test pattern controls
108 * @index: FIMC-LITE platform device index
109 * @pipeline: video capture pipeline data structure
110 * @pipeline_ops: media pipeline ops for the video node driver
111 * @slock: spinlock protecting this data structure and the hw registers
112 * @lock: mutex serializing video device and the subdev operations
113 * @clock: FIMC-LITE gate clock
114 * @regs: memory mapped io registers
115 * @irq_queue: interrupt handler waitqueue
116 * @payload: image size in bytes (w x h x bpp)
117 * @inp_frame: camera input frame structure
118 * @out_frame: DMA output frame structure
119 * @out_path: output data path (DMA or FIFO)
120 * @source_subdev_grp_id: source subdev group id
121 * @state: driver state flags
122 * @pending_buf_q: pending buffers queue head
123 * @active_buf_q: the queue head of buffers scheduled in hardware
124 * @vb_queue: vb2 buffers queue
125 * @active_buf_count: number of video buffers scheduled in hardware
126 * @frame_count: the captured frames counter
127 * @reqbufs_count: the number of buffers requested with REQBUFS ioctl
128 * @ref_count: driver's private reference counter
129 */
130struct fimc_lite {
131 struct platform_device *pdev;
132 struct flite_drvdata *dd;
133 struct v4l2_device *v4l2_dev;
134 struct video_device vfd;
135 struct v4l2_fh fh;
136 struct vb2_alloc_ctx *alloc_ctx;
137 struct v4l2_subdev subdev;
138 struct media_pad vd_pad;
139 struct media_pad subdev_pads[FLITE_SD_PADS_NUM];
140 struct v4l2_subdev *sensor;
141 struct v4l2_ctrl_handler ctrl_handler;
142 struct v4l2_ctrl *test_pattern;
143 int index;
144 struct fimc_pipeline pipeline;
145 const struct fimc_pipeline_ops *pipeline_ops;
146
147 struct mutex lock;
148 spinlock_t slock;
149
150 struct clk *clock;
151 void __iomem *regs;
152 wait_queue_head_t irq_queue;
153
154 unsigned long payload[FLITE_MAX_PLANES];
155 struct flite_frame inp_frame;
156 struct flite_frame out_frame;
157 atomic_t out_path;
158 unsigned int source_subdev_grp_id;
159
160 unsigned long state;
161 struct list_head pending_buf_q;
162 struct list_head active_buf_q;
163 struct vb2_queue vb_queue;
164 unsigned int frame_count;
165 unsigned int reqbufs_count;
166 int ref_count;
167
168 struct fimc_lite_events events;
169 bool streaming;
170};
171
172static inline bool fimc_lite_active(struct fimc_lite *fimc)
173{
174 unsigned long flags;
175 bool ret;
176
177 spin_lock_irqsave(&fimc->slock, flags);
178 ret = fimc->state & (1 << ST_FLITE_RUN) ||
179 fimc->state & (1 << ST_FLITE_PENDING);
180 spin_unlock_irqrestore(&fimc->slock, flags);
181 return ret;
182}
183
184static inline void fimc_lite_active_queue_add(struct fimc_lite *dev,
185 struct flite_buffer *buf)
186{
187 list_add_tail(&buf->list, &dev->active_buf_q);
188}
189
190static inline struct flite_buffer *fimc_lite_active_queue_pop(
191 struct fimc_lite *dev)
192{
193 struct flite_buffer *buf = list_entry(dev->active_buf_q.next,
194 struct flite_buffer, list);
195 list_del(&buf->list);
196 return buf;
197}
198
199static inline void fimc_lite_pending_queue_add(struct fimc_lite *dev,
200 struct flite_buffer *buf)
201{
202 list_add_tail(&buf->list, &dev->pending_buf_q);
203}
204
205static inline struct flite_buffer *fimc_lite_pending_queue_pop(
206 struct fimc_lite *dev)
207{
208 struct flite_buffer *buf = list_entry(dev->pending_buf_q.next,
209 struct flite_buffer, list);
210 list_del(&buf->list);
211 return buf;
212}
213
214#endif /* FIMC_LITE_H_ */
diff --git a/drivers/media/platform/exynos4-is/fimc-m2m.c b/drivers/media/platform/exynos4-is/fimc-m2m.c
new file mode 100644
index 000000000000..bde1f47f7ed3
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-m2m.c
@@ -0,0 +1,865 @@
1/*
2 * Samsung S5P/EXYNOS4 SoC series FIMC (video postprocessor) driver
3 *
4 * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd.
5 * Sylwester Nawrocki <s.nawrocki@samsung.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 as published
9 * by the Free Software Foundation, either version 2 of the License,
10 * or (at your option) any later version.
11 */
12
13#include <linux/module.h>
14#include <linux/kernel.h>
15#include <linux/types.h>
16#include <linux/errno.h>
17#include <linux/bug.h>
18#include <linux/interrupt.h>
19#include <linux/device.h>
20#include <linux/platform_device.h>
21#include <linux/pm_runtime.h>
22#include <linux/list.h>
23#include <linux/io.h>
24#include <linux/slab.h>
25#include <linux/clk.h>
26#include <media/v4l2-ioctl.h>
27#include <media/videobuf2-core.h>
28#include <media/videobuf2-dma-contig.h>
29
30#include "fimc-core.h"
31#include "fimc-reg.h"
32#include "media-dev.h"
33
34static unsigned int get_m2m_fmt_flags(unsigned int stream_type)
35{
36 if (stream_type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
37 return FMT_FLAGS_M2M_IN;
38 else
39 return FMT_FLAGS_M2M_OUT;
40}
41
42void fimc_m2m_job_finish(struct fimc_ctx *ctx, int vb_state)
43{
44 struct vb2_buffer *src_vb, *dst_vb;
45
46 if (!ctx || !ctx->m2m_ctx)
47 return;
48
49 src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
50 dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
51
52 if (src_vb && dst_vb) {
53 v4l2_m2m_buf_done(src_vb, vb_state);
54 v4l2_m2m_buf_done(dst_vb, vb_state);
55 v4l2_m2m_job_finish(ctx->fimc_dev->m2m.m2m_dev,
56 ctx->m2m_ctx);
57 }
58}
59
60/* Complete the transaction which has been scheduled for execution. */
61static int fimc_m2m_shutdown(struct fimc_ctx *ctx)
62{
63 struct fimc_dev *fimc = ctx->fimc_dev;
64 int ret;
65
66 if (!fimc_m2m_pending(fimc))
67 return 0;
68
69 fimc_ctx_state_set(FIMC_CTX_SHUT, ctx);
70
71 ret = wait_event_timeout(fimc->irq_queue,
72 !fimc_ctx_state_is_set(FIMC_CTX_SHUT, ctx),
73 FIMC_SHUTDOWN_TIMEOUT);
74
75 return ret == 0 ? -ETIMEDOUT : ret;
76}
77
78static int start_streaming(struct vb2_queue *q, unsigned int count)
79{
80 struct fimc_ctx *ctx = q->drv_priv;
81 int ret;
82
83 ret = pm_runtime_get_sync(&ctx->fimc_dev->pdev->dev);
84 return ret > 0 ? 0 : ret;
85}
86
87static int stop_streaming(struct vb2_queue *q)
88{
89 struct fimc_ctx *ctx = q->drv_priv;
90 int ret;
91
92 ret = fimc_m2m_shutdown(ctx);
93 if (ret == -ETIMEDOUT)
94 fimc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
95
96 pm_runtime_put(&ctx->fimc_dev->pdev->dev);
97 return 0;
98}
99
100static void fimc_device_run(void *priv)
101{
102 struct vb2_buffer *src_vb, *dst_vb;
103 struct fimc_ctx *ctx = priv;
104 struct fimc_frame *sf, *df;
105 struct fimc_dev *fimc;
106 unsigned long flags;
107 int ret;
108
109 if (WARN(!ctx, "Null context\n"))
110 return;
111
112 fimc = ctx->fimc_dev;
113 spin_lock_irqsave(&fimc->slock, flags);
114
115 set_bit(ST_M2M_PEND, &fimc->state);
116 sf = &ctx->s_frame;
117 df = &ctx->d_frame;
118
119 if (ctx->state & FIMC_PARAMS) {
120 /* Prepare the DMA offsets for scaler */
121 fimc_prepare_dma_offset(ctx, sf);
122 fimc_prepare_dma_offset(ctx, df);
123 }
124
125 src_vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
126 ret = fimc_prepare_addr(ctx, src_vb, sf, &sf->paddr);
127 if (ret)
128 goto dma_unlock;
129
130 dst_vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
131 ret = fimc_prepare_addr(ctx, dst_vb, df, &df->paddr);
132 if (ret)
133 goto dma_unlock;
134
135 dst_vb->v4l2_buf.timestamp = src_vb->v4l2_buf.timestamp;
136
137 /* Reconfigure hardware if the context has changed. */
138 if (fimc->m2m.ctx != ctx) {
139 ctx->state |= FIMC_PARAMS;
140 fimc->m2m.ctx = ctx;
141 }
142
143 if (ctx->state & FIMC_PARAMS) {
144 fimc_set_yuv_order(ctx);
145 fimc_hw_set_input_path(ctx);
146 fimc_hw_set_in_dma(ctx);
147 ret = fimc_set_scaler_info(ctx);
148 if (ret)
149 goto dma_unlock;
150 fimc_hw_set_prescaler(ctx);
151 fimc_hw_set_mainscaler(ctx);
152 fimc_hw_set_target_format(ctx);
153 fimc_hw_set_rotation(ctx);
154 fimc_hw_set_effect(ctx);
155 fimc_hw_set_out_dma(ctx);
156 if (fimc->drv_data->alpha_color)
157 fimc_hw_set_rgb_alpha(ctx);
158 fimc_hw_set_output_path(ctx);
159 }
160 fimc_hw_set_input_addr(fimc, &sf->paddr);
161 fimc_hw_set_output_addr(fimc, &df->paddr, -1);
162
163 fimc_activate_capture(ctx);
164 ctx->state &= (FIMC_CTX_M2M | FIMC_CTX_CAP);
165 fimc_hw_activate_input_dma(fimc, true);
166
167dma_unlock:
168 spin_unlock_irqrestore(&fimc->slock, flags);
169}
170
171static void fimc_job_abort(void *priv)
172{
173 fimc_m2m_shutdown(priv);
174}
175
176static int fimc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
177 unsigned int *num_buffers, unsigned int *num_planes,
178 unsigned int sizes[], void *allocators[])
179{
180 struct fimc_ctx *ctx = vb2_get_drv_priv(vq);
181 struct fimc_frame *f;
182 int i;
183
184 f = ctx_get_frame(ctx, vq->type);
185 if (IS_ERR(f))
186 return PTR_ERR(f);
187 /*
188 * Return number of non-contigous planes (plane buffers)
189 * depending on the configured color format.
190 */
191 if (!f->fmt)
192 return -EINVAL;
193
194 *num_planes = f->fmt->memplanes;
195 for (i = 0; i < f->fmt->memplanes; i++) {
196 sizes[i] = (f->f_width * f->f_height * f->fmt->depth[i]) / 8;
197 allocators[i] = ctx->fimc_dev->alloc_ctx;
198 }
199 return 0;
200}
201
202static int fimc_buf_prepare(struct vb2_buffer *vb)
203{
204 struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
205 struct fimc_frame *frame;
206 int i;
207
208 frame = ctx_get_frame(ctx, vb->vb2_queue->type);
209 if (IS_ERR(frame))
210 return PTR_ERR(frame);
211
212 for (i = 0; i < frame->fmt->memplanes; i++)
213 vb2_set_plane_payload(vb, i, frame->payload[i]);
214
215 return 0;
216}
217
218static void fimc_buf_queue(struct vb2_buffer *vb)
219{
220 struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
221
222 dbg("ctx: %p, ctx->state: 0x%x", ctx, ctx->state);
223
224 if (ctx->m2m_ctx)
225 v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
226}
227
228static void fimc_lock(struct vb2_queue *vq)
229{
230 struct fimc_ctx *ctx = vb2_get_drv_priv(vq);
231 mutex_lock(&ctx->fimc_dev->lock);
232}
233
234static void fimc_unlock(struct vb2_queue *vq)
235{
236 struct fimc_ctx *ctx = vb2_get_drv_priv(vq);
237 mutex_unlock(&ctx->fimc_dev->lock);
238}
239
240static struct vb2_ops fimc_qops = {
241 .queue_setup = fimc_queue_setup,
242 .buf_prepare = fimc_buf_prepare,
243 .buf_queue = fimc_buf_queue,
244 .wait_prepare = fimc_unlock,
245 .wait_finish = fimc_lock,
246 .stop_streaming = stop_streaming,
247 .start_streaming = start_streaming,
248};
249
250/*
251 * V4L2 ioctl handlers
252 */
253static int fimc_m2m_querycap(struct file *file, void *fh,
254 struct v4l2_capability *cap)
255{
256 struct fimc_dev *fimc = video_drvdata(file);
257 unsigned int caps;
258
259 /*
260 * This is only a mem-to-mem video device. The capture and output
261 * device capability flags are left only for backward compatibility
262 * and are scheduled for removal.
263 */
264 caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE |
265 V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE;
266
267 __fimc_vidioc_querycap(&fimc->pdev->dev, cap, caps);
268 return 0;
269}
270
271static int fimc_m2m_enum_fmt_mplane(struct file *file, void *priv,
272 struct v4l2_fmtdesc *f)
273{
274 struct fimc_fmt *fmt;
275
276 fmt = fimc_find_format(NULL, NULL, get_m2m_fmt_flags(f->type),
277 f->index);
278 if (!fmt)
279 return -EINVAL;
280
281 strncpy(f->description, fmt->name, sizeof(f->description) - 1);
282 f->pixelformat = fmt->fourcc;
283 return 0;
284}
285
286static int fimc_m2m_g_fmt_mplane(struct file *file, void *fh,
287 struct v4l2_format *f)
288{
289 struct fimc_ctx *ctx = fh_to_ctx(fh);
290 struct fimc_frame *frame = ctx_get_frame(ctx, f->type);
291
292 if (IS_ERR(frame))
293 return PTR_ERR(frame);
294
295 __fimc_get_format(frame, f);
296 return 0;
297}
298
299static int fimc_try_fmt_mplane(struct fimc_ctx *ctx, struct v4l2_format *f)
300{
301 struct fimc_dev *fimc = ctx->fimc_dev;
302 const struct fimc_variant *variant = fimc->variant;
303 struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
304 struct fimc_fmt *fmt;
305 u32 max_w, mod_x, mod_y;
306
307 if (!IS_M2M(f->type))
308 return -EINVAL;
309
310 fmt = fimc_find_format(&pix->pixelformat, NULL,
311 get_m2m_fmt_flags(f->type), 0);
312 if (WARN(fmt == NULL, "Pixel format lookup failed"))
313 return -EINVAL;
314
315 if (pix->field == V4L2_FIELD_ANY)
316 pix->field = V4L2_FIELD_NONE;
317 else if (pix->field != V4L2_FIELD_NONE)
318 return -EINVAL;
319
320 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
321 max_w = variant->pix_limit->scaler_dis_w;
322 mod_x = ffs(variant->min_inp_pixsize) - 1;
323 } else {
324 max_w = variant->pix_limit->out_rot_dis_w;
325 mod_x = ffs(variant->min_out_pixsize) - 1;
326 }
327
328 if (tiled_fmt(fmt)) {
329 mod_x = 6; /* 64 x 32 pixels tile */
330 mod_y = 5;
331 } else {
332 if (variant->min_vsize_align == 1)
333 mod_y = fimc_fmt_is_rgb(fmt->color) ? 0 : 1;
334 else
335 mod_y = ffs(variant->min_vsize_align) - 1;
336 }
337
338 v4l_bound_align_image(&pix->width, 16, max_w, mod_x,
339 &pix->height, 8, variant->pix_limit->scaler_dis_w, mod_y, 0);
340
341 fimc_adjust_mplane_format(fmt, pix->width, pix->height, &f->fmt.pix_mp);
342 return 0;
343}
344
345static int fimc_m2m_try_fmt_mplane(struct file *file, void *fh,
346 struct v4l2_format *f)
347{
348 struct fimc_ctx *ctx = fh_to_ctx(fh);
349 return fimc_try_fmt_mplane(ctx, f);
350}
351
352static void __set_frame_format(struct fimc_frame *frame, struct fimc_fmt *fmt,
353 struct v4l2_pix_format_mplane *pixm)
354{
355 int i;
356
357 for (i = 0; i < fmt->colplanes; i++) {
358 frame->bytesperline[i] = pixm->plane_fmt[i].bytesperline;
359 frame->payload[i] = pixm->plane_fmt[i].sizeimage;
360 }
361
362 frame->f_width = pixm->width;
363 frame->f_height = pixm->height;
364 frame->o_width = pixm->width;
365 frame->o_height = pixm->height;
366 frame->width = pixm->width;
367 frame->height = pixm->height;
368 frame->offs_h = 0;
369 frame->offs_v = 0;
370 frame->fmt = fmt;
371}
372
373static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh,
374 struct v4l2_format *f)
375{
376 struct fimc_ctx *ctx = fh_to_ctx(fh);
377 struct fimc_dev *fimc = ctx->fimc_dev;
378 struct fimc_fmt *fmt;
379 struct vb2_queue *vq;
380 struct fimc_frame *frame;
381 int ret;
382
383 ret = fimc_try_fmt_mplane(ctx, f);
384 if (ret)
385 return ret;
386
387 vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
388
389 if (vb2_is_busy(vq)) {
390 v4l2_err(&fimc->m2m.vfd, "queue (%d) busy\n", f->type);
391 return -EBUSY;
392 }
393
394 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
395 frame = &ctx->s_frame;
396 else
397 frame = &ctx->d_frame;
398
399 fmt = fimc_find_format(&f->fmt.pix_mp.pixelformat, NULL,
400 get_m2m_fmt_flags(f->type), 0);
401 if (!fmt)
402 return -EINVAL;
403
404 __set_frame_format(frame, fmt, &f->fmt.pix_mp);
405
406 /* Update RGB Alpha control state and value range */
407 fimc_alpha_ctrl_update(ctx);
408
409 return 0;
410}
411
412static int fimc_m2m_reqbufs(struct file *file, void *fh,
413 struct v4l2_requestbuffers *reqbufs)
414{
415 struct fimc_ctx *ctx = fh_to_ctx(fh);
416 return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
417}
418
419static int fimc_m2m_querybuf(struct file *file, void *fh,
420 struct v4l2_buffer *buf)
421{
422 struct fimc_ctx *ctx = fh_to_ctx(fh);
423 return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
424}
425
426static int fimc_m2m_qbuf(struct file *file, void *fh,
427 struct v4l2_buffer *buf)
428{
429 struct fimc_ctx *ctx = fh_to_ctx(fh);
430 return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
431}
432
433static int fimc_m2m_dqbuf(struct file *file, void *fh,
434 struct v4l2_buffer *buf)
435{
436 struct fimc_ctx *ctx = fh_to_ctx(fh);
437 return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
438}
439
440static int fimc_m2m_expbuf(struct file *file, void *fh,
441 struct v4l2_exportbuffer *eb)
442{
443 struct fimc_ctx *ctx = fh_to_ctx(fh);
444 return v4l2_m2m_expbuf(file, ctx->m2m_ctx, eb);
445}
446
447
448static int fimc_m2m_streamon(struct file *file, void *fh,
449 enum v4l2_buf_type type)
450{
451 struct fimc_ctx *ctx = fh_to_ctx(fh);
452 return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
453}
454
455static int fimc_m2m_streamoff(struct file *file, void *fh,
456 enum v4l2_buf_type type)
457{
458 struct fimc_ctx *ctx = fh_to_ctx(fh);
459 return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
460}
461
462static int fimc_m2m_cropcap(struct file *file, void *fh,
463 struct v4l2_cropcap *cr)
464{
465 struct fimc_ctx *ctx = fh_to_ctx(fh);
466 struct fimc_frame *frame;
467
468 frame = ctx_get_frame(ctx, cr->type);
469 if (IS_ERR(frame))
470 return PTR_ERR(frame);
471
472 cr->bounds.left = 0;
473 cr->bounds.top = 0;
474 cr->bounds.width = frame->o_width;
475 cr->bounds.height = frame->o_height;
476 cr->defrect = cr->bounds;
477
478 return 0;
479}
480
481static int fimc_m2m_g_crop(struct file *file, void *fh, struct v4l2_crop *cr)
482{
483 struct fimc_ctx *ctx = fh_to_ctx(fh);
484 struct fimc_frame *frame;
485
486 frame = ctx_get_frame(ctx, cr->type);
487 if (IS_ERR(frame))
488 return PTR_ERR(frame);
489
490 cr->c.left = frame->offs_h;
491 cr->c.top = frame->offs_v;
492 cr->c.width = frame->width;
493 cr->c.height = frame->height;
494
495 return 0;
496}
497
498static int fimc_m2m_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
499{
500 struct fimc_dev *fimc = ctx->fimc_dev;
501 struct fimc_frame *f;
502 u32 min_size, halign, depth = 0;
503 int i;
504
505 if (cr->c.top < 0 || cr->c.left < 0) {
506 v4l2_err(&fimc->m2m.vfd,
507 "doesn't support negative values for top & left\n");
508 return -EINVAL;
509 }
510 if (cr->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
511 f = &ctx->d_frame;
512 else if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
513 f = &ctx->s_frame;
514 else
515 return -EINVAL;
516
517 min_size = (f == &ctx->s_frame) ?
518 fimc->variant->min_inp_pixsize : fimc->variant->min_out_pixsize;
519
520 /* Get pixel alignment constraints. */
521 if (fimc->variant->min_vsize_align == 1)
522 halign = fimc_fmt_is_rgb(f->fmt->color) ? 0 : 1;
523 else
524 halign = ffs(fimc->variant->min_vsize_align) - 1;
525
526 for (i = 0; i < f->fmt->colplanes; i++)
527 depth += f->fmt->depth[i];
528
529 v4l_bound_align_image(&cr->c.width, min_size, f->o_width,
530 ffs(min_size) - 1,
531 &cr->c.height, min_size, f->o_height,
532 halign, 64/(ALIGN(depth, 8)));
533
534 /* adjust left/top if cropping rectangle is out of bounds */
535 if (cr->c.left + cr->c.width > f->o_width)
536 cr->c.left = f->o_width - cr->c.width;
537 if (cr->c.top + cr->c.height > f->o_height)
538 cr->c.top = f->o_height - cr->c.height;
539
540 cr->c.left = round_down(cr->c.left, min_size);
541 cr->c.top = round_down(cr->c.top, fimc->variant->hor_offs_align);
542
543 dbg("l:%d, t:%d, w:%d, h:%d, f_w: %d, f_h: %d",
544 cr->c.left, cr->c.top, cr->c.width, cr->c.height,
545 f->f_width, f->f_height);
546
547 return 0;
548}
549
550static int fimc_m2m_s_crop(struct file *file, void *fh, const struct v4l2_crop *crop)
551{
552 struct fimc_ctx *ctx = fh_to_ctx(fh);
553 struct fimc_dev *fimc = ctx->fimc_dev;
554 struct v4l2_crop cr = *crop;
555 struct fimc_frame *f;
556 int ret;
557
558 ret = fimc_m2m_try_crop(ctx, &cr);
559 if (ret)
560 return ret;
561
562 f = (cr.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ?
563 &ctx->s_frame : &ctx->d_frame;
564
565 /* Check to see if scaling ratio is within supported range */
566 if (cr.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
567 ret = fimc_check_scaler_ratio(ctx, cr.c.width,
568 cr.c.height, ctx->d_frame.width,
569 ctx->d_frame.height, ctx->rotation);
570 } else {
571 ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width,
572 ctx->s_frame.height, cr.c.width,
573 cr.c.height, ctx->rotation);
574 }
575 if (ret) {
576 v4l2_err(&fimc->m2m.vfd, "Out of scaler range\n");
577 return -EINVAL;
578 }
579
580 f->offs_h = cr.c.left;
581 f->offs_v = cr.c.top;
582 f->width = cr.c.width;
583 f->height = cr.c.height;
584
585 fimc_ctx_state_set(FIMC_PARAMS, ctx);
586
587 return 0;
588}
589
590static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = {
591 .vidioc_querycap = fimc_m2m_querycap,
592 .vidioc_enum_fmt_vid_cap_mplane = fimc_m2m_enum_fmt_mplane,
593 .vidioc_enum_fmt_vid_out_mplane = fimc_m2m_enum_fmt_mplane,
594 .vidioc_g_fmt_vid_cap_mplane = fimc_m2m_g_fmt_mplane,
595 .vidioc_g_fmt_vid_out_mplane = fimc_m2m_g_fmt_mplane,
596 .vidioc_try_fmt_vid_cap_mplane = fimc_m2m_try_fmt_mplane,
597 .vidioc_try_fmt_vid_out_mplane = fimc_m2m_try_fmt_mplane,
598 .vidioc_s_fmt_vid_cap_mplane = fimc_m2m_s_fmt_mplane,
599 .vidioc_s_fmt_vid_out_mplane = fimc_m2m_s_fmt_mplane,
600 .vidioc_reqbufs = fimc_m2m_reqbufs,
601 .vidioc_querybuf = fimc_m2m_querybuf,
602 .vidioc_qbuf = fimc_m2m_qbuf,
603 .vidioc_dqbuf = fimc_m2m_dqbuf,
604 .vidioc_expbuf = fimc_m2m_expbuf,
605 .vidioc_streamon = fimc_m2m_streamon,
606 .vidioc_streamoff = fimc_m2m_streamoff,
607 .vidioc_g_crop = fimc_m2m_g_crop,
608 .vidioc_s_crop = fimc_m2m_s_crop,
609 .vidioc_cropcap = fimc_m2m_cropcap
610
611};
612
613static int queue_init(void *priv, struct vb2_queue *src_vq,
614 struct vb2_queue *dst_vq)
615{
616 struct fimc_ctx *ctx = priv;
617 int ret;
618
619 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
620 src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
621 src_vq->drv_priv = ctx;
622 src_vq->ops = &fimc_qops;
623 src_vq->mem_ops = &vb2_dma_contig_memops;
624 src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
625 src_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY;
626
627 ret = vb2_queue_init(src_vq);
628 if (ret)
629 return ret;
630
631 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
632 dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
633 dst_vq->drv_priv = ctx;
634 dst_vq->ops = &fimc_qops;
635 dst_vq->mem_ops = &vb2_dma_contig_memops;
636 dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
637 dst_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY;
638
639 return vb2_queue_init(dst_vq);
640}
641
642static int fimc_m2m_set_default_format(struct fimc_ctx *ctx)
643{
644 struct v4l2_pix_format_mplane pixm = {
645 .pixelformat = V4L2_PIX_FMT_RGB32,
646 .width = 800,
647 .height = 600,
648 .plane_fmt[0] = {
649 .bytesperline = 800 * 4,
650 .sizeimage = 800 * 4 * 600,
651 },
652 };
653 struct fimc_fmt *fmt;
654
655 fmt = fimc_find_format(&pixm.pixelformat, NULL, FMT_FLAGS_M2M, 0);
656 if (!fmt)
657 return -EINVAL;
658
659 __set_frame_format(&ctx->s_frame, fmt, &pixm);
660 __set_frame_format(&ctx->d_frame, fmt, &pixm);
661
662 return 0;
663}
664
665static int fimc_m2m_open(struct file *file)
666{
667 struct fimc_dev *fimc = video_drvdata(file);
668 struct fimc_ctx *ctx;
669 int ret = -EBUSY;
670
671 pr_debug("pid: %d, state: %#lx\n", task_pid_nr(current), fimc->state);
672
673 if (mutex_lock_interruptible(&fimc->lock))
674 return -ERESTARTSYS;
675 /*
676 * Don't allow simultaneous open() of the mem-to-mem and the
677 * capture video node that belong to same FIMC IP instance.
678 */
679 if (test_bit(ST_CAPT_BUSY, &fimc->state))
680 goto unlock;
681
682 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
683 if (!ctx) {
684 ret = -ENOMEM;
685 goto unlock;
686 }
687 v4l2_fh_init(&ctx->fh, &fimc->m2m.vfd);
688 ctx->fimc_dev = fimc;
689
690 /* Default color format */
691 ctx->s_frame.fmt = fimc_get_format(0);
692 ctx->d_frame.fmt = fimc_get_format(0);
693
694 ret = fimc_ctrls_create(ctx);
695 if (ret)
696 goto error_fh;
697
698 /* Use separate control handler per file handle */
699 ctx->fh.ctrl_handler = &ctx->ctrls.handler;
700 file->private_data = &ctx->fh;
701 v4l2_fh_add(&ctx->fh);
702
703 /* Setup the device context for memory-to-memory mode */
704 ctx->state = FIMC_CTX_M2M;
705 ctx->flags = 0;
706 ctx->in_path = FIMC_IO_DMA;
707 ctx->out_path = FIMC_IO_DMA;
708 ctx->scaler.enabled = 1;
709
710 ctx->m2m_ctx = v4l2_m2m_ctx_init(fimc->m2m.m2m_dev, ctx, queue_init);
711 if (IS_ERR(ctx->m2m_ctx)) {
712 ret = PTR_ERR(ctx->m2m_ctx);
713 goto error_c;
714 }
715
716 if (fimc->m2m.refcnt++ == 0)
717 set_bit(ST_M2M_RUN, &fimc->state);
718
719 ret = fimc_m2m_set_default_format(ctx);
720 if (ret < 0)
721 goto error_m2m_ctx;
722
723 mutex_unlock(&fimc->lock);
724 return 0;
725
726error_m2m_ctx:
727 v4l2_m2m_ctx_release(ctx->m2m_ctx);
728error_c:
729 fimc_ctrls_delete(ctx);
730error_fh:
731 v4l2_fh_del(&ctx->fh);
732 v4l2_fh_exit(&ctx->fh);
733 kfree(ctx);
734unlock:
735 mutex_unlock(&fimc->lock);
736 return ret;
737}
738
739static int fimc_m2m_release(struct file *file)
740{
741 struct fimc_ctx *ctx = fh_to_ctx(file->private_data);
742 struct fimc_dev *fimc = ctx->fimc_dev;
743
744 dbg("pid: %d, state: 0x%lx, refcnt= %d",
745 task_pid_nr(current), fimc->state, fimc->m2m.refcnt);
746
747 mutex_lock(&fimc->lock);
748
749 v4l2_m2m_ctx_release(ctx->m2m_ctx);
750 fimc_ctrls_delete(ctx);
751 v4l2_fh_del(&ctx->fh);
752 v4l2_fh_exit(&ctx->fh);
753
754 if (--fimc->m2m.refcnt <= 0)
755 clear_bit(ST_M2M_RUN, &fimc->state);
756 kfree(ctx);
757
758 mutex_unlock(&fimc->lock);
759 return 0;
760}
761
762static unsigned int fimc_m2m_poll(struct file *file,
763 struct poll_table_struct *wait)
764{
765 struct fimc_ctx *ctx = fh_to_ctx(file->private_data);
766 struct fimc_dev *fimc = ctx->fimc_dev;
767 int ret;
768
769 if (mutex_lock_interruptible(&fimc->lock))
770 return -ERESTARTSYS;
771
772 ret = v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
773 mutex_unlock(&fimc->lock);
774
775 return ret;
776}
777
778
779static int fimc_m2m_mmap(struct file *file, struct vm_area_struct *vma)
780{
781 struct fimc_ctx *ctx = fh_to_ctx(file->private_data);
782 struct fimc_dev *fimc = ctx->fimc_dev;
783 int ret;
784
785 if (mutex_lock_interruptible(&fimc->lock))
786 return -ERESTARTSYS;
787
788 ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
789 mutex_unlock(&fimc->lock);
790
791 return ret;
792}
793
794static const struct v4l2_file_operations fimc_m2m_fops = {
795 .owner = THIS_MODULE,
796 .open = fimc_m2m_open,
797 .release = fimc_m2m_release,
798 .poll = fimc_m2m_poll,
799 .unlocked_ioctl = video_ioctl2,
800 .mmap = fimc_m2m_mmap,
801};
802
803static struct v4l2_m2m_ops m2m_ops = {
804 .device_run = fimc_device_run,
805 .job_abort = fimc_job_abort,
806};
807
808int fimc_register_m2m_device(struct fimc_dev *fimc,
809 struct v4l2_device *v4l2_dev)
810{
811 struct video_device *vfd = &fimc->m2m.vfd;
812 int ret;
813
814 fimc->v4l2_dev = v4l2_dev;
815
816 memset(vfd, 0, sizeof(*vfd));
817 vfd->fops = &fimc_m2m_fops;
818 vfd->ioctl_ops = &fimc_m2m_ioctl_ops;
819 vfd->v4l2_dev = v4l2_dev;
820 vfd->minor = -1;
821 vfd->release = video_device_release_empty;
822 vfd->lock = &fimc->lock;
823 vfd->vfl_dir = VFL_DIR_M2M;
824
825 snprintf(vfd->name, sizeof(vfd->name), "fimc.%d.m2m", fimc->id);
826 video_set_drvdata(vfd, fimc);
827
828 fimc->m2m.m2m_dev = v4l2_m2m_init(&m2m_ops);
829 if (IS_ERR(fimc->m2m.m2m_dev)) {
830 v4l2_err(v4l2_dev, "failed to initialize v4l2-m2m device\n");
831 return PTR_ERR(fimc->m2m.m2m_dev);
832 }
833
834 ret = media_entity_init(&vfd->entity, 0, NULL, 0);
835 if (ret)
836 goto err_me;
837
838 ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
839 if (ret)
840 goto err_vd;
841
842 v4l2_info(v4l2_dev, "Registered %s as /dev/%s\n",
843 vfd->name, video_device_node_name(vfd));
844 return 0;
845
846err_vd:
847 media_entity_cleanup(&vfd->entity);
848err_me:
849 v4l2_m2m_release(fimc->m2m.m2m_dev);
850 return ret;
851}
852
853void fimc_unregister_m2m_device(struct fimc_dev *fimc)
854{
855 if (!fimc)
856 return;
857
858 if (fimc->m2m.m2m_dev)
859 v4l2_m2m_release(fimc->m2m.m2m_dev);
860
861 if (video_is_registered(&fimc->m2m.vfd)) {
862 video_unregister_device(&fimc->m2m.vfd);
863 media_entity_cleanup(&fimc->m2m.vfd.entity);
864 }
865}
diff --git a/drivers/media/platform/exynos4-is/fimc-reg.c b/drivers/media/platform/exynos4-is/fimc-reg.c
new file mode 100644
index 000000000000..f079f36099de
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-reg.c
@@ -0,0 +1,841 @@
1/*
2 * Register interface file for Samsung Camera Interface (FIMC) driver
3 *
4 * Copyright (C) 2010 - 2013 Samsung Electronics Co., Ltd.
5 * Sylwester Nawrocki <s.nawrocki@samsung.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#include <linux/delay.h>
13#include <linux/io.h>
14#include <linux/regmap.h>
15
16#include <media/s5p_fimc.h>
17#include "media-dev.h"
18
19#include "fimc-reg.h"
20#include "fimc-core.h"
21
22void fimc_hw_reset(struct fimc_dev *dev)
23{
24 u32 cfg;
25
26 cfg = readl(dev->regs + FIMC_REG_CISRCFMT);
27 cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
28 writel(cfg, dev->regs + FIMC_REG_CISRCFMT);
29
30 /* Software reset. */
31 cfg = readl(dev->regs + FIMC_REG_CIGCTRL);
32 cfg |= (FIMC_REG_CIGCTRL_SWRST | FIMC_REG_CIGCTRL_IRQ_LEVEL);
33 writel(cfg, dev->regs + FIMC_REG_CIGCTRL);
34 udelay(10);
35
36 cfg = readl(dev->regs + FIMC_REG_CIGCTRL);
37 cfg &= ~FIMC_REG_CIGCTRL_SWRST;
38 writel(cfg, dev->regs + FIMC_REG_CIGCTRL);
39
40 if (dev->drv_data->out_buf_count > 4)
41 fimc_hw_set_dma_seq(dev, 0xF);
42}
43
44static u32 fimc_hw_get_in_flip(struct fimc_ctx *ctx)
45{
46 u32 flip = FIMC_REG_MSCTRL_FLIP_NORMAL;
47
48 if (ctx->hflip)
49 flip = FIMC_REG_MSCTRL_FLIP_Y_MIRROR;
50 if (ctx->vflip)
51 flip = FIMC_REG_MSCTRL_FLIP_X_MIRROR;
52
53 if (ctx->rotation <= 90)
54 return flip;
55
56 return (flip ^ FIMC_REG_MSCTRL_FLIP_180) & FIMC_REG_MSCTRL_FLIP_180;
57}
58
59static u32 fimc_hw_get_target_flip(struct fimc_ctx *ctx)
60{
61 u32 flip = FIMC_REG_CITRGFMT_FLIP_NORMAL;
62
63 if (ctx->hflip)
64 flip |= FIMC_REG_CITRGFMT_FLIP_Y_MIRROR;
65 if (ctx->vflip)
66 flip |= FIMC_REG_CITRGFMT_FLIP_X_MIRROR;
67
68 if (ctx->rotation <= 90)
69 return flip;
70
71 return (flip ^ FIMC_REG_CITRGFMT_FLIP_180) & FIMC_REG_CITRGFMT_FLIP_180;
72}
73
74void fimc_hw_set_rotation(struct fimc_ctx *ctx)
75{
76 u32 cfg, flip;
77 struct fimc_dev *dev = ctx->fimc_dev;
78
79 cfg = readl(dev->regs + FIMC_REG_CITRGFMT);
80 cfg &= ~(FIMC_REG_CITRGFMT_INROT90 | FIMC_REG_CITRGFMT_OUTROT90 |
81 FIMC_REG_CITRGFMT_FLIP_180);
82
83 /*
84 * The input and output rotator cannot work simultaneously.
85 * Use the output rotator in output DMA mode or the input rotator
86 * in direct fifo output mode.
87 */
88 if (ctx->rotation == 90 || ctx->rotation == 270) {
89 if (ctx->out_path == FIMC_IO_LCDFIFO)
90 cfg |= FIMC_REG_CITRGFMT_INROT90;
91 else
92 cfg |= FIMC_REG_CITRGFMT_OUTROT90;
93 }
94
95 if (ctx->out_path == FIMC_IO_DMA) {
96 cfg |= fimc_hw_get_target_flip(ctx);
97 writel(cfg, dev->regs + FIMC_REG_CITRGFMT);
98 } else {
99 /* LCD FIFO path */
100 flip = readl(dev->regs + FIMC_REG_MSCTRL);
101 flip &= ~FIMC_REG_MSCTRL_FLIP_MASK;
102 flip |= fimc_hw_get_in_flip(ctx);
103 writel(flip, dev->regs + FIMC_REG_MSCTRL);
104 }
105}
106
107void fimc_hw_set_target_format(struct fimc_ctx *ctx)
108{
109 u32 cfg;
110 struct fimc_dev *dev = ctx->fimc_dev;
111 struct fimc_frame *frame = &ctx->d_frame;
112
113 dbg("w= %d, h= %d color: %d", frame->width,
114 frame->height, frame->fmt->color);
115
116 cfg = readl(dev->regs + FIMC_REG_CITRGFMT);
117 cfg &= ~(FIMC_REG_CITRGFMT_FMT_MASK | FIMC_REG_CITRGFMT_HSIZE_MASK |
118 FIMC_REG_CITRGFMT_VSIZE_MASK);
119
120 switch (frame->fmt->color) {
121 case FIMC_FMT_RGB444...FIMC_FMT_RGB888:
122 cfg |= FIMC_REG_CITRGFMT_RGB;
123 break;
124 case FIMC_FMT_YCBCR420:
125 cfg |= FIMC_REG_CITRGFMT_YCBCR420;
126 break;
127 case FIMC_FMT_YCBYCR422...FIMC_FMT_CRYCBY422:
128 if (frame->fmt->colplanes == 1)
129 cfg |= FIMC_REG_CITRGFMT_YCBCR422_1P;
130 else
131 cfg |= FIMC_REG_CITRGFMT_YCBCR422;
132 break;
133 default:
134 break;
135 }
136
137 if (ctx->rotation == 90 || ctx->rotation == 270)
138 cfg |= (frame->height << 16) | frame->width;
139 else
140 cfg |= (frame->width << 16) | frame->height;
141
142 writel(cfg, dev->regs + FIMC_REG_CITRGFMT);
143
144 cfg = readl(dev->regs + FIMC_REG_CITAREA);
145 cfg &= ~FIMC_REG_CITAREA_MASK;
146 cfg |= (frame->width * frame->height);
147 writel(cfg, dev->regs + FIMC_REG_CITAREA);
148}
149
150static void fimc_hw_set_out_dma_size(struct fimc_ctx *ctx)
151{
152 struct fimc_dev *dev = ctx->fimc_dev;
153 struct fimc_frame *frame = &ctx->d_frame;
154 u32 cfg;
155
156 cfg = (frame->f_height << 16) | frame->f_width;
157 writel(cfg, dev->regs + FIMC_REG_ORGOSIZE);
158
159 /* Select color space conversion equation (HD/SD size).*/
160 cfg = readl(dev->regs + FIMC_REG_CIGCTRL);
161 if (frame->f_width >= 1280) /* HD */
162 cfg |= FIMC_REG_CIGCTRL_CSC_ITU601_709;
163 else /* SD */
164 cfg &= ~FIMC_REG_CIGCTRL_CSC_ITU601_709;
165 writel(cfg, dev->regs + FIMC_REG_CIGCTRL);
166
167}
168
169void fimc_hw_set_out_dma(struct fimc_ctx *ctx)
170{
171 struct fimc_dev *dev = ctx->fimc_dev;
172 struct fimc_frame *frame = &ctx->d_frame;
173 struct fimc_dma_offset *offset = &frame->dma_offset;
174 struct fimc_fmt *fmt = frame->fmt;
175 u32 cfg;
176
177 /* Set the input dma offsets. */
178 cfg = (offset->y_v << 16) | offset->y_h;
179 writel(cfg, dev->regs + FIMC_REG_CIOYOFF);
180
181 cfg = (offset->cb_v << 16) | offset->cb_h;
182 writel(cfg, dev->regs + FIMC_REG_CIOCBOFF);
183
184 cfg = (offset->cr_v << 16) | offset->cr_h;
185 writel(cfg, dev->regs + FIMC_REG_CIOCROFF);
186
187 fimc_hw_set_out_dma_size(ctx);
188
189 /* Configure chroma components order. */
190 cfg = readl(dev->regs + FIMC_REG_CIOCTRL);
191
192 cfg &= ~(FIMC_REG_CIOCTRL_ORDER2P_MASK |
193 FIMC_REG_CIOCTRL_ORDER422_MASK |
194 FIMC_REG_CIOCTRL_YCBCR_PLANE_MASK |
195 FIMC_REG_CIOCTRL_RGB16FMT_MASK);
196
197 if (fmt->colplanes == 1)
198 cfg |= ctx->out_order_1p;
199 else if (fmt->colplanes == 2)
200 cfg |= ctx->out_order_2p | FIMC_REG_CIOCTRL_YCBCR_2PLANE;
201 else if (fmt->colplanes == 3)
202 cfg |= FIMC_REG_CIOCTRL_YCBCR_3PLANE;
203
204 if (fmt->color == FIMC_FMT_RGB565)
205 cfg |= FIMC_REG_CIOCTRL_RGB565;
206 else if (fmt->color == FIMC_FMT_RGB555)
207 cfg |= FIMC_REG_CIOCTRL_ARGB1555;
208 else if (fmt->color == FIMC_FMT_RGB444)
209 cfg |= FIMC_REG_CIOCTRL_ARGB4444;
210
211 writel(cfg, dev->regs + FIMC_REG_CIOCTRL);
212}
213
214static void fimc_hw_en_autoload(struct fimc_dev *dev, int enable)
215{
216 u32 cfg = readl(dev->regs + FIMC_REG_ORGISIZE);
217 if (enable)
218 cfg |= FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN;
219 else
220 cfg &= ~FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN;
221 writel(cfg, dev->regs + FIMC_REG_ORGISIZE);
222}
223
224void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable)
225{
226 u32 cfg = readl(dev->regs + FIMC_REG_CIOCTRL);
227 if (enable)
228 cfg |= FIMC_REG_CIOCTRL_LASTIRQ_ENABLE;
229 else
230 cfg &= ~FIMC_REG_CIOCTRL_LASTIRQ_ENABLE;
231 writel(cfg, dev->regs + FIMC_REG_CIOCTRL);
232}
233
234void fimc_hw_set_prescaler(struct fimc_ctx *ctx)
235{
236 struct fimc_dev *dev = ctx->fimc_dev;
237 struct fimc_scaler *sc = &ctx->scaler;
238 u32 cfg, shfactor;
239
240 shfactor = 10 - (sc->hfactor + sc->vfactor);
241 cfg = shfactor << 28;
242
243 cfg |= (sc->pre_hratio << 16) | sc->pre_vratio;
244 writel(cfg, dev->regs + FIMC_REG_CISCPRERATIO);
245
246 cfg = (sc->pre_dst_width << 16) | sc->pre_dst_height;
247 writel(cfg, dev->regs + FIMC_REG_CISCPREDST);
248}
249
250static void fimc_hw_set_scaler(struct fimc_ctx *ctx)
251{
252 struct fimc_dev *dev = ctx->fimc_dev;
253 struct fimc_scaler *sc = &ctx->scaler;
254 struct fimc_frame *src_frame = &ctx->s_frame;
255 struct fimc_frame *dst_frame = &ctx->d_frame;
256
257 u32 cfg = readl(dev->regs + FIMC_REG_CISCCTRL);
258
259 cfg &= ~(FIMC_REG_CISCCTRL_CSCR2Y_WIDE | FIMC_REG_CISCCTRL_CSCY2R_WIDE |
260 FIMC_REG_CISCCTRL_SCALEUP_H | FIMC_REG_CISCCTRL_SCALEUP_V |
261 FIMC_REG_CISCCTRL_SCALERBYPASS | FIMC_REG_CISCCTRL_ONE2ONE |
262 FIMC_REG_CISCCTRL_INRGB_FMT_MASK | FIMC_REG_CISCCTRL_OUTRGB_FMT_MASK |
263 FIMC_REG_CISCCTRL_INTERLACE | FIMC_REG_CISCCTRL_RGB_EXT);
264
265 if (!(ctx->flags & FIMC_COLOR_RANGE_NARROW))
266 cfg |= (FIMC_REG_CISCCTRL_CSCR2Y_WIDE |
267 FIMC_REG_CISCCTRL_CSCY2R_WIDE);
268
269 if (!sc->enabled)
270 cfg |= FIMC_REG_CISCCTRL_SCALERBYPASS;
271
272 if (sc->scaleup_h)
273 cfg |= FIMC_REG_CISCCTRL_SCALEUP_H;
274
275 if (sc->scaleup_v)
276 cfg |= FIMC_REG_CISCCTRL_SCALEUP_V;
277
278 if (sc->copy_mode)
279 cfg |= FIMC_REG_CISCCTRL_ONE2ONE;
280
281 if (ctx->in_path == FIMC_IO_DMA) {
282 switch (src_frame->fmt->color) {
283 case FIMC_FMT_RGB565:
284 cfg |= FIMC_REG_CISCCTRL_INRGB_FMT_RGB565;
285 break;
286 case FIMC_FMT_RGB666:
287 cfg |= FIMC_REG_CISCCTRL_INRGB_FMT_RGB666;
288 break;
289 case FIMC_FMT_RGB888:
290 cfg |= FIMC_REG_CISCCTRL_INRGB_FMT_RGB888;
291 break;
292 }
293 }
294
295 if (ctx->out_path == FIMC_IO_DMA) {
296 u32 color = dst_frame->fmt->color;
297
298 if (color >= FIMC_FMT_RGB444 && color <= FIMC_FMT_RGB565)
299 cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB565;
300 else if (color == FIMC_FMT_RGB666)
301 cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB666;
302 else if (color == FIMC_FMT_RGB888)
303 cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB888;
304 } else {
305 cfg |= FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB888;
306
307 if (ctx->flags & FIMC_SCAN_MODE_INTERLACED)
308 cfg |= FIMC_REG_CISCCTRL_INTERLACE;
309 }
310
311 writel(cfg, dev->regs + FIMC_REG_CISCCTRL);
312}
313
314void fimc_hw_set_mainscaler(struct fimc_ctx *ctx)
315{
316 struct fimc_dev *dev = ctx->fimc_dev;
317 const struct fimc_variant *variant = dev->variant;
318 struct fimc_scaler *sc = &ctx->scaler;
319 u32 cfg;
320
321 dbg("main_hratio= 0x%X main_vratio= 0x%X",
322 sc->main_hratio, sc->main_vratio);
323
324 fimc_hw_set_scaler(ctx);
325
326 cfg = readl(dev->regs + FIMC_REG_CISCCTRL);
327 cfg &= ~(FIMC_REG_CISCCTRL_MHRATIO_MASK |
328 FIMC_REG_CISCCTRL_MVRATIO_MASK);
329
330 if (variant->has_mainscaler_ext) {
331 cfg |= FIMC_REG_CISCCTRL_MHRATIO_EXT(sc->main_hratio);
332 cfg |= FIMC_REG_CISCCTRL_MVRATIO_EXT(sc->main_vratio);
333 writel(cfg, dev->regs + FIMC_REG_CISCCTRL);
334
335 cfg = readl(dev->regs + FIMC_REG_CIEXTEN);
336
337 cfg &= ~(FIMC_REG_CIEXTEN_MVRATIO_EXT_MASK |
338 FIMC_REG_CIEXTEN_MHRATIO_EXT_MASK);
339 cfg |= FIMC_REG_CIEXTEN_MHRATIO_EXT(sc->main_hratio);
340 cfg |= FIMC_REG_CIEXTEN_MVRATIO_EXT(sc->main_vratio);
341 writel(cfg, dev->regs + FIMC_REG_CIEXTEN);
342 } else {
343 cfg |= FIMC_REG_CISCCTRL_MHRATIO(sc->main_hratio);
344 cfg |= FIMC_REG_CISCCTRL_MVRATIO(sc->main_vratio);
345 writel(cfg, dev->regs + FIMC_REG_CISCCTRL);
346 }
347}
348
349void fimc_hw_enable_capture(struct fimc_ctx *ctx)
350{
351 struct fimc_dev *dev = ctx->fimc_dev;
352 u32 cfg;
353
354 cfg = readl(dev->regs + FIMC_REG_CIIMGCPT);
355 cfg |= FIMC_REG_CIIMGCPT_CPT_FREN_ENABLE;
356
357 if (ctx->scaler.enabled)
358 cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN_SC;
359 else
360 cfg &= FIMC_REG_CIIMGCPT_IMGCPTEN_SC;
361
362 cfg |= FIMC_REG_CIIMGCPT_IMGCPTEN;
363 writel(cfg, dev->regs + FIMC_REG_CIIMGCPT);
364}
365
366void fimc_hw_disable_capture(struct fimc_dev *dev)
367{
368 u32 cfg = readl(dev->regs + FIMC_REG_CIIMGCPT);
369 cfg &= ~(FIMC_REG_CIIMGCPT_IMGCPTEN |
370 FIMC_REG_CIIMGCPT_IMGCPTEN_SC);
371 writel(cfg, dev->regs + FIMC_REG_CIIMGCPT);
372}
373
374void fimc_hw_set_effect(struct fimc_ctx *ctx)
375{
376 struct fimc_dev *dev = ctx->fimc_dev;
377 struct fimc_effect *effect = &ctx->effect;
378 u32 cfg = 0;
379
380 if (effect->type != FIMC_REG_CIIMGEFF_FIN_BYPASS) {
381 cfg |= FIMC_REG_CIIMGEFF_IE_SC_AFTER |
382 FIMC_REG_CIIMGEFF_IE_ENABLE;
383 cfg |= effect->type;
384 if (effect->type == FIMC_REG_CIIMGEFF_FIN_ARBITRARY)
385 cfg |= (effect->pat_cb << 13) | effect->pat_cr;
386 }
387
388 writel(cfg, dev->regs + FIMC_REG_CIIMGEFF);
389}
390
391void fimc_hw_set_rgb_alpha(struct fimc_ctx *ctx)
392{
393 struct fimc_dev *dev = ctx->fimc_dev;
394 struct fimc_frame *frame = &ctx->d_frame;
395 u32 cfg;
396
397 if (!(frame->fmt->flags & FMT_HAS_ALPHA))
398 return;
399
400 cfg = readl(dev->regs + FIMC_REG_CIOCTRL);
401 cfg &= ~FIMC_REG_CIOCTRL_ALPHA_OUT_MASK;
402 cfg |= (frame->alpha << 4);
403 writel(cfg, dev->regs + FIMC_REG_CIOCTRL);
404}
405
406static void fimc_hw_set_in_dma_size(struct fimc_ctx *ctx)
407{
408 struct fimc_dev *dev = ctx->fimc_dev;
409 struct fimc_frame *frame = &ctx->s_frame;
410 u32 cfg_o = 0;
411 u32 cfg_r = 0;
412
413 if (FIMC_IO_LCDFIFO == ctx->out_path)
414 cfg_r |= FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN;
415
416 cfg_o |= (frame->f_height << 16) | frame->f_width;
417 cfg_r |= (frame->height << 16) | frame->width;
418
419 writel(cfg_o, dev->regs + FIMC_REG_ORGISIZE);
420 writel(cfg_r, dev->regs + FIMC_REG_CIREAL_ISIZE);
421}
422
423void fimc_hw_set_in_dma(struct fimc_ctx *ctx)
424{
425 struct fimc_dev *dev = ctx->fimc_dev;
426 struct fimc_frame *frame = &ctx->s_frame;
427 struct fimc_dma_offset *offset = &frame->dma_offset;
428 u32 cfg;
429
430 /* Set the pixel offsets. */
431 cfg = (offset->y_v << 16) | offset->y_h;
432 writel(cfg, dev->regs + FIMC_REG_CIIYOFF);
433
434 cfg = (offset->cb_v << 16) | offset->cb_h;
435 writel(cfg, dev->regs + FIMC_REG_CIICBOFF);
436
437 cfg = (offset->cr_v << 16) | offset->cr_h;
438 writel(cfg, dev->regs + FIMC_REG_CIICROFF);
439
440 /* Input original and real size. */
441 fimc_hw_set_in_dma_size(ctx);
442
443 /* Use DMA autoload only in FIFO mode. */
444 fimc_hw_en_autoload(dev, ctx->out_path == FIMC_IO_LCDFIFO);
445
446 /* Set the input DMA to process single frame only. */
447 cfg = readl(dev->regs + FIMC_REG_MSCTRL);
448 cfg &= ~(FIMC_REG_MSCTRL_INFORMAT_MASK
449 | FIMC_REG_MSCTRL_IN_BURST_COUNT_MASK
450 | FIMC_REG_MSCTRL_INPUT_MASK
451 | FIMC_REG_MSCTRL_C_INT_IN_MASK
452 | FIMC_REG_MSCTRL_2P_IN_ORDER_MASK
453 | FIMC_REG_MSCTRL_ORDER422_MASK);
454
455 cfg |= (FIMC_REG_MSCTRL_IN_BURST_COUNT(4)
456 | FIMC_REG_MSCTRL_INPUT_MEMORY
457 | FIMC_REG_MSCTRL_FIFO_CTRL_FULL);
458
459 switch (frame->fmt->color) {
460 case FIMC_FMT_RGB565...FIMC_FMT_RGB888:
461 cfg |= FIMC_REG_MSCTRL_INFORMAT_RGB;
462 break;
463 case FIMC_FMT_YCBCR420:
464 cfg |= FIMC_REG_MSCTRL_INFORMAT_YCBCR420;
465
466 if (frame->fmt->colplanes == 2)
467 cfg |= ctx->in_order_2p | FIMC_REG_MSCTRL_C_INT_IN_2PLANE;
468 else
469 cfg |= FIMC_REG_MSCTRL_C_INT_IN_3PLANE;
470
471 break;
472 case FIMC_FMT_YCBYCR422...FIMC_FMT_CRYCBY422:
473 if (frame->fmt->colplanes == 1) {
474 cfg |= ctx->in_order_1p
475 | FIMC_REG_MSCTRL_INFORMAT_YCBCR422_1P;
476 } else {
477 cfg |= FIMC_REG_MSCTRL_INFORMAT_YCBCR422;
478
479 if (frame->fmt->colplanes == 2)
480 cfg |= ctx->in_order_2p
481 | FIMC_REG_MSCTRL_C_INT_IN_2PLANE;
482 else
483 cfg |= FIMC_REG_MSCTRL_C_INT_IN_3PLANE;
484 }
485 break;
486 default:
487 break;
488 }
489
490 writel(cfg, dev->regs + FIMC_REG_MSCTRL);
491
492 /* Input/output DMA linear/tiled mode. */
493 cfg = readl(dev->regs + FIMC_REG_CIDMAPARAM);
494 cfg &= ~FIMC_REG_CIDMAPARAM_TILE_MASK;
495
496 if (tiled_fmt(ctx->s_frame.fmt))
497 cfg |= FIMC_REG_CIDMAPARAM_R_64X32;
498
499 if (tiled_fmt(ctx->d_frame.fmt))
500 cfg |= FIMC_REG_CIDMAPARAM_W_64X32;
501
502 writel(cfg, dev->regs + FIMC_REG_CIDMAPARAM);
503}
504
505
506void fimc_hw_set_input_path(struct fimc_ctx *ctx)
507{
508 struct fimc_dev *dev = ctx->fimc_dev;
509
510 u32 cfg = readl(dev->regs + FIMC_REG_MSCTRL);
511 cfg &= ~FIMC_REG_MSCTRL_INPUT_MASK;
512
513 if (ctx->in_path == FIMC_IO_DMA)
514 cfg |= FIMC_REG_MSCTRL_INPUT_MEMORY;
515 else
516 cfg |= FIMC_REG_MSCTRL_INPUT_EXTCAM;
517
518 writel(cfg, dev->regs + FIMC_REG_MSCTRL);
519}
520
521void fimc_hw_set_output_path(struct fimc_ctx *ctx)
522{
523 struct fimc_dev *dev = ctx->fimc_dev;
524
525 u32 cfg = readl(dev->regs + FIMC_REG_CISCCTRL);
526 cfg &= ~FIMC_REG_CISCCTRL_LCDPATHEN_FIFO;
527 if (ctx->out_path == FIMC_IO_LCDFIFO)
528 cfg |= FIMC_REG_CISCCTRL_LCDPATHEN_FIFO;
529 writel(cfg, dev->regs + FIMC_REG_CISCCTRL);
530}
531
532void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr)
533{
534 u32 cfg = readl(dev->regs + FIMC_REG_CIREAL_ISIZE);
535 cfg |= FIMC_REG_CIREAL_ISIZE_ADDR_CH_DIS;
536 writel(cfg, dev->regs + FIMC_REG_CIREAL_ISIZE);
537
538 writel(paddr->y, dev->regs + FIMC_REG_CIIYSA(0));
539 writel(paddr->cb, dev->regs + FIMC_REG_CIICBSA(0));
540 writel(paddr->cr, dev->regs + FIMC_REG_CIICRSA(0));
541
542 cfg &= ~FIMC_REG_CIREAL_ISIZE_ADDR_CH_DIS;
543 writel(cfg, dev->regs + FIMC_REG_CIREAL_ISIZE);
544}
545
546void fimc_hw_set_output_addr(struct fimc_dev *dev,
547 struct fimc_addr *paddr, int index)
548{
549 int i = (index == -1) ? 0 : index;
550 do {
551 writel(paddr->y, dev->regs + FIMC_REG_CIOYSA(i));
552 writel(paddr->cb, dev->regs + FIMC_REG_CIOCBSA(i));
553 writel(paddr->cr, dev->regs + FIMC_REG_CIOCRSA(i));
554 dbg("dst_buf[%d]: 0x%X, cb: 0x%X, cr: 0x%X",
555 i, paddr->y, paddr->cb, paddr->cr);
556 } while (index == -1 && ++i < FIMC_MAX_OUT_BUFS);
557}
558
559int fimc_hw_set_camera_polarity(struct fimc_dev *fimc,
560 struct fimc_source_info *cam)
561{
562 u32 cfg = readl(fimc->regs + FIMC_REG_CIGCTRL);
563
564 cfg &= ~(FIMC_REG_CIGCTRL_INVPOLPCLK | FIMC_REG_CIGCTRL_INVPOLVSYNC |
565 FIMC_REG_CIGCTRL_INVPOLHREF | FIMC_REG_CIGCTRL_INVPOLHSYNC |
566 FIMC_REG_CIGCTRL_INVPOLFIELD);
567
568 if (cam->flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
569 cfg |= FIMC_REG_CIGCTRL_INVPOLPCLK;
570
571 if (cam->flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
572 cfg |= FIMC_REG_CIGCTRL_INVPOLVSYNC;
573
574 if (cam->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
575 cfg |= FIMC_REG_CIGCTRL_INVPOLHREF;
576
577 if (cam->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
578 cfg |= FIMC_REG_CIGCTRL_INVPOLHSYNC;
579
580 if (cam->flags & V4L2_MBUS_FIELD_EVEN_LOW)
581 cfg |= FIMC_REG_CIGCTRL_INVPOLFIELD;
582
583 writel(cfg, fimc->regs + FIMC_REG_CIGCTRL);
584
585 return 0;
586}
587
588struct mbus_pixfmt_desc {
589 u32 pixelcode;
590 u32 cisrcfmt;
591 u16 bus_width;
592};
593
594static const struct mbus_pixfmt_desc pix_desc[] = {
595 { V4L2_MBUS_FMT_YUYV8_2X8, FIMC_REG_CISRCFMT_ORDER422_YCBYCR, 8 },
596 { V4L2_MBUS_FMT_YVYU8_2X8, FIMC_REG_CISRCFMT_ORDER422_YCRYCB, 8 },
597 { V4L2_MBUS_FMT_VYUY8_2X8, FIMC_REG_CISRCFMT_ORDER422_CRYCBY, 8 },
598 { V4L2_MBUS_FMT_UYVY8_2X8, FIMC_REG_CISRCFMT_ORDER422_CBYCRY, 8 },
599};
600
601int fimc_hw_set_camera_source(struct fimc_dev *fimc,
602 struct fimc_source_info *source)
603{
604 struct fimc_vid_cap *vc = &fimc->vid_cap;
605 struct fimc_frame *f = &vc->ctx->s_frame;
606 u32 bus_width, cfg = 0;
607 int i;
608
609 switch (source->fimc_bus_type) {
610 case FIMC_BUS_TYPE_ITU_601:
611 case FIMC_BUS_TYPE_ITU_656:
612 for (i = 0; i < ARRAY_SIZE(pix_desc); i++) {
613 if (vc->ci_fmt.code == pix_desc[i].pixelcode) {
614 cfg = pix_desc[i].cisrcfmt;
615 bus_width = pix_desc[i].bus_width;
616 break;
617 }
618 }
619
620 if (i == ARRAY_SIZE(pix_desc)) {
621 v4l2_err(&vc->vfd,
622 "Camera color format not supported: %d\n",
623 vc->ci_fmt.code);
624 return -EINVAL;
625 }
626
627 if (source->fimc_bus_type == FIMC_BUS_TYPE_ITU_601) {
628 if (bus_width == 8)
629 cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
630 else if (bus_width == 16)
631 cfg |= FIMC_REG_CISRCFMT_ITU601_16BIT;
632 } /* else defaults to ITU-R BT.656 8-bit */
633 break;
634 case FIMC_BUS_TYPE_MIPI_CSI2:
635 if (fimc_fmt_is_user_defined(f->fmt->color))
636 cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
637 break;
638 default:
639 case FIMC_BUS_TYPE_ISP_WRITEBACK:
640 /* Anything to do here ? */
641 break;
642 }
643
644 cfg |= (f->o_width << 16) | f->o_height;
645 writel(cfg, fimc->regs + FIMC_REG_CISRCFMT);
646 return 0;
647}
648
649void fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f)
650{
651 u32 hoff2, voff2;
652
653 u32 cfg = readl(fimc->regs + FIMC_REG_CIWDOFST);
654
655 cfg &= ~(FIMC_REG_CIWDOFST_HOROFF_MASK | FIMC_REG_CIWDOFST_VEROFF_MASK);
656 cfg |= FIMC_REG_CIWDOFST_OFF_EN |
657 (f->offs_h << 16) | f->offs_v;
658
659 writel(cfg, fimc->regs + FIMC_REG_CIWDOFST);
660
661 /* See CIWDOFSTn register description in the datasheet for details. */
662 hoff2 = f->o_width - f->width - f->offs_h;
663 voff2 = f->o_height - f->height - f->offs_v;
664 cfg = (hoff2 << 16) | voff2;
665 writel(cfg, fimc->regs + FIMC_REG_CIWDOFST2);
666}
667
668int fimc_hw_set_camera_type(struct fimc_dev *fimc,
669 struct fimc_source_info *source)
670{
671 struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
672 u32 csis_data_alignment = 32;
673 u32 cfg, tmp;
674
675 cfg = readl(fimc->regs + FIMC_REG_CIGCTRL);
676
677 /* Select ITU B interface, disable Writeback path and test pattern. */
678 cfg &= ~(FIMC_REG_CIGCTRL_TESTPAT_MASK | FIMC_REG_CIGCTRL_SELCAM_ITU_A |
679 FIMC_REG_CIGCTRL_SELCAM_MIPI | FIMC_REG_CIGCTRL_CAMIF_SELWB |
680 FIMC_REG_CIGCTRL_SELCAM_MIPI_A | FIMC_REG_CIGCTRL_CAM_JPEG |
681 FIMC_REG_CIGCTRL_SELWB_A);
682
683 switch (source->fimc_bus_type) {
684 case FIMC_BUS_TYPE_MIPI_CSI2:
685 cfg |= FIMC_REG_CIGCTRL_SELCAM_MIPI;
686
687 if (source->mux_id == 0)
688 cfg |= FIMC_REG_CIGCTRL_SELCAM_MIPI_A;
689
690 /* TODO: add remaining supported formats. */
691 switch (vid_cap->ci_fmt.code) {
692 case V4L2_MBUS_FMT_VYUY8_2X8:
693 tmp = FIMC_REG_CSIIMGFMT_YCBCR422_8BIT;
694 break;
695 case V4L2_MBUS_FMT_JPEG_1X8:
696 case V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8:
697 tmp = FIMC_REG_CSIIMGFMT_USER(1);
698 cfg |= FIMC_REG_CIGCTRL_CAM_JPEG;
699 break;
700 default:
701 v4l2_err(&vid_cap->vfd,
702 "Not supported camera pixel format: %#x\n",
703 vid_cap->ci_fmt.code);
704 return -EINVAL;
705 }
706 tmp |= (csis_data_alignment == 32) << 8;
707
708 writel(tmp, fimc->regs + FIMC_REG_CSIIMGFMT);
709 break;
710 case FIMC_BUS_TYPE_ITU_601...FIMC_BUS_TYPE_ITU_656:
711 if (source->mux_id == 0) /* ITU-A, ITU-B: 0, 1 */
712 cfg |= FIMC_REG_CIGCTRL_SELCAM_ITU_A;
713 break;
714 case FIMC_BUS_TYPE_LCD_WRITEBACK_A:
715 cfg |= FIMC_REG_CIGCTRL_CAMIF_SELWB;
716 /* fall through */
717 case FIMC_BUS_TYPE_ISP_WRITEBACK:
718 if (fimc->variant->has_isp_wb)
719 cfg |= FIMC_REG_CIGCTRL_CAMIF_SELWB;
720 else
721 WARN_ONCE(1, "ISP Writeback input is not supported\n");
722 break;
723 default:
724 v4l2_err(&vid_cap->vfd, "Invalid FIMC bus type selected: %d\n",
725 source->fimc_bus_type);
726 return -EINVAL;
727 }
728 writel(cfg, fimc->regs + FIMC_REG_CIGCTRL);
729
730 return 0;
731}
732
733void fimc_hw_clear_irq(struct fimc_dev *dev)
734{
735 u32 cfg = readl(dev->regs + FIMC_REG_CIGCTRL);
736 cfg |= FIMC_REG_CIGCTRL_IRQ_CLR;
737 writel(cfg, dev->regs + FIMC_REG_CIGCTRL);
738}
739
740void fimc_hw_enable_scaler(struct fimc_dev *dev, bool on)
741{
742 u32 cfg = readl(dev->regs + FIMC_REG_CISCCTRL);
743 if (on)
744 cfg |= FIMC_REG_CISCCTRL_SCALERSTART;
745 else
746 cfg &= ~FIMC_REG_CISCCTRL_SCALERSTART;
747 writel(cfg, dev->regs + FIMC_REG_CISCCTRL);
748}
749
750void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on)
751{
752 u32 cfg = readl(dev->regs + FIMC_REG_MSCTRL);
753 if (on)
754 cfg |= FIMC_REG_MSCTRL_ENVID;
755 else
756 cfg &= ~FIMC_REG_MSCTRL_ENVID;
757 writel(cfg, dev->regs + FIMC_REG_MSCTRL);
758}
759
760/* Return an index to the buffer actually being written. */
761s32 fimc_hw_get_frame_index(struct fimc_dev *dev)
762{
763 s32 reg;
764
765 if (dev->drv_data->cistatus2) {
766 reg = readl(dev->regs + FIMC_REG_CISTATUS2) & 0x3f;
767 return reg - 1;
768 }
769
770 reg = readl(dev->regs + FIMC_REG_CISTATUS);
771
772 return (reg & FIMC_REG_CISTATUS_FRAMECNT_MASK) >>
773 FIMC_REG_CISTATUS_FRAMECNT_SHIFT;
774}
775
776/* Return an index to the buffer being written previously. */
777s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev)
778{
779 s32 reg;
780
781 if (!dev->drv_data->cistatus2)
782 return -1;
783
784 reg = readl(dev->regs + FIMC_REG_CISTATUS2);
785 return ((reg >> 7) & 0x3f) - 1;
786}
787
788/* Locking: the caller holds fimc->slock */
789void fimc_activate_capture(struct fimc_ctx *ctx)
790{
791 fimc_hw_enable_scaler(ctx->fimc_dev, ctx->scaler.enabled);
792 fimc_hw_enable_capture(ctx);
793}
794
795void fimc_deactivate_capture(struct fimc_dev *fimc)
796{
797 fimc_hw_en_lastirq(fimc, true);
798 fimc_hw_disable_capture(fimc);
799 fimc_hw_enable_scaler(fimc, false);
800 fimc_hw_en_lastirq(fimc, false);
801}
802
803int fimc_hw_camblk_cfg_writeback(struct fimc_dev *fimc)
804{
805 struct regmap *map = fimc->sysreg;
806 unsigned int mask, val, camblk_cfg;
807 int ret;
808
809 if (map == NULL)
810 return 0;
811
812 ret = regmap_read(map, SYSREG_CAMBLK, &camblk_cfg);
813 if (ret < 0 || ((camblk_cfg & 0x00700000) >> 20 != 0x3))
814 return ret;
815
816 if (!WARN(fimc->id >= 3, "not supported id: %d\n", fimc->id))
817 val = 0x1 << (fimc->id + 20);
818 else
819 val = 0;
820
821 mask = SYSREG_CAMBLK_FIFORST_ISP | SYSREG_CAMBLK_ISPWB_FULL_EN;
822 ret = regmap_update_bits(map, SYSREG_CAMBLK, mask, val);
823 if (ret < 0)
824 return ret;
825
826 usleep_range(1000, 2000);
827
828 val |= SYSREG_CAMBLK_FIFORST_ISP;
829 ret = regmap_update_bits(map, SYSREG_CAMBLK, mask, val);
830 if (ret < 0)
831 return ret;
832
833 mask = SYSREG_ISPBLK_FIFORST_CAM_BLK;
834 ret = regmap_update_bits(map, SYSREG_ISPBLK, mask, ~mask);
835 if (ret < 0)
836 return ret;
837
838 usleep_range(1000, 2000);
839
840 return regmap_update_bits(map, SYSREG_ISPBLK, mask, mask);
841}
diff --git a/drivers/media/platform/exynos4-is/fimc-reg.h b/drivers/media/platform/exynos4-is/fimc-reg.h
new file mode 100644
index 000000000000..6c97798c75a5
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-reg.h
@@ -0,0 +1,338 @@
1/*
2 * Samsung camera host interface (FIMC) registers definition
3 *
4 * Copyright (C) 2010 - 2012 Samsung Electronics Co., Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#ifndef FIMC_REG_H_
12#define FIMC_REG_H_
13
14#include "fimc-core.h"
15
16/* Input source format */
17#define FIMC_REG_CISRCFMT 0x00
18#define FIMC_REG_CISRCFMT_ITU601_8BIT (1 << 31)
19#define FIMC_REG_CISRCFMT_ITU601_16BIT (1 << 29)
20#define FIMC_REG_CISRCFMT_ORDER422_YCBYCR (0 << 14)
21#define FIMC_REG_CISRCFMT_ORDER422_YCRYCB (1 << 14)
22#define FIMC_REG_CISRCFMT_ORDER422_CBYCRY (2 << 14)
23#define FIMC_REG_CISRCFMT_ORDER422_CRYCBY (3 << 14)
24
25/* Window offset */
26#define FIMC_REG_CIWDOFST 0x04
27#define FIMC_REG_CIWDOFST_OFF_EN (1 << 31)
28#define FIMC_REG_CIWDOFST_CLROVFIY (1 << 30)
29#define FIMC_REG_CIWDOFST_CLROVRLB (1 << 29)
30#define FIMC_REG_CIWDOFST_HOROFF_MASK (0x7ff << 16)
31#define FIMC_REG_CIWDOFST_CLROVFICB (1 << 15)
32#define FIMC_REG_CIWDOFST_CLROVFICR (1 << 14)
33#define FIMC_REG_CIWDOFST_VEROFF_MASK (0xfff << 0)
34
35/* Global control */
36#define FIMC_REG_CIGCTRL 0x08
37#define FIMC_REG_CIGCTRL_SWRST (1 << 31)
38#define FIMC_REG_CIGCTRL_CAMRST_A (1 << 30)
39#define FIMC_REG_CIGCTRL_SELCAM_ITU_A (1 << 29)
40#define FIMC_REG_CIGCTRL_TESTPAT_NORMAL (0 << 27)
41#define FIMC_REG_CIGCTRL_TESTPAT_COLOR_BAR (1 << 27)
42#define FIMC_REG_CIGCTRL_TESTPAT_HOR_INC (2 << 27)
43#define FIMC_REG_CIGCTRL_TESTPAT_VER_INC (3 << 27)
44#define FIMC_REG_CIGCTRL_TESTPAT_MASK (3 << 27)
45#define FIMC_REG_CIGCTRL_TESTPAT_SHIFT 27
46#define FIMC_REG_CIGCTRL_INVPOLPCLK (1 << 26)
47#define FIMC_REG_CIGCTRL_INVPOLVSYNC (1 << 25)
48#define FIMC_REG_CIGCTRL_INVPOLHREF (1 << 24)
49#define FIMC_REG_CIGCTRL_IRQ_OVFEN (1 << 22)
50#define FIMC_REG_CIGCTRL_HREF_MASK (1 << 21)
51#define FIMC_REG_CIGCTRL_IRQ_LEVEL (1 << 20)
52#define FIMC_REG_CIGCTRL_IRQ_CLR (1 << 19)
53#define FIMC_REG_CIGCTRL_IRQ_ENABLE (1 << 16)
54#define FIMC_REG_CIGCTRL_SHDW_DISABLE (1 << 12)
55/* 0 - selects Writeback A (LCD), 1 - selects Writeback B (LCD/ISP) */
56#define FIMC_REG_CIGCTRL_SELWB_A (1 << 10)
57#define FIMC_REG_CIGCTRL_CAM_JPEG (1 << 8)
58#define FIMC_REG_CIGCTRL_SELCAM_MIPI_A (1 << 7)
59#define FIMC_REG_CIGCTRL_CAMIF_SELWB (1 << 6)
60/* 0 - ITU601; 1 - ITU709 */
61#define FIMC_REG_CIGCTRL_CSC_ITU601_709 (1 << 5)
62#define FIMC_REG_CIGCTRL_INVPOLHSYNC (1 << 4)
63#define FIMC_REG_CIGCTRL_SELCAM_MIPI (1 << 3)
64#define FIMC_REG_CIGCTRL_INVPOLFIELD (1 << 1)
65#define FIMC_REG_CIGCTRL_INTERLACE (1 << 0)
66
67/* Window offset 2 */
68#define FIMC_REG_CIWDOFST2 0x14
69#define FIMC_REG_CIWDOFST2_HOROFF_MASK (0xfff << 16)
70#define FIMC_REG_CIWDOFST2_VEROFF_MASK (0xfff << 0)
71
72/* Output DMA Y/Cb/Cr plane start addresses */
73#define FIMC_REG_CIOYSA(n) (0x18 + (n) * 4)
74#define FIMC_REG_CIOCBSA(n) (0x28 + (n) * 4)
75#define FIMC_REG_CIOCRSA(n) (0x38 + (n) * 4)
76
77/* Target image format */
78#define FIMC_REG_CITRGFMT 0x48
79#define FIMC_REG_CITRGFMT_INROT90 (1 << 31)
80#define FIMC_REG_CITRGFMT_YCBCR420 (0 << 29)
81#define FIMC_REG_CITRGFMT_YCBCR422 (1 << 29)
82#define FIMC_REG_CITRGFMT_YCBCR422_1P (2 << 29)
83#define FIMC_REG_CITRGFMT_RGB (3 << 29)
84#define FIMC_REG_CITRGFMT_FMT_MASK (3 << 29)
85#define FIMC_REG_CITRGFMT_HSIZE_MASK (0xfff << 16)
86#define FIMC_REG_CITRGFMT_FLIP_SHIFT 14
87#define FIMC_REG_CITRGFMT_FLIP_NORMAL (0 << 14)
88#define FIMC_REG_CITRGFMT_FLIP_X_MIRROR (1 << 14)
89#define FIMC_REG_CITRGFMT_FLIP_Y_MIRROR (2 << 14)
90#define FIMC_REG_CITRGFMT_FLIP_180 (3 << 14)
91#define FIMC_REG_CITRGFMT_FLIP_MASK (3 << 14)
92#define FIMC_REG_CITRGFMT_OUTROT90 (1 << 13)
93#define FIMC_REG_CITRGFMT_VSIZE_MASK (0xfff << 0)
94
95/* Output DMA control */
96#define FIMC_REG_CIOCTRL 0x4c
97#define FIMC_REG_CIOCTRL_ORDER422_MASK (3 << 0)
98#define FIMC_REG_CIOCTRL_ORDER422_YCBYCR (0 << 0)
99#define FIMC_REG_CIOCTRL_ORDER422_YCRYCB (1 << 0)
100#define FIMC_REG_CIOCTRL_ORDER422_CBYCRY (2 << 0)
101#define FIMC_REG_CIOCTRL_ORDER422_CRYCBY (3 << 0)
102#define FIMC_REG_CIOCTRL_LASTIRQ_ENABLE (1 << 2)
103#define FIMC_REG_CIOCTRL_YCBCR_3PLANE (0 << 3)
104#define FIMC_REG_CIOCTRL_YCBCR_2PLANE (1 << 3)
105#define FIMC_REG_CIOCTRL_YCBCR_PLANE_MASK (1 << 3)
106#define FIMC_REG_CIOCTRL_ALPHA_OUT_MASK (0xff << 4)
107#define FIMC_REG_CIOCTRL_RGB16FMT_MASK (3 << 16)
108#define FIMC_REG_CIOCTRL_RGB565 (0 << 16)
109#define FIMC_REG_CIOCTRL_ARGB1555 (1 << 16)
110#define FIMC_REG_CIOCTRL_ARGB4444 (2 << 16)
111#define FIMC_REG_CIOCTRL_ORDER2P_SHIFT 24
112#define FIMC_REG_CIOCTRL_ORDER2P_MASK (3 << 24)
113#define FIMC_REG_CIOCTRL_ORDER422_2P_LSB_CRCB (0 << 24)
114
115/* Pre-scaler control 1 */
116#define FIMC_REG_CISCPRERATIO 0x50
117
118#define FIMC_REG_CISCPREDST 0x54
119
120/* Main scaler control */
121#define FIMC_REG_CISCCTRL 0x58
122#define FIMC_REG_CISCCTRL_SCALERBYPASS (1 << 31)
123#define FIMC_REG_CISCCTRL_SCALEUP_H (1 << 30)
124#define FIMC_REG_CISCCTRL_SCALEUP_V (1 << 29)
125#define FIMC_REG_CISCCTRL_CSCR2Y_WIDE (1 << 28)
126#define FIMC_REG_CISCCTRL_CSCY2R_WIDE (1 << 27)
127#define FIMC_REG_CISCCTRL_LCDPATHEN_FIFO (1 << 26)
128#define FIMC_REG_CISCCTRL_INTERLACE (1 << 25)
129#define FIMC_REG_CISCCTRL_SCALERSTART (1 << 15)
130#define FIMC_REG_CISCCTRL_INRGB_FMT_RGB565 (0 << 13)
131#define FIMC_REG_CISCCTRL_INRGB_FMT_RGB666 (1 << 13)
132#define FIMC_REG_CISCCTRL_INRGB_FMT_RGB888 (2 << 13)
133#define FIMC_REG_CISCCTRL_INRGB_FMT_MASK (3 << 13)
134#define FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB565 (0 << 11)
135#define FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB666 (1 << 11)
136#define FIMC_REG_CISCCTRL_OUTRGB_FMT_RGB888 (2 << 11)
137#define FIMC_REG_CISCCTRL_OUTRGB_FMT_MASK (3 << 11)
138#define FIMC_REG_CISCCTRL_RGB_EXT (1 << 10)
139#define FIMC_REG_CISCCTRL_ONE2ONE (1 << 9)
140#define FIMC_REG_CISCCTRL_MHRATIO(x) ((x) << 16)
141#define FIMC_REG_CISCCTRL_MVRATIO(x) ((x) << 0)
142#define FIMC_REG_CISCCTRL_MHRATIO_MASK (0x1ff << 16)
143#define FIMC_REG_CISCCTRL_MVRATIO_MASK (0x1ff << 0)
144#define FIMC_REG_CISCCTRL_MHRATIO_EXT(x) (((x) >> 6) << 16)
145#define FIMC_REG_CISCCTRL_MVRATIO_EXT(x) (((x) >> 6) << 0)
146
147/* Target area */
148#define FIMC_REG_CITAREA 0x5c
149#define FIMC_REG_CITAREA_MASK 0x0fffffff
150
151/* General status */
152#define FIMC_REG_CISTATUS 0x64
153#define FIMC_REG_CISTATUS_OVFIY (1 << 31)
154#define FIMC_REG_CISTATUS_OVFICB (1 << 30)
155#define FIMC_REG_CISTATUS_OVFICR (1 << 29)
156#define FIMC_REG_CISTATUS_VSYNC (1 << 28)
157#define FIMC_REG_CISTATUS_FRAMECNT_MASK (3 << 26)
158#define FIMC_REG_CISTATUS_FRAMECNT_SHIFT 26
159#define FIMC_REG_CISTATUS_WINOFF_EN (1 << 25)
160#define FIMC_REG_CISTATUS_IMGCPT_EN (1 << 22)
161#define FIMC_REG_CISTATUS_IMGCPT_SCEN (1 << 21)
162#define FIMC_REG_CISTATUS_VSYNC_A (1 << 20)
163#define FIMC_REG_CISTATUS_VSYNC_B (1 << 19)
164#define FIMC_REG_CISTATUS_OVRLB (1 << 18)
165#define FIMC_REG_CISTATUS_FRAME_END (1 << 17)
166#define FIMC_REG_CISTATUS_LASTCAPT_END (1 << 16)
167#define FIMC_REG_CISTATUS_VVALID_A (1 << 15)
168#define FIMC_REG_CISTATUS_VVALID_B (1 << 14)
169
170/* Indexes to the last and the currently processed buffer. */
171#define FIMC_REG_CISTATUS2 0x68
172
173/* Image capture control */
174#define FIMC_REG_CIIMGCPT 0xc0
175#define FIMC_REG_CIIMGCPT_IMGCPTEN (1 << 31)
176#define FIMC_REG_CIIMGCPT_IMGCPTEN_SC (1 << 30)
177#define FIMC_REG_CIIMGCPT_CPT_FREN_ENABLE (1 << 25)
178#define FIMC_REG_CIIMGCPT_CPT_FRMOD_CNT (1 << 18)
179
180/* Frame capture sequence */
181#define FIMC_REG_CICPTSEQ 0xc4
182
183/* Image effect */
184#define FIMC_REG_CIIMGEFF 0xd0
185#define FIMC_REG_CIIMGEFF_IE_ENABLE (1 << 30)
186#define FIMC_REG_CIIMGEFF_IE_SC_BEFORE (0 << 29)
187#define FIMC_REG_CIIMGEFF_IE_SC_AFTER (1 << 29)
188#define FIMC_REG_CIIMGEFF_FIN_BYPASS (0 << 26)
189#define FIMC_REG_CIIMGEFF_FIN_ARBITRARY (1 << 26)
190#define FIMC_REG_CIIMGEFF_FIN_NEGATIVE (2 << 26)
191#define FIMC_REG_CIIMGEFF_FIN_ARTFREEZE (3 << 26)
192#define FIMC_REG_CIIMGEFF_FIN_EMBOSSING (4 << 26)
193#define FIMC_REG_CIIMGEFF_FIN_SILHOUETTE (5 << 26)
194#define FIMC_REG_CIIMGEFF_FIN_MASK (7 << 26)
195#define FIMC_REG_CIIMGEFF_PAT_CBCR_MASK ((0xff << 13) | 0xff)
196
197/* Input DMA Y/Cb/Cr plane start address 0/1 */
198#define FIMC_REG_CIIYSA(n) (0xd4 + (n) * 0x70)
199#define FIMC_REG_CIICBSA(n) (0xd8 + (n) * 0x70)
200#define FIMC_REG_CIICRSA(n) (0xdc + (n) * 0x70)
201
202/* Real input DMA image size */
203#define FIMC_REG_CIREAL_ISIZE 0xf8
204#define FIMC_REG_CIREAL_ISIZE_AUTOLOAD_EN (1 << 31)
205#define FIMC_REG_CIREAL_ISIZE_ADDR_CH_DIS (1 << 30)
206
207/* Input DMA control */
208#define FIMC_REG_MSCTRL 0xfc
209#define FIMC_REG_MSCTRL_IN_BURST_COUNT_MASK (0xf << 24)
210#define FIMC_REG_MSCTRL_2P_IN_ORDER_MASK (3 << 16)
211#define FIMC_REG_MSCTRL_2P_IN_ORDER_SHIFT 16
212#define FIMC_REG_MSCTRL_C_INT_IN_3PLANE (0 << 15)
213#define FIMC_REG_MSCTRL_C_INT_IN_2PLANE (1 << 15)
214#define FIMC_REG_MSCTRL_C_INT_IN_MASK (1 << 15)
215#define FIMC_REG_MSCTRL_FLIP_SHIFT 13
216#define FIMC_REG_MSCTRL_FLIP_MASK (3 << 13)
217#define FIMC_REG_MSCTRL_FLIP_NORMAL (0 << 13)
218#define FIMC_REG_MSCTRL_FLIP_X_MIRROR (1 << 13)
219#define FIMC_REG_MSCTRL_FLIP_Y_MIRROR (2 << 13)
220#define FIMC_REG_MSCTRL_FLIP_180 (3 << 13)
221#define FIMC_REG_MSCTRL_FIFO_CTRL_FULL (1 << 12)
222#define FIMC_REG_MSCTRL_ORDER422_SHIFT 4
223#define FIMC_REG_MSCTRL_ORDER422_CRYCBY (0 << 4)
224#define FIMC_REG_MSCTRL_ORDER422_YCRYCB (1 << 4)
225#define FIMC_REG_MSCTRL_ORDER422_CBYCRY (2 << 4)
226#define FIMC_REG_MSCTRL_ORDER422_YCBYCR (3 << 4)
227#define FIMC_REG_MSCTRL_ORDER422_MASK (3 << 4)
228#define FIMC_REG_MSCTRL_INPUT_EXTCAM (0 << 3)
229#define FIMC_REG_MSCTRL_INPUT_MEMORY (1 << 3)
230#define FIMC_REG_MSCTRL_INPUT_MASK (1 << 3)
231#define FIMC_REG_MSCTRL_INFORMAT_YCBCR420 (0 << 1)
232#define FIMC_REG_MSCTRL_INFORMAT_YCBCR422 (1 << 1)
233#define FIMC_REG_MSCTRL_INFORMAT_YCBCR422_1P (2 << 1)
234#define FIMC_REG_MSCTRL_INFORMAT_RGB (3 << 1)
235#define FIMC_REG_MSCTRL_INFORMAT_MASK (3 << 1)
236#define FIMC_REG_MSCTRL_ENVID (1 << 0)
237#define FIMC_REG_MSCTRL_IN_BURST_COUNT(x) ((x) << 24)
238
239/* Output DMA Y/Cb/Cr offset */
240#define FIMC_REG_CIOYOFF 0x168
241#define FIMC_REG_CIOCBOFF 0x16c
242#define FIMC_REG_CIOCROFF 0x170
243
244/* Input DMA Y/Cb/Cr offset */
245#define FIMC_REG_CIIYOFF 0x174
246#define FIMC_REG_CIICBOFF 0x178
247#define FIMC_REG_CIICROFF 0x17c
248
249/* Input DMA original image size */
250#define FIMC_REG_ORGISIZE 0x180
251
252/* Output DMA original image size */
253#define FIMC_REG_ORGOSIZE 0x184
254
255/* Real output DMA image size (extension register) */
256#define FIMC_REG_CIEXTEN 0x188
257#define FIMC_REG_CIEXTEN_MHRATIO_EXT(x) (((x) & 0x3f) << 10)
258#define FIMC_REG_CIEXTEN_MVRATIO_EXT(x) ((x) & 0x3f)
259#define FIMC_REG_CIEXTEN_MHRATIO_EXT_MASK (0x3f << 10)
260#define FIMC_REG_CIEXTEN_MVRATIO_EXT_MASK 0x3f
261
262#define FIMC_REG_CIDMAPARAM 0x18c
263#define FIMC_REG_CIDMAPARAM_R_LINEAR (0 << 29)
264#define FIMC_REG_CIDMAPARAM_R_64X32 (3 << 29)
265#define FIMC_REG_CIDMAPARAM_W_LINEAR (0 << 13)
266#define FIMC_REG_CIDMAPARAM_W_64X32 (3 << 13)
267#define FIMC_REG_CIDMAPARAM_TILE_MASK ((3 << 29) | (3 << 13))
268
269/* MIPI CSI image format */
270#define FIMC_REG_CSIIMGFMT 0x194
271#define FIMC_REG_CSIIMGFMT_YCBCR422_8BIT 0x1e
272#define FIMC_REG_CSIIMGFMT_RAW8 0x2a
273#define FIMC_REG_CSIIMGFMT_RAW10 0x2b
274#define FIMC_REG_CSIIMGFMT_RAW12 0x2c
275/* User defined formats. x = 0...16. */
276#define FIMC_REG_CSIIMGFMT_USER(x) (0x30 + x - 1)
277
278/* Output frame buffer sequence mask */
279#define FIMC_REG_CIFCNTSEQ 0x1fc
280
281/* SYSREG ISP Writeback register address offsets */
282#define SYSREG_ISPBLK 0x020c
283#define SYSREG_ISPBLK_FIFORST_CAM_BLK (1 << 7)
284
285#define SYSREG_CAMBLK 0x0218
286#define SYSREG_CAMBLK_FIFORST_ISP (1 << 15)
287#define SYSREG_CAMBLK_ISPWB_FULL_EN (7 << 20)
288
289/*
290 * Function declarations
291 */
292void fimc_hw_reset(struct fimc_dev *fimc);
293void fimc_hw_set_rotation(struct fimc_ctx *ctx);
294void fimc_hw_set_target_format(struct fimc_ctx *ctx);
295void fimc_hw_set_out_dma(struct fimc_ctx *ctx);
296void fimc_hw_en_lastirq(struct fimc_dev *fimc, int enable);
297void fimc_hw_en_irq(struct fimc_dev *fimc, int enable);
298void fimc_hw_set_prescaler(struct fimc_ctx *ctx);
299void fimc_hw_set_mainscaler(struct fimc_ctx *ctx);
300void fimc_hw_enable_capture(struct fimc_ctx *ctx);
301void fimc_hw_set_effect(struct fimc_ctx *ctx);
302void fimc_hw_set_rgb_alpha(struct fimc_ctx *ctx);
303void fimc_hw_set_in_dma(struct fimc_ctx *ctx);
304void fimc_hw_set_input_path(struct fimc_ctx *ctx);
305void fimc_hw_set_output_path(struct fimc_ctx *ctx);
306void fimc_hw_set_input_addr(struct fimc_dev *fimc, struct fimc_addr *paddr);
307void fimc_hw_set_output_addr(struct fimc_dev *fimc, struct fimc_addr *paddr,
308 int index);
309int fimc_hw_set_camera_source(struct fimc_dev *fimc,
310 struct fimc_source_info *cam);
311void fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f);
312int fimc_hw_set_camera_polarity(struct fimc_dev *fimc,
313 struct fimc_source_info *cam);
314int fimc_hw_set_camera_type(struct fimc_dev *fimc,
315 struct fimc_source_info *cam);
316void fimc_hw_clear_irq(struct fimc_dev *dev);
317void fimc_hw_enable_scaler(struct fimc_dev *dev, bool on);
318void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on);
319void fimc_hw_disable_capture(struct fimc_dev *dev);
320s32 fimc_hw_get_frame_index(struct fimc_dev *dev);
321s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev);
322int fimc_hw_camblk_cfg_writeback(struct fimc_dev *fimc);
323void fimc_activate_capture(struct fimc_ctx *ctx);
324void fimc_deactivate_capture(struct fimc_dev *fimc);
325
326/**
327 * fimc_hw_set_dma_seq - configure output DMA buffer sequence
328 * @mask: bitmask for the DMA output buffer registers, set to 0 to skip buffer
329 * This function masks output DMA ring buffers, it allows to select which of
330 * the 32 available output buffer address registers will be used by the DMA
331 * engine.
332 */
333static inline void fimc_hw_set_dma_seq(struct fimc_dev *dev, u32 mask)
334{
335 writel(mask, dev->regs + FIMC_REG_CIFCNTSEQ);
336}
337
338#endif /* FIMC_REG_H_ */
diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
new file mode 100644
index 000000000000..15ef8f28239b
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/media-dev.c
@@ -0,0 +1,1511 @@
1/*
2 * S5P/EXYNOS4 SoC series camera host interface media device driver
3 *
4 * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd.
5 * Sylwester Nawrocki <s.nawrocki@samsung.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 as published
9 * by the Free Software Foundation, either version 2 of the License,
10 * or (at your option) any later version.
11 */
12
13#include <linux/bug.h>
14#include <linux/device.h>
15#include <linux/errno.h>
16#include <linux/i2c.h>
17#include <linux/kernel.h>
18#include <linux/list.h>
19#include <linux/module.h>
20#include <linux/of.h>
21#include <linux/of_platform.h>
22#include <linux/of_device.h>
23#include <linux/of_i2c.h>
24#include <linux/platform_device.h>
25#include <linux/pm_runtime.h>
26#include <linux/types.h>
27#include <linux/slab.h>
28#include <media/v4l2-ctrls.h>
29#include <media/v4l2-of.h>
30#include <media/media-device.h>
31#include <media/s5p_fimc.h>
32
33#include "media-dev.h"
34#include "fimc-core.h"
35#include "fimc-is.h"
36#include "fimc-lite.h"
37#include "mipi-csis.h"
38
39static int __fimc_md_set_camclk(struct fimc_md *fmd,
40 struct fimc_source_info *si,
41 bool on);
42/**
43 * fimc_pipeline_prepare - update pipeline information with subdevice pointers
44 * @me: media entity terminating the pipeline
45 *
46 * Caller holds the graph mutex.
47 */
48static void fimc_pipeline_prepare(struct fimc_pipeline *p,
49 struct media_entity *me)
50{
51 struct v4l2_subdev *sd;
52 int i;
53
54 for (i = 0; i < IDX_MAX; i++)
55 p->subdevs[i] = NULL;
56
57 while (1) {
58 struct media_pad *pad = NULL;
59
60 /* Find remote source pad */
61 for (i = 0; i < me->num_pads; i++) {
62 struct media_pad *spad = &me->pads[i];
63 if (!(spad->flags & MEDIA_PAD_FL_SINK))
64 continue;
65 pad = media_entity_remote_source(spad);
66 if (pad)
67 break;
68 }
69
70 if (pad == NULL ||
71 media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
72 break;
73 sd = media_entity_to_v4l2_subdev(pad->entity);
74
75 switch (sd->grp_id) {
76 case GRP_ID_FIMC_IS_SENSOR:
77 case GRP_ID_SENSOR:
78 p->subdevs[IDX_SENSOR] = sd;
79 break;
80 case GRP_ID_CSIS:
81 p->subdevs[IDX_CSIS] = sd;
82 break;
83 case GRP_ID_FLITE:
84 p->subdevs[IDX_FLITE] = sd;
85 break;
86 case GRP_ID_FIMC:
87 /* No need to control FIMC subdev through subdev ops */
88 break;
89 case GRP_ID_FIMC_IS:
90 p->subdevs[IDX_IS_ISP] = sd;
91 break;
92 default:
93 break;
94 }
95 me = &sd->entity;
96 if (me->num_pads == 1)
97 break;
98 }
99}
100
101/**
102 * __subdev_set_power - change power state of a single subdev
103 * @sd: subdevice to change power state for
104 * @on: 1 to enable power or 0 to disable
105 *
106 * Return result of s_power subdev operation or -ENXIO if sd argument
107 * is NULL. Return 0 if the subdevice does not implement s_power.
108 */
109static int __subdev_set_power(struct v4l2_subdev *sd, int on)
110{
111 int *use_count;
112 int ret;
113
114 if (sd == NULL)
115 return -ENXIO;
116
117 use_count = &sd->entity.use_count;
118 if (on && (*use_count)++ > 0)
119 return 0;
120 else if (!on && (*use_count == 0 || --(*use_count) > 0))
121 return 0;
122 ret = v4l2_subdev_call(sd, core, s_power, on);
123
124 return ret != -ENOIOCTLCMD ? ret : 0;
125}
126
127/**
128 * fimc_pipeline_s_power - change power state of all pipeline subdevs
129 * @fimc: fimc device terminating the pipeline
130 * @state: true to power on, false to power off
131 *
132 * Needs to be called with the graph mutex held.
133 */
134static int fimc_pipeline_s_power(struct fimc_pipeline *p, bool on)
135{
136 static const u8 seq[2][IDX_MAX - 1] = {
137 { IDX_IS_ISP, IDX_SENSOR, IDX_CSIS, IDX_FLITE },
138 { IDX_CSIS, IDX_FLITE, IDX_SENSOR, IDX_IS_ISP },
139 };
140 int i, ret = 0;
141
142 if (p->subdevs[IDX_SENSOR] == NULL)
143 return -ENXIO;
144
145 for (i = 0; i < IDX_MAX - 1; i++) {
146 unsigned int idx = seq[on][i];
147
148 ret = __subdev_set_power(p->subdevs[idx], on);
149
150
151 if (ret < 0 && ret != -ENXIO)
152 goto error;
153 }
154 return 0;
155error:
156 for (; i >= 0; i--) {
157 unsigned int idx = seq[on][i];
158 __subdev_set_power(p->subdevs[idx], !on);
159 }
160 return ret;
161}
162
163/**
164 * __fimc_pipeline_open - update the pipeline information, enable power
165 * of all pipeline subdevs and the sensor clock
166 * @me: media entity to start graph walk with
167 * @prepare: true to walk the current pipeline and acquire all subdevs
168 *
169 * Called with the graph mutex held.
170 */
171static int __fimc_pipeline_open(struct fimc_pipeline *p,
172 struct media_entity *me, bool prepare)
173{
174 struct fimc_md *fmd = entity_to_fimc_mdev(me);
175 struct v4l2_subdev *sd;
176 int ret;
177
178 if (WARN_ON(p == NULL || me == NULL))
179 return -EINVAL;
180
181 if (prepare)
182 fimc_pipeline_prepare(p, me);
183
184 sd = p->subdevs[IDX_SENSOR];
185 if (sd == NULL)
186 return -EINVAL;
187
188 /* Disable PXLASYNC clock if this pipeline includes FIMC-IS */
189 if (!IS_ERR(fmd->wbclk[CLK_IDX_WB_B]) && p->subdevs[IDX_IS_ISP]) {
190 ret = clk_prepare_enable(fmd->wbclk[CLK_IDX_WB_B]);
191 if (ret < 0)
192 return ret;
193 }
194 ret = fimc_md_set_camclk(sd, true);
195 if (ret < 0)
196 goto err_wbclk;
197
198 ret = fimc_pipeline_s_power(p, 1);
199 if (!ret)
200 return 0;
201
202 fimc_md_set_camclk(sd, false);
203
204err_wbclk:
205 if (!IS_ERR(fmd->wbclk[CLK_IDX_WB_B]) && p->subdevs[IDX_IS_ISP])
206 clk_disable_unprepare(fmd->wbclk[CLK_IDX_WB_B]);
207
208 return ret;
209}
210
211/**
212 * __fimc_pipeline_close - disable the sensor clock and pipeline power
213 * @fimc: fimc device terminating the pipeline
214 *
215 * Disable power of all subdevs and turn the external sensor clock off.
216 */
217static int __fimc_pipeline_close(struct fimc_pipeline *p)
218{
219 struct v4l2_subdev *sd = p ? p->subdevs[IDX_SENSOR] : NULL;
220 struct fimc_md *fmd;
221 int ret = 0;
222
223 if (WARN_ON(sd == NULL))
224 return -EINVAL;
225
226 if (p->subdevs[IDX_SENSOR]) {
227 ret = fimc_pipeline_s_power(p, 0);
228 fimc_md_set_camclk(sd, false);
229 }
230
231 fmd = entity_to_fimc_mdev(&sd->entity);
232
233 /* Disable PXLASYNC clock if this pipeline includes FIMC-IS */
234 if (!IS_ERR(fmd->wbclk[CLK_IDX_WB_B]) && p->subdevs[IDX_IS_ISP])
235 clk_disable_unprepare(fmd->wbclk[CLK_IDX_WB_B]);
236
237 return ret == -ENXIO ? 0 : ret;
238}
239
240/**
241 * __fimc_pipeline_s_stream - call s_stream() on pipeline subdevs
242 * @pipeline: video pipeline structure
243 * @on: passed as the s_stream() callback argument
244 */
245static int __fimc_pipeline_s_stream(struct fimc_pipeline *p, bool on)
246{
247 static const u8 seq[2][IDX_MAX] = {
248 { IDX_FIMC, IDX_SENSOR, IDX_IS_ISP, IDX_CSIS, IDX_FLITE },
249 { IDX_CSIS, IDX_FLITE, IDX_FIMC, IDX_SENSOR, IDX_IS_ISP },
250 };
251 int i, ret = 0;
252
253 if (p->subdevs[IDX_SENSOR] == NULL)
254 return -ENODEV;
255
256 for (i = 0; i < IDX_MAX; i++) {
257 unsigned int idx = seq[on][i];
258
259 ret = v4l2_subdev_call(p->subdevs[idx], video, s_stream, on);
260
261 if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
262 goto error;
263 }
264 return 0;
265error:
266 for (; i >= 0; i--) {
267 unsigned int idx = seq[on][i];
268 v4l2_subdev_call(p->subdevs[idx], video, s_stream, !on);
269 }
270 return ret;
271}
272
273/* Media pipeline operations for the FIMC/FIMC-LITE video device driver */
274static const struct fimc_pipeline_ops fimc_pipeline_ops = {
275 .open = __fimc_pipeline_open,
276 .close = __fimc_pipeline_close,
277 .set_stream = __fimc_pipeline_s_stream,
278};
279
280/*
281 * Sensor subdevice helper functions
282 */
283static struct v4l2_subdev *fimc_md_register_sensor(struct fimc_md *fmd,
284 struct fimc_source_info *si)
285{
286 struct i2c_adapter *adapter;
287 struct v4l2_subdev *sd = NULL;
288
289 if (!si || !fmd)
290 return NULL;
291 /*
292 * If FIMC bus type is not Writeback FIFO assume it is same
293 * as sensor_bus_type.
294 */
295 si->fimc_bus_type = si->sensor_bus_type;
296
297 adapter = i2c_get_adapter(si->i2c_bus_num);
298 if (!adapter) {
299 v4l2_warn(&fmd->v4l2_dev,
300 "Failed to get I2C adapter %d, deferring probe\n",
301 si->i2c_bus_num);
302 return ERR_PTR(-EPROBE_DEFER);
303 }
304 sd = v4l2_i2c_new_subdev_board(&fmd->v4l2_dev, adapter,
305 si->board_info, NULL);
306 if (IS_ERR_OR_NULL(sd)) {
307 i2c_put_adapter(adapter);
308 v4l2_warn(&fmd->v4l2_dev,
309 "Failed to acquire subdev %s, deferring probe\n",
310 si->board_info->type);
311 return ERR_PTR(-EPROBE_DEFER);
312 }
313 v4l2_set_subdev_hostdata(sd, si);
314 sd->grp_id = GRP_ID_SENSOR;
315
316 v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice %s\n",
317 sd->name);
318 return sd;
319}
320
321static void fimc_md_unregister_sensor(struct v4l2_subdev *sd)
322{
323 struct i2c_client *client = v4l2_get_subdevdata(sd);
324 struct i2c_adapter *adapter;
325
326 if (!client)
327 return;
328
329 v4l2_device_unregister_subdev(sd);
330
331 if (!client->dev.of_node) {
332 adapter = client->adapter;
333 i2c_unregister_device(client);
334 if (adapter)
335 i2c_put_adapter(adapter);
336 }
337}
338
339#ifdef CONFIG_OF
340/* Register I2C client subdev associated with @node. */
341static int fimc_md_of_add_sensor(struct fimc_md *fmd,
342 struct device_node *node, int index)
343{
344 struct fimc_sensor_info *si;
345 struct i2c_client *client;
346 struct v4l2_subdev *sd;
347 int ret;
348
349 if (WARN_ON(index >= ARRAY_SIZE(fmd->sensor)))
350 return -EINVAL;
351 si = &fmd->sensor[index];
352
353 client = of_find_i2c_device_by_node(node);
354 if (!client)
355 return -EPROBE_DEFER;
356
357 device_lock(&client->dev);
358
359 if (!client->driver ||
360 !try_module_get(client->driver->driver.owner)) {
361 ret = -EPROBE_DEFER;
362 v4l2_info(&fmd->v4l2_dev, "No driver found for %s\n",
363 node->full_name);
364 goto dev_put;
365 }
366
367 /* Enable sensor's master clock */
368 ret = __fimc_md_set_camclk(fmd, &si->pdata, true);
369 if (ret < 0)
370 goto mod_put;
371 sd = i2c_get_clientdata(client);
372
373 ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
374 __fimc_md_set_camclk(fmd, &si->pdata, false);
375 if (ret < 0)
376 goto mod_put;
377
378 v4l2_set_subdev_hostdata(sd, &si->pdata);
379 if (si->pdata.fimc_bus_type == FIMC_BUS_TYPE_ISP_WRITEBACK)
380 sd->grp_id = GRP_ID_FIMC_IS_SENSOR;
381 else
382 sd->grp_id = GRP_ID_SENSOR;
383
384 si->subdev = sd;
385 v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice: %s (%d)\n",
386 sd->name, fmd->num_sensors);
387 fmd->num_sensors++;
388
389mod_put:
390 module_put(client->driver->driver.owner);
391dev_put:
392 device_unlock(&client->dev);
393 put_device(&client->dev);
394 return ret;
395}
396
397/* Parse port node and register as a sub-device any sensor specified there. */
398static int fimc_md_parse_port_node(struct fimc_md *fmd,
399 struct device_node *port,
400 unsigned int index)
401{
402 struct device_node *rem, *ep, *np;
403 struct fimc_source_info *pd;
404 struct v4l2_of_endpoint endpoint;
405 int ret;
406 u32 val;
407
408 pd = &fmd->sensor[index].pdata;
409
410 /* Assume here a port node can have only one endpoint node. */
411 ep = of_get_next_child(port, NULL);
412 if (!ep)
413 return 0;
414
415 v4l2_of_parse_endpoint(ep, &endpoint);
416 if (WARN_ON(endpoint.port == 0) || index >= FIMC_MAX_SENSORS)
417 return -EINVAL;
418
419 pd->mux_id = (endpoint.port - 1) & 0x1;
420
421 rem = v4l2_of_get_remote_port_parent(ep);
422 of_node_put(ep);
423 if (rem == NULL) {
424 v4l2_info(&fmd->v4l2_dev, "Remote device at %s not found\n",
425 ep->full_name);
426 return 0;
427 }
428 if (!of_property_read_u32(rem, "samsung,camclk-out", &val))
429 pd->clk_id = val;
430
431 if (!of_property_read_u32(rem, "clock-frequency", &val))
432 pd->clk_frequency = val;
433
434 if (pd->clk_frequency == 0) {
435 v4l2_err(&fmd->v4l2_dev, "Wrong clock frequency at node %s\n",
436 rem->full_name);
437 of_node_put(rem);
438 return -EINVAL;
439 }
440
441 if (fimc_input_is_parallel(endpoint.port)) {
442 if (endpoint.bus_type == V4L2_MBUS_PARALLEL)
443 pd->sensor_bus_type = FIMC_BUS_TYPE_ITU_601;
444 else
445 pd->sensor_bus_type = FIMC_BUS_TYPE_ITU_656;
446 pd->flags = endpoint.bus.parallel.flags;
447 } else if (fimc_input_is_mipi_csi(endpoint.port)) {
448 /*
449 * MIPI CSI-2: only input mux selection and
450 * the sensor's clock frequency is needed.
451 */
452 pd->sensor_bus_type = FIMC_BUS_TYPE_MIPI_CSI2;
453 } else {
454 v4l2_err(&fmd->v4l2_dev, "Wrong port id (%u) at node %s\n",
455 endpoint.port, rem->full_name);
456 }
457 /*
458 * For FIMC-IS handled sensors, that are placed under i2c-isp device
459 * node, FIMC is connected to the FIMC-IS through its ISP Writeback
460 * input. Sensors are attached to the FIMC-LITE hostdata interface
461 * directly or through MIPI-CSIS, depending on the external media bus
462 * used. This needs to be handled in a more reliable way, not by just
463 * checking parent's node name.
464 */
465 np = of_get_parent(rem);
466
467 if (np && !of_node_cmp(np->name, "i2c-isp"))
468 pd->fimc_bus_type = FIMC_BUS_TYPE_ISP_WRITEBACK;
469 else
470 pd->fimc_bus_type = pd->sensor_bus_type;
471
472 ret = fimc_md_of_add_sensor(fmd, rem, index);
473 of_node_put(rem);
474
475 return ret;
476}
477
478/* Register all SoC external sub-devices */
479static int fimc_md_of_sensors_register(struct fimc_md *fmd,
480 struct device_node *np)
481{
482 struct device_node *parent = fmd->pdev->dev.of_node;
483 struct device_node *node, *ports;
484 int index = 0;
485 int ret;
486
487 /* Attach sensors linked to MIPI CSI-2 receivers */
488 for_each_available_child_of_node(parent, node) {
489 struct device_node *port;
490
491 if (of_node_cmp(node->name, "csis"))
492 continue;
493 /* The csis node can have only port subnode. */
494 port = of_get_next_child(node, NULL);
495 if (!port)
496 continue;
497
498 ret = fimc_md_parse_port_node(fmd, port, index);
499 if (ret < 0)
500 return ret;
501 index++;
502 }
503
504 /* Attach sensors listed in the parallel-ports node */
505 ports = of_get_child_by_name(parent, "parallel-ports");
506 if (!ports)
507 return 0;
508
509 for_each_child_of_node(ports, node) {
510 ret = fimc_md_parse_port_node(fmd, node, index);
511 if (ret < 0)
512 break;
513 index++;
514 }
515
516 return 0;
517}
518
519static int __of_get_csis_id(struct device_node *np)
520{
521 u32 reg = 0;
522
523 np = of_get_child_by_name(np, "port");
524 if (!np)
525 return -EINVAL;
526 of_property_read_u32(np, "reg", &reg);
527 return reg - FIMC_INPUT_MIPI_CSI2_0;
528}
529#else
530#define fimc_md_of_sensors_register(fmd, np) (-ENOSYS)
531#define __of_get_csis_id(np) (-ENOSYS)
532#endif
533
534static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
535{
536 struct s5p_platform_fimc *pdata = fmd->pdev->dev.platform_data;
537 struct device_node *of_node = fmd->pdev->dev.of_node;
538 int num_clients = 0;
539 int ret, i;
540
541 /*
542 * Runtime resume one of the FIMC entities to make sure
543 * the sclk_cam clocks are not globally disabled.
544 */
545 if (!fmd->pmf)
546 return -ENXIO;
547
548 ret = pm_runtime_get_sync(fmd->pmf);
549 if (ret < 0)
550 return ret;
551
552 if (of_node) {
553 fmd->num_sensors = 0;
554 ret = fimc_md_of_sensors_register(fmd, of_node);
555 } else if (pdata) {
556 WARN_ON(pdata->num_clients > ARRAY_SIZE(fmd->sensor));
557 num_clients = min_t(u32, pdata->num_clients,
558 ARRAY_SIZE(fmd->sensor));
559 fmd->num_sensors = num_clients;
560
561 for (i = 0; i < num_clients; i++) {
562 struct fimc_sensor_info *si = &fmd->sensor[i];
563 struct v4l2_subdev *sd;
564
565 si->pdata = pdata->source_info[i];
566 ret = __fimc_md_set_camclk(fmd, &si->pdata, true);
567 if (ret)
568 break;
569 sd = fimc_md_register_sensor(fmd, &si->pdata);
570 ret = __fimc_md_set_camclk(fmd, &si->pdata, false);
571
572 if (IS_ERR(sd)) {
573 si->subdev = NULL;
574 ret = PTR_ERR(sd);
575 break;
576 }
577 si->subdev = sd;
578 if (ret)
579 break;
580 }
581 }
582
583 pm_runtime_put(fmd->pmf);
584 return ret;
585}
586
587/*
588 * MIPI-CSIS, FIMC and FIMC-LITE platform devices registration.
589 */
590
591static int register_fimc_lite_entity(struct fimc_md *fmd,
592 struct fimc_lite *fimc_lite)
593{
594 struct v4l2_subdev *sd;
595 int ret;
596
597 if (WARN_ON(fimc_lite->index >= FIMC_LITE_MAX_DEVS ||
598 fmd->fimc_lite[fimc_lite->index]))
599 return -EBUSY;
600
601 sd = &fimc_lite->subdev;
602 sd->grp_id = GRP_ID_FLITE;
603 v4l2_set_subdev_hostdata(sd, (void *)&fimc_pipeline_ops);
604
605 ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
606 if (!ret)
607 fmd->fimc_lite[fimc_lite->index] = fimc_lite;
608 else
609 v4l2_err(&fmd->v4l2_dev, "Failed to register FIMC.LITE%d\n",
610 fimc_lite->index);
611 return ret;
612}
613
614static int register_fimc_entity(struct fimc_md *fmd, struct fimc_dev *fimc)
615{
616 struct v4l2_subdev *sd;
617 int ret;
618
619 if (WARN_ON(fimc->id >= FIMC_MAX_DEVS || fmd->fimc[fimc->id]))
620 return -EBUSY;
621
622 sd = &fimc->vid_cap.subdev;
623 sd->grp_id = GRP_ID_FIMC;
624 v4l2_set_subdev_hostdata(sd, (void *)&fimc_pipeline_ops);
625
626 ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
627 if (!ret) {
628 if (!fmd->pmf && fimc->pdev)
629 fmd->pmf = &fimc->pdev->dev;
630 fmd->fimc[fimc->id] = fimc;
631 fimc->vid_cap.user_subdev_api = fmd->user_subdev_api;
632 } else {
633 v4l2_err(&fmd->v4l2_dev, "Failed to register FIMC.%d (%d)\n",
634 fimc->id, ret);
635 }
636 return ret;
637}
638
639static int register_csis_entity(struct fimc_md *fmd,
640 struct platform_device *pdev,
641 struct v4l2_subdev *sd)
642{
643 struct device_node *node = pdev->dev.of_node;
644 int id, ret;
645
646 id = node ? __of_get_csis_id(node) : max(0, pdev->id);
647
648 if (WARN_ON(id < 0 || id >= CSIS_MAX_ENTITIES))
649 return -ENOENT;
650
651 if (WARN_ON(fmd->csis[id].sd))
652 return -EBUSY;
653
654 sd->grp_id = GRP_ID_CSIS;
655 ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
656 if (!ret)
657 fmd->csis[id].sd = sd;
658 else
659 v4l2_err(&fmd->v4l2_dev,
660 "Failed to register MIPI-CSIS.%d (%d)\n", id, ret);
661 return ret;
662}
663
664static int register_fimc_is_entity(struct fimc_md *fmd, struct fimc_is *is)
665{
666 struct v4l2_subdev *sd = &is->isp.subdev;
667 int ret;
668
669 ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
670 if (ret) {
671 v4l2_err(&fmd->v4l2_dev,
672 "Failed to register FIMC-ISP (%d)\n", ret);
673 return ret;
674 }
675
676 fmd->fimc_is = is;
677 return 0;
678}
679
680static int fimc_md_register_platform_entity(struct fimc_md *fmd,
681 struct platform_device *pdev,
682 int plat_entity)
683{
684 struct device *dev = &pdev->dev;
685 int ret = -EPROBE_DEFER;
686 void *drvdata;
687
688 /* Lock to ensure dev->driver won't change. */
689 device_lock(dev);
690
691 if (!dev->driver || !try_module_get(dev->driver->owner))
692 goto dev_unlock;
693
694 drvdata = dev_get_drvdata(dev);
695 /* Some subdev didn't probe succesfully id drvdata is NULL */
696 if (drvdata) {
697 switch (plat_entity) {
698 case IDX_FIMC:
699 ret = register_fimc_entity(fmd, drvdata);
700 break;
701 case IDX_FLITE:
702 ret = register_fimc_lite_entity(fmd, drvdata);
703 break;
704 case IDX_CSIS:
705 ret = register_csis_entity(fmd, pdev, drvdata);
706 break;
707 case IDX_IS_ISP:
708 ret = register_fimc_is_entity(fmd, drvdata);
709 break;
710 default:
711 ret = -ENODEV;
712 }
713 }
714
715 module_put(dev->driver->owner);
716dev_unlock:
717 device_unlock(dev);
718 if (ret == -EPROBE_DEFER)
719 dev_info(&fmd->pdev->dev, "deferring %s device registration\n",
720 dev_name(dev));
721 else if (ret < 0)
722 dev_err(&fmd->pdev->dev, "%s device registration failed (%d)\n",
723 dev_name(dev), ret);
724 return ret;
725}
726
727static int fimc_md_pdev_match(struct device *dev, void *data)
728{
729 struct platform_device *pdev = to_platform_device(dev);
730 int plat_entity = -1;
731 int ret;
732 char *p;
733
734 if (!get_device(dev))
735 return -ENODEV;
736
737 if (!strcmp(pdev->name, CSIS_DRIVER_NAME)) {
738 plat_entity = IDX_CSIS;
739 } else if (!strcmp(pdev->name, FIMC_LITE_DRV_NAME)) {
740 plat_entity = IDX_FLITE;
741 } else {
742 p = strstr(pdev->name, "fimc");
743 if (p && *(p + 4) == 0)
744 plat_entity = IDX_FIMC;
745 }
746
747 if (plat_entity >= 0)
748 ret = fimc_md_register_platform_entity(data, pdev,
749 plat_entity);
750 put_device(dev);
751 return 0;
752}
753
754/* Register FIMC, FIMC-LITE and CSIS media entities */
755#ifdef CONFIG_OF
756static int fimc_md_register_of_platform_entities(struct fimc_md *fmd,
757 struct device_node *parent)
758{
759 struct device_node *node;
760 int ret = 0;
761
762 for_each_available_child_of_node(parent, node) {
763 struct platform_device *pdev;
764 int plat_entity = -1;
765
766 pdev = of_find_device_by_node(node);
767 if (!pdev)
768 continue;
769
770 /* If driver of any entity isn't ready try all again later. */
771 if (!strcmp(node->name, CSIS_OF_NODE_NAME))
772 plat_entity = IDX_CSIS;
773 else if (!strcmp(node->name, FIMC_IS_OF_NODE_NAME))
774 plat_entity = IDX_IS_ISP;
775 else if (!strcmp(node->name, FIMC_LITE_OF_NODE_NAME))
776 plat_entity = IDX_FLITE;
777 else if (!strcmp(node->name, FIMC_OF_NODE_NAME) &&
778 !of_property_read_bool(node, "samsung,lcd-wb"))
779 plat_entity = IDX_FIMC;
780
781 if (plat_entity >= 0)
782 ret = fimc_md_register_platform_entity(fmd, pdev,
783 plat_entity);
784 put_device(&pdev->dev);
785 if (ret < 0)
786 break;
787 }
788
789 return ret;
790}
791#else
792#define fimc_md_register_of_platform_entities(fmd, node) (-ENOSYS)
793#endif
794
795static void fimc_md_unregister_entities(struct fimc_md *fmd)
796{
797 int i;
798
799 for (i = 0; i < FIMC_MAX_DEVS; i++) {
800 if (fmd->fimc[i] == NULL)
801 continue;
802 v4l2_device_unregister_subdev(&fmd->fimc[i]->vid_cap.subdev);
803 fmd->fimc[i]->pipeline_ops = NULL;
804 fmd->fimc[i] = NULL;
805 }
806 for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) {
807 if (fmd->fimc_lite[i] == NULL)
808 continue;
809 v4l2_device_unregister_subdev(&fmd->fimc_lite[i]->subdev);
810 fmd->fimc_lite[i]->pipeline_ops = NULL;
811 fmd->fimc_lite[i] = NULL;
812 }
813 for (i = 0; i < CSIS_MAX_ENTITIES; i++) {
814 if (fmd->csis[i].sd == NULL)
815 continue;
816 v4l2_device_unregister_subdev(fmd->csis[i].sd);
817 fmd->csis[i].sd = NULL;
818 }
819 for (i = 0; i < fmd->num_sensors; i++) {
820 if (fmd->sensor[i].subdev == NULL)
821 continue;
822 fimc_md_unregister_sensor(fmd->sensor[i].subdev);
823 fmd->sensor[i].subdev = NULL;
824 }
825
826 if (fmd->fimc_is)
827 v4l2_device_unregister_subdev(&fmd->fimc_is->isp.subdev);
828
829 v4l2_info(&fmd->v4l2_dev, "Unregistered all entities\n");
830}
831
832/**
833 * __fimc_md_create_fimc_links - create links to all FIMC entities
834 * @fmd: fimc media device
835 * @source: the source entity to create links to all fimc entities from
836 * @sensor: sensor subdev linked to FIMC[fimc_id] entity, may be null
837 * @pad: the source entity pad index
838 * @link_mask: bitmask of the fimc devices for which link should be enabled
839 */
840static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,
841 struct media_entity *source,
842 struct v4l2_subdev *sensor,
843 int pad, int link_mask)
844{
845 struct fimc_source_info *si = NULL;
846 struct media_entity *sink;
847 unsigned int flags = 0;
848 int i, ret = 0;
849
850 if (sensor) {
851 si = v4l2_get_subdev_hostdata(sensor);
852 /* Skip direct FIMC links in the logical FIMC-IS sensor path */
853 if (si && si->fimc_bus_type == FIMC_BUS_TYPE_ISP_WRITEBACK)
854 ret = 1;
855 }
856
857 for (i = 0; !ret && i < FIMC_MAX_DEVS; i++) {
858 if (!fmd->fimc[i])
859 continue;
860 /*
861 * Some FIMC variants are not fitted with camera capture
862 * interface. Skip creating a link from sensor for those.
863 */
864 if (!fmd->fimc[i]->variant->has_cam_if)
865 continue;
866
867 flags = ((1 << i) & link_mask) ? MEDIA_LNK_FL_ENABLED : 0;
868
869 sink = &fmd->fimc[i]->vid_cap.subdev.entity;
870 ret = media_entity_create_link(source, pad, sink,
871 FIMC_SD_PAD_SINK_CAM, flags);
872 if (ret)
873 return ret;
874
875 /* Notify FIMC capture subdev entity */
876 ret = media_entity_call(sink, link_setup, &sink->pads[0],
877 &source->pads[pad], flags);
878 if (ret)
879 break;
880
881 v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]\n",
882 source->name, flags ? '=' : '-', sink->name);
883
884 if (flags == 0 || sensor == NULL)
885 continue;
886
887 if (!WARN_ON(si == NULL)) {
888 unsigned long irq_flags;
889 struct fimc_sensor_info *inf = source_to_sensor_info(si);
890
891 spin_lock_irqsave(&fmd->slock, irq_flags);
892 inf->host = fmd->fimc[i];
893 spin_unlock_irqrestore(&fmd->slock, irq_flags);
894 }
895 }
896
897 for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) {
898 if (!fmd->fimc_lite[i])
899 continue;
900
901 sink = &fmd->fimc_lite[i]->subdev.entity;
902 ret = media_entity_create_link(source, pad, sink,
903 FLITE_SD_PAD_SINK, 0);
904 if (ret)
905 return ret;
906
907 /* Notify FIMC-LITE subdev entity */
908 ret = media_entity_call(sink, link_setup, &sink->pads[0],
909 &source->pads[pad], 0);
910 if (ret)
911 break;
912
913 v4l2_info(&fmd->v4l2_dev, "created link [%s] -> [%s]\n",
914 source->name, sink->name);
915 }
916 return 0;
917}
918
919/* Create links from FIMC-LITE source pads to other entities */
920static int __fimc_md_create_flite_source_links(struct fimc_md *fmd)
921{
922 struct media_entity *source, *sink;
923 int i, ret = 0;
924
925 for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) {
926 struct fimc_lite *fimc = fmd->fimc_lite[i];
927
928 if (fimc == NULL)
929 continue;
930
931 source = &fimc->subdev.entity;
932 sink = &fimc->vfd.entity;
933 /* FIMC-LITE's subdev and video node */
934 ret = media_entity_create_link(source, FLITE_SD_PAD_SOURCE_DMA,
935 sink, 0, 0);
936 if (ret)
937 break;
938 /* Link from FIMC-LITE to IS-ISP subdev */
939 sink = &fmd->fimc_is->isp.subdev.entity;
940 ret = media_entity_create_link(source, FLITE_SD_PAD_SOURCE_ISP,
941 sink, 0, 0);
942 if (ret)
943 break;
944 }
945
946 return ret;
947}
948
949/* Create FIMC-IS links */
950static int __fimc_md_create_fimc_is_links(struct fimc_md *fmd)
951{
952 struct media_entity *source, *sink;
953 int i, ret;
954
955 source = &fmd->fimc_is->isp.subdev.entity;
956
957 for (i = 0; i < FIMC_MAX_DEVS; i++) {
958 if (fmd->fimc[i] == NULL)
959 continue;
960
961 /* Link from IS-ISP subdev to FIMC */
962 sink = &fmd->fimc[i]->vid_cap.subdev.entity;
963 ret = media_entity_create_link(source, FIMC_ISP_SD_PAD_SRC_FIFO,
964 sink, FIMC_SD_PAD_SINK_FIFO, 0);
965 if (ret)
966 return ret;
967 }
968
969 return ret;
970}
971
972/**
973 * fimc_md_create_links - create default links between registered entities
974 *
975 * Parallel interface sensor entities are connected directly to FIMC capture
976 * entities. The sensors using MIPI CSIS bus are connected through immutable
977 * link with CSI receiver entity specified by mux_id. Any registered CSIS
978 * entity has a link to each registered FIMC capture entity. Enabled links
979 * are created by default between each subsequent registered sensor and
980 * subsequent FIMC capture entity. The number of default active links is
981 * determined by the number of available sensors or FIMC entities,
982 * whichever is less.
983 */
984static int fimc_md_create_links(struct fimc_md *fmd)
985{
986 struct v4l2_subdev *csi_sensors[CSIS_MAX_ENTITIES] = { NULL };
987 struct v4l2_subdev *sensor, *csis;
988 struct fimc_source_info *pdata;
989 struct media_entity *source, *sink;
990 int i, pad, fimc_id = 0, ret = 0;
991 u32 flags, link_mask = 0;
992
993 for (i = 0; i < fmd->num_sensors; i++) {
994 if (fmd->sensor[i].subdev == NULL)
995 continue;
996
997 sensor = fmd->sensor[i].subdev;
998 pdata = v4l2_get_subdev_hostdata(sensor);
999 if (!pdata)
1000 continue;
1001
1002 source = NULL;
1003
1004 switch (pdata->sensor_bus_type) {
1005 case FIMC_BUS_TYPE_MIPI_CSI2:
1006 if (WARN(pdata->mux_id >= CSIS_MAX_ENTITIES,
1007 "Wrong CSI channel id: %d\n", pdata->mux_id))
1008 return -EINVAL;
1009
1010 csis = fmd->csis[pdata->mux_id].sd;
1011 if (WARN(csis == NULL,
1012 "MIPI-CSI interface specified "
1013 "but s5p-csis module is not loaded!\n"))
1014 return -EINVAL;
1015
1016 pad = sensor->entity.num_pads - 1;
1017 ret = media_entity_create_link(&sensor->entity, pad,
1018 &csis->entity, CSIS_PAD_SINK,
1019 MEDIA_LNK_FL_IMMUTABLE |
1020 MEDIA_LNK_FL_ENABLED);
1021 if (ret)
1022 return ret;
1023
1024 v4l2_info(&fmd->v4l2_dev, "created link [%s] => [%s]\n",
1025 sensor->entity.name, csis->entity.name);
1026
1027 source = NULL;
1028 csi_sensors[pdata->mux_id] = sensor;
1029 break;
1030
1031 case FIMC_BUS_TYPE_ITU_601...FIMC_BUS_TYPE_ITU_656:
1032 source = &sensor->entity;
1033 pad = 0;
1034 break;
1035
1036 default:
1037 v4l2_err(&fmd->v4l2_dev, "Wrong bus_type: %x\n",
1038 pdata->sensor_bus_type);
1039 return -EINVAL;
1040 }
1041 if (source == NULL)
1042 continue;
1043
1044 link_mask = 1 << fimc_id++;
1045 ret = __fimc_md_create_fimc_sink_links(fmd, source, sensor,
1046 pad, link_mask);
1047 }
1048
1049 for (i = 0; i < CSIS_MAX_ENTITIES; i++) {
1050 if (fmd->csis[i].sd == NULL)
1051 continue;
1052
1053 source = &fmd->csis[i].sd->entity;
1054 pad = CSIS_PAD_SOURCE;
1055 sensor = csi_sensors[i];
1056
1057 link_mask = 1 << fimc_id++;
1058 ret = __fimc_md_create_fimc_sink_links(fmd, source, sensor,
1059 pad, link_mask);
1060 }
1061
1062 /* Create immutable links between each FIMC's subdev and video node */
1063 flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED;
1064 for (i = 0; i < FIMC_MAX_DEVS; i++) {
1065 if (!fmd->fimc[i])
1066 continue;
1067
1068 source = &fmd->fimc[i]->vid_cap.subdev.entity;
1069 sink = &fmd->fimc[i]->vid_cap.vfd.entity;
1070
1071 ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE,
1072 sink, 0, flags);
1073 if (ret)
1074 break;
1075 }
1076
1077 ret = __fimc_md_create_flite_source_links(fmd);
1078 if (ret < 0)
1079 return ret;
1080
1081 if (fmd->use_isp)
1082 ret = __fimc_md_create_fimc_is_links(fmd);
1083
1084 return ret;
1085}
1086
1087/*
1088 * The peripheral sensor and CAM_BLK (PIXELASYNCMx) clocks management.
1089 */
1090static void fimc_md_put_clocks(struct fimc_md *fmd)
1091{
1092 int i = FIMC_MAX_CAMCLKS;
1093
1094 while (--i >= 0) {
1095 if (IS_ERR(fmd->camclk[i].clock))
1096 continue;
1097 clk_unprepare(fmd->camclk[i].clock);
1098 clk_put(fmd->camclk[i].clock);
1099 fmd->camclk[i].clock = ERR_PTR(-EINVAL);
1100 }
1101
1102 /* Writeback (PIXELASYNCMx) clocks */
1103 for (i = 0; i < FIMC_MAX_WBCLKS; i++) {
1104 if (IS_ERR(fmd->wbclk[i]))
1105 continue;
1106 clk_put(fmd->wbclk[i]);
1107 fmd->wbclk[i] = ERR_PTR(-EINVAL);
1108 }
1109}
1110
1111static int fimc_md_get_clocks(struct fimc_md *fmd)
1112{
1113 struct device *dev = NULL;
1114 char clk_name[32];
1115 struct clk *clock;
1116 int ret, i;
1117
1118 for (i = 0; i < FIMC_MAX_CAMCLKS; i++)
1119 fmd->camclk[i].clock = ERR_PTR(-EINVAL);
1120
1121 if (fmd->pdev->dev.of_node)
1122 dev = &fmd->pdev->dev;
1123
1124 for (i = 0; i < FIMC_MAX_CAMCLKS; i++) {
1125 snprintf(clk_name, sizeof(clk_name), "sclk_cam%u", i);
1126 clock = clk_get(dev, clk_name);
1127
1128 if (IS_ERR(clock)) {
1129 dev_err(&fmd->pdev->dev, "Failed to get clock: %s\n",
1130 clk_name);
1131 ret = PTR_ERR(clock);
1132 break;
1133 }
1134 ret = clk_prepare(clock);
1135 if (ret < 0) {
1136 clk_put(clock);
1137 fmd->camclk[i].clock = ERR_PTR(-EINVAL);
1138 break;
1139 }
1140 fmd->camclk[i].clock = clock;
1141 }
1142 if (ret)
1143 fimc_md_put_clocks(fmd);
1144
1145 if (!fmd->use_isp)
1146 return 0;
1147 /*
1148 * For now get only PIXELASYNCM1 clock (Writeback B/ISP),
1149 * leave PIXELASYNCM0 out for the LCD Writeback driver.
1150 */
1151 fmd->wbclk[CLK_IDX_WB_A] = ERR_PTR(-EINVAL);
1152
1153 for (i = CLK_IDX_WB_B; i < FIMC_MAX_WBCLKS; i++) {
1154 snprintf(clk_name, sizeof(clk_name), "pxl_async%u", i);
1155 clock = clk_get(dev, clk_name);
1156 if (IS_ERR(clock)) {
1157 v4l2_err(&fmd->v4l2_dev, "Failed to get clock: %s\n",
1158 clk_name);
1159 ret = PTR_ERR(clock);
1160 break;
1161 }
1162 fmd->wbclk[i] = clock;
1163 }
1164 if (ret)
1165 fimc_md_put_clocks(fmd);
1166
1167 return ret;
1168}
1169
1170static int __fimc_md_set_camclk(struct fimc_md *fmd,
1171 struct fimc_source_info *si,
1172 bool on)
1173{
1174 struct fimc_camclk_info *camclk;
1175 int ret = 0;
1176
1177 if (WARN_ON(si->clk_id >= FIMC_MAX_CAMCLKS) || !fmd || !fmd->pmf)
1178 return -EINVAL;
1179
1180 camclk = &fmd->camclk[si->clk_id];
1181
1182 dbg("camclk %d, f: %lu, use_count: %d, on: %d",
1183 si->clk_id, si->clk_frequency, camclk->use_count, on);
1184
1185 if (on) {
1186 if (camclk->use_count > 0 &&
1187 camclk->frequency != si->clk_frequency)
1188 return -EINVAL;
1189
1190 if (camclk->use_count++ == 0) {
1191 clk_set_rate(camclk->clock, si->clk_frequency);
1192 camclk->frequency = si->clk_frequency;
1193 ret = pm_runtime_get_sync(fmd->pmf);
1194 if (ret < 0)
1195 return ret;
1196 ret = clk_enable(camclk->clock);
1197 dbg("Enabled camclk %d: f: %lu", si->clk_id,
1198 clk_get_rate(camclk->clock));
1199 }
1200 return ret;
1201 }
1202
1203 if (WARN_ON(camclk->use_count == 0))
1204 return 0;
1205
1206 if (--camclk->use_count == 0) {
1207 clk_disable(camclk->clock);
1208 pm_runtime_put(fmd->pmf);
1209 dbg("Disabled camclk %d", si->clk_id);
1210 }
1211 return ret;
1212}
1213
1214/**
1215 * fimc_md_set_camclk - peripheral sensor clock setup
1216 * @sd: sensor subdev to configure sclk_cam clock for
1217 * @on: 1 to enable or 0 to disable the clock
1218 *
1219 * There are 2 separate clock outputs available in the SoC for external
1220 * image processors. These clocks are shared between all registered FIMC
1221 * devices to which sensors can be attached, either directly or through
1222 * the MIPI CSI receiver. The clock is allowed here to be used by
1223 * multiple sensors concurrently if they use same frequency.
1224 * This function should only be called when the graph mutex is held.
1225 */
1226int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on)
1227{
1228 struct fimc_source_info *si = v4l2_get_subdev_hostdata(sd);
1229 struct fimc_md *fmd = entity_to_fimc_mdev(&sd->entity);
1230
1231 return __fimc_md_set_camclk(fmd, si, on);
1232}
1233
1234static int fimc_md_link_notify(struct media_pad *source,
1235 struct media_pad *sink, u32 flags)
1236{
1237 struct fimc_lite *fimc_lite = NULL;
1238 struct fimc_dev *fimc = NULL;
1239 struct fimc_pipeline *pipeline;
1240 struct v4l2_subdev *sd;
1241 struct mutex *lock;
1242 int i, ret = 0;
1243 int ref_count;
1244
1245 if (media_entity_type(sink->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
1246 return 0;
1247
1248 sd = media_entity_to_v4l2_subdev(sink->entity);
1249
1250 switch (sd->grp_id) {
1251 case GRP_ID_FLITE:
1252 fimc_lite = v4l2_get_subdevdata(sd);
1253 if (WARN_ON(fimc_lite == NULL))
1254 return 0;
1255 pipeline = &fimc_lite->pipeline;
1256 lock = &fimc_lite->lock;
1257 break;
1258 case GRP_ID_FIMC:
1259 fimc = v4l2_get_subdevdata(sd);
1260 if (WARN_ON(fimc == NULL))
1261 return 0;
1262 pipeline = &fimc->pipeline;
1263 lock = &fimc->lock;
1264 break;
1265 default:
1266 return 0;
1267 }
1268
1269 mutex_lock(lock);
1270 ref_count = fimc ? fimc->vid_cap.refcnt : fimc_lite->ref_count;
1271
1272 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
1273 if (ref_count > 0) {
1274 ret = __fimc_pipeline_close(pipeline);
1275 if (!ret && fimc)
1276 fimc_ctrls_delete(fimc->vid_cap.ctx);
1277 }
1278 for (i = 0; i < IDX_MAX; i++)
1279 pipeline->subdevs[i] = NULL;
1280 } else if (ref_count > 0) {
1281 /*
1282 * Link activation. Enable power of pipeline elements only if
1283 * the pipeline is already in use, i.e. its video node is open.
1284 * Recreate the controls destroyed during the link deactivation.
1285 */
1286 ret = __fimc_pipeline_open(pipeline,
1287 source->entity, true);
1288 if (!ret && fimc)
1289 ret = fimc_capture_ctrls_create(fimc);
1290 }
1291
1292 mutex_unlock(lock);
1293 return ret ? -EPIPE : ret;
1294}
1295
1296static ssize_t fimc_md_sysfs_show(struct device *dev,
1297 struct device_attribute *attr, char *buf)
1298{
1299 struct platform_device *pdev = to_platform_device(dev);
1300 struct fimc_md *fmd = platform_get_drvdata(pdev);
1301
1302 if (fmd->user_subdev_api)
1303 return strlcpy(buf, "Sub-device API (sub-dev)\n", PAGE_SIZE);
1304
1305 return strlcpy(buf, "V4L2 video node only API (vid-dev)\n", PAGE_SIZE);
1306}
1307
1308static ssize_t fimc_md_sysfs_store(struct device *dev,
1309 struct device_attribute *attr,
1310 const char *buf, size_t count)
1311{
1312 struct platform_device *pdev = to_platform_device(dev);
1313 struct fimc_md *fmd = platform_get_drvdata(pdev);
1314 bool subdev_api;
1315 int i;
1316
1317 if (!strcmp(buf, "vid-dev\n"))
1318 subdev_api = false;
1319 else if (!strcmp(buf, "sub-dev\n"))
1320 subdev_api = true;
1321 else
1322 return count;
1323
1324 fmd->user_subdev_api = subdev_api;
1325 for (i = 0; i < FIMC_MAX_DEVS; i++)
1326 if (fmd->fimc[i])
1327 fmd->fimc[i]->vid_cap.user_subdev_api = subdev_api;
1328 return count;
1329}
1330/*
1331 * This device attribute is to select video pipeline configuration method.
1332 * There are following valid values:
1333 * vid-dev - for V4L2 video node API only, subdevice will be configured
1334 * by the host driver.
1335 * sub-dev - for media controller API, subdevs must be configured in user
1336 * space before starting streaming.
1337 */
1338static DEVICE_ATTR(subdev_conf_mode, S_IWUSR | S_IRUGO,
1339 fimc_md_sysfs_show, fimc_md_sysfs_store);
1340
1341static int fimc_md_get_pinctrl(struct fimc_md *fmd)
1342{
1343 struct device *dev = &fmd->pdev->dev;
1344 struct fimc_pinctrl *pctl = &fmd->pinctl;
1345
1346 pctl->pinctrl = devm_pinctrl_get(dev);
1347 if (IS_ERR(pctl->pinctrl))
1348 return PTR_ERR(pctl->pinctrl);
1349
1350 pctl->state_default = pinctrl_lookup_state(pctl->pinctrl,
1351 PINCTRL_STATE_DEFAULT);
1352 if (IS_ERR(pctl->state_default))
1353 return PTR_ERR(pctl->state_default);
1354
1355 pctl->state_idle = pinctrl_lookup_state(pctl->pinctrl,
1356 PINCTRL_STATE_IDLE);
1357 return 0;
1358}
1359
1360static int fimc_md_probe(struct platform_device *pdev)
1361{
1362 struct device *dev = &pdev->dev;
1363 struct v4l2_device *v4l2_dev;
1364 struct fimc_md *fmd;
1365 int ret;
1366
1367 fmd = devm_kzalloc(dev, sizeof(*fmd), GFP_KERNEL);
1368 if (!fmd)
1369 return -ENOMEM;
1370
1371 spin_lock_init(&fmd->slock);
1372 fmd->pdev = pdev;
1373
1374 strlcpy(fmd->media_dev.model, "SAMSUNG S5P FIMC",
1375 sizeof(fmd->media_dev.model));
1376 fmd->media_dev.link_notify = fimc_md_link_notify;
1377 fmd->media_dev.dev = dev;
1378
1379 v4l2_dev = &fmd->v4l2_dev;
1380 v4l2_dev->mdev = &fmd->media_dev;
1381 v4l2_dev->notify = fimc_sensor_notify;
1382 strlcpy(v4l2_dev->name, "s5p-fimc-md", sizeof(v4l2_dev->name));
1383
1384 fmd->use_isp = fimc_md_is_isp_available(dev->of_node);
1385
1386 ret = v4l2_device_register(dev, &fmd->v4l2_dev);
1387 if (ret < 0) {
1388 v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret);
1389 return ret;
1390 }
1391 ret = media_device_register(&fmd->media_dev);
1392 if (ret < 0) {
1393 v4l2_err(v4l2_dev, "Failed to register media device: %d\n", ret);
1394 goto err_md;
1395 }
1396 ret = fimc_md_get_clocks(fmd);
1397 if (ret)
1398 goto err_clk;
1399
1400 fmd->user_subdev_api = (dev->of_node != NULL);
1401
1402 /* Protect the media graph while we're registering entities */
1403 mutex_lock(&fmd->media_dev.graph_mutex);
1404
1405 ret = fimc_md_get_pinctrl(fmd);
1406 if (ret < 0) {
1407 if (ret != EPROBE_DEFER)
1408 dev_err(dev, "Failed to get pinctrl: %d\n", ret);
1409 goto err_unlock;
1410 }
1411
1412 if (dev->of_node)
1413 ret = fimc_md_register_of_platform_entities(fmd, dev->of_node);
1414 else
1415 ret = bus_for_each_dev(&platform_bus_type, NULL, fmd,
1416 fimc_md_pdev_match);
1417 if (ret)
1418 goto err_unlock;
1419
1420 if (dev->platform_data || dev->of_node) {
1421 ret = fimc_md_register_sensor_entities(fmd);
1422 if (ret)
1423 goto err_unlock;
1424 }
1425
1426 ret = fimc_md_create_links(fmd);
1427 if (ret)
1428 goto err_unlock;
1429 ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev);
1430 if (ret)
1431 goto err_unlock;
1432
1433 ret = device_create_file(&pdev->dev, &dev_attr_subdev_conf_mode);
1434 if (ret)
1435 goto err_unlock;
1436
1437 platform_set_drvdata(pdev, fmd);
1438 mutex_unlock(&fmd->media_dev.graph_mutex);
1439 return 0;
1440
1441err_unlock:
1442 mutex_unlock(&fmd->media_dev.graph_mutex);
1443err_clk:
1444 media_device_unregister(&fmd->media_dev);
1445 fimc_md_put_clocks(fmd);
1446 fimc_md_unregister_entities(fmd);
1447err_md:
1448 v4l2_device_unregister(&fmd->v4l2_dev);
1449 return ret;
1450}
1451
1452static int fimc_md_remove(struct platform_device *pdev)
1453{
1454 struct fimc_md *fmd = platform_get_drvdata(pdev);
1455
1456 if (!fmd)
1457 return 0;
1458 device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode);
1459 fimc_md_unregister_entities(fmd);
1460 media_device_unregister(&fmd->media_dev);
1461 fimc_md_put_clocks(fmd);
1462 return 0;
1463}
1464
1465static struct platform_device_id fimc_driver_ids[] __always_unused = {
1466 { .name = "s5p-fimc-md" },
1467 { },
1468};
1469MODULE_DEVICE_TABLE(platform, fimc_driver_ids);
1470
1471static const struct of_device_id fimc_md_of_match[] = {
1472 { .compatible = "samsung,fimc" },
1473 { },
1474};
1475MODULE_DEVICE_TABLE(of, fimc_md_of_match);
1476
1477static struct platform_driver fimc_md_driver = {
1478 .probe = fimc_md_probe,
1479 .remove = fimc_md_remove,
1480 .driver = {
1481 .of_match_table = of_match_ptr(fimc_md_of_match),
1482 .name = "s5p-fimc-md",
1483 .owner = THIS_MODULE,
1484 }
1485};
1486
1487static int __init fimc_md_init(void)
1488{
1489 int ret;
1490
1491 request_module("s5p-csis");
1492 ret = fimc_register_driver();
1493 if (ret)
1494 return ret;
1495
1496 return platform_driver_register(&fimc_md_driver);
1497}
1498
1499static void __exit fimc_md_exit(void)
1500{
1501 platform_driver_unregister(&fimc_md_driver);
1502 fimc_unregister_driver();
1503}
1504
1505module_init(fimc_md_init);
1506module_exit(fimc_md_exit);
1507
1508MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
1509MODULE_DESCRIPTION("S5P FIMC camera host interface/video postprocessor driver");
1510MODULE_LICENSE("GPL");
1511MODULE_VERSION("2.0.1");
diff --git a/drivers/media/platform/exynos4-is/media-dev.h b/drivers/media/platform/exynos4-is/media-dev.h
new file mode 100644
index 000000000000..44d86b61d660
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/media-dev.h
@@ -0,0 +1,152 @@
1/*
2 * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef FIMC_MDEVICE_H_
10#define FIMC_MDEVICE_H_
11
12#include <linux/clk.h>
13#include <linux/platform_device.h>
14#include <linux/mutex.h>
15#include <linux/of.h>
16#include <linux/pinctrl/consumer.h>
17#include <media/media-device.h>
18#include <media/media-entity.h>
19#include <media/v4l2-device.h>
20#include <media/v4l2-subdev.h>
21
22#include "fimc-core.h"
23#include "fimc-lite.h"
24#include "mipi-csis.h"
25
26#define FIMC_OF_NODE_NAME "fimc"
27#define FIMC_LITE_OF_NODE_NAME "fimc-lite"
28#define FIMC_IS_OF_NODE_NAME "fimc-is"
29#define CSIS_OF_NODE_NAME "csis"
30
31#define PINCTRL_STATE_IDLE "idle"
32
33#define FIMC_MAX_SENSORS 8
34#define FIMC_MAX_CAMCLKS 2
35
36/* LCD/ISP Writeback clocks (PIXELASYNCMx) */
37enum {
38 CLK_IDX_WB_A,
39 CLK_IDX_WB_B,
40 FIMC_MAX_WBCLKS
41};
42
43struct fimc_csis_info {
44 struct v4l2_subdev *sd;
45 int id;
46};
47
48struct fimc_camclk_info {
49 struct clk *clock;
50 int use_count;
51 unsigned long frequency;
52};
53
54/**
55 * struct fimc_sensor_info - image data source subdev information
56 * @pdata: sensor's atrributes passed as media device's platform data
57 * @subdev: image sensor v4l2 subdev
58 * @host: fimc device the sensor is currently linked to
59 *
60 * This data structure applies to image sensor and the writeback subdevs.
61 */
62struct fimc_sensor_info {
63 struct fimc_source_info pdata;
64 struct v4l2_subdev *subdev;
65 struct fimc_dev *host;
66};
67
68/**
69 * struct fimc_md - fimc media device information
70 * @csis: MIPI CSIS subdevs data
71 * @sensor: array of registered sensor subdevs
72 * @num_sensors: actual number of registered sensors
73 * @camclk: external sensor clock information
74 * @fimc: array of registered fimc devices
75 * @fimc_is: fimc-is data structure
76 * @use_isp: set to true when FIMC-IS subsystem is used
77 * @pmf: handle to the CAMCLK clock control FIMC helper device
78 * @media_dev: top level media device
79 * @v4l2_dev: top level v4l2_device holding up the subdevs
80 * @pdev: platform device this media device is hooked up into
81 * @pinctrl: camera port pinctrl handle
82 * @state_default: pinctrl default state handle
83 * @state_idle: pinctrl idle state handle
84 * @user_subdev_api: true if subdevs are not configured by the host driver
85 * @slock: spinlock protecting @sensor array
86 */
87struct fimc_md {
88 struct fimc_csis_info csis[CSIS_MAX_ENTITIES];
89 struct fimc_sensor_info sensor[FIMC_MAX_SENSORS];
90 int num_sensors;
91 struct fimc_camclk_info camclk[FIMC_MAX_CAMCLKS];
92 struct clk *wbclk[FIMC_MAX_WBCLKS];
93 struct fimc_lite *fimc_lite[FIMC_LITE_MAX_DEVS];
94 struct fimc_dev *fimc[FIMC_MAX_DEVS];
95 struct fimc_is *fimc_is;
96 bool use_isp;
97 struct device *pmf;
98 struct media_device media_dev;
99 struct v4l2_device v4l2_dev;
100 struct platform_device *pdev;
101 struct fimc_pinctrl {
102 struct pinctrl *pinctrl;
103 struct pinctrl_state *state_default;
104 struct pinctrl_state *state_idle;
105 } pinctl;
106 bool user_subdev_api;
107 spinlock_t slock;
108};
109
110#define is_subdev_pad(pad) (pad == NULL || \
111 media_entity_type(pad->entity) == MEDIA_ENT_T_V4L2_SUBDEV)
112
113#define me_subtype(me) \
114 ((me->type) & (MEDIA_ENT_TYPE_MASK | MEDIA_ENT_SUBTYPE_MASK))
115
116#define subdev_has_devnode(__sd) (__sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE)
117
118static inline
119struct fimc_sensor_info *source_to_sensor_info(struct fimc_source_info *si)
120{
121 return container_of(si, struct fimc_sensor_info, pdata);
122}
123
124static inline struct fimc_md *entity_to_fimc_mdev(struct media_entity *me)
125{
126 return me->parent == NULL ? NULL :
127 container_of(me->parent, struct fimc_md, media_dev);
128}
129
130static inline void fimc_md_graph_lock(struct fimc_dev *fimc)
131{
132 mutex_lock(&fimc->vid_cap.vfd.entity.parent->graph_mutex);
133}
134
135static inline void fimc_md_graph_unlock(struct fimc_dev *fimc)
136{
137 mutex_unlock(&fimc->vid_cap.vfd.entity.parent->graph_mutex);
138}
139
140int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on);
141
142#ifdef CONFIG_OF
143static inline bool fimc_md_is_isp_available(struct device_node *node)
144{
145 node = of_get_child_by_name(node, FIMC_IS_OF_NODE_NAME);
146 return node ? of_device_is_available(node) : false;
147}
148#else
149#define fimc_md_is_isp_available(node) (false)
150#endif /* CONFIG_OF */
151
152#endif
diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c
new file mode 100644
index 000000000000..a2eda9d5ac87
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/mipi-csis.c
@@ -0,0 +1,1019 @@
1/*
2 * Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver
3 *
4 * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd.
5 * Sylwester Nawrocki <s.nawrocki@samsung.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#include <linux/clk.h>
13#include <linux/delay.h>
14#include <linux/device.h>
15#include <linux/errno.h>
16#include <linux/interrupt.h>
17#include <linux/io.h>
18#include <linux/irq.h>
19#include <linux/kernel.h>
20#include <linux/memory.h>
21#include <linux/module.h>
22#include <linux/of.h>
23#include <linux/platform_data/mipi-csis.h>
24#include <linux/platform_device.h>
25#include <linux/pm_runtime.h>
26#include <linux/regulator/consumer.h>
27#include <linux/slab.h>
28#include <linux/spinlock.h>
29#include <linux/videodev2.h>
30#include <media/s5p_fimc.h>
31#include <media/v4l2-of.h>
32#include <media/v4l2-subdev.h>
33
34#include "mipi-csis.h"
35
36static int debug;
37module_param(debug, int, 0644);
38MODULE_PARM_DESC(debug, "Debug level (0-2)");
39
40/* Register map definition */
41
42/* CSIS global control */
43#define S5PCSIS_CTRL 0x00
44#define S5PCSIS_CTRL_DPDN_DEFAULT (0 << 31)
45#define S5PCSIS_CTRL_DPDN_SWAP (1 << 31)
46#define S5PCSIS_CTRL_ALIGN_32BIT (1 << 20)
47#define S5PCSIS_CTRL_UPDATE_SHADOW (1 << 16)
48#define S5PCSIS_CTRL_WCLK_EXTCLK (1 << 8)
49#define S5PCSIS_CTRL_RESET (1 << 4)
50#define S5PCSIS_CTRL_ENABLE (1 << 0)
51
52/* D-PHY control */
53#define S5PCSIS_DPHYCTRL 0x04
54#define S5PCSIS_DPHYCTRL_HSS_MASK (0x1f << 27)
55#define S5PCSIS_DPHYCTRL_ENABLE (0x1f << 0)
56
57#define S5PCSIS_CONFIG 0x08
58#define S5PCSIS_CFG_FMT_YCBCR422_8BIT (0x1e << 2)
59#define S5PCSIS_CFG_FMT_RAW8 (0x2a << 2)
60#define S5PCSIS_CFG_FMT_RAW10 (0x2b << 2)
61#define S5PCSIS_CFG_FMT_RAW12 (0x2c << 2)
62/* User defined formats, x = 1...4 */
63#define S5PCSIS_CFG_FMT_USER(x) ((0x30 + x - 1) << 2)
64#define S5PCSIS_CFG_FMT_MASK (0x3f << 2)
65#define S5PCSIS_CFG_NR_LANE_MASK 3
66
67/* Interrupt mask */
68#define S5PCSIS_INTMSK 0x10
69#define S5PCSIS_INTMSK_EN_ALL 0xf000103f
70#define S5PCSIS_INTMSK_EVEN_BEFORE (1 << 31)
71#define S5PCSIS_INTMSK_EVEN_AFTER (1 << 30)
72#define S5PCSIS_INTMSK_ODD_BEFORE (1 << 29)
73#define S5PCSIS_INTMSK_ODD_AFTER (1 << 28)
74#define S5PCSIS_INTMSK_ERR_SOT_HS (1 << 12)
75#define S5PCSIS_INTMSK_ERR_LOST_FS (1 << 5)
76#define S5PCSIS_INTMSK_ERR_LOST_FE (1 << 4)
77#define S5PCSIS_INTMSK_ERR_OVER (1 << 3)
78#define S5PCSIS_INTMSK_ERR_ECC (1 << 2)
79#define S5PCSIS_INTMSK_ERR_CRC (1 << 1)
80#define S5PCSIS_INTMSK_ERR_UNKNOWN (1 << 0)
81
82/* Interrupt source */
83#define S5PCSIS_INTSRC 0x14
84#define S5PCSIS_INTSRC_EVEN_BEFORE (1 << 31)
85#define S5PCSIS_INTSRC_EVEN_AFTER (1 << 30)
86#define S5PCSIS_INTSRC_EVEN (0x3 << 30)
87#define S5PCSIS_INTSRC_ODD_BEFORE (1 << 29)
88#define S5PCSIS_INTSRC_ODD_AFTER (1 << 28)
89#define S5PCSIS_INTSRC_ODD (0x3 << 28)
90#define S5PCSIS_INTSRC_NON_IMAGE_DATA (0xff << 28)
91#define S5PCSIS_INTSRC_ERR_SOT_HS (0xf << 12)
92#define S5PCSIS_INTSRC_ERR_LOST_FS (1 << 5)
93#define S5PCSIS_INTSRC_ERR_LOST_FE (1 << 4)
94#define S5PCSIS_INTSRC_ERR_OVER (1 << 3)
95#define S5PCSIS_INTSRC_ERR_ECC (1 << 2)
96#define S5PCSIS_INTSRC_ERR_CRC (1 << 1)
97#define S5PCSIS_INTSRC_ERR_UNKNOWN (1 << 0)
98#define S5PCSIS_INTSRC_ERRORS 0xf03f
99
100/* Pixel resolution */
101#define S5PCSIS_RESOL 0x2c
102#define CSIS_MAX_PIX_WIDTH 0xffff
103#define CSIS_MAX_PIX_HEIGHT 0xffff
104
105/* Non-image packet data buffers */
106#define S5PCSIS_PKTDATA_ODD 0x2000
107#define S5PCSIS_PKTDATA_EVEN 0x3000
108#define S5PCSIS_PKTDATA_SIZE SZ_4K
109
110enum {
111 CSIS_CLK_MUX,
112 CSIS_CLK_GATE,
113};
114
115static char *csi_clock_name[] = {
116 [CSIS_CLK_MUX] = "sclk_csis",
117 [CSIS_CLK_GATE] = "csis",
118};
119#define NUM_CSIS_CLOCKS ARRAY_SIZE(csi_clock_name)
120#define DEFAULT_SCLK_CSIS_FREQ 166000000UL
121
122static const char * const csis_supply_name[] = {
123 "vddcore", /* CSIS Core (1.0V, 1.1V or 1.2V) suppply */
124 "vddio", /* CSIS I/O and PLL (1.8V) supply */
125};
126#define CSIS_NUM_SUPPLIES ARRAY_SIZE(csis_supply_name)
127
128enum {
129 ST_POWERED = 1,
130 ST_STREAMING = 2,
131 ST_SUSPENDED = 4,
132};
133
134struct s5pcsis_event {
135 u32 mask;
136 const char * const name;
137 unsigned int counter;
138};
139
140static const struct s5pcsis_event s5pcsis_events[] = {
141 /* Errors */
142 { S5PCSIS_INTSRC_ERR_SOT_HS, "SOT Error" },
143 { S5PCSIS_INTSRC_ERR_LOST_FS, "Lost Frame Start Error" },
144 { S5PCSIS_INTSRC_ERR_LOST_FE, "Lost Frame End Error" },
145 { S5PCSIS_INTSRC_ERR_OVER, "FIFO Overflow Error" },
146 { S5PCSIS_INTSRC_ERR_ECC, "ECC Error" },
147 { S5PCSIS_INTSRC_ERR_CRC, "CRC Error" },
148 { S5PCSIS_INTSRC_ERR_UNKNOWN, "Unknown Error" },
149 /* Non-image data receive events */
150 { S5PCSIS_INTSRC_EVEN_BEFORE, "Non-image data before even frame" },
151 { S5PCSIS_INTSRC_EVEN_AFTER, "Non-image data after even frame" },
152 { S5PCSIS_INTSRC_ODD_BEFORE, "Non-image data before odd frame" },
153 { S5PCSIS_INTSRC_ODD_AFTER, "Non-image data after odd frame" },
154};
155#define S5PCSIS_NUM_EVENTS ARRAY_SIZE(s5pcsis_events)
156
157struct csis_pktbuf {
158 u32 *data;
159 unsigned int len;
160};
161
162/**
163 * struct csis_state - the driver's internal state data structure
164 * @lock: mutex serializing the subdev and power management operations,
165 * protecting @format and @flags members
166 * @pads: CSIS pads array
167 * @sd: v4l2_subdev associated with CSIS device instance
168 * @index: the hardware instance index
169 * @pdev: CSIS platform device
170 * @regs: mmaped I/O registers memory
171 * @supplies: CSIS regulator supplies
172 * @clock: CSIS clocks
173 * @irq: requested s5p-mipi-csis irq number
174 * @flags: the state variable for power and streaming control
175 * @clock_frequency: device bus clock frequency
176 * @hs_settle: HS-RX settle time
177 * @num_lanes: number of MIPI-CSI data lanes used
178 * @max_num_lanes: maximum number of MIPI-CSI data lanes supported
179 * @wclk_ext: CSI wrapper clock: 0 - bus clock, 1 - external SCLK_CAM
180 * @csis_fmt: current CSIS pixel format
181 * @format: common media bus format for the source and sink pad
182 * @slock: spinlock protecting structure members below
183 * @pkt_buf: the frame embedded (non-image) data buffer
184 * @events: MIPI-CSIS event (error) counters
185 */
186struct csis_state {
187 struct mutex lock;
188 struct media_pad pads[CSIS_PADS_NUM];
189 struct v4l2_subdev sd;
190 u8 index;
191 struct platform_device *pdev;
192 void __iomem *regs;
193 struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES];
194 struct clk *clock[NUM_CSIS_CLOCKS];
195 int irq;
196 u32 flags;
197
198 u32 clk_frequency;
199 u32 hs_settle;
200 u32 num_lanes;
201 u32 max_num_lanes;
202 u8 wclk_ext;
203
204 const struct csis_pix_format *csis_fmt;
205 struct v4l2_mbus_framefmt format;
206
207 spinlock_t slock;
208 struct csis_pktbuf pkt_buf;
209 struct s5pcsis_event events[S5PCSIS_NUM_EVENTS];
210};
211
212/**
213 * struct csis_pix_format - CSIS pixel format description
214 * @pix_width_alignment: horizontal pixel alignment, width will be
215 * multiple of 2^pix_width_alignment
216 * @code: corresponding media bus code
217 * @fmt_reg: S5PCSIS_CONFIG register value
218 * @data_alignment: MIPI-CSI data alignment in bits
219 */
220struct csis_pix_format {
221 unsigned int pix_width_alignment;
222 enum v4l2_mbus_pixelcode code;
223 u32 fmt_reg;
224 u8 data_alignment;
225};
226
227static const struct csis_pix_format s5pcsis_formats[] = {
228 {
229 .code = V4L2_MBUS_FMT_VYUY8_2X8,
230 .fmt_reg = S5PCSIS_CFG_FMT_YCBCR422_8BIT,
231 .data_alignment = 32,
232 }, {
233 .code = V4L2_MBUS_FMT_JPEG_1X8,
234 .fmt_reg = S5PCSIS_CFG_FMT_USER(1),
235 .data_alignment = 32,
236 }, {
237 .code = V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8,
238 .fmt_reg = S5PCSIS_CFG_FMT_USER(1),
239 .data_alignment = 32,
240 }, {
241 .code = V4L2_MBUS_FMT_SGRBG8_1X8,
242 .fmt_reg = S5PCSIS_CFG_FMT_RAW8,
243 .data_alignment = 24,
244 }, {
245 .code = V4L2_MBUS_FMT_SGRBG10_1X10,
246 .fmt_reg = S5PCSIS_CFG_FMT_RAW10,
247 .data_alignment = 24,
248 }, {
249 .code = V4L2_MBUS_FMT_SGRBG12_1X12,
250 .fmt_reg = S5PCSIS_CFG_FMT_RAW12,
251 .data_alignment = 24,
252 }
253};
254
255#define s5pcsis_write(__csis, __r, __v) writel(__v, __csis->regs + __r)
256#define s5pcsis_read(__csis, __r) readl(__csis->regs + __r)
257
258static struct csis_state *sd_to_csis_state(struct v4l2_subdev *sdev)
259{
260 return container_of(sdev, struct csis_state, sd);
261}
262
263static const struct csis_pix_format *find_csis_format(
264 struct v4l2_mbus_framefmt *mf)
265{
266 int i;
267
268 for (i = 0; i < ARRAY_SIZE(s5pcsis_formats); i++)
269 if (mf->code == s5pcsis_formats[i].code)
270 return &s5pcsis_formats[i];
271 return NULL;
272}
273
274static void s5pcsis_enable_interrupts(struct csis_state *state, bool on)
275{
276 u32 val = s5pcsis_read(state, S5PCSIS_INTMSK);
277
278 val = on ? val | S5PCSIS_INTMSK_EN_ALL :
279 val & ~S5PCSIS_INTMSK_EN_ALL;
280 s5pcsis_write(state, S5PCSIS_INTMSK, val);
281}
282
283static void s5pcsis_reset(struct csis_state *state)
284{
285 u32 val = s5pcsis_read(state, S5PCSIS_CTRL);
286
287 s5pcsis_write(state, S5PCSIS_CTRL, val | S5PCSIS_CTRL_RESET);
288 udelay(10);
289}
290
291static void s5pcsis_system_enable(struct csis_state *state, int on)
292{
293 u32 val, mask;
294
295 val = s5pcsis_read(state, S5PCSIS_CTRL);
296 if (on)
297 val |= S5PCSIS_CTRL_ENABLE;
298 else
299 val &= ~S5PCSIS_CTRL_ENABLE;
300 s5pcsis_write(state, S5PCSIS_CTRL, val);
301
302 val = s5pcsis_read(state, S5PCSIS_DPHYCTRL);
303 val &= ~S5PCSIS_DPHYCTRL_ENABLE;
304 if (on) {
305 mask = (1 << (state->num_lanes + 1)) - 1;
306 val |= (mask & S5PCSIS_DPHYCTRL_ENABLE);
307 }
308 s5pcsis_write(state, S5PCSIS_DPHYCTRL, val);
309}
310
311/* Called with the state.lock mutex held */
312static void __s5pcsis_set_format(struct csis_state *state)
313{
314 struct v4l2_mbus_framefmt *mf = &state->format;
315 u32 val;
316
317 v4l2_dbg(1, debug, &state->sd, "fmt: %#x, %d x %d\n",
318 mf->code, mf->width, mf->height);
319
320 /* Color format */
321 val = s5pcsis_read(state, S5PCSIS_CONFIG);
322 val = (val & ~S5PCSIS_CFG_FMT_MASK) | state->csis_fmt->fmt_reg;
323 s5pcsis_write(state, S5PCSIS_CONFIG, val);
324
325 /* Pixel resolution */
326 val = (mf->width << 16) | mf->height;
327 s5pcsis_write(state, S5PCSIS_RESOL, val);
328}
329
330static void s5pcsis_set_hsync_settle(struct csis_state *state, int settle)
331{
332 u32 val = s5pcsis_read(state, S5PCSIS_DPHYCTRL);
333
334 val = (val & ~S5PCSIS_DPHYCTRL_HSS_MASK) | (settle << 27);
335 s5pcsis_write(state, S5PCSIS_DPHYCTRL, val);
336}
337
338static void s5pcsis_set_params(struct csis_state *state)
339{
340 u32 val;
341
342 val = s5pcsis_read(state, S5PCSIS_CONFIG);
343 val = (val & ~S5PCSIS_CFG_NR_LANE_MASK) | (state->num_lanes - 1);
344 s5pcsis_write(state, S5PCSIS_CONFIG, val);
345
346 __s5pcsis_set_format(state);
347 s5pcsis_set_hsync_settle(state, state->hs_settle);
348
349 val = s5pcsis_read(state, S5PCSIS_CTRL);
350 if (state->csis_fmt->data_alignment == 32)
351 val |= S5PCSIS_CTRL_ALIGN_32BIT;
352 else /* 24-bits */
353 val &= ~S5PCSIS_CTRL_ALIGN_32BIT;
354
355 val &= ~S5PCSIS_CTRL_WCLK_EXTCLK;
356 if (state->wclk_ext)
357 val |= S5PCSIS_CTRL_WCLK_EXTCLK;
358 s5pcsis_write(state, S5PCSIS_CTRL, val);
359
360 /* Update the shadow register. */
361 val = s5pcsis_read(state, S5PCSIS_CTRL);
362 s5pcsis_write(state, S5PCSIS_CTRL, val | S5PCSIS_CTRL_UPDATE_SHADOW);
363}
364
365static void s5pcsis_clk_put(struct csis_state *state)
366{
367 int i;
368
369 for (i = 0; i < NUM_CSIS_CLOCKS; i++) {
370 if (IS_ERR(state->clock[i]))
371 continue;
372 clk_unprepare(state->clock[i]);
373 clk_put(state->clock[i]);
374 state->clock[i] = ERR_PTR(-EINVAL);
375 }
376}
377
378static int s5pcsis_clk_get(struct csis_state *state)
379{
380 struct device *dev = &state->pdev->dev;
381 int i, ret;
382
383 for (i = 0; i < NUM_CSIS_CLOCKS; i++)
384 state->clock[i] = ERR_PTR(-EINVAL);
385
386 for (i = 0; i < NUM_CSIS_CLOCKS; i++) {
387 state->clock[i] = clk_get(dev, csi_clock_name[i]);
388 if (IS_ERR(state->clock[i])) {
389 ret = PTR_ERR(state->clock[i]);
390 goto err;
391 }
392 ret = clk_prepare(state->clock[i]);
393 if (ret < 0) {
394 clk_put(state->clock[i]);
395 state->clock[i] = ERR_PTR(-EINVAL);
396 goto err;
397 }
398 }
399 return 0;
400err:
401 s5pcsis_clk_put(state);
402 dev_err(dev, "failed to get clock: %s\n", csi_clock_name[i]);
403 return ret;
404}
405
406static void dump_regs(struct csis_state *state, const char *label)
407{
408 struct {
409 u32 offset;
410 const char * const name;
411 } registers[] = {
412 { 0x00, "CTRL" },
413 { 0x04, "DPHYCTRL" },
414 { 0x08, "CONFIG" },
415 { 0x0c, "DPHYSTS" },
416 { 0x10, "INTMSK" },
417 { 0x2c, "RESOL" },
418 { 0x38, "SDW_CONFIG" },
419 };
420 u32 i;
421
422 v4l2_info(&state->sd, "--- %s ---\n", label);
423
424 for (i = 0; i < ARRAY_SIZE(registers); i++) {
425 u32 cfg = s5pcsis_read(state, registers[i].offset);
426 v4l2_info(&state->sd, "%10s: 0x%08x\n", registers[i].name, cfg);
427 }
428}
429
430static void s5pcsis_start_stream(struct csis_state *state)
431{
432 s5pcsis_reset(state);
433 s5pcsis_set_params(state);
434 s5pcsis_system_enable(state, true);
435 s5pcsis_enable_interrupts(state, true);
436}
437
438static void s5pcsis_stop_stream(struct csis_state *state)
439{
440 s5pcsis_enable_interrupts(state, false);
441 s5pcsis_system_enable(state, false);
442}
443
444static void s5pcsis_clear_counters(struct csis_state *state)
445{
446 unsigned long flags;
447 int i;
448
449 spin_lock_irqsave(&state->slock, flags);
450 for (i = 0; i < S5PCSIS_NUM_EVENTS; i++)
451 state->events[i].counter = 0;
452 spin_unlock_irqrestore(&state->slock, flags);
453}
454
455static void s5pcsis_log_counters(struct csis_state *state, bool non_errors)
456{
457 int i = non_errors ? S5PCSIS_NUM_EVENTS : S5PCSIS_NUM_EVENTS - 4;
458 unsigned long flags;
459
460 spin_lock_irqsave(&state->slock, flags);
461
462 for (i--; i >= 0; i--) {
463 if (state->events[i].counter > 0 || debug)
464 v4l2_info(&state->sd, "%s events: %d\n",
465 state->events[i].name,
466 state->events[i].counter);
467 }
468 spin_unlock_irqrestore(&state->slock, flags);
469}
470
471/*
472 * V4L2 subdev operations
473 */
474static int s5pcsis_s_power(struct v4l2_subdev *sd, int on)
475{
476 struct csis_state *state = sd_to_csis_state(sd);
477 struct device *dev = &state->pdev->dev;
478
479 if (on)
480 return pm_runtime_get_sync(dev);
481
482 return pm_runtime_put_sync(dev);
483}
484
485static int s5pcsis_s_stream(struct v4l2_subdev *sd, int enable)
486{
487 struct csis_state *state = sd_to_csis_state(sd);
488 int ret = 0;
489
490 v4l2_dbg(1, debug, sd, "%s: %d, state: 0x%x\n",
491 __func__, enable, state->flags);
492
493 if (enable) {
494 s5pcsis_clear_counters(state);
495 ret = pm_runtime_get_sync(&state->pdev->dev);
496 if (ret && ret != 1)
497 return ret;
498 }
499
500 mutex_lock(&state->lock);
501 if (enable) {
502 if (state->flags & ST_SUSPENDED) {
503 ret = -EBUSY;
504 goto unlock;
505 }
506 s5pcsis_start_stream(state);
507 state->flags |= ST_STREAMING;
508 } else {
509 s5pcsis_stop_stream(state);
510 state->flags &= ~ST_STREAMING;
511 if (debug > 0)
512 s5pcsis_log_counters(state, true);
513 }
514unlock:
515 mutex_unlock(&state->lock);
516 if (!enable)
517 pm_runtime_put(&state->pdev->dev);
518
519 return ret == 1 ? 0 : ret;
520}
521
522static int s5pcsis_enum_mbus_code(struct v4l2_subdev *sd,
523 struct v4l2_subdev_fh *fh,
524 struct v4l2_subdev_mbus_code_enum *code)
525{
526 if (code->index >= ARRAY_SIZE(s5pcsis_formats))
527 return -EINVAL;
528
529 code->code = s5pcsis_formats[code->index].code;
530 return 0;
531}
532
533static struct csis_pix_format const *s5pcsis_try_format(
534 struct v4l2_mbus_framefmt *mf)
535{
536 struct csis_pix_format const *csis_fmt;
537
538 csis_fmt = find_csis_format(mf);
539 if (csis_fmt == NULL)
540 csis_fmt = &s5pcsis_formats[0];
541
542 mf->code = csis_fmt->code;
543 v4l_bound_align_image(&mf->width, 1, CSIS_MAX_PIX_WIDTH,
544 csis_fmt->pix_width_alignment,
545 &mf->height, 1, CSIS_MAX_PIX_HEIGHT, 1,
546 0);
547 return csis_fmt;
548}
549
550static struct v4l2_mbus_framefmt *__s5pcsis_get_format(
551 struct csis_state *state, struct v4l2_subdev_fh *fh,
552 enum v4l2_subdev_format_whence which)
553{
554 if (which == V4L2_SUBDEV_FORMAT_TRY)
555 return fh ? v4l2_subdev_get_try_format(fh, 0) : NULL;
556
557 return &state->format;
558}
559
560static int s5pcsis_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
561 struct v4l2_subdev_format *fmt)
562{
563 struct csis_state *state = sd_to_csis_state(sd);
564 struct csis_pix_format const *csis_fmt;
565 struct v4l2_mbus_framefmt *mf;
566
567 mf = __s5pcsis_get_format(state, fh, fmt->which);
568
569 if (fmt->pad == CSIS_PAD_SOURCE) {
570 if (mf) {
571 mutex_lock(&state->lock);
572 fmt->format = *mf;
573 mutex_unlock(&state->lock);
574 }
575 return 0;
576 }
577 csis_fmt = s5pcsis_try_format(&fmt->format);
578 if (mf) {
579 mutex_lock(&state->lock);
580 *mf = fmt->format;
581 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
582 state->csis_fmt = csis_fmt;
583 mutex_unlock(&state->lock);
584 }
585 return 0;
586}
587
588static int s5pcsis_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
589 struct v4l2_subdev_format *fmt)
590{
591 struct csis_state *state = sd_to_csis_state(sd);
592 struct v4l2_mbus_framefmt *mf;
593
594 mf = __s5pcsis_get_format(state, fh, fmt->which);
595 if (!mf)
596 return -EINVAL;
597
598 mutex_lock(&state->lock);
599 fmt->format = *mf;
600 mutex_unlock(&state->lock);
601 return 0;
602}
603
604static int s5pcsis_s_rx_buffer(struct v4l2_subdev *sd, void *buf,
605 unsigned int *size)
606{
607 struct csis_state *state = sd_to_csis_state(sd);
608 unsigned long flags;
609
610 *size = min_t(unsigned int, *size, S5PCSIS_PKTDATA_SIZE);
611
612 spin_lock_irqsave(&state->slock, flags);
613 state->pkt_buf.data = buf;
614 state->pkt_buf.len = *size;
615 spin_unlock_irqrestore(&state->slock, flags);
616
617 return 0;
618}
619
620static int s5pcsis_log_status(struct v4l2_subdev *sd)
621{
622 struct csis_state *state = sd_to_csis_state(sd);
623
624 mutex_lock(&state->lock);
625 s5pcsis_log_counters(state, true);
626 if (debug && (state->flags & ST_POWERED))
627 dump_regs(state, __func__);
628 mutex_unlock(&state->lock);
629 return 0;
630}
631
632static int s5pcsis_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
633{
634 struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
635
636 format->colorspace = V4L2_COLORSPACE_JPEG;
637 format->code = s5pcsis_formats[0].code;
638 format->width = S5PCSIS_DEF_PIX_WIDTH;
639 format->height = S5PCSIS_DEF_PIX_HEIGHT;
640 format->field = V4L2_FIELD_NONE;
641
642 return 0;
643}
644
645static const struct v4l2_subdev_internal_ops s5pcsis_sd_internal_ops = {
646 .open = s5pcsis_open,
647};
648
649static struct v4l2_subdev_core_ops s5pcsis_core_ops = {
650 .s_power = s5pcsis_s_power,
651 .log_status = s5pcsis_log_status,
652};
653
654static struct v4l2_subdev_pad_ops s5pcsis_pad_ops = {
655 .enum_mbus_code = s5pcsis_enum_mbus_code,
656 .get_fmt = s5pcsis_get_fmt,
657 .set_fmt = s5pcsis_set_fmt,
658};
659
660static struct v4l2_subdev_video_ops s5pcsis_video_ops = {
661 .s_rx_buffer = s5pcsis_s_rx_buffer,
662 .s_stream = s5pcsis_s_stream,
663};
664
665static struct v4l2_subdev_ops s5pcsis_subdev_ops = {
666 .core = &s5pcsis_core_ops,
667 .pad = &s5pcsis_pad_ops,
668 .video = &s5pcsis_video_ops,
669};
670
671static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id)
672{
673 struct csis_state *state = dev_id;
674 struct csis_pktbuf *pktbuf = &state->pkt_buf;
675 unsigned long flags;
676 u32 status;
677
678 status = s5pcsis_read(state, S5PCSIS_INTSRC);
679 spin_lock_irqsave(&state->slock, flags);
680
681 if ((status & S5PCSIS_INTSRC_NON_IMAGE_DATA) && pktbuf->data) {
682 u32 offset;
683
684 if (status & S5PCSIS_INTSRC_EVEN)
685 offset = S5PCSIS_PKTDATA_EVEN;
686 else
687 offset = S5PCSIS_PKTDATA_ODD;
688
689 memcpy(pktbuf->data, state->regs + offset, pktbuf->len);
690 pktbuf->data = NULL;
691 rmb();
692 }
693
694 /* Update the event/error counters */
695 if ((status & S5PCSIS_INTSRC_ERRORS) || debug) {
696 int i;
697 for (i = 0; i < S5PCSIS_NUM_EVENTS; i++) {
698 if (!(status & state->events[i].mask))
699 continue;
700 state->events[i].counter++;
701 v4l2_dbg(2, debug, &state->sd, "%s: %d\n",
702 state->events[i].name,
703 state->events[i].counter);
704 }
705 v4l2_dbg(2, debug, &state->sd, "status: %08x\n", status);
706 }
707 spin_unlock_irqrestore(&state->slock, flags);
708
709 s5pcsis_write(state, S5PCSIS_INTSRC, status);
710 return IRQ_HANDLED;
711}
712
713static int s5pcsis_get_platform_data(struct platform_device *pdev,
714 struct csis_state *state)
715{
716 struct s5p_platform_mipi_csis *pdata = pdev->dev.platform_data;
717
718 if (pdata == NULL) {
719 dev_err(&pdev->dev, "Platform data not specified\n");
720 return -EINVAL;
721 }
722
723 state->clk_frequency = pdata->clk_rate;
724 state->num_lanes = pdata->lanes;
725 state->hs_settle = pdata->hs_settle;
726 state->index = max(0, pdev->id);
727 state->max_num_lanes = state->index ? CSIS1_MAX_LANES :
728 CSIS0_MAX_LANES;
729 return 0;
730}
731
732#ifdef CONFIG_OF
733static int s5pcsis_parse_dt(struct platform_device *pdev,
734 struct csis_state *state)
735{
736 struct device_node *node = pdev->dev.of_node;
737 struct v4l2_of_endpoint endpoint;
738
739 if (of_property_read_u32(node, "clock-frequency",
740 &state->clk_frequency))
741 state->clk_frequency = DEFAULT_SCLK_CSIS_FREQ;
742 if (of_property_read_u32(node, "bus-width",
743 &state->max_num_lanes))
744 return -EINVAL;
745
746 node = v4l2_of_get_next_endpoint(node, NULL);
747 if (!node) {
748 dev_err(&pdev->dev, "No port node at %s\n",
749 node->full_name);
750 return -EINVAL;
751 }
752 /* Get port node and validate MIPI-CSI channel id. */
753 v4l2_of_parse_endpoint(node, &endpoint);
754
755 state->index = endpoint.port - FIMC_INPUT_MIPI_CSI2_0;
756 if (state->index < 0 || state->index >= CSIS_MAX_ENTITIES)
757 return -ENXIO;
758
759 /* Get MIPI CSI-2 bus configration from the endpoint node. */
760 of_property_read_u32(node, "samsung,csis-hs-settle",
761 &state->hs_settle);
762 state->wclk_ext = of_property_read_bool(node,
763 "samsung,csis-wclk");
764
765 state->num_lanes = endpoint.bus.mipi_csi2.num_data_lanes;
766
767 of_node_put(node);
768 return 0;
769}
770#else
771#define s5pcsis_parse_dt(pdev, state) (-ENOSYS)
772#endif
773
774static int s5pcsis_probe(struct platform_device *pdev)
775{
776 struct device *dev = &pdev->dev;
777 struct resource *mem_res;
778 struct csis_state *state;
779 int ret = -ENOMEM;
780 int i;
781
782 state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
783 if (!state)
784 return -ENOMEM;
785
786 mutex_init(&state->lock);
787 spin_lock_init(&state->slock);
788 state->pdev = pdev;
789
790 if (dev->of_node)
791 ret = s5pcsis_parse_dt(pdev, state);
792 else
793 ret = s5pcsis_get_platform_data(pdev, state);
794 if (ret < 0)
795 return ret;
796
797 if (state->num_lanes == 0 || state->num_lanes > state->max_num_lanes) {
798 dev_err(dev, "Unsupported number of data lanes: %d (max. %d)\n",
799 state->num_lanes, state->max_num_lanes);
800 return -EINVAL;
801 }
802
803 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
804 state->regs = devm_ioremap_resource(dev, mem_res);
805 if (IS_ERR(state->regs))
806 return PTR_ERR(state->regs);
807
808 state->irq = platform_get_irq(pdev, 0);
809 if (state->irq < 0) {
810 dev_err(dev, "Failed to get irq\n");
811 return state->irq;
812 }
813
814 for (i = 0; i < CSIS_NUM_SUPPLIES; i++)
815 state->supplies[i].supply = csis_supply_name[i];
816
817 ret = devm_regulator_bulk_get(dev, CSIS_NUM_SUPPLIES,
818 state->supplies);
819 if (ret)
820 return ret;
821
822 ret = s5pcsis_clk_get(state);
823 if (ret < 0)
824 return ret;
825
826 if (state->clk_frequency)
827 ret = clk_set_rate(state->clock[CSIS_CLK_MUX],
828 state->clk_frequency);
829 else
830 dev_WARN(dev, "No clock frequency specified!\n");
831 if (ret < 0)
832 goto e_clkput;
833
834 ret = clk_enable(state->clock[CSIS_CLK_MUX]);
835 if (ret < 0)
836 goto e_clkput;
837
838 ret = devm_request_irq(dev, state->irq, s5pcsis_irq_handler,
839 0, dev_name(dev), state);
840 if (ret) {
841 dev_err(dev, "Interrupt request failed\n");
842 goto e_clkdis;
843 }
844
845 v4l2_subdev_init(&state->sd, &s5pcsis_subdev_ops);
846 state->sd.owner = THIS_MODULE;
847 snprintf(state->sd.name, sizeof(state->sd.name), "%s.%d",
848 CSIS_SUBDEV_NAME, state->index);
849 state->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
850 state->csis_fmt = &s5pcsis_formats[0];
851
852 state->format.code = s5pcsis_formats[0].code;
853 state->format.width = S5PCSIS_DEF_PIX_WIDTH;
854 state->format.height = S5PCSIS_DEF_PIX_HEIGHT;
855
856 state->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
857 state->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
858 ret = media_entity_init(&state->sd.entity,
859 CSIS_PADS_NUM, state->pads, 0);
860 if (ret < 0)
861 goto e_clkdis;
862
863 /* This allows to retrieve the platform device id by the host driver */
864 v4l2_set_subdevdata(&state->sd, pdev);
865
866 /* .. and a pointer to the subdev. */
867 platform_set_drvdata(pdev, &state->sd);
868 memcpy(state->events, s5pcsis_events, sizeof(state->events));
869 pm_runtime_enable(dev);
870
871 dev_info(&pdev->dev, "lanes: %d, hs_settle: %d, wclk: %d, freq: %u\n",
872 state->num_lanes, state->hs_settle, state->wclk_ext,
873 state->clk_frequency);
874 return 0;
875
876e_clkdis:
877 clk_disable(state->clock[CSIS_CLK_MUX]);
878e_clkput:
879 s5pcsis_clk_put(state);
880 return ret;
881}
882
883static int s5pcsis_pm_suspend(struct device *dev, bool runtime)
884{
885 struct platform_device *pdev = to_platform_device(dev);
886 struct v4l2_subdev *sd = platform_get_drvdata(pdev);
887 struct csis_state *state = sd_to_csis_state(sd);
888 int ret = 0;
889
890 v4l2_dbg(1, debug, sd, "%s: flags: 0x%x\n",
891 __func__, state->flags);
892
893 mutex_lock(&state->lock);
894 if (state->flags & ST_POWERED) {
895 s5pcsis_stop_stream(state);
896 ret = s5p_csis_phy_enable(state->index, false);
897 if (ret)
898 goto unlock;
899 ret = regulator_bulk_disable(CSIS_NUM_SUPPLIES,
900 state->supplies);
901 if (ret)
902 goto unlock;
903 clk_disable(state->clock[CSIS_CLK_GATE]);
904 state->flags &= ~ST_POWERED;
905 if (!runtime)
906 state->flags |= ST_SUSPENDED;
907 }
908 unlock:
909 mutex_unlock(&state->lock);
910 return ret ? -EAGAIN : 0;
911}
912
913static int s5pcsis_pm_resume(struct device *dev, bool runtime)
914{
915 struct platform_device *pdev = to_platform_device(dev);
916 struct v4l2_subdev *sd = platform_get_drvdata(pdev);
917 struct csis_state *state = sd_to_csis_state(sd);
918 int ret = 0;
919
920 v4l2_dbg(1, debug, sd, "%s: flags: 0x%x\n",
921 __func__, state->flags);
922
923 mutex_lock(&state->lock);
924 if (!runtime && !(state->flags & ST_SUSPENDED))
925 goto unlock;
926
927 if (!(state->flags & ST_POWERED)) {
928 ret = regulator_bulk_enable(CSIS_NUM_SUPPLIES,
929 state->supplies);
930 if (ret)
931 goto unlock;
932 ret = s5p_csis_phy_enable(state->index, true);
933 if (!ret) {
934 state->flags |= ST_POWERED;
935 } else {
936 regulator_bulk_disable(CSIS_NUM_SUPPLIES,
937 state->supplies);
938 goto unlock;
939 }
940 clk_enable(state->clock[CSIS_CLK_GATE]);
941 }
942 if (state->flags & ST_STREAMING)
943 s5pcsis_start_stream(state);
944
945 state->flags &= ~ST_SUSPENDED;
946 unlock:
947 mutex_unlock(&state->lock);
948 return ret ? -EAGAIN : 0;
949}
950
951#ifdef CONFIG_PM_SLEEP
952static int s5pcsis_suspend(struct device *dev)
953{
954 return s5pcsis_pm_suspend(dev, false);
955}
956
957static int s5pcsis_resume(struct device *dev)
958{
959 return s5pcsis_pm_resume(dev, false);
960}
961#endif
962
963#ifdef CONFIG_PM_RUNTIME
964static int s5pcsis_runtime_suspend(struct device *dev)
965{
966 return s5pcsis_pm_suspend(dev, true);
967}
968
969static int s5pcsis_runtime_resume(struct device *dev)
970{
971 return s5pcsis_pm_resume(dev, true);
972}
973#endif
974
975static int s5pcsis_remove(struct platform_device *pdev)
976{
977 struct v4l2_subdev *sd = platform_get_drvdata(pdev);
978 struct csis_state *state = sd_to_csis_state(sd);
979
980 pm_runtime_disable(&pdev->dev);
981 s5pcsis_pm_suspend(&pdev->dev, false);
982 clk_disable(state->clock[CSIS_CLK_MUX]);
983 pm_runtime_set_suspended(&pdev->dev);
984 s5pcsis_clk_put(state);
985
986 media_entity_cleanup(&state->sd.entity);
987
988 return 0;
989}
990
991static const struct dev_pm_ops s5pcsis_pm_ops = {
992 SET_RUNTIME_PM_OPS(s5pcsis_runtime_suspend, s5pcsis_runtime_resume,
993 NULL)
994 SET_SYSTEM_SLEEP_PM_OPS(s5pcsis_suspend, s5pcsis_resume)
995};
996
997static const struct of_device_id s5pcsis_of_match[] = {
998 { .compatible = "samsung,s5pv210-csis" },
999 { .compatible = "samsung,exynos4210-csis" },
1000 { /* sentinel */ },
1001};
1002MODULE_DEVICE_TABLE(of, s5pcsis_of_match);
1003
1004static struct platform_driver s5pcsis_driver = {
1005 .probe = s5pcsis_probe,
1006 .remove = s5pcsis_remove,
1007 .driver = {
1008 .of_match_table = s5pcsis_of_match,
1009 .name = CSIS_DRIVER_NAME,
1010 .owner = THIS_MODULE,
1011 .pm = &s5pcsis_pm_ops,
1012 },
1013};
1014
1015module_platform_driver(s5pcsis_driver);
1016
1017MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
1018MODULE_DESCRIPTION("Samsung S5P/EXYNOS SoC MIPI-CSI2 receiver driver");
1019MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/exynos4-is/mipi-csis.h b/drivers/media/platform/exynos4-is/mipi-csis.h
new file mode 100644
index 000000000000..28c11c4085d8
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/mipi-csis.h
@@ -0,0 +1,26 @@
1/*
2 * Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver
3 *
4 * Copyright (C) 2011 Samsung Electronics Co., Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#ifndef S5P_MIPI_CSIS_H_
11#define S5P_MIPI_CSIS_H_
12
13#define CSIS_DRIVER_NAME "s5p-mipi-csis"
14#define CSIS_SUBDEV_NAME CSIS_DRIVER_NAME
15#define CSIS_MAX_ENTITIES 2
16#define CSIS0_MAX_LANES 4
17#define CSIS1_MAX_LANES 2
18
19#define CSIS_PAD_SINK 0
20#define CSIS_PAD_SOURCE 1
21#define CSIS_PADS_NUM 2
22
23#define S5PCSIS_DEF_PIX_WIDTH 640
24#define S5PCSIS_DEF_PIX_HEIGHT 480
25
26#endif