aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/s5p-fimc/Makefile2
-rw-r--r--drivers/media/video/s5p-fimc/fimc-capture.c819
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.c563
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.h205
-rw-r--r--drivers/media/video/s5p-fimc/fimc-reg.c173
-rw-r--r--include/media/s3c_fimc.h60
6 files changed, 1630 insertions, 192 deletions
diff --git a/drivers/media/video/s5p-fimc/Makefile b/drivers/media/video/s5p-fimc/Makefile
index 0d9d54132ecc..7ea1b1403b1e 100644
--- a/drivers/media/video/s5p-fimc/Makefile
+++ b/drivers/media/video/s5p-fimc/Makefile
@@ -1,3 +1,3 @@
1 1
2obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) := s5p-fimc.o 2obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) := s5p-fimc.o
3s5p-fimc-y := fimc-core.o fimc-reg.o 3s5p-fimc-y := fimc-core.o fimc-reg.o fimc-capture.o
diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c
new file mode 100644
index 000000000000..e8f13d3e2df1
--- /dev/null
+++ b/drivers/media/video/s5p-fimc/fimc-capture.c
@@ -0,0 +1,819 @@
1/*
2 * Samsung S5P SoC series camera interface (camera capture) driver
3 *
4 * Copyright (c) 2010 Samsung Electronics Co., Ltd
5 * Author: 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/version.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/list.h>
22#include <linux/slab.h>
23#include <linux/clk.h>
24#include <linux/i2c.h>
25
26#include <linux/videodev2.h>
27#include <media/v4l2-device.h>
28#include <media/v4l2-ioctl.h>
29#include <media/v4l2-mem2mem.h>
30#include <media/videobuf-core.h>
31#include <media/videobuf-dma-contig.h>
32
33#include "fimc-core.h"
34
35static struct v4l2_subdev *fimc_subdev_register(struct fimc_dev *fimc,
36 struct s3c_fimc_isp_info *isp_info)
37{
38 struct i2c_adapter *i2c_adap;
39 struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
40 struct v4l2_subdev *sd = NULL;
41
42 i2c_adap = i2c_get_adapter(isp_info->i2c_bus_num);
43 if (!i2c_adap)
44 return ERR_PTR(-ENOMEM);
45
46 sd = v4l2_i2c_new_subdev_board(&vid_cap->v4l2_dev, i2c_adap,
47 MODULE_NAME, isp_info->board_info, NULL);
48 if (!sd) {
49 v4l2_err(&vid_cap->v4l2_dev, "failed to acquire subdev\n");
50 return NULL;
51 }
52
53 v4l2_info(&vid_cap->v4l2_dev, "subdevice %s registered successfuly\n",
54 isp_info->board_info->type);
55
56 return sd;
57}
58
59static void fimc_subdev_unregister(struct fimc_dev *fimc)
60{
61 struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
62 struct i2c_client *client;
63
64 if (vid_cap->input_index < 0)
65 return; /* Subdevice already released or not registered. */
66
67 if (vid_cap->sd) {
68 v4l2_device_unregister_subdev(vid_cap->sd);
69 client = v4l2_get_subdevdata(vid_cap->sd);
70 i2c_unregister_device(client);
71 i2c_put_adapter(client->adapter);
72 vid_cap->sd = NULL;
73 }
74
75 vid_cap->input_index = -1;
76}
77
78/**
79 * fimc_subdev_attach - attach v4l2_subdev to camera host interface
80 *
81 * @fimc: FIMC device information
82 * @index: index to the array of available subdevices,
83 * -1 for full array search or non negative value
84 * to select specific subdevice
85 */
86static int fimc_subdev_attach(struct fimc_dev *fimc, int index)
87{
88 struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
89 struct s3c_platform_fimc *pdata = fimc->pdata;
90 struct s3c_fimc_isp_info *isp_info;
91 struct v4l2_subdev *sd;
92 int i;
93
94 for (i = 0; i < FIMC_MAX_CAMIF_CLIENTS; ++i) {
95 isp_info = pdata->isp_info[i];
96
97 if (!isp_info || (index >= 0 && i != index))
98 continue;
99
100 sd = fimc_subdev_register(fimc, isp_info);
101 if (sd) {
102 vid_cap->sd = sd;
103 vid_cap->input_index = i;
104
105 return 0;
106 }
107 }
108
109 vid_cap->input_index = -1;
110 vid_cap->sd = NULL;
111 v4l2_err(&vid_cap->v4l2_dev, "fimc%d: sensor attach failed\n",
112 fimc->id);
113 return -ENODEV;
114}
115
116static int fimc_isp_subdev_init(struct fimc_dev *fimc, int index)
117{
118 struct s3c_fimc_isp_info *isp_info;
119 int ret;
120
121 ret = fimc_subdev_attach(fimc, index);
122 if (ret)
123 return ret;
124
125 isp_info = fimc->pdata->isp_info[fimc->vid_cap.input_index];
126 ret = fimc_hw_set_camera_polarity(fimc, isp_info);
127 if (!ret) {
128 ret = v4l2_subdev_call(fimc->vid_cap.sd, core,
129 s_power, 1);
130 if (!ret)
131 return ret;
132 }
133
134 fimc_subdev_unregister(fimc);
135 err("ISP initialization failed: %d", ret);
136 return ret;
137}
138
139/*
140 * At least one buffer on the pending_buf_q queue is required.
141 * Locking: The caller holds fimc->slock spinlock.
142 */
143int fimc_vid_cap_buf_queue(struct fimc_dev *fimc,
144 struct fimc_vid_buffer *fimc_vb)
145{
146 struct fimc_vid_cap *cap = &fimc->vid_cap;
147 struct fimc_ctx *ctx = cap->ctx;
148 int ret = 0;
149
150 BUG_ON(!fimc || !fimc_vb);
151
152 ret = fimc_prepare_addr(ctx, fimc_vb, &ctx->d_frame,
153 &fimc_vb->paddr);
154 if (ret)
155 return ret;
156
157 if (test_bit(ST_CAPT_STREAM, &fimc->state)) {
158 fimc_pending_queue_add(cap, fimc_vb);
159 } else {
160 /* Setup the buffer directly for processing. */
161 int buf_id = (cap->reqbufs_count == 1) ? -1 : cap->buf_index;
162 fimc_hw_set_output_addr(fimc, &fimc_vb->paddr, buf_id);
163
164 fimc_vb->index = cap->buf_index;
165 active_queue_add(cap, fimc_vb);
166
167 if (++cap->buf_index >= FIMC_MAX_OUT_BUFS)
168 cap->buf_index = 0;
169 }
170 return ret;
171}
172
173static int fimc_stop_capture(struct fimc_dev *fimc)
174{
175 unsigned long flags;
176 struct fimc_vid_cap *cap;
177 int ret;
178
179 cap = &fimc->vid_cap;
180
181 if (!fimc_capture_active(fimc))
182 return 0;
183
184 spin_lock_irqsave(&fimc->slock, flags);
185 set_bit(ST_CAPT_SHUT, &fimc->state);
186 fimc_deactivate_capture(fimc);
187 spin_unlock_irqrestore(&fimc->slock, flags);
188
189 wait_event_timeout(fimc->irq_queue,
190 test_bit(ST_CAPT_SHUT, &fimc->state),
191 FIMC_SHUTDOWN_TIMEOUT);
192
193 ret = v4l2_subdev_call(cap->sd, video, s_stream, 0);
194 if (ret)
195 v4l2_err(&fimc->vid_cap.v4l2_dev, "s_stream(0) failed\n");
196
197 spin_lock_irqsave(&fimc->slock, flags);
198 fimc->state &= ~(1 << ST_CAPT_RUN | 1 << ST_CAPT_PEND |
199 1 << ST_CAPT_STREAM);
200
201 fimc->vid_cap.active_buf_cnt = 0;
202 spin_unlock_irqrestore(&fimc->slock, flags);
203
204 dbg("state: 0x%lx", fimc->state);
205 return 0;
206}
207
208static int fimc_capture_open(struct file *file)
209{
210 struct fimc_dev *fimc = video_drvdata(file);
211 int ret = 0;
212
213 dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state);
214
215 /* Return if the corresponding video mem2mem node is already opened. */
216 if (fimc_m2m_active(fimc))
217 return -EBUSY;
218
219 if (mutex_lock_interruptible(&fimc->lock))
220 return -ERESTARTSYS;
221
222 if (++fimc->vid_cap.refcnt == 1) {
223 ret = fimc_isp_subdev_init(fimc, -1);
224 if (ret) {
225 fimc->vid_cap.refcnt--;
226 ret = -EIO;
227 }
228 }
229
230 file->private_data = fimc->vid_cap.ctx;
231
232 mutex_unlock(&fimc->lock);
233 return ret;
234}
235
236static int fimc_capture_close(struct file *file)
237{
238 struct fimc_dev *fimc = video_drvdata(file);
239
240 if (mutex_lock_interruptible(&fimc->lock))
241 return -ERESTARTSYS;
242
243 dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state);
244
245 if (--fimc->vid_cap.refcnt == 0) {
246 fimc_stop_capture(fimc);
247
248 videobuf_stop(&fimc->vid_cap.vbq);
249 videobuf_mmap_free(&fimc->vid_cap.vbq);
250
251 v4l2_err(&fimc->vid_cap.v4l2_dev, "releasing ISP\n");
252 v4l2_subdev_call(fimc->vid_cap.sd, core, s_power, 0);
253 fimc_subdev_unregister(fimc);
254 }
255
256 mutex_unlock(&fimc->lock);
257 return 0;
258}
259
260static unsigned int fimc_capture_poll(struct file *file,
261 struct poll_table_struct *wait)
262{
263 struct fimc_ctx *ctx = file->private_data;
264 struct fimc_dev *fimc = ctx->fimc_dev;
265 struct fimc_vid_cap *cap = &fimc->vid_cap;
266 int ret;
267
268 if (mutex_lock_interruptible(&fimc->lock))
269 return POLLERR;
270
271 ret = videobuf_poll_stream(file, &cap->vbq, wait);
272 mutex_unlock(&fimc->lock);
273
274 return ret;
275}
276
277static int fimc_capture_mmap(struct file *file, struct vm_area_struct *vma)
278{
279 struct fimc_ctx *ctx = file->private_data;
280 struct fimc_dev *fimc = ctx->fimc_dev;
281 struct fimc_vid_cap *cap = &fimc->vid_cap;
282 int ret;
283
284 if (mutex_lock_interruptible(&fimc->lock))
285 return -ERESTARTSYS;
286
287 ret = videobuf_mmap_mapper(&cap->vbq, vma);
288 mutex_unlock(&fimc->lock);
289
290 return ret;
291}
292
293/* video device file operations */
294static const struct v4l2_file_operations fimc_capture_fops = {
295 .owner = THIS_MODULE,
296 .open = fimc_capture_open,
297 .release = fimc_capture_close,
298 .poll = fimc_capture_poll,
299 .unlocked_ioctl = video_ioctl2,
300 .mmap = fimc_capture_mmap,
301};
302
303static int fimc_vidioc_querycap_capture(struct file *file, void *priv,
304 struct v4l2_capability *cap)
305{
306 struct fimc_ctx *ctx = file->private_data;
307 struct fimc_dev *fimc = ctx->fimc_dev;
308
309 strncpy(cap->driver, fimc->pdev->name, sizeof(cap->driver) - 1);
310 strncpy(cap->card, fimc->pdev->name, sizeof(cap->card) - 1);
311 cap->bus_info[0] = 0;
312 cap->version = KERNEL_VERSION(1, 0, 0);
313 cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE;
314
315 return 0;
316}
317
318/* Synchronize formats of the camera interface input and attached sensor. */
319static int sync_capture_fmt(struct fimc_ctx *ctx)
320{
321 struct fimc_frame *frame = &ctx->s_frame;
322 struct fimc_dev *fimc = ctx->fimc_dev;
323 struct v4l2_mbus_framefmt *fmt = &fimc->vid_cap.fmt;
324 int ret;
325
326 fmt->width = ctx->d_frame.o_width;
327 fmt->height = ctx->d_frame.o_height;
328
329 ret = v4l2_subdev_call(fimc->vid_cap.sd, video, s_mbus_fmt, fmt);
330 if (ret == -ENOIOCTLCMD) {
331 err("s_mbus_fmt failed");
332 return ret;
333 }
334 dbg("w: %d, h: %d, code= %d", fmt->width, fmt->height, fmt->code);
335
336 frame->fmt = find_mbus_format(fmt, FMT_FLAGS_CAM);
337 if (!frame->fmt) {
338 err("fimc source format not found\n");
339 return -EINVAL;
340 }
341
342 frame->f_width = fmt->width;
343 frame->f_height = fmt->height;
344 frame->width = fmt->width;
345 frame->height = fmt->height;
346 frame->o_width = fmt->width;
347 frame->o_height = fmt->height;
348 frame->offs_h = 0;
349 frame->offs_v = 0;
350
351 return 0;
352}
353
354static int fimc_cap_s_fmt(struct file *file, void *priv,
355 struct v4l2_format *f)
356{
357 struct fimc_ctx *ctx = priv;
358 struct fimc_dev *fimc = ctx->fimc_dev;
359 struct fimc_frame *frame;
360 struct v4l2_pix_format *pix;
361 int ret;
362
363 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
364 return -EINVAL;
365
366 ret = fimc_vidioc_try_fmt(file, priv, f);
367 if (ret)
368 return ret;
369
370 if (mutex_lock_interruptible(&fimc->lock))
371 return -ERESTARTSYS;
372
373 if (fimc_capture_active(fimc)) {
374 ret = -EBUSY;
375 goto sf_unlock;
376 }
377
378 frame = &ctx->d_frame;
379
380 pix = &f->fmt.pix;
381 frame->fmt = find_format(f, FMT_FLAGS_M2M | FMT_FLAGS_CAM);
382 if (!frame->fmt) {
383 err("fimc target format not found\n");
384 ret = -EINVAL;
385 goto sf_unlock;
386 }
387
388 /* Output DMA frame pixel size and offsets. */
389 frame->f_width = pix->bytesperline * 8 / frame->fmt->depth;
390 frame->f_height = pix->height;
391 frame->width = pix->width;
392 frame->height = pix->height;
393 frame->o_width = pix->width;
394 frame->o_height = pix->height;
395 frame->size = (pix->width * pix->height * frame->fmt->depth) >> 3;
396 frame->offs_h = 0;
397 frame->offs_v = 0;
398
399 ret = sync_capture_fmt(ctx);
400
401 ctx->state |= (FIMC_PARAMS | FIMC_DST_FMT);
402
403sf_unlock:
404 mutex_unlock(&fimc->lock);
405 return ret;
406}
407
408static int fimc_cap_enum_input(struct file *file, void *priv,
409 struct v4l2_input *i)
410{
411 struct fimc_ctx *ctx = priv;
412 struct s3c_platform_fimc *pldata = ctx->fimc_dev->pdata;
413 struct s3c_fimc_isp_info *isp_info;
414
415 if (i->index >= FIMC_MAX_CAMIF_CLIENTS)
416 return -EINVAL;
417
418 isp_info = pldata->isp_info[i->index];
419 if (isp_info == NULL)
420 return -EINVAL;
421
422 i->type = V4L2_INPUT_TYPE_CAMERA;
423 strncpy(i->name, isp_info->board_info->type, 32);
424 return 0;
425}
426
427static int fimc_cap_s_input(struct file *file, void *priv,
428 unsigned int i)
429{
430 struct fimc_ctx *ctx = priv;
431 struct fimc_dev *fimc = ctx->fimc_dev;
432 struct s3c_platform_fimc *pdata = fimc->pdata;
433 int ret;
434
435 if (fimc_capture_active(ctx->fimc_dev))
436 return -EBUSY;
437
438 if (mutex_lock_interruptible(&fimc->lock))
439 return -ERESTARTSYS;
440
441 if (i >= FIMC_MAX_CAMIF_CLIENTS || !pdata->isp_info[i]) {
442 ret = -EINVAL;
443 goto si_unlock;
444 }
445
446 if (fimc->vid_cap.sd) {
447 ret = v4l2_subdev_call(fimc->vid_cap.sd, core, s_power, 0);
448 if (ret)
449 err("s_power failed: %d", ret);
450 }
451
452 /* Release the attached sensor subdevice. */
453 fimc_subdev_unregister(fimc);
454
455 ret = fimc_isp_subdev_init(fimc, i);
456
457si_unlock:
458 mutex_unlock(&fimc->lock);
459 return ret;
460}
461
462static int fimc_cap_g_input(struct file *file, void *priv,
463 unsigned int *i)
464{
465 struct fimc_ctx *ctx = priv;
466 struct fimc_vid_cap *cap = &ctx->fimc_dev->vid_cap;
467
468 *i = cap->input_index;
469 return 0;
470}
471
472static int fimc_cap_streamon(struct file *file, void *priv,
473 enum v4l2_buf_type type)
474{
475 struct s3c_fimc_isp_info *isp_info;
476 struct fimc_ctx *ctx = priv;
477 struct fimc_dev *fimc = ctx->fimc_dev;
478 int ret = -EBUSY;
479
480 if (mutex_lock_interruptible(&fimc->lock))
481 return -ERESTARTSYS;
482
483 if (fimc_capture_active(fimc) || !fimc->vid_cap.sd)
484 goto s_unlock;
485
486 if (!(ctx->state & FIMC_DST_FMT)) {
487 v4l2_err(&fimc->vid_cap.v4l2_dev, "Format is not set\n");
488 ret = -EINVAL;
489 goto s_unlock;
490 }
491
492 ret = v4l2_subdev_call(fimc->vid_cap.sd, video, s_stream, 1);
493 if (ret && ret != -ENOIOCTLCMD)
494 goto s_unlock;
495
496 ret = fimc_prepare_config(ctx, ctx->state);
497 if (ret)
498 goto s_unlock;
499
500 isp_info = fimc->pdata->isp_info[fimc->vid_cap.input_index];
501 fimc_hw_set_camera_type(fimc, isp_info);
502 fimc_hw_set_camera_source(fimc, isp_info);
503 fimc_hw_set_camera_offset(fimc, &ctx->s_frame);
504
505 if (ctx->state & FIMC_PARAMS) {
506 ret = fimc_set_scaler_info(ctx);
507 if (ret) {
508 err("Scaler setup error");
509 goto s_unlock;
510 }
511 fimc_hw_set_input_path(ctx);
512 fimc_hw_set_scaler(ctx);
513 fimc_hw_set_target_format(ctx);
514 fimc_hw_set_rotation(ctx);
515 fimc_hw_set_effect(ctx);
516 }
517
518 fimc_hw_set_output_path(ctx);
519 fimc_hw_set_out_dma(ctx);
520
521 INIT_LIST_HEAD(&fimc->vid_cap.pending_buf_q);
522 INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q);
523 fimc->vid_cap.active_buf_cnt = 0;
524 fimc->vid_cap.frame_count = 0;
525
526 set_bit(ST_CAPT_PEND, &fimc->state);
527 ret = videobuf_streamon(&fimc->vid_cap.vbq);
528
529s_unlock:
530 mutex_unlock(&fimc->lock);
531 return ret;
532}
533
534static int fimc_cap_streamoff(struct file *file, void *priv,
535 enum v4l2_buf_type type)
536{
537 struct fimc_ctx *ctx = priv;
538 struct fimc_dev *fimc = ctx->fimc_dev;
539 struct fimc_vid_cap *cap = &fimc->vid_cap;
540 unsigned long flags;
541 int ret;
542
543 spin_lock_irqsave(&fimc->slock, flags);
544 if (!fimc_capture_running(fimc) && !fimc_capture_pending(fimc)) {
545 spin_unlock_irqrestore(&fimc->slock, flags);
546 dbg("state: 0x%lx", fimc->state);
547 return -EINVAL;
548 }
549 spin_unlock_irqrestore(&fimc->slock, flags);
550
551 if (mutex_lock_interruptible(&fimc->lock))
552 return -ERESTARTSYS;
553
554 fimc_stop_capture(fimc);
555 ret = videobuf_streamoff(&cap->vbq);
556 mutex_unlock(&fimc->lock);
557 return ret;
558}
559
560static int fimc_cap_reqbufs(struct file *file, void *priv,
561 struct v4l2_requestbuffers *reqbufs)
562{
563 struct fimc_ctx *ctx = priv;
564 struct fimc_dev *fimc = ctx->fimc_dev;
565 struct fimc_vid_cap *cap = &fimc->vid_cap;
566 int ret;
567
568 if (fimc_capture_active(ctx->fimc_dev))
569 return -EBUSY;
570
571 if (mutex_lock_interruptible(&fimc->lock))
572 return -ERESTARTSYS;
573
574 ret = videobuf_reqbufs(&cap->vbq, reqbufs);
575 if (!ret)
576 cap->reqbufs_count = reqbufs->count;
577
578 mutex_unlock(&fimc->lock);
579 return ret;
580}
581
582static int fimc_cap_querybuf(struct file *file, void *priv,
583 struct v4l2_buffer *buf)
584{
585 struct fimc_ctx *ctx = priv;
586 struct fimc_vid_cap *cap = &ctx->fimc_dev->vid_cap;
587
588 if (fimc_capture_active(ctx->fimc_dev))
589 return -EBUSY;
590
591 return videobuf_querybuf(&cap->vbq, buf);
592}
593
594static int fimc_cap_qbuf(struct file *file, void *priv,
595 struct v4l2_buffer *buf)
596{
597 struct fimc_ctx *ctx = priv;
598 struct fimc_dev *fimc = ctx->fimc_dev;
599 struct fimc_vid_cap *cap = &fimc->vid_cap;
600 int ret;
601
602 if (mutex_lock_interruptible(&fimc->lock))
603 return -ERESTARTSYS;
604
605 ret = videobuf_qbuf(&cap->vbq, buf);
606
607 mutex_unlock(&fimc->lock);
608 return ret;
609}
610
611static int fimc_cap_dqbuf(struct file *file, void *priv,
612 struct v4l2_buffer *buf)
613{
614 struct fimc_ctx *ctx = priv;
615 int ret;
616
617 if (mutex_lock_interruptible(&ctx->fimc_dev->lock))
618 return -ERESTARTSYS;
619
620 ret = videobuf_dqbuf(&ctx->fimc_dev->vid_cap.vbq, buf,
621 file->f_flags & O_NONBLOCK);
622
623 mutex_unlock(&ctx->fimc_dev->lock);
624 return ret;
625}
626
627static int fimc_cap_s_ctrl(struct file *file, void *priv,
628 struct v4l2_control *ctrl)
629{
630 struct fimc_ctx *ctx = priv;
631 int ret = -EINVAL;
632
633 if (mutex_lock_interruptible(&ctx->fimc_dev->lock))
634 return -ERESTARTSYS;
635
636 /* Allow any controls but 90/270 rotation while streaming */
637 if (!fimc_capture_active(ctx->fimc_dev) ||
638 ctrl->id != V4L2_CID_ROTATE ||
639 (ctrl->value != 90 && ctrl->value != 270)) {
640 ret = check_ctrl_val(ctx, ctrl);
641 if (!ret) {
642 ret = fimc_s_ctrl(ctx, ctrl);
643 if (!ret)
644 ctx->state |= FIMC_PARAMS;
645 }
646 }
647 if (ret == -EINVAL)
648 ret = v4l2_subdev_call(ctx->fimc_dev->vid_cap.sd,
649 core, s_ctrl, ctrl);
650
651 mutex_unlock(&ctx->fimc_dev->lock);
652 return ret;
653}
654
655static int fimc_cap_s_crop(struct file *file, void *fh,
656 struct v4l2_crop *cr)
657{
658 struct fimc_frame *f;
659 struct fimc_ctx *ctx = file->private_data;
660 struct fimc_dev *fimc = ctx->fimc_dev;
661 int ret = -EINVAL;
662
663 if (fimc_capture_active(fimc))
664 return -EBUSY;
665
666 ret = fimc_try_crop(ctx, cr);
667 if (ret)
668 return ret;
669
670 if (mutex_lock_interruptible(&fimc->lock))
671 return -ERESTARTSYS;
672
673 if (!(ctx->state & FIMC_DST_FMT)) {
674 v4l2_err(&fimc->vid_cap.v4l2_dev,
675 "Capture color format not set\n");
676 goto sc_unlock;
677 }
678
679 f = &ctx->s_frame;
680 /* Check for the pixel scaling ratio when cropping input image. */
681 ret = fimc_check_scaler_ratio(&cr->c, &ctx->d_frame);
682 if (ret) {
683 v4l2_err(&fimc->vid_cap.v4l2_dev, "Out of the scaler range");
684 } else {
685 ret = 0;
686 f->offs_h = cr->c.left;
687 f->offs_v = cr->c.top;
688 f->width = cr->c.width;
689 f->height = cr->c.height;
690 }
691
692sc_unlock:
693 mutex_unlock(&fimc->lock);
694 return ret;
695}
696
697
698static const struct v4l2_ioctl_ops fimc_capture_ioctl_ops = {
699 .vidioc_querycap = fimc_vidioc_querycap_capture,
700
701 .vidioc_enum_fmt_vid_cap = fimc_vidioc_enum_fmt,
702 .vidioc_try_fmt_vid_cap = fimc_vidioc_try_fmt,
703 .vidioc_s_fmt_vid_cap = fimc_cap_s_fmt,
704 .vidioc_g_fmt_vid_cap = fimc_vidioc_g_fmt,
705
706 .vidioc_reqbufs = fimc_cap_reqbufs,
707 .vidioc_querybuf = fimc_cap_querybuf,
708
709 .vidioc_qbuf = fimc_cap_qbuf,
710 .vidioc_dqbuf = fimc_cap_dqbuf,
711
712 .vidioc_streamon = fimc_cap_streamon,
713 .vidioc_streamoff = fimc_cap_streamoff,
714
715 .vidioc_queryctrl = fimc_vidioc_queryctrl,
716 .vidioc_g_ctrl = fimc_vidioc_g_ctrl,
717 .vidioc_s_ctrl = fimc_cap_s_ctrl,
718
719 .vidioc_g_crop = fimc_vidioc_g_crop,
720 .vidioc_s_crop = fimc_cap_s_crop,
721 .vidioc_cropcap = fimc_vidioc_cropcap,
722
723 .vidioc_enum_input = fimc_cap_enum_input,
724 .vidioc_s_input = fimc_cap_s_input,
725 .vidioc_g_input = fimc_cap_g_input,
726};
727
728int fimc_register_capture_device(struct fimc_dev *fimc)
729{
730 struct v4l2_device *v4l2_dev = &fimc->vid_cap.v4l2_dev;
731 struct video_device *vfd;
732 struct fimc_vid_cap *vid_cap;
733 struct fimc_ctx *ctx;
734 struct v4l2_format f;
735 int ret;
736
737 ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
738 if (!ctx)
739 return -ENOMEM;
740
741 ctx->fimc_dev = fimc;
742 ctx->in_path = FIMC_CAMERA;
743 ctx->out_path = FIMC_DMA;
744 ctx->state = FIMC_CTX_CAP;
745
746 f.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
747 ctx->d_frame.fmt = find_format(&f, FMT_FLAGS_M2M);
748
749 if (!v4l2_dev->name[0])
750 snprintf(v4l2_dev->name, sizeof(v4l2_dev->name),
751 "%s.capture", dev_name(&fimc->pdev->dev));
752
753 ret = v4l2_device_register(NULL, v4l2_dev);
754 if (ret)
755 goto err_info;
756
757 vfd = video_device_alloc();
758 if (!vfd) {
759 v4l2_err(v4l2_dev, "Failed to allocate video device\n");
760 goto err_v4l2_reg;
761 }
762
763 snprintf(vfd->name, sizeof(vfd->name), "%s:cap",
764 dev_name(&fimc->pdev->dev));
765
766 vfd->fops = &fimc_capture_fops;
767 vfd->ioctl_ops = &fimc_capture_ioctl_ops;
768 vfd->minor = -1;
769 vfd->release = video_device_release;
770 video_set_drvdata(vfd, fimc);
771
772 vid_cap = &fimc->vid_cap;
773 vid_cap->vfd = vfd;
774 vid_cap->active_buf_cnt = 0;
775 vid_cap->reqbufs_count = 0;
776 vid_cap->refcnt = 0;
777 /* The default color format for image sensor. */
778 vid_cap->fmt.code = V4L2_MBUS_FMT_YUYV8_2X8;
779
780 INIT_LIST_HEAD(&vid_cap->pending_buf_q);
781 INIT_LIST_HEAD(&vid_cap->active_buf_q);
782 spin_lock_init(&ctx->slock);
783 vid_cap->ctx = ctx;
784
785 videobuf_queue_dma_contig_init(&vid_cap->vbq, &fimc_qops,
786 vid_cap->v4l2_dev.dev, &fimc->irqlock,
787 V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
788 sizeof(struct fimc_vid_buffer), (void *)ctx);
789
790 ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
791 if (ret) {
792 v4l2_err(v4l2_dev, "Failed to register video device\n");
793 goto err_vd_reg;
794 }
795
796 v4l2_info(v4l2_dev,
797 "FIMC capture driver registered as /dev/video%d\n",
798 vfd->num);
799
800 return 0;
801
802err_vd_reg:
803 video_device_release(vfd);
804err_v4l2_reg:
805 v4l2_device_unregister(v4l2_dev);
806err_info:
807 dev_err(&fimc->pdev->dev, "failed to install\n");
808 return ret;
809}
810
811void fimc_unregister_capture_device(struct fimc_dev *fimc)
812{
813 struct fimc_vid_cap *capture = &fimc->vid_cap;
814
815 if (capture->vfd)
816 video_unregister_device(capture->vfd);
817
818 kfree(capture->ctx);
819}
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c
index 23cc054bd7b1..5168a9a5d821 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.c
+++ b/drivers/media/video/s5p-fimc/fimc-core.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * S5P camera interface (video postprocessor) driver 2 * S5P camera interface (video postprocessor) driver
3 * 3 *
4 * Copyright (c) 2010 Samsung Electronics 4 * Copyright (c) 2010 Samsung Electronics Co., Ltd
5 * 5 *
6 * Sylwester Nawrocki, <s.nawrocki@samsung.com> 6 * Sylwester Nawrocki, <s.nawrocki@samsung.com>
7 * 7 *
@@ -38,85 +38,102 @@ static struct fimc_fmt fimc_formats[] = {
38 .depth = 16, 38 .depth = 16,
39 .color = S5P_FIMC_RGB565, 39 .color = S5P_FIMC_RGB565,
40 .buff_cnt = 1, 40 .buff_cnt = 1,
41 .planes_cnt = 1 41 .planes_cnt = 1,
42 .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_BE,
43 .flags = FMT_FLAGS_M2M,
42 }, { 44 }, {
43 .name = "BGR666", 45 .name = "BGR666",
44 .fourcc = V4L2_PIX_FMT_BGR666, 46 .fourcc = V4L2_PIX_FMT_BGR666,
45 .depth = 32, 47 .depth = 32,
46 .color = S5P_FIMC_RGB666, 48 .color = S5P_FIMC_RGB666,
47 .buff_cnt = 1, 49 .buff_cnt = 1,
48 .planes_cnt = 1 50 .planes_cnt = 1,
51 .flags = FMT_FLAGS_M2M,
49 }, { 52 }, {
50 .name = "XRGB-8-8-8-8, 24 bpp", 53 .name = "XRGB-8-8-8-8, 24 bpp",
51 .fourcc = V4L2_PIX_FMT_RGB24, 54 .fourcc = V4L2_PIX_FMT_RGB24,
52 .depth = 32, 55 .depth = 32,
53 .color = S5P_FIMC_RGB888, 56 .color = S5P_FIMC_RGB888,
54 .buff_cnt = 1, 57 .buff_cnt = 1,
55 .planes_cnt = 1 58 .planes_cnt = 1,
59 .flags = FMT_FLAGS_M2M,
56 }, { 60 }, {
57 .name = "YUV 4:2:2 packed, YCbYCr", 61 .name = "YUV 4:2:2 packed, YCbYCr",
58 .fourcc = V4L2_PIX_FMT_YUYV, 62 .fourcc = V4L2_PIX_FMT_YUYV,
59 .depth = 16, 63 .depth = 16,
60 .color = S5P_FIMC_YCBYCR422, 64 .color = S5P_FIMC_YCBYCR422,
61 .buff_cnt = 1, 65 .buff_cnt = 1,
62 .planes_cnt = 1 66 .planes_cnt = 1,
63 }, { 67 .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
68 .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM,
69 }, {
64 .name = "YUV 4:2:2 packed, CbYCrY", 70 .name = "YUV 4:2:2 packed, CbYCrY",
65 .fourcc = V4L2_PIX_FMT_UYVY, 71 .fourcc = V4L2_PIX_FMT_UYVY,
66 .depth = 16, 72 .depth = 16,
67 .color = S5P_FIMC_CBYCRY422, 73 .color = S5P_FIMC_CBYCRY422,
68 .buff_cnt = 1, 74 .buff_cnt = 1,
69 .planes_cnt = 1 75 .planes_cnt = 1,
76 .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8,
77 .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM,
70 }, { 78 }, {
71 .name = "YUV 4:2:2 packed, CrYCbY", 79 .name = "YUV 4:2:2 packed, CrYCbY",
72 .fourcc = V4L2_PIX_FMT_VYUY, 80 .fourcc = V4L2_PIX_FMT_VYUY,
73 .depth = 16, 81 .depth = 16,
74 .color = S5P_FIMC_CRYCBY422, 82 .color = S5P_FIMC_CRYCBY422,
75 .buff_cnt = 1, 83 .buff_cnt = 1,
76 .planes_cnt = 1 84 .planes_cnt = 1,
85 .mbus_code = V4L2_MBUS_FMT_VYUY8_2X8,
86 .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM,
77 }, { 87 }, {
78 .name = "YUV 4:2:2 packed, YCrYCb", 88 .name = "YUV 4:2:2 packed, YCrYCb",
79 .fourcc = V4L2_PIX_FMT_YVYU, 89 .fourcc = V4L2_PIX_FMT_YVYU,
80 .depth = 16, 90 .depth = 16,
81 .color = S5P_FIMC_YCRYCB422, 91 .color = S5P_FIMC_YCRYCB422,
82 .buff_cnt = 1, 92 .buff_cnt = 1,
83 .planes_cnt = 1 93 .planes_cnt = 1,
94 .mbus_code = V4L2_MBUS_FMT_YVYU8_2X8,
95 .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM,
84 }, { 96 }, {
85 .name = "YUV 4:2:2 planar, Y/Cb/Cr", 97 .name = "YUV 4:2:2 planar, Y/Cb/Cr",
86 .fourcc = V4L2_PIX_FMT_YUV422P, 98 .fourcc = V4L2_PIX_FMT_YUV422P,
87 .depth = 12, 99 .depth = 12,
88 .color = S5P_FIMC_YCBCR422, 100 .color = S5P_FIMC_YCBCR422,
89 .buff_cnt = 1, 101 .buff_cnt = 1,
90 .planes_cnt = 3 102 .planes_cnt = 3,
103 .flags = FMT_FLAGS_M2M,
91 }, { 104 }, {
92 .name = "YUV 4:2:2 planar, Y/CbCr", 105 .name = "YUV 4:2:2 planar, Y/CbCr",
93 .fourcc = V4L2_PIX_FMT_NV16, 106 .fourcc = V4L2_PIX_FMT_NV16,
94 .depth = 16, 107 .depth = 16,
95 .color = S5P_FIMC_YCBCR422, 108 .color = S5P_FIMC_YCBCR422,
96 .buff_cnt = 1, 109 .buff_cnt = 1,
97 .planes_cnt = 2 110 .planes_cnt = 2,
111 .flags = FMT_FLAGS_M2M,
98 }, { 112 }, {
99 .name = "YUV 4:2:2 planar, Y/CrCb", 113 .name = "YUV 4:2:2 planar, Y/CrCb",
100 .fourcc = V4L2_PIX_FMT_NV61, 114 .fourcc = V4L2_PIX_FMT_NV61,
101 .depth = 16, 115 .depth = 16,
102 .color = S5P_FIMC_RGB565, 116 .color = S5P_FIMC_RGB565,
103 .buff_cnt = 1, 117 .buff_cnt = 1,
104 .planes_cnt = 2 118 .planes_cnt = 2,
119 .flags = FMT_FLAGS_M2M,
105 }, { 120 }, {
106 .name = "YUV 4:2:0 planar, YCbCr", 121 .name = "YUV 4:2:0 planar, YCbCr",
107 .fourcc = V4L2_PIX_FMT_YUV420, 122 .fourcc = V4L2_PIX_FMT_YUV420,
108 .depth = 12, 123 .depth = 12,
109 .color = S5P_FIMC_YCBCR420, 124 .color = S5P_FIMC_YCBCR420,
110 .buff_cnt = 1, 125 .buff_cnt = 1,
111 .planes_cnt = 3 126 .planes_cnt = 3,
127 .flags = FMT_FLAGS_M2M,
112 }, { 128 }, {
113 .name = "YUV 4:2:0 planar, Y/CbCr", 129 .name = "YUV 4:2:0 planar, Y/CbCr",
114 .fourcc = V4L2_PIX_FMT_NV12, 130 .fourcc = V4L2_PIX_FMT_NV12,
115 .depth = 12, 131 .depth = 12,
116 .color = S5P_FIMC_YCBCR420, 132 .color = S5P_FIMC_YCBCR420,
117 .buff_cnt = 1, 133 .buff_cnt = 1,
118 .planes_cnt = 2 134 .planes_cnt = 2,
119 } 135 .flags = FMT_FLAGS_M2M,
136 },
120}; 137};
121 138
122static struct v4l2_queryctrl fimc_ctrls[] = { 139static struct v4l2_queryctrl fimc_ctrls[] = {
@@ -156,7 +173,7 @@ static struct v4l2_queryctrl *get_ctrl(int id)
156 return NULL; 173 return NULL;
157} 174}
158 175
159static int fimc_check_scaler_ratio(struct v4l2_rect *r, struct fimc_frame *f) 176int fimc_check_scaler_ratio(struct v4l2_rect *r, struct fimc_frame *f)
160{ 177{
161 if (r->width > f->width) { 178 if (r->width > f->width) {
162 if (f->width > (r->width * SCALER_MAX_HRATIO)) 179 if (f->width > (r->width * SCALER_MAX_HRATIO))
@@ -199,7 +216,7 @@ static int fimc_get_scaler_factor(u32 src, u32 tar, u32 *ratio, u32 *shift)
199 return 0; 216 return 0;
200} 217}
201 218
202static int fimc_set_scaler_info(struct fimc_ctx *ctx) 219int fimc_set_scaler_info(struct fimc_ctx *ctx)
203{ 220{
204 struct fimc_scaler *sc = &ctx->scaler; 221 struct fimc_scaler *sc = &ctx->scaler;
205 struct fimc_frame *s_frame = &ctx->s_frame; 222 struct fimc_frame *s_frame = &ctx->s_frame;
@@ -259,6 +276,51 @@ static int fimc_set_scaler_info(struct fimc_ctx *ctx)
259 return 0; 276 return 0;
260} 277}
261 278
279static void fimc_capture_handler(struct fimc_dev *fimc)
280{
281 struct fimc_vid_cap *cap = &fimc->vid_cap;
282 struct fimc_vid_buffer *v_buf = NULL;
283
284 if (!list_empty(&cap->active_buf_q)) {
285 v_buf = active_queue_pop(cap);
286 fimc_buf_finish(fimc, v_buf);
287 }
288
289 if (test_and_clear_bit(ST_CAPT_SHUT, &fimc->state)) {
290 wake_up(&fimc->irq_queue);
291 return;
292 }
293
294 if (!list_empty(&cap->pending_buf_q)) {
295
296 v_buf = pending_queue_pop(cap);
297 fimc_hw_set_output_addr(fimc, &v_buf->paddr, cap->buf_index);
298 v_buf->index = cap->buf_index;
299
300 dbg("hw ptr: %d, sw ptr: %d",
301 fimc_hw_get_frame_index(fimc), cap->buf_index);
302
303 spin_lock(&fimc->irqlock);
304 v_buf->vb.state = VIDEOBUF_ACTIVE;
305 spin_unlock(&fimc->irqlock);
306
307 /* Move the buffer to the capture active queue */
308 active_queue_add(cap, v_buf);
309
310 dbg("next frame: %d, done frame: %d",
311 fimc_hw_get_frame_index(fimc), v_buf->index);
312
313 if (++cap->buf_index >= FIMC_MAX_OUT_BUFS)
314 cap->buf_index = 0;
315
316 } else if (test_and_clear_bit(ST_CAPT_STREAM, &fimc->state) &&
317 cap->active_buf_cnt <= 1) {
318 fimc_deactivate_capture(fimc);
319 }
320
321 dbg("frame: %d, active_buf_cnt= %d",
322 fimc_hw_get_frame_index(fimc), cap->active_buf_cnt);
323}
262 324
263static irqreturn_t fimc_isr(int irq, void *priv) 325static irqreturn_t fimc_isr(int irq, void *priv)
264{ 326{
@@ -285,6 +347,16 @@ static irqreturn_t fimc_isr(int irq, void *priv)
285 spin_unlock(&fimc->irqlock); 347 spin_unlock(&fimc->irqlock);
286 v4l2_m2m_job_finish(fimc->m2m.m2m_dev, ctx->m2m_ctx); 348 v4l2_m2m_job_finish(fimc->m2m.m2m_dev, ctx->m2m_ctx);
287 } 349 }
350 goto isr_unlock;
351
352 }
353
354 if (test_bit(ST_CAPT_RUN, &fimc->state))
355 fimc_capture_handler(fimc);
356
357 if (test_and_clear_bit(ST_CAPT_PEND, &fimc->state)) {
358 set_bit(ST_CAPT_RUN, &fimc->state);
359 wake_up(&fimc->irq_queue);
288 } 360 }
289 361
290isr_unlock: 362isr_unlock:
@@ -424,7 +496,7 @@ static void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f)
424 * 496 *
425 * Return: 0 if dimensions are valid or non zero otherwise. 497 * Return: 0 if dimensions are valid or non zero otherwise.
426 */ 498 */
427static int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags) 499int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags)
428{ 500{
429 struct fimc_frame *s_frame, *d_frame; 501 struct fimc_frame *s_frame, *d_frame;
430 struct fimc_vid_buffer *buf = NULL; 502 struct fimc_vid_buffer *buf = NULL;
@@ -513,9 +585,9 @@ static void fimc_dma_run(void *priv)
513 if (ctx->state & FIMC_PARAMS) 585 if (ctx->state & FIMC_PARAMS)
514 fimc_hw_set_out_dma(ctx); 586 fimc_hw_set_out_dma(ctx);
515 587
516 ctx->state = 0;
517 fimc_activate_capture(ctx); 588 fimc_activate_capture(ctx);
518 589
590 ctx->state &= (FIMC_CTX_M2M | FIMC_CTX_CAP);
519 fimc_hw_activate_input_dma(fimc, true); 591 fimc_hw_activate_input_dma(fimc, true);
520 592
521dma_unlock: 593dma_unlock:
@@ -598,10 +670,31 @@ static void fimc_buf_queue(struct videobuf_queue *vq,
598 struct videobuf_buffer *vb) 670 struct videobuf_buffer *vb)
599{ 671{
600 struct fimc_ctx *ctx = vq->priv_data; 672 struct fimc_ctx *ctx = vq->priv_data;
601 v4l2_m2m_buf_queue(ctx->m2m_ctx, vq, vb); 673 struct fimc_dev *fimc = ctx->fimc_dev;
674 struct fimc_vid_cap *cap = &fimc->vid_cap;
675 unsigned long flags;
676
677 dbg("ctx: %p, ctx->state: 0x%x", ctx, ctx->state);
678
679 if ((ctx->state & FIMC_CTX_M2M) && ctx->m2m_ctx) {
680 v4l2_m2m_buf_queue(ctx->m2m_ctx, vq, vb);
681 } else if (ctx->state & FIMC_CTX_CAP) {
682 spin_lock_irqsave(&fimc->slock, flags);
683 fimc_vid_cap_buf_queue(fimc, (struct fimc_vid_buffer *)vb);
684
685 dbg("fimc->cap.active_buf_cnt: %d",
686 fimc->vid_cap.active_buf_cnt);
687
688 if (cap->active_buf_cnt >= cap->reqbufs_count ||
689 cap->active_buf_cnt >= FIMC_MAX_OUT_BUFS) {
690 if (!test_and_set_bit(ST_CAPT_STREAM, &fimc->state))
691 fimc_activate_capture(ctx);
692 }
693 spin_unlock_irqrestore(&fimc->slock, flags);
694 }
602} 695}
603 696
604static struct videobuf_queue_ops fimc_qops = { 697struct videobuf_queue_ops fimc_qops = {
605 .buf_setup = fimc_buf_setup, 698 .buf_setup = fimc_buf_setup,
606 .buf_prepare = fimc_buf_prepare, 699 .buf_prepare = fimc_buf_prepare,
607 .buf_queue = fimc_buf_queue, 700 .buf_queue = fimc_buf_queue,
@@ -624,7 +717,7 @@ static int fimc_m2m_querycap(struct file *file, void *priv,
624 return 0; 717 return 0;
625} 718}
626 719
627static int fimc_m2m_enum_fmt(struct file *file, void *priv, 720int fimc_vidioc_enum_fmt(struct file *file, void *priv,
628 struct v4l2_fmtdesc *f) 721 struct v4l2_fmtdesc *f)
629{ 722{
630 struct fimc_fmt *fmt; 723 struct fimc_fmt *fmt;
@@ -635,109 +728,139 @@ static int fimc_m2m_enum_fmt(struct file *file, void *priv,
635 fmt = &fimc_formats[f->index]; 728 fmt = &fimc_formats[f->index];
636 strncpy(f->description, fmt->name, sizeof(f->description) - 1); 729 strncpy(f->description, fmt->name, sizeof(f->description) - 1);
637 f->pixelformat = fmt->fourcc; 730 f->pixelformat = fmt->fourcc;
731
638 return 0; 732 return 0;
639} 733}
640 734
641static int fimc_m2m_g_fmt(struct file *file, void *priv, struct v4l2_format *f) 735int fimc_vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
642{ 736{
643 struct fimc_ctx *ctx = priv; 737 struct fimc_ctx *ctx = priv;
738 struct fimc_dev *fimc = ctx->fimc_dev;
644 struct fimc_frame *frame; 739 struct fimc_frame *frame;
645 740
646 frame = ctx_get_frame(ctx, f->type); 741 frame = ctx_get_frame(ctx, f->type);
647 if (IS_ERR(frame)) 742 if (IS_ERR(frame))
648 return PTR_ERR(frame); 743 return PTR_ERR(frame);
649 744
745 if (mutex_lock_interruptible(&fimc->lock))
746 return -ERESTARTSYS;
747
650 f->fmt.pix.width = frame->width; 748 f->fmt.pix.width = frame->width;
651 f->fmt.pix.height = frame->height; 749 f->fmt.pix.height = frame->height;
652 f->fmt.pix.field = V4L2_FIELD_NONE; 750 f->fmt.pix.field = V4L2_FIELD_NONE;
653 f->fmt.pix.pixelformat = frame->fmt->fourcc; 751 f->fmt.pix.pixelformat = frame->fmt->fourcc;
654 752
753 mutex_unlock(&fimc->lock);
655 return 0; 754 return 0;
656} 755}
657 756
658static struct fimc_fmt *find_format(struct v4l2_format *f) 757struct fimc_fmt *find_format(struct v4l2_format *f, unsigned int mask)
659{ 758{
660 struct fimc_fmt *fmt; 759 struct fimc_fmt *fmt;
661 unsigned int i; 760 unsigned int i;
662 761
663 for (i = 0; i < ARRAY_SIZE(fimc_formats); ++i) { 762 for (i = 0; i < ARRAY_SIZE(fimc_formats); ++i) {
664 fmt = &fimc_formats[i]; 763 fmt = &fimc_formats[i];
665 if (fmt->fourcc == f->fmt.pix.pixelformat) 764 if (fmt->fourcc == f->fmt.pix.pixelformat &&
765 (fmt->flags & mask))
666 break; 766 break;
667 } 767 }
668 if (i == ARRAY_SIZE(fimc_formats))
669 return NULL;
670 768
671 return fmt; 769 return (i == ARRAY_SIZE(fimc_formats)) ? NULL : fmt;
672} 770}
673 771
674static int fimc_m2m_try_fmt(struct file *file, void *priv, 772struct fimc_fmt *find_mbus_format(struct v4l2_mbus_framefmt *f,
675 struct v4l2_format *f) 773 unsigned int mask)
676{ 774{
677 struct fimc_fmt *fmt; 775 struct fimc_fmt *fmt;
678 u32 max_width, max_height, mod_x, mod_y; 776 unsigned int i;
777
778 for (i = 0; i < ARRAY_SIZE(fimc_formats); ++i) {
779 fmt = &fimc_formats[i];
780 if (fmt->mbus_code == f->code && (fmt->flags & mask))
781 break;
782 }
783
784 return (i == ARRAY_SIZE(fimc_formats)) ? NULL : fmt;
785}
786
787
788int fimc_vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
789{
679 struct fimc_ctx *ctx = priv; 790 struct fimc_ctx *ctx = priv;
680 struct fimc_dev *fimc = ctx->fimc_dev; 791 struct fimc_dev *fimc = ctx->fimc_dev;
681 struct v4l2_pix_format *pix = &f->fmt.pix;
682 struct samsung_fimc_variant *variant = fimc->variant; 792 struct samsung_fimc_variant *variant = fimc->variant;
793 struct v4l2_pix_format *pix = &f->fmt.pix;
794 struct fimc_fmt *fmt;
795 u32 max_width, mod_x, mod_y, mask;
796 int ret = -EINVAL, is_output = 0;
683 797
684 fmt = find_format(f); 798 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
685 if (!fmt) { 799 if (ctx->state & FIMC_CTX_CAP)
686 v4l2_err(&fimc->m2m.v4l2_dev, 800 return -EINVAL;
687 "Fourcc format (0x%X) invalid.\n", pix->pixelformat); 801 is_output = 1;
802 } else if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
688 return -EINVAL; 803 return -EINVAL;
689 } 804 }
690 805
806 dbg("w: %d, h: %d, bpl: %d",
807 pix->width, pix->height, pix->bytesperline);
808
809 if (mutex_lock_interruptible(&fimc->lock))
810 return -ERESTARTSYS;
811
812 mask = is_output ? FMT_FLAGS_M2M : FMT_FLAGS_M2M | FMT_FLAGS_CAM;
813 fmt = find_format(f, mask);
814 if (!fmt) {
815 v4l2_err(&fimc->m2m.v4l2_dev, "Fourcc format (0x%X) invalid.\n",
816 pix->pixelformat);
817 goto tf_out;
818 }
819
691 if (pix->field == V4L2_FIELD_ANY) 820 if (pix->field == V4L2_FIELD_ANY)
692 pix->field = V4L2_FIELD_NONE; 821 pix->field = V4L2_FIELD_NONE;
693 else if (V4L2_FIELD_NONE != pix->field) 822 else if (V4L2_FIELD_NONE != pix->field)
694 return -EINVAL; 823 goto tf_out;
695 824
696 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { 825 if (is_output) {
697 max_width = variant->scaler_dis_w; 826 max_width = variant->scaler_dis_w;
698 max_height = variant->scaler_dis_w; 827 mod_x = ffs(variant->min_inp_pixsize) - 1;
699 mod_x = variant->min_inp_pixsize;
700 mod_y = variant->min_inp_pixsize;
701 } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
702 max_width = variant->out_rot_dis_w;
703 max_height = variant->out_rot_dis_w;
704 mod_x = variant->min_out_pixsize;
705 mod_y = variant->min_out_pixsize;
706 } else { 828 } else {
707 err("Wrong stream type (%d)", f->type); 829 max_width = variant->out_rot_dis_w;
708 return -EINVAL; 830 mod_x = ffs(variant->min_out_pixsize) - 1;
709 } 831 }
710 832
711 dbg("max_w= %d, max_h= %d", max_width, max_height);
712
713 if (pix->height > max_height)
714 pix->height = max_height;
715 if (pix->width > max_width)
716 pix->width = max_width;
717
718 if (tiled_fmt(fmt)) { 833 if (tiled_fmt(fmt)) {
719 mod_x = 64; /* 64x32 tile */ 834 mod_x = 6; /* 64 x 32 pixels tile */
720 mod_y = 32; 835 mod_y = 5;
836 } else {
837 if (fimc->id == 1 && fimc->variant->pix_hoff)
838 mod_y = fimc_fmt_is_rgb(fmt->color) ? 0 : 1;
839 else
840 mod_y = mod_x;
721 } 841 }
722 842
723 dbg("mod_x= 0x%X, mod_y= 0x%X", mod_x, mod_y); 843 dbg("mod_x: %d, mod_y: %d, max_w: %d", mod_x, mod_y, max_width);
724 844
725 pix->width = (pix->width == 0) ? mod_x : ALIGN(pix->width, mod_x); 845 v4l_bound_align_image(&pix->width, 16, max_width, mod_x,
726 pix->height = (pix->height == 0) ? mod_y : ALIGN(pix->height, mod_y); 846 &pix->height, 8, variant->scaler_dis_w, mod_y, 0);
727 847
728 if (pix->bytesperline == 0 || 848 if (pix->bytesperline == 0 ||
729 pix->bytesperline * 8 / fmt->depth > pix->width) 849 (pix->bytesperline * 8 / fmt->depth) > pix->width)
730 pix->bytesperline = (pix->width * fmt->depth) >> 3; 850 pix->bytesperline = (pix->width * fmt->depth) >> 3;
731 851
732 if (pix->sizeimage == 0) 852 if (pix->sizeimage == 0)
733 pix->sizeimage = pix->height * pix->bytesperline; 853 pix->sizeimage = pix->height * pix->bytesperline;
734 854
735 dbg("pix->bytesperline= %d, fmt->depth= %d", 855 dbg("w: %d, h: %d, bpl: %d, depth: %d",
736 pix->bytesperline, fmt->depth); 856 pix->width, pix->height, pix->bytesperline, fmt->depth);
737 857
738 return 0; 858 ret = 0;
739}
740 859
860tf_out:
861 mutex_unlock(&fimc->lock);
862 return ret;
863}
741 864
742static int fimc_m2m_s_fmt(struct file *file, void *priv, struct v4l2_format *f) 865static int fimc_m2m_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
743{ 866{
@@ -750,9 +873,7 @@ static int fimc_m2m_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
750 unsigned long flags; 873 unsigned long flags;
751 int ret = 0; 874 int ret = 0;
752 875
753 BUG_ON(!ctx); 876 ret = fimc_vidioc_try_fmt(file, priv, f);
754
755 ret = fimc_m2m_try_fmt(file, priv, f);
756 if (ret) 877 if (ret)
757 return ret; 878 return ret;
758 879
@@ -785,7 +906,7 @@ static int fimc_m2m_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
785 spin_unlock_irqrestore(&ctx->slock, flags); 906 spin_unlock_irqrestore(&ctx->slock, flags);
786 907
787 pix = &f->fmt.pix; 908 pix = &f->fmt.pix;
788 frame->fmt = find_format(f); 909 frame->fmt = find_format(f, FMT_FLAGS_M2M);
789 if (!frame->fmt) { 910 if (!frame->fmt) {
790 ret = -EINVAL; 911 ret = -EINVAL;
791 goto sf_out; 912 goto sf_out;
@@ -857,21 +978,33 @@ static int fimc_m2m_streamoff(struct file *file, void *priv,
857 return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); 978 return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
858} 979}
859 980
860int fimc_m2m_queryctrl(struct file *file, void *priv, 981int fimc_vidioc_queryctrl(struct file *file, void *priv,
861 struct v4l2_queryctrl *qc) 982 struct v4l2_queryctrl *qc)
862{ 983{
984 struct fimc_ctx *ctx = priv;
863 struct v4l2_queryctrl *c; 985 struct v4l2_queryctrl *c;
986
864 c = get_ctrl(qc->id); 987 c = get_ctrl(qc->id);
865 if (!c) 988 if (c) {
866 return -EINVAL; 989 *qc = *c;
867 *qc = *c; 990 return 0;
868 return 0; 991 }
992
993 if (ctx->state & FIMC_CTX_CAP)
994 return v4l2_subdev_call(ctx->fimc_dev->vid_cap.sd,
995 core, queryctrl, qc);
996 return -EINVAL;
869} 997}
870 998
871int fimc_m2m_g_ctrl(struct file *file, void *priv, 999int fimc_vidioc_g_ctrl(struct file *file, void *priv,
872 struct v4l2_control *ctrl) 1000 struct v4l2_control *ctrl)
873{ 1001{
874 struct fimc_ctx *ctx = priv; 1002 struct fimc_ctx *ctx = priv;
1003 struct fimc_dev *fimc = ctx->fimc_dev;
1004 int ret = 0;
1005
1006 if (mutex_lock_interruptible(&fimc->lock))
1007 return -ERESTARTSYS;
875 1008
876 switch (ctrl->id) { 1009 switch (ctrl->id) {
877 case V4L2_CID_HFLIP: 1010 case V4L2_CID_HFLIP:
@@ -884,15 +1017,22 @@ int fimc_m2m_g_ctrl(struct file *file, void *priv,
884 ctrl->value = ctx->rotation; 1017 ctrl->value = ctx->rotation;
885 break; 1018 break;
886 default: 1019 default:
887 v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev, "Invalid control\n"); 1020 if (ctx->state & FIMC_CTX_CAP) {
888 return -EINVAL; 1021 ret = v4l2_subdev_call(fimc->vid_cap.sd, core,
1022 g_ctrl, ctrl);
1023 } else {
1024 v4l2_err(&fimc->m2m.v4l2_dev,
1025 "Invalid control\n");
1026 ret = -EINVAL;
1027 }
889 } 1028 }
890 dbg("ctrl->value= %d", ctrl->value); 1029 dbg("ctrl->value= %d", ctrl->value);
891 return 0; 1030
1031 mutex_unlock(&fimc->lock);
1032 return ret;
892} 1033}
893 1034
894static int check_ctrl_val(struct fimc_ctx *ctx, 1035int check_ctrl_val(struct fimc_ctx *ctx, struct v4l2_control *ctrl)
895 struct v4l2_control *ctrl)
896{ 1036{
897 struct v4l2_queryctrl *c; 1037 struct v4l2_queryctrl *c;
898 c = get_ctrl(ctrl->id); 1038 c = get_ctrl(ctrl->id);
@@ -909,22 +1049,23 @@ static int check_ctrl_val(struct fimc_ctx *ctx,
909 return 0; 1049 return 0;
910} 1050}
911 1051
912int fimc_m2m_s_ctrl(struct file *file, void *priv, 1052int fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_control *ctrl)
913 struct v4l2_control *ctrl)
914{ 1053{
915 struct fimc_ctx *ctx = priv;
916 struct samsung_fimc_variant *variant = ctx->fimc_dev->variant; 1054 struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
1055 struct fimc_dev *fimc = ctx->fimc_dev;
917 unsigned long flags; 1056 unsigned long flags;
918 int ret = 0;
919 1057
920 ret = check_ctrl_val(ctx, ctrl); 1058 if (ctx->rotation != 0 &&
921 if (ret) 1059 (ctrl->id == V4L2_CID_HFLIP || ctrl->id == V4L2_CID_VFLIP)) {
922 return ret; 1060 v4l2_err(&fimc->m2m.v4l2_dev,
1061 "Simultaneous flip and rotation is not supported\n");
1062 return -EINVAL;
1063 }
1064
1065 spin_lock_irqsave(&ctx->slock, flags);
923 1066
924 switch (ctrl->id) { 1067 switch (ctrl->id) {
925 case V4L2_CID_HFLIP: 1068 case V4L2_CID_HFLIP:
926 if (ctx->rotation != 0)
927 return 0;
928 if (ctrl->value) 1069 if (ctrl->value)
929 ctx->flip |= FLIP_X_AXIS; 1070 ctx->flip |= FLIP_X_AXIS;
930 else 1071 else
@@ -932,8 +1073,6 @@ int fimc_m2m_s_ctrl(struct file *file, void *priv,
932 break; 1073 break;
933 1074
934 case V4L2_CID_VFLIP: 1075 case V4L2_CID_VFLIP:
935 if (ctx->rotation != 0)
936 return 0;
937 if (ctrl->value) 1076 if (ctrl->value)
938 ctx->flip |= FLIP_Y_AXIS; 1077 ctx->flip |= FLIP_Y_AXIS;
939 else 1078 else
@@ -941,77 +1080,95 @@ int fimc_m2m_s_ctrl(struct file *file, void *priv,
941 break; 1080 break;
942 1081
943 case V4L2_CID_ROTATE: 1082 case V4L2_CID_ROTATE:
944 if (ctrl->value == 90 || ctrl->value == 270) { 1083 /* Check for the output rotator availability */
945 if (ctx->out_path == FIMC_LCDFIFO && 1084 if ((ctrl->value == 90 || ctrl->value == 270) &&
946 !variant->has_inp_rot) { 1085 (ctx->in_path == FIMC_DMA && !variant->has_out_rot)) {
947 return -EINVAL; 1086 spin_unlock_irqrestore(&ctx->slock, flags);
948 } else if (ctx->in_path == FIMC_DMA && 1087 return -EINVAL;
949 !variant->has_out_rot) { 1088 } else {
950 return -EINVAL; 1089 ctx->rotation = ctrl->value;
951 }
952 } 1090 }
953 ctx->rotation = ctrl->value;
954 if (ctrl->value == 180)
955 ctx->flip = FLIP_XY_AXIS;
956 break; 1091 break;
957 1092
958 default: 1093 default:
959 v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev, "Invalid control\n"); 1094 spin_unlock_irqrestore(&ctx->slock, flags);
1095 v4l2_err(&fimc->m2m.v4l2_dev, "Invalid control\n");
960 return -EINVAL; 1096 return -EINVAL;
961 } 1097 }
962 spin_lock_irqsave(&ctx->slock, flags);
963 ctx->state |= FIMC_PARAMS; 1098 ctx->state |= FIMC_PARAMS;
964 spin_unlock_irqrestore(&ctx->slock, flags); 1099 spin_unlock_irqrestore(&ctx->slock, flags);
1100
965 return 0; 1101 return 0;
966} 1102}
967 1103
1104static int fimc_m2m_s_ctrl(struct file *file, void *priv,
1105 struct v4l2_control *ctrl)
1106{
1107 struct fimc_ctx *ctx = priv;
1108 int ret = 0;
1109
1110 ret = check_ctrl_val(ctx, ctrl);
1111 if (ret)
1112 return ret;
1113
1114 ret = fimc_s_ctrl(ctx, ctrl);
1115 return 0;
1116}
968 1117
969static int fimc_m2m_cropcap(struct file *file, void *fh, 1118int fimc_vidioc_cropcap(struct file *file, void *fh,
970 struct v4l2_cropcap *cr) 1119 struct v4l2_cropcap *cr)
971{ 1120{
972 struct fimc_frame *frame; 1121 struct fimc_frame *frame;
973 struct fimc_ctx *ctx = fh; 1122 struct fimc_ctx *ctx = fh;
1123 struct fimc_dev *fimc = ctx->fimc_dev;
974 1124
975 frame = ctx_get_frame(ctx, cr->type); 1125 frame = ctx_get_frame(ctx, cr->type);
976 if (IS_ERR(frame)) 1126 if (IS_ERR(frame))
977 return PTR_ERR(frame); 1127 return PTR_ERR(frame);
978 1128
979 cr->bounds.left = 0; 1129 if (mutex_lock_interruptible(&fimc->lock))
980 cr->bounds.top = 0; 1130 return -ERESTARTSYS;
981 cr->bounds.width = frame->f_width; 1131
982 cr->bounds.height = frame->f_height; 1132 cr->bounds.left = 0;
983 cr->defrect.left = frame->offs_h; 1133 cr->bounds.top = 0;
984 cr->defrect.top = frame->offs_v; 1134 cr->bounds.width = frame->f_width;
985 cr->defrect.width = frame->o_width; 1135 cr->bounds.height = frame->f_height;
986 cr->defrect.height = frame->o_height; 1136 cr->defrect = cr->bounds;
1137
1138 mutex_unlock(&fimc->lock);
987 return 0; 1139 return 0;
988} 1140}
989 1141
990static int fimc_m2m_g_crop(struct file *file, void *fh, struct v4l2_crop *cr) 1142int fimc_vidioc_g_crop(struct file *file, void *fh, struct v4l2_crop *cr)
991{ 1143{
992 struct fimc_frame *frame; 1144 struct fimc_frame *frame;
993 struct fimc_ctx *ctx = file->private_data; 1145 struct fimc_ctx *ctx = file->private_data;
1146 struct fimc_dev *fimc = ctx->fimc_dev;
994 1147
995 frame = ctx_get_frame(ctx, cr->type); 1148 frame = ctx_get_frame(ctx, cr->type);
996 if (IS_ERR(frame)) 1149 if (IS_ERR(frame))
997 return PTR_ERR(frame); 1150 return PTR_ERR(frame);
998 1151
1152 if (mutex_lock_interruptible(&fimc->lock))
1153 return -ERESTARTSYS;
1154
999 cr->c.left = frame->offs_h; 1155 cr->c.left = frame->offs_h;
1000 cr->c.top = frame->offs_v; 1156 cr->c.top = frame->offs_v;
1001 cr->c.width = frame->width; 1157 cr->c.width = frame->width;
1002 cr->c.height = frame->height; 1158 cr->c.height = frame->height;
1003 1159
1160 mutex_unlock(&fimc->lock);
1004 return 0; 1161 return 0;
1005} 1162}
1006 1163
1007static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr) 1164int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
1008{ 1165{
1009 struct fimc_ctx *ctx = file->private_data;
1010 struct fimc_dev *fimc = ctx->fimc_dev; 1166 struct fimc_dev *fimc = ctx->fimc_dev;
1011 unsigned long flags;
1012 struct fimc_frame *f; 1167 struct fimc_frame *f;
1013 u32 min_size; 1168 u32 min_size, halign;
1014 int ret = 0; 1169
1170 f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ?
1171 &ctx->s_frame : &ctx->d_frame;
1015 1172
1016 if (cr->c.top < 0 || cr->c.left < 0) { 1173 if (cr->c.top < 0 || cr->c.left < 0) {
1017 v4l2_err(&fimc->m2m.v4l2_dev, 1174 v4l2_err(&fimc->m2m.v4l2_dev,
@@ -1019,66 +1176,98 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
1019 return -EINVAL; 1176 return -EINVAL;
1020 } 1177 }
1021 1178
1022 if (cr->c.width <= 0 || cr->c.height <= 0) {
1023 v4l2_err(&fimc->m2m.v4l2_dev,
1024 "crop width and height must be greater than 0\n");
1025 return -EINVAL;
1026 }
1027
1028 f = ctx_get_frame(ctx, cr->type); 1179 f = ctx_get_frame(ctx, cr->type);
1029 if (IS_ERR(f)) 1180 if (IS_ERR(f))
1030 return PTR_ERR(f); 1181 return PTR_ERR(f);
1031 1182
1032 /* Adjust to required pixel boundary. */ 1183 min_size = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
1033 min_size = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ? 1184 ? fimc->variant->min_inp_pixsize
1034 fimc->variant->min_inp_pixsize : fimc->variant->min_out_pixsize; 1185 : fimc->variant->min_out_pixsize;
1035 1186
1036 cr->c.width = round_down(cr->c.width, min_size); 1187 if (ctx->state & FIMC_CTX_M2M) {
1037 cr->c.height = round_down(cr->c.height, min_size); 1188 if (fimc->id == 1 && fimc->variant->pix_hoff)
1038 cr->c.left = round_down(cr->c.left + 1, min_size); 1189 halign = fimc_fmt_is_rgb(f->fmt->color) ? 0 : 1;
1039 cr->c.top = round_down(cr->c.top + 1, min_size); 1190 else
1040 1191 halign = ffs(min_size) - 1;
1041 if ((cr->c.left + cr->c.width > f->o_width) 1192 /* there are more strict aligment requirements at camera interface */
1042 || (cr->c.top + cr->c.height > f->o_height)) { 1193 } else {
1043 v4l2_err(&fimc->m2m.v4l2_dev, "Error in S_CROP params\n"); 1194 min_size = 16;
1044 return -EINVAL; 1195 halign = 4;
1045 } 1196 }
1046 1197
1198 v4l_bound_align_image(&cr->c.width, min_size, f->o_width,
1199 ffs(min_size) - 1,
1200 &cr->c.height, min_size, f->o_height,
1201 halign, 64/(ALIGN(f->fmt->depth, 8)));
1202
1203 /* adjust left/top if cropping rectangle is out of bounds */
1204 if (cr->c.left + cr->c.width > f->o_width)
1205 cr->c.left = f->o_width - cr->c.width;
1206 if (cr->c.top + cr->c.height > f->o_height)
1207 cr->c.top = f->o_height - cr->c.height;
1208
1209 cr->c.left = round_down(cr->c.left, min_size);
1210 cr->c.top = round_down(cr->c.top,
1211 ctx->state & FIMC_CTX_M2M ? 8 : 16);
1212
1213 dbg("l:%d, t:%d, w:%d, h:%d, f_w: %d, f_h: %d",
1214 cr->c.left, cr->c.top, cr->c.width, cr->c.height,
1215 f->f_width, f->f_height);
1216
1217 return 0;
1218}
1219
1220
1221static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
1222{
1223 struct fimc_ctx *ctx = file->private_data;
1224 struct fimc_dev *fimc = ctx->fimc_dev;
1225 unsigned long flags;
1226 struct fimc_frame *f;
1227 int ret;
1228
1229 ret = fimc_try_crop(ctx, cr);
1230 if (ret)
1231 return ret;
1232
1233 f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ?
1234 &ctx->s_frame : &ctx->d_frame;
1235
1047 spin_lock_irqsave(&ctx->slock, flags); 1236 spin_lock_irqsave(&ctx->slock, flags);
1048 if ((ctx->state & FIMC_SRC_FMT) && (ctx->state & FIMC_DST_FMT)) { 1237 if (~ctx->state & (FIMC_SRC_FMT | FIMC_DST_FMT)) {
1049 /* Check for the pixel scaling ratio when cropping input img. */ 1238 /* Check to see if scaling ratio is within supported range */
1050 if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) 1239 if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
1051 ret = fimc_check_scaler_ratio(&cr->c, &ctx->d_frame); 1240 ret = fimc_check_scaler_ratio(&cr->c, &ctx->d_frame);
1052 else if (cr->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1241 else
1053 ret = fimc_check_scaler_ratio(&cr->c, &ctx->s_frame); 1242 ret = fimc_check_scaler_ratio(&cr->c, &ctx->s_frame);
1054
1055 if (ret) { 1243 if (ret) {
1056 spin_unlock_irqrestore(&ctx->slock, flags); 1244 spin_unlock_irqrestore(&ctx->slock, flags);
1057 v4l2_err(&fimc->m2m.v4l2_dev, "Out of scaler range"); 1245 v4l2_err(&fimc->m2m.v4l2_dev, "Out of scaler range");
1058 return -EINVAL; 1246 return -EINVAL;
1059 } 1247 }
1060 } 1248 }
1061 ctx->state |= FIMC_PARAMS; 1249 ctx->state |= FIMC_PARAMS;
1062 spin_unlock_irqrestore(&ctx->slock, flags);
1063 1250
1064 f->offs_h = cr->c.left; 1251 f->offs_h = cr->c.left;
1065 f->offs_v = cr->c.top; 1252 f->offs_v = cr->c.top;
1066 f->width = cr->c.width; 1253 f->width = cr->c.width;
1067 f->height = cr->c.height; 1254 f->height = cr->c.height;
1255
1256 spin_unlock_irqrestore(&ctx->slock, flags);
1068 return 0; 1257 return 0;
1069} 1258}
1070 1259
1071static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = { 1260static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = {
1072 .vidioc_querycap = fimc_m2m_querycap, 1261 .vidioc_querycap = fimc_m2m_querycap,
1073 1262
1074 .vidioc_enum_fmt_vid_cap = fimc_m2m_enum_fmt, 1263 .vidioc_enum_fmt_vid_cap = fimc_vidioc_enum_fmt,
1075 .vidioc_enum_fmt_vid_out = fimc_m2m_enum_fmt, 1264 .vidioc_enum_fmt_vid_out = fimc_vidioc_enum_fmt,
1076 1265
1077 .vidioc_g_fmt_vid_cap = fimc_m2m_g_fmt, 1266 .vidioc_g_fmt_vid_cap = fimc_vidioc_g_fmt,
1078 .vidioc_g_fmt_vid_out = fimc_m2m_g_fmt, 1267 .vidioc_g_fmt_vid_out = fimc_vidioc_g_fmt,
1079 1268
1080 .vidioc_try_fmt_vid_cap = fimc_m2m_try_fmt, 1269 .vidioc_try_fmt_vid_cap = fimc_vidioc_try_fmt,
1081 .vidioc_try_fmt_vid_out = fimc_m2m_try_fmt, 1270 .vidioc_try_fmt_vid_out = fimc_vidioc_try_fmt,
1082 1271
1083 .vidioc_s_fmt_vid_cap = fimc_m2m_s_fmt, 1272 .vidioc_s_fmt_vid_cap = fimc_m2m_s_fmt,
1084 .vidioc_s_fmt_vid_out = fimc_m2m_s_fmt, 1273 .vidioc_s_fmt_vid_out = fimc_m2m_s_fmt,
@@ -1092,13 +1281,13 @@ static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = {
1092 .vidioc_streamon = fimc_m2m_streamon, 1281 .vidioc_streamon = fimc_m2m_streamon,
1093 .vidioc_streamoff = fimc_m2m_streamoff, 1282 .vidioc_streamoff = fimc_m2m_streamoff,
1094 1283
1095 .vidioc_queryctrl = fimc_m2m_queryctrl, 1284 .vidioc_queryctrl = fimc_vidioc_queryctrl,
1096 .vidioc_g_ctrl = fimc_m2m_g_ctrl, 1285 .vidioc_g_ctrl = fimc_vidioc_g_ctrl,
1097 .vidioc_s_ctrl = fimc_m2m_s_ctrl, 1286 .vidioc_s_ctrl = fimc_m2m_s_ctrl,
1098 1287
1099 .vidioc_g_crop = fimc_m2m_g_crop, 1288 .vidioc_g_crop = fimc_vidioc_g_crop,
1100 .vidioc_s_crop = fimc_m2m_s_crop, 1289 .vidioc_s_crop = fimc_m2m_s_crop,
1101 .vidioc_cropcap = fimc_m2m_cropcap 1290 .vidioc_cropcap = fimc_vidioc_cropcap
1102 1291
1103}; 1292};
1104 1293
@@ -1120,11 +1309,23 @@ static int fimc_m2m_open(struct file *file)
1120 struct fimc_ctx *ctx = NULL; 1309 struct fimc_ctx *ctx = NULL;
1121 int err = 0; 1310 int err = 0;
1122 1311
1123 mutex_lock(&fimc->lock); 1312 if (mutex_lock_interruptible(&fimc->lock))
1313 return -ERESTARTSYS;
1314
1315 dbg("pid: %d, state: 0x%lx, refcnt: %d",
1316 task_pid_nr(current), fimc->state, fimc->vid_cap.refcnt);
1317
1318 /*
1319 * Return if the corresponding video capture node
1320 * is already opened.
1321 */
1322 if (fimc->vid_cap.refcnt > 0) {
1323 mutex_unlock(&fimc->lock);
1324 return -EBUSY;
1325 }
1326
1124 fimc->m2m.refcnt++; 1327 fimc->m2m.refcnt++;
1125 set_bit(ST_OUTDMA_RUN, &fimc->state); 1328 set_bit(ST_OUTDMA_RUN, &fimc->state);
1126 mutex_unlock(&fimc->lock);
1127
1128 1329
1129 ctx = kzalloc(sizeof *ctx, GFP_KERNEL); 1330 ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
1130 if (!ctx) 1331 if (!ctx)
@@ -1135,8 +1336,8 @@ static int fimc_m2m_open(struct file *file)
1135 /* Default color format */ 1336 /* Default color format */
1136 ctx->s_frame.fmt = &fimc_formats[0]; 1337 ctx->s_frame.fmt = &fimc_formats[0];
1137 ctx->d_frame.fmt = &fimc_formats[0]; 1338 ctx->d_frame.fmt = &fimc_formats[0];
1138 /* per user process device context initialization */ 1339 /* Setup the device context for mem2mem mode. */
1139 ctx->state = 0; 1340 ctx->state = FIMC_CTX_M2M;
1140 ctx->flags = 0; 1341 ctx->flags = 0;
1141 ctx->in_path = FIMC_DMA; 1342 ctx->in_path = FIMC_DMA;
1142 ctx->out_path = FIMC_DMA; 1343 ctx->out_path = FIMC_DMA;
@@ -1147,6 +1348,8 @@ static int fimc_m2m_open(struct file *file)
1147 err = PTR_ERR(ctx->m2m_ctx); 1348 err = PTR_ERR(ctx->m2m_ctx);
1148 kfree(ctx); 1349 kfree(ctx);
1149 } 1350 }
1351
1352 mutex_unlock(&fimc->lock);
1150 return err; 1353 return err;
1151} 1354}
1152 1355
@@ -1155,11 +1358,16 @@ static int fimc_m2m_release(struct file *file)
1155 struct fimc_ctx *ctx = file->private_data; 1358 struct fimc_ctx *ctx = file->private_data;
1156 struct fimc_dev *fimc = ctx->fimc_dev; 1359 struct fimc_dev *fimc = ctx->fimc_dev;
1157 1360
1361 mutex_lock(&fimc->lock);
1362
1363 dbg("pid: %d, state: 0x%lx, refcnt= %d",
1364 task_pid_nr(current), fimc->state, fimc->m2m.refcnt);
1365
1158 v4l2_m2m_ctx_release(ctx->m2m_ctx); 1366 v4l2_m2m_ctx_release(ctx->m2m_ctx);
1159 kfree(ctx); 1367 kfree(ctx);
1160 mutex_lock(&fimc->lock);
1161 if (--fimc->m2m.refcnt <= 0) 1368 if (--fimc->m2m.refcnt <= 0)
1162 clear_bit(ST_OUTDMA_RUN, &fimc->state); 1369 clear_bit(ST_OUTDMA_RUN, &fimc->state);
1370
1163 mutex_unlock(&fimc->lock); 1371 mutex_unlock(&fimc->lock);
1164 return 0; 1372 return 0;
1165} 1373}
@@ -1168,6 +1376,7 @@ static unsigned int fimc_m2m_poll(struct file *file,
1168 struct poll_table_struct *wait) 1376 struct poll_table_struct *wait)
1169{ 1377{
1170 struct fimc_ctx *ctx = file->private_data; 1378 struct fimc_ctx *ctx = file->private_data;
1379
1171 return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); 1380 return v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
1172} 1381}
1173 1382
@@ -1175,6 +1384,7 @@ static unsigned int fimc_m2m_poll(struct file *file,
1175static int fimc_m2m_mmap(struct file *file, struct vm_area_struct *vma) 1384static int fimc_m2m_mmap(struct file *file, struct vm_area_struct *vma)
1176{ 1385{
1177 struct fimc_ctx *ctx = file->private_data; 1386 struct fimc_ctx *ctx = file->private_data;
1387
1178 return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); 1388 return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
1179} 1389}
1180 1390
@@ -1322,9 +1532,11 @@ static int fimc_probe(struct platform_device *pdev)
1322 fimc->id = pdev->id; 1532 fimc->id = pdev->id;
1323 fimc->variant = drv_data->variant[fimc->id]; 1533 fimc->variant = drv_data->variant[fimc->id];
1324 fimc->pdev = pdev; 1534 fimc->pdev = pdev;
1535 fimc->pdata = pdev->dev.platform_data;
1325 fimc->state = ST_IDLE; 1536 fimc->state = ST_IDLE;
1326 1537
1327 spin_lock_init(&fimc->irqlock); 1538 spin_lock_init(&fimc->irqlock);
1539 init_waitqueue_head(&fimc->irq_queue);
1328 spin_lock_init(&fimc->slock); 1540 spin_lock_init(&fimc->slock);
1329 1541
1330 mutex_init(&fimc->lock); 1542 mutex_init(&fimc->lock);
@@ -1354,6 +1566,7 @@ static int fimc_probe(struct platform_device *pdev)
1354 ret = fimc_clk_get(fimc); 1566 ret = fimc_clk_get(fimc);
1355 if (ret) 1567 if (ret)
1356 goto err_regs_unmap; 1568 goto err_regs_unmap;
1569 clk_set_rate(fimc->clock[0], drv_data->lclk_frequency);
1357 1570
1358 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 1571 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1359 if (!res) { 1572 if (!res) {
@@ -1375,11 +1588,27 @@ static int fimc_probe(struct platform_device *pdev)
1375 if (ret) 1588 if (ret)
1376 goto err_irq; 1589 goto err_irq;
1377 1590
1591 /* At least one camera sensor is required to register capture node */
1592 if (fimc->pdata) {
1593 int i;
1594 for (i = 0; i < FIMC_MAX_CAMIF_CLIENTS; ++i)
1595 if (fimc->pdata->isp_info[i])
1596 break;
1597
1598 if (i < FIMC_MAX_CAMIF_CLIENTS) {
1599 ret = fimc_register_capture_device(fimc);
1600 if (ret)
1601 goto err_m2m;
1602 }
1603 }
1604
1378 dev_dbg(&pdev->dev, "%s(): fimc-%d registered successfully\n", 1605 dev_dbg(&pdev->dev, "%s(): fimc-%d registered successfully\n",
1379 __func__, fimc->id); 1606 __func__, fimc->id);
1380 1607
1381 return 0; 1608 return 0;
1382 1609
1610err_m2m:
1611 fimc_unregister_m2m_device(fimc);
1383err_irq: 1612err_irq:
1384 free_irq(fimc->irq, fimc); 1613 free_irq(fimc->irq, fimc);
1385err_clk: 1614err_clk:
@@ -1404,6 +1633,8 @@ static int __devexit fimc_remove(struct platform_device *pdev)
1404 fimc_hw_reset(fimc); 1633 fimc_hw_reset(fimc);
1405 1634
1406 fimc_unregister_m2m_device(fimc); 1635 fimc_unregister_m2m_device(fimc);
1636 fimc_unregister_capture_device(fimc);
1637
1407 fimc_clk_release(fimc); 1638 fimc_clk_release(fimc);
1408 iounmap(fimc->regs); 1639 iounmap(fimc->regs);
1409 release_resource(fimc->regs_res); 1640 release_resource(fimc->regs_res);
@@ -1474,7 +1705,8 @@ static struct samsung_fimc_driverdata fimc_drvdata_s5p = {
1474 [1] = &fimc01_variant_s5p, 1705 [1] = &fimc01_variant_s5p,
1475 [2] = &fimc2_variant_s5p, 1706 [2] = &fimc2_variant_s5p,
1476 }, 1707 },
1477 .devs_cnt = 3 1708 .devs_cnt = 3,
1709 .lclk_frequency = 133000000UL,
1478}; 1710};
1479 1711
1480static struct samsung_fimc_driverdata fimc_drvdata_s5pv210 = { 1712static struct samsung_fimc_driverdata fimc_drvdata_s5pv210 = {
@@ -1483,7 +1715,8 @@ static struct samsung_fimc_driverdata fimc_drvdata_s5pv210 = {
1483 [1] = &fimc01_variant_s5pv210, 1715 [1] = &fimc01_variant_s5pv210,
1484 [2] = &fimc2_variant_s5pv210, 1716 [2] = &fimc2_variant_s5pv210,
1485 }, 1717 },
1486 .devs_cnt = 3 1718 .devs_cnt = 3,
1719 .lclk_frequency = 166000000UL,
1487}; 1720};
1488 1721
1489static struct platform_device_id fimc_driver_ids[] = { 1722static struct platform_device_id fimc_driver_ids[] = {
@@ -1524,6 +1757,6 @@ static void __exit fimc_exit(void)
1524module_init(fimc_init); 1757module_init(fimc_init);
1525module_exit(fimc_exit); 1758module_exit(fimc_exit);
1526 1759
1527MODULE_AUTHOR("Sylwester Nawrocki, s.nawrocki@samsung.com"); 1760MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
1528MODULE_DESCRIPTION("S3C/S5P FIMC (video postprocessor) driver"); 1761MODULE_DESCRIPTION("S5P FIMC camera host interface/video postprocessor driver");
1529MODULE_LICENSE("GPL"); 1762MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h
index 5aeb3efbd457..ce0a6b8a7d54 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.h
+++ b/drivers/media/video/s5p-fimc/fimc-core.h
@@ -11,10 +11,14 @@
11#ifndef FIMC_CORE_H_ 11#ifndef FIMC_CORE_H_
12#define FIMC_CORE_H_ 12#define FIMC_CORE_H_
13 13
14/*#define DEBUG*/
15
14#include <linux/types.h> 16#include <linux/types.h>
15#include <media/videobuf-core.h> 17#include <media/videobuf-core.h>
16#include <media/v4l2-device.h> 18#include <media/v4l2-device.h>
17#include <media/v4l2-mem2mem.h> 19#include <media/v4l2-mem2mem.h>
20#include <media/v4l2-mediabus.h>
21#include <media/s3c_fimc.h>
18#include <linux/videodev2.h> 22#include <linux/videodev2.h>
19#include "regs-fimc.h" 23#include "regs-fimc.h"
20 24
@@ -28,6 +32,8 @@
28#define dbg(fmt, args...) 32#define dbg(fmt, args...)
29#endif 33#endif
30 34
35/* Time to wait for next frame VSYNC interrupt while stopping operation. */
36#define FIMC_SHUTDOWN_TIMEOUT ((100*HZ)/1000)
31#define NUM_FIMC_CLOCKS 2 37#define NUM_FIMC_CLOCKS 2
32#define MODULE_NAME "s5p-fimc" 38#define MODULE_NAME "s5p-fimc"
33#define FIMC_MAX_DEVS 3 39#define FIMC_MAX_DEVS 3
@@ -36,19 +42,41 @@
36#define SCALER_MAX_VRATIO 64 42#define SCALER_MAX_VRATIO 64
37#define DMA_MIN_SIZE 8 43#define DMA_MIN_SIZE 8
38 44
39enum { 45/* FIMC device state flags */
46enum fimc_dev_flags {
47 /* for m2m node */
40 ST_IDLE, 48 ST_IDLE,
41 ST_OUTDMA_RUN, 49 ST_OUTDMA_RUN,
42 ST_M2M_PEND, 50 ST_M2M_PEND,
51 /* for capture node */
52 ST_CAPT_PEND,
53 ST_CAPT_RUN,
54 ST_CAPT_STREAM,
55 ST_CAPT_SHUT,
43}; 56};
44 57
45#define fimc_m2m_active(dev) test_bit(ST_OUTDMA_RUN, &(dev)->state) 58#define fimc_m2m_active(dev) test_bit(ST_OUTDMA_RUN, &(dev)->state)
46#define fimc_m2m_pending(dev) test_bit(ST_M2M_PEND, &(dev)->state) 59#define fimc_m2m_pending(dev) test_bit(ST_M2M_PEND, &(dev)->state)
47 60
61#define fimc_capture_running(dev) test_bit(ST_CAPT_RUN, &(dev)->state)
62#define fimc_capture_pending(dev) test_bit(ST_CAPT_PEND, &(dev)->state)
63
64#define fimc_capture_active(dev) \
65 (test_bit(ST_CAPT_RUN, &(dev)->state) || \
66 test_bit(ST_CAPT_PEND, &(dev)->state))
67
68#define fimc_capture_streaming(dev) \
69 test_bit(ST_CAPT_STREAM, &(dev)->state)
70
71#define fimc_buf_finish(dev, vid_buf) do { \
72 spin_lock(&(dev)->irqlock); \
73 (vid_buf)->vb.state = VIDEOBUF_DONE; \
74 spin_unlock(&(dev)->irqlock); \
75 wake_up(&(vid_buf)->vb.done); \
76} while (0)
77
48enum fimc_datapath { 78enum fimc_datapath {
49 FIMC_ITU_CAM_A, 79 FIMC_CAMERA,
50 FIMC_ITU_CAM_B,
51 FIMC_MIPI_CAM,
52 FIMC_DMA, 80 FIMC_DMA,
53 FIMC_LCDFIFO, 81 FIMC_LCDFIFO,
54 FIMC_WRITEBACK 82 FIMC_WRITEBACK
@@ -123,20 +151,25 @@ enum fimc_color_fmt {
123 151
124/** 152/**
125 * struct fimc_fmt - the driver's internal color format data 153 * struct fimc_fmt - the driver's internal color format data
154 * @mbus_code: Media Bus pixel code, -1 if not applicable
126 * @name: format description 155 * @name: format description
127 * @fourcc: the fourcc code for this format 156 * @fourcc: the fourcc code for this format, 0 if not applicable
128 * @color: the corresponding fimc_color_fmt 157 * @color: the corresponding fimc_color_fmt
129 * @depth: number of bits per pixel 158 * @depth: driver's private 'number of bits per pixel'
130 * @buff_cnt: number of physically non-contiguous data planes 159 * @buff_cnt: number of physically non-contiguous data planes
131 * @planes_cnt: number of physically contiguous data planes 160 * @planes_cnt: number of physically contiguous data planes
132 */ 161 */
133struct fimc_fmt { 162struct fimc_fmt {
163 enum v4l2_mbus_pixelcode mbus_code;
134 char *name; 164 char *name;
135 u32 fourcc; 165 u32 fourcc;
136 u32 color; 166 u32 color;
137 u32 depth;
138 u16 buff_cnt; 167 u16 buff_cnt;
139 u16 planes_cnt; 168 u16 planes_cnt;
169 u16 depth;
170 u16 flags;
171#define FMT_FLAGS_CAM (1 << 0)
172#define FMT_FLAGS_M2M (1 << 1)
140}; 173};
141 174
142/** 175/**
@@ -220,10 +253,14 @@ struct fimc_addr {
220 253
221/** 254/**
222 * struct fimc_vid_buffer - the driver's video buffer 255 * struct fimc_vid_buffer - the driver's video buffer
223 * @vb: v4l videobuf buffer 256 * @vb: v4l videobuf buffer
257 * @paddr: precalculated physical address set
258 * @index: buffer index for the output DMA engine
224 */ 259 */
225struct fimc_vid_buffer { 260struct fimc_vid_buffer {
226 struct videobuf_buffer vb; 261 struct videobuf_buffer vb;
262 struct fimc_addr paddr;
263 int index;
227}; 264};
228 265
229/** 266/**
@@ -274,6 +311,40 @@ struct fimc_m2m_device {
274}; 311};
275 312
276/** 313/**
314 * struct fimc_vid_cap - camera capture device information
315 * @ctx: hardware context data
316 * @vfd: video device node for camera capture mode
317 * @v4l2_dev: v4l2_device struct to manage subdevs
318 * @sd: pointer to camera sensor subdevice currently in use
319 * @fmt: Media Bus format configured at selected image sensor
320 * @pending_buf_q: the pending buffer queue head
321 * @active_buf_q: the queue head of buffers scheduled in hardware
322 * @vbq: the capture am video buffer queue
323 * @active_buf_cnt: number of video buffers scheduled in hardware
324 * @buf_index: index for managing the output DMA buffers
325 * @frame_count: the frame counter for statistics
326 * @reqbufs_count: the number of buffers requested in REQBUFS ioctl
327 * @input_index: input (camera sensor) index
328 * @refcnt: driver's private reference counter
329 */
330struct fimc_vid_cap {
331 struct fimc_ctx *ctx;
332 struct video_device *vfd;
333 struct v4l2_device v4l2_dev;
334 struct v4l2_subdev *sd;
335 struct v4l2_mbus_framefmt fmt;
336 struct list_head pending_buf_q;
337 struct list_head active_buf_q;
338 struct videobuf_queue vbq;
339 int active_buf_cnt;
340 int buf_index;
341 unsigned int frame_count;
342 unsigned int reqbufs_count;
343 int input_index;
344 int refcnt;
345};
346
347/**
277 * struct samsung_fimc_variant - camera interface variant information 348 * struct samsung_fimc_variant - camera interface variant information
278 * 349 *
279 * @pix_hoff: indicate whether horizontal offset is in pixels or in bytes 350 * @pix_hoff: indicate whether horizontal offset is in pixels or in bytes
@@ -308,10 +379,12 @@ struct samsung_fimc_variant {
308 * 379 *
309 * @variant: the variant information for this driver. 380 * @variant: the variant information for this driver.
310 * @dev_cnt: number of fimc sub-devices available in SoC 381 * @dev_cnt: number of fimc sub-devices available in SoC
382 * @lclk_frequency: fimc bus clock frequency
311 */ 383 */
312struct samsung_fimc_driverdata { 384struct samsung_fimc_driverdata {
313 struct samsung_fimc_variant *variant[FIMC_MAX_DEVS]; 385 struct samsung_fimc_variant *variant[FIMC_MAX_DEVS];
314 int devs_cnt; 386 unsigned long lclk_frequency;
387 int devs_cnt;
315}; 388};
316 389
317struct fimc_ctx; 390struct fimc_ctx;
@@ -322,19 +395,23 @@ struct fimc_ctx;
322 * @slock: the spinlock protecting this data structure 395 * @slock: the spinlock protecting this data structure
323 * @lock: the mutex protecting this data structure 396 * @lock: the mutex protecting this data structure
324 * @pdev: pointer to the FIMC platform device 397 * @pdev: pointer to the FIMC platform device
398 * @pdata: pointer to the device platform data
325 * @id: FIMC device index (0..2) 399 * @id: FIMC device index (0..2)
326 * @clock[]: the clocks required for FIMC operation 400 * @clock[]: the clocks required for FIMC operation
327 * @regs: the mapped hardware registers 401 * @regs: the mapped hardware registers
328 * @regs_res: the resource claimed for IO registers 402 * @regs_res: the resource claimed for IO registers
329 * @irq: interrupt number of the FIMC subdevice 403 * @irq: interrupt number of the FIMC subdevice
330 * @irqlock: spinlock protecting videobuffer queue 404 * @irqlock: spinlock protecting videobuffer queue
405 * @irq_queue:
331 * @m2m: memory-to-memory V4L2 device information 406 * @m2m: memory-to-memory V4L2 device information
332 * @state: the FIMC device state flags 407 * @vid_cap: camera capture device information
408 * @state: flags used to synchronize m2m and capture mode operation
333 */ 409 */
334struct fimc_dev { 410struct fimc_dev {
335 spinlock_t slock; 411 spinlock_t slock;
336 struct mutex lock; 412 struct mutex lock;
337 struct platform_device *pdev; 413 struct platform_device *pdev;
414 struct s3c_platform_fimc *pdata;
338 struct samsung_fimc_variant *variant; 415 struct samsung_fimc_variant *variant;
339 int id; 416 int id;
340 struct clk *clock[NUM_FIMC_CLOCKS]; 417 struct clk *clock[NUM_FIMC_CLOCKS];
@@ -342,7 +419,9 @@ struct fimc_dev {
342 struct resource *regs_res; 419 struct resource *regs_res;
343 int irq; 420 int irq;
344 spinlock_t irqlock; 421 spinlock_t irqlock;
422 wait_queue_head_t irq_queue;
345 struct fimc_m2m_device m2m; 423 struct fimc_m2m_device m2m;
424 struct fimc_vid_cap vid_cap;
346 unsigned long state; 425 unsigned long state;
347}; 426};
348 427
@@ -387,6 +466,7 @@ struct fimc_ctx {
387 struct v4l2_m2m_ctx *m2m_ctx; 466 struct v4l2_m2m_ctx *m2m_ctx;
388}; 467};
389 468
469extern struct videobuf_queue_ops fimc_qops;
390 470
391static inline int tiled_fmt(struct fimc_fmt *fmt) 471static inline int tiled_fmt(struct fimc_fmt *fmt)
392{ 472{
@@ -433,7 +513,10 @@ static inline struct fimc_frame *ctx_get_frame(struct fimc_ctx *ctx,
433 struct fimc_frame *frame; 513 struct fimc_frame *frame;
434 514
435 if (V4L2_BUF_TYPE_VIDEO_OUTPUT == type) { 515 if (V4L2_BUF_TYPE_VIDEO_OUTPUT == type) {
436 frame = &ctx->s_frame; 516 if (ctx->state & FIMC_CTX_M2M)
517 frame = &ctx->s_frame;
518 else
519 return ERR_PTR(-EINVAL);
437 } else if (V4L2_BUF_TYPE_VIDEO_CAPTURE == type) { 520 } else if (V4L2_BUF_TYPE_VIDEO_CAPTURE == type) {
438 frame = &ctx->d_frame; 521 frame = &ctx->d_frame;
439 } else { 522 } else {
@@ -445,6 +528,13 @@ static inline struct fimc_frame *ctx_get_frame(struct fimc_ctx *ctx,
445 return frame; 528 return frame;
446} 529}
447 530
531static inline u32 fimc_hw_get_frame_index(struct fimc_dev *dev)
532{
533 u32 reg = readl(dev->regs + S5P_CISTATUS);
534 return (reg & S5P_CISTATUS_FRAMECNT_MASK) >>
535 S5P_CISTATUS_FRAMECNT_SHIFT;
536}
537
448/* -----------------------------------------------------*/ 538/* -----------------------------------------------------*/
449/* fimc-reg.c */ 539/* fimc-reg.c */
450void fimc_hw_reset(struct fimc_dev *fimc); 540void fimc_hw_reset(struct fimc_dev *fimc);
@@ -462,6 +552,52 @@ void fimc_hw_set_output_path(struct fimc_ctx *ctx);
462void fimc_hw_set_input_addr(struct fimc_dev *fimc, struct fimc_addr *paddr); 552void fimc_hw_set_input_addr(struct fimc_dev *fimc, struct fimc_addr *paddr);
463void fimc_hw_set_output_addr(struct fimc_dev *fimc, struct fimc_addr *paddr, 553void fimc_hw_set_output_addr(struct fimc_dev *fimc, struct fimc_addr *paddr,
464 int index); 554 int index);
555int fimc_hw_set_camera_source(struct fimc_dev *fimc,
556 struct s3c_fimc_isp_info *cam);
557int fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f);
558int fimc_hw_set_camera_polarity(struct fimc_dev *fimc,
559 struct s3c_fimc_isp_info *cam);
560int fimc_hw_set_camera_type(struct fimc_dev *fimc,
561 struct s3c_fimc_isp_info *cam);
562
563/* -----------------------------------------------------*/
564/* fimc-core.c */
565int fimc_vidioc_enum_fmt(struct file *file, void *priv,
566 struct v4l2_fmtdesc *f);
567int fimc_vidioc_g_fmt(struct file *file, void *priv,
568 struct v4l2_format *f);
569int fimc_vidioc_try_fmt(struct file *file, void *priv,
570 struct v4l2_format *f);
571int fimc_vidioc_g_crop(struct file *file, void *fh,
572 struct v4l2_crop *cr);
573int fimc_vidioc_cropcap(struct file *file, void *fh,
574 struct v4l2_cropcap *cr);
575int fimc_vidioc_queryctrl(struct file *file, void *priv,
576 struct v4l2_queryctrl *qc);
577int fimc_vidioc_g_ctrl(struct file *file, void *priv,
578 struct v4l2_control *ctrl);
579
580int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr);
581int check_ctrl_val(struct fimc_ctx *ctx, struct v4l2_control *ctrl);
582int fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_control *ctrl);
583
584struct fimc_fmt *find_format(struct v4l2_format *f, unsigned int mask);
585struct fimc_fmt *find_mbus_format(struct v4l2_mbus_framefmt *f,
586 unsigned int mask);
587
588int fimc_check_scaler_ratio(struct v4l2_rect *r, struct fimc_frame *f);
589int fimc_set_scaler_info(struct fimc_ctx *ctx);
590int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags);
591int fimc_prepare_addr(struct fimc_ctx *ctx, struct fimc_vid_buffer *buf,
592 struct fimc_frame *frame, struct fimc_addr *paddr);
593
594/* -----------------------------------------------------*/
595/* fimc-capture.c */
596int fimc_register_capture_device(struct fimc_dev *fimc);
597void fimc_unregister_capture_device(struct fimc_dev *fimc);
598int fimc_sensor_sd_init(struct fimc_dev *fimc, int index);
599int fimc_vid_cap_buf_queue(struct fimc_dev *fimc,
600 struct fimc_vid_buffer *fimc_vb);
465 601
466/* Locking: the caller holds fimc->slock */ 602/* Locking: the caller holds fimc->slock */
467static inline void fimc_activate_capture(struct fimc_ctx *ctx) 603static inline void fimc_activate_capture(struct fimc_ctx *ctx)
@@ -478,4 +614,51 @@ static inline void fimc_deactivate_capture(struct fimc_dev *fimc)
478 fimc_hw_en_lastirq(fimc, false); 614 fimc_hw_en_lastirq(fimc, false);
479} 615}
480 616
617/*
618 * Add video buffer to the active buffers queue.
619 * The caller holds irqlock spinlock.
620 */
621static inline void active_queue_add(struct fimc_vid_cap *vid_cap,
622 struct fimc_vid_buffer *buf)
623{
624 buf->vb.state = VIDEOBUF_ACTIVE;
625 list_add_tail(&buf->vb.queue, &vid_cap->active_buf_q);
626 vid_cap->active_buf_cnt++;
627}
628
629/*
630 * Pop a video buffer from the capture active buffers queue
631 * Locking: Need to be called with dev->slock held.
632 */
633static inline struct fimc_vid_buffer *
634active_queue_pop(struct fimc_vid_cap *vid_cap)
635{
636 struct fimc_vid_buffer *buf;
637 buf = list_entry(vid_cap->active_buf_q.next,
638 struct fimc_vid_buffer, vb.queue);
639 list_del(&buf->vb.queue);
640 vid_cap->active_buf_cnt--;
641 return buf;
642}
643
644/* Add video buffer to the capture pending buffers queue */
645static inline void fimc_pending_queue_add(struct fimc_vid_cap *vid_cap,
646 struct fimc_vid_buffer *buf)
647{
648 buf->vb.state = VIDEOBUF_QUEUED;
649 list_add_tail(&buf->vb.queue, &vid_cap->pending_buf_q);
650}
651
652/* Add video buffer to the capture pending buffers queue */
653static inline struct fimc_vid_buffer *
654pending_queue_pop(struct fimc_vid_cap *vid_cap)
655{
656 struct fimc_vid_buffer *buf;
657 buf = list_entry(vid_cap->pending_buf_q.next,
658 struct fimc_vid_buffer, vb.queue);
659 list_del(&buf->vb.queue);
660 return buf;
661}
662
663
481#endif /* FIMC_CORE_H_ */ 664#endif /* FIMC_CORE_H_ */
diff --git a/drivers/media/video/s5p-fimc/fimc-reg.c b/drivers/media/video/s5p-fimc/fimc-reg.c
index 95adc8464693..511631a2e5c3 100644
--- a/drivers/media/video/s5p-fimc/fimc-reg.c
+++ b/drivers/media/video/s5p-fimc/fimc-reg.c
@@ -13,6 +13,7 @@
13#include <linux/io.h> 13#include <linux/io.h>
14#include <linux/delay.h> 14#include <linux/delay.h>
15#include <mach/map.h> 15#include <mach/map.h>
16#include <media/s3c_fimc.h>
16 17
17#include "fimc-core.h" 18#include "fimc-core.h"
18 19
@@ -176,6 +177,15 @@ static void fimc_hw_set_out_dma_size(struct fimc_ctx *ctx)
176 cfg = S5P_ORIG_SIZE_HOR(frame->f_width); 177 cfg = S5P_ORIG_SIZE_HOR(frame->f_width);
177 cfg |= S5P_ORIG_SIZE_VER(frame->f_height); 178 cfg |= S5P_ORIG_SIZE_VER(frame->f_height);
178 writel(cfg, dev->regs + S5P_ORGOSIZE); 179 writel(cfg, dev->regs + S5P_ORGOSIZE);
180
181 /* Select color space conversion equation (HD/SD size).*/
182 cfg = readl(dev->regs + S5P_CIGCTRL);
183 if (frame->f_width >= 1280) /* HD */
184 cfg |= S5P_CIGCTRL_CSC_ITU601_709;
185 else /* SD */
186 cfg &= ~S5P_CIGCTRL_CSC_ITU601_709;
187 writel(cfg, dev->regs + S5P_CIGCTRL);
188
179} 189}
180 190
181void fimc_hw_set_out_dma(struct fimc_ctx *ctx) 191void fimc_hw_set_out_dma(struct fimc_ctx *ctx)
@@ -231,19 +241,12 @@ static void fimc_hw_en_autoload(struct fimc_dev *dev, int enable)
231 241
232void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable) 242void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable)
233{ 243{
234 unsigned long flags; 244 u32 cfg = readl(dev->regs + S5P_CIOCTRL);
235 u32 cfg;
236
237 spin_lock_irqsave(&dev->slock, flags);
238
239 cfg = readl(dev->regs + S5P_CIOCTRL);
240 if (enable) 245 if (enable)
241 cfg |= S5P_CIOCTRL_LASTIRQ_ENABLE; 246 cfg |= S5P_CIOCTRL_LASTIRQ_ENABLE;
242 else 247 else
243 cfg &= ~S5P_CIOCTRL_LASTIRQ_ENABLE; 248 cfg &= ~S5P_CIOCTRL_LASTIRQ_ENABLE;
244 writel(cfg, dev->regs + S5P_CIOCTRL); 249 writel(cfg, dev->regs + S5P_CIOCTRL);
245
246 spin_unlock_irqrestore(&dev->slock, flags);
247} 250}
248 251
249static void fimc_hw_set_prescaler(struct fimc_ctx *ctx) 252static void fimc_hw_set_prescaler(struct fimc_ctx *ctx)
@@ -325,14 +328,18 @@ void fimc_hw_set_scaler(struct fimc_ctx *ctx)
325void fimc_hw_en_capture(struct fimc_ctx *ctx) 328void fimc_hw_en_capture(struct fimc_ctx *ctx)
326{ 329{
327 struct fimc_dev *dev = ctx->fimc_dev; 330 struct fimc_dev *dev = ctx->fimc_dev;
328 u32 cfg;
329 331
330 cfg = readl(dev->regs + S5P_CIIMGCPT); 332 u32 cfg = readl(dev->regs + S5P_CIIMGCPT);
331 /* One shot mode for output DMA or freerun for FIFO. */ 333
332 if (ctx->out_path == FIMC_DMA) 334 if (ctx->out_path == FIMC_DMA) {
333 cfg |= S5P_CIIMGCPT_CPT_FREN_ENABLE; 335 /* one shot mode */
334 else 336 cfg |= S5P_CIIMGCPT_CPT_FREN_ENABLE | S5P_CIIMGCPT_IMGCPTEN;
335 cfg &= ~S5P_CIIMGCPT_CPT_FREN_ENABLE; 337 } else {
338 /* Continous frame capture mode (freerun). */
339 cfg &= ~(S5P_CIIMGCPT_CPT_FREN_ENABLE |
340 S5P_CIIMGCPT_CPT_FRMOD_CNT);
341 cfg |= S5P_CIIMGCPT_IMGCPTEN;
342 }
336 343
337 if (ctx->scaler.enabled) 344 if (ctx->scaler.enabled)
338 cfg |= S5P_CIIMGCPT_IMGCPTEN_SC; 345 cfg |= S5P_CIIMGCPT_IMGCPTEN_SC;
@@ -523,3 +530,139 @@ void fimc_hw_set_output_addr(struct fimc_dev *dev,
523 i, paddr->y, paddr->cb, paddr->cr); 530 i, paddr->y, paddr->cb, paddr->cr);
524 } while (index == -1 && ++i < FIMC_MAX_OUT_BUFS); 531 } while (index == -1 && ++i < FIMC_MAX_OUT_BUFS);
525} 532}
533
534int fimc_hw_set_camera_polarity(struct fimc_dev *fimc,
535 struct s3c_fimc_isp_info *cam)
536{
537 u32 cfg = readl(fimc->regs + S5P_CIGCTRL);
538
539 cfg &= ~(S5P_CIGCTRL_INVPOLPCLK | S5P_CIGCTRL_INVPOLVSYNC |
540 S5P_CIGCTRL_INVPOLHREF | S5P_CIGCTRL_INVPOLHSYNC);
541
542 if (cam->flags & FIMC_CLK_INV_PCLK)
543 cfg |= S5P_CIGCTRL_INVPOLPCLK;
544
545 if (cam->flags & FIMC_CLK_INV_VSYNC)
546 cfg |= S5P_CIGCTRL_INVPOLVSYNC;
547
548 if (cam->flags & FIMC_CLK_INV_HREF)
549 cfg |= S5P_CIGCTRL_INVPOLHREF;
550
551 if (cam->flags & FIMC_CLK_INV_HSYNC)
552 cfg |= S5P_CIGCTRL_INVPOLHSYNC;
553
554 writel(cfg, fimc->regs + S5P_CIGCTRL);
555
556 return 0;
557}
558
559int fimc_hw_set_camera_source(struct fimc_dev *fimc,
560 struct s3c_fimc_isp_info *cam)
561{
562 struct fimc_frame *f = &fimc->vid_cap.ctx->s_frame;
563 u32 cfg = 0;
564
565 if (cam->bus_type == FIMC_ITU_601 || cam->bus_type == FIMC_ITU_656) {
566
567 switch (fimc->vid_cap.fmt.code) {
568 case V4L2_MBUS_FMT_YUYV8_2X8:
569 cfg = S5P_CISRCFMT_ORDER422_YCBYCR;
570 break;
571 case V4L2_MBUS_FMT_YVYU8_2X8:
572 cfg = S5P_CISRCFMT_ORDER422_YCRYCB;
573 break;
574 case V4L2_MBUS_FMT_VYUY8_2X8:
575 cfg = S5P_CISRCFMT_ORDER422_CRYCBY;
576 break;
577 case V4L2_MBUS_FMT_UYVY8_2X8:
578 cfg = S5P_CISRCFMT_ORDER422_CBYCRY;
579 break;
580 default:
581 err("camera image format not supported: %d",
582 fimc->vid_cap.fmt.code);
583 return -EINVAL;
584 }
585
586 if (cam->bus_type == FIMC_ITU_601) {
587 if (cam->bus_width == 8) {
588 cfg |= S5P_CISRCFMT_ITU601_8BIT;
589 } else if (cam->bus_width == 16) {
590 cfg |= S5P_CISRCFMT_ITU601_16BIT;
591 } else {
592 err("invalid bus width: %d", cam->bus_width);
593 return -EINVAL;
594 }
595 } /* else defaults to ITU-R BT.656 8-bit */
596 }
597
598 cfg |= S5P_CISRCFMT_HSIZE(f->o_width) | S5P_CISRCFMT_VSIZE(f->o_height);
599 writel(cfg, fimc->regs + S5P_CISRCFMT);
600 return 0;
601}
602
603
604int fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f)
605{
606 u32 hoff2, voff2;
607
608 u32 cfg = readl(fimc->regs + S5P_CIWDOFST);
609
610 cfg &= ~(S5P_CIWDOFST_HOROFF_MASK | S5P_CIWDOFST_VEROFF_MASK);
611 cfg |= S5P_CIWDOFST_OFF_EN |
612 S5P_CIWDOFST_HOROFF(f->offs_h) |
613 S5P_CIWDOFST_VEROFF(f->offs_v);
614
615 writel(cfg, fimc->regs + S5P_CIWDOFST);
616
617 /* See CIWDOFSTn register description in the datasheet for details. */
618 hoff2 = f->o_width - f->width - f->offs_h;
619 voff2 = f->o_height - f->height - f->offs_v;
620 cfg = S5P_CIWDOFST2_HOROFF(hoff2) | S5P_CIWDOFST2_VEROFF(voff2);
621
622 writel(cfg, fimc->regs + S5P_CIWDOFST2);
623 return 0;
624}
625
626int fimc_hw_set_camera_type(struct fimc_dev *fimc,
627 struct s3c_fimc_isp_info *cam)
628{
629 u32 cfg, tmp;
630 struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
631
632 cfg = readl(fimc->regs + S5P_CIGCTRL);
633
634 /* Select ITU B interface, disable Writeback path and test pattern. */
635 cfg &= ~(S5P_CIGCTRL_TESTPAT_MASK | S5P_CIGCTRL_SELCAM_ITU_A |
636 S5P_CIGCTRL_SELCAM_MIPI | S5P_CIGCTRL_CAMIF_SELWB |
637 S5P_CIGCTRL_SELCAM_MIPI_A);
638
639 if (cam->bus_type == FIMC_MIPI_CSI2) {
640 cfg |= S5P_CIGCTRL_SELCAM_MIPI;
641
642 if (cam->mux_id == 0)
643 cfg |= S5P_CIGCTRL_SELCAM_MIPI_A;
644
645 /* TODO: add remaining supported formats. */
646 if (vid_cap->fmt.code == V4L2_MBUS_FMT_VYUY8_2X8) {
647 tmp = S5P_CSIIMGFMT_YCBCR422_8BIT;
648 } else {
649 err("camera image format not supported: %d",
650 vid_cap->fmt.code);
651 return -EINVAL;
652 }
653 writel(tmp | (0x1 << 8), fimc->regs + S5P_CSIIMGFMT);
654
655 } else if (cam->bus_type == FIMC_ITU_601 ||
656 cam->bus_type == FIMC_ITU_656) {
657 if (cam->mux_id == 0) /* ITU-A, ITU-B: 0, 1 */
658 cfg |= S5P_CIGCTRL_SELCAM_ITU_A;
659 } else if (cam->bus_type == FIMC_LCD_WB) {
660 cfg |= S5P_CIGCTRL_CAMIF_SELWB;
661 } else {
662 err("invalid camera bus type selected\n");
663 return -EINVAL;
664 }
665 writel(cfg, fimc->regs + S5P_CIGCTRL);
666
667 return 0;
668}
diff --git a/include/media/s3c_fimc.h b/include/media/s3c_fimc.h
new file mode 100644
index 000000000000..ca1b6738e4a4
--- /dev/null
+++ b/include/media/s3c_fimc.h
@@ -0,0 +1,60 @@
1/*
2 * Samsung S5P SoC camera interface driver header
3 *
4 * Copyright (c) 2010 Samsung Electronics Co., Ltd
5 * Author: 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#ifndef S3C_FIMC_H_
13#define S3C_FIMC_H_
14
15enum cam_bus_type {
16 FIMC_ITU_601 = 1,
17 FIMC_ITU_656,
18 FIMC_MIPI_CSI2,
19 FIMC_LCD_WB, /* FIFO link from LCD mixer */
20};
21
22#define FIMC_CLK_INV_PCLK (1 << 0)
23#define FIMC_CLK_INV_VSYNC (1 << 1)
24#define FIMC_CLK_INV_HREF (1 << 2)
25#define FIMC_CLK_INV_HSYNC (1 << 3)
26
27struct i2c_board_info;
28
29/**
30 * struct s3c_fimc_isp_info - image sensor information required for host
31 * interace configuration.
32 *
33 * @board_info: pointer to I2C subdevice's board info
34 * @bus_type: determines bus type, MIPI, ITU-R BT.601 etc.
35 * @i2c_bus_num: i2c control bus id the sensor is attached to
36 * @mux_id: FIMC camera interface multiplexer index (separate for MIPI and ITU)
37 * @bus_width: camera data bus width in bits
38 * @flags: flags defining bus signals polarity inversion (High by default)
39 */
40struct s3c_fimc_isp_info {
41 struct i2c_board_info *board_info;
42 enum cam_bus_type bus_type;
43 u16 i2c_bus_num;
44 u16 mux_id;
45 u16 bus_width;
46 u16 flags;
47};
48
49
50#define FIMC_MAX_CAMIF_CLIENTS 2
51
52/**
53 * struct s3c_platform_fimc - camera host interface platform data
54 *
55 * @isp_info: properties of camera sensor required for host interface setup
56 */
57struct s3c_platform_fimc {
58 struct s3c_fimc_isp_info *isp_info[FIMC_MAX_CAMIF_CLIENTS];
59};
60#endif /* S3C_FIMC_H_ */