コード例 #1
0
ファイル: iss.c プロジェクト: a2hojsjsjs/linux
/*
 * Configure the bridge. Valid inputs are
 *
 * IPIPEIF_INPUT_CSI2A: CSI2a receiver
 * IPIPEIF_INPUT_CSI2B: CSI2b receiver
 *
 * The bridge and lane shifter are configured according to the selected input
 * and the ISP platform data.
 */
void omap4iss_configure_bridge(struct iss_device *iss,
			       enum ipipeif_input_entity input)
{
	u32 issctrl_val;
	u32 isp5ctrl_val;

	issctrl_val = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_CTRL);
	issctrl_val &= ~ISS_CTRL_INPUT_SEL_MASK;
	issctrl_val &= ~ISS_CTRL_CLK_DIV_MASK;

	isp5ctrl_val = iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL);

	switch (input) {
	case IPIPEIF_INPUT_CSI2A:
		issctrl_val |= ISS_CTRL_INPUT_SEL_CSI2A;
		break;

	case IPIPEIF_INPUT_CSI2B:
		issctrl_val |= ISS_CTRL_INPUT_SEL_CSI2B;
		break;

	default:
		return;
	}

	issctrl_val |= ISS_CTRL_SYNC_DETECT_VS_RAISING;

	isp5ctrl_val |= ISP5_CTRL_VD_PULSE_EXT | ISP5_CTRL_PSYNC_CLK_SEL |
			ISP5_CTRL_SYNC_ENABLE;

	iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_CTRL, issctrl_val);
	iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL, isp5ctrl_val);
}
コード例 #2
0
ファイル: iss.c プロジェクト: a2hojsjsjs/linux
static int iss_isp_reset(struct iss_device *iss)
{
	unsigned int timeout;

	/* Fist, ensure that the ISP is IDLE (no transactions happening) */
	iss_reg_update(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_SYSCONFIG,
		       ISP5_SYSCONFIG_STANDBYMODE_MASK,
		       ISP5_SYSCONFIG_STANDBYMODE_SMART);

	iss_reg_set(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL, ISP5_CTRL_MSTANDBY);

	timeout = iss_poll_condition_timeout(
		iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL) &
		ISP5_CTRL_MSTANDBY_WAIT, 1000000, 1000, 1500);
	if (timeout) {
		dev_err(iss->dev, "ISP5 standby timeout\n");
		return -ETIMEDOUT;
	}

	/* Now finally, do the reset */
	iss_reg_set(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_SYSCONFIG,
		    ISP5_SYSCONFIG_SOFTRESET);

	timeout = iss_poll_condition_timeout(
		!(iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_SYSCONFIG) &
		ISP5_SYSCONFIG_SOFTRESET), 1000000, 1000, 1500);
	if (timeout) {
		dev_err(iss->dev, "ISP5 reset timeout\n");
		return -ETIMEDOUT;
	}

	return 0;
}
コード例 #3
0
ファイル: iss.c プロジェクト: a2hojsjsjs/linux
/*
 * iss_isr - Interrupt Service Routine for ISS module.
 * @irq: Not used currently.
 * @_iss: Pointer to the OMAP4 ISS device
 *
 * Handles the corresponding callback if plugged in.
 *
 * Returns IRQ_HANDLED when IRQ was correctly handled, or IRQ_NONE when the
 * IRQ wasn't handled.
 */
