From patchwork Wed Nov 21 11:15:50 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: 151661 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp1790153ljp; Wed, 21 Nov 2018 03:16:38 -0800 (PST) X-Google-Smtp-Source: AJdET5ctSzFRuGESTLfIn9pATLXlEmarAlGHziZF3bgzlhmnoJ1KkiVV7RqzA+qv3ZBUmYF8RgYi X-Received: by 2002:a62:3241:: with SMTP id y62-v6mr6431263pfy.218.1542798998755; Wed, 21 Nov 2018 03:16:38 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542798998; cv=none; d=google.com; s=arc-20160816; b=S/Qou5C3tIELegjCYWjwTo7ZbRttd+BajmfmuCGrnL/IhNjMH81pTN8+BbxTm1q+5S FbqMuBnVqJfRHGyaYdDHFH/1e/f4jqutvBHeCMl9ZD4Ue8CXRay5qw/v1ybf0ucDmtKn cjuxPwuY2ZxnahOarUhC1cY+QizQSE+fwL2+8sG/niw6M4V33b9vR6b1NAHBplv3gt7e EAnO+iqYTStPK4KSH7bdm4cHyacvac9laLdamPoMSYT6YKJYgwn7UfWp7ms8xhMSeOsC PC2RqpPBlkajboUTdbFaezUpKFiKzUi3gU6Vfl8vEhrArNcQDTAdq0s3c+WS7lccU9pr bZ7g== 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=+0T+af+gL7o3UEAnmuWem0Gch3XofOL5cmle2io2CJ4=; b=hA8ehEgxMlJh1mLOiSNG/1is8lk2/7QAG+FcH0Qq3mELGGskB7gDWG4zl3oAvJBMMN 7LycPWLyK+GN0O7jUecOj22KoT/uXuX0zKw1ZmgoZuYa7rU100XOSmSZc/E7cNUqpu1o IxBjUdZUmQwmc7sgs6erDbtt1iMK8+50H9LBzJoQVc44Jf9dlZmMsgY4H3AFAs+RikLa 8JkKq0GiO0P1wgF6eM/JzOa1Bs/StO1OwdEf9l/meyhei5peVukzhKHU0jSdo0244+FX anqS810IGPkZ+znplF3HV84wFEAWruyh1ZYyBDOqpqrsx1g7czN71kZAvKoTQoHthe9w H4kA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=NRFnoN00; 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 n3si9574252pfn.285.2018.11.21.03.16.38; Wed, 21 Nov 2018 03:16:38 -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=NRFnoN00; 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 S1730040AbeKUVug (ORCPT + 4 others); Wed, 21 Nov 2018 16:50:36 -0500 Received: from mail-wr1-f68.google.com ([209.85.221.68]:38168 "EHLO mail-wr1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730016AbeKUVug (ORCPT ); Wed, 21 Nov 2018 16:50:36 -0500 Received: by mail-wr1-f68.google.com with SMTP id v13so1778980wrw.5 for ; Wed, 21 Nov 2018 03:16:34 -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=+0T+af+gL7o3UEAnmuWem0Gch3XofOL5cmle2io2CJ4=; b=NRFnoN00zxIOv37weqEE/kFIHbrng90wP2/17J9esy+L73rLec1i6f4XTX9jPJSvR0 9IL0WHAIMWJm7wNzQ59pyPwaP7qJs9evlu7/6cHI9IPlfn9AtlUvw1a8zAHrQ6HkanJB QCmcHA6yrWq+mOyvahRqECs1Ns+tpFQHcoYYw= 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=+0T+af+gL7o3UEAnmuWem0Gch3XofOL5cmle2io2CJ4=; b=Y78VNyYpDWcKjxM7s7xLsE8xvYsHqCZAfcZgwMxmS/hfcccgkK2oUcrue6I1+FFSQc Ug9KSfB7iloyCc+LzZqVdwNymNCqEP9tKeaGZNHMO8u007dmMYHOpow6Jr46cZ5Lv+9E aP2e98Ize/wUU0X+jU2cfndGLmeiuRZmmqqNimYY2HO4vhyeyxCIZe/t2bO/L1nkbEzn wqrxW2Yo+63y1JvreI3ROl+JHW307bkk1jmc33XiJRyXprQ35QQevOYqUnX+lNF1olro egfpdTOFaDXWx+mzCHdRk7Ws6zRHjgJ449wABws4+dthJMr7c1NKEOLQJQ0fQoLDWezg KNhA== X-Gm-Message-State: AA+aEWaarH3eoDgvHk+U/4IlD6tH+FnE6XV6/jHQpxrBSe/o+L3jSEzD 0Gwl2pWJmKko4bjXzzuX4lAT0ATBAPU= X-Received: by 2002:a5d:694d:: with SMTP id r13mr5212458wrw.323.1542798993394; Wed, 21 Nov 2018 03:16:33 -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 a125-v6sm771526wmf.8.2018.11.21.03.16.32 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 21 Nov 2018 03:16:32 -0800 (PST) From: Rui Miguel Silva To: sakari.ailus@linux.intel.com, Philipp Zabel Cc: linux-media@vger.kernel.org, devel@driverdev.osuosl.org, devicetree@vger.kernel.org, Greg Kroah-Hartman , Rui Miguel Silva Subject: [PATCH v8 04/12] media: staging/imx7: add MIPI CSI-2 receiver subdev for i.MX7 Date: Wed, 21 Nov 2018 11:15:50 +0000 Message-Id: <20181121111558.10838-5-rui.silva@linaro.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181121111558.10838-1-rui.silva@linaro.org> References: <20181121111558.10838-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 | 1134 ++++++++++++++++++++ 2 files changed, 1135 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..39bf0657557e --- /dev/null +++ b/drivers/staging/media/imx/imx7-mipi-csis.c @@ -0,0 +1,1134 @@ +// 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 { + struct mutex lock; + 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, + .owner = THIS_MODULE, + .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 Wed Nov 21 11:15:51 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: 151660 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp1790166ljp; Wed, 21 Nov 2018 03:16:39 -0800 (PST) X-Google-Smtp-Source: AFSGD/Wb4gKLThlPMXA4AzF/WdVYwzqw/5sx7A3D9X+xVv10Ht0kB9/LkMKpcMiJvelH49kTczcX X-Received: by 2002:a63:b94c:: with SMTP id v12mr5533525pgo.221.1542798999458; Wed, 21 Nov 2018 03:16:39 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542798999; cv=none; d=google.com; s=arc-20160816; b=bfwkCLHmYu5IuCHClbIiDqHhz8PEAiXFJNW5XPnzylp/sLOKEEE4gfwLivBAkbxq1x x5EXIcm+LogBNknt43sHePPjb/93QCfRF02dlnxSw+dtsx+TVprJaKv+XdimOwMW1pxi hEqTBTMvyAkM39RapDmfaP4/Ji7PJBKUL+qqEv/KbZqThXiPJpSN/fkS3+O16247Bjsh Djlo7mqO193loBsaQbntWhtWpRToeeiewKGdzJYhq5DOtN94kOOkJopEKhjzLpylPd+v G7wWWzQ7vZtYc5KftjcTgYN9WHBSig0nWw1iHlpCnmDM/u8sdoGutU/mYqDCejuswAaa XTNQ== 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=O/lqWEOmJGaOH6tQ9BihzsFfBg0BfEe6nbbb5s6cf1s=; b=aaskBW/aTxeYUI24I1iOpbFmHnmTbFjFijM/GwlsHgpRjIgJtQym981bwrFur0raNC D7ro2hrpXC+vm0d7HEKigIJ5hIrm3mYjRanTGqb1HcX3YUt/aTIiF+EijdtaMT18D0IJ I7yJf5EI8XeZEPRAUUhWJ1+Ty0cZ4AcQbApj+wK23kqdcrGwXrzSyqzk0rXCs1/bzPTB Byj3sPNkia/yrwx9NyWzfh4nEFkR5WUHB6fVfH/jWISS03zgQ5z7421Zx0LHN+u4aF6W wsqptCr3dxe9+B/el1tTPp5tbVgF+pznSMQyJ5pWPQ+BDYQYkfurjzNxNpccvxbO0Q8T yjOQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=FII3XqAL; 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 n3si9574252pfn.285.2018.11.21.03.16.39; Wed, 21 Nov 2018 03:16:39 -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=FII3XqAL; 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 S1730044AbeKUVug (ORCPT + 4 others); Wed, 21 Nov 2018 16:50:36 -0500 Received: from mail-wm1-f65.google.com ([209.85.128.65]:37711 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730035AbeKUVug (ORCPT ); Wed, 21 Nov 2018 16:50:36 -0500 Received: by mail-wm1-f65.google.com with SMTP id p2-v6so5323586wmc.2 for ; Wed, 21 Nov 2018 03:16:35 -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=O/lqWEOmJGaOH6tQ9BihzsFfBg0BfEe6nbbb5s6cf1s=; b=FII3XqAL+f5GjiIhTJPvxpZI7acnfih0HcOx+3xZFZwA8YkvLl3ySRmVzQ3+how//7 1fXHh3CQpEsXuaSroBAjwH2rebnHPUjbINGIYGa4MJ2Vzj6T3HsUFAz0GjFSftynsB14 Hkhw6VtW4JC2UZm0aFCDaqp4l6OaWv01ZqPXM= 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=O/lqWEOmJGaOH6tQ9BihzsFfBg0BfEe6nbbb5s6cf1s=; b=FfDKSM4/qIAaeyCTVvyAlHydLLnIcB0wQnE2CPcMxKOkxbOk/XW9igg4iwgxMh9IbH UDQRExllFw6Kf0WPDE+kyPFPSXI2RiZioupfSHW8iRebPzrrqed0XcpL16cTjdZNzwOl P9YpbMq8DMzLObujRmccduwoctI7QYOI/HXCUHeoEuFHeLJw1Dc9avITF4annWoEqADF UhL7LYFIG4N7MzYr2JTlgUMc7vuGoVIF3+sUj7n+M+faQWYH4o6WrctRpsjYcG+/mJFY VLhZMVO/fDbBCykI6W8LEtPjgrlHOW3gmhtGnPVj74zcbgv87EE2Wqx5+ecw+LKkxMvU LL6g== X-Gm-Message-State: AA+aEWaD2KtiUI/fZde7wkjMjNtm9CbI9EQrKP7X6ki8I7MNlBek41XV 6CssyCFos1jfTsF1PJdeLmg7Yg== X-Received: by 2002:a1c:2104:: with SMTP id h4-v6mr5092434wmh.130.1542798995220; Wed, 21 Nov 2018 03:16:35 -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 a125-v6sm771526wmf.8.2018.11.21.03.16.34 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 21 Nov 2018 03:16:34 -0800 (PST) From: Rui Miguel Silva To: sakari.ailus@linux.intel.com, Philipp Zabel Cc: linux-media@vger.kernel.org, devel@driverdev.osuosl.org, devicetree@vger.kernel.org, Greg Kroah-Hartman , Rui Miguel Silva Subject: [PATCH v8 05/12] media: dt-bindings: add bindings for i.MX7 media driver Date: Wed, 21 Nov 2018 11:15:51 +0000 Message-Id: <20181121111558.10838-6-rui.silva@linaro.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181121111558.10838-1-rui.silva@linaro.org> References: <20181121111558.10838-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 bindings documentation for i.MX7 media drivers. The imx7 MIPI CSI2 and imx7 CMOS Sensor Interface. Signed-off-by: Rui Miguel Silva Reviewed-by: Rob Herring Acked-by: Sakari Ailus --- .../devicetree/bindings/media/imx7-csi.txt | 45 ++++++++++ .../bindings/media/imx7-mipi-csi2.txt | 90 +++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/imx7-csi.txt create mode 100644 Documentation/devicetree/bindings/media/imx7-mipi-csi2.txt -- 2.19.1 diff --git a/Documentation/devicetree/bindings/media/imx7-csi.txt b/Documentation/devicetree/bindings/media/imx7-csi.txt new file mode 100644 index 000000000000..171b089ee91f --- /dev/null +++ b/Documentation/devicetree/bindings/media/imx7-csi.txt @@ -0,0 +1,45 @@ +Freescale i.MX7 CMOS Sensor Interface +===================================== + +csi node +-------- + +This is device node for the CMOS Sensor Interface (CSI) which enables the chip +to connect directly to external CMOS image sensors. + +Required properties: + +- compatible : "fsl,imx7-csi"; +- reg : base address and length of the register set for the device; +- interrupts : should contain CSI interrupt; +- clocks : list of clock specifiers, see + Documentation/devicetree/bindings/clock/clock-bindings.txt for details; +- clock-names : must contain "axi", "mclk" and "dcic" entries, matching + entries in the clock property; + +The device node shall contain one 'port' child node with one child 'endpoint' +node, according to the bindings defined in: + Documentation/devicetree/bindings/media/video-interfaces.txt. + +In the following example a remote endpoint is a video multiplexer. + +example: + + csi: csi@30710000 { + #address-cells = <1>; + #size-cells = <0>; + + 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"; + + port { + csi_from_csi_mux: endpoint { + remote-endpoint = <&csi_mux_to_csi>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/media/imx7-mipi-csi2.txt b/Documentation/devicetree/bindings/media/imx7-mipi-csi2.txt new file mode 100644 index 000000000000..71fd74ed3ec8 --- /dev/null +++ b/Documentation/devicetree/bindings/media/imx7-mipi-csi2.txt @@ -0,0 +1,90 @@ +Freescale i.MX7 Mipi CSI2 +========================= + +mipi_csi2 node +-------------- + +This is the device node for the MIPI CSI-2 receiver core in i.MX7 SoC. It is +compatible with previous version of Samsung D-phy. + +Required properties: + +- compatible : "fsl,imx7-mipi-csi2"; +- reg : base address and length of the register set for the device; +- interrupts : should contain MIPI CSIS interrupt; +- clocks : list of clock specifiers, see + Documentation/devicetree/bindings/clock/clock-bindings.txt for details; +- clock-names : must contain "pclk", "wrap" and "phy" entries, matching + entries in the clock property; +- power-domains : a phandle to the power domain, see + Documentation/devicetree/bindings/power/power_domain.txt for details. +- reset-names : should include following entry "mrst"; +- resets : a list of phandle, should contain reset entry of + reset-names; +- phy-supply : from the generic phy bindings, a phandle to a regulator that + provides power to MIPI CSIS core; + +Optional properties: + +- clock-frequency : The IP's main (system bus) clock frequency in Hz, default + value when this property is not specified is 166 MHz; +- fsl,csis-hs-settle : differential receiver (HS-RX) settle time; + +The device node should contain two 'port' child nodes with one child 'endpoint' +node, according to the bindings defined in: + Documentation/devicetree/bindings/ media/video-interfaces.txt. + The following are properties specific to those nodes. + +port node +--------- + +- reg : (required) can take the values 0 or 1, where 0 shall be + related to the sink port and port 1 shall be the source + one; + +endpoint node +------------- + +- data-lanes : (required) an array specifying active physical MIPI-CSI2 + data input lanes and their mapping to logical lanes; this + shall only be applied to port 0 (sink port), the array's + content is unused only its length is meaningful, + in this case the maximum length supported is 2; + +example: + + mipi_csi: mipi-csi@30750000 { + #address-cells = <1>; + #size-cells = <0>; + + 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"; + clock-frequency = <166000000>; + power-domains = <&pgc_mipi_phy>; + phy-supply = <®_1p0d>; + resets = <&src IMX7_RESET_MIPI_PHY_MRST>; + reset-names = "mrst"; + 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>; + + mipi_vc0_to_csi_mux: endpoint { + remote-endpoint = <&csi_mux_from_mipi_vc0>; + }; + }; + }; From patchwork Wed Nov 21 11:15:55 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: 151665 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp1790280ljp; Wed, 21 Nov 2018 03:16:45 -0800 (PST) X-Google-Smtp-Source: AJdET5ezv94ksoH2S7DJdr7FcTcXoRXLh+QSeFdJPoQBhyU3ceMCWm0cnpp29/+ck8+M/tGVZeLf X-Received: by 2002:a62:5504:: with SMTP id j4-v6mr6390293pfb.166.1542799005811; Wed, 21 Nov 2018 03:16:45 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542799005; cv=none; d=google.com; s=arc-20160816; b=uBjJPi1JZrLF6Av1vpX0LBBMw2QG06qnQutfjZhP7rzTyBAUf6KGWP7ZLZLBTZv26s GPFUsHggBZB/uJDqPWcDnfibfCZ/+2UcUpkySw4yw8rUp8PHAbP3au3XDH7yHFL7pUxB CRLhuSM0W/CkICCGolHCbDJmncJg5pNaGVoBb9YxDEx0kODGdLcaNlpQVqbm6Oxa4cgc A29fgWKqbHnZB62Gl1AMisHgOSB3ZRul6uTPx6Itjdgg1aZaTPYxm7wfSLhJTjXcJWXh E7j/zhQO/sjqZy3txM78RYXStXDUrMTMV+0pRCajuqTB7mGRcWVhMrO7HuuS3MH0EhDT 5OqA== 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=hwILDOZ2K8BoWjQk+MB5dbRSXpF5/BEpNZgvyLxuSP4=; b=zX2DY+aXPKuv4I2aSfxFxh1Aa/kxzdzYDslFqa96uRiT3aTV8mMdGuJaeEU2qzUlVK jooA7I8dtyWdRF8ZNMTLjtLYM7PdO4GTyhctHfcFPaEaksN2XoNwjuIcUjKTcBERaT7F w6F8+GAqUWqIvfP3zh8Xz7bZCqb9HODLV9ofgvnomGkIEbHoabukSiifciWS94jdV+ZV +xVnSTQrJVtKDK6G8oDznwGJcAMrMdgK0l9iIqVNvjf1i8fFNxUhqlTVm0jyZS59oMbl YBlV/KyFFja5wQb1rnB44No7RA1Y4vpfYPkAOagE56jSkJd06rP6IJv4a6+12gECe5Nd rM+g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=YYStklGi; 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 n3si9574252pfn.285.2018.11.21.03.16.45; Wed, 21 Nov 2018 03:16:45 -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=YYStklGi; 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 S1730074AbeKUVuo (ORCPT + 4 others); Wed, 21 Nov 2018 16:50:44 -0500 Received: from mail-wm1-f68.google.com ([209.85.128.68]:39840 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730058AbeKUVun (ORCPT ); Wed, 21 Nov 2018 16:50:43 -0500 Received: by mail-wm1-f68.google.com with SMTP id u13-v6so5352000wmc.4 for ; Wed, 21 Nov 2018 03:16:43 -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=hwILDOZ2K8BoWjQk+MB5dbRSXpF5/BEpNZgvyLxuSP4=; b=YYStklGiU1jlb0siLRuH0qKjvY2c5GmA5339CwBsGT8HjjkFBclekq44/OOK6Or5Hz FIuNYVD1KaC9mCgvJNNw8AYG2mwjm0rVGVEKDTQz9uHKLeXdegbcdNxdKF7BACq0U1JP SePL49O5DgMaYGLvuG/z/pc9U0qap2k4WCrf0= 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=hwILDOZ2K8BoWjQk+MB5dbRSXpF5/BEpNZgvyLxuSP4=; b=PZD46oN3J81WxHco80iPt0gW2qgEPVh3UZDzhzLVTPd5WcGNGMG8gMQp7QqM/z7aRt kU6347GzOUfCHXc1uIp+Pj80Nol7wyFgWBW0RSn8XQpXBN+zxXETReyCnCJOvo+6zkKY Yzj7DHT6jAcxcPUrOos7UmH9ZCiZMr69LdfR7jOqhMyuhm5kiHJxNNMI67dqw7BnXXuR D6fwdur6Ip0aqGig7MsAve7t4bQ0vdvJiFlj4YlBccVzCzHgHUsukDIStjmUDNI6Lij/ zO8D0crOcW2yZFx8WWwd0/mnMN6SNTs6QjB6r0Lf8rtO3gFVBMYZjZ3P7XHFuvegyZLh AdSA== X-Gm-Message-State: AGRZ1gKQq6wj1pZaoN1FIS2gdiC3Uxxo6uTQ2mDz4DkFONVAneLlw4DP lDgGUzNVq/4mpTUesLDOI6JrMg== X-Received: by 2002:a7b:c397:: with SMTP id s23mr5204981wmj.127.1542799002573; Wed, 21 Nov 2018 03:16:42 -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 a125-v6sm771526wmf.8.2018.11.21.03.16.41 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 21 Nov 2018 03:16:42 -0800 (PST) From: Rui Miguel Silva To: sakari.ailus@linux.intel.com, Philipp Zabel Cc: linux-media@vger.kernel.org, devel@driverdev.osuosl.org, devicetree@vger.kernel.org, Greg Kroah-Hartman , Rui Miguel Silva Subject: [PATCH v8 09/12] ARM: dts: imx7s-warp: add ov2680 sensor node Date: Wed, 21 Nov 2018 11:15:55 +0000 Message-Id: <20181121111558.10838-10-rui.silva@linaro.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181121111558.10838-1-rui.silva@linaro.org> References: <20181121111558.10838-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 From patchwork Wed Nov 21 11:15:57 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: 151667 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp1790362ljp; Wed, 21 Nov 2018 03:16:49 -0800 (PST) X-Google-Smtp-Source: AFSGD/W1UXzNSHWHTdQPPCmNKlXYNaWflQRVaOqfk6faPLU6yDpIs+8SpVbSJbwYbjzHyOHLeb53 X-Received: by 2002:a63:451a:: with SMTP id s26mr5630431pga.150.1542799009633; Wed, 21 Nov 2018 03:16:49 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542799009; cv=none; d=google.com; s=arc-20160816; b=HkeuS/XuE4VIkIEwuPU6iuvE0Ikno+sSJEDz+oLZf1RCK0wpGyzWAAM+4U2eBkE33Z qNkS0uXFMtA5Bb0Vf0GnZ4FTI9qhXJSyvNF5OuSamTWp/e99ILQFO+oGuSk9i2R1b1bm ViC4Ws8eC1mM0+zDewbydIwQPZIxnjDOtO5PT5eCJzJEW3KTU26mKtHqvrD1rV9AiC/u KAXJsRCy66KZsUIm09o3IGbBQPKdSKWFzxPnHjGOGKjGupF6Fm8eI0a/01wzPy2RmChu Hho6QUerwVL1SQwAAi25y3ORqlvIwib/Ns7eV3leQpLLqMGtu2VyPytjI/lq/7yiWm6y pxzg== 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=ZvB6ZOpx43UpNq0U+HWQj7jn07JvDA4Lf9yxtvRaR6U=; b=pyv6P6Bb9QWVoYt78TCJzTO8+c7vuKpWL+OkM0zoXzi5ytxQ9XKiy3JjLt/1k74EI/ u+504ThZb7Y61F4UlKlGtTMo9mDi2cYojwO/0eg4HEzqNL3GfERwheCiS173tgCJfXeX NXxh03QQjMWSd+/V+PUP2tI7wWPOK7sM2TDnhzjC7AMW5dpd4xn1tBc29w92q4gsKDLv eKewNltV1NzRxxU8pHzudsqWZDTwavMLJ3RkPgW/3JcSwy/MVuhnAajjfrpkMZpdWmkJ 7cgMK2aLxgFYp+hyhL9hPdFPBS2itLFYxY5ArdZd6bsjgLHTQVjusmmxbfVtlVt8HM3U IGUg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=dVJKiITy; 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 n3si9574252pfn.285.2018.11.21.03.16.49; Wed, 21 Nov 2018 03:16:49 -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=dVJKiITy; 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 S1730086AbeKUVur (ORCPT + 4 others); Wed, 21 Nov 2018 16:50:47 -0500 Received: from mail-wm1-f65.google.com ([209.85.128.65]:37726 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730077AbeKUVur (ORCPT ); Wed, 21 Nov 2018 16:50:47 -0500 Received: by mail-wm1-f65.google.com with SMTP id p2-v6so5324141wmc.2 for ; Wed, 21 Nov 2018 03:16:47 -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=ZvB6ZOpx43UpNq0U+HWQj7jn07JvDA4Lf9yxtvRaR6U=; b=dVJKiITyiSKV3DhMrOGldnYw5VJBi7QfE8Aanc022lT7RnhTK7LpnKMwALf5y6gi+k qGmzIZP3HaoVbegHayYCaqRe8iyj2G0ZZI0Ugfszs1DhrpWm+ae7yu41TYi8udV1f8Jd JdOv0fvB4nMcKEXTptzohrza9Ly/7gp/KEnzg= 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=ZvB6ZOpx43UpNq0U+HWQj7jn07JvDA4Lf9yxtvRaR6U=; b=sFPjZPmamhJRvgMe/Sd+LoxFsTUItsVMl1cdvqp4+hkPTXkHY5lZIEawO5GEyleVjM 9znFyOyp05EaSLRXEo8gSmQc/wHwHFy6vkqGlmemGYmh4/URA5jtKD8yPNHrrpHJeier 84iAw4f6WxNznyaogyxTWxj/kUCsXQJh2NG07hAi3nSu/gDyk1NCpIlIzj6mtU+wl5ue cAL7IQFw3L5EjRkj1LWmjRFhWQpyaFUlpr7LP/biztycyY4mu1YfMG7DNdZg7rOn6hL1 UezoamwL5MBSfe4BZiKMVnkgW0Xhp2DmALWxZSyfu/4IFp/7PBx0IcrHq7M/8BGetG2p TA9w== X-Gm-Message-State: AA+aEWa/8qK51l8L58CkzknkYABtH8e5Sx2AX6ISKAFNCOGepUni2Npf TcoBSr/mKB+JU+AYkrP6i8XDSA== X-Received: by 2002:a1c:6783:: with SMTP id b125-v6mr5331185wmc.147.1542799006574; Wed, 21 Nov 2018 03:16:46 -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 a125-v6sm771526wmf.8.2018.11.21.03.16.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 21 Nov 2018 03:16:46 -0800 (PST) From: Rui Miguel Silva To: sakari.ailus@linux.intel.com, Philipp Zabel Cc: linux-media@vger.kernel.org, devel@driverdev.osuosl.org, devicetree@vger.kernel.org, Greg Kroah-Hartman , Rui Miguel Silva Subject: [PATCH v8 11/12] media: staging/imx: add i.MX7 entries to TODO file Date: Wed, 21 Nov 2018 11:15:57 +0000 Message-Id: <20181121111558.10838-12-rui.silva@linaro.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181121111558.10838-1-rui.silva@linaro.org> References: <20181121111558.10838-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 some i.MX7 related entries to TODO file. Signed-off-by: Rui Miguel Silva --- drivers/staging/media/imx/TODO | 9 +++++++++ 1 file changed, 9 insertions(+) -- 2.19.1 diff --git a/drivers/staging/media/imx/TODO b/drivers/staging/media/imx/TODO index aeeb15494a49..6f29b5ca5324 100644 --- a/drivers/staging/media/imx/TODO +++ b/drivers/staging/media/imx/TODO @@ -45,3 +45,12 @@ Which means a port must not contain mixed-use endpoints, they must all refer to media links between V4L2 subdevices. + +- i.MX7: all of the above, since it uses the imx media core + +- i.MX7: use Frame Interval Monitor + +- i.MX7: runtime testing with parallel sensor, links setup and streaming + +- i.MX7: runtime testing with different formats, for the time only 10-bit bayer + is tested From patchwork Wed Nov 21 11:15:58 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: 151668 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp1790389ljp; Wed, 21 Nov 2018 03:16:52 -0800 (PST) X-Google-Smtp-Source: AFSGD/UjDzEATT6hIL7UagmpHeEpiLS1q0vIEjtDq/CZl9mSkcRO55P518MVXrsA+9i4UblAMc5E X-Received: by 2002:a63:d846:: with SMTP id k6mr5685919pgj.251.1542799011597; Wed, 21 Nov 2018 03:16:51 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542799011; cv=none; d=google.com; s=arc-20160816; b=wPhahgYsVr9NxL2f9X8WHLPB5qhHQ9qoTPDPsyj5tMm00KplY/Tc+lsU87WYcOXNjJ lkSTNGsrXX3oqS7Qr/RAozS1x/q9VtAX/sSPfrQcIvRdWQRDr5nvSY2k8AK91repZgsK Xy7vVtzfwUInYgcF40TCAK9NP+uWOZ4f8hmXAps2y43uI8B49zNRLKIUf4RQdwdRdx7+ h00ucCKj69J+0akLPrFGeYnHB7Jh6Vmg5Vi495+Z0LJr85YAi4UWMOaI6Qn7zEozTWaS TgzEAkCTlqAIqmdT/28C2taBVlJSnBxSrvD3pZ9FT3IdPtQFwfAhEfNkh9vz1coNfTO8 cSzg== 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=SDll1pv1EukuhR1AIqusnkMzOSkhoq3sWKTbeNmkFOY=; b=Lhd7pHGa97cdjaXLEKcO51cj2vbLHGtal2Zm9IxXSBAe4AT2Uq1Aj54Vzeg/rMx9v0 BEeXDdQ6MMymkhkTh0kB3mm3tyzgaLHAIPFmC0Dwt4VzMVcvgaAqTOGNej2NX6QZu27n HviRs5d6ct7IhzHmpaAtmz39FOwiPupxvEF+p6L5Q9kayxCHbAvjdUvn52gt1t2cmw4Q 6edA3Vfy7DUB9AA4z6xZrTSdzsSW6fBUi1QjZDKsxvz8vSgqDnafcujFL6JEAf45MmvJ o+juOt80odt2GXvBNLtd9xXe+JKw0AiNz0a4HC+lU/YsNs3ZvGfDx2tOB9pKpQprEZku IC/A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=D+OBMiVh; 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 n3si9574252pfn.285.2018.11.21.03.16.51; Wed, 21 Nov 2018 03:16:51 -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=D+OBMiVh; 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 S1730089AbeKUVut (ORCPT + 4 others); Wed, 21 Nov 2018 16:50:49 -0500 Received: from mail-wm1-f68.google.com ([209.85.128.68]:37730 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730087AbeKUVut (ORCPT ); Wed, 21 Nov 2018 16:50:49 -0500 Received: by mail-wm1-f68.google.com with SMTP id p2-v6so5324221wmc.2 for ; Wed, 21 Nov 2018 03:16:49 -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=SDll1pv1EukuhR1AIqusnkMzOSkhoq3sWKTbeNmkFOY=; b=D+OBMiVhql7Rw2IOxTbJHaSRFPDjnDh5eGVL1IUDoYNBZ/HxJJhRDcfO9igLMr8WPd XfEpnCYogLvXVaOcMnexGyOP06FnotVv4AP2SyCGK9r75MJfBfJb7QihvMmx9GhR9dli qfNU85t9qoWcwfx7tZojZkO68M/jGQMHJG/6U= 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=SDll1pv1EukuhR1AIqusnkMzOSkhoq3sWKTbeNmkFOY=; b=jZH+hyl5qLDGCUjYRf8l+1b7JMrnuB6V8IBf9X/mSsPNM8q0ESOwbecMBd53wWUasd uzWeuZ9tgsXTGuSB8O3IkEb/bExUzvX9lyH962lNIShrMhDL+jXyKkVcKeFSICCFkqst JpPE/edRwNV5zkT+IjqAhgxST195zjbokkLuRc1ZDbTB6RRaZGkDSyVrYMy4duUwZ0+e wYURphl13nBnU7IlNnjkfbgvsfcRd+sPnp3MMTcoV0D+T/h93vf0eTvZWfqz4ZygxX2J S1FF4TPA5zCBh3Elo8eyl4CtsOLKDdpydzK5jJCIcLcwkbjuJJVf7/3CcGQJUhIrbV2C 1R2w== X-Gm-Message-State: AGRZ1gL/MkuVfoe9dfaAGszsGObFxde4dvuqI5h+aGbjyrCNDo5WKzU/ CiyPF/TIkVKXwbm/lTb2q3k7VQ== X-Received: by 2002:a1c:87cc:: with SMTP id j195mr5352577wmd.2.1542799008386; Wed, 21 Nov 2018 03:16:48 -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 a125-v6sm771526wmf.8.2018.11.21.03.16.47 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 21 Nov 2018 03:16:48 -0800 (PST) From: Rui Miguel Silva To: sakari.ailus@linux.intel.com, Philipp Zabel Cc: linux-media@vger.kernel.org, devel@driverdev.osuosl.org, devicetree@vger.kernel.org, Greg Kroah-Hartman , Rui Miguel Silva Subject: [PATCH v8 12/12] media: video-mux: add bayer formats Date: Wed, 21 Nov 2018 11:15:58 +0000 Message-Id: <20181121111558.10838-13-rui.silva@linaro.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181121111558.10838-1-rui.silva@linaro.org> References: <20181121111558.10838-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 non vendor bayer formats to the allowed format array. Signed-off-by: Rui Miguel Silva --- drivers/media/platform/video-mux.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) -- 2.19.1 diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c index c33900e3c23e..0ba30756e1e4 100644 --- a/drivers/media/platform/video-mux.c +++ b/drivers/media/platform/video-mux.c @@ -263,6 +263,26 @@ static int video_mux_set_format(struct v4l2_subdev *sd, case MEDIA_BUS_FMT_UYYVYY16_0_5X48: case MEDIA_BUS_FMT_JPEG_1X8: case MEDIA_BUS_FMT_AHSV8888_1X32: + case MEDIA_BUS_FMT_SBGGR8_1X8: + case MEDIA_BUS_FMT_SGBRG8_1X8: + case MEDIA_BUS_FMT_SGRBG8_1X8: + case MEDIA_BUS_FMT_SRGGB8_1X8: + case MEDIA_BUS_FMT_SBGGR10_1X10: + case MEDIA_BUS_FMT_SGBRG10_1X10: + case MEDIA_BUS_FMT_SGRBG10_1X10: + case MEDIA_BUS_FMT_SRGGB10_1X10: + case MEDIA_BUS_FMT_SBGGR12_1X12: + case MEDIA_BUS_FMT_SGBRG12_1X12: + case MEDIA_BUS_FMT_SGRBG12_1X12: + case MEDIA_BUS_FMT_SRGGB12_1X12: + case MEDIA_BUS_FMT_SBGGR14_1X14: + case MEDIA_BUS_FMT_SGBRG14_1X14: + case MEDIA_BUS_FMT_SGRBG14_1X14: + case MEDIA_BUS_FMT_SRGGB14_1X14: + case MEDIA_BUS_FMT_SBGGR16_1X16: + case MEDIA_BUS_FMT_SGBRG16_1X16: + case MEDIA_BUS_FMT_SGRBG16_1X16: + case MEDIA_BUS_FMT_SRGGB16_1X16: break; default: sdformat->format.code = MEDIA_BUS_FMT_Y8_1X8;