All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
To: Arun Kumar K <arun.kk@samsung.com>
Cc: linux-media@vger.kernel.org, linux-samsung-soc@vger.kernel.org,
	devicetree@vger.kernel.org, s.nawrocki@samsung.com,
	hverkuil@xs4all.nl, a.hajda@samsung.com, sachin.kamat@linaro.org,
	shaik.ameer@samsung.com, kilyeon.im@samsung.com,
	arunkk.samsung@gmail.com
Subject: Re: [PATCH v4 09/13] [media] exynos5-fimc-is: Add the hardware pipeline control
Date: Sat, 10 Aug 2013 01:11:58 +0200	[thread overview]
Message-ID: <5205773E.90603@gmail.com> (raw)
In-Reply-To: <1375866242-18084-10-git-send-email-arun.kk@samsung.com>

On 08/07/2013 11:03 AM, Arun Kumar K wrote:
> This patch adds the crucial hardware pipeline control for the
> fimc-is driver. All the subdev nodes will call this pipeline
> interfaces to reach the hardware. Responsibilities of this module
> involves configuring and maintaining the hardware pipeline involving
> multiple sub-ips like ISP, DRC, Scalers, ODC, 3DNR, FD etc.
>
> Signed-off-by: Arun Kumar K<arun.kk@samsung.com>
> Signed-off-by: Kilyeon Im<kilyeon.im@samsung.com>
> ---
>   .../media/platform/exynos5-is/fimc-is-pipeline.c   | 1691 ++++++++++++++++++++
>   .../media/platform/exynos5-is/fimc-is-pipeline.h   |  127 ++
>   2 files changed, 1818 insertions(+)
>   create mode 100644 drivers/media/platform/exynos5-is/fimc-is-pipeline.c
>   create mode 100644 drivers/media/platform/exynos5-is/fimc-is-pipeline.h
>
> diff --git a/drivers/media/platform/exynos5-is/fimc-is-pipeline.c b/drivers/media/platform/exynos5-is/fimc-is-pipeline.c
> new file mode 100644
> index 0000000..e37ce56
> --- /dev/null
> +++ b/drivers/media/platform/exynos5-is/fimc-is-pipeline.c
> @@ -0,0 +1,1691 @@
> +/*
> + * Samsung EXYNOS5 FIMC-IS (Imaging Subsystem) driver
> +*
> + * Copyright (C) 2013 Samsung Electronics Co., Ltd.
> + * Arun Kumar K<arun.kk@samsung.com>
> + * Kil-yeon Lim<kilyeon.im@samsung.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include "fimc-is.h"
> +#include "fimc-is-pipeline.h"
> +#include "fimc-is-metadata.h"
> +#include "fimc-is-regs.h"
> +#include "fimc-is-cmd.h"
> +#include<media/videobuf2-dma-contig.h>
> +#include<linux/delay.h>
> +
> +/* Default setting values */
> +#define DEFAULT_PREVIEW_STILL_WIDTH		1280
> +#define DEFAULT_PREVIEW_STILL_HEIGHT		720
> +#define DEFAULT_CAPTURE_VIDEO_WIDTH		1920
> +#define DEFAULT_CAPTURE_VIDEO_HEIGHT		1080
> +#define DEFAULT_CAPTURE_STILL_WIDTH		2560
> +#define DEFAULT_CAPTURE_STILL_HEIGHT		1920
> +#define DEFAULT_CAPTURE_STILL_CROP_WIDTH	2560
> +#define DEFAULT_CAPTURE_STILL_CROP_HEIGHT	1440
> +#define DEFAULT_PREVIEW_VIDEO_WIDTH		640
> +#define DEFAULT_PREVIEW_VIDEO_HEIGHT		480
> +
> +/* Init params for pipeline devices */
> +static const struct sensor_param init_sensor_param = {
> +	.frame_rate = {
> +		.frame_rate = 30,
> +	},
> +};
> +
> +static const struct isp_param init_isp_param = {
> +	.control = {
> +		.cmd = CONTROL_COMMAND_START,
> +		.bypass = CONTROL_BYPASS_DISABLE,
> +	},
> +	.otf_input = {
> +		.cmd = OTF_INPUT_COMMAND_DISABLE,
> +		.width = DEFAULT_CAPTURE_STILL_WIDTH,
> +		.height = DEFAULT_CAPTURE_STILL_HEIGHT,
> +		.format = OTF_INPUT_FORMAT_BAYER,
> +		.bitwidth = OTF_INPUT_BIT_WIDTH_10BIT,
> +		.order = OTF_INPUT_ORDER_BAYER_GR_BG,
> +		.frametime_max = 33333,
> +	},
> +	.dma1_input = {
> +		.cmd = DMA_INPUT_COMMAND_DISABLE,
> +	},
> +	.dma2_input = {
> +		.cmd = DMA_INPUT_COMMAND_DISABLE,
> +	},
> +	.aa = {
> +		.cmd = ISP_AA_COMMAND_START,
> +		.target = ISP_AA_TARGET_AF | ISP_AA_TARGET_AE |
> +						ISP_AA_TARGET_AWB,
> +		.mode = ISP_AF_CONTINUOUS,
> +	},
> +	.flash = {
> +		.cmd = ISP_FLASH_COMMAND_DISABLE,
> +		.redeye = ISP_FLASH_REDEYE_DISABLE,
> +	},
> +	.awb = {
> +		.cmd = ISP_AWB_COMMAND_AUTO,
> +	},
> +	.effect = {
> +		.cmd = ISP_IMAGE_EFFECT_DISABLE,
> +	},
> +	.iso = {
> +		.cmd = ISP_ISO_COMMAND_AUTO,
> +	},
> +	.adjust = {
> +		.cmd = ISP_ADJUST_COMMAND_AUTO,
> +	},
> +	.metering = {
> +		.cmd = ISP_METERING_COMMAND_CENTER,
> +		.win_width = DEFAULT_CAPTURE_STILL_WIDTH,
> +		.win_height = DEFAULT_CAPTURE_STILL_HEIGHT,
> +	},
> +	.afc = {
> +		.cmd = ISP_AFC_COMMAND_AUTO,
> +	},
> +	.otf_output = {
> +		.cmd = OTF_OUTPUT_COMMAND_ENABLE,
> +		.width = DEFAULT_CAPTURE_STILL_WIDTH,
> +		.height = DEFAULT_CAPTURE_STILL_HEIGHT,
> +		.format = OTF_OUTPUT_FORMAT_YUV444,
> +		.bitwidth = OTF_OUTPUT_BIT_WIDTH_12BIT,
> +		.order = OTF_OUTPUT_ORDER_BAYER_GR_BG,
> +	},
> +	.dma1_output = {
> +		.cmd = DMA_OUTPUT_COMMAND_DISABLE,
> +		.width = DEFAULT_CAPTURE_STILL_WIDTH,
> +		.height = DEFAULT_CAPTURE_STILL_HEIGHT,
> +		.format = DMA_INPUT_FORMAT_YUV444,
> +		.bitwidth = DMA_INPUT_BIT_WIDTH_8BIT,
> +		.plane = 1,
> +		.order = DMA_INPUT_ORDER_YCBCR,
> +	},
> +	.dma2_output = {
> +		.cmd = DMA_OUTPUT_COMMAND_DISABLE,
> +		.width = DEFAULT_CAPTURE_STILL_WIDTH,
> +		.height = DEFAULT_CAPTURE_STILL_HEIGHT,
> +		.format = DMA_OUTPUT_FORMAT_BAYER,
> +		.bitwidth = DMA_OUTPUT_BIT_WIDTH_12BIT,
> +		.plane = 1,
> +		.order = DMA_OUTPUT_ORDER_GB_BG,
> +		.dma_out_mask = 0xFFFFFFFF,

nit: should be lower case or ~1U.

> +	},
> +};
> +
> +static const struct drc_param init_drc_param = {
> +	.control = {
> +		.cmd = CONTROL_COMMAND_START,
> +		.bypass = CONTROL_BYPASS_ENABLE,
> +	},
> +	.otf_input = {
> +		.cmd = OTF_INPUT_COMMAND_ENABLE,
> +		.width = DEFAULT_CAPTURE_STILL_WIDTH,
> +		.height = DEFAULT_CAPTURE_STILL_HEIGHT,
> +		.format = OTF_INPUT_FORMAT_YUV444,
> +		.bitwidth = OTF_INPUT_BIT_WIDTH_12BIT,
> +		.order = OTF_INPUT_ORDER_BAYER_GR_BG,
> +	},
> +	.dma_input = {
> +		.cmd = DMA_INPUT_COMMAND_DISABLE,
> +		.width = DEFAULT_CAPTURE_STILL_WIDTH,
> +		.height = DEFAULT_CAPTURE_STILL_HEIGHT,
> +		.format = DMA_INPUT_FORMAT_YUV444,
> +		.bitwidth = DMA_INPUT_BIT_WIDTH_8BIT,
> +		.plane = 1,
> +		.order = DMA_INPUT_ORDER_YCBCR,
> +	},
> +	.otf_output = {
> +		.cmd = OTF_OUTPUT_COMMAND_ENABLE,
> +		.width = DEFAULT_CAPTURE_STILL_WIDTH,
> +		.height = DEFAULT_CAPTURE_STILL_HEIGHT,
> +		.format = OTF_OUTPUT_FORMAT_YUV444,
> +		.bitwidth = OTF_INPUT_BIT_WIDTH_8BIT,
> +		.order = OTF_OUTPUT_ORDER_BAYER_GR_BG,
> +	},
> +};
> +
> +static const struct scalerc_param init_scalerc_param = {
> +	.control = {
> +		.cmd = CONTROL_COMMAND_START,
> +		.bypass = CONTROL_BYPASS_ENABLE,
> +	},
> +	.otf_input = {
> +		.cmd = OTF_INPUT_COMMAND_ENABLE,
> +		.width = DEFAULT_CAPTURE_STILL_WIDTH,
> +		.height = DEFAULT_CAPTURE_STILL_HEIGHT,
> +		.format = OTF_INPUT_FORMAT_YUV444,
> +		.bitwidth = OTF_INPUT_BIT_WIDTH_12BIT,
> +		.order = OTF_INPUT_ORDER_BAYER_GR_BG,
> +	},
> +	.input_crop = {
> +		.cmd = OTF_INPUT_COMMAND_ENABLE,
> +		.crop_width = DEFAULT_CAPTURE_STILL_CROP_WIDTH,
> +		.crop_height = DEFAULT_CAPTURE_STILL_CROP_HEIGHT,
> +		.in_width = DEFAULT_CAPTURE_STILL_WIDTH,
> +		.in_height = DEFAULT_CAPTURE_STILL_HEIGHT,
> +		.out_width = DEFAULT_CAPTURE_VIDEO_WIDTH,
> +		.out_height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
> +	},
> +	.output_crop = {
> +		.cmd = SCALER_CROP_COMMAND_DISABLE,
> +		.crop_width = DEFAULT_CAPTURE_STILL_WIDTH,
> +		.crop_height = DEFAULT_CAPTURE_STILL_HEIGHT,
> +		.format = DMA_OUTPUT_FORMAT_YUV420,
> +	},
> +	.otf_output = {
> +		.cmd = OTF_OUTPUT_COMMAND_ENABLE,
> +		.width = DEFAULT_CAPTURE_VIDEO_WIDTH,
> +		.height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
> +		.format = OTF_OUTPUT_FORMAT_YUV444,
> +		.bitwidth = OTF_OUTPUT_BIT_WIDTH_8BIT,
> +		.order = OTF_OUTPUT_ORDER_BAYER_GR_BG,
> +	},
> +	.dma_output = {
> +		.cmd = DMA_OUTPUT_COMMAND_DISABLE,
> +		.width = DEFAULT_CAPTURE_STILL_WIDTH,
> +		.height = DEFAULT_CAPTURE_STILL_HEIGHT,
> +		.format = DMA_OUTPUT_FORMAT_YUV420,
> +		.bitwidth = DMA_OUTPUT_BIT_WIDTH_8BIT,
> +		.plane = 3,
> +		.order = DMA_OUTPUT_ORDER_NONE,
> +		.dma_out_mask = 0xffff,
> +	},
> +};
> +
> +static const struct odc_param init_odc_param = {
> +	.control = {
> +		.cmd = CONTROL_COMMAND_START,
> +		.bypass = CONTROL_BYPASS_ENABLE,
> +		.err = CONTROL_ERROR_NONE,
> +	},
> +	.otf_input = {
> +		.cmd = OTF_INPUT_COMMAND_ENABLE,
> +		.width = DEFAULT_CAPTURE_VIDEO_WIDTH,
> +		.height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
> +		.format = OTF_INPUT_FORMAT_YUV444,
> +		.bitwidth = OTF_INPUT_BIT_WIDTH_8BIT,
> +		.order = OTF_INPUT_ORDER_BAYER_GR_BG,
> +	},
> +	.otf_output = {
> +		.cmd = OTF_OUTPUT_COMMAND_ENABLE,
> +		.width = DEFAULT_CAPTURE_VIDEO_WIDTH,
> +		.height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
> +		.format = OTF_OUTPUT_FORMAT_YUV422,
> +		.bitwidth = OTF_OUTPUT_BIT_WIDTH_8BIT,
> +		.order = OTF_OUTPUT_ORDER_BAYER_GR_BG,
> +	},
> +};
> +
> +static const struct dis_param init_dis_param = {
> +	.control = {
> +		.cmd = CONTROL_COMMAND_START,
> +		.bypass = CONTROL_BYPASS_ENABLE,
> +	},
> +	.otf_input = {
> +		.cmd = OTF_INPUT_COMMAND_ENABLE,
> +		.width = DEFAULT_CAPTURE_VIDEO_WIDTH,
> +		.height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
> +		.format = OTF_INPUT_FORMAT_YUV422,
> +		.bitwidth = OTF_INPUT_BIT_WIDTH_8BIT,
> +		.order = OTF_INPUT_ORDER_BAYER_GR_BG,
> +	},
> +	.otf_output = {
> +		.cmd = OTF_OUTPUT_COMMAND_ENABLE,
> +		.width = DEFAULT_CAPTURE_VIDEO_WIDTH,
> +		.height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
> +		.format = OTF_OUTPUT_FORMAT_YUV422,
> +		.bitwidth = OTF_OUTPUT_BIT_WIDTH_8BIT,
> +		.order = OTF_OUTPUT_ORDER_BAYER_GR_BG,
> +	},
> +};
> +static const struct tdnr_param init_tdnr_param = {
> +	.control = {
> +		.cmd = CONTROL_COMMAND_START,
> +		.bypass = CONTROL_BYPASS_ENABLE,
> +	},
> +	.otf_input = {
> +		.cmd = OTF_INPUT_COMMAND_ENABLE,
> +		.width = DEFAULT_CAPTURE_VIDEO_WIDTH,
> +		.height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
> +		.format = OTF_INPUT_FORMAT_YUV422,
> +		.bitwidth = OTF_INPUT_BIT_WIDTH_8BIT,
> +		.order = OTF_INPUT_ORDER_BAYER_GR_BG,
> +	},
> +	.otf_output = {
> +		.cmd = OTF_OUTPUT_COMMAND_ENABLE,
> +		.width = DEFAULT_CAPTURE_VIDEO_WIDTH,
> +		.height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
> +		.format = OTF_OUTPUT_FORMAT_YUV444,
> +		.bitwidth = OTF_INPUT_BIT_WIDTH_8BIT,
> +		.order = OTF_OUTPUT_ORDER_BAYER_GR_BG,
> +	},
> +	.dma_output = {
> +		.cmd = DMA_OUTPUT_COMMAND_DISABLE,
> +		.width = DEFAULT_CAPTURE_VIDEO_WIDTH,
> +		.height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
> +		.format = DMA_OUTPUT_FORMAT_YUV420,
> +		.bitwidth = DMA_OUTPUT_BIT_WIDTH_8BIT,
> +		.plane = 2,
> +		.order = DMA_OUTPUT_ORDER_CBCR,
> +		.dma_out_mask = 0xffff,
> +	},
> +};
> +
> +static const struct scalerp_param init_scalerp_param = {
> +	.control = {
> +		.cmd = CONTROL_COMMAND_START,
> +		.bypass = CONTROL_BYPASS_ENABLE,
> +	},
> +	.otf_input = {
> +		.cmd = OTF_INPUT_COMMAND_ENABLE,
> +		.width = DEFAULT_CAPTURE_VIDEO_WIDTH,
> +		.height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
> +		.format = OTF_INPUT_FORMAT_YUV444,
> +		.bitwidth = OTF_INPUT_BIT_WIDTH_8BIT,
> +		.order = OTF_INPUT_ORDER_BAYER_GR_BG,
> +	},
> +	.input_crop = {
> +		.cmd = OTF_INPUT_COMMAND_ENABLE,
> +		.crop_width = DEFAULT_CAPTURE_VIDEO_WIDTH,
> +		.crop_height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
> +		.in_width = DEFAULT_CAPTURE_VIDEO_WIDTH,
> +		.in_height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
> +		.out_width = DEFAULT_PREVIEW_STILL_WIDTH,
> +		.out_height = DEFAULT_PREVIEW_STILL_HEIGHT,
> +	},
> +	.output_crop = {
> +		.cmd = SCALER_CROP_COMMAND_DISABLE,
> +		.crop_width = DEFAULT_PREVIEW_STILL_WIDTH,
> +		.crop_height = DEFAULT_PREVIEW_STILL_HEIGHT,
> +		.format = OTF_OUTPUT_FORMAT_YUV420,
> +	},
> +	.otf_output = {
> +		.cmd = OTF_OUTPUT_COMMAND_ENABLE,
> +		.width = DEFAULT_PREVIEW_STILL_WIDTH,
> +		.height = DEFAULT_PREVIEW_STILL_HEIGHT,
> +		.format = OTF_INPUT_FORMAT_YUV444,
> +		.bitwidth = OTF_INPUT_BIT_WIDTH_8BIT,
> +		.order = OTF_OUTPUT_ORDER_BAYER_GR_BG,
> +	},
> +	.dma_output = {
> +		.cmd = DMA_OUTPUT_COMMAND_DISABLE,
> +		.width = DEFAULT_PREVIEW_STILL_WIDTH,
> +		.height = DEFAULT_PREVIEW_STILL_HEIGHT,
> +		.format = OTF_OUTPUT_FORMAT_YUV420,
> +		.bitwidth = DMA_OUTPUT_BIT_WIDTH_8BIT,
> +		.plane = 3,
> +		.order = DMA_OUTPUT_ORDER_NONE,
> +		.dma_out_mask = 0xffff,
> +	},
> +};
> +
> +static const struct fd_param init_fd_param = {
> +	.control = {
> +		.cmd = CONTROL_COMMAND_STOP,
> +		.bypass = CONTROL_BYPASS_DISABLE,
> +	},
> +	.otf_input = {
> +		.cmd = OTF_INPUT_COMMAND_ENABLE,
> +		.width = DEFAULT_PREVIEW_STILL_WIDTH,
> +		.height = DEFAULT_PREVIEW_STILL_HEIGHT,
> +		.format = OTF_INPUT_FORMAT_YUV444,
> +		.bitwidth = OTF_INPUT_BIT_WIDTH_8BIT,
> +		.order = OTF_INPUT_ORDER_BAYER_GR_BG,
> +	},
> +	.dma_input = {
> +		.cmd = DMA_INPUT_COMMAND_DISABLE,
> +	},
> +	.config = {
> +		.cmd = FD_CONFIG_COMMAND_MAXIMUM_NUMBER |
> +			FD_CONFIG_COMMAND_ROLL_ANGLE |
> +			FD_CONFIG_COMMAND_YAW_ANGLE |
> +			FD_CONFIG_COMMAND_SMILE_MODE |
> +			FD_CONFIG_COMMAND_BLINK_MODE |
> +			FD_CONFIG_COMMAND_EYES_DETECT |
> +			FD_CONFIG_COMMAND_MOUTH_DETECT |
> +			FD_CONFIG_COMMAND_ORIENTATION |
> +			FD_CONFIG_COMMAND_ORIENTATION_VALUE,
> +		.max_number = CAMERA2_MAX_FACES,
> +		.roll_angle = FD_CONFIG_ROLL_ANGLE_FULL,
> +		.yaw_angle = FD_CONFIG_YAW_ANGLE_45_90,
> +		.smile_mode = FD_CONFIG_SMILE_MODE_DISABLE,
> +		.blink_mode = FD_CONFIG_BLINK_MODE_DISABLE,
> +		.eye_detect = FD_CONFIG_EYES_DETECT_ENABLE,
> +		.mouth_detect = FD_CONFIG_MOUTH_DETECT_DISABLE,
> +		.orientation = FD_CONFIG_ORIENTATION_DISABLE,
> +	},
> +};
> +
> +static int fimc_is_pipeline_create_subdevs(struct fimc_is_pipeline *pipeline)
> +{
> +	struct fimc_is *is = pipeline->is;
> +	int ret;
> +
> +	/* ISP */
> +	ret = fimc_is_isp_subdev_create(&pipeline->isp,
> +			is->alloc_ctx, pipeline);
> +	if (ret<  0)
> +		return ret;
> +
> +	/* SCC scaler */
> +	ret = fimc_is_scaler_subdev_create(&pipeline->scaler[SCALER_SCC],
> +			SCALER_SCC, is->alloc_ctx, pipeline);
> +	if (ret<  0)
> +		return ret;
> +
> +	/* SCP scaler */
> +	ret = fimc_is_scaler_subdev_create(&pipeline->scaler[SCALER_SCP],
> +			SCALER_SCP, is->alloc_ctx, pipeline);
> +	if (ret<  0)
> +		return ret;
> +
> +	return ret;
> +}
> +
> +static int fimc_is_pipeline_unregister_subdevs(struct fimc_is_pipeline *p)
> +{
> +	fimc_is_isp_subdev_destroy(&p->isp);
> +	fimc_is_scaler_subdev_destroy(&p->scaler[SCALER_SCC]);
> +	fimc_is_scaler_subdev_destroy(&p->scaler[SCALER_SCP]);
> +
> +	return 0;
> +}
> +
> +int fimc_is_pipeline_init(struct fimc_is_pipeline *pipeline,
> +			unsigned int instance, void *is_ctx)
> +{
> +	struct fimc_is *is = is_ctx;
> +	unsigned int i;
> +	int ret;
> +
> +	if (test_bit(PIPELINE_INIT,&pipeline->state))
> +		return -EINVAL;
> +
> +	/* Initialize context variables */
> +	pipeline->instance = instance;
> +	pipeline->is = is;
> +	pipeline->dev =&is->pdev->dev;
> +	pipeline->minfo =&is->minfo;
> +	pipeline->state = 0;
> +	pipeline->force_down = false;
> +	for (i = 0; i<  FIMC_IS_NUM_COMPS; i++)
> +		pipeline->comp_state[i] = 0;
> +
> +	spin_lock_init(&pipeline->slock_buf);
> +	init_waitqueue_head(&pipeline->wait_q);
> +	mutex_init(&pipeline->pipe_lock);
> +	mutex_init(&pipeline->pipe_scl_lock);
> +
> +	ret = fimc_is_pipeline_create_subdevs(pipeline);
> +	if (ret) {
> +		dev_err(pipeline->dev, "Subdev creation failed\n");
> +		return -EINVAL;
> +	}
> +
> +	set_bit(PIPELINE_INIT,&pipeline->state);
> +	return 0;
> +}
> +
> +int fimc_is_pipeline_destroy(struct fimc_is_pipeline *pipeline)
> +{
> +	if (!pipeline)
> +		return -EINVAL;
> +
> +	if (!test_bit(PIPELINE_INIT,&pipeline->state))
> +		return -EINVAL;
> +	return fimc_is_pipeline_unregister_subdevs(pipeline);
> +}
> +
> +static int fimc_is_pipeline_initmem(struct fimc_is_pipeline *pipeline)
> +{
> +	struct fimc_is_meminfo *minfo = pipeline->minfo;
> +	unsigned int offset;
> +
> +	/* Allocate fw memory */
> +	minfo->fw.vaddr = dma_alloc_coherent(pipeline->dev,
> +			FIMC_IS_A5_MEM_SIZE + FIMC_IS_A5_SEN_SIZE,
> +			&minfo->fw.paddr, GFP_KERNEL);
> +	if (minfo->fw.vaddr == NULL)
> +		return -ENOMEM;
> +	minfo->fw.size = FIMC_IS_A5_MEM_SIZE + FIMC_IS_A5_SEN_SIZE;
> +
> +	/* FW memory should be 64MB aligned */
> +	if ((u32)minfo->fw.paddr&  FIMC_IS_FW_BASE_MASK) {
> +		dev_err(pipeline->dev, "FW memory not 64MB aligned.\n");
> +		dma_free_coherent(pipeline->dev, minfo->fw.size,
> +				minfo->fw.vaddr,
> +				minfo->fw.paddr);
> +		return -EIO;
> +	}
> +
> +	/* Assigning memory regions */
> +	offset = FIMC_IS_A5_MEM_SIZE - FIMC_IS_REGION_SIZE;
> +	minfo->region.paddr = minfo->fw.paddr + offset;
> +	minfo->region.vaddr = minfo->fw.vaddr + offset;
> +	pipeline->is_region = (struct is_region *)minfo->region.vaddr;
> +
> +	minfo->shared.paddr = minfo->fw.paddr +
> +		(unsigned int)((void *)&pipeline->is_region->shared[0] -
> +		 minfo->fw.vaddr);
> +	minfo->shared.vaddr = minfo->fw.vaddr +
> +		(unsigned int)((void *)&pipeline->is_region->shared[0] -
> +		 minfo->fw.vaddr);
> +
> +	/* Allocate shot buffer */
> +	minfo->shot.vaddr = dma_alloc_coherent(pipeline->dev,
> +			sizeof(struct camera2_shot),
> +			&minfo->shot.paddr, GFP_KERNEL);
> +	if (minfo->shot.vaddr == NULL) {
> +		dma_free_coherent(pipeline->dev, minfo->fw.size,
> +				minfo->fw.vaddr,
> +				minfo->fw.paddr);
> +		return -ENOMEM;
> +	}
> +	minfo->shot.size = sizeof(struct camera2_shot);
> +
> +	return 0;
> +}
> +
> +static void fimc_is_pipeline_freemem(struct fimc_is_pipeline *pipeline)
> +{
> +	struct fimc_is_meminfo *minfo = pipeline->minfo;
> +	if (minfo->fw.vaddr)
> +		dma_free_coherent(pipeline->dev, minfo->fw.size,
> +				minfo->fw.vaddr,
> +				minfo->fw.paddr);
> +	if (minfo->shot.vaddr)
> +		dma_free_coherent(pipeline->dev, minfo->shot.size,
> +				minfo->shot.vaddr,
> +				minfo->shot.paddr);
> +}
> +
> +static int fimc_is_pipeline_load_firmware(struct fimc_is_pipeline *pipeline)
> +{
> +	const struct firmware *fw_blob;
> +	struct fimc_is *is = pipeline->is;
> +	int ret;
> +
> +	ret = request_firmware(&fw_blob, is->drvdata->fw_name,&is->pdev->dev);
> +	if (ret != 0) {
> +		dev_err(pipeline->dev, "Firmware file not found\n");
> +		return -EINVAL;
> +	}
> +	if (fw_blob->size>  FIMC_IS_A5_MEM_SIZE + FIMC_IS_A5_SEN_SIZE) {
> +		dev_err(pipeline->dev, "Firmware file too big.\n");
> +		release_firmware(fw_blob);
> +		return -ENOMEM;
> +	}
> +
> +	memcpy(pipeline->minfo->fw.vaddr, fw_blob->data, fw_blob->size);
> +	wmb();
> +	release_firmware(fw_blob);
> +
> +	return 0;
> +}
> +
> +static void fimc_is_pipeline_forcedown(struct fimc_is_pipeline *pipeline,
> +		bool on)
> +{
> +	struct fimc_is *is = pipeline->is;
> +	if (on) {
> +		pmu_is_write(0x0, is, PMUREG_ISP_ARM_OPTION);
> +		pmu_is_write(0x1cf82000, is, PMUREG_ISP_LOW_POWER_OFF);
> +		pipeline->force_down = true;
> +	} else {
> +		pmu_is_write(0xffffffff, is, PMUREG_ISP_ARM_OPTION);
> +		pmu_is_write(0x8, is, PMUREG_ISP_LOW_POWER_OFF);
> +		pipeline->force_down = false;
> +	}
> +}
> +
> +static int fimc_is_pipeline_power(struct fimc_is_pipeline *pipeline, int on)
> +{
> +	int ret = 0;
> +	u32 timeout;
> +	struct fimc_is *is = pipeline->is;
> +	struct device *dev =&is->pdev->dev;
> +
> +	if (on) {
> +		/* force poweroff setting */
> +		if (pipeline->force_down)
> +			fimc_is_pipeline_forcedown(pipeline, false);
> +
> +		/* FIMC-IS local power enable */
> +		ret = pm_runtime_get_sync(dev);
> +		if (ret)
> +			return ret;
> +
> +		/* A5 start address setting */
> +		writel(pipeline->minfo->fw.paddr, is->interface.regs + BBOAR);
> +
> +		/* A5 power on*/
> +		pmu_is_write(0x1, is, PMUREG_ISP_ARM_CONFIGURATION);
> +
> +		/* enable A5 */
> +		pmu_is_write(0x00018000, is, PMUREG_ISP_ARM_OPTION);
> +		timeout = 1000;
> +		while ((pmu_is_read(is, PMUREG_ISP_ARM_STATUS)&  0x1) != 0x1) {
> +			if (timeout == 0)
> +				dev_err(pipeline->dev, "A5 power on failed\n");

Shouldn't you return an error here. Now it seems like an potential 
endless loop.	

> +			timeout--;
> +			udelay(1);
> +		}

> +	} else {
> +		/* disable A5 */
> +		pmu_is_write(0x10000, is, PMUREG_ISP_ARM_OPTION);
> +		/* A5 power off*/
> +		pmu_is_write(0x0, is, PMUREG_ISP_ARM_CONFIGURATION);
> +
> +		/* Check A5 power off status register */
> +		timeout = 1000;
> +		while (pmu_is_read(is, PMUREG_ISP_ARM_STATUS)&  0x1) {
> +			if (timeout == 0) {
> +				dev_err(pipeline->dev, "A5 power off failed\n");
> +				fimc_is_pipeline_forcedown(pipeline, true);

Ditto.

> +			}
> +			timeout--;
> +			udelay(1);
> +		}

Might be worth to create a separate function for this polling and

> +		pmu_is_write(0x0, is, PMUREG_CMU_RESET_ISP_SYS_PWR_REG);
> +
> +		/* FIMC-IS local power down */
> +		pm_runtime_put_sync(dev);
> +	}
> +
> +	return ret;
> +}
> +
> +static int fimc_is_pipeline_load_setfile(struct fimc_is_pipeline *pipeline,
> +		unsigned int setfile_addr,
> +		unsigned char *setfile_name)
> +{
> +	struct fimc_is *is = pipeline->is;
> +	const struct firmware *fw_blob;
> +	int ret;
> +
> +	ret = request_firmware(&fw_blob, setfile_name,&is->pdev->dev);
> +	if (ret != 0) {

nit: sometimes those test are "if (ret != 0)" and sometimes "if (ret)".
      Would be nice to use one style consistently. I would recommend to
to use "if (ret < 0)". But that's really a meaningless detail.


> +		dev_err(pipeline->dev, "Setfile %s not found\n", setfile_name);
> +		return -EINVAL;
> +	}
> +
> +	memcpy(pipeline->minfo->fw.vaddr + setfile_addr,
> +			fw_blob->data, fw_blob->size);
> +	wmb();
> +	release_firmware(fw_blob);
> +
> +	return 0;
> +}
> +
> +static int fimc_is_pipeline_setfile(struct fimc_is_pipeline *pipeline)
> +{
> +	struct fimc_is *is = pipeline->is;
> +	struct fimc_is_sensor *sensor = pipeline->sensor;
> +	int ret;
> +	unsigned int setfile_addr;
> +
> +	/* Get setfile addr from HW */
> +	ret = fimc_is_itf_get_setfile_addr(&is->interface,
> +			pipeline->instance,&setfile_addr);
> +	if (ret<  0) {
> +		dev_err(pipeline->dev, "Get setfile addr failed.\n");
> +		return ret;
> +	}
> +
> +	if (!sensor->drvdata->setfile_name)
> +		return -EINVAL;
> +
> +	/* Load setfile */
> +	ret = fimc_is_pipeline_load_setfile(pipeline, setfile_addr,
> +			sensor->drvdata->setfile_name);
> +	if (ret<  0) {
> +		dev_err(pipeline->dev, "Load setfile failed.\n");
> +		return ret;
> +	}
> +
> +	/* Send HW command */
> +	ret = fimc_is_itf_load_setfile(&is->interface, pipeline->instance);
> +	if (ret<  0) {
> +		dev_err(pipeline->dev, "HW Load setfile failed.\n");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int fimc_is_pipeline_isp_setparams(struct fimc_is_pipeline *pipeline,
> +		unsigned int enable)
> +{
> +	struct isp_param *isp_param =&pipeline->is_region->parameter.isp;
> +	struct fimc_is *is = pipeline->is;
> +	unsigned long index[2] = {0};
> +	unsigned int sensor_width, sensor_height, scc_width, scc_height;
> +	unsigned int crop_x, crop_y, isp_width, isp_height;
> +	unsigned int sensor_ratio, output_ratio;
> +	int ret;
> +
> +	/* Crop calculation */
> +	sensor_width = pipeline->sensor->width;
> +	sensor_height = pipeline->sensor->height;
> +	scc_width = pipeline->scaler[SCALER_SCC].width;
> +	scc_height = pipeline->scaler[SCALER_SCC].height;
> +	isp_width = sensor_width;
> +	isp_height = sensor_height;
> +	crop_x = crop_y = 0;
> +
> +	sensor_ratio = sensor_width * 1000 / sensor_height;
> +	output_ratio = scc_width * 1000 / scc_height;
> +
> +	if (sensor_ratio == output_ratio) {
> +		isp_width = sensor_width;
> +		isp_height = sensor_height;
> +	} else if (sensor_ratio<  output_ratio) {
> +		isp_height = (sensor_width * scc_height) / scc_width;
> +		isp_height = ALIGN(isp_height, 2);
> +		crop_y = ((sensor_height - isp_height)>>  1)&  ~1U;
> +	} else {
> +		isp_width = (sensor_height * scc_width) / scc_height;
> +		isp_width = ALIGN(isp_width, 4);
> +		crop_x =  ((sensor_width - isp_width)>>  1)&  ~1U;
> +	}
> +	pipeline->isp_width = isp_width;
> +	pipeline->isp_height = isp_height;
> +
> +	isp_param->otf_output.cmd = OTF_OUTPUT_COMMAND_ENABLE;
> +	isp_param->otf_output.width = pipeline->sensor->width;
> +	isp_param->otf_output.height = pipeline->sensor->height;
> +	isp_param->otf_output.format = OTF_OUTPUT_FORMAT_YUV444;
> +	isp_param->otf_output.bitwidth = OTF_OUTPUT_BIT_WIDTH_12BIT;
> +	isp_param->otf_output.order = OTF_INPUT_ORDER_BAYER_GR_BG;
> +	__set_bit(PARAM_ISP_OTF_OUTPUT, index);
> +
> +	isp_param->dma1_output.cmd = DMA_OUTPUT_COMMAND_DISABLE;
> +	__set_bit(PARAM_ISP_DMA1_OUTPUT, index);
> +
> +	isp_param->dma2_output.cmd = DMA_OUTPUT_COMMAND_DISABLE;
> +	__set_bit(PARAM_ISP_DMA2_OUTPUT, index);
> +
> +	if (enable)
> +		isp_param->control.bypass = CONTROL_BYPASS_DISABLE;
> +	else
> +		isp_param->control.bypass = CONTROL_BYPASS_ENABLE;
> +	isp_param->control.cmd = CONTROL_COMMAND_START;
> +	isp_param->control.run_mode = 1;
> +	__set_bit(PARAM_ISP_CONTROL, index);
> +
> +	isp_param->dma1_input.cmd = DMA_INPUT_COMMAND_BUF_MNGR;
> +	isp_param->dma1_input.width = sensor_width;
> +	isp_param->dma1_input.height = sensor_height;
> +	isp_param->dma1_input.dma_crop_offset_x = crop_x;
> +	isp_param->dma1_input.dma_crop_offset_y = crop_y;
> +	isp_param->dma1_input.dma_crop_width = isp_width;
> +	isp_param->dma1_input.dma_crop_height = isp_height;
> +	isp_param->dma1_input.bayer_crop_offset_x = 0;
> +	isp_param->dma1_input.bayer_crop_offset_y = 0;
> +	isp_param->dma1_input.bayer_crop_width = 0;
> +	isp_param->dma1_input.bayer_crop_height = 0;
> +	isp_param->dma1_input.user_min_frametime = 0;
> +	isp_param->dma1_input.user_max_frametime = 66666;
> +	isp_param->dma1_input.wide_frame_gap = 1;
> +	isp_param->dma1_input.frame_gap = 4096;
> +	isp_param->dma1_input.line_gap = 45;
> +	isp_param->dma1_input.order = DMA_INPUT_ORDER_GR_BG;
> +	isp_param->dma1_input.plane = 1;
> +	isp_param->dma1_input.buffer_number = 1;
> +	isp_param->dma1_input.buffer_address = 0;
> +	isp_param->dma1_input.reserved[1] = 0;
> +	isp_param->dma1_input.reserved[2] = 0;
> +	if (pipeline->isp.fmt->fourcc == V4L2_PIX_FMT_SGRBG8)
> +		isp_param->dma1_input.bitwidth = DMA_INPUT_BIT_WIDTH_8BIT;
> +	else if (pipeline->isp.fmt->fourcc == V4L2_PIX_FMT_SGRBG10)
> +		isp_param->dma1_input.bitwidth = DMA_INPUT_BIT_WIDTH_10BIT;
> +	else
> +		isp_param->dma1_input.bitwidth = DMA_INPUT_BIT_WIDTH_12BIT;
> +	__set_bit(PARAM_ISP_DMA1_INPUT, index);
> +
> +	index[0] = 0xFFFFFFFF;
> +	index[1] = 0xFFFFFFFF;

lower case ?

> +	wmb();
> +	ret = fimc_is_itf_set_param(&is->interface, pipeline->instance,
> +			index[0], index[1]);
> +	if (ret) {
> +		dev_err(pipeline->dev, "%s failed\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	set_bit(COMP_ENABLE,&pipeline->comp_state[IS_ISP]);
> +
> +	return 0;
> +}
> +
> +static int fimc_is_pipeline_drc_setparams(struct fimc_is_pipeline *pipeline,
> +		unsigned int enable)
> +{
> +	struct drc_param *drc_param =&pipeline->is_region->parameter.drc;
> +	struct fimc_is *is = pipeline->is;
> +	int ret;
> +	unsigned long index[2] = {0};
> +
> +	if (enable)
> +		drc_param->control.bypass = CONTROL_BYPASS_DISABLE;
> +	else
> +		drc_param->control.bypass = CONTROL_BYPASS_ENABLE;
> +	__set_bit(PARAM_DRC_CONTROL, index);
> +
> +	drc_param->otf_input.cmd = OTF_INPUT_COMMAND_ENABLE;
> +	drc_param->otf_input.width = pipeline->isp_width;
> +	drc_param->otf_input.height = pipeline->isp_height;
> +	__set_bit(PARAM_DRC_OTF_INPUT, index);
> +
> +	drc_param->otf_output.cmd = OTF_OUTPUT_COMMAND_ENABLE;
> +	drc_param->otf_output.width = pipeline->isp_width;
> +	drc_param->otf_output.height = pipeline->isp_height;
> +	__set_bit(PARAM_DRC_OTF_OUTPUT, index);
> +
> +	wmb();
> +	ret = fimc_is_itf_set_param(&is->interface, pipeline->instance,
> +			index[0], index[1]);
> +	if (ret) {
> +		dev_err(pipeline->dev, "%s failed\n", __func__);
> +		return -EINVAL;
> +	}
> +	if (enable)
> +		set_bit(COMP_ENABLE,&pipeline->comp_state[IS_DRC]);
> +	else
> +		clear_bit(COMP_ENABLE,&pipeline->comp_state[IS_DRC]);
> +
> +	return 0;
> +}
> +
> +static int fimc_is_pipeline_scc_setparams(struct fimc_is_pipeline *pipeline,
> +		unsigned int enable)
> +{
> +	struct scalerc_param *scc_param =
> +		&pipeline->is_region->parameter.scalerc;
> +	struct fimc_is *is = pipeline->is;
> +	int ret;
> +	unsigned long index[2] = {0};
> +	unsigned int scc_width, scc_height;
> +
> +	scc_width = pipeline->scaler[SCALER_SCC].width;
> +	scc_height = pipeline->scaler[SCALER_SCC].height;
> +
> +	if (enable)
> +		scc_param->control.bypass = CONTROL_BYPASS_DISABLE;
> +	else
> +		scc_param->control.bypass = CONTROL_BYPASS_ENABLE;
> +	__set_bit(PARAM_SCALERC_CONTROL, index);
> +
> +	scc_param->otf_input.cmd = OTF_INPUT_COMMAND_ENABLE;
> +	scc_param->otf_input.width = pipeline->isp_width;
> +	scc_param->otf_input.height = pipeline->isp_height;
> +	__set_bit(PARAM_SCALERC_OTF_INPUT, index);
> +
> +	/* SCC OUTPUT */
> +	scc_param->input_crop.cmd = SCALER_CROP_COMMAND_ENABLE;
> +	scc_param->input_crop.pos_x = 0;
> +	scc_param->input_crop.pos_y = 0;
> +	scc_param->input_crop.crop_width = pipeline->isp_width;
> +	scc_param->input_crop.crop_height = pipeline->isp_height;
> +	scc_param->input_crop.in_width = pipeline->isp_width;
> +	scc_param->input_crop.in_height = pipeline->isp_height;
> +	scc_param->input_crop.out_width = scc_width;
> +	scc_param->input_crop.out_height = scc_height;
> +	__set_bit(PARAM_SCALERC_INPUT_CROP, index);
> +
> +	scc_param->output_crop.cmd = SCALER_CROP_COMMAND_DISABLE;
> +	scc_param->output_crop.pos_x = 0;
> +	scc_param->output_crop.pos_y = 0;
> +	scc_param->output_crop.crop_width = scc_width;
> +	scc_param->output_crop.crop_height = scc_height;
> +	__set_bit(PARAM_SCALERC_OUTPUT_CROP, index);
> +
> +	scc_param->otf_output.cmd = OTF_OUTPUT_COMMAND_ENABLE;
> +	scc_param->otf_output.width = scc_width;
> +	scc_param->otf_output.height = scc_height;
> +	__set_bit(PARAM_SCALERC_OTF_OUTPUT, index);
> +
> +	scc_param->dma_output.width = scc_width;
> +	scc_param->dma_output.height = scc_height;
> +	__set_bit(PARAM_SCALERC_DMA_OUTPUT, index);
> +
> +	wmb();
> +	ret = fimc_is_itf_set_param(&is->interface, pipeline->instance,
> +			index[0], index[1]);
> +	if (ret) {
> +		dev_err(pipeline->dev, "%s failed\n", __func__);
> +		return -EINVAL;
> +	}
> +	set_bit(COMP_ENABLE,&pipeline->comp_state[IS_SCC]);
> +	return 0;
> +}
> +
> +static int fimc_is_pipeline_odc_setparams(struct fimc_is_pipeline *pipeline,
> +		unsigned int enable)
> +{
> +	struct odc_param *odc_param =&pipeline->is_region->parameter.odc;
> +	struct fimc_is *is = pipeline->is;
> +	int ret;
> +	unsigned long index[2] = {0};
> +	unsigned int scc_width, scc_height;
> +
> +	scc_width = pipeline->scaler[SCALER_SCC].width;
> +	scc_height = pipeline->scaler[SCALER_SCC].height;
> +
> +	if (enable)
> +		odc_param->control.bypass = CONTROL_BYPASS_DISABLE;
> +	else
> +		odc_param->control.bypass = CONTROL_BYPASS_ENABLE;
> +	__set_bit(PARAM_ODC_CONTROL, index);
> +
> +	odc_param->otf_input.width = scc_width;
> +	odc_param->otf_input.height = scc_height;
> +	__set_bit(PARAM_ODC_OTF_INPUT, index);
> +
> +	odc_param->otf_output.width = scc_width;
> +	odc_param->otf_output.height = scc_height;
> +	__set_bit(PARAM_ODC_OTF_OUTPUT, index);
> +
> +	wmb();
> +	ret = fimc_is_itf_set_param(&is->interface, pipeline->instance,
> +			index[0], index[1]);
> +	if (ret) {
> +		dev_err(pipeline->dev, "%s failed\n", __func__);
> +		return -EINVAL;
> +	}
> +	if (enable)
> +		set_bit(COMP_ENABLE,&pipeline->comp_state[IS_ODC]);
> +	else
> +		clear_bit(COMP_ENABLE,&pipeline->comp_state[IS_ODC]);
> +
> +	return 0;
> +}
> +
> +static int fimc_is_pipeline_dis_setparams(struct fimc_is_pipeline *pipeline,
> +		unsigned int enable)
> +{
> +	struct dis_param *dis_param =&pipeline->is_region->parameter.dis;
> +	struct fimc_is *is = pipeline->is;
> +	int ret;
> +	unsigned long index[2] = {0};
> +	unsigned int scc_width, scc_height;
> +
> +	scc_width = pipeline->scaler[SCALER_SCC].width;
> +	scc_height = pipeline->scaler[SCALER_SCC].height;
> +
> +	if (enable)
> +		dis_param->control.bypass = CONTROL_BYPASS_DISABLE;
> +	else
> +		dis_param->control.bypass = CONTROL_BYPASS_ENABLE;
> +	__set_bit(PARAM_DIS_CONTROL, index);
> +
> +	/* DIS INPUT */
> +	dis_param->otf_input.width = scc_width;
> +	dis_param->otf_input.height = scc_height;
> +	__set_bit(PARAM_DIS_OTF_INPUT, index);
> +
> +	/* DIS OUTPUT */
> +	dis_param->otf_output.width = scc_width;
> +	dis_param->otf_output.height = scc_height;
> +	__set_bit(PARAM_DIS_OTF_OUTPUT, index);
> +
> +	wmb();
> +	ret = fimc_is_itf_set_param(&is->interface, pipeline->instance,
> +			index[0], index[1]);
> +	if (ret) {
> +		dev_err(pipeline->dev, "%s failed\n", __func__);
> +		return -EINVAL;
> +	}
> +	if (enable)
> +		set_bit(COMP_ENABLE,&pipeline->comp_state[IS_DIS]);
> +	else
> +		clear_bit(COMP_ENABLE,&pipeline->comp_state[IS_DIS]);
> +
> +	return 0;
> +}
> +
> +static int fimc_is_pipeline_3dnr_setparams(struct fimc_is_pipeline *pipeline,
> +		unsigned int enable)
> +{
> +	struct tdnr_param *tdnr_param =&pipeline->is_region->parameter.tdnr;
> +	struct fimc_is *is = pipeline->is;
> +	int ret;
> +	unsigned long index[2] = {0};
> +	unsigned int scc_width, scc_height;
> +
> +	scc_width = pipeline->scaler[SCALER_SCC].width;
> +	scc_height = pipeline->scaler[SCALER_SCC].height;
> +
> +	if (enable)
> +		tdnr_param->control.bypass = CONTROL_BYPASS_DISABLE;
> +	else
> +		tdnr_param->control.bypass = CONTROL_BYPASS_ENABLE;
> +	__set_bit(PARAM_TDNR_CONTROL, index);
> +
> +	tdnr_param->otf_input.width = scc_width;
> +	tdnr_param->otf_input.height = scc_height;
> +	__set_bit(PARAM_TDNR_OTF_INPUT, index);
> +
> +	tdnr_param->dma_output.width = scc_width;
> +	tdnr_param->dma_output.height = scc_height;
> +	__set_bit(PARAM_TDNR_DMA_OUTPUT, index);
> +
> +	tdnr_param->otf_output.width = scc_width;
> +	tdnr_param->otf_output.height = scc_height;
> +	__set_bit(PARAM_TDNR_OTF_OUTPUT, index);
> +
> +	wmb();
> +	ret = fimc_is_itf_set_param(&is->interface, pipeline->instance,
> +			index[0], index[1]);
> +	if (ret) {
> +		dev_err(pipeline->dev, "%s failed\n", __func__);
> +		return -EINVAL;
> +	}
> +	if (enable)
> +		set_bit(COMP_ENABLE,&pipeline->comp_state[IS_TDNR]);
> +	else
> +		clear_bit(COMP_ENABLE,&pipeline->comp_state[IS_TDNR]);
> +
> +	return 0;
> +}
> +
> +static int fimc_is_pipeline_scp_setparams(struct fimc_is_pipeline *pipeline,
> +		unsigned int enable)
> +{
> +	struct scalerp_param *scp_param =
> +		&pipeline->is_region->parameter.scalerp;
> +	struct fimc_is *is = pipeline->is;
> +	int ret;
> +	unsigned long index[2] = {0};
> +	unsigned int scc_width, scc_height;
> +	unsigned int scp_width, scp_height;
> +
> +	scc_width = pipeline->scaler[SCALER_SCC].width;
> +	scc_height = pipeline->scaler[SCALER_SCC].height;
> +	scp_width = pipeline->scaler[SCALER_SCP].width;
> +	scp_height = pipeline->scaler[SCALER_SCP].height;
> +
> +	if (enable)
> +		scp_param->control.bypass = CONTROL_BYPASS_DISABLE;
> +	else
> +		scp_param->control.bypass = CONTROL_BYPASS_ENABLE;
> +	__set_bit(PARAM_SCALERP_CONTROL, index);
> +
> +	/* SCP Input */
> +	scp_param->otf_input.width = scc_width;
> +	scp_param->otf_input.height = scc_height;
> +	__set_bit(PARAM_SCALERP_OTF_INPUT, index);
> +
> +	/* SCP Output */
> +	scp_param->input_crop.cmd = SCALER_CROP_COMMAND_ENABLE;
> +	scp_param->input_crop.pos_x = 0;
> +	scp_param->input_crop.pos_y = 0;
> +	scp_param->input_crop.crop_width = scc_width;
> +	scp_param->input_crop.crop_height = scc_height;
> +	scp_param->input_crop.in_width = scc_width;
> +	scp_param->input_crop.in_height = scc_height;
> +	scp_param->input_crop.out_width = scp_width;
> +	scp_param->input_crop.out_height = scp_height;
> +	__set_bit(PARAM_SCALERP_INPUT_CROP, index);
> +
> +	scp_param->output_crop.cmd = SCALER_CROP_COMMAND_DISABLE;
> +	__set_bit(PARAM_SCALERP_OUTPUT_CROP, index);
> +
> +	scp_param->otf_output.width = scp_width;
> +	scp_param->otf_output.height = scp_height;
> +	__set_bit(PARAM_SCALERP_OTF_OUTPUT, index);
> +
> +	scp_param->dma_output.width = scp_width;
> +	scp_param->dma_output.height = scp_height;
> +	__set_bit(PARAM_SCALERP_DMA_OUTPUT, index);
> +
> +	wmb();
> +	ret = fimc_is_itf_set_param(&is->interface, pipeline->instance,
> +			index[0], index[1]);
> +	if (ret) {
> +		dev_err(pipeline->dev, "%s failed\n", __func__);
> +		return -EINVAL;
> +	}
> +	set_bit(COMP_ENABLE,&pipeline->comp_state[IS_SCP]);
> +
> +	return 0;
> +}
> +
> +static int fimc_is_pipeline_fd_setparams(struct fimc_is_pipeline *pipeline,
> +		unsigned int enable)
> +{
> +	struct fd_param *fd_param =&pipeline->is_region->parameter.fd;
> +	struct fimc_is *is = pipeline->is;
> +	int ret;
> +	unsigned long index[2] = {0};
> +
> +	if (enable)
> +		fd_param->control.bypass = CONTROL_BYPASS_DISABLE;
> +	else
> +		fd_param->control.bypass = CONTROL_BYPASS_ENABLE;
> +	__set_bit(PARAM_FD_CONTROL, index);
> +
> +	fd_param->otf_input.width = pipeline->scaler[SCALER_SCP].width;
> +	fd_param->otf_input.height = pipeline->scaler[SCALER_SCP].height;
> +	__set_bit(PARAM_FD_OTF_INPUT, index);
> +
> +	wmb();
> +	ret = fimc_is_itf_set_param(&is->interface, pipeline->instance,
> +			index[0], index[1]);
> +	if (ret) {
> +		dev_err(pipeline->dev, "%s failed\n", __func__);
> +		return -EINVAL;
> +	}
> +	if (enable)
> +		set_bit(COMP_ENABLE,&pipeline->comp_state[IS_FD]);
> +	else
> +		clear_bit(COMP_ENABLE,&pipeline->comp_state[IS_FD]);
> +
> +	return 0;
> +}
> +
> +void fimc_is_pipeline_buf_lock(struct fimc_is_pipeline *pipeline)
> +{
> +	spin_lock_irqsave(&pipeline->slock_buf, pipeline->slock_flags);
> +}
> +
> +void fimc_is_pipeline_buf_unlock(struct fimc_is_pipeline *pipeline)
> +{
> +	spin_unlock_irqrestore(&pipeline->slock_buf, pipeline->slock_flags);
> +}
> +
> +int fimc_is_pipeline_setparams(struct fimc_is_pipeline *pipeline)
> +{
> +	int ret;
> +
> +	/* Enabling basic components in pipeline */
> +	ret = fimc_is_pipeline_isp_setparams(pipeline, true);
> +	if (!ret)
> +		ret = fimc_is_pipeline_drc_setparams(pipeline, false);
> +	if (!ret)
> +		ret = fimc_is_pipeline_scc_setparams(pipeline, true);
> +	if (!ret)
> +		ret = fimc_is_pipeline_odc_setparams(pipeline, false);
> +	if (!ret)
> +		ret = fimc_is_pipeline_dis_setparams(pipeline, false);
> +	if (!ret)
> +		ret = fimc_is_pipeline_3dnr_setparams(pipeline, false);
> +	if (!ret)
> +		ret = fimc_is_pipeline_scp_setparams(pipeline, true);
> +	if (!ret)
> +		ret = fimc_is_pipeline_fd_setparams(pipeline, false);
> +	if (ret)
> +		dev_err(pipeline->dev, "Pipeline setparam failed.\n");
> +
> +	return ret;
> +}
> +
> +int fimc_is_pipeline_scaler_start(struct fimc_is_pipeline *pipeline,
> +		enum fimc_is_scaler_id scaler_id,
> +		unsigned int num_bufs,
> +		unsigned int num_planes)
> +{
> +	struct fimc_is *is = pipeline->is;
> +	struct scalerp_param *scp_param =
> +		&pipeline->is_region->parameter.scalerp;
> +	struct scalerc_param *scc_param =
> +		&pipeline->is_region->parameter.scalerc;
> +	struct param_dma_output *dma_output;
> +	const struct fimc_is_fmt *fmt;
> +	unsigned int region_index;
> +	unsigned long *comp_state;
> +	int ret;
> +	unsigned int pipe_start_flag = 0;
> +	unsigned int i, buf_mask = 0;
> +	unsigned long index[2] = {0};
> +
> +	if (!test_bit(PIPELINE_OPEN,&pipeline->state)) {
> +		dev_err(pipeline->dev, "Pipeline not opened.\n");
> +		return -EINVAL;
> +	}
> +
> +	mutex_lock(&pipeline->pipe_scl_lock);
> +
> +	if (test_bit(PIPELINE_START,&pipeline->state)) {
> +		/*
> +		 * Pipeline is started.
> +		 * Stop it now to set params and start again
> +		 */
> +		ret = fimc_is_pipeline_stop(pipeline);
> +		if (ret) {
> +			dev_err(pipeline->dev, "Not able to stop pipeline\n");
> +			goto exit;
> +		}
> +		pipe_start_flag = 1;
> +	}
> +
> +	if (scaler_id == SCALER_SCC) {
> +		dma_output =&scc_param->dma_output;
> +		region_index = FIMC_IS_SCC_REGION_INDEX;
> +		comp_state =&pipeline->comp_state[IS_SCC];
> +		fmt = pipeline->scaler[SCALER_SCC].fmt;
> +		__set_bit(PARAM_SCALERC_DMA_OUTPUT, index);
> +	} else {
> +		dma_output =&scp_param->dma_output;
> +		comp_state =&pipeline->comp_state[IS_SCP];
> +		fmt = pipeline->scaler[SCALER_SCC].fmt;
> +		region_index = FIMC_IS_SCP_REGION_INDEX;
> +		__set_bit(PARAM_SCALERP_DMA_OUTPUT, index);
> +	}
> +
> +	for (i = 0; i<  num_bufs; i++)
> +		buf_mask |= BIT(i);
> +
> +	dma_output->cmd = DMA_OUTPUT_COMMAND_ENABLE;
> +	dma_output->dma_out_mask = buf_mask;
> +	dma_output->buffer_number = num_bufs;
> +	dma_output->plane = num_planes;
> +	if ((fmt->fourcc == V4L2_PIX_FMT_YUV420M) ||
> +			(fmt->fourcc == V4L2_PIX_FMT_NV12M))
> +		dma_output->format = DMA_OUTPUT_FORMAT_YUV420;
> +	else if (fmt->fourcc == V4L2_PIX_FMT_NV16)
> +		dma_output->format = DMA_OUTPUT_FORMAT_YUV422;
> +
> +	dma_output->buffer_address = pipeline->minfo->shared.paddr +
> +				region_index * sizeof(unsigned int);
> +
> +	ret = fimc_is_itf_set_param(&is->interface, pipeline->instance,
> +			index[0], index[1]);
> +	if (ret)
> +		dev_err(pipeline->dev, "fimc_is_itf_set_param is fail\n");
> +	else
> +		set_bit(COMP_START, comp_state);
> +
> +	if (pipe_start_flag) {
> +		ret = fimc_is_pipeline_start(pipeline);
> +		if (ret) {
> +			dev_err(pipeline->dev,
> +					"Not able to start pipeline back\n");
> +			goto exit;
> +		}
> +	}
> +
> +exit:
> +	mutex_unlock(&pipeline->pipe_scl_lock);
> +	return ret;
> +}
> +
> +int fimc_is_pipeline_scaler_stop(struct fimc_is_pipeline *pipeline,
> +		enum fimc_is_scaler_id scaler_id)
> +{
> +	struct fimc_is *is = pipeline->is;
> +	struct scalerp_param *scp_param =
> +		&pipeline->is_region->parameter.scalerp;
> +	struct scalerc_param *scc_param =
> +		&pipeline->is_region->parameter.scalerc;
> +	struct param_dma_output *dma_output;
> +	unsigned int pipe_start_flag = 0;
> +	unsigned long index[2] = {0};
> +	unsigned long *comp_state;
> +	int ret;
> +
> +	if (!test_bit(PIPELINE_OPEN,&pipeline->state))
> +		return -EINVAL;
> +
> +	mutex_lock(&pipeline->pipe_scl_lock);
> +
> +	if (test_bit(PIPELINE_START,&pipeline->state)) {
> +		/*
> +		 * Pipeline is started.
> +		 * Stop it now to set params and start again
> +		 */
> +		ret = fimc_is_pipeline_stop(pipeline);
> +		if (ret) {
> +			dev_err(pipeline->dev, "Not able to stop pipeline\n");
> +			goto exit;
> +		}
> +		pipe_start_flag = 1;
> +	}
> +
> +	comp_state = (scaler_id == SCALER_SCC) ?
> +		&pipeline->comp_state[IS_SCC] :&pipeline->comp_state[IS_SCP];
> +
> +	if (!test_bit(COMP_START, comp_state)) {
> +		ret = 0;
> +		goto exit;
> +	}
> +
> +	if (scaler_id == SCALER_SCC) {
> +		dma_output =&scc_param->dma_output;
> +		__set_bit(PARAM_SCALERC_DMA_OUTPUT, index);
> +	} else {
> +		dma_output =&scp_param->dma_output;
> +		__set_bit(PARAM_SCALERP_DMA_OUTPUT, index);
> +	}
> +	dma_output->cmd = DMA_OUTPUT_COMMAND_DISABLE;
> +
> +	ret = fimc_is_itf_set_param(&is->interface, pipeline->instance,
> +			index[0], index[1]);
> +	if (ret<  0)
> +		dev_err(pipeline->dev, "fimc_is_itf_set_param is fail\n");
> +	else
> +		clear_bit(COMP_START, comp_state);
> +
> +	if (pipe_start_flag) {
> +		ret = fimc_is_pipeline_start(pipeline);
> +		if (ret) {
> +			dev_err(pipeline->dev,
> +					"Not able to start pipeline back\n");
> +			return -EINVAL;

Shouldn't this be	ret = -EINVAL; ?

> +		}
> +	}
> +
> +exit:
> +	mutex_unlock(&pipeline->pipe_scl_lock);
> +	return ret;
> +}
> +
> +void fimc_is_pipeline_config_shot(struct fimc_is_pipeline *pipeline)
> +{
> +	struct camera2_shot *shot =
> +		(struct camera2_shot *)pipeline->minfo->shot.vaddr;
> +
> +	shot->magicnumber = FIMC_IS_MAGIC_NUMBER;
> +
> +	shot->ctl.aa.mode = AA_CONTROL_AUTO;
> +	shot->ctl.aa.ae_mode = AA_AEMODE_ON;
> +}
> +
> +int fimc_is_pipeline_shot(struct fimc_is_pipeline *pipeline)
> +{
> +	struct fimc_is *is = pipeline->is;
> +	int ret;
> +	unsigned int rcount, i;
> +	struct camera2_shot *shot = pipeline->minfo->shot.vaddr;
> +	struct fimc_is_buf *scc_buf, *scp_buf, *bayer_buf;
> +
> +	if (!test_bit(PIPELINE_START,&pipeline->state))
> +		return -EINVAL;
> +
> +	if (test_bit(PIPELINE_RUN,&pipeline->state))
> +		return -EBUSY;
> +
> +	fimc_is_pipeline_buf_lock(pipeline);
> +
> +	if (list_empty(&pipeline->isp.wait_queue)) {
> +		/* No more bayer buffers */
> +		wake_up(&pipeline->wait_q);
> +		fimc_is_pipeline_buf_unlock(pipeline);
> +		return 0;
> +	}
> +
> +	set_bit(PIPELINE_RUN,&pipeline->state);
> +
> +	/* Get bayer input buffer */
> +	bayer_buf = fimc_is_isp_wait_queue_get(&pipeline->isp);
> +	if (!bayer_buf) {
> +		fimc_is_pipeline_buf_unlock(pipeline);
> +		goto err_exit;
> +	}
> +	fimc_is_isp_run_queue_add(&pipeline->isp, bayer_buf);
> +
> +	/* Get SCC buffer */
> +	if (test_bit(COMP_START,&pipeline->comp_state[IS_SCC])&&
> +		!list_empty(&pipeline->scaler[SCALER_SCC].wait_queue)) {
> +		scc_buf = fimc_is_scaler_wait_queue_get(
> +				&pipeline->scaler[SCALER_SCC]);
> +		if (scc_buf) {
> +			fimc_is_scaler_run_queue_add(
> +					&pipeline->scaler[SCALER_SCC],
> +					scc_buf);
> +			for (i = 0; i<  3; i++)
> +				shot->uctl.scaler_ud.scc_target_address[i] =
> +							scc_buf->paddr[i];
> +			set_bit(COMP_RUN,&pipeline->comp_state[IS_SCC]);
> +		}
> +	} else {
> +		dev_dbg(pipeline->dev, "No SCC buffer available\n");
> +		for (i = 0; i<  3; i++)
> +			shot->uctl.scaler_ud.scc_target_address[i] = 0;
> +	}
> +
> +	/* Get SCP buffer */
> +	if (test_bit(COMP_START,&pipeline->comp_state[IS_SCP])&&
> +		!list_empty(&pipeline->scaler[SCALER_SCP].wait_queue)) {
> +		scp_buf = fimc_is_scaler_wait_queue_get(
> +				&pipeline->scaler[SCALER_SCP]);
> +		if (scp_buf) {
> +			fimc_is_scaler_run_queue_add(
> +					&pipeline->scaler[SCALER_SCP],
> +					scp_buf);
> +			for (i = 0; i<  3; i++)
> +				shot->uctl.scaler_ud.scp_target_address[i] =
> +							scp_buf->paddr[i];
> +			set_bit(COMP_RUN,&pipeline->comp_state[IS_SCP]);
> +		}
> +	} else {
> +		dev_dbg(pipeline->dev, "No SCP buffer available\n");
> +		for (i = 0; i<  3; i++)
> +			shot->uctl.scaler_ud.scp_target_address[i] = 0;
> +	}
> +	fimc_is_pipeline_buf_unlock(pipeline);
> +
> +	/* Send shot command */
> +	pipeline->fcount++;
> +	rcount = pipeline->fcount;
> +	shot->ctl.request.framecount = pipeline->fcount;
> +	dev_dbg(pipeline->dev,
> +		"Shot command fcount : %d, Bayer addr : 0x%08x\n",
> +		pipeline->fcount, bayer_buf->paddr[0]);
> +	ret = fimc_is_itf_shot_nblk(&is->interface, pipeline->instance,
> +			bayer_buf->paddr[0],
> +			pipeline->minfo->shot.paddr,
> +			pipeline->fcount,
> +			rcount);
> +	if (ret<  0) {
> +		dev_err(pipeline->dev, "Shot command failed.\n");
> +		goto err_exit;
> +	}
> +	return 0;
> +
> +err_exit:
> +	clear_bit(PIPELINE_RUN,&pipeline->state);
> +	clear_bit(COMP_RUN,&pipeline->comp_state[IS_SCC]);
> +	clear_bit(COMP_RUN,&pipeline->comp_state[IS_SCP]);
> +	return -EINVAL;
> +}
> +
> +int fimc_is_pipeline_start(struct fimc_is_pipeline *pipeline)
> +{
> +	int ret = 0;
> +	struct fimc_is *is = pipeline->is;
> +
> +	/* Check if open or not */
> +	if (!test_bit(PIPELINE_OPEN,&pipeline->state)) {
> +		dev_err(pipeline->dev, "Pipeline not open.\n");
> +		return -EINVAL;
> +	}
> +
> +	mutex_lock(&pipeline->pipe_lock);
> +
> +	/* Check if already started */
> +	if (test_bit(PIPELINE_START,&pipeline->state))
> +		goto err_exit;
> +
> +	/* Set pipeline component params */
> +	ret = fimc_is_pipeline_setparams(pipeline);
> +	if (ret<  0) {
> +		dev_err(pipeline->dev, "Set params failed\n");
> +		goto err_exit;
> +	}
> +
> +	/* Send preview still command */
> +	ret = fimc_is_itf_preview_still(&is->interface, pipeline->instance);
> +	if (ret) {
> +		dev_err(pipeline->dev, "Preview still command failed\n");
> +		goto err_exit;
> +	}
> +
> +	/* Confiture shot memory to A5 */
> +	ret = fimc_is_itf_cfg_mem(&is->interface, pipeline->instance,
> +			pipeline->minfo->shot.paddr,
> +			sizeof(struct camera2_shot));
> +	if (ret<  0) {
> +		dev_err(pipeline->dev, "Config A5 mem failed.\n");
> +		goto err_exit;
> +	}
> +
> +	/* Set shot params */
> +	fimc_is_pipeline_config_shot(pipeline);
> +
> +	/* Process ON command */
> +	ret = fimc_is_itf_process_on(&is->interface, pipeline->instance);
> +	if (ret) {
> +		dev_err(pipeline->dev, "Process on failed\n");
> +		goto err_exit;
> +	}
> +
> +	/* Stream ON */
> +	ret = fimc_is_itf_stream_on(&is->interface, pipeline->instance);
> +	if (ret<  0) {
> +		dev_err(pipeline->dev, "Stream On failed.\n");
> +		goto err_exit;
> +	}
> +
> +	/* Set state to START */
> +	set_bit(PIPELINE_START,&pipeline->state);
> +
> +	mutex_unlock(&pipeline->pipe_lock);
> +	return 0;
> +
> +err_exit:
> +	mutex_unlock(&pipeline->pipe_lock);
> +	return ret;
> +}
> +
> +int fimc_is_pipeline_stop(struct fimc_is_pipeline *pipeline)
> +{
> +	int ret;
> +	struct fimc_is *is = pipeline->is;
> +
> +	mutex_lock(&pipeline->pipe_lock);
> +
> +	/* Check if started */
> +	if (!test_bit(PIPELINE_OPEN,&pipeline->state) ||
> +		!test_bit(PIPELINE_START,&pipeline->state)) {
> +		ret = -EINVAL;
> +		goto err_exit;
> +	}
> +
> +	/* Wait if any operation is in progress */
> +	ret = wait_event_timeout(pipeline->wait_q,
> +			!test_bit(PIPELINE_RUN,&pipeline->state),
> +			FIMC_IS_COMMAND_TIMEOUT);
> +	if (!ret) {
> +		dev_err(pipeline->dev, "Pipeline timeout");
> +		ret = -EBUSY;
> +		goto err_exit;
> +	}
> +
> +	/* Wait for scaler operations if any to complete */
> +	ret = wait_event_timeout(pipeline->scaler[SCALER_SCC].event_q,
> +			!test_bit(COMP_RUN,&pipeline->comp_state[IS_SCC]),
> +			FIMC_IS_COMMAND_TIMEOUT);
> +	if (!ret) {
> +		dev_err(pipeline->dev, "SCC timeout");
> +		ret = -EBUSY;
> +		goto err_exit;
> +	}
> +	ret = wait_event_timeout(pipeline->scaler[SCALER_SCP].event_q,
> +			!test_bit(COMP_RUN,&pipeline->comp_state[IS_SCP]),
> +			FIMC_IS_COMMAND_TIMEOUT);
> +	if (!ret) {
> +		dev_err(pipeline->dev, "SCP timeout");
> +		ret = -EBUSY;
> +		goto err_exit;
> +	}
> +
> +

nit: superfluous empty line

> +	/* Process OFF */
> +	ret = fimc_is_itf_process_off(&is->interface, pipeline->instance);
> +	if (ret) {
> +		dev_err(pipeline->dev, "Process off failed\n");
> +		ret = -EINVAL;
> +		goto err_exit;
> +	}
> +
> +	/* Stream OFF */
> +	ret = fimc_is_itf_stream_off(&is->interface, pipeline->instance);
> +	if (ret<  0) {
> +		dev_err(pipeline->dev, "Stream Off failed.\n");
> +		ret = -EINVAL;
> +		goto err_exit;
> +	}
> +
> +	/* Clear state */
> +	clear_bit(PIPELINE_START,&pipeline->state);
> +
> +err_exit:
> +	mutex_unlock(&pipeline->pipe_lock);
> +	return ret;
> +}
> +
> +int fimc_is_pipeline_open(struct fimc_is_pipeline *pipeline,
> +			struct fimc_is_sensor *sensor)
> +{
> +	struct fimc_is *is = pipeline->is;
> +	struct is_region *region;
> +	int ret;
> +
> +	if (!sensor)
> +		return -EINVAL;
> +
> +	mutex_lock(&pipeline->pipe_lock);
> +
> +	if (test_bit(PIPELINE_OPEN,&pipeline->state)) {
> +		dev_err(pipeline->dev, "Pipeline already open.\n");
> +		ret = -EINVAL;
> +		goto err_exit;
> +	}
> +
> +	pipeline->fcount = 0;
> +	pipeline->sensor = sensor;
> +
> +	if (is->num_pipelines == 0) {
> +		/* Init memory */
> +		ret = fimc_is_pipeline_initmem(pipeline);
> +		if (ret<  0) {
> +			dev_err(pipeline->dev, "Pipeline memory init failed.\n");

nit: dots in the log messages probably could be ommited

> +			goto err_exit;
> +		}
> +
> +		/* Load firmware */
> +		ret = fimc_is_pipeline_load_firmware(pipeline);
> +		if (ret<  0) {
> +			dev_err(pipeline->dev, "Firmware load failed.\n");

> +			goto err_fw;
> +		}
> +
> +		/* Power ON */
> +		ret = fimc_is_pipeline_power(pipeline, 1);
> +		if (ret<  0) {
> +			dev_err(pipeline->dev, "A5 power on failed.\n");

> +			goto err_fw;
> +		}
> +
> +		/* Wait for FW Init to complete */
> +		ret = fimc_is_itf_wait_init_state(&is->interface);
> +		if (ret<  0) {
> +			dev_err(pipeline->dev, "FW init failed.\n");

> +			goto err_fw;
> +		}
> +	}
> +
> +	/* Open Sensor */
> +	region = pipeline->is_region;
> +	ret = fimc_is_itf_open_sensor(&is->interface,
> +			pipeline->instance,
> +			sensor->drvdata->id,
> +			sensor->i2c_bus,
> +			pipeline->minfo->shared.paddr);
> +	if (ret<  0) {
> +		dev_err(pipeline->dev, "Open sensor failed\n");
> +		goto err_exit;
> +	}
> +
> +	if (is->num_pipelines == 0) {
> +		/* Copy init params to FW region */
> +		memset(&region->parameter, 0x0, sizeof(struct is_param_region));
> +
> +		memcpy(&region->parameter.sensor,&init_sensor_param,
> +				sizeof(struct sensor_param));
> +		memcpy(&region->parameter.isp,&init_isp_param,
> +				sizeof(struct isp_param));
> +		memcpy(&region->parameter.drc,&init_drc_param,
> +				sizeof(struct drc_param));
> +		memcpy(&region->parameter.scalerc,&init_scalerc_param,
> +				sizeof(struct scalerc_param));
> +		memcpy(&region->parameter.odc,&init_odc_param,
> +				sizeof(struct odc_param));
> +		memcpy(&region->parameter.dis,&init_dis_param,
> +				sizeof(struct dis_param));
> +		memcpy(&region->parameter.tdnr,&init_tdnr_param,
> +				sizeof(struct tdnr_param));
> +		memcpy(&region->parameter.scalerp,&init_scalerp_param,
> +				sizeof(struct scalerp_param));
> +		memcpy(&region->parameter.fd,&init_fd_param,
> +				sizeof(struct fd_param));

No need for memory barrier here ?
	
> +	}
> +
> +	/* Load setfile */
> +	ret = fimc_is_pipeline_setfile(pipeline);
> +	if (ret<  0)
> +		goto err_exit;
> +
> +	/* Stream off */
> +	ret = fimc_is_itf_stream_off(&is->interface, pipeline->instance);
> +	if (ret<  0)
> +		goto err_exit;
> +
> +	/* Process off */
> +	ret = fimc_is_itf_process_off(&is->interface, pipeline->instance);
> +	if (ret<  0)
> +		goto err_exit;
> +
> +	/* Set state to OPEN */
> +	set_bit(PIPELINE_OPEN,&pipeline->state);
> +	is->num_pipelines++;
> +
> +	mutex_unlock(&pipeline->pipe_lock);
> +	return 0;
> +
> +err_fw:
> +	fimc_is_pipeline_freemem(pipeline);
> +err_exit:
> +	mutex_unlock(&pipeline->pipe_lock);
> +	return ret;
> +}
> +
> +int fimc_is_pipeline_close(struct fimc_is_pipeline *pipeline)
> +{
> +	int ret;
> +	struct fimc_is *is = pipeline->is;
> +
> +	mutex_lock(&pipeline->pipe_lock);
> +
> +	if (!test_bit(PIPELINE_OPEN,&pipeline->state)) {
> +		dev_err(pipeline->dev, "Pipeline not opened\n");
> +		ret = -EINVAL;
> +		goto err_exit;
> +	}
> +
> +	if (test_bit(PIPELINE_START,&pipeline->state)) {
> +		dev_err(pipeline->dev, "Cannot close pipeline when its started\n");
> +		ret = -EINVAL;
> +		goto err_exit;
> +	}
> +
> +	is->num_pipelines--;
> +	if (is->num_pipelines == 0) {
> +		/* FW power off command */
> +		ret = fimc_is_itf_power_down(&is->interface,
> +					pipeline->instance);
> +		if (ret)
> +			dev_err(pipeline->dev, "FW power down error\n");
> +
> +		/* Pipeline power off*/
> +		fimc_is_pipeline_power(pipeline, 0);
> +
> +		/* Free memory */
> +		fimc_is_pipeline_freemem(pipeline);
> +	}
> +
> +	clear_bit(PIPELINE_OPEN,&pipeline->state);
> +	mutex_unlock(&pipeline->pipe_lock);
> +	return 0;
> +
> +err_exit:
> +	mutex_unlock(&pipeline->pipe_lock);
> +	return ret;
> +}
> diff --git a/drivers/media/platform/exynos5-is/fimc-is-pipeline.h b/drivers/media/platform/exynos5-is/fimc-is-pipeline.h
> new file mode 100644
> index 0000000..aa89787
> --- /dev/null
> +++ b/drivers/media/platform/exynos5-is/fimc-is-pipeline.h
> @@ -0,0 +1,127 @@
> +/*
> + * Samsung EXYNOS5 FIMC-IS (Imaging Subsystem) driver
> + *
> + * Copyright (C) 2013 Samsung Electronics Co., Ltd.
> + *  Arun Kumar K<arun.kk@samsung.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +#ifndef FIMC_IS_PIPELINE_H_
> +#define FIMC_IS_PIPELINE_H_
> +
> +#include "fimc-is-core.h"
> +#include "fimc-is-sensor.h"
> +#include "fimc-is-isp.h"
> +#include "fimc-is-scaler.h"
> +
> +#define FIMC_IS_A5_MEM_SIZE		0x00a00000
> +#define FIMC_IS_A5_SEN_SIZE		0x00100000
> +#define FIMC_IS_REGION_SIZE		0x5000
> +#define FIMC_IS_SETFILE_SIZE		0xc0d8
> +#define FIMC_IS_TDNR_MEM_SIZE		(1920 * 1080 * 4)
> +#define FIMC_IS_DEBUG_REGION_ADDR	0x00840000
> +#define FIMC_IS_SHARED_REGION_ADDR	0x008c0000
> +
> +#define FIMC_IS_SCP_REGION_INDEX	400
> +#define FIMC_IS_SCC_REGION_INDEX	447
> +
> +#define MAX_ODC_INTERNAL_BUF_WIDTH	2560  /* 4808 in HW */
> +#define MAX_ODC_INTERNAL_BUF_HEIGHT	1920  /* 3356 in HW */
> +#define SIZE_ODC_INTERNAL_BUF \
> +	(MAX_ODC_INTERNAL_BUF_WIDTH * MAX_ODC_INTERNAL_BUF_HEIGHT * 3)
> +
> +#define MAX_DIS_INTERNAL_BUF_WIDTH	2400
> +#define MAX_DIS_INTERNAL_BUF_HEIGHT	1360
> +#define SIZE_DIS_INTERNAL_BUF \
> +	(MAX_DIS_INTERNAL_BUF_WIDTH * MAX_DIS_INTERNAL_BUF_HEIGHT * 2)
> +
> +#define MAX_3DNR_INTERNAL_BUF_WIDTH	1920
> +#define MAX_3DNR_INTERNAL_BUF_HEIGHT	1088
> +#define SIZE_DNR_INTERNAL_BUF \
> +	(MAX_3DNR_INTERNAL_BUF_WIDTH * MAX_3DNR_INTERNAL_BUF_HEIGHT * 2)
> +
> +#define NUM_ODC_INTERNAL_BUF		2
> +#define NUM_DIS_INTERNAL_BUF		5
> +#define NUM_DNR_INTERNAL_BUF		2
> +
> +#define FIMC_IS_FW_BASE_MASK		((1<<  26) - 1)
> +
> +#define FIMC_IS_NUM_COMPS		8
> +
> +#define FIMC_IS_MAGIC_NUMBER		0x23456789
> +
> +enum pipeline_state {
> +	PIPELINE_INIT,
> +	PIPELINE_OPEN,
> +	PIPELINE_START,
> +	PIPELINE_RUN,
> +};
> +
> +enum is_components {
> +	IS_ISP,
> +	IS_DRC,
> +	IS_SCC,
> +	IS_ODC,
> +	IS_DIS,
> +	IS_TDNR,
> +	IS_SCP,
> +	IS_FD
> +};
> +
> +enum component_state {
> +	COMP_ENABLE,
> +	COMP_START,
> +	COMP_RUN
> +};
> +
> +struct fimc_is_pipeline {
> +	unsigned long		state;
> +	unsigned long		comp_state[FIMC_IS_NUM_COMPS];
> +	bool			force_down;
> +	unsigned int		instance;
> +	/* Locks the isp / scaler buffers */
> +	spinlock_t		slock_buf;
> +	unsigned long		slock_flags;
> +	wait_queue_head_t	wait_q;
> +	/* For locking pipeline ops */
> +	struct mutex		pipe_lock;
> +	/* For locking scaler ops in pipeline */
> +	struct mutex		pipe_scl_lock;
> +
> +	struct fimc_is_meminfo	*minfo;
> +	struct is_region	*is_region;
> +	struct device		*dev;
> +
> +	struct fimc_is		*is;
> +	struct fimc_is_sensor	*sensor;
> +	struct fimc_is_isp	isp;
> +	struct fimc_is_scaler	scaler[FIMC_IS_NUM_SCALERS];
> +
> +	unsigned int		fcount;
> +	unsigned int		isp_width;
> +	unsigned int		isp_height;
> +};
> +
> +void fimc_is_pipeline_buf_lock(struct fimc_is_pipeline *pipeline);
> +void fimc_is_pipeline_buf_unlock(struct fimc_is_pipeline *pipeline);
> +int fimc_is_pipeline_setparams(struct fimc_is_pipeline *pipeline);
> +int fimc_is_pipeline_scaler_start(struct fimc_is_pipeline *pipeline,
> +		enum fimc_is_scaler_id scaler_id,
> +		unsigned int num_bufs,
> +		unsigned int num_planes);
> +int fimc_is_pipeline_scaler_stop(struct fimc_is_pipeline *pipeline,
> +		enum fimc_is_scaler_id scaler_id);
> +void fimc_is_pipeline_config_shot(struct fimc_is_pipeline *pipeline);
> +int fimc_is_pipeline_shot(struct fimc_is_pipeline *pipeline);
> +int fimc_is_pipeline_start(struct fimc_is_pipeline *pipeline);
> +int fimc_is_pipeline_stop(struct fimc_is_pipeline *pipeline);
> +int fimc_is_pipeline_init(struct fimc_is_pipeline *pipeline,
> +			unsigned int instance, void *is_ctx);
> +int fimc_is_pipeline_destroy(struct fimc_is_pipeline *pipeline);
> +int fimc_is_pipeline_open(struct fimc_is_pipeline *pipeline,
> +			struct fimc_is_sensor *sensor);
> +int fimc_is_pipeline_close(struct fimc_is_pipeline *pipeline);
> +
> +#endif


Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>

-- 
Thanks,
Sylwester

  reply	other threads:[~2013-08-09 23:12 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-08-07  9:03 [PATCH v4 00/13] Exynos5 IS driver Arun Kumar K
2013-08-07  9:03 ` [PATCH v4 01/13] [media] exynos5-is: Adding media device driver for exynos5 Arun Kumar K
2013-08-08 22:08   ` Sylwester Nawrocki
2013-08-13  8:40     ` Arun Kumar K
2013-08-07  9:03 ` [PATCH v4 02/13] [media] exynos5-fimc-is: Add Exynos5 FIMC-IS device tree bindings documentation Arun Kumar K
2013-08-07  9:03 ` [PATCH v4 03/13] [media] exynos5-fimc-is: Add driver core files Arun Kumar K
2013-08-09 22:14   ` Sylwester Nawrocki
2013-08-13  8:42     ` Arun Kumar K
2013-08-07  9:03 ` [PATCH v4 04/13] [media] exynos5-fimc-is: Add common driver header files Arun Kumar K
2013-08-09 22:19   ` Sylwester Nawrocki
2013-08-07  9:03 ` [PATCH v4 05/13] [media] exynos5-fimc-is: Add register definition and context header Arun Kumar K
2013-08-09 22:21   ` Sylwester Nawrocki
2013-08-07  9:03 ` [PATCH v4 06/13] [media] exynos5-fimc-is: Add isp subdev Arun Kumar K
2013-08-09 22:32   ` Sylwester Nawrocki
2013-08-07  9:03 ` [PATCH v4 07/13] [media] exynos5-fimc-is: Add scaler subdev Arun Kumar K
2013-08-09 22:36   ` Sylwester Nawrocki
2013-08-07  9:03 ` [PATCH v4 08/13] [media] exynos5-fimc-is: Add sensor interface Arun Kumar K
2013-08-09 22:44   ` Sylwester Nawrocki
2013-08-07  9:03 ` [PATCH v4 09/13] [media] exynos5-fimc-is: Add the hardware pipeline control Arun Kumar K
2013-08-09 23:11   ` Sylwester Nawrocki [this message]
2013-08-07  9:03 ` [PATCH v4 10/13] [media] exynos5-fimc-is: Add the hardware interface module Arun Kumar K
2013-08-09 23:20   ` Sylwester Nawrocki
2013-08-07  9:03 ` [PATCH v4 11/13] [media] exynos5-is: Add Kconfig and Makefile Arun Kumar K
2013-08-09 23:25   ` Sylwester Nawrocki
2013-08-07  9:04 ` [PATCH v4 12/13] V4L: s5k6a3: Change sensor min/max resolutions Arun Kumar K
2013-08-09 23:37   ` Sylwester Nawrocki
2013-08-07  9:04 ` [PATCH v4 13/13] V4L: Add driver for s5k4e5 image sensor Arun Kumar K
2013-08-09 23:40   ` Sylwester Nawrocki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5205773E.90603@gmail.com \
    --to=sylvester.nawrocki@gmail.com \
    --cc=a.hajda@samsung.com \
    --cc=arun.kk@samsung.com \
    --cc=arunkk.samsung@gmail.com \
    --cc=devicetree@vger.kernel.org \
    --cc=hverkuil@xs4all.nl \
    --cc=kilyeon.im@samsung.com \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-samsung-soc@vger.kernel.org \
    --cc=s.nawrocki@samsung.com \
    --cc=sachin.kamat@linaro.org \
    --cc=shaik.ameer@samsung.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.