static irqreturn_t iss_isr(int irq, void *_iss)
{
	static const u32 ipipeif_events = ISP5_IRQ_IPIPEIF_IRQ |
					  ISP5_IRQ_ISIF_INT(0);
	static const u32 resizer_events = ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR |
					  ISP5_IRQ_RSZ_FIFO_OVF |
					  ISP5_IRQ_RSZ_INT_DMA;
	struct iss_device *iss = _iss;
	u32 irqstatus;

	irqstatus = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQSTATUS(5));
	iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQSTATUS(5), irqstatus);

	if (irqstatus & ISS_HL_IRQ_CSIA)
		omap4iss_csi2_isr(&iss->csi2a);

	if (irqstatus & ISS_HL_IRQ_CSIB)
		omap4iss_csi2_isr(&iss->csi2b);

	if (irqstatus & ISS_HL_IRQ_ISP(0)) {
		u32 isp_irqstatus = iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1,
						 ISP5_IRQSTATUS(0));
		iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQSTATUS(0),
			      isp_irqstatus);

		if (isp_irqstatus & ISP5_IRQ_OCP_ERR)
			dev_dbg(iss->dev, "ISP5 OCP Error!\n");

		if (isp_irqstatus & ipipeif_events) {
			omap4iss_ipipeif_isr(&iss->ipipeif,
					     isp_irqstatus & ipipeif_events);
		}

		if (isp_irqstatus & resizer_events)
			omap4iss_resizer_isr(&iss->resizer,
					     isp_irqstatus & resizer_events);

#ifdef ISS_ISR_DEBUG
		iss_isp_isr_dbg(iss, isp_irqstatus);
#endif
	}

	omap4iss_flush(iss);

#ifdef ISS_ISR_DEBUG
	iss_isr_dbg(iss, irqstatus);
#endif

	return IRQ_HANDLED;
}
コード例 #4
0
ファイル: iss_csi2.c プロジェクト: MaxChina/linux
/*
 * omap4iss_csi2_isr - CSI2 interrupt handling.
 */
void omap4iss_csi2_isr(struct iss_csi2_device *csi2)
{
	struct iss_pipeline *pipe = to_iss_pipeline(&csi2->subdev.entity);
	u32 csi2_irqstatus, cpxio1_irqstatus;
	struct iss_device *iss = csi2->iss;

	if (!csi2->available)
		return;

	csi2_irqstatus = iss_reg_read(csi2->iss, csi2->regs1, CSI2_IRQSTATUS);
	iss_reg_write(csi2->iss, csi2->regs1, CSI2_IRQSTATUS, csi2_irqstatus);

	/* Failure Cases */
	if (csi2_irqstatus & CSI2_IRQ_COMPLEXIO_ERR) {
		cpxio1_irqstatus = iss_reg_read(csi2->iss, csi2->regs1,
						CSI2_COMPLEXIO_IRQSTATUS);
		iss_reg_write(csi2->iss, csi2->regs1, CSI2_COMPLEXIO_IRQSTATUS,
			      cpxio1_irqstatus);
		dev_dbg(iss->dev, "CSI2: ComplexIO Error IRQ %x\n",
			cpxio1_irqstatus);
		pipe->error = true;
	}

	if (csi2_irqstatus & (CSI2_IRQ_OCP_ERR |
			      CSI2_IRQ_SHORT_PACKET |
			      CSI2_IRQ_ECC_NO_CORRECTION |
			      CSI2_IRQ_COMPLEXIO_ERR |
			      CSI2_IRQ_FIFO_OVF)) {
		dev_dbg(iss->dev,
			"CSI2 Err: OCP:%d SHORT:%d ECC:%d CPXIO:%d OVF:%d\n",
			csi2_irqstatus & CSI2_IRQ_OCP_ERR ? 1 : 0,
			csi2_irqstatus & CSI2_IRQ_SHORT_PACKET ? 1 : 0,
			csi2_irqstatus & CSI2_IRQ_ECC_NO_CORRECTION ? 1 : 0,
			csi2_irqstatus & CSI2_IRQ_COMPLEXIO_ERR ? 1 : 0,
			csi2_irqstatus & CSI2_IRQ_FIFO_OVF ? 1 : 0);
		pipe->error = true;
	}

	if (omap4iss_module_sync_is_stopping(&csi2->wait, &csi2->stopping))
		return;

	/* Successful cases */
	if (csi2_irqstatus & CSI2_IRQ_CONTEXT0)
		csi2_isr_ctx(csi2, &csi2->contexts[0]);

	if (csi2_irqstatus & CSI2_IRQ_ECC_CORRECTION)
		dev_dbg(iss->dev, "CSI2: ECC correction done\n");
}
コード例 #5
0
ファイル: iss_csi2.c プロジェクト: MaxChina/linux
/*
 * csi2_timing_config - CSI2 timing configuration.
 * @timing: csi2_timing_cfg structure
 */
