1183 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * ispccp2.c4 *5 * TI OMAP3 ISP - CCP2 module6 *7 * Copyright (C) 2010 Nokia Corporation8 * Copyright (C) 2010 Texas Instruments, Inc.9 *10 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>11 * Sakari Ailus <sakari.ailus@iki.fi>12 */13 14#include <linux/delay.h>15#include <linux/device.h>16#include <linux/mm.h>17#include <linux/module.h>18#include <linux/mutex.h>19#include <linux/uaccess.h>20#include <linux/regulator/consumer.h>21 22#include "isp.h"23#include "ispreg.h"24#include "ispccp2.h"25 26/* Number of LCX channels */27#define CCP2_LCx_CHANS_NUM 328/* Max/Min size for CCP2 video port */29#define ISPCCP2_DAT_START_MIN 030#define ISPCCP2_DAT_START_MAX 409531#define ISPCCP2_DAT_SIZE_MIN 032#define ISPCCP2_DAT_SIZE_MAX 409533#define ISPCCP2_VPCLK_FRACDIV 6553634#define ISPCCP2_LCx_CTRL_FORMAT_RAW8_DPCM10_VP 0x1235#define ISPCCP2_LCx_CTRL_FORMAT_RAW10_VP 0x1636/* Max/Min size for CCP2 memory channel */37#define ISPCCP2_LCM_HSIZE_COUNT_MIN 1638#define ISPCCP2_LCM_HSIZE_COUNT_MAX 819139#define ISPCCP2_LCM_HSIZE_SKIP_MIN 040#define ISPCCP2_LCM_HSIZE_SKIP_MAX 819141#define ISPCCP2_LCM_VSIZE_MIN 142#define ISPCCP2_LCM_VSIZE_MAX 819143#define ISPCCP2_LCM_HWORDS_MIN 144#define ISPCCP2_LCM_HWORDS_MAX 409545#define ISPCCP2_LCM_CTRL_BURST_SIZE_32X 546#define ISPCCP2_LCM_CTRL_READ_THROTTLE_FULL 047#define ISPCCP2_LCM_CTRL_SRC_DECOMPR_DPCM10 248#define ISPCCP2_LCM_CTRL_SRC_FORMAT_RAW8 249#define ISPCCP2_LCM_CTRL_SRC_FORMAT_RAW10 350#define ISPCCP2_LCM_CTRL_DST_FORMAT_RAW10 351#define ISPCCP2_LCM_CTRL_DST_PORT_VP 052#define ISPCCP2_LCM_CTRL_DST_PORT_MEM 153 54/* Set only the required bits */55#define BIT_SET(var, shift, mask, val) \56 do { \57 var = ((var) & ~((mask) << (shift))) \58 | ((val) << (shift)); \59 } while (0)60 61/*62 * ccp2_print_status - Print current CCP2 module register values.63 */64#define CCP2_PRINT_REGISTER(isp, name)\65 dev_dbg(isp->dev, "###CCP2 " #name "=0x%08x\n", \66 isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_##name))67 68static void ccp2_print_status(struct isp_ccp2_device *ccp2)69{70 struct isp_device *isp = to_isp_device(ccp2);71 72 dev_dbg(isp->dev, "-------------CCP2 Register dump-------------\n");73 74 CCP2_PRINT_REGISTER(isp, SYSCONFIG);75 CCP2_PRINT_REGISTER(isp, SYSSTATUS);76 CCP2_PRINT_REGISTER(isp, LC01_IRQENABLE);77 CCP2_PRINT_REGISTER(isp, LC01_IRQSTATUS);78 CCP2_PRINT_REGISTER(isp, LC23_IRQENABLE);79 CCP2_PRINT_REGISTER(isp, LC23_IRQSTATUS);80 CCP2_PRINT_REGISTER(isp, LCM_IRQENABLE);81 CCP2_PRINT_REGISTER(isp, LCM_IRQSTATUS);82 CCP2_PRINT_REGISTER(isp, CTRL);83 CCP2_PRINT_REGISTER(isp, LCx_CTRL(0));84 CCP2_PRINT_REGISTER(isp, LCx_CODE(0));85 CCP2_PRINT_REGISTER(isp, LCx_STAT_START(0));86 CCP2_PRINT_REGISTER(isp, LCx_STAT_SIZE(0));87 CCP2_PRINT_REGISTER(isp, LCx_SOF_ADDR(0));88 CCP2_PRINT_REGISTER(isp, LCx_EOF_ADDR(0));89 CCP2_PRINT_REGISTER(isp, LCx_DAT_START(0));90 CCP2_PRINT_REGISTER(isp, LCx_DAT_SIZE(0));91 CCP2_PRINT_REGISTER(isp, LCx_DAT_PING_ADDR(0));92 CCP2_PRINT_REGISTER(isp, LCx_DAT_PONG_ADDR(0));93 CCP2_PRINT_REGISTER(isp, LCx_DAT_OFST(0));94 CCP2_PRINT_REGISTER(isp, LCM_CTRL);95 CCP2_PRINT_REGISTER(isp, LCM_VSIZE);96 CCP2_PRINT_REGISTER(isp, LCM_HSIZE);97 CCP2_PRINT_REGISTER(isp, LCM_PREFETCH);98 CCP2_PRINT_REGISTER(isp, LCM_SRC_ADDR);99 CCP2_PRINT_REGISTER(isp, LCM_SRC_OFST);100 CCP2_PRINT_REGISTER(isp, LCM_DST_ADDR);101 CCP2_PRINT_REGISTER(isp, LCM_DST_OFST);102 103 dev_dbg(isp->dev, "--------------------------------------------\n");104}105 106/*107 * ccp2_reset - Reset the CCP2108 * @ccp2: pointer to ISP CCP2 device109 */110static void ccp2_reset(struct isp_ccp2_device *ccp2)111{112 struct isp_device *isp = to_isp_device(ccp2);113 int i = 0;114 115 /* Reset the CSI1/CCP2B and wait for reset to complete */116 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_SYSCONFIG,117 ISPCCP2_SYSCONFIG_SOFT_RESET);118 while (!(isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_SYSSTATUS) &119 ISPCCP2_SYSSTATUS_RESET_DONE)) {120 udelay(10);121 if (i++ > 10) { /* try read 10 times */122 dev_warn(isp->dev,123 "omap3_isp: timeout waiting for ccp2 reset\n");124 break;125 }126 }127}128 129/*130 * ccp2_pwr_cfg - Configure the power mode settings131 * @ccp2: pointer to ISP CCP2 device132 */133static void ccp2_pwr_cfg(struct isp_ccp2_device *ccp2)134{135 struct isp_device *isp = to_isp_device(ccp2);136 137 isp_reg_writel(isp, ISPCCP2_SYSCONFIG_MSTANDBY_MODE_SMART |138 ((isp->revision == ISP_REVISION_15_0 && isp->autoidle) ?139 ISPCCP2_SYSCONFIG_AUTO_IDLE : 0),140 OMAP3_ISP_IOMEM_CCP2, ISPCCP2_SYSCONFIG);141}142 143/*144 * ccp2_if_enable - Enable CCP2 interface.145 * @ccp2: pointer to ISP CCP2 device146 * @enable: enable/disable flag147 */148static int ccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable)149{150 struct isp_device *isp = to_isp_device(ccp2);151 int ret;152 int i;153 154 if (enable && ccp2->vdds_csib) {155 ret = regulator_enable(ccp2->vdds_csib);156 if (ret < 0)157 return ret;158 }159 160 /* Enable/Disable all the LCx channels */161 for (i = 0; i < CCP2_LCx_CHANS_NUM; i++)162 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(i),163 ISPCCP2_LCx_CTRL_CHAN_EN,164 enable ? ISPCCP2_LCx_CTRL_CHAN_EN : 0);165 166 /* Enable/Disable ccp2 interface in ccp2 mode */167 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL,168 ISPCCP2_CTRL_MODE | ISPCCP2_CTRL_IF_EN,169 enable ? (ISPCCP2_CTRL_MODE | ISPCCP2_CTRL_IF_EN) : 0);170 171 if (!enable && ccp2->vdds_csib)172 regulator_disable(ccp2->vdds_csib);173 174 return 0;175}176 177/*178 * ccp2_mem_enable - Enable CCP2 memory interface.179 * @ccp2: pointer to ISP CCP2 device180 * @enable: enable/disable flag181 */182static void ccp2_mem_enable(struct isp_ccp2_device *ccp2, u8 enable)183{184 struct isp_device *isp = to_isp_device(ccp2);185 186 if (enable)187 ccp2_if_enable(ccp2, 0);188 189 /* Enable/Disable ccp2 interface in ccp2 mode */190 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL,191 ISPCCP2_CTRL_MODE, enable ? ISPCCP2_CTRL_MODE : 0);192 193 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_CTRL,194 ISPCCP2_LCM_CTRL_CHAN_EN,195 enable ? ISPCCP2_LCM_CTRL_CHAN_EN : 0);196}197 198/*199 * ccp2_phyif_config - Initialize CCP2 phy interface config200 * @ccp2: Pointer to ISP CCP2 device201 * @buscfg: CCP2 platform data202 *203 * Configure the CCP2 physical interface module from platform data.204 *205 * Returns -EIO if strobe is chosen in CSI1 mode, or 0 on success.206 */207static int ccp2_phyif_config(struct isp_ccp2_device *ccp2,208 const struct isp_ccp2_cfg *buscfg)209{210 struct isp_device *isp = to_isp_device(ccp2);211 u32 val;212 213 val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL) |214 ISPCCP2_CTRL_MODE;215 /* Data/strobe physical layer */216 BIT_SET(val, ISPCCP2_CTRL_PHY_SEL_SHIFT, ISPCCP2_CTRL_PHY_SEL_MASK,217 buscfg->phy_layer);218 BIT_SET(val, ISPCCP2_CTRL_IO_OUT_SEL_SHIFT,219 ISPCCP2_CTRL_IO_OUT_SEL_MASK, buscfg->ccp2_mode);220 BIT_SET(val, ISPCCP2_CTRL_INV_SHIFT, ISPCCP2_CTRL_INV_MASK,221 buscfg->strobe_clk_pol);222 BIT_SET(val, ISPCCP2_CTRL_VP_CLK_POL_SHIFT,223 ISPCCP2_CTRL_VP_CLK_POL_MASK, buscfg->vp_clk_pol);224 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);225 226 val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);227 if (!(val & ISPCCP2_CTRL_MODE)) {228 if (buscfg->ccp2_mode == ISP_CCP2_MODE_CCP2)229 dev_warn(isp->dev, "OMAP3 CCP2 bus not available\n");230 if (buscfg->phy_layer == ISP_CCP2_PHY_DATA_STROBE)231 /* Strobe mode requires CCP2 */232 return -EIO;233 }234 235 return 0;236}237 238/*239 * ccp2_vp_config - Initialize CCP2 video port interface.240 * @ccp2: Pointer to ISP CCP2 device241 * @vpclk_div: Video port divisor242 *243 * Configure the CCP2 video port with the given clock divisor. The valid divisor244 * values depend on the ISP revision:245 *246 * - revision 1.0 and 2.0 1 to 4247 * - revision 15.0 1 to 65536248 *249 * The exact divisor value used might differ from the requested value, as ISP250 * revision 15.0 represent the divisor by 65536 divided by an integer.251 */252static void ccp2_vp_config(struct isp_ccp2_device *ccp2,253 unsigned int vpclk_div)254{255 struct isp_device *isp = to_isp_device(ccp2);256 u32 val;257 258 /* ISPCCP2_CTRL Video port */259 val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);260 val |= ISPCCP2_CTRL_VP_ONLY_EN; /* Disable the memory write port */261 262 if (isp->revision == ISP_REVISION_15_0) {263 vpclk_div = clamp_t(unsigned int, vpclk_div, 1, 65536);264 vpclk_div = min(ISPCCP2_VPCLK_FRACDIV / vpclk_div, 65535U);265 BIT_SET(val, ISPCCP2_CTRL_VPCLK_DIV_SHIFT,266 ISPCCP2_CTRL_VPCLK_DIV_MASK, vpclk_div);267 } else {268 vpclk_div = clamp_t(unsigned int, vpclk_div, 1, 4);269 BIT_SET(val, ISPCCP2_CTRL_VP_OUT_CTRL_SHIFT,270 ISPCCP2_CTRL_VP_OUT_CTRL_MASK, vpclk_div - 1);271 }272 273 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);274}275 276/*277 * ccp2_lcx_config - Initialize CCP2 logical channel interface.278 * @ccp2: Pointer to ISP CCP2 device279 * @config: Pointer to ISP LCx config structure.280 *281 * This will analyze the parameters passed by the interface config282 * and configure CSI1/CCP2 logical channel283 *284 */285static void ccp2_lcx_config(struct isp_ccp2_device *ccp2,286 struct isp_interface_lcx_config *config)287{288 struct isp_device *isp = to_isp_device(ccp2);289 u32 val, format;290 291 switch (config->format) {292 case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8:293 format = ISPCCP2_LCx_CTRL_FORMAT_RAW8_DPCM10_VP;294 break;295 case MEDIA_BUS_FMT_SGRBG10_1X10:296 default:297 format = ISPCCP2_LCx_CTRL_FORMAT_RAW10_VP; /* RAW10+VP */298 break;299 }300 /* ISPCCP2_LCx_CTRL logical channel #0 */301 val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(0))302 | (ISPCCP2_LCx_CTRL_REGION_EN); /* Region */303 304 if (isp->revision == ISP_REVISION_15_0) {305 /* CRC */306 BIT_SET(val, ISPCCP2_LCx_CTRL_CRC_SHIFT_15_0,307 ISPCCP2_LCx_CTRL_CRC_MASK,308 config->crc);309 /* Format = RAW10+VP or RAW8+DPCM10+VP*/310 BIT_SET(val, ISPCCP2_LCx_CTRL_FORMAT_SHIFT_15_0,311 ISPCCP2_LCx_CTRL_FORMAT_MASK_15_0, format);312 } else {313 BIT_SET(val, ISPCCP2_LCx_CTRL_CRC_SHIFT,314 ISPCCP2_LCx_CTRL_CRC_MASK,315 config->crc);316 317 BIT_SET(val, ISPCCP2_LCx_CTRL_FORMAT_SHIFT,318 ISPCCP2_LCx_CTRL_FORMAT_MASK, format);319 }320 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(0));321 322 /* ISPCCP2_DAT_START for logical channel #0 */323 isp_reg_writel(isp, config->data_start << ISPCCP2_LCx_DAT_SHIFT,324 OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_DAT_START(0));325 326 /* ISPCCP2_DAT_SIZE for logical channel #0 */327 isp_reg_writel(isp, config->data_size << ISPCCP2_LCx_DAT_SHIFT,328 OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_DAT_SIZE(0));329 330 /* Enable error IRQs for logical channel #0 */331 val = ISPCCP2_LC01_IRQSTATUS_LC0_FIFO_OVF_IRQ |332 ISPCCP2_LC01_IRQSTATUS_LC0_CRC_IRQ |333 ISPCCP2_LC01_IRQSTATUS_LC0_FSP_IRQ |334 ISPCCP2_LC01_IRQSTATUS_LC0_FW_IRQ |335 ISPCCP2_LC01_IRQSTATUS_LC0_FSC_IRQ |336 ISPCCP2_LC01_IRQSTATUS_LC0_SSC_IRQ;337 338 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LC01_IRQSTATUS);339 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LC01_IRQENABLE, val);340}341 342/*343 * ccp2_if_configure - Configure ccp2 with data from sensor344 * @ccp2: Pointer to ISP CCP2 device345 *346 * Return 0 on success or a negative error code347 */348static int ccp2_if_configure(struct isp_ccp2_device *ccp2)349{350 struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);351 const struct isp_bus_cfg *buscfg;352 struct v4l2_mbus_framefmt *format;353 struct media_pad *pad;354 struct v4l2_subdev *sensor;355 u32 lines = 0;356 int ret;357 358 ccp2_pwr_cfg(ccp2);359 360 pad = media_pad_remote_pad_first(&ccp2->pads[CCP2_PAD_SINK]);361 sensor = media_entity_to_v4l2_subdev(pad->entity);362 buscfg = v4l2_subdev_to_bus_cfg(pipe->external);363 if (WARN_ON(!buscfg))364 return -EPIPE;365 366 ret = ccp2_phyif_config(ccp2, &buscfg->bus.ccp2);367 if (ret < 0)368 return ret;369 370 ccp2_vp_config(ccp2, buscfg->bus.ccp2.vpclk_div + 1);371 372 v4l2_subdev_call(sensor, sensor, g_skip_top_lines, &lines);373 374 format = &ccp2->formats[CCP2_PAD_SINK];375 376 ccp2->if_cfg.data_start = lines;377 ccp2->if_cfg.crc = buscfg->bus.ccp2.crc;378 ccp2->if_cfg.format = format->code;379 ccp2->if_cfg.data_size = format->height;380 381 ccp2_lcx_config(ccp2, &ccp2->if_cfg);382 383 return 0;384}385 386static int ccp2_adjust_bandwidth(struct isp_ccp2_device *ccp2)387{388 struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);389 struct isp_device *isp = to_isp_device(ccp2);390 const struct v4l2_mbus_framefmt *ofmt = &ccp2->formats[CCP2_PAD_SOURCE];391 unsigned long l3_ick = pipe->l3_ick;392 struct v4l2_fract *timeperframe;393 unsigned int vpclk_div = 2;394 unsigned int value;395 u64 bound;396 u64 area;397 398 /* Compute the minimum clock divisor, based on the pipeline maximum399 * data rate. This is an absolute lower bound if we don't want SBL400 * overflows, so round the value up.401 */402 vpclk_div = max_t(unsigned int, DIV_ROUND_UP(l3_ick, pipe->max_rate),403 vpclk_div);404 405 /* Compute the maximum clock divisor, based on the requested frame rate.406 * This is a soft lower bound to achieve a frame rate equal or higher407 * than the requested value, so round the value down.408 */409 timeperframe = &pipe->max_timeperframe;410 411 if (timeperframe->numerator) {412 area = ofmt->width * ofmt->height;413 bound = div_u64(area * timeperframe->denominator,414 timeperframe->numerator);415 value = min_t(u64, bound, l3_ick);416 vpclk_div = max_t(unsigned int, l3_ick / value, vpclk_div);417 }418 419 dev_dbg(isp->dev, "%s: minimum clock divisor = %u\n", __func__,420 vpclk_div);421 422 return vpclk_div;423}424 425/*426 * ccp2_mem_configure - Initialize CCP2 memory input/output interface427 * @ccp2: Pointer to ISP CCP2 device428 * @config: Pointer to ISP mem interface config structure429 *430 * This will analyze the parameters passed by the interface config431 * structure, and configure the respective registers for proper432 * CSI1/CCP2 memory input.433 */434static void ccp2_mem_configure(struct isp_ccp2_device *ccp2,435 struct isp_interface_mem_config *config)436{437 struct isp_device *isp = to_isp_device(ccp2);438 u32 sink_pixcode = ccp2->formats[CCP2_PAD_SINK].code;439 u32 source_pixcode = ccp2->formats[CCP2_PAD_SOURCE].code;440 unsigned int dpcm_decompress = 0;441 u32 val, hwords;442 443 if (sink_pixcode != source_pixcode &&444 sink_pixcode == MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8)445 dpcm_decompress = 1;446 447 ccp2_pwr_cfg(ccp2);448 449 /* Hsize, Skip */450 isp_reg_writel(isp, ISPCCP2_LCM_HSIZE_SKIP_MIN |451 (config->hsize_count << ISPCCP2_LCM_HSIZE_SHIFT),452 OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_HSIZE);453 454 /* Vsize, no. of lines */455 isp_reg_writel(isp, config->vsize_count << ISPCCP2_LCM_VSIZE_SHIFT,456 OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_VSIZE);457 458 if (ccp2->video_in.bpl_padding == 0)459 config->src_ofst = 0;460 else461 config->src_ofst = ccp2->video_in.bpl_value;462 463 isp_reg_writel(isp, config->src_ofst, OMAP3_ISP_IOMEM_CCP2,464 ISPCCP2_LCM_SRC_OFST);465 466 /* Source and Destination formats */467 val = ISPCCP2_LCM_CTRL_DST_FORMAT_RAW10 <<468 ISPCCP2_LCM_CTRL_DST_FORMAT_SHIFT;469 470 if (dpcm_decompress) {471 /* source format is RAW8 */472 val |= ISPCCP2_LCM_CTRL_SRC_FORMAT_RAW8 <<473 ISPCCP2_LCM_CTRL_SRC_FORMAT_SHIFT;474 475 /* RAW8 + DPCM10 - simple predictor */476 val |= ISPCCP2_LCM_CTRL_SRC_DPCM_PRED;477 478 /* enable source DPCM decompression */479 val |= ISPCCP2_LCM_CTRL_SRC_DECOMPR_DPCM10 <<480 ISPCCP2_LCM_CTRL_SRC_DECOMPR_SHIFT;481 } else {482 /* source format is RAW10 */483 val |= ISPCCP2_LCM_CTRL_SRC_FORMAT_RAW10 <<484 ISPCCP2_LCM_CTRL_SRC_FORMAT_SHIFT;485 }486 487 /* Burst size to 32x64 */488 val |= ISPCCP2_LCM_CTRL_BURST_SIZE_32X <<489 ISPCCP2_LCM_CTRL_BURST_SIZE_SHIFT;490 491 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_CTRL);492 493 /* Prefetch setup */494 if (dpcm_decompress)495 hwords = (ISPCCP2_LCM_HSIZE_SKIP_MIN +496 config->hsize_count) >> 3;497 else498 hwords = (ISPCCP2_LCM_HSIZE_SKIP_MIN +499 config->hsize_count) >> 2;500 501 isp_reg_writel(isp, hwords << ISPCCP2_LCM_PREFETCH_SHIFT,502 OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_PREFETCH);503 504 /* Video port */505 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL,506 ISPCCP2_CTRL_IO_OUT_SEL | ISPCCP2_CTRL_MODE);507 ccp2_vp_config(ccp2, ccp2_adjust_bandwidth(ccp2));508 509 /* Clear LCM interrupts */510 isp_reg_writel(isp, ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ |511 ISPCCP2_LCM_IRQSTATUS_EOF_IRQ,512 OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_IRQSTATUS);513 514 /* Enable LCM interrupts */515 isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_IRQENABLE,516 ISPCCP2_LCM_IRQSTATUS_EOF_IRQ |517 ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ);518}519 520/*521 * ccp2_set_inaddr - Sets memory address of input frame.522 * @ccp2: Pointer to ISP CCP2 device523 * @addr: 32bit memory address aligned on 32byte boundary.524 *525 * Configures the memory address from which the input frame is to be read.526 */527static void ccp2_set_inaddr(struct isp_ccp2_device *ccp2, u32 addr)528{529 struct isp_device *isp = to_isp_device(ccp2);530 531 isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_SRC_ADDR);532}533 534/* -----------------------------------------------------------------------------535 * Interrupt handling536 */537 538static void ccp2_isr_buffer(struct isp_ccp2_device *ccp2)539{540 struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);541 struct isp_buffer *buffer;542 543 buffer = omap3isp_video_buffer_next(&ccp2->video_in);544 if (buffer != NULL)545 ccp2_set_inaddr(ccp2, buffer->dma);546 547 pipe->state |= ISP_PIPELINE_IDLE_INPUT;548 549 if (ccp2->state == ISP_PIPELINE_STREAM_SINGLESHOT) {550 if (isp_pipeline_ready(pipe))551 omap3isp_pipeline_set_stream(pipe,552 ISP_PIPELINE_STREAM_SINGLESHOT);553 }554}555 556/*557 * omap3isp_ccp2_isr - Handle ISP CCP2 interrupts558 * @ccp2: Pointer to ISP CCP2 device559 *560 * This will handle the CCP2 interrupts561 */562void omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2)563{564 struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);565 struct isp_device *isp = to_isp_device(ccp2);566 static const u32 ISPCCP2_LC01_ERROR =567 ISPCCP2_LC01_IRQSTATUS_LC0_FIFO_OVF_IRQ |568 ISPCCP2_LC01_IRQSTATUS_LC0_CRC_IRQ |569 ISPCCP2_LC01_IRQSTATUS_LC0_FSP_IRQ |570 ISPCCP2_LC01_IRQSTATUS_LC0_FW_IRQ |571 ISPCCP2_LC01_IRQSTATUS_LC0_FSC_IRQ |572 ISPCCP2_LC01_IRQSTATUS_LC0_SSC_IRQ;573 u32 lcx_irqstatus, lcm_irqstatus;574 575 /* First clear the interrupts */576 lcx_irqstatus = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2,577 ISPCCP2_LC01_IRQSTATUS);578 isp_reg_writel(isp, lcx_irqstatus, OMAP3_ISP_IOMEM_CCP2,579 ISPCCP2_LC01_IRQSTATUS);580 581 lcm_irqstatus = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2,582 ISPCCP2_LCM_IRQSTATUS);583 isp_reg_writel(isp, lcm_irqstatus, OMAP3_ISP_IOMEM_CCP2,584 ISPCCP2_LCM_IRQSTATUS);585 /* Errors */586 if (lcx_irqstatus & ISPCCP2_LC01_ERROR) {587 pipe->error = true;588 dev_dbg(isp->dev, "CCP2 err:%x\n", lcx_irqstatus);589 return;590 }591 592 if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ) {593 pipe->error = true;594 dev_dbg(isp->dev, "CCP2 OCP err:%x\n", lcm_irqstatus);595 }596 597 if (omap3isp_module_sync_is_stopping(&ccp2->wait, &ccp2->stopping))598 return;599 600 /* Handle queued buffers on frame end interrupts */601 if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_EOF_IRQ)602 ccp2_isr_buffer(ccp2);603}604 605/* -----------------------------------------------------------------------------606 * V4L2 subdev operations607 */608 609static const unsigned int ccp2_fmts[] = {610 MEDIA_BUS_FMT_SGRBG10_1X10,611 MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8,612};613 614/*615 * __ccp2_get_format - helper function for getting ccp2 format616 * @ccp2 : Pointer to ISP CCP2 device617 * @sd_state: V4L2 subdev state618 * @pad : pad number619 * @which : wanted subdev format620 * return format structure or NULL on error621 */622static struct v4l2_mbus_framefmt *623__ccp2_get_format(struct isp_ccp2_device *ccp2,624 struct v4l2_subdev_state *sd_state,625 unsigned int pad, enum v4l2_subdev_format_whence which)626{627 if (which == V4L2_SUBDEV_FORMAT_TRY)628 return v4l2_subdev_state_get_format(sd_state, pad);629 else630 return &ccp2->formats[pad];631}632 633/*634 * ccp2_try_format - Handle try format by pad subdev method635 * @ccp2 : Pointer to ISP CCP2 device636 * @sd_state: V4L2 subdev state637 * @pad : pad num638 * @fmt : pointer to v4l2 mbus format structure639 * @which : wanted subdev format640 */641static void ccp2_try_format(struct isp_ccp2_device *ccp2,642 struct v4l2_subdev_state *sd_state,643 unsigned int pad,644 struct v4l2_mbus_framefmt *fmt,645 enum v4l2_subdev_format_whence which)646{647 struct v4l2_mbus_framefmt *format;648 649 switch (pad) {650 case CCP2_PAD_SINK:651 if (fmt->code != MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8)652 fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;653 654 if (ccp2->input == CCP2_INPUT_SENSOR) {655 fmt->width = clamp_t(u32, fmt->width,656 ISPCCP2_DAT_START_MIN,657 ISPCCP2_DAT_START_MAX);658 fmt->height = clamp_t(u32, fmt->height,659 ISPCCP2_DAT_SIZE_MIN,660 ISPCCP2_DAT_SIZE_MAX);661 } else if (ccp2->input == CCP2_INPUT_MEMORY) {662 fmt->width = clamp_t(u32, fmt->width,663 ISPCCP2_LCM_HSIZE_COUNT_MIN,664 ISPCCP2_LCM_HSIZE_COUNT_MAX);665 fmt->height = clamp_t(u32, fmt->height,666 ISPCCP2_LCM_VSIZE_MIN,667 ISPCCP2_LCM_VSIZE_MAX);668 }669 break;670 671 case CCP2_PAD_SOURCE:672 /* Source format - copy sink format and change pixel code673 * to SGRBG10_1X10 as we don't support CCP2 write to memory.674 * When CCP2 write to memory feature will be added this675 * should be changed properly.676 */677 format = __ccp2_get_format(ccp2, sd_state, CCP2_PAD_SINK,678 which);679 memcpy(fmt, format, sizeof(*fmt));680 fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;681 break;682 }683 684 fmt->field = V4L2_FIELD_NONE;685 fmt->colorspace = V4L2_COLORSPACE_SRGB;686}687 688/*689 * ccp2_enum_mbus_code - Handle pixel format enumeration690 * @sd : pointer to v4l2 subdev structure691 * @sd_state: V4L2 subdev state692 * @code : pointer to v4l2_subdev_mbus_code_enum structure693 * return -EINVAL or zero on success694 */695static int ccp2_enum_mbus_code(struct v4l2_subdev *sd,696 struct v4l2_subdev_state *sd_state,697 struct v4l2_subdev_mbus_code_enum *code)698{699 struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);700 struct v4l2_mbus_framefmt *format;701 702 if (code->pad == CCP2_PAD_SINK) {703 if (code->index >= ARRAY_SIZE(ccp2_fmts))704 return -EINVAL;705 706 code->code = ccp2_fmts[code->index];707 } else {708 if (code->index != 0)709 return -EINVAL;710 711 format = __ccp2_get_format(ccp2, sd_state, CCP2_PAD_SINK,712 code->which);713 code->code = format->code;714 }715 716 return 0;717}718 719static int ccp2_enum_frame_size(struct v4l2_subdev *sd,720 struct v4l2_subdev_state *sd_state,721 struct v4l2_subdev_frame_size_enum *fse)722{723 struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);724 struct v4l2_mbus_framefmt format;725 726 if (fse->index != 0)727 return -EINVAL;728 729 format.code = fse->code;730 format.width = 1;731 format.height = 1;732 ccp2_try_format(ccp2, sd_state, fse->pad, &format, fse->which);733 fse->min_width = format.width;734 fse->min_height = format.height;735 736 if (format.code != fse->code)737 return -EINVAL;738 739 format.code = fse->code;740 format.width = -1;741 format.height = -1;742 ccp2_try_format(ccp2, sd_state, fse->pad, &format, fse->which);743 fse->max_width = format.width;744 fse->max_height = format.height;745 746 return 0;747}748 749/*750 * ccp2_get_format - Handle get format by pads subdev method751 * @sd : pointer to v4l2 subdev structure752 * @sd_state: V4L2 subdev state753 * @fmt : pointer to v4l2 subdev format structure754 * return -EINVAL or zero on success755 */756static int ccp2_get_format(struct v4l2_subdev *sd,757 struct v4l2_subdev_state *sd_state,758 struct v4l2_subdev_format *fmt)759{760 struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);761 struct v4l2_mbus_framefmt *format;762 763 format = __ccp2_get_format(ccp2, sd_state, fmt->pad, fmt->which);764 if (format == NULL)765 return -EINVAL;766 767 fmt->format = *format;768 return 0;769}770 771/*772 * ccp2_set_format - Handle set format by pads subdev method773 * @sd : pointer to v4l2 subdev structure774 * @sd_state: V4L2 subdev state775 * @fmt : pointer to v4l2 subdev format structure776 * returns zero777 */778static int ccp2_set_format(struct v4l2_subdev *sd,779 struct v4l2_subdev_state *sd_state,780 struct v4l2_subdev_format *fmt)781{782 struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);783 struct v4l2_mbus_framefmt *format;784 785 format = __ccp2_get_format(ccp2, sd_state, fmt->pad, fmt->which);786 if (format == NULL)787 return -EINVAL;788 789 ccp2_try_format(ccp2, sd_state, fmt->pad, &fmt->format, fmt->which);790 *format = fmt->format;791 792 /* Propagate the format from sink to source */793 if (fmt->pad == CCP2_PAD_SINK) {794 format = __ccp2_get_format(ccp2, sd_state, CCP2_PAD_SOURCE,795 fmt->which);796 *format = fmt->format;797 ccp2_try_format(ccp2, sd_state, CCP2_PAD_SOURCE, format,798 fmt->which);799 }800 801 return 0;802}803 804/*805 * ccp2_init_formats - Initialize formats on all pads806 * @sd: ISP CCP2 V4L2 subdevice807 * @fh: V4L2 subdev file handle808 *809 * Initialize all pad formats with default values. If fh is not NULL, try810 * formats are initialized on the file handle. Otherwise active formats are811 * initialized on the device.812 */813static int ccp2_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)814{815 struct v4l2_subdev_format format;816 817 memset(&format, 0, sizeof(format));818 format.pad = CCP2_PAD_SINK;819 format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;820 format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;821 format.format.width = 4096;822 format.format.height = 4096;823 ccp2_set_format(sd, fh ? fh->state : NULL, &format);824 825 return 0;826}827 828/*829 * ccp2_s_stream - Enable/Disable streaming on ccp2 subdev830 * @sd : pointer to v4l2 subdev structure831 * @enable: 1 == Enable, 0 == Disable832 * return zero833 */834static int ccp2_s_stream(struct v4l2_subdev *sd, int enable)835{836 struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);837 struct isp_device *isp = to_isp_device(ccp2);838 struct device *dev = to_device(ccp2);839 int ret;840 841 if (ccp2->state == ISP_PIPELINE_STREAM_STOPPED) {842 if (enable == ISP_PIPELINE_STREAM_STOPPED)843 return 0;844 atomic_set(&ccp2->stopping, 0);845 }846 847 switch (enable) {848 case ISP_PIPELINE_STREAM_CONTINUOUS:849 if (ccp2->phy) {850 ret = omap3isp_csiphy_acquire(ccp2->phy, &sd->entity);851 if (ret < 0)852 return ret;853 }854 855 ccp2_if_configure(ccp2);856 ccp2_print_status(ccp2);857 858 /* Enable CSI1/CCP2 interface */859 ret = ccp2_if_enable(ccp2, 1);860 if (ret < 0) {861 if (ccp2->phy)862 omap3isp_csiphy_release(ccp2->phy);863 return ret;864 }865 break;866 867 case ISP_PIPELINE_STREAM_SINGLESHOT:868 if (ccp2->state != ISP_PIPELINE_STREAM_SINGLESHOT) {869 struct v4l2_mbus_framefmt *format;870 871 format = &ccp2->formats[CCP2_PAD_SINK];872 873 ccp2->mem_cfg.hsize_count = format->width;874 ccp2->mem_cfg.vsize_count = format->height;875 ccp2->mem_cfg.src_ofst = 0;876 877 ccp2_mem_configure(ccp2, &ccp2->mem_cfg);878 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CSI1_READ);879 ccp2_print_status(ccp2);880 }881 ccp2_mem_enable(ccp2, 1);882 break;883 884 case ISP_PIPELINE_STREAM_STOPPED:885 if (omap3isp_module_sync_idle(&sd->entity, &ccp2->wait,886 &ccp2->stopping))887 dev_dbg(dev, "%s: module stop timeout.\n", sd->name);888 if (ccp2->input == CCP2_INPUT_MEMORY) {889 ccp2_mem_enable(ccp2, 0);890 omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_CSI1_READ);891 } else if (ccp2->input == CCP2_INPUT_SENSOR) {892 /* Disable CSI1/CCP2 interface */893 ccp2_if_enable(ccp2, 0);894 if (ccp2->phy)895 omap3isp_csiphy_release(ccp2->phy);896 }897 break;898 }899 900 ccp2->state = enable;901 return 0;902}903 904/* subdev video operations */905static const struct v4l2_subdev_video_ops ccp2_sd_video_ops = {906 .s_stream = ccp2_s_stream,907};908 909/* subdev pad operations */910static const struct v4l2_subdev_pad_ops ccp2_sd_pad_ops = {911 .enum_mbus_code = ccp2_enum_mbus_code,912 .enum_frame_size = ccp2_enum_frame_size,913 .get_fmt = ccp2_get_format,914 .set_fmt = ccp2_set_format,915};916 917/* subdev operations */918static const struct v4l2_subdev_ops ccp2_sd_ops = {919 .video = &ccp2_sd_video_ops,920 .pad = &ccp2_sd_pad_ops,921};922 923/* subdev internal operations */924static const struct v4l2_subdev_internal_ops ccp2_sd_internal_ops = {925 .open = ccp2_init_formats,926};927 928/* --------------------------------------------------------------------------929 * ISP ccp2 video device node930 */931 932/*933 * ccp2_video_queue - Queue video buffer.934 * @video : Pointer to isp video structure935 * @buffer: Pointer to isp_buffer structure936 * return -EIO or zero on success937 */938static int ccp2_video_queue(struct isp_video *video, struct isp_buffer *buffer)939{940 struct isp_ccp2_device *ccp2 = &video->isp->isp_ccp2;941 942 ccp2_set_inaddr(ccp2, buffer->dma);943 return 0;944}945 946static const struct isp_video_operations ccp2_video_ops = {947 .queue = ccp2_video_queue,948};949 950/* -----------------------------------------------------------------------------951 * Media entity operations952 */953 954/*955 * ccp2_link_setup - Setup ccp2 connections.956 * @entity : Pointer to media entity structure957 * @local : Pointer to local pad array958 * @remote : Pointer to remote pad array959 * @flags : Link flags960 * return -EINVAL on error or zero on success961 */962static int ccp2_link_setup(struct media_entity *entity,963 const struct media_pad *local,964 const struct media_pad *remote, u32 flags)965{966 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);967 struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);968 unsigned int index = local->index;969 970 /* FIXME: this is actually a hack! */971 if (is_media_entity_v4l2_subdev(remote->entity))972 index |= 2 << 16;973 974 switch (index) {975 case CCP2_PAD_SINK:976 /* read from memory */977 if (flags & MEDIA_LNK_FL_ENABLED) {978 if (ccp2->input == CCP2_INPUT_SENSOR)979 return -EBUSY;980 ccp2->input = CCP2_INPUT_MEMORY;981 } else {982 if (ccp2->input == CCP2_INPUT_MEMORY)983 ccp2->input = CCP2_INPUT_NONE;984 }985 break;986 987 case CCP2_PAD_SINK | 2 << 16:988 /* read from sensor/phy */989 if (flags & MEDIA_LNK_FL_ENABLED) {990 if (ccp2->input == CCP2_INPUT_MEMORY)991 return -EBUSY;992 ccp2->input = CCP2_INPUT_SENSOR;993 } else {994 if (ccp2->input == CCP2_INPUT_SENSOR)995 ccp2->input = CCP2_INPUT_NONE;996 } break;997 998 case CCP2_PAD_SOURCE | 2 << 16:999 /* write to video port/ccdc */1000 if (flags & MEDIA_LNK_FL_ENABLED)1001 ccp2->output = CCP2_OUTPUT_CCDC;1002 else1003 ccp2->output = CCP2_OUTPUT_NONE;1004 break;1005 1006 default:1007 return -EINVAL;1008 }1009 1010 return 0;1011}1012 1013/* media operations */1014static const struct media_entity_operations ccp2_media_ops = {1015 .link_setup = ccp2_link_setup,1016 .link_validate = v4l2_subdev_link_validate,1017};1018 1019/*1020 * omap3isp_ccp2_unregister_entities - Unregister media entities: subdev1021 * @ccp2: Pointer to ISP CCP2 device1022 */1023void omap3isp_ccp2_unregister_entities(struct isp_ccp2_device *ccp2)1024{1025 v4l2_device_unregister_subdev(&ccp2->subdev);1026 omap3isp_video_unregister(&ccp2->video_in);1027}1028 1029/*1030 * omap3isp_ccp2_register_entities - Register the subdev media entity1031 * @ccp2: Pointer to ISP CCP2 device1032 * @vdev: Pointer to v4l device1033 * return negative error code or zero on success1034 */1035 1036int omap3isp_ccp2_register_entities(struct isp_ccp2_device *ccp2,1037 struct v4l2_device *vdev)1038{1039 int ret;1040 1041 /* Register the subdev and video nodes. */1042 ccp2->subdev.dev = vdev->mdev->dev;1043 ret = v4l2_device_register_subdev(vdev, &ccp2->subdev);1044 if (ret < 0)1045 goto error;1046 1047 ret = omap3isp_video_register(&ccp2->video_in, vdev);1048 if (ret < 0)1049 goto error;1050 1051 return 0;1052 1053error:1054 omap3isp_ccp2_unregister_entities(ccp2);1055 return ret;1056}1057 1058/* -----------------------------------------------------------------------------1059 * ISP ccp2 initialisation and cleanup1060 */1061 1062/*1063 * ccp2_init_entities - Initialize ccp2 subdev and media entity.1064 * @ccp2: Pointer to ISP CCP2 device1065 * return negative error code or zero on success1066 */1067static int ccp2_init_entities(struct isp_ccp2_device *ccp2)1068{1069 struct v4l2_subdev *sd = &ccp2->subdev;1070 struct media_pad *pads = ccp2->pads;1071 struct media_entity *me = &sd->entity;1072 int ret;1073 1074 ccp2->input = CCP2_INPUT_NONE;1075 ccp2->output = CCP2_OUTPUT_NONE;1076 1077 v4l2_subdev_init(sd, &ccp2_sd_ops);1078 sd->internal_ops = &ccp2_sd_internal_ops;1079 strscpy(sd->name, "OMAP3 ISP CCP2", sizeof(sd->name));1080 sd->grp_id = 1 << 16; /* group ID for isp subdevs */1081 v4l2_set_subdevdata(sd, ccp2);1082 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;1083 1084 pads[CCP2_PAD_SINK].flags = MEDIA_PAD_FL_SINK1085 | MEDIA_PAD_FL_MUST_CONNECT;1086 pads[CCP2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;1087 1088 me->ops = &ccp2_media_ops;1089 ret = media_entity_pads_init(me, CCP2_PADS_NUM, pads);1090 if (ret < 0)1091 return ret;1092 1093 ccp2_init_formats(sd, NULL);1094 1095 /*1096 * The CCP2 has weird line alignment requirements, possibly caused by1097 * DPCM8 decompression. Line length for data read from memory must be a1098 * multiple of 128 bits (16 bytes) in continuous mode (when no padding1099 * is present at end of lines). Additionally, if padding is used, the1100 * padded line length must be a multiple of 32 bytes. To simplify the1101 * implementation we use a fixed 32 bytes alignment regardless of the1102 * input format and width. If strict 128 bits alignment support is1103 * required ispvideo will need to be made aware of this special dual1104 * alignment requirements.1105 */1106 ccp2->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;1107 ccp2->video_in.bpl_alignment = 32;1108 ccp2->video_in.bpl_max = 0xffffffe0;1109 ccp2->video_in.isp = to_isp_device(ccp2);1110 ccp2->video_in.ops = &ccp2_video_ops;1111 ccp2->video_in.capture_mem = PAGE_ALIGN(4096 * 4096) * 3;1112 1113 ret = omap3isp_video_init(&ccp2->video_in, "CCP2");1114 if (ret < 0)1115 goto error;1116 1117 return 0;1118 1119error:1120 media_entity_cleanup(&ccp2->subdev.entity);1121 return ret;1122}1123 1124/*1125 * omap3isp_ccp2_init - CCP2 initialization.1126 * @isp : Pointer to ISP device1127 * return negative error code or zero on success1128 */1129int omap3isp_ccp2_init(struct isp_device *isp)1130{1131 struct isp_ccp2_device *ccp2 = &isp->isp_ccp2;1132 int ret;1133 1134 init_waitqueue_head(&ccp2->wait);1135 1136 /*1137 * On the OMAP34xx the CSI1 receiver is operated in the CSIb IO1138 * complex, which is powered by vdds_csib power rail. Hence the1139 * request for the regulator.1140 *1141 * On the OMAP36xx, the CCP2 uses the CSI PHY1 or PHY2, shared with1142 * the CSI2c or CSI2a receivers. The PHY then needs to be explicitly1143 * configured.1144 *1145 * TODO: Don't hardcode the usage of PHY1 (shared with CSI2c).1146 */1147 if (isp->revision == ISP_REVISION_2_0) {1148 ccp2->vdds_csib = devm_regulator_get(isp->dev, "vdds_csib");1149 if (IS_ERR(ccp2->vdds_csib)) {1150 if (PTR_ERR(ccp2->vdds_csib) == -EPROBE_DEFER) {1151 dev_dbg(isp->dev,1152 "Can't get regulator vdds_csib, deferring probing\n");1153 return -EPROBE_DEFER;1154 }1155 dev_dbg(isp->dev,1156 "Could not get regulator vdds_csib\n");1157 ccp2->vdds_csib = NULL;1158 }1159 ccp2->phy = &isp->isp_csiphy2;1160 } else if (isp->revision == ISP_REVISION_15_0) {1161 ccp2->phy = &isp->isp_csiphy1;1162 }1163 1164 ret = ccp2_init_entities(ccp2);1165 if (ret < 0)1166 return ret;1167 1168 ccp2_reset(ccp2);1169 return 0;1170}1171 1172/*1173 * omap3isp_ccp2_cleanup - CCP2 un-initialization1174 * @isp : Pointer to ISP device1175 */1176void omap3isp_ccp2_cleanup(struct isp_device *isp)1177{1178 struct isp_ccp2_device *ccp2 = &isp->isp_ccp2;1179 1180 omap3isp_video_cleanup(&ccp2->video_in);1181 media_entity_cleanup(&ccp2->subdev.entity);1182}1183