cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

fimc-core.c (28989B)


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