static void csi2_timing_config(struct iss_csi2_device *csi2,
			       struct iss_csi2_timing_cfg *timing)
{
	u32 reg;

	reg = iss_reg_read(csi2->iss, csi2->regs1, CSI2_TIMING);

	if (timing->force_rx_mode)
		reg |= CSI2_TIMING_FORCE_RX_MODE_IO1;
	else
		reg &= ~CSI2_TIMING_FORCE_RX_MODE_IO1;

	if (timing->stop_state_16x)
		reg |= CSI2_TIMING_STOP_STATE_X16_IO1;
	else
		reg &= ~CSI2_TIMING_STOP_STATE_X16_IO1;

	if (timing->stop_state_4x)
		reg |= CSI2_TIMING_STOP_STATE_X4_IO1;
	else
		reg &= ~CSI2_TIMING_STOP_STATE_X4_IO1;

	reg &= ~CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK;
	reg |= timing->stop_state_counter <<
	       CSI2_TIMING_STOP_STATE_COUNTER_IO1_SHIFT;

	iss_reg_write(csi2->iss, csi2->regs1, CSI2_TIMING, reg);
}
コード例 #6
0
ファイル: iss_csi2.c プロジェクト: MaxChina/linux
/*
 * csi2_ctx_enable - Enable specified CSI2 context
 * @ctxnum: Context number, valid between 0 and 7 values.
 * @enable: enable
 *
 */
static void csi2_ctx_enable(struct iss_csi2_device *csi2, u8 ctxnum, u8 enable)
{
	struct iss_csi2_ctx_cfg *ctx = &csi2->contexts[ctxnum];
	u32 reg;

	reg = iss_reg_read(csi2->iss, csi2->regs1, CSI2_CTX_CTRL1(ctxnum));

	if (enable) {
		unsigned int skip = 0;

		if (csi2->frame_skip)
			skip = csi2->frame_skip;
		else if (csi2->output & CSI2_OUTPUT_MEMORY)
			skip = 1;

		reg &= ~CSI2_CTX_CTRL1_COUNT_MASK;
		reg |= CSI2_CTX_CTRL1_COUNT_UNLOCK
		    |  (skip << CSI2_CTX_CTRL1_COUNT_SHIFT)
		    |  CSI2_CTX_CTRL1_CTX_EN;
	} else {
		reg &= ~CSI2_CTX_CTRL1_CTX_EN;
	}

	iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_CTRL1(ctxnum), reg);
	ctx->enabled = enable;
}
コード例 #7
0
ファイル: iss.c プロジェクト: a2hojsjsjs/linux
static int __iss_subclk_update(struct iss_device *iss)
{
	u32 clk = 0;
	int ret = 0, timeout = 1000;

	if (iss->subclk_resources & OMAP4_ISS_SUBCLK_CSI2_A)
		clk |= ISS_CLKCTRL_CSI2_A;

	if (iss->subclk_resources & OMAP4_ISS_SUBCLK_CSI2_B)
		clk |= ISS_CLKCTRL_CSI2_B;

	if (iss->subclk_resources & OMAP4_ISS_SUBCLK_ISP)
		clk |= ISS_CLKCTRL_ISP;

	iss_reg_update(iss, OMAP4_ISS_MEM_TOP, ISS_CLKCTRL,
		       ISS_CLKCTRL_MASK, clk);

	/* Wait for HW assertion */
	while (--timeout > 0) {
		udelay(1);
		if ((iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_CLKSTAT) &
		    ISS_CLKCTRL_MASK) == clk)
			break;
	}

	if (!timeout)
		ret = -EBUSY;

	return ret;
}
コード例 #8
0
ファイル: iss_csi2.c プロジェクト: MaxChina/linux
/*
 * omap4iss_csi2_reset - Resets the CSI2 module.
 *
 * Must be called with the phy lock held.
 *
 * Returns 0 if successful, or -EBUSY if power command didn't respond.
 */
