From patchwork Thu Nov 22 15:18:25 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rui Miguel Silva X-Patchwork-Id: 151792 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp877105ljp; Thu, 22 Nov 2018 07:19:06 -0800 (PST) X-Google-Smtp-Source: AFSGD/WrSB6Y7XgQ+TZVrLzOKcSCCJX1mpBPAXLlTEKJHH3driIB4+mwRFBb3wt5cxZhytgaUPNm X-Received: by 2002:a17:902:1105:: with SMTP id d5mr1701662pla.47.1542899946495; Thu, 22 Nov 2018 07:19:06 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542899946; cv=none; d=google.com; s=arc-20160816; b=jItjV0HojgD9RhCWKqPF9gbU53JM3QCT3gTAciyKKCiQvpapM+gG5syqKAEnl+jr6G qOExBv6pYFITKAnFeVue0p33JEtZHa/admGoi5bcKG+d764ieRfMD0rzBlZxHuEJdrZQ EKZTFhN7bucch7/UImK1vnjS0/SO84vpHRG3GreWa3WJ6fdnLqRYDckunxWN3bzo4jhN ePQj/ScIgtL/ogBX9sngh+CM4cDWjKH/lfxbBbl4ofUJId7hmsB+GNNvI7l5TIviAIvq w8NSa0gWtGYWYJgnTTocARftWSDO7nzMPC+AOCcRDiPx5urb7HQFE297Jf8KsWQiNkmM ItVA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=JdxegwIT00xcMlWMNFNfRSYrQYgeN1TPqB9m+yMKv8c=; b=jtToqQFSYlj7KLPBDOmSagPy+gy3PxSQb/Fg+osasuoEh0arNhr/OsISZ7m2Bo3DdY LXsUnMjiI4pFK8SsfHpCrVxabyUNYerNF7XRF/JRhUVR2/qIq3+yvh4zkiD2xaGhYHSz D5kBvybIbQ483ZV9qwqc2YlTSNIHMa0UDlSwjKrFbmUTsQyo0b/x/6rL2YPVqEnRBxf8 V15Ni4pq1S5RkFc9IC2GCFzquU24GxkC6L40nBYBkrWKX9WOGUEm2eTFeNdEIHKjHIWV kYJimYMWR5R3uId3UCIuTqwG0IRrdxwmAv3iMnNZM7OJDHVud9znaALwe945/P0ASOuP XukA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ajQLuqwe; spf=pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-media-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h3si27736717pgl.468.2018.11.22.07.19.06; Thu, 22 Nov 2018 07:19:06 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ajQLuqwe; spf=pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-media-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2437565AbeKWB6w (ORCPT + 4 others); Thu, 22 Nov 2018 20:58:52 -0500 Received: from mail-wr1-f67.google.com ([209.85.221.67]:37521 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2437559AbeKWB6w (ORCPT ); Thu, 22 Nov 2018 20:58:52 -0500 Received: by mail-wr1-f67.google.com with SMTP id j10so9615424wru.4 for ; Thu, 22 Nov 2018 07:19:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=JdxegwIT00xcMlWMNFNfRSYrQYgeN1TPqB9m+yMKv8c=; b=ajQLuqweTFr1ywjt6oHFotbSdBTVUMS3wWqgSrD01qkK/mqmlMggt/dPleDniLr3b/ GBmYGdqKOBQ73Wsk+YK2arc+4aydc3imzlRvW1rv3C061Cq2EjYKAXTuX0Qb8/LyMZJ0 hwPNLwHxjxs/wSHSs7s5YufQ07jCXZrQ6OBPQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=JdxegwIT00xcMlWMNFNfRSYrQYgeN1TPqB9m+yMKv8c=; b=krhBzVLXzEaXVkMFKxOHMl+L2JzwNog3e5wPiy1tiIglO++d5vc7hWVrRL0vFvOkiF qV2Z7eBu/g1HVAONV/XCaG9t3+HZmYW3t6NdmEaGBCiPxGgqtMJJx46YlzVTl31iy1s6 yVeqlCDQraKdkHyRO+3c1eGLfdiwE4armFe0/TpLnhiNHZMsjr9fkR2QmCbPghSA2C74 VRf1iiS1qctewqIUAKlV9aKMf09fCJcrZ7iKQeI0DJHW0RxkYyXngGyFfcOfoTrOZLJC tRr4bT5hRLQWvTeN9TOhMS2Y6Hol1D4wENT6VaLjoUJnCJMdv3XYAOK5orfbSiaRDaaT ddRg== X-Gm-Message-State: AA+aEWbXnkjNyAKlyeZ5vGUpDTimvRtSmJPfnRGD1gVDMOq9unEYS8LA OS9Xbi1EHv+dJfpJHEcCks48hg== X-Received: by 2002:a5d:4d46:: with SMTP id a6mr10314390wru.28.1542899941660; Thu, 22 Nov 2018 07:19:01 -0800 (PST) Received: from arch-late.local (a109-49-46-234.cpe.netcabo.pt. [109.49.46.234]) by smtp.gmail.com with ESMTPSA id q7-v6sm4642476wmg.27.2018.11.22.07.19.00 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 22 Nov 2018 07:19:01 -0800 (PST) From: Rui Miguel Silva To: sakari.ailus@linux.intel.com, Steve Longerbeam , Hans Verkuil , Philipp Zabel Cc: linux-media@vger.kernel.org, devel@driverdev.osuosl.org, devicetree@vger.kernel.org, Greg Kroah-Hartman , Rui Miguel Silva Subject: [PATCH v9 04/13] media: staging/imx7: add MIPI CSI-2 receiver subdev for i.MX7 Date: Thu, 22 Nov 2018 15:18:25 +0000 Message-Id: <20181122151834.6194-5-rui.silva@linaro.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181122151834.6194-1-rui.silva@linaro.org> References: <20181122151834.6194-1-rui.silva@linaro.org> MIME-Version: 1.0 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Adds MIPI CSI-2 subdev for i.MX7 to connect with sensors with a MIPI CSI-2 interface. Signed-off-by: Rui Miguel Silva --- drivers/staging/media/imx/Makefile | 1 + drivers/staging/media/imx/imx7-mipi-csis.c | 1135 ++++++++++++++++++++ 2 files changed, 1136 insertions(+) create mode 100644 drivers/staging/media/imx/imx7-mipi-csis.c -- 2.19.1 diff --git a/drivers/staging/media/imx/Makefile b/drivers/staging/media/imx/Makefile index 074f016d3519..d2d909a36239 100644 --- a/drivers/staging/media/imx/Makefile +++ b/drivers/staging/media/imx/Makefile @@ -14,3 +14,4 @@ obj-$(CONFIG_VIDEO_IMX_CSI) += imx-media-csi.o obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-mipi-csi2.o obj-$(CONFIG_VIDEO_IMX7_CSI) += imx7-media-csi.o +obj-$(CONFIG_VIDEO_IMX7_CSI) += imx7-mipi-csis.o diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c b/drivers/staging/media/imx/imx7-mipi-csis.c new file mode 100644 index 000000000000..56963d0c2043 --- /dev/null +++ b/drivers/staging/media/imx/imx7-mipi-csis.c @@ -0,0 +1,1135 @@ +// SPDX-License-Identifier: GPL +/* + * Freescale i.MX7 SoC series MIPI-CSI V3.3 receiver driver + * + * Copyright (C) 2018 Linaro Ltd + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "imx-media.h" + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Debug level (0-2)"); + +#define CSIS_DRIVER_NAME "imx7-mipi-csis" +#define CSIS_SUBDEV_NAME CSIS_DRIVER_NAME + +#define CSIS_PAD_SINK 0 +#define CSIS_PAD_SOURCE 1 +#define CSIS_PADS_NUM 2 + +#define MIPI_CSIS_DEF_PIX_WIDTH 640 +#define MIPI_CSIS_DEF_PIX_HEIGHT 480 + +/* Register map definition */ + +/* CSIS common control */ +#define MIPI_CSIS_CMN_CTRL 0x04 +#define MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW BIT(16) +#define MIPI_CSIS_CMN_CTRL_INTER_MODE BIT(10) +#define MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW_CTRL BIT(2) +#define MIPI_CSIS_CMN_CTRL_RESET BIT(1) +#define MIPI_CSIS_CMN_CTRL_ENABLE BIT(0) + +#define MIPI_CSIS_CMN_CTRL_LANE_NR_OFFSET 8 +#define MIPI_CSIS_CMN_CTRL_LANE_NR_MASK (3 << 8) + +/* CSIS clock control */ +#define MIPI_CSIS_CLK_CTRL 0x08 +#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH3(x) ((x) << 28) +#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH2(x) ((x) << 24) +#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH1(x) ((x) << 20) +#define MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH0(x) ((x) << 16) +#define MIPI_CSIS_CLK_CTRL_CLKGATE_EN_MSK (0xf << 4) +#define MIPI_CSIS_CLK_CTRL_WCLK_SRC BIT(0) + +/* CSIS Interrupt mask */ +#define MIPI_CSIS_INTMSK 0x10 +#define MIPI_CSIS_INTMSK_EVEN_BEFORE BIT(31) +#define MIPI_CSIS_INTMSK_EVEN_AFTER BIT(30) +#define MIPI_CSIS_INTMSK_ODD_BEFORE BIT(29) +#define MIPI_CSIS_INTMSK_ODD_AFTER BIT(28) +#define MIPI_CSIS_INTMSK_FRAME_START BIT(24) +#define MIPI_CSIS_INTMSK_FRAME_END BIT(20) +#define MIPI_CSIS_INTMSK_ERR_SOT_HS BIT(16) +#define MIPI_CSIS_INTMSK_ERR_LOST_FS BIT(12) +#define MIPI_CSIS_INTMSK_ERR_LOST_FE BIT(8) +#define MIPI_CSIS_INTMSK_ERR_OVER BIT(4) +#define MIPI_CSIS_INTMSK_ERR_WRONG_CFG BIT(3) +#define MIPI_CSIS_INTMSK_ERR_ECC BIT(2) +#define MIPI_CSIS_INTMSK_ERR_CRC BIT(1) +#define MIPI_CSIS_INTMSK_ERR_UNKNOWN BIT(0) + +/* CSIS Interrupt source */ +#define MIPI_CSIS_INTSRC 0x14 +#define MIPI_CSIS_INTSRC_EVEN_BEFORE BIT(31) +#define MIPI_CSIS_INTSRC_EVEN_AFTER BIT(30) +#define MIPI_CSIS_INTSRC_EVEN BIT(30) +#define MIPI_CSIS_INTSRC_ODD_BEFORE BIT(29) +#define MIPI_CSIS_INTSRC_ODD_AFTER BIT(28) +#define MIPI_CSIS_INTSRC_ODD (0x3 << 28) +#define MIPI_CSIS_INTSRC_NON_IMAGE_DATA (0xf << 28) +#define MIPI_CSIS_INTSRC_FRAME_START BIT(24) +#define MIPI_CSIS_INTSRC_FRAME_END BIT(20) +#define MIPI_CSIS_INTSRC_ERR_SOT_HS BIT(16) +#define MIPI_CSIS_INTSRC_ERR_LOST_FS BIT(12) +#define MIPI_CSIS_INTSRC_ERR_LOST_FE BIT(8) +#define MIPI_CSIS_INTSRC_ERR_OVER BIT(4) +#define MIPI_CSIS_INTSRC_ERR_WRONG_CFG BIT(3) +#define MIPI_CSIS_INTSRC_ERR_ECC BIT(2) +#define MIPI_CSIS_INTSRC_ERR_CRC BIT(1) +#define MIPI_CSIS_INTSRC_ERR_UNKNOWN BIT(0) +#define MIPI_CSIS_INTSRC_ERRORS 0xfffff + +/* D-PHY status control */ +#define MIPI_CSIS_DPHYSTATUS 0x20 +#define MIPI_CSIS_DPHYSTATUS_ULPS_DAT BIT(8) +#define MIPI_CSIS_DPHYSTATUS_STOPSTATE_DAT BIT(4) +#define MIPI_CSIS_DPHYSTATUS_ULPS_CLK BIT(1) +#define MIPI_CSIS_DPHYSTATUS_STOPSTATE_CLK BIT(0) + +/* D-PHY common control */ +#define MIPI_CSIS_DPHYCTRL 0x24 +#define MIPI_CSIS_DPHYCTRL_HSS_MASK (0xff << 24) +#define MIPI_CSIS_DPHYCTRL_HSS_OFFSET 24 +#define MIPI_CSIS_DPHYCTRL_SCLKS_MASK (0x3 << 22) +#define MIPI_CSIS_DPHYCTRL_SCLKS_OFFSET 22 +#define MIPI_CSIS_DPHYCTRL_DPDN_SWAP_CLK BIT(6) +#define MIPI_CSIS_DPHYCTRL_DPDN_SWAP_DAT BIT(5) +#define MIPI_CSIS_DPHYCTRL_ENABLE_DAT BIT(1) +#define MIPI_CSIS_DPHYCTRL_ENABLE_CLK BIT(0) +#define MIPI_CSIS_DPHYCTRL_ENABLE (0x1f << 0) + +/* D-PHY Master and Slave Control register Low */ +#define MIPI_CSIS_DPHYBCTRL_L 0x30 +/* D-PHY Master and Slave Control register High */ +#define MIPI_CSIS_DPHYBCTRL_H 0x34 +/* D-PHY Slave Control register Low */ +#define MIPI_CSIS_DPHYSCTRL_L 0x38 +/* D-PHY Slave Control register High */ +#define MIPI_CSIS_DPHYSCTRL_H 0x3c + +/* ISP Configuration register */ +#define MIPI_CSIS_ISPCONFIG_CH0 0x40 +#define MIPI_CSIS_ISPCONFIG_CH1 0x50 +#define MIPI_CSIS_ISPCONFIG_CH2 0x60 +#define MIPI_CSIS_ISPCONFIG_CH3 0x70 + +#define MIPI_CSIS_ISPCFG_MEM_FULL_GAP_MSK (0xff << 24) +#define MIPI_CSIS_ISPCFG_MEM_FULL_GAP(x) ((x) << 24) +#define MIPI_CSIS_ISPCFG_DOUBLE_CMPNT BIT(12) +#define MIPI_CSIS_ISPCFG_ALIGN_32BIT BIT(11) +#define MIPI_CSIS_ISPCFG_FMT_YCBCR422_8BIT (0x1e << 2) +#define MIPI_CSIS_ISPCFG_FMT_RAW8 (0x2a << 2) +#define MIPI_CSIS_ISPCFG_FMT_RAW10 (0x2b << 2) +#define MIPI_CSIS_ISPCFG_FMT_RAW12 (0x2c << 2) + +/* User defined formats, x = 1...4 */ +#define MIPI_CSIS_ISPCFG_FMT_USER(x) ((0x30 + (x) - 1) << 2) +#define MIPI_CSIS_ISPCFG_FMT_MASK (0x3f << 2) + +/* ISP Image Resolution register */ +#define MIPI_CSIS_ISPRESOL_CH0 0x44 +#define MIPI_CSIS_ISPRESOL_CH1 0x54 +#define MIPI_CSIS_ISPRESOL_CH2 0x64 +#define MIPI_CSIS_ISPRESOL_CH3 0x74 +#define CSIS_MAX_PIX_WIDTH 0xffff +#define CSIS_MAX_PIX_HEIGHT 0xffff + +/* ISP SYNC register */ +#define MIPI_CSIS_ISPSYNC_CH0 0x48 +#define MIPI_CSIS_ISPSYNC_CH1 0x58 +#define MIPI_CSIS_ISPSYNC_CH2 0x68 +#define MIPI_CSIS_ISPSYNC_CH3 0x78 + +#define MIPI_CSIS_ISPSYNC_HSYNC_LINTV_OFFSET 18 +#define MIPI_CSIS_ISPSYNC_VSYNC_SINTV_OFFSET 12 +#define MIPI_CSIS_ISPSYNC_VSYNC_EINTV_OFFSET 0 + +/* Non-image packet data buffers */ +#define MIPI_CSIS_PKTDATA_ODD 0x2000 +#define MIPI_CSIS_PKTDATA_EVEN 0x3000 +#define MIPI_CSIS_PKTDATA_SIZE SZ_4K + +#define DEFAULT_SCLK_CSIS_FREQ 166000000UL + +enum { + ST_POWERED = 1, + ST_STREAMING = 2, + ST_SUSPENDED = 4, +}; + +struct mipi_csis_event { + u32 mask; + const char * const name; + unsigned int counter; +}; + +static const struct mipi_csis_event mipi_csis_events[] = { + /* Errors */ + { MIPI_CSIS_INTSRC_ERR_SOT_HS, "SOT Error" }, + { MIPI_CSIS_INTSRC_ERR_LOST_FS, "Lost Frame Start Error" }, + { MIPI_CSIS_INTSRC_ERR_LOST_FE, "Lost Frame End Error" }, + { MIPI_CSIS_INTSRC_ERR_OVER, "FIFO Overflow Error" }, + { MIPI_CSIS_INTSRC_ERR_WRONG_CFG, "Wrong Configuration Error" }, + { MIPI_CSIS_INTSRC_ERR_ECC, "ECC Error" }, + { MIPI_CSIS_INTSRC_ERR_CRC, "CRC Error" }, + { MIPI_CSIS_INTSRC_ERR_UNKNOWN, "Unknown Error" }, + /* Non-image data receive events */ + { MIPI_CSIS_INTSRC_EVEN_BEFORE, "Non-image data before even frame" }, + { MIPI_CSIS_INTSRC_EVEN_AFTER, "Non-image data after even frame" }, + { MIPI_CSIS_INTSRC_ODD_BEFORE, "Non-image data before odd frame" }, + { MIPI_CSIS_INTSRC_ODD_AFTER, "Non-image data after odd frame" }, + /* Frame start/end */ + { MIPI_CSIS_INTSRC_FRAME_START, "Frame Start" }, + { MIPI_CSIS_INTSRC_FRAME_END, "Frame End" }, +}; + +#define MIPI_CSIS_NUM_EVENTS ARRAY_SIZE(mipi_csis_events) + +struct csis_hw_reset { + struct regmap *src; + u8 req_src; + u8 rst_bit; +}; + +struct csi_state { + /* lock elements below */ + struct mutex lock; + /* lock for event handler */ + spinlock_t slock; + struct device *dev; + struct media_pad pads[CSIS_PADS_NUM]; + struct v4l2_subdev mipi_sd; + struct v4l2_subdev *src_sd; + + u8 index; + struct platform_device *pdev; + struct phy *phy; + void __iomem *regs; + struct clk *pclk_clk; + struct clk *wrap_clk; + struct clk *phy_clk; + int irq; + u32 flags; + + u32 clk_frequency; + u32 hs_settle; + + struct reset_control *mrst; + + const struct csis_pix_format *csis_fmt; + struct v4l2_mbus_framefmt format_mbus; + + struct v4l2_fwnode_bus_mipi_csi2 bus; + + struct mipi_csis_event events[MIPI_CSIS_NUM_EVENTS]; + + struct v4l2_async_notifier subdev_notifier; + + struct csis_hw_reset hw_reset; + struct regulator *mipi_phy_regulator; + bool sink_linked; +}; + +struct csis_pix_format { + unsigned int pix_width_alignment; + u32 code; + u32 fmt_reg; + u8 data_alignment; +}; + +static const struct csis_pix_format mipi_csis_formats[] = { + { + .code = MEDIA_BUS_FMT_SBGGR10_1X10, + .fmt_reg = MIPI_CSIS_ISPCFG_FMT_RAW10, + .data_alignment = 16, + }, { + .code = MEDIA_BUS_FMT_VYUY8_2X8, + .fmt_reg = MIPI_CSIS_ISPCFG_FMT_YCBCR422_8BIT, + .data_alignment = 16, + }, { + .code = MEDIA_BUS_FMT_SBGGR8_1X8, + .fmt_reg = MIPI_CSIS_ISPCFG_FMT_RAW8, + .data_alignment = 8, + }, { + .code = MEDIA_BUS_FMT_YUYV8_2X8, + .fmt_reg = MIPI_CSIS_ISPCFG_FMT_YCBCR422_8BIT, + .data_alignment = 16, + } +}; + +#define mipi_csis_write(__csis, __r, __v) writel(__v, (__csis)->regs + (__r)) +#define mipi_csis_read(__csis, __r) readl((__csis)->regs + (__r)) + +static void dump_regs(struct csi_state *state, const char *label) +{ + u32 cfg; + u32 i; + struct { + u32 offset; + const char * const name; + } registers[] = { + { 0x04, "CTRL" }, + { 0x24, "DPHYCTRL" }, + { 0x08, "CLKCTRL" }, + { 0x20, "DPHYSTS" }, + { 0x10, "INTMSK" }, + { 0x40, "CONFIG_CH0" }, + { 0xC0, "DBG_CONFIG" }, + { 0x38, "DPHYSLAVE_L" }, + { 0x3C, "DPHYSLAVE_H" }, + }; + + v4l2_info(&state->mipi_sd, "--- %s ---\n", label); + + for (i = 0; i < ARRAY_SIZE(registers); i++) { + cfg = mipi_csis_read(state, registers[i].offset); + v4l2_info(&state->mipi_sd, "%12s: 0x%08x 0x%p\n", + registers[i].name, cfg, state->regs); + } +} + +static struct csi_state *mipi_sd_to_csis_state(struct v4l2_subdev *sdev) +{ + return container_of(sdev, struct csi_state, mipi_sd); +} + +static const struct csis_pix_format *find_csis_format(u32 code) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mipi_csis_formats); i++) + if (code == mipi_csis_formats[i].code) + return &mipi_csis_formats[i]; + return NULL; +} + +static void mipi_csis_enable_interrupts(struct csi_state *state, bool on) +{ + u32 val = mipi_csis_read(state, MIPI_CSIS_INTMSK); + + if (on) + val |= 0xffffffff; + else + val &= ~0xffffffff; + mipi_csis_write(state, MIPI_CSIS_INTMSK, val); +} + +static void mipi_csis_sw_reset(struct csi_state *state) +{ + u32 val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL); + + mipi_csis_write(state, MIPI_CSIS_CMN_CTRL, + val | MIPI_CSIS_CMN_CTRL_RESET); + usleep_range(10, 20); +} + +static int mipi_csis_phy_init(struct csi_state *state) +{ + state->mipi_phy_regulator = devm_regulator_get(state->dev, "phy"); + + return regulator_set_voltage(state->mipi_phy_regulator, 1000000, + 1000000); +} + +static void mipi_csis_phy_reset(struct csi_state *state) +{ + reset_control_assert(state->mrst); + + msleep(20); + + reset_control_deassert(state->mrst); +} + +static void mipi_csis_system_enable(struct csi_state *state, int on) +{ + u32 val, mask; + + val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL); + if (on) + val |= MIPI_CSIS_CMN_CTRL_ENABLE; + else + val &= ~MIPI_CSIS_CMN_CTRL_ENABLE; + mipi_csis_write(state, MIPI_CSIS_CMN_CTRL, val); + + val = mipi_csis_read(state, MIPI_CSIS_DPHYCTRL); + val &= ~MIPI_CSIS_DPHYCTRL_ENABLE; + if (on) { + mask = (1 << (state->bus.num_data_lanes + 1)) - 1; + val |= (mask & MIPI_CSIS_DPHYCTRL_ENABLE); + } + mipi_csis_write(state, MIPI_CSIS_DPHYCTRL, val); +} + +/* Called with the state.lock mutex held */ +static void __mipi_csis_set_format(struct csi_state *state) +{ + struct v4l2_mbus_framefmt *mf = &state->format_mbus; + u32 val; + + /* Color format */ + val = mipi_csis_read(state, MIPI_CSIS_ISPCONFIG_CH0); + val = (val & ~MIPI_CSIS_ISPCFG_FMT_MASK) | state->csis_fmt->fmt_reg; + mipi_csis_write(state, MIPI_CSIS_ISPCONFIG_CH0, val); + + /* Pixel resolution */ + val = mf->width | (mf->height << 16); + mipi_csis_write(state, MIPI_CSIS_ISPRESOL_CH0, val); +} + +static void mipi_csis_set_hsync_settle(struct csi_state *state, int hs_settle) +{ + u32 val = mipi_csis_read(state, MIPI_CSIS_DPHYCTRL); + + val = ((val & ~MIPI_CSIS_DPHYCTRL_HSS_MASK) | (hs_settle << 24)); + + mipi_csis_write(state, MIPI_CSIS_DPHYCTRL, val); +} + +static void mipi_csis_set_params(struct csi_state *state) +{ + int lanes = state->bus.num_data_lanes; + u32 val; + + val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL); + val &= ~MIPI_CSIS_CMN_CTRL_LANE_NR_MASK; + val |= (lanes - 1) << MIPI_CSIS_CMN_CTRL_LANE_NR_OFFSET; + mipi_csis_write(state, MIPI_CSIS_CMN_CTRL, val); + + __mipi_csis_set_format(state); + + mipi_csis_set_hsync_settle(state, state->hs_settle); + + val = mipi_csis_read(state, MIPI_CSIS_ISPCONFIG_CH0); + if (state->csis_fmt->data_alignment == 32) + val |= MIPI_CSIS_ISPCFG_ALIGN_32BIT; + else + val &= ~MIPI_CSIS_ISPCFG_ALIGN_32BIT; + mipi_csis_write(state, MIPI_CSIS_ISPCONFIG_CH0, val); + + val = (0 << MIPI_CSIS_ISPSYNC_HSYNC_LINTV_OFFSET) | + (0 << MIPI_CSIS_ISPSYNC_VSYNC_SINTV_OFFSET) | + (0 << MIPI_CSIS_ISPSYNC_VSYNC_EINTV_OFFSET); + mipi_csis_write(state, MIPI_CSIS_ISPSYNC_CH0, val); + + val = mipi_csis_read(state, MIPI_CSIS_CLK_CTRL); + val &= ~MIPI_CSIS_CLK_CTRL_WCLK_SRC; + if (state->wrap_clk) + val |= MIPI_CSIS_CLK_CTRL_WCLK_SRC; + else + val &= ~MIPI_CSIS_CLK_CTRL_WCLK_SRC; + + val |= MIPI_CSIS_CLK_CTRL_CLKGATE_TRAIL_CH0(15); + val &= ~MIPI_CSIS_CLK_CTRL_CLKGATE_EN_MSK; + mipi_csis_write(state, MIPI_CSIS_CLK_CTRL, val); + + mipi_csis_write(state, MIPI_CSIS_DPHYBCTRL_L, 0x1f4); + mipi_csis_write(state, MIPI_CSIS_DPHYBCTRL_H, 0); + + /* Update the shadow register. */ + val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL); + mipi_csis_write(state, MIPI_CSIS_CMN_CTRL, + val | MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW | + MIPI_CSIS_CMN_CTRL_UPDATE_SHADOW_CTRL); +} + +static void mipi_csis_clk_enable(struct csi_state *state) +{ + clk_prepare_enable(state->pclk_clk); + clk_prepare_enable(state->wrap_clk); + clk_prepare_enable(state->phy_clk); +} + +static void mipi_csis_clk_disable(struct csi_state *state) +{ + clk_disable_unprepare(state->pclk_clk); + clk_disable_unprepare(state->wrap_clk); + clk_disable_unprepare(state->phy_clk); +} + +static int mipi_csis_clk_get(struct csi_state *state) +{ + struct device *dev = &state->pdev->dev; + int ret; + + state->pclk_clk = devm_clk_get(dev, "pclk"); + if (IS_ERR(state->pclk_clk)) { + dev_err(dev, "Could not get pclk clock\n"); + return -ENODEV; + } + + state->wrap_clk = devm_clk_get(dev, "wrap"); + if (IS_ERR(state->wrap_clk)) { + dev_info(dev, "Could not get wrap clock, using pclk\n"); + state->wrap_clk = NULL; + } + + state->phy_clk = devm_clk_get(dev, "phy"); + if (IS_ERR(state->phy_clk)) { + dev_err(dev, "Could not get mipi phy clock\n"); + return -ENODEV; + } + + /* Set clock rate */ + ret = clk_set_rate(state->wrap_clk, state->clk_frequency); + if (ret < 0) + dev_err(dev, "set rate=%d failed: %d\n", state->clk_frequency, + ret); + + return ret; +} + +static void mipi_csis_start_stream(struct csi_state *state) +{ + mipi_csis_sw_reset(state); + mipi_csis_set_params(state); + mipi_csis_system_enable(state, true); + mipi_csis_enable_interrupts(state, true); +} + +static void mipi_csis_stop_stream(struct csi_state *state) +{ + mipi_csis_enable_interrupts(state, false); + mipi_csis_system_enable(state, false); +} + +static void mipi_csis_clear_counters(struct csi_state *state) +{ + unsigned long flags; + int i; + + spin_lock_irqsave(&state->slock, flags); + for (i = 0; i < MIPI_CSIS_NUM_EVENTS; i++) + state->events[i].counter = 0; + spin_unlock_irqrestore(&state->slock, flags); +} + +static void mipi_csis_log_counters(struct csi_state *state, bool non_errors) +{ + int i = non_errors ? MIPI_CSIS_NUM_EVENTS : MIPI_CSIS_NUM_EVENTS - 4; + unsigned long flags; + + spin_lock_irqsave(&state->slock, flags); + + for (i--; i >= 0; i--) { + if (state->events[i].counter > 0 || debug) + v4l2_info(&state->mipi_sd, "%s events: %d\n", + state->events[i].name, + state->events[i].counter); + } + spin_unlock_irqrestore(&state->slock, flags); +} + +/* + * V4L2 subdev operations + */ +static int mipi_csis_s_power(struct v4l2_subdev *mipi_sd, int on) +{ + struct csi_state *state = mipi_sd_to_csis_state(mipi_sd); + struct device *dev = &state->pdev->dev; + + v4l2_subdev_call(state->src_sd, core, s_power, on); + + if (on) + return pm_runtime_get_sync(dev); + + return pm_runtime_put_sync(dev); +} + +static int mipi_csis_s_stream(struct v4l2_subdev *mipi_sd, int enable) +{ + struct csi_state *state = mipi_sd_to_csis_state(mipi_sd); + int ret = 0; + + if (enable) { + mipi_csis_clear_counters(state); + ret = pm_runtime_get_sync(&state->pdev->dev); + if (ret && ret != 1) + return ret; + } + + mutex_lock(&state->lock); + if (enable) { + if (state->flags & ST_SUSPENDED) { + ret = -EBUSY; + goto unlock; + } + + mipi_csis_start_stream(state); + ret = v4l2_subdev_call(state->src_sd, video, s_stream, 1); + if (ret < 0) + goto unlock; + + mipi_csis_log_counters(state, true); + + state->flags |= ST_STREAMING; + } else { + v4l2_subdev_call(state->src_sd, video, s_stream, 0); + mipi_csis_stop_stream(state); + state->flags &= ~ST_STREAMING; + if (debug > 0) + mipi_csis_log_counters(state, true); + } + +unlock: + mutex_unlock(&state->lock); + if (!enable) + pm_runtime_put(&state->pdev->dev); + + return ret; +} + +static int mipi_csis_link_setup(struct media_entity *entity, + const struct media_pad *local_pad, + const struct media_pad *remote_pad, u32 flags) +{ + struct v4l2_subdev *mipi_sd = media_entity_to_v4l2_subdev(entity); + struct csi_state *state = mipi_sd_to_csis_state(mipi_sd); + struct v4l2_subdev *remote_sd; + int ret = 0; + + dev_dbg(state->dev, "link setup %s -> %s", remote_pad->entity->name, + local_pad->entity->name); + + remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity); + + mutex_lock(&state->lock); + + if (local_pad->flags & MEDIA_PAD_FL_SOURCE) { + if (flags & MEDIA_LNK_FL_ENABLED) { + if (state->sink_linked) { + ret = -EBUSY; + goto out; + } + state->sink_linked = true; + } else { + state->sink_linked = false; + } + } else { + if (flags & MEDIA_LNK_FL_ENABLED) { + if (state->src_sd) { + ret = -EBUSY; + goto out; + } + state->src_sd = remote_sd; + } else { + state->src_sd = NULL; + } + } + +out: + mutex_unlock(&state->lock); + return ret; +} + +static int mipi_csis_init_cfg(struct v4l2_subdev *mipi_sd, + struct v4l2_subdev_pad_config *cfg) +{ + struct v4l2_mbus_framefmt *mf; + int ret; + int i; + + for (i = 0; i < CSIS_PADS_NUM; i++) { + mf = v4l2_subdev_get_try_format(mipi_sd, cfg, i); + + ret = imx_media_init_mbus_fmt(mf, MIPI_CSIS_DEF_PIX_HEIGHT, + MIPI_CSIS_DEF_PIX_WIDTH, 0, + V4L2_FIELD_NONE, NULL); + if (ret < 0) + return ret; + } + + return 0; +} + +static struct csis_pix_format const *mipi_csis_try_format( + struct v4l2_subdev *mipi_sd, + struct v4l2_mbus_framefmt *mf) +{ + struct csi_state *state = mipi_sd_to_csis_state(mipi_sd); + struct csis_pix_format const *csis_fmt; + + csis_fmt = find_csis_format(mf->code); + if (!csis_fmt) + csis_fmt = &mipi_csis_formats[0]; + + v4l_bound_align_image(&mf->width, 1, CSIS_MAX_PIX_WIDTH, + csis_fmt->pix_width_alignment, + &mf->height, 1, CSIS_MAX_PIX_HEIGHT, 1, + 0); + + state->format_mbus.code = csis_fmt->code; + state->format_mbus.width = mf->width; + state->format_mbus.height = mf->height; + + return csis_fmt; +} + +static struct v4l2_mbus_framefmt *mipi_csis_get_format(struct csi_state *state, + struct v4l2_subdev_pad_config *cfg, + enum v4l2_subdev_format_whence which, + unsigned int pad) +{ + if (which == V4L2_SUBDEV_FORMAT_TRY) + return v4l2_subdev_get_try_format(&state->mipi_sd, cfg, pad); + + return &state->format_mbus; +} + +static int mipi_csis_set_fmt(struct v4l2_subdev *mipi_sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *sdformat) +{ + struct csi_state *state = mipi_sd_to_csis_state(mipi_sd); + struct csis_pix_format const *csis_fmt; + struct v4l2_mbus_framefmt *fmt; + + if (sdformat->pad >= CSIS_PADS_NUM) + return -EINVAL; + + fmt = mipi_csis_get_format(state, cfg, sdformat->which, sdformat->pad); + + mutex_lock(&state->lock); + if (fmt && sdformat->pad == CSIS_PAD_SOURCE) { + sdformat->format = *fmt; + goto unlock; + } + + csis_fmt = mipi_csis_try_format(mipi_sd, &sdformat->format); + + sdformat->format = *fmt; + + if (csis_fmt && sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE) + state->csis_fmt = csis_fmt; + else + cfg->try_fmt = sdformat->format; + +unlock: + mutex_unlock(&state->lock); + + return 0; +} + +static int mipi_csis_get_fmt(struct v4l2_subdev *mipi_sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *sdformat) +{ + struct csi_state *state = mipi_sd_to_csis_state(mipi_sd); + struct v4l2_mbus_framefmt *fmt; + + mutex_lock(&state->lock); + + fmt = mipi_csis_get_format(state, cfg, sdformat->which, sdformat->pad); + + sdformat->format = *fmt; + + mutex_unlock(&state->lock); + + return 0; +} + +static int mipi_csis_log_status(struct v4l2_subdev *mipi_sd) +{ + struct csi_state *state = mipi_sd_to_csis_state(mipi_sd); + + mutex_lock(&state->lock); + mipi_csis_log_counters(state, true); + if (debug && (state->flags & ST_POWERED)) + dump_regs(state, __func__); + mutex_unlock(&state->lock); + + return 0; +} + +static irqreturn_t mipi_csis_irq_handler(int irq, void *dev_id) +{ + struct csi_state *state = dev_id; + unsigned long flags; + u32 status; + int i; + + status = mipi_csis_read(state, MIPI_CSIS_INTSRC); + + spin_lock_irqsave(&state->slock, flags); + + /* Update the event/error counters */ + if ((status & MIPI_CSIS_INTSRC_ERRORS) || debug) { + for (i = 0; i < MIPI_CSIS_NUM_EVENTS; i++) { + if (!(status & state->events[i].mask)) + continue; + state->events[i].counter++; + } + } + spin_unlock_irqrestore(&state->slock, flags); + + mipi_csis_write(state, MIPI_CSIS_INTSRC, status); + + return IRQ_HANDLED; +} + +static int mipi_csi_registered(struct v4l2_subdev *mipi_sd) +{ + struct csi_state *state = mipi_sd_to_csis_state(mipi_sd); + int i, ret; + + for (i = 0; i < CSIS_PADS_NUM; i++) { + state->pads[i].flags = (i == CSIS_PAD_SINK) ? + MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE; + } + + /* set a default mbus format */ + ret = imx_media_init_mbus_fmt(&state->format_mbus, + MIPI_CSIS_DEF_PIX_HEIGHT, + MIPI_CSIS_DEF_PIX_WIDTH, 0, + V4L2_FIELD_NONE, NULL); + if (ret) + return ret; + + return media_entity_pads_init(&mipi_sd->entity, CSIS_PADS_NUM, + state->pads); +} + +static struct v4l2_subdev_core_ops mipi_csis_core_ops = { + .s_power = mipi_csis_s_power, + .log_status = mipi_csis_log_status, +}; + +static const struct media_entity_operations mipi_csis_entity_ops = { + .link_setup = mipi_csis_link_setup, + .link_validate = v4l2_subdev_link_validate, +}; + +static struct v4l2_subdev_video_ops mipi_csis_video_ops = { + .s_stream = mipi_csis_s_stream, +}; + +static const struct v4l2_subdev_pad_ops mipi_csis_pad_ops = { + .init_cfg = mipi_csis_init_cfg, + .get_fmt = mipi_csis_get_fmt, + .set_fmt = mipi_csis_set_fmt, +}; + +static struct v4l2_subdev_ops mipi_csis_subdev_ops = { + .core = &mipi_csis_core_ops, + .video = &mipi_csis_video_ops, + .pad = &mipi_csis_pad_ops, +}; + +static const struct v4l2_subdev_internal_ops mipi_csis_internal_ops = { + .registered = mipi_csi_registered, +}; + +static int mipi_csis_parse_dt(struct platform_device *pdev, + struct csi_state *state) +{ + struct device_node *node = pdev->dev.of_node; + + if (of_property_read_u32(node, "clock-frequency", + &state->clk_frequency)) + state->clk_frequency = DEFAULT_SCLK_CSIS_FREQ; + + /* Get MIPI PHY resets */ + state->mrst = devm_reset_control_get_exclusive(&pdev->dev, "mrst"); + if (IS_ERR(state->mrst)) + return PTR_ERR(state->mrst); + + /* Get MIPI CSI-2 bus configration from the endpoint node. */ + of_property_read_u32(node, "fsl,csis-hs-settle", &state->hs_settle); + + return 0; +} + +static int mipi_csis_pm_resume(struct device *dev, bool runtime); + +static int mipi_csis_parse_endpoint(struct device *dev, + struct v4l2_fwnode_endpoint *ep, + struct v4l2_async_subdev *asd) +{ + struct v4l2_subdev *mipi_sd = dev_get_drvdata(dev); + struct csi_state *state = mipi_sd_to_csis_state(mipi_sd); + + if (!fwnode_device_is_available(asd->match.fwnode)) { + v4l2_err(mipi_sd, "remote is not available\n"); + return -EINVAL; + } + + if (ep->bus_type != V4L2_MBUS_CSI2_DPHY) + v4l2_err(mipi_sd, "invalid bus type, must be MIPI CSI2\n"); + + state->bus = ep->bus.mipi_csi2; + + dev_dbg(state->dev, "data lanes: %d\n", state->bus.num_data_lanes); + dev_dbg(state->dev, "flags: 0x%08x\n", state->bus.flags); + + return 0; +} + +static int mipi_csis_subdev_init(struct v4l2_subdev *mipi_sd, + struct platform_device *pdev, + const struct v4l2_subdev_ops *ops) +{ + struct csi_state *state = mipi_sd_to_csis_state(mipi_sd); + unsigned int sink_port = 0; + int ret; + + v4l2_subdev_init(mipi_sd, ops); + mipi_sd->owner = THIS_MODULE; + snprintf(mipi_sd->name, sizeof(mipi_sd->name), "%s.%d", + CSIS_SUBDEV_NAME, state->index); + + mipi_sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + mipi_sd->ctrl_handler = NULL; + + mipi_sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; + mipi_sd->entity.ops = &mipi_csis_entity_ops; + + mipi_sd->dev = &pdev->dev; + + state->csis_fmt = &mipi_csis_formats[0]; + state->format_mbus.code = mipi_csis_formats[0].code; + state->format_mbus.width = MIPI_CSIS_DEF_PIX_WIDTH; + state->format_mbus.height = MIPI_CSIS_DEF_PIX_HEIGHT; + state->format_mbus.field = V4L2_FIELD_NONE; + + v4l2_set_subdevdata(mipi_sd, &pdev->dev); + + ret = v4l2_async_register_fwnode_subdev(mipi_sd, + sizeof(struct v4l2_async_subdev), &sink_port, 1, + mipi_csis_parse_endpoint); + if (ret < 0) + dev_err(&pdev->dev, "async fwnode register failed: %d\n", ret); + + return ret; +} + +static int mipi_csis_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct resource *mem_res; + struct csi_state *state; + int ret = -ENOMEM; + + state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; + + mutex_init(&state->lock); + spin_lock_init(&state->slock); + + state->pdev = pdev; + state->dev = dev; + + ret = mipi_csis_parse_dt(pdev, state); + if (ret < 0) { + dev_err(dev, "Failed to parse device tree: %d\n", ret); + return ret; + } + + mipi_csis_phy_init(state); + mipi_csis_phy_reset(state); + + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + state->regs = devm_ioremap_resource(dev, mem_res); + if (IS_ERR(state->regs)) + return PTR_ERR(state->regs); + + state->irq = platform_get_irq(pdev, 0); + if (state->irq < 0) { + dev_err(dev, "Failed to get irq\n"); + return state->irq; + } + + ret = mipi_csis_clk_get(state); + if (ret < 0) + return ret; + + mipi_csis_clk_enable(state); + + ret = devm_request_irq(dev, state->irq, mipi_csis_irq_handler, + 0, dev_name(dev), state); + if (ret) { + dev_err(dev, "Interrupt request failed\n"); + goto disable_clock; + } + + platform_set_drvdata(pdev, &state->mipi_sd); + + ret = mipi_csis_subdev_init(&state->mipi_sd, pdev, + &mipi_csis_subdev_ops); + if (ret < 0) + goto disable_clock; + + state->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK; + state->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; + ret = media_entity_pads_init(&state->mipi_sd.entity, CSIS_PADS_NUM, + state->pads); + if (ret < 0) + goto unregister_subdev; + + memcpy(state->events, mipi_csis_events, sizeof(state->events)); + + pm_runtime_enable(dev); + if (!pm_runtime_enabled(dev)) { + ret = mipi_csis_pm_resume(dev, true); + if (ret < 0) + goto unregister_all; + } + + dev_info(&pdev->dev, "lanes: %d, hs_settle: %d, wclk: %d, freq: %u\n", + state->bus.num_data_lanes, state->hs_settle, + state->wrap_clk ? 1 : 0, state->clk_frequency); + return 0; + +unregister_all: + media_entity_cleanup(&state->mipi_sd.entity); +unregister_subdev: + v4l2_async_unregister_subdev(&state->mipi_sd); +disable_clock: + mipi_csis_clk_disable(state); + + return ret; +} + +static int mipi_csis_pm_suspend(struct device *dev, bool runtime) +{ + struct platform_device *pdev = to_platform_device(dev); + struct v4l2_subdev *mipi_sd = platform_get_drvdata(pdev); + struct csi_state *state = mipi_sd_to_csis_state(mipi_sd); + int ret = 0; + + mutex_lock(&state->lock); + if (state->flags & ST_POWERED) { + mipi_csis_stop_stream(state); + ret = regulator_disable(state->mipi_phy_regulator); + if (ret) + goto unlock; + mipi_csis_clk_disable(state); + state->flags &= ~ST_POWERED; + if (!runtime) + state->flags |= ST_SUSPENDED; + } + + unlock: + mutex_unlock(&state->lock); + + return ret ? -EAGAIN : 0; +} + +static int mipi_csis_pm_resume(struct device *dev, bool runtime) +{ + struct platform_device *pdev = to_platform_device(dev); + struct v4l2_subdev *mipi_sd = platform_get_drvdata(pdev); + struct csi_state *state = mipi_sd_to_csis_state(mipi_sd); + int ret = 0; + + mutex_lock(&state->lock); + if (!runtime && !(state->flags & ST_SUSPENDED)) + goto unlock; + + if (!(state->flags & ST_POWERED)) { + ret = regulator_enable(state->mipi_phy_regulator); + if (ret) + goto unlock; + + state->flags |= ST_POWERED; + mipi_csis_clk_enable(state); + } + if (state->flags & ST_STREAMING) + mipi_csis_start_stream(state); + + state->flags &= ~ST_SUSPENDED; + + unlock: + mutex_unlock(&state->lock); + + return ret ? -EAGAIN : 0; +} + +static int mipi_csis_suspend(struct device *dev) +{ + return mipi_csis_pm_suspend(dev, false); +} + +static int mipi_csis_resume(struct device *dev) +{ + return mipi_csis_pm_resume(dev, false); +} + +static int mipi_csis_runtime_suspend(struct device *dev) +{ + return mipi_csis_pm_suspend(dev, true); +} + +static int mipi_csis_runtime_resume(struct device *dev) +{ + return mipi_csis_pm_resume(dev, true); +} + +static int mipi_csis_remove(struct platform_device *pdev) +{ + struct v4l2_subdev *mipi_sd = platform_get_drvdata(pdev); + struct csi_state *state = mipi_sd_to_csis_state(mipi_sd); + + v4l2_async_unregister_subdev(&state->mipi_sd); + v4l2_async_notifier_unregister(&state->subdev_notifier); + + pm_runtime_disable(&pdev->dev); + mipi_csis_pm_suspend(&pdev->dev, true); + mipi_csis_clk_disable(state); + media_entity_cleanup(&state->mipi_sd.entity); + pm_runtime_set_suspended(&pdev->dev); + + return 0; +} + +static const struct dev_pm_ops mipi_csis_pm_ops = { + SET_RUNTIME_PM_OPS(mipi_csis_runtime_suspend, mipi_csis_runtime_resume, + NULL) + SET_SYSTEM_SLEEP_PM_OPS(mipi_csis_suspend, mipi_csis_resume) +}; + +static const struct of_device_id mipi_csis_of_match[] = { + { .compatible = "fsl,imx7-mipi-csi2", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, mipi_csis_of_match); + +static struct platform_driver mipi_csis_driver = { + .probe = mipi_csis_probe, + .remove = mipi_csis_remove, + .driver = { + .of_match_table = mipi_csis_of_match, + .name = CSIS_DRIVER_NAME, + .pm = &mipi_csis_pm_ops, + }, +}; + +module_platform_driver(mipi_csis_driver); + +MODULE_DESCRIPTION("i.MX7 MIPI CSI-2 Receiver driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:imx7-mipi-csi2"); From patchwork Thu Nov 22 15:18:27 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rui Miguel Silva X-Patchwork-Id: 151793 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp877170ljp; Thu, 22 Nov 2018 07:19:08 -0800 (PST) X-Google-Smtp-Source: AJdET5eZKblme989YKRYnNKwgbF6k2H2pq1HG/MK43iTaUk+DKgIlm0hAIWWpSkO3ZMFwEi4oAfQ X-Received: by 2002:a65:4946:: with SMTP id q6mr10156849pgs.201.1542899948866; Thu, 22 Nov 2018 07:19:08 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542899948; cv=none; d=google.com; s=arc-20160816; b=t6nEfUiEIsML1g8+oQa/CL3rYU82KBH0oFScQbJSQfgfdgCDzraprqjKAAUvOsYqma dePHNm72080xxVv/m5q6CzrmR46DJkjOTzPz8/IWE2I2fFY0BV3mw4aYJcmhekRyW1Bx 2gOy5GgpdwtkgMMVEmvNkCu2k6tQeaZ1zyT9uDqrLsXxc7m6JggP0/PeqSnvql3j/aka cJJdeMxsmw7zx+tzIDZTfpsdCx4d8SbBYsolKCiFd5zJP6wdHEirUPSn1lt/BlUeEbM0 hpuC4+rnWISyDc5ae+8xCLVdiJ3353jSFNajaAp2h9wx0jG3RAmiQ3+DtCF9d7sXl1bF DVkg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=FZ8G5yYILthpV8ESgYKvlf+xdTtu3ymno44JQQkzOag=; b=RPO2vXzYQ3Dd0jMqLTkfQpthe2ggUzOF761jfyssefAfPsZWcQWrkLAIxRL3A55tEx l7pddMNyFW0/v+4kIvD5HnD1kTS/ZNQnXwRambSrFc5CJqtIf8ECro7SofGi7uvPPlDH cVcnKFReoIvlDoind+QnbGGInjYFGRX+SrE3ezTJ4bZ3ryh9SXJ8TlJFMlOu1UG3a5FS 16vPvmh5Rox+udcx4eQtboV6o63IqeFj4snEiNQ7oHTNFGeW5RkxGf5ySwhI5mQn+/M6 khcccfWM6dX/GIgVVGy79n4L7jGVFCedf57N4bdu5FSD+RzYfFZzNy2kFMVqgQBb5JMR 2yqA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=GV6eQMQP; spf=pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-media-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h3si27736717pgl.468.2018.11.22.07.19.08; Thu, 22 Nov 2018 07:19:08 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=GV6eQMQP; spf=pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-media-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2437569AbeKWB6z (ORCPT + 4 others); Thu, 22 Nov 2018 20:58:55 -0500 Received: from mail-wm1-f41.google.com ([209.85.128.41]:54196 "EHLO mail-wm1-f41.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2437563AbeKWB6z (ORCPT ); Thu, 22 Nov 2018 20:58:55 -0500 Received: by mail-wm1-f41.google.com with SMTP id y1so6076000wmi.3 for ; Thu, 22 Nov 2018 07:19:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=FZ8G5yYILthpV8ESgYKvlf+xdTtu3ymno44JQQkzOag=; b=GV6eQMQPLJF/1Ejn+JEGtFiwr5J5x2SV7eORszWZSyi4twpOAG4b7sibj3HbUxkhyw C1gs4OctM+wg4XON+BiuQs3ucHQ5IYE0N4mw6LAkdOVYDsmrshBtcXZA3aAgBk0xKFVt RSQmXHHzTORQuIt9U+tZ6yElCDTi5dpYrH/z4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=FZ8G5yYILthpV8ESgYKvlf+xdTtu3ymno44JQQkzOag=; b=UPmznGfW7ZJwratKrRvO0E/pJRmKKQokZTz+JXJBtmw6DDbtdOM9LvZtoubna1FQ1j 5iXe/1YHKSLbC5FwR7l7O37V7bpVg4vZPlj1IKVJULrc4K0NrtwUAom2GdA6rAQHbqOo C349ID5dW41rnEBk6TLaCyWsfmrVvcLU/RztgO5piNmA/ud3wU27QXRmMnwM1BywlDtp T7FQp4K0m+WmUFurYBT+n7DZh24yB0OFkiO42xZaQPr621c6cpVpE7CdnkXqKqCs99tj Xy4OF8w4KzdNAgCP/g8tByTPCLqOgj26EZm8VKgQkAwZG27M7Aw8GCGz4E7mvcugwox/ X69Q== X-Gm-Message-State: AGRZ1gLLpTEiw+44D5Fnrohsac0wYeN81Pi3Q4Guto7PNhFI+xHYsbxo cWI57Pygs776ykonLELxFJvMug== X-Received: by 2002:a1c:9c0a:: with SMTP id f10mr10284999wme.73.1542899946013; Thu, 22 Nov 2018 07:19:06 -0800 (PST) Received: from arch-late.local (a109-49-46-234.cpe.netcabo.pt. [109.49.46.234]) by smtp.gmail.com with ESMTPSA id q7-v6sm4642476wmg.27.2018.11.22.07.19.04 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 22 Nov 2018 07:19:05 -0800 (PST) From: Rui Miguel Silva To: sakari.ailus@linux.intel.com, Steve Longerbeam , Hans Verkuil , Philipp Zabel Cc: linux-media@vger.kernel.org, devel@driverdev.osuosl.org, devicetree@vger.kernel.org, Greg Kroah-Hartman , Rui Miguel Silva Subject: [PATCH v9 06/13] ARM: dts: imx7s: add mipi phy power domain Date: Thu, 22 Nov 2018 15:18:27 +0000 Message-Id: <20181122151834.6194-7-rui.silva@linaro.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181122151834.6194-1-rui.silva@linaro.org> References: <20181122151834.6194-1-rui.silva@linaro.org> MIME-Version: 1.0 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add power domain index 0 related with mipi-phy to imx7s. While at it rename pcie power-domain node to remove pgc prefix. Signed-off-by: Rui Miguel Silva --- arch/arm/boot/dts/imx7s.dtsi | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) -- 2.19.1 diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi index aa8df7d93b2e..6e2e4f99cdb0 100644 --- a/arch/arm/boot/dts/imx7s.dtsi +++ b/arch/arm/boot/dts/imx7s.dtsi @@ -608,7 +608,13 @@ #address-cells = <1>; #size-cells = <0>; - pgc_pcie_phy: pgc-power-domain@1 { + pgc_mipi_phy: power-domain@0 { + #power-domain-cells = <0>; + reg = <0>; + power-supply = <®_1p0d>; + }; + + pgc_pcie_phy: power-domain@1 { #power-domain-cells = <0>; reg = <1>; power-supply = <®_1p0d>; From patchwork Thu Nov 22 15:18:28 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rui Miguel Silva X-Patchwork-Id: 151794 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp877213ljp; Thu, 22 Nov 2018 07:19:11 -0800 (PST) X-Google-Smtp-Source: AJdET5eZ8bBa0OWcM+5BQhnf2Yl3yL3DjdAvg5F9at5BSpv4h7YNx2pcn3tPMprtCT8irUkDS6T4 X-Received: by 2002:a62:704a:: with SMTP id l71-v6mr11821987pfc.68.1542899951412; Thu, 22 Nov 2018 07:19:11 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542899951; cv=none; d=google.com; s=arc-20160816; b=Ua6zSGB8ghfmPUr57H7p5t8ML9C7foLV3XT7Wdp+An6B4AxKcbAx/IcsdW3VVt6Iq0 N87fR9ALtfaZQjvlXE/trKKMFI1nJpbVEJrbybQ0q6runpwvahyCSuRkVAV0tPYTqgUF rNisKShlqFNKU+NDij4yJI7zTQHqc6sUYLOooNzfSXjJ+JKxfd8TVWJnQXIthWQ2xFC/ jBCdtIh3Zji4DASoy+gR+800kA/csaqEPGPGj10dwxleZVqUYpb5FUJ84nny219Xjjy1 VUalMsuJqMk5yVNzeboXL0P5h5bHIuBzndvRoSspwpj7Q75N162gnuGSjuKzZT6eTgbm BexQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=BynIKUh+cU/9TC+FY6oxCg2pfIC9VRpVis3fFJl0OMA=; b=PpY/JjZJR0pMC5KwZYWwoXFOzGzI65mabQcPGYaGeGiu9tUJan4wh73YdY06pcKKKN DU52eg7PJNq5EDueQ3YVp+9LePhqZ/dOXDXc5X68iJD3bhj1nLUWQkfleu7xICK2MxnS YZRXxIsZTnNI4AnxOYBDWxrJ2LlS2Q0mPpDw054wgLh1r5hFUpTUVwWd/XZ8pXCx1LFR yWjPXqqMQGpkHlFZIcOoMJzymFeHSld0yMAKcIZC7SS5vI3whck+mj85Q6B/KcniE7i5 zHeZyj8JJRqaGnjTtp1qNLVZxyhQVeeUBVD0n6vzWv9Y/D/kkSCFcb7PFb7zPztunTVn UGBA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=A3jUKzw9; spf=pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-media-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h3si27736717pgl.468.2018.11.22.07.19.11; Thu, 22 Nov 2018 07:19:11 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=A3jUKzw9; spf=pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-media-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2437572AbeKWB65 (ORCPT + 4 others); Thu, 22 Nov 2018 20:58:57 -0500 Received: from mail-wr1-f68.google.com ([209.85.221.68]:37529 "EHLO mail-wr1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2437563AbeKWB65 (ORCPT ); Thu, 22 Nov 2018 20:58:57 -0500 Received: by mail-wr1-f68.google.com with SMTP id j10so9615707wru.4 for ; Thu, 22 Nov 2018 07:19:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=BynIKUh+cU/9TC+FY6oxCg2pfIC9VRpVis3fFJl0OMA=; b=A3jUKzw93GaNCfaGbIwqyw3Vz7fkjw5iGaL7pHnBFhSfKhoGkm7L5eHxYKv8IokWIS fE07tTm2KYO4K5gTLgSFtJ/JYJp0a8p71D+eD0DdrS0BQLjFrfBkDdMu2vkGgfHWBAP9 6qNGIVwfygz4o3iQwGUKVDzfS6zxyucFRjxa0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=BynIKUh+cU/9TC+FY6oxCg2pfIC9VRpVis3fFJl0OMA=; b=J5CbH1vLPk9pez03LANt9peW4F+hhW4KwKJMujG422jfHv9HQFm2TLYyE13m+m3HuU rwqAfTxWgV+XtxXVrggHHniXPZyb1Bre4lKA3mAMeXYeI+HfgyhYUywh0aZD9Egc1WVM QocRQpy6EV16spMC5y4I6D9RVpLZ9cOHB7oN01hLR2qZhle6MPe+1nGR1JzNJxVuNLNa CGX2Qq6Yf0R9q3UhtKL7zc163zRZcCbC2RFQs6c7uPUIsDdVHpGmXBHXuzUDDgFDSGzY By4BzgsGczE9kqHK6rRIbzIYaw9CxVPxqRulHBIbNfV9o8Pk9nIOJeAcFHExeiqMlz+p gB/A== X-Gm-Message-State: AA+aEWYrPazmFEQO0KGyuyhDg88/+1N83iHCLhUuVa5nhDpaRsVJ3CEl K+K0/swGb65Wv+iuSTTgfRGRpg== X-Received: by 2002:adf:82a8:: with SMTP id 37mr9614832wrc.252.1542899948229; Thu, 22 Nov 2018 07:19:08 -0800 (PST) Received: from arch-late.local (a109-49-46-234.cpe.netcabo.pt. [109.49.46.234]) by smtp.gmail.com with ESMTPSA id q7-v6sm4642476wmg.27.2018.11.22.07.19.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 22 Nov 2018 07:19:07 -0800 (PST) From: Rui Miguel Silva To: sakari.ailus@linux.intel.com, Steve Longerbeam , Hans Verkuil , Philipp Zabel Cc: linux-media@vger.kernel.org, devel@driverdev.osuosl.org, devicetree@vger.kernel.org, Greg Kroah-Hartman , Rui Miguel Silva Subject: [PATCH v9 07/13] ARM: dts: imx7s: add multiplexer controls Date: Thu, 22 Nov 2018 15:18:28 +0000 Message-Id: <20181122151834.6194-8-rui.silva@linaro.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181122151834.6194-1-rui.silva@linaro.org> References: <20181122151834.6194-1-rui.silva@linaro.org> MIME-Version: 1.0 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org The IOMUXC General Purpose Register has bitfield to control video bus multiplexer to control the CSI input between the MIPI-CSI2 and parallel interface. Add that register and mask. Signed-off-by: Rui Miguel Silva Reviewed-by: Philipp Zabel --- arch/arm/boot/dts/imx7s.dtsi | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) -- 2.19.1 diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi index 6e2e4f99cdb0..174635a73fb6 100644 --- a/arch/arm/boot/dts/imx7s.dtsi +++ b/arch/arm/boot/dts/imx7s.dtsi @@ -499,8 +499,15 @@ gpr: iomuxc-gpr@30340000 { compatible = "fsl,imx7d-iomuxc-gpr", - "fsl,imx6q-iomuxc-gpr", "syscon"; + "fsl,imx6q-iomuxc-gpr", "syscon", + "simple-mfd"; reg = <0x30340000 0x10000>; + + mux: mux-controller { + compatible = "mmio-mux"; + #mux-control-cells = <0>; + mux-reg-masks = <0x14 0x00000010>; + }; }; ocotp: ocotp-ctrl@30350000 { From patchwork Thu Nov 22 15:18:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rui Miguel Silva X-Patchwork-Id: 151795 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp877251ljp; Thu, 22 Nov 2018 07:19:13 -0800 (PST) X-Google-Smtp-Source: AFSGD/WyQo1H0kw/TPNe8oRmj9uRGQZ9foFqptJ51Ezm1X4rhaj5k/wKdo5hdwv8Eaj593O1bAzF X-Received: by 2002:a63:396:: with SMTP id 144mr10531902pgd.68.1542899953401; Thu, 22 Nov 2018 07:19:13 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542899953; cv=none; d=google.com; s=arc-20160816; b=COgeGOXDRapJt1r0oSy3Dyk1joZRGvwgDA34OJWUhB6ConAZYEO4UwqveFkfJ8+Oo7 BQPWdYnd4lm/CWtO8uZNQRAjUHirhwR5hD8YnNvhmITpz+G5rvOFpZ+K9RpyBvQ9J1pl FdsSHtXuYnIgGJESXv7nT1WjCr4GIp1eEmTzciEQZy2qDlok27sf0xLA8cmZN9NcW20A rZYyusyJLSF3PPX3WWo8bQ/K60/Jap/3GPvwjbJOSB/WpIuQxjwAj3UKg+QqOPEXdLpC gT3R/BmFBRBVSyLBW06BuY9JOAE9WbGmSaq3ooKLe3Rr28l7tlGMBinZlWj9jCpOmkFN +gPg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=mkaMa4XsIgCXPrhbga8BMHpGLrERSv4s9EuPQM6xBFA=; b=CsLTqFzKNyZ6qcKyYXKOLtWbk9pYaUPiyahGFDbOiFrx6S0xqXjK9QSB8IN/RWH5GA GkX7iEKFgHpJOBmEGKefhEWulzLPhQkpQedK69GK98kHIk0IHZ6iBQZ/ZZJFQ8OdekRd UvqK00zjRXMn2jMT8Lrf2HM5ePKHy1dMWMI8Z42q7RORBu0byDTXj7DT9hRoP1AxQpw9 SPaGYoxPqRSLgofRqCaZl87UXngIsbHyujv5eXN8nziHLXZ6IwW489GWcRL/Stm6Yx47 Oym5eoFT2bn2WkMPOslxT/ZauTRB5p+bGJMfXY2Zm9pFWS6q2wl6JRGw8jwVqnFyvYce aAtg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="EPt/fvb1"; spf=pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-media-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h3si27736717pgl.468.2018.11.22.07.19.13; Thu, 22 Nov 2018 07:19:13 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="EPt/fvb1"; spf=pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-media-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2437575AbeKWB67 (ORCPT + 4 others); Thu, 22 Nov 2018 20:58:59 -0500 Received: from mail-wm1-f66.google.com ([209.85.128.66]:55907 "EHLO mail-wm1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2437573AbeKWB67 (ORCPT ); Thu, 22 Nov 2018 20:58:59 -0500 Received: by mail-wm1-f66.google.com with SMTP id y139so9262290wmc.5 for ; Thu, 22 Nov 2018 07:19:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=mkaMa4XsIgCXPrhbga8BMHpGLrERSv4s9EuPQM6xBFA=; b=EPt/fvb1tq9QWnE8OMHjKxPcoF8yb53jDjhvP78b4HjJMFENvB7Bqiwv8uyerkhbdl 0jTwp6bWvpJQ/4/3ZH5IDJqcb59mTjsxzizbIUMiMw70mvyHU6JRCohElpvS7LLKsNFv 2u3GtRbmzJKZWrF6ZkDqg32ZzIXr3vyjQPslI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=mkaMa4XsIgCXPrhbga8BMHpGLrERSv4s9EuPQM6xBFA=; b=TQNBP9JOo2O3En5BNZlMH1yQd05QoNdSceXAPC3NKBp27suN09LeLsrQvuPECPE9Xc hcdPStlymD4irTwoYJCkCisQk2Db1Vfbj5eMr8Q+QmG3Oi5L/2rVsMTCsBKHgP6uIIt0 iqttsfB/ccru6bE/OFlD7rv3Ps2OmqEJtXR6zJ+1uFDIe8CkTddhwCoS4fHP1cXKvNIA 6YV+n7MgNwReFbT0vO6O7dbnwJB1MKgUpbieAavhoVipAWwpPQ3bG98Ra7FKFoQE2H06 hJAazvufv3073UVlfqvnRI31M5H1rmBmlL2bVqVcRrEG36Xidyu4kj8RX2Nh79HdkjSJ YfXw== X-Gm-Message-State: AGRZ1gIRa2JIfnCXFGibKSdJGd4WfqblbFRPZLUn81LgnIZKCfc4/Wt0 ++KjxT96q88E8M2x8W5F+KYY7Q== X-Received: by 2002:a1c:6e09:: with SMTP id j9mr10510180wmc.105.1542899950406; Thu, 22 Nov 2018 07:19:10 -0800 (PST) Received: from arch-late.local (a109-49-46-234.cpe.netcabo.pt. [109.49.46.234]) by smtp.gmail.com with ESMTPSA id q7-v6sm4642476wmg.27.2018.11.22.07.19.09 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 22 Nov 2018 07:19:10 -0800 (PST) From: Rui Miguel Silva To: sakari.ailus@linux.intel.com, Steve Longerbeam , Hans Verkuil , Philipp Zabel Cc: linux-media@vger.kernel.org, devel@driverdev.osuosl.org, devicetree@vger.kernel.org, Greg Kroah-Hartman , Rui Miguel Silva Subject: [PATCH v9 08/13] ARM: dts: imx7: Add video mux, csi and mipi_csi and connections Date: Thu, 22 Nov 2018 15:18:29 +0000 Message-Id: <20181122151834.6194-9-rui.silva@linaro.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181122151834.6194-1-rui.silva@linaro.org> References: <20181122151834.6194-1-rui.silva@linaro.org> MIME-Version: 1.0 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org This patch adds the device tree nodes for csi, video multiplexer and mipi-csi besides the graph connecting the necessary endpoints to make the media capture entities to work in imx7 Warp board. Signed-off-by: Rui Miguel Silva --- arch/arm/boot/dts/imx7s-warp.dts | 51 ++++++++++++++++++++++++++++++++ arch/arm/boot/dts/imx7s.dtsi | 27 +++++++++++++++++ 2 files changed, 78 insertions(+) -- 2.19.1 diff --git a/arch/arm/boot/dts/imx7s-warp.dts b/arch/arm/boot/dts/imx7s-warp.dts index f7ba2c0a24ad..757856a3964b 100644 --- a/arch/arm/boot/dts/imx7s-warp.dts +++ b/arch/arm/boot/dts/imx7s-warp.dts @@ -276,6 +276,57 @@ status = "okay"; }; +&gpr { + csi_mux { + compatible = "video-mux"; + mux-controls = <&mux 0>; + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + csi_mux_from_mipi_vc0: endpoint { + remote-endpoint = <&mipi_vc0_to_csi_mux>; + }; + }; + + port@2 { + reg = <2>; + + csi_mux_to_csi: endpoint { + remote-endpoint = <&csi_from_csi_mux>; + }; + }; + }; +}; + +&csi { + status = "okay"; + + port { + csi_from_csi_mux: endpoint { + remote-endpoint = <&csi_mux_to_csi>; + }; + }; +}; + +&mipi_csi { + clock-frequency = <166000000>; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + fsl,csis-hs-settle = <3>; + + port@1 { + reg = <1>; + + mipi_vc0_to_csi_mux: endpoint { + remote-endpoint = <&csi_mux_from_mipi_vc0>; + }; + }; +}; + &wdog1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_wdog>; diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi index 174635a73fb6..0c495082e2bf 100644 --- a/arch/arm/boot/dts/imx7s.dtsi +++ b/arch/arm/boot/dts/imx7s.dtsi @@ -8,6 +8,7 @@ #include #include #include +#include #include "imx7d-pinfunc.h" / { @@ -711,6 +712,17 @@ status = "disabled"; }; + csi: csi@30710000 { + compatible = "fsl,imx7-csi"; + reg = <0x30710000 0x10000>; + interrupts = ; + clocks = <&clks IMX7D_CLK_DUMMY>, + <&clks IMX7D_CSI_MCLK_ROOT_CLK>, + <&clks IMX7D_CLK_DUMMY>; + clock-names = "axi", "mclk", "dcic"; + status = "disabled"; + }; + lcdif: lcdif@30730000 { compatible = "fsl,imx7d-lcdif", "fsl,imx28-lcdif"; reg = <0x30730000 0x10000>; @@ -720,6 +732,21 @@ clock-names = "pix", "axi"; status = "disabled"; }; + + mipi_csi: mipi-csi@30750000 { + compatible = "fsl,imx7-mipi-csi2"; + reg = <0x30750000 0x10000>; + interrupts = ; + clocks = <&clks IMX7D_IPG_ROOT_CLK>, + <&clks IMX7D_MIPI_CSI_ROOT_CLK>, + <&clks IMX7D_MIPI_DPHY_ROOT_CLK>; + clock-names = "pclk", "wrap", "phy"; + power-domains = <&pgc_mipi_phy>; + phy-supply = <®_1p0d>; + resets = <&src IMX7_RESET_MIPI_PHY_MRST>; + reset-names = "mrst"; + status = "disabled"; + }; }; aips3: aips-bus@30800000 { From patchwork Thu Nov 22 15:18:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rui Miguel Silva X-Patchwork-Id: 151796 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp877299ljp; Thu, 22 Nov 2018 07:19:15 -0800 (PST) X-Google-Smtp-Source: AFSGD/UL27B4org1MFAKBUyBGlYp8nJsJ2SL7g2+OyqtjAtgIaUhh19n60GE9xr5L9u0OSA+cdNc X-Received: by 2002:a63:a84a:: with SMTP id i10mr10625002pgp.263.1542899955645; Thu, 22 Nov 2018 07:19:15 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542899955; cv=none; d=google.com; s=arc-20160816; b=dakgDJC/Gu9qKyLZZouX2oov/OKxnQida3crPExJmdLa7I55J7QF22Sy8OkNPkV8rc 4PJVEm6qaL5H7qhI2RDLBw4yQ1HXqODdqkGWAhBF3HeOlcIwNv9NA5nYg0mhZV5bDpa8 /P7+V7FsvmsXAgrYlz9t4kpse+I2S7g/HnCKCBW/BNUF7RTd13pp3BVW5VPwvXodafhF vQE4U1XYbW4e1D56E4SrEHmuM0GVVODeAvFhFYpSSuAV7MxzaC875ij/4S6IPBy81RxO oE+Y0YAwRckZtO/8zzEeMT/x6m/hRxhEFJj7+GMlroYHezuzb1PiyVPMhpFvL8Foq+z0 Kv9g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=75uIXLgjHMqHSaLVtS+l1jKHfW+/RhI5naRHtAooAd4=; b=un5gQCS9Lyu3/RGCDwSx3h++swj4aUJ7gK+GsiEznRx0qunRdeb8he1I0gvOYq+fxq /Ysad4Y8Ms/sJnFjSOdUNqx+QI5Js1zFah4QZpTf6CLzVa0OUg8bC2o8zG17GMtBILi3 1+Pj0S/sK3i9LPWbns5FyOP3F8v4eqZYJkrpLLrvMKKdAeWeb5UjkWoB3jPEEdZo0Rtb jNjR29i1AwaS4kqC0LFJTHlDi4YpPProId0Sp57Ecyp+vmF+drFsEmp2lXdtmJinP2yJ JoFgMIKDoz+/aVdA6KVBsyrBSbSmHL4CIsO8+qdjVG2RHAB4us4b7th3KYhpM0/drQVS J6Ow== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=cAcLMH0f; spf=pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-media-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h3si27736717pgl.468.2018.11.22.07.19.15; Thu, 22 Nov 2018 07:19:15 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=cAcLMH0f; spf=pass (google.com: best guess record for domain of linux-media-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-media-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2437578AbeKWB7C (ORCPT + 4 others); Thu, 22 Nov 2018 20:59:02 -0500 Received: from mail-wm1-f65.google.com ([209.85.128.65]:52953 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2437573AbeKWB7B (ORCPT ); Thu, 22 Nov 2018 20:59:01 -0500 Received: by mail-wm1-f65.google.com with SMTP id r11-v6so9290377wmb.2 for ; Thu, 22 Nov 2018 07:19:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=75uIXLgjHMqHSaLVtS+l1jKHfW+/RhI5naRHtAooAd4=; b=cAcLMH0fyt52Od+JVFJ1W1dR3/jEW6CWGSdlvgrdRECjgInP0a67+wzYOp2KxVXaYH 0b5oBo9zQfwcn0eUio2/YZhisQdkRFPCjO2sTDGP3mydLbzEQGL6eGVj+64C22xUBfOx PbaYAX9W5gqH3XFt0KG6QVJBo7MGerTXUJbRc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=75uIXLgjHMqHSaLVtS+l1jKHfW+/RhI5naRHtAooAd4=; b=tm3V/SK3srLPQq6WyN5SJqSMHb3aso4wpubPk/05w/BMuDtiesZ8jk8Q/PB8v2FhBY bk+1TxGmjCoXb8xa34zlpq5IDzqUL3UfijZvGcC1+eVoEQU4a7EbvTvO7Y6E667Msbq+ FPNk/HwlkW1bgLk+Uu/B6cFmef94x2z/zujvFqVqzg2fzfDs+8gB5NPw62ag9EP7tO+J 1PQeVwd5i16W9Iq2y0L7OqzNv1s6QbUcMJoOfvyZ0z/m1ScAzzTU0YRMgolNN1xR7gHc 9AsrKcWV8m2R65AyLCQzfdveqKxiOPlpvKmeidjtKLiVrj+q7zRR3qRxGsRucsW8jXx5 is4w== X-Gm-Message-State: AA+aEWYYfbOStnKrg/OdboJWTz66r2JBiusz+A7A8FgMXed/NeXu7LA0 SRipkERyRjGEix1yd9/XTlzOow== X-Received: by 2002:a1c:ac05:: with SMTP id v5-v6mr10793011wme.144.1542899952472; Thu, 22 Nov 2018 07:19:12 -0800 (PST) Received: from arch-late.local (a109-49-46-234.cpe.netcabo.pt. [109.49.46.234]) by smtp.gmail.com with ESMTPSA id q7-v6sm4642476wmg.27.2018.11.22.07.19.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 22 Nov 2018 07:19:12 -0800 (PST) From: Rui Miguel Silva To: sakari.ailus@linux.intel.com, Steve Longerbeam , Hans Verkuil , Philipp Zabel Cc: linux-media@vger.kernel.org, devel@driverdev.osuosl.org, devicetree@vger.kernel.org, Greg Kroah-Hartman , Rui Miguel Silva Subject: [PATCH v9 09/13] ARM: dts: imx7s-warp: add ov2680 sensor node Date: Thu, 22 Nov 2018 15:18:30 +0000 Message-Id: <20181122151834.6194-10-rui.silva@linaro.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181122151834.6194-1-rui.silva@linaro.org> References: <20181122151834.6194-1-rui.silva@linaro.org> MIME-Version: 1.0 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Warp7 comes with a Omnivision OV2680 sensor, add the node here to make complete the camera data path for this system. Add the needed regulator to the analog voltage supply, the port and endpoints in mipi_csi node and the pinctrl for the reset gpio. Signed-off-by: Rui Miguel Silva --- arch/arm/boot/dts/imx7s-warp.dts | 44 ++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) -- 2.19.1 diff --git a/arch/arm/boot/dts/imx7s-warp.dts b/arch/arm/boot/dts/imx7s-warp.dts index 757856a3964b..4ada85850411 100644 --- a/arch/arm/boot/dts/imx7s-warp.dts +++ b/arch/arm/boot/dts/imx7s-warp.dts @@ -54,6 +54,14 @@ regulator-always-on; }; + reg_peri_3p15v: regulator-peri-3p15v { + compatible = "regulator-fixed"; + regulator-name = "peri_3p15v_reg"; + regulator-min-microvolt = <3150000>; + regulator-max-microvolt = <3150000>; + regulator-always-on; + }; + sound { compatible = "simple-audio-card"; simple-audio-card,name = "imx7-sgtl5000"; @@ -177,6 +185,27 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c2>; status = "okay"; + + ov2680: camera@36 { + compatible = "ovti,ov2680"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ov2680>; + reg = <0x36>; + clocks = <&osc>; + clock-names = "xvclk"; + reset-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>; + DOVDD-supply = <&sw2_reg>; + DVDD-supply = <&sw2_reg>; + AVDD-supply = <®_peri_3p15v>; + + port { + ov2680_to_mipi: endpoint { + remote-endpoint = <&mipi_from_sensor>; + clock-lanes = <0>; + data-lanes = <1>; + }; + }; + }; }; &i2c3 { @@ -318,6 +347,15 @@ #size-cells = <0>; fsl,csis-hs-settle = <3>; + port@0 { + reg = <0>; + + mipi_from_sensor: endpoint { + remote-endpoint = <&ov2680_to_mipi>; + data-lanes = <1>; + }; + }; + port@1 { reg = <1>; @@ -381,6 +419,12 @@ >; }; + pinctrl_ov2680: ov2660grp { + fsl,pins = < + MX7D_PAD_LPSR_GPIO1_IO03__GPIO1_IO3 0x14 + >; + }; + pinctrl_sai1: sai1grp { fsl,pins = < MX7D_PAD_SAI1_RX_DATA__SAI1_RX_DATA0 0x1f