1 /*
2  * S5P camera interface (video postprocessor) driver
3  *
4  * Copyright (c) 2010 Samsung Electronics Co., Ltd
5  *
6  * Sylwester Nawrocki, <s.nawrocki@samsung.com>
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 as published
10  * by the Free Software Foundation, either version 2 of the License,
11  * or (at your option) any later version.
12  */
13 
14 #include <linux/module.h>
15 #include <linux/kernel.h>
16 #include <linux/version.h>
17 #include <linux/types.h>
18 #include <linux/errno.h>
19 #include <linux/bug.h>
20 #include <linux/interrupt.h>
21 #include <linux/device.h>
22 #include <linux/platform_device.h>
23 #include <linux/list.h>
24 #include <linux/io.h>
25 #include <linux/slab.h>
26 #include <linux/clk.h>
27 #include <media/v4l2-ioctl.h>
28 #include <media/videobuf2-core.h>
29 #include <media/videobuf2-dma-contig.h>
30 
31 #include "fimc-core.h"
32 
33 static char *fimc_clocks[MAX_FIMC_CLOCKS] = {
34 	"sclk_fimc", "fimc", "sclk_cam"
35 };
36 
37 static struct fimc_fmt fimc_formats[] = {
38 	{
39 		.name		= "RGB565",
40 		.fourcc		= V4L2_PIX_FMT_RGB565X,
41 		.depth		= { 16 },
42 		.color		= S5P_FIMC_RGB565,
43 		.memplanes	= 1,
44 		.colplanes	= 1,
45 		.mbus_code	= V4L2_MBUS_FMT_RGB565_2X8_BE,
46 		.flags		= FMT_FLAGS_M2M,
47 	}, {
48 		.name		= "BGR666",
49 		.fourcc		= V4L2_PIX_FMT_BGR666,
50 		.depth		= { 32 },
51 		.color		= S5P_FIMC_RGB666,
52 		.memplanes	= 1,
53 		.colplanes	= 1,
54 		.flags		= FMT_FLAGS_M2M,
55 	}, {
56 		.name		= "XRGB-8-8-8-8, 32 bpp",
57 		.fourcc		= V4L2_PIX_FMT_RGB32,
58 		.depth		= { 32 },
59 		.color		= S5P_FIMC_RGB888,
60 		.memplanes	= 1,
61 		.colplanes	= 1,
62 		.flags		= FMT_FLAGS_M2M,
63 	}, {
64 		.name		= "YUV 4:2:2 packed, YCbYCr",
65 		.fourcc		= V4L2_PIX_FMT_YUYV,
66 		.depth		= { 16 },
67 		.color		= S5P_FIMC_YCBYCR422,
68 		.memplanes	= 1,
69 		.colplanes	= 1,
70 		.mbus_code	= V4L2_MBUS_FMT_YUYV8_2X8,
71 		.flags		= FMT_FLAGS_M2M | FMT_FLAGS_CAM,
72 	}, {
73 		.name		= "YUV 4:2:2 packed, CbYCrY",
74 		.fourcc		= V4L2_PIX_FMT_UYVY,
75 		.depth		= { 16 },
76 		.color		= S5P_FIMC_CBYCRY422,
77 		.memplanes	= 1,
78 		.colplanes	= 1,
79 		.mbus_code	= V4L2_MBUS_FMT_UYVY8_2X8,
80 		.flags		= FMT_FLAGS_M2M | FMT_FLAGS_CAM,
81 	}, {
82 		.name		= "YUV 4:2:2 packed, CrYCbY",
83 		.fourcc		= V4L2_PIX_FMT_VYUY,
84 		.depth		= { 16 },
85 		.color		= S5P_FIMC_CRYCBY422,
86 		.memplanes	= 1,
87 		.colplanes	= 1,
88 		.mbus_code	= V4L2_MBUS_FMT_VYUY8_2X8,
89 		.flags		= FMT_FLAGS_M2M | FMT_FLAGS_CAM,
90 	}, {
91 		.name		= "YUV 4:2:2 packed, YCrYCb",
92 		.fourcc		= V4L2_PIX_FMT_YVYU,
93 		.depth		= { 16 },
94 		.color		= S5P_FIMC_YCRYCB422,
95 		.memplanes	= 1,
96 		.colplanes	= 1,
97 		.mbus_code	= V4L2_MBUS_FMT_YVYU8_2X8,
98 		.flags		= FMT_FLAGS_M2M | FMT_FLAGS_CAM,
99 	}, {
100 		.name		= "YUV 4:2:2 planar, Y/Cb/Cr",
101 		.fourcc		= V4L2_PIX_FMT_YUV422P,
102 		.depth		= { 12 },
103 		.color		= S5P_FIMC_YCBYCR422,
104 		.memplanes	= 1,
105 		.colplanes	= 3,
106 		.flags		= FMT_FLAGS_M2M,
107 	}, {
108 		.name		= "YUV 4:2:2 planar, Y/CbCr",
109 		.fourcc		= V4L2_PIX_FMT_NV16,
110 		.depth		= { 16 },
111 		.color		= S5P_FIMC_YCBYCR422,
112 		.memplanes	= 1,
113 		.colplanes	= 2,
114 		.flags		= FMT_FLAGS_M2M,
115 	}, {
116 		.name		= "YUV 4:2:2 planar, Y/CrCb",
117 		.fourcc		= V4L2_PIX_FMT_NV61,
118 		.depth		= { 16 },
119 		.color		= S5P_FIMC_YCRYCB422,
120 		.memplanes	= 1,
121 		.colplanes	= 2,
122 		.flags		= FMT_FLAGS_M2M,
123 	}, {
124 		.name		= "YUV 4:2:0 planar, YCbCr",
125 		.fourcc		= V4L2_PIX_FMT_YUV420,
126 		.depth		= { 12 },
127 		.color		= S5P_FIMC_YCBCR420,
128 		.memplanes	= 1,
129 		.colplanes	= 3,
130 		.flags		= FMT_FLAGS_M2M,
131 	}, {
132 		.name		= "YUV 4:2:0 planar, Y/CbCr",
133 		.fourcc		= V4L2_PIX_FMT_NV12,
134 		.depth		= { 12 },
135 		.color		= S5P_FIMC_YCBCR420,
136 		.memplanes	= 1,
137 		.colplanes	= 2,
138 		.flags		= FMT_FLAGS_M2M,
139 	}, {
140 		.name		= "YUV 4:2:0 non-contiguous 2-planar, Y/CbCr",
141 		.fourcc		= V4L2_PIX_FMT_NV12M,
142 		.color		= S5P_FIMC_YCBCR420,
143 		.depth		= { 8, 4 },
144 		.memplanes	= 2,
145 		.colplanes	= 2,
146 		.flags		= FMT_FLAGS_M2M,
147 	}, {
148 		.name		= "YUV 4:2:0 non-contiguous 3-planar, Y/Cb/Cr",
149 		.fourcc		= V4L2_PIX_FMT_YUV420M,
150 		.color		= S5P_FIMC_YCBCR420,
151 		.depth		= { 8, 2, 2 },
152 		.memplanes	= 3,
153 		.colplanes	= 3,
154 		.flags		= FMT_FLAGS_M2M,
155 	}, {
156 		.name		= "YUV 4:2:0 non-contiguous 2-planar, Y/CbCr, tiled",
157 		.fourcc		= V4L2_PIX_FMT_NV12MT,
158 		.color		= S5P_FIMC_YCBCR420,
159 		.depth		= { 8, 4 },
160 		.memplanes	= 2,
161 		.colplanes	= 2,
162 		.flags		= FMT_FLAGS_M2M,
163 	},
164 };
165 
166 static struct v4l2_queryctrl fimc_ctrls[] = {
167 	{
168 		.id		= V4L2_CID_HFLIP,
169 		.type		= V4L2_CTRL_TYPE_BOOLEAN,
170 		.name		= "Horizontal flip",
171 		.minimum	= 0,
172 		.maximum	= 1,
173 		.default_value	= 0,
174 	}, {
175 		.id		= V4L2_CID_VFLIP,
176 		.type		= V4L2_CTRL_TYPE_BOOLEAN,
177 		.name		= "Vertical flip",
178 		.minimum	= 0,
179 		.maximum	= 1,
180 		.default_value	= 0,
181 	}, {
182 		.id		= V4L2_CID_ROTATE,
183 		.type		= V4L2_CTRL_TYPE_INTEGER,
184 		.name		= "Rotation (CCW)",
185 		.minimum	= 0,
186 		.maximum	= 270,
187 		.step		= 90,
188 		.default_value	= 0,
189 	},
190 };
191 
192 
get_ctrl(int id)193 static struct v4l2_queryctrl *get_ctrl(int id)
194 {
195 	int i;
196 
197 	for (i = 0; i < ARRAY_SIZE(fimc_ctrls); ++i)
198 		if (id == fimc_ctrls[i].id)
199 			return &fimc_ctrls[i];
200 	return NULL;
201 }
202 
fimc_check_scaler_ratio(int sw,int sh,int dw,int dh,int rot)203 int fimc_check_scaler_ratio(int sw, int sh, int dw, int dh, int rot)
204 {
205 	int tx, ty;
206 
207 	if (rot == 90 || rot == 270) {
208 		ty = dw;
209 		tx = dh;
210 	} else {
211 		tx = dw;
212 		ty = dh;
213 	}
214 
215 	if ((sw >= SCALER_MAX_HRATIO * tx) || (sh >= SCALER_MAX_VRATIO * ty))
216 		return -EINVAL;
217 
218 	return 0;
219 }
220 
fimc_get_scaler_factor(u32 src,u32 tar,u32 * ratio,u32 * shift)221 static int fimc_get_scaler_factor(u32 src, u32 tar, u32 *ratio, u32 *shift)
222 {
223 	u32 sh = 6;
224 
225 	if (src >= 64 * tar)
226 		return -EINVAL;
227 
228 	while (sh--) {
229 		u32 tmp = 1 << sh;
230 		if (src >= tar * tmp) {
231 			*shift = sh, *ratio = tmp;
232 			return 0;
233 		}
234 	}
235 
236 	*shift = 0, *ratio = 1;
237 
238 	dbg("s: %d, t: %d, shift: %d, ratio: %d",
239 	    src, tar, *shift, *ratio);
240 	return 0;
241 }
242 
fimc_set_scaler_info(struct fimc_ctx * ctx)243 int fimc_set_scaler_info(struct fimc_ctx *ctx)
244 {
245 	struct fimc_scaler *sc = &ctx->scaler;
246 	struct fimc_frame *s_frame = &ctx->s_frame;
247 	struct fimc_frame *d_frame = &ctx->d_frame;
248 	struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
249 	int tx, ty, sx, sy;
250 	int ret;
251 
252 	if (ctx->rotation == 90 || ctx->rotation == 270) {
253 		ty = d_frame->width;
254 		tx = d_frame->height;
255 	} else {
256 		tx = d_frame->width;
257 		ty = d_frame->height;
258 	}
259 	if (tx <= 0 || ty <= 0) {
260 		v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev,
261 			"invalid target size: %d x %d", tx, ty);
262 		return -EINVAL;
263 	}
264 
265 	sx = s_frame->width;
266 	sy = s_frame->height;
267 	if (sx <= 0 || sy <= 0) {
268 		err("invalid source size: %d x %d", sx, sy);
269 		return -EINVAL;
270 	}
271 
272 	sc->real_width = sx;
273 	sc->real_height = sy;
274 	dbg("sx= %d, sy= %d, tx= %d, ty= %d", sx, sy, tx, ty);
275 
276 	ret = fimc_get_scaler_factor(sx, tx, &sc->pre_hratio, &sc->hfactor);
277 	if (ret)
278 		return ret;
279 
280 	ret = fimc_get_scaler_factor(sy, ty,  &sc->pre_vratio, &sc->vfactor);
281 	if (ret)
282 		return ret;
283 
284 	sc->pre_dst_width = sx / sc->pre_hratio;
285 	sc->pre_dst_height = sy / sc->pre_vratio;
286 
287 	if (variant->has_mainscaler_ext) {
288 		sc->main_hratio = (sx << 14) / (tx << sc->hfactor);
289 		sc->main_vratio = (sy << 14) / (ty << sc->vfactor);
290 	} else {
291 		sc->main_hratio = (sx << 8) / (tx << sc->hfactor);
292 		sc->main_vratio = (sy << 8) / (ty << sc->vfactor);
293 
294 	}
295 
296 	sc->scaleup_h = (tx >= sx) ? 1 : 0;
297 	sc->scaleup_v = (ty >= sy) ? 1 : 0;
298 
299 	/* check to see if input and output size/format differ */
300 	if (s_frame->fmt->color == d_frame->fmt->color
301 		&& s_frame->width == d_frame->width
302 		&& s_frame->height == d_frame->height)
303 		sc->copy_mode = 1;
304 	else
305 		sc->copy_mode = 0;
306 
307 	return 0;
308 }
309 
fimc_m2m_job_finish(struct fimc_ctx * ctx,int vb_state)310 static void fimc_m2m_job_finish(struct fimc_ctx *ctx, int vb_state)
311 {
312 	struct vb2_buffer *src_vb, *dst_vb;
313 	struct fimc_dev *fimc = ctx->fimc_dev;
314 
315 	if (!ctx || !ctx->m2m_ctx)
316 		return;
317 
318 	src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
319 	dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
320 
321 	if (src_vb && dst_vb) {
322 		v4l2_m2m_buf_done(src_vb, vb_state);
323 		v4l2_m2m_buf_done(dst_vb, vb_state);
324 		v4l2_m2m_job_finish(fimc->m2m.m2m_dev, ctx->m2m_ctx);
325 	}
326 }
327 
328 /* Complete the transaction which has been scheduled for execution. */
fimc_m2m_shutdown(struct fimc_ctx * ctx)329 static void fimc_m2m_shutdown(struct fimc_ctx *ctx)
330 {
331 	struct fimc_dev *fimc = ctx->fimc_dev;
332 	int ret;
333 
334 	if (!fimc_m2m_pending(fimc))
335 		return;
336 
337 	fimc_ctx_state_lock_set(FIMC_CTX_SHUT, ctx);
338 
339 	ret = wait_event_timeout(fimc->irq_queue,
340 			   !fimc_ctx_state_is_set(FIMC_CTX_SHUT, ctx),
341 			   FIMC_SHUTDOWN_TIMEOUT);
342 	/*
343 	 * In case of a timeout the buffers are not released in the interrupt
344 	 * handler so return them here with the error flag set, if there are
345 	 * any on the queue.
346 	 */
347 	if (ret == 0)
348 		fimc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
349 }
350 
stop_streaming(struct vb2_queue * q)351 static int stop_streaming(struct vb2_queue *q)
352 {
353 	struct fimc_ctx *ctx = q->drv_priv;
354 
355 	fimc_m2m_shutdown(ctx);
356 
357 	return 0;
358 }
359 
fimc_capture_irq_handler(struct fimc_dev * fimc)360 static void fimc_capture_irq_handler(struct fimc_dev *fimc)
361 {
362 	struct fimc_vid_cap *cap = &fimc->vid_cap;
363 	struct fimc_vid_buffer *v_buf;
364 	struct timeval *tv;
365 	struct timespec ts;
366 
367 	if (!list_empty(&cap->active_buf_q) &&
368 	    test_bit(ST_CAPT_RUN, &fimc->state)) {
369 		ktime_get_real_ts(&ts);
370 
371 		v_buf = active_queue_pop(cap);
372 
373 		tv = &v_buf->vb.v4l2_buf.timestamp;
374 		tv->tv_sec = ts.tv_sec;
375 		tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
376 		v_buf->vb.v4l2_buf.sequence = cap->frame_count++;
377 
378 		vb2_buffer_done(&v_buf->vb, VB2_BUF_STATE_DONE);
379 	}
380 
381 	if (test_and_clear_bit(ST_CAPT_SHUT, &fimc->state)) {
382 		wake_up(&fimc->irq_queue);
383 		return;
384 	}
385 
386 	if (!list_empty(&cap->pending_buf_q)) {
387 
388 		v_buf = pending_queue_pop(cap);
389 		fimc_hw_set_output_addr(fimc, &v_buf->paddr, cap->buf_index);
390 		v_buf->index = cap->buf_index;
391 
392 		/* Move the buffer to the capture active queue */
393 		active_queue_add(cap, v_buf);
394 
395 		dbg("next frame: %d, done frame: %d",
396 		    fimc_hw_get_frame_index(fimc), v_buf->index);
397 
398 		if (++cap->buf_index >= FIMC_MAX_OUT_BUFS)
399 			cap->buf_index = 0;
400 	}
401 
402 	if (cap->active_buf_cnt == 0) {
403 		clear_bit(ST_CAPT_RUN, &fimc->state);
404 
405 		if (++cap->buf_index >= FIMC_MAX_OUT_BUFS)
406 			cap->buf_index = 0;
407 	} else {
408 		set_bit(ST_CAPT_RUN, &fimc->state);
409 	}
410 
411 	dbg("frame: %d, active_buf_cnt: %d",
412 	    fimc_hw_get_frame_index(fimc), cap->active_buf_cnt);
413 }
414 
fimc_isr(int irq,void * priv)415 static irqreturn_t fimc_isr(int irq, void *priv)
416 {
417 	struct fimc_dev *fimc = priv;
418 	struct fimc_vid_cap *cap = &fimc->vid_cap;
419 	struct fimc_ctx *ctx;
420 
421 	fimc_hw_clear_irq(fimc);
422 
423 	if (test_and_clear_bit(ST_M2M_PEND, &fimc->state)) {
424 		ctx = v4l2_m2m_get_curr_priv(fimc->m2m.m2m_dev);
425 		if (ctx != NULL) {
426 			fimc_m2m_job_finish(ctx, VB2_BUF_STATE_DONE);
427 
428 			spin_lock(&ctx->slock);
429 			if (ctx->state & FIMC_CTX_SHUT) {
430 				ctx->state &= ~FIMC_CTX_SHUT;
431 				wake_up(&fimc->irq_queue);
432 			}
433 			spin_unlock(&ctx->slock);
434 		}
435 
436 		return IRQ_HANDLED;
437 	}
438 
439 	spin_lock(&fimc->slock);
440 
441 	if (test_bit(ST_CAPT_PEND, &fimc->state)) {
442 		fimc_capture_irq_handler(fimc);
443 
444 		if (cap->active_buf_cnt == 1) {
445 			fimc_deactivate_capture(fimc);
446 			clear_bit(ST_CAPT_STREAM, &fimc->state);
447 		}
448 	}
449 
450 	spin_unlock(&fimc->slock);
451 	return IRQ_HANDLED;
452 }
453 
454 /* The color format (colplanes, memplanes) must be already configured. */
fimc_prepare_addr(struct fimc_ctx * ctx,struct vb2_buffer * vb,struct fimc_frame * frame,struct fimc_addr * paddr)455 int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb,
456 		      struct fimc_frame *frame, struct fimc_addr *paddr)
457 {
458 	int ret = 0;
459 	u32 pix_size;
460 
461 	if (vb == NULL || frame == NULL)
462 		return -EINVAL;
463 
464 	pix_size = frame->width * frame->height;
465 
466 	dbg("memplanes= %d, colplanes= %d, pix_size= %d",
467 		frame->fmt->memplanes, frame->fmt->colplanes, pix_size);
468 
469 	paddr->y = vb2_dma_contig_plane_paddr(vb, 0);
470 
471 	if (frame->fmt->memplanes == 1) {
472 		switch (frame->fmt->colplanes) {
473 		case 1:
474 			paddr->cb = 0;
475 			paddr->cr = 0;
476 			break;
477 		case 2:
478 			/* decompose Y into Y/Cb */
479 			paddr->cb = (u32)(paddr->y + pix_size);
480 			paddr->cr = 0;
481 			break;
482 		case 3:
483 			paddr->cb = (u32)(paddr->y + pix_size);
484 			/* decompose Y into Y/Cb/Cr */
485 			if (S5P_FIMC_YCBCR420 == frame->fmt->color)
486 				paddr->cr = (u32)(paddr->cb
487 						+ (pix_size >> 2));
488 			else /* 422 */
489 				paddr->cr = (u32)(paddr->cb
490 						+ (pix_size >> 1));
491 			break;
492 		default:
493 			return -EINVAL;
494 		}
495 	} else {
496 		if (frame->fmt->memplanes >= 2)
497 			paddr->cb = vb2_dma_contig_plane_paddr(vb, 1);
498 
499 		if (frame->fmt->memplanes == 3)
500 			paddr->cr = vb2_dma_contig_plane_paddr(vb, 2);
501 	}
502 
503 	dbg("PHYS_ADDR: y= 0x%X  cb= 0x%X cr= 0x%X ret= %d",
504 	    paddr->y, paddr->cb, paddr->cr, ret);
505 
506 	return ret;
507 }
508 
509 /* Set order for 1 and 2 plane YCBCR 4:2:2 formats. */
fimc_set_yuv_order(struct fimc_ctx * ctx)510 static void fimc_set_yuv_order(struct fimc_ctx *ctx)
511 {
512 	/* The one only mode supported in SoC. */
513 	ctx->in_order_2p = S5P_FIMC_LSB_CRCB;
514 	ctx->out_order_2p = S5P_FIMC_LSB_CRCB;
515 
516 	/* Set order for 1 plane input formats. */
517 	switch (ctx->s_frame.fmt->color) {
518 	case S5P_FIMC_YCRYCB422:
519 		ctx->in_order_1p = S5P_MSCTRL_ORDER422_CBYCRY;
520 		break;
521 	case S5P_FIMC_CBYCRY422:
522 		ctx->in_order_1p = S5P_MSCTRL_ORDER422_YCRYCB;
523 		break;
524 	case S5P_FIMC_CRYCBY422:
525 		ctx->in_order_1p = S5P_MSCTRL_ORDER422_YCBYCR;
526 		break;
527 	case S5P_FIMC_YCBYCR422:
528 	default:
529 		ctx->in_order_1p = S5P_MSCTRL_ORDER422_CRYCBY;
530 		break;
531 	}
532 	dbg("ctx->in_order_1p= %d", ctx->in_order_1p);
533 
534 	switch (ctx->d_frame.fmt->color) {
535 	case S5P_FIMC_YCRYCB422:
536 		ctx->out_order_1p = S5P_CIOCTRL_ORDER422_CBYCRY;
537 		break;
538 	case S5P_FIMC_CBYCRY422:
539 		ctx->out_order_1p = S5P_CIOCTRL_ORDER422_YCRYCB;
540 		break;
541 	case S5P_FIMC_CRYCBY422:
542 		ctx->out_order_1p = S5P_CIOCTRL_ORDER422_YCBYCR;
543 		break;
544 	case S5P_FIMC_YCBYCR422:
545 	default:
546 		ctx->out_order_1p = S5P_CIOCTRL_ORDER422_CRYCBY;
547 		break;
548 	}
549 	dbg("ctx->out_order_1p= %d", ctx->out_order_1p);
550 }
551 
fimc_prepare_dma_offset(struct fimc_ctx * ctx,struct fimc_frame * f)552 static void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f)
553 {
554 	struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
555 	u32 i, depth = 0;
556 
557 	for (i = 0; i < f->fmt->colplanes; i++)
558 		depth += f->fmt->depth[i];
559 
560 	f->dma_offset.y_h = f->offs_h;
561 	if (!variant->pix_hoff)
562 		f->dma_offset.y_h *= (depth >> 3);
563 
564 	f->dma_offset.y_v = f->offs_v;
565 
566 	f->dma_offset.cb_h = f->offs_h;
567 	f->dma_offset.cb_v = f->offs_v;
568 
569 	f->dma_offset.cr_h = f->offs_h;
570 	f->dma_offset.cr_v = f->offs_v;
571 
572 	if (!variant->pix_hoff) {
573 		if (f->fmt->colplanes == 3) {
574 			f->dma_offset.cb_h >>= 1;
575 			f->dma_offset.cr_h >>= 1;
576 		}
577 		if (f->fmt->color == S5P_FIMC_YCBCR420) {
578 			f->dma_offset.cb_v >>= 1;
579 			f->dma_offset.cr_v >>= 1;
580 		}
581 	}
582 
583 	dbg("in_offset: color= %d, y_h= %d, y_v= %d",
584 	    f->fmt->color, f->dma_offset.y_h, f->dma_offset.y_v);
585 }
586 
587 /**
588  * fimc_prepare_config - check dimensions, operation and color mode
589  *			 and pre-calculate offset and the scaling coefficients.
590  *
591  * @ctx: hardware context information
592  * @flags: flags indicating which parameters to check/update
593  *
594  * Return: 0 if dimensions are valid or non zero otherwise.
595  */
fimc_prepare_config(struct fimc_ctx * ctx,u32 flags)596 int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags)
597 {
598 	struct fimc_frame *s_frame, *d_frame;
599 	struct vb2_buffer *vb = NULL;
600 	int ret = 0;
601 
602 	s_frame = &ctx->s_frame;
603 	d_frame = &ctx->d_frame;
604 
605 	if (flags & FIMC_PARAMS) {
606 		/* Prepare the DMA offset ratios for scaler. */
607 		fimc_prepare_dma_offset(ctx, &ctx->s_frame);
608 		fimc_prepare_dma_offset(ctx, &ctx->d_frame);
609 
610 		if (s_frame->height > (SCALER_MAX_VRATIO * d_frame->height) ||
611 		    s_frame->width > (SCALER_MAX_HRATIO * d_frame->width)) {
612 			err("out of scaler range");
613 			return -EINVAL;
614 		}
615 		fimc_set_yuv_order(ctx);
616 	}
617 
618 	/* Input DMA mode is not allowed when the scaler is disabled. */
619 	ctx->scaler.enabled = 1;
620 
621 	if (flags & FIMC_SRC_ADDR) {
622 		vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
623 		ret = fimc_prepare_addr(ctx, vb, s_frame, &s_frame->paddr);
624 		if (ret)
625 			return ret;
626 	}
627 
628 	if (flags & FIMC_DST_ADDR) {
629 		vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
630 		ret = fimc_prepare_addr(ctx, vb, d_frame, &d_frame->paddr);
631 	}
632 
633 	return ret;
634 }
635 
fimc_dma_run(void * priv)636 static void fimc_dma_run(void *priv)
637 {
638 	struct fimc_ctx *ctx = priv;
639 	struct fimc_dev *fimc;
640 	unsigned long flags;
641 	u32 ret;
642 
643 	if (WARN(!ctx, "null hardware context\n"))
644 		return;
645 
646 	fimc = ctx->fimc_dev;
647 
648 	spin_lock_irqsave(&ctx->slock, flags);
649 	set_bit(ST_M2M_PEND, &fimc->state);
650 
651 	ctx->state |= (FIMC_SRC_ADDR | FIMC_DST_ADDR);
652 	ret = fimc_prepare_config(ctx, ctx->state);
653 	if (ret)
654 		goto dma_unlock;
655 
656 	/* Reconfigure hardware if the context has changed. */
657 	if (fimc->m2m.ctx != ctx) {
658 		ctx->state |= FIMC_PARAMS;
659 		fimc->m2m.ctx = ctx;
660 	}
661 
662 	spin_lock(&fimc->slock);
663 	fimc_hw_set_input_addr(fimc, &ctx->s_frame.paddr);
664 
665 	if (ctx->state & FIMC_PARAMS) {
666 		fimc_hw_set_input_path(ctx);
667 		fimc_hw_set_in_dma(ctx);
668 		ret = fimc_set_scaler_info(ctx);
669 		if (ret) {
670 			spin_unlock(&fimc->slock);
671 			goto dma_unlock;
672 		}
673 		fimc_hw_set_prescaler(ctx);
674 		fimc_hw_set_mainscaler(ctx);
675 		fimc_hw_set_target_format(ctx);
676 		fimc_hw_set_rotation(ctx);
677 		fimc_hw_set_effect(ctx);
678 	}
679 
680 	fimc_hw_set_output_path(ctx);
681 	if (ctx->state & (FIMC_DST_ADDR | FIMC_PARAMS))
682 		fimc_hw_set_output_addr(fimc, &ctx->d_frame.paddr, -1);
683 
684 	if (ctx->state & FIMC_PARAMS)
685 		fimc_hw_set_out_dma(ctx);
686 
687 	fimc_activate_capture(ctx);
688 
689 	ctx->state &= (FIMC_CTX_M2M | FIMC_CTX_CAP |
690 		       FIMC_SRC_FMT | FIMC_DST_FMT);
691 	fimc_hw_activate_input_dma(fimc, true);
692 	spin_unlock(&fimc->slock);
693 
694 dma_unlock:
695 	spin_unlock_irqrestore(&ctx->slock, flags);
696 }
697 
fimc_job_abort(void * priv)698 static void fimc_job_abort(void *priv)
699 {
700 	fimc_m2m_shutdown(priv);
701 }
702 
fimc_queue_setup(struct vb2_queue * vq,unsigned int * num_buffers,unsigned int * num_planes,unsigned long sizes[],void * allocators[])703 static int fimc_queue_setup(struct vb2_queue *vq, unsigned int *num_buffers,
704 			    unsigned int *num_planes, unsigned long sizes[],
705 			    void *allocators[])
706 {
707 	struct fimc_ctx *ctx = vb2_get_drv_priv(vq);
708 	struct fimc_frame *f;
709 	int i;
710 
711 	f = ctx_get_frame(ctx, vq->type);
712 	if (IS_ERR(f))
713 		return PTR_ERR(f);
714 
715 	/*
716 	 * Return number of non-contigous planes (plane buffers)
717 	 * depending on the configured color format.
718 	 */
719 	if (f->fmt)
720 		*num_planes = f->fmt->memplanes;
721 
722 	for (i = 0; i < f->fmt->memplanes; i++) {
723 		sizes[i] = (f->width * f->height * f->fmt->depth[i]) >> 3;
724 		allocators[i] = ctx->fimc_dev->alloc_ctx;
725 	}
726 
727 	if (*num_buffers == 0)
728 		*num_buffers = 1;
729 
730 	return 0;
731 }
732 
fimc_buf_prepare(struct vb2_buffer * vb)733 static int fimc_buf_prepare(struct vb2_buffer *vb)
734 {
735 	struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
736 	struct fimc_frame *frame;
737 	int i;
738 
739 	frame = ctx_get_frame(ctx, vb->vb2_queue->type);
740 	if (IS_ERR(frame))
741 		return PTR_ERR(frame);
742 
743 	for (i = 0; i < frame->fmt->memplanes; i++)
744 		vb2_set_plane_payload(vb, i, frame->payload[i]);
745 
746 	return 0;
747 }
748 
fimc_buf_queue(struct vb2_buffer * vb)749 static void fimc_buf_queue(struct vb2_buffer *vb)
750 {
751 	struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
752 
753 	dbg("ctx: %p, ctx->state: 0x%x", ctx, ctx->state);
754 
755 	if (ctx->m2m_ctx)
756 		v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
757 }
758 
fimc_lock(struct vb2_queue * vq)759 static void fimc_lock(struct vb2_queue *vq)
760 {
761 	struct fimc_ctx *ctx = vb2_get_drv_priv(vq);
762 	mutex_lock(&ctx->fimc_dev->lock);
763 }
764 
fimc_unlock(struct vb2_queue * vq)765 static void fimc_unlock(struct vb2_queue *vq)
766 {
767 	struct fimc_ctx *ctx = vb2_get_drv_priv(vq);
768 	mutex_unlock(&ctx->fimc_dev->lock);
769 }
770 
771 static struct vb2_ops fimc_qops = {
772 	.queue_setup	 = fimc_queue_setup,
773 	.buf_prepare	 = fimc_buf_prepare,
774 	.buf_queue	 = fimc_buf_queue,
775 	.wait_prepare	 = fimc_unlock,
776 	.wait_finish	 = fimc_lock,
777 	.stop_streaming	 = stop_streaming,
778 };
779 
fimc_m2m_querycap(struct file * file,void * priv,struct v4l2_capability * cap)780 static int fimc_m2m_querycap(struct file *file, void *priv,
781 			   struct v4l2_capability *cap)
782 {
783 	struct fimc_ctx *ctx = file->private_data;
784 	struct fimc_dev *fimc = ctx->fimc_dev;
785 
786 	strncpy(cap->driver, fimc->pdev->name, sizeof(cap->driver) - 1);
787 	strncpy(cap->card, fimc->pdev->name, sizeof(cap->card) - 1);
788 	cap->bus_info[0] = 0;
789 	cap->version = KERNEL_VERSION(1, 0, 0);
790 	cap->capabilities = V4L2_CAP_STREAMING |
791 		V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
792 		V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE;
793 
794 	return 0;
795 }
796 
fimc_vidioc_enum_fmt_mplane(struct file * file,void * priv,struct v4l2_fmtdesc * f)797 int fimc_vidioc_enum_fmt_mplane(struct file *file, void *priv,
798 				struct v4l2_fmtdesc *f)
799 {
800 	struct fimc_fmt *fmt;
801 
802 	if (f->index >= ARRAY_SIZE(fimc_formats))
803 		return -EINVAL;
804 
805 	fmt = &fimc_formats[f->index];
806 	strncpy(f->description, fmt->name, sizeof(f->description) - 1);
807 	f->pixelformat = fmt->fourcc;
808 
809 	return 0;
810 }
811 
fimc_vidioc_g_fmt_mplane(struct file * file,void * priv,struct v4l2_format * f)812 int fimc_vidioc_g_fmt_mplane(struct file *file, void *priv,
813 			     struct v4l2_format *f)
814 {
815 	struct fimc_ctx *ctx = priv;
816 	struct fimc_frame *frame;
817 	struct v4l2_pix_format_mplane *pixm;
818 	int i;
819 
820 	frame = ctx_get_frame(ctx, f->type);
821 	if (IS_ERR(frame))
822 		return PTR_ERR(frame);
823 
824 	pixm = &f->fmt.pix_mp;
825 
826 	pixm->width		= frame->width;
827 	pixm->height		= frame->height;
828 	pixm->field		= V4L2_FIELD_NONE;
829 	pixm->pixelformat	= frame->fmt->fourcc;
830 	pixm->colorspace	= V4L2_COLORSPACE_JPEG;
831 	pixm->num_planes	= frame->fmt->memplanes;
832 
833 	for (i = 0; i < pixm->num_planes; ++i) {
834 		int bpl = frame->o_width;
835 
836 		if (frame->fmt->colplanes == 1) /* packed formats */
837 			bpl = (bpl * frame->fmt->depth[0]) / 8;
838 
839 		pixm->plane_fmt[i].bytesperline = bpl;
840 
841 		pixm->plane_fmt[i].sizeimage = (frame->o_width *
842 			frame->o_height * frame->fmt->depth[i]) / 8;
843 	}
844 
845 	return 0;
846 }
847 
find_format(struct v4l2_format * f,unsigned int mask)848 struct fimc_fmt *find_format(struct v4l2_format *f, unsigned int mask)
849 {
850 	struct fimc_fmt *fmt;
851 	unsigned int i;
852 
853 	for (i = 0; i < ARRAY_SIZE(fimc_formats); ++i) {
854 		fmt = &fimc_formats[i];
855 		if (fmt->fourcc == f->fmt.pix.pixelformat &&
856 		   (fmt->flags & mask))
857 			break;
858 	}
859 
860 	return (i == ARRAY_SIZE(fimc_formats)) ? NULL : fmt;
861 }
862 
find_mbus_format(struct v4l2_mbus_framefmt * f,unsigned int mask)863 struct fimc_fmt *find_mbus_format(struct v4l2_mbus_framefmt *f,
864 				  unsigned int mask)
865 {
866 	struct fimc_fmt *fmt;
867 	unsigned int i;
868 
869 	for (i = 0; i < ARRAY_SIZE(fimc_formats); ++i) {
870 		fmt = &fimc_formats[i];
871 		if (fmt->mbus_code == f->code && (fmt->flags & mask))
872 			break;
873 	}
874 
875 	return (i == ARRAY_SIZE(fimc_formats)) ? NULL : fmt;
876 }
877 
878 
fimc_vidioc_try_fmt_mplane(struct file * file,void * priv,struct v4l2_format * f)879 int fimc_vidioc_try_fmt_mplane(struct file *file, void *priv,
880 			       struct v4l2_format *f)
881 {
882 	struct fimc_ctx *ctx = priv;
883 	struct fimc_dev *fimc = ctx->fimc_dev;
884 	struct samsung_fimc_variant *variant = fimc->variant;
885 	struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
886 	struct fimc_fmt *fmt;
887 	u32 max_width, mod_x, mod_y, mask;
888 	int i, is_output = 0;
889 
890 
891 	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
892 		if (fimc_ctx_state_is_set(FIMC_CTX_CAP, ctx))
893 			return -EINVAL;
894 		is_output = 1;
895 	} else if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
896 		return -EINVAL;
897 	}
898 
899 	dbg("w: %d, h: %d", pix->width, pix->height);
900 
901 	mask = is_output ? FMT_FLAGS_M2M : FMT_FLAGS_M2M | FMT_FLAGS_CAM;
902 	fmt = find_format(f, mask);
903 	if (!fmt) {
904 		v4l2_err(&fimc->m2m.v4l2_dev, "Fourcc format (0x%X) invalid.\n",
905 			 pix->pixelformat);
906 		return -EINVAL;
907 	}
908 
909 	if (pix->field == V4L2_FIELD_ANY)
910 		pix->field = V4L2_FIELD_NONE;
911 	else if (V4L2_FIELD_NONE != pix->field)
912 		return -EINVAL;
913 
914 	if (is_output) {
915 		max_width = variant->pix_limit->scaler_dis_w;
916 		mod_x = ffs(variant->min_inp_pixsize) - 1;
917 	} else {
918 		max_width = variant->pix_limit->out_rot_dis_w;
919 		mod_x = ffs(variant->min_out_pixsize) - 1;
920 	}
921 
922 	if (tiled_fmt(fmt)) {
923 		mod_x = 6; /* 64 x 32 pixels tile */
924 		mod_y = 5;
925 	} else {
926 		if (fimc->id == 1 && variant->pix_hoff)
927 			mod_y = fimc_fmt_is_rgb(fmt->color) ? 0 : 1;
928 		else
929 			mod_y = mod_x;
930 	}
931 
932 	dbg("mod_x: %d, mod_y: %d, max_w: %d", mod_x, mod_y, max_width);
933 
934 	v4l_bound_align_image(&pix->width, 16, max_width, mod_x,
935 		&pix->height, 8, variant->pix_limit->scaler_dis_w, mod_y, 0);
936 
937 	pix->num_planes = fmt->memplanes;
938 	pix->colorspace	= V4L2_COLORSPACE_JPEG;
939 
940 
941 	for (i = 0; i < pix->num_planes; ++i) {
942 		u32 bpl = pix->plane_fmt[i].bytesperline;
943 		u32 *sizeimage = &pix->plane_fmt[i].sizeimage;
944 
945 		if (fmt->colplanes > 1 && (bpl == 0 || bpl < pix->width))
946 			bpl = pix->width; /* Planar */
947 
948 		if (fmt->colplanes == 1 && /* Packed */
949 		    (bpl == 0 || ((bpl * 8) / fmt->depth[i]) < pix->width))
950 			bpl = (pix->width * fmt->depth[0]) / 8;
951 
952 		if (i == 0) /* Same bytesperline for each plane. */
953 			mod_x = bpl;
954 
955 		pix->plane_fmt[i].bytesperline = mod_x;
956 		*sizeimage = (pix->width * pix->height * fmt->depth[i]) / 8;
957 	}
958 
959 	return 0;
960 }
961 
fimc_m2m_s_fmt_mplane(struct file * file,void * priv,struct v4l2_format * f)962 static int fimc_m2m_s_fmt_mplane(struct file *file, void *priv,
963 				 struct v4l2_format *f)
964 {
965 	struct fimc_ctx *ctx = priv;
966 	struct fimc_dev *fimc = ctx->fimc_dev;
967 	struct vb2_queue *vq;
968 	struct fimc_frame *frame;
969 	struct v4l2_pix_format_mplane *pix;
970 	int i, ret = 0;
971 
972 	ret = fimc_vidioc_try_fmt_mplane(file, priv, f);
973 	if (ret)
974 		return ret;
975 
976 	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
977 
978 	if (vb2_is_busy(vq)) {
979 		v4l2_err(&fimc->m2m.v4l2_dev, "queue (%d) busy\n", f->type);
980 		return -EBUSY;
981 	}
982 
983 	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
984 		frame = &ctx->s_frame;
985 	} else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
986 		frame = &ctx->d_frame;
987 	} else {
988 		v4l2_err(&fimc->m2m.v4l2_dev,
989 			 "Wrong buffer/video queue type (%d)\n", f->type);
990 		return -EINVAL;
991 	}
992 
993 	pix = &f->fmt.pix_mp;
994 	frame->fmt = find_format(f, FMT_FLAGS_M2M);
995 	if (!frame->fmt)
996 		return -EINVAL;
997 
998 	for (i = 0; i < frame->fmt->colplanes; i++) {
999 		frame->payload[i] =
1000 			(pix->width * pix->height * frame->fmt->depth[i]) / 8;
1001 	}
1002 
1003 	frame->f_width	= pix->plane_fmt[0].bytesperline * 8 /
1004 		frame->fmt->depth[0];
1005 	frame->f_height	= pix->height;
1006 	frame->width	= pix->width;
1007 	frame->height	= pix->height;
1008 	frame->o_width	= pix->width;
1009 	frame->o_height = pix->height;
1010 	frame->offs_h	= 0;
1011 	frame->offs_v	= 0;
1012 
1013 	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1014 		fimc_ctx_state_lock_set(FIMC_PARAMS | FIMC_DST_FMT, ctx);
1015 	else
1016 		fimc_ctx_state_lock_set(FIMC_PARAMS | FIMC_SRC_FMT, ctx);
1017 
1018 	dbg("f_w: %d, f_h: %d", frame->f_width, frame->f_height);
1019 
1020 	return 0;
1021 }
1022 
fimc_m2m_reqbufs(struct file * file,void * priv,struct v4l2_requestbuffers * reqbufs)1023 static int fimc_m2m_reqbufs(struct file *file, void *priv,
1024 			  struct v4l2_requestbuffers *reqbufs)
1025 {
1026 	struct fimc_ctx *ctx = priv;
1027 	return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
1028 }
1029 
fimc_m2m_querybuf(struct file * file,void * priv,struct v4l2_buffer * buf)1030 static int fimc_m2m_querybuf(struct file *file, void *priv,
1031 			   struct v4l2_buffer *buf)
1032 {
1033 	struct fimc_ctx *ctx = priv;
1034 	return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
1035 }
1036 
fimc_m2m_qbuf(struct file * file,void * priv,struct v4l2_buffer * buf)1037 static int fimc_m2m_qbuf(struct file *file, void *priv,
1038 			  struct v4l2_buffer *buf)
1039 {
1040 	struct fimc_ctx *ctx = priv;
1041 
1042 	return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
1043 }
1044 
fimc_m2m_dqbuf(struct file * file,void * priv,struct v4l2_buffer * buf)1045 static int fimc_m2m_dqbuf(struct file *file, void *priv,
1046 			   struct v4l2_buffer *buf)
1047 {
1048 	struct fimc_ctx *ctx = priv;
1049 	return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
1050 }
1051 
fimc_m2m_streamon(struct file * file,void * priv,enum v4l2_buf_type type)1052 static int fimc_m2m_streamon(struct file *file, void *priv,
1053 			   enum v4l2_buf_type type)
1054 {
1055 	struct fimc_ctx *ctx = priv;
1056 
1057 	/* The source and target color format need to be set */
1058 	if (V4L2_TYPE_IS_OUTPUT(type)) {
1059 		if (!fimc_ctx_state_is_set(FIMC_SRC_FMT, ctx))
1060 			return -EINVAL;
1061 	} else if (!fimc_ctx_state_is_set(FIMC_DST_FMT, ctx)) {
1062 		return -EINVAL;
1063 	}
1064 
1065 	return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
1066 }
1067 
fimc_m2m_streamoff(struct file * file,void * priv,enum v4l2_buf_type type)1068 static int fimc_m2m_streamoff(struct file *file, void *priv,
1069 			    enum v4l2_buf_type type)
1070 {
1071 	struct fimc_ctx *ctx = priv;
1072 	return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
1073 }
1074 
fimc_vidioc_queryctrl(struct file * file,void * priv,struct v4l2_queryctrl * qc)1075 int fimc_vidioc_queryctrl(struct file *file, void *priv,
1076 			    struct v4l2_queryctrl *qc)
1077 {
1078 	struct fimc_ctx *ctx = priv;
1079 	struct v4l2_queryctrl *c;
1080 	int ret = -EINVAL;
1081 
1082 	c = get_ctrl(qc->id);
1083 	if (c) {
1084 		*qc = *c;
1085 		return 0;
1086 	}
1087 
1088 	if (fimc_ctx_state_is_set(FIMC_CTX_CAP, ctx)) {
1089 		return v4l2_subdev_call(ctx->fimc_dev->vid_cap.sd,
1090 					core, queryctrl, qc);
1091 	}
1092 	return ret;
1093 }
1094 
fimc_vidioc_g_ctrl(struct file * file,void * priv,struct v4l2_control * ctrl)1095 int fimc_vidioc_g_ctrl(struct file *file, void *priv,
1096 			 struct v4l2_control *ctrl)
1097 {
1098 	struct fimc_ctx *ctx = priv;
1099 	struct fimc_dev *fimc = ctx->fimc_dev;
1100 
1101 	switch (ctrl->id) {
1102 	case V4L2_CID_HFLIP:
1103 		ctrl->value = (FLIP_X_AXIS & ctx->flip) ? 1 : 0;
1104 		break;
1105 	case V4L2_CID_VFLIP:
1106 		ctrl->value = (FLIP_Y_AXIS & ctx->flip) ? 1 : 0;
1107 		break;
1108 	case V4L2_CID_ROTATE:
1109 		ctrl->value = ctx->rotation;
1110 		break;
1111 	default:
1112 		if (fimc_ctx_state_is_set(FIMC_CTX_CAP, ctx)) {
1113 			return v4l2_subdev_call(fimc->vid_cap.sd, core,
1114 						g_ctrl, ctrl);
1115 		} else {
1116 			v4l2_err(&fimc->m2m.v4l2_dev, "Invalid control\n");
1117 			return -EINVAL;
1118 		}
1119 	}
1120 	dbg("ctrl->value= %d", ctrl->value);
1121 
1122 	return 0;
1123 }
1124 
check_ctrl_val(struct fimc_ctx * ctx,struct v4l2_control * ctrl)1125 int check_ctrl_val(struct fimc_ctx *ctx,  struct v4l2_control *ctrl)
1126 {
1127 	struct v4l2_queryctrl *c;
1128 	c = get_ctrl(ctrl->id);
1129 	if (!c)
1130 		return -EINVAL;
1131 
1132 	if (ctrl->value < c->minimum || ctrl->value > c->maximum
1133 		|| (c->step != 0 && ctrl->value % c->step != 0)) {
1134 		v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev,
1135 		"Invalid control value\n");
1136 		return -ERANGE;
1137 	}
1138 
1139 	return 0;
1140 }
1141 
fimc_s_ctrl(struct fimc_ctx * ctx,struct v4l2_control * ctrl)1142 int fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_control *ctrl)
1143 {
1144 	struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
1145 	struct fimc_dev *fimc = ctx->fimc_dev;
1146 	int ret = 0;
1147 
1148 	switch (ctrl->id) {
1149 	case V4L2_CID_HFLIP:
1150 		if (ctrl->value)
1151 			ctx->flip |= FLIP_X_AXIS;
1152 		else
1153 			ctx->flip &= ~FLIP_X_AXIS;
1154 		break;
1155 
1156 	case V4L2_CID_VFLIP:
1157 		if (ctrl->value)
1158 			ctx->flip |= FLIP_Y_AXIS;
1159 		else
1160 			ctx->flip &= ~FLIP_Y_AXIS;
1161 		break;
1162 
1163 	case V4L2_CID_ROTATE:
1164 		if (fimc_ctx_state_is_set(FIMC_DST_FMT | FIMC_SRC_FMT, ctx)) {
1165 			ret = fimc_check_scaler_ratio(ctx->s_frame.width,
1166 					ctx->s_frame.height, ctx->d_frame.width,
1167 					ctx->d_frame.height, ctrl->value);
1168 		}
1169 
1170 		if (ret) {
1171 			v4l2_err(&fimc->m2m.v4l2_dev, "Out of scaler range\n");
1172 			return -EINVAL;
1173 		}
1174 
1175 		/* Check for the output rotator availability */
1176 		if ((ctrl->value == 90 || ctrl->value == 270) &&
1177 		    (ctx->in_path == FIMC_DMA && !variant->has_out_rot))
1178 			return -EINVAL;
1179 		ctx->rotation = ctrl->value;
1180 		break;
1181 
1182 	default:
1183 		v4l2_err(&fimc->m2m.v4l2_dev, "Invalid control\n");
1184 		return -EINVAL;
1185 	}
1186 
1187 	fimc_ctx_state_lock_set(FIMC_PARAMS, ctx);
1188 
1189 	return 0;
1190 }
1191 
fimc_m2m_s_ctrl(struct file * file,void * priv,struct v4l2_control * ctrl)1192 static int fimc_m2m_s_ctrl(struct file *file, void *priv,
1193 			   struct v4l2_control *ctrl)
1194 {
1195 	struct fimc_ctx *ctx = priv;
1196 	int ret = 0;
1197 
1198 	ret = check_ctrl_val(ctx, ctrl);
1199 	if (ret)
1200 		return ret;
1201 
1202 	ret = fimc_s_ctrl(ctx, ctrl);
1203 	return 0;
1204 }
1205 
fimc_m2m_cropcap(struct file * file,void * fh,struct v4l2_cropcap * cr)1206 static int fimc_m2m_cropcap(struct file *file, void *fh,
1207 			struct v4l2_cropcap *cr)
1208 {
1209 	struct fimc_frame *frame;
1210 	struct fimc_ctx *ctx = fh;
1211 
1212 	frame = ctx_get_frame(ctx, cr->type);
1213 	if (IS_ERR(frame))
1214 		return PTR_ERR(frame);
1215 
1216 	cr->bounds.left		= 0;
1217 	cr->bounds.top		= 0;
1218 	cr->bounds.width	= frame->f_width;
1219 	cr->bounds.height	= frame->f_height;
1220 	cr->defrect		= cr->bounds;
1221 
1222 	return 0;
1223 }
1224 
fimc_m2m_g_crop(struct file * file,void * fh,struct v4l2_crop * cr)1225 static int fimc_m2m_g_crop(struct file *file, void *fh, struct v4l2_crop *cr)
1226 {
1227 	struct fimc_frame *frame;
1228 	struct fimc_ctx *ctx = file->private_data;
1229 
1230 	frame = ctx_get_frame(ctx, cr->type);
1231 	if (IS_ERR(frame))
1232 		return PTR_ERR(frame);
1233 
1234 	cr->c.left = frame->offs_h;
1235 	cr->c.top = frame->offs_v;
1236 	cr->c.width = frame->width;
1237 	cr->c.height = frame->height;
1238 
1239 	return 0;
1240 }
1241 
fimc_try_crop(struct fimc_ctx * ctx,struct v4l2_crop * cr)1242 int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
1243 {
1244 	struct fimc_dev *fimc = ctx->fimc_dev;
1245 	struct fimc_frame *f;
1246 	u32 min_size, halign, depth = 0;
1247 	bool is_capture_ctx;
1248 	int i;
1249 
1250 	if (cr->c.top < 0 || cr->c.left < 0) {
1251 		v4l2_err(&fimc->m2m.v4l2_dev,
1252 			"doesn't support negative values for top & left\n");
1253 		return -EINVAL;
1254 	}
1255 
1256 	is_capture_ctx = fimc_ctx_state_is_set(FIMC_CTX_CAP, ctx);
1257 
1258 	if (cr->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1259 		f = is_capture_ctx ? &ctx->s_frame : &ctx->d_frame;
1260 	else if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
1261 		 !is_capture_ctx)
1262 		f = &ctx->s_frame;
1263 	else
1264 		return -EINVAL;
1265 
1266 	min_size = (f == &ctx->s_frame) ?
1267 		fimc->variant->min_inp_pixsize : fimc->variant->min_out_pixsize;
1268 
1269 	/* Get pixel alignment constraints. */
1270 	if (is_capture_ctx) {
1271 		min_size = 16;
1272 		halign = 4;
1273 	} else {
1274 		if (fimc->id == 1 && fimc->variant->pix_hoff)
1275 			halign = fimc_fmt_is_rgb(f->fmt->color) ? 0 : 1;
1276 		else
1277 			halign = ffs(min_size) - 1;
1278 	}
1279 
1280 	for (i = 0; i < f->fmt->colplanes; i++)
1281 		depth += f->fmt->depth[i];
1282 
1283 	v4l_bound_align_image(&cr->c.width, min_size, f->o_width,
1284 			      ffs(min_size) - 1,
1285 			      &cr->c.height, min_size, f->o_height,
1286 			      halign, 64/(ALIGN(depth, 8)));
1287 
1288 	/* adjust left/top if cropping rectangle is out of bounds */
1289 	if (cr->c.left + cr->c.width > f->o_width)
1290 		cr->c.left = f->o_width - cr->c.width;
1291 	if (cr->c.top + cr->c.height > f->o_height)
1292 		cr->c.top = f->o_height - cr->c.height;
1293 
1294 	cr->c.left = round_down(cr->c.left, min_size);
1295 	cr->c.top  = round_down(cr->c.top, is_capture_ctx ? 16 : 8);
1296 
1297 	dbg("l:%d, t:%d, w:%d, h:%d, f_w: %d, f_h: %d",
1298 	    cr->c.left, cr->c.top, cr->c.width, cr->c.height,
1299 	    f->f_width, f->f_height);
1300 
1301 	return 0;
1302 }
1303 
fimc_m2m_s_crop(struct file * file,void * fh,struct v4l2_crop * cr)1304 static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
1305 {
1306 	struct fimc_ctx *ctx = file->private_data;
1307 	struct fimc_dev *fimc = ctx->fimc_dev;
1308 	struct fimc_frame *f;
1309 	int ret;
1310 
1311 	ret = fimc_try_crop(ctx, cr);
1312 	if (ret)
1313 		return ret;
1314 
1315 	f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ?
1316 		&ctx->s_frame : &ctx->d_frame;
1317 
1318 	/* Check to see if scaling ratio is within supported range */
1319 	if (fimc_ctx_state_is_set(FIMC_DST_FMT | FIMC_SRC_FMT, ctx)) {
1320 		if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
1321 			ret = fimc_check_scaler_ratio(cr->c.width, cr->c.height,
1322 						      ctx->d_frame.width,
1323 						      ctx->d_frame.height,
1324 						      ctx->rotation);
1325 		} else {
1326 			ret = fimc_check_scaler_ratio(ctx->s_frame.width,
1327 						      ctx->s_frame.height,
1328 						      cr->c.width, cr->c.height,
1329 						      ctx->rotation);
1330 		}
1331 		if (ret) {
1332 			v4l2_err(&fimc->m2m.v4l2_dev, "Out of scaler range\n");
1333 			return -EINVAL;
1334 		}
1335 	}
1336 
1337 	f->offs_h = cr->c.left;
1338 	f->offs_v = cr->c.top;
1339 	f->width  = cr->c.width;
1340 	f->height = cr->c.height;
1341 
1342 	fimc_ctx_state_lock_set(FIMC_PARAMS, ctx);
1343 
1344 	return 0;
1345 }
1346 
1347 static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = {
1348 	.vidioc_querycap		= fimc_m2m_querycap,
1349 
1350 	.vidioc_enum_fmt_vid_cap_mplane	= fimc_vidioc_enum_fmt_mplane,
1351 	.vidioc_enum_fmt_vid_out_mplane	= fimc_vidioc_enum_fmt_mplane,
1352 
1353 	.vidioc_g_fmt_vid_cap_mplane	= fimc_vidioc_g_fmt_mplane,
1354 	.vidioc_g_fmt_vid_out_mplane	= fimc_vidioc_g_fmt_mplane,
1355 
1356 	.vidioc_try_fmt_vid_cap_mplane	= fimc_vidioc_try_fmt_mplane,
1357 	.vidioc_try_fmt_vid_out_mplane	= fimc_vidioc_try_fmt_mplane,
1358 
1359 	.vidioc_s_fmt_vid_cap_mplane	= fimc_m2m_s_fmt_mplane,
1360 	.vidioc_s_fmt_vid_out_mplane	= fimc_m2m_s_fmt_mplane,
1361 
1362 	.vidioc_reqbufs			= fimc_m2m_reqbufs,
1363 	.vidioc_querybuf		= fimc_m2m_querybuf,
1364 
1365 	.vidioc_qbuf			= fimc_m2m_qbuf,
1366 	.vidioc_dqbuf			= fimc_m2m_dqbuf,
1367 
1368 	.vidioc_streamon		= fimc_m2m_streamon,
1369 	.vidioc_streamoff		= fimc_m2m_streamoff,
1370 
1371 	.vidioc_queryctrl		= fimc_vidioc_queryctrl,
1372 	.vidioc_g_ctrl			= fimc_vidioc_g_ctrl,
1373 	.vidioc_s_ctrl			= fimc_m2m_s_ctrl,
1374 
1375 	.vidioc_g_crop			= fimc_m2m_g_crop,
1376 	.vidioc_s_crop			= fimc_m2m_s_crop,
1377 	.vidioc_cropcap			= fimc_m2m_cropcap
1378 
1379 };
1380 
queue_init(void * priv,struct vb2_queue * src_vq,struct vb2_queue * dst_vq)1381 static int queue_init(void *priv, struct vb2_queue *src_vq,
1382 		      struct vb2_queue *dst_vq)
1383 {
1384 	struct fimc_ctx *ctx = priv;
1385 	int ret;
1386 
1387 	memset(src_vq, 0, sizeof(*src_vq));
1388 	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1389 	src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
1390 	src_vq->drv_priv = ctx;
1391 	src_vq->ops = &fimc_qops;
1392 	src_vq->mem_ops = &vb2_dma_contig_memops;
1393 	src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
1394 
1395 	ret = vb2_queue_init(src_vq);
1396 	if (ret)
1397 		return ret;
1398 
1399 	memset(dst_vq, 0, sizeof(*dst_vq));
1400 	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1401 	dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
1402 	dst_vq->drv_priv = ctx;
1403 	dst_vq->ops = &fimc_qops;
1404 	dst_vq->mem_ops = &vb2_dma_contig_memops;
1405 	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
1406 
1407 	return vb2_queue_init(dst_vq);
1408 }
1409 
fimc_m2m_open(struct file * file)1410 static int fimc_m2m_open(struct file *file)
1411 {
1412 	struct fimc_dev *fimc = video_drvdata(file);
1413 	struct fimc_ctx *ctx = NULL;
1414 
1415 	dbg("pid: %d, state: 0x%lx, refcnt: %d",
1416 		task_pid_nr(current), fimc->state, fimc->vid_cap.refcnt);
1417 
1418 	/*
1419 	 * Return if the corresponding video capture node
1420 	 * is already opened.
1421 	 */
1422 	if (fimc->vid_cap.refcnt > 0)
1423 		return -EBUSY;
1424 
1425 	fimc->m2m.refcnt++;
1426 	set_bit(ST_OUTDMA_RUN, &fimc->state);
1427 
1428 	ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
1429 	if (!ctx)
1430 		return -ENOMEM;
1431 
1432 	file->private_data = ctx;
1433 	ctx->fimc_dev = fimc;
1434 	/* Default color format */
1435 	ctx->s_frame.fmt = &fimc_formats[0];
1436 	ctx->d_frame.fmt = &fimc_formats[0];
1437 	/* Setup the device context for mem2mem mode. */
1438 	ctx->state = FIMC_CTX_M2M;
1439 	ctx->flags = 0;
1440 	ctx->in_path = FIMC_DMA;
1441 	ctx->out_path = FIMC_DMA;
1442 	spin_lock_init(&ctx->slock);
1443 
1444 	ctx->m2m_ctx = v4l2_m2m_ctx_init(fimc->m2m.m2m_dev, ctx, queue_init);
1445 	if (IS_ERR(ctx->m2m_ctx)) {
1446 		int err = PTR_ERR(ctx->m2m_ctx);
1447 		kfree(ctx);
1448 		return err;
1449 	}
1450 
1451 	return 0;
1452 }
1453 
fimc_m2m_release(struct file * file)1454 static int fimc_m2m_release(struct file *file)
1455 {
1456 	struct fimc_ctx *ctx = file->private_data;
1457 	struct fimc_dev *fimc = ctx->fimc_dev;
1458 
1459 	dbg("pid: %d, state: 0x%lx, refcnt= %d",
1460 		task_pid_nr(current), fimc->state, fimc->m2m.refcnt);
1461 
1462 	v4l2_m2m_ctx_release(ctx->m2m_ctx);
1463 	kfree(ctx);
1464 	if (--fimc->m2m.refcnt <= 0)
1465 		clear_bit(ST_OUTDMA_RUN, &fimc->state);
1466 
1467 	return 0;
1468 }
1469 
fimc_m2m_poll(struct file * file,struct poll_table_struct * wait)1470 static unsigned int fimc_m2m_poll(struct file *file,
1471 				     struct poll_table_struct *wait)
1472 {
1473 	struct fimc_ctx *ctx = file->private_data;
1474 
1475 	return v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
1476 }
1477 
1478 
fimc_m2m_mmap(struct file * file,struct vm_area_struct * vma)1479 static int fimc_m2m_mmap(struct file *file, struct vm_area_struct *vma)
1480 {
1481 	struct fimc_ctx *ctx = file->private_data;
1482 
1483 	return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
1484 }
1485 
1486 static const struct v4l2_file_operations fimc_m2m_fops = {
1487 	.owner		= THIS_MODULE,
1488 	.open		= fimc_m2m_open,
1489 	.release	= fimc_m2m_release,
1490 	.poll		= fimc_m2m_poll,
1491 	.unlocked_ioctl	= video_ioctl2,
1492 	.mmap		= fimc_m2m_mmap,
1493 };
1494 
1495 static struct v4l2_m2m_ops m2m_ops = {
1496 	.device_run	= fimc_dma_run,
1497 	.job_abort	= fimc_job_abort,
1498 };
1499 
fimc_register_m2m_device(struct fimc_dev * fimc)1500 static int fimc_register_m2m_device(struct fimc_dev *fimc)
1501 {
1502 	struct video_device *vfd;
1503 	struct platform_device *pdev;
1504 	struct v4l2_device *v4l2_dev;
1505 	int ret = 0;
1506 
1507 	if (!fimc)
1508 		return -ENODEV;
1509 
1510 	pdev = fimc->pdev;
1511 	v4l2_dev = &fimc->m2m.v4l2_dev;
1512 
1513 	/* set name if it is empty */
1514 	if (!v4l2_dev->name[0])
1515 		snprintf(v4l2_dev->name, sizeof(v4l2_dev->name),
1516 			 "%s.m2m", dev_name(&pdev->dev));
1517 
1518 	ret = v4l2_device_register(&pdev->dev, v4l2_dev);
1519 	if (ret)
1520 		goto err_m2m_r1;
1521 
1522 	vfd = video_device_alloc();
1523 	if (!vfd) {
1524 		v4l2_err(v4l2_dev, "Failed to allocate video device\n");
1525 		goto err_m2m_r1;
1526 	}
1527 
1528 	vfd->fops	= &fimc_m2m_fops;
1529 	vfd->ioctl_ops	= &fimc_m2m_ioctl_ops;
1530 	vfd->minor	= -1;
1531 	vfd->release	= video_device_release;
1532 	vfd->lock	= &fimc->lock;
1533 
1534 	snprintf(vfd->name, sizeof(vfd->name), "%s:m2m", dev_name(&pdev->dev));
1535 
1536 	video_set_drvdata(vfd, fimc);
1537 	platform_set_drvdata(pdev, fimc);
1538 
1539 	fimc->m2m.vfd = vfd;
1540 	fimc->m2m.m2m_dev = v4l2_m2m_init(&m2m_ops);
1541 	if (IS_ERR(fimc->m2m.m2m_dev)) {
1542 		v4l2_err(v4l2_dev, "failed to initialize v4l2-m2m device\n");
1543 		ret = PTR_ERR(fimc->m2m.m2m_dev);
1544 		goto err_m2m_r2;
1545 	}
1546 
1547 	ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
1548 	if (ret) {
1549 		v4l2_err(v4l2_dev,
1550 			 "%s(): failed to register video device\n", __func__);
1551 		goto err_m2m_r3;
1552 	}
1553 	v4l2_info(v4l2_dev,
1554 		  "FIMC m2m driver registered as /dev/video%d\n", vfd->num);
1555 
1556 	return 0;
1557 
1558 err_m2m_r3:
1559 	v4l2_m2m_release(fimc->m2m.m2m_dev);
1560 err_m2m_r2:
1561 	video_device_release(fimc->m2m.vfd);
1562 err_m2m_r1:
1563 	v4l2_device_unregister(v4l2_dev);
1564 
1565 	return ret;
1566 }
1567 
fimc_unregister_m2m_device(struct fimc_dev * fimc)1568 static void fimc_unregister_m2m_device(struct fimc_dev *fimc)
1569 {
1570 	if (fimc) {
1571 		v4l2_m2m_release(fimc->m2m.m2m_dev);
1572 		video_unregister_device(fimc->m2m.vfd);
1573 
1574 		v4l2_device_unregister(&fimc->m2m.v4l2_dev);
1575 	}
1576 }
1577 
fimc_clk_release(struct fimc_dev * fimc)1578 static void fimc_clk_release(struct fimc_dev *fimc)
1579 {
1580 	int i;
1581 	for (i = 0; i < fimc->num_clocks; i++) {
1582 		if (fimc->clock[i]) {
1583 			clk_disable(fimc->clock[i]);
1584 			clk_put(fimc->clock[i]);
1585 		}
1586 	}
1587 }
1588 
fimc_clk_get(struct fimc_dev * fimc)1589 static int fimc_clk_get(struct fimc_dev *fimc)
1590 {
1591 	int i;
1592 	for (i = 0; i < fimc->num_clocks; i++) {
1593 		fimc->clock[i] = clk_get(&fimc->pdev->dev, fimc_clocks[i]);
1594 
1595 		if (!IS_ERR_OR_NULL(fimc->clock[i])) {
1596 			clk_enable(fimc->clock[i]);
1597 			continue;
1598 		}
1599 		dev_err(&fimc->pdev->dev, "failed to get fimc clock: %s\n",
1600 			fimc_clocks[i]);
1601 		return -ENXIO;
1602 	}
1603 	return 0;
1604 }
1605 
fimc_probe(struct platform_device * pdev)1606 static int fimc_probe(struct platform_device *pdev)
1607 {
1608 	struct fimc_dev *fimc;
1609 	struct resource *res;
1610 	struct samsung_fimc_driverdata *drv_data;
1611 	struct s5p_platform_fimc *pdata;
1612 	int ret = 0;
1613 	int cap_input_index = -1;
1614 
1615 	dev_dbg(&pdev->dev, "%s():\n", __func__);
1616 
1617 	drv_data = (struct samsung_fimc_driverdata *)
1618 		platform_get_device_id(pdev)->driver_data;
1619 
1620 	if (pdev->id >= drv_data->num_entities) {
1621 		dev_err(&pdev->dev, "Invalid platform device id: %d\n",
1622 			pdev->id);
1623 		return -EINVAL;
1624 	}
1625 
1626 	fimc = kzalloc(sizeof(struct fimc_dev), GFP_KERNEL);
1627 	if (!fimc)
1628 		return -ENOMEM;
1629 
1630 	fimc->id = pdev->id;
1631 	fimc->variant = drv_data->variant[fimc->id];
1632 	fimc->pdev = pdev;
1633 	pdata = pdev->dev.platform_data;
1634 	fimc->pdata = pdata;
1635 	fimc->state = ST_IDLE;
1636 
1637 	init_waitqueue_head(&fimc->irq_queue);
1638 	spin_lock_init(&fimc->slock);
1639 
1640 	mutex_init(&fimc->lock);
1641 
1642 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1643 	if (!res) {
1644 		dev_err(&pdev->dev, "failed to find the registers\n");
1645 		ret = -ENOENT;
1646 		goto err_info;
1647 	}
1648 
1649 	fimc->regs_res = request_mem_region(res->start, resource_size(res),
1650 			dev_name(&pdev->dev));
1651 	if (!fimc->regs_res) {
1652 		dev_err(&pdev->dev, "failed to obtain register region\n");
1653 		ret = -ENOENT;
1654 		goto err_info;
1655 	}
1656 
1657 	fimc->regs = ioremap(res->start, resource_size(res));
1658 	if (!fimc->regs) {
1659 		dev_err(&pdev->dev, "failed to map registers\n");
1660 		ret = -ENXIO;
1661 		goto err_req_region;
1662 	}
1663 
1664 	fimc->num_clocks = MAX_FIMC_CLOCKS - 1;
1665 
1666 	/* Check if a video capture node needs to be registered. */
1667 	if (pdata && pdata->num_clients > 0) {
1668 		cap_input_index = 0;
1669 		fimc->num_clocks++;
1670 	}
1671 
1672 	ret = fimc_clk_get(fimc);
1673 	if (ret)
1674 		goto err_regs_unmap;
1675 	clk_set_rate(fimc->clock[CLK_BUS], drv_data->lclk_frequency);
1676 
1677 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1678 	if (!res) {
1679 		dev_err(&pdev->dev, "failed to get IRQ resource\n");
1680 		ret = -ENXIO;
1681 		goto err_clk;
1682 	}
1683 	fimc->irq = res->start;
1684 
1685 	fimc_hw_reset(fimc);
1686 
1687 	ret = request_irq(fimc->irq, fimc_isr, 0, pdev->name, fimc);
1688 	if (ret) {
1689 		dev_err(&pdev->dev, "failed to install irq (%d)\n", ret);
1690 		goto err_clk;
1691 	}
1692 
1693 	/* Initialize contiguous memory allocator */
1694 	fimc->alloc_ctx = vb2_dma_contig_init_ctx(&fimc->pdev->dev);
1695 	if (IS_ERR(fimc->alloc_ctx)) {
1696 		ret = PTR_ERR(fimc->alloc_ctx);
1697 		goto err_irq;
1698 	}
1699 
1700 	ret = fimc_register_m2m_device(fimc);
1701 	if (ret)
1702 		goto err_irq;
1703 
1704 	/* At least one camera sensor is required to register capture node */
1705 	if (cap_input_index >= 0) {
1706 		ret = fimc_register_capture_device(fimc);
1707 		if (ret)
1708 			goto err_m2m;
1709 		clk_disable(fimc->clock[CLK_CAM]);
1710 	}
1711 	/*
1712 	 * Exclude the additional output DMA address registers by masking
1713 	 * them out on HW revisions that provide extended capabilites.
1714 	 */
1715 	if (fimc->variant->out_buf_count > 4)
1716 		fimc_hw_set_dma_seq(fimc, 0xF);
1717 
1718 	dev_dbg(&pdev->dev, "%s(): fimc-%d registered successfully\n",
1719 		__func__, fimc->id);
1720 
1721 	return 0;
1722 
1723 err_m2m:
1724 	fimc_unregister_m2m_device(fimc);
1725 err_irq:
1726 	free_irq(fimc->irq, fimc);
1727 err_clk:
1728 	fimc_clk_release(fimc);
1729 err_regs_unmap:
1730 	iounmap(fimc->regs);
1731 err_req_region:
1732 	release_resource(fimc->regs_res);
1733 	kfree(fimc->regs_res);
1734 err_info:
1735 	kfree(fimc);
1736 
1737 	return ret;
1738 }
1739 
fimc_remove(struct platform_device * pdev)1740 static int __devexit fimc_remove(struct platform_device *pdev)
1741 {
1742 	struct fimc_dev *fimc =
1743 		(struct fimc_dev *)platform_get_drvdata(pdev);
1744 
1745 	free_irq(fimc->irq, fimc);
1746 	fimc_hw_reset(fimc);
1747 
1748 	fimc_unregister_m2m_device(fimc);
1749 	fimc_unregister_capture_device(fimc);
1750 
1751 	fimc_clk_release(fimc);
1752 
1753 	vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx);
1754 
1755 	iounmap(fimc->regs);
1756 	release_resource(fimc->regs_res);
1757 	kfree(fimc->regs_res);
1758 	kfree(fimc);
1759 
1760 	dev_info(&pdev->dev, "%s driver unloaded\n", pdev->name);
1761 	return 0;
1762 }
1763 
1764 /* Image pixel limits, similar across several FIMC HW revisions. */
1765 static struct fimc_pix_limit s5p_pix_limit[4] = {
1766 	[0] = {
1767 		.scaler_en_w	= 3264,
1768 		.scaler_dis_w	= 8192,
1769 		.in_rot_en_h	= 1920,
1770 		.in_rot_dis_w	= 8192,
1771 		.out_rot_en_w	= 1920,
1772 		.out_rot_dis_w	= 4224,
1773 	},
1774 	[1] = {
1775 		.scaler_en_w	= 4224,
1776 		.scaler_dis_w	= 8192,
1777 		.in_rot_en_h	= 1920,
1778 		.in_rot_dis_w	= 8192,
1779 		.out_rot_en_w	= 1920,
1780 		.out_rot_dis_w	= 4224,
1781 	},
1782 	[2] = {
1783 		.scaler_en_w	= 1920,
1784 		.scaler_dis_w	= 8192,
1785 		.in_rot_en_h	= 1280,
1786 		.in_rot_dis_w	= 8192,
1787 		.out_rot_en_w	= 1280,
1788 		.out_rot_dis_w	= 1920,
1789 	},
1790 	[3] = {
1791 		.scaler_en_w	= 1920,
1792 		.scaler_dis_w	= 8192,
1793 		.in_rot_en_h	= 1366,
1794 		.in_rot_dis_w	= 8192,
1795 		.out_rot_en_w	= 1366,
1796 		.out_rot_dis_w	= 1920,
1797 	},
1798 };
1799 
1800 static struct samsung_fimc_variant fimc0_variant_s5p = {
1801 	.has_inp_rot	 = 1,
1802 	.has_out_rot	 = 1,
1803 	.min_inp_pixsize = 16,
1804 	.min_out_pixsize = 16,
1805 	.hor_offs_align	 = 8,
1806 	.out_buf_count	 = 4,
1807 	.pix_limit	 = &s5p_pix_limit[0],
1808 };
1809 
1810 static struct samsung_fimc_variant fimc2_variant_s5p = {
1811 	.min_inp_pixsize = 16,
1812 	.min_out_pixsize = 16,
1813 	.hor_offs_align	 = 8,
1814 	.out_buf_count	 = 4,
1815 	.pix_limit = &s5p_pix_limit[1],
1816 };
1817 
1818 static struct samsung_fimc_variant fimc0_variant_s5pv210 = {
1819 	.pix_hoff	 = 1,
1820 	.has_inp_rot	 = 1,
1821 	.has_out_rot	 = 1,
1822 	.min_inp_pixsize = 16,
1823 	.min_out_pixsize = 16,
1824 	.hor_offs_align	 = 8,
1825 	.out_buf_count	 = 4,
1826 	.pix_limit	 = &s5p_pix_limit[1],
1827 };
1828 
1829 static struct samsung_fimc_variant fimc1_variant_s5pv210 = {
1830 	.pix_hoff	 = 1,
1831 	.has_inp_rot	 = 1,
1832 	.has_out_rot	 = 1,
1833 	.has_mainscaler_ext = 1,
1834 	.min_inp_pixsize = 16,
1835 	.min_out_pixsize = 16,
1836 	.hor_offs_align	 = 1,
1837 	.out_buf_count	 = 4,
1838 	.pix_limit	 = &s5p_pix_limit[2],
1839 };
1840 
1841 static struct samsung_fimc_variant fimc2_variant_s5pv210 = {
1842 	.pix_hoff	 = 1,
1843 	.min_inp_pixsize = 16,
1844 	.min_out_pixsize = 16,
1845 	.hor_offs_align	 = 8,
1846 	.out_buf_count	 = 4,
1847 	.pix_limit	 = &s5p_pix_limit[2],
1848 };
1849 
1850 static struct samsung_fimc_variant fimc0_variant_exynos4 = {
1851 	.pix_hoff	 = 1,
1852 	.has_inp_rot	 = 1,
1853 	.has_out_rot	 = 1,
1854 	.has_cistatus2	 = 1,
1855 	.has_mainscaler_ext = 1,
1856 	.min_inp_pixsize = 16,
1857 	.min_out_pixsize = 16,
1858 	.hor_offs_align	 = 1,
1859 	.out_buf_count	 = 32,
1860 	.pix_limit	 = &s5p_pix_limit[1],
1861 };
1862 
1863 static struct samsung_fimc_variant fimc2_variant_exynos4 = {
1864 	.pix_hoff	 = 1,
1865 	.has_cistatus2	 = 1,
1866 	.has_mainscaler_ext = 1,
1867 	.min_inp_pixsize = 16,
1868 	.min_out_pixsize = 16,
1869 	.hor_offs_align	 = 1,
1870 	.out_buf_count	 = 32,
1871 	.pix_limit	 = &s5p_pix_limit[3],
1872 };
1873 
1874 /* S5PC100 */
1875 static struct samsung_fimc_driverdata fimc_drvdata_s5p = {
1876 	.variant = {
1877 		[0] = &fimc0_variant_s5p,
1878 		[1] = &fimc0_variant_s5p,
1879 		[2] = &fimc2_variant_s5p,
1880 	},
1881 	.num_entities = 3,
1882 	.lclk_frequency = 133000000UL,
1883 };
1884 
1885 /* S5PV210, S5PC110 */
1886 static struct samsung_fimc_driverdata fimc_drvdata_s5pv210 = {
1887 	.variant = {
1888 		[0] = &fimc0_variant_s5pv210,
1889 		[1] = &fimc1_variant_s5pv210,
1890 		[2] = &fimc2_variant_s5pv210,
1891 	},
1892 	.num_entities = 3,
1893 	.lclk_frequency = 166000000UL,
1894 };
1895 
1896 /* S5PV310, S5PC210 */
1897 static struct samsung_fimc_driverdata fimc_drvdata_exynos4 = {
1898 	.variant = {
1899 		[0] = &fimc0_variant_exynos4,
1900 		[1] = &fimc0_variant_exynos4,
1901 		[2] = &fimc0_variant_exynos4,
1902 		[3] = &fimc2_variant_exynos4,
1903 	},
1904 	.num_entities = 4,
1905 	.lclk_frequency = 166000000UL,
1906 };
1907 
1908 static struct platform_device_id fimc_driver_ids[] = {
1909 	{
1910 		.name		= "s5p-fimc",
1911 		.driver_data	= (unsigned long)&fimc_drvdata_s5p,
1912 	}, {
1913 		.name		= "s5pv210-fimc",
1914 		.driver_data	= (unsigned long)&fimc_drvdata_s5pv210,
1915 	}, {
1916 		.name		= "exynos4-fimc",
1917 		.driver_data	= (unsigned long)&fimc_drvdata_exynos4,
1918 	},
1919 	{},
1920 };
1921 MODULE_DEVICE_TABLE(platform, fimc_driver_ids);
1922 
1923 static struct platform_driver fimc_driver = {
1924 	.probe		= fimc_probe,
1925 	.remove	= __devexit_p(fimc_remove),
1926 	.id_table	= fimc_driver_ids,
1927 	.driver = {
1928 		.name	= MODULE_NAME,
1929 		.owner	= THIS_MODULE,
1930 	}
1931 };
1932 
fimc_init(void)1933 static int __init fimc_init(void)
1934 {
1935 	int ret = platform_driver_register(&fimc_driver);
1936 	if (ret)
1937 		err("platform_driver_register failed: %d\n", ret);
1938 	return ret;
1939 }
1940 
fimc_exit(void)1941 static void __exit fimc_exit(void)
1942 {
1943 	platform_driver_unregister(&fimc_driver);
1944 }
1945 
1946 module_init(fimc_init);
1947 module_exit(fimc_exit);
1948 
1949 MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
1950 MODULE_DESCRIPTION("S5P FIMC camera host interface/video postprocessor driver");
1951 MODULE_LICENSE("GPL");
1952