int omap4iss_csi2_reset(struct iss_csi2_device *csi2)
{
	unsigned int timeout;

	if (!csi2->available)
		return -ENODEV;

	if (csi2->phy->phy_in_use)
		return -EBUSY;

	iss_reg_set(csi2->iss, csi2->regs1, CSI2_SYSCONFIG,
		    CSI2_SYSCONFIG_SOFT_RESET);

	timeout = iss_poll_condition_timeout(
		iss_reg_read(csi2->iss, csi2->regs1, CSI2_SYSSTATUS) &
		CSI2_SYSSTATUS_RESET_DONE, 500, 100, 200);
	if (timeout) {
		dev_err(csi2->iss->dev, "CSI2: Soft reset timeout!\n");
		return -EBUSY;
	}

	iss_reg_set(csi2->iss, csi2->regs1, CSI2_COMPLEXIO_CFG,
		    CSI2_COMPLEXIO_CFG_RESET_CTRL);

	timeout = iss_poll_condition_timeout(
		iss_reg_read(csi2->iss, csi2->phy->phy_regs, REGISTER1) &
		REGISTER1_RESET_DONE_CTRLCLK, 10000, 100, 500);
	if (timeout) {
		dev_err(csi2->iss->dev, "CSI2: CSI2_96M_FCLK reset timeout!\n");
		return -EBUSY;
	}

	iss_reg_update(csi2->iss, csi2->regs1, CSI2_SYSCONFIG,
		       CSI2_SYSCONFIG_MSTANDBY_MODE_MASK |
		       CSI2_SYSCONFIG_AUTO_IDLE,
		       CSI2_SYSCONFIG_MSTANDBY_MODE_NO);

	return 0;
}
コード例 #9
0
ファイル: iss.c プロジェクト: vanquishsecurity/linux
static int iss_reset(struct iss_device *iss)
{
	unsigned int timeout;

	iss_reg_set(iss, OMAP4_ISS_MEM_TOP, ISS_HL_SYSCONFIG,
		    ISS_HL_SYSCONFIG_SOFTRESET);

	timeout = iss_poll_condition_timeout(
		!(iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_SYSCONFIG) &
		ISS_HL_SYSCONFIG_SOFTRESET), 1000, 10, 100);
	if (timeout) {
		dev_err(iss->dev, "ISS reset timeout\n");
		return -ETIMEDOUT;
	}

	iss->crashed = 0;
	return 0;
}
コード例 #10
0
ファイル: iss_csi2.c プロジェクト: MaxChina/linux
static void csi2_isr_ctx(struct iss_csi2_device *csi2,
			 struct iss_csi2_ctx_cfg *ctx)
{
	unsigned int n = ctx->ctxnum;
	u32 status;

	status = iss_reg_read(csi2->iss, csi2->regs1, CSI2_CTX_IRQSTATUS(n));
	iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_IRQSTATUS(n), status);

	/* Propagate frame number */
	if (status & CSI2_CTX_IRQ_FS) {
		struct iss_pipeline *pipe =
				     to_iss_pipeline(&csi2->subdev.entity);
		if (pipe->do_propagation)
			atomic_inc(&pipe->frame_number);
	}

	if (!(status & CSI2_CTX_IRQ_FE))
		return;

	/* Skip interrupts until we reach the frame skip count. The CSI2 will be
	 * automatically disabled, as the frame skip count has been programmed
	 * in the CSI2_CTx_CTRL1::COUNT field, so reenable it.
	 *
	 * It would have been nice to rely on the FRAME_NUMBER interrupt instead
	 * but it turned out that the interrupt is only generated when the CSI2
	 * writes to memory (the CSI2_CTx_CTRL1::COUNT field is decreased
	 * correctly and reaches 0 when data is forwarded to the video port only
	 * but no interrupt arrives). Maybe a CSI2 hardware bug.
	 */
	if (csi2->frame_skip) {
		csi2->frame_skip--;
		if (csi2->frame_skip == 0) {
			ctx->format_id = csi2_ctx_map_format(csi2);
			csi2_ctx_config(csi2, ctx);
			csi2_ctx_enable(csi2, n, 1);
		}
		return;
	}

	if (csi2->output & CSI2_OUTPUT_MEMORY)
		csi2_isr_buffer(csi2);
}
コード例 #11
0
ファイル: iss.c プロジェクト: a2hojsjsjs/linux
/*
 * omap4iss_flush - Post pending L3 bus writes by doing a register readback
 * @iss: OMAP4 ISS device
 *
 * In order to force posting of pending writes, we need to write and
 * readback the same register, in this case the revision register.
 *
 * See this link for reference:
 *   http://www.mail-archive.com/[email protected]/msg08149.html
 */
