18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * ispccp2.c
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * TI OMAP3 ISP - CCP2 module
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Copyright (C) 2010 Nokia Corporation
88c2ecf20Sopenharmony_ci * Copyright (C) 2010 Texas Instruments, Inc.
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
118c2ecf20Sopenharmony_ci *	     Sakari Ailus <sakari.ailus@iki.fi>
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include <linux/delay.h>
158c2ecf20Sopenharmony_ci#include <linux/device.h>
168c2ecf20Sopenharmony_ci#include <linux/mm.h>
178c2ecf20Sopenharmony_ci#include <linux/module.h>
188c2ecf20Sopenharmony_ci#include <linux/mutex.h>
198c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
208c2ecf20Sopenharmony_ci#include <linux/regulator/consumer.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#include "isp.h"
238c2ecf20Sopenharmony_ci#include "ispreg.h"
248c2ecf20Sopenharmony_ci#include "ispccp2.h"
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci/* Number of LCX channels */
278c2ecf20Sopenharmony_ci#define CCP2_LCx_CHANS_NUM			3
288c2ecf20Sopenharmony_ci/* Max/Min size for CCP2 video port */
298c2ecf20Sopenharmony_ci#define ISPCCP2_DAT_START_MIN			0
308c2ecf20Sopenharmony_ci#define ISPCCP2_DAT_START_MAX			4095
318c2ecf20Sopenharmony_ci#define ISPCCP2_DAT_SIZE_MIN			0
328c2ecf20Sopenharmony_ci#define ISPCCP2_DAT_SIZE_MAX			4095
338c2ecf20Sopenharmony_ci#define ISPCCP2_VPCLK_FRACDIV			65536
348c2ecf20Sopenharmony_ci#define ISPCCP2_LCx_CTRL_FORMAT_RAW8_DPCM10_VP	0x12
358c2ecf20Sopenharmony_ci#define ISPCCP2_LCx_CTRL_FORMAT_RAW10_VP	0x16
368c2ecf20Sopenharmony_ci/* Max/Min size for CCP2 memory channel */
378c2ecf20Sopenharmony_ci#define ISPCCP2_LCM_HSIZE_COUNT_MIN		16
388c2ecf20Sopenharmony_ci#define ISPCCP2_LCM_HSIZE_COUNT_MAX		8191
398c2ecf20Sopenharmony_ci#define ISPCCP2_LCM_HSIZE_SKIP_MIN		0
408c2ecf20Sopenharmony_ci#define ISPCCP2_LCM_HSIZE_SKIP_MAX		8191
418c2ecf20Sopenharmony_ci#define ISPCCP2_LCM_VSIZE_MIN			1
428c2ecf20Sopenharmony_ci#define ISPCCP2_LCM_VSIZE_MAX			8191
438c2ecf20Sopenharmony_ci#define ISPCCP2_LCM_HWORDS_MIN			1
448c2ecf20Sopenharmony_ci#define ISPCCP2_LCM_HWORDS_MAX			4095
458c2ecf20Sopenharmony_ci#define ISPCCP2_LCM_CTRL_BURST_SIZE_32X		5
468c2ecf20Sopenharmony_ci#define ISPCCP2_LCM_CTRL_READ_THROTTLE_FULL	0
478c2ecf20Sopenharmony_ci#define ISPCCP2_LCM_CTRL_SRC_DECOMPR_DPCM10	2
488c2ecf20Sopenharmony_ci#define ISPCCP2_LCM_CTRL_SRC_FORMAT_RAW8	2
498c2ecf20Sopenharmony_ci#define ISPCCP2_LCM_CTRL_SRC_FORMAT_RAW10	3
508c2ecf20Sopenharmony_ci#define ISPCCP2_LCM_CTRL_DST_FORMAT_RAW10	3
518c2ecf20Sopenharmony_ci#define ISPCCP2_LCM_CTRL_DST_PORT_VP		0
528c2ecf20Sopenharmony_ci#define ISPCCP2_LCM_CTRL_DST_PORT_MEM		1
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci/* Set only the required bits */
558c2ecf20Sopenharmony_ci#define BIT_SET(var, shift, mask, val)			\
568c2ecf20Sopenharmony_ci	do {						\
578c2ecf20Sopenharmony_ci		var = ((var) & ~((mask) << (shift)))	\
588c2ecf20Sopenharmony_ci			| ((val) << (shift));		\
598c2ecf20Sopenharmony_ci	} while (0)
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci/*
628c2ecf20Sopenharmony_ci * ccp2_print_status - Print current CCP2 module register values.
638c2ecf20Sopenharmony_ci */
648c2ecf20Sopenharmony_ci#define CCP2_PRINT_REGISTER(isp, name)\
658c2ecf20Sopenharmony_ci	dev_dbg(isp->dev, "###CCP2 " #name "=0x%08x\n", \
668c2ecf20Sopenharmony_ci		isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_##name))
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_cistatic void ccp2_print_status(struct isp_ccp2_device *ccp2)
698c2ecf20Sopenharmony_ci{
708c2ecf20Sopenharmony_ci	struct isp_device *isp = to_isp_device(ccp2);
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	dev_dbg(isp->dev, "-------------CCP2 Register dump-------------\n");
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, SYSCONFIG);
758c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, SYSSTATUS);
768c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, LC01_IRQENABLE);
778c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, LC01_IRQSTATUS);
788c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, LC23_IRQENABLE);
798c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, LC23_IRQSTATUS);
808c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, LCM_IRQENABLE);
818c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, LCM_IRQSTATUS);
828c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, CTRL);
838c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, LCx_CTRL(0));
848c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, LCx_CODE(0));
858c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, LCx_STAT_START(0));
868c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, LCx_STAT_SIZE(0));
878c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, LCx_SOF_ADDR(0));
888c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, LCx_EOF_ADDR(0));
898c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, LCx_DAT_START(0));
908c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, LCx_DAT_SIZE(0));
918c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, LCx_DAT_PING_ADDR(0));
928c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, LCx_DAT_PONG_ADDR(0));
938c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, LCx_DAT_OFST(0));
948c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, LCM_CTRL);
958c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, LCM_VSIZE);
968c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, LCM_HSIZE);
978c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, LCM_PREFETCH);
988c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, LCM_SRC_ADDR);
998c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, LCM_SRC_OFST);
1008c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, LCM_DST_ADDR);
1018c2ecf20Sopenharmony_ci	CCP2_PRINT_REGISTER(isp, LCM_DST_OFST);
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	dev_dbg(isp->dev, "--------------------------------------------\n");
1048c2ecf20Sopenharmony_ci}
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci/*
1078c2ecf20Sopenharmony_ci * ccp2_reset - Reset the CCP2
1088c2ecf20Sopenharmony_ci * @ccp2: pointer to ISP CCP2 device
1098c2ecf20Sopenharmony_ci */
1108c2ecf20Sopenharmony_cistatic void ccp2_reset(struct isp_ccp2_device *ccp2)
1118c2ecf20Sopenharmony_ci{
1128c2ecf20Sopenharmony_ci	struct isp_device *isp = to_isp_device(ccp2);
1138c2ecf20Sopenharmony_ci	int i = 0;
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	/* Reset the CSI1/CCP2B and wait for reset to complete */
1168c2ecf20Sopenharmony_ci	isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_SYSCONFIG,
1178c2ecf20Sopenharmony_ci		    ISPCCP2_SYSCONFIG_SOFT_RESET);
1188c2ecf20Sopenharmony_ci	while (!(isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_SYSSTATUS) &
1198c2ecf20Sopenharmony_ci		 ISPCCP2_SYSSTATUS_RESET_DONE)) {
1208c2ecf20Sopenharmony_ci		udelay(10);
1218c2ecf20Sopenharmony_ci		if (i++ > 10) {  /* try read 10 times */
1228c2ecf20Sopenharmony_ci			dev_warn(isp->dev,
1238c2ecf20Sopenharmony_ci				"omap3_isp: timeout waiting for ccp2 reset\n");
1248c2ecf20Sopenharmony_ci			break;
1258c2ecf20Sopenharmony_ci		}
1268c2ecf20Sopenharmony_ci	}
1278c2ecf20Sopenharmony_ci}
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci/*
1308c2ecf20Sopenharmony_ci * ccp2_pwr_cfg - Configure the power mode settings
1318c2ecf20Sopenharmony_ci * @ccp2: pointer to ISP CCP2 device
1328c2ecf20Sopenharmony_ci */
1338c2ecf20Sopenharmony_cistatic void ccp2_pwr_cfg(struct isp_ccp2_device *ccp2)
1348c2ecf20Sopenharmony_ci{
1358c2ecf20Sopenharmony_ci	struct isp_device *isp = to_isp_device(ccp2);
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	isp_reg_writel(isp, ISPCCP2_SYSCONFIG_MSTANDBY_MODE_SMART |
1388c2ecf20Sopenharmony_ci			((isp->revision == ISP_REVISION_15_0 && isp->autoidle) ?
1398c2ecf20Sopenharmony_ci			  ISPCCP2_SYSCONFIG_AUTO_IDLE : 0),
1408c2ecf20Sopenharmony_ci		       OMAP3_ISP_IOMEM_CCP2, ISPCCP2_SYSCONFIG);
1418c2ecf20Sopenharmony_ci}
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci/*
1448c2ecf20Sopenharmony_ci * ccp2_if_enable - Enable CCP2 interface.
1458c2ecf20Sopenharmony_ci * @ccp2: pointer to ISP CCP2 device
1468c2ecf20Sopenharmony_ci * @enable: enable/disable flag
1478c2ecf20Sopenharmony_ci */
1488c2ecf20Sopenharmony_cistatic int ccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable)
1498c2ecf20Sopenharmony_ci{
1508c2ecf20Sopenharmony_ci	struct isp_device *isp = to_isp_device(ccp2);
1518c2ecf20Sopenharmony_ci	int ret;
1528c2ecf20Sopenharmony_ci	int i;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	if (enable && ccp2->vdds_csib) {
1558c2ecf20Sopenharmony_ci		ret = regulator_enable(ccp2->vdds_csib);
1568c2ecf20Sopenharmony_ci		if (ret < 0)
1578c2ecf20Sopenharmony_ci			return ret;
1588c2ecf20Sopenharmony_ci	}
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	/* Enable/Disable all the LCx channels */
1618c2ecf20Sopenharmony_ci	for (i = 0; i < CCP2_LCx_CHANS_NUM; i++)
1628c2ecf20Sopenharmony_ci		isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(i),
1638c2ecf20Sopenharmony_ci				ISPCCP2_LCx_CTRL_CHAN_EN,
1648c2ecf20Sopenharmony_ci				enable ? ISPCCP2_LCx_CTRL_CHAN_EN : 0);
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	/* Enable/Disable ccp2 interface in ccp2 mode */
1678c2ecf20Sopenharmony_ci	isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL,
1688c2ecf20Sopenharmony_ci			ISPCCP2_CTRL_MODE | ISPCCP2_CTRL_IF_EN,
1698c2ecf20Sopenharmony_ci			enable ? (ISPCCP2_CTRL_MODE | ISPCCP2_CTRL_IF_EN) : 0);
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	if (!enable && ccp2->vdds_csib)
1728c2ecf20Sopenharmony_ci		regulator_disable(ccp2->vdds_csib);
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	return 0;
1758c2ecf20Sopenharmony_ci}
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci/*
1788c2ecf20Sopenharmony_ci * ccp2_mem_enable - Enable CCP2 memory interface.
1798c2ecf20Sopenharmony_ci * @ccp2: pointer to ISP CCP2 device
1808c2ecf20Sopenharmony_ci * @enable: enable/disable flag
1818c2ecf20Sopenharmony_ci */
1828c2ecf20Sopenharmony_cistatic void ccp2_mem_enable(struct isp_ccp2_device *ccp2, u8 enable)
1838c2ecf20Sopenharmony_ci{
1848c2ecf20Sopenharmony_ci	struct isp_device *isp = to_isp_device(ccp2);
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	if (enable)
1878c2ecf20Sopenharmony_ci		ccp2_if_enable(ccp2, 0);
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	/* Enable/Disable ccp2 interface in ccp2 mode */
1908c2ecf20Sopenharmony_ci	isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL,
1918c2ecf20Sopenharmony_ci			ISPCCP2_CTRL_MODE, enable ? ISPCCP2_CTRL_MODE : 0);
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci	isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_CTRL,
1948c2ecf20Sopenharmony_ci			ISPCCP2_LCM_CTRL_CHAN_EN,
1958c2ecf20Sopenharmony_ci			enable ? ISPCCP2_LCM_CTRL_CHAN_EN : 0);
1968c2ecf20Sopenharmony_ci}
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci/*
1998c2ecf20Sopenharmony_ci * ccp2_phyif_config - Initialize CCP2 phy interface config
2008c2ecf20Sopenharmony_ci * @ccp2: Pointer to ISP CCP2 device
2018c2ecf20Sopenharmony_ci * @buscfg: CCP2 platform data
2028c2ecf20Sopenharmony_ci *
2038c2ecf20Sopenharmony_ci * Configure the CCP2 physical interface module from platform data.
2048c2ecf20Sopenharmony_ci *
2058c2ecf20Sopenharmony_ci * Returns -EIO if strobe is chosen in CSI1 mode, or 0 on success.
2068c2ecf20Sopenharmony_ci */
2078c2ecf20Sopenharmony_cistatic int ccp2_phyif_config(struct isp_ccp2_device *ccp2,
2088c2ecf20Sopenharmony_ci			     const struct isp_ccp2_cfg *buscfg)
2098c2ecf20Sopenharmony_ci{
2108c2ecf20Sopenharmony_ci	struct isp_device *isp = to_isp_device(ccp2);
2118c2ecf20Sopenharmony_ci	u32 val;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL) |
2148c2ecf20Sopenharmony_ci			    ISPCCP2_CTRL_MODE;
2158c2ecf20Sopenharmony_ci	/* Data/strobe physical layer */
2168c2ecf20Sopenharmony_ci	BIT_SET(val, ISPCCP2_CTRL_PHY_SEL_SHIFT, ISPCCP2_CTRL_PHY_SEL_MASK,
2178c2ecf20Sopenharmony_ci		buscfg->phy_layer);
2188c2ecf20Sopenharmony_ci	BIT_SET(val, ISPCCP2_CTRL_IO_OUT_SEL_SHIFT,
2198c2ecf20Sopenharmony_ci		ISPCCP2_CTRL_IO_OUT_SEL_MASK, buscfg->ccp2_mode);
2208c2ecf20Sopenharmony_ci	BIT_SET(val, ISPCCP2_CTRL_INV_SHIFT, ISPCCP2_CTRL_INV_MASK,
2218c2ecf20Sopenharmony_ci		buscfg->strobe_clk_pol);
2228c2ecf20Sopenharmony_ci	BIT_SET(val, ISPCCP2_CTRL_VP_CLK_POL_SHIFT,
2238c2ecf20Sopenharmony_ci		ISPCCP2_CTRL_VP_CLK_POL_MASK, buscfg->vp_clk_pol);
2248c2ecf20Sopenharmony_ci	isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
2278c2ecf20Sopenharmony_ci	if (!(val & ISPCCP2_CTRL_MODE)) {
2288c2ecf20Sopenharmony_ci		if (buscfg->ccp2_mode == ISP_CCP2_MODE_CCP2)
2298c2ecf20Sopenharmony_ci			dev_warn(isp->dev, "OMAP3 CCP2 bus not available\n");
2308c2ecf20Sopenharmony_ci		if (buscfg->phy_layer == ISP_CCP2_PHY_DATA_STROBE)
2318c2ecf20Sopenharmony_ci			/* Strobe mode requires CCP2 */
2328c2ecf20Sopenharmony_ci			return -EIO;
2338c2ecf20Sopenharmony_ci	}
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	return 0;
2368c2ecf20Sopenharmony_ci}
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci/*
2398c2ecf20Sopenharmony_ci * ccp2_vp_config - Initialize CCP2 video port interface.
2408c2ecf20Sopenharmony_ci * @ccp2: Pointer to ISP CCP2 device
2418c2ecf20Sopenharmony_ci * @vpclk_div: Video port divisor
2428c2ecf20Sopenharmony_ci *
2438c2ecf20Sopenharmony_ci * Configure the CCP2 video port with the given clock divisor. The valid divisor
2448c2ecf20Sopenharmony_ci * values depend on the ISP revision:
2458c2ecf20Sopenharmony_ci *
2468c2ecf20Sopenharmony_ci * - revision 1.0 and 2.0	1 to 4
2478c2ecf20Sopenharmony_ci * - revision 15.0		1 to 65536
2488c2ecf20Sopenharmony_ci *
2498c2ecf20Sopenharmony_ci * The exact divisor value used might differ from the requested value, as ISP
2508c2ecf20Sopenharmony_ci * revision 15.0 represent the divisor by 65536 divided by an integer.
2518c2ecf20Sopenharmony_ci */
2528c2ecf20Sopenharmony_cistatic void ccp2_vp_config(struct isp_ccp2_device *ccp2,
2538c2ecf20Sopenharmony_ci			   unsigned int vpclk_div)
2548c2ecf20Sopenharmony_ci{
2558c2ecf20Sopenharmony_ci	struct isp_device *isp = to_isp_device(ccp2);
2568c2ecf20Sopenharmony_ci	u32 val;
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	/* ISPCCP2_CTRL Video port */
2598c2ecf20Sopenharmony_ci	val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
2608c2ecf20Sopenharmony_ci	val |= ISPCCP2_CTRL_VP_ONLY_EN;	/* Disable the memory write port */
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	if (isp->revision == ISP_REVISION_15_0) {
2638c2ecf20Sopenharmony_ci		vpclk_div = clamp_t(unsigned int, vpclk_div, 1, 65536);
2648c2ecf20Sopenharmony_ci		vpclk_div = min(ISPCCP2_VPCLK_FRACDIV / vpclk_div, 65535U);
2658c2ecf20Sopenharmony_ci		BIT_SET(val, ISPCCP2_CTRL_VPCLK_DIV_SHIFT,
2668c2ecf20Sopenharmony_ci			ISPCCP2_CTRL_VPCLK_DIV_MASK, vpclk_div);
2678c2ecf20Sopenharmony_ci	} else {
2688c2ecf20Sopenharmony_ci		vpclk_div = clamp_t(unsigned int, vpclk_div, 1, 4);
2698c2ecf20Sopenharmony_ci		BIT_SET(val, ISPCCP2_CTRL_VP_OUT_CTRL_SHIFT,
2708c2ecf20Sopenharmony_ci			ISPCCP2_CTRL_VP_OUT_CTRL_MASK, vpclk_div - 1);
2718c2ecf20Sopenharmony_ci	}
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
2748c2ecf20Sopenharmony_ci}
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci/*
2778c2ecf20Sopenharmony_ci * ccp2_lcx_config - Initialize CCP2 logical channel interface.
2788c2ecf20Sopenharmony_ci * @ccp2: Pointer to ISP CCP2 device
2798c2ecf20Sopenharmony_ci * @config: Pointer to ISP LCx config structure.
2808c2ecf20Sopenharmony_ci *
2818c2ecf20Sopenharmony_ci * This will analyze the parameters passed by the interface config
2828c2ecf20Sopenharmony_ci * and configure CSI1/CCP2 logical channel
2838c2ecf20Sopenharmony_ci *
2848c2ecf20Sopenharmony_ci */
2858c2ecf20Sopenharmony_cistatic void ccp2_lcx_config(struct isp_ccp2_device *ccp2,
2868c2ecf20Sopenharmony_ci			    struct isp_interface_lcx_config *config)
2878c2ecf20Sopenharmony_ci{
2888c2ecf20Sopenharmony_ci	struct isp_device *isp = to_isp_device(ccp2);
2898c2ecf20Sopenharmony_ci	u32 val, format;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	switch (config->format) {
2928c2ecf20Sopenharmony_ci	case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8:
2938c2ecf20Sopenharmony_ci		format = ISPCCP2_LCx_CTRL_FORMAT_RAW8_DPCM10_VP;
2948c2ecf20Sopenharmony_ci		break;
2958c2ecf20Sopenharmony_ci	case MEDIA_BUS_FMT_SGRBG10_1X10:
2968c2ecf20Sopenharmony_ci	default:
2978c2ecf20Sopenharmony_ci		format = ISPCCP2_LCx_CTRL_FORMAT_RAW10_VP;	/* RAW10+VP */
2988c2ecf20Sopenharmony_ci		break;
2998c2ecf20Sopenharmony_ci	}
3008c2ecf20Sopenharmony_ci	/* ISPCCP2_LCx_CTRL logical channel #0 */
3018c2ecf20Sopenharmony_ci	val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(0))
3028c2ecf20Sopenharmony_ci			    | (ISPCCP2_LCx_CTRL_REGION_EN); /* Region */
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci	if (isp->revision == ISP_REVISION_15_0) {
3058c2ecf20Sopenharmony_ci		/* CRC */
3068c2ecf20Sopenharmony_ci		BIT_SET(val, ISPCCP2_LCx_CTRL_CRC_SHIFT_15_0,
3078c2ecf20Sopenharmony_ci			ISPCCP2_LCx_CTRL_CRC_MASK,
3088c2ecf20Sopenharmony_ci			config->crc);
3098c2ecf20Sopenharmony_ci		/* Format = RAW10+VP or RAW8+DPCM10+VP*/
3108c2ecf20Sopenharmony_ci		BIT_SET(val, ISPCCP2_LCx_CTRL_FORMAT_SHIFT_15_0,
3118c2ecf20Sopenharmony_ci			ISPCCP2_LCx_CTRL_FORMAT_MASK_15_0, format);
3128c2ecf20Sopenharmony_ci	} else {
3138c2ecf20Sopenharmony_ci		BIT_SET(val, ISPCCP2_LCx_CTRL_CRC_SHIFT,
3148c2ecf20Sopenharmony_ci			ISPCCP2_LCx_CTRL_CRC_MASK,
3158c2ecf20Sopenharmony_ci			config->crc);
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci		BIT_SET(val, ISPCCP2_LCx_CTRL_FORMAT_SHIFT,
3188c2ecf20Sopenharmony_ci			ISPCCP2_LCx_CTRL_FORMAT_MASK, format);
3198c2ecf20Sopenharmony_ci	}
3208c2ecf20Sopenharmony_ci	isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(0));
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	/* ISPCCP2_DAT_START for logical channel #0 */
3238c2ecf20Sopenharmony_ci	isp_reg_writel(isp, config->data_start << ISPCCP2_LCx_DAT_SHIFT,
3248c2ecf20Sopenharmony_ci		       OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_DAT_START(0));
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	/* ISPCCP2_DAT_SIZE for logical channel #0 */
3278c2ecf20Sopenharmony_ci	isp_reg_writel(isp, config->data_size << ISPCCP2_LCx_DAT_SHIFT,
3288c2ecf20Sopenharmony_ci		       OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_DAT_SIZE(0));
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	/* Enable error IRQs for logical channel #0 */
3318c2ecf20Sopenharmony_ci	val = ISPCCP2_LC01_IRQSTATUS_LC0_FIFO_OVF_IRQ |
3328c2ecf20Sopenharmony_ci	      ISPCCP2_LC01_IRQSTATUS_LC0_CRC_IRQ |
3338c2ecf20Sopenharmony_ci	      ISPCCP2_LC01_IRQSTATUS_LC0_FSP_IRQ |
3348c2ecf20Sopenharmony_ci	      ISPCCP2_LC01_IRQSTATUS_LC0_FW_IRQ |
3358c2ecf20Sopenharmony_ci	      ISPCCP2_LC01_IRQSTATUS_LC0_FSC_IRQ |
3368c2ecf20Sopenharmony_ci	      ISPCCP2_LC01_IRQSTATUS_LC0_SSC_IRQ;
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci	isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LC01_IRQSTATUS);
3398c2ecf20Sopenharmony_ci	isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LC01_IRQENABLE, val);
3408c2ecf20Sopenharmony_ci}
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci/*
3438c2ecf20Sopenharmony_ci * ccp2_if_configure - Configure ccp2 with data from sensor
3448c2ecf20Sopenharmony_ci * @ccp2: Pointer to ISP CCP2 device
3458c2ecf20Sopenharmony_ci *
3468c2ecf20Sopenharmony_ci * Return 0 on success or a negative error code
3478c2ecf20Sopenharmony_ci */
3488c2ecf20Sopenharmony_cistatic int ccp2_if_configure(struct isp_ccp2_device *ccp2)
3498c2ecf20Sopenharmony_ci{
3508c2ecf20Sopenharmony_ci	struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
3518c2ecf20Sopenharmony_ci	const struct isp_bus_cfg *buscfg;
3528c2ecf20Sopenharmony_ci	struct v4l2_mbus_framefmt *format;
3538c2ecf20Sopenharmony_ci	struct media_pad *pad;
3548c2ecf20Sopenharmony_ci	struct v4l2_subdev *sensor;
3558c2ecf20Sopenharmony_ci	u32 lines = 0;
3568c2ecf20Sopenharmony_ci	int ret;
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	ccp2_pwr_cfg(ccp2);
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	pad = media_entity_remote_pad(&ccp2->pads[CCP2_PAD_SINK]);
3618c2ecf20Sopenharmony_ci	sensor = media_entity_to_v4l2_subdev(pad->entity);
3628c2ecf20Sopenharmony_ci	buscfg = v4l2_subdev_to_bus_cfg(pipe->external);
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	ret = ccp2_phyif_config(ccp2, &buscfg->bus.ccp2);
3658c2ecf20Sopenharmony_ci	if (ret < 0)
3668c2ecf20Sopenharmony_ci		return ret;
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	ccp2_vp_config(ccp2, buscfg->bus.ccp2.vpclk_div + 1);
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci	v4l2_subdev_call(sensor, sensor, g_skip_top_lines, &lines);
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	format = &ccp2->formats[CCP2_PAD_SINK];
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	ccp2->if_cfg.data_start = lines;
3758c2ecf20Sopenharmony_ci	ccp2->if_cfg.crc = buscfg->bus.ccp2.crc;
3768c2ecf20Sopenharmony_ci	ccp2->if_cfg.format = format->code;
3778c2ecf20Sopenharmony_ci	ccp2->if_cfg.data_size = format->height;
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci	ccp2_lcx_config(ccp2, &ccp2->if_cfg);
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci	return 0;
3828c2ecf20Sopenharmony_ci}
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_cistatic int ccp2_adjust_bandwidth(struct isp_ccp2_device *ccp2)
3858c2ecf20Sopenharmony_ci{
3868c2ecf20Sopenharmony_ci	struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
3878c2ecf20Sopenharmony_ci	struct isp_device *isp = to_isp_device(ccp2);
3888c2ecf20Sopenharmony_ci	const struct v4l2_mbus_framefmt *ofmt = &ccp2->formats[CCP2_PAD_SOURCE];
3898c2ecf20Sopenharmony_ci	unsigned long l3_ick = pipe->l3_ick;
3908c2ecf20Sopenharmony_ci	struct v4l2_fract *timeperframe;
3918c2ecf20Sopenharmony_ci	unsigned int vpclk_div = 2;
3928c2ecf20Sopenharmony_ci	unsigned int value;
3938c2ecf20Sopenharmony_ci	u64 bound;
3948c2ecf20Sopenharmony_ci	u64 area;
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	/* Compute the minimum clock divisor, based on the pipeline maximum
3978c2ecf20Sopenharmony_ci	 * data rate. This is an absolute lower bound if we don't want SBL
3988c2ecf20Sopenharmony_ci	 * overflows, so round the value up.
3998c2ecf20Sopenharmony_ci	 */
4008c2ecf20Sopenharmony_ci	vpclk_div = max_t(unsigned int, DIV_ROUND_UP(l3_ick, pipe->max_rate),
4018c2ecf20Sopenharmony_ci			  vpclk_div);
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci	/* Compute the maximum clock divisor, based on the requested frame rate.
4048c2ecf20Sopenharmony_ci	 * This is a soft lower bound to achieve a frame rate equal or higher
4058c2ecf20Sopenharmony_ci	 * than the requested value, so round the value down.
4068c2ecf20Sopenharmony_ci	 */
4078c2ecf20Sopenharmony_ci	timeperframe = &pipe->max_timeperframe;
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	if (timeperframe->numerator) {
4108c2ecf20Sopenharmony_ci		area = ofmt->width * ofmt->height;
4118c2ecf20Sopenharmony_ci		bound = div_u64(area * timeperframe->denominator,
4128c2ecf20Sopenharmony_ci				timeperframe->numerator);
4138c2ecf20Sopenharmony_ci		value = min_t(u64, bound, l3_ick);
4148c2ecf20Sopenharmony_ci		vpclk_div = max_t(unsigned int, l3_ick / value, vpclk_div);
4158c2ecf20Sopenharmony_ci	}
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	dev_dbg(isp->dev, "%s: minimum clock divisor = %u\n", __func__,
4188c2ecf20Sopenharmony_ci		vpclk_div);
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci	return vpclk_div;
4218c2ecf20Sopenharmony_ci}
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci/*
4248c2ecf20Sopenharmony_ci * ccp2_mem_configure - Initialize CCP2 memory input/output interface
4258c2ecf20Sopenharmony_ci * @ccp2: Pointer to ISP CCP2 device
4268c2ecf20Sopenharmony_ci * @config: Pointer to ISP mem interface config structure
4278c2ecf20Sopenharmony_ci *
4288c2ecf20Sopenharmony_ci * This will analyze the parameters passed by the interface config
4298c2ecf20Sopenharmony_ci * structure, and configure the respective registers for proper
4308c2ecf20Sopenharmony_ci * CSI1/CCP2 memory input.
4318c2ecf20Sopenharmony_ci */
4328c2ecf20Sopenharmony_cistatic void ccp2_mem_configure(struct isp_ccp2_device *ccp2,
4338c2ecf20Sopenharmony_ci			       struct isp_interface_mem_config *config)
4348c2ecf20Sopenharmony_ci{
4358c2ecf20Sopenharmony_ci	struct isp_device *isp = to_isp_device(ccp2);
4368c2ecf20Sopenharmony_ci	u32 sink_pixcode = ccp2->formats[CCP2_PAD_SINK].code;
4378c2ecf20Sopenharmony_ci	u32 source_pixcode = ccp2->formats[CCP2_PAD_SOURCE].code;
4388c2ecf20Sopenharmony_ci	unsigned int dpcm_decompress = 0;
4398c2ecf20Sopenharmony_ci	u32 val, hwords;
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci	if (sink_pixcode != source_pixcode &&
4428c2ecf20Sopenharmony_ci	    sink_pixcode == MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8)
4438c2ecf20Sopenharmony_ci		dpcm_decompress = 1;
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci	ccp2_pwr_cfg(ccp2);
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci	/* Hsize, Skip */
4488c2ecf20Sopenharmony_ci	isp_reg_writel(isp, ISPCCP2_LCM_HSIZE_SKIP_MIN |
4498c2ecf20Sopenharmony_ci		       (config->hsize_count << ISPCCP2_LCM_HSIZE_SHIFT),
4508c2ecf20Sopenharmony_ci		       OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_HSIZE);
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci	/* Vsize, no. of lines */
4538c2ecf20Sopenharmony_ci	isp_reg_writel(isp, config->vsize_count << ISPCCP2_LCM_VSIZE_SHIFT,
4548c2ecf20Sopenharmony_ci		       OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_VSIZE);
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	if (ccp2->video_in.bpl_padding == 0)
4578c2ecf20Sopenharmony_ci		config->src_ofst = 0;
4588c2ecf20Sopenharmony_ci	else
4598c2ecf20Sopenharmony_ci		config->src_ofst = ccp2->video_in.bpl_value;
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	isp_reg_writel(isp, config->src_ofst, OMAP3_ISP_IOMEM_CCP2,
4628c2ecf20Sopenharmony_ci		       ISPCCP2_LCM_SRC_OFST);
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	/* Source and Destination formats */
4658c2ecf20Sopenharmony_ci	val = ISPCCP2_LCM_CTRL_DST_FORMAT_RAW10 <<
4668c2ecf20Sopenharmony_ci	      ISPCCP2_LCM_CTRL_DST_FORMAT_SHIFT;
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	if (dpcm_decompress) {
4698c2ecf20Sopenharmony_ci		/* source format is RAW8 */
4708c2ecf20Sopenharmony_ci		val |= ISPCCP2_LCM_CTRL_SRC_FORMAT_RAW8 <<
4718c2ecf20Sopenharmony_ci		       ISPCCP2_LCM_CTRL_SRC_FORMAT_SHIFT;
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci		/* RAW8 + DPCM10 - simple predictor */
4748c2ecf20Sopenharmony_ci		val |= ISPCCP2_LCM_CTRL_SRC_DPCM_PRED;
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_ci		/* enable source DPCM decompression */
4778c2ecf20Sopenharmony_ci		val |= ISPCCP2_LCM_CTRL_SRC_DECOMPR_DPCM10 <<
4788c2ecf20Sopenharmony_ci		       ISPCCP2_LCM_CTRL_SRC_DECOMPR_SHIFT;
4798c2ecf20Sopenharmony_ci	} else {
4808c2ecf20Sopenharmony_ci		/* source format is RAW10 */
4818c2ecf20Sopenharmony_ci		val |= ISPCCP2_LCM_CTRL_SRC_FORMAT_RAW10 <<
4828c2ecf20Sopenharmony_ci		       ISPCCP2_LCM_CTRL_SRC_FORMAT_SHIFT;
4838c2ecf20Sopenharmony_ci	}
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci	/* Burst size to 32x64 */
4868c2ecf20Sopenharmony_ci	val |= ISPCCP2_LCM_CTRL_BURST_SIZE_32X <<
4878c2ecf20Sopenharmony_ci	       ISPCCP2_LCM_CTRL_BURST_SIZE_SHIFT;
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci	isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_CTRL);
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_ci	/* Prefetch setup */
4928c2ecf20Sopenharmony_ci	if (dpcm_decompress)
4938c2ecf20Sopenharmony_ci		hwords = (ISPCCP2_LCM_HSIZE_SKIP_MIN +
4948c2ecf20Sopenharmony_ci			  config->hsize_count) >> 3;
4958c2ecf20Sopenharmony_ci	else
4968c2ecf20Sopenharmony_ci		hwords = (ISPCCP2_LCM_HSIZE_SKIP_MIN +
4978c2ecf20Sopenharmony_ci			  config->hsize_count) >> 2;
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci	isp_reg_writel(isp, hwords << ISPCCP2_LCM_PREFETCH_SHIFT,
5008c2ecf20Sopenharmony_ci		       OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_PREFETCH);
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	/* Video port */
5038c2ecf20Sopenharmony_ci	isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL,
5048c2ecf20Sopenharmony_ci		    ISPCCP2_CTRL_IO_OUT_SEL | ISPCCP2_CTRL_MODE);
5058c2ecf20Sopenharmony_ci	ccp2_vp_config(ccp2, ccp2_adjust_bandwidth(ccp2));
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci	/* Clear LCM interrupts */
5088c2ecf20Sopenharmony_ci	isp_reg_writel(isp, ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ |
5098c2ecf20Sopenharmony_ci		       ISPCCP2_LCM_IRQSTATUS_EOF_IRQ,
5108c2ecf20Sopenharmony_ci		       OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_IRQSTATUS);
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci	/* Enable LCM interrupts */
5138c2ecf20Sopenharmony_ci	isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_IRQENABLE,
5148c2ecf20Sopenharmony_ci		    ISPCCP2_LCM_IRQSTATUS_EOF_IRQ |
5158c2ecf20Sopenharmony_ci		    ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ);
5168c2ecf20Sopenharmony_ci}
5178c2ecf20Sopenharmony_ci
5188c2ecf20Sopenharmony_ci/*
5198c2ecf20Sopenharmony_ci * ccp2_set_inaddr - Sets memory address of input frame.
5208c2ecf20Sopenharmony_ci * @ccp2: Pointer to ISP CCP2 device
5218c2ecf20Sopenharmony_ci * @addr: 32bit memory address aligned on 32byte boundary.
5228c2ecf20Sopenharmony_ci *
5238c2ecf20Sopenharmony_ci * Configures the memory address from which the input frame is to be read.
5248c2ecf20Sopenharmony_ci */
5258c2ecf20Sopenharmony_cistatic void ccp2_set_inaddr(struct isp_ccp2_device *ccp2, u32 addr)
5268c2ecf20Sopenharmony_ci{
5278c2ecf20Sopenharmony_ci	struct isp_device *isp = to_isp_device(ccp2);
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_SRC_ADDR);
5308c2ecf20Sopenharmony_ci}
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci/* -----------------------------------------------------------------------------
5338c2ecf20Sopenharmony_ci * Interrupt handling
5348c2ecf20Sopenharmony_ci */
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_cistatic void ccp2_isr_buffer(struct isp_ccp2_device *ccp2)
5378c2ecf20Sopenharmony_ci{
5388c2ecf20Sopenharmony_ci	struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
5398c2ecf20Sopenharmony_ci	struct isp_buffer *buffer;
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci	buffer = omap3isp_video_buffer_next(&ccp2->video_in);
5428c2ecf20Sopenharmony_ci	if (buffer != NULL)
5438c2ecf20Sopenharmony_ci		ccp2_set_inaddr(ccp2, buffer->dma);
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	pipe->state |= ISP_PIPELINE_IDLE_INPUT;
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci	if (ccp2->state == ISP_PIPELINE_STREAM_SINGLESHOT) {
5488c2ecf20Sopenharmony_ci		if (isp_pipeline_ready(pipe))
5498c2ecf20Sopenharmony_ci			omap3isp_pipeline_set_stream(pipe,
5508c2ecf20Sopenharmony_ci						ISP_PIPELINE_STREAM_SINGLESHOT);
5518c2ecf20Sopenharmony_ci	}
5528c2ecf20Sopenharmony_ci}
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci/*
5558c2ecf20Sopenharmony_ci * omap3isp_ccp2_isr - Handle ISP CCP2 interrupts
5568c2ecf20Sopenharmony_ci * @ccp2: Pointer to ISP CCP2 device
5578c2ecf20Sopenharmony_ci *
5588c2ecf20Sopenharmony_ci * This will handle the CCP2 interrupts
5598c2ecf20Sopenharmony_ci */
5608c2ecf20Sopenharmony_civoid omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2)
5618c2ecf20Sopenharmony_ci{
5628c2ecf20Sopenharmony_ci	struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
5638c2ecf20Sopenharmony_ci	struct isp_device *isp = to_isp_device(ccp2);
5648c2ecf20Sopenharmony_ci	static const u32 ISPCCP2_LC01_ERROR =
5658c2ecf20Sopenharmony_ci		ISPCCP2_LC01_IRQSTATUS_LC0_FIFO_OVF_IRQ |
5668c2ecf20Sopenharmony_ci		ISPCCP2_LC01_IRQSTATUS_LC0_CRC_IRQ |
5678c2ecf20Sopenharmony_ci		ISPCCP2_LC01_IRQSTATUS_LC0_FSP_IRQ |
5688c2ecf20Sopenharmony_ci		ISPCCP2_LC01_IRQSTATUS_LC0_FW_IRQ |
5698c2ecf20Sopenharmony_ci		ISPCCP2_LC01_IRQSTATUS_LC0_FSC_IRQ |
5708c2ecf20Sopenharmony_ci		ISPCCP2_LC01_IRQSTATUS_LC0_SSC_IRQ;
5718c2ecf20Sopenharmony_ci	u32 lcx_irqstatus, lcm_irqstatus;
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci	/* First clear the interrupts */
5748c2ecf20Sopenharmony_ci	lcx_irqstatus = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2,
5758c2ecf20Sopenharmony_ci				      ISPCCP2_LC01_IRQSTATUS);
5768c2ecf20Sopenharmony_ci	isp_reg_writel(isp, lcx_irqstatus, OMAP3_ISP_IOMEM_CCP2,
5778c2ecf20Sopenharmony_ci		       ISPCCP2_LC01_IRQSTATUS);
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	lcm_irqstatus = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2,
5808c2ecf20Sopenharmony_ci				      ISPCCP2_LCM_IRQSTATUS);
5818c2ecf20Sopenharmony_ci	isp_reg_writel(isp, lcm_irqstatus, OMAP3_ISP_IOMEM_CCP2,
5828c2ecf20Sopenharmony_ci		       ISPCCP2_LCM_IRQSTATUS);
5838c2ecf20Sopenharmony_ci	/* Errors */
5848c2ecf20Sopenharmony_ci	if (lcx_irqstatus & ISPCCP2_LC01_ERROR) {
5858c2ecf20Sopenharmony_ci		pipe->error = true;
5868c2ecf20Sopenharmony_ci		dev_dbg(isp->dev, "CCP2 err:%x\n", lcx_irqstatus);
5878c2ecf20Sopenharmony_ci		return;
5888c2ecf20Sopenharmony_ci	}
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ) {
5918c2ecf20Sopenharmony_ci		pipe->error = true;
5928c2ecf20Sopenharmony_ci		dev_dbg(isp->dev, "CCP2 OCP err:%x\n", lcm_irqstatus);
5938c2ecf20Sopenharmony_ci	}
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	if (omap3isp_module_sync_is_stopping(&ccp2->wait, &ccp2->stopping))
5968c2ecf20Sopenharmony_ci		return;
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci	/* Handle queued buffers on frame end interrupts */
5998c2ecf20Sopenharmony_ci	if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_EOF_IRQ)
6008c2ecf20Sopenharmony_ci		ccp2_isr_buffer(ccp2);
6018c2ecf20Sopenharmony_ci}
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_ci/* -----------------------------------------------------------------------------
6048c2ecf20Sopenharmony_ci * V4L2 subdev operations
6058c2ecf20Sopenharmony_ci */
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_cistatic const unsigned int ccp2_fmts[] = {
6088c2ecf20Sopenharmony_ci	MEDIA_BUS_FMT_SGRBG10_1X10,
6098c2ecf20Sopenharmony_ci	MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8,
6108c2ecf20Sopenharmony_ci};
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci/*
6138c2ecf20Sopenharmony_ci * __ccp2_get_format - helper function for getting ccp2 format
6148c2ecf20Sopenharmony_ci * @ccp2  : Pointer to ISP CCP2 device
6158c2ecf20Sopenharmony_ci * @cfg: V4L2 subdev pad configuration
6168c2ecf20Sopenharmony_ci * @pad   : pad number
6178c2ecf20Sopenharmony_ci * @which : wanted subdev format
6188c2ecf20Sopenharmony_ci * return format structure or NULL on error
6198c2ecf20Sopenharmony_ci */
6208c2ecf20Sopenharmony_cistatic struct v4l2_mbus_framefmt *
6218c2ecf20Sopenharmony_ci__ccp2_get_format(struct isp_ccp2_device *ccp2, struct v4l2_subdev_pad_config *cfg,
6228c2ecf20Sopenharmony_ci		     unsigned int pad, enum v4l2_subdev_format_whence which)
6238c2ecf20Sopenharmony_ci{
6248c2ecf20Sopenharmony_ci	if (which == V4L2_SUBDEV_FORMAT_TRY)
6258c2ecf20Sopenharmony_ci		return v4l2_subdev_get_try_format(&ccp2->subdev, cfg, pad);
6268c2ecf20Sopenharmony_ci	else
6278c2ecf20Sopenharmony_ci		return &ccp2->formats[pad];
6288c2ecf20Sopenharmony_ci}
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci/*
6318c2ecf20Sopenharmony_ci * ccp2_try_format - Handle try format by pad subdev method
6328c2ecf20Sopenharmony_ci * @ccp2  : Pointer to ISP CCP2 device
6338c2ecf20Sopenharmony_ci * @cfg: V4L2 subdev pad configuration
6348c2ecf20Sopenharmony_ci * @pad   : pad num
6358c2ecf20Sopenharmony_ci * @fmt   : pointer to v4l2 mbus format structure
6368c2ecf20Sopenharmony_ci * @which : wanted subdev format
6378c2ecf20Sopenharmony_ci */
6388c2ecf20Sopenharmony_cistatic void ccp2_try_format(struct isp_ccp2_device *ccp2,
6398c2ecf20Sopenharmony_ci			       struct v4l2_subdev_pad_config *cfg, unsigned int pad,
6408c2ecf20Sopenharmony_ci			       struct v4l2_mbus_framefmt *fmt,
6418c2ecf20Sopenharmony_ci			       enum v4l2_subdev_format_whence which)
6428c2ecf20Sopenharmony_ci{
6438c2ecf20Sopenharmony_ci	struct v4l2_mbus_framefmt *format;
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_ci	switch (pad) {
6468c2ecf20Sopenharmony_ci	case CCP2_PAD_SINK:
6478c2ecf20Sopenharmony_ci		if (fmt->code != MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8)
6488c2ecf20Sopenharmony_ci			fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_ci		if (ccp2->input == CCP2_INPUT_SENSOR) {
6518c2ecf20Sopenharmony_ci			fmt->width = clamp_t(u32, fmt->width,
6528c2ecf20Sopenharmony_ci					     ISPCCP2_DAT_START_MIN,
6538c2ecf20Sopenharmony_ci					     ISPCCP2_DAT_START_MAX);
6548c2ecf20Sopenharmony_ci			fmt->height = clamp_t(u32, fmt->height,
6558c2ecf20Sopenharmony_ci					      ISPCCP2_DAT_SIZE_MIN,
6568c2ecf20Sopenharmony_ci					      ISPCCP2_DAT_SIZE_MAX);
6578c2ecf20Sopenharmony_ci		} else if (ccp2->input == CCP2_INPUT_MEMORY) {
6588c2ecf20Sopenharmony_ci			fmt->width = clamp_t(u32, fmt->width,
6598c2ecf20Sopenharmony_ci					     ISPCCP2_LCM_HSIZE_COUNT_MIN,
6608c2ecf20Sopenharmony_ci					     ISPCCP2_LCM_HSIZE_COUNT_MAX);
6618c2ecf20Sopenharmony_ci			fmt->height = clamp_t(u32, fmt->height,
6628c2ecf20Sopenharmony_ci					      ISPCCP2_LCM_VSIZE_MIN,
6638c2ecf20Sopenharmony_ci					      ISPCCP2_LCM_VSIZE_MAX);
6648c2ecf20Sopenharmony_ci		}
6658c2ecf20Sopenharmony_ci		break;
6668c2ecf20Sopenharmony_ci
6678c2ecf20Sopenharmony_ci	case CCP2_PAD_SOURCE:
6688c2ecf20Sopenharmony_ci		/* Source format - copy sink format and change pixel code
6698c2ecf20Sopenharmony_ci		 * to SGRBG10_1X10 as we don't support CCP2 write to memory.
6708c2ecf20Sopenharmony_ci		 * When CCP2 write to memory feature will be added this
6718c2ecf20Sopenharmony_ci		 * should be changed properly.
6728c2ecf20Sopenharmony_ci		 */
6738c2ecf20Sopenharmony_ci		format = __ccp2_get_format(ccp2, cfg, CCP2_PAD_SINK, which);
6748c2ecf20Sopenharmony_ci		memcpy(fmt, format, sizeof(*fmt));
6758c2ecf20Sopenharmony_ci		fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
6768c2ecf20Sopenharmony_ci		break;
6778c2ecf20Sopenharmony_ci	}
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_ci	fmt->field = V4L2_FIELD_NONE;
6808c2ecf20Sopenharmony_ci	fmt->colorspace = V4L2_COLORSPACE_SRGB;
6818c2ecf20Sopenharmony_ci}
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_ci/*
6848c2ecf20Sopenharmony_ci * ccp2_enum_mbus_code - Handle pixel format enumeration
6858c2ecf20Sopenharmony_ci * @sd     : pointer to v4l2 subdev structure
6868c2ecf20Sopenharmony_ci * @cfg: V4L2 subdev pad configuration
6878c2ecf20Sopenharmony_ci * @code   : pointer to v4l2_subdev_mbus_code_enum structure
6888c2ecf20Sopenharmony_ci * return -EINVAL or zero on success
6898c2ecf20Sopenharmony_ci */
6908c2ecf20Sopenharmony_cistatic int ccp2_enum_mbus_code(struct v4l2_subdev *sd,
6918c2ecf20Sopenharmony_ci				  struct v4l2_subdev_pad_config *cfg,
6928c2ecf20Sopenharmony_ci				  struct v4l2_subdev_mbus_code_enum *code)
6938c2ecf20Sopenharmony_ci{
6948c2ecf20Sopenharmony_ci	struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
6958c2ecf20Sopenharmony_ci	struct v4l2_mbus_framefmt *format;
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_ci	if (code->pad == CCP2_PAD_SINK) {
6988c2ecf20Sopenharmony_ci		if (code->index >= ARRAY_SIZE(ccp2_fmts))
6998c2ecf20Sopenharmony_ci			return -EINVAL;
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci		code->code = ccp2_fmts[code->index];
7028c2ecf20Sopenharmony_ci	} else {
7038c2ecf20Sopenharmony_ci		if (code->index != 0)
7048c2ecf20Sopenharmony_ci			return -EINVAL;
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ci		format = __ccp2_get_format(ccp2, cfg, CCP2_PAD_SINK,
7078c2ecf20Sopenharmony_ci					      code->which);
7088c2ecf20Sopenharmony_ci		code->code = format->code;
7098c2ecf20Sopenharmony_ci	}
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_ci	return 0;
7128c2ecf20Sopenharmony_ci}
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_cistatic int ccp2_enum_frame_size(struct v4l2_subdev *sd,
7158c2ecf20Sopenharmony_ci				   struct v4l2_subdev_pad_config *cfg,
7168c2ecf20Sopenharmony_ci				   struct v4l2_subdev_frame_size_enum *fse)
7178c2ecf20Sopenharmony_ci{
7188c2ecf20Sopenharmony_ci	struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
7198c2ecf20Sopenharmony_ci	struct v4l2_mbus_framefmt format;
7208c2ecf20Sopenharmony_ci
7218c2ecf20Sopenharmony_ci	if (fse->index != 0)
7228c2ecf20Sopenharmony_ci		return -EINVAL;
7238c2ecf20Sopenharmony_ci
7248c2ecf20Sopenharmony_ci	format.code = fse->code;
7258c2ecf20Sopenharmony_ci	format.width = 1;
7268c2ecf20Sopenharmony_ci	format.height = 1;
7278c2ecf20Sopenharmony_ci	ccp2_try_format(ccp2, cfg, fse->pad, &format, fse->which);
7288c2ecf20Sopenharmony_ci	fse->min_width = format.width;
7298c2ecf20Sopenharmony_ci	fse->min_height = format.height;
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci	if (format.code != fse->code)
7328c2ecf20Sopenharmony_ci		return -EINVAL;
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci	format.code = fse->code;
7358c2ecf20Sopenharmony_ci	format.width = -1;
7368c2ecf20Sopenharmony_ci	format.height = -1;
7378c2ecf20Sopenharmony_ci	ccp2_try_format(ccp2, cfg, fse->pad, &format, fse->which);
7388c2ecf20Sopenharmony_ci	fse->max_width = format.width;
7398c2ecf20Sopenharmony_ci	fse->max_height = format.height;
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_ci	return 0;
7428c2ecf20Sopenharmony_ci}
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_ci/*
7458c2ecf20Sopenharmony_ci * ccp2_get_format - Handle get format by pads subdev method
7468c2ecf20Sopenharmony_ci * @sd    : pointer to v4l2 subdev structure
7478c2ecf20Sopenharmony_ci * @cfg: V4L2 subdev pad configuration
7488c2ecf20Sopenharmony_ci * @fmt   : pointer to v4l2 subdev format structure
7498c2ecf20Sopenharmony_ci * return -EINVAL or zero on success
7508c2ecf20Sopenharmony_ci */
7518c2ecf20Sopenharmony_cistatic int ccp2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
7528c2ecf20Sopenharmony_ci			      struct v4l2_subdev_format *fmt)
7538c2ecf20Sopenharmony_ci{
7548c2ecf20Sopenharmony_ci	struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
7558c2ecf20Sopenharmony_ci	struct v4l2_mbus_framefmt *format;
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci	format = __ccp2_get_format(ccp2, cfg, fmt->pad, fmt->which);
7588c2ecf20Sopenharmony_ci	if (format == NULL)
7598c2ecf20Sopenharmony_ci		return -EINVAL;
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_ci	fmt->format = *format;
7628c2ecf20Sopenharmony_ci	return 0;
7638c2ecf20Sopenharmony_ci}
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci/*
7668c2ecf20Sopenharmony_ci * ccp2_set_format - Handle set format by pads subdev method
7678c2ecf20Sopenharmony_ci * @sd    : pointer to v4l2 subdev structure
7688c2ecf20Sopenharmony_ci * @cfg: V4L2 subdev pad configuration
7698c2ecf20Sopenharmony_ci * @fmt   : pointer to v4l2 subdev format structure
7708c2ecf20Sopenharmony_ci * returns zero
7718c2ecf20Sopenharmony_ci */
7728c2ecf20Sopenharmony_cistatic int ccp2_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
7738c2ecf20Sopenharmony_ci			      struct v4l2_subdev_format *fmt)
7748c2ecf20Sopenharmony_ci{
7758c2ecf20Sopenharmony_ci	struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
7768c2ecf20Sopenharmony_ci	struct v4l2_mbus_framefmt *format;
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci	format = __ccp2_get_format(ccp2, cfg, fmt->pad, fmt->which);
7798c2ecf20Sopenharmony_ci	if (format == NULL)
7808c2ecf20Sopenharmony_ci		return -EINVAL;
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_ci	ccp2_try_format(ccp2, cfg, fmt->pad, &fmt->format, fmt->which);
7838c2ecf20Sopenharmony_ci	*format = fmt->format;
7848c2ecf20Sopenharmony_ci
7858c2ecf20Sopenharmony_ci	/* Propagate the format from sink to source */
7868c2ecf20Sopenharmony_ci	if (fmt->pad == CCP2_PAD_SINK) {
7878c2ecf20Sopenharmony_ci		format = __ccp2_get_format(ccp2, cfg, CCP2_PAD_SOURCE,
7888c2ecf20Sopenharmony_ci					   fmt->which);
7898c2ecf20Sopenharmony_ci		*format = fmt->format;
7908c2ecf20Sopenharmony_ci		ccp2_try_format(ccp2, cfg, CCP2_PAD_SOURCE, format, fmt->which);
7918c2ecf20Sopenharmony_ci	}
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_ci	return 0;
7948c2ecf20Sopenharmony_ci}
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_ci/*
7978c2ecf20Sopenharmony_ci * ccp2_init_formats - Initialize formats on all pads
7988c2ecf20Sopenharmony_ci * @sd: ISP CCP2 V4L2 subdevice
7998c2ecf20Sopenharmony_ci * @fh: V4L2 subdev file handle
8008c2ecf20Sopenharmony_ci *
8018c2ecf20Sopenharmony_ci * Initialize all pad formats with default values. If fh is not NULL, try
8028c2ecf20Sopenharmony_ci * formats are initialized on the file handle. Otherwise active formats are
8038c2ecf20Sopenharmony_ci * initialized on the device.
8048c2ecf20Sopenharmony_ci */
8058c2ecf20Sopenharmony_cistatic int ccp2_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
8068c2ecf20Sopenharmony_ci{
8078c2ecf20Sopenharmony_ci	struct v4l2_subdev_format format;
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci	memset(&format, 0, sizeof(format));
8108c2ecf20Sopenharmony_ci	format.pad = CCP2_PAD_SINK;
8118c2ecf20Sopenharmony_ci	format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
8128c2ecf20Sopenharmony_ci	format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
8138c2ecf20Sopenharmony_ci	format.format.width = 4096;
8148c2ecf20Sopenharmony_ci	format.format.height = 4096;
8158c2ecf20Sopenharmony_ci	ccp2_set_format(sd, fh ? fh->pad : NULL, &format);
8168c2ecf20Sopenharmony_ci
8178c2ecf20Sopenharmony_ci	return 0;
8188c2ecf20Sopenharmony_ci}
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci/*
8218c2ecf20Sopenharmony_ci * ccp2_s_stream - Enable/Disable streaming on ccp2 subdev
8228c2ecf20Sopenharmony_ci * @sd    : pointer to v4l2 subdev structure
8238c2ecf20Sopenharmony_ci * @enable: 1 == Enable, 0 == Disable
8248c2ecf20Sopenharmony_ci * return zero
8258c2ecf20Sopenharmony_ci */
8268c2ecf20Sopenharmony_cistatic int ccp2_s_stream(struct v4l2_subdev *sd, int enable)
8278c2ecf20Sopenharmony_ci{
8288c2ecf20Sopenharmony_ci	struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
8298c2ecf20Sopenharmony_ci	struct isp_device *isp = to_isp_device(ccp2);
8308c2ecf20Sopenharmony_ci	struct device *dev = to_device(ccp2);
8318c2ecf20Sopenharmony_ci	int ret;
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci	if (ccp2->state == ISP_PIPELINE_STREAM_STOPPED) {
8348c2ecf20Sopenharmony_ci		if (enable == ISP_PIPELINE_STREAM_STOPPED)
8358c2ecf20Sopenharmony_ci			return 0;
8368c2ecf20Sopenharmony_ci		atomic_set(&ccp2->stopping, 0);
8378c2ecf20Sopenharmony_ci	}
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_ci	switch (enable) {
8408c2ecf20Sopenharmony_ci	case ISP_PIPELINE_STREAM_CONTINUOUS:
8418c2ecf20Sopenharmony_ci		if (ccp2->phy) {
8428c2ecf20Sopenharmony_ci			ret = omap3isp_csiphy_acquire(ccp2->phy, &sd->entity);
8438c2ecf20Sopenharmony_ci			if (ret < 0)
8448c2ecf20Sopenharmony_ci				return ret;
8458c2ecf20Sopenharmony_ci		}
8468c2ecf20Sopenharmony_ci
8478c2ecf20Sopenharmony_ci		ccp2_if_configure(ccp2);
8488c2ecf20Sopenharmony_ci		ccp2_print_status(ccp2);
8498c2ecf20Sopenharmony_ci
8508c2ecf20Sopenharmony_ci		/* Enable CSI1/CCP2 interface */
8518c2ecf20Sopenharmony_ci		ret = ccp2_if_enable(ccp2, 1);
8528c2ecf20Sopenharmony_ci		if (ret < 0) {
8538c2ecf20Sopenharmony_ci			if (ccp2->phy)
8548c2ecf20Sopenharmony_ci				omap3isp_csiphy_release(ccp2->phy);
8558c2ecf20Sopenharmony_ci			return ret;
8568c2ecf20Sopenharmony_ci		}
8578c2ecf20Sopenharmony_ci		break;
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_ci	case ISP_PIPELINE_STREAM_SINGLESHOT:
8608c2ecf20Sopenharmony_ci		if (ccp2->state != ISP_PIPELINE_STREAM_SINGLESHOT) {
8618c2ecf20Sopenharmony_ci			struct v4l2_mbus_framefmt *format;
8628c2ecf20Sopenharmony_ci
8638c2ecf20Sopenharmony_ci			format = &ccp2->formats[CCP2_PAD_SINK];
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_ci			ccp2->mem_cfg.hsize_count = format->width;
8668c2ecf20Sopenharmony_ci			ccp2->mem_cfg.vsize_count = format->height;
8678c2ecf20Sopenharmony_ci			ccp2->mem_cfg.src_ofst = 0;
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci			ccp2_mem_configure(ccp2, &ccp2->mem_cfg);
8708c2ecf20Sopenharmony_ci			omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CSI1_READ);
8718c2ecf20Sopenharmony_ci			ccp2_print_status(ccp2);
8728c2ecf20Sopenharmony_ci		}
8738c2ecf20Sopenharmony_ci		ccp2_mem_enable(ccp2, 1);
8748c2ecf20Sopenharmony_ci		break;
8758c2ecf20Sopenharmony_ci
8768c2ecf20Sopenharmony_ci	case ISP_PIPELINE_STREAM_STOPPED:
8778c2ecf20Sopenharmony_ci		if (omap3isp_module_sync_idle(&sd->entity, &ccp2->wait,
8788c2ecf20Sopenharmony_ci					      &ccp2->stopping))
8798c2ecf20Sopenharmony_ci			dev_dbg(dev, "%s: module stop timeout.\n", sd->name);
8808c2ecf20Sopenharmony_ci		if (ccp2->input == CCP2_INPUT_MEMORY) {
8818c2ecf20Sopenharmony_ci			ccp2_mem_enable(ccp2, 0);
8828c2ecf20Sopenharmony_ci			omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_CSI1_READ);
8838c2ecf20Sopenharmony_ci		} else if (ccp2->input == CCP2_INPUT_SENSOR) {
8848c2ecf20Sopenharmony_ci			/* Disable CSI1/CCP2 interface */
8858c2ecf20Sopenharmony_ci			ccp2_if_enable(ccp2, 0);
8868c2ecf20Sopenharmony_ci			if (ccp2->phy)
8878c2ecf20Sopenharmony_ci				omap3isp_csiphy_release(ccp2->phy);
8888c2ecf20Sopenharmony_ci		}
8898c2ecf20Sopenharmony_ci		break;
8908c2ecf20Sopenharmony_ci	}
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_ci	ccp2->state = enable;
8938c2ecf20Sopenharmony_ci	return 0;
8948c2ecf20Sopenharmony_ci}
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ci/* subdev video operations */
8978c2ecf20Sopenharmony_cistatic const struct v4l2_subdev_video_ops ccp2_sd_video_ops = {
8988c2ecf20Sopenharmony_ci	.s_stream = ccp2_s_stream,
8998c2ecf20Sopenharmony_ci};
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci/* subdev pad operations */
9028c2ecf20Sopenharmony_cistatic const struct v4l2_subdev_pad_ops ccp2_sd_pad_ops = {
9038c2ecf20Sopenharmony_ci	.enum_mbus_code = ccp2_enum_mbus_code,
9048c2ecf20Sopenharmony_ci	.enum_frame_size = ccp2_enum_frame_size,
9058c2ecf20Sopenharmony_ci	.get_fmt = ccp2_get_format,
9068c2ecf20Sopenharmony_ci	.set_fmt = ccp2_set_format,
9078c2ecf20Sopenharmony_ci};
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ci/* subdev operations */
9108c2ecf20Sopenharmony_cistatic const struct v4l2_subdev_ops ccp2_sd_ops = {
9118c2ecf20Sopenharmony_ci	.video = &ccp2_sd_video_ops,
9128c2ecf20Sopenharmony_ci	.pad = &ccp2_sd_pad_ops,
9138c2ecf20Sopenharmony_ci};
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_ci/* subdev internal operations */
9168c2ecf20Sopenharmony_cistatic const struct v4l2_subdev_internal_ops ccp2_sd_internal_ops = {
9178c2ecf20Sopenharmony_ci	.open = ccp2_init_formats,
9188c2ecf20Sopenharmony_ci};
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ci/* --------------------------------------------------------------------------
9218c2ecf20Sopenharmony_ci * ISP ccp2 video device node
9228c2ecf20Sopenharmony_ci */
9238c2ecf20Sopenharmony_ci
9248c2ecf20Sopenharmony_ci/*
9258c2ecf20Sopenharmony_ci * ccp2_video_queue - Queue video buffer.
9268c2ecf20Sopenharmony_ci * @video : Pointer to isp video structure
9278c2ecf20Sopenharmony_ci * @buffer: Pointer to isp_buffer structure
9288c2ecf20Sopenharmony_ci * return -EIO or zero on success
9298c2ecf20Sopenharmony_ci */
9308c2ecf20Sopenharmony_cistatic int ccp2_video_queue(struct isp_video *video, struct isp_buffer *buffer)
9318c2ecf20Sopenharmony_ci{
9328c2ecf20Sopenharmony_ci	struct isp_ccp2_device *ccp2 = &video->isp->isp_ccp2;
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_ci	ccp2_set_inaddr(ccp2, buffer->dma);
9358c2ecf20Sopenharmony_ci	return 0;
9368c2ecf20Sopenharmony_ci}
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_cistatic const struct isp_video_operations ccp2_video_ops = {
9398c2ecf20Sopenharmony_ci	.queue = ccp2_video_queue,
9408c2ecf20Sopenharmony_ci};
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci/* -----------------------------------------------------------------------------
9438c2ecf20Sopenharmony_ci * Media entity operations
9448c2ecf20Sopenharmony_ci */
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_ci/*
9478c2ecf20Sopenharmony_ci * ccp2_link_setup - Setup ccp2 connections.
9488c2ecf20Sopenharmony_ci * @entity : Pointer to media entity structure
9498c2ecf20Sopenharmony_ci * @local  : Pointer to local pad array
9508c2ecf20Sopenharmony_ci * @remote : Pointer to remote pad array
9518c2ecf20Sopenharmony_ci * @flags  : Link flags
9528c2ecf20Sopenharmony_ci * return -EINVAL on error or zero on success
9538c2ecf20Sopenharmony_ci */
9548c2ecf20Sopenharmony_cistatic int ccp2_link_setup(struct media_entity *entity,
9558c2ecf20Sopenharmony_ci			   const struct media_pad *local,
9568c2ecf20Sopenharmony_ci			   const struct media_pad *remote, u32 flags)
9578c2ecf20Sopenharmony_ci{
9588c2ecf20Sopenharmony_ci	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
9598c2ecf20Sopenharmony_ci	struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
9608c2ecf20Sopenharmony_ci	unsigned int index = local->index;
9618c2ecf20Sopenharmony_ci
9628c2ecf20Sopenharmony_ci	/* FIXME: this is actually a hack! */
9638c2ecf20Sopenharmony_ci	if (is_media_entity_v4l2_subdev(remote->entity))
9648c2ecf20Sopenharmony_ci		index |= 2 << 16;
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_ci	switch (index) {
9678c2ecf20Sopenharmony_ci	case CCP2_PAD_SINK:
9688c2ecf20Sopenharmony_ci		/* read from memory */
9698c2ecf20Sopenharmony_ci		if (flags & MEDIA_LNK_FL_ENABLED) {
9708c2ecf20Sopenharmony_ci			if (ccp2->input == CCP2_INPUT_SENSOR)
9718c2ecf20Sopenharmony_ci				return -EBUSY;
9728c2ecf20Sopenharmony_ci			ccp2->input = CCP2_INPUT_MEMORY;
9738c2ecf20Sopenharmony_ci		} else {
9748c2ecf20Sopenharmony_ci			if (ccp2->input == CCP2_INPUT_MEMORY)
9758c2ecf20Sopenharmony_ci				ccp2->input = CCP2_INPUT_NONE;
9768c2ecf20Sopenharmony_ci		}
9778c2ecf20Sopenharmony_ci		break;
9788c2ecf20Sopenharmony_ci
9798c2ecf20Sopenharmony_ci	case CCP2_PAD_SINK | 2 << 16:
9808c2ecf20Sopenharmony_ci		/* read from sensor/phy */
9818c2ecf20Sopenharmony_ci		if (flags & MEDIA_LNK_FL_ENABLED) {
9828c2ecf20Sopenharmony_ci			if (ccp2->input == CCP2_INPUT_MEMORY)
9838c2ecf20Sopenharmony_ci				return -EBUSY;
9848c2ecf20Sopenharmony_ci			ccp2->input = CCP2_INPUT_SENSOR;
9858c2ecf20Sopenharmony_ci		} else {
9868c2ecf20Sopenharmony_ci			if (ccp2->input == CCP2_INPUT_SENSOR)
9878c2ecf20Sopenharmony_ci				ccp2->input = CCP2_INPUT_NONE;
9888c2ecf20Sopenharmony_ci		} break;
9898c2ecf20Sopenharmony_ci
9908c2ecf20Sopenharmony_ci	case CCP2_PAD_SOURCE | 2 << 16:
9918c2ecf20Sopenharmony_ci		/* write to video port/ccdc */
9928c2ecf20Sopenharmony_ci		if (flags & MEDIA_LNK_FL_ENABLED)
9938c2ecf20Sopenharmony_ci			ccp2->output = CCP2_OUTPUT_CCDC;
9948c2ecf20Sopenharmony_ci		else
9958c2ecf20Sopenharmony_ci			ccp2->output = CCP2_OUTPUT_NONE;
9968c2ecf20Sopenharmony_ci		break;
9978c2ecf20Sopenharmony_ci
9988c2ecf20Sopenharmony_ci	default:
9998c2ecf20Sopenharmony_ci		return -EINVAL;
10008c2ecf20Sopenharmony_ci	}
10018c2ecf20Sopenharmony_ci
10028c2ecf20Sopenharmony_ci	return 0;
10038c2ecf20Sopenharmony_ci}
10048c2ecf20Sopenharmony_ci
10058c2ecf20Sopenharmony_ci/* media operations */
10068c2ecf20Sopenharmony_cistatic const struct media_entity_operations ccp2_media_ops = {
10078c2ecf20Sopenharmony_ci	.link_setup = ccp2_link_setup,
10088c2ecf20Sopenharmony_ci	.link_validate = v4l2_subdev_link_validate,
10098c2ecf20Sopenharmony_ci};
10108c2ecf20Sopenharmony_ci
10118c2ecf20Sopenharmony_ci/*
10128c2ecf20Sopenharmony_ci * omap3isp_ccp2_unregister_entities - Unregister media entities: subdev
10138c2ecf20Sopenharmony_ci * @ccp2: Pointer to ISP CCP2 device
10148c2ecf20Sopenharmony_ci */
10158c2ecf20Sopenharmony_civoid omap3isp_ccp2_unregister_entities(struct isp_ccp2_device *ccp2)
10168c2ecf20Sopenharmony_ci{
10178c2ecf20Sopenharmony_ci	v4l2_device_unregister_subdev(&ccp2->subdev);
10188c2ecf20Sopenharmony_ci	omap3isp_video_unregister(&ccp2->video_in);
10198c2ecf20Sopenharmony_ci}
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_ci/*
10228c2ecf20Sopenharmony_ci * omap3isp_ccp2_register_entities - Register the subdev media entity
10238c2ecf20Sopenharmony_ci * @ccp2: Pointer to ISP CCP2 device
10248c2ecf20Sopenharmony_ci * @vdev: Pointer to v4l device
10258c2ecf20Sopenharmony_ci * return negative error code or zero on success
10268c2ecf20Sopenharmony_ci */
10278c2ecf20Sopenharmony_ci
10288c2ecf20Sopenharmony_ciint omap3isp_ccp2_register_entities(struct isp_ccp2_device *ccp2,
10298c2ecf20Sopenharmony_ci				    struct v4l2_device *vdev)
10308c2ecf20Sopenharmony_ci{
10318c2ecf20Sopenharmony_ci	int ret;
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_ci	/* Register the subdev and video nodes. */
10348c2ecf20Sopenharmony_ci	ccp2->subdev.dev = vdev->mdev->dev;
10358c2ecf20Sopenharmony_ci	ret = v4l2_device_register_subdev(vdev, &ccp2->subdev);
10368c2ecf20Sopenharmony_ci	if (ret < 0)
10378c2ecf20Sopenharmony_ci		goto error;
10388c2ecf20Sopenharmony_ci
10398c2ecf20Sopenharmony_ci	ret = omap3isp_video_register(&ccp2->video_in, vdev);
10408c2ecf20Sopenharmony_ci	if (ret < 0)
10418c2ecf20Sopenharmony_ci		goto error;
10428c2ecf20Sopenharmony_ci
10438c2ecf20Sopenharmony_ci	return 0;
10448c2ecf20Sopenharmony_ci
10458c2ecf20Sopenharmony_cierror:
10468c2ecf20Sopenharmony_ci	omap3isp_ccp2_unregister_entities(ccp2);
10478c2ecf20Sopenharmony_ci	return ret;
10488c2ecf20Sopenharmony_ci}
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_ci/* -----------------------------------------------------------------------------
10518c2ecf20Sopenharmony_ci * ISP ccp2 initialisation and cleanup
10528c2ecf20Sopenharmony_ci */
10538c2ecf20Sopenharmony_ci
10548c2ecf20Sopenharmony_ci/*
10558c2ecf20Sopenharmony_ci * ccp2_init_entities - Initialize ccp2 subdev and media entity.
10568c2ecf20Sopenharmony_ci * @ccp2: Pointer to ISP CCP2 device
10578c2ecf20Sopenharmony_ci * return negative error code or zero on success
10588c2ecf20Sopenharmony_ci */
10598c2ecf20Sopenharmony_cistatic int ccp2_init_entities(struct isp_ccp2_device *ccp2)
10608c2ecf20Sopenharmony_ci{
10618c2ecf20Sopenharmony_ci	struct v4l2_subdev *sd = &ccp2->subdev;
10628c2ecf20Sopenharmony_ci	struct media_pad *pads = ccp2->pads;
10638c2ecf20Sopenharmony_ci	struct media_entity *me = &sd->entity;
10648c2ecf20Sopenharmony_ci	int ret;
10658c2ecf20Sopenharmony_ci
10668c2ecf20Sopenharmony_ci	ccp2->input = CCP2_INPUT_NONE;
10678c2ecf20Sopenharmony_ci	ccp2->output = CCP2_OUTPUT_NONE;
10688c2ecf20Sopenharmony_ci
10698c2ecf20Sopenharmony_ci	v4l2_subdev_init(sd, &ccp2_sd_ops);
10708c2ecf20Sopenharmony_ci	sd->internal_ops = &ccp2_sd_internal_ops;
10718c2ecf20Sopenharmony_ci	strscpy(sd->name, "OMAP3 ISP CCP2", sizeof(sd->name));
10728c2ecf20Sopenharmony_ci	sd->grp_id = 1 << 16;   /* group ID for isp subdevs */
10738c2ecf20Sopenharmony_ci	v4l2_set_subdevdata(sd, ccp2);
10748c2ecf20Sopenharmony_ci	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_ci	pads[CCP2_PAD_SINK].flags = MEDIA_PAD_FL_SINK
10778c2ecf20Sopenharmony_ci				    | MEDIA_PAD_FL_MUST_CONNECT;
10788c2ecf20Sopenharmony_ci	pads[CCP2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
10798c2ecf20Sopenharmony_ci
10808c2ecf20Sopenharmony_ci	me->ops = &ccp2_media_ops;
10818c2ecf20Sopenharmony_ci	ret = media_entity_pads_init(me, CCP2_PADS_NUM, pads);
10828c2ecf20Sopenharmony_ci	if (ret < 0)
10838c2ecf20Sopenharmony_ci		return ret;
10848c2ecf20Sopenharmony_ci
10858c2ecf20Sopenharmony_ci	ccp2_init_formats(sd, NULL);
10868c2ecf20Sopenharmony_ci
10878c2ecf20Sopenharmony_ci	/*
10888c2ecf20Sopenharmony_ci	 * The CCP2 has weird line alignment requirements, possibly caused by
10898c2ecf20Sopenharmony_ci	 * DPCM8 decompression. Line length for data read from memory must be a
10908c2ecf20Sopenharmony_ci	 * multiple of 128 bits (16 bytes) in continuous mode (when no padding
10918c2ecf20Sopenharmony_ci	 * is present at end of lines). Additionally, if padding is used, the
10928c2ecf20Sopenharmony_ci	 * padded line length must be a multiple of 32 bytes. To simplify the
10938c2ecf20Sopenharmony_ci	 * implementation we use a fixed 32 bytes alignment regardless of the
10948c2ecf20Sopenharmony_ci	 * input format and width. If strict 128 bits alignment support is
10958c2ecf20Sopenharmony_ci	 * required ispvideo will need to be made aware of this special dual
10968c2ecf20Sopenharmony_ci	 * alignment requirements.
10978c2ecf20Sopenharmony_ci	 */
10988c2ecf20Sopenharmony_ci	ccp2->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
10998c2ecf20Sopenharmony_ci	ccp2->video_in.bpl_alignment = 32;
11008c2ecf20Sopenharmony_ci	ccp2->video_in.bpl_max = 0xffffffe0;
11018c2ecf20Sopenharmony_ci	ccp2->video_in.isp = to_isp_device(ccp2);
11028c2ecf20Sopenharmony_ci	ccp2->video_in.ops = &ccp2_video_ops;
11038c2ecf20Sopenharmony_ci	ccp2->video_in.capture_mem = PAGE_ALIGN(4096 * 4096) * 3;
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_ci	ret = omap3isp_video_init(&ccp2->video_in, "CCP2");
11068c2ecf20Sopenharmony_ci	if (ret < 0)
11078c2ecf20Sopenharmony_ci		goto error;
11088c2ecf20Sopenharmony_ci
11098c2ecf20Sopenharmony_ci	return 0;
11108c2ecf20Sopenharmony_ci
11118c2ecf20Sopenharmony_cierror:
11128c2ecf20Sopenharmony_ci	media_entity_cleanup(&ccp2->subdev.entity);
11138c2ecf20Sopenharmony_ci	return ret;
11148c2ecf20Sopenharmony_ci}
11158c2ecf20Sopenharmony_ci
11168c2ecf20Sopenharmony_ci/*
11178c2ecf20Sopenharmony_ci * omap3isp_ccp2_init - CCP2 initialization.
11188c2ecf20Sopenharmony_ci * @isp : Pointer to ISP device
11198c2ecf20Sopenharmony_ci * return negative error code or zero on success
11208c2ecf20Sopenharmony_ci */
11218c2ecf20Sopenharmony_ciint omap3isp_ccp2_init(struct isp_device *isp)
11228c2ecf20Sopenharmony_ci{
11238c2ecf20Sopenharmony_ci	struct isp_ccp2_device *ccp2 = &isp->isp_ccp2;
11248c2ecf20Sopenharmony_ci	int ret;
11258c2ecf20Sopenharmony_ci
11268c2ecf20Sopenharmony_ci	init_waitqueue_head(&ccp2->wait);
11278c2ecf20Sopenharmony_ci
11288c2ecf20Sopenharmony_ci	/*
11298c2ecf20Sopenharmony_ci	 * On the OMAP34xx the CSI1 receiver is operated in the CSIb IO
11308c2ecf20Sopenharmony_ci	 * complex, which is powered by vdds_csib power rail. Hence the
11318c2ecf20Sopenharmony_ci	 * request for the regulator.
11328c2ecf20Sopenharmony_ci	 *
11338c2ecf20Sopenharmony_ci	 * On the OMAP36xx, the CCP2 uses the CSI PHY1 or PHY2, shared with
11348c2ecf20Sopenharmony_ci	 * the CSI2c or CSI2a receivers. The PHY then needs to be explicitly
11358c2ecf20Sopenharmony_ci	 * configured.
11368c2ecf20Sopenharmony_ci	 *
11378c2ecf20Sopenharmony_ci	 * TODO: Don't hardcode the usage of PHY1 (shared with CSI2c).
11388c2ecf20Sopenharmony_ci	 */
11398c2ecf20Sopenharmony_ci	if (isp->revision == ISP_REVISION_2_0) {
11408c2ecf20Sopenharmony_ci		ccp2->vdds_csib = devm_regulator_get(isp->dev, "vdds_csib");
11418c2ecf20Sopenharmony_ci		if (IS_ERR(ccp2->vdds_csib)) {
11428c2ecf20Sopenharmony_ci			if (PTR_ERR(ccp2->vdds_csib) == -EPROBE_DEFER) {
11438c2ecf20Sopenharmony_ci				dev_dbg(isp->dev,
11448c2ecf20Sopenharmony_ci					"Can't get regulator vdds_csib, deferring probing\n");
11458c2ecf20Sopenharmony_ci				return -EPROBE_DEFER;
11468c2ecf20Sopenharmony_ci			}
11478c2ecf20Sopenharmony_ci			dev_dbg(isp->dev,
11488c2ecf20Sopenharmony_ci				"Could not get regulator vdds_csib\n");
11498c2ecf20Sopenharmony_ci			ccp2->vdds_csib = NULL;
11508c2ecf20Sopenharmony_ci		}
11518c2ecf20Sopenharmony_ci		ccp2->phy = &isp->isp_csiphy2;
11528c2ecf20Sopenharmony_ci	} else if (isp->revision == ISP_REVISION_15_0) {
11538c2ecf20Sopenharmony_ci		ccp2->phy = &isp->isp_csiphy1;
11548c2ecf20Sopenharmony_ci	}
11558c2ecf20Sopenharmony_ci
11568c2ecf20Sopenharmony_ci	ret = ccp2_init_entities(ccp2);
11578c2ecf20Sopenharmony_ci	if (ret < 0)
11588c2ecf20Sopenharmony_ci		return ret;
11598c2ecf20Sopenharmony_ci
11608c2ecf20Sopenharmony_ci	ccp2_reset(ccp2);
11618c2ecf20Sopenharmony_ci	return 0;
11628c2ecf20Sopenharmony_ci}
11638c2ecf20Sopenharmony_ci
11648c2ecf20Sopenharmony_ci/*
11658c2ecf20Sopenharmony_ci * omap3isp_ccp2_cleanup - CCP2 un-initialization
11668c2ecf20Sopenharmony_ci * @isp : Pointer to ISP device
11678c2ecf20Sopenharmony_ci */
11688c2ecf20Sopenharmony_civoid omap3isp_ccp2_cleanup(struct isp_device *isp)
11698c2ecf20Sopenharmony_ci{
11708c2ecf20Sopenharmony_ci	struct isp_ccp2_device *ccp2 = &isp->isp_ccp2;
11718c2ecf20Sopenharmony_ci
11728c2ecf20Sopenharmony_ci	omap3isp_video_cleanup(&ccp2->video_in);
11738c2ecf20Sopenharmony_ci	media_entity_cleanup(&ccp2->subdev.entity);
11748c2ecf20Sopenharmony_ci}
1175