159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/*
259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * TI OMAP4 ISS V4L2 Driver
359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Copyright (C) 2012, Texas Instruments
559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * This program is free software; you can redistribute it and/or modify
959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * it under the terms of the GNU General Public License as published by
1059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * the Free Software Foundation; either version 2 of the License, or
1159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * (at your option) any later version.
1259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
1359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
1459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre#include <linux/clk.h>
1559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre#include <linux/delay.h>
1659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre#include <linux/device.h>
1759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre#include <linux/dma-mapping.h>
1859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre#include <linux/i2c.h>
1959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre#include <linux/interrupt.h>
2059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre#include <linux/module.h>
2159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre#include <linux/platform_device.h>
2259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre#include <linux/slab.h>
2359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre#include <linux/sched.h>
2459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre#include <linux/vmalloc.h>
2559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
2659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre#include <media/v4l2-common.h>
2759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre#include <media/v4l2-device.h>
2859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre#include <media/v4l2-ctrls.h>
2959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
3059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre#include "iss.h"
3159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre#include "iss_regs.h"
3259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
3359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre#define ISS_PRINT_REGISTER(iss, name)\
3459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	dev_dbg(iss->dev, "###ISS " #name "=0x%08x\n", \
3511abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart		iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_##name))
3659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
3759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic void iss_print_status(struct iss_device *iss)
3859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
3959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	dev_dbg(iss->dev, "-------------ISS HL Register dump-------------\n");
4059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
4159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ISS_PRINT_REGISTER(iss, HL_REVISION);
4259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ISS_PRINT_REGISTER(iss, HL_SYSCONFIG);
43ade1ec3736c432981fefaa07b20e818c8501a44eLaurent Pinchart	ISS_PRINT_REGISTER(iss, HL_IRQSTATUS(5));
44ade1ec3736c432981fefaa07b20e818c8501a44eLaurent Pinchart	ISS_PRINT_REGISTER(iss, HL_IRQENABLE_SET(5));
45ade1ec3736c432981fefaa07b20e818c8501a44eLaurent Pinchart	ISS_PRINT_REGISTER(iss, HL_IRQENABLE_CLR(5));
4659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ISS_PRINT_REGISTER(iss, CTRL);
4759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ISS_PRINT_REGISTER(iss, CLKCTRL);
4859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ISS_PRINT_REGISTER(iss, CLKSTAT);
4959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
5059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	dev_dbg(iss->dev, "-----------------------------------------------\n");
5159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
5259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
5359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/*
5459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * omap4iss_flush - Post pending L3 bus writes by doing a register readback
5559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @iss: OMAP4 ISS device
5659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
5759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * In order to force posting of pending writes, we need to write and
5859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * readback the same register, in this case the revision register.
5959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
6059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * See this link for reference:
6159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *   http://www.mail-archive.com/linux-omap@vger.kernel.org/msg08149.html
6259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
6359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrevoid omap4iss_flush(struct iss_device *iss)
6459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
6511abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart	iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION, 0);
6611abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart	iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION);
6759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
6859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
6959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/*
70af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart * iss_isp_enable_interrupts - Enable ISS ISP interrupts.
7159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @iss: OMAP4 ISS device
7259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
73af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchartstatic void omap4iss_isp_enable_interrupts(struct iss_device *iss)
7459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
75af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart	static const u32 isp_irq = ISP5_IRQ_OCP_ERR |
76af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart				   ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR |
77af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart				   ISP5_IRQ_RSZ_FIFO_OVF |
78af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart				   ISP5_IRQ_RSZ_INT_DMA |
79af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart				   ISP5_IRQ_ISIF_INT(0);
8059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
81af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart	/* Enable ISP interrupts */
82af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart	iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQSTATUS(0), isp_irq);
83af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart	iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQENABLE_SET(0),
84af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart		      isp_irq);
8559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
8659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
8759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/*
88af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart * iss_isp_disable_interrupts - Disable ISS interrupts.
8959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @iss: OMAP4 ISS device
9059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
91af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchartstatic void omap4iss_isp_disable_interrupts(struct iss_device *iss)
9259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
93af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart	iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQENABLE_CLR(0), ~0);
9459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
9559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
9659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/*
97af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart * iss_enable_interrupts - Enable ISS interrupts.
9859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @iss: OMAP4 ISS device
9959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
100af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchartstatic void iss_enable_interrupts(struct iss_device *iss)
10159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
102af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart	static const u32 hl_irq = ISS_HL_IRQ_CSIA | ISS_HL_IRQ_CSIB
103af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart				| ISS_HL_IRQ_ISP(0);
10459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
105af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart	/* Enable HL interrupts */
106af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart	iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQSTATUS(5), hl_irq);
107af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart	iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQENABLE_SET(5), hl_irq);
108af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart
109af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart	if (iss->regs[OMAP4_ISS_MEM_ISP_SYS1])
110af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart		omap4iss_isp_enable_interrupts(iss);
11159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
11259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
11359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/*
114af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart * iss_disable_interrupts - Disable ISS interrupts.
11559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @iss: OMAP4 ISS device
11659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
117af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchartstatic void iss_disable_interrupts(struct iss_device *iss)
11859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
119af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart	if (iss->regs[OMAP4_ISS_MEM_ISP_SYS1])
120af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart		omap4iss_isp_disable_interrupts(iss);
121af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart
122af15d025ecdf35ad1eb438595727d80155d8d28eLaurent Pinchart	iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQENABLE_CLR(5), ~0);
12359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
12459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
12559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreint omap4iss_get_external_info(struct iss_pipeline *pipe,
12659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			       struct media_link *link)
12759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
12859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct iss_device *iss =
12959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		container_of(pipe, struct iss_video, pipe)->iss;
13059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct v4l2_subdev_format fmt;
131ea72717e961d1166882370a87876bfeacc967eb0Laurent Pinchart	struct v4l2_ctrl *ctrl;
13259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	int ret;
13359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
13459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (!pipe->external)
13559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		return 0;
13659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
13759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (pipe->external_rate)
13859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		return 0;
13959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
14059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	memset(&fmt, 0, sizeof(fmt));
14159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
14259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	fmt.pad = link->source->index;
14359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
14459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = v4l2_subdev_call(media_entity_to_v4l2_subdev(link->sink->entity),
14559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			       pad, get_fmt, NULL, &fmt);
14659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0)
14759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		return -EPIPE;
14859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
14959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	pipe->external_bpp = omap4iss_video_format_info(fmt.format.code)->bpp;
15059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
151ea72717e961d1166882370a87876bfeacc967eb0Laurent Pinchart	ctrl = v4l2_ctrl_find(pipe->external->ctrl_handler,
152ea72717e961d1166882370a87876bfeacc967eb0Laurent Pinchart			      V4L2_CID_PIXEL_RATE);
153ea72717e961d1166882370a87876bfeacc967eb0Laurent Pinchart	if (ctrl == NULL) {
15459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		dev_warn(iss->dev, "no pixel rate control in subdev %s\n",
15559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			 pipe->external->name);
156ea72717e961d1166882370a87876bfeacc967eb0Laurent Pinchart		return -EPIPE;
15759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
15859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
159ea72717e961d1166882370a87876bfeacc967eb0Laurent Pinchart	pipe->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl);
16059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
16159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return 0;
16259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
16359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
16459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/*
16559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Configure the bridge. Valid inputs are
16659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
16759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * IPIPEIF_INPUT_CSI2A: CSI2a receiver
16859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * IPIPEIF_INPUT_CSI2B: CSI2b receiver
16959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
17059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * The bridge and lane shifter are configured according to the selected input
17159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * and the ISP platform data.
17259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
17359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrevoid omap4iss_configure_bridge(struct iss_device *iss,
17459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			       enum ipipeif_input_entity input)
17559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
17659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	u32 issctrl_val;
17759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	u32 isp5ctrl_val;
17859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
17911abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart	issctrl_val = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_CTRL);
18059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	issctrl_val &= ~ISS_CTRL_INPUT_SEL_MASK;
18159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	issctrl_val &= ~ISS_CTRL_CLK_DIV_MASK;
18259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
18311abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart	isp5ctrl_val = iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL);
18459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
18559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	switch (input) {
18659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	case IPIPEIF_INPUT_CSI2A:
18759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		issctrl_val |= ISS_CTRL_INPUT_SEL_CSI2A;
18859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		break;
18959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
19059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	case IPIPEIF_INPUT_CSI2B:
19159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		issctrl_val |= ISS_CTRL_INPUT_SEL_CSI2B;
19259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		break;
19359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
19459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	default:
19559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		return;
19659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
19759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
19859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	issctrl_val |= ISS_CTRL_SYNC_DETECT_VS_RAISING;
19959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
200cce093ee559779d376fbd767d70a5b0ce4cf015aLaurent Pinchart	isp5ctrl_val |= ISP5_CTRL_VD_PULSE_EXT | ISP5_CTRL_PSYNC_CLK_SEL |
201cce093ee559779d376fbd767d70a5b0ce4cf015aLaurent Pinchart			ISP5_CTRL_SYNC_ENABLE;
20259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
20311abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart	iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_CTRL, issctrl_val);
20411abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart	iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL, isp5ctrl_val);
20559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
20659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
207d14cb130f359878f88fbb1e73af15ccd823cd32fLaurent Pinchart#ifdef ISS_ISR_DEBUG
208380df42b5730541a740735052d61e9d2ee09d0ceLaurent Pinchartstatic void iss_isr_dbg(struct iss_device *iss, u32 irqstatus)
20959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
2105122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart	static const char * const name[] = {
2115122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"ISP_0",
2125122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"ISP_1",
2135122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"ISP_2",
2145122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"ISP_3",
2155122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"CSIA",
2165122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"CSIB",
2175122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"CCP2_0",
2185122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"CCP2_1",
2195122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"CCP2_2",
2205122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"CCP2_3",
2215122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"CBUFF",
2225122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"BTE",
2235122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"SIMCOP_0",
2245122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"SIMCOP_1",
2255122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"SIMCOP_2",
2265122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"SIMCOP_3",
2275122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"CCP2_8",
2285122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"HS_VS",
2295122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"18",
2305122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"19",
2315122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"20",
2325122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"21",
2335122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"22",
2345122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"23",
2355122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"24",
2365122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"25",
2375122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"26",
2385122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"27",
2395122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"28",
2405122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"29",
2415122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"30",
2425122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"31",
24359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	};
2445122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart	unsigned int i;
24559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
24659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	dev_dbg(iss->dev, "ISS IRQ: ");
24759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
24859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	for (i = 0; i < ARRAY_SIZE(name); i++) {
24959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		if ((1 << i) & irqstatus)
25059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			pr_cont("%s ", name[i]);
25159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
25259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	pr_cont("\n");
25359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
25459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
255380df42b5730541a740735052d61e9d2ee09d0ceLaurent Pinchartstatic void iss_isp_isr_dbg(struct iss_device *iss, u32 irqstatus)
2565122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart{
2575122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart	static const char * const name[] = {
2585122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"ISIF_0",
2595122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"ISIF_1",
2605122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"ISIF_2",
2615122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"ISIF_3",
2625122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"IPIPEREQ",
2635122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"IPIPELAST_PIX",
2645122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"IPIPEDMA",
2655122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"IPIPEBSC",
2665122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"IPIPEHST",
2675122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"IPIPEIF",
2685122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"AEW",
2695122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"AF",
2705122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"H3A",
2715122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"RSZ_REG",
2725122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"RSZ_LAST_PIX",
2735122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"RSZ_DMA",
2745122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"RSZ_CYC_RZA",
2755122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"RSZ_CYC_RZB",
2765122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"RSZ_FIFO_OVF",
2775122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"RSZ_FIFO_IN_BLK_ERR",
2785122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"20",
2795122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"21",
2805122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"RSZ_EOF0",
2815122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"RSZ_EOF1",
2825122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"H3A_EOF",
2835122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"IPIPE_EOF",
2845122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"26",
2855122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"IPIPE_DPC_INI",
2865122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"IPIPE_DPC_RNEW0",
2875122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"IPIPE_DPC_RNEW1",
2885122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"30",
2895122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		"OCP_ERR",
2905122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart	};
2915122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart	unsigned int i;
2925122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart
2935122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart	dev_dbg(iss->dev, "ISP IRQ: ");
2945122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart
2955122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart	for (i = 0; i < ARRAY_SIZE(name); i++) {
2965122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		if ((1 << i) & irqstatus)
2975122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart			pr_cont("%s ", name[i]);
2985122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart	}
2995122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart	pr_cont("\n");
3005122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart}
3015122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart#endif
3025122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart
30359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/*
30459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_isr - Interrupt Service Routine for ISS module.
30559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @irq: Not used currently.
30659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @_iss: Pointer to the OMAP4 ISS device
30759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
30859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Handles the corresponding callback if plugged in.
30959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
31059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Returns IRQ_HANDLED when IRQ was correctly handled, or IRQ_NONE when the
31159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * IRQ wasn't handled.
31259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
31359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic irqreturn_t iss_isr(int irq, void *_iss)
31459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
315ade1ec3736c432981fefaa07b20e818c8501a44eLaurent Pinchart	static const u32 ipipeif_events = ISP5_IRQ_IPIPEIF_IRQ |
316ade1ec3736c432981fefaa07b20e818c8501a44eLaurent Pinchart					  ISP5_IRQ_ISIF_INT(0);
317ade1ec3736c432981fefaa07b20e818c8501a44eLaurent Pinchart	static const u32 resizer_events = ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR |
31859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre					  ISP5_IRQ_RSZ_FIFO_OVF |
31959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre					  ISP5_IRQ_RSZ_INT_DMA;
32059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct iss_device *iss = _iss;
32159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	u32 irqstatus;
32259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
32311abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart	irqstatus = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQSTATUS(5));
32411abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart	iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQSTATUS(5), irqstatus);
32559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
32659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (irqstatus & ISS_HL_IRQ_CSIA)
32759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		omap4iss_csi2_isr(&iss->csi2a);
32859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
32959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (irqstatus & ISS_HL_IRQ_CSIB)
33059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		omap4iss_csi2_isr(&iss->csi2b);
33159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
33259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (irqstatus & ISS_HL_IRQ_ISP(0)) {
33311abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart		u32 isp_irqstatus = iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1,
33411abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart						 ISP5_IRQSTATUS(0));
33511abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart		iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQSTATUS(0),
33611abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart			      isp_irqstatus);
33759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
33859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		if (isp_irqstatus & ISP5_IRQ_OCP_ERR)
33959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			dev_dbg(iss->dev, "ISP5 OCP Error!\n");
34059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
34159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		if (isp_irqstatus & ipipeif_events) {
34259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			omap4iss_ipipeif_isr(&iss->ipipeif,
34359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre					     isp_irqstatus & ipipeif_events);
34459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		}
34559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
34659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		if (isp_irqstatus & resizer_events)
34759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			omap4iss_resizer_isr(&iss->resizer,
34859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre					     isp_irqstatus & resizer_events);
3495122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart
350d14cb130f359878f88fbb1e73af15ccd823cd32fLaurent Pinchart#ifdef ISS_ISR_DEBUG
3515122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart		iss_isp_isr_dbg(iss, isp_irqstatus);
3525122f6a26d4e706653e1677708594b82b1ec7cd3Laurent Pinchart#endif
35359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
35459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
35559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	omap4iss_flush(iss);
35659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
357d14cb130f359878f88fbb1e73af15ccd823cd32fLaurent Pinchart#ifdef ISS_ISR_DEBUG
35859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	iss_isr_dbg(iss, irqstatus);
35959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre#endif
36059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
36159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return IRQ_HANDLED;
36259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
36359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
36459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* -----------------------------------------------------------------------------
36559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Pipeline power management
36659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
36759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Entities must be powered up when part of a pipeline that contains at least
36859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * one open video device node.
36959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
37059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * To achieve this use the entity use_count field to track the number of users.
37159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * For entities corresponding to video device nodes the use_count field stores
37259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * the users count of the node. For entities corresponding to subdevs the
37359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * use_count field stores the total number of users of all video device nodes
37459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * in the pipeline.
37559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
37659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * The omap4iss_pipeline_pm_use() function must be called in the open() and
37759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * close() handlers of video device nodes. It increments or decrements the use
37859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * count of all subdev entities in the pipeline.
37959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
38059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * To react to link management on powered pipelines, the link setup notification
38159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * callback updates the use count of all entities in the source and sink sides
38259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * of the link.
38359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
38459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
38559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/*
38659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_pipeline_pm_use_count - Count the number of users of a pipeline
38759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @entity: The entity
38859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
38959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Return the total number of users of all video device nodes in the pipeline.
39059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
39159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_pipeline_pm_use_count(struct media_entity *entity)
39259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
39359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct media_entity_graph graph;
39459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	int use = 0;
39559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
39659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	media_entity_graph_walk_start(&graph, entity);
39759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
39859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	while ((entity = media_entity_graph_walk_next(&graph))) {
39959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
40059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			use += entity->use_count;
40159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
40259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
40359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return use;
40459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
40559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
40659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/*
40759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_pipeline_pm_power_one - Apply power change to an entity
40859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @entity: The entity
40959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @change: Use count change
41059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
41159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Change the entity use count by @change. If the entity is a subdev update its
41259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * power state by calling the core::s_power operation when the use count goes
41359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * from 0 to != 0 or from != 0 to 0.
41459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
41559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Return 0 on success or a negative error code on failure.
41659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
41759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_pipeline_pm_power_one(struct media_entity *entity, int change)
41859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
41959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct v4l2_subdev *subdev;
42059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
42159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV
42259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	       ? media_entity_to_v4l2_subdev(entity) : NULL;
42359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
42459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (entity->use_count == 0 && change > 0 && subdev != NULL) {
42559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		int ret;
42659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
42759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		ret = v4l2_subdev_call(subdev, core, s_power, 1);
42859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		if (ret < 0 && ret != -ENOIOCTLCMD)
42959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			return ret;
43059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
43159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
43259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	entity->use_count += change;
43359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	WARN_ON(entity->use_count < 0);
43459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
43559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (entity->use_count == 0 && change < 0 && subdev != NULL)
43659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		v4l2_subdev_call(subdev, core, s_power, 0);
43759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
43859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return 0;
43959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
44059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
44159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/*
44259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_pipeline_pm_power - Apply power change to all entities in a pipeline
44359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @entity: The entity
44459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @change: Use count change
44559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
44659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Walk the pipeline to update the use count and the power state of all non-node
44759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * entities.
44859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
44959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Return 0 on success or a negative error code on failure.
45059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
45159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_pipeline_pm_power(struct media_entity *entity, int change)
45259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
45359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct media_entity_graph graph;
45459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct media_entity *first = entity;
45559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	int ret = 0;
45659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
45759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (!change)
45859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		return 0;
45959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
46059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	media_entity_graph_walk_start(&graph, entity);
46159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
46259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	while (!ret && (entity = media_entity_graph_walk_next(&graph)))
46359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
46459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			ret = iss_pipeline_pm_power_one(entity, change);
46559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
46659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (!ret)
46759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		return 0;
46859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
46959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	media_entity_graph_walk_start(&graph, first);
47059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
47159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	while ((first = media_entity_graph_walk_next(&graph))
47259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	       && first != entity)
47359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE)
47459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			iss_pipeline_pm_power_one(first, -change);
47559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
47659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return ret;
47759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
47859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
47959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/*
48059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * omap4iss_pipeline_pm_use - Update the use count of an entity
48159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @entity: The entity
48259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @use: Use (1) or stop using (0) the entity
48359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
48459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Update the use count of all entities in the pipeline and power entities on or
48559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * off accordingly.
48659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
48759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Return 0 on success or a negative error code on failure. Powering entities
48859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * off is assumed to never fail. No failure can occur when the use parameter is
48959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * set to 0.
49059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
49159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreint omap4iss_pipeline_pm_use(struct media_entity *entity, int use)
49259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
49359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	int change = use ? 1 : -1;
49459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	int ret;
49559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
49659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	mutex_lock(&entity->parent->graph_mutex);
49759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
49859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	/* Apply use count to node. */
49959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	entity->use_count += change;
50059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	WARN_ON(entity->use_count < 0);
50159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
50259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	/* Apply power change to connected non-nodes. */
50359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = iss_pipeline_pm_power(entity, change);
50459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0)
50559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		entity->use_count -= change;
50659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
50759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	mutex_unlock(&entity->parent->graph_mutex);
50859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
50959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return ret;
51059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
51159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
51259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/*
51359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_pipeline_link_notify - Link management notification callback
51459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @link: The link
51559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @flags: New link flags that will be applied
51659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
51759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * React to link management on powered pipelines by updating the use count of
51859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * all entities in the source and sink sides of the link. Entities are powered
51959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * on or off accordingly.
52059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
52159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Return 0 on success or a negative error code on failure. Powering entities
52259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * off is assumed to never fail. This function will not fail for disconnection
52359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * events.
52459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
52559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_pipeline_link_notify(struct media_link *link, u32 flags,
52659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre				    unsigned int notification)
52759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
52859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct media_entity *source = link->source->entity;
52959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct media_entity *sink = link->sink->entity;
53059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	int source_use = iss_pipeline_pm_use_count(source);
53159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	int sink_use = iss_pipeline_pm_use_count(sink);
53259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	int ret;
53359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
53459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH &&
53559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	    !(link->flags & MEDIA_LNK_FL_ENABLED)) {
53659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		/* Powering off entities is assumed to never fail. */
53759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		iss_pipeline_pm_power(source, -sink_use);
53859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		iss_pipeline_pm_power(sink, -source_use);
53959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		return 0;
54059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
54159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
54259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH &&
54359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		(flags & MEDIA_LNK_FL_ENABLED)) {
54459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		ret = iss_pipeline_pm_power(source, sink_use);
54559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		if (ret < 0)
54659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			return ret;
54759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
54859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		ret = iss_pipeline_pm_power(sink, source_use);
54959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		if (ret < 0)
55059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			iss_pipeline_pm_power(source, -sink_use);
55159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
55259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		return ret;
55359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
55459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
55559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return 0;
55659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
55759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
55859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* -----------------------------------------------------------------------------
55959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Pipeline stream management
56059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
56159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
56259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/*
56359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_pipeline_enable - Enable streaming on a pipeline
56459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @pipe: ISS pipeline
56559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @mode: Stream mode (single shot or continuous)
56659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
56759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Walk the entities chain starting at the pipeline output video node and start
56859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * all modules in the chain in the given mode.
56959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
57059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Return 0 if successful, or the return value of the failed video::s_stream
57159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * operation otherwise.
57259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
57359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_pipeline_enable(struct iss_pipeline *pipe,
57459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			       enum iss_pipeline_stream_state mode)
57559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
576f3632ba850c70bf24a80295621857166e0c0b14cLaurent Pinchart	struct iss_device *iss = pipe->output->iss;
57759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct media_entity *entity;
57859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct media_pad *pad;
57959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct v4l2_subdev *subdev;
58059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	unsigned long flags;
58159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	int ret;
58259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
583f3632ba850c70bf24a80295621857166e0c0b14cLaurent Pinchart	/* If one of the entities in the pipeline has crashed it will not work
584f3632ba850c70bf24a80295621857166e0c0b14cLaurent Pinchart	 * properly. Refuse to start streaming in that case. This check must be
585f3632ba850c70bf24a80295621857166e0c0b14cLaurent Pinchart	 * performed before the loop below to avoid starting entities if the
586f3632ba850c70bf24a80295621857166e0c0b14cLaurent Pinchart	 * pipeline won't start anyway (those entities would then likely fail to
587f3632ba850c70bf24a80295621857166e0c0b14cLaurent Pinchart	 * stop, making the problem worse).
588f3632ba850c70bf24a80295621857166e0c0b14cLaurent Pinchart	 */
589f3632ba850c70bf24a80295621857166e0c0b14cLaurent Pinchart	if (pipe->entities & iss->crashed)
590f3632ba850c70bf24a80295621857166e0c0b14cLaurent Pinchart		return -EIO;
591f3632ba850c70bf24a80295621857166e0c0b14cLaurent Pinchart
59259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	spin_lock_irqsave(&pipe->lock, flags);
59359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	pipe->state &= ~(ISS_PIPELINE_IDLE_INPUT | ISS_PIPELINE_IDLE_OUTPUT);
59459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	spin_unlock_irqrestore(&pipe->lock, flags);
59559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
59659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	pipe->do_propagation = false;
59759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
59859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	entity = &pipe->output->video.entity;
59959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	while (1) {
60059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		pad = &entity->pads[0];
60159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		if (!(pad->flags & MEDIA_PAD_FL_SINK))
60259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			break;
60359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
60459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		pad = media_entity_remote_pad(pad);
60559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		if (pad == NULL ||
60659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
60759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			break;
60859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
60959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		entity = pad->entity;
61059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		subdev = media_entity_to_v4l2_subdev(entity);
61159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
61259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		ret = v4l2_subdev_call(subdev, video, s_stream, mode);
61359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		if (ret < 0 && ret != -ENOIOCTLCMD)
61459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			return ret;
61559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
61659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	iss_print_status(pipe->output->iss);
61759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return 0;
61859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
61959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
62059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/*
62159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_pipeline_disable - Disable streaming on a pipeline
62259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @pipe: ISS pipeline
62359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
62459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Walk the entities chain starting at the pipeline output video node and stop
62559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * all modules in the chain. Wait synchronously for the modules to be stopped if
62659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * necessary.
62759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
62859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_pipeline_disable(struct iss_pipeline *pipe)
62959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
630f3632ba850c70bf24a80295621857166e0c0b14cLaurent Pinchart	struct iss_device *iss = pipe->output->iss;
63159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct media_entity *entity;
63259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct media_pad *pad;
63359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct v4l2_subdev *subdev;
6346016498f2b9d72b4f813d7349f0621ccc92c4f5aLaurent Pinchart	int failure = 0;
6356016498f2b9d72b4f813d7349f0621ccc92c4f5aLaurent Pinchart	int ret;
63659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
63759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	entity = &pipe->output->video.entity;
63859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	while (1) {
63959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		pad = &entity->pads[0];
64059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		if (!(pad->flags & MEDIA_PAD_FL_SINK))
64159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			break;
64259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
64359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		pad = media_entity_remote_pad(pad);
64459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		if (pad == NULL ||
64559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
64659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			break;
64759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
64859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		entity = pad->entity;
64959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		subdev = media_entity_to_v4l2_subdev(entity);
65059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
6516016498f2b9d72b4f813d7349f0621ccc92c4f5aLaurent Pinchart		ret = v4l2_subdev_call(subdev, video, s_stream, 0);
6526016498f2b9d72b4f813d7349f0621ccc92c4f5aLaurent Pinchart		if (ret < 0) {
6536016498f2b9d72b4f813d7349f0621ccc92c4f5aLaurent Pinchart			dev_dbg(iss->dev, "%s: module stop timeout.\n",
6546016498f2b9d72b4f813d7349f0621ccc92c4f5aLaurent Pinchart				subdev->name);
655f3632ba850c70bf24a80295621857166e0c0b14cLaurent Pinchart			/* If the entity failed to stopped, assume it has
656f3632ba850c70bf24a80295621857166e0c0b14cLaurent Pinchart			 * crashed. Mark it as such, the ISS will be reset when
657f3632ba850c70bf24a80295621857166e0c0b14cLaurent Pinchart			 * applications will release it.
658f3632ba850c70bf24a80295621857166e0c0b14cLaurent Pinchart			 */
659f3632ba850c70bf24a80295621857166e0c0b14cLaurent Pinchart			iss->crashed |= 1U << subdev->entity.id;
6606016498f2b9d72b4f813d7349f0621ccc92c4f5aLaurent Pinchart			failure = -ETIMEDOUT;
6616016498f2b9d72b4f813d7349f0621ccc92c4f5aLaurent Pinchart		}
66259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
66359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
6646016498f2b9d72b4f813d7349f0621ccc92c4f5aLaurent Pinchart	return failure;
66559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
66659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
66759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/*
66859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * omap4iss_pipeline_set_stream - Enable/disable streaming on a pipeline
66959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @pipe: ISS pipeline
67059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @state: Stream state (stopped, single shot or continuous)
67159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
67259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Set the pipeline to the given stream state. Pipelines can be started in
67359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * single-shot or continuous mode.
67459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
67559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Return 0 if successful, or the return value of the failed video::s_stream
67659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * operation otherwise. The pipeline state is not updated when the operation
67759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * fails, except when stopping the pipeline.
67859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
67959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreint omap4iss_pipeline_set_stream(struct iss_pipeline *pipe,
68059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre				 enum iss_pipeline_stream_state state)
68159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
68259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	int ret;
68359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
68459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (state == ISS_PIPELINE_STREAM_STOPPED)
68559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		ret = iss_pipeline_disable(pipe);
68659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	else
68759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		ret = iss_pipeline_enable(pipe, state);
68859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
68959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret == 0 || state == ISS_PIPELINE_STREAM_STOPPED)
69059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		pipe->stream_state = state;
69159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
69259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return ret;
69359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
69459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
69559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/*
696112da08512bb0c58c169ec8bda0166f627250a2cLaurent Pinchart * omap4iss_pipeline_cancel_stream - Cancel stream on a pipeline
697112da08512bb0c58c169ec8bda0166f627250a2cLaurent Pinchart * @pipe: ISS pipeline
698112da08512bb0c58c169ec8bda0166f627250a2cLaurent Pinchart *
699112da08512bb0c58c169ec8bda0166f627250a2cLaurent Pinchart * Cancelling a stream mark all buffers on all video nodes in the pipeline as
700112da08512bb0c58c169ec8bda0166f627250a2cLaurent Pinchart * erroneous and makes sure no new buffer can be queued. This function is called
701112da08512bb0c58c169ec8bda0166f627250a2cLaurent Pinchart * when a fatal error that prevents any further operation on the pipeline
702112da08512bb0c58c169ec8bda0166f627250a2cLaurent Pinchart * occurs.
703112da08512bb0c58c169ec8bda0166f627250a2cLaurent Pinchart */
704112da08512bb0c58c169ec8bda0166f627250a2cLaurent Pinchartvoid omap4iss_pipeline_cancel_stream(struct iss_pipeline *pipe)
705112da08512bb0c58c169ec8bda0166f627250a2cLaurent Pinchart{
706112da08512bb0c58c169ec8bda0166f627250a2cLaurent Pinchart	if (pipe->input)
707112da08512bb0c58c169ec8bda0166f627250a2cLaurent Pinchart		omap4iss_video_cancel_stream(pipe->input);
708112da08512bb0c58c169ec8bda0166f627250a2cLaurent Pinchart	if (pipe->output)
709112da08512bb0c58c169ec8bda0166f627250a2cLaurent Pinchart		omap4iss_video_cancel_stream(pipe->output);
710112da08512bb0c58c169ec8bda0166f627250a2cLaurent Pinchart}
711112da08512bb0c58c169ec8bda0166f627250a2cLaurent Pinchart
712112da08512bb0c58c169ec8bda0166f627250a2cLaurent Pinchart/*
71359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_pipeline_is_last - Verify if entity has an enabled link to the output
71459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *			  video node
71559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @me: ISS module's media entity
71659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
71759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Returns 1 if the entity has an enabled link to the output video node or 0
71859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * otherwise. It's true only while pipeline can have no more than one output
71959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * node.
72059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
72159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_pipeline_is_last(struct media_entity *me)
72259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
72359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct iss_pipeline *pipe;
72459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct media_pad *pad;
72559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
72659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (!me->pipe)
72759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		return 0;
72859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	pipe = to_iss_pipeline(me);
72959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (pipe->stream_state == ISS_PIPELINE_STREAM_STOPPED)
73059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		return 0;
73159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	pad = media_entity_remote_pad(&pipe->output->pad);
73259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return pad->entity == me;
73359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
73459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
73559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_reset(struct iss_device *iss)
73659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
73705b1b986b540fe48f98a09b087b054754d67ef41Laurent Pinchart	unsigned int timeout;
73859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
73911abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart	iss_reg_set(iss, OMAP4_ISS_MEM_TOP, ISS_HL_SYSCONFIG,
74011abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart		    ISS_HL_SYSCONFIG_SOFTRESET);
74159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
74205b1b986b540fe48f98a09b087b054754d67ef41Laurent Pinchart	timeout = iss_poll_condition_timeout(
74305b1b986b540fe48f98a09b087b054754d67ef41Laurent Pinchart		!(iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_SYSCONFIG) &
744fa7014f569b2a38b926792a9b9021df0af0556e9Laurent Pinchart		ISS_HL_SYSCONFIG_SOFTRESET), 1000, 10, 100);
74505b1b986b540fe48f98a09b087b054754d67ef41Laurent Pinchart	if (timeout) {
74605b1b986b540fe48f98a09b087b054754d67ef41Laurent Pinchart		dev_err(iss->dev, "ISS reset timeout\n");
74705b1b986b540fe48f98a09b087b054754d67ef41Laurent Pinchart		return -ETIMEDOUT;
74859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
74959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
750f3632ba850c70bf24a80295621857166e0c0b14cLaurent Pinchart	iss->crashed = 0;
75159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return 0;
75259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
75359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
75459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_isp_reset(struct iss_device *iss)
75559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
75605b1b986b540fe48f98a09b087b054754d67ef41Laurent Pinchart	unsigned int timeout;
75759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
75859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	/* Fist, ensure that the ISP is IDLE (no transactions happening) */
75911abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart	iss_reg_update(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_SYSCONFIG,
76011abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart		       ISP5_SYSCONFIG_STANDBYMODE_MASK,
76111abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart		       ISP5_SYSCONFIG_STANDBYMODE_SMART);
76259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
76311abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart	iss_reg_set(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL, ISP5_CTRL_MSTANDBY);
76459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
76505b1b986b540fe48f98a09b087b054754d67ef41Laurent Pinchart	timeout = iss_poll_condition_timeout(
76605b1b986b540fe48f98a09b087b054754d67ef41Laurent Pinchart		iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL) &
76705b1b986b540fe48f98a09b087b054754d67ef41Laurent Pinchart		ISP5_CTRL_MSTANDBY_WAIT, 1000000, 1000, 1500);
76805b1b986b540fe48f98a09b087b054754d67ef41Laurent Pinchart	if (timeout) {
76905b1b986b540fe48f98a09b087b054754d67ef41Laurent Pinchart		dev_err(iss->dev, "ISP5 standby timeout\n");
77005b1b986b540fe48f98a09b087b054754d67ef41Laurent Pinchart		return -ETIMEDOUT;
77159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
77259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
77359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	/* Now finally, do the reset */
77411abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart	iss_reg_set(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_SYSCONFIG,
77511abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart		    ISP5_SYSCONFIG_SOFTRESET);
77659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
77705b1b986b540fe48f98a09b087b054754d67ef41Laurent Pinchart	timeout = iss_poll_condition_timeout(
77805b1b986b540fe48f98a09b087b054754d67ef41Laurent Pinchart		!(iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_SYSCONFIG) &
77905b1b986b540fe48f98a09b087b054754d67ef41Laurent Pinchart		ISP5_SYSCONFIG_SOFTRESET), 1000000, 1000, 1500);
78005b1b986b540fe48f98a09b087b054754d67ef41Laurent Pinchart	if (timeout) {
78105b1b986b540fe48f98a09b087b054754d67ef41Laurent Pinchart		dev_err(iss->dev, "ISP5 reset timeout\n");
78205b1b986b540fe48f98a09b087b054754d67ef41Laurent Pinchart		return -ETIMEDOUT;
78359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
78459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
78559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return 0;
78659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
78759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
78859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/*
78959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_module_sync_idle - Helper to sync module with its idle state
79059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @me: ISS submodule's media entity
79159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @wait: ISS submodule's wait queue for streamoff/interrupt synchronization
79259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @stopping: flag which tells module wants to stop
79359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
79459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * This function checks if ISS submodule needs to wait for next interrupt. If
79559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * yes, makes the caller to sleep while waiting for such event.
79659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
79759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreint omap4iss_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait,
79859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			      atomic_t *stopping)
79959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
80059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct iss_pipeline *pipe = to_iss_pipeline(me);
80159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct iss_video *video = pipe->output;
80259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	unsigned long flags;
80359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
80459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (pipe->stream_state == ISS_PIPELINE_STREAM_STOPPED ||
80559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	    (pipe->stream_state == ISS_PIPELINE_STREAM_SINGLESHOT &&
80659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	     !iss_pipeline_ready(pipe)))
80759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		return 0;
80859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
80959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	/*
81059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	 * atomic_set() doesn't include memory barrier on ARM platform for SMP
81159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	 * scenario. We'll call it here to avoid race conditions.
81259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	 */
81359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	atomic_set(stopping, 1);
81459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	smp_wmb();
81559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
81659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	/*
81759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	 * If module is the last one, it's writing to memory. In this case,
81859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	 * it's necessary to check if the module is already paused due to
81959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	 * DMA queue underrun or if it has to wait for next interrupt to be
82059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	 * idle.
82159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	 * If it isn't the last one, the function won't sleep but *stopping
82259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	 * will still be set to warn next submodule caller's interrupt the
82359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	 * module wants to be idle.
82459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	 */
82559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (!iss_pipeline_is_last(me))
82659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		return 0;
82759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
82859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	spin_lock_irqsave(&video->qlock, flags);
82959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (video->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) {
83059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		spin_unlock_irqrestore(&video->qlock, flags);
83159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		atomic_set(stopping, 0);
83259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		smp_wmb();
83359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		return 0;
83459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
83559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	spin_unlock_irqrestore(&video->qlock, flags);
83659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (!wait_event_timeout(*wait, !atomic_read(stopping),
83759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre				msecs_to_jiffies(1000))) {
83859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		atomic_set(stopping, 0);
83959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		smp_wmb();
84059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		return -ETIMEDOUT;
84159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
84259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
84359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return 0;
84459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
84559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
84659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/*
84759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * omap4iss_module_sync_is_stopped - Helper to verify if module was stopping
84859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @wait: ISS submodule's wait queue for streamoff/interrupt synchronization
84959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @stopping: flag which tells module wants to stop
85059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
85159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * This function checks if ISS submodule was stopping. In case of yes, it
85259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * notices the caller by setting stopping to 0 and waking up the wait queue.
85359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Returns 1 if it was stopping or 0 otherwise.
85459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
85559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreint omap4iss_module_sync_is_stopping(wait_queue_head_t *wait,
85659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre				     atomic_t *stopping)
85759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
85859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (atomic_cmpxchg(stopping, 1, 0)) {
85959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		wake_up(wait);
86059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		return 1;
86159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
86259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
86359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return 0;
86459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
86559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
86659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* --------------------------------------------------------------------------
86759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Clock management
86859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
86959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
87059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre#define ISS_CLKCTRL_MASK	(ISS_CLKCTRL_CSI2_A |\
87159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre				 ISS_CLKCTRL_CSI2_B |\
87259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre				 ISS_CLKCTRL_ISP)
87359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
87459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int __iss_subclk_update(struct iss_device *iss)
87559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
87659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	u32 clk = 0;
87759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	int ret = 0, timeout = 1000;
87859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
87959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (iss->subclk_resources & OMAP4_ISS_SUBCLK_CSI2_A)
88059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		clk |= ISS_CLKCTRL_CSI2_A;
88159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
88259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (iss->subclk_resources & OMAP4_ISS_SUBCLK_CSI2_B)
88359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		clk |= ISS_CLKCTRL_CSI2_B;
88459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
88559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (iss->subclk_resources & OMAP4_ISS_SUBCLK_ISP)
88659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		clk |= ISS_CLKCTRL_ISP;
88759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
88811abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart	iss_reg_update(iss, OMAP4_ISS_MEM_TOP, ISS_CLKCTRL,
88911abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart		       ISS_CLKCTRL_MASK, clk);
89059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
89159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	/* Wait for HW assertion */
89259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	while (--timeout > 0) {
89359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		udelay(1);
89411abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart		if ((iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_CLKSTAT) &
89511abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart		    ISS_CLKCTRL_MASK) == clk)
89659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			break;
89759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
89859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
89959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (!timeout)
90059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		ret = -EBUSY;
90159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
90259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return ret;
90359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
90459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
90559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreint omap4iss_subclk_enable(struct iss_device *iss,
90659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			    enum iss_subclk_resource res)
90759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
90859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	iss->subclk_resources |= res;
90959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
91059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return __iss_subclk_update(iss);
91159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
91259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
91359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreint omap4iss_subclk_disable(struct iss_device *iss,
91459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			     enum iss_subclk_resource res)
91559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
91659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	iss->subclk_resources &= ~res;
91759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
91859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return __iss_subclk_update(iss);
91959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
92059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
92159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre#define ISS_ISP5_CLKCTRL_MASK	(ISP5_CTRL_BL_CLK_ENABLE |\
92259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre				 ISP5_CTRL_ISIF_CLK_ENABLE |\
92359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre				 ISP5_CTRL_H3A_CLK_ENABLE |\
92459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre				 ISP5_CTRL_RSZ_CLK_ENABLE |\
92559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre				 ISP5_CTRL_IPIPE_CLK_ENABLE |\
92659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre				 ISP5_CTRL_IPIPEIF_CLK_ENABLE)
92759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
92868c03a666c36068428fed43010bde521d4341079Laurent Pinchartstatic void __iss_isp_subclk_update(struct iss_device *iss)
92959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
93059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	u32 clk = 0;
93159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
93259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_ISIF)
93359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		clk |= ISP5_CTRL_ISIF_CLK_ENABLE;
93459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
93559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_H3A)
93659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		clk |= ISP5_CTRL_H3A_CLK_ENABLE;
93759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
93859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_RSZ)
93959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		clk |= ISP5_CTRL_RSZ_CLK_ENABLE;
94059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
94159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_IPIPE)
94259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		clk |= ISP5_CTRL_IPIPE_CLK_ENABLE;
94359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
94459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_IPIPEIF)
94559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		clk |= ISP5_CTRL_IPIPEIF_CLK_ENABLE;
94659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
94759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (clk)
94859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		clk |= ISP5_CTRL_BL_CLK_ENABLE;
94959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
95011abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart	iss_reg_update(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL,
95111abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart		       ISS_ISP5_CLKCTRL_MASK, clk);
95259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
95359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
95468c03a666c36068428fed43010bde521d4341079Laurent Pinchartvoid omap4iss_isp_subclk_enable(struct iss_device *iss,
95559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre				enum iss_isp_subclk_resource res)
95659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
95759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	iss->isp_subclk_resources |= res;
95859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
95968c03a666c36068428fed43010bde521d4341079Laurent Pinchart	__iss_isp_subclk_update(iss);
96059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
96159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
96268c03a666c36068428fed43010bde521d4341079Laurent Pinchartvoid omap4iss_isp_subclk_disable(struct iss_device *iss,
96368c03a666c36068428fed43010bde521d4341079Laurent Pinchart				 enum iss_isp_subclk_resource res)
96459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
96559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	iss->isp_subclk_resources &= ~res;
96659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
96768c03a666c36068428fed43010bde521d4341079Laurent Pinchart	__iss_isp_subclk_update(iss);
96859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
96959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
97059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/*
97159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_enable_clocks - Enable ISS clocks
97259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @iss: OMAP4 ISS device
97359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
97459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Return 0 if successful, or clk_enable return value if any of tthem fails.
97559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
97659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_enable_clocks(struct iss_device *iss)
97759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
9782b16b44a1c44814ed00cf750d20f3c404b5d4e48Laurent Pinchart	int ret;
97959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
9802b16b44a1c44814ed00cf750d20f3c404b5d4e48Laurent Pinchart	ret = clk_enable(iss->iss_fck);
9812b16b44a1c44814ed00cf750d20f3c404b5d4e48Laurent Pinchart	if (ret) {
98259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		dev_err(iss->dev, "clk_enable iss_fck failed\n");
9832b16b44a1c44814ed00cf750d20f3c404b5d4e48Laurent Pinchart		return ret;
98459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
98559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
9862b16b44a1c44814ed00cf750d20f3c404b5d4e48Laurent Pinchart	ret = clk_enable(iss->iss_ctrlclk);
9872b16b44a1c44814ed00cf750d20f3c404b5d4e48Laurent Pinchart	if (ret) {
98859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		dev_err(iss->dev, "clk_enable iss_ctrlclk failed\n");
9892b16b44a1c44814ed00cf750d20f3c404b5d4e48Laurent Pinchart		clk_disable(iss->iss_fck);
9902b16b44a1c44814ed00cf750d20f3c404b5d4e48Laurent Pinchart		return ret;
99159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
99259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
9932b16b44a1c44814ed00cf750d20f3c404b5d4e48Laurent Pinchart	return 0;
99459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
99559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
99659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/*
99759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_disable_clocks - Disable ISS clocks
99859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @iss: OMAP4 ISS device
99959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
100059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic void iss_disable_clocks(struct iss_device *iss)
100159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
100259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	clk_disable(iss->iss_ctrlclk);
100359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	clk_disable(iss->iss_fck);
100459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
100559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
100659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_get_clocks(struct iss_device *iss)
100759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
10081153be56a10576abc3dd2a89aee59debb4dcc2b6Laurent Pinchart	iss->iss_fck = devm_clk_get(iss->dev, "iss_fck");
100959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (IS_ERR(iss->iss_fck)) {
101059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		dev_err(iss->dev, "Unable to get iss_fck clock info\n");
101159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		return PTR_ERR(iss->iss_fck);
101259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
101359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
10141153be56a10576abc3dd2a89aee59debb4dcc2b6Laurent Pinchart	iss->iss_ctrlclk = devm_clk_get(iss->dev, "iss_ctrlclk");
101559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (IS_ERR(iss->iss_ctrlclk)) {
101659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		dev_err(iss->dev, "Unable to get iss_ctrlclk clock info\n");
1017057ef1e56c956b4f68f33c8d0ccd301a0ecb6326Vitaly Osipov		return PTR_ERR(iss->iss_ctrlclk);
101859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
101959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
102059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return 0;
102159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
102259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
102359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/*
102459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * omap4iss_get - Acquire the ISS resource.
102559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
102659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Initializes the clocks for the first acquire.
102759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
102859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Increment the reference count on the ISS. If the first reference is taken,
102959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * enable clocks and power-up all submodules.
103059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
103159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Return a pointer to the ISS device structure, or NULL if an error occurred.
103259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
103359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestruct iss_device *omap4iss_get(struct iss_device *iss)
103459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
103559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct iss_device *__iss = iss;
103659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
103759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (iss == NULL)
103859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		return NULL;
103959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
104059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	mutex_lock(&iss->iss_mutex);
104159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (iss->ref_count > 0)
104259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto out;
104359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
104459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (iss_enable_clocks(iss) < 0) {
104559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		__iss = NULL;
104659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto out;
104759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
104859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
104959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	iss_enable_interrupts(iss);
105059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
105159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreout:
105259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (__iss != NULL)
105359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		iss->ref_count++;
105459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	mutex_unlock(&iss->iss_mutex);
105559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
105659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return __iss;
105759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
105859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
105959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/*
106059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * omap4iss_put - Release the ISS
106159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
106259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Decrement the reference count on the ISS. If the last reference is released,
106359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * power-down all submodules, disable clocks and free temporary buffers.
106459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
106559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrevoid omap4iss_put(struct iss_device *iss)
106659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
106759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (iss == NULL)
106859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		return;
106959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
107059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	mutex_lock(&iss->iss_mutex);
107159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	BUG_ON(iss->ref_count == 0);
107259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (--iss->ref_count == 0) {
107359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		iss_disable_interrupts(iss);
1074f3632ba850c70bf24a80295621857166e0c0b14cLaurent Pinchart		/* Reset the ISS if an entity has failed to stop. This is the
1075f3632ba850c70bf24a80295621857166e0c0b14cLaurent Pinchart		 * only way to recover from such conditions, although it would
1076f3632ba850c70bf24a80295621857166e0c0b14cLaurent Pinchart		 * be worth investigating whether resetting the ISP only can't
1077f3632ba850c70bf24a80295621857166e0c0b14cLaurent Pinchart		 * fix the problem in some cases.
1078f3632ba850c70bf24a80295621857166e0c0b14cLaurent Pinchart		 */
1079f3632ba850c70bf24a80295621857166e0c0b14cLaurent Pinchart		if (iss->crashed)
1080f3632ba850c70bf24a80295621857166e0c0b14cLaurent Pinchart			iss_reset(iss);
108159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		iss_disable_clocks(iss);
108259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
108359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	mutex_unlock(&iss->iss_mutex);
108459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
108559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
108659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_map_mem_resource(struct platform_device *pdev,
108759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre				struct iss_device *iss,
108859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre				enum iss_mem_resources res)
108959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
109059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct resource *mem;
109159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
109259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	mem = platform_get_resource(pdev, IORESOURCE_MEM, res);
109359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
10941153be56a10576abc3dd2a89aee59debb4dcc2b6Laurent Pinchart	iss->regs[res] = devm_ioremap_resource(iss->dev, mem);
109559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
10961153be56a10576abc3dd2a89aee59debb4dcc2b6Laurent Pinchart	return PTR_ERR_OR_ZERO(iss->regs[res]);
109759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
109859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
109959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic void iss_unregister_entities(struct iss_device *iss)
110059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
110159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	omap4iss_resizer_unregister_entities(&iss->resizer);
110259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	omap4iss_ipipe_unregister_entities(&iss->ipipe);
110359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	omap4iss_ipipeif_unregister_entities(&iss->ipipeif);
110459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	omap4iss_csi2_unregister_entities(&iss->csi2a);
110559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	omap4iss_csi2_unregister_entities(&iss->csi2b);
110659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
110759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	v4l2_device_unregister(&iss->v4l2_dev);
110859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	media_device_unregister(&iss->media_dev);
110959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
111059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
111159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/*
111259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_register_subdev_group - Register a group of subdevices
111359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @iss: OMAP4 ISS device
111459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @board_info: I2C subdevs board information array
111559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
111659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Register all I2C subdevices in the board_info array. The array must be
111759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * terminated by a NULL entry, and the first entry must be the sensor.
111859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre *
111959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Return a pointer to the sensor media entity if it has been successfully
112059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * registered, or NULL otherwise.
112159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */
112259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic struct v4l2_subdev *
112359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreiss_register_subdev_group(struct iss_device *iss,
112459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		     struct iss_subdev_i2c_board_info *board_info)
112559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
112659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct v4l2_subdev *sensor = NULL;
112759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	unsigned int first;
112859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
112959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (board_info->board_info == NULL)
113059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		return NULL;
113159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
113259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	for (first = 1; board_info->board_info; ++board_info, first = 0) {
113359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		struct v4l2_subdev *subdev;
113459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		struct i2c_adapter *adapter;
113559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
113659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		adapter = i2c_get_adapter(board_info->i2c_adapter_id);
113759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		if (adapter == NULL) {
1138499226fb196fef838fa38700b96448a2ec41b704Laurent Pinchart			dev_err(iss->dev,
1139499226fb196fef838fa38700b96448a2ec41b704Laurent Pinchart				"%s: Unable to get I2C adapter %d for device %s\n",
1140499226fb196fef838fa38700b96448a2ec41b704Laurent Pinchart				__func__, board_info->i2c_adapter_id,
114159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre				board_info->board_info->type);
114259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			continue;
114359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		}
114459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
114559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		subdev = v4l2_i2c_new_subdev_board(&iss->v4l2_dev, adapter,
114659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre				board_info->board_info, NULL);
114759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		if (subdev == NULL) {
114859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			dev_err(iss->dev, "%s: Unable to register subdev %s\n",
114959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre				__func__, board_info->board_info->type);
115059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			continue;
115159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		}
115259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
115359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		if (first)
115459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			sensor = subdev;
115559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
115659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
115759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return sensor;
115859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
115959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
116059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_register_entities(struct iss_device *iss)
116159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
116259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct iss_platform_data *pdata = iss->pdata;
116359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct iss_v4l2_subdevs_group *subdevs;
116459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	int ret;
116559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
116659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	iss->media_dev.dev = iss->dev;
116759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	strlcpy(iss->media_dev.model, "TI OMAP4 ISS",
116859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		sizeof(iss->media_dev.model));
116959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	iss->media_dev.hw_revision = iss->revision;
117059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	iss->media_dev.link_notify = iss_pipeline_link_notify;
117159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = media_device_register(&iss->media_dev);
117259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0) {
11734cd89e91bb8dbefe54743df6a5c4437812c96e3aLaurent Pinchart		dev_err(iss->dev, "%s: Media device registration failed (%d)\n",
117459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			__func__, ret);
117559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		return ret;
117659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
117759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
117859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	iss->v4l2_dev.mdev = &iss->media_dev;
117959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = v4l2_device_register(iss->dev, &iss->v4l2_dev);
118059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0) {
11814cd89e91bb8dbefe54743df6a5c4437812c96e3aLaurent Pinchart		dev_err(iss->dev, "%s: V4L2 device registration failed (%d)\n",
118259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			__func__, ret);
118359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto done;
118459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
118559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
118659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	/* Register internal entities */
118759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = omap4iss_csi2_register_entities(&iss->csi2a, &iss->v4l2_dev);
118859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0)
118959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto done;
119059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
119159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = omap4iss_csi2_register_entities(&iss->csi2b, &iss->v4l2_dev);
119259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0)
119359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto done;
119459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
119559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = omap4iss_ipipeif_register_entities(&iss->ipipeif, &iss->v4l2_dev);
119659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0)
119759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto done;
119859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
119959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = omap4iss_ipipe_register_entities(&iss->ipipe, &iss->v4l2_dev);
120059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0)
120159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto done;
120259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
120359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = omap4iss_resizer_register_entities(&iss->resizer, &iss->v4l2_dev);
120459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0)
120559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto done;
120659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
120759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	/* Register external entities */
120859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	for (subdevs = pdata->subdevs; subdevs && subdevs->subdevs; ++subdevs) {
120959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		struct v4l2_subdev *sensor;
121059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		struct media_entity *input;
121159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		unsigned int flags;
121259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		unsigned int pad;
121359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
121459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		sensor = iss_register_subdev_group(iss, subdevs->subdevs);
121559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		if (sensor == NULL)
121659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			continue;
121759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
121859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		sensor->host_priv = subdevs;
121959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
122059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		/* Connect the sensor to the correct interface module.
122159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		 * CSI2a receiver through CSIPHY1, or
122259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		 * CSI2b receiver through CSIPHY2
122359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		 */
122459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		switch (subdevs->interface) {
122559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		case ISS_INTERFACE_CSI2A_PHY1:
122659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			input = &iss->csi2a.subdev.entity;
122759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			pad = CSI2_PAD_SINK;
122859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			flags = MEDIA_LNK_FL_IMMUTABLE
122959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			      | MEDIA_LNK_FL_ENABLED;
123059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			break;
123159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
123259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		case ISS_INTERFACE_CSI2B_PHY2:
123359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			input = &iss->csi2b.subdev.entity;
123459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			pad = CSI2_PAD_SINK;
123559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			flags = MEDIA_LNK_FL_IMMUTABLE
123659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			      | MEDIA_LNK_FL_ENABLED;
123759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			break;
123859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
123959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		default:
12404cd89e91bb8dbefe54743df6a5c4437812c96e3aLaurent Pinchart			dev_err(iss->dev, "%s: invalid interface type %u\n",
12414cd89e91bb8dbefe54743df6a5c4437812c96e3aLaurent Pinchart				__func__, subdevs->interface);
124259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			ret = -EINVAL;
124359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			goto done;
124459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		}
124559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
124659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		ret = media_entity_create_link(&sensor->entity, 0, input, pad,
124759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre					       flags);
124859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		if (ret < 0)
124959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			goto done;
125059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
125159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
125259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = v4l2_device_register_subdev_nodes(&iss->v4l2_dev);
125359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
125459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirredone:
125559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0)
125659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		iss_unregister_entities(iss);
125759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
125859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return ret;
125959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
126059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
126159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic void iss_cleanup_modules(struct iss_device *iss)
126259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
126359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	omap4iss_csi2_cleanup(iss);
126459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	omap4iss_ipipeif_cleanup(iss);
126559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	omap4iss_ipipe_cleanup(iss);
126659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	omap4iss_resizer_cleanup(iss);
126759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
126859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
126959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_initialize_modules(struct iss_device *iss)
127059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
127159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	int ret;
127259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
127359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = omap4iss_csiphy_init(iss);
127459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0) {
127559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		dev_err(iss->dev, "CSI PHY initialization failed\n");
127659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto error_csiphy;
127759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
127859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
127959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = omap4iss_csi2_init(iss);
128059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0) {
128159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		dev_err(iss->dev, "CSI2 initialization failed\n");
128259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto error_csi2;
128359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
128459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
128559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = omap4iss_ipipeif_init(iss);
128659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0) {
128759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		dev_err(iss->dev, "ISP IPIPEIF initialization failed\n");
128859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto error_ipipeif;
128959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
129059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
129159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = omap4iss_ipipe_init(iss);
129259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0) {
129359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		dev_err(iss->dev, "ISP IPIPE initialization failed\n");
129459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto error_ipipe;
129559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
129659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
129759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = omap4iss_resizer_init(iss);
129859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0) {
129959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		dev_err(iss->dev, "ISP RESIZER initialization failed\n");
130059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto error_resizer;
130159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
130259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
130359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	/* Connect the submodules. */
130459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = media_entity_create_link(
130559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			&iss->csi2a.subdev.entity, CSI2_PAD_SOURCE,
130659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
130759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0)
130859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto error_link;
130959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
131059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = media_entity_create_link(
131159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			&iss->csi2b.subdev.entity, CSI2_PAD_SOURCE,
131259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
131359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0)
131459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto error_link;
131559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
131659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = media_entity_create_link(
131759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
131859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
131959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0)
132059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto error_link;
132159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
132259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = media_entity_create_link(
132359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
132459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			&iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0);
132559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0)
132659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto error_link;
132759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
132859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = media_entity_create_link(
132959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			&iss->ipipe.subdev.entity, IPIPE_PAD_SOURCE_VP,
133059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
133159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0)
133259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto error_link;
133359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
133459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return 0;
133559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
133659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreerror_link:
133759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	omap4iss_resizer_cleanup(iss);
133859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreerror_resizer:
133959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	omap4iss_ipipe_cleanup(iss);
134059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreerror_ipipe:
134159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	omap4iss_ipipeif_cleanup(iss);
134259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreerror_ipipeif:
134359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	omap4iss_csi2_cleanup(iss);
134459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreerror_csi2:
134559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreerror_csiphy:
134659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return ret;
134759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
134859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
134959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_probe(struct platform_device *pdev)
135059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
135159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct iss_platform_data *pdata = pdev->dev.platform_data;
135259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct iss_device *iss;
13534334fd18e2bcf9c6aa7c535c25b05b462aab05b3Laurent Pinchart	unsigned int i;
13544334fd18e2bcf9c6aa7c535c25b05b462aab05b3Laurent Pinchart	int ret;
135559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
135659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (pdata == NULL)
135759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		return -EINVAL;
135859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
13591153be56a10576abc3dd2a89aee59debb4dcc2b6Laurent Pinchart	iss = devm_kzalloc(&pdev->dev, sizeof(*iss), GFP_KERNEL);
136059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (!iss) {
136159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		dev_err(&pdev->dev, "Could not allocate memory\n");
136259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		return -ENOMEM;
136359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
136459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
136559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	mutex_init(&iss->iss_mutex);
136659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
136759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	iss->dev = &pdev->dev;
136859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	iss->pdata = pdata;
136959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
137059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	iss->raw_dmamask = DMA_BIT_MASK(32);
137159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	iss->dev->dma_mask = &iss->raw_dmamask;
137259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	iss->dev->coherent_dma_mask = DMA_BIT_MASK(32);
137359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
137459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	platform_set_drvdata(pdev, iss);
137559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
137659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	/* Clocks */
137759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = iss_map_mem_resource(pdev, iss, OMAP4_ISS_MEM_TOP);
137859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0)
137959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto error;
138059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
138159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = iss_get_clocks(iss);
138259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0)
138359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto error;
138459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
138559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (omap4iss_get(iss) == NULL)
138659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto error;
138759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
138859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = iss_reset(iss);
138959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0)
139059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto error_iss;
139159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
139211abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart	iss->revision = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION);
139359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	dev_info(iss->dev, "Revision %08x found\n", iss->revision);
139459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
139559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	for (i = 1; i < OMAP4_ISS_MEM_LAST; i++) {
139659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		ret = iss_map_mem_resource(pdev, iss, i);
139759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		if (ret)
139859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre			goto error_iss;
139959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
140059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
140159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	/* Configure BTE BW_LIMITER field to max recommended value (1 GB) */
140211abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart	iss_reg_update(iss, OMAP4_ISS_MEM_BTE, BTE_CTRL,
140311abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart		       BTE_CTRL_BW_LIMITER_MASK,
140411abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart		       18 << BTE_CTRL_BW_LIMITER_SHIFT);
140559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
140659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	/* Perform ISP reset */
140759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = omap4iss_subclk_enable(iss, OMAP4_ISS_SUBCLK_ISP);
140859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0)
140959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto error_iss;
141059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
141159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = iss_isp_reset(iss);
141259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0)
141359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto error_iss;
141459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
141559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	dev_info(iss->dev, "ISP Revision %08x found\n",
141611abbfd30f74f79fe78d9ff79cc3fcfa86a975c5Laurent Pinchart		 iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_REVISION));
141759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
141859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	/* Interrupt */
141959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	iss->irq_num = platform_get_irq(pdev, 0);
142059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (iss->irq_num <= 0) {
142159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		dev_err(iss->dev, "No IRQ resource\n");
142259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		ret = -ENODEV;
142359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto error_iss;
142459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
142559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
14261153be56a10576abc3dd2a89aee59debb4dcc2b6Laurent Pinchart	if (devm_request_irq(iss->dev, iss->irq_num, iss_isr, IRQF_SHARED,
14271153be56a10576abc3dd2a89aee59debb4dcc2b6Laurent Pinchart			     "OMAP4 ISS", iss)) {
142859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		dev_err(iss->dev, "Unable to request IRQ\n");
142959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		ret = -EINVAL;
143059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto error_iss;
143159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	}
143259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
143359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	/* Entities */
143459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = iss_initialize_modules(iss);
143559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0)
14361153be56a10576abc3dd2a89aee59debb4dcc2b6Laurent Pinchart		goto error_iss;
143759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
143859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	ret = iss_register_entities(iss);
143959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	if (ret < 0)
144059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		goto error_modules;
144159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
144259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	omap4iss_put(iss);
144359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
144459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return 0;
144559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
144659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreerror_modules:
144759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	iss_cleanup_modules(iss);
144859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreerror_iss:
144959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	omap4iss_put(iss);
145059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreerror:
145159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	platform_set_drvdata(pdev, NULL);
145259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
145359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	mutex_destroy(&iss->iss_mutex);
145459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
145559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return ret;
145659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
145759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
145859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_remove(struct platform_device *pdev)
145959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{
146059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	struct iss_device *iss = platform_get_drvdata(pdev);
146159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
146259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	iss_unregister_entities(iss);
146359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	iss_cleanup_modules(iss);
146459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
146559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	return 0;
146659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}
146759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
146859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic struct platform_device_id omap4iss_id_table[] = {
146959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	{ "omap4iss", 0 },
147059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	{ },
147159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre};
147259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio AguirreMODULE_DEVICE_TABLE(platform, omap4iss_id_table);
147359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
147459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic struct platform_driver iss_driver = {
147559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	.probe		= iss_probe,
147659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	.remove		= iss_remove,
147759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	.id_table	= omap4iss_id_table,
147859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	.driver = {
147959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		.owner	= THIS_MODULE,
148059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre		.name	= "omap4iss",
148159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre	},
148259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre};
148359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
148459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirremodule_platform_driver(iss_driver);
148559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre
148659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio AguirreMODULE_DESCRIPTION("TI OMAP4 ISS driver");
148759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio AguirreMODULE_AUTHOR("Sergio Aguirre <sergio.a.aguirre@gmail.com>");
148859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio AguirreMODULE_LICENSE("GPL");
148959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio AguirreMODULE_VERSION(ISS_VIDEO_DRIVER_VERSION);
1490