1 /* linux/drivers/media/video/samsung/fimc/fimc_overlay.c
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
6 * V4L2 Overlay 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/uaccess.h>
19 #include <plat/media.h>
23 int fimc_try_fmt_overlay(struct file *filp, void *fh, struct v4l2_format *f)
25 struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
26 int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
30 ctx = &ctrl->out->ctx[ctx_id];
32 fimc_info1("%s: top(%d) left(%d) width(%d) height(%d)\n", __func__,
33 f->fmt.win.w.top, f->fmt.win.w.left,
34 f->fmt.win.w.width, f->fmt.win.w.height);
36 if ((ctx->overlay.mode == FIMC_OVLY_NONE_SINGLE_BUF) ||
37 (ctx->overlay.mode == FIMC_OVLY_NONE_MULTI_BUF) ||
38 (ctx->overlay.mode == FIMC_OVLY_DMA_AUTO) ||
39 (ctx->overlay.mode == FIMC_OVLY_DMA_MANUAL))
42 /* Check Overlay Size : Overlay size must be smaller than LCD size. */
43 is_rotate = fimc_mapping_rot_flip(ctx->rotate, ctx->flip);
44 if (is_rotate & FIMC_ROT) { /* Landscape mode */
45 if (f->fmt.win.w.width > ctrl->fb.lcd_vres) {
46 fimc_warn("The width is changed %d -> %d\n",
47 f->fmt.win.w.width, ctrl->fb.lcd_vres);
48 f->fmt.win.w.width = ctrl->fb.lcd_vres;
51 if (f->fmt.win.w.height > ctrl->fb.lcd_hres) {
52 fimc_warn("The height is changed %d -> %d\n",
53 f->fmt.win.w.height, ctrl->fb.lcd_hres);
54 f->fmt.win.w.height = ctrl->fb.lcd_hres;
56 } else { /* Portrait mode */
57 if (f->fmt.win.w.width > ctrl->fb.lcd_hres) {
58 fimc_warn("The width is changed %d -> %d\n",
59 f->fmt.win.w.width, ctrl->fb.lcd_hres);
60 f->fmt.win.w.width = ctrl->fb.lcd_hres;
63 if (f->fmt.win.w.height > ctrl->fb.lcd_vres) {
64 fimc_warn("The height is changed %d -> %d\n",
65 f->fmt.win.w.height, ctrl->fb.lcd_vres);
66 f->fmt.win.w.height = ctrl->fb.lcd_vres;
73 int fimc_g_fmt_vid_overlay(struct file *filp, void *fh, struct v4l2_format *f)
75 struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
76 int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
79 ctx = &ctrl->out->ctx[ctx_id];
81 fimc_info1("%s: called\n", __func__);
83 f->fmt.win = ctx->win;
88 static int fimc_check_pos(struct fimc_control *ctrl,
90 struct v4l2_format *f)
92 if (ctx->win.w.width != f->fmt.win.w.width) {
93 fimc_err("%s: cannot change width(%d,%d)\n", __func__,
94 ctx->win.w.width, f->fmt.win.w.width);
96 } else if (ctx->win.w.height != f->fmt.win.w.height) {
97 fimc_err("%s: cannot change height(%d,%d)\n", __func__,
98 ctx->win.w.height, f->fmt.win.w.height);
105 static int fimc_change_fifo_position(struct fimc_control *ctrl,
106 struct fimc_ctx *ctx) {
107 struct v4l2_rect fimd_rect;
108 struct s3cfb_user_window window;
109 int window_id = ((ctrl->id == 3) ? 2 : ctrl->id);
112 memset(&fimd_rect, 0, sizeof(struct v4l2_rect));
114 ret = fimc_fimd_rect(ctrl, ctx, &fimd_rect);
116 fimc_err("fimc_fimd_rect fail\n");
120 /* Update WIN position */
121 window.x = fimd_rect.left;
122 window.y = fimd_rect.top;
123 ret = s3cfb_direct_ioctl(window_id, S3CFB_WIN_POSITION,
124 (unsigned long)&window);
126 fimc_err("direct_ioctl(S3CFB_WIN_POSITION) fail\n");
133 int fimc_s_fmt_vid_overlay(struct file *filp, void *fh, struct v4l2_format *f)
135 struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
136 int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
137 struct fimc_ctx *ctx;
139 ctx = &ctrl->out->ctx[ctx_id];
141 fimc_info1("%s: called\n", __func__);
143 switch (ctx->status) {
145 ret = fimc_check_pos(ctrl, ctx, f);
147 fimc_err("When FIMC is running, "
148 "you can only move the position.\n");
152 ret = fimc_try_fmt_overlay(filp, fh, f);
156 ctx->win = f->fmt.win;
157 fimc_change_fifo_position(ctrl, ctx);
161 ret = fimc_try_fmt_overlay(filp, fh, f);
164 ctx->win = f->fmt.win;
169 fimc_err("FIMC is running\n");
170 fimc_err("%s::FIMC is running(%d)\n", __func__, ctx->status);
177 int fimc_g_fbuf(struct file *filp, void *fh, struct v4l2_framebuffer *fb)
179 struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
180 int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
181 struct fimc_ctx *ctx;
184 ctx = &ctrl->out->ctx[ctx_id];
186 fimc_info1("%s: called\n", __func__);
188 fb->capability = ctx->fbuf.capability;
190 fb->base = ctx->fbuf.base;
192 fb->fmt.width = ctx->fbuf.fmt.width;
193 fb->fmt.height = ctx->fbuf.fmt.height;
194 fb->fmt.pixelformat = ctx->fbuf.fmt.pixelformat;
195 format = ctx->fbuf.fmt.pixelformat;
198 case V4L2_PIX_FMT_YUV420: /* fall through */
199 case V4L2_PIX_FMT_NV12:
202 case V4L2_PIX_FMT_RGB565:
205 case V4L2_PIX_FMT_RGB32:
210 ctx->fbuf.fmt.bytesperline = fb->fmt.width * bpp;
211 fb->fmt.bytesperline = ctx->fbuf.fmt.bytesperline;
212 fb->fmt.sizeimage = ctx->fbuf.fmt.sizeimage;
213 fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
219 int fimc_s_fbuf(struct file *filp, void *fh, struct v4l2_framebuffer *fb)
221 struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
222 int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
223 struct fimc_ctx *ctx;
225 u32 format = fb->fmt.pixelformat;
226 ctx = &ctrl->out->ctx[ctx_id];
228 fimc_info1("%s: called. width(%d), height(%d)\n",
229 __func__, fb->fmt.width, fb->fmt.height);
231 ctx->fbuf.capability = V4L2_FBUF_CAP_EXTERNOVERLAY;
233 ctx->fbuf.base = fb->base;
235 if (ctx->overlay.mode == FIMC_OVLY_NONE_MULTI_BUF) {
236 ctx->fbuf.fmt.width = fb->fmt.width;
237 ctx->fbuf.fmt.height = fb->fmt.height;
238 ctx->fbuf.fmt.pixelformat = fb->fmt.pixelformat;
241 case V4L2_PIX_FMT_YUV420: /* fall through */
242 case V4L2_PIX_FMT_NV12:
245 case V4L2_PIX_FMT_RGB565:
248 case V4L2_PIX_FMT_RGB32:
253 ctx->fbuf.fmt.bytesperline = fb->fmt.width * bpp;
254 ctx->fbuf.fmt.sizeimage = fb->fmt.sizeimage;
255 ctx->fbuf.fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
256 ctx->fbuf.fmt.priv = 0;
257 } else if (fb->base) {
258 ctx->fbuf.fmt.width = fb->fmt.width;
259 ctx->fbuf.fmt.height = fb->fmt.height;
260 ctx->fbuf.fmt.pixelformat = fb->fmt.pixelformat;
263 case V4L2_PIX_FMT_YUV420: /* fall through */
264 case V4L2_PIX_FMT_NV12:
267 case V4L2_PIX_FMT_RGB565:
270 case V4L2_PIX_FMT_RGB32:
275 ctx->fbuf.fmt.bytesperline = fb->fmt.width * bpp;
276 ctx->fbuf.fmt.sizeimage = fb->fmt.sizeimage;
277 ctx->fbuf.fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
278 ctx->fbuf.fmt.priv = 0;
280 ctx->overlay.mode = FIMC_OVLY_NONE_SINGLE_BUF;
282 ctx->overlay.mode = FIMC_OVLY_NOT_FIXED;