void omap4iss_flush(struct iss_device *iss)
{
	iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION, 0);
	iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION);
}
コード例 #12
0
ファイル: iss.c プロジェクト: a2hojsjsjs/linux
static int iss_probe(struct platform_device *pdev)
{
	struct iss_platform_data *pdata = pdev->dev.platform_data;
	struct iss_device *iss;
	unsigned int i;
	int ret;

	if (!pdata)
		return -EINVAL;

	iss = devm_kzalloc(&pdev->dev, sizeof(*iss), GFP_KERNEL);
	if (!iss)
		return -ENOMEM;

	mutex_init(&iss->iss_mutex);

	iss->dev = &pdev->dev;
	iss->pdata = pdata;

	iss->raw_dmamask = DMA_BIT_MASK(32);
	iss->dev->dma_mask = &iss->raw_dmamask;
	iss->dev->coherent_dma_mask = DMA_BIT_MASK(32);

	platform_set_drvdata(pdev, iss);

	/*
	 * TODO: When implementing DT support switch to syscon regmap lookup by
	 * phandle.
	 */
	iss->syscon = syscon_regmap_lookup_by_compatible("syscon");
	if (IS_ERR(iss->syscon)) {
		ret = PTR_ERR(iss->syscon);
		goto error;
	}

	/* Clocks */
	ret = iss_map_mem_resource(pdev, iss, OMAP4_ISS_MEM_TOP);
	if (ret < 0)
		goto error;

	ret = iss_get_clocks(iss);
	if (ret < 0)
		goto error;

	if (!omap4iss_get(iss))
		goto error;

	ret = iss_reset(iss);
	if (ret < 0)
		goto error_iss;

	iss->revision = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION);
	dev_info(iss->dev, "Revision %08x found\n", iss->revision);

	for (i = 1; i < OMAP4_ISS_MEM_LAST; i++) {
		ret = iss_map_mem_resource(pdev, iss, i);
		if (ret)
			goto error_iss;
	}

	/* Configure BTE BW_LIMITER field to max recommended value (1 GB) */
	iss_reg_update(iss, OMAP4_ISS_MEM_BTE, BTE_CTRL,
		       BTE_CTRL_BW_LIMITER_MASK,
		       18 << BTE_CTRL_BW_LIMITER_SHIFT);

	/* Perform ISP reset */
	ret = omap4iss_subclk_enable(iss, OMAP4_ISS_SUBCLK_ISP);
	if (ret < 0)
		goto error_iss;

	ret = iss_isp_reset(iss);
	if (ret < 0)
		goto error_iss;

	dev_info(iss->dev, "ISP Revision %08x found\n",
		 iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_REVISION));

	/* Interrupt */
	ret = platform_get_irq(pdev, 0);
	if (ret <= 0) {
		dev_err(iss->dev, "No IRQ resource\n");
		ret = -ENODEV;
		goto error_iss;
	}
	iss->irq_num = ret;

	if (devm_request_irq(iss->dev, iss->irq_num, iss_isr, IRQF_SHARED,
			     "OMAP4 ISS", iss)) {
		dev_err(iss->dev, "Unable to request IRQ\n");
		ret = -EINVAL;
		goto error_iss;
	}

	/* Entities */
	ret = iss_initialize_modules(iss);
	if (ret < 0)
		goto error_iss;

	ret = iss_register_entities(iss);
	if (ret < 0)
		goto error_modules;

	ret = media_entity_enum_init(&iss->crashed, &iss->media_dev);
	if (ret)
		goto error_entities;

	ret = iss_create_links(iss);
	if (ret < 0)
		goto error_entities;

	omap4iss_put(iss);

	return 0;

