aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/s5p-fimc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/s5p-fimc')
-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.c952
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.h377
-rw-r--r--drivers/media/video/s5p-fimc/fimc-reg.c321
-rw-r--r--drivers/media/video/s5p-fimc/regs-fimc.h64
6 files changed, 1981 insertions, 554 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 6961c55baf9b..2e7c547894b6 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,86 +38,103 @@ 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,
120 }; 136 },
137};
121 138
122static struct v4l2_queryctrl fimc_ctrls[] = { 139static struct v4l2_queryctrl fimc_ctrls[] = {
123 { 140 {
@@ -127,16 +144,14 @@ static struct v4l2_queryctrl fimc_ctrls[] = {
127 .minimum = 0, 144 .minimum = 0,
128 .maximum = 1, 145 .maximum = 1,
129 .default_value = 0, 146 .default_value = 0,
130 }, 147 }, {
131 {
132 .id = V4L2_CID_VFLIP, 148 .id = V4L2_CID_VFLIP,
133 .type = V4L2_CTRL_TYPE_BOOLEAN, 149 .type = V4L2_CTRL_TYPE_BOOLEAN,
134 .name = "Vertical flip", 150 .name = "Vertical flip",
135 .minimum = 0, 151 .minimum = 0,
136 .maximum = 1, 152 .maximum = 1,
137 .default_value = 0, 153 .default_value = 0,
138 }, 154 }, {
139 {
140 .id = V4L2_CID_ROTATE, 155 .id = V4L2_CID_ROTATE,
141 .type = V4L2_CTRL_TYPE_INTEGER, 156 .type = V4L2_CTRL_TYPE_INTEGER,
142 .name = "Rotation (CCW)", 157 .name = "Rotation (CCW)",
@@ -158,7 +173,7 @@ static struct v4l2_queryctrl *get_ctrl(int id)
158 return NULL; 173 return NULL;
159} 174}
160 175
161static 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)
162{ 177{
163 if (r->width > f->width) { 178 if (r->width > f->width) {
164 if (f->width > (r->width * SCALER_MAX_HRATIO)) 179 if (f->width > (r->width * SCALER_MAX_HRATIO))
@@ -181,32 +196,27 @@ static int fimc_check_scaler_ratio(struct v4l2_rect *r, struct fimc_frame *f)
181 196
182static int fimc_get_scaler_factor(u32 src, u32 tar, u32 *ratio, u32 *shift) 197static int fimc_get_scaler_factor(u32 src, u32 tar, u32 *ratio, u32 *shift)
183{ 198{
184 if (src >= tar * 64) { 199 u32 sh = 6;
200
201 if (src >= 64 * tar)
185 return -EINVAL; 202 return -EINVAL;
186 } else if (src >= tar * 32) { 203
187 *ratio = 32; 204 while (sh--) {
188 *shift = 5; 205 u32 tmp = 1 << sh;
189 } else if (src >= tar * 16) { 206 if (src >= tar * tmp) {
190 *ratio = 16; 207 *shift = sh, *ratio = tmp;
191 *shift = 4; 208 return 0;
192 } else if (src >= tar * 8) { 209 }
193 *ratio = 8;
194 *shift = 3;
195 } else if (src >= tar * 4) {
196 *ratio = 4;
197 *shift = 2;
198 } else if (src >= tar * 2) {
199 *ratio = 2;
200 *shift = 1;
201 } else {
202 *ratio = 1;
203 *shift = 0;
204 } 210 }
205 211
212 *shift = 0, *ratio = 1;
213
214 dbg("s: %d, t: %d, shift: %d, ratio: %d",
215 src, tar, *shift, *ratio);
206 return 0; 216 return 0;
207} 217}
208 218
209static int fimc_set_scaler_info(struct fimc_ctx *ctx) 219int fimc_set_scaler_info(struct fimc_ctx *ctx)
210{ 220{
211 struct fimc_scaler *sc = &ctx->scaler; 221 struct fimc_scaler *sc = &ctx->scaler;
212 struct fimc_frame *s_frame = &ctx->s_frame; 222 struct fimc_frame *s_frame = &ctx->s_frame;
@@ -214,8 +224,13 @@ static int fimc_set_scaler_info(struct fimc_ctx *ctx)
214 int tx, ty, sx, sy; 224 int tx, ty, sx, sy;
215 int ret; 225 int ret;
216 226
217 tx = d_frame->width; 227 if (ctx->rotation == 90 || ctx->rotation == 270) {
218 ty = d_frame->height; 228 ty = d_frame->width;
229 tx = d_frame->height;
230 } else {
231 tx = d_frame->width;
232 ty = d_frame->height;
233 }
219 if (tx <= 0 || ty <= 0) { 234 if (tx <= 0 || ty <= 0) {
220 v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev, 235 v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev,
221 "invalid target size: %d x %d", tx, ty); 236 "invalid target size: %d x %d", tx, ty);
@@ -261,12 +276,57 @@ static int fimc_set_scaler_info(struct fimc_ctx *ctx)
261 return 0; 276 return 0;
262} 277}
263 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}
264 324
265static irqreturn_t fimc_isr(int irq, void *priv) 325static irqreturn_t fimc_isr(int irq, void *priv)
266{ 326{
267 struct fimc_vid_buffer *src_buf, *dst_buf; 327 struct fimc_vid_buffer *src_buf, *dst_buf;
268 struct fimc_dev *fimc = (struct fimc_dev *)priv;
269 struct fimc_ctx *ctx; 328 struct fimc_ctx *ctx;
329 struct fimc_dev *fimc = priv;
270 330
271 BUG_ON(!fimc); 331 BUG_ON(!fimc);
272 fimc_hw_clear_irq(fimc); 332 fimc_hw_clear_irq(fimc);
@@ -281,12 +341,22 @@ static irqreturn_t fimc_isr(int irq, void *priv)
281 dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); 341 dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
282 if (src_buf && dst_buf) { 342 if (src_buf && dst_buf) {
283 spin_lock(&fimc->irqlock); 343 spin_lock(&fimc->irqlock);
284 src_buf->vb.state = dst_buf->vb.state = VIDEOBUF_DONE; 344 src_buf->vb.state = dst_buf->vb.state = VIDEOBUF_DONE;
285 wake_up(&src_buf->vb.done); 345 wake_up(&src_buf->vb.done);
286 wake_up(&dst_buf->vb.done); 346 wake_up(&dst_buf->vb.done);
287 spin_unlock(&fimc->irqlock); 347 spin_unlock(&fimc->irqlock);
288 v4l2_m2m_job_finish(fimc->m2m.m2m_dev, ctx->m2m_ctx); 348 v4l2_m2m_job_finish(fimc->m2m.m2m_dev, ctx->m2m_ctx);
289 } 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);
290 } 360 }
291 361
292isr_unlock: 362isr_unlock:
@@ -295,20 +365,13 @@ isr_unlock:
295} 365}
296 366
297/* The color format (planes_cnt, buff_cnt) must be already configured. */ 367/* The color format (planes_cnt, buff_cnt) must be already configured. */
298static int fimc_prepare_addr(struct fimc_ctx *ctx, 368int fimc_prepare_addr(struct fimc_ctx *ctx, struct fimc_vid_buffer *buf,
299 struct fimc_vid_buffer *buf, enum v4l2_buf_type type) 369 struct fimc_frame *frame, struct fimc_addr *paddr)
300{ 370{
301 struct fimc_frame *frame;
302 struct fimc_addr *paddr;
303 u32 pix_size;
304 int ret = 0; 371 int ret = 0;
372 u32 pix_size;
305 373
306 frame = ctx_m2m_get_frame(ctx, type); 374 if (buf == NULL || frame == NULL)
307 if (IS_ERR(frame))
308 return PTR_ERR(frame);
309 paddr = &frame->paddr;
310
311 if (!buf)
312 return -EINVAL; 375 return -EINVAL;
313 376
314 pix_size = frame->width * frame->height; 377 pix_size = frame->width * frame->height;
@@ -344,8 +407,8 @@ static int fimc_prepare_addr(struct fimc_ctx *ctx,
344 } 407 }
345 } 408 }
346 409
347 dbg("PHYS_ADDR: type= %d, y= 0x%X cb= 0x%X cr= 0x%X ret= %d", 410 dbg("PHYS_ADDR: y= 0x%X cb= 0x%X cr= 0x%X ret= %d",
348 type, paddr->y, paddr->cb, paddr->cr, ret); 411 paddr->y, paddr->cb, paddr->cr, ret);
349 412
350 return ret; 413 return ret;
351} 414}
@@ -433,7 +496,7 @@ static void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f)
433 * 496 *
434 * Return: 0 if dimensions are valid or non zero otherwise. 497 * Return: 0 if dimensions are valid or non zero otherwise.
435 */ 498 */
436static int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags) 499int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags)
437{ 500{
438 struct fimc_frame *s_frame, *d_frame; 501 struct fimc_frame *s_frame, *d_frame;
439 struct fimc_vid_buffer *buf = NULL; 502 struct fimc_vid_buffer *buf = NULL;
@@ -443,12 +506,6 @@ static int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags)
443 d_frame = &ctx->d_frame; 506 d_frame = &ctx->d_frame;
444 507
445 if (flags & FIMC_PARAMS) { 508 if (flags & FIMC_PARAMS) {
446 if ((ctx->out_path == FIMC_DMA) &&
447 (ctx->rotation == 90 || ctx->rotation == 270)) {
448 swap(d_frame->f_width, d_frame->f_height);
449 swap(d_frame->width, d_frame->height);
450 }
451
452 /* Prepare the DMA offset ratios for scaler. */ 509 /* Prepare the DMA offset ratios for scaler. */
453 fimc_prepare_dma_offset(ctx, &ctx->s_frame); 510 fimc_prepare_dma_offset(ctx, &ctx->s_frame);
454 fimc_prepare_dma_offset(ctx, &ctx->d_frame); 511 fimc_prepare_dma_offset(ctx, &ctx->d_frame);
@@ -466,16 +523,14 @@ static int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags)
466 523
467 if (flags & FIMC_SRC_ADDR) { 524 if (flags & FIMC_SRC_ADDR) {
468 buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); 525 buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
469 ret = fimc_prepare_addr(ctx, buf, 526 ret = fimc_prepare_addr(ctx, buf, s_frame, &s_frame->paddr);
470 V4L2_BUF_TYPE_VIDEO_OUTPUT);
471 if (ret) 527 if (ret)
472 return ret; 528 return ret;
473 } 529 }
474 530
475 if (flags & FIMC_DST_ADDR) { 531 if (flags & FIMC_DST_ADDR) {
476 buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); 532 buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
477 ret = fimc_prepare_addr(ctx, buf, 533 ret = fimc_prepare_addr(ctx, buf, d_frame, &d_frame->paddr);
478 V4L2_BUF_TYPE_VIDEO_CAPTURE);
479 } 534 }
480 535
481 return ret; 536 return ret;
@@ -499,12 +554,14 @@ static void fimc_dma_run(void *priv)
499 ctx->state |= (FIMC_SRC_ADDR | FIMC_DST_ADDR); 554 ctx->state |= (FIMC_SRC_ADDR | FIMC_DST_ADDR);
500 ret = fimc_prepare_config(ctx, ctx->state); 555 ret = fimc_prepare_config(ctx, ctx->state);
501 if (ret) { 556 if (ret) {
502 err("general configuration error"); 557 err("Wrong parameters");
503 goto dma_unlock; 558 goto dma_unlock;
504 } 559 }
505 560 /* Reconfigure hardware if the context has changed. */
506 if (fimc->m2m.ctx != ctx) 561 if (fimc->m2m.ctx != ctx) {
507 ctx->state |= FIMC_PARAMS; 562 ctx->state |= FIMC_PARAMS;
563 fimc->m2m.ctx = ctx;
564 }
508 565
509 fimc_hw_set_input_addr(fimc, &ctx->s_frame.paddr); 566 fimc_hw_set_input_addr(fimc, &ctx->s_frame.paddr);
510 567
@@ -512,10 +569,9 @@ static void fimc_dma_run(void *priv)
512 fimc_hw_set_input_path(ctx); 569 fimc_hw_set_input_path(ctx);
513 fimc_hw_set_in_dma(ctx); 570 fimc_hw_set_in_dma(ctx);
514 if (fimc_set_scaler_info(ctx)) { 571 if (fimc_set_scaler_info(ctx)) {
515 err("scaler configuration error"); 572 err("Scaler setup error");
516 goto dma_unlock; 573 goto dma_unlock;
517 } 574 }
518 fimc_hw_set_prescaler(ctx);
519 fimc_hw_set_scaler(ctx); 575 fimc_hw_set_scaler(ctx);
520 fimc_hw_set_target_format(ctx); 576 fimc_hw_set_target_format(ctx);
521 fimc_hw_set_rotation(ctx); 577 fimc_hw_set_rotation(ctx);
@@ -524,19 +580,15 @@ static void fimc_dma_run(void *priv)
524 580
525 fimc_hw_set_output_path(ctx); 581 fimc_hw_set_output_path(ctx);
526 if (ctx->state & (FIMC_DST_ADDR | FIMC_PARAMS)) 582 if (ctx->state & (FIMC_DST_ADDR | FIMC_PARAMS))
527 fimc_hw_set_output_addr(fimc, &ctx->d_frame.paddr); 583 fimc_hw_set_output_addr(fimc, &ctx->d_frame.paddr, -1);
528 584
529 if (ctx->state & FIMC_PARAMS) 585 if (ctx->state & FIMC_PARAMS)
530 fimc_hw_set_out_dma(ctx); 586 fimc_hw_set_out_dma(ctx);
531 587
532 if (ctx->scaler.enabled) 588 fimc_activate_capture(ctx);
533 fimc_hw_start_scaler(fimc);
534 fimc_hw_en_capture(ctx);
535 589
536 ctx->state = 0; 590 ctx->state &= (FIMC_CTX_M2M | FIMC_CTX_CAP);
537 fimc_hw_start_in_dma(fimc); 591 fimc_hw_activate_input_dma(fimc, true);
538
539 fimc->m2m.ctx = ctx;
540 592
541dma_unlock: 593dma_unlock:
542 spin_unlock_irqrestore(&ctx->slock, flags); 594 spin_unlock_irqrestore(&ctx->slock, flags);
@@ -560,7 +612,7 @@ static int fimc_buf_setup(struct videobuf_queue *vq, unsigned int *count,
560 struct fimc_ctx *ctx = vq->priv_data; 612 struct fimc_ctx *ctx = vq->priv_data;
561 struct fimc_frame *frame; 613 struct fimc_frame *frame;
562 614
563 frame = ctx_m2m_get_frame(ctx, vq->type); 615 frame = ctx_get_frame(ctx, vq->type);
564 if (IS_ERR(frame)) 616 if (IS_ERR(frame))
565 return PTR_ERR(frame); 617 return PTR_ERR(frame);
566 618
@@ -578,7 +630,7 @@ static int fimc_buf_prepare(struct videobuf_queue *vq,
578 struct fimc_frame *frame; 630 struct fimc_frame *frame;
579 int ret; 631 int ret;
580 632
581 frame = ctx_m2m_get_frame(ctx, vq->type); 633 frame = ctx_get_frame(ctx, vq->type);
582 if (IS_ERR(frame)) 634 if (IS_ERR(frame))
583 return PTR_ERR(frame); 635 return PTR_ERR(frame);
584 636
@@ -618,10 +670,31 @@ static void fimc_buf_queue(struct videobuf_queue *vq,
618 struct videobuf_buffer *vb) 670 struct videobuf_buffer *vb)
619{ 671{
620 struct fimc_ctx *ctx = vq->priv_data; 672 struct fimc_ctx *ctx = vq->priv_data;
621 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 }
622} 695}
623 696
624static struct videobuf_queue_ops fimc_qops = { 697struct videobuf_queue_ops fimc_qops = {
625 .buf_setup = fimc_buf_setup, 698 .buf_setup = fimc_buf_setup,
626 .buf_prepare = fimc_buf_prepare, 699 .buf_prepare = fimc_buf_prepare,
627 .buf_queue = fimc_buf_queue, 700 .buf_queue = fimc_buf_queue,
@@ -644,7 +717,7 @@ static int fimc_m2m_querycap(struct file *file, void *priv,
644 return 0; 717 return 0;
645} 718}
646 719
647static int fimc_m2m_enum_fmt(struct file *file, void *priv, 720int fimc_vidioc_enum_fmt(struct file *file, void *priv,
648 struct v4l2_fmtdesc *f) 721 struct v4l2_fmtdesc *f)
649{ 722{
650 struct fimc_fmt *fmt; 723 struct fimc_fmt *fmt;
@@ -655,189 +728,210 @@ static int fimc_m2m_enum_fmt(struct file *file, void *priv,
655 fmt = &fimc_formats[f->index]; 728 fmt = &fimc_formats[f->index];
656 strncpy(f->description, fmt->name, sizeof(f->description) - 1); 729 strncpy(f->description, fmt->name, sizeof(f->description) - 1);
657 f->pixelformat = fmt->fourcc; 730 f->pixelformat = fmt->fourcc;
731
658 return 0; 732 return 0;
659} 733}
660 734
661static 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)
662{ 736{
663 struct fimc_ctx *ctx = priv; 737 struct fimc_ctx *ctx = priv;
738 struct fimc_dev *fimc = ctx->fimc_dev;
664 struct fimc_frame *frame; 739 struct fimc_frame *frame;
665 740
666 frame = ctx_m2m_get_frame(ctx, f->type); 741 frame = ctx_get_frame(ctx, f->type);
667 if (IS_ERR(frame)) 742 if (IS_ERR(frame))
668 return PTR_ERR(frame); 743 return PTR_ERR(frame);
669 744
745 if (mutex_lock_interruptible(&fimc->lock))
746 return -ERESTARTSYS;
747
670 f->fmt.pix.width = frame->width; 748 f->fmt.pix.width = frame->width;
671 f->fmt.pix.height = frame->height; 749 f->fmt.pix.height = frame->height;
672 f->fmt.pix.field = V4L2_FIELD_NONE; 750 f->fmt.pix.field = V4L2_FIELD_NONE;
673 f->fmt.pix.pixelformat = frame->fmt->fourcc; 751 f->fmt.pix.pixelformat = frame->fmt->fourcc;
674 752
753 mutex_unlock(&fimc->lock);
675 return 0; 754 return 0;
676} 755}
677 756
678static struct fimc_fmt *find_format(struct v4l2_format *f) 757struct fimc_fmt *find_format(struct v4l2_format *f, unsigned int mask)
679{ 758{
680 struct fimc_fmt *fmt; 759 struct fimc_fmt *fmt;
681 unsigned int i; 760 unsigned int i;
682 761
683 for (i = 0; i < ARRAY_SIZE(fimc_formats); ++i) { 762 for (i = 0; i < ARRAY_SIZE(fimc_formats); ++i) {
684 fmt = &fimc_formats[i]; 763 fmt = &fimc_formats[i];
685 if (fmt->fourcc == f->fmt.pix.pixelformat) 764 if (fmt->fourcc == f->fmt.pix.pixelformat &&
765 (fmt->flags & mask))
686 break; 766 break;
687 } 767 }
688 if (i == ARRAY_SIZE(fimc_formats))
689 return NULL;
690 768
691 return fmt; 769 return (i == ARRAY_SIZE(fimc_formats)) ? NULL : fmt;
692} 770}
693 771
694static int fimc_m2m_try_fmt(struct file *file, void *priv, 772struct fimc_fmt *find_mbus_format(struct v4l2_mbus_framefmt *f,
695 struct v4l2_format *f) 773 unsigned int mask)
696{ 774{
697 struct fimc_fmt *fmt; 775 struct fimc_fmt *fmt;
698 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{
699 struct fimc_ctx *ctx = priv; 790 struct fimc_ctx *ctx = priv;
700 struct fimc_dev *fimc = ctx->fimc_dev; 791 struct fimc_dev *fimc = ctx->fimc_dev;
701 struct v4l2_pix_format *pix = &f->fmt.pix;
702 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;
703 797
704 fmt = find_format(f); 798 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
705 if (!fmt) { 799 if (ctx->state & FIMC_CTX_CAP)
706 v4l2_err(&fimc->m2m.v4l2_dev, 800 return -EINVAL;
707 "Fourcc format (0x%X) invalid.\n", pix->pixelformat); 801 is_output = 1;
802 } else if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
708 return -EINVAL; 803 return -EINVAL;
709 } 804 }
710 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
711 if (pix->field == V4L2_FIELD_ANY) 820 if (pix->field == V4L2_FIELD_ANY)
712 pix->field = V4L2_FIELD_NONE; 821 pix->field = V4L2_FIELD_NONE;
713 else if (V4L2_FIELD_NONE != pix->field) 822 else if (V4L2_FIELD_NONE != pix->field)
714 return -EINVAL; 823 goto tf_out;
715 824
716 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { 825 if (is_output) {
717 max_width = variant->scaler_dis_w; 826 max_width = variant->pix_limit->scaler_dis_w;
718 max_height = variant->scaler_dis_w; 827 mod_x = ffs(variant->min_inp_pixsize) - 1;
719 mod_x = variant->min_inp_pixsize;
720 mod_y = variant->min_inp_pixsize;
721 } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
722 max_width = variant->out_rot_dis_w;
723 max_height = variant->out_rot_dis_w;
724 mod_x = variant->min_out_pixsize;
725 mod_y = variant->min_out_pixsize;
726 } else { 828 } else {
727 err("Wrong stream type (%d)", f->type); 829 max_width = variant->pix_limit->out_rot_dis_w;
728 return -EINVAL; 830 mod_x = ffs(variant->min_out_pixsize) - 1;
729 } 831 }
730 832
731 dbg("max_w= %d, max_h= %d", max_width, max_height);
732
733 if (pix->height > max_height)
734 pix->height = max_height;
735 if (pix->width > max_width)
736 pix->width = max_width;
737
738 if (tiled_fmt(fmt)) { 833 if (tiled_fmt(fmt)) {
739 mod_x = 64; /* 64x32 tile */ 834 mod_x = 6; /* 64 x 32 pixels tile */
740 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;
741 } 841 }
742 842
743 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);
744 844
745 pix->width = (pix->width == 0) ? mod_x : ALIGN(pix->width, mod_x); 845 v4l_bound_align_image(&pix->width, 16, max_width, mod_x,
746 pix->height = (pix->height == 0) ? mod_y : ALIGN(pix->height, mod_y); 846 &pix->height, 8, variant->pix_limit->scaler_dis_w, mod_y, 0);
747 847
748 if (pix->bytesperline == 0 || 848 if (pix->bytesperline == 0 ||
749 pix->bytesperline * 8 / fmt->depth > pix->width) 849 (pix->bytesperline * 8 / fmt->depth) > pix->width)
750 pix->bytesperline = (pix->width * fmt->depth) >> 3; 850 pix->bytesperline = (pix->width * fmt->depth) >> 3;
751 851
752 if (pix->sizeimage == 0) 852 if (pix->sizeimage == 0)
753 pix->sizeimage = pix->height * pix->bytesperline; 853 pix->sizeimage = pix->height * pix->bytesperline;
754 854
755 dbg("pix->bytesperline= %d, fmt->depth= %d", 855 dbg("w: %d, h: %d, bpl: %d, depth: %d",
756 pix->bytesperline, fmt->depth); 856 pix->width, pix->height, pix->bytesperline, fmt->depth);
757 857
758 return 0; 858 ret = 0;
759}
760 859
860tf_out:
861 mutex_unlock(&fimc->lock);
862 return ret;
863}
761 864
762static 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)
763{ 866{
764 struct fimc_ctx *ctx = priv; 867 struct fimc_ctx *ctx = priv;
765 struct v4l2_device *v4l2_dev = &ctx->fimc_dev->m2m.v4l2_dev; 868 struct fimc_dev *fimc = ctx->fimc_dev;
766 struct videobuf_queue *src_vq, *dst_vq; 869 struct v4l2_device *v4l2_dev = &fimc->m2m.v4l2_dev;
870 struct videobuf_queue *vq;
767 struct fimc_frame *frame; 871 struct fimc_frame *frame;
768 struct v4l2_pix_format *pix; 872 struct v4l2_pix_format *pix;
769 unsigned long flags; 873 unsigned long flags;
770 int ret = 0; 874 int ret = 0;
771 875
772 BUG_ON(!ctx); 876 ret = fimc_vidioc_try_fmt(file, priv, f);
773
774 ret = fimc_m2m_try_fmt(file, priv, f);
775 if (ret) 877 if (ret)
776 return ret; 878 return ret;
777 879
778 mutex_lock(&ctx->fimc_dev->lock); 880 if (mutex_lock_interruptible(&fimc->lock))
881 return -ERESTARTSYS;
779 882
780 src_vq = v4l2_m2m_get_src_vq(ctx->m2m_ctx); 883 vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
781 dst_vq = v4l2_m2m_get_dst_vq(ctx->m2m_ctx); 884 mutex_lock(&vq->vb_lock);
782 885
783 mutex_lock(&src_vq->vb_lock); 886 if (videobuf_queue_is_busy(vq)) {
784 mutex_lock(&dst_vq->vb_lock); 887 v4l2_err(v4l2_dev, "%s: queue (%d) busy\n", __func__, f->type);
888 ret = -EBUSY;
889 goto sf_out;
890 }
785 891
892 spin_lock_irqsave(&ctx->slock, flags);
786 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { 893 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
787 if (videobuf_queue_is_busy(src_vq)) {
788 v4l2_err(v4l2_dev, "%s queue busy\n", __func__);
789 ret = -EBUSY;
790 goto s_fmt_out;
791 }
792 frame = &ctx->s_frame; 894 frame = &ctx->s_frame;
793 spin_lock_irqsave(&ctx->slock, flags);
794 ctx->state |= FIMC_SRC_FMT; 895 ctx->state |= FIMC_SRC_FMT;
795 spin_unlock_irqrestore(&ctx->slock, flags);
796
797 } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { 896 } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
798 if (videobuf_queue_is_busy(dst_vq)) {
799 v4l2_err(v4l2_dev, "%s queue busy\n", __func__);
800 ret = -EBUSY;
801 goto s_fmt_out;
802 }
803 frame = &ctx->d_frame; 897 frame = &ctx->d_frame;
804 spin_lock_irqsave(&ctx->slock, flags);
805 ctx->state |= FIMC_DST_FMT; 898 ctx->state |= FIMC_DST_FMT;
806 spin_unlock_irqrestore(&ctx->slock, flags);
807 } else { 899 } else {
900 spin_unlock_irqrestore(&ctx->slock, flags);
808 v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev, 901 v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev,
809 "Wrong buffer/video queue type (%d)\n", f->type); 902 "Wrong buffer/video queue type (%d)\n", f->type);
810 ret = -EINVAL; 903 ret = -EINVAL;
811 goto s_fmt_out; 904 goto sf_out;
812 } 905 }
906 spin_unlock_irqrestore(&ctx->slock, flags);
813 907
814 pix = &f->fmt.pix; 908 pix = &f->fmt.pix;
815 frame->fmt = find_format(f); 909 frame->fmt = find_format(f, FMT_FLAGS_M2M);
816 if (!frame->fmt) { 910 if (!frame->fmt) {
817 ret = -EINVAL; 911 ret = -EINVAL;
818 goto s_fmt_out; 912 goto sf_out;
819 } 913 }
820 914
821 frame->f_width = pix->bytesperline * 8 / frame->fmt->depth; 915 frame->f_width = pix->bytesperline * 8 / frame->fmt->depth;
822 frame->f_height = pix->sizeimage/pix->bytesperline; 916 frame->f_height = pix->height;
823 frame->width = pix->width; 917 frame->width = pix->width;
824 frame->height = pix->height; 918 frame->height = pix->height;
825 frame->o_width = pix->width; 919 frame->o_width = pix->width;
826 frame->o_height = pix->height; 920 frame->o_height = pix->height;
827 frame->offs_h = 0; 921 frame->offs_h = 0;
828 frame->offs_v = 0; 922 frame->offs_v = 0;
829 frame->size = (pix->width * pix->height * frame->fmt->depth) >> 3; 923 frame->size = (pix->width * pix->height * frame->fmt->depth) >> 3;
830 src_vq->field = dst_vq->field = pix->field; 924 vq->field = pix->field;
925
831 spin_lock_irqsave(&ctx->slock, flags); 926 spin_lock_irqsave(&ctx->slock, flags);
832 ctx->state |= FIMC_PARAMS; 927 ctx->state |= FIMC_PARAMS;
833 spin_unlock_irqrestore(&ctx->slock, flags); 928 spin_unlock_irqrestore(&ctx->slock, flags);
834 929
835 dbg("f_width= %d, f_height= %d", frame->f_width, frame->f_height); 930 dbg("f_w: %d, f_h: %d", frame->f_width, frame->f_height);
836 931
837s_fmt_out: 932sf_out:
838 mutex_unlock(&dst_vq->vb_lock); 933 mutex_unlock(&vq->vb_lock);
839 mutex_unlock(&src_vq->vb_lock); 934 mutex_unlock(&fimc->lock);
840 mutex_unlock(&ctx->fimc_dev->lock);
841 return ret; 935 return ret;
842} 936}
843 937
@@ -884,21 +978,33 @@ static int fimc_m2m_streamoff(struct file *file, void *priv,
884 return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); 978 return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
885} 979}
886 980
887int fimc_m2m_queryctrl(struct file *file, void *priv, 981int fimc_vidioc_queryctrl(struct file *file, void *priv,
888 struct v4l2_queryctrl *qc) 982 struct v4l2_queryctrl *qc)
889{ 983{
984 struct fimc_ctx *ctx = priv;
890 struct v4l2_queryctrl *c; 985 struct v4l2_queryctrl *c;
986
891 c = get_ctrl(qc->id); 987 c = get_ctrl(qc->id);
892 if (!c) 988 if (c) {
893 return -EINVAL; 989 *qc = *c;
894 *qc = *c; 990 return 0;
895 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;
896} 997}
897 998
898int fimc_m2m_g_ctrl(struct file *file, void *priv, 999int fimc_vidioc_g_ctrl(struct file *file, void *priv,
899 struct v4l2_control *ctrl) 1000 struct v4l2_control *ctrl)
900{ 1001{
901 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;
902 1008
903 switch (ctrl->id) { 1009 switch (ctrl->id) {
904 case V4L2_CID_HFLIP: 1010 case V4L2_CID_HFLIP:
@@ -911,15 +1017,22 @@ int fimc_m2m_g_ctrl(struct file *file, void *priv,
911 ctrl->value = ctx->rotation; 1017 ctrl->value = ctx->rotation;
912 break; 1018 break;
913 default: 1019 default:
914 v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev, "Invalid control\n"); 1020 if (ctx->state & FIMC_CTX_CAP) {
915 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 }
916 } 1028 }
917 dbg("ctrl->value= %d", ctrl->value); 1029 dbg("ctrl->value= %d", ctrl->value);
918 return 0; 1030
1031 mutex_unlock(&fimc->lock);
1032 return ret;
919} 1033}
920 1034
921static int check_ctrl_val(struct fimc_ctx *ctx, 1035int check_ctrl_val(struct fimc_ctx *ctx, struct v4l2_control *ctrl)
922 struct v4l2_control *ctrl)
923{ 1036{
924 struct v4l2_queryctrl *c; 1037 struct v4l2_queryctrl *c;
925 c = get_ctrl(ctrl->id); 1038 c = get_ctrl(ctrl->id);
@@ -936,22 +1049,23 @@ static int check_ctrl_val(struct fimc_ctx *ctx,
936 return 0; 1049 return 0;
937} 1050}
938 1051
939int fimc_m2m_s_ctrl(struct file *file, void *priv, 1052int fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_control *ctrl)
940 struct v4l2_control *ctrl)
941{ 1053{
942 struct fimc_ctx *ctx = priv;
943 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;
944 unsigned long flags; 1056 unsigned long flags;
945 int ret = 0;
946 1057
947 ret = check_ctrl_val(ctx, ctrl); 1058 if (ctx->rotation != 0 &&
948 if (ret) 1059 (ctrl->id == V4L2_CID_HFLIP || ctrl->id == V4L2_CID_VFLIP)) {
949 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);
950 1066
951 switch (ctrl->id) { 1067 switch (ctrl->id) {
952 case V4L2_CID_HFLIP: 1068 case V4L2_CID_HFLIP:
953 if (ctx->rotation != 0)
954 return 0;
955 if (ctrl->value) 1069 if (ctrl->value)
956 ctx->flip |= FLIP_X_AXIS; 1070 ctx->flip |= FLIP_X_AXIS;
957 else 1071 else
@@ -959,8 +1073,6 @@ int fimc_m2m_s_ctrl(struct file *file, void *priv,
959 break; 1073 break;
960 1074
961 case V4L2_CID_VFLIP: 1075 case V4L2_CID_VFLIP:
962 if (ctx->rotation != 0)
963 return 0;
964 if (ctrl->value) 1076 if (ctrl->value)
965 ctx->flip |= FLIP_Y_AXIS; 1077 ctx->flip |= FLIP_Y_AXIS;
966 else 1078 else
@@ -968,77 +1080,95 @@ int fimc_m2m_s_ctrl(struct file *file, void *priv,
968 break; 1080 break;
969 1081
970 case V4L2_CID_ROTATE: 1082 case V4L2_CID_ROTATE:
971 if (ctrl->value == 90 || ctrl->value == 270) { 1083 /* Check for the output rotator availability */
972 if (ctx->out_path == FIMC_LCDFIFO && 1084 if ((ctrl->value == 90 || ctrl->value == 270) &&
973 !variant->has_inp_rot) { 1085 (ctx->in_path == FIMC_DMA && !variant->has_out_rot)) {
974 return -EINVAL; 1086 spin_unlock_irqrestore(&ctx->slock, flags);
975 } else if (ctx->in_path == FIMC_DMA && 1087 return -EINVAL;
976 !variant->has_out_rot) { 1088 } else {
977 return -EINVAL; 1089 ctx->rotation = ctrl->value;
978 }
979 } 1090 }
980 ctx->rotation = ctrl->value;
981 if (ctrl->value == 180)
982 ctx->flip = FLIP_XY_AXIS;
983 break; 1091 break;
984 1092
985 default: 1093 default:
986 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");
987 return -EINVAL; 1096 return -EINVAL;
988 } 1097 }
989 spin_lock_irqsave(&ctx->slock, flags);
990 ctx->state |= FIMC_PARAMS; 1098 ctx->state |= FIMC_PARAMS;
991 spin_unlock_irqrestore(&ctx->slock, flags); 1099 spin_unlock_irqrestore(&ctx->slock, flags);
1100
992 return 0; 1101 return 0;
993} 1102}
994 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}
995 1117
996static int fimc_m2m_cropcap(struct file *file, void *fh, 1118int fimc_vidioc_cropcap(struct file *file, void *fh,
997 struct v4l2_cropcap *cr) 1119 struct v4l2_cropcap *cr)
998{ 1120{
999 struct fimc_frame *frame; 1121 struct fimc_frame *frame;
1000 struct fimc_ctx *ctx = fh; 1122 struct fimc_ctx *ctx = fh;
1123 struct fimc_dev *fimc = ctx->fimc_dev;
1001 1124
1002 frame = ctx_m2m_get_frame(ctx, cr->type); 1125 frame = ctx_get_frame(ctx, cr->type);
1003 if (IS_ERR(frame)) 1126 if (IS_ERR(frame))
1004 return PTR_ERR(frame); 1127 return PTR_ERR(frame);
1005 1128
1006 cr->bounds.left = 0; 1129 if (mutex_lock_interruptible(&fimc->lock))
1007 cr->bounds.top = 0; 1130 return -ERESTARTSYS;
1008 cr->bounds.width = frame->f_width; 1131
1009 cr->bounds.height = frame->f_height; 1132 cr->bounds.left = 0;
1010 cr->defrect.left = frame->offs_h; 1133 cr->bounds.top = 0;
1011 cr->defrect.top = frame->offs_v; 1134 cr->bounds.width = frame->f_width;
1012 cr->defrect.width = frame->o_width; 1135 cr->bounds.height = frame->f_height;
1013 cr->defrect.height = frame->o_height; 1136 cr->defrect = cr->bounds;
1137
1138 mutex_unlock(&fimc->lock);
1014 return 0; 1139 return 0;
1015} 1140}
1016 1141
1017static 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)
1018{ 1143{
1019 struct fimc_frame *frame; 1144 struct fimc_frame *frame;
1020 struct fimc_ctx *ctx = file->private_data; 1145 struct fimc_ctx *ctx = file->private_data;
1146 struct fimc_dev *fimc = ctx->fimc_dev;
1021 1147
1022 frame = ctx_m2m_get_frame(ctx, cr->type); 1148 frame = ctx_get_frame(ctx, cr->type);
1023 if (IS_ERR(frame)) 1149 if (IS_ERR(frame))
1024 return PTR_ERR(frame); 1150 return PTR_ERR(frame);
1025 1151
1152 if (mutex_lock_interruptible(&fimc->lock))
1153 return -ERESTARTSYS;
1154
1026 cr->c.left = frame->offs_h; 1155 cr->c.left = frame->offs_h;
1027 cr->c.top = frame->offs_v; 1156 cr->c.top = frame->offs_v;
1028 cr->c.width = frame->width; 1157 cr->c.width = frame->width;
1029 cr->c.height = frame->height; 1158 cr->c.height = frame->height;
1030 1159
1160 mutex_unlock(&fimc->lock);
1031 return 0; 1161 return 0;
1032} 1162}
1033 1163
1034static 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)
1035{ 1165{
1036 struct fimc_ctx *ctx = file->private_data;
1037 struct fimc_dev *fimc = ctx->fimc_dev; 1166 struct fimc_dev *fimc = ctx->fimc_dev;
1038 unsigned long flags;
1039 struct fimc_frame *f; 1167 struct fimc_frame *f;
1040 u32 min_size; 1168 u32 min_size, halign;
1041 int ret = 0; 1169
1170 f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ?
1171 &ctx->s_frame : &ctx->d_frame;
1042 1172
1043 if (cr->c.top < 0 || cr->c.left < 0) { 1173 if (cr->c.top < 0 || cr->c.left < 0) {
1044 v4l2_err(&fimc->m2m.v4l2_dev, 1174 v4l2_err(&fimc->m2m.v4l2_dev,
@@ -1046,66 +1176,98 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
1046 return -EINVAL; 1176 return -EINVAL;
1047 } 1177 }
1048 1178
1049 if (cr->c.width <= 0 || cr->c.height <= 0) { 1179 f = ctx_get_frame(ctx, cr->type);
1050 v4l2_err(&fimc->m2m.v4l2_dev,
1051 "crop width and height must be greater than 0\n");
1052 return -EINVAL;
1053 }
1054
1055 f = ctx_m2m_get_frame(ctx, cr->type);
1056 if (IS_ERR(f)) 1180 if (IS_ERR(f))
1057 return PTR_ERR(f); 1181 return PTR_ERR(f);
1058 1182
1059 /* Adjust to required pixel boundary. */ 1183 min_size = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
1060 min_size = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ? 1184 ? fimc->variant->min_inp_pixsize
1061 fimc->variant->min_inp_pixsize : fimc->variant->min_out_pixsize; 1185 : fimc->variant->min_out_pixsize;
1062
1063 cr->c.width = round_down(cr->c.width, min_size);
1064 cr->c.height = round_down(cr->c.height, min_size);
1065 cr->c.left = round_down(cr->c.left + 1, min_size);
1066 cr->c.top = round_down(cr->c.top + 1, min_size);
1067 1186
1068 if ((cr->c.left + cr->c.width > f->o_width) 1187 if (ctx->state & FIMC_CTX_M2M) {
1069 || (cr->c.top + cr->c.height > f->o_height)) { 1188 if (fimc->id == 1 && fimc->variant->pix_hoff)
1070 v4l2_err(&fimc->m2m.v4l2_dev, "Error in S_CROP params\n"); 1189 halign = fimc_fmt_is_rgb(f->fmt->color) ? 0 : 1;
1071 return -EINVAL; 1190 else
1191 halign = ffs(min_size) - 1;
1192 /* there are more strict aligment requirements at camera interface */
1193 } else {
1194 min_size = 16;
1195 halign = 4;
1072 } 1196 }
1073 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
1074 spin_lock_irqsave(&ctx->slock, flags); 1236 spin_lock_irqsave(&ctx->slock, flags);
1075 if ((ctx->state & FIMC_SRC_FMT) && (ctx->state & FIMC_DST_FMT)) { 1237 if (~ctx->state & (FIMC_SRC_FMT | FIMC_DST_FMT)) {
1076 /* Check for the pixel scaling ratio when cropping input img. */ 1238 /* Check to see if scaling ratio is within supported range */
1077 if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) 1239 if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
1078 ret = fimc_check_scaler_ratio(&cr->c, &ctx->d_frame); 1240 ret = fimc_check_scaler_ratio(&cr->c, &ctx->d_frame);
1079 else if (cr->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1241 else
1080 ret = fimc_check_scaler_ratio(&cr->c, &ctx->s_frame); 1242 ret = fimc_check_scaler_ratio(&cr->c, &ctx->s_frame);
1081
1082 if (ret) { 1243 if (ret) {
1083 spin_unlock_irqrestore(&ctx->slock, flags); 1244 spin_unlock_irqrestore(&ctx->slock, flags);
1084 v4l2_err(&fimc->m2m.v4l2_dev, "Out of scaler range"); 1245 v4l2_err(&fimc->m2m.v4l2_dev, "Out of scaler range");
1085 return -EINVAL; 1246 return -EINVAL;
1086 } 1247 }
1087 } 1248 }
1088 ctx->state |= FIMC_PARAMS; 1249 ctx->state |= FIMC_PARAMS;
1089 spin_unlock_irqrestore(&ctx->slock, flags);
1090 1250
1091 f->offs_h = cr->c.left; 1251 f->offs_h = cr->c.left;
1092 f->offs_v = cr->c.top; 1252 f->offs_v = cr->c.top;
1093 f->width = cr->c.width; 1253 f->width = cr->c.width;
1094 f->height = cr->c.height; 1254 f->height = cr->c.height;
1255
1256 spin_unlock_irqrestore(&ctx->slock, flags);
1095 return 0; 1257 return 0;
1096} 1258}
1097 1259
1098static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = { 1260static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = {
1099 .vidioc_querycap = fimc_m2m_querycap, 1261 .vidioc_querycap = fimc_m2m_querycap,
1100 1262
1101 .vidioc_enum_fmt_vid_cap = fimc_m2m_enum_fmt, 1263 .vidioc_enum_fmt_vid_cap = fimc_vidioc_enum_fmt,
1102 .vidioc_enum_fmt_vid_out = fimc_m2m_enum_fmt, 1264 .vidioc_enum_fmt_vid_out = fimc_vidioc_enum_fmt,
1103 1265
1104 .vidioc_g_fmt_vid_cap = fimc_m2m_g_fmt, 1266 .vidioc_g_fmt_vid_cap = fimc_vidioc_g_fmt,
1105 .vidioc_g_fmt_vid_out = fimc_m2m_g_fmt, 1267 .vidioc_g_fmt_vid_out = fimc_vidioc_g_fmt,
1106 1268
1107 .vidioc_try_fmt_vid_cap = fimc_m2m_try_fmt, 1269 .vidioc_try_fmt_vid_cap = fimc_vidioc_try_fmt,
1108 .vidioc_try_fmt_vid_out = fimc_m2m_try_fmt, 1270 .vidioc_try_fmt_vid_out = fimc_vidioc_try_fmt,
1109 1271
1110 .vidioc_s_fmt_vid_cap = fimc_m2m_s_fmt, 1272 .vidioc_s_fmt_vid_cap = fimc_m2m_s_fmt,
1111 .vidioc_s_fmt_vid_out = fimc_m2m_s_fmt, 1273 .vidioc_s_fmt_vid_out = fimc_m2m_s_fmt,
@@ -1119,13 +1281,13 @@ static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = {
1119 .vidioc_streamon = fimc_m2m_streamon, 1281 .vidioc_streamon = fimc_m2m_streamon,
1120 .vidioc_streamoff = fimc_m2m_streamoff, 1282 .vidioc_streamoff = fimc_m2m_streamoff,
1121 1283
1122 .vidioc_queryctrl = fimc_m2m_queryctrl, 1284 .vidioc_queryctrl = fimc_vidioc_queryctrl,
1123 .vidioc_g_ctrl = fimc_m2m_g_ctrl, 1285 .vidioc_g_ctrl = fimc_vidioc_g_ctrl,
1124 .vidioc_s_ctrl = fimc_m2m_s_ctrl, 1286 .vidioc_s_ctrl = fimc_m2m_s_ctrl,
1125 1287
1126 .vidioc_g_crop = fimc_m2m_g_crop, 1288 .vidioc_g_crop = fimc_vidioc_g_crop,
1127 .vidioc_s_crop = fimc_m2m_s_crop, 1289 .vidioc_s_crop = fimc_m2m_s_crop,
1128 .vidioc_cropcap = fimc_m2m_cropcap 1290 .vidioc_cropcap = fimc_vidioc_cropcap
1129 1291
1130}; 1292};
1131 1293
@@ -1136,9 +1298,9 @@ static void queue_init(void *priv, struct videobuf_queue *vq,
1136 struct fimc_dev *fimc = ctx->fimc_dev; 1298 struct fimc_dev *fimc = ctx->fimc_dev;
1137 1299
1138 videobuf_queue_dma_contig_init(vq, &fimc_qops, 1300 videobuf_queue_dma_contig_init(vq, &fimc_qops,
1139 fimc->m2m.v4l2_dev.dev, 1301 &fimc->pdev->dev,
1140 &fimc->irqlock, type, V4L2_FIELD_NONE, 1302 &fimc->irqlock, type, V4L2_FIELD_NONE,
1141 sizeof(struct fimc_vid_buffer), priv); 1303 sizeof(struct fimc_vid_buffer), priv, NULL);
1142} 1304}
1143 1305
1144static int fimc_m2m_open(struct file *file) 1306static int fimc_m2m_open(struct file *file)
@@ -1147,25 +1309,38 @@ static int fimc_m2m_open(struct file *file)
1147 struct fimc_ctx *ctx = NULL; 1309 struct fimc_ctx *ctx = NULL;
1148 int err = 0; 1310 int err = 0;
1149 1311
1150 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 err = -EBUSY;
1324 goto err_unlock;
1325 }
1326
1151 fimc->m2m.refcnt++; 1327 fimc->m2m.refcnt++;
1152 set_bit(ST_OUTDMA_RUN, &fimc->state); 1328 set_bit(ST_OUTDMA_RUN, &fimc->state);
1153 mutex_unlock(&fimc->lock);
1154
1155 1329
1156 ctx = kzalloc(sizeof *ctx, GFP_KERNEL); 1330 ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
1157 if (!ctx) 1331 if (!ctx) {
1158 return -ENOMEM; 1332 err = -ENOMEM;
1333 goto err_unlock;
1334 }
1159 1335
1160 file->private_data = ctx; 1336 file->private_data = ctx;
1161 ctx->fimc_dev = fimc; 1337 ctx->fimc_dev = fimc;
1162 /* default format */ 1338 /* Default color format */
1163 ctx->s_frame.fmt = &fimc_formats[0]; 1339 ctx->s_frame.fmt = &fimc_formats[0];
1164 ctx->d_frame.fmt = &fimc_formats[0]; 1340 ctx->d_frame.fmt = &fimc_formats[0];
1165 /* per user process device context initialization */ 1341 /* Setup the device context for mem2mem mode. */
1166 ctx->state = 0; 1342 ctx->state = FIMC_CTX_M2M;
1167 ctx->flags = 0; 1343 ctx->flags = 0;
1168 ctx->effect.type = S5P_FIMC_EFFECT_ORIGINAL;
1169 ctx->in_path = FIMC_DMA; 1344 ctx->in_path = FIMC_DMA;
1170 ctx->out_path = FIMC_DMA; 1345 ctx->out_path = FIMC_DMA;
1171 spin_lock_init(&ctx->slock); 1346 spin_lock_init(&ctx->slock);
@@ -1175,6 +1350,9 @@ static int fimc_m2m_open(struct file *file)
1175 err = PTR_ERR(ctx->m2m_ctx); 1350 err = PTR_ERR(ctx->m2m_ctx);
1176 kfree(ctx); 1351 kfree(ctx);
1177 } 1352 }
1353
1354err_unlock:
1355 mutex_unlock(&fimc->lock);
1178 return err; 1356 return err;
1179} 1357}
1180 1358
@@ -1183,11 +1361,16 @@ static int fimc_m2m_release(struct file *file)
1183 struct fimc_ctx *ctx = file->private_data; 1361 struct fimc_ctx *ctx = file->private_data;
1184 struct fimc_dev *fimc = ctx->fimc_dev; 1362 struct fimc_dev *fimc = ctx->fimc_dev;
1185 1363
1364 mutex_lock(&fimc->lock);
1365
1366 dbg("pid: %d, state: 0x%lx, refcnt= %d",
1367 task_pid_nr(current), fimc->state, fimc->m2m.refcnt);
1368
1186 v4l2_m2m_ctx_release(ctx->m2m_ctx); 1369 v4l2_m2m_ctx_release(ctx->m2m_ctx);
1187 kfree(ctx); 1370 kfree(ctx);
1188 mutex_lock(&fimc->lock);
1189 if (--fimc->m2m.refcnt <= 0) 1371 if (--fimc->m2m.refcnt <= 0)
1190 clear_bit(ST_OUTDMA_RUN, &fimc->state); 1372 clear_bit(ST_OUTDMA_RUN, &fimc->state);
1373
1191 mutex_unlock(&fimc->lock); 1374 mutex_unlock(&fimc->lock);
1192 return 0; 1375 return 0;
1193} 1376}
@@ -1196,6 +1379,7 @@ static unsigned int fimc_m2m_poll(struct file *file,
1196 struct poll_table_struct *wait) 1379 struct poll_table_struct *wait)
1197{ 1380{
1198 struct fimc_ctx *ctx = file->private_data; 1381 struct fimc_ctx *ctx = file->private_data;
1382
1199 return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); 1383 return v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
1200} 1384}
1201 1385
@@ -1203,6 +1387,7 @@ static unsigned int fimc_m2m_poll(struct file *file,
1203static int fimc_m2m_mmap(struct file *file, struct vm_area_struct *vma) 1387static int fimc_m2m_mmap(struct file *file, struct vm_area_struct *vma)
1204{ 1388{
1205 struct fimc_ctx *ctx = file->private_data; 1389 struct fimc_ctx *ctx = file->private_data;
1390
1206 return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); 1391 return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
1207} 1392}
1208 1393
@@ -1241,7 +1426,7 @@ static int fimc_register_m2m_device(struct fimc_dev *fimc)
1241 1426
1242 ret = v4l2_device_register(&pdev->dev, v4l2_dev); 1427 ret = v4l2_device_register(&pdev->dev, v4l2_dev);
1243 if (ret) 1428 if (ret)
1244 return ret;; 1429 goto err_m2m_r1;
1245 1430
1246 vfd = video_device_alloc(); 1431 vfd = video_device_alloc();
1247 if (!vfd) { 1432 if (!vfd) {
@@ -1293,7 +1478,7 @@ static void fimc_unregister_m2m_device(struct fimc_dev *fimc)
1293 if (fimc) { 1478 if (fimc) {
1294 v4l2_m2m_release(fimc->m2m.m2m_dev); 1479 v4l2_m2m_release(fimc->m2m.m2m_dev);
1295 video_unregister_device(fimc->m2m.vfd); 1480 video_unregister_device(fimc->m2m.vfd);
1296 video_device_release(fimc->m2m.vfd); 1481
1297 v4l2_device_unregister(&fimc->m2m.v4l2_dev); 1482 v4l2_device_unregister(&fimc->m2m.v4l2_dev);
1298 } 1483 }
1299} 1484}
@@ -1337,7 +1522,7 @@ static int fimc_probe(struct platform_device *pdev)
1337 drv_data = (struct samsung_fimc_driverdata *) 1522 drv_data = (struct samsung_fimc_driverdata *)
1338 platform_get_device_id(pdev)->driver_data; 1523 platform_get_device_id(pdev)->driver_data;
1339 1524
1340 if (pdev->id >= drv_data->devs_cnt) { 1525 if (pdev->id >= drv_data->num_entities) {
1341 dev_err(&pdev->dev, "Invalid platform device id: %d\n", 1526 dev_err(&pdev->dev, "Invalid platform device id: %d\n",
1342 pdev->id); 1527 pdev->id);
1343 return -EINVAL; 1528 return -EINVAL;
@@ -1350,9 +1535,11 @@ static int fimc_probe(struct platform_device *pdev)
1350 fimc->id = pdev->id; 1535 fimc->id = pdev->id;
1351 fimc->variant = drv_data->variant[fimc->id]; 1536 fimc->variant = drv_data->variant[fimc->id];
1352 fimc->pdev = pdev; 1537 fimc->pdev = pdev;
1538 fimc->pdata = pdev->dev.platform_data;
1353 fimc->state = ST_IDLE; 1539 fimc->state = ST_IDLE;
1354 1540
1355 spin_lock_init(&fimc->irqlock); 1541 spin_lock_init(&fimc->irqlock);
1542 init_waitqueue_head(&fimc->irq_queue);
1356 spin_lock_init(&fimc->slock); 1543 spin_lock_init(&fimc->slock);
1357 1544
1358 mutex_init(&fimc->lock); 1545 mutex_init(&fimc->lock);
@@ -1382,6 +1569,7 @@ static int fimc_probe(struct platform_device *pdev)
1382 ret = fimc_clk_get(fimc); 1569 ret = fimc_clk_get(fimc);
1383 if (ret) 1570 if (ret)
1384 goto err_regs_unmap; 1571 goto err_regs_unmap;
1572 clk_set_rate(fimc->clock[0], drv_data->lclk_frequency);
1385 1573
1386 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 1574 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1387 if (!res) { 1575 if (!res) {
@@ -1399,25 +1587,38 @@ static int fimc_probe(struct platform_device *pdev)
1399 goto err_clk; 1587 goto err_clk;
1400 } 1588 }
1401 1589
1402 fimc->work_queue = create_workqueue(dev_name(&fimc->pdev->dev));
1403 if (!fimc->work_queue) {
1404 ret = -ENOMEM;
1405 goto err_irq;
1406 }
1407
1408 ret = fimc_register_m2m_device(fimc); 1590 ret = fimc_register_m2m_device(fimc);
1409 if (ret) 1591 if (ret)
1410 goto err_wq; 1592 goto err_irq;
1593
1594 /* At least one camera sensor is required to register capture node */
1595 if (fimc->pdata) {
1596 int i;
1597 for (i = 0; i < FIMC_MAX_CAMIF_CLIENTS; ++i)
1598 if (fimc->pdata->isp_info[i])
1599 break;
1600
1601 if (i < FIMC_MAX_CAMIF_CLIENTS) {
1602 ret = fimc_register_capture_device(fimc);
1603 if (ret)
1604 goto err_m2m;
1605 }
1606 }
1411 1607
1412 fimc_hw_en_lastirq(fimc, true); 1608 /*
1609 * Exclude the additional output DMA address registers by masking
1610 * them out on HW revisions that provide extended capabilites.
1611 */
1612 if (fimc->variant->out_buf_count > 4)
1613 fimc_hw_set_dma_seq(fimc, 0xF);
1413 1614
1414 dev_dbg(&pdev->dev, "%s(): fimc-%d registered successfully\n", 1615 dev_dbg(&pdev->dev, "%s(): fimc-%d registered successfully\n",
1415 __func__, fimc->id); 1616 __func__, fimc->id);
1416 1617
1417 return 0; 1618 return 0;
1418 1619
1419err_wq: 1620err_m2m:
1420 destroy_workqueue(fimc->work_queue); 1621 fimc_unregister_m2m_device(fimc);
1421err_irq: 1622err_irq:
1422 free_irq(fimc->irq, fimc); 1623 free_irq(fimc->irq, fimc);
1423err_clk: 1624err_clk:
@@ -1429,7 +1630,7 @@ err_req_region:
1429 kfree(fimc->regs_res); 1630 kfree(fimc->regs_res);
1430err_info: 1631err_info:
1431 kfree(fimc); 1632 kfree(fimc);
1432 dev_err(&pdev->dev, "failed to install\n"); 1633
1433 return ret; 1634 return ret;
1434} 1635}
1435 1636
@@ -1438,91 +1639,151 @@ static int __devexit fimc_remove(struct platform_device *pdev)
1438 struct fimc_dev *fimc = 1639 struct fimc_dev *fimc =
1439 (struct fimc_dev *)platform_get_drvdata(pdev); 1640 (struct fimc_dev *)platform_get_drvdata(pdev);
1440 1641
1441 v4l2_info(&fimc->m2m.v4l2_dev, "Removing %s\n", pdev->name);
1442
1443 free_irq(fimc->irq, fimc); 1642 free_irq(fimc->irq, fimc);
1444
1445 fimc_hw_reset(fimc); 1643 fimc_hw_reset(fimc);
1446 1644
1447 fimc_unregister_m2m_device(fimc); 1645 fimc_unregister_m2m_device(fimc);
1646 fimc_unregister_capture_device(fimc);
1647
1448 fimc_clk_release(fimc); 1648 fimc_clk_release(fimc);
1449 iounmap(fimc->regs); 1649 iounmap(fimc->regs);
1450 release_resource(fimc->regs_res); 1650 release_resource(fimc->regs_res);
1451 kfree(fimc->regs_res); 1651 kfree(fimc->regs_res);
1452 kfree(fimc); 1652 kfree(fimc);
1653
1654 dev_info(&pdev->dev, "%s driver unloaded\n", pdev->name);
1453 return 0; 1655 return 0;
1454} 1656}
1455 1657
1456static struct samsung_fimc_variant fimc01_variant_s5p = { 1658/* Image pixel limits, similar across several FIMC HW revisions. */
1457 .has_inp_rot = 1, 1659static struct fimc_pix_limit s5p_pix_limit[3] = {
1458 .has_out_rot = 1, 1660 [0] = {
1661 .scaler_en_w = 3264,
1662 .scaler_dis_w = 8192,
1663 .in_rot_en_h = 1920,
1664 .in_rot_dis_w = 8192,
1665 .out_rot_en_w = 1920,
1666 .out_rot_dis_w = 4224,
1667 },
1668 [1] = {
1669 .scaler_en_w = 4224,
1670 .scaler_dis_w = 8192,
1671 .in_rot_en_h = 1920,
1672 .in_rot_dis_w = 8192,
1673 .out_rot_en_w = 1920,
1674 .out_rot_dis_w = 4224,
1675 },
1676 [2] = {
1677 .scaler_en_w = 1920,
1678 .scaler_dis_w = 8192,
1679 .in_rot_en_h = 1280,
1680 .in_rot_dis_w = 8192,
1681 .out_rot_en_w = 1280,
1682 .out_rot_dis_w = 1920,
1683 },
1684};
1685
1686static struct samsung_fimc_variant fimc0_variant_s5p = {
1687 .has_inp_rot = 1,
1688 .has_out_rot = 1,
1459 .min_inp_pixsize = 16, 1689 .min_inp_pixsize = 16,
1460 .min_out_pixsize = 16, 1690 .min_out_pixsize = 16,
1461 1691 .hor_offs_align = 8,
1462 .scaler_en_w = 3264, 1692 .out_buf_count = 4,
1463 .scaler_dis_w = 8192, 1693 .pix_limit = &s5p_pix_limit[0],
1464 .in_rot_en_h = 1920,
1465 .in_rot_dis_w = 8192,
1466 .out_rot_en_w = 1920,
1467 .out_rot_dis_w = 4224,
1468}; 1694};
1469 1695
1470static struct samsung_fimc_variant fimc2_variant_s5p = { 1696static struct samsung_fimc_variant fimc2_variant_s5p = {
1471 .min_inp_pixsize = 16, 1697 .min_inp_pixsize = 16,
1472 .min_out_pixsize = 16, 1698 .min_out_pixsize = 16,
1699 .hor_offs_align = 8,
1700 .out_buf_count = 4,
1701 .pix_limit = &s5p_pix_limit[1],
1702};
1473 1703
1474 .scaler_en_w = 4224, 1704static struct samsung_fimc_variant fimc0_variant_s5pv210 = {
1475 .scaler_dis_w = 8192, 1705 .pix_hoff = 1,
1476 .in_rot_en_h = 1920, 1706 .has_inp_rot = 1,
1477 .in_rot_dis_w = 8192, 1707 .has_out_rot = 1,
1478 .out_rot_en_w = 1920, 1708 .min_inp_pixsize = 16,
1479 .out_rot_dis_w = 4224, 1709 .min_out_pixsize = 16,
1710 .hor_offs_align = 8,
1711 .out_buf_count = 4,
1712 .pix_limit = &s5p_pix_limit[1],
1480}; 1713};
1481 1714
1482static struct samsung_fimc_variant fimc01_variant_s5pv210 = { 1715static struct samsung_fimc_variant fimc1_variant_s5pv210 = {
1483 .pix_hoff = 1, 1716 .pix_hoff = 1,
1484 .has_inp_rot = 1, 1717 .has_inp_rot = 1,
1485 .has_out_rot = 1, 1718 .has_out_rot = 1,
1486 .min_inp_pixsize = 16, 1719 .min_inp_pixsize = 16,
1487 .min_out_pixsize = 32, 1720 .min_out_pixsize = 16,
1488 1721 .hor_offs_align = 1,
1489 .scaler_en_w = 4224, 1722 .out_buf_count = 4,
1490 .scaler_dis_w = 8192, 1723 .pix_limit = &s5p_pix_limit[2],
1491 .in_rot_en_h = 1920,
1492 .in_rot_dis_w = 8192,
1493 .out_rot_en_w = 1920,
1494 .out_rot_dis_w = 4224,
1495}; 1724};
1496 1725
1497static struct samsung_fimc_variant fimc2_variant_s5pv210 = { 1726static struct samsung_fimc_variant fimc2_variant_s5pv210 = {
1498 .pix_hoff = 1, 1727 .pix_hoff = 1,
1499 .min_inp_pixsize = 16, 1728 .min_inp_pixsize = 16,
1500 .min_out_pixsize = 32, 1729 .min_out_pixsize = 16,
1501 1730 .hor_offs_align = 8,
1502 .scaler_en_w = 1920, 1731 .out_buf_count = 4,
1503 .scaler_dis_w = 8192, 1732 .pix_limit = &s5p_pix_limit[2],
1504 .in_rot_en_h = 1280, 1733};
1505 .in_rot_dis_w = 8192, 1734
1506 .out_rot_en_w = 1280, 1735static struct samsung_fimc_variant fimc0_variant_s5pv310 = {
1507 .out_rot_dis_w = 1920, 1736 .pix_hoff = 1,
1737 .has_inp_rot = 1,
1738 .has_out_rot = 1,
1739 .min_inp_pixsize = 16,
1740 .min_out_pixsize = 16,
1741 .hor_offs_align = 1,
1742 .out_buf_count = 32,
1743 .pix_limit = &s5p_pix_limit[1],
1744};
1745
1746static struct samsung_fimc_variant fimc2_variant_s5pv310 = {
1747 .pix_hoff = 1,
1748 .min_inp_pixsize = 16,
1749 .min_out_pixsize = 16,
1750 .hor_offs_align = 1,
1751 .out_buf_count = 32,
1752 .pix_limit = &s5p_pix_limit[2],
1508}; 1753};
1509 1754
1755/* S5PC100 */
1510static struct samsung_fimc_driverdata fimc_drvdata_s5p = { 1756static struct samsung_fimc_driverdata fimc_drvdata_s5p = {
1511 .variant = { 1757 .variant = {
1512 [0] = &fimc01_variant_s5p, 1758 [0] = &fimc0_variant_s5p,
1513 [1] = &fimc01_variant_s5p, 1759 [1] = &fimc0_variant_s5p,
1514 [2] = &fimc2_variant_s5p, 1760 [2] = &fimc2_variant_s5p,
1515 }, 1761 },
1516 .devs_cnt = 3 1762 .num_entities = 3,
1763 .lclk_frequency = 133000000UL,
1517}; 1764};
1518 1765
1766/* S5PV210, S5PC110 */
1519static struct samsung_fimc_driverdata fimc_drvdata_s5pv210 = { 1767static struct samsung_fimc_driverdata fimc_drvdata_s5pv210 = {
1520 .variant = { 1768 .variant = {
1521 [0] = &fimc01_variant_s5pv210, 1769 [0] = &fimc0_variant_s5pv210,
1522 [1] = &fimc01_variant_s5pv210, 1770 [1] = &fimc1_variant_s5pv210,
1523 [2] = &fimc2_variant_s5pv210, 1771 [2] = &fimc2_variant_s5pv210,
1524 }, 1772 },
1525 .devs_cnt = 3 1773 .num_entities = 3,
1774 .lclk_frequency = 166000000UL,
1775};
1776
1777/* S5PV310, S5PC210 */
1778static struct samsung_fimc_driverdata fimc_drvdata_s5pv310 = {
1779 .variant = {
1780 [0] = &fimc0_variant_s5pv310,
1781 [1] = &fimc0_variant_s5pv310,
1782 [2] = &fimc0_variant_s5pv310,
1783 [3] = &fimc2_variant_s5pv310,
1784 },
1785 .num_entities = 4,
1786 .lclk_frequency = 166000000UL,
1526}; 1787};
1527 1788
1528static struct platform_device_id fimc_driver_ids[] = { 1789static struct platform_device_id fimc_driver_ids[] = {
@@ -1532,6 +1793,9 @@ static struct platform_device_id fimc_driver_ids[] = {
1532 }, { 1793 }, {
1533 .name = "s5pv210-fimc", 1794 .name = "s5pv210-fimc",
1534 .driver_data = (unsigned long)&fimc_drvdata_s5pv210, 1795 .driver_data = (unsigned long)&fimc_drvdata_s5pv210,
1796 }, {
1797 .name = "s5pv310-fimc",
1798 .driver_data = (unsigned long)&fimc_drvdata_s5pv310,
1535 }, 1799 },
1536 {}, 1800 {},
1537}; 1801};
@@ -1547,20 +1811,12 @@ static struct platform_driver fimc_driver = {
1547 } 1811 }
1548}; 1812};
1549 1813
1550static char banner[] __initdata = KERN_INFO
1551 "S5PC Camera Interface V4L2 Driver, (c) 2010 Samsung Electronics\n";
1552
1553static int __init fimc_init(void) 1814static int __init fimc_init(void)
1554{ 1815{
1555 u32 ret; 1816 int ret = platform_driver_register(&fimc_driver);
1556 printk(banner); 1817 if (ret)
1557 1818 err("platform_driver_register failed: %d\n", ret);
1558 ret = platform_driver_register(&fimc_driver); 1819 return ret;
1559 if (ret) {
1560 printk(KERN_ERR "FIMC platform driver register failed\n");
1561 return -1;
1562 }
1563 return 0;
1564} 1820}
1565 1821
1566static void __exit fimc_exit(void) 1822static void __exit fimc_exit(void)
@@ -1571,6 +1827,6 @@ static void __exit fimc_exit(void)
1571module_init(fimc_init); 1827module_init(fimc_init);
1572module_exit(fimc_exit); 1828module_exit(fimc_exit);
1573 1829
1574MODULE_AUTHOR("Sylwester Nawrocki, s.nawrocki@samsung.com"); 1830MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
1575MODULE_DESCRIPTION("S3C/S5P FIMC (video postprocessor) driver"); 1831MODULE_DESCRIPTION("S5P FIMC camera host interface/video postprocessor driver");
1576MODULE_LICENSE("GPL"); 1832MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h
index 6b3e0cd73cdd..3e1078516560 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,47 +32,72 @@
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 4
34#define FIMC_MAX_OUT_BUFS 4 40#define FIMC_MAX_OUT_BUFS 4
35#define SCALER_MAX_HRATIO 64 41#define SCALER_MAX_HRATIO 64
36#define SCALER_MAX_VRATIO 64 42#define SCALER_MAX_VRATIO 64
43#define DMA_MIN_SIZE 8
37 44
38enum { 45/* FIMC device state flags */
46enum fimc_dev_flags {
47 /* for m2m node */
39 ST_IDLE, 48 ST_IDLE,
40 ST_OUTDMA_RUN, 49 ST_OUTDMA_RUN,
41 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,
42}; 56};
43 57
44#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)
45#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)
46 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
47enum fimc_datapath { 78enum fimc_datapath {
48 FIMC_ITU_CAM_A, 79 FIMC_CAMERA,
49 FIMC_ITU_CAM_B,
50 FIMC_MIPI_CAM,
51 FIMC_DMA, 80 FIMC_DMA,
52 FIMC_LCDFIFO, 81 FIMC_LCDFIFO,
53 FIMC_WRITEBACK 82 FIMC_WRITEBACK
54}; 83};
55 84
56enum fimc_color_fmt { 85enum fimc_color_fmt {
57 S5P_FIMC_RGB565, 86 S5P_FIMC_RGB565 = 0x10,
58 S5P_FIMC_RGB666, 87 S5P_FIMC_RGB666,
59 S5P_FIMC_RGB888, 88 S5P_FIMC_RGB888,
60 S5P_FIMC_YCBCR420, 89 S5P_FIMC_RGB30_LOCAL,
90 S5P_FIMC_YCBCR420 = 0x20,
61 S5P_FIMC_YCBCR422, 91 S5P_FIMC_YCBCR422,
62 S5P_FIMC_YCBYCR422, 92 S5P_FIMC_YCBYCR422,
63 S5P_FIMC_YCRYCB422, 93 S5P_FIMC_YCRYCB422,
64 S5P_FIMC_CBYCRY422, 94 S5P_FIMC_CBYCRY422,
65 S5P_FIMC_CRYCBY422, 95 S5P_FIMC_CRYCBY422,
66 S5P_FIMC_RGB30_LOCAL,
67 S5P_FIMC_YCBCR444_LOCAL, 96 S5P_FIMC_YCBCR444_LOCAL,
68 S5P_FIMC_MAX_COLOR = S5P_FIMC_YCBCR444_LOCAL,
69 S5P_FIMC_COLOR_MASK = 0x0F,
70}; 97};
71 98
99#define fimc_fmt_is_rgb(x) ((x) & 0x10)
100
72/* Y/Cb/Cr components order at DMA output for 1 plane YCbCr 4:2:2 formats. */ 101/* Y/Cb/Cr components order at DMA output for 1 plane YCbCr 4:2:2 formats. */
73#define S5P_FIMC_OUT_CRYCBY S5P_CIOCTRL_ORDER422_CRYCBY 102#define S5P_FIMC_OUT_CRYCBY S5P_CIOCTRL_ORDER422_CRYCBY
74#define S5P_FIMC_OUT_CBYCRY S5P_CIOCTRL_ORDER422_YCRYCB 103#define S5P_FIMC_OUT_CBYCRY S5P_CIOCTRL_ORDER422_YCRYCB
@@ -93,11 +122,13 @@ enum fimc_color_fmt {
93#define S5P_FIMC_EFFECT_SIKHOUETTE S5P_CIIMGEFF_FIN_SILHOUETTE 122#define S5P_FIMC_EFFECT_SIKHOUETTE S5P_CIIMGEFF_FIN_SILHOUETTE
94 123
95/* The hardware context state. */ 124/* The hardware context state. */
96#define FIMC_PARAMS (1 << 0) 125#define FIMC_PARAMS (1 << 0)
97#define FIMC_SRC_ADDR (1 << 1) 126#define FIMC_SRC_ADDR (1 << 1)
98#define FIMC_DST_ADDR (1 << 2) 127#define FIMC_DST_ADDR (1 << 2)
99#define FIMC_SRC_FMT (1 << 3) 128#define FIMC_SRC_FMT (1 << 3)
100#define FIMC_DST_FMT (1 << 4) 129#define FIMC_DST_FMT (1 << 4)
130#define FIMC_CTX_M2M (1 << 5)
131#define FIMC_CTX_CAP (1 << 6)
101 132
102/* Image conversion flags */ 133/* Image conversion flags */
103#define FIMC_IN_DMA_ACCESS_TILED (1 << 0) 134#define FIMC_IN_DMA_ACCESS_TILED (1 << 0)
@@ -106,7 +137,9 @@ enum fimc_color_fmt {
106#define FIMC_OUT_DMA_ACCESS_LINEAR (0 << 1) 137#define FIMC_OUT_DMA_ACCESS_LINEAR (0 << 1)
107#define FIMC_SCAN_MODE_PROGRESSIVE (0 << 2) 138#define FIMC_SCAN_MODE_PROGRESSIVE (0 << 2)
108#define FIMC_SCAN_MODE_INTERLACED (1 << 2) 139#define FIMC_SCAN_MODE_INTERLACED (1 << 2)
109/* YCbCr data dynamic range for RGB-YUV color conversion. Y/Cb/Cr: (0 ~ 255) */ 140/*
141 * YCbCr data dynamic range for RGB-YUV color conversion.
142 * Y/Cb/Cr: (0 ~ 255) */
110#define FIMC_COLOR_RANGE_WIDE (0 << 3) 143#define FIMC_COLOR_RANGE_WIDE (0 << 3)
111/* Y (16 ~ 235), Cb/Cr (16 ~ 240) */ 144/* Y (16 ~ 235), Cb/Cr (16 ~ 240) */
112#define FIMC_COLOR_RANGE_NARROW (1 << 3) 145#define FIMC_COLOR_RANGE_NARROW (1 << 3)
@@ -118,20 +151,25 @@ enum fimc_color_fmt {
118 151
119/** 152/**
120 * 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
121 * @name: format description 155 * @name: format description
122 * @fourcc: the fourcc code for this format 156 * @fourcc: the fourcc code for this format, 0 if not applicable
123 * @color: the corresponding fimc_color_fmt 157 * @color: the corresponding fimc_color_fmt
124 * @depth: number of bits per pixel 158 * @depth: driver's private 'number of bits per pixel'
125 * @buff_cnt: number of physically non-contiguous data planes 159 * @buff_cnt: number of physically non-contiguous data planes
126 * @planes_cnt: number of physically contiguous data planes 160 * @planes_cnt: number of physically contiguous data planes
127 */ 161 */
128struct fimc_fmt { 162struct fimc_fmt {
163 enum v4l2_mbus_pixelcode mbus_code;
129 char *name; 164 char *name;
130 u32 fourcc; 165 u32 fourcc;
131 u32 color; 166 u32 color;
132 u32 depth;
133 u16 buff_cnt; 167 u16 buff_cnt;
134 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)
135}; 173};
136 174
137/** 175/**
@@ -167,37 +205,37 @@ struct fimc_effect {
167/** 205/**
168 * struct fimc_scaler - the configuration data for FIMC inetrnal scaler 206 * struct fimc_scaler - the configuration data for FIMC inetrnal scaler
169 * 207 *
170 * @enabled: the flag set when the scaler is used 208 * @scaleup_h: flag indicating scaling up horizontally
209 * @scaleup_v: flag indicating scaling up vertically
210 * @copy_mode: flag indicating transparent DMA transfer (no scaling
211 * and color format conversion)
212 * @enabled: flag indicating if the scaler is used
171 * @hfactor: horizontal shift factor 213 * @hfactor: horizontal shift factor
172 * @vfactor: vertical shift factor 214 * @vfactor: vertical shift factor
173 * @pre_hratio: horizontal ratio of the prescaler 215 * @pre_hratio: horizontal ratio of the prescaler
174 * @pre_vratio: vertical ratio of the prescaler 216 * @pre_vratio: vertical ratio of the prescaler
175 * @pre_dst_width: the prescaler's destination width 217 * @pre_dst_width: the prescaler's destination width
176 * @pre_dst_height: the prescaler's destination height 218 * @pre_dst_height: the prescaler's destination height
177 * @scaleup_h: flag indicating scaling up horizontally
178 * @scaleup_v: flag indicating scaling up vertically
179 * @main_hratio: the main scaler's horizontal ratio 219 * @main_hratio: the main scaler's horizontal ratio
180 * @main_vratio: the main scaler's vertical ratio 220 * @main_vratio: the main scaler's vertical ratio
181 * @real_width: source width - offset 221 * @real_width: source pixel (width - offset)
182 * @real_height: source height - offset 222 * @real_height: source pixel (height - offset)
183 * @copy_mode: flag set if one-to-one mode is used, i.e. no scaling
184 * and color format conversion
185 */ 223 */
186struct fimc_scaler { 224struct fimc_scaler {
187 u32 enabled; 225 unsigned int scaleup_h:1;
226 unsigned int scaleup_v:1;
227 unsigned int copy_mode:1;
228 unsigned int enabled:1;
188 u32 hfactor; 229 u32 hfactor;
189 u32 vfactor; 230 u32 vfactor;
190 u32 pre_hratio; 231 u32 pre_hratio;
191 u32 pre_vratio; 232 u32 pre_vratio;
192 u32 pre_dst_width; 233 u32 pre_dst_width;
193 u32 pre_dst_height; 234 u32 pre_dst_height;
194 u32 scaleup_h;
195 u32 scaleup_v;
196 u32 main_hratio; 235 u32 main_hratio;
197 u32 main_vratio; 236 u32 main_vratio;
198 u32 real_width; 237 u32 real_width;
199 u32 real_height; 238 u32 real_height;
200 u32 copy_mode;
201}; 239};
202 240
203/** 241/**
@@ -215,15 +253,18 @@ struct fimc_addr {
215 253
216/** 254/**
217 * struct fimc_vid_buffer - the driver's video buffer 255 * struct fimc_vid_buffer - the driver's video buffer
218 * @vb: v4l videobuf buffer 256 * @vb: v4l videobuf buffer
257 * @paddr: precalculated physical address set
258 * @index: buffer index for the output DMA engine
219 */ 259 */
220struct fimc_vid_buffer { 260struct fimc_vid_buffer {
221 struct videobuf_buffer vb; 261 struct videobuf_buffer vb;
262 struct fimc_addr paddr;
263 int index;
222}; 264};
223 265
224/** 266/**
225 * struct fimc_frame - input/output frame format properties 267 * struct fimc_frame - source/target frame properties
226 *
227 * @f_width: image full width (virtual screen size) 268 * @f_width: image full width (virtual screen size)
228 * @f_height: image full height (virtual screen size) 269 * @f_height: image full height (virtual screen size)
229 * @o_width: original image width as set by S_FMT 270 * @o_width: original image width as set by S_FMT
@@ -270,67 +311,119 @@ struct fimc_m2m_device {
270}; 311};
271 312
272/** 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/**
348 * struct fimc_pix_limit - image pixel size limits in various IP configurations
349 *
350 * @scaler_en_w: max input pixel width when the scaler is enabled
351 * @scaler_dis_w: max input pixel width when the scaler is disabled
352 * @in_rot_en_h: max input width with the input rotator is on
353 * @in_rot_dis_w: max input width with the input rotator is off
354 * @out_rot_en_w: max output width with the output rotator on
355 * @out_rot_dis_w: max output width with the output rotator off
356 */
357struct fimc_pix_limit {
358 u16 scaler_en_w;
359 u16 scaler_dis_w;
360 u16 in_rot_en_h;
361 u16 in_rot_dis_w;
362 u16 out_rot_en_w;
363 u16 out_rot_dis_w;
364};
365
366/**
273 * struct samsung_fimc_variant - camera interface variant information 367 * struct samsung_fimc_variant - camera interface variant information
274 * 368 *
275 * @pix_hoff: indicate whether horizontal offset is in pixels or in bytes 369 * @pix_hoff: indicate whether horizontal offset is in pixels or in bytes
276 * @has_inp_rot: set if has input rotator 370 * @has_inp_rot: set if has input rotator
277 * @has_out_rot: set if has output rotator 371 * @has_out_rot: set if has output rotator
372 * @pix_limit: pixel size constraints for the scaler
278 * @min_inp_pixsize: minimum input pixel size 373 * @min_inp_pixsize: minimum input pixel size
279 * @min_out_pixsize: minimum output pixel size 374 * @min_out_pixsize: minimum output pixel size
280 * @scaler_en_w: maximum input pixel width when the scaler is enabled 375 * @hor_offs_align: horizontal pixel offset aligment
281 * @scaler_dis_w: maximum input pixel width when the scaler is disabled 376 * @out_buf_count: the number of buffers in output DMA sequence
282 * @in_rot_en_h: maximum input width when the input rotator is used
283 * @in_rot_dis_w: maximum input width when the input rotator is used
284 * @out_rot_en_w: maximum output width for the output rotator enabled
285 * @out_rot_dis_w: maximum output width for the output rotator enabled
286 */ 377 */
287struct samsung_fimc_variant { 378struct samsung_fimc_variant {
288 unsigned int pix_hoff:1; 379 unsigned int pix_hoff:1;
289 unsigned int has_inp_rot:1; 380 unsigned int has_inp_rot:1;
290 unsigned int has_out_rot:1; 381 unsigned int has_out_rot:1;
291 382 struct fimc_pix_limit *pix_limit;
292 u16 min_inp_pixsize; 383 u16 min_inp_pixsize;
293 u16 min_out_pixsize; 384 u16 min_out_pixsize;
294 u16 scaler_en_w; 385 u16 hor_offs_align;
295 u16 scaler_dis_w; 386 u16 out_buf_count;
296 u16 in_rot_en_h;
297 u16 in_rot_dis_w;
298 u16 out_rot_en_w;
299 u16 out_rot_dis_w;
300}; 387};
301 388
302/** 389/**
303 * struct samsung_fimc_driverdata - per-device type driver data for init time. 390 * struct samsung_fimc_driverdata - per device type driver data for init time.
304 * 391 *
305 * @variant: the variant information for this driver. 392 * @variant: the variant information for this driver.
306 * @dev_cnt: number of fimc sub-devices available in SoC 393 * @dev_cnt: number of fimc sub-devices available in SoC
394 * @lclk_frequency: fimc bus clock frequency
307 */ 395 */
308struct samsung_fimc_driverdata { 396struct samsung_fimc_driverdata {
309 struct samsung_fimc_variant *variant[FIMC_MAX_DEVS]; 397 struct samsung_fimc_variant *variant[FIMC_MAX_DEVS];
310 int devs_cnt; 398 unsigned long lclk_frequency;
399 int num_entities;
311}; 400};
312 401
313struct fimc_ctx; 402struct fimc_ctx;
314 403
315/** 404/**
316 * struct fimc_subdev - abstraction for a FIMC entity 405 * struct fimc_dev - abstraction for FIMC entity
317 * 406 *
318 * @slock: the spinlock protecting this data structure 407 * @slock: the spinlock protecting this data structure
319 * @lock: the mutex protecting this data structure 408 * @lock: the mutex protecting this data structure
320 * @pdev: pointer to the FIMC platform device 409 * @pdev: pointer to the FIMC platform device
410 * @pdata: pointer to the device platform data
321 * @id: FIMC device index (0..2) 411 * @id: FIMC device index (0..2)
322 * @clock[]: the clocks required for FIMC operation 412 * @clock[]: the clocks required for FIMC operation
323 * @regs: the mapped hardware registers 413 * @regs: the mapped hardware registers
324 * @regs_res: the resource claimed for IO registers 414 * @regs_res: the resource claimed for IO registers
325 * @irq: interrupt number of the FIMC subdevice 415 * @irq: interrupt number of the FIMC subdevice
326 * @irqlock: spinlock protecting videbuffer queue 416 * @irqlock: spinlock protecting videobuffer queue
417 * @irq_queue:
327 * @m2m: memory-to-memory V4L2 device information 418 * @m2m: memory-to-memory V4L2 device information
328 * @state: the FIMC device state flags 419 * @vid_cap: camera capture device information
420 * @state: flags used to synchronize m2m and capture mode operation
329 */ 421 */
330struct fimc_dev { 422struct fimc_dev {
331 spinlock_t slock; 423 spinlock_t slock;
332 struct mutex lock; 424 struct mutex lock;
333 struct platform_device *pdev; 425 struct platform_device *pdev;
426 struct s3c_platform_fimc *pdata;
334 struct samsung_fimc_variant *variant; 427 struct samsung_fimc_variant *variant;
335 int id; 428 int id;
336 struct clk *clock[NUM_FIMC_CLOCKS]; 429 struct clk *clock[NUM_FIMC_CLOCKS];
@@ -338,8 +431,9 @@ struct fimc_dev {
338 struct resource *regs_res; 431 struct resource *regs_res;
339 int irq; 432 int irq;
340 spinlock_t irqlock; 433 spinlock_t irqlock;
341 struct workqueue_struct *work_queue; 434 wait_queue_head_t irq_queue;
342 struct fimc_m2m_device m2m; 435 struct fimc_m2m_device m2m;
436 struct fimc_vid_cap vid_cap;
343 unsigned long state; 437 unsigned long state;
344}; 438};
345 439
@@ -359,7 +453,7 @@ struct fimc_dev {
359 * @effect: image effect 453 * @effect: image effect
360 * @rotation: image clockwise rotation in degrees 454 * @rotation: image clockwise rotation in degrees
361 * @flip: image flip mode 455 * @flip: image flip mode
362 * @flags: an additional flags for image conversion 456 * @flags: additional flags for image conversion
363 * @state: flags to keep track of user configuration 457 * @state: flags to keep track of user configuration
364 * @fimc_dev: the FIMC device this context applies to 458 * @fimc_dev: the FIMC device this context applies to
365 * @m2m_ctx: memory-to-memory device context 459 * @m2m_ctx: memory-to-memory device context
@@ -384,6 +478,7 @@ struct fimc_ctx {
384 struct v4l2_m2m_ctx *m2m_ctx; 478 struct v4l2_m2m_ctx *m2m_ctx;
385}; 479};
386 480
481extern struct videobuf_queue_ops fimc_qops;
387 482
388static inline int tiled_fmt(struct fimc_fmt *fmt) 483static inline int tiled_fmt(struct fimc_fmt *fmt)
389{ 484{
@@ -397,18 +492,24 @@ static inline void fimc_hw_clear_irq(struct fimc_dev *dev)
397 writel(cfg, dev->regs + S5P_CIGCTRL); 492 writel(cfg, dev->regs + S5P_CIGCTRL);
398} 493}
399 494
400static inline void fimc_hw_start_scaler(struct fimc_dev *dev) 495static inline void fimc_hw_enable_scaler(struct fimc_dev *dev, bool on)
401{ 496{
402 u32 cfg = readl(dev->regs + S5P_CISCCTRL); 497 u32 cfg = readl(dev->regs + S5P_CISCCTRL);
403 cfg |= S5P_CISCCTRL_SCALERSTART; 498 if (on)
499 cfg |= S5P_CISCCTRL_SCALERSTART;
500 else
501 cfg &= ~S5P_CISCCTRL_SCALERSTART;
404 writel(cfg, dev->regs + S5P_CISCCTRL); 502 writel(cfg, dev->regs + S5P_CISCCTRL);
405} 503}
406 504
407static inline void fimc_hw_stop_scaler(struct fimc_dev *dev) 505static inline void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on)
408{ 506{
409 u32 cfg = readl(dev->regs + S5P_CISCCTRL); 507 u32 cfg = readl(dev->regs + S5P_MSCTRL);
410 cfg &= ~S5P_CISCCTRL_SCALERSTART; 508 if (on)
411 writel(cfg, dev->regs + S5P_CISCCTRL); 509 cfg |= S5P_MSCTRL_ENVID;
510 else
511 cfg &= ~S5P_MSCTRL_ENVID;
512 writel(cfg, dev->regs + S5P_MSCTRL);
412} 513}
413 514
414static inline void fimc_hw_dis_capture(struct fimc_dev *dev) 515static inline void fimc_hw_dis_capture(struct fimc_dev *dev)
@@ -418,27 +519,30 @@ static inline void fimc_hw_dis_capture(struct fimc_dev *dev)
418 writel(cfg, dev->regs + S5P_CIIMGCPT); 519 writel(cfg, dev->regs + S5P_CIIMGCPT);
419} 520}
420 521
421static inline void fimc_hw_start_in_dma(struct fimc_dev *dev) 522/**
422{ 523 * fimc_hw_set_dma_seq - configure output DMA buffer sequence
423 u32 cfg = readl(dev->regs + S5P_MSCTRL); 524 * @mask: each bit corresponds to one of 32 output buffer registers set
424 cfg |= S5P_MSCTRL_ENVID; 525 * 1 to include buffer in the sequence, 0 to disable
425 writel(cfg, dev->regs + S5P_MSCTRL); 526 *
426} 527 * This function mask output DMA ring buffers, i.e. it allows to configure
427 528 * which of the output buffer address registers will be used by the DMA
428static inline void fimc_hw_stop_in_dma(struct fimc_dev *dev) 529 * engine.
530 */
531static inline void fimc_hw_set_dma_seq(struct fimc_dev *dev, u32 mask)
429{ 532{
430 u32 cfg = readl(dev->regs + S5P_MSCTRL); 533 writel(mask, dev->regs + S5P_CIFCNTSEQ);
431 cfg &= ~S5P_MSCTRL_ENVID;
432 writel(cfg, dev->regs + S5P_MSCTRL);
433} 534}
434 535
435static inline struct fimc_frame *ctx_m2m_get_frame(struct fimc_ctx *ctx, 536static inline struct fimc_frame *ctx_get_frame(struct fimc_ctx *ctx,
436 enum v4l2_buf_type type) 537 enum v4l2_buf_type type)
437{ 538{
438 struct fimc_frame *frame; 539 struct fimc_frame *frame;
439 540
440 if (V4L2_BUF_TYPE_VIDEO_OUTPUT == type) { 541 if (V4L2_BUF_TYPE_VIDEO_OUTPUT == type) {
441 frame = &ctx->s_frame; 542 if (ctx->state & FIMC_CTX_M2M)
543 frame = &ctx->s_frame;
544 else
545 return ERR_PTR(-EINVAL);
442 } else if (V4L2_BUF_TYPE_VIDEO_CAPTURE == type) { 546 } else if (V4L2_BUF_TYPE_VIDEO_CAPTURE == type) {
443 frame = &ctx->d_frame; 547 frame = &ctx->d_frame;
444 } else { 548 } else {
@@ -450,22 +554,137 @@ static inline struct fimc_frame *ctx_m2m_get_frame(struct fimc_ctx *ctx,
450 return frame; 554 return frame;
451} 555}
452 556
557static inline u32 fimc_hw_get_frame_index(struct fimc_dev *dev)
558{
559 u32 reg = readl(dev->regs + S5P_CISTATUS);
560 return (reg & S5P_CISTATUS_FRAMECNT_MASK) >>
561 S5P_CISTATUS_FRAMECNT_SHIFT;
562}
563
453/* -----------------------------------------------------*/ 564/* -----------------------------------------------------*/
454/* fimc-reg.c */ 565/* fimc-reg.c */
455void fimc_hw_reset(struct fimc_dev *dev); 566void fimc_hw_reset(struct fimc_dev *fimc);
456void fimc_hw_set_rotation(struct fimc_ctx *ctx); 567void fimc_hw_set_rotation(struct fimc_ctx *ctx);
457void fimc_hw_set_target_format(struct fimc_ctx *ctx); 568void fimc_hw_set_target_format(struct fimc_ctx *ctx);
458void fimc_hw_set_out_dma(struct fimc_ctx *ctx); 569void fimc_hw_set_out_dma(struct fimc_ctx *ctx);
459void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable); 570void fimc_hw_en_lastirq(struct fimc_dev *fimc, int enable);
460void fimc_hw_en_irq(struct fimc_dev *dev, int enable); 571void fimc_hw_en_irq(struct fimc_dev *fimc, int enable);
461void fimc_hw_set_prescaler(struct fimc_ctx *ctx);
462void fimc_hw_set_scaler(struct fimc_ctx *ctx); 572void fimc_hw_set_scaler(struct fimc_ctx *ctx);
463void fimc_hw_en_capture(struct fimc_ctx *ctx); 573void fimc_hw_en_capture(struct fimc_ctx *ctx);
464void fimc_hw_set_effect(struct fimc_ctx *ctx); 574void fimc_hw_set_effect(struct fimc_ctx *ctx);
465void fimc_hw_set_in_dma(struct fimc_ctx *ctx); 575void fimc_hw_set_in_dma(struct fimc_ctx *ctx);
466void fimc_hw_set_input_path(struct fimc_ctx *ctx); 576void fimc_hw_set_input_path(struct fimc_ctx *ctx);
467void fimc_hw_set_output_path(struct fimc_ctx *ctx); 577void fimc_hw_set_output_path(struct fimc_ctx *ctx);
468void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr); 578void fimc_hw_set_input_addr(struct fimc_dev *fimc, struct fimc_addr *paddr);
469void fimc_hw_set_output_addr(struct fimc_dev *dev, struct fimc_addr *paddr); 579void fimc_hw_set_output_addr(struct fimc_dev *fimc, struct fimc_addr *paddr,
580 int index);
581int fimc_hw_set_camera_source(struct fimc_dev *fimc,
582 struct s3c_fimc_isp_info *cam);
583int fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f);
584int fimc_hw_set_camera_polarity(struct fimc_dev *fimc,
585 struct s3c_fimc_isp_info *cam);
586int fimc_hw_set_camera_type(struct fimc_dev *fimc,
587 struct s3c_fimc_isp_info *cam);
588
589/* -----------------------------------------------------*/
590/* fimc-core.c */
591int fimc_vidioc_enum_fmt(struct file *file, void *priv,
592 struct v4l2_fmtdesc *f);
593int fimc_vidioc_g_fmt(struct file *file, void *priv,
594 struct v4l2_format *f);
595int fimc_vidioc_try_fmt(struct file *file, void *priv,
596 struct v4l2_format *f);
597int fimc_vidioc_g_crop(struct file *file, void *fh,
598 struct v4l2_crop *cr);
599int fimc_vidioc_cropcap(struct file *file, void *fh,
600 struct v4l2_cropcap *cr);
601int fimc_vidioc_queryctrl(struct file *file, void *priv,
602 struct v4l2_queryctrl *qc);
603int fimc_vidioc_g_ctrl(struct file *file, void *priv,
604 struct v4l2_control *ctrl);
605
606int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr);
607int check_ctrl_val(struct fimc_ctx *ctx, struct v4l2_control *ctrl);
608int fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_control *ctrl);
609
610struct fimc_fmt *find_format(struct v4l2_format *f, unsigned int mask);
611struct fimc_fmt *find_mbus_format(struct v4l2_mbus_framefmt *f,
612 unsigned int mask);
613
614int fimc_check_scaler_ratio(struct v4l2_rect *r, struct fimc_frame *f);
615int fimc_set_scaler_info(struct fimc_ctx *ctx);
616int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags);
617int fimc_prepare_addr(struct fimc_ctx *ctx, struct fimc_vid_buffer *buf,
618 struct fimc_frame *frame, struct fimc_addr *paddr);
619
620/* -----------------------------------------------------*/
621/* fimc-capture.c */
622int fimc_register_capture_device(struct fimc_dev *fimc);
623void fimc_unregister_capture_device(struct fimc_dev *fimc);
624int fimc_sensor_sd_init(struct fimc_dev *fimc, int index);
625int fimc_vid_cap_buf_queue(struct fimc_dev *fimc,
626 struct fimc_vid_buffer *fimc_vb);
627
628/* Locking: the caller holds fimc->slock */
629static inline void fimc_activate_capture(struct fimc_ctx *ctx)
630{
631 fimc_hw_enable_scaler(ctx->fimc_dev, ctx->scaler.enabled);
632 fimc_hw_en_capture(ctx);
633}
634
635static inline void fimc_deactivate_capture(struct fimc_dev *fimc)
636{
637 fimc_hw_en_lastirq(fimc, true);
638 fimc_hw_dis_capture(fimc);
639 fimc_hw_enable_scaler(fimc, false);
640 fimc_hw_en_lastirq(fimc, false);
641}
642
643/*
644 * Add video buffer to the active buffers queue.
645 * The caller holds irqlock spinlock.
646 */
647static inline void active_queue_add(struct fimc_vid_cap *vid_cap,
648 struct fimc_vid_buffer *buf)
649{
650 buf->vb.state = VIDEOBUF_ACTIVE;
651 list_add_tail(&buf->vb.queue, &vid_cap->active_buf_q);
652 vid_cap->active_buf_cnt++;
653}
654
655/*
656 * Pop a video buffer from the capture active buffers queue
657 * Locking: Need to be called with dev->slock held.
658 */
659static inline struct fimc_vid_buffer *
660active_queue_pop(struct fimc_vid_cap *vid_cap)
661{
662 struct fimc_vid_buffer *buf;
663 buf = list_entry(vid_cap->active_buf_q.next,
664 struct fimc_vid_buffer, vb.queue);
665 list_del(&buf->vb.queue);
666 vid_cap->active_buf_cnt--;
667 return buf;
668}
669
670/* Add video buffer to the capture pending buffers queue */
671static inline void fimc_pending_queue_add(struct fimc_vid_cap *vid_cap,
672 struct fimc_vid_buffer *buf)
673{
674 buf->vb.state = VIDEOBUF_QUEUED;
675 list_add_tail(&buf->vb.queue, &vid_cap->pending_buf_q);
676}
677
678/* Add video buffer to the capture pending buffers queue */
679static inline struct fimc_vid_buffer *
680pending_queue_pop(struct fimc_vid_cap *vid_cap)
681{
682 struct fimc_vid_buffer *buf;
683 buf = list_entry(vid_cap->pending_buf_q.next,
684 struct fimc_vid_buffer, vb.queue);
685 list_del(&buf->vb.queue);
686 return buf;
687}
688
470 689
471#endif /* FIMC_CORE_H_ */ 690#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 5570f1ce0c9c..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
@@ -29,49 +30,11 @@ void fimc_hw_reset(struct fimc_dev *dev)
29 cfg = readl(dev->regs + S5P_CIGCTRL); 30 cfg = readl(dev->regs + S5P_CIGCTRL);
30 cfg |= (S5P_CIGCTRL_SWRST | S5P_CIGCTRL_IRQ_LEVEL); 31 cfg |= (S5P_CIGCTRL_SWRST | S5P_CIGCTRL_IRQ_LEVEL);
31 writel(cfg, dev->regs + S5P_CIGCTRL); 32 writel(cfg, dev->regs + S5P_CIGCTRL);
32 msleep(1); 33 udelay(1000);
33 34
34 cfg = readl(dev->regs + S5P_CIGCTRL); 35 cfg = readl(dev->regs + S5P_CIGCTRL);
35 cfg &= ~S5P_CIGCTRL_SWRST; 36 cfg &= ~S5P_CIGCTRL_SWRST;
36 writel(cfg, dev->regs + S5P_CIGCTRL); 37 writel(cfg, dev->regs + S5P_CIGCTRL);
37
38}
39
40void fimc_hw_set_rotation(struct fimc_ctx *ctx)
41{
42 u32 cfg, flip;
43 struct fimc_dev *dev = ctx->fimc_dev;
44
45 cfg = readl(dev->regs + S5P_CITRGFMT);
46 cfg &= ~(S5P_CITRGFMT_INROT90 | S5P_CITRGFMT_OUTROT90);
47
48 flip = readl(dev->regs + S5P_MSCTRL);
49 flip &= ~S5P_MSCTRL_FLIP_MASK;
50
51 /*
52 * The input and output rotator cannot work simultaneously.
53 * Use the output rotator in output DMA mode or the input rotator
54 * in direct fifo output mode.
55 */
56 if (ctx->rotation == 90 || ctx->rotation == 270) {
57 if (ctx->out_path == FIMC_LCDFIFO) {
58 cfg |= S5P_CITRGFMT_INROT90;
59 if (ctx->rotation == 270)
60 flip |= S5P_MSCTRL_FLIP_180;
61 } else {
62 cfg |= S5P_CITRGFMT_OUTROT90;
63 if (ctx->rotation == 270)
64 cfg |= S5P_CITRGFMT_FLIP_180;
65 }
66 } else if (ctx->rotation == 180) {
67 if (ctx->out_path == FIMC_LCDFIFO)
68 flip |= S5P_MSCTRL_FLIP_180;
69 else
70 cfg |= S5P_CITRGFMT_FLIP_180;
71 }
72 if (ctx->rotation == 180 || ctx->rotation == 270)
73 writel(flip, dev->regs + S5P_MSCTRL);
74 writel(cfg, dev->regs + S5P_CITRGFMT);
75} 38}
76 39
77static u32 fimc_hw_get_in_flip(u32 ctx_flip) 40static u32 fimc_hw_get_in_flip(u32 ctx_flip)
@@ -114,6 +77,46 @@ static u32 fimc_hw_get_target_flip(u32 ctx_flip)
114 return flip; 77 return flip;
115} 78}
116 79
80void fimc_hw_set_rotation(struct fimc_ctx *ctx)
81{
82 u32 cfg, flip;
83 struct fimc_dev *dev = ctx->fimc_dev;
84
85 cfg = readl(dev->regs + S5P_CITRGFMT);
86 cfg &= ~(S5P_CITRGFMT_INROT90 | S5P_CITRGFMT_OUTROT90 |
87 S5P_CITRGFMT_FLIP_180);
88
89 flip = readl(dev->regs + S5P_MSCTRL);
90 flip &= ~S5P_MSCTRL_FLIP_MASK;
91
92 /*
93 * The input and output rotator cannot work simultaneously.
94 * Use the output rotator in output DMA mode or the input rotator
95 * in direct fifo output mode.
96 */
97 if (ctx->rotation == 90 || ctx->rotation == 270) {
98 if (ctx->out_path == FIMC_LCDFIFO) {
99 cfg |= S5P_CITRGFMT_INROT90;
100 if (ctx->rotation == 270)
101 flip |= S5P_MSCTRL_FLIP_180;
102 } else {
103 cfg |= S5P_CITRGFMT_OUTROT90;
104 if (ctx->rotation == 270)
105 cfg |= S5P_CITRGFMT_FLIP_180;
106 }
107 } else if (ctx->rotation == 180) {
108 if (ctx->out_path == FIMC_LCDFIFO)
109 flip |= S5P_MSCTRL_FLIP_180;
110 else
111 cfg |= S5P_CITRGFMT_FLIP_180;
112 }
113 if (ctx->rotation == 180 || ctx->rotation == 270)
114 writel(flip, dev->regs + S5P_MSCTRL);
115
116 cfg |= fimc_hw_get_target_flip(ctx->flip);
117 writel(cfg, dev->regs + S5P_CITRGFMT);
118}
119
117void fimc_hw_set_target_format(struct fimc_ctx *ctx) 120void fimc_hw_set_target_format(struct fimc_ctx *ctx)
118{ 121{
119 u32 cfg; 122 u32 cfg;
@@ -149,13 +152,15 @@ void fimc_hw_set_target_format(struct fimc_ctx *ctx)
149 break; 152 break;
150 } 153 }
151 154
152 cfg |= S5P_CITRGFMT_HSIZE(frame->width); 155 if (ctx->rotation == 90 || ctx->rotation == 270) {
153 cfg |= S5P_CITRGFMT_VSIZE(frame->height); 156 cfg |= S5P_CITRGFMT_HSIZE(frame->height);
157 cfg |= S5P_CITRGFMT_VSIZE(frame->width);
158 } else {
154 159
155 if (ctx->rotation == 0) { 160 cfg |= S5P_CITRGFMT_HSIZE(frame->width);
156 cfg &= ~S5P_CITRGFMT_FLIP_MASK; 161 cfg |= S5P_CITRGFMT_VSIZE(frame->height);
157 cfg |= fimc_hw_get_target_flip(ctx->flip);
158 } 162 }
163
159 writel(cfg, dev->regs + S5P_CITRGFMT); 164 writel(cfg, dev->regs + S5P_CITRGFMT);
160 165
161 cfg = readl(dev->regs + S5P_CITAREA) & ~S5P_CITAREA_MASK; 166 cfg = readl(dev->regs + S5P_CITAREA) & ~S5P_CITAREA_MASK;
@@ -167,16 +172,20 @@ static void fimc_hw_set_out_dma_size(struct fimc_ctx *ctx)
167{ 172{
168 struct fimc_dev *dev = ctx->fimc_dev; 173 struct fimc_dev *dev = ctx->fimc_dev;
169 struct fimc_frame *frame = &ctx->d_frame; 174 struct fimc_frame *frame = &ctx->d_frame;
170 u32 cfg = 0; 175 u32 cfg;
171 176
172 if (ctx->rotation == 90 || ctx->rotation == 270) { 177 cfg = S5P_ORIG_SIZE_HOR(frame->f_width);
173 cfg |= S5P_ORIG_SIZE_HOR(frame->f_height); 178 cfg |= S5P_ORIG_SIZE_VER(frame->f_height);
174 cfg |= S5P_ORIG_SIZE_VER(frame->f_width);
175 } else {
176 cfg |= S5P_ORIG_SIZE_HOR(frame->f_width);
177 cfg |= S5P_ORIG_SIZE_VER(frame->f_height);
178 }
179 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
180} 189}
181 190
182void fimc_hw_set_out_dma(struct fimc_ctx *ctx) 191void fimc_hw_set_out_dma(struct fimc_ctx *ctx)
@@ -232,36 +241,28 @@ static void fimc_hw_en_autoload(struct fimc_dev *dev, int enable)
232 241
233void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable) 242void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable)
234{ 243{
235 unsigned long flags; 244 u32 cfg = readl(dev->regs + S5P_CIOCTRL);
236 u32 cfg;
237
238 spin_lock_irqsave(&dev->slock, flags);
239
240 cfg = readl(dev->regs + S5P_CIOCTRL);
241 if (enable) 245 if (enable)
242 cfg |= S5P_CIOCTRL_LASTIRQ_ENABLE; 246 cfg |= S5P_CIOCTRL_LASTIRQ_ENABLE;
243 else 247 else
244 cfg &= ~S5P_CIOCTRL_LASTIRQ_ENABLE; 248 cfg &= ~S5P_CIOCTRL_LASTIRQ_ENABLE;
245 writel(cfg, dev->regs + S5P_CIOCTRL); 249 writel(cfg, dev->regs + S5P_CIOCTRL);
246
247 spin_unlock_irqrestore(&dev->slock, flags);
248} 250}
249 251
250void fimc_hw_set_prescaler(struct fimc_ctx *ctx) 252static void fimc_hw_set_prescaler(struct fimc_ctx *ctx)
251{ 253{
252 struct fimc_dev *dev = ctx->fimc_dev; 254 struct fimc_dev *dev = ctx->fimc_dev;
253 struct fimc_scaler *sc = &ctx->scaler; 255 struct fimc_scaler *sc = &ctx->scaler;
254 u32 cfg = 0, shfactor; 256 u32 cfg, shfactor;
255 257
256 shfactor = 10 - (sc->hfactor + sc->vfactor); 258 shfactor = 10 - (sc->hfactor + sc->vfactor);
257 259
258 cfg |= S5P_CISCPRERATIO_SHFACTOR(shfactor); 260 cfg = S5P_CISCPRERATIO_SHFACTOR(shfactor);
259 cfg |= S5P_CISCPRERATIO_HOR(sc->pre_hratio); 261 cfg |= S5P_CISCPRERATIO_HOR(sc->pre_hratio);
260 cfg |= S5P_CISCPRERATIO_VER(sc->pre_vratio); 262 cfg |= S5P_CISCPRERATIO_VER(sc->pre_vratio);
261 writel(cfg, dev->regs + S5P_CISCPRERATIO); 263 writel(cfg, dev->regs + S5P_CISCPRERATIO);
262 264
263 cfg = 0; 265 cfg = S5P_CISCPREDST_WIDTH(sc->pre_dst_width);
264 cfg |= S5P_CISCPREDST_WIDTH(sc->pre_dst_width);
265 cfg |= S5P_CISCPREDST_HEIGHT(sc->pre_dst_height); 266 cfg |= S5P_CISCPREDST_HEIGHT(sc->pre_dst_height);
266 writel(cfg, dev->regs + S5P_CISCPREDST); 267 writel(cfg, dev->regs + S5P_CISCPREDST);
267} 268}
@@ -274,6 +275,8 @@ void fimc_hw_set_scaler(struct fimc_ctx *ctx)
274 struct fimc_frame *dst_frame = &ctx->d_frame; 275 struct fimc_frame *dst_frame = &ctx->d_frame;
275 u32 cfg = 0; 276 u32 cfg = 0;
276 277
278 fimc_hw_set_prescaler(ctx);
279
277 if (!(ctx->flags & FIMC_COLOR_RANGE_NARROW)) 280 if (!(ctx->flags & FIMC_COLOR_RANGE_NARROW))
278 cfg |= (S5P_CISCCTRL_CSCR2Y_WIDE | S5P_CISCCTRL_CSCY2R_WIDE); 281 cfg |= (S5P_CISCCTRL_CSCR2Y_WIDE | S5P_CISCCTRL_CSCY2R_WIDE);
279 282
@@ -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;
@@ -364,7 +371,7 @@ static void fimc_hw_set_in_dma_size(struct fimc_ctx *ctx)
364 u32 cfg_r = 0; 371 u32 cfg_r = 0;
365 372
366 if (FIMC_LCDFIFO == ctx->out_path) 373 if (FIMC_LCDFIFO == ctx->out_path)
367 cfg_r |= S5P_CIREAL_ISIZE_AUTOLOAD_EN; 374 cfg_r |= S5P_CIREAL_ISIZE_AUTOLOAD_EN;
368 375
369 cfg_o |= S5P_ORIG_SIZE_HOR(frame->f_width); 376 cfg_o |= S5P_ORIG_SIZE_HOR(frame->f_width);
370 cfg_o |= S5P_ORIG_SIZE_VER(frame->f_height); 377 cfg_o |= S5P_ORIG_SIZE_VER(frame->f_height);
@@ -380,27 +387,25 @@ void fimc_hw_set_in_dma(struct fimc_ctx *ctx)
380 struct fimc_dev *dev = ctx->fimc_dev; 387 struct fimc_dev *dev = ctx->fimc_dev;
381 struct fimc_frame *frame = &ctx->s_frame; 388 struct fimc_frame *frame = &ctx->s_frame;
382 struct fimc_dma_offset *offset = &frame->dma_offset; 389 struct fimc_dma_offset *offset = &frame->dma_offset;
383 u32 cfg = 0; 390 u32 cfg;
384 391
385 /* Set the pixel offsets. */ 392 /* Set the pixel offsets. */
386 cfg |= S5P_CIO_OFFS_HOR(offset->y_h); 393 cfg = S5P_CIO_OFFS_HOR(offset->y_h);
387 cfg |= S5P_CIO_OFFS_VER(offset->y_v); 394 cfg |= S5P_CIO_OFFS_VER(offset->y_v);
388 writel(cfg, dev->regs + S5P_CIIYOFF); 395 writel(cfg, dev->regs + S5P_CIIYOFF);
389 396
390 cfg = 0; 397 cfg = S5P_CIO_OFFS_HOR(offset->cb_h);
391 cfg |= S5P_CIO_OFFS_HOR(offset->cb_h);
392 cfg |= S5P_CIO_OFFS_VER(offset->cb_v); 398 cfg |= S5P_CIO_OFFS_VER(offset->cb_v);
393 writel(cfg, dev->regs + S5P_CIICBOFF); 399 writel(cfg, dev->regs + S5P_CIICBOFF);
394 400
395 cfg = 0; 401 cfg = S5P_CIO_OFFS_HOR(offset->cr_h);
396 cfg |= S5P_CIO_OFFS_HOR(offset->cr_h);
397 cfg |= S5P_CIO_OFFS_VER(offset->cr_v); 402 cfg |= S5P_CIO_OFFS_VER(offset->cr_v);
398 writel(cfg, dev->regs + S5P_CIICROFF); 403 writel(cfg, dev->regs + S5P_CIICROFF);
399 404
400 /* Input original and real size. */ 405 /* Input original and real size. */
401 fimc_hw_set_in_dma_size(ctx); 406 fimc_hw_set_in_dma_size(ctx);
402 407
403 /* Autoload is used currently only in FIFO mode. */ 408 /* Use DMA autoload only in FIFO mode. */
404 fimc_hw_en_autoload(dev, ctx->out_path == FIMC_LCDFIFO); 409 fimc_hw_en_autoload(dev, ctx->out_path == FIMC_LCDFIFO);
405 410
406 /* Set the input DMA to process single frame only. */ 411 /* Set the input DMA to process single frame only. */
@@ -501,27 +506,163 @@ void fimc_hw_set_output_path(struct fimc_ctx *ctx)
501 506
502void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr) 507void fimc_hw_set_input_addr(struct fimc_dev *dev, struct fimc_addr *paddr)
503{ 508{
504 u32 cfg = 0; 509 u32 cfg = readl(dev->regs + S5P_CIREAL_ISIZE);
505
506 cfg = readl(dev->regs + S5P_CIREAL_ISIZE);
507 cfg |= S5P_CIREAL_ISIZE_ADDR_CH_DIS; 510 cfg |= S5P_CIREAL_ISIZE_ADDR_CH_DIS;
508 writel(cfg, dev->regs + S5P_CIREAL_ISIZE); 511 writel(cfg, dev->regs + S5P_CIREAL_ISIZE);
509 512
510 writel(paddr->y, dev->regs + S5P_CIIYSA0); 513 writel(paddr->y, dev->regs + S5P_CIIYSA(0));
511 writel(paddr->cb, dev->regs + S5P_CIICBSA0); 514 writel(paddr->cb, dev->regs + S5P_CIICBSA(0));
512 writel(paddr->cr, dev->regs + S5P_CIICRSA0); 515 writel(paddr->cr, dev->regs + S5P_CIICRSA(0));
513 516
514 cfg &= ~S5P_CIREAL_ISIZE_ADDR_CH_DIS; 517 cfg &= ~S5P_CIREAL_ISIZE_ADDR_CH_DIS;
515 writel(cfg, dev->regs + S5P_CIREAL_ISIZE); 518 writel(cfg, dev->regs + S5P_CIREAL_ISIZE);
516} 519}
517 520
518void fimc_hw_set_output_addr(struct fimc_dev *dev, struct fimc_addr *paddr) 521void fimc_hw_set_output_addr(struct fimc_dev *dev,
522 struct fimc_addr *paddr, int index)
519{ 523{
520 int i; 524 int i = (index == -1) ? 0 : index;
521 /* Set all the output register sets to point to single video buffer. */ 525 do {
522 for (i = 0; i < FIMC_MAX_OUT_BUFS; i++) {
523 writel(paddr->y, dev->regs + S5P_CIOYSA(i)); 526 writel(paddr->y, dev->regs + S5P_CIOYSA(i));
524 writel(paddr->cb, dev->regs + S5P_CIOCBSA(i)); 527 writel(paddr->cb, dev->regs + S5P_CIOCBSA(i));
525 writel(paddr->cr, dev->regs + S5P_CIOCRSA(i)); 528 writel(paddr->cr, dev->regs + S5P_CIOCRSA(i));
529 dbg("dst_buf[%d]: 0x%X, cb: 0x%X, cr: 0x%X",
530 i, paddr->y, paddr->cb, paddr->cr);
531 } while (index == -1 && ++i < FIMC_MAX_OUT_BUFS);
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 */
526 } 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;
527} 668}
diff --git a/drivers/media/video/s5p-fimc/regs-fimc.h b/drivers/media/video/s5p-fimc/regs-fimc.h
index a3cfe824db00..a57daedb5b5c 100644
--- a/drivers/media/video/s5p-fimc/regs-fimc.h
+++ b/drivers/media/video/s5p-fimc/regs-fimc.h
@@ -11,10 +11,6 @@
11#ifndef REGS_FIMC_H_ 11#ifndef REGS_FIMC_H_
12#define REGS_FIMC_H_ 12#define REGS_FIMC_H_
13 13
14#define S5P_CIOYSA(__x) (0x18 + (__x) * 4)
15#define S5P_CIOCBSA(__x) (0x28 + (__x) * 4)
16#define S5P_CIOCRSA(__x) (0x38 + (__x) * 4)
17
18/* Input source format */ 14/* Input source format */
19#define S5P_CISRCFMT 0x00 15#define S5P_CISRCFMT 0x00
20#define S5P_CISRCFMT_ITU601_8BIT (1 << 31) 16#define S5P_CISRCFMT_ITU601_8BIT (1 << 31)
@@ -28,22 +24,21 @@
28 24
29/* Window offset */ 25/* Window offset */
30#define S5P_CIWDOFST 0x04 26#define S5P_CIWDOFST 0x04
31#define S5P_CIWDOFST_WINOFSEN (1 << 31) 27#define S5P_CIWDOFST_OFF_EN (1 << 31)
32#define S5P_CIWDOFST_CLROVFIY (1 << 30) 28#define S5P_CIWDOFST_CLROVFIY (1 << 30)
33#define S5P_CIWDOFST_CLROVRLB (1 << 29) 29#define S5P_CIWDOFST_CLROVRLB (1 << 29)
34#define S5P_CIWDOFST_WINHOROFST_MASK (0x7ff << 16) 30#define S5P_CIWDOFST_HOROFF_MASK (0x7ff << 16)
35#define S5P_CIWDOFST_CLROVFICB (1 << 15) 31#define S5P_CIWDOFST_CLROVFICB (1 << 15)
36#define S5P_CIWDOFST_CLROVFICR (1 << 14) 32#define S5P_CIWDOFST_CLROVFICR (1 << 14)
37#define S5P_CIWDOFST_WINHOROFST(x) ((x) << 16) 33#define S5P_CIWDOFST_HOROFF(x) ((x) << 16)
38#define S5P_CIWDOFST_WINVEROFST(x) ((x) << 0) 34#define S5P_CIWDOFST_VEROFF(x) ((x) << 0)
39#define S5P_CIWDOFST_WINVEROFST_MASK (0xfff << 0) 35#define S5P_CIWDOFST_VEROFF_MASK (0xfff << 0)
40 36
41/* Global control */ 37/* Global control */
42#define S5P_CIGCTRL 0x08 38#define S5P_CIGCTRL 0x08
43#define S5P_CIGCTRL_SWRST (1 << 31) 39#define S5P_CIGCTRL_SWRST (1 << 31)
44#define S5P_CIGCTRL_CAMRST_A (1 << 30) 40#define S5P_CIGCTRL_CAMRST_A (1 << 30)
45#define S5P_CIGCTRL_SELCAM_ITU_A (1 << 29) 41#define S5P_CIGCTRL_SELCAM_ITU_A (1 << 29)
46#define S5P_CIGCTRL_SELCAM_ITU_MASK (1 << 29)
47#define S5P_CIGCTRL_TESTPAT_NORMAL (0 << 27) 42#define S5P_CIGCTRL_TESTPAT_NORMAL (0 << 27)
48#define S5P_CIGCTRL_TESTPAT_COLOR_BAR (1 << 27) 43#define S5P_CIGCTRL_TESTPAT_COLOR_BAR (1 << 27)
49#define S5P_CIGCTRL_TESTPAT_HOR_INC (2 << 27) 44#define S5P_CIGCTRL_TESTPAT_HOR_INC (2 << 27)
@@ -61,6 +56,8 @@
61#define S5P_CIGCTRL_SHDW_DISABLE (1 << 12) 56#define S5P_CIGCTRL_SHDW_DISABLE (1 << 12)
62#define S5P_CIGCTRL_SELCAM_MIPI_A (1 << 7) 57#define S5P_CIGCTRL_SELCAM_MIPI_A (1 << 7)
63#define S5P_CIGCTRL_CAMIF_SELWB (1 << 6) 58#define S5P_CIGCTRL_CAMIF_SELWB (1 << 6)
59/* 0 - ITU601; 1 - ITU709 */
60#define S5P_CIGCTRL_CSC_ITU601_709 (1 << 5)
64#define S5P_CIGCTRL_INVPOLHSYNC (1 << 4) 61#define S5P_CIGCTRL_INVPOLHSYNC (1 << 4)
65#define S5P_CIGCTRL_SELCAM_MIPI (1 << 3) 62#define S5P_CIGCTRL_SELCAM_MIPI (1 << 3)
66#define S5P_CIGCTRL_INTERLACE (1 << 0) 63#define S5P_CIGCTRL_INTERLACE (1 << 0)
@@ -72,23 +69,10 @@
72#define S5P_CIWDOFST2_HOROFF(x) ((x) << 16) 69#define S5P_CIWDOFST2_HOROFF(x) ((x) << 16)
73#define S5P_CIWDOFST2_VEROFF(x) ((x) << 0) 70#define S5P_CIWDOFST2_VEROFF(x) ((x) << 0)
74 71
75/* Output DMA Y plane start address */ 72/* Output DMA Y/Cb/Cr plane start addresses */
76#define S5P_CIOYSA1 0x18 73#define S5P_CIOYSA(n) (0x18 + (n) * 4)
77#define S5P_CIOYSA2 0x1c 74#define S5P_CIOCBSA(n) (0x28 + (n) * 4)
78#define S5P_CIOYSA3 0x20 75#define S5P_CIOCRSA(n) (0x38 + (n) * 4)
79#define S5P_CIOYSA4 0x24
80
81/* Output DMA Cb plane start address */
82#define S5P_CIOCBSA1 0x28
83#define S5P_CIOCBSA2 0x2c
84#define S5P_CIOCBSA3 0x30
85#define S5P_CIOCBSA4 0x34
86
87/* Output DMA Cr plane start address */
88#define S5P_CIOCRSA1 0x38
89#define S5P_CIOCRSA2 0x3c
90#define S5P_CIOCRSA3 0x40
91#define S5P_CIOCRSA4 0x44
92 76
93/* Target image format */ 77/* Target image format */
94#define S5P_CITRGFMT 0x48 78#define S5P_CITRGFMT 0x48
@@ -168,6 +152,8 @@
168#define S5P_CISTATUS_OVFICB (1 << 30) 152#define S5P_CISTATUS_OVFICB (1 << 30)
169#define S5P_CISTATUS_OVFICR (1 << 29) 153#define S5P_CISTATUS_OVFICR (1 << 29)
170#define S5P_CISTATUS_VSYNC (1 << 28) 154#define S5P_CISTATUS_VSYNC (1 << 28)
155#define S5P_CISTATUS_FRAMECNT_MASK (3 << 26)
156#define S5P_CISTATUS_FRAMECNT_SHIFT 26
171#define S5P_CISTATUS_WINOFF_EN (1 << 25) 157#define S5P_CISTATUS_WINOFF_EN (1 << 25)
172#define S5P_CISTATUS_IMGCPT_EN (1 << 22) 158#define S5P_CISTATUS_IMGCPT_EN (1 << 22)
173#define S5P_CISTATUS_IMGCPT_SCEN (1 << 21) 159#define S5P_CISTATUS_IMGCPT_SCEN (1 << 21)
@@ -206,10 +192,10 @@
206#define S5P_CIIMGEFF_PAT_CB(x) ((x) << 13) 192#define S5P_CIIMGEFF_PAT_CB(x) ((x) << 13)
207#define S5P_CIIMGEFF_PAT_CR(x) ((x) << 0) 193#define S5P_CIIMGEFF_PAT_CR(x) ((x) << 0)
208 194
209/* Input DMA Y/Cb/Cr plane start address 0 */ 195/* Input DMA Y/Cb/Cr plane start address 0/1 */
210#define S5P_CIIYSA0 0xd4 196#define S5P_CIIYSA(n) (0xd4 + (n) * 0x70)
211#define S5P_CIICBSA0 0xd8 197#define S5P_CIICBSA(n) (0xd8 + (n) * 0x70)
212#define S5P_CIICRSA0 0xdc 198#define S5P_CIICRSA(n) (0xdc + (n) * 0x70)
213 199
214/* Real input DMA image size */ 200/* Real input DMA image size */
215#define S5P_CIREAL_ISIZE 0xf8 201#define S5P_CIREAL_ISIZE 0xf8
@@ -250,11 +236,6 @@
250#define S5P_MSCTRL_ENVID (1 << 0) 236#define S5P_MSCTRL_ENVID (1 << 0)
251#define S5P_MSCTRL_FRAME_COUNT(x) ((x) << 24) 237#define S5P_MSCTRL_FRAME_COUNT(x) ((x) << 24)
252 238
253/* Input DMA Y/Cb/Cr plane start address 1 */
254#define S5P_CIIYSA1 0x144
255#define S5P_CIICBSA1 0x148
256#define S5P_CIICRSA1 0x14c
257
258/* Output DMA Y/Cb/Cr offset */ 239/* Output DMA Y/Cb/Cr offset */
259#define S5P_CIOYOFF 0x168 240#define S5P_CIOYOFF 0x168
260#define S5P_CIOCBOFF 0x16c 241#define S5P_CIOCBOFF 0x16c
@@ -289,5 +270,16 @@
289 270
290/* MIPI CSI image format */ 271/* MIPI CSI image format */
291#define S5P_CSIIMGFMT 0x194 272#define S5P_CSIIMGFMT 0x194
273#define S5P_CSIIMGFMT_YCBCR422_8BIT 0x1e
274#define S5P_CSIIMGFMT_RAW8 0x2a
275#define S5P_CSIIMGFMT_RAW10 0x2b
276#define S5P_CSIIMGFMT_RAW12 0x2c
277#define S5P_CSIIMGFMT_USER1 0x30
278#define S5P_CSIIMGFMT_USER2 0x31
279#define S5P_CSIIMGFMT_USER3 0x32
280#define S5P_CSIIMGFMT_USER4 0x33
281
282/* Output frame buffer sequence mask */
283#define S5P_CIFCNTSEQ 0x1FC
292 284
293#endif /* REGS_FIMC_H_ */ 285#endif /* REGS_FIMC_H_ */