From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from mail-ea0-f177.google.com ([209.85.215.177]:38055 "EHLO mail-ea0-f177.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1031447Ab3HIXMF (ORCPT ); Fri, 9 Aug 2013 19:12:05 -0400 Message-ID: <5205773E.90603@gmail.com> Date: Sat, 10 Aug 2013 01:11:58 +0200 From: Sylwester Nawrocki MIME-Version: 1.0 To: Arun Kumar K 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 References: <1375866242-18084-1-git-send-email-arun.kk@samsung.com> <1375866242-18084-10-git-send-email-arun.kk@samsung.com> In-Reply-To: <1375866242-18084-10-git-send-email-arun.kk@samsung.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Sender: linux-media-owner@vger.kernel.org List-ID: 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 > Signed-off-by: Kilyeon Im > --- > .../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 > + * Kil-yeon Lim > + * > + * 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 > +#include > + > +/* 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(®ion->parameter, 0x0, sizeof(struct is_param_region)); > + > + memcpy(®ion->parameter.sensor,&init_sensor_param, > + sizeof(struct sensor_param)); > + memcpy(®ion->parameter.isp,&init_isp_param, > + sizeof(struct isp_param)); > + memcpy(®ion->parameter.drc,&init_drc_param, > + sizeof(struct drc_param)); > + memcpy(®ion->parameter.scalerc,&init_scalerc_param, > + sizeof(struct scalerc_param)); > + memcpy(®ion->parameter.odc,&init_odc_param, > + sizeof(struct odc_param)); > + memcpy(®ion->parameter.dis,&init_dis_param, > + sizeof(struct dis_param)); > + memcpy(®ion->parameter.tdnr,&init_tdnr_param, > + sizeof(struct tdnr_param)); > + memcpy(®ion->parameter.scalerp,&init_scalerp_param, > + sizeof(struct scalerp_param)); > + memcpy(®ion->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 > + * > + * 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 -- Thanks, Sylwester