aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorSylwester Nawrocki <s.nawrocki@samsung.com>2012-04-27 04:29:05 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-05-20 08:26:24 -0400
commit4af813108b880e96a4b8b01e162f950a4aaa2475 (patch)
tree43d66e2ed014d2cf9101a242b957644f4d055d75 /drivers/media/video
parent5af86c2691b9e0fc1f993cdcd4aa27eb684c1c17 (diff)
[media] s5p-fimc: Add support for Exynos4x12 FIMC-LITE
This patch adds driver for FIMC-LITE camera host interface. This new IP differs from the regular FIMC IP in that it doesn't have input DMA, scaler and color space conversion support. So it just plain camera host interface for MIPI-CSI2 and ITU-R interfaces. For the serial bus support it interworks with MIPI-CSIS and the exisiting s5p-csis driver. The FIMC-LITE and MIPI-CSIS drivers can also be reused in the Exynos5 SoC series. Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/Kconfig24
-rw-r--r--drivers/media/video/s5p-fimc/Kconfig48
-rw-r--r--drivers/media/video/s5p-fimc/Makefile4
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.h1
-rw-r--r--drivers/media/video/s5p-fimc/fimc-lite.c1576
-rw-r--r--drivers/media/video/s5p-fimc/fimc-mdevice.c152
-rw-r--r--drivers/media/video/s5p-fimc/fimc-mdevice.h5
7 files changed, 1766 insertions, 44 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 3dc0ea7ba927..268b36db1411 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -1130,19 +1130,6 @@ config VIDEO_MX2
1130 This is a v4l2 driver for the i.MX27 and the i.MX25 Camera Sensor 1130 This is a v4l2 driver for the i.MX27 and the i.MX25 Camera Sensor
1131 Interface 1131 Interface
1132 1132
1133config VIDEO_SAMSUNG_S5P_FIMC
1134 tristate "Samsung S5P and EXYNOS4 camera interface driver (EXPERIMENTAL)"
1135 depends on VIDEO_V4L2 && I2C && PLAT_S5P && PM_RUNTIME && \
1136 VIDEO_V4L2_SUBDEV_API && EXPERIMENTAL
1137 select VIDEOBUF2_DMA_CONTIG
1138 select V4L2_MEM2MEM_DEV
1139 ---help---
1140 This is a v4l2 driver for Samsung S5P and EXYNOS4 camera
1141 host interface and video postprocessor.
1142
1143 To compile this driver as a module, choose M here: the
1144 module will be called s5p-fimc.
1145
1146config VIDEO_ATMEL_ISI 1133config VIDEO_ATMEL_ISI
1147 tristate "ATMEL Image Sensor Interface (ISI) support" 1134 tristate "ATMEL Image Sensor Interface (ISI) support"
1148 depends on VIDEO_DEV && SOC_CAMERA && ARCH_AT91 1135 depends on VIDEO_DEV && SOC_CAMERA && ARCH_AT91
@@ -1151,16 +1138,7 @@ config VIDEO_ATMEL_ISI
1151 This module makes the ATMEL Image Sensor Interface available 1138 This module makes the ATMEL Image Sensor Interface available
1152 as a v4l2 device. 1139 as a v4l2 device.
1153 1140
1154config VIDEO_S5P_MIPI_CSIS 1141source "drivers/media/video/s5p-fimc/Kconfig"
1155 tristate "Samsung S5P and EXYNOS4 MIPI CSI receiver driver"
1156 depends on VIDEO_V4L2 && PM_RUNTIME && PLAT_S5P
1157 depends on VIDEO_V4L2_SUBDEV_API && REGULATOR
1158 ---help---
1159 This is a v4l2 driver for Samsung S5P/EXYNOS4 MIPI-CSI receiver.
1160
1161 To compile this driver as a module, choose M here: the
1162 module will be called s5p-csis.
1163
1164source "drivers/media/video/s5p-tv/Kconfig" 1142source "drivers/media/video/s5p-tv/Kconfig"
1165 1143
1166endif # V4L_PLATFORM_DRIVERS 1144endif # V4L_PLATFORM_DRIVERS
diff --git a/drivers/media/video/s5p-fimc/Kconfig b/drivers/media/video/s5p-fimc/Kconfig
new file mode 100644
index 000000000000..a564f7eeb064
--- /dev/null
+++ b/drivers/media/video/s5p-fimc/Kconfig
@@ -0,0 +1,48 @@
1
2config VIDEO_SAMSUNG_S5P_FIMC
3 bool "Samsung S5P/EXYNOS SoC camera interface driver (experimental)"
4 depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && PLAT_S5P && PM_RUNTIME
5 depends on EXPERIMENTAL
6 help
7 Say Y here to enable camera host interface devices for
8 Samsung S5P and EXYNOS SoC series.
9
10if VIDEO_SAMSUNG_S5P_FIMC
11
12config VIDEO_S5P_FIMC
13 tristate "S5P/EXYNOS4 FIMC/CAMIF camera interface driver"
14 depends on I2C
15 select VIDEOBUF2_DMA_CONTIG
16 select V4L2_MEM2MEM_DEV
17 help
18 This is a V4L2 driver for Samsung S5P and EXYNOS4 SoC camera host
19 interface and video postprocessor (FIMC and FIMC-LITE) 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 help
28 This is a V4L2 driver for Samsung S5P and EXYNOS4 SoC MIPI-CSI2
29 receiver (MIPI-CSIS) devices.
30
31 To compile this driver as a module, choose M here: the
32 module will be called s5p-csis.
33
34if ARCH_EXYNOS
35
36config VIDEO_EXYNOS_FIMC_LITE
37 tristate "EXYNOS FIMC-LITE camera interface driver"
38 depends on I2C
39 select VIDEOBUF2_DMA_CONTIG
40 help
41 This is a V4L2 driver for Samsung EXYNOS4/5 SoC FIMC-LITE camera
42 host interface.
43
44 To compile this driver as a module, choose M here: the
45 module will be called exynos-fimc-lite.
46endif
47
48endif # VIDEO_SAMSUNG_S5P_FIMC
diff --git a/drivers/media/video/s5p-fimc/Makefile b/drivers/media/video/s5p-fimc/Makefile
index 1da3c6ae7fa8..46485143e1ca 100644
--- a/drivers/media/video/s5p-fimc/Makefile
+++ b/drivers/media/video/s5p-fimc/Makefile
@@ -1,5 +1,7 @@
1s5p-fimc-objs := fimc-core.o fimc-reg.o fimc-m2m.o fimc-capture.o fimc-mdevice.o 1s5p-fimc-objs := fimc-core.o fimc-reg.o fimc-m2m.o fimc-capture.o fimc-mdevice.o
2exynos-fimc-lite-objs += fimc-lite-reg.o fimc-lite.o
2s5p-csis-objs := mipi-csis.o 3s5p-csis-objs := mipi-csis.o
3 4
4obj-$(CONFIG_VIDEO_S5P_MIPI_CSIS) += s5p-csis.o 5obj-$(CONFIG_VIDEO_S5P_MIPI_CSIS) += s5p-csis.o
5obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) += s5p-fimc.o 6obj-$(CONFIG_VIDEO_EXYNOS_FIMC_LITE) += exynos-fimc-lite.o
7obj-$(CONFIG_VIDEO_S5P_FIMC) += s5p-fimc.o
diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h
index 97a25d2fac58..c67d485ecce6 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.h
+++ b/drivers/media/video/s5p-fimc/fimc-core.h
@@ -17,6 +17,7 @@
17#include <linux/types.h> 17#include <linux/types.h>
18#include <linux/videodev2.h> 18#include <linux/videodev2.h>
19#include <linux/io.h> 19#include <linux/io.h>
20#include <asm/sizes.h>
20 21
21#include <media/media-entity.h> 22#include <media/media-entity.h>
22#include <media/videobuf2-core.h> 23#include <media/videobuf2-core.h>
diff --git a/drivers/media/video/s5p-fimc/fimc-lite.c b/drivers/media/video/s5p-fimc/fimc-lite.c
new file mode 100644
index 000000000000..400d701aef04
--- /dev/null
+++ b/drivers/media/video/s5p-fimc/fimc-lite.c
@@ -0,0 +1,1576 @@
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/device.h>
15#include <linux/errno.h>
16#include <linux/interrupt.h>
17#include <linux/kernel.h>
18#include <linux/list.h>
19#include <linux/module.h>
20#include <linux/types.h>
21#include <linux/platform_device.h>
22#include <linux/pm_runtime.h>
23#include <linux/slab.h>
24#include <linux/videodev2.h>
25
26#include <media/v4l2-device.h>
27#include <media/v4l2-ioctl.h>
28#include <media/v4l2-mem2mem.h>
29#include <media/videobuf2-core.h>
30#include <media/videobuf2-dma-contig.h>
31
32#include "fimc-mdevice.h"
33#include "fimc-core.h"
34#include "fimc-lite-reg.h"
35
36static int debug;
37module_param(debug, int, 0644);
38
39static const struct fimc_fmt fimc_lite_formats[] = {
40 {
41 .name = "YUV 4:2:2 packed, YCbYCr",
42 .fourcc = V4L2_PIX_FMT_YUYV,
43 .depth = { 16 },
44 .color = FIMC_FMT_YCBYCR422,
45 .memplanes = 1,
46 .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
47 }, {
48 .name = "YUV 4:2:2 packed, CbYCrY",
49 .fourcc = V4L2_PIX_FMT_UYVY,
50 .depth = { 16 },
51 .color = FIMC_FMT_CBYCRY422,
52 .memplanes = 1,
53 .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8,
54 }, {
55 .name = "YUV 4:2:2 packed, CrYCbY",
56 .fourcc = V4L2_PIX_FMT_VYUY,
57 .depth = { 16 },
58 .color = FIMC_FMT_CRYCBY422,
59 .memplanes = 1,
60 .mbus_code = V4L2_MBUS_FMT_VYUY8_2X8,
61 }, {
62 .name = "YUV 4:2:2 packed, YCrYCb",
63 .fourcc = V4L2_PIX_FMT_YVYU,
64 .depth = { 16 },
65 .color = FIMC_FMT_YCRYCB422,
66 .memplanes = 1,
67 .mbus_code = V4L2_MBUS_FMT_YVYU8_2X8,
68 }, {
69 .name = "RAW8 (GRBG)",
70 .fourcc = V4L2_PIX_FMT_SGRBG8,
71 .depth = { 8 },
72 .color = FIMC_FMT_RAW8,
73 .memplanes = 1,
74 .mbus_code = V4L2_MBUS_FMT_SGRBG8_1X8,
75 }, {
76 .name = "RAW10 (GRBG)",
77 .fourcc = V4L2_PIX_FMT_SGRBG10,
78 .depth = { 10 },
79 .color = FIMC_FMT_RAW10,
80 .memplanes = 1,
81 .mbus_code = V4L2_MBUS_FMT_SGRBG10_1X10,
82 }, {
83 .name = "RAW12 (GRBG)",
84 .fourcc = V4L2_PIX_FMT_SGRBG12,
85 .depth = { 12 },
86 .color = FIMC_FMT_RAW12,
87 .memplanes = 1,
88 .mbus_code = V4L2_MBUS_FMT_SGRBG12_1X12,
89 },
90};
91
92/**
93 * fimc_lite_find_format - lookup fimc color format by fourcc or media bus code
94 * @pixelformat: fourcc to match, ignored if null
95 * @mbus_code: media bus code to match, ignored if null
96 * @index: index to the fimc_lite_formats array, ignored if negative
97 */
98static const struct fimc_fmt *fimc_lite_find_format(const u32 *pixelformat,
99 const u32 *mbus_code, int index)
100{
101 const struct fimc_fmt *fmt, *def_fmt = NULL;
102 unsigned int i;
103 int id = 0;
104
105 if (index >= (int)ARRAY_SIZE(fimc_lite_formats))
106 return NULL;
107
108 for (i = 0; i < ARRAY_SIZE(fimc_lite_formats); ++i) {
109 fmt = &fimc_lite_formats[i];
110 if (pixelformat && fmt->fourcc == *pixelformat)
111 return fmt;
112 if (mbus_code && fmt->mbus_code == *mbus_code)
113 return fmt;
114 if (index == id)
115 def_fmt = fmt;
116 id++;
117 }
118 return def_fmt;
119}
120
121static int fimc_lite_hw_init(struct fimc_lite *fimc)
122{
123 struct fimc_pipeline *pipeline = &fimc->pipeline;
124 struct fimc_sensor_info *sensor;
125 unsigned long flags;
126
127 if (pipeline->subdevs[IDX_SENSOR] == NULL)
128 return -ENXIO;
129
130 if (fimc->fmt == NULL)
131 return -EINVAL;
132
133 sensor = v4l2_get_subdev_hostdata(pipeline->subdevs[IDX_SENSOR]);
134 spin_lock_irqsave(&fimc->slock, flags);
135
136 flite_hw_set_camera_bus(fimc, sensor->pdata);
137 flite_hw_set_source_format(fimc, &fimc->inp_frame);
138 flite_hw_set_window_offset(fimc, &fimc->inp_frame);
139 flite_hw_set_output_dma(fimc, &fimc->out_frame, true);
140 flite_hw_set_interrupt_mask(fimc);
141 flite_hw_set_test_pattern(fimc, fimc->test_pattern->val);
142
143 if (debug > 0)
144 flite_hw_dump_regs(fimc, __func__);
145
146 spin_unlock_irqrestore(&fimc->slock, flags);
147 return 0;
148}
149
150/*
151 * Reinitialize the driver so it is ready to start the streaming again.
152 * Set fimc->state to indicate stream off and the hardware shut down state.
153 * If not suspending (@suspend is false), return any buffers to videobuf2.
154 * Otherwise put any owned buffers onto the pending buffers queue, so they
155 * can be re-spun when the device is being resumed. Also perform FIMC
156 * software reset and disable streaming on the whole pipeline if required.
157 */
158static int fimc_lite_reinit(struct fimc_lite *fimc, bool suspend)
159{
160 struct flite_buffer *buf;
161 unsigned long flags;
162 bool streaming;
163
164 spin_lock_irqsave(&fimc->slock, flags);
165 streaming = fimc->state & (1 << ST_SENSOR_STREAM);
166
167 fimc->state &= ~(1 << ST_FLITE_RUN | 1 << ST_FLITE_OFF |
168 1 << ST_FLITE_STREAM | 1 << ST_SENSOR_STREAM);
169 if (suspend)
170 fimc->state |= (1 << ST_FLITE_SUSPENDED);
171 else
172 fimc->state &= ~(1 << ST_FLITE_PENDING |
173 1 << ST_FLITE_SUSPENDED);
174
175 /* Release unused buffers */
176 while (!suspend && !list_empty(&fimc->pending_buf_q)) {
177 buf = fimc_lite_pending_queue_pop(fimc);
178 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
179 }
180 /* If suspending put unused buffers onto pending queue */
181 while (!list_empty(&fimc->active_buf_q)) {
182 buf = fimc_lite_active_queue_pop(fimc);
183 if (suspend)
184 fimc_lite_pending_queue_add(fimc, buf);
185 else
186 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
187 }
188
189 spin_unlock_irqrestore(&fimc->slock, flags);
190
191 flite_hw_reset(fimc);
192
193 if (!streaming)
194 return 0;
195
196 return fimc_pipeline_s_stream(&fimc->pipeline, 0);
197}
198
199static int fimc_lite_stop_capture(struct fimc_lite *fimc, bool suspend)
200{
201 unsigned long flags;
202
203 if (!fimc_lite_active(fimc))
204 return 0;
205
206 spin_lock_irqsave(&fimc->slock, flags);
207 set_bit(ST_FLITE_OFF, &fimc->state);
208 flite_hw_capture_stop(fimc);
209 spin_unlock_irqrestore(&fimc->slock, flags);
210
211 wait_event_timeout(fimc->irq_queue,
212 !test_bit(ST_FLITE_OFF, &fimc->state),
213 (2*HZ/10)); /* 200 ms */
214
215 return fimc_lite_reinit(fimc, suspend);
216}
217
218/* Must be called with fimc.slock spinlock held. */
219static void fimc_lite_config_update(struct fimc_lite *fimc)
220{
221 flite_hw_set_window_offset(fimc, &fimc->inp_frame);
222 flite_hw_set_dma_window(fimc, &fimc->out_frame);
223 flite_hw_set_test_pattern(fimc, fimc->test_pattern->val);
224 clear_bit(ST_FLITE_CONFIG, &fimc->state);
225}
226
227static irqreturn_t flite_irq_handler(int irq, void *priv)
228{
229 struct fimc_lite *fimc = priv;
230 struct flite_buffer *vbuf;
231 unsigned long flags;
232 struct timeval *tv;
233 struct timespec ts;
234 u32 intsrc;
235
236 spin_lock_irqsave(&fimc->slock, flags);
237
238 intsrc = flite_hw_get_interrupt_source(fimc);
239 flite_hw_clear_pending_irq(fimc);
240
241 if (test_and_clear_bit(ST_FLITE_OFF, &fimc->state)) {
242 wake_up(&fimc->irq_queue);
243 goto done;
244 }
245
246 if (intsrc & FLITE_REG_CISTATUS_IRQ_SRC_OVERFLOW) {
247 clear_bit(ST_FLITE_RUN, &fimc->state);
248 fimc->events.data_overflow++;
249 }
250
251 if (intsrc & FLITE_REG_CISTATUS_IRQ_SRC_LASTCAPEND) {
252 flite_hw_clear_last_capture_end(fimc);
253 clear_bit(ST_FLITE_STREAM, &fimc->state);
254 wake_up(&fimc->irq_queue);
255 }
256
257 if (fimc->out_path != FIMC_IO_DMA)
258 goto done;
259
260 if ((intsrc & FLITE_REG_CISTATUS_IRQ_SRC_FRMSTART) &&
261 test_bit(ST_FLITE_RUN, &fimc->state) &&
262 !list_empty(&fimc->active_buf_q) &&
263 !list_empty(&fimc->pending_buf_q)) {
264 vbuf = fimc_lite_active_queue_pop(fimc);
265 ktime_get_ts(&ts);
266 tv = &vbuf->vb.v4l2_buf.timestamp;
267 tv->tv_sec = ts.tv_sec;
268 tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
269 vbuf->vb.v4l2_buf.sequence = fimc->frame_count++;
270 vb2_buffer_done(&vbuf->vb, VB2_BUF_STATE_DONE);
271
272 vbuf = fimc_lite_pending_queue_pop(fimc);
273 flite_hw_set_output_addr(fimc, vbuf->paddr);
274 fimc_lite_active_queue_add(fimc, vbuf);
275 }
276
277 if (test_bit(ST_FLITE_CONFIG, &fimc->state))
278 fimc_lite_config_update(fimc);
279
280 if (list_empty(&fimc->pending_buf_q)) {
281 flite_hw_capture_stop(fimc);
282 clear_bit(ST_FLITE_STREAM, &fimc->state);
283 }
284done:
285 set_bit(ST_FLITE_RUN, &fimc->state);
286 spin_unlock_irqrestore(&fimc->slock, flags);
287 return IRQ_HANDLED;
288}
289
290static int start_streaming(struct vb2_queue *q, unsigned int count)
291{
292 struct fimc_lite *fimc = q->drv_priv;
293 int ret;
294
295 fimc->frame_count = 0;
296
297 ret = fimc_lite_hw_init(fimc);
298 if (ret) {
299 fimc_lite_reinit(fimc, false);
300 return ret;
301 }
302
303 set_bit(ST_FLITE_PENDING, &fimc->state);
304
305 if (!list_empty(&fimc->active_buf_q) &&
306 !test_and_set_bit(ST_FLITE_STREAM, &fimc->state)) {
307 flite_hw_capture_start(fimc);
308
309 if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state))
310 fimc_pipeline_s_stream(&fimc->pipeline, 1);
311 }
312 if (debug > 0)
313 flite_hw_dump_regs(fimc, __func__);
314
315 return 0;
316}
317
318static int stop_streaming(struct vb2_queue *q)
319{
320 struct fimc_lite *fimc = q->drv_priv;
321
322 if (!fimc_lite_active(fimc))
323 return -EINVAL;
324
325 return fimc_lite_stop_capture(fimc, false);
326}
327
328static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
329 unsigned int *num_buffers, unsigned int *num_planes,
330 unsigned int sizes[], void *allocators[])
331{
332 const struct v4l2_pix_format_mplane *pixm = NULL;
333 struct fimc_lite *fimc = vq->drv_priv;
334 struct flite_frame *frame = &fimc->out_frame;
335 const struct fimc_fmt *fmt = fimc->fmt;
336 unsigned long wh;
337 int i;
338
339 if (pfmt) {
340 pixm = &pfmt->fmt.pix_mp;
341 fmt = fimc_lite_find_format(&pixm->pixelformat, NULL, -1);
342 wh = pixm->width * pixm->height;
343 } else {
344 wh = frame->f_width * frame->f_height;
345 }
346
347 if (fmt == NULL)
348 return -EINVAL;
349
350 *num_planes = fmt->memplanes;
351
352 for (i = 0; i < fmt->memplanes; i++) {
353 unsigned int size = (wh * fmt->depth[i]) / 8;
354 if (pixm)
355 sizes[i] = max(size, pixm->plane_fmt[i].sizeimage);
356 else
357 sizes[i] = size;
358 allocators[i] = fimc->alloc_ctx;
359 }
360
361 return 0;
362}
363
364static int buffer_prepare(struct vb2_buffer *vb)
365{
366 struct vb2_queue *vq = vb->vb2_queue;
367 struct fimc_lite *fimc = vq->drv_priv;
368 int i;
369
370 if (fimc->fmt == NULL)
371 return -EINVAL;
372
373 for (i = 0; i < fimc->fmt->memplanes; i++) {
374 unsigned long size = fimc->payload[i];
375
376 if (vb2_plane_size(vb, i) < size) {
377 v4l2_err(fimc->vfd,
378 "User buffer too small (%ld < %ld)\n",
379 vb2_plane_size(vb, i), size);
380 return -EINVAL;
381 }
382 vb2_set_plane_payload(vb, i, size);
383 }
384
385 return 0;
386}
387
388static void buffer_queue(struct vb2_buffer *vb)
389{
390 struct flite_buffer *buf
391 = container_of(vb, struct flite_buffer, vb);
392 struct fimc_lite *fimc = vb2_get_drv_priv(vb->vb2_queue);
393 unsigned long flags;
394
395 spin_lock_irqsave(&fimc->slock, flags);
396 buf->paddr = vb2_dma_contig_plane_dma_addr(vb, 0);
397
398 if (!test_bit(ST_FLITE_SUSPENDED, &fimc->state) &&
399 !test_bit(ST_FLITE_STREAM, &fimc->state) &&
400 list_empty(&fimc->active_buf_q)) {
401 flite_hw_set_output_addr(fimc, buf->paddr);
402 fimc_lite_active_queue_add(fimc, buf);
403 } else {
404 fimc_lite_pending_queue_add(fimc, buf);
405 }
406
407 if (vb2_is_streaming(&fimc->vb_queue) &&
408 !list_empty(&fimc->pending_buf_q) &&
409 !test_and_set_bit(ST_FLITE_STREAM, &fimc->state)) {
410 flite_hw_capture_start(fimc);
411 spin_unlock_irqrestore(&fimc->slock, flags);
412
413 if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state))
414 fimc_pipeline_s_stream(&fimc->pipeline, 1);
415 return;
416 }
417 spin_unlock_irqrestore(&fimc->slock, flags);
418}
419
420static void fimc_lock(struct vb2_queue *vq)
421{
422 struct fimc_lite *fimc = vb2_get_drv_priv(vq);
423 mutex_lock(&fimc->lock);
424}
425
426static void fimc_unlock(struct vb2_queue *vq)
427{
428 struct fimc_lite *fimc = vb2_get_drv_priv(vq);
429 mutex_unlock(&fimc->lock);
430}
431
432static const struct vb2_ops fimc_lite_qops = {
433 .queue_setup = queue_setup,
434 .buf_prepare = buffer_prepare,
435 .buf_queue = buffer_queue,
436 .wait_prepare = fimc_unlock,
437 .wait_finish = fimc_lock,
438 .start_streaming = start_streaming,
439 .stop_streaming = stop_streaming,
440};
441
442static void fimc_lite_clear_event_counters(struct fimc_lite *fimc)
443{
444 unsigned long flags;
445
446 spin_lock_irqsave(&fimc->slock, flags);
447 memset(&fimc->events, 0, sizeof(fimc->events));
448 spin_unlock_irqrestore(&fimc->slock, flags);
449}
450
451static int fimc_lite_open(struct file *file)
452{
453 struct fimc_lite *fimc = video_drvdata(file);
454 int ret = v4l2_fh_open(file);
455
456 if (ret)
457 return ret;
458
459 set_bit(ST_FLITE_IN_USE, &fimc->state);
460 pm_runtime_get_sync(&fimc->pdev->dev);
461
462 if (++fimc->ref_count != 1 || fimc->out_path != FIMC_IO_DMA)
463 return ret;
464
465 ret = fimc_pipeline_initialize(&fimc->pipeline, &fimc->vfd->entity,
466 true);
467 if (ret < 0) {
468 v4l2_err(fimc->vfd, "Video pipeline initialization failed\n");
469 pm_runtime_put_sync(&fimc->pdev->dev);
470 fimc->ref_count--;
471 v4l2_fh_release(file);
472 clear_bit(ST_FLITE_IN_USE, &fimc->state);
473 }
474
475 fimc_lite_clear_event_counters(fimc);
476 return ret;
477}
478
479static int fimc_lite_close(struct file *file)
480{
481 struct fimc_lite *fimc = video_drvdata(file);
482
483 if (--fimc->ref_count == 0 && fimc->out_path == FIMC_IO_DMA) {
484 clear_bit(ST_FLITE_IN_USE, &fimc->state);
485 fimc_lite_stop_capture(fimc, false);
486 fimc_pipeline_shutdown(&fimc->pipeline);
487 clear_bit(ST_FLITE_SUSPENDED, &fimc->state);
488 }
489
490 pm_runtime_put(&fimc->pdev->dev);
491
492 if (fimc->ref_count == 0)
493 vb2_queue_release(&fimc->vb_queue);
494
495 return v4l2_fh_release(file);
496}
497
498static unsigned int fimc_lite_poll(struct file *file,
499 struct poll_table_struct *wait)
500{
501 struct fimc_lite *fimc = video_drvdata(file);
502 return vb2_poll(&fimc->vb_queue, file, wait);
503}
504
505static int fimc_lite_mmap(struct file *file, struct vm_area_struct *vma)
506{
507 struct fimc_lite *fimc = video_drvdata(file);
508 return vb2_mmap(&fimc->vb_queue, vma);
509}
510
511static const struct v4l2_file_operations fimc_lite_fops = {
512 .owner = THIS_MODULE,
513 .open = fimc_lite_open,
514 .release = fimc_lite_close,
515 .poll = fimc_lite_poll,
516 .unlocked_ioctl = video_ioctl2,
517 .mmap = fimc_lite_mmap,
518};
519
520/*
521 * Format and crop negotiation helpers
522 */
523
524static const struct fimc_fmt *fimc_lite_try_format(struct fimc_lite *fimc,
525 u32 *width, u32 *height,
526 u32 *code, u32 *fourcc, int pad)
527{
528 struct flite_variant *variant = fimc->variant;
529 const struct fimc_fmt *fmt;
530
531 fmt = fimc_lite_find_format(fourcc, code, 0);
532 if (WARN_ON(!fmt))
533 return NULL;
534
535 if (code)
536 *code = fmt->mbus_code;
537 if (fourcc)
538 *fourcc = fmt->fourcc;
539
540 if (pad == FLITE_SD_PAD_SINK) {
541 v4l_bound_align_image(width, 8, variant->max_width,
542 ffs(variant->out_width_align) - 1,
543 height, 0, variant->max_height, 0, 0);
544 } else {
545 v4l_bound_align_image(width, 8, fimc->inp_frame.rect.width,
546 ffs(variant->out_width_align) - 1,
547 height, 0, fimc->inp_frame.rect.height,
548 0, 0);
549 }
550
551 v4l2_dbg(1, debug, &fimc->subdev, "code: 0x%x, %dx%d\n",
552 code ? *code : 0, *width, *height);
553
554 return fmt;
555}
556
557static void fimc_lite_try_crop(struct fimc_lite *fimc, struct v4l2_rect *r)
558{
559 struct flite_frame *frame = &fimc->inp_frame;
560
561 v4l_bound_align_image(&r->width, 0, frame->f_width, 0,
562 &r->height, 0, frame->f_height, 0, 0);
563
564 /* Adjust left/top if cropping rectangle got out of bounds */
565 r->left = clamp_t(u32, r->left, 0, frame->f_width - r->width);
566 r->left = round_down(r->left, fimc->variant->win_hor_offs_align);
567 r->top = clamp_t(u32, r->top, 0, frame->f_height - r->height);
568
569 v4l2_dbg(1, debug, &fimc->subdev, "(%d,%d)/%dx%d, sink fmt: %dx%d",
570 r->left, r->top, r->width, r->height,
571 frame->f_width, frame->f_height);
572}
573
574static void fimc_lite_try_compose(struct fimc_lite *fimc, struct v4l2_rect *r)
575{
576 struct flite_frame *frame = &fimc->out_frame;
577 struct v4l2_rect *crop_rect = &fimc->inp_frame.rect;
578
579 /* Scaling is not supported so we enforce compose rectangle size
580 same as size of the sink crop rectangle. */
581 r->width = crop_rect->width;
582 r->height = crop_rect->height;
583
584 /* Adjust left/top if the composing rectangle got out of bounds */
585 r->left = clamp_t(u32, r->left, 0, frame->f_width - r->width);
586 r->left = round_down(r->left, fimc->variant->out_hor_offs_align);
587 r->top = clamp_t(u32, r->top, 0, fimc->out_frame.f_height - r->height);
588
589 v4l2_dbg(1, debug, &fimc->subdev, "(%d,%d)/%dx%d, source fmt: %dx%d",
590 r->left, r->top, r->width, r->height,
591 frame->f_width, frame->f_height);
592}
593
594/*
595 * Video node ioctl operations
596 */
597static int fimc_vidioc_querycap_capture(struct file *file, void *priv,
598 struct v4l2_capability *cap)
599{
600 strlcpy(cap->driver, FIMC_LITE_DRV_NAME, sizeof(cap->driver));
601 cap->bus_info[0] = 0;
602 cap->card[0] = 0;
603 cap->capabilities = V4L2_CAP_STREAMING;
604 return 0;
605}
606
607static int fimc_lite_enum_fmt_mplane(struct file *file, void *priv,
608 struct v4l2_fmtdesc *f)
609{
610 const struct fimc_fmt *fmt;
611
612 if (f->index >= ARRAY_SIZE(fimc_lite_formats))
613 return -EINVAL;
614
615 fmt = &fimc_lite_formats[f->index];
616 strlcpy(f->description, fmt->name, sizeof(f->description));
617 f->pixelformat = fmt->fourcc;
618
619 return 0;
620}
621
622static int fimc_lite_g_fmt_mplane(struct file *file, void *fh,
623 struct v4l2_format *f)
624{
625 struct fimc_lite *fimc = video_drvdata(file);
626 struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp;
627 struct v4l2_plane_pix_format *plane_fmt = &pixm->plane_fmt[0];
628 struct flite_frame *frame = &fimc->out_frame;
629 const struct fimc_fmt *fmt = fimc->fmt;
630
631 plane_fmt->bytesperline = (frame->f_width * fmt->depth[0]) / 8;
632 plane_fmt->sizeimage = plane_fmt->bytesperline * frame->f_height;
633
634 pixm->num_planes = fmt->memplanes;
635 pixm->pixelformat = fmt->fourcc;
636 pixm->width = frame->f_width;
637 pixm->height = frame->f_height;
638 pixm->field = V4L2_FIELD_NONE;
639 pixm->colorspace = V4L2_COLORSPACE_JPEG;
640 return 0;
641}
642
643static int fimc_lite_try_fmt(struct fimc_lite *fimc,
644 struct v4l2_pix_format_mplane *pixm,
645 const struct fimc_fmt **ffmt)
646{
647 struct flite_variant *variant = fimc->variant;
648 u32 bpl = pixm->plane_fmt[0].bytesperline;
649 const struct fimc_fmt *fmt;
650
651 fmt = fimc_lite_find_format(&pixm->pixelformat, NULL, 0);
652 if (WARN_ON(fmt == NULL))
653 return -EINVAL;
654 if (ffmt)
655 *ffmt = fmt;
656 v4l_bound_align_image(&pixm->width, 8, variant->max_width,
657 ffs(variant->out_width_align) - 1,
658 &pixm->height, 0, variant->max_height, 0, 0);
659
660 if ((bpl == 0 || ((bpl * 8) / fmt->depth[0]) < pixm->width))
661 pixm->plane_fmt[0].bytesperline = (pixm->width *
662 fmt->depth[0]) / 8;
663
664 if (pixm->plane_fmt[0].sizeimage == 0)
665 pixm->plane_fmt[0].sizeimage = (pixm->width * pixm->height *
666 fmt->depth[0]) / 8;
667 pixm->num_planes = fmt->memplanes;
668 pixm->pixelformat = fmt->fourcc;
669 pixm->colorspace = V4L2_COLORSPACE_JPEG;
670 pixm->field = V4L2_FIELD_NONE;
671 return 0;
672}
673
674static int fimc_lite_try_fmt_mplane(struct file *file, void *fh,
675 struct v4l2_format *f)
676{
677 struct fimc_lite *fimc = video_drvdata(file);
678
679 return fimc_lite_try_fmt(fimc, &f->fmt.pix_mp, NULL);
680}
681
682static int fimc_lite_s_fmt_mplane(struct file *file, void *priv,
683 struct v4l2_format *f)
684{
685 struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp;
686 struct fimc_lite *fimc = video_drvdata(file);
687 struct flite_frame *frame = &fimc->out_frame;
688 const struct fimc_fmt *fmt = NULL;
689 int ret;
690
691 if (vb2_is_busy(&fimc->vb_queue))
692 return -EBUSY;
693
694 ret = fimc_lite_try_fmt(fimc, &f->fmt.pix_mp, &fmt);
695 if (ret < 0)
696 return ret;
697
698 fimc->fmt = fmt;
699 fimc->payload[0] = max((pixm->width * pixm->height * fmt->depth[0]) / 8,
700 pixm->plane_fmt[0].sizeimage);
701 frame->f_width = pixm->width;
702 frame->f_height = pixm->height;
703
704 return 0;
705}
706
707static int fimc_pipeline_validate(struct fimc_lite *fimc)
708{
709 struct v4l2_subdev *sd = &fimc->subdev;
710 struct v4l2_subdev_format sink_fmt, src_fmt;
711 struct media_pad *pad;
712 int ret;
713
714 while (1) {
715 /* Retrieve format at the sink pad */
716 pad = &sd->entity.pads[0];
717 if (!(pad->flags & MEDIA_PAD_FL_SINK))
718 break;
719 /* Don't call FIMC subdev operation to avoid nested locking */
720 if (sd == &fimc->subdev) {
721 struct flite_frame *ff = &fimc->out_frame;
722 sink_fmt.format.width = ff->f_width;
723 sink_fmt.format.height = ff->f_height;
724 sink_fmt.format.code = fimc->fmt->mbus_code;
725 } else {
726 sink_fmt.pad = pad->index;
727 sink_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
728 ret = v4l2_subdev_call(sd, pad, get_fmt, NULL,
729 &sink_fmt);
730 if (ret < 0 && ret != -ENOIOCTLCMD)
731 return -EPIPE;
732 }
733 /* Retrieve format at the source pad */
734 pad = media_entity_remote_source(pad);
735 if (pad == NULL ||
736 media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
737 break;
738
739 sd = media_entity_to_v4l2_subdev(pad->entity);
740 src_fmt.pad = pad->index;
741 src_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
742 ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &src_fmt);
743 if (ret < 0 && ret != -ENOIOCTLCMD)
744 return -EPIPE;
745
746 if (src_fmt.format.width != sink_fmt.format.width ||
747 src_fmt.format.height != sink_fmt.format.height ||
748 src_fmt.format.code != sink_fmt.format.code)
749 return -EPIPE;
750 }
751 return 0;
752}
753
754static int fimc_lite_streamon(struct file *file, void *priv,
755 enum v4l2_buf_type type)
756{
757 struct fimc_lite *fimc = video_drvdata(file);
758 struct v4l2_subdev *sensor = fimc->pipeline.subdevs[IDX_SENSOR];
759 struct fimc_pipeline *p = &fimc->pipeline;
760 int ret;
761
762 if (fimc_lite_active(fimc))
763 return -EBUSY;
764
765 media_entity_pipeline_start(&sensor->entity, p->m_pipeline);
766
767 ret = fimc_pipeline_validate(fimc);
768 if (ret) {
769 media_entity_pipeline_stop(&sensor->entity);
770 return ret;
771 }
772
773 return vb2_streamon(&fimc->vb_queue, type);
774}
775
776static int fimc_lite_streamoff(struct file *file, void *priv,
777 enum v4l2_buf_type type)
778{
779 struct fimc_lite *fimc = video_drvdata(file);
780 struct v4l2_subdev *sd = fimc->pipeline.subdevs[IDX_SENSOR];
781 int ret;
782
783 ret = vb2_streamoff(&fimc->vb_queue, type);
784 if (ret == 0)
785 media_entity_pipeline_stop(&sd->entity);
786 return ret;
787}
788
789static int fimc_lite_reqbufs(struct file *file, void *priv,
790 struct v4l2_requestbuffers *reqbufs)
791{
792 struct fimc_lite *fimc = video_drvdata(file);
793 int ret;
794
795 reqbufs->count = max_t(u32, FLITE_REQ_BUFS_MIN, reqbufs->count);
796 ret = vb2_reqbufs(&fimc->vb_queue, reqbufs);
797 if (!ret < 0)
798 fimc->reqbufs_count = reqbufs->count;
799
800 return ret;
801}
802
803static int fimc_lite_querybuf(struct file *file, void *priv,
804 struct v4l2_buffer *buf)
805{
806 struct fimc_lite *fimc = video_drvdata(file);
807
808 return vb2_querybuf(&fimc->vb_queue, buf);
809}
810
811static int fimc_lite_qbuf(struct file *file, void *priv,
812 struct v4l2_buffer *buf)
813{
814 struct fimc_lite *fimc = video_drvdata(file);
815
816 return vb2_qbuf(&fimc->vb_queue, buf);
817}
818
819static int fimc_lite_dqbuf(struct file *file, void *priv,
820 struct v4l2_buffer *buf)
821{
822 struct fimc_lite *fimc = video_drvdata(file);
823
824 return vb2_dqbuf(&fimc->vb_queue, buf, file->f_flags & O_NONBLOCK);
825}
826
827static int fimc_lite_create_bufs(struct file *file, void *priv,
828 struct v4l2_create_buffers *create)
829{
830 struct fimc_lite *fimc = video_drvdata(file);
831
832 return vb2_create_bufs(&fimc->vb_queue, create);
833}
834
835static int fimc_lite_prepare_buf(struct file *file, void *priv,
836 struct v4l2_buffer *b)
837{
838 struct fimc_lite *fimc = video_drvdata(file);
839
840 return vb2_prepare_buf(&fimc->vb_queue, b);
841}
842
843/* Return 1 if rectangle a is enclosed in rectangle b, or 0 otherwise. */
844static int enclosed_rectangle(struct v4l2_rect *a, struct v4l2_rect *b)
845{
846 if (a->left < b->left || a->top < b->top)
847 return 0;
848 if (a->left + a->width > b->left + b->width)
849 return 0;
850 if (a->top + a->height > b->top + b->height)
851 return 0;
852
853 return 1;
854}
855
856static int fimc_lite_g_selection(struct file *file, void *fh,
857 struct v4l2_selection *sel)
858{
859 struct fimc_lite *fimc = video_drvdata(file);
860 struct flite_frame *f = &fimc->out_frame;
861
862 if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
863 return -EINVAL;
864
865 switch (sel->target) {
866 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
867 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
868 sel->r.left = 0;
869 sel->r.top = 0;
870 sel->r.width = f->f_width;
871 sel->r.height = f->f_height;
872 return 0;
873
874 case V4L2_SEL_TGT_COMPOSE_ACTIVE:
875 sel->r = f->rect;
876 return 0;
877 }
878
879 return -EINVAL;
880}
881
882static int fimc_lite_s_selection(struct file *file, void *fh,
883 struct v4l2_selection *sel)
884{
885 struct fimc_lite *fimc = video_drvdata(file);
886 struct flite_frame *f = &fimc->out_frame;
887 struct v4l2_rect rect = sel->r;
888 unsigned long flags;
889
890 if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ||
891 sel->target != V4L2_SEL_TGT_COMPOSE_ACTIVE)
892 return -EINVAL;
893
894 fimc_lite_try_compose(fimc, &rect);
895
896 if ((sel->flags & V4L2_SEL_FLAG_LE) &&
897 !enclosed_rectangle(&rect, &sel->r))
898 return -ERANGE;
899
900 if ((sel->flags & V4L2_SEL_FLAG_GE) &&
901 !enclosed_rectangle(&sel->r, &rect))
902 return -ERANGE;
903
904 sel->r = rect;
905 spin_lock_irqsave(&fimc->slock, flags);
906 f->rect = rect;
907 set_bit(ST_FLITE_CONFIG, &fimc->state);
908 spin_unlock_irqrestore(&fimc->slock, flags);
909
910 return 0;
911}
912
913static const struct v4l2_ioctl_ops fimc_lite_ioctl_ops = {
914 .vidioc_querycap = fimc_vidioc_querycap_capture,
915 .vidioc_enum_fmt_vid_cap_mplane = fimc_lite_enum_fmt_mplane,
916 .vidioc_try_fmt_vid_cap_mplane = fimc_lite_try_fmt_mplane,
917 .vidioc_s_fmt_vid_cap_mplane = fimc_lite_s_fmt_mplane,
918 .vidioc_g_fmt_vid_cap_mplane = fimc_lite_g_fmt_mplane,
919 .vidioc_g_selection = fimc_lite_g_selection,
920 .vidioc_s_selection = fimc_lite_s_selection,
921 .vidioc_reqbufs = fimc_lite_reqbufs,
922 .vidioc_querybuf = fimc_lite_querybuf,
923 .vidioc_prepare_buf = fimc_lite_prepare_buf,
924 .vidioc_create_bufs = fimc_lite_create_bufs,
925 .vidioc_qbuf = fimc_lite_qbuf,
926 .vidioc_dqbuf = fimc_lite_dqbuf,
927 .vidioc_streamon = fimc_lite_streamon,
928 .vidioc_streamoff = fimc_lite_streamoff,
929};
930
931/* Capture subdev media entity operations */
932static int fimc_lite_link_setup(struct media_entity *entity,
933 const struct media_pad *local,
934 const struct media_pad *remote, u32 flags)
935{
936 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
937 struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
938 unsigned int remote_ent_type = media_entity_type(remote->entity);
939
940 if (WARN_ON(fimc == NULL))
941 return 0;
942
943 v4l2_dbg(1, debug, sd, "%s: %s --> %s, flags: 0x%x. source_id: 0x%x",
944 __func__, local->entity->name, remote->entity->name,
945 flags, fimc->source_subdev_grp_id);
946
947 switch (local->index) {
948 case FIMC_SD_PAD_SINK:
949 if (remote_ent_type != MEDIA_ENT_T_V4L2_SUBDEV)
950 return -EINVAL;
951
952 if (flags & MEDIA_LNK_FL_ENABLED) {
953 if (fimc->source_subdev_grp_id != 0)
954 return -EBUSY;
955 fimc->source_subdev_grp_id = sd->grp_id;
956 return 0;
957 }
958
959 fimc->source_subdev_grp_id = 0;
960 break;
961
962 case FIMC_SD_PAD_SOURCE:
963 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
964 fimc->out_path = FIMC_IO_NONE;
965 return 0;
966 }
967 if (remote_ent_type == MEDIA_ENT_T_V4L2_SUBDEV)
968 fimc->out_path = FIMC_IO_ISP;
969 else
970 fimc->out_path = FIMC_IO_DMA;
971 break;
972
973 default:
974 v4l2_err(sd, "Invalid pad index\n");
975 return -EINVAL;
976 }
977
978 return 0;
979}
980
981static const struct media_entity_operations fimc_lite_subdev_media_ops = {
982 .link_setup = fimc_lite_link_setup,
983};
984
985static int fimc_lite_subdev_enum_mbus_code(struct v4l2_subdev *sd,
986 struct v4l2_subdev_fh *fh,
987 struct v4l2_subdev_mbus_code_enum *code)
988{
989 const struct fimc_fmt *fmt;
990
991 fmt = fimc_lite_find_format(NULL, NULL, code->index);
992 if (!fmt)
993 return -EINVAL;
994 code->code = fmt->mbus_code;
995 return 0;
996}
997
998static int fimc_lite_subdev_get_fmt(struct v4l2_subdev *sd,
999 struct v4l2_subdev_fh *fh,
1000 struct v4l2_subdev_format *fmt)
1001{
1002 struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
1003 struct v4l2_mbus_framefmt *mf = &fmt->format;
1004 struct flite_frame *f = &fimc->out_frame;
1005
1006 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
1007 mf = v4l2_subdev_get_try_format(fh, fmt->pad);
1008 fmt->format = *mf;
1009 return 0;
1010 }
1011 mf->colorspace = V4L2_COLORSPACE_JPEG;
1012
1013 mutex_lock(&fimc->lock);
1014 mf->code = fimc->fmt->mbus_code;
1015
1016 if (fmt->pad == FLITE_SD_PAD_SINK) {
1017 /* full camera input frame size */
1018 mf->width = f->f_width;
1019 mf->height = f->f_height;
1020 } else {
1021 /* crop size */
1022 mf->width = f->rect.width;
1023 mf->height = f->rect.height;
1024 }
1025 mutex_unlock(&fimc->lock);
1026 return 0;
1027}
1028
1029static int fimc_lite_subdev_set_fmt(struct v4l2_subdev *sd,
1030 struct v4l2_subdev_fh *fh,
1031 struct v4l2_subdev_format *fmt)
1032{
1033 struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
1034 struct v4l2_mbus_framefmt *mf = &fmt->format;
1035 struct flite_frame *sink = &fimc->inp_frame;
1036 const struct fimc_fmt *ffmt;
1037
1038 v4l2_dbg(1, debug, sd, "pad%d: code: 0x%x, %dx%d",
1039 fmt->pad, mf->code, mf->width, mf->height);
1040
1041 mf->colorspace = V4L2_COLORSPACE_JPEG;
1042 mutex_lock(&fimc->lock);
1043
1044 if ((fimc->out_path == FIMC_IO_ISP && sd->entity.stream_count > 0) ||
1045 (fimc->out_path == FIMC_IO_DMA && vb2_is_busy(&fimc->vb_queue))) {
1046 mutex_unlock(&fimc->lock);
1047 return -EBUSY;
1048 }
1049
1050 ffmt = fimc_lite_try_format(fimc, &mf->width, &mf->height,
1051 &mf->code, NULL, fmt->pad);
1052
1053 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
1054 mf = v4l2_subdev_get_try_format(fh, fmt->pad);
1055 *mf = fmt->format;
1056 mutex_unlock(&fimc->lock);
1057 return 0;
1058 }
1059
1060 if (fmt->pad == FLITE_SD_PAD_SINK) {
1061 sink->f_width = mf->width;
1062 sink->f_height = mf->height;
1063 fimc->fmt = ffmt;
1064 /* Set sink crop rectangle */
1065 sink->rect.width = mf->width;
1066 sink->rect.height = mf->height;
1067 sink->rect.left = 0;
1068 sink->rect.top = 0;
1069 /* Reset source crop rectangle */
1070 fimc->out_frame.rect = sink->rect;
1071 } else {
1072 /* Allow changing format only on sink pad */
1073 mf->code = fimc->fmt->mbus_code;
1074 mf->width = sink->rect.width;
1075 mf->height = sink->rect.height;
1076 }
1077
1078 mutex_unlock(&fimc->lock);
1079 return 0;
1080}
1081
1082static int fimc_lite_subdev_get_selection(struct v4l2_subdev *sd,
1083 struct v4l2_subdev_fh *fh,
1084 struct v4l2_subdev_selection *sel)
1085{
1086 struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
1087 struct flite_frame *f = &fimc->inp_frame;
1088
1089 if ((sel->target != V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL &&
1090 sel->target != V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS) ||
1091 sel->pad != FLITE_SD_PAD_SINK)
1092 return -EINVAL;
1093
1094 if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
1095 sel->r = *v4l2_subdev_get_try_crop(fh, sel->pad);
1096 return 0;
1097 }
1098
1099 mutex_lock(&fimc->lock);
1100 if (sel->target == V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL) {
1101 sel->r = f->rect;
1102 } else {
1103 sel->r.left = 0;
1104 sel->r.top = 0;
1105 sel->r.width = f->f_width;
1106 sel->r.height = f->f_height;
1107 }
1108 mutex_unlock(&fimc->lock);
1109
1110 v4l2_dbg(1, debug, sd, "%s: (%d,%d) %dx%d, f_w: %d, f_h: %d",
1111 __func__, f->rect.left, f->rect.top, f->rect.width,
1112 f->rect.height, f->f_width, f->f_height);
1113
1114 return 0;
1115}
1116
1117static int fimc_lite_subdev_set_selection(struct v4l2_subdev *sd,
1118 struct v4l2_subdev_fh *fh,
1119 struct v4l2_subdev_selection *sel)
1120{
1121 struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
1122 struct flite_frame *f = &fimc->inp_frame;
1123 int ret = 0;
1124
1125 if (sel->target != V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL ||
1126 sel->pad != FLITE_SD_PAD_SINK)
1127 return -EINVAL;
1128
1129 mutex_lock(&fimc->lock);
1130 fimc_lite_try_crop(fimc, &sel->r);
1131
1132 if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
1133 *v4l2_subdev_get_try_crop(fh, sel->pad) = sel->r;
1134 } else {
1135 unsigned long flags;
1136 spin_lock_irqsave(&fimc->slock, flags);
1137 f->rect = sel->r;
1138 /* Same crop rectangle on the source pad */
1139 fimc->out_frame.rect = sel->r;
1140 set_bit(ST_FLITE_CONFIG, &fimc->state);
1141 spin_unlock_irqrestore(&fimc->slock, flags);
1142 }
1143 mutex_unlock(&fimc->lock);
1144
1145 v4l2_dbg(1, debug, sd, "%s: (%d,%d) %dx%d, f_w: %d, f_h: %d",
1146 __func__, f->rect.left, f->rect.top, f->rect.width,
1147 f->rect.height, f->f_width, f->f_height);
1148
1149 return ret;
1150}
1151
1152static int fimc_lite_subdev_s_stream(struct v4l2_subdev *sd, int on)
1153{
1154 struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
1155
1156 if (fimc->out_path == FIMC_IO_DMA)
1157 return -ENOIOCTLCMD;
1158
1159 /* TODO: */
1160
1161 return 0;
1162}
1163
1164static int fimc_lite_subdev_s_power(struct v4l2_subdev *sd, int on)
1165{
1166 struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
1167
1168 if (fimc->out_path == FIMC_IO_DMA)
1169 return -ENOIOCTLCMD;
1170
1171 /* TODO: */
1172
1173 return 0;
1174}
1175
1176static int fimc_lite_log_status(struct v4l2_subdev *sd)
1177{
1178 struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
1179
1180 flite_hw_dump_regs(fimc, __func__);
1181 return 0;
1182}
1183
1184static int fimc_lite_subdev_registered(struct v4l2_subdev *sd)
1185{
1186 struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
1187 struct vb2_queue *q = &fimc->vb_queue;
1188 struct video_device *vfd;
1189 int ret;
1190
1191 fimc->fmt = &fimc_lite_formats[0];
1192 fimc->out_path = FIMC_IO_DMA;
1193
1194 vfd = video_device_alloc();
1195 if (!vfd) {
1196 v4l2_err(sd->v4l2_dev, "Failed to allocate video device\n");
1197 return -ENOMEM;
1198 }
1199
1200 snprintf(vfd->name, sizeof(vfd->name), "fimc-lite.%d.capture",
1201 fimc->index);
1202
1203 vfd->fops = &fimc_lite_fops;
1204 vfd->ioctl_ops = &fimc_lite_ioctl_ops;
1205 vfd->v4l2_dev = sd->v4l2_dev;
1206 vfd->minor = -1;
1207 vfd->release = video_device_release;
1208 vfd->lock = &fimc->lock;
1209 fimc->vfd = vfd;
1210 fimc->ref_count = 0;
1211 fimc->reqbufs_count = 0;
1212
1213 INIT_LIST_HEAD(&fimc->pending_buf_q);
1214 INIT_LIST_HEAD(&fimc->active_buf_q);
1215
1216 memset(q, 0, sizeof(*q));
1217 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1218 q->io_modes = VB2_MMAP | VB2_USERPTR;
1219 q->ops = &fimc_lite_qops;
1220 q->mem_ops = &vb2_dma_contig_memops;
1221 q->buf_struct_size = sizeof(struct flite_buffer);
1222 q->drv_priv = fimc;
1223
1224 vb2_queue_init(q);
1225
1226 fimc->vd_pad.flags = MEDIA_PAD_FL_SINK;
1227 ret = media_entity_init(&vfd->entity, 1, &fimc->vd_pad, 0);
1228 if (ret)
1229 goto err;
1230
1231 video_set_drvdata(vfd, fimc);
1232
1233 ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
1234 if (ret)
1235 goto err_vd;
1236
1237 v4l2_info(sd->v4l2_dev, "Registered %s as /dev/%s\n",
1238 vfd->name, video_device_node_name(vfd));
1239 return 0;
1240
1241 err_vd:
1242 media_entity_cleanup(&vfd->entity);
1243 err:
1244 video_device_release(vfd);
1245 return ret;
1246}
1247
1248static void fimc_lite_subdev_unregistered(struct v4l2_subdev *sd)
1249{
1250 struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
1251
1252 if (fimc == NULL)
1253 return;
1254
1255 if (fimc->vfd) {
1256 video_unregister_device(fimc->vfd);
1257 media_entity_cleanup(&fimc->vfd->entity);
1258 fimc->vfd = NULL;
1259 }
1260}
1261
1262static const struct v4l2_subdev_internal_ops fimc_lite_subdev_internal_ops = {
1263 .registered = fimc_lite_subdev_registered,
1264 .unregistered = fimc_lite_subdev_unregistered,
1265};
1266
1267static const struct v4l2_subdev_pad_ops fimc_lite_subdev_pad_ops = {
1268 .enum_mbus_code = fimc_lite_subdev_enum_mbus_code,
1269 .get_selection = fimc_lite_subdev_get_selection,
1270 .set_selection = fimc_lite_subdev_set_selection,
1271 .get_fmt = fimc_lite_subdev_get_fmt,
1272 .set_fmt = fimc_lite_subdev_set_fmt,
1273};
1274
1275static const struct v4l2_subdev_video_ops fimc_lite_subdev_video_ops = {
1276 .s_stream = fimc_lite_subdev_s_stream,
1277};
1278
1279static const struct v4l2_subdev_core_ops fimc_lite_core_ops = {
1280 .s_power = fimc_lite_subdev_s_power,
1281 .log_status = fimc_lite_log_status,
1282};
1283
1284static struct v4l2_subdev_ops fimc_lite_subdev_ops = {
1285 .core = &fimc_lite_core_ops,
1286 .video = &fimc_lite_subdev_video_ops,
1287 .pad = &fimc_lite_subdev_pad_ops,
1288};
1289
1290static int fimc_lite_s_ctrl(struct v4l2_ctrl *ctrl)
1291{
1292 struct fimc_lite *fimc = container_of(ctrl->handler, struct fimc_lite,
1293 ctrl_handler);
1294 set_bit(ST_FLITE_CONFIG, &fimc->state);
1295 return 0;
1296}
1297
1298static const struct v4l2_ctrl_ops fimc_lite_ctrl_ops = {
1299 .s_ctrl = fimc_lite_s_ctrl,
1300};
1301
1302static const struct v4l2_ctrl_config fimc_lite_ctrl = {
1303 .ops = &fimc_lite_ctrl_ops,
1304 .id = V4L2_CTRL_CLASS_USER | 0x1001,
1305 .type = V4L2_CTRL_TYPE_BOOLEAN,
1306 .name = "Test Pattern 640x480",
1307};
1308
1309static int fimc_lite_create_capture_subdev(struct fimc_lite *fimc)
1310{
1311 struct v4l2_ctrl_handler *handler = &fimc->ctrl_handler;
1312 struct v4l2_subdev *sd = &fimc->subdev;
1313 int ret;
1314
1315 v4l2_subdev_init(sd, &fimc_lite_subdev_ops);
1316 sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
1317 snprintf(sd->name, sizeof(sd->name), "FIMC-LITE.%d", fimc->index);
1318
1319 fimc->subdev_pads[FIMC_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1320 fimc->subdev_pads[FIMC_SD_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
1321 ret = media_entity_init(&sd->entity, FIMC_SD_PADS_NUM,
1322 fimc->subdev_pads, 0);
1323 if (ret)
1324 return ret;
1325
1326 v4l2_ctrl_handler_init(handler, 1);
1327 fimc->test_pattern = v4l2_ctrl_new_custom(handler, &fimc_lite_ctrl,
1328 NULL);
1329 if (handler->error) {
1330 media_entity_cleanup(&sd->entity);
1331 return handler->error;
1332 }
1333
1334 sd->ctrl_handler = handler;
1335 sd->internal_ops = &fimc_lite_subdev_internal_ops;
1336 sd->entity.ops = &fimc_lite_subdev_media_ops;
1337 v4l2_set_subdevdata(sd, fimc);
1338
1339 return 0;
1340}
1341
1342static void fimc_lite_unregister_capture_subdev(struct fimc_lite *fimc)
1343{
1344 struct v4l2_subdev *sd = &fimc->subdev;
1345
1346 v4l2_device_unregister_subdev(sd);
1347 media_entity_cleanup(&sd->entity);
1348 v4l2_ctrl_handler_free(&fimc->ctrl_handler);
1349 v4l2_set_subdevdata(sd, NULL);
1350}
1351
1352static void fimc_lite_clk_put(struct fimc_lite *fimc)
1353{
1354 if (IS_ERR_OR_NULL(fimc->clock))
1355 return;
1356
1357 clk_unprepare(fimc->clock);
1358 clk_put(fimc->clock);
1359 fimc->clock = NULL;
1360}
1361
1362static int fimc_lite_clk_get(struct fimc_lite *fimc)
1363{
1364 int ret;
1365
1366 fimc->clock = clk_get(&fimc->pdev->dev, FLITE_CLK_NAME);
1367 if (IS_ERR(fimc->clock))
1368 return PTR_ERR(fimc->clock);
1369
1370 ret = clk_prepare(fimc->clock);
1371 if (ret < 0) {
1372 clk_put(fimc->clock);
1373 fimc->clock = NULL;
1374 }
1375 return ret;
1376}
1377
1378static int __devinit fimc_lite_probe(struct platform_device *pdev)
1379{
1380 struct flite_drvdata *drv_data = fimc_lite_get_drvdata(pdev);
1381 struct fimc_lite *fimc;
1382 struct resource *res;
1383 int ret;
1384
1385 fimc = devm_kzalloc(&pdev->dev, sizeof(*fimc), GFP_KERNEL);
1386 if (!fimc)
1387 return -ENOMEM;
1388
1389 fimc->index = pdev->id;
1390 fimc->variant = drv_data->variant[fimc->index];
1391 fimc->pdev = pdev;
1392
1393 init_waitqueue_head(&fimc->irq_queue);
1394 spin_lock_init(&fimc->slock);
1395 mutex_init(&fimc->lock);
1396
1397 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1398 fimc->regs = devm_request_and_ioremap(&pdev->dev, res);
1399 if (fimc->regs == NULL) {
1400 dev_err(&pdev->dev, "Failed to obtain io memory\n");
1401 return -ENOENT;
1402 }
1403
1404 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1405 if (res == NULL) {
1406 dev_err(&pdev->dev, "Failed to get IRQ resource\n");
1407 return -ENXIO;
1408 }
1409
1410 ret = fimc_lite_clk_get(fimc);
1411 if (ret)
1412 return ret;
1413
1414 ret = devm_request_irq(&pdev->dev, res->start, flite_irq_handler,
1415 0, dev_name(&pdev->dev), fimc);
1416 if (ret) {
1417 dev_err(&pdev->dev, "Failed to install irq (%d)\n", ret);
1418 goto err_clk;
1419 }
1420
1421 /* The video node will be created within the subdev's registered() op */
1422 ret = fimc_lite_create_capture_subdev(fimc);
1423 if (ret)
1424 goto err_clk;
1425
1426 platform_set_drvdata(pdev, fimc);
1427 pm_runtime_enable(&pdev->dev);
1428 ret = pm_runtime_get_sync(&pdev->dev);
1429 if (ret < 0)
1430 goto err_sd;
1431
1432 fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
1433 if (IS_ERR(fimc->alloc_ctx)) {
1434 ret = PTR_ERR(fimc->alloc_ctx);
1435 goto err_pm;
1436 }
1437 pm_runtime_put(&pdev->dev);
1438
1439 dev_dbg(&pdev->dev, "FIMC-LITE.%d registered successfully\n",
1440 fimc->index);
1441 return 0;
1442err_pm:
1443 pm_runtime_put(&pdev->dev);
1444err_sd:
1445 fimc_lite_unregister_capture_subdev(fimc);
1446err_clk:
1447 fimc_lite_clk_put(fimc);
1448 return ret;
1449}
1450
1451static int fimc_lite_runtime_resume(struct device *dev)
1452{
1453 struct fimc_lite *fimc = dev_get_drvdata(dev);
1454
1455 clk_enable(fimc->clock);
1456 return 0;
1457}
1458
1459static int fimc_lite_runtime_suspend(struct device *dev)
1460{
1461 struct fimc_lite *fimc = dev_get_drvdata(dev);
1462
1463 clk_disable(fimc->clock);
1464 return 0;
1465}
1466
1467#ifdef CONFIG_PM_SLEEP
1468static int fimc_lite_resume(struct device *dev)
1469{
1470 struct fimc_lite *fimc = dev_get_drvdata(dev);
1471 struct flite_buffer *buf;
1472 unsigned long flags;
1473 int i;
1474
1475 spin_lock_irqsave(&fimc->slock, flags);
1476 if (!test_and_clear_bit(ST_LPM, &fimc->state) ||
1477 !test_bit(ST_FLITE_IN_USE, &fimc->state)) {
1478 spin_unlock_irqrestore(&fimc->slock, flags);
1479 return 0;
1480 }
1481 flite_hw_reset(fimc);
1482 spin_unlock_irqrestore(&fimc->slock, flags);
1483
1484 if (!test_and_clear_bit(ST_FLITE_SUSPENDED, &fimc->state))
1485 return 0;
1486
1487 INIT_LIST_HEAD(&fimc->active_buf_q);
1488 fimc_pipeline_initialize(&fimc->pipeline, &fimc->vfd->entity, false);
1489 fimc_lite_hw_init(fimc);
1490 clear_bit(ST_FLITE_SUSPENDED, &fimc->state);
1491
1492 for (i = 0; i < fimc->reqbufs_count; i++) {
1493 if (list_empty(&fimc->pending_buf_q))
1494 break;
1495 buf = fimc_lite_pending_queue_pop(fimc);
1496 buffer_queue(&buf->vb);
1497 }
1498 return 0;
1499}
1500
1501static int fimc_lite_suspend(struct device *dev)
1502{
1503 struct fimc_lite *fimc = dev_get_drvdata(dev);
1504 bool suspend = test_bit(ST_FLITE_IN_USE, &fimc->state);
1505 int ret;
1506
1507 if (test_and_set_bit(ST_LPM, &fimc->state))
1508 return 0;
1509
1510 ret = fimc_lite_stop_capture(fimc, suspend);
1511 if (ret)
1512 return ret;
1513
1514 return fimc_pipeline_shutdown(&fimc->pipeline);
1515}
1516#endif /* CONFIG_PM_SLEEP */
1517
1518static int __devexit fimc_lite_remove(struct platform_device *pdev)
1519{
1520 struct fimc_lite *fimc = platform_get_drvdata(pdev);
1521 struct device *dev = &pdev->dev;
1522
1523 pm_runtime_disable(dev);
1524 pm_runtime_set_suspended(dev);
1525 fimc_lite_unregister_capture_subdev(fimc);
1526 vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx);
1527 fimc_lite_clk_put(fimc);
1528
1529 dev_info(dev, "Driver unloaded\n");
1530 return 0;
1531}
1532
1533static struct flite_variant fimc_lite0_variant_exynos4 = {
1534 .max_width = 8192,
1535 .max_height = 8192,
1536 .out_width_align = 8,
1537 .win_hor_offs_align = 2,
1538 .out_hor_offs_align = 8,
1539};
1540
1541/* EXYNOS4212, EXYNOS4412 */
1542static struct flite_drvdata fimc_lite_drvdata_exynos4 = {
1543 .variant = {
1544 [0] = &fimc_lite0_variant_exynos4,
1545 [1] = &fimc_lite0_variant_exynos4,
1546 },
1547};
1548
1549static struct platform_device_id fimc_lite_driver_ids[] = {
1550 {
1551 .name = "exynos-fimc-lite",
1552 .driver_data = (unsigned long)&fimc_lite_drvdata_exynos4,
1553 },
1554 { /* sentinel */ },
1555};
1556MODULE_DEVICE_TABLE(platform, fimc_lite_driver_ids);
1557
1558static const struct dev_pm_ops fimc_lite_pm_ops = {
1559 SET_SYSTEM_SLEEP_PM_OPS(fimc_lite_suspend, fimc_lite_resume)
1560 SET_RUNTIME_PM_OPS(fimc_lite_runtime_suspend, fimc_lite_runtime_resume,
1561 NULL)
1562};
1563
1564static struct platform_driver fimc_lite_driver = {
1565 .probe = fimc_lite_probe,
1566 .remove = __devexit_p(fimc_lite_remove),
1567 .id_table = fimc_lite_driver_ids,
1568 .driver = {
1569 .name = FIMC_LITE_DRV_NAME,
1570 .owner = THIS_MODULE,
1571 .pm = &fimc_lite_pm_ops,
1572 }
1573};
1574module_platform_driver(fimc_lite_driver);
1575MODULE_LICENSE("GPL");
1576MODULE_ALIAS("platform:" FIMC_LITE_DRV_NAME);
diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.c b/drivers/media/video/s5p-fimc/fimc-mdevice.c
index 212474130dfb..6753c45631b8 100644
--- a/drivers/media/video/s5p-fimc/fimc-mdevice.c
+++ b/drivers/media/video/s5p-fimc/fimc-mdevice.c
@@ -66,6 +66,9 @@ void fimc_pipeline_prepare(struct fimc_pipeline *p, struct media_entity *me)
66 case CSIS_GROUP_ID: 66 case CSIS_GROUP_ID:
67 p->subdevs[IDX_CSIS] = sd; 67 p->subdevs[IDX_CSIS] = sd;
68 break; 68 break;
69 case FLITE_GROUP_ID:
70 p->subdevs[IDX_FLITE] = sd;
71 break;
69 case FIMC_GROUP_ID: 72 case FIMC_GROUP_ID:
70 /* No need to control FIMC subdev through subdev ops */ 73 /* No need to control FIMC subdev through subdev ops */
71 break; 74 break;
@@ -336,6 +339,7 @@ static int fimc_register_callback(struct device *dev, void *p)
336 339
337 if (!fimc || !fimc->pdev) 340 if (!fimc || !fimc->pdev)
338 return 0; 341 return 0;
342
339 if (fimc->pdev->id < 0 || fimc->pdev->id >= FIMC_MAX_DEVS) 343 if (fimc->pdev->id < 0 || fimc->pdev->id >= FIMC_MAX_DEVS)
340 return 0; 344 return 0;
341 345
@@ -351,6 +355,31 @@ static int fimc_register_callback(struct device *dev, void *p)
351 return ret; 355 return ret;
352} 356}
353 357
358static int fimc_lite_register_callback(struct device *dev, void *p)
359{
360 struct fimc_lite *fimc = dev_get_drvdata(dev);
361 struct v4l2_subdev *sd = &fimc->subdev;
362 struct fimc_md *fmd = p;
363 int ret;
364
365 if (fimc == NULL)
366 return 0;
367
368 if (fimc->index >= FIMC_LITE_MAX_DEVS)
369 return 0;
370
371 fmd->fimc_lite[fimc->index] = fimc;
372 sd->grp_id = FLITE_GROUP_ID;
373
374 ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
375 if (ret) {
376 v4l2_err(&fmd->v4l2_dev,
377 "Failed to register FIMC-LITE.%d (%d)\n",
378 fimc->index, ret);
379 }
380 return ret;
381}
382
354static int csis_register_callback(struct device *dev, void *p) 383static int csis_register_callback(struct device *dev, void *p)
355{ 384{
356 struct v4l2_subdev *sd = dev_get_drvdata(dev); 385 struct v4l2_subdev *sd = dev_get_drvdata(dev);
@@ -396,6 +425,15 @@ static int fimc_md_register_platform_entities(struct fimc_md *fmd)
396 fimc_register_callback); 425 fimc_register_callback);
397 if (ret) 426 if (ret)
398 return ret; 427 return ret;
428
429 driver = driver_find(FIMC_LITE_DRV_NAME, &platform_bus_type);
430 if (driver && try_module_get(driver->owner)) {
431 ret = driver_for_each_device(driver, NULL, fmd,
432 fimc_lite_register_callback);
433 if (ret)
434 return ret;
435 module_put(driver->owner);
436 }
399 /* 437 /*
400 * Check if there is any sensor on the MIPI-CSI2 bus and 438 * Check if there is any sensor on the MIPI-CSI2 bus and
401 * if not skip the s5p-csis module loading. 439 * if not skip the s5p-csis module loading.
@@ -433,6 +471,12 @@ static void fimc_md_unregister_entities(struct fimc_md *fmd)
433 v4l2_device_unregister_subdev(&fmd->fimc[i]->vid_cap.subdev); 471 v4l2_device_unregister_subdev(&fmd->fimc[i]->vid_cap.subdev);
434 fmd->fimc[i] = NULL; 472 fmd->fimc[i] = NULL;
435 } 473 }
474 for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) {
475 if (fmd->fimc_lite[i] == NULL)
476 continue;
477 v4l2_device_unregister_subdev(&fmd->fimc_lite[i]->subdev);
478 fmd->fimc_lite[i] = NULL;
479 }
436 for (i = 0; i < CSIS_MAX_ENTITIES; i++) { 480 for (i = 0; i < CSIS_MAX_ENTITIES; i++) {
437 if (fmd->csis[i].sd == NULL) 481 if (fmd->csis[i].sd == NULL)
438 continue; 482 continue;
@@ -456,28 +500,28 @@ static void fimc_md_unregister_entities(struct fimc_md *fmd)
456 * @pad: the source entity pad index 500 * @pad: the source entity pad index
457 * @fimc_id: index of the fimc device for which link should be enabled 501 * @fimc_id: index of the fimc device for which link should be enabled
458 */ 502 */
459static int __fimc_md_create_fimc_links(struct fimc_md *fmd, 503static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,
460 struct media_entity *source, 504 struct media_entity *source,
461 struct v4l2_subdev *sensor, 505 struct v4l2_subdev *sensor,
462 int pad, int fimc_id) 506 int pad, int fimc_id)
463{ 507{
464 struct fimc_sensor_info *s_info; 508 struct fimc_sensor_info *s_info;
465 struct media_entity *sink; 509 struct media_entity *sink;
466 unsigned int flags; 510 unsigned int flags = 0;
467 int ret, i; 511 int ret, i;
468 512
469 for (i = 0; i < FIMC_MAX_DEVS; i++) { 513 for (i = 0; i < FIMC_MAX_DEVS; i++) {
470 if (!fmd->fimc[i]) 514 if (!fmd->fimc[i])
471 break; 515 continue;
472 /* 516 /*
473 * Some FIMC variants are not fitted with camera capture 517 * Some FIMC variants are not fitted with camera capture
474 * interface. Skip creating a link from sensor for those. 518 * interface. Skip creating a link from sensor for those.
475 */ 519 */
476 if (sensor->grp_id == SENSOR_GROUP_ID && 520 if (!fmd->fimc[i]->variant->has_cam_if)
477 !fmd->fimc[i]->variant->has_cam_if)
478 continue; 521 continue;
479 522
480 flags = (i == fimc_id) ? MEDIA_LNK_FL_ENABLED : 0; 523 flags = (i == fimc_id) ? MEDIA_LNK_FL_ENABLED : 0;
524
481 sink = &fmd->fimc[i]->vid_cap.subdev.entity; 525 sink = &fmd->fimc[i]->vid_cap.subdev.entity;
482 ret = media_entity_create_link(source, pad, sink, 526 ret = media_entity_create_link(source, pad, sink,
483 FIMC_SD_PAD_SINK, flags); 527 FIMC_SD_PAD_SINK, flags);
@@ -493,7 +537,7 @@ static int __fimc_md_create_fimc_links(struct fimc_md *fmd,
493 v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]", 537 v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]",
494 source->name, flags ? '=' : '-', sink->name); 538 source->name, flags ? '=' : '-', sink->name);
495 539
496 if (flags == 0) 540 if (flags == 0 || sensor == NULL)
497 continue; 541 continue;
498 s_info = v4l2_get_subdev_hostdata(sensor); 542 s_info = v4l2_get_subdev_hostdata(sensor);
499 if (!WARN_ON(s_info == NULL)) { 543 if (!WARN_ON(s_info == NULL)) {
@@ -503,9 +547,55 @@ static int __fimc_md_create_fimc_links(struct fimc_md *fmd,
503 spin_unlock_irqrestore(&fmd->slock, irq_flags); 547 spin_unlock_irqrestore(&fmd->slock, irq_flags);
504 } 548 }
505 } 549 }
550
551 for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) {
552 if (!fmd->fimc_lite[i])
553 continue;
554
555 flags = (i == fimc_id) ? MEDIA_LNK_FL_ENABLED : 0;
556
557 sink = &fmd->fimc_lite[i]->subdev.entity;
558 ret = media_entity_create_link(source, pad, sink,
559 FLITE_SD_PAD_SINK, flags);
560 if (ret)
561 return ret;
562
563 /* Notify FIMC-LITE subdev entity */
564 ret = media_entity_call(sink, link_setup, &sink->pads[0],
565 &source->pads[pad], flags);
566 if (ret)
567 break;
568
569 v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]",
570 source->name, flags ? '=' : '-', sink->name);
571 }
506 return 0; 572 return 0;
507} 573}
508 574
575/* Create links from FIMC-LITE source pads to other entities */
576static int __fimc_md_create_flite_source_links(struct fimc_md *fmd)
577{
578 struct media_entity *source, *sink;
579 unsigned int flags = MEDIA_LNK_FL_ENABLED;
580 int i, ret;
581
582 for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) {
583 struct fimc_lite *fimc = fmd->fimc_lite[i];
584 if (fimc == NULL)
585 continue;
586 source = &fimc->subdev.entity;
587 sink = &fimc->vfd->entity;
588 /* FIMC-LITE's subdev and video node */
589 ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE,
590 sink, 0, flags);
591 if (ret)
592 break;
593 /* TODO: create links to other entities */
594 }
595
596 return ret;
597}
598
509/** 599/**
510 * fimc_md_create_links - create default links between registered entities 600 * fimc_md_create_links - create default links between registered entities
511 * 601 *
@@ -562,8 +652,7 @@ static int fimc_md_create_links(struct fimc_md *fmd)
562 v4l2_info(&fmd->v4l2_dev, "created link [%s] => [%s]", 652 v4l2_info(&fmd->v4l2_dev, "created link [%s] => [%s]",
563 sensor->entity.name, csis->entity.name); 653 sensor->entity.name, csis->entity.name);
564 654
565 source = &csis->entity; 655 source = NULL;
566 pad = CSIS_PAD_SOURCE;
567 break; 656 break;
568 657
569 case FIMC_ITU_601...FIMC_ITU_656: 658 case FIMC_ITU_601...FIMC_ITU_656:
@@ -579,9 +668,21 @@ static int fimc_md_create_links(struct fimc_md *fmd)
579 if (source == NULL) 668 if (source == NULL)
580 continue; 669 continue;
581 670
582 ret = __fimc_md_create_fimc_links(fmd, source, sensor, pad, 671 ret = __fimc_md_create_fimc_sink_links(fmd, source, sensor,
583 fimc_id++); 672 pad, fimc_id++);
673 }
674
675 fimc_id = 0;
676 for (i = 0; i < ARRAY_SIZE(fmd->csis); i++) {
677 if (fmd->csis[i].sd == NULL)
678 continue;
679 source = &fmd->csis[i].sd->entity;
680 pad = CSIS_PAD_SOURCE;
681
682 ret = __fimc_md_create_fimc_sink_links(fmd, source, NULL,
683 pad, fimc_id++);
584 } 684 }
685
585 /* Create immutable links between each FIMC's subdev and video node */ 686 /* Create immutable links between each FIMC's subdev and video node */
586 flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED; 687 flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED;
587 for (i = 0; i < FIMC_MAX_DEVS; i++) { 688 for (i = 0; i < FIMC_MAX_DEVS; i++) {
@@ -595,7 +696,7 @@ static int fimc_md_create_links(struct fimc_md *fmd)
595 break; 696 break;
596 } 697 }
597 698
598 return ret; 699 return __fimc_md_create_flite_source_links(fmd);
599} 700}
600 701
601/* 702/*
@@ -703,9 +804,10 @@ int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on)
703static int fimc_md_link_notify(struct media_pad *source, 804static int fimc_md_link_notify(struct media_pad *source,
704 struct media_pad *sink, u32 flags) 805 struct media_pad *sink, u32 flags)
705{ 806{
807 struct fimc_lite *fimc_lite = NULL;
808 struct fimc_dev *fimc = NULL;
706 struct fimc_pipeline *pipeline; 809 struct fimc_pipeline *pipeline;
707 struct v4l2_subdev *sd; 810 struct v4l2_subdev *sd;
708 struct fimc_dev *fimc;
709 int ret = 0; 811 int ret = 0;
710 812
711 if (media_entity_type(sink->entity) != MEDIA_ENT_T_V4L2_SUBDEV) 813 if (media_entity_type(sink->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
@@ -714,6 +816,10 @@ static int fimc_md_link_notify(struct media_pad *source,
714 sd = media_entity_to_v4l2_subdev(sink->entity); 816 sd = media_entity_to_v4l2_subdev(sink->entity);
715 817
716 switch (sd->grp_id) { 818 switch (sd->grp_id) {
819 case FLITE_GROUP_ID:
820 fimc_lite = v4l2_get_subdevdata(sd);
821 pipeline = &fimc_lite->pipeline;
822 break;
717 case FIMC_GROUP_ID: 823 case FIMC_GROUP_ID:
718 fimc = v4l2_get_subdevdata(sd); 824 fimc = v4l2_get_subdevdata(sd);
719 pipeline = &fimc->pipeline; 825 pipeline = &fimc->pipeline;
@@ -739,15 +845,23 @@ static int fimc_md_link_notify(struct media_pad *source,
739 * pipeline is already in use, i.e. its video node is opened. 845 * pipeline is already in use, i.e. its video node is opened.
740 * Recreate the controls destroyed during the link deactivation. 846 * Recreate the controls destroyed during the link deactivation.
741 */ 847 */
742 mutex_lock(&fimc->lock); 848 if (fimc) {
743 if (fimc->vid_cap.refcnt > 0) { 849 mutex_lock(&fimc->lock);
850 if (fimc->vid_cap.refcnt > 0) {
744 ret = __fimc_pipeline_initialize(pipeline, 851 ret = __fimc_pipeline_initialize(pipeline,
745 source->entity, true); 852 source->entity, true);
746 if (!ret) 853 if (!ret)
747 ret = fimc_capture_ctrls_create(fimc); 854 ret = fimc_capture_ctrls_create(fimc);
855 }
856 mutex_unlock(&fimc->lock);
857 } else {
858 mutex_lock(&fimc_lite->lock);
859 if (fimc_lite->ref_count > 0) {
860 ret = __fimc_pipeline_initialize(pipeline,
861 source->entity, true);
862 }
863 mutex_unlock(&fimc_lite->lock);
748 } 864 }
749 mutex_unlock(&fimc->lock);
750
751 return ret ? -EPIPE : ret; 865 return ret ? -EPIPE : ret;
752} 866}
753 867
diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.h b/drivers/media/video/s5p-fimc/fimc-mdevice.h
index c5ac3e64b0d9..3524c19ae801 100644
--- a/drivers/media/video/s5p-fimc/fimc-mdevice.h
+++ b/drivers/media/video/s5p-fimc/fimc-mdevice.h
@@ -18,13 +18,15 @@
18#include <media/v4l2-subdev.h> 18#include <media/v4l2-subdev.h>
19 19
20#include "fimc-core.h" 20#include "fimc-core.h"
21#include "fimc-lite.h"
21#include "mipi-csis.h" 22#include "mipi-csis.h"
22 23
23/* Group IDs of sensor, MIPI CSIS and the writeback subdevs. */ 24/* Group IDs of sensor, MIPI-CSIS, FIMC-LITE and the writeback subdevs. */
24#define SENSOR_GROUP_ID (1 << 8) 25#define SENSOR_GROUP_ID (1 << 8)
25#define CSIS_GROUP_ID (1 << 9) 26#define CSIS_GROUP_ID (1 << 9)
26#define WRITEBACK_GROUP_ID (1 << 10) 27#define WRITEBACK_GROUP_ID (1 << 10)
27#define FIMC_GROUP_ID (1 << 11) 28#define FIMC_GROUP_ID (1 << 11)
29#define FLITE_GROUP_ID (1 << 12)
28 30
29#define FIMC_MAX_SENSORS 8 31#define FIMC_MAX_SENSORS 8
30#define FIMC_MAX_CAMCLKS 2 32#define FIMC_MAX_CAMCLKS 2
@@ -74,6 +76,7 @@ struct fimc_md {
74 struct fimc_sensor_info sensor[FIMC_MAX_SENSORS]; 76 struct fimc_sensor_info sensor[FIMC_MAX_SENSORS];
75 int num_sensors; 77 int num_sensors;
76 struct fimc_camclk_info camclk[FIMC_MAX_CAMCLKS]; 78 struct fimc_camclk_info camclk[FIMC_MAX_CAMCLKS];
79 struct fimc_lite *fimc_lite[FIMC_LITE_MAX_DEVS];
77 struct fimc_dev *fimc[FIMC_MAX_DEVS]; 80 struct fimc_dev *fimc[FIMC_MAX_DEVS];
78 struct media_device media_dev; 81 struct media_device media_dev;
79 struct v4l2_device v4l2_dev; 82 struct v4l2_device v4l2_dev;