1 /* linux/drivers/media/video/samsung/fimc/fimc_output.c
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
6 * V4L2 Output device support file for Samsung Camera Interface (FIMC) driver
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.
13 #include <linux/slab.h>
14 #include <linux/bootmem.h>
15 #include <linux/string.h>
16 #include <linux/platform_device.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>
23 #include <media/videobuf-core.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>
35 #include <plat/sysmmu.h>
37 static __u32 fimc_get_pixel_format_type(__u32 pixelformat)
39 switch (pixelformat) {
40 case V4L2_PIX_FMT_RGB32:
41 case V4L2_PIX_FMT_RGB565:
44 case V4L2_PIX_FMT_NV12:
45 case V4L2_PIX_FMT_NV12T:
46 case V4L2_PIX_FMT_NV21:
47 case V4L2_PIX_FMT_YUV420:
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:
64 void fimc_outdev_set_src_addr(struct fimc_control *ctrl, dma_addr_t *base)
66 fimc_hwset_addr_change_disable(ctrl);
67 fimc_hwset_input_address(ctrl, base);
68 fimc_hwset_addr_change_enable(ctrl);
71 int fimc_outdev_start_camif(void *param)
73 struct fimc_control *ctrl = (struct fimc_control *)param;
75 fimc_hwset_start_scaler(ctrl);
76 fimc_hwset_enable_capture(ctrl, 0); /* bypass disable */
77 fimc_hwset_start_input_dma(ctrl);
82 static int fimc_outdev_stop_camif(void *param)
84 struct fimc_control *ctrl = (struct fimc_control *)param;
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);
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)
97 struct s3cfb_user_window window;
98 int window_id = ((ctrl->id == 3) ? 2 : ctrl->id);
101 fimc_dbg("%s: called\n", __func__);
103 ret = wait_event_timeout(ctrl->wq, (ctx->status == FIMC_STREAMOFF),
104 FIMC_ONESHOT_TIMEOUT);
106 fimc_err("Fail: %s ctx->status=%d\n", __func__, ctx->status);
108 fimc_outdev_stop_camif(ctrl);
110 if (ctx->overlay.mode == FIMC_OVLY_DMA_MANUAL)
113 ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_OFF,
114 (unsigned long)NULL);
116 fimc_err("direct_ioctl(S3CFB_SET_WIN_OFF) fail\n");
120 /* reset WIN position */
121 memset(&window, 0, sizeof(window));
122 ret = s3cfb_direct_ioctl(window_id, S3CFB_WIN_POSITION,
123 (unsigned long)&window);
125 fimc_err("direct_ioctl(S3CFB_WIN_POSITION) fail\n");
129 ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_ADDR, 0x00000000);
131 fimc_err("direct_ioctl(S3CFB_SET_WIN_ADDR) fail\n");
135 ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_MEM, DMA_MEM_NONE);
137 fimc_err("direct_ioctl(S3CFB_SET_WIN_MEM) fail\n");
141 ctrl->fb.is_enable = 0;
147 static int fimc_outdev_stop_fifo(struct fimc_control *ctrl,
148 struct fimc_ctx *ctx)
150 struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
153 fimc_dbg("%s: called\n", __func__);
155 if (pdata->hw_ver == 0x40) { /* to support C100 */
156 ret = ctrl->fb.close_fifo(ctrl->id, fimc_outdev_stop_camif,
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);
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)
176 int fimc_outdev_stop_streaming(struct fimc_control *ctrl, struct fimc_ctx *ctx)
180 fimc_dbg("%s: called\n", __func__);
182 switch (ctx->overlay.mode) {
184 ctx->status = FIMC_READY_OFF;
185 fimc_outdev_stop_fifo(ctrl, ctx);
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;
192 ctx->status = FIMC_READY_OFF;
194 #if (!defined(CONFIG_S5PV310_DEV_PD) || !defined(CONFIG_PM_RUNTIME))
195 fimc_outdev_stop_dma(ctrl, ctx);
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;
203 ctx->status = FIMC_READY_OFF;
205 ret = wait_event_timeout(ctrl->wq,
206 (ctx->status == FIMC_STREAMOFF),
207 FIMC_ONESHOT_TIMEOUT);
209 fimc_dump_context(ctrl, ctx);
210 fimc_err("fail %s: %d\n", __func__, ctx->ctx_num);
221 static int fimc_outdev_dma_auto_dst_resize(struct v4l2_rect *org)
224 org->width = org->width + 16 - (org->width % 16);
229 int fimc_outdev_resume_dma(struct fimc_control *ctrl, struct fimc_ctx *ctx)
231 struct v4l2_rect fimd_rect, fimd_rect_virtual;
232 struct fb_var_screeninfo var;
233 struct s3cfb_user_window window;
235 int window_id = ((ctrl->id == 3) ? 2 : ctrl->id);
237 memset(&fimd_rect, 0, sizeof(struct v4l2_rect));
238 ret = fimc_fimd_rect(ctrl, ctx, &fimd_rect);
240 fimc_err("fimc_fimd_rect fail\n");
244 /* Support any size */
245 memcpy(&fimd_rect_virtual, &fimd_rect, sizeof(fimd_rect));
246 fimc_outdev_dma_auto_dst_resize(&fimd_rect_virtual);
248 /* Get WIN var_screeninfo */
249 ret = s3cfb_direct_ioctl(window_id, FBIOGET_VSCREENINFO,
250 (unsigned long)&var);
252 fimc_err("direct_ioctl(FBIOGET_VSCREENINFO) fail\n");
256 /* window path : DMA */
257 ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_PATH, DATA_PATH_DMA);
259 fimc_err("direct_ioctl(S3CFB_SET_WIN_PATH) fail\n");
263 /* Don't allocate the memory. */
264 ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_MEM, DMA_MEM_OTHER);
266 fimc_err("direct_ioctl(S3CFB_SET_WIN_MEM) fail\n");
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;
276 ret = s3cfb_direct_ioctl(window_id, FBIOPUT_VSCREENINFO,
277 (unsigned long)&var);
279 fimc_err("direct_ioctl(FBIOPUT_VSCREENINFO) fail\n");
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);
289 fimc_err("direct_ioctl(S3CFB_WIN_POSITION) fail\n");
295 fimc_err("out going queue is empty.\n");
299 ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_ADDR,
300 (unsigned long)ctx->dst[idx].base[FIMC_ADDR_Y]);
302 fimc_err("direct_ioctl(S3CFB_SET_WIN_ADDR) fail\n");
307 /* Remarked for better screen display
308 * when dynamic screen size change is requested
310 ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_ON,
311 (unsigned long)NULL);
313 fimc_err("direct_ioctl(S3CFB_SET_WIN_ON) fail\n");
318 ctrl->fb.is_enable = 1;
323 static void fimc_init_out_buf(struct fimc_ctx *ctx)
327 for (i = 0; i < FIMC_OUTBUFS; i++) {
328 ctx->src[i].state = VIDEOBUF_IDLE;
329 ctx->src[i].flags = 0x0;
336 static int fimc_outdev_set_src_buf(struct fimc_control *ctrl,
337 struct fimc_ctx *ctx)
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;
345 dma_addr_t *curr = &ctrl->mem.curr;
348 case V4L2_PIX_FMT_RGB32:
349 size = PAGE_ALIGN(y_size << 2);
351 case V4L2_PIX_FMT_RGB565: /* fall through */
352 case V4L2_PIX_FMT_YUYV:
353 size = PAGE_ALIGN(y_size << 1);
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);
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);
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);
370 fimc_err("%s: Invalid pixelformt : %d\n", __func__, format);
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);
384 /* Initialize source buffer addr */
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;
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;
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;
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;
435 fimc_err("%s: Invalid pixelformt : %d\n", __func__, format);
442 #ifdef CONFIG_VIDEO_FIMC_UMP_VCM_CMA
443 int fimc_vcm_alloc_outbuf(struct fimc_control *ctrl, int buf_num, int buf_size)
445 unsigned long arg = 0;
446 struct ump_vcm ump_vcm;
447 struct vcm_phys *phys = NULL;
448 dma_addr_t phys_addr;
450 phys = kmalloc(sizeof(*phys) + sizeof(*phys->parts), GFP_KERNEL);
451 memset(phys, 0, sizeof(*phys) + sizeof(*phys->parts));
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);
458 phys->size = buf_size;
460 phys->parts[0].start = phys_addr;
461 phys->parts[0].size = buf_size;
463 ctrl->dev_vcm_res[buf_num] = vcm_map(ctrl->dev_vcm, phys, 0);
465 /* physical address */
466 ctrl->mem.base = ctrl->dev_vcm_res[buf_num]->phys->parts->start;
468 /* virtual address */
469 ctrl->mem.vaddr_base = ctrl->dev_vcm_res[buf_num]->start;
471 ctrl->mem.curr = ctrl->mem.base;
472 ctrl->mem.vaddr_curr = ctrl->mem.vaddr_base;
474 fimc_info1("%s : vaddr base : 0x%x\n", __func__, ctrl->mem.vaddr_base);
475 ctrl->mem.size = buf_size;
478 ctrl->ump_memory_description.addr = ctrl->mem.base;
479 ctrl->ump_memory_description.size = ctrl->mem.size;
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;
486 ctrl->ump_wrapped_buffer[buf_num] =
487 ump_dd_handle_create_from_phys_blocks(&ctrl->ump_memory_description, 1);
489 if (UMP_DD_HANDLE_INVALID == ctrl->ump_wrapped_buffer[buf_num]) {
490 fimc_err("%s : ump_wrapped_buffer is unhandled\n", __func__);
493 #ifdef CONFIG_UMP_VCM_ALLOC
494 if (ump_dd_vcm_attribute_set(ctrl->ump_wrapped_buffer[buf_num], arg))
500 int fimc_vcm_free_outbuf(struct fimc_control *ctrl, int buf_num, int phy_addr)
502 kfree(ctrl->dev_vcm_res[buf_num]->phys);
503 vcm_unmap(ctrl->dev_vcm_res[buf_num]);
508 static int fimc_outdev_set_dst_buf(struct fimc_control *ctrl,
509 struct fimc_ctx *ctx)
512 struct vcm_res *vcm_res;
514 u32 width = ctrl->fb.lcd_hres;
515 u32 height = ctrl->fb.lcd_vres;
518 size = PAGE_ALIGN(width * height * 4);
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;
536 dma_addr_t *curr = &ctrl->mem.curr;
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);
542 end = ctrl->mem.base + ctrl->mem.size;
543 size = PAGE_ALIGN(width * height * 4);
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);
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;
570 static int fimc_set_rot_degree(struct fimc_control *ctrl,
571 struct fimc_ctx *ctx,
575 case 0: /* fall through */
576 case 90: /* fall through */
577 case 180: /* fall through */
579 ctx->rotate = degree;
583 fimc_err("Invalid rotate value : %d\n", degree);
590 int fimc_outdev_check_param(struct fimc_control *ctrl,
591 struct fimc_ctx *ctx)
593 struct v4l2_rect dst, bound = { 0, };
595 int ret = 0, i, exclusive = 0;
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;
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;
609 bound.width = ctrl->fb.lcd_hres;
610 bound.height = ctrl->fb.lcd_vres;
613 case FIMC_OVLY_DMA_AUTO: /* fall through */
614 case FIMC_OVLY_DMA_MANUAL:
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;
623 fimc_err("%s: invalid ovelay mode.\n", __func__);
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);
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);
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__);
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:
659 case FIMC_OVLY_NONE_SINGLE_BUF: /* fall through */
660 case FIMC_OVLY_NONE_MULTI_BUF: /* fall through */
661 case FIMC_OVLY_NOT_FIXED:
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);
676 static void fimc_outdev_set_src_format(struct fimc_control *ctrl,
677 u32 pixfmt, enum v4l2_field field)
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);
688 static void fimc_outdev_set_dst_format(struct fimc_control *ctrl,
689 struct v4l2_pix_format *pixfmt)
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);
698 static void fimc_outdev_set_format(struct fimc_control *ctrl,
699 struct fimc_ctx *ctx)
701 struct v4l2_pix_format pixfmt;
702 memset(&pixfmt, 0, sizeof(pixfmt));
704 fimc_outdev_set_src_format(ctrl, ctx->pix.pixelformat, ctx->pix.field);
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;
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;
729 fimc_err("Invalid overlay mode %d\n", ctx->overlay.mode);
733 fimc_outdev_set_dst_format(ctrl, &pixfmt);
736 static void fimc_outdev_set_path(struct fimc_control *ctrl,
737 struct fimc_ctx *ctx)
740 fimc_hwset_input_source(ctrl, FIMC_SRC_MSDMA);
742 if (ctx->overlay.mode == FIMC_OVLY_FIFO) {
743 fimc_hwset_enable_lcdfifo(ctrl);
744 fimc_hwset_enable_autoload(ctrl);
746 fimc_hwset_disable_lcdfifo(ctrl);
747 fimc_hwset_disable_autoload(ctrl);
751 static void fimc_outdev_set_rot(struct fimc_control *ctrl,
752 struct fimc_ctx *ctx)
754 u32 rot = ctx->rotate;
755 u32 flip = ctx->flip;
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);
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);
768 static void fimc_outdev_set_src_dma_offset(struct fimc_control *ctrl,
769 struct fimc_ctx *ctx)
771 struct v4l2_rect bound, crop;
772 u32 pixfmt = ctx->pix.pixelformat;
774 bound.width = ctx->pix.width;
775 bound.height = ctx->pix.height;
777 crop.left = ctx->crop.left;
778 crop.top = ctx->crop.top;
779 crop.width = ctx->crop.width;
780 crop.height = ctx->crop.height;
782 fimc_hwset_input_offset(ctrl, pixfmt, &bound, &crop);
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)
790 u32 rot = ctx->rotate;
792 if ((ctx->overlay.mode == FIMC_OVLY_FIFO) &&
793 ((rot == 90) || (rot == 270))) {
795 if (real->height % 16) {
796 fimc_err("SRC Real_H(%d): multiple of 16 !\n",
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",
811 if (ctx->sc.pre_vratio) {
812 if (real->width % ctx->sc.pre_vratio) {
813 fimc_err("SRC Real_W(%d): multiple of "
821 if (real->height < 16) {
822 fimc_err("SRC Real_H(%d): Min 16\n", real->height);
825 if (real->width < 8) {
826 fimc_err("SRC Real_W(%d): Min 8\n", real->width);
830 /* No Input Rotator */
831 if (real->height < 8) {
832 fimc_err("SRC Real_H(%d): Min 8\n", real->height);
836 if (real->width < 16) {
837 fimc_err("SRC Real_W(%d): Min 16\n", real->width);
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);
848 if (org->height < real->height) {
849 fimc_err("SRC Org_H(%d): larger than Real_H(%d)\n",
850 org->height, real->height);
854 if (org->width < real->width) {
855 fimc_err("SRC Org_W: Org_W(%d) >= Real_W(%d)\n", org->width,
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);
868 if (real->width % 16) {
869 fimc_err("SRC Real_W(%d): multiple of 16 !\n", real->width);
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);
882 if (org->width % 16) {
883 fimc_err("SRC Org_W(%d): multiple of 16\n", org->width);
887 if (org->height < 8) {
888 fimc_err("SRC Org_H(%d): Min 8\n", org->height);
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)
900 u32 rot = ctx->rotate;
901 u32 pixelformat = ctx->pix.pixelformat;
903 if ((ctx->overlay.mode == FIMC_OVLY_FIFO) &&
904 ((rot == 90) || (rot == 270))) {
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",
916 if (real->height < 16) {
917 fimc_err("SRC Real_H(%d): Min 16\n", real->height);
920 if (real->width < 8) {
921 fimc_err("SRC Real_W(%d): Min 8\n", real->width);
925 /* No Input Rotator */
926 if (real->height < 8) {
927 fimc_err("SRC Real_H(%d): Min 8\n", real->height);
931 if (real->width < 16) {
932 fimc_err("SRC Real_W(%d): Min 16\n", real->width);
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);
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);
951 if (org->width < real->width) {
952 fimc_err("SRC Org_W: Org_W(%d) >= Real_W(%d)\n",
953 org->width, real->width);
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",
966 case V4L2_PIX_FMT_YUV422P:
967 if (real->height % 2) {
968 fimc_err("SRC Real_H(%d): multiple of 2\n",
971 } else if (real->width % 2) {
972 fimc_err("SRC Real_H(%d): multiple of 2\n",
976 case V4L2_PIX_FMT_YVU420:
977 if (real->height % 4) {
978 fimc_err("SRC Real_H(%d): multiple of 4\n",
981 } else if (real->width % 2) {
982 fimc_err("SRC Real_H(%d): multiple of 2\n",
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",
993 } else if (real->width % 2) {
994 fimc_err("SRC Real_H(%d): multiple of 2\n",
1004 static int fimc_outdev_set_src_dma_size(struct fimc_control *ctrl,
1005 struct fimc_ctx *ctx)
1007 struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
1008 struct v4l2_rect real, org;
1011 real.width = ctx->crop.width;
1012 real.height = ctx->crop.height;
1013 org.width = ctx->pix.width;
1014 org.height = ctx->pix.height;
1016 if (pdata->hw_ver >= 0x50)
1017 ret = fimc50_outdev_check_src_size(ctrl, ctx, &real, &org);
1019 ret = fimc4x_outdev_check_src_size(ctrl, ctx, &real, &org);
1024 fimc_hwset_org_input_size(ctrl, org.width, org.height);
1025 fimc_hwset_real_input_size(ctrl, real.width, real.height);
1030 static void fimc_outdev_set_dst_dma_offset(struct fimc_control *ctrl,
1031 struct fimc_ctx *ctx)
1033 struct v4l2_rect bound, win;
1034 struct v4l2_rect *w = &ctx->win.w;
1035 u32 pixfmt = ctx->fbuf.fmt.pixelformat;
1037 memset(&bound, 0, sizeof(bound));
1038 memset(&win, 0, sizeof(win));
1040 switch (ctx->rotate) {
1042 bound.width = ctx->fbuf.fmt.width;
1043 bound.height = ctx->fbuf.fmt.height;
1047 win.width = w->width;
1048 win.height = w->height;
1052 bound.width = ctx->fbuf.fmt.height;
1053 bound.height = ctx->fbuf.fmt.width;
1055 win.left = ctx->fbuf.fmt.height - (w->height + w->top);
1057 win.width = w->height;
1058 win.height = w->width;
1062 bound.width = ctx->fbuf.fmt.width;
1063 bound.height = ctx->fbuf.fmt.height;
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;
1072 bound.width = ctx->fbuf.fmt.height;
1073 bound.height = ctx->fbuf.fmt.width;
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;
1082 fimc_err("Rotation degree is invalid(%d)\n", ctx->rotate);
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);
1095 fimc_hwset_output_offset(ctrl, pixfmt, &bound, &win);
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);
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)
1109 u32 rot = ctx->rotate;
1112 pixel_type = fimc_get_pixel_format_type(ctx->fbuf.fmt.pixelformat);
1114 if (FIMC_YUV420 == pixel_type && real->height % 2) {
1115 fimc_err("DST Real_H(%d): even number for YUV420 formats\n",
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);
1129 if (org->width < real->height) {
1130 fimc_err("DST Org_W: Org_W(%d) >= Real_H(%d)\n",
1131 org->width, real->height);
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);
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);
1147 if (org->height < real->height) {
1148 fimc_err("DST Org_H: Org_H(%d) >= Real_H(%d)\n",
1149 org->height, real->height);
1153 if (org->width % 8) {
1154 fimc_err("DST Org_W: multiple of 8\n");
1158 if (org->width < real->width) {
1159 fimc_err("DST Org_W: Org_W(%d) >= Real_W(%d)\n",
1160 org->width, real->width);
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);
1174 static int fimc_outdev_set_dst_dma_size(struct fimc_control *ctrl,
1175 struct fimc_ctx *ctx)
1177 struct v4l2_rect org, real;
1180 memset(&org, 0, sizeof(org));
1181 memset(&real, 0, sizeof(real));
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;
1189 switch (ctx->rotate) {
1190 case 0: /* fall through */
1192 org.width = ctx->fbuf.fmt.width;
1193 org.height = ctx->fbuf.fmt.height;
1195 case 90: /* fall through */
1197 org.width = ctx->fbuf.fmt.height;
1198 org.height = ctx->fbuf.fmt.width;
1201 fimc_err("Rotation degree is invalid(%d)\n",
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;
1213 switch (ctx->rotate) {
1214 case 0: /* fall through */
1216 org.width = ctx->win.w.width;
1217 org.height = ctx->win.w.height;
1219 case 90: /* fall through */
1221 org.width = ctx->win.w.height;
1222 org.height = ctx->win.w.width;
1225 fimc_err("Rotation degree is invalid(%d)\n",
1231 case FIMC_OVLY_FIFO:
1232 switch (ctx->rotate) {
1233 case 0: /* fall through */
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;
1240 case 90: /* fall through */
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;
1249 fimc_err("Rotation degree is invalid(%d)\n",
1259 if (ctx->overlay.mode == FIMC_OVLY_DMA_AUTO)
1260 fimc_outdev_dma_auto_dst_resize(&org);
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);
1265 ret = fimc_outdev_check_dst_size(ctrl, ctx, &real, &org);
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);
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)
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;
1290 switch (ctx->rotate) {
1291 case 0: /* fall through */
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;
1298 case 90: /* fall through */
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;
1306 fimc_err("Rotation degree is invalid(%d)\n",
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);
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)
1321 u32 pixels = 0, dstfmt = 0;
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);
1330 /* SRC width double boundary check */
1331 switch (ctx->pix.pixelformat) {
1332 case V4L2_PIX_FMT_RGB32:
1335 case V4L2_PIX_FMT_YUYV: /* fall through */
1336 case V4L2_PIX_FMT_RGB565:
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:
1346 fimc_err("Invalid color format(0x%x)\n", ctx->pix.pixelformat);
1350 if (src->width % pixels) {
1351 fimc_err("source width(%d) multiple of %d pixels\n", src->width,
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;
1363 case FIMC_OVLY_NONE_SINGLE_BUF: /* fall through */
1364 case FIMC_OVLY_NONE_MULTI_BUF:
1365 dstfmt = ctx->fbuf.fmt.pixelformat;
1372 case V4L2_PIX_FMT_RGB32:
1375 case V4L2_PIX_FMT_RGB565:
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:
1385 fimc_err("Invalid color format(0x%x)\n", dstfmt);
1389 if (dst->width % pixels) {
1390 fimc_err("source width(%d) multiple of %d pixels\n",
1391 dst->width, pixels);
1398 static int fimc_outdev_set_scaler(struct fimc_control *ctrl,
1399 struct fimc_ctx *ctx)
1401 struct v4l2_rect src, dst;
1403 struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
1405 memset(&src, 0, sizeof(src));
1406 memset(&dst, 0, sizeof(dst));
1408 fimc_outdev_calibrate_scale_info(ctrl, ctx, &src, &dst);
1410 ret = fimc_get_scaler_factor(src.width, dst.width,
1411 &ctx->sc.pre_hratio, &ctx->sc.hfactor);
1413 fimc_err("Fail : Out of Width scale range(%d, %d)\n",
1414 src.width, dst.width);
1418 ret = fimc_get_scaler_factor(src.height, dst.height,
1419 &ctx->sc.pre_vratio, &ctx->sc.vfactor);
1421 fimc_err("Fail : Out of Height scale range(%d, %d)\n",
1422 src.height, dst.height);
1426 ctx->sc.pre_dst_width = src.width / ctx->sc.pre_hratio;
1427 ctx->sc.pre_dst_height = src.height / ctx->sc.pre_vratio;
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);
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);
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);
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);
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);
1456 if (pdata->hw_ver < 0x50) {
1457 ret = fimc_outdev_check_scaler(ctrl, ctx, &src, &dst);
1462 fimc_hwset_prescaler(ctrl, &ctx->sc);
1463 fimc_hwset_scaler(ctrl, &ctx->sc);
1468 int fimc_outdev_set_ctx_param(struct fimc_control *ctrl, struct fimc_ctx *ctx)
1471 #if defined(CONFIG_VIDEO_IPC)
1473 struct v4l2_rect src, dst;
1474 memset(&src, 0, sizeof(src));
1475 memset(&dst, 0, sizeof(dst));
1478 if ((ctrl->status == FIMC_READY_ON) ||
1479 (ctrl->status == FIMC_STREAMON_IDLE))
1480 fimc_hwset_enable_irq(ctrl, 0, 1);
1482 #if (defined(CONFIG_S5PV310_DEV_PD) && defined(CONFIG_PM_RUNTIME))
1483 fimc_hwset_output_buf_sequence_all(ctrl, FRAME_SEQ);
1486 fimc_outdev_set_format(ctrl, ctx);
1487 fimc_outdev_set_path(ctrl, ctx);
1488 fimc_outdev_set_rot(ctrl, ctx);
1490 fimc_outdev_set_src_dma_offset(ctrl, ctx);
1491 ret = fimc_outdev_set_src_dma_size(ctrl, ctx);
1495 fimc_outdev_set_dst_dma_offset(ctrl, ctx);
1497 ret = fimc_outdev_set_dst_dma_size(ctrl, ctx);
1501 ret = fimc_outdev_set_scaler(ctrl, ctx);
1505 #if defined(CONFIG_VIDEO_IPC)
1506 if (ctx->overlay.mode == FIMC_OVLY_FIFO)
1507 if (ctx->pix.field == V4L2_FIELD_INTERLACED_TB)
1511 fimc_outdev_calibrate_scale_info(ctrl, ctx, &src, &dst);
1512 ret = ipc_init(dst.width, dst.height/2, IPC_2D);
1521 int fimc_fimd_rect(const struct fimc_control *ctrl,
1522 const struct fimc_ctx *ctx,
1523 struct v4l2_rect *fimd_rect)
1525 switch (ctx->rotate) {
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;
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;
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;
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;
1563 fimc_err("Rotation degree is invalid(%d)\n", ctx->rotate);
1572 int fimc_start_fifo(struct fimc_control *ctrl, struct fimc_ctx *ctx)
1574 struct v4l2_rect fimd_rect;
1575 struct fb_var_screeninfo var;
1576 struct s3cfb_user_window window;
1578 int window_id = ((ctrl->id == 3) ? 2 : ctrl->id);
1580 memset(&fimd_rect, 0, sizeof(struct v4l2_rect));
1581 ret = fimc_fimd_rect(ctrl, ctx, &fimd_rect);
1583 fimc_err("fimc_fimd_rect fail\n");
1587 /* Get WIN var_screeninfo */
1588 ret = s3cfb_direct_ioctl(window_id, FBIOGET_VSCREENINFO,
1589 (unsigned long)&var);
1591 fimc_err("direct_ioctl(FBIOGET_VSCREENINFO) fail\n");
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);
1603 fimc_err("direct_ioctl(S3CFB_SET_WIN_PATH) fail\n");
1607 ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_MEM, DMA_MEM_NONE);
1609 fimc_err("direct_ioctl(S3CFB_SET_WIN_MEM) fail\n");
1613 ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_ADDR, 0x00000000);
1615 fimc_err("direct_ioctl(S3CFB_SET_WIN_ADDR) fail\n");
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);
1627 fimc_err("direct_ioctl(FBIOPUT_VSCREENINFO) fail\n");
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);
1637 fimc_err("direct_ioctl(S3CFB_WIN_POSITION) fail\n");
1642 ret = ctrl->fb.open_fifo(window_id, 0, fimc_outdev_start_camif, (void *)ctrl);
1644 fimc_err("FIMD FIFO close fail\n");
1651 int fimc_outdev_overlay_buf(struct file *filp,
1652 struct fimc_control *ctrl,
1653 struct fimc_ctx *ctx)
1656 struct fimc_overlay_buf *buf;
1658 buf = &ctx->overlay.buf;
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__);
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]);
1676 ctx->overlay.req_idx = -1;
1681 int fimc_reqbufs_output(void *fh, struct v4l2_requestbuffers *b)
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;
1691 ctx = &ctrl->out->ctx[ctx_id];
1692 buf = &ctx->overlay.buf;
1693 mode = ctx->overlay.mode;
1695 fimc_info1("%s: called\n", __func__);
1697 if (ctx->status != FIMC_STREAMOFF) {
1698 fimc_err("%s: FIMC is running\n", __func__);
1702 if (ctx->is_requested == 1 && b->count != 0) {
1703 fimc_err("Buffers were already requested\n");
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;
1713 #if (!defined(CONFIG_S5PV310_DEV_PD) || !defined(CONFIG_PM_RUNTIME))
1714 fimc_hwset_output_buf_sequence_all(ctrl, FRAME_SEQ);
1717 fimc_init_out_buf(ctx);
1718 ctx->is_requested = 0;
1720 if (b->count == 0) {
1721 ctrl->mem.curr = ctrl->mem.base;
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]) {
1732 fimc_err("%s: do_munmap fail. "
1733 "vir_addr[%d](0x%08x)\n",
1734 __func__, i, buf->vir_addr[i]);
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;
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;
1754 ctx->is_requested = 1;
1757 ctx->buf_num = b->count;
1762 int fimc_querybuf_output(void *fh, struct v4l2_buffer *b)
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;
1769 fimc_info1("%s: called\n", __func__);
1771 ctx = &ctrl->out->ctx[ctx_id];
1772 if (ctx->status != FIMC_STREAMOFF) {
1773 fimc_err("%s: FIMC is running\n", __func__);
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);
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);
1793 int fimc_g_ctrl_output(void *fh, struct v4l2_control *c)
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];
1801 if (ctx->status != FIMC_STREAMOFF) {
1802 fimc_err("%s: FIMC is running\n", __func__);
1807 case V4L2_CID_ROTATION:
1808 c->value = ctx->rotate;
1811 case V4L2_CID_HFLIP:
1812 if (ctx->flip & V4L2_CID_HFLIP)
1818 case V4L2_CID_VFLIP:
1819 if (ctx->flip & V4L2_CID_VFLIP)
1825 #ifdef CONFIG_VIDEO_FIMC_UMP_VCM_CMA
1826 case V4L2_CID_GET_UMP_SECURE_ID:
1828 ump_secure_id secure_id =
1829 ump_dd_secure_id_get(ctrl->ump_wrapped_buffer);
1831 fimc_info1("%s : ump_secure_id : %d\n", __func__, secure_id);
1835 case V4L2_CID_OVERLAY_VADDR0:
1836 c->value = ctx->overlay.buf.vir_addr[0];
1839 case V4L2_CID_OVERLAY_VADDR1:
1840 c->value = ctx->overlay.buf.vir_addr[1];
1843 case V4L2_CID_OVERLAY_VADDR2:
1844 c->value = ctx->overlay.buf.vir_addr[2];
1847 case V4L2_CID_OVERLAY_AUTO:
1848 if (ctx->overlay.mode == FIMC_OVLY_DMA_AUTO)
1854 case V4L2_CID_RESERVED_MEM_BASE_ADDR:
1855 c->value = ctrl->mem.base;
1858 case V4L2_CID_FIMC_VERSION:
1859 c->value = pdata->hw_ver;
1863 fimc_err("Invalid control id: %d\n", c->id);
1870 static int fimc_set_dst_info(struct fimc_control *ctrl,
1871 struct fimc_ctx *ctx,
1872 struct fimc_buf *fimc_buf)
1874 struct fimc_buf *buf;
1877 struct vcm_res *vcm_res;
1880 for (i = 0; i < ctx->buf_num; i++) {
1883 vcm_res = (struct vcm_res *)ump_dd_vcm_res_get(
1884 (unsigned int)buf->base[FIMC_ADDR_Y], ctrl->vcm_id);
1887 buf->base[FIMC_ADDR_Y] = vcm_res->start;
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];
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];
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];
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];
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];
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];
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;
1916 ctx->dst[i].base[FIMC_ADDR_CB] = 0;
1917 ctx->dst[i].length[FIMC_ADDR_CB] = 0;
1919 ctx->dst[i].base[FIMC_ADDR_CR] = 0;
1920 ctx->dst[i].length[FIMC_ADDR_CR] = 0;
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]);
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]);
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]);
1937 int fimc_s_ctrl_output(struct file *filp, void *fh, struct v4l2_control *c)
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;
1944 ctx = &ctrl->out->ctx[ctx_id];
1945 if (ctx->status != FIMC_STREAMOFF) {
1946 fimc_err("%s: FIMC is running\n", __func__);
1951 case V4L2_CID_ROTATION:
1952 ret = fimc_set_rot_degree(ctrl, ctx, c->value);
1955 case V4L2_CID_HFLIP:
1957 ctx->flip |= FIMC_XFLIP;
1959 ctx->flip &= ~FIMC_XFLIP;
1962 case V4L2_CID_VFLIP:
1964 ctx->flip |= FIMC_YFLIP;
1966 ctx->flip &= ~FIMC_YFLIP;
1969 case V4L2_CID_OVERLAY_AUTO:
1970 if (c->value == 1) {
1971 ctx->overlay.mode = FIMC_OVLY_DMA_AUTO;
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);
1979 case V4L2_CID_OVLY_MODE:
1980 ctx->overlay.mode = c->value;
1983 case V4L2_CID_DST_INFO:
1984 ret = fimc_set_dst_info(ctrl, ctx,
1985 (struct fimc_buf *)c->value);
1987 case V4L2_CID_GET_PHY_SRC_YADDR:
1988 c->value = ctx->src[c->value].base[FIMC_ADDR_Y];
1990 case V4L2_CID_GET_PHY_SRC_CADDR:
1991 c->value = ctx->src[c->value].base[FIMC_ADDR_CB];
1994 fimc_err("Invalid control id: %d\n", c->id);
2001 int fimc_cropcap_output(void *fh, struct v4l2_cropcap *a)
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;
2008 fimc_info1("%s: called\n", __func__);
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__);
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;
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");
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;
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;
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;
2061 a->bounds = ctx->cropcap.bounds;
2062 a->defrect = ctx->cropcap.defrect;
2063 a->pixelaspect = ctx->cropcap.pixelaspect;
2068 int fimc_g_crop_output(void *fh, struct v4l2_crop *a)
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;
2074 ctx = &ctrl->out->ctx[ctx_id];
2076 fimc_info1("%s: called\n", __func__);
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);
2088 int fimc_s_crop_output(void *fh, struct v4l2_crop *a)
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;
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);
2097 ctx = &ctrl->out->ctx[ctx_id];
2098 if (ctx->status != FIMC_STREAMOFF) {
2099 fimc_err("%s: FIMC is running\n", __func__);
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);
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);
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);
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);
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);
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);
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;
2151 int fimc_streamon_output(void *fh)
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;
2158 ctrl->log |= FIMC_LOG_INFO_L1;
2159 fimc_info1("%s: called\n", __func__);
2161 ctx = &ctrl->out->ctx[ctx_id];
2162 if (ctx->overlay.mode == FIMC_OVLY_NOT_FIXED)
2163 ctx->overlay.mode = FIMC_OVLY_MODE;
2165 /* initialize destination buffers */
2166 if (ctx->overlay.mode == FIMC_OVLY_DMA_AUTO) {
2167 ret = fimc_outdev_set_dst_buf(ctrl, ctx);
2172 ret = fimc_outdev_check_param(ctrl, ctx);
2174 fimc_err("Fail: fimc_outdev_check_param\n");
2178 ctx->status = FIMC_READY_ON;
2179 if (ctrl->status == FIMC_STREAMOFF)
2180 ctrl->status = FIMC_READY_ON;
2182 ctrl->log &= ~(FIMC_LOG_INFO_L1);
2186 void fimc_outdev_init_idxs(struct fimc_control *ctrl)
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;
2196 int fimc_streamoff_output(void *fh)
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);
2205 ctrl->log |= FIMC_LOG_INFO_L1;
2206 fimc_info1("%s: called\n", __func__);
2208 ctx = &ctrl->out->ctx[ctx_id];
2209 /* Move it to here to ignore fimc_irq_out_dma operation. */
2210 ctx->status = FIMC_STREAMOFF;
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);
2217 fimc_err("Fail: fimc_outdev_stop_streaming\n");
2221 /* Need some delay to waiting reamined operation */
2224 ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_OFF,
2225 (unsigned long)NULL);
2227 fimc_err("direct_ioctl(S3CFB_SET_WIN_OFF) fail\n");
2231 /* reset WIN position */
2232 memset(&window, 0, sizeof(window));
2233 ret = s3cfb_direct_ioctl(window_id, S3CFB_WIN_POSITION,
2234 (unsigned long)&window);
2236 fimc_err("direct_ioctl(S3CFB_WIN_POSITION) fail\n");
2240 ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_ADDR, 0x00000000);
2242 fimc_err("direct_ioctl(S3CFB_SET_WIN_ADDR) fail\n");
2246 ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_MEM, DMA_MEM_NONE);
2248 fimc_err("direct_ioctl(S3CFB_SET_WIN_MEM) fail\n");
2252 ctrl->fb.is_enable = 0;
2256 ret = fimc_init_in_queue(ctrl, ctx);
2258 fimc_err("Fail: fimc_init_in_queue\n");
2262 ret = fimc_init_out_queue(ctrl, ctx);
2264 fimc_err("Fail: fimc_init_out_queue\n");
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;
2274 if (ctrl->out->last_ctx == ctx->ctx_num)
2275 ctrl->out->last_ctx = -1;
2277 if (ctx->overlay.mode == FIMC_OVLY_DMA_AUTO) {
2278 ctrl->mem.curr = ctx->dst[0].base[FIMC_ADDR_Y];
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;
2287 ctx->dst[i].base[FIMC_ADDR_Y] = 0;
2288 ctx->dst[i].length[FIMC_ADDR_Y] = 0;
2290 ctx->dst[i].base[FIMC_ADDR_CB] = 0;
2291 ctx->dst[i].length[FIMC_ADDR_CB] = 0;
2293 ctx->dst[i].base[FIMC_ADDR_CR] = 0;
2294 ctx->dst[i].length[FIMC_ADDR_CR] = 0;
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)
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);
2312 ctrl->log &= ~(FIMC_LOG_INFO_L1);
2316 static int fimc_qbuf_output_single_buf(struct fimc_control *ctrl,
2317 struct fimc_ctx *ctx,
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;
2329 fimc_outdev_set_src_addr(ctrl, ctx->src[idx].base);
2331 memset(&buf_set, 0x00, sizeof(buf_set));
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;
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;
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;
2349 case V4L2_PIX_FMT_NV12T:
2350 if (rot == 0 || rot == 180)
2351 fimc_get_nv12t_size(width, height, &y_size, &c_size);
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;
2358 fimc_err("%s: Invalid pixelformt : %d\n", __func__, 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;
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;
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;
2377 case V4L2_PIX_FMT_NV12T:
2378 if (rot == 0 || rot == 180)
2379 fimc_get_nv12t_size(width, height, &y_size, &c_size);
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;
2386 fimc_err("%s: Invalid pixelformt : %d\n", __func__, format);
2390 cfg = fimc_hwget_output_buf_sequence(ctrl);
2392 for (i = 0; i < FIMC_PHYBUFS; i++) {
2393 if (check_bit(cfg, i))
2394 fimc_hwset_output_address(ctrl, &buf_set, i);
2397 ctrl->out->idxs.active.idx = idx;
2398 ctrl->out->idxs.active.ctx = ctx->ctx_num;
2400 ctrl->status = FIMC_STREAMON;
2401 ctx->status = FIMC_STREAMON;
2403 ret = fimc_outdev_start_camif(ctrl);
2405 fimc_err("Fail: fimc_start_camif\n");
2412 static int fimc_qbuf_output_multi_buf(struct fimc_control *ctrl,
2413 struct fimc_ctx *ctx,
2416 struct fimc_buf_set buf_set; /* destination addr */
2417 u32 format = ctx->fbuf.fmt.pixelformat;
2418 int ret = -1, i, cfg;
2420 fimc_outdev_set_src_addr(ctrl, ctx->src[idx].base);
2422 memset(&buf_set, 0x00, sizeof(buf_set));
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];
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];
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];
2441 fimc_err("%s: Invalid pixelformt : %d\n", __func__, 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];
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];
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];
2462 fimc_err("%s: Invalid pixelformt : %d\n", __func__, format);
2466 cfg = fimc_hwget_output_buf_sequence(ctrl);
2468 for (i = 0; i < FIMC_PHYBUFS; i++) {
2469 if (check_bit(cfg, i))
2470 fimc_hwset_output_address(ctrl, &buf_set, i);
2473 ctrl->out->idxs.active.idx = idx;
2474 ctrl->out->idxs.active.ctx = ctx->ctx_num;
2476 ctrl->status = FIMC_STREAMON;
2477 ctx->status = FIMC_STREAMON;
2479 ret = fimc_outdev_start_camif(ctrl);
2481 fimc_err("Fail: fimc_start_camif\n");
2488 static int fimc_qbuf_output_dma_auto(struct fimc_control *ctrl,
2489 struct fimc_ctx *ctx,
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);
2499 switch (ctx->status) {
2501 memset(&fimd_rect, 0, sizeof(struct v4l2_rect));
2502 ret = fimc_fimd_rect(ctrl, ctx, &fimd_rect);
2504 fimc_err("fimc_fimd_rect fail\n");
2508 /* Support any size */
2509 memcpy(&fimd_rect_virtual, &fimd_rect, sizeof(fimd_rect));
2510 fimc_outdev_dma_auto_dst_resize(&fimd_rect_virtual);
2512 if (ctrl->fb.is_enable == 1) {
2513 ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_OFF,
2514 (unsigned long)NULL);
2516 fimc_err("direct_ioctl(S3CFB_SET_WIN_OFF) fail\n");
2521 /* Get WIN var_screeninfo */
2522 ret = s3cfb_direct_ioctl(window_id, FBIOGET_VSCREENINFO,
2523 (unsigned long)&var);
2525 fimc_err("direct_ioctl(FBIOGET_VSCREENINFO) fail\n");
2528 /* window path : DMA */
2529 ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_PATH,
2532 fimc_err("direct_ioctl(S3CFB_SET_WIN_PATH) fail\n");
2536 /* Don't allocate the memory. */
2537 ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_MEM, DMA_MEM_OTHER);
2539 fimc_err("direct_ioctl(S3CFB_SET_WIN_MEM) fail\n");
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;
2549 ret = s3cfb_direct_ioctl(window_id, FBIOPUT_VSCREENINFO,
2550 (unsigned long)&var);
2552 fimc_err("direct_ioctl(FBIOPUT_VSCREENINFO) fail\n");
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);
2562 fimc_err("direct_ioctl(S3CFB_WIN_POSITION) fail\n");
2566 ret = s3cfb_direct_ioctl(window_id, S3CFB_SET_WIN_ON,
2567 (unsigned long)NULL);
2569 fimc_err("direct_ioctl(S3CFB_SET_WIN_ON) fail\n");
2574 case FIMC_STREAMON_IDLE:
2575 fimc_outdev_set_src_addr(ctrl, ctx->src[idx].base);
2577 memset(&buf_set, 0x00, sizeof(buf_set));
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];
2583 buf_set.base[FIMC_ADDR_Y] = ctx->dst[idx].base[FIMC_ADDR_Y];
2586 cfg = fimc_hwget_output_buf_sequence(ctrl);
2588 for (i = 0; i < FIMC_PHYBUFS; i++) {
2589 if (check_bit(cfg, i))
2590 fimc_hwset_output_address(ctrl, &buf_set, i);
2593 ctrl->out->idxs.active.idx = idx;
2594 ctrl->out->idxs.active.ctx = ctx->ctx_num;
2596 ctrl->status = FIMC_STREAMON;
2597 ctx->status = FIMC_STREAMON;
2599 ret = fimc_outdev_start_camif(ctrl);
2601 fimc_err("Fail: fimc_start_camif\n");
2602 ctrl->status = FIMC_STREAMON_IDLE;
2603 ctx->status = FIMC_STREAMON_IDLE;
2616 static int fimc_qbuf_output_dma_manual(struct fimc_control *ctrl,
2617 struct fimc_ctx *ctx,
2620 struct fimc_buf_set buf_set; /* destination addr */
2621 int ret = -1, i, cfg;
2623 fimc_outdev_set_src_addr(ctrl, ctx->src[idx].base);
2625 memset(&buf_set, 0x00, sizeof(buf_set));
2627 buf_set.vaddr_base[FIMC_ADDR_Y] = ctx->dst[idx].base[FIMC_ADDR_Y];
2629 buf_set.base[FIMC_ADDR_Y] = ctx->dst[idx].base[FIMC_ADDR_Y];
2631 cfg = fimc_hwget_output_buf_sequence(ctrl);
2633 for (i = 0; i < FIMC_PHYBUFS; i++) {
2634 if (check_bit(cfg, i))
2635 fimc_hwset_output_address(ctrl, &buf_set, i);
2638 ctrl->out->idxs.active.idx = idx;
2639 ctrl->out->idxs.active.ctx = ctx->ctx_num;
2641 ctrl->status = FIMC_STREAMON;
2642 ctx->status = FIMC_STREAMON;
2644 ret = fimc_outdev_start_camif(ctrl);
2646 fimc_err("Fail: fimc_start_camif\n");
2653 static int fimc_qbuf_output_fifo(struct fimc_control *ctrl,
2654 struct fimc_ctx *ctx,
2659 #if defined(CONFIG_VIDEO_IPC)
2660 if (ctx->pix.field == V4L2_FIELD_INTERLACED_TB)
2664 fimc_outdev_set_src_addr(ctrl, ctx->src[idx].base);
2666 ctrl->out->idxs.active.idx = idx;
2667 ctrl->out->idxs.active.ctx = ctx->ctx_num;
2669 ctrl->status = FIMC_STREAMON;
2670 ctx->status = FIMC_STREAMON;
2672 ret = fimc_start_fifo(ctrl, ctx);
2674 fimc_err("Fail: fimc_start_fifo\n");
2681 static int fimc_update_in_queue_addr(struct fimc_control *ctrl,
2682 struct fimc_ctx *ctx,
2683 u32 idx, dma_addr_t *addr)
2686 struct vcm_res *vcm_res;
2689 if (idx >= FIMC_OUTBUFS) {
2690 fimc_err("%s: Failed\n", __func__);
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);
2699 ctx->src[idx].base[FIMC_ADDR_Y] = vcm_res->start;
2702 vcm_res = (struct vcm_res *)
2703 ump_dd_vcm_res_get(addr[FIMC_ADDR_CB], ctrl->vcm_id);
2705 ctx->src[idx].base[FIMC_ADDR_CB] = vcm_res->start;
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);
2713 ctx->src[idx].base[FIMC_ADDR_Y] = vcm_res->start;
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;
2720 vcm_res = (struct vcm_res *)
2721 ump_dd_vcm_res_get(addr[FIMC_ADDR_Y], ctrl->vcm_id);
2723 ctx->src[idx].base[FIMC_ADDR_Y] = vcm_res->start;
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];
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];
2739 int fimc_qbuf_output(void *fh, struct v4l2_buffer *b)
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;
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",
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);
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);
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);
2780 #if (defined(CONFIG_S5PV310_DEV_PD) && defined(CONFIG_PM_RUNTIME))
2781 pm_runtime_get_sync(ctrl->dev);
2784 /* Attach the buffer to the incoming queue. */
2785 ret = fimc_push_inq(ctrl, ctx, b->index);
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);
2795 if ((ctrl->status == FIMC_READY_ON) ||
2796 (ctrl->status == FIMC_STREAMON_IDLE)) {
2797 ret = fimc_pop_inq(ctrl, &ctx_num, &idx);
2799 fimc_err("Fail: fimc_pop_inq\n");
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);
2811 switch (ctx->overlay.mode) {
2812 case FIMC_OVLY_FIFO:
2813 ret = fimc_qbuf_output_fifo(ctrl, ctx, idx);
2815 case FIMC_OVLY_DMA_AUTO:
2816 ret = fimc_qbuf_output_dma_auto(ctrl, ctx, idx);
2818 case FIMC_OVLY_DMA_MANUAL:
2819 ret = fimc_qbuf_output_dma_manual(ctrl, ctx, idx);
2821 case FIMC_OVLY_NONE_SINGLE_BUF:
2822 ret = fimc_qbuf_output_single_buf(ctrl, ctx, idx);
2824 case FIMC_OVLY_NONE_MULTI_BUF:
2825 ret = fimc_qbuf_output_multi_buf(ctrl, ctx, idx);
2835 int fimc_dqbuf_output(void *fh, struct v4l2_buffer *b)
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;
2842 ctx = &ctrl->out->ctx[ctx_id];
2843 ret = fimc_pop_outq(ctrl, ctx, &idx);
2845 ret = wait_event_timeout(ctrl->wq, (ctx->outq[0] != -1),
2846 FIMC_DQUEUE_TIMEOUT);
2848 fimc_dump_context(ctrl, ctx);
2849 fimc_err("[0] out_queue is empty\n");
2851 } else if (ret == -ERESTARTSYS) {
2852 fimc_print_signal(ctrl);
2855 ret = fimc_pop_outq(ctrl, ctx, &idx);
2857 fimc_err("[1] out_queue is empty\n");
2858 fimc_dump_context(ctrl, ctx);
2866 fimc_info2("ctx(%d) dqueued idx = %d\n", ctx->ctx_num, b->index);
2871 int fimc_g_fmt_vid_out(struct file *filp, void *fh, struct v4l2_format *f)
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;
2880 fimc_info1("%s: called\n", __func__);
2883 out = kzalloc(sizeof(*out), GFP_KERNEL);
2885 fimc_err("%s: no memory for outdev info\n", __func__);
2890 /* init: struct fimc_outinfo */
2893 spin_lock_init(&ctrl->out->lock_in);
2894 spin_lock_init(&ctrl->out->lock_out);
2896 for (i = 0; i < FIMC_INQUEUES; i++) {
2897 ctrl->out->inq[i].ctx = -1;
2898 ctrl->out->inq[i].idx = -1;
2901 for (i = 0; i < FIMC_MAX_CTXS; i++) {
2902 ctx = &ctrl->out->ctx[i];
2904 ctx->overlay.mode = FIMC_OVLY_NOT_FIXED;
2905 ctx->status = FIMC_STREAMOFF;
2907 for (j = 0; j < FIMC_OUTBUFS; j++) {
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;
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;
2927 f->fmt.pix = ctrl->out->ctx[ctx_id].pix;
2932 int fimc_try_fmt_vid_out(struct file *filp, void *fh, struct v4l2_format *f)
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;
2939 fimc_info1("%s: called. width(%d), height(%d)\n", __func__,
2940 f->fmt.pix.width, f->fmt.pix.height);
2942 ctx = &ctrl->out->ctx[ctx_id];
2943 if (ctx->status != FIMC_STREAMOFF) {
2944 fimc_err("%s: FIMC is running\n", __func__);
2948 /* Check pixel 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 */
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;
2967 /* Fill the return value. */
2969 case V4L2_PIX_FMT_RGB32:
2970 f->fmt.pix.bytesperline = f->fmt.pix.width << 2;
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;
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;
2985 f->fmt.pix.bytesperline = f->fmt.pix.width;
2988 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
2991 ctx->crop.width = f->fmt.pix.width;
2992 ctx->crop.height = f->fmt.pix.height;
2997 int fimc_s_fmt_vid_out(struct file *filp, void *fh, struct v4l2_format *f)
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;
3004 fimc_info1("%s: called\n", __func__);
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__);
3013 ret = fimc_try_fmt_vid_out(filp, fh, f);
3017 ctx->pix = f->fmt.pix;
3022 int fimc_init_in_queue(struct fimc_control *ctrl, struct fimc_ctx *ctx)
3024 struct fimc_idx swap_queue[FIMC_INQUEUES];
3025 int swap_cnt = 0, i;
3026 unsigned long spin_flags;
3028 spin_lock_irqsave(&ctrl->out->lock_in, spin_flags);
3030 /* init incoming queue */
3031 for (i = 0; i < FIMC_OUTBUFS; i++)
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;
3042 ctrl->out->inq[i].ctx = -1;
3043 ctrl->out->inq[i].idx = -1;
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;
3052 spin_unlock_irqrestore(&ctrl->out->lock_in, spin_flags);
3057 int fimc_init_out_queue(struct fimc_control *ctrl, struct fimc_ctx *ctx)
3059 unsigned long spin_flags;
3062 spin_lock_irqsave(&ctrl->out->lock_out, spin_flags);
3064 /* Init incoming queue */
3065 for (i = 0; i < FIMC_OUTBUFS; i++)
3068 spin_unlock_irqrestore(&ctrl->out->lock_out, spin_flags);
3073 int fimc_push_inq(struct fimc_control *ctrl, struct fimc_ctx *ctx, int idx)
3075 struct fimc_idx swap_common_inq[FIMC_INQUEUES];
3076 int swap_queue[FIMC_OUTBUFS];
3078 unsigned long spin_flags;
3080 fimc_dbg("%s: idx = %d\n", __func__, idx);
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);
3088 spin_lock_irqsave(&ctrl->out->lock_in, spin_flags);
3090 /* ctx own incoming queue */
3091 /* Backup original queue */
3092 for (i = 0; i < FIMC_OUTBUFS; i++)
3093 swap_queue[i] = ctx->inq[i];
3095 /* Attach new idx */
3097 ctx->src[idx].state = VIDEOBUF_QUEUED;
3098 ctx->src[idx].flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED;
3100 /* Shift the origonal queue */
3101 for (i = 1; i < FIMC_OUTBUFS; i++)
3102 ctx->inq[i] = swap_queue[i-1];
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;
3111 /* Attach new idx */
3112 ctrl->out->inq[0].ctx = ctx->ctx_num;
3113 ctrl->out->inq[0].idx = idx;
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;
3121 spin_unlock_irqrestore(&ctrl->out->lock_in, spin_flags);
3126 int fimc_pop_inq(struct fimc_control *ctrl, int *ctx_num, int *idx)
3128 struct fimc_ctx *ctx;
3129 unsigned long spin_flags;
3133 spin_lock_irqsave(&ctrl->out->lock_in, spin_flags);
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;
3146 /* common incoming queue is empty. */
3148 spin_unlock_irqrestore(&ctrl->out->lock_in, spin_flags);
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];
3158 ctx->src[ctx_idx].state = VIDEOBUF_ACTIVE;
3159 ctx->src[ctx_idx].flags = V4L2_BUF_FLAG_MAPPED;
3164 if (*idx != ctx_idx)
3165 fimc_err("common inq(%d) vs inq(%d) mismatch\n", *idx, ctx_idx);
3167 /* incoming queue is empty. */
3171 fimc_dbg("%s: index = %d\n", __func__, *idx);
3173 spin_unlock_irqrestore(&ctrl->out->lock_in, spin_flags);
3178 int fimc_push_outq(struct fimc_control *ctrl, struct fimc_ctx *ctx, int idx)
3180 unsigned long spin_flags;
3181 int swap_queue[FIMC_OUTBUFS];
3184 fimc_dbg("%s: index = %d\n", __func__, idx);
3186 spin_lock_irqsave(&ctrl->out->lock_out, spin_flags);
3188 /* Backup original queue */
3189 for (i = 0; i < FIMC_OUTBUFS; i++)
3190 swap_queue[i] = ctx->outq[i];
3192 /* Attach new index */
3194 ctx->src[idx].state = VIDEOBUF_DONE;
3195 ctx->src[idx].flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE;
3197 /* Shift the origonal queue */
3198 for (i = 1; i < FIMC_OUTBUFS; i++)
3199 ctx->outq[i] = swap_queue[i-1];
3201 spin_unlock_irqrestore(&ctrl->out->lock_out, spin_flags);
3206 int fimc_pop_outq(struct fimc_control *ctrl, struct fimc_ctx *ctx, int *idx)
3208 unsigned long spin_flags;
3211 spin_lock_irqsave(&ctrl->out->lock_out, spin_flags);
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];
3218 ctx->src[*idx].state = VIDEOBUF_IDLE;
3219 ctx->src[*idx].flags = V4L2_BUF_FLAG_MAPPED;
3224 /* outgoing queue is empty. */
3227 fimc_dbg("%s: outgoing queue : %d, %d, %d\n", __func__,
3228 ctx->outq[0], ctx->outq[1], ctx->outq[2]);
3230 fimc_dbg("%s: idx = %d\n", __func__, *idx);
3233 spin_unlock_irqrestore(&ctrl->out->lock_out, spin_flags);
3238 void fimc_dump_context(struct fimc_control *ctrl, struct fimc_ctx *ctx)
3242 fimc_err("ctx%d, ctrl->status: %d, ctx->status: %d\n",
3243 ctx->ctx_num, ctrl->status, ctx->status);
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);
3249 for (i = 0; i < FIMC_OUTBUFS; i++)
3250 fimc_err("inq[%d] = %d\n", i, ctx->inq[i]);
3252 for (i = 0; i < FIMC_OUTBUFS; i++)
3253 fimc_err("outq[%d] = %d\n", i, ctx->outq[i]);
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);
3263 void fimc_print_signal(struct fimc_control *ctrl)
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]);
3270 fimc_dbg(":pend=%.8lx shpend=%.8lx\n",
3271 current->pending.signal.sig[0],
3272 current->signal->shared_pending.signal.sig[0]);