upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / media / video / samsung / fimc / fimc_output.c
1 /* linux/drivers/media/video/samsung/fimc/fimc_output.c
2  *
3  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4  *              http://www.samsung.com/
5  *
6  * V4L2 Output device support file for Samsung Camera Interface (FIMC) driver
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11 */
12
13 #include <linux/slab.h>
14 #include <linux/bootmem.h>
15 #include <linux/string.h>
16 #include <linux/platform_device.h>
17 #include <linux/mm.h>
18 #include <linux/videodev2.h>
19 #ifdef CONFIG_VIDEO_SAMSUNG_V4L2
20 #include <linux/videodev2_exynos_media.h>
21 #include <linux/videodev2_exynos_camera.h>
22 #endif
23 #include <media/videobuf-core.h>
24 #include <linux/io.h>
25 #include <linux/uaccess.h>
26 #include <linux/mman.h>
27 #include <plat/media.h>
28 #include <linux/clk.h>
29 #include <linux/delay.h>
30
31 #include "fimc.h"
32 #include "fimc-ipc.h"
33
34 #ifdef SYSMMU_FIMC
35 #include <plat/sysmmu.h>
36 #endif
37 static __u32 fimc_get_pixel_format_type(__u32 pixelformat)
38 {
39         switch (pixelformat) {
40         case V4L2_PIX_FMT_RGB32:
41         case V4L2_PIX_FMT_RGB565:
42                 return FIMC_RGB;
43
44         case V4L2_PIX_FMT_NV12:
45         case V4L2_PIX_FMT_NV12T:
46         case V4L2_PIX_FMT_NV21:
47         case V4L2_PIX_FMT_YUV420:
48                 return FIMC_YUV420;
49
50         case V4L2_PIX_FMT_YUYV:
51         case V4L2_PIX_FMT_UYVY:
52         case V4L2_PIX_FMT_YVYU:
53         case V4L2_PIX_FMT_VYUY:
54         case V4L2_PIX_FMT_NV16:
55         case V4L2_PIX_FMT_NV61:
56         case V4L2_PIX_FMT_YUV422P:
57                 return FIMC_YUV422;
58
59         default:
60                 return FIMC_YUV444;
61         }
62 }
63
64 void fimc_outdev_set_src_addr(struct fimc_control *ctrl, dma_addr_t *base)
65 {
66         fimc_hwset_addr_change_disable(ctrl);
67         fimc_hwset_input_address(ctrl, base);
68         fimc_hwset_addr_change_enable(ctrl);
69 }
70
71 int fimc_outdev_start_camif(void *param)
72 {
73         struct fimc_control *ctrl = (struct fimc_control *)param;
74
75         fimc_hwset_start_scaler(ctrl);
76         fimc_hwset_enable_capture(ctrl, 0);     /* bypass disable */
77         fimc_hwset_start_input_dma(ctrl);
78
79         return 0;
80 }
81
82 static int fimc_outdev_stop_camif(void *param)
83 {
84         struct fimc_control *ctrl = (struct fimc_control *)param;
85
86         fimc_hwset_stop_input_dma(ctrl);
87         fimc_hwset_disable_autoload(ctrl);
88         fimc_hwset_stop_scaler(ctrl);
89         fimc_hwset_disable_capture(ctrl);
90
91         return 0;
92 }
93
94 #if (!defined(CONFIG_S5PV310_DEV_PD) || !defined(CONFIG_PM_RUNTIME))
95 static int fimc_outdev_stop_dma(struct fimc_control *ctrl, struct fimc_ctx *ctx)
96 {
97         struct s3cfb_user_window window;
98         int window_id = ((ctrl->id == 3) ? 2 : ctrl->id);
99         int ret = -1;
100
101         fimc_dbg("%s: called\n", __func__);
102
103         ret = wait_event_timeout(ctrl->wq, (ctx->status == FIMC_STREAMOFF),
104                                                         FIMC_ONESHOT_TIMEOUT);
105         if (ret == 0)
106                 fimc_err("Fail: %s ctx->status=%d\n", __func__, ctx->status);
107
108         fimc_outdev_stop_camif(ctrl);
109
110         if (ctx->overlay.mode == FIMC_OVLY_DMA_MANUAL)
111                 return 0;
112
113         ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_OFF,
114                                                         (unsigned long)NULL);
115         if (ret < 0) {
116                 fimc_err("direct_ioctl(S3CFB_SET_WIN_OFF) fail\n");
117                 return -EINVAL;
118         }
119
120         /* reset WIN position */
121         memset(&window, 0, sizeof(window));
122         ret = s3cfb_direct_ioctl(window_id, S3CFB_WIN_POSITION,
123                         (unsigned long)&window);
124         if (ret < 0) {
125                 fimc_err("direct_ioctl(S3CFB_WIN_POSITION) fail\n");
126                 return -EINVAL;
127         }
128
129         ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_ADDR, 0x00000000);
130         if (ret < 0) {
131                 fimc_err("direct_ioctl(S3CFB_SET_WIN_ADDR) fail\n");
132                 return -EINVAL;
133         }
134
135         ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_MEM, DMA_MEM_NONE);
136         if (ret < 0) {
137                 fimc_err("direct_ioctl(S3CFB_SET_WIN_MEM) fail\n");
138                 return -EINVAL;
139         }
140
141         ctrl->fb.is_enable = 0;
142
143         return 0;
144 }
145 #endif
146
147 static int fimc_outdev_stop_fifo(struct fimc_control *ctrl,
148                                  struct fimc_ctx *ctx)
149 {
150         struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
151         int ret = -1;
152
153         fimc_dbg("%s: called\n", __func__);
154
155         if (pdata->hw_ver == 0x40) {            /* to support C100 */
156                 ret = ctrl->fb.close_fifo(ctrl->id, fimc_outdev_stop_camif,
157                                 (void *)ctrl);
158                 if (ret < 0)
159                         fimc_err("FIMD FIFO close fail\n");
160         } else if ((pdata->hw_ver == 0x43) || (pdata->hw_ver >= 0x50)) {
161                 ret = ctrl->fb.close_fifo(ctrl->id, NULL, NULL);
162                 if (ret < 0)
163                         fimc_err("FIMD FIFO close fail\n");
164                 fimc_hw_wait_winoff(ctrl);
165                 fimc_outdev_stop_camif(ctrl);
166                 fimc_hw_wait_stop_input_dma(ctrl);
167 #if defined(CONFIG_VIDEO_IPC)
168                 if (ctx->pix.field == V4L2_FIELD_INTERLACED_TB)
169                         ipc_stop();
170 #endif
171         }
172
173         return 0;
174 }
175
176 int fimc_outdev_stop_streaming(struct fimc_control *ctrl, struct fimc_ctx *ctx)
177 {
178         int ret = 0;
179
180         fimc_dbg("%s: called\n", __func__);
181
182         switch (ctx->overlay.mode) {
183         case FIMC_OVLY_FIFO:
184                 ctx->status = FIMC_READY_OFF;
185                 fimc_outdev_stop_fifo(ctrl, ctx);
186                 break;
187         case FIMC_OVLY_DMA_AUTO:                /* fall through */
188         case FIMC_OVLY_DMA_MANUAL:
189                 if (ctx->status == FIMC_STREAMON_IDLE)
190                         ctx->status = FIMC_STREAMOFF;
191                 else
192                         ctx->status = FIMC_READY_OFF;
193
194 #if (!defined(CONFIG_S5PV310_DEV_PD) || !defined(CONFIG_PM_RUNTIME))
195                 fimc_outdev_stop_dma(ctrl, ctx);
196 #endif
197                 break;
198         case FIMC_OVLY_NONE_SINGLE_BUF:         /* fall through */
199         case FIMC_OVLY_NONE_MULTI_BUF:
200                 if (ctx->status == FIMC_STREAMON_IDLE)
201                         ctx->status = FIMC_STREAMOFF;
202                 else
203                         ctx->status = FIMC_READY_OFF;
204
205                 ret = wait_event_timeout(ctrl->wq,
206                                         (ctx->status == FIMC_STREAMOFF),
207                                         FIMC_ONESHOT_TIMEOUT);
208                 if (ret == 0) {
209                         fimc_dump_context(ctrl, ctx);
210                         fimc_err("fail %s: %d\n", __func__, ctx->ctx_num);
211                 }
212
213                 break;
214         default:
215                 break;
216         }
217
218         return 0;
219 }
220
221 static int fimc_outdev_dma_auto_dst_resize(struct v4l2_rect *org)
222 {
223         if (org->width % 16)
224                 org->width = org->width + 16 - (org->width % 16);
225
226         return 0;
227 }
228
229 int fimc_outdev_resume_dma(struct fimc_control *ctrl, struct fimc_ctx *ctx)
230 {
231         struct v4l2_rect fimd_rect, fimd_rect_virtual;
232         struct fb_var_screeninfo var;
233         struct s3cfb_user_window window;
234         int ret = -1, idx;
235         int window_id = ((ctrl->id == 3) ? 2 : ctrl->id);
236
237         memset(&fimd_rect, 0, sizeof(struct v4l2_rect));
238         ret = fimc_fimd_rect(ctrl, ctx, &fimd_rect);
239         if (ret < 0) {
240                 fimc_err("fimc_fimd_rect fail\n");
241                 return -EINVAL;
242         }
243
244         /* Support any size */
245         memcpy(&fimd_rect_virtual, &fimd_rect, sizeof(fimd_rect));
246         fimc_outdev_dma_auto_dst_resize(&fimd_rect_virtual);
247
248         /* Get WIN var_screeninfo */
249         ret = s3cfb_direct_ioctl(window_id, FBIOGET_VSCREENINFO,
250                                                 (unsigned long)&var);
251         if (ret < 0) {
252                 fimc_err("direct_ioctl(FBIOGET_VSCREENINFO) fail\n");
253                 return -EINVAL;
254         }
255
256         /* window path : DMA */
257         ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_PATH, DATA_PATH_DMA);
258         if (ret < 0) {
259                 fimc_err("direct_ioctl(S3CFB_SET_WIN_PATH) fail\n");
260                 return -EINVAL;
261         }
262
263         /* Don't allocate the memory. */
264         ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_MEM, DMA_MEM_OTHER);
265         if (ret < 0) {
266                 fimc_err("direct_ioctl(S3CFB_SET_WIN_MEM) fail\n");
267                 return -EINVAL;
268         }
269
270         /* Update WIN size */
271         var.xres_virtual = fimd_rect_virtual.width;
272         var.yres_virtual = fimd_rect_virtual.height;
273         var.xres = fimd_rect.width;
274         var.yres = fimd_rect.height;
275
276         ret = s3cfb_direct_ioctl(window_id, FBIOPUT_VSCREENINFO,
277                                                 (unsigned long)&var);
278         if (ret < 0) {
279                 fimc_err("direct_ioctl(FBIOPUT_VSCREENINFO) fail\n");
280                 return -EINVAL;
281         }
282
283         /* Update WIN position */
284         window.x = fimd_rect.left;
285         window.y = fimd_rect.top;
286         ret = s3cfb_direct_ioctl(window_id, S3CFB_WIN_POSITION,
287                         (unsigned long)&window);
288         if (ret < 0) {
289                 fimc_err("direct_ioctl(S3CFB_WIN_POSITION) fail\n");
290                 return -EINVAL;
291         }
292
293         idx = ctx->outq[0];
294         if (idx == -1) {
295                 fimc_err("out going queue is empty.\n");
296                 return -EINVAL;
297         }
298
299         ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_ADDR,
300                         (unsigned long)ctx->dst[idx].base[FIMC_ADDR_Y]);
301         if (ret < 0) {
302                 fimc_err("direct_ioctl(S3CFB_SET_WIN_ADDR) fail\n");
303                 return -EINVAL;
304         }
305
306 #if 0
307         /* Remarked for better screen display
308          * when dynamic screen size change is requested
309          */
310         ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_ON,
311                                                         (unsigned long)NULL);
312         if (ret < 0) {
313                 fimc_err("direct_ioctl(S3CFB_SET_WIN_ON) fail\n");
314                 return -EINVAL;
315         }
316 #endif
317
318         ctrl->fb.is_enable = 1;
319
320         return 0;
321 }
322
323 static void fimc_init_out_buf(struct fimc_ctx *ctx)
324 {
325         int i;
326
327         for (i = 0; i < FIMC_OUTBUFS; i++) {
328                 ctx->src[i].state = VIDEOBUF_IDLE;
329                 ctx->src[i].flags = 0x0;
330
331                 ctx->inq[i] = -1;
332                 ctx->outq[i] = -1;
333         }
334 }
335
336 static int fimc_outdev_set_src_buf(struct fimc_control *ctrl,
337                                    struct fimc_ctx *ctx)
338 {
339         u32 width = ctx->pix.width;
340         u32 height = ctx->pix.height;
341         u32 format = ctx->pix.pixelformat;
342         u32 y_size = width * height;
343         u32 cb_size = 0, cr_size = 0;
344         u32 i, size;
345         dma_addr_t *curr = &ctrl->mem.curr;
346
347         switch (format) {
348         case V4L2_PIX_FMT_RGB32:
349                 size = PAGE_ALIGN(y_size << 2);
350                 break;
351         case V4L2_PIX_FMT_RGB565:       /* fall through */
352         case V4L2_PIX_FMT_YUYV:
353                 size = PAGE_ALIGN(y_size << 1);
354                 break;
355         case V4L2_PIX_FMT_YUV420:
356                 cb_size = y_size >> 2;
357                 cr_size = y_size >> 2;
358                 size = PAGE_ALIGN(y_size + cb_size + cr_size);
359                 break;
360         case V4L2_PIX_FMT_NV12:
361         case V4L2_PIX_FMT_NV21:
362                 cb_size = y_size >> 1;
363                 size = PAGE_ALIGN(y_size + cb_size);
364                 break;
365         case V4L2_PIX_FMT_NV12T:
366                 fimc_get_nv12t_size(width, height, &y_size, &cb_size);
367                 size = PAGE_ALIGN(y_size + cb_size);
368                 break;
369         default:
370                 fimc_err("%s: Invalid pixelformt : %d\n", __func__, format);
371                 return -EINVAL;
372         }
373
374         if ((*curr + size * FIMC_OUTBUFS) > (ctrl->mem.base + ctrl->mem.size)) {
375                 fimc_err("%s: Reserved memory is not sufficient\n", __func__);
376                 fimc_err("ctrl->mem.base = 0x%x\n", ctrl->mem.base);
377                 fimc_err("ctrl->mem.size = 0x%x\n", ctrl->mem.size);
378                 fimc_err("*curr          = 0x%x\n", *curr);
379                 fimc_err("size           = 0x%x\n", size);
380                 fimc_err("FIMC_OUTBUFS   = 0x%x\n", FIMC_OUTBUFS);
381                 return -EINVAL;
382         }
383
384         /* Initialize source buffer addr */
385         switch (format) {
386         case V4L2_PIX_FMT_RGB565:       /* fall through */
387         case V4L2_PIX_FMT_RGB32:        /* fall through */
388         case V4L2_PIX_FMT_YUYV:
389                 for (i = 0; i < FIMC_OUTBUFS; i++) {
390                         ctx->src[i].base[FIMC_ADDR_Y] = *curr;
391                         ctx->src[i].length[FIMC_ADDR_Y] = size;
392                         ctx->src[i].base[FIMC_ADDR_CB] = 0;
393                         ctx->src[i].length[FIMC_ADDR_CB] = 0;
394                         ctx->src[i].base[FIMC_ADDR_CR] = 0;
395                         ctx->src[i].length[FIMC_ADDR_CR] = 0;
396                         *curr += size;
397                 }
398                 break;
399         case V4L2_PIX_FMT_NV12:
400         case V4L2_PIX_FMT_NV21:
401                 for (i = 0; i < FIMC_OUTBUFS; i++) {
402                         ctx->src[i].base[FIMC_ADDR_Y] = *curr;
403                         ctx->src[i].length[FIMC_ADDR_Y] = y_size;
404                         ctx->src[i].base[FIMC_ADDR_CB] = *curr + y_size;
405                         ctx->src[i].length[FIMC_ADDR_CB] = cb_size;
406                         ctx->src[i].base[FIMC_ADDR_CR] = 0;
407                         ctx->src[i].length[FIMC_ADDR_CR] = 0;
408                         *curr += size;
409                 }
410                 break;
411         case V4L2_PIX_FMT_NV12T:
412                 for (i = 0; i < FIMC_OUTBUFS; i++) {
413                         ctx->src[i].base[FIMC_ADDR_Y] = *curr;
414                         ctx->src[i].base[FIMC_ADDR_CB] = *curr + y_size;
415                         ctx->src[i].length[FIMC_ADDR_Y] = y_size;
416                         ctx->src[i].length[FIMC_ADDR_CB] = cb_size;
417                         ctx->src[i].base[FIMC_ADDR_CR] = 0;
418                         ctx->src[i].length[FIMC_ADDR_CR] = 0;
419                         *curr += size;
420                 }
421                 break;
422         case V4L2_PIX_FMT_YUV420:
423                 for (i = 0; i < FIMC_OUTBUFS; i++) {
424                         ctx->src[i].base[FIMC_ADDR_Y] = *curr;
425                         ctx->src[i].base[FIMC_ADDR_CB] = *curr + y_size;
426                         ctx->src[i].base[FIMC_ADDR_CR] = *curr + y_size + cb_size;
427                         ctx->src[i].length[FIMC_ADDR_Y] = y_size;
428                         ctx->src[i].length[FIMC_ADDR_CB] = cb_size;
429                         ctx->src[i].length[FIMC_ADDR_CR] = cr_size;
430                         *curr += size;
431                 }
432                 break;
433
434         default:
435                 fimc_err("%s: Invalid pixelformt : %d\n", __func__, format);
436                 return -EINVAL;
437         }
438
439         return 0;
440 }
441
442 #ifdef CONFIG_VIDEO_FIMC_UMP_VCM_CMA
443 int fimc_vcm_alloc_outbuf(struct fimc_control *ctrl, int buf_num, int buf_size)
444 {
445         unsigned long arg = 0;
446         struct ump_vcm ump_vcm;
447         struct vcm_phys *phys = NULL;
448         dma_addr_t phys_addr;
449
450         phys = kmalloc(sizeof(*phys) + sizeof(*phys->parts), GFP_KERNEL);
451         memset(phys, 0, sizeof(*phys) + sizeof(*phys->parts));
452
453         phys_addr = (dma_addr_t)cma_alloc(ctrl->dev, ctrl->cma_name, \
454                                          (size_t)buf_size, 0);
455         fimc_info1("%s : phys_addr : 0x%x, ctrl->dev : 0x%x\n", __func__,
456                         phys_addr, (unsigned int)ctrl->dev);
457         phys->count = 1;
458         phys->size = buf_size;
459         phys->free = NULL;
460         phys->parts[0].start = phys_addr;
461         phys->parts[0].size = buf_size;
462
463         ctrl->dev_vcm_res[buf_num] = vcm_map(ctrl->dev_vcm, phys, 0);
464
465         /* physical address */
466         ctrl->mem.base = ctrl->dev_vcm_res[buf_num]->phys->parts->start;
467
468         /* virtual address */
469         ctrl->mem.vaddr_base = ctrl->dev_vcm_res[buf_num]->start;
470
471         ctrl->mem.curr = ctrl->mem.base;
472         ctrl->mem.vaddr_curr = ctrl->mem.vaddr_base;
473
474         fimc_info1("%s : vaddr base : 0x%x\n", __func__, ctrl->mem.vaddr_base);
475         ctrl->mem.size = buf_size;
476
477         /* UMP */
478         ctrl->ump_memory_description.addr = ctrl->mem.base;
479         ctrl->ump_memory_description.size = ctrl->mem.size;
480
481         ump_vcm.vcm = ctrl->dev_vcm;
482         ump_vcm.vcm_res = ctrl->dev_vcm_res[buf_num];
483         ump_vcm.dev_id = ctrl->vcm_id;
484         arg = (unsigned int)&ump_vcm;
485
486         ctrl->ump_wrapped_buffer[buf_num] =
487                 ump_dd_handle_create_from_phys_blocks(&ctrl->ump_memory_description, 1);
488
489         if (UMP_DD_HANDLE_INVALID == ctrl->ump_wrapped_buffer[buf_num]) {
490                 fimc_err("%s : ump_wrapped_buffer is unhandled\n", __func__);
491                 return -ENOMEM;
492         }
493 #ifdef CONFIG_UMP_VCM_ALLOC
494         if (ump_dd_vcm_attribute_set(ctrl->ump_wrapped_buffer[buf_num], arg))
495                 return -ENOMEM;
496 #endif
497         return 0;
498 }
499
500 int fimc_vcm_free_outbuf(struct fimc_control *ctrl, int buf_num, int phy_addr)
501 {
502         kfree(ctrl->dev_vcm_res[buf_num]->phys);
503         vcm_unmap(ctrl->dev_vcm_res[buf_num]);
504         cma_free(phy_addr);
505 }
506 #endif
507
508 static int fimc_outdev_set_dst_buf(struct fimc_control *ctrl,
509                                    struct fimc_ctx *ctx)
510 {
511 #ifdef SYSMMU_FIMC
512         struct vcm_res *vcm_res;
513
514         u32 width = ctrl->fb.lcd_hres;
515         u32 height = ctrl->fb.lcd_vres;
516         u32 i, size;
517
518         size = PAGE_ALIGN(width * height * 4);
519
520         /* Initialize destination buffer addr */
521         for (i = 0; i < FIMC_OUTBUFS; i++) {
522                 fimc_vcm_alloc_outbuf(ctrl, i, size);
523                 ctx->dst[i].base[FIMC_ADDR_Y] = ctrl->mem.base;
524                 ctx->dst[i].vaddr_base[FIMC_ADDR_Y] = ctrl->mem.vaddr_curr;
525                 ctx->dst[i].length[FIMC_ADDR_Y] = size;
526                 ctx->dst[i].base[FIMC_ADDR_CB] = 0;
527                 ctx->dst[i].vaddr_base[FIMC_ADDR_CB] = 0;
528                 ctx->dst[i].length[FIMC_ADDR_CB] = 0;
529                 ctx->dst[i].base[FIMC_ADDR_CR] = 0;
530                 ctx->dst[i].vaddr_base[FIMC_ADDR_CR] = 0;
531                 ctx->dst[i].length[FIMC_ADDR_CR] = 0;
532         }
533
534         return 0;
535 #else
536         dma_addr_t *curr = &ctrl->mem.curr;
537         dma_addr_t end;
538         u32 width = max_t(u32, ctrl->fb.lcd_hres, ctx->pix.width);
539         u32 height = max_t(u32, ctrl->fb.lcd_vres, ctx->pix.height);
540         u32 i, size;
541
542         end = ctrl->mem.base + ctrl->mem.size;
543         size = PAGE_ALIGN(width * height * 4);
544
545         if ((*curr + (size * FIMC_OUTBUFS)) > end) {
546                 fimc_err("%s: Reserved memory is not sufficient\n", __func__);
547                 fimc_err("ctrl->mem.base = 0x%x\n", ctrl->mem.base);
548                 fimc_err("ctrl->mem.size = 0x%x\n", ctrl->mem.size);
549                 fimc_err("*curr          = 0x%x\n", *curr);
550                 fimc_err("size           = 0x%x\n", size);
551                 fimc_err("FIMC_OUTBUFS   = 0x%x\n", FIMC_OUTBUFS);
552                 return -EINVAL;
553         }
554
555         /* Initialize destination buffer addr */
556         for (i = 0; i < FIMC_OUTBUFS; i++) {
557                 ctx->dst[i].base[FIMC_ADDR_Y] = *curr;
558                 ctx->dst[i].length[FIMC_ADDR_Y] = size;
559                 ctx->dst[i].base[FIMC_ADDR_CB] = 0;
560                 ctx->dst[i].length[FIMC_ADDR_CB] = 0;
561                 ctx->dst[i].base[FIMC_ADDR_CR] = 0;
562                 ctx->dst[i].length[FIMC_ADDR_CR] = 0;
563                 *curr += size;
564         }
565
566         return 0;
567 #endif
568 }
569
570 static int fimc_set_rot_degree(struct fimc_control *ctrl,
571                                struct fimc_ctx *ctx,
572                                int degree)
573 {
574         switch (degree) {
575         case 0:         /* fall through */
576         case 90:        /* fall through */
577         case 180:       /* fall through */
578         case 270:
579                 ctx->rotate = degree;
580                 break;
581
582         default:
583                 fimc_err("Invalid rotate value : %d\n", degree);
584                 return -EINVAL;
585         }
586
587         return 0;
588 }
589
590 int fimc_outdev_check_param(struct fimc_control *ctrl,
591                             struct fimc_ctx *ctx)
592 {
593         struct v4l2_rect dst, bound = { 0, };
594         u32 rot = 0;
595         int ret = 0, i, exclusive = 0;
596
597         rot = fimc_mapping_rot_flip(ctx->rotate, ctx->flip);
598         dst.top = ctx->win.w.top;
599         dst.left = ctx->win.w.left;
600         dst.width = ctx->win.w.width;
601         dst.height = ctx->win.w.height;
602
603         switch (ctx->overlay.mode) {
604         case FIMC_OVLY_FIFO:            /* fall through */
605                 if (rot & FIMC_ROT) {
606                         bound.width = ctrl->fb.lcd_vres;
607                         bound.height = ctrl->fb.lcd_hres;
608                 } else {
609                         bound.width = ctrl->fb.lcd_hres;
610                         bound.height = ctrl->fb.lcd_vres;
611                 }
612                 break;
613         case FIMC_OVLY_DMA_AUTO:        /* fall through */
614         case FIMC_OVLY_DMA_MANUAL:
615                 break;
616         case FIMC_OVLY_NONE_SINGLE_BUF: /* fall through */
617         case FIMC_OVLY_NONE_MULTI_BUF:
618                 bound.width = ctx->fbuf.fmt.width;
619                 bound.height = ctx->fbuf.fmt.height;
620                 break;
621
622         default:
623                 fimc_err("%s: invalid ovelay mode.\n", __func__);
624                 return -EINVAL;
625         }
626
627         if (((dst.left + dst.width) > bound.width) &&
628                 (ctx->overlay.mode != FIMC_OVLY_DMA_AUTO) &&
629                 (ctx->overlay.mode != FIMC_OVLY_DMA_MANUAL)) {
630                 fimc_err("Horizontal position setting is failed\n");
631                 fimc_err("\tleft = %d, width = %d, bound width = %d,\n",
632                                 dst.left, dst.width, bound.width);
633                 ret = -EINVAL;
634         } else if (((dst.top + dst.height) > bound.height) &&
635                 (ctx->overlay.mode != FIMC_OVLY_DMA_AUTO) &&
636                 (ctx->overlay.mode != FIMC_OVLY_DMA_MANUAL)) {
637                 fimc_err("Vertical position setting is failed\n");
638                 fimc_err("\ttop = %d, height = %d, bound height = %d,\n",
639                                 dst.top, dst.height, bound.height);
640                 ret = -EINVAL;
641         }
642
643         if ((ctx->status != FIMC_STREAMOFF) &&
644             (ctx->status != FIMC_READY_ON) &&
645             (ctx->status != FIMC_STREAMON_IDLE) &&
646             (ctx->status != FIMC_ON_IDLE_SLEEP)) {
647                 fimc_err("%s: FIMC is running\n", __func__);
648                 return -EBUSY;
649         }
650
651         /* check other open instance */
652         for (i = 0; i < FIMC_MAX_CTXS; i++) {
653                 switch (ctrl->out->ctx[i].overlay.mode) {
654                 case FIMC_OVLY_FIFO:            /* fall through */
655                 case FIMC_OVLY_DMA_AUTO:        /* fall through */
656                 case FIMC_OVLY_DMA_MANUAL:
657                         exclusive++;
658                         break;
659                 case FIMC_OVLY_NONE_SINGLE_BUF: /* fall through */
660                 case FIMC_OVLY_NONE_MULTI_BUF:  /* fall through */
661                 case FIMC_OVLY_NOT_FIXED:
662                         break;
663                 }
664         }
665
666         if (exclusive > 1) {
667                 for (i = 0; i < FIMC_MAX_CTXS; i++)
668                         fimc_err("%s: ctx %d mode = %d", __func__, i,
669                                         ctrl->out->ctx[i].overlay.mode);
670                 return -EBUSY;
671         }
672
673         return ret;
674 }
675
676 static void fimc_outdev_set_src_format(struct fimc_control *ctrl,
677                                        u32 pixfmt, enum v4l2_field field)
678 {
679         fimc_hwset_input_burst_cnt(ctrl, 4);
680         fimc_hwset_input_colorspace(ctrl, pixfmt);
681         fimc_hwset_input_yuv(ctrl, pixfmt);
682         fimc_hwset_input_rgb(ctrl, pixfmt);
683         fimc_hwset_intput_field(ctrl, field);
684         fimc_hwset_ext_rgb(ctrl, 1);
685         fimc_hwset_input_addr_style(ctrl, pixfmt);
686 }
687
688 static void fimc_outdev_set_dst_format(struct fimc_control *ctrl,
689                                        struct v4l2_pix_format *pixfmt)
690 {
691         fimc_hwset_output_colorspace(ctrl, pixfmt->pixelformat);
692         fimc_hwset_output_yuv(ctrl, pixfmt->pixelformat);
693         fimc_hwset_output_rgb(ctrl, pixfmt->pixelformat);
694         fimc_hwset_output_scan(ctrl, pixfmt);
695         fimc_hwset_output_addr_style(ctrl, pixfmt->pixelformat);
696 }
697
698 static void fimc_outdev_set_format(struct fimc_control *ctrl,
699                                    struct fimc_ctx *ctx)
700 {
701         struct v4l2_pix_format pixfmt;
702         memset(&pixfmt, 0, sizeof(pixfmt));
703
704         fimc_outdev_set_src_format(ctrl, ctx->pix.pixelformat, ctx->pix.field);
705
706         switch (ctx->overlay.mode) {
707         case FIMC_OVLY_FIFO:            /* fall through */
708         case FIMC_OVLY_DMA_AUTO:        /* fall through */
709         case FIMC_OVLY_DMA_MANUAL:      /* Non-destructive overlay mode */
710                 if (ctx->pix.field == V4L2_FIELD_NONE) {
711                         pixfmt.pixelformat = V4L2_PIX_FMT_RGB32;
712                         pixfmt.field = V4L2_FIELD_NONE;
713                 } else if (ctx->pix.field == V4L2_FIELD_INTERLACED_TB) {
714                         pixfmt.pixelformat = V4L2_PIX_FMT_YUV444;
715                         pixfmt.field = V4L2_FIELD_INTERLACED_TB;
716                 } else if (ctx->pix.field == V4L2_FIELD_ANY) {
717                         pixfmt.pixelformat = V4L2_PIX_FMT_RGB32;
718                         pixfmt.field = V4L2_FIELD_NONE;
719                 }
720
721                 break;
722         case FIMC_OVLY_NONE_SINGLE_BUF: /* fall through */
723         case FIMC_OVLY_NONE_MULTI_BUF:  /* Destructive overlay mode */
724                 pixfmt.pixelformat = ctx->fbuf.fmt.pixelformat;
725                 pixfmt.field = V4L2_FIELD_NONE;
726
727                 break;
728         default:
729                 fimc_err("Invalid overlay mode %d\n", ctx->overlay.mode);
730                 break;
731         }
732
733         fimc_outdev_set_dst_format(ctrl, &pixfmt);
734 }
735
736 static void fimc_outdev_set_path(struct fimc_control *ctrl,
737                                  struct fimc_ctx *ctx)
738 {
739         /* source path */
740         fimc_hwset_input_source(ctrl, FIMC_SRC_MSDMA);
741
742         if (ctx->overlay.mode == FIMC_OVLY_FIFO) {
743                 fimc_hwset_enable_lcdfifo(ctrl);
744                 fimc_hwset_enable_autoload(ctrl);
745         } else {
746                 fimc_hwset_disable_lcdfifo(ctrl);
747                 fimc_hwset_disable_autoload(ctrl);
748         }
749 }
750
751 static void fimc_outdev_set_rot(struct fimc_control *ctrl,
752                                 struct fimc_ctx *ctx)
753 {
754         u32 rot = ctx->rotate;
755         u32 flip = ctx->flip;
756
757         if (ctx->overlay.mode == FIMC_OVLY_FIFO) {
758                 fimc_hwset_input_rot(ctrl, rot, flip);
759                 fimc_hwset_input_flip(ctrl, rot, flip);
760                 fimc_hwset_output_rot_flip(ctrl, 0, 0);
761         } else {
762                 fimc_hwset_input_rot(ctrl, 0, 0);
763                 fimc_hwset_input_flip(ctrl, 0, 0);
764                 fimc_hwset_output_rot_flip(ctrl, rot, flip);
765         }
766 }
767
768 static void fimc_outdev_set_src_dma_offset(struct fimc_control *ctrl,
769                                            struct fimc_ctx *ctx)
770 {
771         struct v4l2_rect bound, crop;
772         u32 pixfmt = ctx->pix.pixelformat;
773
774         bound.width = ctx->pix.width;
775         bound.height = ctx->pix.height;
776
777         crop.left = ctx->crop.left;
778         crop.top = ctx->crop.top;
779         crop.width = ctx->crop.width;
780         crop.height = ctx->crop.height;
781
782         fimc_hwset_input_offset(ctrl, pixfmt, &bound, &crop);
783 }
784
785 static int fimc4x_outdev_check_src_size(struct fimc_control *ctrl,
786                                         struct fimc_ctx *ctx,
787                                         struct v4l2_rect *real,
788                                         struct v4l2_rect *org)
789 {
790         u32 rot = ctx->rotate;
791
792         if ((ctx->overlay.mode == FIMC_OVLY_FIFO) &&
793             ((rot == 90) || (rot == 270))) {
794                 /* Input Rotator */
795                 if (real->height % 16) {
796                         fimc_err("SRC Real_H(%d): multiple of 16 !\n",
797                                         real->height);
798                         return -EINVAL;
799                 }
800
801                 if (ctx->sc.pre_hratio) {
802                         if (real->height % (ctx->sc.pre_hratio * 4)) {
803                                 fimc_err("SRC Real_H(%d): multiple of "
804                                                 "4*pre_hratio(%d)\n",
805                                                 real->height,
806                                                 ctx->sc.pre_hratio);
807                                 return -EINVAL;
808                         }
809                 }
810
811                 if (ctx->sc.pre_vratio) {
812                         if (real->width % ctx->sc.pre_vratio) {
813                                 fimc_err("SRC Real_W(%d): multiple of "
814                                                 "pre_vratio(%d)\n",
815                                                 real->width,
816                                                 ctx->sc.pre_vratio);
817                                 return -EINVAL;
818                         }
819                 }
820
821                 if (real->height < 16) {
822                         fimc_err("SRC Real_H(%d): Min 16\n", real->height);
823                         return -EINVAL;
824                 }
825                 if (real->width < 8) {
826                         fimc_err("SRC Real_W(%d): Min 8\n", real->width);
827                         return -EINVAL;
828                 }
829         } else {
830                 /* No Input Rotator */
831                 if (real->height < 8) {
832                         fimc_err("SRC Real_H(%d): Min 8\n", real->height);
833                         return -EINVAL;
834                 }
835
836                 if (real->width < 16) {
837                         fimc_err("SRC Real_W(%d): Min 16\n", real->width);
838                         return -EINVAL;
839                 }
840
841                 if (real->width > ctrl->limit->real_w_no_rot) {
842                         fimc_err("SRC REAL_W(%d): Real_W <= %d\n", real->width,
843                                         ctrl->limit->real_w_no_rot);
844                         return -EINVAL;
845                 }
846         }
847
848         if (org->height < real->height) {
849                 fimc_err("SRC Org_H(%d): larger than Real_H(%d)\n",
850                                 org->height, real->height);
851                 return -EINVAL;
852         }
853
854         if (org->width < real->width) {
855                 fimc_err("SRC Org_W: Org_W(%d) >= Real_W(%d)\n", org->width,
856                                 real->width);
857                 return -EINVAL;
858         }
859
860         if (ctx->sc.pre_vratio) {
861                 if (real->height % ctx->sc.pre_vratio) {
862                         fimc_err("SRC Real_H(%d): multi of pre_vratio(%d)!\n",
863                                         real->height, ctx->sc.pre_vratio);
864                         return -EINVAL;
865                 }
866         }
867
868         if (real->width % 16) {
869                 fimc_err("SRC Real_W(%d): multiple of 16 !\n", real->width);
870                 return -EINVAL;
871         }
872
873         if (ctx->sc.pre_hratio) {
874                 if (real->width % (ctx->sc.pre_hratio * 4)) {
875                         fimc_err("SRC Real_W(%d): "
876                                         "multiple of 4 * pre_hratio(%d)!\n",
877                                         real->width, ctx->sc.pre_hratio);
878                         return -EINVAL;
879                 }
880         }
881
882         if (org->width % 16) {
883                 fimc_err("SRC Org_W(%d): multiple of 16\n", org->width);
884                 return -EINVAL;
885         }
886
887         if (org->height < 8) {
888                 fimc_err("SRC Org_H(%d): Min 8\n", org->height);
889                 return -EINVAL;
890         }
891
892         return 0;
893 }
894
895 static int fimc50_outdev_check_src_size(struct fimc_control *ctrl,
896                                         struct fimc_ctx *ctx,
897                                         struct v4l2_rect *real,
898                                         struct v4l2_rect *org)
899 {
900         u32 rot = ctx->rotate;
901         u32 pixelformat = ctx->pix.pixelformat;
902
903         if ((ctx->overlay.mode == FIMC_OVLY_FIFO) &&
904             ((rot == 90) || (rot == 270))) {
905                 /* Input Rotator */
906                 switch (pixelformat) {
907                 case V4L2_PIX_FMT_YUV422P:      /* fall through */
908                 case V4L2_PIX_FMT_YVU420:
909                         if (real->height % 2) {
910                                 fimc_err("SRC Real_H(%d): multiple of 2\n",
911                                                 real->height);
912                                 return -EINVAL;
913                         }
914                 }
915
916                 if (real->height < 16) {
917                         fimc_err("SRC Real_H(%d): Min 16\n", real->height);
918                         return -EINVAL;
919                 }
920                 if (real->width < 8) {
921                         fimc_err("SRC Real_W(%d): Min 8\n", real->width);
922                         return -EINVAL;
923                 }
924         } else {
925                 /* No Input Rotator */
926                 if (real->height < 8) {
927                         fimc_err("SRC Real_H(%d): Min 8\n", real->height);
928                         return -EINVAL;
929                 }
930
931                 if (real->width < 16) {
932                         fimc_err("SRC Real_W(%d): Min 16\n", real->width);
933                         return -EINVAL;
934                 }
935
936                 if (real->width > ctrl->limit->real_w_no_rot) {
937                         fimc_err("SRC REAL_W(%d): Real_W <= %d\n", real->width,
938                                         ctrl->limit->real_w_no_rot);
939                         return -EINVAL;
940                 }
941         }
942
943         if (org->height < real->height) {
944                 fimc_err("SRC Org_H: larger than Real_H, "
945                                 "org %dx%d, real %dx%d\n",
946                                 org->width, org->height,
947                                 real->width, real->height);
948                 return -EINVAL;
949         }
950
951         if (org->width < real->width) {
952                 fimc_err("SRC Org_W: Org_W(%d) >= Real_W(%d)\n",
953                                 org->width, real->width);
954                 return -EINVAL;
955         }
956
957         if (ctx->pix.field == V4L2_FIELD_INTERLACED_TB) {
958                 switch (pixelformat) {
959                 case V4L2_PIX_FMT_YUV444:       /* fall through */
960                 case V4L2_PIX_FMT_RGB32:
961                         if (real->height % 2) {
962                                 fimc_err("SRC Real_H(%d): multiple of 2\n",
963                                                 real->height);
964                                 return -EINVAL;
965                         }
966                 case V4L2_PIX_FMT_YUV422P:
967                         if (real->height % 2) {
968                                 fimc_err("SRC Real_H(%d): multiple of 2\n",
969                                                 real->height);
970                                 return -EINVAL;
971                         } else if (real->width % 2) {
972                                 fimc_err("SRC Real_H(%d): multiple of 2\n",
973                                                 real->width);
974                                 return -EINVAL;
975                         }
976                 case V4L2_PIX_FMT_YVU420:
977                         if (real->height % 4) {
978                                 fimc_err("SRC Real_H(%d): multiple of 4\n",
979                                                 real->height);
980                                 return -EINVAL;
981                         } else if (real->width % 2) {
982                                 fimc_err("SRC Real_H(%d): multiple of 2\n",
983                                                 real->width);
984                                 return -EINVAL;
985                         }
986                 }
987         } else if (ctx->pix.field == V4L2_FIELD_NONE) {
988                 if (pixelformat == V4L2_PIX_FMT_YUV422P) {
989                         if (real->height % 2) {
990                                 fimc_err("SRC Real_H(%d): multiple of 2\n",
991                                                 real->height);
992                                 return -EINVAL;
993                         } else if (real->width % 2) {
994                                 fimc_err("SRC Real_H(%d): multiple of 2\n",
995                                                 real->width);
996                                 return -EINVAL;
997                         }
998                 }
999         }
1000
1001         return 0;
1002 }
1003
1004 static int fimc_outdev_set_src_dma_size(struct fimc_control *ctrl,
1005                                         struct fimc_ctx *ctx)
1006 {
1007         struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
1008         struct v4l2_rect real, org;
1009         int ret = 0;
1010
1011         real.width = ctx->crop.width;
1012         real.height = ctx->crop.height;
1013         org.width = ctx->pix.width;
1014         org.height = ctx->pix.height;
1015
1016         if (pdata->hw_ver >= 0x50)
1017                 ret = fimc50_outdev_check_src_size(ctrl, ctx, &real, &org);
1018         else
1019                 ret = fimc4x_outdev_check_src_size(ctrl, ctx, &real, &org);
1020
1021         if (ret < 0)
1022                 return ret;
1023
1024         fimc_hwset_org_input_size(ctrl, org.width, org.height);
1025         fimc_hwset_real_input_size(ctrl, real.width, real.height);
1026
1027         return 0;
1028 }
1029
1030 static void fimc_outdev_set_dst_dma_offset(struct fimc_control *ctrl,
1031                                            struct fimc_ctx *ctx)
1032 {
1033         struct v4l2_rect bound, win;
1034         struct v4l2_rect *w = &ctx->win.w;
1035         u32 pixfmt = ctx->fbuf.fmt.pixelformat;
1036
1037         memset(&bound, 0, sizeof(bound));
1038         memset(&win, 0, sizeof(win));
1039
1040         switch (ctx->rotate) {
1041         case 0:
1042                 bound.width = ctx->fbuf.fmt.width;
1043                 bound.height = ctx->fbuf.fmt.height;
1044
1045                 win.left = w->left;
1046                 win.top = w->top;
1047                 win.width = w->width;
1048                 win.height = w->height;
1049
1050                 break;
1051         case 90:
1052                 bound.width = ctx->fbuf.fmt.height;
1053                 bound.height = ctx->fbuf.fmt.width;
1054
1055                 win.left = ctx->fbuf.fmt.height - (w->height + w->top);
1056                 win.top = w->left;
1057                 win.width = w->height;
1058                 win.height = w->width;
1059
1060                 break;
1061         case 180:
1062                 bound.width = ctx->fbuf.fmt.width;
1063                 bound.height = ctx->fbuf.fmt.height;
1064
1065                 win.left = ctx->fbuf.fmt.width - (w->left + w->width);
1066                 win.top = ctx->fbuf.fmt.height - (w->top + w->height);
1067                 win.width = w->width;
1068                 win.height = w->height;
1069
1070                 break;
1071         case 270:
1072                 bound.width = ctx->fbuf.fmt.height;
1073                 bound.height = ctx->fbuf.fmt.width;
1074
1075                 win.left = ctx->win.w.top;
1076                 win.top = ctx->fbuf.fmt.width - (w->left + w->width);
1077                 win.width = w->height;
1078                 win.height = w->width;
1079
1080                 break;
1081         default:
1082                 fimc_err("Rotation degree is invalid(%d)\n", ctx->rotate);
1083                 break;
1084         }
1085
1086         switch (ctx->overlay.mode) {
1087         case FIMC_OVLY_FIFO:            /* fall through */
1088         case FIMC_OVLY_DMA_AUTO:        /* fall through */
1089         case FIMC_OVLY_DMA_MANUAL:
1090                 memset(&bound, 0, sizeof(bound));
1091                 memset(&win, 0, sizeof(win));
1092                 fimc_hwset_output_offset(ctrl, pixfmt, &bound, &win);
1093                 break;
1094         default:
1095                 fimc_hwset_output_offset(ctrl, pixfmt, &bound, &win);
1096                 break;
1097         }
1098
1099         fimc_dbg("bound:width(%d), height(%d)\n", bound.width, bound.height);
1100         fimc_dbg("win:width(%d), height(%d)\n", win.width, win.height);
1101         fimc_dbg("win:top(%d), left(%d)\n", win.top, win.left);
1102 }
1103
1104 static int fimc_outdev_check_dst_size(struct fimc_control *ctrl,
1105                                       struct fimc_ctx *ctx,
1106                                       struct v4l2_rect *real,
1107                                       struct v4l2_rect *org)
1108 {
1109         u32 rot = ctx->rotate;
1110         __u32 pixel_type;
1111
1112         pixel_type = fimc_get_pixel_format_type(ctx->fbuf.fmt.pixelformat);
1113
1114         if (FIMC_YUV420 == pixel_type && real->height % 2) {
1115                 fimc_err("DST Real_H(%d): even number for YUV420 formats\n",
1116                                 real->height);
1117                 return -EINVAL;
1118         }
1119
1120         if ((ctx->overlay.mode != FIMC_OVLY_FIFO) &&
1121             ((rot == 90) || (rot == 270))) {
1122                 /* Use Output Rotator */
1123                 if (org->height < real->width) {
1124                         fimc_err("DST Org_H: Org_H(%d) >= Real_W(%d)\n",
1125                                         org->height, real->width);
1126                         return -EINVAL;
1127                 }
1128
1129                 if (org->width < real->height) {
1130                         fimc_err("DST Org_W: Org_W(%d) >= Real_H(%d)\n",
1131                                         org->width, real->height);
1132                         return -EINVAL;
1133                 }
1134
1135                 if (real->height > ctrl->limit->trg_h_rot) {
1136                         fimc_err("DST REAL_H: Real_H(%d) <= %d\n", real->height,
1137                                         ctrl->limit->trg_h_rot);
1138                         return -EINVAL;
1139                 }
1140         } else if (ctx->overlay.mode != FIMC_OVLY_FIFO) {
1141                 /* No Output Rotator */
1142                 if (org->height < 8) {
1143                         fimc_err("DST Org_H(%d): Min 8\n", org->height);
1144                         return -EINVAL;
1145                 }
1146
1147                 if (org->height < real->height) {
1148                         fimc_err("DST Org_H: Org_H(%d) >= Real_H(%d)\n",
1149                                         org->height, real->height);
1150                         return -EINVAL;
1151                 }
1152                 /*
1153                 if (org->width % 8) {
1154                         fimc_err("DST Org_W: multiple of 8\n");
1155                         return -EINVAL;
1156                 }*/
1157
1158                 if (org->width < real->width) {
1159                         fimc_err("DST Org_W: Org_W(%d) >= Real_W(%d)\n",
1160                                         org->width, real->width);
1161                         return -EINVAL;
1162                 }
1163
1164                 if (real->height > ctrl->limit->trg_h_no_rot) {
1165                         fimc_err("DST REAL_H: Real_H(%d) <= %d\n", real->height,
1166                                         ctrl->limit->trg_h_no_rot);
1167                         return -EINVAL;
1168                 }
1169         }
1170
1171         return 0;
1172 }
1173
1174 static int fimc_outdev_set_dst_dma_size(struct fimc_control *ctrl,
1175                                         struct fimc_ctx *ctx)
1176 {
1177         struct v4l2_rect org, real;
1178         int ret = -1;
1179
1180         memset(&org, 0, sizeof(org));
1181         memset(&real, 0, sizeof(real));
1182
1183         switch (ctx->overlay.mode) {
1184         case FIMC_OVLY_NONE_MULTI_BUF:  /* fall through */
1185         case FIMC_OVLY_NONE_SINGLE_BUF:
1186                 real.width = ctx->win.w.width;
1187                 real.height = ctx->win.w.height;
1188
1189                 switch (ctx->rotate) {
1190                 case 0:         /* fall through */
1191                 case 180:
1192                         org.width = ctx->fbuf.fmt.width;
1193                         org.height = ctx->fbuf.fmt.height;
1194                         break;
1195                 case 90:        /* fall through */
1196                 case 270:
1197                         org.width = ctx->fbuf.fmt.height;
1198                         org.height = ctx->fbuf.fmt.width;
1199                         break;
1200                 default:
1201                         fimc_err("Rotation degree is invalid(%d)\n",
1202                                         ctx->rotate);
1203                         break;
1204                 }
1205
1206                 break;
1207
1208         case FIMC_OVLY_DMA_MANUAL:      /* fall through */
1209         case FIMC_OVLY_DMA_AUTO:
1210                 real.width = ctx->win.w.width;
1211                 real.height = ctx->win.w.height;
1212
1213                 switch (ctx->rotate) {
1214                 case 0:         /* fall through */
1215                 case 180:
1216                         org.width = ctx->win.w.width;
1217                         org.height = ctx->win.w.height;
1218                         break;
1219                 case 90:        /* fall through */
1220                 case 270:
1221                         org.width = ctx->win.w.height;
1222                         org.height = ctx->win.w.width;
1223                         break;
1224                 default:
1225                         fimc_err("Rotation degree is invalid(%d)\n",
1226                                         ctx->rotate);
1227                         break;
1228                 }
1229
1230                 break;
1231         case FIMC_OVLY_FIFO:
1232                 switch (ctx->rotate) {
1233                 case 0:         /* fall through */
1234                 case 180:
1235                         real.width = ctx->win.w.width;
1236                         real.height = ctx->win.w.height;
1237                         org.width = ctrl->fb.lcd_hres;
1238                         org.height = ctrl->fb.lcd_vres;
1239                         break;
1240                 case 90:        /* fall through */
1241                 case 270:
1242                         real.width = ctx->win.w.height;
1243                         real.height = ctx->win.w.width;
1244                         org.width = ctrl->fb.lcd_vres;
1245                         org.height = ctrl->fb.lcd_hres;
1246                         break;
1247
1248                 default:
1249                         fimc_err("Rotation degree is invalid(%d)\n",
1250                                         ctx->rotate);
1251                         break;
1252                 }
1253
1254                 break;
1255         default:
1256                 break;
1257         }
1258
1259         if (ctx->overlay.mode == FIMC_OVLY_DMA_AUTO)
1260                 fimc_outdev_dma_auto_dst_resize(&org);
1261
1262         fimc_dbg("DST org: width(%d), height(%d)\n", org.width, org.height);
1263         fimc_dbg("DST real: width(%d), height(%d)\n", real.width, real.height);
1264
1265         ret = fimc_outdev_check_dst_size(ctrl, ctx, &real, &org);
1266         if (ret < 0)
1267                 return ret;
1268
1269         fimc_hwset_output_size(ctrl, real.width, real.height);
1270         fimc_hwset_output_area(ctrl, real.width, real.height);
1271         fimc_hwset_org_output_size(ctrl, org.width, org.height);
1272         fimc_hwset_ext_output_size(ctrl, real.width, real.height);
1273
1274         return 0;
1275 }
1276
1277 static void fimc_outdev_calibrate_scale_info(struct fimc_control *ctrl,
1278                                              struct fimc_ctx *ctx,
1279                                              struct v4l2_rect *src,
1280                                              struct v4l2_rect *dst)
1281 {
1282         if (ctx->overlay.mode != FIMC_OVLY_FIFO) {
1283                 /* OUTPUT ROTATOR */
1284                 src->width = ctx->crop.width;
1285                 src->height = ctx->crop.height;
1286                 dst->width = ctx->win.w.width;
1287                 dst->height = ctx->win.w.height;
1288         } else {
1289                 /* INPUT ROTATOR */
1290                 switch (ctx->rotate) {
1291                 case 0:         /* fall through */
1292                 case 180:
1293                         src->width = ctx->crop.width;
1294                         src->height = ctx->crop.height;
1295                         dst->width = ctx->win.w.width;
1296                         dst->height = ctx->win.w.height;
1297                         break;
1298                 case 90:        /* fall through */
1299                 case 270:
1300                         src->width = ctx->crop.height;
1301                         src->height = ctx->crop.width;
1302                         dst->width = ctx->win.w.height;
1303                         dst->height = ctx->win.w.width;
1304                         break;
1305                 default:
1306                         fimc_err("Rotation degree is invalid(%d)\n",
1307                                         ctx->rotate);
1308                         break;
1309                 }
1310         }
1311
1312         fimc_dbg("src->width(%d), src->height(%d)\n", src->width, src->height);
1313         fimc_dbg("dst->width(%d), dst->height(%d)\n", dst->width, dst->height);
1314 }
1315
1316 static int fimc_outdev_check_scaler(struct fimc_control *ctrl,
1317                                     struct fimc_ctx *ctx,
1318                                     struct v4l2_rect *src,
1319                                     struct v4l2_rect *dst)
1320 {
1321         u32 pixels = 0, dstfmt = 0;
1322
1323         /* Check scaler limitation */
1324         if (ctx->sc.pre_dst_width > ctrl->limit->pre_dst_w) {
1325                 fimc_err("MAX PreDstWidth(%d) is %d\n", ctx->sc.pre_dst_width,
1326                                         ctrl->limit->pre_dst_w);
1327                 return -EDOM;
1328         }
1329
1330         /* SRC width double boundary check */
1331         switch (ctx->pix.pixelformat) {
1332         case V4L2_PIX_FMT_RGB32:
1333                 pixels = 1;
1334                 break;
1335         case V4L2_PIX_FMT_YUYV:         /* fall through */
1336         case V4L2_PIX_FMT_RGB565:
1337                 pixels = 2;
1338                 break;
1339         case V4L2_PIX_FMT_YUV420:       /* fall through */
1340         case V4L2_PIX_FMT_NV12:         /* fall through */
1341         case V4L2_PIX_FMT_NV21:         /* fall through */
1342         case V4L2_PIX_FMT_NV12T:
1343                 pixels = 8;
1344                 break;
1345         default:
1346                 fimc_err("Invalid color format(0x%x)\n", ctx->pix.pixelformat);
1347                 return -EINVAL;
1348         }
1349
1350         if (src->width % pixels) {
1351                 fimc_err("source width(%d) multiple of %d pixels\n", src->width,
1352                                 pixels);
1353                 return -EDOM;
1354         }
1355
1356         /* DST width double boundary check */
1357         switch (ctx->overlay.mode) {
1358         case FIMC_OVLY_FIFO:                    /* fall through */
1359         case FIMC_OVLY_DMA_AUTO:                /* fall through */
1360         case FIMC_OVLY_DMA_MANUAL:
1361                 dstfmt = V4L2_PIX_FMT_RGB32;
1362                 break;
1363         case FIMC_OVLY_NONE_SINGLE_BUF:         /* fall through */
1364         case FIMC_OVLY_NONE_MULTI_BUF:
1365                 dstfmt = ctx->fbuf.fmt.pixelformat;
1366                 break;
1367         default:
1368                 break;
1369         }
1370
1371         switch (dstfmt) {
1372         case V4L2_PIX_FMT_RGB32:
1373                 pixels = 1;
1374                 break;
1375         case V4L2_PIX_FMT_RGB565:
1376                 pixels = 2;
1377                 break;
1378         case V4L2_PIX_FMT_YUV420:       /* fall through */
1379         case V4L2_PIX_FMT_NV12:         /* fall through */
1380         case V4L2_PIX_FMT_NV21:         /* fall through */
1381         case V4L2_PIX_FMT_NV12T:
1382                 pixels = 8;
1383                 break;
1384         default:
1385                 fimc_err("Invalid color format(0x%x)\n", dstfmt);
1386                 return -EINVAL;
1387         }
1388
1389         if (dst->width % pixels) {
1390                 fimc_err("source width(%d) multiple of %d pixels\n",
1391                                 dst->width, pixels);
1392                 return -EDOM;
1393         }
1394
1395         return 0;
1396 }
1397
1398 static int fimc_outdev_set_scaler(struct fimc_control *ctrl,
1399                                   struct fimc_ctx *ctx)
1400 {
1401         struct v4l2_rect src, dst;
1402         int ret = 0;
1403         struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
1404
1405         memset(&src, 0, sizeof(src));
1406         memset(&dst, 0, sizeof(dst));
1407
1408         fimc_outdev_calibrate_scale_info(ctrl, ctx, &src, &dst);
1409
1410         ret = fimc_get_scaler_factor(src.width, dst.width,
1411                         &ctx->sc.pre_hratio, &ctx->sc.hfactor);
1412         if (ret < 0) {
1413                 fimc_err("Fail : Out of Width scale range(%d, %d)\n",
1414                                 src.width, dst.width);
1415                 return ret;
1416         }
1417
1418         ret = fimc_get_scaler_factor(src.height, dst.height,
1419                         &ctx->sc.pre_vratio, &ctx->sc.vfactor);
1420         if (ret < 0) {
1421                 fimc_err("Fail : Out of Height scale range(%d, %d)\n",
1422                                 src.height, dst.height);
1423                 return ret;
1424         }
1425
1426         ctx->sc.pre_dst_width = src.width / ctx->sc.pre_hratio;
1427         ctx->sc.pre_dst_height = src.height / ctx->sc.pre_vratio;
1428
1429         if (pdata->hw_ver >= 0x50) {
1430                 ctx->sc.main_hratio = (src.width << 14) /
1431                                         (dst.width << ctx->sc.hfactor);
1432                 ctx->sc.main_vratio = (src.height << 14) /
1433                                         (dst.height << ctx->sc.vfactor);
1434         } else {
1435                 ctx->sc.main_hratio = (src.width << 8) /
1436                                         (dst.width << ctx->sc.hfactor);
1437                 ctx->sc.main_vratio = (src.height << 8) /
1438                                         (dst.height << ctx->sc.vfactor);
1439         }
1440
1441         fimc_dbg("pre_hratio(%d), hfactor(%d), pre_vratio(%d), vfactor(%d)\n",
1442                 ctx->sc.pre_hratio, ctx->sc.hfactor,
1443                 ctx->sc.pre_vratio, ctx->sc.vfactor);
1444
1445
1446         fimc_dbg("pre_dst_width(%d), main_hratio(%d), "
1447                 "pre_dst_height(%d), main_vratio(%d)\n",
1448                 ctx->sc.pre_dst_width, ctx->sc.main_hratio,
1449                 ctx->sc.pre_dst_height, ctx->sc.main_vratio);
1450
1451         ctx->sc.bypass = 0;     /* Input DMA cannot support scaler bypass. */
1452         ctx->sc.scaleup_h = (dst.width >= src.width) ? 1 : 0;
1453         ctx->sc.scaleup_v = (dst.height >= src.height) ? 1 : 0;
1454         ctx->sc.shfactor = 10 - (ctx->sc.hfactor + ctx->sc.vfactor);
1455
1456         if (pdata->hw_ver < 0x50) {
1457                 ret = fimc_outdev_check_scaler(ctrl, ctx, &src, &dst);
1458                 if (ret < 0)
1459                         return ret;
1460         }
1461
1462         fimc_hwset_prescaler(ctrl, &ctx->sc);
1463         fimc_hwset_scaler(ctrl, &ctx->sc);
1464
1465         return 0;
1466 }
1467
1468 int fimc_outdev_set_ctx_param(struct fimc_control *ctrl, struct fimc_ctx *ctx)
1469 {
1470         int ret;
1471 #if defined(CONFIG_VIDEO_IPC)
1472         u32 use_ipc = 0;
1473         struct v4l2_rect src, dst;
1474         memset(&src, 0, sizeof(src));
1475         memset(&dst, 0, sizeof(dst));
1476 #endif
1477
1478         if ((ctrl->status == FIMC_READY_ON) ||
1479                         (ctrl->status == FIMC_STREAMON_IDLE))
1480                 fimc_hwset_enable_irq(ctrl, 0, 1);
1481
1482 #if (defined(CONFIG_S5PV310_DEV_PD) && defined(CONFIG_PM_RUNTIME))
1483         fimc_hwset_output_buf_sequence_all(ctrl, FRAME_SEQ);
1484 #endif
1485
1486         fimc_outdev_set_format(ctrl, ctx);
1487         fimc_outdev_set_path(ctrl, ctx);
1488         fimc_outdev_set_rot(ctrl, ctx);
1489
1490         fimc_outdev_set_src_dma_offset(ctrl, ctx);
1491         ret = fimc_outdev_set_src_dma_size(ctrl, ctx);
1492         if (ret < 0)
1493                 return ret;
1494
1495         fimc_outdev_set_dst_dma_offset(ctrl, ctx);
1496
1497         ret = fimc_outdev_set_dst_dma_size(ctrl, ctx);
1498         if (ret < 0)
1499                 return ret;
1500
1501         ret = fimc_outdev_set_scaler(ctrl, ctx);
1502         if (ret < 0)
1503                 return ret;
1504
1505 #if defined(CONFIG_VIDEO_IPC)
1506         if (ctx->overlay.mode == FIMC_OVLY_FIFO)
1507                 if (ctx->pix.field == V4L2_FIELD_INTERLACED_TB)
1508                         use_ipc = 1;
1509
1510         if (use_ipc) {
1511                 fimc_outdev_calibrate_scale_info(ctrl, ctx, &src, &dst);
1512                 ret = ipc_init(dst.width, dst.height/2, IPC_2D);
1513                 if (ret < 0)
1514                         return ret;
1515         }
1516 #endif
1517
1518         return 0;
1519 }
1520
1521 int fimc_fimd_rect(const struct fimc_control *ctrl,
1522                    const struct fimc_ctx *ctx,
1523                    struct v4l2_rect *fimd_rect)
1524 {
1525         switch (ctx->rotate) {
1526         case 0:
1527                 fimd_rect->left = ctx->win.w.left;
1528                 fimd_rect->top = ctx->win.w.top;
1529                 fimd_rect->width = ctx->win.w.width;
1530                 fimd_rect->height = ctx->win.w.height;
1531
1532                 break;
1533
1534         case 90:
1535                 fimd_rect->left = ctrl->fb.lcd_hres -
1536                                 (ctx->win.w.top + ctx->win.w.height);
1537                 fimd_rect->top = ctx->win.w.left;
1538                 fimd_rect->width = ctx->win.w.height;
1539                 fimd_rect->height = ctx->win.w.width;
1540
1541                 break;
1542
1543         case 180:
1544                 fimd_rect->left = ctrl->fb.lcd_hres -
1545                                 (ctx->win.w.left + ctx->win.w.width);
1546                 fimd_rect->top = ctrl->fb.lcd_vres -
1547                                 (ctx->win.w.top + ctx->win.w.height);
1548                 fimd_rect->width = ctx->win.w.width;
1549                 fimd_rect->height = ctx->win.w.height;
1550
1551                 break;
1552
1553         case 270:
1554                 fimd_rect->left = ctx->win.w.top;
1555                 fimd_rect->top = ctrl->fb.lcd_vres -
1556                                 (ctx->win.w.left + ctx->win.w.width);
1557                 fimd_rect->width = ctx->win.w.height;
1558                 fimd_rect->height = ctx->win.w.width;
1559
1560                 break;
1561
1562         default:
1563                 fimc_err("Rotation degree is invalid(%d)\n", ctx->rotate);
1564                 return -EINVAL;
1565
1566                 break;
1567         }
1568
1569         return 0;
1570 }
1571
1572 int fimc_start_fifo(struct fimc_control *ctrl, struct fimc_ctx *ctx)
1573 {
1574         struct v4l2_rect fimd_rect;
1575         struct fb_var_screeninfo var;
1576         struct s3cfb_user_window window;
1577         int ret = -1;
1578         int window_id = ((ctrl->id == 3) ? 2 : ctrl->id);
1579
1580         memset(&fimd_rect, 0, sizeof(struct v4l2_rect));
1581         ret = fimc_fimd_rect(ctrl, ctx, &fimd_rect);
1582         if (ret < 0) {
1583                 fimc_err("fimc_fimd_rect fail\n");
1584                 return -EINVAL;
1585         }
1586
1587         /* Get WIN var_screeninfo */
1588         ret = s3cfb_direct_ioctl(window_id, FBIOGET_VSCREENINFO,
1589                                                 (unsigned long)&var);
1590         if (ret < 0) {
1591                 fimc_err("direct_ioctl(FBIOGET_VSCREENINFO) fail\n");
1592                 return -EINVAL;
1593         }
1594
1595         /* Don't allocate the memory. */
1596         if (ctx->pix.field == V4L2_FIELD_NONE)
1597                 ret = s3cfb_direct_ioctl(window_id,
1598                                         S3CFB_SET_WIN_PATH, DATA_PATH_FIFO);
1599         else if (ctx->pix.field == V4L2_FIELD_INTERLACED_TB)
1600                 ret = s3cfb_direct_ioctl(window_id,
1601                                         S3CFB_SET_WIN_PATH, DATA_PATH_IPC);
1602         if (ret < 0) {
1603                 fimc_err("direct_ioctl(S3CFB_SET_WIN_PATH) fail\n");
1604                 return -EINVAL;
1605         }
1606
1607         ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_MEM, DMA_MEM_NONE);
1608         if (ret < 0) {
1609                 fimc_err("direct_ioctl(S3CFB_SET_WIN_MEM) fail\n");
1610                 return -EINVAL;
1611         }
1612
1613         ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_ADDR, 0x00000000);
1614         if (ret < 0) {
1615                 fimc_err("direct_ioctl(S3CFB_SET_WIN_ADDR) fail\n");
1616                 return -EINVAL;
1617         }
1618
1619         /* Update WIN size */
1620         var.xres_virtual = fimd_rect.width;
1621         var.yres_virtual = fimd_rect.height;
1622         var.xres = fimd_rect.width;
1623         var.yres = fimd_rect.height;
1624         ret = s3cfb_direct_ioctl(window_id, FBIOPUT_VSCREENINFO,
1625                                         (unsigned long)&var);
1626         if (ret < 0) {
1627                 fimc_err("direct_ioctl(FBIOPUT_VSCREENINFO) fail\n");
1628                 return -EINVAL;
1629         }
1630
1631         /* Update WIN position */
1632         window.x = fimd_rect.left;
1633         window.y = fimd_rect.top;
1634         ret = s3cfb_direct_ioctl(window_id, S3CFB_WIN_POSITION,
1635                         (unsigned long)&window);
1636         if (ret < 0) {
1637                 fimc_err("direct_ioctl(S3CFB_WIN_POSITION) fail\n");
1638                 return -EINVAL;
1639         }
1640
1641         /* Open WIN FIFO */
1642         ret = ctrl->fb.open_fifo(window_id, 0, fimc_outdev_start_camif, (void *)ctrl);
1643         if (ret < 0) {
1644                 fimc_err("FIMD FIFO close fail\n");
1645                 return -EINVAL;
1646         }
1647
1648         return 0;
1649 }
1650
1651 int fimc_outdev_overlay_buf(struct file *filp,
1652                             struct fimc_control *ctrl,
1653                             struct fimc_ctx *ctx)
1654 {
1655         int ret = 0, i;
1656         struct fimc_overlay_buf *buf;
1657
1658         buf = &ctx->overlay.buf;
1659
1660         for (i = 0; i < FIMC_OUTBUFS; i++) {
1661                 ctx->overlay.req_idx = i;
1662                 buf->size[i] = ctx->dst[i].length[0];
1663                 buf->phy_addr[i] = ctx->dst[i].base[0];
1664                 buf->vir_addr[i] = do_mmap(filp, 0, buf->size[i],
1665                                         PROT_READ|PROT_WRITE, MAP_SHARED, 0);
1666                 if (buf->vir_addr[i] == -EINVAL) {
1667                         fimc_err("%s: fail\n", __func__);
1668                         return -EINVAL;
1669                 }
1670
1671                 fimc_dbg("idx : %d, size(0x%08x), phy_addr(0x%08x), "
1672                                 "vir_addr(0x%08x)\n", i, buf->size[i],
1673                                 buf->phy_addr[i], buf->vir_addr[i]);
1674         }
1675
1676         ctx->overlay.req_idx = -1;
1677
1678         return ret;
1679 }
1680
1681 int fimc_reqbufs_output(void *fh, struct v4l2_requestbuffers *b)
1682 {
1683         struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
1684         struct fimc_ctx *ctx;
1685         struct fimc_overlay_buf *buf;
1686         struct mm_struct *mm = current->mm;
1687         enum fimc_overlay_mode mode;
1688         int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
1689         int ret = -1, i;
1690
1691         ctx = &ctrl->out->ctx[ctx_id];
1692         buf = &ctx->overlay.buf;
1693         mode = ctx->overlay.mode;
1694
1695         fimc_info1("%s: called\n", __func__);
1696
1697         if (ctx->status != FIMC_STREAMOFF) {
1698                 fimc_err("%s: FIMC is running\n", __func__);
1699                 return -EBUSY;
1700         }
1701
1702         if (ctx->is_requested == 1 && b->count != 0) {
1703                 fimc_err("Buffers were already requested\n");
1704                 return -EBUSY;
1705         }
1706
1707         if (b->count > FIMC_OUTBUFS) {
1708                 fimc_warn("The buffer count is modified by driver "
1709                                 "from %d to %d\n", b->count, FIMC_OUTBUFS);
1710                 b->count = FIMC_OUTBUFS;
1711         }
1712
1713 #if (!defined(CONFIG_S5PV310_DEV_PD) || !defined(CONFIG_PM_RUNTIME))
1714         fimc_hwset_output_buf_sequence_all(ctrl, FRAME_SEQ);
1715 #endif
1716
1717         fimc_init_out_buf(ctx);
1718         ctx->is_requested = 0;
1719
1720         if (b->count == 0) {
1721                 ctrl->mem.curr = ctrl->mem.base;
1722
1723                 switch (ctx->overlay.mode) {
1724                 case FIMC_OVLY_DMA_AUTO:        /* fall through */
1725                 case FIMC_OVLY_DMA_MANUAL:
1726                         for (i = 0; i < FIMC_OUTBUFS; i++) {
1727                                 if (buf->vir_addr[i]) {
1728                                         ret = do_munmap(mm,
1729                                                         buf->vir_addr[i],
1730                                                         buf->size[i]);
1731                                         if (ret < 0)
1732                                                 fimc_err("%s: do_munmap fail. "
1733                                                 "vir_addr[%d](0x%08x)\n",
1734                                                 __func__, i, buf->vir_addr[i]);
1735                                 }
1736                         }
1737                         break;
1738                 default:
1739                         break;
1740                 }
1741         } else {
1742                 /* initialize source buffers */
1743                 if (b->memory == V4L2_MEMORY_MMAP) {
1744                         ret = fimc_outdev_set_src_buf(ctrl, ctx);
1745                         ctx->overlay.req_idx = FIMC_MMAP_IDX;
1746                         if (ret)
1747                                 return ret;
1748                 } else if (b->memory == V4L2_MEMORY_USERPTR) {
1749                         if (mode == FIMC_OVLY_DMA_AUTO ||
1750                                         mode == FIMC_OVLY_NOT_FIXED)
1751                                 ctx->overlay.req_idx = FIMC_USERPTR_IDX;
1752                 }
1753
1754                 ctx->is_requested = 1;
1755         }
1756
1757         ctx->buf_num = b->count;
1758
1759         return 0;
1760 }
1761
1762 int fimc_querybuf_output(void *fh, struct v4l2_buffer *b)
1763 {
1764         struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
1765         struct fimc_ctx *ctx;
1766         int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
1767         u32 buf_length = 0;
1768
1769         fimc_info1("%s: called\n", __func__);
1770
1771         ctx = &ctrl->out->ctx[ctx_id];
1772         if (ctx->status != FIMC_STREAMOFF) {
1773                 fimc_err("%s: FIMC is running\n", __func__);
1774                 return -EBUSY;
1775         }
1776
1777         if (b->index > ctx->buf_num) {
1778                 fimc_err("The index is out of bounds. You requested %d buffers."
1779                         "But requested index is %d\n", ctx->buf_num, b->index);
1780                 return -EINVAL;
1781         }
1782
1783         b->flags = ctx->src[b->index].flags;
1784         b->m.offset = b->index * PAGE_SIZE;
1785         buf_length = ctx->src[b->index].length[FIMC_ADDR_Y] +
1786                 ctx->src[b->index].length[FIMC_ADDR_CB] +
1787                 ctx->src[b->index].length[FIMC_ADDR_CR];
1788         b->length = PAGE_ALIGN(buf_length);
1789
1790         return 0;
1791 }
1792
1793 int fimc_g_ctrl_output(void *fh, struct v4l2_control *c)
1794 {
1795         struct fimc_ctx *ctx;
1796         struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
1797         int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
1798         struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
1799         ctx = &ctrl->out->ctx[ctx_id];
1800
1801         if (ctx->status != FIMC_STREAMOFF) {
1802                 fimc_err("%s: FIMC is running\n", __func__);
1803                 return -EBUSY;
1804         }
1805
1806         switch (c->id) {
1807         case V4L2_CID_ROTATION:
1808                 c->value = ctx->rotate;
1809                 break;
1810
1811         case V4L2_CID_HFLIP:
1812                 if (ctx->flip & V4L2_CID_HFLIP)
1813                         c->value = 1;
1814                 else
1815                         c->value = 0;
1816                 break;
1817
1818         case V4L2_CID_VFLIP:
1819                 if (ctx->flip & V4L2_CID_VFLIP)
1820                         c->value = 1;
1821                 else
1822                         c->value = 0;
1823                 break;
1824
1825 #ifdef CONFIG_VIDEO_FIMC_UMP_VCM_CMA
1826         case V4L2_CID_GET_UMP_SECURE_ID:
1827         {
1828                 ump_secure_id secure_id =
1829                         ump_dd_secure_id_get(ctrl->ump_wrapped_buffer);
1830                 c->id = secure_id;
1831                 fimc_info1("%s : ump_secure_id : %d\n", __func__, secure_id);
1832                 break;
1833         }
1834 #endif
1835         case V4L2_CID_OVERLAY_VADDR0:
1836                 c->value = ctx->overlay.buf.vir_addr[0];
1837                 break;
1838
1839         case V4L2_CID_OVERLAY_VADDR1:
1840                 c->value = ctx->overlay.buf.vir_addr[1];
1841                 break;
1842
1843         case V4L2_CID_OVERLAY_VADDR2:
1844                 c->value = ctx->overlay.buf.vir_addr[2];
1845                 break;
1846
1847         case V4L2_CID_OVERLAY_AUTO:
1848                 if (ctx->overlay.mode == FIMC_OVLY_DMA_AUTO)
1849                         c->value = 1;
1850                 else
1851                         c->value = 0;
1852                 break;
1853
1854         case V4L2_CID_RESERVED_MEM_BASE_ADDR:
1855                 c->value = ctrl->mem.base;
1856                 break;
1857
1858         case V4L2_CID_FIMC_VERSION:
1859                 c->value = pdata->hw_ver;
1860                 break;
1861
1862         default:
1863                 fimc_err("Invalid control id: %d\n", c->id);
1864                 return -EINVAL;
1865         }
1866
1867         return 0;
1868 }
1869
1870 static int fimc_set_dst_info(struct fimc_control *ctrl,
1871                              struct fimc_ctx *ctx,
1872                              struct fimc_buf *fimc_buf)
1873 {
1874         struct fimc_buf *buf;
1875         int i;
1876 #ifdef SYSMMU_FIMC
1877         struct vcm_res *vcm_res;
1878 #endif
1879
1880         for (i = 0; i < ctx->buf_num; i++) {
1881                 buf = &fimc_buf[i];
1882 #ifdef SYSMMU_FIMC
1883                 vcm_res = (struct vcm_res *)ump_dd_vcm_res_get(
1884                         (unsigned int)buf->base[FIMC_ADDR_Y], ctrl->vcm_id);
1885
1886                 if (vcm_res)
1887                         buf->base[FIMC_ADDR_Y] = vcm_res->start;
1888                 else
1889                         return -EINVAL;
1890                 ctx->dst[i].base[FIMC_ADDR_Y] = buf->base[FIMC_ADDR_Y];
1891                 ctx->dst[i].length[FIMC_ADDR_Y] = buf->length[FIMC_ADDR_Y];
1892
1893                 ctx->dst[i].base[FIMC_ADDR_CB] = \
1894                 ctx->dst[i].base[FIMC_ADDR_Y] + buf->base[FIMC_ADDR_CB];
1895                 ctx->dst[i].length[FIMC_ADDR_CB] = buf->length[FIMC_ADDR_CB];
1896
1897                 ctx->dst[i].base[FIMC_ADDR_CR] = \
1898                 ctx->dst[i].base[FIMC_ADDR_CB] + buf->base[FIMC_ADDR_CR];
1899                 ctx->dst[i].length[FIMC_ADDR_CR] = buf->length[FIMC_ADDR_CR];
1900 #else
1901                 ctx->dst[i].base[FIMC_ADDR_Y] = buf->base[FIMC_ADDR_Y];
1902                 ctx->dst[i].length[FIMC_ADDR_Y] = buf->length[FIMC_ADDR_Y];
1903
1904                 ctx->dst[i].base[FIMC_ADDR_CB] = buf->base[FIMC_ADDR_CB];
1905                 ctx->dst[i].length[FIMC_ADDR_CB] = buf->length[FIMC_ADDR_CB];
1906
1907                 ctx->dst[i].base[FIMC_ADDR_CR] = buf->base[FIMC_ADDR_CR];
1908                 ctx->dst[i].length[FIMC_ADDR_CR] = buf->length[FIMC_ADDR_CR];
1909 #endif
1910         }
1911
1912         for (i = ctx->buf_num; i < FIMC_OUTBUFS; i++) {
1913                 ctx->dst[i].base[FIMC_ADDR_Y] = 0;
1914                 ctx->dst[i].length[FIMC_ADDR_Y] = 0;
1915
1916                 ctx->dst[i].base[FIMC_ADDR_CB] = 0;
1917                 ctx->dst[i].length[FIMC_ADDR_CB] = 0;
1918
1919                 ctx->dst[i].base[FIMC_ADDR_CR] = 0;
1920                 ctx->dst[i].length[FIMC_ADDR_CR] = 0;
1921         }
1922
1923         /* for debugging */
1924         for (i = 0; i < FIMC_OUTBUFS; i++) {
1925                 fimc_dbg("dst[%d]: base[0]=0x%08x, size[0]=0x%08x\n",
1926                         i, ctx->dst[i].base[0], ctx->dst[i].length[0]);
1927
1928                 fimc_dbg("dst[%d]: base[1]=0x%08x, size[1]=0x%08x\n",
1929                         i, ctx->dst[i].base[1], ctx->dst[i].length[2]);
1930
1931                 fimc_dbg("dst[%d]: base[2]=0x%08x, size[2]=0x%08x\n",
1932                         i, ctx->dst[i].base[1], ctx->dst[i].length[2]);
1933         }
1934
1935         return 0;
1936 }
1937 int fimc_s_ctrl_output(struct file *filp, void *fh, struct v4l2_control *c)
1938 {
1939         struct fimc_ctx *ctx;
1940         struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
1941         int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
1942         int ret = 0;
1943
1944         ctx = &ctrl->out->ctx[ctx_id];
1945         if (ctx->status != FIMC_STREAMOFF) {
1946                 fimc_err("%s: FIMC is running\n", __func__);
1947                 return -EBUSY;
1948         }
1949
1950         switch (c->id) {
1951         case V4L2_CID_ROTATION:
1952                 ret = fimc_set_rot_degree(ctrl, ctx, c->value);
1953
1954                 break;
1955         case V4L2_CID_HFLIP:
1956                 if (c->value)
1957                         ctx->flip |= FIMC_XFLIP;
1958                 else
1959                         ctx->flip &= ~FIMC_XFLIP;
1960
1961                 break;
1962         case V4L2_CID_VFLIP:
1963                 if (c->value)
1964                         ctx->flip |= FIMC_YFLIP;
1965                 else
1966                         ctx->flip &= ~FIMC_YFLIP;
1967
1968                 break;
1969         case V4L2_CID_OVERLAY_AUTO:
1970                 if (c->value == 1) {
1971                         ctx->overlay.mode = FIMC_OVLY_DMA_AUTO;
1972                 } else {
1973                         ctx->overlay.mode = FIMC_OVLY_DMA_MANUAL;
1974                         ret = fimc_outdev_set_dst_buf(ctrl, ctx);
1975                         fimc_outdev_overlay_buf(filp, ctrl, ctx);
1976                 }
1977
1978                 break;
1979         case V4L2_CID_OVLY_MODE:
1980                 ctx->overlay.mode = c->value;
1981
1982                 break;
1983         case V4L2_CID_DST_INFO:
1984                 ret = fimc_set_dst_info(ctrl, ctx,
1985                                         (struct fimc_buf *)c->value);
1986                 break;
1987         case V4L2_CID_GET_PHY_SRC_YADDR:
1988                 c->value = ctx->src[c->value].base[FIMC_ADDR_Y];
1989                 break;
1990         case V4L2_CID_GET_PHY_SRC_CADDR:
1991                 c->value = ctx->src[c->value].base[FIMC_ADDR_CB];
1992                 break;
1993         default:
1994                 fimc_err("Invalid control id: %d\n", c->id);
1995                 ret = -EINVAL;
1996         }
1997
1998         return ret;
1999 }
2000
2001 int fimc_cropcap_output(void *fh, struct v4l2_cropcap *a)
2002 {
2003         struct fimc_ctx *ctx;
2004         struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
2005         int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
2006         u32 is_rotate = 0, max_w = 0, max_h = 0, pixelformat;
2007
2008         fimc_info1("%s: called\n", __func__);
2009
2010         ctx = &ctrl->out->ctx[ctx_id];
2011         pixelformat = ctx->pix.pixelformat;
2012         if (ctx->status != FIMC_STREAMOFF) {
2013                 fimc_err("%s: FIMC is running\n", __func__);
2014                 return -EBUSY;
2015         }
2016
2017         is_rotate = fimc_mapping_rot_flip(ctx->rotate, ctx->flip);
2018         switch (pixelformat) {
2019         case V4L2_PIX_FMT_NV12:         /* fall through */
2020         case V4L2_PIX_FMT_NV21:         /* fall through */
2021         case V4L2_PIX_FMT_NV12T:        /* fall through */
2022         case V4L2_PIX_FMT_YUYV:         /* fall through */
2023         case V4L2_PIX_FMT_YUV420:       /* fall through */
2024                 max_w = FIMC_SRC_MAX_W;
2025                 max_h = FIMC_SRC_MAX_H;
2026         case V4L2_PIX_FMT_RGB32:        /* fall through */
2027         case V4L2_PIX_FMT_RGB565:       /* fall through */
2028                 if (is_rotate & FIMC_ROT) {             /* Landscape mode */
2029                         max_w = ctrl->fb.lcd_vres;
2030                         max_h = ctrl->fb.lcd_hres;
2031                 } else {                                /* Portrait */
2032                         max_w = ctrl->fb.lcd_hres;
2033                         max_h = ctrl->fb.lcd_vres;
2034                 }
2035
2036                 break;
2037         default:
2038                 fimc_warn("Supported format : V4L2_PIX_FMT_YUYV, "
2039                         "V4L2_PIX_FMT_NV12, V4L2_PIX_FMT_NV12T, "
2040                         "V4L2_PIX_FMT_RGB32, V4L2_PIX_FMT_RGB565\n");
2041                 return -EINVAL;
2042         }
2043
2044         /* crop bounds */
2045         ctx->cropcap.bounds.left = 0;
2046         ctx->cropcap.bounds.top = 0;
2047         ctx->cropcap.bounds.width = max_w;
2048         ctx->cropcap.bounds.height = max_h;
2049
2050         /* crop default values */
2051         ctx->cropcap.defrect.left = 0;
2052         ctx->cropcap.defrect.top = 0;
2053         ctx->cropcap.defrect.width = max_w;
2054         ctx->cropcap.defrect.height = max_h;
2055
2056         /* crop pixel aspec values */
2057         /* To Do : Have to modify but I don't know the meaning. */
2058         ctx->cropcap.pixelaspect.numerator = 16;
2059         ctx->cropcap.pixelaspect.denominator = 9;
2060
2061         a->bounds = ctx->cropcap.bounds;
2062         a->defrect = ctx->cropcap.defrect;
2063         a->pixelaspect = ctx->cropcap.pixelaspect;
2064
2065         return 0;
2066 }
2067
2068 int fimc_g_crop_output(void *fh, struct v4l2_crop *a)
2069 {
2070         struct fimc_ctx *ctx;
2071         struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
2072         int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
2073
2074         ctx = &ctrl->out->ctx[ctx_id];
2075
2076         fimc_info1("%s: called\n", __func__);
2077
2078         mutex_lock(&ctrl->v4l2_lock);
2079         a->c.left   = ctx->crop.left;
2080         a->c.top    = ctx->crop.top;
2081         a->c.width  = ctx->crop.width;
2082         a->c.height = ctx->crop.height;
2083         mutex_unlock(&ctrl->v4l2_lock);
2084
2085         return 0;
2086 }
2087
2088 int fimc_s_crop_output(void *fh, struct v4l2_crop *a)
2089 {
2090         struct fimc_ctx *ctx;
2091         struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
2092         int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
2093
2094         fimc_info1("%s: called: left(%d), top(%d), width(%d), height(%d),\n",
2095                 __func__, a->c.left, a->c.top, a->c.width, a->c.height);
2096
2097         ctx = &ctrl->out->ctx[ctx_id];
2098         if (ctx->status != FIMC_STREAMOFF) {
2099                 fimc_err("%s: FIMC is running\n", __func__);
2100                 return -EBUSY;
2101         }
2102
2103         /* Check arguments : widht and height */
2104         if ((a->c.width < 0) || (a->c.height < 0)) {
2105                 fimc_err("The crop rect must be bigger than 0\n");
2106                 fimc_err("width = %d, height = %d\n", a->c.width, a->c.height);
2107                 return -EINVAL;
2108         }
2109
2110         if ((a->c.width > FIMC_SRC_MAX_W) || (a->c.height > FIMC_SRC_MAX_H)) {
2111                 fimc_err("The crop width/height must be smaller than "
2112                         "%d and %d\n", FIMC_SRC_MAX_W, FIMC_SRC_MAX_H);
2113                 fimc_err("width = %d, height = %d\n", a->c.width, a->c.height);
2114                 return -EINVAL;
2115         }
2116
2117         /* Check arguments : left and top */
2118         if ((a->c.left < 0) || (a->c.top < 0)) {
2119                 fimc_err("The crop left, top must be  bigger than 0\n");
2120                 fimc_err("left = %d, top = %d\n", a->c.left, a->c.top);
2121                 return -EINVAL;
2122         }
2123
2124         if ((a->c.left > FIMC_SRC_MAX_W) || (a->c.top > FIMC_SRC_MAX_H)) {
2125                 fimc_err("The crop left, top must be smaller than %d, %d\n",
2126                         FIMC_SRC_MAX_W, FIMC_SRC_MAX_H);
2127                 fimc_err("left = %d, top = %d\n", a->c.left, a->c.top);
2128                 return -EINVAL;
2129         }
2130
2131         if ((a->c.left + a->c.width) > FIMC_SRC_MAX_W) {
2132                 fimc_err("The crop rect must be in bound rect\n");
2133                 fimc_err("left = %d, width = %d\n", a->c.left, a->c.width);
2134                 return -EINVAL;
2135         }
2136
2137         if ((a->c.top + a->c.height) > FIMC_SRC_MAX_H) {
2138                 fimc_err("The crop rect must be in bound rect\n");
2139                 fimc_err("top = %d, width = %d\n", a->c.top, a->c.height);
2140                 return -EINVAL;
2141         }
2142
2143         ctx->crop.left = a->c.left;
2144         ctx->crop.top = a->c.top;
2145         ctx->crop.width = a->c.width;
2146         ctx->crop.height = a->c.height;
2147
2148         return 0;
2149 }
2150
2151 int fimc_streamon_output(void *fh)
2152 {
2153         struct fimc_ctx *ctx;
2154         struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
2155         int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
2156         int ret = -1;
2157
2158         ctrl->log |= FIMC_LOG_INFO_L1;
2159         fimc_info1("%s: called\n", __func__);
2160
2161         ctx = &ctrl->out->ctx[ctx_id];
2162         if (ctx->overlay.mode == FIMC_OVLY_NOT_FIXED)
2163                 ctx->overlay.mode = FIMC_OVLY_MODE;
2164
2165         /* initialize destination buffers */
2166         if (ctx->overlay.mode == FIMC_OVLY_DMA_AUTO) {
2167                 ret = fimc_outdev_set_dst_buf(ctrl, ctx);
2168                 if (ret)
2169                         return ret;
2170         }
2171
2172         ret = fimc_outdev_check_param(ctrl, ctx);
2173         if (ret < 0) {
2174                 fimc_err("Fail: fimc_outdev_check_param\n");
2175                 return ret;
2176         }
2177
2178         ctx->status = FIMC_READY_ON;
2179         if (ctrl->status == FIMC_STREAMOFF)
2180                 ctrl->status = FIMC_READY_ON;
2181
2182         ctrl->log &= ~(FIMC_LOG_INFO_L1);
2183         return ret;
2184 }
2185
2186 void fimc_outdev_init_idxs(struct fimc_control *ctrl)
2187 {
2188         ctrl->out->idxs.prev.ctx = -1;
2189         ctrl->out->idxs.prev.idx = -1;
2190         ctrl->out->idxs.active.ctx = -1;
2191         ctrl->out->idxs.active.idx = -1;
2192         ctrl->out->idxs.next.ctx = -1;
2193         ctrl->out->idxs.next.idx = -1;
2194 }
2195
2196 int fimc_streamoff_output(void *fh)
2197 {
2198         struct fimc_ctx *ctx;
2199         struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
2200         int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
2201         int ret = -1, i = 0, off_cnt = 0;
2202         struct s3cfb_user_window window;
2203         int window_id = ((ctrl->id == 3) ? 2 : ctrl->id);
2204
2205         ctrl->log |= FIMC_LOG_INFO_L1;
2206         fimc_info1("%s: called\n", __func__);
2207
2208         ctx = &ctrl->out->ctx[ctx_id];
2209         /* Move it to here to ignore fimc_irq_out_dma operation. */
2210         ctx->status = FIMC_STREAMOFF;
2211
2212         if (ctx->overlay.mode == FIMC_OVLY_DMA_AUTO ||
2213                         ctx->overlay.mode == FIMC_OVLY_DMA_MANUAL) {
2214 #if (!defined(CONFIG_S5PV310_DEV_PD) || !defined(CONFIG_PM_RUNTIME))
2215                 ret = fimc_outdev_stop_streaming(ctrl, ctx);
2216                 if (ret < 0) {
2217                         fimc_err("Fail: fimc_outdev_stop_streaming\n");
2218                         return -EINVAL;
2219                 }
2220 #else
2221                 /* Need some delay to waiting reamined operation */
2222                 msleep(100);
2223
2224                 ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_OFF,
2225                         (unsigned long)NULL);
2226                 if (ret < 0) {
2227                         fimc_err("direct_ioctl(S3CFB_SET_WIN_OFF) fail\n");
2228                         return -EINVAL;
2229                 }
2230
2231                 /* reset WIN position */
2232                 memset(&window, 0, sizeof(window));
2233                 ret = s3cfb_direct_ioctl(window_id, S3CFB_WIN_POSITION,
2234                                 (unsigned long)&window);
2235                 if (ret < 0) {
2236                         fimc_err("direct_ioctl(S3CFB_WIN_POSITION) fail\n");
2237                         return -EINVAL;
2238                 }
2239
2240                 ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_ADDR, 0x00000000);
2241                 if (ret < 0) {
2242                         fimc_err("direct_ioctl(S3CFB_SET_WIN_ADDR) fail\n");
2243                         return -EINVAL;
2244                 }
2245
2246                 ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_MEM, DMA_MEM_NONE);
2247                 if (ret < 0) {
2248                         fimc_err("direct_ioctl(S3CFB_SET_WIN_MEM) fail\n");
2249                         return -EINVAL;
2250                 }
2251
2252                 ctrl->fb.is_enable = 0;
2253 #endif
2254         }
2255
2256         ret = fimc_init_in_queue(ctrl, ctx);
2257         if (ret < 0) {
2258                 fimc_err("Fail: fimc_init_in_queue\n");
2259                 return -EINVAL;
2260         }
2261
2262         ret = fimc_init_out_queue(ctrl, ctx);
2263         if (ret < 0) {
2264                 fimc_err("Fail: fimc_init_out_queue\n");
2265                 return -EINVAL;
2266         }
2267
2268         /* Make all buffers DQUEUED state. */
2269         for (i = 0; i < FIMC_OUTBUFS; i++) {
2270                 ctx->src[i].state = VIDEOBUF_IDLE;
2271                 ctx->src[i].flags = V4L2_BUF_FLAG_MAPPED;
2272         }
2273
2274         if (ctrl->out->last_ctx == ctx->ctx_num)
2275                 ctrl->out->last_ctx = -1;
2276
2277         if (ctx->overlay.mode == FIMC_OVLY_DMA_AUTO) {
2278                 ctrl->mem.curr = ctx->dst[0].base[FIMC_ADDR_Y];
2279
2280                 for (i = 0; i < FIMC_OUTBUFS; i++) {
2281 #ifdef CONFIG_VIDEO_FIMC_UMP_VCM_CMA
2282                         fimc_vcm_free_outbuf(ctrl, i, ctx->dst[i].base[FIMC_ADDR_Y]);
2283                         ctx->dst[i].vaddr_base[FIMC_ADDR_Y] = 0;
2284                         ctx->dst[i].vaddr_base[FIMC_ADDR_CB] = 0;
2285                         ctx->dst[i].vaddr_base[FIMC_ADDR_CR] = 0;
2286 #endif
2287                         ctx->dst[i].base[FIMC_ADDR_Y] = 0;
2288                         ctx->dst[i].length[FIMC_ADDR_Y] = 0;
2289
2290                         ctx->dst[i].base[FIMC_ADDR_CB] = 0;
2291                         ctx->dst[i].length[FIMC_ADDR_CB] = 0;
2292
2293                         ctx->dst[i].base[FIMC_ADDR_CR] = 0;
2294                         ctx->dst[i].length[FIMC_ADDR_CR] = 0;
2295                 }
2296         }
2297
2298         /* check all ctx to change ctrl->status from streamon to streamoff */
2299         for (i = 0; i < FIMC_MAX_CTXS; i++) {
2300                 if (ctrl->out->ctx[i].status == FIMC_STREAMOFF)
2301                         off_cnt++;
2302         }
2303
2304 #if (!defined(CONFIG_S5PV310_DEV_PD) || !defined(CONFIG_PM_RUNTIME))
2305         if (off_cnt == FIMC_MAX_CTXS) {
2306                 ctrl->status = FIMC_STREAMOFF;
2307                 fimc_outdev_init_idxs(ctrl);
2308                 fimc_outdev_stop_camif(ctrl);
2309         }
2310 #endif
2311
2312         ctrl->log &= ~(FIMC_LOG_INFO_L1);
2313         return 0;
2314 }
2315
2316 static int fimc_qbuf_output_single_buf(struct fimc_control *ctrl,
2317                                        struct fimc_ctx *ctx,
2318                                        int idx)
2319 {
2320         struct fimc_buf_set buf_set;    /* destination addr */
2321         u32 format = ctx->fbuf.fmt.pixelformat;
2322         u32 width = ctx->fbuf.fmt.width;
2323         u32 height = ctx->fbuf.fmt.height;
2324         u32 y_size = width * height;
2325         u32 c_size = y_size >> 2;
2326         int ret = -1, i, cfg;
2327         u32 rot = ctx->rotate;
2328
2329         fimc_outdev_set_src_addr(ctrl, ctx->src[idx].base);
2330
2331         memset(&buf_set, 0x00, sizeof(buf_set));
2332
2333 #ifdef SYSMMU_FIMC
2334         switch (format) {
2335         case V4L2_PIX_FMT_RGB32:
2336         case V4L2_PIX_FMT_RGB565:       /* fall through */
2337                 buf_set.vaddr_base[FIMC_ADDR_Y] = (dma_addr_t)ctx->fbuf.base;
2338                 break;
2339         case V4L2_PIX_FMT_YUV420:
2340                 buf_set.vaddr_base[FIMC_ADDR_Y] = (dma_addr_t)ctx->fbuf.base;
2341                 buf_set.vaddr_base[FIMC_ADDR_CB] = buf_set.vaddr_base[FIMC_ADDR_Y] + y_size;
2342                 buf_set.vaddr_base[FIMC_ADDR_CR] = buf_set.vaddr_base[FIMC_ADDR_CB] + c_size;
2343                 break;
2344         case V4L2_PIX_FMT_NV12:
2345         case V4L2_PIX_FMT_NV21:
2346                 buf_set.vaddr_base[FIMC_ADDR_Y] = (dma_addr_t)ctx->fbuf.base;
2347                 buf_set.vaddr_base[FIMC_ADDR_CB] = buf_set.base[FIMC_ADDR_Y] + y_size;
2348                 break;
2349         case V4L2_PIX_FMT_NV12T:
2350                 if (rot == 0 || rot == 180)
2351                         fimc_get_nv12t_size(width, height, &y_size, &c_size);
2352                 else
2353                         fimc_get_nv12t_size(height, width, &y_size, &c_size);
2354                 buf_set.vaddr_base[FIMC_ADDR_Y] = (dma_addr_t)ctx->fbuf.base;
2355                 buf_set.vaddr_base[FIMC_ADDR_CB] = buf_set.base[FIMC_ADDR_Y] + y_size;
2356                 break;
2357         default:
2358                 fimc_err("%s: Invalid pixelformt : %d\n", __func__, format);
2359                 return -EINVAL;
2360         }
2361 #else
2362         switch (format) {
2363         case V4L2_PIX_FMT_RGB32:
2364         case V4L2_PIX_FMT_RGB565:       /* fall through */
2365                 buf_set.base[FIMC_ADDR_Y] = (dma_addr_t)ctx->fbuf.base;
2366                 break;
2367         case V4L2_PIX_FMT_YUV420:
2368                 buf_set.base[FIMC_ADDR_Y] = (dma_addr_t)ctx->fbuf.base;
2369                 buf_set.base[FIMC_ADDR_CB] = buf_set.base[FIMC_ADDR_Y] + y_size;
2370                 buf_set.base[FIMC_ADDR_CR] = buf_set.base[FIMC_ADDR_CB] + c_size;
2371                 break;
2372         case V4L2_PIX_FMT_NV12:
2373         case V4L2_PIX_FMT_NV21:
2374                 buf_set.base[FIMC_ADDR_Y] = (dma_addr_t)ctx->fbuf.base;
2375                 buf_set.base[FIMC_ADDR_CB] = buf_set.base[FIMC_ADDR_Y] + y_size;
2376                 break;
2377         case V4L2_PIX_FMT_NV12T:
2378                 if (rot == 0 || rot == 180)
2379                         fimc_get_nv12t_size(width, height, &y_size, &c_size);
2380                 else
2381                         fimc_get_nv12t_size(height, width, &y_size, &c_size);
2382                 buf_set.base[FIMC_ADDR_Y] = (dma_addr_t)ctx->fbuf.base;
2383                 buf_set.base[FIMC_ADDR_CB] = buf_set.base[FIMC_ADDR_Y] + y_size;
2384                 break;
2385         default:
2386                 fimc_err("%s: Invalid pixelformt : %d\n", __func__, format);
2387                 return -EINVAL;
2388         }
2389 #endif
2390         cfg = fimc_hwget_output_buf_sequence(ctrl);
2391
2392         for (i = 0; i < FIMC_PHYBUFS; i++) {
2393                 if (check_bit(cfg, i))
2394                         fimc_hwset_output_address(ctrl, &buf_set, i);
2395         }
2396
2397         ctrl->out->idxs.active.idx = idx;
2398         ctrl->out->idxs.active.ctx = ctx->ctx_num;
2399
2400         ctrl->status = FIMC_STREAMON;
2401         ctx->status = FIMC_STREAMON;
2402
2403         ret = fimc_outdev_start_camif(ctrl);
2404         if (ret < 0) {
2405                 fimc_err("Fail: fimc_start_camif\n");
2406                 return -EINVAL;
2407         }
2408
2409         return 0;
2410 }
2411
2412 static int fimc_qbuf_output_multi_buf(struct fimc_control *ctrl,
2413                                       struct fimc_ctx *ctx,
2414                                       int idx)
2415 {
2416         struct fimc_buf_set buf_set;    /* destination addr */
2417         u32 format = ctx->fbuf.fmt.pixelformat;
2418         int ret = -1, i, cfg;
2419
2420         fimc_outdev_set_src_addr(ctrl, ctx->src[idx].base);
2421
2422         memset(&buf_set, 0x00, sizeof(buf_set));
2423 #ifdef SYSMMU_FIMC
2424         switch (format) {
2425         case V4L2_PIX_FMT_RGB32:
2426         case V4L2_PIX_FMT_RGB565:       /* fall through */
2427                 buf_set.vaddr_base[FIMC_ADDR_Y] = ctx->dst[idx].base[FIMC_ADDR_Y];
2428                 break;
2429         case V4L2_PIX_FMT_YUV420:
2430                 buf_set.vaddr_base[FIMC_ADDR_Y] = ctx->dst[idx].base[FIMC_ADDR_Y];
2431                 buf_set.vaddr_base[FIMC_ADDR_CB] = ctx->dst[idx].base[FIMC_ADDR_CB];
2432                 buf_set.vaddr_base[FIMC_ADDR_CR] = ctx->dst[idx].base[FIMC_ADDR_CR];
2433                 break;
2434         case V4L2_PIX_FMT_NV12:         /* fall through */
2435         case V4L2_PIX_FMT_NV21:         /* fall through */
2436         case V4L2_PIX_FMT_NV12T:
2437                 buf_set.vaddr_base[FIMC_ADDR_Y] = ctx->dst[idx].base[FIMC_ADDR_Y];
2438                 buf_set.vaddr_base[FIMC_ADDR_CB] = ctx->dst[idx].base[FIMC_ADDR_CB];
2439                 break;
2440         default:
2441                 fimc_err("%s: Invalid pixelformt : %d\n", __func__, format);
2442                 return -EINVAL;
2443         }
2444 #else
2445         switch (format) {
2446         case V4L2_PIX_FMT_RGB32:
2447         case V4L2_PIX_FMT_RGB565:       /* fall through */
2448                 buf_set.base[FIMC_ADDR_Y] = ctx->dst[idx].base[FIMC_ADDR_Y];
2449                 break;
2450         case V4L2_PIX_FMT_YUV420:
2451                 buf_set.base[FIMC_ADDR_Y] = ctx->dst[idx].base[FIMC_ADDR_Y];
2452                 buf_set.base[FIMC_ADDR_CB] = ctx->dst[idx].base[FIMC_ADDR_CB];
2453                 buf_set.base[FIMC_ADDR_CR] = ctx->dst[idx].base[FIMC_ADDR_CR];
2454                 break;
2455         case V4L2_PIX_FMT_NV12:         /* fall through */
2456         case V4L2_PIX_FMT_NV21:         /* fall through */
2457         case V4L2_PIX_FMT_NV12T:
2458                 buf_set.base[FIMC_ADDR_Y] = ctx->dst[idx].base[FIMC_ADDR_Y];
2459                 buf_set.base[FIMC_ADDR_CB] = ctx->dst[idx].base[FIMC_ADDR_CB];
2460                 break;
2461         default:
2462                 fimc_err("%s: Invalid pixelformt : %d\n", __func__, format);
2463                 return -EINVAL;
2464         }
2465 #endif
2466         cfg = fimc_hwget_output_buf_sequence(ctrl);
2467
2468         for (i = 0; i < FIMC_PHYBUFS; i++) {
2469                 if (check_bit(cfg, i))
2470                         fimc_hwset_output_address(ctrl, &buf_set, i);
2471         }
2472
2473         ctrl->out->idxs.active.idx = idx;
2474         ctrl->out->idxs.active.ctx = ctx->ctx_num;
2475
2476         ctrl->status = FIMC_STREAMON;
2477         ctx->status = FIMC_STREAMON;
2478
2479         ret = fimc_outdev_start_camif(ctrl);
2480         if (ret < 0) {
2481                 fimc_err("Fail: fimc_start_camif\n");
2482                 return -EINVAL;
2483         }
2484
2485         return 0;
2486 }
2487
2488 static int fimc_qbuf_output_dma_auto(struct fimc_control *ctrl,
2489                                       struct fimc_ctx *ctx,
2490                                       int idx)
2491 {
2492         struct fb_var_screeninfo var;
2493         struct s3cfb_user_window window;
2494         struct v4l2_rect fimd_rect, fimd_rect_virtual;
2495         struct fimc_buf_set buf_set;    /* destination addr */
2496         int ret = -1, i, cfg;
2497         int window_id = ((ctrl->id == 3) ? 2 : ctrl->id);
2498
2499         switch (ctx->status) {
2500         case FIMC_READY_ON:
2501                 memset(&fimd_rect, 0, sizeof(struct v4l2_rect));
2502                 ret = fimc_fimd_rect(ctrl, ctx, &fimd_rect);
2503                 if (ret < 0) {
2504                         fimc_err("fimc_fimd_rect fail\n");
2505                         return -EINVAL;
2506                 }
2507
2508                 /* Support any size */
2509                 memcpy(&fimd_rect_virtual, &fimd_rect, sizeof(fimd_rect));
2510                 fimc_outdev_dma_auto_dst_resize(&fimd_rect_virtual);
2511
2512                 if (ctrl->fb.is_enable == 1) {
2513                         ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_OFF,
2514                                         (unsigned long)NULL);
2515                         if (ret < 0) {
2516                                 fimc_err("direct_ioctl(S3CFB_SET_WIN_OFF) fail\n");
2517                                 return -EINVAL;
2518                         }
2519                 }
2520
2521                 /* Get WIN var_screeninfo */
2522                 ret = s3cfb_direct_ioctl(window_id, FBIOGET_VSCREENINFO,
2523                                                 (unsigned long)&var);
2524                 if (ret < 0) {
2525                         fimc_err("direct_ioctl(FBIOGET_VSCREENINFO) fail\n");
2526                         return -EINVAL;
2527                 }
2528                 /* window path : DMA */
2529                 ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_PATH,
2530                                                         DATA_PATH_DMA);
2531                 if (ret < 0) {
2532                         fimc_err("direct_ioctl(S3CFB_SET_WIN_PATH) fail\n");
2533                         return -EINVAL;
2534                 }
2535
2536                 /* Don't allocate the memory. */
2537                 ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_MEM, DMA_MEM_OTHER);
2538                 if (ret < 0) {
2539                         fimc_err("direct_ioctl(S3CFB_SET_WIN_MEM) fail\n");
2540                         return -EINVAL;
2541                 }
2542
2543                 /* Update WIN size */
2544                 var.xres_virtual = fimd_rect_virtual.width;
2545                 var.yres_virtual = fimd_rect_virtual.height;
2546                 var.xres = fimd_rect.width;
2547                 var.yres = fimd_rect.height;
2548
2549                 ret = s3cfb_direct_ioctl(window_id, FBIOPUT_VSCREENINFO,
2550                                                         (unsigned long)&var);
2551                 if (ret < 0) {
2552                         fimc_err("direct_ioctl(FBIOPUT_VSCREENINFO) fail\n");
2553                         return -EINVAL;
2554                 }
2555
2556                 /* Update WIN position */
2557                 window.x = fimd_rect.left;
2558                 window.y = fimd_rect.top;
2559                 ret = s3cfb_direct_ioctl(window_id, S3CFB_WIN_POSITION,
2560                                 (unsigned long)&window);
2561                 if (ret < 0) {
2562                         fimc_err("direct_ioctl(S3CFB_WIN_POSITION) fail\n");
2563                         return -EINVAL;
2564                 }
2565
2566                 ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_ON,
2567                                 (unsigned long)NULL);
2568                 if (ret < 0) {
2569                         fimc_err("direct_ioctl(S3CFB_SET_WIN_ON) fail\n");
2570                         return -EINVAL;
2571                 }
2572                 /* fall through */
2573
2574         case FIMC_STREAMON_IDLE:
2575                 fimc_outdev_set_src_addr(ctrl, ctx->src[idx].base);
2576
2577                 memset(&buf_set, 0x00, sizeof(buf_set));
2578 #ifdef SYSMMU_FIMC
2579                 buf_set.base[FIMC_ADDR_Y] = ctx->dst[idx].base[FIMC_ADDR_Y];
2580                 buf_set.vaddr_base[FIMC_ADDR_Y]
2581                         = ctx->dst[idx].vaddr_base[FIMC_ADDR_Y];
2582 #else
2583                 buf_set.base[FIMC_ADDR_Y] = ctx->dst[idx].base[FIMC_ADDR_Y];
2584 #endif
2585
2586                 cfg = fimc_hwget_output_buf_sequence(ctrl);
2587
2588                 for (i = 0; i < FIMC_PHYBUFS; i++) {
2589                         if (check_bit(cfg, i))
2590                                 fimc_hwset_output_address(ctrl, &buf_set, i);
2591                 }
2592
2593                 ctrl->out->idxs.active.idx = idx;
2594                 ctrl->out->idxs.active.ctx = ctx->ctx_num;
2595
2596                 ctrl->status = FIMC_STREAMON;
2597                 ctx->status = FIMC_STREAMON;
2598
2599                 ret = fimc_outdev_start_camif(ctrl);
2600                 if (ret < 0) {
2601                         fimc_err("Fail: fimc_start_camif\n");
2602                         ctrl->status = FIMC_STREAMON_IDLE;
2603                         ctx->status = FIMC_STREAMON_IDLE;
2604                         return -EINVAL;
2605                 }
2606
2607                 break;
2608
2609         default:
2610                 break;
2611         }
2612
2613         return 0;
2614 }
2615
2616 static int fimc_qbuf_output_dma_manual(struct fimc_control *ctrl,
2617                                       struct fimc_ctx *ctx,
2618                                       int idx)
2619 {
2620         struct fimc_buf_set buf_set;    /* destination addr */
2621         int ret = -1, i, cfg;
2622
2623         fimc_outdev_set_src_addr(ctrl, ctx->src[idx].base);
2624
2625         memset(&buf_set, 0x00, sizeof(buf_set));
2626 #ifdef SYSMMU_FIMC
2627         buf_set.vaddr_base[FIMC_ADDR_Y] = ctx->dst[idx].base[FIMC_ADDR_Y];
2628 #else
2629         buf_set.base[FIMC_ADDR_Y] = ctx->dst[idx].base[FIMC_ADDR_Y];
2630 #endif
2631         cfg = fimc_hwget_output_buf_sequence(ctrl);
2632
2633         for (i = 0; i < FIMC_PHYBUFS; i++) {
2634                 if (check_bit(cfg, i))
2635                         fimc_hwset_output_address(ctrl, &buf_set, i);
2636         }
2637
2638         ctrl->out->idxs.active.idx = idx;
2639         ctrl->out->idxs.active.ctx = ctx->ctx_num;
2640
2641         ctrl->status = FIMC_STREAMON;
2642         ctx->status = FIMC_STREAMON;
2643
2644         ret = fimc_outdev_start_camif(ctrl);
2645         if (ret < 0) {
2646                 fimc_err("Fail: fimc_start_camif\n");
2647                 return -EINVAL;
2648         }
2649
2650         return 0;
2651 }
2652
2653 static int fimc_qbuf_output_fifo(struct fimc_control *ctrl,
2654                                       struct fimc_ctx *ctx,
2655                                       int idx)
2656 {
2657         int ret = -1;
2658
2659 #if defined(CONFIG_VIDEO_IPC)
2660         if (ctx->pix.field == V4L2_FIELD_INTERLACED_TB)
2661                 ipc_start();
2662 #endif
2663
2664         fimc_outdev_set_src_addr(ctrl, ctx->src[idx].base);
2665
2666         ctrl->out->idxs.active.idx = idx;
2667         ctrl->out->idxs.active.ctx = ctx->ctx_num;
2668
2669         ctrl->status = FIMC_STREAMON;
2670         ctx->status = FIMC_STREAMON;
2671
2672         ret = fimc_start_fifo(ctrl, ctx);
2673         if (ret < 0) {
2674                 fimc_err("Fail: fimc_start_fifo\n");
2675                 return -EINVAL;
2676         }
2677
2678         return 0;
2679 }
2680
2681 static int fimc_update_in_queue_addr(struct fimc_control *ctrl,
2682                                      struct fimc_ctx *ctx,
2683                                      u32 idx, dma_addr_t *addr)
2684 {
2685 #ifdef SYSMMU_FIMC
2686         struct vcm_res *vcm_res;
2687 #endif
2688
2689         if (idx >= FIMC_OUTBUFS) {
2690                 fimc_err("%s: Failed\n", __func__);
2691                 return -EINVAL;
2692         }
2693
2694 #ifdef SYSMMU_FIMC
2695         if (ctx->pix.pixelformat == V4L2_PIX_FMT_NV12T) {
2696                 vcm_res = (struct vcm_res *)
2697                         ump_dd_vcm_res_get(addr[FIMC_ADDR_Y], ctrl->vcm_id);
2698                 if (vcm_res)
2699                         ctx->src[idx].base[FIMC_ADDR_Y] = vcm_res->start;
2700                 else
2701                         return -EINVAL;
2702                 vcm_res = (struct vcm_res *)
2703                         ump_dd_vcm_res_get(addr[FIMC_ADDR_CB], ctrl->vcm_id);
2704                 if (vcm_res)
2705                         ctx->src[idx].base[FIMC_ADDR_CB] = vcm_res->start;
2706                 else
2707                         return -EINVAL;
2708                 ctx->src[idx].base[FIMC_ADDR_CR] = 0;
2709         } else if (ctx->pix.pixelformat == V4L2_PIX_FMT_NV21) {
2710                 vcm_res = (struct vcm_res *)
2711                         ump_dd_vcm_res_get(addr[FIMC_ADDR_Y], ctrl->vcm_id);
2712                 if (vcm_res)
2713                         ctx->src[idx].base[FIMC_ADDR_Y] = vcm_res->start;
2714                 else
2715                         return -EINVAL;
2716                 ctx->src[idx].base[FIMC_ADDR_CB] =
2717                         ctx->src[idx].base[FIMC_ADDR_Y] + addr[FIMC_ADDR_CB];
2718                 ctx->src[idx].base[FIMC_ADDR_CR] = 0;
2719         } else {
2720                 vcm_res = (struct vcm_res *)
2721                         ump_dd_vcm_res_get(addr[FIMC_ADDR_Y], ctrl->vcm_id);
2722                 if (vcm_res)
2723                         ctx->src[idx].base[FIMC_ADDR_Y] = vcm_res->start;
2724                 else
2725                         return -EINVAL;
2726                 ctx->src[idx].base[FIMC_ADDR_CB] =
2727                         ctx->src[idx].base[FIMC_ADDR_Y] + addr[FIMC_ADDR_CB];
2728                 ctx->src[idx].base[FIMC_ADDR_CR] =
2729                         ctx->src[idx].base[FIMC_ADDR_CB] + addr[FIMC_ADDR_CR];
2730         }
2731 #else
2732         ctx->src[idx].base[FIMC_ADDR_Y] = addr[FIMC_ADDR_Y];
2733         ctx->src[idx].base[FIMC_ADDR_CB] = addr[FIMC_ADDR_CB];
2734         ctx->src[idx].base[FIMC_ADDR_CR] = addr[FIMC_ADDR_CR];
2735 #endif
2736         return 0;
2737 }
2738
2739 int fimc_qbuf_output(void *fh, struct v4l2_buffer *b)
2740 {
2741         struct fimc_buf *buf = (struct fimc_buf *)b->m.userptr;
2742         struct fimc_ctx *ctx;
2743         struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
2744         int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
2745         int idx, ctx_num;
2746         int ret = -1;
2747
2748         ctx = &ctrl->out->ctx[ctx_id];
2749         fimc_info2("ctx(%d) queued idx = %d\n", ctx->ctx_num, b->index);
2750         if (ctx->status == FIMC_STREAMOFF) {
2751                 printk("%s:: can not queue is FIMC_STREAMOFF status \n",
2752                                 __func__);
2753                 return ret;
2754         }
2755
2756         if (b->index > ctx->buf_num) {
2757                 fimc_err("The index is out of bounds. "
2758                         "You requested %d buffers. "
2759                         "But you set the index as %d\n",
2760                         ctx->buf_num, b->index);
2761                 return -EINVAL;
2762         }
2763
2764         /* Check the buffer state if the state is VIDEOBUF_IDLE. */
2765         if (ctx->src[b->index].state != VIDEOBUF_IDLE) {
2766                 fimc_err("The index(%d) buffer must be dequeued state(%d)\n",
2767                                  b->index, ctx->src[b->index].state);
2768                 return -EINVAL;
2769         }
2770
2771         if ((ctrl->status == FIMC_READY_ON) ||
2772             (ctrl->status == FIMC_STREAMON) ||
2773             (ctrl->status == FIMC_STREAMON_IDLE)) {
2774                 if (b->memory == V4L2_MEMORY_USERPTR) {
2775                         ret = fimc_update_in_queue_addr(ctrl, ctx, b->index, buf->base);
2776                         if (ret < 0)
2777                                 return ret;
2778                 }
2779
2780 #if (defined(CONFIG_S5PV310_DEV_PD) && defined(CONFIG_PM_RUNTIME))
2781                 pm_runtime_get_sync(ctrl->dev);
2782 #endif
2783
2784                 /* Attach the buffer to the incoming queue. */
2785                 ret = fimc_push_inq(ctrl, ctx, b->index);
2786                 if (ret < 0) {
2787                         fimc_err("Fail: fimc_push_inq\n");
2788 #if (defined(CONFIG_S5PV310_DEV_PD) && defined(CONFIG_PM_RUNTIME))
2789                         pm_runtime_put_sync(ctrl->dev);
2790 #endif
2791                         return -EINVAL;
2792                 }
2793         }
2794
2795         if ((ctrl->status == FIMC_READY_ON) ||
2796             (ctrl->status == FIMC_STREAMON_IDLE)) {
2797                 ret = fimc_pop_inq(ctrl, &ctx_num, &idx);
2798                 if (ret < 0) {
2799                         fimc_err("Fail: fimc_pop_inq\n");
2800                         return -EINVAL;
2801                 }
2802
2803                 ctx = &ctrl->out->ctx[ctx_num];
2804                 if (ctx_num != ctrl->out->last_ctx) {
2805                         ctrl->out->last_ctx = ctx->ctx_num;
2806                         ret = fimc_outdev_set_ctx_param(ctrl, ctx);
2807                         if (ret < 0)
2808                                 return ret;
2809                 }
2810
2811                 switch (ctx->overlay.mode) {
2812                 case FIMC_OVLY_FIFO:
2813                         ret = fimc_qbuf_output_fifo(ctrl, ctx, idx);
2814                         break;
2815                 case FIMC_OVLY_DMA_AUTO:
2816                         ret = fimc_qbuf_output_dma_auto(ctrl, ctx, idx);
2817                         break;
2818                 case FIMC_OVLY_DMA_MANUAL:
2819                         ret = fimc_qbuf_output_dma_manual(ctrl, ctx, idx);
2820                         break;
2821                 case FIMC_OVLY_NONE_SINGLE_BUF:
2822                         ret = fimc_qbuf_output_single_buf(ctrl, ctx, idx);
2823                         break;
2824                 case FIMC_OVLY_NONE_MULTI_BUF:
2825                         ret = fimc_qbuf_output_multi_buf(ctrl, ctx, idx);
2826                         break;
2827                 default:
2828                         break;
2829                 }
2830         }
2831
2832         return ret;
2833 }
2834
2835 int fimc_dqbuf_output(void *fh, struct v4l2_buffer *b)
2836 {
2837         struct fimc_ctx *ctx;
2838         struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
2839         int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
2840         int idx = -1, ret = -1;
2841
2842         ctx = &ctrl->out->ctx[ctx_id];
2843         ret = fimc_pop_outq(ctrl, ctx, &idx);
2844         if (ret < 0) {
2845                 ret = wait_event_timeout(ctrl->wq, (ctx->outq[0] != -1),
2846                                                         FIMC_DQUEUE_TIMEOUT);
2847                 if (ret == 0) {
2848                         fimc_dump_context(ctrl, ctx);
2849                         fimc_err("[0] out_queue is empty\n");
2850                         return -EAGAIN;
2851                 } else if (ret == -ERESTARTSYS) {
2852                         fimc_print_signal(ctrl);
2853                 } else {
2854                         /* Normal case */
2855                         ret = fimc_pop_outq(ctrl, ctx, &idx);
2856                         if (ret < 0) {
2857                                 fimc_err("[1] out_queue is empty\n");
2858                                 fimc_dump_context(ctrl, ctx);
2859                                 return -EINVAL;
2860                         }
2861                 }
2862         }
2863
2864         b->index = idx;
2865
2866         fimc_info2("ctx(%d) dqueued idx = %d\n", ctx->ctx_num, b->index);
2867
2868         return ret;
2869 }
2870
2871 int fimc_g_fmt_vid_out(struct file *filp, void *fh, struct v4l2_format *f)
2872 {
2873         struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
2874         struct fimc_outinfo *out = ctrl->out;
2875         struct fimc_ctx *ctx;
2876         int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
2877         int i, j;
2878         int in_use;
2879
2880         fimc_info1("%s: called\n", __func__);
2881
2882         if (!out) {
2883                 out = kzalloc(sizeof(*out), GFP_KERNEL);
2884                 if (!out) {
2885                         fimc_err("%s: no memory for outdev info\n", __func__);
2886                         return -ENOMEM;
2887                 }
2888                 ctrl->out = out;
2889
2890                 /* init: struct fimc_outinfo */
2891                 out->last_ctx = -1;
2892
2893                 spin_lock_init(&ctrl->out->lock_in);
2894                 spin_lock_init(&ctrl->out->lock_out);
2895
2896                 for (i = 0; i < FIMC_INQUEUES; i++) {
2897                         ctrl->out->inq[i].ctx = -1;
2898                         ctrl->out->inq[i].idx = -1;
2899                 }
2900
2901                 for (i = 0; i < FIMC_MAX_CTXS; i++) {
2902                         ctx = &ctrl->out->ctx[i];
2903                         ctx->ctx_num = i;
2904                         ctx->overlay.mode = FIMC_OVLY_NOT_FIXED;
2905                         ctx->status = FIMC_STREAMOFF;
2906
2907                         for (j = 0; j < FIMC_OUTBUFS; j++) {
2908                                 ctx->inq[j] = -1;
2909                                 ctx->outq[j] = -1;
2910                         }
2911                 }
2912
2913                 ctrl->out->idxs.prev.ctx = -1;
2914                 ctrl->out->idxs.prev.idx = -1;
2915                 ctrl->out->idxs.active.ctx = -1;
2916                 ctrl->out->idxs.active.idx = -1;
2917                 ctrl->out->idxs.next.ctx = -1;
2918                 ctrl->out->idxs.next.idx = -1;
2919
2920                 in_use = atomic_read(&ctrl->in_use);
2921                 for (i = 0; i < in_use; i++)
2922                         ctrl->out->ctx_used[i] = true;
2923                 for (i = in_use; i < FIMC_MAX_CTXS; i++)
2924                         ctrl->out->ctx_used[i] = false;
2925         }
2926
2927         f->fmt.pix = ctrl->out->ctx[ctx_id].pix;
2928
2929         return 0;
2930 }
2931
2932 int fimc_try_fmt_vid_out(struct file *filp, void *fh, struct v4l2_format *f)
2933 {
2934         struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
2935         int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
2936         struct fimc_ctx *ctx;
2937         u32 format = f->fmt.pix.pixelformat;
2938
2939         fimc_info1("%s: called. width(%d), height(%d)\n", __func__,
2940                                 f->fmt.pix.width, f->fmt.pix.height);
2941
2942         ctx = &ctrl->out->ctx[ctx_id];
2943         if (ctx->status != FIMC_STREAMOFF) {
2944                 fimc_err("%s: FIMC is running\n", __func__);
2945                 return -EBUSY;
2946         }
2947
2948         /* Check pixel format */
2949         switch (format) {
2950         case V4L2_PIX_FMT_NV12:         /* fall through */
2951         case V4L2_PIX_FMT_NV21:         /* fall through */
2952         case V4L2_PIX_FMT_NV12T:        /* fall through */
2953         case V4L2_PIX_FMT_YUYV:         /* fall through */
2954         case V4L2_PIX_FMT_YUV420:       /* fall through */
2955         case V4L2_PIX_FMT_RGB32:        /* fall through */
2956         case V4L2_PIX_FMT_RGB565:       /* fall through */
2957                 break;
2958         default:
2959                 fimc_warn("Supported format : V4L2_PIX_FMT_YUYV, "
2960                         "V4L2_PIX_FMT_NV12, V4L2_PIX_FMT_NV12T, "
2961                         "V4L2_PIX_FMT_RGB32, V4L2_PIX_FMT_RGB565\n");
2962                 fimc_warn("Changed format : V4L2_PIX_FMT_RGB32\n");
2963                 f->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32;
2964                 return -EINVAL;
2965         }
2966
2967         /* Fill the return value. */
2968         switch (format) {
2969         case V4L2_PIX_FMT_RGB32:
2970                 f->fmt.pix.bytesperline = f->fmt.pix.width << 2;
2971                 break;
2972         case V4L2_PIX_FMT_YUYV:         /* fall through */
2973         case V4L2_PIX_FMT_YUV420:       /* fall through */
2974         case V4L2_PIX_FMT_RGB565:
2975                 f->fmt.pix.bytesperline = f->fmt.pix.width << 1;
2976                 break;
2977         case V4L2_PIX_FMT_NV12:         /* fall through */
2978         case V4L2_PIX_FMT_NV21:         /* fall through */
2979         case V4L2_PIX_FMT_NV12T:
2980                 f->fmt.pix.bytesperline = (f->fmt.pix.width * 3) >> 1;
2981                 break;
2982
2983         default:
2984                 /* dummy value*/
2985                 f->fmt.pix.bytesperline = f->fmt.pix.width;
2986         }
2987
2988         f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
2989         ctx->crop.left = 0;
2990         ctx->crop.top = 0;
2991         ctx->crop.width = f->fmt.pix.width;
2992         ctx->crop.height = f->fmt.pix.height;
2993
2994         return 0;
2995 }
2996
2997 int fimc_s_fmt_vid_out(struct file *filp, void *fh, struct v4l2_format *f)
2998 {
2999         struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
3000         int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
3001         struct fimc_ctx *ctx;
3002         int ret = -1;
3003
3004         fimc_info1("%s: called\n", __func__);
3005
3006         /* Check stream status */
3007         ctx = &ctrl->out->ctx[ctx_id];
3008         if (ctx->status != FIMC_STREAMOFF) {
3009                 fimc_err("%s: FIMC is running\n", __func__);
3010                 return -EBUSY;
3011         }
3012
3013         ret = fimc_try_fmt_vid_out(filp, fh, f);
3014         if (ret < 0)
3015                 return ret;
3016
3017         ctx->pix = f->fmt.pix;
3018
3019         return ret;
3020 }
3021
3022 int fimc_init_in_queue(struct fimc_control *ctrl, struct fimc_ctx *ctx)
3023 {
3024         struct fimc_idx swap_queue[FIMC_INQUEUES];
3025         int swap_cnt = 0, i;
3026         unsigned long spin_flags;
3027
3028         spin_lock_irqsave(&ctrl->out->lock_in, spin_flags);
3029
3030         /* init incoming queue */
3031         for (i = 0; i < FIMC_OUTBUFS; i++)
3032                 ctx->inq[i] = -1;
3033
3034         /* init common incoming queue */
3035         for (i = 0; i < FIMC_INQUEUES; i++) {
3036                 if (ctrl->out->inq[i].ctx != ctx->ctx_num) {
3037                         swap_queue[swap_cnt].ctx = ctrl->out->inq[i].ctx;
3038                         swap_queue[swap_cnt].idx = ctrl->out->inq[i].idx;
3039                         swap_cnt++;
3040                 }
3041
3042                 ctrl->out->inq[i].ctx = -1;
3043                 ctrl->out->inq[i].idx = -1;
3044         }
3045
3046         /* restore common incoming queue */
3047         for (i = 0; i < swap_cnt; i++) {
3048                 ctrl->out->inq[i].ctx = swap_queue[i].ctx;
3049                 ctrl->out->inq[i].idx = swap_queue[i].idx;
3050  }
3051
3052         spin_unlock_irqrestore(&ctrl->out->lock_in, spin_flags);
3053
3054         return 0;
3055 }
3056
3057 int fimc_init_out_queue(struct fimc_control *ctrl, struct fimc_ctx *ctx)
3058 {
3059         unsigned long spin_flags;
3060         int i;
3061
3062         spin_lock_irqsave(&ctrl->out->lock_out, spin_flags);
3063
3064         /* Init incoming queue */
3065         for (i = 0; i < FIMC_OUTBUFS; i++)
3066                 ctx->outq[i] = -1;
3067
3068         spin_unlock_irqrestore(&ctrl->out->lock_out, spin_flags);
3069
3070         return 0;
3071 }
3072
3073 int fimc_push_inq(struct fimc_control *ctrl, struct fimc_ctx *ctx, int idx)
3074 {
3075         struct fimc_idx swap_common_inq[FIMC_INQUEUES];
3076         int swap_queue[FIMC_OUTBUFS];
3077         int i;
3078         unsigned long spin_flags;
3079
3080         fimc_dbg("%s: idx = %d\n", __func__, idx);
3081
3082         if (ctrl->out->inq[FIMC_INQUEUES-1].idx != -1) {
3083                 fimc_err("FULL: common incoming queue(%d)\n",
3084                                 ctrl->out->inq[FIMC_INQUEUES-1].idx);
3085                 return -EBUSY;
3086         }
3087
3088         spin_lock_irqsave(&ctrl->out->lock_in, spin_flags);
3089
3090         /* ctx own incoming queue */
3091         /* Backup original queue */
3092         for (i = 0; i < FIMC_OUTBUFS; i++)
3093                 swap_queue[i] = ctx->inq[i];
3094
3095         /* Attach new idx */
3096         ctx->inq[0] = idx;
3097         ctx->src[idx].state = VIDEOBUF_QUEUED;
3098         ctx->src[idx].flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED;
3099
3100         /* Shift the origonal queue */
3101         for (i = 1; i < FIMC_OUTBUFS; i++)
3102                 ctx->inq[i] = swap_queue[i-1];
3103
3104         /* Common incoming queue */
3105         /* Backup original queue */
3106         for (i = 0; i < FIMC_INQUEUES; i++) {
3107                 swap_common_inq[i].ctx = ctrl->out->inq[i].ctx;
3108                 swap_common_inq[i].idx = ctrl->out->inq[i].idx;
3109         }
3110
3111         /* Attach new idx */
3112         ctrl->out->inq[0].ctx = ctx->ctx_num;
3113         ctrl->out->inq[0].idx = idx;
3114
3115         /* Shift the origonal queue */
3116         for (i = 1; i < FIMC_INQUEUES; i++) {
3117                 ctrl->out->inq[i].ctx = swap_common_inq[i-1].ctx;
3118                 ctrl->out->inq[i].idx = swap_common_inq[i-1].idx;
3119         }
3120
3121         spin_unlock_irqrestore(&ctrl->out->lock_in, spin_flags);
3122
3123         return 0;
3124 }
3125
3126 int fimc_pop_inq(struct fimc_control *ctrl, int *ctx_num, int *idx)
3127 {
3128         struct fimc_ctx *ctx;
3129         unsigned long spin_flags;
3130         int i, ret = 0;
3131         int ctx_idx = -1;
3132
3133         spin_lock_irqsave(&ctrl->out->lock_in, spin_flags);
3134
3135         /* find valid index from common incoming queue */
3136         for (i = (FIMC_INQUEUES-1); i >= 0; i--) {
3137                 if (ctrl->out->inq[i].ctx != -1) {
3138                         *ctx_num = ctrl->out->inq[i].ctx;
3139                         *idx = ctrl->out->inq[i].idx;
3140                         ctrl->out->inq[i].ctx = -1;
3141                         ctrl->out->inq[i].idx = -1;
3142                         break;
3143                 }
3144         }
3145
3146         /* common incoming queue is empty. */
3147         if (i < 0) {
3148                 spin_unlock_irqrestore(&ctrl->out->lock_in, spin_flags);
3149                 return -EINVAL;
3150         }
3151
3152         /* find valid index from incoming queue. */
3153         ctx = &ctrl->out->ctx[*ctx_num];
3154         for (i = (FIMC_OUTBUFS-1); i >= 0; i--) {
3155                 if (ctx->inq[i] != -1) {
3156                         ctx_idx = ctx->inq[i];
3157                         ctx->inq[i] = -1;
3158                         ctx->src[ctx_idx].state = VIDEOBUF_ACTIVE;
3159                         ctx->src[ctx_idx].flags = V4L2_BUF_FLAG_MAPPED;
3160                         break;
3161                 }
3162         }
3163
3164         if (*idx != ctx_idx)
3165                 fimc_err("common inq(%d) vs inq(%d) mismatch\n", *idx, ctx_idx);
3166
3167         /* incoming queue is empty. */
3168         if (i < 0)
3169                 ret = -EINVAL;
3170         else
3171                 fimc_dbg("%s: index = %d\n", __func__, *idx);
3172
3173         spin_unlock_irqrestore(&ctrl->out->lock_in, spin_flags);
3174
3175         return ret;
3176 }
3177
3178 int fimc_push_outq(struct fimc_control *ctrl, struct fimc_ctx *ctx, int idx)
3179 {
3180         unsigned long spin_flags;
3181         int swap_queue[FIMC_OUTBUFS];
3182         int i;
3183
3184         fimc_dbg("%s: index = %d\n", __func__, idx);
3185
3186         spin_lock_irqsave(&ctrl->out->lock_out, spin_flags);
3187
3188         /* Backup original queue */
3189         for (i = 0; i < FIMC_OUTBUFS; i++)
3190                 swap_queue[i] = ctx->outq[i];
3191
3192         /* Attach new index */
3193         ctx->outq[0] = idx;
3194         ctx->src[idx].state = VIDEOBUF_DONE;
3195         ctx->src[idx].flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE;
3196
3197         /* Shift the origonal queue */
3198         for (i = 1; i < FIMC_OUTBUFS; i++)
3199                 ctx->outq[i] = swap_queue[i-1];
3200
3201         spin_unlock_irqrestore(&ctrl->out->lock_out, spin_flags);
3202
3203         return 0;
3204 }
3205
3206 int fimc_pop_outq(struct fimc_control *ctrl, struct fimc_ctx *ctx, int *idx)
3207 {
3208         unsigned long spin_flags;
3209         int i, ret = 0;
3210
3211         spin_lock_irqsave(&ctrl->out->lock_out, spin_flags);
3212
3213         /* Find last valid idx in outgoing queue. */
3214         for (i = (FIMC_OUTBUFS-1); i >= 0; i--) {
3215                 if (ctx->outq[i] != -1) {
3216                         *idx = ctx->outq[i];
3217                         ctx->outq[i] = -1;
3218                         ctx->src[*idx].state = VIDEOBUF_IDLE;
3219                         ctx->src[*idx].flags = V4L2_BUF_FLAG_MAPPED;
3220                         break;
3221                 }
3222         }
3223
3224         /* outgoing queue is empty. */
3225         if (i < 0) {
3226                 ret = -EINVAL;
3227                 fimc_dbg("%s: outgoing queue : %d, %d, %d\n", __func__,
3228                                 ctx->outq[0], ctx->outq[1], ctx->outq[2]);
3229         } else
3230                 fimc_dbg("%s: idx = %d\n", __func__, *idx);
3231
3232
3233         spin_unlock_irqrestore(&ctrl->out->lock_out, spin_flags);
3234
3235         return ret;
3236 }
3237
3238 void fimc_dump_context(struct fimc_control *ctrl, struct fimc_ctx *ctx)
3239 {
3240         int i = 0;
3241
3242         fimc_err("ctx%d, ctrl->status: %d, ctx->status: %d\n",
3243                 ctx->ctx_num, ctrl->status, ctx->status);
3244
3245         for (i = 0; i < FIMC_INQUEUES; i++)
3246                 fimc_err("ctrl->inq[%d]: ctx(%d) idx(%d)\n",
3247                         i, ctrl->out->inq[i].ctx, ctrl->out->inq[i].idx);
3248
3249         for (i = 0; i < FIMC_OUTBUFS; i++)
3250                 fimc_err("inq[%d] = %d\n", i, ctx->inq[i]);
3251
3252         for (i = 0; i < FIMC_OUTBUFS; i++)
3253                 fimc_err("outq[%d] = %d\n", i, ctx->outq[i]);
3254
3255         fimc_err("state : prev.ctx(%d), prev.idx(%d) "
3256                         "active.ctx(%d), active.idx(%d) "
3257                         "next.ctx(%d), next.idx(%d)\n",
3258                 ctrl->out->idxs.prev.ctx, ctrl->out->idxs.prev.idx,
3259                 ctrl->out->idxs.active.ctx, ctrl->out->idxs.active.idx,
3260                 ctrl->out->idxs.next.ctx, ctrl->out->idxs.next.idx);
3261 }
3262
3263 void fimc_print_signal(struct fimc_control *ctrl)
3264 {
3265         if (signal_pending(current)) {
3266                 fimc_dbg(".pend=%.8lx shpend=%.8lx\n",
3267                         current->pending.signal.sig[0],
3268                         current->signal->shared_pending.signal.sig[0]);
3269         } else {
3270                 fimc_dbg(":pend=%.8lx shpend=%.8lx\n",
3271                         current->pending.signal.sig[0],
3272                         current->signal->shared_pending.signal.sig[0]);
3273         }
3274 }