1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Samsung S5P/EXYNOS4 SoC series FIMC (CAMIF) driver
4 *
5 * Copyright (C) 2010-2012 Samsung Electronics Co., Ltd.
6 * Sylwester Nawrocki <s.nawrocki@samsung.com>
7 */
8
9#include <linux/module.h>
10#include <linux/kernel.h>
11#include <linux/types.h>
12#include <linux/errno.h>
13#include <linux/bug.h>
14#include <linux/interrupt.h>
15#include <linux/device.h>
16#include <linux/platform_device.h>
17#include <linux/pm_runtime.h>
18#include <linux/list.h>
19#include <linux/mfd/syscon.h>
20#include <linux/io.h>
21#include <linux/of.h>
22#include <linux/slab.h>
23#include <linux/clk.h>
24#include <media/v4l2-ioctl.h>
25#include <media/videobuf2-v4l2.h>
26#include <media/videobuf2-dma-contig.h>
27
28#include "fimc-core.h"
29#include "fimc-reg.h"
30#include "media-dev.h"
31
32static const char *fimc_clocks[MAX_FIMC_CLOCKS] = {
33	"sclk_fimc", "fimc"
34};
35
36static const struct fimc_fmt fimc_formats[] = {
37	{
38		.fourcc		= V4L2_PIX_FMT_RGB565,
39		.depth		= { 16 },
40		.color		= FIMC_FMT_RGB565,
41		.memplanes	= 1,
42		.colplanes	= 1,
43		.flags		= FMT_FLAGS_M2M,
44	}, {
45		.fourcc		= V4L2_PIX_FMT_BGR666,
46		.depth		= { 32 },
47		.color		= FIMC_FMT_RGB666,
48		.memplanes	= 1,
49		.colplanes	= 1,
50		.flags		= FMT_FLAGS_M2M,
51	}, {
52		.fourcc		= V4L2_PIX_FMT_BGR32,
53		.depth		= { 32 },
54		.color		= FIMC_FMT_RGB888,
55		.memplanes	= 1,
56		.colplanes	= 1,
57		.flags		= FMT_FLAGS_M2M | FMT_HAS_ALPHA,
58	}, {
59		.fourcc		= V4L2_PIX_FMT_RGB555,
60		.depth		= { 16 },
61		.color		= FIMC_FMT_RGB555,
62		.memplanes	= 1,
63		.colplanes	= 1,
64		.flags		= FMT_FLAGS_M2M_OUT | FMT_HAS_ALPHA,
65	}, {
66		.fourcc		= V4L2_PIX_FMT_RGB444,
67		.depth		= { 16 },
68		.color		= FIMC_FMT_RGB444,
69		.memplanes	= 1,
70		.colplanes	= 1,
71		.flags		= FMT_FLAGS_M2M_OUT | FMT_HAS_ALPHA,
72	}, {
73		.mbus_code	= MEDIA_BUS_FMT_YUV10_1X30,
74		.flags		= FMT_FLAGS_WRITEBACK,
75	}, {
76		.fourcc		= V4L2_PIX_FMT_YUYV,
77		.depth		= { 16 },
78		.color		= FIMC_FMT_YCBYCR422,
79		.memplanes	= 1,
80		.colplanes	= 1,
81		.mbus_code	= MEDIA_BUS_FMT_YUYV8_2X8,
82		.flags		= FMT_FLAGS_M2M | FMT_FLAGS_CAM,
83	}, {
84		.fourcc		= V4L2_PIX_FMT_UYVY,
85		.depth		= { 16 },
86		.color		= FIMC_FMT_CBYCRY422,
87		.memplanes	= 1,
88		.colplanes	= 1,
89		.mbus_code	= MEDIA_BUS_FMT_UYVY8_2X8,
90		.flags		= FMT_FLAGS_M2M | FMT_FLAGS_CAM,
91	}, {
92		.fourcc		= V4L2_PIX_FMT_VYUY,
93		.depth		= { 16 },
94		.color		= FIMC_FMT_CRYCBY422,
95		.memplanes	= 1,
96		.colplanes	= 1,
97		.mbus_code	= MEDIA_BUS_FMT_VYUY8_2X8,
98		.flags		= FMT_FLAGS_M2M | FMT_FLAGS_CAM,
99	}, {
100		.fourcc		= V4L2_PIX_FMT_YVYU,
101		.depth		= { 16 },
102		.color		= FIMC_FMT_YCRYCB422,
103		.memplanes	= 1,
104		.colplanes	= 1,
105		.mbus_code	= MEDIA_BUS_FMT_YVYU8_2X8,
106		.flags		= FMT_FLAGS_M2M | FMT_FLAGS_CAM,
107	}, {
108		.fourcc		= V4L2_PIX_FMT_YUV422P,
109		.depth		= { 16 },
110		.color		= FIMC_FMT_YCBYCR422,
111		.memplanes	= 1,
112		.colplanes	= 3,
113		.flags		= FMT_FLAGS_M2M,
114	}, {
115		.fourcc		= V4L2_PIX_FMT_NV16,
116		.depth		= { 16 },
117		.color		= FIMC_FMT_YCBYCR422,
118		.memplanes	= 1,
119		.colplanes	= 2,
120		.flags		= FMT_FLAGS_M2M,
121	}, {
122		.fourcc		= V4L2_PIX_FMT_NV61,
123		.depth		= { 16 },
124		.color		= FIMC_FMT_YCRYCB422,
125		.memplanes	= 1,
126		.colplanes	= 2,
127		.flags		= FMT_FLAGS_M2M,
128	}, {
129		.fourcc		= V4L2_PIX_FMT_YUV420,
130		.depth		= { 12 },
131		.color		= FIMC_FMT_YCBCR420,
132		.memplanes	= 1,
133		.colplanes	= 3,
134		.flags		= FMT_FLAGS_M2M,
135	}, {
136		.fourcc		= V4L2_PIX_FMT_NV12,
137		.depth		= { 12 },
138		.color		= FIMC_FMT_YCBCR420,
139		.memplanes	= 1,
140		.colplanes	= 2,
141		.flags		= FMT_FLAGS_M2M,
142	}, {
143		.fourcc		= V4L2_PIX_FMT_NV12M,
144		.color		= FIMC_FMT_YCBCR420,
145		.depth		= { 8, 4 },
146		.memplanes	= 2,
147		.colplanes	= 2,
148		.flags		= FMT_FLAGS_M2M,
149	}, {
150		.fourcc		= V4L2_PIX_FMT_YUV420M,
151		.color		= FIMC_FMT_YCBCR420,
152		.depth		= { 8, 2, 2 },
153		.memplanes	= 3,
154		.colplanes	= 3,
155		.flags		= FMT_FLAGS_M2M,
156	}, {
157		.fourcc		= V4L2_PIX_FMT_NV12MT,
158		.color		= FIMC_FMT_YCBCR420,
159		.depth		= { 8, 4 },
160		.memplanes	= 2,
161		.colplanes	= 2,
162		.flags		= FMT_FLAGS_M2M,
163	}, {
164		.fourcc		= V4L2_PIX_FMT_JPEG,
165		.color		= FIMC_FMT_JPEG,
166		.depth		= { 8 },
167		.memplanes	= 1,
168		.colplanes	= 1,
169		.mbus_code	= MEDIA_BUS_FMT_JPEG_1X8,
170		.flags		= FMT_FLAGS_CAM | FMT_FLAGS_COMPRESSED,
171	}, {
172		.fourcc		= V4L2_PIX_FMT_S5C_UYVY_JPG,
173		.color		= FIMC_FMT_YUYV_JPEG,
174		.depth		= { 8 },
175		.memplanes	= 2,
176		.colplanes	= 1,
177		.mdataplanes	= 0x2, /* plane 1 holds frame meta data */
178		.mbus_code	= MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8,
179		.flags		= FMT_FLAGS_CAM | FMT_FLAGS_COMPRESSED,
180	},
181};
182
183const struct fimc_fmt *fimc_get_format(unsigned int index)
184{
185	if (index >= ARRAY_SIZE(fimc_formats))
186		return NULL;
187
188	return &fimc_formats[index];
189}
190
191int fimc_check_scaler_ratio(struct fimc_ctx *ctx, int sw, int sh,
192			    int dw, int dh, int rotation)
193{
194	if (rotation == 90 || rotation == 270)
195		swap(dw, dh);
196
197	if (!ctx->scaler.enabled)
198		return (sw == dw && sh == dh) ? 0 : -EINVAL;
199
200	if ((sw >= SCALER_MAX_HRATIO * dw) || (sh >= SCALER_MAX_VRATIO * dh))
201		return -EINVAL;
202
203	return 0;
204}
205
206static int fimc_get_scaler_factor(u32 src, u32 tar, u32 *ratio, u32 *shift)
207{
208	u32 sh = 6;
209
210	if (src >= 64 * tar)
211		return -EINVAL;
212
213	while (sh--) {
214		u32 tmp = 1 << sh;
215		if (src >= tar * tmp) {
216			*shift = sh;
217			*ratio = tmp;
218			return 0;
219		}
220	}
221	*shift = 0;
222	*ratio = 1;
223	return 0;
224}
225
226int fimc_set_scaler_info(struct fimc_ctx *ctx)
227{
228	const struct fimc_variant *variant = ctx->fimc_dev->variant;
229	struct device *dev = &ctx->fimc_dev->pdev->dev;
230	struct fimc_scaler *sc = &ctx->scaler;
231	const struct fimc_frame *s_frame = &ctx->s_frame;
232	const struct fimc_frame *d_frame = &ctx->d_frame;
233	int tx, ty, sx, sy;
234	int ret;
235
236	if (ctx->rotation == 90 || ctx->rotation == 270) {
237		ty = d_frame->width;
238		tx = d_frame->height;
239	} else {
240		tx = d_frame->width;
241		ty = d_frame->height;
242	}
243	if (tx <= 0 || ty <= 0) {
244		dev_err(dev, "Invalid target size: %dx%d\n", tx, ty);
245		return -EINVAL;
246	}
247
248	sx = s_frame->width;
249	sy = s_frame->height;
250	if (sx <= 0 || sy <= 0) {
251		dev_err(dev, "Invalid source size: %dx%d\n", sx, sy);
252		return -EINVAL;
253	}
254	sc->real_width = sx;
255	sc->real_height = sy;
256
257	ret = fimc_get_scaler_factor(sx, tx, &sc->pre_hratio, &sc->hfactor);
258	if (ret)
259		return ret;
260
261	ret = fimc_get_scaler_factor(sy, ty,  &sc->pre_vratio, &sc->vfactor);
262	if (ret)
263		return ret;
264
265	sc->pre_dst_width = sx / sc->pre_hratio;
266	sc->pre_dst_height = sy / sc->pre_vratio;
267
268	if (variant->has_mainscaler_ext) {
269		sc->main_hratio = (sx << 14) / (tx << sc->hfactor);
270		sc->main_vratio = (sy << 14) / (ty << sc->vfactor);
271	} else {
272		sc->main_hratio = (sx << 8) / (tx << sc->hfactor);
273		sc->main_vratio = (sy << 8) / (ty << sc->vfactor);
274
275	}
276
277	sc->scaleup_h = (tx >= sx) ? 1 : 0;
278	sc->scaleup_v = (ty >= sy) ? 1 : 0;
279
280	/* check to see if input and output size/format differ */
281	if (s_frame->fmt->color == d_frame->fmt->color
282		&& s_frame->width == d_frame->width
283		&& s_frame->height == d_frame->height)
284		sc->copy_mode = 1;
285	else
286		sc->copy_mode = 0;
287
288	return 0;
289}
290
291static irqreturn_t fimc_irq_handler(int irq, void *priv)
292{
293	struct fimc_dev *fimc = priv;
294	struct fimc_ctx *ctx;
295
296	fimc_hw_clear_irq(fimc);
297
298	spin_lock(&fimc->slock);
299
300	if (test_and_clear_bit(ST_M2M_PEND, &fimc->state)) {
301		if (test_and_clear_bit(ST_M2M_SUSPENDING, &fimc->state)) {
302			set_bit(ST_M2M_SUSPENDED, &fimc->state);
303			wake_up(&fimc->irq_queue);
304			goto out;
305		}
306		ctx = v4l2_m2m_get_curr_priv(fimc->m2m.m2m_dev);
307		if (ctx != NULL) {
308			spin_unlock(&fimc->slock);
309			fimc_m2m_job_finish(ctx, VB2_BUF_STATE_DONE);
310
311			if (ctx->state & FIMC_CTX_SHUT) {
312				ctx->state &= ~FIMC_CTX_SHUT;
313				wake_up(&fimc->irq_queue);
314			}
315			return IRQ_HANDLED;
316		}
317	} else if (test_bit(ST_CAPT_PEND, &fimc->state)) {
318		int last_buf = test_bit(ST_CAPT_JPEG, &fimc->state) &&
319				fimc->vid_cap.reqbufs_count == 1;
320		fimc_capture_irq_handler(fimc, !last_buf);
321	}
322out:
323	spin_unlock(&fimc->slock);
324	return IRQ_HANDLED;
325}
326
327/* The color format (colplanes, memplanes) must be already configured. */
328int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb,
329		      const struct fimc_frame *frame, struct fimc_addr *addr)
330{
331	int ret = 0;
332	u32 pix_size;
333
334	if (vb == NULL || frame == NULL)
335		return -EINVAL;
336
337	pix_size = frame->width * frame->height;
338
339	dbg("memplanes= %d, colplanes= %d, pix_size= %d",
340		frame->fmt->memplanes, frame->fmt->colplanes, pix_size);
341
342	addr->y = vb2_dma_contig_plane_dma_addr(vb, 0);
343
344	if (frame->fmt->memplanes == 1) {
345		switch (frame->fmt->colplanes) {
346		case 1:
347			addr->cb = 0;
348			addr->cr = 0;
349			break;
350		case 2:
351			/* decompose Y into Y/Cb */
352			addr->cb = (u32)(addr->y + pix_size);
353			addr->cr = 0;
354			break;
355		case 3:
356			addr->cb = (u32)(addr->y + pix_size);
357			/* decompose Y into Y/Cb/Cr */
358			if (FIMC_FMT_YCBCR420 == frame->fmt->color)
359				addr->cr = (u32)(addr->cb + (pix_size >> 2));
360			else /* 422 */
361				addr->cr = (u32)(addr->cb + (pix_size >> 1));
362			break;
363		default:
364			return -EINVAL;
365		}
366	} else if (!frame->fmt->mdataplanes) {
367		if (frame->fmt->memplanes >= 2)
368			addr->cb = vb2_dma_contig_plane_dma_addr(vb, 1);
369
370		if (frame->fmt->memplanes == 3)
371			addr->cr = vb2_dma_contig_plane_dma_addr(vb, 2);
372	}
373
374	dbg("DMA ADDR: y= 0x%X  cb= 0x%X cr= 0x%X ret= %d",
375	    addr->y, addr->cb, addr->cr, ret);
376
377	return ret;
378}
379
380/* Set order for 1 and 2 plane YCBCR 4:2:2 formats. */
381void fimc_set_yuv_order(struct fimc_ctx *ctx)
382{
383	/* The one only mode supported in SoC. */
384	ctx->in_order_2p = FIMC_REG_CIOCTRL_ORDER422_2P_LSB_CRCB;
385	ctx->out_order_2p = FIMC_REG_CIOCTRL_ORDER422_2P_LSB_CRCB;
386
387	/* Set order for 1 plane input formats. */
388	switch (ctx->s_frame.fmt->color) {
389	case FIMC_FMT_YCRYCB422:
390		ctx->in_order_1p = FIMC_REG_MSCTRL_ORDER422_YCRYCB;
391		break;
392	case FIMC_FMT_CBYCRY422:
393		ctx->in_order_1p = FIMC_REG_MSCTRL_ORDER422_CBYCRY;
394		break;
395	case FIMC_FMT_CRYCBY422:
396		ctx->in_order_1p = FIMC_REG_MSCTRL_ORDER422_CRYCBY;
397		break;
398	case FIMC_FMT_YCBYCR422:
399	default:
400		ctx->in_order_1p = FIMC_REG_MSCTRL_ORDER422_YCBYCR;
401		break;
402	}
403	dbg("ctx->in_order_1p= %d", ctx->in_order_1p);
404
405	switch (ctx->d_frame.fmt->color) {
406	case FIMC_FMT_YCRYCB422:
407		ctx->out_order_1p = FIMC_REG_CIOCTRL_ORDER422_YCRYCB;
408		break;
409	case FIMC_FMT_CBYCRY422:
410		ctx->out_order_1p = FIMC_REG_CIOCTRL_ORDER422_CBYCRY;
411		break;
412	case FIMC_FMT_CRYCBY422:
413		ctx->out_order_1p = FIMC_REG_CIOCTRL_ORDER422_CRYCBY;
414		break;
415	case FIMC_FMT_YCBYCR422:
416	default:
417		ctx->out_order_1p = FIMC_REG_CIOCTRL_ORDER422_YCBYCR;
418		break;
419	}
420	dbg("ctx->out_order_1p= %d", ctx->out_order_1p);
421}
422
423void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f)
424{
425	bool pix_hoff = ctx->fimc_dev->drv_data->dma_pix_hoff;
426	u32 i, depth = 0;
427
428	for (i = 0; i < f->fmt->memplanes; i++)
429		depth += f->fmt->depth[i];
430
431	f->dma_offset.y_h = f->offs_h;
432	if (!pix_hoff)
433		f->dma_offset.y_h *= (depth >> 3);
434
435	f->dma_offset.y_v = f->offs_v;
436
437	f->dma_offset.cb_h = f->offs_h;
438	f->dma_offset.cb_v = f->offs_v;
439
440	f->dma_offset.cr_h = f->offs_h;
441	f->dma_offset.cr_v = f->offs_v;
442
443	if (!pix_hoff) {
444		if (f->fmt->colplanes == 3) {
445			f->dma_offset.cb_h >>= 1;
446			f->dma_offset.cr_h >>= 1;
447		}
448		if (f->fmt->color == FIMC_FMT_YCBCR420) {
449			f->dma_offset.cb_v >>= 1;
450			f->dma_offset.cr_v >>= 1;
451		}
452	}
453
454	dbg("in_offset: color= %d, y_h= %d, y_v= %d",
455	    f->fmt->color, f->dma_offset.y_h, f->dma_offset.y_v);
456}
457
458static int fimc_set_color_effect(struct fimc_ctx *ctx, enum v4l2_colorfx colorfx)
459{
460	struct fimc_effect *effect = &ctx->effect;
461
462	switch (colorfx) {
463	case V4L2_COLORFX_NONE:
464		effect->type = FIMC_REG_CIIMGEFF_FIN_BYPASS;
465		break;
466	case V4L2_COLORFX_BW:
467		effect->type = FIMC_REG_CIIMGEFF_FIN_ARBITRARY;
468		effect->pat_cb = 128;
469		effect->pat_cr = 128;
470		break;
471	case V4L2_COLORFX_SEPIA:
472		effect->type = FIMC_REG_CIIMGEFF_FIN_ARBITRARY;
473		effect->pat_cb = 115;
474		effect->pat_cr = 145;
475		break;
476	case V4L2_COLORFX_NEGATIVE:
477		effect->type = FIMC_REG_CIIMGEFF_FIN_NEGATIVE;
478		break;
479	case V4L2_COLORFX_EMBOSS:
480		effect->type = FIMC_REG_CIIMGEFF_FIN_EMBOSSING;
481		break;
482	case V4L2_COLORFX_ART_FREEZE:
483		effect->type = FIMC_REG_CIIMGEFF_FIN_ARTFREEZE;
484		break;
485	case V4L2_COLORFX_SILHOUETTE:
486		effect->type = FIMC_REG_CIIMGEFF_FIN_SILHOUETTE;
487		break;
488	case V4L2_COLORFX_SET_CBCR:
489		effect->type = FIMC_REG_CIIMGEFF_FIN_ARBITRARY;
490		effect->pat_cb = ctx->ctrls.colorfx_cbcr->val >> 8;
491		effect->pat_cr = ctx->ctrls.colorfx_cbcr->val & 0xff;
492		break;
493	default:
494		return -EINVAL;
495	}
496
497	return 0;
498}
499
500/*
501 * V4L2 controls handling
502 */
503#define ctrl_to_ctx(__ctrl) \
504	container_of((__ctrl)->handler, struct fimc_ctx, ctrls.handler)
505
506static int __fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_ctrl *ctrl)
507{
508	struct fimc_dev *fimc = ctx->fimc_dev;
509	const struct fimc_variant *variant = fimc->variant;
510	int ret = 0;
511
512	if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)
513		return 0;
514
515	switch (ctrl->id) {
516	case V4L2_CID_HFLIP:
517		ctx->hflip = ctrl->val;
518		break;
519
520	case V4L2_CID_VFLIP:
521		ctx->vflip = ctrl->val;
522		break;
523
524	case V4L2_CID_ROTATE:
525		if (fimc_capture_pending(fimc)) {
526			ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width,
527					ctx->s_frame.height, ctx->d_frame.width,
528					ctx->d_frame.height, ctrl->val);
529			if (ret)
530				return -EINVAL;
531		}
532		if ((ctrl->val == 90 || ctrl->val == 270) &&
533		    !variant->has_out_rot)
534			return -EINVAL;
535
536		ctx->rotation = ctrl->val;
537		break;
538
539	case V4L2_CID_ALPHA_COMPONENT:
540		ctx->d_frame.alpha = ctrl->val;
541		break;
542
543	case V4L2_CID_COLORFX:
544		ret = fimc_set_color_effect(ctx, ctrl->val);
545		if (ret)
546			return ret;
547		break;
548	}
549
550	ctx->state |= FIMC_PARAMS;
551	set_bit(ST_CAPT_APPLY_CFG, &fimc->state);
552	return 0;
553}
554
555static int fimc_s_ctrl(struct v4l2_ctrl *ctrl)
556{
557	struct fimc_ctx *ctx = ctrl_to_ctx(ctrl);
558	unsigned long flags;
559	int ret;
560
561	spin_lock_irqsave(&ctx->fimc_dev->slock, flags);
562	ret = __fimc_s_ctrl(ctx, ctrl);
563	spin_unlock_irqrestore(&ctx->fimc_dev->slock, flags);
564
565	return ret;
566}
567
568static const struct v4l2_ctrl_ops fimc_ctrl_ops = {
569	.s_ctrl = fimc_s_ctrl,
570};
571
572int fimc_ctrls_create(struct fimc_ctx *ctx)
573{
574	unsigned int max_alpha = fimc_get_alpha_mask(ctx->d_frame.fmt);
575	struct fimc_ctrls *ctrls = &ctx->ctrls;
576	struct v4l2_ctrl_handler *handler = &ctrls->handler;
577
578	if (ctx->ctrls.ready)
579		return 0;
580
581	v4l2_ctrl_handler_init(handler, 6);
582
583	ctrls->rotate = v4l2_ctrl_new_std(handler, &fimc_ctrl_ops,
584					V4L2_CID_ROTATE, 0, 270, 90, 0);
585	ctrls->hflip = v4l2_ctrl_new_std(handler, &fimc_ctrl_ops,
586					V4L2_CID_HFLIP, 0, 1, 1, 0);
587	ctrls->vflip = v4l2_ctrl_new_std(handler, &fimc_ctrl_ops,
588					V4L2_CID_VFLIP, 0, 1, 1, 0);
589
590	if (ctx->fimc_dev->drv_data->alpha_color)
591		ctrls->alpha = v4l2_ctrl_new_std(handler, &fimc_ctrl_ops,
592					V4L2_CID_ALPHA_COMPONENT,
593					0, max_alpha, 1, 0);
594	else
595		ctrls->alpha = NULL;
596
597	ctrls->colorfx = v4l2_ctrl_new_std_menu(handler, &fimc_ctrl_ops,
598				V4L2_CID_COLORFX, V4L2_COLORFX_SET_CBCR,
599				~0x983f, V4L2_COLORFX_NONE);
600
601	ctrls->colorfx_cbcr = v4l2_ctrl_new_std(handler, &fimc_ctrl_ops,
602				V4L2_CID_COLORFX_CBCR, 0, 0xffff, 1, 0);
603
604	ctx->effect.type = FIMC_REG_CIIMGEFF_FIN_BYPASS;
605
606	if (!handler->error) {
607		v4l2_ctrl_cluster(2, &ctrls->colorfx);
608		ctrls->ready = true;
609	}
610
611	return handler->error;
612}
613
614void fimc_ctrls_delete(struct fimc_ctx *ctx)
615{
616	struct fimc_ctrls *ctrls = &ctx->ctrls;
617
618	if (ctrls->ready) {
619		v4l2_ctrl_handler_free(&ctrls->handler);
620		ctrls->ready = false;
621		ctrls->alpha = NULL;
622	}
623}
624
625void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active)
626{
627	unsigned int has_alpha = ctx->d_frame.fmt->flags & FMT_HAS_ALPHA;
628	struct fimc_ctrls *ctrls = &ctx->ctrls;
629
630	if (!ctrls->ready)
631		return;
632
633	mutex_lock(ctrls->handler.lock);
634	v4l2_ctrl_activate(ctrls->rotate, active);
635	v4l2_ctrl_activate(ctrls->hflip, active);
636	v4l2_ctrl_activate(ctrls->vflip, active);
637	v4l2_ctrl_activate(ctrls->colorfx, active);
638	if (ctrls->alpha)
639		v4l2_ctrl_activate(ctrls->alpha, active && has_alpha);
640
641	if (active) {
642		fimc_set_color_effect(ctx, ctrls->colorfx->cur.val);
643		ctx->rotation = ctrls->rotate->val;
644		ctx->hflip    = ctrls->hflip->val;
645		ctx->vflip    = ctrls->vflip->val;
646	} else {
647		ctx->effect.type = FIMC_REG_CIIMGEFF_FIN_BYPASS;
648		ctx->rotation = 0;
649		ctx->hflip    = 0;
650		ctx->vflip    = 0;
651	}
652	mutex_unlock(ctrls->handler.lock);
653}
654
655/* Update maximum value of the alpha color control */
656void fimc_alpha_ctrl_update(struct fimc_ctx *ctx)
657{
658	struct fimc_dev *fimc = ctx->fimc_dev;
659	struct v4l2_ctrl *ctrl = ctx->ctrls.alpha;
660
661	if (ctrl == NULL || !fimc->drv_data->alpha_color)
662		return;
663
664	v4l2_ctrl_lock(ctrl);
665	ctrl->maximum = fimc_get_alpha_mask(ctx->d_frame.fmt);
666
667	if (ctrl->cur.val > ctrl->maximum)
668		ctrl->cur.val = ctrl->maximum;
669
670	v4l2_ctrl_unlock(ctrl);
671}
672
673void __fimc_get_format(const struct fimc_frame *frame, struct v4l2_format *f)
674{
675	struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp;
676	int i;
677
678	pixm->width = frame->o_width;
679	pixm->height = frame->o_height;
680	pixm->field = V4L2_FIELD_NONE;
681	pixm->pixelformat = frame->fmt->fourcc;
682	pixm->colorspace = V4L2_COLORSPACE_JPEG;
683	pixm->num_planes = frame->fmt->memplanes;
684
685	for (i = 0; i < pixm->num_planes; ++i) {
686		pixm->plane_fmt[i].bytesperline = frame->bytesperline[i];
687		pixm->plane_fmt[i].sizeimage = frame->payload[i];
688	}
689}
690
691/**
692 * fimc_adjust_mplane_format - adjust bytesperline/sizeimage for each plane
693 * @fmt: fimc pixel format description (input)
694 * @width: requested pixel width
695 * @height: requested pixel height
696 * @pix: multi-plane format to adjust
697 */
698void fimc_adjust_mplane_format(const struct fimc_fmt *fmt, u32 width, u32 height,
699			       struct v4l2_pix_format_mplane *pix)
700{
701	u32 bytesperline = 0;
702	int i;
703
704	pix->colorspace	= V4L2_COLORSPACE_JPEG;
705	pix->field = V4L2_FIELD_NONE;
706	pix->num_planes = fmt->memplanes;
707	pix->pixelformat = fmt->fourcc;
708	pix->height = height;
709	pix->width = width;
710
711	for (i = 0; i < pix->num_planes; ++i) {
712		struct v4l2_plane_pix_format *plane_fmt = &pix->plane_fmt[i];
713		u32 bpl = plane_fmt->bytesperline;
714		u32 sizeimage;
715
716		if (fmt->colplanes > 1 && (bpl == 0 || bpl < pix->width))
717			bpl = pix->width; /* Planar */
718
719		if (fmt->colplanes == 1 && /* Packed */
720		    (bpl == 0 || ((bpl * 8) / fmt->depth[i]) < pix->width))
721			bpl = (pix->width * fmt->depth[0]) / 8;
722		/*
723		 * Currently bytesperline for each plane is same, except
724		 * V4L2_PIX_FMT_YUV420M format. This calculation may need
725		 * to be changed when other multi-planar formats are added
726		 * to the fimc_formats[] array.
727		 */
728		if (i == 0)
729			bytesperline = bpl;
730		else if (i == 1 && fmt->memplanes == 3)
731			bytesperline /= 2;
732
733		plane_fmt->bytesperline = bytesperline;
734		sizeimage = pix->width * pix->height * fmt->depth[i] / 8;
735
736		/* Ensure full last row for tiled formats */
737		if (tiled_fmt(fmt)) {
738			/* 64 * 32 * plane_fmt->bytesperline / 64 */
739			u32 row_size = plane_fmt->bytesperline * 32;
740
741			sizeimage = roundup(sizeimage, row_size);
742		}
743
744		plane_fmt->sizeimage = max(sizeimage, plane_fmt->sizeimage);
745	}
746}
747
748/**
749 * fimc_find_format - lookup fimc color format by fourcc or media bus format
750 * @pixelformat: fourcc to match, ignored if null
751 * @mbus_code: media bus code to match, ignored if null
752 * @mask: the color flags to match
753 * @index: offset in the fimc_formats array, ignored if negative
754 */
755const struct fimc_fmt *fimc_find_format(const u32 *pixelformat,
756					const u32 *mbus_code,
757					unsigned int mask, int index)
758{
759	const struct fimc_fmt *fmt, *def_fmt = NULL;
760	unsigned int i;
761	int id = 0;
762
763	if (index >= (int)ARRAY_SIZE(fimc_formats))
764		return NULL;
765
766	for (i = 0; i < ARRAY_SIZE(fimc_formats); ++i) {
767		fmt = &fimc_formats[i];
768		if (!(fmt->flags & mask))
769			continue;
770		if (pixelformat && fmt->fourcc == *pixelformat)
771			return fmt;
772		if (mbus_code && fmt->mbus_code == *mbus_code)
773			return fmt;
774		if (index == id)
775			def_fmt = fmt;
776		id++;
777	}
778	return def_fmt;
779}
780
781static void fimc_clk_put(struct fimc_dev *fimc)
782{
783	int i;
784	for (i = 0; i < MAX_FIMC_CLOCKS; i++) {
785		if (IS_ERR(fimc->clock[i]))
786			continue;
787		clk_unprepare(fimc->clock[i]);
788		clk_put(fimc->clock[i]);
789		fimc->clock[i] = ERR_PTR(-EINVAL);
790	}
791}
792
793static int fimc_clk_get(struct fimc_dev *fimc)
794{
795	int i, ret;
796
797	for (i = 0; i < MAX_FIMC_CLOCKS; i++)
798		fimc->clock[i] = ERR_PTR(-EINVAL);
799
800	for (i = 0; i < MAX_FIMC_CLOCKS; i++) {
801		fimc->clock[i] = clk_get(&fimc->pdev->dev, fimc_clocks[i]);
802		if (IS_ERR(fimc->clock[i])) {
803			ret = PTR_ERR(fimc->clock[i]);
804			goto err;
805		}
806		ret = clk_prepare(fimc->clock[i]);
807		if (ret < 0) {
808			clk_put(fimc->clock[i]);
809			fimc->clock[i] = ERR_PTR(-EINVAL);
810			goto err;
811		}
812	}
813	return 0;
814err:
815	fimc_clk_put(fimc);
816	dev_err(&fimc->pdev->dev, "failed to get clock: %s\n",
817		fimc_clocks[i]);
818	return ret;
819}
820
821#ifdef CONFIG_PM
822static int fimc_m2m_suspend(struct fimc_dev *fimc)
823{
824	unsigned long flags;
825	int timeout;
826
827	spin_lock_irqsave(&fimc->slock, flags);
828	if (!fimc_m2m_pending(fimc)) {
829		spin_unlock_irqrestore(&fimc->slock, flags);
830		return 0;
831	}
832	clear_bit(ST_M2M_SUSPENDED, &fimc->state);
833	set_bit(ST_M2M_SUSPENDING, &fimc->state);
834	spin_unlock_irqrestore(&fimc->slock, flags);
835
836	timeout = wait_event_timeout(fimc->irq_queue,
837			     test_bit(ST_M2M_SUSPENDED, &fimc->state),
838			     FIMC_SHUTDOWN_TIMEOUT);
839
840	clear_bit(ST_M2M_SUSPENDING, &fimc->state);
841	return timeout == 0 ? -EAGAIN : 0;
842}
843
844static int fimc_m2m_resume(struct fimc_dev *fimc)
845{
846	struct fimc_ctx *ctx;
847	unsigned long flags;
848
849	spin_lock_irqsave(&fimc->slock, flags);
850	/* Clear for full H/W setup in first run after resume */
851	ctx = fimc->m2m.ctx;
852	fimc->m2m.ctx = NULL;
853	spin_unlock_irqrestore(&fimc->slock, flags);
854
855	if (test_and_clear_bit(ST_M2M_SUSPENDED, &fimc->state))
856		fimc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
857
858	return 0;
859}
860#endif /* CONFIG_PM */
861
862static const struct of_device_id fimc_of_match[];
863
864static int fimc_parse_dt(struct fimc_dev *fimc, u32 *clk_freq)
865{
866	struct device *dev = &fimc->pdev->dev;
867	struct device_node *node = dev->of_node;
868	const struct of_device_id *of_id;
869	struct fimc_variant *v;
870	struct fimc_pix_limit *lim;
871	u32 args[FIMC_PIX_LIMITS_MAX];
872	int ret;
873
874	if (of_property_read_bool(node, "samsung,lcd-wb"))
875		return -ENODEV;
876
877	v = devm_kzalloc(dev, sizeof(*v) + sizeof(*lim), GFP_KERNEL);
878	if (!v)
879		return -ENOMEM;
880
881	of_id = of_match_node(fimc_of_match, node);
882	if (!of_id)
883		return -EINVAL;
884	fimc->drv_data = of_id->data;
885	ret = of_property_read_u32_array(node, "samsung,pix-limits",
886					 args, FIMC_PIX_LIMITS_MAX);
887	if (ret < 0)
888		return ret;
889
890	lim = (struct fimc_pix_limit *)&v[1];
891
892	lim->scaler_en_w = args[0];
893	lim->scaler_dis_w = args[1];
894	lim->out_rot_en_w = args[2];
895	lim->out_rot_dis_w = args[3];
896	v->pix_limit = lim;
897
898	ret = of_property_read_u32_array(node, "samsung,min-pix-sizes",
899								args, 2);
900	v->min_inp_pixsize = ret ? FIMC_DEF_MIN_SIZE : args[0];
901	v->min_out_pixsize = ret ? FIMC_DEF_MIN_SIZE : args[1];
902	ret = of_property_read_u32_array(node, "samsung,min-pix-alignment",
903								args, 2);
904	v->min_vsize_align = ret ? FIMC_DEF_HEIGHT_ALIGN : args[0];
905	v->hor_offs_align = ret ? FIMC_DEF_HOR_OFFS_ALIGN : args[1];
906
907	ret = of_property_read_u32(node, "samsung,rotators", &args[1]);
908	v->has_inp_rot = ret ? 1 : args[1] & 0x01;
909	v->has_out_rot = ret ? 1 : args[1] & 0x10;
910	v->has_mainscaler_ext = of_property_read_bool(node,
911					"samsung,mainscaler-ext");
912
913	v->has_isp_wb = of_property_read_bool(node, "samsung,isp-wb");
914	v->has_cam_if = of_property_read_bool(node, "samsung,cam-if");
915	of_property_read_u32(node, "clock-frequency", clk_freq);
916	fimc->id = of_alias_get_id(node, "fimc");
917
918	fimc->variant = v;
919	return 0;
920}
921
922static int fimc_probe(struct platform_device *pdev)
923{
924	struct device *dev = &pdev->dev;
925	u32 lclk_freq = 0;
926	struct fimc_dev *fimc;
927	int ret = 0;
928	int irq;
929
930	fimc = devm_kzalloc(dev, sizeof(*fimc), GFP_KERNEL);
931	if (!fimc)
932		return -ENOMEM;
933
934	fimc->pdev = pdev;
935
936	if (dev->of_node) {
937		ret = fimc_parse_dt(fimc, &lclk_freq);
938		if (ret < 0)
939			return ret;
940	} else {
941		fimc->drv_data = fimc_get_drvdata(pdev);
942		fimc->id = pdev->id;
943	}
944	if (!fimc->drv_data || fimc->id >= fimc->drv_data->num_entities ||
945	    fimc->id < 0) {
946		dev_err(dev, "Invalid driver data or device id (%d)\n",
947			fimc->id);
948		return -EINVAL;
949	}
950	if (!dev->of_node)
951		fimc->variant = fimc->drv_data->variant[fimc->id];
952
953	init_waitqueue_head(&fimc->irq_queue);
954	spin_lock_init(&fimc->slock);
955	mutex_init(&fimc->lock);
956
957	if (fimc->variant->has_isp_wb) {
958		fimc->sysreg = fimc_get_sysreg_regmap(dev->of_node);
959		if (IS_ERR(fimc->sysreg))
960			return PTR_ERR(fimc->sysreg);
961	}
962
963	fimc->regs = devm_platform_ioremap_resource(pdev, 0);
964	if (IS_ERR(fimc->regs))
965		return PTR_ERR(fimc->regs);
966
967	irq = platform_get_irq(pdev, 0);
968	if (irq < 0)
969		return irq;
970
971	ret = fimc_clk_get(fimc);
972	if (ret)
973		return ret;
974
975	if (lclk_freq == 0)
976		lclk_freq = fimc->drv_data->lclk_frequency;
977
978	ret = clk_set_rate(fimc->clock[CLK_BUS], lclk_freq);
979	if (ret < 0)
980		return ret;
981
982	ret = clk_enable(fimc->clock[CLK_BUS]);
983	if (ret < 0)
984		return ret;
985
986	ret = devm_request_irq(dev, irq, fimc_irq_handler,
987			       0, dev_name(dev), fimc);
988	if (ret < 0) {
989		dev_err(dev, "failed to install irq (%d)\n", ret);
990		goto err_sclk;
991	}
992
993	ret = fimc_initialize_capture_subdev(fimc);
994	if (ret < 0)
995		goto err_sclk;
996
997	platform_set_drvdata(pdev, fimc);
998	pm_runtime_enable(dev);
999
1000	if (!pm_runtime_enabled(dev)) {
1001		ret = clk_enable(fimc->clock[CLK_GATE]);
1002		if (ret < 0)
1003			goto err_sd;
1004	}
1005
1006	vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32));
1007
1008	dev_dbg(dev, "FIMC.%d registered successfully\n", fimc->id);
1009	return 0;
1010
1011err_sd:
1012	fimc_unregister_capture_subdev(fimc);
1013err_sclk:
1014	clk_disable(fimc->clock[CLK_BUS]);
1015	fimc_clk_put(fimc);
1016	return ret;
1017}
1018
1019#ifdef CONFIG_PM
1020static int fimc_runtime_resume(struct device *dev)
1021{
1022	struct fimc_dev *fimc =	dev_get_drvdata(dev);
1023
1024	dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state);
1025
1026	/* Enable clocks and perform basic initialization */
1027	clk_enable(fimc->clock[CLK_GATE]);
1028	fimc_hw_reset(fimc);
1029
1030	/* Resume the capture or mem-to-mem device */
1031	if (fimc_capture_busy(fimc))
1032		return fimc_capture_resume(fimc);
1033
1034	return fimc_m2m_resume(fimc);
1035}
1036
1037static int fimc_runtime_suspend(struct device *dev)
1038{
1039	struct fimc_dev *fimc =	dev_get_drvdata(dev);
1040	int ret = 0;
1041
1042	if (fimc_capture_busy(fimc))
1043		ret = fimc_capture_suspend(fimc);
1044	else
1045		ret = fimc_m2m_suspend(fimc);
1046	if (!ret)
1047		clk_disable(fimc->clock[CLK_GATE]);
1048
1049	dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state);
1050	return ret;
1051}
1052#endif
1053
1054#ifdef CONFIG_PM_SLEEP
1055static int fimc_resume(struct device *dev)
1056{
1057	struct fimc_dev *fimc =	dev_get_drvdata(dev);
1058	unsigned long flags;
1059
1060	dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state);
1061
1062	/* Do not resume if the device was idle before system suspend */
1063	spin_lock_irqsave(&fimc->slock, flags);
1064	if (!test_and_clear_bit(ST_LPM, &fimc->state) ||
1065	    (!fimc_m2m_active(fimc) && !fimc_capture_busy(fimc))) {
1066		spin_unlock_irqrestore(&fimc->slock, flags);
1067		return 0;
1068	}
1069	fimc_hw_reset(fimc);
1070	spin_unlock_irqrestore(&fimc->slock, flags);
1071
1072	if (fimc_capture_busy(fimc))
1073		return fimc_capture_resume(fimc);
1074
1075	return fimc_m2m_resume(fimc);
1076}
1077
1078static int fimc_suspend(struct device *dev)
1079{
1080	struct fimc_dev *fimc =	dev_get_drvdata(dev);
1081
1082	dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state);
1083
1084	if (test_and_set_bit(ST_LPM, &fimc->state))
1085		return 0;
1086	if (fimc_capture_busy(fimc))
1087		return fimc_capture_suspend(fimc);
1088
1089	return fimc_m2m_suspend(fimc);
1090}
1091#endif /* CONFIG_PM_SLEEP */
1092
1093static void fimc_remove(struct platform_device *pdev)
1094{
1095	struct fimc_dev *fimc = platform_get_drvdata(pdev);
1096
1097	pm_runtime_disable(&pdev->dev);
1098	if (!pm_runtime_status_suspended(&pdev->dev))
1099		clk_disable(fimc->clock[CLK_GATE]);
1100	pm_runtime_set_suspended(&pdev->dev);
1101
1102	fimc_unregister_capture_subdev(fimc);
1103	vb2_dma_contig_clear_max_seg_size(&pdev->dev);
1104
1105	clk_disable(fimc->clock[CLK_BUS]);
1106	fimc_clk_put(fimc);
1107
1108	dev_info(&pdev->dev, "driver unloaded\n");
1109}
1110
1111/* S5PV210, S5PC110 */
1112static const struct fimc_drvdata fimc_drvdata_s5pv210 = {
1113	.num_entities	= 3,
1114	.lclk_frequency	= 166000000UL,
1115	.out_buf_count	= 4,
1116	.dma_pix_hoff	= 1,
1117};
1118
1119/* EXYNOS4210, S5PV310, S5PC210 */
1120static const struct fimc_drvdata fimc_drvdata_exynos4210 = {
1121	.num_entities	= 4,
1122	.lclk_frequency = 166000000UL,
1123	.dma_pix_hoff	= 1,
1124	.cistatus2	= 1,
1125	.alpha_color	= 1,
1126	.out_buf_count	= 32,
1127};
1128
1129/* EXYNOS4212, EXYNOS4412 */
1130static const struct fimc_drvdata fimc_drvdata_exynos4x12 = {
1131	.num_entities	= 4,
1132	.lclk_frequency	= 166000000UL,
1133	.dma_pix_hoff	= 1,
1134	.cistatus2	= 1,
1135	.alpha_color	= 1,
1136	.out_buf_count	= 32,
1137};
1138
1139static const struct of_device_id fimc_of_match[] = {
1140	{
1141		.compatible = "samsung,s5pv210-fimc",
1142		.data = &fimc_drvdata_s5pv210,
1143	}, {
1144		.compatible = "samsung,exynos4210-fimc",
1145		.data = &fimc_drvdata_exynos4210,
1146	}, {
1147		.compatible = "samsung,exynos4212-fimc",
1148		.data = &fimc_drvdata_exynos4x12,
1149	},
1150	{ /* sentinel */ },
1151};
1152
1153static const struct dev_pm_ops fimc_pm_ops = {
1154	SET_SYSTEM_SLEEP_PM_OPS(fimc_suspend, fimc_resume)
1155	SET_RUNTIME_PM_OPS(fimc_runtime_suspend, fimc_runtime_resume, NULL)
1156};
1157
1158static struct platform_driver fimc_driver = {
1159	.probe		= fimc_probe,
1160	.remove_new	= fimc_remove,
1161	.driver = {
1162		.of_match_table = fimc_of_match,
1163		.name		= FIMC_DRIVER_NAME,
1164		.pm		= &fimc_pm_ops,
1165	}
1166};
1167
1168int __init fimc_register_driver(void)
1169{
1170	return platform_driver_register(&fimc_driver);
1171}
1172
1173void fimc_unregister_driver(void)
1174{
1175	platform_driver_unregister(&fimc_driver);
1176}
1177