error_entities:
	iss_unregister_entities(iss);
	media_entity_enum_cleanup(&iss->crashed);
error_modules:
	iss_cleanup_modules(iss);
error_iss:
	omap4iss_put(iss);
error:
	platform_set_drvdata(pdev, NULL);

	mutex_destroy(&iss->iss_mutex);

	return ret;
}
コード例 #13
0
ファイル: iss.c プロジェクト: vanquishsecurity/linux
static int iss_probe(struct platform_device *pdev)
{
	struct iss_platform_data *pdata = pdev->dev.platform_data;
	struct iss_device *iss;
	unsigned int i;
	int ret;

	if (pdata == NULL)
		return -EINVAL;

	iss = devm_kzalloc(&pdev->dev, sizeof(*iss), GFP_KERNEL);
	if (!iss) {
		dev_err(&pdev->dev, "Could not allocate memory\n");
		return -ENOMEM;
	}

	mutex_init(&iss->iss_mutex);

	iss->dev = &pdev->dev;
	iss->pdata = pdata;

	iss->raw_dmamask = DMA_BIT_MASK(32);
	iss->dev->dma_mask = &iss->raw_dmamask;
	iss->dev->coherent_dma_mask = DMA_BIT_MASK(32);

	platform_set_drvdata(pdev, iss);

	/* Clocks */
	ret = iss_map_mem_resource(pdev, iss, OMAP4_ISS_MEM_TOP);
	if (ret < 0)
		goto error;

	ret = iss_get_clocks(iss);
	if (ret < 0)
		goto error;

	if (omap4iss_get(iss) == NULL)
		goto error;

	ret = iss_reset(iss);
	if (ret < 0)
		goto error_iss;

	iss->revision = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION);
	dev_info(iss->dev, "Revision %08x found\n", iss->revision);

	for (i = 1; i < OMAP4_ISS_MEM_LAST; i++) {
		ret = iss_map_mem_resource(pdev, iss, i);
		if (ret)
			goto error_iss;
	}

	/* Configure BTE BW_LIMITER field to max recommended value (1 GB) */
	iss_reg_update(iss, OMAP4_ISS_MEM_BTE, BTE_CTRL,
		       BTE_CTRL_BW_LIMITER_MASK,
		       18 << BTE_CTRL_BW_LIMITER_SHIFT);

	/* Perform ISP reset */
	ret = omap4iss_subclk_enable(iss, OMAP4_ISS_SUBCLK_ISP);
	if (ret < 0)
		goto error_iss;

	ret = iss_isp_reset(iss);
	if (ret < 0)
		goto error_iss;

	dev_info(iss->dev, "ISP Revision %08x found\n",
		 iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_REVISION));

	/* Interrupt */
	iss->irq_num = platform_get_irq(pdev, 0);
	if (iss->irq_num <= 0) {
		dev_err(iss->dev, "No IRQ resource\n");
		ret = -ENODEV;
		goto error_iss;
	}

	if (devm_request_irq(iss->dev, iss->irq_num, iss_isr, IRQF_SHARED,
			     "OMAP4 ISS", iss)) {
		dev_err(iss->dev, "Unable to request IRQ\n");
		ret = -EINVAL;
		goto error_iss;
	}

	/* Entities */
	ret = iss_initialize_modules(iss);
	if (ret < 0)
		goto error_iss;

	ret = iss_register_entities(iss);
	if (ret < 0)
		goto error_modules;

	omap4iss_put(iss);

	return 0;

error_modules:
	iss_cleanup_modules(iss);
error_iss:
	omap4iss_put(iss);
error:
	platform_set_drvdata(pdev, NULL);

	mutex_destroy(&iss->iss_mutex);

	return ret;
}