iss.c revision ea72717e961d1166882370a87876bfeacc967eb0
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", \ 3559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre readl(iss->regs[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); 4359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISS_PRINT_REGISTER(iss, HL_IRQSTATUS_5); 4459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISS_PRINT_REGISTER(iss, HL_IRQENABLE_5_SET); 4559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISS_PRINT_REGISTER(iss, HL_IRQENABLE_5_CLR); 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{ 6559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre writel(0, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_REVISION); 6659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_REVISION); 6759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 6859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 6959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* 7059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_enable_interrupts - Enable ISS interrupts. 7159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @iss: OMAP4 ISS device 7259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 7359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic void iss_enable_interrupts(struct iss_device *iss) 7459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 7559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre static const u32 hl_irq = ISS_HL_IRQ_CSIA | ISS_HL_IRQ_CSIB | ISS_HL_IRQ_ISP(0); 7659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 7759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre /* Enable HL interrupts */ 7859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre writel(hl_irq, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQSTATUS_5); 7959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre writel(hl_irq, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQENABLE_5_SET); 8059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 8159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 8259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 8359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* 8459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_disable_interrupts - Disable ISS interrupts. 8559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @iss: OMAP4 ISS device 8659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 8759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic void iss_disable_interrupts(struct iss_device *iss) 8859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 8959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre writel(-1, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQENABLE_5_CLR); 9059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 9159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 9259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* 9359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_isp_enable_interrupts - Enable ISS ISP interrupts. 9459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @iss: OMAP4 ISS device 9559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 9659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrevoid omap4iss_isp_enable_interrupts(struct iss_device *iss) 9759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 9859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre static const u32 isp_irq = ISP5_IRQ_OCP_ERR | 9959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISP5_IRQ_RSZ_FIFO_IN_BLK | 10059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISP5_IRQ_RSZ_FIFO_OVF | 10159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISP5_IRQ_RSZ_INT_DMA | 10259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISP5_IRQ_ISIF0; 10359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 10459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre /* Enable ISP interrupts */ 10559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre writel(isp_irq, iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_IRQSTATUS(0)); 10659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre writel(isp_irq, iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_IRQENABLE_SET(0)); 10759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 10859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 10959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* 11059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_isp_disable_interrupts - Disable ISS interrupts. 11159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @iss: OMAP4 ISS device 11259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 11359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrevoid omap4iss_isp_disable_interrupts(struct iss_device *iss) 11459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 11559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre writel(-1, iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_IRQENABLE_CLR(0)); 11659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 11759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 11859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreint omap4iss_get_external_info(struct iss_pipeline *pipe, 11959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct media_link *link) 12059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 12159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct iss_device *iss = 12259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre container_of(pipe, struct iss_video, pipe)->iss; 12359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct v4l2_subdev_format fmt; 124ea72717e961d1166882370a87876bfeacc967eb0Laurent Pinchart struct v4l2_ctrl *ctrl; 12559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre int ret; 12659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 12759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (!pipe->external) 12859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 0; 12959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 13059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (pipe->external_rate) 13159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 0; 13259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 13359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre memset(&fmt, 0, sizeof(fmt)); 13459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 13559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre fmt.pad = link->source->index; 13659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; 13759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = v4l2_subdev_call(media_entity_to_v4l2_subdev(link->sink->entity), 13859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre pad, get_fmt, NULL, &fmt); 13959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) 14059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return -EPIPE; 14159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 14259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre pipe->external_bpp = omap4iss_video_format_info(fmt.format.code)->bpp; 14359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 144ea72717e961d1166882370a87876bfeacc967eb0Laurent Pinchart ctrl = v4l2_ctrl_find(pipe->external->ctrl_handler, 145ea72717e961d1166882370a87876bfeacc967eb0Laurent Pinchart V4L2_CID_PIXEL_RATE); 146ea72717e961d1166882370a87876bfeacc967eb0Laurent Pinchart if (ctrl == NULL) { 14759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre dev_warn(iss->dev, "no pixel rate control in subdev %s\n", 14859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre pipe->external->name); 149ea72717e961d1166882370a87876bfeacc967eb0Laurent Pinchart return -EPIPE; 15059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 15159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 152ea72717e961d1166882370a87876bfeacc967eb0Laurent Pinchart pipe->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl); 15359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 15459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 0; 15559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 15659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 15759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* 15859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Configure the bridge. Valid inputs are 15959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 16059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * IPIPEIF_INPUT_CSI2A: CSI2a receiver 16159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * IPIPEIF_INPUT_CSI2B: CSI2b receiver 16259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 16359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * The bridge and lane shifter are configured according to the selected input 16459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * and the ISP platform data. 16559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 16659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrevoid omap4iss_configure_bridge(struct iss_device *iss, 16759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre enum ipipeif_input_entity input) 16859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 16959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre u32 issctrl_val; 17059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre u32 isp5ctrl_val; 17159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 17259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre issctrl_val = readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_CTRL); 17359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre issctrl_val &= ~ISS_CTRL_INPUT_SEL_MASK; 17459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre issctrl_val &= ~ISS_CTRL_CLK_DIV_MASK; 17559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 17659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre isp5ctrl_val = readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL); 17759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 17859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre switch (input) { 17959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre case IPIPEIF_INPUT_CSI2A: 18059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre issctrl_val |= ISS_CTRL_INPUT_SEL_CSI2A; 18159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre isp5ctrl_val |= ISP5_CTRL_VD_PULSE_EXT; 18259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre break; 18359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 18459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre case IPIPEIF_INPUT_CSI2B: 18559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre issctrl_val |= ISS_CTRL_INPUT_SEL_CSI2B; 18659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre isp5ctrl_val |= ISP5_CTRL_VD_PULSE_EXT; 18759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre break; 18859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 18959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre default: 19059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return; 19159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 19259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 19359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre issctrl_val |= ISS_CTRL_SYNC_DETECT_VS_RAISING; 19459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 19559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre isp5ctrl_val |= ISP5_CTRL_PSYNC_CLK_SEL | ISP5_CTRL_SYNC_ENABLE; 19659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 19759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre writel(issctrl_val, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_CTRL); 19859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre writel(isp5ctrl_val, iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL); 19959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 20059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 20159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic inline void iss_isr_dbg(struct iss_device *iss, u32 irqstatus) 20259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 20359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre static const char *name[] = { 20459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "ISP_IRQ0", 20559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "ISP_IRQ1", 20659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "ISP_IRQ2", 20759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "ISP_IRQ3", 20859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "CSIA_IRQ", 20959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "CSIB_IRQ", 21059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "CCP2_IRQ0", 21159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "CCP2_IRQ1", 21259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "CCP2_IRQ2", 21359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "CCP2_IRQ3", 21459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "CBUFF_IRQ", 21559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "BTE_IRQ", 21659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "SIMCOP_IRQ0", 21759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "SIMCOP_IRQ1", 21859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "SIMCOP_IRQ2", 21959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "SIMCOP_IRQ3", 22059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "CCP2_IRQ8", 22159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "HS_VS_IRQ", 22259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "res18", 22359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "res19", 22459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "res20", 22559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "res21", 22659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "res22", 22759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "res23", 22859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "res24", 22959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "res25", 23059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "res26", 23159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "res27", 23259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "res28", 23359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "res29", 23459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "res30", 23559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "res31", 23659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre }; 23759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre int i; 23859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 23959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre dev_dbg(iss->dev, "ISS IRQ: "); 24059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 24159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre for (i = 0; i < ARRAY_SIZE(name); i++) { 24259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if ((1 << i) & irqstatus) 24359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre pr_cont("%s ", name[i]); 24459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 24559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre pr_cont("\n"); 24659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 24759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 24859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* 24959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_isr - Interrupt Service Routine for ISS module. 25059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @irq: Not used currently. 25159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @_iss: Pointer to the OMAP4 ISS device 25259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 25359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Handles the corresponding callback if plugged in. 25459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 25559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Returns IRQ_HANDLED when IRQ was correctly handled, or IRQ_NONE when the 25659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * IRQ wasn't handled. 25759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 25859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic irqreturn_t iss_isr(int irq, void *_iss) 25959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 26059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre static const u32 ipipeif_events = ISP5_IRQ_IPIPEIF | 26159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISP5_IRQ_ISIF0; 26259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre static const u32 resizer_events = ISP5_IRQ_RSZ_FIFO_IN_BLK | 26359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISP5_IRQ_RSZ_FIFO_OVF | 26459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISP5_IRQ_RSZ_INT_DMA; 26559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct iss_device *iss = _iss; 26659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre u32 irqstatus; 26759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 26859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre irqstatus = readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQSTATUS_5); 26959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre writel(irqstatus, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQSTATUS_5); 27059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 27159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (irqstatus & ISS_HL_IRQ_CSIA) 27259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre omap4iss_csi2_isr(&iss->csi2a); 27359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 27459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (irqstatus & ISS_HL_IRQ_CSIB) 27559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre omap4iss_csi2_isr(&iss->csi2b); 27659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 27759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (irqstatus & ISS_HL_IRQ_ISP(0)) { 27859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre u32 isp_irqstatus = readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + 27959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISP5_IRQSTATUS(0)); 28059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre writel(isp_irqstatus, iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + 28159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISP5_IRQSTATUS(0)); 28259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 28359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (isp_irqstatus & ISP5_IRQ_OCP_ERR) 28459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre dev_dbg(iss->dev, "ISP5 OCP Error!\n"); 28559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 28659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (isp_irqstatus & ipipeif_events) { 28759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre omap4iss_ipipeif_isr(&iss->ipipeif, 28859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre isp_irqstatus & ipipeif_events); 28959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 29059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 29159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (isp_irqstatus & resizer_events) 29259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre omap4iss_resizer_isr(&iss->resizer, 29359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre isp_irqstatus & resizer_events); 29459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 29559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 29659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre omap4iss_flush(iss); 29759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 29859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre#if defined(DEBUG) && defined(ISS_ISR_DEBUG) 29959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss_isr_dbg(iss, irqstatus); 30059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre#endif 30159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 30259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return IRQ_HANDLED; 30359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 30459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 30559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* ----------------------------------------------------------------------------- 30659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Pipeline power management 30759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 30859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Entities must be powered up when part of a pipeline that contains at least 30959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * one open video device node. 31059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 31159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * To achieve this use the entity use_count field to track the number of users. 31259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * For entities corresponding to video device nodes the use_count field stores 31359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * the users count of the node. For entities corresponding to subdevs the 31459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * use_count field stores the total number of users of all video device nodes 31559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * in the pipeline. 31659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 31759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * The omap4iss_pipeline_pm_use() function must be called in the open() and 31859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * close() handlers of video device nodes. It increments or decrements the use 31959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * count of all subdev entities in the pipeline. 32059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 32159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * To react to link management on powered pipelines, the link setup notification 32259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * callback updates the use count of all entities in the source and sink sides 32359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * of the link. 32459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 32559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 32659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* 32759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_pipeline_pm_use_count - Count the number of users of a pipeline 32859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @entity: The entity 32959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 33059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Return the total number of users of all video device nodes in the pipeline. 33159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 33259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_pipeline_pm_use_count(struct media_entity *entity) 33359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 33459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct media_entity_graph graph; 33559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre int use = 0; 33659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 33759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre media_entity_graph_walk_start(&graph, entity); 33859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 33959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre while ((entity = media_entity_graph_walk_next(&graph))) { 34059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE) 34159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre use += entity->use_count; 34259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 34359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 34459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return use; 34559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 34659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 34759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* 34859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_pipeline_pm_power_one - Apply power change to an entity 34959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @entity: The entity 35059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @change: Use count change 35159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 35259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Change the entity use count by @change. If the entity is a subdev update its 35359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * power state by calling the core::s_power operation when the use count goes 35459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * from 0 to != 0 or from != 0 to 0. 35559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 35659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Return 0 on success or a negative error code on failure. 35759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 35859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_pipeline_pm_power_one(struct media_entity *entity, int change) 35959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 36059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct v4l2_subdev *subdev; 36159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 36259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV 36359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ? media_entity_to_v4l2_subdev(entity) : NULL; 36459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 36559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (entity->use_count == 0 && change > 0 && subdev != NULL) { 36659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre int ret; 36759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 36859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = v4l2_subdev_call(subdev, core, s_power, 1); 36959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0 && ret != -ENOIOCTLCMD) 37059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return ret; 37159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 37259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 37359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre entity->use_count += change; 37459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre WARN_ON(entity->use_count < 0); 37559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 37659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (entity->use_count == 0 && change < 0 && subdev != NULL) 37759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre v4l2_subdev_call(subdev, core, s_power, 0); 37859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 37959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 0; 38059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 38159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 38259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* 38359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_pipeline_pm_power - Apply power change to all entities in a pipeline 38459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @entity: The entity 38559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @change: Use count change 38659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 38759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Walk the pipeline to update the use count and the power state of all non-node 38859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * entities. 38959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 39059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Return 0 on success or a negative error code on failure. 39159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 39259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_pipeline_pm_power(struct media_entity *entity, int change) 39359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 39459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct media_entity_graph graph; 39559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct media_entity *first = entity; 39659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre int ret = 0; 39759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 39859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (!change) 39959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 0; 40059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 40159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre media_entity_graph_walk_start(&graph, entity); 40259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 40359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre while (!ret && (entity = media_entity_graph_walk_next(&graph))) 40459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE) 40559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = iss_pipeline_pm_power_one(entity, change); 40659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 40759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (!ret) 40859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 0; 40959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 41059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre media_entity_graph_walk_start(&graph, first); 41159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 41259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre while ((first = media_entity_graph_walk_next(&graph)) 41359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre && first != entity) 41459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE) 41559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss_pipeline_pm_power_one(first, -change); 41659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 41759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return ret; 41859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 41959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 42059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* 42159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * omap4iss_pipeline_pm_use - Update the use count of an entity 42259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @entity: The entity 42359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @use: Use (1) or stop using (0) the entity 42459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 42559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Update the use count of all entities in the pipeline and power entities on or 42659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * off accordingly. 42759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 42859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Return 0 on success or a negative error code on failure. Powering entities 42959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * off is assumed to never fail. No failure can occur when the use parameter is 43059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * set to 0. 43159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 43259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreint omap4iss_pipeline_pm_use(struct media_entity *entity, int use) 43359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 43459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre int change = use ? 1 : -1; 43559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre int ret; 43659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 43759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre mutex_lock(&entity->parent->graph_mutex); 43859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 43959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre /* Apply use count to node. */ 44059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre entity->use_count += change; 44159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre WARN_ON(entity->use_count < 0); 44259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 44359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre /* Apply power change to connected non-nodes. */ 44459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = iss_pipeline_pm_power(entity, change); 44559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) 44659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre entity->use_count -= change; 44759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 44859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre mutex_unlock(&entity->parent->graph_mutex); 44959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 45059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return ret; 45159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 45259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 45359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* 45459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_pipeline_link_notify - Link management notification callback 45559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @link: The link 45659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @flags: New link flags that will be applied 45759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 45859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * React to link management on powered pipelines by updating the use count of 45959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * all entities in the source and sink sides of the link. Entities are powered 46059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * on or off accordingly. 46159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 46259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Return 0 on success or a negative error code on failure. Powering entities 46359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * off is assumed to never fail. This function will not fail for disconnection 46459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * events. 46559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 46659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_pipeline_link_notify(struct media_link *link, u32 flags, 46759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre unsigned int notification) 46859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 46959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct media_entity *source = link->source->entity; 47059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct media_entity *sink = link->sink->entity; 47159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre int source_use = iss_pipeline_pm_use_count(source); 47259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre int sink_use = iss_pipeline_pm_use_count(sink); 47359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre int ret; 47459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 47559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH && 47659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre !(link->flags & MEDIA_LNK_FL_ENABLED)) { 47759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre /* Powering off entities is assumed to never fail. */ 47859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss_pipeline_pm_power(source, -sink_use); 47959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss_pipeline_pm_power(sink, -source_use); 48059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 0; 48159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 48259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 48359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH && 48459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre (flags & MEDIA_LNK_FL_ENABLED)) { 48559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = iss_pipeline_pm_power(source, sink_use); 48659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) 48759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return ret; 48859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 48959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = iss_pipeline_pm_power(sink, source_use); 49059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) 49159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss_pipeline_pm_power(source, -sink_use); 49259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 49359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return ret; 49459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 49559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 49659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 0; 49759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 49859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 49959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* ----------------------------------------------------------------------------- 50059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Pipeline stream management 50159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 50259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 50359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* 50459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_pipeline_enable - Enable streaming on a pipeline 50559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @pipe: ISS pipeline 50659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @mode: Stream mode (single shot or continuous) 50759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 50859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Walk the entities chain starting at the pipeline output video node and start 50959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * all modules in the chain in the given mode. 51059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 51159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Return 0 if successful, or the return value of the failed video::s_stream 51259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * operation otherwise. 51359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 51459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_pipeline_enable(struct iss_pipeline *pipe, 51559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre enum iss_pipeline_stream_state mode) 51659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 51759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct media_entity *entity; 51859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct media_pad *pad; 51959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct v4l2_subdev *subdev; 52059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre unsigned long flags; 52159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre int ret; 52259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 52359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre spin_lock_irqsave(&pipe->lock, flags); 52459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre pipe->state &= ~(ISS_PIPELINE_IDLE_INPUT | ISS_PIPELINE_IDLE_OUTPUT); 52559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre spin_unlock_irqrestore(&pipe->lock, flags); 52659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 52759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre pipe->do_propagation = false; 52859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 52959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre entity = &pipe->output->video.entity; 53059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre while (1) { 53159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre pad = &entity->pads[0]; 53259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (!(pad->flags & MEDIA_PAD_FL_SINK)) 53359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre break; 53459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 53559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre pad = media_entity_remote_pad(pad); 53659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (pad == NULL || 53759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) 53859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre break; 53959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 54059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre entity = pad->entity; 54159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre subdev = media_entity_to_v4l2_subdev(entity); 54259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 54359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = v4l2_subdev_call(subdev, video, s_stream, mode); 54459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0 && ret != -ENOIOCTLCMD) 54559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return ret; 54659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 54759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss_print_status(pipe->output->iss); 54859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 0; 54959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 55059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 55159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* 55259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_pipeline_disable - Disable streaming on a pipeline 55359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @pipe: ISS pipeline 55459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 55559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Walk the entities chain starting at the pipeline output video node and stop 55659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * all modules in the chain. Wait synchronously for the modules to be stopped if 55759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * necessary. 55859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 55959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_pipeline_disable(struct iss_pipeline *pipe) 56059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 56159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct media_entity *entity; 56259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct media_pad *pad; 56359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct v4l2_subdev *subdev; 56459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre int failure = 0; 56559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 56659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre entity = &pipe->output->video.entity; 56759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre while (1) { 56859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre pad = &entity->pads[0]; 56959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (!(pad->flags & MEDIA_PAD_FL_SINK)) 57059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre break; 57159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 57259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre pad = media_entity_remote_pad(pad); 57359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (pad == NULL || 57459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) 57559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre break; 57659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 57759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre entity = pad->entity; 57859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre subdev = media_entity_to_v4l2_subdev(entity); 57959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 58059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre v4l2_subdev_call(subdev, video, s_stream, 0); 58159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 58259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 58359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return failure; 58459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 58559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 58659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* 58759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * omap4iss_pipeline_set_stream - Enable/disable streaming on a pipeline 58859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @pipe: ISS pipeline 58959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @state: Stream state (stopped, single shot or continuous) 59059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 59159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Set the pipeline to the given stream state. Pipelines can be started in 59259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * single-shot or continuous mode. 59359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 59459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Return 0 if successful, or the return value of the failed video::s_stream 59559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * operation otherwise. The pipeline state is not updated when the operation 59659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * fails, except when stopping the pipeline. 59759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 59859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreint omap4iss_pipeline_set_stream(struct iss_pipeline *pipe, 59959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre enum iss_pipeline_stream_state state) 60059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 60159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre int ret; 60259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 60359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (state == ISS_PIPELINE_STREAM_STOPPED) 60459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = iss_pipeline_disable(pipe); 60559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre else 60659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = iss_pipeline_enable(pipe, state); 60759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 60859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret == 0 || state == ISS_PIPELINE_STREAM_STOPPED) 60959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre pipe->stream_state = state; 61059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 61159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return ret; 61259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 61359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 61459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* 61559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_pipeline_is_last - Verify if entity has an enabled link to the output 61659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * video node 61759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @me: ISS module's media entity 61859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 61959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Returns 1 if the entity has an enabled link to the output video node or 0 62059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * otherwise. It's true only while pipeline can have no more than one output 62159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * node. 62259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 62359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_pipeline_is_last(struct media_entity *me) 62459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 62559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct iss_pipeline *pipe; 62659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct media_pad *pad; 62759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 62859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (!me->pipe) 62959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 0; 63059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre pipe = to_iss_pipeline(me); 63159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (pipe->stream_state == ISS_PIPELINE_STREAM_STOPPED) 63259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 0; 63359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre pad = media_entity_remote_pad(&pipe->output->pad); 63459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return pad->entity == me; 63559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 63659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 63759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_reset(struct iss_device *iss) 63859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 63959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre unsigned long timeout = 0; 64059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 64159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre writel(readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_SYSCONFIG) | 64259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISS_HL_SYSCONFIG_SOFTRESET, 64359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_SYSCONFIG); 64459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 64559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre while (readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_SYSCONFIG) & 64659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISS_HL_SYSCONFIG_SOFTRESET) { 64759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (timeout++ > 10000) { 64859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre dev_alert(iss->dev, "cannot reset ISS\n"); 64959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return -ETIMEDOUT; 65059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 65159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre udelay(1); 65259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 65359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 65459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 0; 65559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 65659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 65759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_isp_reset(struct iss_device *iss) 65859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 65959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre unsigned long timeout = 0; 66059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 66159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre /* Fist, ensure that the ISP is IDLE (no transactions happening) */ 66259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_SYSCONFIG) & 66359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ~ISP5_SYSCONFIG_STANDBYMODE_MASK) | 66459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISP5_SYSCONFIG_STANDBYMODE_SMART, 66559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_SYSCONFIG); 66659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 66759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL) | 66859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISP5_CTRL_MSTANDBY, 66959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL); 67059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 67159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre for (;;) { 67259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL) & 67359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISP5_CTRL_MSTANDBY_WAIT) 67459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre break; 67559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (timeout++ > 1000) { 67659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre dev_alert(iss->dev, "cannot set ISP5 to standby\n"); 67759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return -ETIMEDOUT; 67859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 67959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre msleep(1); 68059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 68159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 68259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre /* Now finally, do the reset */ 68359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_SYSCONFIG) | 68459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISP5_SYSCONFIG_SOFTRESET, 68559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_SYSCONFIG); 68659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 68759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre timeout = 0; 68859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre while (readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_SYSCONFIG) & 68959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISP5_SYSCONFIG_SOFTRESET) { 69059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (timeout++ > 1000) { 69159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre dev_alert(iss->dev, "cannot reset ISP5\n"); 69259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return -ETIMEDOUT; 69359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 69459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre msleep(1); 69559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 69659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 69759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 0; 69859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 69959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 70059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* 70159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_module_sync_idle - Helper to sync module with its idle state 70259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @me: ISS submodule's media entity 70359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @wait: ISS submodule's wait queue for streamoff/interrupt synchronization 70459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @stopping: flag which tells module wants to stop 70559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 70659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * This function checks if ISS submodule needs to wait for next interrupt. If 70759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * yes, makes the caller to sleep while waiting for such event. 70859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 70959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreint omap4iss_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait, 71059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre atomic_t *stopping) 71159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 71259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct iss_pipeline *pipe = to_iss_pipeline(me); 71359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct iss_video *video = pipe->output; 71459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre unsigned long flags; 71559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 71659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (pipe->stream_state == ISS_PIPELINE_STREAM_STOPPED || 71759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre (pipe->stream_state == ISS_PIPELINE_STREAM_SINGLESHOT && 71859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre !iss_pipeline_ready(pipe))) 71959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 0; 72059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 72159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre /* 72259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * atomic_set() doesn't include memory barrier on ARM platform for SMP 72359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * scenario. We'll call it here to avoid race conditions. 72459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 72559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre atomic_set(stopping, 1); 72659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre smp_wmb(); 72759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 72859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre /* 72959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * If module is the last one, it's writing to memory. In this case, 73059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * it's necessary to check if the module is already paused due to 73159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * DMA queue underrun or if it has to wait for next interrupt to be 73259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * idle. 73359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * If it isn't the last one, the function won't sleep but *stopping 73459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * will still be set to warn next submodule caller's interrupt the 73559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * module wants to be idle. 73659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 73759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (!iss_pipeline_is_last(me)) 73859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 0; 73959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 74059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre spin_lock_irqsave(&video->qlock, flags); 74159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (video->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) { 74259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre spin_unlock_irqrestore(&video->qlock, flags); 74359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre atomic_set(stopping, 0); 74459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre smp_wmb(); 74559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 0; 74659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 74759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre spin_unlock_irqrestore(&video->qlock, flags); 74859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (!wait_event_timeout(*wait, !atomic_read(stopping), 74959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre msecs_to_jiffies(1000))) { 75059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre atomic_set(stopping, 0); 75159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre smp_wmb(); 75259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return -ETIMEDOUT; 75359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 75459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 75559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 0; 75659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 75759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 75859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* 75959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * omap4iss_module_sync_is_stopped - Helper to verify if module was stopping 76059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @wait: ISS submodule's wait queue for streamoff/interrupt synchronization 76159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @stopping: flag which tells module wants to stop 76259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 76359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * This function checks if ISS submodule was stopping. In case of yes, it 76459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * notices the caller by setting stopping to 0 and waking up the wait queue. 76559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Returns 1 if it was stopping or 0 otherwise. 76659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 76759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreint omap4iss_module_sync_is_stopping(wait_queue_head_t *wait, 76859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre atomic_t *stopping) 76959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 77059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (atomic_cmpxchg(stopping, 1, 0)) { 77159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre wake_up(wait); 77259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 1; 77359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 77459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 77559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 0; 77659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 77759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 77859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* -------------------------------------------------------------------------- 77959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Clock management 78059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 78159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 78259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre#define ISS_CLKCTRL_MASK (ISS_CLKCTRL_CSI2_A |\ 78359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISS_CLKCTRL_CSI2_B |\ 78459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISS_CLKCTRL_ISP) 78559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 78659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int __iss_subclk_update(struct iss_device *iss) 78759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 78859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre u32 clk = 0; 78959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre int ret = 0, timeout = 1000; 79059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 79159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (iss->subclk_resources & OMAP4_ISS_SUBCLK_CSI2_A) 79259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre clk |= ISS_CLKCTRL_CSI2_A; 79359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 79459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (iss->subclk_resources & OMAP4_ISS_SUBCLK_CSI2_B) 79559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre clk |= ISS_CLKCTRL_CSI2_B; 79659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 79759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (iss->subclk_resources & OMAP4_ISS_SUBCLK_ISP) 79859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre clk |= ISS_CLKCTRL_ISP; 79959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 80059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre writel((readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_CLKCTRL) & 80159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ~ISS_CLKCTRL_MASK) | clk, 80259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->regs[OMAP4_ISS_MEM_TOP] + ISS_CLKCTRL); 80359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 80459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre /* Wait for HW assertion */ 80559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre while (--timeout > 0) { 80659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre udelay(1); 80759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if ((readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_CLKSTAT) & 80859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISS_CLKCTRL_MASK) == clk) 80959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre break; 81059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 81159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 81259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (!timeout) 81359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = -EBUSY; 81459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 81559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return ret; 81659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 81759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 81859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreint omap4iss_subclk_enable(struct iss_device *iss, 81959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre enum iss_subclk_resource res) 82059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 82159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->subclk_resources |= res; 82259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 82359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return __iss_subclk_update(iss); 82459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 82559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 82659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreint omap4iss_subclk_disable(struct iss_device *iss, 82759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre enum iss_subclk_resource res) 82859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 82959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->subclk_resources &= ~res; 83059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 83159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return __iss_subclk_update(iss); 83259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 83359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 83459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre#define ISS_ISP5_CLKCTRL_MASK (ISP5_CTRL_BL_CLK_ENABLE |\ 83559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISP5_CTRL_ISIF_CLK_ENABLE |\ 83659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISP5_CTRL_H3A_CLK_ENABLE |\ 83759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISP5_CTRL_RSZ_CLK_ENABLE |\ 83859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISP5_CTRL_IPIPE_CLK_ENABLE |\ 83959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ISP5_CTRL_IPIPEIF_CLK_ENABLE) 84059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 84159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int __iss_isp_subclk_update(struct iss_device *iss) 84259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 84359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre u32 clk = 0; 84459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 84559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_ISIF) 84659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre clk |= ISP5_CTRL_ISIF_CLK_ENABLE; 84759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 84859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_H3A) 84959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre clk |= ISP5_CTRL_H3A_CLK_ENABLE; 85059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 85159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_RSZ) 85259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre clk |= ISP5_CTRL_RSZ_CLK_ENABLE; 85359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 85459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_IPIPE) 85559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre clk |= ISP5_CTRL_IPIPE_CLK_ENABLE; 85659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 85759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_IPIPEIF) 85859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre clk |= ISP5_CTRL_IPIPEIF_CLK_ENABLE; 85959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 86059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (clk) 86159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre clk |= ISP5_CTRL_BL_CLK_ENABLE; 86259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 86359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL) & 86459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ~ISS_ISP5_CLKCTRL_MASK) | clk, 86559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL); 86659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 86759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 0; 86859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 86959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 87059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreint omap4iss_isp_subclk_enable(struct iss_device *iss, 87159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre enum iss_isp_subclk_resource res) 87259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 87359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->isp_subclk_resources |= res; 87459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 87559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return __iss_isp_subclk_update(iss); 87659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 87759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 87859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreint omap4iss_isp_subclk_disable(struct iss_device *iss, 87959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre enum iss_isp_subclk_resource res) 88059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 88159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->isp_subclk_resources &= ~res; 88259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 88359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return __iss_isp_subclk_update(iss); 88459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 88559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 88659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* 88759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_enable_clocks - Enable ISS clocks 88859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @iss: OMAP4 ISS device 88959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 89059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Return 0 if successful, or clk_enable return value if any of tthem fails. 89159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 89259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_enable_clocks(struct iss_device *iss) 89359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 89459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre int r; 89559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 89659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre r = clk_enable(iss->iss_fck); 89759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (r) { 89859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre dev_err(iss->dev, "clk_enable iss_fck failed\n"); 89959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return r; 90059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 90159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 90259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre r = clk_enable(iss->iss_ctrlclk); 90359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (r) { 90459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre dev_err(iss->dev, "clk_enable iss_ctrlclk failed\n"); 90559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto out_clk_enable_ctrlclk; 90659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 90759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 0; 90859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 90959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreout_clk_enable_ctrlclk: 91059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre clk_disable(iss->iss_fck); 91159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return r; 91259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 91359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 91459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* 91559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_disable_clocks - Disable ISS clocks 91659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @iss: OMAP4 ISS device 91759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 91859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic void iss_disable_clocks(struct iss_device *iss) 91959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 92059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre clk_disable(iss->iss_ctrlclk); 92159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre clk_disable(iss->iss_fck); 92259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 92359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 92459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic void iss_put_clocks(struct iss_device *iss) 92559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 92659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (iss->iss_fck) { 92759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre clk_put(iss->iss_fck); 92859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->iss_fck = NULL; 92959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 93059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 93159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (iss->iss_ctrlclk) { 93259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre clk_put(iss->iss_ctrlclk); 93359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->iss_ctrlclk = NULL; 93459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 93559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 93659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 93759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_get_clocks(struct iss_device *iss) 93859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 93959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->iss_fck = clk_get(iss->dev, "iss_fck"); 94059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (IS_ERR(iss->iss_fck)) { 94159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre dev_err(iss->dev, "Unable to get iss_fck clock info\n"); 94259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss_put_clocks(iss); 94359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return PTR_ERR(iss->iss_fck); 94459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 94559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 94659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->iss_ctrlclk = clk_get(iss->dev, "iss_ctrlclk"); 94759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (IS_ERR(iss->iss_ctrlclk)) { 94859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre dev_err(iss->dev, "Unable to get iss_ctrlclk clock info\n"); 94959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss_put_clocks(iss); 95059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return PTR_ERR(iss->iss_fck); 95159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 95259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 95359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 0; 95459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 95559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 95659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* 95759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * omap4iss_get - Acquire the ISS resource. 95859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 95959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Initializes the clocks for the first acquire. 96059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 96159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Increment the reference count on the ISS. If the first reference is taken, 96259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * enable clocks and power-up all submodules. 96359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 96459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Return a pointer to the ISS device structure, or NULL if an error occurred. 96559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 96659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestruct iss_device *omap4iss_get(struct iss_device *iss) 96759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 96859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct iss_device *__iss = iss; 96959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 97059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (iss == NULL) 97159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return NULL; 97259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 97359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre mutex_lock(&iss->iss_mutex); 97459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (iss->ref_count > 0) 97559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto out; 97659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 97759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (iss_enable_clocks(iss) < 0) { 97859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre __iss = NULL; 97959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto out; 98059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 98159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 98259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss_enable_interrupts(iss); 98359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 98459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreout: 98559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (__iss != NULL) 98659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->ref_count++; 98759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre mutex_unlock(&iss->iss_mutex); 98859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 98959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return __iss; 99059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 99159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 99259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* 99359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * omap4iss_put - Release the ISS 99459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 99559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Decrement the reference count on the ISS. If the last reference is released, 99659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * power-down all submodules, disable clocks and free temporary buffers. 99759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 99859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrevoid omap4iss_put(struct iss_device *iss) 99959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 100059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (iss == NULL) 100159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return; 100259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 100359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre mutex_lock(&iss->iss_mutex); 100459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre BUG_ON(iss->ref_count == 0); 100559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (--iss->ref_count == 0) { 100659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss_disable_interrupts(iss); 100759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss_disable_clocks(iss); 100859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 100959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre mutex_unlock(&iss->iss_mutex); 101059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 101159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 101259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_map_mem_resource(struct platform_device *pdev, 101359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct iss_device *iss, 101459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre enum iss_mem_resources res) 101559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 101659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct resource *mem; 101759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 101859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre /* request the mem region for the camera registers */ 101959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 102059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre mem = platform_get_resource(pdev, IORESOURCE_MEM, res); 102159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (!mem) { 102259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre dev_err(iss->dev, "no mem resource?\n"); 102359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return -ENODEV; 102459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 102559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 102659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (!request_mem_region(mem->start, resource_size(mem), pdev->name)) { 102759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre dev_err(iss->dev, 102859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "cannot reserve camera register I/O region\n"); 102959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return -ENODEV; 103059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 103159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->res[res] = mem; 103259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 103359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre /* map the region */ 103459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->regs[res] = ioremap_nocache(mem->start, resource_size(mem)); 103559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (!iss->regs[res]) { 103659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre dev_err(iss->dev, "cannot map camera register I/O region\n"); 103759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return -ENODEV; 103859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 103959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 104059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 0; 104159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 104259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 104359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic void iss_unregister_entities(struct iss_device *iss) 104459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 104559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre omap4iss_resizer_unregister_entities(&iss->resizer); 104659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre omap4iss_ipipe_unregister_entities(&iss->ipipe); 104759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre omap4iss_ipipeif_unregister_entities(&iss->ipipeif); 104859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre omap4iss_csi2_unregister_entities(&iss->csi2a); 104959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre omap4iss_csi2_unregister_entities(&iss->csi2b); 105059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 105159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre v4l2_device_unregister(&iss->v4l2_dev); 105259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre media_device_unregister(&iss->media_dev); 105359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 105459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 105559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre/* 105659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * iss_register_subdev_group - Register a group of subdevices 105759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @iss: OMAP4 ISS device 105859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * @board_info: I2C subdevs board information array 105959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 106059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Register all I2C subdevices in the board_info array. The array must be 106159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * terminated by a NULL entry, and the first entry must be the sensor. 106259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * 106359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * Return a pointer to the sensor media entity if it has been successfully 106459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * registered, or NULL otherwise. 106559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 106659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic struct v4l2_subdev * 106759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreiss_register_subdev_group(struct iss_device *iss, 106859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct iss_subdev_i2c_board_info *board_info) 106959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 107059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct v4l2_subdev *sensor = NULL; 107159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre unsigned int first; 107259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 107359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (board_info->board_info == NULL) 107459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return NULL; 107559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 107659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre for (first = 1; board_info->board_info; ++board_info, first = 0) { 107759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct v4l2_subdev *subdev; 107859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct i2c_adapter *adapter; 107959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 108059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre adapter = i2c_get_adapter(board_info->i2c_adapter_id); 108159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (adapter == NULL) { 108259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre dev_err(iss->dev, "%s: Unable to get I2C adapter %d for " 108359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre "device %s\n", __func__, 108459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre board_info->i2c_adapter_id, 108559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre board_info->board_info->type); 108659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre continue; 108759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 108859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 108959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre subdev = v4l2_i2c_new_subdev_board(&iss->v4l2_dev, adapter, 109059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre board_info->board_info, NULL); 109159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (subdev == NULL) { 109259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre dev_err(iss->dev, "%s: Unable to register subdev %s\n", 109359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre __func__, board_info->board_info->type); 109459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre continue; 109559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 109659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 109759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (first) 109859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre sensor = subdev; 109959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 110059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 110159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return sensor; 110259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 110359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 110459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_register_entities(struct iss_device *iss) 110559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 110659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct iss_platform_data *pdata = iss->pdata; 110759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct iss_v4l2_subdevs_group *subdevs; 110859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre int ret; 110959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 111059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->media_dev.dev = iss->dev; 111159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre strlcpy(iss->media_dev.model, "TI OMAP4 ISS", 111259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre sizeof(iss->media_dev.model)); 111359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->media_dev.hw_revision = iss->revision; 111459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->media_dev.link_notify = iss_pipeline_link_notify; 111559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = media_device_register(&iss->media_dev); 111659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) { 111759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre printk(KERN_ERR "%s: Media device registration failed (%d)\n", 111859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre __func__, ret); 111959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return ret; 112059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 112159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 112259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->v4l2_dev.mdev = &iss->media_dev; 112359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = v4l2_device_register(iss->dev, &iss->v4l2_dev); 112459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) { 112559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre printk(KERN_ERR "%s: V4L2 device registration failed (%d)\n", 112659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre __func__, ret); 112759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto done; 112859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 112959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 113059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre /* Register internal entities */ 113159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = omap4iss_csi2_register_entities(&iss->csi2a, &iss->v4l2_dev); 113259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) 113359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto done; 113459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 113559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = omap4iss_csi2_register_entities(&iss->csi2b, &iss->v4l2_dev); 113659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) 113759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto done; 113859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 113959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = omap4iss_ipipeif_register_entities(&iss->ipipeif, &iss->v4l2_dev); 114059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) 114159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto done; 114259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 114359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = omap4iss_ipipe_register_entities(&iss->ipipe, &iss->v4l2_dev); 114459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) 114559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto done; 114659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 114759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = omap4iss_resizer_register_entities(&iss->resizer, &iss->v4l2_dev); 114859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) 114959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto done; 115059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 115159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre /* Register external entities */ 115259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre for (subdevs = pdata->subdevs; subdevs && subdevs->subdevs; ++subdevs) { 115359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct v4l2_subdev *sensor; 115459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct media_entity *input; 115559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre unsigned int flags; 115659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre unsigned int pad; 115759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 115859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre sensor = iss_register_subdev_group(iss, subdevs->subdevs); 115959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (sensor == NULL) 116059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre continue; 116159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 116259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre sensor->host_priv = subdevs; 116359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 116459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre /* Connect the sensor to the correct interface module. 116559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * CSI2a receiver through CSIPHY1, or 116659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre * CSI2b receiver through CSIPHY2 116759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre */ 116859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre switch (subdevs->interface) { 116959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre case ISS_INTERFACE_CSI2A_PHY1: 117059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre input = &iss->csi2a.subdev.entity; 117159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre pad = CSI2_PAD_SINK; 117259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre flags = MEDIA_LNK_FL_IMMUTABLE 117359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre | MEDIA_LNK_FL_ENABLED; 117459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre break; 117559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 117659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre case ISS_INTERFACE_CSI2B_PHY2: 117759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre input = &iss->csi2b.subdev.entity; 117859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre pad = CSI2_PAD_SINK; 117959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre flags = MEDIA_LNK_FL_IMMUTABLE 118059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre | MEDIA_LNK_FL_ENABLED; 118159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre break; 118259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 118359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre default: 118459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre printk(KERN_ERR "%s: invalid interface type %u\n", 118559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre __func__, subdevs->interface); 118659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = -EINVAL; 118759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto done; 118859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 118959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 119059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = media_entity_create_link(&sensor->entity, 0, input, pad, 119159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre flags); 119259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) 119359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto done; 119459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 119559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 119659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = v4l2_device_register_subdev_nodes(&iss->v4l2_dev); 119759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 119859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirredone: 119959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) 120059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss_unregister_entities(iss); 120159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 120259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return ret; 120359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 120459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 120559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic void iss_cleanup_modules(struct iss_device *iss) 120659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 120759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre omap4iss_csi2_cleanup(iss); 120859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre omap4iss_ipipeif_cleanup(iss); 120959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre omap4iss_ipipe_cleanup(iss); 121059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre omap4iss_resizer_cleanup(iss); 121159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 121259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 121359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_initialize_modules(struct iss_device *iss) 121459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 121559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre int ret; 121659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 121759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = omap4iss_csiphy_init(iss); 121859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) { 121959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre dev_err(iss->dev, "CSI PHY initialization failed\n"); 122059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto error_csiphy; 122159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 122259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 122359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = omap4iss_csi2_init(iss); 122459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) { 122559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre dev_err(iss->dev, "CSI2 initialization failed\n"); 122659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto error_csi2; 122759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 122859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 122959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = omap4iss_ipipeif_init(iss); 123059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) { 123159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre dev_err(iss->dev, "ISP IPIPEIF initialization failed\n"); 123259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto error_ipipeif; 123359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 123459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 123559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = omap4iss_ipipe_init(iss); 123659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) { 123759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre dev_err(iss->dev, "ISP IPIPE initialization failed\n"); 123859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto error_ipipe; 123959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 124059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 124159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = omap4iss_resizer_init(iss); 124259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) { 124359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre dev_err(iss->dev, "ISP RESIZER initialization failed\n"); 124459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto error_resizer; 124559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 124659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 124759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre /* Connect the submodules. */ 124859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = media_entity_create_link( 124959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre &iss->csi2a.subdev.entity, CSI2_PAD_SOURCE, 125059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0); 125159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) 125259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto error_link; 125359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 125459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = media_entity_create_link( 125559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre &iss->csi2b.subdev.entity, CSI2_PAD_SOURCE, 125659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0); 125759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) 125859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto error_link; 125959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 126059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = media_entity_create_link( 126159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP, 126259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre &iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0); 126359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) 126459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto error_link; 126559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 126659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = media_entity_create_link( 126759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP, 126859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre &iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0); 126959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) 127059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto error_link; 127159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 127259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = media_entity_create_link( 127359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre &iss->ipipe.subdev.entity, IPIPE_PAD_SOURCE_VP, 127459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre &iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0); 127559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) 127659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto error_link; 127759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 127859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 0; 127959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 128059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreerror_link: 128159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre omap4iss_resizer_cleanup(iss); 128259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreerror_resizer: 128359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre omap4iss_ipipe_cleanup(iss); 128459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreerror_ipipe: 128559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre omap4iss_ipipeif_cleanup(iss); 128659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreerror_ipipeif: 128759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre omap4iss_csi2_cleanup(iss); 128859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreerror_csi2: 128959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreerror_csiphy: 129059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return ret; 129159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 129259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 129359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_probe(struct platform_device *pdev) 129459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 129559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct iss_platform_data *pdata = pdev->dev.platform_data; 129659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct iss_device *iss; 129759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre int i, ret; 129859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 129959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (pdata == NULL) 130059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return -EINVAL; 130159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 130259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss = kzalloc(sizeof(*iss), GFP_KERNEL); 130359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (!iss) { 130459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre dev_err(&pdev->dev, "Could not allocate memory\n"); 130559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return -ENOMEM; 130659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 130759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 130859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre mutex_init(&iss->iss_mutex); 130959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 131059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->dev = &pdev->dev; 131159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->pdata = pdata; 131259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->ref_count = 0; 131359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 131459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->raw_dmamask = DMA_BIT_MASK(32); 131559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->dev->dma_mask = &iss->raw_dmamask; 131659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->dev->coherent_dma_mask = DMA_BIT_MASK(32); 131759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 131859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre platform_set_drvdata(pdev, iss); 131959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 132059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre /* Clocks */ 132159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = iss_map_mem_resource(pdev, iss, OMAP4_ISS_MEM_TOP); 132259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) 132359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto error; 132459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 132559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = iss_get_clocks(iss); 132659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) 132759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto error; 132859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 132959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (omap4iss_get(iss) == NULL) 133059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto error; 133159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 133259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = iss_reset(iss); 133359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) 133459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto error_iss; 133559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 133659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->revision = readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_REVISION); 133759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre dev_info(iss->dev, "Revision %08x found\n", iss->revision); 133859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 133959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre for (i = 1; i < OMAP4_ISS_MEM_LAST; i++) { 134059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = iss_map_mem_resource(pdev, iss, i); 134159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret) 134259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto error_iss; 134359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 134459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 134559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre /* Configure BTE BW_LIMITER field to max recommended value (1 GB) */ 134659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre writel((readl(iss->regs[OMAP4_ISS_MEM_BTE] + BTE_CTRL) & ~BTE_CTRL_BW_LIMITER_MASK) | 134759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre (18 << BTE_CTRL_BW_LIMITER_SHIFT), 134859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->regs[OMAP4_ISS_MEM_BTE] + BTE_CTRL); 134959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 135059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre /* Perform ISP reset */ 135159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = omap4iss_subclk_enable(iss, OMAP4_ISS_SUBCLK_ISP); 135259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) 135359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto error_iss; 135459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 135559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = iss_isp_reset(iss); 135659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) 135759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto error_iss; 135859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 135959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre dev_info(iss->dev, "ISP Revision %08x found\n", 136059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_REVISION)); 136159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 136259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre /* Interrupt */ 136359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->irq_num = platform_get_irq(pdev, 0); 136459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (iss->irq_num <= 0) { 136559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre dev_err(iss->dev, "No IRQ resource\n"); 136659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = -ENODEV; 136759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto error_iss; 136859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 136959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 137059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (request_irq(iss->irq_num, iss_isr, IRQF_SHARED, "OMAP4 ISS", iss)) { 137159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre dev_err(iss->dev, "Unable to request IRQ\n"); 137259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = -EINVAL; 137359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto error_iss; 137459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 137559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 137659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre /* Entities */ 137759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = iss_initialize_modules(iss); 137859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) 137959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto error_irq; 138059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 138159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre ret = iss_register_entities(iss); 138259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (ret < 0) 138359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre goto error_modules; 138459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 138559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre omap4iss_put(iss); 138659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 138759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 0; 138859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 138959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreerror_modules: 139059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss_cleanup_modules(iss); 139159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreerror_irq: 139259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre free_irq(iss->irq_num, iss); 139359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreerror_iss: 139459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre omap4iss_put(iss); 139559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirreerror: 139659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss_put_clocks(iss); 139759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 139859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre for (i = 0; i < OMAP4_ISS_MEM_LAST; i++) { 139959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (iss->regs[i]) { 140059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iounmap(iss->regs[i]); 140159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->regs[i] = NULL; 140259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 140359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 140459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (iss->res[i]) { 140559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre release_mem_region(iss->res[i]->start, 140659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre resource_size(iss->res[i])); 140759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->res[i] = NULL; 140859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 140959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 141059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre platform_set_drvdata(pdev, NULL); 141159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 141259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre mutex_destroy(&iss->iss_mutex); 141359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre kfree(iss); 141459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 141559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return ret; 141659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 141759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 141859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic int iss_remove(struct platform_device *pdev) 141959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre{ 142059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre struct iss_device *iss = platform_get_drvdata(pdev); 142159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre int i; 142259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 142359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss_unregister_entities(iss); 142459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss_cleanup_modules(iss); 142559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 142659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre free_irq(iss->irq_num, iss); 142759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss_put_clocks(iss); 142859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 142959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre for (i = 0; i < OMAP4_ISS_MEM_LAST; i++) { 143059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (iss->regs[i]) { 143159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iounmap(iss->regs[i]); 143259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->regs[i] = NULL; 143359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 143459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 143559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre if (iss->res[i]) { 143659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre release_mem_region(iss->res[i]->start, 143759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre resource_size(iss->res[i])); 143859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre iss->res[i] = NULL; 143959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 144059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre } 144159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 144259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre kfree(iss); 144359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 144459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre return 0; 144559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre} 144659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 144759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic struct platform_device_id omap4iss_id_table[] = { 144859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre { "omap4iss", 0 }, 144959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre { }, 145059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}; 145159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio AguirreMODULE_DEVICE_TABLE(platform, omap4iss_id_table); 145259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 145359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirrestatic struct platform_driver iss_driver = { 145459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre .probe = iss_probe, 145559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre .remove = iss_remove, 145659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre .id_table = omap4iss_id_table, 145759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre .driver = { 145859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre .owner = THIS_MODULE, 145959f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre .name = "omap4iss", 146059f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre }, 146159f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre}; 146259f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 146359f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirremodule_platform_driver(iss_driver); 146459f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio Aguirre 146559f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio AguirreMODULE_DESCRIPTION("TI OMAP4 ISS driver"); 146659f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio AguirreMODULE_AUTHOR("Sergio Aguirre <sergio.a.aguirre@gmail.com>"); 146759f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio AguirreMODULE_LICENSE("GPL"); 146859f0ad8076816d13f7cba80d2b178ff5ab787e2eSergio AguirreMODULE_VERSION(ISS_VIDEO_DRIVER_VERSION); 1469